@wcstack/debounce 1.13.1 → 1.15.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/dist/index.d.ts CHANGED
@@ -1,3 +1,24 @@
1
+ interface IWcBindableProperty {
2
+ readonly name: string;
3
+ readonly event: string;
4
+ readonly getter?: (event: Event) => any;
5
+ }
6
+ interface IWcBindableInput {
7
+ readonly name: string;
8
+ readonly attribute?: string;
9
+ }
10
+ interface IWcBindableCommand {
11
+ readonly name: string;
12
+ readonly async?: boolean;
13
+ }
14
+ interface IWcBindable {
15
+ readonly protocol: "wc-bindable";
16
+ readonly version: 1;
17
+ readonly properties: readonly IWcBindableProperty[];
18
+ readonly inputs?: readonly IWcBindableInput[];
19
+ readonly commands?: readonly IWcBindableCommand[];
20
+ }
21
+
1
22
  interface ITagNames {
2
23
  readonly debounce: string;
3
24
  readonly throttle: string;
@@ -16,26 +37,7 @@ interface IWritableConfig {
16
37
  triggerAttribute?: string;
17
38
  tagNames?: IWritableTagNames;
18
39
  }
19
- interface IWcBindableProperty {
20
- readonly name: string;
21
- readonly event: string;
22
- readonly getter?: (event: Event) => any;
23
- }
24
- interface IWcBindableInput {
25
- readonly name: string;
26
- readonly attribute?: string;
27
- }
28
- interface IWcBindableCommand {
29
- readonly name: string;
30
- readonly async?: boolean;
31
- }
32
- interface IWcBindable {
33
- readonly protocol: "wc-bindable";
34
- readonly version: number;
35
- readonly properties: IWcBindableProperty[];
36
- readonly inputs?: IWcBindableInput[];
37
- readonly commands?: IWcBindableCommand[];
38
- }
40
+
39
41
  /**
40
42
  * Tuning options for {@link DebounceCore}. Mirrors lodash's `debounce` knobs.
41
43
  * - `wait`: quiet period (ms) the signal must be idle before a trailing fire.
@@ -66,7 +68,7 @@ interface WcsDebounceFiredDetail {
66
68
  }
67
69
  /**
68
70
  * Value types for DebounceCore (headless) — the observable state properties.
69
- * Use with `bind()` from `@wc-bindable/core` for compile-time type checking.
71
+ * Use with `bind()` from `a wc-bindable binding core` for compile-time type checking.
70
72
  */
71
73
  interface WcsDebounceCoreValues {
72
74
  value: any;
@@ -132,13 +134,19 @@ declare class DebounceCore extends EventTarget {
132
134
  private _lastCallTime;
133
135
  private _lastInvokeTime;
134
136
  private _timerId;
137
+ private _timerGen;
135
138
  private _pendingKind;
136
139
  private _pendingValue;
137
140
  private _pendingArgs;
138
141
  private _value;
139
142
  private _lastArgs;
140
143
  private _pending;
144
+ private _gen;
145
+ private _ready;
141
146
  constructor(prefix?: string, target?: EventTarget, options?: DebounceOptions);
147
+ get ready(): Promise<void>;
148
+ observe(): Promise<void>;
149
+ dispose(): void;
142
150
  /**
143
151
  * Update the tuning knobs. The Shell calls this with the element's current
144
152
  * attributes before each schedule, so live attribute edits take effect on the
@@ -170,6 +178,7 @@ declare class DebounceCore extends EventTarget {
170
178
  private _invoke;
171
179
  private _setPending;
172
180
  private _dispatch;
181
+ private _armTimer;
173
182
  private _clearTimer;
174
183
  }
175
184
 
@@ -202,7 +211,9 @@ declare class Debounce extends HTMLElement {
202
211
  static wcBindable: IWcBindable;
203
212
  protected _core: DebounceCore;
204
213
  private _source;
214
+ private _connectedCallbackPromise;
205
215
  constructor();
216
+ get connectedCallbackPromise(): Promise<void>;
206
217
  get wait(): number;
207
218
  set wait(value: number);
208
219
  get leading(): boolean;
package/dist/index.esm.js CHANGED
@@ -122,6 +122,9 @@ class DebounceCore extends EventTarget {
122
122
  _lastCallTime = undefined;
123
123
  _lastInvokeTime = 0;
124
124
  _timerId = null;
125
+ // Generation stamped onto the live timer at arm time, compared in
126
+ // `_timerExpired` against `_gen` to drop callbacks that outlived a dispose().
127
+ _timerGen = 0;
125
128
  // Last-wins pending payload. `_pendingKind === null` doubles as the "consumed /
126
129
  // empty" sentinel (lodash clears `lastArgs` in invokeFunc): a trailing edge with
127
130
  // no fresh call since the last fire sees `null` and does not re-fire, which is
@@ -133,6 +136,15 @@ class DebounceCore extends EventTarget {
133
136
  _value = undefined;
134
137
  _lastArgs = [];
135
138
  _pending = false;
139
+ // Generation guard (§3.4): bumped on dispose() so a timer that survives a
140
+ // tear-down can no longer settle into a detached element. A pending timer is
141
+ // also cleared by dispose() → cancel(), so the guard is defensive: it stops
142
+ // any callback that has already been dequeued by the host event loop from
143
+ // writing state after dispose().
144
+ _gen = 0;
145
+ // SSR (§3.8): the debounce engine is purely timer-driven with no asynchronous
146
+ // probe to await, so readiness is immediate.
147
+ _ready = Promise.resolve();
136
148
  constructor(prefix = "wcs-debounce", target, options) {
137
149
  super();
138
150
  this._prefix = prefix;
@@ -141,6 +153,22 @@ class DebounceCore extends EventTarget {
141
153
  this.configure(options);
142
154
  }
143
155
  }
156
+ // --- Lifecycle (§3.5 / §3.8) ---
157
+ get ready() {
158
+ return this._ready;
159
+ }
160
+ // Debounce is command-driven (setSource / trigger schedule work on demand)
161
+ // with no subscription to establish, so observe() is an idempotent no-op that
162
+ // resolves once ready.
163
+ observe() {
164
+ return this._ready;
165
+ }
166
+ // Tear down the pending timer and invalidate the generation so a stale timer
167
+ // callback cannot fire after the element is detached.
168
+ dispose() {
169
+ this._gen++;
170
+ this.cancel();
171
+ }
144
172
  // --- Configuration ---
145
173
  /**
146
174
  * Update the tuning knobs. The Shell calls this with the element's current
@@ -240,13 +268,13 @@ class DebounceCore extends EventTarget {
240
268
  // same) — overwriting `_timerId` without clearing would orphan the old
241
269
  // timer and let it fire spuriously later.
242
270
  this._clearTimer();
243
- this._timerId = setTimeout(this._timerExpired, this._wait);
271
+ this._armTimer(this._wait);
244
272
  this._invoke(now);
245
273
  return;
246
274
  }
247
275
  }
248
276
  if (this._timerId === null) {
249
- this._timerId = setTimeout(this._timerExpired, this._wait);
277
+ this._armTimer(this._wait);
250
278
  }
251
279
  }
252
280
  _shouldInvoke(now) {
@@ -267,6 +295,11 @@ class DebounceCore extends EventTarget {
267
295
  : timeWaiting;
268
296
  }
269
297
  _timerExpired = () => {
298
+ // §3.4 generation guard: a timer dequeued by the host before dispose() could
299
+ // clear it must not settle into a torn-down element. Capture the generation
300
+ // when the timer is scheduled (via `_armTimer`) and bail if it is stale.
301
+ if (this._timerGen !== this._gen)
302
+ return;
270
303
  const now = Date.now();
271
304
  if (this._shouldInvoke(now)) {
272
305
  this._trailingEdge(now);
@@ -274,11 +307,11 @@ class DebounceCore extends EventTarget {
274
307
  }
275
308
  // Fired before the quiet period elapsed (a later call moved the deadline) —
276
309
  // re-arm for the remaining time instead of settling now.
277
- this._timerId = setTimeout(this._timerExpired, this._remainingWait(now));
310
+ this._armTimer(this._remainingWait(now));
278
311
  };
279
312
  _leadingEdge(now) {
280
313
  this._lastInvokeTime = now;
281
- this._timerId = setTimeout(this._timerExpired, this._wait);
314
+ this._armTimer(this._wait);
282
315
  if (this._leading) {
283
316
  this._invoke(now);
284
317
  }
@@ -319,6 +352,12 @@ class DebounceCore extends EventTarget {
319
352
  _dispatch(type, detail) {
320
353
  this._target.dispatchEvent(new CustomEvent(type, { detail, bubbles: true }));
321
354
  }
355
+ // Arm the settle timer, stamping the current generation so a callback that the
356
+ // host dequeues after a dispose() can detect it is stale (§3.4).
357
+ _armTimer(delay) {
358
+ this._timerGen = this._gen;
359
+ this._timerId = setTimeout(this._timerExpired, delay);
360
+ }
322
361
  _clearTimer() {
323
362
  if (this._timerId !== null) {
324
363
  clearTimeout(this._timerId);
@@ -369,7 +408,7 @@ const DEFAULT_WAIT = 250;
369
408
  * subclasses this with `"wcs-throttle"` and throttle defaults.
370
409
  */
371
410
  class Debounce extends HTMLElement {
372
- static hasConnectedCallbackPromise = false;
411
+ static hasConnectedCallbackPromise = true;
373
412
  static eventPrefix = "wcs-debounce";
374
413
  static wcBindable = {
375
414
  protocol: "wc-bindable",
@@ -396,10 +435,14 @@ class Debounce extends HTMLElement {
396
435
  };
397
436
  _core;
398
437
  _source = undefined;
438
+ _connectedCallbackPromise = Promise.resolve();
399
439
  constructor() {
400
440
  super();
401
441
  this._core = new DebounceCore(this.constructor.eventPrefix, this);
402
442
  }
443
+ get connectedCallbackPromise() {
444
+ return this._connectedCallbackPromise;
445
+ }
403
446
  // --- Attribute accessors ---
404
447
  get wait() {
405
448
  const attr = this.getAttribute("wait");
@@ -508,10 +551,14 @@ class Debounce extends HTMLElement {
508
551
  if (config.autoTrigger) {
509
552
  registerAutoTrigger();
510
553
  }
554
+ // §4.1/§4.4 Shell SSR: expose connectedCallbackPromise backed by observe().
555
+ // observe() is a no-op resolving once ready (the engine is command-driven).
556
+ this._connectedCallbackPromise = this._core.observe();
511
557
  }
512
558
  disconnectedCallback() {
513
- // Drop any in-flight timer so a detached element leaks nothing.
514
- this._core.cancel();
559
+ // Drop any in-flight timer so a detached element leaks nothing, and bump the
560
+ // Core generation so a surviving timer callback cannot settle (§3.5).
561
+ this._core.dispose();
515
562
  }
516
563
  }
517
564
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/config.ts","../src/wcBindableFactory.ts","../src/core/DebounceCore.ts","../src/autoTrigger.ts","../src/components/Debounce.ts","../src/components/Throttle.ts","../src/registerComponents.ts","../src/bootstrapDebounce.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n debounce: string;\n throttle: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-debouncetarget\",\n tagNames: {\n debounce: \"wcs-debounce\",\n throttle: \"wcs-throttle\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (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 { IWcBindableProperty } from \"./types.js\";\n\n/**\n * Build the wc-bindable `properties` list for a debounce/throttle element, with\n * every event name derived from a single `prefix`. `<wcs-debounce>` uses\n * `\"wcs-debounce\"`, `<wcs-throttle>` uses `\"wcs-throttle\"`, so the two tags share\n * one engine (DebounceCore) yet advertise distinct event namespaces from one\n * source of truth — no hand-duplicated property tables (cf. the geolocation Shell\n * which overrode its wcBindable by hand).\n *\n * - `value` — the debounced value of the latest `source` write (value surface),\n * read from the `<prefix>:settled` event.\n * - `fired` — the coalesced args of the latest `trigger()` pulse (signal\n * surface), read from the `<prefix>:fired` event. Declared as a\n * property (not just an event) so state can subscribe via the\n * event-token protocol (`eventToken.fired: <name>`).\n * - `pending` — whether a debounce is currently in flight.\n */\nexport function makeDebounceProperties(prefix: string): IWcBindableProperty[] {\n return [\n { name: \"value\", event: `${prefix}:settled`, getter: (e: Event) => (e as CustomEvent).detail.value },\n { name: \"fired\", event: `${prefix}:fired`, getter: (e: Event) => (e as CustomEvent).detail.args },\n { name: \"pending\", event: `${prefix}:pending-changed` },\n ];\n}\n","import { IWcBindable, DebounceOptions } from \"../types.js\";\nimport { makeDebounceProperties } from \"../wcBindableFactory.js\";\n\ntype PendingKind = \"value\" | \"signal\" | null;\n\n/**\n * Headless debounce/throttle primitive. A framework-agnostic port of lodash's\n * `debounce` algorithm (`shouldInvoke` / `leadingEdge` / `trailingEdge` /\n * `remainingWait`, timed via `Date.now()`), exposed through the wc-bindable\n * protocol.\n *\n * It coalesces a stream of *signals* and emits at most one per quiet period.\n * Two surfaces share the single timer:\n *\n * - **value** — writing {@link setSource} schedules a settle; on fire the\n * debounced value is published via the `<prefix>:settled` event and the\n * `value` getter. Wire it as `source: src; value: debounced`.\n * - **signal** — calling {@link trigger}`(...args)` coalesces a burst of pulses;\n * on fire one `<prefix>:fired` event carries the latest args (relayed by state\n * through the command-token / event-token protocols).\n *\n * A given instance is meant to be used for one surface at a time. Because each\n * surface keeps its own field (`_value` vs `_lastArgs`), the getters never\n * pollute each other; if both are driven on one instance the *last* scheduled\n * signal wins (lodash's last-args semantics).\n *\n * Throttle is the same engine with `maxWait === wait` (and `leading` on by\n * default), so `<wcs-throttle>` reuses this class with a different `eventPrefix`.\n */\nexport class DebounceCore extends EventTarget {\n // The static contract advertises the *default* `wcs-debounce:*` event names. A\n // headless Core constructed with a non-default `eventPrefix` (e.g.\n // `\"wcs-throttle\"`) dispatches under that prefix, so its events won't match\n // this metadata — rebuild the property table with `makeDebounceProperties(prefix)`\n // for that case. (The `<wcs-throttle>` Shell already overrides its own\n // `wcBindable` this way, so binding through an element is always consistent.)\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: makeDebounceProperties(\"wcs-debounce\"),\n commands: [\n { name: \"trigger\" },\n { name: \"cancel\" },\n { name: \"flush\" },\n ],\n };\n\n private readonly _prefix: string;\n private _target: EventTarget;\n\n // Tuning (lodash knobs).\n private _wait: number = 0;\n private _leading: boolean = false;\n private _trailing: boolean = true;\n private _maxWait: number = 0;\n private _hasMaxWait: boolean = false;\n\n // Timing bookkeeping.\n private _lastCallTime: number | undefined = undefined;\n private _lastInvokeTime: number = 0;\n private _timerId: ReturnType<typeof setTimeout> | null = null;\n\n // Last-wins pending payload. `_pendingKind === null` doubles as the \"consumed /\n // empty\" sentinel (lodash clears `lastArgs` in invokeFunc): a trailing edge with\n // no fresh call since the last fire sees `null` and does not re-fire, which is\n // what stops a single leading pulse from also firing on the trailing edge.\n private _pendingKind: PendingKind = null;\n private _pendingValue: any = undefined;\n private _pendingArgs: any[] | undefined = undefined;\n\n // Observable state (getter backing).\n private _value: any = undefined;\n private _lastArgs: any[] = [];\n private _pending: boolean = false;\n\n constructor(prefix: string = \"wcs-debounce\", target?: EventTarget, options?: DebounceOptions) {\n super();\n this._prefix = prefix;\n this._target = target ?? this;\n if (options) {\n this.configure(options);\n }\n }\n\n // --- Configuration ---\n\n /**\n * Update the tuning knobs. The Shell calls this with the element's current\n * attributes before each schedule, so live attribute edits take effect on the\n * next signal. `maxWait` is clamped to at least `wait` (lodash semantics); an\n * absent / invalid `maxWait` disables maxWait entirely.\n */\n configure(options: DebounceOptions = {}): void {\n if (typeof options.wait === \"number\" && Number.isFinite(options.wait) && options.wait >= 0) {\n this._wait = options.wait;\n }\n if (typeof options.leading === \"boolean\") {\n this._leading = options.leading;\n }\n if (typeof options.trailing === \"boolean\") {\n this._trailing = options.trailing;\n }\n const mw = options.maxWait;\n if (typeof mw === \"number\" && Number.isFinite(mw) && mw >= 0) {\n this._maxWait = Math.max(mw, this._wait);\n this._hasMaxWait = true;\n } else {\n this._maxWait = 0;\n this._hasMaxWait = false;\n }\n }\n\n // --- Observable getters ---\n\n get value(): any {\n return this._value;\n }\n\n get fired(): any[] {\n return this._lastArgs;\n }\n\n get pending(): boolean {\n return this._pending;\n }\n\n // --- Public entry points ---\n\n /** Value surface: schedule a settle carrying `value` (last write wins). */\n setSource(value: any): void {\n this._schedule(\"value\", value, undefined);\n }\n\n /** Signal surface: coalesce a pulse carrying `args` (last call wins). */\n trigger(...args: any[]): void {\n this._schedule(\"signal\", undefined, args);\n }\n\n /** Drop any pending fire without emitting. Getters keep their last values. */\n cancel(): void {\n this._clearTimer();\n this._lastInvokeTime = 0;\n this._lastCallTime = undefined;\n this._pendingKind = null;\n this._pendingValue = undefined;\n this._pendingArgs = undefined;\n this._setPending(false);\n }\n\n /**\n * Emit any buffered payload immediately, then clear pending. Unlike lodash's\n * `flush` (which honours `trailing`), this fires whatever is buffered — the\n * command's intent is \"publish now\" — but is a no-op when nothing is pending.\n */\n flush(): void {\n if (this._timerId === null && this._pendingKind === null) return;\n const now = Date.now();\n this._clearTimer();\n if (this._pendingKind !== null) {\n this._invoke(now);\n }\n this._pendingKind = null;\n this._pendingValue = undefined;\n this._pendingArgs = undefined;\n this._setPending(false);\n }\n\n // --- Engine (lodash port) ---\n\n private _schedule(kind: Exclude<PendingKind, null>, value: any, args: any[] | undefined): void {\n const now = Date.now();\n const isInvoking = this._shouldInvoke(now);\n\n this._pendingKind = kind;\n if (kind === \"value\") {\n this._pendingValue = value;\n } else {\n this._pendingArgs = args;\n }\n this._lastCallTime = now;\n this._setPending(true);\n\n if (isInvoking) {\n if (this._timerId === null) {\n this._leadingEdge(now);\n return;\n }\n if (this._hasMaxWait) {\n // Continuous input that has reached maxWait: restart the steady timer and\n // invoke now so a fire happens at least every maxWait ms (throttle path).\n // Clear the pending handle first (lodash's \"tight loop\" branch does the\n // same) — overwriting `_timerId` without clearing would orphan the old\n // timer and let it fire spuriously later.\n this._clearTimer();\n this._timerId = setTimeout(this._timerExpired, this._wait);\n this._invoke(now);\n return;\n }\n }\n if (this._timerId === null) {\n this._timerId = setTimeout(this._timerExpired, this._wait);\n }\n }\n\n private _shouldInvoke(now: number): boolean {\n if (this._lastCallTime === undefined) return true;\n const timeSinceLastCall = now - this._lastCallTime;\n const timeSinceLastInvoke = now - this._lastInvokeTime;\n return (\n timeSinceLastCall >= this._wait ||\n timeSinceLastCall < 0 ||\n (this._hasMaxWait && timeSinceLastInvoke >= this._maxWait)\n );\n }\n\n private _remainingWait(now: number): number {\n const timeSinceLastCall = now - (this._lastCallTime as number);\n const timeSinceLastInvoke = now - this._lastInvokeTime;\n const timeWaiting = this._wait - timeSinceLastCall;\n return this._hasMaxWait\n ? Math.min(timeWaiting, this._maxWait - timeSinceLastInvoke)\n : timeWaiting;\n }\n\n private _timerExpired = (): void => {\n const now = Date.now();\n if (this._shouldInvoke(now)) {\n this._trailingEdge(now);\n return;\n }\n // Fired before the quiet period elapsed (a later call moved the deadline) —\n // re-arm for the remaining time instead of settling now.\n this._timerId = setTimeout(this._timerExpired, this._remainingWait(now));\n };\n\n private _leadingEdge(now: number): void {\n this._lastInvokeTime = now;\n this._timerId = setTimeout(this._timerExpired, this._wait);\n if (this._leading) {\n this._invoke(now);\n }\n }\n\n private _trailingEdge(now: number): void {\n this._timerId = null;\n // Only fire when there is an unconsumed payload (a call arrived since the last\n // invoke). After a lone leading fire `_pendingKind` is null, so a single pulse\n // does not double-fire on its trailing edge.\n if (this._trailing && this._pendingKind !== null) {\n this._invoke(now);\n }\n this._pendingKind = null;\n this._pendingValue = undefined;\n this._pendingArgs = undefined;\n this._setPending(false);\n }\n\n private _invoke(now: number): void {\n this._lastInvokeTime = now;\n const kind = this._pendingKind;\n if (kind === \"value\") {\n this._value = this._pendingValue;\n this._dispatch(`${this._prefix}:settled`, { value: this._value });\n } else if (kind === \"signal\") {\n this._lastArgs = this._pendingArgs ?? [];\n this._dispatch(`${this._prefix}:fired`, { args: this._lastArgs });\n }\n // Mark consumed (mirrors lodash clearing `lastArgs`).\n this._pendingKind = null;\n }\n\n private _setPending(pending: boolean): void {\n if (this._pending === pending) return;\n this._pending = pending;\n this._dispatch(`${this._prefix}:pending-changed`, pending);\n }\n\n private _dispatch(type: string, detail: any): void {\n this._target.dispatchEvent(new CustomEvent(type, { detail, bubbles: true }));\n }\n\n private _clearTimer(): void {\n if (this._timerId !== null) {\n clearTimeout(this._timerId);\n this._timerId = null;\n }\n }\n}\n","import { config } from \"./config.js\";\n\nlet registered = false;\n\ninterface Triggerable extends Element {\n trigger(...args: unknown[]): void;\n}\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const id = triggerElement.getAttribute(config.triggerAttribute);\n if (!id) return;\n\n // Resolve the registered constructors at call time (avoids a components ⇄\n // autoTrigger import cycle, mirroring <wcs-timer>). The DOM trigger fires a\n // single coalesced pulse on the referenced <wcs-debounce> / <wcs-throttle>.\n const DebounceCtor = customElements.get(config.tagNames.debounce);\n const ThrottleCtor = customElements.get(config.tagNames.throttle);\n const el = document.getElementById(id);\n if (!el) return;\n const isDebounce = DebounceCtor && el instanceof DebounceCtor;\n const isThrottle = ThrottleCtor && el instanceof ThrottleCtor;\n if (!isDebounce && !isThrottle) return;\n\n // Suppress the element's default action so a debounce can fire without\n // navigating. See README \"Optional DOM Triggering\".\n event.preventDefault();\n (el as unknown as Triggerable).trigger();\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, DebounceOptions } from \"../types.js\";\nimport { DebounceCore } from \"../core/DebounceCore.js\";\nimport { makeDebounceProperties } from \"../wcBindableFactory.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\n\nconst DEFAULT_WAIT = 250;\n\n/**\n * `<wcs-debounce>` — declarative debounce. See {@link DebounceCore} for the\n * engine. The `eventPrefix` defaults to `\"wcs-debounce\"`; `<wcs-throttle>`\n * subclasses this with `\"wcs-throttle\"` and throttle defaults.\n */\nexport class Debounce extends HTMLElement {\n static hasConnectedCallbackPromise = false;\n protected static eventPrefix = \"wcs-debounce\";\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: makeDebounceProperties(\"wcs-debounce\"),\n // `source` is the value-surface input (its debounced echo comes back on the\n // `value` property). `trigger` / `cancel` / `flush` are commands from the\n // Core. No momentary boolean `trigger` property exists — the signal surface\n // is driven by the `trigger` command (command-token) or a DOM click\n // (autoTrigger), which sidesteps the attribute/method name clash that forced\n // <wcs-geo>'s watch → watchPosition rename.\n inputs: [\n { name: \"source\" },\n { name: \"wait\", attribute: \"wait\" },\n { name: \"leading\", attribute: \"leading\" },\n { name: \"trailing\", attribute: \"trailing\" },\n { name: \"maxWait\", attribute: \"max-wait\" },\n ],\n commands: [\n { name: \"trigger\" },\n { name: \"cancel\" },\n { name: \"flush\" },\n ],\n };\n\n protected _core: DebounceCore;\n private _source: any = undefined;\n\n constructor() {\n super();\n this._core = new DebounceCore((this.constructor as typeof Debounce).eventPrefix, this);\n }\n\n // --- Attribute accessors ---\n\n get wait(): number {\n const attr = this.getAttribute(\"wait\");\n if (attr === null || attr.trim() === \"\") return this._defaultWait();\n // Strict parse via Number() (\"100px\" -> NaN, not 100). Fall back to the\n // default for any non-finite or negative value.\n const parsed = Number(attr);\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : this._defaultWait();\n }\n\n set wait(value: number) {\n this.setAttribute(\"wait\", String(value));\n }\n\n get leading(): boolean {\n return this.hasAttribute(\"leading\");\n }\n\n set leading(value: boolean) {\n if (value) {\n this.setAttribute(\"leading\", \"\");\n } else {\n this.removeAttribute(\"leading\");\n }\n }\n\n // `trailing` defaults to true; the boolean `no-trailing` attribute opts out (a\n // bare `trailing` attribute can't express \"false\", so the negative flag carries\n // the override).\n get trailing(): boolean {\n return !this.hasAttribute(\"no-trailing\");\n }\n\n set trailing(value: boolean) {\n if (value) {\n this.removeAttribute(\"no-trailing\");\n } else {\n this.setAttribute(\"no-trailing\", \"\");\n }\n }\n\n get maxWait(): number | undefined {\n const attr = this.getAttribute(\"max-wait\");\n if (attr === null || attr.trim() === \"\") return this._defaultMaxWait();\n const parsed = Number(attr);\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : this._defaultMaxWait();\n }\n\n set maxWait(value: number) {\n this.setAttribute(\"max-wait\", String(value));\n }\n\n // --- Value-surface input ---\n\n get source(): any {\n return this._source;\n }\n\n set source(value: any) {\n this._source = value;\n this._core.configure(this._options());\n this._core.setSource(value);\n }\n\n // --- Core delegated getters ---\n\n get value(): any {\n return this._core.value;\n }\n\n get fired(): any[] {\n return this._core.fired;\n }\n\n get pending(): boolean {\n return this._core.pending;\n }\n\n // --- Commands ---\n\n trigger(...args: any[]): void {\n this._core.configure(this._options());\n this._core.trigger(...args);\n }\n\n cancel(): void {\n this._core.cancel();\n }\n\n flush(): void {\n this._core.flush();\n }\n\n // --- Internal ---\n\n // Overridden by <wcs-throttle> to bias the defaults toward throttle (leading\n // on, maxWait pinned to wait).\n protected _defaultWait(): number {\n return DEFAULT_WAIT;\n }\n\n // Resolves the effective `leading` value (not a static default). It is a method\n // rather than reading `this.leading` directly because <wcs-throttle> inverts the\n // default (on, opt out via `no-leading`) while sharing the inherited `leading`\n // attribute setter — overriding the getter alone would desync getter and setter.\n protected _resolveLeading(): boolean {\n return this.leading;\n }\n\n protected _defaultMaxWait(): number | undefined {\n return undefined;\n }\n\n protected _options(): DebounceOptions {\n return {\n wait: this.wait,\n leading: this._resolveLeading(),\n trailing: this.trailing,\n maxWait: this.maxWait,\n };\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n }\n\n disconnectedCallback(): void {\n // Drop any in-flight timer so a detached element leaks nothing.\n this._core.cancel();\n }\n}\n","import { IWcBindable } from \"../types.js\";\nimport { Debounce } from \"./Debounce.js\";\nimport { makeDebounceProperties } from \"../wcBindableFactory.js\";\n\n/**\n * `<wcs-throttle>` — the same {@link DebounceCore} engine biased to throttle:\n * `maxWait === wait` (a fire happens at least every `wait` ms under continuous\n * input) and `leading` on by default. It advertises its own `wcs-throttle:*`\n * event namespace (via `makeDebounceProperties(\"wcs-throttle\")`), and the Core\n * dispatches under that prefix because the constructor passes it through.\n */\nexport class Throttle extends Debounce {\n protected static eventPrefix = \"wcs-throttle\";\n static wcBindable: IWcBindable = {\n ...Debounce.wcBindable,\n properties: makeDebounceProperties(\"wcs-throttle\"),\n };\n\n // leading defaults on for throttle; `no-leading` opts out (symmetric with the\n // inherited `no-trailing`).\n protected _resolveLeading(): boolean {\n return !this.hasAttribute(\"no-leading\");\n }\n\n // Pin maxWait to wait so throttle fires on a steady cadence; an explicit\n // `max-wait` attribute still overrides via the inherited getter.\n protected _defaultMaxWait(): number | undefined {\n return this.wait;\n }\n}\n","import { Debounce } from \"./components/Debounce.js\";\nimport { Throttle } from \"./components/Throttle.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.debounce)) {\n customElements.define(config.tagNames.debounce, Debounce);\n }\n if (!customElements.get(config.tagNames.throttle)) {\n customElements.define(config.tagNames.throttle, Throttle);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapDebounce(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/wcBindableFactory.ts","../src/core/DebounceCore.ts","../src/autoTrigger.ts","../src/components/Debounce.ts","../src/components/Throttle.ts","../src/registerComponents.ts","../src/bootstrapDebounce.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n autoTrigger: boolean;\n triggerAttribute: string;\n tagNames: {\n debounce: string;\n throttle: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-debouncetarget\",\n tagNames: {\n debounce: \"wcs-debounce\",\n throttle: \"wcs-throttle\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (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 { IWcBindableProperty } from \"./types.js\";\n\n/**\n * Build the wc-bindable `properties` list for a debounce/throttle element, with\n * every event name derived from a single `prefix`. `<wcs-debounce>` uses\n * `\"wcs-debounce\"`, `<wcs-throttle>` uses `\"wcs-throttle\"`, so the two tags share\n * one engine (DebounceCore) yet advertise distinct event namespaces from one\n * source of truth — no hand-duplicated property tables (cf. the geolocation Shell\n * which overrode its wcBindable by hand).\n *\n * - `value` — the debounced value of the latest `source` write (value surface),\n * read from the `<prefix>:settled` event.\n * - `fired` — the coalesced args of the latest `trigger()` pulse (signal\n * surface), read from the `<prefix>:fired` event. Declared as a\n * property (not just an event) so state can subscribe via the\n * event-token protocol (`eventToken.fired: <name>`).\n * - `pending` — whether a debounce is currently in flight.\n */\nexport function makeDebounceProperties(prefix: string): IWcBindableProperty[] {\n return [\n { name: \"value\", event: `${prefix}:settled`, getter: (e: Event) => (e as CustomEvent).detail.value },\n { name: \"fired\", event: `${prefix}:fired`, getter: (e: Event) => (e as CustomEvent).detail.args },\n { name: \"pending\", event: `${prefix}:pending-changed` },\n ];\n}\n","import { IWcBindable, DebounceOptions } from \"../types.js\";\nimport { makeDebounceProperties } from \"../wcBindableFactory.js\";\n\ntype PendingKind = \"value\" | \"signal\" | null;\n\n/**\n * Headless debounce/throttle primitive. A framework-agnostic port of lodash's\n * `debounce` algorithm (`shouldInvoke` / `leadingEdge` / `trailingEdge` /\n * `remainingWait`, timed via `Date.now()`), exposed through the wc-bindable\n * protocol.\n *\n * It coalesces a stream of *signals* and emits at most one per quiet period.\n * Two surfaces share the single timer:\n *\n * - **value** — writing {@link setSource} schedules a settle; on fire the\n * debounced value is published via the `<prefix>:settled` event and the\n * `value` getter. Wire it as `source: src; value: debounced`.\n * - **signal** — calling {@link trigger}`(...args)` coalesces a burst of pulses;\n * on fire one `<prefix>:fired` event carries the latest args (relayed by state\n * through the command-token / event-token protocols).\n *\n * A given instance is meant to be used for one surface at a time. Because each\n * surface keeps its own field (`_value` vs `_lastArgs`), the getters never\n * pollute each other; if both are driven on one instance the *last* scheduled\n * signal wins (lodash's last-args semantics).\n *\n * Throttle is the same engine with `maxWait === wait` (and `leading` on by\n * default), so `<wcs-throttle>` reuses this class with a different `eventPrefix`.\n */\nexport class DebounceCore extends EventTarget {\n // The static contract advertises the *default* `wcs-debounce:*` event names. A\n // headless Core constructed with a non-default `eventPrefix` (e.g.\n // `\"wcs-throttle\"`) dispatches under that prefix, so its events won't match\n // this metadata — rebuild the property table with `makeDebounceProperties(prefix)`\n // for that case. (The `<wcs-throttle>` Shell already overrides its own\n // `wcBindable` this way, so binding through an element is always consistent.)\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: makeDebounceProperties(\"wcs-debounce\"),\n commands: [\n { name: \"trigger\" },\n { name: \"cancel\" },\n { name: \"flush\" },\n ],\n };\n\n private readonly _prefix: string;\n private _target: EventTarget;\n\n // Tuning (lodash knobs).\n private _wait: number = 0;\n private _leading: boolean = false;\n private _trailing: boolean = true;\n private _maxWait: number = 0;\n private _hasMaxWait: boolean = false;\n\n // Timing bookkeeping.\n private _lastCallTime: number | undefined = undefined;\n private _lastInvokeTime: number = 0;\n private _timerId: ReturnType<typeof setTimeout> | null = null;\n // Generation stamped onto the live timer at arm time, compared in\n // `_timerExpired` against `_gen` to drop callbacks that outlived a dispose().\n private _timerGen: number = 0;\n\n // Last-wins pending payload. `_pendingKind === null` doubles as the \"consumed /\n // empty\" sentinel (lodash clears `lastArgs` in invokeFunc): a trailing edge with\n // no fresh call since the last fire sees `null` and does not re-fire, which is\n // what stops a single leading pulse from also firing on the trailing edge.\n private _pendingKind: PendingKind = null;\n private _pendingValue: any = undefined;\n private _pendingArgs: any[] | undefined = undefined;\n\n // Observable state (getter backing).\n private _value: any = undefined;\n private _lastArgs: any[] = [];\n private _pending: boolean = false;\n\n // Generation guard (§3.4): bumped on dispose() so a timer that survives a\n // tear-down can no longer settle into a detached element. A pending timer is\n // also cleared by dispose() → cancel(), so the guard is defensive: it stops\n // any callback that has already been dequeued by the host event loop from\n // writing state after dispose().\n private _gen = 0;\n // SSR (§3.8): the debounce engine is purely timer-driven with no asynchronous\n // probe to await, so readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n constructor(prefix: string = \"wcs-debounce\", target?: EventTarget, options?: DebounceOptions) {\n super();\n this._prefix = prefix;\n this._target = target ?? this;\n if (options) {\n this.configure(options);\n }\n }\n\n // --- Lifecycle (§3.5 / §3.8) ---\n\n get ready(): Promise<void> {\n return this._ready;\n }\n\n // Debounce is command-driven (setSource / trigger schedule work on demand)\n // with no subscription to establish, so observe() is an idempotent no-op that\n // resolves once ready.\n observe(): Promise<void> {\n return this._ready;\n }\n\n // Tear down the pending timer and invalidate the generation so a stale timer\n // callback cannot fire after the element is detached.\n dispose(): void {\n this._gen++;\n this.cancel();\n }\n\n // --- Configuration ---\n\n /**\n * Update the tuning knobs. The Shell calls this with the element's current\n * attributes before each schedule, so live attribute edits take effect on the\n * next signal. `maxWait` is clamped to at least `wait` (lodash semantics); an\n * absent / invalid `maxWait` disables maxWait entirely.\n */\n configure(options: DebounceOptions = {}): void {\n if (typeof options.wait === \"number\" && Number.isFinite(options.wait) && options.wait >= 0) {\n this._wait = options.wait;\n }\n if (typeof options.leading === \"boolean\") {\n this._leading = options.leading;\n }\n if (typeof options.trailing === \"boolean\") {\n this._trailing = options.trailing;\n }\n const mw = options.maxWait;\n if (typeof mw === \"number\" && Number.isFinite(mw) && mw >= 0) {\n this._maxWait = Math.max(mw, this._wait);\n this._hasMaxWait = true;\n } else {\n this._maxWait = 0;\n this._hasMaxWait = false;\n }\n }\n\n // --- Observable getters ---\n\n get value(): any {\n return this._value;\n }\n\n get fired(): any[] {\n return this._lastArgs;\n }\n\n get pending(): boolean {\n return this._pending;\n }\n\n // --- Public entry points ---\n\n /** Value surface: schedule a settle carrying `value` (last write wins). */\n setSource(value: any): void {\n this._schedule(\"value\", value, undefined);\n }\n\n /** Signal surface: coalesce a pulse carrying `args` (last call wins). */\n trigger(...args: any[]): void {\n this._schedule(\"signal\", undefined, args);\n }\n\n /** Drop any pending fire without emitting. Getters keep their last values. */\n cancel(): void {\n this._clearTimer();\n this._lastInvokeTime = 0;\n this._lastCallTime = undefined;\n this._pendingKind = null;\n this._pendingValue = undefined;\n this._pendingArgs = undefined;\n this._setPending(false);\n }\n\n /**\n * Emit any buffered payload immediately, then clear pending. Unlike lodash's\n * `flush` (which honours `trailing`), this fires whatever is buffered — the\n * command's intent is \"publish now\" — but is a no-op when nothing is pending.\n */\n flush(): void {\n if (this._timerId === null && this._pendingKind === null) return;\n const now = Date.now();\n this._clearTimer();\n if (this._pendingKind !== null) {\n this._invoke(now);\n }\n this._pendingKind = null;\n this._pendingValue = undefined;\n this._pendingArgs = undefined;\n this._setPending(false);\n }\n\n // --- Engine (lodash port) ---\n\n private _schedule(kind: Exclude<PendingKind, null>, value: any, args: any[] | undefined): void {\n const now = Date.now();\n const isInvoking = this._shouldInvoke(now);\n\n this._pendingKind = kind;\n if (kind === \"value\") {\n this._pendingValue = value;\n } else {\n this._pendingArgs = args;\n }\n this._lastCallTime = now;\n this._setPending(true);\n\n if (isInvoking) {\n if (this._timerId === null) {\n this._leadingEdge(now);\n return;\n }\n if (this._hasMaxWait) {\n // Continuous input that has reached maxWait: restart the steady timer and\n // invoke now so a fire happens at least every maxWait ms (throttle path).\n // Clear the pending handle first (lodash's \"tight loop\" branch does the\n // same) — overwriting `_timerId` without clearing would orphan the old\n // timer and let it fire spuriously later.\n this._clearTimer();\n this._armTimer(this._wait);\n this._invoke(now);\n return;\n }\n }\n if (this._timerId === null) {\n this._armTimer(this._wait);\n }\n }\n\n private _shouldInvoke(now: number): boolean {\n if (this._lastCallTime === undefined) return true;\n const timeSinceLastCall = now - this._lastCallTime;\n const timeSinceLastInvoke = now - this._lastInvokeTime;\n return (\n timeSinceLastCall >= this._wait ||\n timeSinceLastCall < 0 ||\n (this._hasMaxWait && timeSinceLastInvoke >= this._maxWait)\n );\n }\n\n private _remainingWait(now: number): number {\n const timeSinceLastCall = now - (this._lastCallTime as number);\n const timeSinceLastInvoke = now - this._lastInvokeTime;\n const timeWaiting = this._wait - timeSinceLastCall;\n return this._hasMaxWait\n ? Math.min(timeWaiting, this._maxWait - timeSinceLastInvoke)\n : timeWaiting;\n }\n\n private _timerExpired = (): void => {\n // §3.4 generation guard: a timer dequeued by the host before dispose() could\n // clear it must not settle into a torn-down element. Capture the generation\n // when the timer is scheduled (via `_armTimer`) and bail if it is stale.\n if (this._timerGen !== this._gen) return;\n const now = Date.now();\n if (this._shouldInvoke(now)) {\n this._trailingEdge(now);\n return;\n }\n // Fired before the quiet period elapsed (a later call moved the deadline) —\n // re-arm for the remaining time instead of settling now.\n this._armTimer(this._remainingWait(now));\n };\n\n private _leadingEdge(now: number): void {\n this._lastInvokeTime = now;\n this._armTimer(this._wait);\n if (this._leading) {\n this._invoke(now);\n }\n }\n\n private _trailingEdge(now: number): void {\n this._timerId = null;\n // Only fire when there is an unconsumed payload (a call arrived since the last\n // invoke). After a lone leading fire `_pendingKind` is null, so a single pulse\n // does not double-fire on its trailing edge.\n if (this._trailing && this._pendingKind !== null) {\n this._invoke(now);\n }\n this._pendingKind = null;\n this._pendingValue = undefined;\n this._pendingArgs = undefined;\n this._setPending(false);\n }\n\n private _invoke(now: number): void {\n this._lastInvokeTime = now;\n const kind = this._pendingKind;\n if (kind === \"value\") {\n this._value = this._pendingValue;\n this._dispatch(`${this._prefix}:settled`, { value: this._value });\n } else if (kind === \"signal\") {\n this._lastArgs = this._pendingArgs ?? [];\n this._dispatch(`${this._prefix}:fired`, { args: this._lastArgs });\n }\n // Mark consumed (mirrors lodash clearing `lastArgs`).\n this._pendingKind = null;\n }\n\n private _setPending(pending: boolean): void {\n if (this._pending === pending) return;\n this._pending = pending;\n this._dispatch(`${this._prefix}:pending-changed`, pending);\n }\n\n private _dispatch(type: string, detail: any): void {\n this._target.dispatchEvent(new CustomEvent(type, { detail, bubbles: true }));\n }\n\n // Arm the settle timer, stamping the current generation so a callback that the\n // host dequeues after a dispose() can detect it is stale (§3.4).\n private _armTimer(delay: number): void {\n this._timerGen = this._gen;\n this._timerId = setTimeout(this._timerExpired, delay);\n }\n\n private _clearTimer(): void {\n if (this._timerId !== null) {\n clearTimeout(this._timerId);\n this._timerId = null;\n }\n }\n}\n","import { config } from \"./config.js\";\n\nlet registered = false;\n\ninterface Triggerable extends Element {\n trigger(...args: unknown[]): void;\n}\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const id = triggerElement.getAttribute(config.triggerAttribute);\n if (!id) return;\n\n // Resolve the registered constructors at call time (avoids a components ⇄\n // autoTrigger import cycle, mirroring <wcs-timer>). The DOM trigger fires a\n // single coalesced pulse on the referenced <wcs-debounce> / <wcs-throttle>.\n const DebounceCtor = customElements.get(config.tagNames.debounce);\n const ThrottleCtor = customElements.get(config.tagNames.throttle);\n const el = document.getElementById(id);\n if (!el) return;\n const isDebounce = DebounceCtor && el instanceof DebounceCtor;\n const isThrottle = ThrottleCtor && el instanceof ThrottleCtor;\n if (!isDebounce && !isThrottle) return;\n\n // Suppress the element's default action so a debounce can fire without\n // navigating. See README \"Optional DOM Triggering\".\n event.preventDefault();\n (el as unknown as Triggerable).trigger();\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, DebounceOptions } from \"../types.js\";\nimport { DebounceCore } from \"../core/DebounceCore.js\";\nimport { makeDebounceProperties } from \"../wcBindableFactory.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\n\nconst DEFAULT_WAIT = 250;\n\n/**\n * `<wcs-debounce>` — declarative debounce. See {@link DebounceCore} for the\n * engine. The `eventPrefix` defaults to `\"wcs-debounce\"`; `<wcs-throttle>`\n * subclasses this with `\"wcs-throttle\"` and throttle defaults.\n */\nexport class Debounce extends HTMLElement {\n static hasConnectedCallbackPromise = true;\n protected static eventPrefix = \"wcs-debounce\";\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: makeDebounceProperties(\"wcs-debounce\"),\n // `source` is the value-surface input (its debounced echo comes back on the\n // `value` property). `trigger` / `cancel` / `flush` are commands from the\n // Core. No momentary boolean `trigger` property exists — the signal surface\n // is driven by the `trigger` command (command-token) or a DOM click\n // (autoTrigger), which sidesteps the attribute/method name clash that forced\n // <wcs-geo>'s watch → watchPosition rename.\n inputs: [\n { name: \"source\" },\n { name: \"wait\", attribute: \"wait\" },\n { name: \"leading\", attribute: \"leading\" },\n { name: \"trailing\", attribute: \"trailing\" },\n { name: \"maxWait\", attribute: \"max-wait\" },\n ],\n commands: [\n { name: \"trigger\" },\n { name: \"cancel\" },\n { name: \"flush\" },\n ],\n };\n\n protected _core: DebounceCore;\n private _source: any = undefined;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n\n constructor() {\n super();\n this._core = new DebounceCore((this.constructor as typeof Debounce).eventPrefix, this);\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Attribute accessors ---\n\n get wait(): number {\n const attr = this.getAttribute(\"wait\");\n if (attr === null || attr.trim() === \"\") return this._defaultWait();\n // Strict parse via Number() (\"100px\" -> NaN, not 100). Fall back to the\n // default for any non-finite or negative value.\n const parsed = Number(attr);\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : this._defaultWait();\n }\n\n set wait(value: number) {\n this.setAttribute(\"wait\", String(value));\n }\n\n get leading(): boolean {\n return this.hasAttribute(\"leading\");\n }\n\n set leading(value: boolean) {\n if (value) {\n this.setAttribute(\"leading\", \"\");\n } else {\n this.removeAttribute(\"leading\");\n }\n }\n\n // `trailing` defaults to true; the boolean `no-trailing` attribute opts out (a\n // bare `trailing` attribute can't express \"false\", so the negative flag carries\n // the override).\n get trailing(): boolean {\n return !this.hasAttribute(\"no-trailing\");\n }\n\n set trailing(value: boolean) {\n if (value) {\n this.removeAttribute(\"no-trailing\");\n } else {\n this.setAttribute(\"no-trailing\", \"\");\n }\n }\n\n get maxWait(): number | undefined {\n const attr = this.getAttribute(\"max-wait\");\n if (attr === null || attr.trim() === \"\") return this._defaultMaxWait();\n const parsed = Number(attr);\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : this._defaultMaxWait();\n }\n\n set maxWait(value: number) {\n this.setAttribute(\"max-wait\", String(value));\n }\n\n // --- Value-surface input ---\n\n get source(): any {\n return this._source;\n }\n\n set source(value: any) {\n this._source = value;\n this._core.configure(this._options());\n this._core.setSource(value);\n }\n\n // --- Core delegated getters ---\n\n get value(): any {\n return this._core.value;\n }\n\n get fired(): any[] {\n return this._core.fired;\n }\n\n get pending(): boolean {\n return this._core.pending;\n }\n\n // --- Commands ---\n\n trigger(...args: any[]): void {\n this._core.configure(this._options());\n this._core.trigger(...args);\n }\n\n cancel(): void {\n this._core.cancel();\n }\n\n flush(): void {\n this._core.flush();\n }\n\n // --- Internal ---\n\n // Overridden by <wcs-throttle> to bias the defaults toward throttle (leading\n // on, maxWait pinned to wait).\n protected _defaultWait(): number {\n return DEFAULT_WAIT;\n }\n\n // Resolves the effective `leading` value (not a static default). It is a method\n // rather than reading `this.leading` directly because <wcs-throttle> inverts the\n // default (on, opt out via `no-leading`) while sharing the inherited `leading`\n // attribute setter — overriding the getter alone would desync getter and setter.\n protected _resolveLeading(): boolean {\n return this.leading;\n }\n\n protected _defaultMaxWait(): number | undefined {\n return undefined;\n }\n\n protected _options(): DebounceOptions {\n return {\n wait: this.wait,\n leading: this._resolveLeading(),\n trailing: this.trailing,\n maxWait: this.maxWait,\n };\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n // §4.1/§4.4 Shell SSR: expose connectedCallbackPromise backed by observe().\n // observe() is a no-op resolving once ready (the engine is command-driven).\n this._connectedCallbackPromise = this._core.observe();\n }\n\n disconnectedCallback(): void {\n // Drop any in-flight timer so a detached element leaks nothing, and bump the\n // Core generation so a surviving timer callback cannot settle (§3.5).\n this._core.dispose();\n }\n}\n","import { IWcBindable } from \"../types.js\";\nimport { Debounce } from \"./Debounce.js\";\nimport { makeDebounceProperties } from \"../wcBindableFactory.js\";\n\n/**\n * `<wcs-throttle>` — the same {@link DebounceCore} engine biased to throttle:\n * `maxWait === wait` (a fire happens at least every `wait` ms under continuous\n * input) and `leading` on by default. It advertises its own `wcs-throttle:*`\n * event namespace (via `makeDebounceProperties(\"wcs-throttle\")`), and the Core\n * dispatches under that prefix because the constructor passes it through.\n */\nexport class Throttle extends Debounce {\n protected static eventPrefix = \"wcs-throttle\";\n static wcBindable: IWcBindable = {\n ...Debounce.wcBindable,\n properties: makeDebounceProperties(\"wcs-throttle\"),\n };\n\n // leading defaults on for throttle; `no-leading` opts out (symmetric with the\n // inherited `no-trailing`).\n protected _resolveLeading(): boolean {\n return !this.hasAttribute(\"no-leading\");\n }\n\n // Pin maxWait to wait so throttle fires on a steady cadence; an explicit\n // `max-wait` attribute still overrides via the inherited getter.\n protected _defaultMaxWait(): number | undefined {\n return this.wait;\n }\n}\n","import { Debounce } from \"./components/Debounce.js\";\nimport { Throttle } from \"./components/Throttle.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.debounce)) {\n customElements.define(config.tagNames.debounce, Debounce);\n }\n if (!customElements.get(config.tagNames.throttle)) {\n customElements.define(config.tagNames.throttle, Throttle);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapDebounce(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-debouncetarget",tagNames:{debounce:"wcs-debounce",throttle:"wcs-throttle"}};function e(t){if(null===t||"object"!=typeof t)return t;Object.freeze(t);for(const i of Object.keys(t))e(t[i]);return t}function i(t){if(null===t||"object"!=typeof t)return t;const e={};for(const n of Object.keys(t))e[n]=i(t[n]);return e}let n=null;const s=t;function a(){return n||(n=e(i(t))),n}function r(t){return[{name:"value",event:`${t}:settled`,getter:t=>t.detail.value},{name:"fired",event:`${t}:fired`,getter:t=>t.detail.args},{name:"pending",event:`${t}:pending-changed`}]}class l extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:r("wcs-debounce"),commands:[{name:"trigger"},{name:"cancel"},{name:"flush"}]};_prefix;_target;_wait=0;_leading=!1;_trailing=!0;_maxWait=0;_hasMaxWait=!1;_lastCallTime=void 0;_lastInvokeTime=0;_timerId=null;_pendingKind=null;_pendingValue=void 0;_pendingArgs=void 0;_value=void 0;_lastArgs=[];_pending=!1;constructor(t="wcs-debounce",e,i){super(),this._prefix=t,this._target=e??this,i&&this.configure(i)}configure(t={}){"number"==typeof t.wait&&Number.isFinite(t.wait)&&t.wait>=0&&(this._wait=t.wait),"boolean"==typeof t.leading&&(this._leading=t.leading),"boolean"==typeof t.trailing&&(this._trailing=t.trailing);const e=t.maxWait;"number"==typeof e&&Number.isFinite(e)&&e>=0?(this._maxWait=Math.max(e,this._wait),this._hasMaxWait=!0):(this._maxWait=0,this._hasMaxWait=!1)}get value(){return this._value}get fired(){return this._lastArgs}get pending(){return this._pending}setSource(t){this._schedule("value",t,void 0)}trigger(...t){this._schedule("signal",void 0,t)}cancel(){this._clearTimer(),this._lastInvokeTime=0,this._lastCallTime=void 0,this._pendingKind=null,this._pendingValue=void 0,this._pendingArgs=void 0,this._setPending(!1)}flush(){if(null===this._timerId&&null===this._pendingKind)return;const t=Date.now();this._clearTimer(),null!==this._pendingKind&&this._invoke(t),this._pendingKind=null,this._pendingValue=void 0,this._pendingArgs=void 0,this._setPending(!1)}_schedule(t,e,i){const n=Date.now(),s=this._shouldInvoke(n);if(this._pendingKind=t,"value"===t?this._pendingValue=e:this._pendingArgs=i,this._lastCallTime=n,this._setPending(!0),s){if(null===this._timerId)return void this._leadingEdge(n);if(this._hasMaxWait)return this._clearTimer(),this._timerId=setTimeout(this._timerExpired,this._wait),void this._invoke(n)}null===this._timerId&&(this._timerId=setTimeout(this._timerExpired,this._wait))}_shouldInvoke(t){if(void 0===this._lastCallTime)return!0;const e=t-this._lastCallTime,i=t-this._lastInvokeTime;return e>=this._wait||e<0||this._hasMaxWait&&i>=this._maxWait}_remainingWait(t){const e=t-this._lastCallTime,i=t-this._lastInvokeTime,n=this._wait-e;return this._hasMaxWait?Math.min(n,this._maxWait-i):n}_timerExpired=()=>{const t=Date.now();this._shouldInvoke(t)?this._trailingEdge(t):this._timerId=setTimeout(this._timerExpired,this._remainingWait(t))};_leadingEdge(t){this._lastInvokeTime=t,this._timerId=setTimeout(this._timerExpired,this._wait),this._leading&&this._invoke(t)}_trailingEdge(t){this._timerId=null,this._trailing&&null!==this._pendingKind&&this._invoke(t),this._pendingKind=null,this._pendingValue=void 0,this._pendingArgs=void 0,this._setPending(!1)}_invoke(t){this._lastInvokeTime=t;const e=this._pendingKind;"value"===e?(this._value=this._pendingValue,this._dispatch(`${this._prefix}:settled`,{value:this._value})):"signal"===e&&(this._lastArgs=this._pendingArgs??[],this._dispatch(`${this._prefix}:fired`,{args:this._lastArgs})),this._pendingKind=null}_setPending(t){this._pending!==t&&(this._pending=t,this._dispatch(`${this._prefix}:pending-changed`,t))}_dispatch(t,e){this._target.dispatchEvent(new CustomEvent(t,{detail:e,bubbles:!0}))}_clearTimer(){null!==this._timerId&&(clearTimeout(this._timerId),this._timerId=null)}}let o=!1;function h(t){const e=t.target;if(!(e instanceof Element))return;const i=e.closest(`[${s.triggerAttribute}]`);if(!i)return;const n=i.getAttribute(s.triggerAttribute);if(!n)return;const a=customElements.get(s.tagNames.debounce),r=customElements.get(s.tagNames.throttle),l=document.getElementById(n);if(!l)return;(a&&l instanceof a||r&&l instanceof r)&&(t.preventDefault(),l.trigger())}class u extends HTMLElement{static hasConnectedCallbackPromise=!1;static eventPrefix="wcs-debounce";static wcBindable={protocol:"wc-bindable",version:1,properties:r("wcs-debounce"),inputs:[{name:"source"},{name:"wait",attribute:"wait"},{name:"leading",attribute:"leading"},{name:"trailing",attribute:"trailing"},{name:"maxWait",attribute:"max-wait"}],commands:[{name:"trigger"},{name:"cancel"},{name:"flush"}]};_core;_source=void 0;constructor(){super(),this._core=new l(this.constructor.eventPrefix,this)}get wait(){const t=this.getAttribute("wait");if(null===t||""===t.trim())return this._defaultWait();const e=Number(t);return Number.isFinite(e)&&e>=0?e:this._defaultWait()}set wait(t){this.setAttribute("wait",String(t))}get leading(){return this.hasAttribute("leading")}set leading(t){t?this.setAttribute("leading",""):this.removeAttribute("leading")}get trailing(){return!this.hasAttribute("no-trailing")}set trailing(t){t?this.removeAttribute("no-trailing"):this.setAttribute("no-trailing","")}get maxWait(){const t=this.getAttribute("max-wait");if(null===t||""===t.trim())return this._defaultMaxWait();const e=Number(t);return Number.isFinite(e)&&e>=0?e:this._defaultMaxWait()}set maxWait(t){this.setAttribute("max-wait",String(t))}get source(){return this._source}set source(t){this._source=t,this._core.configure(this._options()),this._core.setSource(t)}get value(){return this._core.value}get fired(){return this._core.fired}get pending(){return this._core.pending}trigger(...t){this._core.configure(this._options()),this._core.trigger(...t)}cancel(){this._core.cancel()}flush(){this._core.flush()}_defaultWait(){return 250}_resolveLeading(){return this.leading}_defaultMaxWait(){}_options(){return{wait:this.wait,leading:this._resolveLeading(),trailing:this.trailing,maxWait:this.maxWait}}connectedCallback(){this.style.display="none",s.autoTrigger&&(o||(o=!0,document.addEventListener("click",h)))}disconnectedCallback(){this._core.cancel()}}class g extends u{static eventPrefix="wcs-throttle";static wcBindable={...u.wcBindable,properties:r("wcs-throttle")};_resolveLeading(){return!this.hasAttribute("no-leading")}_defaultMaxWait(){return this.wait}}function d(e){var i;e&&("boolean"==typeof(i=e).autoTrigger&&(t.autoTrigger=i.autoTrigger),"string"==typeof i.triggerAttribute&&(t.triggerAttribute=i.triggerAttribute),i.tagNames&&Object.assign(t.tagNames,i.tagNames),n=null),customElements.get(s.tagNames.debounce)||customElements.define(s.tagNames.debounce,u),customElements.get(s.tagNames.throttle)||customElements.define(s.tagNames.throttle,g)}export{l as DebounceCore,u as WcsDebounce,g as WcsThrottle,d as bootstrapDebounce,a as getConfig,r as makeDebounceProperties};
1
+ const t={autoTrigger:!0,triggerAttribute:"data-debouncetarget",tagNames:{debounce:"wcs-debounce",throttle:"wcs-throttle"}};function e(t){if(null===t||"object"!=typeof t)return t;Object.freeze(t);for(const i of Object.keys(t))e(t[i]);return t}function i(t){if(null===t||"object"!=typeof t)return t;const e={};for(const n of Object.keys(t))e[n]=i(t[n]);return e}let n=null;const s=t;function r(){return n||(n=e(i(t))),n}function a(t){return[{name:"value",event:`${t}:settled`,getter:t=>t.detail.value},{name:"fired",event:`${t}:fired`,getter:t=>t.detail.args},{name:"pending",event:`${t}:pending-changed`}]}class l extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:a("wcs-debounce"),commands:[{name:"trigger"},{name:"cancel"},{name:"flush"}]};_prefix;_target;_wait=0;_leading=!1;_trailing=!0;_maxWait=0;_hasMaxWait=!1;_lastCallTime=void 0;_lastInvokeTime=0;_timerId=null;_timerGen=0;_pendingKind=null;_pendingValue=void 0;_pendingArgs=void 0;_value=void 0;_lastArgs=[];_pending=!1;_gen=0;_ready=Promise.resolve();constructor(t="wcs-debounce",e,i){super(),this._prefix=t,this._target=e??this,i&&this.configure(i)}get ready(){return this._ready}observe(){return this._ready}dispose(){this._gen++,this.cancel()}configure(t={}){"number"==typeof t.wait&&Number.isFinite(t.wait)&&t.wait>=0&&(this._wait=t.wait),"boolean"==typeof t.leading&&(this._leading=t.leading),"boolean"==typeof t.trailing&&(this._trailing=t.trailing);const e=t.maxWait;"number"==typeof e&&Number.isFinite(e)&&e>=0?(this._maxWait=Math.max(e,this._wait),this._hasMaxWait=!0):(this._maxWait=0,this._hasMaxWait=!1)}get value(){return this._value}get fired(){return this._lastArgs}get pending(){return this._pending}setSource(t){this._schedule("value",t,void 0)}trigger(...t){this._schedule("signal",void 0,t)}cancel(){this._clearTimer(),this._lastInvokeTime=0,this._lastCallTime=void 0,this._pendingKind=null,this._pendingValue=void 0,this._pendingArgs=void 0,this._setPending(!1)}flush(){if(null===this._timerId&&null===this._pendingKind)return;const t=Date.now();this._clearTimer(),null!==this._pendingKind&&this._invoke(t),this._pendingKind=null,this._pendingValue=void 0,this._pendingArgs=void 0,this._setPending(!1)}_schedule(t,e,i){const n=Date.now(),s=this._shouldInvoke(n);if(this._pendingKind=t,"value"===t?this._pendingValue=e:this._pendingArgs=i,this._lastCallTime=n,this._setPending(!0),s){if(null===this._timerId)return void this._leadingEdge(n);if(this._hasMaxWait)return this._clearTimer(),this._armTimer(this._wait),void this._invoke(n)}null===this._timerId&&this._armTimer(this._wait)}_shouldInvoke(t){if(void 0===this._lastCallTime)return!0;const e=t-this._lastCallTime,i=t-this._lastInvokeTime;return e>=this._wait||e<0||this._hasMaxWait&&i>=this._maxWait}_remainingWait(t){const e=t-this._lastCallTime,i=t-this._lastInvokeTime,n=this._wait-e;return this._hasMaxWait?Math.min(n,this._maxWait-i):n}_timerExpired=()=>{if(this._timerGen!==this._gen)return;const t=Date.now();this._shouldInvoke(t)?this._trailingEdge(t):this._armTimer(this._remainingWait(t))};_leadingEdge(t){this._lastInvokeTime=t,this._armTimer(this._wait),this._leading&&this._invoke(t)}_trailingEdge(t){this._timerId=null,this._trailing&&null!==this._pendingKind&&this._invoke(t),this._pendingKind=null,this._pendingValue=void 0,this._pendingArgs=void 0,this._setPending(!1)}_invoke(t){this._lastInvokeTime=t;const e=this._pendingKind;"value"===e?(this._value=this._pendingValue,this._dispatch(`${this._prefix}:settled`,{value:this._value})):"signal"===e&&(this._lastArgs=this._pendingArgs??[],this._dispatch(`${this._prefix}:fired`,{args:this._lastArgs})),this._pendingKind=null}_setPending(t){this._pending!==t&&(this._pending=t,this._dispatch(`${this._prefix}:pending-changed`,t))}_dispatch(t,e){this._target.dispatchEvent(new CustomEvent(t,{detail:e,bubbles:!0}))}_armTimer(t){this._timerGen=this._gen,this._timerId=setTimeout(this._timerExpired,t)}_clearTimer(){null!==this._timerId&&(clearTimeout(this._timerId),this._timerId=null)}}let o=!1;function h(t){const e=t.target;if(!(e instanceof Element))return;const i=e.closest(`[${s.triggerAttribute}]`);if(!i)return;const n=i.getAttribute(s.triggerAttribute);if(!n)return;const r=customElements.get(s.tagNames.debounce),a=customElements.get(s.tagNames.throttle),l=document.getElementById(n);if(!l)return;(r&&l instanceof r||a&&l instanceof a)&&(t.preventDefault(),l.trigger())}class g extends HTMLElement{static hasConnectedCallbackPromise=!0;static eventPrefix="wcs-debounce";static wcBindable={protocol:"wc-bindable",version:1,properties:a("wcs-debounce"),inputs:[{name:"source"},{name:"wait",attribute:"wait"},{name:"leading",attribute:"leading"},{name:"trailing",attribute:"trailing"},{name:"maxWait",attribute:"max-wait"}],commands:[{name:"trigger"},{name:"cancel"},{name:"flush"}]};_core;_source=void 0;_connectedCallbackPromise=Promise.resolve();constructor(){super(),this._core=new l(this.constructor.eventPrefix,this)}get connectedCallbackPromise(){return this._connectedCallbackPromise}get wait(){const t=this.getAttribute("wait");if(null===t||""===t.trim())return this._defaultWait();const e=Number(t);return Number.isFinite(e)&&e>=0?e:this._defaultWait()}set wait(t){this.setAttribute("wait",String(t))}get leading(){return this.hasAttribute("leading")}set leading(t){t?this.setAttribute("leading",""):this.removeAttribute("leading")}get trailing(){return!this.hasAttribute("no-trailing")}set trailing(t){t?this.removeAttribute("no-trailing"):this.setAttribute("no-trailing","")}get maxWait(){const t=this.getAttribute("max-wait");if(null===t||""===t.trim())return this._defaultMaxWait();const e=Number(t);return Number.isFinite(e)&&e>=0?e:this._defaultMaxWait()}set maxWait(t){this.setAttribute("max-wait",String(t))}get source(){return this._source}set source(t){this._source=t,this._core.configure(this._options()),this._core.setSource(t)}get value(){return this._core.value}get fired(){return this._core.fired}get pending(){return this._core.pending}trigger(...t){this._core.configure(this._options()),this._core.trigger(...t)}cancel(){this._core.cancel()}flush(){this._core.flush()}_defaultWait(){return 250}_resolveLeading(){return this.leading}_defaultMaxWait(){}_options(){return{wait:this.wait,leading:this._resolveLeading(),trailing:this.trailing,maxWait:this.maxWait}}connectedCallback(){this.style.display="none",s.autoTrigger&&(o||(o=!0,document.addEventListener("click",h))),this._connectedCallbackPromise=this._core.observe()}disconnectedCallback(){this._core.dispose()}}class u extends g{static eventPrefix="wcs-throttle";static wcBindable={...g.wcBindable,properties:a("wcs-throttle")};_resolveLeading(){return!this.hasAttribute("no-leading")}_defaultMaxWait(){return this.wait}}function d(e){var i;e&&("boolean"==typeof(i=e).autoTrigger&&(t.autoTrigger=i.autoTrigger),"string"==typeof i.triggerAttribute&&(t.triggerAttribute=i.triggerAttribute),i.tagNames&&Object.assign(t.tagNames,i.tagNames),n=null),customElements.get(s.tagNames.debounce)||customElements.define(s.tagNames.debounce,g),customElements.get(s.tagNames.throttle)||customElements.define(s.tagNames.throttle,u)}export{l as DebounceCore,g as WcsDebounce,u as WcsThrottle,d as bootstrapDebounce,r as getConfig,a as makeDebounceProperties};
2
2
  //# sourceMappingURL=index.esm.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.min.js","sources":["../src/config.ts","../src/wcBindableFactory.ts","../src/core/DebounceCore.ts","../src/autoTrigger.ts","../src/components/Debounce.ts","../src/components/Throttle.ts","../src/bootstrapDebounce.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 debounce: string;\n throttle: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-debouncetarget\",\n tagNames: {\n debounce: \"wcs-debounce\",\n throttle: \"wcs-throttle\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (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 { IWcBindableProperty } from \"./types.js\";\n\n/**\n * Build the wc-bindable `properties` list for a debounce/throttle element, with\n * every event name derived from a single `prefix`. `<wcs-debounce>` uses\n * `\"wcs-debounce\"`, `<wcs-throttle>` uses `\"wcs-throttle\"`, so the two tags share\n * one engine (DebounceCore) yet advertise distinct event namespaces from one\n * source of truth — no hand-duplicated property tables (cf. the geolocation Shell\n * which overrode its wcBindable by hand).\n *\n * - `value` — the debounced value of the latest `source` write (value surface),\n * read from the `<prefix>:settled` event.\n * - `fired` — the coalesced args of the latest `trigger()` pulse (signal\n * surface), read from the `<prefix>:fired` event. Declared as a\n * property (not just an event) so state can subscribe via the\n * event-token protocol (`eventToken.fired: <name>`).\n * - `pending` — whether a debounce is currently in flight.\n */\nexport function makeDebounceProperties(prefix: string): IWcBindableProperty[] {\n return [\n { name: \"value\", event: `${prefix}:settled`, getter: (e: Event) => (e as CustomEvent).detail.value },\n { name: \"fired\", event: `${prefix}:fired`, getter: (e: Event) => (e as CustomEvent).detail.args },\n { name: \"pending\", event: `${prefix}:pending-changed` },\n ];\n}\n","import { IWcBindable, DebounceOptions } from \"../types.js\";\nimport { makeDebounceProperties } from \"../wcBindableFactory.js\";\n\ntype PendingKind = \"value\" | \"signal\" | null;\n\n/**\n * Headless debounce/throttle primitive. A framework-agnostic port of lodash's\n * `debounce` algorithm (`shouldInvoke` / `leadingEdge` / `trailingEdge` /\n * `remainingWait`, timed via `Date.now()`), exposed through the wc-bindable\n * protocol.\n *\n * It coalesces a stream of *signals* and emits at most one per quiet period.\n * Two surfaces share the single timer:\n *\n * - **value** — writing {@link setSource} schedules a settle; on fire the\n * debounced value is published via the `<prefix>:settled` event and the\n * `value` getter. Wire it as `source: src; value: debounced`.\n * - **signal** — calling {@link trigger}`(...args)` coalesces a burst of pulses;\n * on fire one `<prefix>:fired` event carries the latest args (relayed by state\n * through the command-token / event-token protocols).\n *\n * A given instance is meant to be used for one surface at a time. Because each\n * surface keeps its own field (`_value` vs `_lastArgs`), the getters never\n * pollute each other; if both are driven on one instance the *last* scheduled\n * signal wins (lodash's last-args semantics).\n *\n * Throttle is the same engine with `maxWait === wait` (and `leading` on by\n * default), so `<wcs-throttle>` reuses this class with a different `eventPrefix`.\n */\nexport class DebounceCore extends EventTarget {\n // The static contract advertises the *default* `wcs-debounce:*` event names. A\n // headless Core constructed with a non-default `eventPrefix` (e.g.\n // `\"wcs-throttle\"`) dispatches under that prefix, so its events won't match\n // this metadata — rebuild the property table with `makeDebounceProperties(prefix)`\n // for that case. (The `<wcs-throttle>` Shell already overrides its own\n // `wcBindable` this way, so binding through an element is always consistent.)\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: makeDebounceProperties(\"wcs-debounce\"),\n commands: [\n { name: \"trigger\" },\n { name: \"cancel\" },\n { name: \"flush\" },\n ],\n };\n\n private readonly _prefix: string;\n private _target: EventTarget;\n\n // Tuning (lodash knobs).\n private _wait: number = 0;\n private _leading: boolean = false;\n private _trailing: boolean = true;\n private _maxWait: number = 0;\n private _hasMaxWait: boolean = false;\n\n // Timing bookkeeping.\n private _lastCallTime: number | undefined = undefined;\n private _lastInvokeTime: number = 0;\n private _timerId: ReturnType<typeof setTimeout> | null = null;\n\n // Last-wins pending payload. `_pendingKind === null` doubles as the \"consumed /\n // empty\" sentinel (lodash clears `lastArgs` in invokeFunc): a trailing edge with\n // no fresh call since the last fire sees `null` and does not re-fire, which is\n // what stops a single leading pulse from also firing on the trailing edge.\n private _pendingKind: PendingKind = null;\n private _pendingValue: any = undefined;\n private _pendingArgs: any[] | undefined = undefined;\n\n // Observable state (getter backing).\n private _value: any = undefined;\n private _lastArgs: any[] = [];\n private _pending: boolean = false;\n\n constructor(prefix: string = \"wcs-debounce\", target?: EventTarget, options?: DebounceOptions) {\n super();\n this._prefix = prefix;\n this._target = target ?? this;\n if (options) {\n this.configure(options);\n }\n }\n\n // --- Configuration ---\n\n /**\n * Update the tuning knobs. The Shell calls this with the element's current\n * attributes before each schedule, so live attribute edits take effect on the\n * next signal. `maxWait` is clamped to at least `wait` (lodash semantics); an\n * absent / invalid `maxWait` disables maxWait entirely.\n */\n configure(options: DebounceOptions = {}): void {\n if (typeof options.wait === \"number\" && Number.isFinite(options.wait) && options.wait >= 0) {\n this._wait = options.wait;\n }\n if (typeof options.leading === \"boolean\") {\n this._leading = options.leading;\n }\n if (typeof options.trailing === \"boolean\") {\n this._trailing = options.trailing;\n }\n const mw = options.maxWait;\n if (typeof mw === \"number\" && Number.isFinite(mw) && mw >= 0) {\n this._maxWait = Math.max(mw, this._wait);\n this._hasMaxWait = true;\n } else {\n this._maxWait = 0;\n this._hasMaxWait = false;\n }\n }\n\n // --- Observable getters ---\n\n get value(): any {\n return this._value;\n }\n\n get fired(): any[] {\n return this._lastArgs;\n }\n\n get pending(): boolean {\n return this._pending;\n }\n\n // --- Public entry points ---\n\n /** Value surface: schedule a settle carrying `value` (last write wins). */\n setSource(value: any): void {\n this._schedule(\"value\", value, undefined);\n }\n\n /** Signal surface: coalesce a pulse carrying `args` (last call wins). */\n trigger(...args: any[]): void {\n this._schedule(\"signal\", undefined, args);\n }\n\n /** Drop any pending fire without emitting. Getters keep their last values. */\n cancel(): void {\n this._clearTimer();\n this._lastInvokeTime = 0;\n this._lastCallTime = undefined;\n this._pendingKind = null;\n this._pendingValue = undefined;\n this._pendingArgs = undefined;\n this._setPending(false);\n }\n\n /**\n * Emit any buffered payload immediately, then clear pending. Unlike lodash's\n * `flush` (which honours `trailing`), this fires whatever is buffered — the\n * command's intent is \"publish now\" — but is a no-op when nothing is pending.\n */\n flush(): void {\n if (this._timerId === null && this._pendingKind === null) return;\n const now = Date.now();\n this._clearTimer();\n if (this._pendingKind !== null) {\n this._invoke(now);\n }\n this._pendingKind = null;\n this._pendingValue = undefined;\n this._pendingArgs = undefined;\n this._setPending(false);\n }\n\n // --- Engine (lodash port) ---\n\n private _schedule(kind: Exclude<PendingKind, null>, value: any, args: any[] | undefined): void {\n const now = Date.now();\n const isInvoking = this._shouldInvoke(now);\n\n this._pendingKind = kind;\n if (kind === \"value\") {\n this._pendingValue = value;\n } else {\n this._pendingArgs = args;\n }\n this._lastCallTime = now;\n this._setPending(true);\n\n if (isInvoking) {\n if (this._timerId === null) {\n this._leadingEdge(now);\n return;\n }\n if (this._hasMaxWait) {\n // Continuous input that has reached maxWait: restart the steady timer and\n // invoke now so a fire happens at least every maxWait ms (throttle path).\n // Clear the pending handle first (lodash's \"tight loop\" branch does the\n // same) — overwriting `_timerId` without clearing would orphan the old\n // timer and let it fire spuriously later.\n this._clearTimer();\n this._timerId = setTimeout(this._timerExpired, this._wait);\n this._invoke(now);\n return;\n }\n }\n if (this._timerId === null) {\n this._timerId = setTimeout(this._timerExpired, this._wait);\n }\n }\n\n private _shouldInvoke(now: number): boolean {\n if (this._lastCallTime === undefined) return true;\n const timeSinceLastCall = now - this._lastCallTime;\n const timeSinceLastInvoke = now - this._lastInvokeTime;\n return (\n timeSinceLastCall >= this._wait ||\n timeSinceLastCall < 0 ||\n (this._hasMaxWait && timeSinceLastInvoke >= this._maxWait)\n );\n }\n\n private _remainingWait(now: number): number {\n const timeSinceLastCall = now - (this._lastCallTime as number);\n const timeSinceLastInvoke = now - this._lastInvokeTime;\n const timeWaiting = this._wait - timeSinceLastCall;\n return this._hasMaxWait\n ? Math.min(timeWaiting, this._maxWait - timeSinceLastInvoke)\n : timeWaiting;\n }\n\n private _timerExpired = (): void => {\n const now = Date.now();\n if (this._shouldInvoke(now)) {\n this._trailingEdge(now);\n return;\n }\n // Fired before the quiet period elapsed (a later call moved the deadline) —\n // re-arm for the remaining time instead of settling now.\n this._timerId = setTimeout(this._timerExpired, this._remainingWait(now));\n };\n\n private _leadingEdge(now: number): void {\n this._lastInvokeTime = now;\n this._timerId = setTimeout(this._timerExpired, this._wait);\n if (this._leading) {\n this._invoke(now);\n }\n }\n\n private _trailingEdge(now: number): void {\n this._timerId = null;\n // Only fire when there is an unconsumed payload (a call arrived since the last\n // invoke). After a lone leading fire `_pendingKind` is null, so a single pulse\n // does not double-fire on its trailing edge.\n if (this._trailing && this._pendingKind !== null) {\n this._invoke(now);\n }\n this._pendingKind = null;\n this._pendingValue = undefined;\n this._pendingArgs = undefined;\n this._setPending(false);\n }\n\n private _invoke(now: number): void {\n this._lastInvokeTime = now;\n const kind = this._pendingKind;\n if (kind === \"value\") {\n this._value = this._pendingValue;\n this._dispatch(`${this._prefix}:settled`, { value: this._value });\n } else if (kind === \"signal\") {\n this._lastArgs = this._pendingArgs ?? [];\n this._dispatch(`${this._prefix}:fired`, { args: this._lastArgs });\n }\n // Mark consumed (mirrors lodash clearing `lastArgs`).\n this._pendingKind = null;\n }\n\n private _setPending(pending: boolean): void {\n if (this._pending === pending) return;\n this._pending = pending;\n this._dispatch(`${this._prefix}:pending-changed`, pending);\n }\n\n private _dispatch(type: string, detail: any): void {\n this._target.dispatchEvent(new CustomEvent(type, { detail, bubbles: true }));\n }\n\n private _clearTimer(): void {\n if (this._timerId !== null) {\n clearTimeout(this._timerId);\n this._timerId = null;\n }\n }\n}\n","import { config } from \"./config.js\";\n\nlet registered = false;\n\ninterface Triggerable extends Element {\n trigger(...args: unknown[]): void;\n}\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const id = triggerElement.getAttribute(config.triggerAttribute);\n if (!id) return;\n\n // Resolve the registered constructors at call time (avoids a components ⇄\n // autoTrigger import cycle, mirroring <wcs-timer>). The DOM trigger fires a\n // single coalesced pulse on the referenced <wcs-debounce> / <wcs-throttle>.\n const DebounceCtor = customElements.get(config.tagNames.debounce);\n const ThrottleCtor = customElements.get(config.tagNames.throttle);\n const el = document.getElementById(id);\n if (!el) return;\n const isDebounce = DebounceCtor && el instanceof DebounceCtor;\n const isThrottle = ThrottleCtor && el instanceof ThrottleCtor;\n if (!isDebounce && !isThrottle) return;\n\n // Suppress the element's default action so a debounce can fire without\n // navigating. See README \"Optional DOM Triggering\".\n event.preventDefault();\n (el as unknown as Triggerable).trigger();\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, DebounceOptions } from \"../types.js\";\nimport { DebounceCore } from \"../core/DebounceCore.js\";\nimport { makeDebounceProperties } from \"../wcBindableFactory.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\n\nconst DEFAULT_WAIT = 250;\n\n/**\n * `<wcs-debounce>` — declarative debounce. See {@link DebounceCore} for the\n * engine. The `eventPrefix` defaults to `\"wcs-debounce\"`; `<wcs-throttle>`\n * subclasses this with `\"wcs-throttle\"` and throttle defaults.\n */\nexport class Debounce extends HTMLElement {\n static hasConnectedCallbackPromise = false;\n protected static eventPrefix = \"wcs-debounce\";\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: makeDebounceProperties(\"wcs-debounce\"),\n // `source` is the value-surface input (its debounced echo comes back on the\n // `value` property). `trigger` / `cancel` / `flush` are commands from the\n // Core. No momentary boolean `trigger` property exists — the signal surface\n // is driven by the `trigger` command (command-token) or a DOM click\n // (autoTrigger), which sidesteps the attribute/method name clash that forced\n // <wcs-geo>'s watch → watchPosition rename.\n inputs: [\n { name: \"source\" },\n { name: \"wait\", attribute: \"wait\" },\n { name: \"leading\", attribute: \"leading\" },\n { name: \"trailing\", attribute: \"trailing\" },\n { name: \"maxWait\", attribute: \"max-wait\" },\n ],\n commands: [\n { name: \"trigger\" },\n { name: \"cancel\" },\n { name: \"flush\" },\n ],\n };\n\n protected _core: DebounceCore;\n private _source: any = undefined;\n\n constructor() {\n super();\n this._core = new DebounceCore((this.constructor as typeof Debounce).eventPrefix, this);\n }\n\n // --- Attribute accessors ---\n\n get wait(): number {\n const attr = this.getAttribute(\"wait\");\n if (attr === null || attr.trim() === \"\") return this._defaultWait();\n // Strict parse via Number() (\"100px\" -> NaN, not 100). Fall back to the\n // default for any non-finite or negative value.\n const parsed = Number(attr);\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : this._defaultWait();\n }\n\n set wait(value: number) {\n this.setAttribute(\"wait\", String(value));\n }\n\n get leading(): boolean {\n return this.hasAttribute(\"leading\");\n }\n\n set leading(value: boolean) {\n if (value) {\n this.setAttribute(\"leading\", \"\");\n } else {\n this.removeAttribute(\"leading\");\n }\n }\n\n // `trailing` defaults to true; the boolean `no-trailing` attribute opts out (a\n // bare `trailing` attribute can't express \"false\", so the negative flag carries\n // the override).\n get trailing(): boolean {\n return !this.hasAttribute(\"no-trailing\");\n }\n\n set trailing(value: boolean) {\n if (value) {\n this.removeAttribute(\"no-trailing\");\n } else {\n this.setAttribute(\"no-trailing\", \"\");\n }\n }\n\n get maxWait(): number | undefined {\n const attr = this.getAttribute(\"max-wait\");\n if (attr === null || attr.trim() === \"\") return this._defaultMaxWait();\n const parsed = Number(attr);\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : this._defaultMaxWait();\n }\n\n set maxWait(value: number) {\n this.setAttribute(\"max-wait\", String(value));\n }\n\n // --- Value-surface input ---\n\n get source(): any {\n return this._source;\n }\n\n set source(value: any) {\n this._source = value;\n this._core.configure(this._options());\n this._core.setSource(value);\n }\n\n // --- Core delegated getters ---\n\n get value(): any {\n return this._core.value;\n }\n\n get fired(): any[] {\n return this._core.fired;\n }\n\n get pending(): boolean {\n return this._core.pending;\n }\n\n // --- Commands ---\n\n trigger(...args: any[]): void {\n this._core.configure(this._options());\n this._core.trigger(...args);\n }\n\n cancel(): void {\n this._core.cancel();\n }\n\n flush(): void {\n this._core.flush();\n }\n\n // --- Internal ---\n\n // Overridden by <wcs-throttle> to bias the defaults toward throttle (leading\n // on, maxWait pinned to wait).\n protected _defaultWait(): number {\n return DEFAULT_WAIT;\n }\n\n // Resolves the effective `leading` value (not a static default). It is a method\n // rather than reading `this.leading` directly because <wcs-throttle> inverts the\n // default (on, opt out via `no-leading`) while sharing the inherited `leading`\n // attribute setter — overriding the getter alone would desync getter and setter.\n protected _resolveLeading(): boolean {\n return this.leading;\n }\n\n protected _defaultMaxWait(): number | undefined {\n return undefined;\n }\n\n protected _options(): DebounceOptions {\n return {\n wait: this.wait,\n leading: this._resolveLeading(),\n trailing: this.trailing,\n maxWait: this.maxWait,\n };\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n }\n\n disconnectedCallback(): void {\n // Drop any in-flight timer so a detached element leaks nothing.\n this._core.cancel();\n }\n}\n","import { IWcBindable } from \"../types.js\";\nimport { Debounce } from \"./Debounce.js\";\nimport { makeDebounceProperties } from \"../wcBindableFactory.js\";\n\n/**\n * `<wcs-throttle>` — the same {@link DebounceCore} engine biased to throttle:\n * `maxWait === wait` (a fire happens at least every `wait` ms under continuous\n * input) and `leading` on by default. It advertises its own `wcs-throttle:*`\n * event namespace (via `makeDebounceProperties(\"wcs-throttle\")`), and the Core\n * dispatches under that prefix because the constructor passes it through.\n */\nexport class Throttle extends Debounce {\n protected static eventPrefix = \"wcs-throttle\";\n static wcBindable: IWcBindable = {\n ...Debounce.wcBindable,\n properties: makeDebounceProperties(\"wcs-throttle\"),\n };\n\n // leading defaults on for throttle; `no-leading` opts out (symmetric with the\n // inherited `no-trailing`).\n protected _resolveLeading(): boolean {\n return !this.hasAttribute(\"no-leading\");\n }\n\n // Pin maxWait to wait so throttle fires on a steady cadence; an explicit\n // `max-wait` attribute still overrides via the inherited getter.\n protected _defaultMaxWait(): number | undefined {\n return this.wait;\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapDebounce(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n","import { Debounce } from \"./components/Debounce.js\";\nimport { Throttle } from \"./components/Throttle.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.debounce)) {\n customElements.define(config.tagNames.debounce, Debounce);\n }\n if (!customElements.get(config.tagNames.throttle)) {\n customElements.define(config.tagNames.throttle, Throttle);\n }\n}\n"],"names":["_config","autoTrigger","triggerAttribute","tagNames","debounce","throttle","deepFreeze","obj","Object","freeze","key","keys","deepClone","clone","frozenConfig","config","getConfig","makeDebounceProperties","prefix","name","event","getter","e","detail","value","args","DebounceCore","EventTarget","static","protocol","version","properties","commands","_prefix","_target","_wait","_leading","_trailing","_maxWait","_hasMaxWait","_lastCallTime","undefined","_lastInvokeTime","_timerId","_pendingKind","_pendingValue","_pendingArgs","_value","_lastArgs","_pending","constructor","target","options","super","this","configure","wait","Number","isFinite","leading","trailing","mw","maxWait","Math","max","fired","pending","setSource","_schedule","trigger","cancel","_clearTimer","_setPending","flush","now","Date","_invoke","kind","isInvoking","_shouldInvoke","_leadingEdge","setTimeout","_timerExpired","timeSinceLastCall","timeSinceLastInvoke","_remainingWait","timeWaiting","min","_trailingEdge","_dispatch","type","dispatchEvent","CustomEvent","bubbles","clearTimeout","registered","handleClick","Element","triggerElement","closest","id","getAttribute","DebounceCtor","customElements","get","ThrottleCtor","el","document","getElementById","preventDefault","Debounce","HTMLElement","inputs","attribute","_core","_source","eventPrefix","attr","trim","_defaultWait","parsed","setAttribute","String","hasAttribute","removeAttribute","_defaultMaxWait","source","_options","_resolveLeading","connectedCallback","style","display","addEventListener","disconnectedCallback","Throttle","wcBindable","bootstrapDebounce","userConfig","partialConfig","assign","define"],"mappings":"AAWA,MAAMA,EAA2B,CAC/BC,aAAa,EACbC,iBAAkB,sBAClBC,SAAU,CACRC,SAAU,eACVC,SAAU,iBAId,SAASC,EAAcC,GACrB,GAAY,OAARA,GAA+B,iBAARA,EAAkB,OAAOA,EACpDC,OAAOC,OAAOF,GACd,IAAK,MAAMG,KAAOF,OAAOG,KAAKJ,GAC5BD,EAAYC,EAAgCG,IAE9C,OAAOH,CACT,CAEA,SAASK,EAAaL,GACpB,GAAY,OAARA,GAA+B,iBAARA,EAAkB,OAAOA,EACpD,MAAMM,EAAiC,CAAA,EACvC,IAAK,MAAMH,KAAOF,OAAOG,KAAKJ,GAC5BM,EAAMH,GAAOE,EAAWL,EAAgCG,IAE1D,OAAOG,CACT,CAEA,IAAIC,EAA+B,KAE5B,MAAMC,EAAkBf,WAEfgB,IAId,OAHKF,IACHA,EAAeR,EAAWM,EAAUZ,KAE/Bc,CACT,CC7BM,SAAUG,EAAuBC,GACrC,MAAO,CACL,CAAEC,KAAM,QAASC,MAAO,GAAGF,YAAkBG,OAASC,GAAcA,EAAkBC,OAAOC,OAC7F,CAAEL,KAAM,QAASC,MAAO,GAAGF,UAAgBG,OAASC,GAAcA,EAAkBC,OAAOE,MAC3F,CAAEN,KAAM,UAAWC,MAAO,GAAGF,qBAEjC,CCKM,MAAOQ,UAAqBC,YAOhCC,kBAAiC,CAC/BC,SAAU,cACVC,QAAS,EACTC,WAAYd,EAAuB,gBACnCe,SAAU,CACR,CAAEb,KAAM,WACR,CAAEA,KAAM,UACR,CAAEA,KAAM,WAIKc,QACTC,QAGAC,MAAgB,EAChBC,UAAoB,EACpBC,WAAqB,EACrBC,SAAmB,EACnBC,aAAuB,EAGvBC,mBAAoCC,EACpCC,gBAA0B,EAC1BC,SAAiD,KAMjDC,aAA4B,KAC5BC,mBAAqBJ,EACrBK,kBAAkCL,EAGlCM,YAAcN,EACdO,UAAmB,GACnBC,UAAoB,EAE5B,WAAAC,CAAYhC,EAAiB,eAAgBiC,EAAsBC,GACjEC,QACAC,KAAKrB,QAAUf,EACfoC,KAAKpB,QAAUiB,GAAUG,KACrBF,GACFE,KAAKC,UAAUH,EAEnB,CAUA,SAAAG,CAAUH,EAA2B,IACP,iBAAjBA,EAAQI,MAAqBC,OAAOC,SAASN,EAAQI,OAASJ,EAAQI,MAAQ,IACvFF,KAAKnB,MAAQiB,EAAQI,MAEQ,kBAApBJ,EAAQO,UACjBL,KAAKlB,SAAWgB,EAAQO,SAEM,kBAArBP,EAAQQ,WACjBN,KAAKjB,UAAYe,EAAQQ,UAE3B,MAAMC,EAAKT,EAAQU,QACD,iBAAPD,GAAmBJ,OAAOC,SAASG,IAAOA,GAAM,GACzDP,KAAKhB,SAAWyB,KAAKC,IAAIH,EAAIP,KAAKnB,OAClCmB,KAAKf,aAAc,IAEnBe,KAAKhB,SAAW,EAChBgB,KAAKf,aAAc,EAEvB,CAIA,SAAIf,GACF,OAAO8B,KAAKP,MACd,CAEA,SAAIkB,GACF,OAAOX,KAAKN,SACd,CAEA,WAAIkB,GACF,OAAOZ,KAAKL,QACd,CAKA,SAAAkB,CAAU3C,GACR8B,KAAKc,UAAU,QAAS5C,OAAOiB,EACjC,CAGA,OAAA4B,IAAW5C,GACT6B,KAAKc,UAAU,cAAU3B,EAAWhB,EACtC,CAGA,MAAA6C,GACEhB,KAAKiB,cACLjB,KAAKZ,gBAAkB,EACvBY,KAAKd,mBAAgBC,EACrBa,KAAKV,aAAe,KACpBU,KAAKT,mBAAgBJ,EACrBa,KAAKR,kBAAeL,EACpBa,KAAKkB,aAAY,EACnB,CAOA,KAAAC,GACE,GAAsB,OAAlBnB,KAAKX,UAA2C,OAAtBW,KAAKV,aAAuB,OAC1D,MAAM8B,EAAMC,KAAKD,MACjBpB,KAAKiB,cACqB,OAAtBjB,KAAKV,cACPU,KAAKsB,QAAQF,GAEfpB,KAAKV,aAAe,KACpBU,KAAKT,mBAAgBJ,EACrBa,KAAKR,kBAAeL,EACpBa,KAAKkB,aAAY,EACnB,CAIQ,SAAAJ,CAAUS,EAAkCrD,EAAYC,GAC9D,MAAMiD,EAAMC,KAAKD,MACXI,EAAaxB,KAAKyB,cAAcL,GAWtC,GATApB,KAAKV,aAAeiC,EACP,UAATA,EACFvB,KAAKT,cAAgBrB,EAErB8B,KAAKR,aAAerB,EAEtB6B,KAAKd,cAAgBkC,EACrBpB,KAAKkB,aAAY,GAEbM,EAAY,CACd,GAAsB,OAAlBxB,KAAKX,SAEP,YADAW,KAAK0B,aAAaN,GAGpB,GAAIpB,KAAKf,YASP,OAHAe,KAAKiB,cACLjB,KAAKX,SAAWsC,WAAW3B,KAAK4B,cAAe5B,KAAKnB,YACpDmB,KAAKsB,QAAQF,EAGjB,CACsB,OAAlBpB,KAAKX,WACPW,KAAKX,SAAWsC,WAAW3B,KAAK4B,cAAe5B,KAAKnB,OAExD,CAEQ,aAAA4C,CAAcL,GACpB,QAA2BjC,IAAvBa,KAAKd,cAA6B,OAAO,EAC7C,MAAM2C,EAAoBT,EAAMpB,KAAKd,cAC/B4C,EAAsBV,EAAMpB,KAAKZ,gBACvC,OACEyC,GAAqB7B,KAAKnB,OAC1BgD,EAAoB,GACnB7B,KAAKf,aAAe6C,GAAuB9B,KAAKhB,QAErD,CAEQ,cAAA+C,CAAeX,GACrB,MAAMS,EAAoBT,EAAOpB,KAAKd,cAChC4C,EAAsBV,EAAMpB,KAAKZ,gBACjC4C,EAAchC,KAAKnB,MAAQgD,EACjC,OAAO7B,KAAKf,YACRwB,KAAKwB,IAAID,EAAahC,KAAKhB,SAAW8C,GACtCE,CACN,CAEQJ,cAAgB,KACtB,MAAMR,EAAMC,KAAKD,MACbpB,KAAKyB,cAAcL,GACrBpB,KAAKkC,cAAcd,GAKrBpB,KAAKX,SAAWsC,WAAW3B,KAAK4B,cAAe5B,KAAK+B,eAAeX,KAG7D,YAAAM,CAAaN,GACnBpB,KAAKZ,gBAAkBgC,EACvBpB,KAAKX,SAAWsC,WAAW3B,KAAK4B,cAAe5B,KAAKnB,OAChDmB,KAAKlB,UACPkB,KAAKsB,QAAQF,EAEjB,CAEQ,aAAAc,CAAcd,GACpBpB,KAAKX,SAAW,KAIZW,KAAKjB,WAAmC,OAAtBiB,KAAKV,cACzBU,KAAKsB,QAAQF,GAEfpB,KAAKV,aAAe,KACpBU,KAAKT,mBAAgBJ,EACrBa,KAAKR,kBAAeL,EACpBa,KAAKkB,aAAY,EACnB,CAEQ,OAAAI,CAAQF,GACdpB,KAAKZ,gBAAkBgC,EACvB,MAAMG,EAAOvB,KAAKV,aACL,UAATiC,GACFvB,KAAKP,OAASO,KAAKT,cACnBS,KAAKmC,UAAU,GAAGnC,KAAKrB,kBAAmB,CAAET,MAAO8B,KAAKP,UACtC,WAAT8B,IACTvB,KAAKN,UAAYM,KAAKR,cAAgB,GACtCQ,KAAKmC,UAAU,GAAGnC,KAAKrB,gBAAiB,CAAER,KAAM6B,KAAKN,aAGvDM,KAAKV,aAAe,IACtB,CAEQ,WAAA4B,CAAYN,GACdZ,KAAKL,WAAaiB,IACtBZ,KAAKL,SAAWiB,EAChBZ,KAAKmC,UAAU,GAAGnC,KAAKrB,0BAA2BiC,GACpD,CAEQ,SAAAuB,CAAUC,EAAcnE,GAC9B+B,KAAKpB,QAAQyD,cAAc,IAAIC,YAAYF,EAAM,CAAEnE,SAAQsE,SAAS,IACtE,CAEQ,WAAAtB,GACgB,OAAlBjB,KAAKX,WACPmD,aAAaxC,KAAKX,UAClBW,KAAKX,SAAW,KAEpB,EC5RF,IAAIoD,GAAa,EAMjB,SAASC,EAAY5E,GACnB,MAAM+B,EAAS/B,EAAM+B,OACrB,KAAMA,aAAkB8C,SAAU,OAElC,MAAMC,EAAiB/C,EAAOgD,QAAiB,IAAIpF,EAAOb,qBAC1D,IAAKgG,EAAgB,OAErB,MAAME,EAAKF,EAAeG,aAAatF,EAAOb,kBAC9C,IAAKkG,EAAI,OAKT,MAAME,EAAeC,eAAeC,IAAIzF,EAAOZ,SAASC,UAClDqG,EAAeF,eAAeC,IAAIzF,EAAOZ,SAASE,UAClDqG,EAAKC,SAASC,eAAeR,GACnC,IAAKM,EAAI,QACUJ,GAAgBI,aAAcJ,GAC9BG,GAAgBC,aAAcD,KAKjDrF,EAAMyF,iBACLH,EAA8BrC,UACjC,CCpBM,MAAOyC,UAAiBC,YAC5BnF,oCAAqC,EAC3BA,mBAAqB,eAC/BA,kBAAiC,CAC/BC,SAAU,cACVC,QAAS,EACTC,WAAYd,EAAuB,gBAOnC+F,OAAQ,CACN,CAAE7F,KAAM,UACR,CAAEA,KAAM,OAAQ8F,UAAW,QAC3B,CAAE9F,KAAM,UAAW8F,UAAW,WAC9B,CAAE9F,KAAM,WAAY8F,UAAW,YAC/B,CAAE9F,KAAM,UAAW8F,UAAW,aAEhCjF,SAAU,CACR,CAAEb,KAAM,WACR,CAAEA,KAAM,UACR,CAAEA,KAAM,WAIF+F,MACFC,aAAe1E,EAEvB,WAAAS,GACEG,QACAC,KAAK4D,MAAQ,IAAIxF,EAAc4B,KAAKJ,YAAgCkE,YAAa9D,KACnF,CAIA,QAAIE,GACF,MAAM6D,EAAO/D,KAAK+C,aAAa,QAC/B,GAAa,OAATgB,GAAiC,KAAhBA,EAAKC,OAAe,OAAOhE,KAAKiE,eAGrD,MAAMC,EAAS/D,OAAO4D,GACtB,OAAO5D,OAAOC,SAAS8D,IAAWA,GAAU,EAAIA,EAASlE,KAAKiE,cAChE,CAEA,QAAI/D,CAAKhC,GACP8B,KAAKmE,aAAa,OAAQC,OAAOlG,GACnC,CAEA,WAAImC,GACF,OAAOL,KAAKqE,aAAa,UAC3B,CAEA,WAAIhE,CAAQnC,GACNA,EACF8B,KAAKmE,aAAa,UAAW,IAE7BnE,KAAKsE,gBAAgB,UAEzB,CAKA,YAAIhE,GACF,OAAQN,KAAKqE,aAAa,cAC5B,CAEA,YAAI/D,CAASpC,GACPA,EACF8B,KAAKsE,gBAAgB,eAErBtE,KAAKmE,aAAa,cAAe,GAErC,CAEA,WAAI3D,GACF,MAAMuD,EAAO/D,KAAK+C,aAAa,YAC/B,GAAa,OAATgB,GAAiC,KAAhBA,EAAKC,OAAe,OAAOhE,KAAKuE,kBACrD,MAAML,EAAS/D,OAAO4D,GACtB,OAAO5D,OAAOC,SAAS8D,IAAWA,GAAU,EAAIA,EAASlE,KAAKuE,iBAChE,CAEA,WAAI/D,CAAQtC,GACV8B,KAAKmE,aAAa,WAAYC,OAAOlG,GACvC,CAIA,UAAIsG,GACF,OAAOxE,KAAK6D,OACd,CAEA,UAAIW,CAAOtG,GACT8B,KAAK6D,QAAU3F,EACf8B,KAAK4D,MAAM3D,UAAUD,KAAKyE,YAC1BzE,KAAK4D,MAAM/C,UAAU3C,EACvB,CAIA,SAAIA,GACF,OAAO8B,KAAK4D,MAAM1F,KACpB,CAEA,SAAIyC,GACF,OAAOX,KAAK4D,MAAMjD,KACpB,CAEA,WAAIC,GACF,OAAOZ,KAAK4D,MAAMhD,OACpB,CAIA,OAAAG,IAAW5C,GACT6B,KAAK4D,MAAM3D,UAAUD,KAAKyE,YAC1BzE,KAAK4D,MAAM7C,WAAW5C,EACxB,CAEA,MAAA6C,GACEhB,KAAK4D,MAAM5C,QACb,CAEA,KAAAG,GACEnB,KAAK4D,MAAMzC,OACb,CAMU,YAAA8C,GACR,OA7IiB,GA8InB,CAMU,eAAAS,GACR,OAAO1E,KAAKK,OACd,CAEU,eAAAkE,GAEV,CAEU,QAAAE,GACR,MAAO,CACLvE,KAAMF,KAAKE,KACXG,QAASL,KAAK0E,kBACdpE,SAAUN,KAAKM,SACfE,QAASR,KAAKQ,QAElB,CAIA,iBAAAmE,GACE3E,KAAK4E,MAAMC,QAAU,OACjBpH,EAAOd,cD3IT8F,IACJA,GAAa,EACbY,SAASyB,iBAAiB,QAASpC,IC4InC,CAEA,oBAAAqC,GAEE/E,KAAK4D,MAAM5C,QACb,EC5KI,MAAOgE,UAAiBxB,EAClBlF,mBAAqB,eAC/BA,kBAAiC,IAC5BkF,EAASyB,WACZxG,WAAYd,EAAuB,iBAK3B,eAAA+G,GACR,OAAQ1E,KAAKqE,aAAa,aAC5B,CAIU,eAAAE,GACR,OAAOvE,KAAKE,IACd,ECxBI,SAAUgF,EAAkBC,GN6C5B,IAAoBC,EM5CpBD,IN6CqC,kBADjBC,EM3CZD,GN4CaxI,cACvBD,EAAQC,YAAcyI,EAAczI,aAEQ,iBAAnCyI,EAAcxI,mBACvBF,EAAQE,iBAAmBwI,EAAcxI,kBAEvCwI,EAAcvI,UAChBK,OAAOmI,OAAO3I,EAAQG,SAAUuI,EAAcvI,UAEhDW,EAAe,MOtDVyF,eAAeC,IAAIzF,EAAOZ,SAASC,WACtCmG,eAAeqC,OAAO7H,EAAOZ,SAASC,SAAU0G,GAE7CP,eAAeC,IAAIzF,EAAOZ,SAASE,WACtCkG,eAAeqC,OAAO7H,EAAOZ,SAASE,SAAUiI,EDApD"}
