@wix/editor-react-components 1.2761.0 → 1.2763.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.
Files changed (163) hide show
  1. package/dist/site/components/AccordionComponent/component.js +1 -1
  2. package/dist/site/components/AccordionComponent/manifest.js +1 -1
  3. package/dist/site/components/AnimatedIcon/manifest.js +1 -1
  4. package/dist/site/components/AudioPlayer/component.js +1 -1
  5. package/dist/site/components/AudioPlayer/manifest.js +1 -1
  6. package/dist/site/components/BoxContainer/component.js +3 -3
  7. package/dist/site/components/BoxContainer/manifest.js +1 -1
  8. package/dist/site/components/Breadcrumbs/component.js +3 -3
  9. package/dist/site/components/Breadcrumbs/manifest.js +1 -1
  10. package/dist/site/components/Button/manifest.js +1 -1
  11. package/dist/site/components/Checkbox/component.js +1 -1
  12. package/dist/site/components/Checkbox/manifest.js +1 -1
  13. package/dist/site/components/CheckboxGroup/component.js +1 -1
  14. package/dist/site/components/CheckboxGroup/manifest.js +1 -1
  15. package/dist/site/components/CollapsibleText/component.js +2 -2
  16. package/dist/site/components/CollapsibleText/manifest.js +1 -1
  17. package/dist/site/components/DatePicker/component.js +2 -2
  18. package/dist/site/components/DatePicker/manifest.js +1 -1
  19. package/dist/site/components/Dropdown/component.js +2 -2
  20. package/dist/site/components/Dropdown/manifest.js +1 -1
  21. package/dist/site/components/GoogleMap/component.js +3 -3
  22. package/dist/site/components/HTMLComponent/component.js +2 -2
  23. package/dist/site/components/HeadingTextBlock/component.js +1 -1
  24. package/dist/site/components/HeadingTextBlock/manifest.js +1 -1
  25. package/dist/site/components/HipaaIcon/component.js +2 -2
  26. package/dist/site/components/HipaaIcon/manifest.js +1 -1
  27. package/dist/site/components/Image3/component.js +2 -2
  28. package/dist/site/components/ImageReveal/component.js +2 -2
  29. package/dist/site/components/ImageReveal/manifest.js +1 -1
  30. package/dist/site/components/Line/component.js +1 -1
  31. package/dist/site/components/LinkBar/component.js +2 -2
  32. package/dist/site/components/LinkBar/manifest.js +1 -1
  33. package/dist/site/components/Logo/component.js +1 -1
  34. package/dist/site/components/Logo/manifest.js +1 -1
  35. package/dist/site/components/Logo/sdk.js +1 -1
  36. package/dist/site/components/Lottie/component.js +3 -3
  37. package/dist/site/components/Lottie/manifest.js +1 -1
  38. package/dist/site/components/MarkdownBlock/component.js +2 -2
  39. package/dist/site/components/MarkdownBlock/manifest.js +1 -1
  40. package/dist/site/components/Menu/component.js +3 -3
  41. package/dist/site/components/Menu/manifest.js +2 -3
  42. package/dist/site/components/MultiStateBox/component.js +1 -1
  43. package/dist/site/components/MultiStateBox/manifest.js +1 -1
  44. package/dist/site/components/ProgressBar/component.js +1 -1
  45. package/dist/site/components/ProgressBar/manifest.js +1 -1
  46. package/dist/site/components/ProgressBar/sdk.js +1 -1
  47. package/dist/site/components/RadioButtons/component.js +1 -1
  48. package/dist/site/components/RadioButtons/manifest.js +1 -1
  49. package/dist/site/components/Repeater/component.js +2 -2
  50. package/dist/site/components/Repeater/manifest.js +1 -1
  51. package/dist/site/components/ShareButtons/component.js +2 -2
  52. package/dist/site/components/ShareButtons/manifest.js +1 -1
  53. package/dist/site/components/Slideshow/component.js +1 -1
  54. package/dist/site/components/Tabs/component.js +1 -1
  55. package/dist/site/components/Tabs/manifest.js +1 -1
  56. package/dist/site/components/TextBox/component.js +1 -1
  57. package/dist/site/components/TextBox/manifest.js +1 -1
  58. package/dist/site/components/TextEffects3d/component.js +1 -1
  59. package/dist/site/components/TextEffects3d/manifest.js +1 -1
  60. package/dist/site/components/TextEffectsBauhaus/component.js +1 -1
  61. package/dist/site/components/TextEffectsBauhaus/manifest.js +1 -1
  62. package/dist/site/components/TextEffectsGlass/component.js +1 -1
  63. package/dist/site/components/TextEffectsGlass/manifest.js +1 -1
  64. package/dist/site/components/TextEffectsGlitch/component.js +1 -1
  65. package/dist/site/components/TextEffectsGlitch/manifest.js +1 -1
  66. package/dist/site/components/TextEffectsLetterPress/component.js +1 -1
  67. package/dist/site/components/TextEffectsLetterPress/manifest.js +1 -1
  68. package/dist/site/components/TextEffectsMatrix/component.js +1 -1
  69. package/dist/site/components/TextEffectsMatrix/manifest.js +1 -1
  70. package/dist/site/components/TextEffectsNeonSign/component.js +1 -1
  71. package/dist/site/components/TextEffectsNeonSign/manifest.js +1 -1
  72. package/dist/site/components/TextEffectsNoisy/component.js +1 -1
  73. package/dist/site/components/TextEffectsNoisy/manifest.js +1 -1
  74. package/dist/site/components/TextEffectsOutlineOut/component.js +2 -2
  75. package/dist/site/components/TextEffectsOutlineOut/manifest.js +1 -1
  76. package/dist/site/components/TextEffectsRetro/component.js +1 -1
  77. package/dist/site/components/TextEffectsRetro/manifest.js +1 -1
  78. package/dist/site/components/TextEffectsShook/component.js +1 -1
  79. package/dist/site/components/TextEffectsShook/manifest.js +1 -1
  80. package/dist/site/components/TextEffectsSticker/component.js +1 -1
  81. package/dist/site/components/TextEffectsSticker/manifest.js +2 -2
  82. package/dist/site/components/TextEffectsStriped/component.js +1 -1
  83. package/dist/site/components/TextEffectsStriped/manifest.js +1 -1
  84. package/dist/site/components/TextInput/component.js +2 -2
  85. package/dist/site/components/TextInput/manifest.js +1 -1
  86. package/dist/site/components/TextMarquee/component.js +1 -1
  87. package/dist/site/components/TimePicker/component.js +2 -2
  88. package/dist/site/components/TimePicker/manifest.js +1 -1
  89. package/dist/site/components/TransparentVideo/component.js +2 -2
  90. package/dist/site/components/VideoScrub/VideoScrub.types.d.ts +37 -0
  91. package/dist/site/components/VideoScrub/component.js +334 -34
  92. package/dist/site/components/VideoScrub/constants.d.ts +8 -3
  93. package/dist/site/components/VideoScrub/css.css +75 -2
  94. package/dist/site/components/VideoScrub/hooks/useScrubProgress.d.ts +4 -2
  95. package/dist/site/components/VideoScrub/hooks/useTimeframes.d.ts +23 -0
  96. package/dist/site/components/VideoScrub/manifest.js +268 -6
  97. package/dist/site/components/VideoScrub/timeframes/index.d.ts +1 -1
  98. package/dist/site/components/VideoScrub/timeframes/types.d.ts +1 -1
  99. package/dist/site/components/VideoScrub/timeframes/useActiveTimeframeIndex.d.ts +2 -0
  100. package/dist/site/components/VideoScrub/utils.d.ts +19 -5
  101. package/dist/site/components/chunks/AnimatedIcon.js +1 -1
  102. package/dist/site/components/chunks/Button.js +2 -2
  103. package/dist/site/components/chunks/Image.js +1 -1
  104. package/dist/site/components/chunks/Link.js +1 -1
  105. package/dist/site/components/chunks/Patterns.js +1 -1
  106. package/dist/site/components/chunks/ResponsiveBox.js +1 -1
  107. package/dist/site/components/chunks/TextEffectsShared.js +2 -2
  108. package/dist/site/components/chunks/a11y.js +4 -4
  109. package/dist/site/components/chunks/constants10.js +20 -65
  110. package/dist/site/components/chunks/constants11.js +12 -14
  111. package/dist/site/components/chunks/constants12.js +9 -9
  112. package/dist/site/components/chunks/constants13.js +8 -10
  113. package/dist/site/components/chunks/constants14.js +13 -9
  114. package/dist/site/components/chunks/constants15.js +17 -14
  115. package/dist/site/components/chunks/constants16.js +12 -17
  116. package/dist/site/components/chunks/constants17.js +13 -11
  117. package/dist/site/components/chunks/constants18.js +96 -21
  118. package/dist/site/components/chunks/constants19.js +50 -92
  119. package/dist/site/components/chunks/constants2.js +126 -47
  120. package/dist/site/components/chunks/constants20.js +50 -54
  121. package/dist/site/components/chunks/constants21.js +52 -49
  122. package/dist/site/components/chunks/constants22.js +310 -43
  123. package/dist/site/components/chunks/constants23.js +65 -310
  124. package/dist/site/components/chunks/constants24.js +99 -70
  125. package/dist/site/components/chunks/constants25.js +30 -101
  126. package/dist/site/components/chunks/constants26.js +17 -35
  127. package/dist/site/components/chunks/constants27.js +447 -16
  128. package/dist/site/components/chunks/constants28.js +29 -441
  129. package/dist/site/components/chunks/constants29.js +78 -26
  130. package/dist/site/components/chunks/constants3.js +84 -118
  131. package/dist/site/components/chunks/constants30.js +15 -85
  132. package/dist/site/components/chunks/constants31.js +42 -11
  133. package/dist/site/components/chunks/constants32.js +45 -41
  134. package/dist/site/components/chunks/constants33.js +24 -49
  135. package/dist/site/components/chunks/constants34.js +56 -25
  136. package/dist/site/components/chunks/constants35.js +13 -58
  137. package/dist/site/components/chunks/constants36.js +206 -14
  138. package/dist/site/components/chunks/constants37.js +153 -182
  139. package/dist/site/components/chunks/constants38.js +49 -162
  140. package/dist/site/components/chunks/constants39.js +102 -51
  141. package/dist/site/components/chunks/constants4.js +13 -88
  142. package/dist/site/components/chunks/constants40.js +39 -69
  143. package/dist/site/components/chunks/constants41.js +79 -72
  144. package/dist/site/components/chunks/constants42.js +77 -83
  145. package/dist/site/components/chunks/constants43.js +56 -75
  146. package/dist/site/components/chunks/constants5.js +19 -10
  147. package/dist/site/components/chunks/constants6.js +14 -14
  148. package/dist/site/components/chunks/constants7.js +10 -11
  149. package/dist/site/components/chunks/constants8.js +14 -14
  150. package/dist/site/components/chunks/constants9.js +65 -22
  151. package/dist/site/components/chunks/customElementInit.js +1 -1
  152. package/dist/site/components/chunks/index4.js +3 -2133
  153. package/dist/site/components/chunks/index5.js +2080 -1414
  154. package/dist/site/components/chunks/index6.js +1467 -3
  155. package/dist/site/components/chunks/manifestBase.js +1 -1
  156. package/dist/site/components/chunks/parseHtml.js +1 -1
  157. package/dist/site/components/chunks/parseSvg.js +1 -1
  158. package/dist/site/components/chunks/types.js +61 -0
  159. package/dist/site/components/chunks/useConsentPolicyProps.js +2 -2
  160. package/dist/site/components/chunks/utils2.js +1 -1
  161. package/dist/site/components/extensions.js +1 -1
  162. package/package.json +2 -2
  163. package/dist/site/components/chunks/constants44.js +0 -72
