@fusion.dev/helix-headless 0.59.0 → 0.59.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.
@@ -107645,7 +107645,8 @@
107645
107645
  "type": {
107646
107646
  "text": "Promise<void>"
107647
107647
  }
107648
- }
107648
+ },
107649
+ "description": "Into picture in picture and back, and quiet about being refused.\n\nCaught rather than `void`ed, the way `FullscreenController` catches its\nown: this is called from a click handler that discards the promise, so a\nrefusal is otherwise an unhandled rejection naming neither the element nor\nthe reason. The roster already declines to draw the button where the\nconsumer refused the feature, which leaves the refusals nothing can see\ncoming, a request without user activation and a window another document is\nalready using."
107649
107650
  },
107650
107651
  {
107651
107652
  "kind": "field",
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  var HelixHeadlessObjectInspector_1;
8
- import { CopyController, customElement, HelixElement, inlineStep, scrollItemIntoView, VirtualizeController, } from '@fusion.dev/helix-core';
8
+ import { CopyController, customElement, elementById, HelixElement, inlineStep, scrollItemIntoView, searchableById, VirtualizeController, } from '@fusion.dev/helix-core';
9
9
  import { caretDown, caretRight } from '@fusion.dev/helix-icons';
10
10
  import { html, nothing } from 'lit';
11
11
  import { property, state } from 'lit/decorators.js';
@@ -146,9 +146,7 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
146
146
  }
147
147
  willUpdate(changed) {
148
148
  super.willUpdate(changed);
149
- if (this.loadedFor !== this.for &&
150
- typeof this.ownerDocument?.getElementById === 'function' &&
151
- !this.hydrating) {
149
+ if (this.loadedFor !== this.for && searchableById(this) && !this.hydrating) {
152
150
  this.loadedFor = this.for;
153
151
  this.load();
154
152
  }
@@ -178,7 +176,7 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
178
176
  }
179
177
  }
