@wcstack/intersection 1.12.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.
@@ -0,0 +1,570 @@
1
+ const _config = {
2
+ tagNames: {
3
+ intersect: "wcs-intersect",
4
+ },
5
+ };
6
+ function deepFreeze(obj) {
7
+ if (obj === null || typeof obj !== "object")
8
+ return obj;
9
+ Object.freeze(obj);
10
+ for (const key of Object.keys(obj)) {
11
+ deepFreeze(obj[key]);
12
+ }
13
+ return obj;
14
+ }
15
+ function deepClone(obj) {
16
+ if (obj === null || typeof obj !== "object")
17
+ return obj;
18
+ const clone = {};
19
+ for (const key of Object.keys(obj)) {
20
+ clone[key] = deepClone(obj[key]);
21
+ }
22
+ return clone;
23
+ }
24
+ let frozenConfig = null;
25
+ const config = _config;
26
+ function getConfig() {
27
+ if (!frozenConfig) {
28
+ frozenConfig = deepFreeze(deepClone(_config));
29
+ }
30
+ return frozenConfig;
31
+ }
32
+ function setConfig(partialConfig) {
33
+ if (partialConfig.tagNames) {
34
+ Object.assign(_config.tagNames, partialConfig.tagNames);
35
+ }
36
+ frozenConfig = null;
37
+ }
38
+
39
+ /**
40
+ * Headless visibility primitive. A thin, framework-agnostic wrapper around the
41
+ * IntersectionObserver API exposed through the wc-bindable protocol.
42
+ *
43
+ * Unlike the other @wcstack sensors (geolocation / timer / websocket), the thing
44
+ * being observed is a *DOM element* — so `observe()` takes the target node. The
45
+ * Core stays DOM-resolution-agnostic: it observes whatever element it is handed
46
+ * (the Shell resolves `target` / `root` selectors before calling). It is a
47
+ * read-only producer — element/layout → state only, with no element-bound path.
48
+ *
49
+ * Every observer callback is published via the single `wcs-intersect:change`
50
+ * event; `intersecting` / `ratio` are read from it through getters (mirroring how
51
+ * GeolocationCore exposes latitude/longitude from one `wcs-geo:position` event),
52
+ * so an observer that binds any of them is notified on every change.
53
+ *
54
+ * `visible` is a latch: it flips to `true` the first time the target intersects
55
+ * and stays `true` until `reset()` — ideal for one-way lazy-load bindings
56
+ * (`src@visible`). `observing` reflects whether an observation is currently
57
+ * active (like TimerCore's `running`).
58
+ *
59
+ * Single-target by design: the Shell observes exactly one element, so the state
60
+ * reflects that element. Multi-target observation is intentionally out of scope.
61
+ */
62
+ class IntersectionCore extends EventTarget {
63
+ static wcBindable = {
64
+ protocol: "wc-bindable",
65
+ version: 1,
66
+ properties: [
67
+ { name: "entry", event: "wcs-intersect:change" },
68
+ { name: "intersecting", event: "wcs-intersect:change", getter: (e) => e.detail.isIntersecting },
69
+ { name: "ratio", event: "wcs-intersect:change", getter: (e) => e.detail.intersectionRatio },
70
+ { name: "visible", event: "wcs-intersect:visible-changed" },
71
+ { name: "observing", event: "wcs-intersect:observing-changed" },
72
+ ],
73
+ commands: [
74
+ { name: "observe" },
75
+ { name: "unobserve" },
76
+ { name: "disconnect" },
77
+ { name: "reset" },
78
+ ],
79
+ };
80
+ _target;
81
+ // The live observer and the single element it observes. Options are kept so a
82
+ // repeated observe() with identical options is a no-op (avoids the create→
83
+ // observe→disconnect churn an autoloader upgrade can otherwise cause).
84
+ _observer = null;
85
+ _observed = null;
86
+ _options = {};
87
+ _entry = null;
88
+ _visible = false;
89
+ _observing = false;
90
+ constructor(target) {
91
+ super();
92
+ this._target = target ?? this;
93
+ }
94
+ get entry() {
95
+ return this._entry;
96
+ }
97
+ get intersecting() {
98
+ return this._entry ? this._entry.isIntersecting : false;
99
+ }
100
+ get ratio() {
101
+ return this._entry ? this._entry.intersectionRatio : 0;
102
+ }
103
+ get visible() {
104
+ return this._visible;
105
+ }
106
+ get observing() {
107
+ return this._observing;
108
+ }
109
+ // --- State setters with event dispatch ---
110
+ _setEntry(entry) {
111
+ // No same-value guard: `change` carries event semantics (every callback is a
112
+ // distinct observation) and `intersecting` / `ratio` are derived getters that
113
+ // must re-fire on each entry, mirroring GeolocationCore's `position`.
114
+ this._entry = entry;
115
+ this._target.dispatchEvent(new CustomEvent("wcs-intersect:change", {
116
+ detail: entry,
117
+ bubbles: true,
118
+ }));
119
+ }
120
+ _setVisible(visible) {
121
+ if (this._visible === visible)
122
+ return;
123
+ this._visible = visible;
124
+ this._target.dispatchEvent(new CustomEvent("wcs-intersect:visible-changed", {
125
+ detail: visible,
126
+ bubbles: true,
127
+ }));
128
+ }
129
+ _setObserving(observing) {
130
+ if (this._observing === observing)
131
+ return;
132
+ this._observing = observing;
133
+ this._target.dispatchEvent(new CustomEvent("wcs-intersect:observing-changed", {
134
+ detail: observing,
135
+ bubbles: true,
136
+ }));
137
+ }
138
+ // --- Public API ---
139
+ /**
140
+ * Start observing `element`. Idempotent while already observing the same
141
+ * element with the same options. Changing the element or options tears down the
142
+ * current observer and builds a new one (IntersectionObserver options are fixed
143
+ * at construction, so reconfiguring requires a fresh observer).
144
+ *
145
+ * If IntersectionObserver is unavailable (SSR) or the options are invalid (e.g.
146
+ * a malformed `rootMargin`, which the constructor rejects), this is a silent
147
+ * no-op — `observing` stays false, consistent with the never-throw design of
148
+ * the other @wcstack sensors.
149
+ */
150
+ observe(element, options = {}) {
151
+ if (this._observer && this._observed === element && this._optionsEqual(this._options, options)) {
152
+ return;
153
+ }
154
+ this._teardownObserver();
155
+ const observer = this._createObserver(options);
156
+ if (!observer) {
157
+ // Creation failed (unsupported environment or invalid options) *after* we
158
+ // tore down any previous observer. If we were already observing, the
159
+ // observation is now gone, so reflect that — otherwise `observing` would
160
+ // keep reporting true with no live observer behind it (e.g. re-observing an
161
+ // active target with a newly-invalid rootMargin).
162
+ this._setObserving(false);
163
+ return;
164
+ }
165
+ this._observer = observer;
166
+ this._observed = element;
167
+ this._options = options;
168
+ observer.observe(element);
169
+ this._setObserving(true);
170
+ }
171
+ /**
172
+ * Stop observing `element`. A no-op if it is not the currently observed
173
+ * element. The observer instance is torn down (single-target Core), so a later
174
+ * observe() rebuilds it.
175
+ */
176
+ unobserve(element) {
177
+ if (this._observed !== element)
178
+ return;
179
+ this._teardownObserver();
180
+ this._setObserving(false);
181
+ }
182
+ /** Stop all observation and release the observer. */
183
+ disconnect() {
184
+ this._teardownObserver();
185
+ this._setObserving(false);
186
+ }
187
+ /** Clear the `visible` latch so a later intersection can set it again. */
188
+ reset() {
189
+ this._setVisible(false);
190
+ }
191
+ // --- Internal ---
192
+ _teardownObserver() {
193
+ if (this._observer) {
194
+ this._observer.disconnect();
195
+ this._observer = null;
196
+ }
197
+ this._observed = null;
198
+ }
199
+ _createObserver(options) {
200
+ if (typeof IntersectionObserver === "undefined")
201
+ return null;
202
+ try {
203
+ return new IntersectionObserver(this._onIntersect, {
204
+ root: options.root ?? null,
205
+ rootMargin: options.rootMargin ?? "0px",
206
+ threshold: options.threshold ?? 0,
207
+ });
208
+ }
209
+ catch {
210
+ // Invalid options (e.g. a malformed rootMargin) — surface nothing and leave
211
+ // observing false, rather than letting the constructor throw escape.
212
+ return null;
213
+ }
214
+ }
215
+ _onIntersect = (entries) => {
216
+ for (const entry of entries) {
217
+ const normalized = this._normalizeEntry(entry);
218
+ this._setEntry(normalized);
219
+ // Latch on the first (and any) intersecting observation; never auto-clears.
220
+ if (normalized.isIntersecting) {
221
+ this._setVisible(true);
222
+ }
223
+ }
224
+ };
225
+ _normalizeEntry(entry) {
226
+ return {
227
+ isIntersecting: entry.isIntersecting,
228
+ intersectionRatio: entry.intersectionRatio,
229
+ time: entry.time,
230
+ boundingClientRect: this._normalizeRect(entry.boundingClientRect),
231
+ intersectionRect: this._normalizeRect(entry.intersectionRect),
232
+ rootBounds: entry.rootBounds ? this._normalizeRect(entry.rootBounds) : null,
233
+ target: entry.target,
234
+ };
235
+ }
236
+ _normalizeRect(rect) {
237
+ return {
238
+ x: rect.x,
239
+ y: rect.y,
240
+ width: rect.width,
241
+ height: rect.height,
242
+ top: rect.top,
243
+ right: rect.right,
244
+ bottom: rect.bottom,
245
+ left: rect.left,
246
+ };
247
+ }
248
+ _optionsEqual(a, b) {
249
+ if ((a.root ?? null) !== (b.root ?? null))
250
+ return false;
251
+ if ((a.rootMargin ?? "0px") !== (b.rootMargin ?? "0px"))
252
+ return false;
253
+ return this._thresholdKey(a.threshold) === this._thresholdKey(b.threshold);
254
+ }
255
+ _thresholdKey(threshold) {
256
+ if (threshold === undefined)
257
+ return "0";
258
+ return Array.isArray(threshold) ? threshold.join(",") : String(threshold);
259
+ }
260
+ }
261
+
262
+ /**
263
+ * `<wcs-intersect>` — declarative IntersectionObserver.
264
+ *
265
+ * The `target` attribute is the single knob that decides both *what* is observed
266
+ * and how the element renders (it never injects a layout box unless asked):
267
+ *
268
+ * | `target` | observes | display | use case |
269
+ * |-----------------|-----------------------|-------------|-------------------|
270
+ * | omitted | first element child | `contents` | lazy-load wrapper |
271
+ * | `"#hero"` / sel | the matched element | `none` | scrollspy (single)|
272
+ * | `"self"` | the element itself | `block` | infinite-scroll |
273
+ *
274
+ * `display:contents` means wrapping a child injects no box of its own (so a
275
+ * `<wcs-intersect><img></wcs-intersect>` does not disturb a flex/grid parent);
276
+ * only the explicit `target="self"` sentinel takes a box.
277
+ */
278
+ class WcsIntersect extends HTMLElement {
279
+ static hasConnectedCallbackPromise = false;
280
+ // Only attributes that change *what or how* we observe trigger a re-observe.
281
+ // `once` is intentionally excluded: it is evaluated at intersection fire time
282
+ // (in `_onChange`), so toggling it takes effect without re-observing — and a
283
+ // re-observe on its change would be a pure no-op (same target, same options).
284
+ // `manual` is also excluded: it is a connect-time policy ("don't auto-observe
285
+ // on connect"), not a live switch that should start/stop an active observation.
286
+ static observedAttributes = ["target", "root", "root-margin", "threshold"];
287
+ static wcBindable = {
288
+ ...IntersectionCore.wcBindable,
289
+ properties: [
290
+ ...IntersectionCore.wcBindable.properties,
291
+ { name: "trigger", event: "wcs-intersect:trigger-changed" },
292
+ ],
293
+ // Shell-level settable surface. Each input carries its mirrored `attribute`
294
+ // 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.
297
+ inputs: [
298
+ { name: "target", attribute: "target" },
299
+ { name: "root", attribute: "root" },
300
+ { name: "rootMargin", attribute: "root-margin" },
301
+ { name: "threshold", attribute: "threshold" },
302
+ { name: "once", attribute: "once" },
303
+ { name: "manual", attribute: "manual" },
304
+ { name: "trigger" },
305
+ ],
306
+ // Core の commands をそのまま継承(単一情報源)。<wcs-sse>/<wcs-broadcast> と同型。
307
+ // spread でも継承されるが、Core に command 追加時の追従漏れを防ぐため明示参照する。
308
+ commands: IntersectionCore.wcBindable.commands,
309
+ };
310
+ _core;
311
+ _trigger = false;
312
+ constructor() {
313
+ super();
314
+ this._core = new IntersectionCore(this);
315
+ }
316
+ // --- Attribute accessors ---
317
+ get target() {
318
+ return this.getAttribute("target") ?? "";
319
+ }
320
+ set target(value) {
321
+ this.setAttribute("target", value);
322
+ }
323
+ get root() {
324
+ return this.getAttribute("root") ?? "";
325
+ }
326
+ set root(value) {
327
+ this.setAttribute("root", value);
328
+ }
329
+ get rootMargin() {
330
+ const attr = this.getAttribute("root-margin");
331
+ return attr === null || attr.trim() === "" ? "0px" : attr;
332
+ }
333
+ set rootMargin(value) {
334
+ this.setAttribute("root-margin", value);
335
+ }
336
+ get threshold() {
337
+ return this.getAttribute("threshold") ?? "";
338
+ }
339
+ set threshold(value) {
340
+ this.setAttribute("threshold", value);
341
+ }
342
+ get once() {
343
+ return this.hasAttribute("once");
344
+ }
345
+ set once(value) {
346
+ if (value) {
347
+ this.setAttribute("once", "");
348
+ }
349
+ else {
350
+ this.removeAttribute("once");
351
+ }
352
+ }
353
+ get manual() {
354
+ return this.hasAttribute("manual");
355
+ }
356
+ set manual(value) {
357
+ if (value) {
358
+ this.setAttribute("manual", "");
359
+ }
360
+ else {
361
+ this.removeAttribute("manual");
362
+ }
363
+ }
364
+ // --- Core delegated getters ---
365
+ get entry() {
366
+ return this._core.entry;
367
+ }
368
+ get intersecting() {
369
+ return this._core.intersecting;
370
+ }
371
+ get ratio() {
372
+ return this._core.ratio;
373
+ }
374
+ get visible() {
375
+ return this._core.visible;
376
+ }
377
+ get observing() {
378
+ return this._core.observing;
379
+ }
380
+ // --- Command property ---
381
+ get trigger() {
382
+ return this._trigger;
383
+ }
384
+ set trigger(value) {
385
+ // Momentary command-property: a false→true write re-runs observe(). Mirrors
386
+ // the trigger flag on <wcs-geo> / <wcs-ws> / <wcs-sse>. Prefer the command-token
387
+ // protocol (`command.observe: $command.start`) for state-driven observation;
388
+ // this exists mainly for simple boolean bindings.
389
+ const v = !!value; // normalize truthy state-bindings, like <wcs-sse>'s setter
390
+ if (v) {
391
+ this._trigger = true;
392
+ // try/finally mirrors <wcs-sse>'s set trigger: observe() is never-throw
393
+ // today, but should a synchronous throw path ever appear, the finally still
394
+ // auto-resets _trigger (no stuck-true latch) and emits the completion notice.
395
+ try {
396
+ this.observe();
397
+ }
398
+ finally {
399
+ this._trigger = false;
400
+ // Always auto-reset to false after the observe() attempt — this is the
401
+ // *momentary acknowledgement* that the trigger was consumed, NOT a signal
402
+ // that observation succeeded (whether the target resolved is reflected by
403
+ // `observing`, not by this event). Firing unconditionally keeps the bound
404
+ // state's trigger flag from sticking at true regardless of resolution.
405
+ // Read `observing` if you need the actual outcome.
406
+ this.dispatchEvent(new CustomEvent("wcs-intersect:trigger-changed", {
407
+ detail: false,
408
+ bubbles: true,
409
+ }));
410
+ }
411
+ }
412
+ }
413
+ // --- Commands ---
414
+ /** Re-resolve the target/root from the DOM and (re)start observing. */
415
+ observe() {
416
+ const { element, display } = this._resolveTarget();
417
+ // `display` is derived from the `target` *mode* (self/selector/child), not from
418
+ // whether the selector currently matches — so it is applied unconditionally,
419
+ // before the resolution check. A `target="#x"` whose node is momentarily absent
420
+ // still renders `display:none` (it is a selector pointer, never a box).
421
+ this.style.display = display;
422
+ if (!element) {
423
+ // The target is no longer resolvable (e.g. a `target` selector whose node
424
+ // was removed from the DOM). Tear down any stale observation so `observing`
425
+ // does not keep reporting true against a node that is gone.
426
+ this._core.disconnect();
427
+ return;
428
+ }
429
+ this._core.observe(element, this._options());
430
+ }
431
+ unobserve() {
432
+ // Single-target Shell: "stop observing my target" is exactly the Core's
433
+ // teardown. Delegate to the Core's tracked state rather than re-resolving the
434
+ // selector, so a target that has since left the DOM can still be stopped
435
+ // (re-resolving would yield null and silently leave the observer running).
436
+ this._core.disconnect();
437
+ }
438
+ disconnect() {
439
+ this._core.disconnect();
440
+ }
441
+ reset() {
442
+ this._core.reset();
443
+ }
444
+ // --- Internal ---
445
+ _resolveTarget() {
446
+ const target = this.target;
447
+ if (target === "self") {
448
+ // Explicit sentinel: observe the element itself as a (typically zero-height)
449
+ // marker, which requires a layout box.
450
+ return { element: this, display: "block" };
451
+ }
452
+ if (target !== "") {
453
+ // Selector pointer: observe a referenced element in place, staying invisible.
454
+ const scope = this.getRootNode();
455
+ // A user-authored selector can be syntactically invalid (e.g. `#`, `:::`,
456
+ // `[data-*`), which makes querySelector throw a SyntaxError. Swallow it and
457
+ // treat the target as unresolvable — the same "nothing to observe" path as a
458
+ // selector matching no element — so a bad attribute never lets the throw
459
+ // escape observe() → connectedCallback / attributeChangedCallback (never-throw).
460
+ return { element: this._safeQuery(scope, target), display: "none" };
461
+ }
462
+ // Omitted: observe the first element child without injecting a box of our own.
463
+ const child = this.firstElementChild;
464
+ if (child) {
465
+ return { element: child, display: "contents" };
466
+ }
467
+ // No child to wrap (e.g. used as an empty marker) — fall back to self.
468
+ return { element: this, display: "block" };
469
+ }
470
+ _resolveRoot() {
471
+ const root = this.root;
472
+ if (root === "")
473
+ return null;
474
+ const scope = this.getRootNode();
475
+ // Same never-throw guard as the target selector: an invalid `root` selector
476
+ // falls back to a null root (the viewport) rather than throwing out of observe().
477
+ return this._safeQuery(scope, root);
478
+ }
479
+ // Wrap querySelector so a syntactically invalid user-authored selector resolves
480
+ // to null (unresolvable) instead of letting the SyntaxError escape — keeping the
481
+ // sensor never-throw, mirroring worker/src/autoTrigger.ts's resolveText guard.
482
+ _safeQuery(scope, selector) {
483
+ try {
484
+ return scope.querySelector(selector);
485
+ }
486
+ catch {
487
+ return null;
488
+ }
489
+ }
490
+ _parseThreshold() {
491
+ const raw = this.threshold.trim();
492
+ if (raw === "")
493
+ return 0;
494
+ // Strict parse via Number() (unlike parseFloat, "0.5px" -> NaN, not 0.5); drop
495
+ // any non-finite or out-of-range [0,1] value, matching the README note.
496
+ // Drop empty slots first ("0,,1" / "1,") — Number("") is 0, which would
497
+ // otherwise smuggle a spurious 0 threshold past the finite/range filter.
498
+ const nums = raw
499
+ .split(",")
500
+ .map((s) => s.trim())
501
+ .filter((s) => s !== "")
502
+ .map((s) => Number(s))
503
+ .filter((n) => Number.isFinite(n) && n >= 0 && n <= 1);
504
+ if (nums.length === 0)
505
+ return 0;
506
+ return nums.length === 1 ? nums[0] : nums;
507
+ }
508
+ _options() {
509
+ return {
510
+ root: this._resolveRoot(),
511
+ rootMargin: this.rootMargin,
512
+ threshold: this._parseThreshold(),
513
+ };
514
+ }
515
+ _onChange = (event) => {
516
+ // `wcs-intersect:change` bubbles, so a nested `<wcs-intersect>` descendant's
517
+ // change would otherwise reach this (ancestor) listener and let a *child's*
518
+ // intersection tear down *our* observer. Only act on our own Core's event.
519
+ // (This also avoids reading `.detail` off a foreign event shape.)
520
+ if (event.target !== this)
521
+ return;
522
+ // `once`: tear down after the first intersecting observation (lazy-load idiom).
523
+ // Gated at fire time so toggling the `once` attribute takes effect live.
524
+ if (this.once && event.detail.isIntersecting) {
525
+ this._core.disconnect();
526
+ }
527
+ };
528
+ // --- Lifecycle ---
529
+ connectedCallback() {
530
+ this.addEventListener("wcs-intersect:change", this._onChange);
531
+ if (!this.manual) {
532
+ this.observe();
533
+ }
534
+ }
535
+ disconnectedCallback() {
536
+ this.removeEventListener("wcs-intersect:change", this._onChange);
537
+ this._core.disconnect();
538
+ }
539
+ attributeChangedCallback(_name, oldValue, newValue) {
540
+ // Defensive same-value guard. Per spec attributeChangedCallback only fires on
541
+ // an actual value change, so this is effectively a dead branch today — but
542
+ // setAttribute() with an unchanged value (and some test/tooling paths) can
543
+ // still invoke it, and re-observing on an unchanged attribute would be a
544
+ // wasted observer rebuild. Kept intentionally; do not remove.
545
+ if (oldValue === newValue)
546
+ return;
547
+ // Only react once connected and in automatic mode. The Core's idempotency
548
+ // guard absorbs the autoloader upgrade case (attributeChangedCallback +
549
+ // connectedCallback both calling observe() with identical options).
550
+ if (!this.isConnected || this.manual)
551
+ return;
552
+ this.observe();
553
+ }
554
+ }
555
+
556
+ function registerComponents() {
557
+ if (!customElements.get(config.tagNames.intersect)) {
558
+ customElements.define(config.tagNames.intersect, WcsIntersect);
559
+ }
560
+ }
561
+
562
+ function bootstrapIntersection(userConfig) {
563
+ if (userConfig) {
564
+ setConfig(userConfig);
565
+ }
566
+ registerComponents();
567
+ }
568
+
569
+ export { IntersectionCore, WcsIntersect, bootstrapIntersection, getConfig };
570
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +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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"}
@@ -0,0 +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};
2
+ //# sourceMappingURL=index.esm.min.js.map