1
+ {"version":3,"file":"index.esm.min.js","sources":["../src/config.ts","../src/wcBindableFactory.ts","../src/core/DebounceCore.ts","../src/autoTrigger.ts","../src/components/Debounce.ts","../src/components/Throttle.ts","../src/bootstrapDebounce.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 debounce: string;\n throttle: string;\n };\n}\n\nconst _config: IInternalConfig = {\n autoTrigger: true,\n triggerAttribute: \"data-debouncetarget\",\n tagNames: {\n debounce: \"wcs-debounce\",\n throttle: \"wcs-throttle\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (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 { IWcBindableProperty } from \"./types.js\";\n\n/**\n * Build the wc-bindable `properties` list for a debounce/throttle element, with\n * every event name derived from a single `prefix`. `<wcs-debounce>` uses\n * `\"wcs-debounce\"`, `<wcs-throttle>` uses `\"wcs-throttle\"`, so the two tags share\n * one engine (DebounceCore) yet advertise distinct event namespaces from one\n * source of truth — no hand-duplicated property tables (cf. the geolocation Shell\n * which overrode its wcBindable by hand).\n *\n * - `value` — the debounced value of the latest `source` write (value surface),\n * read from the `<prefix>:settled` event.\n * - `fired` — the coalesced args of the latest `trigger()` pulse (signal\n * surface), read from the `<prefix>:fired` event. Declared as a\n * property (not just an event) so state can subscribe via the\n * event-token protocol (`eventToken.fired: <name>`).\n * - `pending` — whether a debounce is currently in flight.\n */\nexport function makeDebounceProperties(prefix: string): IWcBindableProperty[] {\n return [\n { name: \"value\", event: `${prefix}:settled`, getter: (e: Event) => (e as CustomEvent).detail.value },\n { name: \"fired\", event: `${prefix}:fired`, getter: (e: Event) => (e as CustomEvent).detail.args },\n { name: \"pending\", event: `${prefix}:pending-changed` },\n ];\n}\n","import { IWcBindable, DebounceOptions } from \"../types.js\";\nimport { makeDebounceProperties } from \"../wcBindableFactory.js\";\n\ntype PendingKind = \"value\" | \"signal\" | null;\n\n/**\n * Headless debounce/throttle primitive. A framework-agnostic port of lodash's\n * `debounce` algorithm (`shouldInvoke` / `leadingEdge` / `trailingEdge` /\n * `remainingWait`, timed via `Date.now()`), exposed through the wc-bindable\n * protocol.\n *\n * It coalesces a stream of *signals* and emits at most one per quiet period.\n * Two surfaces share the single timer:\n *\n * - **value** — writing {@link setSource} schedules a settle; on fire the\n * debounced value is published via the `<prefix>:settled` event and the\n * `value` getter. Wire it as `source: src; value: debounced`.\n * - **signal** — calling {@link trigger}`(...args)` coalesces a burst of pulses;\n * on fire one `<prefix>:fired` event carries the latest args (relayed by state\n * through the command-token / event-token protocols).\n *\n * A given instance is meant to be used for one surface at a time. Because each\n * surface keeps its own field (`_value` vs `_lastArgs`), the getters never\n * pollute each other; if both are driven on one instance the *last* scheduled\n * signal wins (lodash's last-args semantics).\n *\n * Throttle is the same engine with `maxWait === wait` (and `leading` on by\n * default), so `<wcs-throttle>` reuses this class with a different `eventPrefix`.\n */\nexport class DebounceCore extends EventTarget {\n // The static contract advertises the *default* `wcs-debounce:*` event names. A\n // headless Core constructed with a non-default `eventPrefix` (e.g.\n // `\"wcs-throttle\"`) dispatches under that prefix, so its events won't match\n // this metadata — rebuild the property table with `makeDebounceProperties(prefix)`\n // for that case. (The `<wcs-throttle>` Shell already overrides its own\n // `wcBindable` this way, so binding through an element is always consistent.)\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: makeDebounceProperties(\"wcs-debounce\"),\n commands: [\n { name: \"trigger\" },\n { name: \"cancel\" },\n { name: \"flush\" },\n ],\n };\n\n private readonly _prefix: string;\n private _target: EventTarget;\n\n // Tuning (lodash knobs).\n private _wait: number = 0;\n private _leading: boolean = false;\n private _trailing: boolean = true;\n private _maxWait: number = 0;\n private _hasMaxWait: boolean = false;\n\n // Timing bookkeeping.\n private _lastCallTime: number | undefined = undefined;\n private _lastInvokeTime: number = 0;\n private _timerId: ReturnType<typeof setTimeout> | null = null;\n // Generation stamped onto the live timer at arm time, compared in\n // `_timerExpired` against `_gen` to drop callbacks that outlived a dispose().\n private _timerGen: number = 0;\n\n // Last-wins pending payload. `_pendingKind === null` doubles as the \"consumed /\n // empty\" sentinel (lodash clears `lastArgs` in invokeFunc): a trailing edge with\n // no fresh call since the last fire sees `null` and does not re-fire, which is\n // what stops a single leading pulse from also firing on the trailing edge.\n private _pendingKind: PendingKind = null;\n private _pendingValue: any = undefined;\n private _pendingArgs: any[] | undefined = undefined;\n\n // Observable state (getter backing).\n private _value: any = undefined;\n private _lastArgs: any[] = [];\n private _pending: boolean = false;\n\n // Generation guard (§3.4): bumped on dispose() so a timer that survives a\n // tear-down can no longer settle into a detached element. A pending timer is\n // also cleared by dispose() → cancel(), so the guard is defensive: it stops\n // any callback that has already been dequeued by the host event loop from\n // writing state after dispose().\n private _gen = 0;\n // SSR (§3.8): the debounce engine is purely timer-driven with no asynchronous\n // probe to await, so readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n constructor(prefix: string = \"wcs-debounce\", target?: EventTarget, options?: DebounceOptions) {\n super();\n this._prefix = prefix;\n this._target = target ?? this;\n if (options) {\n this.configure(options);\n }\n }\n\n // --- Lifecycle (§3.5 / §3.8) ---\n\n get ready(): Promise<void> {\n return this._ready;\n }\n\n // Debounce is command-driven (setSource / trigger schedule work on demand)\n // with no subscription to establish, so observe() is an idempotent no-op that\n // resolves once ready.\n observe(): Promise<void> {\n return this._ready;\n }\n\n // Tear down the pending timer and invalidate the generation so a stale timer\n // callback cannot fire after the element is detached.\n dispose(): void {\n this._gen++;\n this.cancel();\n }\n\n // --- Configuration ---\n\n /**\n * Update the tuning knobs. The Shell calls this with the element's current\n * attributes before each schedule, so live attribute edits take effect on the\n * next signal. `maxWait` is clamped to at least `wait` (lodash semantics); an\n * absent / invalid `maxWait` disables maxWait entirely.\n */\n configure(options: DebounceOptions = {}): void {\n if (typeof options.wait === \"number\" && Number.isFinite(options.wait) && options.wait >= 0) {\n this._wait = options.wait;\n }\n if (typeof options.leading === \"boolean\") {\n this._leading = options.leading;\n }\n if (typeof options.trailing === \"boolean\") {\n this._trailing = options.trailing;\n }\n const mw = options.maxWait;\n if (typeof mw === \"number\" && Number.isFinite(mw) && mw >= 0) {\n this._maxWait = Math.max(mw, this._wait);\n this._hasMaxWait = true;\n } else {\n this._maxWait = 0;\n this._hasMaxWait = false;\n }\n }\n\n // --- Observable getters ---\n\n get value(): any {\n return this._value;\n }\n\n get fired(): any[] {\n return this._lastArgs;\n }\n\n get pending(): boolean {\n return this._pending;\n }\n\n // --- Public entry points ---\n\n /** Value surface: schedule a settle carrying `value` (last write wins). */\n setSource(value: any): void {\n this._schedule(\"value\", value, undefined);\n }\n\n /** Signal surface: coalesce a pulse carrying `args` (last call wins). */\n trigger(...args: any[]): void {\n this._schedule(\"signal\", undefined, args);\n }\n\n /** Drop any pending fire without emitting. Getters keep their last values. */\n cancel(): void {\n this._clearTimer();\n this._lastInvokeTime = 0;\n this._lastCallTime = undefined;\n this._pendingKind = null;\n this._pendingValue = undefined;\n this._pendingArgs = undefined;\n this._setPending(false);\n }\n\n /**\n * Emit any buffered payload immediately, then clear pending. Unlike lodash's\n * `flush` (which honours `trailing`), this fires whatever is buffered — the\n * command's intent is \"publish now\" — but is a no-op when nothing is pending.\n */\n flush(): void {\n if (this._timerId === null && this._pendingKind === null) return;\n const now = Date.now();\n this._clearTimer();\n if (this._pendingKind !== null) {\n this._invoke(now);\n }\n this._pendingKind = null;\n this._pendingValue = undefined;\n this._pendingArgs = undefined;\n this._setPending(false);\n }\n\n // --- Engine (lodash port) ---\n\n private _schedule(kind: Exclude<PendingKind, null>, value: any, args: any[] | undefined): void {\n const now = Date.now();\n const isInvoking = this._shouldInvoke(now);\n\n this._pendingKind = kind;\n if (kind === \"value\") {\n this._pendingValue = value;\n } else {\n this._pendingArgs = args;\n }\n this._lastCallTime = now;\n this._setPending(true);\n\n if (isInvoking) {\n if (this._timerId === null) {\n this._leadingEdge(now);\n return;\n }\n if (this._hasMaxWait) {\n // Continuous input that has reached maxWait: restart the steady timer and\n // invoke now so a fire happens at least every maxWait ms (throttle path).\n // Clear the pending handle first (lodash's \"tight loop\" branch does the\n // same) — overwriting `_timerId` without clearing would orphan the old\n // timer and let it fire spuriously later.\n this._clearTimer();\n this._armTimer(this._wait);\n this._invoke(now);\n return;\n }\n }\n if (this._timerId === null) {\n this._armTimer(this._wait);\n }\n }\n\n private _shouldInvoke(now: number): boolean {\n if (this._lastCallTime === undefined) return true;\n const timeSinceLastCall = now - this._lastCallTime;\n const timeSinceLastInvoke = now - this._lastInvokeTime;\n return (\n timeSinceLastCall >= this._wait ||\n timeSinceLastCall < 0 ||\n (this._hasMaxWait && timeSinceLastInvoke >= this._maxWait)\n );\n }\n\n private _remainingWait(now: number): number {\n const timeSinceLastCall = now - (this._lastCallTime as number);\n const timeSinceLastInvoke = now - this._lastInvokeTime;\n const timeWaiting = this._wait - timeSinceLastCall;\n return this._hasMaxWait\n ? Math.min(timeWaiting, this._maxWait - timeSinceLastInvoke)\n : timeWaiting;\n }\n\n private _timerExpired = (): void => {\n // §3.4 generation guard: a timer dequeued by the host before dispose() could\n // clear it must not settle into a torn-down element. Capture the generation\n // when the timer is scheduled (via `_armTimer`) and bail if it is stale.\n if (this._timerGen !== this._gen) return;\n const now = Date.now();\n if (this._shouldInvoke(now)) {\n this._trailingEdge(now);\n return;\n }\n // Fired before the quiet period elapsed (a later call moved the deadline) —\n // re-arm for the remaining time instead of settling now.\n this._armTimer(this._remainingWait(now));\n };\n\n private _leadingEdge(now: number): void {\n this._lastInvokeTime = now;\n this._armTimer(this._wait);\n if (this._leading) {\n this._invoke(now);\n }\n }\n\n private _trailingEdge(now: number): void {\n this._timerId = null;\n // Only fire when there is an unconsumed payload (a call arrived since the last\n // invoke). After a lone leading fire `_pendingKind` is null, so a single pulse\n // does not double-fire on its trailing edge.\n if (this._trailing && this._pendingKind !== null) {\n this._invoke(now);\n }\n this._pendingKind = null;\n this._pendingValue = undefined;\n this._pendingArgs = undefined;\n this._setPending(false);\n }\n\n private _invoke(now: number): void {\n this._lastInvokeTime = now;\n const kind = this._pendingKind;\n if (kind === \"value\") {\n this._value = this._pendingValue;\n this._dispatch(`${this._prefix}:settled`, { value: this._value });\n } else if (kind === \"signal\") {\n this._lastArgs = this._pendingArgs ?? [];\n this._dispatch(`${this._prefix}:fired`, { args: this._lastArgs });\n }\n // Mark consumed (mirrors lodash clearing `lastArgs`).\n this._pendingKind = null;\n }\n\n private _setPending(pending: boolean): void {\n if (this._pending === pending) return;\n this._pending = pending;\n this._dispatch(`${this._prefix}:pending-changed`, pending);\n }\n\n private _dispatch(type: string, detail: any): void {\n this._target.dispatchEvent(new CustomEvent(type, { detail, bubbles: true }));\n }\n\n // Arm the settle timer, stamping the current generation so a callback that the\n // host dequeues after a dispose() can detect it is stale (§3.4).\n private _armTimer(delay: number): void {\n this._timerGen = this._gen;\n this._timerId = setTimeout(this._timerExpired, delay);\n }\n\n private _clearTimer(): void {\n if (this._timerId !== null) {\n clearTimeout(this._timerId);\n this._timerId = null;\n }\n }\n}\n","import { config } from \"./config.js\";\n\nlet registered = false;\n\ninterface Triggerable extends Element {\n trigger(...args: unknown[]): void;\n}\n\nfunction handleClick(event: Event): void {\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n const triggerElement = target.closest<Element>(`[${config.triggerAttribute}]`);\n if (!triggerElement) return;\n\n const id = triggerElement.getAttribute(config.triggerAttribute);\n if (!id) return;\n\n // Resolve the registered constructors at call time (avoids a components ⇄\n // autoTrigger import cycle, mirroring <wcs-timer>). The DOM trigger fires a\n // single coalesced pulse on the referenced <wcs-debounce> / <wcs-throttle>.\n const DebounceCtor = customElements.get(config.tagNames.debounce);\n const ThrottleCtor = customElements.get(config.tagNames.throttle);\n const el = document.getElementById(id);\n if (!el) return;\n const isDebounce = DebounceCtor && el instanceof DebounceCtor;\n const isThrottle = ThrottleCtor && el instanceof ThrottleCtor;\n if (!isDebounce && !isThrottle) return;\n\n // Suppress the element's default action so a debounce can fire without\n // navigating. See README \"Optional DOM Triggering\".\n event.preventDefault();\n (el as unknown as Triggerable).trigger();\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, DebounceOptions } from \"../types.js\";\nimport { DebounceCore } from \"../core/DebounceCore.js\";\nimport { makeDebounceProperties } from \"../wcBindableFactory.js\";\nimport { registerAutoTrigger } from \"../autoTrigger.js\";\n\nconst DEFAULT_WAIT = 250;\n\n/**\n * `<wcs-debounce>` — declarative debounce. See {@link DebounceCore} for the\n * engine. The `eventPrefix` defaults to `\"wcs-debounce\"`; `<wcs-throttle>`\n * subclasses this with `\"wcs-throttle\"` and throttle defaults.\n */\nexport class Debounce extends HTMLElement {\n static hasConnectedCallbackPromise = true;\n protected static eventPrefix = \"wcs-debounce\";\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: makeDebounceProperties(\"wcs-debounce\"),\n // `source` is the value-surface input (its debounced echo comes back on the\n // `value` property). `trigger` / `cancel` / `flush` are commands from the\n // Core. No momentary boolean `trigger` property exists — the signal surface\n // is driven by the `trigger` command (command-token) or a DOM click\n // (autoTrigger), which sidesteps the attribute/method name clash that forced\n // <wcs-geo>'s watch → watchPosition rename.\n inputs: [\n { name: \"source\" },\n { name: \"wait\", attribute: \"wait\" },\n { name: \"leading\", attribute: \"leading\" },\n { name: \"trailing\", attribute: \"trailing\" },\n { name: \"maxWait\", attribute: \"max-wait\" },\n ],\n commands: [\n { name: \"trigger\" },\n { name: \"cancel\" },\n { name: \"flush\" },\n ],\n };\n\n protected _core: DebounceCore;\n private _source: any = undefined;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n\n constructor() {\n super();\n this._core = new DebounceCore((this.constructor as typeof Debounce).eventPrefix, this);\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Attribute accessors ---\n\n get wait(): number {\n const attr = this.getAttribute(\"wait\");\n if (attr === null || attr.trim() === \"\") return this._defaultWait();\n // Strict parse via Number() (\"100px\" -> NaN, not 100). Fall back to the\n // default for any non-finite or negative value.\n const parsed = Number(attr);\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : this._defaultWait();\n }\n\n set wait(value: number) {\n this.setAttribute(\"wait\", String(value));\n }\n\n get leading(): boolean {\n return this.hasAttribute(\"leading\");\n }\n\n set leading(value: boolean) {\n if (value) {\n this.setAttribute(\"leading\", \"\");\n } else {\n this.removeAttribute(\"leading\");\n }\n }\n\n // `trailing` defaults to true; the boolean `no-trailing` attribute opts out (a\n // bare `trailing` attribute can't express \"false\", so the negative flag carries\n // the override).\n get trailing(): boolean {\n return !this.hasAttribute(\"no-trailing\");\n }\n\n set trailing(value: boolean) {\n if (value) {\n this.removeAttribute(\"no-trailing\");\n } else {\n this.setAttribute(\"no-trailing\", \"\");\n }\n }\n\n get maxWait(): number | undefined {\n const attr = this.getAttribute(\"max-wait\");\n if (attr === null || attr.trim() === \"\") return this._defaultMaxWait();\n const parsed = Number(attr);\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : this._defaultMaxWait();\n }\n\n set maxWait(value: number) {\n this.setAttribute(\"max-wait\", String(value));\n }\n\n // --- Value-surface input ---\n\n get source(): any {\n return this._source;\n }\n\n set source(value: any) {\n this._source = value;\n this._core.configure(this._options());\n this._core.setSource(value);\n }\n\n // --- Core delegated getters ---\n\n get value(): any {\n return this._core.value;\n }\n\n get fired(): any[] {\n return this._core.fired;\n }\n\n get pending(): boolean {\n return this._core.pending;\n }\n\n // --- Commands ---\n\n trigger(...args: any[]): void {\n this._core.configure(this._options());\n this._core.trigger(...args);\n }\n\n cancel(): void {\n this._core.cancel();\n }\n\n flush(): void {\n this._core.flush();\n }\n\n // --- Internal ---\n\n // Overridden by <wcs-throttle> to bias the defaults toward throttle (leading\n // on, maxWait pinned to wait).\n protected _defaultWait(): number {\n return DEFAULT_WAIT;\n }\n\n // Resolves the effective `leading` value (not a static default). It is a method\n // rather than reading `this.leading` directly because <wcs-throttle> inverts the\n // default (on, opt out via `no-leading`) while sharing the inherited `leading`\n // attribute setter — overriding the getter alone would desync getter and setter.\n protected _resolveLeading(): boolean {\n return this.leading;\n }\n\n protected _defaultMaxWait(): number | undefined {\n return undefined;\n }\n\n protected _options(): DebounceOptions {\n return {\n wait: this.wait,\n leading: this._resolveLeading(),\n trailing: this.trailing,\n maxWait: this.maxWait,\n };\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this.style.display = \"none\";\n if (config.autoTrigger) {\n registerAutoTrigger();\n }\n // §4.1/§4.4 Shell SSR: expose connectedCallbackPromise backed by observe().\n // observe() is a no-op resolving once ready (the engine is command-driven).\n this._connectedCallbackPromise = this._core.observe();\n }\n\n disconnectedCallback(): void {\n // Drop any in-flight timer so a detached element leaks nothing, and bump the\n // Core generation so a surviving timer callback cannot settle (§3.5).\n this._core.dispose();\n }\n}\n","import { IWcBindable } from \"../types.js\";\nimport { Debounce } from \"./Debounce.js\";\nimport { makeDebounceProperties } from \"../wcBindableFactory.js\";\n\n/**\n * `<wcs-throttle>` — the same {@link DebounceCore} engine biased to throttle:\n * `maxWait === wait` (a fire happens at least every `wait` ms under continuous\n * input) and `leading` on by default. It advertises its own `wcs-throttle:*`\n * event namespace (via `makeDebounceProperties(\"wcs-throttle\")`), and the Core\n * dispatches under that prefix because the constructor passes it through.\n */\nexport class Throttle extends Debounce {\n protected static eventPrefix = \"wcs-throttle\";\n static wcBindable: IWcBindable = {\n ...Debounce.wcBindable,\n properties: makeDebounceProperties(\"wcs-throttle\"),\n };\n\n // leading defaults on for throttle; `no-leading` opts out (symmetric with the\n // inherited `no-trailing`).\n protected _resolveLeading(): boolean {\n return !this.hasAttribute(\"no-leading\");\n }\n\n // Pin maxWait to wait so throttle fires on a steady cadence; an explicit\n // `max-wait` attribute still overrides via the inherited getter.\n protected _defaultMaxWait(): number | undefined {\n return this.wait;\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapDebounce(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n","import { Debounce } from \"./components/Debounce.js\";\nimport { Throttle } from \"./components/Throttle.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.debounce)) {\n customElements.define(config.tagNames.debounce, Debounce);\n }\n if (!customElements.get(config.tagNames.throttle)) {\n customElements.define(config.tagNames.throttle, Throttle);\n }\n}\n"],"names":["_config","autoTrigger","triggerAttribute","tagNames","debounce","throttle","deepFreeze","obj","Object","freeze","key","keys","deepClone","clone","frozenConfig","config","getConfig","makeDebounceProperties","prefix","name","event","getter","e","detail","value","args","DebounceCore","EventTarget","static","protocol","version","properties","commands","_prefix","_target","_wait","_leading","_trailing","_maxWait","_hasMaxWait","_lastCallTime","undefined","_lastInvokeTime","_timerId","_timerGen","_pendingKind","_pendingValue","_pendingArgs","_value","_lastArgs","_pending","_gen","_ready","Promise","resolve","constructor","target","options","super","this","configure","ready","observe","dispose","cancel","wait","Number","isFinite","leading","trailing","mw","maxWait","Math","max","fired","pending","setSource","_schedule","trigger","_clearTimer","_setPending","flush","now","Date","_invoke","kind","isInvoking","_shouldInvoke","_leadingEdge","_armTimer","timeSinceLastCall","timeSinceLastInvoke","_remainingWait","timeWaiting","min","_timerExpired","_trailingEdge","_dispatch","type","dispatchEvent","CustomEvent","bubbles","delay","setTimeout","clearTimeout","registered","handleClick","Element","triggerElement","closest","id","getAttribute","DebounceCtor","customElements","get","ThrottleCtor","el","document","getElementById","preventDefault","Debounce","HTMLElement","inputs","attribute","_core","_source","_connectedCallbackPromise","eventPrefix","connectedCallbackPromise","attr","trim","_defaultWait","parsed","setAttribute","String","hasAttribute","removeAttribute","_defaultMaxWait","source","_options","_resolveLeading","connectedCallback","style","display","addEventListener","disconnectedCallback","Throttle","wcBindable","bootstrapDebounce","userConfig","partialConfig","assign","define"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wcstack/debounce",
3
- "version": "1.13.1",
3
+ "version": "1.15.0",
4
4
  "description": "Declarative debounce/throttle components for Web Components. Framework-agnostic signal coalescing via wc-bindable-protocol.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.esm.js",