markdown-flow-ui 0.1.128-dev.1 → 0.1.129

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 (95) hide show
  1. package/dist/_virtual/index.cjs8.js +1 -1
  2. package/dist/_virtual/index.cjs9.js +1 -1
  3. package/dist/_virtual/index.es8.js +2 -2
  4. package/dist/_virtual/index.es9.js +2 -2
  5. package/dist/assets/markdown-flow-ui.css +1 -1
  6. package/dist/components/MarkdownFlowEditor/components/EditorToolbar.cjs.js.map +1 -1
  7. package/dist/components/MarkdownFlowEditor/components/EditorToolbar.es.js.map +1 -1
  8. package/dist/components/Slide/Player.cjs.js +1 -1
  9. package/dist/components/Slide/Player.cjs.js.map +1 -1
  10. package/dist/components/Slide/Player.d.ts +22 -2
  11. package/dist/components/Slide/Player.es.js +695 -474
  12. package/dist/components/Slide/Player.es.js.map +1 -1
  13. package/dist/components/Slide/Slide.cjs.js +1 -1
  14. package/dist/components/Slide/Slide.cjs.js.map +1 -1
  15. package/dist/components/Slide/Slide.es.js +673 -595
  16. package/dist/components/Slide/Slide.es.js.map +1 -1
  17. package/dist/components/Slide/Slide.stories.d.ts +2 -0
  18. package/dist/components/Slide/SubtitleOverlay.cjs.js.map +1 -1
  19. package/dist/components/Slide/SubtitleOverlay.es.js.map +1 -1
  20. package/dist/components/Slide/constants.cjs.js +1 -1
  21. package/dist/components/Slide/constants.cjs.js.map +1 -1
  22. package/dist/components/Slide/constants.d.ts +4 -2
  23. package/dist/components/Slide/constants.es.js +4 -2
  24. package/dist/components/Slide/constants.es.js.map +1 -1
  25. package/dist/components/Slide/useSlide.cjs.js +1 -1
  26. package/dist/components/Slide/useSlide.cjs.js.map +1 -1
  27. package/dist/components/Slide/useSlide.d.ts +2 -0
  28. package/dist/components/Slide/useSlide.es.js +124 -105
  29. package/dist/components/Slide/useSlide.es.js.map +1 -1
  30. package/dist/components/Slide/utils/audioSegments.cjs.js +2 -0
  31. package/dist/components/Slide/utils/audioSegments.cjs.js.map +1 -0
  32. package/dist/components/Slide/utils/audioSegments.d.ts +2 -0
  33. package/dist/components/Slide/utils/audioSegments.es.js +21 -0
  34. package/dist/components/Slide/utils/audioSegments.es.js.map +1 -0
  35. package/dist/components/Slide/utils/audioSegments.test.d.ts +1 -0
  36. package/dist/components/Slide/utils/playbackSequence.cjs.js +1 -1
  37. package/dist/components/Slide/utils/playbackSequence.cjs.js.map +1 -1
  38. package/dist/components/Slide/utils/playbackSequence.d.ts +10 -0
  39. package/dist/components/Slide/utils/playbackSequence.es.js +15 -6
  40. package/dist/components/Slide/utils/playbackSequence.es.js.map +1 -1
  41. package/dist/components/Slide/utils/playerKeyboardShortcuts.cjs.js +1 -1
  42. package/dist/components/Slide/utils/playerKeyboardShortcuts.cjs.js.map +1 -1
  43. package/dist/components/Slide/utils/playerKeyboardShortcuts.d.ts +1 -1
  44. package/dist/components/Slide/utils/playerKeyboardShortcuts.es.js +14 -5
  45. package/dist/components/Slide/utils/playerKeyboardShortcuts.es.js.map +1 -1
  46. package/dist/components/Slide/utils/segmentSeek.cjs.js +2 -0
  47. package/dist/components/Slide/utils/segmentSeek.cjs.js.map +1 -0
  48. package/dist/components/Slide/utils/segmentSeek.d.ts +8 -0
  49. package/dist/components/Slide/utils/segmentSeek.es.js +31 -0
  50. package/dist/components/Slide/utils/segmentSeek.es.js.map +1 -0
  51. package/dist/components/Slide/utils/segmentSeek.test.d.ts +1 -0
  52. package/dist/components/Slide/utils/streamingNavigation.cjs.js.map +1 -1
  53. package/dist/components/Slide/utils/streamingNavigation.es.js.map +1 -1
  54. package/dist/components/Slide/utils/subtitleCue.cjs.js +2 -2
  55. package/dist/components/Slide/utils/subtitleCue.cjs.js.map +1 -1
  56. package/dist/components/Slide/utils/subtitleCue.d.ts +31 -0
  57. package/dist/components/Slide/utils/subtitleCue.es.js +157 -6
  58. package/dist/components/Slide/utils/subtitleCue.es.js.map +1 -1
  59. package/dist/components/Slide/utils/subtitleJumpNavigation.cjs.js +2 -0
  60. package/dist/components/Slide/utils/subtitleJumpNavigation.cjs.js.map +1 -0
  61. package/dist/components/Slide/utils/subtitleJumpNavigation.d.ts +10 -0
  62. package/dist/components/Slide/utils/subtitleJumpNavigation.es.js +22 -0
  63. package/dist/components/Slide/utils/subtitleJumpNavigation.es.js.map +1 -0
  64. package/dist/components/Slide/utils/subtitleJumpNavigation.test.d.ts +1 -0
  65. package/dist/lib/interaction-defaults.cjs.js.map +1 -1
  66. package/dist/lib/interaction-defaults.es.js.map +1 -1
  67. package/dist/node_modules/@braintree/sanitize-url/dist/index.cjs.js +1 -1
  68. package/dist/node_modules/@braintree/sanitize-url/dist/index.es.js +1 -1
  69. package/dist/node_modules/classnames/index.cjs.js +1 -1
  70. package/dist/node_modules/classnames/index.es.js +1 -1
  71. package/dist/node_modules/lucide-react/dist/esm/icons/fast-forward.cjs.js +7 -0
  72. package/dist/node_modules/lucide-react/dist/esm/icons/fast-forward.cjs.js.map +1 -0
  73. package/dist/node_modules/lucide-react/dist/esm/icons/fast-forward.es.js +16 -0
  74. package/dist/node_modules/lucide-react/dist/esm/icons/fast-forward.es.js.map +1 -0
  75. package/dist/node_modules/lucide-react/dist/esm/icons/rewind.cjs.js +7 -0
  76. package/dist/node_modules/lucide-react/dist/esm/icons/rewind.cjs.js.map +1 -0
  77. package/dist/node_modules/lucide-react/dist/esm/icons/rewind.es.js +16 -0
  78. package/dist/node_modules/lucide-react/dist/esm/icons/rewind.es.js.map +1 -0
  79. package/dist/node_modules/lucide-react/dist/esm/icons/skip-back.cjs.js +7 -0
  80. package/dist/node_modules/lucide-react/dist/esm/icons/skip-back.cjs.js.map +1 -0
  81. package/dist/node_modules/lucide-react/dist/esm/icons/skip-back.es.js +16 -0
  82. package/dist/node_modules/lucide-react/dist/esm/icons/skip-back.es.js.map +1 -0
  83. package/dist/node_modules/lucide-react/dist/esm/icons/skip-forward.cjs.js +7 -0
  84. package/dist/node_modules/lucide-react/dist/esm/icons/skip-forward.cjs.js.map +1 -0
  85. package/dist/node_modules/lucide-react/dist/esm/icons/skip-forward.es.js +16 -0
  86. package/dist/node_modules/lucide-react/dist/esm/icons/skip-forward.es.js.map +1 -0
  87. package/package.json +1 -1
  88. package/dist/node_modules/lucide-react/dist/esm/icons/rotate-ccw.cjs.js +0 -7
  89. package/dist/node_modules/lucide-react/dist/esm/icons/rotate-ccw.cjs.js.map +0 -1
  90. package/dist/node_modules/lucide-react/dist/esm/icons/rotate-ccw.es.js +0 -16
  91. package/dist/node_modules/lucide-react/dist/esm/icons/rotate-ccw.es.js.map +0 -1
  92. package/dist/node_modules/lucide-react/dist/esm/icons/rotate-cw.cjs.js +0 -7
  93. package/dist/node_modules/lucide-react/dist/esm/icons/rotate-cw.cjs.js.map +0 -1
  94. package/dist/node_modules/lucide-react/dist/esm/icons/rotate-cw.es.js +0 -16
  95. package/dist/node_modules/lucide-react/dist/esm/icons/rotate-cw.es.js.map +0 -1
