Files
cal-diy-oidc/packages/embeds/embed-core/index.html
T
Rajiv Sahal 8c39210a12 fix: scroll issues in Embed (#26583)
* chore: add new view for two step slot selection for embed

* fix: make sure two step slot selection is false by default

* chore: update embed playground to showcase two step slot selection

* chore: add tests

* chore: update embed snippet generator code to include two step slot selection

* chore: update docs

* fix: back button styling

* chore: implement feedback from cubic

* fix: add missing isEnableTwoStepSlotSelectionVisible properties to test mock store

Co-Authored-By: unknown <>

* chore: implement PR feedback

* chore: update slot selection modal

* chore: add prop to hide available times header

* fix: scope two-step slot selection visibility to mobile only

Restores the isMobile check in the timeslot visibility guard to ensure
desktop embeds continue to show the booking UI when two-step slot
selection is enabled. The feature should only hide the timeslot list
on mobile devices.

Addresses Cubic AI review feedback (confidence 9/10).

Co-Authored-By: unknown <>

* fixup: use translations for loading instead of actual word

* fix: type check

* fix: add window.matchMedia mock for jsdom test environment

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: add window.matchMedia mock to packages/testing/src/setupVitest.ts

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: unit tests failing

* add a width style to the two-step slot selection embed container.

* refactor: rename enableTwoStepSlotSelection to useSlotsViewOnSmallScreen

- Rename external-facing embed config option from enableTwoStepSlotSelection to useSlotsViewOnSmallScreen
- Update URL parameter parsing in embed-iframe.ts
- Update type definitions in types.ts and index.d.ts
- Update internal variable names to slotsViewOnSmallScreen for consistency
- Update documentation, playground examples, and tests

Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>

* Add config to prefill all booking fields so that slot has confirm button along with it

* chore: implement PR feedback

* fix: move twoStepSlotSelection embed outside misc-embeds div to fix e2e test

The e2e test was failing because the misc-embeds div content was
intercepting pointer events on mobile viewport. This follows the same
pattern used for skeletonDemo - the embed is now outside misc-embeds
and the div is hidden when testing this namespace.

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: prevent pointer event interception in twoStepSlotSelection embed

Hide heading and note elements and set pointer-events: none on container
elements while keeping pointer-events: auto on the iframe container.
This prevents the container from intercepting clicks on the iframe
during mobile viewport e2e tests.

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: hide all non-essential content for twoStepSlotSelection e2e test

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: disable pointer-events on body for twoStepSlotSelection e2e test

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: remove pointer-events: auto on container to let clicks pass through to iframe

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: explicitly set pointer-events: none on container and inline-embed-container

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: also set pointer-events: none on html element to prevent interception

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: make .place div fill viewport for twoStepSlotSelection e2e test

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: failing embed tests

* fixup

* fixup fixup

* fix: failing tests

* fix: update checks for verifying prefilled date

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
2026-01-21 15:44:33 -03:00

546 lines
24 KiB
HTML

<html>
<head>
<title>Embed Playground</title>
<style>
html.grid-row-gap body {
grid-row-gap: 10rem;
flex-flow: column;
display: flex;
}
</style>
<script type="text/javascript" src="./playground/lib/playground-init.ts"></script>
<script>
let popupRescheduleUid = null;
let popupCancelUid = null;
let calLink = null;
const initialNamespace = (url.searchParams.get("only") || "").split("ns:")[1] || "";
(function defineVariables() {
const searchParams = new URL(document.URL).searchParams;
popupRescheduleUid = searchParams.get("popupRescheduleUid") || "qm3kwt3aTnVD7vmP9tiT2f";
popupCancelUid = searchParams.get("popupCancelUid") || "qm3kwt3aTnVD7vmP9tiT2f";
calLink = searchParams.get("calLink");
})()
if (!location.search.includes("nonResponsive")) {
document.write('<meta name="viewport" content="width=device-width"/>');
}
if (location.search.includes("grid-row-gap")) {
document.documentElement.classList.add("grid-row-gap");
}
function addInlineEmbedInNewNamespaceWithoutReload(selector) {
Cal("init", "withoutReloadNamespace", {
debug: true,
calOrigin: window.calOrigin,
});
Cal.ns.withoutReloadNamespace("inline", {
elementOrSelector: selector,
calLink: "pro?case=addInlineEmbedInANewNamespaceWithoutReload",
config: {
"flag.coep": "true"
}
});
};
</script>
<script>
// Put the snippet in a function so that it can be re-executed for scenario testing
// TODO: How to reuse embed-snippet export here?
function embedSnippet() {
((C, A, L) => {
const p = (a, ar) => {
a.q.push(ar);
};
const d = C.document;
C.Cal =
C.Cal ||
function () {
const cal = C.Cal;
const 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 || [];
if (typeof namespace === "string") {
// Make sure that even after re-execution of the snippet, the namespace is not overridden
cal.ns[namespace] = cal.ns[namespace] || api;
p(cal.ns[namespace], ar);
p(cal, ['initNamespace', namespace])
} else p(cal, ar);
return;
}
p(cal, ar);
};
})(window, window.calOrigin + "/embed/embed.js", "init");
}
embedSnippet();
</script>
<script>
function doubleInstallSnippetWithInlineEmbedWithNonDefaultNamespace(selector) {
Cal("init", "doubleInstall", {
debug: true,
calOrigin: window.calOrigin,
});
Cal.ns.doubleInstall("inline", {
elementOrSelector: selector,
calLink: "pro?case=doubleInstallSnippetWithInlineEmbedWithNonDefaultNamespace",
config: {
"flag.coep": "true"
}
});
embedSnippet();
Cal("init", "doubleInstall", {
debug: true,
calOrigin: window.calOrigin,
});
Cal.ns.doubleInstall("inline", {
elementOrSelector: selector,
calLink: "pro",
config: {
"flag.coep": "true"
}
});
}
function doubleInstallSnippetWithInlineEmbed(selector) {
Cal("init", {
debug: true,
calOrigin: window.calOrigin,
});
Cal("inline", {
elementOrSelector: selector,
calLink: "pro?case=doubleInstallSnippetWithInlineEmbed",
config: {
"flag.coep": "true"
}
});
embedSnippet();
Cal("init", {
debug: true,
calOrigin: window.calOrigin,
});
Cal("inline", {
elementOrSelector: selector,
calLink: "pro",
config: {
"flag.coep": "true"
}
});
}
function addTwoInlineEmbedWithTwoDifferentNamespacesWithDifferentInitConfig() {
Cal("init", "namespace-init-test-1", {
debug: true,
calOrigin: window.calOrigin,
});
Cal("init", "namespace-init-test-2", {
debug: true,
calOrigin: "http://127.0.0.1:3000",
});
Cal.ns['namespace-init-test-2']("inline", {
elementOrSelector: '#two-different-namespace-with-different-init-config-content-2',
calLink: "pro",
config: {
"flag.coep": "true"
}
});
Cal.ns['namespace-init-test-1']("inline", {
elementOrSelector: '#two-different-namespace-with-different-init-config-content-1',
calLink: "pro",
config: {
"flag.coep": "true"
}
});
}
</script>
<style>
body {
background: linear-gradient(90deg,
rgba(120, 116, 186, 1) 0%,
rgba(221, 221, 255, 1) 41%,
rgba(148, 232, 249, 1) 100%);
}
.inline-embed-container {
/* border: 1px solid black; */
margin-bottom: 5px;
border-bottom: 1px solid;
}
.loader {
color: green;
}
</style>
</head>
<body>
<div style="margin-bottom: 20px;">
<h2>Different variations of the page</h2>
<div style="display: flex; flex-flow: row; gap: 10px;">
<span style="display: block"><a href="?color-scheme=dark">With Dark Color Scheme for the Page</a></span>
<span style="display: block"><a href="?nonResponsive">Non responsive version of this page here</a></span>
<span style="display: block"><a href="?grid-row-gap">Grid row gap version of this page here</a></span>
</div>
</div>
<div id="misc-embeds">
<h2>Misc Embeds</h2>
<div>
<button id="add-inline-embed-in-a-new-namespace-without-reload-button"
onclick="addInlineEmbedInNewNamespaceWithoutReload('#add-inline-embed-in-a-new-namespace-without-reload-button-content')">Add
Inline Embed in a new namespace without reload</button>
<div id="add-inline-embed-in-a-new-namespace-without-reload-button-content"></div>
</div>
<div>
<button id="double-install-snippet-with-inline-embed-default-namespace-button"
onclick="doubleInstallSnippetWithInlineEmbed('#double-install-snippet-with-inline-embed-default-namespace-content')">Double
Install Embed Snippet with inline embed - Default Namespace</button>
<div id="double-install-snippet-with-inline-embed-default-namespace-content"></div>
</div>
<div>
<button id="double-install-snippet-with-inline-embed-non-default-namespace-button"
onclick="doubleInstallSnippetWithInlineEmbedWithNonDefaultNamespace('#double-install-snippet-with-inline-embed-non-default-namespace-content')">Double
Install Embed Snippet with inline embed - Non Default Namespace</button>
<div id="double-install-snippet-with-inline-embed-non-default-namespace-content"></div>
</div>
<div>
<button id="two-different-namespace-with-different-init-config"
onclick="addTwoInlineEmbedWithTwoDifferentNamespacesWithDifferentInitConfig()">Two different namespace with two
different config</button>
<div id="two-different-namespace-with-different-init-config-area">
<div id="two-different-namespace-with-different-init-config-content-1"></div>
<div id="two-different-namespace-with-different-init-config-content-2"></div>
</div>
</div>
<span style="display: block">
<a
href="?name=john&email=email&guests=abc&guests=def&notes=NOTES&location=%7B%22optionValue%22%3A%22%2B919999999999%22%2C%22value%22%3A%22phone%22%7D&only=ns%3ApageParamsForwarding">
Page Params Forwarding(Prefills various fields by auto-forwarding query params)
</a>
</span>
<span style="display: block"><a href="?only=prerender-test">Go to Prerender test page only</a><small></small></span>
<span style="display: block"><a href="?only=preload-test">Go to Preload test page only</a><small></small></span>
<button onclick="document.documentElement.style.colorScheme='dark'">Toggle Dark Scheme(For Embedding Page)</button>
<button onclick="document.documentElement.style.colorScheme='light'">Toggle Light Scheme(For Embedding
Page)</button>
<div>
<script>
if (only === "all" || only === "prerender-test") {
document.write(`
<button data-cal-namespace="e2ePrerenderLightTheme" data-cal-config='{"theme":"dark", "email":"preloaded-prefilled@example.com", "name": "Preloaded Prefilled", "flag.coep": "true"}' data-cal-link="free/30min">Book with Free User[Dark Theme]</button>
<i
>Corresponding Cal Link is being prerendered. Assuming that it would take you some time to click this
as you are reading this text, it would open up super fast[If you are running a production build on
local]. Try switching to slow 3G or create a custom Network configuration which is impossibly
slow. This should be used if you know beforehand which type of embed is going to be opened.</i
>`);
}
if (only === "all" || only === "preload-test") {
document.write(`
<button data-cal-namespace="preloadTest" data-cal-config='{"theme":"dark", "email":"preloaded-prefilled@example.com", "name": "Preloaded Prefilled", "flag.coep": "true"}' data-cal-link="free/30min">Book with Free User[Dark Theme]</button>
<i
>Corresponding Cal Link is being preloaded. That means that all the resources would be preloaded. This could be useful in preloading possible resources if you don't know before hand which type of embed you want to show</i
>`);
}
</script>
</div>
<span style="display: block"><a href="?only=all">Render All embeds together</a><small> - It would be slow to
load</small></span>
<a href="?only=ns:floatingButton">Floating Popup</a>
<h2>Popup Examples - Theme Tests</h2>
<button data-cal-namespace="e2ePopupLightTheme" data-cal-link="free"
data-cal-config='{"theme":"light", "flag.coep": "true"}'>Book an event with Free[Light Theme]</button>
<button data-cal-namespace="popupAutoTheme" data-cal-link="free" data-cal-config='{"flag.coep": "true"}'>
Book with Free User[Auto Theme]
</button>
<button data-cal-namespace="popupDarkTheme" data-cal-config='{"theme":"dark", "flag.coep": "true"}'
data-cal-link="free">
Book with Free User[Dark Theme]
</button>
<button data-cal-namespace="popupTeamLinkLightTheme" data-cal-config='{"theme":"light", "flag.coep": "true"}'
data-cal-link="team/seeded-team/collective-seeded-team-event">
Book with Test Team[Light Theme]
</button>
<button data-cal-namespace="popupTeamLinkDarkTheme" data-cal-config='{"theme":"dark", "flag.coep": "true"}'
data-cal-link="team/seeded-team/collective-seeded-team-event">
Book with Test Team[Dark Theme]
</button>
<button data-cal-namespace="popupTeamLinksList" data-cal-link="team/seeded-team/"
data-cal-config='{"flag.coep": "true"}'>
See Team Links [Auto Theme]
</button>
<button data-cal-namespace="popupPaidEvent" data-cal-link="pro/paid" data-cal-config='{"flag.coep": "true"}'>
Book Paid Event [Auto Theme]
</button>
<h2>Popup Examples - Reschedule Tests</h2>
<script>
document.write(
`<button data-cal-namespace="popupRescheduleWithReschedulePath" data-cal-config='{"flag.coep":"true"}' data-cal-link="reschedule/${popupRescheduleUid}">Reschedule Event(with /reschedule) - Needs popupRescheduleUid param</button>`
);
</script>
<script>
document.write(
`<button data-cal-namespace="popupRescheduleWithRescheduleUidParam" data-cal-config='{"flag.coep":"true", "rescheduleUid": "${popupRescheduleUid}"}' data-cal-link="${calLink}">Reschedule Event(with rescheduleUid param) - Needs popupRescheduleUid and calLink param</button>`
);
</script>
<h2>Popup Examples - Cancel Tests</h2>
<script>
document.write(
`<button data-cal-namespace="popupCancelBooking" data-cal-config='{"flag.coep":"true"}' data-cal-link="booking/${popupCancelUid}?cancel=true">Cancel Booking - Needs popupCancelUid param</button>`
);
</script>
<h2>Popup Examples - Different Configurations</h2>
<button data-cal-namespace="popupHideEventTypeDetails" data-cal-link="free/30min"
data-cal-config='{"flag.coep": "true"}'>
Book Free Event [Auto Theme][uiConfig.hideEventTypeDetails=true]
</button>
<button data-cal-namespace="popupPaidEvent" data-cal-config='{"layout":"week_view", "flag.coep": "true"}'
data-cal-link="pro/paid">
Book Paid Event - weekly view
</button>
<button data-cal-namespace="popupPaidEvent" data-cal-config='{"layout":"column_view", "flag.coep": "true"}'
data-cal-link="pro/paid">
Book Paid Event - column view
</button>
<h2>Popup Examples - Routing Form Tests</h2>
<button data-cal-namespace="routingFormAuto" data-cal-link="forms/948ae412-d995-4865-875a-48302588de03"
data-cal-config='{"flag.coep": "true"}'>
Book through Routing Form [Auto Theme] - Test for 'routed' event
</button>
<button data-cal-namespace="routingFormDark" data-cal-config='{"theme":"dark", "flag.coep": "true"}'
data-cal-link="forms/948ae412-d995-4865-875a-48302588de03">
Book through Routing Form [Dark Theme]
</button>
<button data-cal-namespace="routingFormHeadlessRouter"
data-cal-link="router?form=948ae412-d995-4865-875a-48302588de03&Test field=event-routing"
data-cal-config='{"flag.coep": "true"}'>
Book through Headless Router
</button>
<h2>Popup Examples - Child Element Target Tests</h2>
<a style="display: block;" data-cal-namespace="childElementTarget" href="javascript:void(0)"
data-cal-link="free/30min" data-cal-config='{"flag.coep": "true"}'>
I am Anchor
<b>[I am Bold inside anchor]</b>
<span>
I am span inside anchor
</span>
</a>
<h2>Inline Embed Examples</h2>
<div id="namespaces-test">
<div class="inline-embed-container" id="cal-booking-place-default">
<h3>
<a href="?only=ns:default">[Dark Theme][Guests(janedoe@example.com and test@example.com)](Default
Namespace)</a>
</h3>
<button onclick="Cal('ui',{theme:'light'})">Toggle to Light</button>
<button onclick="Cal('ui',{layout:'week_view'})">Toggle to Week View</button>
<button onclick="Cal('ui',{layout:'month_view'})">Toggle to Month View</button>
<button onclick="Cal('ui',{layout:'column_view'})">Toggle to Column View</button>
<i class="last-action"> You would see last Booking page action in my place </i>
<div>
<div class="place" style="width: 100%"></div>
<div class="loader" id="cal-booking-loader-"></div>
</div>
</div>
<div class="inline-embed-container" id="cal-booking-place-second">
<h3><a href="?only=ns:second">[Custom Styling]</a></h3>
<div class="place">
<div>
If you render booking embed in me, I won't restrict you. The entire page is yours. Content is by
default aligned center
</div>
<button onclick="heavilyCustomizeUi({ namespace: 'second' })">
Heavily customize UI
</button>
<button
onclick="(function () {Cal.ns.second('ui', {cssVarsPerTheme:{light:{'cal-border-booker':'green', 'cal-border-booker-width':'20px'},dark:{'cal-border-booker':'red', 'cal-border-booker-width':'5px'}}})})()">
Change booker border for dark and light themes
</button>
<button onclick="fakeErrorScenario({ namespace: 'second' })">
Create error scenario
</button>
<button
onclick="(function () {Cal.ns.second('ui', {cssVarsPerTheme:{light:{'cal-brand':'green'},dark:{'cal-brand':'red'}}})})()">
Change Brand color for dark and light theme
</button>
<button
onclick="(function () {Cal.ns.second('ui', {styles:{eventTypeListItem:{backgroundColor:'blue'}}})})()">
Change <code>eventTypeListItem</code> bg color[Deprecated]
</button>
<button onclick="(function () {Cal.ns.second('ui', {styles:{align:'left'}})})()">
Align left[Deprecated]
</button>
<button onclick="(function () {Cal.ns.second('ui', {styles:{align:'center'}})})()">
Align Center[Deprecated]
</button>
<button onclick="(function () {Cal.ns.second('ui', {styles:{enabledDateButton: {
backgroundColor: window.generateRandomHexColor(),
},
disabledDateButton: {
backgroundColor: window.generateRandomHexColor(),
},}})})()">
Change 'enabledDateButton` and `disabledDateButton` background Color[Deprecated]
</button>
</div>
</div>
<div class="inline-embed-container" id="cal-booking-place-third">
<h3><a href="?only=ns:third">[Custom Styling - Transparent Background]</a></h3>
<div style="width: 30%" class="place">
<div>If you render booking embed in me, I would not let you be more than 30% wide</div>
</div>
</div>
<div class="inline-embed-container" id="cal-booking-place-fourth">
<h3><a href="?only=ns:fourth">[Team Event Test][inline taking entire width]</a></h3>
<div style="width: 30%" class="place">
<div>If you render booking embed in me, I would not let you be more than 30% wide</div>
</div>
</div>
<div class="inline-embed-container" id="cal-booking-place-corpTest">
<h3><a href="?only=ns:corpTest">CORP/COEP Blocking Test</a></h3>
<div class="place">
<div>It would forever load</div>
</div>
</div>
</div>
<div class="inline-embed-container" id="cal-booking-place-fifth">
<h3><a href="?only=ns:fifth">[Team Event Test][inline along with some content]</a></h3>
<div style="display: flex; align-items: center">
<h4 style="width: 30%">On the right side you can book a team meeting =></h4>
<div style="width: 70%" class="place"></div>
</div>
</div>
<div class="inline-embed-container" id="cal-booking-place-inline-routing-form">
<h3><a href="?only=inline-routing-form">Inline Routing Form</a></h3>
<div style="display: flex; align-items: center">
<h4 style="width: 30%">On the right side you can book a team meeting =></h4>
<div style="width: 70%" class="place"></div>
</div>
</div>
<div class="inline-embed-container" id="cal-booking-place-hideEventTypeDetails">
<h3><a href="?only=ns:hideEventTypeDetails">Hide EventType Details Test</a></h3>
<div class="place"></div>
</div>
<div class="inline-embed-container" style="width: 500px; overflow-y: scroll;"
id="cal-booking-place-windowScrollToTimeslot">
<h3><a href="?only=ns:windowScrollToTimeslot">Scroll to Timeslot Test - Selecting a date would scroll the window
to
the timeslot</a></h3>
<div class="place"></div>
</div>
<div class="inline-embed-container" style="height: 500px; width: 500px; overflow-y: scroll;"
id="cal-booking-place-containerScrollToTimeslot">
<h3><a href="?only=ns:containerScrollToTimeslot">Container Scroll Test - Selecting a date would scroll the element
to the timeslot</a></h3>
<div class="place"></div>
</div>
<div class="inline-embed-container" id="cal-booking-place-conflicting-theme">
<h3><a href="?only=conflicting-theme">You would be able to test out conflicting themes for the same namespace
here.</a></h3>
<div class="light"></div>
<div class="dark"></div>
<i>Note that one of the embeds would stay in loading state as they are using the same namespace and it is not
supported to have more than 1 embeds using same namespace</i>
</div>
<div class="inline-embed-container" id="cal-booking-place-monthView">
<h3><a href="?only=ns:monthView">Test Month View</a></h3>
<div class="place" style="width: 100%"></div>
</div>
<div class="inline-embed-container" id="cal-booking-place-weekView">
<h3><a href="?only=ns:weekView">Test Week View</a></h3>
<div class="place" style="width: 100%"></div>
</div>
<div class="inline-embed-container" id="cal-booking-place-columnView">
<h3><a href="?only=ns:columnView">Test Column View</a></h3>
<div class="place" style="width: 100%"></div>
</div>
<div class="inline-embed-container" id="cal-booking-place-columnViewHideEventTypeDetails">
<h3><a href="?only=ns:columnViewHideEventTypeDetails">Test Column View Hide Event Type Details</a></h3>
<div class="place" style="width: 100%"></div>
</div>
<div class="inline-embed-container" id="cal-booking-place-pageParamsForwarding">
<h3><a href="?only=ns:pageParamsForwarding">Test Page Params Forwarding</a></h3>
<div class="place" style="width: 100%"></div>
</div>
<div class="inline-embed-container" id="cal-booking-place-autoScrollTest">
<h3><a href="?only=ns:autoScrollTest">Test Auto Scroll</a></h3>
<div class="place" style="width: 100%"></div>
</div>
</div>
<div id="cal-booking-place-twoStepSlotSelection">
<div class="inline-embed-container" style="width: 30%;">
<h3><a href="?only=ns:twoStepSlotSelection">Test Two Step Slot Selection</a></h3>
<i>Note: Two step slot selection only applies to mobile view. If you're testing this on a big screen, you need to make the screen mobile width.</i>
<div class="place" style="width: 100%"></div>
</div>
</div>
<div id="cal-booking-place-skeletonDemo">
<h3><a href="?only=ns:skeletonDemo">Skeleton Loader INLINE Demo</a></h3>
<div class="inline-embed-container">
<div id="cal-booking-place-skeletonDemo">
<div class="place"></div>
</div>
</div>
</div>
<div id="cal-booking-place-skeletonDemoElementClick">
<a href="?only=ns:skeletonDemoElementClick">Skeleton Loader MODAL Demo</a>
<h3><button data-cal-namespace="skeletonDemoElementClick"
data-cal-link="team/seeded-team/collective-seeded-team-event"
data-cal-config='{"cal.embed.pageType":"team.event.booking.slots"}'>Skeleton Loader MODAL Demo</button></h3>
<div class="inline-embed-container">
<div id="cal-booking-place-skeletonDemoElementClick">
<div class="place"></div>
</div>
</div>
</div>
<script type="module" src="./playground/lib/playground.ts"></script>
<script>
if (initialNamespace.startsWith("skeletonDemo") || initialNamespace === "twoStepSlotSelection") {
document.getElementById("misc-embeds").style.display = "none";
}
// For twoStepSlotSelection, make the .place div fill the entire viewport
// This ensures nothing else can intercept pointer events on mobile viewport
if (initialNamespace === "twoStepSlotSelection") {
const container = document.getElementById("cal-booking-place-twoStepSlotSelection");
if (container) {
// Hide the container's other content (h3, note)
container.style.display = "contents";
const inlineContainer = container.querySelector(".inline-embed-container");
if (inlineContainer) {
inlineContainer.style.display = "contents";
}
const place = container.querySelector(".place");
if (place) {
// Make the .place div fill the entire viewport
place.style.position = "fixed";
place.style.top = "0";
place.style.left = "0";
place.style.width = "100vw";
place.style.height = "100vh";
place.style.zIndex = "9999";
}
}
}
</script>
</body>
</html>