@wcstack/picture-in-picture 1.20.0 → 1.21.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/README.ja.md +31 -11
- package/README.md +31 -11
- package/dist/index.d.ts +60 -10
- package/dist/index.esm.js +103 -4
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js +1 -1
- package/dist/index.esm.min.js.map +1 -1
- package/package.json +1 -1
package/README.ja.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
`@wcstack/state` と組み合わせると、`<wcs-pip>` はパス契約で直接バインドできます:
|
|
9
9
|
|
|
10
10
|
- **入力サーフェス**: `target` — どの `<video>` 要素を操作するか
|
|
11
|
-
- **出力 state サーフェス**: `active`、`error`
|
|
11
|
+
- **出力 state サーフェス**: `active`、`error`、`errorInfo`
|
|
12
12
|
- **コマンドサーフェス**: `requestPictureInPicture()`、`exitPictureInPicture()`
|
|
13
13
|
|
|
14
14
|
これにより、`document.pictureInPictureElement` を手動でポーリングしたりレイアウトを気にしたりせずに、「ポップアウト」ボタンを HTML 上で宣言的に表現できます。
|
|
@@ -89,7 +89,7 @@ npm install @wcstack/picture-in-picture
|
|
|
89
89
|
|
|
90
90
|
### 3. 失敗を報告する(gesture 制約による reject 等)
|
|
91
91
|
|
|
92
|
-
`error`
|
|
92
|
+
`error` と `errorInfo` は観測可能な出力です(どちらも専用イベントを発火します — 下記「出力 state」参照)。そのため `active` と同様にバインドでき、あるいはコマンドの promise が解決した後に命令的に読むこともできます:
|
|
93
93
|
|
|
94
94
|
```html
|
|
95
95
|
<wcs-state>
|
|
@@ -97,19 +97,23 @@ npm install @wcstack/picture-in-picture
|
|
|
97
97
|
export default {
|
|
98
98
|
$commandTokens: ["popOut"],
|
|
99
99
|
pipActive: false,
|
|
100
|
+
pipError: null,
|
|
100
101
|
};
|
|
101
102
|
</script>
|
|
102
103
|
</wcs-state>
|
|
103
104
|
|
|
104
|
-
<wcs-pip target="#player" data-wcs="active: pipActive; command.requestPictureInPicture: $command.popOut"></wcs-pip>
|
|
105
|
+
<wcs-pip target="#player" data-wcs="active: pipActive; error: pipError; command.requestPictureInPicture: $command.popOut"></wcs-pip>
|
|
105
106
|
<button data-wcs="onclick: $command.popOut">ポップアウト</button>
|
|
106
107
|
```
|
|
107
108
|
|
|
109
|
+
あるいは命令的に、安定した失敗 taxonomy として `errorInfo` を読みます:
|
|
110
|
+
|
|
108
111
|
```js
|
|
109
112
|
const pip = document.querySelector("wcs-pip");
|
|
110
113
|
await pip.requestPictureInPicture();
|
|
111
114
|
if (pip.error) {
|
|
112
115
|
console.log("Picture-in-Picture に入れませんでした:", pip.error);
|
|
116
|
+
console.log(pip.errorInfo); // { code: "not-allowed", phase: "execute", recoverable: true, message: "..." }
|
|
113
117
|
}
|
|
114
118
|
```
|
|
115
119
|
|
|
@@ -133,13 +137,25 @@ if (pip.error) {
|
|
|
133
137
|
|
|
134
138
|
## 出力 state
|
|
135
139
|
|
|
136
|
-
| プロパティ
|
|
137
|
-
|
|
138
|
-
| `active`
|
|
139
|
-
| `error`
|
|
140
|
+
| プロパティ | 型 | イベント | 説明 |
|
|
141
|
+
|-------------|--------------------------|------------------------------|------|
|
|
142
|
+
| `active` | `boolean` | `wcs-pip:change` | 解決済みの `<video>` target が現在 document の Picture-in-Picture 要素かどうか。 |
|
|
143
|
+
| `error` | `any` | `wcs-pip:error` | 直近のコマンド失敗(不正なタグ・非対応API・gesture 制約による reject)、または直近が成功/未失敗なら `null`。observable 化しても `error` の値の形自体は不変。 |
|
|
144
|
+
| `errorInfo` | `WcsIoErrorInfo \| null` | `wcs-pip:error-info-changed` | `error` から導出される追加的でシリアライズ可能な失敗 **taxonomy**: 安定した `{ code, phase, recoverable, message }`。`error` と歩調を合わせて `null` になる。下の taxonomy 表参照。 |
|
|
140
145
|
|
|
141
146
|
`active` は、`enterpictureinpicture`/`leavepictureinpicture` が**その対象要素自身に**発火するたびに、`document.pictureInPictureElement` と解決済み `<video>` target を比較して導出されます(`document` レベルのイベントではありません — 詳細は下記「イベント購読」参照)。
|
|
142
147
|
|
|
148
|
+
### `errorInfo` taxonomy
|
|
149
|
+
|
|
150
|
+
`errorInfo` は `error` の*追加的*な射影であり(`error` 自体の値の形は変えません)、分岐に使える安定したシリアライズ可能な code を提供します。cloneable でない例外を運ばずに、そのままログや DevTools/remote へ転送できます。`error` と厳密に同期して null↔非null を移り、`wcs-pip:error-info-changed` イベントは `wcs-pip:error` の直前に発火します。
|
|
151
|
+
|
|
152
|
+
| `code` | `phase` | `recoverable` | 発生条件 |
|
|
153
|
+
|----------------------|-----------|---------------|----------|
|
|
154
|
+
| `capability-missing` | `probe` | `false` | Picture-in-Picture API が利用不可(`{ message: "Picture-in-Picture API is not supported." }`)。 |
|
|
155
|
+
| `invalid-argument` | `start` | `false` | `target` が `<video>` 要素に解決しない(`{ message: "target must be a <video> element." }`)。 |
|
|
156
|
+
| `not-allowed` | `execute` | `true` | `NotAllowedError` / `TypeError` で reject(例: ユーザージェスチャー外での呼び出し)— 本物のジェスチャー内で再試行すれば成功しうる。 |
|
|
157
|
+
| `pip-error` | `execute` | `false` | プラットフォーム呼び出しからのその他の caught 例外。 |
|
|
158
|
+
|
|
143
159
|
## コマンド
|
|
144
160
|
|
|
145
161
|
| コマンド | 説明 |
|
|
@@ -176,8 +192,10 @@ wcs-pip:state(active) ~ .back-to-page-button { display: none; } /* デフォル
|
|
|
176
192
|
```
|
|
177
193
|
|
|
178
194
|
属性やクラスと異なり `:state()` は要素の外部から書き込めないため、この出力ステートが
|
|
179
|
-
入力と混同される心配がありません。`error`
|
|
180
|
-
|
|
195
|
+
入力と混同される心配がありません。`error`/`errorInfo` はあえて `:state()` に反映して
|
|
196
|
+
いません — presence/absence 疑似クラスに素直に対応するのは boolean の `active` のみだから
|
|
197
|
+
です。(`error`/`errorInfo` は各自のイベントで観測可能であり `data-wcs` でバインドできます
|
|
198
|
+
— 上記「出力 state」参照。)
|
|
181
199
|
|
|
182
200
|
**対応ブラウザ**(新構文 `:state(x)`): Chrome/Edge 125+、Safari 17.4+、Firefox 126+。
|
|
183
201
|
非対応の環境ではステートが一切 set されないだけです — `:state()` セレクタがマッチしなく
|
|
@@ -219,6 +237,8 @@ PipCore.wcBindable = {
|
|
|
219
237
|
version: 1,
|
|
220
238
|
properties: [
|
|
221
239
|
{ name: "active", event: "wcs-pip:change", getter: (e) => e.detail.active },
|
|
240
|
+
{ name: "error", event: "wcs-pip:error" },
|
|
241
|
+
{ name: "errorInfo", event: "wcs-pip:error-info-changed" },
|
|
222
242
|
],
|
|
223
243
|
commands: [
|
|
224
244
|
{ name: "requestPictureInPicture", async: true },
|
|
@@ -256,8 +276,8 @@ core.dispose(); // リスナーを外す
|
|
|
256
276
|
- **Document Picture-in-Picture API はスコープ外。** 上記「スコープ」参照。
|
|
257
277
|
- **例外を投げない。** 非対応環境・不正なタグの target・gesture 制約による reject は全て `error` に集約されます。
|
|
258
278
|
- **`document.pictureInPictureElement` は document 全体で単一の値**です(`document.fullscreenElement` と同様)。複数の `<wcs-pip>` インスタンスは、自分の `<video>` target の `enterpictureinpicture`/`leavepictureinpicture` リスナーによって自己フィルタされます — 上記「イベント購読先」参照。ただし非対称な点に注意してください: `exitPictureInPicture()` はインスタンス単位にスコープされて**いません** — document全体に作用する `document.exitPictureInPicture()` を呼ぶため、どのインスタンスから呼んでも、現在 Picture-in-Picture 中の `<video>`(別インスタンスの `target` が PiP 化したものであっても)を終了させます(silent no-op の判定も同様に document 全体の「何かが PiP 中か」であり、「自分の target が PiP 中か」ではありません)。これはプラットフォーム API 自体の挙動、および `@wcstack/fullscreen` の `exitFullscreen()`(`docs/fullscreen-tag-design.md` §7 の「スコープの注意(§2.1との非対称)」、および `packages/fullscreen/README.ja.md` の「複数インスタンス」節参照)をそのまま反映したものです。
|
|
259
|
-
- **`desired`/`actual` の二相 state は無し** — 本ノードは単一の `active` boolean と `error`
|
|
260
|
-
- **`error`
|
|
279
|
+
- **`desired`/`actual` の二相 state は無し** — 本ノードは単一の `active` boolean と `error`/`errorInfo` の失敗ペアを公開し、`permission` より単純な `@wcstack/fullscreen` の state モデルと同型です。
|
|
280
|
+
- **`error` と `errorInfo` は観測可能(バインド可能)です。** 両者は `static wcBindable.properties` に各自のイベント(`wcs-pip:error` / `wcs-pip:error-info-changed`)付きで宣言されているため、バインディングシステムは request/exit の失敗を `data-wcs` で購読できます(例: `error: pipError`)。`errorInfo` は `error` から導出される追加的でシリアライズ可能な taxonomy です(「出力 state」参照)。`error` の値の形自体は不変です。コマンドの promise が解決した後に `element.error` / `element.errorInfo` を命令的に読むこともできます(例: `await el.requestPictureInPicture(); if (el.error) { ... }`)。
|
|
261
281
|
|
|
262
282
|
## ライセンス
|
|
263
283
|
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ It is an **async primitive node** that turns a `<video>` element's Picture-in-Pi
|
|
|
8
8
|
With `@wcstack/state`, `<wcs-pip>` can be bound directly through path contracts:
|
|
9
9
|
|
|
10
10
|
- **input surface**: `target` — which `<video>` element to control
|
|
11
|
-
- **output state surface**: `active`, `error`
|
|
11
|
+
- **output state surface**: `active`, `error`, `errorInfo`
|
|
12
12
|
- **command surface**: `requestPictureInPicture()`, `exitPictureInPicture()`
|
|
13
13
|
|
|
14
14
|
This means a "pop out" video button — with no live-region layout thrashing, no manual `document.pictureInPictureElement` polling — can be expressed declaratively in HTML.
|
|
@@ -89,7 +89,7 @@ Neither button touches `<wcs-pip>` directly: each click emits a command token, a
|
|
|
89
89
|
|
|
90
90
|
### 3. Reporting failures (e.g. gesture-context rejection)
|
|
91
91
|
|
|
92
|
-
`error`
|
|
92
|
+
`error` and `errorInfo` are observable outputs (both fire an event — see "Output state" below), so you can bind them like `active`, or read them imperatively after the command's promise settles:
|
|
93
93
|
|
|
94
94
|
```html
|
|
95
95
|
<wcs-state>
|
|
@@ -97,19 +97,23 @@ Neither button touches `<wcs-pip>` directly: each click emits a command token, a
|
|
|
97
97
|
export default {
|
|
98
98
|
$commandTokens: ["popOut"],
|
|
99
99
|
pipActive: false,
|
|
100
|
+
pipError: null,
|
|
100
101
|
};
|
|
101
102
|
</script>
|
|
102
103
|
</wcs-state>
|
|
103
104
|
|
|
104
|
-
<wcs-pip target="#player" data-wcs="active: pipActive; command.requestPictureInPicture: $command.popOut"></wcs-pip>
|
|
105
|
+
<wcs-pip target="#player" data-wcs="active: pipActive; error: pipError; command.requestPictureInPicture: $command.popOut"></wcs-pip>
|
|
105
106
|
<button data-wcs="onclick: $command.popOut">Pop out</button>
|
|
106
107
|
```
|
|
107
108
|
|
|
109
|
+
Or imperatively, reading `errorInfo` for the stable failure taxonomy:
|
|
110
|
+
|
|
108
111
|
```js
|
|
109
112
|
const pip = document.querySelector("wcs-pip");
|
|
110
113
|
await pip.requestPictureInPicture();
|
|
111
114
|
if (pip.error) {
|
|
112
115
|
console.log("Could not enter Picture-in-Picture:", pip.error);
|
|
116
|
+
console.log(pip.errorInfo); // { code: "not-allowed", phase: "execute", recoverable: true, message: "..." }
|
|
113
117
|
}
|
|
114
118
|
```
|
|
115
119
|
|
|
@@ -133,13 +137,25 @@ Unlike `@wcstack/fullscreen` (where `target="self"` is a legitimate way to fulls
|
|
|
133
137
|
|
|
134
138
|
## Output state
|
|
135
139
|
|
|
136
|
-
| Property
|
|
137
|
-
|
|
138
|
-
| `active`
|
|
139
|
-
| `error`
|
|
140
|
+
| Property | Type | Event | Description |
|
|
141
|
+
|-------------|--------------------------|------------------------------|--------------|
|
|
142
|
+
| `active` | `boolean` | `wcs-pip:change` | Whether the resolved `<video>` target is currently the document's Picture-in-Picture element. |
|
|
143
|
+
| `error` | `any` | `wcs-pip:error` | The most recent command failure (wrong tag, unsupported API, gesture-context rejection), or `null` if the last attempt succeeded / nothing has failed yet. Value shape unchanged from before it became observable. |
|
|
144
|
+
| `errorInfo` | `WcsIoErrorInfo \| null` | `wcs-pip:error-info-changed` | Additive serializable failure **taxonomy** derived from `error`: a stable `{ code, phase, recoverable, message }`. `null` in lockstep with `error`. See the taxonomy table below. |
|
|
140
145
|
|
|
141
146
|
`active` is derived from comparing `document.pictureInPictureElement` against the resolved `<video>` target whenever `enterpictureinpicture`/`leavepictureinpicture` fires **on that target element** — not from a `document`-level event (see "Event subscription" below).
|
|
142
147
|
|
|
148
|
+
### `errorInfo` taxonomy
|
|
149
|
+
|
|
150
|
+
`errorInfo` is an *additive* projection of `error` (it never changes `error`'s own value shape) that gives a stable, serializable code you can branch on — safe to log or forward to DevTools/remote without carrying a non-cloneable exception. It moves null↔non-null exactly in step with `error`, and its `wcs-pip:error-info-changed` event fires immediately before `wcs-pip:error`.
|
|
151
|
+
|
|
152
|
+
| `code` | `phase` | `recoverable` | When |
|
|
153
|
+
|----------------------|-----------|---------------|------|
|
|
154
|
+
| `capability-missing` | `probe` | `false` | The Picture-in-Picture API is not available (`{ message: "Picture-in-Picture API is not supported." }`). |
|
|
155
|
+
| `invalid-argument` | `start` | `false` | `target` did not resolve to a `<video>` element (`{ message: "target must be a <video> element." }`). |
|
|
156
|
+
| `not-allowed` | `execute` | `true` | The request was rejected with `NotAllowedError` / `TypeError` (e.g. called outside a user gesture) — retrying from within a genuine gesture may succeed. |
|
|
157
|
+
| `pip-error` | `execute` | `false` | Any other caught exception from the platform call. |
|
|
158
|
+
|
|
143
159
|
## Commands
|
|
144
160
|
|
|
145
161
|
| Command | Description |
|
|
@@ -177,8 +193,10 @@ wcs-pip:state(active) ~ .back-to-page-button { display: none; } /* default */
|
|
|
177
193
|
|
|
178
194
|
Unlike attributes or classes, `:state()` cannot be written from outside the
|
|
179
195
|
element, so there is no risk of confusing this output state with an input.
|
|
180
|
-
`error`
|
|
181
|
-
|
|
196
|
+
`error`/`errorInfo` are intentionally **not** reflected as `:state()` — only the
|
|
197
|
+
boolean `active` maps cleanly to a presence/absence pseudo-class. (They *are*
|
|
198
|
+
observable via their own events for `data-wcs` binding — see "Output state"
|
|
199
|
+
above.)
|
|
182
200
|
|
|
183
201
|
**Browser support** (`:state(x)` syntax): Chrome/Edge 125+, Safari 17.4+,
|
|
184
202
|
Firefox 126+. In older browsers the states are simply never set — `:state()`
|
|
@@ -222,6 +240,8 @@ PipCore.wcBindable = {
|
|
|
222
240
|
version: 1,
|
|
223
241
|
properties: [
|
|
224
242
|
{ name: "active", event: "wcs-pip:change", getter: (e) => e.detail.active },
|
|
243
|
+
{ name: "error", event: "wcs-pip:error" },
|
|
244
|
+
{ name: "errorInfo", event: "wcs-pip:error-info-changed" },
|
|
225
245
|
],
|
|
226
246
|
commands: [
|
|
227
247
|
{ name: "requestPictureInPicture", async: true },
|
|
@@ -259,8 +279,8 @@ core.dispose(); // detach listeners
|
|
|
259
279
|
- **Document Picture-in-Picture API is out of scope.** See "Scope" above.
|
|
260
280
|
- **Never throws.** Unsupported environments, wrong-tag targets, and gesture-context rejections are all funneled into `error`.
|
|
261
281
|
- **`document.pictureInPictureElement` is a single document-wide value**, like `document.fullscreenElement`. Multiple `<wcs-pip>` instances self-filter via their own `<video>` target's `enterpictureinpicture`/`leavepictureinpicture` listeners — see "Event subscription" above. Note the asymmetry, though: `exitPictureInPicture()` is **not** scoped per instance — it calls the document-global `document.exitPictureInPicture()`, so invoking it on any instance exits whatever `<video>` is currently in Picture-in-Picture, even one entered via another instance's `target` (its silent no-op check is likewise document-wide: "is anything in Picture-in-Picture", not "is *my* target in Picture-in-Picture"). This mirrors the platform API itself and `@wcstack/fullscreen`'s `exitFullscreen()` (see `docs/fullscreen-tag-design.md` §7's "scope note" alongside §2.1, and the "Multiple instances" bullet in `packages/fullscreen/README.md`).
|
|
262
|
-
- **No `desired`/`actual` two-phase state** — this node exposes a single `active` boolean plus `error
|
|
263
|
-
- **`error`
|
|
282
|
+
- **No `desired`/`actual` two-phase state** — this node exposes a single `active` boolean plus the `error`/`errorInfo` failure pair, mirroring `@wcstack/fullscreen`'s simpler-than-`permission` state model.
|
|
283
|
+
- **`error` and `errorInfo` are observable (bindable).** Both are declared in `static wcBindable.properties` with their own events (`wcs-pip:error` / `wcs-pip:error-info-changed`), so a binding system can subscribe to a request/exit failure via `data-wcs` (e.g. `error: pipError`). `errorInfo` is the additive serializable taxonomy derived from `error` (see "Output state"); the `error` value shape is unchanged. You can still read `element.error` / `element.errorInfo` imperatively after a command's promise settles (e.g. `await el.requestPictureInPicture(); if (el.error) { ... }`).
|
|
264
284
|
|
|
265
285
|
## License
|
|
266
286
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/** operation error の phase(taxonomy)。 */
|
|
2
|
+
type WcsIoErrorPhase = "probe" | "start" | "execute" | "decode" | "commit" | "dispose";
|
|
3
|
+
/** serializable な error info(non-cloneable な cause とは分離。DevTools / remote へは info のみ)。 */
|
|
4
|
+
interface WcsIoErrorInfo {
|
|
5
|
+
readonly code: string;
|
|
6
|
+
readonly phase: WcsIoErrorPhase;
|
|
7
|
+
readonly recoverable: boolean;
|
|
8
|
+
readonly capabilityId?: string;
|
|
9
|
+
readonly message: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
1
12
|
interface IWcBindableProperty {
|
|
2
13
|
readonly name: string;
|
|
3
14
|
readonly event: string;
|
|
@@ -13,7 +24,8 @@ interface IWcBindableCommand {
|
|
|
13
24
|
}
|
|
14
25
|
interface IWcBindable {
|
|
15
26
|
readonly protocol: "wc-bindable";
|
|
16
|
-
|
|
27
|
+
/** Integer protocol version. All versions >= 1 are core-compatible. */
|
|
28
|
+
readonly version: number;
|
|
17
29
|
readonly properties: readonly IWcBindableProperty[];
|
|
18
30
|
readonly inputs?: readonly IWcBindableInput[];
|
|
19
31
|
readonly commands?: readonly IWcBindableCommand[];
|
|
@@ -34,26 +46,27 @@ interface IWritableConfig {
|
|
|
34
46
|
|
|
35
47
|
/**
|
|
36
48
|
* Value types for PipCore (headless) — the Core's readable value surface.
|
|
37
|
-
*
|
|
38
|
-
* `wcBindable.properties` with
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
* (
|
|
49
|
+
* `active`, `error`, and `errorInfo` are all *observable* (declared in
|
|
50
|
+
* `wcBindable.properties` with change events: `wcs-pip:change` / `:error` /
|
|
51
|
+
* `:error-info-changed`), so a wc-bindable binding core delivers a request/exit
|
|
52
|
+
* failure. `errorInfo` is the additive serializable failure taxonomy derived
|
|
53
|
+
* from `error` (README "Output state").
|
|
42
54
|
*
|
|
43
55
|
* @example
|
|
44
56
|
* ```typescript
|
|
45
57
|
* const core = new PipCore();
|
|
46
|
-
* // bind() only ever delivers "active" — see the note above about "error".
|
|
47
58
|
* bind(core, (name: keyof WcsPipCoreValues, value) => { ... });
|
|
48
59
|
* ```
|
|
49
60
|
*/
|
|
50
61
|
interface WcsPipCoreValues {
|
|
51
62
|
active: boolean;
|
|
52
63
|
error: any;
|
|
64
|
+
/** Additive failure taxonomy derived from `error` (stable code / phase / recoverable). */
|
|
65
|
+
errorInfo: WcsIoErrorInfo | null;
|
|
53
66
|
}
|
|
54
67
|
/**
|
|
55
68
|
* Value types for the Shell (`<wcs-pip>`) — identical value surface to the
|
|
56
|
-
* Core (
|
|
69
|
+
* Core (`active` / `error` / `errorInfo` all observable). The Shell adds the
|
|
57
70
|
* `target` input (attribute-mirrored) and no additional observable
|
|
58
71
|
* properties.
|
|
59
72
|
*/
|
|
@@ -94,6 +107,7 @@ declare class PipCore extends EventTarget {
|
|
|
94
107
|
private _target;
|
|
95
108
|
private _active;
|
|
96
109
|
private _error;
|
|
110
|
+
private _errorInfo;
|
|
97
111
|
private _video;
|
|
98
112
|
private _gen;
|
|
99
113
|
private _ready;
|
|
@@ -101,6 +115,13 @@ declare class PipCore extends EventTarget {
|
|
|
101
115
|
get ready(): Promise<void>;
|
|
102
116
|
get active(): boolean;
|
|
103
117
|
get error(): any;
|
|
118
|
+
/**
|
|
119
|
+
* The last failure's serializable `WcsIoErrorInfo` (stable `code` / `phase` /
|
|
120
|
+
* `recoverable`), or null. Additive wc-bindable property (event
|
|
121
|
+
* `wcs-pip:error-info-changed`), derived from `error`; the existing `error`
|
|
122
|
+
* value shape is unchanged.
|
|
123
|
+
*/
|
|
124
|
+
get errorInfo(): WcsIoErrorInfo | null;
|
|
104
125
|
/**
|
|
105
126
|
* (Re-)subscribe to `enterpictureinpicture`/`leavepictureinpicture` on
|
|
106
127
|
* `element` (the Shell's resolved `<video>` target). Idempotent when called
|
|
@@ -133,6 +154,7 @@ declare class PipCore extends EventTarget {
|
|
|
133
154
|
private _detach;
|
|
134
155
|
private _setActive;
|
|
135
156
|
private _setError;
|
|
157
|
+
private _commitErrorInfo;
|
|
136
158
|
}
|
|
137
159
|
|
|
138
160
|
/**
|
|
@@ -168,6 +190,7 @@ declare class WcsPip extends HTMLElement {
|
|
|
168
190
|
set target(value: string);
|
|
169
191
|
get active(): boolean;
|
|
170
192
|
get error(): any;
|
|
193
|
+
get errorInfo(): WcsIoErrorInfo | null;
|
|
171
194
|
requestPictureInPicture(): Promise<void>;
|
|
172
195
|
exitPictureInPicture(): Promise<void>;
|
|
173
196
|
/**
|
|
@@ -192,5 +215,32 @@ declare class WcsPip extends HTMLElement {
|
|
|
192
215
|
attributeChangedCallback(_name: string, oldValue: string | null, newValue: string | null): void;
|
|
193
216
|
}
|
|
194
217
|
|
|
195
|
-
|
|
196
|
-
|
|
218
|
+
/**
|
|
219
|
+
* pictureInPictureCapabilities.ts
|
|
220
|
+
*
|
|
221
|
+
* Picture-in-Picture node 固有の error code(taxonomy)と derivation。汎用の error
|
|
222
|
+
* info 型は `./platformCapability.js`(/io-core/ から copy-distribution される生成
|
|
223
|
+
* ファイル)から import する。Picture-in-Picture は referenced `<video>` を操作する
|
|
224
|
+
* ノードで競合 operation を持たないため lane は無く、error taxonomy(errorInfo)のみを
|
|
225
|
+
* 採用する(fullscreen と同型)。
|
|
226
|
+
*
|
|
227
|
+
* `_setError` は合成 `{ message }`(target が `<video>` に解決しない / API 非対応)と
|
|
228
|
+
* caught 例外(`NotAllowedError` = user gesture 外の requestPictureInPicture 拒否等)を
|
|
229
|
+
* 混在受理する。呼出側が明示 `kind` を渡して合成側を曖昧さ無く分類し、caught は `.name`
|
|
230
|
+
* で分類する(fullscreen / storage / screen-orientation と同じ discriminator 方式)。
|
|
231
|
+
*/
|
|
232
|
+
|
|
233
|
+
/** 安定した Picture-in-Picture error code(taxonomy)。値は公開キーとして固定。 */
|
|
234
|
+
declare const WCS_PICTURE_IN_PICTURE_ERROR_CODE: {
|
|
235
|
+
/** Picture-in-Picture API 非対応。 */
|
|
236
|
+
readonly CapabilityMissing: "capability-missing";
|
|
237
|
+
/** target が `<video>` に解決しない等の入力不備。 */
|
|
238
|
+
readonly InvalidArgument: "invalid-argument";
|
|
239
|
+
/** `NotAllowedError` / `TypeError` — user gesture 外での要求拒否。 */
|
|
240
|
+
readonly NotAllowed: "not-allowed";
|
|
241
|
+
/** その他の caught 例外。 */
|
|
242
|
+
readonly PipError: "pip-error";
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
export { PipCore, WCS_PICTURE_IN_PICTURE_ERROR_CODE, WcsPip, bootstrapPip, getConfig };
|
|
246
|
+
export type { IWritableConfig, IWritableTagNames, WcsIoErrorInfo, WcsIoErrorPhase, WcsPipCoreValues, WcsPipValues };
|
package/dist/index.esm.js
CHANGED
|
@@ -36,6 +36,57 @@ function setConfig(partialConfig) {
|
|
|
36
36
|
frozenConfig = null;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* pictureInPictureCapabilities.ts
|
|
41
|
+
*
|
|
42
|
+
* Picture-in-Picture node 固有の error code(taxonomy)と derivation。汎用の error
|
|
43
|
+
* info 型は `./platformCapability.js`(/io-core/ から copy-distribution される生成
|
|
44
|
+
* ファイル)から import する。Picture-in-Picture は referenced `<video>` を操作する
|
|
45
|
+
* ノードで競合 operation を持たないため lane は無く、error taxonomy(errorInfo)のみを
|
|
46
|
+
* 採用する(fullscreen と同型)。
|
|
47
|
+
*
|
|
48
|
+
* `_setError` は合成 `{ message }`(target が `<video>` に解決しない / API 非対応)と
|
|
49
|
+
* caught 例外(`NotAllowedError` = user gesture 外の requestPictureInPicture 拒否等)を
|
|
50
|
+
* 混在受理する。呼出側が明示 `kind` を渡して合成側を曖昧さ無く分類し、caught は `.name`
|
|
51
|
+
* で分類する(fullscreen / storage / screen-orientation と同じ discriminator 方式)。
|
|
52
|
+
*/
|
|
53
|
+
/** 安定した Picture-in-Picture error code(taxonomy)。値は公開キーとして固定。 */
|
|
54
|
+
const WCS_PICTURE_IN_PICTURE_ERROR_CODE = {
|
|
55
|
+
/** Picture-in-Picture API 非対応。 */
|
|
56
|
+
CapabilityMissing: "capability-missing",
|
|
57
|
+
/** target が `<video>` に解決しない等の入力不備。 */
|
|
58
|
+
InvalidArgument: "invalid-argument",
|
|
59
|
+
/** `NotAllowedError` / `TypeError` — user gesture 外での要求拒否。 */
|
|
60
|
+
NotAllowed: "not-allowed",
|
|
61
|
+
/** その他の caught 例外。 */
|
|
62
|
+
PipError: "pip-error",
|
|
63
|
+
};
|
|
64
|
+
function messageOf(error) {
|
|
65
|
+
return typeof error?.message === "string"
|
|
66
|
+
? error.message
|
|
67
|
+
: String(error);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Picture-in-Picture の失敗を serializable な error taxonomy に写す。`kind` は合成
|
|
71
|
+
* エラーの呼出側が渡す明示 discriminator(`capability-missing` / `invalid-argument`)。
|
|
72
|
+
* 未指定は caught 例外を意味し、`.name` で分類する。`NotAllowedError` / `TypeError` は
|
|
73
|
+
* user gesture 内で再試行すれば成功しうるため recoverable=true。
|
|
74
|
+
*/
|
|
75
|
+
function derivePictureInPictureErrorInfo(error, kind) {
|
|
76
|
+
const message = messageOf(error);
|
|
77
|
+
if (kind === "capability-missing") {
|
|
78
|
+
return { code: WCS_PICTURE_IN_PICTURE_ERROR_CODE.CapabilityMissing, phase: "probe", recoverable: false, message };
|
|
79
|
+
}
|
|
80
|
+
if (kind === "invalid-argument") {
|
|
81
|
+
return { code: WCS_PICTURE_IN_PICTURE_ERROR_CODE.InvalidArgument, phase: "start", recoverable: false, message };
|
|
82
|
+
}
|
|
83
|
+
const name = error?.name;
|
|
84
|
+
if (name === "NotAllowedError" || name === "TypeError") {
|
|
85
|
+
return { code: WCS_PICTURE_IN_PICTURE_ERROR_CODE.NotAllowed, phase: "execute", recoverable: true, message };
|
|
86
|
+
}
|
|
87
|
+
return { code: WCS_PICTURE_IN_PICTURE_ERROR_CODE.PipError, phase: "execute", recoverable: false, message };
|
|
88
|
+
}
|
|
89
|
+
|
|
39
90
|
/**
|
|
40
91
|
* Headless Picture-in-Picture primitive. A thin, framework-agnostic wrapper
|
|
41
92
|
* around the classic Picture-in-Picture API
|
|
@@ -68,6 +119,14 @@ class PipCore extends EventTarget {
|
|
|
68
119
|
version: 1,
|
|
69
120
|
properties: [
|
|
70
121
|
{ name: "active", event: "wcs-pip:change", getter: (e) => e.detail.active },
|
|
122
|
+
// `error` / `errorInfo` are observable failure outputs. Historically `error`
|
|
123
|
+
// was an imperative getter with no event; both are now bindable (event-backed)
|
|
124
|
+
// so `data-wcs` / bind() can observe a request/exit failure. `errorInfo` is the
|
|
125
|
+
// additive serializable taxonomy (stable code / phase / recoverable) derived
|
|
126
|
+
// from `error`; the `error` value shape is unchanged. No lane — Picture-in-Picture
|
|
127
|
+
// drives a referenced `<video>`, not a competing operation (fullscreen と同型)。
|
|
128
|
+
{ name: "error", event: "wcs-pip:error" },
|
|
129
|
+
{ name: "errorInfo", event: "wcs-pip:error-info-changed" },
|
|
71
130
|
],
|
|
72
131
|
commands: [
|
|
73
132
|
{ name: "requestPictureInPicture", async: true },
|
|
@@ -77,6 +136,7 @@ class PipCore extends EventTarget {
|
|
|
77
136
|
_target;
|
|
78
137
|
_active = false;
|
|
79
138
|
_error = null;
|
|
139
|
+
_errorInfo = null;
|
|
80
140
|
// The <video> element the Core currently subscribes to for
|
|
81
141
|
// enterpictureinpicture/leavepictureinpicture (null when unresolved/torn down).
|
|
82
142
|
_video = null;
|
|
@@ -99,6 +159,15 @@ class PipCore extends EventTarget {
|
|
|
99
159
|
get error() {
|
|
100
160
|
return this._error;
|
|
101
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* The last failure's serializable `WcsIoErrorInfo` (stable `code` / `phase` /
|
|
164
|
+
* `recoverable`), or null. Additive wc-bindable property (event
|
|
165
|
+
* `wcs-pip:error-info-changed`), derived from `error`; the existing `error`
|
|
166
|
+
* value shape is unchanged.
|
|
167
|
+
*/
|
|
168
|
+
get errorInfo() {
|
|
169
|
+
return this._errorInfo;
|
|
170
|
+
}
|
|
102
171
|
// --- Lifecycle (§3.5) ---
|
|
103
172
|
/**
|
|
104
173
|
* (Re-)subscribe to `enterpictureinpicture`/`leavepictureinpicture` on
|
|
@@ -136,7 +205,9 @@ class PipCore extends EventTarget {
|
|
|
136
205
|
async requestPictureInPicture(element) {
|
|
137
206
|
const gen = ++this._gen;
|
|
138
207
|
if (!element || element.tagName !== "VIDEO") {
|
|
139
|
-
|
|
208
|
+
// Distinct from "API is not supported" (below): the resolved target did
|
|
209
|
+
// not satisfy the `<video>`-only constraint (wrong tag / unresolved).
|
|
210
|
+
this._setError({ message: "target must be a <video> element." }, "invalid-argument");
|
|
140
211
|
return;
|
|
141
212
|
}
|
|
142
213
|
// Re-wire to `element` before issuing the platform call: a caller may
|
|
@@ -152,7 +223,7 @@ class PipCore extends EventTarget {
|
|
|
152
223
|
this.observe(element);
|
|
153
224
|
const fn = this._requestPictureInPictureFn(element);
|
|
154
225
|
if (!fn) {
|
|
155
|
-
this._setError({ message: "Picture-in-Picture API is not supported." });
|
|
226
|
+
this._setError({ message: "Picture-in-Picture API is not supported." }, "capability-missing");
|
|
156
227
|
return;
|
|
157
228
|
}
|
|
158
229
|
try {
|
|
@@ -246,8 +317,33 @@ class PipCore extends EventTarget {
|
|
|
246
317
|
bubbles: true,
|
|
247
318
|
}));
|
|
248
319
|
}
|
|
249
|
-
|
|
320
|
+
// `kind` is an explicit taxonomy discriminator passed only from the synthetic
|
|
321
|
+
// error sites (unsupported / non-<video> target); caught exceptions pass no kind
|
|
322
|
+
// and are classified by their `.name`. Both `error` and the additive `errorInfo`
|
|
323
|
+
// are now event-backed so a request/exit failure is observable via bind().
|
|
324
|
+
_setError(error, kind) {
|
|
325
|
+
// Same-value guard on reference: each failure builds a fresh object and the
|
|
326
|
+
// clear path passes the literal null, so this only suppresses redundant
|
|
327
|
+
// null→null (a successful request/exit clearing an already-null error).
|
|
328
|
+
if (this._error === error)
|
|
329
|
+
return;
|
|
250
330
|
this._error = error;
|
|
331
|
+
// Keep the additive errorInfo taxonomy in sync; fire it before the `error`
|
|
332
|
+
// event so an observer of both sees the classification first (io-node family).
|
|
333
|
+
this._commitErrorInfo(error === null ? null : derivePictureInPictureErrorInfo(error, kind));
|
|
334
|
+
this._target.dispatchEvent(new CustomEvent("wcs-pip:error", {
|
|
335
|
+
detail: error,
|
|
336
|
+
bubbles: true,
|
|
337
|
+
}));
|
|
338
|
+
}
|
|
339
|
+
// Called only from _setError (already reference-guarded), so errorInfo
|
|
340
|
+
// transitions exactly when error does — no separate guard needed here.
|
|
341
|
+
_commitErrorInfo(info) {
|
|
342
|
+
this._errorInfo = info;
|
|
343
|
+
this._target.dispatchEvent(new CustomEvent("wcs-pip:error-info-changed", {
|
|
344
|
+
detail: info,
|
|
345
|
+
bubbles: true,
|
|
346
|
+
}));
|
|
251
347
|
}
|
|
252
348
|
}
|
|
253
349
|
|
|
@@ -356,6 +452,9 @@ class WcsPip extends HTMLElement {
|
|
|
356
452
|
get error() {
|
|
357
453
|
return this._core.error;
|
|
358
454
|
}
|
|
455
|
+
get errorInfo() {
|
|
456
|
+
return this._core.errorInfo;
|
|
457
|
+
}
|
|
359
458
|
// --- Commands ---
|
|
360
459
|
async requestPictureInPicture() {
|
|
361
460
|
const { element } = this._resolveVideoTarget();
|
|
@@ -442,5 +541,5 @@ function bootstrapPip(userConfig) {
|
|
|
442
541
|
registerComponents();
|
|
443
542
|
}
|
|
444
543
|
|
|
445
|
-
export { PipCore, WcsPip, bootstrapPip, getConfig };
|
|
544
|
+
export { PipCore, WCS_PICTURE_IN_PICTURE_ERROR_CODE, WcsPip, bootstrapPip, getConfig };
|
|
446
545
|
//# sourceMappingURL=index.esm.js.map
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/config.ts","../src/core/PipCore.ts","../src/components/Pip.ts","../src/registerComponents.ts","../src/bootstrapPip.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n tagNames: {\n pip: string;\n };\n}\n\nconst _config: IInternalConfig = {\n tagNames: {\n pip: \"wcs-pip\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { IWcBindable } from \"../types.js\";\n\n/**\n * Headless Picture-in-Picture primitive. A thin, framework-agnostic wrapper\n * around the classic Picture-in-Picture API\n * (`HTMLVideoElement.requestPictureInPicture()` / `document.exitPictureInPicture()` /\n * `document.pictureInPictureElement`) exposed through the wc-bindable protocol.\n *\n * This Core follows the same basic pattern as `@wcstack/fullscreen`'s\n * `FullscreenCore` (docs/fullscreen-tag-design.md): target resolution is done\n * by the Shell (this Core receives the resolved element at call time), API\n * resolution is call-time/non-cached, `_gen` is a single Core-level generation\n * guard, and `error` is a simple single field (no permission-style 4-value\n * state). See docs/picture-in-picture-tag-design.md for the differences from\n * Fullscreen:\n *\n * - **§2 target constraint**: the resolved target MUST be a `<video>` element.\n * Picture-in-Picture is only defined as an instance method of\n * `HTMLVideoElement` — unlike Fullscreen, which any `Element` supports. A\n * non-`<video>` target is a never-throw failure: it is treated the same as\n * an unresolved target and reported via `error`.\n * - **§3 event subscription target**: `enterpictureinpicture` /\n * `leavepictureinpicture` fire on the `<video>` element itself, not on\n * `document` (the reverse of Fullscreen's `document`-level\n * `fullscreenchange`). The Core attaches/detaches these listeners directly\n * on the resolved `<video>` element, re-wiring them whenever the target is\n * re-resolved (e.g. the Shell's `target` attribute changes).\n */\nexport class PipCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"active\", event: \"wcs-pip:change\", getter: (e: Event) => (e as CustomEvent).detail.active },\n ],\n commands: [\n { name: \"requestPictureInPicture\", async: true },\n { name: \"exitPictureInPicture\", async: true },\n ],\n };\n\n private _target: EventTarget;\n private _active: boolean = false;\n private _error: any = null;\n\n // The <video> element the Core currently subscribes to for\n // enterpictureinpicture/leavepictureinpicture (null when unresolved/torn down).\n private _video: HTMLVideoElement | null = null;\n\n // Generation guard (§3.4 / fullscreen-tag-design.md §6): bumped on dispose()\n // and each async command start. A completion that lands after dispose() (or\n // after a superseding call) is stale and MUST NOT write state.\n private _gen = 0;\n\n // SSR (§3.8): no asynchronous probe to await, so readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get ready(): Promise<void> {\n return this._ready;\n }\n\n get active(): boolean {\n return this._active;\n }\n\n get error(): any {\n return this._error;\n }\n\n // --- Lifecycle (§3.5) ---\n\n /**\n * (Re-)subscribe to `enterpictureinpicture`/`leavepictureinpicture` on\n * `element` (the Shell's resolved `<video>` target). Idempotent when called\n * again with the same element; re-wires the listeners when the element\n * changes (e.g. the `target` attribute was changed), detaching from the\n * previous element first so no stale listener lingers.\n */\n observe(element: HTMLVideoElement | null): Promise<void> {\n if (this._video === element) {\n return this._ready;\n }\n this._detach();\n this._video = element;\n if (element) {\n element.addEventListener(\"enterpictureinpicture\", this._onEnter);\n element.addEventListener(\"leavepictureinpicture\", this._onLeave);\n }\n this._syncActive();\n return this._ready;\n }\n\n dispose(): void {\n this._gen++;\n this._detach();\n this._video = null;\n }\n\n // --- Commands (§3.6 never-throw) ---\n\n /**\n * Request Picture-in-Picture for `element`. `element` must be a `<video>`\n * (checked before the gesture-context failure path, since a type mismatch is\n * an environment-independent, permanent error — docs/picture-in-picture-tag-design.md §2).\n * Never throws: all failures (wrong tag, unsupported API, gesture-context\n * rejection) are funneled into `error` and the returned promise resolves.\n */\n async requestPictureInPicture(element: HTMLVideoElement | null): Promise<void> {\n const gen = ++this._gen;\n if (!element || element.tagName !== \"VIDEO\") {\n this._setError({ message: \"target must be a <video> element.\" });\n return;\n }\n // Re-wire to `element` before issuing the platform call: a caller may\n // request a <video> different from the one last passed to observe() (e.g.\n // the Shell's target attribute pointed at nothing at connect time and the\n // matching <video> was only inserted later, so no attributeChangedCallback\n // ever re-resolved it). Without this, `_video` stays stale and\n // `_syncActive()` below (and future enter/leave events) would never\n // recognize `element` as this Core's target, leaving `active` permanently\n // wrong even though the request succeeded (mirrors\n // FullscreenCore.requestFullscreen()'s unconditional `this._resolvedTarget\n // = element` assignment — docs/fullscreen-tag-design.md §6).\n this.observe(element);\n const fn = this._requestPictureInPictureFn(element);\n if (!fn) {\n this._setError({ message: \"Picture-in-Picture API is not supported.\" });\n return;\n }\n try {\n await fn.call(element);\n if (gen !== this._gen) return; // stale\n this._setError(null);\n this._syncActive(); // belt-and-suspenders (mirrors FullscreenCore's _applyActive() on success)\n } catch (e: any) {\n if (gen !== this._gen) return; // stale\n this._setError(e); // e.g. NotAllowedError (gesture-context rejection)\n }\n }\n\n /**\n * Exit Picture-in-Picture. Mirrors FullscreenCore.exitFullscreen(): a\n * silent no-op (resolve, no error) when nothing is currently in\n * Picture-in-Picture — see fullscreen-tag-design.md §7.\n */\n async exitPictureInPicture(): Promise<void> {\n // no-op checks come BEFORE the generation bump: a call that does nothing\n // must not supersede an in-flight requestPictureInPicture() — bumping\n // first would make the pending request's settle handling stale and\n // silently swallow its error update (mirrors\n // FullscreenCore.exitFullscreen()).\n if (this._pictureInPictureElement() === null) return; // already not in PiP: silent no-op\n const fn = this._exitPictureInPictureFn();\n if (!fn) return; // unsupported: silent no-op (semantically already \"not in PiP\")\n const gen = ++this._gen;\n try {\n await fn();\n if (gen !== this._gen) return;\n this._setError(null);\n this._syncActive(); // belt-and-suspenders (mirrors FullscreenCore.exitFullscreen()'s success-path _applyActive()); covers a delayed/dropped leavepictureinpicture\n } catch (e: any) {\n if (gen !== this._gen) return;\n this._setError(e);\n }\n }\n\n // --- Internal: API resolution (call-time, never cached — §3.7) ---\n\n // Unlike FullscreenCore's _elementFullscreenFn(), a naive direct property\n // lookup (`e.requestPictureInPicture`, walking the prototype chain) here is\n // safe: it cannot recurse into the Shell's own command method,\n // because the resolved target is validated to be a <video> element (§2)\n // before this is called, and <wcs-pip> (the Shell) is never itself a\n // <video>. Fullscreen's own→Element.prototype two-step resolution guards\n // against `target=\"self\"`/no-target resolving to the Shell element, which\n // cannot happen here.\n private _requestPictureInPictureFn(el: HTMLVideoElement): (() => Promise<PictureInPictureWindow>) | undefined {\n const e = el as any;\n return typeof e.requestPictureInPicture === \"function\" ? e.requestPictureInPicture : undefined;\n }\n\n private _exitPictureInPictureFn(): (() => Promise<void>) | undefined {\n const d = document as any;\n return typeof d.exitPictureInPicture === \"function\" ? d.exitPictureInPicture.bind(document) : undefined;\n }\n\n private _pictureInPictureElement(): Element | null {\n const d = document as any;\n return d.pictureInPictureElement ?? null;\n }\n\n // --- Internal: event wiring ---\n\n private _onEnter = (): void => {\n this._syncActive();\n };\n\n private _onLeave = (): void => {\n this._syncActive();\n };\n\n private _syncActive(): void {\n const isActive = this._video !== null && this._pictureInPictureElement() === this._video;\n this._setActive(isActive);\n }\n\n private _detach(): void {\n if (this._video) {\n this._video.removeEventListener(\"enterpictureinpicture\", this._onEnter);\n this._video.removeEventListener(\"leavepictureinpicture\", this._onLeave);\n }\n }\n\n // --- State setters with event dispatch (§3.3 same-value guard) ---\n\n private _setActive(active: boolean): void {\n if (this._active === active) return;\n this._active = active;\n this._target.dispatchEvent(new CustomEvent(\"wcs-pip:change\", {\n detail: { active },\n bubbles: true,\n }));\n }\n\n private _setError(error: any): void {\n this._error = error;\n }\n}\n","import { IWcBindable } from \"../types.js\";\nimport { PipCore } from \"../core/PipCore.js\";\n\n/**\n * `<wcs-pip target=\"...\">` — declarative Picture-in-Picture control.\n *\n * Like `<wcs-fullscreen>` (docs/fullscreen-tag-design.md §0/§1), this Shell\n * does not operate on itself: it is a non-visible control tag that resolves a\n * `target` element and invokes Picture-in-Picture commands against it. The\n * `target` attribute resolves in the same 3 modes as `intersection`/`fullscreen`\n * (`self` / a selector / the first element child), reused verbatim from\n * `@wcstack/intersection`'s `_resolveTarget()`/`_safeQuery()`\n * (packages/intersection/src/components/Intersect.ts).\n *\n * Picture-in-Picture-specific difference (docs/picture-in-picture-tag-design.md\n * §2): the resolved target must be a `<video>` element. This Shell resolves the\n * DOM element and hands it to the Core; the Core performs the `tagName ===\n * \"VIDEO\"` validation (never-throw — a mismatch is treated as an unresolved\n * target and reported via `error`, not thrown).\n */\nexport class WcsPip extends HTMLElement {\n // SSR (§4.4): observe() completes synchronously, but the Shell still exposes\n // connectedCallbackPromise so the state binder can await it uniformly across\n // all IO nodes before snapshotting.\n static hasConnectedCallbackPromise = true;\n\n static observedAttributes = [\"target\"];\n\n static wcBindable: IWcBindable = {\n ...PipCore.wcBindable,\n inputs: [{ name: \"target\", attribute: \"target\" }],\n // Core の commands をそのまま継承(単一情報源)。fullscreen/intersection と同型。\n commands: PipCore.wcBindable.commands,\n };\n\n private _core: PipCore;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new PipCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n \"wcs-pip:change\": (d) => ({ active: d?.active === true }),\n });\n }\n\n // CSS state reflection (:state()) — debug-only snapshot getter. NOT part of\n // wc-bindable (not a bind target); see README \"CSS styling with :state()\".\n // MUST NOT return the live CustomStateSet (that would let callers write\n // states from outside, defeating the point of :state() being read-only).\n get debugStates(): string[] {\n return this._internals ? [...this._internals.states] : [];\n }\n\n private _initInternals(): ElementInternals | null {\n // never-throw (docs/custom-state-reflection-design.md §3.1): attachInternals\n // is absent in happy-dom / older environments, and pre-125 Chromium rejects\n // non-dashed state names from states.add() (probed and discarded here).\n // Either case silently disables reflection — the component still works,\n // it just doesn't expose :state() selectors.\n try {\n if (typeof this.attachInternals !== \"function\") return null;\n const internals = this.attachInternals();\n internals.states.add(\"wcs-probe\");\n internals.states.delete(\"wcs-probe\");\n return internals;\n } catch {\n return null;\n }\n }\n\n private _wireStates(map: Record<string, (detail: any) => Record<string, boolean>>): void {\n if (this._internals === null) return;\n const states = this._internals.states;\n for (const [event, toStates] of Object.entries(map)) {\n this.addEventListener(event, (e) => {\n const debug = this.hasAttribute(\"debug-states\");\n for (const [name, on] of Object.entries(toStates((e as CustomEvent).detail))) {\n try {\n if (on) { states.add(name); } else { states.delete(name); }\n } catch { /* never-throw */ }\n if (debug) this.toggleAttribute(`data-wcs-state-${name}`, on);\n }\n });\n }\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Attribute accessors ---\n\n get target(): string {\n return this.getAttribute(\"target\") ?? \"\";\n }\n\n set target(value: string) {\n this.setAttribute(\"target\", value);\n }\n\n // --- Core delegated getters ---\n\n get active(): boolean {\n return this._core.active;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n // --- Commands ---\n\n async requestPictureInPicture(): Promise<void> {\n const { element } = this._resolveVideoTarget();\n return this._core.requestPictureInPicture(element);\n }\n\n async exitPictureInPicture(): Promise<void> {\n return this._core.exitPictureInPicture();\n }\n\n // --- Internal ---\n\n /**\n * `_resolveTarget()`/`_safeQuery()` copied verbatim from `@wcstack/intersection`\n * (packages/intersection/src/components/Intersect.ts:243-267, 281-287) per the\n * fullscreen/picture-in-picture batch's shared target-resolution archetype\n * (docs/fullscreen-tag-design.md §1).\n */\n private _resolveTarget(): { element: Element | null; display: string } {\n const target = this.target;\n if (target === \"self\") {\n return { element: this, display: \"block\" };\n }\n if (target !== \"\") {\n const scope = this.getRootNode() as Document | ShadowRoot;\n return { element: this._safeQuery(scope, target), display: \"none\" };\n }\n const child = this.firstElementChild;\n if (child) {\n return { element: child, display: \"contents\" };\n }\n return { element: this, display: \"block\" };\n }\n\n private _safeQuery(scope: Document | ShadowRoot, selector: string): Element | null {\n try {\n return scope.querySelector(selector);\n } catch {\n return null;\n }\n }\n\n /**\n * Layers the Picture-in-Picture-specific `tagName === \"VIDEO\"` check on top\n * of `_resolveTarget()` (docs/picture-in-picture-tag-design.md §2). A\n * resolved-but-wrong-tag element is treated as unresolved (`element: null`)\n * so it flows into the same \"target not found\" failure path as Fullscreen's\n * missing-target case — never-throw, no exception escapes.\n */\n private _resolveVideoTarget(): { element: HTMLVideoElement | null; display: string } {\n const { element, display } = this._resolveTarget();\n if (element !== null && element.tagName !== \"VIDEO\") {\n return { element: null, display };\n }\n return { element: element as HTMLVideoElement | null, display };\n }\n\n private _observe(): void {\n const { element, display } = this._resolveVideoTarget();\n this.style.display = display;\n this._connectedCallbackPromise = this._core.observe(element);\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this._observe();\n }\n\n disconnectedCallback(): void {\n this._core.dispose();\n }\n\n attributeChangedCallback(_name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n if (!this.isConnected) return;\n this._observe();\n }\n}\n","import { WcsPip } from \"./components/Pip.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.pip)) {\n customElements.define(config.tagNames.pip, WcsPip);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapPip(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/config.ts","../src/core/pictureInPictureCapabilities.ts","../src/core/PipCore.ts","../src/components/Pip.ts","../src/registerComponents.ts","../src/bootstrapPip.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n tagNames: {\n pip: string;\n };\n}\n\nconst _config: IInternalConfig = {\n tagNames: {\n pip: \"wcs-pip\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","/**\n * pictureInPictureCapabilities.ts\n *\n * Picture-in-Picture node 固有の error code(taxonomy)と derivation。汎用の error\n * info 型は `./platformCapability.js`(/io-core/ から copy-distribution される生成\n * ファイル)から import する。Picture-in-Picture は referenced `<video>` を操作する\n * ノードで競合 operation を持たないため lane は無く、error taxonomy(errorInfo)のみを\n * 採用する(fullscreen と同型)。\n *\n * `_setError` は合成 `{ message }`(target が `<video>` に解決しない / API 非対応)と\n * caught 例外(`NotAllowedError` = user gesture 外の requestPictureInPicture 拒否等)を\n * 混在受理する。呼出側が明示 `kind` を渡して合成側を曖昧さ無く分類し、caught は `.name`\n * で分類する(fullscreen / storage / screen-orientation と同じ discriminator 方式)。\n */\n\nimport type { WcsIoErrorInfo } from \"./platformCapability.js\";\n\n/** 明示 kind discriminator(合成エラーの呼出側が渡す)。 */\nexport type PictureInPictureErrorKind = \"capability-missing\" | \"invalid-argument\";\n\n/** 安定した Picture-in-Picture error code(taxonomy)。値は公開キーとして固定。 */\nexport const WCS_PICTURE_IN_PICTURE_ERROR_CODE = {\n /** Picture-in-Picture API 非対応。 */\n CapabilityMissing: \"capability-missing\",\n /** target が `<video>` に解決しない等の入力不備。 */\n InvalidArgument: \"invalid-argument\",\n /** `NotAllowedError` / `TypeError` — user gesture 外での要求拒否。 */\n NotAllowed: \"not-allowed\",\n /** その他の caught 例外。 */\n PipError: \"pip-error\",\n} as const;\n\nfunction messageOf(error: unknown): string {\n return typeof (error as { message?: unknown } | null)?.message === \"string\"\n ? (error as { message: string }).message\n : String(error);\n}\n\n/**\n * Picture-in-Picture の失敗を serializable な error taxonomy に写す。`kind` は合成\n * エラーの呼出側が渡す明示 discriminator(`capability-missing` / `invalid-argument`)。\n * 未指定は caught 例外を意味し、`.name` で分類する。`NotAllowedError` / `TypeError` は\n * user gesture 内で再試行すれば成功しうるため recoverable=true。\n */\nexport function derivePictureInPictureErrorInfo(error: unknown, kind?: PictureInPictureErrorKind): WcsIoErrorInfo {\n const message = messageOf(error);\n if (kind === \"capability-missing\") {\n return { code: WCS_PICTURE_IN_PICTURE_ERROR_CODE.CapabilityMissing, phase: \"probe\", recoverable: false, message };\n }\n if (kind === \"invalid-argument\") {\n return { code: WCS_PICTURE_IN_PICTURE_ERROR_CODE.InvalidArgument, phase: \"start\", recoverable: false, message };\n }\n const name = (error as { name?: unknown } | null)?.name;\n if (name === \"NotAllowedError\" || name === \"TypeError\") {\n return { code: WCS_PICTURE_IN_PICTURE_ERROR_CODE.NotAllowed, phase: \"execute\", recoverable: true, message };\n }\n return { code: WCS_PICTURE_IN_PICTURE_ERROR_CODE.PipError, phase: \"execute\", recoverable: false, message };\n}\n","import { IWcBindable } from \"../types.js\";\nimport { WcsIoErrorInfo } from \"./platformCapability.js\";\nimport { derivePictureInPictureErrorInfo, PictureInPictureErrorKind } from \"./pictureInPictureCapabilities.js\";\n\n/**\n * Headless Picture-in-Picture primitive. A thin, framework-agnostic wrapper\n * around the classic Picture-in-Picture API\n * (`HTMLVideoElement.requestPictureInPicture()` / `document.exitPictureInPicture()` /\n * `document.pictureInPictureElement`) exposed through the wc-bindable protocol.\n *\n * This Core follows the same basic pattern as `@wcstack/fullscreen`'s\n * `FullscreenCore` (docs/fullscreen-tag-design.md): target resolution is done\n * by the Shell (this Core receives the resolved element at call time), API\n * resolution is call-time/non-cached, `_gen` is a single Core-level generation\n * guard, and `error` is a simple single field (no permission-style 4-value\n * state). See docs/picture-in-picture-tag-design.md for the differences from\n * Fullscreen:\n *\n * - **§2 target constraint**: the resolved target MUST be a `<video>` element.\n * Picture-in-Picture is only defined as an instance method of\n * `HTMLVideoElement` — unlike Fullscreen, which any `Element` supports. A\n * non-`<video>` target is a never-throw failure: it is treated the same as\n * an unresolved target and reported via `error`.\n * - **§3 event subscription target**: `enterpictureinpicture` /\n * `leavepictureinpicture` fire on the `<video>` element itself, not on\n * `document` (the reverse of Fullscreen's `document`-level\n * `fullscreenchange`). The Core attaches/detaches these listeners directly\n * on the resolved `<video>` element, re-wiring them whenever the target is\n * re-resolved (e.g. the Shell's `target` attribute changes).\n */\nexport class PipCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"active\", event: \"wcs-pip:change\", getter: (e: Event) => (e as CustomEvent).detail.active },\n // `error` / `errorInfo` are observable failure outputs. Historically `error`\n // was an imperative getter with no event; both are now bindable (event-backed)\n // so `data-wcs` / bind() can observe a request/exit failure. `errorInfo` is the\n // additive serializable taxonomy (stable code / phase / recoverable) derived\n // from `error`; the `error` value shape is unchanged. No lane — Picture-in-Picture\n // drives a referenced `<video>`, not a competing operation (fullscreen と同型)。\n { name: \"error\", event: \"wcs-pip:error\" },\n { name: \"errorInfo\", event: \"wcs-pip:error-info-changed\" },\n ],\n commands: [\n { name: \"requestPictureInPicture\", async: true },\n { name: \"exitPictureInPicture\", async: true },\n ],\n };\n\n private _target: EventTarget;\n private _active: boolean = false;\n private _error: any = null;\n private _errorInfo: WcsIoErrorInfo | null = null;\n\n // The <video> element the Core currently subscribes to for\n // enterpictureinpicture/leavepictureinpicture (null when unresolved/torn down).\n private _video: HTMLVideoElement | null = null;\n\n // Generation guard (§3.4 / fullscreen-tag-design.md §6): bumped on dispose()\n // and each async command start. A completion that lands after dispose() (or\n // after a superseding call) is stale and MUST NOT write state.\n private _gen = 0;\n\n // SSR (§3.8): no asynchronous probe to await, so readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get ready(): Promise<void> {\n return this._ready;\n }\n\n get active(): boolean {\n return this._active;\n }\n\n get error(): any {\n return this._error;\n }\n\n /**\n * The last failure's serializable `WcsIoErrorInfo` (stable `code` / `phase` /\n * `recoverable`), or null. Additive wc-bindable property (event\n * `wcs-pip:error-info-changed`), derived from `error`; the existing `error`\n * value shape is unchanged.\n */\n get errorInfo(): WcsIoErrorInfo | null {\n return this._errorInfo;\n }\n\n // --- Lifecycle (§3.5) ---\n\n /**\n * (Re-)subscribe to `enterpictureinpicture`/`leavepictureinpicture` on\n * `element` (the Shell's resolved `<video>` target). Idempotent when called\n * again with the same element; re-wires the listeners when the element\n * changes (e.g. the `target` attribute was changed), detaching from the\n * previous element first so no stale listener lingers.\n */\n observe(element: HTMLVideoElement | null): Promise<void> {\n if (this._video === element) {\n return this._ready;\n }\n this._detach();\n this._video = element;\n if (element) {\n element.addEventListener(\"enterpictureinpicture\", this._onEnter);\n element.addEventListener(\"leavepictureinpicture\", this._onLeave);\n }\n this._syncActive();\n return this._ready;\n }\n\n dispose(): void {\n this._gen++;\n this._detach();\n this._video = null;\n }\n\n // --- Commands (§3.6 never-throw) ---\n\n /**\n * Request Picture-in-Picture for `element`. `element` must be a `<video>`\n * (checked before the gesture-context failure path, since a type mismatch is\n * an environment-independent, permanent error — docs/picture-in-picture-tag-design.md §2).\n * Never throws: all failures (wrong tag, unsupported API, gesture-context\n * rejection) are funneled into `error` and the returned promise resolves.\n */\n async requestPictureInPicture(element: HTMLVideoElement | null): Promise<void> {\n const gen = ++this._gen;\n if (!element || element.tagName !== \"VIDEO\") {\n // Distinct from \"API is not supported\" (below): the resolved target did\n // not satisfy the `<video>`-only constraint (wrong tag / unresolved).\n this._setError({ message: \"target must be a <video> element.\" }, \"invalid-argument\");\n return;\n }\n // Re-wire to `element` before issuing the platform call: a caller may\n // request a <video> different from the one last passed to observe() (e.g.\n // the Shell's target attribute pointed at nothing at connect time and the\n // matching <video> was only inserted later, so no attributeChangedCallback\n // ever re-resolved it). Without this, `_video` stays stale and\n // `_syncActive()` below (and future enter/leave events) would never\n // recognize `element` as this Core's target, leaving `active` permanently\n // wrong even though the request succeeded (mirrors\n // FullscreenCore.requestFullscreen()'s unconditional `this._resolvedTarget\n // = element` assignment — docs/fullscreen-tag-design.md §6).\n this.observe(element);\n const fn = this._requestPictureInPictureFn(element);\n if (!fn) {\n this._setError({ message: \"Picture-in-Picture API is not supported.\" }, \"capability-missing\");\n return;\n }\n try {\n await fn.call(element);\n if (gen !== this._gen) return; // stale\n this._setError(null);\n this._syncActive(); // belt-and-suspenders (mirrors FullscreenCore's _applyActive() on success)\n } catch (e: any) {\n if (gen !== this._gen) return; // stale\n this._setError(e); // e.g. NotAllowedError (gesture-context rejection)\n }\n }\n\n /**\n * Exit Picture-in-Picture. Mirrors FullscreenCore.exitFullscreen(): a\n * silent no-op (resolve, no error) when nothing is currently in\n * Picture-in-Picture — see fullscreen-tag-design.md §7.\n */\n async exitPictureInPicture(): Promise<void> {\n // no-op checks come BEFORE the generation bump: a call that does nothing\n // must not supersede an in-flight requestPictureInPicture() — bumping\n // first would make the pending request's settle handling stale and\n // silently swallow its error update (mirrors\n // FullscreenCore.exitFullscreen()).\n if (this._pictureInPictureElement() === null) return; // already not in PiP: silent no-op\n const fn = this._exitPictureInPictureFn();\n if (!fn) return; // unsupported: silent no-op (semantically already \"not in PiP\")\n const gen = ++this._gen;\n try {\n await fn();\n if (gen !== this._gen) return;\n this._setError(null);\n this._syncActive(); // belt-and-suspenders (mirrors FullscreenCore.exitFullscreen()'s success-path _applyActive()); covers a delayed/dropped leavepictureinpicture\n } catch (e: any) {\n if (gen !== this._gen) return;\n this._setError(e);\n }\n }\n\n // --- Internal: API resolution (call-time, never cached — §3.7) ---\n\n // Unlike FullscreenCore's _elementFullscreenFn(), a naive direct property\n // lookup (`e.requestPictureInPicture`, walking the prototype chain) here is\n // safe: it cannot recurse into the Shell's own command method,\n // because the resolved target is validated to be a <video> element (§2)\n // before this is called, and <wcs-pip> (the Shell) is never itself a\n // <video>. Fullscreen's own→Element.prototype two-step resolution guards\n // against `target=\"self\"`/no-target resolving to the Shell element, which\n // cannot happen here.\n private _requestPictureInPictureFn(el: HTMLVideoElement): (() => Promise<PictureInPictureWindow>) | undefined {\n const e = el as any;\n return typeof e.requestPictureInPicture === \"function\" ? e.requestPictureInPicture : undefined;\n }\n\n private _exitPictureInPictureFn(): (() => Promise<void>) | undefined {\n const d = document as any;\n return typeof d.exitPictureInPicture === \"function\" ? d.exitPictureInPicture.bind(document) : undefined;\n }\n\n private _pictureInPictureElement(): Element | null {\n const d = document as any;\n return d.pictureInPictureElement ?? null;\n }\n\n // --- Internal: event wiring ---\n\n private _onEnter = (): void => {\n this._syncActive();\n };\n\n private _onLeave = (): void => {\n this._syncActive();\n };\n\n private _syncActive(): void {\n const isActive = this._video !== null && this._pictureInPictureElement() === this._video;\n this._setActive(isActive);\n }\n\n private _detach(): void {\n if (this._video) {\n this._video.removeEventListener(\"enterpictureinpicture\", this._onEnter);\n this._video.removeEventListener(\"leavepictureinpicture\", this._onLeave);\n }\n }\n\n // --- State setters with event dispatch (§3.3 same-value guard) ---\n\n private _setActive(active: boolean): void {\n if (this._active === active) return;\n this._active = active;\n this._target.dispatchEvent(new CustomEvent(\"wcs-pip:change\", {\n detail: { active },\n bubbles: true,\n }));\n }\n\n // `kind` is an explicit taxonomy discriminator passed only from the synthetic\n // error sites (unsupported / non-<video> target); caught exceptions pass no kind\n // and are classified by their `.name`. Both `error` and the additive `errorInfo`\n // are now event-backed so a request/exit failure is observable via bind().\n private _setError(error: any, kind?: PictureInPictureErrorKind): void {\n // Same-value guard on reference: each failure builds a fresh object and the\n // clear path passes the literal null, so this only suppresses redundant\n // null→null (a successful request/exit clearing an already-null error).\n if (this._error === error) return;\n this._error = error;\n // Keep the additive errorInfo taxonomy in sync; fire it before the `error`\n // event so an observer of both sees the classification first (io-node family).\n this._commitErrorInfo(error === null ? null : derivePictureInPictureErrorInfo(error, kind));\n this._target.dispatchEvent(new CustomEvent(\"wcs-pip:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n // Called only from _setError (already reference-guarded), so errorInfo\n // transitions exactly when error does — no separate guard needed here.\n private _commitErrorInfo(info: WcsIoErrorInfo | null): void {\n this._errorInfo = info;\n this._target.dispatchEvent(new CustomEvent(\"wcs-pip:error-info-changed\", {\n detail: info,\n bubbles: true,\n }));\n }\n}\n","import { IWcBindable } from \"../types.js\";\nimport { PipCore } from \"../core/PipCore.js\";\nimport { WcsIoErrorInfo } from \"../core/platformCapability.js\";\n\n/**\n * `<wcs-pip target=\"...\">` — declarative Picture-in-Picture control.\n *\n * Like `<wcs-fullscreen>` (docs/fullscreen-tag-design.md §0/§1), this Shell\n * does not operate on itself: it is a non-visible control tag that resolves a\n * `target` element and invokes Picture-in-Picture commands against it. The\n * `target` attribute resolves in the same 3 modes as `intersection`/`fullscreen`\n * (`self` / a selector / the first element child), reused verbatim from\n * `@wcstack/intersection`'s `_resolveTarget()`/`_safeQuery()`\n * (packages/intersection/src/components/Intersect.ts).\n *\n * Picture-in-Picture-specific difference (docs/picture-in-picture-tag-design.md\n * §2): the resolved target must be a `<video>` element. This Shell resolves the\n * DOM element and hands it to the Core; the Core performs the `tagName ===\n * \"VIDEO\"` validation (never-throw — a mismatch is treated as an unresolved\n * target and reported via `error`, not thrown).\n */\nexport class WcsPip extends HTMLElement {\n // SSR (§4.4): observe() completes synchronously, but the Shell still exposes\n // connectedCallbackPromise so the state binder can await it uniformly across\n // all IO nodes before snapshotting.\n static hasConnectedCallbackPromise = true;\n\n static observedAttributes = [\"target\"];\n\n static wcBindable: IWcBindable = {\n ...PipCore.wcBindable,\n inputs: [{ name: \"target\", attribute: \"target\" }],\n // Core の commands をそのまま継承(単一情報源)。fullscreen/intersection と同型。\n commands: PipCore.wcBindable.commands,\n };\n\n private _core: PipCore;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new PipCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n \"wcs-pip:change\": (d) => ({ active: d?.active === true }),\n });\n }\n\n // CSS state reflection (:state()) — debug-only snapshot getter. NOT part of\n // wc-bindable (not a bind target); see README \"CSS styling with :state()\".\n // MUST NOT return the live CustomStateSet (that would let callers write\n // states from outside, defeating the point of :state() being read-only).\n get debugStates(): string[] {\n return this._internals ? [...this._internals.states] : [];\n }\n\n private _initInternals(): ElementInternals | null {\n // never-throw (docs/custom-state-reflection-design.md §3.1): attachInternals\n // is absent in happy-dom / older environments, and pre-125 Chromium rejects\n // non-dashed state names from states.add() (probed and discarded here).\n // Either case silently disables reflection — the component still works,\n // it just doesn't expose :state() selectors.\n try {\n if (typeof this.attachInternals !== \"function\") return null;\n const internals = this.attachInternals();\n internals.states.add(\"wcs-probe\");\n internals.states.delete(\"wcs-probe\");\n return internals;\n } catch {\n return null;\n }\n }\n\n private _wireStates(map: Record<string, (detail: any) => Record<string, boolean>>): void {\n if (this._internals === null) return;\n const states = this._internals.states;\n for (const [event, toStates] of Object.entries(map)) {\n this.addEventListener(event, (e) => {\n const debug = this.hasAttribute(\"debug-states\");\n for (const [name, on] of Object.entries(toStates((e as CustomEvent).detail))) {\n try {\n if (on) { states.add(name); } else { states.delete(name); }\n } catch { /* never-throw */ }\n if (debug) this.toggleAttribute(`data-wcs-state-${name}`, on);\n }\n });\n }\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Attribute accessors ---\n\n get target(): string {\n return this.getAttribute(\"target\") ?? \"\";\n }\n\n set target(value: string) {\n this.setAttribute(\"target\", value);\n }\n\n // --- Core delegated getters ---\n\n get active(): boolean {\n return this._core.active;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n get errorInfo(): WcsIoErrorInfo | null {\n return this._core.errorInfo;\n }\n\n // --- Commands ---\n\n async requestPictureInPicture(): Promise<void> {\n const { element } = this._resolveVideoTarget();\n return this._core.requestPictureInPicture(element);\n }\n\n async exitPictureInPicture(): Promise<void> {\n return this._core.exitPictureInPicture();\n }\n\n // --- Internal ---\n\n /**\n * `_resolveTarget()`/`_safeQuery()` copied verbatim from `@wcstack/intersection`\n * (packages/intersection/src/components/Intersect.ts:243-267, 281-287) per the\n * fullscreen/picture-in-picture batch's shared target-resolution archetype\n * (docs/fullscreen-tag-design.md §1).\n */\n private _resolveTarget(): { element: Element | null; display: string } {\n const target = this.target;\n if (target === \"self\") {\n return { element: this, display: \"block\" };\n }\n if (target !== \"\") {\n const scope = this.getRootNode() as Document | ShadowRoot;\n return { element: this._safeQuery(scope, target), display: \"none\" };\n }\n const child = this.firstElementChild;\n if (child) {\n return { element: child, display: \"contents\" };\n }\n return { element: this, display: \"block\" };\n }\n\n private _safeQuery(scope: Document | ShadowRoot, selector: string): Element | null {\n try {\n return scope.querySelector(selector);\n } catch {\n return null;\n }\n }\n\n /**\n * Layers the Picture-in-Picture-specific `tagName === \"VIDEO\"` check on top\n * of `_resolveTarget()` (docs/picture-in-picture-tag-design.md §2). A\n * resolved-but-wrong-tag element is treated as unresolved (`element: null`)\n * so it flows into the same \"target not found\" failure path as Fullscreen's\n * missing-target case — never-throw, no exception escapes.\n */\n private _resolveVideoTarget(): { element: HTMLVideoElement | null; display: string } {\n const { element, display } = this._resolveTarget();\n if (element !== null && element.tagName !== \"VIDEO\") {\n return { element: null, display };\n }\n return { element: element as HTMLVideoElement | null, display };\n }\n\n private _observe(): void {\n const { element, display } = this._resolveVideoTarget();\n this.style.display = display;\n this._connectedCallbackPromise = this._core.observe(element);\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this._observe();\n }\n\n disconnectedCallback(): void {\n this._core.dispose();\n }\n\n attributeChangedCallback(_name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n if (!this.isConnected) return;\n this._observe();\n }\n}\n","import { WcsPip } from \"./components/Pip.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.pip)) {\n customElements.define(config.tagNames.pip, WcsPip);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapPip(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n"],"names":[],"mappings":"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"}
|
package/dist/index.esm.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e={tagNames:{pip:"wcs-pip"}};function t(e){if(null===e||"object"!=typeof e)return e;Object.freeze(e);for(const r of Object.keys(e))t(e[r]);return e}function r(e){if(null===e||"object"!=typeof e)return e;const t={};for(const i of Object.keys(e))t[i]=r(e[i]);return t}let i=null;const
|
|
1
|
+
const e={tagNames:{pip:"wcs-pip"}};function t(e){if(null===e||"object"!=typeof e)return e;Object.freeze(e);for(const r of Object.keys(e))t(e[r]);return e}function r(e){if(null===e||"object"!=typeof e)return e;const t={};for(const i of Object.keys(e))t[i]=r(e[i]);return t}let i=null;const n=e;function s(){return i||(i=t(r(e))),i}const c={CapabilityMissing:"capability-missing",InvalidArgument:"invalid-argument",NotAllowed:"not-allowed",PipError:"pip-error"};function o(e,t){const r=function(e){return"string"==typeof e?.message?e.message:String(e)}(e);if("capability-missing"===t)return{code:c.CapabilityMissing,phase:"probe",recoverable:!1,message:r};if("invalid-argument"===t)return{code:c.InvalidArgument,phase:"start",recoverable:!1,message:r};const i=e?.name;return"NotAllowedError"===i||"TypeError"===i?{code:c.NotAllowed,phase:"execute",recoverable:!0,message:r}:{code:c.PipError,phase:"execute",recoverable:!1,message:r}}class a extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"active",event:"wcs-pip:change",getter:e=>e.detail.active},{name:"error",event:"wcs-pip:error"},{name:"errorInfo",event:"wcs-pip:error-info-changed"}],commands:[{name:"requestPictureInPicture",async:!0},{name:"exitPictureInPicture",async:!0}]};_target;_active=!1;_error=null;_errorInfo=null;_video=null;_gen=0;_ready=Promise.resolve();constructor(e){super(),this._target=e??this}get ready(){return this._ready}get active(){return this._active}get error(){return this._error}get errorInfo(){return this._errorInfo}observe(e){return this._video===e||(this._detach(),this._video=e,e&&(e.addEventListener("enterpictureinpicture",this._onEnter),e.addEventListener("leavepictureinpicture",this._onLeave)),this._syncActive()),this._ready}dispose(){this._gen++,this._detach(),this._video=null}async requestPictureInPicture(e){const t=++this._gen;if(!e||"VIDEO"!==e.tagName)return void this._setError({message:"target must be a <video> element."},"invalid-argument");this.observe(e);const r=this._requestPictureInPictureFn(e);if(r)try{if(await r.call(e),t!==this._gen)return;this._setError(null),this._syncActive()}catch(e){if(t!==this._gen)return;this._setError(e)}else this._setError({message:"Picture-in-Picture API is not supported."},"capability-missing")}async exitPictureInPicture(){if(null===this._pictureInPictureElement())return;const e=this._exitPictureInPictureFn();if(!e)return;const t=++this._gen;try{if(await e(),t!==this._gen)return;this._setError(null),this._syncActive()}catch(e){if(t!==this._gen)return;this._setError(e)}}_requestPictureInPictureFn(e){const t=e;return"function"==typeof t.requestPictureInPicture?t.requestPictureInPicture:void 0}_exitPictureInPictureFn(){const e=document;return"function"==typeof e.exitPictureInPicture?e.exitPictureInPicture.bind(document):void 0}_pictureInPictureElement(){return document.pictureInPictureElement??null}_onEnter=()=>{this._syncActive()};_onLeave=()=>{this._syncActive()};_syncActive(){const e=null!==this._video&&this._pictureInPictureElement()===this._video;this._setActive(e)}_detach(){this._video&&(this._video.removeEventListener("enterpictureinpicture",this._onEnter),this._video.removeEventListener("leavepictureinpicture",this._onLeave))}_setActive(e){this._active!==e&&(this._active=e,this._target.dispatchEvent(new CustomEvent("wcs-pip:change",{detail:{active:e},bubbles:!0})))}_setError(e,t){this._error!==e&&(this._error=e,this._commitErrorInfo(null===e?null:o(e,t)),this._target.dispatchEvent(new CustomEvent("wcs-pip:error",{detail:e,bubbles:!0})))}_commitErrorInfo(e){this._errorInfo=e,this._target.dispatchEvent(new CustomEvent("wcs-pip:error-info-changed",{detail:e,bubbles:!0}))}}class u extends HTMLElement{static hasConnectedCallbackPromise=!0;static observedAttributes=["target"];static wcBindable={...a.wcBindable,inputs:[{name:"target",attribute:"target"}],commands:a.wcBindable.commands};_core;_connectedCallbackPromise=Promise.resolve();_internals=null;constructor(){super(),this._core=new a(this),this._internals=this._initInternals(),this._wireStates({"wcs-pip:change":e=>({active:!0===e?.active})})}get debugStates(){return this._internals?[...this._internals.states]:[]}_initInternals(){try{if("function"!=typeof this.attachInternals)return null;const e=this.attachInternals();return e.states.add("wcs-probe"),e.states.delete("wcs-probe"),e}catch{return null}}_wireStates(e){if(null===this._internals)return;const t=this._internals.states;for(const[r,i]of Object.entries(e))this.addEventListener(r,e=>{const r=this.hasAttribute("debug-states");for(const[n,s]of Object.entries(i(e.detail))){try{s?t.add(n):t.delete(n)}catch{}r&&this.toggleAttribute(`data-wcs-state-${n}`,s)}})}get connectedCallbackPromise(){return this._connectedCallbackPromise}get target(){return this.getAttribute("target")??""}set target(e){this.setAttribute("target",e)}get active(){return this._core.active}get error(){return this._core.error}get errorInfo(){return this._core.errorInfo}async requestPictureInPicture(){const{element:e}=this._resolveVideoTarget();return this._core.requestPictureInPicture(e)}async exitPictureInPicture(){return this._core.exitPictureInPicture()}_resolveTarget(){const e=this.target;if("self"===e)return{element:this,display:"block"};if(""!==e){const t=this.getRootNode();return{element:this._safeQuery(t,e),display:"none"}}const t=this.firstElementChild;return t?{element:t,display:"contents"}:{element:this,display:"block"}}_safeQuery(e,t){try{return e.querySelector(t)}catch{return null}}_resolveVideoTarget(){const{element:e,display:t}=this._resolveTarget();return null!==e&&"VIDEO"!==e.tagName?{element:null,display:t}:{element:e,display:t}}_observe(){const{element:e,display:t}=this._resolveVideoTarget();this.style.display=t,this._connectedCallbackPromise=this._core.observe(e)}connectedCallback(){this._observe()}disconnectedCallback(){this._core.dispose()}attributeChangedCallback(e,t,r){t!==r&&this.isConnected&&this._observe()}}function l(t){var r;t&&((r=t).tagNames&&Object.assign(e.tagNames,r.tagNames),i=null),customElements.get(n.tagNames.pip)||customElements.define(n.tagNames.pip,u)}export{a as PipCore,c as WCS_PICTURE_IN_PICTURE_ERROR_CODE,u as WcsPip,l as bootstrapPip,s as getConfig};
|
|
2
2
|
//# sourceMappingURL=index.esm.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.min.js","sources":["../src/config.ts","../src/core/PipCore.ts","../src/components/Pip.ts","../src/bootstrapPip.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n tagNames: {\n pip: string;\n };\n}\n\nconst _config: IInternalConfig = {\n tagNames: {\n pip: \"wcs-pip\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { IWcBindable } from \"../types.js\";\n\n/**\n * Headless Picture-in-Picture primitive. A thin, framework-agnostic wrapper\n * around the classic Picture-in-Picture API\n * (`HTMLVideoElement.requestPictureInPicture()` / `document.exitPictureInPicture()` /\n * `document.pictureInPictureElement`) exposed through the wc-bindable protocol.\n *\n * This Core follows the same basic pattern as `@wcstack/fullscreen`'s\n * `FullscreenCore` (docs/fullscreen-tag-design.md): target resolution is done\n * by the Shell (this Core receives the resolved element at call time), API\n * resolution is call-time/non-cached, `_gen` is a single Core-level generation\n * guard, and `error` is a simple single field (no permission-style 4-value\n * state). See docs/picture-in-picture-tag-design.md for the differences from\n * Fullscreen:\n *\n * - **§2 target constraint**: the resolved target MUST be a `<video>` element.\n * Picture-in-Picture is only defined as an instance method of\n * `HTMLVideoElement` — unlike Fullscreen, which any `Element` supports. A\n * non-`<video>` target is a never-throw failure: it is treated the same as\n * an unresolved target and reported via `error`.\n * - **§3 event subscription target**: `enterpictureinpicture` /\n * `leavepictureinpicture` fire on the `<video>` element itself, not on\n * `document` (the reverse of Fullscreen's `document`-level\n * `fullscreenchange`). The Core attaches/detaches these listeners directly\n * on the resolved `<video>` element, re-wiring them whenever the target is\n * re-resolved (e.g. the Shell's `target` attribute changes).\n */\nexport class PipCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"active\", event: \"wcs-pip:change\", getter: (e: Event) => (e as CustomEvent).detail.active },\n ],\n commands: [\n { name: \"requestPictureInPicture\", async: true },\n { name: \"exitPictureInPicture\", async: true },\n ],\n };\n\n private _target: EventTarget;\n private _active: boolean = false;\n private _error: any = null;\n\n // The <video> element the Core currently subscribes to for\n // enterpictureinpicture/leavepictureinpicture (null when unresolved/torn down).\n private _video: HTMLVideoElement | null = null;\n\n // Generation guard (§3.4 / fullscreen-tag-design.md §6): bumped on dispose()\n // and each async command start. A completion that lands after dispose() (or\n // after a superseding call) is stale and MUST NOT write state.\n private _gen = 0;\n\n // SSR (§3.8): no asynchronous probe to await, so readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get ready(): Promise<void> {\n return this._ready;\n }\n\n get active(): boolean {\n return this._active;\n }\n\n get error(): any {\n return this._error;\n }\n\n // --- Lifecycle (§3.5) ---\n\n /**\n * (Re-)subscribe to `enterpictureinpicture`/`leavepictureinpicture` on\n * `element` (the Shell's resolved `<video>` target). Idempotent when called\n * again with the same element; re-wires the listeners when the element\n * changes (e.g. the `target` attribute was changed), detaching from the\n * previous element first so no stale listener lingers.\n */\n observe(element: HTMLVideoElement | null): Promise<void> {\n if (this._video === element) {\n return this._ready;\n }\n this._detach();\n this._video = element;\n if (element) {\n element.addEventListener(\"enterpictureinpicture\", this._onEnter);\n element.addEventListener(\"leavepictureinpicture\", this._onLeave);\n }\n this._syncActive();\n return this._ready;\n }\n\n dispose(): void {\n this._gen++;\n this._detach();\n this._video = null;\n }\n\n // --- Commands (§3.6 never-throw) ---\n\n /**\n * Request Picture-in-Picture for `element`. `element` must be a `<video>`\n * (checked before the gesture-context failure path, since a type mismatch is\n * an environment-independent, permanent error — docs/picture-in-picture-tag-design.md §2).\n * Never throws: all failures (wrong tag, unsupported API, gesture-context\n * rejection) are funneled into `error` and the returned promise resolves.\n */\n async requestPictureInPicture(element: HTMLVideoElement | null): Promise<void> {\n const gen = ++this._gen;\n if (!element || element.tagName !== \"VIDEO\") {\n this._setError({ message: \"target must be a <video> element.\" });\n return;\n }\n // Re-wire to `element` before issuing the platform call: a caller may\n // request a <video> different from the one last passed to observe() (e.g.\n // the Shell's target attribute pointed at nothing at connect time and the\n // matching <video> was only inserted later, so no attributeChangedCallback\n // ever re-resolved it). Without this, `_video` stays stale and\n // `_syncActive()` below (and future enter/leave events) would never\n // recognize `element` as this Core's target, leaving `active` permanently\n // wrong even though the request succeeded (mirrors\n // FullscreenCore.requestFullscreen()'s unconditional `this._resolvedTarget\n // = element` assignment — docs/fullscreen-tag-design.md §6).\n this.observe(element);\n const fn = this._requestPictureInPictureFn(element);\n if (!fn) {\n this._setError({ message: \"Picture-in-Picture API is not supported.\" });\n return;\n }\n try {\n await fn.call(element);\n if (gen !== this._gen) return; // stale\n this._setError(null);\n this._syncActive(); // belt-and-suspenders (mirrors FullscreenCore's _applyActive() on success)\n } catch (e: any) {\n if (gen !== this._gen) return; // stale\n this._setError(e); // e.g. NotAllowedError (gesture-context rejection)\n }\n }\n\n /**\n * Exit Picture-in-Picture. Mirrors FullscreenCore.exitFullscreen(): a\n * silent no-op (resolve, no error) when nothing is currently in\n * Picture-in-Picture — see fullscreen-tag-design.md §7.\n */\n async exitPictureInPicture(): Promise<void> {\n // no-op checks come BEFORE the generation bump: a call that does nothing\n // must not supersede an in-flight requestPictureInPicture() — bumping\n // first would make the pending request's settle handling stale and\n // silently swallow its error update (mirrors\n // FullscreenCore.exitFullscreen()).\n if (this._pictureInPictureElement() === null) return; // already not in PiP: silent no-op\n const fn = this._exitPictureInPictureFn();\n if (!fn) return; // unsupported: silent no-op (semantically already \"not in PiP\")\n const gen = ++this._gen;\n try {\n await fn();\n if (gen !== this._gen) return;\n this._setError(null);\n this._syncActive(); // belt-and-suspenders (mirrors FullscreenCore.exitFullscreen()'s success-path _applyActive()); covers a delayed/dropped leavepictureinpicture\n } catch (e: any) {\n if (gen !== this._gen) return;\n this._setError(e);\n }\n }\n\n // --- Internal: API resolution (call-time, never cached — §3.7) ---\n\n // Unlike FullscreenCore's _elementFullscreenFn(), a naive direct property\n // lookup (`e.requestPictureInPicture`, walking the prototype chain) here is\n // safe: it cannot recurse into the Shell's own command method,\n // because the resolved target is validated to be a <video> element (§2)\n // before this is called, and <wcs-pip> (the Shell) is never itself a\n // <video>. Fullscreen's own→Element.prototype two-step resolution guards\n // against `target=\"self\"`/no-target resolving to the Shell element, which\n // cannot happen here.\n private _requestPictureInPictureFn(el: HTMLVideoElement): (() => Promise<PictureInPictureWindow>) | undefined {\n const e = el as any;\n return typeof e.requestPictureInPicture === \"function\" ? e.requestPictureInPicture : undefined;\n }\n\n private _exitPictureInPictureFn(): (() => Promise<void>) | undefined {\n const d = document as any;\n return typeof d.exitPictureInPicture === \"function\" ? d.exitPictureInPicture.bind(document) : undefined;\n }\n\n private _pictureInPictureElement(): Element | null {\n const d = document as any;\n return d.pictureInPictureElement ?? null;\n }\n\n // --- Internal: event wiring ---\n\n private _onEnter = (): void => {\n this._syncActive();\n };\n\n private _onLeave = (): void => {\n this._syncActive();\n };\n\n private _syncActive(): void {\n const isActive = this._video !== null && this._pictureInPictureElement() === this._video;\n this._setActive(isActive);\n }\n\n private _detach(): void {\n if (this._video) {\n this._video.removeEventListener(\"enterpictureinpicture\", this._onEnter);\n this._video.removeEventListener(\"leavepictureinpicture\", this._onLeave);\n }\n }\n\n // --- State setters with event dispatch (§3.3 same-value guard) ---\n\n private _setActive(active: boolean): void {\n if (this._active === active) return;\n this._active = active;\n this._target.dispatchEvent(new CustomEvent(\"wcs-pip:change\", {\n detail: { active },\n bubbles: true,\n }));\n }\n\n private _setError(error: any): void {\n this._error = error;\n }\n}\n","import { IWcBindable } from \"../types.js\";\nimport { PipCore } from \"../core/PipCore.js\";\n\n/**\n * `<wcs-pip target=\"...\">` — declarative Picture-in-Picture control.\n *\n * Like `<wcs-fullscreen>` (docs/fullscreen-tag-design.md §0/§1), this Shell\n * does not operate on itself: it is a non-visible control tag that resolves a\n * `target` element and invokes Picture-in-Picture commands against it. The\n * `target` attribute resolves in the same 3 modes as `intersection`/`fullscreen`\n * (`self` / a selector / the first element child), reused verbatim from\n * `@wcstack/intersection`'s `_resolveTarget()`/`_safeQuery()`\n * (packages/intersection/src/components/Intersect.ts).\n *\n * Picture-in-Picture-specific difference (docs/picture-in-picture-tag-design.md\n * §2): the resolved target must be a `<video>` element. This Shell resolves the\n * DOM element and hands it to the Core; the Core performs the `tagName ===\n * \"VIDEO\"` validation (never-throw — a mismatch is treated as an unresolved\n * target and reported via `error`, not thrown).\n */\nexport class WcsPip extends HTMLElement {\n // SSR (§4.4): observe() completes synchronously, but the Shell still exposes\n // connectedCallbackPromise so the state binder can await it uniformly across\n // all IO nodes before snapshotting.\n static hasConnectedCallbackPromise = true;\n\n static observedAttributes = [\"target\"];\n\n static wcBindable: IWcBindable = {\n ...PipCore.wcBindable,\n inputs: [{ name: \"target\", attribute: \"target\" }],\n // Core の commands をそのまま継承(単一情報源)。fullscreen/intersection と同型。\n commands: PipCore.wcBindable.commands,\n };\n\n private _core: PipCore;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new PipCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n \"wcs-pip:change\": (d) => ({ active: d?.active === true }),\n });\n }\n\n // CSS state reflection (:state()) — debug-only snapshot getter. NOT part of\n // wc-bindable (not a bind target); see README \"CSS styling with :state()\".\n // MUST NOT return the live CustomStateSet (that would let callers write\n // states from outside, defeating the point of :state() being read-only).\n get debugStates(): string[] {\n return this._internals ? [...this._internals.states] : [];\n }\n\n private _initInternals(): ElementInternals | null {\n // never-throw (docs/custom-state-reflection-design.md §3.1): attachInternals\n // is absent in happy-dom / older environments, and pre-125 Chromium rejects\n // non-dashed state names from states.add() (probed and discarded here).\n // Either case silently disables reflection — the component still works,\n // it just doesn't expose :state() selectors.\n try {\n if (typeof this.attachInternals !== \"function\") return null;\n const internals = this.attachInternals();\n internals.states.add(\"wcs-probe\");\n internals.states.delete(\"wcs-probe\");\n return internals;\n } catch {\n return null;\n }\n }\n\n private _wireStates(map: Record<string, (detail: any) => Record<string, boolean>>): void {\n if (this._internals === null) return;\n const states = this._internals.states;\n for (const [event, toStates] of Object.entries(map)) {\n this.addEventListener(event, (e) => {\n const debug = this.hasAttribute(\"debug-states\");\n for (const [name, on] of Object.entries(toStates((e as CustomEvent).detail))) {\n try {\n if (on) { states.add(name); } else { states.delete(name); }\n } catch { /* never-throw */ }\n if (debug) this.toggleAttribute(`data-wcs-state-${name}`, on);\n }\n });\n }\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Attribute accessors ---\n\n get target(): string {\n return this.getAttribute(\"target\") ?? \"\";\n }\n\n set target(value: string) {\n this.setAttribute(\"target\", value);\n }\n\n // --- Core delegated getters ---\n\n get active(): boolean {\n return this._core.active;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n // --- Commands ---\n\n async requestPictureInPicture(): Promise<void> {\n const { element } = this._resolveVideoTarget();\n return this._core.requestPictureInPicture(element);\n }\n\n async exitPictureInPicture(): Promise<void> {\n return this._core.exitPictureInPicture();\n }\n\n // --- Internal ---\n\n /**\n * `_resolveTarget()`/`_safeQuery()` copied verbatim from `@wcstack/intersection`\n * (packages/intersection/src/components/Intersect.ts:243-267, 281-287) per the\n * fullscreen/picture-in-picture batch's shared target-resolution archetype\n * (docs/fullscreen-tag-design.md §1).\n */\n private _resolveTarget(): { element: Element | null; display: string } {\n const target = this.target;\n if (target === \"self\") {\n return { element: this, display: \"block\" };\n }\n if (target !== \"\") {\n const scope = this.getRootNode() as Document | ShadowRoot;\n return { element: this._safeQuery(scope, target), display: \"none\" };\n }\n const child = this.firstElementChild;\n if (child) {\n return { element: child, display: \"contents\" };\n }\n return { element: this, display: \"block\" };\n }\n\n private _safeQuery(scope: Document | ShadowRoot, selector: string): Element | null {\n try {\n return scope.querySelector(selector);\n } catch {\n return null;\n }\n }\n\n /**\n * Layers the Picture-in-Picture-specific `tagName === \"VIDEO\"` check on top\n * of `_resolveTarget()` (docs/picture-in-picture-tag-design.md §2). A\n * resolved-but-wrong-tag element is treated as unresolved (`element: null`)\n * so it flows into the same \"target not found\" failure path as Fullscreen's\n * missing-target case — never-throw, no exception escapes.\n */\n private _resolveVideoTarget(): { element: HTMLVideoElement | null; display: string } {\n const { element, display } = this._resolveTarget();\n if (element !== null && element.tagName !== \"VIDEO\") {\n return { element: null, display };\n }\n return { element: element as HTMLVideoElement | null, display };\n }\n\n private _observe(): void {\n const { element, display } = this._resolveVideoTarget();\n this.style.display = display;\n this._connectedCallbackPromise = this._core.observe(element);\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this._observe();\n }\n\n disconnectedCallback(): void {\n this._core.dispose();\n }\n\n attributeChangedCallback(_name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n if (!this.isConnected) return;\n this._observe();\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapPip(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n","import { WcsPip } from \"./components/Pip.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.pip)) {\n customElements.define(config.tagNames.pip, WcsPip);\n }\n}\n"],"names":["_config","tagNames","pip","deepFreeze","obj","Object","freeze","key","keys","deepClone","clone","frozenConfig","config","getConfig","PipCore","EventTarget","static","protocol","version","properties","name","event","getter","e","detail","active","commands","async","_target","_active","_error","_video","_gen","_ready","Promise","resolve","constructor","target","super","this","ready","error","observe","element","_detach","addEventListener","_onEnter","_onLeave","_syncActive","dispose","requestPictureInPicture","gen","tagName","_setError","message","fn","_requestPictureInPictureFn","call","exitPictureInPicture","_pictureInPictureElement","_exitPictureInPictureFn","el","undefined","d","document","bind","pictureInPictureElement","isActive","_setActive","removeEventListener","dispatchEvent","CustomEvent","bubbles","WcsPip","HTMLElement","wcBindable","inputs","attribute","_core","_connectedCallbackPromise","_internals","_initInternals","_wireStates","debugStates","states","attachInternals","internals","add","delete","map","toStates","entries","debug","hasAttribute","on","toggleAttribute","connectedCallbackPromise","getAttribute","value","setAttribute","_resolveVideoTarget","_resolveTarget","display","scope","getRootNode","_safeQuery","child","firstElementChild","selector","querySelector","_observe","style","connectedCallback","disconnectedCallback","attributeChangedCallback","_name","oldValue","newValue","isConnected","bootstrapPip","userConfig","partialConfig","assign","customElements","get","define"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.esm.min.js","sources":["../src/config.ts","../src/core/pictureInPictureCapabilities.ts","../src/core/PipCore.ts","../src/components/Pip.ts","../src/bootstrapPip.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n tagNames: {\n pip: string;\n };\n}\n\nconst _config: IInternalConfig = {\n tagNames: {\n pip: \"wcs-pip\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","/**\n * pictureInPictureCapabilities.ts\n *\n * Picture-in-Picture node 固有の error code(taxonomy)と derivation。汎用の error\n * info 型は `./platformCapability.js`(/io-core/ から copy-distribution される生成\n * ファイル)から import する。Picture-in-Picture は referenced `<video>` を操作する\n * ノードで競合 operation を持たないため lane は無く、error taxonomy(errorInfo)のみを\n * 採用する(fullscreen と同型)。\n *\n * `_setError` は合成 `{ message }`(target が `<video>` に解決しない / API 非対応)と\n * caught 例外(`NotAllowedError` = user gesture 外の requestPictureInPicture 拒否等)を\n * 混在受理する。呼出側が明示 `kind` を渡して合成側を曖昧さ無く分類し、caught は `.name`\n * で分類する(fullscreen / storage / screen-orientation と同じ discriminator 方式)。\n */\n\nimport type { WcsIoErrorInfo } from \"./platformCapability.js\";\n\n/** 明示 kind discriminator(合成エラーの呼出側が渡す)。 */\nexport type PictureInPictureErrorKind = \"capability-missing\" | \"invalid-argument\";\n\n/** 安定した Picture-in-Picture error code(taxonomy)。値は公開キーとして固定。 */\nexport const WCS_PICTURE_IN_PICTURE_ERROR_CODE = {\n /** Picture-in-Picture API 非対応。 */\n CapabilityMissing: \"capability-missing\",\n /** target が `<video>` に解決しない等の入力不備。 */\n InvalidArgument: \"invalid-argument\",\n /** `NotAllowedError` / `TypeError` — user gesture 外での要求拒否。 */\n NotAllowed: \"not-allowed\",\n /** その他の caught 例外。 */\n PipError: \"pip-error\",\n} as const;\n\nfunction messageOf(error: unknown): string {\n return typeof (error as { message?: unknown } | null)?.message === \"string\"\n ? (error as { message: string }).message\n : String(error);\n}\n\n/**\n * Picture-in-Picture の失敗を serializable な error taxonomy に写す。`kind` は合成\n * エラーの呼出側が渡す明示 discriminator(`capability-missing` / `invalid-argument`)。\n * 未指定は caught 例外を意味し、`.name` で分類する。`NotAllowedError` / `TypeError` は\n * user gesture 内で再試行すれば成功しうるため recoverable=true。\n */\nexport function derivePictureInPictureErrorInfo(error: unknown, kind?: PictureInPictureErrorKind): WcsIoErrorInfo {\n const message = messageOf(error);\n if (kind === \"capability-missing\") {\n return { code: WCS_PICTURE_IN_PICTURE_ERROR_CODE.CapabilityMissing, phase: \"probe\", recoverable: false, message };\n }\n if (kind === \"invalid-argument\") {\n return { code: WCS_PICTURE_IN_PICTURE_ERROR_CODE.InvalidArgument, phase: \"start\", recoverable: false, message };\n }\n const name = (error as { name?: unknown } | null)?.name;\n if (name === \"NotAllowedError\" || name === \"TypeError\") {\n return { code: WCS_PICTURE_IN_PICTURE_ERROR_CODE.NotAllowed, phase: \"execute\", recoverable: true, message };\n }\n return { code: WCS_PICTURE_IN_PICTURE_ERROR_CODE.PipError, phase: \"execute\", recoverable: false, message };\n}\n","import { IWcBindable } from \"../types.js\";\nimport { WcsIoErrorInfo } from \"./platformCapability.js\";\nimport { derivePictureInPictureErrorInfo, PictureInPictureErrorKind } from \"./pictureInPictureCapabilities.js\";\n\n/**\n * Headless Picture-in-Picture primitive. A thin, framework-agnostic wrapper\n * around the classic Picture-in-Picture API\n * (`HTMLVideoElement.requestPictureInPicture()` / `document.exitPictureInPicture()` /\n * `document.pictureInPictureElement`) exposed through the wc-bindable protocol.\n *\n * This Core follows the same basic pattern as `@wcstack/fullscreen`'s\n * `FullscreenCore` (docs/fullscreen-tag-design.md): target resolution is done\n * by the Shell (this Core receives the resolved element at call time), API\n * resolution is call-time/non-cached, `_gen` is a single Core-level generation\n * guard, and `error` is a simple single field (no permission-style 4-value\n * state). See docs/picture-in-picture-tag-design.md for the differences from\n * Fullscreen:\n *\n * - **§2 target constraint**: the resolved target MUST be a `<video>` element.\n * Picture-in-Picture is only defined as an instance method of\n * `HTMLVideoElement` — unlike Fullscreen, which any `Element` supports. A\n * non-`<video>` target is a never-throw failure: it is treated the same as\n * an unresolved target and reported via `error`.\n * - **§3 event subscription target**: `enterpictureinpicture` /\n * `leavepictureinpicture` fire on the `<video>` element itself, not on\n * `document` (the reverse of Fullscreen's `document`-level\n * `fullscreenchange`). The Core attaches/detaches these listeners directly\n * on the resolved `<video>` element, re-wiring them whenever the target is\n * re-resolved (e.g. the Shell's `target` attribute changes).\n */\nexport class PipCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"active\", event: \"wcs-pip:change\", getter: (e: Event) => (e as CustomEvent).detail.active },\n // `error` / `errorInfo` are observable failure outputs. Historically `error`\n // was an imperative getter with no event; both are now bindable (event-backed)\n // so `data-wcs` / bind() can observe a request/exit failure. `errorInfo` is the\n // additive serializable taxonomy (stable code / phase / recoverable) derived\n // from `error`; the `error` value shape is unchanged. No lane — Picture-in-Picture\n // drives a referenced `<video>`, not a competing operation (fullscreen と同型)。\n { name: \"error\", event: \"wcs-pip:error\" },\n { name: \"errorInfo\", event: \"wcs-pip:error-info-changed\" },\n ],\n commands: [\n { name: \"requestPictureInPicture\", async: true },\n { name: \"exitPictureInPicture\", async: true },\n ],\n };\n\n private _target: EventTarget;\n private _active: boolean = false;\n private _error: any = null;\n private _errorInfo: WcsIoErrorInfo | null = null;\n\n // The <video> element the Core currently subscribes to for\n // enterpictureinpicture/leavepictureinpicture (null when unresolved/torn down).\n private _video: HTMLVideoElement | null = null;\n\n // Generation guard (§3.4 / fullscreen-tag-design.md §6): bumped on dispose()\n // and each async command start. A completion that lands after dispose() (or\n // after a superseding call) is stale and MUST NOT write state.\n private _gen = 0;\n\n // SSR (§3.8): no asynchronous probe to await, so readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get ready(): Promise<void> {\n return this._ready;\n }\n\n get active(): boolean {\n return this._active;\n }\n\n get error(): any {\n return this._error;\n }\n\n /**\n * The last failure's serializable `WcsIoErrorInfo` (stable `code` / `phase` /\n * `recoverable`), or null. Additive wc-bindable property (event\n * `wcs-pip:error-info-changed`), derived from `error`; the existing `error`\n * value shape is unchanged.\n */\n get errorInfo(): WcsIoErrorInfo | null {\n return this._errorInfo;\n }\n\n // --- Lifecycle (§3.5) ---\n\n /**\n * (Re-)subscribe to `enterpictureinpicture`/`leavepictureinpicture` on\n * `element` (the Shell's resolved `<video>` target). Idempotent when called\n * again with the same element; re-wires the listeners when the element\n * changes (e.g. the `target` attribute was changed), detaching from the\n * previous element first so no stale listener lingers.\n */\n observe(element: HTMLVideoElement | null): Promise<void> {\n if (this._video === element) {\n return this._ready;\n }\n this._detach();\n this._video = element;\n if (element) {\n element.addEventListener(\"enterpictureinpicture\", this._onEnter);\n element.addEventListener(\"leavepictureinpicture\", this._onLeave);\n }\n this._syncActive();\n return this._ready;\n }\n\n dispose(): void {\n this._gen++;\n this._detach();\n this._video = null;\n }\n\n // --- Commands (§3.6 never-throw) ---\n\n /**\n * Request Picture-in-Picture for `element`. `element` must be a `<video>`\n * (checked before the gesture-context failure path, since a type mismatch is\n * an environment-independent, permanent error — docs/picture-in-picture-tag-design.md §2).\n * Never throws: all failures (wrong tag, unsupported API, gesture-context\n * rejection) are funneled into `error` and the returned promise resolves.\n */\n async requestPictureInPicture(element: HTMLVideoElement | null): Promise<void> {\n const gen = ++this._gen;\n if (!element || element.tagName !== \"VIDEO\") {\n // Distinct from \"API is not supported\" (below): the resolved target did\n // not satisfy the `<video>`-only constraint (wrong tag / unresolved).\n this._setError({ message: \"target must be a <video> element.\" }, \"invalid-argument\");\n return;\n }\n // Re-wire to `element` before issuing the platform call: a caller may\n // request a <video> different from the one last passed to observe() (e.g.\n // the Shell's target attribute pointed at nothing at connect time and the\n // matching <video> was only inserted later, so no attributeChangedCallback\n // ever re-resolved it). Without this, `_video` stays stale and\n // `_syncActive()` below (and future enter/leave events) would never\n // recognize `element` as this Core's target, leaving `active` permanently\n // wrong even though the request succeeded (mirrors\n // FullscreenCore.requestFullscreen()'s unconditional `this._resolvedTarget\n // = element` assignment — docs/fullscreen-tag-design.md §6).\n this.observe(element);\n const fn = this._requestPictureInPictureFn(element);\n if (!fn) {\n this._setError({ message: \"Picture-in-Picture API is not supported.\" }, \"capability-missing\");\n return;\n }\n try {\n await fn.call(element);\n if (gen !== this._gen) return; // stale\n this._setError(null);\n this._syncActive(); // belt-and-suspenders (mirrors FullscreenCore's _applyActive() on success)\n } catch (e: any) {\n if (gen !== this._gen) return; // stale\n this._setError(e); // e.g. NotAllowedError (gesture-context rejection)\n }\n }\n\n /**\n * Exit Picture-in-Picture. Mirrors FullscreenCore.exitFullscreen(): a\n * silent no-op (resolve, no error) when nothing is currently in\n * Picture-in-Picture — see fullscreen-tag-design.md §7.\n */\n async exitPictureInPicture(): Promise<void> {\n // no-op checks come BEFORE the generation bump: a call that does nothing\n // must not supersede an in-flight requestPictureInPicture() — bumping\n // first would make the pending request's settle handling stale and\n // silently swallow its error update (mirrors\n // FullscreenCore.exitFullscreen()).\n if (this._pictureInPictureElement() === null) return; // already not in PiP: silent no-op\n const fn = this._exitPictureInPictureFn();\n if (!fn) return; // unsupported: silent no-op (semantically already \"not in PiP\")\n const gen = ++this._gen;\n try {\n await fn();\n if (gen !== this._gen) return;\n this._setError(null);\n this._syncActive(); // belt-and-suspenders (mirrors FullscreenCore.exitFullscreen()'s success-path _applyActive()); covers a delayed/dropped leavepictureinpicture\n } catch (e: any) {\n if (gen !== this._gen) return;\n this._setError(e);\n }\n }\n\n // --- Internal: API resolution (call-time, never cached — §3.7) ---\n\n // Unlike FullscreenCore's _elementFullscreenFn(), a naive direct property\n // lookup (`e.requestPictureInPicture`, walking the prototype chain) here is\n // safe: it cannot recurse into the Shell's own command method,\n // because the resolved target is validated to be a <video> element (§2)\n // before this is called, and <wcs-pip> (the Shell) is never itself a\n // <video>. Fullscreen's own→Element.prototype two-step resolution guards\n // against `target=\"self\"`/no-target resolving to the Shell element, which\n // cannot happen here.\n private _requestPictureInPictureFn(el: HTMLVideoElement): (() => Promise<PictureInPictureWindow>) | undefined {\n const e = el as any;\n return typeof e.requestPictureInPicture === \"function\" ? e.requestPictureInPicture : undefined;\n }\n\n private _exitPictureInPictureFn(): (() => Promise<void>) | undefined {\n const d = document as any;\n return typeof d.exitPictureInPicture === \"function\" ? d.exitPictureInPicture.bind(document) : undefined;\n }\n\n private _pictureInPictureElement(): Element | null {\n const d = document as any;\n return d.pictureInPictureElement ?? null;\n }\n\n // --- Internal: event wiring ---\n\n private _onEnter = (): void => {\n this._syncActive();\n };\n\n private _onLeave = (): void => {\n this._syncActive();\n };\n\n private _syncActive(): void {\n const isActive = this._video !== null && this._pictureInPictureElement() === this._video;\n this._setActive(isActive);\n }\n\n private _detach(): void {\n if (this._video) {\n this._video.removeEventListener(\"enterpictureinpicture\", this._onEnter);\n this._video.removeEventListener(\"leavepictureinpicture\", this._onLeave);\n }\n }\n\n // --- State setters with event dispatch (§3.3 same-value guard) ---\n\n private _setActive(active: boolean): void {\n if (this._active === active) return;\n this._active = active;\n this._target.dispatchEvent(new CustomEvent(\"wcs-pip:change\", {\n detail: { active },\n bubbles: true,\n }));\n }\n\n // `kind` is an explicit taxonomy discriminator passed only from the synthetic\n // error sites (unsupported / non-<video> target); caught exceptions pass no kind\n // and are classified by their `.name`. Both `error` and the additive `errorInfo`\n // are now event-backed so a request/exit failure is observable via bind().\n private _setError(error: any, kind?: PictureInPictureErrorKind): void {\n // Same-value guard on reference: each failure builds a fresh object and the\n // clear path passes the literal null, so this only suppresses redundant\n // null→null (a successful request/exit clearing an already-null error).\n if (this._error === error) return;\n this._error = error;\n // Keep the additive errorInfo taxonomy in sync; fire it before the `error`\n // event so an observer of both sees the classification first (io-node family).\n this._commitErrorInfo(error === null ? null : derivePictureInPictureErrorInfo(error, kind));\n this._target.dispatchEvent(new CustomEvent(\"wcs-pip:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n // Called only from _setError (already reference-guarded), so errorInfo\n // transitions exactly when error does — no separate guard needed here.\n private _commitErrorInfo(info: WcsIoErrorInfo | null): void {\n this._errorInfo = info;\n this._target.dispatchEvent(new CustomEvent(\"wcs-pip:error-info-changed\", {\n detail: info,\n bubbles: true,\n }));\n }\n}\n","import { IWcBindable } from \"../types.js\";\nimport { PipCore } from \"../core/PipCore.js\";\nimport { WcsIoErrorInfo } from \"../core/platformCapability.js\";\n\n/**\n * `<wcs-pip target=\"...\">` — declarative Picture-in-Picture control.\n *\n * Like `<wcs-fullscreen>` (docs/fullscreen-tag-design.md §0/§1), this Shell\n * does not operate on itself: it is a non-visible control tag that resolves a\n * `target` element and invokes Picture-in-Picture commands against it. The\n * `target` attribute resolves in the same 3 modes as `intersection`/`fullscreen`\n * (`self` / a selector / the first element child), reused verbatim from\n * `@wcstack/intersection`'s `_resolveTarget()`/`_safeQuery()`\n * (packages/intersection/src/components/Intersect.ts).\n *\n * Picture-in-Picture-specific difference (docs/picture-in-picture-tag-design.md\n * §2): the resolved target must be a `<video>` element. This Shell resolves the\n * DOM element and hands it to the Core; the Core performs the `tagName ===\n * \"VIDEO\"` validation (never-throw — a mismatch is treated as an unresolved\n * target and reported via `error`, not thrown).\n */\nexport class WcsPip extends HTMLElement {\n // SSR (§4.4): observe() completes synchronously, but the Shell still exposes\n // connectedCallbackPromise so the state binder can await it uniformly across\n // all IO nodes before snapshotting.\n static hasConnectedCallbackPromise = true;\n\n static observedAttributes = [\"target\"];\n\n static wcBindable: IWcBindable = {\n ...PipCore.wcBindable,\n inputs: [{ name: \"target\", attribute: \"target\" }],\n // Core の commands をそのまま継承(単一情報源)。fullscreen/intersection と同型。\n commands: PipCore.wcBindable.commands,\n };\n\n private _core: PipCore;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new PipCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n \"wcs-pip:change\": (d) => ({ active: d?.active === true }),\n });\n }\n\n // CSS state reflection (:state()) — debug-only snapshot getter. NOT part of\n // wc-bindable (not a bind target); see README \"CSS styling with :state()\".\n // MUST NOT return the live CustomStateSet (that would let callers write\n // states from outside, defeating the point of :state() being read-only).\n get debugStates(): string[] {\n return this._internals ? [...this._internals.states] : [];\n }\n\n private _initInternals(): ElementInternals | null {\n // never-throw (docs/custom-state-reflection-design.md §3.1): attachInternals\n // is absent in happy-dom / older environments, and pre-125 Chromium rejects\n // non-dashed state names from states.add() (probed and discarded here).\n // Either case silently disables reflection — the component still works,\n // it just doesn't expose :state() selectors.\n try {\n if (typeof this.attachInternals !== \"function\") return null;\n const internals = this.attachInternals();\n internals.states.add(\"wcs-probe\");\n internals.states.delete(\"wcs-probe\");\n return internals;\n } catch {\n return null;\n }\n }\n\n private _wireStates(map: Record<string, (detail: any) => Record<string, boolean>>): void {\n if (this._internals === null) return;\n const states = this._internals.states;\n for (const [event, toStates] of Object.entries(map)) {\n this.addEventListener(event, (e) => {\n const debug = this.hasAttribute(\"debug-states\");\n for (const [name, on] of Object.entries(toStates((e as CustomEvent).detail))) {\n try {\n if (on) { states.add(name); } else { states.delete(name); }\n } catch { /* never-throw */ }\n if (debug) this.toggleAttribute(`data-wcs-state-${name}`, on);\n }\n });\n }\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Attribute accessors ---\n\n get target(): string {\n return this.getAttribute(\"target\") ?? \"\";\n }\n\n set target(value: string) {\n this.setAttribute(\"target\", value);\n }\n\n // --- Core delegated getters ---\n\n get active(): boolean {\n return this._core.active;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n get errorInfo(): WcsIoErrorInfo | null {\n return this._core.errorInfo;\n }\n\n // --- Commands ---\n\n async requestPictureInPicture(): Promise<void> {\n const { element } = this._resolveVideoTarget();\n return this._core.requestPictureInPicture(element);\n }\n\n async exitPictureInPicture(): Promise<void> {\n return this._core.exitPictureInPicture();\n }\n\n // --- Internal ---\n\n /**\n * `_resolveTarget()`/`_safeQuery()` copied verbatim from `@wcstack/intersection`\n * (packages/intersection/src/components/Intersect.ts:243-267, 281-287) per the\n * fullscreen/picture-in-picture batch's shared target-resolution archetype\n * (docs/fullscreen-tag-design.md §1).\n */\n private _resolveTarget(): { element: Element | null; display: string } {\n const target = this.target;\n if (target === \"self\") {\n return { element: this, display: \"block\" };\n }\n if (target !== \"\") {\n const scope = this.getRootNode() as Document | ShadowRoot;\n return { element: this._safeQuery(scope, target), display: \"none\" };\n }\n const child = this.firstElementChild;\n if (child) {\n return { element: child, display: \"contents\" };\n }\n return { element: this, display: \"block\" };\n }\n\n private _safeQuery(scope: Document | ShadowRoot, selector: string): Element | null {\n try {\n return scope.querySelector(selector);\n } catch {\n return null;\n }\n }\n\n /**\n * Layers the Picture-in-Picture-specific `tagName === \"VIDEO\"` check on top\n * of `_resolveTarget()` (docs/picture-in-picture-tag-design.md §2). A\n * resolved-but-wrong-tag element is treated as unresolved (`element: null`)\n * so it flows into the same \"target not found\" failure path as Fullscreen's\n * missing-target case — never-throw, no exception escapes.\n */\n private _resolveVideoTarget(): { element: HTMLVideoElement | null; display: string } {\n const { element, display } = this._resolveTarget();\n if (element !== null && element.tagName !== \"VIDEO\") {\n return { element: null, display };\n }\n return { element: element as HTMLVideoElement | null, display };\n }\n\n private _observe(): void {\n const { element, display } = this._resolveVideoTarget();\n this.style.display = display;\n this._connectedCallbackPromise = this._core.observe(element);\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this._observe();\n }\n\n disconnectedCallback(): void {\n this._core.dispose();\n }\n\n attributeChangedCallback(_name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n if (!this.isConnected) return;\n this._observe();\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapPip(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n","import { WcsPip } from \"./components/Pip.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.pip)) {\n customElements.define(config.tagNames.pip, WcsPip);\n }\n}\n"],"names":["_config","tagNames","pip","deepFreeze","obj","Object","freeze","key","keys","deepClone","clone","frozenConfig","config","getConfig","WCS_PICTURE_IN_PICTURE_ERROR_CODE","CapabilityMissing","InvalidArgument","NotAllowed","PipError","derivePictureInPictureErrorInfo","error","kind","message","String","messageOf","code","phase","recoverable","name","PipCore","EventTarget","static","protocol","version","properties","event","getter","e","detail","active","commands","async","_target","_active","_error","_errorInfo","_video","_gen","_ready","Promise","resolve","constructor","target","super","this","ready","errorInfo","observe","element","_detach","addEventListener","_onEnter","_onLeave","_syncActive","dispose","requestPictureInPicture","gen","tagName","_setError","fn","_requestPictureInPictureFn","call","exitPictureInPicture","_pictureInPictureElement","_exitPictureInPictureFn","el","undefined","d","document","bind","pictureInPictureElement","isActive","_setActive","removeEventListener","dispatchEvent","CustomEvent","bubbles","_commitErrorInfo","info","WcsPip","HTMLElement","wcBindable","inputs","attribute","_core","_connectedCallbackPromise","_internals","_initInternals","_wireStates","debugStates","states","attachInternals","internals","add","delete","map","toStates","entries","debug","hasAttribute","on","toggleAttribute","connectedCallbackPromise","getAttribute","value","setAttribute","_resolveVideoTarget","_resolveTarget","display","scope","getRootNode","_safeQuery","child","firstElementChild","selector","querySelector","_observe","style","connectedCallback","disconnectedCallback","attributeChangedCallback","_name","oldValue","newValue","isConnected","bootstrapPip","userConfig","partialConfig","assign","customElements","get","define"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wcstack/picture-in-picture",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.21.1",
|
|
4
4
|
"description": "Declarative Picture-in-Picture component for Web Components. Framework-agnostic <video> Picture-in-Picture control via wc-bindable-protocol.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.esm.js",
|