// node_modules/pure-web/src/js/auto-definer.js
async function defineWebComponents(...args) {
  let opts = {};
  if (args.length && typeof args[args.length - 1] === "object") {
    opts = args.pop() || {};
  }
  const tags = args;
  const {
    baseURL,
    mapper = (tag) => `${tag}.js`,
    onError = (tag, err) => console.error(`[defineWebComponents] ${tag}:`, err)
  } = opts;
  const base = baseURL ? new URL(
    baseURL,
    typeof location !== "undefined" ? location.href : import.meta.url
  ) : new URL("./", import.meta.url);
  const toPascal = (tag) => tag.toLowerCase().replace(/(^|-)([a-z])/g, (_, __, c) => c.toUpperCase());
  const loadOne = async (tag) => {
    try {
      if (customElements.get(tag))
        return { tag, status: "already-defined" };
      const spec = mapper(tag);
      const href = spec instanceof URL ? spec.href : new URL(spec, base).href;
      const mod = await import(href);
      const Named = mod?.default ?? mod?.[toPascal(tag)];
      if (!Named) {
        if (customElements.get(tag))
          return { tag, status: "self-defined" };
        throw new Error(
          `No export found for ${tag}. Expected default export or named export "${toPascal(
            tag
          )}".`
        );
      }
      if (!customElements.get(tag)) {
        customElements.define(tag, Named);
        return { tag, status: "defined" };
      }
      return { tag, status: "race-already-defined" };
    } catch (err) {
      onError(tag, err);
      throw err;
    }
  };
  return Promise.all(tags.map(loadOne));
}
var AutoDefiner = class {
  constructor(options = {}) {
    const {
      baseURL,
      mapper,
      onError,
      predicate = () => true,
      attributeModule = "data-module",
      root = document,
      scanExisting = true,
      debounceMs = 16,
      observeShadows = true,
      enhancers = [],
      // [{String selector, Function run(elem)}]
      patchAttachShadow = true
    } = options;
    const pending = /* @__PURE__ */ new Set();
    const inFlight = /* @__PURE__ */ new Set();
    const knownMissing = /* @__PURE__ */ new Set();
    const perTagModulePath = /* @__PURE__ */ new Map();
    const shadowObservers = /* @__PURE__ */ new WeakMap();
    const enhancerApplied = /* @__PURE__ */ new WeakMap();
    let timer = 0;
    let stopped = false;
    let restoreAttachShadow = null;
    const applyEnhancers = (element) => {
      if (!element || !enhancers.length)
        return;
      let appliedEnhancers = enhancerApplied.get(element);
      if (!appliedEnhancers) {
        appliedEnhancers = /* @__PURE__ */ new Set();
        enhancerApplied.set(element, appliedEnhancers);
      }
      for (const enhancer of enhancers) {
        if (!enhancer.selector || !enhancer.run)
          continue;
        if (appliedEnhancers.has(enhancer.selector))
          continue;
        try {
          if (element.matches && element.matches(enhancer.selector)) {
            enhancer.run(element);
            appliedEnhancers.add(enhancer.selector);
          }
        } catch (err) {
          console.warn(
            `[AutoDefiner] Error applying enhancer for selector "${enhancer.selector}":`,
            err
          );
        }
      }
    };
    const queueTag = (tag, el) => {
      if (stopped)
        return;
      if (!tag || !tag.includes("-"))
        return;
      if (customElements.get(tag))
        return;
      if (inFlight.has(tag))
        return;
      if (knownMissing.has(tag))
        return;
      if (el && el.getAttribute) {
        const override = el.getAttribute(attributeModule);
        if (override && !perTagModulePath.has(tag)) {
          perTagModulePath.set(tag, override);
        }
      }
      pending.add(tag);
      schedule();
    };
    const schedule = () => {
      if (timer)
        return;
      timer = setTimeout(flush, debounceMs);
    };
    const crawlTree = (rootNode) => {
      if (!rootNode)
        return;
      if (rootNode.nodeType === 1) {
        const el = (
          /** @type {Element} */
          rootNode
        );
        const tag = el.tagName?.toLowerCase();
        if (tag && tag.includes("-") && !customElements.get(tag) && predicate(tag, el)) {
          queueTag(tag, el);
        }
        applyEnhancers(el);
        if (observeShadows && el.shadowRoot) {
          observeShadowRoot(el.shadowRoot);
        }
      }
      if (rootNode.querySelectorAll) {
        rootNode.querySelectorAll("*").forEach((e) => {
          const t = e.tagName?.toLowerCase();
          if (t && t.includes("-") && !customElements.get(t) && predicate(t, e)) {
            queueTag(t, e);
          }
          applyEnhancers(e);
          if (observeShadows && e.shadowRoot) {
            observeShadowRoot(e.shadowRoot);
          }
        });
      }
    };
    const observeShadowRoot = (sr) => {
      if (!sr || shadowObservers.has(sr))
        return;
      crawlTree(sr);
      const mo = new MutationObserver((mutations) => {
        for (const m of mutations) {
          m.addedNodes?.forEach((n) => {
            crawlTree(n);
          });
          if (m.type === "attributes" && m.target) {
            crawlTree(m.target);
          }
        }
      });
      mo.observe(sr, {
        childList: true,
        subtree: true,
        attributes: true,
        attributeFilter: [
          attributeModule,
          ...enhancers.map((e) => e.selector).filter((s) => s.startsWith("data-"))
        ]
      });
      shadowObservers.set(sr, mo);
    };
    async function flush() {
      clearTimeout(timer);
      timer = 0;
      if (!pending.size)
        return;
      const tags = Array.from(pending);
      pending.clear();
      tags.forEach((t) => inFlight.add(t));
      try {
        const effectiveMapper = (tag) => perTagModulePath.get(tag) ?? (mapper ? mapper(tag) : `${tag}.js`);
        await defineWebComponents(...tags, {
          baseURL,
          mapper: effectiveMapper,
          onError: (tag, err) => {
            knownMissing.add(tag);
            onError?.(tag, err);
          }
        });
      } catch {
      } finally {
        tags.forEach((t) => inFlight.delete(t));
      }
    }
    const mountNode = root === document ? document.documentElement : root;
    const obs = new MutationObserver((mutations) => {
      for (const m of mutations) {
        m.addedNodes?.forEach((n) => {
          crawlTree(n);
        });
        if (m.type === "attributes" && m.target) {
          crawlTree(m.target);
        }
      }
    });
    obs.observe(mountNode, {
      childList: true,
      subtree: true,
      attributes: true,
      attributeFilter: [
        attributeModule,
        ...enhancers.map((e) => e.selector).filter((s) => s.startsWith("data-"))
      ]
    });
    if (observeShadows && patchAttachShadow && Element.prototype.attachShadow) {
      const orig = Element.prototype.attachShadow;
      Element.prototype.attachShadow = function patchedAttachShadow(init) {
        const sr = orig.call(this, init);
        if (init && init.mode === "open") {
          observeShadowRoot(sr);
          const tag = this.tagName?.toLowerCase();
          if (tag && tag.includes("-") && !customElements.get(tag)) {
            queueTag(tag, this);
          }
        }
        return sr;
      };
      restoreAttachShadow = () => Element.prototype.attachShadow = orig;
    }
    if (scanExisting) {
      crawlTree(mountNode);
    }
    return {
      stop() {
        stopped = true;
        obs.disconnect();
        if (restoreAttachShadow)
          restoreAttachShadow();
        if (timer) {
          clearTimeout(timer);
          timer = 0;
        }
        shadowObservers.forEach((mo) => mo.disconnect());
      },
      flush
    };
  }
  /**
   * Dynamically load and (idempotently) define a set of web components by tag name.
   */
  static async define(...args) {
    let opts = {};
    if (args.length && typeof args[args.length - 1] === "object") {
      opts = args.pop() || {};
    }
    const tags = args;
    const {
      baseURL,
      mapper = (tag) => `${tag}.js`,
      onError = (tag, err) => console.error(`[defineWebComponents] ${tag}:`, err)
    } = opts;
    const base = baseURL ? new URL(
      baseURL,
      typeof location !== "undefined" ? location.href : import.meta.url
    ) : new URL("./", import.meta.url);
    const toPascal = (tag) => tag.toLowerCase().replace(/(^|-)([a-z])/g, (_, __, c) => c.toUpperCase());
    const loadOne = async (tag) => {
      try {
        if (customElements.get(tag))
          return { tag, status: "already-defined" };
        const spec = mapper(tag);
        const href = spec instanceof URL ? spec.href : new URL(spec, base).href;
        const mod = await import(href);
        const Named = mod?.default ?? mod?.[toPascal(tag)];
        if (!Named) {
          if (customElements.get(tag))
            return { tag, status: "self-defined" };
          throw new Error(
            `No export found for ${tag}. Expected default export or named export "${toPascal(
              tag
            )}".`
          );
        }
        if (!customElements.get(tag)) {
          customElements.define(tag, Named);
          return { tag, status: "defined" };
        }
        return { tag, status: "race-already-defined" };
      } catch (err) {
        onError(tag, err);
        throw err;
      }
    };
    return Promise.all(tags.map(loadOne));
  }
};
export {
  AutoDefiner
};
//# sourceMappingURL=pds-auto-definer.js.map