@@ -1,9 +1,12 @@
1
- import { jsxs, jsx } from "react/jsx-runtime";
2
- import { useRef, useState, useEffect, useCallback } from "react";
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useRef, useState, useEffect, useCallback, useLayoutEffect, useMemo } from "react";
3
3
  import { c as clsx } from "../chunks/clsx.js";
4
- import { V as Video } from "../chunks/Video.js";
5
- import { S as ScrollSpeed, a as SCROLL_VH_PER_SECOND, M as MAX_SCROLL_VH, b as MIN_SCROLL_VH, D as DEFAULT_VIDEO, c as DEFAULT_VIDEO_RATIO, R as ROOT_CLASS } from "../chunks/constants2.js";
6
4
  import { useService } from "@wix/services-manager-react";
5
+ import { T as TranslationsDefinition } from "../chunks/index4.js";
6
+ import { V as Video } from "../chunks/Video.js";
7
+ import { S as STICKY_TOP, a as ScrollSpeed, b as SCROLL_VH_PER_SECOND, c as START_LINE, M as MAX_SCROLL_VH, d as MIN_SCROLL_VH, e as assertDuration, i as isDuration, T as TIMEFRAME_CONTENT_CLASS, f as TIMEFRAMES_ARIA_LABEL_DEFAULT, g as TIMEFRAMES_ARIA_LABEL_KEY, A as ARIA_LABEL_NAMESPACE, D as DEFAULT_VIDEO_RATIO, h as TIMEFRAMES_LAYER_CLASS, R as ROOT_CLASS, j as ScrubStart } from "../chunks/types.js";
8
+ import { c as convertA11yKeysToHtmlFormat } from "../chunks/a11y.js";
9
+ import { g as getTranslation } from "../chunks/getTranslation.js";
7
10
  import { E as EnvironmentDefinition } from "../chunks/index2.js";
