@seatlayer/js 0.23.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -3
- package/dist/index.cjs +204 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +117 -10
- package/dist/index.d.ts +117 -10
- package/dist/index.js +204 -20
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -157,6 +157,15 @@ declare class SeatingChart {
|
|
|
157
157
|
constructor(options: SeatingChartOptions);
|
|
158
158
|
/** Fetch the chart, mount the renderer, seed statuses and go live. Idempotent. */
|
|
159
159
|
render(): Promise<this>;
|
|
160
|
+
/**
|
|
161
|
+
* Attribution badge pinned to the embed's bottom-right, linking to
|
|
162
|
+
* seatlayer.io. Rendered as an absolutely-positioned overlay with
|
|
163
|
+
* self-contained inline styles — the SDK embed ships no widget CSS, and an
|
|
164
|
+
* overlay keeps it out of the layout flow so it never disturbs the SDK v0.22
|
|
165
|
+
* fill-height resize contract. Mirrors the full widget's mark + wordmark and
|
|
166
|
+
* reuses the `picker.poweredBy` i18n string.
|
|
167
|
+
*/
|
|
168
|
+
private buildBadge;
|
|
160
169
|
private placeTooltip;
|
|
161
170
|
private updateTooltip;
|
|
162
171
|
/** Current selection with prices resolved from the chart categories. */
|
|
@@ -257,15 +266,28 @@ interface EmbeddedDesignerOptions {
|
|
|
257
266
|
/**
|
|
258
267
|
* How to size the iframe's height. The Designer is a full application (its
|
|
259
268
|
* shell is `position:fixed; height:100dvh`), not flowing content, so it should
|
|
260
|
-
* fill
|
|
269
|
+
* fill its box rather than be measured.
|
|
261
270
|
*
|
|
262
|
-
* - `'fill'` (default):
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
271
|
+
* - `'fill'` (default): container-aware. On mount the SDK probes whether the
|
|
272
|
+
* host gave the container a DEFINITE (bounded) height:
|
|
273
|
+
* - **Bounded container** (a fixed-height block, `height`/`max-height`,
|
|
274
|
+
* `flex:1; min-h:0`, a resolved `%`, etc.) → the iframe fills 100% of
|
|
275
|
+
* that block and tracks its size live via a `ResizeObserver`.
|
|
276
|
+
* - **Content-sized container** (the block collapses to whatever the iframe
|
|
277
|
+
* measures — typical full-page usage) → the iframe grows so its bottom
|
|
278
|
+
* edge reaches the bottom of the viewport (`window.innerHeight -
|
|
279
|
+
* iframe.top`), recomputed (rAF-throttled) on `resize` /
|
|
280
|
+
* `orientationchange` / `scroll`.
|
|
281
|
+
* Either way the result is clamped to `minHeight`. The verdict is cached but
|
|
282
|
+
* re-probed on `resize`/`orientationchange` so a responsive host layout can
|
|
283
|
+
* flip between the two. The legacy `seatlayer.designer.resize` message is
|
|
284
|
+
* ignored in `'fill'` mode: it is circular, because the fixed-position shell
|
|
285
|
+
* just echoes the iframe height.
|
|
267
286
|
* - a number: a fixed pixel height. In this mode the legacy resize message is
|
|
268
287
|
* still honoured (unless `autoResize` is `false`) so older hosts keep growing.
|
|
288
|
+
*
|
|
289
|
+
* All SDK-managed heights are written with `!important` priority so a host
|
|
290
|
+
* theme's `iframe { height: … !important }` cannot override them.
|
|
269
291
|
*/
|
|
270
292
|
height?: 'fill' | number;
|
|
271
293
|
/** Minimum height (px) that `'fill'` mode clamps to. Defaults to `480`. */
|
|
@@ -282,8 +304,30 @@ interface EmbeddedDesignerOptions {
|
|
|
282
304
|
* fresh Designer session and call `setDesignerUrl()` with the new URL, which
|
|
283
305
|
* recreates the iframe and returns to the loading state. When omitted, "Try
|
|
284
306
|
* again" reloads the current `designerUrl` in place.
|
|
307
|
+
*
|
|
308
|
+
* When supplied, it also powers automatic session renewal — see
|
|
309
|
+
* {@link EmbeddedDesignerOptions.autoRenewSession}.
|
|
285
310
|
*/
|
|
286
311
|
onRequestRelaunch?: () => void;
|
|
312
|
+
/**
|
|
313
|
+
* Keep long editing sessions alive without the user ever hitting the expiry
|
|
314
|
+
* wall. Designer sessions are short-lived security tokens; when the host wires
|
|
315
|
+
* `onRequestRelaunch` the SDK, with this enabled, will:
|
|
316
|
+
*
|
|
317
|
+
* - **Renew proactively.** From each `ready` message's `expiresAt` it schedules
|
|
318
|
+
* a silent relaunch shortly before the session lapses (~3 min ahead; for a
|
|
319
|
+
* TTL under 15 min it renews after 80% of the remaining life, and never
|
|
320
|
+
* sooner than 30s after `ready`). The host mints a fresh session and swaps
|
|
321
|
+
* `designerUrl`, so the editor keeps working with no error card.
|
|
322
|
+
* - **Recover on expiry.** If an expiry error still slips through (a slept
|
|
323
|
+
* laptop woke past the renewal window, say) it makes ONE automatic relaunch
|
|
324
|
+
* attempt before showing the "Try again" card, and only falls back to the
|
|
325
|
+
* card if that relaunch also fails.
|
|
326
|
+
*
|
|
327
|
+
* Defaults to `true` whenever `onRequestRelaunch` is provided; a no-op without
|
|
328
|
+
* it. Set `false` to keep the fully manual "Try again" behavior.
|
|
329
|
+
*/
|
|
330
|
+
autoRenewSession?: boolean;
|
|
287
331
|
onReady?: (message: EmbeddedDesignerMessage) => void;
|
|
288
332
|
onSaved?: (message: EmbeddedDesignerMessage) => void;
|
|
289
333
|
onPublished?: (message: EmbeddedDesignerMessage) => void;
|
|
@@ -297,6 +341,14 @@ declare class EmbeddedDesigner {
|
|
|
297
341
|
private designerOrigin;
|
|
298
342
|
private overlay;
|
|
299
343
|
private timeoutTimer;
|
|
344
|
+
/** Proactive session-renewal timer; armed from each `ready`, cleared on re-mount. */
|
|
345
|
+
private renewTimer;
|
|
346
|
+
/**
|
|
347
|
+
* One automatic recovery relaunch is allowed per expiry. Reset ONLY when a fresh
|
|
348
|
+
* `ready` arrives — deliberately not on re-mount — so a session that keeps failing
|
|
349
|
+
* to load can't loop the host through endless silent relaunches.
|
|
350
|
+
*/
|
|
351
|
+
private autoRecoverUsed;
|
|
300
352
|
private phase;
|
|
301
353
|
private restoreContainerPosition;
|
|
302
354
|
private pinned;
|
|
@@ -307,7 +359,14 @@ declare class EmbeddedDesigner {
|
|
|
307
359
|
/** Latest height (px string) the Designer reported; re-applied after unpin. */
|
|
308
360
|
private lastAutoHeight;
|
|
309
361
|
private fillRaf;
|
|
362
|
+
private reprobeRaf;
|
|
310
363
|
private fillListening;
|
|
364
|
+
/** Resolved container element (fill measurement + ResizeObserver target). */
|
|
365
|
+
private containerEl;
|
|
366
|
+
/** Cached fill verdict: 'container' = bounded block, 'viewport' = full page. */
|
|
367
|
+
private fillMode;
|
|
368
|
+
/** Live block-size tracking in container-fill mode; disconnected on destroy. */
|
|
369
|
+
private resizeObs;
|
|
311
370
|
constructor(options: EmbeddedDesignerOptions);
|
|
312
371
|
mount(): HTMLIFrameElement;
|
|
313
372
|
/** Replace the iframe instead of assigning a new fragment to an existing one. */
|
|
@@ -318,14 +377,39 @@ declare class EmbeddedDesigner {
|
|
|
318
377
|
private autoResizeEnabled;
|
|
319
378
|
/** Fill mode is the default; a numeric `height` opts into a fixed pixel box. */
|
|
320
379
|
private fillEnabled;
|
|
380
|
+
/** Write an SDK-managed height with `!important` so a host theme can't win. */
|
|
381
|
+
private setFrameHeight;
|
|
321
382
|
/**
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
*
|
|
383
|
+
* Decide whether the host gave the container a DEFINITE (bounded) height — a
|
|
384
|
+
* fixed block the embed should fill 100% of — versus a content-sized container
|
|
385
|
+
* that collapses to whatever the iframe measures (full-page usage).
|
|
386
|
+
*
|
|
387
|
+
* We drive the iframe to two extreme heights within a single synchronous task
|
|
388
|
+
* and watch whether the container follows: a bounded box barely moves, a
|
|
389
|
+
* content-sized one grows with the iframe. Because we restore the height before
|
|
390
|
+
* yielding, the browser only lays out — it never paints the extremes, so there
|
|
391
|
+
* is no visible flash. Works for px, resolved `%`, and flex (`flex:1;min-h:0`)
|
|
392
|
+
* heights, and leaves a mere `min-height` floor classified as content-sized so
|
|
393
|
+
* full-page hosts keep the old viewport-fill behavior.
|
|
394
|
+
*/
|
|
395
|
+
private detectFillMode;
|
|
396
|
+
/**
|
|
397
|
+
* Size the iframe for the current fill verdict, clamped to `minHeight`. In
|
|
398
|
+
* container mode it fills 100% of the bounded block; in viewport mode its
|
|
399
|
+
* bottom edge meets the bottom of the viewport (`window.innerHeight - top`).
|
|
400
|
+
* No-op while pinned fullscreen (the pin fills the viewport itself).
|
|
325
401
|
*/
|
|
326
402
|
private applyFill;
|
|
327
|
-
/** rAF-throttled fill recompute, so a burst of scroll/
|
|
403
|
+
/** rAF-throttled fill recompute, so a burst of scroll/RO ticks coalesces. */
|
|
328
404
|
private scheduleFill;
|
|
405
|
+
/**
|
|
406
|
+
* rAF-throttled re-probe: a host layout change (responsive breakpoint, a block
|
|
407
|
+
* gaining/losing a definite height) can flip the verdict, so `resize` /
|
|
408
|
+
* `orientationchange` re-detect and swap the container observer accordingly.
|
|
409
|
+
*/
|
|
410
|
+
private scheduleReprobe;
|
|
411
|
+
/** Attach/detach the container ResizeObserver to match the current verdict. */
|
|
412
|
+
private syncContainerObserver;
|
|
329
413
|
private startFill;
|
|
330
414
|
private stopFill;
|
|
331
415
|
/**
|
|
@@ -337,6 +421,29 @@ declare class EmbeddedDesigner {
|
|
|
337
421
|
/** Undo `pinFullscreen`: restore the iframe style + scroll lock. Idempotent. */
|
|
338
422
|
private unpinFullscreen;
|
|
339
423
|
private clearTimeoutTimer;
|
|
424
|
+
/**
|
|
425
|
+
* Auto-renewal (proactive + one expiry recovery) is on when the host wired a
|
|
426
|
+
* relaunch hook and did not opt out. Without the hook there is nothing to call,
|
|
427
|
+
* so it is a no-op.
|
|
428
|
+
*/
|
|
429
|
+
private autoRenewEnabled;
|
|
430
|
+
private clearRenewTimer;
|
|
431
|
+
/**
|
|
432
|
+
* Arm the proactive renewal timer from a `ready` message's `expiresAt` (epoch
|
|
433
|
+
* ms). We relaunch a comfortable lead before expiry so the host can mint a fresh
|
|
434
|
+
* session and swap `designerUrl` without the user ever seeing the expiry card:
|
|
435
|
+
*
|
|
436
|
+
* - normal TTL (≥ 15 min): renew {@link RENEW_LEAD_MS} (~3 min) before expiry;
|
|
437
|
+
* - short TTL (< 15 min): renew after {@link RENEW_SHORT_TTL_FRACTION} (80%) of
|
|
438
|
+
* the remaining life, so the lead can't overshoot the whole session;
|
|
439
|
+
* - either way, never sooner than {@link RENEW_MIN_DELAY_MS} (30s) after `ready`
|
|
440
|
+
* so a burst of `ready` messages can't spin the host.
|
|
441
|
+
*
|
|
442
|
+
* Re-armed on every `ready`; cleared on destroy / setDesignerUrl (via re-mount).
|
|
443
|
+
* A no-op when auto-renewal is off or `expiresAt` is missing/already past — the
|
|
444
|
+
* expiry-error path recovers a session that has already lapsed.
|
|
445
|
+
*/
|
|
446
|
+
private scheduleRenewal;
|
|
340
447
|
private ensureContainerPositioned;
|
|
341
448
|
private restoreContainerStyle;
|
|
342
449
|
private removeOverlay;
|
package/dist/index.d.ts
CHANGED
|
@@ -157,6 +157,15 @@ declare class SeatingChart {
|
|
|
157
157
|
constructor(options: SeatingChartOptions);
|
|
158
158
|
/** Fetch the chart, mount the renderer, seed statuses and go live. Idempotent. */
|
|
159
159
|
render(): Promise<this>;
|
|
160
|
+
/**
|
|
161
|
+
* Attribution badge pinned to the embed's bottom-right, linking to
|
|
162
|
+
* seatlayer.io. Rendered as an absolutely-positioned overlay with
|
|
163
|
+
* self-contained inline styles — the SDK embed ships no widget CSS, and an
|
|
164
|
+
* overlay keeps it out of the layout flow so it never disturbs the SDK v0.22
|
|
165
|
+
* fill-height resize contract. Mirrors the full widget's mark + wordmark and
|
|
166
|
+
* reuses the `picker.poweredBy` i18n string.
|
|
167
|
+
*/
|
|
168
|
+
private buildBadge;
|
|
160
169
|
private placeTooltip;
|
|
161
170
|
private updateTooltip;
|
|
162
171
|
/** Current selection with prices resolved from the chart categories. */
|
|
@@ -257,15 +266,28 @@ interface EmbeddedDesignerOptions {
|
|
|
257
266
|
/**
|
|
258
267
|
* How to size the iframe's height. The Designer is a full application (its
|
|
259
268
|
* shell is `position:fixed; height:100dvh`), not flowing content, so it should
|
|
260
|
-
* fill
|
|
269
|
+
* fill its box rather than be measured.
|
|
261
270
|
*
|
|
262
|
-
* - `'fill'` (default):
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
271
|
+
* - `'fill'` (default): container-aware. On mount the SDK probes whether the
|
|
272
|
+
* host gave the container a DEFINITE (bounded) height:
|
|
273
|
+
* - **Bounded container** (a fixed-height block, `height`/`max-height`,
|
|
274
|
+
* `flex:1; min-h:0`, a resolved `%`, etc.) → the iframe fills 100% of
|
|
275
|
+
* that block and tracks its size live via a `ResizeObserver`.
|
|
276
|
+
* - **Content-sized container** (the block collapses to whatever the iframe
|
|
277
|
+
* measures — typical full-page usage) → the iframe grows so its bottom
|
|
278
|
+
* edge reaches the bottom of the viewport (`window.innerHeight -
|
|
279
|
+
* iframe.top`), recomputed (rAF-throttled) on `resize` /
|
|
280
|
+
* `orientationchange` / `scroll`.
|
|
281
|
+
* Either way the result is clamped to `minHeight`. The verdict is cached but
|
|
282
|
+
* re-probed on `resize`/`orientationchange` so a responsive host layout can
|
|
283
|
+
* flip between the two. The legacy `seatlayer.designer.resize` message is
|
|
284
|
+
* ignored in `'fill'` mode: it is circular, because the fixed-position shell
|
|
285
|
+
* just echoes the iframe height.
|
|
267
286
|
* - a number: a fixed pixel height. In this mode the legacy resize message is
|
|
268
287
|
* still honoured (unless `autoResize` is `false`) so older hosts keep growing.
|
|
288
|
+
*
|
|
289
|
+
* All SDK-managed heights are written with `!important` priority so a host
|
|
290
|
+
* theme's `iframe { height: … !important }` cannot override them.
|
|
269
291
|
*/
|
|
270
292
|
height?: 'fill' | number;
|
|
271
293
|
/** Minimum height (px) that `'fill'` mode clamps to. Defaults to `480`. */
|
|
@@ -282,8 +304,30 @@ interface EmbeddedDesignerOptions {
|
|
|
282
304
|
* fresh Designer session and call `setDesignerUrl()` with the new URL, which
|
|
283
305
|
* recreates the iframe and returns to the loading state. When omitted, "Try
|
|
284
306
|
* again" reloads the current `designerUrl` in place.
|
|
307
|
+
*
|
|
308
|
+
* When supplied, it also powers automatic session renewal — see
|
|
309
|
+
* {@link EmbeddedDesignerOptions.autoRenewSession}.
|
|
285
310
|
*/
|
|
286
311
|
onRequestRelaunch?: () => void;
|
|
312
|
+
/**
|
|
313
|
+
* Keep long editing sessions alive without the user ever hitting the expiry
|
|
314
|
+
* wall. Designer sessions are short-lived security tokens; when the host wires
|
|
315
|
+
* `onRequestRelaunch` the SDK, with this enabled, will:
|
|
316
|
+
*
|
|
317
|
+
* - **Renew proactively.** From each `ready` message's `expiresAt` it schedules
|
|
318
|
+
* a silent relaunch shortly before the session lapses (~3 min ahead; for a
|
|
319
|
+
* TTL under 15 min it renews after 80% of the remaining life, and never
|
|
320
|
+
* sooner than 30s after `ready`). The host mints a fresh session and swaps
|
|
321
|
+
* `designerUrl`, so the editor keeps working with no error card.
|
|
322
|
+
* - **Recover on expiry.** If an expiry error still slips through (a slept
|
|
323
|
+
* laptop woke past the renewal window, say) it makes ONE automatic relaunch
|
|
324
|
+
* attempt before showing the "Try again" card, and only falls back to the
|
|
325
|
+
* card if that relaunch also fails.
|
|
326
|
+
*
|
|
327
|
+
* Defaults to `true` whenever `onRequestRelaunch` is provided; a no-op without
|
|
328
|
+
* it. Set `false` to keep the fully manual "Try again" behavior.
|
|
329
|
+
*/
|
|
330
|
+
autoRenewSession?: boolean;
|
|
287
331
|
onReady?: (message: EmbeddedDesignerMessage) => void;
|
|
288
332
|
onSaved?: (message: EmbeddedDesignerMessage) => void;
|
|
289
333
|
onPublished?: (message: EmbeddedDesignerMessage) => void;
|
|
@@ -297,6 +341,14 @@ declare class EmbeddedDesigner {
|
|
|
297
341
|
private designerOrigin;
|
|
298
342
|
private overlay;
|
|
299
343
|
private timeoutTimer;
|
|
344
|
+
/** Proactive session-renewal timer; armed from each `ready`, cleared on re-mount. */
|
|
345
|
+
private renewTimer;
|
|
346
|
+
/**
|
|
347
|
+
* One automatic recovery relaunch is allowed per expiry. Reset ONLY when a fresh
|
|
348
|
+
* `ready` arrives — deliberately not on re-mount — so a session that keeps failing
|
|
349
|
+
* to load can't loop the host through endless silent relaunches.
|
|
350
|
+
*/
|
|
351
|
+
private autoRecoverUsed;
|
|
300
352
|
private phase;
|
|
301
353
|
private restoreContainerPosition;
|
|
302
354
|
private pinned;
|
|
@@ -307,7 +359,14 @@ declare class EmbeddedDesigner {
|
|
|
307
359
|
/** Latest height (px string) the Designer reported; re-applied after unpin. */
|
|
308
360
|
private lastAutoHeight;
|
|
309
361
|
private fillRaf;
|
|
362
|
+
private reprobeRaf;
|
|
310
363
|
private fillListening;
|
|
364
|
+
/** Resolved container element (fill measurement + ResizeObserver target). */
|
|
365
|
+
private containerEl;
|
|
366
|
+
/** Cached fill verdict: 'container' = bounded block, 'viewport' = full page. */
|
|
367
|
+
private fillMode;
|
|
368
|
+
/** Live block-size tracking in container-fill mode; disconnected on destroy. */
|
|
369
|
+
private resizeObs;
|
|
311
370
|
constructor(options: EmbeddedDesignerOptions);
|
|
312
371
|
mount(): HTMLIFrameElement;
|
|
313
372
|
/** Replace the iframe instead of assigning a new fragment to an existing one. */
|
|
@@ -318,14 +377,39 @@ declare class EmbeddedDesigner {
|
|
|
318
377
|
private autoResizeEnabled;
|
|
319
378
|
/** Fill mode is the default; a numeric `height` opts into a fixed pixel box. */
|
|
320
379
|
private fillEnabled;
|
|
380
|
+
/** Write an SDK-managed height with `!important` so a host theme can't win. */
|
|
381
|
+
private setFrameHeight;
|
|
321
382
|
/**
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
*
|
|
383
|
+
* Decide whether the host gave the container a DEFINITE (bounded) height — a
|
|
384
|
+
* fixed block the embed should fill 100% of — versus a content-sized container
|
|
385
|
+
* that collapses to whatever the iframe measures (full-page usage).
|
|
386
|
+
*
|
|
387
|
+
* We drive the iframe to two extreme heights within a single synchronous task
|
|
388
|
+
* and watch whether the container follows: a bounded box barely moves, a
|
|
389
|
+
* content-sized one grows with the iframe. Because we restore the height before
|
|
390
|
+
* yielding, the browser only lays out — it never paints the extremes, so there
|
|
391
|
+
* is no visible flash. Works for px, resolved `%`, and flex (`flex:1;min-h:0`)
|
|
392
|
+
* heights, and leaves a mere `min-height` floor classified as content-sized so
|
|
393
|
+
* full-page hosts keep the old viewport-fill behavior.
|
|
394
|
+
*/
|
|
395
|
+
private detectFillMode;
|
|
396
|
+
/**
|
|
397
|
+
* Size the iframe for the current fill verdict, clamped to `minHeight`. In
|
|
398
|
+
* container mode it fills 100% of the bounded block; in viewport mode its
|
|
399
|
+
* bottom edge meets the bottom of the viewport (`window.innerHeight - top`).
|
|
400
|
+
* No-op while pinned fullscreen (the pin fills the viewport itself).
|
|
325
401
|
*/
|
|
326
402
|
private applyFill;
|
|
327
|
-
/** rAF-throttled fill recompute, so a burst of scroll/
|
|
403
|
+
/** rAF-throttled fill recompute, so a burst of scroll/RO ticks coalesces. */
|
|
328
404
|
private scheduleFill;
|
|
405
|
+
/**
|
|
406
|
+
* rAF-throttled re-probe: a host layout change (responsive breakpoint, a block
|
|
407
|
+
* gaining/losing a definite height) can flip the verdict, so `resize` /
|
|
408
|
+
* `orientationchange` re-detect and swap the container observer accordingly.
|
|
409
|
+
*/
|
|
410
|
+
private scheduleReprobe;
|
|
411
|
+
/** Attach/detach the container ResizeObserver to match the current verdict. */
|
|
412
|
+
private syncContainerObserver;
|
|
329
413
|
private startFill;
|
|
330
414
|
private stopFill;
|
|
331
415
|
/**
|
|
@@ -337,6 +421,29 @@ declare class EmbeddedDesigner {
|
|
|
337
421
|
/** Undo `pinFullscreen`: restore the iframe style + scroll lock. Idempotent. */
|
|
338
422
|
private unpinFullscreen;
|
|
339
423
|
private clearTimeoutTimer;
|
|
424
|
+
/**
|
|
425
|
+
* Auto-renewal (proactive + one expiry recovery) is on when the host wired a
|
|
426
|
+
* relaunch hook and did not opt out. Without the hook there is nothing to call,
|
|
427
|
+
* so it is a no-op.
|
|
428
|
+
*/
|
|
429
|
+
private autoRenewEnabled;
|
|
430
|
+
private clearRenewTimer;
|
|
431
|
+
/**
|
|
432
|
+
* Arm the proactive renewal timer from a `ready` message's `expiresAt` (epoch
|
|
433
|
+
* ms). We relaunch a comfortable lead before expiry so the host can mint a fresh
|
|
434
|
+
* session and swap `designerUrl` without the user ever seeing the expiry card:
|
|
435
|
+
*
|
|
436
|
+
* - normal TTL (≥ 15 min): renew {@link RENEW_LEAD_MS} (~3 min) before expiry;
|
|
437
|
+
* - short TTL (< 15 min): renew after {@link RENEW_SHORT_TTL_FRACTION} (80%) of
|
|
438
|
+
* the remaining life, so the lead can't overshoot the whole session;
|
|
439
|
+
* - either way, never sooner than {@link RENEW_MIN_DELAY_MS} (30s) after `ready`
|
|
440
|
+
* so a burst of `ready` messages can't spin the host.
|
|
441
|
+
*
|
|
442
|
+
* Re-armed on every `ready`; cleared on destroy / setDesignerUrl (via re-mount).
|
|
443
|
+
* A no-op when auto-renewal is off or `expiresAt` is missing/already past — the
|
|
444
|
+
* expiry-error path recovers a session that has already lapsed.
|
|
445
|
+
*/
|
|
446
|
+
private scheduleRenewal;
|
|
340
447
|
private ensureContainerPositioned;
|
|
341
448
|
private restoreContainerStyle;
|
|
342
449
|
private removeOverlay;
|