@wcstack/pointer-lock 1.16.0 → 1.17.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 CHANGED
@@ -100,6 +100,55 @@ npm install @wcstack/pointer-lock
100
100
  | --------- | ------------ |
101
101
  | `target` | ロック対象の要素を指すセレクタ(または`"self"`)。上記「`target`属性がロック対象を決める」を参照。省略時は先頭の子要素。 |
102
102
 
103
+ ## `:state()` による CSS スタイリング
104
+
105
+ `<wcs-pointer-lock>` は `active` 出力を
106
+ [`ElementInternals` の `CustomStateSet`](https://developer.mozilla.org/ja/docs/Web/API/CustomStateSet)
107
+ に反映します。そのため `data-wcs` バインディングやクラスの手動トグルなしに、CSS の
108
+ `:state()` 疑似クラスで直接スタイリングできます。
109
+
110
+ | ステート | on になる条件 |
111
+ |----------|----------------|
112
+ | `active` | `wcs-pointer-lock:change` が `true` で発火(`false` でクリア) |
113
+
114
+ ```css
115
+ wcs-pointer-lock:state(active) ~ .crosshair { display: block; }
116
+ wcs-pointer-lock:state(active) ~ .crosshair { display: none; } /* デフォルト */
117
+ ```
118
+
119
+ 属性やクラスと異なり `:state()` は要素の外部から書き込めないため、この出力ステートが
120
+ 入力と混同される心配がありません。`error` はあえて反映していません — 上記「観測可能プロパティ」参照。
121
+ 単純な getter として公開されるのみで、`wcBindable` の property ではありません。
122
+
123
+ **対応ブラウザ**(新構文 `:state(x)`): Chrome/Edge 125+、Safari 17.4+、Firefox 126+。
124
+ 非対応の環境ではステートが一切 set されないだけです — `:state()` セレクタがマッチしなく
125
+ なりますが、`<wcs-pointer-lock>` 自体は通常どおり動作し続けます(graceful degradation・never-throw)。
126
+
127
+ **SSR:** `:state()` は HTML にシリアライズできないため、サーバーレンダリングされた
128
+ マークアップの初期ペイントにはこれらのステートは乗りません(`@wcstack/server` は無改変)。
129
+ ハイドレーション前の見た目を制御したい場合は、代わりに `wcs-pointer-lock:not(:defined)` と組み合わせてください。
130
+
131
+ ### デバッグ
132
+
133
+ カスタムステートは DevTools の Elements パネルには表示されず、`attachInternals()`
134
+ は同一要素に 2 回呼べないため、コンソールから直接覗く手段がありません。そのための
135
+ デバッグ専用の補助を 2 つ用意しています:
136
+
137
+ - `el.debugStates` — 現在 on になっているステート名の**スナップショット**配列
138
+ (例: `["active"]`)。`wc-bindable` の一部ではなく(バインド対象ではない)、
139
+ 形状も契約として保証されません — デバッグ用途にのみ使ってください。
140
+ - `debug-states` 属性(opt-in・既定 OFF)は、ステート変化を要素の
141
+ `data-wcs-state-active` 属性にミラーします。
142
+ Elements パネルを開いておけば、トグルのたびにハイライトされます:
143
+
144
+ ```html
145
+ <wcs-pointer-lock target="#scene" debug-states></wcs-pointer-lock>
146
+ ```
147
+
148
+ **CSS は `data-wcs-state-*` ではなく `:state()` に書いてください。** ミラーされた
149
+ 属性は、DevTools を開いた状態でステート変化を可視化するためだけのものであり、
150
+ スタイリング用の正式なフックではありません。
151
+
103
152
  ## 複数インスタンス — 「documentがロック中か」ではなくインスタンスごとに`active`を見る
104
153
 
105
154
  `document.pointerLockElement` はdocument全体で単一の値しか持ちません(同時にロックできる要素は高々1つ)。複数の`<wcs-pointer-lock>`インスタンス(例: `target="#a"`と`target="#b"`)が同時に存在する場合、各インスタンスは`document.pointerLockElement`を**自分自身の**解決済みtargetと比較します(単に「documentがロック中か」ではありません)。`#a`をロックすると、`target="#a"`のインスタンスは`active: true`、`target="#b"`のインスタンスは`active: false`を報告します — document全体では何か(`#a`)がロックされているにもかかわらずです。
package/README.md CHANGED
@@ -100,6 +100,58 @@ Every bound state path must be declared up front — `locked: false` here; bindi
100
100
  | --------- | ------------ |
101
101
  | `target` | Selector (or `"self"`) identifying the element to lock. See "The `target` attribute decides what is locked" above. Omitted → first element child. |
102
102
 
103
+ ## CSS styling with `:state()`
104
+
105
+ `<wcs-pointer-lock>` reflects its `active` output onto its
106
+ [`ElementInternals` `CustomStateSet`](https://developer.mozilla.org/en-US/docs/Web/API/CustomStateSet),
107
+ so you can style it directly from CSS with the `:state()` pseudo-class — no
108
+ `data-wcs` binding or extra class toggling required.
109
+
110
+ | State | On when |
111
+ |-------|---------|
112
+ | `active` | `wcs-pointer-lock:change` fires with `true` (cleared on `false`) |
113
+
114
+ ```css
115
+ wcs-pointer-lock:state(active) ~ .crosshair { display: block; }
116
+ wcs-pointer-lock:state(active) ~ .crosshair { display: none; } /* default */
117
+ ```
118
+
119
+ Unlike attributes or classes, `:state()` cannot be written from outside the
120
+ element, so there is no risk of confusing this output state with an input.
121
+ `error` is intentionally not reflected — see "Observable Properties" above;
122
+ it is exposed only as a plain getter, not a `wcBindable` property.
123
+
124
+ **Browser support** (`:state(x)` syntax): Chrome/Edge 125+, Safari 17.4+,
125
+ Firefox 126+. In older browsers the states are simply never set — `:state()`
126
+ selectors never match, but `<wcs-pointer-lock>` itself keeps working normally
127
+ (graceful degradation, never-throw).
128
+
129
+ **SSR**: `:state()` cannot be serialized into HTML, so server-rendered markup
130
+ never carries these states on first paint (`@wcstack/server` is unaffected).
131
+ If you need to style the pre-hydration gap, pair your rule with
132
+ `wcs-pointer-lock:not(:defined)` instead.
133
+
134
+ ### Debugging
135
+
136
+ Custom states are invisible in DevTools' Elements panel and `attachInternals()`
137
+ cannot be called twice, so there is no console way to inspect them directly.
138
+ Two debug-only aids are provided for that:
139
+
140
+ - `el.debugStates` — a **snapshot** array of the currently-on state names
141
+ (e.g. `["active"]`). It is not part of `wc-bindable` (not a bind target)
142
+ and its shape is not a guaranteed contract — use it for debugging only.
143
+ - The `debug-states` attribute (opt-in, default off) mirrors state changes
144
+ onto a `data-wcs-state-active` attribute on the element, so the Elements
145
+ panel highlights it as it toggles:
146
+
147
+ ```html
148
+ <wcs-pointer-lock target="#scene" debug-states></wcs-pointer-lock>
149
+ ```
150
+
151
+ **Write your CSS against `:state()`, not `data-wcs-state-*`.** The mirrored
152
+ attribute exists purely to make state changes visible while debugging with
153
+ DevTools open; it is not a supported styling hook.
154
+
103
155
  ## Multiple instances — read `active` per-instance, not "is *anything* locked"
104
156
 
105
157
  `document.pointerLockElement` is a single document-wide value — at most one element can be locked at a time. When several `<wcs-pointer-lock>` instances exist simultaneously (e.g. `target="#a"` and `target="#b"`), each instance compares `document.pointerLockElement` against **its own** resolved target, not merely "is the document locked". Locking `#a` makes the `target="#a"` instance report `active: true` and the `target="#b"` instance report `active: false` — even though *some* element (`#a`) is locked document-wide.
package/dist/index.d.ts CHANGED
@@ -172,8 +172,12 @@ declare class WcsPointerLock extends HTMLElement {
172
172
  static wcBindable: IWcBindable;
173
173
  private _core;
174
174
  private _connectedCallbackPromise;
175
+ private _internals;
175
176
  constructor();
176
177
  get connectedCallbackPromise(): Promise<void>;
178
+ get debugStates(): string[];
179
+ private _initInternals;
180
+ private _wireStates;
177
181
  get target(): string;
178
182
  set target(value: string);
179
183
  get active(): boolean;
package/dist/index.esm.js CHANGED
@@ -314,13 +314,66 @@ class WcsPointerLock extends HTMLElement {
314
314
  };
315
315
  _core;
316
316
  _connectedCallbackPromise = Promise.resolve();
317
+ _internals = null;
317
318
  constructor() {
318
319
  super();
319
320
  this._core = new PointerLockCore(this);
321
+ this._internals = this._initInternals();
322
+ this._wireStates({
323
+ "wcs-pointer-lock:change": (d) => ({ active: d === true }),
324
+ });
320
325
  }
321
326
  get connectedCallbackPromise() {
322
327
  return this._connectedCallbackPromise;
323
328
  }
329
+ // CSS state reflection (:state()) — debug-only snapshot getter. NOT part of
330
+ // wc-bindable (not a bind target); see README "CSS styling with :state()".
331
+ // MUST NOT return the live CustomStateSet (that would let callers write
332
+ // states from outside, defeating the point of :state() being read-only).
333
+ get debugStates() {
334
+ return this._internals ? [...this._internals.states] : [];
335
+ }
336
+ _initInternals() {
337
+ // never-throw (docs/custom-state-reflection-design.md §3.6): attachInternals
338
+ // is absent in happy-dom / older environments, and pre-125 Chromium rejects
339
+ // non-dashed state names from states.add() (probed and discarded here).
340
+ // Either case silently disables reflection — the component still works,
341
+ // it just doesn't expose :state() selectors.
342
+ try {
343
+ if (typeof this.attachInternals !== "function")
344
+ return null;
345
+ const internals = this.attachInternals();
346
+ internals.states.add("wcs-probe");
347
+ internals.states.delete("wcs-probe");
348
+ return internals;
349
+ }
350
+ catch {
351
+ return null;
352
+ }
353
+ }
354
+ _wireStates(map) {
355
+ if (this._internals === null)
356
+ return;
357
+ const states = this._internals.states;
358
+ for (const [event, toStates] of Object.entries(map)) {
359
+ this.addEventListener(event, (e) => {
360
+ const debug = this.hasAttribute("debug-states");
361
+ for (const [name, on] of Object.entries(toStates(e.detail))) {
362
+ try {
363
+ if (on) {
364
+ states.add(name);
365
+ }
366
+ else {
367
+ states.delete(name);
368
+ }
369
+ }
370
+ catch { /* never-throw */ }
371
+ if (debug)
372
+ this.toggleAttribute(`data-wcs-state-${name}`, on);
373
+ }
374
+ });
375
+ }
376
+ }
324
377
  // --- Attribute accessors ---
325
378
  get target() {
326
379
  return this.getAttribute("target") ?? "";
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/config.ts","../src/core/PointerLockCore.ts","../src/components/PointerLock.ts","../src/registerComponents.ts","../src/bootstrapPointerLock.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n tagNames: {\n pointerLock: string;\n };\n}\n\nconst _config: IInternalConfig = {\n tagNames: {\n pointerLock: \"wcs-pointer-lock\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { IWcBindable } from \"../types.js\";\n\n/**\n * Headless Pointer Lock primitive. A thin, framework-agnostic wrapper around\n * the Pointer Lock API (`Element.requestPointerLock()` /\n * `document.exitPointerLock()` / `document.pointerLockElement` / the\n * `document`-scoped `pointerlockchange` event) exposed through the\n * wc-bindable protocol.\n *\n * This Core follows the same basic pattern as `FullscreenCore`\n * (docs/fullscreen-tag-design.md, referenced by docs/pointer-lock-tag-design.md\n * §1): target resolution happens in the Shell, `pointerlockchange` is\n * subscribed on `document` (not on the target element) and each instance\n * self-filters by comparing `document.pointerLockElement` against its own\n * resolved target, API resolution is call-time (never cached) and probes the\n * standard name before the legacy (`webkit`-prefixed) name, and a single\n * Core-level `_gen` generation guard protects the asynchronous\n * `requestPointerLock()` call from stale resolution after dispose().\n *\n * Key difference from Fullscreen (docs/pointer-lock-tag-design.md §2):\n * `exitPointerLock()` is a *synchronous* platform API (it returns `void`, not\n * a `Promise`), so the Core's `exitPointerLock()` command is synchronous too\n * and carries no `_gen` guard of its own — it is wrapped in `try/catch` only\n * as a defensive measure (never-throw), not because it can go stale.\n *\n * Scope note (docs/pointer-lock-tag-design.md §3): `movementX`/`movementY`\n * are intentionally NOT exposed by this Core (v1 scope). They are\n * high-frequency `mousemove` data unsuited to the same-value-guarded\n * declarative `properties` surface; see the design doc for the rationale and\n * the planned `debounce`/`throttle`-based opt-in for a future version.\n */\nexport class PointerLockCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n // `active`'s CustomEvent detail is the bare boolean value itself — no\n // getter needed (docs/pointer-lock-tag-design.md §2). This differs from\n // FullscreenCore's `{ active }`-shaped detail + getter.\n properties: [\n { name: \"active\", event: \"wcs-pointer-lock:change\" },\n ],\n commands: [\n { name: \"requestPointerLock\", async: true },\n // Synchronous platform API (document.exitPointerLock() returns void) —\n // no `async` flag (docs/pointer-lock-tag-design.md §2).\n { name: \"exitPointerLock\" },\n ],\n };\n\n private _target: EventTarget;\n private _active = false;\n private _error: any = null;\n\n // The element this instance last resolved requestPointerLock()/observe()\n // against, kept so the document-scoped `pointerlockchange` handler can\n // self-filter under multiple concurrent instances (docs/fullscreen-tag-design.md\n // §2.1, inherited verbatim by pointer-lock per docs/pointer-lock-tag-design.md §1).\n private _resolvedTarget: Element | null = null;\n\n // True once observe() has attached the live `document` listener. Guards\n // observe() so a redundant call does not re-subscribe; dispose() resets it\n // so a later observe() resumes cleanly.\n private _subscribed = false;\n\n // Core-level generation guard (§3.4 of the guidelines / §6 of\n // fullscreen-tag-design.md): only requestPointerLock() is asynchronous and\n // needs it. exitPointerLock() is synchronous and has no stale-resolution\n // race to guard against.\n private _gen = 0;\n\n // SSR (§3.8): no asynchronous probe to await — observe() completes\n // synchronously, so readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get ready(): Promise<void> {\n return this._ready;\n }\n\n get active(): boolean {\n return this._active;\n }\n\n get error(): any {\n return this._error;\n }\n\n // Lifecycle (§3.5). Idempotent: a second observe() while already subscribed\n // updates the tracked resolved target without re-subscribing to `document`.\n observe(target: Element | null): Promise<void> {\n this._resolvedTarget = target;\n if (!this._subscribed) {\n this._subscribed = true;\n document.addEventListener(this._pointerLockChangeEventName(), this._onChange);\n }\n this._applyActive();\n return this._ready;\n }\n\n dispose(): void {\n this._gen++; // invalidate any in-flight requestPointerLock() resolution\n if (this._subscribed) {\n this._subscribed = false;\n document.removeEventListener(this._pointerLockChangeEventName(), this._onChange);\n }\n this._resolvedTarget = null;\n }\n\n /**\n * Request pointer lock on `element`. Never-throw: a missing API or a\n * rejected promise (e.g. called outside a user-gesture context —\n * `NotAllowedError`, docs/fullscreen-tag-design.md §3) is captured into\n * `error` rather than propagated. `element` may be `null` when the Shell's\n * `target` selector did not resolve (docs/pointer-lock-tag-design.md §1\n * defers error representation to FullscreenCore verbatim — this null-target\n * case mirrors `FullscreenCore.requestFullscreen(null)`,\n * docs/fullscreen-tag-design.md §6): distinct from \"API is not supported\"\n * below, so a typo'd selector doesn't masquerade as an unsupported platform.\n */\n async requestPointerLock(element: Element | null): Promise<void> {\n const gen = ++this._gen;\n this._resolvedTarget = element;\n if (!element) {\n this._setError({ message: \"Pointer Lock target could not be resolved.\" });\n return;\n }\n const fn = this._requestPointerLockFn(element);\n if (!fn) {\n // Resolved synchronously in the same tick as the call — dispose()\n // cannot have run yet, so no staleness check is needed here (matches\n // the reference `requestFullscreen()` implementation,\n // docs/fullscreen-tag-design.md §6).\n this._setError({ message: \"Pointer Lock API is not supported.\" });\n return;\n }\n try {\n // fn is already bound to `element` by _requestPointerLockFn().\n await fn();\n if (gen !== this._gen) return; // stale\n this._setError(null);\n this._applyActive();\n } catch (e: any) {\n if (gen !== this._gen) return; // stale\n this._setError(e);\n }\n }\n\n /**\n * Exit pointer lock. Synchronous platform API (docs/pointer-lock-tag-design.md\n * §2) — returns `void`, not a `Promise`. Silent no-op when nothing is\n * currently locked or the API is unsupported (mirrors\n * `FullscreenCore.exitFullscreen()`'s no-op contract,\n * docs/fullscreen-tag-design.md §7). Wrapped in try/catch defensively: even\n * though the platform API is synchronous and documented as not throwing in\n * this case, a synchronous throw from a non-conformant/fake implementation\n * must never escape (never-throw).\n */\n exitPointerLock(): void {\n try {\n if (this._pointerLockElement() === null) return; // already unlocked: silent no-op\n const fn = this._exitPointerLockFn();\n if (!fn) return; // unsupported: silent no-op (semantically already \"not locked\")\n fn();\n this._setError(null);\n this._applyActive();\n } catch (e: any) {\n this._setError(e);\n }\n }\n\n // --- API resolution (call-time, never cached — §3.7) ---\n\n // Resolved from `Element.prototype` rather than `el.requestPointerLock`\n // directly: when `target=\"self\"`, `el` is the `<wcs-pointer-lock>` Shell\n // itself, whose own class declares an instance method also named\n // `requestPointerLock()` (the wcBindable command). Reading the property off\n // the instance would pick up that Shell method instead of the native\n // platform API and recurse infinitely (Shell.requestPointerLock() ->\n // Core.requestPointerLock() -> resolves \"el.requestPointerLock\" -> the same\n // Shell method again). Going through `Element.prototype` sidesteps the name\n // collision — note this does NOT pick up an override on a subclass's own\n // prototype (e.g. `WcsPointerLock.prototype`); it deliberately jumps\n // straight to the platform-defined layer. Both the standard and legacy name\n // are resolved the same way, for symmetry — matching FullscreenCore's\n // `_elementFullscreenFn` (docs/fullscreen-tag-design.md §4) ONLY in that one\n // respect. Unlike that Core, this one does not check `el`'s own properties\n // first: there is no test-stub/per-element monkey-patch path to accommodate\n // here (mocks.ts installs the fakes directly on `Element.prototype`), so it\n // goes straight there for both names.\n private _requestPointerLockFn(el: Element): (() => Promise<void>) | undefined {\n const proto = Element.prototype as any;\n const standard = proto.requestPointerLock;\n if (typeof standard === \"function\") return standard.bind(el);\n const legacy = proto.webkitRequestPointerLock;\n return typeof legacy === \"function\" ? legacy.bind(el) : undefined;\n }\n\n private _exitPointerLockFn(): (() => void) | undefined {\n const d = document as any;\n return d.exitPointerLock?.bind(document) ?? d.webkitExitPointerLock?.bind(document);\n }\n\n private _pointerLockElement(): Element | null {\n const d = document as any;\n return d.pointerLockElement ?? d.webkitPointerLockElement ?? null;\n }\n\n // NOTE (test-environment caveat, not a production concern): happy-dom\n // always implements `document.onpointerlockchange` (as `null`) regardless\n // of which fake API surface a test installs, so `\"onpointerlockchange\" in\n // document` can never observably be `false` under this test runner and the\n // `webkitpointerlockchange` branch below cannot be driven through\n // `observe()` in a unit test. The branch is still correct and required for\n // real legacy WebKit builds that lack `onpointerlockchange` entirely — kept\n // as documented, deliberate, untestable-in-this-harness code per\n // docs/pointer-lock-tag-design.md.\n /* v8 ignore next 3 */\n private _pointerLockChangeEventName(): string {\n return \"onpointerlockchange\" in document ? \"pointerlockchange\" : \"webkitpointerlockchange\";\n }\n\n private _onChange = (): void => {\n this._applyActive();\n };\n\n // Self-filter (docs/fullscreen-tag-design.md §2.1): compares against this\n // instance's own resolved target, not merely \"is *something* locked\" — so\n // multiple concurrent instances each report the correct `active` value.\n private _applyActive(): void {\n const next = this._resolvedTarget !== null && this._pointerLockElement() === this._resolvedTarget;\n this._setActive(next);\n }\n\n // Same-value guard (MUST, §3.3 of the guidelines). detail itself is the\n // bare boolean value (no getter needed) per docs/pointer-lock-tag-design.md\n // §2 — unlike FullscreenCore's `{ active }`-shaped detail + getter.\n private _setActive(v: boolean): void {\n if (this._active === v) return;\n this._active = v;\n this._target.dispatchEvent(new CustomEvent(\"wcs-pointer-lock:change\", {\n detail: v,\n bubbles: true,\n }));\n }\n\n private _setError(e: any): void {\n this._error = e;\n }\n}\n","import { IWcBindable } from \"../types.js\";\nimport { PointerLockCore } from \"../core/PointerLockCore.js\";\n\n/**\n * `<wcs-pointer-lock target=\"...\">` — declarative Pointer Lock API control.\n *\n * Like `<wcs-fullscreen>` (docs/fullscreen-tag-design.md §0), this Shell does\n * not lock itself — it operates on a *referenced* element via the `target`\n * attribute, using the same 3-mode resolution rule as `intersection`\n * (`_resolveTarget()`/`_safeQuery()`, copied verbatim per\n * docs/pointer-lock-tag-design.md §1 / docs/fullscreen-tag-design.md §1):\n *\n * | `target` | operates on | display |\n * |-----------------|-------------------------|-------------|\n * | omitted | first element child | `contents` |\n * | `\"#selector\"` | the matched element | `none` |\n * | `\"self\"` | the element itself | `block` |\n *\n * `requestPointerLock()` requires a user-gesture context (docs/fullscreen-tag-design.md\n * §3) — the primary activation path is the command-token protocol\n * (`command.requestPointerLock: $command.<token>` on `<wcs-pointer-lock>`,\n * emitted by a button's `onclick: $command.<token>`), not an\n * autoTrigger attribute (none is provided in v1,\n * docs/pointer-lock-tag-design.md §4).\n *\n * `movementX`/`movementY` are intentionally out of scope for v1\n * (docs/pointer-lock-tag-design.md §3) — do not add them without revisiting\n * the design doc.\n */\nexport class WcsPointerLock extends HTMLElement {\n // SSR (§4.4): the Core subscribes synchronously on connect, but the Shell\n // still exposes connectedCallbackPromise so the state binder can await it\n // uniformly across all IO nodes before snapshotting.\n static hasConnectedCallbackPromise = true;\n\n static observedAttributes = [\"target\"];\n\n static wcBindable: IWcBindable = {\n ...PointerLockCore.wcBindable,\n inputs: [{ name: \"target\", attribute: \"target\" }],\n // Core の commands をそのまま継承(単一情報源)。network/intersection と同型。\n commands: PointerLockCore.wcBindable.commands,\n };\n\n private _core: PointerLockCore;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n\n constructor() {\n super();\n this._core = new PointerLockCore(this);\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Attribute accessors ---\n\n get target(): string {\n return this.getAttribute(\"target\") ?? \"\";\n }\n\n set target(value: string) {\n this.setAttribute(\"target\", value);\n }\n\n // --- Core delegated getters ---\n\n get active(): boolean {\n return this._core.active;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n // --- Commands ---\n\n /**\n * Resolve `target` and request pointer lock on it. Requires a user-gesture\n * context. never-throw: an unresolvable target or an unsupported/rejected\n * API call are both surfaced via `error`, never thrown (mirrors\n * `<wcs-fullscreen>`'s `requestFullscreen()`, docs/fullscreen-tag-design.md\n * §3/§6 — the Shell passes the (possibly `null`) resolved element straight\n * through and lets the Core set `error`, rather than silently no-op'ing\n * here).\n */\n async requestPointerLock(): Promise<void> {\n const { element } = this._resolveTarget();\n await this._core.requestPointerLock(element);\n }\n\n /** Exit pointer lock. Synchronous command — silent no-op if nothing is locked. */\n exitPointerLock(): void {\n this._core.exitPointerLock();\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this._applyDisplayAndObserve();\n }\n\n disconnectedCallback(): void {\n this._core.dispose();\n }\n\n attributeChangedCallback(name: string): void {\n if (name === \"target\" && this.isConnected) {\n this._applyDisplayAndObserve();\n }\n }\n\n // --- Internal ---\n\n private _applyDisplayAndObserve(): void {\n const { element, display } = this._resolveTarget();\n this.style.display = display;\n this._connectedCallbackPromise = this._core.observe(element);\n }\n\n // Copied verbatim from packages/intersection/src/components/Intersect.ts\n // (§1 of docs/pointer-lock-tag-design.md / docs/fullscreen-tag-design.md).\n private _resolveTarget(): { element: Element | null; display: string } {\n const target = this.target;\n if (target === \"self\") {\n return { element: this, display: \"block\" };\n }\n if (target !== \"\") {\n const scope = this.getRootNode() as Document | ShadowRoot;\n return { element: this._safeQuery(scope, target), display: \"none\" };\n }\n const child = this.firstElementChild;\n if (child) {\n return { element: child, display: \"contents\" };\n }\n return { element: this, display: \"block\" };\n }\n\n // Copied verbatim from packages/intersection/src/components/Intersect.ts.\n private _safeQuery(scope: Document | ShadowRoot, selector: string): Element | null {\n try {\n return scope.querySelector(selector);\n } catch {\n return null;\n }\n }\n}\n","import { WcsPointerLock } from \"./components/PointerLock.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.pointerLock)) {\n customElements.define(config.tagNames.pointerLock, WcsPointerLock);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapPointerLock(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n"],"names":[],"mappings":"AAQA,MAAM,OAAO,GAAoB;AAC/B,IAAA,QAAQ,EAAE;AACR,QAAA,WAAW,EAAE,kBAAkB;AAChC,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;AAEhC,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,aAAa,CAAC,QAAQ,EAAE;QAC1B,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,aAAa,CAAC,QAAQ,CAAC;IACzD;IACA,YAAY,GAAG,IAAI;AACrB;;AC9CA;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BG;AACG,MAAO,eAAgB,SAAQ,WAAW,CAAA;IAC9C,OAAO,UAAU,GAAgB;AAC/B,QAAA,QAAQ,EAAE,aAAa;AACvB,QAAA,OAAO,EAAE,CAAC;;;;AAIV,QAAA,UAAU,EAAE;AACV,YAAA,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,yBAAyB,EAAE;AACrD,SAAA;AACD,QAAA,QAAQ,EAAE;AACR,YAAA,EAAE,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,IAAI,EAAE;;;YAG3C,EAAE,IAAI,EAAE,iBAAiB,EAAE;AAC5B,SAAA;KACF;AAEO,IAAA,OAAO;IACP,OAAO,GAAG,KAAK;IACf,MAAM,GAAQ,IAAI;;;;;IAMlB,eAAe,GAAmB,IAAI;;;;IAKtC,WAAW,GAAG,KAAK;;;;;IAMnB,IAAI,GAAG,CAAC;;;AAIR,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,MAAM,GAAA;QACR,OAAO,IAAI,CAAC,OAAO;IACrB;AAEA,IAAA,IAAI,KAAK,GAAA;QACP,OAAO,IAAI,CAAC,MAAM;IACpB;;;AAIA,IAAA,OAAO,CAAC,MAAsB,EAAA;AAC5B,QAAA,IAAI,CAAC,eAAe,GAAG,MAAM;AAC7B,QAAA,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;AACrB,YAAA,IAAI,CAAC,WAAW,GAAG,IAAI;AACvB,YAAA,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,2BAA2B,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC;QAC/E;QACA,IAAI,CAAC,YAAY,EAAE;QACnB,OAAO,IAAI,CAAC,MAAM;IACpB;IAEA,OAAO,GAAA;AACL,QAAA,IAAI,CAAC,IAAI,EAAE,CAAC;AACZ,QAAA,IAAI,IAAI,CAAC,WAAW,EAAE;AACpB,YAAA,IAAI,CAAC,WAAW,GAAG,KAAK;AACxB,YAAA,QAAQ,CAAC,mBAAmB,CAAC,IAAI,CAAC,2BAA2B,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC;QAClF;AACA,QAAA,IAAI,CAAC,eAAe,GAAG,IAAI;IAC7B;AAEA;;;;;;;;;;AAUG;IACH,MAAM,kBAAkB,CAAC,OAAuB,EAAA;AAC9C,QAAA,MAAM,GAAG,GAAG,EAAE,IAAI,CAAC,IAAI;AACvB,QAAA,IAAI,CAAC,eAAe,GAAG,OAAO;QAC9B,IAAI,CAAC,OAAO,EAAE;YACZ,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,4CAA4C,EAAE,CAAC;YACzE;QACF;QACA,MAAM,EAAE,GAAG,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC;QAC9C,IAAI,CAAC,EAAE,EAAE;;;;;YAKP,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,oCAAoC,EAAE,CAAC;YACjE;QACF;AACA,QAAA,IAAI;;YAEF,MAAM,EAAE,EAAE;AACV,YAAA,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI;AAAE,gBAAA,OAAO;AAC9B,YAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YACpB,IAAI,CAAC,YAAY,EAAE;QACrB;QAAE,OAAO,CAAM,EAAE;AACf,YAAA,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI;AAAE,gBAAA,OAAO;AAC9B,YAAA,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;QACnB;IACF;AAEA;;;;;;;;;AASG;IACH,eAAe,GAAA;AACb,QAAA,IAAI;AACF,YAAA,IAAI,IAAI,CAAC,mBAAmB,EAAE,KAAK,IAAI;AAAE,gBAAA,OAAO;AAChD,YAAA,MAAM,EAAE,GAAG,IAAI,CAAC,kBAAkB,EAAE;AACpC,YAAA,IAAI,CAAC,EAAE;AAAE,gBAAA,OAAO;AAChB,YAAA,EAAE,EAAE;AACJ,YAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YACpB,IAAI,CAAC,YAAY,EAAE;QACrB;QAAE,OAAO,CAAM,EAAE;AACf,YAAA,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;QACnB;IACF;;;;;;;;;;;;;;;;;;;AAqBQ,IAAA,qBAAqB,CAAC,EAAW,EAAA;AACvC,QAAA,MAAM,KAAK,GAAG,OAAO,CAAC,SAAgB;AACtC,QAAA,MAAM,QAAQ,GAAG,KAAK,CAAC,kBAAkB;QACzC,IAAI,OAAO,QAAQ,KAAK,UAAU;AAAE,YAAA,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;AAC5D,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,wBAAwB;AAC7C,QAAA,OAAO,OAAO,MAAM,KAAK,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,SAAS;IACnE;IAEQ,kBAAkB,GAAA;QACxB,MAAM,CAAC,GAAG,QAAe;AACzB,QAAA,OAAO,CAAC,CAAC,eAAe,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,qBAAqB,EAAE,IAAI,CAAC,QAAQ,CAAC;IACrF;IAEQ,mBAAmB,GAAA;QACzB,MAAM,CAAC,GAAG,QAAe;QACzB,OAAO,CAAC,CAAC,kBAAkB,IAAI,CAAC,CAAC,wBAAwB,IAAI,IAAI;IACnE;;;;;;;;;;;IAYQ,2BAA2B,GAAA;QACjC,OAAO,qBAAqB,IAAI,QAAQ,GAAG,mBAAmB,GAAG,yBAAyB;IAC5F;IAEQ,SAAS,GAAG,MAAW;QAC7B,IAAI,CAAC,YAAY,EAAE;AACrB,IAAA,CAAC;;;;IAKO,YAAY,GAAA;AAClB,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,KAAK,IAAI,IAAI,IAAI,CAAC,mBAAmB,EAAE,KAAK,IAAI,CAAC,eAAe;AACjG,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;IACvB;;;;AAKQ,IAAA,UAAU,CAAC,CAAU,EAAA;AAC3B,QAAA,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC;YAAE;AACxB,QAAA,IAAI,CAAC,OAAO,GAAG,CAAC;QAChB,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,yBAAyB,EAAE;AACpE,YAAA,MAAM,EAAE,CAAC;AACT,YAAA,OAAO,EAAE,IAAI;AACd,SAAA,CAAC,CAAC;IACL;AAEQ,IAAA,SAAS,CAAC,CAAM,EAAA;AACtB,QAAA,IAAI,CAAC,MAAM,GAAG,CAAC;IACjB;;;ACxPF;;;;;;;;;;;;;;;;;;;;;;;;;AAyBG;AACG,MAAO,cAAe,SAAQ,WAAW,CAAA;;;;AAI7C,IAAA,OAAO,2BAA2B,GAAG,IAAI;AAEzC,IAAA,OAAO,kBAAkB,GAAG,CAAC,QAAQ,CAAC;IAEtC,OAAO,UAAU,GAAgB;QAC/B,GAAG,eAAe,CAAC,UAAU;QAC7B,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;;AAEjD,QAAA,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,QAAQ;KAC9C;AAEO,IAAA,KAAK;AACL,IAAA,yBAAyB,GAAkB,OAAO,CAAC,OAAO,EAAE;AAEpE,IAAA,WAAA,GAAA;AACE,QAAA,KAAK,EAAE;QACP,IAAI,CAAC,KAAK,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC;IACxC;AAEA,IAAA,IAAI,wBAAwB,GAAA;QAC1B,OAAO,IAAI,CAAC,yBAAyB;IACvC;;AAIA,IAAA,IAAI,MAAM,GAAA;QACR,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE;IAC1C;IAEA,IAAI,MAAM,CAAC,KAAa,EAAA;AACtB,QAAA,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC;IACpC;;AAIA,IAAA,IAAI,MAAM,GAAA;AACR,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM;IAC1B;AAEA,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK;IACzB;;AAIA;;;;;;;;AAQG;AACH,IAAA,MAAM,kBAAkB,GAAA;QACtB,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE;QACzC,MAAM,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,OAAO,CAAC;IAC9C;;IAGA,eAAe,GAAA;AACb,QAAA,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE;IAC9B;;IAIA,iBAAiB,GAAA;QACf,IAAI,CAAC,uBAAuB,EAAE;IAChC;IAEA,oBAAoB,GAAA;AAClB,QAAA,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE;IACtB;AAEA,IAAA,wBAAwB,CAAC,IAAY,EAAA;QACnC,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,WAAW,EAAE;YACzC,IAAI,CAAC,uBAAuB,EAAE;QAChC;IACF;;IAIQ,uBAAuB,GAAA;QAC7B,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE;AAClD,QAAA,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,OAAO;QAC5B,IAAI,CAAC,yBAAyB,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;IAC9D;;;IAIQ,cAAc,GAAA;AACpB,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM;AAC1B,QAAA,IAAI,MAAM,KAAK,MAAM,EAAE;YACrB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE;QAC5C;AACA,QAAA,IAAI,MAAM,KAAK,EAAE,EAAE;AACjB,YAAA,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAA2B;AACzD,YAAA,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE;QACrE;AACA,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB;QACpC,IAAI,KAAK,EAAE;YACT,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE;QAChD;QACA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE;IAC5C;;IAGQ,UAAU,CAAC,KAA4B,EAAE,QAAgB,EAAA;AAC/D,QAAA,IAAI;AACF,YAAA,OAAO,KAAK,CAAC,aAAa,CAAC,QAAQ,CAAC;QACtC;AAAE,QAAA,MAAM;AACN,YAAA,OAAO,IAAI;QACb;IACF;;;SC/Ic,kBAAkB,GAAA;AAChC,IAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE;QACpD,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;IACpE;AACF;;ACHM,SAAU,oBAAoB,CAAC,UAA4B,EAAA;IAC/D,IAAI,UAAU,EAAE;QACd,SAAS,CAAC,UAAU,CAAC;IACvB;AACA,IAAA,kBAAkB,EAAE;AACtB;;;;"}
1
+ {"version":3,"file":"index.esm.js","sources":["../src/config.ts","../src/core/PointerLockCore.ts","../src/components/PointerLock.ts","../src/registerComponents.ts","../src/bootstrapPointerLock.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n tagNames: {\n pointerLock: string;\n };\n}\n\nconst _config: IInternalConfig = {\n tagNames: {\n pointerLock: \"wcs-pointer-lock\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { IWcBindable } from \"../types.js\";\n\n/**\n * Headless Pointer Lock primitive. A thin, framework-agnostic wrapper around\n * the Pointer Lock API (`Element.requestPointerLock()` /\n * `document.exitPointerLock()` / `document.pointerLockElement` / the\n * `document`-scoped `pointerlockchange` event) exposed through the\n * wc-bindable protocol.\n *\n * This Core follows the same basic pattern as `FullscreenCore`\n * (docs/fullscreen-tag-design.md, referenced by docs/pointer-lock-tag-design.md\n * §1): target resolution happens in the Shell, `pointerlockchange` is\n * subscribed on `document` (not on the target element) and each instance\n * self-filters by comparing `document.pointerLockElement` against its own\n * resolved target, API resolution is call-time (never cached) and probes the\n * standard name before the legacy (`webkit`-prefixed) name, and a single\n * Core-level `_gen` generation guard protects the asynchronous\n * `requestPointerLock()` call from stale resolution after dispose().\n *\n * Key difference from Fullscreen (docs/pointer-lock-tag-design.md §2):\n * `exitPointerLock()` is a *synchronous* platform API (it returns `void`, not\n * a `Promise`), so the Core's `exitPointerLock()` command is synchronous too\n * and carries no `_gen` guard of its own — it is wrapped in `try/catch` only\n * as a defensive measure (never-throw), not because it can go stale.\n *\n * Scope note (docs/pointer-lock-tag-design.md §3): `movementX`/`movementY`\n * are intentionally NOT exposed by this Core (v1 scope). They are\n * high-frequency `mousemove` data unsuited to the same-value-guarded\n * declarative `properties` surface; see the design doc for the rationale and\n * the planned `debounce`/`throttle`-based opt-in for a future version.\n */\nexport class PointerLockCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n // `active`'s CustomEvent detail is the bare boolean value itself — no\n // getter needed (docs/pointer-lock-tag-design.md §2). This differs from\n // FullscreenCore's `{ active }`-shaped detail + getter.\n properties: [\n { name: \"active\", event: \"wcs-pointer-lock:change\" },\n ],\n commands: [\n { name: \"requestPointerLock\", async: true },\n // Synchronous platform API (document.exitPointerLock() returns void) —\n // no `async` flag (docs/pointer-lock-tag-design.md §2).\n { name: \"exitPointerLock\" },\n ],\n };\n\n private _target: EventTarget;\n private _active = false;\n private _error: any = null;\n\n // The element this instance last resolved requestPointerLock()/observe()\n // against, kept so the document-scoped `pointerlockchange` handler can\n // self-filter under multiple concurrent instances (docs/fullscreen-tag-design.md\n // §2.1, inherited verbatim by pointer-lock per docs/pointer-lock-tag-design.md §1).\n private _resolvedTarget: Element | null = null;\n\n // True once observe() has attached the live `document` listener. Guards\n // observe() so a redundant call does not re-subscribe; dispose() resets it\n // so a later observe() resumes cleanly.\n private _subscribed = false;\n\n // Core-level generation guard (§3.4 of the guidelines / §6 of\n // fullscreen-tag-design.md): only requestPointerLock() is asynchronous and\n // needs it. exitPointerLock() is synchronous and has no stale-resolution\n // race to guard against.\n private _gen = 0;\n\n // SSR (§3.8): no asynchronous probe to await — observe() completes\n // synchronously, so readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get ready(): Promise<void> {\n return this._ready;\n }\n\n get active(): boolean {\n return this._active;\n }\n\n get error(): any {\n return this._error;\n }\n\n // Lifecycle (§3.5). Idempotent: a second observe() while already subscribed\n // updates the tracked resolved target without re-subscribing to `document`.\n observe(target: Element | null): Promise<void> {\n this._resolvedTarget = target;\n if (!this._subscribed) {\n this._subscribed = true;\n document.addEventListener(this._pointerLockChangeEventName(), this._onChange);\n }\n this._applyActive();\n return this._ready;\n }\n\n dispose(): void {\n this._gen++; // invalidate any in-flight requestPointerLock() resolution\n if (this._subscribed) {\n this._subscribed = false;\n document.removeEventListener(this._pointerLockChangeEventName(), this._onChange);\n }\n this._resolvedTarget = null;\n }\n\n /**\n * Request pointer lock on `element`. Never-throw: a missing API or a\n * rejected promise (e.g. called outside a user-gesture context —\n * `NotAllowedError`, docs/fullscreen-tag-design.md §3) is captured into\n * `error` rather than propagated. `element` may be `null` when the Shell's\n * `target` selector did not resolve (docs/pointer-lock-tag-design.md §1\n * defers error representation to FullscreenCore verbatim — this null-target\n * case mirrors `FullscreenCore.requestFullscreen(null)`,\n * docs/fullscreen-tag-design.md §6): distinct from \"API is not supported\"\n * below, so a typo'd selector doesn't masquerade as an unsupported platform.\n */\n async requestPointerLock(element: Element | null): Promise<void> {\n const gen = ++this._gen;\n this._resolvedTarget = element;\n if (!element) {\n this._setError({ message: \"Pointer Lock target could not be resolved.\" });\n return;\n }\n const fn = this._requestPointerLockFn(element);\n if (!fn) {\n // Resolved synchronously in the same tick as the call — dispose()\n // cannot have run yet, so no staleness check is needed here (matches\n // the reference `requestFullscreen()` implementation,\n // docs/fullscreen-tag-design.md §6).\n this._setError({ message: \"Pointer Lock API is not supported.\" });\n return;\n }\n try {\n // fn is already bound to `element` by _requestPointerLockFn().\n await fn();\n if (gen !== this._gen) return; // stale\n this._setError(null);\n this._applyActive();\n } catch (e: any) {\n if (gen !== this._gen) return; // stale\n this._setError(e);\n }\n }\n\n /**\n * Exit pointer lock. Synchronous platform API (docs/pointer-lock-tag-design.md\n * §2) — returns `void`, not a `Promise`. Silent no-op when nothing is\n * currently locked or the API is unsupported (mirrors\n * `FullscreenCore.exitFullscreen()`'s no-op contract,\n * docs/fullscreen-tag-design.md §7). Wrapped in try/catch defensively: even\n * though the platform API is synchronous and documented as not throwing in\n * this case, a synchronous throw from a non-conformant/fake implementation\n * must never escape (never-throw).\n */\n exitPointerLock(): void {\n try {\n if (this._pointerLockElement() === null) return; // already unlocked: silent no-op\n const fn = this._exitPointerLockFn();\n if (!fn) return; // unsupported: silent no-op (semantically already \"not locked\")\n fn();\n this._setError(null);\n this._applyActive();\n } catch (e: any) {\n this._setError(e);\n }\n }\n\n // --- API resolution (call-time, never cached — §3.7) ---\n\n // Resolved from `Element.prototype` rather than `el.requestPointerLock`\n // directly: when `target=\"self\"`, `el` is the `<wcs-pointer-lock>` Shell\n // itself, whose own class declares an instance method also named\n // `requestPointerLock()` (the wcBindable command). Reading the property off\n // the instance would pick up that Shell method instead of the native\n // platform API and recurse infinitely (Shell.requestPointerLock() ->\n // Core.requestPointerLock() -> resolves \"el.requestPointerLock\" -> the same\n // Shell method again). Going through `Element.prototype` sidesteps the name\n // collision — note this does NOT pick up an override on a subclass's own\n // prototype (e.g. `WcsPointerLock.prototype`); it deliberately jumps\n // straight to the platform-defined layer. Both the standard and legacy name\n // are resolved the same way, for symmetry — matching FullscreenCore's\n // `_elementFullscreenFn` (docs/fullscreen-tag-design.md §4) ONLY in that one\n // respect. Unlike that Core, this one does not check `el`'s own properties\n // first: there is no test-stub/per-element monkey-patch path to accommodate\n // here (mocks.ts installs the fakes directly on `Element.prototype`), so it\n // goes straight there for both names.\n private _requestPointerLockFn(el: Element): (() => Promise<void>) | undefined {\n const proto = Element.prototype as any;\n const standard = proto.requestPointerLock;\n if (typeof standard === \"function\") return standard.bind(el);\n const legacy = proto.webkitRequestPointerLock;\n return typeof legacy === \"function\" ? legacy.bind(el) : undefined;\n }\n\n private _exitPointerLockFn(): (() => void) | undefined {\n const d = document as any;\n return d.exitPointerLock?.bind(document) ?? d.webkitExitPointerLock?.bind(document);\n }\n\n private _pointerLockElement(): Element | null {\n const d = document as any;\n return d.pointerLockElement ?? d.webkitPointerLockElement ?? null;\n }\n\n // NOTE (test-environment caveat, not a production concern): happy-dom\n // always implements `document.onpointerlockchange` (as `null`) regardless\n // of which fake API surface a test installs, so `\"onpointerlockchange\" in\n // document` can never observably be `false` under this test runner and the\n // `webkitpointerlockchange` branch below cannot be driven through\n // `observe()` in a unit test. The branch is still correct and required for\n // real legacy WebKit builds that lack `onpointerlockchange` entirely — kept\n // as documented, deliberate, untestable-in-this-harness code per\n // docs/pointer-lock-tag-design.md.\n /* v8 ignore next 3 */\n private _pointerLockChangeEventName(): string {\n return \"onpointerlockchange\" in document ? \"pointerlockchange\" : \"webkitpointerlockchange\";\n }\n\n private _onChange = (): void => {\n this._applyActive();\n };\n\n // Self-filter (docs/fullscreen-tag-design.md §2.1): compares against this\n // instance's own resolved target, not merely \"is *something* locked\" — so\n // multiple concurrent instances each report the correct `active` value.\n private _applyActive(): void {\n const next = this._resolvedTarget !== null && this._pointerLockElement() === this._resolvedTarget;\n this._setActive(next);\n }\n\n // Same-value guard (MUST, §3.3 of the guidelines). detail itself is the\n // bare boolean value (no getter needed) per docs/pointer-lock-tag-design.md\n // §2 — unlike FullscreenCore's `{ active }`-shaped detail + getter.\n private _setActive(v: boolean): void {\n if (this._active === v) return;\n this._active = v;\n this._target.dispatchEvent(new CustomEvent(\"wcs-pointer-lock:change\", {\n detail: v,\n bubbles: true,\n }));\n }\n\n private _setError(e: any): void {\n this._error = e;\n }\n}\n","import { IWcBindable } from \"../types.js\";\nimport { PointerLockCore } from \"../core/PointerLockCore.js\";\n\n/**\n * `<wcs-pointer-lock target=\"...\">` — declarative Pointer Lock API control.\n *\n * Like `<wcs-fullscreen>` (docs/fullscreen-tag-design.md §0), this Shell does\n * not lock itself — it operates on a *referenced* element via the `target`\n * attribute, using the same 3-mode resolution rule as `intersection`\n * (`_resolveTarget()`/`_safeQuery()`, copied verbatim per\n * docs/pointer-lock-tag-design.md §1 / docs/fullscreen-tag-design.md §1):\n *\n * | `target` | operates on | display |\n * |-----------------|-------------------------|-------------|\n * | omitted | first element child | `contents` |\n * | `\"#selector\"` | the matched element | `none` |\n * | `\"self\"` | the element itself | `block` |\n *\n * `requestPointerLock()` requires a user-gesture context (docs/fullscreen-tag-design.md\n * §3) — the primary activation path is the command-token protocol\n * (`command.requestPointerLock: $command.<token>` on `<wcs-pointer-lock>`,\n * emitted by a button's `onclick: $command.<token>`), not an\n * autoTrigger attribute (none is provided in v1,\n * docs/pointer-lock-tag-design.md §4).\n *\n * `movementX`/`movementY` are intentionally out of scope for v1\n * (docs/pointer-lock-tag-design.md §3) — do not add them without revisiting\n * the design doc.\n */\nexport class WcsPointerLock extends HTMLElement {\n // SSR (§4.4): the Core subscribes synchronously on connect, but the Shell\n // still exposes connectedCallbackPromise so the state binder can await it\n // uniformly across all IO nodes before snapshotting.\n static hasConnectedCallbackPromise = true;\n\n static observedAttributes = [\"target\"];\n\n static wcBindable: IWcBindable = {\n ...PointerLockCore.wcBindable,\n inputs: [{ name: \"target\", attribute: \"target\" }],\n // Core の commands をそのまま継承(単一情報源)。network/intersection と同型。\n commands: PointerLockCore.wcBindable.commands,\n };\n\n private _core: PointerLockCore;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new PointerLockCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n \"wcs-pointer-lock:change\": (d) => ({ active: d === true }),\n });\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // CSS state reflection (:state()) — debug-only snapshot getter. NOT part of\n // wc-bindable (not a bind target); see README \"CSS styling with :state()\".\n // MUST NOT return the live CustomStateSet (that would let callers write\n // states from outside, defeating the point of :state() being read-only).\n get debugStates(): string[] {\n return this._internals ? [...this._internals.states] : [];\n }\n\n private _initInternals(): ElementInternals | null {\n // never-throw (docs/custom-state-reflection-design.md §3.6): attachInternals\n // is absent in happy-dom / older environments, and pre-125 Chromium rejects\n // non-dashed state names from states.add() (probed and discarded here).\n // Either case silently disables reflection — the component still works,\n // it just doesn't expose :state() selectors.\n try {\n if (typeof this.attachInternals !== \"function\") return null;\n const internals = this.attachInternals();\n internals.states.add(\"wcs-probe\");\n internals.states.delete(\"wcs-probe\");\n return internals;\n } catch {\n return null;\n }\n }\n\n private _wireStates(map: Record<string, (detail: any) => Record<string, boolean>>): void {\n if (this._internals === null) return;\n const states = this._internals.states;\n for (const [event, toStates] of Object.entries(map)) {\n this.addEventListener(event, (e) => {\n const debug = this.hasAttribute(\"debug-states\");\n for (const [name, on] of Object.entries(toStates((e as CustomEvent).detail))) {\n try {\n if (on) { states.add(name); } else { states.delete(name); }\n } catch { /* never-throw */ }\n if (debug) this.toggleAttribute(`data-wcs-state-${name}`, on);\n }\n });\n }\n }\n\n // --- Attribute accessors ---\n\n get target(): string {\n return this.getAttribute(\"target\") ?? \"\";\n }\n\n set target(value: string) {\n this.setAttribute(\"target\", value);\n }\n\n // --- Core delegated getters ---\n\n get active(): boolean {\n return this._core.active;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n // --- Commands ---\n\n /**\n * Resolve `target` and request pointer lock on it. Requires a user-gesture\n * context. never-throw: an unresolvable target or an unsupported/rejected\n * API call are both surfaced via `error`, never thrown (mirrors\n * `<wcs-fullscreen>`'s `requestFullscreen()`, docs/fullscreen-tag-design.md\n * §3/§6 — the Shell passes the (possibly `null`) resolved element straight\n * through and lets the Core set `error`, rather than silently no-op'ing\n * here).\n */\n async requestPointerLock(): Promise<void> {\n const { element } = this._resolveTarget();\n await this._core.requestPointerLock(element);\n }\n\n /** Exit pointer lock. Synchronous command — silent no-op if nothing is locked. */\n exitPointerLock(): void {\n this._core.exitPointerLock();\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this._applyDisplayAndObserve();\n }\n\n disconnectedCallback(): void {\n this._core.dispose();\n }\n\n attributeChangedCallback(name: string): void {\n if (name === \"target\" && this.isConnected) {\n this._applyDisplayAndObserve();\n }\n }\n\n // --- Internal ---\n\n private _applyDisplayAndObserve(): void {\n const { element, display } = this._resolveTarget();\n this.style.display = display;\n this._connectedCallbackPromise = this._core.observe(element);\n }\n\n // Copied verbatim from packages/intersection/src/components/Intersect.ts\n // (§1 of docs/pointer-lock-tag-design.md / docs/fullscreen-tag-design.md).\n private _resolveTarget(): { element: Element | null; display: string } {\n const target = this.target;\n if (target === \"self\") {\n return { element: this, display: \"block\" };\n }\n if (target !== \"\") {\n const scope = this.getRootNode() as Document | ShadowRoot;\n return { element: this._safeQuery(scope, target), display: \"none\" };\n }\n const child = this.firstElementChild;\n if (child) {\n return { element: child, display: \"contents\" };\n }\n return { element: this, display: \"block\" };\n }\n\n // Copied verbatim from packages/intersection/src/components/Intersect.ts.\n private _safeQuery(scope: Document | ShadowRoot, selector: string): Element | null {\n try {\n return scope.querySelector(selector);\n } catch {\n return null;\n }\n }\n}\n","import { WcsPointerLock } from \"./components/PointerLock.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.pointerLock)) {\n customElements.define(config.tagNames.pointerLock, WcsPointerLock);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapPointerLock(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n"],"names":[],"mappings":"AAQA,MAAM,OAAO,GAAoB;AAC/B,IAAA,QAAQ,EAAE;AACR,QAAA,WAAW,EAAE,kBAAkB;AAChC,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;AAEhC,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,aAAa,CAAC,QAAQ,EAAE;QAC1B,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,aAAa,CAAC,QAAQ,CAAC;IACzD;IACA,YAAY,GAAG,IAAI;AACrB;;AC9CA;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BG;AACG,MAAO,eAAgB,SAAQ,WAAW,CAAA;IAC9C,OAAO,UAAU,GAAgB;AAC/B,QAAA,QAAQ,EAAE,aAAa;AACvB,QAAA,OAAO,EAAE,CAAC;;;;AAIV,QAAA,UAAU,EAAE;AACV,YAAA,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,yBAAyB,EAAE;AACrD,SAAA;AACD,QAAA,QAAQ,EAAE;AACR,YAAA,EAAE,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,IAAI,EAAE;;;YAG3C,EAAE,IAAI,EAAE,iBAAiB,EAAE;AAC5B,SAAA;KACF;AAEO,IAAA,OAAO;IACP,OAAO,GAAG,KAAK;IACf,MAAM,GAAQ,IAAI;;;;;IAMlB,eAAe,GAAmB,IAAI;;;;IAKtC,WAAW,GAAG,KAAK;;;;;IAMnB,IAAI,GAAG,CAAC;;;AAIR,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,MAAM,GAAA;QACR,OAAO,IAAI,CAAC,OAAO;IACrB;AAEA,IAAA,IAAI,KAAK,GAAA;QACP,OAAO,IAAI,CAAC,MAAM;IACpB;;;AAIA,IAAA,OAAO,CAAC,MAAsB,EAAA;AAC5B,QAAA,IAAI,CAAC,eAAe,GAAG,MAAM;AAC7B,QAAA,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;AACrB,YAAA,IAAI,CAAC,WAAW,GAAG,IAAI;AACvB,YAAA,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,2BAA2B,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC;QAC/E;QACA,IAAI,CAAC,YAAY,EAAE;QACnB,OAAO,IAAI,CAAC,MAAM;IACpB;IAEA,OAAO,GAAA;AACL,QAAA,IAAI,CAAC,IAAI,EAAE,CAAC;AACZ,QAAA,IAAI,IAAI,CAAC,WAAW,EAAE;AACpB,YAAA,IAAI,CAAC,WAAW,GAAG,KAAK;AACxB,YAAA,QAAQ,CAAC,mBAAmB,CAAC,IAAI,CAAC,2BAA2B,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC;QAClF;AACA,QAAA,IAAI,CAAC,eAAe,GAAG,IAAI;IAC7B;AAEA;;;;;;;;;;AAUG;IACH,MAAM,kBAAkB,CAAC,OAAuB,EAAA;AAC9C,QAAA,MAAM,GAAG,GAAG,EAAE,IAAI,CAAC,IAAI;AACvB,QAAA,IAAI,CAAC,eAAe,GAAG,OAAO;QAC9B,IAAI,CAAC,OAAO,EAAE;YACZ,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,4CAA4C,EAAE,CAAC;YACzE;QACF;QACA,MAAM,EAAE,GAAG,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC;QAC9C,IAAI,CAAC,EAAE,EAAE;;;;;YAKP,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,oCAAoC,EAAE,CAAC;YACjE;QACF;AACA,QAAA,IAAI;;YAEF,MAAM,EAAE,EAAE;AACV,YAAA,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI;AAAE,gBAAA,OAAO;AAC9B,YAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YACpB,IAAI,CAAC,YAAY,EAAE;QACrB;QAAE,OAAO,CAAM,EAAE;AACf,YAAA,IAAI,GAAG,KAAK,IAAI,CAAC,IAAI;AAAE,gBAAA,OAAO;AAC9B,YAAA,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;QACnB;IACF;AAEA;;;;;;;;;AASG;IACH,eAAe,GAAA;AACb,QAAA,IAAI;AACF,YAAA,IAAI,IAAI,CAAC,mBAAmB,EAAE,KAAK,IAAI;AAAE,gBAAA,OAAO;AAChD,YAAA,MAAM,EAAE,GAAG,IAAI,CAAC,kBAAkB,EAAE;AACpC,YAAA,IAAI,CAAC,EAAE;AAAE,gBAAA,OAAO;AAChB,YAAA,EAAE,EAAE;AACJ,YAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YACpB,IAAI,CAAC,YAAY,EAAE;QACrB;QAAE,OAAO,CAAM,EAAE;AACf,YAAA,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;QACnB;IACF;;;;;;;;;;;;;;;;;;;AAqBQ,IAAA,qBAAqB,CAAC,EAAW,EAAA;AACvC,QAAA,MAAM,KAAK,GAAG,OAAO,CAAC,SAAgB;AACtC,QAAA,MAAM,QAAQ,GAAG,KAAK,CAAC,kBAAkB;QACzC,IAAI,OAAO,QAAQ,KAAK,UAAU;AAAE,YAAA,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;AAC5D,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,wBAAwB;AAC7C,QAAA,OAAO,OAAO,MAAM,KAAK,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,SAAS;IACnE;IAEQ,kBAAkB,GAAA;QACxB,MAAM,CAAC,GAAG,QAAe;AACzB,QAAA,OAAO,CAAC,CAAC,eAAe,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,qBAAqB,EAAE,IAAI,CAAC,QAAQ,CAAC;IACrF;IAEQ,mBAAmB,GAAA;QACzB,MAAM,CAAC,GAAG,QAAe;QACzB,OAAO,CAAC,CAAC,kBAAkB,IAAI,CAAC,CAAC,wBAAwB,IAAI,IAAI;IACnE;;;;;;;;;;;IAYQ,2BAA2B,GAAA;QACjC,OAAO,qBAAqB,IAAI,QAAQ,GAAG,mBAAmB,GAAG,yBAAyB;IAC5F;IAEQ,SAAS,GAAG,MAAW;QAC7B,IAAI,CAAC,YAAY,EAAE;AACrB,IAAA,CAAC;;;;IAKO,YAAY,GAAA;AAClB,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,KAAK,IAAI,IAAI,IAAI,CAAC,mBAAmB,EAAE,KAAK,IAAI,CAAC,eAAe;AACjG,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;IACvB;;;;AAKQ,IAAA,UAAU,CAAC,CAAU,EAAA;AAC3B,QAAA,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC;YAAE;AACxB,QAAA,IAAI,CAAC,OAAO,GAAG,CAAC;QAChB,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,yBAAyB,EAAE;AACpE,YAAA,MAAM,EAAE,CAAC;AACT,YAAA,OAAO,EAAE,IAAI;AACd,SAAA,CAAC,CAAC;IACL;AAEQ,IAAA,SAAS,CAAC,CAAM,EAAA;AACtB,QAAA,IAAI,CAAC,MAAM,GAAG,CAAC;IACjB;;;ACxPF;;;;;;;;;;;;;;;;;;;;;;;;;AAyBG;AACG,MAAO,cAAe,SAAQ,WAAW,CAAA;;;;AAI7C,IAAA,OAAO,2BAA2B,GAAG,IAAI;AAEzC,IAAA,OAAO,kBAAkB,GAAG,CAAC,QAAQ,CAAC;IAEtC,OAAO,UAAU,GAAgB;QAC/B,GAAG,eAAe,CAAC,UAAU;QAC7B,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;;AAEjD,QAAA,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,QAAQ;KAC9C;AAEO,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,eAAe,CAAC,IAAI,CAAC;AACtC,QAAA,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,cAAc,EAAE;QACvC,IAAI,CAAC,WAAW,CAAC;AACf,YAAA,yBAAyB,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;AAC3D,SAAA,CAAC;IACJ;AAEA,IAAA,IAAI,wBAAwB,GAAA;QAC1B,OAAO,IAAI,CAAC,yBAAyB;IACvC;;;;;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;;AAIA,IAAA,IAAI,MAAM,GAAA;QACR,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE;IAC1C;IAEA,IAAI,MAAM,CAAC,KAAa,EAAA;AACtB,QAAA,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC;IACpC;;AAIA,IAAA,IAAI,MAAM,GAAA;AACR,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM;IAC1B;AAEA,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK;IACzB;;AAIA;;;;;;;;AAQG;AACH,IAAA,MAAM,kBAAkB,GAAA;QACtB,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE;QACzC,MAAM,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,OAAO,CAAC;IAC9C;;IAGA,eAAe,GAAA;AACb,QAAA,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE;IAC9B;;IAIA,iBAAiB,GAAA;QACf,IAAI,CAAC,uBAAuB,EAAE;IAChC;IAEA,oBAAoB,GAAA;AAClB,QAAA,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE;IACtB;AAEA,IAAA,wBAAwB,CAAC,IAAY,EAAA;QACnC,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,WAAW,EAAE;YACzC,IAAI,CAAC,uBAAuB,EAAE;QAChC;IACF;;IAIQ,uBAAuB,GAAA;QAC7B,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE;AAClD,QAAA,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,OAAO;QAC5B,IAAI,CAAC,yBAAyB,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;IAC9D;;;IAIQ,cAAc,GAAA;AACpB,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM;AAC1B,QAAA,IAAI,MAAM,KAAK,MAAM,EAAE;YACrB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE;QAC5C;AACA,QAAA,IAAI,MAAM,KAAK,EAAE,EAAE;AACjB,YAAA,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAA2B;AACzD,YAAA,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE;QACrE;AACA,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB;QACpC,IAAI,KAAK,EAAE;YACT,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE;QAChD;QACA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE;IAC5C;;IAGQ,UAAU,CAAC,KAA4B,EAAE,QAAgB,EAAA;AAC/D,QAAA,IAAI;AACF,YAAA,OAAO,KAAK,CAAC,aAAa,CAAC,QAAQ,CAAC;QACtC;AAAE,QAAA,MAAM;AACN,YAAA,OAAO,IAAI;QACb;IACF;;;SC7Lc,kBAAkB,GAAA;AAChC,IAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE;QACpD,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;IACpE;AACF;;ACHM,SAAU,oBAAoB,CAAC,UAA4B,EAAA;IAC/D,IAAI,UAAU,EAAE;QACd,SAAS,CAAC,UAAU,CAAC;IACvB;AACA,IAAA,kBAAkB,EAAE;AACtB;;;;"}
@@ -1,2 +1,2 @@
1
- const e={tagNames:{pointerLock:"wcs-pointer-lock"}};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 n of Object.keys(e))t[n]=r(e[n]);return t}let n=null;const s=e;function i(){return n||(n=t(r(e))),n}class o extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"active",event:"wcs-pointer-lock:change"}],commands:[{name:"requestPointerLock",async:!0},{name:"exitPointerLock"}]};_target;_active=!1;_error=null;_resolvedTarget=null;_subscribed=!1;_gen=0;_ready=Promise.resolve();constructor(e){super(),this._target=e??this}get ready(){return this._ready}get active(){return this._active}get error(){return this._error}observe(e){return this._resolvedTarget=e,this._subscribed||(this._subscribed=!0,document.addEventListener(this._pointerLockChangeEventName(),this._onChange)),this._applyActive(),this._ready}dispose(){this._gen++,this._subscribed&&(this._subscribed=!1,document.removeEventListener(this._pointerLockChangeEventName(),this._onChange)),this._resolvedTarget=null}async requestPointerLock(e){const t=++this._gen;if(this._resolvedTarget=e,!e)return void this._setError({message:"Pointer Lock target could not be resolved."});const r=this._requestPointerLockFn(e);if(r)try{if(await r(),t!==this._gen)return;this._setError(null),this._applyActive()}catch(e){if(t!==this._gen)return;this._setError(e)}else this._setError({message:"Pointer Lock API is not supported."})}exitPointerLock(){try{if(null===this._pointerLockElement())return;const e=this._exitPointerLockFn();if(!e)return;e(),this._setError(null),this._applyActive()}catch(e){this._setError(e)}}_requestPointerLockFn(e){const t=Element.prototype,r=t.requestPointerLock;if("function"==typeof r)return r.bind(e);const n=t.webkitRequestPointerLock;return"function"==typeof n?n.bind(e):void 0}_exitPointerLockFn(){const e=document;return e.exitPointerLock?.bind(document)??e.webkitExitPointerLock?.bind(document)}_pointerLockElement(){const e=document;return e.pointerLockElement??e.webkitPointerLockElement??null}_pointerLockChangeEventName(){return"onpointerlockchange"in document?"pointerlockchange":"webkitpointerlockchange"}_onChange=()=>{this._applyActive()};_applyActive(){const e=null!==this._resolvedTarget&&this._pointerLockElement()===this._resolvedTarget;this._setActive(e)}_setActive(e){this._active!==e&&(this._active=e,this._target.dispatchEvent(new CustomEvent("wcs-pointer-lock:change",{detail:e,bubbles:!0})))}_setError(e){this._error=e}}class c extends HTMLElement{static hasConnectedCallbackPromise=!0;static observedAttributes=["target"];static wcBindable={...o.wcBindable,inputs:[{name:"target",attribute:"target"}],commands:o.wcBindable.commands};_core;_connectedCallbackPromise=Promise.resolve();constructor(){super(),this._core=new o(this)}get connectedCallbackPromise(){return this._connectedCallbackPromise}get target(){return this.getAttribute("target")??""}set target(e){this.setAttribute("target",e)}get active(){return this._core.active}get error(){return this._core.error}async requestPointerLock(){const{element:e}=this._resolveTarget();await this._core.requestPointerLock(e)}exitPointerLock(){this._core.exitPointerLock()}connectedCallback(){this._applyDisplayAndObserve()}disconnectedCallback(){this._core.dispose()}attributeChangedCallback(e){"target"===e&&this.isConnected&&this._applyDisplayAndObserve()}_applyDisplayAndObserve(){const{element:e,display:t}=this._resolveTarget();this.style.display=t,this._connectedCallbackPromise=this._core.observe(e)}_resolveTarget(){const e=this.target;if("self"===e)return{element:this,display:"block"};if(""!==e){const t=this.getRootNode();return{element:this._safeQuery(t,e),display:"none"}}const t=this.firstElementChild;return t?{element:t,display:"contents"}:{element:this,display:"block"}}_safeQuery(e,t){try{return e.querySelector(t)}catch{return null}}}function a(t){var r;t&&((r=t).tagNames&&Object.assign(e.tagNames,r.tagNames),n=null),customElements.get(s.tagNames.pointerLock)||customElements.define(s.tagNames.pointerLock,c)}export{o as PointerLockCore,c as WcsPointerLock,a as bootstrapPointerLock,i as getConfig};
1
+ const t={tagNames:{pointerLock:"wcs-pointer-lock"}};function e(t){if(null===t||"object"!=typeof t)return t;Object.freeze(t);for(const r of Object.keys(t))e(t[r]);return t}function r(t){if(null===t||"object"!=typeof t)return t;const e={};for(const n of Object.keys(t))e[n]=r(t[n]);return e}let n=null;const s=t;function i(){return n||(n=e(r(t))),n}class o extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"active",event:"wcs-pointer-lock:change"}],commands:[{name:"requestPointerLock",async:!0},{name:"exitPointerLock"}]};_target;_active=!1;_error=null;_resolvedTarget=null;_subscribed=!1;_gen=0;_ready=Promise.resolve();constructor(t){super(),this._target=t??this}get ready(){return this._ready}get active(){return this._active}get error(){return this._error}observe(t){return this._resolvedTarget=t,this._subscribed||(this._subscribed=!0,document.addEventListener(this._pointerLockChangeEventName(),this._onChange)),this._applyActive(),this._ready}dispose(){this._gen++,this._subscribed&&(this._subscribed=!1,document.removeEventListener(this._pointerLockChangeEventName(),this._onChange)),this._resolvedTarget=null}async requestPointerLock(t){const e=++this._gen;if(this._resolvedTarget=t,!t)return void this._setError({message:"Pointer Lock target could not be resolved."});const r=this._requestPointerLockFn(t);if(r)try{if(await r(),e!==this._gen)return;this._setError(null),this._applyActive()}catch(t){if(e!==this._gen)return;this._setError(t)}else this._setError({message:"Pointer Lock API is not supported."})}exitPointerLock(){try{if(null===this._pointerLockElement())return;const t=this._exitPointerLockFn();if(!t)return;t(),this._setError(null),this._applyActive()}catch(t){this._setError(t)}}_requestPointerLockFn(t){const e=Element.prototype,r=e.requestPointerLock;if("function"==typeof r)return r.bind(t);const n=e.webkitRequestPointerLock;return"function"==typeof n?n.bind(t):void 0}_exitPointerLockFn(){const t=document;return t.exitPointerLock?.bind(document)??t.webkitExitPointerLock?.bind(document)}_pointerLockElement(){const t=document;return t.pointerLockElement??t.webkitPointerLockElement??null}_pointerLockChangeEventName(){return"onpointerlockchange"in document?"pointerlockchange":"webkitpointerlockchange"}_onChange=()=>{this._applyActive()};_applyActive(){const t=null!==this._resolvedTarget&&this._pointerLockElement()===this._resolvedTarget;this._setActive(t)}_setActive(t){this._active!==t&&(this._active=t,this._target.dispatchEvent(new CustomEvent("wcs-pointer-lock:change",{detail:t,bubbles:!0})))}_setError(t){this._error=t}}class c extends HTMLElement{static hasConnectedCallbackPromise=!0;static observedAttributes=["target"];static wcBindable={...o.wcBindable,inputs:[{name:"target",attribute:"target"}],commands:o.wcBindable.commands};_core;_connectedCallbackPromise=Promise.resolve();_internals=null;constructor(){super(),this._core=new o(this),this._internals=this._initInternals(),this._wireStates({"wcs-pointer-lock:change":t=>({active:!0===t})})}get connectedCallbackPromise(){return this._connectedCallbackPromise}get debugStates(){return this._internals?[...this._internals.states]:[]}_initInternals(){try{if("function"!=typeof this.attachInternals)return null;const t=this.attachInternals();return t.states.add("wcs-probe"),t.states.delete("wcs-probe"),t}catch{return null}}_wireStates(t){if(null===this._internals)return;const e=this._internals.states;for(const[r,n]of Object.entries(t))this.addEventListener(r,t=>{const r=this.hasAttribute("debug-states");for(const[s,i]of Object.entries(n(t.detail))){try{i?e.add(s):e.delete(s)}catch{}r&&this.toggleAttribute(`data-wcs-state-${s}`,i)}})}get target(){return this.getAttribute("target")??""}set target(t){this.setAttribute("target",t)}get active(){return this._core.active}get error(){return this._core.error}async requestPointerLock(){const{element:t}=this._resolveTarget();await this._core.requestPointerLock(t)}exitPointerLock(){this._core.exitPointerLock()}connectedCallback(){this._applyDisplayAndObserve()}disconnectedCallback(){this._core.dispose()}attributeChangedCallback(t){"target"===t&&this.isConnected&&this._applyDisplayAndObserve()}_applyDisplayAndObserve(){const{element:t,display:e}=this._resolveTarget();this.style.display=e,this._connectedCallbackPromise=this._core.observe(t)}_resolveTarget(){const t=this.target;if("self"===t)return{element:this,display:"block"};if(""!==t){const e=this.getRootNode();return{element:this._safeQuery(e,t),display:"none"}}const e=this.firstElementChild;return e?{element:e,display:"contents"}:{element:this,display:"block"}}_safeQuery(t,e){try{return t.querySelector(e)}catch{return null}}}function a(e){var r;e&&((r=e).tagNames&&Object.assign(t.tagNames,r.tagNames),n=null),customElements.get(s.tagNames.pointerLock)||customElements.define(s.tagNames.pointerLock,c)}export{o as PointerLockCore,c as WcsPointerLock,a as bootstrapPointerLock,i 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/PointerLockCore.ts","../src/components/PointerLock.ts","../src/bootstrapPointerLock.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n tagNames: {\n pointerLock: string;\n };\n}\n\nconst _config: IInternalConfig = {\n tagNames: {\n pointerLock: \"wcs-pointer-lock\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { IWcBindable } from \"../types.js\";\n\n/**\n * Headless Pointer Lock primitive. A thin, framework-agnostic wrapper around\n * the Pointer Lock API (`Element.requestPointerLock()` /\n * `document.exitPointerLock()` / `document.pointerLockElement` / the\n * `document`-scoped `pointerlockchange` event) exposed through the\n * wc-bindable protocol.\n *\n * This Core follows the same basic pattern as `FullscreenCore`\n * (docs/fullscreen-tag-design.md, referenced by docs/pointer-lock-tag-design.md\n * §1): target resolution happens in the Shell, `pointerlockchange` is\n * subscribed on `document` (not on the target element) and each instance\n * self-filters by comparing `document.pointerLockElement` against its own\n * resolved target, API resolution is call-time (never cached) and probes the\n * standard name before the legacy (`webkit`-prefixed) name, and a single\n * Core-level `_gen` generation guard protects the asynchronous\n * `requestPointerLock()` call from stale resolution after dispose().\n *\n * Key difference from Fullscreen (docs/pointer-lock-tag-design.md §2):\n * `exitPointerLock()` is a *synchronous* platform API (it returns `void`, not\n * a `Promise`), so the Core's `exitPointerLock()` command is synchronous too\n * and carries no `_gen` guard of its own — it is wrapped in `try/catch` only\n * as a defensive measure (never-throw), not because it can go stale.\n *\n * Scope note (docs/pointer-lock-tag-design.md §3): `movementX`/`movementY`\n * are intentionally NOT exposed by this Core (v1 scope). They are\n * high-frequency `mousemove` data unsuited to the same-value-guarded\n * declarative `properties` surface; see the design doc for the rationale and\n * the planned `debounce`/`throttle`-based opt-in for a future version.\n */\nexport class PointerLockCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n // `active`'s CustomEvent detail is the bare boolean value itself — no\n // getter needed (docs/pointer-lock-tag-design.md §2). This differs from\n // FullscreenCore's `{ active }`-shaped detail + getter.\n properties: [\n { name: \"active\", event: \"wcs-pointer-lock:change\" },\n ],\n commands: [\n { name: \"requestPointerLock\", async: true },\n // Synchronous platform API (document.exitPointerLock() returns void) —\n // no `async` flag (docs/pointer-lock-tag-design.md §2).\n { name: \"exitPointerLock\" },\n ],\n };\n\n private _target: EventTarget;\n private _active = false;\n private _error: any = null;\n\n // The element this instance last resolved requestPointerLock()/observe()\n // against, kept so the document-scoped `pointerlockchange` handler can\n // self-filter under multiple concurrent instances (docs/fullscreen-tag-design.md\n // §2.1, inherited verbatim by pointer-lock per docs/pointer-lock-tag-design.md §1).\n private _resolvedTarget: Element | null = null;\n\n // True once observe() has attached the live `document` listener. Guards\n // observe() so a redundant call does not re-subscribe; dispose() resets it\n // so a later observe() resumes cleanly.\n private _subscribed = false;\n\n // Core-level generation guard (§3.4 of the guidelines / §6 of\n // fullscreen-tag-design.md): only requestPointerLock() is asynchronous and\n // needs it. exitPointerLock() is synchronous and has no stale-resolution\n // race to guard against.\n private _gen = 0;\n\n // SSR (§3.8): no asynchronous probe to await — observe() completes\n // synchronously, so readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get ready(): Promise<void> {\n return this._ready;\n }\n\n get active(): boolean {\n return this._active;\n }\n\n get error(): any {\n return this._error;\n }\n\n // Lifecycle (§3.5). Idempotent: a second observe() while already subscribed\n // updates the tracked resolved target without re-subscribing to `document`.\n observe(target: Element | null): Promise<void> {\n this._resolvedTarget = target;\n if (!this._subscribed) {\n this._subscribed = true;\n document.addEventListener(this._pointerLockChangeEventName(), this._onChange);\n }\n this._applyActive();\n return this._ready;\n }\n\n dispose(): void {\n this._gen++; // invalidate any in-flight requestPointerLock() resolution\n if (this._subscribed) {\n this._subscribed = false;\n document.removeEventListener(this._pointerLockChangeEventName(), this._onChange);\n }\n this._resolvedTarget = null;\n }\n\n /**\n * Request pointer lock on `element`. Never-throw: a missing API or a\n * rejected promise (e.g. called outside a user-gesture context —\n * `NotAllowedError`, docs/fullscreen-tag-design.md §3) is captured into\n * `error` rather than propagated. `element` may be `null` when the Shell's\n * `target` selector did not resolve (docs/pointer-lock-tag-design.md §1\n * defers error representation to FullscreenCore verbatim — this null-target\n * case mirrors `FullscreenCore.requestFullscreen(null)`,\n * docs/fullscreen-tag-design.md §6): distinct from \"API is not supported\"\n * below, so a typo'd selector doesn't masquerade as an unsupported platform.\n */\n async requestPointerLock(element: Element | null): Promise<void> {\n const gen = ++this._gen;\n this._resolvedTarget = element;\n if (!element) {\n this._setError({ message: \"Pointer Lock target could not be resolved.\" });\n return;\n }\n const fn = this._requestPointerLockFn(element);\n if (!fn) {\n // Resolved synchronously in the same tick as the call — dispose()\n // cannot have run yet, so no staleness check is needed here (matches\n // the reference `requestFullscreen()` implementation,\n // docs/fullscreen-tag-design.md §6).\n this._setError({ message: \"Pointer Lock API is not supported.\" });\n return;\n }\n try {\n // fn is already bound to `element` by _requestPointerLockFn().\n await fn();\n if (gen !== this._gen) return; // stale\n this._setError(null);\n this._applyActive();\n } catch (e: any) {\n if (gen !== this._gen) return; // stale\n this._setError(e);\n }\n }\n\n /**\n * Exit pointer lock. Synchronous platform API (docs/pointer-lock-tag-design.md\n * §2) — returns `void`, not a `Promise`. Silent no-op when nothing is\n * currently locked or the API is unsupported (mirrors\n * `FullscreenCore.exitFullscreen()`'s no-op contract,\n * docs/fullscreen-tag-design.md §7). Wrapped in try/catch defensively: even\n * though the platform API is synchronous and documented as not throwing in\n * this case, a synchronous throw from a non-conformant/fake implementation\n * must never escape (never-throw).\n */\n exitPointerLock(): void {\n try {\n if (this._pointerLockElement() === null) return; // already unlocked: silent no-op\n const fn = this._exitPointerLockFn();\n if (!fn) return; // unsupported: silent no-op (semantically already \"not locked\")\n fn();\n this._setError(null);\n this._applyActive();\n } catch (e: any) {\n this._setError(e);\n }\n }\n\n // --- API resolution (call-time, never cached — §3.7) ---\n\n // Resolved from `Element.prototype` rather than `el.requestPointerLock`\n // directly: when `target=\"self\"`, `el` is the `<wcs-pointer-lock>` Shell\n // itself, whose own class declares an instance method also named\n // `requestPointerLock()` (the wcBindable command). Reading the property off\n // the instance would pick up that Shell method instead of the native\n // platform API and recurse infinitely (Shell.requestPointerLock() ->\n // Core.requestPointerLock() -> resolves \"el.requestPointerLock\" -> the same\n // Shell method again). Going through `Element.prototype` sidesteps the name\n // collision — note this does NOT pick up an override on a subclass's own\n // prototype (e.g. `WcsPointerLock.prototype`); it deliberately jumps\n // straight to the platform-defined layer. Both the standard and legacy name\n // are resolved the same way, for symmetry — matching FullscreenCore's\n // `_elementFullscreenFn` (docs/fullscreen-tag-design.md §4) ONLY in that one\n // respect. Unlike that Core, this one does not check `el`'s own properties\n // first: there is no test-stub/per-element monkey-patch path to accommodate\n // here (mocks.ts installs the fakes directly on `Element.prototype`), so it\n // goes straight there for both names.\n private _requestPointerLockFn(el: Element): (() => Promise<void>) | undefined {\n const proto = Element.prototype as any;\n const standard = proto.requestPointerLock;\n if (typeof standard === \"function\") return standard.bind(el);\n const legacy = proto.webkitRequestPointerLock;\n return typeof legacy === \"function\" ? legacy.bind(el) : undefined;\n }\n\n private _exitPointerLockFn(): (() => void) | undefined {\n const d = document as any;\n return d.exitPointerLock?.bind(document) ?? d.webkitExitPointerLock?.bind(document);\n }\n\n private _pointerLockElement(): Element | null {\n const d = document as any;\n return d.pointerLockElement ?? d.webkitPointerLockElement ?? null;\n }\n\n // NOTE (test-environment caveat, not a production concern): happy-dom\n // always implements `document.onpointerlockchange` (as `null`) regardless\n // of which fake API surface a test installs, so `\"onpointerlockchange\" in\n // document` can never observably be `false` under this test runner and the\n // `webkitpointerlockchange` branch below cannot be driven through\n // `observe()` in a unit test. The branch is still correct and required for\n // real legacy WebKit builds that lack `onpointerlockchange` entirely — kept\n // as documented, deliberate, untestable-in-this-harness code per\n // docs/pointer-lock-tag-design.md.\n /* v8 ignore next 3 */\n private _pointerLockChangeEventName(): string {\n return \"onpointerlockchange\" in document ? \"pointerlockchange\" : \"webkitpointerlockchange\";\n }\n\n private _onChange = (): void => {\n this._applyActive();\n };\n\n // Self-filter (docs/fullscreen-tag-design.md §2.1): compares against this\n // instance's own resolved target, not merely \"is *something* locked\" — so\n // multiple concurrent instances each report the correct `active` value.\n private _applyActive(): void {\n const next = this._resolvedTarget !== null && this._pointerLockElement() === this._resolvedTarget;\n this._setActive(next);\n }\n\n // Same-value guard (MUST, §3.3 of the guidelines). detail itself is the\n // bare boolean value (no getter needed) per docs/pointer-lock-tag-design.md\n // §2 — unlike FullscreenCore's `{ active }`-shaped detail + getter.\n private _setActive(v: boolean): void {\n if (this._active === v) return;\n this._active = v;\n this._target.dispatchEvent(new CustomEvent(\"wcs-pointer-lock:change\", {\n detail: v,\n bubbles: true,\n }));\n }\n\n private _setError(e: any): void {\n this._error = e;\n }\n}\n","import { IWcBindable } from \"../types.js\";\nimport { PointerLockCore } from \"../core/PointerLockCore.js\";\n\n/**\n * `<wcs-pointer-lock target=\"...\">` — declarative Pointer Lock API control.\n *\n * Like `<wcs-fullscreen>` (docs/fullscreen-tag-design.md §0), this Shell does\n * not lock itself — it operates on a *referenced* element via the `target`\n * attribute, using the same 3-mode resolution rule as `intersection`\n * (`_resolveTarget()`/`_safeQuery()`, copied verbatim per\n * docs/pointer-lock-tag-design.md §1 / docs/fullscreen-tag-design.md §1):\n *\n * | `target` | operates on | display |\n * |-----------------|-------------------------|-------------|\n * | omitted | first element child | `contents` |\n * | `\"#selector\"` | the matched element | `none` |\n * | `\"self\"` | the element itself | `block` |\n *\n * `requestPointerLock()` requires a user-gesture context (docs/fullscreen-tag-design.md\n * §3) — the primary activation path is the command-token protocol\n * (`command.requestPointerLock: $command.<token>` on `<wcs-pointer-lock>`,\n * emitted by a button's `onclick: $command.<token>`), not an\n * autoTrigger attribute (none is provided in v1,\n * docs/pointer-lock-tag-design.md §4).\n *\n * `movementX`/`movementY` are intentionally out of scope for v1\n * (docs/pointer-lock-tag-design.md §3) — do not add them without revisiting\n * the design doc.\n */\nexport class WcsPointerLock extends HTMLElement {\n // SSR (§4.4): the Core subscribes synchronously on connect, but the Shell\n // still exposes connectedCallbackPromise so the state binder can await it\n // uniformly across all IO nodes before snapshotting.\n static hasConnectedCallbackPromise = true;\n\n static observedAttributes = [\"target\"];\n\n static wcBindable: IWcBindable = {\n ...PointerLockCore.wcBindable,\n inputs: [{ name: \"target\", attribute: \"target\" }],\n // Core の commands をそのまま継承(単一情報源)。network/intersection と同型。\n commands: PointerLockCore.wcBindable.commands,\n };\n\n private _core: PointerLockCore;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n\n constructor() {\n super();\n this._core = new PointerLockCore(this);\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Attribute accessors ---\n\n get target(): string {\n return this.getAttribute(\"target\") ?? \"\";\n }\n\n set target(value: string) {\n this.setAttribute(\"target\", value);\n }\n\n // --- Core delegated getters ---\n\n get active(): boolean {\n return this._core.active;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n // --- Commands ---\n\n /**\n * Resolve `target` and request pointer lock on it. Requires a user-gesture\n * context. never-throw: an unresolvable target or an unsupported/rejected\n * API call are both surfaced via `error`, never thrown (mirrors\n * `<wcs-fullscreen>`'s `requestFullscreen()`, docs/fullscreen-tag-design.md\n * §3/§6 — the Shell passes the (possibly `null`) resolved element straight\n * through and lets the Core set `error`, rather than silently no-op'ing\n * here).\n */\n async requestPointerLock(): Promise<void> {\n const { element } = this._resolveTarget();\n await this._core.requestPointerLock(element);\n }\n\n /** Exit pointer lock. Synchronous command — silent no-op if nothing is locked. */\n exitPointerLock(): void {\n this._core.exitPointerLock();\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this._applyDisplayAndObserve();\n }\n\n disconnectedCallback(): void {\n this._core.dispose();\n }\n\n attributeChangedCallback(name: string): void {\n if (name === \"target\" && this.isConnected) {\n this._applyDisplayAndObserve();\n }\n }\n\n // --- Internal ---\n\n private _applyDisplayAndObserve(): void {\n const { element, display } = this._resolveTarget();\n this.style.display = display;\n this._connectedCallbackPromise = this._core.observe(element);\n }\n\n // Copied verbatim from packages/intersection/src/components/Intersect.ts\n // (§1 of docs/pointer-lock-tag-design.md / docs/fullscreen-tag-design.md).\n private _resolveTarget(): { element: Element | null; display: string } {\n const target = this.target;\n if (target === \"self\") {\n return { element: this, display: \"block\" };\n }\n if (target !== \"\") {\n const scope = this.getRootNode() as Document | ShadowRoot;\n return { element: this._safeQuery(scope, target), display: \"none\" };\n }\n const child = this.firstElementChild;\n if (child) {\n return { element: child, display: \"contents\" };\n }\n return { element: this, display: \"block\" };\n }\n\n // Copied verbatim from packages/intersection/src/components/Intersect.ts.\n private _safeQuery(scope: Document | ShadowRoot, selector: string): Element | null {\n try {\n return scope.querySelector(selector);\n } catch {\n return null;\n }\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapPointerLock(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n","import { WcsPointerLock } from \"./components/PointerLock.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.pointerLock)) {\n customElements.define(config.tagNames.pointerLock, WcsPointerLock);\n }\n}\n"],"names":["_config","tagNames","pointerLock","deepFreeze","obj","Object","freeze","key","keys","deepClone","clone","frozenConfig","config","getConfig","PointerLockCore","EventTarget","static","protocol","version","properties","name","event","commands","async","_target","_active","_error","_resolvedTarget","_subscribed","_gen","_ready","Promise","resolve","constructor","target","super","this","ready","active","error","observe","document","addEventListener","_pointerLockChangeEventName","_onChange","_applyActive","dispose","removeEventListener","requestPointerLock","element","gen","_setError","message","fn","_requestPointerLockFn","e","exitPointerLock","_pointerLockElement","_exitPointerLockFn","el","proto","Element","prototype","standard","bind","legacy","webkitRequestPointerLock","undefined","d","webkitExitPointerLock","pointerLockElement","webkitPointerLockElement","next","_setActive","v","dispatchEvent","CustomEvent","detail","bubbles","WcsPointerLock","HTMLElement","wcBindable","inputs","attribute","_core","_connectedCallbackPromise","connectedCallbackPromise","getAttribute","value","setAttribute","_resolveTarget","connectedCallback","_applyDisplayAndObserve","disconnectedCallback","attributeChangedCallback","isConnected","display","style","scope","getRootNode","_safeQuery","child","firstElementChild","selector","querySelector","bootstrapPointerLock","userConfig","partialConfig","assign","customElements","get","define"],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.min.js","sources":["../src/config.ts","../src/core/PointerLockCore.ts","../src/components/PointerLock.ts","../src/bootstrapPointerLock.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n tagNames: {\n pointerLock: string;\n };\n}\n\nconst _config: IInternalConfig = {\n tagNames: {\n pointerLock: \"wcs-pointer-lock\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { IWcBindable } from \"../types.js\";\n\n/**\n * Headless Pointer Lock primitive. A thin, framework-agnostic wrapper around\n * the Pointer Lock API (`Element.requestPointerLock()` /\n * `document.exitPointerLock()` / `document.pointerLockElement` / the\n * `document`-scoped `pointerlockchange` event) exposed through the\n * wc-bindable protocol.\n *\n * This Core follows the same basic pattern as `FullscreenCore`\n * (docs/fullscreen-tag-design.md, referenced by docs/pointer-lock-tag-design.md\n * §1): target resolution happens in the Shell, `pointerlockchange` is\n * subscribed on `document` (not on the target element) and each instance\n * self-filters by comparing `document.pointerLockElement` against its own\n * resolved target, API resolution is call-time (never cached) and probes the\n * standard name before the legacy (`webkit`-prefixed) name, and a single\n * Core-level `_gen` generation guard protects the asynchronous\n * `requestPointerLock()` call from stale resolution after dispose().\n *\n * Key difference from Fullscreen (docs/pointer-lock-tag-design.md §2):\n * `exitPointerLock()` is a *synchronous* platform API (it returns `void`, not\n * a `Promise`), so the Core's `exitPointerLock()` command is synchronous too\n * and carries no `_gen` guard of its own — it is wrapped in `try/catch` only\n * as a defensive measure (never-throw), not because it can go stale.\n *\n * Scope note (docs/pointer-lock-tag-design.md §3): `movementX`/`movementY`\n * are intentionally NOT exposed by this Core (v1 scope). They are\n * high-frequency `mousemove` data unsuited to the same-value-guarded\n * declarative `properties` surface; see the design doc for the rationale and\n * the planned `debounce`/`throttle`-based opt-in for a future version.\n */\nexport class PointerLockCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n // `active`'s CustomEvent detail is the bare boolean value itself — no\n // getter needed (docs/pointer-lock-tag-design.md §2). This differs from\n // FullscreenCore's `{ active }`-shaped detail + getter.\n properties: [\n { name: \"active\", event: \"wcs-pointer-lock:change\" },\n ],\n commands: [\n { name: \"requestPointerLock\", async: true },\n // Synchronous platform API (document.exitPointerLock() returns void) —\n // no `async` flag (docs/pointer-lock-tag-design.md §2).\n { name: \"exitPointerLock\" },\n ],\n };\n\n private _target: EventTarget;\n private _active = false;\n private _error: any = null;\n\n // The element this instance last resolved requestPointerLock()/observe()\n // against, kept so the document-scoped `pointerlockchange` handler can\n // self-filter under multiple concurrent instances (docs/fullscreen-tag-design.md\n // §2.1, inherited verbatim by pointer-lock per docs/pointer-lock-tag-design.md §1).\n private _resolvedTarget: Element | null = null;\n\n // True once observe() has attached the live `document` listener. Guards\n // observe() so a redundant call does not re-subscribe; dispose() resets it\n // so a later observe() resumes cleanly.\n private _subscribed = false;\n\n // Core-level generation guard (§3.4 of the guidelines / §6 of\n // fullscreen-tag-design.md): only requestPointerLock() is asynchronous and\n // needs it. exitPointerLock() is synchronous and has no stale-resolution\n // race to guard against.\n private _gen = 0;\n\n // SSR (§3.8): no asynchronous probe to await — observe() completes\n // synchronously, so readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get ready(): Promise<void> {\n return this._ready;\n }\n\n get active(): boolean {\n return this._active;\n }\n\n get error(): any {\n return this._error;\n }\n\n // Lifecycle (§3.5). Idempotent: a second observe() while already subscribed\n // updates the tracked resolved target without re-subscribing to `document`.\n observe(target: Element | null): Promise<void> {\n this._resolvedTarget = target;\n if (!this._subscribed) {\n this._subscribed = true;\n document.addEventListener(this._pointerLockChangeEventName(), this._onChange);\n }\n this._applyActive();\n return this._ready;\n }\n\n dispose(): void {\n this._gen++; // invalidate any in-flight requestPointerLock() resolution\n if (this._subscribed) {\n this._subscribed = false;\n document.removeEventListener(this._pointerLockChangeEventName(), this._onChange);\n }\n this._resolvedTarget = null;\n }\n\n /**\n * Request pointer lock on `element`. Never-throw: a missing API or a\n * rejected promise (e.g. called outside a user-gesture context —\n * `NotAllowedError`, docs/fullscreen-tag-design.md §3) is captured into\n * `error` rather than propagated. `element` may be `null` when the Shell's\n * `target` selector did not resolve (docs/pointer-lock-tag-design.md §1\n * defers error representation to FullscreenCore verbatim — this null-target\n * case mirrors `FullscreenCore.requestFullscreen(null)`,\n * docs/fullscreen-tag-design.md §6): distinct from \"API is not supported\"\n * below, so a typo'd selector doesn't masquerade as an unsupported platform.\n */\n async requestPointerLock(element: Element | null): Promise<void> {\n const gen = ++this._gen;\n this._resolvedTarget = element;\n if (!element) {\n this._setError({ message: \"Pointer Lock target could not be resolved.\" });\n return;\n }\n const fn = this._requestPointerLockFn(element);\n if (!fn) {\n // Resolved synchronously in the same tick as the call — dispose()\n // cannot have run yet, so no staleness check is needed here (matches\n // the reference `requestFullscreen()` implementation,\n // docs/fullscreen-tag-design.md §6).\n this._setError({ message: \"Pointer Lock API is not supported.\" });\n return;\n }\n try {\n // fn is already bound to `element` by _requestPointerLockFn().\n await fn();\n if (gen !== this._gen) return; // stale\n this._setError(null);\n this._applyActive();\n } catch (e: any) {\n if (gen !== this._gen) return; // stale\n this._setError(e);\n }\n }\n\n /**\n * Exit pointer lock. Synchronous platform API (docs/pointer-lock-tag-design.md\n * §2) — returns `void`, not a `Promise`. Silent no-op when nothing is\n * currently locked or the API is unsupported (mirrors\n * `FullscreenCore.exitFullscreen()`'s no-op contract,\n * docs/fullscreen-tag-design.md §7). Wrapped in try/catch defensively: even\n * though the platform API is synchronous and documented as not throwing in\n * this case, a synchronous throw from a non-conformant/fake implementation\n * must never escape (never-throw).\n */\n exitPointerLock(): void {\n try {\n if (this._pointerLockElement() === null) return; // already unlocked: silent no-op\n const fn = this._exitPointerLockFn();\n if (!fn) return; // unsupported: silent no-op (semantically already \"not locked\")\n fn();\n this._setError(null);\n this._applyActive();\n } catch (e: any) {\n this._setError(e);\n }\n }\n\n // --- API resolution (call-time, never cached — §3.7) ---\n\n // Resolved from `Element.prototype` rather than `el.requestPointerLock`\n // directly: when `target=\"self\"`, `el` is the `<wcs-pointer-lock>` Shell\n // itself, whose own class declares an instance method also named\n // `requestPointerLock()` (the wcBindable command). Reading the property off\n // the instance would pick up that Shell method instead of the native\n // platform API and recurse infinitely (Shell.requestPointerLock() ->\n // Core.requestPointerLock() -> resolves \"el.requestPointerLock\" -> the same\n // Shell method again). Going through `Element.prototype` sidesteps the name\n // collision — note this does NOT pick up an override on a subclass's own\n // prototype (e.g. `WcsPointerLock.prototype`); it deliberately jumps\n // straight to the platform-defined layer. Both the standard and legacy name\n // are resolved the same way, for symmetry — matching FullscreenCore's\n // `_elementFullscreenFn` (docs/fullscreen-tag-design.md §4) ONLY in that one\n // respect. Unlike that Core, this one does not check `el`'s own properties\n // first: there is no test-stub/per-element monkey-patch path to accommodate\n // here (mocks.ts installs the fakes directly on `Element.prototype`), so it\n // goes straight there for both names.\n private _requestPointerLockFn(el: Element): (() => Promise<void>) | undefined {\n const proto = Element.prototype as any;\n const standard = proto.requestPointerLock;\n if (typeof standard === \"function\") return standard.bind(el);\n const legacy = proto.webkitRequestPointerLock;\n return typeof legacy === \"function\" ? legacy.bind(el) : undefined;\n }\n\n private _exitPointerLockFn(): (() => void) | undefined {\n const d = document as any;\n return d.exitPointerLock?.bind(document) ?? d.webkitExitPointerLock?.bind(document);\n }\n\n private _pointerLockElement(): Element | null {\n const d = document as any;\n return d.pointerLockElement ?? d.webkitPointerLockElement ?? null;\n }\n\n // NOTE (test-environment caveat, not a production concern): happy-dom\n // always implements `document.onpointerlockchange` (as `null`) regardless\n // of which fake API surface a test installs, so `\"onpointerlockchange\" in\n // document` can never observably be `false` under this test runner and the\n // `webkitpointerlockchange` branch below cannot be driven through\n // `observe()` in a unit test. The branch is still correct and required for\n // real legacy WebKit builds that lack `onpointerlockchange` entirely — kept\n // as documented, deliberate, untestable-in-this-harness code per\n // docs/pointer-lock-tag-design.md.\n /* v8 ignore next 3 */\n private _pointerLockChangeEventName(): string {\n return \"onpointerlockchange\" in document ? \"pointerlockchange\" : \"webkitpointerlockchange\";\n }\n\n private _onChange = (): void => {\n this._applyActive();\n };\n\n // Self-filter (docs/fullscreen-tag-design.md §2.1): compares against this\n // instance's own resolved target, not merely \"is *something* locked\" — so\n // multiple concurrent instances each report the correct `active` value.\n private _applyActive(): void {\n const next = this._resolvedTarget !== null && this._pointerLockElement() === this._resolvedTarget;\n this._setActive(next);\n }\n\n // Same-value guard (MUST, §3.3 of the guidelines). detail itself is the\n // bare boolean value (no getter needed) per docs/pointer-lock-tag-design.md\n // §2 — unlike FullscreenCore's `{ active }`-shaped detail + getter.\n private _setActive(v: boolean): void {\n if (this._active === v) return;\n this._active = v;\n this._target.dispatchEvent(new CustomEvent(\"wcs-pointer-lock:change\", {\n detail: v,\n bubbles: true,\n }));\n }\n\n private _setError(e: any): void {\n this._error = e;\n }\n}\n","import { IWcBindable } from \"../types.js\";\nimport { PointerLockCore } from \"../core/PointerLockCore.js\";\n\n/**\n * `<wcs-pointer-lock target=\"...\">` — declarative Pointer Lock API control.\n *\n * Like `<wcs-fullscreen>` (docs/fullscreen-tag-design.md §0), this Shell does\n * not lock itself — it operates on a *referenced* element via the `target`\n * attribute, using the same 3-mode resolution rule as `intersection`\n * (`_resolveTarget()`/`_safeQuery()`, copied verbatim per\n * docs/pointer-lock-tag-design.md §1 / docs/fullscreen-tag-design.md §1):\n *\n * | `target` | operates on | display |\n * |-----------------|-------------------------|-------------|\n * | omitted | first element child | `contents` |\n * | `\"#selector\"` | the matched element | `none` |\n * | `\"self\"` | the element itself | `block` |\n *\n * `requestPointerLock()` requires a user-gesture context (docs/fullscreen-tag-design.md\n * §3) — the primary activation path is the command-token protocol\n * (`command.requestPointerLock: $command.<token>` on `<wcs-pointer-lock>`,\n * emitted by a button's `onclick: $command.<token>`), not an\n * autoTrigger attribute (none is provided in v1,\n * docs/pointer-lock-tag-design.md §4).\n *\n * `movementX`/`movementY` are intentionally out of scope for v1\n * (docs/pointer-lock-tag-design.md §3) — do not add them without revisiting\n * the design doc.\n */\nexport class WcsPointerLock extends HTMLElement {\n // SSR (§4.4): the Core subscribes synchronously on connect, but the Shell\n // still exposes connectedCallbackPromise so the state binder can await it\n // uniformly across all IO nodes before snapshotting.\n static hasConnectedCallbackPromise = true;\n\n static observedAttributes = [\"target\"];\n\n static wcBindable: IWcBindable = {\n ...PointerLockCore.wcBindable,\n inputs: [{ name: \"target\", attribute: \"target\" }],\n // Core の commands をそのまま継承(単一情報源)。network/intersection と同型。\n commands: PointerLockCore.wcBindable.commands,\n };\n\n private _core: PointerLockCore;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new PointerLockCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n \"wcs-pointer-lock:change\": (d) => ({ active: d === true }),\n });\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // CSS state reflection (:state()) — debug-only snapshot getter. NOT part of\n // wc-bindable (not a bind target); see README \"CSS styling with :state()\".\n // MUST NOT return the live CustomStateSet (that would let callers write\n // states from outside, defeating the point of :state() being read-only).\n get debugStates(): string[] {\n return this._internals ? [...this._internals.states] : [];\n }\n\n private _initInternals(): ElementInternals | null {\n // never-throw (docs/custom-state-reflection-design.md §3.6): attachInternals\n // is absent in happy-dom / older environments, and pre-125 Chromium rejects\n // non-dashed state names from states.add() (probed and discarded here).\n // Either case silently disables reflection — the component still works,\n // it just doesn't expose :state() selectors.\n try {\n if (typeof this.attachInternals !== \"function\") return null;\n const internals = this.attachInternals();\n internals.states.add(\"wcs-probe\");\n internals.states.delete(\"wcs-probe\");\n return internals;\n } catch {\n return null;\n }\n }\n\n private _wireStates(map: Record<string, (detail: any) => Record<string, boolean>>): void {\n if (this._internals === null) return;\n const states = this._internals.states;\n for (const [event, toStates] of Object.entries(map)) {\n this.addEventListener(event, (e) => {\n const debug = this.hasAttribute(\"debug-states\");\n for (const [name, on] of Object.entries(toStates((e as CustomEvent).detail))) {\n try {\n if (on) { states.add(name); } else { states.delete(name); }\n } catch { /* never-throw */ }\n if (debug) this.toggleAttribute(`data-wcs-state-${name}`, on);\n }\n });\n }\n }\n\n // --- Attribute accessors ---\n\n get target(): string {\n return this.getAttribute(\"target\") ?? \"\";\n }\n\n set target(value: string) {\n this.setAttribute(\"target\", value);\n }\n\n // --- Core delegated getters ---\n\n get active(): boolean {\n return this._core.active;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n // --- Commands ---\n\n /**\n * Resolve `target` and request pointer lock on it. Requires a user-gesture\n * context. never-throw: an unresolvable target or an unsupported/rejected\n * API call are both surfaced via `error`, never thrown (mirrors\n * `<wcs-fullscreen>`'s `requestFullscreen()`, docs/fullscreen-tag-design.md\n * §3/§6 — the Shell passes the (possibly `null`) resolved element straight\n * through and lets the Core set `error`, rather than silently no-op'ing\n * here).\n */\n async requestPointerLock(): Promise<void> {\n const { element } = this._resolveTarget();\n await this._core.requestPointerLock(element);\n }\n\n /** Exit pointer lock. Synchronous command — silent no-op if nothing is locked. */\n exitPointerLock(): void {\n this._core.exitPointerLock();\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this._applyDisplayAndObserve();\n }\n\n disconnectedCallback(): void {\n this._core.dispose();\n }\n\n attributeChangedCallback(name: string): void {\n if (name === \"target\" && this.isConnected) {\n this._applyDisplayAndObserve();\n }\n }\n\n // --- Internal ---\n\n private _applyDisplayAndObserve(): void {\n const { element, display } = this._resolveTarget();\n this.style.display = display;\n this._connectedCallbackPromise = this._core.observe(element);\n }\n\n // Copied verbatim from packages/intersection/src/components/Intersect.ts\n // (§1 of docs/pointer-lock-tag-design.md / docs/fullscreen-tag-design.md).\n private _resolveTarget(): { element: Element | null; display: string } {\n const target = this.target;\n if (target === \"self\") {\n return { element: this, display: \"block\" };\n }\n if (target !== \"\") {\n const scope = this.getRootNode() as Document | ShadowRoot;\n return { element: this._safeQuery(scope, target), display: \"none\" };\n }\n const child = this.firstElementChild;\n if (child) {\n return { element: child, display: \"contents\" };\n }\n return { element: this, display: \"block\" };\n }\n\n // Copied verbatim from packages/intersection/src/components/Intersect.ts.\n private _safeQuery(scope: Document | ShadowRoot, selector: string): Element | null {\n try {\n return scope.querySelector(selector);\n } catch {\n return null;\n }\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapPointerLock(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n","import { WcsPointerLock } from \"./components/PointerLock.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.pointerLock)) {\n customElements.define(config.tagNames.pointerLock, WcsPointerLock);\n }\n}\n"],"names":["_config","tagNames","pointerLock","deepFreeze","obj","Object","freeze","key","keys","deepClone","clone","frozenConfig","config","getConfig","PointerLockCore","EventTarget","static","protocol","version","properties","name","event","commands","async","_target","_active","_error","_resolvedTarget","_subscribed","_gen","_ready","Promise","resolve","constructor","target","super","this","ready","active","error","observe","document","addEventListener","_pointerLockChangeEventName","_onChange","_applyActive","dispose","removeEventListener","requestPointerLock","element","gen","_setError","message","fn","_requestPointerLockFn","e","exitPointerLock","_pointerLockElement","_exitPointerLockFn","el","proto","Element","prototype","standard","bind","legacy","webkitRequestPointerLock","undefined","d","webkitExitPointerLock","pointerLockElement","webkitPointerLockElement","next","_setActive","v","dispatchEvent","CustomEvent","detail","bubbles","WcsPointerLock","HTMLElement","wcBindable","inputs","attribute","_core","_connectedCallbackPromise","_internals","_initInternals","_wireStates","connectedCallbackPromise","debugStates","states","attachInternals","internals","add","delete","map","toStates","entries","debug","hasAttribute","on","toggleAttribute","getAttribute","value","setAttribute","_resolveTarget","connectedCallback","_applyDisplayAndObserve","disconnectedCallback","attributeChangedCallback","isConnected","display","style","scope","getRootNode","_safeQuery","child","firstElementChild","selector","querySelector","bootstrapPointerLock","userConfig","partialConfig","assign","customElements","get","define"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wcstack/pointer-lock",
3
- "version": "1.16.0",
3
+ "version": "1.17.0",
4
4
  "description": "Declarative Pointer Lock component for Web Components. Framework-agnostic Pointer Lock API control via wc-bindable-protocol.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.esm.js",