@mattebox/player 0.4.0 → 0.6.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 (71) hide show
  1. package/README.md +9 -6
  2. package/dist/cdn/mattebox-player.min.js +105 -34
  3. package/dist/element.d.ts +17 -21
  4. package/dist/element.d.ts.map +1 -1
  5. package/dist/element.js +59 -41
  6. package/dist/element.js.map +1 -1
  7. package/dist/elements/spinner.d.ts +25 -0
  8. package/dist/elements/spinner.d.ts.map +1 -0
  9. package/dist/elements/spinner.js +80 -0
  10. package/dist/elements/spinner.js.map +1 -0
  11. package/dist/elements/start-button.d.ts.map +1 -1
  12. package/dist/elements/start-button.js +3 -2
  13. package/dist/elements/start-button.js.map +1 -1
  14. package/dist/elements/title.d.ts +19 -0
  15. package/dist/elements/title.d.ts.map +1 -0
  16. package/dist/elements/title.js +139 -0
  17. package/dist/elements/title.js.map +1 -0
  18. package/dist/entries/spinner.d.ts +5 -0
  19. package/dist/entries/spinner.d.ts.map +1 -0
  20. package/dist/entries/spinner.js +9 -0
  21. package/dist/entries/spinner.js.map +1 -0
  22. package/dist/entries/title.d.ts +5 -0
  23. package/dist/entries/title.d.ts.map +1 -0
  24. package/dist/entries/title.js +9 -0
  25. package/dist/entries/title.js.map +1 -0
  26. package/dist/es2015/_virtual/{_@oxc-project_runtime@0.149.0 → _@oxc-project_runtime@0.150.0}/helpers/esm/asyncToGenerator.js +1 -1
  27. package/dist/es2015/_virtual/{_@oxc-project_runtime@0.149.0 → _@oxc-project_runtime@0.150.0}/helpers/esm/defineProperty.js +1 -1
  28. package/dist/es2015/_virtual/{_@oxc-project_runtime@0.149.0 → _@oxc-project_runtime@0.150.0}/helpers/esm/objectSpread2.js +1 -1
  29. package/dist/es2015/_virtual/{_@oxc-project_runtime@0.149.0 → _@oxc-project_runtime@0.150.0}/helpers/esm/toPrimitive.js +1 -1
  30. package/dist/es2015/_virtual/{_@oxc-project_runtime@0.149.0 → _@oxc-project_runtime@0.150.0}/helpers/esm/toPropertyKey.js +1 -1
  31. package/dist/es2015/_virtual/{_@oxc-project_runtime@0.149.0 → _@oxc-project_runtime@0.150.0}/helpers/esm/typeof.js +1 -1
  32. package/dist/es2015/controls/menu.js +1 -1
  33. package/dist/es2015/element.js +47 -33
  34. package/dist/es2015/elements/spinner.js +84 -0
  35. package/dist/es2015/elements/start-button.js +6 -3
  36. package/dist/es2015/elements/title.js +151 -0
  37. package/dist/es2015/entries/spinner.js +7 -0
  38. package/dist/es2015/entries/title.js +7 -0
  39. package/dist/es2015/index.js +5 -3
  40. package/dist/es2015/presets.js +1 -1
  41. package/dist/es2015/style.js +13 -5
  42. package/dist/es2015/tags.js +3 -2
  43. package/dist/index.d.ts +6 -3
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +2 -1
  46. package/dist/index.js.map +1 -1
  47. package/dist/namespaces.d.ts +1 -1
  48. package/dist/style.d.ts +1 -1
  49. package/dist/style.d.ts.map +1 -1
  50. package/dist/style.js +13 -5
  51. package/dist/style.js.map +1 -1
  52. package/dist/tags.d.ts +2 -1
  53. package/dist/tags.d.ts.map +1 -1
  54. package/dist/tags.js +2 -1
  55. package/dist/tags.js.map +1 -1
  56. package/package.json +3 -3
  57. package/dist/compose.d.ts +0 -5
  58. package/dist/compose.d.ts.map +0 -1
  59. package/dist/compose.js +0 -31
  60. package/dist/compose.js.map +0 -1
  61. package/dist/elements/panels.d.ts +0 -15
  62. package/dist/elements/panels.d.ts.map +0 -1
  63. package/dist/elements/panels.js +0 -55
  64. package/dist/elements/panels.js.map +0 -1
  65. package/dist/entries/panels.d.ts +0 -5
  66. package/dist/entries/panels.d.ts.map +0 -1
  67. package/dist/entries/panels.js +0 -8
  68. package/dist/entries/panels.js.map +0 -1
  69. package/dist/es2015/compose.js +0 -33
  70. package/dist/es2015/elements/panels.js +0 -52
  71. package/dist/es2015/entries/panels.js +0 -7
