{"version":3,"sources":["../src/components/Icon/icon-config.ts","../src/components/Icon/Icon.tsx"],"names":["map","forwardRef","useSyncExternalStore","jsx","cn"],"mappings":"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","file":"chunk-QKFOJKVE.cjs","sourcesContent":["import type { ComponentType } from \"react\";\nimport type { IconSet } from \"./icon-config.types\";\n\ntype IconComponent = ComponentType<{ className?: string; size?: number }>;\n\nconst registry = new Map<string, IconSet>();\nlet defaultSetName = \"lucide\";\n\n/**\n * Addendum layer — icon sets consulted across EVERY lookup, after the active\n * base set but before the lucide auto-fallback, regardless of `defaultSet`.\n * This is how a brand-icon pack (e.g. `@particle-academy/fancy-brand-icons`)\n * layers in: `<Icon name=\"github\" />` resolves the brand mark on top of Lucide\n * (or any swapped base) without a `set=` query. Base set still wins; addenda\n * supplement. Empty by default ⇒ behavior unchanged.\n */\nconst addenda: IconSet[] = [];\n\n/** Register an icon set as an addendum (supplements every base set). */\nexport function registerIconAddendum(set: IconSet): void {\n  if (!addenda.includes(set)) addenda.push(set);\n}\n\nfunction resolveFromAddenda(name: string): IconComponent | null {\n  for (const set of addenda) {\n    const hit = set.resolve(name);\n    if (hit) return hit as IconComponent;\n  }\n  return null;\n}\n\nfunction kebabToPascal(str: string): string {\n  return str\n    .split(\"-\")\n    .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n    .join(\"\");\n}\n\n/**\n * Lazy lucide barrel. The auto-fallback (`<Icon name=\"…\" />` resolving ANY\n * lucide icon by kebab name) needs the whole namespace because names are\n * dynamic — un-tree-shakeable. Importing it eagerly forced all ~5400 icons\n * into react-fancy's main bundle for every consumer (~548KB). Instead we\n * dynamic-import it on first auto-resolve, so the barrel becomes a lazy chunk\n * loaded ONLY by apps that actually use `<Icon name>` with an unregistered\n * icon — never on the critical path. Consumers wanting sync resolution +\n * tree-shaking should `registerIcons({ ...named imports })` (those win and\n * never trigger the lazy load).\n */\nlet lucideModule: Record<string, IconComponent | undefined> | null = null;\nlet lucidePromise: Promise<unknown> | null = null;\nlet lucideVersion = 0;\nconst lucideListeners = new Set<() => void>();\n\nfunction ensureLucideLoaded(): void {\n  if (lucideModule || lucidePromise) return;\n  lucidePromise = import(\"lucide-react\")\n    .then((mod) => {\n      lucideModule = mod as unknown as Record<string, IconComponent | undefined>;\n      lucideVersion++;\n      for (const listener of lucideListeners) listener();\n    })\n    .catch(() => {\n      // Leave lucidePromise set so we don't hammer a failed import.\n    });\n}\n\n/** Subscribe to the lazy lucide load so `<Icon>` can re-render once it lands. */\nexport function subscribeIconResolution(listener: () => void): () => void {\n  lucideListeners.add(listener);\n  return () => lucideListeners.delete(listener);\n}\n\n/** Snapshot for useSyncExternalStore — bumps when the lucide barrel loads. */\nexport function getIconResolutionVersion(): number {\n  return lucideVersion;\n}\n\n/**\n * Fallback resolver: look up any lucide-react icon by its kebab-case name\n * without requiring the consumer to call `registerIcons()` first. Returns null\n * until the lazy barrel has loaded (the first call kicks off the import; `<Icon>`\n * re-renders via `subscribeIconResolution` when it's ready). Overrides\n * registered via `registerIcons()` still win and resolve synchronously.\n */\nfunction resolveFromLucide(name: string): IconComponent | null {\n  // SSR-deterministic: never resolve the lazily-imported lucide barrel on the\n  // server. A long-running SSR process (e.g. Inertia's node SSR daemon) loads\n  // the barrel after its first request, then renders auto-fallback lucide icons\n  // that a fresh client (barrel not yet loaded) does NOT have at hydration →\n  // React #418 (\"server HTML didn't match\"). Returning null on the server makes\n  // the server render match the client's FIRST render; the icon then appears\n  // once the client loads the barrel (via subscribeIconResolution). Registered\n  // icons + addenda (brand packs) still resolve synchronously on both sides.\n  if (typeof window === \"undefined\") return null;\n  if (!lucideModule) {\n    ensureLucideLoaded();\n    return null;\n  }\n  const pascal = kebabToPascal(name);\n  const icon = lucideModule[pascal];\n  return typeof icon === \"function\" || (icon && typeof icon === \"object\") ? (icon as IconComponent) : null;\n}\n\n/**\n * Register individual icon components by their kebab-case name.\n *\n * ```tsx\n * import { registerIcons } from \"@particle-academy/react-fancy\";\n * import { Home, Settings, Mail } from \"lucide-react\";\n *\n * registerIcons({ Home, Settings, Mail });\n * ```\n *\n * Icons are registered into the default \"lucide\" icon set and resolved\n * by the `<Icon name=\"home\" />` component using kebab-case names.\n */\nexport function registerIcons(\n  icons: Record<string, ComponentType<{ className?: string; size?: number }>>,\n): void {\n  let set = registry.get(\"lucide\");\n  if (!set) {\n    const map = new Map<string, ComponentType<{ className?: string; size?: number }>>();\n    set = {\n      resolve: (name: string) => {\n        const pascal = kebabToPascal(name);\n        return map.get(pascal) ?? null;\n      },\n      _map: map,\n    } as IconSet & { _map: Map<string, ComponentType<{ className?: string; size?: number }>> };\n    registry.set(\"lucide\", set);\n  }\n  const map = (set as IconSet & { _map: Map<string, ComponentType<{ className?: string; size?: number }>> })._map;\n  for (const [key, component] of Object.entries(icons)) {\n    map.set(key, component);\n  }\n}\n\nexport function registerIconSet(name: string, set: IconSet): void {\n  registry.set(name, set);\n}\n\nexport function configureIcons(options: { defaultSet?: string }): void {\n  if (options.defaultSet) {\n    defaultSetName = options.defaultSet;\n  }\n}\n\nexport function resolveIcon(\n  name: string,\n  setName?: string,\n): IconComponent | null {\n  const resolvedSet = setName ?? defaultSetName;\n  const set = registry.get(resolvedSet);\n  const registered = set ? set.resolve(name) : null;\n  if (registered) return registered;\n  // Addenda fill gaps after the base set, before the lucide auto-fallback — so a\n  // brand pack's `github` wins over lucide's auto-resolved one.\n  const fromAddenda = resolveFromAddenda(name);\n  if (fromAddenda) return fromAddenda;\n  if (resolvedSet === \"lucide\") return resolveFromLucide(name);\n  return null;\n}\n","import { forwardRef, useSyncExternalStore } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { resolveIcon, subscribeIconResolution, getIconResolutionVersion } from \"./icon-config\";\nimport type { IconProps } from \"./Icon.types\";\n\nconst sizeClasses: Record<NonNullable<IconProps[\"size\"]>, string> = {\n  xs: \"h-3 w-3\",\n  sm: \"h-4 w-4\",\n  md: \"h-5 w-5\",\n  lg: \"h-6 w-6\",\n  xl: \"h-8 w-8\",\n};\n\nconst sizePixels: Record<NonNullable<IconProps[\"size\"]>, number> = {\n  xs: 12,\n  sm: 16,\n  md: 20,\n  lg: 24,\n  xl: 32,\n};\n\nexport const Icon = forwardRef<HTMLSpanElement, IconProps>(\n  ({ size = \"md\", className, children, name, iconSet, ...props }, ref) => {\n    // Re-render when the lazy lucide barrel lands, so `<Icon name>` auto-resolved\n    // from lucide appears once loaded. Registered icons resolve synchronously and\n    // never trigger the lazy load. SSR snapshot is the same getter (version 0).\n    useSyncExternalStore(\n      subscribeIconResolution,\n      getIconResolutionVersion,\n      getIconResolutionVersion,\n    );\n\n    let content = children;\n\n    if (name && !children) {\n      const ResolvedIcon = resolveIcon(name, iconSet);\n      if (ResolvedIcon) {\n        content = <ResolvedIcon size={sizePixels[size]} />;\n      }\n    }\n\n    return (\n      <span\n        ref={ref}\n        aria-hidden=\"true\"\n        data-react-fancy-icon=\"\"\n        className={cn(\n          \"inline-flex items-center justify-center flex-shrink-0\",\n          sizeClasses[size],\n          className,\n        )}\n        {...props}\n      >\n        {content}\n      </span>\n    );\n  },\n);\n\nIcon.displayName = \"Icon\";\n"]}