* 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>
202 lines
6.0 KiB
Markdown
202 lines
6.0 KiB
Markdown
# 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
|
|
|
|
```mermaid
|
|
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 created
|
|
- `INITIALIZED`: After __iframeReady event is processed
|
|
- `prerenderState`: Can be null | "inProgress" | "completed"
|
|
|
|
### Visibility States
|
|
1. Initial Creation:
|
|
- iframe.style.visibility = "hidden"
|
|
- body.style.visibility = "hidden"
|
|
|
|
2. After __iframeReady:
|
|
- iframe becomes visible (unless prerendering)
|
|
|
|
3. After parentKnowsIframeReady:
|
|
- body becomes visible
|
|
- Background remains transparent
|
|
|
|
## Event Details
|
|
|
|
1. **Initial Load**
|
|
- embed.js loads in parent page
|
|
- For inline embeds: Creates elements immediately
|
|
- For modal embeds: Waits for CTA click (unless prerendering)
|
|
|
|
2. **iframe Creation**
|
|
- iframe is created with `visibility: hidden`
|
|
- Loader is shown (default or skeleton)
|
|
- EmbedStore initialized
|
|
|
|
3. **__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
|
|
|
|
4. **__dimensionChanged Event**
|
|
- Fired by: Iframe
|
|
- Purpose: Maintain proper iframe sizing
|
|
- Triggers:
|
|
- On initial load
|
|
- When content size changes
|
|
- After window load completes
|
|
|
|
5. **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
|
|
|
|
6. **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:
|
|
|
|
1. Initial State:
|
|
- prerenderState: null
|
|
|
|
2. During Prerender:
|
|
- prerenderState: "inProgress"
|
|
- Limited events allowed (only __iframeReady, __dimensionChanged)
|
|
- iframe and body remain hidden
|
|
|
|
3. 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:
|
|
|
|
1. Commands are queued if iframe isn't ready:
|
|
```typescript
|
|
if (!this.iframeReady) {
|
|
this.iframeDoQueue.push(doInIframeArg);
|
|
return;
|
|
}
|
|
```
|
|
|
|
2. 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 |