@wcstack/broadcast 1.19.1 → 1.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +3 -1
- package/README.md +3 -1
- package/dist/index.d.ts +46 -3
- package/dist/index.esm.js +78 -1
- 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
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
- **入力面**: `name`, `manual`
|
|
16
16
|
- **コマンド面**: `open`, `post`, `close`
|
|
17
|
-
- **出力状態面**: `message`, `error`
|
|
17
|
+
- **出力状態面**: `message`, `error`, `errorInfo`
|
|
18
18
|
|
|
19
19
|
つまり、タブ間の同期を HTML 上で宣言的に表現でき、UI 層に `new BroadcastChannel()` / `postMessage()` / `onmessage` リスナ、後始末のグルーコードを書く必要がありません。
|
|
20
20
|
|
|
@@ -131,6 +131,7 @@ post は DOM クリック(autoTrigger)または command-token から起動
|
|
|
131
131
|
| --------- | ------------------------ | ------------------------------------------------------------------------------------ |
|
|
132
132
|
| `message` | `wcs-broadcast:message` | チャンネル上の他のコンテキストから受信した直近の値(structured clone のコピー)。このコンテキスト自身の post では決して設定されない。 |
|
|
133
133
|
| `error` | `wcs-broadcast:error` | 正規化された `{ name, message }` — `DataCloneError`(クローン不可能な post)、`DataError`(ピアのメッセージをデシリアライズできなかった)、`InvalidStateError`(開いているチャンネルが無い状態での post)、または `NotSupportedError`(BroadcastChannel が利用不可)。 |
|
|
134
|
+
| `errorInfo` | `wcs-broadcast:error-info-changed` | シリアライズ可能な失敗タクソノミ `WcsIoErrorInfo \| null`(安定した `code` / `phase` / `recoverable`)。`error` と同じ失敗から導出される。追加的で、`error` の形状は不変。 |
|
|
134
135
|
|
|
135
136
|
## コマンド
|
|
136
137
|
|
|
@@ -203,6 +204,7 @@ form:has(wcs-broadcast:state(error)) .banner { display: block; }
|
|
|
203
204
|
- **接続状態は無い。** BroadcastChannel は構築された瞬間に「開いて」います — connecting/ハンドシェイク段階も、`readyState` も、再接続もありません(必要ないため)。Shell は接続時に同期的に開くので `connectedCallbackPromise` は即座に resolve する(解決済み promise)が、`hasConnectedCallbackPromise = true` として公開されており、state バインダ / SSR がスナップショット前に一様に readiness を await できます。
|
|
204
205
|
- **再接続で開き直す。** 要素を削除して再挿入すると `connectedCallback` が再度実行され、`name` 属性(真実の源)からチャンネルを開き直します。`disconnectedCallback` がそれを閉じます。
|
|
205
206
|
- **無言のエラー処理(ゼロログ)。** wcstack 全体のゼロ依存主義に従い、`<wcs-broadcast>` は実行時の失敗に対して一切ログ出力も throw もしません。BroadcastChannel コンストラクタの欠如、クローン不可能な post、デシリアライズ失敗は `error` プロパティ / `wcs-broadcast:error` イベントを通じてのみ表面化します — `post()` は resolve し、決して reject しません。観測・対処するには `error` をバインドしてください。
|
|
207
|
+
- **`errorInfo` タクソノミ。** `error` に現れるのと同じ失敗を、シリアライズ可能な `WcsIoErrorInfo`(安定した `code` / `phase` / `recoverable`)に分類する**追加的な**バインド可能出力(`wcs-broadcast:error-info-changed`)です。`error` の形状は変えません。`BroadcastChannel` コンストラクタの欠如(`NotSupportedError`)は `capability-missing`(phase `probe`)、クローン不可能な post(`DataCloneError`——呼び出し側入力の不備)は `invalid-argument`(phase `execute`)、その他(`DataError` のデシリアライズ失敗、`InvalidStateError`、`Error` フォールバック)は `broadcast-error`(phase `execute`)です。いずれも `recoverable: false`(同じ入力を再送しても回復しません)。`errorInfo` は `error` と同期して遷移し(同じタイミングで、`error` と共にクリアされる)ます。共有の `WcsIoErrorInfo` 型と `WCS_BROADCAST_ERROR_CODE` 定数は export 済みです。
|
|
206
208
|
|
|
207
209
|
## ヘッドレス利用(`BroadcastCore`)
|
|
208
210
|
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ With `@wcstack/state`, `<wcs-broadcast>` can be bound directly through path cont
|
|
|
14
14
|
|
|
15
15
|
- **input surface**: `name`, `manual`
|
|
16
16
|
- **command surface**: `open`, `post`, `close`
|
|
17
|
-
- **output state surface**: `message`, `error`
|
|
17
|
+
- **output state surface**: `message`, `error`, `errorInfo`
|
|
18
18
|
|
|
19
19
|
This means cross-tab synchronization can be expressed declaratively in HTML, without writing `new BroadcastChannel()`, `postMessage()`, `onmessage` listeners, or teardown glue in your UI layer.
|
|
20
20
|
|
|
@@ -131,6 +131,7 @@ You do not need the event-token to *read* the latest message — bind `message`
|
|
|
131
131
|
| --------- | ------------------------ | ------------------------------------------------------------------------------------ |
|
|
132
132
|
| `message` | `wcs-broadcast:message` | The last value received from another context on the channel (structured-clone copy). Never set by this context's own posts. |
|
|
133
133
|
| `error` | `wcs-broadcast:error` | Normalized `{ name, message }` — `DataCloneError` (non-cloneable post), `DataError` (a peer's message could not be deserialized), `InvalidStateError` (post with no open channel), or `NotSupportedError` (BroadcastChannel unavailable). |
|
|
134
|
+
| `errorInfo` | `wcs-broadcast:error-info-changed` | Serializable failure taxonomy `WcsIoErrorInfo \| null` (stable `code` / `phase` / `recoverable`), derived from the same failure as `error`. Additive — the `error` shape is unchanged. |
|
|
134
135
|
|
|
135
136
|
## Commands
|
|
136
137
|
|
|
@@ -205,6 +206,7 @@ DevTools open; it is not a supported styling hook.
|
|
|
205
206
|
- **No connection state.** A BroadcastChannel is "open" the moment it is constructed — there is no connecting/handshake phase, no `readyState`, and no reconnect (none is needed). The Shell opens synchronously on connect, so its `connectedCallbackPromise` resolves immediately (an already-resolved promise). It is still exposed (`hasConnectedCallbackPromise = true`) so a state binder / SSR can uniformly await readiness before snapshotting.
|
|
206
207
|
- **Reconnect re-opens.** Removing and re-inserting the element runs `connectedCallback` again, re-opening the channel from the `name` attribute (the source of truth), and `disconnectedCallback` closes it.
|
|
207
208
|
- **Silent failure handling (zero-log).** Consistent with the rest of wcstack's zero-dependency philosophy, `<wcs-broadcast>` never logs or throws for runtime failures. A missing BroadcastChannel constructor, a non-cloneable post, or a deserialization failure are surfaced only through the `error` property / `wcs-broadcast:error` event — `post()` resolves and never rejects. Bind `error` to observe and react.
|
|
209
|
+
- **`errorInfo` taxonomy.** An **additive** bindable output (`wcs-broadcast:error-info-changed`) that classifies the same failure surfaced on `error` into a serializable `WcsIoErrorInfo` with a stable `code` / `phase` / `recoverable`, without changing the `error` shape. A missing `BroadcastChannel` constructor (`NotSupportedError`) is `capability-missing` (phase `probe`); a non-cloneable post (`DataCloneError` — caller input) is `invalid-argument` (phase `execute`); anything else (a `DataError` deserialization failure, an `InvalidStateError`, or an `Error` fallback) is `broadcast-error` (phase `execute`). All are `recoverable: false` (the same input re-sent will not recover). `errorInfo` stays in lockstep with `error` (same transitions, cleared alongside it). The shared `WcsIoErrorInfo` type and the `WCS_BROADCAST_ERROR_CODE` constants are exported.
|
|
208
210
|
|
|
209
211
|
## Headless usage (`BroadcastCore`)
|
|
210
212
|
|
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[];
|
|
@@ -68,6 +80,8 @@ interface WcsBroadcastCoreValues {
|
|
|
68
80
|
message: any;
|
|
69
81
|
/** The last error (post failure / deserialization failure / unsupported), or `null`. */
|
|
70
82
|
error: WcsBroadcastErrorDetail | null;
|
|
83
|
+
/** Additive failure taxonomy derived from `error` (stable code / phase / recoverable), or `null`. */
|
|
84
|
+
errorInfo: WcsIoErrorInfo | null;
|
|
71
85
|
}
|
|
72
86
|
/**
|
|
73
87
|
* Value types for the Shell (`<wcs-broadcast>`) — identical observable surface
|
|
@@ -128,15 +142,24 @@ declare class BroadcastCore extends EventTarget {
|
|
|
128
142
|
private _name;
|
|
129
143
|
private _message;
|
|
130
144
|
private _error;
|
|
145
|
+
private _errorInfo;
|
|
131
146
|
private _gen;
|
|
132
147
|
private _ready;
|
|
133
148
|
constructor(target?: EventTarget);
|
|
134
149
|
get ready(): Promise<void>;
|
|
135
150
|
get message(): any;
|
|
136
151
|
get error(): WcsBroadcastErrorDetail | null;
|
|
152
|
+
/**
|
|
153
|
+
* The last failure's serializable `WcsIoErrorInfo` (stable `code` / `phase` /
|
|
154
|
+
* `recoverable`), or null. Additive wc-bindable property (event
|
|
155
|
+
* `wcs-broadcast:error-info-changed`), derived from `error`; the existing
|
|
156
|
+
* `error` property/event are unchanged.
|
|
157
|
+
*/
|
|
158
|
+
get errorInfo(): WcsIoErrorInfo | null;
|
|
137
159
|
observe(): Promise<void>;
|
|
138
160
|
private _setMessage;
|
|
139
161
|
private _setError;
|
|
162
|
+
private _commitErrorInfo;
|
|
140
163
|
/**
|
|
141
164
|
* Join the named channel. Any previously-open channel is closed first, so
|
|
142
165
|
* calling `open()` again switches channels. When the BroadcastChannel
|
|
@@ -193,6 +216,7 @@ declare class WcsBroadcast extends HTMLElement {
|
|
|
193
216
|
set manual(value: boolean);
|
|
194
217
|
get message(): any;
|
|
195
218
|
get error(): WcsBroadcastErrorDetail | null;
|
|
219
|
+
get errorInfo(): WcsIoErrorInfo | null;
|
|
196
220
|
open(): void;
|
|
197
221
|
post(data: any): void;
|
|
198
222
|
close(): void;
|
|
@@ -201,5 +225,24 @@ declare class WcsBroadcast extends HTMLElement {
|
|
|
201
225
|
disconnectedCallback(): void;
|
|
202
226
|
}
|
|
203
227
|
|
|
204
|
-
|
|
205
|
-
|
|
228
|
+
/**
|
|
229
|
+
* broadcastCapabilities.ts
|
|
230
|
+
*
|
|
231
|
+
* Broadcast node 固有の error code(taxonomy)と derivation。汎用の error info 型は
|
|
232
|
+
* `./platformCapability.js`(/io-core/ から copy-distribution される生成ファイル)から
|
|
233
|
+
* import する。BroadcastChannel の post / message は concurrent-independent(競合しない)
|
|
234
|
+
* ため lane は持たず、error taxonomy(errorInfo)のみを採用する。
|
|
235
|
+
*/
|
|
236
|
+
|
|
237
|
+
/** 安定した broadcast error code(taxonomy)。値は公開キーとして固定。 */
|
|
238
|
+
declare const WCS_BROADCAST_ERROR_CODE: {
|
|
239
|
+
/** BroadcastChannel コンストラクタ不在(`_unsupportedError()` の `NotSupportedError`)。 */
|
|
240
|
+
readonly CapabilityMissing: "capability-missing";
|
|
241
|
+
/** structured clone 不可な payload を post(`DataCloneError`)。呼び出し側入力の不備。 */
|
|
242
|
+
readonly InvalidArgument: "invalid-argument";
|
|
243
|
+
/** その他の post / channel 失敗(DataError / InvalidStateError / "Error" fallback など)。 */
|
|
244
|
+
readonly BroadcastError: "broadcast-error";
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
export { BroadcastCore, WCS_BROADCAST_ERROR_CODE, WcsBroadcast, bootstrapBroadcast, getConfig };
|
|
248
|
+
export type { IWritableConfig, IWritableTagNames, WcsBroadcastCommands, WcsBroadcastCoreCommands, WcsBroadcastCoreValues, WcsBroadcastErrorDetail, WcsBroadcastInputs, WcsBroadcastValues, WcsIoErrorInfo, WcsIoErrorPhase };
|
package/dist/index.esm.js
CHANGED
|
@@ -48,6 +48,46 @@ function setConfig(partialConfig) {
|
|
|
48
48
|
frozenConfig = null;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* broadcastCapabilities.ts
|
|
53
|
+
*
|
|
54
|
+
* Broadcast node 固有の error code(taxonomy)と derivation。汎用の error info 型は
|
|
55
|
+
* `./platformCapability.js`(/io-core/ から copy-distribution される生成ファイル)から
|
|
56
|
+
* import する。BroadcastChannel の post / message は concurrent-independent(競合しない)
|
|
57
|
+
* ため lane は持たず、error taxonomy(errorInfo)のみを採用する。
|
|
58
|
+
*/
|
|
59
|
+
/** 安定した broadcast error code(taxonomy)。値は公開キーとして固定。 */
|
|
60
|
+
const WCS_BROADCAST_ERROR_CODE = {
|
|
61
|
+
/** BroadcastChannel コンストラクタ不在(`_unsupportedError()` の `NotSupportedError`)。 */
|
|
62
|
+
CapabilityMissing: "capability-missing",
|
|
63
|
+
/** structured clone 不可な payload を post(`DataCloneError`)。呼び出し側入力の不備。 */
|
|
64
|
+
InvalidArgument: "invalid-argument",
|
|
65
|
+
/** その他の post / channel 失敗(DataError / InvalidStateError / "Error" fallback など)。 */
|
|
66
|
+
BroadcastError: "broadcast-error",
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* 正規化済み error(`{ name, message }`)を serializable な error taxonomy に写す。
|
|
70
|
+
* `name` は `DOMException.name`(`_normalizeError`)/ 合成名(`_unsupportedError` の
|
|
71
|
+
* `NotSupportedError`、`messageerror` の `DataError`、post 前の `InvalidStateError`)。
|
|
72
|
+
*
|
|
73
|
+
* - `NotSupportedError`(BroadcastChannel 不在)は利用直前の能力欠如 → phase="probe" /
|
|
74
|
+
* capability-missing。
|
|
75
|
+
* - `DataCloneError`(structured clone 不可な payload を post)は呼び出し側入力の不備 →
|
|
76
|
+
* phase="execute" / invalid-argument。
|
|
77
|
+
* - それ以外(`DataError` の deserialize 失敗 / `InvalidStateError` / "Error" fallback)は
|
|
78
|
+
* phase="execute" / broadcast-error。
|
|
79
|
+
* いずれも同一入力の再送では回復しない(recoverable=false)。
|
|
80
|
+
*/
|
|
81
|
+
function deriveBroadcastErrorInfo(error) {
|
|
82
|
+
if (error.name === "NotSupportedError") {
|
|
83
|
+
return { code: WCS_BROADCAST_ERROR_CODE.CapabilityMissing, phase: "probe", recoverable: false, message: error.message };
|
|
84
|
+
}
|
|
85
|
+
if (error.name === "DataCloneError") {
|
|
86
|
+
return { code: WCS_BROADCAST_ERROR_CODE.InvalidArgument, phase: "execute", recoverable: false, message: error.message };
|
|
87
|
+
}
|
|
88
|
+
return { code: WCS_BROADCAST_ERROR_CODE.BroadcastError, phase: "execute", recoverable: false, message: error.message };
|
|
89
|
+
}
|
|
90
|
+
|
|
51
91
|
/**
|
|
52
92
|
* Headless cross-tab messaging primitive. A thin, framework-agnostic wrapper
|
|
53
93
|
* around the BroadcastChannel API exposed through the wc-bindable protocol.
|
|
@@ -77,6 +117,12 @@ class BroadcastCore extends EventTarget {
|
|
|
77
117
|
properties: [
|
|
78
118
|
{ name: "message", event: "wcs-broadcast:message" },
|
|
79
119
|
{ name: "error", event: "wcs-broadcast:error" },
|
|
120
|
+
// Serializable failure taxonomy (stable code / phase / recoverable), or null.
|
|
121
|
+
// Additive bindable output derived from `error` (the DOMException.name /
|
|
122
|
+
// synthetic name); the existing `error` property/event are unchanged. Fires
|
|
123
|
+
// wcs-broadcast:error-info-changed. No lane — post/message are concurrent-
|
|
124
|
+
// independent (mirrors ClipboardCore).
|
|
125
|
+
{ name: "errorInfo", event: "wcs-broadcast:error-info-changed" },
|
|
80
126
|
],
|
|
81
127
|
commands: [
|
|
82
128
|
{ name: "open" },
|
|
@@ -89,6 +135,7 @@ class BroadcastCore extends EventTarget {
|
|
|
89
135
|
_name = null;
|
|
90
136
|
_message = null;
|
|
91
137
|
_error = null;
|
|
138
|
+
_errorInfo = null;
|
|
92
139
|
// Generation guard (§3.4): bumped on dispose(). An incoming message /
|
|
93
140
|
// messageerror that fires after the Shell disconnected (a peer posted between
|
|
94
141
|
// disconnect and the channel actually closing, or a queued event drains late)
|
|
@@ -111,6 +158,15 @@ class BroadcastCore extends EventTarget {
|
|
|
111
158
|
get error() {
|
|
112
159
|
return this._error;
|
|
113
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* The last failure's serializable `WcsIoErrorInfo` (stable `code` / `phase` /
|
|
163
|
+
* `recoverable`), or null. Additive wc-bindable property (event
|
|
164
|
+
* `wcs-broadcast:error-info-changed`), derived from `error`; the existing
|
|
165
|
+
* `error` property/event are unchanged.
|
|
166
|
+
*/
|
|
167
|
+
get errorInfo() {
|
|
168
|
+
return this._errorInfo;
|
|
169
|
+
}
|
|
114
170
|
// --- Lifecycle (§3.5) ---
|
|
115
171
|
// observe() establishes monitoring. BroadcastChannel is command-driven (the
|
|
116
172
|
// Shell calls open(name) from connectedCallback / attributeChangedCallback),
|
|
@@ -140,11 +196,25 @@ class BroadcastCore extends EventTarget {
|
|
|
140
196
|
if (this._error === error)
|
|
141
197
|
return;
|
|
142
198
|
this._error = error;
|
|
199
|
+
// Keep the additive `errorInfo` taxonomy in sync with `error`: derive from the
|
|
200
|
+
// error name (or null on clear). Fires before the `error` event so an observer
|
|
201
|
+
// binding both sees the classification first, mirroring the io-node family.
|
|
202
|
+
this._commitErrorInfo(error === null ? null : deriveBroadcastErrorInfo(error));
|
|
143
203
|
this._target.dispatchEvent(new CustomEvent("wcs-broadcast:error", {
|
|
144
204
|
detail: error,
|
|
145
205
|
bubbles: true,
|
|
146
206
|
}));
|
|
147
207
|
}
|
|
208
|
+
// Called only from _setError (which already same-value-guards on reference
|
|
209
|
+
// identity), so errorInfo transitions exactly when error does — no separate
|
|
210
|
+
// guard needed here.
|
|
211
|
+
_commitErrorInfo(info) {
|
|
212
|
+
this._errorInfo = info;
|
|
213
|
+
this._target.dispatchEvent(new CustomEvent("wcs-broadcast:error-info-changed", {
|
|
214
|
+
detail: info,
|
|
215
|
+
bubbles: true,
|
|
216
|
+
}));
|
|
217
|
+
}
|
|
148
218
|
// --- Public API ---
|
|
149
219
|
/**
|
|
150
220
|
* Join the named channel. Any previously-open channel is closed first, so
|
|
@@ -244,6 +314,10 @@ class BroadcastCore extends EventTarget {
|
|
|
244
314
|
this._gen++;
|
|
245
315
|
this._closeChannel();
|
|
246
316
|
this._error = null;
|
|
317
|
+
// dispose bypasses _setError (silent, no dispatch on a torn-down element), so
|
|
318
|
+
// clear the errorInfo mirror directly too — otherwise a stale taxonomy would
|
|
319
|
+
// survive after `error` has been reset to null.
|
|
320
|
+
this._errorInfo = null;
|
|
247
321
|
}
|
|
248
322
|
// --- Internal ---
|
|
249
323
|
// Per-channel listeners, (re)created in open() so each closes over its own
|
|
@@ -478,6 +552,9 @@ class WcsBroadcast extends HTMLElement {
|
|
|
478
552
|
get error() {
|
|
479
553
|
return this._core.error;
|
|
480
554
|
}
|
|
555
|
+
get errorInfo() {
|
|
556
|
+
return this._core.errorInfo;
|
|
557
|
+
}
|
|
481
558
|
// --- Commands ---
|
|
482
559
|
open() {
|
|
483
560
|
if (this.name) {
|
|
@@ -536,5 +613,5 @@ function bootstrapBroadcast(userConfig) {
|
|
|
536
613
|
registerComponents();
|
|
537
614
|
}
|
|
538
615
|
|
|
539
|
-
export { BroadcastCore, WcsBroadcast, bootstrapBroadcast, getConfig };
|
|
616
|
+
export { BroadcastCore, WCS_BROADCAST_ERROR_CODE, WcsBroadcast, bootstrapBroadcast, getConfig };
|
|
540
617
|
//# 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/BroadcastCore.ts","../src/autoTrigger.ts","../src/components/Broadcast.ts","../src/registerComponents.ts","../src/bootstrapBroadcast.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n broadcast: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-broadcast-target\",\n tagNames: {\n broadcast: \"wcs-broadcast\",\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\n// Live reference to the mutable internal config: reads always reflect the latest\n// setConfig() call. The readonly IConfig type only blocks callers from writing\n// through it — the underlying object still changes. If you need a stable,\n// frozen snapshot that won't move under you, use getConfig() instead.\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 (typeof partialConfig.autoTrigger === \"boolean\") {\n _config.autoTrigger = partialConfig.autoTrigger;\n }\n if (typeof partialConfig.triggerAttribute === \"string\") {\n _config.triggerAttribute = partialConfig.triggerAttribute;\n }\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { IWcBindable, WcsBroadcastErrorDetail } from \"../types.js\";\n\n/**\n * Headless cross-tab messaging primitive. A thin, framework-agnostic wrapper\n * around the BroadcastChannel API exposed through the wc-bindable protocol.\n *\n * BroadcastChannel is a same-origin pub/sub bus: every context (tab, iframe,\n * worker) that opens a channel with the same `name` receives every other\n * context's posts — but NOT its own. This self-exclusion is the whole point:\n * `post` is a `state → element` action (command-token) and an incoming\n * `message` is an `element → state` notification (event-token), but the two\n * only close the loop *across* a context boundary. Within a single tab a lone\n * `<wcs-broadcast>` never hears itself; open the page in two tabs to see the\n * round-trip.\n *\n * Unlike WebSocketCore there is no connection state, no reconnect, and no wire\n * encoding: a channel is \"open\" the moment it is constructed, and payloads ride\n * the browser's structured clone (objects pass through as-is, no JSON\n * round-trip). The only failure surfaces are a non-cloneable `post`\n * (`DataCloneError`), a `messageerror` (a peer posted something this context\n * cannot deserialize), and an absent `BroadcastChannel` constructor\n * (`unsupported`). All three flow through the `error` property — the Core never\n * throws — symmetrical with FetchCore / ClipboardCore.\n */\nexport class BroadcastCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"message\", event: \"wcs-broadcast:message\" },\n { name: \"error\", event: \"wcs-broadcast:error\" },\n ],\n commands: [\n { name: \"open\" },\n { name: \"post\" },\n { name: \"close\" },\n ],\n };\n\n private _target: EventTarget;\n private _channel: BroadcastChannel | null = null;\n private _name: string | null = null;\n private _message: any = null;\n private _error: WcsBroadcastErrorDetail | null = null;\n // Generation guard (§3.4): bumped on dispose(). An incoming message /\n // messageerror that fires after the Shell disconnected (a peer posted between\n // disconnect and the channel actually closing, or a queued event drains late)\n // has a stale `gen` and MUST NOT write state to a torn-down element. A boolean\n // flag is insufficient: dispose→reconnect would let a stale event slip through.\n private _gen = 0;\n // SSR (§3.8): a channel opens synchronously (no asynchronous probe to await),\n // 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 message(): any {\n return this._message;\n }\n\n get error(): WcsBroadcastErrorDetail | null {\n return this._error;\n }\n\n // --- Lifecycle (§3.5) ---\n\n // observe() establishes monitoring. BroadcastChannel is command-driven (the\n // Shell calls open(name) from connectedCallback / attributeChangedCallback),\n // so there is no subscription for observe() to set up here: it is an idempotent\n // no-op that resolves once ready. It exists for skeleton symmetry with the\n // monitor-style nodes so a host can uniformly await observe() == ready.\n observe(): Promise<void> {\n return this._ready;\n }\n\n // --- State setters with event dispatch ---\n\n // Deliberately NO same-value guard (unlike `error` below). A received message\n // is an event, not idempotent state: a peer posting the same value twice is\n // two distinct occurrences and must re-fire wcs-broadcast:message each time so\n // a `message:` binding and any `eventToken.message:` subscriber see both.\n private _setMessage(message: any): void {\n this._message = message;\n this._target.dispatchEvent(new CustomEvent(\"wcs-broadcast:message\", {\n detail: message,\n bubbles: true,\n }));\n }\n\n private _setError(error: WcsBroadcastErrorDetail | null): void {\n // Same-value guard. `error` has no derived state, so suppressing redundant\n // null→null dispatches (e.g. a successful open clearing an already-null\n // error) avoids spurious events. Reference identity is sufficient: each\n // failure builds a fresh object, and the clear path always passes null.\n if (this._error === error) return;\n this._error = error;\n this._target.dispatchEvent(new CustomEvent(\"wcs-broadcast:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n // --- Public API ---\n\n /**\n * Join the named channel. Any previously-open channel is closed first, so\n * calling `open()` again switches channels. When the BroadcastChannel\n * constructor is unavailable this surfaces an `unsupported` error and leaves\n * the Core channel-less (a later `post()` then errors loudly rather than\n * silently dropping).\n */\n open(name: string): void {\n if (!this._hasBroadcastChannel()) {\n this._setError(this._unsupportedError());\n return;\n }\n // Idempotent on the same channel: re-opening the channel we are already on\n // is pure churn (BroadcastChannel has no reconnect semantics). This also\n // absorbs the custom-element *upgrade* path — when a connected element with\n // a `name` attribute is upgraded (autoloader defines the tag after the\n // markup exists), the spec fires attributeChangedCallback (isConnected ===\n // true) *and* connectedCallback, so the Shell calls open() twice. Without\n // this guard that would create a channel and immediately tear it down.\n if (this._channel && this._name === name) return;\n this._closeChannel();\n this._setError(null);\n // Capture the generation for this channel (§3.4). The listeners below close\n // over `gen`; an event that fires after dispose() (which bumps _gen) is\n // recognised as stale and dropped without writing state to a torn-down\n // element. The handlers are stored so _closeChannel() can remove them by the\n // same reference.\n const gen = ++this._gen;\n const channel = new BroadcastChannel(name);\n this._onMessage = (event: MessageEvent): void => {\n if (gen !== this._gen) return;\n this._setMessage(event.data);\n };\n // Fired when a peer posted a value this context cannot deserialize. The event\n // carries no usable payload, so report a synthetic DataError.\n this._onMessageError = (): void => {\n if (gen !== this._gen) return;\n this._setError({\n name: \"DataError\",\n message: \"Failed to deserialize a message received on the channel.\",\n });\n };\n channel.addEventListener(\"message\", this._onMessage);\n channel.addEventListener(\"messageerror\", this._onMessageError);\n this._channel = channel;\n this._name = name;\n }\n\n /**\n * Post a structured-cloneable value to every other context on the channel.\n * The local context never receives it (self-exclusion). Never throws:\n * a non-cloneable value surfaces as a `DataCloneError` through `error`, and\n * posting with no open channel surfaces an `InvalidStateError`.\n */\n post(data: any): void {\n if (!this._hasBroadcastChannel()) {\n this._setError(this._unsupportedError());\n return;\n }\n if (!this._channel) {\n this._setError({\n name: \"InvalidStateError\",\n message: \"Channel is not open. Call open(name) before post().\",\n });\n return;\n }\n try {\n this._channel.postMessage(data);\n } catch (err) {\n this._setError(this._normalizeError(err));\n }\n }\n\n /** Leave the channel. Idempotent — a no-op when no channel is open. */\n close(): void {\n this._closeChannel();\n }\n\n /**\n * Tear the Core down for a disconnected Shell: close the channel and reset the\n * error shadow silently (no dispatch on a torn-down element). A later\n * reconnect re-opens via the Shell's connectedCallback.\n *\n * Asymmetry by design: `_message` is deliberately NOT reset. `error` is\n * transient connection state — a stale error from a previous channel would be\n * misleading after a reconnect, so it is cleared. `message` is the last value\n * received (an event payload), not connection state; it is retained as the\n * Core's last-known datum so a binding still reads it across a disconnect/\n * reconnect, and it is naturally overwritten by the next incoming message.\n */\n dispose(): void {\n // Bump the generation first (§3.4) so any message/messageerror that drains\n // after teardown is recognised as stale, then close the channel and reset the\n // error shadow silently.\n this._gen++;\n this._closeChannel();\n this._error = null;\n }\n\n // --- Internal ---\n\n // Per-channel listeners, (re)created in open() so each closes over its own\n // generation (§3.4). null while no channel is open; the real handlers are\n // installed by open() and removed by the same reference in _closeChannel().\n private _onMessage: ((event: MessageEvent) => void) | null = null;\n private _onMessageError: (() => void) | null = null;\n\n private _closeChannel(): void {\n if (!this._channel) return;\n this._channel.removeEventListener(\"message\", this._onMessage!);\n this._channel.removeEventListener(\"messageerror\", this._onMessageError!);\n this._channel.close();\n this._channel = null;\n this._name = null;\n this._onMessage = null;\n this._onMessageError = null;\n }\n\n private _hasBroadcastChannel(): boolean {\n return typeof BroadcastChannel !== \"undefined\";\n }\n\n private _normalizeError(err: unknown): WcsBroadcastErrorDetail {\n if (err instanceof Error) {\n // DOMException is an Error subclass; its `name` (DataCloneError, etc.) is\n // the meaningful discriminator for consumers switching on failure kind.\n return { name: err.name, message: err.message };\n }\n return { name: \"Error\", message: String(err) };\n }\n\n private _unsupportedError(): WcsBroadcastErrorDetail {\n return {\n name: \"NotSupportedError\",\n message: \"BroadcastChannel is not available in this environment.\",\n };\n }\n}\n","import { config } from \"./config.js\";\nimport type { WcsBroadcast } from \"./components/Broadcast.js\";\n\nlet registered = false;\n\n// Attribute names for the optional post-on-click DOM trigger (clipboard.js-style\n// DX). The element carrying `data-broadcast-target` points at a <wcs-broadcast>\n// by id; the text to post comes from either a literal `data-broadcast-text` or\n// a `data-broadcast-from` CSS selector resolving to a source element.\nconst TEXT_ATTRIBUTE = \"data-broadcast-text\";\nconst FROM_ATTRIBUTE = \"data-broadcast-from\";\n\nfunction resolveText(triggerElement: Element): string | null {\n // Literal text wins when present (including an empty string — posting \"\" is a\n // legitimate request). The `?? \"\"` right-hand side is defensive and\n // unreachable: hasAttribute() just returned true, so getAttribute() cannot be\n // null here. It exists only to satisfy the `string | null` return type — do\n // not chase coverage on it (the DOM contract makes the null branch impossible).\n if (triggerElement.hasAttribute(TEXT_ATTRIBUTE)) {\n return triggerElement.getAttribute(TEXT_ATTRIBUTE) ?? \"\";\n }\n const selector = triggerElement.getAttribute(FROM_ATTRIBUTE);\n if (!selector) return null;\n // A user-authored selector can be syntactically invalid (e.g. `[data-*` or a\n // bare `:not()`), which makes querySelector throw a SyntaxError. Swallow it\n // and treat the source as unresolvable — the same \"nothing to post\" path as a\n // selector that matches no element — so one bad attribute never crashes the\n // document-level click handler and kills autoTrigger for the whole tab.\n let source: Element | null;\n try {\n source = document.querySelector(selector);\n } catch {\n return null;\n }\n if (!source) return null;\n // Read a form control's `value`; fall back to text content. A bare\n // `\"value\" in source` check is too broad — it also matches <button>,\n // <li value>, <progress>, etc. (which carry an unrelated `value`), posting the\n // wrong thing. Narrow to the text-bearing controls a user actually points\n // `data-broadcast-from` at; everything else falls through to textContent.\n if (\n source instanceof HTMLInputElement ||\n source instanceof HTMLTextAreaElement ||\n source instanceof HTMLSelectElement\n ) {\n return source.value;\n }\n // `?? \"\"` is defensive: per the DOM spec only Document / DocumentType /\n // Notation nodes have a null `textContent`, and querySelector only ever\n // returns an Element (whose textContent is always a string). The branch is\n // therefore unreachable in practice and kept solely for the `string | null`\n // type — not worth a contrived test.\n return source.textContent ?? \"\";\n}\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const broadcastId = triggerElement.getAttribute(config.triggerAttribute);\n if (!broadcastId) return;\n\n // Resolve the registered constructor at call time instead of importing\n // WcsBroadcast as a value (avoids a components ⇄ autoTrigger import cycle:\n // Broadcast.connectedCallback() calls registerAutoTrigger()). instanceof\n // against the customElements registry keeps the same identity guarantee.\n const BroadcastCtor = customElements.get(config.tagNames.broadcast);\n const broadcastElement = document.getElementById(broadcastId);\n if (!BroadcastCtor || !(broadcastElement instanceof BroadcastCtor)) return;\n\n const text = resolveText(triggerElement);\n // No resolvable source: leave the click alone (do not preventDefault) so the\n // element's default action is unaffected.\n if (text === null) return;\n\n // Suppress the default action so a post can run without navigating. Intentional:\n // do not attach data-broadcast-target to an element whose default action you\n // also want (a real <a href> link). See README \"Optional DOM Triggering\".\n event.preventDefault();\n (broadcastElement as WcsBroadcast).post(text);\n}\n\nexport function registerAutoTrigger(): void {\n if (registered) return;\n registered = true;\n document.addEventListener(\"click\", handleClick);\n}\n\nexport function unregisterAutoTrigger(): void {\n if (!registered) return;\n registered = false;\n document.removeEventListener(\"click\", handleClick);\n}\n","import { config } from \"../config.js\";\nimport { IWcBindable, WcsBroadcastErrorDetail } from \"../types.js\";\nimport { BroadcastCore } from \"../core/BroadcastCore.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\n\n// Named WcsBroadcast (not `Broadcast`) to match the <wcs-clipboard> WcsClipboard\n// / <wcs-ws> WcsWebSocket convention and avoid shadowing any global.\nexport class WcsBroadcast extends HTMLElement {\n // SSR (§4.4): the channel opens synchronously in connectedCallback, so the\n // Core's observe() resolves immediately; we still expose connectedCallbackPromise\n // so a state binder can uniformly await readiness before snapshotting.\n static hasConnectedCallbackPromise = true;\n static wcBindable: IWcBindable = {\n ...BroadcastCore.wcBindable,\n // Shell-level settable surface. `name` selects the channel; `manual`\n // suppresses auto-open on connect. There is no momentary `post` property:\n // posting needs an argument (the payload), so element actions run via\n // command-token (`command.post: $command.ping`) or the DOM autoTrigger, not\n // a value-derived setter — keeping `post` a plain command keeps the\n // command-token wiring (`command.post:`) readable.\n inputs: [\n { name: \"name\", attribute: \"name\" },\n { name: \"manual\", attribute: \"manual\" },\n ],\n // Commands are identical to the Core's — no rename needed since the `name` /\n // `manual` attribute accessors do not collide with open/post/close.\n commands: BroadcastCore.wcBindable.commands,\n };\n static get observedAttributes(): string[] { return [\"name\"]; }\n\n private _core: BroadcastCore;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new BroadcastCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n \"wcs-broadcast:error\": (d) => ({ error: d != null }),\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 (async-io-node-guidelines.md §3.6): attachInternals is absent\n // 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 name(): string {\n return this.getAttribute(\"name\") || \"\";\n }\n\n set name(value: string) {\n this.setAttribute(\"name\", value);\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n // --- Core delegated getters ---\n\n get message(): any {\n return this._core.message;\n }\n\n get error(): WcsBroadcastErrorDetail | null {\n return this._core.error;\n }\n\n // --- Commands ---\n\n open(): void {\n if (this.name) {\n this._core.open(this.name);\n }\n }\n\n post(data: any): void {\n this._core.post(data);\n }\n\n close(): void {\n this._core.close();\n }\n\n // --- Lifecycle ---\n\n attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void {\n if (name === \"name\" && this.isConnected && !this.manual && newValue) {\n this._core.open(newValue);\n }\n }\n\n connectedCallback(): void {\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n if (!this.manual && this.name) {\n this._core.open(this.name);\n }\n // SSR (§4.4): expose the Core's readiness as connectedCallbackPromise. The\n // channel opens synchronously above, so observe() resolves immediately.\n this._connectedCallbackPromise = this._core.observe();\n }\n\n disconnectedCallback(): void {\n // Deliberately does NOT call unregisterAutoTrigger(). The autoTrigger click\n // listener is a single process-wide document listener (registerAutoTrigger\n // is idempotent), shared by every <wcs-broadcast> on the page — not owned by\n // this element. Tearing it down when the last element disconnects would\n // break a later-inserted trigger, so it is intentionally left installed for\n // the document's lifetime (one passive listener, negligible cost). This\n // mirrors <wcs-clipboard>, which registers but never unregisters either.\n // unregisterAutoTrigger stays exported purely as a symmetric teardown hook\n // for tests / advanced manual control; the production lifecycle never calls\n // it.\n this._core.dispose();\n }\n}\n","import { WcsBroadcast } from \"./components/Broadcast.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.broadcast)) {\n customElements.define(config.tagNames.broadcast, WcsBroadcast);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapBroadcast(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/broadcastCapabilities.ts","../src/core/BroadcastCore.ts","../src/autoTrigger.ts","../src/components/Broadcast.ts","../src/registerComponents.ts","../src/bootstrapBroadcast.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n broadcast: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-broadcast-target\",\n tagNames: {\n broadcast: \"wcs-broadcast\",\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\n// Live reference to the mutable internal config: reads always reflect the latest\n// setConfig() call. The readonly IConfig type only blocks callers from writing\n// through it — the underlying object still changes. If you need a stable,\n// frozen snapshot that won't move under you, use getConfig() instead.\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 (typeof partialConfig.autoTrigger === \"boolean\") {\n _config.autoTrigger = partialConfig.autoTrigger;\n }\n if (typeof partialConfig.triggerAttribute === \"string\") {\n _config.triggerAttribute = partialConfig.triggerAttribute;\n }\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","/**\n * broadcastCapabilities.ts\n *\n * Broadcast node 固有の error code(taxonomy)と derivation。汎用の error info 型は\n * `./platformCapability.js`(/io-core/ から copy-distribution される生成ファイル)から\n * import する。BroadcastChannel の post / message は concurrent-independent(競合しない)\n * ため lane は持たず、error taxonomy(errorInfo)のみを採用する。\n */\n\nimport type { WcsIoErrorInfo } from \"./platformCapability.js\";\nimport type { WcsBroadcastErrorDetail } from \"../types.js\";\n\n/** 安定した broadcast error code(taxonomy)。値は公開キーとして固定。 */\nexport const WCS_BROADCAST_ERROR_CODE = {\n /** BroadcastChannel コンストラクタ不在(`_unsupportedError()` の `NotSupportedError`)。 */\n CapabilityMissing: \"capability-missing\",\n /** structured clone 不可な payload を post(`DataCloneError`)。呼び出し側入力の不備。 */\n InvalidArgument: \"invalid-argument\",\n /** その他の post / channel 失敗(DataError / InvalidStateError / \"Error\" fallback など)。 */\n BroadcastError: \"broadcast-error\",\n} as const;\n\n/**\n * 正規化済み error(`{ name, message }`)を serializable な error taxonomy に写す。\n * `name` は `DOMException.name`(`_normalizeError`)/ 合成名(`_unsupportedError` の\n * `NotSupportedError`、`messageerror` の `DataError`、post 前の `InvalidStateError`)。\n *\n * - `NotSupportedError`(BroadcastChannel 不在)は利用直前の能力欠如 → phase=\"probe\" /\n * capability-missing。\n * - `DataCloneError`(structured clone 不可な payload を post)は呼び出し側入力の不備 →\n * phase=\"execute\" / invalid-argument。\n * - それ以外(`DataError` の deserialize 失敗 / `InvalidStateError` / \"Error\" fallback)は\n * phase=\"execute\" / broadcast-error。\n * いずれも同一入力の再送では回復しない(recoverable=false)。\n */\nexport function deriveBroadcastErrorInfo(error: WcsBroadcastErrorDetail): WcsIoErrorInfo {\n if (error.name === \"NotSupportedError\") {\n return { code: WCS_BROADCAST_ERROR_CODE.CapabilityMissing, phase: \"probe\", recoverable: false, message: error.message };\n }\n if (error.name === \"DataCloneError\") {\n return { code: WCS_BROADCAST_ERROR_CODE.InvalidArgument, phase: \"execute\", recoverable: false, message: error.message };\n }\n return { code: WCS_BROADCAST_ERROR_CODE.BroadcastError, phase: \"execute\", recoverable: false, message: error.message };\n}\n","import { IWcBindable, WcsBroadcastErrorDetail } from \"../types.js\";\nimport { WcsIoErrorInfo } from \"./platformCapability.js\";\nimport { deriveBroadcastErrorInfo } from \"./broadcastCapabilities.js\";\n\n/**\n * Headless cross-tab messaging primitive. A thin, framework-agnostic wrapper\n * around the BroadcastChannel API exposed through the wc-bindable protocol.\n *\n * BroadcastChannel is a same-origin pub/sub bus: every context (tab, iframe,\n * worker) that opens a channel with the same `name` receives every other\n * context's posts — but NOT its own. This self-exclusion is the whole point:\n * `post` is a `state → element` action (command-token) and an incoming\n * `message` is an `element → state` notification (event-token), but the two\n * only close the loop *across* a context boundary. Within a single tab a lone\n * `<wcs-broadcast>` never hears itself; open the page in two tabs to see the\n * round-trip.\n *\n * Unlike WebSocketCore there is no connection state, no reconnect, and no wire\n * encoding: a channel is \"open\" the moment it is constructed, and payloads ride\n * the browser's structured clone (objects pass through as-is, no JSON\n * round-trip). The only failure surfaces are a non-cloneable `post`\n * (`DataCloneError`), a `messageerror` (a peer posted something this context\n * cannot deserialize), and an absent `BroadcastChannel` constructor\n * (`unsupported`). All three flow through the `error` property — the Core never\n * throws — symmetrical with FetchCore / ClipboardCore.\n */\nexport class BroadcastCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"message\", event: \"wcs-broadcast:message\" },\n { name: \"error\", event: \"wcs-broadcast:error\" },\n // Serializable failure taxonomy (stable code / phase / recoverable), or null.\n // Additive bindable output derived from `error` (the DOMException.name /\n // synthetic name); the existing `error` property/event are unchanged. Fires\n // wcs-broadcast:error-info-changed. No lane — post/message are concurrent-\n // independent (mirrors ClipboardCore).\n { name: \"errorInfo\", event: \"wcs-broadcast:error-info-changed\" },\n ],\n commands: [\n { name: \"open\" },\n { name: \"post\" },\n { name: \"close\" },\n ],\n };\n\n private _target: EventTarget;\n private _channel: BroadcastChannel | null = null;\n private _name: string | null = null;\n private _message: any = null;\n private _error: WcsBroadcastErrorDetail | null = null;\n private _errorInfo: WcsIoErrorInfo | null = null;\n // Generation guard (§3.4): bumped on dispose(). An incoming message /\n // messageerror that fires after the Shell disconnected (a peer posted between\n // disconnect and the channel actually closing, or a queued event drains late)\n // has a stale `gen` and MUST NOT write state to a torn-down element. A boolean\n // flag is insufficient: dispose→reconnect would let a stale event slip through.\n private _gen = 0;\n // SSR (§3.8): a channel opens synchronously (no asynchronous probe to await),\n // 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 message(): any {\n return this._message;\n }\n\n get error(): WcsBroadcastErrorDetail | null {\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-broadcast:error-info-changed`), derived from `error`; the existing\n * `error` property/event are unchanged.\n */\n get errorInfo(): WcsIoErrorInfo | null {\n return this._errorInfo;\n }\n\n // --- Lifecycle (§3.5) ---\n\n // observe() establishes monitoring. BroadcastChannel is command-driven (the\n // Shell calls open(name) from connectedCallback / attributeChangedCallback),\n // so there is no subscription for observe() to set up here: it is an idempotent\n // no-op that resolves once ready. It exists for skeleton symmetry with the\n // monitor-style nodes so a host can uniformly await observe() == ready.\n observe(): Promise<void> {\n return this._ready;\n }\n\n // --- State setters with event dispatch ---\n\n // Deliberately NO same-value guard (unlike `error` below). A received message\n // is an event, not idempotent state: a peer posting the same value twice is\n // two distinct occurrences and must re-fire wcs-broadcast:message each time so\n // a `message:` binding and any `eventToken.message:` subscriber see both.\n private _setMessage(message: any): void {\n this._message = message;\n this._target.dispatchEvent(new CustomEvent(\"wcs-broadcast:message\", {\n detail: message,\n bubbles: true,\n }));\n }\n\n private _setError(error: WcsBroadcastErrorDetail | null): void {\n // Same-value guard. `error` has no derived state, so suppressing redundant\n // null→null dispatches (e.g. a successful open clearing an already-null\n // error) avoids spurious events. Reference identity is sufficient: each\n // failure builds a fresh object, and the clear path always passes null.\n if (this._error === error) return;\n this._error = error;\n // Keep the additive `errorInfo` taxonomy in sync with `error`: derive from the\n // error name (or null on clear). Fires before the `error` event so an observer\n // binding both sees the classification first, mirroring the io-node family.\n this._commitErrorInfo(error === null ? null : deriveBroadcastErrorInfo(error));\n this._target.dispatchEvent(new CustomEvent(\"wcs-broadcast:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n // Called only from _setError (which already same-value-guards on reference\n // identity), so errorInfo transitions exactly when error does — no separate\n // guard needed here.\n private _commitErrorInfo(info: WcsIoErrorInfo | null): void {\n this._errorInfo = info;\n this._target.dispatchEvent(new CustomEvent(\"wcs-broadcast:error-info-changed\", {\n detail: info,\n bubbles: true,\n }));\n }\n\n // --- Public API ---\n\n /**\n * Join the named channel. Any previously-open channel is closed first, so\n * calling `open()` again switches channels. When the BroadcastChannel\n * constructor is unavailable this surfaces an `unsupported` error and leaves\n * the Core channel-less (a later `post()` then errors loudly rather than\n * silently dropping).\n */\n open(name: string): void {\n if (!this._hasBroadcastChannel()) {\n this._setError(this._unsupportedError());\n return;\n }\n // Idempotent on the same channel: re-opening the channel we are already on\n // is pure churn (BroadcastChannel has no reconnect semantics). This also\n // absorbs the custom-element *upgrade* path — when a connected element with\n // a `name` attribute is upgraded (autoloader defines the tag after the\n // markup exists), the spec fires attributeChangedCallback (isConnected ===\n // true) *and* connectedCallback, so the Shell calls open() twice. Without\n // this guard that would create a channel and immediately tear it down.\n if (this._channel && this._name === name) return;\n this._closeChannel();\n this._setError(null);\n // Capture the generation for this channel (§3.4). The listeners below close\n // over `gen`; an event that fires after dispose() (which bumps _gen) is\n // recognised as stale and dropped without writing state to a torn-down\n // element. The handlers are stored so _closeChannel() can remove them by the\n // same reference.\n const gen = ++this._gen;\n const channel = new BroadcastChannel(name);\n this._onMessage = (event: MessageEvent): void => {\n if (gen !== this._gen) return;\n this._setMessage(event.data);\n };\n // Fired when a peer posted a value this context cannot deserialize. The event\n // carries no usable payload, so report a synthetic DataError.\n this._onMessageError = (): void => {\n if (gen !== this._gen) return;\n this._setError({\n name: \"DataError\",\n message: \"Failed to deserialize a message received on the channel.\",\n });\n };\n channel.addEventListener(\"message\", this._onMessage);\n channel.addEventListener(\"messageerror\", this._onMessageError);\n this._channel = channel;\n this._name = name;\n }\n\n /**\n * Post a structured-cloneable value to every other context on the channel.\n * The local context never receives it (self-exclusion). Never throws:\n * a non-cloneable value surfaces as a `DataCloneError` through `error`, and\n * posting with no open channel surfaces an `InvalidStateError`.\n */\n post(data: any): void {\n if (!this._hasBroadcastChannel()) {\n this._setError(this._unsupportedError());\n return;\n }\n if (!this._channel) {\n this._setError({\n name: \"InvalidStateError\",\n message: \"Channel is not open. Call open(name) before post().\",\n });\n return;\n }\n try {\n this._channel.postMessage(data);\n } catch (err) {\n this._setError(this._normalizeError(err));\n }\n }\n\n /** Leave the channel. Idempotent — a no-op when no channel is open. */\n close(): void {\n this._closeChannel();\n }\n\n /**\n * Tear the Core down for a disconnected Shell: close the channel and reset the\n * error shadow silently (no dispatch on a torn-down element). A later\n * reconnect re-opens via the Shell's connectedCallback.\n *\n * Asymmetry by design: `_message` is deliberately NOT reset. `error` is\n * transient connection state — a stale error from a previous channel would be\n * misleading after a reconnect, so it is cleared. `message` is the last value\n * received (an event payload), not connection state; it is retained as the\n * Core's last-known datum so a binding still reads it across a disconnect/\n * reconnect, and it is naturally overwritten by the next incoming message.\n */\n dispose(): void {\n // Bump the generation first (§3.4) so any message/messageerror that drains\n // after teardown is recognised as stale, then close the channel and reset the\n // error shadow silently.\n this._gen++;\n this._closeChannel();\n this._error = null;\n // dispose bypasses _setError (silent, no dispatch on a torn-down element), so\n // clear the errorInfo mirror directly too — otherwise a stale taxonomy would\n // survive after `error` has been reset to null.\n this._errorInfo = null;\n }\n\n // --- Internal ---\n\n // Per-channel listeners, (re)created in open() so each closes over its own\n // generation (§3.4). null while no channel is open; the real handlers are\n // installed by open() and removed by the same reference in _closeChannel().\n private _onMessage: ((event: MessageEvent) => void) | null = null;\n private _onMessageError: (() => void) | null = null;\n\n private _closeChannel(): void {\n if (!this._channel) return;\n this._channel.removeEventListener(\"message\", this._onMessage!);\n this._channel.removeEventListener(\"messageerror\", this._onMessageError!);\n this._channel.close();\n this._channel = null;\n this._name = null;\n this._onMessage = null;\n this._onMessageError = null;\n }\n\n private _hasBroadcastChannel(): boolean {\n return typeof BroadcastChannel !== \"undefined\";\n }\n\n private _normalizeError(err: unknown): WcsBroadcastErrorDetail {\n if (err instanceof Error) {\n // DOMException is an Error subclass; its `name` (DataCloneError, etc.) is\n // the meaningful discriminator for consumers switching on failure kind.\n return { name: err.name, message: err.message };\n }\n return { name: \"Error\", message: String(err) };\n }\n\n private _unsupportedError(): WcsBroadcastErrorDetail {\n return {\n name: \"NotSupportedError\",\n message: \"BroadcastChannel is not available in this environment.\",\n };\n }\n}\n","import { config } from \"./config.js\";\nimport type { WcsBroadcast } from \"./components/Broadcast.js\";\n\nlet registered = false;\n\n// Attribute names for the optional post-on-click DOM trigger (clipboard.js-style\n// DX). The element carrying `data-broadcast-target` points at a <wcs-broadcast>\n// by id; the text to post comes from either a literal `data-broadcast-text` or\n// a `data-broadcast-from` CSS selector resolving to a source element.\nconst TEXT_ATTRIBUTE = \"data-broadcast-text\";\nconst FROM_ATTRIBUTE = \"data-broadcast-from\";\n\nfunction resolveText(triggerElement: Element): string | null {\n // Literal text wins when present (including an empty string — posting \"\" is a\n // legitimate request). The `?? \"\"` right-hand side is defensive and\n // unreachable: hasAttribute() just returned true, so getAttribute() cannot be\n // null here. It exists only to satisfy the `string | null` return type — do\n // not chase coverage on it (the DOM contract makes the null branch impossible).\n if (triggerElement.hasAttribute(TEXT_ATTRIBUTE)) {\n return triggerElement.getAttribute(TEXT_ATTRIBUTE) ?? \"\";\n }\n const selector = triggerElement.getAttribute(FROM_ATTRIBUTE);\n if (!selector) return null;\n // A user-authored selector can be syntactically invalid (e.g. `[data-*` or a\n // bare `:not()`), which makes querySelector throw a SyntaxError. Swallow it\n // and treat the source as unresolvable — the same \"nothing to post\" path as a\n // selector that matches no element — so one bad attribute never crashes the\n // document-level click handler and kills autoTrigger for the whole tab.\n let source: Element | null;\n try {\n source = document.querySelector(selector);\n } catch {\n return null;\n }\n if (!source) return null;\n // Read a form control's `value`; fall back to text content. A bare\n // `\"value\" in source` check is too broad — it also matches <button>,\n // <li value>, <progress>, etc. (which carry an unrelated `value`), posting the\n // wrong thing. Narrow to the text-bearing controls a user actually points\n // `data-broadcast-from` at; everything else falls through to textContent.\n if (\n source instanceof HTMLInputElement ||\n source instanceof HTMLTextAreaElement ||\n source instanceof HTMLSelectElement\n ) {\n return source.value;\n }\n // `?? \"\"` is defensive: per the DOM spec only Document / DocumentType /\n // Notation nodes have a null `textContent`, and querySelector only ever\n // returns an Element (whose textContent is always a string). The branch is\n // therefore unreachable in practice and kept solely for the `string | null`\n // type — not worth a contrived test.\n return source.textContent ?? \"\";\n}\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const broadcastId = triggerElement.getAttribute(config.triggerAttribute);\n if (!broadcastId) return;\n\n // Resolve the registered constructor at call time instead of importing\n // WcsBroadcast as a value (avoids a components ⇄ autoTrigger import cycle:\n // Broadcast.connectedCallback() calls registerAutoTrigger()). instanceof\n // against the customElements registry keeps the same identity guarantee.\n const BroadcastCtor = customElements.get(config.tagNames.broadcast);\n const broadcastElement = document.getElementById(broadcastId);\n if (!BroadcastCtor || !(broadcastElement instanceof BroadcastCtor)) return;\n\n const text = resolveText(triggerElement);\n // No resolvable source: leave the click alone (do not preventDefault) so the\n // element's default action is unaffected.\n if (text === null) return;\n\n // Suppress the default action so a post can run without navigating. Intentional:\n // do not attach data-broadcast-target to an element whose default action you\n // also want (a real <a href> link). See README \"Optional DOM Triggering\".\n event.preventDefault();\n (broadcastElement as WcsBroadcast).post(text);\n}\n\nexport function registerAutoTrigger(): void {\n if (registered) return;\n registered = true;\n document.addEventListener(\"click\", handleClick);\n}\n\nexport function unregisterAutoTrigger(): void {\n if (!registered) return;\n registered = false;\n document.removeEventListener(\"click\", handleClick);\n}\n","import { config } from \"../config.js\";\nimport { IWcBindable, WcsBroadcastErrorDetail } from \"../types.js\";\nimport { BroadcastCore } from \"../core/BroadcastCore.js\";\nimport { WcsIoErrorInfo } from \"../core/platformCapability.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\n\n// Named WcsBroadcast (not `Broadcast`) to match the <wcs-clipboard> WcsClipboard\n// / <wcs-ws> WcsWebSocket convention and avoid shadowing any global.\nexport class WcsBroadcast extends HTMLElement {\n // SSR (§4.4): the channel opens synchronously in connectedCallback, so the\n // Core's observe() resolves immediately; we still expose connectedCallbackPromise\n // so a state binder can uniformly await readiness before snapshotting.\n static hasConnectedCallbackPromise = true;\n static wcBindable: IWcBindable = {\n ...BroadcastCore.wcBindable,\n // Shell-level settable surface. `name` selects the channel; `manual`\n // suppresses auto-open on connect. There is no momentary `post` property:\n // posting needs an argument (the payload), so element actions run via\n // command-token (`command.post: $command.ping`) or the DOM autoTrigger, not\n // a value-derived setter — keeping `post` a plain command keeps the\n // command-token wiring (`command.post:`) readable.\n inputs: [\n { name: \"name\", attribute: \"name\" },\n { name: \"manual\", attribute: \"manual\" },\n ],\n // Commands are identical to the Core's — no rename needed since the `name` /\n // `manual` attribute accessors do not collide with open/post/close.\n commands: BroadcastCore.wcBindable.commands,\n };\n static get observedAttributes(): string[] { return [\"name\"]; }\n\n private _core: BroadcastCore;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new BroadcastCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n \"wcs-broadcast:error\": (d) => ({ error: d != null }),\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 (async-io-node-guidelines.md §3.6): attachInternals is absent\n // 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 name(): string {\n return this.getAttribute(\"name\") || \"\";\n }\n\n set name(value: string) {\n this.setAttribute(\"name\", value);\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n // --- Core delegated getters ---\n\n get message(): any {\n return this._core.message;\n }\n\n get error(): WcsBroadcastErrorDetail | null {\n return this._core.error;\n }\n\n get errorInfo(): WcsIoErrorInfo | null {\n return this._core.errorInfo;\n }\n\n // --- Commands ---\n\n open(): void {\n if (this.name) {\n this._core.open(this.name);\n }\n }\n\n post(data: any): void {\n this._core.post(data);\n }\n\n close(): void {\n this._core.close();\n }\n\n // --- Lifecycle ---\n\n attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void {\n if (name === \"name\" && this.isConnected && !this.manual && newValue) {\n this._core.open(newValue);\n }\n }\n\n connectedCallback(): void {\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n if (!this.manual && this.name) {\n this._core.open(this.name);\n }\n // SSR (§4.4): expose the Core's readiness as connectedCallbackPromise. The\n // channel opens synchronously above, so observe() resolves immediately.\n this._connectedCallbackPromise = this._core.observe();\n }\n\n disconnectedCallback(): void {\n // Deliberately does NOT call unregisterAutoTrigger(). The autoTrigger click\n // listener is a single process-wide document listener (registerAutoTrigger\n // is idempotent), shared by every <wcs-broadcast> on the page — not owned by\n // this element. Tearing it down when the last element disconnects would\n // break a later-inserted trigger, so it is intentionally left installed for\n // the document's lifetime (one passive listener, negligible cost). This\n // mirrors <wcs-clipboard>, which registers but never unregisters either.\n // unregisterAutoTrigger stays exported purely as a symmetric teardown hook\n // for tests / advanced manual control; the production lifecycle never calls\n // it.\n this._core.dispose();\n }\n}\n","import { WcsBroadcast } from \"./components/Broadcast.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.broadcast)) {\n customElements.define(config.tagNames.broadcast, WcsBroadcast);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapBroadcast(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n"],"names":[],"mappings":"AAUA,MAAM,OAAO,GAAoB;AAC/B,IAAA,WAAW,EAAE,IAAI;AACjB,IAAA,gBAAgB,EAAE,uBAAuB;AACzC,IAAA,QAAQ,EAAE;AACR,QAAA,SAAS,EAAE,eAAe;AAC3B,KAAA;CACF;AAED,SAAS,UAAU,CAAI,GAAM,EAAA;AAC3B,IAAA,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ;AAAE,QAAA,OAAO,GAAG;AACvD,IAAA,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;IAClB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;AAClC,QAAA,UAAU,CAAE,GAA+B,CAAC,GAAG,CAAC,CAAC;IACnD;AACA,IAAA,OAAO,GAAG;AACZ;AAEA,SAAS,SAAS,CAAI,GAAM,EAAA;AAC1B,IAAA,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ;AAAE,QAAA,OAAO,GAAG;IACvD,MAAM,KAAK,GAA4B,EAAE;IACzC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QAClC,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAAE,GAA+B,CAAC,GAAG,CAAC,CAAC;IAC/D;AACA,IAAA,OAAO,KAAU;AACnB;AAEA,IAAI,YAAY,GAAmB,IAAI;AAEvC;AACA;AACA;AACA;AACO,MAAM,MAAM,GAAY,OAAkB;SAEjC,SAAS,GAAA;IACvB,IAAI,CAAC,YAAY,EAAE;QACjB,YAAY,GAAG,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAC/C;AACA,IAAA,OAAO,YAAY;AACrB;AAEM,SAAU,SAAS,CAAC,aAA8B,EAAA;AACtD,IAAA,IAAI,OAAO,aAAa,CAAC,WAAW,KAAK,SAAS,EAAE;AAClD,QAAA,OAAO,CAAC,WAAW,GAAG,aAAa,CAAC,WAAW;IACjD;AACA,IAAA,IAAI,OAAO,aAAa,CAAC,gBAAgB,KAAK,QAAQ,EAAE;AACtD,QAAA,OAAO,CAAC,gBAAgB,GAAG,aAAa,CAAC,gBAAgB;IAC3D;AACA,IAAA,IAAI,aAAa,CAAC,QAAQ,EAAE;QAC1B,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,aAAa,CAAC,QAAQ,CAAC;IACzD;IACA,YAAY,GAAG,IAAI;AACrB;;AC9DA;;;;;;;AAOG;AAKH;AACO,MAAM,wBAAwB,GAAG;;AAEtC,IAAA,iBAAiB,EAAE,oBAAoB;;AAEvC,IAAA,eAAe,EAAE,kBAAkB;;AAEnC,IAAA,cAAc,EAAE,iBAAiB;;AAGnC;;;;;;;;;;;;AAYG;AACG,SAAU,wBAAwB,CAAC,KAA8B,EAAA;AACrE,IAAA,IAAI,KAAK,CAAC,IAAI,KAAK,mBAAmB,EAAE;QACtC,OAAO,EAAE,IAAI,EAAE,wBAAwB,CAAC,iBAAiB,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;IACzH;AACA,IAAA,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,EAAE;QACnC,OAAO,EAAE,IAAI,EAAE,wBAAwB,CAAC,eAAe,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;IACzH;IACA,OAAO,EAAE,IAAI,EAAE,wBAAwB,CAAC,cAAc,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;AACxH;;ACvCA;;;;;;;;;;;;;;;;;;;;;AAqBG;AACG,MAAO,aAAc,SAAQ,WAAW,CAAA;IAC5C,OAAO,UAAU,GAAgB;AAC/B,QAAA,QAAQ,EAAE,aAAa;AACvB,QAAA,OAAO,EAAE,CAAC;AACV,QAAA,UAAU,EAAE;AACV,YAAA,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,uBAAuB,EAAE;AACnD,YAAA,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,qBAAqB,EAAE;;;;;;AAM/C,YAAA,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,kCAAkC,EAAE;AACjE,SAAA;AACD,QAAA,QAAQ,EAAE;YACR,EAAE,IAAI,EAAE,MAAM,EAAE;YAChB,EAAE,IAAI,EAAE,MAAM,EAAE;YAChB,EAAE,IAAI,EAAE,OAAO,EAAE;AAClB,SAAA;KACF;AAEO,IAAA,OAAO;IACP,QAAQ,GAA4B,IAAI;IACxC,KAAK,GAAkB,IAAI;IAC3B,QAAQ,GAAQ,IAAI;IACpB,MAAM,GAAmC,IAAI;IAC7C,UAAU,GAA0B,IAAI;;;;;;IAMxC,IAAI,GAAG,CAAC;;;AAGR,IAAA,MAAM,GAAkB,OAAO,CAAC,OAAO,EAAE;AAEjD,IAAA,WAAA,CAAY,MAAoB,EAAA;AAC9B,QAAA,KAAK,EAAE;AACP,QAAA,IAAI,CAAC,OAAO,GAAG,MAAM,IAAI,IAAI;IAC/B;AAEA,IAAA,IAAI,KAAK,GAAA;QACP,OAAO,IAAI,CAAC,MAAM;IACpB;AAEA,IAAA,IAAI,OAAO,GAAA;QACT,OAAO,IAAI,CAAC,QAAQ;IACtB;AAEA,IAAA,IAAI,KAAK,GAAA;QACP,OAAO,IAAI,CAAC,MAAM;IACpB;AAEA;;;;;AAKG;AACH,IAAA,IAAI,SAAS,GAAA;QACX,OAAO,IAAI,CAAC,UAAU;IACxB;;;;;;;IASA,OAAO,GAAA;QACL,OAAO,IAAI,CAAC,MAAM;IACpB;;;;;;AAQQ,IAAA,WAAW,CAAC,OAAY,EAAA;AAC9B,QAAA,IAAI,CAAC,QAAQ,GAAG,OAAO;QACvB,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,uBAAuB,EAAE;AAClE,YAAA,MAAM,EAAE,OAAO;AACf,YAAA,OAAO,EAAE,IAAI;AACd,SAAA,CAAC,CAAC;IACL;AAEQ,IAAA,SAAS,CAAC,KAAqC,EAAA;;;;;AAKrD,QAAA,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK;YAAE;AAC3B,QAAA,IAAI,CAAC,MAAM,GAAG,KAAK;;;;AAInB,QAAA,IAAI,CAAC,gBAAgB,CAAC,KAAK,KAAK,IAAI,GAAG,IAAI,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;QAC9E,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,qBAAqB,EAAE;AAChE,YAAA,MAAM,EAAE,KAAK;AACb,YAAA,OAAO,EAAE,IAAI;AACd,SAAA,CAAC,CAAC;IACL;;;;AAKQ,IAAA,gBAAgB,CAAC,IAA2B,EAAA;AAClD,QAAA,IAAI,CAAC,UAAU,GAAG,IAAI;QACtB,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,kCAAkC,EAAE;AAC7E,YAAA,MAAM,EAAE,IAAI;AACZ,YAAA,OAAO,EAAE,IAAI;AACd,SAAA,CAAC,CAAC;IACL;;AAIA;;;;;;AAMG;AACH,IAAA,IAAI,CAAC,IAAY,EAAA;AACf,QAAA,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE;YAChC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACxC;QACF;;;;;;;;QAQA,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI;YAAE;QAC1C,IAAI,CAAC,aAAa,EAAE;AACpB,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;;;;;;AAMpB,QAAA,MAAM,GAAG,GAAG,EAAE,IAAI,CAAC,IAAI;AACvB,QAAA,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC;AAC1C,QAAA,IAAI,CAAC,UAAU,GAAG,CAAC,KAAmB,KAAU;AAC9C,YAAA,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI;gBAAE;AACvB,YAAA,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC;AAC9B,QAAA,CAAC;;;AAGD,QAAA,IAAI,CAAC,eAAe,GAAG,MAAW;AAChC,YAAA,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI;gBAAE;YACvB,IAAI,CAAC,SAAS,CAAC;AACb,gBAAA,IAAI,EAAE,WAAW;AACjB,gBAAA,OAAO,EAAE,0DAA0D;AACpE,aAAA,CAAC;AACJ,QAAA,CAAC;QACD,OAAO,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,UAAU,CAAC;QACpD,OAAO,CAAC,gBAAgB,CAAC,cAAc,EAAE,IAAI,CAAC,eAAe,CAAC;AAC9D,QAAA,IAAI,CAAC,QAAQ,GAAG,OAAO;AACvB,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI;IACnB;AAEA;;;;;AAKG;AACH,IAAA,IAAI,CAAC,IAAS,EAAA;AACZ,QAAA,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE;YAChC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACxC;QACF;AACA,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YAClB,IAAI,CAAC,SAAS,CAAC;AACb,gBAAA,IAAI,EAAE,mBAAmB;AACzB,gBAAA,OAAO,EAAE,qDAAqD;AAC/D,aAAA,CAAC;YACF;QACF;AACA,QAAA,IAAI;AACF,YAAA,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC;QACjC;QAAE,OAAO,GAAG,EAAE;YACZ,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;QAC3C;IACF;;IAGA,KAAK,GAAA;QACH,IAAI,CAAC,aAAa,EAAE;IACtB;AAEA;;;;;;;;;;;AAWG;IACH,OAAO,GAAA;;;;QAIL,IAAI,CAAC,IAAI,EAAE;QACX,IAAI,CAAC,aAAa,EAAE;AACpB,QAAA,IAAI,CAAC,MAAM,GAAG,IAAI;;;;AAIlB,QAAA,IAAI,CAAC,UAAU,GAAG,IAAI;IACxB;;;;;IAOQ,UAAU,GAA2C,IAAI;IACzD,eAAe,GAAwB,IAAI;IAE3C,aAAa,GAAA;QACnB,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE;QACpB,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,UAAW,CAAC;QAC9D,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,cAAc,EAAE,IAAI,CAAC,eAAgB,CAAC;AACxE,QAAA,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE;AACrB,QAAA,IAAI,CAAC,QAAQ,GAAG,IAAI;AACpB,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI;AACjB,QAAA,IAAI,CAAC,UAAU,GAAG,IAAI;AACtB,QAAA,IAAI,CAAC,eAAe,GAAG,IAAI;IAC7B;IAEQ,oBAAoB,GAAA;AAC1B,QAAA,OAAO,OAAO,gBAAgB,KAAK,WAAW;IAChD;AAEQ,IAAA,eAAe,CAAC,GAAY,EAAA;AAClC,QAAA,IAAI,GAAG,YAAY,KAAK,EAAE;;;AAGxB,YAAA,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE;QACjD;AACA,QAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE;IAChD;IAEQ,iBAAiB,GAAA;QACvB,OAAO;AACL,YAAA,IAAI,EAAE,mBAAmB;AACzB,YAAA,OAAO,EAAE,wDAAwD;SAClE;IACH;;;AC1RF,IAAI,UAAU,GAAG,KAAK;AAEtB;AACA;AACA;AACA;AACA,MAAM,cAAc,GAAG,qBAAqB;AAC5C,MAAM,cAAc,GAAG,qBAAqB;AAE5C,SAAS,WAAW,CAAC,cAAuB,EAAA;;;;;;AAM1C,IAAA,IAAI,cAAc,CAAC,YAAY,CAAC,cAAc,CAAC,EAAE;QAC/C,OAAO,cAAc,CAAC,YAAY,CAAC,cAAc,CAAC,IAAI,EAAE;IAC1D;IACA,MAAM,QAAQ,GAAG,cAAc,CAAC,YAAY,CAAC,cAAc,CAAC;AAC5D,IAAA,IAAI,CAAC,QAAQ;AAAE,QAAA,OAAO,IAAI;;;;;;AAM1B,IAAA,IAAI,MAAsB;AAC1B,IAAA,IAAI;AACF,QAAA,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC;IAC3C;AAAE,IAAA,MAAM;AACN,QAAA,OAAO,IAAI;IACb;AACA,IAAA,IAAI,CAAC,MAAM;AAAE,QAAA,OAAO,IAAI;;;;;;IAMxB,IACE,MAAM,YAAY,gBAAgB;AAClC,QAAA,MAAM,YAAY,mBAAmB;QACrC,MAAM,YAAY,iBAAiB,EACnC;QACA,OAAO,MAAM,CAAC,KAAK;IACrB;;;;;;AAMA,IAAA,OAAO,MAAM,CAAC,WAAW,IAAI,EAAE;AACjC;AAEA,SAAS,WAAW,CAAC,KAAY,EAAA;AAC/B,IAAA,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM;AAC3B,IAAA,IAAI,EAAE,MAAM,YAAY,OAAO,CAAC;QAAE;AAElC,IAAA,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,CAAU,CAAA,CAAA,EAAI,MAAM,CAAC,gBAAgB,CAAA,CAAA,CAAG,CAAC;AAC9E,IAAA,IAAI,CAAC,cAAc;QAAE;IAErB,MAAM,WAAW,GAAG,cAAc,CAAC,YAAY,CAAC,MAAM,CAAC,gBAAgB,CAAC;AACxE,IAAA,IAAI,CAAC,WAAW;QAAE;;;;;AAMlB,IAAA,MAAM,aAAa,GAAG,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;IACnE,MAAM,gBAAgB,GAAG,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC;IAC7D,IAAI,CAAC,aAAa,IAAI,EAAE,gBAAgB,YAAY,aAAa,CAAC;QAAE;AAEpE,IAAA,MAAM,IAAI,GAAG,WAAW,CAAC,cAAc,CAAC;;;IAGxC,IAAI,IAAI,KAAK,IAAI;QAAE;;;;IAKnB,KAAK,CAAC,cAAc,EAAE;AACrB,IAAA,gBAAiC,CAAC,IAAI,CAAC,IAAI,CAAC;AAC/C;SAEgB,mBAAmB,GAAA;AACjC,IAAA,IAAI,UAAU;QAAE;IAChB,UAAU,GAAG,IAAI;AACjB,IAAA,QAAQ,CAAC,gBAAgB,CAAC,OAAO,EAAE,WAAW,CAAC;AACjD;;ACnFA;AACA;AACM,MAAO,YAAa,SAAQ,WAAW,CAAA;;;;AAI3C,IAAA,OAAO,2BAA2B,GAAG,IAAI;IACzC,OAAO,UAAU,GAAgB;QAC/B,GAAG,aAAa,CAAC,UAAU;;;;;;;AAO3B,QAAA,MAAM,EAAE;AACN,YAAA,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE;AACnC,YAAA,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE;AACxC,SAAA;;;AAGD,QAAA,QAAQ,EAAE,aAAa,CAAC,UAAU,CAAC,QAAQ;KAC5C;IACD,WAAW,kBAAkB,GAAA,EAAe,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AAErD,IAAA,KAAK;AACL,IAAA,yBAAyB,GAAkB,OAAO,CAAC,OAAO,EAAE;IAC5D,UAAU,GAA4B,IAAI;AAElD,IAAA,WAAA,GAAA;AACE,QAAA,KAAK,EAAE;QACP,IAAI,CAAC,KAAK,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC;AACpC,QAAA,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,cAAc,EAAE;QACvC,IAAI,CAAC,WAAW,CAAC;AACf,YAAA,qBAAqB,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;AACrD,SAAA,CAAC;IACJ;;;;;AAMA,IAAA,IAAI,WAAW,GAAA;AACb,QAAA,OAAO,IAAI,CAAC,UAAU,GAAG,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,EAAE;IAC3D;IAEQ,cAAc,GAAA;;;;;;AAMpB,QAAA,IAAI;AACF,YAAA,IAAI,OAAO,IAAI,CAAC,eAAe,KAAK,UAAU;AAAE,gBAAA,OAAO,IAAI;AAC3D,YAAA,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,EAAE;AACxC,YAAA,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC;AACjC,YAAA,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC;AACpC,YAAA,OAAO,SAAS;QAClB;AAAE,QAAA,MAAM;AACN,YAAA,OAAO,IAAI;QACb;IACF;AAEQ,IAAA,WAAW,CAAC,GAA6D,EAAA;AAC/E,QAAA,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI;YAAE;AAC9B,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM;AACrC,QAAA,KAAK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;YACnD,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAC,KAAI;gBACjC,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC;AAC/C,gBAAA,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAE,CAAiB,CAAC,MAAM,CAAC,CAAC,EAAE;AAC5E,oBAAA,IAAI;wBACF,IAAI,EAAE,EAAE;AAAE,4BAAA,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;wBAAE;6BAAO;AAAE,4BAAA,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;wBAAE;oBAC5D;AAAE,oBAAA,MAAM,oBAAoB;AAC5B,oBAAA,IAAI,KAAK;wBAAE,IAAI,CAAC,eAAe,CAAC,CAAA,eAAA,EAAkB,IAAI,CAAA,CAAE,EAAE,EAAE,CAAC;gBAC/D;AACF,YAAA,CAAC,CAAC;QACJ;IACF;AAEA,IAAA,IAAI,wBAAwB,GAAA;QAC1B,OAAO,IAAI,CAAC,yBAAyB;IACvC;;AAIA,IAAA,IAAI,IAAI,GAAA;QACN,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE;IACxC;IAEA,IAAI,IAAI,CAAC,KAAa,EAAA;AACpB,QAAA,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC;IAClC;AAEA,IAAA,IAAI,MAAM,GAAA;AACR,QAAA,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC;IACpC;IAEA,IAAI,MAAM,CAAC,KAAc,EAAA;QACvB,IAAI,KAAK,EAAE;AACT,YAAA,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAC;QACjC;aAAO;AACL,YAAA,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC;QAChC;IACF;;AAIA,IAAA,IAAI,OAAO,GAAA;AACT,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO;IAC3B;AAEA,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK;IACzB;AAEA,IAAA,IAAI,SAAS,GAAA;AACX,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS;IAC7B;;IAIA,IAAI,GAAA;AACF,QAAA,IAAI,IAAI,CAAC,IAAI,EAAE;YACb,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QAC5B;IACF;AAEA,IAAA,IAAI,CAAC,IAAS,EAAA;AACZ,QAAA,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;IACvB;IAEA,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;IACpB;;AAIA,IAAA,wBAAwB,CAAC,IAAY,EAAE,SAAwB,EAAE,QAAuB,EAAA;AACtF,QAAA,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,QAAQ,EAAE;AACnE,YAAA,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;QAC3B;IACF;IAEA,iBAAiB,GAAA;AACf,QAAA,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM;AAC3B,QAAA,IAAI,MAAM,CAAC,WAAW,EAAE;AACtB,YAAA,mBAAmB,EAAE;QACvB;QACA,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,EAAE;YAC7B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QAC5B;;;QAGA,IAAI,CAAC,yBAAyB,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE;IACvD;IAEA,oBAAoB,GAAA;;;;;;;;;;;AAWlB,QAAA,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE;IACtB;;;SC3Kc,kBAAkB,GAAA;AAChC,IAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE;QAClD,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IAChE;AACF;;ACHM,SAAU,kBAAkB,CAAC,UAA4B,EAAA;IAC7D,IAAI,UAAU,EAAE;QACd,SAAS,CAAC,UAAU,CAAC;IACvB;AACA,IAAA,kBAAkB,EAAE;AACtB;;;;"}
|
package/dist/index.esm.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e={autoTrigger:!0,triggerAttribute:"data-broadcast-target",tagNames:{broadcast:"wcs-broadcast"}};function t(e){if(null===e||"object"!=typeof e)return e;Object.freeze(e);for(const
|
|
1
|
+
const e={autoTrigger:!0,triggerAttribute:"data-broadcast-target",tagNames:{broadcast:"wcs-broadcast"}};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 s of Object.keys(e))t[s]=r(e[s]);return t}let s=null;const n=e;function a(){return s||(s=t(r(e))),s}const o={CapabilityMissing:"capability-missing",InvalidArgument:"invalid-argument",BroadcastError:"broadcast-error"};class i extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"message",event:"wcs-broadcast:message"},{name:"error",event:"wcs-broadcast:error"},{name:"errorInfo",event:"wcs-broadcast:error-info-changed"}],commands:[{name:"open"},{name:"post"},{name:"close"}]};_target;_channel=null;_name=null;_message=null;_error=null;_errorInfo=null;_gen=0;_ready=Promise.resolve();constructor(e){super(),this._target=e??this}get ready(){return this._ready}get message(){return this._message}get error(){return this._error}get errorInfo(){return this._errorInfo}observe(){return this._ready}_setMessage(e){this._message=e,this._target.dispatchEvent(new CustomEvent("wcs-broadcast:message",{detail:e,bubbles:!0}))}_setError(e){this._error!==e&&(this._error=e,this._commitErrorInfo(null===e?null:function(e){return"NotSupportedError"===e.name?{code:o.CapabilityMissing,phase:"probe",recoverable:!1,message:e.message}:"DataCloneError"===e.name?{code:o.InvalidArgument,phase:"execute",recoverable:!1,message:e.message}:{code:o.BroadcastError,phase:"execute",recoverable:!1,message:e.message}}(e)),this._target.dispatchEvent(new CustomEvent("wcs-broadcast:error",{detail:e,bubbles:!0})))}_commitErrorInfo(e){this._errorInfo=e,this._target.dispatchEvent(new CustomEvent("wcs-broadcast:error-info-changed",{detail:e,bubbles:!0}))}open(e){if(!this._hasBroadcastChannel())return void this._setError(this._unsupportedError());if(this._channel&&this._name===e)return;this._closeChannel(),this._setError(null);const t=++this._gen,r=new BroadcastChannel(e);this._onMessage=e=>{t===this._gen&&this._setMessage(e.data)},this._onMessageError=()=>{t===this._gen&&this._setError({name:"DataError",message:"Failed to deserialize a message received on the channel."})},r.addEventListener("message",this._onMessage),r.addEventListener("messageerror",this._onMessageError),this._channel=r,this._name=e}post(e){if(this._hasBroadcastChannel())if(this._channel)try{this._channel.postMessage(e)}catch(e){this._setError(this._normalizeError(e))}else this._setError({name:"InvalidStateError",message:"Channel is not open. Call open(name) before post()."});else this._setError(this._unsupportedError())}close(){this._closeChannel()}dispose(){this._gen++,this._closeChannel(),this._error=null,this._errorInfo=null}_onMessage=null;_onMessageError=null;_closeChannel(){this._channel&&(this._channel.removeEventListener("message",this._onMessage),this._channel.removeEventListener("messageerror",this._onMessageError),this._channel.close(),this._channel=null,this._name=null,this._onMessage=null,this._onMessageError=null)}_hasBroadcastChannel(){return"undefined"!=typeof BroadcastChannel}_normalizeError(e){return e instanceof Error?{name:e.name,message:e.message}:{name:"Error",message:String(e)}}_unsupportedError(){return{name:"NotSupportedError",message:"BroadcastChannel is not available in this environment."}}}let c=!1;const l="data-broadcast-text";function u(e){const t=e.target;if(!(t instanceof Element))return;const r=t.closest(`[${n.triggerAttribute}]`);if(!r)return;const s=r.getAttribute(n.triggerAttribute);if(!s)return;const a=customElements.get(n.tagNames.broadcast),o=document.getElementById(s);if(!(a&&o instanceof a))return;const i=function(e){if(e.hasAttribute(l))return e.getAttribute(l)??"";const t=e.getAttribute("data-broadcast-from");if(!t)return null;let r;try{r=document.querySelector(t)}catch{return null}return r?r instanceof HTMLInputElement||r instanceof HTMLTextAreaElement||r instanceof HTMLSelectElement?r.value:r.textContent??"":null}(r);null!==i&&(e.preventDefault(),o.post(i))}class h extends HTMLElement{static hasConnectedCallbackPromise=!0;static wcBindable={...i.wcBindable,inputs:[{name:"name",attribute:"name"},{name:"manual",attribute:"manual"}],commands:i.wcBindable.commands};static get observedAttributes(){return["name"]}_core;_connectedCallbackPromise=Promise.resolve();_internals=null;constructor(){super(),this._core=new i(this),this._internals=this._initInternals(),this._wireStates({"wcs-broadcast:error":e=>({error:null!=e})})}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,s]of Object.entries(e))this.addEventListener(r,e=>{const r=this.hasAttribute("debug-states");for(const[n,a]of Object.entries(s(e.detail))){try{a?t.add(n):t.delete(n)}catch{}r&&this.toggleAttribute(`data-wcs-state-${n}`,a)}})}get connectedCallbackPromise(){return this._connectedCallbackPromise}get name(){return this.getAttribute("name")||""}set name(e){this.setAttribute("name",e)}get manual(){return this.hasAttribute("manual")}set manual(e){e?this.setAttribute("manual",""):this.removeAttribute("manual")}get message(){return this._core.message}get error(){return this._core.error}get errorInfo(){return this._core.errorInfo}open(){this.name&&this._core.open(this.name)}post(e){this._core.post(e)}close(){this._core.close()}attributeChangedCallback(e,t,r){"name"===e&&this.isConnected&&!this.manual&&r&&this._core.open(r)}connectedCallback(){this.style.display="none",n.autoTrigger&&(c||(c=!0,document.addEventListener("click",u))),!this.manual&&this.name&&this._core.open(this.name),this._connectedCallbackPromise=this._core.observe()}disconnectedCallback(){this._core.dispose()}}function m(t){var r;t&&("boolean"==typeof(r=t).autoTrigger&&(e.autoTrigger=r.autoTrigger),"string"==typeof r.triggerAttribute&&(e.triggerAttribute=r.triggerAttribute),r.tagNames&&Object.assign(e.tagNames,r.tagNames),s=null),customElements.get(n.tagNames.broadcast)||customElements.define(n.tagNames.broadcast,h)}export{i as BroadcastCore,o as WCS_BROADCAST_ERROR_CODE,h as WcsBroadcast,m as bootstrapBroadcast,a 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/BroadcastCore.ts","../src/autoTrigger.ts","../src/components/Broadcast.ts","../src/bootstrapBroadcast.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n broadcast: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-broadcast-target\",\n tagNames: {\n broadcast: \"wcs-broadcast\",\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\n// Live reference to the mutable internal config: reads always reflect the latest\n// setConfig() call. The readonly IConfig type only blocks callers from writing\n// through it — the underlying object still changes. If you need a stable,\n// frozen snapshot that won't move under you, use getConfig() instead.\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 (typeof partialConfig.autoTrigger === \"boolean\") {\n _config.autoTrigger = partialConfig.autoTrigger;\n }\n if (typeof partialConfig.triggerAttribute === \"string\") {\n _config.triggerAttribute = partialConfig.triggerAttribute;\n }\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { IWcBindable, WcsBroadcastErrorDetail } from \"../types.js\";\n\n/**\n * Headless cross-tab messaging primitive. A thin, framework-agnostic wrapper\n * around the BroadcastChannel API exposed through the wc-bindable protocol.\n *\n * BroadcastChannel is a same-origin pub/sub bus: every context (tab, iframe,\n * worker) that opens a channel with the same `name` receives every other\n * context's posts — but NOT its own. This self-exclusion is the whole point:\n * `post` is a `state → element` action (command-token) and an incoming\n * `message` is an `element → state` notification (event-token), but the two\n * only close the loop *across* a context boundary. Within a single tab a lone\n * `<wcs-broadcast>` never hears itself; open the page in two tabs to see the\n * round-trip.\n *\n * Unlike WebSocketCore there is no connection state, no reconnect, and no wire\n * encoding: a channel is \"open\" the moment it is constructed, and payloads ride\n * the browser's structured clone (objects pass through as-is, no JSON\n * round-trip). The only failure surfaces are a non-cloneable `post`\n * (`DataCloneError`), a `messageerror` (a peer posted something this context\n * cannot deserialize), and an absent `BroadcastChannel` constructor\n * (`unsupported`). All three flow through the `error` property — the Core never\n * throws — symmetrical with FetchCore / ClipboardCore.\n */\nexport class BroadcastCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"message\", event: \"wcs-broadcast:message\" },\n { name: \"error\", event: \"wcs-broadcast:error\" },\n ],\n commands: [\n { name: \"open\" },\n { name: \"post\" },\n { name: \"close\" },\n ],\n };\n\n private _target: EventTarget;\n private _channel: BroadcastChannel | null = null;\n private _name: string | null = null;\n private _message: any = null;\n private _error: WcsBroadcastErrorDetail | null = null;\n // Generation guard (§3.4): bumped on dispose(). An incoming message /\n // messageerror that fires after the Shell disconnected (a peer posted between\n // disconnect and the channel actually closing, or a queued event drains late)\n // has a stale `gen` and MUST NOT write state to a torn-down element. A boolean\n // flag is insufficient: dispose→reconnect would let a stale event slip through.\n private _gen = 0;\n // SSR (§3.8): a channel opens synchronously (no asynchronous probe to await),\n // 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 message(): any {\n return this._message;\n }\n\n get error(): WcsBroadcastErrorDetail | null {\n return this._error;\n }\n\n // --- Lifecycle (§3.5) ---\n\n // observe() establishes monitoring. BroadcastChannel is command-driven (the\n // Shell calls open(name) from connectedCallback / attributeChangedCallback),\n // so there is no subscription for observe() to set up here: it is an idempotent\n // no-op that resolves once ready. It exists for skeleton symmetry with the\n // monitor-style nodes so a host can uniformly await observe() == ready.\n observe(): Promise<void> {\n return this._ready;\n }\n\n // --- State setters with event dispatch ---\n\n // Deliberately NO same-value guard (unlike `error` below). A received message\n // is an event, not idempotent state: a peer posting the same value twice is\n // two distinct occurrences and must re-fire wcs-broadcast:message each time so\n // a `message:` binding and any `eventToken.message:` subscriber see both.\n private _setMessage(message: any): void {\n this._message = message;\n this._target.dispatchEvent(new CustomEvent(\"wcs-broadcast:message\", {\n detail: message,\n bubbles: true,\n }));\n }\n\n private _setError(error: WcsBroadcastErrorDetail | null): void {\n // Same-value guard. `error` has no derived state, so suppressing redundant\n // null→null dispatches (e.g. a successful open clearing an already-null\n // error) avoids spurious events. Reference identity is sufficient: each\n // failure builds a fresh object, and the clear path always passes null.\n if (this._error === error) return;\n this._error = error;\n this._target.dispatchEvent(new CustomEvent(\"wcs-broadcast:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n // --- Public API ---\n\n /**\n * Join the named channel. Any previously-open channel is closed first, so\n * calling `open()` again switches channels. When the BroadcastChannel\n * constructor is unavailable this surfaces an `unsupported` error and leaves\n * the Core channel-less (a later `post()` then errors loudly rather than\n * silently dropping).\n */\n open(name: string): void {\n if (!this._hasBroadcastChannel()) {\n this._setError(this._unsupportedError());\n return;\n }\n // Idempotent on the same channel: re-opening the channel we are already on\n // is pure churn (BroadcastChannel has no reconnect semantics). This also\n // absorbs the custom-element *upgrade* path — when a connected element with\n // a `name` attribute is upgraded (autoloader defines the tag after the\n // markup exists), the spec fires attributeChangedCallback (isConnected ===\n // true) *and* connectedCallback, so the Shell calls open() twice. Without\n // this guard that would create a channel and immediately tear it down.\n if (this._channel && this._name === name) return;\n this._closeChannel();\n this._setError(null);\n // Capture the generation for this channel (§3.4). The listeners below close\n // over `gen`; an event that fires after dispose() (which bumps _gen) is\n // recognised as stale and dropped without writing state to a torn-down\n // element. The handlers are stored so _closeChannel() can remove them by the\n // same reference.\n const gen = ++this._gen;\n const channel = new BroadcastChannel(name);\n this._onMessage = (event: MessageEvent): void => {\n if (gen !== this._gen) return;\n this._setMessage(event.data);\n };\n // Fired when a peer posted a value this context cannot deserialize. The event\n // carries no usable payload, so report a synthetic DataError.\n this._onMessageError = (): void => {\n if (gen !== this._gen) return;\n this._setError({\n name: \"DataError\",\n message: \"Failed to deserialize a message received on the channel.\",\n });\n };\n channel.addEventListener(\"message\", this._onMessage);\n channel.addEventListener(\"messageerror\", this._onMessageError);\n this._channel = channel;\n this._name = name;\n }\n\n /**\n * Post a structured-cloneable value to every other context on the channel.\n * The local context never receives it (self-exclusion). Never throws:\n * a non-cloneable value surfaces as a `DataCloneError` through `error`, and\n * posting with no open channel surfaces an `InvalidStateError`.\n */\n post(data: any): void {\n if (!this._hasBroadcastChannel()) {\n this._setError(this._unsupportedError());\n return;\n }\n if (!this._channel) {\n this._setError({\n name: \"InvalidStateError\",\n message: \"Channel is not open. Call open(name) before post().\",\n });\n return;\n }\n try {\n this._channel.postMessage(data);\n } catch (err) {\n this._setError(this._normalizeError(err));\n }\n }\n\n /** Leave the channel. Idempotent — a no-op when no channel is open. */\n close(): void {\n this._closeChannel();\n }\n\n /**\n * Tear the Core down for a disconnected Shell: close the channel and reset the\n * error shadow silently (no dispatch on a torn-down element). A later\n * reconnect re-opens via the Shell's connectedCallback.\n *\n * Asymmetry by design: `_message` is deliberately NOT reset. `error` is\n * transient connection state — a stale error from a previous channel would be\n * misleading after a reconnect, so it is cleared. `message` is the last value\n * received (an event payload), not connection state; it is retained as the\n * Core's last-known datum so a binding still reads it across a disconnect/\n * reconnect, and it is naturally overwritten by the next incoming message.\n */\n dispose(): void {\n // Bump the generation first (§3.4) so any message/messageerror that drains\n // after teardown is recognised as stale, then close the channel and reset the\n // error shadow silently.\n this._gen++;\n this._closeChannel();\n this._error = null;\n }\n\n // --- Internal ---\n\n // Per-channel listeners, (re)created in open() so each closes over its own\n // generation (§3.4). null while no channel is open; the real handlers are\n // installed by open() and removed by the same reference in _closeChannel().\n private _onMessage: ((event: MessageEvent) => void) | null = null;\n private _onMessageError: (() => void) | null = null;\n\n private _closeChannel(): void {\n if (!this._channel) return;\n this._channel.removeEventListener(\"message\", this._onMessage!);\n this._channel.removeEventListener(\"messageerror\", this._onMessageError!);\n this._channel.close();\n this._channel = null;\n this._name = null;\n this._onMessage = null;\n this._onMessageError = null;\n }\n\n private _hasBroadcastChannel(): boolean {\n return typeof BroadcastChannel !== \"undefined\";\n }\n\n private _normalizeError(err: unknown): WcsBroadcastErrorDetail {\n if (err instanceof Error) {\n // DOMException is an Error subclass; its `name` (DataCloneError, etc.) is\n // the meaningful discriminator for consumers switching on failure kind.\n return { name: err.name, message: err.message };\n }\n return { name: \"Error\", message: String(err) };\n }\n\n private _unsupportedError(): WcsBroadcastErrorDetail {\n return {\n name: \"NotSupportedError\",\n message: \"BroadcastChannel is not available in this environment.\",\n };\n }\n}\n","import { config } from \"./config.js\";\nimport type { WcsBroadcast } from \"./components/Broadcast.js\";\n\nlet registered = false;\n\n// Attribute names for the optional post-on-click DOM trigger (clipboard.js-style\n// DX). The element carrying `data-broadcast-target` points at a <wcs-broadcast>\n// by id; the text to post comes from either a literal `data-broadcast-text` or\n// a `data-broadcast-from` CSS selector resolving to a source element.\nconst TEXT_ATTRIBUTE = \"data-broadcast-text\";\nconst FROM_ATTRIBUTE = \"data-broadcast-from\";\n\nfunction resolveText(triggerElement: Element): string | null {\n // Literal text wins when present (including an empty string — posting \"\" is a\n // legitimate request). The `?? \"\"` right-hand side is defensive and\n // unreachable: hasAttribute() just returned true, so getAttribute() cannot be\n // null here. It exists only to satisfy the `string | null` return type — do\n // not chase coverage on it (the DOM contract makes the null branch impossible).\n if (triggerElement.hasAttribute(TEXT_ATTRIBUTE)) {\n return triggerElement.getAttribute(TEXT_ATTRIBUTE) ?? \"\";\n }\n const selector = triggerElement.getAttribute(FROM_ATTRIBUTE);\n if (!selector) return null;\n // A user-authored selector can be syntactically invalid (e.g. `[data-*` or a\n // bare `:not()`), which makes querySelector throw a SyntaxError. Swallow it\n // and treat the source as unresolvable — the same \"nothing to post\" path as a\n // selector that matches no element — so one bad attribute never crashes the\n // document-level click handler and kills autoTrigger for the whole tab.\n let source: Element | null;\n try {\n source = document.querySelector(selector);\n } catch {\n return null;\n }\n if (!source) return null;\n // Read a form control's `value`; fall back to text content. A bare\n // `\"value\" in source` check is too broad — it also matches <button>,\n // <li value>, <progress>, etc. (which carry an unrelated `value`), posting the\n // wrong thing. Narrow to the text-bearing controls a user actually points\n // `data-broadcast-from` at; everything else falls through to textContent.\n if (\n source instanceof HTMLInputElement ||\n source instanceof HTMLTextAreaElement ||\n source instanceof HTMLSelectElement\n ) {\n return source.value;\n }\n // `?? \"\"` is defensive: per the DOM spec only Document / DocumentType /\n // Notation nodes have a null `textContent`, and querySelector only ever\n // returns an Element (whose textContent is always a string). The branch is\n // therefore unreachable in practice and kept solely for the `string | null`\n // type — not worth a contrived test.\n return source.textContent ?? \"\";\n}\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const broadcastId = triggerElement.getAttribute(config.triggerAttribute);\n if (!broadcastId) return;\n\n // Resolve the registered constructor at call time instead of importing\n // WcsBroadcast as a value (avoids a components ⇄ autoTrigger import cycle:\n // Broadcast.connectedCallback() calls registerAutoTrigger()). instanceof\n // against the customElements registry keeps the same identity guarantee.\n const BroadcastCtor = customElements.get(config.tagNames.broadcast);\n const broadcastElement = document.getElementById(broadcastId);\n if (!BroadcastCtor || !(broadcastElement instanceof BroadcastCtor)) return;\n\n const text = resolveText(triggerElement);\n // No resolvable source: leave the click alone (do not preventDefault) so the\n // element's default action is unaffected.\n if (text === null) return;\n\n // Suppress the default action so a post can run without navigating. Intentional:\n // do not attach data-broadcast-target to an element whose default action you\n // also want (a real <a href> link). See README \"Optional DOM Triggering\".\n event.preventDefault();\n (broadcastElement as WcsBroadcast).post(text);\n}\n\nexport function registerAutoTrigger(): void {\n if (registered) return;\n registered = true;\n document.addEventListener(\"click\", handleClick);\n}\n\nexport function unregisterAutoTrigger(): void {\n if (!registered) return;\n registered = false;\n document.removeEventListener(\"click\", handleClick);\n}\n","import { config } from \"../config.js\";\nimport { IWcBindable, WcsBroadcastErrorDetail } from \"../types.js\";\nimport { BroadcastCore } from \"../core/BroadcastCore.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\n\n// Named WcsBroadcast (not `Broadcast`) to match the <wcs-clipboard> WcsClipboard\n// / <wcs-ws> WcsWebSocket convention and avoid shadowing any global.\nexport class WcsBroadcast extends HTMLElement {\n // SSR (§4.4): the channel opens synchronously in connectedCallback, so the\n // Core's observe() resolves immediately; we still expose connectedCallbackPromise\n // so a state binder can uniformly await readiness before snapshotting.\n static hasConnectedCallbackPromise = true;\n static wcBindable: IWcBindable = {\n ...BroadcastCore.wcBindable,\n // Shell-level settable surface. `name` selects the channel; `manual`\n // suppresses auto-open on connect. There is no momentary `post` property:\n // posting needs an argument (the payload), so element actions run via\n // command-token (`command.post: $command.ping`) or the DOM autoTrigger, not\n // a value-derived setter — keeping `post` a plain command keeps the\n // command-token wiring (`command.post:`) readable.\n inputs: [\n { name: \"name\", attribute: \"name\" },\n { name: \"manual\", attribute: \"manual\" },\n ],\n // Commands are identical to the Core's — no rename needed since the `name` /\n // `manual` attribute accessors do not collide with open/post/close.\n commands: BroadcastCore.wcBindable.commands,\n };\n static get observedAttributes(): string[] { return [\"name\"]; }\n\n private _core: BroadcastCore;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new BroadcastCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n \"wcs-broadcast:error\": (d) => ({ error: d != null }),\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 (async-io-node-guidelines.md §3.6): attachInternals is absent\n // 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 name(): string {\n return this.getAttribute(\"name\") || \"\";\n }\n\n set name(value: string) {\n this.setAttribute(\"name\", value);\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n // --- Core delegated getters ---\n\n get message(): any {\n return this._core.message;\n }\n\n get error(): WcsBroadcastErrorDetail | null {\n return this._core.error;\n }\n\n // --- Commands ---\n\n open(): void {\n if (this.name) {\n this._core.open(this.name);\n }\n }\n\n post(data: any): void {\n this._core.post(data);\n }\n\n close(): void {\n this._core.close();\n }\n\n // --- Lifecycle ---\n\n attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void {\n if (name === \"name\" && this.isConnected && !this.manual && newValue) {\n this._core.open(newValue);\n }\n }\n\n connectedCallback(): void {\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n if (!this.manual && this.name) {\n this._core.open(this.name);\n }\n // SSR (§4.4): expose the Core's readiness as connectedCallbackPromise. The\n // channel opens synchronously above, so observe() resolves immediately.\n this._connectedCallbackPromise = this._core.observe();\n }\n\n disconnectedCallback(): void {\n // Deliberately does NOT call unregisterAutoTrigger(). The autoTrigger click\n // listener is a single process-wide document listener (registerAutoTrigger\n // is idempotent), shared by every <wcs-broadcast> on the page — not owned by\n // this element. Tearing it down when the last element disconnects would\n // break a later-inserted trigger, so it is intentionally left installed for\n // the document's lifetime (one passive listener, negligible cost). This\n // mirrors <wcs-clipboard>, which registers but never unregisters either.\n // unregisterAutoTrigger stays exported purely as a symmetric teardown hook\n // for tests / advanced manual control; the production lifecycle never calls\n // it.\n this._core.dispose();\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapBroadcast(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n","import { WcsBroadcast } from \"./components/Broadcast.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.broadcast)) {\n customElements.define(config.tagNames.broadcast, WcsBroadcast);\n }\n}\n"],"names":["_config","autoTrigger","triggerAttribute","tagNames","broadcast","deepFreeze","obj","Object","freeze","key","keys","deepClone","clone","frozenConfig","config","getConfig","BroadcastCore","EventTarget","static","protocol","version","properties","name","event","commands","_target","_channel","_name","_message","_error","_gen","_ready","Promise","resolve","constructor","target","super","this","ready","message","error","observe","_setMessage","dispatchEvent","CustomEvent","detail","bubbles","_setError","open","_hasBroadcastChannel","_unsupportedError","_closeChannel","gen","channel","BroadcastChannel","_onMessage","data","_onMessageError","addEventListener","post","postMessage","err","_normalizeError","close","dispose","removeEventListener","Error","String","registered","TEXT_ATTRIBUTE","handleClick","Element","triggerElement","closest","broadcastId","getAttribute","BroadcastCtor","customElements","get","broadcastElement","document","getElementById","text","hasAttribute","selector","source","querySelector","HTMLInputElement","HTMLTextAreaElement","HTMLSelectElement","value","textContent","resolveText","preventDefault","WcsBroadcast","HTMLElement","wcBindable","inputs","attribute","observedAttributes","_core","_connectedCallbackPromise","_internals","_initInternals","_wireStates","d","debugStates","states","attachInternals","internals","add","delete","map","toStates","entries","e","debug","on","toggleAttribute","connectedCallbackPromise","setAttribute","manual","removeAttribute","attributeChangedCallback","_oldValue","newValue","isConnected","connectedCallback","style","display","disconnectedCallback","bootstrapBroadcast","userConfig","partialConfig","assign","define"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.esm.min.js","sources":["../src/config.ts","../src/core/broadcastCapabilities.ts","../src/core/BroadcastCore.ts","../src/autoTrigger.ts","../src/components/Broadcast.ts","../src/bootstrapBroadcast.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n broadcast: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-broadcast-target\",\n tagNames: {\n broadcast: \"wcs-broadcast\",\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\n// Live reference to the mutable internal config: reads always reflect the latest\n// setConfig() call. The readonly IConfig type only blocks callers from writing\n// through it — the underlying object still changes. If you need a stable,\n// frozen snapshot that won't move under you, use getConfig() instead.\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 (typeof partialConfig.autoTrigger === \"boolean\") {\n _config.autoTrigger = partialConfig.autoTrigger;\n }\n if (typeof partialConfig.triggerAttribute === \"string\") {\n _config.triggerAttribute = partialConfig.triggerAttribute;\n }\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","/**\n * broadcastCapabilities.ts\n *\n * Broadcast node 固有の error code(taxonomy)と derivation。汎用の error info 型は\n * `./platformCapability.js`(/io-core/ から copy-distribution される生成ファイル)から\n * import する。BroadcastChannel の post / message は concurrent-independent(競合しない)\n * ため lane は持たず、error taxonomy(errorInfo)のみを採用する。\n */\n\nimport type { WcsIoErrorInfo } from \"./platformCapability.js\";\nimport type { WcsBroadcastErrorDetail } from \"../types.js\";\n\n/** 安定した broadcast error code(taxonomy)。値は公開キーとして固定。 */\nexport const WCS_BROADCAST_ERROR_CODE = {\n /** BroadcastChannel コンストラクタ不在(`_unsupportedError()` の `NotSupportedError`)。 */\n CapabilityMissing: \"capability-missing\",\n /** structured clone 不可な payload を post(`DataCloneError`)。呼び出し側入力の不備。 */\n InvalidArgument: \"invalid-argument\",\n /** その他の post / channel 失敗(DataError / InvalidStateError / \"Error\" fallback など)。 */\n BroadcastError: \"broadcast-error\",\n} as const;\n\n/**\n * 正規化済み error(`{ name, message }`)を serializable な error taxonomy に写す。\n * `name` は `DOMException.name`(`_normalizeError`)/ 合成名(`_unsupportedError` の\n * `NotSupportedError`、`messageerror` の `DataError`、post 前の `InvalidStateError`)。\n *\n * - `NotSupportedError`(BroadcastChannel 不在)は利用直前の能力欠如 → phase=\"probe\" /\n * capability-missing。\n * - `DataCloneError`(structured clone 不可な payload を post)は呼び出し側入力の不備 →\n * phase=\"execute\" / invalid-argument。\n * - それ以外(`DataError` の deserialize 失敗 / `InvalidStateError` / \"Error\" fallback)は\n * phase=\"execute\" / broadcast-error。\n * いずれも同一入力の再送では回復しない(recoverable=false)。\n */\nexport function deriveBroadcastErrorInfo(error: WcsBroadcastErrorDetail): WcsIoErrorInfo {\n if (error.name === \"NotSupportedError\") {\n return { code: WCS_BROADCAST_ERROR_CODE.CapabilityMissing, phase: \"probe\", recoverable: false, message: error.message };\n }\n if (error.name === \"DataCloneError\") {\n return { code: WCS_BROADCAST_ERROR_CODE.InvalidArgument, phase: \"execute\", recoverable: false, message: error.message };\n }\n return { code: WCS_BROADCAST_ERROR_CODE.BroadcastError, phase: \"execute\", recoverable: false, message: error.message };\n}\n","import { IWcBindable, WcsBroadcastErrorDetail } from \"../types.js\";\nimport { WcsIoErrorInfo } from \"./platformCapability.js\";\nimport { deriveBroadcastErrorInfo } from \"./broadcastCapabilities.js\";\n\n/**\n * Headless cross-tab messaging primitive. A thin, framework-agnostic wrapper\n * around the BroadcastChannel API exposed through the wc-bindable protocol.\n *\n * BroadcastChannel is a same-origin pub/sub bus: every context (tab, iframe,\n * worker) that opens a channel with the same `name` receives every other\n * context's posts — but NOT its own. This self-exclusion is the whole point:\n * `post` is a `state → element` action (command-token) and an incoming\n * `message` is an `element → state` notification (event-token), but the two\n * only close the loop *across* a context boundary. Within a single tab a lone\n * `<wcs-broadcast>` never hears itself; open the page in two tabs to see the\n * round-trip.\n *\n * Unlike WebSocketCore there is no connection state, no reconnect, and no wire\n * encoding: a channel is \"open\" the moment it is constructed, and payloads ride\n * the browser's structured clone (objects pass through as-is, no JSON\n * round-trip). The only failure surfaces are a non-cloneable `post`\n * (`DataCloneError`), a `messageerror` (a peer posted something this context\n * cannot deserialize), and an absent `BroadcastChannel` constructor\n * (`unsupported`). All three flow through the `error` property — the Core never\n * throws — symmetrical with FetchCore / ClipboardCore.\n */\nexport class BroadcastCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"message\", event: \"wcs-broadcast:message\" },\n { name: \"error\", event: \"wcs-broadcast:error\" },\n // Serializable failure taxonomy (stable code / phase / recoverable), or null.\n // Additive bindable output derived from `error` (the DOMException.name /\n // synthetic name); the existing `error` property/event are unchanged. Fires\n // wcs-broadcast:error-info-changed. No lane — post/message are concurrent-\n // independent (mirrors ClipboardCore).\n { name: \"errorInfo\", event: \"wcs-broadcast:error-info-changed\" },\n ],\n commands: [\n { name: \"open\" },\n { name: \"post\" },\n { name: \"close\" },\n ],\n };\n\n private _target: EventTarget;\n private _channel: BroadcastChannel | null = null;\n private _name: string | null = null;\n private _message: any = null;\n private _error: WcsBroadcastErrorDetail | null = null;\n private _errorInfo: WcsIoErrorInfo | null = null;\n // Generation guard (§3.4): bumped on dispose(). An incoming message /\n // messageerror that fires after the Shell disconnected (a peer posted between\n // disconnect and the channel actually closing, or a queued event drains late)\n // has a stale `gen` and MUST NOT write state to a torn-down element. A boolean\n // flag is insufficient: dispose→reconnect would let a stale event slip through.\n private _gen = 0;\n // SSR (§3.8): a channel opens synchronously (no asynchronous probe to await),\n // 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 message(): any {\n return this._message;\n }\n\n get error(): WcsBroadcastErrorDetail | null {\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-broadcast:error-info-changed`), derived from `error`; the existing\n * `error` property/event are unchanged.\n */\n get errorInfo(): WcsIoErrorInfo | null {\n return this._errorInfo;\n }\n\n // --- Lifecycle (§3.5) ---\n\n // observe() establishes monitoring. BroadcastChannel is command-driven (the\n // Shell calls open(name) from connectedCallback / attributeChangedCallback),\n // so there is no subscription for observe() to set up here: it is an idempotent\n // no-op that resolves once ready. It exists for skeleton symmetry with the\n // monitor-style nodes so a host can uniformly await observe() == ready.\n observe(): Promise<void> {\n return this._ready;\n }\n\n // --- State setters with event dispatch ---\n\n // Deliberately NO same-value guard (unlike `error` below). A received message\n // is an event, not idempotent state: a peer posting the same value twice is\n // two distinct occurrences and must re-fire wcs-broadcast:message each time so\n // a `message:` binding and any `eventToken.message:` subscriber see both.\n private _setMessage(message: any): void {\n this._message = message;\n this._target.dispatchEvent(new CustomEvent(\"wcs-broadcast:message\", {\n detail: message,\n bubbles: true,\n }));\n }\n\n private _setError(error: WcsBroadcastErrorDetail | null): void {\n // Same-value guard. `error` has no derived state, so suppressing redundant\n // null→null dispatches (e.g. a successful open clearing an already-null\n // error) avoids spurious events. Reference identity is sufficient: each\n // failure builds a fresh object, and the clear path always passes null.\n if (this._error === error) return;\n this._error = error;\n // Keep the additive `errorInfo` taxonomy in sync with `error`: derive from the\n // error name (or null on clear). Fires before the `error` event so an observer\n // binding both sees the classification first, mirroring the io-node family.\n this._commitErrorInfo(error === null ? null : deriveBroadcastErrorInfo(error));\n this._target.dispatchEvent(new CustomEvent(\"wcs-broadcast:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n // Called only from _setError (which already same-value-guards on reference\n // identity), so errorInfo transitions exactly when error does — no separate\n // guard needed here.\n private _commitErrorInfo(info: WcsIoErrorInfo | null): void {\n this._errorInfo = info;\n this._target.dispatchEvent(new CustomEvent(\"wcs-broadcast:error-info-changed\", {\n detail: info,\n bubbles: true,\n }));\n }\n\n // --- Public API ---\n\n /**\n * Join the named channel. Any previously-open channel is closed first, so\n * calling `open()` again switches channels. When the BroadcastChannel\n * constructor is unavailable this surfaces an `unsupported` error and leaves\n * the Core channel-less (a later `post()` then errors loudly rather than\n * silently dropping).\n */\n open(name: string): void {\n if (!this._hasBroadcastChannel()) {\n this._setError(this._unsupportedError());\n return;\n }\n // Idempotent on the same channel: re-opening the channel we are already on\n // is pure churn (BroadcastChannel has no reconnect semantics). This also\n // absorbs the custom-element *upgrade* path — when a connected element with\n // a `name` attribute is upgraded (autoloader defines the tag after the\n // markup exists), the spec fires attributeChangedCallback (isConnected ===\n // true) *and* connectedCallback, so the Shell calls open() twice. Without\n // this guard that would create a channel and immediately tear it down.\n if (this._channel && this._name === name) return;\n this._closeChannel();\n this._setError(null);\n // Capture the generation for this channel (§3.4). The listeners below close\n // over `gen`; an event that fires after dispose() (which bumps _gen) is\n // recognised as stale and dropped without writing state to a torn-down\n // element. The handlers are stored so _closeChannel() can remove them by the\n // same reference.\n const gen = ++this._gen;\n const channel = new BroadcastChannel(name);\n this._onMessage = (event: MessageEvent): void => {\n if (gen !== this._gen) return;\n this._setMessage(event.data);\n };\n // Fired when a peer posted a value this context cannot deserialize. The event\n // carries no usable payload, so report a synthetic DataError.\n this._onMessageError = (): void => {\n if (gen !== this._gen) return;\n this._setError({\n name: \"DataError\",\n message: \"Failed to deserialize a message received on the channel.\",\n });\n };\n channel.addEventListener(\"message\", this._onMessage);\n channel.addEventListener(\"messageerror\", this._onMessageError);\n this._channel = channel;\n this._name = name;\n }\n\n /**\n * Post a structured-cloneable value to every other context on the channel.\n * The local context never receives it (self-exclusion). Never throws:\n * a non-cloneable value surfaces as a `DataCloneError` through `error`, and\n * posting with no open channel surfaces an `InvalidStateError`.\n */\n post(data: any): void {\n if (!this._hasBroadcastChannel()) {\n this._setError(this._unsupportedError());\n return;\n }\n if (!this._channel) {\n this._setError({\n name: \"InvalidStateError\",\n message: \"Channel is not open. Call open(name) before post().\",\n });\n return;\n }\n try {\n this._channel.postMessage(data);\n } catch (err) {\n this._setError(this._normalizeError(err));\n }\n }\n\n /** Leave the channel. Idempotent — a no-op when no channel is open. */\n close(): void {\n this._closeChannel();\n }\n\n /**\n * Tear the Core down for a disconnected Shell: close the channel and reset the\n * error shadow silently (no dispatch on a torn-down element). A later\n * reconnect re-opens via the Shell's connectedCallback.\n *\n * Asymmetry by design: `_message` is deliberately NOT reset. `error` is\n * transient connection state — a stale error from a previous channel would be\n * misleading after a reconnect, so it is cleared. `message` is the last value\n * received (an event payload), not connection state; it is retained as the\n * Core's last-known datum so a binding still reads it across a disconnect/\n * reconnect, and it is naturally overwritten by the next incoming message.\n */\n dispose(): void {\n // Bump the generation first (§3.4) so any message/messageerror that drains\n // after teardown is recognised as stale, then close the channel and reset the\n // error shadow silently.\n this._gen++;\n this._closeChannel();\n this._error = null;\n // dispose bypasses _setError (silent, no dispatch on a torn-down element), so\n // clear the errorInfo mirror directly too — otherwise a stale taxonomy would\n // survive after `error` has been reset to null.\n this._errorInfo = null;\n }\n\n // --- Internal ---\n\n // Per-channel listeners, (re)created in open() so each closes over its own\n // generation (§3.4). null while no channel is open; the real handlers are\n // installed by open() and removed by the same reference in _closeChannel().\n private _onMessage: ((event: MessageEvent) => void) | null = null;\n private _onMessageError: (() => void) | null = null;\n\n private _closeChannel(): void {\n if (!this._channel) return;\n this._channel.removeEventListener(\"message\", this._onMessage!);\n this._channel.removeEventListener(\"messageerror\", this._onMessageError!);\n this._channel.close();\n this._channel = null;\n this._name = null;\n this._onMessage = null;\n this._onMessageError = null;\n }\n\n private _hasBroadcastChannel(): boolean {\n return typeof BroadcastChannel !== \"undefined\";\n }\n\n private _normalizeError(err: unknown): WcsBroadcastErrorDetail {\n if (err instanceof Error) {\n // DOMException is an Error subclass; its `name` (DataCloneError, etc.) is\n // the meaningful discriminator for consumers switching on failure kind.\n return { name: err.name, message: err.message };\n }\n return { name: \"Error\", message: String(err) };\n }\n\n private _unsupportedError(): WcsBroadcastErrorDetail {\n return {\n name: \"NotSupportedError\",\n message: \"BroadcastChannel is not available in this environment.\",\n };\n }\n}\n","import { config } from \"./config.js\";\nimport type { WcsBroadcast } from \"./components/Broadcast.js\";\n\nlet registered = false;\n\n// Attribute names for the optional post-on-click DOM trigger (clipboard.js-style\n// DX). The element carrying `data-broadcast-target` points at a <wcs-broadcast>\n// by id; the text to post comes from either a literal `data-broadcast-text` or\n// a `data-broadcast-from` CSS selector resolving to a source element.\nconst TEXT_ATTRIBUTE = \"data-broadcast-text\";\nconst FROM_ATTRIBUTE = \"data-broadcast-from\";\n\nfunction resolveText(triggerElement: Element): string | null {\n // Literal text wins when present (including an empty string — posting \"\" is a\n // legitimate request). The `?? \"\"` right-hand side is defensive and\n // unreachable: hasAttribute() just returned true, so getAttribute() cannot be\n // null here. It exists only to satisfy the `string | null` return type — do\n // not chase coverage on it (the DOM contract makes the null branch impossible).\n if (triggerElement.hasAttribute(TEXT_ATTRIBUTE)) {\n return triggerElement.getAttribute(TEXT_ATTRIBUTE) ?? \"\";\n }\n const selector = triggerElement.getAttribute(FROM_ATTRIBUTE);\n if (!selector) return null;\n // A user-authored selector can be syntactically invalid (e.g. `[data-*` or a\n // bare `:not()`), which makes querySelector throw a SyntaxError. Swallow it\n // and treat the source as unresolvable — the same \"nothing to post\" path as a\n // selector that matches no element — so one bad attribute never crashes the\n // document-level click handler and kills autoTrigger for the whole tab.\n let source: Element | null;\n try {\n source = document.querySelector(selector);\n } catch {\n return null;\n }\n if (!source) return null;\n // Read a form control's `value`; fall back to text content. A bare\n // `\"value\" in source` check is too broad — it also matches <button>,\n // <li value>, <progress>, etc. (which carry an unrelated `value`), posting the\n // wrong thing. Narrow to the text-bearing controls a user actually points\n // `data-broadcast-from` at; everything else falls through to textContent.\n if (\n source instanceof HTMLInputElement ||\n source instanceof HTMLTextAreaElement ||\n source instanceof HTMLSelectElement\n ) {\n return source.value;\n }\n // `?? \"\"` is defensive: per the DOM spec only Document / DocumentType /\n // Notation nodes have a null `textContent`, and querySelector only ever\n // returns an Element (whose textContent is always a string). The branch is\n // therefore unreachable in practice and kept solely for the `string | null`\n // type — not worth a contrived test.\n return source.textContent ?? \"\";\n}\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const broadcastId = triggerElement.getAttribute(config.triggerAttribute);\n if (!broadcastId) return;\n\n // Resolve the registered constructor at call time instead of importing\n // WcsBroadcast as a value (avoids a components ⇄ autoTrigger import cycle:\n // Broadcast.connectedCallback() calls registerAutoTrigger()). instanceof\n // against the customElements registry keeps the same identity guarantee.\n const BroadcastCtor = customElements.get(config.tagNames.broadcast);\n const broadcastElement = document.getElementById(broadcastId);\n if (!BroadcastCtor || !(broadcastElement instanceof BroadcastCtor)) return;\n\n const text = resolveText(triggerElement);\n // No resolvable source: leave the click alone (do not preventDefault) so the\n // element's default action is unaffected.\n if (text === null) return;\n\n // Suppress the default action so a post can run without navigating. Intentional:\n // do not attach data-broadcast-target to an element whose default action you\n // also want (a real <a href> link). See README \"Optional DOM Triggering\".\n event.preventDefault();\n (broadcastElement as WcsBroadcast).post(text);\n}\n\nexport function registerAutoTrigger(): void {\n if (registered) return;\n registered = true;\n document.addEventListener(\"click\", handleClick);\n}\n\nexport function unregisterAutoTrigger(): void {\n if (!registered) return;\n registered = false;\n document.removeEventListener(\"click\", handleClick);\n}\n","import { config } from \"../config.js\";\nimport { IWcBindable, WcsBroadcastErrorDetail } from \"../types.js\";\nimport { BroadcastCore } from \"../core/BroadcastCore.js\";\nimport { WcsIoErrorInfo } from \"../core/platformCapability.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\n\n// Named WcsBroadcast (not `Broadcast`) to match the <wcs-clipboard> WcsClipboard\n// / <wcs-ws> WcsWebSocket convention and avoid shadowing any global.\nexport class WcsBroadcast extends HTMLElement {\n // SSR (§4.4): the channel opens synchronously in connectedCallback, so the\n // Core's observe() resolves immediately; we still expose connectedCallbackPromise\n // so a state binder can uniformly await readiness before snapshotting.\n static hasConnectedCallbackPromise = true;\n static wcBindable: IWcBindable = {\n ...BroadcastCore.wcBindable,\n // Shell-level settable surface. `name` selects the channel; `manual`\n // suppresses auto-open on connect. There is no momentary `post` property:\n // posting needs an argument (the payload), so element actions run via\n // command-token (`command.post: $command.ping`) or the DOM autoTrigger, not\n // a value-derived setter — keeping `post` a plain command keeps the\n // command-token wiring (`command.post:`) readable.\n inputs: [\n { name: \"name\", attribute: \"name\" },\n { name: \"manual\", attribute: \"manual\" },\n ],\n // Commands are identical to the Core's — no rename needed since the `name` /\n // `manual` attribute accessors do not collide with open/post/close.\n commands: BroadcastCore.wcBindable.commands,\n };\n static get observedAttributes(): string[] { return [\"name\"]; }\n\n private _core: BroadcastCore;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new BroadcastCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n \"wcs-broadcast:error\": (d) => ({ error: d != null }),\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 (async-io-node-guidelines.md §3.6): attachInternals is absent\n // 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 name(): string {\n return this.getAttribute(\"name\") || \"\";\n }\n\n set name(value: string) {\n this.setAttribute(\"name\", value);\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n // --- Core delegated getters ---\n\n get message(): any {\n return this._core.message;\n }\n\n get error(): WcsBroadcastErrorDetail | null {\n return this._core.error;\n }\n\n get errorInfo(): WcsIoErrorInfo | null {\n return this._core.errorInfo;\n }\n\n // --- Commands ---\n\n open(): void {\n if (this.name) {\n this._core.open(this.name);\n }\n }\n\n post(data: any): void {\n this._core.post(data);\n }\n\n close(): void {\n this._core.close();\n }\n\n // --- Lifecycle ---\n\n attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void {\n if (name === \"name\" && this.isConnected && !this.manual && newValue) {\n this._core.open(newValue);\n }\n }\n\n connectedCallback(): void {\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n if (!this.manual && this.name) {\n this._core.open(this.name);\n }\n // SSR (§4.4): expose the Core's readiness as connectedCallbackPromise. The\n // channel opens synchronously above, so observe() resolves immediately.\n this._connectedCallbackPromise = this._core.observe();\n }\n\n disconnectedCallback(): void {\n // Deliberately does NOT call unregisterAutoTrigger(). The autoTrigger click\n // listener is a single process-wide document listener (registerAutoTrigger\n // is idempotent), shared by every <wcs-broadcast> on the page — not owned by\n // this element. Tearing it down when the last element disconnects would\n // break a later-inserted trigger, so it is intentionally left installed for\n // the document's lifetime (one passive listener, negligible cost). This\n // mirrors <wcs-clipboard>, which registers but never unregisters either.\n // unregisterAutoTrigger stays exported purely as a symmetric teardown hook\n // for tests / advanced manual control; the production lifecycle never calls\n // it.\n this._core.dispose();\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapBroadcast(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n","import { WcsBroadcast } from \"./components/Broadcast.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.broadcast)) {\n customElements.define(config.tagNames.broadcast, WcsBroadcast);\n }\n}\n"],"names":["_config","autoTrigger","triggerAttribute","tagNames","broadcast","deepFreeze","obj","Object","freeze","key","keys","deepClone","clone","frozenConfig","config","getConfig","WCS_BROADCAST_ERROR_CODE","CapabilityMissing","InvalidArgument","BroadcastError","BroadcastCore","EventTarget","static","protocol","version","properties","name","event","commands","_target","_channel","_name","_message","_error","_errorInfo","_gen","_ready","Promise","resolve","constructor","target","super","this","ready","message","error","errorInfo","observe","_setMessage","dispatchEvent","CustomEvent","detail","bubbles","_setError","_commitErrorInfo","code","phase","recoverable","deriveBroadcastErrorInfo","info","open","_hasBroadcastChannel","_unsupportedError","_closeChannel","gen","channel","BroadcastChannel","_onMessage","data","_onMessageError","addEventListener","post","postMessage","err","_normalizeError","close","dispose","removeEventListener","Error","String","registered","TEXT_ATTRIBUTE","handleClick","Element","triggerElement","closest","broadcastId","getAttribute","BroadcastCtor","customElements","get","broadcastElement","document","getElementById","text","hasAttribute","selector","source","querySelector","HTMLInputElement","HTMLTextAreaElement","HTMLSelectElement","value","textContent","resolveText","preventDefault","WcsBroadcast","HTMLElement","wcBindable","inputs","attribute","observedAttributes","_core","_connectedCallbackPromise","_internals","_initInternals","_wireStates","d","debugStates","states","attachInternals","internals","add","delete","map","toStates","entries","e","debug","on","toggleAttribute","connectedCallbackPromise","setAttribute","manual","removeAttribute","attributeChangedCallback","_oldValue","newValue","isConnected","connectedCallback","style","display","disconnectedCallback","bootstrapBroadcast","userConfig","partialConfig","assign","define"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wcstack/broadcast",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.21.0",
|
|
4
4
|
"description": "Declarative cross-tab messaging component for Web Components. Framework-agnostic BroadcastChannel primitive via wc-bindable-protocol.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.esm.js",
|