@mattebox/player 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +24 -0
  3. package/README.md +22 -0
  4. package/dist/cdn/mattebox-player.min.js +340 -0
  5. package/dist/controls/bar.d.ts +56 -0
  6. package/dist/controls/bar.d.ts.map +1 -0
  7. package/dist/controls/bar.js +245 -0
  8. package/dist/controls/bar.js.map +1 -0
  9. package/dist/controls/buttons.d.ts +13 -0
  10. package/dist/controls/buttons.d.ts.map +1 -0
  11. package/dist/controls/buttons.js +157 -0
  12. package/dist/controls/buttons.js.map +1 -0
  13. package/dist/controls/control.d.ts +12 -0
  14. package/dist/controls/control.d.ts.map +1 -0
  15. package/dist/controls/control.js +2 -0
  16. package/dist/controls/control.js.map +1 -0
  17. package/dist/controls/cues.d.ts +33 -0
  18. package/dist/controls/cues.d.ts.map +1 -0
  19. package/dist/controls/cues.js +170 -0
  20. package/dist/controls/cues.js.map +1 -0
  21. package/dist/controls/fullscreen.d.ts +21 -0
  22. package/dist/controls/fullscreen.d.ts.map +1 -0
  23. package/dist/controls/fullscreen.js +78 -0
  24. package/dist/controls/fullscreen.js.map +1 -0
  25. package/dist/controls/icons.d.ts +35 -0
  26. package/dist/controls/icons.d.ts.map +1 -0
  27. package/dist/controls/icons.js +76 -0
  28. package/dist/controls/icons.js.map +1 -0
  29. package/dist/controls/keys.d.ts +26 -0
  30. package/dist/controls/keys.d.ts.map +1 -0
  31. package/dist/controls/keys.js +66 -0
  32. package/dist/controls/keys.js.map +1 -0
  33. package/dist/controls/live.d.ts +10 -0
  34. package/dist/controls/live.d.ts.map +1 -0
  35. package/dist/controls/live.js +59 -0
  36. package/dist/controls/live.js.map +1 -0
  37. package/dist/controls/menu.d.ts +34 -0
  38. package/dist/controls/menu.d.ts.map +1 -0
  39. package/dist/controls/menu.js +225 -0
  40. package/dist/controls/menu.js.map +1 -0
  41. package/dist/controls/menus.d.ts +43 -0
  42. package/dist/controls/menus.d.ts.map +1 -0
  43. package/dist/controls/menus.js +262 -0
  44. package/dist/controls/menus.js.map +1 -0
  45. package/dist/controls/options.d.ts +44 -0
  46. package/dist/controls/options.d.ts.map +1 -0
  47. package/dist/controls/options.js +54 -0
  48. package/dist/controls/options.js.map +1 -0
  49. package/dist/controls/pip.d.ts +16 -0
  50. package/dist/controls/pip.d.ts.map +1 -0
  51. package/dist/controls/pip.js +53 -0
  52. package/dist/controls/pip.js.map +1 -0
  53. package/dist/controls/ranges.d.ts +24 -0
  54. package/dist/controls/ranges.d.ts.map +1 -0
  55. package/dist/controls/ranges.js +48 -0
  56. package/dist/controls/ranges.js.map +1 -0
  57. package/dist/controls/screens.d.ts +22 -0
  58. package/dist/controls/screens.d.ts.map +1 -0
  59. package/dist/controls/screens.js +69 -0
  60. package/dist/controls/screens.js.map +1 -0
  61. package/dist/controls/seek.d.ts +52 -0
  62. package/dist/controls/seek.d.ts.map +1 -0
  63. package/dist/controls/seek.js +215 -0
  64. package/dist/controls/seek.js.map +1 -0
  65. package/dist/controls/slider.d.ts +28 -0
  66. package/dist/controls/slider.d.ts.map +1 -0
  67. package/dist/controls/slider.js +145 -0
  68. package/dist/controls/slider.js.map +1 -0
  69. package/dist/controls/speed.d.ts +8 -0
  70. package/dist/controls/speed.d.ts.map +1 -0
  71. package/dist/controls/speed.js +34 -0
  72. package/dist/controls/speed.js.map +1 -0
  73. package/dist/controls/time.d.ts +8 -0
  74. package/dist/controls/time.d.ts.map +1 -0
  75. package/dist/controls/time.js +25 -0
  76. package/dist/controls/time.js.map +1 -0
  77. package/dist/controls/volume.d.ts +8 -0
  78. package/dist/controls/volume.d.ts.map +1 -0
  79. package/dist/controls/volume.js +29 -0
  80. package/dist/controls/volume.js.map +1 -0
  81. package/dist/dom.d.ts +18 -0
  82. package/dist/dom.d.ts.map +1 -0
  83. package/dist/dom.js +45 -0
  84. package/dist/dom.js.map +1 -0
  85. package/dist/element.d.ts +101 -0
  86. package/dist/element.d.ts.map +1 -0
  87. package/dist/element.js +327 -0
  88. package/dist/element.js.map +1 -0
  89. package/dist/es2015/_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/asyncToGenerator.js +27 -0
  90. package/dist/es2015/_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/defineProperty.js +12 -0
  91. package/dist/es2015/_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/objectSpread2.js +25 -0
  92. package/dist/es2015/_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/toPrimitive.js +14 -0
  93. package/dist/es2015/_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/toPropertyKey.js +9 -0
  94. package/dist/es2015/_virtual/_@oxc-project_runtime@0.148.0/helpers/esm/typeof.js +11 -0
  95. package/dist/es2015/controls/bar.js +227 -0
  96. package/dist/es2015/controls/buttons.js +146 -0
  97. package/dist/es2015/controls/cues.js +153 -0
  98. package/dist/es2015/controls/fullscreen.js +54 -0
  99. package/dist/es2015/controls/icons.js +50 -0
  100. package/dist/es2015/controls/keys.js +60 -0
  101. package/dist/es2015/controls/live.js +60 -0
  102. package/dist/es2015/controls/menu.js +226 -0
  103. package/dist/es2015/controls/menus.js +258 -0
  104. package/dist/es2015/controls/options.js +46 -0
  105. package/dist/es2015/controls/pip.js +39 -0
  106. package/dist/es2015/controls/ranges.js +51 -0
  107. package/dist/es2015/controls/screens.js +74 -0
  108. package/dist/es2015/controls/seek.js +203 -0
  109. package/dist/es2015/controls/slider.js +136 -0
  110. package/dist/es2015/controls/speed.js +41 -0
  111. package/dist/es2015/controls/time.js +27 -0
  112. package/dist/es2015/controls/volume.js +30 -0
  113. package/dist/es2015/dom.js +43 -0
  114. package/dist/es2015/element.js +311 -0
  115. package/dist/es2015/index.js +10 -0
  116. package/dist/es2015/namespaces.js +7 -0
  117. package/dist/es2015/panels/drm.js +29 -0
  118. package/dist/es2015/panels/error.js +25 -0
  119. package/dist/es2015/panels/live.js +48 -0
  120. package/dist/es2015/panels/quality.js +52 -0
  121. package/dist/es2015/panels/tracks.js +47 -0
  122. package/dist/es2015/presets.js +46 -0
  123. package/dist/es2015/style.js +347 -0
  124. package/dist/index.d.ts +4 -0
  125. package/dist/index.d.ts.map +1 -0
  126. package/dist/index.js +9 -0
  127. package/dist/index.js.map +1 -0
  128. package/dist/namespaces.d.ts +45 -0
  129. package/dist/namespaces.d.ts.map +1 -0
  130. package/dist/namespaces.js +5 -0
  131. package/dist/namespaces.js.map +1 -0
  132. package/dist/panels/drm.d.ts +8 -0
  133. package/dist/panels/drm.d.ts.map +1 -0
  134. package/dist/panels/drm.js +36 -0
  135. package/dist/panels/drm.js.map +1 -0
  136. package/dist/panels/error.d.ts +13 -0
  137. package/dist/panels/error.d.ts.map +1 -0
  138. package/dist/panels/error.js +23 -0
  139. package/dist/panels/error.js.map +1 -0
  140. package/dist/panels/live.d.ts +3 -0
  141. package/dist/panels/live.d.ts.map +1 -0
  142. package/dist/panels/live.js +56 -0
  143. package/dist/panels/live.js.map +1 -0
  144. package/dist/panels/panel.d.ts +13 -0
  145. package/dist/panels/panel.d.ts.map +1 -0
  146. package/dist/panels/panel.js +2 -0
  147. package/dist/panels/panel.js.map +1 -0
  148. package/dist/panels/quality.d.ts +3 -0
  149. package/dist/panels/quality.d.ts.map +1 -0
  150. package/dist/panels/quality.js +59 -0
  151. package/dist/panels/quality.js.map +1 -0
  152. package/dist/panels/tracks.d.ts +3 -0
  153. package/dist/panels/tracks.d.ts.map +1 -0
  154. package/dist/panels/tracks.js +49 -0
  155. package/dist/panels/tracks.js.map +1 -0
  156. package/dist/presets.d.ts +23 -0
  157. package/dist/presets.d.ts.map +1 -0
  158. package/dist/presets.js +36 -0
  159. package/dist/presets.js.map +1 -0
  160. package/dist/style.d.ts +13 -0
  161. package/dist/style.d.ts.map +1 -0
  162. package/dist/style.js +345 -0
  163. package/dist/style.js.map +1 -0
  164. package/package.json +58 -0
