import{x as f}from"./iframe-CMPv_g6-.js";import{l as P,o as b}from"./onFind-B81tRmr7.js";import"./preload-helper-PPVm8Dsz.js";const F=Symbol.for("brightspot.onFind");let y;function v(){return y||(y=globalThis[F],y||(y={calledIndex:0,callbacks:[],blacklist:[],triggerPaused:!1,triggerOnResume:!1,triggerAll:!1,triggerElements:[],triggerFrame:0,initialized:!1},globalThis[F]=y),y)}class O{#n;#e;#t;#a;#s;constructor(t,e,n){this.#n=t,this.#e=`data-ofc${v().calledIndex++}`,Array.isArray(e)||(e=[e]),this.#t=e.map(e.some(o=>o.indexOf(",")>-1)?o=>o:o=>`${o}:not([${this.#e}])`).join(","),this.#a=n;const a=e.map(o=>o.trim()).filter(o=>o.indexOf(" ")<0&&o.indexOf(",")<0);a.length===e.length&&(this.#s=a)}addTriggerElements(t,e){if(this.#n.contains(e)){e.matches(this.#t)&&t.push(e);for(const n of e.querySelectorAll(this.#t))t.push(n)}}trigger(t){if(document.readyState!=="loading")if(this.#s&&Array.isArray(t))for(const e of t)this.#s.some(n=>e.matches(n))&&this.#o(e);else for(const e of this.#n.querySelectorAll(this.#t))this.#o(e)}#o(t){if(!H(t)&&!t.hasAttribute(this.#e)){t.setAttribute(this.#e,"");try{this.#a(t)}catch(e){P.error("Failed callback!",t,e)}}}}function H(s){if(!(s instanceof Element))return!1;const{blacklist:t}=v();return t.length>0&&t.some(e=>s.closest(e)!==null)}const $=Array.prototype.every,S=s=>s.nodeType===Node.TEXT_NODE;function C(s){const t=v();if(t.triggerPaused){t.triggerOnResume=!0;return}const e=Array.isArray(s),n=[];if(e){for(const a of s){const o=a.target;if(!H(o))switch(a.type){case"attributes":a.oldValue!==o.getAttribute(a.attributeName)&&n.push(a);break;case"childList":(!$.call(a.addedNodes,S)||!$.call(a.removedNodes,S))&&n.push(a);break}}if(n.length===0)return}if(n.length>500&&(t.triggerAll=!0),!t.triggerAll)if(e)for(const a of n){const o=a.target;switch(a.type){case"attributes":t.triggerElements.push(o);break;case"childList":for(const r of t.callbacks)r.addTriggerElements(t.triggerElements,o);break}}else t.triggerAll=!0;(t.triggerAll||t.triggerElements.length>0)&&!t.triggerFrame&&(t.triggerFrame=window.requestAnimationFrame(()=>{const a=t.triggerAll?void 0:t.triggerElements;t.triggerAll=!1,t.triggerElements=[],t.triggerFrame=0,t.callbacks.forEach(o=>o.trigger(a))}))}function z(){C(),new MutationObserver(C).observe(document,{attributes:!0,attributeFilter:["class","data-bsp-autosubmit","data-chart-type","data-code-type","data-internal-name","data-tab","name","rel","target"],attributeOldValue:!0,childList:!0,subtree:!0})}function D(){const s=v();s.initialized||(s.initialized=!0,document.readyState==="loading"?document.addEventListener("DOMContentLoaded",z):z())}function m(s,t,e){D();let n,a;typeof e<"u"?(n=s,a=t):(n=document,a=s,e=t);const o=new O(n,a,e);o.trigger(),v().callbacks.push(o)}m.triggerCallbacks=C;m.pause=()=>{v().triggerPaused=!0};m.resume=()=>{const s=v();s.triggerPaused=!1,s.triggerOnResume&&(s.triggerOnResume=!1,setTimeout(C,100))};m.ignore=(...s)=>{const{blacklist:t}=v();for(const e of s){try{document.querySelector(e)}catch{continue}t.includes(e)||t.push(e)}};const{expect:d,userEvent:c,waitFor:u,within:k}=__STORYBOOK_MODULE_TEST__,R={title:"Utilities/onFind",tags:["autodocs"],parameters:{docs:{subtitle:"The `onFind` utility observes DOM mutations and executes callbacks when elements matching specified selectors appear. Uses MutationObserver internally to efficiently track element additions and attribute changes."},controls:{expanded:!0}},argTypes:{selector:{control:{type:"text"},description:"CSS selector to watch for"}},args:{selector:".dynamic-item"}},x={render:s=>{const t=`onfind-${Math.random().toString(36).substring(2,9)}`,e=`.dynamic-item-${t}`;let n=0,a=0;const o=()=>{const i=document.getElementById(`${t}-items-count`),l=document.getElementById(`${t}-found-count`);i&&(i.textContent=String(n)),l&&(l.textContent=String(a))};return b(e,i=>{a++,o(),i.classList.add("ring-2","ring-success-500")}),f`
      <div class="space-y-4">
        <div class="text-base">
          <p class="mb-2">
            Click "Add Item" to dynamically create elements. The onFind observer detects them and highlights them with a
            green border.
          </p>
        </div>

        <div class="flex gap-2">
          <button data-testid="add-item" @click=${()=>{n++;const i=document.getElementById(`${t}-container`);if(i){const l=document.createElement("div");l.className=`dynamic-item-${t} rounded border bg-white p-4`,l.textContent=`Item ${n}`,i.appendChild(l)}o()}} class="btu-button btu-button-primary btu-button-sm">
            Add Item
          </button>
          <button data-testid="clear-items" @click=${()=>{n=0,a=0;const i=document.getElementById(`${t}-container`);i&&(i.innerHTML=""),o()}} class="btu-button btu-button-gray btu-button-sm">
            Clear All
          </button>
        </div>

        <div id="${t}-container" class="min-h-32 space-y-2 rounded border-2 border-gray-300 bg-gray-50 p-4">
          <div class="text-sm text-gray-500">Items will appear here...</div>
        </div>

        <div class="flex justify-around">
          <div>
            <div class="text-xs text-gray-500">Items created</div>
            <div data-testid="items-count" id="${t}-items-count" class="text-2xl font-bold text-gray-900">
              0
            </div>
          </div>
          <div>
            <div class="text-xs text-gray-500">Items detected by onFind</div>
            <div data-testid="found-count" id="${t}-found-count" class="text-2xl font-bold text-primary-600">
              0
            </div>
          </div>
        </div>
      </div>
    `},parameters:{docs:{description:{story:"Interactive example showing onFind detecting dynamically added elements. Elements are automatically highlighted when detected."}}},play:async({canvasElement:s,step:t})=>{const e=k(s);await t("Detects dynamically added element",async()=>{await c.click(e.getByTestId("add-item")),await u(()=>d(e.getByTestId("found-count")).toHaveTextContent("1"))}),await t("Detects multiple elements",async()=>{await c.click(e.getByTestId("add-item")),await c.click(e.getByTestId("add-item")),await u(()=>d(e.getByTestId("found-count")).toHaveTextContent("3"))}),await t("Clear resets counts",async()=>{await c.click(e.getByTestId("clear-items")),d(e.getByTestId("items-count")).toHaveTextContent("0"),d(e.getByTestId("found-count")).toHaveTextContent("0")}),await t("Detection resumes after clear",async()=>{await c.click(e.getByTestId("add-item")),await u(()=>d(e.getByTestId("found-count")).toHaveTextContent("1"))})}},B={render:()=>{const s="onfind-ignore-demo",t=".ignore-demo-item",e="ignore-demo-zone";let n=0,a=0;const o=()=>{const i=document.getElementById(`${s}-found-count`);i&&(i.textContent=String(n))};return b.ignore(`.${e}`),b(t,i=>{n++,o(),i.classList.add("ring-2","ring-success-500")}),f`
      <div class="space-y-4">
        <p class="text-base">
          Elements added inside the <strong>ignored zone</strong> are skipped by onFind callbacks. Elements added
          outside are detected normally.
        </p>

        <div class="flex gap-2">
          <button data-testid="add-outside" @click=${()=>{a++;const i=document.getElementById(`${s}-outside`);if(i){const l=document.createElement("div");l.className=`${t.slice(1)} rounded border bg-white p-4`,l.textContent=`Outside ${a}`,i.appendChild(l)}}} class="btu-button btu-button-primary btu-button-sm">
            Add Outside
          </button>
          <button data-testid="add-inside" @click=${()=>{a++;const i=document.getElementById(`${s}-inside`);if(i){const l=document.createElement("div");l.className=`${t.slice(1)} rounded border bg-white p-4`,l.textContent=`Inside ${a}`,i.appendChild(l)}}} class="btu-button btu-button-gray btu-button-sm">
            Add Inside Ignored
          </button>
        </div>

        <div class="grid grid-cols-2 gap-4">
          <div>
            <div class="mb-1 text-xs font-semibold text-gray-500">Normal zone</div>
            <div id="${s}-outside" class="min-h-32 space-y-2 rounded border-2 border-gray-300 bg-gray-50 p-4">
              <div class="text-sm text-gray-400">Items detected here</div>
            </div>
          </div>
          <div>
            <div class="mb-1 text-xs font-semibold text-gray-500">Ignored zone</div>
            <div
              id="${s}-inside"
              class="${e} border-red-300 bg-red-50 min-h-32 space-y-2 rounded border-2 p-4"
            >
              <div class="text-sm text-gray-400">Items ignored here</div>
            </div>
          </div>
        </div>

        <div>
          <div class="text-xs text-gray-500">Items detected by onFind</div>
          <div
            data-testid="ignore-found-count"
            id="${s}-found-count"
            class="text-2xl font-bold text-primary-600"
          >
            0
          </div>
        </div>
      </div>
    `},parameters:{docs:{description:{story:"Demonstrates `onFind.ignore()` — elements inside ignored containers are excluded from callback processing. Useful for skipping rich-text editors or other zones where DOM mutations should not trigger component initialization."}}},play:async({canvasElement:s,step:t})=>{const e=k(s);await t("Detects outside ignored zone",async()=>{await c.click(e.getByTestId("add-outside")),await u(()=>d(e.getByTestId("ignore-found-count")).toHaveTextContent("1"))}),await t("Skips inside ignored zone",async()=>{await c.click(e.getByTestId("add-inside")),await new Promise(n=>requestAnimationFrame(()=>requestAnimationFrame(n))),d(e.getByTestId("ignore-found-count")).toHaveTextContent("1")}),await t("Continues detecting outside",async()=>{await c.click(e.getByTestId("add-outside")),await u(()=>d(e.getByTestId("ignore-found-count")).toHaveTextContent("2"))})}},I={render:()=>{const s="onfind-pause-demo",t=".pause-demo-item";let e=0,n=0;const a=()=>{const i=document.getElementById(`${s}-found-count`);i&&(i.textContent=String(e))};b(t,i=>{e++,a(),i.classList.add("ring-2","ring-success-500")});const o=()=>{n++;const i=document.getElementById(`${s}-container`);if(i){const l=document.createElement("div");l.className=`${t.slice(1)} rounded border bg-white p-4`,l.textContent=`Item ${n}`,i.appendChild(l)}};let r=!1;return f`
      <div class="space-y-4">
        <p class="text-base">
          Use <code>onFind.pause()</code> to temporarily stop detection and <code>onFind.resume()</code> to restart it.
          Elements added while paused are detected on resume.
        </p>

        <div class="flex gap-2">
          <button data-testid="pause-add" @click=${o} class="btu-button btu-button-primary btu-button-sm">
            Add Item
          </button>
          <button data-testid="toggle-pause" @click=${()=>{r=!r,r?b.pause():b.resume();const i=document.querySelector('[data-testid="toggle-pause"]');i&&(i.textContent=r?"Resume":"Pause",i.className=r?"btu-button btu-button-success btu-button-sm":"btu-button btu-button-warning btu-button-sm")}} class="btu-button btu-button-warning btu-button-sm">
            Pause
          </button>
        </div>

        <div id="${s}-container" class="min-h-32 space-y-2 rounded border-2 border-gray-300 bg-gray-50 p-4">
          <div class="text-sm text-gray-500">Items will appear here...</div>
        </div>

        <div>
          <div class="text-xs text-gray-500">Items detected by onFind</div>
          <div
            data-testid="pause-found-count"
            id="${s}-found-count"
            class="text-2xl font-bold text-primary-600"
          >
            0
          </div>
        </div>
      </div>
    `},parameters:{docs:{description:{story:"Demonstrates `onFind.pause()` and `onFind.resume()`. While paused, DOM mutations are queued and processed when resumed."}}},play:async({canvasElement:s,step:t})=>{const e=k(s);await t("Normal detection before pause",async()=>{await c.click(e.getByTestId("pause-add")),await u(()=>d(e.getByTestId("pause-found-count")).toHaveTextContent("1"))}),await t("Pause stops detection",async()=>{await c.click(e.getByTestId("toggle-pause")),await c.click(e.getByTestId("pause-add")),await new Promise(n=>setTimeout(n,200)),d(e.getByTestId("pause-found-count")).toHaveTextContent("1")}),await t("Resume triggers pending detection",async()=>{await c.click(e.getByTestId("toggle-pause")),await u(()=>d(e.getByTestId("pause-found-count")).toHaveTextContent("2"),{timeout:2e3})})}},w={render:()=>{const s=b,t=".singleton-item-a",e=".singleton-item-b";let n=0,a=0;const o=()=>{const g=document.getElementById("singleton-count-a"),h=document.getElementById("singleton-count-b");g&&(g.textContent=String(n)),h&&(h.textContent=String(a))};s.ignore(".singleton-ignored-zone"),s(t,g=>{n++,o(),g.classList.add("ring-2","ring-blue-500")}),m(e,g=>{a++,o(),g.classList.add("ring-2","ring-purple-500")});const r=(g,h,M)=>{const A=document.getElementById(M);if(A){const E=document.createElement("div");E.className=`${g.slice(1)} rounded border bg-white p-4`,E.textContent=h,A.appendChild(E)}};let p=!1;return f`
      <div class="space-y-4">
        <p class="text-base">
          Two separate ES module instances of <code>onFind</code> (each with its own <code>_state</code> cache) share
          one observer, ignore list, and pause/resume state via <code>globalThis[Symbol.for()]</code>.
        </p>

        <div class="flex items-center gap-4">
          <button
            data-testid="singleton-toggle-pause"
            @click=${()=>{p=!p,p?s.pause():s.resume();const g=document.querySelector('[data-testid="singleton-toggle-pause"]');g&&(g.textContent=p?"Resume":"Pause",g.className=p?"btu-button btu-button-success btu-button-sm":"btu-button btu-button-warning btu-button-sm")}}
            class="btu-button btu-button-warning btu-button-sm"
          >
            Pause
          </button>
          <div class="text-blue-600 flex items-center gap-1 text-sm">
            Bundle A:
            <span data-testid="singleton-count-a" id="singleton-count-a" class="font-bold">0</span>
            items found
          </div>
          <div class="flex items-center gap-1 text-sm text-purple-600">
            Bundle B:
            <span data-testid="singleton-count-b" id="singleton-count-b" class="font-bold">0</span>
            items found
          </div>
        </div>

        <div class="grid grid-cols-3 gap-4">
          <div>
            <div class="text-blue-600 mb-2 text-xs font-semibold">Bundle A zone</div>
            <div class="mb-2 flex gap-1">
              <button
                data-testid="singleton-add-a"
                @click=${()=>r(t,"Bundle A item","singleton-zone-a")}
                class="btu-button btu-button-primary btu-button-sm"
              >
                Add A
              </button>
              <button
                data-testid="singleton-zone-a-add-b"
                @click=${()=>r(e,"Bundle B item","singleton-zone-a")}
                class="btu-button btu-button-purple btu-button-sm"
              >
                Add B
              </button>
            </div>
            <div id="singleton-zone-a" class="border-blue-300 bg-blue-50 min-h-24 space-y-2 rounded border-2 p-4">
              <div class="text-sm text-gray-400">A items here</div>
            </div>
          </div>
          <div>
            <div class="mb-2 text-xs font-semibold text-purple-600">Bundle B zone</div>
            <div class="mb-2 flex gap-1">
              <button
                data-testid="singleton-zone-b-add-a"
                @click=${()=>r(t,"Bundle A item","singleton-zone-b")}
                class="btu-button btu-button-primary btu-button-sm"
              >
                Add A
              </button>
              <button
                data-testid="singleton-add-b"
                @click=${()=>r(e,"Bundle B item","singleton-zone-b")}
                class="btu-button btu-button-purple btu-button-sm"
              >
                Add B
              </button>
            </div>
            <div id="singleton-zone-b" class="min-h-24 space-y-2 rounded border-2 border-purple-300 bg-purple-50 p-4">
              <div class="text-sm text-gray-400">B items here</div>
            </div>
          </div>
          <div>
            <div class="text-red-600 mb-2 text-xs font-semibold">Ignored zone</div>
            <div class="mb-2 flex gap-1">
              <button
                data-testid="singleton-add-ignored"
                @click=${()=>{r(t,"Ignored A","singleton-ignored"),r(e,"Ignored B","singleton-ignored")}}
                class="btu-button btu-button-gray btu-button-sm"
              >
                Add A & B
              </button>
            </div>
            <div
              id="singleton-ignored"
              class="singleton-ignored-zone border-red-300 bg-red-50 min-h-24 space-y-2 rounded border-2 p-4"
            >
              <div class="text-sm text-gray-400">Items ignored here</div>
            </div>
          </div>
        </div>
      </div>
    `},parameters:{docs:{description:{story:"Two independent module instances of `onFind` (simulating separate bundles) share a single MutationObserver, ignore list, and pause/resume state through the `globalThis[Symbol.for()]` singleton pattern."}}},play:async({canvasElement:s,step:t})=>{const e=k(s);await t("Shared observer: Bundle A detects A items, Bundle B detects B items",async()=>{await c.click(e.getByTestId("singleton-add-a")),await u(()=>d(e.getByTestId("singleton-count-a")).toHaveTextContent("1")),await c.click(e.getByTestId("singleton-add-b")),await u(()=>d(e.getByTestId("singleton-count-b")).toHaveTextContent("1"))}),await t("Cross-zone detection fires correct callback",async()=>{await c.click(e.getByTestId("singleton-zone-a-add-b")),await u(()=>d(e.getByTestId("singleton-count-b")).toHaveTextContent("2")),d(e.getByTestId("singleton-count-a")).toHaveTextContent("1"),await c.click(e.getByTestId("singleton-zone-b-add-a")),await u(()=>d(e.getByTestId("singleton-count-a")).toHaveTextContent("2")),d(e.getByTestId("singleton-count-b")).toHaveTextContent("2")}),await t("Shared ignore list: Bundle A ignore() blocks Bundle B callbacks",async()=>{const n=e.getByTestId("singleton-count-a").textContent,a=e.getByTestId("singleton-count-b").textContent;await c.click(e.getByTestId("singleton-add-ignored")),await new Promise(o=>requestAnimationFrame(()=>requestAnimationFrame(o))),d(e.getByTestId("singleton-count-a")).toHaveTextContent(n),d(e.getByTestId("singleton-count-b")).toHaveTextContent(a)}),await t("Ignore lists are merged and deduped across bundles",async()=>{const n=globalThis[Symbol.for("brightspot.onFind")],a=n.blacklist.length;m.ignore(".singleton-ignored-zone"),d(n.blacklist.length).toBe(a),m.ignore(".bundle-b-ignored"),d(n.blacklist).toContain(".singleton-ignored-zone"),d(n.blacklist).toContain(".bundle-b-ignored"),d(n.blacklist.length).toBe(a+1)}),await t("Shared pause/resume: Bundle A pause() stops Bundle B detection",async()=>{await c.click(e.getByTestId("singleton-toggle-pause")),await c.click(e.getByTestId("singleton-add-a")),await c.click(e.getByTestId("singleton-add-b")),await new Promise(n=>setTimeout(n,200)),d(e.getByTestId("singleton-count-a")).toHaveTextContent("2"),d(e.getByTestId("singleton-count-b")).toHaveTextContent("2"),await c.click(e.getByTestId("singleton-toggle-pause")),await u(()=>d(e.getByTestId("singleton-count-a")).toHaveTextContent("3"),{timeout:2e3}),await u(()=>d(e.getByTestId("singleton-count-b")).toHaveTextContent("3"),{timeout:2e3})}),await t("No index collision on data-ofc attributes",async()=>{const n=s.querySelectorAll(".singleton-item-a, .singleton-item-b"),a=new Set;n.forEach(o=>{o.getAttributeNames().filter(r=>r.startsWith("data-ofc")).forEach(r=>a.add(r))}),d(a.size).toBeGreaterThanOrEqual(2)}),await t("Singleton state: both bundles share the same globalThis object",async()=>{const n=globalThis[Symbol.for("brightspot.onFind")];d(n).toBeDefined(),d(n.callbacks).toBeDefined(),d(Array.isArray(n.callbacks)).toBe(!0),d(n.initialized).toBe(!0),d(b.pause).not.toBe(m.pause),d(b.resume).not.toBe(m.resume)})}},T={render:()=>f`
    <div class="space-y-4 text-sm">
      <div>
        <h3 class="mb-2 font-bold">Basic Usage</h3>
        <pre
          class="overflow-x-auto rounded bg-gray-900 p-4 text-gray-100"
        ><code>import onFind from '@brightspot/ui/util/onFind.js'

// Watch for elements globally
onFind('.my-component', (element) => {
  console.log('Found element:', element)
  // Initialize component
})

// Watch within a specific root element
const container = document.querySelector('#container')
onFind(container, '.my-widget', (element) => {
  // Initialize widget
})</code></pre>
      </div>

      <div>
        <h3 class="mb-2 font-bold">Multiple Selectors</h3>
        <pre class="overflow-x-auto rounded bg-gray-900 p-4 text-gray-100"><code>// Watch for multiple selectors at once
onFind(['.button', '.input', '.select'], (element) => {
  if (element.matches('.button')) {
    // Handle button
  } else if (element.matches('.input')) {
    // Handle input
  }
})</code></pre>
      </div>

      <div>
        <h3 class="mb-2 font-bold">Pause and Resume</h3>
        <pre class="overflow-x-auto rounded bg-gray-900 p-4 text-gray-100"><code>// Pause observations temporarily
onFind.pause()

// Make bulk DOM changes without triggering callbacks
// ...

// Resume observations
onFind.resume()</code></pre>
      </div>

      <div>
        <h3 class="mb-2 font-bold">Ignore Selectors</h3>
        <pre
          class="overflow-x-auto rounded bg-gray-900 p-4 text-gray-100"
        ><code>// Exclude elements inside matching containers from all callbacks.
// Calls are additive and shared across bundles.
onFind.ignore('.ProseMirror', '.RichTextEditor')

// Elements inside ignored containers will not trigger callbacks,
// even if they match a registered selector.</code></pre>
      </div>

      <div>
        <h3 class="mb-2 font-bold">Common Use Cases</h3>
        <ul class="list-inside list-disc space-y-1 text-gray-700">
          <li>Initialize components when they appear in the DOM</li>
          <li>Attach event listeners to dynamically created elements</li>
          <li>Enhance server-rendered content progressively</li>
          <li>Detect and respond to attribute changes</li>
          <li>Apply transformations to newly added content</li>
        </ul>
      </div>

      <div>
        <h3 class="mb-2 font-bold">Parameters</h3>
        <ul class="space-y-2">
          <li>
            <code class="rounded bg-gray-200 px-1">root</code> (ParentNode, optional): Root element to observe. Defaults
            to document.
          </li>
          <li>
            <code class="rounded bg-gray-200 px-1">selectors</code> (string | string[]): CSS selector(s) to watch for
          </li>
          <li>
            <code class="rounded bg-gray-200 px-1">fn</code> (function): Callback executed when matching elements are
            found
          </li>
        </ul>
      </div>

      <div>
        <h3 class="mb-2 font-bold">Static Methods</h3>
        <table class="w-full text-left text-sm">
          <thead>
            <tr class="border-b">
              <th class="py-2 pr-4">Method</th>
              <th class="py-2 pr-4">Signature</th>
              <th class="py-2">Description</th>
            </tr>
          </thead>
          <tbody>
            <tr class="border-b">
              <td class="py-2 pr-4"><code class="rounded bg-gray-200 px-1">onFind.ignore</code></td>
              <td class="py-2 pr-4"><code class="text-xs">(...selectors: string[]) =&gt; void</code></td>
              <td class="py-2">
                Exclude elements inside matching containers from all callbacks. Calls are additive and shared across
                bundles.
              </td>
            </tr>
            <tr class="border-b">
              <td class="py-2 pr-4"><code class="rounded bg-gray-200 px-1">onFind.pause</code></td>
              <td class="py-2 pr-4"><code class="text-xs">() =&gt; void</code></td>
              <td class="py-2">Pause mutation processing. Mutations that occur while paused trigger on resume.</td>
            </tr>
            <tr class="border-b">
              <td class="py-2 pr-4"><code class="rounded bg-gray-200 px-1">onFind.resume</code></td>
              <td class="py-2 pr-4"><code class="text-xs">() =&gt; void</code></td>
              <td class="py-2">Resume mutation processing after a pause.</td>
            </tr>
            <tr>
              <td class="py-2 pr-4"><code class="rounded bg-gray-200 px-1">onFind.triggerCallbacks</code></td>
              <td class="py-2 pr-4"><code class="text-xs">(mutations?: MutationRecord[]) =&gt; void</code></td>
              <td class="py-2">Manually trigger callback evaluation for all registered selectors.</td>
            </tr>
          </tbody>
        </table>
      </div>

      <div>
        <h3 class="mb-2 font-bold">How It Works</h3>
        <p class="text-gray-700">
          onFind uses MutationObserver to efficiently watch for DOM changes. Each callback is executed only once per
          element using data attributes to track already-processed elements. The observer watches for childList
          mutations and specific attribute changes. Use <code class="rounded bg-gray-200 px-1">onFind.ignore()</code>
          to exclude containers (e.g., rich-text editors) from triggering callbacks.
        </p>
      </div>
    </div>
  `,parameters:{docs:{description:{story:"Code examples and documentation for using the onFind utility."}}}};x.parameters={...x.parameters,docs:{...x.parameters?.docs,source:{originalSource:`{
  render: args => {
    const instanceId = \`onfind-\${Math.random().toString(36).substring(2, 9)}\`;
    const uniqueSelector = \`.dynamic-item-\${instanceId}\`;
    let itemCount = 0;
    let foundCount = 0;
    const updateCounts = () => {
      const itemsEl = document.getElementById(\`\${instanceId}-items-count\`);
      const foundEl = document.getElementById(\`\${instanceId}-found-count\`);
      if (itemsEl) itemsEl.textContent = String(itemCount);
      if (foundEl) foundEl.textContent = String(foundCount);
    };

    // Set up onFind observer for dynamic items with unique selector
    onFind(uniqueSelector, (element: HTMLElement) => {
      foundCount++;
      updateCounts();
      element.classList.add('ring-2', 'ring-success-500');
    });
    const addItem = () => {
      itemCount++;
      const container = document.getElementById(\`\${instanceId}-container\`);
      if (container) {
        const item = document.createElement('div');
        item.className = \`dynamic-item-\${instanceId} rounded border bg-white p-4\`;
        item.textContent = \`Item \${itemCount}\`;
        container.appendChild(item);
      }
      updateCounts();
    };
    const clearItems = () => {
      itemCount = 0;
      foundCount = 0;
      const container = document.getElementById(\`\${instanceId}-container\`);
      if (container) {
        container.innerHTML = '';
      }
      updateCounts();
    };
    return html\`
      <div class="space-y-4">
        <div class="text-base">
          <p class="mb-2">
            Click "Add Item" to dynamically create elements. The onFind observer detects them and highlights them with a
            green border.
          </p>
        </div>

        <div class="flex gap-2">
          <button data-testid="add-item" @click=\${addItem} class="btu-button btu-button-primary btu-button-sm">
            Add Item
          </button>
          <button data-testid="clear-items" @click=\${clearItems} class="btu-button btu-button-gray btu-button-sm">
            Clear All
          </button>
        </div>

        <div id="\${instanceId}-container" class="min-h-32 space-y-2 rounded border-2 border-gray-300 bg-gray-50 p-4">
          <div class="text-sm text-gray-500">Items will appear here...</div>
        </div>

        <div class="flex justify-around">
          <div>
            <div class="text-xs text-gray-500">Items created</div>
            <div data-testid="items-count" id="\${instanceId}-items-count" class="text-2xl font-bold text-gray-900">
              0
            </div>
          </div>
          <div>
            <div class="text-xs text-gray-500">Items detected by onFind</div>
            <div data-testid="found-count" id="\${instanceId}-found-count" class="text-2xl font-bold text-primary-600">
              0
            </div>
          </div>
        </div>
      </div>
    \`;
  },
  parameters: {
    docs: {
      description: {
        story: \`Interactive example showing onFind detecting dynamically added elements. Elements are automatically highlighted when detected.\`
      }
    }
  },
  play: async ({
    canvasElement,
    step
  }) => {
    const canvas = within(canvasElement);
    await step('Detects dynamically added element', async () => {
      await userEvent.click(canvas.getByTestId('add-item'));
      await waitFor(() => expect(canvas.getByTestId('found-count')).toHaveTextContent('1'));
    });
    await step('Detects multiple elements', async () => {
      await userEvent.click(canvas.getByTestId('add-item'));
      await userEvent.click(canvas.getByTestId('add-item'));
      await waitFor(() => expect(canvas.getByTestId('found-count')).toHaveTextContent('3'));
    });
    await step('Clear resets counts', async () => {
      await userEvent.click(canvas.getByTestId('clear-items'));
      expect(canvas.getByTestId('items-count')).toHaveTextContent('0');
      expect(canvas.getByTestId('found-count')).toHaveTextContent('0');
    });
    await step('Detection resumes after clear', async () => {
      await userEvent.click(canvas.getByTestId('add-item'));
      await waitFor(() => expect(canvas.getByTestId('found-count')).toHaveTextContent('1'));
    });
  }
}`,...x.parameters?.docs?.source}}};B.parameters={...B.parameters,docs:{...B.parameters?.docs,source:{originalSource:`{
  render: () => {
    const instanceId = 'onfind-ignore-demo';
    const itemSelector = '.ignore-demo-item';
    const ignoredClass = 'ignore-demo-zone';
    let foundCount = 0;
    let itemCount = 0;
    const updateCount = () => {
      const el = document.getElementById(\`\${instanceId}-found-count\`);
      if (el) el.textContent = String(foundCount);
    };
    onFind.ignore(\`.\${ignoredClass}\`);
    onFind(itemSelector, (element: HTMLElement) => {
      foundCount++;
      updateCount();
      element.classList.add('ring-2', 'ring-success-500');
    });
    const addOutside = () => {
      itemCount++;
      const container = document.getElementById(\`\${instanceId}-outside\`);
      if (container) {
        const item = document.createElement('div');
        item.className = \`\${itemSelector.slice(1)} rounded border bg-white p-4\`;
        item.textContent = \`Outside \${itemCount}\`;
        container.appendChild(item);
      }
    };
    const addInside = () => {
      itemCount++;
      const container = document.getElementById(\`\${instanceId}-inside\`);
      if (container) {
        const item = document.createElement('div');
        item.className = \`\${itemSelector.slice(1)} rounded border bg-white p-4\`;
        item.textContent = \`Inside \${itemCount}\`;
        container.appendChild(item);
      }
    };
    return html\`
      <div class="space-y-4">
        <p class="text-base">
          Elements added inside the <strong>ignored zone</strong> are skipped by onFind callbacks. Elements added
          outside are detected normally.
        </p>

        <div class="flex gap-2">
          <button data-testid="add-outside" @click=\${addOutside} class="btu-button btu-button-primary btu-button-sm">
            Add Outside
          </button>
          <button data-testid="add-inside" @click=\${addInside} class="btu-button btu-button-gray btu-button-sm">
            Add Inside Ignored
          </button>
        </div>

        <div class="grid grid-cols-2 gap-4">
          <div>
            <div class="mb-1 text-xs font-semibold text-gray-500">Normal zone</div>
            <div id="\${instanceId}-outside" class="min-h-32 space-y-2 rounded border-2 border-gray-300 bg-gray-50 p-4">
              <div class="text-sm text-gray-400">Items detected here</div>
            </div>
          </div>
          <div>
            <div class="mb-1 text-xs font-semibold text-gray-500">Ignored zone</div>
            <div
              id="\${instanceId}-inside"
              class="\${ignoredClass} border-red-300 bg-red-50 min-h-32 space-y-2 rounded border-2 p-4"
            >
              <div class="text-sm text-gray-400">Items ignored here</div>
            </div>
          </div>
        </div>

        <div>
          <div class="text-xs text-gray-500">Items detected by onFind</div>
          <div
            data-testid="ignore-found-count"
            id="\${instanceId}-found-count"
            class="text-2xl font-bold text-primary-600"
          >
            0
          </div>
        </div>
      </div>
    \`;
  },
  parameters: {
    docs: {
      description: {
        story: \`Demonstrates \\\`onFind.ignore()\\\` — elements inside ignored containers are excluded from callback processing. Useful for skipping rich-text editors or other zones where DOM mutations should not trigger component initialization.\`
      }
    }
  },
  play: async ({
    canvasElement,
    step
  }) => {
    const canvas = within(canvasElement);
    await step('Detects outside ignored zone', async () => {
      await userEvent.click(canvas.getByTestId('add-outside'));
      await waitFor(() => expect(canvas.getByTestId('ignore-found-count')).toHaveTextContent('1'));
    });
    await step('Skips inside ignored zone', async () => {
      await userEvent.click(canvas.getByTestId('add-inside'));
      // Wait a frame to ensure mutation observer has processed
      await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve)));
      expect(canvas.getByTestId('ignore-found-count')).toHaveTextContent('1');
    });
    await step('Continues detecting outside', async () => {
      await userEvent.click(canvas.getByTestId('add-outside'));
      await waitFor(() => expect(canvas.getByTestId('ignore-found-count')).toHaveTextContent('2'));
    });
  }
}`,...B.parameters?.docs?.source}}};I.parameters={...I.parameters,docs:{...I.parameters?.docs,source:{originalSource:`{
  render: () => {
    const instanceId = 'onfind-pause-demo';
    const itemSelector = '.pause-demo-item';
    let foundCount = 0;
    let itemCount = 0;
    const updateCount = () => {
      const el = document.getElementById(\`\${instanceId}-found-count\`);
      if (el) el.textContent = String(foundCount);
    };
    onFind(itemSelector, (element: HTMLElement) => {
      foundCount++;
      updateCount();
      element.classList.add('ring-2', 'ring-success-500');
    });
    const addItem = () => {
      itemCount++;
      const container = document.getElementById(\`\${instanceId}-container\`);
      if (container) {
        const item = document.createElement('div');
        item.className = \`\${itemSelector.slice(1)} rounded border bg-white p-4\`;
        item.textContent = \`Item \${itemCount}\`;
        container.appendChild(item);
      }
    };
    let paused = false;
    const togglePause = () => {
      paused = !paused;
      if (paused) {
        onFind.pause();
      } else {
        onFind.resume();
      }
      const btn = document.querySelector('[data-testid="toggle-pause"]') as HTMLButtonElement;
      if (btn) {
        btn.textContent = paused ? 'Resume' : 'Pause';
        btn.className = paused ? 'btu-button btu-button-success btu-button-sm' : 'btu-button btu-button-warning btu-button-sm';
      }
    };
    return html\`
      <div class="space-y-4">
        <p class="text-base">
          Use <code>onFind.pause()</code> to temporarily stop detection and <code>onFind.resume()</code> to restart it.
          Elements added while paused are detected on resume.
        </p>

        <div class="flex gap-2">
          <button data-testid="pause-add" @click=\${addItem} class="btu-button btu-button-primary btu-button-sm">
            Add Item
          </button>
          <button data-testid="toggle-pause" @click=\${togglePause} class="btu-button btu-button-warning btu-button-sm">
            Pause
          </button>
        </div>

        <div id="\${instanceId}-container" class="min-h-32 space-y-2 rounded border-2 border-gray-300 bg-gray-50 p-4">
          <div class="text-sm text-gray-500">Items will appear here...</div>
        </div>

        <div>
          <div class="text-xs text-gray-500">Items detected by onFind</div>
          <div
            data-testid="pause-found-count"
            id="\${instanceId}-found-count"
            class="text-2xl font-bold text-primary-600"
          >
            0
          </div>
        </div>
      </div>
    \`;
  },
  parameters: {
    docs: {
      description: {
        story: \`Demonstrates \\\`onFind.pause()\\\` and \\\`onFind.resume()\\\`. While paused, DOM mutations are queued and processed when resumed.\`
      }
    }
  },
  play: async ({
    canvasElement,
    step
  }) => {
    const canvas = within(canvasElement);
    await step('Normal detection before pause', async () => {
      await userEvent.click(canvas.getByTestId('pause-add'));
      await waitFor(() => expect(canvas.getByTestId('pause-found-count')).toHaveTextContent('1'));
    });
    await step('Pause stops detection', async () => {
      await userEvent.click(canvas.getByTestId('toggle-pause'));
      await userEvent.click(canvas.getByTestId('pause-add'));
      // Wait enough time for normal detection to fire if it were going to
      await new Promise(resolve => setTimeout(resolve, 200));
      expect(canvas.getByTestId('pause-found-count')).toHaveTextContent('1');
    });
    await step('Resume triggers pending detection', async () => {
      await userEvent.click(canvas.getByTestId('toggle-pause'));
      // resume() does setTimeout(triggerCallbacks, 100) then rAF — needs generous timeout
      await waitFor(() => expect(canvas.getByTestId('pause-found-count')).toHaveTextContent('2'), {
        timeout: 2000
      });
    });
  }
}`,...I.parameters?.docs?.source}}};w.parameters={...w.parameters,docs:{...w.parameters?.docs,source:{originalSource:`{
  render: () => {
    const onFindA = onFind;
    const selectorA = '.singleton-item-a';
    const selectorB = '.singleton-item-b';
    let countA = 0;
    let countB = 0;
    const updateCounts = () => {
      const elA = document.getElementById('singleton-count-a');
      const elB = document.getElementById('singleton-count-b');
      if (elA) elA.textContent = String(countA);
      if (elB) elB.textContent = String(countB);
    };

    // Bundle A sets up the ignore list — Bundle B should respect it
    onFindA.ignore('.singleton-ignored-zone');

    // Bundle A registers selectorA
    onFindA(selectorA, (element: HTMLElement) => {
      countA++;
      updateCounts();
      element.classList.add('ring-2', 'ring-blue-500');
    });

    // Bundle B (separate module scope, own _state cache) registers selectorB
    onFindB(selectorB, (element: HTMLElement) => {
      countB++;
      updateCounts();
      element.classList.add('ring-2', 'ring-purple-500');
    });
    const addItem = (selector: string, label: string, zoneId: string) => {
      const container = document.getElementById(zoneId);
      if (container) {
        const item = document.createElement('div');
        item.className = \`\${selector.slice(1)} rounded border bg-white p-4\`;
        item.textContent = label;
        container.appendChild(item);
      }
    };
    let paused = false;

    // Pause/resume via Bundle A — should also affect Bundle B's callbacks
    const togglePause = () => {
      paused = !paused;
      if (paused) {
        onFindA.pause();
      } else {
        onFindA.resume();
      }
      const btn = document.querySelector('[data-testid="singleton-toggle-pause"]') as HTMLButtonElement;
      if (btn) {
        btn.textContent = paused ? 'Resume' : 'Pause';
        btn.className = paused ? 'btu-button btu-button-success btu-button-sm' : 'btu-button btu-button-warning btu-button-sm';
      }
    };
    const addIgnored = () => {
      addItem(selectorA, 'Ignored A', 'singleton-ignored');
      addItem(selectorB, 'Ignored B', 'singleton-ignored');
    };
    return html\`
      <div class="space-y-4">
        <p class="text-base">
          Two separate ES module instances of <code>onFind</code> (each with its own <code>_state</code> cache) share
          one observer, ignore list, and pause/resume state via <code>globalThis[Symbol.for()]</code>.
        </p>

        <div class="flex items-center gap-4">
          <button
            data-testid="singleton-toggle-pause"
            @click=\${togglePause}
            class="btu-button btu-button-warning btu-button-sm"
          >
            Pause
          </button>
          <div class="text-blue-600 flex items-center gap-1 text-sm">
            Bundle A:
            <span data-testid="singleton-count-a" id="singleton-count-a" class="font-bold">0</span>
            items found
          </div>
          <div class="flex items-center gap-1 text-sm text-purple-600">
            Bundle B:
            <span data-testid="singleton-count-b" id="singleton-count-b" class="font-bold">0</span>
            items found
          </div>
        </div>

        <div class="grid grid-cols-3 gap-4">
          <div>
            <div class="text-blue-600 mb-2 text-xs font-semibold">Bundle A zone</div>
            <div class="mb-2 flex gap-1">
              <button
                data-testid="singleton-add-a"
                @click=\${() => addItem(selectorA, 'Bundle A item', 'singleton-zone-a')}
                class="btu-button btu-button-primary btu-button-sm"
              >
                Add A
              </button>
              <button
                data-testid="singleton-zone-a-add-b"
                @click=\${() => addItem(selectorB, 'Bundle B item', 'singleton-zone-a')}
                class="btu-button btu-button-purple btu-button-sm"
              >
                Add B
              </button>
            </div>
            <div id="singleton-zone-a" class="border-blue-300 bg-blue-50 min-h-24 space-y-2 rounded border-2 p-4">
              <div class="text-sm text-gray-400">A items here</div>
            </div>
          </div>
          <div>
            <div class="mb-2 text-xs font-semibold text-purple-600">Bundle B zone</div>
            <div class="mb-2 flex gap-1">
              <button
                data-testid="singleton-zone-b-add-a"
                @click=\${() => addItem(selectorA, 'Bundle A item', 'singleton-zone-b')}
                class="btu-button btu-button-primary btu-button-sm"
              >
                Add A
              </button>
              <button
                data-testid="singleton-add-b"
                @click=\${() => addItem(selectorB, 'Bundle B item', 'singleton-zone-b')}
                class="btu-button btu-button-purple btu-button-sm"
              >
                Add B
              </button>
            </div>
            <div id="singleton-zone-b" class="min-h-24 space-y-2 rounded border-2 border-purple-300 bg-purple-50 p-4">
              <div class="text-sm text-gray-400">B items here</div>
            </div>
          </div>
          <div>
            <div class="text-red-600 mb-2 text-xs font-semibold">Ignored zone</div>
            <div class="mb-2 flex gap-1">
              <button
                data-testid="singleton-add-ignored"
                @click=\${addIgnored}
                class="btu-button btu-button-gray btu-button-sm"
              >
                Add A & B
              </button>
            </div>
            <div
              id="singleton-ignored"
              class="singleton-ignored-zone border-red-300 bg-red-50 min-h-24 space-y-2 rounded border-2 p-4"
            >
              <div class="text-sm text-gray-400">Items ignored here</div>
            </div>
          </div>
        </div>
      </div>
    \`;
  },
  parameters: {
    docs: {
      description: {
        story: \`Two independent module instances of \\\`onFind\\\` (simulating separate bundles) share a single MutationObserver, ignore list, and pause/resume state through the \\\`globalThis[Symbol.for()]\\\` singleton pattern.\`
      }
    }
  },
  play: async ({
    canvasElement,
    step
  }) => {
    const canvas = within(canvasElement);
    await step('Shared observer: Bundle A detects A items, Bundle B detects B items', async () => {
      await userEvent.click(canvas.getByTestId('singleton-add-a'));
      await waitFor(() => expect(canvas.getByTestId('singleton-count-a')).toHaveTextContent('1'));
      await userEvent.click(canvas.getByTestId('singleton-add-b'));
      await waitFor(() => expect(canvas.getByTestId('singleton-count-b')).toHaveTextContent('1'));
    });
    await step('Cross-zone detection fires correct callback', async () => {
      // Add B-selector item to zone A — should increment B count, not A
      await userEvent.click(canvas.getByTestId('singleton-zone-a-add-b'));
      await waitFor(() => expect(canvas.getByTestId('singleton-count-b')).toHaveTextContent('2'));
      expect(canvas.getByTestId('singleton-count-a')).toHaveTextContent('1');

      // Add A-selector item to zone B — should increment A count, not B
      await userEvent.click(canvas.getByTestId('singleton-zone-b-add-a'));
      await waitFor(() => expect(canvas.getByTestId('singleton-count-a')).toHaveTextContent('2'));
      expect(canvas.getByTestId('singleton-count-b')).toHaveTextContent('2');
    });
    await step('Shared ignore list: Bundle A ignore() blocks Bundle B callbacks', async () => {
      const countABefore = canvas.getByTestId('singleton-count-a').textContent;
      const countBBefore = canvas.getByTestId('singleton-count-b').textContent;
      await userEvent.click(canvas.getByTestId('singleton-add-ignored'));
      await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve)));
      expect(canvas.getByTestId('singleton-count-a')).toHaveTextContent(countABefore!);
      expect(canvas.getByTestId('singleton-count-b')).toHaveTextContent(countBBefore!);
    });
    await step('Ignore lists are merged and deduped across bundles', async () => {
      const state = (globalThis as any)[Symbol.for('brightspot.onFind')];
      const before = state.blacklist.length;

      // Bundle B ignores the same selector Bundle A already added in render()
      onFindB.ignore('.singleton-ignored-zone');
      expect(state.blacklist.length).toBe(before); // no duplicate

      // Bundle B adds a new selector — it merges into the shared list
      onFindB.ignore('.bundle-b-ignored');
      expect(state.blacklist).toContain('.singleton-ignored-zone');
      expect(state.blacklist).toContain('.bundle-b-ignored');
      expect(state.blacklist.length).toBe(before + 1);
    });
    await step('Shared pause/resume: Bundle A pause() stops Bundle B detection', async () => {
      await userEvent.click(canvas.getByTestId('singleton-toggle-pause'));
      await userEvent.click(canvas.getByTestId('singleton-add-a'));
      await userEvent.click(canvas.getByTestId('singleton-add-b'));
      await new Promise(resolve => setTimeout(resolve, 200));

      // Still at previous counts while paused
      expect(canvas.getByTestId('singleton-count-a')).toHaveTextContent('2');
      expect(canvas.getByTestId('singleton-count-b')).toHaveTextContent('2');
      await userEvent.click(canvas.getByTestId('singleton-toggle-pause'));
      await waitFor(() => expect(canvas.getByTestId('singleton-count-a')).toHaveTextContent('3'), {
        timeout: 2000
      });
      await waitFor(() => expect(canvas.getByTestId('singleton-count-b')).toHaveTextContent('3'), {
        timeout: 2000
      });
    });
    await step('No index collision on data-ofc attributes', async () => {
      const allDetected = canvasElement.querySelectorAll('.singleton-item-a, .singleton-item-b');
      const indices = new Set<string>();
      allDetected.forEach(el => {
        el.getAttributeNames().filter(name => name.startsWith('data-ofc')).forEach(name => indices.add(name));
      });
      expect(indices.size).toBeGreaterThanOrEqual(2);
    });
    await step('Singleton state: both bundles share the same globalThis object', async () => {
      const state = (globalThis as any)[Symbol.for('brightspot.onFind')];
      expect(state).toBeDefined();
      expect(state.callbacks).toBeDefined();
      expect(Array.isArray(state.callbacks)).toBe(true);
      expect(state.initialized).toBe(true);

      // Function refs are different (proving separate module scopes) but state is shared
      expect(onFind.pause).not.toBe(onFindB.pause);
      expect(onFind.resume).not.toBe(onFindB.resume);
    });
  }
}`,...w.parameters?.docs?.source}}};T.parameters={...T.parameters,docs:{...T.parameters?.docs,source:{originalSource:`{
  render: () => html\`
    <div class="space-y-4 text-sm">
      <div>
        <h3 class="mb-2 font-bold">Basic Usage</h3>
        <pre
          class="overflow-x-auto rounded bg-gray-900 p-4 text-gray-100"
        ><code>import onFind from '@brightspot/ui/util/onFind.js'

// Watch for elements globally
onFind('.my-component', (element) => {
  console.log('Found element:', element)
  // Initialize component
})

// Watch within a specific root element
const container = document.querySelector('#container')
onFind(container, '.my-widget', (element) => {
  // Initialize widget
})</code></pre>
      </div>

      <div>
        <h3 class="mb-2 font-bold">Multiple Selectors</h3>
        <pre class="overflow-x-auto rounded bg-gray-900 p-4 text-gray-100"><code>// Watch for multiple selectors at once
onFind(['.button', '.input', '.select'], (element) => {
  if (element.matches('.button')) {
    // Handle button
  } else if (element.matches('.input')) {
    // Handle input
  }
})</code></pre>
      </div>

      <div>
        <h3 class="mb-2 font-bold">Pause and Resume</h3>
        <pre class="overflow-x-auto rounded bg-gray-900 p-4 text-gray-100"><code>// Pause observations temporarily
onFind.pause()

// Make bulk DOM changes without triggering callbacks
// ...

// Resume observations
onFind.resume()</code></pre>
      </div>

      <div>
        <h3 class="mb-2 font-bold">Ignore Selectors</h3>
        <pre
          class="overflow-x-auto rounded bg-gray-900 p-4 text-gray-100"
        ><code>// Exclude elements inside matching containers from all callbacks.
// Calls are additive and shared across bundles.
onFind.ignore('.ProseMirror', '.RichTextEditor')

// Elements inside ignored containers will not trigger callbacks,
// even if they match a registered selector.</code></pre>
      </div>

      <div>
        <h3 class="mb-2 font-bold">Common Use Cases</h3>
        <ul class="list-inside list-disc space-y-1 text-gray-700">
          <li>Initialize components when they appear in the DOM</li>
          <li>Attach event listeners to dynamically created elements</li>
          <li>Enhance server-rendered content progressively</li>
          <li>Detect and respond to attribute changes</li>
          <li>Apply transformations to newly added content</li>
        </ul>
      </div>

      <div>
        <h3 class="mb-2 font-bold">Parameters</h3>
        <ul class="space-y-2">
          <li>
            <code class="rounded bg-gray-200 px-1">root</code> (ParentNode, optional): Root element to observe. Defaults
            to document.
          </li>
          <li>
            <code class="rounded bg-gray-200 px-1">selectors</code> (string | string[]): CSS selector(s) to watch for
          </li>
          <li>
            <code class="rounded bg-gray-200 px-1">fn</code> (function): Callback executed when matching elements are
            found
          </li>
        </ul>
      </div>

      <div>
        <h3 class="mb-2 font-bold">Static Methods</h3>
        <table class="w-full text-left text-sm">
          <thead>
            <tr class="border-b">
              <th class="py-2 pr-4">Method</th>
              <th class="py-2 pr-4">Signature</th>
              <th class="py-2">Description</th>
            </tr>
          </thead>
          <tbody>
            <tr class="border-b">
              <td class="py-2 pr-4"><code class="rounded bg-gray-200 px-1">onFind.ignore</code></td>
              <td class="py-2 pr-4"><code class="text-xs">(...selectors: string[]) =&gt; void</code></td>
              <td class="py-2">
                Exclude elements inside matching containers from all callbacks. Calls are additive and shared across
                bundles.
              </td>
            </tr>
            <tr class="border-b">
              <td class="py-2 pr-4"><code class="rounded bg-gray-200 px-1">onFind.pause</code></td>
              <td class="py-2 pr-4"><code class="text-xs">() =&gt; void</code></td>
              <td class="py-2">Pause mutation processing. Mutations that occur while paused trigger on resume.</td>
            </tr>
            <tr class="border-b">
              <td class="py-2 pr-4"><code class="rounded bg-gray-200 px-1">onFind.resume</code></td>
              <td class="py-2 pr-4"><code class="text-xs">() =&gt; void</code></td>
              <td class="py-2">Resume mutation processing after a pause.</td>
            </tr>
            <tr>
              <td class="py-2 pr-4"><code class="rounded bg-gray-200 px-1">onFind.triggerCallbacks</code></td>
              <td class="py-2 pr-4"><code class="text-xs">(mutations?: MutationRecord[]) =&gt; void</code></td>
              <td class="py-2">Manually trigger callback evaluation for all registered selectors.</td>
            </tr>
          </tbody>
        </table>
      </div>

      <div>
        <h3 class="mb-2 font-bold">How It Works</h3>
        <p class="text-gray-700">
          onFind uses MutationObserver to efficiently watch for DOM changes. Each callback is executed only once per
          element using data attributes to track already-processed elements. The observer watches for childList
          mutations and specific attribute changes. Use <code class="rounded bg-gray-200 px-1">onFind.ignore()</code>
          to exclude containers (e.g., rich-text editors) from triggering callbacks.
        </p>
      </div>
    </div>
  \`,
  parameters: {
    docs: {
      description: {
        story: \`Code examples and documentation for using the onFind utility.\`
      }
    }
  }
}`,...T.parameters?.docs?.source}}};const U=["Interactive","Ignore","PauseResume","Singleton","UsageExample"];export{B as Ignore,x as Interactive,I as PauseResume,w as Singleton,T as UsageExample,U as __namedExportsOrder,R as default};
