@wix/editor-react-components 1.2762.0 → 1.2764.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/Image3/component.preview.d.ts +1 -3
  29. package/dist/site/components/Image3/manifest.js +1 -4
  30. package/dist/site/components/ImageReveal/component.js +2 -2
  31. package/dist/site/components/ImageReveal/manifest.js +1 -1
  32. package/dist/site/components/Line/component.js +1 -1
  33. package/dist/site/components/LinkBar/component.js +2 -2
  34. package/dist/site/components/LinkBar/manifest.js +1 -1
  35. package/dist/site/components/Logo/component.js +1 -1
  36. package/dist/site/components/Logo/manifest.js +1 -1
  37. package/dist/site/components/Logo/sdk.js +1 -1
  38. package/dist/site/components/Lottie/component.js +3 -3
  39. package/dist/site/components/Lottie/manifest.js +1 -1
  40. package/dist/site/components/MarkdownBlock/component.js +2 -2
  41. package/dist/site/components/MarkdownBlock/manifest.js +1 -1
  42. package/dist/site/components/Menu/component.js +3 -3
  43. package/dist/site/components/Menu/manifest.js +1 -1
  44. package/dist/site/components/MultiStateBox/component.js +1 -1
  45. package/dist/site/components/MultiStateBox/manifest.js +1 -1
  46. package/dist/site/components/ProgressBar/component.js +1 -1
  47. package/dist/site/components/ProgressBar/manifest.js +1 -1
  48. package/dist/site/components/ProgressBar/sdk.js +1 -1
  49. package/dist/site/components/RadioButtons/component.js +1 -1
  50. package/dist/site/components/RadioButtons/manifest.js +1 -1
  51. package/dist/site/components/Repeater/component.js +2 -2
  52. package/dist/site/components/Repeater/manifest.js +1 -1
  53. package/dist/site/components/ShareButtons/component.js +2 -2
  54. package/dist/site/components/ShareButtons/manifest.js +1 -1
  55. package/dist/site/components/Slideshow/component.js +1 -1
  56. package/dist/site/components/Tabs/component.js +1 -1
  57. package/dist/site/components/Tabs/manifest.js +1 -1
  58. package/dist/site/components/TextBox/component.js +1 -1
  59. package/dist/site/components/TextBox/manifest.js +1 -1
  60. package/dist/site/components/TextEffects3d/component.js +1 -1
  61. package/dist/site/components/TextEffects3d/manifest.js +1 -1
  62. package/dist/site/components/TextEffectsBauhaus/component.js +1 -1
  63. package/dist/site/components/TextEffectsBauhaus/manifest.js +1 -1
  64. package/dist/site/components/TextEffectsGlass/component.js +1 -1
  65. package/dist/site/components/TextEffectsGlass/manifest.js +1 -1
  66. package/dist/site/components/TextEffectsGlitch/component.js +1 -1
  67. package/dist/site/components/TextEffectsGlitch/manifest.js +1 -1
  68. package/dist/site/components/TextEffectsLetterPress/component.js +1 -1
  69. package/dist/site/components/TextEffectsLetterPress/manifest.js +1 -1
  70. package/dist/site/components/TextEffectsMatrix/component.js +1 -1
  71. package/dist/site/components/TextEffectsMatrix/manifest.js +1 -1
  72. package/dist/site/components/TextEffectsNeonSign/component.js +1 -1
  73. package/dist/site/components/TextEffectsNeonSign/manifest.js +1 -1
  74. package/dist/site/components/TextEffectsNoisy/component.js +1 -1
  75. package/dist/site/components/TextEffectsNoisy/manifest.js +1 -1
  76. package/dist/site/components/TextEffectsOutlineOut/component.js +2 -2
  77. package/dist/site/components/TextEffectsOutlineOut/manifest.js +1 -1
  78. package/dist/site/components/TextEffectsRetro/component.js +1 -1
  79. package/dist/site/components/TextEffectsRetro/manifest.js +1 -1
  80. package/dist/site/components/TextEffectsShook/component.js +1 -1
  81. package/dist/site/components/TextEffectsShook/manifest.js +1 -1
  82. package/dist/site/components/TextEffectsSticker/component.js +1 -1
  83. package/dist/site/components/TextEffectsSticker/manifest.js +2 -2
  84. package/dist/site/components/TextEffectsStriped/component.js +1 -1
  85. package/dist/site/components/TextEffectsStriped/manifest.js +1 -1
  86. package/dist/site/components/TextInput/component.js +2 -2
  87. package/dist/site/components/TextInput/manifest.js +1 -1
  88. package/dist/site/components/TextMarquee/component.js +1 -1
  89. package/dist/site/components/TimePicker/component.js +2 -2
  90. package/dist/site/components/TimePicker/manifest.js +1 -1
  91. package/dist/site/components/TransparentVideo/component.js +2 -2
  92. package/dist/site/components/VideoScrub/VideoScrub.types.d.ts +28 -0
  93. package/dist/site/components/VideoScrub/component.js +295 -29
  94. package/dist/site/components/VideoScrub/constants.d.ts +5 -0
  95. package/dist/site/components/VideoScrub/css.css +21 -1
  96. package/dist/site/components/VideoScrub/hooks/useTimeframes.d.ts +23 -0
  97. package/dist/site/components/VideoScrub/manifest.js +102 -6
  98. package/dist/site/components/VideoScrub/timeframes/index.d.ts +1 -1
  99. package/dist/site/components/VideoScrub/timeframes/types.d.ts +1 -1
  100. package/dist/site/components/VideoScrub/timeframes/useActiveTimeframeIndex.d.ts +2 -0
  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 +128 -34
  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 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, D as DEFAULT_VIDEO_RATIO, R as ROOT_CLASS, e as ScrubStart } 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(
@@ -203,6 +206,224 @@ const useScrubProgress = ({
203
206
  };
204
207
  }, [enabled, start, rootRef, stageRef, onProgress]);