@@ -0,0 +1,139 @@
1
+ /**
2
+ * <mbx-title>: the heading, the subheading and the artwork of what plays,
3
+ * as a lower third across the picture above the bar: a scrim that fades
4
+ * upward, the artwork in the first column, the two lines in the second,
5
+ * so a heading alone sits on a band and never floats. The content comes
6
+ * from attributes, `heading`,
7
+ * `subheading` and `artwork`, because the stream carries none of it: a page
8
+ * writes what it knows, and a Cast receiver writes what the sender said.
9
+ * With none of the three the element draws nothing.
10
+ *
11
+ * Shown while the video is paused, which includes before the first play,
12
+ * and hidden while it plays. The element carries `playing` for that rule,
13
+ * so a page changes it in CSS: `mattebox-player[started] mbx-title
14
+ * { display: none }` keeps it to the time before the first play, like the
15
+ * poster, and `mattebox-player:hover mbx-title { display: flex }` brings it
16
+ * back on hover. The height of the bar's rows, its box less the fade it
17
+ * pads itself with, goes on the host as `--mbx-bar-rows`, so the text sits
18
+ * just above the seek row while the band runs under the bar to the bottom
19
+ * edge, one ramp with the bar's own fade. The scrim is the page's to
20
+ * override. Placed first among the screens, so the start button, the
21
+ * error screen and the spinner paint over its band.
22
+ */
23
+ import { el } from '../dom.js';
24
+ import { Component } from './component.js';
25
+ import { style } from './shared.js';
26
+ const STYLE = `
27
+ :host {
28
+ position: absolute;
29
+ left: 0;
30
+ right: 0;
31
+ bottom: 0;
32
+ display: flex;
33
+ align-items: flex-end;
34
+ gap: 14px;
35
+ /* The band runs under the bar to the bottom edge, one ramp with the
36
+ bar's own fade, so there is no seam where the bar begins; the text
37
+ sits 12px above the bar's rows, inside the bar's fade. */
38
+ padding: 72px calc(var(--mbx-pad) + 8px) calc(var(--mbx-bar-rows, 0px) + 12px);
39
+ background: linear-gradient(to top, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0.3) 45%, rgba(0, 0, 0, 0));
40
+ color: var(--mbx-text);
41
+ font: 400 14px/1.35 var(--mbx-font);
42
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
43
+ pointer-events: none;
44
+ }
45
+ :host([playing]) { display: none; }
46
+ :host([empty]) { display: none; }
47
+ :host([hidden]) { display: none; }
48
+ [part~="artwork"] {
49
+ flex: none;
50
+ height: 72px;
51
+ width: auto;
52
+ max-width: 128px;
53
+ border-radius: var(--mbx-radius);
54
+ object-fit: cover;
55
+ box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.14);
56
+ }
57
+ [part~="artwork"][hidden] { display: none; }
58
+ [part~="text"] { display: flex; flex-direction: column; gap: 2px; min-width: 0; max-width: 60ch; }
59
+ [part~="heading"] {
60
+ font-size: 20px;
61
+ font-weight: 600;
62
+ letter-spacing: -0.01em;
63
+ line-height: 1.2;
64
+ white-space: nowrap;
65
+ overflow: hidden;
66
+ text-overflow: ellipsis;
67
+ }
68
+ [part~="subheading"] { color: rgba(255, 255, 255, 0.78); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
69
+ [part~="heading"]:empty, [part~="subheading"]:empty { display: none; }
70
+ `;
71
+ export class MbxTitle extends Component {
72
+ static get observedAttributes() {
73
+ return ['heading', 'subheading', 'artwork'];
74
+ }
75
+ constructor() {
76
+ super();
77
+ this.resizer = null;
78
+ const root = this.attachShadow({ mode: 'open' });
79
+ this.artwork = el('img', 'artwork');
80
+ this.artwork.alt = '';
81
+ this.artwork.hidden = true;
82
+ const text = el('div', 'text');
83
+ this.heading = el('div', 'heading');
84
+ this.subheading = el('div', 'subheading');
85
+ text.append(this.heading, this.subheading);
86
+ root.append(style(STYLE), this.artwork, text);
87
+ }
88
+ attach(player) {
89
+ this.listen(player.video, ['play', 'pause', 'ended', 'emptied'], () => {
90
+ this.state(player);
91
+ });
92
+ if (typeof ResizeObserver !== 'undefined') {
93
+ this.resizer = new ResizeObserver(() => {
94
+ this.fit(player);
95
+ });
96
+ this.resizer.observe(player);
97
+ }
98
+ this.fit(player);
99
+ this.state(player);
100
+ this.render();
101
+ }
102
+ detach() {
103
+ this.resizer?.disconnect();
104
+ this.resizer = null;
105
+ this.removeAttribute('playing');
106
+ this.style.removeProperty('--mbx-bar-rows');
107
+ }
108
+ /** `playing` on the element, for its own stylesheet and the page's. */
109
+ state(player) {
110
+ this.toggleAttribute('playing', !player.video.paused);
111
+ }
112
+ /** The height of the bar's rows: its box less the padding above them, which is its fade. Zero without a bar. */
113
+ fit(player) {
114
+ const bar = player.querySelector('mbx-control-bar');
115
+ let rows = 0;
116
+ if (bar !== null) {
117
+ const top = Number.parseFloat(getComputedStyle(bar).paddingTop) || 0;
118
+ rows = Math.max(0, bar.getBoundingClientRect().height - top);
119
+ }
120
+ this.style.setProperty('--mbx-bar-rows', `${rows}px`);
121
+ }
122
+ render() {
123
+ const heading = this.getAttribute('heading') ?? '';
124
+ const subheading = this.getAttribute('subheading') ?? '';
125
+ const artwork = this.getAttribute('artwork');
126
+ this.heading.textContent = heading;
127
+ this.subheading.textContent = subheading;
128
+ if (artwork === null) {
129
+ this.artwork.removeAttribute('src');
130
+ this.artwork.hidden = true;
131
+ }
132
+ else {
133
+ this.artwork.src = artwork;
134
+ this.artwork.hidden = false;
135
+ }
136
+ this.toggleAttribute('empty', heading === '' && subheading === '' && artwork === null);
137
+ }
138
+ }
139
+ //# sourceMappingURL=title.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"title.js","sourceRoot":"","sources":["../../src/elements/title.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /** `@mattebox/player/elements/spinner`: registers <mbx-spinner>, and the player with it. */
2
+ import '../element-entry.js';
3
+ import { MbxSpinner } from '../elements/spinner.js';
4
+ export { MbxSpinner };
5
+ //# sourceMappingURL=spinner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/entries/spinner.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,OAAO,qBAAqB,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAOpD,OAAO,EAAE,UAAU,EAAE,CAAC"}
@@ -0,0 +1,9 @@
1
+ /** `@mattebox/player/elements/spinner`: registers <mbx-spinner>, and the player with it. */
2
+ import '../element-entry.js';
3
+ import { MbxSpinner } from '../elements/spinner.js';
4
+ import { SPINNER } from '../tags.js';
5
+ if (customElements.get(SPINNER) === undefined) {
6
+ customElements.define(SPINNER, MbxSpinner);
7
+ }
8
+ export { MbxSpinner };
9
+ //# sourceMappingURL=spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/entries/spinner.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,OAAO,qBAAqB,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,IAAI,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,SAAS,EAAE,CAAC;IAC9C,cAAc,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC7C,CAAC;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
@@ -0,0 +1,5 @@
1
+ /** `@mattebox/player/elements/title`: registers <mbx-title>, and the player with it. */
2
+ import '../element-entry.js';
3
+ import { MbxTitle } from '../elements/title.js';
4
+ export { MbxTitle };
5
+ //# sourceMappingURL=title.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"title.d.ts","sourceRoot":"","sources":["../../src/entries/title.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,OAAO,qBAAqB,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAOhD,OAAO,EAAE,QAAQ,EAAE,CAAC"}
@@ -0,0 +1,9 @@
1
+ /** `@mattebox/player/elements/title`: registers <mbx-title>, and the player with it. */
2
+ import '../element-entry.js';
3
+ import { MbxTitle } from '../elements/title.js';
4
+ import { TITLE } from '../tags.js';
5
+ if (customElements.get(TITLE) === undefined) {
6
+ customElements.define(TITLE, MbxTitle);
7
+ }
8
+ export { MbxTitle };
9
+ //# sourceMappingURL=title.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"title.js","sourceRoot":"","sources":["../../src/entries/title.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,OAAO,qBAAqB,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,IAAI,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,SAAS,EAAE,CAAC;IAC5C,cAAc,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;AACzC,CAAC;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
@@ -1,4 +1,4 @@
1
- //#region \0@oxc-project+runtime@0.149.0/helpers/esm/asyncToGenerator.js
1
+ //#region \0@oxc-project+runtime@0.150.0/helpers/esm/asyncToGenerator.js
2
2
  function asyncGeneratorStep(n, t, e, r, o, a, c) {
3
3
  try {
4
4
  var i = n[a](c), u = i.value;
@@ -1,5 +1,5 @@
1
1
  import toPropertyKey from "./toPropertyKey.js";
2
- //#region \0@oxc-project+runtime@0.149.0/helpers/esm/defineProperty.js
2
+ //#region \0@oxc-project+runtime@0.150.0/helpers/esm/defineProperty.js
3
3
  function _defineProperty(e, r, t) {
4
4
  return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
5
5
  value: t,
@@ -1,5 +1,5 @@
1
1
  import _defineProperty from "./defineProperty.js";
2
- //#region \0@oxc-project+runtime@0.149.0/helpers/esm/objectSpread2.js
2
+ //#region \0@oxc-project+runtime@0.150.0/helpers/esm/objectSpread2.js
3
3
  function ownKeys(e, r) {
4
4
  var t = Object.keys(e);
5
5
  if (Object.getOwnPropertySymbols) {
@@ -1,5 +1,5 @@
1
1
  import _typeof from "./typeof.js";
2
- //#region \0@oxc-project+runtime@0.149.0/helpers/esm/toPrimitive.js
2
+ //#region \0@oxc-project+runtime@0.150.0/helpers/esm/toPrimitive.js
3
3
  function toPrimitive(t, r) {
4
4
  if ("object" != _typeof(t) || !t) return t;
5
5
  var e = t[Symbol.toPrimitive];
@@ -1,6 +1,6 @@
1
1
  import _typeof from "./typeof.js";
2
2
  import toPrimitive from "./toPrimitive.js";
3
- //#region \0@oxc-project+runtime@0.149.0/helpers/esm/toPropertyKey.js
3
+ //#region \0@oxc-project+runtime@0.150.0/helpers/esm/toPropertyKey.js
4
4
  function toPropertyKey(t) {
5
5
  var i = toPrimitive(t, "string");
6
6
  return "symbol" == _typeof(i) ? i : i + "";
@@ -1,4 +1,4 @@
1
- //#region \0@oxc-project+runtime@0.149.0/helpers/esm/typeof.js
1
+ //#region \0@oxc-project+runtime@0.150.0/helpers/esm/typeof.js
2
2
  function _typeof(o) {
3
3
  "@babel/helpers - typeof";
4
4
  return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
@@ -1,5 +1,5 @@
1
1
  import { el, state } from "../dom.js";
2
- import _objectSpread2 from "../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/objectSpread2.js";
2
+ import _objectSpread2 from "../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/objectSpread2.js";
3
3
  //#region src/controls/menu.ts
4
4
  /**
5
5
  * The menu primitive the quality, audio, subtitles and speed menus share: a
@@ -1,11 +1,10 @@
1
- import { CONTROL_BAR, PANELS, PLAYER } from "./tags.js";
2
- import { composeBar, composePanels } from "./compose.js";
3
1
  import { namespaces } from "./namespaces.js";
4
- import _asyncToGenerator from "./_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/asyncToGenerator.js";
2
+ import _asyncToGenerator from "./_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/asyncToGenerator.js";
5
3
  import { drmGuard, resolvePreset } from "./presets.js";
6
4
  import { STYLE } from "./style.js";
7
5
  import { errorSurface } from "./surface.js";
8
- import _objectSpread2 from "./_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/objectSpread2.js";
6
+ import { PLAYER } from "./tags.js";
7
+ import _objectSpread2 from "./_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/objectSpread2.js";
9
8
  import { createPlayer, inferType, matteboxHandler, nativeHandler } from "@mattebox/player-core";
10
9
  //#region src/element.ts
11
10
  /** Attributes forwarded onto the video as attributes, never as properties. */
@@ -33,11 +32,19 @@ const OWN = [
33
32
  const CHAPTERS = "chapters";
34
33
  /**
35
34
  * The one attribute whose meaning the element owns: `native` keeps the
36
- * browser's controls on the video, `custom` swaps them for the bar, `none`
37
- * leaves the video bare for a page that draws its own. Anything else is
38
- * `native`. Changing it swaps the bar without touching the session.
35
+ * browser's controls on the video, `custom` swaps them for the controls the
36
+ * page placed inside, `none` takes the browser's off and hides every child
37
+ * but the video. Anything else is `native`. Changing it never touches the
38
+ * session.
39
39
  */
40
40
  const CONTROLS = "controls";
41
+ /**
42
+ * Inline playback, on until the page writes `playsinline="false"`, the way
43
+ * `spellcheck` and `draggable` are on until told otherwise. An iPhone takes
44
+ * a video without `playsinline` to its own fullscreen on play, where no
45
+ * control the page placed shows. Changing it never reloads.
46
+ */
47
+ const PLAYSINLINE = "playsinline";
41
48
  /** The video's state, as attributes on the element, read on the events the video fires for it. */
42
49
  const STATE_EVENTS = [
43
50
  "play",
@@ -46,7 +53,11 @@ const STATE_EVENTS = [
46
53
  "emptied",
47
54
  "volumechange",
48
55
  "loadedmetadata",
49
- "resize"
56
+ "resize",
57
+ "playing",
58
+ "waiting",
59
+ "stalled",
60
+ "canplay"
50
61
  ];
51
62
  /** Every stage the engine ships. A narrower preset is optimization. */
52
63
  const DEFAULT_PRESET = "full";
@@ -68,7 +79,8 @@ var MatteboxPlayerElement = class MatteboxPlayerElement extends HTMLElement {
68
79
  ...FORWARDED,
69
80
  ...OWN,
70
81
  CONTROLS,
71
- CHAPTERS
82
+ CHAPTERS,
83
+ PLAYSINLINE
72
84
  ];
73
85
  }
74
86
  /**
@@ -84,20 +96,22 @@ var MatteboxPlayerElement = class MatteboxPlayerElement extends HTMLElement {
84
96
  constructor(options) {
85
97
  super();
86
98
  this.options = options !== null && options !== void 0 ? options : defaults;
87
- this.composed = [];
88
- this.settled = false;
89
99
  this.focusable = false;
90
100
  this.track = null;
91
101
  this.core = null;
92
102
  this.current = null;
93
103
  this.failure = null;
94
104
  this.reflecting = false;
105
+ this.started = false;
106
+ this.waiting = false;
95
107
  this.offs = [];
96
108
  this.queue = Promise.resolve();
97
109
  this.pending = false;
98
110
  this.media = document.createElement("video");
99
111
  this.media.controls = true;
112
+ this.media.setAttribute(PLAYSINLINE, "");
100
113
  for (const name of STATE_EVENTS) this.media.addEventListener(name, () => {
114
+ this.note(name);
101
115
  this.reflect();
102
116
  });
103
117
  this.media.addEventListener("playing", () => {
@@ -130,8 +144,8 @@ var MatteboxPlayerElement = class MatteboxPlayerElement extends HTMLElement {
130
144
  /**
131
145
  * The fatal error of the current load, or null once a load starts or
132
146
  * playback resumes. The `error` event says when; this says what, for a
133
- * control that attaches after the event, such as the default composition
134
- * behind a source that fails while the page is still parsing.
147
+ * control that attaches after the event, such as an error screen parsed
148
+ * after a source that failed while the page was still loading.
135
149
  */
136
150
  get error() {
137
151
  return this.failure;
@@ -140,17 +154,19 @@ var MatteboxPlayerElement = class MatteboxPlayerElement extends HTMLElement {
140
154
  if (this.media.parentNode !== this) this.append(this.media);
141
155
  for (const name of FORWARDED) this.forward(name);
142
156
  this.reflect();
143
- if (!this.settled) this.settle();
144
157
  this.reload();
145
158
  }
146
- /** Decides on the default composition once the children are all in, then on every mode change. */
147
- settle() {
148
- const done = () => {
149
- this.settled = true;
150
- this.mode();
151
- };
152
- if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", done, { once: true });
153
- else queueMicrotask(done);
159
+ /** The two states the video does not hold: whether it has played once, and whether it waits for data. */
160
+ note(event) {
161
+ if (event === "playing") {
162
+ this.started = true;
163
+ this.waiting = false;
164
+ } else if (event === "waiting" || event === "stalled") this.waiting = true;
165
+ else if (event === "canplay") this.waiting = false;
166
+ else if (event === "emptied") {
167
+ this.started = false;
168
+ this.waiting = false;
169
+ }
154
170
  }
155
171
  /** The video's state on the element, for `mattebox-player[paused]` and the like. */
156
172
  reflect() {
@@ -161,6 +177,8 @@ var MatteboxPlayerElement = class MatteboxPlayerElement extends HTMLElement {
161
177
  this.toggleAttribute("ended", video.ended);
162
178
  this.toggleAttribute("muted", video.muted);
163
179
  this.toggleAttribute("audio", this.audio());
180
+ this.toggleAttribute("started", this.started);
181
+ this.toggleAttribute("waiting", this.waiting);
164
182
  this.reflecting = false;
165
183
  }
166
184
  /**
@@ -194,14 +212,18 @@ var MatteboxPlayerElement = class MatteboxPlayerElement extends HTMLElement {
194
212
  this.chapters();
195
213
  return;
196
214
  }
215
+ if (name === PLAYSINLINE) {
216
+ this.media.toggleAttribute(PLAYSINLINE, this.getAttribute(PLAYSINLINE) !== "false");
217
+ return;
218
+ }
197
219
  if (name === "preset") this.enqueue(() => this.discard());
198
220
  if (name === "src" || name === "type") this.toggleAttribute("audio", this.audio());
199
221
  this.reload();
200
222
  }
201
223
  /**
202
- * Applies the `controls` attribute: the video's own controls, the
203
- * tabindex, and the default composition for the mode where the page
204
- * wrote none. The controls themselves are elements and attach on their own.
224
+ * Applies the `controls` attribute: the video's own controls and the
225
+ * tabindex. The controls themselves are elements the page placed, and
226
+ * they attach on their own; the element appends none.
205
227
  */
206
228
  mode() {
207
229
  const value = this.getAttribute(CONTROLS);
@@ -215,14 +237,6 @@ var MatteboxPlayerElement = class MatteboxPlayerElement extends HTMLElement {
215
237
  this.tabIndex = 0;
216
238
  this.focusable = true;
217
239
  }
218
- if (!this.settled) return;
219
- for (const node of this.composed) node.remove();
220
- this.composed = [];
221
- const own = custom ? CONTROL_BAR : PANELS;
222
- if (this.querySelector(`:scope > ${own}`) === null) {
223
- this.composed = custom ? composeBar() : composePanels();
224
- this.append(...this.composed);
225
- }
226
240
  }
227
241
  /** Keeps a hidden chapters track on the video for the `chapters` attribute, or none. */
228
242
  chapters() {
@@ -0,0 +1,84 @@
1
+ import { Component } from "./component.js";
2
+ import { style } from "./shared.js";
3
+ //#region src/elements/spinner.ts
4
+ const STYLE = `
5
+ :host {
6
+ position: absolute;
7
+ top: 50%;
8
+ left: 50%;
9
+ width: 44px;
10
+ height: 44px;
11
+ margin: -22px 0 0 -22px;
12
+ display: none;
13
+ pointer-events: none;
14
+ color: var(--mbx-text);
15
+ filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.5));
16
+ }
17
+ :host([waiting]) { display: block; }
18
+ :host([hidden]) { display: none; }
19
+ [part~="ring"] {
20
+ box-sizing: border-box;
21
+ width: 100%;
22
+ height: 100%;
23
+ border: 3px solid rgba(255, 255, 255, 0.22);
24
+ border-top-color: currentColor;
25
+ border-radius: 50%;
26
+ animation: mbx-turn 0.8s linear infinite;
27
+ }
28
+ [part~="ring"][hidden] { display: none; }
29
+ slot[hidden] { display: none; }
30
+ ::slotted(*) { width: 100%; height: 100%; }
31
+ @keyframes mbx-turn { to { transform: rotate(360deg); } }
32
+ @media (prefers-reduced-motion: reduce) {
33
+ [part~="ring"] { animation: none; }
34
+ }
35
+ `;
36
+ /** What the video fires as it waits and as it goes on. */
37
+ const EVENTS = [
38
+ "waiting",
39
+ "stalled",
40
+ "playing",
41
+ "canplay",
42
+ "emptied"
43
+ ];
44
+ var MbxSpinner = class extends Component {
45
+ static get observedAttributes() {
46
+ return ["label"];
47
+ }
48
+ constructor() {
49
+ super();
50
+ const root = this.attachShadow({ mode: "open" });
51
+ this.ring = document.createElement("div");
52
+ this.ring.setAttribute("part", "ring");
53
+ this.slot_ = document.createElement("slot");
54
+ this.slot_.name = "icon";
55
+ this.slot_.addEventListener("slotchange", () => {
56
+ this.ring.hidden = this.slot_.assignedNodes().length > 0;
57
+ });
58
+ root.append(style(STYLE), this.ring, this.slot_);
59
+ }
60
+ /** Named before attaching: a constructor must not add attributes. */
61
+ connectedCallback() {
62
+ if (!this.hasAttribute("role")) this.setAttribute("role", "status");
63
+ super.connectedCallback();
64
+ }
65
+ attach(player) {
66
+ const video = player.video;
67
+ this.listen(video, EVENTS, () => {
68
+ this.render();
69
+ });
70
+ this.render();
71
+ }
72
+ detach() {
73
+ this.removeAttribute("waiting");
74
+ }
75
+ render() {
76
+ var _this$getAttribute;
77
+ const player = this.player;
78
+ if (player === null) return;
79
+ this.setAttribute("aria-label", (_this$getAttribute = this.getAttribute("label")) !== null && _this$getAttribute !== void 0 ? _this$getAttribute : "Loading");
80
+ this.toggleAttribute("waiting", player.hasAttribute("waiting"));
81
+ }
82
+ };
83
+ //#endregion
84
+ export { MbxSpinner };
@@ -52,7 +52,10 @@ var MbxStartButton = class extends Component {
52
52
  this.listen(video, [
53
53
  "play",
54
54
  "pause",
55
- "ended"
55
+ "ended",
56
+ "waiting",
57
+ "stalled",
58
+ "canplay"
56
59
  ], () => {
57
60
  this.render();
58
61
  });
@@ -111,13 +114,13 @@ var MbxStartButton = class extends Component {
111
114
  if (cramped !== wasCramped) this.render();
112
115
  }
113
116
  render() {
114
- var _this$player2, _this$getAttribute;
117
+ var _this$player2, _this$getAttribute, _this$player3;
115
118
  const video = (_this$player2 = this.player) === null || _this$player2 === void 0 ? void 0 : _this$player2.video;
116
119
  if (video === void 0) return;
117
120
  const state = video.ended ? "replay" : "play";
118
121
  show(this.slots, state);
119
122
  this.button.setAttribute("aria-label", (_this$getAttribute = this.getAttribute(`label-${state}`)) !== null && _this$getAttribute !== void 0 ? _this$getAttribute : state === "play" ? "Play" : "Replay");
120
- this.hidden = this.failed || !video.paused;
123
+ this.hidden = this.failed || !video.paused || ((_this$player3 = this.player) === null || _this$player3 === void 0 ? void 0 : _this$player3.hasAttribute("waiting")) === true;
121
124
  }
122
125
  };
123
126
  //#endregion