2023-04-03 05:20:44 +00:00
|
|
|
import { Collapsible, CollapsibleContent } from "@radix-ui/react-collapsible";
|
2022-05-05 14:29:49 +00:00
|
|
|
import classNames from "classnames";
|
2023-05-02 18:57:01 +00:00
|
|
|
import type { TFunction } from "next-i18next";
|
2023-02-16 22:39:57 +00:00
|
|
|
import type { NextRouter } from "next/router";
|
|
|
|
import { useRouter } from "next/router";
|
|
|
|
import type { MutableRefObject, RefObject } from "react";
|
|
|
|
import { createRef, forwardRef, useRef, useState } from "react";
|
|
|
|
import type { ControlProps } from "react-select";
|
|
|
|
import { components } from "react-select";
|
2022-05-05 14:29:49 +00:00
|
|
|
|
2023-06-14 09:22:44 +00:00
|
|
|
import type { BookerLayout } from "@calcom/features/bookings/Booker/types";
|
|
|
|
import { useFlagMap } from "@calcom/features/flags/context/provider";
|
2023-06-26 15:24:19 +00:00
|
|
|
import { APP_NAME, EMBED_LIB_URL, IS_SELF_HOSTED, WEBAPP_URL } from "@calcom/lib/constants";
|
2022-05-05 14:29:49 +00:00
|
|
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
2023-06-14 09:22:44 +00:00
|
|
|
import { BookerLayouts } from "@calcom/prisma/zod-utils";
|
2022-11-23 02:55:25 +00:00
|
|
|
import {
|
|
|
|
Button,
|
|
|
|
Dialog,
|
|
|
|
DialogClose,
|
|
|
|
DialogContent,
|
|
|
|
HorizontalTabs,
|
|
|
|
Label,
|
|
|
|
showToast,
|
|
|
|
Switch,
|
|
|
|
TextArea,
|
|
|
|
TextField,
|
2023-02-17 20:27:29 +00:00
|
|
|
ColorPicker,
|
2023-05-02 18:57:01 +00:00
|
|
|
Select,
|
2022-11-23 02:55:25 +00:00
|
|
|
} from "@calcom/ui";
|
2023-04-12 15:26:31 +00:00
|
|
|
import { Code, Trello, Sun, ArrowLeft } from "@calcom/ui/components/icon";
|
2022-05-05 14:29:49 +00:00
|
|
|
|
|
|
|
type EmbedType = "inline" | "floating-popup" | "element-click";
|
2022-06-09 05:05:18 +00:00
|
|
|
type EmbedFramework = "react" | "HTML";
|
|
|
|
|
|
|
|
const enum Theme {
|
|
|
|
auto = "auto",
|
|
|
|
light = "light",
|
|
|
|
dark = "dark",
|
|
|
|
}
|
|
|
|
|
2023-06-26 15:24:19 +00:00
|
|
|
const EMBED_CAL_ORIGIN = WEBAPP_URL;
|
|
|
|
const EMBED_CAL_JS_URL = `${WEBAPP_URL}/embed/embed.js`;
|
|
|
|
|
2022-06-09 05:05:18 +00:00
|
|
|
type PreviewState = {
|
|
|
|
inline: {
|
|
|
|
width: string;
|
|
|
|
height: string;
|
|
|
|
};
|
|
|
|
theme: Theme;
|
2023-06-26 15:24:19 +00:00
|
|
|
floatingPopup: {
|
|
|
|
config?: {
|
|
|
|
layout: BookerLayouts;
|
|
|
|
};
|
|
|
|
[key: string]: string | boolean | undefined | Record<string, string>;
|
|
|
|
};
|
2022-06-09 05:05:18 +00:00
|
|
|
elementClick: Record<string, string>;
|
|
|
|
palette: {
|
|
|
|
brandColor: string;
|
|
|
|
};
|
2022-12-13 07:23:26 +00:00
|
|
|
hideEventTypeDetails: boolean;
|
2023-06-14 09:22:44 +00:00
|
|
|
layout: BookerLayouts;
|
2022-06-09 05:05:18 +00:00
|
|
|
};
|
2022-09-15 05:34:11 +00:00
|
|
|
const queryParamsForDialog = ["embedType", "embedTabName", "embedUrl"];
|
2022-05-05 14:29:49 +00:00
|
|
|
|
2022-06-09 05:05:18 +00:00
|
|
|
const getDimension = (dimension: string) => {
|
|
|
|
if (dimension.match(/^\d+$/)) {
|
|
|
|
dimension = `${dimension}%`;
|
|
|
|
}
|
|
|
|
return dimension;
|
|
|
|
};
|
|
|
|
|
2022-09-19 09:47:46 +00:00
|
|
|
const goto = (router: NextRouter, searchParams: Record<string, string>) => {
|
|
|
|
const newQuery = new URLSearchParams(router.asPath.split("?")[1]);
|
|
|
|
Object.keys(searchParams).forEach((key) => {
|
|
|
|
newQuery.set(key, searchParams[key]);
|
|
|
|
});
|
|
|
|
router.push(`${router.asPath.split("?")[0]}?${newQuery.toString()}`, undefined, {
|
|
|
|
shallow: true,
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
const removeQueryParams = (router: NextRouter, queryParams: string[]) => {
|
2022-11-09 15:57:23 +00:00
|
|
|
const params = new URLSearchParams(window.location.search);
|
|
|
|
|
2022-09-19 09:47:46 +00:00
|
|
|
queryParams.forEach((param) => {
|
2022-11-09 15:57:23 +00:00
|
|
|
params.delete(param);
|
2022-09-19 09:47:46 +00:00
|
|
|
});
|
2022-11-09 15:57:23 +00:00
|
|
|
|
|
|
|
router.push(`${router.asPath.split("?")[0]}?${params.toString()}`);
|
2022-09-19 09:47:46 +00:00
|
|
|
};
|
|
|
|
|
2022-06-09 05:05:18 +00:00
|
|
|
/**
|
|
|
|
* It allows us to show code with certain reusable blocks indented according to the block variable placement
|
|
|
|
* So, if you add a variable ${abc} with indentation of 4 spaces, it will automatically indent all newlines in `abc` with the same indent before constructing the final string
|
|
|
|
* `A${var}C` with var = "B" -> partsWithoutBlock=['A','C'] blocksOrVariables=['B']
|
|
|
|
*/
|
|
|
|
const code = (partsWithoutBlock: TemplateStringsArray, ...blocksOrVariables: string[]) => {
|
|
|
|
const constructedCode: string[] = [];
|
|
|
|
for (let i = 0; i < partsWithoutBlock.length; i++) {
|
|
|
|
const partWithoutBlock = partsWithoutBlock[i];
|
|
|
|
// blocksOrVariables length would always be 1 less than partsWithoutBlock
|
|
|
|
// So, last item should be concatenated as is.
|
|
|
|
if (i >= blocksOrVariables.length) {
|
|
|
|
constructedCode.push(partWithoutBlock);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const block = blocksOrVariables[i];
|
|
|
|
const indentedBlock: string[] = [];
|
|
|
|
let indent = "";
|
|
|
|
block.split("\n").forEach((line) => {
|
|
|
|
indentedBlock.push(line);
|
|
|
|
});
|
|
|
|
// non-null assertion is okay because we know that we are referencing last element.
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
|
|
const indentationMatch = partWithoutBlock
|
|
|
|
.split("\n")
|
|
|
|
.at(-1)!
|
|
|
|
.match(/(^[\t ]*).*$/);
|
|
|
|
if (indentationMatch) {
|
|
|
|
indent = indentationMatch[1];
|
|
|
|
}
|
|
|
|
constructedCode.push(partWithoutBlock + indentedBlock.join("\n" + indent));
|
|
|
|
}
|
|
|
|
return constructedCode.join("");
|
|
|
|
};
|
|
|
|
|
|
|
|
const getInstructionString = ({
|
|
|
|
apiName,
|
|
|
|
instructionName,
|
|
|
|
instructionArg,
|
|
|
|
}: {
|
|
|
|
apiName: string;
|
|
|
|
instructionName: string;
|
|
|
|
instructionArg: Record<string, unknown>;
|
|
|
|
}) => {
|
|
|
|
return `${apiName}("${instructionName}", ${JSON.stringify(instructionArg)});`;
|
|
|
|
};
|
|
|
|
|
|
|
|
const getEmbedUIInstructionString = ({
|
|
|
|
apiName,
|
|
|
|
theme,
|
|
|
|
brandColor,
|
2022-12-13 07:23:26 +00:00
|
|
|
hideEventTypeDetails,
|
2023-06-14 09:22:44 +00:00
|
|
|
layout,
|
2022-06-09 05:05:18 +00:00
|
|
|
}: {
|
|
|
|
apiName: string;
|
|
|
|
theme?: string;
|
|
|
|
brandColor: string;
|
2022-12-13 07:23:26 +00:00
|
|
|
hideEventTypeDetails: boolean;
|
2023-06-14 09:22:44 +00:00
|
|
|
layout?: string;
|
2022-06-09 05:05:18 +00:00
|
|
|
}) => {
|
|
|
|
theme = theme !== "auto" ? theme : undefined;
|
|
|
|
return getInstructionString({
|
|
|
|
apiName,
|
|
|
|
instructionName: "ui",
|
|
|
|
instructionArg: {
|
|
|
|
theme,
|
|
|
|
styles: {
|
|
|
|
branding: {
|
|
|
|
brandColor,
|
|
|
|
},
|
|
|
|
},
|
2022-12-13 07:23:26 +00:00
|
|
|
hideEventTypeDetails: hideEventTypeDetails,
|
2023-06-14 09:22:44 +00:00
|
|
|
layout,
|
2022-06-09 05:05:18 +00:00
|
|
|
},
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
|
const Codes: Record<string, Record<string, (...args: any[]) => string>> = {
|
|
|
|
react: {
|
|
|
|
inline: ({
|
|
|
|
calLink,
|
|
|
|
uiInstructionCode,
|
|
|
|
previewState,
|
|
|
|
}: {
|
|
|
|
calLink: string;
|
|
|
|
uiInstructionCode: string;
|
|
|
|
previewState: PreviewState;
|
|
|
|
}) => {
|
|
|
|
const width = getDimension(previewState.inline.width);
|
|
|
|
const height = getDimension(previewState.inline.height);
|
|
|
|
return code`
|
|
|
|
import Cal, { getCalApi } from "@calcom/embed-react";
|
2023-03-28 18:17:40 +00:00
|
|
|
import { useEffect } from "react";
|
2023-06-26 15:24:19 +00:00
|
|
|
export default function MyApp() {
|
2022-06-09 05:05:18 +00:00
|
|
|
useEffect(()=>{
|
|
|
|
(async function () {
|
|
|
|
const cal = await getCalApi();
|
|
|
|
${uiInstructionCode}
|
|
|
|
})();
|
2022-07-23 00:39:50 +00:00
|
|
|
}, [])
|
2023-06-26 15:24:19 +00:00
|
|
|
return <Cal
|
|
|
|
calLink="${calLink}"
|
|
|
|
style={{width:"${width}",height:"${height}",overflow:"scroll"}}
|
|
|
|
${previewState.layout ? "config={{layout: '" + previewState.layout + "'}}" : ""}${
|
|
|
|
IS_SELF_HOSTED
|
|
|
|
? `
|
|
|
|
calOrigin="${EMBED_CAL_ORIGIN}"
|
|
|
|
calJsUrl="${EMBED_CAL_JS_URL}"`
|
|
|
|
: ""
|
|
|
|
}
|
|
|
|
/>;
|
2022-06-09 05:05:18 +00:00
|
|
|
};`;
|
|
|
|
},
|
|
|
|
"floating-popup": ({
|
|
|
|
floatingButtonArg,
|
|
|
|
uiInstructionCode,
|
|
|
|
}: {
|
|
|
|
floatingButtonArg: string;
|
|
|
|
uiInstructionCode: string;
|
|
|
|
}) => {
|
|
|
|
return code`
|
2023-06-26 15:24:19 +00:00
|
|
|
import { getCalApi } from "@calcom/embed-react";
|
2023-03-28 18:17:40 +00:00
|
|
|
import { useEffect } from "react";
|
2023-06-26 15:24:19 +00:00
|
|
|
export default function App() {
|
2022-06-09 05:05:18 +00:00
|
|
|
useEffect(()=>{
|
|
|
|
(async function () {
|
2023-06-26 15:24:19 +00:00
|
|
|
const cal = await getCalApi(${IS_SELF_HOSTED ? `"${EMBED_CAL_JS_URL}"` : ""});
|
2023-03-28 18:17:40 +00:00
|
|
|
cal("floatingButton", ${floatingButtonArg});
|
2022-06-09 05:05:18 +00:00
|
|
|
${uiInstructionCode}
|
|
|
|
})();
|
2022-07-23 00:39:50 +00:00
|
|
|
}, [])
|
2022-06-09 05:05:18 +00:00
|
|
|
};`;
|
|
|
|
},
|
2023-06-26 15:24:19 +00:00
|
|
|
"element-click": ({
|
|
|
|
calLink,
|
|
|
|
uiInstructionCode,
|
|
|
|
previewState,
|
|
|
|
}: {
|
|
|
|
calLink: string;
|
|
|
|
uiInstructionCode: string;
|
|
|
|
previewState: PreviewState;
|
|
|
|
}) => {
|
2022-06-09 05:05:18 +00:00
|
|
|
return code`
|
2023-06-26 15:24:19 +00:00
|
|
|
import { getCalApi } from "@calcom/embed-react";
|
2023-03-28 18:17:40 +00:00
|
|
|
import { useEffect } from "react";
|
2023-06-26 15:24:19 +00:00
|
|
|
export default function App() {
|
2022-06-09 05:05:18 +00:00
|
|
|
useEffect(()=>{
|
|
|
|
(async function () {
|
2023-06-26 15:24:19 +00:00
|
|
|
const cal = await getCalApi(${IS_SELF_HOSTED ? `"${EMBED_CAL_JS_URL}"` : ""});
|
2022-06-09 05:05:18 +00:00
|
|
|
${uiInstructionCode}
|
|
|
|
})();
|
2022-07-23 00:39:50 +00:00
|
|
|
}, [])
|
2023-06-26 15:24:19 +00:00
|
|
|
return <button
|
|
|
|
data-cal-link="${calLink}"${IS_SELF_HOSTED ? `\ndata-cal-origin="${EMBED_CAL_ORIGIN}"` : ""}
|
|
|
|
${`data-cal-config='${JSON.stringify({
|
|
|
|
layout: previewState.layout,
|
|
|
|
})}'`}
|
|
|
|
>Click me</button>;
|
2022-06-09 05:05:18 +00:00
|
|
|
};`;
|
|
|
|
},
|
|
|
|
},
|
|
|
|
HTML: {
|
2023-06-26 15:24:19 +00:00
|
|
|
inline: ({
|
|
|
|
calLink,
|
|
|
|
uiInstructionCode,
|
|
|
|
previewState,
|
|
|
|
}: {
|
|
|
|
calLink: string;
|
|
|
|
uiInstructionCode: string;
|
|
|
|
previewState: PreviewState;
|
|
|
|
}) => {
|
2022-06-09 05:05:18 +00:00
|
|
|
return code`Cal("inline", {
|
|
|
|
elementOrSelector:"#my-cal-inline",
|
2023-06-26 15:24:19 +00:00
|
|
|
calLink: "${calLink}",
|
|
|
|
layout: "${previewState.layout}"
|
2022-06-09 05:05:18 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
${uiInstructionCode}`;
|
|
|
|
},
|
|
|
|
|
|
|
|
"floating-popup": ({
|
|
|
|
floatingButtonArg,
|
|
|
|
uiInstructionCode,
|
|
|
|
}: {
|
|
|
|
floatingButtonArg: string;
|
|
|
|
uiInstructionCode: string;
|
|
|
|
}) => {
|
|
|
|
return code`Cal("floatingButton", ${floatingButtonArg});
|
|
|
|
${uiInstructionCode}`;
|
|
|
|
},
|
2023-06-26 15:24:19 +00:00
|
|
|
"element-click": ({
|
|
|
|
calLink,
|
|
|
|
uiInstructionCode,
|
|
|
|
previewState,
|
|
|
|
}: {
|
|
|
|
calLink: string;
|
|
|
|
uiInstructionCode: string;
|
|
|
|
previewState: PreviewState;
|
|
|
|
}) => {
|
|
|
|
return code`
|
|
|
|
// Important: Please add following attributes to the element you want to open Cal on click
|
|
|
|
// \`data-cal-link="${calLink}"\`
|
|
|
|
// \`data-cal-config='${JSON.stringify({
|
|
|
|
layout: previewState.layout,
|
|
|
|
})}'\`
|
|
|
|
|
2022-06-09 05:05:18 +00:00
|
|
|
${uiInstructionCode}`;
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
const getEmbedTypeSpecificString = ({
|
|
|
|
embedFramework,
|
|
|
|
embedType,
|
|
|
|
calLink,
|
|
|
|
previewState,
|
|
|
|
}: {
|
|
|
|
embedFramework: EmbedFramework;
|
|
|
|
embedType: EmbedType;
|
|
|
|
calLink: string;
|
|
|
|
previewState: PreviewState;
|
|
|
|
}) => {
|
|
|
|
const frameworkCodes = Codes[embedFramework];
|
|
|
|
if (!frameworkCodes) {
|
|
|
|
throw new Error(`No code available for the framework:${embedFramework}`);
|
|
|
|
}
|
2022-08-24 20:18:42 +00:00
|
|
|
let uiInstructionStringArg: {
|
|
|
|
apiName: string;
|
|
|
|
theme: PreviewState["theme"];
|
|
|
|
brandColor: string;
|
2022-12-13 07:23:26 +00:00
|
|
|
hideEventTypeDetails: boolean;
|
2023-06-14 09:22:44 +00:00
|
|
|
layout?: BookerLayout;
|
2022-08-24 20:18:42 +00:00
|
|
|
};
|
2022-06-09 05:05:18 +00:00
|
|
|
if (embedFramework === "react") {
|
|
|
|
uiInstructionStringArg = {
|
|
|
|
apiName: "cal",
|
|
|
|
theme: previewState.theme,
|
|
|
|
brandColor: previewState.palette.brandColor,
|
2022-12-13 07:23:26 +00:00
|
|
|
hideEventTypeDetails: previewState.hideEventTypeDetails,
|
2023-06-14 09:22:44 +00:00
|
|
|
layout: previewState.layout,
|
2022-06-09 05:05:18 +00:00
|
|
|
};
|
|
|
|
} else {
|
|
|
|
uiInstructionStringArg = {
|
|
|
|
apiName: "Cal",
|
|
|
|
theme: previewState.theme,
|
|
|
|
brandColor: previewState.palette.brandColor,
|
2022-12-13 07:23:26 +00:00
|
|
|
hideEventTypeDetails: previewState.hideEventTypeDetails,
|
2023-06-14 09:22:44 +00:00
|
|
|
layout: previewState.layout,
|
2022-06-09 05:05:18 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
if (!frameworkCodes[embedType]) {
|
|
|
|
throw new Error(`Code not available for framework:${embedFramework} and embedType:${embedType}`);
|
|
|
|
}
|
|
|
|
if (embedType === "inline") {
|
|
|
|
return frameworkCodes[embedType]({
|
|
|
|
calLink,
|
|
|
|
uiInstructionCode: getEmbedUIInstructionString(uiInstructionStringArg),
|
|
|
|
previewState,
|
|
|
|
});
|
|
|
|
} else if (embedType === "floating-popup") {
|
|
|
|
const floatingButtonArg = {
|
|
|
|
calLink,
|
2023-06-26 15:24:19 +00:00
|
|
|
...(IS_SELF_HOSTED ? { calOrigin: EMBED_CAL_ORIGIN } : null),
|
2022-06-09 05:05:18 +00:00
|
|
|
...previewState.floatingPopup,
|
|
|
|
};
|
|
|
|
return frameworkCodes[embedType]({
|
|
|
|
floatingButtonArg: JSON.stringify(floatingButtonArg),
|
|
|
|
uiInstructionCode: getEmbedUIInstructionString(uiInstructionStringArg),
|
|
|
|
previewState,
|
|
|
|
});
|
|
|
|
} else if (embedType === "element-click") {
|
|
|
|
return frameworkCodes[embedType]({
|
|
|
|
calLink,
|
|
|
|
uiInstructionCode: getEmbedUIInstructionString(uiInstructionStringArg),
|
|
|
|
previewState,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
};
|
|
|
|
|
2023-05-02 18:57:01 +00:00
|
|
|
const embeds = (t: TFunction) =>
|
|
|
|
(() => {
|
|
|
|
return [
|
|
|
|
{
|
|
|
|
title: t("inline_embed"),
|
|
|
|
subtitle: t("load_inline_content"),
|
|
|
|
type: "inline",
|
|
|
|
illustration: (
|
|
|
|
<svg
|
|
|
|
width="100%"
|
|
|
|
height="100%"
|
|
|
|
className="rounded-md"
|
|
|
|
viewBox="0 0 308 265"
|
|
|
|
fill="none"
|
|
|
|
xmlns="http://www.w3.org/2000/svg">
|
|
|
|
<path
|
|
|
|
d="M0 1.99999C0 0.895423 0.895431 0 2 0H306C307.105 0 308 0.895431 308 2V263C308 264.105 307.105 265 306 265H2C0.895431 265 0 264.105 0 263V1.99999Z"
|
|
|
|
fill="white"
|
|
|
|
/>
|
|
|
|
<rect x="24" width="260" height="38.5" rx="6" fill="#F3F4F6" />
|
|
|
|
<rect x="24.5" y="51" width="139" height="163" rx="1.5" fill="#F8F8F8" />
|
|
|
|
<rect opacity="0.8" x="48" y="74.5" width="80" height="8" rx="6" fill="#F3F4F6" />
|
|
|
|
<rect x="48" y="86.5" width="48" height="4" rx="6" fill="#F3F4F6" />
|
|
|
|
<rect x="49" y="99.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="61" y="99.5" width="6" height="6" rx="1" fill="#3E3E3E" />
|
|
|
|
<rect x="73" y="99.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="85" y="99.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="97" y="99.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="109" y="99.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="121" y="99.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="133" y="99.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="85" y="113.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="97" y="113.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="109" y="113.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="121" y="113.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="133" y="113.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="49" y="125.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="61" y="125.5" width="6" height="6" rx="1" fill="#3E3E3E" />
|
|
|
|
<path
|
|
|
|
d="M61 124.5H67V122.5H61V124.5ZM68 125.5V131.5H70V125.5H68ZM67 132.5H61V134.5H67V132.5ZM60 131.5V125.5H58V131.5H60ZM61 132.5C60.4477 132.5 60 132.052 60 131.5H58C58 133.157 59.3431 134.5 61 134.5V132.5ZM68 131.5C68 132.052 67.5523 132.5 67 132.5V134.5C68.6569 134.5 70 133.157 70 131.5H68ZM67 124.5C67.5523 124.5 68 124.948 68 125.5H70C70 123.843 68.6569 122.5 67 122.5V124.5ZM61 122.5C59.3431 122.5 58 123.843 58 125.5H60C60 124.948 60.4477 124.5 61 124.5V122.5Z"
|
|
|
|
fill="#3E3E3E"
|
|
|
|
/>
|
|
|
|
<rect x="73" y="125.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="85" y="125.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="97" y="125.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="109" y="125.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="121" y="125.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="133" y="125.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="49" y="137.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="61" y="137.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="73" y="137.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="85" y="137.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="97" y="137.5" width="6" height="6" rx="1" fill="#3E3E3E" />
|
|
|
|
<rect x="109" y="137.5" width="6" height="6" rx="1" fill="#3E3E3E" />
|
|
|
|
<rect x="121" y="137.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="133" y="137.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="49" y="149.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="61" y="149.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="73" y="149.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="85" y="149.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="97" y="149.5" width="6" height="6" rx="1" fill="#3E3E3E" />
|
|
|
|
<rect x="109" y="149.5" width="6" height="6" rx="1" fill="#3E3E3E" />
|
|
|
|
<rect x="121" y="149.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="133" y="149.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="49" y="161.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="61" y="161.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="73" y="161.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="85" y="161.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="97" y="161.5" width="6" height="6" rx="1" fill="#3E3E3E" />
|
|
|
|
<rect x="109" y="161.5" width="6" height="6" rx="1" fill="#C6C6C6" />
|
|
|
|
<rect x="24.5" y="51" width="139" height="163" rx="6" stroke="#292929" />
|
|
|
|
<rect x="176" y="50.5" width="108" height="164" rx="6" fill="#F3F4F6" />
|
|
|
|
<rect x="24" y="226.5" width="260" height="38.5" rx="6" fill="#F3F4F6" />
|
|
|
|
</svg>
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
title: t("floating_pop_up_button"),
|
|
|
|
subtitle: t("floating_button_trigger_modal"),
|
|
|
|
type: "floating-popup",
|
|
|
|
illustration: (
|
|
|
|
<svg
|
|
|
|
width="100%"
|
|
|
|
height="100%"
|
|
|
|
className="rounded-md"
|
|
|
|
viewBox="0 0 308 265"
|
|
|
|
fill="none"
|
|
|
|
xmlns="http://www.w3.org/2000/svg">
|
|
|
|
<path
|
|
|
|
d="M0 1.99999C0 0.895423 0.895431 0 2 0H306C307.105 0 308 0.895431 308 2V263C308 264.105 307.105 265 306 265H2C0.895431 265 0 264.105 0 263V1.99999Z"
|
|
|
|
fill="white"
|
|
|
|
/>
|
|
|
|
<rect x="24" width="260" height="38.5" rx="6" fill="#F3F4F6" />
|
|
|
|
<rect x="24" y="50.5" width="120" height="76" rx="6" fill="#F3F4F6" />
|
|
|
|
<rect x="24" y="138.5" width="120" height="76" rx="6" fill="#F3F4F6" />
|
|
|
|
<rect x="156" y="50.5" width="128" height="164" rx="6" fill="#F3F4F6" />
|
|
|
|
<rect x="24" y="226.5" width="260" height="38.5" rx="6" fill="#F3F4F6" />
|
|
|
|
<rect x="226" y="223.5" width="66" height="26" rx="6" fill="#292929" />
|
|
|
|
<rect x="242" y="235.5" width="34" height="2" rx="1" fill="white" />
|
|
|
|
</svg>
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
title: t("pop_up_element_click"),
|
|
|
|
subtitle: t("open_dialog_with_element_click"),
|
|
|
|
type: "element-click",
|
|
|
|
illustration: (
|
|
|
|
<svg
|
|
|
|
width="100%"
|
|
|
|
height="100%"
|
|
|
|
className="rounded-md"
|
|
|
|
viewBox="0 0 308 265"
|
|
|
|
fill="none"
|
|
|
|
xmlns="http://www.w3.org/2000/svg">
|
|
|
|
<path
|
|
|
|
d="M0 1.99999C0 0.895423 0.895431 0 2 0H306C307.105 0 308 0.895431 308 2V263C308 264.105 307.105 265 306 265H2C0.895431 265 0 264.105 0 263V1.99999Z"
|
|
|
|
fill="white"
|
|
|
|
/>
|
|
|
|
<rect x="24" y="0.50293" width="260" height="24" rx="6" fill="#F3F4F6" />
|
|
|
|
<rect x="24" y="35" width="259" height="192" rx="5.5" fill="#F9FAFB" />
|
|
|
|
<g filter="url(#filter0_i_3223_14162)">
|
|
|
|
<rect opacity="0.8" x="40" y="99" width="24" height="24" rx="2" fill="#E5E7EB" />
|
|
|
|
<rect x="40" y="127" width="48" height="8" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="40" y="139" width="82" height="8" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="40" y="151" width="34" height="4" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="40" y="159" width="34" height="4" rx="1" fill="#E5E7EB" />
|
|
|
|
</g>
|
|
|
|
<rect x="152" y="48" width="2" height="169" rx="2" fill="#E5E7EB" />
|
|
|
|
|
|
|
|
<rect opacity="0.8" x="176" y="84" width="80" height="8" rx="2" fill="#E5E7EB" />
|
|
|
|
<rect x="176" y="96" width="48" height="4" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="177" y="109" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="189" y="109" width="6" height="6" rx="1" fill="#0D121D" />
|
|
|
|
<rect x="201" y="109" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="213" y="109" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="225" y="109" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="237" y="109" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="249" y="109" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="261" y="109" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="213" y="123" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="225" y="123" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="237" y="123" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="249" y="123" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="261" y="123" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="177" y="135" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="189" y="135" width="6" height="6" rx="1" fill="#0D121D" />
|
|
|
|
<rect x="187.3" y="133.4" width="9" height="9" rx="1.5" stroke="#0D121D" />
|
|
|
|
<rect x="201" y="135" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="213" y="135" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="225" y="135" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="237" y="135" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="249" y="135" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="261" y="135" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="177" y="147" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="189" y="147" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="201" y="147" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="213" y="147" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="225" y="147" width="6" height="6" rx="1" fill="#0D121D" />
|
|
|
|
<rect x="237" y="147" width="6" height="6" rx="1" fill="#0D121D" />
|
|
|
|
<rect x="249" y="147" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="261" y="147" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="177" y="159" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="189" y="159" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="201" y="159" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="213" y="159" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="225" y="159" width="6" height="6" rx="1" fill="#0D121D" />
|
|
|
|
<rect x="237" y="159" width="6" height="6" rx="1" fill="#0D121D" />
|
|
|
|
<rect x="249" y="159" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="261" y="159" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="177" y="171" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="189" y="171" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="201" y="171" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="213" y="171" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="225" y="171" width="6" height="6" rx="1" fill="#0D121D" />
|
|
|
|
<rect x="237" y="171" width="6" height="6" rx="1" fill="#E5E7EB" />
|
|
|
|
<rect x="24" y="35" width="259" height="192" rx="5.5" stroke="#101010" />
|
|
|
|
<rect x="24" y="241.503" width="260" height="24" rx="6" fill="#F3F4F6" />
|
|
|
|
</svg>
|
|
|
|
),
|
|
|
|
},
|
|
|
|
];
|
|
|
|
})();
|
2023-03-20 07:52:54 +00:00
|
|
|
|
2022-06-09 05:05:18 +00:00
|
|
|
const tabs = [
|
|
|
|
{
|
|
|
|
name: "HTML",
|
2022-09-18 23:14:57 +00:00
|
|
|
href: "embedTabName=embed-code",
|
2023-04-12 15:26:31 +00:00
|
|
|
icon: Code,
|
2022-06-09 05:05:18 +00:00
|
|
|
type: "code",
|
|
|
|
Component: forwardRef<
|
|
|
|
HTMLTextAreaElement | HTMLIFrameElement | null,
|
|
|
|
{ embedType: EmbedType; calLink: string; previewState: PreviewState }
|
|
|
|
>(function EmbedHtml({ embedType, calLink, previewState }, ref) {
|
|
|
|
const { t } = useLocale();
|
|
|
|
if (ref instanceof Function || !ref) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
if (ref.current && !(ref.current instanceof HTMLTextAreaElement)) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return (
|
|
|
|
<>
|
2022-06-29 08:06:36 +00:00
|
|
|
<div>
|
2023-04-05 18:14:46 +00:00
|
|
|
<small className="text-subtle flex py-4">
|
2022-11-30 21:52:56 +00:00
|
|
|
{t("place_where_cal_widget_appear", { appName: APP_NAME })}
|
|
|
|
</small>
|
2022-06-29 08:06:36 +00:00
|
|
|
</div>
|
2022-06-09 05:05:18 +00:00
|
|
|
<TextArea
|
|
|
|
data-testid="embed-code"
|
|
|
|
ref={ref as typeof ref & MutableRefObject<HTMLTextAreaElement>}
|
|
|
|
name="embed-code"
|
2023-04-05 18:14:46 +00:00
|
|
|
className="text-default bg-default selection:bg-subtle h-[calc(100%-50px)] font-mono"
|
2022-07-27 02:24:00 +00:00
|
|
|
style={{ resize: "none", overflow: "auto" }}
|
2022-06-09 05:05:18 +00:00
|
|
|
readOnly
|
|
|
|
value={
|
|
|
|
`<!-- Cal ${embedType} embed code begins -->\n` +
|
|
|
|
(embedType === "inline"
|
|
|
|
? `<div style="width:${getDimension(previewState.inline.width)};height:${getDimension(
|
|
|
|
previewState.inline.height
|
|
|
|
)};overflow:scroll" id="my-cal-inline"></div>\n`
|
|
|
|
: "") +
|
|
|
|
`<script type="text/javascript">
|
|
|
|
${getEmbedSnippetString()}
|
|
|
|
${getEmbedTypeSpecificString({ embedFramework: "HTML", embedType, calLink, previewState })}
|
|
|
|
</script>
|
|
|
|
<!-- Cal ${embedType} embed code ends -->`
|
2022-07-13 21:14:16 +00:00
|
|
|
}
|
|
|
|
/>
|
2023-05-02 18:57:01 +00:00
|
|
|
<p className="text-subtle hidden text-sm">{t("need_help_embedding")}</p>
|
2022-06-09 05:05:18 +00:00
|
|
|
</>
|
|
|
|
);
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "React",
|
2022-09-18 23:14:57 +00:00
|
|
|
href: "embedTabName=embed-react",
|
2023-04-12 15:26:31 +00:00
|
|
|
icon: Code,
|
2022-06-09 05:05:18 +00:00
|
|
|
type: "code",
|
|
|
|
Component: forwardRef<
|
|
|
|
HTMLTextAreaElement | HTMLIFrameElement | null,
|
|
|
|
{ embedType: EmbedType; calLink: string; previewState: PreviewState }
|
|
|
|
>(function EmbedReact({ embedType, calLink, previewState }, ref) {
|
|
|
|
const { t } = useLocale();
|
|
|
|
if (ref instanceof Function || !ref) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
if (ref.current && !(ref.current instanceof HTMLTextAreaElement)) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return (
|
|
|
|
<>
|
2023-04-05 18:14:46 +00:00
|
|
|
<small className="text-subtle flex py-4">{t("create_update_react_component")}</small>
|
2022-06-09 05:05:18 +00:00
|
|
|
<TextArea
|
|
|
|
data-testid="embed-react"
|
|
|
|
ref={ref as typeof ref & MutableRefObject<HTMLTextAreaElement>}
|
|
|
|
name="embed-react"
|
2023-04-05 18:14:46 +00:00
|
|
|
className="text-default bg-default selection:bg-subtle h-[calc(100%-50px)] font-mono"
|
2022-06-09 05:05:18 +00:00
|
|
|
readOnly
|
2022-07-27 02:24:00 +00:00
|
|
|
style={{ resize: "none", overflow: "auto" }}
|
2022-06-09 05:05:18 +00:00
|
|
|
value={`/* First make sure that you have installed the package */
|
|
|
|
|
|
|
|
/* If you are using yarn */
|
|
|
|
// yarn add @calcom/embed-react
|
|
|
|
|
|
|
|
/* If you are using npm */
|
|
|
|
// npm install @calcom/embed-react
|
|
|
|
${getEmbedTypeSpecificString({ embedFramework: "react", embedType, calLink, previewState })}
|
2022-07-13 21:14:16 +00:00
|
|
|
`}
|
|
|
|
/>
|
2022-06-09 05:05:18 +00:00
|
|
|
</>
|
|
|
|
);
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Preview",
|
2022-09-18 23:14:57 +00:00
|
|
|
href: "embedTabName=embed-preview",
|
2023-04-12 15:26:31 +00:00
|
|
|
icon: Trello,
|
2022-06-09 05:05:18 +00:00
|
|
|
type: "iframe",
|
|
|
|
Component: forwardRef<
|
|
|
|
HTMLIFrameElement | HTMLTextAreaElement | null,
|
2022-08-24 20:18:42 +00:00
|
|
|
{ calLink: string; embedType: EmbedType; previewState: PreviewState }
|
2022-06-09 05:05:18 +00:00
|
|
|
>(function Preview({ calLink, embedType }, ref) {
|
|
|
|
if (ref instanceof Function || !ref) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
if (ref.current && !(ref.current instanceof HTMLIFrameElement)) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return (
|
|
|
|
<iframe
|
|
|
|
ref={ref as typeof ref & MutableRefObject<HTMLIFrameElement>}
|
|
|
|
data-testid="embed-preview"
|
2023-01-20 22:04:58 +00:00
|
|
|
className="h-[100vh] border"
|
2022-06-09 05:05:18 +00:00
|
|
|
width="100%"
|
|
|
|
height="100%"
|
|
|
|
src={`${WEBAPP_URL}/embed/preview.html?embedType=${embedType}&calLink=${calLink}`}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}),
|
|
|
|
},
|
|
|
|
];
|
2022-05-05 14:29:49 +00:00
|
|
|
|
|
|
|
function getEmbedSnippetString() {
|
|
|
|
// TODO: Import this string from @calcom/embed-snippet
|
2022-06-09 05:05:18 +00:00
|
|
|
return `(function (C, A, L) { let p = function (a, ar) { a.q.push(ar); }; let d = C.document; C.Cal = C.Cal || function () { let cal = C.Cal; let ar = arguments; if (!cal.loaded) { cal.ns = {}; cal.q = cal.q || []; d.head.appendChild(d.createElement("script")).src = A; cal.loaded = true; } if (ar[0] === L) { const api = function () { p(api, arguments); }; const namespace = ar[1]; api.q = api.q || []; typeof namespace === "string" ? (cal.ns[namespace] = api) && p(api, ar) : p(cal, ar); return; } p(cal, ar); }; })(window, "${EMBED_LIB_URL}", "init");
|
2022-05-06 15:56:26 +00:00
|
|
|
Cal("init", {origin:"${WEBAPP_URL}"});
|
2022-05-05 14:29:49 +00:00
|
|
|
`;
|
|
|
|
}
|
|
|
|
|
2022-06-09 05:05:18 +00:00
|
|
|
const ThemeSelectControl = ({ children, ...props }: ControlProps<{ value: Theme; label: string }, false>) => {
|
2022-05-05 14:29:49 +00:00
|
|
|
return (
|
|
|
|
<components.Control {...props}>
|
2023-05-02 18:57:01 +00:00
|
|
|
<Sun className="text-subtle mr-2 h-4 w-4" />
|
2022-05-05 14:29:49 +00:00
|
|
|
{children}
|
|
|
|
</components.Control>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const ChooseEmbedTypesDialogContent = () => {
|
|
|
|
const { t } = useLocale();
|
|
|
|
const router = useRouter();
|
2023-06-14 09:22:44 +00:00
|
|
|
|
2022-05-05 14:29:49 +00:00
|
|
|
return (
|
2023-03-20 07:52:54 +00:00
|
|
|
<DialogContent className="rounded-lg p-10" type="creation" size="lg">
|
|
|
|
<div className="mb-2">
|
2023-04-05 18:14:46 +00:00
|
|
|
<h3 className="font-cal text-emphasis mb-2 text-2xl font-bold leading-none" id="modal-title">
|
2022-11-30 21:52:56 +00:00
|
|
|
{t("how_you_want_add_cal_site", { appName: APP_NAME })}
|
2022-05-05 14:29:49 +00:00
|
|
|
</h3>
|
|
|
|
<div>
|
2023-04-05 18:14:46 +00:00
|
|
|
<p className="text-subtle text-sm">{t("choose_ways_put_cal_site", { appName: APP_NAME })}</p>
|
2022-05-05 14:29:49 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
2023-04-05 18:14:46 +00:00
|
|
|
<div className="items-start space-y-2 md:flex md:space-y-0">
|
2023-05-02 18:57:01 +00:00
|
|
|
{embeds(t).map((embed, index) => (
|
2022-05-05 14:29:49 +00:00
|
|
|
<button
|
2023-04-05 18:14:46 +00:00
|
|
|
className="hover:bg-subtle bg-muted w-full rounded-md border border-transparent p-6 text-left hover:rounded-md ltr:mr-4 ltr:last:mr-0 rtl:ml-4 rtl:last:ml-0 lg:w-1/3"
|
2022-05-05 14:29:49 +00:00
|
|
|
key={index}
|
|
|
|
data-testid={embed.type}
|
|
|
|
onClick={() => {
|
2022-09-19 09:47:46 +00:00
|
|
|
goto(router, {
|
|
|
|
embedType: embed.type,
|
|
|
|
});
|
2022-05-05 14:29:49 +00:00
|
|
|
}}>
|
2023-04-05 18:14:46 +00:00
|
|
|
<div className="bg-default order-none box-border flex-none rounded-md border border-solid dark:bg-transparent dark:invert">
|
2022-05-05 14:29:49 +00:00
|
|
|
{embed.illustration}
|
|
|
|
</div>
|
2023-04-05 18:14:46 +00:00
|
|
|
<div className="text-emphasis mt-4 font-semibold">{embed.title}</div>
|
|
|
|
<p className="text-subtle mt-2 text-sm">{embed.subtitle}</p>
|
2022-05-05 14:29:49 +00:00
|
|
|
</button>
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
</DialogContent>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const EmbedTypeCodeAndPreviewDialogContent = ({
|
|
|
|
embedType,
|
2022-08-13 11:04:57 +00:00
|
|
|
embedUrl,
|
2022-05-05 14:29:49 +00:00
|
|
|
}: {
|
|
|
|
embedType: EmbedType;
|
2022-08-13 11:04:57 +00:00
|
|
|
embedUrl: string;
|
2022-05-05 14:29:49 +00:00
|
|
|
}) => {
|
|
|
|
const { t } = useLocale();
|
2023-03-09 18:57:59 +00:00
|
|
|
|
2022-05-05 14:29:49 +00:00
|
|
|
const router = useRouter();
|
|
|
|
const iframeRef = useRef<HTMLIFrameElement>(null);
|
2023-03-09 18:57:59 +00:00
|
|
|
const dialogContentRef = useRef<HTMLDivElement>(null);
|
2023-06-14 09:22:44 +00:00
|
|
|
const flags = useFlagMap();
|
|
|
|
const isBookerLayoutsEnabled = flags["booker-layouts"] === true;
|
2023-03-09 18:57:59 +00:00
|
|
|
|
2022-09-18 23:14:57 +00:00
|
|
|
const s = (href: string) => {
|
2022-09-19 09:47:46 +00:00
|
|
|
const searchParams = new URLSearchParams(router.asPath.split("?")[1] || "");
|
2022-09-18 23:14:57 +00:00
|
|
|
const [a, b] = href.split("=");
|
|
|
|
searchParams.set(a, b);
|
|
|
|
return `${router.asPath.split("?")[0]}?${searchParams.toString()}`;
|
|
|
|
};
|
|
|
|
const parsedTabs = tabs.map((t) => ({ ...t, href: s(t.href) }));
|
2023-02-16 22:39:57 +00:00
|
|
|
const embedCodeRefs: Record<(typeof tabs)[0]["name"], RefObject<HTMLTextAreaElement>> = {};
|
2022-06-16 11:55:49 +00:00
|
|
|
tabs
|
|
|
|
.filter((tab) => tab.type === "code")
|
|
|
|
.forEach((codeTab) => {
|
|
|
|
embedCodeRefs[codeTab.name] = createRef();
|
|
|
|
});
|
|
|
|
|
|
|
|
const refOfEmbedCodesRefs = useRef(embedCodeRefs);
|
2023-05-02 18:57:01 +00:00
|
|
|
const embed = embeds(t).find((embed) => embed.type === embedType);
|
2022-05-05 14:29:49 +00:00
|
|
|
|
|
|
|
const [isEmbedCustomizationOpen, setIsEmbedCustomizationOpen] = useState(true);
|
|
|
|
const [isBookingCustomizationOpen, setIsBookingCustomizationOpen] = useState(true);
|
2023-06-14 09:22:44 +00:00
|
|
|
const [previewState, setPreviewState] = useState<PreviewState>({
|
2022-05-05 14:29:49 +00:00
|
|
|
inline: {
|
|
|
|
width: "100%",
|
|
|
|
height: "100%",
|
|
|
|
},
|
2022-06-09 05:05:18 +00:00
|
|
|
theme: Theme.auto,
|
2023-06-26 15:24:19 +00:00
|
|
|
layout: BookerLayouts.MONTH_VIEW,
|
2022-05-05 14:29:49 +00:00
|
|
|
floatingPopup: {},
|
|
|
|
elementClick: {},
|
2022-12-13 07:23:26 +00:00
|
|
|
hideEventTypeDetails: false,
|
2022-05-05 14:29:49 +00:00
|
|
|
palette: {
|
|
|
|
brandColor: "#000000",
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const close = () => {
|
2022-09-19 09:47:46 +00:00
|
|
|
removeQueryParams(router, ["dialog", ...queryParamsForDialog]);
|
|
|
|
};
|
2022-05-05 14:29:49 +00:00
|
|
|
|
2022-09-19 09:47:46 +00:00
|
|
|
// Use embed-code as default tab
|
|
|
|
if (!router.query.embedTabName) {
|
|
|
|
goto(router, {
|
|
|
|
embedTabName: "embed-code",
|
2022-05-05 14:29:49 +00:00
|
|
|
});
|
2022-09-19 09:47:46 +00:00
|
|
|
}
|
2022-05-05 14:29:49 +00:00
|
|
|
|
2022-08-13 11:04:57 +00:00
|
|
|
if (!embed || !embedUrl) {
|
2022-05-05 14:29:49 +00:00
|
|
|
close();
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2022-08-13 11:04:57 +00:00
|
|
|
const calLink = decodeURIComponent(embedUrl);
|
2022-05-05 14:29:49 +00:00
|
|
|
|
2023-02-16 22:39:57 +00:00
|
|
|
const addToPalette = (update: (typeof previewState)["palette"]) => {
|
2022-05-05 14:29:49 +00:00
|
|
|
setPreviewState((previewState) => {
|
|
|
|
return {
|
|
|
|
...previewState,
|
|
|
|
palette: {
|
|
|
|
...previewState.palette,
|
|
|
|
...update,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2022-05-17 20:43:27 +00:00
|
|
|
const previewInstruction = (instruction: { name: string; arg: unknown }) => {
|
2022-05-05 14:29:49 +00:00
|
|
|
iframeRef.current?.contentWindow?.postMessage(
|
|
|
|
{
|
|
|
|
mode: "cal:preview",
|
|
|
|
type: "instruction",
|
|
|
|
instruction,
|
|
|
|
},
|
|
|
|
"*"
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const inlineEmbedDimensionUpdate = ({ width, height }: { width: string; height: string }) => {
|
|
|
|
iframeRef.current?.contentWindow?.postMessage(
|
|
|
|
{
|
|
|
|
mode: "cal:preview",
|
|
|
|
type: "inlineEmbedDimensionUpdate",
|
|
|
|
data: {
|
|
|
|
width: getDimension(width),
|
|
|
|
height: getDimension(height),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"*"
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
previewInstruction({
|
|
|
|
name: "ui",
|
|
|
|
arg: {
|
|
|
|
theme: previewState.theme,
|
2023-06-14 09:22:44 +00:00
|
|
|
layout: previewState.layout,
|
2023-06-26 15:24:19 +00:00
|
|
|
hideEventTypeDetails: previewState.hideEventTypeDetails,
|
2022-05-05 14:29:49 +00:00
|
|
|
styles: {
|
|
|
|
branding: {
|
|
|
|
...previewState.palette,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
if (embedType === "floating-popup") {
|
|
|
|
previewInstruction({
|
|
|
|
name: "floatingButton",
|
|
|
|
arg: {
|
|
|
|
attributes: {
|
|
|
|
id: "my-floating-button",
|
|
|
|
},
|
|
|
|
...previewState.floatingPopup,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (embedType === "inline") {
|
|
|
|
inlineEmbedDimensionUpdate({
|
|
|
|
width: previewState.inline.width,
|
|
|
|
height: previewState.inline.height,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
const ThemeOptions = [
|
2023-04-03 05:20:44 +00:00
|
|
|
{ value: Theme.auto, label: "Auto" },
|
2022-06-09 05:05:18 +00:00
|
|
|
{ value: Theme.dark, label: "Dark Theme" },
|
|
|
|
{ value: Theme.light, label: "Light Theme" },
|
2022-05-05 14:29:49 +00:00
|
|
|
];
|
|
|
|
|
2023-06-14 09:22:44 +00:00
|
|
|
const layoutOptions = [
|
|
|
|
{ value: BookerLayouts.MONTH_VIEW, label: t("bookerlayout_month_view") },
|
|
|
|
{ value: BookerLayouts.WEEK_VIEW, label: t("bookerlayout_week_view") },
|
|
|
|
{ value: BookerLayouts.COLUMN_VIEW, label: t("bookerlayout_column_view") },
|
|
|
|
];
|
|
|
|
|
2022-05-05 14:29:49 +00:00
|
|
|
const FloatingPopupPositionOptions = [
|
|
|
|
{
|
|
|
|
value: "bottom-right",
|
2023-05-02 18:57:01 +00:00
|
|
|
label: "Bottom right",
|
2022-05-05 14:29:49 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
value: "bottom-left",
|
2023-05-02 18:57:01 +00:00
|
|
|
label: "Bottom left",
|
2022-05-05 14:29:49 +00:00
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
return (
|
2023-04-03 05:20:44 +00:00
|
|
|
<DialogContent
|
|
|
|
ref={dialogContentRef}
|
|
|
|
className="rounded-lg p-0.5 sm:max-w-[80rem]"
|
|
|
|
enableOverflow
|
|
|
|
type="creation">
|
2022-05-05 14:29:49 +00:00
|
|
|
<div className="flex">
|
2023-04-05 18:14:46 +00:00
|
|
|
<div className="bg-muted flex w-1/3 flex-col p-8">
|
2023-04-03 05:20:44 +00:00
|
|
|
<h3
|
2023-04-05 18:14:46 +00:00
|
|
|
className="text-emphasis mb-2.5 flex items-center text-xl font-semibold leading-5"
|
2023-04-03 05:20:44 +00:00
|
|
|
id="modal-title">
|
2022-05-05 14:29:49 +00:00
|
|
|
<button
|
2023-04-03 05:20:44 +00:00
|
|
|
className="h-6 w-6"
|
2022-05-05 14:29:49 +00:00
|
|
|
onClick={() => {
|
2022-09-19 09:47:46 +00:00
|
|
|
removeQueryParams(router, ["embedType", "embedTabName"]);
|
2022-05-05 14:29:49 +00:00
|
|
|
}}>
|
2023-04-12 15:26:31 +00:00
|
|
|
<ArrowLeft className="mr-4 w-4" />
|
2022-05-05 14:29:49 +00:00
|
|
|
</button>
|
|
|
|
{embed.title}
|
|
|
|
</h3>
|
2023-05-02 18:57:01 +00:00
|
|
|
<h4 className="text-subtle mb-6 text-sm font-normal">{embed.subtitle}</h4>
|
2023-04-03 05:20:44 +00:00
|
|
|
<div className="flex flex-col">
|
|
|
|
<div className={classNames("font-medium", embedType === "element-click" ? "hidden" : "")}>
|
2022-11-10 13:09:19 +00:00
|
|
|
<Collapsible
|
|
|
|
open={isEmbedCustomizationOpen}
|
|
|
|
onOpenChange={() => setIsEmbedCustomizationOpen((val) => !val)}>
|
|
|
|
<CollapsibleContent className="text-sm">
|
2023-04-03 05:20:44 +00:00
|
|
|
<div className={classNames(embedType === "inline" ? "block" : "hidden")}>
|
2022-11-10 13:09:19 +00:00
|
|
|
{/*TODO: Add Auto/Fixed toggle from Figma */}
|
2023-04-05 18:14:46 +00:00
|
|
|
<div className="text-default mb-[9px] text-sm">Window sizing</div>
|
2023-05-02 18:57:01 +00:00
|
|
|
<div className="justify-left mb-6 flex items-center !font-normal ">
|
2023-04-03 05:20:44 +00:00
|
|
|
<div className="mr-[9px]">
|
|
|
|
<TextField
|
|
|
|
labelProps={{ className: "hidden" }}
|
|
|
|
className="focus:ring-offset-0"
|
|
|
|
required
|
|
|
|
value={previewState.inline.width}
|
|
|
|
onChange={(e) => {
|
|
|
|
setPreviewState((previewState) => {
|
|
|
|
const width = e.target.value || "100%";
|
|
|
|
|
|
|
|
return {
|
|
|
|
...previewState,
|
|
|
|
inline: {
|
|
|
|
...previewState.inline,
|
|
|
|
width,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}}
|
|
|
|
addOnLeading={<>W</>}
|
|
|
|
/>
|
|
|
|
</div>
|
2022-05-05 14:29:49 +00:00
|
|
|
|
2022-11-10 13:09:19 +00:00
|
|
|
<TextField
|
|
|
|
labelProps={{ className: "hidden" }}
|
2023-04-03 05:20:44 +00:00
|
|
|
className="focus:ring-offset-0"
|
2022-11-10 13:09:19 +00:00
|
|
|
value={previewState.inline.height}
|
|
|
|
required
|
|
|
|
onChange={(e) => {
|
|
|
|
const height = e.target.value || "100%";
|
|
|
|
|
|
|
|
setPreviewState((previewState) => {
|
|
|
|
return {
|
|
|
|
...previewState,
|
|
|
|
inline: {
|
|
|
|
...previewState.inline,
|
|
|
|
height,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}}
|
2023-01-31 20:58:15 +00:00
|
|
|
addOnLeading={<>H</>}
|
2022-11-10 13:09:19 +00:00
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
className={classNames(
|
2023-05-02 18:57:01 +00:00
|
|
|
"items-center justify-between",
|
2023-04-05 18:14:46 +00:00
|
|
|
embedType === "floating-popup" ? "text-emphasis" : "hidden"
|
2022-11-10 13:09:19 +00:00
|
|
|
)}>
|
2023-05-02 18:57:01 +00:00
|
|
|
<div className="mb-2 text-sm">Button text</div>
|
2022-11-10 13:09:19 +00:00
|
|
|
{/* Default Values should come from preview iframe */}
|
2022-05-05 14:29:49 +00:00
|
|
|
<TextField
|
|
|
|
labelProps={{ className: "hidden" }}
|
|
|
|
onChange={(e) => {
|
|
|
|
setPreviewState((previewState) => {
|
|
|
|
return {
|
|
|
|
...previewState,
|
2022-11-10 13:09:19 +00:00
|
|
|
floatingPopup: {
|
|
|
|
...previewState.floatingPopup,
|
|
|
|
buttonText: e.target.value,
|
2022-05-05 14:29:49 +00:00
|
|
|
},
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}}
|
2023-05-02 18:57:01 +00:00
|
|
|
defaultValue={t("book_my_cal")}
|
2022-11-10 13:09:19 +00:00
|
|
|
required
|
2022-05-05 14:29:49 +00:00
|
|
|
/>
|
|
|
|
</div>
|
2022-11-10 13:09:19 +00:00
|
|
|
<div
|
|
|
|
className={classNames(
|
|
|
|
"mt-4 flex items-center justify-start",
|
2023-04-05 18:14:46 +00:00
|
|
|
embedType === "floating-popup"
|
|
|
|
? "text-emphasis space-x-2 rtl:space-x-reverse"
|
|
|
|
: "hidden"
|
2022-11-10 13:09:19 +00:00
|
|
|
)}>
|
|
|
|
<Switch
|
|
|
|
defaultChecked={true}
|
|
|
|
onCheckedChange={(checked) => {
|
2022-05-05 14:29:49 +00:00
|
|
|
setPreviewState((previewState) => {
|
|
|
|
return {
|
|
|
|
...previewState,
|
|
|
|
floatingPopup: {
|
|
|
|
...previewState.floatingPopup,
|
2022-11-10 13:09:19 +00:00
|
|
|
hideButtonIcon: !checked,
|
2022-05-05 14:29:49 +00:00
|
|
|
},
|
|
|
|
};
|
|
|
|
});
|
2022-07-13 21:14:16 +00:00
|
|
|
}}
|
|
|
|
/>
|
2023-05-02 18:57:01 +00:00
|
|
|
<div className="text-default my-2 text-sm">Display calendar icon</div>
|
2022-05-05 14:29:49 +00:00
|
|
|
</div>
|
2022-11-10 13:09:19 +00:00
|
|
|
<div
|
|
|
|
className={classNames(
|
|
|
|
"mt-4 items-center justify-between",
|
2023-04-05 18:14:46 +00:00
|
|
|
embedType === "floating-popup" ? "text-emphasis" : "hidden"
|
2022-11-10 13:09:19 +00:00
|
|
|
)}>
|
2023-05-02 18:57:01 +00:00
|
|
|
<div className="mb-2">Position of button</div>
|
2022-11-10 13:09:19 +00:00
|
|
|
<Select
|
|
|
|
onChange={(position) => {
|
2022-05-05 14:29:49 +00:00
|
|
|
setPreviewState((previewState) => {
|
|
|
|
return {
|
|
|
|
...previewState,
|
|
|
|
floatingPopup: {
|
|
|
|
...previewState.floatingPopup,
|
2022-11-10 13:09:19 +00:00
|
|
|
buttonPosition: position?.value,
|
2022-05-05 14:29:49 +00:00
|
|
|
},
|
|
|
|
};
|
|
|
|
});
|
2022-07-13 21:14:16 +00:00
|
|
|
}}
|
2022-11-10 13:09:19 +00:00
|
|
|
defaultValue={FloatingPopupPositionOptions[0]}
|
|
|
|
options={FloatingPopupPositionOptions}
|
2022-07-13 21:14:16 +00:00
|
|
|
/>
|
2022-05-05 14:29:49 +00:00
|
|
|
</div>
|
2023-05-02 18:57:01 +00:00
|
|
|
<div className="mt-3 flex flex-col xl:flex-row xl:justify-between">
|
|
|
|
<div className={classNames("mt-4", embedType === "floating-popup" ? "" : "hidden")}>
|
|
|
|
<div className="whitespace-nowrap">Button color</div>
|
|
|
|
<div className="mt-2 w-40 xl:mt-0 xl:w-full">
|
|
|
|
<ColorPicker
|
|
|
|
className="w-[130px]"
|
|
|
|
popoverAlign="start"
|
|
|
|
container={dialogContentRef?.current ?? undefined}
|
|
|
|
defaultValue="#000000"
|
|
|
|
onChange={(color) => {
|
|
|
|
setPreviewState((previewState) => {
|
|
|
|
return {
|
|
|
|
...previewState,
|
|
|
|
floatingPopup: {
|
|
|
|
...previewState.floatingPopup,
|
|
|
|
buttonColor: color,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</div>
|
2022-11-10 13:09:19 +00:00
|
|
|
</div>
|
2023-05-02 18:57:01 +00:00
|
|
|
<div className={classNames("mt-4", embedType === "floating-popup" ? "" : "hidden")}>
|
|
|
|
<div className="whitespace-nowrap">Text color</div>
|
2023-06-22 22:25:37 +00:00
|
|
|
<div className="mb-6 mt-2 w-40 xl:mt-0 xl:w-full">
|
2023-05-02 18:57:01 +00:00
|
|
|
<ColorPicker
|
|
|
|
className="w-[130px]"
|
|
|
|
popoverAlign="start"
|
|
|
|
container={dialogContentRef?.current ?? undefined}
|
|
|
|
defaultValue="#000000"
|
|
|
|
onChange={(color) => {
|
|
|
|
setPreviewState((previewState) => {
|
|
|
|
return {
|
|
|
|
...previewState,
|
|
|
|
floatingPopup: {
|
|
|
|
...previewState.floatingPopup,
|
|
|
|
buttonTextColor: color,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</div>
|
2022-11-10 13:09:19 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</CollapsibleContent>
|
|
|
|
</Collapsible>
|
|
|
|
</div>
|
2023-04-03 05:20:44 +00:00
|
|
|
<div className="font-medium">
|
2022-11-10 13:09:19 +00:00
|
|
|
<Collapsible
|
|
|
|
open={isBookingCustomizationOpen}
|
|
|
|
onOpenChange={() => setIsBookingCustomizationOpen((val) => !val)}>
|
|
|
|
<CollapsibleContent>
|
2023-05-02 18:57:01 +00:00
|
|
|
<div className="text-sm">
|
|
|
|
<Label className="mb-6">
|
|
|
|
<div className="mb-2">Theme</div>
|
|
|
|
<Select
|
|
|
|
className="w-full"
|
|
|
|
defaultValue={ThemeOptions[0]}
|
|
|
|
components={{
|
|
|
|
Control: ThemeSelectControl,
|
|
|
|
IndicatorSeparator: () => null,
|
|
|
|
}}
|
|
|
|
onChange={(option) => {
|
|
|
|
if (!option) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
setPreviewState((previewState) => {
|
|
|
|
return {
|
|
|
|
...previewState,
|
|
|
|
theme: option.value,
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}}
|
|
|
|
options={ThemeOptions}
|
|
|
|
/>
|
|
|
|
</Label>
|
2023-04-03 05:20:44 +00:00
|
|
|
<div className="mb-6 flex items-center justify-start space-x-2 rtl:space-x-reverse">
|
2022-12-13 07:23:26 +00:00
|
|
|
<Switch
|
|
|
|
checked={previewState.hideEventTypeDetails}
|
|
|
|
onCheckedChange={(checked) => {
|
|
|
|
setPreviewState((previewState) => {
|
|
|
|
return {
|
|
|
|
...previewState,
|
|
|
|
hideEventTypeDetails: checked,
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}}
|
|
|
|
/>
|
2023-04-05 18:14:46 +00:00
|
|
|
<div className="text-default text-sm">{t("hide_eventtype_details")}</div>
|
2022-12-13 07:23:26 +00:00
|
|
|
</div>
|
2022-11-10 13:09:19 +00:00
|
|
|
{[
|
|
|
|
{ name: "brandColor", title: "Brand Color" },
|
|
|
|
// { name: "lightColor", title: "Light Color" },
|
|
|
|
// { name: "lighterColor", title: "Lighter Color" },
|
|
|
|
// { name: "lightestColor", title: "Lightest Color" },
|
|
|
|
// { name: "highlightColor", title: "Highlight Color" },
|
|
|
|
// { name: "medianColor", title: "Median Color" },
|
|
|
|
].map((palette) => (
|
2023-04-03 05:20:44 +00:00
|
|
|
<Label key={palette.name} className="mb-6">
|
|
|
|
<div className="mb-2">{palette.title}</div>
|
2022-11-10 13:09:19 +00:00
|
|
|
<div className="w-full">
|
|
|
|
<ColorPicker
|
2023-03-09 18:57:59 +00:00
|
|
|
popoverAlign="start"
|
|
|
|
container={dialogContentRef?.current ?? undefined}
|
2022-11-10 13:09:19 +00:00
|
|
|
defaultValue="#000000"
|
|
|
|
onChange={(color) => {
|
|
|
|
addToPalette({
|
2023-02-16 22:39:57 +00:00
|
|
|
[palette.name as keyof (typeof previewState)["palette"]]: color,
|
2022-11-10 13:09:19 +00:00
|
|
|
});
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</Label>
|
|
|
|
))}
|
2023-06-14 09:22:44 +00:00
|
|
|
{isBookerLayoutsEnabled && (
|
|
|
|
<Label className="mb-6">
|
|
|
|
<div className="mb-2">{t("layout")}</div>
|
|
|
|
<Select
|
|
|
|
className="w-full"
|
|
|
|
defaultValue={layoutOptions[0]}
|
|
|
|
onChange={(option) => {
|
|
|
|
if (!option) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
setPreviewState((previewState) => {
|
2023-06-26 15:24:19 +00:00
|
|
|
const config = {
|
|
|
|
...(previewState.floatingPopup.config ?? {}),
|
|
|
|
layout: option.value,
|
|
|
|
};
|
2023-06-14 09:22:44 +00:00
|
|
|
return {
|
|
|
|
...previewState,
|
2023-06-26 15:24:19 +00:00
|
|
|
floatingPopup: {
|
|
|
|
config,
|
|
|
|
},
|
2023-06-14 09:22:44 +00:00
|
|
|
layout: option.value,
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}}
|
|
|
|
options={layoutOptions}
|
|
|
|
/>
|
|
|
|
</Label>
|
|
|
|
)}
|
2022-11-10 13:09:19 +00:00
|
|
|
</div>
|
|
|
|
</CollapsibleContent>
|
|
|
|
</Collapsible>
|
|
|
|
</div>
|
2022-05-05 14:29:49 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
2022-09-19 11:34:30 +00:00
|
|
|
<div className="flex w-2/3 flex-col p-8">
|
2022-09-18 23:14:57 +00:00
|
|
|
<HorizontalTabs data-testid="embed-tabs" tabs={parsedTabs} linkProps={{ shallow: true }} />
|
2022-06-09 05:05:18 +00:00
|
|
|
{tabs.map((tab) => {
|
|
|
|
return (
|
|
|
|
<div
|
2022-09-18 23:14:57 +00:00
|
|
|
key={tab.href}
|
2022-09-19 09:47:46 +00:00
|
|
|
className={classNames(
|
|
|
|
router.query.embedTabName === tab.href.split("=")[1] ? "flex flex-grow flex-col" : "hidden"
|
|
|
|
)}>
|
2022-09-15 05:34:11 +00:00
|
|
|
<div className="flex h-[55vh] flex-grow flex-col">
|
|
|
|
{tab.type === "code" ? (
|
|
|
|
<tab.Component
|
|
|
|
embedType={embedType}
|
|
|
|
calLink={calLink}
|
|
|
|
previewState={previewState}
|
|
|
|
ref={refOfEmbedCodesRefs.current[tab.name]}
|
|
|
|
/>
|
|
|
|
) : (
|
|
|
|
<tab.Component
|
|
|
|
embedType={embedType}
|
|
|
|
calLink={calLink}
|
|
|
|
previewState={previewState}
|
|
|
|
ref={iframeRef}
|
|
|
|
/>
|
|
|
|
)}
|
2022-06-09 05:05:18 +00:00
|
|
|
</div>
|
2022-09-15 05:34:11 +00:00
|
|
|
<div className={router.query.embedTabName == "embed-preview" ? "block" : "hidden"} />
|
2022-06-09 05:05:18 +00:00
|
|
|
<div className="mt-8 flex flex-row-reverse gap-x-2">
|
|
|
|
{tab.type === "code" ? (
|
|
|
|
<Button
|
|
|
|
type="submit"
|
|
|
|
onClick={() => {
|
2022-06-16 11:55:49 +00:00
|
|
|
const currentTabCodeEl = refOfEmbedCodesRefs.current[tab.name].current;
|
|
|
|
if (!currentTabCodeEl) {
|
2022-06-09 05:05:18 +00:00
|
|
|
return;
|
|
|
|
}
|
2022-06-16 11:55:49 +00:00
|
|
|
navigator.clipboard.writeText(currentTabCodeEl.value);
|
2022-06-09 05:05:18 +00:00
|
|
|
showToast(t("code_copied"), "success");
|
|
|
|
}}>
|
|
|
|
{t("copy_code")}
|
|
|
|
</Button>
|
|
|
|
) : null}
|
2022-11-28 19:14:38 +00:00
|
|
|
<DialogClose />
|
2022-06-09 05:05:18 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
})}
|
2022-05-05 14:29:49 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</DialogContent>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export const EmbedDialog = () => {
|
|
|
|
const router = useRouter();
|
2022-08-13 11:04:57 +00:00
|
|
|
const embedUrl: string = router.query.embedUrl as string;
|
2022-05-05 14:29:49 +00:00
|
|
|
return (
|
2023-06-06 23:52:13 +00:00
|
|
|
<Dialog name="embed" clearQueryParamsOnClose={queryParamsForDialog}>
|
2022-05-05 14:29:49 +00:00
|
|
|
{!router.query.embedType ? (
|
|
|
|
<ChooseEmbedTypesDialogContent />
|
|
|
|
) : (
|
|
|
|
<EmbedTypeCodeAndPreviewDialogContent
|
|
|
|
embedType={router.query.embedType as EmbedType}
|
2022-08-13 11:04:57 +00:00
|
|
|
embedUrl={embedUrl}
|
2022-05-05 14:29:49 +00:00
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</Dialog>
|
|
|
|
);
|
|
|
|
};
|
2022-08-13 11:04:57 +00:00
|
|
|
type EmbedButtonProps<T> = {
|
|
|
|
embedUrl: string;
|
|
|
|
children?: React.ReactNode;
|
2022-09-02 19:00:41 +00:00
|
|
|
className?: string;
|
2022-08-13 11:04:57 +00:00
|
|
|
as?: T;
|
|
|
|
};
|
2022-05-05 14:29:49 +00:00
|
|
|
|
2022-08-13 11:04:57 +00:00
|
|
|
export const EmbedButton = <T extends React.ElementType>({
|
|
|
|
embedUrl,
|
2022-07-27 02:24:00 +00:00
|
|
|
children,
|
2022-05-05 14:29:49 +00:00
|
|
|
className = "",
|
2022-08-13 11:04:57 +00:00
|
|
|
as,
|
2022-05-05 14:29:49 +00:00
|
|
|
...props
|
2022-08-13 11:04:57 +00:00
|
|
|
}: EmbedButtonProps<T> & React.ComponentPropsWithoutRef<T>) => {
|
2022-05-05 14:29:49 +00:00
|
|
|
const router = useRouter();
|
2023-01-20 14:19:12 +00:00
|
|
|
className = classNames("hidden lg:inline-flex", className);
|
2022-05-05 14:29:49 +00:00
|
|
|
const openEmbedModal = () => {
|
2022-09-19 09:47:46 +00:00
|
|
|
goto(router, {
|
|
|
|
dialog: "embed",
|
|
|
|
embedUrl,
|
|
|
|
});
|
2022-05-05 14:29:49 +00:00
|
|
|
};
|
2022-08-13 11:04:57 +00:00
|
|
|
const Component = as ?? Button;
|
2022-05-05 14:29:49 +00:00
|
|
|
|
|
|
|
return (
|
2022-08-13 11:04:57 +00:00
|
|
|
<Component
|
2022-05-05 14:29:49 +00:00
|
|
|
{...props}
|
2022-08-13 11:04:57 +00:00
|
|
|
className={className}
|
|
|
|
data-test-embed-url={embedUrl}
|
|
|
|
data-testid="embed"
|
2022-09-02 19:00:41 +00:00
|
|
|
type="button"
|
|
|
|
onClick={() => {
|
|
|
|
openEmbedModal();
|
|
|
|
}}>
|
2022-07-27 02:24:00 +00:00
|
|
|
{children}
|
2022-08-13 11:04:57 +00:00
|
|
|
</Component>
|
2022-05-05 14:29:49 +00:00
|
|
|
);
|
|
|
|
};
|