205
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
+ }
206
427
  const root = "root__Wv1E1";
207
428
  const stage = "stage__XFpev";
208
429
  const media = "media__tTFno";
@@ -221,14 +442,34 @@ const SCRUB_ROOT_STYLE = {
221
442
  minHeight: "max-content",
222
443
  aspectRatio: "auto"
223
444
  };
445
+ const NO_TIMEFRAMES = [];
224
446
  const VideoScrub = ({
225
447
  id,
226
448
  className,
227
449
  video,
228
450
  scrollSpeed = ScrollSpeed.normal,
229
451
  scrubStart = ScrubStart.top,
230
- scrubAllowed = true
452
+ scrubAllowed = true,
453
+ timeframes: savedTimeframes,
454
+ activeTimeframeIndex = 0,
455
+ elementProps
231
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
+ };
232
473
  const rootRef = useRef(null);
233
474
  const stageRef = useRef(null);
234
475
  const videoRef = useRef(null);
@@ -246,6 +487,14 @@ const VideoScrub = ({
246
487
  stageRef,
247
488
  onProgress: seekProgress
248
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
+ });
249
498
  return /* @__PURE__ */ jsxs(
250
499
  "div",
251
500
  {
@@ -259,34 +508,51 @@ const VideoScrub = ({
259
508
  ),
260
509
  style: layout ? SCRUB_ROOT_STYLE : void 0,
261
510
  children: [
262
- /* @__PURE__ */ jsx(
511
+ /* @__PURE__ */ jsxs(
263
512
  "div",
264
513
  {
265
514
  ref: stageRef,
266
- className: clsx(styles.stage, frameReady2 && styles.frameReady),
515
+ className: clsx(
516
+ styles.stage,
517
+ (frameReady2 || timeframe.frameShown) && styles.frameReady
518
+ ),
267
519
  "data-scrub-stage": layout ? "" : void 0,
268
- "aria-hidden": "true",
269
- children: /* @__PURE__ */ jsx(
270
- "div",
271
- {
272
- className: styles.media,
273
- style: layout ? {
274
- aspectRatio: `1 / ${getVideoRatio(video) ?? DEFAULT_VIDEO_RATIO}`
275
- } : void 0,
276
- children: video && /* @__PURE__ */ jsx(
277
- Video,
278
- {
279
- id: `video_${id}`,
280
- videoMedia: video,
281
- videoRef,
282
- qualityPolicy: "proportional",
283
- autoplay: false,
284
- loop: false,
285
- muted: true
286
- }
287
- )
288
- }
289
- )
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
+ ]
290
556
  }
291
557
  ),
292
558
  layout && /* @__PURE__ */ jsx(
@@ -6,3 +6,8 @@ export declare const MIN_SCROLL_VH = 50;
6
6
  export declare const MAX_SCROLL_VH = 1000;
7
7
  export declare const STICKY_TOP = "var(--video-scrub-sticky-top)";
8
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,4 +1,24 @@
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 {
2
22
  --maskImage: initial;
3
23
  --boxShadow: initial;
4
24
  --border-width-top: initial;
@@ -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
+ };
@@ -1,10 +1,10 @@
1
- import { b as DISPLAY_GROUPS, C as CSS_PROPERTIES, M as MEDIA, D as DATA, A as Archetype, L as LAYOUT } from "../chunks/chunk-EVX7ZUBD.js";
1
+ import { b as DISPLAY_GROUPS, C as CSS_PROPERTIES, M as MEDIA, D as DATA, E as ELEMENTS, L as LAYOUT, c as ContainerType, A as Archetype } from "../chunks/chunk-EVX7ZUBD.js";
2
2
  import { V as VideoCategoryTypes } from "../chunks/types.impl.js";
3
- import { a as ScrollSpeed, e as ScrubStart, R as ROOT_CLASS } from "../chunks/constants2.js";
3
+ import { k as TIMEFRAMES_GROUP_KEY, a as ScrollSpeed, j as ScrubStart, h as TIMEFRAMES_LAYER_CLASS, T as TIMEFRAME_CONTENT_CLASS, l as MAX_COUNT, R as ROOT_CLASS } from "../chunks/types.js";
4
4
  const manifest = {
5
- id: "45b42eec-531c-46e4-980f-0546afae1eaa",
6
- type: "wixEditorElements.VideoScrub__DEV__v4",
7
- description: "A video that plays by page scroll: while the visitor scrolls past it, the video stays on screen and its time follows the scroll.",
5
+ id: "f67effcb-a591-4156-adee-445134fe12da",
6
+ type: "wixEditorElements.VideoScrub__DEV__v5",
7
+ description: "A video that plays by page scroll: while the visitor scrolls past it, the video stays on screen and its time follows the scroll. Timeframes show elements over the video during parts of it.",
8
8
  installation: {
9
9
  initialSize: {
10
10
  width: {
@@ -52,6 +52,88 @@ const manifest = {
52
52
  { value: ScrollSpeed.fast, displayName: "Fast" }
53
53
  ]
54
54
  }
55
+ },
56
+ // Time ranges on the video. Each one owns a container of elements, shown over the video while
57
+ // the time is inside it. The Timeframes panel edits them (TimelineBox rules, renamed).
58
+ timeframes: {
59
+ displayName: "Timeframes",
60
+ dataType: DATA.DATA_TYPE.arrayItems,
61
+ [DATA.DATA_TYPE.arrayItems]: {
62
+ maxSize: MAX_COUNT,
63
+ data: {
64
+ items: {
65
+ // Our own stable id: runtime items have no `_id`. A name ending in `Id` stops the
66
+ // editor from making `_id` (TimelineBox finding), so it is `Identifier`.
67
+ timeframeIdentifier: {
68
+ displayName: "Timeframe Identifier",
69
+ dataType: DATA.DATA_TYPE.text
70
+ },
71
+ // The editor's item list reads `item.name`.
72
+ name: {
73
+ displayName: "Name",
74
+ dataType: DATA.DATA_TYPE.text
75
+ },
76
+ startMs: {
77
+ displayName: "Start Ms",
78
+ dataType: DATA.DATA_TYPE.number
79
+ },
80
+ endMs: {
81
+ displayName: "End Ms",
82
+ dataType: DATA.DATA_TYPE.number
83
+ },
84
+ container: {
85
+ displayName: "Timeframe",
86
+ dataType: DATA.DATA_TYPE.container,
87
+ [DATA.DATA_TYPE.container]: {
88
+ selector: `.${TIMEFRAME_CONTENT_CLASS}`,
89
+ containerType: ContainerType.simple,
90
+ simple: {
91
+ displayName: "Timeframe",
92
+ behaviors: { selectable: true },
93
+ // Always the size of the stage, like MultiStateBox's state container.
94
+ layout: {
95
+ resizeDirection: LAYOUT.RESIZE_DIRECTION.none
96
+ }
97
+ }
98
+ }
99
+ },
100
+ // Stored only for now: missing means 1.
101
+ scrollSensitivity: {
102
+ displayName: "Scroll Sensitivity",
103
+ dataType: DATA.DATA_TYPE.number
104
+ }
105
+ }
106
+ }
107
+ }
108
+ },
109
+ activeTimeframeIndex: {
110
+ displayName: "Active Timeframe Index",
111
+ dataType: DATA.DATA_TYPE.number,
112
+ defaultValue: 0
113
+ }
114
+ },
115
+ displayFilters: {
116
+ data: { hide: ["activeTimeframeIndex"] }
117
+ },
118
+ elements: {
119
+ // The layer over the video that holds the timeframes. Only its label is set here.
120
+ timeframesLayer: {
121
+ elementType: ELEMENTS.ELEMENT_TYPE.inlineElement,
122
+ inlineElement: {
123
+ displayName: "Timeframes",
124
+ selector: `.${TIMEFRAMES_LAYER_CLASS}`,
125
+ behaviors: {
126
+ selectable: false
127
+ },
128
+ data: {
129
+ a11y: {
130
+ dataType: DATA.DATA_TYPE.a11y,
131
+ [DATA.DATA_TYPE.a11y]: {
132
+ attributes: [DATA.A11Y_ATTRIBUTES.ariaLabel]
133
+ }
134
+ }
135
+ }
136
+ }
55
137
  }
56
138
  },
57
139
  // Custom properties, not cssProperties: Studio puts cssProperties on the root, and the root is
@@ -154,6 +236,16 @@ const manifest = {
154
236
  }
155
237
  },
156
238
  displayGroups: {
239
+ [TIMEFRAMES_GROUP_KEY]: {
240
+ displayName: "Timeframe",
241
+ groupType: DISPLAY_GROUPS.GROUP_TYPE.arrayItems,
242
+ arrayItems: {
243
+ arrayItems: "timeframes",
244
+ selectedItemIndex: "activeTimeframeIndex",
245
+ // A new VideoScrub has no timeframes, so "nothing selected" is a normal state.
246
+ allowNoSelection: true
247
+ }
248
+ },
157
249
  borderColorGroup: {
158
250
  groupType: DISPLAY_GROUPS.GROUP_TYPE.borderColor,
159
251
  [DISPLAY_GROUPS.GROUP_TYPE.borderColor]: {
@@ -213,7 +305,10 @@ const manifest = {
213
305
  client: {
214
306
  componentUrl: "./site/components/VideoScrub/component.tsx",
215
307
  dependencies: {
216
- serviceDependencies: ["@wix/viewer-service-environment"]
308
+ serviceDependencies: [
309
+ "@wix/viewer-service-environment",
310
+ "@wix/viewer-service-translations"
311
+ ]
217
312
  }
218
313
  },
219
314
  editor: {
@@ -221,6 +316,7 @@ const manifest = {
221
316
  dependencies: {
222
317
  serviceDependencies: [
223
318
  "@wix/viewer-service-environment",
319
+ "@wix/viewer-service-translations",
224
320
  "@wix/site-service-editor-context"
225
321
  ]
226
322
  }
@@ -8,6 +8,6 @@ export { add, createInitial, edgeLimits, fitToDuration, moveTimeframe, moveLimit
8
8
  export type { Edge } from './edit';
9
9
  export { activeAt } from './query';
10
10
  export { watchVideoTime } from './watchVideoTime';
11
- export { useActiveTimeframeIndex } from './useActiveTimeframeIndex';
11
+ export { indexAt, useActiveTimeframeIndex } from './useActiveTimeframeIndex';
12
12
  export { TimeframeLayer } from './TimeframeLayer';
13
13
  export type { TimeframeLayerItem, TimeframeLayerProps } from './TimeframeLayer';
@@ -36,7 +36,7 @@ export declare const MAX_COUNT = 40;
36
36
  * `selector` points at it, like Accordion's `.item-content`. The editor needs this selector to find
37
37
  * each container. (Saves can still fail with SCHEMA_REFERENCES_NOT_FOUND; that is a server bug.)
38
38
  */
39
- export declare const TIMEFRAME_CONTENT_CLASS = "timeframe-content";
39
+ export declare const TIMEFRAME_CONTENT_CLASS = "video-scrub-timeframe-content";
40
40
  /** Length of a new timeframe from createInitial and add, when there is room. */
41
41
  export declare const DEFAULT_TIMEFRAME_MS = 5000;
42
42
  export type TimeframeErrorCode = 'badTime' | 'tooShort' | 'outOfRange' | 'notSorted' | 'overlap' | 'tooMany' | 'notFound' | 'onBoundary' | 'inGap' | 'insideTimeframe' | 'noRoom' | 'badSensitivity' | 'badItem' | 'badKey' | 'duplicateKey' | 'duplicateId';
@@ -1,4 +1,6 @@
1
1
  import { TimeframeTiming } from './types';
2
+ /** The index of the timeframe at `timeMs`, or undefined in a gap or for a bad duration. */
3
+ export declare function indexAt<T extends TimeframeTiming>(timeframes: ReadonlyArray<T>, timeMs: number, durationMs: number | undefined): number | undefined;
2
4
  /**
3
5
  * The index of the timeframe showing in `video` now. It re-renders only when the index changes.
4
6
  * `durationMs` comes from the data. Undefined or invalid gives undefined.
@@ -1,7 +1,7 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { forwardRef, useRef, useImperativeHandle, useCallback, useMemo } from "react";
3
3
  import { p as parseSvg } from "./parseSvg.js";
4
- import { A as AnimatedSvgIds, a as AnimatedDataAttributes, b as AnimationDirection, T as TestIds, D as DEFAULT_ANIMATION_DURATION } from "./constants20.js";
4
+ import { A as AnimatedSvgIds, a as AnimatedDataAttributes, b as AnimationDirection, T as TestIds, D as DEFAULT_ANIMATION_DURATION } from "./constants19.js";
5
5
  import { c as cn } from "./index9.js";
6
6
  const AnimatedSvg = forwardRef(
7
7
  ({ svgContent, reducedMotion = false, duration }, ref) => {
@@ -7,8 +7,8 @@ import { a as getDataAttributes, g as getQaDataAttributes } from "./dataUtils.js
7
7
  import { f as formatClassNames } from "./classNames.js";
8
8
  import { I as IconAnimationTriggers } from "./Button.types.js";
9
9
  import AnimatedIconWithReducedMotion from "../AnimatedIcon/component.js";
10
- import { T as TRANSITION_DURATION, D as DesignStates, S as SEMANTIC_CLASS_NAMES, a as TestIds, C as COMPONENT_TYPE } from "./constants22.js";
11
- import { d as activateByEnterButton, a as activateBySpaceOrEnterButton, r as removeAriaPrefix, g as getAccessibilityAttributesSpread } from "./a11y.js";
10
+ import { T as TRANSITION_DURATION, D as DesignStates, S as SEMANTIC_CLASS_NAMES, a as TestIds, C as COMPONENT_TYPE } from "./constants21.js";
11
+ import { e as activateByEnterButton, a as activateBySpaceOrEnterButton, r as removeAriaPrefix, g as getAccessibilityAttributesSpread } from "./a11y.js";
12
12
  import { i as isValidLink } from "./Link.js";
13
13
  import { d as defineStaticService } from "./staticService.js";
14
14
  import { d as defineService } from "./index8.js";
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { i as imageKit, g as getPlaceholder } from "./index5.js";
2
+ import { i as imageKit, g as getPlaceholder } from "./index6.js";
3
3
  const image = "image__WopE9";
4
4
  const styles = {
5
5
  image
@@ -1,6 +1,6 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
- import { a as activateBySpaceOrEnterButton, c as activateBySpaceButton, d as activateByEnterButton } from "./a11y.js";
3
+ import { a as activateBySpaceOrEnterButton, d as activateBySpaceButton, e as activateByEnterButton } from "./a11y.js";
4
4
  import { a as getDataAttributes } from "./dataUtils.js";
5
5
  const TestIds = {
6
6
  root: "linkElement"
@@ -2,7 +2,7 @@ import React__default from "react";
2
2
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
3
3
  import { c as clsx } from "./clsx.js";
4
4
  import { a as getDataAttributes } from "./dataUtils.js";
5
- import { T as TestIds } from "./constants10.js";
5
+ import { T as TestIds } from "./constants9.js";
6
6
  function bidiFactory() {
7
7
  var bidi2 = (function(exports$1) {
8
8
  var DATA = {
@@ -2,7 +2,7 @@ import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
3
  import { c as clsx } from "./clsx.js";
4
4
  import { f as formatClassNames } from "./classNames.js";
5
- import { e as getTabIndexAttribute, h as getAriaAttributes } from "./a11y.js";
5
+ import { f as getTabIndexAttribute, h as getAriaAttributes } from "./a11y.js";
6
6
  import { a as getDataAttributes } from "./dataUtils.js";
7
7
  const clickable = "clickable__Nql0c";
8
8
  const commonStyles = {
@@ -2,8 +2,8 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import React__default from "react";
3
3
  import { f as formatClassNames } from "./classNames.js";
4
4
  import { a as getDataAttributes } from "./dataUtils.js";
5
- import { e as getTabIndexAttribute } from "./a11y.js";
6
- import { D as DEFAULT_TEXT_DIRECTION, a as DEFAULT_HTML_TAG, d as dataHooks, T as TestIds } from "./constants10.js";
5
+ import { f as getTabIndexAttribute } from "./a11y.js";
6
+ import { D as DEFAULT_TEXT_DIRECTION, a as DEFAULT_HTML_TAG, d as dataHooks, T as TestIds } from "./constants9.js";
7
7
  import { c as clsx } from "./clsx.js";
8
8
  import { L as Link } from "./Link.js";
9
9
  const semanticClassNames = {