@wcstack/intersection 1.25.0 → 1.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/auto.min.js CHANGED
@@ -1 +1,2 @@
1
- import{bootstrapIntersection as o}from"./index.esm.min.js";o();
1
+ const t={tagNames:{intersect:"wcs-intersect"}};class e extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"entry",event:"wcs-intersect:change",semantics:"state"},{name:"intersecting",event:"wcs-intersect:change",semantics:"state",getter:t=>t.detail.isIntersecting},{name:"ratio",event:"wcs-intersect:change",semantics:"state",getter:t=>t.detail.intersectionRatio},{name:"visible",event:"wcs-intersect:visible-changed",semantics:"state"},{name:"observing",event:"wcs-intersect:observing-changed",semantics:"state"}],commands:[{name:"observe"},{name:"reobserve"},{name:"unobserve"},{name:"disconnect"},{name:"reset"}]};_target;_observer=null;_observed=null;_options={};_entry=null;_visible=!1;_observing=!1;_gen=0;_ready=Promise.resolve();constructor(t){super(),this._target=t??this}get ready(){return this._ready}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._ready;this._teardownObserver();const s=this._createObserver(e);return s?(this._observer=s,this._observed=t,this._options=e,s.observe(t),this._setObserving(!0),this._ready):(this._setObserving(!1),this._ready)}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)}dispose(){this._gen++,this.disconnect()}_teardownObserver(){this._observer&&(this._observer.disconnect(),this._observer=null),this._observed=null,this._gen++}_createObserver(t){if("undefined"==typeof IntersectionObserver)return null;const e=this._gen;try{return new IntersectionObserver(t=>this._onIntersect(e,t),{root:t.root??null,rootMargin:t.rootMargin??"0px",threshold:t.threshold??0})}catch{return null}}_onIntersect(t,e){if(t===this._gen)for(const t of e){const e=this._normalizeEntry(t);this._setEntry(e),e.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)}}function s(t,e){let s=Object.getPrototypeOf(t);for(;null!==s;){const t=Object.getOwnPropertyDescriptor(s,e);if(void 0!==t)return"function"==typeof t.get||"function"==typeof t.set;s=Object.getPrototypeOf(s)}return!1}class r extends HTMLElement{static hasConnectedCallbackPromise=!0;static observedAttributes=["target","root","root-margin","threshold"];static wcBindable={...e.wcBindable,properties:[...e.wcBindable.properties,{name:"trigger",event:"wcs-intersect:trigger-changed",semantics:"state"}],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:e.wcBindable.commands};_core;_trigger=!1;_connectedCallbackPromise=Promise.resolve();_internals=null;constructor(){super(),this._core=new e(this),this._internals=this._initInternals(),this._wireStates({"wcs-intersect:visible-changed":t=>({visible:!0===t}),"wcs-intersect:observing-changed":t=>({observing:!0===t}),"wcs-intersect:change":t=>({intersecting:!0===t.isIntersecting})})}get debugStates(){return this._internals?[...this._internals.states]:[]}_initInternals(){try{if("function"!=typeof this.attachInternals)return null;const t=this.attachInternals();return t.states.add("wcs-probe"),t.states.delete("wcs-probe"),t}catch{return null}}_wireStates(t){if(null===this._internals)return;const e=this._internals.states;for(const[s,r]of Object.entries(t))this.addEventListener(s,t=>{const s=this.hasAttribute("debug-states");for(const[i,n]of Object.entries(r(t.detail))){try{n?e.add(i):e.delete(i)}catch{}s&&this.toggleAttribute(`data-wcs-state-${i}`,n)}})}get connectedCallbackPromise(){return this._connectedCallbackPromise}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(){!function(t){const e=t.constructor?.wcBindable,r=e?.inputs;if(void 0!==r)for(const e of r){const r=e.name;if(!Object.prototype.hasOwnProperty.call(t,r))continue;if(!s(t,r))continue;const i=t,n=i[r];delete i[r],i[r]=n}}(this),this.addEventListener("wcs-intersect:change",this._onChange),this.manual||this.observe(),this._connectedCallbackPromise=this._core.ready}disconnectedCallback(){this.removeEventListener("wcs-intersect:change",this._onChange),this._core.dispose()}attributeChangedCallback(t,e,s){e!==s&&this.isConnected&&!this.manual&&this.observe()}}customElements.get(t.tagNames.intersect)||customElements.define(t.tagNames.intersect,r);
2
+ //# sourceMappingURL=auto.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto.min.js","sources":["../src/config.ts","../src/core/IntersectionCore.ts","../src/protocol/upgradeProperties.ts","../src/components/Intersect.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\", semantics: \"state\" },\n { name: \"intersecting\", event: \"wcs-intersect:change\", semantics: \"state\", getter: (e: Event) => (e as CustomEvent).detail.isIntersecting },\n { name: \"ratio\", event: \"wcs-intersect:change\", semantics: \"state\", getter: (e: Event) => (e as CustomEvent).detail.intersectionRatio },\n { name: \"visible\", event: \"wcs-intersect:visible-changed\", semantics: \"state\" },\n { name: \"observing\", event: \"wcs-intersect:observing-changed\", semantics: \"state\" },\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 // Generation guard (§3.4): bumped on dispose() and on each observe()/reobserve()\n // teardown+rebuild. IntersectionObserver delivers its callback asynchronously off\n // layout, so a callback can fire after the element is disposed or after a rapid\n // disconnect→reconnect rebuilt the observer. Each observer captures the gen live at\n // creation; a callback from a superseded/torn-down observer has a stale gen and\n // MUST NOT write state to a torn-down element. A boolean flag is insufficient\n // (dispose→observe would flip it back and let stale work slip through).\n private _gen = 0;\n\n // SSR (§3.8): IntersectionObserver setup is synchronous (no async probe to await),\n // so readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n /** Resolves immediately — there is no asynchronous probe to await (§3.8). */\n get ready(): Promise<void> {\n return this._ready;\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 = {}): Promise<void> {\n if (this._observer && this._observed === element && this._optionsEqual(this._options, options)) {\n return this._ready;\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 this._ready;\n }\n this._observer = observer;\n this._observed = element;\n this._options = options;\n observer.observe(element);\n this._setObserving(true);\n // SSR (§3.5): observe() returns the readiness promise. Observation establishment\n // is synchronous, so this resolves immediately.\n return this._ready;\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 // --- Lifecycle (§3.5) ---\n\n /**\n * `observe()` (the IntersectionObserver-style command above) establishes\n * monitoring, so there is no separate idempotent monitoring entry point — only\n * teardown. `dispose()` invalidates any in-flight observer callback (`_gen++`)\n * and releases the observer. A later observe() revives it (the Shell calls this\n * from `disconnectedCallback`).\n */\n dispose(): void {\n this._gen++;\n this.disconnect();\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 // Invalidate the torn-down observer's generation: its callback can still fire\n // once asynchronously after disconnect(), and must be dropped (§3.4).\n this._gen++;\n }\n\n private _createObserver(options: IntersectOptions): IntersectionObserver | null {\n if (typeof IntersectionObserver === \"undefined\") return null;\n // Capture the generation live at creation. The callback closure below guards\n // against deliveries from this observer after it has been superseded or\n // disposed (a stale callback fired off layout after teardown).\n const gen = this._gen;\n try {\n return new IntersectionObserver(\n (entries) => this._onIntersect(gen, entries),\n {\n root: options.root ?? null,\n rootMargin: options.rootMargin ?? \"0px\",\n threshold: options.threshold ?? 0,\n },\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(gen: number, entries: IntersectionObserverEntry[]): void {\n // Stale-generation guard (§3.4): drop callbacks from an observer that was torn\n // down or disposed (e.g. a delivery that landed after disconnect/reconnect).\n if (gen !== this._gen) return;\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","// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /protocol/upgrade-properties.ts by scripts/sync-protocol-types.mjs.\n// Run `node scripts/sync-protocol-types.mjs` after editing the source.\n// ===========================================================================\n\n// custom element の property upgrade — `static wcBindable.inputs` に宣言した入力のうち、\n// 要素が upgrade される前に代入された own データプロパティを取り込み直す。\n//\n// なぜ必要か:\n// 未定義タグの要素は素の HTMLElement なので、`el.url = \"...\"` は own データプロパティを作る。\n// upgrade 後にクラスの accessor が prototype へ入っても own プロパティが優先されるため、\n// setter は二度と呼ばれず、値は要素へ届かないまま消える(エラーも警告も出ない)。\n// 常にプロパティ代入を行う framework(Angular の `[prop]`、Lit の `.prop=`、\n// Solid の `prop:`、Vue の `.prop` 修飾子)× 遅延定義(autoloader / CDN / code-split)で\n// 常態的に起きる。docs/architecture-hardening/13-framework-adapter-binding-constraints.md §1.2。\n//\n// 安全側の判定:\n// own プロパティがあっても、prototype チェーンに accessor が無ければ「シャドウ」ではなく\n// その own プロパティ自体が正規の格納先なので触らない(public class field を壊さない)。\n//\n// SINGLE SOURCE OF TRUTH: edit only this file (/protocol/upgrade-properties.ts), then run\n// `node scripts/sync-protocol-types.mjs` to regenerate the per-package copies\n// (packages/<pkg>/src/protocol/upgradeProperties.ts). Those copies are generated — do not edit them.\nimport { IWcBindable } from \"./wcBindable.js\";\n\nfunction hasAccessorOnPrototype(target: object, name: string): boolean {\n let proto = Object.getPrototypeOf(target);\n while (proto !== null) {\n const descriptor = Object.getOwnPropertyDescriptor(proto, name);\n if (descriptor !== undefined) {\n return typeof descriptor.get === \"function\" || typeof descriptor.set === \"function\";\n }\n proto = Object.getPrototypeOf(proto);\n }\n return false;\n}\n\n/**\n * `connectedCallback` の先頭で呼ぶ。宣言済み input のうち upgrade 前の代入で\n * accessor をシャドウしている own プロパティを、delete → 再代入で setter に通し直す。\n *\n * - 冪等: 再代入は accessor を通るので own プロパティは残らず、2 回目以降は no-op。\n * - 宣言に `inputs` が無い要素、`wcBindable` を持たない要素では何もしない。\n * - 値の意味は変えない。今まで捨てられていた代入が届くようになる一方向の変化。\n */\nexport function upgradeProperties(element: object): void {\n const declaration = (element as { constructor?: { wcBindable?: IWcBindable } }).constructor?.wcBindable;\n const inputs = declaration?.inputs;\n if (inputs === undefined) return;\n for (const input of inputs) {\n const name = input.name;\n if (!Object.prototype.hasOwnProperty.call(element, name)) continue;\n if (!hasAccessorOnPrototype(element, name)) continue;\n const record = element as Record<string, unknown>;\n const value = record[name];\n delete record[name];\n record[name] = value;\n }\n}\n","import { IWcBindable, IntersectOptions, WcsIntersectEntry } from \"../types.js\";\nimport { IntersectionCore } from \"../core/IntersectionCore.js\";\nimport { upgradeProperties } from \"../protocol/upgradeProperties.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 // SSR (§4.4): the first observation is established synchronously on connect, but\n // the Shell still exposes connectedCallbackPromise so the state binder can await\n // it uniformly across all IO nodes before snapshotting.\n static hasConnectedCallbackPromise = true;\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\", semantics: \"state\" },\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 private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new IntersectionCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n \"wcs-intersect:visible-changed\": (d) => ({ visible: d === true }),\n \"wcs-intersect:observing-changed\": (d) => ({ observing: d === true }),\n \"wcs-intersect:change\": (d) => ({ intersecting: d.isIntersecting === true }),\n });\n }\n\n // CSS state reflection (:state()) — debug-only snapshot getter. NOT part of\n // wc-bindable (not a bind target); see README \"CSS styling with :state()\".\n // MUST NOT return the live CustomStateSet (that would let callers write\n // states from outside, defeating the point of :state() being read-only).\n get debugStates(): string[] {\n return this._internals ? [...this._internals.states] : [];\n }\n\n private _initInternals(): ElementInternals | null {\n // never-throw (async-io-node-guidelines.md §3.6): attachInternals is absent\n // in happy-dom / older environments, and pre-125 Chromium rejects\n // non-dashed state names from states.add() (probed and discarded here).\n // Either case silently disables reflection — the component still works,\n // it just doesn't expose :state() selectors.\n try {\n if (typeof this.attachInternals !== \"function\") return null;\n const internals = this.attachInternals();\n internals.states.add(\"wcs-probe\");\n internals.states.delete(\"wcs-probe\");\n return internals;\n } catch {\n return null;\n }\n }\n\n private _wireStates(map: Record<string, (detail: any) => Record<string, boolean>>): void {\n if (this._internals === null) return;\n const states = this._internals.states;\n for (const [event, toStates] of Object.entries(map)) {\n this.addEventListener(event, (e) => {\n const debug = this.hasAttribute(\"debug-states\");\n for (const [name, on] of Object.entries(toStates((e as CustomEvent).detail))) {\n try {\n if (on) { states.add(name); } else { states.delete(name); }\n } catch { /* never-throw */ }\n if (debug) this.toggleAttribute(`data-wcs-state-${name}`, on);\n }\n });\n }\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Attribute accessors ---\n\n get target(): string {\n return this.getAttribute(\"target\") ?? \"\";\n }\n\n set target(value: string) {\n this.setAttribute(\"target\", value);\n }\n\n 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 // upgrade 前に代入された input を取り込み直す(doc 13 §1.2 / Phase A1)\n upgradeProperties(this);\n this.addEventListener(\"wcs-intersect:change\", this._onChange);\n if (!this.manual) {\n this.observe();\n }\n // SSR (§4.4): readiness is synchronous (observation is established above), but\n // expose the Core's ready promise as connectedCallbackPromise so the state\n // binder can await it uniformly. `manual` defers observation but readiness is\n // still immediate.\n this._connectedCallbackPromise = this._core.ready;\n }\n\n disconnectedCallback(): void {\n this.removeEventListener(\"wcs-intersect:change\", this._onChange);\n // dispose() tears down the observer AND bumps the Core's generation so any\n // IntersectionObserver callback still in flight is dropped (§3.4 / §4.1).\n this._core.dispose();\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"],"names":["config","tagNames","intersect","IntersectionCore","EventTarget","static","protocol","version","properties","name","event","semantics","getter","e","detail","isIntersecting","intersectionRatio","commands","_target","_observer","_observed","_options","_entry","_visible","_observing","_gen","_ready","Promise","resolve","constructor","target","super","this","ready","entry","intersecting","ratio","visible","observing","_setEntry","dispatchEvent","CustomEvent","bubbles","_setVisible","_setObserving","observe","element","options","_optionsEqual","_teardownObserver","observer","_createObserver","reobserve","unobserve","disconnect","reset","dispose","IntersectionObserver","gen","entries","_onIntersect","root","rootMargin","threshold","normalized","_normalizeEntry","time","boundingClientRect","_normalizeRect","intersectionRect","rootBounds","rect","x","y","width","height","top","right","bottom","left","a","b","_thresholdKey","undefined","Array","isArray","join","String","hasAccessorOnPrototype","proto","Object","getPrototypeOf","descriptor","getOwnPropertyDescriptor","get","set","WcsIntersect","HTMLElement","wcBindable","inputs","attribute","_core","_trigger","_connectedCallbackPromise","_internals","_initInternals","_wireStates","d","debugStates","states","attachInternals","internals","add","delete","map","toStates","addEventListener","debug","hasAttribute","on","toggleAttribute","connectedCallbackPromise","getAttribute","value","setAttribute","attr","trim","once","removeAttribute","manual","trigger","display","_resolveTarget","style","scope","getRootNode","_safeQuery","child","firstElementChild","_resolveRoot","selector","querySelector","_parseThreshold","raw","nums","split","s","filter","Number","n","isFinite","length","_onChange","connectedCallback","declaration","input","prototype","hasOwnProperty","call","record","upgradeProperties","disconnectedCallback","removeEventListener","attributeChangedCallback","_name","oldValue","newValue","isConnected","customElements","define"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wcstack/intersection",
3
- "version": "1.25.0",
3
+ "version": "1.26.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",
package/dist/auto.js DELETED
@@ -1,3 +0,0 @@
1
- import { bootstrapIntersection } from "./index.esm.js";
2
-
3
- bootstrapIntersection();
@@ -1,2 +0,0 @@
1
- const t={tagNames:{intersect:"wcs-intersect"}};function e(t){if(null===t||"object"!=typeof t)return t;Object.freeze(t);for(const s of Object.keys(t))e(t[s]);return t}function s(t){if(null===t||"object"!=typeof t)return t;const e={};for(const r of Object.keys(t))e[r]=s(t[r]);return e}let r=null;const n=t;function i(){return r||(r=e(s(t))),r}class o extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"entry",event:"wcs-intersect:change",semantics:"state"},{name:"intersecting",event:"wcs-intersect:change",semantics:"state",getter:t=>t.detail.isIntersecting},{name:"ratio",event:"wcs-intersect:change",semantics:"state",getter:t=>t.detail.intersectionRatio},{name:"visible",event:"wcs-intersect:visible-changed",semantics:"state"},{name:"observing",event:"wcs-intersect:observing-changed",semantics:"state"}],commands:[{name:"observe"},{name:"reobserve"},{name:"unobserve"},{name:"disconnect"},{name:"reset"}]};_target;_observer=null;_observed=null;_options={};_entry=null;_visible=!1;_observing=!1;_gen=0;_ready=Promise.resolve();constructor(t){super(),this._target=t??this}get ready(){return this._ready}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._ready;this._teardownObserver();const s=this._createObserver(e);return s?(this._observer=s,this._observed=t,this._options=e,s.observe(t),this._setObserving(!0),this._ready):(this._setObserving(!1),this._ready)}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)}dispose(){this._gen++,this.disconnect()}_teardownObserver(){this._observer&&(this._observer.disconnect(),this._observer=null),this._observed=null,this._gen++}_createObserver(t){if("undefined"==typeof IntersectionObserver)return null;const e=this._gen;try{return new IntersectionObserver(t=>this._onIntersect(e,t),{root:t.root??null,rootMargin:t.rootMargin??"0px",threshold:t.threshold??0})}catch{return null}}_onIntersect(t,e){if(t===this._gen)for(const t of e){const e=this._normalizeEntry(t);this._setEntry(e),e.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)}}function c(t,e){let s=Object.getPrototypeOf(t);for(;null!==s;){const t=Object.getOwnPropertyDescriptor(s,e);if(void 0!==t)return"function"==typeof t.get||"function"==typeof t.set;s=Object.getPrototypeOf(s)}return!1}class a extends HTMLElement{static hasConnectedCallbackPromise=!0;static observedAttributes=["target","root","root-margin","threshold"];static wcBindable={...o.wcBindable,properties:[...o.wcBindable.properties,{name:"trigger",event:"wcs-intersect:trigger-changed",semantics:"state"}],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;_connectedCallbackPromise=Promise.resolve();_internals=null;constructor(){super(),this._core=new o(this),this._internals=this._initInternals(),this._wireStates({"wcs-intersect:visible-changed":t=>({visible:!0===t}),"wcs-intersect:observing-changed":t=>({observing:!0===t}),"wcs-intersect:change":t=>({intersecting:!0===t.isIntersecting})})}get debugStates(){return this._internals?[...this._internals.states]:[]}_initInternals(){try{if("function"!=typeof this.attachInternals)return null;const t=this.attachInternals();return t.states.add("wcs-probe"),t.states.delete("wcs-probe"),t}catch{return null}}_wireStates(t){if(null===this._internals)return;const e=this._internals.states;for(const[s,r]of Object.entries(t))this.addEventListener(s,t=>{const s=this.hasAttribute("debug-states");for(const[n,i]of Object.entries(r(t.detail))){try{i?e.add(n):e.delete(n)}catch{}s&&this.toggleAttribute(`data-wcs-state-${n}`,i)}})}get connectedCallbackPromise(){return this._connectedCallbackPromise}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(){!function(t){const e=t.constructor?.wcBindable,s=e?.inputs;if(void 0!==s)for(const e of s){const s=e.name;if(!Object.prototype.hasOwnProperty.call(t,s))continue;if(!c(t,s))continue;const r=t,n=r[s];delete r[s],r[s]=n}}(this),this.addEventListener("wcs-intersect:change",this._onChange),this.manual||this.observe(),this._connectedCallbackPromise=this._core.ready}disconnectedCallback(){this.removeEventListener("wcs-intersect:change",this._onChange),this._core.dispose()}attributeChangedCallback(t,e,s){e!==s&&this.isConnected&&!this.manual&&this.observe()}}function h(e){var s;e&&((s=e).tagNames&&Object.assign(t.tagNames,s.tagNames),r=null),customElements.get(n.tagNames.intersect)||customElements.define(n.tagNames.intersect,a)}export{o as IntersectionCore,a as WcsIntersect,h as bootstrapIntersection,i as getConfig};
2
- //# sourceMappingURL=index.esm.min.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.esm.min.js","sources":["../src/config.ts","../src/core/IntersectionCore.ts","../src/protocol/upgradeProperties.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\", semantics: \"state\" },\n { name: \"intersecting\", event: \"wcs-intersect:change\", semantics: \"state\", getter: (e: Event) => (e as CustomEvent).detail.isIntersecting },\n { name: \"ratio\", event: \"wcs-intersect:change\", semantics: \"state\", getter: (e: Event) => (e as CustomEvent).detail.intersectionRatio },\n { name: \"visible\", event: \"wcs-intersect:visible-changed\", semantics: \"state\" },\n { name: \"observing\", event: \"wcs-intersect:observing-changed\", semantics: \"state\" },\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 // Generation guard (§3.4): bumped on dispose() and on each observe()/reobserve()\n // teardown+rebuild. IntersectionObserver delivers its callback asynchronously off\n // layout, so a callback can fire after the element is disposed or after a rapid\n // disconnect→reconnect rebuilt the observer. Each observer captures the gen live at\n // creation; a callback from a superseded/torn-down observer has a stale gen and\n // MUST NOT write state to a torn-down element. A boolean flag is insufficient\n // (dispose→observe would flip it back and let stale work slip through).\n private _gen = 0;\n\n // SSR (§3.8): IntersectionObserver setup is synchronous (no async probe to await),\n // so readiness is immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n /** Resolves immediately — there is no asynchronous probe to await (§3.8). */\n get ready(): Promise<void> {\n return this._ready;\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 = {}): Promise<void> {\n if (this._observer && this._observed === element && this._optionsEqual(this._options, options)) {\n return this._ready;\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 this._ready;\n }\n this._observer = observer;\n this._observed = element;\n this._options = options;\n observer.observe(element);\n this._setObserving(true);\n // SSR (§3.5): observe() returns the readiness promise. Observation establishment\n // is synchronous, so this resolves immediately.\n return this._ready;\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 // --- Lifecycle (§3.5) ---\n\n /**\n * `observe()` (the IntersectionObserver-style command above) establishes\n * monitoring, so there is no separate idempotent monitoring entry point — only\n * teardown. `dispose()` invalidates any in-flight observer callback (`_gen++`)\n * and releases the observer. A later observe() revives it (the Shell calls this\n * from `disconnectedCallback`).\n */\n dispose(): void {\n this._gen++;\n this.disconnect();\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 // Invalidate the torn-down observer's generation: its callback can still fire\n // once asynchronously after disconnect(), and must be dropped (§3.4).\n this._gen++;\n }\n\n private _createObserver(options: IntersectOptions): IntersectionObserver | null {\n if (typeof IntersectionObserver === \"undefined\") return null;\n // Capture the generation live at creation. The callback closure below guards\n // against deliveries from this observer after it has been superseded or\n // disposed (a stale callback fired off layout after teardown).\n const gen = this._gen;\n try {\n return new IntersectionObserver(\n (entries) => this._onIntersect(gen, entries),\n {\n root: options.root ?? null,\n rootMargin: options.rootMargin ?? \"0px\",\n threshold: options.threshold ?? 0,\n },\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(gen: number, entries: IntersectionObserverEntry[]): void {\n // Stale-generation guard (§3.4): drop callbacks from an observer that was torn\n // down or disposed (e.g. a delivery that landed after disconnect/reconnect).\n if (gen !== this._gen) return;\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","// ===========================================================================\n// AUTO-GENERATED FILE - DO NOT EDIT.\n// Generated from /protocol/upgrade-properties.ts by scripts/sync-protocol-types.mjs.\n// Run `node scripts/sync-protocol-types.mjs` after editing the source.\n// ===========================================================================\n\n// custom element の property upgrade — `static wcBindable.inputs` に宣言した入力のうち、\n// 要素が upgrade される前に代入された own データプロパティを取り込み直す。\n//\n// なぜ必要か:\n// 未定義タグの要素は素の HTMLElement なので、`el.url = \"...\"` は own データプロパティを作る。\n// upgrade 後にクラスの accessor が prototype へ入っても own プロパティが優先されるため、\n// setter は二度と呼ばれず、値は要素へ届かないまま消える(エラーも警告も出ない)。\n// 常にプロパティ代入を行う framework(Angular の `[prop]`、Lit の `.prop=`、\n// Solid の `prop:`、Vue の `.prop` 修飾子)× 遅延定義(autoloader / CDN / code-split)で\n// 常態的に起きる。docs/architecture-hardening/13-framework-adapter-binding-constraints.md §1.2。\n//\n// 安全側の判定:\n// own プロパティがあっても、prototype チェーンに accessor が無ければ「シャドウ」ではなく\n// その own プロパティ自体が正規の格納先なので触らない(public class field を壊さない)。\n//\n// SINGLE SOURCE OF TRUTH: edit only this file (/protocol/upgrade-properties.ts), then run\n// `node scripts/sync-protocol-types.mjs` to regenerate the per-package copies\n// (packages/<pkg>/src/protocol/upgradeProperties.ts). Those copies are generated — do not edit them.\nimport { IWcBindable } from \"./wcBindable.js\";\n\nfunction hasAccessorOnPrototype(target: object, name: string): boolean {\n let proto = Object.getPrototypeOf(target);\n while (proto !== null) {\n const descriptor = Object.getOwnPropertyDescriptor(proto, name);\n if (descriptor !== undefined) {\n return typeof descriptor.get === \"function\" || typeof descriptor.set === \"function\";\n }\n proto = Object.getPrototypeOf(proto);\n }\n return false;\n}\n\n/**\n * `connectedCallback` の先頭で呼ぶ。宣言済み input のうち upgrade 前の代入で\n * accessor をシャドウしている own プロパティを、delete → 再代入で setter に通し直す。\n *\n * - 冪等: 再代入は accessor を通るので own プロパティは残らず、2 回目以降は no-op。\n * - 宣言に `inputs` が無い要素、`wcBindable` を持たない要素では何もしない。\n * - 値の意味は変えない。今まで捨てられていた代入が届くようになる一方向の変化。\n */\nexport function upgradeProperties(element: object): void {\n const declaration = (element as { constructor?: { wcBindable?: IWcBindable } }).constructor?.wcBindable;\n const inputs = declaration?.inputs;\n if (inputs === undefined) return;\n for (const input of inputs) {\n const name = input.name;\n if (!Object.prototype.hasOwnProperty.call(element, name)) continue;\n if (!hasAccessorOnPrototype(element, name)) continue;\n const record = element as Record<string, unknown>;\n const value = record[name];\n delete record[name];\n record[name] = value;\n }\n}\n","import { IWcBindable, IntersectOptions, WcsIntersectEntry } from \"../types.js\";\nimport { IntersectionCore } from \"../core/IntersectionCore.js\";\nimport { upgradeProperties } from \"../protocol/upgradeProperties.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 // SSR (§4.4): the first observation is established synchronously on connect, but\n // the Shell still exposes connectedCallbackPromise so the state binder can await\n // it uniformly across all IO nodes before snapshotting.\n static hasConnectedCallbackPromise = true;\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\", semantics: \"state\" },\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 private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n private _internals: ElementInternals | null = null;\n\n constructor() {\n super();\n this._core = new IntersectionCore(this);\n this._internals = this._initInternals();\n this._wireStates({\n \"wcs-intersect:visible-changed\": (d) => ({ visible: d === true }),\n \"wcs-intersect:observing-changed\": (d) => ({ observing: d === true }),\n \"wcs-intersect:change\": (d) => ({ intersecting: d.isIntersecting === true }),\n });\n }\n\n // CSS state reflection (:state()) — debug-only snapshot getter. NOT part of\n // wc-bindable (not a bind target); see README \"CSS styling with :state()\".\n // MUST NOT return the live CustomStateSet (that would let callers write\n // states from outside, defeating the point of :state() being read-only).\n get debugStates(): string[] {\n return this._internals ? [...this._internals.states] : [];\n }\n\n private _initInternals(): ElementInternals | null {\n // never-throw (async-io-node-guidelines.md §3.6): attachInternals is absent\n // in happy-dom / older environments, and pre-125 Chromium rejects\n // non-dashed state names from states.add() (probed and discarded here).\n // Either case silently disables reflection — the component still works,\n // it just doesn't expose :state() selectors.\n try {\n if (typeof this.attachInternals !== \"function\") return null;\n const internals = this.attachInternals();\n internals.states.add(\"wcs-probe\");\n internals.states.delete(\"wcs-probe\");\n return internals;\n } catch {\n return null;\n }\n }\n\n private _wireStates(map: Record<string, (detail: any) => Record<string, boolean>>): void {\n if (this._internals === null) return;\n const states = this._internals.states;\n for (const [event, toStates] of Object.entries(map)) {\n this.addEventListener(event, (e) => {\n const debug = this.hasAttribute(\"debug-states\");\n for (const [name, on] of Object.entries(toStates((e as CustomEvent).detail))) {\n try {\n if (on) { states.add(name); } else { states.delete(name); }\n } catch { /* never-throw */ }\n if (debug) this.toggleAttribute(`data-wcs-state-${name}`, on);\n }\n });\n }\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Attribute accessors ---\n\n get target(): string {\n return this.getAttribute(\"target\") ?? \"\";\n }\n\n set target(value: string) {\n this.setAttribute(\"target\", value);\n }\n\n 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 // upgrade 前に代入された input を取り込み直す(doc 13 §1.2 / Phase A1)\n upgradeProperties(this);\n this.addEventListener(\"wcs-intersect:change\", this._onChange);\n if (!this.manual) {\n this.observe();\n }\n // SSR (§4.4): readiness is synchronous (observation is established above), but\n // expose the Core's ready promise as connectedCallbackPromise so the state\n // binder can await it uniformly. `manual` defers observation but readiness is\n // still immediate.\n this._connectedCallbackPromise = this._core.ready;\n }\n\n disconnectedCallback(): void {\n this.removeEventListener(\"wcs-intersect:change\", this._onChange);\n // dispose() tears down the observer AND bumps the Core's generation so any\n // IntersectionObserver callback still in flight is dropped (§3.4 / §4.1).\n this._core.dispose();\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","semantics","getter","e","detail","isIntersecting","intersectionRatio","commands","_target","_observer","_observed","_options","_entry","_visible","_observing","_gen","_ready","Promise","resolve","constructor","target","super","this","ready","entry","intersecting","ratio","visible","observing","_setEntry","dispatchEvent","CustomEvent","bubbles","_setVisible","_setObserving","observe","element","options","_optionsEqual","_teardownObserver","observer","_createObserver","reobserve","unobserve","disconnect","reset","dispose","IntersectionObserver","gen","entries","_onIntersect","root","rootMargin","threshold","normalized","_normalizeEntry","time","boundingClientRect","_normalizeRect","intersectionRect","rootBounds","rect","x","y","width","height","top","right","bottom","left","a","b","_thresholdKey","undefined","Array","isArray","join","String","hasAccessorOnPrototype","proto","getPrototypeOf","descriptor","getOwnPropertyDescriptor","get","set","WcsIntersect","HTMLElement","wcBindable","inputs","attribute","_core","_trigger","_connectedCallbackPromise","_internals","_initInternals","_wireStates","d","debugStates","states","attachInternals","internals","add","delete","map","toStates","addEventListener","debug","hasAttribute","on","toggleAttribute","connectedCallbackPromise","getAttribute","value","setAttribute","attr","trim","once","removeAttribute","manual","trigger","display","_resolveTarget","style","scope","getRootNode","_safeQuery","child","firstElementChild","_resolveRoot","selector","querySelector","_parseThreshold","raw","nums","split","s","filter","Number","n","isFinite","length","_onChange","connectedCallback","declaration","input","prototype","hasOwnProperty","call","record","upgradeProperties","disconnectedCallback","removeEventListener","attributeChangedCallback","_name","oldValue","newValue","isConnected","bootstrapIntersection","userConfig","partialConfig","assign","customElements","define"],"mappings":"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"}