vidply 1.2.0 → 1.2.1

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 (164) hide show
  1. package/README.md +946 -946
  2. package/dist/dev/{vidply.AudioDescriptionManager-R47Q4YR4.js → vidply.AudioDescriptionManager-6RFVF27Z.js} +275 -19
  3. package/dist/dev/vidply.AudioDescriptionManager-6RFVF27Z.js.map +7 -0
  4. package/dist/dev/{vidply.CaptionStyleMenu-7XHRBWUM.js → vidply.CaptionStyleMenu-R2SCQ6VP.js} +4 -4
  5. package/dist/dev/{vidply.DASHRenderer-PWEMC3BT.js → vidply.DASHRenderer-EOVEW73H.js} +3 -3
  6. package/dist/dev/vidply.DASHRenderer-EOVEW73H.js.map +7 -0
  7. package/dist/dev/{vidply.FloatingPlayerManager-PKNNNAS2.js → vidply.FloatingPlayerManager-V5XQWS75.js} +5 -5
  8. package/dist/dev/vidply.FloatingPlayerManager-V5XQWS75.js.map +7 -0
  9. package/dist/dev/{vidply.HLSRenderer-E7RQ74HI.js → vidply.HLSRenderer-ZBEFVH5W.js} +4 -4
  10. package/dist/dev/vidply.HLSRenderer-ZBEFVH5W.js.map +7 -0
  11. package/dist/dev/vidply.HTML5Renderer-P7ICKYU4.js +12 -0
  12. package/dist/dev/{vidply.SignLanguageManager-FET5FQZ7.js → vidply.SignLanguageManager-7IAJOVF6.js} +8 -8
  13. package/dist/dev/vidply.SignLanguageManager-7IAJOVF6.js.map +7 -0
  14. package/dist/dev/{vidply.SoundCloudRenderer-RVSJZODO.js → vidply.SoundCloudRenderer-OA7QQYGN.js} +3 -3
  15. package/dist/dev/vidply.SoundCloudRenderer-OA7QQYGN.js.map +7 -0
  16. package/dist/dev/{vidply.TranscriptManager-5GXOQCLX.js → vidply.TranscriptManager-BPM3T23L.js} +10 -10
  17. package/dist/dev/vidply.TranscriptManager-BPM3T23L.js.map +7 -0
  18. package/dist/dev/{vidply.VimeoRenderer-ER2LSBBW.js → vidply.VimeoRenderer-BRHFYPNJ.js} +3 -3
  19. package/dist/dev/vidply.VimeoRenderer-BRHFYPNJ.js.map +7 -0
  20. package/dist/dev/{vidply.YouTubeRenderer-NFTOWJAB.js → vidply.YouTubeRenderer-HRTN4EJ5.js} +3 -3
  21. package/dist/dev/vidply.YouTubeRenderer-HRTN4EJ5.js.map +7 -0
  22. package/dist/dev/{vidply.chunk-6RQA4ROD.js → vidply.chunk-5IK3IC5V.js} +2 -2
  23. package/dist/dev/{vidply.chunk-JJ47NO24.js → vidply.chunk-C55OBT5H.js} +2 -2
  24. package/dist/dev/vidply.chunk-C55OBT5H.js.map +7 -0
  25. package/dist/dev/{vidply.chunk-DZSDO3B7.js → vidply.chunk-HOYEMJSD.js} +2 -2
  26. package/dist/dev/{vidply.chunk-VMSQAZM7.js → vidply.chunk-JAKZNGOR.js} +2 -2
  27. package/dist/dev/{vidply.chunk-64WXMTGL.js → vidply.chunk-LDVFAFGC.js} +5 -5
  28. package/dist/dev/vidply.chunk-LDVFAFGC.js.map +7 -0
  29. package/dist/dev/{vidply.chunk-RZWZGDV7.js → vidply.chunk-NSMAZCMB.js} +6 -6
  30. package/dist/dev/vidply.chunk-NSMAZCMB.js.map +7 -0
  31. package/dist/dev/{vidply.chunk-KI7C3QVL.js → vidply.chunk-RQG3MA7W.js} +2 -2
  32. package/dist/dev/vidply.chunk-RQG3MA7W.js.map +7 -0
  33. package/dist/dev/{vidply.chunk-BNFIUL2Z.js → vidply.chunk-UHMVDBDB.js} +3 -3
  34. package/dist/dev/vidply.chunk-UHMVDBDB.js.map +7 -0
  35. package/dist/dev/{vidply.chunk-NQPURMQY.js → vidply.chunk-W5BR65JY.js} +6 -6
  36. package/dist/dev/vidply.chunk-W5BR65JY.js.map +7 -0
  37. package/dist/dev/{vidply.chunk-W25HUCHS.js → vidply.chunk-XAK3DPTO.js} +2 -2
  38. package/dist/dev/vidply.chunk-XAK3DPTO.js.map +7 -0
  39. package/dist/dev/{vidply.chunk-SK4V2DAU.js → vidply.chunk-YVCYQZJI.js} +3 -3
  40. package/dist/dev/{vidply.de-4YAT7FFM.js → vidply.de-5W5LBFSJ.js} +2 -2
  41. package/dist/dev/vidply.de-5W5LBFSJ.js.map +7 -0
  42. package/dist/dev/{vidply.es-LEWIRUBH.js → vidply.es-SHDAT6L6.js} +2 -2
  43. package/dist/dev/vidply.es-SHDAT6L6.js.map +7 -0
  44. package/dist/dev/vidply.esm.js +73 -34
  45. package/dist/dev/vidply.esm.js.map +2 -2
  46. package/dist/dev/{vidply.fr-Q4GV2NOE.js → vidply.fr-2JANOMNB.js} +2 -2
  47. package/dist/dev/vidply.fr-2JANOMNB.js.map +7 -0
  48. package/dist/dev/{vidply.ja-S6ITA6WU.js → vidply.ja-WWMSTEJH.js} +2 -2
  49. package/dist/dev/vidply.ja-WWMSTEJH.js.map +7 -0
  50. package/dist/legacy/vidply.js +345 -32
  51. package/dist/legacy/vidply.js.map +3 -3
  52. package/dist/legacy/vidply.min.js +2 -2
  53. package/dist/legacy/vidply.min.meta.json +66 -47
  54. package/dist/prod/vidply.AudioDescriptionManager-YTDVDQBO.min.js +6 -0
  55. package/dist/prod/{vidply.CaptionStyleMenu-M3KVQWB5.min.js → vidply.CaptionStyleMenu-2AFF3HF2.min.js} +2 -2
  56. package/dist/prod/{vidply.DASHRenderer-DN3S27AV.min.js → vidply.DASHRenderer-URDOTOKS.min.js} +2 -2
  57. package/dist/prod/{vidply.FloatingPlayerManager-SKAZ4J43.min.js → vidply.FloatingPlayerManager-QUBFK7CQ.min.js} +2 -2
  58. package/dist/prod/{vidply.HLSRenderer-62HH4YTK.min.js → vidply.HLSRenderer-46KNUVAB.min.js} +2 -2
  59. package/dist/prod/vidply.HTML5Renderer-7TQDMIGY.min.js +6 -0
  60. package/dist/prod/{vidply.SignLanguageManager-V3OBTSSF.min.js → vidply.SignLanguageManager-H4C36EVL.min.js} +2 -2
  61. package/dist/prod/{vidply.SoundCloudRenderer-CXRVZIAJ.min.js → vidply.SoundCloudRenderer-OYSWMW7D.min.js} +2 -2
  62. package/dist/prod/{vidply.TranscriptManager-SYM3DFUY.min.js → vidply.TranscriptManager-BA3DAS63.min.js} +2 -2
  63. package/dist/prod/{vidply.VimeoRenderer-72TWRYFQ.min.js → vidply.VimeoRenderer-NF3COTHU.min.js} +2 -2
  64. package/dist/prod/{vidply.YouTubeRenderer-UMHEV3KD.min.js → vidply.YouTubeRenderer-UCQKYIJ4.min.js} +2 -2
  65. package/dist/prod/{vidply.chunk-Z3YDSA7O.min.js → vidply.chunk-2HNCP64N.min.js} +1 -1
  66. package/dist/prod/{vidply.chunk-EKEYJWMG.min.js → vidply.chunk-6ECBIYVI.min.js} +2 -2
  67. package/dist/prod/{vidply.chunk-YEENJS3Q.min.js → vidply.chunk-7S5AFTST.min.js} +2 -2
  68. package/dist/prod/{vidply.chunk-P4UXOHWA.min.js → vidply.chunk-EUOA2DJK.min.js} +1 -1
  69. package/dist/prod/{vidply.chunk-2TB6MUHO.min.js → vidply.chunk-G6KGXNEW.min.js} +1 -1
  70. package/dist/prod/{vidply.chunk-ABPXVDLZ.min.js → vidply.chunk-JPMAK3NS.min.js} +1 -1
  71. package/dist/prod/{vidply.chunk-P3PQBY7N.min.js → vidply.chunk-L4O44K63.min.js} +1 -1
  72. package/dist/prod/{vidply.chunk-WX3MVEAL.min.js → vidply.chunk-M76ABMKB.min.js} +1 -1
  73. package/dist/prod/{vidply.chunk-TM6AXJVD.min.js → vidply.chunk-WRVDVD33.min.js} +2 -2
  74. package/dist/prod/{vidply.chunk-RI3X7WHK.min.js → vidply.chunk-X2FQEQYR.min.js} +2 -2
  75. package/dist/prod/{vidply.chunk-UK7YGOB5.min.js → vidply.chunk-XXUH7ADU.min.js} +2 -2
  76. package/dist/prod/{vidply.de-BCHXRQ53.min.js → vidply.de-JMCATTKZ.min.js} +1 -1
  77. package/dist/prod/{vidply.es-PICAKMZD.min.js → vidply.es-YVG37V7Z.min.js} +1 -1
  78. package/dist/prod/vidply.esm.min.js +2 -2
  79. package/dist/prod/{vidply.fr-ZILI7CDR.min.js → vidply.fr-OGKGN2R4.min.js} +1 -1
  80. package/dist/prod/{vidply.ja-5WQ4OK4J.min.js → vidply.ja-Z6DS7QLS.min.js} +1 -1
  81. package/dist/vidply.css +5796 -5796
  82. package/dist/vidply.esm.min.meta.json +148 -135
  83. package/package.json +7 -7
  84. package/src/controls/CaptionManager.ts +598 -598
  85. package/src/controls/ControlBar.ts +4159 -4159
  86. package/src/controls/KeyboardManager.ts +383 -383
  87. package/src/controls/SettingsDialog.ts +488 -488
  88. package/src/controls/TranscriptManager.ts +2426 -2426
  89. package/src/core/AudioDescriptionManager.ts +863 -774
  90. package/src/core/DescriptionSpeechManager.ts +232 -0
  91. package/src/core/FloatingPlayerManager.ts +674 -674
  92. package/src/core/LazyInit.ts +80 -80
  93. package/src/core/MetadataAlertsManager.ts +514 -514
  94. package/src/core/Player.ts +2915 -2872
  95. package/src/core/PosterManager.ts +169 -169
  96. package/src/core/PseudoFullscreen.ts +179 -179
  97. package/src/core/ResponsiveManager.ts +231 -231
  98. package/src/core/ResumeManager.ts +236 -236
  99. package/src/core/SignLanguageManager.ts +1308 -1308
  100. package/src/core/ThemeManager.ts +157 -157
  101. package/src/features/PlaylistManager.ts +1838 -1827
  102. package/src/i18n/i18n.ts +223 -223
  103. package/src/i18n/languages/de.ts +217 -217
  104. package/src/i18n/languages/en.ts +218 -218
  105. package/src/i18n/languages/es.ts +214 -214
  106. package/src/i18n/languages/fr.ts +214 -214
  107. package/src/i18n/languages/ja.ts +214 -214
  108. package/src/icons/Icons.ts +167 -167
  109. package/src/index.ts +196 -193
  110. package/src/renderers/DASHRenderer.ts +1077 -1077
  111. package/src/renderers/HLSRenderer.ts +944 -944
  112. package/src/renderers/HTML5Renderer.ts +389 -389
  113. package/src/renderers/SoundCloudRenderer.ts +437 -437
  114. package/src/renderers/VimeoRenderer.ts +298 -298
  115. package/src/renderers/YouTubeRenderer.ts +290 -290
  116. package/src/styles/vidply.css +5796 -5796
  117. package/src/types/events.ts +124 -122
  118. package/src/types/globals.d.ts +313 -313
  119. package/src/types/options.ts +185 -182
  120. package/src/types/renderer.ts +58 -58
  121. package/src/utils/DOMUtils.ts +281 -281
  122. package/src/utils/DownloadInfo.ts +171 -171
  123. package/src/utils/DraggablePanel.ts +539 -539
  124. package/src/utils/DraggablePanelMenu.ts +195 -195
  125. package/src/utils/DraggableResizable.ts +997 -997
  126. package/src/utils/EventEmitter.ts +59 -59
  127. package/src/utils/FormUtils.ts +95 -95
  128. package/src/utils/MenuFactory.ts +483 -483
  129. package/src/utils/Sanitize.ts +70 -70
  130. package/src/utils/SettingsMenuFactory.ts +289 -289
  131. package/src/utils/StorageManager.ts +287 -287
  132. package/src/utils/TrackLabelUtils.ts +52 -52
  133. package/src/utils/UrlSafe.ts +69 -69
  134. package/src/utils/VideoFrameCapture.ts +114 -114
  135. package/src/utils/WindowComponents.ts +250 -250
  136. package/dist/dev/vidply.AudioDescriptionManager-R47Q4YR4.js.map +0 -7
  137. package/dist/dev/vidply.DASHRenderer-PWEMC3BT.js.map +0 -7
  138. package/dist/dev/vidply.FloatingPlayerManager-PKNNNAS2.js.map +0 -7
  139. package/dist/dev/vidply.HLSRenderer-E7RQ74HI.js.map +0 -7
  140. package/dist/dev/vidply.HTML5Renderer-BU4QJJJY.js +0 -12
  141. package/dist/dev/vidply.SignLanguageManager-FET5FQZ7.js.map +0 -7
  142. package/dist/dev/vidply.SoundCloudRenderer-RVSJZODO.js.map +0 -7
  143. package/dist/dev/vidply.TranscriptManager-5GXOQCLX.js.map +0 -7
  144. package/dist/dev/vidply.VimeoRenderer-ER2LSBBW.js.map +0 -7
  145. package/dist/dev/vidply.YouTubeRenderer-NFTOWJAB.js.map +0 -7
  146. package/dist/dev/vidply.chunk-64WXMTGL.js.map +0 -7
  147. package/dist/dev/vidply.chunk-BNFIUL2Z.js.map +0 -7
  148. package/dist/dev/vidply.chunk-JJ47NO24.js.map +0 -7
  149. package/dist/dev/vidply.chunk-KI7C3QVL.js.map +0 -7
  150. package/dist/dev/vidply.chunk-NQPURMQY.js.map +0 -7
  151. package/dist/dev/vidply.chunk-RZWZGDV7.js.map +0 -7
  152. package/dist/dev/vidply.chunk-W25HUCHS.js.map +0 -7
  153. package/dist/dev/vidply.de-4YAT7FFM.js.map +0 -7
  154. package/dist/dev/vidply.es-LEWIRUBH.js.map +0 -7
  155. package/dist/dev/vidply.fr-Q4GV2NOE.js.map +0 -7
  156. package/dist/dev/vidply.ja-S6ITA6WU.js.map +0 -7
  157. package/dist/prod/vidply.AudioDescriptionManager-RHLIJW5C.min.js +0 -6
  158. package/dist/prod/vidply.HTML5Renderer-IU5T3WEW.min.js +0 -6
  159. /package/dist/dev/{vidply.CaptionStyleMenu-7XHRBWUM.js.map → vidply.CaptionStyleMenu-R2SCQ6VP.js.map} +0 -0
  160. /package/dist/dev/{vidply.HTML5Renderer-BU4QJJJY.js.map → vidply.HTML5Renderer-P7ICKYU4.js.map} +0 -0
  161. /package/dist/dev/{vidply.chunk-6RQA4ROD.js.map → vidply.chunk-5IK3IC5V.js.map} +0 -0
  162. /package/dist/dev/{vidply.chunk-DZSDO3B7.js.map → vidply.chunk-HOYEMJSD.js.map} +0 -0
  163. /package/dist/dev/{vidply.chunk-VMSQAZM7.js.map → vidply.chunk-JAKZNGOR.js.map} +0 -0
  164. /package/dist/dev/{vidply.chunk-SK4V2DAU.js.map → vidply.chunk-YVCYQZJI.js.map} +0 -0
