@wcstack/raf 1.22.6 → 1.24.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
@@ -161,6 +161,8 @@ core.start();
161
161
  core.dispose();
162
162
  ```
163
163
 
164
+ Core の構造サーフェスは wcstack I/O ノード横断の規範です([async-io-node-guidelines §3.9](../../docs/async-io-node-guidelines.md))。要素なしで signals に束縛するには [@wcstack/signals — Core を直接束縛する](../signals/README.ja.md#core-を直接束縛する要素なし) を参照。
165
+
164
166
  ## 設定
165
167
 
166
168
  ```javascript
package/README.md CHANGED
@@ -162,6 +162,8 @@ core.start();
162
162
  core.dispose();
163
163
  ```
164
164
 
165
+ The structural Core surface is normative across wcstack IO nodes ([async-io-node-guidelines §3.9](../../docs/async-io-node-guidelines.md)); to bind it into signals with no element at all, see [@wcstack/signals — Binding a Core directly](../signals/README.md#binding-a-core-directly-no-element).
166
+
165
167
  ## Configuration
166
168
 
167
169
  ```javascript
package/dist/index.d.ts CHANGED
@@ -1,7 +1,24 @@
1
+ /**
2
+ * Observation semantics of a `properties` entry.
3
+ *
4
+ * "state" — current value. A snapshot may cache it, and equality-based dedupe is safe.
5
+ * "event" — occurrence. Repeated identical payloads are distinct occurrences; never dedupe.
6
+ * "handle" — live / opaque resource with its own lifecycle (e.g. MediaStream). Not
7
+ * snapshot-safe and not necessarily serializable; consumers need an explicit
8
+ * ref / callback surface rather than a value slot.
9
+ */
10
+ type WcBindableSemantics = "state" | "event" | "handle";
1
11
  interface IWcBindableProperty {
2
12
  readonly name: string;
3
13
  readonly event: string;
4
14
  readonly getter?: (event: Event) => any;
15
+ /**
16
+ * Optional, additive, forward-compatible. An absent value means **unspecified**, NOT
17
+ * "state": a reader that finds no `semantics` MUST keep the behavior it had before this
18
+ * field existed (deliver the update as-is; do not start deduping, caching or serializing
19
+ * on assumption). Only an explicit value licenses a reader to change its handling.
20
+ */
21
+ readonly semantics?: WcBindableSemantics;
5
22
  }