8
11
  const clamp = (value, min, max) => Math.min(max, Math.max(min, value));
9
12
  const getScrollLengthVh = (duration, speed = ScrollSpeed.normal) => clamp(
@@ -18,14 +21,29 @@ const getVideoRatio = (video) => {
18
21
  const height = Number(sized == null ? void 0 : sized.height);
19
22
  return width > 0 && height > 0 ? height / width : void 0;
20
23
  };
21
- const getScrubProgress = (root2, stage2) => {
24
+ const getScrollSpaceHeight = (duration, speed, start) => {
25
+ const length = `${getScrollLengthVh(duration, speed)}vh`;
26
+ const part = START_LINE[start];
27
+ return part === void 0 ? length : `max(0px, ${length} - max(0px, ${part * 100}vh - ${STICKY_TOP}))`;
28
+ };
29
+ const getScrubProgress = (root2, stage2, {
30
+ start,
31
+ viewportHeight,
32
+ stickyTop
33
+ }) => {
22
34
  const rootRect = root2.getBoundingClientRect();
23
35
  const stageRect = stage2.getBoundingClientRect();
24
- const travel = rootRect.height - stageRect.height;
25
- if (!(travel > 0)) {
36
+ const travel = Math.max(0, rootRect.height - stageRect.height);
37
+ const part = START_LINE[start];
38
+ const line = part === void 0 ? stickyTop : Math.max(part * viewportHeight, stickyTop);
39
+ const preRoll = line - stickyTop;
40
+ const distance = preRoll + travel;
41
+ if (!(distance > 0)) {
26
42
  return 0;
27
43
  }
28
- return clamp((stageRect.top - rootRect.top) / travel, 0, 1);
44
+ const preRolled = clamp(line - rootRect.top, 0, preRoll);
45
+ const stuck = clamp(stageRect.top - rootRect.top, 0, travel);
46
+ return clamp((preRolled + stuck) / distance, 0, 1);
29
47
  };
30
48
  const useScrubGate = ({
31
49
  scrubAllowed,
@@ -142,6 +160,7 @@ const useScrubVideo = ({
142
160
  };
143
161
  const useScrubProgress = ({
144
162
  enabled,
163
+ start,
145
164
  rootRef,
146
165
  stageRef,
147
166
  onProgress
@@ -153,7 +172,14 @@ const useScrubProgress = ({
153
172
  return void 0;
154
173
  }
155
174
  let frame = 0;
156
- const read = () => onProgress(getScrubProgress(root2, stage2));
175
+ const stageStyle = getComputedStyle(stage2);
176
+ const read = () => onProgress(
177
+ getScrubProgress(root2, stage2, {
178
+ start,
179
+ viewportHeight: window.innerHeight,
180
+ stickyTop: parseFloat(stageStyle.top) || 0
181
+ })
182
+ );
157
183
  const tick = () => {
158
184
  read();
159
185
  frame = requestAnimationFrame(tick);
@@ -178,16 +204,236 @@ const useScrubProgress = ({
178
204
  observer.disconnect();
179
205
  stop();
180
206
  };
181
- }, [enabled, rootRef, stageRef, onProgress]);
207
+ }, [enabled, start, rootRef, stageRef, onProgress]);
182
208
  };
209
+ const toMs = (seconds) => Number.isFinite(seconds) ? Math.floor(seconds * 1e3 + 1e-6) : NaN;
210
+ function activeAt(list, timeMs, durationMs) {
211
+ assertDuration(durationMs);
212
+ if (!Number.isFinite(timeMs)) {
213
+ return void 0;
214
+ }
215
+ if (timeMs >= durationMs) {
216
+ let latest;
217
+ for (const item2 of list) {
218
+ if (item2.startMs < durationMs && item2.endMs >= durationMs && (!latest || item2.startMs > latest.startMs)) {
219
+ latest = item2;
220
+ }
221
+ }
222
+ return latest;
223
+ }
224
+ return list.find((item2) => item2.startMs <= timeMs && timeMs < item2.endMs);
225
+ }
226
+ const REPORT = [
227
+ "seeking",
228
+ "seeked",
229
+ "timeupdate",
230
+ "loadedmetadata",
231
+ "emptied"
232
+ ];
233
+ function watchVideoTime(video, onTimeMs) {
234
+ let lastMs;
235
+ let lastEnded;
236
+ let stopped = false;
237
+ const report = () => {
238
+ const timeMs = toMs(video.currentTime);
239
+ const { ended } = video;
240
+ if (stopped || !Number.isFinite(timeMs) || timeMs === lastMs && ended === lastEnded) {
241
+ return;
242
+ }
243
+ lastMs = timeMs;
244
+ lastEnded = ended;
245
+ onTimeMs(timeMs, ended);
246
+ };
247
+ for (const type of REPORT) {
248
+ video.addEventListener(type, report);
249
+ }
250
+ report();
251
+ return () => {
252
+ if (stopped) {
253
+ return;
254
+ }
255
+ stopped = true;
256
+ for (const type of REPORT) {
257
+ video.removeEventListener(type, report);
258
+ }
259
+ };
260
+ }
261
+ function indexAt(timeframes, timeMs, durationMs) {
262
+ if (!isDuration(durationMs)) {
263
+ return void 0;
264
+ }
265
+ const active = activeAt(timeframes, timeMs, durationMs);
266
+ const index = active === void 0 ? -1 : timeframes.indexOf(active);
267
+ return index === -1 ? void 0 : index;
268
+ }
269
+ function useActiveTimeframeIndex(timeframes, video, durationMs) {
270
+ const [index, setIndex] = useState(() => indexAt(timeframes, 0, durationMs));
271
+ useEffect(() => {
272
+ if (!video || !isDuration(durationMs)) {
273
+ setIndex(indexAt(timeframes, 0, durationMs));
274
+ return void 0;
275
+ }
276
+ return watchVideoTime(
277
+ video,
278
+ (timeMs, ended) => setIndex(indexAt(timeframes, ended ? durationMs : timeMs, durationMs))
279
+ );
280
+ }, [video, timeframes, durationMs]);
281
+ return isDuration(durationMs) ? index : void 0;
282
+ }
283
+ const layer = "layer__OWBg-";
284
+ const item = "item__BRyMo";
285
+ const inactive = "inactive__JyOT2";
286
+ const content = "content__SndXf";
287
+ const styles$1 = {
288
+ layer,
289
+ item,
290
+ inactive,
291
+ content
292
+ };
293
+ const inactiveProps = { hidden: true, "aria-hidden": true, inert: "" };
294
+ function TimeframeLayer({
295
+ items,
296
+ activeIndex,
297
+ className,
298
+ a11yAttributes
299
+ }) {
300
+ const layerRef = useRef(null);
301
+ const activeItemRef = useRef(null);
302
+ useLayoutEffect(() => {
303
+ const layer2 = layerRef.current;
304
+ if (!layer2) {
305
+ return;
306
+ }
307
+ const previous = activeItemRef.current;
308
+ const current = layer2.querySelector(
309
+ ":scope > [data-timeframe-active]"
310
+ );
311
+ activeItemRef.current = current;
312
+ if (previous && previous !== current && previous.contains(layer2.ownerDocument.activeElement)) {
313
+ layer2.focus({ preventScroll: true });
314
+ }
315
+ });
316
+ return /* @__PURE__ */ jsx(
317
+ "div",
318
+ {
319
+ ...a11yAttributes,
320
+ ref: layerRef,
321
+ className: clsx(styles$1.layer, className),
322
+ role: "group",
323
+ tabIndex: -1,
324
+ children: items.map((item2, index) => {
325
+ const active = index === activeIndex;
326
+ return /* @__PURE__ */ jsx(
327
+ "div",
328
+ {
329
+ "data-timeframe-index": index,
330
+ "data-timeframe-active": active ? "" : void 0,
331
+ className: clsx(styles$1.item, !active && styles$1.inactive),
332
+ ...active ? {} : inactiveProps,
333
+ children: /* @__PURE__ */ jsx(
334
+ "div",
335
+ {
336
+ className: clsx(TIMEFRAME_CONTENT_CLASS, styles$1.content),
337
+ "data-timeframe-content": "",
338
+ children: item2.content
339
+ }
340
+ )
341
+ },
342
+ item2.key
343
+ );
344
+ })
345
+ }
346
+ );
347
+ }
348
+ const isTimeframe = (item2) => typeof item2 === "object" && item2 !== null && Number.isFinite(item2.startMs) && Number.isFinite(item2.endMs);
349
+ function useTimeframes({
350
+ timeframes: savedTimeframes,
351
+ activeTimeframeIndex,
352
+ durationSeconds,
353
+ editing,
354
+ videoRef,
355
+ videoKey
356
+ }) {
357
+ const [media2, setMedia] = useState(null);
358
+ useEffect(() => {
359
+ setMedia(videoRef.current);
360
+ }, [videoRef, videoKey]);
361
+ const durationMs = durationSeconds > 0 ? toMs(durationSeconds) : void 0;
362
+ const timeframes = useMemo(
363
+ () => savedTimeframes.filter(isTimeframe),
364
+ [savedTimeframes]
365
+ );
366
+ const timing = useMemo(
367
+ () => timeframes.map(({ startMs, endMs }) => ({ startMs, endMs })),
368
+ [timeframes]
369
+ );
370
+ useActiveTimeframeIndex(timing, editing ? null : media2, durationMs);
371
+ let timeMs = 0;
372
+ if (media2) {
373
+ timeMs = media2.ended && durationMs !== void 0 ? durationMs : toMs(media2.currentTime);
374
+ }
375
+ const playingIndex = indexAt(timing, timeMs, durationMs);
376
+ const selectedItem = Number.isInteger(activeTimeframeIndex) ? savedTimeframes[activeTimeframeIndex] : void 0;
377
+ const found = selectedItem ? timeframes.indexOf(selectedItem) : -1;
378
+ let selected;
379
+ if (found !== -1) {
380
+ selected = found;
381
+ } else if (activeTimeframeIndex < 0) {
382
+ selected = void 0;
383
+ } else if (timeframes.length > 0) {
384
+ selected = activeTimeframeIndex >= savedTimeframes.length ? timeframes.length - 1 : 0;
385
+ }
386
+ const seekMs = editing && selected !== void 0 ? timing[selected].startMs : void 0;
387
+ useEffect(() => {
388
+ if (!media2 || seekMs === void 0) {
389
+ return void 0;
390
+ }
391
+ const go = () => {
392
+ media2.pause();
393
+ media2.currentTime = seekMs / 1e3;
394
+ };
395
+ if (media2.readyState >= 1) {
396
+ go();
397
+ }
398
+ media2.addEventListener("loadedmetadata", go);
399
+ return () => media2.removeEventListener("loadedmetadata", go);
400
+ }, [media2, seekMs]);
401
+ const [frameShown, setFrameShown] = useState(false);
402
+ useEffect(() => {
403
+ setFrameShown(false);
404
+ if (!editing || !media2) {
405
+ return void 0;
406
+ }
407
+ const show = () => setFrameShown(true);
408
+ const hide = () => setFrameShown(false);
409
+ media2.addEventListener("seeked", show);
410
+ media2.addEventListener("emptied", hide);
411
+ return () => {
412
+ media2.removeEventListener("seeked", show);
413
+ media2.removeEventListener("emptied", hide);
414
+ };
415
+ }, [editing, media2]);
416
+ const items = timeframes.map((timeframe, index) => ({
417
+ // Index keys only for broken items with no identifier; they mix up state after a split.
418
+ key: typeof timeframe.timeframeIdentifier === "string" && timeframe.timeframeIdentifier !== "" ? timeframe.timeframeIdentifier : `timeframe-index-${index}`,
419
+ content: timeframe.container
420
+ }));
421
+ return {
422
+ items,
423
+ activeIndex: editing ? selected : playingIndex,
424
+ frameShown: editing && frameShown
425
+ };
426
+ }
183
427
  const root = "root__Wv1E1";
184
428
  const stage = "stage__XFpev";
429
+ const media = "media__tTFno";
185
430
  const scrubbing = "scrubbing__yEgJI";
186
431
  const scrollSpace = "scrollSpace__oaKzu";
187
432
  const frameReady = "frameReady__g-HFT";
188
433
  const styles = {
189
434
  root,
190
435
  stage,
436
+ media,
191
437
  scrubbing,
192
438
  scrollSpace,
193
439
  frameReady
@@ -196,30 +442,59 @@ const SCRUB_ROOT_STYLE = {
196
442
  minHeight: "max-content",
197
443
  aspectRatio: "auto"
198
444
  };
445
+ const NO_TIMEFRAMES = [];
199
446
  const VideoScrub = ({
200
447
  id,
201
448
  className,
202
- video: savedVideo,
449
+ video,
203
450
  scrollSpeed = ScrollSpeed.normal,
204
- scrubAllowed = true
451
+ scrubStart = ScrubStart.top,
452
+ scrubAllowed = true,
453
+ timeframes: savedTimeframes,
454
+ activeTimeframeIndex = 0,
455
+ elementProps
205
456
  }) => {
457
+ var _a;
458
+ const editing = !scrubAllowed;
459
+ const { translate } = useService(
460
+ TranslationsDefinition
461
+ );
462
+ const layerProps = elementProps == null ? void 0 : elementProps.timeframesLayer;
463
+ const layerA11y = {
464
+ ...(layerProps == null ? void 0 : layerProps.a11y) && convertA11yKeysToHtmlFormat(layerProps.a11y),
465
+ "aria-label": ((_a = layerProps == null ? void 0 : layerProps.a11y) == null ? void 0 : _a.ariaLabel) || // The service returns the key itself when there is no translation.
466
+ getTranslation(
467
+ translate(ARIA_LABEL_NAMESPACE),
468
+ "label",
469
+ { label: TIMEFRAMES_ARIA_LABEL_KEY },
470
+ { label: TIMEFRAMES_ARIA_LABEL_DEFAULT }
471
+ )
472
+ };
206
473
  const rootRef = useRef(null);
207
474
  const stageRef = useRef(null);
208
475
  const videoRef = useRef(null);
209
- const video = savedVideo ?? DEFAULT_VIDEO;
210
- const duration = video.duration ?? 0;
476
+ const duration = (video == null ? void 0 : video.duration) ?? 0;
211
477
  const { layout, seek } = useScrubGate({ scrubAllowed, duration });
212
478
  const { seekProgress, frameReady: frameReady2 } = useScrubVideo({
213
479
  enabled: seek,
214
480
  videoRef,
215
- videoKey: video.uri
481
+ videoKey: video == null ? void 0 : video.uri
216
482
  });
217
483
  useScrubProgress({
218
484
  enabled: seek,
485
+ start: scrubStart,
219
486
  rootRef,
220
487
  stageRef,
221
488
  onProgress: seekProgress
222
489
  });
490
+ const timeframe = useTimeframes({
491
+ timeframes: savedTimeframes ?? NO_TIMEFRAMES,
492
+ activeTimeframeIndex,
493
+ durationSeconds: duration,
494
+ editing,
495
+ videoRef,
496
+ videoKey: (video == null ? void 0 : video.uri) ?? ""
497
+ });
223
498
  return /* @__PURE__ */ jsxs(
224
499
  "div",
225
500
  {
@@ -233,35 +508,60 @@ const VideoScrub = ({
233
508
  ),
234
509
  style: layout ? SCRUB_ROOT_STYLE : void 0,
235
510
  children: [
236
- /* @__PURE__ */ jsx(
511
+ /* @__PURE__ */ jsxs(
237
512
  "div",
238
513
  {
239
514
  ref: stageRef,
240
- className: clsx(styles.stage, frameReady2 && styles.frameReady),
241
- style: layout ? {
242
- aspectRatio: `1 / ${getVideoRatio(video) ?? DEFAULT_VIDEO_RATIO}`
243
- } : void 0,
515
+ className: clsx(
516
+ styles.stage,
517
+ (frameReady2 || timeframe.frameShown) && styles.frameReady
518
+ ),
244
519
  "data-scrub-stage": layout ? "" : void 0,
245
- "aria-hidden": "true",
246
- children: /* @__PURE__ */ jsx(
247
- Video,
248
- {
249
- id: `video_${id}`,
250
- videoMedia: video,
251
- videoRef,
252
- qualityPolicy: "proportional",
253
- autoplay: false,
254
- loop: false,
255
- muted: true
256
- }
257
- )
520
+ children: [
521
+ /* @__PURE__ */ jsx(
522
+ "div",
523
+ {
524
+ className: styles.media,
525
+ "aria-hidden": "true",
526
+ style: layout ? {
527
+ aspectRatio: `1 / ${getVideoRatio(video) ?? DEFAULT_VIDEO_RATIO}`
528
+ } : void 0,
529
+ children: video && /* @__PURE__ */ jsx(
530
+ Video,
531
+ {
532
+ id: `video_${id}`,
533
+ videoMedia: video,
534
+ videoRef,
535
+ qualityPolicy: "proportional",
536
+ autoplay: false,
537
+ loop: false,
538
+ muted: true
539
+ }
540
+ )
541
+ }
542
+ ),
543
+ timeframe.items.length > 0 && /* @__PURE__ */ jsx(
544
+ TimeframeLayer,
545
+ {
546
+ className: clsx(
547
+ TIMEFRAMES_LAYER_CLASS,
548
+ layerProps == null ? void 0 : layerProps.className
549
+ ),
550
+ items: timeframe.items,
551
+ activeIndex: timeframe.activeIndex,
552
+ a11yAttributes: layerA11y
553
+ }
554
+ )
555
+ ]
258
556
  }
259
557
  ),
260
558
  layout && /* @__PURE__ */ jsx(
261
559
  "div",
262
560
  {
263
561
  className: styles.scrollSpace,
264
- style: { height: `${getScrollLengthVh(duration, scrollSpeed)}vh` }
562
+ style: {
563
+ height: getScrollSpaceHeight(duration, scrollSpeed, scrubStart)
564
+ }
265
565
  }
266
566
  )
267
567
  ]
@@ -1,8 +1,13 @@
1
- import { VideoMedia } from '@wix/video';
2
- import { ScrollSpeed } from './VideoScrub.types';
1
+ import { ScrollSpeed, ScrubStart } from './VideoScrub.types';
3
2
  export declare const ROOT_CLASS = "video-scrub";
4
3
  export declare const DEFAULT_VIDEO_RATIO: number;
5
4
  export declare const SCROLL_VH_PER_SECOND: Record<ScrollSpeed, number>;
6
5
  export declare const MIN_SCROLL_VH = 50;
7
6
  export declare const MAX_SCROLL_VH = 1000;
8
- export declare const DEFAULT_VIDEO: VideoMedia;
7
+ export declare const STICKY_TOP = "var(--video-scrub-sticky-top)";
8
+ export declare const START_LINE: Partial<Record<ScrubStart, number>>;
9
+ export declare const TIMEFRAMES_LAYER_CLASS = "video-scrub-timeframes";
10
+ export declare const ARIA_LABEL_NAMESPACE = "ariaLabels";
11
+ export declare const TIMEFRAMES_ARIA_LABEL_KEY = "VideoScrub_AriaLabel_Timeframes";
12
+ export declare const TIMEFRAMES_ARIA_LABEL_DEFAULT = "Video content";
13
+ export declare const TIMEFRAMES_GROUP_KEY = "timeframes";
@@ -1,18 +1,91 @@
1
- .root__Wv1E1 {
1
+ .layer__OWBg- {
2
+ position: absolute;
3
+ inset: 0;
4
+ display: grid;
5
+ grid-template-rows: minmax(0, 1fr);
6
+ grid-template-columns: minmax(0, 1fr);
7
+ outline: none;
8
+ }
9
+
10
+ .item__BRyMo {
11
+ grid-area: 1/1;
12
+ }
13
+
14
+ .inactive__JyOT2 {
15
+ display: none;
16
+ }
17
+
18
+ .content__SndXf {
19
+ width: 100%;
20
+ height: 100%;
21
+ }.root__Wv1E1 {
22
+ --maskImage: initial;
23
+ --boxShadow: initial;
24
+ --border-width-top: initial;
25
+ --border-width-inline-end: initial;
26
+ --border-width-bottom: initial;
27
+ --border-width-inline-start: initial;
28
+ --border-color-top: initial;
29
+ --border-color-inline-end: initial;
30
+ --border-color-bottom: initial;
31
+ --border-color-inline-start: initial;
32
+ --border-style-top: initial;
33
+ --border-style-inline-end: initial;
34
+ --border-style-bottom: initial;
35
+ --border-style-inline-start: initial;
36
+ --borderStartStartRadius: initial;
37
+ --borderStartEndRadius: initial;
38
+ --borderEndStartRadius: initial;
39
+ --borderEndEndRadius: initial;
2
40
  position: relative;
3
41
  box-sizing: border-box;
4
42
  }
5
43
 
6
44
  .stage__XFpev {
7
45
  position: relative;
46
+ box-sizing: border-box;
8
47
  width: 100%;
9
48
  height: 100%;
10
49
  overflow: hidden;
50
+ box-shadow: var(--boxShadow, none);
51
+ border-top-width: var(--border-width-top, 0);
52
+ border-inline-end-width: var(--border-width-inline-end, 0);
53
+ border-bottom-width: var(--border-width-bottom, 0);
54
+ border-inline-start-width: var(--border-width-inline-start, 0);
55
+ border-top-color: var(--border-color-top, transparent);
56
+ border-inline-end-color: var(--border-color-inline-end, transparent);
57
+ border-bottom-color: var(--border-color-bottom, transparent);
58
+ border-inline-start-color: var(--border-color-inline-start, transparent);
59
+ border-top-style: var(--border-style-top, solid);
60
+ border-inline-end-style: var(--border-style-inline-end, solid);
61
+ border-bottom-style: var(--border-style-bottom, solid);
62
+ border-inline-start-style: var(--border-style-inline-start, solid);
63
+ border-start-start-radius: var(--borderStartStartRadius, 0);
64
+ border-start-end-radius: var(--borderStartEndRadius, 0);
65
+ border-end-start-radius: var(--borderEndStartRadius, 0);
66
+ border-end-end-radius: var(--borderEndEndRadius, 0);
67
+ }
68
+
69
+ .media__tTFno {
70
+ position: relative;
71
+ width: 100%;
72
+ height: 100%;
73
+ mask-image: var(--maskImage, none);
74
+ mask-size: 100% 100%;
75
+ mask-repeat: no-repeat;
76
+ mask-position: center;
77
+ }
78
+
79
+ .scrubbing__yEgJI {
80
+ --video-scrub-sticky-top: var(
81
+ --wix-top-inset,
82
+ calc(var(--wix-ads-top-height, 0px) + var(--top-offset, 0px))
83
+ );
11
84
  }
12
85
 
13
86
  .scrubbing__yEgJI .stage__XFpev {
14
87
  position: sticky;
15
- top: var(--wix-top-inset, calc(var(--wix-ads-top-height, 0px) + var(--top-offset, 0px)));
88
+ top: var(--video-scrub-sticky-top);
16
89
  transition: top var(--wix-top-inset-transition-duration, 0ms) var(--wix-top-inset-transition-easing, linear);
17
90
  height: inherit;
18
91
  }
@@ -1,10 +1,12 @@
1
1
  import { RefObject } from 'react';
2
+ import { ScrubStart } from '../VideoScrub.types';
2
3
  /**
3
4
  * Calls `onProgress` every frame with the scroll progress through the tall root, while the root
4
- * is on screen. It only reads layout, so it adds no forced reflow to the frame.
5
+ * is on screen. It only reads layout and style, so it adds no forced reflow to the frame.
5
6
  */
6
- export declare const useScrubProgress: ({ enabled, rootRef, stageRef, onProgress, }: {
7
+ export declare const useScrubProgress: ({ enabled, start, rootRef, stageRef, onProgress, }: {
7
8
  enabled: boolean;
9
+ start: ScrubStart;
8
10
  rootRef: RefObject<HTMLElement | null>;
9
11
  stageRef: RefObject<HTMLElement | null>;
10
12
  onProgress: (progress: number) => void;
@@ -0,0 +1,23 @@
1
+ import { RefObject } from 'react';
2
+ import { TimeframeLayerItem } from '../timeframes';
3
+ import { VideoScrubTimeframe } from '../VideoScrub.types';
4
+ /**
5
+ * The timeframe to show, and the layer items (TimelineBox's view logic).
6
+ * Editing: the timeframe selected in the editor (R1), and the video stays on its start frame.
7
+ * Otherwise: the timeframe at the video's time, which the scroll sets by seeking (each `seeked`
8
+ * reports the new time).
9
+ */
10
+ export declare function useTimeframes({ timeframes: savedTimeframes, activeTimeframeIndex, durationSeconds, editing, videoRef, videoKey, }: {
11
+ timeframes: ReadonlyArray<VideoScrubTimeframe>;
12
+ activeTimeframeIndex: number;
13
+ durationSeconds: number;
14
+ editing: boolean;
15
+ videoRef: RefObject<HTMLVideoElement | null>;
16
+ /** Changes when the video changes (its uri), in case @wix/video makes a new <video>. */
17
+ videoKey: string;
18
+ }): {
19
+ items: Array<TimeframeLayerItem>;
20
+ activeIndex: number | undefined;
21
+ /** Editing only: a seek landed, so the video (not the poster) should show. */
22
+ frameShown: boolean;
23
+ };