@@ -1,59 +1,59 @@
1
- type DefaultEventMap = Record<string, unknown>;
2
- type Listener<T> = T extends void ? () => void : (data: T) => void;
3
-
4
- /**
5
- * Generic typed event emitter. The `TEvents` parameter is constrained
6
- * via the self-referential `Record<keyof TEvents, unknown>` so concrete
7
- * event maps (like `PlayerEventMap`) can be used directly without
8
- * adding a noisy `[key: string]: unknown` index signature, which would
9
- * defeat the typo-protection that strongly typed event maps provide.
10
- */
11
- export class EventEmitter<TEvents extends Record<keyof TEvents, unknown> = DefaultEventMap> {
12
- private events: Partial<Record<keyof TEvents, Array<(...args: unknown[]) => void>>> = {};
13
-
14
- on<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): this {
15
- const listeners = this.events[event] ?? [];
16
- listeners.push(listener as (...args: unknown[]) => void);
17
- this.events[event] = listeners;
18
- return this;
19
- }
20
-
21
- once<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): this {
22
- const onceListener = ((...args: unknown[]) => {
23
- (listener as (...a: unknown[]) => void)(...args);
24
- this.off(event, onceListener as Listener<TEvents[K]>);
25
- }) as unknown as Listener<TEvents[K]>;
26
- return this.on(event, onceListener);
27
- }
28
-
29
- off<K extends keyof TEvents>(event: K, listener?: Listener<TEvents[K]>): this {
30
- const listeners = this.events[event];
31
- if (!listeners) return this;
32
-
33
- if (!listener) {
34
- delete this.events[event];
35
- } else {
36
- this.events[event] = listeners.filter(
37
- l => l !== (listener as unknown)
38
- );
39
- }
40
-
41
- return this;
42
- }
43
-
44
- emit<K extends keyof TEvents>(event: K, ...args: unknown[]): this {
45
- const listeners = this.events[event];
46
- if (!listeners) return this;
47
-
48
- listeners.forEach(listener => {
49
- listener(...args);
50
- });
51
-
52
- return this;
53
- }
54
-
55
- removeAllListeners(): this {
56
- this.events = {};
57
- return this;
58
- }
59
- }
1
+ type DefaultEventMap = Record<string, unknown>;
2
+ type Listener<T> = T extends void ? () => void : (data: T) => void;
3
+
4
+ /**
5
+ * Generic typed event emitter. The `TEvents` parameter is constrained
6
+ * via the self-referential `Record<keyof TEvents, unknown>` so concrete
7
+ * event maps (like `PlayerEventMap`) can be used directly without
8
+ * adding a noisy `[key: string]: unknown` index signature, which would
9
+ * defeat the typo-protection that strongly typed event maps provide.
10
+ */
11
+ export class EventEmitter<TEvents extends Record<keyof TEvents, unknown> = DefaultEventMap> {
12
+ private events: Partial<Record<keyof TEvents, Array<(...args: unknown[]) => void>>> = {};
13
+
14
+ on<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): this {
15
+ const listeners = this.events[event] ?? [];
16
+ listeners.push(listener as (...args: unknown[]) => void);
17
+ this.events[event] = listeners;
18
+ return this;
19
+ }
20
+
21
+ once<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): this {
22
+ const onceListener = ((...args: unknown[]) => {
23
+ (listener as (...a: unknown[]) => void)(...args);
24
+ this.off(event, onceListener as Listener<TEvents[K]>);
25
+ }) as unknown as Listener<TEvents[K]>;
26
+ return this.on(event, onceListener);
27
+ }
28
+
29
+ off<K extends keyof TEvents>(event: K, listener?: Listener<TEvents[K]>): this {
30
+ const listeners = this.events[event];
31
+ if (!listeners) return this;
32
+
33
+ if (!listener) {
34
+ delete this.events[event];
35
+ } else {
36
+ this.events[event] = listeners.filter(
37
+ l => l !== (listener as unknown)
38
+ );
39
+ }
40
+
41
+ return this;
42
+ }
43
+
44
+ emit<K extends keyof TEvents>(event: K, ...args: unknown[]): this {
45
+ const listeners = this.events[event];
46
+ if (!listeners) return this;
47
+
48
+ listeners.forEach(listener => {
49
+ listener(...args);
50
+ });
51
+
52
+ return this;
53
+ }
54
+
55
+ removeAllListeners(): this {
56
+ this.events = {};
57
+ return this;
58
+ }
59
+ }
@@ -1,95 +1,95 @@
1
- import { DOMUtils } from './DOMUtils.js';
2
- import { i18n } from '../i18n/i18n.js';
3
-
4
- export interface SelectOption {
5
- value: string;
6
- text: string;
7
- selected?: boolean;
8
- }
9
-
10
- export interface LabeledSelectOptions {
11
- classPrefix: string;
12
- labelClass: string;
13
- selectClass: string;
14
- labelText: string;
15
- selectId: string;
16
- hidden?: boolean;
17
- onChange?: (e: Event) => void;
18
- options?: SelectOption[];
19
- }
20
-
21
- export function createLabeledSelect({
22
- classPrefix: _classPrefix,
23
- labelClass,
24
- selectClass,
25
- labelText,
26
- selectId,
27
- hidden = false,
28
- onChange = undefined,
29
- options = []
30
- }: LabeledSelectOptions): { label: HTMLLabelElement; select: HTMLSelectElement } {
31
- const isI18nKey =
32
- typeof labelText === 'string' &&
33
- (labelText.startsWith('transcript.') ||
34
- labelText.startsWith('player.') ||
35
- labelText.startsWith('settings.') ||
36
- labelText.startsWith('captions.'));
37
- const labelTextContent = isI18nKey ? i18n.t(labelText) || labelText : labelText;
38
-
39
- const label = DOMUtils.createElement('label', {
40
- className: labelClass,
41
- textContent: labelTextContent,
42
- attributes: {
43
- for: selectId,
44
- style: hidden ? 'display: none;' : undefined
45
- }
46
- });
47
-
48
- const select = DOMUtils.createElement('select', {
49
- className: selectClass,
50
- attributes: {
51
- id: selectId,
52
- style: hidden ? 'display: none;' : undefined
53
- }
54
- });
55
-
56
- options.forEach(opt => {
57
- const option = DOMUtils.createElement('option', {
58
- textContent: opt.text,
59
- attributes: {
60
- value: opt.value,
61
- selected: opt.selected ? 'selected' : undefined
62
- }
63
- });
64
- select.appendChild(option);
65
- });
66
-
67
- if (onChange) {
68
- select.addEventListener('change', onChange);
69
- }
70
-
71
- return { label, select };
72
- }
73
-
74
- export function toggleLabeledSelect(
75
- label: HTMLElement | null,
76
- select: HTMLElement | null,
77
- show: boolean
78
- ): void {
79
- if (label) {
80
- label.style.display = show ? 'block' : 'none';
81
- }
82
- if (select) {
83
- select.style.display = show ? 'block' : 'none';
84
- }
85
- }
86
-
87
- export function preventDragOnElement(element: HTMLElement | null): void {
88
- if (!element) return;
89
-
90
- (['pointerdown', 'mousedown', 'click'] as const).forEach(eventType => {
91
- element.addEventListener(eventType, (e: Event) => {
92
- e.stopPropagation();
93
- });
94
- });
95
- }
1
+ import { DOMUtils } from './DOMUtils.js';
2
+ import { i18n } from '../i18n/i18n.js';
3
+
4
+ export interface SelectOption {
5
+ value: string;
6
+ text: string;
7
+ selected?: boolean;
8
+ }
9
+
10
+ export interface LabeledSelectOptions {
11
+ classPrefix: string;
12
+ labelClass: string;
13
+ selectClass: string;
14
+ labelText: string;
15
+ selectId: string;
16
+ hidden?: boolean;
17
+ onChange?: (e: Event) => void;
18
+ options?: SelectOption[];
19
+ }
20
+
21
+ export function createLabeledSelect({
22
+ classPrefix: _classPrefix,
23
+ labelClass,
24
+ selectClass,
25
+ labelText,
26
+ selectId,
27
+ hidden = false,
28
+ onChange = undefined,
29
+ options = []
30
+ }: LabeledSelectOptions): { label: HTMLLabelElement; select: HTMLSelectElement } {
31
+ const isI18nKey =
32
+ typeof labelText === 'string' &&
33
+ (labelText.startsWith('transcript.') ||
34
+ labelText.startsWith('player.') ||
35
+ labelText.startsWith('settings.') ||
36
+ labelText.startsWith('captions.'));
37
+ const labelTextContent = isI18nKey ? i18n.t(labelText) || labelText : labelText;
38
+
39
+ const label = DOMUtils.createElement('label', {
40
+ className: labelClass,
41
+ textContent: labelTextContent,
42
+ attributes: {
43
+ for: selectId,
44
+ style: hidden ? 'display: none;' : undefined
45
+ }
46
+ });
47
+
48
+ const select = DOMUtils.createElement('select', {
49
+ className: selectClass,
50
+ attributes: {
51
+ id: selectId,
52
+ style: hidden ? 'display: none;' : undefined
53
+ }
54
+ });
55
+
56
+ options.forEach(opt => {
57
+ const option = DOMUtils.createElement('option', {
58
+ textContent: opt.text,
59
+ attributes: {
60
+ value: opt.value,
61
+ selected: opt.selected ? 'selected' : undefined
62
+ }
63
+ });
64
+ select.appendChild(option);
65
+ });
66
+
67
+ if (onChange) {
68
+ select.addEventListener('change', onChange);
69
+ }
70
+
71
+ return { label, select };
72
+ }
73
+
74
+ export function toggleLabeledSelect(
75
+ label: HTMLElement | null,
76
+ select: HTMLElement | null,
77
+ show: boolean
78
+ ): void {
79
+ if (label) {
80
+ label.style.display = show ? 'block' : 'none';
81
+ }
82
+ if (select) {
83
+ select.style.display = show ? 'block' : 'none';
84
+ }
85
+ }
86
+
87
+ export function preventDragOnElement(element: HTMLElement | null): void {
88
+ if (!element) return;
89
+
90
+ (['pointerdown', 'mousedown', 'click'] as const).forEach(eventType => {
91
+ element.addEventListener(eventType, (e: Event) => {
92
+ e.stopPropagation();
93
+ });
94
+ });
95
+ }