6
23
  interface IWcBindableInput {
7
24
  readonly name: string;
@@ -13,7 +30,8 @@ interface IWcBindableCommand {
13
30
  }
14
31
  interface IWcBindable {
15
32
  readonly protocol: "wc-bindable";
16
- readonly version: 1;
33
+ /** Integer protocol version. All versions >= 1 are core-compatible. */
34
+ readonly version: number;
17
35
  readonly properties: readonly IWcBindableProperty[];
18
36
  readonly inputs?: readonly IWcBindableInput[];
19
37
  readonly commands?: readonly IWcBindableCommand[];
package/dist/index.esm.js CHANGED
@@ -89,11 +89,11 @@ class RafCore extends EventTarget {
89
89
  protocol: "wc-bindable",
90
90
  version: 1,
91
91
  properties: [
92
- { name: "tick", event: "wcs-raf:tick", getter: (e) => e.detail.count },
93
- { name: "elapsed", event: "wcs-raf:tick", getter: (e) => e.detail.elapsed },
94
- { name: "dt", event: "wcs-raf:tick", getter: (e) => e.detail.dt },
95
- { name: "running", event: "wcs-raf:running-changed" },
96
- { name: "suspended", event: "wcs-raf:suspended-changed" },
92
+ { name: "tick", event: "wcs-raf:tick", semantics: "state", getter: (e) => e.detail.count },
93
+ { name: "elapsed", event: "wcs-raf:tick", semantics: "state", getter: (e) => e.detail.elapsed },
94
+ { name: "dt", event: "wcs-raf:tick", semantics: "state", getter: (e) => e.detail.dt },
95
+ { name: "running", event: "wcs-raf:running-changed", semantics: "state" },
96
+ { name: "suspended", event: "wcs-raf:suspended-changed", semantics: "state" },
97
97
  ],
98
98
  commands: [
99
99
  { name: "start" },
@@ -472,13 +472,55 @@ function registerAutoTrigger() {
472
472
  document.addEventListener("click", handleClick);
473
473
  }
474
474
 
475
+ // ===========================================================================
476
+ // AUTO-GENERATED FILE - DO NOT EDIT.
477
+ // Generated from /protocol/upgrade-properties.ts by scripts/sync-protocol-types.mjs.
478
+ // Run `node scripts/sync-protocol-types.mjs` after editing the source.
479
+ // ===========================================================================
480
+ function hasAccessorOnPrototype(target, name) {
481
+ let proto = Object.getPrototypeOf(target);
482
+ while (proto !== null) {
483
+ const descriptor = Object.getOwnPropertyDescriptor(proto, name);
484
+ if (descriptor !== undefined) {
485
+ return typeof descriptor.get === "function" || typeof descriptor.set === "function";
486
+ }
487
+ proto = Object.getPrototypeOf(proto);
488
+ }
489
+ return false;
490
+ }
491
+ /**
492
+ * `connectedCallback` の先頭で呼ぶ。宣言済み input のうち upgrade 前の代入で
493
+ * accessor をシャドウしている own プロパティを、delete → 再代入で setter に通し直す。
494
+ *
495
+ * - 冪等: 再代入は accessor を通るので own プロパティは残らず、2 回目以降は no-op。
496
+ * - 宣言に `inputs` が無い要素、`wcBindable` を持たない要素では何もしない。
497
+ * - 値の意味は変えない。今まで捨てられていた代入が届くようになる一方向の変化。
498
+ */
499
+ function upgradeProperties(element) {
500
+ const declaration = element.constructor?.wcBindable;
501
+ const inputs = declaration?.inputs;
502
+ if (inputs === undefined)
503
+ return;
504
+ for (const input of inputs) {
505
+ const name = input.name;
506
+ if (!Object.prototype.hasOwnProperty.call(element, name))
507
+ continue;
508
+ if (!hasAccessorOnPrototype(element, name))
509
+ continue;
510
+ const record = element;
511
+ const value = record[name];
512
+ delete record[name];
513
+ record[name] = value;
514
+ }
515
+ }
516
+
475
517
  class Raf extends HTMLElement {
476
518
  static hasConnectedCallbackPromise = true;
477
519
  static wcBindable = {
478
520
  ...RafCore.wcBindable,
479
521
  properties: [
480
522
  ...RafCore.wcBindable.properties,
481
- { name: "trigger", event: "wcs-raf:trigger-changed" },
523
+ { name: "trigger", event: "wcs-raf:trigger-changed", semantics: "state" },
482
524
  ],
483
525
  // Shell-level settable surface. `attribute` is a purely descriptive hint
484
526
  // (per SPEC-extensions.md the binding core does not act on it) naming the
@@ -659,6 +701,8 @@ class Raf extends HTMLElement {
659
701
  }
660
702
  // --- Lifecycle ---
661
703
  connectedCallback() {
704
+ // upgrade 前に代入された input を取り込み直す(doc 13 §1.2 / Phase A1)
705
+ upgradeProperties(this);
662
706
  this.style.display = "none";
663
707
  if (config.autoTrigger) {
664
708
  registerAutoTrigger();
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/config.ts","../src/core/RafCore.ts","../src/autoTrigger.ts","../src/components/Raf.ts","../src/registerComponents.ts","../src/bootstrapRaf.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n raf: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-raftarget\",\n tagNames: {\n raf: \"wcs-raf\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\n// Internal-only live handle to the mutable config. NOT part of the public API\n// (deliberately absent from exports.ts) — it is exported solely so sibling\n// modules in this package can read current settings cheaply. External consumers\n// must use getConfig() (returns a deep-frozen snapshot) / setConfig(). Mutating\n// this object directly bypasses the frozenConfig cache and is unsupported.\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (typeof partialConfig.autoTrigger === \"boolean\") {\n _config.autoTrigger = partialConfig.autoTrigger;\n }\n if (typeof partialConfig.triggerAttribute === \"string\") {\n _config.triggerAttribute = partialConfig.triggerAttribute;\n }\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { IWcBindable } from \"../types.js\";\n\nexport interface RafStartOptions {\n repeat?: number;\n}\n\n/**\n * Injectable frame scheduler. The default resolves\n * `globalThis.requestAnimationFrame` / `cancelAnimationFrame` AT CALL TIME\n * (async-io-node-guidelines §3.7); tests inject a fake that pumps frames with\n * explicit timestamps (the `dt` contract is timestamp-derived, so tests must\n * control the clock, not just the callback order).\n *\n * Contract: `request()` MUST return a non-null handle. The core uses `null`\n * as its internal \"not armed\" sentinel, so a scheduler returning literal\n * `null` would silently corrupt the handle bookkeeping (re-entrancy guards\n * and cancel tracking). Native rAF returns a long, so this only concerns\n * custom scheduler injections — return a number, object, or any other\n * non-nullish token.\n */\nexport interface RafScheduler {\n request(callback: (timestamp: number) => void): unknown;\n cancel(handle: unknown): void;\n}\n\n/**\n * Headless requestAnimationFrame primitive — `TimerCore`'s sibling with the\n * time source swapped from `setInterval` (a period) to rAF (the browser's\n * rendering opportunity). Exposed through the wc-bindable protocol: it streams\n * `tick` (frame counter), `elapsed` (accumulated ACTIVE milliseconds), `dt`\n * (delta to the previous frame) and the `running` / `suspended` pair, and is\n * driven by the `start` / `stop` / `reset` / `pause` / `resume` commands.\n *\n * `tick` / `elapsed` / `dt` are all surfaced via the single `wcs-raf:tick`\n * event (read through getters, mirroring how FetchCore exposes value/status\n * from one `wcs-fetch:response` event).\n *\n * Contracts specific to this node (docs/raf-tag-design.md):\n *\n * - **dt describes continuous running only.** The first frame after `start()`,\n * `resume()`, or a visibility interruption reports `dt = 0` — a value that\n * spans an interruption never reaches observers. Like `suspended`, the\n * visibility boundary is only detected once observe() has subscribed to\n * `visibilitychange`; a headless setup that skips observe() will see the\n * raw spanning delta on the first frame after a hidden gap. There is\n * deliberately NO upper clamp: how to treat a slow frame is the consumer's\n * domain decision.\n * - **elapsed is Σdt (active time).** Because interruption-spanning deltas are\n * normalized to 0, summing dt yields exactly the time frames were actually\n * being delivered — no separate segment bookkeeping is needed, and hidden /\n * paused periods contribute nothing. Granularity is one frame: between\n * frames the getter returns the value as of the last tick.\n * - **running / suspended are a desired/actual pair** (the wakelock split): in\n * a hidden tab the browser delivers no frames at all, so `running` (the\n * started intent) stays true while `suspended` reports that delivery is\n * actually stopped. `suspended` is only meaningful after `observe()` has\n * subscribed to `visibilitychange`; without a document it stays false.\n * - **No `error` surface.** rAF has no persistent failure mode; on a platform\n * without it, `start()` is a silent no-op (never-throw, resize precedent).\n */\nexport class RafCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"tick\", event: \"wcs-raf:tick\", getter: (e: Event) => (e as CustomEvent).detail.count },\n { name: \"elapsed\", event: \"wcs-raf:tick\", getter: (e: Event) => (e as CustomEvent).detail.elapsed },\n { name: \"dt\", event: \"wcs-raf:tick\", getter: (e: Event) => (e as CustomEvent).detail.dt },\n { name: \"running\", event: \"wcs-raf:running-changed\" },\n { name: \"suspended\", event: \"wcs-raf:suspended-changed\" },\n ],\n commands: [\n { name: \"start\" },\n { name: \"stop\" },\n { name: \"reset\" },\n { name: \"pause\" },\n { name: \"resume\" },\n ],\n };\n\n private _target: EventTarget;\n private _injectedScheduler: RafScheduler | null;\n private _handle: unknown = null;\n\n // Lazily-created wrapper around the global rAF pair, cached so the hot\n // frame-reschedule path (_frame, once per delivered frame) does not\n // allocate a new object + closures every call. `request`/`cancel` still\n // dereference `globalThis.requestAnimationFrame` / `cancelAnimationFrame`\n // live on every invocation (they are not snapshotted here), so call-time\n // resolution (§3.7) is unchanged — only the wrapper object itself is\n // reused once the global functions are first found present.\n private _globalScheduler: RafScheduler | null = null;\n\n // Generation guard (§3.4): a monotonic arming counter. Bumped when a run is\n // armed (start()/resume()), when an armed handle is cancelled\n // (_clearHandle()) and on dispose(). _requestFrame() captures the value in\n // each request's closure and drops the frame if it no longer matches the\n // live field when it fires. cancel() is best-effort against a non-compliant\n // scheduler; the captured generation is the guarantee — a stale callback can\n // neither mutate state, dispatch on a torn-down element, nor corrupt a\n // newer run's `_handle` bookkeeping. A live-field comparison (the previous\n // `_runGen` scheme) could not survive a dispose() → start() round trip: the\n // new start() re-synced the pair and let the stale callback through,\n // permanently doubling the frame loop.\n private _gen = 0;\n // SSR (§3.8): there is no asynchronous probe, so readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n private _tick: number = 0;\n private _dt: number = 0;\n private _elapsed: number = 0;\n private _running: boolean = false;\n private _suspended: boolean = false;\n private _paused: boolean = false;\n\n // Timestamp of the previous frame within the current continuous run.\n // `null` means \"the next frame starts a run segment\": its dt is reported as\n // 0 (the G3 normalization). Cleared at start()/resume() and on every\n // visibilitychange (an interruption boundary).\n private _lastTs: number | null = null;\n\n // `_tick` value captured at the start of the current run. `repeat` counts\n // frames *per run*, so the stop condition compares against this baseline\n // rather than the cumulative `_tick` (which only resets on reset()).\n private _repeat: number = 0;\n private _runStartTick: number = 0;\n\n // The document whose visibility drives `suspended`, subscribed in observe()\n // and released in dispose(). Null before observe() or in non-DOM\n // environments — `suspended` then simply stays false.\n private _visibilityDoc: Document | null = null;\n\n constructor(target?: EventTarget, scheduler?: RafScheduler) {\n super();\n this._target = target ?? this;\n this._injectedScheduler = scheduler ?? null;\n }\n\n get tick(): number {\n return this._tick;\n }\n\n get elapsed(): number {\n return this._elapsed;\n }\n\n get dt(): number {\n return this._dt;\n }\n\n get running(): boolean {\n return this._running;\n }\n\n get suspended(): boolean {\n return this._suspended;\n }\n\n // SSR readiness (§3.8): resolves after the first probe. There is nothing to\n // probe, so this is an already-resolved promise.\n get ready(): Promise<void> {\n return this._ready;\n }\n\n // Lifecycle (§3.5). observe() establishes the one ambient subscription this\n // node has — `visibilitychange`, which drives the `suspended` output and the\n // dt=0 normalization across a hidden period. Idempotent; a no-op without a\n // document (SSR pre-pass, worker). dispose() tears everything down and bumps\n // the generation so a frame already queued cannot fire onto a torn-down\n // element.\n observe(): Promise<void> {\n if (this._visibilityDoc === null && typeof document !== \"undefined\") {\n this._visibilityDoc = document;\n document.addEventListener(\"visibilitychange\", this._onVisibilityChange);\n // Sync `suspended` to the visibility state at subscription time: with a\n // start()-before-observe() ordering (headless Core usage) the document\n // may already be hidden, and waiting for the next visibilitychange\n // would report suspended=false until then. Same-value guarded, so the\n // common visible-at-observe case dispatches nothing.\n this._updateSuspended();\n }\n return this._ready;\n }\n\n dispose(): void {\n this._gen++;\n this.stop();\n if (this._visibilityDoc !== null) {\n this._visibilityDoc.removeEventListener(\"visibilitychange\", this._onVisibilityChange);\n this._visibilityDoc = null;\n }\n }\n\n // --- State setters with event dispatch ---\n\n private _dispatchTick(timestamp: number): void {\n this._target.dispatchEvent(new CustomEvent(\"wcs-raf:tick\", {\n detail: { count: this._tick, elapsed: this._elapsed, dt: this._dt, timestamp },\n bubbles: true,\n }));\n }\n\n private _setRunning(running: boolean): void {\n if (this._running === running) return;\n this._running = running;\n this._target.dispatchEvent(new CustomEvent(\"wcs-raf:running-changed\", {\n detail: running,\n bubbles: true,\n }));\n // `suspended` is derived from (running && hidden), so every running\n // transition re-evaluates it: stop/pause drop a suspension, and a start()\n // inside an already-hidden tab reports it immediately (honestly: no frame\n // will arrive until the tab is visible again).\n this._updateSuspended();\n }\n\n private _setSuspended(suspended: boolean): void {\n if (this._suspended === suspended) return;\n this._suspended = suspended;\n this._target.dispatchEvent(new CustomEvent(\"wcs-raf:suspended-changed\", {\n detail: suspended,\n bubbles: true,\n }));\n }\n\n private _updateSuspended(): void {\n const hidden = this._visibilityDoc !== null && this._visibilityDoc.visibilityState === \"hidden\";\n this._setSuspended(this._running && hidden);\n }\n\n // --- Public API ---\n\n start(options: RafStartOptions = {}): void {\n // Idempotent while running: a redundant start() must not stack a second\n // frame loop (which would double the tick rate). Reconfiguring an active\n // run is done via stop() + start().\n if (this._running) return;\n\n // Resolve the platform API at call time (§3.7). Absent rAF (SSR pre-pass,\n // worker) makes start() a silent no-op — never-throw, and this node has no\n // error surface by design.\n const scheduler = this._resolveScheduler();\n if (scheduler === null) return;\n\n // start() begins a fresh run, so clear any lingering pause from a prior\n // pause()-without-resume(). Without this, the loop would run while _paused\n // stayed true, leaving pause() a no-op and letting resume() overwrite the\n // live handle (leak + double fire).\n this._paused = false;\n\n // `repeat` is per-run intent, NOT persistent configuration: every start()\n // re-establishes it from the options, defaulting to \"unlimited\" when\n // omitted. This keeps a bare start() after a bounded run from silently\n // inheriting the old bounds.\n this._repeat = (typeof options.repeat === \"number\" && options.repeat > 0) ? options.repeat : 0;\n\n // New arming generation (§3.4): invalidates any callback still in flight\n // from a previous run (e.g. one whose cancel() a non-compliant scheduler\n // ignored). Bumped BEFORE the running-changed dispatch below, so that a\n // re-entrant restart from a listener arms with the newest generation —\n // the re-entrancy guard then keeps this outer call from arming (and\n // bumping) on top of it.\n this._gen++;\n\n this._setRunning(true);\n // Baseline this run's per-run repeat counting (set after _setRunning so a\n // re-start of a completed bounded run fires the full N frames again).\n this._runStartTick = this._tick;\n // G3: the first frame of a run reports dt = 0.\n this._lastTs = null;\n\n // Re-entrancy guard: _setRunning(true) just dispatched running-changed\n // synchronously, and a listener may have changed the world from inside it.\n // - `!_running`: the listener called stop()/pause()/dispose(). Without\n // this check a \"ghost\" frame would still be scheduled for an\n // already-stopped run — it would either tick once while running stays\n // false, or leave an uncancellable handle behind.\n // - `_handle !== null`: the listener restarted the loop itself\n // (stop()→start()); the inner start() already armed the new run, and\n // requesting again here would overwrite `_handle` (losing the inner\n // handle, never cancelled) and stack a permanent second frame loop.\n // On the normal path `_handle` is always null here — every transition\n // to `_running === false` clears it — so non-null can only mean a\n // re-entrant listener already scheduled the run for us.\n if (!this._running || this._handle !== null) return;\n this._requestFrame(scheduler);\n }\n\n stop(): void {\n this._clearHandle();\n this._paused = false;\n this._setRunning(false);\n }\n\n reset(): void {\n this._clearHandle();\n this._paused = false;\n this._tick = 0;\n this._elapsed = 0;\n this._dt = 0;\n this._lastTs = null;\n this._setRunning(false);\n // Notify observers that the counter/elapsed/dt have returned to zero. The\n // notification is not a frame, so `timestamp` is 0 (see WcsRafTickDetail).\n this._dispatchTick(0);\n }\n\n pause(): void {\n // Pause only a live loop; a no-op otherwise so it composes safely with the\n // declarative lifecycle. Unlike stop(), it records `_paused` so resume()\n // can tell an intentional pause from a full stop. No elapsed bookkeeping\n // is needed: elapsed is Σdt, and the resume boundary's dt is 0.\n if (!this._running || this._paused) return;\n this._clearHandle();\n this._paused = true;\n this._setRunning(false);\n }\n\n resume(): void {\n if (!this._paused) return;\n const scheduler = this._resolveScheduler();\n if (scheduler === null) return;\n this._paused = false;\n // New arming generation (§3.4), bumped before the running-changed\n // dispatch for the same re-entrancy reason as start().\n this._gen++;\n this._setRunning(true);\n // G3: the first frame after a pause reports dt = 0 (elapsed therefore does\n // not count the paused period — the \"active time\" contract).\n this._lastTs = null;\n\n // Re-entrancy guard, for the same reasons as start() (see the comment\n // there): a running-changed listener may have synchronously stopped this\n // node — or restarted it, leaving `_handle` already armed — from inside\n // _setRunning(true) above.\n if (!this._running || this._handle !== null) return;\n this._requestFrame(scheduler);\n }\n\n // --- Internal ---\n\n private _frame = (timestamp: number): void => {\n // Reached only through _requestFrame's generation-checked closure (§3.4):\n // a stale callback — disposed, cancelled by a non-compliant scheduler, or\n // superseded by a newer run — never gets here.\n this._handle = null;\n\n // dt: delta to the previous frame within this continuous run; 0 when this\n // frame opens a segment (start/resume/visibility boundary — G3).\n const dt = this._lastTs === null ? 0 : timestamp - this._lastTs;\n this._lastTs = timestamp;\n\n this._tick++;\n this._dt = dt;\n this._elapsed += dt;\n this._dispatchTick(timestamp);\n\n // Auto-stop once this run has fired the requested number of frames\n // (repeat=0 runs forever). Counted per-run via `_runStartTick`, so a\n // re-start after a completed bounded run fires N frames again. `once` is\n // expressed by the Shell as repeat=1.\n //\n // The cleanup mirrors stop() exactly, because a tick listener may have\n // synchronously paused — or paused and resumed — DURING the final frame's\n // dispatch above. The run's budget is exhausted either way, so clear the\n // pause (a later resume() must be a no-op, not an N+1th frame) and cancel\n // any handle a re-entrant resume() armed (it would otherwise survive as a\n // ghost frame and tick past the budget). On the normal path both are\n // already clear (no-ops). A stop()→start() restart is NOT affected: the\n // new run re-baselines `_runStartTick`, so this branch is not taken.\n if (this._repeat > 0 && (this._tick - this._runStartTick) >= this._repeat) {\n this._clearHandle();\n this._paused = false;\n this._setRunning(false);\n return;\n }\n\n // Re-request the next frame — unless a tick listener stopped the loop\n // synchronously during the dispatch above, or already scheduled a new run\n // itself (a synchronous stop()→start() / pause()→resume() restart leaves\n // _handle non-null; re-requesting on top of it would stack a permanent\n // second frame loop. The generation guard cannot catch this: a tail\n // request here would capture the restart's own — current — generation\n // and produce a second equally-valid loop).\n if (this._running && this._handle === null) {\n const scheduler = this._resolveScheduler();\n if (scheduler !== null) {\n this._requestFrame(scheduler);\n }\n }\n };\n\n private _onVisibilityChange = (): void => {\n // Either direction is an interruption boundary: entering hidden means the\n // browser stops delivering frames, so the NEXT delivered frame must not\n // report a delta spanning the gap (G3). Clearing on the visible edge too\n // is belt-and-braces for a missed hidden event — the worst case is one\n // extra dt=0 frame.\n this._lastTs = null;\n this._updateSuspended();\n };\n\n private _resolveScheduler(): RafScheduler | null {\n if (this._injectedScheduler !== null) return this._injectedScheduler;\n const g = globalThis as unknown as {\n requestAnimationFrame?: (cb: (ts: number) => void) => unknown;\n cancelAnimationFrame?: (handle: unknown) => void;\n };\n // The availability check itself still runs on every call (§3.7: resolved\n // at call time, not cached across an absence/presence flip).\n if (typeof g.requestAnimationFrame !== \"function\" || typeof g.cancelAnimationFrame !== \"function\") {\n return null;\n }\n if (this._globalScheduler === null) {\n // `g` is just a typed alias for `globalThis` (not a snapshot), so these\n // closures keep dereferencing the live global functions even though the\n // wrapper object itself is created only once.\n this._globalScheduler = {\n request: (cb) => g.requestAnimationFrame!(cb),\n cancel: (handle) => g.cancelAnimationFrame!(handle),\n };\n }\n return this._globalScheduler;\n }\n\n // Arm the next frame (§3.4). The callback closes over the generation\n // current at request time and re-checks it against the live `_gen` when the\n // frame arrives; a callback that outlived its run bails here. See the\n // `_gen` field comment for why this must be a per-request capture and not a\n // live-field comparison.\n private _requestFrame(scheduler: RafScheduler): void {\n const gen = this._gen;\n this._handle = scheduler.request((timestamp: number) => {\n if (gen !== this._gen) return;\n this._frame(timestamp);\n });\n }\n\n private _clearHandle(): void {\n if (this._handle !== null) {\n this._resolveScheduler()?.cancel(this._handle);\n this._handle = null;\n // Invalidate the cancelled callback's captured generation as well:\n // cancel() is best-effort against a non-compliant scheduler, the\n // generation is the guarantee (§3.4).\n this._gen++;\n }\n }\n}\n","import { config } from \"./config.js\";\nimport type { Raf } from \"./components/Raf.js\";\n\nlet registered = false;\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const rafId = triggerElement.getAttribute(config.triggerAttribute);\n if (!rafId) return;\n\n // Resolve the registered constructor at call time instead of importing Raf\n // as a value. The value import created a components/Raf.ts ⇄ autoTrigger.ts\n // cycle (Raf.connectedCallback() calls registerAutoTrigger()). instanceof\n // against the customElements registry keeps the exact same identity guarantee\n // — only the registered <wcs-raf> class matches — without the import cycle.\n const RafCtor = customElements.get(config.tagNames.raf);\n const rafElement = document.getElementById(rafId);\n if (!RafCtor || !(rafElement instanceof RafCtor)) return;\n\n // Suppress the element's default action so a loop can start without\n // navigating. Intentional: do not attach data-raftarget to an element whose\n // default action you also want (real <a href> link, form-submit button) — it\n // will be cancelled. See README \"Optional DOM Triggering\".\n event.preventDefault();\n (rafElement as Raf).start();\n}\n\nexport function registerAutoTrigger(): void {\n if (registered) return;\n registered = true;\n document.addEventListener(\"click\", handleClick);\n}\n\nexport function unregisterAutoTrigger(): void {\n if (!registered) return;\n registered = false;\n document.removeEventListener(\"click\", handleClick);\n}\n","import { config } from \"../config.js\";\nimport { IWcBindable } from \"../types.js\";\nimport { RafCore } from \"../core/RafCore.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\n\nexport class Raf extends HTMLElement {\n static hasConnectedCallbackPromise = true;\n static wcBindable: IWcBindable = {\n ...RafCore.wcBindable,\n properties: [\n ...RafCore.wcBindable.properties,\n { name: \"trigger\", event: \"wcs-raf:trigger-changed\" },\n ],\n // Shell-level settable surface. `attribute` is a purely descriptive hint\n // (per SPEC-extensions.md the binding core does not act on it) naming the\n // mirrored HTML attribute, matching <wcs-timer>. `trigger` is a momentary\n // command-property with no backing attribute, so it carries no hint.\n // `start` / `stop` / `reset` / `pause` / `resume` commands are inherited\n // from the Core above. Deliberately absent vs <wcs-timer>: `interval`\n // (rAF has no period) and `immediate` (the first frame already IS the\n // next rendering opportunity — no earlier meaningful moment exists).\n inputs: [\n { name: \"once\", attribute: \"once\" },\n { name: \"repeat\", attribute: \"repeat\" },\n { name: \"manual\", attribute: \"manual\" },\n { name: \"trigger\" },\n ],\n };\n\n private _core: RafCore;\n private _trigger: boolean = false;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new RafCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n \"wcs-raf:running-changed\": (d) => ({ running: d === true }),\n \"wcs-raf:suspended-changed\": (d) => ({ suspended: d === true }),\n });\n }\n\n // CSS state reflection (:state()) — debug-only snapshot getter. NOT part of\n // wc-bindable (not a bind target); see README \"CSS styling with :state()\".\n // MUST NOT return the live CustomStateSet (that would let callers write\n // states from outside, defeating the point of :state() being read-only).\n get debugStates(): string[] {\n return this._internals ? [...this._internals.states] : [];\n }\n\n private _initInternals(): ElementInternals | null {\n // never-throw (async-io-node-guidelines.md §3.6): attachInternals is absent\n // in happy-dom / older environments, and pre-125 Chromium rejects\n // non-dashed state names from states.add() (probed and discarded here).\n // Either case silently disables reflection — the component still works,\n // it just doesn't expose :state() selectors.\n try {\n if (typeof this.attachInternals !== \"function\") return null;\n const internals = this.attachInternals();\n internals.states.add(\"wcs-probe\");\n internals.states.delete(\"wcs-probe\");\n return internals;\n } catch {\n return null;\n }\n }\n\n private _wireStates(map: Record<string, (detail: any) => Record<string, boolean>>): void {\n if (this._internals === null) return;\n const states = this._internals.states;\n for (const [event, toStates] of Object.entries(map)) {\n this.addEventListener(event, (e) => {\n const debug = this.hasAttribute(\"debug-states\");\n for (const [name, on] of Object.entries(toStates((e as CustomEvent).detail))) {\n try {\n if (on) { states.add(name); } else { states.delete(name); }\n } catch { /* never-throw */ }\n if (debug) this.toggleAttribute(`data-wcs-state-${name}`, on);\n }\n });\n }\n }\n\n // SSR (§4.1/§4.4): the Shell exposes the Core's readiness so a server-side\n // renderer can await the connect-time probe before snapshotting. There is no\n // async probe here (observe() resolves immediately), but the contract is\n // uniform across IO nodes.\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Attribute accessors ---\n\n get once(): boolean {\n return this.hasAttribute(\"once\");\n }\n\n set once(value: boolean) {\n if (value) {\n this.setAttribute(\"once\", \"\");\n } else {\n this.removeAttribute(\"once\");\n }\n }\n\n get repeat(): number {\n const attr = this.getAttribute(\"repeat\");\n if (attr === null || attr.trim() === \"\") return 0;\n // Strict parse via Number() (\"3px\" -> NaN, not 3), matching <wcs-timer>.\n // Normalise any non-positive / non-numeric value to 0 (= unlimited).\n const parsed = Number(attr);\n return (Number.isFinite(parsed) && parsed > 0) ? parsed : 0;\n }\n\n set repeat(value: number) {\n this.setAttribute(\"repeat\", String(value));\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n // --- Core delegated getters ---\n\n get tick(): number {\n return this._core.tick;\n }\n\n get elapsed(): number {\n return this._core.elapsed;\n }\n\n get dt(): number {\n return this._core.dt;\n }\n\n get running(): boolean {\n return this._core.running;\n }\n\n get suspended(): boolean {\n return this._core.suspended;\n }\n\n // --- Command property ---\n\n get trigger(): boolean {\n return this._trigger;\n }\n\n set trigger(value: boolean) {\n // Momentary command-property: a false→true write starts the loop. Mirrors\n // <wcs-timer>. Prefer the command-token protocol (`command.start:\n // $command.begin`) for state-driven starts; this exists mainly for the DOM\n // click trigger and simple boolean bindings.\n const v = !!value;\n if (v) {\n this._trigger = true;\n this.start();\n this._trigger = false;\n // The `trigger-changed` event reports the momentary flag returning to\n // false, i.e. that the trigger property *changed* — it is deliberately\n // not gated on whether start() actually began a new run (same contract\n // as <wcs-timer>).\n this.dispatchEvent(new CustomEvent(\"wcs-raf:trigger-changed\", {\n detail: false,\n bubbles: true,\n }));\n }\n }\n\n // --- Commands ---\n\n start(): void {\n // `once` is sugar for \"fire exactly one frame\": map it to repeat=1, but\n // let an explicit repeat attribute win when both are present.\n const repeat = this.repeat > 0 ? this.repeat : (this.once ? 1 : 0);\n this._core.start({ repeat });\n }\n\n stop(): void {\n this._core.stop();\n }\n\n reset(): void {\n this._core.reset();\n }\n\n pause(): void {\n this._core.pause();\n }\n\n resume(): void {\n this._core.resume();\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n // Establish monitoring (§3.5): observe() subscribes visibilitychange (the\n // `suspended` output) and resolves once ready; expose it as\n // connectedCallbackPromise for SSR. Note for SSR pages: an auto-started\n // frame loop keeps scheduling — prefer `manual` in server-rendered markup\n // (see README).\n this._connectedCallbackPromise = this._core.observe();\n if (!this.manual) {\n this.start();\n }\n }\n\n disconnectedCallback(): void {\n // dispose() stops the loop, releases the visibility subscription and bumps\n // the generation so a frame already queued cannot fire onto a disconnected\n // element (§3.5 / §4.4).\n this._core.dispose();\n }\n}\n","import { Raf } from \"./components/Raf.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.raf)) {\n customElements.define(config.tagNames.raf, Raf);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapRaf(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.js","sources":["../src/config.ts","../src/core/RafCore.ts","../src/autoTrigger.ts","../src/protocol/upgradeProperties.ts","../src/components/Raf.ts","../src/registerComponents.ts","../src/bootstrapRaf.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n raf: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-raftarget\",\n tagNames: {\n raf: \"wcs-raf\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\n// Internal-only live handle to the mutable config. NOT part of the public API\n// (deliberately absent from exports.ts) — it is exported solely so sibling\n// modules in this package can read current settings cheaply. External consumers\n// must use getConfig() (returns a deep-frozen snapshot) / setConfig(). Mutating\n// this object directly bypasses the frozenConfig cache and is unsupported.\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (typeof partialConfig.autoTrigger === \"boolean\") {\n _config.autoTrigger = partialConfig.autoTrigger;\n }\n if (typeof partialConfig.triggerAttribute === \"string\") {\n _config.triggerAttribute = partialConfig.triggerAttribute;\n }\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { IWcBindable } from \"../types.js\";\n\nexport interface RafStartOptions {\n repeat?: number;\n}\n\n/**\n * Injectable frame scheduler. The default resolves\n * `globalThis.requestAnimationFrame` / `cancelAnimationFrame` AT CALL TIME\n * (async-io-node-guidelines §3.7); tests inject a fake that pumps frames with\n * explicit timestamps (the `dt` contract is timestamp-derived, so tests must\n * control the clock, not just the callback order).\n *\n * Contract: `request()` MUST return a non-null handle. The core uses `null`\n * as its internal \"not armed\" sentinel, so a scheduler returning literal\n * `null` would silently corrupt the handle bookkeeping (re-entrancy guards\n * and cancel tracking). Native rAF returns a long, so this only concerns\n * custom scheduler injections — return a number, object, or any other\n * non-nullish token.\n */\nexport interface RafScheduler {\n request(callback: (timestamp: number) => void): unknown;\n cancel(handle: unknown): void;\n}\n\n/**\n * Headless requestAnimationFrame primitive — `TimerCore`'s sibling with the\n * time source swapped from `setInterval` (a period) to rAF (the browser's\n * rendering opportunity). Exposed through the wc-bindable protocol: it streams\n * `tick` (frame counter), `elapsed` (accumulated ACTIVE milliseconds), `dt`\n * (delta to the previous frame) and the `running` / `suspended` pair, and is\n * driven by the `start` / `stop` / `reset` / `pause` / `resume` commands.\n *\n * `tick` / `elapsed` / `dt` are all surfaced via the single `wcs-raf:tick`\n * event (read through getters, mirroring how FetchCore exposes value/status\n * from one `wcs-fetch:response` event).\n *\n * Contracts specific to this node (docs/raf-tag-design.md):\n *\n * - **dt describes continuous running only.** The first frame after `start()`,\n * `resume()`, or a visibility interruption reports `dt = 0` — a value that\n * spans an interruption never reaches observers. Like `suspended`, the\n * visibility boundary is only detected once observe() has subscribed to\n * `visibilitychange`; a headless setup that skips observe() will see the\n * raw spanning delta on the first frame after a hidden gap. There is\n * deliberately NO upper clamp: how to treat a slow frame is the consumer's\n * domain decision.\n * - **elapsed is Σdt (active time).** Because interruption-spanning deltas are\n * normalized to 0, summing dt yields exactly the time frames were actually\n * being delivered — no separate segment bookkeeping is needed, and hidden /\n * paused periods contribute nothing. Granularity is one frame: between\n * frames the getter returns the value as of the last tick.\n * - **running / suspended are a desired/actual pair** (the wakelock split): in\n * a hidden tab the browser delivers no frames at all, so `running` (the\n * started intent) stays true while `suspended` reports that delivery is\n * actually stopped. `suspended` is only meaningful after `observe()` has\n * subscribed to `visibilitychange`; without a document it stays false.\n * - **No `error` surface.** rAF has no persistent failure mode; on a platform\n * without it, `start()` is a silent no-op (never-throw, resize precedent).\n */\nexport class RafCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"tick\", event: \"wcs-raf:tick\", semantics: \"state\", getter: (e: Event) => (e as CustomEvent).detail.count },\n { name: \"elapsed\", event: \"wcs-raf:tick\", semantics: \"state\", getter: (e: Event) => (e as CustomEvent).detail.elapsed },\n { name: \"dt\", event: \"wcs-raf:tick\", semantics: \"state\", getter: (e: Event) => (e as CustomEvent).detail.dt },\n { name: \"running\", event: \"wcs-raf:running-changed\", semantics: \"state\" },\n { name: \"suspended\", event: \"wcs-raf:suspended-changed\", semantics: \"state\" },\n ],\n commands: [\n { name: \"start\" },\n { name: \"stop\" },\n { name: \"reset\" },\n { name: \"pause\" },\n { name: \"resume\" },\n ],\n };\n\n private _target: EventTarget;\n private _injectedScheduler: RafScheduler | null;\n private _handle: unknown = null;\n\n // Lazily-created wrapper around the global rAF pair, cached so the hot\n // frame-reschedule path (_frame, once per delivered frame) does not\n // allocate a new object + closures every call. `request`/`cancel` still\n // dereference `globalThis.requestAnimationFrame` / `cancelAnimationFrame`\n // live on every invocation (they are not snapshotted here), so call-time\n // resolution (§3.7) is unchanged — only the wrapper object itself is\n // reused once the global functions are first found present.\n private _globalScheduler: RafScheduler | null = null;\n\n // Generation guard (§3.4): a monotonic arming counter. Bumped when a run is\n // armed (start()/resume()), when an armed handle is cancelled\n // (_clearHandle()) and on dispose(). _requestFrame() captures the value in\n // each request's closure and drops the frame if it no longer matches the\n // live field when it fires. cancel() is best-effort against a non-compliant\n // scheduler; the captured generation is the guarantee — a stale callback can\n // neither mutate state, dispatch on a torn-down element, nor corrupt a\n // newer run's `_handle` bookkeeping. A live-field comparison (the previous\n // `_runGen` scheme) could not survive a dispose() → start() round trip: the\n // new start() re-synced the pair and let the stale callback through,\n // permanently doubling the frame loop.\n private _gen = 0;\n // SSR (§3.8): there is no asynchronous probe, so readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n private _tick: number = 0;\n private _dt: number = 0;\n private _elapsed: number = 0;\n private _running: boolean = false;\n private _suspended: boolean = false;\n private _paused: boolean = false;\n\n // Timestamp of the previous frame within the current continuous run.\n // `null` means \"the next frame starts a run segment\": its dt is reported as\n // 0 (the G3 normalization). Cleared at start()/resume() and on every\n // visibilitychange (an interruption boundary).\n private _lastTs: number | null = null;\n\n // `_tick` value captured at the start of the current run. `repeat` counts\n // frames *per run*, so the stop condition compares against this baseline\n // rather than the cumulative `_tick` (which only resets on reset()).\n private _repeat: number = 0;\n private _runStartTick: number = 0;\n\n // The document whose visibility drives `suspended`, subscribed in observe()\n // and released in dispose(). Null before observe() or in non-DOM\n // environments — `suspended` then simply stays false.\n private _visibilityDoc: Document | null = null;\n\n constructor(target?: EventTarget, scheduler?: RafScheduler) {\n super();\n this._target = target ?? this;\n this._injectedScheduler = scheduler ?? null;\n }\n\n get tick(): number {\n return this._tick;\n }\n\n get elapsed(): number {\n return this._elapsed;\n }\n\n get dt(): number {\n return this._dt;\n }\n\n get running(): boolean {\n return this._running;\n }\n\n get suspended(): boolean {\n return this._suspended;\n }\n\n // SSR readiness (§3.8): resolves after the first probe. There is nothing to\n // probe, so this is an already-resolved promise.\n get ready(): Promise<void> {\n return this._ready;\n }\n\n // Lifecycle (§3.5). observe() establishes the one ambient subscription this\n // node has — `visibilitychange`, which drives the `suspended` output and the\n // dt=0 normalization across a hidden period. Idempotent; a no-op without a\n // document (SSR pre-pass, worker). dispose() tears everything down and bumps\n // the generation so a frame already queued cannot fire onto a torn-down\n // element.\n observe(): Promise<void> {\n if (this._visibilityDoc === null && typeof document !== \"undefined\") {\n this._visibilityDoc = document;\n document.addEventListener(\"visibilitychange\", this._onVisibilityChange);\n // Sync `suspended` to the visibility state at subscription time: with a\n // start()-before-observe() ordering (headless Core usage) the document\n // may already be hidden, and waiting for the next visibilitychange\n // would report suspended=false until then. Same-value guarded, so the\n // common visible-at-observe case dispatches nothing.\n this._updateSuspended();\n }\n return this._ready;\n }\n\n dispose(): void {\n this._gen++;\n this.stop();\n if (this._visibilityDoc !== null) {\n this._visibilityDoc.removeEventListener(\"visibilitychange\", this._onVisibilityChange);\n this._visibilityDoc = null;\n }\n }\n\n // --- State setters with event dispatch ---\n\n private _dispatchTick(timestamp: number): void {\n this._target.dispatchEvent(new CustomEvent(\"wcs-raf:tick\", {\n detail: { count: this._tick, elapsed: this._elapsed, dt: this._dt, timestamp },\n bubbles: true,\n }));\n }\n\n private _setRunning(running: boolean): void {\n if (this._running === running) return;\n this._running = running;\n this._target.dispatchEvent(new CustomEvent(\"wcs-raf:running-changed\", {\n detail: running,\n bubbles: true,\n }));\n // `suspended` is derived from (running && hidden), so every running\n // transition re-evaluates it: stop/pause drop a suspension, and a start()\n // inside an already-hidden tab reports it immediately (honestly: no frame\n // will arrive until the tab is visible again).\n this._updateSuspended();\n }\n\n private _setSuspended(suspended: boolean): void {\n if (this._suspended === suspended) return;\n this._suspended = suspended;\n this._target.dispatchEvent(new CustomEvent(\"wcs-raf:suspended-changed\", {\n detail: suspended,\n bubbles: true,\n }));\n }\n\n private _updateSuspended(): void {\n const hidden = this._visibilityDoc !== null && this._visibilityDoc.visibilityState === \"hidden\";\n this._setSuspended(this._running && hidden);\n }\n\n // --- Public API ---\n\n start(options: RafStartOptions = {}): void {\n // Idempotent while running: a redundant start() must not stack a second\n // frame loop (which would double the tick rate). Reconfiguring an active\n // run is done via stop() + start().\n if (this._running) return;\n\n // Resolve the platform API at call time (§3.7). Absent rAF (SSR pre-pass,\n // worker) makes start() a silent no-op — never-throw, and this node has no\n // error surface by design.\n const scheduler = this._resolveScheduler();\n if (scheduler === null) return;\n\n // start() begins a fresh run, so clear any lingering pause from a prior\n // pause()-without-resume(). Without this, the loop would run while _paused\n // stayed true, leaving pause() a no-op and letting resume() overwrite the\n // live handle (leak + double fire).\n this._paused = false;\n\n // `repeat` is per-run intent, NOT persistent configuration: every start()\n // re-establishes it from the options, defaulting to \"unlimited\" when\n // omitted. This keeps a bare start() after a bounded run from silently\n // inheriting the old bounds.\n this._repeat = (typeof options.repeat === \"number\" && options.repeat > 0) ? options.repeat : 0;\n\n // New arming generation (§3.4): invalidates any callback still in flight\n // from a previous run (e.g. one whose cancel() a non-compliant scheduler\n // ignored). Bumped BEFORE the running-changed dispatch below, so that a\n // re-entrant restart from a listener arms with the newest generation —\n // the re-entrancy guard then keeps this outer call from arming (and\n // bumping) on top of it.\n this._gen++;\n\n this._setRunning(true);\n // Baseline this run's per-run repeat counting (set after _setRunning so a\n // re-start of a completed bounded run fires the full N frames again).\n this._runStartTick = this._tick;\n // G3: the first frame of a run reports dt = 0.\n this._lastTs = null;\n\n // Re-entrancy guard: _setRunning(true) just dispatched running-changed\n // synchronously, and a listener may have changed the world from inside it.\n // - `!_running`: the listener called stop()/pause()/dispose(). Without\n // this check a \"ghost\" frame would still be scheduled for an\n // already-stopped run — it would either tick once while running stays\n // false, or leave an uncancellable handle behind.\n // - `_handle !== null`: the listener restarted the loop itself\n // (stop()→start()); the inner start() already armed the new run, and\n // requesting again here would overwrite `_handle` (losing the inner\n // handle, never cancelled) and stack a permanent second frame loop.\n // On the normal path `_handle` is always null here — every transition\n // to `_running === false` clears it — so non-null can only mean a\n // re-entrant listener already scheduled the run for us.\n if (!this._running || this._handle !== null) return;\n this._requestFrame(scheduler);\n }\n\n stop(): void {\n this._clearHandle();\n this._paused = false;\n this._setRunning(false);\n }\n\n reset(): void {\n this._clearHandle();\n this._paused = false;\n this._tick = 0;\n this._elapsed = 0;\n this._dt = 0;\n this._lastTs = null;\n this._setRunning(false);\n // Notify observers that the counter/elapsed/dt have returned to zero. The\n // notification is not a frame, so `timestamp` is 0 (see WcsRafTickDetail).\n this._dispatchTick(0);\n }\n\n pause(): void {\n // Pause only a live loop; a no-op otherwise so it composes safely with the\n // declarative lifecycle. Unlike stop(), it records `_paused` so resume()\n // can tell an intentional pause from a full stop. No elapsed bookkeeping\n // is needed: elapsed is Σdt, and the resume boundary's dt is 0.\n if (!this._running || this._paused) return;\n this._clearHandle();\n this._paused = true;\n this._setRunning(false);\n }\n\n resume(): void {\n if (!this._paused) return;\n const scheduler = this._resolveScheduler();\n if (scheduler === null) return;\n this._paused = false;\n // New arming generation (§3.4), bumped before the running-changed\n // dispatch for the same re-entrancy reason as start().\n this._gen++;\n this._setRunning(true);\n // G3: the first frame after a pause reports dt = 0 (elapsed therefore does\n // not count the paused period — the \"active time\" contract).\n this._lastTs = null;\n\n // Re-entrancy guard, for the same reasons as start() (see the comment\n // there): a running-changed listener may have synchronously stopped this\n // node — or restarted it, leaving `_handle` already armed — from inside\n // _setRunning(true) above.\n if (!this._running || this._handle !== null) return;\n this._requestFrame(scheduler);\n }\n\n // --- Internal ---\n\n private _frame = (timestamp: number): void => {\n // Reached only through _requestFrame's generation-checked closure (§3.4):\n // a stale callback — disposed, cancelled by a non-compliant scheduler, or\n // superseded by a newer run — never gets here.\n this._handle = null;\n\n // dt: delta to the previous frame within this continuous run; 0 when this\n // frame opens a segment (start/resume/visibility boundary — G3).\n const dt = this._lastTs === null ? 0 : timestamp - this._lastTs;\n this._lastTs = timestamp;\n\n this._tick++;\n this._dt = dt;\n this._elapsed += dt;\n this._dispatchTick(timestamp);\n\n // Auto-stop once this run has fired the requested number of frames\n // (repeat=0 runs forever). Counted per-run via `_runStartTick`, so a\n // re-start after a completed bounded run fires N frames again. `once` is\n // expressed by the Shell as repeat=1.\n //\n // The cleanup mirrors stop() exactly, because a tick listener may have\n // synchronously paused — or paused and resumed — DURING the final frame's\n // dispatch above. The run's budget is exhausted either way, so clear the\n // pause (a later resume() must be a no-op, not an N+1th frame) and cancel\n // any handle a re-entrant resume() armed (it would otherwise survive as a\n // ghost frame and tick past the budget). On the normal path both are\n // already clear (no-ops). A stop()→start() restart is NOT affected: the\n // new run re-baselines `_runStartTick`, so this branch is not taken.\n if (this._repeat > 0 && (this._tick - this._runStartTick) >= this._repeat) {\n this._clearHandle();\n this._paused = false;\n this._setRunning(false);\n return;\n }\n\n // Re-request the next frame — unless a tick listener stopped the loop\n // synchronously during the dispatch above, or already scheduled a new run\n // itself (a synchronous stop()→start() / pause()→resume() restart leaves\n // _handle non-null; re-requesting on top of it would stack a permanent\n // second frame loop. The generation guard cannot catch this: a tail\n // request here would capture the restart's own — current — generation\n // and produce a second equally-valid loop).\n if (this._running && this._handle === null) {\n const scheduler = this._resolveScheduler();\n if (scheduler !== null) {\n this._requestFrame(scheduler);\n }\n }\n };\n\n private _onVisibilityChange = (): void => {\n // Either direction is an interruption boundary: entering hidden means the\n // browser stops delivering frames, so the NEXT delivered frame must not\n // report a delta spanning the gap (G3). Clearing on the visible edge too\n // is belt-and-braces for a missed hidden event — the worst case is one\n // extra dt=0 frame.\n this._lastTs = null;\n this._updateSuspended();\n };\n\n private _resolveScheduler(): RafScheduler | null {\n if (this._injectedScheduler !== null) return this._injectedScheduler;\n const g = globalThis as unknown as {\n requestAnimationFrame?: (cb: (ts: number) => void) => unknown;\n cancelAnimationFrame?: (handle: unknown) => void;\n };\n // The availability check itself still runs on every call (§3.7: resolved\n // at call time, not cached across an absence/presence flip).\n if (typeof g.requestAnimationFrame !== \"function\" || typeof g.cancelAnimationFrame !== \"function\") {\n return null;\n }\n if (this._globalScheduler === null) {\n // `g` is just a typed alias for `globalThis` (not a snapshot), so these\n // closures keep dereferencing the live global functions even though the\n // wrapper object itself is created only once.\n this._globalScheduler = {\n request: (cb) => g.requestAnimationFrame!(cb),\n cancel: (handle) => g.cancelAnimationFrame!(handle),\n };\n }\n return this._globalScheduler;\n }\n\n // Arm the next frame (§3.4). The callback closes over the generation\n // current at request time and re-checks it against the live `_gen` when the\n // frame arrives; a callback that outlived its run bails here. See the\n // `_gen` field comment for why this must be a per-request capture and not a\n // live-field comparison.\n private _requestFrame(scheduler: RafScheduler): void {\n const gen = this._gen;\n this._handle = scheduler.request((timestamp: number) => {\n if (gen !== this._gen) return;\n this._frame(timestamp);\n });\n }\n\n private _clearHandle(): void {\n if (this._handle !== null) {\n this._resolveScheduler()?.cancel(this._handle);\n this._handle = null;\n // Invalidate the cancelled callback's captured generation as well:\n // cancel() is best-effort against a non-compliant scheduler, the\n // generation is the guarantee (§3.4).\n this._gen++;\n }\n }\n}\n","import { config } from \"./config.js\";\nimport type { Raf } from \"./components/Raf.js\";\n\nlet registered = false;\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const rafId = triggerElement.getAttribute(config.triggerAttribute);\n if (!rafId) return;\n\n // Resolve the registered constructor at call time instead of importing Raf\n // as a value. The value import created a components/Raf.ts ⇄ autoTrigger.ts\n // cycle (Raf.connectedCallback() calls registerAutoTrigger()). instanceof\n // against the customElements registry keeps the exact same identity guarantee\n // — only the registered <wcs-raf> class matches — without the import cycle.\n const RafCtor = customElements.get(config.tagNames.raf);\n const rafElement = document.getElementById(rafId);\n if (!RafCtor || !(rafElement instanceof RafCtor)) return;\n\n // Suppress the element's default action so a loop can start without\n // navigating. Intentional: do not attach data-raftarget to an element whose\n // default action you also want (real <a href> link, form-submit button) — it\n // will be cancelled. See README \"Optional DOM Triggering\".\n event.preventDefault();\n (rafElement as Raf).start();\n}\n\nexport function registerAutoTrigger(): void {\n if (registered) return;\n registered = true;\n document.addEventListener(\"click\", handleClick);\n}\n\nexport function unregisterAutoTrigger(): void {\n if (!registered) return;\n registered = false;\n document.removeEventListener(\"click\", handleClick);\n}\n","// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /protocol/upgrade-properties.ts by scripts/sync-protocol-types.mjs.\n// Run `node scripts/sync-protocol-types.mjs` after editing the source.\n// ===========================================================================\n\n// custom element の property upgrade — `static wcBindable.inputs` に宣言した入力のうち、\n// 要素が upgrade される前に代入された own データプロパティを取り込み直す。\n//\n// なぜ必要か:\n// 未定義タグの要素は素の HTMLElement なので、`el.url = \"...\"` は own データプロパティを作る。\n// upgrade 後にクラスの accessor が prototype へ入っても own プロパティが優先されるため、\n// setter は二度と呼ばれず、値は要素へ届かないまま消える(エラーも警告も出ない)。\n// 常にプロパティ代入を行う framework(Angular の `[prop]`、Lit の `.prop=`、\n// Solid の `prop:`、Vue の `.prop` 修飾子)× 遅延定義(autoloader / CDN / code-split)で\n// 常態的に起きる。docs/architecture-hardening/13-framework-adapter-binding-constraints.md §1.2。\n//\n// 安全側の判定:\n// own プロパティがあっても、prototype チェーンに accessor が無ければ「シャドウ」ではなく\n// その own プロパティ自体が正規の格納先なので触らない(public class field を壊さない)。\n//\n// SINGLE SOURCE OF TRUTH: edit only this file (/protocol/upgrade-properties.ts), then run\n// `node scripts/sync-protocol-types.mjs` to regenerate the per-package copies\n// (packages/<pkg>/src/protocol/upgradeProperties.ts). Those copies are generated — do not edit them.\nimport { IWcBindable } from \"./wcBindable.js\";\n\nfunction hasAccessorOnPrototype(target: object, name: string): boolean {\n let proto = Object.getPrototypeOf(target);\n while (proto !== null) {\n const descriptor = Object.getOwnPropertyDescriptor(proto, name);\n if (descriptor !== undefined) {\n return typeof descriptor.get === \"function\" || typeof descriptor.set === \"function\";\n }\n proto = Object.getPrototypeOf(proto);\n }\n return false;\n}\n\n/**\n * `connectedCallback` の先頭で呼ぶ。宣言済み input のうち upgrade 前の代入で\n * accessor をシャドウしている own プロパティを、delete → 再代入で setter に通し直す。\n *\n * - 冪等: 再代入は accessor を通るので own プロパティは残らず、2 回目以降は no-op。\n * - 宣言に `inputs` が無い要素、`wcBindable` を持たない要素では何もしない。\n * - 値の意味は変えない。今まで捨てられていた代入が届くようになる一方向の変化。\n */\nexport function upgradeProperties(element: object): void {\n const declaration = (element as { constructor?: { wcBindable?: IWcBindable } }).constructor?.wcBindable;\n const inputs = declaration?.inputs;\n if (inputs === undefined) return;\n for (const input of inputs) {\n const name = input.name;\n if (!Object.prototype.hasOwnProperty.call(element, name)) continue;\n if (!hasAccessorOnPrototype(element, name)) continue;\n const record = element as Record<string, unknown>;\n const value = record[name];\n delete record[name];\n record[name] = value;\n }\n}\n","import { config } from \"../config.js\";\nimport { IWcBindable } from \"../types.js\";\nimport { RafCore } from \"../core/RafCore.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\nimport { upgradeProperties } from \"../protocol/upgradeProperties.js\";\n\nexport class Raf extends HTMLElement {\n static hasConnectedCallbackPromise = true;\n static wcBindable: IWcBindable = {\n ...RafCore.wcBindable,\n properties: [\n ...RafCore.wcBindable.properties,\n { name: \"trigger\", event: \"wcs-raf:trigger-changed\", semantics: \"state\" },\n ],\n // Shell-level settable surface. `attribute` is a purely descriptive hint\n // (per SPEC-extensions.md the binding core does not act on it) naming the\n // mirrored HTML attribute, matching <wcs-timer>. `trigger` is a momentary\n // command-property with no backing attribute, so it carries no hint.\n // `start` / `stop` / `reset` / `pause` / `resume` commands are inherited\n // from the Core above. Deliberately absent vs <wcs-timer>: `interval`\n // (rAF has no period) and `immediate` (the first frame already IS the\n // next rendering opportunity — no earlier meaningful moment exists).\n inputs: [\n { name: \"once\", attribute: \"once\" },\n { name: \"repeat\", attribute: \"repeat\" },\n { name: \"manual\", attribute: \"manual\" },\n { name: \"trigger\" },\n ],\n };\n\n private _core: RafCore;\n private _trigger: boolean = false;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new RafCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n \"wcs-raf:running-changed\": (d) => ({ running: d === true }),\n \"wcs-raf:suspended-changed\": (d) => ({ suspended: d === true }),\n });\n }\n\n // CSS state reflection (:state()) — debug-only snapshot getter. NOT part of\n // wc-bindable (not a bind target); see README \"CSS styling with :state()\".\n // MUST NOT return the live CustomStateSet (that would let callers write\n // states from outside, defeating the point of :state() being read-only).\n get debugStates(): string[] {\n return this._internals ? [...this._internals.states] : [];\n }\n\n private _initInternals(): ElementInternals | null {\n // never-throw (async-io-node-guidelines.md §3.6): attachInternals is absent\n // in happy-dom / older environments, and pre-125 Chromium rejects\n // non-dashed state names from states.add() (probed and discarded here).\n // Either case silently disables reflection — the component still works,\n // it just doesn't expose :state() selectors.\n try {\n if (typeof this.attachInternals !== \"function\") return null;\n const internals = this.attachInternals();\n internals.states.add(\"wcs-probe\");\n internals.states.delete(\"wcs-probe\");\n return internals;\n } catch {\n return null;\n }\n }\n\n private _wireStates(map: Record<string, (detail: any) => Record<string, boolean>>): void {\n if (this._internals === null) return;\n const states = this._internals.states;\n for (const [event, toStates] of Object.entries(map)) {\n this.addEventListener(event, (e) => {\n const debug = this.hasAttribute(\"debug-states\");\n for (const [name, on] of Object.entries(toStates((e as CustomEvent).detail))) {\n try {\n if (on) { states.add(name); } else { states.delete(name); }\n } catch { /* never-throw */ }\n if (debug) this.toggleAttribute(`data-wcs-state-${name}`, on);\n }\n });\n }\n }\n\n // SSR (§4.1/§4.4): the Shell exposes the Core's readiness so a server-side\n // renderer can await the connect-time probe before snapshotting. There is no\n // async probe here (observe() resolves immediately), but the contract is\n // uniform across IO nodes.\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Attribute accessors ---\n\n get once(): boolean {\n return this.hasAttribute(\"once\");\n }\n\n set once(value: boolean) {\n if (value) {\n this.setAttribute(\"once\", \"\");\n } else {\n this.removeAttribute(\"once\");\n }\n }\n\n get repeat(): number {\n const attr = this.getAttribute(\"repeat\");\n if (attr === null || attr.trim() === \"\") return 0;\n // Strict parse via Number() (\"3px\" -> NaN, not 3), matching <wcs-timer>.\n // Normalise any non-positive / non-numeric value to 0 (= unlimited).\n const parsed = Number(attr);\n return (Number.isFinite(parsed) && parsed > 0) ? parsed : 0;\n }\n\n set repeat(value: number) {\n this.setAttribute(\"repeat\", String(value));\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n // --- Core delegated getters ---\n\n get tick(): number {\n return this._core.tick;\n }\n\n get elapsed(): number {\n return this._core.elapsed;\n }\n\n get dt(): number {\n return this._core.dt;\n }\n\n get running(): boolean {\n return this._core.running;\n }\n\n get suspended(): boolean {\n return this._core.suspended;\n }\n\n // --- Command property ---\n\n get trigger(): boolean {\n return this._trigger;\n }\n\n set trigger(value: boolean) {\n // Momentary command-property: a false→true write starts the loop. Mirrors\n // <wcs-timer>. Prefer the command-token protocol (`command.start:\n // $command.begin`) for state-driven starts; this exists mainly for the DOM\n // click trigger and simple boolean bindings.\n const v = !!value;\n if (v) {\n this._trigger = true;\n this.start();\n this._trigger = false;\n // The `trigger-changed` event reports the momentary flag returning to\n // false, i.e. that the trigger property *changed* — it is deliberately\n // not gated on whether start() actually began a new run (same contract\n // as <wcs-timer>).\n this.dispatchEvent(new CustomEvent(\"wcs-raf:trigger-changed\", {\n detail: false,\n bubbles: true,\n }));\n }\n }\n\n // --- Commands ---\n\n start(): void {\n // `once` is sugar for \"fire exactly one frame\": map it to repeat=1, but\n // let an explicit repeat attribute win when both are present.\n const repeat = this.repeat > 0 ? this.repeat : (this.once ? 1 : 0);\n this._core.start({ repeat });\n }\n\n stop(): void {\n this._core.stop();\n }\n\n reset(): void {\n this._core.reset();\n }\n\n pause(): void {\n this._core.pause();\n }\n\n resume(): void {\n this._core.resume();\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n // upgrade 前に代入された input を取り込み直す(doc 13 §1.2 / Phase A1)\n upgradeProperties(this);\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n // Establish monitoring (§3.5): observe() subscribes visibilitychange (the\n // `suspended` output) and resolves once ready; expose it as\n // connectedCallbackPromise for SSR. Note for SSR pages: an auto-started\n // frame loop keeps scheduling — prefer `manual` in server-rendered markup\n // (see README).\n this._connectedCallbackPromise = this._core.observe();\n if (!this.manual) {\n this.start();\n }\n }\n\n disconnectedCallback(): void {\n // dispose() stops the loop, releases the visibility subscription and bumps\n // the generation so a frame already queued cannot fire onto a disconnected\n // element (§3.5 / §4.4).\n this._core.dispose();\n }\n}\n","import { Raf } from \"./components/Raf.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.raf)) {\n customElements.define(config.tagNames.raf, Raf);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapRaf(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const t={autoTrigger:!0,triggerAttribute:"data-raftarget",tagNames:{raf:"wcs-raf"}};function e(t){if(null===t||"object"!=typeof t)return t;Object.freeze(t);for(const s of Object.keys(t))e(t[s]);return t}function s(t){if(null===t||"object"!=typeof t)return t;const e={};for(const i of Object.keys(t))e[i]=s(t[i]);return e}let i=null;const n=t;function r(){return i||(i=e(s(t))),i}class a extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"tick",event:"wcs-raf:tick",getter:t=>t.detail.count},{name:"elapsed",event:"wcs-raf:tick",getter:t=>t.detail.elapsed},{name:"dt",event:"wcs-raf:tick",getter:t=>t.detail.dt},{name:"running",event:"wcs-raf:running-changed"},{name:"suspended",event:"wcs-raf:suspended-changed"}],commands:[{name:"start"},{name:"stop"},{name:"reset"},{name:"pause"},{name:"resume"}]};_target;_injectedScheduler;_handle=null;_globalScheduler=null;_gen=0;_ready=Promise.resolve();_tick=0;_dt=0;_elapsed=0;_running=!1;_suspended=!1;_paused=!1;_lastTs=null;_repeat=0;_runStartTick=0;_visibilityDoc=null;constructor(t,e){super(),this._target=t??this,this._injectedScheduler=e??null}get tick(){return this._tick}get elapsed(){return this._elapsed}get dt(){return this._dt}get running(){return this._running}get suspended(){return this._suspended}get ready(){return this._ready}observe(){return null===this._visibilityDoc&&"undefined"!=typeof document&&(this._visibilityDoc=document,document.addEventListener("visibilitychange",this._onVisibilityChange),this._updateSuspended()),this._ready}dispose(){this._gen++,this.stop(),null!==this._visibilityDoc&&(this._visibilityDoc.removeEventListener("visibilitychange",this._onVisibilityChange),this._visibilityDoc=null)}_dispatchTick(t){this._target.dispatchEvent(new CustomEvent("wcs-raf:tick",{detail:{count:this._tick,elapsed:this._elapsed,dt:this._dt,timestamp:t},bubbles:!0}))}_setRunning(t){this._running!==t&&(this._running=t,this._target.dispatchEvent(new CustomEvent("wcs-raf:running-changed",{detail:t,bubbles:!0})),this._updateSuspended())}_setSuspended(t){this._suspended!==t&&(this._suspended=t,this._target.dispatchEvent(new CustomEvent("wcs-raf:suspended-changed",{detail:t,bubbles:!0})))}_updateSuspended(){const t=null!==this._visibilityDoc&&"hidden"===this._visibilityDoc.visibilityState;this._setSuspended(this._running&&t)}start(t={}){if(this._running)return;const e=this._resolveScheduler();null!==e&&(this._paused=!1,this._repeat="number"==typeof t.repeat&&t.repeat>0?t.repeat:0,this._gen++,this._setRunning(!0),this._runStartTick=this._tick,this._lastTs=null,this._running&&null===this._handle&&this._requestFrame(e))}stop(){this._clearHandle(),this._paused=!1,this._setRunning(!1)}reset(){this._clearHandle(),this._paused=!1,this._tick=0,this._elapsed=0,this._dt=0,this._lastTs=null,this._setRunning(!1),this._dispatchTick(0)}pause(){this._running&&!this._paused&&(this._clearHandle(),this._paused=!0,this._setRunning(!1))}resume(){if(!this._paused)return;const t=this._resolveScheduler();null!==t&&(this._paused=!1,this._gen++,this._setRunning(!0),this._lastTs=null,this._running&&null===this._handle&&this._requestFrame(t))}_frame=t=>{this._handle=null;const e=null===this._lastTs?0:t-this._lastTs;if(this._lastTs=t,this._tick++,this._dt=e,this._elapsed+=e,this._dispatchTick(t),this._repeat>0&&this._tick-this._runStartTick>=this._repeat)return this._clearHandle(),this._paused=!1,void this._setRunning(!1);if(this._running&&null===this._handle){const t=this._resolveScheduler();null!==t&&this._requestFrame(t)}};_onVisibilityChange=()=>{this._lastTs=null,this._updateSuspended()};_resolveScheduler(){if(null!==this._injectedScheduler)return this._injectedScheduler;const t=globalThis;return"function"!=typeof t.requestAnimationFrame||"function"!=typeof t.cancelAnimationFrame?null:(null===this._globalScheduler&&(this._globalScheduler={request:e=>t.requestAnimationFrame(e),cancel:e=>t.cancelAnimationFrame(e)}),this._globalScheduler)}_requestFrame(t){const e=this._gen;this._handle=t.request(t=>{e===this._gen&&this._frame(t)})}_clearHandle(){null!==this._handle&&(this._resolveScheduler()?.cancel(this._handle),this._handle=null,this._gen++)}}let u=!1;function l(t){const e=t.target;if(!(e instanceof Element))return;const s=e.closest(`[${n.triggerAttribute}]`);if(!s)return;const i=s.getAttribute(n.triggerAttribute);if(!i)return;const r=customElements.get(n.tagNames.raf),a=document.getElementById(i);r&&a instanceof r&&(t.preventDefault(),a.start())}class c extends HTMLElement{static hasConnectedCallbackPromise=!0;static wcBindable={...a.wcBindable,properties:[...a.wcBindable.properties,{name:"trigger",event:"wcs-raf:trigger-changed"}],inputs:[{name:"once",attribute:"once"},{name:"repeat",attribute:"repeat"},{name:"manual",attribute:"manual"},{name:"trigger"}]};_core;_trigger=!1;_connectedCallbackPromise=Promise.resolve();_internals=null;constructor(){super(),this._core=new a(this),this._internals=this._initInternals(),this._wireStates({"wcs-raf:running-changed":t=>({running:!0===t}),"wcs-raf:suspended-changed":t=>({suspended:!0===t})})}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[s,i]of Object.entries(t))this.addEventListener(s,t=>{const s=this.hasAttribute("debug-states");for(const[n,r]of Object.entries(i(t.detail))){try{r?e.add(n):e.delete(n)}catch{}s&&this.toggleAttribute(`data-wcs-state-${n}`,r)}})}get connectedCallbackPromise(){return this._connectedCallbackPromise}get once(){return this.hasAttribute("once")}set once(t){t?this.setAttribute("once",""):this.removeAttribute("once")}get repeat(){const t=this.getAttribute("repeat");if(null===t||""===t.trim())return 0;const e=Number(t);return Number.isFinite(e)&&e>0?e:0}set repeat(t){this.setAttribute("repeat",String(t))}get manual(){return this.hasAttribute("manual")}set manual(t){t?this.setAttribute("manual",""):this.removeAttribute("manual")}get tick(){return this._core.tick}get elapsed(){return this._core.elapsed}get dt(){return this._core.dt}get running(){return this._core.running}get suspended(){return this._core.suspended}get trigger(){return this._trigger}set trigger(t){!!t&&(this._trigger=!0,this.start(),this._trigger=!1,this.dispatchEvent(new CustomEvent("wcs-raf:trigger-changed",{detail:!1,bubbles:!0})))}start(){const t=this.repeat>0?this.repeat:this.once?1:0;this._core.start({repeat:t})}stop(){this._core.stop()}reset(){this._core.reset()}pause(){this._core.pause()}resume(){this._core.resume()}connectedCallback(){this.style.display="none",n.autoTrigger&&(u||(u=!0,document.addEventListener("click",l))),this._connectedCallbackPromise=this._core.observe(),this.manual||this.start()}disconnectedCallback(){this._core.dispose()}}function h(e){var s;e&&("boolean"==typeof(s=e).autoTrigger&&(t.autoTrigger=s.autoTrigger),"string"==typeof s.triggerAttribute&&(t.triggerAttribute=s.triggerAttribute),s.tagNames&&Object.assign(t.tagNames,s.tagNames),i=null),customElements.get(n.tagNames.raf)||customElements.define(n.tagNames.raf,c)}export{a as RafCore,c as WcsRaf,h as bootstrapRaf,r as getConfig};
1
+ const t={autoTrigger:!0,triggerAttribute:"data-raftarget",tagNames:{raf:"wcs-raf"}};function e(t){if(null===t||"object"!=typeof t)return t;Object.freeze(t);for(const s of Object.keys(t))e(t[s]);return t}function s(t){if(null===t||"object"!=typeof t)return t;const e={};for(const n of Object.keys(t))e[n]=s(t[n]);return e}let n=null;const i=t;function r(){return n||(n=e(s(t))),n}class a extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"tick",event:"wcs-raf:tick",semantics:"state",getter:t=>t.detail.count},{name:"elapsed",event:"wcs-raf:tick",semantics:"state",getter:t=>t.detail.elapsed},{name:"dt",event:"wcs-raf:tick",semantics:"state",getter:t=>t.detail.dt},{name:"running",event:"wcs-raf:running-changed",semantics:"state"},{name:"suspended",event:"wcs-raf:suspended-changed",semantics:"state"}],commands:[{name:"start"},{name:"stop"},{name:"reset"},{name:"pause"},{name:"resume"}]};_target;_injectedScheduler;_handle=null;_globalScheduler=null;_gen=0;_ready=Promise.resolve();_tick=0;_dt=0;_elapsed=0;_running=!1;_suspended=!1;_paused=!1;_lastTs=null;_repeat=0;_runStartTick=0;_visibilityDoc=null;constructor(t,e){super(),this._target=t??this,this._injectedScheduler=e??null}get tick(){return this._tick}get elapsed(){return this._elapsed}get dt(){return this._dt}get running(){return this._running}get suspended(){return this._suspended}get ready(){return this._ready}observe(){return null===this._visibilityDoc&&"undefined"!=typeof document&&(this._visibilityDoc=document,document.addEventListener("visibilitychange",this._onVisibilityChange),this._updateSuspended()),this._ready}dispose(){this._gen++,this.stop(),null!==this._visibilityDoc&&(this._visibilityDoc.removeEventListener("visibilitychange",this._onVisibilityChange),this._visibilityDoc=null)}_dispatchTick(t){this._target.dispatchEvent(new CustomEvent("wcs-raf:tick",{detail:{count:this._tick,elapsed:this._elapsed,dt:this._dt,timestamp:t},bubbles:!0}))}_setRunning(t){this._running!==t&&(this._running=t,this._target.dispatchEvent(new CustomEvent("wcs-raf:running-changed",{detail:t,bubbles:!0})),this._updateSuspended())}_setSuspended(t){this._suspended!==t&&(this._suspended=t,this._target.dispatchEvent(new CustomEvent("wcs-raf:suspended-changed",{detail:t,bubbles:!0})))}_updateSuspended(){const t=null!==this._visibilityDoc&&"hidden"===this._visibilityDoc.visibilityState;this._setSuspended(this._running&&t)}start(t={}){if(this._running)return;const e=this._resolveScheduler();null!==e&&(this._paused=!1,this._repeat="number"==typeof t.repeat&&t.repeat>0?t.repeat:0,this._gen++,this._setRunning(!0),this._runStartTick=this._tick,this._lastTs=null,this._running&&null===this._handle&&this._requestFrame(e))}stop(){this._clearHandle(),this._paused=!1,this._setRunning(!1)}reset(){this._clearHandle(),this._paused=!1,this._tick=0,this._elapsed=0,this._dt=0,this._lastTs=null,this._setRunning(!1),this._dispatchTick(0)}pause(){this._running&&!this._paused&&(this._clearHandle(),this._paused=!0,this._setRunning(!1))}resume(){if(!this._paused)return;const t=this._resolveScheduler();null!==t&&(this._paused=!1,this._gen++,this._setRunning(!0),this._lastTs=null,this._running&&null===this._handle&&this._requestFrame(t))}_frame=t=>{this._handle=null;const e=null===this._lastTs?0:t-this._lastTs;if(this._lastTs=t,this._tick++,this._dt=e,this._elapsed+=e,this._dispatchTick(t),this._repeat>0&&this._tick-this._runStartTick>=this._repeat)return this._clearHandle(),this._paused=!1,void this._setRunning(!1);if(this._running&&null===this._handle){const t=this._resolveScheduler();null!==t&&this._requestFrame(t)}};_onVisibilityChange=()=>{this._lastTs=null,this._updateSuspended()};_resolveScheduler(){if(null!==this._injectedScheduler)return this._injectedScheduler;const t=globalThis;return"function"!=typeof t.requestAnimationFrame||"function"!=typeof t.cancelAnimationFrame?null:(null===this._globalScheduler&&(this._globalScheduler={request:e=>t.requestAnimationFrame(e),cancel:e=>t.cancelAnimationFrame(e)}),this._globalScheduler)}_requestFrame(t){const e=this._gen;this._handle=t.request(t=>{e===this._gen&&this._frame(t)})}_clearHandle(){null!==this._handle&&(this._resolveScheduler()?.cancel(this._handle),this._handle=null,this._gen++)}}let u=!1;function c(t){const e=t.target;if(!(e instanceof Element))return;const s=e.closest(`[${i.triggerAttribute}]`);if(!s)return;const n=s.getAttribute(i.triggerAttribute);if(!n)return;const r=customElements.get(i.tagNames.raf),a=document.getElementById(n);r&&a instanceof r&&(t.preventDefault(),a.start())}function l(t,e){let s=Object.getPrototypeOf(t);for(;null!==s;){const t=Object.getOwnPropertyDescriptor(s,e);if(void 0!==t)return"function"==typeof t.get||"function"==typeof t.set;s=Object.getPrototypeOf(s)}return!1}class h extends HTMLElement{static hasConnectedCallbackPromise=!0;static wcBindable={...a.wcBindable,properties:[...a.wcBindable.properties,{name:"trigger",event:"wcs-raf:trigger-changed",semantics:"state"}],inputs:[{name:"once",attribute:"once"},{name:"repeat",attribute:"repeat"},{name:"manual",attribute:"manual"},{name:"trigger"}]};_core;_trigger=!1;_connectedCallbackPromise=Promise.resolve();_internals=null;constructor(){super(),this._core=new a(this),this._internals=this._initInternals(),this._wireStates({"wcs-raf:running-changed":t=>({running:!0===t}),"wcs-raf:suspended-changed":t=>({suspended:!0===t})})}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[s,n]of Object.entries(t))this.addEventListener(s,t=>{const s=this.hasAttribute("debug-states");for(const[i,r]of Object.entries(n(t.detail))){try{r?e.add(i):e.delete(i)}catch{}s&&this.toggleAttribute(`data-wcs-state-${i}`,r)}})}get connectedCallbackPromise(){return this._connectedCallbackPromise}get once(){return this.hasAttribute("once")}set once(t){t?this.setAttribute("once",""):this.removeAttribute("once")}get repeat(){const t=this.getAttribute("repeat");if(null===t||""===t.trim())return 0;const e=Number(t);return Number.isFinite(e)&&e>0?e:0}set repeat(t){this.setAttribute("repeat",String(t))}get manual(){return this.hasAttribute("manual")}set manual(t){t?this.setAttribute("manual",""):this.removeAttribute("manual")}get tick(){return this._core.tick}get elapsed(){return this._core.elapsed}get dt(){return this._core.dt}get running(){return this._core.running}get suspended(){return this._core.suspended}get trigger(){return this._trigger}set trigger(t){!!t&&(this._trigger=!0,this.start(),this._trigger=!1,this.dispatchEvent(new CustomEvent("wcs-raf:trigger-changed",{detail:!1,bubbles:!0})))}start(){const t=this.repeat>0?this.repeat:this.once?1:0;this._core.start({repeat:t})}stop(){this._core.stop()}reset(){this._core.reset()}pause(){this._core.pause()}resume(){this._core.resume()}connectedCallback(){!function(t){const e=t.constructor?.wcBindable,s=e?.inputs;if(void 0!==s)for(const e of s){const s=e.name;if(!Object.prototype.hasOwnProperty.call(t,s))continue;if(!l(t,s))continue;const n=t,i=n[s];delete n[s],n[s]=i}}(this),this.style.display="none",i.autoTrigger&&(u||(u=!0,document.addEventListener("click",c))),this._connectedCallbackPromise=this._core.observe(),this.manual||this.start()}disconnectedCallback(){this._core.dispose()}}function o(e){var s;e&&("boolean"==typeof(s=e).autoTrigger&&(t.autoTrigger=s.autoTrigger),"string"==typeof s.triggerAttribute&&(t.triggerAttribute=s.triggerAttribute),s.tagNames&&Object.assign(t.tagNames,s.tagNames),n=null),customElements.get(i.tagNames.raf)||customElements.define(i.tagNames.raf,h)}export{a as RafCore,h as WcsRaf,o as bootstrapRaf,r 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/RafCore.ts","../src/autoTrigger.ts","../src/components/Raf.ts","../src/bootstrapRaf.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n raf: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-raftarget\",\n tagNames: {\n raf: \"wcs-raf\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\n// Internal-only live handle to the mutable config. NOT part of the public API\n// (deliberately absent from exports.ts) — it is exported solely so sibling\n// modules in this package can read current settings cheaply. External consumers\n// must use getConfig() (returns a deep-frozen snapshot) / setConfig(). Mutating\n// this object directly bypasses the frozenConfig cache and is unsupported.\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (typeof partialConfig.autoTrigger === \"boolean\") {\n _config.autoTrigger = partialConfig.autoTrigger;\n }\n if (typeof partialConfig.triggerAttribute === \"string\") {\n _config.triggerAttribute = partialConfig.triggerAttribute;\n }\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { IWcBindable } from \"../types.js\";\n\nexport interface RafStartOptions {\n repeat?: number;\n}\n\n/**\n * Injectable frame scheduler. The default resolves\n * `globalThis.requestAnimationFrame` / `cancelAnimationFrame` AT CALL TIME\n * (async-io-node-guidelines §3.7); tests inject a fake that pumps frames with\n * explicit timestamps (the `dt` contract is timestamp-derived, so tests must\n * control the clock, not just the callback order).\n *\n * Contract: `request()` MUST return a non-null handle. The core uses `null`\n * as its internal \"not armed\" sentinel, so a scheduler returning literal\n * `null` would silently corrupt the handle bookkeeping (re-entrancy guards\n * and cancel tracking). Native rAF returns a long, so this only concerns\n * custom scheduler injections — return a number, object, or any other\n * non-nullish token.\n */\nexport interface RafScheduler {\n request(callback: (timestamp: number) => void): unknown;\n cancel(handle: unknown): void;\n}\n\n/**\n * Headless requestAnimationFrame primitive — `TimerCore`'s sibling with the\n * time source swapped from `setInterval` (a period) to rAF (the browser's\n * rendering opportunity). Exposed through the wc-bindable protocol: it streams\n * `tick` (frame counter), `elapsed` (accumulated ACTIVE milliseconds), `dt`\n * (delta to the previous frame) and the `running` / `suspended` pair, and is\n * driven by the `start` / `stop` / `reset` / `pause` / `resume` commands.\n *\n * `tick` / `elapsed` / `dt` are all surfaced via the single `wcs-raf:tick`\n * event (read through getters, mirroring how FetchCore exposes value/status\n * from one `wcs-fetch:response` event).\n *\n * Contracts specific to this node (docs/raf-tag-design.md):\n *\n * - **dt describes continuous running only.** The first frame after `start()`,\n * `resume()`, or a visibility interruption reports `dt = 0` — a value that\n * spans an interruption never reaches observers. Like `suspended`, the\n * visibility boundary is only detected once observe() has subscribed to\n * `visibilitychange`; a headless setup that skips observe() will see the\n * raw spanning delta on the first frame after a hidden gap. There is\n * deliberately NO upper clamp: how to treat a slow frame is the consumer's\n * domain decision.\n * - **elapsed is Σdt (active time).** Because interruption-spanning deltas are\n * normalized to 0, summing dt yields exactly the time frames were actually\n * being delivered — no separate segment bookkeeping is needed, and hidden /\n * paused periods contribute nothing. Granularity is one frame: between\n * frames the getter returns the value as of the last tick.\n * - **running / suspended are a desired/actual pair** (the wakelock split): in\n * a hidden tab the browser delivers no frames at all, so `running` (the\n * started intent) stays true while `suspended` reports that delivery is\n * actually stopped. `suspended` is only meaningful after `observe()` has\n * subscribed to `visibilitychange`; without a document it stays false.\n * - **No `error` surface.** rAF has no persistent failure mode; on a platform\n * without it, `start()` is a silent no-op (never-throw, resize precedent).\n */\nexport class RafCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"tick\", event: \"wcs-raf:tick\", getter: (e: Event) => (e as CustomEvent).detail.count },\n { name: \"elapsed\", event: \"wcs-raf:tick\", getter: (e: Event) => (e as CustomEvent).detail.elapsed },\n { name: \"dt\", event: \"wcs-raf:tick\", getter: (e: Event) => (e as CustomEvent).detail.dt },\n { name: \"running\", event: \"wcs-raf:running-changed\" },\n { name: \"suspended\", event: \"wcs-raf:suspended-changed\" },\n ],\n commands: [\n { name: \"start\" },\n { name: \"stop\" },\n { name: \"reset\" },\n { name: \"pause\" },\n { name: \"resume\" },\n ],\n };\n\n private _target: EventTarget;\n private _injectedScheduler: RafScheduler | null;\n private _handle: unknown = null;\n\n // Lazily-created wrapper around the global rAF pair, cached so the hot\n // frame-reschedule path (_frame, once per delivered frame) does not\n // allocate a new object + closures every call. `request`/`cancel` still\n // dereference `globalThis.requestAnimationFrame` / `cancelAnimationFrame`\n // live on every invocation (they are not snapshotted here), so call-time\n // resolution (§3.7) is unchanged — only the wrapper object itself is\n // reused once the global functions are first found present.\n private _globalScheduler: RafScheduler | null = null;\n\n // Generation guard (§3.4): a monotonic arming counter. Bumped when a run is\n // armed (start()/resume()), when an armed handle is cancelled\n // (_clearHandle()) and on dispose(). _requestFrame() captures the value in\n // each request's closure and drops the frame if it no longer matches the\n // live field when it fires. cancel() is best-effort against a non-compliant\n // scheduler; the captured generation is the guarantee — a stale callback can\n // neither mutate state, dispatch on a torn-down element, nor corrupt a\n // newer run's `_handle` bookkeeping. A live-field comparison (the previous\n // `_runGen` scheme) could not survive a dispose() → start() round trip: the\n // new start() re-synced the pair and let the stale callback through,\n // permanently doubling the frame loop.\n private _gen = 0;\n // SSR (§3.8): there is no asynchronous probe, so readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n private _tick: number = 0;\n private _dt: number = 0;\n private _elapsed: number = 0;\n private _running: boolean = false;\n private _suspended: boolean = false;\n private _paused: boolean = false;\n\n // Timestamp of the previous frame within the current continuous run.\n // `null` means \"the next frame starts a run segment\": its dt is reported as\n // 0 (the G3 normalization). Cleared at start()/resume() and on every\n // visibilitychange (an interruption boundary).\n private _lastTs: number | null = null;\n\n // `_tick` value captured at the start of the current run. `repeat` counts\n // frames *per run*, so the stop condition compares against this baseline\n // rather than the cumulative `_tick` (which only resets on reset()).\n private _repeat: number = 0;\n private _runStartTick: number = 0;\n\n // The document whose visibility drives `suspended`, subscribed in observe()\n // and released in dispose(). Null before observe() or in non-DOM\n // environments — `suspended` then simply stays false.\n private _visibilityDoc: Document | null = null;\n\n constructor(target?: EventTarget, scheduler?: RafScheduler) {\n super();\n this._target = target ?? this;\n this._injectedScheduler = scheduler ?? null;\n }\n\n get tick(): number {\n return this._tick;\n }\n\n get elapsed(): number {\n return this._elapsed;\n }\n\n get dt(): number {\n return this._dt;\n }\n\n get running(): boolean {\n return this._running;\n }\n\n get suspended(): boolean {\n return this._suspended;\n }\n\n // SSR readiness (§3.8): resolves after the first probe. There is nothing to\n // probe, so this is an already-resolved promise.\n get ready(): Promise<void> {\n return this._ready;\n }\n\n // Lifecycle (§3.5). observe() establishes the one ambient subscription this\n // node has — `visibilitychange`, which drives the `suspended` output and the\n // dt=0 normalization across a hidden period. Idempotent; a no-op without a\n // document (SSR pre-pass, worker). dispose() tears everything down and bumps\n // the generation so a frame already queued cannot fire onto a torn-down\n // element.\n observe(): Promise<void> {\n if (this._visibilityDoc === null && typeof document !== \"undefined\") {\n this._visibilityDoc = document;\n document.addEventListener(\"visibilitychange\", this._onVisibilityChange);\n // Sync `suspended` to the visibility state at subscription time: with a\n // start()-before-observe() ordering (headless Core usage) the document\n // may already be hidden, and waiting for the next visibilitychange\n // would report suspended=false until then. Same-value guarded, so the\n // common visible-at-observe case dispatches nothing.\n this._updateSuspended();\n }\n return this._ready;\n }\n\n dispose(): void {\n this._gen++;\n this.stop();\n if (this._visibilityDoc !== null) {\n this._visibilityDoc.removeEventListener(\"visibilitychange\", this._onVisibilityChange);\n this._visibilityDoc = null;\n }\n }\n\n // --- State setters with event dispatch ---\n\n private _dispatchTick(timestamp: number): void {\n this._target.dispatchEvent(new CustomEvent(\"wcs-raf:tick\", {\n detail: { count: this._tick, elapsed: this._elapsed, dt: this._dt, timestamp },\n bubbles: true,\n }));\n }\n\n private _setRunning(running: boolean): void {\n if (this._running === running) return;\n this._running = running;\n this._target.dispatchEvent(new CustomEvent(\"wcs-raf:running-changed\", {\n detail: running,\n bubbles: true,\n }));\n // `suspended` is derived from (running && hidden), so every running\n // transition re-evaluates it: stop/pause drop a suspension, and a start()\n // inside an already-hidden tab reports it immediately (honestly: no frame\n // will arrive until the tab is visible again).\n this._updateSuspended();\n }\n\n private _setSuspended(suspended: boolean): void {\n if (this._suspended === suspended) return;\n this._suspended = suspended;\n this._target.dispatchEvent(new CustomEvent(\"wcs-raf:suspended-changed\", {\n detail: suspended,\n bubbles: true,\n }));\n }\n\n private _updateSuspended(): void {\n const hidden = this._visibilityDoc !== null && this._visibilityDoc.visibilityState === \"hidden\";\n this._setSuspended(this._running && hidden);\n }\n\n // --- Public API ---\n\n start(options: RafStartOptions = {}): void {\n // Idempotent while running: a redundant start() must not stack a second\n // frame loop (which would double the tick rate). Reconfiguring an active\n // run is done via stop() + start().\n if (this._running) return;\n\n // Resolve the platform API at call time (§3.7). Absent rAF (SSR pre-pass,\n // worker) makes start() a silent no-op — never-throw, and this node has no\n // error surface by design.\n const scheduler = this._resolveScheduler();\n if (scheduler === null) return;\n\n // start() begins a fresh run, so clear any lingering pause from a prior\n // pause()-without-resume(). Without this, the loop would run while _paused\n // stayed true, leaving pause() a no-op and letting resume() overwrite the\n // live handle (leak + double fire).\n this._paused = false;\n\n // `repeat` is per-run intent, NOT persistent configuration: every start()\n // re-establishes it from the options, defaulting to \"unlimited\" when\n // omitted. This keeps a bare start() after a bounded run from silently\n // inheriting the old bounds.\n this._repeat = (typeof options.repeat === \"number\" && options.repeat > 0) ? options.repeat : 0;\n\n // New arming generation (§3.4): invalidates any callback still in flight\n // from a previous run (e.g. one whose cancel() a non-compliant scheduler\n // ignored). Bumped BEFORE the running-changed dispatch below, so that a\n // re-entrant restart from a listener arms with the newest generation —\n // the re-entrancy guard then keeps this outer call from arming (and\n // bumping) on top of it.\n this._gen++;\n\n this._setRunning(true);\n // Baseline this run's per-run repeat counting (set after _setRunning so a\n // re-start of a completed bounded run fires the full N frames again).\n this._runStartTick = this._tick;\n // G3: the first frame of a run reports dt = 0.\n this._lastTs = null;\n\n // Re-entrancy guard: _setRunning(true) just dispatched running-changed\n // synchronously, and a listener may have changed the world from inside it.\n // - `!_running`: the listener called stop()/pause()/dispose(). Without\n // this check a \"ghost\" frame would still be scheduled for an\n // already-stopped run — it would either tick once while running stays\n // false, or leave an uncancellable handle behind.\n // - `_handle !== null`: the listener restarted the loop itself\n // (stop()→start()); the inner start() already armed the new run, and\n // requesting again here would overwrite `_handle` (losing the inner\n // handle, never cancelled) and stack a permanent second frame loop.\n // On the normal path `_handle` is always null here — every transition\n // to `_running === false` clears it — so non-null can only mean a\n // re-entrant listener already scheduled the run for us.\n if (!this._running || this._handle !== null) return;\n this._requestFrame(scheduler);\n }\n\n stop(): void {\n this._clearHandle();\n this._paused = false;\n this._setRunning(false);\n }\n\n reset(): void {\n this._clearHandle();\n this._paused = false;\n this._tick = 0;\n this._elapsed = 0;\n this._dt = 0;\n this._lastTs = null;\n this._setRunning(false);\n // Notify observers that the counter/elapsed/dt have returned to zero. The\n // notification is not a frame, so `timestamp` is 0 (see WcsRafTickDetail).\n this._dispatchTick(0);\n }\n\n pause(): void {\n // Pause only a live loop; a no-op otherwise so it composes safely with the\n // declarative lifecycle. Unlike stop(), it records `_paused` so resume()\n // can tell an intentional pause from a full stop. No elapsed bookkeeping\n // is needed: elapsed is Σdt, and the resume boundary's dt is 0.\n if (!this._running || this._paused) return;\n this._clearHandle();\n this._paused = true;\n this._setRunning(false);\n }\n\n resume(): void {\n if (!this._paused) return;\n const scheduler = this._resolveScheduler();\n if (scheduler === null) return;\n this._paused = false;\n // New arming generation (§3.4), bumped before the running-changed\n // dispatch for the same re-entrancy reason as start().\n this._gen++;\n this._setRunning(true);\n // G3: the first frame after a pause reports dt = 0 (elapsed therefore does\n // not count the paused period — the \"active time\" contract).\n this._lastTs = null;\n\n // Re-entrancy guard, for the same reasons as start() (see the comment\n // there): a running-changed listener may have synchronously stopped this\n // node — or restarted it, leaving `_handle` already armed — from inside\n // _setRunning(true) above.\n if (!this._running || this._handle !== null) return;\n this._requestFrame(scheduler);\n }\n\n // --- Internal ---\n\n private _frame = (timestamp: number): void => {\n // Reached only through _requestFrame's generation-checked closure (§3.4):\n // a stale callback — disposed, cancelled by a non-compliant scheduler, or\n // superseded by a newer run — never gets here.\n this._handle = null;\n\n // dt: delta to the previous frame within this continuous run; 0 when this\n // frame opens a segment (start/resume/visibility boundary — G3).\n const dt = this._lastTs === null ? 0 : timestamp - this._lastTs;\n this._lastTs = timestamp;\n\n this._tick++;\n this._dt = dt;\n this._elapsed += dt;\n this._dispatchTick(timestamp);\n\n // Auto-stop once this run has fired the requested number of frames\n // (repeat=0 runs forever). Counted per-run via `_runStartTick`, so a\n // re-start after a completed bounded run fires N frames again. `once` is\n // expressed by the Shell as repeat=1.\n //\n // The cleanup mirrors stop() exactly, because a tick listener may have\n // synchronously paused — or paused and resumed — DURING the final frame's\n // dispatch above. The run's budget is exhausted either way, so clear the\n // pause (a later resume() must be a no-op, not an N+1th frame) and cancel\n // any handle a re-entrant resume() armed (it would otherwise survive as a\n // ghost frame and tick past the budget). On the normal path both are\n // already clear (no-ops). A stop()→start() restart is NOT affected: the\n // new run re-baselines `_runStartTick`, so this branch is not taken.\n if (this._repeat > 0 && (this._tick - this._runStartTick) >= this._repeat) {\n this._clearHandle();\n this._paused = false;\n this._setRunning(false);\n return;\n }\n\n // Re-request the next frame — unless a tick listener stopped the loop\n // synchronously during the dispatch above, or already scheduled a new run\n // itself (a synchronous stop()→start() / pause()→resume() restart leaves\n // _handle non-null; re-requesting on top of it would stack a permanent\n // second frame loop. The generation guard cannot catch this: a tail\n // request here would capture the restart's own — current — generation\n // and produce a second equally-valid loop).\n if (this._running && this._handle === null) {\n const scheduler = this._resolveScheduler();\n if (scheduler !== null) {\n this._requestFrame(scheduler);\n }\n }\n };\n\n private _onVisibilityChange = (): void => {\n // Either direction is an interruption boundary: entering hidden means the\n // browser stops delivering frames, so the NEXT delivered frame must not\n // report a delta spanning the gap (G3). Clearing on the visible edge too\n // is belt-and-braces for a missed hidden event — the worst case is one\n // extra dt=0 frame.\n this._lastTs = null;\n this._updateSuspended();\n };\n\n private _resolveScheduler(): RafScheduler | null {\n if (this._injectedScheduler !== null) return this._injectedScheduler;\n const g = globalThis as unknown as {\n requestAnimationFrame?: (cb: (ts: number) => void) => unknown;\n cancelAnimationFrame?: (handle: unknown) => void;\n };\n // The availability check itself still runs on every call (§3.7: resolved\n // at call time, not cached across an absence/presence flip).\n if (typeof g.requestAnimationFrame !== \"function\" || typeof g.cancelAnimationFrame !== \"function\") {\n return null;\n }\n if (this._globalScheduler === null) {\n // `g` is just a typed alias for `globalThis` (not a snapshot), so these\n // closures keep dereferencing the live global functions even though the\n // wrapper object itself is created only once.\n this._globalScheduler = {\n request: (cb) => g.requestAnimationFrame!(cb),\n cancel: (handle) => g.cancelAnimationFrame!(handle),\n };\n }\n return this._globalScheduler;\n }\n\n // Arm the next frame (§3.4). The callback closes over the generation\n // current at request time and re-checks it against the live `_gen` when the\n // frame arrives; a callback that outlived its run bails here. See the\n // `_gen` field comment for why this must be a per-request capture and not a\n // live-field comparison.\n private _requestFrame(scheduler: RafScheduler): void {\n const gen = this._gen;\n this._handle = scheduler.request((timestamp: number) => {\n if (gen !== this._gen) return;\n this._frame(timestamp);\n });\n }\n\n private _clearHandle(): void {\n if (this._handle !== null) {\n this._resolveScheduler()?.cancel(this._handle);\n this._handle = null;\n // Invalidate the cancelled callback's captured generation as well:\n // cancel() is best-effort against a non-compliant scheduler, the\n // generation is the guarantee (§3.4).\n this._gen++;\n }\n }\n}\n","import { config } from \"./config.js\";\nimport type { Raf } from \"./components/Raf.js\";\n\nlet registered = false;\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const rafId = triggerElement.getAttribute(config.triggerAttribute);\n if (!rafId) return;\n\n // Resolve the registered constructor at call time instead of importing Raf\n // as a value. The value import created a components/Raf.ts ⇄ autoTrigger.ts\n // cycle (Raf.connectedCallback() calls registerAutoTrigger()). instanceof\n // against the customElements registry keeps the exact same identity guarantee\n // — only the registered <wcs-raf> class matches — without the import cycle.\n const RafCtor = customElements.get(config.tagNames.raf);\n const rafElement = document.getElementById(rafId);\n if (!RafCtor || !(rafElement instanceof RafCtor)) return;\n\n // Suppress the element's default action so a loop can start without\n // navigating. Intentional: do not attach data-raftarget to an element whose\n // default action you also want (real <a href> link, form-submit button) — it\n // will be cancelled. See README \"Optional DOM Triggering\".\n event.preventDefault();\n (rafElement as Raf).start();\n}\n\nexport function registerAutoTrigger(): void {\n if (registered) return;\n registered = true;\n document.addEventListener(\"click\", handleClick);\n}\n\nexport function unregisterAutoTrigger(): void {\n if (!registered) return;\n registered = false;\n document.removeEventListener(\"click\", handleClick);\n}\n","import { config } from \"../config.js\";\nimport { IWcBindable } from \"../types.js\";\nimport { RafCore } from \"../core/RafCore.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\n\nexport class Raf extends HTMLElement {\n static hasConnectedCallbackPromise = true;\n static wcBindable: IWcBindable = {\n ...RafCore.wcBindable,\n properties: [\n ...RafCore.wcBindable.properties,\n { name: \"trigger\", event: \"wcs-raf:trigger-changed\" },\n ],\n // Shell-level settable surface. `attribute` is a purely descriptive hint\n // (per SPEC-extensions.md the binding core does not act on it) naming the\n // mirrored HTML attribute, matching <wcs-timer>. `trigger` is a momentary\n // command-property with no backing attribute, so it carries no hint.\n // `start` / `stop` / `reset` / `pause` / `resume` commands are inherited\n // from the Core above. Deliberately absent vs <wcs-timer>: `interval`\n // (rAF has no period) and `immediate` (the first frame already IS the\n // next rendering opportunity — no earlier meaningful moment exists).\n inputs: [\n { name: \"once\", attribute: \"once\" },\n { name: \"repeat\", attribute: \"repeat\" },\n { name: \"manual\", attribute: \"manual\" },\n { name: \"trigger\" },\n ],\n };\n\n private _core: RafCore;\n private _trigger: boolean = false;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new RafCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n \"wcs-raf:running-changed\": (d) => ({ running: d === true }),\n \"wcs-raf:suspended-changed\": (d) => ({ suspended: d === true }),\n });\n }\n\n // CSS state reflection (:state()) — debug-only snapshot getter. NOT part of\n // wc-bindable (not a bind target); see README \"CSS styling with :state()\".\n // MUST NOT return the live CustomStateSet (that would let callers write\n // states from outside, defeating the point of :state() being read-only).\n get debugStates(): string[] {\n return this._internals ? [...this._internals.states] : [];\n }\n\n private _initInternals(): ElementInternals | null {\n // never-throw (async-io-node-guidelines.md §3.6): attachInternals is absent\n // in happy-dom / older environments, and pre-125 Chromium rejects\n // non-dashed state names from states.add() (probed and discarded here).\n // Either case silently disables reflection — the component still works,\n // it just doesn't expose :state() selectors.\n try {\n if (typeof this.attachInternals !== \"function\") return null;\n const internals = this.attachInternals();\n internals.states.add(\"wcs-probe\");\n internals.states.delete(\"wcs-probe\");\n return internals;\n } catch {\n return null;\n }\n }\n\n private _wireStates(map: Record<string, (detail: any) => Record<string, boolean>>): void {\n if (this._internals === null) return;\n const states = this._internals.states;\n for (const [event, toStates] of Object.entries(map)) {\n this.addEventListener(event, (e) => {\n const debug = this.hasAttribute(\"debug-states\");\n for (const [name, on] of Object.entries(toStates((e as CustomEvent).detail))) {\n try {\n if (on) { states.add(name); } else { states.delete(name); }\n } catch { /* never-throw */ }\n if (debug) this.toggleAttribute(`data-wcs-state-${name}`, on);\n }\n });\n }\n }\n\n // SSR (§4.1/§4.4): the Shell exposes the Core's readiness so a server-side\n // renderer can await the connect-time probe before snapshotting. There is no\n // async probe here (observe() resolves immediately), but the contract is\n // uniform across IO nodes.\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Attribute accessors ---\n\n get once(): boolean {\n return this.hasAttribute(\"once\");\n }\n\n set once(value: boolean) {\n if (value) {\n this.setAttribute(\"once\", \"\");\n } else {\n this.removeAttribute(\"once\");\n }\n }\n\n get repeat(): number {\n const attr = this.getAttribute(\"repeat\");\n if (attr === null || attr.trim() === \"\") return 0;\n // Strict parse via Number() (\"3px\" -> NaN, not 3), matching <wcs-timer>.\n // Normalise any non-positive / non-numeric value to 0 (= unlimited).\n const parsed = Number(attr);\n return (Number.isFinite(parsed) && parsed > 0) ? parsed : 0;\n }\n\n set repeat(value: number) {\n this.setAttribute(\"repeat\", String(value));\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n // --- Core delegated getters ---\n\n get tick(): number {\n return this._core.tick;\n }\n\n get elapsed(): number {\n return this._core.elapsed;\n }\n\n get dt(): number {\n return this._core.dt;\n }\n\n get running(): boolean {\n return this._core.running;\n }\n\n get suspended(): boolean {\n return this._core.suspended;\n }\n\n // --- Command property ---\n\n get trigger(): boolean {\n return this._trigger;\n }\n\n set trigger(value: boolean) {\n // Momentary command-property: a false→true write starts the loop. Mirrors\n // <wcs-timer>. Prefer the command-token protocol (`command.start:\n // $command.begin`) for state-driven starts; this exists mainly for the DOM\n // click trigger and simple boolean bindings.\n const v = !!value;\n if (v) {\n this._trigger = true;\n this.start();\n this._trigger = false;\n // The `trigger-changed` event reports the momentary flag returning to\n // false, i.e. that the trigger property *changed* — it is deliberately\n // not gated on whether start() actually began a new run (same contract\n // as <wcs-timer>).\n this.dispatchEvent(new CustomEvent(\"wcs-raf:trigger-changed\", {\n detail: false,\n bubbles: true,\n }));\n }\n }\n\n // --- Commands ---\n\n start(): void {\n // `once` is sugar for \"fire exactly one frame\": map it to repeat=1, but\n // let an explicit repeat attribute win when both are present.\n const repeat = this.repeat > 0 ? this.repeat : (this.once ? 1 : 0);\n this._core.start({ repeat });\n }\n\n stop(): void {\n this._core.stop();\n }\n\n reset(): void {\n this._core.reset();\n }\n\n pause(): void {\n this._core.pause();\n }\n\n resume(): void {\n this._core.resume();\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n // Establish monitoring (§3.5): observe() subscribes visibilitychange (the\n // `suspended` output) and resolves once ready; expose it as\n // connectedCallbackPromise for SSR. Note for SSR pages: an auto-started\n // frame loop keeps scheduling — prefer `manual` in server-rendered markup\n // (see README).\n this._connectedCallbackPromise = this._core.observe();\n if (!this.manual) {\n this.start();\n }\n }\n\n disconnectedCallback(): void {\n // dispose() stops the loop, releases the visibility subscription and bumps\n // the generation so a frame already queued cannot fire onto a disconnected\n // element (§3.5 / §4.4).\n this._core.dispose();\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapRaf(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n","import { Raf } from \"./components/Raf.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.raf)) {\n customElements.define(config.tagNames.raf, Raf);\n }\n}\n"],"names":["_config","autoTrigger","triggerAttribute","tagNames","raf","deepFreeze","obj","Object","freeze","key","keys","deepClone","clone","frozenConfig","config","getConfig","RafCore","EventTarget","static","protocol","version","properties","name","event","getter","e","detail","count","elapsed","dt","commands","_target","_injectedScheduler","_handle","_globalScheduler","_gen","_ready","Promise","resolve","_tick","_dt","_elapsed","_running","_suspended","_paused","_lastTs","_repeat","_runStartTick","_visibilityDoc","constructor","target","scheduler","super","this","tick","running","suspended","ready","observe","document","addEventListener","_onVisibilityChange","_updateSuspended","dispose","stop","removeEventListener","_dispatchTick","timestamp","dispatchEvent","CustomEvent","bubbles","_setRunning","_setSuspended","hidden","visibilityState","start","options","_resolveScheduler","repeat","_requestFrame","_clearHandle","reset","pause","resume","_frame","g","globalThis","requestAnimationFrame","cancelAnimationFrame","request","cb","cancel","handle","gen","registered","handleClick","Element","triggerElement","closest","rafId","getAttribute","RafCtor","customElements","get","rafElement","getElementById","preventDefault","Raf","HTMLElement","wcBindable","inputs","attribute","_core","_trigger","_connectedCallbackPromise","_internals","_initInternals","_wireStates","d","debugStates","states","attachInternals","internals","add","delete","map","toStates","entries","debug","hasAttribute","on","toggleAttribute","connectedCallbackPromise","once","value","setAttribute","removeAttribute","attr","trim","parsed","Number","isFinite","String","manual","trigger","connectedCallback","style","display","disconnectedCallback","bootstrapRaf","userConfig","partialConfig","assign","define"],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.min.js","sources":["../src/config.ts","../src/core/RafCore.ts","../src/autoTrigger.ts","../src/protocol/upgradeProperties.ts","../src/components/Raf.ts","../src/bootstrapRaf.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n raf: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-raftarget\",\n tagNames: {\n raf: \"wcs-raf\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\n// Internal-only live handle to the mutable config. NOT part of the public API\n// (deliberately absent from exports.ts) — it is exported solely so sibling\n// modules in this package can read current settings cheaply. External consumers\n// must use getConfig() (returns a deep-frozen snapshot) / setConfig(). Mutating\n// this object directly bypasses the frozenConfig cache and is unsupported.\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (typeof partialConfig.autoTrigger === \"boolean\") {\n _config.autoTrigger = partialConfig.autoTrigger;\n }\n if (typeof partialConfig.triggerAttribute === \"string\") {\n _config.triggerAttribute = partialConfig.triggerAttribute;\n }\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { IWcBindable } from \"../types.js\";\n\nexport interface RafStartOptions {\n repeat?: number;\n}\n\n/**\n * Injectable frame scheduler. The default resolves\n * `globalThis.requestAnimationFrame` / `cancelAnimationFrame` AT CALL TIME\n * (async-io-node-guidelines §3.7); tests inject a fake that pumps frames with\n * explicit timestamps (the `dt` contract is timestamp-derived, so tests must\n * control the clock, not just the callback order).\n *\n * Contract: `request()` MUST return a non-null handle. The core uses `null`\n * as its internal \"not armed\" sentinel, so a scheduler returning literal\n * `null` would silently corrupt the handle bookkeeping (re-entrancy guards\n * and cancel tracking). Native rAF returns a long, so this only concerns\n * custom scheduler injections — return a number, object, or any other\n * non-nullish token.\n */\nexport interface RafScheduler {\n request(callback: (timestamp: number) => void): unknown;\n cancel(handle: unknown): void;\n}\n\n/**\n * Headless requestAnimationFrame primitive — `TimerCore`'s sibling with the\n * time source swapped from `setInterval` (a period) to rAF (the browser's\n * rendering opportunity). Exposed through the wc-bindable protocol: it streams\n * `tick` (frame counter), `elapsed` (accumulated ACTIVE milliseconds), `dt`\n * (delta to the previous frame) and the `running` / `suspended` pair, and is\n * driven by the `start` / `stop` / `reset` / `pause` / `resume` commands.\n *\n * `tick` / `elapsed` / `dt` are all surfaced via the single `wcs-raf:tick`\n * event (read through getters, mirroring how FetchCore exposes value/status\n * from one `wcs-fetch:response` event).\n *\n * Contracts specific to this node (docs/raf-tag-design.md):\n *\n * - **dt describes continuous running only.** The first frame after `start()`,\n * `resume()`, or a visibility interruption reports `dt = 0` — a value that\n * spans an interruption never reaches observers. Like `suspended`, the\n * visibility boundary is only detected once observe() has subscribed to\n * `visibilitychange`; a headless setup that skips observe() will see the\n * raw spanning delta on the first frame after a hidden gap. There is\n * deliberately NO upper clamp: how to treat a slow frame is the consumer's\n * domain decision.\n * - **elapsed is Σdt (active time).** Because interruption-spanning deltas are\n * normalized to 0, summing dt yields exactly the time frames were actually\n * being delivered — no separate segment bookkeeping is needed, and hidden /\n * paused periods contribute nothing. Granularity is one frame: between\n * frames the getter returns the value as of the last tick.\n * - **running / suspended are a desired/actual pair** (the wakelock split): in\n * a hidden tab the browser delivers no frames at all, so `running` (the\n * started intent) stays true while `suspended` reports that delivery is\n * actually stopped. `suspended` is only meaningful after `observe()` has\n * subscribed to `visibilitychange`; without a document it stays false.\n * - **No `error` surface.** rAF has no persistent failure mode; on a platform\n * without it, `start()` is a silent no-op (never-throw, resize precedent).\n */\nexport class RafCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"tick\", event: \"wcs-raf:tick\", semantics: \"state\", getter: (e: Event) => (e as CustomEvent).detail.count },\n { name: \"elapsed\", event: \"wcs-raf:tick\", semantics: \"state\", getter: (e: Event) => (e as CustomEvent).detail.elapsed },\n { name: \"dt\", event: \"wcs-raf:tick\", semantics: \"state\", getter: (e: Event) => (e as CustomEvent).detail.dt },\n { name: \"running\", event: \"wcs-raf:running-changed\", semantics: \"state\" },\n { name: \"suspended\", event: \"wcs-raf:suspended-changed\", semantics: \"state\" },\n ],\n commands: [\n { name: \"start\" },\n { name: \"stop\" },\n { name: \"reset\" },\n { name: \"pause\" },\n { name: \"resume\" },\n ],\n };\n\n private _target: EventTarget;\n private _injectedScheduler: RafScheduler | null;\n private _handle: unknown = null;\n\n // Lazily-created wrapper around the global rAF pair, cached so the hot\n // frame-reschedule path (_frame, once per delivered frame) does not\n // allocate a new object + closures every call. `request`/`cancel` still\n // dereference `globalThis.requestAnimationFrame` / `cancelAnimationFrame`\n // live on every invocation (they are not snapshotted here), so call-time\n // resolution (§3.7) is unchanged — only the wrapper object itself is\n // reused once the global functions are first found present.\n private _globalScheduler: RafScheduler | null = null;\n\n // Generation guard (§3.4): a monotonic arming counter. Bumped when a run is\n // armed (start()/resume()), when an armed handle is cancelled\n // (_clearHandle()) and on dispose(). _requestFrame() captures the value in\n // each request's closure and drops the frame if it no longer matches the\n // live field when it fires. cancel() is best-effort against a non-compliant\n // scheduler; the captured generation is the guarantee — a stale callback can\n // neither mutate state, dispatch on a torn-down element, nor corrupt a\n // newer run's `_handle` bookkeeping. A live-field comparison (the previous\n // `_runGen` scheme) could not survive a dispose() → start() round trip: the\n // new start() re-synced the pair and let the stale callback through,\n // permanently doubling the frame loop.\n private _gen = 0;\n // SSR (§3.8): there is no asynchronous probe, so readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n private _tick: number = 0;\n private _dt: number = 0;\n private _elapsed: number = 0;\n private _running: boolean = false;\n private _suspended: boolean = false;\n private _paused: boolean = false;\n\n // Timestamp of the previous frame within the current continuous run.\n // `null` means \"the next frame starts a run segment\": its dt is reported as\n // 0 (the G3 normalization). Cleared at start()/resume() and on every\n // visibilitychange (an interruption boundary).\n private _lastTs: number | null = null;\n\n // `_tick` value captured at the start of the current run. `repeat` counts\n // frames *per run*, so the stop condition compares against this baseline\n // rather than the cumulative `_tick` (which only resets on reset()).\n private _repeat: number = 0;\n private _runStartTick: number = 0;\n\n // The document whose visibility drives `suspended`, subscribed in observe()\n // and released in dispose(). Null before observe() or in non-DOM\n // environments — `suspended` then simply stays false.\n private _visibilityDoc: Document | null = null;\n\n constructor(target?: EventTarget, scheduler?: RafScheduler) {\n super();\n this._target = target ?? this;\n this._injectedScheduler = scheduler ?? null;\n }\n\n get tick(): number {\n return this._tick;\n }\n\n get elapsed(): number {\n return this._elapsed;\n }\n\n get dt(): number {\n return this._dt;\n }\n\n get running(): boolean {\n return this._running;\n }\n\n get suspended(): boolean {\n return this._suspended;\n }\n\n // SSR readiness (§3.8): resolves after the first probe. There is nothing to\n // probe, so this is an already-resolved promise.\n get ready(): Promise<void> {\n return this._ready;\n }\n\n // Lifecycle (§3.5). observe() establishes the one ambient subscription this\n // node has — `visibilitychange`, which drives the `suspended` output and the\n // dt=0 normalization across a hidden period. Idempotent; a no-op without a\n // document (SSR pre-pass, worker). dispose() tears everything down and bumps\n // the generation so a frame already queued cannot fire onto a torn-down\n // element.\n observe(): Promise<void> {\n if (this._visibilityDoc === null && typeof document !== \"undefined\") {\n this._visibilityDoc = document;\n document.addEventListener(\"visibilitychange\", this._onVisibilityChange);\n // Sync `suspended` to the visibility state at subscription time: with a\n // start()-before-observe() ordering (headless Core usage) the document\n // may already be hidden, and waiting for the next visibilitychange\n // would report suspended=false until then. Same-value guarded, so the\n // common visible-at-observe case dispatches nothing.\n this._updateSuspended();\n }\n return this._ready;\n }\n\n dispose(): void {\n this._gen++;\n this.stop();\n if (this._visibilityDoc !== null) {\n this._visibilityDoc.removeEventListener(\"visibilitychange\", this._onVisibilityChange);\n this._visibilityDoc = null;\n }\n }\n\n // --- State setters with event dispatch ---\n\n private _dispatchTick(timestamp: number): void {\n this._target.dispatchEvent(new CustomEvent(\"wcs-raf:tick\", {\n detail: { count: this._tick, elapsed: this._elapsed, dt: this._dt, timestamp },\n bubbles: true,\n }));\n }\n\n private _setRunning(running: boolean): void {\n if (this._running === running) return;\n this._running = running;\n this._target.dispatchEvent(new CustomEvent(\"wcs-raf:running-changed\", {\n detail: running,\n bubbles: true,\n }));\n // `suspended` is derived from (running && hidden), so every running\n // transition re-evaluates it: stop/pause drop a suspension, and a start()\n // inside an already-hidden tab reports it immediately (honestly: no frame\n // will arrive until the tab is visible again).\n this._updateSuspended();\n }\n\n private _setSuspended(suspended: boolean): void {\n if (this._suspended === suspended) return;\n this._suspended = suspended;\n this._target.dispatchEvent(new CustomEvent(\"wcs-raf:suspended-changed\", {\n detail: suspended,\n bubbles: true,\n }));\n }\n\n private _updateSuspended(): void {\n const hidden = this._visibilityDoc !== null && this._visibilityDoc.visibilityState === \"hidden\";\n this._setSuspended(this._running && hidden);\n }\n\n // --- Public API ---\n\n start(options: RafStartOptions = {}): void {\n // Idempotent while running: a redundant start() must not stack a second\n // frame loop (which would double the tick rate). Reconfiguring an active\n // run is done via stop() + start().\n if (this._running) return;\n\n // Resolve the platform API at call time (§3.7). Absent rAF (SSR pre-pass,\n // worker) makes start() a silent no-op — never-throw, and this node has no\n // error surface by design.\n const scheduler = this._resolveScheduler();\n if (scheduler === null) return;\n\n // start() begins a fresh run, so clear any lingering pause from a prior\n // pause()-without-resume(). Without this, the loop would run while _paused\n // stayed true, leaving pause() a no-op and letting resume() overwrite the\n // live handle (leak + double fire).\n this._paused = false;\n\n // `repeat` is per-run intent, NOT persistent configuration: every start()\n // re-establishes it from the options, defaulting to \"unlimited\" when\n // omitted. This keeps a bare start() after a bounded run from silently\n // inheriting the old bounds.\n this._repeat = (typeof options.repeat === \"number\" && options.repeat > 0) ? options.repeat : 0;\n\n // New arming generation (§3.4): invalidates any callback still in flight\n // from a previous run (e.g. one whose cancel() a non-compliant scheduler\n // ignored). Bumped BEFORE the running-changed dispatch below, so that a\n // re-entrant restart from a listener arms with the newest generation —\n // the re-entrancy guard then keeps this outer call from arming (and\n // bumping) on top of it.\n this._gen++;\n\n this._setRunning(true);\n // Baseline this run's per-run repeat counting (set after _setRunning so a\n // re-start of a completed bounded run fires the full N frames again).\n this._runStartTick = this._tick;\n // G3: the first frame of a run reports dt = 0.\n this._lastTs = null;\n\n // Re-entrancy guard: _setRunning(true) just dispatched running-changed\n // synchronously, and a listener may have changed the world from inside it.\n // - `!_running`: the listener called stop()/pause()/dispose(). Without\n // this check a \"ghost\" frame would still be scheduled for an\n // already-stopped run — it would either tick once while running stays\n // false, or leave an uncancellable handle behind.\n // - `_handle !== null`: the listener restarted the loop itself\n // (stop()→start()); the inner start() already armed the new run, and\n // requesting again here would overwrite `_handle` (losing the inner\n // handle, never cancelled) and stack a permanent second frame loop.\n // On the normal path `_handle` is always null here — every transition\n // to `_running === false` clears it — so non-null can only mean a\n // re-entrant listener already scheduled the run for us.\n if (!this._running || this._handle !== null) return;\n this._requestFrame(scheduler);\n }\n\n stop(): void {\n this._clearHandle();\n this._paused = false;\n this._setRunning(false);\n }\n\n reset(): void {\n this._clearHandle();\n this._paused = false;\n this._tick = 0;\n this._elapsed = 0;\n this._dt = 0;\n this._lastTs = null;\n this._setRunning(false);\n // Notify observers that the counter/elapsed/dt have returned to zero. The\n // notification is not a frame, so `timestamp` is 0 (see WcsRafTickDetail).\n this._dispatchTick(0);\n }\n\n pause(): void {\n // Pause only a live loop; a no-op otherwise so it composes safely with the\n // declarative lifecycle. Unlike stop(), it records `_paused` so resume()\n // can tell an intentional pause from a full stop. No elapsed bookkeeping\n // is needed: elapsed is Σdt, and the resume boundary's dt is 0.\n if (!this._running || this._paused) return;\n this._clearHandle();\n this._paused = true;\n this._setRunning(false);\n }\n\n resume(): void {\n if (!this._paused) return;\n const scheduler = this._resolveScheduler();\n if (scheduler === null) return;\n this._paused = false;\n // New arming generation (§3.4), bumped before the running-changed\n // dispatch for the same re-entrancy reason as start().\n this._gen++;\n this._setRunning(true);\n // G3: the first frame after a pause reports dt = 0 (elapsed therefore does\n // not count the paused period — the \"active time\" contract).\n this._lastTs = null;\n\n // Re-entrancy guard, for the same reasons as start() (see the comment\n // there): a running-changed listener may have synchronously stopped this\n // node — or restarted it, leaving `_handle` already armed — from inside\n // _setRunning(true) above.\n if (!this._running || this._handle !== null) return;\n this._requestFrame(scheduler);\n }\n\n // --- Internal ---\n\n private _frame = (timestamp: number): void => {\n // Reached only through _requestFrame's generation-checked closure (§3.4):\n // a stale callback — disposed, cancelled by a non-compliant scheduler, or\n // superseded by a newer run — never gets here.\n this._handle = null;\n\n // dt: delta to the previous frame within this continuous run; 0 when this\n // frame opens a segment (start/resume/visibility boundary — G3).\n const dt = this._lastTs === null ? 0 : timestamp - this._lastTs;\n this._lastTs = timestamp;\n\n this._tick++;\n this._dt = dt;\n this._elapsed += dt;\n this._dispatchTick(timestamp);\n\n // Auto-stop once this run has fired the requested number of frames\n // (repeat=0 runs forever). Counted per-run via `_runStartTick`, so a\n // re-start after a completed bounded run fires N frames again. `once` is\n // expressed by the Shell as repeat=1.\n //\n // The cleanup mirrors stop() exactly, because a tick listener may have\n // synchronously paused — or paused and resumed — DURING the final frame's\n // dispatch above. The run's budget is exhausted either way, so clear the\n // pause (a later resume() must be a no-op, not an N+1th frame) and cancel\n // any handle a re-entrant resume() armed (it would otherwise survive as a\n // ghost frame and tick past the budget). On the normal path both are\n // already clear (no-ops). A stop()→start() restart is NOT affected: the\n // new run re-baselines `_runStartTick`, so this branch is not taken.\n if (this._repeat > 0 && (this._tick - this._runStartTick) >= this._repeat) {\n this._clearHandle();\n this._paused = false;\n this._setRunning(false);\n return;\n }\n\n // Re-request the next frame — unless a tick listener stopped the loop\n // synchronously during the dispatch above, or already scheduled a new run\n // itself (a synchronous stop()→start() / pause()→resume() restart leaves\n // _handle non-null; re-requesting on top of it would stack a permanent\n // second frame loop. The generation guard cannot catch this: a tail\n // request here would capture the restart's own — current — generation\n // and produce a second equally-valid loop).\n if (this._running && this._handle === null) {\n const scheduler = this._resolveScheduler();\n if (scheduler !== null) {\n this._requestFrame(scheduler);\n }\n }\n };\n\n private _onVisibilityChange = (): void => {\n // Either direction is an interruption boundary: entering hidden means the\n // browser stops delivering frames, so the NEXT delivered frame must not\n // report a delta spanning the gap (G3). Clearing on the visible edge too\n // is belt-and-braces for a missed hidden event — the worst case is one\n // extra dt=0 frame.\n this._lastTs = null;\n this._updateSuspended();\n };\n\n private _resolveScheduler(): RafScheduler | null {\n if (this._injectedScheduler !== null) return this._injectedScheduler;\n const g = globalThis as unknown as {\n requestAnimationFrame?: (cb: (ts: number) => void) => unknown;\n cancelAnimationFrame?: (handle: unknown) => void;\n };\n // The availability check itself still runs on every call (§3.7: resolved\n // at call time, not cached across an absence/presence flip).\n if (typeof g.requestAnimationFrame !== \"function\" || typeof g.cancelAnimationFrame !== \"function\") {\n return null;\n }\n if (this._globalScheduler === null) {\n // `g` is just a typed alias for `globalThis` (not a snapshot), so these\n // closures keep dereferencing the live global functions even though the\n // wrapper object itself is created only once.\n this._globalScheduler = {\n request: (cb) => g.requestAnimationFrame!(cb),\n cancel: (handle) => g.cancelAnimationFrame!(handle),\n };\n }\n return this._globalScheduler;\n }\n\n // Arm the next frame (§3.4). The callback closes over the generation\n // current at request time and re-checks it against the live `_gen` when the\n // frame arrives; a callback that outlived its run bails here. See the\n // `_gen` field comment for why this must be a per-request capture and not a\n // live-field comparison.\n private _requestFrame(scheduler: RafScheduler): void {\n const gen = this._gen;\n this._handle = scheduler.request((timestamp: number) => {\n if (gen !== this._gen) return;\n this._frame(timestamp);\n });\n }\n\n private _clearHandle(): void {\n if (this._handle !== null) {\n this._resolveScheduler()?.cancel(this._handle);\n this._handle = null;\n // Invalidate the cancelled callback's captured generation as well:\n // cancel() is best-effort against a non-compliant scheduler, the\n // generation is the guarantee (§3.4).\n this._gen++;\n }\n }\n}\n","import { config } from \"./config.js\";\nimport type { Raf } from \"./components/Raf.js\";\n\nlet registered = false;\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const rafId = triggerElement.getAttribute(config.triggerAttribute);\n if (!rafId) return;\n\n // Resolve the registered constructor at call time instead of importing Raf\n // as a value. The value import created a components/Raf.ts ⇄ autoTrigger.ts\n // cycle (Raf.connectedCallback() calls registerAutoTrigger()). instanceof\n // against the customElements registry keeps the exact same identity guarantee\n // — only the registered <wcs-raf> class matches — without the import cycle.\n const RafCtor = customElements.get(config.tagNames.raf);\n const rafElement = document.getElementById(rafId);\n if (!RafCtor || !(rafElement instanceof RafCtor)) return;\n\n // Suppress the element's default action so a loop can start without\n // navigating. Intentional: do not attach data-raftarget to an element whose\n // default action you also want (real <a href> link, form-submit button) — it\n // will be cancelled. See README \"Optional DOM Triggering\".\n event.preventDefault();\n (rafElement as Raf).start();\n}\n\nexport function registerAutoTrigger(): void {\n if (registered) return;\n registered = true;\n document.addEventListener(\"click\", handleClick);\n}\n\nexport function unregisterAutoTrigger(): void {\n if (!registered) return;\n registered = false;\n document.removeEventListener(\"click\", handleClick);\n}\n","// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /protocol/upgrade-properties.ts by scripts/sync-protocol-types.mjs.\n// Run `node scripts/sync-protocol-types.mjs` after editing the source.\n// ===========================================================================\n\n// custom element の property upgrade — `static wcBindable.inputs` に宣言した入力のうち、\n// 要素が upgrade される前に代入された own データプロパティを取り込み直す。\n//\n// なぜ必要か:\n// 未定義タグの要素は素の HTMLElement なので、`el.url = \"...\"` は own データプロパティを作る。\n// upgrade 後にクラスの accessor が prototype へ入っても own プロパティが優先されるため、\n// setter は二度と呼ばれず、値は要素へ届かないまま消える(エラーも警告も出ない)。\n// 常にプロパティ代入を行う framework(Angular の `[prop]`、Lit の `.prop=`、\n// Solid の `prop:`、Vue の `.prop` 修飾子)× 遅延定義(autoloader / CDN / code-split)で\n// 常態的に起きる。docs/architecture-hardening/13-framework-adapter-binding-constraints.md §1.2。\n//\n// 安全側の判定:\n// own プロパティがあっても、prototype チェーンに accessor が無ければ「シャドウ」ではなく\n// その own プロパティ自体が正規の格納先なので触らない(public class field を壊さない)。\n//\n// SINGLE SOURCE OF TRUTH: edit only this file (/protocol/upgrade-properties.ts), then run\n// `node scripts/sync-protocol-types.mjs` to regenerate the per-package copies\n// (packages/<pkg>/src/protocol/upgradeProperties.ts). Those copies are generated — do not edit them.\nimport { IWcBindable } from \"./wcBindable.js\";\n\nfunction hasAccessorOnPrototype(target: object, name: string): boolean {\n let proto = Object.getPrototypeOf(target);\n while (proto !== null) {\n const descriptor = Object.getOwnPropertyDescriptor(proto, name);\n if (descriptor !== undefined) {\n return typeof descriptor.get === \"function\" || typeof descriptor.set === \"function\";\n }\n proto = Object.getPrototypeOf(proto);\n }\n return false;\n}\n\n/**\n * `connectedCallback` の先頭で呼ぶ。宣言済み input のうち upgrade 前の代入で\n * accessor をシャドウしている own プロパティを、delete → 再代入で setter に通し直す。\n *\n * - 冪等: 再代入は accessor を通るので own プロパティは残らず、2 回目以降は no-op。\n * - 宣言に `inputs` が無い要素、`wcBindable` を持たない要素では何もしない。\n * - 値の意味は変えない。今まで捨てられていた代入が届くようになる一方向の変化。\n */\nexport function upgradeProperties(element: object): void {\n const declaration = (element as { constructor?: { wcBindable?: IWcBindable } }).constructor?.wcBindable;\n const inputs = declaration?.inputs;\n if (inputs === undefined) return;\n for (const input of inputs) {\n const name = input.name;\n if (!Object.prototype.hasOwnProperty.call(element, name)) continue;\n if (!hasAccessorOnPrototype(element, name)) continue;\n const record = element as Record<string, unknown>;\n const value = record[name];\n delete record[name];\n record[name] = value;\n }\n}\n","import { config } from \"../config.js\";\nimport { IWcBindable } from \"../types.js\";\nimport { RafCore } from \"../core/RafCore.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\nimport { upgradeProperties } from \"../protocol/upgradeProperties.js\";\n\nexport class Raf extends HTMLElement {\n static hasConnectedCallbackPromise = true;\n static wcBindable: IWcBindable = {\n ...RafCore.wcBindable,\n properties: [\n ...RafCore.wcBindable.properties,\n { name: \"trigger\", event: \"wcs-raf:trigger-changed\", semantics: \"state\" },\n ],\n // Shell-level settable surface. `attribute` is a purely descriptive hint\n // (per SPEC-extensions.md the binding core does not act on it) naming the\n // mirrored HTML attribute, matching <wcs-timer>. `trigger` is a momentary\n // command-property with no backing attribute, so it carries no hint.\n // `start` / `stop` / `reset` / `pause` / `resume` commands are inherited\n // from the Core above. Deliberately absent vs <wcs-timer>: `interval`\n // (rAF has no period) and `immediate` (the first frame already IS the\n // next rendering opportunity — no earlier meaningful moment exists).\n inputs: [\n { name: \"once\", attribute: \"once\" },\n { name: \"repeat\", attribute: \"repeat\" },\n { name: \"manual\", attribute: \"manual\" },\n { name: \"trigger\" },\n ],\n };\n\n private _core: RafCore;\n private _trigger: boolean = false;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new RafCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n \"wcs-raf:running-changed\": (d) => ({ running: d === true }),\n \"wcs-raf:suspended-changed\": (d) => ({ suspended: d === true }),\n });\n }\n\n // CSS state reflection (:state()) — debug-only snapshot getter. NOT part of\n // wc-bindable (not a bind target); see README \"CSS styling with :state()\".\n // MUST NOT return the live CustomStateSet (that would let callers write\n // states from outside, defeating the point of :state() being read-only).\n get debugStates(): string[] {\n return this._internals ? [...this._internals.states] : [];\n }\n\n private _initInternals(): ElementInternals | null {\n // never-throw (async-io-node-guidelines.md §3.6): attachInternals is absent\n // in happy-dom / older environments, and pre-125 Chromium rejects\n // non-dashed state names from states.add() (probed and discarded here).\n // Either case silently disables reflection — the component still works,\n // it just doesn't expose :state() selectors.\n try {\n if (typeof this.attachInternals !== \"function\") return null;\n const internals = this.attachInternals();\n internals.states.add(\"wcs-probe\");\n internals.states.delete(\"wcs-probe\");\n return internals;\n } catch {\n return null;\n }\n }\n\n private _wireStates(map: Record<string, (detail: any) => Record<string, boolean>>): void {\n if (this._internals === null) return;\n const states = this._internals.states;\n for (const [event, toStates] of Object.entries(map)) {\n this.addEventListener(event, (e) => {\n const debug = this.hasAttribute(\"debug-states\");\n for (const [name, on] of Object.entries(toStates((e as CustomEvent).detail))) {\n try {\n if (on) { states.add(name); } else { states.delete(name); }\n } catch { /* never-throw */ }\n if (debug) this.toggleAttribute(`data-wcs-state-${name}`, on);\n }\n });\n }\n }\n\n // SSR (§4.1/§4.4): the Shell exposes the Core's readiness so a server-side\n // renderer can await the connect-time probe before snapshotting. There is no\n // async probe here (observe() resolves immediately), but the contract is\n // uniform across IO nodes.\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Attribute accessors ---\n\n get once(): boolean {\n return this.hasAttribute(\"once\");\n }\n\n set once(value: boolean) {\n if (value) {\n this.setAttribute(\"once\", \"\");\n } else {\n this.removeAttribute(\"once\");\n }\n }\n\n get repeat(): number {\n const attr = this.getAttribute(\"repeat\");\n if (attr === null || attr.trim() === \"\") return 0;\n // Strict parse via Number() (\"3px\" -> NaN, not 3), matching <wcs-timer>.\n // Normalise any non-positive / non-numeric value to 0 (= unlimited).\n const parsed = Number(attr);\n return (Number.isFinite(parsed) && parsed > 0) ? parsed : 0;\n }\n\n set repeat(value: number) {\n this.setAttribute(\"repeat\", String(value));\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n // --- Core delegated getters ---\n\n get tick(): number {\n return this._core.tick;\n }\n\n get elapsed(): number {\n return this._core.elapsed;\n }\n\n get dt(): number {\n return this._core.dt;\n }\n\n get running(): boolean {\n return this._core.running;\n }\n\n get suspended(): boolean {\n return this._core.suspended;\n }\n\n // --- Command property ---\n\n get trigger(): boolean {\n return this._trigger;\n }\n\n set trigger(value: boolean) {\n // Momentary command-property: a false→true write starts the loop. Mirrors\n // <wcs-timer>. Prefer the command-token protocol (`command.start:\n // $command.begin`) for state-driven starts; this exists mainly for the DOM\n // click trigger and simple boolean bindings.\n const v = !!value;\n if (v) {\n this._trigger = true;\n this.start();\n this._trigger = false;\n // The `trigger-changed` event reports the momentary flag returning to\n // false, i.e. that the trigger property *changed* — it is deliberately\n // not gated on whether start() actually began a new run (same contract\n // as <wcs-timer>).\n this.dispatchEvent(new CustomEvent(\"wcs-raf:trigger-changed\", {\n detail: false,\n bubbles: true,\n }));\n }\n }\n\n // --- Commands ---\n\n start(): void {\n // `once` is sugar for \"fire exactly one frame\": map it to repeat=1, but\n // let an explicit repeat attribute win when both are present.\n const repeat = this.repeat > 0 ? this.repeat : (this.once ? 1 : 0);\n this._core.start({ repeat });\n }\n\n stop(): void {\n this._core.stop();\n }\n\n reset(): void {\n this._core.reset();\n }\n\n pause(): void {\n this._core.pause();\n }\n\n resume(): void {\n this._core.resume();\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n // upgrade 前に代入された input を取り込み直す(doc 13 §1.2 / Phase A1)\n upgradeProperties(this);\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n // Establish monitoring (§3.5): observe() subscribes visibilitychange (the\n // `suspended` output) and resolves once ready; expose it as\n // connectedCallbackPromise for SSR. Note for SSR pages: an auto-started\n // frame loop keeps scheduling — prefer `manual` in server-rendered markup\n // (see README).\n this._connectedCallbackPromise = this._core.observe();\n if (!this.manual) {\n this.start();\n }\n }\n\n disconnectedCallback(): void {\n // dispose() stops the loop, releases the visibility subscription and bumps\n // the generation so a frame already queued cannot fire onto a disconnected\n // element (§3.5 / §4.4).\n this._core.dispose();\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapRaf(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n","import { Raf } from \"./components/Raf.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.raf)) {\n customElements.define(config.tagNames.raf, Raf);\n }\n}\n"],"names":["_config","autoTrigger","triggerAttribute","tagNames","raf","deepFreeze","obj","Object","freeze","key","keys","deepClone","clone","frozenConfig","config","getConfig","RafCore","EventTarget","static","protocol","version","properties","name","event","semantics","getter","e","detail","count","elapsed","dt","commands","_target","_injectedScheduler","_handle","_globalScheduler","_gen","_ready","Promise","resolve","_tick","_dt","_elapsed","_running","_suspended","_paused","_lastTs","_repeat","_runStartTick","_visibilityDoc","constructor","target","scheduler","super","this","tick","running","suspended","ready","observe","document","addEventListener","_onVisibilityChange","_updateSuspended","dispose","stop","removeEventListener","_dispatchTick","timestamp","dispatchEvent","CustomEvent","bubbles","_setRunning","_setSuspended","hidden","visibilityState","start","options","_resolveScheduler","repeat","_requestFrame","_clearHandle","reset","pause","resume","_frame","g","globalThis","requestAnimationFrame","cancelAnimationFrame","request","cb","cancel","handle","gen","registered","handleClick","Element","triggerElement","closest","rafId","getAttribute","RafCtor","customElements","get","rafElement","getElementById","preventDefault","hasAccessorOnPrototype","proto","getPrototypeOf","descriptor","getOwnPropertyDescriptor","undefined","set","Raf","HTMLElement","wcBindable","inputs","attribute","_core","_trigger","_connectedCallbackPromise","_internals","_initInternals","_wireStates","d","debugStates","states","attachInternals","internals","add","delete","map","toStates","entries","debug","hasAttribute","on","toggleAttribute","connectedCallbackPromise","once","value","setAttribute","removeAttribute","attr","trim","parsed","Number","isFinite","String","manual","trigger","connectedCallback","element","declaration","input","prototype","hasOwnProperty","call","record","upgradeProperties","style","display","disconnectedCallback","bootstrapRaf","userConfig","partialConfig","assign","define"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wcstack/raf",
3
- "version": "1.22.6",
3
+ "version": "1.24.0",
4
4
  "description": "Declarative requestAnimationFrame component for Web Components. Framework-agnostic frame-source primitive (tick/dt/suspended) via wc-bindable-protocol.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.esm.js",