@@ -1,16 +1,25 @@
1
- const c = ({
1
+ const r = ({
2
2
  previousResetKey: n,
3
3
  nextResetKey: t,
4
- currentAudioKey: i,
5
- hasCompletedCurrentStepAudio: o
4
+ currentAudioKey: u,
5
+ hasCompletedCurrentStepAudio: a
6
6
  }) => {
7
7
  const e = n !== t;
8
8
  return {
9
9
  hasPlaybackContextChanged: e,
10
- shouldInitializeAudioSequence: e || !i && !o
10
+ shouldInitializeAudioSequence: e || !u && !a
11
11
  };
12
- };
12
+ }, s = ({
13
+ currentAudioKey: n,
14
+ currentAudioSequenceLength: t,
15
+ currentStepHasSpeakableElement: u,
16
+ hasCompletedCurrentStepAudio: a,
17
+ shouldBlockPlaybackForInteraction: e,
18
+ shouldPausePlaybackForCustomAction: i,
19
+ shouldSkipDefaultAudioStart: o
20
+ }) => n || t === 0 || o || i || !u || e ? !1 : !a;
13
21
  export {
14
- c as getPlaybackSequenceTransition
22
+ r as getPlaybackSequenceTransition,
23
+ s as shouldStartDefaultAudioSequence
15
24
  };
16
25
  //# sourceMappingURL=playbackSequence.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"playbackSequence.es.js","sources":["../../../../src/components/Slide/utils/playbackSequence.ts"],"sourcesContent":["export interface PlaybackSequenceTransitionOptions {\n previousResetKey: string | null;\n nextResetKey: string;\n currentAudioKey: string | null;\n hasCompletedCurrentStepAudio: boolean;\n}\n\nexport interface PlaybackSequenceTransitionResult {\n hasPlaybackContextChanged: boolean;\n shouldInitializeAudioSequence: boolean;\n}\n\nexport const getPlaybackSequenceTransition = ({\n previousResetKey,\n nextResetKey,\n currentAudioKey,\n hasCompletedCurrentStepAudio,\n}: PlaybackSequenceTransitionOptions): PlaybackSequenceTransitionResult => {\n const hasPlaybackContextChanged = previousResetKey !== nextResetKey;\n const shouldInitializeAudioSequence =\n hasPlaybackContextChanged ||\n (!currentAudioKey && !hasCompletedCurrentStepAudio);\n\n return {\n hasPlaybackContextChanged,\n shouldInitializeAudioSequence,\n };\n};\n"],"names":["getPlaybackSequenceTransition","previousResetKey","nextResetKey","currentAudioKey","hasCompletedCurrentStepAudio","hasPlaybackContextChanged"],"mappings":"AAYO,MAAMA,IAAgC,CAAC;AAAA,EAC5C,kBAAAC;AAAA,EACA,cAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,8BAAAC;AACF,MAA2E;AACzE,QAAMC,IAA4BJ,MAAqBC;AAKvD,SAAO;AAAA,IACL,2BAAAG;AAAA,IACA,+BALAA,KACC,CAACF,KAAmB,CAACC;AAAA,EAItB;AAEJ;"}
1
+ {"version":3,"file":"playbackSequence.es.js","sources":["../../../../src/components/Slide/utils/playbackSequence.ts"],"sourcesContent":["export interface PlaybackSequenceTransitionOptions {\n previousResetKey: string | null;\n nextResetKey: string;\n currentAudioKey: string | null;\n hasCompletedCurrentStepAudio: boolean;\n}\n\nexport interface PlaybackSequenceTransitionResult {\n hasPlaybackContextChanged: boolean;\n shouldInitializeAudioSequence: boolean;\n}\n\nexport interface DefaultAudioSequenceStartOptions {\n currentAudioKey: string | null;\n currentAudioSequenceLength: number;\n currentStepHasSpeakableElement: boolean;\n hasCompletedCurrentStepAudio: boolean;\n shouldBlockPlaybackForInteraction: boolean;\n shouldPausePlaybackForCustomAction: boolean;\n shouldSkipDefaultAudioStart: boolean;\n}\n\nexport const getPlaybackSequenceTransition = ({\n previousResetKey,\n nextResetKey,\n currentAudioKey,\n hasCompletedCurrentStepAudio,\n}: PlaybackSequenceTransitionOptions): PlaybackSequenceTransitionResult => {\n const hasPlaybackContextChanged = previousResetKey !== nextResetKey;\n const shouldInitializeAudioSequence =\n hasPlaybackContextChanged ||\n (!currentAudioKey && !hasCompletedCurrentStepAudio);\n\n return {\n hasPlaybackContextChanged,\n shouldInitializeAudioSequence,\n };\n};\n\nexport const shouldStartDefaultAudioSequence = ({\n currentAudioKey,\n currentAudioSequenceLength,\n currentStepHasSpeakableElement,\n hasCompletedCurrentStepAudio,\n shouldBlockPlaybackForInteraction,\n shouldPausePlaybackForCustomAction,\n shouldSkipDefaultAudioStart,\n}: DefaultAudioSequenceStartOptions) => {\n if (\n currentAudioKey ||\n currentAudioSequenceLength === 0 ||\n shouldSkipDefaultAudioStart\n ) {\n return false;\n }\n\n if (\n shouldPausePlaybackForCustomAction ||\n !currentStepHasSpeakableElement ||\n shouldBlockPlaybackForInteraction\n ) {\n return false;\n }\n\n return !hasCompletedCurrentStepAudio;\n};\n"],"names":["getPlaybackSequenceTransition","previousResetKey","nextResetKey","currentAudioKey","hasCompletedCurrentStepAudio","hasPlaybackContextChanged","shouldStartDefaultAudioSequence","currentAudioSequenceLength","currentStepHasSpeakableElement","shouldBlockPlaybackForInteraction","shouldPausePlaybackForCustomAction","shouldSkipDefaultAudioStart"],"mappings":"AAsBO,MAAMA,IAAgC,CAAC;AAAA,EAC5C,kBAAAC;AAAA,EACA,cAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,8BAAAC;AACF,MAA2E;AACzE,QAAMC,IAA4BJ,MAAqBC;AAKvD,SAAO;AAAA,IACL,2BAAAG;AAAA,IACA,+BALAA,KACC,CAACF,KAAmB,CAACC;AAAA,EAItB;AAEJ,GAEaE,IAAkC,CAAC;AAAA,EAC9C,iBAAAH;AAAA,EACA,4BAAAI;AAAA,EACA,gCAAAC;AAAA,EACA,8BAAAJ;AAAA,EACA,mCAAAK;AAAA,EACA,oCAAAC;AAAA,EACA,6BAAAC;AACF,MAEIR,KACAI,MAA+B,KAC/BI,KAMAD,KACA,CAACF,KACDC,IAEO,KAGF,CAACL;"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s='input, textarea, select, [contenteditable]:not([contenteditable="false"]), [role="textbox"], [role="slider"], [role="listbox"], [role="combobox"], [role="tablist"], [role="menu"], [role="tree"], [role="grid"], [data-player-keyboard-shortcuts-ignore="true"]',i="button, [role='button']",a=new Set;let r=null;const l=e=>{if(!e||typeof e!="object")return null;const t=e;return t.nodeType===3?t.parentElement??null:t},y=e=>{if(e.altKey||e.ctrlKey||e.metaKey||e.shiftKey)return null;const t=e.key.toLowerCase();if(e.code==="Space"||t===" "||t==="spacebar")return"togglePlayback";switch(t){case"arrowleft":return"previous";case"arrowright":return"next";case"f":return"fullscreen";case"c":return"subtitle";case"n":return"interaction";default:return null}},u=e=>{const t=l(e);if(!t)return!1;const o=t.tagName?.toLowerCase();if(o==="input"||o==="textarea"||o==="select"||t.isContentEditable)return!0;const n=t.getAttribute?.("contenteditable");return n!=null?n.toLowerCase()!=="false":!!t.closest?.(s)},c=e=>{const t=l(e);return t?t.tagName?.toLowerCase()==="button"?!0:!!t.closest?.(i):!1},d=(e,t)=>e.defaultPrevented||!t||u(e.target)?!0:t==="togglePlayback"&&c(e.target),b=e=>(a.add(e),(!r||!a.has(r))&&(r=e),()=>{a.delete(e),r===e&&(r=a.values().next().value??null)}),f=e=>{if(a.size===0){r=e;return}a.has(e)&&(r=e)},g=e=>r===e;exports.activatePlayerKeyboardShortcutOwner=f;exports.getPlayerKeyboardShortcutAction=y;exports.isActivePlayerKeyboardShortcutOwner=g;exports.isPlayerKeyboardShortcutEditableTarget=u;exports.isPlayerKeyboardShortcutNativeSpaceTarget=c;exports.registerPlayerKeyboardShortcutOwner=b;exports.shouldIgnorePlayerKeyboardShortcutEvent=d;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i='input, textarea, select, [contenteditable]:not([contenteditable="false"]), [role="textbox"], [role="slider"], [role="listbox"], [role="combobox"], [role="tablist"], [role="menu"], [role="tree"], [role="grid"], [data-player-keyboard-shortcuts-ignore="true"]',s="button, [role='button']",a=new Set;let r=null;const l=e=>{if(!e||typeof e!="object")return null;const t=e;return t.nodeType===3?t.parentElement??null:t},d=e=>{if(e.altKey||e.ctrlKey||e.metaKey)return null;const t=e.key.toLowerCase();if(e.shiftKey)switch(t){case"arrowleft":return"previousSubtitle";case"arrowright":return"nextSubtitle";default:return null}if(e.code==="Space"||t===" "||t==="spacebar")return"togglePlayback";switch(t){case"arrowleft":return"previous";case"arrowright":return"next";case"f":return"fullscreen";case"c":return"subtitle";case"n":return"interaction";default:return null}},u=e=>{const t=l(e);if(!t)return!1;const o=t.tagName?.toLowerCase();if(o==="input"||o==="textarea"||o==="select"||t.isContentEditable)return!0;const n=t.getAttribute?.("contenteditable");return n!=null?n.toLowerCase()!=="false":!!t.closest?.(i)},c=e=>{const t=l(e);return t?t.tagName?.toLowerCase()==="button"?!0:!!t.closest?.(s):!1},y=(e,t)=>e.defaultPrevented||!t||u(e.target)?!0:t==="togglePlayback"&&c(e.target),b=e=>(a.add(e),(!r||!a.has(r))&&(r=e),()=>{a.delete(e),r===e&&(r=a.values().next().value??null)}),f=e=>{if(a.size===0){r=e;return}a.has(e)&&(r=e)},g=e=>r===e;exports.activatePlayerKeyboardShortcutOwner=f;exports.getPlayerKeyboardShortcutAction=d;exports.isActivePlayerKeyboardShortcutOwner=g;exports.isPlayerKeyboardShortcutEditableTarget=u;exports.isPlayerKeyboardShortcutNativeSpaceTarget=c;exports.registerPlayerKeyboardShortcutOwner=b;exports.shouldIgnorePlayerKeyboardShortcutEvent=y;
2
2
  //# sourceMappingURL=playerKeyboardShortcuts.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"playerKeyboardShortcuts.cjs.js","sources":["../../../../src/components/Slide/utils/playerKeyboardShortcuts.ts"],"sourcesContent":["export type PlayerKeyboardShortcutAction =\n | \"togglePlayback\"\n | \"previous\"\n | \"next\"\n | \"fullscreen\"\n | \"subtitle\"\n | \"interaction\";\n\nexport interface PlayerKeyboardShortcutEventLike {\n altKey?: boolean;\n code?: string;\n ctrlKey?: boolean;\n defaultPrevented?: boolean;\n key: string;\n metaKey?: boolean;\n shiftKey?: boolean;\n target?: EventTarget | null;\n}\n\ntype KeyboardShortcutTarget = EventTarget & {\n closest?: (selectors: string) => unknown;\n getAttribute?: (qualifiedName: string) => string | null;\n isContentEditable?: boolean;\n nodeType?: number;\n parentElement?: Element | null;\n tagName?: string;\n};\n\nconst EDITABLE_SELECTOR =\n 'input, textarea, select, [contenteditable]:not([contenteditable=\"false\"]), [role=\"textbox\"], [role=\"slider\"], [role=\"listbox\"], [role=\"combobox\"], [role=\"tablist\"], [role=\"menu\"], [role=\"tree\"], [role=\"grid\"], [data-player-keyboard-shortcuts-ignore=\"true\"]';\n\nconst NATIVE_SPACE_TARGET_SELECTOR = \"button, [role='button']\";\n\nconst playerKeyboardShortcutOwners = new Set<string>();\nlet activePlayerKeyboardShortcutOwnerId: string | null = null;\n\nconst getTargetCandidate = (\n target: EventTarget | null | undefined\n): KeyboardShortcutTarget | null => {\n if (!target || typeof target !== \"object\") {\n return null;\n }\n\n const candidate = target as KeyboardShortcutTarget;\n\n if (candidate.nodeType === 3) {\n return (candidate.parentElement as KeyboardShortcutTarget | null) ?? null;\n }\n\n return candidate;\n};\n\nexport const getPlayerKeyboardShortcutAction = (\n event: PlayerKeyboardShortcutEventLike\n): PlayerKeyboardShortcutAction | null => {\n if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {\n return null;\n }\n\n const normalizedKey = event.key.toLowerCase();\n\n if (\n event.code === \"Space\" ||\n normalizedKey === \" \" ||\n normalizedKey === \"spacebar\"\n ) {\n return \"togglePlayback\";\n }\n\n switch (normalizedKey) {\n case \"arrowleft\":\n return \"previous\";\n case \"arrowright\":\n return \"next\";\n case \"f\":\n return \"fullscreen\";\n case \"c\":\n return \"subtitle\";\n case \"n\":\n return \"interaction\";\n default:\n return null;\n }\n};\n\nexport const isPlayerKeyboardShortcutEditableTarget = (\n target: EventTarget | null | undefined\n) => {\n const candidate = getTargetCandidate(target);\n\n if (!candidate) {\n return false;\n }\n\n const tagName = candidate.tagName?.toLowerCase();\n\n if (tagName === \"input\" || tagName === \"textarea\" || tagName === \"select\") {\n return true;\n }\n\n if (candidate.isContentEditable) {\n return true;\n }\n\n const contentEditable = candidate.getAttribute?.(\"contenteditable\");\n\n if (contentEditable !== undefined && contentEditable !== null) {\n return contentEditable.toLowerCase() !== \"false\";\n }\n\n return Boolean(candidate.closest?.(EDITABLE_SELECTOR));\n};\n\nexport const isPlayerKeyboardShortcutNativeSpaceTarget = (\n target: EventTarget | null | undefined\n) => {\n const candidate = getTargetCandidate(target);\n\n if (!candidate) {\n return false;\n }\n\n const tagName = candidate.tagName?.toLowerCase();\n\n if (tagName === \"button\") {\n return true;\n }\n\n return Boolean(candidate.closest?.(NATIVE_SPACE_TARGET_SELECTOR));\n};\n\nexport const shouldIgnorePlayerKeyboardShortcutEvent = (\n event: PlayerKeyboardShortcutEventLike,\n action: PlayerKeyboardShortcutAction | null\n) => {\n if (event.defaultPrevented || !action) {\n return true;\n }\n\n if (isPlayerKeyboardShortcutEditableTarget(event.target)) {\n return true;\n }\n\n return (\n action === \"togglePlayback\" &&\n isPlayerKeyboardShortcutNativeSpaceTarget(event.target)\n );\n};\n\nexport const registerPlayerKeyboardShortcutOwner = (ownerId: string) => {\n playerKeyboardShortcutOwners.add(ownerId);\n\n if (\n !activePlayerKeyboardShortcutOwnerId ||\n !playerKeyboardShortcutOwners.has(activePlayerKeyboardShortcutOwnerId)\n ) {\n activePlayerKeyboardShortcutOwnerId = ownerId;\n }\n\n return () => {\n playerKeyboardShortcutOwners.delete(ownerId);\n\n if (activePlayerKeyboardShortcutOwnerId !== ownerId) {\n return;\n }\n\n activePlayerKeyboardShortcutOwnerId =\n playerKeyboardShortcutOwners.values().next().value ?? null;\n };\n};\n\nexport const activatePlayerKeyboardShortcutOwner = (ownerId: string) => {\n if (playerKeyboardShortcutOwners.size === 0) {\n activePlayerKeyboardShortcutOwnerId = ownerId;\n return;\n }\n\n if (playerKeyboardShortcutOwners.has(ownerId)) {\n activePlayerKeyboardShortcutOwnerId = ownerId;\n }\n};\n\nexport const isActivePlayerKeyboardShortcutOwner = (ownerId: string) =>\n activePlayerKeyboardShortcutOwnerId === ownerId;\n\nexport const resetPlayerKeyboardShortcutOwnersForTest = () => {\n playerKeyboardShortcutOwners.clear();\n activePlayerKeyboardShortcutOwnerId = null;\n};\n"],"names":["EDITABLE_SELECTOR","NATIVE_SPACE_TARGET_SELECTOR","playerKeyboardShortcutOwners","activePlayerKeyboardShortcutOwnerId","getTargetCandidate","target","candidate","getPlayerKeyboardShortcutAction","event","normalizedKey","isPlayerKeyboardShortcutEditableTarget","tagName","contentEditable","isPlayerKeyboardShortcutNativeSpaceTarget","shouldIgnorePlayerKeyboardShortcutEvent","action","registerPlayerKeyboardShortcutOwner","ownerId","activatePlayerKeyboardShortcutOwner","isActivePlayerKeyboardShortcutOwner"],"mappings":"gFA4BA,MAAMA,EACJ,mQAEIC,EAA+B,0BAE/BC,MAAmC,IACzC,IAAIC,EAAqD,KAEzD,MAAMC,EACJC,GACkC,CAClC,GAAI,CAACA,GAAU,OAAOA,GAAW,SAC/B,OAAO,KAGT,MAAMC,EAAYD,EAElB,OAAIC,EAAU,WAAa,EACjBA,EAAU,eAAmD,KAGhEA,CACT,EAEaC,EACXC,GACwC,CACxC,GAAIA,EAAM,QAAUA,EAAM,SAAWA,EAAM,SAAWA,EAAM,SAC1D,OAAO,KAGT,MAAMC,EAAgBD,EAAM,IAAI,YAAA,EAEhC,GACEA,EAAM,OAAS,SACfC,IAAkB,KAClBA,IAAkB,WAElB,MAAO,iBAGT,OAAQA,EAAA,CACN,IAAK,YACH,MAAO,WACT,IAAK,aACH,MAAO,OACT,IAAK,IACH,MAAO,aACT,IAAK,IACH,MAAO,WACT,IAAK,IACH,MAAO,cACT,QACE,OAAO,IAAA,CAEb,EAEaC,EACXL,GACG,CACH,MAAMC,EAAYF,EAAmBC,CAAM,EAE3C,GAAI,CAACC,EACH,MAAO,GAGT,MAAMK,EAAUL,EAAU,SAAS,YAAA,EAMnC,GAJIK,IAAY,SAAWA,IAAY,YAAcA,IAAY,UAI7DL,EAAU,kBACZ,MAAO,GAGT,MAAMM,EAAkBN,EAAU,eAAe,iBAAiB,EAElE,OAAqCM,GAAoB,KAChDA,EAAgB,gBAAkB,QAGpC,EAAQN,EAAU,UAAUN,CAAiB,CACtD,EAEaa,EACXR,GACG,CACH,MAAMC,EAAYF,EAAmBC,CAAM,EAE3C,OAAKC,EAIWA,EAAU,SAAS,YAAA,IAEnB,SACP,GAGF,EAAQA,EAAU,UAAUL,CAA4B,EATtD,EAUX,EAEaa,EAA0C,CACrDN,EACAO,IAEIP,EAAM,kBAAoB,CAACO,GAI3BL,EAAuCF,EAAM,MAAM,EAC9C,GAIPO,IAAW,kBACXF,EAA0CL,EAAM,MAAM,EAI7CQ,EAAuCC,IAClDf,EAA6B,IAAIe,CAAO,GAGtC,CAACd,GACD,CAACD,EAA6B,IAAIC,CAAmC,KAErEA,EAAsCc,GAGjC,IAAM,CACXf,EAA6B,OAAOe,CAAO,EAEvCd,IAAwCc,IAI5Cd,EACED,EAA6B,OAAA,EAAS,KAAA,EAAO,OAAS,KAC1D,GAGWgB,EAAuCD,GAAoB,CACtE,GAAIf,EAA6B,OAAS,EAAG,CAC3CC,EAAsCc,EACtC,MACF,CAEIf,EAA6B,IAAIe,CAAO,IAC1Cd,EAAsCc,EAE1C,EAEaE,EAAuCF,GAClDd,IAAwCc"}
1
+ {"version":3,"file":"playerKeyboardShortcuts.cjs.js","sources":["../../../../src/components/Slide/utils/playerKeyboardShortcuts.ts"],"sourcesContent":["export type PlayerKeyboardShortcutAction =\n | \"togglePlayback\"\n | \"previous\"\n | \"next\"\n | \"previousSubtitle\"\n | \"nextSubtitle\"\n | \"fullscreen\"\n | \"subtitle\"\n | \"interaction\";\n\nexport interface PlayerKeyboardShortcutEventLike {\n altKey?: boolean;\n code?: string;\n ctrlKey?: boolean;\n defaultPrevented?: boolean;\n key: string;\n metaKey?: boolean;\n shiftKey?: boolean;\n target?: EventTarget | null;\n}\n\ntype KeyboardShortcutTarget = EventTarget & {\n closest?: (selectors: string) => unknown;\n getAttribute?: (qualifiedName: string) => string | null;\n isContentEditable?: boolean;\n nodeType?: number;\n parentElement?: Element | null;\n tagName?: string;\n};\n\nconst EDITABLE_SELECTOR =\n 'input, textarea, select, [contenteditable]:not([contenteditable=\"false\"]), [role=\"textbox\"], [role=\"slider\"], [role=\"listbox\"], [role=\"combobox\"], [role=\"tablist\"], [role=\"menu\"], [role=\"tree\"], [role=\"grid\"], [data-player-keyboard-shortcuts-ignore=\"true\"]';\n\nconst NATIVE_SPACE_TARGET_SELECTOR = \"button, [role='button']\";\n\nconst playerKeyboardShortcutOwners = new Set<string>();\nlet activePlayerKeyboardShortcutOwnerId: string | null = null;\n\nconst getTargetCandidate = (\n target: EventTarget | null | undefined\n): KeyboardShortcutTarget | null => {\n if (!target || typeof target !== \"object\") {\n return null;\n }\n\n const candidate = target as KeyboardShortcutTarget;\n\n if (candidate.nodeType === 3) {\n return (candidate.parentElement as KeyboardShortcutTarget | null) ?? null;\n }\n\n return candidate;\n};\n\nexport const getPlayerKeyboardShortcutAction = (\n event: PlayerKeyboardShortcutEventLike\n): PlayerKeyboardShortcutAction | null => {\n if (event.altKey || event.ctrlKey || event.metaKey) {\n return null;\n }\n\n const normalizedKey = event.key.toLowerCase();\n\n if (event.shiftKey) {\n switch (normalizedKey) {\n case \"arrowleft\":\n return \"previousSubtitle\";\n case \"arrowright\":\n return \"nextSubtitle\";\n default:\n return null;\n }\n }\n\n if (\n event.code === \"Space\" ||\n normalizedKey === \" \" ||\n normalizedKey === \"spacebar\"\n ) {\n return \"togglePlayback\";\n }\n\n switch (normalizedKey) {\n case \"arrowleft\":\n return \"previous\";\n case \"arrowright\":\n return \"next\";\n case \"f\":\n return \"fullscreen\";\n case \"c\":\n return \"subtitle\";\n case \"n\":\n return \"interaction\";\n default:\n return null;\n }\n};\n\nexport const isPlayerKeyboardShortcutEditableTarget = (\n target: EventTarget | null | undefined\n) => {\n const candidate = getTargetCandidate(target);\n\n if (!candidate) {\n return false;\n }\n\n const tagName = candidate.tagName?.toLowerCase();\n\n if (tagName === \"input\" || tagName === \"textarea\" || tagName === \"select\") {\n return true;\n }\n\n if (candidate.isContentEditable) {\n return true;\n }\n\n const contentEditable = candidate.getAttribute?.(\"contenteditable\");\n\n if (contentEditable !== undefined && contentEditable !== null) {\n return contentEditable.toLowerCase() !== \"false\";\n }\n\n return Boolean(candidate.closest?.(EDITABLE_SELECTOR));\n};\n\nexport const isPlayerKeyboardShortcutNativeSpaceTarget = (\n target: EventTarget | null | undefined\n) => {\n const candidate = getTargetCandidate(target);\n\n if (!candidate) {\n return false;\n }\n\n const tagName = candidate.tagName?.toLowerCase();\n\n if (tagName === \"button\") {\n return true;\n }\n\n return Boolean(candidate.closest?.(NATIVE_SPACE_TARGET_SELECTOR));\n};\n\nexport const shouldIgnorePlayerKeyboardShortcutEvent = (\n event: PlayerKeyboardShortcutEventLike,\n action: PlayerKeyboardShortcutAction | null\n) => {\n if (event.defaultPrevented || !action) {\n return true;\n }\n\n if (isPlayerKeyboardShortcutEditableTarget(event.target)) {\n return true;\n }\n\n return (\n action === \"togglePlayback\" &&\n isPlayerKeyboardShortcutNativeSpaceTarget(event.target)\n );\n};\n\nexport const registerPlayerKeyboardShortcutOwner = (ownerId: string) => {\n playerKeyboardShortcutOwners.add(ownerId);\n\n if (\n !activePlayerKeyboardShortcutOwnerId ||\n !playerKeyboardShortcutOwners.has(activePlayerKeyboardShortcutOwnerId)\n ) {\n activePlayerKeyboardShortcutOwnerId = ownerId;\n }\n\n return () => {\n playerKeyboardShortcutOwners.delete(ownerId);\n\n if (activePlayerKeyboardShortcutOwnerId !== ownerId) {\n return;\n }\n\n activePlayerKeyboardShortcutOwnerId =\n playerKeyboardShortcutOwners.values().next().value ?? null;\n };\n};\n\nexport const activatePlayerKeyboardShortcutOwner = (ownerId: string) => {\n if (playerKeyboardShortcutOwners.size === 0) {\n activePlayerKeyboardShortcutOwnerId = ownerId;\n return;\n }\n\n if (playerKeyboardShortcutOwners.has(ownerId)) {\n activePlayerKeyboardShortcutOwnerId = ownerId;\n }\n};\n\nexport const isActivePlayerKeyboardShortcutOwner = (ownerId: string) =>\n activePlayerKeyboardShortcutOwnerId === ownerId;\n\nexport const resetPlayerKeyboardShortcutOwnersForTest = () => {\n playerKeyboardShortcutOwners.clear();\n activePlayerKeyboardShortcutOwnerId = null;\n};\n"],"names":["EDITABLE_SELECTOR","NATIVE_SPACE_TARGET_SELECTOR","playerKeyboardShortcutOwners","activePlayerKeyboardShortcutOwnerId","getTargetCandidate","target","candidate","getPlayerKeyboardShortcutAction","event","normalizedKey","isPlayerKeyboardShortcutEditableTarget","tagName","contentEditable","isPlayerKeyboardShortcutNativeSpaceTarget","shouldIgnorePlayerKeyboardShortcutEvent","action","registerPlayerKeyboardShortcutOwner","ownerId","activatePlayerKeyboardShortcutOwner","isActivePlayerKeyboardShortcutOwner"],"mappings":"gFA8BA,MAAMA,EACJ,mQAEIC,EAA+B,0BAE/BC,MAAmC,IACzC,IAAIC,EAAqD,KAEzD,MAAMC,EACJC,GACkC,CAClC,GAAI,CAACA,GAAU,OAAOA,GAAW,SAC/B,OAAO,KAGT,MAAMC,EAAYD,EAElB,OAAIC,EAAU,WAAa,EACjBA,EAAU,eAAmD,KAGhEA,CACT,EAEaC,EACXC,GACwC,CACxC,GAAIA,EAAM,QAAUA,EAAM,SAAWA,EAAM,QACzC,OAAO,KAGT,MAAMC,EAAgBD,EAAM,IAAI,YAAA,EAEhC,GAAIA,EAAM,SACR,OAAQC,EAAA,CACN,IAAK,YACH,MAAO,mBACT,IAAK,aACH,MAAO,eACT,QACE,OAAO,IAAA,CAIb,GACED,EAAM,OAAS,SACfC,IAAkB,KAClBA,IAAkB,WAElB,MAAO,iBAGT,OAAQA,EAAA,CACN,IAAK,YACH,MAAO,WACT,IAAK,aACH,MAAO,OACT,IAAK,IACH,MAAO,aACT,IAAK,IACH,MAAO,WACT,IAAK,IACH,MAAO,cACT,QACE,OAAO,IAAA,CAEb,EAEaC,EACXL,GACG,CACH,MAAMC,EAAYF,EAAmBC,CAAM,EAE3C,GAAI,CAACC,EACH,MAAO,GAGT,MAAMK,EAAUL,EAAU,SAAS,YAAA,EAMnC,GAJIK,IAAY,SAAWA,IAAY,YAAcA,IAAY,UAI7DL,EAAU,kBACZ,MAAO,GAGT,MAAMM,EAAkBN,EAAU,eAAe,iBAAiB,EAElE,OAAqCM,GAAoB,KAChDA,EAAgB,gBAAkB,QAGpC,EAAQN,EAAU,UAAUN,CAAiB,CACtD,EAEaa,EACXR,GACG,CACH,MAAMC,EAAYF,EAAmBC,CAAM,EAE3C,OAAKC,EAIWA,EAAU,SAAS,YAAA,IAEnB,SACP,GAGF,EAAQA,EAAU,UAAUL,CAA4B,EATtD,EAUX,EAEaa,EAA0C,CACrDN,EACAO,IAEIP,EAAM,kBAAoB,CAACO,GAI3BL,EAAuCF,EAAM,MAAM,EAC9C,GAIPO,IAAW,kBACXF,EAA0CL,EAAM,MAAM,EAI7CQ,EAAuCC,IAClDf,EAA6B,IAAIe,CAAO,GAGtC,CAACd,GACD,CAACD,EAA6B,IAAIC,CAAmC,KAErEA,EAAsCc,GAGjC,IAAM,CACXf,EAA6B,OAAOe,CAAO,EAEvCd,IAAwCc,IAI5Cd,EACED,EAA6B,OAAA,EAAS,KAAA,EAAO,OAAS,KAC1D,GAGWgB,EAAuCD,GAAoB,CACtE,GAAIf,EAA6B,OAAS,EAAG,CAC3CC,EAAsCc,EACtC,MACF,CAEIf,EAA6B,IAAIe,CAAO,IAC1Cd,EAAsCc,EAE1C,EAEaE,EAAuCF,GAClDd,IAAwCc"}
@@ -1,4 +1,4 @@
1
- export type PlayerKeyboardShortcutAction = "togglePlayback" | "previous" | "next" | "fullscreen" | "subtitle" | "interaction";
1
+ export type PlayerKeyboardShortcutAction = "togglePlayback" | "previous" | "next" | "previousSubtitle" | "nextSubtitle" | "fullscreen" | "subtitle" | "interaction";
2
2
  export interface PlayerKeyboardShortcutEventLike {
3
3
  altKey?: boolean;
4
4
  code?: string;
@@ -6,9 +6,18 @@ const l = (e) => {
6
6
  const t = e;
7
7
  return t.nodeType === 3 ? t.parentElement ?? null : t;
8
8
  }, d = (e) => {
9
- if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey)
9
+ if (e.altKey || e.ctrlKey || e.metaKey)
10
10
  return null;
11
11
  const t = e.key.toLowerCase();
12
+ if (e.shiftKey)
13
+ switch (t) {
14
+ case "arrowleft":
15
+ return "previousSubtitle";
16
+ case "arrowright":
17
+ return "nextSubtitle";
18
+ default:
19
+ return null;
20
+ }
12
21
  if (e.code === "Space" || t === " " || t === "spacebar")
13
22
  return "togglePlayback";
14
23
  switch (t) {
@@ -37,9 +46,9 @@ const l = (e) => {
37
46
  }, i = (e) => {
38
47
  const t = l(e);
39
48
  return t ? t.tagName?.toLowerCase() === "button" ? !0 : !!t.closest?.(c) : !1;
40
- }, b = (e, t) => e.defaultPrevented || !t || s(e.target) ? !0 : t === "togglePlayback" && i(e.target), y = (e) => (a.add(e), (!r || !a.has(r)) && (r = e), () => {
49
+ }, b = (e, t) => e.defaultPrevented || !t || s(e.target) ? !0 : t === "togglePlayback" && i(e.target), f = (e) => (a.add(e), (!r || !a.has(r)) && (r = e), () => {
41
50
  a.delete(e), r === e && (r = a.values().next().value ?? null);
42
- }), f = (e) => {
51
+ }), y = (e) => {
43
52
  if (a.size === 0) {
44
53
  r = e;
45
54
  return;
@@ -47,12 +56,12 @@ const l = (e) => {
47
56
  a.has(e) && (r = e);
48
57
  }, g = (e) => r === e;
49
58
  export {
50
- f as activatePlayerKeyboardShortcutOwner,
59
+ y as activatePlayerKeyboardShortcutOwner,
51
60
  d as getPlayerKeyboardShortcutAction,
52
61
  g as isActivePlayerKeyboardShortcutOwner,
53
62
  s as isPlayerKeyboardShortcutEditableTarget,
54
63
  i as isPlayerKeyboardShortcutNativeSpaceTarget,
55
- y as registerPlayerKeyboardShortcutOwner,
64
+ f as registerPlayerKeyboardShortcutOwner,
56
65
  b as shouldIgnorePlayerKeyboardShortcutEvent
57
66
  };
58
67
  //# sourceMappingURL=playerKeyboardShortcuts.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"playerKeyboardShortcuts.es.js","sources":["../../../../src/components/Slide/utils/playerKeyboardShortcuts.ts"],"sourcesContent":["export type PlayerKeyboardShortcutAction =\n | \"togglePlayback\"\n | \"previous\"\n | \"next\"\n | \"fullscreen\"\n | \"subtitle\"\n | \"interaction\";\n\nexport interface PlayerKeyboardShortcutEventLike {\n altKey?: boolean;\n code?: string;\n ctrlKey?: boolean;\n defaultPrevented?: boolean;\n key: string;\n metaKey?: boolean;\n shiftKey?: boolean;\n target?: EventTarget | null;\n}\n\ntype KeyboardShortcutTarget = EventTarget & {\n closest?: (selectors: string) => unknown;\n getAttribute?: (qualifiedName: string) => string | null;\n isContentEditable?: boolean;\n nodeType?: number;\n parentElement?: Element | null;\n tagName?: string;\n};\n\nconst EDITABLE_SELECTOR =\n 'input, textarea, select, [contenteditable]:not([contenteditable=\"false\"]), [role=\"textbox\"], [role=\"slider\"], [role=\"listbox\"], [role=\"combobox\"], [role=\"tablist\"], [role=\"menu\"], [role=\"tree\"], [role=\"grid\"], [data-player-keyboard-shortcuts-ignore=\"true\"]';\n\nconst NATIVE_SPACE_TARGET_SELECTOR = \"button, [role='button']\";\n\nconst playerKeyboardShortcutOwners = new Set<string>();\nlet activePlayerKeyboardShortcutOwnerId: string | null = null;\n\nconst getTargetCandidate = (\n target: EventTarget | null | undefined\n): KeyboardShortcutTarget | null => {\n if (!target || typeof target !== \"object\") {\n return null;\n }\n\n const candidate = target as KeyboardShortcutTarget;\n\n if (candidate.nodeType === 3) {\n return (candidate.parentElement as KeyboardShortcutTarget | null) ?? null;\n }\n\n return candidate;\n};\n\nexport const getPlayerKeyboardShortcutAction = (\n event: PlayerKeyboardShortcutEventLike\n): PlayerKeyboardShortcutAction | null => {\n if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {\n return null;\n }\n\n const normalizedKey = event.key.toLowerCase();\n\n if (\n event.code === \"Space\" ||\n normalizedKey === \" \" ||\n normalizedKey === \"spacebar\"\n ) {\n return \"togglePlayback\";\n }\n\n switch (normalizedKey) {\n case \"arrowleft\":\n return \"previous\";\n case \"arrowright\":\n return \"next\";\n case \"f\":\n return \"fullscreen\";\n case \"c\":\n return \"subtitle\";\n case \"n\":\n return \"interaction\";\n default:\n return null;\n }\n};\n\nexport const isPlayerKeyboardShortcutEditableTarget = (\n target: EventTarget | null | undefined\n) => {\n const candidate = getTargetCandidate(target);\n\n if (!candidate) {\n return false;\n }\n\n const tagName = candidate.tagName?.toLowerCase();\n\n if (tagName === \"input\" || tagName === \"textarea\" || tagName === \"select\") {\n return true;\n }\n\n if (candidate.isContentEditable) {\n return true;\n }\n\n const contentEditable = candidate.getAttribute?.(\"contenteditable\");\n\n if (contentEditable !== undefined && contentEditable !== null) {\n return contentEditable.toLowerCase() !== \"false\";\n }\n\n return Boolean(candidate.closest?.(EDITABLE_SELECTOR));\n};\n\nexport const isPlayerKeyboardShortcutNativeSpaceTarget = (\n target: EventTarget | null | undefined\n) => {\n const candidate = getTargetCandidate(target);\n\n if (!candidate) {\n return false;\n }\n\n const tagName = candidate.tagName?.toLowerCase();\n\n if (tagName === \"button\") {\n return true;\n }\n\n return Boolean(candidate.closest?.(NATIVE_SPACE_TARGET_SELECTOR));\n};\n\nexport const shouldIgnorePlayerKeyboardShortcutEvent = (\n event: PlayerKeyboardShortcutEventLike,\n action: PlayerKeyboardShortcutAction | null\n) => {\n if (event.defaultPrevented || !action) {\n return true;\n }\n\n if (isPlayerKeyboardShortcutEditableTarget(event.target)) {\n return true;\n }\n\n return (\n action === \"togglePlayback\" &&\n isPlayerKeyboardShortcutNativeSpaceTarget(event.target)\n );\n};\n\nexport const registerPlayerKeyboardShortcutOwner = (ownerId: string) => {\n playerKeyboardShortcutOwners.add(ownerId);\n\n if (\n !activePlayerKeyboardShortcutOwnerId ||\n !playerKeyboardShortcutOwners.has(activePlayerKeyboardShortcutOwnerId)\n ) {\n activePlayerKeyboardShortcutOwnerId = ownerId;\n }\n\n return () => {\n playerKeyboardShortcutOwners.delete(ownerId);\n\n if (activePlayerKeyboardShortcutOwnerId !== ownerId) {\n return;\n }\n\n activePlayerKeyboardShortcutOwnerId =\n playerKeyboardShortcutOwners.values().next().value ?? null;\n };\n};\n\nexport const activatePlayerKeyboardShortcutOwner = (ownerId: string) => {\n if (playerKeyboardShortcutOwners.size === 0) {\n activePlayerKeyboardShortcutOwnerId = ownerId;\n return;\n }\n\n if (playerKeyboardShortcutOwners.has(ownerId)) {\n activePlayerKeyboardShortcutOwnerId = ownerId;\n }\n};\n\nexport const isActivePlayerKeyboardShortcutOwner = (ownerId: string) =>\n activePlayerKeyboardShortcutOwnerId === ownerId;\n\nexport const resetPlayerKeyboardShortcutOwnersForTest = () => {\n playerKeyboardShortcutOwners.clear();\n activePlayerKeyboardShortcutOwnerId = null;\n};\n"],"names":["EDITABLE_SELECTOR","NATIVE_SPACE_TARGET_SELECTOR","playerKeyboardShortcutOwners","activePlayerKeyboardShortcutOwnerId","getTargetCandidate","target","candidate","getPlayerKeyboardShortcutAction","event","normalizedKey","isPlayerKeyboardShortcutEditableTarget","tagName","contentEditable","isPlayerKeyboardShortcutNativeSpaceTarget","shouldIgnorePlayerKeyboardShortcutEvent","action","registerPlayerKeyboardShortcutOwner","ownerId","activatePlayerKeyboardShortcutOwner","isActivePlayerKeyboardShortcutOwner"],"mappings":"AA4BA,MAAMA,IACJ,oQAEIC,IAA+B,2BAE/BC,wBAAmC,IAAA;AACzC,IAAIC,IAAqD;AAEzD,MAAMC,IAAqB,CACzBC,MACkC;AAClC,MAAI,CAACA,KAAU,OAAOA,KAAW;AAC/B,WAAO;AAGT,QAAMC,IAAYD;AAElB,SAAIC,EAAU,aAAa,IACjBA,EAAU,iBAAmD,OAGhEA;AACT,GAEaC,IAAkC,CAC7CC,MACwC;AACxC,MAAIA,EAAM,UAAUA,EAAM,WAAWA,EAAM,WAAWA,EAAM;AAC1D,WAAO;AAGT,QAAMC,IAAgBD,EAAM,IAAI,YAAA;AAEhC,MACEA,EAAM,SAAS,WACfC,MAAkB,OAClBA,MAAkB;AAElB,WAAO;AAGT,UAAQA,GAAA;AAAA,IACN,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EAAA;AAEb,GAEaC,IAAyC,CACpDL,MACG;AACH,QAAMC,IAAYF,EAAmBC,CAAM;AAE3C,MAAI,CAACC;AACH,WAAO;AAGT,QAAMK,IAAUL,EAAU,SAAS,YAAA;AAMnC,MAJIK,MAAY,WAAWA,MAAY,cAAcA,MAAY,YAI7DL,EAAU;AACZ,WAAO;AAGT,QAAMM,IAAkBN,EAAU,eAAe,iBAAiB;AAElE,SAAqCM,KAAoB,OAChDA,EAAgB,kBAAkB,UAGpC,EAAQN,EAAU,UAAUN,CAAiB;AACtD,GAEaa,IAA4C,CACvDR,MACG;AACH,QAAMC,IAAYF,EAAmBC,CAAM;AAE3C,SAAKC,IAIWA,EAAU,SAAS,YAAA,MAEnB,WACP,KAGF,EAAQA,EAAU,UAAUL,CAA4B,IATtD;AAUX,GAEaa,IAA0C,CACrDN,GACAO,MAEIP,EAAM,oBAAoB,CAACO,KAI3BL,EAAuCF,EAAM,MAAM,IAC9C,KAIPO,MAAW,oBACXF,EAA0CL,EAAM,MAAM,GAI7CQ,IAAsC,CAACC,OAClDf,EAA6B,IAAIe,CAAO,IAGtC,CAACd,KACD,CAACD,EAA6B,IAAIC,CAAmC,OAErEA,IAAsCc,IAGjC,MAAM;AAGX,EAFAf,EAA6B,OAAOe,CAAO,GAEvCd,MAAwCc,MAI5Cd,IACED,EAA6B,OAAA,EAAS,KAAA,EAAO,SAAS;AAC1D,IAGWgB,IAAsC,CAACD,MAAoB;AACtE,MAAIf,EAA6B,SAAS,GAAG;AAC3C,IAAAC,IAAsCc;AACtC;AAAA,EACF;AAEA,EAAIf,EAA6B,IAAIe,CAAO,MAC1Cd,IAAsCc;AAE1C,GAEaE,IAAsC,CAACF,MAClDd,MAAwCc;"}
1
+ {"version":3,"file":"playerKeyboardShortcuts.es.js","sources":["../../../../src/components/Slide/utils/playerKeyboardShortcuts.ts"],"sourcesContent":["export type PlayerKeyboardShortcutAction =\n | \"togglePlayback\"\n | \"previous\"\n | \"next\"\n | \"previousSubtitle\"\n | \"nextSubtitle\"\n | \"fullscreen\"\n | \"subtitle\"\n | \"interaction\";\n\nexport interface PlayerKeyboardShortcutEventLike {\n altKey?: boolean;\n code?: string;\n ctrlKey?: boolean;\n defaultPrevented?: boolean;\n key: string;\n metaKey?: boolean;\n shiftKey?: boolean;\n target?: EventTarget | null;\n}\n\ntype KeyboardShortcutTarget = EventTarget & {\n closest?: (selectors: string) => unknown;\n getAttribute?: (qualifiedName: string) => string | null;\n isContentEditable?: boolean;\n nodeType?: number;\n parentElement?: Element | null;\n tagName?: string;\n};\n\nconst EDITABLE_SELECTOR =\n 'input, textarea, select, [contenteditable]:not([contenteditable=\"false\"]), [role=\"textbox\"], [role=\"slider\"], [role=\"listbox\"], [role=\"combobox\"], [role=\"tablist\"], [role=\"menu\"], [role=\"tree\"], [role=\"grid\"], [data-player-keyboard-shortcuts-ignore=\"true\"]';\n\nconst NATIVE_SPACE_TARGET_SELECTOR = \"button, [role='button']\";\n\nconst playerKeyboardShortcutOwners = new Set<string>();\nlet activePlayerKeyboardShortcutOwnerId: string | null = null;\n\nconst getTargetCandidate = (\n target: EventTarget | null | undefined\n): KeyboardShortcutTarget | null => {\n if (!target || typeof target !== \"object\") {\n return null;\n }\n\n const candidate = target as KeyboardShortcutTarget;\n\n if (candidate.nodeType === 3) {\n return (candidate.parentElement as KeyboardShortcutTarget | null) ?? null;\n }\n\n return candidate;\n};\n\nexport const getPlayerKeyboardShortcutAction = (\n event: PlayerKeyboardShortcutEventLike\n): PlayerKeyboardShortcutAction | null => {\n if (event.altKey || event.ctrlKey || event.metaKey) {\n return null;\n }\n\n const normalizedKey = event.key.toLowerCase();\n\n if (event.shiftKey) {\n switch (normalizedKey) {\n case \"arrowleft\":\n return \"previousSubtitle\";\n case \"arrowright\":\n return \"nextSubtitle\";\n default:\n return null;\n }\n }\n\n if (\n event.code === \"Space\" ||\n normalizedKey === \" \" ||\n normalizedKey === \"spacebar\"\n ) {\n return \"togglePlayback\";\n }\n\n switch (normalizedKey) {\n case \"arrowleft\":\n return \"previous\";\n case \"arrowright\":\n return \"next\";\n case \"f\":\n return \"fullscreen\";\n case \"c\":\n return \"subtitle\";\n case \"n\":\n return \"interaction\";\n default:\n return null;\n }\n};\n\nexport const isPlayerKeyboardShortcutEditableTarget = (\n target: EventTarget | null | undefined\n) => {\n const candidate = getTargetCandidate(target);\n\n if (!candidate) {\n return false;\n }\n\n const tagName = candidate.tagName?.toLowerCase();\n\n if (tagName === \"input\" || tagName === \"textarea\" || tagName === \"select\") {\n return true;\n }\n\n if (candidate.isContentEditable) {\n return true;\n }\n\n const contentEditable = candidate.getAttribute?.(\"contenteditable\");\n\n if (contentEditable !== undefined && contentEditable !== null) {\n return contentEditable.toLowerCase() !== \"false\";\n }\n\n return Boolean(candidate.closest?.(EDITABLE_SELECTOR));\n};\n\nexport const isPlayerKeyboardShortcutNativeSpaceTarget = (\n target: EventTarget | null | undefined\n) => {\n const candidate = getTargetCandidate(target);\n\n if (!candidate) {\n return false;\n }\n\n const tagName = candidate.tagName?.toLowerCase();\n\n if (tagName === \"button\") {\n return true;\n }\n\n return Boolean(candidate.closest?.(NATIVE_SPACE_TARGET_SELECTOR));\n};\n\nexport const shouldIgnorePlayerKeyboardShortcutEvent = (\n event: PlayerKeyboardShortcutEventLike,\n action: PlayerKeyboardShortcutAction | null\n) => {\n if (event.defaultPrevented || !action) {\n return true;\n }\n\n if (isPlayerKeyboardShortcutEditableTarget(event.target)) {\n return true;\n }\n\n return (\n action === \"togglePlayback\" &&\n isPlayerKeyboardShortcutNativeSpaceTarget(event.target)\n );\n};\n\nexport const registerPlayerKeyboardShortcutOwner = (ownerId: string) => {\n playerKeyboardShortcutOwners.add(ownerId);\n\n if (\n !activePlayerKeyboardShortcutOwnerId ||\n !playerKeyboardShortcutOwners.has(activePlayerKeyboardShortcutOwnerId)\n ) {\n activePlayerKeyboardShortcutOwnerId = ownerId;\n }\n\n return () => {\n playerKeyboardShortcutOwners.delete(ownerId);\n\n if (activePlayerKeyboardShortcutOwnerId !== ownerId) {\n return;\n }\n\n activePlayerKeyboardShortcutOwnerId =\n playerKeyboardShortcutOwners.values().next().value ?? null;\n };\n};\n\nexport const activatePlayerKeyboardShortcutOwner = (ownerId: string) => {\n if (playerKeyboardShortcutOwners.size === 0) {\n activePlayerKeyboardShortcutOwnerId = ownerId;\n return;\n }\n\n if (playerKeyboardShortcutOwners.has(ownerId)) {\n activePlayerKeyboardShortcutOwnerId = ownerId;\n }\n};\n\nexport const isActivePlayerKeyboardShortcutOwner = (ownerId: string) =>\n activePlayerKeyboardShortcutOwnerId === ownerId;\n\nexport const resetPlayerKeyboardShortcutOwnersForTest = () => {\n playerKeyboardShortcutOwners.clear();\n activePlayerKeyboardShortcutOwnerId = null;\n};\n"],"names":["EDITABLE_SELECTOR","NATIVE_SPACE_TARGET_SELECTOR","playerKeyboardShortcutOwners","activePlayerKeyboardShortcutOwnerId","getTargetCandidate","target","candidate","getPlayerKeyboardShortcutAction","event","normalizedKey","isPlayerKeyboardShortcutEditableTarget","tagName","contentEditable","isPlayerKeyboardShortcutNativeSpaceTarget","shouldIgnorePlayerKeyboardShortcutEvent","action","registerPlayerKeyboardShortcutOwner","ownerId","activatePlayerKeyboardShortcutOwner","isActivePlayerKeyboardShortcutOwner"],"mappings":"AA8BA,MAAMA,IACJ,oQAEIC,IAA+B,2BAE/BC,wBAAmC,IAAA;AACzC,IAAIC,IAAqD;AAEzD,MAAMC,IAAqB,CACzBC,MACkC;AAClC,MAAI,CAACA,KAAU,OAAOA,KAAW;AAC/B,WAAO;AAGT,QAAMC,IAAYD;AAElB,SAAIC,EAAU,aAAa,IACjBA,EAAU,iBAAmD,OAGhEA;AACT,GAEaC,IAAkC,CAC7CC,MACwC;AACxC,MAAIA,EAAM,UAAUA,EAAM,WAAWA,EAAM;AACzC,WAAO;AAGT,QAAMC,IAAgBD,EAAM,IAAI,YAAA;AAEhC,MAAIA,EAAM;AACR,YAAQC,GAAA;AAAA,MACN,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IAAA;AAIb,MACED,EAAM,SAAS,WACfC,MAAkB,OAClBA,MAAkB;AAElB,WAAO;AAGT,UAAQA,GAAA;AAAA,IACN,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EAAA;AAEb,GAEaC,IAAyC,CACpDL,MACG;AACH,QAAMC,IAAYF,EAAmBC,CAAM;AAE3C,MAAI,CAACC;AACH,WAAO;AAGT,QAAMK,IAAUL,EAAU,SAAS,YAAA;AAMnC,MAJIK,MAAY,WAAWA,MAAY,cAAcA,MAAY,YAI7DL,EAAU;AACZ,WAAO;AAGT,QAAMM,IAAkBN,EAAU,eAAe,iBAAiB;AAElE,SAAqCM,KAAoB,OAChDA,EAAgB,kBAAkB,UAGpC,EAAQN,EAAU,UAAUN,CAAiB;AACtD,GAEaa,IAA4C,CACvDR,MACG;AACH,QAAMC,IAAYF,EAAmBC,CAAM;AAE3C,SAAKC,IAIWA,EAAU,SAAS,YAAA,MAEnB,WACP,KAGF,EAAQA,EAAU,UAAUL,CAA4B,IATtD;AAUX,GAEaa,IAA0C,CACrDN,GACAO,MAEIP,EAAM,oBAAoB,CAACO,KAI3BL,EAAuCF,EAAM,MAAM,IAC9C,KAIPO,MAAW,oBACXF,EAA0CL,EAAM,MAAM,GAI7CQ,IAAsC,CAACC,OAClDf,EAA6B,IAAIe,CAAO,IAGtC,CAACd,KACD,CAACD,EAA6B,IAAIC,CAAmC,OAErEA,IAAsCc,IAGjC,MAAM;AAGX,EAFAf,EAA6B,OAAOe,CAAO,GAEvCd,MAAwCc,MAI5Cd,IACED,EAA6B,OAAA,EAAS,KAAA,EAAO,SAAS;AAC1D,IAGWgB,IAAsC,CAACD,MAAoB;AACtE,MAAIf,EAA6B,SAAS,GAAG;AAC3C,IAAAC,IAAsCc;AACtC;AAAA,EACF;AAEA,EAAIf,EAA6B,IAAIe,CAAO,MAC1Cd,IAAsCc;AAE1C,GAEaE,IAAsC,CAACF,MAClDd,MAAwCc;"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=(e=[])=>e.reduce((o,t)=>o+Math.max(Number(t?.duration_ms??0),0),0),g=(e=[],o)=>{if(e.length===0)return!1;const t=Math.max(Number(o),0),n=u(e),a=e[e.length-1];return t<n||t===n&&!!a?.is_final},c=(e=[],o)=>{const t=Math.max(Number(o),0);let n=0;for(let a=0;a<e.length;a+=1){const r=e[a],s=Math.max(Number(r?.duration_ms??0),0),i=n+s,m=a===e.length-1,l=!!r?.is_final;if(t<i||s===0&&t===n&&(!m||l)||m&&l&&t>=i)return{segmentIndex:a,segmentTimeSeconds:Math.min(Math.max(t-n,0),s)/1e3};n=i}return null};exports.getAudioSegmentsDurationMs=u;exports.isPlaybackTimeCoveredBySegments=g;exports.resolveSegmentSeekTarget=c;
2
+ //# sourceMappingURL=segmentSeek.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segmentSeek.cjs.js","sources":["../../../../src/components/Slide/utils/segmentSeek.ts"],"sourcesContent":["import type { SlideAudioItem } from \"../useSlide\";\n\nexport interface SegmentSeekTarget {\n segmentIndex: number;\n segmentTimeSeconds: number;\n}\n\nexport const getAudioSegmentsDurationMs = (\n segments: NonNullable<SlideAudioItem[\"audioSegments\"]> = []\n) =>\n segments.reduce(\n (totalDurationMs, segment) =>\n totalDurationMs + Math.max(Number(segment?.duration_ms ?? 0), 0),\n 0\n );\n\nexport const isPlaybackTimeCoveredBySegments = (\n segments: NonNullable<SlideAudioItem[\"audioSegments\"]> = [],\n timeMs: number\n) => {\n if (segments.length === 0) {\n return false;\n }\n\n const normalizedTimeMs = Math.max(Number(timeMs), 0);\n const loadedDurationMs = getAudioSegmentsDurationMs(segments);\n const lastSegment = segments[segments.length - 1];\n\n return (\n normalizedTimeMs < loadedDurationMs ||\n (normalizedTimeMs === loadedDurationMs && Boolean(lastSegment?.is_final))\n );\n};\n\nexport const resolveSegmentSeekTarget = (\n segments: NonNullable<SlideAudioItem[\"audioSegments\"]> = [],\n timeMs: number\n): SegmentSeekTarget | null => {\n const normalizedTimeMs = Math.max(Number(timeMs), 0);\n let segmentStartTimeMs = 0;\n\n for (let index = 0; index < segments.length; index += 1) {\n const segment = segments[index];\n const durationMs = Math.max(Number(segment?.duration_ms ?? 0), 0);\n const segmentEndTimeMs = segmentStartTimeMs + durationMs;\n const isLastSegment = index === segments.length - 1;\n const isFinalSegment = Boolean(segment?.is_final);\n\n if (\n normalizedTimeMs < segmentEndTimeMs ||\n (durationMs === 0 &&\n normalizedTimeMs === segmentStartTimeMs &&\n (!isLastSegment || isFinalSegment)) ||\n (isLastSegment && isFinalSegment && normalizedTimeMs >= segmentEndTimeMs)\n ) {\n return {\n segmentIndex: index,\n segmentTimeSeconds:\n Math.min(\n Math.max(normalizedTimeMs - segmentStartTimeMs, 0),\n durationMs\n ) / 1000,\n };\n }\n\n segmentStartTimeMs = segmentEndTimeMs;\n }\n\n return null;\n};\n"],"names":["getAudioSegmentsDurationMs","segments","totalDurationMs","segment","isPlaybackTimeCoveredBySegments","timeMs","normalizedTimeMs","loadedDurationMs","lastSegment","resolveSegmentSeekTarget","segmentStartTimeMs","index","durationMs","segmentEndTimeMs","isLastSegment","isFinalSegment"],"mappings":"gFAOO,MAAMA,EAA6B,CACxCC,EAAyD,CAAA,IAEzDA,EAAS,OACP,CAACC,EAAiBC,IAChBD,EAAkB,KAAK,IAAI,OAAOC,GAAS,aAAe,CAAC,EAAG,CAAC,EACjE,CACF,EAEWC,EAAkC,CAC7CH,EAAyD,CAAA,EACzDI,IACG,CACH,GAAIJ,EAAS,SAAW,EACtB,MAAO,GAGT,MAAMK,EAAmB,KAAK,IAAI,OAAOD,CAAM,EAAG,CAAC,EAC7CE,EAAmBP,EAA2BC,CAAQ,EACtDO,EAAcP,EAASA,EAAS,OAAS,CAAC,EAEhD,OACEK,EAAmBC,GAClBD,IAAqBC,GAAoB,EAAQC,GAAa,QAEnE,EAEaC,EAA2B,CACtCR,EAAyD,CAAA,EACzDI,IAC6B,CAC7B,MAAMC,EAAmB,KAAK,IAAI,OAAOD,CAAM,EAAG,CAAC,EACnD,IAAIK,EAAqB,EAEzB,QAASC,EAAQ,EAAGA,EAAQV,EAAS,OAAQU,GAAS,EAAG,CACvD,MAAMR,EAAUF,EAASU,CAAK,EACxBC,EAAa,KAAK,IAAI,OAAOT,GAAS,aAAe,CAAC,EAAG,CAAC,EAC1DU,EAAmBH,EAAqBE,EACxCE,EAAgBH,IAAUV,EAAS,OAAS,EAC5Cc,EAAiB,EAAQZ,GAAS,SAExC,GACEG,EAAmBO,GAClBD,IAAe,GACdN,IAAqBI,IACpB,CAACI,GAAiBC,IACpBD,GAAiBC,GAAkBT,GAAoBO,EAExD,MAAO,CACL,aAAcF,EACd,mBACE,KAAK,IACH,KAAK,IAAIL,EAAmBI,EAAoB,CAAC,EACjDE,CAAA,EACE,GAAA,EAIVF,EAAqBG,CACvB,CAEA,OAAO,IACT"}
@@ -0,0 +1,8 @@
1
+ import { SlideAudioItem } from '../useSlide';
2
+ export interface SegmentSeekTarget {
3
+ segmentIndex: number;
4
+ segmentTimeSeconds: number;
5
+ }
6
+ export declare const getAudioSegmentsDurationMs: (segments?: NonNullable<SlideAudioItem["audioSegments"]>) => number;
7
+ export declare const isPlaybackTimeCoveredBySegments: (segments: NonNullable<SlideAudioItem["audioSegments"]> | undefined, timeMs: number) => boolean;
8
+ export declare const resolveSegmentSeekTarget: (segments: NonNullable<SlideAudioItem["audioSegments"]> | undefined, timeMs: number) => SegmentSeekTarget | null;
@@ -0,0 +1,31 @@
1
+ const u = (e = []) => e.reduce(
2
+ (o, t) => o + Math.max(Number(t?.duration_ms ?? 0), 0),
3
+ 0
4
+ ), c = (e = [], o) => {
5
+ if (e.length === 0)
6
+ return !1;
7
+ const t = Math.max(Number(o), 0), n = u(e), a = e[e.length - 1];
8
+ return t < n || t === n && !!a?.is_final;
9
+ }, d = (e = [], o) => {
10
+ const t = Math.max(Number(o), 0);
11
+ let n = 0;
12
+ for (let a = 0; a < e.length; a += 1) {
13
+ const m = e[a], s = Math.max(Number(m?.duration_ms ?? 0), 0), i = n + s, r = a === e.length - 1, l = !!m?.is_final;
14
+ if (t < i || s === 0 && t === n && (!r || l) || r && l && t >= i)
15
+ return {
16
+ segmentIndex: a,
17
+ segmentTimeSeconds: Math.min(
18
+ Math.max(t - n, 0),
19
+ s
20
+ ) / 1e3
21
+ };
22
+ n = i;
23
+ }
24
+ return null;
25
+ };
26
+ export {
27
+ u as getAudioSegmentsDurationMs,
28
+ c as isPlaybackTimeCoveredBySegments,
29
+ d as resolveSegmentSeekTarget
30
+ };
31
+ //# sourceMappingURL=segmentSeek.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segmentSeek.es.js","sources":["../../../../src/components/Slide/utils/segmentSeek.ts"],"sourcesContent":["import type { SlideAudioItem } from \"../useSlide\";\n\nexport interface SegmentSeekTarget {\n segmentIndex: number;\n segmentTimeSeconds: number;\n}\n\nexport const getAudioSegmentsDurationMs = (\n segments: NonNullable<SlideAudioItem[\"audioSegments\"]> = []\n) =>\n segments.reduce(\n (totalDurationMs, segment) =>\n totalDurationMs + Math.max(Number(segment?.duration_ms ?? 0), 0),\n 0\n );\n\nexport const isPlaybackTimeCoveredBySegments = (\n segments: NonNullable<SlideAudioItem[\"audioSegments\"]> = [],\n timeMs: number\n) => {\n if (segments.length === 0) {\n return false;\n }\n\n const normalizedTimeMs = Math.max(Number(timeMs), 0);\n const loadedDurationMs = getAudioSegmentsDurationMs(segments);\n const lastSegment = segments[segments.length - 1];\n\n return (\n normalizedTimeMs < loadedDurationMs ||\n (normalizedTimeMs === loadedDurationMs && Boolean(lastSegment?.is_final))\n );\n};\n\nexport const resolveSegmentSeekTarget = (\n segments: NonNullable<SlideAudioItem[\"audioSegments\"]> = [],\n timeMs: number\n): SegmentSeekTarget | null => {\n const normalizedTimeMs = Math.max(Number(timeMs), 0);\n let segmentStartTimeMs = 0;\n\n for (let index = 0; index < segments.length; index += 1) {\n const segment = segments[index];\n const durationMs = Math.max(Number(segment?.duration_ms ?? 0), 0);\n const segmentEndTimeMs = segmentStartTimeMs + durationMs;\n const isLastSegment = index === segments.length - 1;\n const isFinalSegment = Boolean(segment?.is_final);\n\n if (\n normalizedTimeMs < segmentEndTimeMs ||\n (durationMs === 0 &&\n normalizedTimeMs === segmentStartTimeMs &&\n (!isLastSegment || isFinalSegment)) ||\n (isLastSegment && isFinalSegment && normalizedTimeMs >= segmentEndTimeMs)\n ) {\n return {\n segmentIndex: index,\n segmentTimeSeconds:\n Math.min(\n Math.max(normalizedTimeMs - segmentStartTimeMs, 0),\n durationMs\n ) / 1000,\n };\n }\n\n segmentStartTimeMs = segmentEndTimeMs;\n }\n\n return null;\n};\n"],"names":["getAudioSegmentsDurationMs","segments","totalDurationMs","segment","isPlaybackTimeCoveredBySegments","timeMs","normalizedTimeMs","loadedDurationMs","lastSegment","resolveSegmentSeekTarget","segmentStartTimeMs","index","durationMs","segmentEndTimeMs","isLastSegment","isFinalSegment"],"mappings":"AAOO,MAAMA,IAA6B,CACxCC,IAAyD,CAAA,MAEzDA,EAAS;AAAA,EACP,CAACC,GAAiBC,MAChBD,IAAkB,KAAK,IAAI,OAAOC,GAAS,eAAe,CAAC,GAAG,CAAC;AAAA,EACjE;AACF,GAEWC,IAAkC,CAC7CH,IAAyD,CAAA,GACzDI,MACG;AACH,MAAIJ,EAAS,WAAW;AACtB,WAAO;AAGT,QAAMK,IAAmB,KAAK,IAAI,OAAOD,CAAM,GAAG,CAAC,GAC7CE,IAAmBP,EAA2BC,CAAQ,GACtDO,IAAcP,EAASA,EAAS,SAAS,CAAC;AAEhD,SACEK,IAAmBC,KAClBD,MAAqBC,KAAoB,EAAQC,GAAa;AAEnE,GAEaC,IAA2B,CACtCR,IAAyD,CAAA,GACzDI,MAC6B;AAC7B,QAAMC,IAAmB,KAAK,IAAI,OAAOD,CAAM,GAAG,CAAC;AACnD,MAAIK,IAAqB;AAEzB,WAASC,IAAQ,GAAGA,IAAQV,EAAS,QAAQU,KAAS,GAAG;AACvD,UAAMR,IAAUF,EAASU,CAAK,GACxBC,IAAa,KAAK,IAAI,OAAOT,GAAS,eAAe,CAAC,GAAG,CAAC,GAC1DU,IAAmBH,IAAqBE,GACxCE,IAAgBH,MAAUV,EAAS,SAAS,GAC5Cc,IAAiB,EAAQZ,GAAS;AAExC,QACEG,IAAmBO,KAClBD,MAAe,KACdN,MAAqBI,MACpB,CAACI,KAAiBC,MACpBD,KAAiBC,KAAkBT,KAAoBO;AAExD,aAAO;AAAA,QACL,cAAcF;AAAA,QACd,oBACE,KAAK;AAAA,UACH,KAAK,IAAIL,IAAmBI,GAAoB,CAAC;AAAA,UACjDE;AAAA,QAAA,IACE;AAAA,MAAA;AAIV,IAAAF,IAAqBG;AAAA,EACvB;AAEA,SAAO;AACT;"}
@@ -0,0 +1 @@
1
+ export {};
@@ -1 +1 @@
1
- {"version":3,"file":"streamingNavigation.cjs.js","sources":["../../../../src/components/Slide/utils/streamingNavigation.ts"],"sourcesContent":["import type { Element } from \"../types\";\n\ninterface ResolveNextSlideIndexParams {\n previousIndex: number;\n previousSlideElementList: Element[];\n nextSlideElementList: Element[];\n}\n\nconst isResolvedInteractionElement = (element?: Element) =>\n Boolean(\n element?.type === \"interaction\" &&\n (element.readonly || element.user_input?.trim())\n );\n\nconst hasStableMarkerPrefix = (\n previousSlideElementList: Element[],\n nextSlideElementList: Element[]\n) =>\n previousSlideElementList.length <= nextSlideElementList.length &&\n previousSlideElementList.every(\n (element, index) => element === nextSlideElementList[index]\n );\n\nexport const resolveNextSlideIndexAfterMarkerAppend = ({\n previousIndex,\n previousSlideElementList,\n nextSlideElementList,\n}: ResolveNextSlideIndexParams) => {\n if (nextSlideElementList.length === 0) {\n return -1;\n }\n\n const hasAppendedMarkers =\n nextSlideElementList.length > previousSlideElementList.length &&\n hasStableMarkerPrefix(previousSlideElementList, nextSlideElementList);\n const previousLastMarkerIndex = previousSlideElementList.length - 1;\n const wasFocusedOnPreviousLastMarker =\n previousIndex === previousLastMarkerIndex;\n const previousCurrentElement =\n previousIndex >= 0 ? previousSlideElementList[previousIndex] : undefined;\n\n // When a resolved interaction is already the terminal step and SSE appends\n // the first follow-up marker, jump into that new marker immediately instead\n // of waiting for the interaction auto-close and silent-step delay.\n if (\n hasAppendedMarkers &&\n wasFocusedOnPreviousLastMarker &&\n isResolvedInteractionElement(previousCurrentElement)\n ) {\n return previousSlideElementList.length;\n }\n\n if (previousIndex >= 0 && previousIndex < nextSlideElementList.length) {\n return previousIndex;\n }\n\n return -1;\n};\n"],"names":["isResolvedInteractionElement","element","hasStableMarkerPrefix","previousSlideElementList","nextSlideElementList","index","resolveNextSlideIndexAfterMarkerAppend","previousIndex","hasAppendedMarkers","previousLastMarkerIndex","wasFocusedOnPreviousLastMarker","previousCurrentElement"],"mappings":"gFAQA,MAAMA,EAAgCC,GACpC,GACEA,GAAS,OAAS,gBACjBA,EAAQ,UAAYA,EAAQ,YAAY,KAAA,IAGvCC,EAAwB,CAC5BC,EACAC,IAEAD,EAAyB,QAAUC,EAAqB,QACxDD,EAAyB,MACvB,CAACF,EAASI,IAAUJ,IAAYG,EAAqBC,CAAK,CAC5D,EAEWC,EAAyC,CAAC,CACrD,cAAAC,EACA,yBAAAJ,EACA,qBAAAC,CACF,IAAmC,CACjC,GAAIA,EAAqB,SAAW,EAClC,MAAO,GAGT,MAAMI,EACJJ,EAAqB,OAASD,EAAyB,QACvDD,EAAsBC,EAA0BC,CAAoB,EAChEK,EAA0BN,EAAyB,OAAS,EAC5DO,EACJH,IAAkBE,EACdE,EACJJ,GAAiB,EAAIJ,EAAyBI,CAAa,EAAI,OAKjE,OACEC,GACAE,GACAV,EAA6BW,CAAsB,EAE5CR,EAAyB,OAG9BI,GAAiB,GAAKA,EAAgBH,EAAqB,OACtDG,EAGF,EACT"}
1
+ {"version":3,"file":"streamingNavigation.cjs.js","sources":["../../../../src/components/Slide/utils/streamingNavigation.ts"],"sourcesContent":["import type { Element } from \"../types\";\n\ninterface ResolveNextSlideIndexParams {\n previousIndex: number;\n previousSlideElementList: Element[];\n nextSlideElementList: Element[];\n}\n\nconst isResolvedInteractionElement = (element?: Element) =>\n Boolean(\n element?.type === \"interaction\" &&\n (element.readonly || element.user_input?.trim())\n );\n\nconst hasStableMarkerPrefix = (\n previousSlideElementList: Element[],\n nextSlideElementList: Element[]\n) =>\n previousSlideElementList.length <= nextSlideElementList.length &&\n previousSlideElementList.every(\n (element, index) => element === nextSlideElementList[index]\n );\n\nexport const resolveNextSlideIndexAfterMarkerAppend = ({\n previousIndex,\n previousSlideElementList,\n nextSlideElementList,\n}: ResolveNextSlideIndexParams) => {\n if (nextSlideElementList.length === 0) {\n return -1;\n }\n\n const hasAppendedMarkers =\n nextSlideElementList.length > previousSlideElementList.length &&\n hasStableMarkerPrefix(previousSlideElementList, nextSlideElementList);\n const previousLastMarkerIndex = previousSlideElementList.length - 1;\n const wasFocusedOnPreviousLastMarker =\n previousIndex === previousLastMarkerIndex;\n const previousCurrentElement =\n previousIndex >= 0 ? previousSlideElementList[previousIndex] : undefined;\n\n // When a resolved interaction is already the terminal step and SSE appends\n // the first follow-up marker, jump into that new marker immediately instead\n // of waiting for the interaction auto-close and silent-step delay.\n if (\n hasAppendedMarkers &&\n wasFocusedOnPreviousLastMarker &&\n isResolvedInteractionElement(previousCurrentElement)\n ) {\n return previousSlideElementList.length;\n }\n\n if (previousIndex >= 0 && previousIndex < nextSlideElementList.length) {\n return previousIndex;\n }\n\n return -1;\n};\n"],"names":["isResolvedInteractionElement","element","hasStableMarkerPrefix","previousSlideElementList","nextSlideElementList","index","resolveNextSlideIndexAfterMarkerAppend","previousIndex","hasAppendedMarkers","previousLastMarkerIndex","wasFocusedOnPreviousLastMarker","previousCurrentElement"],"mappings":"gFAQA,MAAMA,EAAgCC,GACpC,GACEA,GAAS,OAAS,gBACfA,EAAQ,UAAYA,EAAQ,YAAY,KAAA,IAGzCC,EAAwB,CAC5BC,EACAC,IAEAD,EAAyB,QAAUC,EAAqB,QACxDD,EAAyB,MACvB,CAACF,EAASI,IAAUJ,IAAYG,EAAqBC,CAAK,CAC5D,EAEWC,EAAyC,CAAC,CACrD,cAAAC,EACA,yBAAAJ,EACA,qBAAAC,CACF,IAAmC,CACjC,GAAIA,EAAqB,SAAW,EAClC,MAAO,GAGT,MAAMI,EACJJ,EAAqB,OAASD,EAAyB,QACvDD,EAAsBC,EAA0BC,CAAoB,EAChEK,EAA0BN,EAAyB,OAAS,EAC5DO,EACJH,IAAkBE,EACdE,EACJJ,GAAiB,EAAIJ,EAAyBI,CAAa,EAAI,OAKjE,OACEC,GACAE,GACAV,EAA6BW,CAAsB,EAE5CR,EAAyB,OAG9BI,GAAiB,GAAKA,EAAgBH,EAAqB,OACtDG,EAGF,EACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"streamingNavigation.es.js","sources":["../../../../src/components/Slide/utils/streamingNavigation.ts"],"sourcesContent":["import type { Element } from \"../types\";\n\ninterface ResolveNextSlideIndexParams {\n previousIndex: number;\n previousSlideElementList: Element[];\n nextSlideElementList: Element[];\n}\n\nconst isResolvedInteractionElement = (element?: Element) =>\n Boolean(\n element?.type === \"interaction\" &&\n (element.readonly || element.user_input?.trim())\n );\n\nconst hasStableMarkerPrefix = (\n previousSlideElementList: Element[],\n nextSlideElementList: Element[]\n) =>\n previousSlideElementList.length <= nextSlideElementList.length &&\n previousSlideElementList.every(\n (element, index) => element === nextSlideElementList[index]\n );\n\nexport const resolveNextSlideIndexAfterMarkerAppend = ({\n previousIndex,\n previousSlideElementList,\n nextSlideElementList,\n}: ResolveNextSlideIndexParams) => {\n if (nextSlideElementList.length === 0) {\n return -1;\n }\n\n const hasAppendedMarkers =\n nextSlideElementList.length > previousSlideElementList.length &&\n hasStableMarkerPrefix(previousSlideElementList, nextSlideElementList);\n const previousLastMarkerIndex = previousSlideElementList.length - 1;\n const wasFocusedOnPreviousLastMarker =\n previousIndex === previousLastMarkerIndex;\n const previousCurrentElement =\n previousIndex >= 0 ? previousSlideElementList[previousIndex] : undefined;\n\n // When a resolved interaction is already the terminal step and SSE appends\n // the first follow-up marker, jump into that new marker immediately instead\n // of waiting for the interaction auto-close and silent-step delay.\n if (\n hasAppendedMarkers &&\n wasFocusedOnPreviousLastMarker &&\n isResolvedInteractionElement(previousCurrentElement)\n ) {\n return previousSlideElementList.length;\n }\n\n if (previousIndex >= 0 && previousIndex < nextSlideElementList.length) {\n return previousIndex;\n }\n\n return -1;\n};\n"],"names":["isResolvedInteractionElement","element","hasStableMarkerPrefix","previousSlideElementList","nextSlideElementList","index","resolveNextSlideIndexAfterMarkerAppend","previousIndex","hasAppendedMarkers","previousLastMarkerIndex","wasFocusedOnPreviousLastMarker","previousCurrentElement"],"mappings":"AAQA,MAAMA,IAA+B,CAACC,MACpC,GACEA,GAAS,SAAS,kBACjBA,EAAQ,YAAYA,EAAQ,YAAY,KAAA,KAGvCC,IAAwB,CAC5BC,GACAC,MAEAD,EAAyB,UAAUC,EAAqB,UACxDD,EAAyB;AAAA,EACvB,CAACF,GAASI,MAAUJ,MAAYG,EAAqBC,CAAK;AAC5D,GAEWC,IAAyC,CAAC;AAAA,EACrD,eAAAC;AAAA,EACA,0BAAAJ;AAAA,EACA,sBAAAC;AACF,MAAmC;AACjC,MAAIA,EAAqB,WAAW;AAClC,WAAO;AAGT,QAAMI,IACJJ,EAAqB,SAASD,EAAyB,UACvDD,EAAsBC,GAA0BC,CAAoB,GAChEK,IAA0BN,EAAyB,SAAS,GAC5DO,IACJH,MAAkBE,GACdE,IACJJ,KAAiB,IAAIJ,EAAyBI,CAAa,IAAI;AAKjE,SACEC,KACAE,KACAV,EAA6BW,CAAsB,IAE5CR,EAAyB,SAG9BI,KAAiB,KAAKA,IAAgBH,EAAqB,SACtDG,IAGF;AACT;"}
1
+ {"version":3,"file":"streamingNavigation.es.js","sources":["../../../../src/components/Slide/utils/streamingNavigation.ts"],"sourcesContent":["import type { Element } from \"../types\";\n\ninterface ResolveNextSlideIndexParams {\n previousIndex: number;\n previousSlideElementList: Element[];\n nextSlideElementList: Element[];\n}\n\nconst isResolvedInteractionElement = (element?: Element) =>\n Boolean(\n element?.type === \"interaction\" &&\n (element.readonly || element.user_input?.trim())\n );\n\nconst hasStableMarkerPrefix = (\n previousSlideElementList: Element[],\n nextSlideElementList: Element[]\n) =>\n previousSlideElementList.length <= nextSlideElementList.length &&\n previousSlideElementList.every(\n (element, index) => element === nextSlideElementList[index]\n );\n\nexport const resolveNextSlideIndexAfterMarkerAppend = ({\n previousIndex,\n previousSlideElementList,\n nextSlideElementList,\n}: ResolveNextSlideIndexParams) => {\n if (nextSlideElementList.length === 0) {\n return -1;\n }\n\n const hasAppendedMarkers =\n nextSlideElementList.length > previousSlideElementList.length &&\n hasStableMarkerPrefix(previousSlideElementList, nextSlideElementList);\n const previousLastMarkerIndex = previousSlideElementList.length - 1;\n const wasFocusedOnPreviousLastMarker =\n previousIndex === previousLastMarkerIndex;\n const previousCurrentElement =\n previousIndex >= 0 ? previousSlideElementList[previousIndex] : undefined;\n\n // When a resolved interaction is already the terminal step and SSE appends\n // the first follow-up marker, jump into that new marker immediately instead\n // of waiting for the interaction auto-close and silent-step delay.\n if (\n hasAppendedMarkers &&\n wasFocusedOnPreviousLastMarker &&\n isResolvedInteractionElement(previousCurrentElement)\n ) {\n return previousSlideElementList.length;\n }\n\n if (previousIndex >= 0 && previousIndex < nextSlideElementList.length) {\n return previousIndex;\n }\n\n return -1;\n};\n"],"names":["isResolvedInteractionElement","element","hasStableMarkerPrefix","previousSlideElementList","nextSlideElementList","index","resolveNextSlideIndexAfterMarkerAppend","previousIndex","hasAppendedMarkers","previousLastMarkerIndex","wasFocusedOnPreviousLastMarker","previousCurrentElement"],"mappings":"AAQA,MAAMA,IAA+B,CAACC,MACpC,GACEA,GAAS,SAAS,kBACfA,EAAQ,YAAYA,EAAQ,YAAY,KAAA,KAGzCC,IAAwB,CAC5BC,GACAC,MAEAD,EAAyB,UAAUC,EAAqB,UACxDD,EAAyB;AAAA,EACvB,CAACF,GAASI,MAAUJ,MAAYG,EAAqBC,CAAK;AAC5D,GAEWC,IAAyC,CAAC;AAAA,EACrD,eAAAC;AAAA,EACA,0BAAAJ;AAAA,EACA,sBAAAC;AACF,MAAmC;AACjC,MAAIA,EAAqB,WAAW;AAClC,WAAO;AAGT,QAAMI,IACJJ,EAAqB,SAASD,EAAyB,UACvDD,EAAsBC,GAA0BC,CAAoB,GAChEK,IAA0BN,EAAyB,SAAS,GAC5DO,IACJH,MAAkBE,GACdE,IACJJ,KAAiB,IAAIJ,EAAyBI,CAAa,IAAI;AAKjE,SACEC,KACAE,KACAV,EAA6BW,CAAsB,IAE5CR,EAAyB,SAG9BI,KAAiB,KAAKA,IAAgBH,EAAqB,SACtDG,IAGF;AACT;"}
@@ -1,3 +1,3 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=(o=[],s)=>o.filter(t=>s>=t.start_ms&&s<t.end_ms).sort((t,i)=>(t.position??0)-(i.position??0)||t.segment_index-i.segment_index||t.start_ms-i.start_ms||t.end_ms-i.end_ms).map(t=>t.text.trim()).filter(Boolean).join(`
2
- `);exports.getVisibleSubtitleText=e;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m=t=>{const s=Number(t);return Number.isFinite(s)?Math.max(s,0):0},d=(t=[],s)=>{const n=m(s);return t.filter(i=>n>=i.start_ms&&n<i.end_ms).sort((i,e)=>(i.position??0)-(e.position??0)||i.segment_index-e.segment_index||i.start_ms-e.start_ms||i.end_ms-e.end_ms).map(i=>i.text.trim()).filter(Boolean).join(`
2
+ `)},l=t=>Math.max(Number(t.start_ms??0),0),a=t=>Math.max(Number(t.end_ms??0),0),b=new WeakMap,c=(t=[])=>{const s=b.get(t);if(s)return s;const n=[...t].sort((i,e)=>l(i)-l(e)||a(i)-a(e)||(i.position??0)-(e.position??0)||(i.segment_index??0)-(e.segment_index??0));return b.set(t,n),n},f=(t,s)=>{let n=null;for(const i of t){const e=l(i);if(e>s)break;const u=a(i);s>=e&&s<u&&(n=e)}return n},g=(t,s)=>{let n=null;for(const i of t){const e=l(i);if(e>=s)break;n=e}return n},S=(t,s)=>{const n=t.find(i=>l(i)>s);return n?l(n):null},C=t=>{const s=t[0];return s?l(s):null},p=t=>{const s=t[t.length-1];return s?l(s):null},h=(t,s)=>t?.audioIndex===s.audioIndex&&t.timeMs===s.timeMs,_=({currentAudioIndex:t,currentTimeMs:s,target:n})=>n?.audioIndex===t&&n.timeMs!==m(s),T=({audioIndex:t,excludeTarget:s,getFallbackTimeMs:n,sortedSubtitleCues:i,timeMs:e})=>{if(e===null)return null;const u={audioIndex:t,timeMs:e};if(!h(s,u))return u;const r=n(i,e);return r!==null?{audioIndex:t,timeMs:r}:null},M=({currentTimeMs:t,direction:s,subtitleCues:n=[]})=>{if(n.length===0)return null;const i=c(n),e=m(t),u=f(i,e);return g(i,u??e)},J=({currentAudioIndex:t,currentTimeMs:s,excludeTarget:n,tracks:i})=>{for(let e=t;e<i.length;e+=1){const u=c(i[e]?.subtitleCues??[]),r=e===t?S(u,s):C(u),o=T({audioIndex:e,excludeTarget:n,getFallbackTimeMs:S,sortedSubtitleCues:u,timeMs:r});if(o)return o}return null},N=({currentAudioIndex:t,currentTimeMs:s,excludeTarget:n,tracks:i})=>{for(let e=t;e>=0;e-=1){const u=c(i[e]?.subtitleCues??[]),r=e===t?M({currentTimeMs:s,direction:"previous",subtitleCues:u}):p(u),o=T({audioIndex:e,excludeTarget:n,getFallbackTimeMs:g,sortedSubtitleCues:u,timeMs:r});if(o)return o}return null},x=({currentAudioIndex:t,currentTimeMs:s,direction:n,excludeTarget:i=null,tracks:e=[]})=>{if(e.length===0||t<0||t>=e.length)return null;const u=m(s);return n==="next"?J({currentAudioIndex:t,currentTimeMs:u,excludeTarget:i,tracks:e}):N({currentAudioIndex:t,currentTimeMs:u,excludeTarget:i,tracks:e})};exports.getSubtitleCueJumpTarget=x;exports.getSubtitleCueJumpTime=M;exports.getVisibleSubtitleText=d;exports.shouldClearSubtitleCueJumpTarget=_;
3
3
  //# sourceMappingURL=subtitleCue.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"subtitleCue.cjs.js","sources":["../../../../src/components/Slide/utils/subtitleCue.ts"],"sourcesContent":["import type { ElementSubtitleCue } from \"../types\";\n\nexport const getVisibleSubtitleText = (\n subtitleCues: ElementSubtitleCue[] = [],\n currentTimeMs: number\n) =>\n subtitleCues\n .filter(\n (subtitleCue) =>\n currentTimeMs >= subtitleCue.start_ms &&\n currentTimeMs < subtitleCue.end_ms\n )\n .sort(\n (prevCue, nextCue) =>\n (prevCue.position ?? 0) - (nextCue.position ?? 0) ||\n prevCue.segment_index - nextCue.segment_index ||\n prevCue.start_ms - nextCue.start_ms ||\n prevCue.end_ms - nextCue.end_ms\n )\n .map((subtitleCue) => subtitleCue.text.trim())\n .filter(Boolean)\n .join(\"\\n\");\n"],"names":["getVisibleSubtitleText","subtitleCues","currentTimeMs","subtitleCue","prevCue","nextCue"],"mappings":"gFAEO,MAAMA,EAAyB,CACpCC,EAAqC,CAAA,EACrCC,IAEAD,EACG,OACEE,GACCD,GAAiBC,EAAY,UAC7BD,EAAgBC,EAAY,MAChC,EACC,KACC,CAACC,EAASC,KACPD,EAAQ,UAAY,IAAMC,EAAQ,UAAY,IAC/CD,EAAQ,cAAgBC,EAAQ,eAChCD,EAAQ,SAAWC,EAAQ,UAC3BD,EAAQ,OAASC,EAAQ,MAC7B,EACC,IAAKF,GAAgBA,EAAY,KAAK,KAAA,CAAM,EAC5C,OAAO,OAAO,EACd,KAAK;AAAA,CAAI"}
1
+ {"version":3,"file":"subtitleCue.cjs.js","sources":["../../../../src/components/Slide/utils/subtitleCue.ts"],"sourcesContent":["import type { ElementSubtitleCue } from \"../types\";\n\n/** Direction for subtitle cue jump navigation. */\nexport type SubtitleCueJumpDirection = \"previous\" | \"next\";\n\nexport interface SubtitleCueJumpTrack {\n subtitleCues?: ElementSubtitleCue[];\n}\n\nexport interface SubtitleCueJumpTarget {\n audioIndex: number;\n timeMs: number;\n}\n\nexport interface ShouldClearSubtitleCueJumpTargetOptions {\n currentAudioIndex: number;\n currentTimeMs: number;\n target: SubtitleCueJumpTarget | null | undefined;\n}\n\nconst normalizePlaybackTimeMs = (timeMs: number) => {\n const parsedTimeMs = Number(timeMs);\n\n return Number.isFinite(parsedTimeMs) ? Math.max(parsedTimeMs, 0) : 0;\n};\n\nexport const getVisibleSubtitleText = (\n subtitleCues: ElementSubtitleCue[] = [],\n currentTimeMs: number\n): string => {\n const normalizedCurrentTimeMs = normalizePlaybackTimeMs(currentTimeMs);\n\n return subtitleCues\n .filter(\n (subtitleCue) =>\n normalizedCurrentTimeMs >= subtitleCue.start_ms &&\n normalizedCurrentTimeMs < subtitleCue.end_ms\n )\n .sort(\n (prevCue, nextCue) =>\n (prevCue.position ?? 0) - (nextCue.position ?? 0) ||\n prevCue.segment_index - nextCue.segment_index ||\n prevCue.start_ms - nextCue.start_ms ||\n prevCue.end_ms - nextCue.end_ms\n )\n .map((subtitleCue) => subtitleCue.text.trim())\n .filter(Boolean)\n .join(\"\\n\");\n};\n\nconst getSubtitleCueStartTimeMs = (subtitleCue: ElementSubtitleCue) =>\n Math.max(Number(subtitleCue.start_ms ?? 0), 0);\n\nconst getSubtitleCueEndTimeMs = (subtitleCue: ElementSubtitleCue) =>\n Math.max(Number(subtitleCue.end_ms ?? 0), 0);\n\nconst sortedSubtitleCuesCache = new WeakMap<\n ElementSubtitleCue[],\n ElementSubtitleCue[]\n>();\n\nconst sortSubtitleCuesByPlaybackTime = (\n subtitleCues: ElementSubtitleCue[] = []\n) => {\n const cachedSubtitleCues = sortedSubtitleCuesCache.get(subtitleCues);\n\n if (cachedSubtitleCues) {\n return cachedSubtitleCues;\n }\n\n const sortedSubtitleCues = [...subtitleCues].sort(\n (previousCue, nextCue) =>\n getSubtitleCueStartTimeMs(previousCue) -\n getSubtitleCueStartTimeMs(nextCue) ||\n getSubtitleCueEndTimeMs(previousCue) - getSubtitleCueEndTimeMs(nextCue) ||\n (previousCue.position ?? 0) - (nextCue.position ?? 0) ||\n (previousCue.segment_index ?? 0) - (nextCue.segment_index ?? 0)\n );\n\n sortedSubtitleCuesCache.set(subtitleCues, sortedSubtitleCues);\n\n return sortedSubtitleCues;\n};\n\nconst getActiveSubtitleCueStartTimeMs = (\n subtitleCues: ElementSubtitleCue[],\n currentTimeMs: number\n) => {\n let activeStartTimeMs: number | null = null;\n\n for (const subtitleCue of subtitleCues) {\n const startTimeMs = getSubtitleCueStartTimeMs(subtitleCue);\n\n if (startTimeMs > currentTimeMs) {\n break;\n }\n\n const endTimeMs = getSubtitleCueEndTimeMs(subtitleCue);\n\n if (currentTimeMs >= startTimeMs && currentTimeMs < endTimeMs) {\n activeStartTimeMs = startTimeMs;\n }\n }\n\n return activeStartTimeMs;\n};\n\nconst getPreviousSubtitleCueStartTimeMs = (\n subtitleCues: ElementSubtitleCue[],\n currentTimeMs: number\n) => {\n let previousStartTimeMs: number | null = null;\n\n for (const subtitleCue of subtitleCues) {\n const startTimeMs = getSubtitleCueStartTimeMs(subtitleCue);\n\n if (startTimeMs >= currentTimeMs) {\n break;\n }\n\n previousStartTimeMs = startTimeMs;\n }\n\n return previousStartTimeMs;\n};\n\nconst getNextSubtitleCueStartTimeMs = (\n subtitleCues: ElementSubtitleCue[],\n currentTimeMs: number\n) => {\n const nextSubtitleCue = subtitleCues.find(\n (subtitleCue) => getSubtitleCueStartTimeMs(subtitleCue) > currentTimeMs\n );\n\n return nextSubtitleCue ? getSubtitleCueStartTimeMs(nextSubtitleCue) : null;\n};\n\nconst getFirstSubtitleCueStartTimeMs = (subtitleCues: ElementSubtitleCue[]) => {\n const firstSubtitleCue = subtitleCues[0];\n\n return firstSubtitleCue ? getSubtitleCueStartTimeMs(firstSubtitleCue) : null;\n};\n\nconst getLastSubtitleCueStartTimeMs = (subtitleCues: ElementSubtitleCue[]) => {\n const lastSubtitleCue = subtitleCues[subtitleCues.length - 1];\n\n return lastSubtitleCue ? getSubtitleCueStartTimeMs(lastSubtitleCue) : null;\n};\n\nconst isSameSubtitleCueJumpTarget = (\n previousTarget: SubtitleCueJumpTarget | null | undefined,\n nextTarget: SubtitleCueJumpTarget\n) =>\n previousTarget?.audioIndex === nextTarget.audioIndex &&\n previousTarget.timeMs === nextTarget.timeMs;\n\nexport const shouldClearSubtitleCueJumpTarget = ({\n currentAudioIndex,\n currentTimeMs,\n target,\n}: ShouldClearSubtitleCueJumpTargetOptions) =>\n target?.audioIndex === currentAudioIndex &&\n target.timeMs !== normalizePlaybackTimeMs(currentTimeMs);\n\nconst resolveSubtitleCueJumpTargetCandidate = ({\n audioIndex,\n excludeTarget,\n getFallbackTimeMs,\n sortedSubtitleCues,\n timeMs,\n}: {\n audioIndex: number;\n excludeTarget: SubtitleCueJumpTarget | null;\n getFallbackTimeMs: (\n subtitleCues: ElementSubtitleCue[],\n timeMs: number\n ) => number | null;\n sortedSubtitleCues: ElementSubtitleCue[];\n timeMs: number | null;\n}): SubtitleCueJumpTarget | null => {\n if (timeMs === null) {\n return null;\n }\n\n const target = {\n audioIndex,\n timeMs,\n };\n\n if (!isSameSubtitleCueJumpTarget(excludeTarget, target)) {\n return target;\n }\n\n const fallbackTimeMs = getFallbackTimeMs(sortedSubtitleCues, timeMs);\n\n return fallbackTimeMs !== null\n ? {\n audioIndex,\n timeMs: fallbackTimeMs,\n }\n : null;\n};\n\n/** Options used to resolve a subtitle cue jump target. */\nexport interface GetSubtitleCueJumpTimeOptions {\n currentTimeMs: number;\n direction: SubtitleCueJumpDirection;\n subtitleCues?: ElementSubtitleCue[];\n}\n\n/** Returns the target cue start time in milliseconds, or `null` when no target exists. */\nexport const getSubtitleCueJumpTime = ({\n currentTimeMs,\n direction,\n subtitleCues = [],\n}: GetSubtitleCueJumpTimeOptions): number | null => {\n if (subtitleCues.length === 0) {\n return null;\n }\n\n const sortedSubtitleCues = sortSubtitleCuesByPlaybackTime(subtitleCues);\n const normalizedCurrentTimeMs = normalizePlaybackTimeMs(currentTimeMs);\n\n if (direction === \"next\") {\n return getNextSubtitleCueStartTimeMs(\n sortedSubtitleCues,\n normalizedCurrentTimeMs\n );\n }\n\n const activeStartTimeMs = getActiveSubtitleCueStartTimeMs(\n sortedSubtitleCues,\n normalizedCurrentTimeMs\n );\n\n return getPreviousSubtitleCueStartTimeMs(\n sortedSubtitleCues,\n activeStartTimeMs ?? normalizedCurrentTimeMs\n );\n};\n\nexport interface GetSubtitleCueJumpTargetOptions {\n currentAudioIndex: number;\n currentTimeMs: number;\n direction: SubtitleCueJumpDirection;\n excludeTarget?: SubtitleCueJumpTarget | null;\n tracks?: SubtitleCueJumpTrack[];\n}\n\nconst getNextSubtitleCueJumpTarget = ({\n currentAudioIndex,\n currentTimeMs,\n excludeTarget,\n tracks,\n}: {\n currentAudioIndex: number;\n currentTimeMs: number;\n excludeTarget: SubtitleCueJumpTarget | null;\n tracks: SubtitleCueJumpTrack[];\n}) => {\n for (\n let audioIndex = currentAudioIndex;\n audioIndex < tracks.length;\n audioIndex += 1\n ) {\n const sortedSubtitleCues = sortSubtitleCuesByPlaybackTime(\n tracks[audioIndex]?.subtitleCues ?? []\n );\n const timeMs =\n audioIndex === currentAudioIndex\n ? getNextSubtitleCueStartTimeMs(sortedSubtitleCues, currentTimeMs)\n : getFirstSubtitleCueStartTimeMs(sortedSubtitleCues);\n const target = resolveSubtitleCueJumpTargetCandidate({\n audioIndex,\n excludeTarget,\n getFallbackTimeMs: getNextSubtitleCueStartTimeMs,\n sortedSubtitleCues,\n timeMs,\n });\n\n if (target) {\n return target;\n }\n }\n\n return null;\n};\n\nconst getPreviousSubtitleCueJumpTarget = ({\n currentAudioIndex,\n currentTimeMs,\n excludeTarget,\n tracks,\n}: {\n currentAudioIndex: number;\n currentTimeMs: number;\n excludeTarget: SubtitleCueJumpTarget | null;\n tracks: SubtitleCueJumpTrack[];\n}) => {\n for (let audioIndex = currentAudioIndex; audioIndex >= 0; audioIndex -= 1) {\n const sortedSubtitleCues = sortSubtitleCuesByPlaybackTime(\n tracks[audioIndex]?.subtitleCues ?? []\n );\n const timeMs =\n audioIndex === currentAudioIndex\n ? getSubtitleCueJumpTime({\n currentTimeMs,\n direction: \"previous\",\n subtitleCues: sortedSubtitleCues,\n })\n : getLastSubtitleCueStartTimeMs(sortedSubtitleCues);\n const target = resolveSubtitleCueJumpTargetCandidate({\n audioIndex,\n excludeTarget,\n getFallbackTimeMs: getPreviousSubtitleCueStartTimeMs,\n sortedSubtitleCues,\n timeMs,\n });\n\n if (target) {\n return target;\n }\n }\n\n return null;\n};\n\nexport const getSubtitleCueJumpTarget = ({\n currentAudioIndex,\n currentTimeMs,\n direction,\n excludeTarget = null,\n tracks = [],\n}: GetSubtitleCueJumpTargetOptions): SubtitleCueJumpTarget | null => {\n if (\n tracks.length === 0 ||\n currentAudioIndex < 0 ||\n currentAudioIndex >= tracks.length\n ) {\n return null;\n }\n\n const normalizedCurrentTimeMs = normalizePlaybackTimeMs(currentTimeMs);\n\n if (direction === \"next\") {\n return getNextSubtitleCueJumpTarget({\n currentAudioIndex,\n currentTimeMs: normalizedCurrentTimeMs,\n excludeTarget,\n tracks,\n });\n }\n\n return getPreviousSubtitleCueJumpTarget({\n currentAudioIndex,\n currentTimeMs: normalizedCurrentTimeMs,\n excludeTarget,\n tracks,\n });\n};\n"],"names":["normalizePlaybackTimeMs","timeMs","parsedTimeMs","getVisibleSubtitleText","subtitleCues","currentTimeMs","normalizedCurrentTimeMs","subtitleCue","prevCue","nextCue","getSubtitleCueStartTimeMs","getSubtitleCueEndTimeMs","sortedSubtitleCuesCache","sortSubtitleCuesByPlaybackTime","cachedSubtitleCues","sortedSubtitleCues","previousCue","getActiveSubtitleCueStartTimeMs","activeStartTimeMs","startTimeMs","endTimeMs","getPreviousSubtitleCueStartTimeMs","previousStartTimeMs","getNextSubtitleCueStartTimeMs","nextSubtitleCue","getFirstSubtitleCueStartTimeMs","firstSubtitleCue","getLastSubtitleCueStartTimeMs","lastSubtitleCue","isSameSubtitleCueJumpTarget","previousTarget","nextTarget","shouldClearSubtitleCueJumpTarget","currentAudioIndex","target","resolveSubtitleCueJumpTargetCandidate","audioIndex","excludeTarget","getFallbackTimeMs","fallbackTimeMs","getSubtitleCueJumpTime","direction","getNextSubtitleCueJumpTarget","tracks","getPreviousSubtitleCueJumpTarget","getSubtitleCueJumpTarget"],"mappings":"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"}
@@ -1,2 +1,33 @@
1
1
  import { ElementSubtitleCue } from '../types';
2
+ /** Direction for subtitle cue jump navigation. */
3
+ export type SubtitleCueJumpDirection = "previous" | "next";
4
+ export interface SubtitleCueJumpTrack {
5
+ subtitleCues?: ElementSubtitleCue[];
6
+ }
7
+ export interface SubtitleCueJumpTarget {
8
+ audioIndex: number;
9
+ timeMs: number;
10
+ }
11
+ export interface ShouldClearSubtitleCueJumpTargetOptions {
12
+ currentAudioIndex: number;
13
+ currentTimeMs: number;
14
+ target: SubtitleCueJumpTarget | null | undefined;
15
+ }
2
16
  export declare const getVisibleSubtitleText: (subtitleCues: ElementSubtitleCue[] | undefined, currentTimeMs: number) => string;
17
+ export declare const shouldClearSubtitleCueJumpTarget: ({ currentAudioIndex, currentTimeMs, target, }: ShouldClearSubtitleCueJumpTargetOptions) => boolean;
18
+ /** Options used to resolve a subtitle cue jump target. */
19
+ export interface GetSubtitleCueJumpTimeOptions {
20
+ currentTimeMs: number;
21
+ direction: SubtitleCueJumpDirection;
22
+ subtitleCues?: ElementSubtitleCue[];
23
+ }
24
+ /** Returns the target cue start time in milliseconds, or `null` when no target exists. */
25
+ export declare const getSubtitleCueJumpTime: ({ currentTimeMs, direction, subtitleCues, }: GetSubtitleCueJumpTimeOptions) => number | null;
26
+ export interface GetSubtitleCueJumpTargetOptions {
27
+ currentAudioIndex: number;
28
+ currentTimeMs: number;
29
+ direction: SubtitleCueJumpDirection;
30
+ excludeTarget?: SubtitleCueJumpTarget | null;
31
+ tracks?: SubtitleCueJumpTrack[];
32
+ }
33
+ export declare const getSubtitleCueJumpTarget: ({ currentAudioIndex, currentTimeMs, direction, excludeTarget, tracks, }: GetSubtitleCueJumpTargetOptions) => SubtitleCueJumpTarget | null;
@@ -1,10 +1,161 @@
1
- const m = (o = [], i) => o.filter(
2
- (t) => i >= t.start_ms && i < t.end_ms
3
- ).sort(
4
- (t, s) => (t.position ?? 0) - (s.position ?? 0) || t.segment_index - s.segment_index || t.start_ms - s.start_ms || t.end_ms - s.end_ms
5
- ).map((t) => t.text.trim()).filter(Boolean).join(`
1
+ const m = (t) => {
2
+ const s = Number(t);
3
+ return Number.isFinite(s) ? Math.max(s, 0) : 0;
4
+ }, J = (t = [], s) => {
5
+ const i = m(s);
6
+ return t.filter(
7
+ (n) => i >= n.start_ms && i < n.end_ms
8
+ ).sort(
9
+ (n, e) => (n.position ?? 0) - (e.position ?? 0) || n.segment_index - e.segment_index || n.start_ms - e.start_ms || n.end_ms - e.end_ms
10
+ ).map((n) => n.text.trim()).filter(Boolean).join(`
6
11
  `);
12
+ }, l = (t) => Math.max(Number(t.start_ms ?? 0), 0), a = (t) => Math.max(Number(t.end_ms ?? 0), 0), b = /* @__PURE__ */ new WeakMap(), c = (t = []) => {
13
+ const s = b.get(t);
14
+ if (s)
15
+ return s;
16
+ const i = [...t].sort(
17
+ (n, e) => l(n) - l(e) || a(n) - a(e) || (n.position ?? 0) - (e.position ?? 0) || (n.segment_index ?? 0) - (e.segment_index ?? 0)
18
+ );
19
+ return b.set(t, i), i;
20
+ }, T = (t, s) => {
21
+ let i = null;
22
+ for (const n of t) {
23
+ const e = l(n);
24
+ if (e > s)
25
+ break;
26
+ const r = a(n);
27
+ s >= e && s < r && (i = e);
28
+ }
29
+ return i;
30
+ }, g = (t, s) => {
31
+ let i = null;
32
+ for (const n of t) {
33
+ const e = l(n);
34
+ if (e >= s)
35
+ break;
36
+ i = e;
37
+ }
38
+ return i;
39
+ }, S = (t, s) => {
40
+ const i = t.find(
41
+ (n) => l(n) > s
42
+ );
43
+ return i ? l(i) : null;
44
+ }, d = (t) => {
45
+ const s = t[0];
46
+ return s ? l(s) : null;
47
+ }, f = (t) => {
48
+ const s = t[t.length - 1];
49
+ return s ? l(s) : null;
50
+ }, C = (t, s) => t?.audioIndex === s.audioIndex && t.timeMs === s.timeMs, N = ({
51
+ currentAudioIndex: t,
52
+ currentTimeMs: s,
53
+ target: i
54
+ }) => i?.audioIndex === t && i.timeMs !== m(s), M = ({
55
+ audioIndex: t,
56
+ excludeTarget: s,
57
+ getFallbackTimeMs: i,
58
+ sortedSubtitleCues: n,
59
+ timeMs: e
60
+ }) => {
61
+ if (e === null)
62
+ return null;
63
+ const r = {
64
+ audioIndex: t,
65
+ timeMs: e
66
+ };
67
+ if (!C(s, r))
68
+ return r;
69
+ const u = i(n, e);
70
+ return u !== null ? {
71
+ audioIndex: t,
72
+ timeMs: u
73
+ } : null;
74
+ }, _ = ({
75
+ currentTimeMs: t,
76
+ direction: s,
77
+ subtitleCues: i = []
78
+ }) => {
79
+ if (i.length === 0)
80
+ return null;
81
+ const n = c(i), e = m(t), r = T(
82
+ n,
83
+ e
84
+ );
85
+ return g(
86
+ n,
87
+ r ?? e
88
+ );
89
+ }, h = ({
90
+ currentAudioIndex: t,
91
+ currentTimeMs: s,
92
+ excludeTarget: i,
93
+ tracks: n
94
+ }) => {
95
+ for (let e = t; e < n.length; e += 1) {
96
+ const r = c(
97
+ n[e]?.subtitleCues ?? []
98
+ ), u = e === t ? S(r, s) : d(r), o = M({
99
+ audioIndex: e,
100
+ excludeTarget: i,
101
+ getFallbackTimeMs: S,
102
+ sortedSubtitleCues: r,
103
+ timeMs: u
104
+ });
105
+ if (o)
106
+ return o;
107
+ }
108
+ return null;
109
+ }, p = ({
110
+ currentAudioIndex: t,
111
+ currentTimeMs: s,
112
+ excludeTarget: i,
113
+ tracks: n
114
+ }) => {
115
+ for (let e = t; e >= 0; e -= 1) {
116
+ const r = c(
117
+ n[e]?.subtitleCues ?? []
118
+ ), u = e === t ? _({
119
+ currentTimeMs: s,
120
+ direction: "previous",
121
+ subtitleCues: r
122
+ }) : f(r), o = M({
123
+ audioIndex: e,
124
+ excludeTarget: i,
125
+ getFallbackTimeMs: g,
126
+ sortedSubtitleCues: r,
127
+ timeMs: u
128
+ });
129
+ if (o)
130
+ return o;
131
+ }
132
+ return null;
133
+ }, x = ({
134
+ currentAudioIndex: t,
135
+ currentTimeMs: s,
136
+ direction: i,
137
+ excludeTarget: n = null,
138
+ tracks: e = []
139
+ }) => {
140
+ if (e.length === 0 || t < 0 || t >= e.length)
141
+ return null;
142
+ const r = m(s);
143
+ return i === "next" ? h({
144
+ currentAudioIndex: t,
145
+ currentTimeMs: r,
146
+ excludeTarget: n,
147
+ tracks: e
148
+ }) : p({
149
+ currentAudioIndex: t,
150
+ currentTimeMs: r,
151
+ excludeTarget: n,
152
+ tracks: e
153
+ });
154
+ };
7
155
  export {
8
- m as getVisibleSubtitleText
156
+ x as getSubtitleCueJumpTarget,
157
+ _ as getSubtitleCueJumpTime,
158
+ J as getVisibleSubtitleText,
159
+ N as shouldClearSubtitleCueJumpTarget
9
160
  };
10
161
  //# sourceMappingURL=subtitleCue.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"subtitleCue.es.js","sources":["../../../../src/components/Slide/utils/subtitleCue.ts"],"sourcesContent":["import type { ElementSubtitleCue } from \"../types\";\n\nexport const getVisibleSubtitleText = (\n subtitleCues: ElementSubtitleCue[] = [],\n currentTimeMs: number\n) =>\n subtitleCues\n .filter(\n (subtitleCue) =>\n currentTimeMs >= subtitleCue.start_ms &&\n currentTimeMs < subtitleCue.end_ms\n )\n .sort(\n (prevCue, nextCue) =>\n (prevCue.position ?? 0) - (nextCue.position ?? 0) ||\n prevCue.segment_index - nextCue.segment_index ||\n prevCue.start_ms - nextCue.start_ms ||\n prevCue.end_ms - nextCue.end_ms\n )\n .map((subtitleCue) => subtitleCue.text.trim())\n .filter(Boolean)\n .join(\"\\n\");\n"],"names":["getVisibleSubtitleText","subtitleCues","currentTimeMs","subtitleCue","prevCue","nextCue"],"mappings":"AAEO,MAAMA,IAAyB,CACpCC,IAAqC,CAAA,GACrCC,MAEAD,EACG;AAAA,EACC,CAACE,MACCD,KAAiBC,EAAY,YAC7BD,IAAgBC,EAAY;AAChC,EACC;AAAA,EACC,CAACC,GAASC,OACPD,EAAQ,YAAY,MAAMC,EAAQ,YAAY,MAC/CD,EAAQ,gBAAgBC,EAAQ,iBAChCD,EAAQ,WAAWC,EAAQ,YAC3BD,EAAQ,SAASC,EAAQ;AAC7B,EACC,IAAI,CAACF,MAAgBA,EAAY,KAAK,KAAA,CAAM,EAC5C,OAAO,OAAO,EACd,KAAK;AAAA,CAAI;"}
1
+ {"version":3,"file":"subtitleCue.es.js","sources":["../../../../src/components/Slide/utils/subtitleCue.ts"],"sourcesContent":["import type { ElementSubtitleCue } from \"../types\";\n\n/** Direction for subtitle cue jump navigation. */\nexport type SubtitleCueJumpDirection = \"previous\" | \"next\";\n\nexport interface SubtitleCueJumpTrack {\n subtitleCues?: ElementSubtitleCue[];\n}\n\nexport interface SubtitleCueJumpTarget {\n audioIndex: number;\n timeMs: number;\n}\n\nexport interface ShouldClearSubtitleCueJumpTargetOptions {\n currentAudioIndex: number;\n currentTimeMs: number;\n target: SubtitleCueJumpTarget | null | undefined;\n}\n\nconst normalizePlaybackTimeMs = (timeMs: number) => {\n const parsedTimeMs = Number(timeMs);\n\n return Number.isFinite(parsedTimeMs) ? Math.max(parsedTimeMs, 0) : 0;\n};\n\nexport const getVisibleSubtitleText = (\n subtitleCues: ElementSubtitleCue[] = [],\n currentTimeMs: number\n): string => {\n const normalizedCurrentTimeMs = normalizePlaybackTimeMs(currentTimeMs);\n\n return subtitleCues\n .filter(\n (subtitleCue) =>\n normalizedCurrentTimeMs >= subtitleCue.start_ms &&\n normalizedCurrentTimeMs < subtitleCue.end_ms\n )\n .sort(\n (prevCue, nextCue) =>\n (prevCue.position ?? 0) - (nextCue.position ?? 0) ||\n prevCue.segment_index - nextCue.segment_index ||\n prevCue.start_ms - nextCue.start_ms ||\n prevCue.end_ms - nextCue.end_ms\n )\n .map((subtitleCue) => subtitleCue.text.trim())\n .filter(Boolean)\n .join(\"\\n\");\n};\n\nconst getSubtitleCueStartTimeMs = (subtitleCue: ElementSubtitleCue) =>\n Math.max(Number(subtitleCue.start_ms ?? 0), 0);\n\nconst getSubtitleCueEndTimeMs = (subtitleCue: ElementSubtitleCue) =>\n Math.max(Number(subtitleCue.end_ms ?? 0), 0);\n\nconst sortedSubtitleCuesCache = new WeakMap<\n ElementSubtitleCue[],\n ElementSubtitleCue[]\n>();\n\nconst sortSubtitleCuesByPlaybackTime = (\n subtitleCues: ElementSubtitleCue[] = []\n) => {\n const cachedSubtitleCues = sortedSubtitleCuesCache.get(subtitleCues);\n\n if (cachedSubtitleCues) {\n return cachedSubtitleCues;\n }\n\n const sortedSubtitleCues = [...subtitleCues].sort(\n (previousCue, nextCue) =>\n getSubtitleCueStartTimeMs(previousCue) -\n getSubtitleCueStartTimeMs(nextCue) ||\n getSubtitleCueEndTimeMs(previousCue) - getSubtitleCueEndTimeMs(nextCue) ||\n (previousCue.position ?? 0) - (nextCue.position ?? 0) ||\n (previousCue.segment_index ?? 0) - (nextCue.segment_index ?? 0)\n );\n\n sortedSubtitleCuesCache.set(subtitleCues, sortedSubtitleCues);\n\n return sortedSubtitleCues;\n};\n\nconst getActiveSubtitleCueStartTimeMs = (\n subtitleCues: ElementSubtitleCue[],\n currentTimeMs: number\n) => {\n let activeStartTimeMs: number | null = null;\n\n for (const subtitleCue of subtitleCues) {\n const startTimeMs = getSubtitleCueStartTimeMs(subtitleCue);\n\n if (startTimeMs > currentTimeMs) {\n break;\n }\n\n const endTimeMs = getSubtitleCueEndTimeMs(subtitleCue);\n\n if (currentTimeMs >= startTimeMs && currentTimeMs < endTimeMs) {\n activeStartTimeMs = startTimeMs;\n }\n }\n\n return activeStartTimeMs;\n};\n\nconst getPreviousSubtitleCueStartTimeMs = (\n subtitleCues: ElementSubtitleCue[],\n currentTimeMs: number\n) => {\n let previousStartTimeMs: number | null = null;\n\n for (const subtitleCue of subtitleCues) {\n const startTimeMs = getSubtitleCueStartTimeMs(subtitleCue);\n\n if (startTimeMs >= currentTimeMs) {\n break;\n }\n\n previousStartTimeMs = startTimeMs;\n }\n\n return previousStartTimeMs;\n};\n\nconst getNextSubtitleCueStartTimeMs = (\n subtitleCues: ElementSubtitleCue[],\n currentTimeMs: number\n) => {\n const nextSubtitleCue = subtitleCues.find(\n (subtitleCue) => getSubtitleCueStartTimeMs(subtitleCue) > currentTimeMs\n );\n\n return nextSubtitleCue ? getSubtitleCueStartTimeMs(nextSubtitleCue) : null;\n};\n\nconst getFirstSubtitleCueStartTimeMs = (subtitleCues: ElementSubtitleCue[]) => {\n const firstSubtitleCue = subtitleCues[0];\n\n return firstSubtitleCue ? getSubtitleCueStartTimeMs(firstSubtitleCue) : null;\n};\n\nconst getLastSubtitleCueStartTimeMs = (subtitleCues: ElementSubtitleCue[]) => {\n const lastSubtitleCue = subtitleCues[subtitleCues.length - 1];\n\n return lastSubtitleCue ? getSubtitleCueStartTimeMs(lastSubtitleCue) : null;\n};\n\nconst isSameSubtitleCueJumpTarget = (\n previousTarget: SubtitleCueJumpTarget | null | undefined,\n nextTarget: SubtitleCueJumpTarget\n) =>\n previousTarget?.audioIndex === nextTarget.audioIndex &&\n previousTarget.timeMs === nextTarget.timeMs;\n\nexport const shouldClearSubtitleCueJumpTarget = ({\n currentAudioIndex,\n currentTimeMs,\n target,\n}: ShouldClearSubtitleCueJumpTargetOptions) =>\n target?.audioIndex === currentAudioIndex &&\n target.timeMs !== normalizePlaybackTimeMs(currentTimeMs);\n\nconst resolveSubtitleCueJumpTargetCandidate = ({\n audioIndex,\n excludeTarget,\n getFallbackTimeMs,\n sortedSubtitleCues,\n timeMs,\n}: {\n audioIndex: number;\n excludeTarget: SubtitleCueJumpTarget | null;\n getFallbackTimeMs: (\n subtitleCues: ElementSubtitleCue[],\n timeMs: number\n ) => number | null;\n sortedSubtitleCues: ElementSubtitleCue[];\n timeMs: number | null;\n}): SubtitleCueJumpTarget | null => {\n if (timeMs === null) {\n return null;\n }\n\n const target = {\n audioIndex,\n timeMs,\n };\n\n if (!isSameSubtitleCueJumpTarget(excludeTarget, target)) {\n return target;\n }\n\n const fallbackTimeMs = getFallbackTimeMs(sortedSubtitleCues, timeMs);\n\n return fallbackTimeMs !== null\n ? {\n audioIndex,\n timeMs: fallbackTimeMs,\n }\n : null;\n};\n\n/** Options used to resolve a subtitle cue jump target. */\nexport interface GetSubtitleCueJumpTimeOptions {\n currentTimeMs: number;\n direction: SubtitleCueJumpDirection;\n subtitleCues?: ElementSubtitleCue[];\n}\n\n/** Returns the target cue start time in milliseconds, or `null` when no target exists. */\nexport const getSubtitleCueJumpTime = ({\n currentTimeMs,\n direction,\n subtitleCues = [],\n}: GetSubtitleCueJumpTimeOptions): number | null => {\n if (subtitleCues.length === 0) {\n return null;\n }\n\n const sortedSubtitleCues = sortSubtitleCuesByPlaybackTime(subtitleCues);\n const normalizedCurrentTimeMs = normalizePlaybackTimeMs(currentTimeMs);\n\n if (direction === \"next\") {\n return getNextSubtitleCueStartTimeMs(\n sortedSubtitleCues,\n normalizedCurrentTimeMs\n );\n }\n\n const activeStartTimeMs = getActiveSubtitleCueStartTimeMs(\n sortedSubtitleCues,\n normalizedCurrentTimeMs\n );\n\n return getPreviousSubtitleCueStartTimeMs(\n sortedSubtitleCues,\n activeStartTimeMs ?? normalizedCurrentTimeMs\n );\n};\n\nexport interface GetSubtitleCueJumpTargetOptions {\n currentAudioIndex: number;\n currentTimeMs: number;\n direction: SubtitleCueJumpDirection;\n excludeTarget?: SubtitleCueJumpTarget | null;\n tracks?: SubtitleCueJumpTrack[];\n}\n\nconst getNextSubtitleCueJumpTarget = ({\n currentAudioIndex,\n currentTimeMs,\n excludeTarget,\n tracks,\n}: {\n currentAudioIndex: number;\n currentTimeMs: number;\n excludeTarget: SubtitleCueJumpTarget | null;\n tracks: SubtitleCueJumpTrack[];\n}) => {\n for (\n let audioIndex = currentAudioIndex;\n audioIndex < tracks.length;\n audioIndex += 1\n ) {\n const sortedSubtitleCues = sortSubtitleCuesByPlaybackTime(\n tracks[audioIndex]?.subtitleCues ?? []\n );\n const timeMs =\n audioIndex === currentAudioIndex\n ? getNextSubtitleCueStartTimeMs(sortedSubtitleCues, currentTimeMs)\n : getFirstSubtitleCueStartTimeMs(sortedSubtitleCues);\n const target = resolveSubtitleCueJumpTargetCandidate({\n audioIndex,\n excludeTarget,\n getFallbackTimeMs: getNextSubtitleCueStartTimeMs,\n sortedSubtitleCues,\n timeMs,\n });\n\n if (target) {\n return target;\n }\n }\n\n return null;\n};\n\nconst getPreviousSubtitleCueJumpTarget = ({\n currentAudioIndex,\n currentTimeMs,\n excludeTarget,\n tracks,\n}: {\n currentAudioIndex: number;\n currentTimeMs: number;\n excludeTarget: SubtitleCueJumpTarget | null;\n tracks: SubtitleCueJumpTrack[];\n}) => {\n for (let audioIndex = currentAudioIndex; audioIndex >= 0; audioIndex -= 1) {\n const sortedSubtitleCues = sortSubtitleCuesByPlaybackTime(\n tracks[audioIndex]?.subtitleCues ?? []\n );\n const timeMs =\n audioIndex === currentAudioIndex\n ? getSubtitleCueJumpTime({\n currentTimeMs,\n direction: \"previous\",\n subtitleCues: sortedSubtitleCues,\n })\n : getLastSubtitleCueStartTimeMs(sortedSubtitleCues);\n const target = resolveSubtitleCueJumpTargetCandidate({\n audioIndex,\n excludeTarget,\n getFallbackTimeMs: getPreviousSubtitleCueStartTimeMs,\n sortedSubtitleCues,\n timeMs,\n });\n\n if (target) {\n return target;\n }\n }\n\n return null;\n};\n\nexport const getSubtitleCueJumpTarget = ({\n currentAudioIndex,\n currentTimeMs,\n direction,\n excludeTarget = null,\n tracks = [],\n}: GetSubtitleCueJumpTargetOptions): SubtitleCueJumpTarget | null => {\n if (\n tracks.length === 0 ||\n currentAudioIndex < 0 ||\n currentAudioIndex >= tracks.length\n ) {\n return null;\n }\n\n const normalizedCurrentTimeMs = normalizePlaybackTimeMs(currentTimeMs);\n\n if (direction === \"next\") {\n return getNextSubtitleCueJumpTarget({\n currentAudioIndex,\n currentTimeMs: normalizedCurrentTimeMs,\n excludeTarget,\n tracks,\n });\n }\n\n return getPreviousSubtitleCueJumpTarget({\n currentAudioIndex,\n currentTimeMs: normalizedCurrentTimeMs,\n excludeTarget,\n tracks,\n });\n};\n"],"names":["normalizePlaybackTimeMs","timeMs","parsedTimeMs","getVisibleSubtitleText","subtitleCues","currentTimeMs","normalizedCurrentTimeMs","subtitleCue","prevCue","nextCue","getSubtitleCueStartTimeMs","getSubtitleCueEndTimeMs","sortedSubtitleCuesCache","sortSubtitleCuesByPlaybackTime","cachedSubtitleCues","sortedSubtitleCues","previousCue","getActiveSubtitleCueStartTimeMs","activeStartTimeMs","startTimeMs","endTimeMs","getPreviousSubtitleCueStartTimeMs","previousStartTimeMs","getNextSubtitleCueStartTimeMs","nextSubtitleCue","getFirstSubtitleCueStartTimeMs","firstSubtitleCue","getLastSubtitleCueStartTimeMs","lastSubtitleCue","isSameSubtitleCueJumpTarget","previousTarget","nextTarget","shouldClearSubtitleCueJumpTarget","currentAudioIndex","target","resolveSubtitleCueJumpTargetCandidate","audioIndex","excludeTarget","getFallbackTimeMs","fallbackTimeMs","getSubtitleCueJumpTime","direction","getNextSubtitleCueJumpTarget","tracks","getPreviousSubtitleCueJumpTarget","getSubtitleCueJumpTarget"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=e=>!!(e?.readonly||e?.user_input?.trim()),a=e=>e?.type==="interaction"&&!o(e),c=({currentIndex:e,resolvedCurrentInteractionElement:s,slideElementList:r,targetSlideIndex:n})=>{if(n==null||n<0)return!1;if(n<e)return!0;const i=Math.max(e,0);for(let t=i;t<=n;t+=1)if(!(t===e&&r[t]?.type==="interaction"&&o(s))&&a(r[t]))return!1;return!0};exports.canReachSubtitleJumpTarget=c;exports.hasResolvedInteractionElement=o;exports.isUnresolvedInteractionElement=a;
2
+ //# sourceMappingURL=subtitleJumpNavigation.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subtitleJumpNavigation.cjs.js","sources":["../../../../src/components/Slide/utils/subtitleJumpNavigation.ts"],"sourcesContent":["import type { Element } from \"../types\";\n\nexport const hasResolvedInteractionElement = (element?: Element) =>\n Boolean(element?.readonly || element?.user_input?.trim());\n\nexport const isUnresolvedInteractionElement = (element?: Element) =>\n element?.type === \"interaction\" && !hasResolvedInteractionElement(element);\n\nexport interface CanReachSubtitleJumpTargetOptions {\n currentIndex: number;\n resolvedCurrentInteractionElement?: Element;\n slideElementList: Element[];\n targetSlideIndex: number | undefined;\n}\n\nexport const canReachSubtitleJumpTarget = ({\n currentIndex,\n resolvedCurrentInteractionElement,\n slideElementList,\n targetSlideIndex,\n}: CanReachSubtitleJumpTargetOptions) => {\n if (targetSlideIndex == null || targetSlideIndex < 0) {\n return false;\n }\n\n if (targetSlideIndex < currentIndex) {\n return true;\n }\n\n const firstCheckedIndex = Math.max(currentIndex, 0);\n\n for (\n let slideIndex = firstCheckedIndex;\n slideIndex <= targetSlideIndex;\n slideIndex += 1\n ) {\n const isLocallyResolvedCurrentInteraction =\n slideIndex === currentIndex &&\n slideElementList[slideIndex]?.type === \"interaction\" &&\n hasResolvedInteractionElement(resolvedCurrentInteractionElement);\n\n if (\n !isLocallyResolvedCurrentInteraction &&\n isUnresolvedInteractionElement(slideElementList[slideIndex])\n ) {\n return false;\n }\n }\n\n return true;\n};\n"],"names":["hasResolvedInteractionElement","element","isUnresolvedInteractionElement","canReachSubtitleJumpTarget","currentIndex","resolvedCurrentInteractionElement","slideElementList","targetSlideIndex","firstCheckedIndex","slideIndex"],"mappings":"gFAEO,MAAMA,EAAiCC,GAC5C,GAAQA,GAAS,UAAYA,GAAS,YAAY,KAAA,GAEvCC,EAAkCD,GAC7CA,GAAS,OAAS,eAAiB,CAACD,EAA8BC,CAAO,EAS9DE,EAA6B,CAAC,CACzC,aAAAC,EACA,kCAAAC,EACA,iBAAAC,EACA,iBAAAC,CACF,IAAyC,CACvC,GAAIA,GAAoB,MAAQA,EAAmB,EACjD,MAAO,GAGT,GAAIA,EAAmBH,EACrB,MAAO,GAGT,MAAMI,EAAoB,KAAK,IAAIJ,EAAc,CAAC,EAElD,QACMK,EAAaD,EACjBC,GAAcF,EACdE,GAAc,EAOd,GACE,EALAA,IAAeL,GACfE,EAAiBG,CAAU,GAAG,OAAS,eACvCT,EAA8BK,CAAiC,IAI/DH,EAA+BI,EAAiBG,CAAU,CAAC,EAE3D,MAAO,GAIX,MAAO,EACT"}