@wcstack/intersection 1.12.0 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -137,7 +137,8 @@ Point `target` at a section elsewhere in the document; bind `intersecting` to hi
137
137
 
138
138
  | Command | Description |
139
139
  |---------------|-------------|
140
- | `observe()` | Re-resolve `target` / `root` from the DOM and (re)start observing. |
140
+ | `observe()` | Re-resolve `target` / `root` from the DOM and (re)start observing. Idempotent: an unchanged target+options is a no-op (no fresh callback). |
141
+ | `reobserve()` | Force a fresh observation even when `target` / options are unchanged — tears the observer down and rebuilds it, so a new initial callback fires for the *current* visibility. Use to re-arm an edge-driven consumer (e.g. infinite scroll) after the layout shifted without a visibility transition. `observing` stays `true` across a successful re-arm (no false blip). |
141
142
  | `unobserve()` | Stop observing the current target. |
142
143
  | `disconnect()`| Stop all observation. |
143
144
  | `reset()` | Clear the `visible` latch so a later intersection can set it again. |
@@ -159,7 +160,7 @@ IntersectionCore.wcBindable = {
159
160
  { name: "observing", event: "wcs-intersect:observing-changed" },
160
161
  ],
161
162
  commands: [
162
- { name: "observe" }, { name: "unobserve" }, { name: "disconnect" }, { name: "reset" },
163
+ { name: "observe" }, { name: "reobserve" }, { name: "unobserve" }, { name: "disconnect" }, { name: "reset" },
163
164
  ],
164
165
  };
