@flamingo-stack/openframe-frontend-core 0.0.734 → 0.0.735
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/dist/build/export-map.json +1 -1
- package/dist/{chunk-4V672TEI.cjs → chunk-36CCUJOE.cjs} +406 -353
- package/dist/{chunk-2OHBH6PS.cjs → chunk-3FZZPR76.cjs} +42 -42
- package/dist/{chunk-JRC3KXKV.cjs → chunk-3JP2OVH3.cjs} +30 -30
- package/dist/{chunk-4Q34V7MD.cjs → chunk-3X4N3IT7.cjs} +18 -18
- package/dist/{chunk-R65UD6BH.cjs → chunk-4F7V2MAC.cjs} +12 -12
- package/dist/{chunk-AOTOOGNX.cjs → chunk-6TTAILSV.cjs} +3 -3
- package/dist/{chunk-OV7QQHLG.cjs → chunk-7HT3VHLJ.cjs} +17 -17
- package/dist/{chunk-3NANWZO3.cjs → chunk-EQ7OOK4B.cjs} +11 -11
- package/dist/{chunk-CMUEFHM3.cjs → chunk-EQH7BUNS.cjs} +4 -4
- package/dist/{chunk-EMBH2EJO.cjs → chunk-F7STMHT7.cjs} +65 -65
- package/dist/{chunk-D34BLEIR.cjs → chunk-HLBFTDUL.cjs} +2 -2
- package/dist/{chunk-HAWQA5FI.cjs → chunk-JDXQ6T5P.cjs} +128 -112
- package/dist/{chunk-73ZW3265.cjs → chunk-MRVZ56GT.cjs} +79 -79
- package/dist/{chunk-5DDFSGCE.cjs → chunk-NVCSVGNI.cjs} +33 -33
- package/dist/{chunk-DHIISS4W.cjs → chunk-RH3AKULV.cjs} +6 -6
- package/dist/{chunk-TLQQP2EL.cjs → chunk-SHQZN5LF.cjs} +6 -6
- package/dist/{chunk-L7WJBJU7.cjs → chunk-SZRZBCWC.cjs} +67 -67
- package/dist/{chunk-FA5SMA7L.cjs → chunk-T323E2Y6.cjs} +4 -4
- package/dist/{chunk-5OGT7H2S.cjs → chunk-TUMUT7CV.cjs} +15 -15
- package/dist/{chunk-BP6R5WDW.cjs → chunk-VA7OMDZO.cjs} +41 -23
- package/dist/{chunk-KSXZABGH.cjs → chunk-W6E7XCBI.cjs} +38 -38
- package/dist/{cloud-tenants-HU7YZD33.cjs → cloud-tenants-H5D57P4U.cjs} +7 -7
- package/dist/components/case-studies/index.cjs +19 -19
- package/dist/components/chat/entity-cards/program-card.d.ts.map +1 -1
- package/dist/components/chat/entity-cards/program-card.js +6 -6
- package/dist/components/chat/index.cjs +5 -5
- package/dist/components/contact/index.cjs +8 -8
- package/dist/components/docs/index.cjs +11 -11
- package/dist/components/embeds/index.cjs +8 -8
- package/dist/components/faq/index.cjs +8 -8
- package/dist/components/features/cards-strip.d.ts.map +1 -1
- package/dist/components/features/cards-strip.js +6 -2
- package/dist/components/features/index.cjs +7 -7
- package/dist/components/features/video-bites-strip.d.ts +6 -1
- package/dist/components/features/video-bites-strip.d.ts.map +1 -1
- package/dist/components/features/video-bites-strip.js +15 -3
- package/dist/components/help-center-pages/index.cjs +106 -106
- package/dist/components/index.cjs +61 -55
- package/dist/components/meeting-scheduler/index.cjs +29 -29
- package/dist/components/navigation/index.cjs +10 -10
- package/dist/components/onboarding-guides/index.cjs +10 -10
- package/dist/components/product-demo/index.cjs +6 -6
- package/dist/components/related-content/index.cjs +4 -4
- package/dist/components/tickets/index.cjs +11 -11
- package/dist/components/ui/fade-preview.d.ts +5 -1
- package/dist/components/ui/fade-preview.d.ts.map +1 -1
- package/dist/components/ui/fade-preview.js +18 -1
- package/dist/components/ui/index.cjs +13 -7
- package/dist/components/ui/index.d.ts +1 -0
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +1 -0
- package/dist/components/ui/layout-hold.d.ts +31 -0
- package/dist/components/ui/layout-hold.d.ts.map +1 -0
- package/dist/components/ui/layout-hold.js +25 -0
- package/dist/components/ui/snap-carousel.d.ts.map +1 -1
- package/dist/components/ui/snap-carousel.js +28 -15
- package/dist/{devices-CKLN7BHY.cjs → devices-SQTEXY2H.cjs} +8 -8
- package/dist/{embeddable-chat-FTAX4SVV.cjs → embeddable-chat-S5ODWE3L.cjs} +71 -71
- package/dist/hooks/index.cjs +4 -2
- package/dist/hooks/ui/index.d.ts +1 -0
- package/dist/hooks/ui/index.d.ts.map +1 -1
- package/dist/hooks/ui/index.js +1 -0
- package/dist/hooks/ui/use-resumable-timeout.d.ts +22 -0
- package/dist/hooks/ui/use-resumable-timeout.d.ts.map +1 -0
- package/dist/hooks/ui/use-resumable-timeout.js +26 -0
- package/dist/hooks/use-scenario-player.d.ts +4 -3
- package/dist/hooks/use-scenario-player.d.ts.map +1 -1
- package/dist/hooks/use-scenario-player.js +17 -23
- package/dist/index.cjs +19 -11
- package/dist/{knowledge-NRLHSCC5.cjs → knowledge-FO3TPLFO.cjs} +8 -8
- package/dist/{logs-BR6SLYAF.cjs → logs-Y4WQB2YR.cjs} +15 -15
- package/dist/{policies-MQRXBYG2.cjs → policies-D6VY2ODF.cjs} +11 -11
- package/dist/{software-update-RUGIQP7N.cjs → software-update-7XN6U7HC.cjs} +10 -10
- package/package.json +1 -1
- package/src/components/chat/entity-cards/program-card.tsx +9 -8
- package/src/components/features/cards-strip.tsx +11 -2
- package/src/components/features/video-bites-strip.tsx +22 -3
- package/src/components/ui/fade-preview.tsx +30 -1
- package/src/components/ui/index.ts +1 -0
- package/src/components/ui/layout-hold.tsx +55 -0
- package/src/components/ui/snap-carousel.tsx +36 -20
- package/src/hooks/ui/index.ts +1 -0
- package/src/hooks/ui/use-resumable-timeout.ts +55 -0
- package/src/hooks/use-scenario-player.ts +28 -32
package/src/hooks/ui/index.ts
CHANGED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect, useRef, useState } from 'react';
|
|
4
|
+
|
|
5
|
+
export interface UseResumableTimeoutOptions {
|
|
6
|
+
/** The wait counts down only while this is true. */
|
|
7
|
+
running: boolean;
|
|
8
|
+
/** How long the whole wait is. */
|
|
9
|
+
durationMs: number;
|
|
10
|
+
/** A new value starts the wait over from nothing (the slide changed). */
|
|
11
|
+
resetKey: string | number;
|
|
12
|
+
/** Called once the whole wait has been run. */
|
|
13
|
+
onElapsed: () => void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A wait that PAUSES instead of starting over: `durationMs` of time spent
|
|
18
|
+
* `running`, however many times it is interrupted. A carousel that scrolls off
|
|
19
|
+
* screen half-way through a slide comes back with half a slide left, not a
|
|
20
|
+
* whole one, and the bar that shows the wait picks up where it stopped.
|
|
21
|
+
*
|
|
22
|
+
* Returns how much of the wait had been run at the last stop (0 after a
|
|
23
|
+
* reset), which is what a progress bar draws while it is not running and
|
|
24
|
+
* where it resumes from.
|
|
25
|
+
*/
|
|
26
|
+
export function useResumableTimeout({ running, durationMs, resetKey, onElapsed }: UseResumableTimeoutOptions): number {
|
|
27
|
+
// What has been run so far, for the key it was run under. The ref is the
|
|
28
|
+
// clock's own memory (read when a stretch starts); the state is the same
|
|
29
|
+
// figure for whoever draws it.
|
|
30
|
+
const banked = useRef({ key: resetKey, ms: 0 });
|
|
31
|
+
const [shown, setShown] = useState({ key: resetKey, ms: 0 });
|
|
32
|
+
|
|
33
|
+
const onElapsedRef = useRef(onElapsed);
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
onElapsedRef.current = onElapsed;
|
|
36
|
+
}, [onElapsed]);
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
// A new key: the wait starts over.
|
|
40
|
+
if (banked.current.key !== resetKey) banked.current = { key: resetKey, ms: 0 };
|
|
41
|
+
if (!running) return undefined;
|
|
42
|
+
const startedAt = Date.now();
|
|
43
|
+
const timer = setTimeout(() => onElapsedRef.current(), Math.max(0, durationMs - banked.current.ms));
|
|
44
|
+
return () => {
|
|
45
|
+
clearTimeout(timer);
|
|
46
|
+
// Bank what this stretch ran.
|
|
47
|
+
const ms = Math.min(durationMs, banked.current.ms + (Date.now() - startedAt));
|
|
48
|
+
banked.current = { key: resetKey, ms };
|
|
49
|
+
setShown({ key: resetKey, ms });
|
|
50
|
+
};
|
|
51
|
+
}, [running, durationMs, resetKey]);
|
|
52
|
+
|
|
53
|
+
// Under another key (the slide changed) nothing has been run yet.
|
|
54
|
+
return shown.key === resetKey ? shown.ms : 0;
|
|
55
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useCallback,
|
|
3
|
+
import { useCallback, useState } from 'react';
|
|
4
4
|
import { type AutoplayHoldProps, useAutoplay } from './ui/use-autoplay';
|
|
5
|
+
import { useResumableTimeout } from './ui/use-resumable-timeout';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* How soon the first step follows the moment the demo becomes playable (it
|
|
@@ -78,9 +79,10 @@ export interface UseScenarioPlayerResult {
|
|
|
78
79
|
* not held by the visitor, motion allowed. Under reduced motion it parks on the last step
|
|
79
80
|
* of the current scenario, and every scenario can still be read by choosing it.
|
|
80
81
|
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
82
|
+
* A step is `stepMs` of time spent playing: an interruption pauses it and it
|
|
83
|
+
* resumes with what was left (`useResumableTimeout`, the one clock every timed
|
|
84
|
+
* thing here runs on). At the top of a scenario whose first step is the empty
|
|
85
|
+
* stage, that step is left within `START_MS`.
|
|
84
86
|
*
|
|
85
87
|
* A visitor's own choice (`go`, `setStep`) moves the clock there and lets go of
|
|
86
88
|
* any hold; the rotation carries on from that point.
|
|
@@ -110,34 +112,28 @@ export function useScenarioPlayer({
|
|
|
110
112
|
const [started, setStarted] = useState(false);
|
|
111
113
|
if (playing && !started) setStarted(true);
|
|
112
114
|
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
},
|
|
137
|
-
atEnd ? holdMs : quickStart ? Math.min(START_MS, stepMs) : stepMs,
|
|
138
|
-
);
|
|
139
|
-
return () => clearTimeout(timer);
|
|
140
|
-
}, [playing, rawStep, lastStep, stepMs, holdMs, scenario, scenarioCount, emptyFirstStep]);
|
|
115
|
+
// ONE clock for everything that waits and moves on (`useResumableTimeout`,
|
|
116
|
+
// the carousel's too): a step is `stepMs` of time spent PLAYING. Interrupted
|
|
117
|
+
// (off screen, held, another tab), it comes back with what was left of the
|
|
118
|
+
// step, never a whole new one and never a skipped one.
|
|
119
|
+
const atEnd = rawStep >= lastStep;
|
|
120
|
+
// Step 0 of a scenario whose first step is the empty stage is left at once:
|
|
121
|
+
// a stage that sits empty for a whole step after a tap reads as not
|
|
122
|
+
// responding. A finished scenario holds its full time: it is there to be read.
|
|
123
|
+
const leavesAtOnce = emptyFirstStep && rawStep === 0 && !atEnd;
|
|
124
|
+
useResumableTimeout({
|
|
125
|
+
running: playing,
|
|
126
|
+
durationMs: atEnd ? holdMs : leavesAtOnce ? Math.min(START_MS, stepMs) : stepMs,
|
|
127
|
+
resetKey: `${scenario}:${Math.min(rawStep, lastStep)}`,
|
|
128
|
+
onElapsed: () => {
|
|
129
|
+
if (atEnd) {
|
|
130
|
+
setScenario(current => (current + 1) % scenarioCount);
|
|
131
|
+
setRawStep(0);
|
|
132
|
+
} else {
|
|
133
|
+
setRawStep(current => Math.min(current, lastStep) + 1);
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
});
|
|
141
137
|
|
|
142
138
|
// A visitor's choice is an instruction to play from there: it lets go of any hold.
|
|
143
139
|
const setStep = useCallback(
|