180
178
  load() {
181
- const text = this.for === '' ? '' : (this.ownerDocument.getElementById(this.for)?.textContent ?? '');
179
+ const text = this.for === '' ? '' : (elementById(this, this.for)?.textContent ?? '');
182
180
  try {
183
181
  this.read = text.trim() === '' ? undefined : JSON.parse(text);
184
182
  }
@@ -13,6 +13,8 @@ export interface Conditions {
13
13
  hydrating: boolean;
14
14
  /** Whether anything on the network has offered to play this. */
15
15
  remote: boolean;
16
+ /** Whether the consumer has refused picture in picture on the element. */
17
+ refusedPip: boolean;
16
18
  /** Whether a file is named, which is what a download needs. */
17
19
  source: boolean;
18
20
  }
@@ -1,7 +1,10 @@
1
1
  import { writtenList } from '@fusion.dev/helix-core';
2
2
  export const offers = (one, player) => {
3
3
  if (one === 'pip') {
4
- return !player.hydrating && typeof document !== 'undefined' && document.pictureInPictureEnabled;
4
+ return (!player.hydrating &&
5
+ !player.refusedPip &&
6
+ typeof document !== 'undefined' &&
7
+ document.pictureInPictureEnabled);
5
8
  }
6
9
  if (one === 'remote') {
7
10
  return player.remote;
@@ -510,6 +510,17 @@ export declare class HelixHeadlessVideo extends HelixElement {
510
510
  private skip;
511
511
  /** Steps through the speeds offered, which is what one button can do. */
512
512
  private cycleSpeed;
513
+ /**
514
+ * Into picture in picture and back, and quiet about being refused.
515
+ *
516
+ * Caught rather than `void`ed, the way `FullscreenController` catches its
517
+ * own: this is called from a click handler that discards the promise, so a
518
+ * refusal is otherwise an unhandled rejection naming neither the element nor
519
+ * the reason. The roster already declines to draw the button where the
520
+ * consumer refused the feature, which leaves the refusals nothing can see
521
+ * coming, a request without user activation and a window another document is
522
+ * already using.
523
+ */
513
524
  private togglePip;
514
525
  /**
515
526
  * A press on the picture plays or pauses it.
@@ -174,7 +174,12 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
174
174
  this.captions = [];
175
175
  }
176
176
  get conditions() {
177
- return { hydrating: this.hydrating, remote: this.remoteAvailable, source: this.src !== '' };
177
+ return {
178
+ hydrating: this.hydrating,
179
+ refusedPip: this.disablePictureInPicture,
180
+ remote: this.remoteAvailable,
181
+ source: this.src !== '',
182
+ };
178
183
  }
179
184
  get extras() {
180
185
  return barControls(this.extraControls, this.conditions);
@@ -347,11 +352,16 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
347
352
  if (!video) {
348
353
  return;
349
354
  }
350
- if (document.pictureInPictureElement === video) {
351
- await document.exitPictureInPicture();
352
- return;
355
+ try {
356
+ if (document.pictureInPictureElement === video) {
357
+ await document.exitPictureInPicture();
358
+ return;
359
+ }
360
+ await video.requestPictureInPicture();
361
+ }
362
+ catch (error) {
363
+ console.warn(`<${this.localName}> could not enter picture in picture. A press has to come from the reader, and one window holds it at a time.`, error);
353
364
  }
354
- await video.requestPictureInPicture();
355
365
  }
356
366
  willUpdate(changed) {
357
367
  super.willUpdate(changed);
@@ -83,9 +83,15 @@ export declare class HelixHeadlessVirtualList extends HelixElement {
83
83
  /**
84
84
  * Reads the source named by `for`, before the render that draws it.
85
85
  *
86
+ * **Resolved through `getRootNode()`, so a list inside another component's
87
+ * shadow root names a source in that root rather than in the page.** Read
88
+ * against `ownerDocument` it looked in the document whatever tree it was in,
89
+ * and found nothing from inside an app shell or a sandbox, which is
90
+ * indistinguishable here from the miss this tolerates on purpose.
91
+ *
86
92
  * Not on the server, per the server rules: the shim has attributes and no
87
- * tree, so `getElementById` is undefined there. Nor while hydrating what a
88
- * server sent, which it drew with nothing read. A source that is missing or
93
+ * tree to look an id up in. Nor while hydrating what a server sent, which it
94
+ * drew with nothing read. A source that is missing or
89
95
  * not an array leaves the list empty rather than throwing, because a consumer
90
96
  * whose data has not arrived yet is the ordinary case and an empty list says
91
97
  * so by itself.
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { customElement, HelixElement, VirtualizeController } from '@fusion.dev/helix-core';
7
+ import { customElement, elementById, HelixElement, searchableById, VirtualizeController, } from '@fusion.dev/helix-core';
8
8
  import { html } from 'lit';
9
9
  import { property, state } from 'lit/decorators.js';
10
10
  let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixElement {
@@ -31,9 +31,7 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
31
31
  }
32
32
  willUpdate(changed) {
33
33
  super.willUpdate(changed);
34
- if (this.readFor !== this.for &&
35
- typeof this.ownerDocument?.getElementById === 'function' &&
36
- !this.hydrating) {
34
+ if (this.readFor !== this.for && searchableById(this) && !this.hydrating) {
37
35
  this.readFor = this.for;
38
36
  this.read();
39
37
  }
@@ -48,7 +46,7 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
48
46
  this.place();
49
47
  }
50
48
  read() {
51
- const source = this.for === '' ? null : this.ownerDocument.getElementById(this.for);
49
+ const source = this.for === '' ? null : elementById(this, this.for);
52
50
  const text = source?.textContent ?? '';
53
51
  if (text.trim() === '') {
54
52
  this.rows = [];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fusion.dev/helix-headless",
3
3
  "description": "Headless component tier. Structure, accessibility, state, and form participation. No styling.",
4
- "version": "0.59.0",
4
+ "version": "0.59.1",
5
5
  "license": "MIT",
6
6
  "author": "Ross Sheppard <ross.sheppard@fusion.dev>",
7
7
  "repository": {
@@ -46,14 +46,14 @@
46
46
  },
47
47
  "bugs": "https://github.com/project-fusion/fusion/issues",
48
48
  "dependencies": {
49
- "@fusion.dev/helix-core": "0.59.0",
50
- "@fusion.dev/helix-icons": "0.59.0",
49
+ "@fusion.dev/helix-core": "0.59.1",
50
+ "@fusion.dev/helix-icons": "0.59.1",
51
51
  "uqr": "^0.1.3"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@custom-elements-manifest/analyzer": "^0.11.0",
55
- "@fusion.dev/helix-cem": "0.59.0",
56
- "@fusion.dev/helix-testing": "0.59.0",
55
+ "@fusion.dev/helix-cem": "0.59.1",
56
+ "@fusion.dev/helix-testing": "0.59.1",
57
57
  "@fusion.dev/scripts": "0.0.0-dev",
58
58
  "@happy-dom/global-registrator": "^20.0.0",
59
59
  "@lit-labs/ssr": "^4.1.0",