165
166
  ```
package/dist/index.d.ts CHANGED
@@ -194,6 +194,22 @@ declare class IntersectionCore extends EventTarget {
194
194
  * the other @wcstack sensors.
195
195
  */
196
196
  observe(element: Element, options?: IntersectOptions): void;
197
+ /**
198
+ * Force a fresh observation of `element`, even when it matches the currently
199
+ * observed target+options. Unlike observe() — which is idempotent and
200
+ * early-returns for an unchanged target+options *without* re-delivering a
201
+ * callback — this always tears the observer down and rebuilds it, so a new
202
+ * IntersectionObserver delivers an initial callback for the element's CURRENT
203
+ * visibility.
204
+ *
205
+ * This is the way to re-arm an edge-driven consumer (e.g. infinite scroll) after
206
+ * the layout changed without a visibility *transition*: IntersectionObserver only
207
+ * fires on a change, so appending a short page that leaves the sentinel visible
208
+ * yields no new callback — a bare observe() can't help (idempotent), but a
209
+ * reobserve() re-reads the current state. Same never-throw guarantees as
210
+ * observe(); `observing` stays true across a successful re-arm (no false blip).
211
+ */
212
+ reobserve(element: Element, options?: IntersectOptions): void;
197
213
  /**
198
214
  * Stop observing `element`. A no-op if it is not the currently observed
199
215
  * element. The observer instance is torn down (single-target Core), so a later
@@ -257,6 +273,16 @@ declare class WcsIntersect extends HTMLElement {
257
273
  set trigger(value: boolean);
258
274
  /** Re-resolve the target/root from the DOM and (re)start observing. */
259
275
  observe(): void;
276
+ /**
277
+ * Force a fresh observation: re-resolve target/root from the DOM and re-observe
278
+ * even when nothing changed. Unlike observe() (idempotent for an unchanged
279
+ * target+options), this rebuilds the observer so a new initial callback fires for
280
+ * the current visibility — the way to re-arm an edge-driven consumer after the
281
+ * layout shifted without a visibility transition (e.g. infinite scroll appended a
282
+ * short page that left this sentinel in view). Resolution/teardown rules match
283
+ * observe(): an unresolvable target tears down any stale observation.
284
+ */
285
+ reobserve(): void;
260
286
  unobserve(): void;
261
287
  disconnect(): void;
262
288
  reset(): void;
package/dist/index.esm.js CHANGED
@@ -72,6 +72,7 @@ class IntersectionCore extends EventTarget {
72
72
  ],
73
73
  commands: [
74
74
  { name: "observe" },
75
+ { name: "reobserve" },
75
76
  { name: "unobserve" },
76
77
  { name: "disconnect" },
77
78
  { name: "reset" },
@@ -168,6 +169,25 @@ class IntersectionCore extends EventTarget {
168
169
  observer.observe(element);
169
170
  this._setObserving(true);
170
171
  }
172
+ /**
173
+ * Force a fresh observation of `element`, even when it matches the currently
174
+ * observed target+options. Unlike observe() — which is idempotent and
175
+ * early-returns for an unchanged target+options *without* re-delivering a
176
+ * callback — this always tears the observer down and rebuilds it, so a new
177
+ * IntersectionObserver delivers an initial callback for the element's CURRENT
178
+ * visibility.
179
+ *
180
+ * This is the way to re-arm an edge-driven consumer (e.g. infinite scroll) after
181
+ * the layout changed without a visibility *transition*: IntersectionObserver only
182
+ * fires on a change, so appending a short page that leaves the sentinel visible
183
+ * yields no new callback — a bare observe() can't help (idempotent), but a
184
+ * reobserve() re-reads the current state. Same never-throw guarantees as
185
+ * observe(); `observing` stays true across a successful re-arm (no false blip).
186
+ */
187
+ reobserve(element, options = {}) {
188
+ this._teardownObserver();
189
+ this.observe(element, options);
190
+ }
171
191
  /**
172
192
  * Stop observing `element`. A no-op if it is not the currently observed
173
193
  * element. The observer instance is torn down (single-target Core), so a later
@@ -292,8 +312,8 @@ class WcsIntersect extends HTMLElement {
292
312
  ],
293
313
  // Shell-level settable surface. Each input carries its mirrored `attribute`
294
314
  // hint; `trigger` has none — it is a momentary command-property, not a
295
- // declarative attribute. The observe / unobserve / disconnect / reset commands
296
- // are inherited from the Core via the spread above.
315
+ // declarative attribute. The observe / reobserve / unobserve / disconnect /
316
+ // reset commands are inherited from the Core via the spread above.
297
317
  inputs: [
298
318
  { name: "target", attribute: "target" },
299
319
  { name: "root", attribute: "root" },
@@ -428,6 +448,24 @@ class WcsIntersect extends HTMLElement {
428
448
  }
429
449
  this._core.observe(element, this._options());
430
450
  }
451
+ /**
452
+ * Force a fresh observation: re-resolve target/root from the DOM and re-observe
453
+ * even when nothing changed. Unlike observe() (idempotent for an unchanged
454
+ * target+options), this rebuilds the observer so a new initial callback fires for
455
+ * the current visibility — the way to re-arm an edge-driven consumer after the
456
+ * layout shifted without a visibility transition (e.g. infinite scroll appended a
457
+ * short page that left this sentinel in view). Resolution/teardown rules match
458
+ * observe(): an unresolvable target tears down any stale observation.
459
+ */
460
+ reobserve() {
461
+ const { element, display } = this._resolveTarget();
462
+ this.style.display = display;
463
+ if (!element) {
464
+ this._core.disconnect();
465
+ return;
466
+ }
467
+ this._core.reobserve(element, this._options());
468
+ }
431
469
  unobserve() {
432
470
  // Single-target Shell: "stop observing my target" is exactly the Core's
433
471
  // teardown. Delegate to the Core's tracked state rather than re-resolving the
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/config.ts","../src/core/IntersectionCore.ts","../src/components/Intersect.ts","../src/registerComponents.ts","../src/bootstrapIntersection.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n tagNames: {\n intersect: string;\n };\n}\n\nconst _config: IInternalConfig = {\n tagNames: {\n intersect: \"wcs-intersect\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { IWcBindable, IntersectOptions, WcsIntersectEntry, WcsIntersectRect } from \"../types.js\";\n\n/**\n * Headless visibility primitive. A thin, framework-agnostic wrapper around the\n * IntersectionObserver API exposed through the wc-bindable protocol.\n *\n * Unlike the other @wcstack sensors (geolocation / timer / websocket), the thing\n * being observed is a *DOM element* — so `observe()` takes the target node. The\n * Core stays DOM-resolution-agnostic: it observes whatever element it is handed\n * (the Shell resolves `target` / `root` selectors before calling). It is a\n * read-only producer — element/layout → state only, with no element-bound path.\n *\n * Every observer callback is published via the single `wcs-intersect:change`\n * event; `intersecting` / `ratio` are read from it through getters (mirroring how\n * GeolocationCore exposes latitude/longitude from one `wcs-geo:position` event),\n * so an observer that binds any of them is notified on every change.\n *\n * `visible` is a latch: it flips to `true` the first time the target intersects\n * and stays `true` until `reset()` — ideal for one-way lazy-load bindings\n * (`src@visible`). `observing` reflects whether an observation is currently\n * active (like TimerCore's `running`).\n *\n * Single-target by design: the Shell observes exactly one element, so the state\n * reflects that element. Multi-target observation is intentionally out of scope.\n */\nexport class IntersectionCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"entry\", event: \"wcs-intersect:change\" },\n { name: \"intersecting\", event: \"wcs-intersect:change\", getter: (e: Event) => (e as CustomEvent).detail.isIntersecting },\n { name: \"ratio\", event: \"wcs-intersect:change\", getter: (e: Event) => (e as CustomEvent).detail.intersectionRatio },\n { name: \"visible\", event: \"wcs-intersect:visible-changed\" },\n { name: \"observing\", event: \"wcs-intersect:observing-changed\" },\n ],\n commands: [\n { name: \"observe\" },\n { name: \"unobserve\" },\n { name: \"disconnect\" },\n { name: \"reset\" },\n ],\n };\n\n private _target: EventTarget;\n\n // The live observer and the single element it observes. Options are kept so a\n // repeated observe() with identical options is a no-op (avoids the create→\n // observe→disconnect churn an autoloader upgrade can otherwise cause).\n private _observer: IntersectionObserver | null = null;\n private _observed: Element | null = null;\n private _options: IntersectOptions = {};\n\n private _entry: WcsIntersectEntry | null = null;\n private _visible: boolean = false;\n private _observing: boolean = false;\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get entry(): WcsIntersectEntry | null {\n return this._entry;\n }\n\n get intersecting(): boolean {\n return this._entry ? this._entry.isIntersecting : false;\n }\n\n get ratio(): number {\n return this._entry ? this._entry.intersectionRatio : 0;\n }\n\n get visible(): boolean {\n return this._visible;\n }\n\n get observing(): boolean {\n return this._observing;\n }\n\n // --- State setters with event dispatch ---\n\n private _setEntry(entry: WcsIntersectEntry): void {\n // No same-value guard: `change` carries event semantics (every callback is a\n // distinct observation) and `intersecting` / `ratio` are derived getters that\n // must re-fire on each entry, mirroring GeolocationCore's `position`.\n this._entry = entry;\n this._target.dispatchEvent(new CustomEvent(\"wcs-intersect:change\", {\n detail: entry,\n bubbles: true,\n }));\n }\n\n private _setVisible(visible: boolean): void {\n if (this._visible === visible) return;\n this._visible = visible;\n this._target.dispatchEvent(new CustomEvent(\"wcs-intersect:visible-changed\", {\n detail: visible,\n bubbles: true,\n }));\n }\n\n private _setObserving(observing: boolean): void {\n if (this._observing === observing) return;\n this._observing = observing;\n this._target.dispatchEvent(new CustomEvent(\"wcs-intersect:observing-changed\", {\n detail: observing,\n bubbles: true,\n }));\n }\n\n // --- Public API ---\n\n /**\n * Start observing `element`. Idempotent while already observing the same\n * element with the same options. Changing the element or options tears down the\n * current observer and builds a new one (IntersectionObserver options are fixed\n * at construction, so reconfiguring requires a fresh observer).\n *\n * If IntersectionObserver is unavailable (SSR) or the options are invalid (e.g.\n * a malformed `rootMargin`, which the constructor rejects), this is a silent\n * no-op — `observing` stays false, consistent with the never-throw design of\n * the other @wcstack sensors.\n */\n observe(element: Element, options: IntersectOptions = {}): void {\n if (this._observer && this._observed === element && this._optionsEqual(this._options, options)) {\n return;\n }\n this._teardownObserver();\n const observer = this._createObserver(options);\n if (!observer) {\n // Creation failed (unsupported environment or invalid options) *after* we\n // tore down any previous observer. If we were already observing, the\n // observation is now gone, so reflect that — otherwise `observing` would\n // keep reporting true with no live observer behind it (e.g. re-observing an\n // active target with a newly-invalid rootMargin).\n this._setObserving(false);\n return;\n }\n this._observer = observer;\n this._observed = element;\n this._options = options;\n observer.observe(element);\n this._setObserving(true);\n }\n\n /**\n * Stop observing `element`. A no-op if it is not the currently observed\n * element. The observer instance is torn down (single-target Core), so a later\n * observe() rebuilds it.\n */\n unobserve(element: Element): void {\n if (this._observed !== element) return;\n this._teardownObserver();\n this._setObserving(false);\n }\n\n /** Stop all observation and release the observer. */\n disconnect(): void {\n this._teardownObserver();\n this._setObserving(false);\n }\n\n /** Clear the `visible` latch so a later intersection can set it again. */\n reset(): void {\n this._setVisible(false);\n }\n\n // --- Internal ---\n\n private _teardownObserver(): void {\n if (this._observer) {\n this._observer.disconnect();\n this._observer = null;\n }\n this._observed = null;\n }\n\n private _createObserver(options: IntersectOptions): IntersectionObserver | null {\n if (typeof IntersectionObserver === \"undefined\") return null;\n try {\n return new IntersectionObserver(this._onIntersect, {\n root: options.root ?? null,\n rootMargin: options.rootMargin ?? \"0px\",\n threshold: options.threshold ?? 0,\n });\n } catch {\n // Invalid options (e.g. a malformed rootMargin) — surface nothing and leave\n // observing false, rather than letting the constructor throw escape.\n return null;\n }\n }\n\n private _onIntersect = (entries: IntersectionObserverEntry[]): void => {\n for (const entry of entries) {\n const normalized = this._normalizeEntry(entry);\n this._setEntry(normalized);\n // Latch on the first (and any) intersecting observation; never auto-clears.\n if (normalized.isIntersecting) {\n this._setVisible(true);\n }\n }\n };\n\n private _normalizeEntry(entry: IntersectionObserverEntry): WcsIntersectEntry {\n return {\n isIntersecting: entry.isIntersecting,\n intersectionRatio: entry.intersectionRatio,\n time: entry.time,\n boundingClientRect: this._normalizeRect(entry.boundingClientRect),\n intersectionRect: this._normalizeRect(entry.intersectionRect),\n rootBounds: entry.rootBounds ? this._normalizeRect(entry.rootBounds) : null,\n target: entry.target,\n };\n }\n\n private _normalizeRect(rect: DOMRectReadOnly): WcsIntersectRect {\n return {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n top: rect.top,\n right: rect.right,\n bottom: rect.bottom,\n left: rect.left,\n };\n }\n\n private _optionsEqual(a: IntersectOptions, b: IntersectOptions): boolean {\n if ((a.root ?? null) !== (b.root ?? null)) return false;\n if ((a.rootMargin ?? \"0px\") !== (b.rootMargin ?? \"0px\")) return false;\n return this._thresholdKey(a.threshold) === this._thresholdKey(b.threshold);\n }\n\n private _thresholdKey(threshold: number | number[] | undefined): string {\n if (threshold === undefined) return \"0\";\n return Array.isArray(threshold) ? threshold.join(\",\") : String(threshold);\n }\n}\n","import { IWcBindable, IntersectOptions, WcsIntersectEntry } from \"../types.js\";\nimport { IntersectionCore } from \"../core/IntersectionCore.js\";\n\n/**\n * `<wcs-intersect>` — declarative IntersectionObserver.\n *\n * The `target` attribute is the single knob that decides both *what* is observed\n * and how the element renders (it never injects a layout box unless asked):\n *\n * | `target` | observes | display | use case |\n * |-----------------|-----------------------|-------------|-------------------|\n * | omitted | first element child | `contents` | lazy-load wrapper |\n * | `\"#hero\"` / sel | the matched element | `none` | scrollspy (single)|\n * | `\"self\"` | the element itself | `block` | infinite-scroll |\n *\n * `display:contents` means wrapping a child injects no box of its own (so a\n * `<wcs-intersect><img></wcs-intersect>` does not disturb a flex/grid parent);\n * only the explicit `target=\"self\"` sentinel takes a box.\n */\nexport class WcsIntersect extends HTMLElement {\n static hasConnectedCallbackPromise = false;\n // Only attributes that change *what or how* we observe trigger a re-observe.\n // `once` is intentionally excluded: it is evaluated at intersection fire time\n // (in `_onChange`), so toggling it takes effect without re-observing — and a\n // re-observe on its change would be a pure no-op (same target, same options).\n // `manual` is also excluded: it is a connect-time policy (\"don't auto-observe\n // on connect\"), not a live switch that should start/stop an active observation.\n static observedAttributes = [\"target\", \"root\", \"root-margin\", \"threshold\"];\n\n static wcBindable: IWcBindable = {\n ...IntersectionCore.wcBindable,\n properties: [\n ...IntersectionCore.wcBindable.properties,\n { name: \"trigger\", event: \"wcs-intersect:trigger-changed\" },\n ],\n // Shell-level settable surface. Each input carries its mirrored `attribute`\n // hint; `trigger` has none — it is a momentary command-property, not a\n // declarative attribute. The observe / unobserve / disconnect / reset commands\n // are inherited from the Core via the spread above.\n inputs: [\n { name: \"target\", attribute: \"target\" },\n { name: \"root\", attribute: \"root\" },\n { name: \"rootMargin\", attribute: \"root-margin\" },\n { name: \"threshold\", attribute: \"threshold\" },\n { name: \"once\", attribute: \"once\" },\n { name: \"manual\", attribute: \"manual\" },\n { name: \"trigger\" },\n ],\n // Core の commands をそのまま継承(単一情報源)。<wcs-sse>/<wcs-broadcast> と同型。\n // spread でも継承されるが、Core に command 追加時の追従漏れを防ぐため明示参照する。\n commands: IntersectionCore.wcBindable.commands,\n };\n\n private _core: IntersectionCore;\n private _trigger: boolean = false;\n\n constructor() {\n super();\n this._core = new IntersectionCore(this);\n }\n\n // --- Attribute accessors ---\n\n get target(): string {\n return this.getAttribute(\"target\") ?? \"\";\n }\n\n set target(value: string) {\n this.setAttribute(\"target\", value);\n }\n\n get root(): string {\n return this.getAttribute(\"root\") ?? \"\";\n }\n\n set root(value: string) {\n this.setAttribute(\"root\", value);\n }\n\n get rootMargin(): string {\n const attr = this.getAttribute(\"root-margin\");\n return attr === null || attr.trim() === \"\" ? \"0px\" : attr;\n }\n\n set rootMargin(value: string) {\n this.setAttribute(\"root-margin\", value);\n }\n\n get threshold(): string {\n return this.getAttribute(\"threshold\") ?? \"\";\n }\n\n set threshold(value: string) {\n this.setAttribute(\"threshold\", value);\n }\n\n get once(): boolean {\n return this.hasAttribute(\"once\");\n }\n\n set once(value: boolean) {\n if (value) {\n this.setAttribute(\"once\", \"\");\n } else {\n this.removeAttribute(\"once\");\n }\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n // --- Core delegated getters ---\n\n get entry(): WcsIntersectEntry | null {\n return this._core.entry;\n }\n\n get intersecting(): boolean {\n return this._core.intersecting;\n }\n\n get ratio(): number {\n return this._core.ratio;\n }\n\n get visible(): boolean {\n return this._core.visible;\n }\n\n get observing(): boolean {\n return this._core.observing;\n }\n\n // --- Command property ---\n\n get trigger(): boolean {\n return this._trigger;\n }\n\n set trigger(value: boolean) {\n // Momentary command-property: a false→true write re-runs observe(). Mirrors\n // the trigger flag on <wcs-geo> / <wcs-ws> / <wcs-sse>. Prefer the command-token\n // protocol (`command.observe: $command.start`) for state-driven observation;\n // this exists mainly for simple boolean bindings.\n const v = !!value; // normalize truthy state-bindings, like <wcs-sse>'s setter\n if (v) {\n this._trigger = true;\n // try/finally mirrors <wcs-sse>'s set trigger: observe() is never-throw\n // today, but should a synchronous throw path ever appear, the finally still\n // auto-resets _trigger (no stuck-true latch) and emits the completion notice.\n try {\n this.observe();\n } finally {\n this._trigger = false;\n // Always auto-reset to false after the observe() attempt — this is the\n // *momentary acknowledgement* that the trigger was consumed, NOT a signal\n // that observation succeeded (whether the target resolved is reflected by\n // `observing`, not by this event). Firing unconditionally keeps the bound\n // state's trigger flag from sticking at true regardless of resolution.\n // Read `observing` if you need the actual outcome.\n this.dispatchEvent(new CustomEvent(\"wcs-intersect:trigger-changed\", {\n detail: false,\n bubbles: true,\n }));\n }\n }\n }\n\n // --- Commands ---\n\n /** Re-resolve the target/root from the DOM and (re)start observing. */\n observe(): void {\n const { element, display } = this._resolveTarget();\n // `display` is derived from the `target` *mode* (self/selector/child), not from\n // whether the selector currently matches — so it is applied unconditionally,\n // before the resolution check. A `target=\"#x\"` whose node is momentarily absent\n // still renders `display:none` (it is a selector pointer, never a box).\n this.style.display = display;\n if (!element) {\n // The target is no longer resolvable (e.g. a `target` selector whose node\n // was removed from the DOM). Tear down any stale observation so `observing`\n // does not keep reporting true against a node that is gone.\n this._core.disconnect();\n return;\n }\n this._core.observe(element, this._options());\n }\n\n unobserve(): void {\n // Single-target Shell: \"stop observing my target\" is exactly the Core's\n // teardown. Delegate to the Core's tracked state rather than re-resolving the\n // selector, so a target that has since left the DOM can still be stopped\n // (re-resolving would yield null and silently leave the observer running).\n this._core.disconnect();\n }\n\n disconnect(): void {\n this._core.disconnect();\n }\n\n reset(): void {\n this._core.reset();\n }\n\n // --- Internal ---\n\n private _resolveTarget(): { element: Element | null; display: string } {\n const target = this.target;\n if (target === \"self\") {\n // Explicit sentinel: observe the element itself as a (typically zero-height)\n // marker, which requires a layout box.\n return { element: this, display: \"block\" };\n }\n if (target !== \"\") {\n // Selector pointer: observe a referenced element in place, staying invisible.\n const scope = this.getRootNode() as Document | ShadowRoot;\n // A user-authored selector can be syntactically invalid (e.g. `#`, `:::`,\n // `[data-*`), which makes querySelector throw a SyntaxError. Swallow it and\n // treat the target as unresolvable — the same \"nothing to observe\" path as a\n // selector matching no element — so a bad attribute never lets the throw\n // escape observe() → connectedCallback / attributeChangedCallback (never-throw).\n return { element: this._safeQuery(scope, target), display: \"none\" };\n }\n // Omitted: observe the first element child without injecting a box of our own.\n const child = this.firstElementChild;\n if (child) {\n return { element: child, display: \"contents\" };\n }\n // No child to wrap (e.g. used as an empty marker) — fall back to self.\n return { element: this, display: \"block\" };\n }\n\n private _resolveRoot(): Element | null {\n const root = this.root;\n if (root === \"\") return null;\n const scope = this.getRootNode() as Document | ShadowRoot;\n // Same never-throw guard as the target selector: an invalid `root` selector\n // falls back to a null root (the viewport) rather than throwing out of observe().\n return this._safeQuery(scope, root);\n }\n\n // Wrap querySelector so a syntactically invalid user-authored selector resolves\n // to null (unresolvable) instead of letting the SyntaxError escape — keeping the\n // sensor never-throw, mirroring worker/src/autoTrigger.ts's resolveText guard.\n private _safeQuery(scope: Document | ShadowRoot, selector: string): Element | null {\n try {\n return scope.querySelector(selector);\n } catch {\n return null;\n }\n }\n\n private _parseThreshold(): number | number[] {\n const raw = this.threshold.trim();\n if (raw === \"\") return 0;\n // Strict parse via Number() (unlike parseFloat, \"0.5px\" -> NaN, not 0.5); drop\n // any non-finite or out-of-range [0,1] value, matching the README note.\n // Drop empty slots first (\"0,,1\" / \"1,\") — Number(\"\") is 0, which would\n // otherwise smuggle a spurious 0 threshold past the finite/range filter.\n const nums = raw\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s !== \"\")\n .map((s) => Number(s))\n .filter((n) => Number.isFinite(n) && n >= 0 && n <= 1);\n if (nums.length === 0) return 0;\n return nums.length === 1 ? nums[0] : nums;\n }\n\n private _options(): IntersectOptions {\n return {\n root: this._resolveRoot(),\n rootMargin: this.rootMargin,\n threshold: this._parseThreshold(),\n };\n }\n\n private _onChange = (event: Event): void => {\n // `wcs-intersect:change` bubbles, so a nested `<wcs-intersect>` descendant's\n // change would otherwise reach this (ancestor) listener and let a *child's*\n // intersection tear down *our* observer. Only act on our own Core's event.\n // (This also avoids reading `.detail` off a foreign event shape.)\n if (event.target !== this) return;\n // `once`: tear down after the first intersecting observation (lazy-load idiom).\n // Gated at fire time so toggling the `once` attribute takes effect live.\n if (this.once && (event as CustomEvent).detail.isIntersecting) {\n this._core.disconnect();\n }\n };\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this.addEventListener(\"wcs-intersect:change\", this._onChange);\n if (!this.manual) {\n this.observe();\n }\n }\n\n disconnectedCallback(): void {\n this.removeEventListener(\"wcs-intersect:change\", this._onChange);\n this._core.disconnect();\n }\n\n attributeChangedCallback(_name: string, oldValue: string | null, newValue: string | null): void {\n // Defensive same-value guard. Per spec attributeChangedCallback only fires on\n // an actual value change, so this is effectively a dead branch today — but\n // setAttribute() with an unchanged value (and some test/tooling paths) can\n // still invoke it, and re-observing on an unchanged attribute would be a\n // wasted observer rebuild. Kept intentionally; do not remove.\n if (oldValue === newValue) return;\n // Only react once connected and in automatic mode. The Core's idempotency\n // guard absorbs the autoloader upgrade case (attributeChangedCallback +\n // connectedCallback both calling observe() with identical options).\n if (!this.isConnected || this.manual) return;\n this.observe();\n }\n}\n","import { WcsIntersect } from \"./components/Intersect.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.intersect)) {\n customElements.define(config.tagNames.intersect, WcsIntersect);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapIntersection(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.js","sources":["../src/config.ts","../src/core/IntersectionCore.ts","../src/components/Intersect.ts","../src/registerComponents.ts","../src/bootstrapIntersection.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n tagNames: {\n intersect: string;\n };\n}\n\nconst _config: IInternalConfig = {\n tagNames: {\n intersect: \"wcs-intersect\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { IWcBindable, IntersectOptions, WcsIntersectEntry, WcsIntersectRect } from \"../types.js\";\n\n/**\n * Headless visibility primitive. A thin, framework-agnostic wrapper around the\n * IntersectionObserver API exposed through the wc-bindable protocol.\n *\n * Unlike the other @wcstack sensors (geolocation / timer / websocket), the thing\n * being observed is a *DOM element* — so `observe()` takes the target node. The\n * Core stays DOM-resolution-agnostic: it observes whatever element it is handed\n * (the Shell resolves `target` / `root` selectors before calling). It is a\n * read-only producer — element/layout → state only, with no element-bound path.\n *\n * Every observer callback is published via the single `wcs-intersect:change`\n * event; `intersecting` / `ratio` are read from it through getters (mirroring how\n * GeolocationCore exposes latitude/longitude from one `wcs-geo:position` event),\n * so an observer that binds any of them is notified on every change.\n *\n * `visible` is a latch: it flips to `true` the first time the target intersects\n * and stays `true` until `reset()` — ideal for one-way lazy-load bindings\n * (`src@visible`). `observing` reflects whether an observation is currently\n * active (like TimerCore's `running`).\n *\n * Single-target by design: the Shell observes exactly one element, so the state\n * reflects that element. Multi-target observation is intentionally out of scope.\n */\nexport class IntersectionCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"entry\", event: \"wcs-intersect:change\" },\n { name: \"intersecting\", event: \"wcs-intersect:change\", getter: (e: Event) => (e as CustomEvent).detail.isIntersecting },\n { name: \"ratio\", event: \"wcs-intersect:change\", getter: (e: Event) => (e as CustomEvent).detail.intersectionRatio },\n { name: \"visible\", event: \"wcs-intersect:visible-changed\" },\n { name: \"observing\", event: \"wcs-intersect:observing-changed\" },\n ],\n commands: [\n { name: \"observe\" },\n { name: \"reobserve\" },\n { name: \"unobserve\" },\n { name: \"disconnect\" },\n { name: \"reset\" },\n ],\n };\n\n private _target: EventTarget;\n\n // The live observer and the single element it observes. Options are kept so a\n // repeated observe() with identical options is a no-op (avoids the create→\n // observe→disconnect churn an autoloader upgrade can otherwise cause).\n private _observer: IntersectionObserver | null = null;\n private _observed: Element | null = null;\n private _options: IntersectOptions = {};\n\n private _entry: WcsIntersectEntry | null = null;\n private _visible: boolean = false;\n private _observing: boolean = false;\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get entry(): WcsIntersectEntry | null {\n return this._entry;\n }\n\n get intersecting(): boolean {\n return this._entry ? this._entry.isIntersecting : false;\n }\n\n get ratio(): number {\n return this._entry ? this._entry.intersectionRatio : 0;\n }\n\n get visible(): boolean {\n return this._visible;\n }\n\n get observing(): boolean {\n return this._observing;\n }\n\n // --- State setters with event dispatch ---\n\n private _setEntry(entry: WcsIntersectEntry): void {\n // No same-value guard: `change` carries event semantics (every callback is a\n // distinct observation) and `intersecting` / `ratio` are derived getters that\n // must re-fire on each entry, mirroring GeolocationCore's `position`.\n this._entry = entry;\n this._target.dispatchEvent(new CustomEvent(\"wcs-intersect:change\", {\n detail: entry,\n bubbles: true,\n }));\n }\n\n private _setVisible(visible: boolean): void {\n if (this._visible === visible) return;\n this._visible = visible;\n this._target.dispatchEvent(new CustomEvent(\"wcs-intersect:visible-changed\", {\n detail: visible,\n bubbles: true,\n }));\n }\n\n private _setObserving(observing: boolean): void {\n if (this._observing === observing) return;\n this._observing = observing;\n this._target.dispatchEvent(new CustomEvent(\"wcs-intersect:observing-changed\", {\n detail: observing,\n bubbles: true,\n }));\n }\n\n // --- Public API ---\n\n /**\n * Start observing `element`. Idempotent while already observing the same\n * element with the same options. Changing the element or options tears down the\n * current observer and builds a new one (IntersectionObserver options are fixed\n * at construction, so reconfiguring requires a fresh observer).\n *\n * If IntersectionObserver is unavailable (SSR) or the options are invalid (e.g.\n * a malformed `rootMargin`, which the constructor rejects), this is a silent\n * no-op — `observing` stays false, consistent with the never-throw design of\n * the other @wcstack sensors.\n */\n observe(element: Element, options: IntersectOptions = {}): void {\n if (this._observer && this._observed === element && this._optionsEqual(this._options, options)) {\n return;\n }\n this._teardownObserver();\n const observer = this._createObserver(options);\n if (!observer) {\n // Creation failed (unsupported environment or invalid options) *after* we\n // tore down any previous observer. If we were already observing, the\n // observation is now gone, so reflect that — otherwise `observing` would\n // keep reporting true with no live observer behind it (e.g. re-observing an\n // active target with a newly-invalid rootMargin).\n this._setObserving(false);\n return;\n }\n this._observer = observer;\n this._observed = element;\n this._options = options;\n observer.observe(element);\n this._setObserving(true);\n }\n\n /**\n * Force a fresh observation of `element`, even when it matches the currently\n * observed target+options. Unlike observe() — which is idempotent and\n * early-returns for an unchanged target+options *without* re-delivering a\n * callback — this always tears the observer down and rebuilds it, so a new\n * IntersectionObserver delivers an initial callback for the element's CURRENT\n * visibility.\n *\n * This is the way to re-arm an edge-driven consumer (e.g. infinite scroll) after\n * the layout changed without a visibility *transition*: IntersectionObserver only\n * fires on a change, so appending a short page that leaves the sentinel visible\n * yields no new callback — a bare observe() can't help (idempotent), but a\n * reobserve() re-reads the current state. Same never-throw guarantees as\n * observe(); `observing` stays true across a successful re-arm (no false blip).\n */\n reobserve(element: Element, options: IntersectOptions = {}): void {\n this._teardownObserver();\n this.observe(element, options);\n }\n\n /**\n * Stop observing `element`. A no-op if it is not the currently observed\n * element. The observer instance is torn down (single-target Core), so a later\n * observe() rebuilds it.\n */\n unobserve(element: Element): void {\n if (this._observed !== element) return;\n this._teardownObserver();\n this._setObserving(false);\n }\n\n /** Stop all observation and release the observer. */\n disconnect(): void {\n this._teardownObserver();\n this._setObserving(false);\n }\n\n /** Clear the `visible` latch so a later intersection can set it again. */\n reset(): void {\n this._setVisible(false);\n }\n\n // --- Internal ---\n\n private _teardownObserver(): void {\n if (this._observer) {\n this._observer.disconnect();\n this._observer = null;\n }\n this._observed = null;\n }\n\n private _createObserver(options: IntersectOptions): IntersectionObserver | null {\n if (typeof IntersectionObserver === \"undefined\") return null;\n try {\n return new IntersectionObserver(this._onIntersect, {\n root: options.root ?? null,\n rootMargin: options.rootMargin ?? \"0px\",\n threshold: options.threshold ?? 0,\n });\n } catch {\n // Invalid options (e.g. a malformed rootMargin) — surface nothing and leave\n // observing false, rather than letting the constructor throw escape.\n return null;\n }\n }\n\n private _onIntersect = (entries: IntersectionObserverEntry[]): void => {\n for (const entry of entries) {\n const normalized = this._normalizeEntry(entry);\n this._setEntry(normalized);\n // Latch on the first (and any) intersecting observation; never auto-clears.\n if (normalized.isIntersecting) {\n this._setVisible(true);\n }\n }\n };\n\n private _normalizeEntry(entry: IntersectionObserverEntry): WcsIntersectEntry {\n return {\n isIntersecting: entry.isIntersecting,\n intersectionRatio: entry.intersectionRatio,\n time: entry.time,\n boundingClientRect: this._normalizeRect(entry.boundingClientRect),\n intersectionRect: this._normalizeRect(entry.intersectionRect),\n rootBounds: entry.rootBounds ? this._normalizeRect(entry.rootBounds) : null,\n target: entry.target,\n };\n }\n\n private _normalizeRect(rect: DOMRectReadOnly): WcsIntersectRect {\n return {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n top: rect.top,\n right: rect.right,\n bottom: rect.bottom,\n left: rect.left,\n };\n }\n\n private _optionsEqual(a: IntersectOptions, b: IntersectOptions): boolean {\n if ((a.root ?? null) !== (b.root ?? null)) return false;\n if ((a.rootMargin ?? \"0px\") !== (b.rootMargin ?? \"0px\")) return false;\n return this._thresholdKey(a.threshold) === this._thresholdKey(b.threshold);\n }\n\n private _thresholdKey(threshold: number | number[] | undefined): string {\n if (threshold === undefined) return \"0\";\n return Array.isArray(threshold) ? threshold.join(\",\") : String(threshold);\n }\n}\n","import { IWcBindable, IntersectOptions, WcsIntersectEntry } from \"../types.js\";\nimport { IntersectionCore } from \"../core/IntersectionCore.js\";\n\n/**\n * `<wcs-intersect>` — declarative IntersectionObserver.\n *\n * The `target` attribute is the single knob that decides both *what* is observed\n * and how the element renders (it never injects a layout box unless asked):\n *\n * | `target` | observes | display | use case |\n * |-----------------|-----------------------|-------------|-------------------|\n * | omitted | first element child | `contents` | lazy-load wrapper |\n * | `\"#hero\"` / sel | the matched element | `none` | scrollspy (single)|\n * | `\"self\"` | the element itself | `block` | infinite-scroll |\n *\n * `display:contents` means wrapping a child injects no box of its own (so a\n * `<wcs-intersect><img></wcs-intersect>` does not disturb a flex/grid parent);\n * only the explicit `target=\"self\"` sentinel takes a box.\n */\nexport class WcsIntersect extends HTMLElement {\n static hasConnectedCallbackPromise = false;\n // Only attributes that change *what or how* we observe trigger a re-observe.\n // `once` is intentionally excluded: it is evaluated at intersection fire time\n // (in `_onChange`), so toggling it takes effect without re-observing — and a\n // re-observe on its change would be a pure no-op (same target, same options).\n // `manual` is also excluded: it is a connect-time policy (\"don't auto-observe\n // on connect\"), not a live switch that should start/stop an active observation.\n static observedAttributes = [\"target\", \"root\", \"root-margin\", \"threshold\"];\n\n static wcBindable: IWcBindable = {\n ...IntersectionCore.wcBindable,\n properties: [\n ...IntersectionCore.wcBindable.properties,\n { name: \"trigger\", event: \"wcs-intersect:trigger-changed\" },\n ],\n // Shell-level settable surface. Each input carries its mirrored `attribute`\n // hint; `trigger` has none — it is a momentary command-property, not a\n // declarative attribute. The observe / reobserve / unobserve / disconnect /\n // reset commands are inherited from the Core via the spread above.\n inputs: [\n { name: \"target\", attribute: \"target\" },\n { name: \"root\", attribute: \"root\" },\n { name: \"rootMargin\", attribute: \"root-margin\" },\n { name: \"threshold\", attribute: \"threshold\" },\n { name: \"once\", attribute: \"once\" },\n { name: \"manual\", attribute: \"manual\" },\n { name: \"trigger\" },\n ],\n // Core の commands をそのまま継承(単一情報源)。<wcs-sse>/<wcs-broadcast> と同型。\n // spread でも継承されるが、Core に command 追加時の追従漏れを防ぐため明示参照する。\n commands: IntersectionCore.wcBindable.commands,\n };\n\n private _core: IntersectionCore;\n private _trigger: boolean = false;\n\n constructor() {\n super();\n this._core = new IntersectionCore(this);\n }\n\n // --- Attribute accessors ---\n\n get target(): string {\n return this.getAttribute(\"target\") ?? \"\";\n }\n\n set target(value: string) {\n this.setAttribute(\"target\", value);\n }\n\n get root(): string {\n return this.getAttribute(\"root\") ?? \"\";\n }\n\n set root(value: string) {\n this.setAttribute(\"root\", value);\n }\n\n get rootMargin(): string {\n const attr = this.getAttribute(\"root-margin\");\n return attr === null || attr.trim() === \"\" ? \"0px\" : attr;\n }\n\n set rootMargin(value: string) {\n this.setAttribute(\"root-margin\", value);\n }\n\n get threshold(): string {\n return this.getAttribute(\"threshold\") ?? \"\";\n }\n\n set threshold(value: string) {\n this.setAttribute(\"threshold\", value);\n }\n\n get once(): boolean {\n return this.hasAttribute(\"once\");\n }\n\n set once(value: boolean) {\n if (value) {\n this.setAttribute(\"once\", \"\");\n } else {\n this.removeAttribute(\"once\");\n }\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n // --- Core delegated getters ---\n\n get entry(): WcsIntersectEntry | null {\n return this._core.entry;\n }\n\n get intersecting(): boolean {\n return this._core.intersecting;\n }\n\n get ratio(): number {\n return this._core.ratio;\n }\n\n get visible(): boolean {\n return this._core.visible;\n }\n\n get observing(): boolean {\n return this._core.observing;\n }\n\n // --- Command property ---\n\n get trigger(): boolean {\n return this._trigger;\n }\n\n set trigger(value: boolean) {\n // Momentary command-property: a false→true write re-runs observe(). Mirrors\n // the trigger flag on <wcs-geo> / <wcs-ws> / <wcs-sse>. Prefer the command-token\n // protocol (`command.observe: $command.start`) for state-driven observation;\n // this exists mainly for simple boolean bindings.\n const v = !!value; // normalize truthy state-bindings, like <wcs-sse>'s setter\n if (v) {\n this._trigger = true;\n // try/finally mirrors <wcs-sse>'s set trigger: observe() is never-throw\n // today, but should a synchronous throw path ever appear, the finally still\n // auto-resets _trigger (no stuck-true latch) and emits the completion notice.\n try {\n this.observe();\n } finally {\n this._trigger = false;\n // Always auto-reset to false after the observe() attempt — this is the\n // *momentary acknowledgement* that the trigger was consumed, NOT a signal\n // that observation succeeded (whether the target resolved is reflected by\n // `observing`, not by this event). Firing unconditionally keeps the bound\n // state's trigger flag from sticking at true regardless of resolution.\n // Read `observing` if you need the actual outcome.\n this.dispatchEvent(new CustomEvent(\"wcs-intersect:trigger-changed\", {\n detail: false,\n bubbles: true,\n }));\n }\n }\n }\n\n // --- Commands ---\n\n /** Re-resolve the target/root from the DOM and (re)start observing. */\n observe(): void {\n const { element, display } = this._resolveTarget();\n // `display` is derived from the `target` *mode* (self/selector/child), not from\n // whether the selector currently matches — so it is applied unconditionally,\n // before the resolution check. A `target=\"#x\"` whose node is momentarily absent\n // still renders `display:none` (it is a selector pointer, never a box).\n this.style.display = display;\n if (!element) {\n // The target is no longer resolvable (e.g. a `target` selector whose node\n // was removed from the DOM). Tear down any stale observation so `observing`\n // does not keep reporting true against a node that is gone.\n this._core.disconnect();\n return;\n }\n this._core.observe(element, this._options());\n }\n\n /**\n * Force a fresh observation: re-resolve target/root from the DOM and re-observe\n * even when nothing changed. Unlike observe() (idempotent for an unchanged\n * target+options), this rebuilds the observer so a new initial callback fires for\n * the current visibility — the way to re-arm an edge-driven consumer after the\n * layout shifted without a visibility transition (e.g. infinite scroll appended a\n * short page that left this sentinel in view). Resolution/teardown rules match\n * observe(): an unresolvable target tears down any stale observation.\n */\n reobserve(): void {\n const { element, display } = this._resolveTarget();\n this.style.display = display;\n if (!element) {\n this._core.disconnect();\n return;\n }\n this._core.reobserve(element, this._options());\n }\n\n unobserve(): void {\n // Single-target Shell: \"stop observing my target\" is exactly the Core's\n // teardown. Delegate to the Core's tracked state rather than re-resolving the\n // selector, so a target that has since left the DOM can still be stopped\n // (re-resolving would yield null and silently leave the observer running).\n this._core.disconnect();\n }\n\n disconnect(): void {\n this._core.disconnect();\n }\n\n reset(): void {\n this._core.reset();\n }\n\n // --- Internal ---\n\n private _resolveTarget(): { element: Element | null; display: string } {\n const target = this.target;\n if (target === \"self\") {\n // Explicit sentinel: observe the element itself as a (typically zero-height)\n // marker, which requires a layout box.\n return { element: this, display: \"block\" };\n }\n if (target !== \"\") {\n // Selector pointer: observe a referenced element in place, staying invisible.\n const scope = this.getRootNode() as Document | ShadowRoot;\n // A user-authored selector can be syntactically invalid (e.g. `#`, `:::`,\n // `[data-*`), which makes querySelector throw a SyntaxError. Swallow it and\n // treat the target as unresolvable — the same \"nothing to observe\" path as a\n // selector matching no element — so a bad attribute never lets the throw\n // escape observe() → connectedCallback / attributeChangedCallback (never-throw).\n return { element: this._safeQuery(scope, target), display: \"none\" };\n }\n // Omitted: observe the first element child without injecting a box of our own.\n const child = this.firstElementChild;\n if (child) {\n return { element: child, display: \"contents\" };\n }\n // No child to wrap (e.g. used as an empty marker) — fall back to self.\n return { element: this, display: \"block\" };\n }\n\n private _resolveRoot(): Element | null {\n const root = this.root;\n if (root === \"\") return null;\n const scope = this.getRootNode() as Document | ShadowRoot;\n // Same never-throw guard as the target selector: an invalid `root` selector\n // falls back to a null root (the viewport) rather than throwing out of observe().\n return this._safeQuery(scope, root);\n }\n\n // Wrap querySelector so a syntactically invalid user-authored selector resolves\n // to null (unresolvable) instead of letting the SyntaxError escape — keeping the\n // sensor never-throw, mirroring worker/src/autoTrigger.ts's resolveText guard.\n private _safeQuery(scope: Document | ShadowRoot, selector: string): Element | null {\n try {\n return scope.querySelector(selector);\n } catch {\n return null;\n }\n }\n\n private _parseThreshold(): number | number[] {\n const raw = this.threshold.trim();\n if (raw === \"\") return 0;\n // Strict parse via Number() (unlike parseFloat, \"0.5px\" -> NaN, not 0.5); drop\n // any non-finite or out-of-range [0,1] value, matching the README note.\n // Drop empty slots first (\"0,,1\" / \"1,\") — Number(\"\") is 0, which would\n // otherwise smuggle a spurious 0 threshold past the finite/range filter.\n const nums = raw\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s !== \"\")\n .map((s) => Number(s))\n .filter((n) => Number.isFinite(n) && n >= 0 && n <= 1);\n if (nums.length === 0) return 0;\n return nums.length === 1 ? nums[0] : nums;\n }\n\n private _options(): IntersectOptions {\n return {\n root: this._resolveRoot(),\n rootMargin: this.rootMargin,\n threshold: this._parseThreshold(),\n };\n }\n\n private _onChange = (event: Event): void => {\n // `wcs-intersect:change` bubbles, so a nested `<wcs-intersect>` descendant's\n // change would otherwise reach this (ancestor) listener and let a *child's*\n // intersection tear down *our* observer. Only act on our own Core's event.\n // (This also avoids reading `.detail` off a foreign event shape.)\n if (event.target !== this) return;\n // `once`: tear down after the first intersecting observation (lazy-load idiom).\n // Gated at fire time so toggling the `once` attribute takes effect live.\n if (this.once && (event as CustomEvent).detail.isIntersecting) {\n this._core.disconnect();\n }\n };\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this.addEventListener(\"wcs-intersect:change\", this._onChange);\n if (!this.manual) {\n this.observe();\n }\n }\n\n disconnectedCallback(): void {\n this.removeEventListener(\"wcs-intersect:change\", this._onChange);\n this._core.disconnect();\n }\n\n attributeChangedCallback(_name: string, oldValue: string | null, newValue: string | null): void {\n // Defensive same-value guard. Per spec attributeChangedCallback only fires on\n // an actual value change, so this is effectively a dead branch today — but\n // setAttribute() with an unchanged value (and some test/tooling paths) can\n // still invoke it, and re-observing on an unchanged attribute would be a\n // wasted observer rebuild. Kept intentionally; do not remove.\n if (oldValue === newValue) return;\n // Only react once connected and in automatic mode. The Core's idempotency\n // guard absorbs the autoloader upgrade case (attributeChangedCallback +\n // connectedCallback both calling observe() with identical options).\n if (!this.isConnected || this.manual) return;\n this.observe();\n }\n}\n","import { WcsIntersect } from \"./components/Intersect.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.intersect)) {\n customElements.define(config.tagNames.intersect, WcsIntersect);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapIntersection(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n"],"names":[],"mappings":"AAQA,MAAM,OAAO,GAAoB;AAC/B,IAAA,QAAQ,EAAE;AACR,QAAA,SAAS,EAAE,eAAe;AAC3B,KAAA;CACF;AAED,SAAS,UAAU,CAAI,GAAM,EAAA;AAC3B,IAAA,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ;AAAE,QAAA,OAAO,GAAG;AACvD,IAAA,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;IAClB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;AAClC,QAAA,UAAU,CAAE,GAA+B,CAAC,GAAG,CAAC,CAAC;IACnD;AACA,IAAA,OAAO,GAAG;AACZ;AAEA,SAAS,SAAS,CAAI,GAAM,EAAA;AAC1B,IAAA,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ;AAAE,QAAA,OAAO,GAAG;IACvD,MAAM,KAAK,GAA4B,EAAE;IACzC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QAClC,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAAE,GAA+B,CAAC,GAAG,CAAC,CAAC;IAC/D;AACA,IAAA,OAAO,KAAU;AACnB;AAEA,IAAI,YAAY,GAAmB,IAAI;AAEhC,MAAM,MAAM,GAAY,OAAkB;SAEjC,SAAS,GAAA;IACvB,IAAI,CAAC,YAAY,EAAE;QACjB,YAAY,GAAG,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAC/C;AACA,IAAA,OAAO,YAAY;AACrB;AAEM,SAAU,SAAS,CAAC,aAA8B,EAAA;AACtD,IAAA,IAAI,aAAa,CAAC,QAAQ,EAAE;QAC1B,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,aAAa,CAAC,QAAQ,CAAC;IACzD;IACA,YAAY,GAAG,IAAI;AACrB;;AC9CA;;;;;;;;;;;;;;;;;;;;;;AAsBG;AACG,MAAO,gBAAiB,SAAQ,WAAW,CAAA;IAC/C,OAAO,UAAU,GAAgB;AAC/B,QAAA,QAAQ,EAAE,aAAa;AACvB,QAAA,OAAO,EAAE,CAAC;AACV,QAAA,UAAU,EAAE;AACV,YAAA,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,sBAAsB,EAAE;YAChD,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,CAAC,CAAQ,KAAM,CAAiB,CAAC,MAAM,CAAC,cAAc,EAAE;YACvH,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,CAAC,CAAQ,KAAM,CAAiB,CAAC,MAAM,CAAC,iBAAiB,EAAE;AACnH,YAAA,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,+BAA+B,EAAE;AAC3D,YAAA,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,iCAAiC,EAAE;AAChE,SAAA;AACD,QAAA,QAAQ,EAAE;YACR,EAAE,IAAI,EAAE,SAAS,EAAE;YACnB,EAAE,IAAI,EAAE,WAAW,EAAE;YACrB,EAAE,IAAI,EAAE,WAAW,EAAE;YACrB,EAAE,IAAI,EAAE,YAAY,EAAE;YACtB,EAAE,IAAI,EAAE,OAAO,EAAE;AAClB,SAAA;KACF;AAEO,IAAA,OAAO;;;;IAKP,SAAS,GAAgC,IAAI;IAC7C,SAAS,GAAmB,IAAI;IAChC,QAAQ,GAAqB,EAAE;IAE/B,MAAM,GAA6B,IAAI;IACvC,QAAQ,GAAY,KAAK;IACzB,UAAU,GAAY,KAAK;AAEnC,IAAA,WAAA,CAAY,MAAoB,EAAA;AAC9B,QAAA,KAAK,EAAE;AACP,QAAA,IAAI,CAAC,OAAO,GAAG,MAAM,IAAI,IAAI;IAC/B;AAEA,IAAA,IAAI,KAAK,GAAA;QACP,OAAO,IAAI,CAAC,MAAM;IACpB;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,OAAO,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,GAAG,KAAK;IACzD;AAEA,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,iBAAiB,GAAG,CAAC;IACxD;AAEA,IAAA,IAAI,OAAO,GAAA;QACT,OAAO,IAAI,CAAC,QAAQ;IACtB;AAEA,IAAA,IAAI,SAAS,GAAA;QACX,OAAO,IAAI,CAAC,UAAU;IACxB;;AAIQ,IAAA,SAAS,CAAC,KAAwB,EAAA;;;;AAIxC,QAAA,IAAI,CAAC,MAAM,GAAG,KAAK;QACnB,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,sBAAsB,EAAE;AACjE,YAAA,MAAM,EAAE,KAAK;AACb,YAAA,OAAO,EAAE,IAAI;AACd,SAAA,CAAC,CAAC;IACL;AAEQ,IAAA,WAAW,CAAC,OAAgB,EAAA;AAClC,QAAA,IAAI,IAAI,CAAC,QAAQ,KAAK,OAAO;YAAE;AAC/B,QAAA,IAAI,CAAC,QAAQ,GAAG,OAAO;QACvB,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,+BAA+B,EAAE;AAC1E,YAAA,MAAM,EAAE,OAAO;AACf,YAAA,OAAO,EAAE,IAAI;AACd,SAAA,CAAC,CAAC;IACL;AAEQ,IAAA,aAAa,CAAC,SAAkB,EAAA;AACtC,QAAA,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS;YAAE;AACnC,QAAA,IAAI,CAAC,UAAU,GAAG,SAAS;QAC3B,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,iCAAiC,EAAE;AAC5E,YAAA,MAAM,EAAE,SAAS;AACjB,YAAA,OAAO,EAAE,IAAI;AACd,SAAA,CAAC,CAAC;IACL;;AAIA;;;;;;;;;;AAUG;AACH,IAAA,OAAO,CAAC,OAAgB,EAAE,OAAA,GAA4B,EAAE,EAAA;QACtD,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,KAAK,OAAO,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE;YAC9F;QACF;QACA,IAAI,CAAC,iBAAiB,EAAE;QACxB,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC;QAC9C,IAAI,CAAC,QAAQ,EAAE;;;;;;AAMb,YAAA,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC;YACzB;QACF;AACA,QAAA,IAAI,CAAC,SAAS,GAAG,QAAQ;AACzB,QAAA,IAAI,CAAC,SAAS,GAAG,OAAO;AACxB,QAAA,IAAI,CAAC,QAAQ,GAAG,OAAO;AACvB,QAAA,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC;AACzB,QAAA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;IAC1B;AAEA;;;;;;;;;;;;;;AAcG;AACH,IAAA,SAAS,CAAC,OAAgB,EAAE,OAAA,GAA4B,EAAE,EAAA;QACxD,IAAI,CAAC,iBAAiB,EAAE;AACxB,QAAA,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC;IAChC;AAEA;;;;AAIG;AACH,IAAA,SAAS,CAAC,OAAgB,EAAA;AACxB,QAAA,IAAI,IAAI,CAAC,SAAS,KAAK,OAAO;YAAE;QAChC,IAAI,CAAC,iBAAiB,EAAE;AACxB,QAAA,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC;IAC3B;;IAGA,UAAU,GAAA;QACR,IAAI,CAAC,iBAAiB,EAAE;AACxB,QAAA,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC;IAC3B;;IAGA,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;IACzB;;IAIQ,iBAAiB,GAAA;AACvB,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE;AAClB,YAAA,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE;AAC3B,YAAA,IAAI,CAAC,SAAS,GAAG,IAAI;QACvB;AACA,QAAA,IAAI,CAAC,SAAS,GAAG,IAAI;IACvB;AAEQ,IAAA,eAAe,CAAC,OAAyB,EAAA;QAC/C,IAAI,OAAO,oBAAoB,KAAK,WAAW;AAAE,YAAA,OAAO,IAAI;AAC5D,QAAA,IAAI;AACF,YAAA,OAAO,IAAI,oBAAoB,CAAC,IAAI,CAAC,YAAY,EAAE;AACjD,gBAAA,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,IAAI;AAC1B,gBAAA,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,KAAK;AACvC,gBAAA,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,CAAC;AAClC,aAAA,CAAC;QACJ;AAAE,QAAA,MAAM;;;AAGN,YAAA,OAAO,IAAI;QACb;IACF;AAEQ,IAAA,YAAY,GAAG,CAAC,OAAoC,KAAU;AACpE,QAAA,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE;YAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC;AAC9C,YAAA,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;;AAE1B,YAAA,IAAI,UAAU,CAAC,cAAc,EAAE;AAC7B,gBAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;YACxB;QACF;AACF,IAAA,CAAC;AAEO,IAAA,eAAe,CAAC,KAAgC,EAAA;QACtD,OAAO;YACL,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;YAC1C,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,kBAAkB,EAAE,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,kBAAkB,CAAC;YACjE,gBAAgB,EAAE,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,gBAAgB,CAAC;AAC7D,YAAA,UAAU,EAAE,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,IAAI;YAC3E,MAAM,EAAE,KAAK,CAAC,MAAM;SACrB;IACH;AAEQ,IAAA,cAAc,CAAC,IAAqB,EAAA;QAC1C,OAAO;YACL,CAAC,EAAE,IAAI,CAAC,CAAC;YACT,CAAC,EAAE,IAAI,CAAC,CAAC;YACT,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB;IACH;IAEQ,aAAa,CAAC,CAAmB,EAAE,CAAmB,EAAA;AAC5D,QAAA,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,OAAO,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC;AAAE,YAAA,OAAO,KAAK;AACvD,QAAA,IAAI,CAAC,CAAC,CAAC,UAAU,IAAI,KAAK,OAAO,CAAC,CAAC,UAAU,IAAI,KAAK,CAAC;AAAE,YAAA,OAAO,KAAK;AACrE,QAAA,OAAO,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5E;AAEQ,IAAA,aAAa,CAAC,SAAwC,EAAA;QAC5D,IAAI,SAAS,KAAK,SAAS;AAAE,YAAA,OAAO,GAAG;QACvC,OAAO,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC;IAC3E;;;AClQF;;;;;;;;;;;;;;;AAeG;AACG,MAAO,YAAa,SAAQ,WAAW,CAAA;AAC3C,IAAA,OAAO,2BAA2B,GAAG,KAAK;;;;;;;AAO1C,IAAA,OAAO,kBAAkB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,CAAC;IAE1E,OAAO,UAAU,GAAgB;QAC/B,GAAG,gBAAgB,CAAC,UAAU;AAC9B,QAAA,UAAU,EAAE;AACV,YAAA,GAAG,gBAAgB,CAAC,UAAU,CAAC,UAAU;AACzC,YAAA,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,+BAA+B,EAAE;AAC5D,SAAA;;;;;AAKD,QAAA,MAAM,EAAE;AACN,YAAA,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE;AACvC,YAAA,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE;AACnC,YAAA,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE;AAChD,YAAA,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE;AAC7C,YAAA,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE;AACnC,YAAA,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE;YACvC,EAAE,IAAI,EAAE,SAAS,EAAE;AACpB,SAAA;;;AAGD,QAAA,QAAQ,EAAE,gBAAgB,CAAC,UAAU,CAAC,QAAQ;KAC/C;AAEO,IAAA,KAAK;IACL,QAAQ,GAAY,KAAK;AAEjC,IAAA,WAAA,GAAA;AACE,QAAA,KAAK,EAAE;QACP,IAAI,CAAC,KAAK,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC;IACzC;;AAIA,IAAA,IAAI,MAAM,GAAA;QACR,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE;IAC1C;IAEA,IAAI,MAAM,CAAC,KAAa,EAAA;AACtB,QAAA,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC;IACpC;AAEA,IAAA,IAAI,IAAI,GAAA;QACN,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE;IACxC;IAEA,IAAI,IAAI,CAAC,KAAa,EAAA;AACpB,QAAA,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC;IAClC;AAEA,IAAA,IAAI,UAAU,GAAA;QACZ,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC;AAC7C,QAAA,OAAO,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,KAAK,GAAG,IAAI;IAC3D;IAEA,IAAI,UAAU,CAAC,KAAa,EAAA;AAC1B,QAAA,IAAI,CAAC,YAAY,CAAC,aAAa,EAAE,KAAK,CAAC;IACzC;AAEA,IAAA,IAAI,SAAS,GAAA;QACX,OAAO,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,EAAE;IAC7C;IAEA,IAAI,SAAS,CAAC,KAAa,EAAA;AACzB,QAAA,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,KAAK,CAAC;IACvC;AAEA,IAAA,IAAI,IAAI,GAAA;AACN,QAAA,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;IAClC;IAEA,IAAI,IAAI,CAAC,KAAc,EAAA;QACrB,IAAI,KAAK,EAAE;AACT,YAAA,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC;QAC/B;aAAO;AACL,YAAA,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC;QAC9B;IACF;AAEA,IAAA,IAAI,MAAM,GAAA;AACR,QAAA,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC;IACpC;IAEA,IAAI,MAAM,CAAC,KAAc,EAAA;QACvB,IAAI,KAAK,EAAE;AACT,YAAA,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAC;QACjC;aAAO;AACL,YAAA,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC;QAChC;IACF;;AAIA,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK;IACzB;AAEA,IAAA,IAAI,YAAY,GAAA;AACd,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY;IAChC;AAEA,IAAA,IAAI,KAAK,GAAA;AACP,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK;IACzB;AAEA,IAAA,IAAI,OAAO,GAAA;AACT,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO;IAC3B;AAEA,IAAA,IAAI,SAAS,GAAA;AACX,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS;IAC7B;;AAIA,IAAA,IAAI,OAAO,GAAA;QACT,OAAO,IAAI,CAAC,QAAQ;IACtB;IAEA,IAAI,OAAO,CAAC,KAAc,EAAA;;;;;AAKxB,QAAA,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;QAClB,IAAI,CAAC,EAAE;AACL,YAAA,IAAI,CAAC,QAAQ,GAAG,IAAI;;;;AAIpB,YAAA,IAAI;gBACF,IAAI,CAAC,OAAO,EAAE;YAChB;oBAAU;AACR,gBAAA,IAAI,CAAC,QAAQ,GAAG,KAAK;;;;;;;AAOrB,gBAAA,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,+BAA+B,EAAE;AAClE,oBAAA,MAAM,EAAE,KAAK;AACb,oBAAA,OAAO,EAAE,IAAI;AACd,iBAAA,CAAC,CAAC;YACL;QACF;IACF;;;IAKA,OAAO,GAAA;QACL,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE;;;;;AAKlD,QAAA,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,OAAO;QAC5B,IAAI,CAAC,OAAO,EAAE;;;;AAIZ,YAAA,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE;YACvB;QACF;AACA,QAAA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;IAC9C;AAEA;;;;;;;;AAQG;IACH,SAAS,GAAA;QACP,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE;AAClD,QAAA,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,OAAO;QAC5B,IAAI,CAAC,OAAO,EAAE;AACZ,YAAA,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE;YACvB;QACF;AACA,QAAA,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;IAChD;IAEA,SAAS,GAAA;;;;;AAKP,QAAA,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE;IACzB;IAEA,UAAU,GAAA;AACR,QAAA,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE;IACzB;IAEA,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;IACpB;;IAIQ,cAAc,GAAA;AACpB,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM;AAC1B,QAAA,IAAI,MAAM,KAAK,MAAM,EAAE;;;YAGrB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE;QAC5C;AACA,QAAA,IAAI,MAAM,KAAK,EAAE,EAAE;;AAEjB,YAAA,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAA2B;;;;;;AAMzD,YAAA,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE;QACrE;;AAEA,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB;QACpC,IAAI,KAAK,EAAE;YACT,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE;QAChD;;QAEA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE;IAC5C;IAEQ,YAAY,GAAA;AAClB,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI;QACtB,IAAI,IAAI,KAAK,EAAE;AAAE,YAAA,OAAO,IAAI;AAC5B,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAA2B;;;QAGzD,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC;IACrC;;;;IAKQ,UAAU,CAAC,KAA4B,EAAE,QAAgB,EAAA;AAC/D,QAAA,IAAI;AACF,YAAA,OAAO,KAAK,CAAC,aAAa,CAAC,QAAQ,CAAC;QACtC;AAAE,QAAA,MAAM;AACN,YAAA,OAAO,IAAI;QACb;IACF;IAEQ,eAAe,GAAA;QACrB,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;QACjC,IAAI,GAAG,KAAK,EAAE;AAAE,YAAA,OAAO,CAAC;;;;;QAKxB,MAAM,IAAI,GAAG;aACV,KAAK,CAAC,GAAG;aACT,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE;aACnB,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE;aACtB,GAAG,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC;aACpB,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxD,QAAA,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;AAAE,YAAA,OAAO,CAAC;AAC/B,QAAA,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI;IAC3C;IAEQ,QAAQ,GAAA;QACd,OAAO;AACL,YAAA,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE;YACzB,UAAU,EAAE,IAAI,CAAC,UAAU;AAC3B,YAAA,SAAS,EAAE,IAAI,CAAC,eAAe,EAAE;SAClC;IACH;AAEQ,IAAA,SAAS,GAAG,CAAC,KAAY,KAAU;;;;;AAKzC,QAAA,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI;YAAE;;;QAG3B,IAAI,IAAI,CAAC,IAAI,IAAK,KAAqB,CAAC,MAAM,CAAC,cAAc,EAAE;AAC7D,YAAA,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE;QACzB;AACF,IAAA,CAAC;;IAID,iBAAiB,GAAA;QACf,IAAI,CAAC,gBAAgB,CAAC,sBAAsB,EAAE,IAAI,CAAC,SAAS,CAAC;AAC7D,QAAA,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;YAChB,IAAI,CAAC,OAAO,EAAE;QAChB;IACF;IAEA,oBAAoB,GAAA;QAClB,IAAI,CAAC,mBAAmB,CAAC,sBAAsB,EAAE,IAAI,CAAC,SAAS,CAAC;AAChE,QAAA,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE;IACzB;AAEA,IAAA,wBAAwB,CAAC,KAAa,EAAE,QAAuB,EAAE,QAAuB,EAAA;;;;;;QAMtF,IAAI,QAAQ,KAAK,QAAQ;YAAE;;;;AAI3B,QAAA,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,MAAM;YAAE;QACtC,IAAI,CAAC,OAAO,EAAE;IAChB;;;SCrVc,kBAAkB,GAAA;AAChC,IAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE;QAClD,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IAChE;AACF;;ACHM,SAAU,qBAAqB,CAAC,UAA4B,EAAA;IAChE,IAAI,UAAU,EAAE;QACd,SAAS,CAAC,UAAU,CAAC;IACvB;AACA,IAAA,kBAAkB,EAAE;AACtB;;;;"}
@@ -1,2 +1,2 @@
1
- const t={tagNames:{intersect:"wcs-intersect"}};function e(t){if(null===t||"object"!=typeof t)return t;Object.freeze(t);for(const r of Object.keys(t))e(t[r]);return t}function r(t){if(null===t||"object"!=typeof t)return t;const e={};for(const s of Object.keys(t))e[s]=r(t[s]);return e}let s=null;const i=t;function n(){return s||(s=e(r(t))),s}class o extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"entry",event:"wcs-intersect:change"},{name:"intersecting",event:"wcs-intersect:change",getter:t=>t.detail.isIntersecting},{name:"ratio",event:"wcs-intersect:change",getter:t=>t.detail.intersectionRatio},{name:"visible",event:"wcs-intersect:visible-changed"},{name:"observing",event:"wcs-intersect:observing-changed"}],commands:[{name:"observe"},{name:"unobserve"},{name:"disconnect"},{name:"reset"}]};_target;_observer=null;_observed=null;_options={};_entry=null;_visible=!1;_observing=!1;constructor(t){super(),this._target=t??this}get entry(){return this._entry}get intersecting(){return!!this._entry&&this._entry.isIntersecting}get ratio(){return this._entry?this._entry.intersectionRatio:0}get visible(){return this._visible}get observing(){return this._observing}_setEntry(t){this._entry=t,this._target.dispatchEvent(new CustomEvent("wcs-intersect:change",{detail:t,bubbles:!0}))}_setVisible(t){this._visible!==t&&(this._visible=t,this._target.dispatchEvent(new CustomEvent("wcs-intersect:visible-changed",{detail:t,bubbles:!0})))}_setObserving(t){this._observing!==t&&(this._observing=t,this._target.dispatchEvent(new CustomEvent("wcs-intersect:observing-changed",{detail:t,bubbles:!0})))}observe(t,e={}){if(this._observer&&this._observed===t&&this._optionsEqual(this._options,e))return;this._teardownObserver();const r=this._createObserver(e);r?(this._observer=r,this._observed=t,this._options=e,r.observe(t),this._setObserving(!0)):this._setObserving(!1)}unobserve(t){this._observed===t&&(this._teardownObserver(),this._setObserving(!1))}disconnect(){this._teardownObserver(),this._setObserving(!1)}reset(){this._setVisible(!1)}_teardownObserver(){this._observer&&(this._observer.disconnect(),this._observer=null),this._observed=null}_createObserver(t){if("undefined"==typeof IntersectionObserver)return null;try{return new IntersectionObserver(this._onIntersect,{root:t.root??null,rootMargin:t.rootMargin??"0px",threshold:t.threshold??0})}catch{return null}}_onIntersect=t=>{for(const e of t){const t=this._normalizeEntry(e);this._setEntry(t),t.isIntersecting&&this._setVisible(!0)}};_normalizeEntry(t){return{isIntersecting:t.isIntersecting,intersectionRatio:t.intersectionRatio,time:t.time,boundingClientRect:this._normalizeRect(t.boundingClientRect),intersectionRect:this._normalizeRect(t.intersectionRect),rootBounds:t.rootBounds?this._normalizeRect(t.rootBounds):null,target:t.target}}_normalizeRect(t){return{x:t.x,y:t.y,width:t.width,height:t.height,top:t.top,right:t.right,bottom:t.bottom,left:t.left}}_optionsEqual(t,e){return(t.root??null)===(e.root??null)&&((t.rootMargin??"0px")===(e.rootMargin??"0px")&&this._thresholdKey(t.threshold)===this._thresholdKey(e.threshold))}_thresholdKey(t){return void 0===t?"0":Array.isArray(t)?t.join(","):String(t)}}class a extends HTMLElement{static hasConnectedCallbackPromise=!1;static observedAttributes=["target","root","root-margin","threshold"];static wcBindable={...o.wcBindable,properties:[...o.wcBindable.properties,{name:"trigger",event:"wcs-intersect:trigger-changed"}],inputs:[{name:"target",attribute:"target"},{name:"root",attribute:"root"},{name:"rootMargin",attribute:"root-margin"},{name:"threshold",attribute:"threshold"},{name:"once",attribute:"once"},{name:"manual",attribute:"manual"},{name:"trigger"}],commands:o.wcBindable.commands};_core;_trigger=!1;constructor(){super(),this._core=new o(this)}get target(){return this.getAttribute("target")??""}set target(t){this.setAttribute("target",t)}get root(){return this.getAttribute("root")??""}set root(t){this.setAttribute("root",t)}get rootMargin(){const t=this.getAttribute("root-margin");return null===t||""===t.trim()?"0px":t}set rootMargin(t){this.setAttribute("root-margin",t)}get threshold(){return this.getAttribute("threshold")??""}set threshold(t){this.setAttribute("threshold",t)}get once(){return this.hasAttribute("once")}set once(t){t?this.setAttribute("once",""):this.removeAttribute("once")}get manual(){return this.hasAttribute("manual")}set manual(t){t?this.setAttribute("manual",""):this.removeAttribute("manual")}get entry(){return this._core.entry}get intersecting(){return this._core.intersecting}get ratio(){return this._core.ratio}get visible(){return this._core.visible}get observing(){return this._core.observing}get trigger(){return this._trigger}set trigger(t){if(!!t){this._trigger=!0;try{this.observe()}finally{this._trigger=!1,this.dispatchEvent(new CustomEvent("wcs-intersect:trigger-changed",{detail:!1,bubbles:!0}))}}}observe(){const{element:t,display:e}=this._resolveTarget();this.style.display=e,t?this._core.observe(t,this._options()):this._core.disconnect()}unobserve(){this._core.disconnect()}disconnect(){this._core.disconnect()}reset(){this._core.reset()}_resolveTarget(){const t=this.target;if("self"===t)return{element:this,display:"block"};if(""!==t){const e=this.getRootNode();return{element:this._safeQuery(e,t),display:"none"}}const e=this.firstElementChild;return e?{element:e,display:"contents"}:{element:this,display:"block"}}_resolveRoot(){const t=this.root;if(""===t)return null;const e=this.getRootNode();return this._safeQuery(e,t)}_safeQuery(t,e){try{return t.querySelector(e)}catch{return null}}_parseThreshold(){const t=this.threshold.trim();if(""===t)return 0;const e=t.split(",").map(t=>t.trim()).filter(t=>""!==t).map(t=>Number(t)).filter(t=>Number.isFinite(t)&&t>=0&&t<=1);return 0===e.length?0:1===e.length?e[0]:e}_options(){return{root:this._resolveRoot(),rootMargin:this.rootMargin,threshold:this._parseThreshold()}}_onChange=t=>{t.target===this&&this.once&&t.detail.isIntersecting&&this._core.disconnect()};connectedCallback(){this.addEventListener("wcs-intersect:change",this._onChange),this.manual||this.observe()}disconnectedCallback(){this.removeEventListener("wcs-intersect:change",this._onChange),this._core.disconnect()}attributeChangedCallback(t,e,r){e!==r&&this.isConnected&&!this.manual&&this.observe()}}function c(e){var r;e&&((r=e).tagNames&&Object.assign(t.tagNames,r.tagNames),s=null),customElements.get(i.tagNames.intersect)||customElements.define(i.tagNames.intersect,a)}export{o as IntersectionCore,a as WcsIntersect,c as bootstrapIntersection,n as getConfig};
1
+ const t={tagNames:{intersect:"wcs-intersect"}};function e(t){if(null===t||"object"!=typeof t)return t;Object.freeze(t);for(const r of Object.keys(t))e(t[r]);return t}function r(t){if(null===t||"object"!=typeof t)return t;const e={};for(const s of Object.keys(t))e[s]=r(t[s]);return e}let s=null;const i=t;function n(){return s||(s=e(r(t))),s}class o extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"entry",event:"wcs-intersect:change"},{name:"intersecting",event:"wcs-intersect:change",getter:t=>t.detail.isIntersecting},{name:"ratio",event:"wcs-intersect:change",getter:t=>t.detail.intersectionRatio},{name:"visible",event:"wcs-intersect:visible-changed"},{name:"observing",event:"wcs-intersect:observing-changed"}],commands:[{name:"observe"},{name:"reobserve"},{name:"unobserve"},{name:"disconnect"},{name:"reset"}]};_target;_observer=null;_observed=null;_options={};_entry=null;_visible=!1;_observing=!1;constructor(t){super(),this._target=t??this}get entry(){return this._entry}get intersecting(){return!!this._entry&&this._entry.isIntersecting}get ratio(){return this._entry?this._entry.intersectionRatio:0}get visible(){return this._visible}get observing(){return this._observing}_setEntry(t){this._entry=t,this._target.dispatchEvent(new CustomEvent("wcs-intersect:change",{detail:t,bubbles:!0}))}_setVisible(t){this._visible!==t&&(this._visible=t,this._target.dispatchEvent(new CustomEvent("wcs-intersect:visible-changed",{detail:t,bubbles:!0})))}_setObserving(t){this._observing!==t&&(this._observing=t,this._target.dispatchEvent(new CustomEvent("wcs-intersect:observing-changed",{detail:t,bubbles:!0})))}observe(t,e={}){if(this._observer&&this._observed===t&&this._optionsEqual(this._options,e))return;this._teardownObserver();const r=this._createObserver(e);r?(this._observer=r,this._observed=t,this._options=e,r.observe(t),this._setObserving(!0)):this._setObserving(!1)}reobserve(t,e={}){this._teardownObserver(),this.observe(t,e)}unobserve(t){this._observed===t&&(this._teardownObserver(),this._setObserving(!1))}disconnect(){this._teardownObserver(),this._setObserving(!1)}reset(){this._setVisible(!1)}_teardownObserver(){this._observer&&(this._observer.disconnect(),this._observer=null),this._observed=null}_createObserver(t){if("undefined"==typeof IntersectionObserver)return null;try{return new IntersectionObserver(this._onIntersect,{root:t.root??null,rootMargin:t.rootMargin??"0px",threshold:t.threshold??0})}catch{return null}}_onIntersect=t=>{for(const e of t){const t=this._normalizeEntry(e);this._setEntry(t),t.isIntersecting&&this._setVisible(!0)}};_normalizeEntry(t){return{isIntersecting:t.isIntersecting,intersectionRatio:t.intersectionRatio,time:t.time,boundingClientRect:this._normalizeRect(t.boundingClientRect),intersectionRect:this._normalizeRect(t.intersectionRect),rootBounds:t.rootBounds?this._normalizeRect(t.rootBounds):null,target:t.target}}_normalizeRect(t){return{x:t.x,y:t.y,width:t.width,height:t.height,top:t.top,right:t.right,bottom:t.bottom,left:t.left}}_optionsEqual(t,e){return(t.root??null)===(e.root??null)&&((t.rootMargin??"0px")===(e.rootMargin??"0px")&&this._thresholdKey(t.threshold)===this._thresholdKey(e.threshold))}_thresholdKey(t){return void 0===t?"0":Array.isArray(t)?t.join(","):String(t)}}class a extends HTMLElement{static hasConnectedCallbackPromise=!1;static observedAttributes=["target","root","root-margin","threshold"];static wcBindable={...o.wcBindable,properties:[...o.wcBindable.properties,{name:"trigger",event:"wcs-intersect:trigger-changed"}],inputs:[{name:"target",attribute:"target"},{name:"root",attribute:"root"},{name:"rootMargin",attribute:"root-margin"},{name:"threshold",attribute:"threshold"},{name:"once",attribute:"once"},{name:"manual",attribute:"manual"},{name:"trigger"}],commands:o.wcBindable.commands};_core;_trigger=!1;constructor(){super(),this._core=new o(this)}get target(){return this.getAttribute("target")??""}set target(t){this.setAttribute("target",t)}get root(){return this.getAttribute("root")??""}set root(t){this.setAttribute("root",t)}get rootMargin(){const t=this.getAttribute("root-margin");return null===t||""===t.trim()?"0px":t}set rootMargin(t){this.setAttribute("root-margin",t)}get threshold(){return this.getAttribute("threshold")??""}set threshold(t){this.setAttribute("threshold",t)}get once(){return this.hasAttribute("once")}set once(t){t?this.setAttribute("once",""):this.removeAttribute("once")}get manual(){return this.hasAttribute("manual")}set manual(t){t?this.setAttribute("manual",""):this.removeAttribute("manual")}get entry(){return this._core.entry}get intersecting(){return this._core.intersecting}get ratio(){return this._core.ratio}get visible(){return this._core.visible}get observing(){return this._core.observing}get trigger(){return this._trigger}set trigger(t){if(!!t){this._trigger=!0;try{this.observe()}finally{this._trigger=!1,this.dispatchEvent(new CustomEvent("wcs-intersect:trigger-changed",{detail:!1,bubbles:!0}))}}}observe(){const{element:t,display:e}=this._resolveTarget();this.style.display=e,t?this._core.observe(t,this._options()):this._core.disconnect()}reobserve(){const{element:t,display:e}=this._resolveTarget();this.style.display=e,t?this._core.reobserve(t,this._options()):this._core.disconnect()}unobserve(){this._core.disconnect()}disconnect(){this._core.disconnect()}reset(){this._core.reset()}_resolveTarget(){const t=this.target;if("self"===t)return{element:this,display:"block"};if(""!==t){const e=this.getRootNode();return{element:this._safeQuery(e,t),display:"none"}}const e=this.firstElementChild;return e?{element:e,display:"contents"}:{element:this,display:"block"}}_resolveRoot(){const t=this.root;if(""===t)return null;const e=this.getRootNode();return this._safeQuery(e,t)}_safeQuery(t,e){try{return t.querySelector(e)}catch{return null}}_parseThreshold(){const t=this.threshold.trim();if(""===t)return 0;const e=t.split(",").map(t=>t.trim()).filter(t=>""!==t).map(t=>Number(t)).filter(t=>Number.isFinite(t)&&t>=0&&t<=1);return 0===e.length?0:1===e.length?e[0]:e}_options(){return{root:this._resolveRoot(),rootMargin:this.rootMargin,threshold:this._parseThreshold()}}_onChange=t=>{t.target===this&&this.once&&t.detail.isIntersecting&&this._core.disconnect()};connectedCallback(){this.addEventListener("wcs-intersect:change",this._onChange),this.manual||this.observe()}disconnectedCallback(){this.removeEventListener("wcs-intersect:change",this._onChange),this._core.disconnect()}attributeChangedCallback(t,e,r){e!==r&&this.isConnected&&!this.manual&&this.observe()}}function c(e){var r;e&&((r=e).tagNames&&Object.assign(t.tagNames,r.tagNames),s=null),customElements.get(i.tagNames.intersect)||customElements.define(i.tagNames.intersect,a)}export{o as IntersectionCore,a as WcsIntersect,c as bootstrapIntersection,n as getConfig};
2
2
  //# sourceMappingURL=index.esm.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.min.js","sources":["../src/config.ts","../src/core/IntersectionCore.ts","../src/components/Intersect.ts","../src/bootstrapIntersection.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n tagNames: {\n intersect: string;\n };\n}\n\nconst _config: IInternalConfig = {\n tagNames: {\n intersect: \"wcs-intersect\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { IWcBindable, IntersectOptions, WcsIntersectEntry, WcsIntersectRect } from \"../types.js\";\n\n/**\n * Headless visibility primitive. A thin, framework-agnostic wrapper around the\n * IntersectionObserver API exposed through the wc-bindable protocol.\n *\n * Unlike the other @wcstack sensors (geolocation / timer / websocket), the thing\n * being observed is a *DOM element* — so `observe()` takes the target node. The\n * Core stays DOM-resolution-agnostic: it observes whatever element it is handed\n * (the Shell resolves `target` / `root` selectors before calling). It is a\n * read-only producer — element/layout → state only, with no element-bound path.\n *\n * Every observer callback is published via the single `wcs-intersect:change`\n * event; `intersecting` / `ratio` are read from it through getters (mirroring how\n * GeolocationCore exposes latitude/longitude from one `wcs-geo:position` event),\n * so an observer that binds any of them is notified on every change.\n *\n * `visible` is a latch: it flips to `true` the first time the target intersects\n * and stays `true` until `reset()` — ideal for one-way lazy-load bindings\n * (`src@visible`). `observing` reflects whether an observation is currently\n * active (like TimerCore's `running`).\n *\n * Single-target by design: the Shell observes exactly one element, so the state\n * reflects that element. Multi-target observation is intentionally out of scope.\n */\nexport class IntersectionCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"entry\", event: \"wcs-intersect:change\" },\n { name: \"intersecting\", event: \"wcs-intersect:change\", getter: (e: Event) => (e as CustomEvent).detail.isIntersecting },\n { name: \"ratio\", event: \"wcs-intersect:change\", getter: (e: Event) => (e as CustomEvent).detail.intersectionRatio },\n { name: \"visible\", event: \"wcs-intersect:visible-changed\" },\n { name: \"observing\", event: \"wcs-intersect:observing-changed\" },\n ],\n commands: [\n { name: \"observe\" },\n { name: \"unobserve\" },\n { name: \"disconnect\" },\n { name: \"reset\" },\n ],\n };\n\n private _target: EventTarget;\n\n // The live observer and the single element it observes. Options are kept so a\n // repeated observe() with identical options is a no-op (avoids the create→\n // observe→disconnect churn an autoloader upgrade can otherwise cause).\n private _observer: IntersectionObserver | null = null;\n private _observed: Element | null = null;\n private _options: IntersectOptions = {};\n\n private _entry: WcsIntersectEntry | null = null;\n private _visible: boolean = false;\n private _observing: boolean = false;\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get entry(): WcsIntersectEntry | null {\n return this._entry;\n }\n\n get intersecting(): boolean {\n return this._entry ? this._entry.isIntersecting : false;\n }\n\n get ratio(): number {\n return this._entry ? this._entry.intersectionRatio : 0;\n }\n\n get visible(): boolean {\n return this._visible;\n }\n\n get observing(): boolean {\n return this._observing;\n }\n\n // --- State setters with event dispatch ---\n\n private _setEntry(entry: WcsIntersectEntry): void {\n // No same-value guard: `change` carries event semantics (every callback is a\n // distinct observation) and `intersecting` / `ratio` are derived getters that\n // must re-fire on each entry, mirroring GeolocationCore's `position`.\n this._entry = entry;\n this._target.dispatchEvent(new CustomEvent(\"wcs-intersect:change\", {\n detail: entry,\n bubbles: true,\n }));\n }\n\n private _setVisible(visible: boolean): void {\n if (this._visible === visible) return;\n this._visible = visible;\n this._target.dispatchEvent(new CustomEvent(\"wcs-intersect:visible-changed\", {\n detail: visible,\n bubbles: true,\n }));\n }\n\n private _setObserving(observing: boolean): void {\n if (this._observing === observing) return;\n this._observing = observing;\n this._target.dispatchEvent(new CustomEvent(\"wcs-intersect:observing-changed\", {\n detail: observing,\n bubbles: true,\n }));\n }\n\n // --- Public API ---\n\n /**\n * Start observing `element`. Idempotent while already observing the same\n * element with the same options. Changing the element or options tears down the\n * current observer and builds a new one (IntersectionObserver options are fixed\n * at construction, so reconfiguring requires a fresh observer).\n *\n * If IntersectionObserver is unavailable (SSR) or the options are invalid (e.g.\n * a malformed `rootMargin`, which the constructor rejects), this is a silent\n * no-op — `observing` stays false, consistent with the never-throw design of\n * the other @wcstack sensors.\n */\n observe(element: Element, options: IntersectOptions = {}): void {\n if (this._observer && this._observed === element && this._optionsEqual(this._options, options)) {\n return;\n }\n this._teardownObserver();\n const observer = this._createObserver(options);\n if (!observer) {\n // Creation failed (unsupported environment or invalid options) *after* we\n // tore down any previous observer. If we were already observing, the\n // observation is now gone, so reflect that — otherwise `observing` would\n // keep reporting true with no live observer behind it (e.g. re-observing an\n // active target with a newly-invalid rootMargin).\n this._setObserving(false);\n return;\n }\n this._observer = observer;\n this._observed = element;\n this._options = options;\n observer.observe(element);\n this._setObserving(true);\n }\n\n /**\n * Stop observing `element`. A no-op if it is not the currently observed\n * element. The observer instance is torn down (single-target Core), so a later\n * observe() rebuilds it.\n */\n unobserve(element: Element): void {\n if (this._observed !== element) return;\n this._teardownObserver();\n this._setObserving(false);\n }\n\n /** Stop all observation and release the observer. */\n disconnect(): void {\n this._teardownObserver();\n this._setObserving(false);\n }\n\n /** Clear the `visible` latch so a later intersection can set it again. */\n reset(): void {\n this._setVisible(false);\n }\n\n // --- Internal ---\n\n private _teardownObserver(): void {\n if (this._observer) {\n this._observer.disconnect();\n this._observer = null;\n }\n this._observed = null;\n }\n\n private _createObserver(options: IntersectOptions): IntersectionObserver | null {\n if (typeof IntersectionObserver === \"undefined\") return null;\n try {\n return new IntersectionObserver(this._onIntersect, {\n root: options.root ?? null,\n rootMargin: options.rootMargin ?? \"0px\",\n threshold: options.threshold ?? 0,\n });\n } catch {\n // Invalid options (e.g. a malformed rootMargin) — surface nothing and leave\n // observing false, rather than letting the constructor throw escape.\n return null;\n }\n }\n\n private _onIntersect = (entries: IntersectionObserverEntry[]): void => {\n for (const entry of entries) {\n const normalized = this._normalizeEntry(entry);\n this._setEntry(normalized);\n // Latch on the first (and any) intersecting observation; never auto-clears.\n if (normalized.isIntersecting) {\n this._setVisible(true);\n }\n }\n };\n\n private _normalizeEntry(entry: IntersectionObserverEntry): WcsIntersectEntry {\n return {\n isIntersecting: entry.isIntersecting,\n intersectionRatio: entry.intersectionRatio,\n time: entry.time,\n boundingClientRect: this._normalizeRect(entry.boundingClientRect),\n intersectionRect: this._normalizeRect(entry.intersectionRect),\n rootBounds: entry.rootBounds ? this._normalizeRect(entry.rootBounds) : null,\n target: entry.target,\n };\n }\n\n private _normalizeRect(rect: DOMRectReadOnly): WcsIntersectRect {\n return {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n top: rect.top,\n right: rect.right,\n bottom: rect.bottom,\n left: rect.left,\n };\n }\n\n private _optionsEqual(a: IntersectOptions, b: IntersectOptions): boolean {\n if ((a.root ?? null) !== (b.root ?? null)) return false;\n if ((a.rootMargin ?? \"0px\") !== (b.rootMargin ?? \"0px\")) return false;\n return this._thresholdKey(a.threshold) === this._thresholdKey(b.threshold);\n }\n\n private _thresholdKey(threshold: number | number[] | undefined): string {\n if (threshold === undefined) return \"0\";\n return Array.isArray(threshold) ? threshold.join(\",\") : String(threshold);\n }\n}\n","import { IWcBindable, IntersectOptions, WcsIntersectEntry } from \"../types.js\";\nimport { IntersectionCore } from \"../core/IntersectionCore.js\";\n\n/**\n * `<wcs-intersect>` — declarative IntersectionObserver.\n *\n * The `target` attribute is the single knob that decides both *what* is observed\n * and how the element renders (it never injects a layout box unless asked):\n *\n * | `target` | observes | display | use case |\n * |-----------------|-----------------------|-------------|-------------------|\n * | omitted | first element child | `contents` | lazy-load wrapper |\n * | `\"#hero\"` / sel | the matched element | `none` | scrollspy (single)|\n * | `\"self\"` | the element itself | `block` | infinite-scroll |\n *\n * `display:contents` means wrapping a child injects no box of its own (so a\n * `<wcs-intersect><img></wcs-intersect>` does not disturb a flex/grid parent);\n * only the explicit `target=\"self\"` sentinel takes a box.\n */\nexport class WcsIntersect extends HTMLElement {\n static hasConnectedCallbackPromise = false;\n // Only attributes that change *what or how* we observe trigger a re-observe.\n // `once` is intentionally excluded: it is evaluated at intersection fire time\n // (in `_onChange`), so toggling it takes effect without re-observing — and a\n // re-observe on its change would be a pure no-op (same target, same options).\n // `manual` is also excluded: it is a connect-time policy (\"don't auto-observe\n // on connect\"), not a live switch that should start/stop an active observation.\n static observedAttributes = [\"target\", \"root\", \"root-margin\", \"threshold\"];\n\n static wcBindable: IWcBindable = {\n ...IntersectionCore.wcBindable,\n properties: [\n ...IntersectionCore.wcBindable.properties,\n { name: \"trigger\", event: \"wcs-intersect:trigger-changed\" },\n ],\n // Shell-level settable surface. Each input carries its mirrored `attribute`\n // hint; `trigger` has none — it is a momentary command-property, not a\n // declarative attribute. The observe / unobserve / disconnect / reset commands\n // are inherited from the Core via the spread above.\n inputs: [\n { name: \"target\", attribute: \"target\" },\n { name: \"root\", attribute: \"root\" },\n { name: \"rootMargin\", attribute: \"root-margin\" },\n { name: \"threshold\", attribute: \"threshold\" },\n { name: \"once\", attribute: \"once\" },\n { name: \"manual\", attribute: \"manual\" },\n { name: \"trigger\" },\n ],\n // Core の commands をそのまま継承(単一情報源)。<wcs-sse>/<wcs-broadcast> と同型。\n // spread でも継承されるが、Core に command 追加時の追従漏れを防ぐため明示参照する。\n commands: IntersectionCore.wcBindable.commands,\n };\n\n private _core: IntersectionCore;\n private _trigger: boolean = false;\n\n constructor() {\n super();\n this._core = new IntersectionCore(this);\n }\n\n // --- Attribute accessors ---\n\n get target(): string {\n return this.getAttribute(\"target\") ?? \"\";\n }\n\n set target(value: string) {\n this.setAttribute(\"target\", value);\n }\n\n get root(): string {\n return this.getAttribute(\"root\") ?? \"\";\n }\n\n set root(value: string) {\n this.setAttribute(\"root\", value);\n }\n\n get rootMargin(): string {\n const attr = this.getAttribute(\"root-margin\");\n return attr === null || attr.trim() === \"\" ? \"0px\" : attr;\n }\n\n set rootMargin(value: string) {\n this.setAttribute(\"root-margin\", value);\n }\n\n get threshold(): string {\n return this.getAttribute(\"threshold\") ?? \"\";\n }\n\n set threshold(value: string) {\n this.setAttribute(\"threshold\", value);\n }\n\n get once(): boolean {\n return this.hasAttribute(\"once\");\n }\n\n set once(value: boolean) {\n if (value) {\n this.setAttribute(\"once\", \"\");\n } else {\n this.removeAttribute(\"once\");\n }\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n // --- Core delegated getters ---\n\n get entry(): WcsIntersectEntry | null {\n return this._core.entry;\n }\n\n get intersecting(): boolean {\n return this._core.intersecting;\n }\n\n get ratio(): number {\n return this._core.ratio;\n }\n\n get visible(): boolean {\n return this._core.visible;\n }\n\n get observing(): boolean {\n return this._core.observing;\n }\n\n // --- Command property ---\n\n get trigger(): boolean {\n return this._trigger;\n }\n\n set trigger(value: boolean) {\n // Momentary command-property: a false→true write re-runs observe(). Mirrors\n // the trigger flag on <wcs-geo> / <wcs-ws> / <wcs-sse>. Prefer the command-token\n // protocol (`command.observe: $command.start`) for state-driven observation;\n // this exists mainly for simple boolean bindings.\n const v = !!value; // normalize truthy state-bindings, like <wcs-sse>'s setter\n if (v) {\n this._trigger = true;\n // try/finally mirrors <wcs-sse>'s set trigger: observe() is never-throw\n // today, but should a synchronous throw path ever appear, the finally still\n // auto-resets _trigger (no stuck-true latch) and emits the completion notice.\n try {\n this.observe();\n } finally {\n this._trigger = false;\n // Always auto-reset to false after the observe() attempt — this is the\n // *momentary acknowledgement* that the trigger was consumed, NOT a signal\n // that observation succeeded (whether the target resolved is reflected by\n // `observing`, not by this event). Firing unconditionally keeps the bound\n // state's trigger flag from sticking at true regardless of resolution.\n // Read `observing` if you need the actual outcome.\n this.dispatchEvent(new CustomEvent(\"wcs-intersect:trigger-changed\", {\n detail: false,\n bubbles: true,\n }));\n }\n }\n }\n\n // --- Commands ---\n\n /** Re-resolve the target/root from the DOM and (re)start observing. */\n observe(): void {\n const { element, display } = this._resolveTarget();\n // `display` is derived from the `target` *mode* (self/selector/child), not from\n // whether the selector currently matches — so it is applied unconditionally,\n // before the resolution check. A `target=\"#x\"` whose node is momentarily absent\n // still renders `display:none` (it is a selector pointer, never a box).\n this.style.display = display;\n if (!element) {\n // The target is no longer resolvable (e.g. a `target` selector whose node\n // was removed from the DOM). Tear down any stale observation so `observing`\n // does not keep reporting true against a node that is gone.\n this._core.disconnect();\n return;\n }\n this._core.observe(element, this._options());\n }\n\n unobserve(): void {\n // Single-target Shell: \"stop observing my target\" is exactly the Core's\n // teardown. Delegate to the Core's tracked state rather than re-resolving the\n // selector, so a target that has since left the DOM can still be stopped\n // (re-resolving would yield null and silently leave the observer running).\n this._core.disconnect();\n }\n\n disconnect(): void {\n this._core.disconnect();\n }\n\n reset(): void {\n this._core.reset();\n }\n\n // --- Internal ---\n\n private _resolveTarget(): { element: Element | null; display: string } {\n const target = this.target;\n if (target === \"self\") {\n // Explicit sentinel: observe the element itself as a (typically zero-height)\n // marker, which requires a layout box.\n return { element: this, display: \"block\" };\n }\n if (target !== \"\") {\n // Selector pointer: observe a referenced element in place, staying invisible.\n const scope = this.getRootNode() as Document | ShadowRoot;\n // A user-authored selector can be syntactically invalid (e.g. `#`, `:::`,\n // `[data-*`), which makes querySelector throw a SyntaxError. Swallow it and\n // treat the target as unresolvable — the same \"nothing to observe\" path as a\n // selector matching no element — so a bad attribute never lets the throw\n // escape observe() → connectedCallback / attributeChangedCallback (never-throw).\n return { element: this._safeQuery(scope, target), display: \"none\" };\n }\n // Omitted: observe the first element child without injecting a box of our own.\n const child = this.firstElementChild;\n if (child) {\n return { element: child, display: \"contents\" };\n }\n // No child to wrap (e.g. used as an empty marker) — fall back to self.\n return { element: this, display: \"block\" };\n }\n\n private _resolveRoot(): Element | null {\n const root = this.root;\n if (root === \"\") return null;\n const scope = this.getRootNode() as Document | ShadowRoot;\n // Same never-throw guard as the target selector: an invalid `root` selector\n // falls back to a null root (the viewport) rather than throwing out of observe().\n return this._safeQuery(scope, root);\n }\n\n // Wrap querySelector so a syntactically invalid user-authored selector resolves\n // to null (unresolvable) instead of letting the SyntaxError escape — keeping the\n // sensor never-throw, mirroring worker/src/autoTrigger.ts's resolveText guard.\n private _safeQuery(scope: Document | ShadowRoot, selector: string): Element | null {\n try {\n return scope.querySelector(selector);\n } catch {\n return null;\n }\n }\n\n private _parseThreshold(): number | number[] {\n const raw = this.threshold.trim();\n if (raw === \"\") return 0;\n // Strict parse via Number() (unlike parseFloat, \"0.5px\" -> NaN, not 0.5); drop\n // any non-finite or out-of-range [0,1] value, matching the README note.\n // Drop empty slots first (\"0,,1\" / \"1,\") — Number(\"\") is 0, which would\n // otherwise smuggle a spurious 0 threshold past the finite/range filter.\n const nums = raw\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s !== \"\")\n .map((s) => Number(s))\n .filter((n) => Number.isFinite(n) && n >= 0 && n <= 1);\n if (nums.length === 0) return 0;\n return nums.length === 1 ? nums[0] : nums;\n }\n\n private _options(): IntersectOptions {\n return {\n root: this._resolveRoot(),\n rootMargin: this.rootMargin,\n threshold: this._parseThreshold(),\n };\n }\n\n private _onChange = (event: Event): void => {\n // `wcs-intersect:change` bubbles, so a nested `<wcs-intersect>` descendant's\n // change would otherwise reach this (ancestor) listener and let a *child's*\n // intersection tear down *our* observer. Only act on our own Core's event.\n // (This also avoids reading `.detail` off a foreign event shape.)\n if (event.target !== this) return;\n // `once`: tear down after the first intersecting observation (lazy-load idiom).\n // Gated at fire time so toggling the `once` attribute takes effect live.\n if (this.once && (event as CustomEvent).detail.isIntersecting) {\n this._core.disconnect();\n }\n };\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this.addEventListener(\"wcs-intersect:change\", this._onChange);\n if (!this.manual) {\n this.observe();\n }\n }\n\n disconnectedCallback(): void {\n this.removeEventListener(\"wcs-intersect:change\", this._onChange);\n this._core.disconnect();\n }\n\n attributeChangedCallback(_name: string, oldValue: string | null, newValue: string | null): void {\n // Defensive same-value guard. Per spec attributeChangedCallback only fires on\n // an actual value change, so this is effectively a dead branch today — but\n // setAttribute() with an unchanged value (and some test/tooling paths) can\n // still invoke it, and re-observing on an unchanged attribute would be a\n // wasted observer rebuild. Kept intentionally; do not remove.\n if (oldValue === newValue) return;\n // Only react once connected and in automatic mode. The Core's idempotency\n // guard absorbs the autoloader upgrade case (attributeChangedCallback +\n // connectedCallback both calling observe() with identical options).\n if (!this.isConnected || this.manual) return;\n this.observe();\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapIntersection(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n","import { WcsIntersect } from \"./components/Intersect.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.intersect)) {\n customElements.define(config.tagNames.intersect, WcsIntersect);\n }\n}\n"],"names":["_config","tagNames","intersect","deepFreeze","obj","Object","freeze","key","keys","deepClone","clone","frozenConfig","config","getConfig","IntersectionCore","EventTarget","static","protocol","version","properties","name","event","getter","e","detail","isIntersecting","intersectionRatio","commands","_target","_observer","_observed","_options","_entry","_visible","_observing","constructor","target","super","this","entry","intersecting","ratio","visible","observing","_setEntry","dispatchEvent","CustomEvent","bubbles","_setVisible","_setObserving","observe","element","options","_optionsEqual","_teardownObserver","observer","_createObserver","unobserve","disconnect","reset","IntersectionObserver","_onIntersect","root","rootMargin","threshold","entries","normalized","_normalizeEntry","time","boundingClientRect","_normalizeRect","intersectionRect","rootBounds","rect","x","y","width","height","top","right","bottom","left","a","b","_thresholdKey","undefined","Array","isArray","join","String","WcsIntersect","HTMLElement","wcBindable","inputs","attribute","_core","_trigger","getAttribute","value","setAttribute","attr","trim","once","hasAttribute","removeAttribute","manual","trigger","display","_resolveTarget","style","scope","getRootNode","_safeQuery","child","firstElementChild","_resolveRoot","selector","querySelector","_parseThreshold","raw","nums","split","map","s","filter","Number","n","isFinite","length","_onChange","connectedCallback","addEventListener","disconnectedCallback","removeEventListener","attributeChangedCallback","_name","oldValue","newValue","isConnected","bootstrapIntersection","userConfig","partialConfig","assign","customElements","get","define"],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.min.js","sources":["../src/config.ts","../src/core/IntersectionCore.ts","../src/components/Intersect.ts","../src/bootstrapIntersection.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n tagNames: {\n intersect: string;\n };\n}\n\nconst _config: IInternalConfig = {\n tagNames: {\n intersect: \"wcs-intersect\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { IWcBindable, IntersectOptions, WcsIntersectEntry, WcsIntersectRect } from \"../types.js\";\n\n/**\n * Headless visibility primitive. A thin, framework-agnostic wrapper around the\n * IntersectionObserver API exposed through the wc-bindable protocol.\n *\n * Unlike the other @wcstack sensors (geolocation / timer / websocket), the thing\n * being observed is a *DOM element* — so `observe()` takes the target node. The\n * Core stays DOM-resolution-agnostic: it observes whatever element it is handed\n * (the Shell resolves `target` / `root` selectors before calling). It is a\n * read-only producer — element/layout → state only, with no element-bound path.\n *\n * Every observer callback is published via the single `wcs-intersect:change`\n * event; `intersecting` / `ratio` are read from it through getters (mirroring how\n * GeolocationCore exposes latitude/longitude from one `wcs-geo:position` event),\n * so an observer that binds any of them is notified on every change.\n *\n * `visible` is a latch: it flips to `true` the first time the target intersects\n * and stays `true` until `reset()` — ideal for one-way lazy-load bindings\n * (`src@visible`). `observing` reflects whether an observation is currently\n * active (like TimerCore's `running`).\n *\n * Single-target by design: the Shell observes exactly one element, so the state\n * reflects that element. Multi-target observation is intentionally out of scope.\n */\nexport class IntersectionCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"entry\", event: \"wcs-intersect:change\" },\n { name: \"intersecting\", event: \"wcs-intersect:change\", getter: (e: Event) => (e as CustomEvent).detail.isIntersecting },\n { name: \"ratio\", event: \"wcs-intersect:change\", getter: (e: Event) => (e as CustomEvent).detail.intersectionRatio },\n { name: \"visible\", event: \"wcs-intersect:visible-changed\" },\n { name: \"observing\", event: \"wcs-intersect:observing-changed\" },\n ],\n commands: [\n { name: \"observe\" },\n { name: \"reobserve\" },\n { name: \"unobserve\" },\n { name: \"disconnect\" },\n { name: \"reset\" },\n ],\n };\n\n private _target: EventTarget;\n\n // The live observer and the single element it observes. Options are kept so a\n // repeated observe() with identical options is a no-op (avoids the create→\n // observe→disconnect churn an autoloader upgrade can otherwise cause).\n private _observer: IntersectionObserver | null = null;\n private _observed: Element | null = null;\n private _options: IntersectOptions = {};\n\n private _entry: WcsIntersectEntry | null = null;\n private _visible: boolean = false;\n private _observing: boolean = false;\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get entry(): WcsIntersectEntry | null {\n return this._entry;\n }\n\n get intersecting(): boolean {\n return this._entry ? this._entry.isIntersecting : false;\n }\n\n get ratio(): number {\n return this._entry ? this._entry.intersectionRatio : 0;\n }\n\n get visible(): boolean {\n return this._visible;\n }\n\n get observing(): boolean {\n return this._observing;\n }\n\n // --- State setters with event dispatch ---\n\n private _setEntry(entry: WcsIntersectEntry): void {\n // No same-value guard: `change` carries event semantics (every callback is a\n // distinct observation) and `intersecting` / `ratio` are derived getters that\n // must re-fire on each entry, mirroring GeolocationCore's `position`.\n this._entry = entry;\n this._target.dispatchEvent(new CustomEvent(\"wcs-intersect:change\", {\n detail: entry,\n bubbles: true,\n }));\n }\n\n private _setVisible(visible: boolean): void {\n if (this._visible === visible) return;\n this._visible = visible;\n this._target.dispatchEvent(new CustomEvent(\"wcs-intersect:visible-changed\", {\n detail: visible,\n bubbles: true,\n }));\n }\n\n private _setObserving(observing: boolean): void {\n if (this._observing === observing) return;\n this._observing = observing;\n this._target.dispatchEvent(new CustomEvent(\"wcs-intersect:observing-changed\", {\n detail: observing,\n bubbles: true,\n }));\n }\n\n // --- Public API ---\n\n /**\n * Start observing `element`. Idempotent while already observing the same\n * element with the same options. Changing the element or options tears down the\n * current observer and builds a new one (IntersectionObserver options are fixed\n * at construction, so reconfiguring requires a fresh observer).\n *\n * If IntersectionObserver is unavailable (SSR) or the options are invalid (e.g.\n * a malformed `rootMargin`, which the constructor rejects), this is a silent\n * no-op — `observing` stays false, consistent with the never-throw design of\n * the other @wcstack sensors.\n */\n observe(element: Element, options: IntersectOptions = {}): void {\n if (this._observer && this._observed === element && this._optionsEqual(this._options, options)) {\n return;\n }\n this._teardownObserver();\n const observer = this._createObserver(options);\n if (!observer) {\n // Creation failed (unsupported environment or invalid options) *after* we\n // tore down any previous observer. If we were already observing, the\n // observation is now gone, so reflect that — otherwise `observing` would\n // keep reporting true with no live observer behind it (e.g. re-observing an\n // active target with a newly-invalid rootMargin).\n this._setObserving(false);\n return;\n }\n this._observer = observer;\n this._observed = element;\n this._options = options;\n observer.observe(element);\n this._setObserving(true);\n }\n\n /**\n * Force a fresh observation of `element`, even when it matches the currently\n * observed target+options. Unlike observe() — which is idempotent and\n * early-returns for an unchanged target+options *without* re-delivering a\n * callback — this always tears the observer down and rebuilds it, so a new\n * IntersectionObserver delivers an initial callback for the element's CURRENT\n * visibility.\n *\n * This is the way to re-arm an edge-driven consumer (e.g. infinite scroll) after\n * the layout changed without a visibility *transition*: IntersectionObserver only\n * fires on a change, so appending a short page that leaves the sentinel visible\n * yields no new callback — a bare observe() can't help (idempotent), but a\n * reobserve() re-reads the current state. Same never-throw guarantees as\n * observe(); `observing` stays true across a successful re-arm (no false blip).\n */\n reobserve(element: Element, options: IntersectOptions = {}): void {\n this._teardownObserver();\n this.observe(element, options);\n }\n\n /**\n * Stop observing `element`. A no-op if it is not the currently observed\n * element. The observer instance is torn down (single-target Core), so a later\n * observe() rebuilds it.\n */\n unobserve(element: Element): void {\n if (this._observed !== element) return;\n this._teardownObserver();\n this._setObserving(false);\n }\n\n /** Stop all observation and release the observer. */\n disconnect(): void {\n this._teardownObserver();\n this._setObserving(false);\n }\n\n /** Clear the `visible` latch so a later intersection can set it again. */\n reset(): void {\n this._setVisible(false);\n }\n\n // --- Internal ---\n\n private _teardownObserver(): void {\n if (this._observer) {\n this._observer.disconnect();\n this._observer = null;\n }\n this._observed = null;\n }\n\n private _createObserver(options: IntersectOptions): IntersectionObserver | null {\n if (typeof IntersectionObserver === \"undefined\") return null;\n try {\n return new IntersectionObserver(this._onIntersect, {\n root: options.root ?? null,\n rootMargin: options.rootMargin ?? \"0px\",\n threshold: options.threshold ?? 0,\n });\n } catch {\n // Invalid options (e.g. a malformed rootMargin) — surface nothing and leave\n // observing false, rather than letting the constructor throw escape.\n return null;\n }\n }\n\n private _onIntersect = (entries: IntersectionObserverEntry[]): void => {\n for (const entry of entries) {\n const normalized = this._normalizeEntry(entry);\n this._setEntry(normalized);\n // Latch on the first (and any) intersecting observation; never auto-clears.\n if (normalized.isIntersecting) {\n this._setVisible(true);\n }\n }\n };\n\n private _normalizeEntry(entry: IntersectionObserverEntry): WcsIntersectEntry {\n return {\n isIntersecting: entry.isIntersecting,\n intersectionRatio: entry.intersectionRatio,\n time: entry.time,\n boundingClientRect: this._normalizeRect(entry.boundingClientRect),\n intersectionRect: this._normalizeRect(entry.intersectionRect),\n rootBounds: entry.rootBounds ? this._normalizeRect(entry.rootBounds) : null,\n target: entry.target,\n };\n }\n\n private _normalizeRect(rect: DOMRectReadOnly): WcsIntersectRect {\n return {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n top: rect.top,\n right: rect.right,\n bottom: rect.bottom,\n left: rect.left,\n };\n }\n\n private _optionsEqual(a: IntersectOptions, b: IntersectOptions): boolean {\n if ((a.root ?? null) !== (b.root ?? null)) return false;\n if ((a.rootMargin ?? \"0px\") !== (b.rootMargin ?? \"0px\")) return false;\n return this._thresholdKey(a.threshold) === this._thresholdKey(b.threshold);\n }\n\n private _thresholdKey(threshold: number | number[] | undefined): string {\n if (threshold === undefined) return \"0\";\n return Array.isArray(threshold) ? threshold.join(\",\") : String(threshold);\n }\n}\n","import { IWcBindable, IntersectOptions, WcsIntersectEntry } from \"../types.js\";\nimport { IntersectionCore } from \"../core/IntersectionCore.js\";\n\n/**\n * `<wcs-intersect>` — declarative IntersectionObserver.\n *\n * The `target` attribute is the single knob that decides both *what* is observed\n * and how the element renders (it never injects a layout box unless asked):\n *\n * | `target` | observes | display | use case |\n * |-----------------|-----------------------|-------------|-------------------|\n * | omitted | first element child | `contents` | lazy-load wrapper |\n * | `\"#hero\"` / sel | the matched element | `none` | scrollspy (single)|\n * | `\"self\"` | the element itself | `block` | infinite-scroll |\n *\n * `display:contents` means wrapping a child injects no box of its own (so a\n * `<wcs-intersect><img></wcs-intersect>` does not disturb a flex/grid parent);\n * only the explicit `target=\"self\"` sentinel takes a box.\n */\nexport class WcsIntersect extends HTMLElement {\n static hasConnectedCallbackPromise = false;\n // Only attributes that change *what or how* we observe trigger a re-observe.\n // `once` is intentionally excluded: it is evaluated at intersection fire time\n // (in `_onChange`), so toggling it takes effect without re-observing — and a\n // re-observe on its change would be a pure no-op (same target, same options).\n // `manual` is also excluded: it is a connect-time policy (\"don't auto-observe\n // on connect\"), not a live switch that should start/stop an active observation.\n static observedAttributes = [\"target\", \"root\", \"root-margin\", \"threshold\"];\n\n static wcBindable: IWcBindable = {\n ...IntersectionCore.wcBindable,\n properties: [\n ...IntersectionCore.wcBindable.properties,\n { name: \"trigger\", event: \"wcs-intersect:trigger-changed\" },\n ],\n // Shell-level settable surface. Each input carries its mirrored `attribute`\n // hint; `trigger` has none — it is a momentary command-property, not a\n // declarative attribute. The observe / reobserve / unobserve / disconnect /\n // reset commands are inherited from the Core via the spread above.\n inputs: [\n { name: \"target\", attribute: \"target\" },\n { name: \"root\", attribute: \"root\" },\n { name: \"rootMargin\", attribute: \"root-margin\" },\n { name: \"threshold\", attribute: \"threshold\" },\n { name: \"once\", attribute: \"once\" },\n { name: \"manual\", attribute: \"manual\" },\n { name: \"trigger\" },\n ],\n // Core の commands をそのまま継承(単一情報源)。<wcs-sse>/<wcs-broadcast> と同型。\n // spread でも継承されるが、Core に command 追加時の追従漏れを防ぐため明示参照する。\n commands: IntersectionCore.wcBindable.commands,\n };\n\n private _core: IntersectionCore;\n private _trigger: boolean = false;\n\n constructor() {\n super();\n this._core = new IntersectionCore(this);\n }\n\n // --- Attribute accessors ---\n\n get target(): string {\n return this.getAttribute(\"target\") ?? \"\";\n }\n\n set target(value: string) {\n this.setAttribute(\"target\", value);\n }\n\n get root(): string {\n return this.getAttribute(\"root\") ?? \"\";\n }\n\n set root(value: string) {\n this.setAttribute(\"root\", value);\n }\n\n get rootMargin(): string {\n const attr = this.getAttribute(\"root-margin\");\n return attr === null || attr.trim() === \"\" ? \"0px\" : attr;\n }\n\n set rootMargin(value: string) {\n this.setAttribute(\"root-margin\", value);\n }\n\n get threshold(): string {\n return this.getAttribute(\"threshold\") ?? \"\";\n }\n\n set threshold(value: string) {\n this.setAttribute(\"threshold\", value);\n }\n\n get once(): boolean {\n return this.hasAttribute(\"once\");\n }\n\n set once(value: boolean) {\n if (value) {\n this.setAttribute(\"once\", \"\");\n } else {\n this.removeAttribute(\"once\");\n }\n }\n\n get manual(): boolean {\n return this.hasAttribute(\"manual\");\n }\n\n set manual(value: boolean) {\n if (value) {\n this.setAttribute(\"manual\", \"\");\n } else {\n this.removeAttribute(\"manual\");\n }\n }\n\n // --- Core delegated getters ---\n\n get entry(): WcsIntersectEntry | null {\n return this._core.entry;\n }\n\n get intersecting(): boolean {\n return this._core.intersecting;\n }\n\n get ratio(): number {\n return this._core.ratio;\n }\n\n get visible(): boolean {\n return this._core.visible;\n }\n\n get observing(): boolean {\n return this._core.observing;\n }\n\n // --- Command property ---\n\n get trigger(): boolean {\n return this._trigger;\n }\n\n set trigger(value: boolean) {\n // Momentary command-property: a false→true write re-runs observe(). Mirrors\n // the trigger flag on <wcs-geo> / <wcs-ws> / <wcs-sse>. Prefer the command-token\n // protocol (`command.observe: $command.start`) for state-driven observation;\n // this exists mainly for simple boolean bindings.\n const v = !!value; // normalize truthy state-bindings, like <wcs-sse>'s setter\n if (v) {\n this._trigger = true;\n // try/finally mirrors <wcs-sse>'s set trigger: observe() is never-throw\n // today, but should a synchronous throw path ever appear, the finally still\n // auto-resets _trigger (no stuck-true latch) and emits the completion notice.\n try {\n this.observe();\n } finally {\n this._trigger = false;\n // Always auto-reset to false after the observe() attempt — this is the\n // *momentary acknowledgement* that the trigger was consumed, NOT a signal\n // that observation succeeded (whether the target resolved is reflected by\n // `observing`, not by this event). Firing unconditionally keeps the bound\n // state's trigger flag from sticking at true regardless of resolution.\n // Read `observing` if you need the actual outcome.\n this.dispatchEvent(new CustomEvent(\"wcs-intersect:trigger-changed\", {\n detail: false,\n bubbles: true,\n }));\n }\n }\n }\n\n // --- Commands ---\n\n /** Re-resolve the target/root from the DOM and (re)start observing. */\n observe(): void {\n const { element, display } = this._resolveTarget();\n // `display` is derived from the `target` *mode* (self/selector/child), not from\n // whether the selector currently matches — so it is applied unconditionally,\n // before the resolution check. A `target=\"#x\"` whose node is momentarily absent\n // still renders `display:none` (it is a selector pointer, never a box).\n this.style.display = display;\n if (!element) {\n // The target is no longer resolvable (e.g. a `target` selector whose node\n // was removed from the DOM). Tear down any stale observation so `observing`\n // does not keep reporting true against a node that is gone.\n this._core.disconnect();\n return;\n }\n this._core.observe(element, this._options());\n }\n\n /**\n * Force a fresh observation: re-resolve target/root from the DOM and re-observe\n * even when nothing changed. Unlike observe() (idempotent for an unchanged\n * target+options), this rebuilds the observer so a new initial callback fires for\n * the current visibility — the way to re-arm an edge-driven consumer after the\n * layout shifted without a visibility transition (e.g. infinite scroll appended a\n * short page that left this sentinel in view). Resolution/teardown rules match\n * observe(): an unresolvable target tears down any stale observation.\n */\n reobserve(): void {\n const { element, display } = this._resolveTarget();\n this.style.display = display;\n if (!element) {\n this._core.disconnect();\n return;\n }\n this._core.reobserve(element, this._options());\n }\n\n unobserve(): void {\n // Single-target Shell: \"stop observing my target\" is exactly the Core's\n // teardown. Delegate to the Core's tracked state rather than re-resolving the\n // selector, so a target that has since left the DOM can still be stopped\n // (re-resolving would yield null and silently leave the observer running).\n this._core.disconnect();\n }\n\n disconnect(): void {\n this._core.disconnect();\n }\n\n reset(): void {\n this._core.reset();\n }\n\n // --- Internal ---\n\n private _resolveTarget(): { element: Element | null; display: string } {\n const target = this.target;\n if (target === \"self\") {\n // Explicit sentinel: observe the element itself as a (typically zero-height)\n // marker, which requires a layout box.\n return { element: this, display: \"block\" };\n }\n if (target !== \"\") {\n // Selector pointer: observe a referenced element in place, staying invisible.\n const scope = this.getRootNode() as Document | ShadowRoot;\n // A user-authored selector can be syntactically invalid (e.g. `#`, `:::`,\n // `[data-*`), which makes querySelector throw a SyntaxError. Swallow it and\n // treat the target as unresolvable — the same \"nothing to observe\" path as a\n // selector matching no element — so a bad attribute never lets the throw\n // escape observe() → connectedCallback / attributeChangedCallback (never-throw).\n return { element: this._safeQuery(scope, target), display: \"none\" };\n }\n // Omitted: observe the first element child without injecting a box of our own.\n const child = this.firstElementChild;\n if (child) {\n return { element: child, display: \"contents\" };\n }\n // No child to wrap (e.g. used as an empty marker) — fall back to self.\n return { element: this, display: \"block\" };\n }\n\n private _resolveRoot(): Element | null {\n const root = this.root;\n if (root === \"\") return null;\n const scope = this.getRootNode() as Document | ShadowRoot;\n // Same never-throw guard as the target selector: an invalid `root` selector\n // falls back to a null root (the viewport) rather than throwing out of observe().\n return this._safeQuery(scope, root);\n }\n\n // Wrap querySelector so a syntactically invalid user-authored selector resolves\n // to null (unresolvable) instead of letting the SyntaxError escape — keeping the\n // sensor never-throw, mirroring worker/src/autoTrigger.ts's resolveText guard.\n private _safeQuery(scope: Document | ShadowRoot, selector: string): Element | null {\n try {\n return scope.querySelector(selector);\n } catch {\n return null;\n }\n }\n\n private _parseThreshold(): number | number[] {\n const raw = this.threshold.trim();\n if (raw === \"\") return 0;\n // Strict parse via Number() (unlike parseFloat, \"0.5px\" -> NaN, not 0.5); drop\n // any non-finite or out-of-range [0,1] value, matching the README note.\n // Drop empty slots first (\"0,,1\" / \"1,\") — Number(\"\") is 0, which would\n // otherwise smuggle a spurious 0 threshold past the finite/range filter.\n const nums = raw\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s !== \"\")\n .map((s) => Number(s))\n .filter((n) => Number.isFinite(n) && n >= 0 && n <= 1);\n if (nums.length === 0) return 0;\n return nums.length === 1 ? nums[0] : nums;\n }\n\n private _options(): IntersectOptions {\n return {\n root: this._resolveRoot(),\n rootMargin: this.rootMargin,\n threshold: this._parseThreshold(),\n };\n }\n\n private _onChange = (event: Event): void => {\n // `wcs-intersect:change` bubbles, so a nested `<wcs-intersect>` descendant's\n // change would otherwise reach this (ancestor) listener and let a *child's*\n // intersection tear down *our* observer. Only act on our own Core's event.\n // (This also avoids reading `.detail` off a foreign event shape.)\n if (event.target !== this) return;\n // `once`: tear down after the first intersecting observation (lazy-load idiom).\n // Gated at fire time so toggling the `once` attribute takes effect live.\n if (this.once && (event as CustomEvent).detail.isIntersecting) {\n this._core.disconnect();\n }\n };\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this.addEventListener(\"wcs-intersect:change\", this._onChange);\n if (!this.manual) {\n this.observe();\n }\n }\n\n disconnectedCallback(): void {\n this.removeEventListener(\"wcs-intersect:change\", this._onChange);\n this._core.disconnect();\n }\n\n attributeChangedCallback(_name: string, oldValue: string | null, newValue: string | null): void {\n // Defensive same-value guard. Per spec attributeChangedCallback only fires on\n // an actual value change, so this is effectively a dead branch today — but\n // setAttribute() with an unchanged value (and some test/tooling paths) can\n // still invoke it, and re-observing on an unchanged attribute would be a\n // wasted observer rebuild. Kept intentionally; do not remove.\n if (oldValue === newValue) return;\n // Only react once connected and in automatic mode. The Core's idempotency\n // guard absorbs the autoloader upgrade case (attributeChangedCallback +\n // connectedCallback both calling observe() with identical options).\n if (!this.isConnected || this.manual) return;\n this.observe();\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapIntersection(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n","import { WcsIntersect } from \"./components/Intersect.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.intersect)) {\n customElements.define(config.tagNames.intersect, WcsIntersect);\n }\n}\n"],"names":["_config","tagNames","intersect","deepFreeze","obj","Object","freeze","key","keys","deepClone","clone","frozenConfig","config","getConfig","IntersectionCore","EventTarget","static","protocol","version","properties","name","event","getter","e","detail","isIntersecting","intersectionRatio","commands","_target","_observer","_observed","_options","_entry","_visible","_observing","constructor","target","super","this","entry","intersecting","ratio","visible","observing","_setEntry","dispatchEvent","CustomEvent","bubbles","_setVisible","_setObserving","observe","element","options","_optionsEqual","_teardownObserver","observer","_createObserver","reobserve","unobserve","disconnect","reset","IntersectionObserver","_onIntersect","root","rootMargin","threshold","entries","normalized","_normalizeEntry","time","boundingClientRect","_normalizeRect","intersectionRect","rootBounds","rect","x","y","width","height","top","right","bottom","left","a","b","_thresholdKey","undefined","Array","isArray","join","String","WcsIntersect","HTMLElement","wcBindable","inputs","attribute","_core","_trigger","getAttribute","value","setAttribute","attr","trim","once","hasAttribute","removeAttribute","manual","trigger","display","_resolveTarget","style","scope","getRootNode","_safeQuery","child","firstElementChild","_resolveRoot","selector","querySelector","_parseThreshold","raw","nums","split","map","s","filter","Number","n","isFinite","length","_onChange","connectedCallback","addEventListener","disconnectedCallback","removeEventListener","attributeChangedCallback","_name","oldValue","newValue","isConnected","bootstrapIntersection","userConfig","partialConfig","assign","customElements","get","define"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wcstack/intersection",
3
- "version": "1.12.0",
3
+ "version": "1.13.0",
4
4
  "description": "Declarative IntersectionObserver component for Web Components. Framework-agnostic visibility primitive via wc-bindable-protocol.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.esm.js",