packages/embeds/README.md
This folder contains all the various flavours of embeds.
core contains the core library written in vanilla JS that manages the embed.
snippet contains the Vanilla JS Code Snippet that can be installed on any website and would automatically fetch the core library.
Please see the respective folder READMEs for details on them.
To publish the packages. Following steps should be followed. All commands are to be run at the root.
yarn changeset -> Creates changelog files and adds summary to changelog. Select embed packages only here.yarn changeset version -> Bumps the versions as requiredyarn publish-embed -> Releases all packages. We can't use yarn changeset publish because it doesn't support workspace: prefix removal yet. See https://github.com/changesets/changesets/issues/432#issuecomment-1016365428Skeleton loader is shown for supported page types. For all other page types, default non-skeleton loader is shown. Status:
prerender delegates its task to preload API which then identifies whether to preload or prerender.The embed system initializes through a multi-step process:
Cal object that acts as the entry pointcal-modal-box, cal-floating-button, cal-inline)Communication between the parent page and the embedded iframe uses a message-based system:
// Parent to Iframe communication example
interface InterfaceWithParent {
ui: (config: UiConfig) => void;
connect: (config: PrefillAndIframeAttrsConfig) => void;
}
// Event data structure
type EventData<T> = {
type: string;
namespace: string;
fullType: string;
data: EventDataMap[T];
};
The system uses namespaced events to ensure multiple embeds on the same page don't interfere with each other.
Commands are queued before the iframe is ready:
type Instruction = SingleInstruction | SingleInstruction[];
type InstructionQueue = Instruction[];
// Commands are queued if iframe isn't ready
if (!this.iframeReady) {
this.iframeDoQueue.push(doInIframeArg);
return;
}
Embeds the calendar directly within the page flow:
Cal.inline({
elementOrSelector: "#my-cal-inline",
calLink: "organization/event-type"
});
Creates a modal dialog with the calendar:
Cal.modal({
calLink: "organization/event-type",
config: {
// Optional configuration
useSlotsViewOnSmallScreen: "true"
}
});
Adds a floating action button that opens the calendar in a modal. It uses modal embedding under the hood.
Cal.floatingButton({
calLink: "organization/event-type",
buttonText: "Book meeting",
buttonPosition: "bottom-right"
});
Allows pre-filling form fields:
Cal.inline({
calLink: "organization/event-type",
config: {
name: "John Doe",
email: "[email protected]",
notes: "Initial discussion",
useSlotsViewOnSmallScreen: "true"
}
});
The system allows automatically forwarding query params to the iframe, by setting. This code must be present right after the embed snippet is added to the page.
Cal.config = Cal.config || {};
Cal.config.forwardQueryParams=true
You can enable logging for the embed by adding the cal.embed.logging=1 query parameter to the URL of the page where the embed is placed. This is useful for debugging issues with the embed. It will log all important things in parent as well as in the iframe(i.e. child)
For example, if your page is https.example.com/contact, you can enable logging by visiting https.example.com/contact?cal.embed.logging=1.
The prerendering system optimizes the initial load:
Cal("prerender", {
calLink,
type: "modal"
});
Key aspects:
Modal's Iframe Reuse and Reload Conditions. There could be four situations:
Show modal as is:
Connect but don't fetch the slots:
config changes (handled via "connect" flow)Connect and fetch the slots:
Do a fresh load in iframe:
Without namespace: Prerender when there are high chances of user clicking the CTA.
Cal('prerender', {
calLink: "router?formId=123&ONLY_THOSE_FIELDS_THAT_ARE_REQUIRED_BY_ROUTING_RULES_SHOULD_BE_PRESENT_HERE",
// Prerender right now works only with "modal", so 'element click' embed is able to reuse this prerendered iframe
type: "modal",
// Shows skeleton loader for a Team Event's booking slots page
pageType: "team.event.booking.slots"
});
Using the prerendered iframe with a CTA:
<button data-cal-link="router?formId=123&ALL_FIELDS_HERE">Demo</button>
With namespace: Prerender when there are high changes of user clicking the CTA.
Cal.ns.myNamespace('prerender', {
calLink: "router?formId=123&ONLY_THOSE_FIELDS_THAT_ARE_REQUIRED_BY_ROUTING_RULES_SHOULD_BE_PRESENT_HERE",
// Prerender right now works only with "modal", so 'element click' embed is able to reuse this prerendered iframe
type: "modal"
// Shows skeleton loader for a Team Event's booking slots page
pageType: "team.event.booking.slots"
});
Using the prerendered iframe with a CTA:
<button data-cal-namespace="myNamespace" data-cal-link="router?formId=123&ALL_FIELDS_HERE">Demo</button>