* mvp done * wip * fix ts errors and other code improvements * fix ts errors * ensure mobile layout support * Make skeleton responsive on screen resize * refactor * Add test for EmbedElement * make skeleton closer to pixel perfect * Address PR feedback * Router-preloading ## What does this PR do? <!-- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. --> - Fixes #XXXX (GitHub issue number) - Fixes CAL-XXXX (Linear issue number - should be visible at the bottom of the GitHub issue description) ## Visual Demo (For contributors especially) A visual demonstration is strongly recommended, for both the original and new change **(video / image - any one)**. #### Video Demo (if applicable): - Show screen recordings of the issue or feature. - Demonstrate how to reproduce the issue, the behavior before and after the change. #### Image Demo (if applicable): - Add side-by-side screenshots of the original and updated change. - Highlight any significant change(s). ## Mandatory Tasks (DO NOT REMOVE) - [ ] I have self-reviewed the code (A decent size PR without self-review might be rejected). - [ ] I have updated the developer docs in /docs if this PR makes changes that would require a [documentation change](https://cal.com/docs). If N/A, write N/A here and check the checkbox. - [ ] I confirm automated tests are in place that prove my fix is effective or that my feature works. ## How should this be tested? <!-- Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration. Write details that help to start the tests --> - Are there environment variables that should be set? - What are the minimal test data to have? - What is expected (happy path) to have (input and output)? - Any other important info that could help to test that PR ## Checklist <!-- Remove bullet points below that don't apply to you --> - I haven't read the [contributing guide](https://github.com/calcom/cal.com/blob/main/CONTRIBUTING.md) - My code doesn't follow the style guidelines of this project - I haven't commented my code, particularly in hard-to-understand areas - I haven't checked if my changes generate no new warnings * wip\ * wip * fix mrge.io feedback * wip * Add README and lifecycle * Add README and lifecycle * Update routing form-seed and some other fixes * remove linkFailed fix from the branch * self-review * self-review-2 * self-review-3 * Handle soft connect\ * Update README and fix a bug with query parmas * Add one more case in routing-html playground --------- Co-authored-by: Benny Joo <sldisek783@gmail.com> Co-authored-by: amrit <iamamrit27@gmail.com>
6.0 KiB
6.0 KiB
Cal.com Embed Lifecycle Events
This document details the lifecycle events and states of Cal.com embeds, showing the interaction flow between the parent page and the iframe.
Core Lifecycle Sequence
sequenceDiagram
participant Parent as Parent (User Page)
participant Embed as Embed (iframe)
participant Store as EmbedStore(iframe)
participant UI as UI Components(iframe)
Note over Parent: embed.js loads
alt Inline Embed
Parent->>Parent: Create cal-element
Parent->>Parent: Create iframe (visibility: hidden)
Parent->>Parent: Show loader
else Modal Embed
Note over Parent: No action unless prerender
end
alt Prerender Flow
Note over Parent: Set prerender=true in URL
Parent->>Store: Set prerenderState="inProgress"
Note over Store: Limited events allowed
Parent->>Parent: Create hidden iframe
Parent->>Parent: load booker(no slots)
Note over Parent: Wait for connect() call
end
alt Modal CTA clicked
Parent->>Parent: Create cal-modal-box
Parent->>Parent: Create iframe (visibility: hidden)
Parent->>Parent: Show loader
end
Note over Embed: background: transparent(stays transparent)
Note over Embed: body tag set to visibility: hidden waiting to be shown
Note over Embed: iframe webpage starts rendering
Note over Store: Initialize EmbedStore state
Store->>Store: Set NOT_INITIALIZED state
Store->>Store: Initialize UI config & theme
Note over Parent: Process URL params for prefill
Parent->>Store: Set prefill data from URL
Note over Store: Auto-populate form fields
Embed->>Parent: __iframeReady event
Note over Parent,Embed: Embed ready to receive messages
Note over Store: Set state to INITIALIZED
Store->>UI: Apply theme configuration
Note over UI: DEPRECATED: styles prop
Note over UI: Use cssVarsPerTheme instead
Store->>UI: Apply cssVarsPerTheme
Embed->>Parent: __dimensionChanged event
Note over Parent: Calculate and adjust iframe dimensions
Note over Store: Update parentInformedAboutContentHeight
alt isBookerPage
Note over Embed: Wait for booker ready state
end
Embed->>Parent: linkReady event
Note over Parent: Changes loading state to done
Note over Parent: Removes loader
Note over Parent: Sets iframe visibility to visible
Parent->>Embed: parentKnowsIframeReady event
Note over Embed: Makes body visible
Note over Store: Update UI configuration
alt Prerendering Active
Note over Store: Set prerenderState to completed
Parent->>Store: connect() with new config
Store->>Store: Reset parentInformedAboutContentHeight
Store->>Parent: Update iframe with new params
Note over Store: Remove prerender params
end
loop Dimension Monitoring
Embed->>Embed: Monitor content size changes
alt Dimensions Changed
Embed->>Parent: __dimensionChanged event
Parent->>Parent: Adjust iframe size to avoid scrollbar
end
end
alt Route Changes
UI->>Store: Update UI state
Store->>Parent: __routeChanged event
Parent->>Parent: Handle navigation
Note over Store: Preserve prefill data
end
Detailed State Management
EmbedStore States
NOT_INITIALIZED: Initial state when iframe is createdINITIALIZED: After __iframeReady event is processedprerenderState: Can be null | "inProgress" | "completed"
Visibility States
-
Initial Creation:
- iframe.style.visibility = "hidden"
- body.style.visibility = "hidden"
-
After __iframeReady:
- iframe becomes visible (unless prerendering)
-
After parentKnowsIframeReady:
- body becomes visible
- Background remains transparent
Event Details
-
Initial Load
- embed.js loads in parent page
- For inline embeds: Creates elements immediately
- For modal embeds: Waits for CTA click (unless prerendering)
-
iframe Creation
- iframe is created with
visibility: hidden - Loader is shown (default or skeleton)
- EmbedStore initialized
- iframe is created with
-
__iframeReady Event
- Fired by: Iframe
- Indicates: Embed is ready to receive messages
- Actions:
- Sets iframeReady flag to true
- Makes iframe visible (unless prerendering)
- Processes queued iframe commands
-
__dimensionChanged Event
- Fired by: Iframe
- Purpose: Maintain proper iframe sizing
- Triggers:
- On initial load
- When content size changes
- After window load completes
-
linkReady Event
- Fired by: Iframe
- Indicates: iframe is fully ready for use
- Requirements:
- parentInformedAboutContentHeight must be true
- For booker pages: booker must be in ready state
- Actions:
- Parent removes loader
- Parent makes iframe visible
-
parentKnowsIframeReady Event
- Fired by: Parent
- Indicates: Parent acknowledges iframe readiness
- Actions:
- Makes body visible
- For prerendering: marks prerenderState as "completed"
Prerendering Flow
The prerendering flow follows a special path:
-
Initial State:
- prerenderState: null
-
During Prerender:
- prerenderState: "inProgress"
- Limited events allowed (only __iframeReady, __dimensionChanged)
- iframe and body remain hidden
-
After Connect:
- prerenderState: "completed"
- Full event flow enabled
- Visibility states updated
Command Queue System
The embed system implements a command queue to handle instructions before the iframe is ready:
-
Commands are queued if iframe isn't ready:
if (!this.iframeReady) { this.iframeDoQueue.push(doInIframeArg); return; } -
Queue is processed after __iframeReady event:
- All queued commands are executed in order
- New commands are executed immediately
Error Handling
Page Load Errors:
- System monitors CalComPageStatus
- On non-200 status: fires linkFailed event
- Includes error code and URL information