first commit
This commit is contained in:
2
calcom/packages/embeds/embed-react/.gitignore
vendored
Normal file
2
calcom/packages/embeds/embed-react/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.turbo
|
||||
dist
|
||||
91
calcom/packages/embeds/embed-react/CHANGELOG.md
Normal file
91
calcom/packages/embeds/embed-react/CHANGELOG.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# @calcom/embed-react
|
||||
|
||||
## 1.5.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- Added namespacing support throughout
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @calcom/embed-core@1.5.0
|
||||
- @calcom/embed-snippet@1.3.0
|
||||
|
||||
## 1.4.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- Added a few more events
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @calcom/embed-core@1.4.0
|
||||
- @calcom/embed-snippet@1.2.0
|
||||
|
||||
## 1.3.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- Fix module import of the embed-react package
|
||||
|
||||
## 1.2.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Improve UI instruction layout typings
|
||||
- Updated dependencies
|
||||
- @calcom/embed-snippet@1.1.2
|
||||
- @calcom/embed-core@1.3.2
|
||||
|
||||
## 1.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- layout type fix as zod-utils can't be used in npm package
|
||||
- Updated dependencies
|
||||
- @calcom/embed-snippet@1.1.1
|
||||
- @calcom/embed-core@1.3.1
|
||||
|
||||
## 1.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- Supports new booker layout
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @calcom/embed-core@1.3.0
|
||||
- @calcom/embed-snippet@1.1.0
|
||||
|
||||
## 1.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Fix the build for embed-react
|
||||
- Updated dependencies
|
||||
- @calcom/embed-snippet@1.0.9
|
||||
- @calcom/embed-core@1.2.1
|
||||
|
||||
## 1.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- Fix missing types for @calcom/embed-react. Also, release support for floatingButton config parameter. Though the support is available using embed.js already, for users using getCalApi the TypeScript types would report that config isn't supported.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @calcom/embed-core@1.2.0
|
||||
- @calcom/embed-snippet@1.0.8
|
||||
|
||||
## 1.0.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Add changesets. Use prepack instead of prePublish and prepublish only as that works with both yarn and npm
|
||||
- Updated dependencies
|
||||
- @calcom/embed-snippet@1.0.7
|
||||
- @calcom/embed-core@1.1.5
|
||||
42
calcom/packages/embeds/embed-react/LICENSE
Normal file
42
calcom/packages/embeds/embed-react/LICENSE
Normal file
@@ -0,0 +1,42 @@
|
||||
The Cal.com Commercial License (EE) license (the “EE License”)
|
||||
Copyright (c) 2020-present Cal.com, Inc
|
||||
|
||||
With regard to the Cal.com Software:
|
||||
|
||||
This software and associated documentation files (the "Software") may only be
|
||||
used in production, if you (and any entity that you represent) have agreed to,
|
||||
and are in compliance with, the Cal.com Subscription Terms available
|
||||
at https://cal.com/terms (the “EE Terms”), or other agreements governing
|
||||
the use of the Software, as mutually agreed by you and Cal.com, Inc ("Cal.com"),
|
||||
and otherwise have a valid Cal.com Commercial License subscription ("EE Subscription")
|
||||
for the correct number of hosts as defined in the EE Terms ("Hosts"). Subject to the foregoing sentence,
|
||||
you are free to modify this Software and publish patches to the Software. You agree
|
||||
that Cal.com and/or its licensors (as applicable) retain all right, title and interest in
|
||||
and to all such modifications and/or patches, and all such modifications and/or
|
||||
patches may only be used, copied, modified, displayed, distributed, or otherwise
|
||||
exploited with a valid EE Subscription for the correct number of hosts.
|
||||
Notwithstanding the foregoing, you may copy and modify the Software for development
|
||||
and testing purposes, without requiring a subscription. You agree that Cal.com and/or
|
||||
its licensors (as applicable) retain all right, title and interest in and to all such
|
||||
modifications. You are not granted any other rights beyond what is expressly stated herein.
|
||||
Subject to the foregoing, it is forbidden to copy, merge, publish, distribute, sublicense,
|
||||
and/or sell the Software.
|
||||
|
||||
This EE License applies only to the part of this Software that is not distributed under
|
||||
the AGPLv3 license. Any part of this Software distributed under the AGPLv3 license or which
|
||||
is served client-side as an image, font, cascading stylesheet (CSS), file which produces
|
||||
or is compiled, arranged, augmented, or combined into client-side JavaScript, in whole or
|
||||
in part, is copyrighted under the AGPLv3 license. The full text of this EE License shall
|
||||
be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
For all third party components incorporated into the Cal.com Software, those
|
||||
components are licensed under the original license provided by the owner of the
|
||||
applicable component.
|
||||
25
calcom/packages/embeds/embed-react/README.md
Normal file
25
calcom/packages/embeds/embed-react/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# cal-react
|
||||
|
||||
Embed Cal Link as a React Component
|
||||
|
||||
To know how to use it, follow the steps at <https://developer.cal.com/embed/install-with-react>
|
||||
|
||||
## Development
|
||||
|
||||
Following command starts a hot reloading server
|
||||
`yarn dev`
|
||||
|
||||
If you are working with embed on website, don't forget to do `yarn build` after every change.
|
||||
|
||||
## Running Tests
|
||||
|
||||
Runs tests and updates the snapshots. Right now we don't care about snapshots
|
||||
`yarn embed-tests-quick --update-snapshots`
|
||||
TODO
|
||||
|
||||
- Playwright tests.
|
||||
- Need to what these tests should be as embed-core already have tests. We probably just need to verify that embed-core API is called appropriately.
|
||||
- It would probably be better if Playwright tests exist at one place for all embeds.
|
||||
- Distribution
|
||||
- It would be better DX to serve the unbuilt version with JSX, instead of built version with React.createElement calls. But because of WebPack loaders not running on node_modules automatically, it doesn't work automatically.
|
||||
- Right now if a typescript project uses the package, VSCode takes the user to .d.ts files instead of the functions definitions. How to solve it ?
|
||||
10
calcom/packages/embeds/embed-react/element-click.html
Normal file
10
calcom/packages/embeds/embed-react/element-click.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
|
||||
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
|
||||
<script type="module" src="./element-click.tsx"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
31
calcom/packages/embeds/embed-react/element-click.tsx
Normal file
31
calcom/packages/embeds/embed-react/element-click.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* @fileoverview This file is an example file and tells how to use the element-click popup embed in a React application. This is also used by playwright e2e
|
||||
*/
|
||||
import { useEffect } from "react";
|
||||
import * as React from "react";
|
||||
import ReactDom from "react-dom";
|
||||
|
||||
import { getCalApi } from "./src/index";
|
||||
|
||||
const calNamespace = "element-click";
|
||||
function App() {
|
||||
useEffect(() => {
|
||||
(async function () {
|
||||
const cal = await getCalApi({
|
||||
embedJsUrl: "http://localhost:3000/embed/embed.js",
|
||||
namespace: calNamespace,
|
||||
});
|
||||
cal("ui", { styles: { branding: { brandColor: "#000000" } }, hideEventTypeDetails: false });
|
||||
})();
|
||||
}, []);
|
||||
return (
|
||||
<button
|
||||
data-cal-namespace={calNamespace}
|
||||
data-cal-link="pro"
|
||||
data-cal-config='{"layout":"month_view", "theme":"dark"}'>
|
||||
Click me
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
ReactDom.render(<App />, document.getElementById("root"));
|
||||
11
calcom/packages/embeds/embed-react/env.d.ts
vendored
Normal file
11
calcom/packages/embeds/embed-react/env.d.ts
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
interface ImportMetaEnv {
|
||||
readonly EMBED_PUBLIC_WEBAPP_URL: string;
|
||||
readonly EMBED_PUBLIC_VERCEL_URL: string;
|
||||
readonly EMBED_PUBLIC_EMBED_LIB_URL: string;
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
readonly env: ImportMetaEnv;
|
||||
}
|
||||
10
calcom/packages/embeds/embed-react/floating.html
Normal file
10
calcom/packages/embeds/embed-react/floating.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
|
||||
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
|
||||
<script type="module" src="./floating.tsx"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
30
calcom/packages/embeds/embed-react/floating.tsx
Normal file
30
calcom/packages/embeds/embed-react/floating.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @fileoverview This file is an example file and tells how to use floating popup button in a React application. This is also used by playwright e2e
|
||||
*/
|
||||
import { useEffect } from "react";
|
||||
import * as React from "react";
|
||||
import ReactDom from "react-dom";
|
||||
|
||||
import { getCalApi } from "./src/index";
|
||||
|
||||
function App() {
|
||||
useEffect(() => {
|
||||
(async function () {
|
||||
const cal = await getCalApi({
|
||||
namespace: "floating",
|
||||
embedJsUrl: "http://localhost:3000/embed/embed.js",
|
||||
});
|
||||
cal("floatingButton", {
|
||||
calLink: "pro",
|
||||
calOrigin: "http://localhost:3000",
|
||||
config: {
|
||||
theme: "dark",
|
||||
},
|
||||
});
|
||||
cal("ui", { styles: { branding: { brandColor: "#000000" } }, hideEventTypeDetails: false });
|
||||
})();
|
||||
}, []);
|
||||
return null;
|
||||
}
|
||||
|
||||
ReactDom.render(<App />, document.getElementById("root"));
|
||||
16
calcom/packages/embeds/embed-react/index.html
Normal file
16
calcom/packages/embeds/embed-react/index.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<html>
|
||||
<body>
|
||||
<h1>Playground has following demos</h1>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="./inline.html">Inline</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="./floating.html">Floating Button Popup</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="./element-click.html">Element Click Popup</a>
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
10
calcom/packages/embeds/embed-react/inline.html
Normal file
10
calcom/packages/embeds/embed-react/inline.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
|
||||
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
|
||||
<script type="module" src="./inline.tsx"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
77
calcom/packages/embeds/embed-react/inline.tsx
Normal file
77
calcom/packages/embeds/embed-react/inline.tsx
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @fileoverview This file is an example file and tells how to use the Cal component in a React application. This is also used by playwright e2e
|
||||
*/
|
||||
import * as React from "react";
|
||||
import { useEffect } from "react";
|
||||
import { useState } from "react";
|
||||
import ReactDom from "react-dom";
|
||||
|
||||
// Because we don't import from @calcom/embed-react, this file isn't able to test if the build is successful or not and thus npm package would work or not correctly.
|
||||
// There are tests in test/built which verifiy that the types from built package are correctly generated and exported correctly.
|
||||
import Cal, { getCalApi } from "./src/index";
|
||||
|
||||
const api = getCalApi({
|
||||
namespace: "inline",
|
||||
});
|
||||
|
||||
function App() {
|
||||
const [, setLoaded] = useState(false);
|
||||
useEffect(() => {
|
||||
// Simulate state change causing config object to change, causing rerender of Cal
|
||||
setTimeout(setLoaded.bind(true), 1000);
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const callback = (event: any) => {
|
||||
console.log(event.detail);
|
||||
};
|
||||
api.then((api) => {
|
||||
api("on", {
|
||||
action: "*",
|
||||
callback,
|
||||
});
|
||||
|
||||
api("ui", {
|
||||
cssVarsPerTheme: {
|
||||
light: {
|
||||
"cal-border-booker": "red",
|
||||
"cal-border-booker-width": "20px",
|
||||
},
|
||||
dark: {
|
||||
"cal-border-booker": "red",
|
||||
"cal-border-booker-width": "5px",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
return () => {
|
||||
api.then((api) => {
|
||||
api("off", {
|
||||
action: "*",
|
||||
callback,
|
||||
});
|
||||
});
|
||||
};
|
||||
}, []);
|
||||
return (
|
||||
<>
|
||||
<h1>
|
||||
There is <code>Cal</code> component below me
|
||||
</h1>
|
||||
<Cal
|
||||
calOrigin="http://localhost:3000"
|
||||
embedJsUrl="//localhost:3000/embed/embed.js"
|
||||
namespace="inline"
|
||||
style={{ width: "100%", height: "100%", overflow: "scroll" }}
|
||||
calLink="pro"
|
||||
config={{
|
||||
name: "John Doe",
|
||||
email: "johndoe@gmail.com",
|
||||
notes: "Test Meeting",
|
||||
guests: ["janedoe@gmail.com"],
|
||||
theme: "dark",
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
ReactDom.render(<App />, document.getElementById("root"));
|
||||
60
calcom/packages/embeds/embed-react/package.json
Normal file
60
calcom/packages/embeds/embed-react/package.json
Normal file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"name": "@calcom/embed-react",
|
||||
"sideEffects": false,
|
||||
"version": "1.5.0",
|
||||
"description": "Embed Cal Link as a React Component",
|
||||
"license": "SEE LICENSE IN LICENSE",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/calcom/cal.com",
|
||||
"directory": "packages/embeds/embed-react"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "vite --port=3101 --open",
|
||||
"build": "rm -rf dist && vite build && cp ./dist/Cal.es.js ./dist/Cal.es.mjs && tsc --emitDeclarationOnly --declarationDir dist",
|
||||
"preview": "vite preview",
|
||||
"type-check": "tsc --pretty --noEmit",
|
||||
"type-check:ci": "tsc-absolute --pretty --noEmit",
|
||||
"lint": "eslint --ext .ts,.js,.tsx,.jsx ./src",
|
||||
"embed-tests": "yarn playwright test --config=./playwright/config/playwright.config.ts",
|
||||
"embed-tests-quick": "QUICK=true yarn embed-tests",
|
||||
"embed-tests-update-snapshots:ci": "yarn embed-tests-quick --update-snapshots",
|
||||
"packaged:tests": "cd test/packaged && yarn tsc --noEmit && yarn run -T test -- --packaged-embed-tests-only",
|
||||
"withEmbedPublishEnv": "NEXT_PUBLIC_EMBED_LIB_URL='https://app.cal.com/embed/embed.js' NEXT_PUBLIC_WEBAPP_URL='https://app.cal.com' yarn",
|
||||
"prepack": "yarn ../../../ lint --filter='@calcom/embed-react' && yarn withEmbedPublishEnv build && yarn packaged:tests",
|
||||
"embed-web-start": "yarn workspace @calcom/web start",
|
||||
"embed-dev": "yarn workspace @calcom/embed-react dev",
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
|
||||
},
|
||||
"main": "./dist/Cal.umd.js",
|
||||
"module": "./dist/Cal.es.mjs",
|
||||
"types": "./dist/embed-react/src/index.d.ts",
|
||||
"peerDependencies": {
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/embed-react/src/index.d.ts",
|
||||
"import": "./dist/Cal.es.mjs",
|
||||
"require": "./dist/Cal.umd.js"
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.31.2",
|
||||
"@types/react": "18.0.26",
|
||||
"@types/react-dom": "^18.0.9",
|
||||
"@vitejs/plugin-react": "^2.2.0",
|
||||
"eslint": "^8.34.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"typescript": "^4.9.4",
|
||||
"vite": "^4.5.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@calcom/embed-core": "workspace:*",
|
||||
"@calcom/embed-snippet": "workspace:*"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import { expect } from "@playwright/test";
|
||||
|
||||
import { getEmbedIframe } from "@calcom/embed-core/playwright/lib/testUtils";
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { test } from "@calcom/web/playwright/lib/fixtures";
|
||||
|
||||
test.describe("React Embed", () => {
|
||||
test.describe("Inline", () => {
|
||||
test("should verify that the iframe got created with correct URL - namespaced", async ({
|
||||
page,
|
||||
embeds,
|
||||
}) => {
|
||||
const calNamespace = "inline";
|
||||
await embeds.gotoPlayground({ url: "/inline.html", calNamespace });
|
||||
const embedIframe = await getEmbedIframe({ calNamespace, page, pathname: "/pro" });
|
||||
expect(embedIframe).toBeEmbedCalLink("", embeds.getActionFiredDetails, {
|
||||
pathname: "/pro",
|
||||
searchParams: {
|
||||
theme: "dark",
|
||||
},
|
||||
});
|
||||
// expect(await page.screenshot()).toMatchSnapshot("react-component-inline.png");
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("Floating button Popup", () => {
|
||||
test("should verify that the iframe got created with correct URL - namespaced", async ({
|
||||
page,
|
||||
embeds,
|
||||
}) => {
|
||||
const calNamespace = "floating";
|
||||
await page.waitForLoadState();
|
||||
await embeds.gotoPlayground({ url: "/floating.html", calNamespace });
|
||||
|
||||
await page.click("text=Book my Cal");
|
||||
|
||||
const embedIframe = await getEmbedIframe({ calNamespace, page, pathname: "/pro" });
|
||||
expect(embedIframe).toBeEmbedCalLink(calNamespace, embeds.getActionFiredDetails, {
|
||||
pathname: "/pro",
|
||||
searchParams: {
|
||||
theme: "dark",
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: This test is extremely flaky and has been failing a lot, blocking many PRs. Fix this.
|
||||
// eslint-disable-next-line playwright/no-skipped-test
|
||||
test.describe.skip("Element Click Popup", () => {
|
||||
test("should verify that the iframe got created with correct URL - namespaced", async ({
|
||||
page,
|
||||
embeds,
|
||||
}) => {
|
||||
const calNamespace = "element-click";
|
||||
await embeds.gotoPlayground({ url: "/element-click.html", calNamespace });
|
||||
await page.waitForLoadState();
|
||||
await page.click("text=Click me");
|
||||
|
||||
const embedIframe = await getEmbedIframe({ calNamespace, page, pathname: "/pro" });
|
||||
expect(embedIframe).toBeEmbedCalLink(calNamespace, embeds.getActionFiredDetails, {
|
||||
pathname: "/pro",
|
||||
searchParams: {
|
||||
theme: "dark",
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
64
calcom/packages/embeds/embed-react/src/Cal.tsx
Normal file
64
calcom/packages/embeds/embed-react/src/Cal.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
import type { PrefillAndIframeAttrsConfig } from "@calcom/embed-core";
|
||||
|
||||
import useEmbed from "./useEmbed";
|
||||
|
||||
type CalProps = {
|
||||
calOrigin?: string;
|
||||
calLink: string;
|
||||
initConfig?: {
|
||||
debug?: boolean;
|
||||
uiDebug?: boolean;
|
||||
};
|
||||
namespace?: string;
|
||||
config?: PrefillAndIframeAttrsConfig;
|
||||
embedJsUrl?: string;
|
||||
} & React.HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
const Cal = function Cal(props: CalProps) {
|
||||
const { calLink, calOrigin, namespace = "", config, initConfig = {}, embedJsUrl, ...restProps } = props;
|
||||
if (!calLink) {
|
||||
throw new Error("calLink is required");
|
||||
}
|
||||
const initializedRef = useRef(false);
|
||||
const Cal = useEmbed(embedJsUrl);
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
useEffect(() => {
|
||||
if (!Cal || initializedRef.current || !ref.current) {
|
||||
return;
|
||||
}
|
||||
initializedRef.current = true;
|
||||
const element = ref.current;
|
||||
if (namespace) {
|
||||
Cal("init", namespace, {
|
||||
...initConfig,
|
||||
origin: calOrigin,
|
||||
});
|
||||
Cal.ns[namespace]("inline", {
|
||||
elementOrSelector: element,
|
||||
calLink,
|
||||
config,
|
||||
});
|
||||
} else {
|
||||
Cal("init", {
|
||||
...initConfig,
|
||||
origin: calOrigin,
|
||||
});
|
||||
Cal("inline", {
|
||||
elementOrSelector: element,
|
||||
calLink,
|
||||
config,
|
||||
});
|
||||
}
|
||||
}, [Cal, calLink, config, namespace, calOrigin, initConfig]);
|
||||
|
||||
if (!Cal) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <div ref={ref} {...restProps} />;
|
||||
};
|
||||
export default Cal;
|
||||
40
calcom/packages/embeds/embed-react/src/index.ts
Normal file
40
calcom/packages/embeds/embed-react/src/index.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
"use client";
|
||||
|
||||
import type { GlobalCal, GlobalCalWithoutNs } from "@calcom/embed-core";
|
||||
import EmbedSnippet from "@calcom/embed-snippet";
|
||||
|
||||
import Cal from "./Cal";
|
||||
|
||||
export function getCalApi(options?: {
|
||||
embedJsUrl?: string;
|
||||
namespace?: string;
|
||||
}): Promise<GlobalCal | GlobalCalWithoutNs>;
|
||||
export function getCalApi(embedJsUrl: string): Promise<GlobalCal | GlobalCalWithoutNs>;
|
||||
|
||||
export function getCalApi(
|
||||
optionsOrEmbedJsUrl?:
|
||||
| {
|
||||
embedJsUrl?: string;
|
||||
namespace?: string;
|
||||
}
|
||||
| string
|
||||
): Promise<GlobalCal | GlobalCalWithoutNs> {
|
||||
const options =
|
||||
typeof optionsOrEmbedJsUrl === "string" ? { embedJsUrl: optionsOrEmbedJsUrl } : optionsOrEmbedJsUrl ?? {};
|
||||
|
||||
const { namespace = "", embedJsUrl } = options;
|
||||
return new Promise(function tryReadingFromWindow(resolve) {
|
||||
const globalCal = EmbedSnippet(embedJsUrl);
|
||||
globalCal("init", namespace);
|
||||
const api = namespace ? globalCal.ns[namespace as keyof typeof globalCal.ns] : globalCal;
|
||||
if (!api) {
|
||||
setTimeout(() => {
|
||||
tryReadingFromWindow(resolve);
|
||||
}, 50);
|
||||
return;
|
||||
}
|
||||
resolve(api);
|
||||
});
|
||||
}
|
||||
|
||||
export default Cal;
|
||||
16
calcom/packages/embeds/embed-react/src/useEmbed.ts
Normal file
16
calcom/packages/embeds/embed-react/src/useEmbed.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import EmbedSnippet from "@calcom/embed-snippet";
|
||||
|
||||
export default function useEmbed(embedJsUrl?: string) {
|
||||
const [globalCal, setGlobalCal] = useState<ReturnType<typeof EmbedSnippet>>();
|
||||
useEffect(() => {
|
||||
setGlobalCal(() => {
|
||||
return EmbedSnippet(embedJsUrl);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
return globalCal;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
# Packaged
|
||||
|
||||
The tests in this file are run on the packaged code that is published to npm. The packaged code is different from the source code in atleast the following ways
|
||||
|
||||
- Not all files go to packaged code.If package.json -> files field is specified then only the files that are specified there would be published. So, one might accidentally miss an important file that's available otherwise.
|
||||
- The packaged code doesn't have .ts files. Those files are actually converted to .js files and .d.ts files are generated separately for TypeScript support. It allows the package to work in both TypeScript and non TypeScript environments.
|
||||
25
calcom/packages/embeds/embed-react/test/packaged/api.test.ts
Normal file
25
calcom/packages/embeds/embed-react/test/packaged/api.test.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @fileoverview
|
||||
* This file tests two things in 2 ways
|
||||
* - It is a vitest test file and thus it tests if the code executes without any error. Thus, it tests that package.json->main/module fields are correctly defined. It obviously verifies the assertions as well.
|
||||
* - It is also validates for it's types and thus verifies that @calcom/embed-react has correctly specified it's types in package.json->types field.
|
||||
*/
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
// This import may show up as an error in your IDE, but it's fine because typings are available only after embed-react is built.
|
||||
import { getCalApi } from "@calcom/embed-react";
|
||||
|
||||
const api = getCalApi();
|
||||
|
||||
test("Check that the API is available", async () => {
|
||||
expect(api).toBeDefined();
|
||||
const awaitedApi = await api;
|
||||
awaitedApi("floatingButton", {
|
||||
calLink: "free",
|
||||
config: {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error We are intentionaly testing invalid value
|
||||
layout: "wrongview",
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": "@calcom/tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"module": "ESNext",
|
||||
"target": "ES2015",
|
||||
"moduleResolution": "Node",
|
||||
"baseUrl": ".",
|
||||
"declaration": true,
|
||||
"jsx": "preserve",
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": ["**/*.ts"]
|
||||
}
|
||||
19
calcom/packages/embeds/embed-react/tsconfig.json
Normal file
19
calcom/packages/embeds/embed-react/tsconfig.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"extends": "@calcom/tsconfig/base.json",
|
||||
"compilerOptions": {
|
||||
"module": "ESNext",
|
||||
"target": "ES2015",
|
||||
"moduleResolution": "Node",
|
||||
"baseUrl": ".",
|
||||
"declaration": true,
|
||||
"jsx": "preserve",
|
||||
"outDir": "dist",
|
||||
"paths": {
|
||||
"@calcom/embed-core": ["../embed-core/src"],
|
||||
"@calcom/embed-snippet": ["../embed-snippet/src"]
|
||||
}
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx", "env.d.ts"],
|
||||
// Exclude "test" because that has `api.test.ts` which imports @calcom/embed-react which needs it to be built using this tsconfig.json first. Excluding it here prevents type-check from validating test folder
|
||||
"exclude": ["node_modules", "test"]
|
||||
}
|
||||
32
calcom/packages/embeds/embed-react/vite.config.js
Normal file
32
calcom/packages/embeds/embed-react/vite.config.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import react from "@vitejs/plugin-react";
|
||||
import path from "path";
|
||||
import { defineConfig } from "vite";
|
||||
|
||||
import viteBaseConfig from "../vite.config";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
...viteBaseConfig,
|
||||
plugins: [react()],
|
||||
build: {
|
||||
lib: {
|
||||
entry: path.resolve(__dirname, "src/index.ts"),
|
||||
name: "Cal",
|
||||
fileName: (format) => `Cal.${format}.js`,
|
||||
},
|
||||
rollupOptions: {
|
||||
// make sure to externalize deps that shouldn't be bundled
|
||||
// into your library
|
||||
external: ["react", "react-dom"],
|
||||
output: {
|
||||
exports: "named",
|
||||
// Provide global variables to use in the UMD build
|
||||
// for externalized deps
|
||||
globals: {
|
||||
react: "React",
|
||||
"react-dom": "ReactDOM",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user