@f8team/reel-core 1.0.5 → 1.1.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,40 @@
1
1
  # @f8team/reel-core
2
2
 
3
+ ## 1.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - e6d5243: Stop a replaced source from loading anyway.
8
+
9
+ The YouTube and HLS loaders cleared their `aborted` flag in `detach()`, so a source switch
10
+ (abort, then detach) let an attach that was still waiting for the YouTube or hls.js runtime carry
11
+ on: YouTube mounted a second iframe that stayed in the page, and HLS bound a stale hls.js instance
12
+ to the `<video>`. Each attach now remembers which abort/detach generation it started in and stops
13
+ when a newer one has happened.
14
+
15
+ `<Root>` (React) and `<reel-player>` (Lit) no longer call `setSource` again for the source the
16
+ player was created with in `options.source`. That second call aborted the first load on mount
17
+ (an extra media request) and was how the duplicate YouTube iframe was reached.
18
+
19
+ ## 1.1.0
20
+
21
+ ### Minor Changes
22
+
23
+ - fe0431b: Fix controls that never auto-hide in fullscreen.
24
+
25
+ Entering fullscreen is only possible by hitting the fullscreen control, and the
26
+ pointer focus it leaves behind kept `:focus-within` matching forever, so the
27
+ themes held the controls bar and the mobile transport at full opacity for the
28
+ rest of the session. Reported on Android Chrome and Safari.
29
+
30
+ The idle timer now releases that pointer focus instead of only dropping
31
+ `data-reel-controls-visible`. Keyboard focus and open control menus still keep
32
+ the chrome on screen - the timer re-arms rather than hiding.
33
+
34
+ `@f8team/reel-core` gains `blurFocusInside` and `shouldKeepControlsVisible` so
35
+ the Lit element, the React adapter and app-level players share one auto-hide
36
+ focus contract; `@f8team/reel-react` re-exports both.
37
+
3
38
  ## 1.0.5
4
39
 
5
40
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -400,6 +400,12 @@ var HlsLoader = class {
400
400
  this.rejectAttach = null;
401
401
  this.manifestTimeout = null;
402
402
  this.aborted = false;
403
+ /**
404
+ * Bumped by every abort/detach. `detach()` clears `aborted` so the loader can be reused, so a
405
+ * source switch (abort, then detach) used to let an attach that was still awaiting the runtime
406
+ * carry on and bind a stale hls.js instance to the <video>. Each attach keeps its own value.
407
+ */
408
+ this.generation = 0;
403
409
  this.lastLoadingFragmentKey = null;
404
410
  this.repeatedFragmentLoadCount = 0;
405
411
  this.repeatedFragmentErrorFired = false;
@@ -418,11 +424,12 @@ var HlsLoader = class {
418
424
  async attach(video, source) {
419
425
  this.detach();
420
426
  this.aborted = false;
427
+ const generation = this.generation;
421
428
  this.video = video;
422
429
  this.currentSource = source;
423
430
  this.unauthorizedFired = false;
424
431
  const Hls = await (this.options.loadRuntime ?? defaultLoad)();
425
- if (this.aborted) {
432
+ if (this.aborted || generation !== this.generation) {
426
433
  throw makeAbortError();
427
434
  }
428
435
  if (!Hls.isSupported()) {
@@ -733,6 +740,7 @@ var HlsLoader = class {
733
740
  this.abortLiveXhrs();
734
741
  }
735
742
  abort() {
743
+ this.generation += 1;
736
744
  if (this.aborted) return;
737
745
  this.aborted = true;
738
746
  this.clearManifestTimeout();
@@ -1066,17 +1074,24 @@ var YouTubeLoader = class {
1066
1074
  this.duration = 0;
1067
1075
  this.rejectAttach = null;
1068
1076
  this.aborted = false;
1077
+ /**
1078
+ * Bumped by every abort/detach. `detach()` clears `aborted` so the loader can be reused, so a
1079
+ * source switch (abort, then detach) used to let an attach that was still awaiting the runtime
1080
+ * carry on and mount a second iframe. Each attach keeps the value it started with instead.
1081
+ */
1082
+ this.generation = 0;
1069
1083
  }
1070
1084
  async attach(video, source) {
1071
1085
  this.detach();
1072
1086
  this.aborted = false;
1087
+ const generation = this.generation;
1073
1088
  const id = extractYouTubeId(source.src);
1074
1089
  if (!id) {
1075
1090
  throw new Error(`Cannot extract YouTube videoId from "${source.src}"`);
1076
1091
  }
1077
1092
  this.video = video;
1078
1093
  const YT = await (this.options.loadRuntime ?? defaultLoad2)();
1079
- if (this.aborted) {
1094
+ if (this.aborted || generation !== this.generation) {
1080
1095
  throw makeYtAbortError();
1081
1096
  }
1082
1097
  const parent = video.parentElement;
@@ -1172,6 +1187,7 @@ var YouTubeLoader = class {
1172
1187
  });
1173
1188
  }
1174
1189
  abort() {
1190
+ this.generation += 1;
1175
1191
  if (this.aborted) return;
1176
1192
  this.aborted = true;
1177
1193
  const reject = this.rejectAttach;
@@ -2394,6 +2410,27 @@ function createFocusTrap(container) {
2394
2410
  return { activate, deactivate };
2395
2411
  }
2396
2412
 
2413
+ // src/a11y/controlsFocus.ts
2414
+ var OPEN_MENU_SELECTOR = "[data-reel-menu-open]";
2415
+ function activeElementInside(container) {
2416
+ const active = (container.ownerDocument ?? document).activeElement;
2417
+ if (!(active instanceof HTMLElement)) return null;
2418
+ return container.contains(active) ? active : null;
2419
+ }
2420
+ function blurFocusInside(container) {
2421
+ activeElementInside(container)?.blur();
2422
+ }
2423
+ function shouldKeepControlsVisible(container) {
2424
+ if (container.querySelector(OPEN_MENU_SELECTOR) !== null) return true;
2425
+ const active = activeElementInside(container);
2426
+ if (!active) return false;
2427
+ try {
2428
+ return active.matches(":focus-visible");
2429
+ } catch {
2430
+ return false;
2431
+ }
2432
+ }
2433
+
2397
2434
  // src/util/time.ts
2398
2435
  var TIME_RE = /^(?:(\d+):)?(\d{1,2}):(\d{1,2})(?:\.(\d+))?$/;
2399
2436
  function parseTime(input) {
@@ -2433,6 +2470,7 @@ exports.TOKEN_TO_CSS_VAR = TOKEN_TO_CSS_VAR;
2433
2470
  exports.announce = announce;
2434
2471
  exports.applyTheme = applyTheme;
2435
2472
  exports.areSourceDescriptorsEquivalent = areSourceDescriptorsEquivalent;
2473
+ exports.blurFocusInside = blurFocusInside;
2436
2474
  exports.createFocusTrap = createFocusTrap;
2437
2475
  exports.createPlayer = createPlayer;
2438
2476
  exports.definePlugin = definePlugin;
@@ -2444,6 +2482,7 @@ exports.looksLikeProgressive = looksLikeProgressive;
2444
2482
  exports.looksLikeYouTube = looksLikeYouTube;
2445
2483
  exports.parseTime = parseTime;
2446
2484
  exports.resolveTokens = resolveTokens;
2485
+ exports.shouldKeepControlsVisible = shouldKeepControlsVisible;
2447
2486
  exports.toSeconds = toSeconds;
2448
2487
  //# sourceMappingURL=index.cjs.map
2449
2488
  //# sourceMappingURL=index.cjs.map