@@ -0,0 +1,59 @@
1
+ /**
2
+ * The live button: a dot and the word, the dot red at the edge and grey
3
+ * behind it, the way viewers read it everywhere. Shown once the stream has
4
+ * an availability window, which is what makes it live; disabled at the
5
+ * edge, where there is nowhere to go; a click seeks to the edge. The same
6
+ * test the live panel uses.
7
+ *
8
+ * Without a seek bar, when the window is too narrow to be worth one, there
9
+ * is nowhere to come back from either: the dot stays red and the button
10
+ * stays inert, whatever the playhead does.
11
+ */
12
+ import { el, state } from '../dom.js';
13
+ export function liveButton(video) {
14
+ const root = el('button', 'control live-button');
15
+ root.type = 'button';
16
+ const dot = el('span', 'live-dot');
17
+ root.append(dot, el('span', 'live-text', 'LIVE'));
18
+ root.setAttribute('aria-label', 'Go to the live edge');
19
+ root.hidden = true;
20
+ let live;
21
+ let bar = true;
22
+ function tick() {
23
+ const on = live !== undefined && live.edge !== null;
24
+ root.hidden = !on;
25
+ if (!on)
26
+ return;
27
+ const atEdge = !bar || live?.atEdge === true;
28
+ root.disabled = atEdge;
29
+ state(root, 'control live-button', { 'at-edge': atEdge });
30
+ state(dot, 'live-dot', { 'at-edge': atEdge });
31
+ root.setAttribute('aria-label', atEdge ? 'At the live edge' : 'Go to the live edge');
32
+ }
33
+ function click() {
34
+ live?.seekToEdge();
35
+ }
36
+ root.addEventListener('click', click);
37
+ video.addEventListener('timeupdate', tick);
38
+ tick();
39
+ return {
40
+ root,
41
+ attach(found) {
42
+ live = found;
43
+ tick();
44
+ },
45
+ detach() {
46
+ live = undefined;
47
+ tick();
48
+ },
49
+ seekable(on) {
50
+ bar = on;
51
+ tick();
52
+ },
53
+ dispose() {
54
+ root.removeEventListener('click', click);
55
+ video.removeEventListener('timeupdate', tick);
56
+ },
57
+ };
58
+ }
59
+ //# sourceMappingURL=live.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/controls/live.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAWtC,MAAM,UAAU,UAAU,CAAC,KAAuB;IAChD,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;IACjD,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC;IACrB,MAAM,GAAG,GAAG,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACnC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IAClD,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,qBAAqB,CAAC,CAAC;IACvD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACnB,IAAI,IAAyB,CAAC;IAC9B,IAAI,GAAG,GAAG,IAAI,CAAC;IAEf,SAAS,IAAI;QACX,MAAM,EAAE,GAAG,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC;QACpD,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClB,IAAI,CAAC,EAAE;YAAE,OAAO;QAChB,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;QAC7C,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC;QACvB,KAAK,CAAC,IAAI,EAAE,qBAAqB,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAC1D,KAAK,CAAC,GAAG,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAC9C,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC;IACvF,CAAC;IAED,SAAS,KAAK;QACZ,IAAI,EAAE,UAAU,EAAE,CAAC;IACrB,CAAC;IAED,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACtC,KAAK,CAAC,gBAAgB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAC3C,IAAI,EAAE,CAAC;IAEP,OAAO;QACL,IAAI;QACJ,MAAM,CAAC,KAA0B;YAC/B,IAAI,GAAG,KAAK,CAAC;YACb,IAAI,EAAE,CAAC;QACT,CAAC;QACD,MAAM;YACJ,IAAI,GAAG,SAAS,CAAC;YACjB,IAAI,EAAE,CAAC;QACT,CAAC;QACD,QAAQ,CAAC,EAAW;YAClB,GAAG,GAAG,EAAE,CAAC;YACT,IAAI,EAAE,CAAC;QACT,CAAC;QACD,OAAO;YACL,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACzC,KAAK,CAAC,mBAAmB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;QAChD,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type { Control } from './control.js';
2
+ import type { IconName } from './icons.js';
3
+ export interface MenuGroup {
4
+ /** The part suffix: `track`, `size`. */
5
+ readonly name: string;
6
+ /** A heading, or none for a menu of one group. */
7
+ readonly label?: string;
8
+ readonly items: ReadonlyArray<readonly [string, string]>;
9
+ readonly value: string;
10
+ readonly onSelect: (value: string) => void;
11
+ }
12
+ /** An entry that opens a page of groups, with a Back at its top. */
13
+ export interface MenuPage {
14
+ readonly name: string;
15
+ readonly label: string;
16
+ readonly entries: readonly MenuEntry[];
17
+ }
18
+ export type MenuEntry = MenuGroup | MenuPage;
19
+ export interface MenuOptions {
20
+ /** The part prefix: `quality`, `audio`, `text`, `speed`. */
21
+ readonly name: string;
22
+ /** The accessible name of the button. */
23
+ readonly label: string;
24
+ readonly icon: IconName;
25
+ }
26
+ export interface Menu extends Control {
27
+ /** Replaces the entries, back at the first page. */
28
+ fill(entries: readonly MenuEntry[]): void;
29
+ /** Swaps the button's glyph, for a menu whose state shows on it. */
30
+ show(name: IconName): void;
31
+ close(): void;
32
+ }
33
+ export declare function menu(options: MenuOptions): Menu;
34
+ //# sourceMappingURL=menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu.d.ts","sourceRoot":"","sources":["../../src/controls/menu.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG3C,MAAM,WAAW,SAAS;IACxB,wCAAwC;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACzD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAED,oEAAoE;AACpE,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;CACxC;AAED,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE7C,MAAM,WAAW,WAAW;IAC1B,4DAA4D;IAC5D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;CACzB;AAED,MAAM,WAAW,IAAK,SAAQ,OAAO;IACnC,oDAAoD;IACpD,IAAI,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,GAAG,IAAI,CAAC;IAC1C,oEAAoE;IACpE,IAAI,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC3B,KAAK,IAAI,IAAI,CAAC;CACf;AASD,wBAAgB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CA8M/C"}
@@ -0,0 +1,225 @@
1
+ /**
2
+ * The menu primitive the quality, audio, subtitles and speed menus share: a
3
+ * button that opens a popup of radio items above it, in one or more groups
4
+ * with a heading each, and pages behind entries that open them. The button
5
+ * carries the name and `aria-expanded`; the popup is `role="menu"`, every
6
+ * choice a `menuitemradio` with `aria-checked`, the checked one also
7
+ * carrying `checked` on its part name; an entry that opens a page is a
8
+ * `menuitem` with `aria-haspopup`, and the page starts with a Back.
9
+ *
10
+ * Open on click. Inside, the arrows move focus across every item, Home and
11
+ * End jump, Enter and Space choose, Escape goes back a page or closes and
12
+ * hands focus to the button. A choice closes the popup. A pointer down
13
+ * anywhere else closes it too.
14
+ *
15
+ * The popup never leaves the picture: on opening it takes the room above
16
+ * the button inside the stage as its height and scrolls past that.
17
+ */
18
+ import { el, state } from '../dom.js';
19
+ import { glyph, icon } from './icons.js';
20
+ /** Air between the popup's top and the stage's. */
21
+ const AIR = 8;
22
+ function isPage(entry) {
23
+ return 'entries' in entry;
24
+ }
25
+ export function menu(options) {
26
+ const { name } = options;
27
+ const root = el('div', `menu ${name}-menu`);
28
+ const button = el('button', `control ${name}-button`);
29
+ button.type = 'button';
30
+ button.setAttribute('aria-label', options.label);
31
+ button.setAttribute('aria-haspopup', 'menu');
32
+ button.setAttribute('aria-expanded', 'false');
33
+ const svg = icon(options.icon);
34
+ button.append(svg);
35
+ const popup = el('div', `popup ${name}-popup`);
36
+ popup.setAttribute('role', 'menu');
37
+ popup.setAttribute('aria-label', options.label);
38
+ popup.hidden = true;
39
+ root.append(button, popup);
40
+ let open = false;
41
+ let first = [];
42
+ /** The pages opened, the first being the menu itself. */
43
+ let stack = [];
44
+ const handlers = new WeakMap();
45
+ function items() {
46
+ return [...popup.querySelectorAll('button')];
47
+ }
48
+ function checked() {
49
+ return items().find((item) => item.getAttribute('aria-checked') === 'true');
50
+ }
51
+ /** The focused element as this tree sees it: inside shadow DOM, `document.activeElement` is the host. */
52
+ function focused() {
53
+ return popup.getRootNode().activeElement;
54
+ }
55
+ function outside(event) {
56
+ if (!event.composedPath().includes(root))
57
+ close();
58
+ }
59
+ /** Whatever room there is above the button inside the stage, so the popup never leaves the picture. */
60
+ function fit() {
61
+ const stage = root.closest('[part~="stage"]');
62
+ if (stage === null)
63
+ return;
64
+ const room = button.getBoundingClientRect().top - stage.getBoundingClientRect().top - AIR;
65
+ popup.style.maxHeight = `${Math.max(0, Math.floor(room))}px`;
66
+ }
67
+ function clear() {
68
+ for (const item of items()) {
69
+ const handler = handlers.get(item);
70
+ if (handler !== undefined)
71
+ item.removeEventListener('click', handler);
72
+ }
73
+ popup.replaceChildren();
74
+ }
75
+ function item(part, text, handler) {
76
+ const node = el('button', part, text);
77
+ node.type = 'button';
78
+ node.tabIndex = -1;
79
+ handlers.set(node, handler);
80
+ node.addEventListener('click', handler);
81
+ return node;
82
+ }
83
+ /** Draws the page on top of the stack. */
84
+ function render() {
85
+ clear();
86
+ const page = stack[stack.length - 1];
87
+ if (page === undefined)
88
+ return;
89
+ let tab = true;
90
+ if (stack.length > 1) {
91
+ const back = item(`item back-item ${name}-back-item`, page.label, () => {
92
+ stack.pop();
93
+ render();
94
+ items()[0]?.focus();
95
+ });
96
+ back.setAttribute('role', 'menuitem');
97
+ back.setAttribute('aria-label', `Back from ${page.label}`);
98
+ popup.append(back);
99
+ }
100
+ for (const entry of page.entries) {
101
+ if (isPage(entry)) {
102
+ const link = item(`item page-item ${name}-${entry.name}-item`, entry.label, () => {
103
+ stack.push(entry);
104
+ render();
105
+ items()[0]?.focus();
106
+ });
107
+ link.setAttribute('role', 'menuitem');
108
+ link.setAttribute('aria-haspopup', 'menu');
109
+ popup.append(link);
110
+ continue;
111
+ }
112
+ const section = el('div', `section ${name}-${entry.name}-section`);
113
+ section.setAttribute('role', 'group');
114
+ if (entry.label !== undefined) {
115
+ section.setAttribute('aria-label', entry.label);
116
+ section.append(el('div', `section-label ${name}-${entry.name}-label`, entry.label));
117
+ }
118
+ for (const [id, text] of entry.items) {
119
+ const choice = item(`item ${name}-item ${name}-${entry.name}-item`, text, () => {
120
+ close();
121
+ button.focus();
122
+ entry.onSelect(id);
123
+ });
124
+ choice.value = id;
125
+ choice.setAttribute('role', 'menuitemradio');
126
+ const on = id === entry.value;
127
+ choice.setAttribute('aria-checked', String(on));
128
+ state(choice, `item ${name}-item ${name}-${entry.name}-item`, { checked: on });
129
+ // One tab stop: the first checked item.
130
+ if (on && tab) {
131
+ choice.tabIndex = 0;
132
+ tab = false;
133
+ }
134
+ section.append(choice);
135
+ }
136
+ popup.append(section);
137
+ }
138
+ fit();
139
+ }
140
+ function close() {
141
+ if (!open)
142
+ return;
143
+ open = false;
144
+ popup.hidden = true;
145
+ button.setAttribute('aria-expanded', 'false');
146
+ state(root, `menu ${name}-menu`, { open: false });
147
+ document.removeEventListener('pointerdown', outside, true);
148
+ if (stack.length > 1) {
149
+ stack = stack.slice(0, 1);
150
+ render();
151
+ }
152
+ }
153
+ function show() {
154
+ if (open)
155
+ return;
156
+ open = true;
157
+ popup.hidden = false;
158
+ button.setAttribute('aria-expanded', 'true');
159
+ state(root, `menu ${name}-menu`, { open: true });
160
+ document.addEventListener('pointerdown', outside, true);
161
+ fit();
162
+ (checked() ?? items()[0])?.focus();
163
+ }
164
+ function toggle() {
165
+ if (open)
166
+ close();
167
+ else
168
+ show();
169
+ }
170
+ function key(event) {
171
+ const list = items();
172
+ const index = list.indexOf(focused());
173
+ let next;
174
+ switch (event.key) {
175
+ case 'ArrowDown':
176
+ next = (index + 1) % list.length;
177
+ break;
178
+ case 'ArrowUp':
179
+ next = (index - 1 + list.length) % list.length;
180
+ break;
181
+ case 'Home':
182
+ next = 0;
183
+ break;
184
+ case 'End':
185
+ next = list.length - 1;
186
+ break;
187
+ case 'Escape':
188
+ event.preventDefault();
189
+ if (stack.length > 1) {
190
+ stack.pop();
191
+ render();
192
+ items()[0]?.focus();
193
+ return;
194
+ }
195
+ close();
196
+ button.focus();
197
+ return;
198
+ default:
199
+ return;
200
+ }
201
+ event.preventDefault();
202
+ list[next]?.focus();
203
+ }
204
+ button.addEventListener('click', toggle);
205
+ popup.addEventListener('keydown', key);
206
+ return {
207
+ root,
208
+ fill(entries) {
209
+ first = entries;
210
+ stack = [{ name, label: options.label, entries: first }];
211
+ render();
212
+ },
213
+ show(glyphName) {
214
+ glyph(svg, glyphName);
215
+ },
216
+ close,
217
+ dispose() {
218
+ close();
219
+ clear();
220
+ button.removeEventListener('click', toggle);
221
+ popup.removeEventListener('keydown', key);
222
+ },
223
+ };
224
+ }
225
+ //# sourceMappingURL=menu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu.js","sourceRoot":"","sources":["../../src/controls/menu.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The menus over the engine's namespaces, for the bar under custom
3
+ * controls: quality over `engine.quality`, audio and subtitles over
4
+ * `engine.tracks`, and a lock badge over `engine.drm`. The same reads and
5
+ * writes as the panels, in the bar's shape. Each factory answers null for
6
+ * a native session, and each menu hides itself while it has nothing to
7
+ * offer.
8
+ *
9
+ * The subtitles menu also carries how they look: a size and a background,
10
+ * kept as attributes on the host, where the element's stylesheet turns
11
+ * them into the custom properties the cue rule reads. A page can set them
12
+ * in markup and persist them however it likes.
13
+ */
14
+ import type { Mattebox } from 'mattebox';
15
+ import type { Control } from './control.js';
16
+ /** What a menu over a session gets: the engine, and the host for the state it reflects there. */
17
+ export interface MenuContext {
18
+ readonly engine: Mattebox;
19
+ readonly host: HTMLElement;
20
+ }
21
+ export type MenuFactory = (context: MenuContext) => Control;
22
+ /** The subtitle looks, as attribute name, choices, and default. */
23
+ export declare const SUBTITLE_SIZE = "subtitle-size";
24
+ export declare const SUBTITLE_BACKGROUND = "subtitle-background";
25
+ /** The quality menu: the pin, where "auto" means none. Hidden without renditions. */
26
+ export declare const qualityMenu: MenuFactory;
27
+ /** The audio menu. Hidden unless there is a choice to make. */
28
+ export declare const audioMenu: MenuFactory;
29
+ /**
30
+ * The subtitles menu, with "off" because a text selection is releasable
31
+ * and an audio one is not, and a Settings page behind it with the size and
32
+ * the background. The glyph says whether a track is on.
33
+ */
34
+ export declare const textMenu: MenuFactory;
35
+ /**
36
+ * A lock over `engine.drm`, hidden until a key session opens and absent
37
+ * without the EME stages. Hover or focus shows what it knows: the key
38
+ * system, and the key sessions with their statuses.
39
+ */
40
+ export declare const drmBadge: MenuFactory;
41
+ /** By the name the layout knows them by. */
42
+ export declare const MENUS: Readonly<Record<string, MenuFactory>>;
43
+ //# sourceMappingURL=menus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menus.d.ts","sourceRoot":"","sources":["../../src/controls/menus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAe,QAAQ,EAAoB,MAAM,UAAU,CAAC;AAGxE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAK5C,iGAAiG;AACjG,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;CAC5B;AAED,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC;AAK5D,mEAAmE;AACnE,eAAO,MAAM,aAAa,kBAAkB,CAAC;AAC7C,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AAyBzD,qFAAqF;AACrF,eAAO,MAAM,WAAW,EAAE,WAqCzB,CAAC;AAeF,+DAA+D;AAC/D,eAAO,MAAM,SAAS,EAAE,WA6BvB,CAAC;AAaF;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,WA2DtB,CAAC;AAoBF;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,WA6DtB,CAAC;AAEF,4CAA4C;AAC5C,eAAO,MAAM,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAKvD,CAAC"}
@@ -0,0 +1,262 @@
1
+ import { el } from '../dom.js';
2
+ import { namespaces } from '../namespaces.js';
3
+ import { icon } from './icons.js';
4
+ import { menu } from './menu.js';
5
+ const AUTO = 'auto';
6
+ const OFF = 'off';
7
+ /** The subtitle looks, as attribute name, choices, and default. */
8
+ export const SUBTITLE_SIZE = 'subtitle-size';
9
+ export const SUBTITLE_BACKGROUND = 'subtitle-background';
10
+ const SIZES = [
11
+ ['small', 'Small'],
12
+ ['medium', 'Medium'],
13
+ ['large', 'Large'],
14
+ ['xlarge', 'Extra large'],
15
+ ];
16
+ const BACKGROUNDS = [
17
+ ['none', 'None'],
18
+ ['dark', 'Dark'],
19
+ ['solid', 'Solid'],
20
+ ];
21
+ /** A rendition's height when the manifest declared one, its bitrate otherwise. */
22
+ function renditionLabel(rendition) {
23
+ if (rendition.height !== undefined)
24
+ return `${rendition.height}p`;
25
+ return `${Math.round(rendition.bitrate / 1000)} kbps`;
26
+ }
27
+ /** The language, then the role, then the id: whichever the manifest gave. */
28
+ function trackLabel(track) {
29
+ const parts = [track.lang, track.role].filter((part) => part !== undefined);
30
+ return parts.length === 0 ? track.id : parts.join(' · ');
31
+ }
32
+ /** The quality menu: the pin, where "auto" means none. Hidden without renditions. */
33
+ export const qualityMenu = ({ engine }) => {
34
+ const quality = engine.quality;
35
+ const control = menu({ name: 'quality', label: 'Quality', icon: 'settings' });
36
+ function render() {
37
+ const items = [[AUTO, 'Auto']];
38
+ for (const rendition of quality.renditions)
39
+ items.push([rendition.id, renditionLabel(rendition)]);
40
+ control.fill([
41
+ {
42
+ name: 'rendition',
43
+ items,
44
+ value: quality.pinned ?? AUTO,
45
+ onSelect(value) {
46
+ if (value === AUTO)
47
+ quality.auto();
48
+ else
49
+ quality.pin(value);
50
+ render();
51
+ },
52
+ },
53
+ ]);
54
+ control.root.hidden = quality.renditions.length === 0;
55
+ }
56
+ const offs = [
57
+ engine.on('tracks:changed', render),
58
+ engine.on('quality:constraints-unsatisfiable', render),
59
+ engine.on('quality:pin-unsatisfiable', render),
60
+ ];
61
+ render();
62
+ return {
63
+ root: control.root,
64
+ dispose() {
65
+ for (const off of offs)
66
+ off();
67
+ control.dispose();
68
+ },
69
+ };
70
+ };
71
+ /** The tracks of one content type as menu items, with the active one. */
72
+ function trackItems(engine, contentType, off) {
73
+ const tracks = engine.tracks;
74
+ const available = tracks.available.filter((track) => track.contentType === contentType);
75
+ const items = off ? [[OFF, 'Off']] : [];
76
+ for (const track of available)
77
+ items.push([track.id, trackLabel(track)]);
78
+ return [items, tracks.active(contentType)?.id ?? OFF, available.length];
79
+ }
80
+ /** The audio menu. Hidden unless there is a choice to make. */
81
+ export const audioMenu = ({ engine }) => {
82
+ const control = menu({ name: 'audio', label: 'Audio', icon: 'music' });
83
+ function render() {
84
+ const [items, active, count] = trackItems(engine, 'audio', false);
85
+ control.fill([
86
+ {
87
+ name: 'track',
88
+ items,
89
+ value: active,
90
+ onSelect(value) {
91
+ engine.tracks.select(value);
92
+ render();
93
+ },
94
+ },
95
+ ]);
96
+ control.root.hidden = count < 2;
97
+ }
98
+ const offs = [engine.on('tracks:changed', render), engine.on('tracks:selected', render)];
99
+ render();
100
+ return {
101
+ root: control.root,
102
+ dispose() {
103
+ for (const off of offs)
104
+ off();
105
+ control.dispose();
106
+ },
107
+ };
108
+ };
109
+ /** An attribute's value where it is one of the choices, else the default. */
110
+ function choice(host, attribute, choices, fallback) {
111
+ const value = host.getAttribute(attribute);
112
+ return value !== null && choices.some(([id]) => id === value) ? value : fallback;
113
+ }
114
+ /**
115
+ * The subtitles menu, with "off" because a text selection is releasable
116
+ * and an audio one is not, and a Settings page behind it with the size and
117
+ * the background. The glyph says whether a track is on.
118
+ */
119
+ export const textMenu = ({ engine, host }) => {
120
+ const control = menu({ name: 'text', label: 'Subtitles', icon: 'closed-captions' });
121
+ function looks(attribute, name, label, choices, fallback) {
122
+ return {
123
+ name,
124
+ label,
125
+ items: choices,
126
+ value: choice(host, attribute, choices, fallback),
127
+ onSelect(value) {
128
+ host.setAttribute(attribute, value);
129
+ render();
130
+ },
131
+ };
132
+ }
133
+ function render() {
134
+ const [items, active, count] = trackItems(engine, 'text', true);
135
+ control.fill([
136
+ {
137
+ name: 'track',
138
+ label: 'Track',
139
+ items,
140
+ value: active,
141
+ onSelect(value) {
142
+ if (value === OFF)
143
+ engine.tracks.deselect('text');
144
+ else
145
+ engine.tracks.select(value);
146
+ render();
147
+ },
148
+ },
149
+ {
150
+ name: 'settings',
151
+ label: 'Settings',
152
+ entries: [
153
+ looks(SUBTITLE_SIZE, 'size', 'Size', SIZES, 'medium'),
154
+ looks(SUBTITLE_BACKGROUND, 'background', 'Background', BACKGROUNDS, 'dark'),
155
+ ],
156
+ },
157
+ ]);
158
+ control.show(active === OFF ? 'closed-captions' : 'closed-captions-on');
159
+ control.root.hidden = count === 0;
160
+ }
161
+ const offs = [engine.on('tracks:changed', render), engine.on('tracks:selected', render)];
162
+ render();
163
+ return {
164
+ root: control.root,
165
+ dispose() {
166
+ for (const off of offs)
167
+ off();
168
+ control.dispose();
169
+ },
170
+ };
171
+ };
172
+ /** The name a viewer knows a key system by. */
173
+ function keySystemName(id) {
174
+ if (id.startsWith('com.widevine'))
175
+ return 'Widevine';
176
+ if (id.startsWith('com.microsoft.playready'))
177
+ return 'PlayReady';
178
+ if (id.startsWith('com.apple.fps'))
179
+ return 'FairPlay';
180
+ return id;
181
+ }
182
+ /** "3 keys: usable ×2, expired ×1", or "no key yet". */
183
+ function sessionsText(sessions) {
184
+ if (sessions.length === 0)
185
+ return 'no key yet';
186
+ const counts = new Map();
187
+ for (const session of sessions)
188
+ counts.set(session.status, (counts.get(session.status) ?? 0) + 1);
189
+ const parts = [];
190
+ for (const [status, count] of counts)
191
+ parts.push(count > 1 ? `${status} ×${count}` : status);
192
+ return `${sessions.length} ${sessions.length === 1 ? 'key' : 'keys'}: ${parts.join(', ')}`;
193
+ }
194
+ /**
195
+ * A lock over `engine.drm`, hidden until a key session opens and absent
196
+ * without the EME stages. Hover or focus shows what it knows: the key
197
+ * system, and the key sessions with their statuses.
198
+ */
199
+ export const drmBadge = ({ engine }) => {
200
+ const drm = namespaces(engine).drm;
201
+ const root = el('span', 'badge drm-badge');
202
+ root.setAttribute('role', 'img');
203
+ root.append(icon('lock-closed'));
204
+ root.hidden = true;
205
+ if (drm === undefined)
206
+ return { root, dispose() { } };
207
+ const tooltip = el('div', 'tooltip drm-tooltip');
208
+ tooltip.setAttribute('role', 'tooltip');
209
+ const system = el('div', 'tooltip-title drm-tooltip-title');
210
+ const id = el('div', 'tooltip-text drm-tooltip-id');
211
+ const keys = el('div', 'tooltip-text drm-tooltip-keys');
212
+ tooltip.append(system, id, keys);
213
+ tooltip.hidden = true;
214
+ root.append(tooltip);
215
+ root.tabIndex = 0;
216
+ function render() {
217
+ const name = drm?.keySystem ?? null;
218
+ root.hidden = name === null;
219
+ if (name === null)
220
+ return;
221
+ const sessions = drm?.sessions ?? [];
222
+ system.textContent = keySystemName(name);
223
+ id.textContent = name;
224
+ keys.textContent = sessionsText(sessions);
225
+ root.setAttribute('aria-label', `Protected by ${keySystemName(name)}, ${sessionsText(sessions)}`);
226
+ }
227
+ function show() {
228
+ tooltip.hidden = false;
229
+ }
230
+ function hide() {
231
+ tooltip.hidden = true;
232
+ }
233
+ root.addEventListener('pointerenter', show);
234
+ root.addEventListener('pointerleave', hide);
235
+ root.addEventListener('focus', show);
236
+ root.addEventListener('blur', hide);
237
+ const offs = [
238
+ engine.on('drm:keysystem', render),
239
+ engine.on('drm:keystatus', render),
240
+ engine.on('drm:encrypted', render),
241
+ ];
242
+ render();
243
+ return {
244
+ root,
245
+ dispose() {
246
+ for (const off of offs)
247
+ off();
248
+ root.removeEventListener('pointerenter', show);
249
+ root.removeEventListener('pointerleave', hide);
250
+ root.removeEventListener('focus', show);
251
+ root.removeEventListener('blur', hide);
252
+ },
253
+ };
254
+ };
255
+ /** By the name the layout knows them by. */
256
+ export const MENUS = {
257
+ subtitles: textMenu,
258
+ audio: audioMenu,
259
+ quality: qualityMenu,
260
+ drm: drmBadge,
261
+ };
262
+ //# sourceMappingURL=menus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menus.js","sourceRoot":"","sources":["../../src/controls/menus.ts"],"names":[],"mappings":"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"}