@numueg/theme-sdk 0.2.2 → 0.3.1
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/CHANGELOG.md +29 -1
- package/README.md +8 -8
- package/dist/{entities-iiuRSPpk.d.mts → entities-6MGANln7.d.mts} +64 -1
- package/dist/{entities-iiuRSPpk.d.ts → entities-6MGANln7.d.ts} +64 -1
- package/dist/index.cjs +227 -66
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +221 -45
- package/dist/index.d.ts +221 -45
- package/dist/index.mjs +222 -68
- package/dist/index.mjs.map +1 -1
- package/dist/types.d.mts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/v2-compat.d.mts +1 -1
- package/dist/v2-compat.d.ts +1 -1
- package/package.json +3 -3
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types/theme.ts","../src/contexts/index.ts","../src/hooks/useLocalization.ts","../src/hooks/useShop.ts","../src/hooks/useProduct.ts","../src/hooks/useCollection.ts","../src/hooks/useCart.ts","../src/hooks/useCustomer.ts","../src/hooks/useThemeSettings.ts","../src/hooks/useCurrentTemplate.ts","../src/hooks/usePage.ts","../src/hooks/useSection.ts","../src/hooks/useMoney.ts","../src/hooks/useImage.ts","../src/hooks/useProducts.ts","../src/hooks/useCollections.ts","../src/contexts/customer-actions.ts","../src/hooks/useCustomerActions.ts","../src/hooks/useOrders.ts","../src/hooks/useCustomerAddresses.ts","../src/hooks/useNavigation.ts","../src/hooks/useSearch.ts","../src/hooks/useAnalytics.ts","../src/hooks/useApp.ts","../src/hooks/useWishlist.ts","../src/hooks/useRelatedProducts.ts","../src/hooks/useCurrency.ts","../src/utils/variants.ts","../src/hooks/useVariantSelection.ts","../src/hooks/useGiftCardBalance.ts","../src/hooks/useReorder.ts","../src/hooks/useCheckout.ts","../src/hooks/useShippingRates.ts","../src/components/NuMuProvider.tsx","../src/components/ProductProvider.tsx","../src/utils/styleTokens.ts","../src/mount.tsx","../src/components/CollectionProvider.tsx","../src/components/Money.tsx","../src/components/Image.tsx","../src/components/Link.tsx","../src/components/AddToCartButton.tsx","../src/components/Section.tsx","../src/components/Form.tsx","../src/components/ProductCard.tsx","../src/components/CollectionCard.tsx","../src/components/RichText.tsx","../src/components/CurrencySwitcher.tsx","../src/components/LocaleSwitcher.tsx","../src/components/Editable.tsx","../src/components/Icon.tsx","../src/utils/normalize.ts","../src/utils/federation.ts","../src/utils/dynamicSources.ts","../src/hooks/useResolvedSettings.ts","../src/utils/defineSection.ts","../src/utils/assetUrl.ts","../src/utils/imageTransform.ts","../src/utils/locales.ts"],"names":["useContext","createContext","useMemo","useState","useEffect","unwrap","useCallback","opts","useRef","jsx","ThemeMountBridge","DEFAULT_WIDTHS","ABSOLUTE_URL","readCsrfCookie","jsxs","joinClass","Fragment","forwardRef","EditableText","Component","EditableImage"],"mappings":"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","file":"index.mjs","sourcesContent":["/** V3 Theme Settings — the canonical data shape */\nexport interface ThemeSettingsV3 {\n schema_version: 3;\n theme_id: string;\n global_settings: Record<string, any>;\n templates: Record<string, PageTemplate>;\n section_groups: Record<string, SectionGroup>;\n external_theme?: ExternalThemeMetadata | null;\n}\n\nexport interface PageTemplate {\n name: string;\n sections: Record<string, SectionInstance>;\n order: string[];\n}\n\nexport interface SectionGroup {\n name: string;\n sections: Record<string, SectionInstance>;\n order: string[];\n}\n\nexport interface SectionInstance {\n type: string;\n settings: Record<string, any>;\n disabled?: boolean;\n blocks?: Record<string, BlockInstance>;\n block_order?: string[];\n}\n\nexport interface BlockInstance {\n type: string;\n settings: Record<string, any>;\n disabled?: boolean;\n /** Nested child blocks (blocks-in-blocks): a block can hold its own\n * block container — e.g. a footer \"column\" holding \"link\" blocks, or\n * a mega-menu. Same shape as a section's block container, so the\n * render/editor walk is uniform at any depth. Optional + absent on\n * leaf blocks, so pre-nesting payloads load unchanged. */\n blocks?: Record<string, BlockInstance>;\n block_order?: string[];\n}\n\nexport interface ExternalThemeMetadata {\n bundle_url: string;\n css_url?: string | null;\n mode?: string;\n settings_schema?: Record<string, any> | null;\n section_schemas?: Record<string, any> | null;\n}\n\n/**\n * Live mount handle returned by a V3 theme bundle's `mount(el, ctx)`.\n *\n * Two shapes accepted by the host:\n *\n * 1. **Legacy** — `mount(el, ctx): () => void`\n * The bundle returns only a cleanup function. Every host-side\n * themeSettings change forces a full unmount + remount, which is\n * expensive but always correct. Hosts must keep supporting this\n * for older bundles built against pre-0.2 SDK versions.\n *\n * 2. **Wave 3+** — `mount(el, ctx): MountResult`\n * The bundle returns an object with `cleanup` + an `applyDraft`\n * method that takes a fresh `ThemeSettingsV3` and re-renders the\n * bundle's React tree in-place (no createRoot churn). This is the\n * fast path used by the customizer's live preview — a keystroke\n * in the dashboard becomes a single React reconciliation in the\n * iframe, typically < 16 ms.\n *\n * Hosts feature-detect by checking `typeof handle === \"function\"`\n * (legacy) vs `typeof handle === \"object\" && handle.cleanup`\n * (Wave 3+). Theme authors should prefer the MountResult shape — the\n * `numuTheme` plugin's typings will flag the missing applyDraft once\n * the editor's live-preview path requires it.\n */\nexport interface MountResult {\n /** Unmount the bundle's React tree and release any resources. */\n cleanup: () => void;\n /**\n * Apply a fresh draft (e.g. from the customizer iframe's\n * `numu:theme:update` postMessage) without tearing down the tree.\n * Implementations typically forward the value to a useState setter\n * inside a wrapper that renders `<NuMuProvider themeSettings={...}>`.\n *\n * Safe to call repeatedly; the bundle is expected to dedup\n * reference-equal calls on its own. Returns nothing — selection /\n * navigation echo back via postMessage.\n */\n applyDraft: (next: ThemeSettingsV3) => void;\n}\n\n/** Section schema for customizer form generation */\nexport interface SectionSchema {\n type: string;\n name: string;\n name_ar?: string;\n tag?: string;\n class?: string;\n limit?: number;\n settings: SettingDefinition[];\n blocks?: BlockSchema[];\n max_blocks?: number;\n presets?: SectionPreset[];\n}\n\nexport interface BlockSchema {\n type: string;\n name: string;\n name_ar?: string;\n limit?: number;\n settings: SettingDefinition[];\n /** Child block types this block accepts (recursive). When present,\n * the customizer lets merchants add/remove/reorder these inside the\n * block, up to `max_blocks`. Enables footer columns, mega-menus,\n * multi-column layouts. The host caps practical nesting depth\n * (MAX_BLOCK_DEPTH). */\n blocks?: BlockSchema[];\n max_blocks?: number;\n}\n\n/** Max nesting depth the customizer allows for blocks-in-blocks. Depth\n * 1 = a top-level block in a section; a block at this depth can't take\n * children. Generous (below Shopify's 8) and cheap to raise. Kept in\n * sync with the merchant hub's MAX_BLOCK_DEPTH. */\nexport const MAX_BLOCK_DEPTH = 5;\n\n/**\n * Setting types the V3 customizer renders. Themes can declare any\n * string here; unknown types fall through to a plain text input. The\n * union below documents the canonical set so theme authors get\n * autocomplete and TypeScript errors on typos.\n */\nexport type SettingType =\n | \"text\"\n | \"textarea\"\n | \"richtext\"\n | \"number\"\n | \"range\"\n | \"color\"\n | \"checkbox\"\n | \"select\"\n | \"radio\"\n | \"font\"\n | \"image_picker\"\n | \"url\"\n | \"product\"\n | \"product_list\"\n | \"collection\"\n | \"collection_list\"\n | \"header\"\n | \"paragraph\"\n | \"html\"\n | \"date\"\n | \"time\"\n | \"video_picker\"\n | \"color_scheme\"\n | \"page_picker\"\n | \"blog_picker\"\n | \"link_list_picker\"\n | \"variant_picker\"\n | \"file_upload\"\n | \"icon_picker\"\n | \"icon\";\n\n/**\n * `visible_if` — conditional visibility expression evaluated against\n * sibling settings in the same schema. Two flavors:\n *\n * - String DSL: `\"settings.show_button == true && settings.layout != 'minimal'\"`\n * - Object form: `{ show_button: true, layout: [\"full\", \"split\"] }`\n *\n * Evaluator lives in the merchant hub: any setting whose expression is\n * falsy is skipped from the rendered form.\n */\nexport type VisibleIf = string | Record<string, unknown>;\n\nexport interface SettingDefinition {\n type: SettingType | (string & {}); // unions stay open for forward-compat\n id: string;\n label: string;\n label_ar?: string;\n default?: any;\n info?: string;\n info_ar?: string;\n placeholder?: string;\n options?: { value: string; label: string; label_ar?: string }[];\n min?: number;\n max?: number;\n step?: number;\n unit?: string;\n /** Hide this setting unless the expression evaluates truthy. */\n visible_if?: VisibleIf;\n}\n\nexport interface PresetBlock {\n type: string;\n settings?: Record<string, any>;\n /** Nested starter blocks materialized when the preset is applied\n * (recursive). Lets a preset ship, e.g., a footer column already\n * populated with link blocks. */\n blocks?: PresetBlock[];\n}\n\nexport interface SectionPreset {\n name: string;\n /** Localized names so the Add Section dialog reads in the editor's\n * current locale. Falls back to `name` when the locale is missing. */\n locales?: {\n en?: { name?: string };\n ar?: { name?: string };\n };\n settings?: Record<string, any>;\n blocks?: PresetBlock[];\n}\n\n/** Section component props */\nexport interface SectionProps {\n settings: Record<string, any>;\n blocks?: Record<string, BlockInstance>;\n blockOrder?: string[];\n storeData?: any;\n}\n\n/** Block component props */\nexport interface BlockProps {\n settings: Record<string, any>;\n /** Child block instances when this block nests others (footer column,\n * mega-menu, …). Mirror the section→block render: map `blockOrder`\n * and look each id up in `blocks`, wrapping each child in `<Block>`. */\n blocks?: Record<string, BlockInstance>;\n blockOrder?: string[];\n}\n","\"use client\";\nimport { createContext } from \"react\";\nimport type { Store, Product, Collection, Cart, Customer, Page } from \"../types/entities\";\nimport type { ThemeSettingsV3 } from \"../types/theme\";\n\nexport interface LocalizationState {\n locale: string;\n direction: \"ltr\" | \"rtl\";\n translations: Record<string, string>;\n formatMoney: (amount: number, currency?: string) => string;\n formatDate: (date: string | Date) => string;\n /**\n * Phase 3.7 — locale-aware number formatter. Routes to either\n * Western (1234) or Arab-Indic (١٢٣٤) digits depending on\n * `store.settings.numerals`. Themes calling formatMoney get the\n * same digit choice automatically; this is for raw counts (\"12 items\").\n */\n formatNumber: (n: number, options?: Intl.NumberFormatOptions) => string;\n /**\n * Phase 3.6 — switch the active locale.\n *\n * Sets the `numu_locale` cookie and triggers a full page reload so\n * the server-rendered layout picks up the new locale (the storefront\n * resolves locale at SSR time from cookie/query). Returns once the\n * cookie is written; the page navigation cancels any pending React\n * work so callers don't need to await.\n */\n setLocale: (next: string) => void;\n /**\n * Phase 3.6 — list of locales the store advertises. Empty when the\n * store hasn't configured a multi-locale catalog. Themes use this\n * to decide whether to render the LocaleSwitcher at all.\n */\n availableLocales: string[];\n}\n\nexport const ShopContext = createContext<Store | null>(null);\nexport const ProductContext = createContext<Product | null>(null);\nexport const CollectionContext = createContext<Collection | null>(null);\nexport const CartContext = createContext<{ cart: Cart; addItem: (productId: string, variantId?: string, quantity?: number) => Promise<void>; removeItem: (itemId: string) => Promise<void>; updateQuantity: (itemId: string, quantity: number) => Promise<void>; applyDiscount: (code: string) => Promise<void>; removeDiscount: () => Promise<void>; updateNote: (note: string) => Promise<void>; clearCart: () => Promise<void>; loading: boolean } | null>(null);\nexport const CustomerContext = createContext<Customer | null>(null);\nexport const ThemeSettingsContext = createContext<ThemeSettingsV3 | null>(null);\nexport const LocalizationContext = createContext<LocalizationState | null>(null);\nexport const PageContext = createContext<Page | null>(null);\n/**\n * Wave 5 — currently-active template identifier. Mirrors the key inside\n * `themeSettings.templates.<currentTemplate>` so themes can dispatch\n * which section list to render. Hosts set this via `NuMuProvider`'s\n * `currentTemplate` prop (which is passed in by the storefront page\n * component — `app/(store)/[subdomain]/product/[id]/page.tsx` passes\n * \"product\", `cart/page.tsx` passes \"cart\", etc.). Falls back to \"home\".\n */\nexport const CurrentTemplateContext = createContext<string>(\"home\");\n\n/**\n * A merchant-managed navigation menu item, exactly as the storefront\n * menus resolver returns it (`GET /storefront/store/{id}/menus`):\n * bilingual `label`, a pre-resolved `url`, and nested `children`.\n *\n * This is the RAW shape the host injects via `NuMuProvider`'s\n * `navigation` prop. `useNavigation(handle)` localizes it to the\n * display-ready `NavigationItem` (a single `title` string for the\n * active locale).\n */\nexport interface MenuItemData {\n id: string;\n label: Record<string, string>;\n url: string;\n type?: string | null;\n resource_id?: string | null;\n children?: MenuItemData[];\n}\n\n/**\n * Phase 2.4 — navigation menus keyed by handle (`main-menu`, `footer`,\n * plus custom), injected by the host from the storefront resolver so a\n * theme's `useNavigation(handle)` resolves without a client round-trip.\n *\n * Defaults to `{}` — an empty map signals \"host provided no menus\", at\n * which point `useNavigation` falls back to its own fetch / a theme's\n * `DEFAULT_NAV`. A present-but-handle-absent map means the menu simply\n * doesn't exist (render nothing / fallback), no fetch attempted.\n */\nexport const NavigationContext = createContext<Record<string, MenuItemData[]>>(\n {},\n);\n","import { useContext } from \"react\";\nimport { LocalizationContext } from \"../contexts\";\nimport type { LocalizationState } from \"../contexts\";\n\nexport function useLocalization(): LocalizationState {\n const ctx = useContext(LocalizationContext);\n if (!ctx) throw new Error(\"useLocalization must be used within NuMuProvider\");\n return ctx;\n}\n\nexport function useDirection(): \"ltr\" | \"rtl\" {\n const { direction } = useLocalization();\n return direction;\n}\n\nexport function useLocale(): string {\n const { locale } = useLocalization();\n return locale;\n}\n\nexport function useTranslation() {\n const { translations, locale } = useLocalization();\n return {\n t: (key: string, fallback?: string) => translations[key] || fallback || key,\n locale,\n };\n}\n\n/**\n * Phase 3.6 — pull a translated field off a domain object.\n *\n * Convention: per-product translations live on `entity.attributes`\n * keyed as `<field>_<locale>` — e.g. `name_ar`, `description_ar`.\n * Backend writes these via the merchant hub when a merchant turns on\n * \"Translations\" for a product. Themes call:\n *\n * const productName = useFieldTranslation(product, \"name\");\n *\n * and get the Arabic name when the active locale is \"ar\", falling\n * back to the English `product.name` otherwise. Works for any object\n * that pairs a base field on the entity with an `attributes` JSONB\n * blob holding the translated variants.\n *\n * Why not put translations on the entity itself? Adding `name_ar`,\n * `description_ar`, `name_he`, etc. as first-class columns means a\n * schema migration every time a merchant enables a new locale. JSONB\n * lets the merchant flip locales on/off in settings without touching\n * the table.\n */\nexport function useFieldTranslation<\n T extends { attributes?: Record<string, unknown> },\n>(entity: T | null | undefined, field: string): string | undefined {\n const { locale } = useLocalization();\n if (!entity) return undefined;\n // English (or whichever default locale the merchant configured) is\n // stored as the base field; non-default locales live on attributes\n // with a `<field>_<locale>` key.\n const translated =\n entity.attributes && typeof entity.attributes === \"object\"\n ? (entity.attributes as Record<string, unknown>)[`${field}_${locale}`]\n : undefined;\n if (typeof translated === \"string\" && translated) return translated;\n // Base field — supports any value type that stringifies sensibly.\n const base = (entity as unknown as Record<string, unknown>)[field];\n if (typeof base === \"string\") return base;\n if (base == null) return undefined;\n return String(base);\n}\n\n/**\n * Phase 3.7 — formatted-number hook.\n *\n * Themes that need to render counts (\"12 items\", \"3 reviews\") should\n * route through this hook so Arab-Indic digits (٠١٢٣٤) vs Western\n * (01234) stay consistent with money + date elsewhere on the page.\n *\n * const fmtNum = useNumberFormat();\n * fmtNum(12) → \"12\" (or \"١٢\" for Arabic stores)\n * fmtNum(12.5, { minimumFractionDigits: 2 }) → \"12.50\" / \"١٢٫٥٠\"\n */\nexport function useNumberFormat() {\n const { formatNumber } = useLocalization();\n return formatNumber;\n}\n","\"use client\";\nimport { useContext, useMemo } from \"react\";\nimport { ShopContext } from \"../contexts\";\nimport { useLocale } from \"./useLocalization\";\nimport type { Store } from \"../types/entities\";\n\n/**\n * Augmented Store shape returned from useShop().\n *\n * Adds a couple of conveniences theme devs reach for constantly:\n * - `domain` — the active hostname (subdomain or custom). Resolved\n * from `store.domain ?? store.subdomain ?? store.slug`.\n * - `formatUrl(path)` — emits a fully-qualified URL using `domain`.\n * Theme code that needs to render absolute URLs (canonical tags,\n * Open Graph, JSON-LD) goes through this so dev/prod / subdomain\n * vs. custom-domain stays correct without each theme reinventing\n * the resolver.\n */\nexport interface ShopWithHelpers extends Store {\n /** Fully-qualified hostname this store currently serves on. */\n domain: string;\n /**\n * Format a path (relative or absolute) as a fully-qualified URL on\n * this store's domain. No-ops when given an already-absolute URL.\n *\n * Phase 6 — when the active locale is non-default and the store\n * has opted into locale URL prefixes, the path is prefixed with\n * `/{locale}/` (e.g. `/ar/products/foo`). Already-prefixed paths\n * are left alone so calling `formatUrl(formatUrl(...))` is safe.\n */\n formatUrl(path: string): string;\n}\n\nconst DEFAULT_PROTOCOL =\n typeof window !== \"undefined\"\n ? window.location.protocol.replace(\":\", \"\")\n : \"https\";\n\nfunction resolveDomain(store: Store): string {\n // Custom domain wins when set; otherwise fall back to the platform\n // subdomain. The slug is a last resort for stores that haven't been\n // assigned either yet (mostly demo stores in dev).\n if (store.domain) return store.domain;\n if (store.subdomain) {\n // The platform-domain default lives on the storefront; theme code\n // doesn't have access to env vars, so we read it off the runtime\n // window object when present and fall back to the well-known\n // production value. Themes can override by rendering with\n // `<meta name=\"numu:platform-domain\" content=\"...\">` if they're\n // hosted on a non-default platform.\n const platform =\n (typeof window !== \"undefined\" &&\n (window as unknown as { __NUMU_PLATFORM_DOMAIN?: string })\n .__NUMU_PLATFORM_DOMAIN) ||\n \"numueg.app\";\n return `${store.subdomain}.${platform}`;\n }\n return store.slug;\n}\n\nexport function useShop(): ShopWithHelpers {\n const ctx = useContext(ShopContext);\n if (!ctx) throw new Error(\"useShop must be used within NuMuProvider\");\n const locale = useLocale();\n\n return useMemo(() => {\n const domain = resolveDomain(ctx);\n const settings = (ctx as Store & { settings?: Record<string, unknown> })\n .settings;\n const localePrefixEnabled = Boolean(\n settings && (settings as { locale_url_prefix_enabled?: boolean }).locale_url_prefix_enabled,\n );\n const defaultLocale = ctx.default_language || \"en\";\n // List of locales that get a URL prefix. Defaults to \"everything\n // except the default\" — but a store can opt into `[\"ar\", \"en\"]`\n // (prefix even the default) if it wants a fully prefixed URL\n // scheme like Shopify does for markets.\n const prefixedLocales =\n (settings as { locale_url_prefix_locales?: string[] } | undefined)\n ?.locale_url_prefix_locales || null;\n const shouldPrefix = (l: string): boolean => {\n if (!localePrefixEnabled) return false;\n if (prefixedLocales) return prefixedLocales.includes(l);\n return l !== defaultLocale;\n };\n\n const formatUrl = (path: string): string => {\n if (!path) return `${DEFAULT_PROTOCOL}://${domain}/`;\n // Already absolute? Hand back as-is.\n if (/^https?:\\/\\//i.test(path)) return path;\n // Protocol-relative — assume same protocol as the host.\n if (path.startsWith(\"//\")) return `${DEFAULT_PROTOCOL}:${path}`;\n let normalized = path.startsWith(\"/\") ? path : `/${path}`;\n if (locale && shouldPrefix(locale)) {\n // Idempotent: don't double-prefix if the caller already\n // gave us a /{locale}/... path.\n const prefix = `/${locale}/`;\n const root = `/${locale}`;\n if (normalized !== root && !normalized.startsWith(prefix)) {\n normalized = `${root}${normalized}`;\n }\n }\n return `${DEFAULT_PROTOCOL}://${domain}${normalized}`;\n };\n return { ...ctx, domain, formatUrl };\n }, [ctx, locale]);\n}\n","import { useContext } from \"react\";\nimport { ProductContext } from \"../contexts\";\nimport type { Product } from \"../types/entities\";\n\nexport function useProduct(): Product {\n const ctx = useContext(ProductContext);\n if (!ctx) throw new Error(\"useProduct must be used within ProductProvider\");\n return ctx;\n}\n\nexport function useProductOptional(): Product | null {\n return useContext(ProductContext);\n}\n","import { useContext } from \"react\";\nimport { CollectionContext } from \"../contexts\";\nimport type { Collection } from \"../types/entities\";\n\nexport function useCollection(): Collection {\n const ctx = useContext(CollectionContext);\n if (!ctx) throw new Error(\"useCollection must be used within CollectionProvider\");\n return ctx;\n}\n\nexport function useCollectionOptional(): Collection | null {\n return useContext(CollectionContext);\n}\n","import { useContext } from \"react\";\nimport { CartContext } from \"../contexts\";\n\nexport function useCart() {\n const ctx = useContext(CartContext);\n if (!ctx) throw new Error(\"useCart must be used within NuMuProvider\");\n return ctx;\n}\n","import { useContext } from \"react\";\nimport { CustomerContext } from \"../contexts\";\nimport type { Customer } from \"../types/entities\";\n\nexport function useCustomer(): Customer | null {\n return useContext(CustomerContext);\n}\n","import { useContext } from \"react\";\nimport { ThemeSettingsContext } from \"../contexts\";\nimport type { ThemeSettingsV3 } from \"../types/theme\";\n\nexport function useThemeSettings(): ThemeSettingsV3 {\n const ctx = useContext(ThemeSettingsContext);\n if (!ctx) throw new Error(\"useThemeSettings must be used within NuMuProvider\");\n return ctx;\n}\n","\"use client\";\n\nimport { useContext } from \"react\";\nimport { CurrentTemplateContext } from \"../contexts\";\n\n/**\n * useCurrentTemplate — read the active page template's id.\n *\n * Values are the same strings used as keys in\n * `themeSettings.templates.<id>`:\n *\n * \"home\" | \"product\" | \"collection\" | \"cart\" | \"checkout\"\n * \"order-confirmation\" | \"profile\" | \"page\" | \"404\" | \"password\"\n *\n * Themes use this to render the matching section list:\n *\n * const template = useCurrentTemplate();\n * const settings = useThemeSettings();\n * const sections = settings.templates?.[template]?.sections ?? {};\n *\n * Default: \"home\" — when the host hasn't supplied a CurrentTemplate\n * provider, themes still render their home template instead of\n * crashing or showing a blank screen.\n *\n * The hook is read-only; the active template changes via the host\n * navigating between Next.js routes (each route's `page.tsx` wraps\n * its content with the correct currentTemplate at the\n * `<NuMuProvider currentTemplate=\"…\">` prop).\n */\nexport function useCurrentTemplate(): string {\n return useContext(CurrentTemplateContext);\n}\n","import { useContext } from \"react\";\nimport { PageContext } from \"../contexts\";\nimport type { Page } from \"../types/entities\";\n\nexport function usePage(): Page | null {\n return useContext(PageContext);\n}\n","import { createContext, useContext } from \"react\";\nimport type { SectionInstance } from \"../types/theme\";\n\nexport const SectionContext = createContext<SectionInstance | null>(null);\n\nexport function useSection(): SectionInstance {\n const ctx = useContext(SectionContext);\n if (!ctx) throw new Error(\"useSection must be used within a section component\");\n return ctx;\n}\n\nexport function useSectionOptional(): SectionInstance | null {\n return useContext(SectionContext);\n}\n","\"use client\";\n\nimport { useLocalization } from \"./useLocalization\";\nimport { useShop } from \"./useShop\";\n\n/**\n * useMoney — convenience hook that returns a stable formatter bound to\n * the active store's currency.\n *\n * Useful when a section needs to format multiple amounts in a render:\n *\n * const money = useMoney();\n * return <td>{money(item.price * item.quantity)}</td>\n *\n * For one-off price displays prefer the <Money> component which handles\n * compare-at and inline rendering.\n */\nexport function useMoney(currencyOverride?: string) {\n const { formatMoney } = useLocalization();\n const shop = useShop();\n const ccy = currencyOverride || shop?.currency;\n return (amount: number) => formatMoney(amount, ccy);\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\n\ninterface UseImageOptions {\n /** Sizes attribute (CSS sizes form). */\n sizes?: string;\n /** Widths to generate in srcSet. Falsy → use defaults. */\n widths?: number[];\n /** Pass-through alt text — useImage doesn't render anything; the\n * caller does. */\n alt?: string;\n}\n\ninterface ImageDescriptor {\n src: string | null;\n srcSet: string | null;\n sizes: string;\n alt: string;\n}\n\nconst DEFAULT_WIDTHS = [320, 480, 640, 768, 1024, 1280, 1600, 1920];\nconst DEFAULT_SIZES =\n \"(min-width: 1024px) 25vw, (min-width: 640px) 50vw, 100vw\";\n\n/**\n * useImage — returns srcSet/sizes for a CDN-served image so themes\n * don't have to hand-roll responsive image markup. Pairs with the\n * <Image> component, but is also useful when the theme wants to render\n * something other than a plain `<img>` (e.g., `<picture>` with art\n * direction or a CSS `background-image` via inline style).\n *\n * Returns `null` srcSet if the source URL already encodes a width\n * directive (theme author opted out of auto-sizing).\n */\nexport function useImage(\n src: string | null | undefined,\n opts: UseImageOptions = {},\n): ImageDescriptor {\n const { sizes = DEFAULT_SIZES, widths = DEFAULT_WIDTHS, alt = \"\" } = opts;\n return useMemo(() => {\n if (!src) return { src: null, srcSet: null, sizes, alt };\n if (/[?&]w=\\d+/.test(src)) return { src, srcSet: null, sizes, alt };\n const sep = src.includes(\"?\") ? \"&\" : \"?\";\n const srcSet = widths.map((w) => `${src}${sep}w=${w} ${w}w`).join(\", \");\n return { src, srcSet, sizes, alt };\n }, [src, sizes, widths, alt]);\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { usePage } from \"./usePage\";\nimport { useShop } from \"./useShop\";\nimport type { Product } from \"../types/entities\";\n\ninterface UseProductsOptions {\n /** Limit the slice returned. Defaults to whatever the host gave us. */\n limit?: number;\n /**\n * When true, fetch from `/api/products` if the host didn't provide a\n * list via PageContext. Useful for sections rendered on routes that\n * don't pre-fetch products (e.g. a custom CMS page that wants a\n * \"featured\" rail). Default: false — themes typically prefer SSR data.\n */\n fetchIfMissing?: boolean;\n}\n\ninterface UseProductsResult {\n products: Product[];\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * useProducts — read the storefront-pre-fetched product list from the\n * page context, optionally falling back to a client-side fetch.\n *\n * The SSR path passes `page.data.products: Product[]` from\n * `numu-storefront/src/app/[domain]/page.tsx`; sections on the home\n * route get them for free. For other routes that don't pre-fetch, set\n * `fetchIfMissing: true` and we'll hit `/api/products`.\n */\nexport function useProducts(\n opts: UseProductsOptions = {},\n): UseProductsResult {\n const { limit, fetchIfMissing = false } = opts;\n const page = usePage();\n const shop = useShop();\n const initial = (page?.data?.products as Product[] | undefined) ?? null;\n\n const [products, setProducts] = useState<Product[]>(initial ?? []);\n const [loading, setLoading] = useState<boolean>(\n initial == null && fetchIfMissing,\n );\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n if (initial != null) return;\n if (!fetchIfMissing) return;\n if (!shop?.id) return;\n let cancelled = false;\n (async () => {\n try {\n const params = new URLSearchParams({ store_id: shop.id });\n if (limit) params.set(\"limit\", String(limit));\n const res = await fetch(`/api/products?${params.toString()}`);\n if (!res.ok) throw new Error(`/api/products → ${res.status}`);\n const data = (await res.json()) as { products?: Product[] };\n if (cancelled) return;\n setProducts(data.products ?? []);\n setLoading(false);\n } catch (err) {\n if (cancelled) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [initial, fetchIfMissing, limit, shop?.id]);\n\n const sliced = limit != null ? products.slice(0, limit) : products;\n return { products: sliced, loading, error };\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { usePage } from \"./usePage\";\nimport { useShop } from \"./useShop\";\nimport type { Collection } from \"../types/entities\";\n\ninterface UseCollectionsOptions {\n limit?: number;\n fetchIfMissing?: boolean;\n}\n\ninterface UseCollectionsResult {\n collections: Collection[];\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * useCollections — analog to useProducts. Reads page.data.collections\n * pre-fetched by the storefront SSR; falls back to /api/collections\n * when fetchIfMissing is true.\n */\nexport function useCollections(\n opts: UseCollectionsOptions = {},\n): UseCollectionsResult {\n const { limit, fetchIfMissing = false } = opts;\n const page = usePage();\n const shop = useShop();\n const initial = (page?.data?.collections as Collection[] | undefined) ?? null;\n\n const [collections, setCollections] = useState<Collection[]>(initial ?? []);\n const [loading, setLoading] = useState<boolean>(\n initial == null && fetchIfMissing,\n );\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n if (initial != null) return;\n if (!fetchIfMissing) return;\n if (!shop?.id) return;\n let cancelled = false;\n (async () => {\n try {\n const params = new URLSearchParams({ store_id: shop.id });\n const res = await fetch(`/api/collections?${params.toString()}`);\n if (!res.ok) throw new Error(`/api/collections → ${res.status}`);\n const data = (await res.json()) as { collections?: Collection[] };\n if (cancelled) return;\n setCollections(data.collections ?? []);\n setLoading(false);\n } catch (err) {\n if (cancelled) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [initial, fetchIfMissing, shop?.id]);\n\n const sliced = limit != null ? collections.slice(0, limit) : collections;\n return { collections: sliced, loading, error };\n}\n","\"use client\";\n\nimport { createContext } from \"react\";\n\n/**\n * The action surface a theme can call to drive customer auth +\n * profile mutations. Each action returns the parsed response body\n * (or throws on network failure); the *result* of the operation is\n * conveyed by the response shape, not the throw boundary.\n *\n * The provider implements these by calling /api/customer/* proxy\n * routes on the storefront, which in turn forward to FastAPI's\n * /storefront/store/{store_id}/auth/* and /storefront/me/* endpoints.\n *\n * Why a separate context (vs bundling onto CustomerContext): the\n * value `Customer | null` was already in CustomerContext for\n * back-compat with themes that read `useCustomer()`. Adding a\n * sibling context for actions keeps the existing read hook stable\n * while letting themes opt into actions via `useCustomerActions()`.\n */\nexport interface CustomerActions {\n /** Email + password → returns { success, data?, error? }. On\n * success the SDK refreshes the customer context automatically. */\n login: (input: {\n email: string;\n password: string;\n }) => Promise<unknown>;\n\n /** Create a new customer + log them in. Some stores require\n * email verification before login is fully usable; this flow\n * still issues the auth cookie so the customer can verify from\n * the welcome email and land logged-in. */\n register: (input: {\n email: string;\n password: string;\n first_name?: string;\n last_name?: string;\n phone?: string;\n accepts_marketing?: boolean;\n }) => Promise<unknown>;\n\n /** Clear the customer_access_token cookie + refresh the context\n * to null. Idempotent: safe to call when not logged in. */\n logout: () => Promise<unknown>;\n\n /** Issue a password-reset email. Anti-enumeration: response\n * never reveals whether the email exists. */\n requestRecover: (input: { email: string }) => Promise<unknown>;\n\n /** Submit the new password with the token from the recovery email. */\n confirmReset: (input: {\n token: string;\n password: string;\n }) => Promise<unknown>;\n\n /** Verify the email with the token from the welcome email. */\n verifyEmail: (input: { token: string }) => Promise<unknown>;\n\n /** Resend the verification email. Server-side rate-limited to\n * prevent email-bombing. */\n resendVerification: (input: { email: string }) => Promise<unknown>;\n\n /** Update the customer's profile (name / phone / marketing). */\n updateProfile: (input: {\n first_name?: string;\n last_name?: string;\n phone?: string;\n accepts_marketing?: boolean;\n }) => Promise<unknown>;\n\n /** Change the customer's password from inside the dashboard.\n * Backend requires the current password as confirmation. */\n changePassword: (input: {\n current_password: string;\n new_password: string;\n }) => Promise<unknown>;\n\n /** Re-fetch the customer profile from the backend and replace\n * the context value. Themes call this after performing any\n * out-of-band mutation that changed the customer's record. */\n refresh: () => Promise<void>;\n}\n\nconst NOOP_ACTIONS: CustomerActions = {\n login: async () => ({}),\n register: async () => ({}),\n logout: async () => ({}),\n requestRecover: async () => ({}),\n confirmReset: async () => ({}),\n verifyEmail: async () => ({}),\n resendVerification: async () => ({}),\n updateProfile: async () => ({}),\n changePassword: async () => ({}),\n refresh: async () => undefined,\n};\n\nexport const CustomerActionsContext =\n createContext<CustomerActions>(NOOP_ACTIONS);\n","\"use client\";\n\nimport { useContext } from \"react\";\nimport { CustomerActionsContext, type CustomerActions } from \"../contexts/customer-actions\";\n\n/**\n * Returns the customer-mutation actions provided by NuMuProvider.\n *\n * Pair with `useCustomer()` for read access:\n *\n * const customer = useCustomer();\n * const { login, logout, register } = useCustomerActions();\n *\n * The actions hit the storefront's `/api/customer/*` proxies, which\n * own the cookie/CSRF/idempotency story. Themes don't talk to the\n * backend directly — they get a stable client-side surface here.\n */\nexport function useCustomerActions(): CustomerActions {\n return useContext(CustomerActionsContext);\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { useCustomer } from \"./useCustomer\";\n\n/**\n * Customer order history.\n *\n * `useOrders()` returns the logged-in customer's orders, paginated.\n * The hook is gated on `useCustomer()` — when null (anonymous\n * visitor), it returns an empty list without hitting the network.\n *\n * `useOrder(id)` fetches a single order. Backend rejects with 404\n * when the id doesn't belong to the customer regardless of whether\n * it exists for someone else (avoids enumeration).\n */\n\nexport interface OrderListEntry {\n id: string;\n order_number: string;\n status: string;\n payment_status: string;\n fulfillment_status: string;\n total: number;\n currency: string;\n created_at: string | null;\n item_count?: number;\n}\n\nexport interface OrderListState {\n orders: OrderListEntry[];\n loading: boolean;\n error: Error | null;\n refresh: () => void;\n}\n\nexport interface OrderDetail extends OrderListEntry {\n line_items: unknown[];\n shipping_address?: Record<string, unknown> | null;\n billing_address?: Record<string, unknown> | null;\n subtotal: number;\n shipping_cost: number;\n tax_amount: number;\n discount_amount: number;\n}\n\nexport interface OrderState {\n order: OrderDetail | null;\n loading: boolean;\n error: Error | null;\n refresh: () => void;\n}\n\nfunction unwrap(json: unknown): unknown {\n if (json && typeof json === \"object\" && \"data\" in json) {\n return (json as { data: unknown }).data;\n }\n return json;\n}\n\nexport function useOrders(): OrderListState {\n const customer = useCustomer();\n const [orders, setOrders] = useState<OrderListEntry[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [tick, setTick] = useState(0);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n if (!customer) {\n // Anonymous: nothing to fetch. Reset state so a logged-out\n // visitor doesn't see stale data carried over from a prior session.\n setOrders([]);\n setError(null);\n setLoading(false);\n return;\n }\n let cancelled = false;\n setLoading(true);\n setError(null);\n void (async () => {\n try {\n const res = await fetch(\"/api/customer/me/orders\", {\n method: \"GET\",\n credentials: \"include\",\n cache: \"no-store\",\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const body = unwrap(await res.json());\n if (cancelled) return;\n // Backend returns either a list directly or a paginated wrapper\n // `{ items, total, page, ... }`. Normalize to a list.\n const list = Array.isArray(body)\n ? body\n : Array.isArray((body as Record<string, unknown>)?.items)\n ? ((body as { items: OrderListEntry[] }).items)\n : [];\n setOrders(list as OrderListEntry[]);\n } catch (err) {\n if (cancelled) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [customer, tick]);\n\n return {\n orders,\n loading,\n error,\n refresh: () => setTick((t) => t + 1),\n };\n}\n\nexport function useOrder(id: string | null | undefined): OrderState {\n const customer = useCustomer();\n const [order, setOrder] = useState<OrderDetail | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [tick, setTick] = useState(0);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n if (!customer || !id) {\n setOrder(null);\n setError(null);\n setLoading(false);\n return;\n }\n let cancelled = false;\n setLoading(true);\n setError(null);\n void (async () => {\n try {\n const res = await fetch(\n `/api/customer/me/orders/${encodeURIComponent(id)}`,\n {\n method: \"GET\",\n credentials: \"include\",\n cache: \"no-store\",\n },\n );\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const body = unwrap(await res.json());\n if (cancelled) return;\n setOrder(body as OrderDetail);\n } catch (err) {\n if (cancelled) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [customer, id, tick]);\n\n return {\n order,\n loading,\n error,\n refresh: () => setTick((t) => t + 1),\n };\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useCustomer } from \"./useCustomer\";\n\n/**\n * Customer address book. Used by:\n * - The /account/addresses dashboard (list + CRUD).\n * - Checkout autofill (default address selected by default).\n *\n * Mutations return the updated row (or void on delete) and bump the\n * internal tick so the list reflects state changes immediately.\n * Anonymous visitors get an empty list with no network calls.\n */\n\nexport interface CustomerAddress {\n id: string;\n first_name?: string | null;\n last_name?: string | null;\n address_line1?: string | null;\n address_line2?: string | null;\n city?: string | null;\n state?: string | null;\n postal_code?: string | null;\n country?: string | null;\n phone?: string | null;\n label?: string | null;\n is_default?: boolean;\n // Optional geocoding fields — present when the merchant collects them.\n latitude?: number | null;\n longitude?: number | null;\n}\n\nexport type AddressInput = Omit<CustomerAddress, \"id\" | \"is_default\"> & {\n is_default?: boolean;\n};\n\nexport interface CustomerAddressesState {\n addresses: CustomerAddress[];\n loading: boolean;\n error: Error | null;\n refresh: () => void;\n addAddress: (input: AddressInput) => Promise<CustomerAddress | null>;\n updateAddress: (\n id: string,\n input: Partial<AddressInput>,\n ) => Promise<CustomerAddress | null>;\n deleteAddress: (id: string) => Promise<boolean>;\n setDefaultAddress: (id: string) => Promise<boolean>;\n}\n\nfunction unwrap(json: unknown): unknown {\n if (json && typeof json === \"object\" && \"data\" in json) {\n return (json as { data: unknown }).data;\n }\n return json;\n}\n\nasync function readBody(res: Response): Promise<unknown> {\n try {\n return unwrap(await res.json());\n } catch {\n return null;\n }\n}\n\nexport function useCustomerAddresses(): CustomerAddressesState {\n const customer = useCustomer();\n const [addresses, setAddresses] = useState<CustomerAddress[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [tick, setTick] = useState(0);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n if (!customer) {\n setAddresses([]);\n setLoading(false);\n setError(null);\n return;\n }\n let cancelled = false;\n setLoading(true);\n setError(null);\n void (async () => {\n try {\n const res = await fetch(\"/api/customer/me/addresses\", {\n method: \"GET\",\n credentials: \"include\",\n cache: \"no-store\",\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const body = await readBody(res);\n if (cancelled) return;\n const list = Array.isArray(body)\n ? body\n : Array.isArray((body as Record<string, unknown>)?.items)\n ? ((body as { items: CustomerAddress[] }).items)\n : [];\n setAddresses(list as CustomerAddress[]);\n } catch (err) {\n if (cancelled) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [customer, tick]);\n\n const refresh = useCallback(() => setTick((t) => t + 1), []);\n\n // CSRF: cart and customer mutations both echo the `numu_csrf` cookie\n // value as `x-numu-csrf` header. Read it from document.cookie just-\n // in-time so we always send the freshest value (the cookie may be\n // refreshed by /api/cart on first mount).\n function readCsrf(): string | null {\n if (typeof document === \"undefined\") return null;\n const m = document.cookie.match(/(?:^|; )numu_csrf=([^;]+)/);\n return m ? decodeURIComponent(m[1]) : null;\n }\n\n function mutationHeaders(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n const csrf = readCsrf();\n if (csrf) h[\"x-numu-csrf\"] = csrf;\n return h;\n }\n\n const addAddress = useCallback(\n async (input: AddressInput) => {\n const res = await fetch(\"/api/customer/me/addresses\", {\n method: \"POST\",\n credentials: \"include\",\n headers: mutationHeaders(),\n body: JSON.stringify(input),\n });\n if (!res.ok) return null;\n const created = (await readBody(res)) as CustomerAddress | null;\n refresh();\n return created;\n },\n [refresh],\n );\n\n const updateAddress = useCallback(\n async (id: string, input: Partial<AddressInput>) => {\n const res = await fetch(\n `/api/customer/me/addresses/${encodeURIComponent(id)}`,\n {\n method: \"PUT\",\n credentials: \"include\",\n headers: mutationHeaders(),\n body: JSON.stringify(input),\n },\n );\n if (!res.ok) return null;\n const updated = (await readBody(res)) as CustomerAddress | null;\n refresh();\n return updated;\n },\n [refresh],\n );\n\n const deleteAddress = useCallback(\n async (id: string) => {\n const res = await fetch(\n `/api/customer/me/addresses/${encodeURIComponent(id)}`,\n {\n method: \"DELETE\",\n credentials: \"include\",\n headers: mutationHeaders(),\n },\n );\n if (!res.ok) return false;\n refresh();\n return true;\n },\n [refresh],\n );\n\n const setDefaultAddress = useCallback(\n async (id: string) => {\n const res = await fetch(\n `/api/customer/me/addresses/${encodeURIComponent(id)}/default`,\n {\n method: \"PUT\",\n credentials: \"include\",\n headers: mutationHeaders(),\n },\n );\n if (!res.ok) return false;\n refresh();\n return true;\n },\n [refresh],\n );\n\n return {\n addresses,\n loading,\n error,\n refresh,\n addAddress,\n updateAddress,\n deleteAddress,\n setDefaultAddress,\n };\n}\n","\"use client\";\nimport { useContext, useEffect, useMemo, useState } from \"react\";\nimport {\n LocalizationContext,\n NavigationContext,\n type MenuItemData,\n} from \"../contexts\";\n\n/**\n * Menu item, modeled on Shopify's `linklists` entries.\n *\n * Themes typically render header/footer nav as a tree — we expose\n * `children` so a single fetch hydrates an arbitrary depth. Backends\n * that don't support nesting return a flat list (children=[]).\n */\nexport interface NavigationItem {\n id: string;\n title: string;\n /** The URL the menu item points to — relative path or absolute URL. */\n url: string;\n /** Optional foreign keys when the item references a typed resource. */\n resource_type?: \"product\" | \"collection\" | \"page\" | \"blog\" | \"article\" | \"url\" | null;\n resource_handle?: string | null;\n children: NavigationItem[];\n}\n\nexport interface NavigationState {\n /** Items in display order. Empty array when the menu is missing or still loading. */\n items: NavigationItem[];\n loading: boolean;\n /** Non-null when the fetch failed — the menu still resolves to []. */\n error: Error | null;\n}\n\nconst cache = new Map<string, NavigationItem[]>();\n\n/**\n * Resolve a bilingual label to a single display string for `locale`,\n * degrading gracefully: active locale → English → Arabic → first value.\n */\nfunction localizeLabel(\n label: Record<string, string> | undefined,\n locale: string,\n): string {\n if (!label) return \"\";\n return (\n label[locale] ||\n label.en ||\n label.ar ||\n Object.values(label).find((v) => !!v) ||\n \"\"\n );\n}\n\n/** Map the backend item `type` onto the SDK's `resource_type` union. */\nfunction mapResourceType(type?: string | null): NavigationItem[\"resource_type\"] {\n switch (type) {\n case \"product\":\n return \"product\";\n case \"collection\":\n return \"collection\";\n case \"page\":\n return \"page\";\n case \"blog\":\n return \"blog\";\n case \"article\":\n return \"article\";\n case \"http\":\n case \"url\":\n return \"url\";\n default:\n return null;\n }\n}\n\n/** Localize a raw (bilingual) menu item tree into display NavigationItems. */\nfunction toNavigationItem(raw: MenuItemData, locale: string): NavigationItem {\n return {\n id: raw.id,\n title: localizeLabel(raw.label, locale),\n url: raw.url || \"/\",\n resource_type: mapResourceType(raw.type),\n resource_handle: raw.resource_id ?? null,\n children: (raw.children ?? []).map((child) =>\n toNavigationItem(child, locale),\n ),\n };\n}\n\n/**\n * Fetch a merchant-managed nav menu by handle.\n *\n * Resolution order (Phase 2.4):\n * 1. Host-injected menus — the storefront resolves menus server-side\n * (`GET /storefront/store/{id}/menus`) and injects them via\n * `NuMuProvider`'s `navigation` prop → `NavigationContext`. When the\n * handle is present we localize + return it synchronously, no fetch.\n * A non-empty map that lacks the handle means \"no such menu\" → [].\n * 2. `options.initialItems` — a theme that pre-fetched its own list.\n * 3. Client fetch of `GET /api/storefront/navigation/{handle}` — the\n * legacy fallback for hosts that inject nothing. On 404 / network\n * error the hook resolves to [] (a missing menu is a soft failure;\n * the theme falls back to its own DEFAULT_NAV).\n */\nexport function useNavigation(\n handle: string,\n options?: { initialItems?: NavigationItem[] },\n): NavigationState {\n // NavigationContext defaults to {} outside a provider; LocalizationContext\n // is read defensively (no throw) so useNavigation works even if a theme\n // calls it above NuMuProvider in a test harness.\n const navMap = useContext(NavigationContext);\n const localization = useContext(LocalizationContext);\n const locale = localization?.locale ?? \"en\";\n\n const hostProvidedAny = !!navMap && Object.keys(navMap).length > 0;\n const rawItems = handle ? navMap?.[handle] : undefined;\n\n // Localized view of host-injected items. `null` means \"host wired no\n // navigation at all\" → fall through to initialItems / fetch. `[]` means\n // the host IS authoritative but this handle is absent/empty → render\n // nothing (no doomed fetch).\n const hostItems = useMemo<NavigationItem[] | null>(() => {\n if (rawItems) return rawItems.map((it) => toNavigationItem(it, locale));\n if (hostProvidedAny) return [];\n return null;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [rawItems, hostProvidedAny, locale]);\n\n const [items, setItems] = useState<NavigationItem[]>(\n hostItems ?? options?.initialItems ?? cache.get(handle) ?? [],\n );\n const [loading, setLoading] = useState(\n hostItems === null && !options?.initialItems && !cache.has(handle),\n );\n const [error, setError] = useState<Error | null>(null);\n\n // Keep items in sync with host-injected menus (locale switch, or the\n // map arriving after first paint). When the host is authoritative we\n // never fetch.\n useEffect(() => {\n if (hostItems === null) return;\n setItems(hostItems);\n setLoading(false);\n setError(null);\n }, [hostItems]);\n\n useEffect(() => {\n // Host-injected menus win — skip the network entirely.\n if (hostItems !== null) return;\n if (typeof window === \"undefined\") return;\n if (!handle) {\n setItems([]);\n setLoading(false);\n return;\n }\n if (cache.has(handle) && !options?.initialItems) {\n setItems(cache.get(handle) || []);\n setLoading(false);\n return;\n }\n let cancelled = false;\n setLoading(true);\n setError(null);\n void (async () => {\n try {\n const res = await fetch(\n `/api/storefront/navigation/${encodeURIComponent(handle)}`,\n { cache: \"no-store\" },\n );\n if (!res.ok) {\n // 404 = no such menu; render nothing instead of an error UI.\n if (cancelled) return;\n cache.set(handle, []);\n setItems([]);\n return;\n }\n const json = (await res.json()) as\n | { items?: NavigationItem[] }\n | NavigationItem[];\n const list: NavigationItem[] = Array.isArray(json)\n ? json\n : json.items || [];\n if (cancelled) return;\n cache.set(handle, list);\n setItems(list);\n } catch (err) {\n if (cancelled) return;\n // Non-OK / network failure → empty list + surface error so\n // themes can decide whether to log or show a fallback.\n setError(err instanceof Error ? err : new Error(String(err)));\n setItems([]);\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n // Deliberate: re-run when `handle` or host-injection state changes;\n // `initialItems` change shouldn't refetch (theme passes it once).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [handle, hostItems === null]);\n\n return { items, loading, error };\n}\n","\"use client\";\nimport { useEffect, useRef, useState } from \"react\";\nimport type { Product, Collection, Page } from \"../types/entities\";\n\n/**\n * Mixed-result search shape. The backend tsvector implementation lands in\n * Phase 4; until then this hook talks to /api/storefront/search and\n * gracefully degrades (empty results) when the endpoint isn't available.\n *\n * Two modes:\n * - \"predictive\" (default): debounced, capped at 5 per type, returns\n * fast for autocomplete dropdowns.\n * - \"full\": full result set with paging, used by /search pages.\n */\n\nexport interface SearchResults {\n products: Product[];\n collections: Collection[];\n pages: Page[];\n /** Articles will populate once the blog backend lands; field shape is\n * reserved here so themes can write code that doesn't break on\n * upgrade. */\n articles: Array<{ id: string; title: string; handle: string; excerpt?: string }>;\n total: number;\n}\n\nexport interface UseSearchOptions {\n /** \"predictive\" debounces and caps; \"full\" returns paged results. */\n mode?: \"predictive\" | \"full\";\n /** Restrict to specific result types. Default: all. */\n types?: Array<\"products\" | \"collections\" | \"pages\" | \"articles\">;\n /** Per-type cap. Predictive mode defaults to 5; full mode defaults to 24. */\n limit?: number;\n /** Debounce window in ms for predictive mode. Default 200. */\n debounceMs?: number;\n /** Skip the debounce (e.g. when the user submits the form). */\n immediate?: boolean;\n}\n\nexport interface SearchState {\n query: string;\n results: SearchResults;\n loading: boolean;\n error: Error | null;\n}\n\nconst EMPTY: SearchResults = {\n products: [],\n collections: [],\n pages: [],\n articles: [],\n total: 0,\n};\n\nexport function useSearch(\n query: string,\n options: UseSearchOptions = {},\n): SearchState {\n const {\n mode = \"predictive\",\n types,\n limit,\n debounceMs = 200,\n immediate = false,\n } = options;\n\n const [results, setResults] = useState<SearchResults>(EMPTY);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const lastRequestId = useRef(0);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const trimmed = query.trim();\n if (!trimmed) {\n setResults(EMPTY);\n setLoading(false);\n setError(null);\n return;\n }\n\n const requestId = ++lastRequestId.current;\n setLoading(true);\n setError(null);\n\n const run = async () => {\n try {\n const params = new URLSearchParams({ q: trimmed, mode });\n if (types?.length) params.set(\"types\", types.join(\",\"));\n if (limit) params.set(\"limit\", String(limit));\n const res = await fetch(`/api/storefront/search?${params}`, {\n cache: \"no-store\",\n });\n if (requestId !== lastRequestId.current) return; // superseded\n if (!res.ok) {\n // Backend search not yet wired (Phase 4). Empty result is\n // an acceptable degraded mode — themes show \"no results\"\n // instead of an error banner.\n setResults(EMPTY);\n return;\n }\n const json = (await res.json()) as Partial<SearchResults> & {\n data?: Partial<SearchResults>;\n };\n const body = json.data || json;\n if (requestId !== lastRequestId.current) return;\n setResults({\n products: body.products || [],\n collections: body.collections || [],\n pages: body.pages || [],\n articles: body.articles || [],\n total: body.total || 0,\n });\n } catch (err) {\n if (requestId !== lastRequestId.current) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setResults(EMPTY);\n } finally {\n if (requestId === lastRequestId.current) setLoading(false);\n }\n };\n\n if (immediate || mode === \"full\") {\n void run();\n return;\n }\n const t = setTimeout(run, debounceMs);\n return () => clearTimeout(t);\n }, [query, mode, debounceMs, immediate, limit, types?.join(\",\")]); // eslint-disable-line react-hooks/exhaustive-deps\n\n return { query, results, loading, error };\n}\n","\"use client\";\nimport { useCallback, useMemo } from \"react\";\n\n/**\n * Theme-facing analytics dispatcher.\n *\n * Two delivery channels, fired in parallel:\n * 1. Server-side track: POST /api/storefront/track with the event\n * payload. The host storefront proxies to FastAPI's funnel-event\n * endpoint (/storefront/store/{id}/track) and fans out to\n * merchant-configured pixels (GA4 Measurement Protocol, Meta CAPI,\n * TikTok Events API). Failed pixels never block the UI — we\n * don't await the response.\n * 2. Window CustomEvent (`numu:analytics:event`): so theme devs can\n * wire their own GTM container, third-party SDK, or in-house\n * pixel without going through the server. Detail shape mirrors\n * what gets POSTed.\n *\n * Standard event names (recommended for compatibility with GA4 / Meta):\n * page_view, view_item, view_collection, search, add_to_cart,\n * remove_from_cart, view_cart, begin_checkout, add_payment_info,\n * add_shipping_info, purchase, refund, sign_up, login,\n * add_to_wishlist, share. Custom names are also fine — the dispatcher\n * does not validate, so themes can ship store-specific events.\n *\n * Funnel-event mapping\n * --------------------\n * Standard event names that map to the backend's funnel steps are\n * dispatched with the full funnel-event payload shape (path,\n * session_fingerprint, attribution envelope from\n * window.__numu_attribution). This is what powers the merchant\n * funnel / journey / multi-touch attribution dashboards. Events with\n * no funnel mapping still POST with the loose `{event, payload}`\n * shape — the proxy forwards them so the pixel-fanout layer still\n * fires.\n */\n\nexport interface AnalyticsPayload {\n /** Standard or custom event name. Lowercase + underscores recommended. */\n [key: string]: unknown;\n}\n\nexport interface AnalyticsApi {\n /**\n * Fire an event. Non-blocking — both the fetch and the CustomEvent\n * dispatch happen in the next microtask; theme code shouldn't await.\n */\n track: (eventName: string, payload?: AnalyticsPayload) => void;\n}\n\n/**\n * Standard event name → backend funnel step mapping.\n *\n * Only events listed here drive the funnel / attribution dashboards.\n * Everything else still POSTs (for pixel fanout) but doesn't land in\n * the funnel_events table. The mapping mirrors what the bazaar\n * storefront's trackingService uses on the SaaS side.\n */\nconst EVENT_TO_FUNNEL_STEP: Record<string, string> = {\n page_view: \"page_view\",\n view_item: \"product_view\",\n view_collection: \"page_view\",\n add_to_cart: \"add_to_cart\",\n begin_checkout: \"checkout_started\",\n purchase: \"order_completed\",\n // Wave 2+ standard Meta events — backend's FUNNEL_STEP_TO_META_EVENT\n // table accepts these as funnel steps directly.\n search: \"search\",\n lead: \"lead\",\n sign_up: \"complete_registration\",\n add_to_wishlist: \"add_to_wishlist\",\n add_payment_info: \"add_payment_info\",\n};\n\ninterface AttributionEnvelope {\n v?: number;\n first_touch?: unknown;\n last_touch?: unknown;\n session_id?: string | null;\n}\n\ninterface NumuAttributionBridge {\n get(): AttributionEnvelope | null;\n}\n\ninterface NumuCustomerBridge {\n /** Authenticated customer's UUID, or null when the visitor is a guest. */\n getId(): string | null;\n}\n\ndeclare global {\n interface Window {\n __numu_attribution?: NumuAttributionBridge;\n /**\n * Optional bridge installed by the host storefront's customer\n * provider. When set, the SDK includes ``customer_id`` on\n * funnel-step events so the backend can record touches against\n * the authenticated customer immediately instead of waiting for\n * the next checkout to backfill.\n */\n __numu_customer?: NumuCustomerBridge;\n }\n}\n\nfunction readAttribution(): AttributionEnvelope | null {\n if (typeof window === \"undefined\") return null;\n try {\n return window.__numu_attribution?.get?.() ?? null;\n } catch {\n return null;\n }\n}\n\nfunction readCustomerId(): string | null {\n if (typeof window === \"undefined\") return null;\n try {\n return window.__numu_customer?.getId?.() ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Session fingerprint for funnel-event dedup.\n *\n * The attribution envelope's session_id (ULID, stable for cookie\n * lifetime) is the natural fingerprint — same cookie lifetime as the\n * attribution window, so funnel + journey + multi-touch all agree on\n * what \"one session\" means.\n *\n * Fallback: a per-tab random string when no envelope exists yet (first\n * visit before AttributionProvider's effect has run). Persisted on the\n * window so subsequent calls in the same tab reuse it — otherwise\n * each event would generate its own fingerprint and the funnel\n * dashboard would over-count distinct sessions.\n */\nfunction getFingerprint(): string {\n if (typeof window === \"undefined\") return \"ssr\";\n const env = readAttribution();\n if (env?.session_id) return env.session_id;\n\n const w = window as unknown as { __numu_session_fp?: string };\n if (w.__numu_session_fp) return w.__numu_session_fp;\n // crypto.randomUUID is universally available in our supported\n // browsers (no IE / pre-2022 mobile Safari). Skip the fallback.\n const fp = crypto.randomUUID();\n w.__numu_session_fp = fp;\n return fp;\n}\n\n/**\n * Free function body of the hook's `track`.\n *\n * Extracted so unit tests can call it directly without spinning up a\n * React renderer for what is essentially a side-effect dispatcher.\n * The exported `useAnalytics` hook is a thin memoization wrapper.\n */\nexport function dispatchAnalyticsEvent(\n eventName: string,\n payload: AnalyticsPayload = {},\n): void {\n if (typeof window === \"undefined\") return;\n\n // 1. Window CustomEvent — synchronous, cheap. Themes that wire\n // their own pixels listen here.\n try {\n window.dispatchEvent(\n new CustomEvent(\"numu:analytics:event\", {\n detail: { event: eventName, payload, ts: Date.now() },\n }),\n );\n } catch {\n /* CustomEvent unsupported — no DOM event polyfill needed today. */\n }\n\n // 2. Server-side fanout. Funnel-step events get the strict payload\n // shape the backend's funnel_events table expects (path,\n // fingerprint, step, step_data, attribution). Non-funnel events\n // keep the loose shape for the pixel-fanout layer.\n const step = EVENT_TO_FUNNEL_STEP[eventName] ?? null;\n // Lifting customer_id once so we don't read the bridge twice per\n // dispatch. Absent (null) for guests / unauthenticated visitors;\n // present for logged-in customers whose journey rows should land\n // with customer_id set immediately instead of waiting for the\n // next checkout to backfill.\n const customerId = readCustomerId();\n const body: Record<string, unknown> = step\n ? {\n event_id: crypto.randomUUID(),\n path: window.location.pathname,\n fingerprint: getFingerprint(),\n step,\n step_data: payload,\n referrer:\n typeof document !== \"undefined\" && document.referrer\n ? document.referrer\n : undefined,\n attribution: readAttribution() ?? undefined,\n customer_id: customerId ?? undefined,\n }\n : {\n event: eventName,\n payload,\n ts: Date.now(),\n attribution: readAttribution() ?? undefined,\n customer_id: customerId ?? undefined,\n };\n\n void (async () => {\n try {\n await fetch(\"/api/storefront/track\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n keepalive: true, // survive page-unload (e.g. begin_checkout → redirect)\n });\n } catch {\n /* swallowed by design */\n }\n })();\n}\n\nexport function useAnalytics(): AnalyticsApi {\n const track = useCallback(\n (eventName: string, payload: AnalyticsPayload = {}) => {\n dispatchAnalyticsEvent(eventName, payload);\n },\n [],\n );\n\n return useMemo(() => ({ track }), [track]);\n}\n","\"use client\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useShop } from \"./useShop\";\n\n/**\n * Read app-provided data + manifest for a slug installed on the\n * current store.\n *\n * Phase 6 wired this to the real backend at\n * `/api/storefront/store/{store_id}/apps/{slug}`. Theme usage:\n *\n * const recommend = useApp<RecommendationData>(\"recommendation-engine\");\n * if (!recommend.available) return <Fallback />;\n * if (recommend.loading) return <Skeleton />;\n * return <RecommendList items={recommend.data?.products ?? []} />;\n *\n * `available` flips to true only when an enabled installation exists\n * for the store. Apps the merchant hasn't installed surface as\n * `{ available: false }` rather than as a network error — themes\n * branch on availability without try/catch.\n *\n * The hook revalidates whenever the slug changes, but does NOT refetch\n * on focus / interval — app data is usually slow-changing (config +\n * manifest). Themes that need live data should layer their own\n * refresh on top of the returned `refresh()` callback.\n */\n\nexport interface AppManifestBlock {\n type: string;\n name: string;\n block_schema: Record<string, unknown>;\n}\n\nexport interface AppPayload<T = unknown> {\n slug: string;\n name: string;\n description: string | null;\n icon_url: string | null;\n version: string;\n manifest: Record<string, unknown>;\n settings: Record<string, unknown>;\n blocks: AppManifestBlock[];\n /** App-provided data (shape defined by the app developer). Today\n * the response always returns null for `data` — apps emit data via\n * their `endpoints.data` URL, which the theme fetches separately.\n * Surfaced here so the field is stable when v2 lands the proxy. */\n data: T | null;\n}\n\nexport interface AppState<T = unknown> {\n data: AppPayload<T> | null;\n loading: boolean;\n available: boolean;\n error: Error | null;\n /** Re-fetch the install. Returns a promise that resolves when the\n * request settles (regardless of success). */\n refresh: () => Promise<void>;\n}\n\nexport function useApp<T = unknown>(slug: string): AppState<T> {\n const shop = useShop();\n const [state, setState] = useState<{\n data: AppPayload<T> | null;\n loading: boolean;\n available: boolean;\n error: Error | null;\n }>({ data: null, loading: true, available: false, error: null });\n\n const fetchApp = useCallback(async (): Promise<void> => {\n if (!slug) {\n setState({ data: null, loading: false, available: false, error: null });\n return;\n }\n setState((s) => ({ ...s, loading: true, error: null }));\n try {\n const url = `/api/storefront/apps/${encodeURIComponent(slug)}`;\n const res = await fetch(url, {\n credentials: \"include\",\n headers: { Accept: \"application/json\" },\n });\n if (res.status === 404) {\n // Not installed (or app disabled). Standard not-available\n // shape — keeps theme branching simple.\n setState({\n data: null,\n loading: false,\n available: false,\n error: null,\n });\n return;\n }\n if (!res.ok) {\n throw new Error(`useApp(${slug}) failed: HTTP ${res.status}`);\n }\n const body = (await res.json()) as {\n data?: AppPayload<T> & { available?: boolean };\n };\n const payload = body.data;\n if (!payload) {\n setState({\n data: null,\n loading: false,\n available: false,\n error: null,\n });\n return;\n }\n setState({\n data: payload as AppPayload<T>,\n loading: false,\n available: payload.available !== false,\n error: null,\n });\n } catch (e) {\n setState({\n data: null,\n loading: false,\n available: false,\n error: e instanceof Error ? e : new Error(String(e)),\n });\n }\n }, [slug, shop.id]);\n\n useEffect(() => {\n void fetchApp();\n }, [fetchApp]);\n\n return { ...state, refresh: fetchApp };\n}\n","\"use client\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useCustomer } from \"./useCustomer\";\n\n/**\n * Wishlist hook with localStorage fallback.\n *\n * Architecture (Phase 4 lands the server side):\n * - Authenticated customer: persists to /api/customer/me/wishlist\n * (server-backed, syncs across devices).\n * - Anonymous visitor: persists to localStorage under\n * `numu_wishlist_<store_id>`. On login, the wishlist merges into\n * the server-side list (mirrors the cart's session→customer flow).\n *\n * v1 implementation: localStorage only. The /api/customer/me/wishlist\n * endpoint isn't wired yet; an authed visitor still gets the local\n * fallback so themes work end-to-end. When the endpoint lands, the\n * mutation methods will short-circuit to the server fetch and the\n * effect below will drop the localStorage path for authed users.\n */\n\nexport interface WishlistItem {\n product_id: string;\n /** Optional variant scoping — themes that show variant pickers can\n * wishlist a specific size/color combo separately. */\n variant_id?: string | null;\n /** Server timestamp once persistence lands; ms-since-epoch in v1. */\n added_at: number;\n}\n\nexport interface WishlistState {\n items: WishlistItem[];\n loading: boolean;\n has: (productId: string, variantId?: string | null) => boolean;\n addToWishlist: (productId: string, variantId?: string | null) => void;\n removeFromWishlist: (productId: string, variantId?: string | null) => void;\n clear: () => void;\n}\n\nfunction storageKey(storeId: string): string {\n return `numu_wishlist_${storeId}`;\n}\n\nfunction readLocal(storeId: string): WishlistItem[] {\n if (typeof window === \"undefined\") return [];\n try {\n const raw = window.localStorage.getItem(storageKey(storeId));\n if (!raw) return [];\n const parsed = JSON.parse(raw);\n return Array.isArray(parsed) ? (parsed as WishlistItem[]) : [];\n } catch {\n return [];\n }\n}\n\nfunction writeLocal(storeId: string, items: WishlistItem[]): void {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(storageKey(storeId), JSON.stringify(items));\n } catch {\n /* quota / private mode — wishlist degrades to in-memory for the session */\n }\n}\n\nfunction sameItem(\n a: WishlistItem,\n productId: string,\n variantId?: string | null,\n): boolean {\n return (\n a.product_id === productId && (a.variant_id ?? null) === (variantId ?? null)\n );\n}\n\n/**\n * @param storeId The store the wishlist is scoped to. Pass `useShop().id`.\n * Without it, the hook can't keep one merchant's wishlist\n * from leaking into another's localStorage on a shared\n * domain (e.g. apex preview).\n */\nexport function useWishlist(storeId: string): WishlistState {\n const customer = useCustomer();\n const [items, setItems] = useState<WishlistItem[]>([]);\n const [loading, setLoading] = useState(true);\n\n // Hydrate from localStorage on mount. When the server-side endpoint\n // lands, an authed customer will fetch from there instead.\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n setItems(readLocal(storeId));\n setLoading(false);\n }, [storeId, customer?.id]);\n\n const has = useCallback(\n (productId: string, variantId?: string | null) =>\n items.some((it) => sameItem(it, productId, variantId)),\n [items],\n );\n\n const addToWishlist = useCallback(\n (productId: string, variantId?: string | null) => {\n setItems((prev) => {\n if (prev.some((it) => sameItem(it, productId, variantId))) {\n return prev;\n }\n const next: WishlistItem[] = [\n ...prev,\n {\n product_id: productId,\n variant_id: variantId ?? null,\n added_at: Date.now(),\n },\n ];\n writeLocal(storeId, next);\n return next;\n });\n },\n [storeId],\n );\n\n const removeFromWishlist = useCallback(\n (productId: string, variantId?: string | null) => {\n setItems((prev) => {\n const next = prev.filter((it) => !sameItem(it, productId, variantId));\n writeLocal(storeId, next);\n return next;\n });\n },\n [storeId],\n );\n\n const clear = useCallback(() => {\n setItems([]);\n writeLocal(storeId, []);\n }, [storeId]);\n\n return { items, loading, has, addToWishlist, removeFromWishlist, clear };\n}\n","\"use client\";\nimport { useEffect, useState } from \"react\";\nimport type { Product } from \"../types/entities\";\n\n/**\n * Fetch products related to the given product (same category, excluding\n * self). Phase 3 lands collaborative-filtering / \"frequently bought\n * together\"; v1 ships the simpler same-category-minus-self heuristic.\n *\n * Backend contract: GET /api/storefront/products/{id}/related?limit=N\n * → { items: Product[] } | Product[]\n *\n * Returns an empty list (no error) when the endpoint is missing or the\n * product has no siblings — themes should branch on `items.length` and\n * either render the section or skip it entirely.\n */\n\nexport interface RelatedProductsState {\n items: Product[];\n loading: boolean;\n error: Error | null;\n}\n\nexport function useRelatedProducts(\n productId: string | null | undefined,\n options: { limit?: number } = {},\n): RelatedProductsState {\n const limit = options.limit ?? 4;\n const [items, setItems] = useState<Product[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n if (!productId) {\n setItems([]);\n setLoading(false);\n setError(null);\n return;\n }\n let cancelled = false;\n setLoading(true);\n setError(null);\n void (async () => {\n try {\n const res = await fetch(\n `/api/storefront/products/${encodeURIComponent(productId)}/related?limit=${limit}`,\n { cache: \"no-store\" },\n );\n if (!res.ok) {\n // Endpoint not yet wired — don't surface an error; themes\n // should treat this as \"no related items available\" and\n // skip the section.\n if (cancelled) return;\n setItems([]);\n return;\n }\n const json = (await res.json()) as\n | { items?: Product[]; data?: Product[] }\n | Product[];\n const list: Product[] = Array.isArray(json)\n ? json\n : Array.isArray(json.data)\n ? json.data\n : Array.isArray(json.items)\n ? json.items\n : [];\n if (cancelled) return;\n setItems(list);\n } catch (err) {\n if (cancelled) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setItems([]);\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [productId, limit]);\n\n return { items, loading, error };\n}\n","\"use client\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useShop } from \"./useShop\";\n\n/**\n * Multi-currency presentment — Phase 6.\n *\n * The store's *capture* currency (what Paymob/Stripe/etc. charges)\n * never changes mid-session. This hook is purely about **display**:\n * letting visitors browse prices in a currency they recognize.\n *\n * Usage:\n *\n * const { base, selected, presentment, convert, setSelected } = useCurrency();\n * <p>{convert(product.price.amount_cents)} {selected}</p>\n * {presentment.length > 1 && (\n * <select value={selected} onChange={(e) => setSelected(e.target.value)}>\n * {presentment.map(c => <option key={c}>{c}</option>)}\n * </select>\n * )}\n *\n * Behavior:\n * - `selected` defaults to the persisted `numu_currency` cookie if\n * valid, else `default_presentment`, else `base`.\n * - `setSelected` writes the cookie (path=/, 30d) so navigation\n * preserves the choice across pages.\n * - `convert(cents)` returns the converted cents in `selected`,\n * using the rates from the API. When no rate exists, returns\n * the input unchanged (theme renders in base — better than a\n * wrong number).\n *\n * Use `<CurrencySwitcher>` from the SDK for an opinionated UI, or\n * read this hook directly for full control.\n */\n\nexport interface CurrencyConfig {\n base: string;\n default_presentment: string;\n presentment: string[];\n rates: Record<string, string>; // Decimal-as-string\n auto_convert: boolean;\n}\n\nexport interface CurrencyState {\n base: string;\n selected: string;\n presentment: string[];\n rates: Record<string, number>;\n autoConvert: boolean;\n loading: boolean;\n setSelected: (currency: string) => void;\n convert: (cents: number, target?: string) => number;\n}\n\nconst COOKIE_NAME = \"numu_currency\";\nconst COOKIE_MAX_AGE = 60 * 60 * 24 * 30; // 30 days\n\nfunction readCookie(name: string): string | null {\n if (typeof document === \"undefined\") return null;\n const match = document.cookie.match(\n new RegExp(`(?:^|;\\\\s*)${name}=([^;]+)`),\n );\n return match ? decodeURIComponent(match[1]) : null;\n}\n\nfunction writeCookie(name: string, value: string): void {\n if (typeof document === \"undefined\") return;\n document.cookie = `${name}=${encodeURIComponent(value)}; path=/; max-age=${COOKIE_MAX_AGE}; SameSite=Lax`;\n}\n\nexport function useCurrency(): CurrencyState {\n const shop = useShop();\n const [config, setConfig] = useState<CurrencyConfig | null>(null);\n const [loading, setLoading] = useState(true);\n const [selected, setSelectedState] = useState<string>(\"\");\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n try {\n const res = await fetch(`/api/storefront/currencies`, {\n credentials: \"include\",\n headers: { Accept: \"application/json\" },\n });\n if (!res.ok) throw new Error(`currencies: HTTP ${res.status}`);\n const body = (await res.json()) as { data: CurrencyConfig };\n if (cancelled) return;\n setConfig(body.data);\n // Resolve the initial selection: cookie → default → base.\n // Validate against the presentment list so a stale cookie\n // doesn't lock the visitor onto a currency the merchant\n // removed.\n const cookie = readCookie(COOKIE_NAME);\n const valid =\n cookie && body.data.presentment.includes(cookie) ? cookie : null;\n setSelectedState(valid || body.data.default_presentment || body.data.base);\n } catch {\n if (cancelled) return;\n setConfig(null);\n setSelectedState(shop.currency || \"EGP\");\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [shop.id, shop.currency]);\n\n const rates = useMemo<Record<string, number>>(() => {\n const out: Record<string, number> = {};\n if (!config) return out;\n for (const [k, v] of Object.entries(config.rates)) {\n const n = Number.parseFloat(v);\n if (Number.isFinite(n)) out[k] = n;\n }\n return out;\n }, [config]);\n\n const convert = useCallback(\n (cents: number, target?: string): number => {\n if (!config) return cents;\n const to = target || selected;\n if (!to || to === config.base) return cents;\n const rate = rates[to];\n if (!rate || !Number.isFinite(rate)) return cents;\n return Math.round(cents * rate);\n },\n [config, rates, selected],\n );\n\n const setSelected = useCallback((currency: string) => {\n setSelectedState(currency);\n writeCookie(COOKIE_NAME, currency);\n }, []);\n\n return {\n base: config?.base || shop.currency || \"EGP\",\n selected: selected || config?.base || shop.currency || \"EGP\",\n presentment: config?.presentment || [shop.currency || \"EGP\"],\n rates,\n autoConvert: Boolean(config?.auto_convert),\n loading,\n setSelected,\n convert,\n };\n}\n","/**\n * Variant resolution helpers — Phase 8.1.\n *\n * Themes render a variant picker (Size + Color radios), then ask the\n * SDK \"given my current selection, which variant is it?\" The matching\n * variant's id is what add-to-cart sends.\n */\n\nimport type { Product, ProductVariant } from \"../types/entities\";\n\n/**\n * Pick the variant that exactly matches the given option_values map.\n * Returns null when no variant matches — themes render that as\n * \"Combination unavailable\" or a disabled buy button.\n */\nexport function findVariantByOptions(\n product: Pick<Product, \"variants\">,\n selection: Record<string, string>,\n): ProductVariant | null {\n const variants = product.variants || [];\n if (variants.length === 0) return null;\n // Single-variant products (no axes): the only variant matches the\n // empty selection trivially.\n if (variants.length === 1 && Object.keys(selection).length === 0) {\n return variants[0];\n }\n for (const v of variants) {\n const opts = v.option_values || v.options || {};\n const matches = Object.entries(selection).every(\n ([axis, value]) => opts[axis] === value,\n );\n if (matches && Object.keys(selection).length === Object.keys(opts).length) {\n return v;\n }\n }\n return null;\n}\n\n/**\n * Find the \"default\" variant — the one the PDP should auto-select on\n * first render. Prefers the first in-stock variant; falls back to the\n * first variant if all are out of stock (so the picker still shows\n * something coherent).\n */\nexport function defaultVariant(product: Pick<Product, \"variants\">): ProductVariant | null {\n const variants = product.variants || [];\n if (variants.length === 0) return null;\n const inStock = variants.find((v) => v.is_in_stock || v.in_stock);\n return inStock || variants[0];\n}\n\n/**\n * Given a partial selection (e.g. just Size=M, no Color yet), return\n * the set of values still available on each unselected axis. Themes\n * use this to disable swatches whose paired variants are all out of\n * stock for the current selection.\n */\nexport function availableValues(\n product: Pick<Product, \"options\" | \"variants\">,\n selection: Record<string, string>,\n): Record<string, Set<string>> {\n const axes = product.options || [];\n const variants = product.variants || [];\n const out: Record<string, Set<string>> = {};\n for (const axis of axes) {\n out[axis.name] = new Set();\n for (const v of variants) {\n const opts = v.option_values || v.options || {};\n // Only consider variants compatible with the locked-in part of\n // the selection (every locked axis must match this variant).\n const compatible = Object.entries(selection).every(\n ([k, val]) => k === axis.name || opts[k] === val,\n );\n if (compatible && opts[axis.name]) {\n out[axis.name].add(opts[axis.name]);\n }\n }\n }\n return out;\n}\n","\"use client\";\n\nimport { useCallback, useMemo, useState } from \"react\";\nimport {\n availableValues,\n defaultVariant,\n findVariantByOptions,\n} from \"../utils/variants\";\nimport type { Product, ProductVariant } from \"../types/entities\";\n\nexport interface UseVariantSelection {\n /** Currently-selected axis → value map. */\n selection: Record<string, string>;\n /** The variant matching the current selection, if any. */\n variant: ProductVariant | null;\n /** Pick a value on one axis. Other axes stay locked. */\n select: (axis: string, value: string) => void;\n /** Reset the selection (e.g. on \"Choose another\" button). */\n reset: () => void;\n /**\n * For each unselected axis, the set of values that lead to at\n * least one in-stock variant given the current locked axes.\n * Themes use this to grey out swatches.\n */\n availability: Record<string, Set<string>>;\n /**\n * True when every option axis on the product has a chosen value\n * and `variant` is resolved. Buy buttons should disable until\n * this flips to true on products with options.\n */\n isComplete: boolean;\n}\n\n/**\n * Hook that owns variant-axis selection state for a PDP.\n *\n * Initial state auto-selects the default variant's axis values so\n * the PDP loads with a coherent price + image + buy state, matching\n * Shopify's behavior. Themes that prefer \"Choose your size\" empty\n * state can pass `autoSelect: false`.\n */\nexport function useVariantSelection(\n product: Pick<Product, \"options\" | \"variants\">,\n opts: { autoSelect?: boolean } = {},\n): UseVariantSelection {\n const autoSelect = opts.autoSelect ?? true;\n\n const initial = useMemo<Record<string, string>>(() => {\n if (!autoSelect) return {};\n const dv = defaultVariant(product);\n if (!dv) return {};\n const opts = dv.option_values || dv.options || {};\n return { ...opts };\n }, [product, autoSelect]);\n\n const [selection, setSelection] = useState<Record<string, string>>(initial);\n\n const select = useCallback((axis: string, value: string) => {\n setSelection((prev) => ({ ...prev, [axis]: value }));\n }, []);\n\n const reset = useCallback(() => setSelection({}), []);\n\n const variant = useMemo(\n () => findVariantByOptions(product, selection),\n [product, selection],\n );\n\n const availability = useMemo(\n () => availableValues(product, selection),\n [product, selection],\n );\n\n const isComplete = useMemo(() => {\n const axes = product.options || [];\n if (axes.length === 0) return true;\n return axes.every((a) => Boolean(selection[a.name]));\n }, [product, selection]);\n\n return { selection, variant, select, reset, availability, isComplete };\n}\n","\"use client\";\n\nimport { useCallback, useState } from \"react\";\n\n/**\n * Gift card balance check — Phase 8.3.\n *\n * Themes call this from the checkout payment step to validate a\n * customer-typed code before sending it as part of the checkout\n * payload. The backend returns 404 for any non-redeemable card\n * (expired, depleted, voided, or wrong store) — the response shape\n * stays uniform so the hook can't be used to probe for valid codes.\n *\n * Backend contract (via storefront proxy):\n * GET /api/gift-cards/{code}\n * → 200 { data: { last_four, current_balance_cents, currency,\n * expires_at? } }\n * → 404 { error: { code, message } }\n */\n\nexport interface GiftCardBalance {\n last_four: string;\n current_balance_cents: number;\n currency: string;\n expires_at: string | null;\n}\n\nexport interface UseGiftCardBalance {\n /** Last lookup result, or null when nothing checked yet / failed. */\n balance: GiftCardBalance | null;\n /** True while a lookup is in flight. */\n loading: boolean;\n /** Latest error from the lookup, if any. Cleared on next check. */\n error: Error | null;\n /** Trigger a balance check. Returns the result or null on failure. */\n check: (code: string) => Promise<GiftCardBalance | null>;\n /** Clear the last result + error (e.g. when the user clears the input). */\n reset: () => void;\n}\n\nexport function useGiftCardBalance(): UseGiftCardBalance {\n const [balance, setBalance] = useState<GiftCardBalance | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const check = useCallback(async (code: string): Promise<GiftCardBalance | null> => {\n if (typeof window === \"undefined\") return null;\n const trimmed = (code || \"\").trim();\n if (!trimmed) {\n setError(new Error(\"Enter a gift card code.\"));\n setBalance(null);\n return null;\n }\n setLoading(true);\n setError(null);\n try {\n const res = await fetch(\n `/api/gift-cards/${encodeURIComponent(trimmed)}`,\n { cache: \"no-store\" },\n );\n if (!res.ok) {\n setBalance(null);\n // 404 = invalid/redeemed/expired — surface a friendly message\n // rather than the raw API code so themes don't need to map it.\n if (res.status === 404) {\n setError(new Error(\"That gift card isn't valid or has been used up.\"));\n return null;\n }\n setError(new Error(`Couldn't check gift card (HTTP ${res.status}).`));\n return null;\n }\n const json = (await res.json()) as { data?: GiftCardBalance };\n const data = json?.data;\n if (!data) {\n setBalance(null);\n setError(new Error(\"Unexpected response from server.\"));\n return null;\n }\n setBalance(data);\n return data;\n } catch (err) {\n setBalance(null);\n setError(err instanceof Error ? err : new Error(String(err)));\n return null;\n } finally {\n setLoading(false);\n }\n }, []);\n\n const reset = useCallback(() => {\n setBalance(null);\n setError(null);\n }, []);\n\n return { balance, loading, error, check, reset };\n}\n","\"use client\";\n\nimport { useCallback, useState } from \"react\";\n\n/**\n * Reorder / \"buy again\" — Phase 8.5.\n *\n * Clones every line item from an existing order into the current cart.\n * The backend skips lines whose product is deleted/archived, whose\n * variant is gone, or that are out of stock — returning per-line\n * reasons so themes can show a \"couldn't add X items\" banner.\n *\n * Backend contract:\n * POST /storefront/me/orders/{order_id}/reorder\n * → 200 { data: { added_count, skipped[], cart_total_items } }\n * → 404 if order doesn't belong to the current customer\n */\n\nexport type ReorderSkipReason =\n | \"product_deleted\"\n | \"product_archived\"\n | \"out_of_stock\"\n | \"variant_unavailable\";\n\nexport interface ReorderSkippedItem {\n product_id: string;\n variant_id: string | null;\n quantity: number;\n reason: ReorderSkipReason | string;\n}\n\nexport interface ReorderResult {\n added_count: number;\n skipped: ReorderSkippedItem[];\n cart_total_items: number;\n}\n\nexport interface UseReorder {\n /** Last reorder result. */\n result: ReorderResult | null;\n /** True while a reorder is in flight. */\n loading: boolean;\n /** Latest error, cleared on next reorder call. */\n error: Error | null;\n /** Trigger the reorder. Returns the result or null on failure. */\n reorder: (orderId: string) => Promise<ReorderResult | null>;\n /** Clear the last result + error (e.g. after dismissing the banner). */\n reset: () => void;\n}\n\nexport function useReorder(): UseReorder {\n const [result, setResult] = useState<ReorderResult | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const reorder = useCallback(\n async (orderId: string): Promise<ReorderResult | null> => {\n if (typeof window === \"undefined\") return null;\n if (!orderId) {\n setError(new Error(\"Order id is required.\"));\n return null;\n }\n setLoading(true);\n setError(null);\n try {\n // Read the CSRF cookie value and echo it as a header — the\n // storefront's mutating proxies verify the double-submit.\n const csrf =\n typeof document !== \"undefined\"\n ? (document.cookie.match(/(?:^|; )numu_csrf=([^;]+)/)?.[1] ?? \"\")\n : \"\";\n const res = await fetch(\n `/api/customer/orders/${encodeURIComponent(orderId)}/reorder`,\n {\n method: \"POST\",\n headers: csrf ? { \"x-numu-csrf\": csrf } : {},\n credentials: \"include\",\n },\n );\n if (!res.ok) {\n if (res.status === 401) {\n setError(new Error(\"Please sign in to reorder.\"));\n } else if (res.status === 404) {\n setError(new Error(\"That order can't be found on your account.\"));\n } else {\n setError(new Error(`Couldn't reorder (HTTP ${res.status}).`));\n }\n return null;\n }\n const json = (await res.json()) as { data?: ReorderResult };\n const data = json?.data;\n if (!data) {\n setError(new Error(\"Unexpected response from server.\"));\n return null;\n }\n setResult(data);\n return data;\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n return null;\n } finally {\n setLoading(false);\n }\n },\n [],\n );\n\n const reset = useCallback(() => {\n setResult(null);\n setError(null);\n }, []);\n\n return { result, loading, error, reorder, reset };\n}\n","\"use client\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\n\n/**\n * Programmatic checkout driver — Phase 7.6.\n *\n * The storefront's multi-step checkout pages (Phase 1.2) own the\n * default flow: contact → shipping → payment → review → processing →\n * thank-you. This hook gives themes a programmatic alternative so a\n * BYOT theme can render the checkout exactly how it wants — single-\n * page, accordion, full-bleed hero, whatever — without being forced\n * through the platform's step pages.\n *\n * State lives in `numu_checkout_state` sessionStorage (same blob the\n * platform's step pages use) so themes that drive checkout\n * programmatically can hand off to the platform mid-flow (e.g. theme\n * collects contact + shipping, then redirects to /checkout/payment\n * for the gateway capture). The platform-side state machine guards\n * deep-links via `hasContactStep / hasShippingStep / hasPaymentStep`\n * regardless of how the state got populated.\n *\n * Usage:\n *\n * const checkout = useCheckout();\n * checkout.contact.set({ email, phone, shipping_address });\n * await checkout.shipping.refresh();\n * checkout.shipping.select(rate.id);\n * checkout.payment.select(\"paymob\");\n * const result = await checkout.placeOrder();\n * if (result.payment_url) window.location.assign(result.payment_url);\n */\n\nexport type CheckoutStep =\n | \"contact\"\n | \"shipping\"\n | \"payment\"\n | \"review\"\n | \"processing\";\n\nexport interface CheckoutAddress {\n first_name?: string;\n last_name?: string;\n line1?: string;\n line2?: string | null;\n city?: string;\n state?: string | null;\n postal_code?: string | null;\n country?: string;\n phone?: string | null;\n}\n\nexport interface ShippingRateOption {\n id: string;\n name: string;\n amount_cents: number;\n currency: string;\n estimated_days_min?: number | null;\n estimated_days_max?: number | null;\n carrier?: string | null;\n}\n\nexport interface CheckoutSessionState {\n email: string;\n phone: string;\n shipping_address: CheckoutAddress;\n selected_shipping_rate_id: string | null;\n shipping_method: string | null;\n payment_method: string | null;\n cod_requested: boolean;\n deposit_gateway: string | null;\n saved_payment_method_id: string | null;\n customer_notes: string;\n coupon_code: string;\n}\n\nexport interface PlaceOrderResult {\n order_id: string;\n order_number: string;\n total: number;\n currency: string;\n payment_status: string;\n payment_url?: string | null;\n payment_data?: Record<string, unknown> | null;\n}\n\nexport interface CheckoutApi {\n state: CheckoutSessionState;\n step: CheckoutStep;\n contact: {\n set: (input: {\n email?: string;\n phone?: string;\n shipping_address?: CheckoutAddress;\n }) => void;\n isComplete: () => boolean;\n };\n shipping: {\n rates: ShippingRateOption[] | null;\n loading: boolean;\n refresh: () => Promise<ShippingRateOption[]>;\n select: (rateId: string) => void;\n isComplete: () => boolean;\n };\n payment: {\n select: (\n method: string,\n opts?: { saved_payment_method_id?: string; deposit_gateway?: string },\n ) => void;\n isComplete: () => boolean;\n };\n setNotes: (notes: string) => void;\n setCoupon: (code: string) => void;\n placeOrder: () => Promise<PlaceOrderResult>;\n reset: () => void;\n}\n\nconst STORAGE_KEY = \"numu_checkout_state\";\n\nconst EMPTY_STATE: CheckoutSessionState = {\n email: \"\",\n phone: \"\",\n shipping_address: {},\n selected_shipping_rate_id: null,\n shipping_method: null,\n payment_method: null,\n cod_requested: false,\n deposit_gateway: null,\n saved_payment_method_id: null,\n customer_notes: \"\",\n coupon_code: \"\",\n};\n\nfunction readState(): CheckoutSessionState {\n if (typeof window === \"undefined\") return { ...EMPTY_STATE };\n try {\n const raw = window.sessionStorage.getItem(STORAGE_KEY);\n if (!raw) return { ...EMPTY_STATE };\n return { ...EMPTY_STATE, ...JSON.parse(raw) };\n } catch {\n return { ...EMPTY_STATE };\n }\n}\n\nfunction writeState(state: CheckoutSessionState): void {\n if (typeof window === \"undefined\") return;\n try {\n window.sessionStorage.setItem(STORAGE_KEY, JSON.stringify(state));\n // Notify any other useCheckout() consumers in the same tab.\n window.dispatchEvent(new CustomEvent(\"numu:checkout:updated\"));\n } catch {\n /* Safari private mode → swallow */\n }\n}\n\nfunction hasContact(s: CheckoutSessionState): boolean {\n return Boolean(\n s.email &&\n s.shipping_address?.line1 &&\n s.shipping_address?.city &&\n s.shipping_address?.country,\n );\n}\n\nfunction hasShipping(s: CheckoutSessionState): boolean {\n return hasContact(s) && Boolean(s.selected_shipping_rate_id);\n}\n\nfunction hasPayment(s: CheckoutSessionState): boolean {\n return hasShipping(s) && Boolean(s.payment_method);\n}\n\nfunction resolveStep(s: CheckoutSessionState): CheckoutStep {\n if (!hasContact(s)) return \"contact\";\n if (!hasShipping(s)) return \"shipping\";\n if (!hasPayment(s)) return \"payment\";\n return \"review\";\n}\n\nexport function useCheckout(): CheckoutApi {\n const [state, setState] = useState<CheckoutSessionState>(() => readState());\n const [rates, setRates] = useState<ShippingRateOption[] | null>(null);\n const [ratesLoading, setRatesLoading] = useState(false);\n\n // Sync from sessionStorage when other consumers update (other tab\n // would not trigger the same-tab event but storage event handles it).\n useEffect(() => {\n function onChange() {\n setState(readState());\n }\n window.addEventListener(\"numu:checkout:updated\", onChange);\n window.addEventListener(\"storage\", (e) => {\n if (e.key === STORAGE_KEY) onChange();\n });\n return () => {\n window.removeEventListener(\"numu:checkout:updated\", onChange);\n };\n }, []);\n\n const patch = useCallback((partial: Partial<CheckoutSessionState>) => {\n setState((prev) => {\n const next = { ...prev, ...partial };\n writeState(next);\n return next;\n });\n }, []);\n\n const refreshShipping = useCallback(async (): Promise<ShippingRateOption[]> => {\n setRatesLoading(true);\n try {\n const res = await fetch(\"/api/shipping/options\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ shipping_address: state.shipping_address }),\n });\n if (!res.ok) {\n setRates([]);\n return [];\n }\n const body = await res.json();\n const list: ShippingRateOption[] =\n (body?.data?.options || body?.data || body?.options || []) as ShippingRateOption[];\n setRates(list);\n return list;\n } catch {\n setRates([]);\n return [];\n } finally {\n setRatesLoading(false);\n }\n }, [state.shipping_address]);\n\n const placeOrder = useCallback(async (): Promise<PlaceOrderResult> => {\n // Cart line items are read server-side from the session cookie;\n // we still pass an empty list because the schema requires the field.\n const payload = {\n line_items: [],\n shipping_address: state.shipping_address,\n payment_method: state.payment_method,\n selected_shipping_rate_id: state.selected_shipping_rate_id,\n shipping_method: state.shipping_method,\n guest_email: state.email,\n cod_requested: state.cod_requested,\n deposit_gateway: state.deposit_gateway,\n saved_payment_method_id: state.saved_payment_method_id,\n customer_notes: state.customer_notes || null,\n coupon_code: state.coupon_code || null,\n };\n const res = await fetch(\"/api/checkout\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n // Idempotency-Key prevents a double-click double-charge.\n \"Idempotency-Key\":\n typeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n ? crypto.randomUUID()\n : `${Date.now()}-${Math.random()}`,\n },\n body: JSON.stringify(payload),\n });\n const body = await res.json();\n if (!res.ok) {\n const detail =\n body?.detail || body?.error || `Checkout failed (${res.status})`;\n throw new Error(typeof detail === \"string\" ? detail : JSON.stringify(detail));\n }\n const data = (body?.data || body) as PlaceOrderResult;\n return data;\n }, [state]);\n\n const step = useMemo(() => resolveStep(state), [state]);\n\n const api = useMemo<CheckoutApi>(\n () => ({\n state,\n step,\n contact: {\n set: (input) =>\n patch({\n ...(input.email !== undefined && { email: input.email }),\n ...(input.phone !== undefined && { phone: input.phone }),\n ...(input.shipping_address && {\n shipping_address: {\n ...state.shipping_address,\n ...input.shipping_address,\n },\n // Invalidate downstream picks when address changes.\n selected_shipping_rate_id: null,\n shipping_method: null,\n }),\n }),\n isComplete: () => hasContact(state),\n },\n shipping: {\n rates,\n loading: ratesLoading,\n refresh: refreshShipping,\n select: (rateId) => {\n const rate = rates?.find((r) => r.id === rateId);\n patch({\n selected_shipping_rate_id: rateId,\n shipping_method: rate?.name || null,\n });\n },\n isComplete: () => hasShipping(state),\n },\n payment: {\n select: (method, opts) =>\n patch({\n payment_method: method,\n cod_requested: method === \"cod\",\n deposit_gateway: opts?.deposit_gateway || null,\n saved_payment_method_id: opts?.saved_payment_method_id || null,\n }),\n isComplete: () => hasPayment(state),\n },\n setNotes: (notes) => patch({ customer_notes: notes }),\n setCoupon: (code) => patch({ coupon_code: code }),\n placeOrder,\n reset: () => {\n if (typeof window !== \"undefined\") {\n try {\n window.sessionStorage.removeItem(STORAGE_KEY);\n } catch {\n /* swallow */\n }\n }\n setState({ ...EMPTY_STATE });\n setRates(null);\n },\n }),\n [state, step, rates, ratesLoading, refreshShipping, placeOrder, patch],\n );\n\n return api;\n}\n","\"use client\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport type { CheckoutAddress, ShippingRateOption } from \"./useCheckout\";\n\n/**\n * Fetch shipping rate options for an address — Phase 7.4.\n *\n * Themes that want to display rates on the cart page (Shopify\n * pattern: \"Shipping calculated at checkout — preview from cart\")\n * use this. It posts to /api/shipping/options the same way the\n * platform's shipping step does, but as a self-contained hook so\n * themes don't need to drive the full useCheckout() machinery for a\n * simple display.\n *\n * Returns null when no address is provided (the typical pre-input\n * state) — themes branch on `rates !== null` to decide whether to\n * show the rates panel or a \"Enter address\" prompt.\n *\n * Optionally accepts a `location_id` for multi-location stores\n * (Phase 8.2) — the resolver uses the named fulfilling location's\n * origin address when calculating rates. Ignored if multi-location\n * is off.\n *\n * Usage:\n *\n * const { rates, loading, refresh } = useShippingRates({\n * address: { country: \"EG\", city: \"Cairo\" },\n * });\n */\n\nexport interface UseShippingRatesOptions {\n address?: CheckoutAddress | null;\n location_id?: string | null;\n /** Auto-fetch on mount + when the address changes. Default true. */\n enabled?: boolean;\n}\n\nexport interface UseShippingRatesState {\n rates: ShippingRateOption[] | null;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n}\n\nfunction isAddressSufficient(a?: CheckoutAddress | null): boolean {\n if (!a) return false;\n // Country alone gets a zone-level estimate; city + country gets\n // the rate properly. We require at least country since zones are\n // country-keyed.\n return Boolean(a.country);\n}\n\nexport function useShippingRates({\n address,\n location_id,\n enabled = true,\n}: UseShippingRatesOptions = {}): UseShippingRatesState {\n const [rates, setRates] = useState<ShippingRateOption[] | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const refresh = useCallback(async (): Promise<void> => {\n if (!isAddressSufficient(address)) {\n setRates(null);\n return;\n }\n setLoading(true);\n setError(null);\n try {\n const res = await fetch(\"/api/shipping/options\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n shipping_address: address,\n ...(location_id ? { location_id } : {}),\n }),\n });\n if (!res.ok) {\n // 404 = country not covered by any zone. Surface as \"no\n // rates\" rather than an error so themes can render a\n // \"We don't ship to {country}\" message gracefully.\n if (res.status === 404) {\n setRates([]);\n return;\n }\n throw new Error(`shipping rates: HTTP ${res.status}`);\n }\n const body = await res.json();\n const list: ShippingRateOption[] =\n (body?.data?.options || body?.data || body?.options || []) as ShippingRateOption[];\n setRates(list);\n } catch (e) {\n setError(e instanceof Error ? e : new Error(String(e)));\n setRates([]);\n } finally {\n setLoading(false);\n }\n }, [address, location_id]);\n\n useEffect(() => {\n if (!enabled) return;\n void refresh();\n }, [enabled, refresh]);\n\n return { rates, loading, error, refresh };\n}\n","\"use client\";\nimport {\n useEffect,\n useState,\n useCallback,\n useMemo,\n useRef,\n type ReactNode,\n} from \"react\";\nimport {\n ShopContext,\n CartContext,\n CustomerContext,\n ThemeSettingsContext,\n LocalizationContext,\n CurrentTemplateContext,\n PageContext,\n NavigationContext,\n} from \"../contexts\";\nimport {\n CustomerActionsContext,\n type CustomerActions,\n} from \"../contexts/customer-actions\";\nimport type { Store, Cart, Customer } from \"../types/entities\";\nimport type { ThemeSettingsV3 } from \"../types/theme\";\nimport type { LocalizationState, MenuItemData } from \"../contexts\";\n\nconst RTL_LOCALES = [\"ar\", \"he\", \"fa\", \"ur\"];\n\ninterface NuMuProviderProps {\n store: Store;\n themeSettings: ThemeSettingsV3;\n initialCart?: Cart;\n customer?: Customer | null;\n locale?: string;\n translations?: Record<string, string>;\n /**\n * Wave 5 — id of the active page template. Hosts pass this from the\n * route (e.g. \"product\" inside app/(store)/[subdomain]/product/[id]).\n * Themes read it via `useCurrentTemplate()` to render the matching\n * section list. Defaults to \"home\" when omitted, so existing themes\n * built before the prop existed keep rendering their home template.\n */\n currentTemplate?: string;\n /**\n * Pre-fetched product list for the current page. Themes that call\n * `useProducts()` will read these from PageContext without needing\n * `fetchIfMissing: true`. Hosts typically populate this from their\n * route loader / SSR pass; omitting it leaves `useProducts()`\n * returning an empty array unless the theme opts into client fetch.\n */\n initialProducts?: import(\"../types/entities\").Product[];\n /**\n * Pre-fetched collection list — same pattern as initialProducts for\n * `useCollections()`. Categories/collections shown on the home page\n * read this slot.\n */\n initialCollections?: import(\"../types/entities\").Collection[];\n /**\n * Phase 2.4 — store navigation menus keyed by handle (`main-menu`,\n * `footer`, …), resolved server-side by the host and injected so a\n * theme's `useNavigation(handle)` resolves synchronously without a\n * client round-trip. Omit for hosts/themes that don't wire menus —\n * `useNavigation` then falls back to its own fetch or the theme's\n * `DEFAULT_NAV`.\n */\n navigation?: Record<string, MenuItemData[]>;\n children: ReactNode;\n}\n\nconst EMPTY_CART: Cart = {\n id: \"\",\n items: [],\n subtotal: 0,\n total: 0,\n currency: \"EGP\",\n};\n\n/**\n * The storefront's /api/cart returns money in CENTS (matching the checkout\n * and built-in cart, which divide by 100 themselves). Themes consume the cart\n * via useCart() and render with <Money>/formatMoney, which expect MAJOR units\n * — the same convention as Product.price after the host normalizes it. Convert\n * cart money to major here so the BYOT boundary is consistent end-to-end.\n *\n * Display-only: checkout submits quantities (the server recomputes amounts),\n * so this never changes what the customer is charged.\n */\nfunction normalizeCartFromServer(cart: Cart): Cart {\n const toMajor = (n: number | null | undefined): number =>\n typeof n === \"number\" ? n / 100 : 0;\n return {\n ...cart,\n subtotal: toMajor(cart.subtotal),\n total: toMajor(cart.total),\n ...(cart.discount_amount != null\n ? { discount_amount: toMajor(cart.discount_amount) }\n : {}),\n items: Array.isArray(cart.items)\n ? cart.items.map((it) => ({ ...it, price: toMajor(it.price) }))\n : [],\n };\n}\n\n/**\n * Read the `numu_csrf` cookie value from document.cookie.\n *\n * The storefront's GET /api/cart sets this on first fetch; we echo it\n * back in `x-numu-csrf` on every mutation so the proxy can verify the\n * double-submit. Without this gate any XSS in a theme can drain the\n * customer's cart by hitting /api/cart/add directly.\n */\nfunction readCsrfCookie(): string | null {\n if (typeof document === \"undefined\") return null;\n const match = document.cookie.match(/(?:^|;\\s*)numu_csrf=([^;]+)/);\n return match ? decodeURIComponent(match[1]) : null;\n}\n\n/**\n * postCartMutation — shared helper for cart writes.\n *\n * Three concerns layered together:\n *\n * 1. Request versioning so a burst of \"+ + +\" clicks doesn't apply\n * stale responses. Each call reserves a token; only the response\n * for the highest-numbered token is allowed to update local state.\n *\n * 2. CSRF: every cart mutation includes `x-numu-csrf` from the cookie.\n * The /api/cart/* proxy compares cookie + header (double-submit)\n * and rejects mismatches with 403.\n *\n * 3. Idempotency: each call mints a UUID idempotency key. The\n * backend (when supported) caches the response for that key in\n * Redis so a double-clicked Add-to-Cart only mutates state once.\n * Wire format is stable; backend honoring it is opt-in.\n *\n * Returns the latest cart state (whatever the server says), but the\n * caller shouldn't blindly setState from it — `applyCart` already\n * filtered.\n */\nasync function postCartMutation(\n endpoint: string,\n body: unknown,\n applyCart: (cart: Cart) => void,\n reserveToken: () => number,\n): Promise<void> {\n const token = reserveToken();\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n const csrf = readCsrfCookie();\n if (csrf) headers[\"x-numu-csrf\"] = csrf;\n // Idempotency key — randomUUID is widely supported; fall back if not\n // (older Safari, embedded webviews).\n const idempotencyKey =\n typeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n ? crypto.randomUUID()\n : `${Date.now()}-${Math.random().toString(36).slice(2)}`;\n headers[\"x-numu-idempotency-key\"] = idempotencyKey;\n\n const res = await fetch(endpoint, {\n method: body === undefined ? \"DELETE\" : \"POST\",\n headers,\n body: body === undefined ? undefined : JSON.stringify(body),\n });\n if (!res.ok) return;\n const data = (await res.json()) as Cart;\n applyCart(data);\n // Token was actually consumed on entry; applyCart enforces ordering\n // via the closure below.\n void token;\n}\n\nexport function NuMuProvider({\n store,\n themeSettings,\n initialCart,\n customer,\n locale: initialLocale,\n translations: initialTranslations,\n currentTemplate = \"home\",\n initialProducts,\n initialCollections,\n navigation,\n children,\n}: NuMuProviderProps) {\n // Synthesise a Page record so `useProducts()` and `useCollections()`\n // can read pre-fetched lists via PageContext. Stable identity ensures\n // we don't bust the context on every render (initialProducts and\n // initialCollections come in as fresh arrays from the host's\n // useMemo'd ctx, so referential equality already holds across renders\n // without changes; useMemo here is belt-and-suspenders).\n const pageValue = useMemo(\n () =>\n ({\n type: currentTemplate,\n title: store?.name ?? \"\",\n data: {\n products: initialProducts ?? [],\n collections: initialCollections ?? [],\n },\n }) as import(\"../types/entities\").Page,\n [currentTemplate, store?.name, initialProducts, initialCollections],\n );\n const [cart, setCart] = useState<Cart>(\n initialCart || { ...EMPTY_CART, currency: store.currency },\n );\n const [loading, setLoading] = useState(false);\n // Phase 3.6 — locale precedence:\n // 1. `initialLocale` prop (storefront pages that resolved it server-side)\n // 2. `numu_locale` cookie (client-side fallback for pages that don't\n // thread the prop through)\n // 3. `store.default_language`\n // 4. \"en\"\n const [locale, setLocale] = useState(() => {\n if (initialLocale) return initialLocale;\n if (typeof document !== \"undefined\") {\n const m = document.cookie.match(/(?:^|; )numu_locale=([^;]+)/);\n if (m) return decodeURIComponent(m[1]);\n }\n return store.default_language || \"en\";\n });\n const [translations] = useState(initialTranslations || {});\n\n // ── Customer state + auth actions ──────────────────────────────────────\n // Customer comes from one of three sources, in order of precedence:\n // 1. SSR-supplied `customer` prop (when /account/* routes pre-fetch\n // the customer server-side via the cookie).\n // 2. The mount effect below which calls GET /api/customer/me, used\n // on routes that don't pre-fetch (home/product/etc.) to keep the\n // cart drawer / header user menu accurate.\n // 3. Mutations triggered by `useCustomerActions()` (login/logout/\n // register/updateProfile) — these refresh state immediately.\n const [customerState, setCustomerState] = useState<Customer | null>(\n customer ?? null,\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n // Skip the GET if the SSR pass already supplied a customer; the\n // round-trip would only confirm what we already know and waste a\n // request budget on every navigation.\n if (customer) return;\n let cancelled = false;\n void (async () => {\n try {\n const res = await fetch(\"/api/customer/me\", {\n method: \"GET\",\n credentials: \"include\",\n cache: \"no-store\",\n });\n if (cancelled) return;\n // 401 means logged-out: leave customerState=null. Any other\n // non-OK is treated the same — the customer can still browse.\n if (!res.ok) return;\n const json = await res.json();\n const next =\n json && typeof json === \"object\" && \"data\" in json\n ? (json as { data: Customer }).data\n : (json as Customer);\n if (next && typeof next === \"object\") {\n setCustomerState(next);\n }\n } catch {\n // Network blip — keep current customerState.\n }\n })();\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Refresh re-fetches /api/customer/me; used after any mutation that\n // changed the customer record (login/register/profile update).\n const refreshCustomer = useCallback(async () => {\n if (typeof window === \"undefined\") return;\n try {\n const res = await fetch(\"/api/customer/me\", {\n method: \"GET\",\n credentials: \"include\",\n cache: \"no-store\",\n });\n if (res.status === 401) {\n setCustomerState(null);\n return;\n }\n if (!res.ok) return;\n const json = await res.json();\n const next =\n json && typeof json === \"object\" && \"data\" in json\n ? (json as { data: Customer }).data\n : (json as Customer);\n setCustomerState(next ?? null);\n } catch {\n // ignore\n }\n }, []);\n\n // CSRF: customer mutations echo `numu_csrf` cookie value as header\n // for double-submit. Read just-in-time so we always send the freshest\n // (the cookie may rotate on /api/cart roundtrip).\n function readCsrf(): string | null {\n if (typeof document === \"undefined\") return null;\n const m = document.cookie.match(/(?:^|; )numu_csrf=([^;]+)/);\n return m ? decodeURIComponent(m[1]) : null;\n }\n\n async function postCustomer(path: string, body: unknown): Promise<unknown> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n const csrf = readCsrf();\n if (csrf) headers[\"x-numu-csrf\"] = csrf;\n const res = await fetch(path, {\n method: \"POST\",\n credentials: \"include\",\n cache: \"no-store\",\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n let json: unknown = null;\n try {\n json = await res.json();\n } catch {\n // empty body — fine\n }\n return json;\n }\n\n async function putCustomer(path: string, body: unknown): Promise<unknown> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n const csrf = readCsrf();\n if (csrf) headers[\"x-numu-csrf\"] = csrf;\n const res = await fetch(path, {\n method: \"PUT\",\n credentials: \"include\",\n cache: \"no-store\",\n headers,\n body: JSON.stringify(body ?? {}),\n });\n try {\n return await res.json();\n } catch {\n return null;\n }\n }\n\n const customerActions: CustomerActions = useMemo(\n () => ({\n login: async (input) => {\n const r = await postCustomer(\"/api/customer/login\", input);\n await refreshCustomer();\n return r;\n },\n register: async (input) => {\n const r = await postCustomer(\"/api/customer/register\", input);\n await refreshCustomer();\n return r;\n },\n logout: async () => {\n const r = await postCustomer(\"/api/customer/logout\", {});\n // Don't wait on refresh — backend cleared the cookie, so\n // setCustomerState(null) directly avoids a redundant 401.\n setCustomerState(null);\n return r;\n },\n requestRecover: (input) =>\n postCustomer(\"/api/customer/recover\", input),\n confirmReset: async (input) => {\n const r = await postCustomer(\"/api/customer/reset\", input);\n // Reset clears all sessions on the backend; user must log in\n // again. Force null so any stale state from before the reset\n // doesn't linger.\n setCustomerState(null);\n return r;\n },\n verifyEmail: async (input) => {\n const r = await postCustomer(\"/api/customer/verify-email\", input);\n await refreshCustomer();\n return r;\n },\n resendVerification: (input) =>\n postCustomer(\"/api/customer/resend-verification\", input),\n updateProfile: async (input) => {\n const r = await putCustomer(\"/api/customer/me\", input);\n await refreshCustomer();\n return r;\n },\n changePassword: (input) =>\n putCustomer(\"/api/customer/me/password\", input),\n refresh: refreshCustomer,\n }),\n [refreshCustomer],\n );\n\n // ── Initial cart fetch ─────────────────────────────────────────────────\n // GET /api/cart on mount serves two purposes:\n // 1. Hydrates the live cart state for returning visitors so the\n // header cart count is accurate before any user interaction.\n // 2. Mints the `numu_csrf` cookie (the storefront's GET /api/cart\n // handler emits Set-Cookie if missing). Subsequent cart-write\n // calls read this cookie via document.cookie and echo it as\n // the `x-numu-csrf` header for double-submit verification.\n // Without this priming round-trip, a first-Add-to-Cart 403s\n // because the cookie hasn't been issued yet.\n //\n // SSR-safe: `fetch` is a browser-only call here; we gate on `window`.\n // Errors are swallowed — the cart context starts empty either way,\n // and downstream actions surface their own errors.\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n let cancelled = false;\n void (async () => {\n try {\n const res = await fetch(\"/api/cart\", {\n method: \"GET\",\n credentials: \"include\",\n cache: \"no-store\",\n });\n if (!res.ok || cancelled) return;\n const data = (await res.json()) as Cart;\n if (data && typeof data === \"object\") {\n setCart(normalizeCartFromServer(data));\n }\n } catch {\n // Network blip / not-yet-deployed cart endpoint. Leave the\n // empty initial cart in place; the user can still browse.\n }\n })();\n return () => {\n cancelled = true;\n };\n // Run once per mount; the cart endpoint is idempotent and the\n // CSRF cookie persists across navigations within the SPA.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // ── Request-versioning machinery ───────────────────────────────────────\n // `nextRequestId` increases on each cart mutation; `latestApplied` tracks\n // the highest id whose response has been applied. A response is applied\n // only if its id is >= latestApplied (i.e., not superseded).\n const nextRequestId = useRef(0);\n const latestApplied = useRef(0);\n\n const reserveToken = useCallback(() => {\n nextRequestId.current += 1;\n return nextRequestId.current;\n }, []);\n\n const buildApplyCart = useCallback(\n (token: number) => (newCart: Cart) => {\n if (token < latestApplied.current) {\n // A later request has already updated state — ignore stale response.\n return;\n }\n latestApplied.current = token;\n setCart(normalizeCartFromServer(newCart));\n },\n [],\n );\n\n const mutate = useCallback(\n async (endpoint: string, body: unknown): Promise<void> => {\n const token = reserveToken();\n setLoading(true);\n try {\n await postCartMutation(\n endpoint,\n body,\n buildApplyCart(token),\n () => token, // already reserved; just return the same token\n );\n } finally {\n setLoading(false);\n }\n },\n [reserveToken, buildApplyCart],\n );\n\n // ── Cart actions ───────────────────────────────────────────────────────\n\n const addItem = useCallback(\n async (productId: string, variantId?: string, quantity?: number) => {\n await mutate(\"/api/cart/add\", {\n product_id: productId,\n variant_id: variantId,\n quantity: quantity || 1,\n });\n },\n [mutate],\n );\n\n const removeItem = useCallback(\n async (itemId: string) => {\n await mutate(\"/api/cart/remove\", { item_id: itemId });\n },\n [mutate],\n );\n\n const updateQuantity = useCallback(\n async (itemId: string, quantity: number) => {\n await mutate(\"/api/cart/update\", { item_id: itemId, quantity });\n },\n [mutate],\n );\n\n const applyDiscount = useCallback(\n async (code: string) => {\n await mutate(\"/api/cart/discount\", { code });\n },\n [mutate],\n );\n\n const removeDiscount = useCallback(async () => {\n // DELETE — postCartMutation interprets undefined body as DELETE.\n await mutate(\"/api/cart/discount\", undefined);\n }, [mutate]);\n\n /**\n * Persist a customer note on the cart. Round-trips to the backend so the\n * note survives reload (the previous local-only behavior was a footgun).\n */\n const updateNote = useCallback(\n async (note: string) => {\n await mutate(\"/api/cart/update\", { note });\n },\n [mutate],\n );\n\n const clearCart = useCallback(async () => {\n setCart({ ...EMPTY_CART, currency: store.currency });\n }, [store.currency]);\n\n // Broadcast a `numu:cart:updated` CustomEvent on every cart change.\n // Why: non-React themes (vanilla JS / Alpine / Vue islands) can't\n // consume `useCart()`. They listen on `window` instead, which gives\n // them the same write-then-react contract React themes get for free.\n // The event detail mirrors the React `cart` shape so consumers don't\n // need to re-fetch.\n //\n // We skip the first dispatch — the initial state is the empty\n // placeholder before the GET /api/cart response lands, and themes\n // that ran their own `numu:cart:fetched`-style logic on page load\n // would otherwise see a spurious empty event right after rendering.\n const cartFirstRender = useRef(true);\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n if (cartFirstRender.current) {\n cartFirstRender.current = false;\n return;\n }\n window.dispatchEvent(\n new CustomEvent(\"numu:cart:updated\", { detail: cart }),\n );\n }, [cart]);\n\n const cartValue = useMemo(\n () => ({\n cart,\n addItem,\n removeItem,\n updateQuantity,\n applyDiscount,\n removeDiscount,\n updateNote,\n clearCart,\n loading,\n }),\n [\n cart,\n addItem,\n removeItem,\n updateQuantity,\n applyDiscount,\n removeDiscount,\n updateNote,\n clearCart,\n loading,\n ],\n );\n\n // ── Localization with memoized Intl formatters ─────────────────────────\n // Building Intl.NumberFormat / Intl.DateTimeFormat per call is costly;\n // memoize on (locale, currency).\n //\n // Resilience: stores can come back from older API rows with `currency`\n // null/empty. `Intl.NumberFormat({ currency: \"\" })` throws \"Currency\n // code is required with currency style\", which crashes the entire\n // render tree. Fall back to USD for the formatter so themes keep\n // working — merchants will see prices in USD until they configure a\n // real currency, which is a clearer signal than a blank screen.\n const safeCurrency = (store.currency || \"USD\").toUpperCase();\n\n // Phase 3.7 — numeral system. Merchants opt into Arab-Indic\n // digits (٠١٢٣٤) for Arabic stores via store.settings.numerals.\n // Western (default) keeps the ASCII digits everyone's used to.\n // We construct intl locales with the appropriate `-u-nu-<system>`\n // extension so money + date + count formatters all stay consistent.\n const numeralSystem =\n ((store as unknown as { settings?: { numerals?: string } }).settings\n ?.numerals === \"arabic\")\n ? \"arab\"\n : \"latn\";\n const intlLocale = `${locale}-u-nu-${numeralSystem}`;\n\n // We deliberately compute intlLocale BEFORE these memos so the\n // numbering-system extension is part of the formatter cache key —\n // a merchant flipping store.settings.numerals from \"western\" to\n // \"arabic\" rebuilds the formatters on the next render rather than\n // continuing to render Western digits from the stale cache.\n const moneyFmt = useMemo(() => {\n try {\n return new Intl.NumberFormat(intlLocale, {\n style: \"currency\",\n currency: safeCurrency,\n });\n } catch {\n // Pathologic intlLocale (engine doesn't support `-u-nu-arab`\n // for the active language) — fall back to the bare locale.\n return new Intl.NumberFormat(locale, {\n style: \"currency\",\n currency: safeCurrency,\n });\n }\n }, [intlLocale, locale, safeCurrency]);\n const dateFmt = useMemo(() => {\n try {\n return new Intl.DateTimeFormat(intlLocale, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n });\n } catch {\n return new Intl.DateTimeFormat(locale, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n });\n }\n }, [intlLocale, locale]);\n\n // Phase 3.6 — locales the store advertises. Falls back to a single-\n // entry list (the active locale) so themes can render the\n // LocaleSwitcher unconditionally without an extra check.\n const availableLocales = useMemo(() => {\n const list =\n (store as unknown as { available_locales?: string[] }).available_locales;\n if (Array.isArray(list) && list.length > 0) return list;\n return [locale];\n }, [store, locale]);\n\n // Phase 3.6 — locale switcher. Writes the cookie + reloads so the\n // server-rendered layout picks up the change. We prefer cookie over\n // querystring because cookie persists across cross-page navigation\n // without each page having to thread `?locale=ar` through every link.\n const switchLocale = useCallback((next: string) => {\n if (typeof document === \"undefined\") return;\n if (!next) return;\n // 1-year cookie; SameSite=Lax so it travels with same-origin nav\n // but doesn't leak on cross-site requests. Path=/ so every page\n // sees it.\n document.cookie =\n `numu_locale=${encodeURIComponent(next)}; ` +\n `Path=/; Max-Age=${60 * 60 * 24 * 365}; SameSite=Lax`;\n setLocale(next);\n // Reload so SSR re-runs with the new cookie. Themes that want\n // client-only locale swaps (no SSR re-render) can wrap their text\n // in `useTranslation()` and skip the reload — but locale-aware\n // SSR data (translated product names, RTL <html dir>) needs the\n // reload to take effect.\n if (typeof window !== \"undefined\") {\n window.location.reload();\n }\n }, []);\n\n // Default (no-options) number formatter — memoized so the formatNumber\n // hot path doesn't construct one per call. Declared BEFORE the\n // localization useMemo so the closure captures the resolved value.\n const defaultNumberFmt = useMemo(() => {\n try {\n return new Intl.NumberFormat(intlLocale);\n } catch {\n return new Intl.NumberFormat(locale);\n }\n }, [intlLocale, locale]);\n\n const localization: LocalizationState = useMemo(\n () => ({\n locale,\n direction: RTL_LOCALES.includes(locale) ? \"rtl\" : \"ltr\",\n translations,\n availableLocales,\n setLocale: switchLocale,\n formatMoney: (amount: number, currency?: string) => {\n const ccy = (currency || safeCurrency).toUpperCase();\n if (ccy !== safeCurrency) {\n // Override-currency path is rare; pay the formatter cost only here.\n // Empty/invalid override falls back to the store's safeCurrency\n // before this branch via the `||` above, so we never construct\n // an Intl.NumberFormat with `currency: \"\"`.\n try {\n return new Intl.NumberFormat(intlLocale, {\n style: \"currency\",\n currency: ccy,\n }).format(amount);\n } catch {\n return moneyFmt.format(amount);\n }\n }\n return moneyFmt.format(amount);\n },\n formatDate: (date: string | Date) =>\n dateFmt.format(typeof date === \"string\" ? new Date(date) : date),\n formatNumber: (n: number, options?: Intl.NumberFormatOptions) => {\n if (!options) return defaultNumberFmt.format(n);\n try {\n return new Intl.NumberFormat(intlLocale, options).format(n);\n } catch {\n return String(n);\n }\n },\n }),\n [\n locale,\n translations,\n safeCurrency,\n moneyFmt,\n dateFmt,\n availableLocales,\n switchLocale,\n intlLocale,\n defaultNumberFmt,\n ],\n );\n\n return (\n <ShopContext.Provider value={store}>\n <ThemeSettingsContext.Provider value={themeSettings}>\n <CurrentTemplateContext.Provider value={currentTemplate}>\n <PageContext.Provider value={pageValue}>\n <LocalizationContext.Provider value={localization}>\n <CartContext.Provider value={cartValue}>\n <CustomerContext.Provider value={customerState}>\n <CustomerActionsContext.Provider value={customerActions}>\n <NavigationContext.Provider value={navigation ?? {}}>\n {children}\n </NavigationContext.Provider>\n </CustomerActionsContext.Provider>\n </CustomerContext.Provider>\n </CartContext.Provider>\n </LocalizationContext.Provider>\n </PageContext.Provider>\n </CurrentTemplateContext.Provider>\n </ThemeSettingsContext.Provider>\n </ShopContext.Provider>\n );\n}\n","\"use client\";\nimport type { ReactNode } from \"react\";\nimport { ProductContext } from \"../contexts\";\nimport type { Product } from \"../types/entities\";\n\ninterface ProductProviderProps {\n product: Product;\n children: ReactNode;\n}\n\nexport function ProductProvider({ product, children }: ProductProviderProps) {\n return <ProductContext.Provider value={product}>{children}</ProductContext.Provider>;\n}\n","/**\n * `applyGlobalStyleTokens(globalSettings, el)` — Phase 3.5.\n *\n * Bridges a store's **global theme settings** (colors, fonts, layout) to\n * **CSS custom properties** on the bundle's mount root, so editing a color\n * or font in Theme Settings actually re-paints the storefront. Before this,\n * themes shipped static CSS tokens that nothing wrote to → the pickers were\n * a silent no-op.\n *\n * ## Token contract (canonical names every theme can rely on)\n *\n * For each global setting `<id>` we set `--theme-<id>` verbatim (colors as\n * their value, fonts resolved to a CSS font stack, other scalars as-is).\n * Themes consume these with the current static value as a fallback:\n *\n * --by-cream: var(--theme-background_color, #f7f1e8);\n * --by-espresso: var(--theme-primary_color, #3a2418);\n * --by-font-serif: var(--theme-heading_font, \"Cormorant Garamond\", serif);\n *\n * In addition, well-known ids are aliased to **role** tokens so themes that\n * prefer semantic names share one vocabulary:\n *\n * colors → --theme-color-{background,text,primary,secondary,accent,border,button}\n * fonts → --theme-font-{heading,body}\n *\n * `color_scheme` / `color_scheme_group` settings (object values keyed by role)\n * emit `--scheme-<id>-<role>`.\n *\n * The helper is **idempotent** and safe to call on every `applyDraft` so the\n * customizer's live preview re-paints as the merchant drags a color.\n */\n\ntype GlobalSettings = Record<string, unknown> | null | undefined;\n\n/** id → canonical color role. Covers both `<role>_color` and `color_<role>`. */\nconst COLOR_ROLE_ALIASES: Record<string, string> = {\n background_color: \"background\",\n color_background: \"background\",\n bg_color: \"background\",\n text_color: \"text\",\n color_text: \"text\",\n primary_color: \"primary\",\n color_primary: \"primary\",\n secondary_color: \"secondary\",\n color_secondary: \"secondary\",\n accent_color: \"accent\",\n color_accent: \"accent\",\n border_color: \"border\",\n color_border: \"border\",\n button_color: \"button\",\n color_button: \"button\",\n button_text_color: \"button-text\",\n color_button_text: \"button-text\",\n};\n\n/** id → canonical font role. */\nconst FONT_ROLE_ALIASES: Record<string, string> = {\n heading_font: \"heading\",\n font_heading: \"heading\",\n headings_font: \"heading\",\n body_font: \"body\",\n font_body: \"body\",\n text_font: \"body\",\n};\n\n/**\n * Font token → CSS stack + optional Google Fonts href. A `font_picker`/select\n * stores a token (e.g. \"cormorant\"); we resolve it to a real stack and inject\n * the webfont so a picked font actually loads. Unknown tokens fall through and\n * are used verbatim as the family (so a theme can store a raw stack too).\n */\nconst FONT_REGISTRY: Record<string, { stack: string; href?: string }> = {\n cormorant: {\n stack: '\"Cormorant Garamond\", Georgia, \"Times New Roman\", serif',\n href: \"https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;0,700;1,400&display=swap\",\n },\n \"dm-sans\": {\n stack: '\"DM Sans\", system-ui, -apple-system, \"Segoe UI\", sans-serif',\n href: \"https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,400;0,9..40,500;0,9..40,700&display=swap\",\n },\n playfair: {\n stack: '\"Playfair Display\", Georgia, serif',\n href: \"https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;500;600;700&display=swap\",\n },\n inter: {\n stack: '\"Inter\", system-ui, -apple-system, sans-serif',\n href: \"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap\",\n },\n poppins: {\n stack: '\"Poppins\", system-ui, sans-serif',\n href: \"https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap\",\n },\n montserrat: {\n stack: '\"Montserrat\", system-ui, sans-serif',\n href: \"https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap\",\n },\n lora: {\n stack: '\"Lora\", Georgia, serif',\n href: \"https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400;0,500;0,600;1,400&display=swap\",\n },\n cairo: {\n stack: '\"Cairo\", system-ui, sans-serif',\n href: \"https://fonts.googleapis.com/css2?family=Cairo:wght@400;500;600;700&display=swap\",\n },\n tajawal: {\n stack: '\"Tajawal\", system-ui, sans-serif',\n href: \"https://fonts.googleapis.com/css2?family=Tajawal:wght@400;500;700&display=swap\",\n },\n};\n\nconst COLOR_RE = /^(#([0-9a-f]{3,8})|rgba?\\(|hsla?\\(|color\\(|var\\()/i;\n\nfunction isColorValue(v: unknown): v is string {\n return typeof v === \"string\" && COLOR_RE.test(v.trim());\n}\n\nfunction isFontToken(v: unknown): v is string {\n return typeof v === \"string\" && Object.prototype.hasOwnProperty.call(FONT_REGISTRY, v);\n}\n\n/** Idempotently inject a webfont <link> into <head>. */\nfunction injectFontLink(href: string): void {\n if (typeof document === \"undefined\" || !href) return;\n const existing = document.querySelector(\n `link[data-numu-font][href=\"${href}\"]`,\n );\n if (existing) return;\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = href;\n link.setAttribute(\"data-numu-font\", \"\");\n document.head.appendChild(link);\n}\n\n/**\n * Resolve a font setting value to a CSS stack. Known tokens map through the\n * registry (and load the webfont); anything else is treated as a literal\n * family/stack the theme author supplied.\n */\nexport function resolveFontStack(value: string): string {\n const entry = FONT_REGISTRY[value];\n if (entry) {\n if (entry.href) injectFontLink(entry.href);\n return entry.stack;\n }\n return value;\n}\n\n/**\n * Map a store's global settings onto CSS custom properties on `el`. Call on\n * mount and on every `applyDraft` (live preview). No-op when `el` or the\n * settings are missing. Reserved `__`-prefixed keys (e.g. `__translations`)\n * are skipped.\n */\nexport function applyGlobalStyleTokens(\n globalSettings: GlobalSettings,\n el: HTMLElement | null | undefined,\n): void {\n if (!el || !globalSettings || typeof globalSettings !== \"object\") return;\n const style = el.style;\n\n for (const [key, value] of Object.entries(globalSettings)) {\n if (!key || key.startsWith(\"__\")) continue;\n\n // color_scheme / color_scheme_group → object of role:color\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n for (const [role, c] of Object.entries(value as Record<string, unknown>)) {\n if (isColorValue(c)) style.setProperty(`--scheme-${key}-${role}`, c);\n }\n continue;\n }\n\n if (isColorValue(value)) {\n style.setProperty(`--theme-${key}`, value.trim());\n const role = COLOR_ROLE_ALIASES[key];\n if (role) style.setProperty(`--theme-color-${role}`, value.trim());\n continue;\n }\n\n if (isFontToken(value)) {\n const stack = resolveFontStack(value);\n style.setProperty(`--theme-${key}`, stack);\n const role = FONT_ROLE_ALIASES[key];\n if (role) style.setProperty(`--theme-font-${role}`, stack);\n continue;\n }\n\n // Plain scalar (layout values like page_width \"1240px\", spacing, etc.).\n if (typeof value === \"string\" || typeof value === \"number\") {\n const v = String(value).trim();\n if (v) style.setProperty(`--theme-${key}`, v);\n }\n }\n}\n","\"use client\";\n\n/**\n * `mountTheme(el, ctx, renderApp)` — the canonical V3 bundle entry helper.\n *\n * ## Why this exists\n *\n * Every theme bundle exports `mount(el, ctx): MountResult`. Historically each\n * theme hand-wrote that function, and the wiring it needs is non-trivial and\n * easy to get wrong:\n *\n * 1. **Forward the real catalog.** The host ships the page's products /\n * collections in `ctx.page.data` (home + listing routes) and the product\n * in `ctx.page.data.product` (PDP). A theme that doesn't pass these into\n * `NuMuProvider` (+ wrap the PDP in `<ProductProvider>`) sees\n * `useProducts()` / `useProductOptional()` return empty on a REAL store —\n * so product sections render \"No products yet\" or fall back to demo data\n * on a stocked merchant. This was the single most common BYOT bug:\n * only bon-younes wired it; the other 13 themes dropped the catalog.\n *\n * 2. **Apply global style tokens.** Merchant-chosen colors/fonts live in\n * `themeSettings.global_settings`; they only paint if the bundle calls\n * `applyGlobalStyleTokens` on its mount root (and resolves font tokens\n * to real stacks + injects the webfont link). Themes that skipped this\n * ignored every color/font picker.\n *\n * 3. **Forward navigation.** `useNavigation(handle)` only resolves the\n * header/footer menus the host pre-resolved if the bundle passes\n * `ctx.navigation` into `NuMuProvider`.\n *\n * 4. **Live-preview + lifecycle.** The customizer streams draft settings via\n * the host's `applyDraft`; the bundle must hold them in state and re-paint\n * the style tokens on every draft. And it must return a `MountResult`\n * (`cleanup` + `applyDraft`) the host's `ByotThemeBoundary` understands.\n *\n * `mountTheme` does all of that once, so a theme's `main.tsx` collapses to:\n *\n * ```tsx\n * import { mountTheme } from \"@numueg/theme-sdk\";\n * export function mount(el, ctx) {\n * return mountTheme(el, ctx, ({ currentTemplate }) =>\n * <ThemeApp currentTemplate={currentTemplate} />,\n * );\n * }\n * ```\n *\n * The theme owns only its section list (`ThemeApp`). Everything in the list\n * above is handled here — fix it once, every theme benefits.\n *\n * ## Both ctx shapes\n *\n * The host (numu-storefront `ByotThemeBoundary`) passes\n * `{ themeSettings, storeData, page, locale, demo, navigation }`. Older / dev\n * contexts used `{ store, currentTemplate }`. We normalise both so a bundle\n * built against this helper works regardless of which host calls it.\n */\n\nimport {\n StrictMode,\n forwardRef,\n useEffect,\n useImperativeHandle,\n useState,\n type ReactNode,\n} from \"react\";\nimport { createRoot, type Root } from \"react-dom/client\";\n\nimport { NuMuProvider } from \"./components/NuMuProvider\";\nimport { ProductProvider } from \"./components/ProductProvider\";\nimport { applyGlobalStyleTokens, resolveFontStack } from \"./utils/styleTokens\";\nimport type {\n Store,\n Cart,\n Customer,\n Product,\n Collection,\n} from \"./types/entities\";\nimport type { ThemeSettingsV3, MountResult } from \"./types/theme\";\nimport type { MenuItemData } from \"./contexts\";\n\n/** Minimal page descriptor the host forwards in the mount context. */\nexport interface ThemeMountPage {\n type?: string;\n handle?: string;\n title?: string;\n data?: Record<string, unknown>;\n}\n\n/**\n * The mount context a host (or dev harness) passes to a bundle's `mount`.\n * Accepts both the current storefront shape (`storeData`/`page`) and the\n * legacy/dev shape (`store`/`currentTemplate`); `mountTheme` normalises them.\n */\nexport interface ThemeMountContext {\n // Current storefront contract\n storeData?: Store;\n page?: ThemeMountPage;\n // Legacy / dev contract\n store?: Store;\n currentTemplate?: string;\n // Common\n themeSettings: ThemeSettingsV3;\n initialCart?: Cart;\n customer?: Customer | null;\n locale?: string;\n translations?: Record<string, string>;\n /** AUTHORITATIVE marketplace-preview flag from the host (true only for the\n * catalog \"Try theme\" preview). Themes with demo-image fallbacks gate on\n * it so a real installed store never shows demo imagery. */\n demo?: boolean;\n /** Store navigation menus keyed by handle, resolved server-side. */\n navigation?: Record<string, MenuItemData[]>;\n [extra: string]: unknown;\n}\n\n/** Arguments handed to a theme's render callback on every (re)render. */\nexport interface ThemeRenderArgs {\n /** Active template key — \"home\" | \"product\" | \"collection\" | \"cart\" | … */\n currentTemplate: string;\n /** Marketplace-preview flag (see ThemeMountContext.demo). */\n demo: boolean;\n /** The raw host page descriptor (type/handle/data), or null. */\n page: ThemeMountPage | null;\n /** Normalised store record (never undefined). */\n store: Store;\n /** Live theme settings (reflects customizer drafts via applyDraft). */\n themeSettings: ThemeSettingsV3;\n}\n\ninterface DraftHandle {\n applyDraft: (next: ThemeSettingsV3) => void;\n}\n\n/** Normalise the two ctx shapes' store slot; never return undefined — SDK\n * code reads `store.currency` without optional chaining and would throw. */\nfunction pickStore(ctx: ThemeMountContext): Store {\n const s = ctx.storeData ?? ctx.store;\n if (s) return s;\n return {\n id: \"unknown\",\n name: \"Store\",\n slug: \"store\",\n currency: \"EGP\",\n default_language: \"en\",\n use_nextjs_storefront: true,\n } as Store;\n}\n\n/** Resolve the active template from either contract, defaulting to \"home\". */\nfunction pickTemplate(ctx: ThemeMountContext): string {\n if (typeof ctx.currentTemplate === \"string\" && ctx.currentTemplate) {\n return ctx.currentTemplate;\n }\n const pageType = ctx.page?.type;\n if (typeof pageType === \"string\" && pageType) return pageType;\n return \"home\";\n}\n\n/** Resolve the demo flag: explicit host flag wins; else infer from empty\n * templates (the marketplace preview ships none → render bundled preset). */\nfunction pickDemo(ctx: ThemeMountContext, themeSettings: ThemeSettingsV3): boolean {\n if (typeof ctx.demo === \"boolean\") return ctx.demo;\n const t = themeSettings.templates;\n return !t || Object.keys(t).length === 0;\n}\n\n/**\n * Bridge that holds live draft settings, re-applies global style tokens on\n * every change, and wires the full provider stack (catalog + nav) around the\n * theme's app. Exposes `applyDraft` so the host can stream customizer edits.\n */\nconst ThemeMountBridge = forwardRef<\n DraftHandle,\n {\n ctx: ThemeMountContext;\n mountEl: HTMLElement;\n renderApp: (args: ThemeRenderArgs) => ReactNode;\n }\n>(function ThemeMountBridge({ ctx, mountEl, renderApp }, ref) {\n const [themeSettings, setThemeSettings] = useState<ThemeSettingsV3>(\n ctx.themeSettings,\n );\n useImperativeHandle(\n ref,\n () => ({\n applyDraft: (next) =>\n setThemeSettings((prev) => (prev === next ? prev : next)),\n }),\n [],\n );\n\n // Global settings (colors/fonts/layout) → CSS custom properties on the\n // mount root. Re-runs on every draft so the customizer's live preview\n // re-paints as a merchant drags a color or picks a font.\n useEffect(() => {\n const gs = (themeSettings.global_settings ?? {}) as Record<string, unknown>;\n applyGlobalStyleTokens(gs, mountEl);\n // Fonts: applyGlobalStyleTokens only writes a stack for tokens in its\n // built-in FONT_REGISTRY; the platform's wider font catalog would\n // otherwise fall through as a bare name with no webfont link. Resolve\n // heading/body explicitly so any picked font loads + gets a real stack,\n // writing the exact vars themes read.\n const headingFont = gs.heading_font;\n if (typeof headingFont === \"string\" && headingFont.trim()) {\n mountEl.style.setProperty(\n \"--theme-heading_font\",\n resolveFontStack(headingFont),\n );\n }\n const bodyFont = gs.body_font;\n if (typeof bodyFont === \"string\" && bodyFont.trim()) {\n mountEl.style.setProperty(\"--theme-body_font\", resolveFontStack(bodyFont));\n }\n }, [themeSettings, mountEl]);\n\n const store = pickStore(ctx);\n const template = pickTemplate(ctx);\n const demo = pickDemo(ctx, themeSettings);\n\n // Real catalog the host forwards: home/listing routes ship\n // page.data.{products,collections}; the PDP ships page.data.product.\n // Feeding these into NuMuProvider (+ ProductProvider) is what makes\n // useProducts()/useProduct() return the merchant's ACTUAL catalog.\n const pageData = (ctx.page?.data ?? {}) as {\n products?: Product[];\n collections?: Collection[];\n product?: Product;\n };\n\n const app = renderApp({\n currentTemplate: template,\n demo,\n page: ctx.page ?? null,\n store,\n themeSettings,\n });\n\n return (\n <NuMuProvider\n store={store}\n themeSettings={themeSettings}\n initialCart={ctx.initialCart}\n customer={ctx.customer}\n locale={ctx.locale}\n translations={ctx.translations}\n navigation={ctx.navigation}\n initialProducts={pageData.products}\n initialCollections={pageData.collections}\n currentTemplate={template}\n >\n {pageData.product ? (\n <ProductProvider product={pageData.product}>{app}</ProductProvider>\n ) : (\n app\n )}\n </NuMuProvider>\n );\n});\n\n/**\n * Mount a V3 theme. Owns the React root, the provider stack (catalog + nav +\n * style tokens), and the live-preview draft cycle. Returns the host-contract\n * `MountResult` (`cleanup` + `applyDraft`).\n *\n * @param el the host-supplied container element\n * @param ctx the mount context (either host or legacy/dev shape)\n * @param renderApp returns the theme's section tree for the current args\n */\nexport function mountTheme(\n el: HTMLElement,\n ctx: ThemeMountContext,\n renderApp: (args: ThemeRenderArgs) => ReactNode,\n): MountResult {\n const root: Root = createRoot(el);\n const handleRef = { current: null as DraftHandle | null };\n\n root.render(\n <StrictMode>\n <ThemeMountBridge\n ctx={ctx}\n mountEl={el}\n renderApp={renderApp}\n ref={(h) => {\n handleRef.current = h;\n }}\n />\n </StrictMode>,\n );\n\n return {\n applyDraft: (next) => handleRef.current?.applyDraft(next),\n cleanup: () => {\n root.unmount();\n handleRef.current = null;\n },\n };\n}\n","\"use client\";\nimport type { ReactNode } from \"react\";\nimport { CollectionContext } from \"../contexts\";\nimport type { Collection } from \"../types/entities\";\n\ninterface CollectionProviderProps {\n collection: Collection;\n children: ReactNode;\n}\n\nexport function CollectionProvider({ collection, children }: CollectionProviderProps) {\n return <CollectionContext.Provider value={collection}>{children}</CollectionContext.Provider>;\n}\n","\"use client\";\n\nimport { createElement, type ElementType, type ReactNode } from \"react\";\nimport { useLocalization } from \"../hooks/useLocalization\";\nimport { useShop } from \"../hooks/useShop\";\n\ninterface MoneyProps {\n /** Amount in major units (e.g. dollars, not cents). */\n amount: number;\n /** ISO-4217 currency code. Defaults to the active store's currency. */\n currency?: string;\n /**\n * When the same product has both a sale price and a compare-at price,\n * pass the higher (compare-at) value here and we'll render it with a\n * strike-through next to the active price. Skipped when undefined or\n * <= the main amount.\n */\n compareAt?: number;\n className?: string;\n /** Custom HTML element tag — defaults to `span`. */\n as?: ElementType;\n}\n\n/**\n * <Money amount={49.99} /> — formatted price, locale-aware.\n *\n * Wraps useLocalization().formatMoney so theme code stops re-implementing\n * Intl.NumberFormat. Renders inline with `dir=\"auto\"` so the digits\n * flow naturally in RTL (Arabic) without flipping the currency symbol.\n *\n * Usage:\n * <Money amount={product.price} compareAt={product.compare_at_price} />\n */\nexport function Money({\n amount,\n currency,\n compareAt,\n className,\n as = \"span\",\n}: MoneyProps) {\n const { formatMoney } = useLocalization();\n const shop = useShop();\n const ccy = currency || shop?.currency;\n const showCompare = compareAt != null && compareAt > amount;\n\n const children: ReactNode[] = [\n <span key=\"amt\">{formatMoney(amount, ccy)}</span>,\n ];\n if (showCompare) {\n children.push(\" \");\n children.push(\n <s key=\"cmp\" style={{ opacity: 0.6 }}>\n {formatMoney(compareAt, ccy)}\n </s>,\n );\n }\n\n return createElement(\n as,\n { className, dir: \"auto\" },\n children,\n );\n}\n","\"use client\";\n\nimport type { ImgHTMLAttributes } from \"react\";\n\ninterface ImageProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, \"src\" | \"srcSet\"> {\n src: string | undefined | null;\n alt: string;\n /**\n * Comma-separated breakpoints for the `sizes` attribute. Default\n * matches a typical responsive grid:\n * \"(min-width: 1024px) 25vw, (min-width: 640px) 50vw, 100vw\"\n */\n sizes?: string;\n /**\n * When true (default), generate a `srcSet` with several widths.\n * Disable for above-the-fold hero images where you want a single\n * source under direct theme control.\n */\n responsive?: boolean;\n /**\n * Loading strategy. Default \"lazy\" matches Shopify themes; pass\n * \"eager\" for above-the-fold imagery.\n */\n loading?: \"eager\" | \"lazy\";\n}\n\nconst DEFAULT_WIDTHS = [320, 480, 640, 768, 1024, 1280, 1600, 1920];\n\n/**\n * Build a srcSet string from a base image URL by appending a width\n * query param. Works for any CDN that honors `?w=` (R2 image-resizing,\n * Cloudflare Images, Imgix-compatibles). Hosts that ignore the param\n * just serve the original; not a regression.\n *\n * If the URL already has query params we preserve them; if it already\n * has a width directive we pass through unchanged (assume the theme\n * author knows what they want).\n */\nfunction buildSrcSet(src: string, widths: number[] = DEFAULT_WIDTHS): string {\n if (/[?&]w=\\d+/.test(src)) return \"\";\n const sep = src.includes(\"?\") ? \"&\" : \"?\";\n return widths.map((w) => `${src}${sep}w=${w} ${w}w`).join(\", \");\n}\n\n/**\n * <Image> — drop-in replacement for `<img>` with srcSet + lazy loading\n * defaults. Themes should use this everywhere they'd otherwise write a\n * raw `<img>` so merchant-uploaded images get responsive variants and\n * lazy loading without per-section work.\n *\n * If `src` is empty/null, renders a placeholder div so the layout\n * doesn't shift while a merchant configures images in the customizer.\n */\nexport function Image({\n src,\n alt,\n sizes = \"(min-width: 1024px) 25vw, (min-width: 640px) 50vw, 100vw\",\n responsive = true,\n loading = \"lazy\",\n className,\n style,\n ...rest\n}: ImageProps) {\n if (!src) {\n return (\n <div\n className={className}\n role=\"img\"\n aria-label={alt}\n style={{\n backgroundColor: \"rgba(0,0,0,0.05)\",\n display: \"block\",\n ...style,\n }}\n />\n );\n }\n\n const srcSet = responsive ? buildSrcSet(src) : undefined;\n return (\n <img\n src={src}\n alt={alt}\n srcSet={srcSet || undefined}\n sizes={srcSet ? sizes : undefined}\n loading={loading}\n decoding=\"async\"\n className={className}\n style={style}\n {...rest}\n />\n );\n}\n","\"use client\";\n\nimport type { AnchorHTMLAttributes, ReactNode } from \"react\";\nimport { useShop } from \"../hooks/useShop\";\n\ninterface LinkProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, \"href\"> {\n /**\n * Path relative to the storefront root, e.g. \"/products/foo\",\n * \"/collections/all\", \"/cart\", \"/pages/about\". External URLs (with\n * a protocol) are passed through unchanged.\n */\n to: string;\n children: ReactNode;\n}\n\nconst ABSOLUTE_URL = /^[a-z]+:|^\\/\\//i;\n\n/**\n * Route-aware <Link>. Themes write paths as `/products/<slug>` (matches\n * the production subdomain root). The storefront proxy rewrites those\n * under `/<subdomain>/...` in dev path-segment routing; in production\n * the subdomain hostname does the same job at the edge.\n *\n * For plain anchor behavior — server-rendered HTML, full page nav — we\n * just emit a regular `<a>`. Themes that want client-side transitions\n * can wrap this in their own router-aware component; in practice\n * storefront pages are SSR'd so a full nav is fine and predictable.\n *\n * External URLs (have a protocol or start with `//`) pass through\n * unchanged so social-media links, CDN paths, etc. work without\n * special casing.\n */\nexport function Link({ to, children, ...rest }: LinkProps) {\n const shop = useShop();\n const isAbsolute = ABSOLUTE_URL.test(to);\n let href = to;\n if (!isAbsolute && shop && !to.startsWith(\"/\")) {\n // Relative paths like \"products/foo\" treated as siblings of current.\n // Most themes use leading slashes; this is a defensive fallback.\n href = `/${to}`;\n }\n return (\n <a href={href} {...rest}>\n {children}\n </a>\n );\n}\n","\"use client\";\n\nimport { useState, type ButtonHTMLAttributes, type ReactNode } from \"react\";\nimport { useCart } from \"../hooks/useCart\";\nimport type { Product, ProductVariant } from \"../types/entities\";\n\ninterface AddToCartButtonProps\n extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"onClick\" | \"disabled\"> {\n product: Product;\n variant?: ProductVariant;\n quantity?: number;\n /** Custom labels — fallbacks are English defaults. */\n label?: ReactNode;\n loadingLabel?: ReactNode;\n soldOutLabel?: ReactNode;\n errorLabel?: ReactNode;\n /** Called after successful addition. Useful for analytics events. */\n onAdded?: (product: Product, variant?: ProductVariant) => void;\n}\n\n/**\n * Themed Add-to-Cart button with built-in loading/disabled/error states.\n *\n * Wraps useCart().addItem and tracks its own UX state machine:\n * idle → adding → idle (or → error briefly, then idle)\n *\n * Renders a regular `<button>` so themes style it with whatever class\n * names they want — we only own the disabled/aria-busy logic and label\n * swaps. If the variant (or product) is out of stock, button is\n * disabled and shows soldOutLabel.\n *\n * Doesn't trap navigation — for \"buy now\" flows that should redirect\n * to checkout, themes wrap this in their own `<a>` after onAdded.\n */\nexport function AddToCartButton({\n product,\n variant,\n quantity = 1,\n label = \"Add to cart\",\n loadingLabel = \"Adding…\",\n soldOutLabel = \"Sold out\",\n errorLabel = \"Couldn't add — try again\",\n onAdded,\n ...rest\n}: AddToCartButtonProps) {\n const { addItem } = useCart();\n const [state, setState] = useState<\"idle\" | \"adding\" | \"error\">(\"idle\");\n\n const inStock = variant?.in_stock ?? product.in_stock;\n if (!inStock) {\n return (\n <button\n type=\"button\"\n disabled\n aria-disabled=\"true\"\n {...rest}\n >\n {soldOutLabel}\n </button>\n );\n }\n\n async function handleClick() {\n if (state === \"adding\") return;\n setState(\"adding\");\n try {\n await addItem(product.id, variant?.id, quantity);\n setState(\"idle\");\n onAdded?.(product, variant);\n } catch {\n setState(\"error\");\n // Auto-clear after 2s so the merchant can try again.\n setTimeout(() => setState(\"idle\"), 2000);\n }\n }\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={state === \"adding\"}\n aria-busy={state === \"adding\"}\n {...rest}\n >\n {state === \"adding\"\n ? loadingLabel\n : state === \"error\"\n ? errorLabel\n : label}\n </button>\n );\n}\n","\"use client\";\n\nimport {\n Component,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\n\ninterface SectionProps extends HTMLAttributes<HTMLElement> {\n /** Section instance id (the order key in templates). Required for the\n * customizer's click-to-select to work. */\n id: string;\n /** Section type as registered in the theme registry / schemas. */\n type: string;\n /** Section group id (header / footer / announcement-bar) when this\n * section is mounted inside a group rather than a page template. */\n groupId?: string;\n /** Override the fallback shown when this section throws. Defaults to\n * a small inline error card (visible to the merchant in the customizer,\n * invisible to live shoppers — see CSS comment below). */\n errorFallback?: ReactNode;\n children: ReactNode;\n}\n\n// ── Section ErrorBoundary ───────────────────────────────────────────────────\n//\n// One thrown section used to take down the whole bundle's React tree —\n// every other section unmounted along with the bad one, leaving the\n// merchant with a blank storefront and no way to find the offender.\n//\n// We catch render/lifecycle errors at the per-section seam so a bug in\n// \"Hero v2\" doesn't break the perfectly fine \"Newsletter\" section\n// rendered on the same page. The boundary:\n//\n// 1. Logs the error + section context to console.error so the dev\n// console makes the offender obvious.\n// 2. Re-renders a fallback (defaults to a small error card; theme\n// can override via the `errorFallback` prop).\n// 3. Posts `numu:editor:section-error` to window.parent so the V3\n// customizer can highlight the offending section in its tree.\n//\n// The boundary is INSIDE the `<section data-section-id>` wrapper, so\n// the data attributes still let the customizer click-select the bad\n// section even when its body crashed — merchants can delete it.\n\ninterface BoundaryState {\n error: Error | null;\n}\n\ninterface SectionErrorBoundaryProps {\n sectionId: string;\n sectionType: string;\n fallback: ReactNode;\n children: ReactNode;\n}\n\nclass SectionErrorBoundary extends Component<\n SectionErrorBoundaryProps,\n BoundaryState\n> {\n state: BoundaryState = { error: null };\n\n static getDerivedStateFromError(error: Error): BoundaryState {\n return { error };\n }\n\n componentDidCatch(error: Error) {\n // Match the host's <ByotThemeBoundary> log shape so the prefix is\n // recognizable in the iframe console even when both boundaries fire.\n console.error(\n `[Section ${this.props.sectionType}#${this.props.sectionId}] threw:`,\n error,\n );\n if (typeof window !== \"undefined\" && window.parent !== window) {\n try {\n window.parent.postMessage(\n {\n type: \"numu:editor:section-error\",\n payload: {\n sectionId: this.props.sectionId,\n sectionType: this.props.sectionType,\n message: error.message,\n },\n },\n \"*\",\n );\n } catch {\n // Cross-origin postMessage with `*` is permissive enough that\n // this branch is for true edge cases (sandboxed iframe with\n // disallow-script). Nothing useful to do.\n }\n }\n }\n\n render() {\n if (this.state.error) return this.props.fallback;\n return this.props.children;\n }\n}\n\nfunction defaultSectionFallback(\n sectionType: string,\n sectionId: string,\n): ReactNode {\n return (\n <div\n role=\"alert\"\n data-numu-section-error=\"true\"\n style={{\n padding: \"1rem\",\n border: \"1px dashed #f87171\",\n background: \"#fef2f2\",\n color: \"#b91c1c\",\n fontFamily:\n \"system-ui, -apple-system, BlinkMacSystemFont, sans-serif\",\n fontSize: \"0.875rem\",\n lineHeight: 1.5,\n borderRadius: \"0.375rem\",\n margin: \"0.5rem 0\",\n }}\n >\n <div style={{ fontWeight: 600, marginBottom: \"0.25rem\" }}>\n Section failed to render\n </div>\n <div style={{ opacity: 0.9 }}>\n <code style={{ fontFamily: \"monospace\" }}>{sectionType}</code> threw\n an error. Check the browser console for details.\n </div>\n <div\n style={{\n opacity: 0.6,\n fontSize: \"0.75rem\",\n marginTop: \"0.25rem\",\n fontFamily: \"monospace\",\n }}\n >\n section #{sectionId}\n </div>\n </div>\n );\n}\n\n/**\n * <Section> — wrapper that emits the `data-section-id` / `data-section-type`\n * attributes the storefront's PreviewBridge needs to relay clicks back\n * to the V3 customizer for \"select section X\" navigation.\n *\n * Use this around the top-level element of every section component:\n *\n * export default function Hero({ settings, ...sectionMeta }) {\n * return (\n * <Section id={sectionMeta.id} type=\"hero\">\n * <h1>{settings.headline}</h1>\n * </Section>\n * );\n * }\n *\n * Without `data-section-id` on a real DOM ancestor, clicking anywhere\n * in the section in the customizer iframe falls through to the page\n * background and the merchant has to use the section list panel to\n * select sections — slow and confusing.\n *\n * Errors thrown by `children` are caught by an internal ErrorBoundary\n * so one bad section doesn't unmount its siblings. Customize the\n * fallback via `errorFallback`.\n */\nexport function Section({\n id,\n type,\n groupId,\n errorFallback,\n children,\n ...rest\n}: SectionProps) {\n return (\n <section\n data-section-id={id}\n data-section-type={type}\n data-group-id={groupId}\n {...rest}\n >\n <SectionErrorBoundary\n sectionId={id}\n sectionType={type}\n fallback={errorFallback ?? defaultSectionFallback(type, id)}\n >\n {children}\n </SectionErrorBoundary>\n </section>\n );\n}\n\ninterface BlockProps extends HTMLAttributes<HTMLDivElement> {\n /** Block instance id within its parent section. */\n id: string;\n type: string;\n /** Override the fallback shown when this block throws. */\n errorFallback?: ReactNode;\n children: ReactNode;\n}\n\n/**\n * <Block> — analog to <Section> for nested block selection. Same DOM\n * attribute contract; PreviewBridge reads `data-block-id` and reports\n * the block as selected when its child clicks bubble up.\n *\n * Wraps `children` in the same per-instance ErrorBoundary as <Section>\n * so a bad block within a section isolates its failure.\n */\nexport function Block({ id, type, errorFallback, children, ...rest }: BlockProps) {\n return (\n <div data-block-id={id} data-block-type={type} {...rest}>\n <SectionErrorBoundary\n sectionId={id}\n sectionType={type}\n fallback={errorFallback ?? defaultSectionFallback(type, id)}\n >\n {children}\n </SectionErrorBoundary>\n </div>\n );\n}\n","\"use client\";\n\nimport {\n useState,\n type FormEvent,\n type FormHTMLAttributes,\n type ReactNode,\n} from \"react\";\n\ninterface FormProps\n extends Omit<\n FormHTMLAttributes<HTMLFormElement>,\n \"onSubmit\" | \"method\" | \"action\" | \"children\" | \"onError\"\n > {\n /**\n * Endpoint to POST/etc. the form values to. Should be one of the\n * storefront's `/api/*` proxy routes — they handle CSRF + cookie\n * forwarding + idempotency on the way to FastAPI.\n */\n action: string;\n /**\n * HTTP method. POST is the typical theme use-case (newsletter,\n * contact, customer login, address create). GET is supported for\n * search-style forms.\n */\n method?: \"POST\" | \"GET\" | \"PUT\" | \"DELETE\";\n /**\n * Called with the JSON-decoded response body on success. Use to\n * trigger a toast, redirect, etc. Theme owns the UX.\n */\n onSuccess?: (response: unknown) => void;\n /**\n * Called with the Error on failure. Falls through to the default\n * error label otherwise.\n */\n onError?: (error: Error) => void;\n /**\n * Render-prop access to the in-flight state if the theme wants to\n * show its own loading / disabled / error UI. Default `children`\n * behavior just lets the form's inputs and submit button render —\n * we don't impose styling.\n */\n children?:\n | ReactNode\n | ((state: { submitting: boolean; error: Error | null }) => ReactNode);\n}\n\nconst ABSOLUTE_URL = /^[a-z]+:|^\\/\\//i;\n\nfunction readCsrfCookie(): string | null {\n if (typeof document === \"undefined\") return null;\n const m = document.cookie.match(/(?:^|;\\s*)numu_csrf=([^;]+)/);\n return m ? decodeURIComponent(m[1]) : null;\n}\n\nfunction newIdempotencyKey(): string {\n if (typeof crypto !== \"undefined\" && \"randomUUID\" in crypto) {\n return crypto.randomUUID();\n }\n return `${Date.now()}-${Math.random().toString(36).slice(2)}`;\n}\n\n/**\n * <Form action=\"/api/cart/add\" method=\"POST\" onSuccess={...}>\n *\n * Theme-friendly wrapper around `<form>` that handles:\n * - CSRF: reads `numu_csrf` cookie, sends as `x-numu-csrf` header on\n * every mutating request. Same wire format as <NuMuProvider>'s\n * cart machinery — interoperates seamlessly.\n * - Idempotency: mints a UUID per submit, sends as\n * `x-numu-idempotency-key`. Backend dedupes if it supports the\n * header (cart endpoints today; more later).\n * - Submit lifecycle: tracks `submitting` + `error` state and\n * either passes them to a render-prop child or wires them to a\n * submit-button's `disabled` automatically.\n * - Throws away page navigation: `onSubmit` calls preventDefault and\n * fetches via JSON. Themes that want classic POST-and-navigate\n * can drop down to a plain `<form>`.\n *\n * Refuses to submit to absolute URLs (must point at the storefront\n * itself or an `/api/*` proxy) so a misconfigured theme can't leak\n * customer data to a third party origin.\n */\nexport function Form({\n action,\n method = \"POST\",\n onSuccess,\n onError,\n children,\n ...rest\n}: FormProps) {\n const [submitting, setSubmitting] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n async function handleSubmit(e: FormEvent<HTMLFormElement>) {\n e.preventDefault();\n\n if (ABSOLUTE_URL.test(action)) {\n const err = new Error(\n `<Form action> must be a same-origin path (got \"${action}\"). ` +\n `Use a /api/* proxy route or your route handler.`,\n );\n setError(err);\n onError?.(err);\n return;\n }\n\n setSubmitting(true);\n setError(null);\n try {\n const formData = new FormData(e.currentTarget);\n const isMutation = method !== \"GET\";\n\n // Convert FormData → JSON. Themes can pass `data-numu-multipart=\"true\"`\n // on the form to opt into multipart instead (file uploads).\n const isMultipart =\n e.currentTarget.dataset?.numuMultipart === \"true\";\n\n const headers: Record<string, string> = {};\n if (!isMultipart) headers[\"Content-Type\"] = \"application/json\";\n if (isMutation) {\n const csrf = readCsrfCookie();\n if (csrf) headers[\"x-numu-csrf\"] = csrf;\n headers[\"x-numu-idempotency-key\"] = newIdempotencyKey();\n }\n\n let url = action;\n let body: BodyInit | undefined;\n if (method === \"GET\") {\n const params = new URLSearchParams();\n for (const [k, v] of formData.entries()) {\n if (typeof v === \"string\") params.append(k, v);\n }\n const sep = action.includes(\"?\") ? \"&\" : \"?\";\n url = `${action}${sep}${params.toString()}`;\n } else if (isMultipart) {\n body = formData;\n } else {\n const obj: Record<string, FormDataEntryValue> = {};\n for (const [k, v] of formData.entries()) obj[k] = v;\n body = JSON.stringify(obj);\n }\n\n const res = await fetch(url, { method, headers, body });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(\n `${method} ${action} failed: ${res.status} ${res.statusText}${\n text ? ` — ${text.slice(0, 200)}` : \"\"\n }`,\n );\n }\n const json = res.headers\n .get(\"content-type\")\n ?.includes(\"application/json\")\n ? await res.json()\n : await res.text();\n onSuccess?.(json);\n } catch (err) {\n const e2 = err instanceof Error ? err : new Error(String(err));\n setError(e2);\n onError?.(e2);\n } finally {\n setSubmitting(false);\n }\n }\n\n return (\n <form\n onSubmit={handleSubmit}\n method={method}\n action={action}\n aria-busy={submitting}\n {...rest}\n >\n {typeof children === \"function\"\n ? children({ submitting, error })\n : children}\n </form>\n );\n}\n","\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport type { Product } from \"../types/entities\";\nimport { Image } from \"./Image\";\nimport { Money } from \"./Money\";\nimport { Link } from \"./Link\";\nimport { AddToCartButton } from \"./AddToCartButton\";\n\n/**\n * Opinionated product tile.\n *\n * Themes drop this anywhere a product list is needed — collection\n * pages, search results, recommendations, recently-viewed grids.\n * Renders image + title + price (with compare-at strike-through when\n * present) + an optional \"Sold out\" badge + AddToCartButton.\n *\n * The component is **unstyled by default** — it ships only structural\n * markup with stable class names. Themes provide the CSS. Class names\n * use a `numu-product-card__*` BEM convention so themes can target\n * pieces without grep-and-replace if NUMU later renames anything.\n *\n * Class hooks:\n * .numu-product-card — root <article>\n * .numu-product-card__link — wrapping <a>\n * .numu-product-card__media — image container\n * .numu-product-card__image — the <img> itself\n * .numu-product-card__badge — \"Sold out\" overlay\n * .numu-product-card__title — title <h3>\n * .numu-product-card__price — price wrapper\n * .numu-product-card__cta — CTA wrapper (AddToCartButton)\n *\n * Themes can override any piece by passing `slots`:\n * <ProductCard product={p} slots={{ price: <CustomPrice /> }} />\n *\n * For deeper customization, themes should compose the primitives\n * (Image / Money / Link / AddToCartButton) directly instead.\n */\nexport interface ProductCardSlots {\n /** Replaces the badge area (default: \"Sold out\" when out of stock, else nothing). */\n badge?: ReactNode;\n /** Replaces the title `<h3>` block. */\n title?: ReactNode;\n /** Replaces the price `<Money>` block. */\n price?: ReactNode;\n /** Replaces the AddToCartButton. Pass `null` to hide it. */\n cta?: ReactNode | null;\n}\n\nexport interface ProductCardProps {\n product: Product;\n /** Override the link target. Default: `/products/{slug}`. */\n href?: string;\n className?: string;\n slots?: ProductCardSlots;\n /**\n * Image sizing hint for the responsive srcSet. Default: a 4-up grid\n * sizing (~25vw at desktop, ~50vw at tablet, ~100vw at mobile).\n * Override when rendering in a different layout density.\n */\n imageSizes?: string;\n}\n\nfunction joinClass(...names: Array<string | undefined | null | false>): string {\n return names.filter(Boolean).join(\" \");\n}\n\nexport function ProductCard({\n product,\n href,\n className,\n slots,\n imageSizes,\n}: ProductCardProps) {\n const target = href ?? `/products/${product.slug}`;\n const firstImage = product.images?.[0];\n const inStock = product.in_stock;\n\n const badge =\n slots?.badge !== undefined\n ? slots.badge\n : inStock\n ? null\n : (\n <span className=\"numu-product-card__badge\">Sold out</span>\n );\n\n return (\n <article className={joinClass(\"numu-product-card\", className)}>\n <Link to={target} className=\"numu-product-card__link\">\n <div className=\"numu-product-card__media\">\n <Image\n src={firstImage?.url}\n alt={firstImage?.alt || product.name}\n sizes={imageSizes}\n className=\"numu-product-card__image\"\n />\n {badge}\n </div>\n {slots?.title ?? (\n <h3 className=\"numu-product-card__title\">{product.name}</h3>\n )}\n {slots?.price ?? (\n <div className=\"numu-product-card__price\">\n <Money\n amount={product.price}\n compareAt={product.compare_at_price}\n currency={product.currency}\n />\n </div>\n )}\n </Link>\n {slots?.cta === null\n ? null\n : (\n <div className=\"numu-product-card__cta\">\n {slots?.cta ?? <AddToCartButton product={product} />}\n </div>\n )}\n </article>\n );\n}\n","\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport type { Collection } from \"../types/entities\";\nimport { Image } from \"./Image\";\nimport { Link } from \"./Link\";\n\n/**\n * Opinionated collection tile.\n *\n * Renders a single collection's hero image + name + product count.\n * Used by collection-list sections, footer \"Featured collections\"\n * blocks, and search-result mixed views.\n *\n * Unstyled by default; themes ship the CSS. Class hooks:\n * .numu-collection-card — root <article>\n * .numu-collection-card__link — wrapping <a>\n * .numu-collection-card__media — image container\n * .numu-collection-card__image — the <img>\n * .numu-collection-card__title — title <h3>\n * .numu-collection-card__count — product count line\n */\nexport interface CollectionCardSlots {\n title?: ReactNode;\n /** Replaces the \"N products\" line. Pass null to hide it. */\n count?: ReactNode | null;\n}\n\nexport interface CollectionCardProps {\n collection: Collection;\n /** Override the link target. Default: `/collections/{slug}`. */\n href?: string;\n className?: string;\n slots?: CollectionCardSlots;\n imageSizes?: string;\n}\n\nfunction joinClass(...names: Array<string | undefined | null | false>): string {\n return names.filter(Boolean).join(\" \");\n}\n\nexport function CollectionCard({\n collection,\n href,\n className,\n slots,\n imageSizes,\n}: CollectionCardProps) {\n const target = href ?? `/collections/${collection.slug}`;\n const productCount =\n typeof collection.product_count === \"number\"\n ? collection.product_count\n : undefined;\n\n return (\n <article className={joinClass(\"numu-collection-card\", className)}>\n <Link to={target} className=\"numu-collection-card__link\">\n <div className=\"numu-collection-card__media\">\n <Image\n src={collection.image_url}\n alt={collection.name}\n sizes={imageSizes}\n className=\"numu-collection-card__image\"\n />\n </div>\n {slots?.title ?? (\n <h3 className=\"numu-collection-card__title\">{collection.name}</h3>\n )}\n {slots?.count === null\n ? null\n : (slots?.count ?? (\n productCount !== undefined && (\n <p className=\"numu-collection-card__count\">\n {productCount === 1 ? \"1 product\" : `${productCount} products`}\n </p>\n )\n ))}\n </Link>\n </article>\n );\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\n\n/**\n * <RichText html=... /> — sanitized HTML renderer.\n *\n * Wraps `dangerouslySetInnerHTML` so theme code stops calling it\n * directly with merchant-supplied content. Themes that need to render\n * rich-text fields (product descriptions, page bodies, blog articles,\n * policy bodies) go through this so an XSS in a single field can't\n * cross-contaminate the whole storefront.\n *\n * **Why a built-in allowlist sanitizer instead of DOMPurify?**\n * The audit plan called for DOMPurify, but adding it as a hard dep\n * inflates every theme bundle by ~12KB gzipped — and the merchant-\n * editable surface is small enough (a fixed set of formatting tags +\n * links + images) that a curated allowlist is both smaller AND easier\n * to reason about. If a theme needs richer sanitization (embeds,\n * iframes, MathML), it can import DOMPurify directly and pre-sanitize\n * before passing the result here.\n *\n * Allowed tags:\n * p, br, hr, h1-h6, blockquote, pre, code,\n * strong, b, em, i, u, s, sub, sup, mark,\n * ul, ol, li, dl, dt, dd,\n * a (href, target, rel only),\n * img (src, alt, width, height, loading only — http(s) URLs only),\n * table, thead, tbody, tr, th, td,\n * span, div (with class attribute only).\n *\n * Stripped:\n * <script>, <style>, <iframe>, <object>, <embed>, <link>, <meta>,\n * form/input, on*= handlers, javascript:/data: URLs, srcset on\n * <img> (we let the storefront's image-transform handle that\n * uniformly).\n */\nexport interface RichTextProps {\n html: string | null | undefined;\n className?: string;\n /** Element to render — defaults to `<div>`. Use `<article>` for body content. */\n as?: \"div\" | \"article\" | \"section\" | \"aside\";\n}\n\nconst ALLOWED_TAGS: ReadonlySet<string> = new Set([\n \"p\", \"br\", \"hr\",\n \"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\",\n \"blockquote\", \"pre\", \"code\",\n \"strong\", \"b\", \"em\", \"i\", \"u\", \"s\", \"sub\", \"sup\", \"mark\",\n \"ul\", \"ol\", \"li\", \"dl\", \"dt\", \"dd\",\n \"a\", \"img\",\n \"table\", \"thead\", \"tbody\", \"tr\", \"th\", \"td\",\n \"span\", \"div\",\n]);\n\nconst ALLOWED_ATTRS_BY_TAG: Record<string, ReadonlySet<string>> = {\n a: new Set([\"href\", \"target\", \"rel\", \"class\", \"title\"]),\n img: new Set([\"src\", \"alt\", \"width\", \"height\", \"loading\", \"class\"]),\n span: new Set([\"class\"]),\n div: new Set([\"class\"]),\n p: new Set([\"class\"]),\n h1: new Set([\"class\"]), h2: new Set([\"class\"]), h3: new Set([\"class\"]),\n h4: new Set([\"class\"]), h5: new Set([\"class\"]), h6: new Set([\"class\"]),\n blockquote: new Set([\"class\"]),\n pre: new Set([\"class\"]),\n code: new Set([\"class\"]),\n ul: new Set([\"class\"]), ol: new Set([\"class\"]), li: new Set([\"class\"]),\n table: new Set([\"class\"]),\n thead: new Set([\"class\"]), tbody: new Set([\"class\"]),\n tr: new Set([\"class\"]), th: new Set([\"class\"]), td: new Set([\"class\"]),\n};\n\nconst URL_SAFE_PROTOCOLS = /^(https?|mailto|tel):/i;\n\nfunction isSafeUrl(url: string): boolean {\n const trimmed = url.trim();\n if (!trimmed) return false;\n // Relative paths are fine.\n if (trimmed.startsWith(\"/\") || trimmed.startsWith(\"#\") || trimmed.startsWith(\"?\")) {\n return true;\n }\n // Protocol-bearing — only http/https/mailto/tel.\n return URL_SAFE_PROTOCOLS.test(trimmed);\n}\n\n/**\n * Sanitize an HTML string against the allowlist above. Runs server-\n * AND client-side because rich-text fields are server-rendered for SEO.\n *\n * Implementation note: We use DOMParser when available (browser) for\n * structural correctness; on server we fall through a regex-based\n * pass that handles the common formatting tags + escapes everything\n * else. The server pass is intentionally conservative — themes that\n * need server-rendered rich content with edge-case structure should\n * sanitize on the API tier and pass the sanitized HTML through\n * `bypassSanitize` (escape hatch below).\n */\nexport function sanitizeHtml(input: string): string {\n if (!input) return \"\";\n if (typeof window === \"undefined\" || typeof DOMParser === \"undefined\") {\n return sanitizeHtmlServer(input);\n }\n return sanitizeHtmlClient(input);\n}\n\nfunction sanitizeHtmlClient(input: string): string {\n const doc = new DOMParser().parseFromString(\n `<div>${input}</div>`,\n \"text/html\",\n );\n const root = doc.body.firstElementChild;\n if (!root) return \"\";\n walk(root);\n return root.innerHTML;\n}\n\nfunction walk(node: Element): void {\n const children = Array.from(node.children);\n for (const child of children) {\n const tag = child.tagName.toLowerCase();\n if (!ALLOWED_TAGS.has(tag)) {\n // Replace forbidden tag with its sanitized text content. Drops\n // entire subtree if the tag is one we never want (script/style).\n if (tag === \"script\" || tag === \"style\" || tag === \"iframe\" || tag === \"object\" || tag === \"embed\") {\n child.remove();\n } else {\n const text = child.textContent || \"\";\n child.replaceWith(document.createTextNode(text));\n }\n continue;\n }\n // Strip disallowed attributes.\n const allowed = ALLOWED_ATTRS_BY_TAG[tag] || new Set<string>();\n for (const attr of Array.from(child.attributes)) {\n const name = attr.name.toLowerCase();\n // on*= handlers → always strip.\n if (name.startsWith(\"on\")) {\n child.removeAttribute(attr.name);\n continue;\n }\n if (!allowed.has(name)) {\n child.removeAttribute(attr.name);\n continue;\n }\n // URL-bearing attrs → protocol-check.\n if ((name === \"href\" || name === \"src\") && !isSafeUrl(attr.value)) {\n child.removeAttribute(attr.name);\n continue;\n }\n }\n // Anchor hardening: every external link gets rel=\"noopener noreferrer\"\n // when target=\"_blank\" is set. Stops reverse-tabnabbing without the\n // theme dev having to remember.\n if (tag === \"a\" && child.getAttribute(\"target\") === \"_blank\") {\n child.setAttribute(\"rel\", \"noopener noreferrer\");\n }\n walk(child);\n }\n}\n\n/**\n * Server-side fallback. We don't have a DOM here, so we do an\n * HTML-entity-escape and unescape only the allowed inline formatting\n * tags. This is conservative — block-level tags work but with limited\n * attribute support.\n */\nfunction sanitizeHtmlServer(input: string): string {\n // Strip dangerous blocks entirely.\n let s = input\n .replace(/<script[\\s\\S]*?<\\/script>/gi, \"\")\n .replace(/<style[\\s\\S]*?<\\/style>/gi, \"\")\n .replace(/<iframe[\\s\\S]*?<\\/iframe>/gi, \"\")\n .replace(/<object[\\s\\S]*?<\\/object>/gi, \"\")\n .replace(/<embed[\\s\\S]*?<\\/embed>/gi, \"\")\n .replace(/<link[\\s\\S]*?>/gi, \"\")\n .replace(/<meta[\\s\\S]*?>/gi, \"\");\n // Strip on*= attrs.\n s = s.replace(/\\s+on\\w+\\s*=\\s*(\"[^\"]*\"|'[^']*'|[^\\s>]+)/gi, \"\");\n // Strip javascript:/data: in href/src.\n s = s.replace(\n /\\s+(href|src)\\s*=\\s*(\"[^\"]*\"|'[^']*'|[^\\s>]+)/gi,\n (full, attr, val) => {\n const cleaned = String(val).replace(/^['\"]|['\"]$/g, \"\");\n return isSafeUrl(cleaned) ? full : \"\";\n },\n );\n return s;\n}\n\nexport function RichText({ html, className, as = \"div\" }: RichTextProps) {\n const safe = useMemo(() => sanitizeHtml(html || \"\"), [html]);\n if (!safe) return null;\n const Tag = as;\n return (\n <Tag\n className={className}\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{ __html: safe }}\n />\n );\n}\n","\"use client\";\n\nimport { useCallback } from \"react\";\nimport { useCurrency } from \"../hooks/useCurrency\";\n\n/**\n * <CurrencySwitcher /> — wired in Phase 6.\n *\n * Reads presentment currencies + the persisted selection from\n * `useCurrency()`, which talks to\n * `/api/storefront/store/{id}/currencies`. Changing the dropdown\n * writes the `numu_currency` cookie via the hook, which then\n * propagates to `<Money>`'s display.\n *\n * Renders nothing when the store offers only one currency — themes\n * can drop the component into a layout without conditional render.\n *\n * Pass `render` to take over the markup completely (e.g. a custom\n * dropdown component or a flag-icon grid).\n */\n\nexport interface CurrencySwitcherProps {\n className?: string;\n onSelect?: (currency: string) => void;\n render?: (state: {\n currencies: string[];\n current: string;\n onChange: (next: string) => void;\n }) => React.ReactNode;\n}\n\nexport function CurrencySwitcher({\n className,\n onSelect,\n render,\n}: CurrencySwitcherProps) {\n const { presentment, selected, setSelected, loading } = useCurrency();\n\n const handleChange = useCallback(\n (next: string) => {\n if (next === selected) return;\n setSelected(next);\n onSelect?.(next);\n },\n [selected, setSelected, onSelect],\n );\n\n // No alternatives, or still loading the list. We don't want to\n // briefly flash a 1-option dropdown while the API resolves.\n if (loading) return null;\n if (presentment.length <= 1) return null;\n\n if (render) {\n return (\n <>\n {render({\n currencies: presentment,\n current: selected,\n onChange: handleChange,\n })}\n </>\n );\n }\n\n return (\n <select\n className={className ?? \"numu-currency-switcher\"}\n value={selected}\n onChange={(e) => handleChange(e.target.value)}\n aria-label=\"Currency\"\n >\n {presentment.map((c) => (\n <option key={c} value={c}>\n {c}\n </option>\n ))}\n </select>\n );\n}\n","\"use client\";\n\nimport { useCallback } from \"react\";\nimport { useShop } from \"../hooks/useShop\";\nimport { useLocalization } from \"../hooks/useLocalization\";\n\n/**\n * <LocaleSwitcher /> — language toggle for stores with multiple locales.\n *\n * v1 supports Arabic + English (the storefront's default_language gates\n * which one is the \"primary\"). This component:\n * - Reads `store.available_locales` (or falls back to\n * [default_language, \"en\"] for stores that haven't been migrated yet).\n * - Renders nothing when there's only one locale.\n * - On change, sets a `numu_locale` cookie + reloads the page so the\n * server-rendered layout picks up the new locale (the storefront\n * middleware reads the cookie and stamps `<html lang/dir>`\n * accordingly).\n *\n * Why a hard reload instead of client-side state swap:\n * Locale impacts SSR-rendered content (currency formatting, product\n * field translations, page metadata). Client-side toggling would\n * leave the SSR output inconsistent until the next navigation.\n * One reload trades a brief flicker for guaranteed correctness.\n */\n\nconst LANG_LABELS: Record<string, string> = {\n ar: \"العربية\",\n en: \"English\",\n fr: \"Français\",\n he: \"עברית\",\n fa: \"فارسی\",\n ur: \"اردو\",\n es: \"Español\",\n de: \"Deutsch\",\n};\n\nexport interface LocaleSwitcherProps {\n className?: string;\n onSelect?: (locale: string) => void;\n /** Custom renderer. Receives the resolved locale list + current selection. */\n render?: (state: {\n locales: string[];\n current: string;\n labelFor: (code: string) => string;\n onChange: (next: string) => void;\n }) => React.ReactNode;\n}\n\nexport function LocaleSwitcher({\n className,\n onSelect,\n render,\n}: LocaleSwitcherProps) {\n const shop = useShop();\n const { locale } = useLocalization();\n const available =\n (shop as unknown as { available_locales?: string[] }).available_locales || [];\n // Fallback for stores that don't yet expose available_locales: assume\n // the store's default_language plus English when they differ.\n const list =\n available.length > 0\n ? available\n : shop.default_language === \"en\"\n ? [\"en\"]\n : Array.from(new Set([shop.default_language, \"en\"]));\n\n const labelFor = useCallback((code: string): string => {\n return LANG_LABELS[code] || code.toUpperCase();\n }, []);\n\n const handleChange = useCallback(\n (next: string) => {\n if (next === locale) return;\n onSelect?.(next);\n if (typeof document !== \"undefined\") {\n const oneYear = 60 * 60 * 24 * 365;\n document.cookie = `numu_locale=${encodeURIComponent(next)}; path=/; max-age=${oneYear}; samesite=lax`;\n }\n // Hard reload so SSR re-runs with the new locale. Use replace()\n // so the locale toggle doesn't pollute browser back history.\n if (typeof window !== \"undefined\") {\n window.location.reload();\n }\n },\n [locale, onSelect],\n );\n\n if (list.length <= 1) return null;\n\n if (render) {\n return <>{render({ locales: list, current: locale, labelFor, onChange: handleChange })}</>;\n }\n\n return (\n <select\n className={className ?? \"numu-locale-switcher\"}\n value={locale}\n onChange={(e) => handleChange(e.target.value)}\n aria-label=\"Language\"\n >\n {list.map((l) => (\n <option key={l} value={l}>\n {labelFor(l)}\n </option>\n ))}\n </select>\n );\n}\n","\"use client\";\n\n/**\n * <EditableText> / <EditableImage> — V3 SDK editor-affordance markers.\n *\n * These are the \"I want to edit this\" hooks for V3 themes. They render\n * a normal element (span / img) on live storefronts, but inside the\n * customizer iframe they:\n *\n * 1. Stamp a `data-numu-editable` attribute so the storefront's\n * PreviewBridge can scope click-to-select to specific fields\n * (rather than the whole section).\n * 2. Show a subtle hover affordance (dotted underline / ring) so the\n * merchant discovers what's editable inline.\n * 3. Bubble up a `numu:editor:select-field` postMessage on click,\n * so the dashboard can scroll the matching setting input into\n * view + focus it.\n *\n * Editor mode is detected the same way PreviewBridge does — query\n * params `editor=v3` OR `preview=true`. Outside the editor, these are\n * pass-through `<span>` / `<img>` with no extra cost.\n *\n * Usage in a V3 section:\n *\n * import { EditableText, EditableImage } from \"@numueg/theme-sdk\";\n *\n * export default function Hero({ instance }: SectionProps) {\n * const { settings } = instance;\n * return (\n * <>\n * <EditableText\n * settingId=\"headline\"\n * sectionId={instance.id}\n * value={settings.headline}\n * as=\"h1\"\n * className=\"text-4xl\"\n * />\n * <EditableImage\n * settingId=\"hero_image\"\n * sectionId={instance.id}\n * src={settings.hero_image}\n * alt={settings.image_alt}\n * />\n * </>\n * );\n * }\n *\n * Why two components instead of one polymorphic `<Editable>`? Text and\n * image have different click semantics (text → focus the matching\n * setting; image → open the media picker) and different DOM shapes,\n * and we want the JSX to read naturally. Future field types (link,\n * color picker, video) get their own component pair.\n */\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useState,\n type ElementType,\n type HTMLAttributes,\n type ImgHTMLAttributes,\n type ReactNode,\n} from \"react\";\n\n// ─── Editor-mode detection ──────────────────────────────────────────────────\n\n/**\n * The detection runs lazily (after mount) to keep SSR HTML identical\n * to the first client paint. If we read window.location during render,\n * we'd return false on the server and true on the client → hydration\n * mismatch. By gating on a useEffect-set state, the initial paint\n * never adds editor-only attributes, and they appear on the second\n * paint (one tick later, after the bridge is awake anyway).\n */\nfunction useIsEditor(): boolean {\n const [isEditor, setIsEditor] = useState(false);\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n try {\n const params = new URLSearchParams(window.location.search);\n const flag =\n params.get(\"editor\") === \"v3\" || params.get(\"preview\") === \"true\";\n // The iframe-only check: the merchant's customizer renders this\n // bundle inside an iframe. On a \"plain\" preview tab (no parent\n // window), we keep the editor-mode markers off — they'd be\n // useless to a merchant browsing their own storefront in a\n // separate tab.\n const inFrame = window.parent !== window;\n setIsEditor(flag && inFrame);\n } catch {\n // No-op — SSR / sandboxed environments fall through to false.\n }\n }, []);\n return isEditor;\n}\n\n/**\n * Post a \"this field was clicked\" event to the dashboard so the editor\n * can scroll the matching setting input into view + focus it.\n *\n * Origin is `*` because the parent's origin varies (dev / staging /\n * prod / different merchant subdomains). The dashboard side enforces\n * origin matching for INBOUND messages from the iframe, so an\n * attacker can't spoof a select-field event by hijacking\n * postMessage — the dashboard's origin gate drops anything not from\n * the storefront's exact origin.\n */\nfunction postFieldSelected(\n sectionId: string,\n settingId: string,\n blockId?: string | null,\n): void {\n if (typeof window === \"undefined\") return;\n if (window.parent === window) return;\n try {\n window.parent.postMessage(\n {\n type: \"numu:editor:select-field\",\n payload: {\n sectionId,\n blockId: blockId ?? null,\n settingId,\n },\n },\n \"*\",\n );\n } catch {\n /* parent gone / sandboxed strictly — no-op */\n }\n}\n\n// ─── EditableText ───────────────────────────────────────────────────────────\n\nexport interface EditableTextProps\n extends Omit<HTMLAttributes<HTMLElement>, \"children\"> {\n /** The section instance id (key inside templates.<page>.sections). */\n sectionId: string;\n /** Optional block id when the field lives inside a section block. */\n blockId?: string | null;\n /** The setting key from the section's schema (e.g. \"headline\"). */\n settingId: string;\n /** The current text value (may be HTML for inline_richtext settings). */\n value: string | undefined | null;\n /**\n * Element to render. Defaults to `<span>` so the component is\n * inline-compatible. Pass \"h1\" / \"h2\" / \"p\" / \"div\" for block-level\n * usage.\n */\n as?: ElementType;\n /**\n * Set to true to render the value as HTML (for inline_richtext\n * settings whose stored form is `<b>Welcome</b>`). Defaults to false\n * — plain-text fields are rendered as a text node.\n */\n html?: boolean;\n /** Empty-state placeholder shown when value is \"\" / null. */\n placeholder?: ReactNode;\n}\n\nexport const EditableText = forwardRef<HTMLElement, EditableTextProps>(\n function EditableText(\n {\n sectionId,\n blockId,\n settingId,\n value,\n as: Component = \"span\",\n html = false,\n placeholder,\n className,\n onClick,\n style,\n ...rest\n },\n ref,\n ) {\n const isEditor = useIsEditor();\n\n const handleClick = useCallback(\n (e: React.MouseEvent<HTMLElement>) => {\n // Forward the click first so themes that wired their own\n // handler keep working.\n onClick?.(e);\n if (!isEditor) return;\n // The whole point: route the click to the matching setting\n // input. Stop propagation only when the editor is open so we\n // don't double-fire the section-level click-to-select handler\n // that PreviewBridge installs at the document level. Themes\n // can still receive the click via their own onClick prop\n // (already invoked above).\n e.stopPropagation();\n postFieldSelected(sectionId, settingId, blockId);\n },\n [isEditor, onClick, sectionId, settingId, blockId],\n );\n\n const editorAttrs = useMemo(\n () =>\n isEditor\n ? {\n \"data-numu-editable\": \"text\",\n \"data-numu-section-id\": sectionId,\n \"data-numu-setting-id\": settingId,\n \"data-numu-block-id\": blockId ?? undefined,\n role: \"button\" as const,\n tabIndex: 0,\n }\n : {},\n [isEditor, sectionId, settingId, blockId],\n );\n\n const effectiveStyle = isEditor\n ? {\n ...style,\n cursor: \"text\" as const,\n // Subtle dotted underline so the merchant discovers what's\n // editable. The dashed style + inherited color keeps the\n // affordance from clashing with the theme's typography.\n textDecoration: \"underline dotted rgba(99, 102, 241, 0.7)\",\n textUnderlineOffset: \"4px\",\n }\n : style;\n\n const isEmpty = value == null || value === \"\";\n const display = isEmpty && placeholder !== undefined ? placeholder : value ?? \"\";\n\n if (html && typeof display === \"string\") {\n return (\n <Component\n ref={ref}\n className={className}\n style={effectiveStyle}\n onClick={handleClick}\n dangerouslySetInnerHTML={{ __html: display }}\n {...editorAttrs}\n {...rest}\n />\n );\n }\n return (\n <Component\n ref={ref}\n className={className}\n style={effectiveStyle}\n onClick={handleClick}\n {...editorAttrs}\n {...rest}\n >\n {display}\n </Component>\n );\n },\n);\n\n// ─── EditableImage ──────────────────────────────────────────────────────────\n\nexport interface EditableImageProps\n extends Omit<ImgHTMLAttributes<HTMLImageElement>, \"src\"> {\n sectionId: string;\n blockId?: string | null;\n settingId: string;\n /** Image src — may be empty/undefined if the merchant hasn't picked one yet. */\n src: string | undefined | null;\n /** Placeholder src shown when `src` is empty. Defaults to a 1x1 transparent gif. */\n emptyPlaceholderSrc?: string;\n}\n\nconst EMPTY_GIF =\n \"data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==\";\n\nexport const EditableImage = forwardRef<HTMLImageElement, EditableImageProps>(\n function EditableImage(\n {\n sectionId,\n blockId,\n settingId,\n src,\n alt,\n emptyPlaceholderSrc,\n className,\n onClick,\n style,\n ...rest\n },\n ref,\n ) {\n const isEditor = useIsEditor();\n const isEmpty = !src;\n\n const handleClick = useCallback(\n (e: React.MouseEvent<HTMLImageElement>) => {\n onClick?.(e);\n if (!isEditor) return;\n e.stopPropagation();\n postFieldSelected(sectionId, settingId, blockId);\n },\n [isEditor, onClick, sectionId, settingId, blockId],\n );\n\n const editorAttrs = useMemo(\n () =>\n isEditor\n ? {\n \"data-numu-editable\": \"image\",\n \"data-numu-section-id\": sectionId,\n \"data-numu-setting-id\": settingId,\n \"data-numu-block-id\": blockId ?? undefined,\n role: \"button\" as const,\n tabIndex: 0,\n }\n : {},\n [isEditor, sectionId, settingId, blockId],\n );\n\n const effectiveStyle = isEditor\n ? {\n ...style,\n cursor: \"pointer\" as const,\n outline: isEmpty\n ? \"2px dashed rgba(99, 102, 241, 0.6)\"\n : \"2px dashed transparent\",\n outlineOffset: \"-2px\",\n }\n : style;\n\n const effectiveSrc = src || emptyPlaceholderSrc || EMPTY_GIF;\n const effectiveAlt = alt ?? \"\";\n\n return (\n <img\n ref={ref}\n src={effectiveSrc}\n alt={effectiveAlt}\n className={className}\n style={effectiveStyle}\n onClick={handleClick}\n {...editorAttrs}\n {...rest}\n />\n );\n },\n);\n","/**\n * Icon — the shared icon set for the `icon_picker` setting type.\n *\n * Names are the stored setting values. BOTH the merchant-hub editor's icon\n * grid AND themes render through this same map, so a picked icon looks\n * identical in the customizer and on the storefront.\n *\n * We ship inline SVG (no icon-library dependency) on purpose: the SDK is the\n * host-provided runtime singleton, and keeping it dependency-free avoids\n * bundling an icon library into every storefront. Each entry below is the\n * inner markup of a 24×24 stroke icon; <Icon> wraps it with the shared\n * stroke attributes and sizing.\n *\n * ⚠️ KEEP IN SYNC with the editor's copy in\n * numo-merchant-hub/src/features/theme-editor-v3/components/inputs/SettingInputV3.tsx\n * (the ICON_DEFS in IconPickerButton). The keys are the contract between\n * the picker and this renderer — a name the picker offers must exist here\n * or the theme falls back to a neutral glyph.\n */\n\nexport const ICON_DEFS: Record<string, string> = {\n star: '<polygon points=\"12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2\"/>',\n heart:\n '<path d=\"M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.29 1.51 4.04 3 5.5l7 7Z\"/>',\n check: '<path d=\"M20 6 9 17l-5-5\"/>',\n \"check-circle\": '<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"m9 12 2 2 4-4\"/>',\n shield: '<path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10Z\"/>',\n \"shield-check\":\n '<path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10Z\"/><path d=\"m9 12 2 2 4-4\"/>',\n truck:\n '<path d=\"M10 17h4V5H2v12h3\"/><path d=\"M20 17h2v-3.34a4 4 0 0 0-1.17-2.83L19 9h-5v8h1\"/><circle cx=\"7.5\" cy=\"17.5\" r=\"2.5\"/><circle cx=\"17.5\" cy=\"17.5\" r=\"2.5\"/>',\n \"shopping-bag\":\n '<path d=\"M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4Z\"/><path d=\"M3 6h18\"/><path d=\"M16 10a4 4 0 0 1-8 0\"/>',\n \"shopping-cart\":\n '<circle cx=\"8\" cy=\"21\" r=\"1\"/><circle cx=\"19\" cy=\"21\" r=\"1\"/><path d=\"M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12\"/>',\n gift:\n '<rect x=\"3\" y=\"8\" width=\"18\" height=\"4\" rx=\"1\"/><path d=\"M12 8v13\"/><path d=\"M19 12v7a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-7\"/><path d=\"M7.5 8a2.5 2.5 0 0 1 0-5C9 3 10.5 4.5 12 8c1.5-3.5 3-5 4.5-5a2.5 2.5 0 0 1 0 5\"/>',\n tag: '<path d=\"M20.59 13.41 13.42 20.6a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82Z\"/><circle cx=\"7\" cy=\"7\" r=\"1\"/>',\n zap: '<polygon points=\"13 2 3 14 12 14 11 22 21 10 12 10 13 2\"/>',\n sparkles:\n '<path d=\"M12 3 13.9 9.2 20 11l-6.1 1.8L12 19l-1.9-6.2L4 11l6.1-1.8L12 3Z\"/><path d=\"M5 3v4\"/><path d=\"M3 5h4\"/><path d=\"M19 17v4\"/><path d=\"M17 19h4\"/>',\n flame:\n '<path d=\"M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.07-2.14-.22-4.05 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.15.43-2.29 1-3a2.5 2.5 0 0 0 2.5 2.5Z\"/>',\n leaf:\n '<path d=\"M11 20A7 7 0 0 1 9.8 6.1C15.5 5 17 4.48 19 2c1 2 2 4.18 2 8 0 5.5-4.78 10-10 10Z\"/><path d=\"M2 21c0-3 1.85-5.36 5.08-6\"/>',\n globe:\n '<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M2 12h20\"/><path d=\"M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10Z\"/>',\n \"map-pin\":\n '<path d=\"M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z\"/><circle cx=\"12\" cy=\"10\" r=\"3\"/>',\n phone:\n '<path d=\"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.36 1.9.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.91.34 1.85.57 2.81.7A2 2 0 0 1 22 16.92Z\"/>',\n mail:\n '<rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\"/><path d=\"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\"/>',\n clock: '<circle cx=\"12\" cy=\"12\" r=\"10\"/><polyline points=\"12 6 12 12 16 14\"/>',\n lock:\n '<rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\"/><path d=\"M7 11V7a5 5 0 0 1 10 0v4\"/>',\n headphones:\n '<path d=\"M3 14h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7a9 9 0 0 1 18 0v7a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3\"/>',\n percent:\n '<line x1=\"19\" x2=\"5\" y1=\"5\" y2=\"19\"/><circle cx=\"6.5\" cy=\"6.5\" r=\"2.5\"/><circle cx=\"17.5\" cy=\"17.5\" r=\"2.5\"/>',\n users:\n '<path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\"/><circle cx=\"9\" cy=\"7\" r=\"4\"/><path d=\"M22 21v-2a4 4 0 0 0-3-3.87\"/><path d=\"M16 3.13a4 4 0 0 1 0 7.75\"/>',\n home:\n '<path d=\"m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z\"/><polyline points=\"9 22 9 12 15 12 15 22\"/>',\n store:\n '<path d=\"M2 7l2-4h16l2 4\"/><path d=\"M4 7v13a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1V7\"/><path d=\"M2 7h20\"/><path d=\"M9 21v-6h6v6\"/>',\n bell:\n '<path d=\"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9\"/><path d=\"M10.3 21a1.94 1.94 0 0 0 3.4 0\"/>',\n camera:\n '<path d=\"M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z\"/><circle cx=\"12\" cy=\"13\" r=\"3\"/>',\n image:\n '<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" ry=\"2\"/><circle cx=\"9\" cy=\"9\" r=\"2\"/><path d=\"m21 15-3.09-3.09a2 2 0 0 0-2.82 0L6 21\"/>',\n smile:\n '<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M8 14s1.5 2 4 2 4-2 4-2\"/><line x1=\"9\" x2=\"9.01\" y1=\"9\" y2=\"9\"/><line x1=\"15\" x2=\"15.01\" y1=\"9\" y2=\"9\"/>',\n send: '<path d=\"m22 2-7 20-4-9-9-4Z\"/><path d=\"M22 2 11 13\"/>',\n \"message-circle\":\n '<path d=\"M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5Z\"/>',\n search: '<circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"m21 21-4.3-4.3\"/>',\n package:\n '<path d=\"M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z\"/><path d=\"m3.3 7 8.7 5 8.7-5\"/><path d=\"M12 22V12\"/>',\n award:\n '<circle cx=\"12\" cy=\"8\" r=\"6\"/><path d=\"M15.477 12.89 17 22l-5-3-5 3 1.523-9.11\"/>',\n coffee:\n '<path d=\"M10 2v2\"/><path d=\"M14 2v2\"/><path d=\"M6 2v2\"/><path d=\"M16 8a1 1 0 0 1 1 1v8a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1h14a4 4 0 1 1 0 8h-1\"/>',\n};\n\nexport const ICON_NAMES: string[] = Object.keys(ICON_DEFS);\n\n/** Public alias for the icon name → inner-SVG map. */\nexport const IconMap = ICON_DEFS;\n\nexport interface IconProps {\n /** Icon name from {@link ICON_NAMES}. Unknown names render a neutral glyph. */\n name: string;\n /** Pixel size (width === height). Defaults to 24. */\n size?: number | string;\n strokeWidth?: number;\n className?: string;\n /** Accessible label. When omitted the icon is treated as decorative. */\n title?: string;\n}\n\nconst FALLBACK = ICON_DEFS[\"check-circle\"];\n\n/**\n * Render an icon by name from the shared {@link ICON_DEFS} set. Inherits color\n * from `currentColor`, so set the parent's text color to recolor it.\n */\nexport function Icon({\n name,\n size = 24,\n strokeWidth = 2,\n className,\n title,\n}: IconProps) {\n const inner = ICON_DEFS[name] ?? FALLBACK;\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n role={title ? \"img\" : undefined}\n aria-hidden={title ? undefined : true}\n aria-label={title}\n dangerouslySetInnerHTML={{ __html: inner }}\n />\n );\n}\n","import type {\n ThemeSettingsV3,\n SectionGroup,\n SectionInstance,\n PageTemplate,\n} from \"../types/theme\";\n\n/**\n * Default theme id when neither the V3 payload nor the legacy `theme.base_theme`\n * is set. Sourced from the env at build time so it stays in sync with the\n * backend's `NUMU_DEFAULT_THEME_ID`.\n *\n * Read once: SDK code that runs in browsers can't read env at runtime, but\n * tsup inlines `process.env.*` at build time when configured to do so.\n */\nconst DEFAULT_THEME_ID =\n (typeof process !== \"undefined\" &&\n process.env?.NUMU_DEFAULT_THEME_ID) ||\n \"modern\";\n\n/**\n * Dual-Read normalization: converts V1/V2 legacy payloads to V3 in memory.\n * Portable — works in both Node.js (SSR) and browser.\n *\n * Output must match the backend's `normalize_legacy_to_v3()` byte-for-byte\n * on the same input. The unit test in __tests__/normalize.test.ts asserts\n * this. If you change the shape here, update the backend mapper too —\n * otherwise stores rendered via SDK and stores rendered via SSR will\n * disagree on what the page contains.\n */\nexport function resolveThemeSettings(\n raw: Record<string, unknown> | null | undefined,\n): ThemeSettingsV3 {\n const safeRaw = (raw ?? {}) as Record<string, unknown>;\n\n // Already V3 — pass through unchanged.\n if (safeRaw.schema_version === 3) {\n return safeRaw as unknown as ThemeSettingsV3;\n }\n\n const themeBlock = (safeRaw.theme as Record<string, unknown>) || {};\n const themeId =\n (typeof themeBlock.base_theme === \"string\" && themeBlock.base_theme) ||\n DEFAULT_THEME_ID;\n\n const globalSettings: Record<string, unknown> = {};\n for (const key of [\n \"primary_color\",\n \"secondary_color\",\n \"font_family\",\n \"logo_url\",\n ]) {\n if (themeBlock[key] !== undefined) globalSettings[key] = themeBlock[key];\n }\n if (safeRaw.identity) globalSettings.identity = safeRaw.identity;\n\n const sections: Record<string, SectionInstance> = {};\n const order: string[] = [];\n\n const hero = safeRaw.hero as Record<string, unknown> | undefined;\n if (hero) {\n sections[\"hero_1\"] = {\n type: \"hero\",\n settings: {\n // Mirrors backend `normalize_legacy_to_v3` exactly — includes\n // headline_ar so Arabic content survives the round-trip.\n headline: hero.headline ?? \"\",\n headline_ar: hero.headline_ar ?? \"\",\n subtitle: hero.subtitle ?? \"\",\n background_image: hero.hero_image_url ?? \"\",\n cta_text: hero.cta_text ?? \"\",\n cta_link: hero.cta_link ?? \"\",\n },\n };\n order.push(\"hero_1\");\n }\n\n const products = safeRaw.products as Record<string, unknown> | undefined;\n if (products) {\n sections[\"featured_1\"] = {\n type: \"featured-products\",\n settings: products,\n };\n order.push(\"featured_1\");\n }\n\n const templates: Record<string, PageTemplate> = {};\n if (Object.keys(sections).length > 0) {\n templates[\"home\"] = { name: \"Home\", sections, order };\n }\n\n const sectionGroups: Record<string, SectionGroup> = {\n header: {\n name: \"Header Group\",\n sections: {\n header_1: {\n type: \"header\",\n settings: (safeRaw.header as Record<string, unknown>) || {},\n },\n },\n order: [\"header_1\"],\n },\n footer: {\n name: \"Footer Group\",\n sections: {\n footer_1: {\n type: \"footer\",\n settings: (safeRaw.footer as Record<string, unknown>) || {},\n },\n },\n order: [\"footer_1\"],\n },\n };\n\n let externalTheme: ThemeSettingsV3[\"external_theme\"] = null;\n const ext = safeRaw.external_theme as\n | { bundle_url?: unknown; css_url?: unknown; mode?: unknown }\n | undefined;\n if (\n ext &&\n typeof ext === \"object\" &&\n typeof ext.bundle_url === \"string\" &&\n ext.bundle_url\n ) {\n externalTheme = {\n bundle_url: ext.bundle_url,\n css_url: typeof ext.css_url === \"string\" ? ext.css_url : null,\n mode: typeof ext.mode === \"string\" ? ext.mode : \"production\",\n };\n }\n\n return {\n schema_version: 3,\n theme_id: themeId,\n global_settings: globalSettings,\n templates,\n section_groups: sectionGroups,\n external_theme: externalTheme,\n };\n}\n","\"use client\";\n\n/**\n * Module Federation singleton sharing for @numueg/theme-sdk.\n *\n * Why this exists:\n * BYOT bundles (loaded at runtime as cross-origin ESM modules) need to\n * share React + the SDK with the host storefront. Otherwise React's\n * internal \"two copies\" check trips and hooks crash. The host registers\n * its singletons here; the BYOT bundle reads them via the SDK shim.\n *\n * Threat model:\n * We do NOT want third-party scripts (analytics, chat widgets, BYOT\n * community themes) to read PII off the SDK. The earlier version stored\n * the SDK on `window.__NUMU_SDK__` — anything in the page could read it\n * and call `useCustomer()` etc.\n *\n * Mitigation:\n * The singleton is keyed by a Symbol that's only handed to consumers\n * we've verified (the storefront's BYOT entry function passes it to the\n * bundle's `setup()`). Symbols can't be enumerated through `window` or\n * `Object.getOwnPropertyNames`, so a leaked global reference doesn't\n * yield SDK access.\n *\n * For maximum safety we also expose `clearSdkSingleton()` so the host\n * can revoke after a BYOT theme is unmounted.\n */\n\ninterface SdkSingleton {\n useShop: unknown;\n useProduct: unknown;\n useCollection: unknown;\n useCart: unknown;\n useCustomer: unknown;\n useThemeSettings: unknown;\n useLocalization: unknown;\n usePage: unknown;\n useSection: unknown;\n NuMuProvider: unknown;\n ProductProvider: unknown;\n CollectionProvider: unknown;\n}\n\ninterface ReactSingleton {\n React: unknown;\n ReactDOM: unknown;\n}\n\n// We pin the slot keys via `Symbol.for(name)` so ALL copies of this\n// SDK module — even when bundled with a BYOT theme — resolve to the\n// SAME Symbol identity through the global Symbol registry. The\n// previous implementation also wrote the Symbol back to a string-keyed\n// `globalThis[\"__NUMU_SDK_SLOT__\"]` slot \"so multiple module copies\n// could find it\" — but `Symbol.for()` already supplies that identity\n// (that's its entire purpose), and writing to a string-keyed\n// globalThis property put the slot name into `Object.keys(globalThis)`,\n// breaking the Principle II \"not enumerable\" privacy contract.\n//\n// What's still public:\n// - The Symbol's *name* is in the global Symbol registry. A motivated\n// attacker who knows the name can call Symbol.for() to recover the\n// same Symbol. Privacy here is obscurity-through-naming, not crypto.\n// - The actual SDK object lives at `globalThis[symbol]` — invisible\n// to `Object.keys`, `Object.getOwnPropertyNames`, and accidental\n// enumeration by third-party scripts that don't know to call\n// `Object.getOwnPropertySymbols`.\nfunction sdkSlot(): symbol {\n return Symbol.for(\"@numueg/theme-sdk:singleton\");\n}\n\nfunction reactSlot(): symbol {\n return Symbol.for(\"@numueg/theme-sdk:react\");\n}\n\nexport function registerSdkSingleton(sdk: SdkSingleton): void {\n if (typeof globalThis === \"undefined\") return;\n (globalThis as Record<symbol, unknown>)[sdkSlot()] = sdk;\n}\n\nexport function getSdkSingleton(): SdkSingleton | null {\n if (typeof globalThis === \"undefined\") return null;\n return (\n ((globalThis as Record<symbol, unknown>)[sdkSlot()] as SdkSingleton) ??\n null\n );\n}\n\nexport function clearSdkSingleton(): void {\n if (typeof globalThis === \"undefined\") return;\n delete (globalThis as Record<symbol, unknown>)[sdkSlot()];\n}\n\nexport function registerReactSingleton(\n react: unknown,\n reactDom: unknown,\n): void {\n if (typeof globalThis === \"undefined\") return;\n (globalThis as Record<symbol, unknown>)[reactSlot()] = {\n React: react,\n ReactDOM: reactDom,\n } satisfies ReactSingleton;\n}\n\nexport function getReactSingleton(): ReactSingleton | null {\n if (typeof globalThis === \"undefined\") return null;\n return (\n ((globalThis as Record<symbol, unknown>)[\n reactSlot()\n ] as ReactSingleton) ?? null\n );\n}\n\nexport function isSdkAvailable(): boolean {\n return getSdkSingleton() !== null;\n}\n","/**\n * Dynamic sources — Shopify-parity feature that lets merchants bind a\n * section setting to a value that's pulled from store data at render\n * time instead of being a literal authored value.\n *\n * Stored shape:\n * { __numu_source: \"<path>\" }\n *\n * Paths use dot notation against the resolution context:\n * - `product.title` / `product.description` / `product.price` /\n * `product.image` / `product.first_image_url`\n * - `collection.title` / `collection.description` / `collection.image`\n * - `store.name` / `store.description`\n *\n * Why a reserved discriminant key (`__numu_source`)?\n *\n * Setting values today are plain literals (`\"Hero headline\"`,\n * `12345`, `true`). Themes that read settings as strings/numbers\n * would break if we suddenly stored an object. The reserved key\n * tags object-shape values so the resolver only intercepts the ones\n * it knows about. Anything else (e.g. the `{ url, alt }` shape from\n * the image picker, or a future structured setting) passes through.\n *\n * Bindable-by-type matrix (enforced in the customizer's source picker):\n *\n * text | product.title, product.description (snippet),\n * | collection.title, collection.description (snippet),\n * | store.name, store.description\n * textarea | same as text + full descriptions\n * richtext | full descriptions only\n * url | not bindable yet — product/collection URLs require\n * | the host's route resolver; deferred to a follow-up.\n * image_picker | product.image, collection.image, store.logo\n * number/range | product.price (raw cents) — risky because format\n * | varies. Deferred.\n * color/checkbox/select/radio/font | not bindable.\n *\n * Themes consume dynamic sources via `useResolvedSettings(instance)`\n * which returns the section's settings map with every dynamic ref\n * pre-resolved against the active product/collection/store context.\n * Literal values pass through unchanged.\n */\n\nimport type { Collection, Product, Store } from \"../types/entities\";\n\n/** Stored shape for a dynamic source reference. */\nexport interface DynamicSourceRef {\n __numu_source: string;\n}\n\n/**\n * Type guard. True when `value` is a dynamic source reference object.\n * Order matters: we check the discriminant key BEFORE assuming the\n * value is anything else, so an `{ __numu_source: \"...\" }` from the\n * draft doesn't get treated as a literal record.\n */\nexport function isDynamicSource(value: unknown): value is DynamicSourceRef {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { __numu_source?: unknown }).__numu_source === \"string\"\n );\n}\n\n/**\n * Build a fresh dynamic source ref. Pure helper used by the customizer\n * when the merchant clicks a source in the picker.\n */\nexport function dynamicSource(path: string): DynamicSourceRef {\n return { __numu_source: path };\n}\n\n/** Resolution context for `resolveDynamicValue`. Each field is\n * independently optional so callers can pass only what's relevant\n * (e.g. cart template skips product/collection). */\nexport interface DynamicResolveContext {\n product?: Product | null;\n collection?: Collection | null;\n store?: Pick<Store, \"name\" | \"description\" | \"logo_url\"> | null;\n}\n\n/**\n * Look up the path inside the resolution context. Returns `null` when\n * the source is unknown OR the context doesn't have the resource\n * needed to resolve it (e.g. `product.title` when no product is in\n * context). The customizer's source picker already hides incompatible\n * sources, so this fallback only fires during preview navigation\n * (merchant flips to a product template before the picker re-renders).\n */\nexport function resolveSourcePath(\n path: string,\n ctx: DynamicResolveContext,\n): unknown {\n const [root, ...rest] = path.split(\".\");\n switch (root) {\n case \"product\": {\n const p = ctx.product;\n if (!p) return null;\n return resolveProductField(p, rest.join(\".\"));\n }\n case \"collection\": {\n const c = ctx.collection;\n if (!c) return null;\n return resolveCollectionField(c, rest.join(\".\"));\n }\n case \"store\": {\n const s = ctx.store;\n if (!s) return null;\n return resolveStoreField(s, rest.join(\".\"));\n }\n default:\n return null;\n }\n}\n\nfunction resolveProductField(p: Product, field: string): unknown {\n switch (field) {\n case \"title\":\n case \"name\":\n return p.name;\n case \"description\":\n return p.description ?? \"\";\n case \"description_snippet\":\n // 200-char excerpt — useful for short-description settings that\n // would otherwise inherit a full HTML body.\n return (p.description ?? \"\").replace(/<[^>]+>/g, \" \").trim().slice(0, 200);\n case \"price\":\n return p.price;\n case \"sku\":\n // SKU lives on the default variant in most stores.\n return p.variants?.[0]?.sku ?? null;\n case \"image\":\n case \"first_image_url\":\n return p.images?.[0]?.url ?? null;\n case \"slug\":\n return p.slug;\n default:\n return null;\n }\n}\n\nfunction resolveCollectionField(c: Collection, field: string): unknown {\n switch (field) {\n case \"title\":\n case \"name\":\n return c.name;\n case \"description\":\n return c.description ?? \"\";\n case \"description_snippet\":\n return (c.description ?? \"\").replace(/<[^>]+>/g, \" \").trim().slice(0, 200);\n case \"image\":\n return c.image_url ?? null;\n case \"slug\":\n return c.slug;\n case \"product_count\":\n return c.product_count ?? null;\n default:\n return null;\n }\n}\n\nfunction resolveStoreField(\n s: Pick<Store, \"name\" | \"description\" | \"logo_url\">,\n field: string,\n): unknown {\n switch (field) {\n case \"name\":\n return s.name ?? \"\";\n case \"description\":\n return s.description ?? \"\";\n case \"logo\":\n return s.logo_url ?? null;\n default:\n return null;\n }\n}\n\n/**\n * Resolve a single setting value. Literal values pass through\n * unchanged; dynamic references resolve against the context. Returns\n * `null` (not the original ref) when resolution fails, so themes can\n * branch on the null and either render a placeholder or hide the\n * element entirely.\n */\nexport function resolveDynamicValue<T = unknown>(\n value: unknown,\n ctx: DynamicResolveContext,\n): T | null {\n if (!isDynamicSource(value)) return value as T;\n return resolveSourcePath(value.__numu_source, ctx) as T | null;\n}\n\n/**\n * Walk every key of a settings map and resolve every dynamic\n * reference. Pure helper backing `useResolvedSettings`.\n *\n * The generic is unconstrained on purpose. Theme authors typically\n * type their settings as `interface HeroSettings { headline?: string }`,\n * and TypeScript interfaces don't implicitly satisfy\n * `Record<string, unknown>` — there's no index signature on an\n * interface. Leaving `T` open lets us pass through whatever shape the\n * caller declared and still return the resolved-but-same shape.\n */\nexport function resolveSettingsMap<T = Record<string, unknown>>(\n settings: T,\n ctx: DynamicResolveContext,\n): T {\n if (!settings || typeof settings !== \"object\") return settings;\n const input = settings as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(input)) {\n const v = input[key];\n if (isDynamicSource(v)) {\n const resolved = resolveSourcePath(v.__numu_source, ctx);\n // Preserve nullish from resolution failure so the consumer can\n // detect \"I asked for product.title but no product is active.\"\n out[key] = resolved;\n } else {\n out[key] = v;\n }\n }\n return out as T;\n}\n","\"use client\";\nimport { useContext, useMemo } from \"react\";\nimport { ProductContext, CollectionContext, ShopContext } from \"../contexts\";\nimport type { BlockInstance, SectionInstance } from \"../types/theme\";\nimport {\n type DynamicResolveContext,\n resolveSettingsMap,\n} from \"../utils/dynamicSources\";\n\n/**\n * Resolve every dynamic source in a section's settings against the\n * active product / collection / store contexts.\n *\n * Section components that want to support merchant-bound fields call\n * this in place of reading `instance.settings` directly:\n *\n * const settings = useResolvedSettings(instance);\n *\n * Literal values pass through; `{ __numu_source: \"product.title\" }`\n * becomes the current product's title when the section is rendered\n * inside a `<ProductProvider>`. The returned object is memoized on\n * the upstream contexts so themes can pass it straight into\n * `useMemo` deps without retriggering renders.\n *\n * When the bound resource isn't in context (e.g. `product.*` on a\n * non-product template), the resolved value is `null`. Themes can\n * detect this and render a placeholder or hide the affected element.\n *\n * Note: the SectionContext provider already supplies the `instance`\n * to children of `<Section>` — but we take it explicitly so section\n * components can call this hook before they've descended into\n * SectionContext (i.e. at the top of their render function, alongside\n * destructuring `settings` from props).\n */\nexport function useResolvedSettings<T = Record<string, unknown>>(\n instance: SectionInstance | BlockInstance | null | undefined,\n): T {\n const product = useContext(ProductContext);\n const collection = useContext(CollectionContext);\n const store = useContext(ShopContext);\n\n // Stabilize the resolution context object so the memo only invalidates\n // when one of the upstream values actually changes. Without this each\n // render would build a fresh `{ product, collection, store }` and the\n // useMemo dep array would never hit.\n const ctx = useMemo<DynamicResolveContext>(\n () => ({ product, collection, store }),\n [product, collection, store],\n );\n\n return useMemo(() => {\n const settings = (instance?.settings ?? {}) as T;\n return resolveSettingsMap<T>(settings, ctx);\n }, [instance, ctx]);\n}\n","/**\n * Section + block authoring helpers.\n *\n * `defineSection` and `defineBlock` bind a JSON schema to its render\n * component so theme authors don't keep two files in sync by hand.\n * The plugin ships the schema half (writes `schemas/sections/<type>.json`\n * for the customizer), the runtime imports the component half — both\n * sourced from the same factory call.\n *\n * Why factories instead of two separate files:\n * Pre-Phase-2 layout was:\n * theme/main.tsx → registers components\n * theme/schemas/sections/Hero.json → declares schema\n * Drift was the bug. Renaming a setting required edits in two places;\n * adding a new section meant remembering to update three lists.\n * Factories collapse that into a single export the plugin and runtime\n * both read.\n *\n * Usage:\n * // sections/Hero.tsx\n * import { defineSection } from \"@numueg/theme-sdk\";\n * export default defineSection({\n * schema: {\n * type: \"hero\",\n * name: \"Hero\",\n * settings: [{ type: \"text\", id: \"heading\", label: \"Heading\" }],\n * presets: [{ name: \"Hero — Centered\", settings: { heading: \"Welcome\" } }],\n * },\n * render: ({ settings }) => <h1>{settings.heading}</h1>,\n * });\n *\n * The plugin's section-discovery scan picks up files under\n * `src/sections/**\\/*.{tsx,ts}` whose default export is a section\n * definition. No registration list needed.\n */\n\nimport type { ComponentType } from \"react\";\nimport type {\n BlockProps,\n BlockSchema,\n SectionProps,\n SectionSchema,\n} from \"../types/theme\";\n\nconst SECTION_MARKER = Symbol.for(\"numu.theme.section\");\nconst BLOCK_MARKER = Symbol.for(\"numu.theme.block\");\n\n/**\n * A defined section: paired schema + render component.\n *\n * The marker symbol lets the plugin's discovery scan identify section\n * definitions without depending on a structural shape that themes might\n * accidentally collide with.\n */\nexport interface DefinedSection {\n schema: SectionSchema;\n render: ComponentType<SectionProps>;\n readonly [SECTION_MARKER]: true;\n}\n\nexport interface DefinedBlock {\n schema: BlockSchema;\n render: ComponentType<BlockProps>;\n readonly [BLOCK_MARKER]: true;\n}\n\nexport interface DefineSectionInput {\n schema: SectionSchema;\n render: ComponentType<SectionProps>;\n}\n\nexport interface DefineBlockInput {\n schema: BlockSchema;\n render: ComponentType<BlockProps>;\n}\n\n/**\n * Bind a section schema to its renderer.\n *\n * Validates at runtime that `schema.type` is a stable identifier\n * (lowercase + dashes/underscores) — drift here breaks the plugin's\n * codegen step (which writes `__generated__/sections.d.ts` keyed off\n * `schema.type`).\n */\nexport function defineSection(input: DefineSectionInput): DefinedSection {\n if (!input?.schema?.type) {\n throw new Error(\n \"defineSection: `schema.type` is required and must be a stable string id.\",\n );\n }\n if (!/^[a-z][a-z0-9_-]*$/.test(input.schema.type)) {\n throw new Error(\n `defineSection: section type '${input.schema.type}' must be lowercase alphanumeric ` +\n `with dashes/underscores. The codegen step uses this as a TS key.`,\n );\n }\n if (typeof input.render !== \"function\") {\n throw new Error(\n \"defineSection: `render` must be a React component function.\",\n );\n }\n return Object.freeze({\n schema: input.schema,\n render: input.render,\n [SECTION_MARKER]: true as const,\n });\n}\n\nexport function defineBlock(input: DefineBlockInput): DefinedBlock {\n if (!input?.schema?.type) {\n throw new Error(\"defineBlock: `schema.type` is required.\");\n }\n if (!/^[a-z@][a-z0-9_/-]*$/i.test(input.schema.type)) {\n throw new Error(\n `defineBlock: block type '${input.schema.type}' has illegal chars. ` +\n `Use a-z, 0-9, dashes/underscores; @app/<slug>/<block> form is also accepted.`,\n );\n }\n if (typeof input.render !== \"function\") {\n throw new Error(\n \"defineBlock: `render` must be a React component function.\",\n );\n }\n return Object.freeze({\n schema: input.schema,\n render: input.render,\n [BLOCK_MARKER]: true as const,\n });\n}\n\nexport function isDefinedSection(v: unknown): v is DefinedSection {\n return (\n typeof v === \"object\" &&\n v !== null &&\n (v as Record<symbol, unknown>)[SECTION_MARKER] === true\n );\n}\n\nexport function isDefinedBlock(v: unknown): v is DefinedBlock {\n return (\n typeof v === \"object\" &&\n v !== null &&\n (v as Record<symbol, unknown>)[BLOCK_MARKER] === true\n );\n}\n\n/**\n * Build a section registry from a Vite glob import.\n *\n * Themes call this at the top of their `main.tsx`:\n *\n * const sectionModules = import.meta.glob<{ default: DefinedSection }>(\n * \"./sections/*.tsx\", { eager: true });\n * const sections = collectSections(sectionModules);\n *\n * The returned object is keyed by `schema.type` for direct lookup at\n * render time. Modules whose default export isn't a DefinedSection are\n * skipped with a console warning (drops a half-migrated section without\n * breaking the rest of the bundle).\n */\nexport function collectSections<T extends Record<string, unknown>>(\n modules: T,\n): Record<string, DefinedSection> {\n const out: Record<string, DefinedSection> = {};\n for (const [path, mod] of Object.entries(modules)) {\n const def = (mod as { default?: unknown }).default;\n if (!isDefinedSection(def)) {\n if (typeof console !== \"undefined\") {\n console.warn(\n `[numu] ${path}: default export is not a defineSection() result; skipped.`,\n );\n }\n continue;\n }\n if (out[def.schema.type]) {\n throw new Error(\n `[numu] duplicate section type '${def.schema.type}': ` +\n `previously defined, now also defined in ${path}.`,\n );\n }\n out[def.schema.type] = def;\n }\n return out;\n}\n\nexport function collectBlocks<T extends Record<string, unknown>>(\n modules: T,\n): Record<string, DefinedBlock> {\n const out: Record<string, DefinedBlock> = {};\n for (const [path, mod] of Object.entries(modules)) {\n const def = (mod as { default?: unknown }).default;\n if (!isDefinedBlock(def)) {\n if (typeof console !== \"undefined\") {\n console.warn(\n `[numu] ${path}: default export is not a defineBlock() result; skipped.`,\n );\n }\n continue;\n }\n if (out[def.schema.type]) {\n throw new Error(\n `[numu] duplicate block type '${def.schema.type}': ` +\n `previously defined, now also defined in ${path}.`,\n );\n }\n out[def.schema.type] = def;\n }\n return out;\n}\n","/**\n * `assetUrl(name)` — resolve a theme-bundled asset's runtime URL.\n *\n * Themes ship static assets (images, fonts, JSON) under `assets/`.\n * The plugin copies each asset to `dist/assets/` with a content-hashed\n * filename and writes a manifest (`asset-manifest.json`) mapping each\n * source path to the hashed name.\n *\n * At runtime this function reads the manifest off the runtime window\n * object (`window.__NUMU_ASSET_MANIFEST`) — populated by the storefront's\n * `<RuntimeImportMap>` component when the theme bundle is loaded —\n * and returns the absolute URL to the hashed file.\n *\n * Why a runtime helper instead of bake-time string interpolation:\n * The same theme bundle is reused across hosted stores. The asset\n * base URL differs per environment (CDN vs local dev) and per store\n * (subdomain vs custom domain). Resolving at runtime keeps a single\n * bundle deployable across all of them.\n *\n * Usage:\n * <Image src={assetUrl(\"hero.jpg\")} alt=\"...\" />\n * <link rel=\"preload\" as=\"font\" href={assetUrl(\"fonts/Inter.woff2\")} />\n *\n * Behavior when the manifest is missing or the asset isn't listed:\n * Returns the original `name` (prefixed with the conventional\n * `/assets/` path) as a fallback. This keeps dev workable when the\n * plugin's asset-pipeline step hasn't run yet, and surfaces obviously-\n * wrong asset names as 404s rather than silent failures.\n */\n\ninterface AssetManifest {\n /** Map of source asset path → hashed filename in dist/assets/ */\n [sourcePath: string]: string;\n}\n\ninterface AssetRuntimeConfig {\n /** Manifest written by the plugin at build time and injected at runtime. */\n __NUMU_ASSET_MANIFEST?: AssetManifest;\n /**\n * Optional CDN/path prefix. Defaults to \"/assets/\" — themes hosted on\n * a CDN can override by setting this on `window` before mount.\n */\n __NUMU_ASSET_BASE_URL?: string;\n}\n\nfunction getRuntime(): AssetRuntimeConfig {\n if (typeof window === \"undefined\") return {};\n return window as unknown as AssetRuntimeConfig;\n}\n\nexport function assetUrl(name: string): string {\n if (!name) return \"\";\n // Already-absolute or already-resolved (starts with /, http://, https://) →\n // pass through. Theme code that mixes hand-written paths with assetUrl()\n // is fine, this is just a no-op for those.\n if (/^https?:\\/\\//i.test(name) || name.startsWith(\"//\")) return name;\n\n const runtime = getRuntime();\n const manifest = runtime.__NUMU_ASSET_MANIFEST;\n const base = runtime.__NUMU_ASSET_BASE_URL || \"/assets/\";\n\n // Normalize: strip leading \"./\" or \"assets/\" so callers can write\n // `assetUrl(\"hero.jpg\")` or `assetUrl(\"./hero.jpg\")` interchangeably.\n let key = name.replace(/^\\.\\//, \"\");\n if (key.startsWith(\"/\")) key = key.slice(1);\n if (key.startsWith(\"assets/\")) key = key.slice(\"assets/\".length);\n\n const hashed = manifest?.[key];\n // No manifest hit → fall back to the bare path under base. Keeps dev\n // (where the plugin watch hasn't emitted a manifest yet) workable.\n const filename = hashed || key;\n // Ensure exactly one slash between base and filename.\n const cleanBase = base.endsWith(\"/\") ? base : `${base}/`;\n return `${cleanBase}${filename}`;\n}\n","/**\n * focalSrc — build a URL for a server-side, focal-point-aware image transform.\n *\n * OPT-IN helper. A theme that wants a bandwidth-efficient SMART CROP for a big\n * image (typically a hero) calls this to point the <img src> at the storefront's\n * `/api/image-transform` endpoint with focal/aspect params. The endpoint honors\n * them only when Cloudflare Image Resizing is enabled on the zone\n * (NUMU_CF_IMAGE_RESIZING=1); otherwise it gracefully ignores them and serves a\n * plain resized image — so the theme's CSS `applyImageTransform` framing remains\n * the correctness baseline either way. This is purely a perf optimization.\n *\n * Returns a RELATIVE path (`/api/image-transform?...`) — the SDK runs\n * same-origin inside the storefront, matching how <Form>/useShop build URLs.\n *\n * @example\n * <img\n * src={focalSrc(hero.url, { width: 1600, focal: t?.focal, aspect: \"16/9\" })}\n * style={applyImageTransform(t, \"cover\")} // CSS still frames as fallback\n * />\n */\nexport interface FocalSrcOptions {\n /** Target width in px (e.g. 1600 for a desktop hero). Required for a crop. */\n width?: number;\n /** Focal point, normalized 0..1 (0.5,0.5 = center). */\n focal?: { x?: number; y?: number };\n /** Target aspect ratio \"W/H\" (e.g. \"16/9\"); drives the crop box height. */\n aspect?: string;\n /** Crop mode. Default \"cover\". */\n fit?: \"cover\" | \"contain\";\n /** Quality 1..100. */\n quality?: number;\n /** Output format. */\n format?: \"webp\" | \"avif\" | \"jpeg\" | \"jpg\" | \"png\";\n}\n\nconst clamp01 = (n: number) => Math.min(1, Math.max(0, n));\n\nexport function focalSrc(\n url: string | null | undefined,\n options: FocalSrcOptions = {},\n): string {\n if (!url) return \"\";\n // data: URIs and already-transformed URLs pass through untouched.\n if (url.startsWith(\"data:\") || /[?&](fp-x|fp-y)=/.test(url)) return url;\n\n const p = new URLSearchParams();\n p.set(\"url\", url);\n if (options.width) p.set(\"w\", String(Math.round(options.width)));\n if (options.focal?.x != null) p.set(\"fp-x\", String(clamp01(options.focal.x)));\n if (options.focal?.y != null) p.set(\"fp-y\", String(clamp01(options.focal.y)));\n if (options.aspect) p.set(\"ar\", options.aspect);\n if (options.fit) p.set(\"fit\", options.fit);\n if (options.quality) p.set(\"q\", String(Math.min(100, Math.max(1, Math.round(options.quality)))));\n if (options.format) p.set(\"f\", options.format.toLowerCase());\n\n return `/api/image-transform?${p.toString()}`;\n}\n","/**\n * Theme-bundled locale files: load + merge.\n *\n * The plugin discovers `locales/<code>.json` (and the fallback\n * `locales/en.default.json`) and bakes them into the bundle as a map\n * keyed by locale code. The runtime calls `pickTranslations(map, locale)`\n * to resolve the right one, with English fallback for missing keys.\n *\n * Conventions:\n * - locales/en.default.json is the canonical English source. It's\n * the fallback for any other locale's missing keys.\n * - locales/ar.json (and friends) override or extend the default.\n * - Nested keys are flattened with dot notation: `{\"hero\": {\"cta\": \"Buy\"}}`\n * becomes `\"hero.cta\"` for `t(\"hero.cta\")` to look up.\n *\n * Why flatten:\n * `useTranslation()` returns `t(key)` which expects a string lookup —\n * structured access would force every theme to write\n * `translations.hero?.cta ?? \"Buy\"`. Flattening keeps the call site\n * short and matches Shopify's `t` semantics.\n */\n\nexport interface LocaleMessages {\n [key: string]: string;\n}\n\nexport interface LocaleBundle {\n /** Locale code → flat key/value messages. */\n [locale: string]: LocaleMessages;\n}\n\n/**\n * Recursively flatten a nested locale object into dot-keyed strings.\n *\n * Non-string leaves are skipped with a console warning — translations\n * are user-facing strings; numbers and booleans don't belong in a\n * locale file (they should be in schema settings).\n */\nexport function flattenMessages(\n source: Record<string, unknown>,\n prefix = \"\",\n): LocaleMessages {\n const out: LocaleMessages = {};\n for (const [key, val] of Object.entries(source)) {\n const fullKey = prefix ? `${prefix}.${key}` : key;\n if (val === null || val === undefined) continue;\n if (typeof val === \"string\") {\n out[fullKey] = val;\n } else if (typeof val === \"object\" && !Array.isArray(val)) {\n Object.assign(\n out,\n flattenMessages(val as Record<string, unknown>, fullKey),\n );\n } else if (typeof console !== \"undefined\") {\n console.warn(\n `[numu] locale key '${fullKey}' has non-string value (${typeof val}); skipped.`,\n );\n }\n }\n return out;\n}\n\n/**\n * Resolve the messages map for the requested locale, falling back to\n * \"en\" then \"en.default\" then an empty map. Missing keys in the\n * requested locale are filled from \"en\" (so an Arabic translation\n * file with 90% coverage doesn't show empty strings for the missing\n * 10%; English shows through).\n */\nexport function pickTranslations(\n bundle: LocaleBundle,\n locale: string,\n): LocaleMessages {\n const fallback = bundle[\"en\"] || bundle[\"en.default\"] || {};\n const requested = bundle[locale];\n if (!requested) return fallback;\n // Merge: fallback < requested. The requested locale wins per-key;\n // any key the requested locale doesn't define falls through to en.\n return { ...fallback, ...requested };\n}\n\n/**\n * Build a LocaleBundle from raw imports. Themes call this in their\n * `main.tsx` after a Vite glob import:\n *\n * const localeModules = import.meta.glob<Record<string, unknown>>(\n * \"./locales/*.json\", { eager: true, import: \"default\" });\n * const translations = buildLocaleBundle(localeModules);\n *\n * `localeModules` keys are paths like `./locales/ar.json`; we strip\n * the directory + extension to get the locale code, and flatten each\n * value.\n */\nexport function buildLocaleBundle<T extends Record<string, unknown>>(\n modules: T,\n): LocaleBundle {\n const bundle: LocaleBundle = {};\n for (const [path, raw] of Object.entries(modules)) {\n const m = /\\/([^/]+)\\.json$/.exec(path);\n if (!m) continue;\n let code = m[1];\n // `en.default` → keep as-is so pickTranslations can find it; theme\n // devs naming the file that way is a soft signal that this is the\n // canonical English source.\n if (code !== \"en.default\") {\n // Strip trailing \".default\" from any other code (someone might\n // write `ar.default.json` by mistake).\n code = code.replace(/\\.default$/, \"\");\n }\n const value = raw as unknown;\n if (typeof value === \"object\" && value !== null) {\n bundle[code] = flattenMessages(value as Record<string, unknown>);\n }\n }\n return bundle;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/types/theme.ts","../src/contexts/index.ts","../src/hooks/useLocalization.ts","../src/hooks/useShop.ts","../src/hooks/useProduct.ts","../src/hooks/useCollection.ts","../src/hooks/useCart.ts","../src/hooks/useCustomer.ts","../src/hooks/useThemeSettings.ts","../src/hooks/useCurrentTemplate.ts","../src/hooks/usePage.ts","../src/hooks/useSection.ts","../src/hooks/useMoney.ts","../src/hooks/useImage.ts","../src/hooks/useProducts.ts","../src/hooks/useCollections.ts","../src/contexts/customer-actions.ts","../src/hooks/useCustomerActions.ts","../src/hooks/useOrders.ts","../src/hooks/useCustomerAddresses.ts","../src/hooks/useNavigation.ts","../src/hooks/useSearch.ts","../src/hooks/useAnalytics.ts","../src/hooks/useApp.ts","../src/hooks/useWishlist.ts","../src/hooks/useRelatedProducts.ts","../src/hooks/useProductSizeChart.ts","../src/hooks/useCurrency.ts","../src/utils/variants.ts","../src/hooks/useVariantSelection.ts","../src/hooks/useGiftCardBalance.ts","../src/hooks/useReorder.ts","../src/hooks/useCheckout.ts","../src/hooks/useShippingRates.ts","../src/components/NuMuProvider.tsx","../src/components/ProductProvider.tsx","../src/utils/styleTokens.ts","../src/mount.tsx","../src/entry.tsx","../src/components/CollectionProvider.tsx","../src/components/Money.tsx","../src/utils/imageTransform.ts","../src/components/Image.tsx","../src/components/Link.tsx","../src/components/AddToCartButton.tsx","../src/components/Section.tsx","../src/components/Form.tsx","../src/components/ProductCard.tsx","../src/components/CollectionCard.tsx","../src/components/RichText.tsx","../src/components/CurrencySwitcher.tsx","../src/components/LocaleSwitcher.tsx","../src/components/Editable.tsx","../src/components/Icon.tsx","../src/utils/normalize.ts","../src/utils/federation.ts","../src/utils/dynamicSources.ts","../src/hooks/useResolvedSettings.ts","../src/utils/defineSection.ts","../src/utils/assetUrl.ts","../src/utils/locales.ts"],"names":["useContext","createContext","useMemo","useState","useEffect","unwrap","useCallback","opts","useRef","jsx","ThemeMountBridge","DEFAULT_WIDTHS","ABSOLUTE_URL","readCsrfCookie","jsxs","joinClass","Fragment","forwardRef","EditableText","Component","EditableImage"],"mappings":"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","file":"index.mjs","sourcesContent":["/** V3 Theme Settings — the canonical data shape */\nexport interface ThemeSettingsV3 {\n schema_version: 3;\n theme_id: string;\n global_settings: Record<string, any>;\n templates: Record<string, PageTemplate>;\n section_groups: Record<string, SectionGroup>;\n external_theme?: ExternalThemeMetadata | null;\n}\n\nexport interface PageTemplate {\n name: string;\n sections: Record<string, SectionInstance>;\n order: string[];\n}\n\nexport interface SectionGroup {\n name: string;\n sections: Record<string, SectionInstance>;\n order: string[];\n}\n\nexport interface SectionInstance {\n type: string;\n settings: Record<string, any>;\n disabled?: boolean;\n blocks?: Record<string, BlockInstance>;\n block_order?: string[];\n}\n\nexport interface BlockInstance {\n type: string;\n settings: Record<string, any>;\n disabled?: boolean;\n /** Nested child blocks (blocks-in-blocks): a block can hold its own\n * block container — e.g. a footer \"column\" holding \"link\" blocks, or\n * a mega-menu. Same shape as a section's block container, so the\n * render/editor walk is uniform at any depth. Optional + absent on\n * leaf blocks, so pre-nesting payloads load unchanged. */\n blocks?: Record<string, BlockInstance>;\n block_order?: string[];\n}\n\nexport interface ExternalThemeMetadata {\n bundle_url: string;\n css_url?: string | null;\n mode?: string;\n settings_schema?: Record<string, any> | null;\n section_schemas?: Record<string, any> | null;\n}\n\n/**\n * Live mount handle returned by a V3 theme bundle's `mount(el, ctx)`.\n *\n * Two shapes accepted by the host:\n *\n * 1. **Legacy** — `mount(el, ctx): () => void`\n * The bundle returns only a cleanup function. Every host-side\n * themeSettings change forces a full unmount + remount, which is\n * expensive but always correct. Hosts must keep supporting this\n * for older bundles built against pre-0.2 SDK versions.\n *\n * 2. **Wave 3+** — `mount(el, ctx): MountResult`\n * The bundle returns an object with `cleanup` + an `applyDraft`\n * method that takes a fresh `ThemeSettingsV3` and re-renders the\n * bundle's React tree in-place (no createRoot churn). This is the\n * fast path used by the customizer's live preview — a keystroke\n * in the dashboard becomes a single React reconciliation in the\n * iframe, typically < 16 ms.\n *\n * Hosts feature-detect by checking `typeof handle === \"function\"`\n * (legacy) vs `typeof handle === \"object\" && handle.cleanup`\n * (Wave 3+). Theme authors should prefer the MountResult shape — the\n * `numuTheme` plugin's typings will flag the missing applyDraft once\n * the editor's live-preview path requires it.\n */\nexport interface MountResult {\n /** Unmount the bundle's React tree and release any resources. */\n cleanup: () => void;\n /**\n * Apply a fresh draft (e.g. from the customizer iframe's\n * `numu:theme:update` postMessage) without tearing down the tree.\n * Implementations typically forward the value to a useState setter\n * inside a wrapper that renders `<NuMuProvider themeSettings={...}>`.\n *\n * Safe to call repeatedly; the bundle is expected to dedup\n * reference-equal calls on its own. Returns nothing — selection /\n * navigation echo back via postMessage.\n */\n applyDraft: (next: ThemeSettingsV3) => void;\n}\n\n/** Section schema for customizer form generation */\nexport interface SectionSchema {\n type: string;\n name: string;\n name_ar?: string;\n tag?: string;\n class?: string;\n limit?: number;\n settings: SettingDefinition[];\n blocks?: BlockSchema[];\n max_blocks?: number;\n presets?: SectionPreset[];\n}\n\nexport interface BlockSchema {\n type: string;\n name: string;\n name_ar?: string;\n limit?: number;\n settings: SettingDefinition[];\n /** Child block types this block accepts (recursive). When present,\n * the customizer lets merchants add/remove/reorder these inside the\n * block, up to `max_blocks`. Enables footer columns, mega-menus,\n * multi-column layouts. The host caps practical nesting depth\n * (MAX_BLOCK_DEPTH). */\n blocks?: BlockSchema[];\n max_blocks?: number;\n}\n\n/** Max nesting depth the customizer allows for blocks-in-blocks. Depth\n * 1 = a top-level block in a section; a block at this depth can't take\n * children. Generous (below Shopify's 8) and cheap to raise. Kept in\n * sync with the merchant hub's MAX_BLOCK_DEPTH. */\nexport const MAX_BLOCK_DEPTH = 5;\n\n/**\n * Setting types the V3 customizer renders. Themes can declare any\n * string here; unknown types fall through to a plain text input. The\n * union below documents the canonical set so theme authors get\n * autocomplete and TypeScript errors on typos.\n */\nexport type SettingType =\n | \"text\"\n | \"textarea\"\n | \"richtext\"\n | \"number\"\n | \"range\"\n | \"color\"\n | \"checkbox\"\n | \"select\"\n | \"radio\"\n | \"font\"\n | \"image_picker\"\n | \"url\"\n | \"product\"\n | \"product_list\"\n | \"collection\"\n | \"collection_list\"\n | \"header\"\n | \"paragraph\"\n | \"html\"\n | \"date\"\n | \"time\"\n | \"video_picker\"\n | \"color_scheme\"\n | \"page_picker\"\n | \"blog_picker\"\n | \"link_list_picker\"\n | \"variant_picker\"\n | \"file_upload\"\n | \"icon_picker\"\n | \"icon\";\n\n/**\n * `visible_if` — conditional visibility expression evaluated against\n * sibling settings in the same schema. Two flavors:\n *\n * - String DSL: `\"settings.show_button == true && settings.layout != 'minimal'\"`\n * - Object form: `{ show_button: true, layout: [\"full\", \"split\"] }`\n *\n * Evaluator lives in the merchant hub: any setting whose expression is\n * falsy is skipped from the rendered form.\n */\nexport type VisibleIf = string | Record<string, unknown>;\n\nexport interface SettingDefinition {\n type: SettingType | (string & {}); // unions stay open for forward-compat\n id: string;\n label: string;\n label_ar?: string;\n default?: any;\n info?: string;\n info_ar?: string;\n placeholder?: string;\n options?: { value: string; label: string; label_ar?: string }[];\n min?: number;\n max?: number;\n step?: number;\n unit?: string;\n /** Hide this setting unless the expression evaluates truthy. */\n visible_if?: VisibleIf;\n}\n\nexport interface PresetBlock {\n type: string;\n settings?: Record<string, any>;\n /** Nested starter blocks materialized when the preset is applied\n * (recursive). Lets a preset ship, e.g., a footer column already\n * populated with link blocks. */\n blocks?: PresetBlock[];\n}\n\nexport interface SectionPreset {\n name: string;\n /** Localized names so the Add Section dialog reads in the editor's\n * current locale. Falls back to `name` when the locale is missing. */\n locales?: {\n en?: { name?: string };\n ar?: { name?: string };\n };\n settings?: Record<string, any>;\n blocks?: PresetBlock[];\n}\n\n/** Section component props */\nexport interface SectionProps {\n settings: Record<string, any>;\n blocks?: Record<string, BlockInstance>;\n blockOrder?: string[];\n storeData?: any;\n}\n\n/** Block component props */\nexport interface BlockProps {\n settings: Record<string, any>;\n /** Child block instances when this block nests others (footer column,\n * mega-menu, …). Mirror the section→block render: map `blockOrder`\n * and look each id up in `blocks`, wrapping each child in `<Block>`. */\n blocks?: Record<string, BlockInstance>;\n blockOrder?: string[];\n}\n","\"use client\";\nimport { createContext } from \"react\";\nimport type { Store, Product, Collection, Cart, Customer, Page } from \"../types/entities\";\nimport type { ThemeSettingsV3 } from \"../types/theme\";\n\nexport interface LocalizationState {\n locale: string;\n direction: \"ltr\" | \"rtl\";\n translations: Record<string, string>;\n formatMoney: (amount: number, currency?: string) => string;\n formatDate: (date: string | Date) => string;\n /**\n * Phase 3.7 — locale-aware number formatter. Routes to either\n * Western (1234) or Arab-Indic (١٢٣٤) digits depending on\n * `store.settings.numerals`. Themes calling formatMoney get the\n * same digit choice automatically; this is for raw counts (\"12 items\").\n */\n formatNumber: (n: number, options?: Intl.NumberFormatOptions) => string;\n /**\n * Phase 3.6 — switch the active locale.\n *\n * Sets the `numu_locale` cookie and triggers a full page reload so\n * the server-rendered layout picks up the new locale (the storefront\n * resolves locale at SSR time from cookie/query). Returns once the\n * cookie is written; the page navigation cancels any pending React\n * work so callers don't need to await.\n */\n setLocale: (next: string) => void;\n /**\n * Phase 3.6 — list of locales the store advertises. Empty when the\n * store hasn't configured a multi-locale catalog. Themes use this\n * to decide whether to render the LocaleSwitcher at all.\n */\n availableLocales: string[];\n}\n\nexport const ShopContext = createContext<Store | null>(null);\nexport const ProductContext = createContext<Product | null>(null);\nexport const CollectionContext = createContext<Collection | null>(null);\nexport const CartContext = createContext<{ cart: Cart; addItem: (productId: string, variantId?: string, quantity?: number) => Promise<void>; removeItem: (itemId: string) => Promise<void>; updateQuantity: (itemId: string, quantity: number) => Promise<void>; applyDiscount: (code: string) => Promise<void>; removeDiscount: () => Promise<void>; updateNote: (note: string) => Promise<void>; clearCart: () => Promise<void>; loading: boolean } | null>(null);\nexport const CustomerContext = createContext<Customer | null>(null);\nexport const ThemeSettingsContext = createContext<ThemeSettingsV3 | null>(null);\nexport const LocalizationContext = createContext<LocalizationState | null>(null);\nexport const PageContext = createContext<Page | null>(null);\n/**\n * Wave 5 — currently-active template identifier. Mirrors the key inside\n * `themeSettings.templates.<currentTemplate>` so themes can dispatch\n * which section list to render. Hosts set this via `NuMuProvider`'s\n * `currentTemplate` prop (which is passed in by the storefront page\n * component — `app/(store)/[subdomain]/product/[id]/page.tsx` passes\n * \"product\", `cart/page.tsx` passes \"cart\", etc.). Falls back to \"home\".\n */\nexport const CurrentTemplateContext = createContext<string>(\"home\");\n\n/**\n * A merchant-managed navigation menu item, exactly as the storefront\n * menus resolver returns it (`GET /storefront/store/{id}/menus`):\n * bilingual `label`, a pre-resolved `url`, and nested `children`.\n *\n * This is the RAW shape the host injects via `NuMuProvider`'s\n * `navigation` prop. `useNavigation(handle)` localizes it to the\n * display-ready `NavigationItem` (a single `title` string for the\n * active locale).\n */\nexport interface MenuItemData {\n id: string;\n label: Record<string, string>;\n url: string;\n type?: string | null;\n resource_id?: string | null;\n children?: MenuItemData[];\n}\n\n/**\n * Phase 2.4 — navigation menus keyed by handle (`main-menu`, `footer`,\n * plus custom), injected by the host from the storefront resolver so a\n * theme's `useNavigation(handle)` resolves without a client round-trip.\n *\n * Defaults to `{}` — an empty map signals \"host provided no menus\", at\n * which point `useNavigation` falls back to its own fetch / a theme's\n * `DEFAULT_NAV`. A present-but-handle-absent map means the menu simply\n * doesn't exist (render nothing / fallback), no fetch attempted.\n */\nexport const NavigationContext = createContext<Record<string, MenuItemData[]>>(\n {},\n);\n","import { useContext } from \"react\";\nimport { LocalizationContext } from \"../contexts\";\nimport type { LocalizationState } from \"../contexts\";\n\nexport function useLocalization(): LocalizationState {\n const ctx = useContext(LocalizationContext);\n if (!ctx) throw new Error(\"useLocalization must be used within NuMuProvider\");\n return ctx;\n}\n\nexport function useDirection(): \"ltr\" | \"rtl\" {\n const { direction } = useLocalization();\n return direction;\n}\n\nexport function useLocale(): string {\n const { locale } = useLocalization();\n return locale;\n}\n\nexport function useTranslation() {\n const { translations, locale } = useLocalization();\n return {\n t: (key: string, fallback?: string) => translations[key] || fallback || key,\n locale,\n };\n}\n\n/**\n * Phase 3.6 — pull a translated field off a domain object.\n *\n * Convention: per-product translations live on `entity.attributes`\n * keyed as `<field>_<locale>` — e.g. `name_ar`, `description_ar`.\n * Backend writes these via the merchant hub when a merchant turns on\n * \"Translations\" for a product. Themes call:\n *\n * const productName = useFieldTranslation(product, \"name\");\n *\n * and get the Arabic name when the active locale is \"ar\", falling\n * back to the English `product.name` otherwise. Works for any object\n * that pairs a base field on the entity with an `attributes` JSONB\n * blob holding the translated variants.\n *\n * Why not put translations on the entity itself? Adding `name_ar`,\n * `description_ar`, `name_he`, etc. as first-class columns means a\n * schema migration every time a merchant enables a new locale. JSONB\n * lets the merchant flip locales on/off in settings without touching\n * the table.\n */\nexport function useFieldTranslation<\n T extends { attributes?: Record<string, unknown> },\n>(entity: T | null | undefined, field: string): string | undefined {\n const { locale } = useLocalization();\n if (!entity) return undefined;\n // English (or whichever default locale the merchant configured) is\n // stored as the base field; non-default locales live on attributes\n // with a `<field>_<locale>` key.\n const translated =\n entity.attributes && typeof entity.attributes === \"object\"\n ? (entity.attributes as Record<string, unknown>)[`${field}_${locale}`]\n : undefined;\n if (typeof translated === \"string\" && translated) return translated;\n // Base field — supports any value type that stringifies sensibly.\n const base = (entity as unknown as Record<string, unknown>)[field];\n if (typeof base === \"string\") return base;\n if (base == null) return undefined;\n return String(base);\n}\n\n/**\n * Phase 3.7 — formatted-number hook.\n *\n * Themes that need to render counts (\"12 items\", \"3 reviews\") should\n * route through this hook so Arab-Indic digits (٠١٢٣٤) vs Western\n * (01234) stay consistent with money + date elsewhere on the page.\n *\n * const fmtNum = useNumberFormat();\n * fmtNum(12) → \"12\" (or \"١٢\" for Arabic stores)\n * fmtNum(12.5, { minimumFractionDigits: 2 }) → \"12.50\" / \"١٢٫٥٠\"\n */\nexport function useNumberFormat() {\n const { formatNumber } = useLocalization();\n return formatNumber;\n}\n","\"use client\";\nimport { useContext, useMemo } from \"react\";\nimport { ShopContext } from \"../contexts\";\nimport { useLocale } from \"./useLocalization\";\nimport type { Store } from \"../types/entities\";\n\n/**\n * Augmented Store shape returned from useShop().\n *\n * Adds a couple of conveniences theme devs reach for constantly:\n * - `domain` — the active hostname (subdomain or custom). Resolved\n * from `store.domain ?? store.subdomain ?? store.slug`.\n * - `formatUrl(path)` — emits a fully-qualified URL using `domain`.\n * Theme code that needs to render absolute URLs (canonical tags,\n * Open Graph, JSON-LD) goes through this so dev/prod / subdomain\n * vs. custom-domain stays correct without each theme reinventing\n * the resolver.\n */\nexport interface ShopWithHelpers extends Store {\n /** Fully-qualified hostname this store currently serves on. */\n domain: string;\n /**\n * Format a path (relative or absolute) as a fully-qualified URL on\n * this store's domain. No-ops when given an already-absolute URL.\n *\n * Phase 6 — when the active locale is non-default and the store\n * has opted into locale URL prefixes, the path is prefixed with\n * `/{locale}/` (e.g. `/ar/products/foo`). Already-prefixed paths\n * are left alone so calling `formatUrl(formatUrl(...))` is safe.\n */\n formatUrl(path: string): string;\n}\n\nconst DEFAULT_PROTOCOL =\n typeof window !== \"undefined\"\n ? window.location.protocol.replace(\":\", \"\")\n : \"https\";\n\nfunction resolveDomain(store: Store): string {\n // Custom domain wins when set; otherwise fall back to the platform\n // subdomain. The slug is a last resort for stores that haven't been\n // assigned either yet (mostly demo stores in dev).\n if (store.domain) return store.domain;\n if (store.subdomain) {\n // The platform-domain default lives on the storefront; theme code\n // doesn't have access to env vars, so we read it off the runtime\n // window object when present and fall back to the well-known\n // production value. Themes can override by rendering with\n // `<meta name=\"numu:platform-domain\" content=\"...\">` if they're\n // hosted on a non-default platform.\n const platform =\n (typeof window !== \"undefined\" &&\n (window as unknown as { __NUMU_PLATFORM_DOMAIN?: string })\n .__NUMU_PLATFORM_DOMAIN) ||\n \"numueg.app\";\n return `${store.subdomain}.${platform}`;\n }\n return store.slug;\n}\n\nexport function useShop(): ShopWithHelpers {\n const ctx = useContext(ShopContext);\n if (!ctx) throw new Error(\"useShop must be used within NuMuProvider\");\n const locale = useLocale();\n\n return useMemo(() => {\n const domain = resolveDomain(ctx);\n const settings = (ctx as Store & { settings?: Record<string, unknown> })\n .settings;\n const localePrefixEnabled = Boolean(\n settings && (settings as { locale_url_prefix_enabled?: boolean }).locale_url_prefix_enabled,\n );\n const defaultLocale = ctx.default_language || \"en\";\n // List of locales that get a URL prefix. Defaults to \"everything\n // except the default\" — but a store can opt into `[\"ar\", \"en\"]`\n // (prefix even the default) if it wants a fully prefixed URL\n // scheme like Shopify does for markets.\n const prefixedLocales =\n (settings as { locale_url_prefix_locales?: string[] } | undefined)\n ?.locale_url_prefix_locales || null;\n const shouldPrefix = (l: string): boolean => {\n if (!localePrefixEnabled) return false;\n if (prefixedLocales) return prefixedLocales.includes(l);\n return l !== defaultLocale;\n };\n\n const formatUrl = (path: string): string => {\n if (!path) return `${DEFAULT_PROTOCOL}://${domain}/`;\n // Already absolute? Hand back as-is.\n if (/^https?:\\/\\//i.test(path)) return path;\n // Protocol-relative — assume same protocol as the host.\n if (path.startsWith(\"//\")) return `${DEFAULT_PROTOCOL}:${path}`;\n let normalized = path.startsWith(\"/\") ? path : `/${path}`;\n if (locale && shouldPrefix(locale)) {\n // Idempotent: don't double-prefix if the caller already\n // gave us a /{locale}/... path.\n const prefix = `/${locale}/`;\n const root = `/${locale}`;\n if (normalized !== root && !normalized.startsWith(prefix)) {\n normalized = `${root}${normalized}`;\n }\n }\n return `${DEFAULT_PROTOCOL}://${domain}${normalized}`;\n };\n return { ...ctx, domain, formatUrl };\n }, [ctx, locale]);\n}\n","import { useContext } from \"react\";\nimport { ProductContext } from \"../contexts\";\nimport type { Product } from \"../types/entities\";\n\nexport function useProduct(): Product {\n const ctx = useContext(ProductContext);\n if (!ctx) throw new Error(\"useProduct must be used within ProductProvider\");\n return ctx;\n}\n\nexport function useProductOptional(): Product | null {\n return useContext(ProductContext);\n}\n","import { useContext } from \"react\";\nimport { CollectionContext } from \"../contexts\";\nimport type { Collection } from \"../types/entities\";\n\nexport function useCollection(): Collection {\n const ctx = useContext(CollectionContext);\n if (!ctx) throw new Error(\"useCollection must be used within CollectionProvider\");\n return ctx;\n}\n\nexport function useCollectionOptional(): Collection | null {\n return useContext(CollectionContext);\n}\n","import { useContext } from \"react\";\nimport { CartContext } from \"../contexts\";\n\nexport function useCart() {\n const ctx = useContext(CartContext);\n if (!ctx) throw new Error(\"useCart must be used within NuMuProvider\");\n return ctx;\n}\n","import { useContext } from \"react\";\nimport { CustomerContext } from \"../contexts\";\nimport type { Customer } from \"../types/entities\";\n\nexport function useCustomer(): Customer | null {\n return useContext(CustomerContext);\n}\n","import { useContext } from \"react\";\nimport { ThemeSettingsContext } from \"../contexts\";\nimport type { ThemeSettingsV3 } from \"../types/theme\";\n\nexport function useThemeSettings(): ThemeSettingsV3 {\n const ctx = useContext(ThemeSettingsContext);\n if (!ctx) throw new Error(\"useThemeSettings must be used within NuMuProvider\");\n return ctx;\n}\n","\"use client\";\n\nimport { useContext } from \"react\";\nimport { CurrentTemplateContext } from \"../contexts\";\n\n/**\n * useCurrentTemplate — read the active page template's id.\n *\n * Values are the same strings used as keys in\n * `themeSettings.templates.<id>`:\n *\n * \"home\" | \"product\" | \"collection\" | \"cart\" | \"checkout\"\n * \"order-confirmation\" | \"profile\" | \"page\" | \"404\" | \"password\"\n *\n * Themes use this to render the matching section list:\n *\n * const template = useCurrentTemplate();\n * const settings = useThemeSettings();\n * const sections = settings.templates?.[template]?.sections ?? {};\n *\n * Default: \"home\" — when the host hasn't supplied a CurrentTemplate\n * provider, themes still render their home template instead of\n * crashing or showing a blank screen.\n *\n * The hook is read-only; the active template changes via the host\n * navigating between Next.js routes (each route's `page.tsx` wraps\n * its content with the correct currentTemplate at the\n * `<NuMuProvider currentTemplate=\"…\">` prop).\n */\nexport function useCurrentTemplate(): string {\n return useContext(CurrentTemplateContext);\n}\n","import { useContext } from \"react\";\nimport { PageContext } from \"../contexts\";\nimport type { Page } from \"../types/entities\";\n\nexport function usePage(): Page | null {\n return useContext(PageContext);\n}\n","import { createContext, useContext } from \"react\";\nimport type { SectionInstance } from \"../types/theme\";\n\nexport const SectionContext = createContext<SectionInstance | null>(null);\n\nexport function useSection(): SectionInstance {\n const ctx = useContext(SectionContext);\n if (!ctx) throw new Error(\"useSection must be used within a section component\");\n return ctx;\n}\n\nexport function useSectionOptional(): SectionInstance | null {\n return useContext(SectionContext);\n}\n","\"use client\";\n\nimport { useLocalization } from \"./useLocalization\";\nimport { useShop } from \"./useShop\";\n\n/**\n * useMoney — convenience hook that returns a stable formatter bound to\n * the active store's currency.\n *\n * Useful when a section needs to format multiple amounts in a render:\n *\n * const money = useMoney();\n * return <td>{money(item.price * item.quantity)}</td>\n *\n * For one-off price displays prefer the <Money> component which handles\n * compare-at and inline rendering.\n */\nexport function useMoney(currencyOverride?: string) {\n const { formatMoney } = useLocalization();\n const shop = useShop();\n const ccy = currencyOverride || shop?.currency;\n return (amount: number) => formatMoney(amount, ccy);\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\n\ninterface UseImageOptions {\n /** Sizes attribute (CSS sizes form). */\n sizes?: string;\n /** Widths to generate in srcSet. Falsy → use defaults. */\n widths?: number[];\n /** Pass-through alt text — useImage doesn't render anything; the\n * caller does. */\n alt?: string;\n}\n\ninterface ImageDescriptor {\n src: string | null;\n srcSet: string | null;\n sizes: string;\n alt: string;\n}\n\nconst DEFAULT_WIDTHS = [320, 480, 640, 768, 1024, 1280, 1600, 1920];\nconst DEFAULT_SIZES =\n \"(min-width: 1024px) 25vw, (min-width: 640px) 50vw, 100vw\";\n\n/**\n * useImage — returns srcSet/sizes for a CDN-served image so themes\n * don't have to hand-roll responsive image markup. Pairs with the\n * <Image> component, but is also useful when the theme wants to render\n * something other than a plain `<img>` (e.g., `<picture>` with art\n * direction or a CSS `background-image` via inline style).\n *\n * Returns `null` srcSet if the source URL already encodes a width\n * directive (theme author opted out of auto-sizing).\n */\nexport function useImage(\n src: string | null | undefined,\n opts: UseImageOptions = {},\n): ImageDescriptor {\n const { sizes = DEFAULT_SIZES, widths = DEFAULT_WIDTHS, alt = \"\" } = opts;\n return useMemo(() => {\n if (!src) return { src: null, srcSet: null, sizes, alt };\n if (/[?&]w=\\d+/.test(src)) return { src, srcSet: null, sizes, alt };\n const sep = src.includes(\"?\") ? \"&\" : \"?\";\n const srcSet = widths.map((w) => `${src}${sep}w=${w} ${w}w`).join(\", \");\n return { src, srcSet, sizes, alt };\n }, [src, sizes, widths, alt]);\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { usePage } from \"./usePage\";\nimport { useShop } from \"./useShop\";\nimport type { Product } from \"../types/entities\";\n\ninterface UseProductsOptions {\n /** Limit the slice returned. Defaults to whatever the host gave us. */\n limit?: number;\n /**\n * When true, fetch from `/api/products` if the host didn't provide a\n * list via PageContext. Useful for sections rendered on routes that\n * don't pre-fetch products (e.g. a custom CMS page that wants a\n * \"featured\" rail). Default: false — themes typically prefer SSR data.\n */\n fetchIfMissing?: boolean;\n}\n\ninterface UseProductsResult {\n products: Product[];\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * useProducts — read the storefront-pre-fetched product list from the\n * page context, optionally falling back to a client-side fetch.\n *\n * The SSR path passes `page.data.products: Product[]` from\n * `numu-storefront/src/app/[domain]/page.tsx`; sections on the home\n * route get them for free. For other routes that don't pre-fetch, set\n * `fetchIfMissing: true` and we'll hit `/api/products`.\n */\nexport function useProducts(\n opts: UseProductsOptions = {},\n): UseProductsResult {\n const { limit, fetchIfMissing = false } = opts;\n const page = usePage();\n const shop = useShop();\n const initial = (page?.data?.products as Product[] | undefined) ?? null;\n\n const [products, setProducts] = useState<Product[]>(initial ?? []);\n const [loading, setLoading] = useState<boolean>(\n initial == null && fetchIfMissing,\n );\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n if (initial != null) return;\n if (!fetchIfMissing) return;\n if (!shop?.id) return;\n let cancelled = false;\n (async () => {\n try {\n const params = new URLSearchParams({ store_id: shop.id });\n if (limit) params.set(\"limit\", String(limit));\n const res = await fetch(`/api/products?${params.toString()}`);\n if (!res.ok) throw new Error(`/api/products → ${res.status}`);\n const data = (await res.json()) as { products?: Product[] };\n if (cancelled) return;\n setProducts(data.products ?? []);\n setLoading(false);\n } catch (err) {\n if (cancelled) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [initial, fetchIfMissing, limit, shop?.id]);\n\n const sliced = limit != null ? products.slice(0, limit) : products;\n return { products: sliced, loading, error };\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { usePage } from \"./usePage\";\nimport { useShop } from \"./useShop\";\nimport type { Collection } from \"../types/entities\";\n\ninterface UseCollectionsOptions {\n limit?: number;\n fetchIfMissing?: boolean;\n}\n\ninterface UseCollectionsResult {\n collections: Collection[];\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * useCollections — analog to useProducts. Reads page.data.collections\n * pre-fetched by the storefront SSR; falls back to /api/collections\n * when fetchIfMissing is true.\n */\nexport function useCollections(\n opts: UseCollectionsOptions = {},\n): UseCollectionsResult {\n const { limit, fetchIfMissing = false } = opts;\n const page = usePage();\n const shop = useShop();\n const initial = (page?.data?.collections as Collection[] | undefined) ?? null;\n\n const [collections, setCollections] = useState<Collection[]>(initial ?? []);\n const [loading, setLoading] = useState<boolean>(\n initial == null && fetchIfMissing,\n );\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n if (initial != null) return;\n if (!fetchIfMissing) return;\n if (!shop?.id) return;\n let cancelled = false;\n (async () => {\n try {\n const params = new URLSearchParams({ store_id: shop.id });\n const res = await fetch(`/api/collections?${params.toString()}`);\n if (!res.ok) throw new Error(`/api/collections → ${res.status}`);\n const data = (await res.json()) as { collections?: Collection[] };\n if (cancelled) return;\n setCollections(data.collections ?? []);\n setLoading(false);\n } catch (err) {\n if (cancelled) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [initial, fetchIfMissing, shop?.id]);\n\n const sliced = limit != null ? collections.slice(0, limit) : collections;\n return { collections: sliced, loading, error };\n}\n","\"use client\";\n\nimport { createContext } from \"react\";\n\n/**\n * The action surface a theme can call to drive customer auth +\n * profile mutations. Each action returns the parsed response body\n * (or throws on network failure); the *result* of the operation is\n * conveyed by the response shape, not the throw boundary.\n *\n * The provider implements these by calling /api/customer/* proxy\n * routes on the storefront, which in turn forward to FastAPI's\n * /storefront/store/{store_id}/auth/* and /storefront/me/* endpoints.\n *\n * Why a separate context (vs bundling onto CustomerContext): the\n * value `Customer | null` was already in CustomerContext for\n * back-compat with themes that read `useCustomer()`. Adding a\n * sibling context for actions keeps the existing read hook stable\n * while letting themes opt into actions via `useCustomerActions()`.\n */\nexport interface CustomerActions {\n /** Email + password → returns { success, data?, error? }. On\n * success the SDK refreshes the customer context automatically. */\n login: (input: {\n email: string;\n password: string;\n }) => Promise<unknown>;\n\n /** Create a new customer + log them in. Some stores require\n * email verification before login is fully usable; this flow\n * still issues the auth cookie so the customer can verify from\n * the welcome email and land logged-in. */\n register: (input: {\n email: string;\n password: string;\n first_name?: string;\n last_name?: string;\n phone?: string;\n accepts_marketing?: boolean;\n }) => Promise<unknown>;\n\n /** Clear the customer_access_token cookie + refresh the context\n * to null. Idempotent: safe to call when not logged in. */\n logout: () => Promise<unknown>;\n\n /** Issue a password-reset email. Anti-enumeration: response\n * never reveals whether the email exists. */\n requestRecover: (input: { email: string }) => Promise<unknown>;\n\n /** Submit the new password with the token from the recovery email. */\n confirmReset: (input: {\n token: string;\n password: string;\n }) => Promise<unknown>;\n\n /** Verify the email with the token from the welcome email. */\n verifyEmail: (input: { token: string }) => Promise<unknown>;\n\n /** Resend the verification email. Server-side rate-limited to\n * prevent email-bombing. */\n resendVerification: (input: { email: string }) => Promise<unknown>;\n\n /** Update the customer's profile (name / phone / marketing). */\n updateProfile: (input: {\n first_name?: string;\n last_name?: string;\n phone?: string;\n accepts_marketing?: boolean;\n }) => Promise<unknown>;\n\n /** Change the customer's password from inside the dashboard.\n * Backend requires the current password as confirmation. */\n changePassword: (input: {\n current_password: string;\n new_password: string;\n }) => Promise<unknown>;\n\n /** Re-fetch the customer profile from the backend and replace\n * the context value. Themes call this after performing any\n * out-of-band mutation that changed the customer's record. */\n refresh: () => Promise<void>;\n}\n\nconst NOOP_ACTIONS: CustomerActions = {\n login: async () => ({}),\n register: async () => ({}),\n logout: async () => ({}),\n requestRecover: async () => ({}),\n confirmReset: async () => ({}),\n verifyEmail: async () => ({}),\n resendVerification: async () => ({}),\n updateProfile: async () => ({}),\n changePassword: async () => ({}),\n refresh: async () => undefined,\n};\n\nexport const CustomerActionsContext =\n createContext<CustomerActions>(NOOP_ACTIONS);\n","\"use client\";\n\nimport { useContext } from \"react\";\nimport { CustomerActionsContext, type CustomerActions } from \"../contexts/customer-actions\";\n\n/**\n * Returns the customer-mutation actions provided by NuMuProvider.\n *\n * Pair with `useCustomer()` for read access:\n *\n * const customer = useCustomer();\n * const { login, logout, register } = useCustomerActions();\n *\n * The actions hit the storefront's `/api/customer/*` proxies, which\n * own the cookie/CSRF/idempotency story. Themes don't talk to the\n * backend directly — they get a stable client-side surface here.\n */\nexport function useCustomerActions(): CustomerActions {\n return useContext(CustomerActionsContext);\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { useCustomer } from \"./useCustomer\";\n\n/**\n * Customer order history.\n *\n * `useOrders()` returns the logged-in customer's orders, paginated.\n * The hook is gated on `useCustomer()` — when null (anonymous\n * visitor), it returns an empty list without hitting the network.\n *\n * `useOrder(id)` fetches a single order. Backend rejects with 404\n * when the id doesn't belong to the customer regardless of whether\n * it exists for someone else (avoids enumeration).\n */\n\nexport interface OrderListEntry {\n id: string;\n order_number: string;\n status: string;\n payment_status: string;\n fulfillment_status: string;\n total: number;\n currency: string;\n created_at: string | null;\n item_count?: number;\n}\n\nexport interface OrderListState {\n orders: OrderListEntry[];\n loading: boolean;\n error: Error | null;\n refresh: () => void;\n}\n\nexport interface OrderDetail extends OrderListEntry {\n line_items: unknown[];\n shipping_address?: Record<string, unknown> | null;\n billing_address?: Record<string, unknown> | null;\n subtotal: number;\n shipping_cost: number;\n tax_amount: number;\n discount_amount: number;\n}\n\nexport interface OrderState {\n order: OrderDetail | null;\n loading: boolean;\n error: Error | null;\n refresh: () => void;\n}\n\nfunction unwrap(json: unknown): unknown {\n if (json && typeof json === \"object\" && \"data\" in json) {\n return (json as { data: unknown }).data;\n }\n return json;\n}\n\nexport function useOrders(): OrderListState {\n const customer = useCustomer();\n const [orders, setOrders] = useState<OrderListEntry[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [tick, setTick] = useState(0);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n if (!customer) {\n // Anonymous: nothing to fetch. Reset state so a logged-out\n // visitor doesn't see stale data carried over from a prior session.\n setOrders([]);\n setError(null);\n setLoading(false);\n return;\n }\n let cancelled = false;\n setLoading(true);\n setError(null);\n void (async () => {\n try {\n const res = await fetch(\"/api/customer/me/orders\", {\n method: \"GET\",\n credentials: \"include\",\n cache: \"no-store\",\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const body = unwrap(await res.json());\n if (cancelled) return;\n // Backend returns either a list directly or a paginated wrapper\n // `{ items, total, page, ... }`. Normalize to a list.\n const list = Array.isArray(body)\n ? body\n : Array.isArray((body as Record<string, unknown>)?.items)\n ? ((body as { items: OrderListEntry[] }).items)\n : [];\n setOrders(list as OrderListEntry[]);\n } catch (err) {\n if (cancelled) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [customer, tick]);\n\n return {\n orders,\n loading,\n error,\n refresh: () => setTick((t) => t + 1),\n };\n}\n\nexport function useOrder(id: string | null | undefined): OrderState {\n const customer = useCustomer();\n const [order, setOrder] = useState<OrderDetail | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [tick, setTick] = useState(0);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n if (!customer || !id) {\n setOrder(null);\n setError(null);\n setLoading(false);\n return;\n }\n let cancelled = false;\n setLoading(true);\n setError(null);\n void (async () => {\n try {\n const res = await fetch(\n `/api/customer/me/orders/${encodeURIComponent(id)}`,\n {\n method: \"GET\",\n credentials: \"include\",\n cache: \"no-store\",\n },\n );\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const body = unwrap(await res.json());\n if (cancelled) return;\n setOrder(body as OrderDetail);\n } catch (err) {\n if (cancelled) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [customer, id, tick]);\n\n return {\n order,\n loading,\n error,\n refresh: () => setTick((t) => t + 1),\n };\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useCustomer } from \"./useCustomer\";\n\n/**\n * Customer address book. Used by:\n * - The /account/addresses dashboard (list + CRUD).\n * - Checkout autofill (default address selected by default).\n *\n * Mutations return the updated row (or void on delete) and bump the\n * internal tick so the list reflects state changes immediately.\n * Anonymous visitors get an empty list with no network calls.\n */\n\nexport interface CustomerAddress {\n id: string;\n first_name?: string | null;\n last_name?: string | null;\n address_line1?: string | null;\n address_line2?: string | null;\n city?: string | null;\n state?: string | null;\n postal_code?: string | null;\n country?: string | null;\n phone?: string | null;\n label?: string | null;\n is_default?: boolean;\n // Optional geocoding fields — present when the merchant collects them.\n latitude?: number | null;\n longitude?: number | null;\n}\n\nexport type AddressInput = Omit<CustomerAddress, \"id\" | \"is_default\"> & {\n is_default?: boolean;\n};\n\nexport interface CustomerAddressesState {\n addresses: CustomerAddress[];\n loading: boolean;\n error: Error | null;\n refresh: () => void;\n addAddress: (input: AddressInput) => Promise<CustomerAddress | null>;\n updateAddress: (\n id: string,\n input: Partial<AddressInput>,\n ) => Promise<CustomerAddress | null>;\n deleteAddress: (id: string) => Promise<boolean>;\n setDefaultAddress: (id: string) => Promise<boolean>;\n}\n\nfunction unwrap(json: unknown): unknown {\n if (json && typeof json === \"object\" && \"data\" in json) {\n return (json as { data: unknown }).data;\n }\n return json;\n}\n\nasync function readBody(res: Response): Promise<unknown> {\n try {\n return unwrap(await res.json());\n } catch {\n return null;\n }\n}\n\nexport function useCustomerAddresses(): CustomerAddressesState {\n const customer = useCustomer();\n const [addresses, setAddresses] = useState<CustomerAddress[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [tick, setTick] = useState(0);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n if (!customer) {\n setAddresses([]);\n setLoading(false);\n setError(null);\n return;\n }\n let cancelled = false;\n setLoading(true);\n setError(null);\n void (async () => {\n try {\n const res = await fetch(\"/api/customer/me/addresses\", {\n method: \"GET\",\n credentials: \"include\",\n cache: \"no-store\",\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const body = await readBody(res);\n if (cancelled) return;\n const list = Array.isArray(body)\n ? body\n : Array.isArray((body as Record<string, unknown>)?.items)\n ? ((body as { items: CustomerAddress[] }).items)\n : [];\n setAddresses(list as CustomerAddress[]);\n } catch (err) {\n if (cancelled) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [customer, tick]);\n\n const refresh = useCallback(() => setTick((t) => t + 1), []);\n\n // CSRF: cart and customer mutations both echo the `numu_csrf` cookie\n // value as `x-numu-csrf` header. Read it from document.cookie just-\n // in-time so we always send the freshest value (the cookie may be\n // refreshed by /api/cart on first mount).\n function readCsrf(): string | null {\n if (typeof document === \"undefined\") return null;\n const m = document.cookie.match(/(?:^|; )numu_csrf=([^;]+)/);\n return m ? decodeURIComponent(m[1]) : null;\n }\n\n function mutationHeaders(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n const csrf = readCsrf();\n if (csrf) h[\"x-numu-csrf\"] = csrf;\n return h;\n }\n\n const addAddress = useCallback(\n async (input: AddressInput) => {\n const res = await fetch(\"/api/customer/me/addresses\", {\n method: \"POST\",\n credentials: \"include\",\n headers: mutationHeaders(),\n body: JSON.stringify(input),\n });\n if (!res.ok) return null;\n const created = (await readBody(res)) as CustomerAddress | null;\n refresh();\n return created;\n },\n [refresh],\n );\n\n const updateAddress = useCallback(\n async (id: string, input: Partial<AddressInput>) => {\n const res = await fetch(\n `/api/customer/me/addresses/${encodeURIComponent(id)}`,\n {\n method: \"PUT\",\n credentials: \"include\",\n headers: mutationHeaders(),\n body: JSON.stringify(input),\n },\n );\n if (!res.ok) return null;\n const updated = (await readBody(res)) as CustomerAddress | null;\n refresh();\n return updated;\n },\n [refresh],\n );\n\n const deleteAddress = useCallback(\n async (id: string) => {\n const res = await fetch(\n `/api/customer/me/addresses/${encodeURIComponent(id)}`,\n {\n method: \"DELETE\",\n credentials: \"include\",\n headers: mutationHeaders(),\n },\n );\n if (!res.ok) return false;\n refresh();\n return true;\n },\n [refresh],\n );\n\n const setDefaultAddress = useCallback(\n async (id: string) => {\n const res = await fetch(\n `/api/customer/me/addresses/${encodeURIComponent(id)}/default`,\n {\n method: \"PUT\",\n credentials: \"include\",\n headers: mutationHeaders(),\n },\n );\n if (!res.ok) return false;\n refresh();\n return true;\n },\n [refresh],\n );\n\n return {\n addresses,\n loading,\n error,\n refresh,\n addAddress,\n updateAddress,\n deleteAddress,\n setDefaultAddress,\n };\n}\n","\"use client\";\nimport { useContext, useEffect, useMemo, useState } from \"react\";\nimport {\n LocalizationContext,\n NavigationContext,\n type MenuItemData,\n} from \"../contexts\";\n\n/**\n * Menu item, modeled on Shopify's `linklists` entries.\n *\n * Themes typically render header/footer nav as a tree — we expose\n * `children` so a single fetch hydrates an arbitrary depth. Backends\n * that don't support nesting return a flat list (children=[]).\n */\nexport interface NavigationItem {\n id: string;\n title: string;\n /** The URL the menu item points to — relative path or absolute URL. */\n url: string;\n /** Optional foreign keys when the item references a typed resource. */\n resource_type?: \"product\" | \"collection\" | \"page\" | \"blog\" | \"article\" | \"url\" | null;\n resource_handle?: string | null;\n children: NavigationItem[];\n}\n\nexport interface NavigationState {\n /** Items in display order. Empty array when the menu is missing or still loading. */\n items: NavigationItem[];\n loading: boolean;\n /** Non-null when the fetch failed — the menu still resolves to []. */\n error: Error | null;\n}\n\nconst cache = new Map<string, NavigationItem[]>();\n\n/**\n * Resolve a bilingual label to a single display string for `locale`,\n * degrading gracefully: active locale → English → Arabic → first value.\n */\nfunction localizeLabel(\n label: Record<string, string> | undefined,\n locale: string,\n): string {\n if (!label) return \"\";\n return (\n label[locale] ||\n label.en ||\n label.ar ||\n Object.values(label).find((v) => !!v) ||\n \"\"\n );\n}\n\n/** Map the backend item `type` onto the SDK's `resource_type` union. */\nfunction mapResourceType(type?: string | null): NavigationItem[\"resource_type\"] {\n switch (type) {\n case \"product\":\n return \"product\";\n case \"collection\":\n return \"collection\";\n case \"page\":\n return \"page\";\n case \"blog\":\n return \"blog\";\n case \"article\":\n return \"article\";\n case \"http\":\n case \"url\":\n return \"url\";\n default:\n return null;\n }\n}\n\n/** Localize a raw (bilingual) menu item tree into display NavigationItems. */\nfunction toNavigationItem(raw: MenuItemData, locale: string): NavigationItem {\n return {\n id: raw.id,\n title: localizeLabel(raw.label, locale),\n url: raw.url || \"/\",\n resource_type: mapResourceType(raw.type),\n resource_handle: raw.resource_id ?? null,\n children: (raw.children ?? []).map((child) =>\n toNavigationItem(child, locale),\n ),\n };\n}\n\n/**\n * Fetch a merchant-managed nav menu by handle.\n *\n * Resolution order (Phase 2.4):\n * 1. Host-injected menus — the storefront resolves menus server-side\n * (`GET /storefront/store/{id}/menus`) and injects them via\n * `NuMuProvider`'s `navigation` prop → `NavigationContext`. When the\n * handle is present we localize + return it synchronously, no fetch.\n * A non-empty map that lacks the handle means \"no such menu\" → [].\n * 2. `options.initialItems` — a theme that pre-fetched its own list.\n * 3. Client fetch of `GET /api/storefront/navigation/{handle}` — the\n * legacy fallback for hosts that inject nothing. On 404 / network\n * error the hook resolves to [] (a missing menu is a soft failure;\n * the theme falls back to its own DEFAULT_NAV).\n */\nexport function useNavigation(\n handle: string,\n options?: { initialItems?: NavigationItem[] },\n): NavigationState {\n // NavigationContext defaults to {} outside a provider; LocalizationContext\n // is read defensively (no throw) so useNavigation works even if a theme\n // calls it above NuMuProvider in a test harness.\n const navMap = useContext(NavigationContext);\n const localization = useContext(LocalizationContext);\n const locale = localization?.locale ?? \"en\";\n\n const hostProvidedAny = !!navMap && Object.keys(navMap).length > 0;\n const rawItems = handle ? navMap?.[handle] : undefined;\n\n // Localized view of host-injected items. `null` means \"host wired no\n // navigation at all\" → fall through to initialItems / fetch. `[]` means\n // the host IS authoritative but this handle is absent/empty → render\n // nothing (no doomed fetch).\n const hostItems = useMemo<NavigationItem[] | null>(() => {\n if (rawItems) return rawItems.map((it) => toNavigationItem(it, locale));\n if (hostProvidedAny) return [];\n return null;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [rawItems, hostProvidedAny, locale]);\n\n const [items, setItems] = useState<NavigationItem[]>(\n hostItems ?? options?.initialItems ?? cache.get(handle) ?? [],\n );\n const [loading, setLoading] = useState(\n hostItems === null && !options?.initialItems && !cache.has(handle),\n );\n const [error, setError] = useState<Error | null>(null);\n\n // Keep items in sync with host-injected menus (locale switch, or the\n // map arriving after first paint). When the host is authoritative we\n // never fetch.\n useEffect(() => {\n if (hostItems === null) return;\n setItems(hostItems);\n setLoading(false);\n setError(null);\n }, [hostItems]);\n\n useEffect(() => {\n // Host-injected menus win — skip the network entirely.\n if (hostItems !== null) return;\n if (typeof window === \"undefined\") return;\n if (!handle) {\n setItems([]);\n setLoading(false);\n return;\n }\n if (cache.has(handle) && !options?.initialItems) {\n setItems(cache.get(handle) || []);\n setLoading(false);\n return;\n }\n let cancelled = false;\n setLoading(true);\n setError(null);\n void (async () => {\n try {\n const res = await fetch(\n `/api/storefront/navigation/${encodeURIComponent(handle)}`,\n { cache: \"no-store\" },\n );\n if (!res.ok) {\n // 404 = no such menu; render nothing instead of an error UI.\n if (cancelled) return;\n cache.set(handle, []);\n setItems([]);\n return;\n }\n const json = (await res.json()) as\n | { items?: NavigationItem[] }\n | NavigationItem[];\n const list: NavigationItem[] = Array.isArray(json)\n ? json\n : json.items || [];\n if (cancelled) return;\n cache.set(handle, list);\n setItems(list);\n } catch (err) {\n if (cancelled) return;\n // Non-OK / network failure → empty list + surface error so\n // themes can decide whether to log or show a fallback.\n setError(err instanceof Error ? err : new Error(String(err)));\n setItems([]);\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n // Deliberate: re-run when `handle` or host-injection state changes;\n // `initialItems` change shouldn't refetch (theme passes it once).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [handle, hostItems === null]);\n\n return { items, loading, error };\n}\n","\"use client\";\nimport { useEffect, useRef, useState } from \"react\";\nimport type { Product, Collection, Page } from \"../types/entities\";\n\n/**\n * Mixed-result search shape. The backend tsvector implementation lands in\n * Phase 4; until then this hook talks to /api/storefront/search and\n * gracefully degrades (empty results) when the endpoint isn't available.\n *\n * Two modes:\n * - \"predictive\" (default): debounced, capped at 5 per type, returns\n * fast for autocomplete dropdowns.\n * - \"full\": full result set with paging, used by /search pages.\n */\n\nexport interface SearchResults {\n products: Product[];\n collections: Collection[];\n pages: Page[];\n /** Articles will populate once the blog backend lands; field shape is\n * reserved here so themes can write code that doesn't break on\n * upgrade. */\n articles: Array<{ id: string; title: string; handle: string; excerpt?: string }>;\n total: number;\n}\n\nexport interface UseSearchOptions {\n /** \"predictive\" debounces and caps; \"full\" returns paged results. */\n mode?: \"predictive\" | \"full\";\n /** Restrict to specific result types. Default: all. */\n types?: Array<\"products\" | \"collections\" | \"pages\" | \"articles\">;\n /** Per-type cap. Predictive mode defaults to 5; full mode defaults to 24. */\n limit?: number;\n /** Debounce window in ms for predictive mode. Default 200. */\n debounceMs?: number;\n /** Skip the debounce (e.g. when the user submits the form). */\n immediate?: boolean;\n}\n\nexport interface SearchState {\n query: string;\n results: SearchResults;\n loading: boolean;\n error: Error | null;\n}\n\nconst EMPTY: SearchResults = {\n products: [],\n collections: [],\n pages: [],\n articles: [],\n total: 0,\n};\n\nexport function useSearch(\n query: string,\n options: UseSearchOptions = {},\n): SearchState {\n const {\n mode = \"predictive\",\n types,\n limit,\n debounceMs = 200,\n immediate = false,\n } = options;\n\n const [results, setResults] = useState<SearchResults>(EMPTY);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const lastRequestId = useRef(0);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const trimmed = query.trim();\n if (!trimmed) {\n setResults(EMPTY);\n setLoading(false);\n setError(null);\n return;\n }\n\n const requestId = ++lastRequestId.current;\n setLoading(true);\n setError(null);\n\n const run = async () => {\n try {\n const params = new URLSearchParams({ q: trimmed, mode });\n if (types?.length) params.set(\"types\", types.join(\",\"));\n if (limit) params.set(\"limit\", String(limit));\n const res = await fetch(`/api/storefront/search?${params}`, {\n cache: \"no-store\",\n });\n if (requestId !== lastRequestId.current) return; // superseded\n if (!res.ok) {\n // Backend search not yet wired (Phase 4). Empty result is\n // an acceptable degraded mode — themes show \"no results\"\n // instead of an error banner.\n setResults(EMPTY);\n return;\n }\n const json = (await res.json()) as Partial<SearchResults> & {\n data?: Partial<SearchResults>;\n };\n const body = json.data || json;\n if (requestId !== lastRequestId.current) return;\n setResults({\n products: body.products || [],\n collections: body.collections || [],\n pages: body.pages || [],\n articles: body.articles || [],\n total: body.total || 0,\n });\n } catch (err) {\n if (requestId !== lastRequestId.current) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setResults(EMPTY);\n } finally {\n if (requestId === lastRequestId.current) setLoading(false);\n }\n };\n\n if (immediate || mode === \"full\") {\n void run();\n return;\n }\n const t = setTimeout(run, debounceMs);\n return () => clearTimeout(t);\n }, [query, mode, debounceMs, immediate, limit, types?.join(\",\")]); // eslint-disable-line react-hooks/exhaustive-deps\n\n return { query, results, loading, error };\n}\n","\"use client\";\nimport { useCallback, useMemo } from \"react\";\n\n/**\n * Theme-facing analytics dispatcher.\n *\n * Two delivery channels, fired in parallel:\n * 1. Server-side track: POST /api/storefront/track with the event\n * payload. The host storefront proxies to FastAPI's funnel-event\n * endpoint (/storefront/store/{id}/track) and fans out to\n * merchant-configured pixels (GA4 Measurement Protocol, Meta CAPI,\n * TikTok Events API). Failed pixels never block the UI — we\n * don't await the response.\n * 2. Window CustomEvent (`numu:analytics:event`): so theme devs can\n * wire their own GTM container, third-party SDK, or in-house\n * pixel without going through the server. Detail shape mirrors\n * what gets POSTed.\n *\n * Standard event names (recommended for compatibility with GA4 / Meta):\n * page_view, view_item, view_collection, search, add_to_cart,\n * remove_from_cart, view_cart, begin_checkout, add_payment_info,\n * add_shipping_info, purchase, refund, sign_up, login,\n * add_to_wishlist, share. Custom names are also fine — the dispatcher\n * does not validate, so themes can ship store-specific events.\n *\n * Funnel-event mapping\n * --------------------\n * Standard event names that map to the backend's funnel steps are\n * dispatched with the full funnel-event payload shape (path,\n * session_fingerprint, attribution envelope from\n * window.__numu_attribution). This is what powers the merchant\n * funnel / journey / multi-touch attribution dashboards. Events with\n * no funnel mapping still POST with the loose `{event, payload}`\n * shape — the proxy forwards them so the pixel-fanout layer still\n * fires.\n */\n\nexport interface AnalyticsPayload {\n /** Standard or custom event name. Lowercase + underscores recommended. */\n [key: string]: unknown;\n}\n\nexport interface AnalyticsApi {\n /**\n * Fire an event. Non-blocking — both the fetch and the CustomEvent\n * dispatch happen in the next microtask; theme code shouldn't await.\n */\n track: (eventName: string, payload?: AnalyticsPayload) => void;\n}\n\n/**\n * Standard event name → backend funnel step mapping.\n *\n * Only events listed here drive the funnel / attribution dashboards.\n * Everything else still POSTs (for pixel fanout) but doesn't land in\n * the funnel_events table. The mapping mirrors what the bazaar\n * storefront's trackingService uses on the SaaS side.\n */\nconst EVENT_TO_FUNNEL_STEP: Record<string, string> = {\n page_view: \"page_view\",\n view_item: \"product_view\",\n view_collection: \"page_view\",\n add_to_cart: \"add_to_cart\",\n begin_checkout: \"checkout_started\",\n purchase: \"order_completed\",\n // Wave 2+ standard Meta events — backend's FUNNEL_STEP_TO_META_EVENT\n // table accepts these as funnel steps directly.\n search: \"search\",\n lead: \"lead\",\n sign_up: \"complete_registration\",\n add_to_wishlist: \"add_to_wishlist\",\n add_payment_info: \"add_payment_info\",\n};\n\ninterface AttributionEnvelope {\n v?: number;\n first_touch?: unknown;\n last_touch?: unknown;\n session_id?: string | null;\n}\n\ninterface NumuAttributionBridge {\n get(): AttributionEnvelope | null;\n}\n\ninterface NumuCustomerBridge {\n /** Authenticated customer's UUID, or null when the visitor is a guest. */\n getId(): string | null;\n}\n\ndeclare global {\n interface Window {\n __numu_attribution?: NumuAttributionBridge;\n /**\n * Optional bridge installed by the host storefront's customer\n * provider. When set, the SDK includes ``customer_id`` on\n * funnel-step events so the backend can record touches against\n * the authenticated customer immediately instead of waiting for\n * the next checkout to backfill.\n */\n __numu_customer?: NumuCustomerBridge;\n }\n}\n\nfunction readAttribution(): AttributionEnvelope | null {\n if (typeof window === \"undefined\") return null;\n try {\n return window.__numu_attribution?.get?.() ?? null;\n } catch {\n return null;\n }\n}\n\nfunction readCustomerId(): string | null {\n if (typeof window === \"undefined\") return null;\n try {\n return window.__numu_customer?.getId?.() ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Session fingerprint for funnel-event dedup.\n *\n * The attribution envelope's session_id (ULID, stable for cookie\n * lifetime) is the natural fingerprint — same cookie lifetime as the\n * attribution window, so funnel + journey + multi-touch all agree on\n * what \"one session\" means.\n *\n * Fallback: a per-tab random string when no envelope exists yet (first\n * visit before AttributionProvider's effect has run). Persisted on the\n * window so subsequent calls in the same tab reuse it — otherwise\n * each event would generate its own fingerprint and the funnel\n * dashboard would over-count distinct sessions.\n */\nfunction getFingerprint(): string {\n if (typeof window === \"undefined\") return \"ssr\";\n const env = readAttribution();\n if (env?.session_id) return env.session_id;\n\n const w = window as unknown as { __numu_session_fp?: string };\n if (w.__numu_session_fp) return w.__numu_session_fp;\n // crypto.randomUUID is universally available in our supported\n // browsers (no IE / pre-2022 mobile Safari). Skip the fallback.\n const fp = crypto.randomUUID();\n w.__numu_session_fp = fp;\n return fp;\n}\n\n/**\n * Free function body of the hook's `track`.\n *\n * Extracted so unit tests can call it directly without spinning up a\n * React renderer for what is essentially a side-effect dispatcher.\n * The exported `useAnalytics` hook is a thin memoization wrapper.\n */\nexport function dispatchAnalyticsEvent(\n eventName: string,\n payload: AnalyticsPayload = {},\n): void {\n if (typeof window === \"undefined\") return;\n\n // 1. Window CustomEvent — synchronous, cheap. Themes that wire\n // their own pixels listen here.\n try {\n window.dispatchEvent(\n new CustomEvent(\"numu:analytics:event\", {\n detail: { event: eventName, payload, ts: Date.now() },\n }),\n );\n } catch {\n /* CustomEvent unsupported — no DOM event polyfill needed today. */\n }\n\n // 2. Server-side fanout. Funnel-step events get the strict payload\n // shape the backend's funnel_events table expects (path,\n // fingerprint, step, step_data, attribution). Non-funnel events\n // keep the loose shape for the pixel-fanout layer.\n const step = EVENT_TO_FUNNEL_STEP[eventName] ?? null;\n // Lifting customer_id once so we don't read the bridge twice per\n // dispatch. Absent (null) for guests / unauthenticated visitors;\n // present for logged-in customers whose journey rows should land\n // with customer_id set immediately instead of waiting for the\n // next checkout to backfill.\n const customerId = readCustomerId();\n const body: Record<string, unknown> = step\n ? {\n event_id: crypto.randomUUID(),\n path: window.location.pathname,\n fingerprint: getFingerprint(),\n step,\n step_data: payload,\n referrer:\n typeof document !== \"undefined\" && document.referrer\n ? document.referrer\n : undefined,\n attribution: readAttribution() ?? undefined,\n customer_id: customerId ?? undefined,\n }\n : {\n event: eventName,\n payload,\n ts: Date.now(),\n attribution: readAttribution() ?? undefined,\n customer_id: customerId ?? undefined,\n };\n\n void (async () => {\n try {\n await fetch(\"/api/storefront/track\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n keepalive: true, // survive page-unload (e.g. begin_checkout → redirect)\n });\n } catch {\n /* swallowed by design */\n }\n })();\n}\n\nexport function useAnalytics(): AnalyticsApi {\n const track = useCallback(\n (eventName: string, payload: AnalyticsPayload = {}) => {\n dispatchAnalyticsEvent(eventName, payload);\n },\n [],\n );\n\n return useMemo(() => ({ track }), [track]);\n}\n","\"use client\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useShop } from \"./useShop\";\n\n/**\n * Read app-provided data + manifest for a slug installed on the\n * current store.\n *\n * Phase 6 wired this to the real backend at\n * `/api/storefront/store/{store_id}/apps/{slug}`. Theme usage:\n *\n * const recommend = useApp<RecommendationData>(\"recommendation-engine\");\n * if (!recommend.available) return <Fallback />;\n * if (recommend.loading) return <Skeleton />;\n * return <RecommendList items={recommend.data?.products ?? []} />;\n *\n * `available` flips to true only when an enabled installation exists\n * for the store. Apps the merchant hasn't installed surface as\n * `{ available: false }` rather than as a network error — themes\n * branch on availability without try/catch.\n *\n * The hook revalidates whenever the slug changes, but does NOT refetch\n * on focus / interval — app data is usually slow-changing (config +\n * manifest). Themes that need live data should layer their own\n * refresh on top of the returned `refresh()` callback.\n */\n\nexport interface AppManifestBlock {\n type: string;\n name: string;\n block_schema: Record<string, unknown>;\n}\n\nexport interface AppPayload<T = unknown> {\n slug: string;\n name: string;\n description: string | null;\n icon_url: string | null;\n version: string;\n manifest: Record<string, unknown>;\n settings: Record<string, unknown>;\n blocks: AppManifestBlock[];\n /** App-provided data (shape defined by the app developer). Today\n * the response always returns null for `data` — apps emit data via\n * their `endpoints.data` URL, which the theme fetches separately.\n * Surfaced here so the field is stable when v2 lands the proxy. */\n data: T | null;\n}\n\nexport interface AppState<T = unknown> {\n data: AppPayload<T> | null;\n loading: boolean;\n available: boolean;\n error: Error | null;\n /** Re-fetch the install. Returns a promise that resolves when the\n * request settles (regardless of success). */\n refresh: () => Promise<void>;\n}\n\nexport function useApp<T = unknown>(slug: string): AppState<T> {\n const shop = useShop();\n const [state, setState] = useState<{\n data: AppPayload<T> | null;\n loading: boolean;\n available: boolean;\n error: Error | null;\n }>({ data: null, loading: true, available: false, error: null });\n\n const fetchApp = useCallback(async (): Promise<void> => {\n if (!slug) {\n setState({ data: null, loading: false, available: false, error: null });\n return;\n }\n setState((s) => ({ ...s, loading: true, error: null }));\n try {\n const url = `/api/storefront/apps/${encodeURIComponent(slug)}`;\n const res = await fetch(url, {\n credentials: \"include\",\n headers: { Accept: \"application/json\" },\n });\n if (res.status === 404) {\n // Not installed (or app disabled). Standard not-available\n // shape — keeps theme branching simple.\n setState({\n data: null,\n loading: false,\n available: false,\n error: null,\n });\n return;\n }\n if (!res.ok) {\n throw new Error(`useApp(${slug}) failed: HTTP ${res.status}`);\n }\n const body = (await res.json()) as {\n data?: AppPayload<T> & { available?: boolean };\n };\n const payload = body.data;\n if (!payload) {\n setState({\n data: null,\n loading: false,\n available: false,\n error: null,\n });\n return;\n }\n setState({\n data: payload as AppPayload<T>,\n loading: false,\n available: payload.available !== false,\n error: null,\n });\n } catch (e) {\n setState({\n data: null,\n loading: false,\n available: false,\n error: e instanceof Error ? e : new Error(String(e)),\n });\n }\n }, [slug, shop.id]);\n\n useEffect(() => {\n void fetchApp();\n }, [fetchApp]);\n\n return { ...state, refresh: fetchApp };\n}\n","\"use client\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useCustomer } from \"./useCustomer\";\n\n/**\n * Wishlist hook with localStorage fallback.\n *\n * Architecture (Phase 4 lands the server side):\n * - Authenticated customer: persists to /api/customer/me/wishlist\n * (server-backed, syncs across devices).\n * - Anonymous visitor: persists to localStorage under\n * `numu_wishlist_<store_id>`. On login, the wishlist merges into\n * the server-side list (mirrors the cart's session→customer flow).\n *\n * v1 implementation: localStorage only. The /api/customer/me/wishlist\n * endpoint isn't wired yet; an authed visitor still gets the local\n * fallback so themes work end-to-end. When the endpoint lands, the\n * mutation methods will short-circuit to the server fetch and the\n * effect below will drop the localStorage path for authed users.\n */\n\nexport interface WishlistItem {\n product_id: string;\n /** Optional variant scoping — themes that show variant pickers can\n * wishlist a specific size/color combo separately. */\n variant_id?: string | null;\n /** Server timestamp once persistence lands; ms-since-epoch in v1. */\n added_at: number;\n}\n\nexport interface WishlistState {\n items: WishlistItem[];\n loading: boolean;\n has: (productId: string, variantId?: string | null) => boolean;\n addToWishlist: (productId: string, variantId?: string | null) => void;\n removeFromWishlist: (productId: string, variantId?: string | null) => void;\n clear: () => void;\n}\n\nfunction storageKey(storeId: string): string {\n return `numu_wishlist_${storeId}`;\n}\n\nfunction readLocal(storeId: string): WishlistItem[] {\n if (typeof window === \"undefined\") return [];\n try {\n const raw = window.localStorage.getItem(storageKey(storeId));\n if (!raw) return [];\n const parsed = JSON.parse(raw);\n return Array.isArray(parsed) ? (parsed as WishlistItem[]) : [];\n } catch {\n return [];\n }\n}\n\nfunction writeLocal(storeId: string, items: WishlistItem[]): void {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(storageKey(storeId), JSON.stringify(items));\n } catch {\n /* quota / private mode — wishlist degrades to in-memory for the session */\n }\n}\n\nfunction sameItem(\n a: WishlistItem,\n productId: string,\n variantId?: string | null,\n): boolean {\n return (\n a.product_id === productId && (a.variant_id ?? null) === (variantId ?? null)\n );\n}\n\n/**\n * @param storeId The store the wishlist is scoped to. Pass `useShop().id`.\n * Without it, the hook can't keep one merchant's wishlist\n * from leaking into another's localStorage on a shared\n * domain (e.g. apex preview).\n */\nexport function useWishlist(storeId: string): WishlistState {\n const customer = useCustomer();\n const [items, setItems] = useState<WishlistItem[]>([]);\n const [loading, setLoading] = useState(true);\n\n // Hydrate from localStorage on mount. When the server-side endpoint\n // lands, an authed customer will fetch from there instead.\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n setItems(readLocal(storeId));\n setLoading(false);\n }, [storeId, customer?.id]);\n\n const has = useCallback(\n (productId: string, variantId?: string | null) =>\n items.some((it) => sameItem(it, productId, variantId)),\n [items],\n );\n\n const addToWishlist = useCallback(\n (productId: string, variantId?: string | null) => {\n setItems((prev) => {\n if (prev.some((it) => sameItem(it, productId, variantId))) {\n return prev;\n }\n const next: WishlistItem[] = [\n ...prev,\n {\n product_id: productId,\n variant_id: variantId ?? null,\n added_at: Date.now(),\n },\n ];\n writeLocal(storeId, next);\n return next;\n });\n },\n [storeId],\n );\n\n const removeFromWishlist = useCallback(\n (productId: string, variantId?: string | null) => {\n setItems((prev) => {\n const next = prev.filter((it) => !sameItem(it, productId, variantId));\n writeLocal(storeId, next);\n return next;\n });\n },\n [storeId],\n );\n\n const clear = useCallback(() => {\n setItems([]);\n writeLocal(storeId, []);\n }, [storeId]);\n\n return { items, loading, has, addToWishlist, removeFromWishlist, clear };\n}\n","\"use client\";\nimport { useEffect, useState } from \"react\";\nimport type { Product } from \"../types/entities\";\n\n/**\n * Fetch products related to the given product (same category, excluding\n * self). Phase 3 lands collaborative-filtering / \"frequently bought\n * together\"; v1 ships the simpler same-category-minus-self heuristic.\n *\n * Backend contract: GET /api/storefront/products/{id}/related?limit=N\n * → { items: Product[] } | Product[]\n *\n * Returns an empty list (no error) when the endpoint is missing or the\n * product has no siblings — themes should branch on `items.length` and\n * either render the section or skip it entirely.\n */\n\nexport interface RelatedProductsState {\n items: Product[];\n loading: boolean;\n error: Error | null;\n}\n\nexport function useRelatedProducts(\n productId: string | null | undefined,\n options: { limit?: number } = {},\n): RelatedProductsState {\n const limit = options.limit ?? 4;\n const [items, setItems] = useState<Product[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n if (!productId) {\n setItems([]);\n setLoading(false);\n setError(null);\n return;\n }\n let cancelled = false;\n setLoading(true);\n setError(null);\n void (async () => {\n try {\n const res = await fetch(\n `/api/storefront/products/${encodeURIComponent(productId)}/related?limit=${limit}`,\n { cache: \"no-store\" },\n );\n if (!res.ok) {\n // Endpoint not yet wired — don't surface an error; themes\n // should treat this as \"no related items available\" and\n // skip the section.\n if (cancelled) return;\n setItems([]);\n return;\n }\n const json = (await res.json()) as\n | { items?: Product[]; data?: Product[] }\n | Product[];\n const list: Product[] = Array.isArray(json)\n ? json\n : Array.isArray(json.data)\n ? json.data\n : Array.isArray(json.items)\n ? json.items\n : [];\n if (cancelled) return;\n setItems(list);\n } catch (err) {\n if (cancelled) return;\n setError(err instanceof Error ? err : new Error(String(err)));\n setItems([]);\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [productId, limit]);\n\n return { items, loading, error };\n}\n","\"use client\";\nimport { useMemo } from \"react\";\nimport type { Product, Store, SizeChart } from \"../types/entities\";\nimport { useProductOptional } from \"./useProduct\";\nimport { useShop } from \"./useShop\";\n\n/**\n * useProductSizeChart — resolve the size chart to show for a product.\n *\n * The merchant hub writes the per-product chart to\n * `product.attributes.size_chart` and the store-wide default to\n * `store.settings.size_chart`, with an explicit `mode`:\n *\n * \"off\" → never show, even if a store default exists\n * \"custom\" → use the product's own chart\n * \"default\" → fall back to the store-wide chart\n * (legacy) → no `mode`: a populated product chart wins, else the default\n *\n * This hook centralises that precedence so every theme resolves it identically\n * (the backend `SizeChartSchema` validator and the hub editor share the same\n * shape). Returns `null` when there is nothing to show — render the size-guide\n * trigger only when this is non-null.\n *\n * @param productOverride - resolve against this product instead of the one in\n * context (e.g. when rendering a chart for a related/quick-view product).\n */\nexport function useProductSizeChart(\n productOverride?: Product | null,\n): SizeChart | null {\n const ctxProduct = useProductOptional();\n const product = productOverride ?? ctxProduct;\n const shop = useShop() as Store | undefined;\n const storeSettings = shop?.settings;\n\n return useMemo(\n () => resolveSizeChart(product?.attributes, storeSettings),\n [product?.attributes, storeSettings],\n );\n}\n\nfunction hasRows(c: unknown): c is SizeChart {\n return (\n !!c &&\n typeof c === \"object\" &&\n Array.isArray((c as SizeChart).rows) &&\n (c as SizeChart).rows.length > 0\n );\n}\n\n/**\n * Pure resolver (no React) — exported so non-hook code (SSR helpers, tests)\n * can apply the same precedence.\n */\nexport function resolveSizeChart(\n productAttributes: Record<string, unknown> | undefined,\n storeSettings: Record<string, unknown> | undefined,\n): SizeChart | null {\n const product = productAttributes?.size_chart as SizeChart | undefined;\n const storeDefault = storeSettings?.size_chart as SizeChart | undefined;\n\n if (product?.mode === \"off\") return null;\n if (product?.mode === \"custom\") return hasRows(product) ? product : null;\n if (product?.mode === \"default\") return hasRows(storeDefault) ? storeDefault : null;\n\n // No explicit mode (legacy): a populated product chart wins, else the default.\n if (hasRows(product)) return product;\n if (hasRows(storeDefault)) return storeDefault;\n return null;\n}\n","\"use client\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useShop } from \"./useShop\";\n\n/**\n * Multi-currency presentment — Phase 6.\n *\n * The store's *capture* currency (what Paymob/Stripe/etc. charges)\n * never changes mid-session. This hook is purely about **display**:\n * letting visitors browse prices in a currency they recognize.\n *\n * Usage:\n *\n * const { base, selected, presentment, convert, setSelected } = useCurrency();\n * <p>{convert(product.price.amount_cents)} {selected}</p>\n * {presentment.length > 1 && (\n * <select value={selected} onChange={(e) => setSelected(e.target.value)}>\n * {presentment.map(c => <option key={c}>{c}</option>)}\n * </select>\n * )}\n *\n * Behavior:\n * - `selected` defaults to the persisted `numu_currency` cookie if\n * valid, else `default_presentment`, else `base`.\n * - `setSelected` writes the cookie (path=/, 30d) so navigation\n * preserves the choice across pages.\n * - `convert(cents)` returns the converted cents in `selected`,\n * using the rates from the API. When no rate exists, returns\n * the input unchanged (theme renders in base — better than a\n * wrong number).\n *\n * Use `<CurrencySwitcher>` from the SDK for an opinionated UI, or\n * read this hook directly for full control.\n */\n\nexport interface CurrencyConfig {\n base: string;\n default_presentment: string;\n presentment: string[];\n rates: Record<string, string>; // Decimal-as-string\n auto_convert: boolean;\n}\n\nexport interface CurrencyState {\n base: string;\n selected: string;\n presentment: string[];\n rates: Record<string, number>;\n autoConvert: boolean;\n loading: boolean;\n setSelected: (currency: string) => void;\n convert: (cents: number, target?: string) => number;\n}\n\nconst COOKIE_NAME = \"numu_currency\";\nconst COOKIE_MAX_AGE = 60 * 60 * 24 * 30; // 30 days\n\nfunction readCookie(name: string): string | null {\n if (typeof document === \"undefined\") return null;\n const match = document.cookie.match(\n new RegExp(`(?:^|;\\\\s*)${name}=([^;]+)`),\n );\n return match ? decodeURIComponent(match[1]) : null;\n}\n\nfunction writeCookie(name: string, value: string): void {\n if (typeof document === \"undefined\") return;\n document.cookie = `${name}=${encodeURIComponent(value)}; path=/; max-age=${COOKIE_MAX_AGE}; SameSite=Lax`;\n}\n\nexport function useCurrency(): CurrencyState {\n const shop = useShop();\n const [config, setConfig] = useState<CurrencyConfig | null>(null);\n const [loading, setLoading] = useState(true);\n const [selected, setSelectedState] = useState<string>(\"\");\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n try {\n const res = await fetch(`/api/storefront/currencies`, {\n credentials: \"include\",\n headers: { Accept: \"application/json\" },\n });\n if (!res.ok) throw new Error(`currencies: HTTP ${res.status}`);\n const body = (await res.json()) as { data: CurrencyConfig };\n if (cancelled) return;\n setConfig(body.data);\n // Resolve the initial selection: cookie → default → base.\n // Validate against the presentment list so a stale cookie\n // doesn't lock the visitor onto a currency the merchant\n // removed.\n const cookie = readCookie(COOKIE_NAME);\n const valid =\n cookie && body.data.presentment.includes(cookie) ? cookie : null;\n setSelectedState(valid || body.data.default_presentment || body.data.base);\n } catch {\n if (cancelled) return;\n setConfig(null);\n setSelectedState(shop.currency || \"EGP\");\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [shop.id, shop.currency]);\n\n const rates = useMemo<Record<string, number>>(() => {\n const out: Record<string, number> = {};\n if (!config) return out;\n for (const [k, v] of Object.entries(config.rates)) {\n const n = Number.parseFloat(v);\n if (Number.isFinite(n)) out[k] = n;\n }\n return out;\n }, [config]);\n\n const convert = useCallback(\n (cents: number, target?: string): number => {\n if (!config) return cents;\n const to = target || selected;\n if (!to || to === config.base) return cents;\n const rate = rates[to];\n if (!rate || !Number.isFinite(rate)) return cents;\n return Math.round(cents * rate);\n },\n [config, rates, selected],\n );\n\n const setSelected = useCallback((currency: string) => {\n setSelectedState(currency);\n writeCookie(COOKIE_NAME, currency);\n }, []);\n\n return {\n base: config?.base || shop.currency || \"EGP\",\n selected: selected || config?.base || shop.currency || \"EGP\",\n presentment: config?.presentment || [shop.currency || \"EGP\"],\n rates,\n autoConvert: Boolean(config?.auto_convert),\n loading,\n setSelected,\n convert,\n };\n}\n","/**\n * Variant resolution helpers — Phase 8.1.\n *\n * Themes render a variant picker (Size + Color radios), then ask the\n * SDK \"given my current selection, which variant is it?\" The matching\n * variant's id is what add-to-cart sends.\n */\n\nimport type { Product, ProductVariant } from \"../types/entities\";\n\n/**\n * Pick the variant that exactly matches the given option_values map.\n * Returns null when no variant matches — themes render that as\n * \"Combination unavailable\" or a disabled buy button.\n */\nexport function findVariantByOptions(\n product: Pick<Product, \"variants\">,\n selection: Record<string, string>,\n): ProductVariant | null {\n const variants = product.variants || [];\n if (variants.length === 0) return null;\n // Single-variant products (no axes): the only variant matches the\n // empty selection trivially.\n if (variants.length === 1 && Object.keys(selection).length === 0) {\n return variants[0];\n }\n for (const v of variants) {\n const opts = v.option_values || v.options || {};\n const matches = Object.entries(selection).every(\n ([axis, value]) => opts[axis] === value,\n );\n if (matches && Object.keys(selection).length === Object.keys(opts).length) {\n return v;\n }\n }\n return null;\n}\n\n/**\n * Find the \"default\" variant — the one the PDP should auto-select on\n * first render. Prefers the first in-stock variant; falls back to the\n * first variant if all are out of stock (so the picker still shows\n * something coherent).\n */\nexport function defaultVariant(product: Pick<Product, \"variants\">): ProductVariant | null {\n const variants = product.variants || [];\n if (variants.length === 0) return null;\n const inStock = variants.find((v) => v.is_in_stock || v.in_stock);\n return inStock || variants[0];\n}\n\n/**\n * Given a partial selection (e.g. just Size=M, no Color yet), return\n * the set of values still available on each unselected axis. Themes\n * use this to disable swatches whose paired variants are all out of\n * stock for the current selection.\n */\nexport function availableValues(\n product: Pick<Product, \"options\" | \"variants\">,\n selection: Record<string, string>,\n): Record<string, Set<string>> {\n const axes = product.options || [];\n const variants = product.variants || [];\n const out: Record<string, Set<string>> = {};\n for (const axis of axes) {\n out[axis.name] = new Set();\n for (const v of variants) {\n const opts = v.option_values || v.options || {};\n // Only consider variants compatible with the locked-in part of\n // the selection (every locked axis must match this variant).\n const compatible = Object.entries(selection).every(\n ([k, val]) => k === axis.name || opts[k] === val,\n );\n if (compatible && opts[axis.name]) {\n out[axis.name].add(opts[axis.name]);\n }\n }\n }\n return out;\n}\n","\"use client\";\n\nimport { useCallback, useMemo, useState } from \"react\";\nimport {\n availableValues,\n defaultVariant,\n findVariantByOptions,\n} from \"../utils/variants\";\nimport type { Product, ProductVariant } from \"../types/entities\";\n\nexport interface UseVariantSelection {\n /** Currently-selected axis → value map. */\n selection: Record<string, string>;\n /** The variant matching the current selection, if any. */\n variant: ProductVariant | null;\n /** Pick a value on one axis. Other axes stay locked. */\n select: (axis: string, value: string) => void;\n /** Reset the selection (e.g. on \"Choose another\" button). */\n reset: () => void;\n /**\n * For each unselected axis, the set of values that lead to at\n * least one in-stock variant given the current locked axes.\n * Themes use this to grey out swatches.\n */\n availability: Record<string, Set<string>>;\n /**\n * True when every option axis on the product has a chosen value\n * and `variant` is resolved. Buy buttons should disable until\n * this flips to true on products with options.\n */\n isComplete: boolean;\n}\n\n/**\n * Hook that owns variant-axis selection state for a PDP.\n *\n * Initial state auto-selects the default variant's axis values so\n * the PDP loads with a coherent price + image + buy state, matching\n * Shopify's behavior. Themes that prefer \"Choose your size\" empty\n * state can pass `autoSelect: false`.\n */\nexport function useVariantSelection(\n product: Pick<Product, \"options\" | \"variants\">,\n opts: { autoSelect?: boolean } = {},\n): UseVariantSelection {\n const autoSelect = opts.autoSelect ?? true;\n\n const initial = useMemo<Record<string, string>>(() => {\n if (!autoSelect) return {};\n const dv = defaultVariant(product);\n if (!dv) return {};\n const opts = dv.option_values || dv.options || {};\n return { ...opts };\n }, [product, autoSelect]);\n\n const [selection, setSelection] = useState<Record<string, string>>(initial);\n\n const select = useCallback((axis: string, value: string) => {\n setSelection((prev) => ({ ...prev, [axis]: value }));\n }, []);\n\n const reset = useCallback(() => setSelection({}), []);\n\n const variant = useMemo(\n () => findVariantByOptions(product, selection),\n [product, selection],\n );\n\n const availability = useMemo(\n () => availableValues(product, selection),\n [product, selection],\n );\n\n const isComplete = useMemo(() => {\n const axes = product.options || [];\n if (axes.length === 0) return true;\n return axes.every((a) => Boolean(selection[a.name]));\n }, [product, selection]);\n\n return { selection, variant, select, reset, availability, isComplete };\n}\n","\"use client\";\n\nimport { useCallback, useState } from \"react\";\n\n/**\n * Gift card balance check — Phase 8.3.\n *\n * Themes call this from the checkout payment step to validate a\n * customer-typed code before sending it as part of the checkout\n * payload. The backend returns 404 for any non-redeemable card\n * (expired, depleted, voided, or wrong store) — the response shape\n * stays uniform so the hook can't be used to probe for valid codes.\n *\n * Backend contract (via storefront proxy):\n * GET /api/gift-cards/{code}\n * → 200 { data: { last_four, current_balance_cents, currency,\n * expires_at? } }\n * → 404 { error: { code, message } }\n */\n\nexport interface GiftCardBalance {\n last_four: string;\n current_balance_cents: number;\n currency: string;\n expires_at: string | null;\n}\n\nexport interface UseGiftCardBalance {\n /** Last lookup result, or null when nothing checked yet / failed. */\n balance: GiftCardBalance | null;\n /** True while a lookup is in flight. */\n loading: boolean;\n /** Latest error from the lookup, if any. Cleared on next check. */\n error: Error | null;\n /** Trigger a balance check. Returns the result or null on failure. */\n check: (code: string) => Promise<GiftCardBalance | null>;\n /** Clear the last result + error (e.g. when the user clears the input). */\n reset: () => void;\n}\n\nexport function useGiftCardBalance(): UseGiftCardBalance {\n const [balance, setBalance] = useState<GiftCardBalance | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const check = useCallback(async (code: string): Promise<GiftCardBalance | null> => {\n if (typeof window === \"undefined\") return null;\n const trimmed = (code || \"\").trim();\n if (!trimmed) {\n setError(new Error(\"Enter a gift card code.\"));\n setBalance(null);\n return null;\n }\n setLoading(true);\n setError(null);\n try {\n const res = await fetch(\n `/api/gift-cards/${encodeURIComponent(trimmed)}`,\n { cache: \"no-store\" },\n );\n if (!res.ok) {\n setBalance(null);\n // 404 = invalid/redeemed/expired — surface a friendly message\n // rather than the raw API code so themes don't need to map it.\n if (res.status === 404) {\n setError(new Error(\"That gift card isn't valid or has been used up.\"));\n return null;\n }\n setError(new Error(`Couldn't check gift card (HTTP ${res.status}).`));\n return null;\n }\n const json = (await res.json()) as { data?: GiftCardBalance };\n const data = json?.data;\n if (!data) {\n setBalance(null);\n setError(new Error(\"Unexpected response from server.\"));\n return null;\n }\n setBalance(data);\n return data;\n } catch (err) {\n setBalance(null);\n setError(err instanceof Error ? err : new Error(String(err)));\n return null;\n } finally {\n setLoading(false);\n }\n }, []);\n\n const reset = useCallback(() => {\n setBalance(null);\n setError(null);\n }, []);\n\n return { balance, loading, error, check, reset };\n}\n","\"use client\";\n\nimport { useCallback, useState } from \"react\";\n\n/**\n * Reorder / \"buy again\" — Phase 8.5.\n *\n * Clones every line item from an existing order into the current cart.\n * The backend skips lines whose product is deleted/archived, whose\n * variant is gone, or that are out of stock — returning per-line\n * reasons so themes can show a \"couldn't add X items\" banner.\n *\n * Backend contract:\n * POST /storefront/me/orders/{order_id}/reorder\n * → 200 { data: { added_count, skipped[], cart_total_items } }\n * → 404 if order doesn't belong to the current customer\n */\n\nexport type ReorderSkipReason =\n | \"product_deleted\"\n | \"product_archived\"\n | \"out_of_stock\"\n | \"variant_unavailable\";\n\nexport interface ReorderSkippedItem {\n product_id: string;\n variant_id: string | null;\n quantity: number;\n reason: ReorderSkipReason | string;\n}\n\nexport interface ReorderResult {\n added_count: number;\n skipped: ReorderSkippedItem[];\n cart_total_items: number;\n}\n\nexport interface UseReorder {\n /** Last reorder result. */\n result: ReorderResult | null;\n /** True while a reorder is in flight. */\n loading: boolean;\n /** Latest error, cleared on next reorder call. */\n error: Error | null;\n /** Trigger the reorder. Returns the result or null on failure. */\n reorder: (orderId: string) => Promise<ReorderResult | null>;\n /** Clear the last result + error (e.g. after dismissing the banner). */\n reset: () => void;\n}\n\nexport function useReorder(): UseReorder {\n const [result, setResult] = useState<ReorderResult | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const reorder = useCallback(\n async (orderId: string): Promise<ReorderResult | null> => {\n if (typeof window === \"undefined\") return null;\n if (!orderId) {\n setError(new Error(\"Order id is required.\"));\n return null;\n }\n setLoading(true);\n setError(null);\n try {\n // Read the CSRF cookie value and echo it as a header — the\n // storefront's mutating proxies verify the double-submit.\n const csrf =\n typeof document !== \"undefined\"\n ? (document.cookie.match(/(?:^|; )numu_csrf=([^;]+)/)?.[1] ?? \"\")\n : \"\";\n const res = await fetch(\n `/api/customer/orders/${encodeURIComponent(orderId)}/reorder`,\n {\n method: \"POST\",\n headers: csrf ? { \"x-numu-csrf\": csrf } : {},\n credentials: \"include\",\n },\n );\n if (!res.ok) {\n if (res.status === 401) {\n setError(new Error(\"Please sign in to reorder.\"));\n } else if (res.status === 404) {\n setError(new Error(\"That order can't be found on your account.\"));\n } else {\n setError(new Error(`Couldn't reorder (HTTP ${res.status}).`));\n }\n return null;\n }\n const json = (await res.json()) as { data?: ReorderResult };\n const data = json?.data;\n if (!data) {\n setError(new Error(\"Unexpected response from server.\"));\n return null;\n }\n setResult(data);\n return data;\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n return null;\n } finally {\n setLoading(false);\n }\n },\n [],\n );\n\n const reset = useCallback(() => {\n setResult(null);\n setError(null);\n }, []);\n\n return { result, loading, error, reorder, reset };\n}\n","\"use client\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\n\n/**\n * Programmatic checkout driver — Phase 7.6.\n *\n * The storefront's multi-step checkout pages (Phase 1.2) own the\n * default flow: contact → shipping → payment → review → processing →\n * thank-you. This hook gives themes a programmatic alternative so a\n * BYOT theme can render the checkout exactly how it wants — single-\n * page, accordion, full-bleed hero, whatever — without being forced\n * through the platform's step pages.\n *\n * State lives in `numu_checkout_state` sessionStorage (same blob the\n * platform's step pages use) so themes that drive checkout\n * programmatically can hand off to the platform mid-flow (e.g. theme\n * collects contact + shipping, then redirects to /checkout/payment\n * for the gateway capture). The platform-side state machine guards\n * deep-links via `hasContactStep / hasShippingStep / hasPaymentStep`\n * regardless of how the state got populated.\n *\n * Usage:\n *\n * const checkout = useCheckout();\n * checkout.contact.set({ email, phone, shipping_address });\n * await checkout.shipping.refresh();\n * checkout.shipping.select(rate.id);\n * checkout.payment.select(\"paymob\");\n * const result = await checkout.placeOrder();\n * if (result.payment_url) window.location.assign(result.payment_url);\n */\n\nexport type CheckoutStep =\n | \"contact\"\n | \"shipping\"\n | \"payment\"\n | \"review\"\n | \"processing\";\n\nexport interface CheckoutAddress {\n first_name?: string;\n last_name?: string;\n line1?: string;\n line2?: string | null;\n city?: string;\n state?: string | null;\n postal_code?: string | null;\n country?: string;\n phone?: string | null;\n}\n\nexport interface ShippingRateOption {\n id: string;\n name: string;\n amount_cents: number;\n currency: string;\n estimated_days_min?: number | null;\n estimated_days_max?: number | null;\n carrier?: string | null;\n}\n\nexport interface CheckoutSessionState {\n email: string;\n phone: string;\n shipping_address: CheckoutAddress;\n selected_shipping_rate_id: string | null;\n shipping_method: string | null;\n payment_method: string | null;\n cod_requested: boolean;\n deposit_gateway: string | null;\n saved_payment_method_id: string | null;\n customer_notes: string;\n coupon_code: string;\n}\n\nexport interface PlaceOrderResult {\n order_id: string;\n order_number: string;\n total: number;\n currency: string;\n payment_status: string;\n payment_url?: string | null;\n payment_data?: Record<string, unknown> | null;\n}\n\nexport interface CheckoutApi {\n state: CheckoutSessionState;\n step: CheckoutStep;\n contact: {\n set: (input: {\n email?: string;\n phone?: string;\n shipping_address?: CheckoutAddress;\n }) => void;\n isComplete: () => boolean;\n };\n shipping: {\n rates: ShippingRateOption[] | null;\n loading: boolean;\n refresh: () => Promise<ShippingRateOption[]>;\n select: (rateId: string) => void;\n isComplete: () => boolean;\n };\n payment: {\n select: (\n method: string,\n opts?: { saved_payment_method_id?: string; deposit_gateway?: string },\n ) => void;\n isComplete: () => boolean;\n };\n setNotes: (notes: string) => void;\n setCoupon: (code: string) => void;\n placeOrder: () => Promise<PlaceOrderResult>;\n reset: () => void;\n}\n\nconst STORAGE_KEY = \"numu_checkout_state\";\n\nconst EMPTY_STATE: CheckoutSessionState = {\n email: \"\",\n phone: \"\",\n shipping_address: {},\n selected_shipping_rate_id: null,\n shipping_method: null,\n payment_method: null,\n cod_requested: false,\n deposit_gateway: null,\n saved_payment_method_id: null,\n customer_notes: \"\",\n coupon_code: \"\",\n};\n\nfunction readState(): CheckoutSessionState {\n if (typeof window === \"undefined\") return { ...EMPTY_STATE };\n try {\n const raw = window.sessionStorage.getItem(STORAGE_KEY);\n if (!raw) return { ...EMPTY_STATE };\n return { ...EMPTY_STATE, ...JSON.parse(raw) };\n } catch {\n return { ...EMPTY_STATE };\n }\n}\n\nfunction writeState(state: CheckoutSessionState): void {\n if (typeof window === \"undefined\") return;\n try {\n window.sessionStorage.setItem(STORAGE_KEY, JSON.stringify(state));\n // Notify any other useCheckout() consumers in the same tab.\n window.dispatchEvent(new CustomEvent(\"numu:checkout:updated\"));\n } catch {\n /* Safari private mode → swallow */\n }\n}\n\nfunction hasContact(s: CheckoutSessionState): boolean {\n return Boolean(\n s.email &&\n s.shipping_address?.line1 &&\n s.shipping_address?.city &&\n s.shipping_address?.country,\n );\n}\n\nfunction hasShipping(s: CheckoutSessionState): boolean {\n return hasContact(s) && Boolean(s.selected_shipping_rate_id);\n}\n\nfunction hasPayment(s: CheckoutSessionState): boolean {\n return hasShipping(s) && Boolean(s.payment_method);\n}\n\nfunction resolveStep(s: CheckoutSessionState): CheckoutStep {\n if (!hasContact(s)) return \"contact\";\n if (!hasShipping(s)) return \"shipping\";\n if (!hasPayment(s)) return \"payment\";\n return \"review\";\n}\n\nexport function useCheckout(): CheckoutApi {\n const [state, setState] = useState<CheckoutSessionState>(() => readState());\n const [rates, setRates] = useState<ShippingRateOption[] | null>(null);\n const [ratesLoading, setRatesLoading] = useState(false);\n\n // Sync from sessionStorage when other consumers update (other tab\n // would not trigger the same-tab event but storage event handles it).\n useEffect(() => {\n function onChange() {\n setState(readState());\n }\n window.addEventListener(\"numu:checkout:updated\", onChange);\n window.addEventListener(\"storage\", (e) => {\n if (e.key === STORAGE_KEY) onChange();\n });\n return () => {\n window.removeEventListener(\"numu:checkout:updated\", onChange);\n };\n }, []);\n\n const patch = useCallback((partial: Partial<CheckoutSessionState>) => {\n setState((prev) => {\n const next = { ...prev, ...partial };\n writeState(next);\n return next;\n });\n }, []);\n\n const refreshShipping = useCallback(async (): Promise<ShippingRateOption[]> => {\n setRatesLoading(true);\n try {\n const res = await fetch(\"/api/shipping/options\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ shipping_address: state.shipping_address }),\n });\n if (!res.ok) {\n setRates([]);\n return [];\n }\n const body = await res.json();\n const list: ShippingRateOption[] =\n (body?.data?.options || body?.data || body?.options || []) as ShippingRateOption[];\n setRates(list);\n return list;\n } catch {\n setRates([]);\n return [];\n } finally {\n setRatesLoading(false);\n }\n }, [state.shipping_address]);\n\n const placeOrder = useCallback(async (): Promise<PlaceOrderResult> => {\n // Cart line items are read server-side from the session cookie;\n // we still pass an empty list because the schema requires the field.\n const payload = {\n line_items: [],\n shipping_address: state.shipping_address,\n payment_method: state.payment_method,\n selected_shipping_rate_id: state.selected_shipping_rate_id,\n shipping_method: state.shipping_method,\n guest_email: state.email,\n cod_requested: state.cod_requested,\n deposit_gateway: state.deposit_gateway,\n saved_payment_method_id: state.saved_payment_method_id,\n customer_notes: state.customer_notes || null,\n coupon_code: state.coupon_code || null,\n };\n const res = await fetch(\"/api/checkout\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n // Idempotency-Key prevents a double-click double-charge.\n \"Idempotency-Key\":\n typeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n ? crypto.randomUUID()\n : `${Date.now()}-${Math.random()}`,\n },\n body: JSON.stringify(payload),\n });\n const body = await res.json();\n if (!res.ok) {\n const detail =\n body?.detail || body?.error || `Checkout failed (${res.status})`;\n throw new Error(typeof detail === \"string\" ? detail : JSON.stringify(detail));\n }\n const data = (body?.data || body) as PlaceOrderResult;\n return data;\n }, [state]);\n\n const step = useMemo(() => resolveStep(state), [state]);\n\n const api = useMemo<CheckoutApi>(\n () => ({\n state,\n step,\n contact: {\n set: (input) =>\n patch({\n ...(input.email !== undefined && { email: input.email }),\n ...(input.phone !== undefined && { phone: input.phone }),\n ...(input.shipping_address && {\n shipping_address: {\n ...state.shipping_address,\n ...input.shipping_address,\n },\n // Invalidate downstream picks when address changes.\n selected_shipping_rate_id: null,\n shipping_method: null,\n }),\n }),\n isComplete: () => hasContact(state),\n },\n shipping: {\n rates,\n loading: ratesLoading,\n refresh: refreshShipping,\n select: (rateId) => {\n const rate = rates?.find((r) => r.id === rateId);\n patch({\n selected_shipping_rate_id: rateId,\n shipping_method: rate?.name || null,\n });\n },\n isComplete: () => hasShipping(state),\n },\n payment: {\n select: (method, opts) =>\n patch({\n payment_method: method,\n cod_requested: method === \"cod\",\n deposit_gateway: opts?.deposit_gateway || null,\n saved_payment_method_id: opts?.saved_payment_method_id || null,\n }),\n isComplete: () => hasPayment(state),\n },\n setNotes: (notes) => patch({ customer_notes: notes }),\n setCoupon: (code) => patch({ coupon_code: code }),\n placeOrder,\n reset: () => {\n if (typeof window !== \"undefined\") {\n try {\n window.sessionStorage.removeItem(STORAGE_KEY);\n } catch {\n /* swallow */\n }\n }\n setState({ ...EMPTY_STATE });\n setRates(null);\n },\n }),\n [state, step, rates, ratesLoading, refreshShipping, placeOrder, patch],\n );\n\n return api;\n}\n","\"use client\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport type { CheckoutAddress, ShippingRateOption } from \"./useCheckout\";\n\n/**\n * Fetch shipping rate options for an address — Phase 7.4.\n *\n * Themes that want to display rates on the cart page (Shopify\n * pattern: \"Shipping calculated at checkout — preview from cart\")\n * use this. It posts to /api/shipping/options the same way the\n * platform's shipping step does, but as a self-contained hook so\n * themes don't need to drive the full useCheckout() machinery for a\n * simple display.\n *\n * Returns null when no address is provided (the typical pre-input\n * state) — themes branch on `rates !== null` to decide whether to\n * show the rates panel or a \"Enter address\" prompt.\n *\n * Optionally accepts a `location_id` for multi-location stores\n * (Phase 8.2) — the resolver uses the named fulfilling location's\n * origin address when calculating rates. Ignored if multi-location\n * is off.\n *\n * Usage:\n *\n * const { rates, loading, refresh } = useShippingRates({\n * address: { country: \"EG\", city: \"Cairo\" },\n * });\n */\n\nexport interface UseShippingRatesOptions {\n address?: CheckoutAddress | null;\n location_id?: string | null;\n /** Auto-fetch on mount + when the address changes. Default true. */\n enabled?: boolean;\n}\n\nexport interface UseShippingRatesState {\n rates: ShippingRateOption[] | null;\n loading: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n}\n\nfunction isAddressSufficient(a?: CheckoutAddress | null): boolean {\n if (!a) return false;\n // Country alone gets a zone-level estimate; city + country gets\n // the rate properly. We require at least country since zones are\n // country-keyed.\n return Boolean(a.country);\n}\n\nexport function useShippingRates({\n address,\n location_id,\n enabled = true,\n}: UseShippingRatesOptions = {}): UseShippingRatesState {\n const [rates, setRates] = useState<ShippingRateOption[] | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const refresh = useCallback(async (): Promise<void> => {\n if (!isAddressSufficient(address)) {\n setRates(null);\n return;\n }\n setLoading(true);\n setError(null);\n try {\n const res = await fetch(\"/api/shipping/options\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n shipping_address: address,\n ...(location_id ? { location_id } : {}),\n }),\n });\n if (!res.ok) {\n // 404 = country not covered by any zone. Surface as \"no\n // rates\" rather than an error so themes can render a\n // \"We don't ship to {country}\" message gracefully.\n if (res.status === 404) {\n setRates([]);\n return;\n }\n throw new Error(`shipping rates: HTTP ${res.status}`);\n }\n const body = await res.json();\n const list: ShippingRateOption[] =\n (body?.data?.options || body?.data || body?.options || []) as ShippingRateOption[];\n setRates(list);\n } catch (e) {\n setError(e instanceof Error ? e : new Error(String(e)));\n setRates([]);\n } finally {\n setLoading(false);\n }\n }, [address, location_id]);\n\n useEffect(() => {\n if (!enabled) return;\n void refresh();\n }, [enabled, refresh]);\n\n return { rates, loading, error, refresh };\n}\n","\"use client\";\nimport {\n useEffect,\n useState,\n useCallback,\n useMemo,\n useRef,\n type ReactNode,\n} from \"react\";\nimport {\n ShopContext,\n CartContext,\n CustomerContext,\n ThemeSettingsContext,\n LocalizationContext,\n CurrentTemplateContext,\n PageContext,\n NavigationContext,\n} from \"../contexts\";\nimport {\n CustomerActionsContext,\n type CustomerActions,\n} from \"../contexts/customer-actions\";\nimport type { Store, Cart, Customer } from \"../types/entities\";\nimport type { ThemeSettingsV3 } from \"../types/theme\";\nimport type { LocalizationState, MenuItemData } from \"../contexts\";\n\nconst RTL_LOCALES = [\"ar\", \"he\", \"fa\", \"ur\"];\n\ninterface NuMuProviderProps {\n store: Store;\n themeSettings: ThemeSettingsV3;\n initialCart?: Cart;\n customer?: Customer | null;\n locale?: string;\n translations?: Record<string, string>;\n /**\n * Wave 5 — id of the active page template. Hosts pass this from the\n * route (e.g. \"product\" inside app/(store)/[subdomain]/product/[id]).\n * Themes read it via `useCurrentTemplate()` to render the matching\n * section list. Defaults to \"home\" when omitted, so existing themes\n * built before the prop existed keep rendering their home template.\n */\n currentTemplate?: string;\n /**\n * Pre-fetched product list for the current page. Themes that call\n * `useProducts()` will read these from PageContext without needing\n * `fetchIfMissing: true`. Hosts typically populate this from their\n * route loader / SSR pass; omitting it leaves `useProducts()`\n * returning an empty array unless the theme opts into client fetch.\n */\n initialProducts?: import(\"../types/entities\").Product[];\n /**\n * Pre-fetched collection list — same pattern as initialProducts for\n * `useCollections()`. Categories/collections shown on the home page\n * read this slot.\n */\n initialCollections?: import(\"../types/entities\").Collection[];\n /**\n * Phase 2.4 — store navigation menus keyed by handle (`main-menu`,\n * `footer`, …), resolved server-side by the host and injected so a\n * theme's `useNavigation(handle)` resolves synchronously without a\n * client round-trip. Omit for hosts/themes that don't wire menus —\n * `useNavigation` then falls back to its own fetch or the theme's\n * `DEFAULT_NAV`.\n */\n navigation?: Record<string, MenuItemData[]>;\n children: ReactNode;\n}\n\nconst EMPTY_CART: Cart = {\n id: \"\",\n items: [],\n subtotal: 0,\n total: 0,\n currency: \"EGP\",\n};\n\n/**\n * The storefront's /api/cart returns money in CENTS (matching the checkout\n * and built-in cart, which divide by 100 themselves). Themes consume the cart\n * via useCart() and render with <Money>/formatMoney, which expect MAJOR units\n * — the same convention as Product.price after the host normalizes it. Convert\n * cart money to major here so the BYOT boundary is consistent end-to-end.\n *\n * Display-only: checkout submits quantities (the server recomputes amounts),\n * so this never changes what the customer is charged.\n */\nfunction normalizeCartFromServer(cart: Cart): Cart {\n const toMajor = (n: number | null | undefined): number =>\n typeof n === \"number\" ? n / 100 : 0;\n return {\n ...cart,\n subtotal: toMajor(cart.subtotal),\n total: toMajor(cart.total),\n ...(cart.discount_amount != null\n ? { discount_amount: toMajor(cart.discount_amount) }\n : {}),\n items: Array.isArray(cart.items)\n ? cart.items.map((it) => ({ ...it, price: toMajor(it.price) }))\n : [],\n };\n}\n\n/**\n * The storefront's /api/cart* routes return the cart inside a `{data}`\n * envelope (`{ success, data: Cart, message }`) — the platform-wide response\n * shape the hub / admin / customer-fetch all unwrap. The cart logic here\n * historically read the response AS the cart, so `data.items` was `undefined`\n * and the cart silently stayed EMPTY: add-to-cart returned 200/201 but the\n * header count and cart page never updated. Unwrap `.data` when present.\n */\nfunction unwrapCart(json: unknown): Cart {\n if (\n json &&\n typeof json === \"object\" &&\n \"data\" in json &&\n (json as { data?: unknown }).data &&\n typeof (json as { data?: unknown }).data === \"object\"\n ) {\n return (json as { data: Cart }).data;\n }\n return json as Cart;\n}\n\n/**\n * Read the `numu_csrf` cookie value from document.cookie.\n *\n * The storefront's GET /api/cart sets this on first fetch; we echo it\n * back in `x-numu-csrf` on every mutation so the proxy can verify the\n * double-submit. Without this gate any XSS in a theme can drain the\n * customer's cart by hitting /api/cart/add directly.\n */\nfunction readCsrfCookie(): string | null {\n if (typeof document === \"undefined\") return null;\n const match = document.cookie.match(/(?:^|;\\s*)numu_csrf=([^;]+)/);\n return match ? decodeURIComponent(match[1]) : null;\n}\n\n/**\n * postCartMutation — shared helper for cart writes.\n *\n * Three concerns layered together:\n *\n * 1. Request versioning so a burst of \"+ + +\" clicks doesn't apply\n * stale responses. Each call reserves a token; only the response\n * for the highest-numbered token is allowed to update local state.\n *\n * 2. CSRF: every cart mutation includes `x-numu-csrf` from the cookie.\n * The /api/cart/* proxy compares cookie + header (double-submit)\n * and rejects mismatches with 403.\n *\n * 3. Idempotency: each call mints a UUID idempotency key. The\n * backend (when supported) caches the response for that key in\n * Redis so a double-clicked Add-to-Cart only mutates state once.\n * Wire format is stable; backend honoring it is opt-in.\n *\n * Returns the latest cart state (whatever the server says), but the\n * caller shouldn't blindly setState from it — `applyCart` already\n * filtered.\n */\nasync function postCartMutation(\n endpoint: string,\n body: unknown,\n applyCart: (cart: Cart) => void,\n reserveToken: () => number,\n): Promise<void> {\n const token = reserveToken();\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n const csrf = readCsrfCookie();\n if (csrf) headers[\"x-numu-csrf\"] = csrf;\n // Idempotency key — randomUUID is widely supported; fall back if not\n // (older Safari, embedded webviews).\n const idempotencyKey =\n typeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n ? crypto.randomUUID()\n : `${Date.now()}-${Math.random().toString(36).slice(2)}`;\n headers[\"x-numu-idempotency-key\"] = idempotencyKey;\n\n const res = await fetch(endpoint, {\n method: body === undefined ? \"DELETE\" : \"POST\",\n headers,\n body: body === undefined ? undefined : JSON.stringify(body),\n });\n if (!res.ok) return;\n const json = await res.json();\n applyCart(unwrapCart(json));\n // Token was actually consumed on entry; applyCart enforces ordering\n // via the closure below.\n void token;\n}\n\nexport function NuMuProvider({\n store,\n themeSettings,\n initialCart,\n customer,\n locale: initialLocale,\n translations: initialTranslations,\n currentTemplate = \"home\",\n initialProducts,\n initialCollections,\n navigation,\n children,\n}: NuMuProviderProps) {\n // Synthesise a Page record so `useProducts()` and `useCollections()`\n // can read pre-fetched lists via PageContext. Stable identity ensures\n // we don't bust the context on every render (initialProducts and\n // initialCollections come in as fresh arrays from the host's\n // useMemo'd ctx, so referential equality already holds across renders\n // without changes; useMemo here is belt-and-suspenders).\n const pageValue = useMemo(\n () =>\n ({\n type: currentTemplate,\n title: store?.name ?? \"\",\n data: {\n products: initialProducts ?? [],\n collections: initialCollections ?? [],\n },\n }) as import(\"../types/entities\").Page,\n [currentTemplate, store?.name, initialProducts, initialCollections],\n );\n const [cart, setCart] = useState<Cart>(\n initialCart || { ...EMPTY_CART, currency: store.currency },\n );\n const [loading, setLoading] = useState(false);\n // Phase 3.6 — locale precedence:\n // 1. `initialLocale` prop (storefront pages that resolved it server-side)\n // 2. `numu_locale` cookie (client-side fallback for pages that don't\n // thread the prop through)\n // 3. `store.default_language`\n // 4. \"en\"\n const [locale, setLocale] = useState(() => {\n if (initialLocale) return initialLocale;\n if (typeof document !== \"undefined\") {\n const m = document.cookie.match(/(?:^|; )numu_locale=([^;]+)/);\n if (m) return decodeURIComponent(m[1]);\n }\n return store.default_language || \"en\";\n });\n const [translations] = useState(initialTranslations || {});\n\n // ── Customer state + auth actions ──────────────────────────────────────\n // Customer comes from one of three sources, in order of precedence:\n // 1. SSR-supplied `customer` prop (when /account/* routes pre-fetch\n // the customer server-side via the cookie).\n // 2. The mount effect below which calls GET /api/customer/me, used\n // on routes that don't pre-fetch (home/product/etc.) to keep the\n // cart drawer / header user menu accurate.\n // 3. Mutations triggered by `useCustomerActions()` (login/logout/\n // register/updateProfile) — these refresh state immediately.\n const [customerState, setCustomerState] = useState<Customer | null>(\n customer ?? null,\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n // Skip the GET if the SSR pass already supplied a customer; the\n // round-trip would only confirm what we already know and waste a\n // request budget on every navigation.\n if (customer) return;\n let cancelled = false;\n void (async () => {\n try {\n const res = await fetch(\"/api/customer/me\", {\n method: \"GET\",\n credentials: \"include\",\n cache: \"no-store\",\n });\n if (cancelled) return;\n // 401 means logged-out: leave customerState=null. Any other\n // non-OK is treated the same — the customer can still browse.\n if (!res.ok) return;\n const json = await res.json();\n const next =\n json && typeof json === \"object\" && \"data\" in json\n ? (json as { data: Customer }).data\n : (json as Customer);\n if (next && typeof next === \"object\") {\n setCustomerState(next);\n }\n } catch {\n // Network blip — keep current customerState.\n }\n })();\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Refresh re-fetches /api/customer/me; used after any mutation that\n // changed the customer record (login/register/profile update).\n const refreshCustomer = useCallback(async () => {\n if (typeof window === \"undefined\") return;\n try {\n const res = await fetch(\"/api/customer/me\", {\n method: \"GET\",\n credentials: \"include\",\n cache: \"no-store\",\n });\n if (res.status === 401) {\n setCustomerState(null);\n return;\n }\n if (!res.ok) return;\n const json = await res.json();\n const next =\n json && typeof json === \"object\" && \"data\" in json\n ? (json as { data: Customer }).data\n : (json as Customer);\n setCustomerState(next ?? null);\n } catch {\n // ignore\n }\n }, []);\n\n // CSRF: customer mutations echo `numu_csrf` cookie value as header\n // for double-submit. Read just-in-time so we always send the freshest\n // (the cookie may rotate on /api/cart roundtrip).\n function readCsrf(): string | null {\n if (typeof document === \"undefined\") return null;\n const m = document.cookie.match(/(?:^|; )numu_csrf=([^;]+)/);\n return m ? decodeURIComponent(m[1]) : null;\n }\n\n async function postCustomer(path: string, body: unknown): Promise<unknown> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n const csrf = readCsrf();\n if (csrf) headers[\"x-numu-csrf\"] = csrf;\n const res = await fetch(path, {\n method: \"POST\",\n credentials: \"include\",\n cache: \"no-store\",\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n let json: unknown = null;\n try {\n json = await res.json();\n } catch {\n // empty body — fine\n }\n return json;\n }\n\n async function putCustomer(path: string, body: unknown): Promise<unknown> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n const csrf = readCsrf();\n if (csrf) headers[\"x-numu-csrf\"] = csrf;\n const res = await fetch(path, {\n method: \"PUT\",\n credentials: \"include\",\n cache: \"no-store\",\n headers,\n body: JSON.stringify(body ?? {}),\n });\n try {\n return await res.json();\n } catch {\n return null;\n }\n }\n\n const customerActions: CustomerActions = useMemo(\n () => ({\n login: async (input) => {\n const r = await postCustomer(\"/api/customer/login\", input);\n await refreshCustomer();\n return r;\n },\n register: async (input) => {\n const r = await postCustomer(\"/api/customer/register\", input);\n await refreshCustomer();\n return r;\n },\n logout: async () => {\n const r = await postCustomer(\"/api/customer/logout\", {});\n // Don't wait on refresh — backend cleared the cookie, so\n // setCustomerState(null) directly avoids a redundant 401.\n setCustomerState(null);\n return r;\n },\n requestRecover: (input) =>\n postCustomer(\"/api/customer/recover\", input),\n confirmReset: async (input) => {\n const r = await postCustomer(\"/api/customer/reset\", input);\n // Reset clears all sessions on the backend; user must log in\n // again. Force null so any stale state from before the reset\n // doesn't linger.\n setCustomerState(null);\n return r;\n },\n verifyEmail: async (input) => {\n const r = await postCustomer(\"/api/customer/verify-email\", input);\n await refreshCustomer();\n return r;\n },\n resendVerification: (input) =>\n postCustomer(\"/api/customer/resend-verification\", input),\n updateProfile: async (input) => {\n const r = await putCustomer(\"/api/customer/me\", input);\n await refreshCustomer();\n return r;\n },\n changePassword: (input) =>\n putCustomer(\"/api/customer/me/password\", input),\n refresh: refreshCustomer,\n }),\n [refreshCustomer],\n );\n\n // ── Initial cart fetch ─────────────────────────────────────────────────\n // GET /api/cart on mount serves two purposes:\n // 1. Hydrates the live cart state for returning visitors so the\n // header cart count is accurate before any user interaction.\n // 2. Mints the `numu_csrf` cookie (the storefront's GET /api/cart\n // handler emits Set-Cookie if missing). Subsequent cart-write\n // calls read this cookie via document.cookie and echo it as\n // the `x-numu-csrf` header for double-submit verification.\n // Without this priming round-trip, a first-Add-to-Cart 403s\n // because the cookie hasn't been issued yet.\n //\n // SSR-safe: `fetch` is a browser-only call here; we gate on `window`.\n // Errors are swallowed — the cart context starts empty either way,\n // and downstream actions surface their own errors.\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n let cancelled = false;\n void (async () => {\n try {\n const res = await fetch(\"/api/cart\", {\n method: \"GET\",\n credentials: \"include\",\n cache: \"no-store\",\n });\n if (!res.ok || cancelled) return;\n const json = await res.json();\n const data = unwrapCart(json);\n if (data && typeof data === \"object\") {\n setCart(normalizeCartFromServer(data));\n }\n } catch {\n // Network blip / not-yet-deployed cart endpoint. Leave the\n // empty initial cart in place; the user can still browse.\n }\n })();\n return () => {\n cancelled = true;\n };\n // Run once per mount; the cart endpoint is idempotent and the\n // CSRF cookie persists across navigations within the SPA.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // ── Request-versioning machinery ───────────────────────────────────────\n // `nextRequestId` increases on each cart mutation; `latestApplied` tracks\n // the highest id whose response has been applied. A response is applied\n // only if its id is >= latestApplied (i.e., not superseded).\n const nextRequestId = useRef(0);\n const latestApplied = useRef(0);\n\n const reserveToken = useCallback(() => {\n nextRequestId.current += 1;\n return nextRequestId.current;\n }, []);\n\n const buildApplyCart = useCallback(\n (token: number) => (newCart: Cart) => {\n if (token < latestApplied.current) {\n // A later request has already updated state — ignore stale response.\n return;\n }\n latestApplied.current = token;\n setCart(normalizeCartFromServer(newCart));\n },\n [],\n );\n\n const mutate = useCallback(\n async (endpoint: string, body: unknown): Promise<void> => {\n const token = reserveToken();\n setLoading(true);\n try {\n await postCartMutation(\n endpoint,\n body,\n buildApplyCart(token),\n () => token, // already reserved; just return the same token\n );\n } finally {\n setLoading(false);\n }\n },\n [reserveToken, buildApplyCart],\n );\n\n // ── Cart actions ───────────────────────────────────────────────────────\n\n const addItem = useCallback(\n async (productId: string, variantId?: string, quantity?: number) => {\n // Shared event id for Meta AddToCart dedup: the host /api/cart/add route\n // fires the CAPI event with this id, and the host <MetaPixel> bridge\n // fires the matching browser fbq from the CustomEvent below.\n const eventId =\n typeof crypto !== \"undefined\" && crypto.randomUUID\n ? crypto.randomUUID()\n : `${Date.now()}`;\n const qty = quantity || 1;\n await mutate(\"/api/cart/add\", {\n product_id: productId,\n variant_id: variantId,\n quantity: qty,\n _event_id: eventId,\n });\n // Browser-side AddToCart signal — CAPI is fired server-side by the cart\n // route with the same id. Dispatched directly (not via useAnalytics) so\n // we control the event_id and avoid a duplicate /track POST.\n try {\n if (typeof window !== \"undefined\") {\n window.dispatchEvent(\n new CustomEvent(\"numu:analytics:event\", {\n detail: {\n event: \"add_to_cart\",\n payload: {\n content_ids: [productId],\n content_type: \"product\",\n num_items: qty,\n },\n event_id: eventId,\n },\n }),\n );\n }\n } catch {\n /* CustomEvent unsupported — server CAPI still covers the event */\n }\n },\n [mutate],\n );\n\n const removeItem = useCallback(\n async (itemId: string) => {\n await mutate(\"/api/cart/remove\", { item_id: itemId });\n },\n [mutate],\n );\n\n const updateQuantity = useCallback(\n async (itemId: string, quantity: number) => {\n await mutate(\"/api/cart/update\", { item_id: itemId, quantity });\n },\n [mutate],\n );\n\n const applyDiscount = useCallback(\n async (code: string) => {\n await mutate(\"/api/cart/discount\", { code });\n },\n [mutate],\n );\n\n const removeDiscount = useCallback(async () => {\n // DELETE — postCartMutation interprets undefined body as DELETE.\n await mutate(\"/api/cart/discount\", undefined);\n }, [mutate]);\n\n /**\n * Persist a customer note on the cart. Round-trips to the backend so the\n * note survives reload (the previous local-only behavior was a footgun).\n */\n const updateNote = useCallback(\n async (note: string) => {\n await mutate(\"/api/cart/update\", { note });\n },\n [mutate],\n );\n\n const clearCart = useCallback(async () => {\n setCart({ ...EMPTY_CART, currency: store.currency });\n }, [store.currency]);\n\n // Broadcast a `numu:cart:updated` CustomEvent on every cart change.\n // Why: non-React themes (vanilla JS / Alpine / Vue islands) can't\n // consume `useCart()`. They listen on `window` instead, which gives\n // them the same write-then-react contract React themes get for free.\n // The event detail mirrors the React `cart` shape so consumers don't\n // need to re-fetch.\n //\n // We skip the first dispatch — the initial state is the empty\n // placeholder before the GET /api/cart response lands, and themes\n // that ran their own `numu:cart:fetched`-style logic on page load\n // would otherwise see a spurious empty event right after rendering.\n const cartFirstRender = useRef(true);\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n if (cartFirstRender.current) {\n cartFirstRender.current = false;\n return;\n }\n window.dispatchEvent(\n new CustomEvent(\"numu:cart:updated\", { detail: cart }),\n );\n }, [cart]);\n\n const cartValue = useMemo(\n () => ({\n cart,\n addItem,\n removeItem,\n updateQuantity,\n applyDiscount,\n removeDiscount,\n updateNote,\n clearCart,\n loading,\n }),\n [\n cart,\n addItem,\n removeItem,\n updateQuantity,\n applyDiscount,\n removeDiscount,\n updateNote,\n clearCart,\n loading,\n ],\n );\n\n // ── Localization with memoized Intl formatters ─────────────────────────\n // Building Intl.NumberFormat / Intl.DateTimeFormat per call is costly;\n // memoize on (locale, currency).\n //\n // Resilience: stores can come back from older API rows with `currency`\n // null/empty. `Intl.NumberFormat({ currency: \"\" })` throws \"Currency\n // code is required with currency style\", which crashes the entire\n // render tree. Fall back to USD for the formatter so themes keep\n // working — merchants will see prices in USD until they configure a\n // real currency, which is a clearer signal than a blank screen.\n const safeCurrency = (store.currency || \"USD\").toUpperCase();\n\n // Phase 3.7 — numeral system. Merchants opt into Arab-Indic\n // digits (٠١٢٣٤) for Arabic stores via store.settings.numerals.\n // Western (default) keeps the ASCII digits everyone's used to.\n // We construct intl locales with the appropriate `-u-nu-<system>`\n // extension so money + date + count formatters all stay consistent.\n const numeralSystem =\n ((store as unknown as { settings?: { numerals?: string } }).settings\n ?.numerals === \"arabic\")\n ? \"arab\"\n : \"latn\";\n const intlLocale = `${locale}-u-nu-${numeralSystem}`;\n\n // We deliberately compute intlLocale BEFORE these memos so the\n // numbering-system extension is part of the formatter cache key —\n // a merchant flipping store.settings.numerals from \"western\" to\n // \"arabic\" rebuilds the formatters on the next render rather than\n // continuing to render Western digits from the stale cache.\n const moneyFmt = useMemo(() => {\n try {\n return new Intl.NumberFormat(intlLocale, {\n style: \"currency\",\n currency: safeCurrency,\n });\n } catch {\n // Pathologic intlLocale (engine doesn't support `-u-nu-arab`\n // for the active language) — fall back to the bare locale.\n return new Intl.NumberFormat(locale, {\n style: \"currency\",\n currency: safeCurrency,\n });\n }\n }, [intlLocale, locale, safeCurrency]);\n const dateFmt = useMemo(() => {\n try {\n return new Intl.DateTimeFormat(intlLocale, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n });\n } catch {\n return new Intl.DateTimeFormat(locale, {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n });\n }\n }, [intlLocale, locale]);\n\n // Phase 3.6 — locales the store advertises. Falls back to a single-\n // entry list (the active locale) so themes can render the\n // LocaleSwitcher unconditionally without an extra check.\n const availableLocales = useMemo(() => {\n const list =\n (store as unknown as { available_locales?: string[] }).available_locales;\n if (Array.isArray(list) && list.length > 0) return list;\n return [locale];\n }, [store, locale]);\n\n // Phase 3.6 — locale switcher. Writes the cookie + reloads so the\n // server-rendered layout picks up the change. We prefer cookie over\n // querystring because cookie persists across cross-page navigation\n // without each page having to thread `?locale=ar` through every link.\n const switchLocale = useCallback((next: string) => {\n if (typeof document === \"undefined\") return;\n if (!next) return;\n // 1-year cookie; SameSite=Lax so it travels with same-origin nav\n // but doesn't leak on cross-site requests. Path=/ so every page\n // sees it.\n document.cookie =\n `numu_locale=${encodeURIComponent(next)}; ` +\n `Path=/; Max-Age=${60 * 60 * 24 * 365}; SameSite=Lax`;\n setLocale(next);\n // Reload so SSR re-runs with the new cookie. Themes that want\n // client-only locale swaps (no SSR re-render) can wrap their text\n // in `useTranslation()` and skip the reload — but locale-aware\n // SSR data (translated product names, RTL <html dir>) needs the\n // reload to take effect.\n if (typeof window !== \"undefined\") {\n window.location.reload();\n }\n }, []);\n\n // Default (no-options) number formatter — memoized so the formatNumber\n // hot path doesn't construct one per call. Declared BEFORE the\n // localization useMemo so the closure captures the resolved value.\n const defaultNumberFmt = useMemo(() => {\n try {\n return new Intl.NumberFormat(intlLocale);\n } catch {\n return new Intl.NumberFormat(locale);\n }\n }, [intlLocale, locale]);\n\n const localization: LocalizationState = useMemo(\n () => ({\n locale,\n direction: RTL_LOCALES.includes(locale) ? \"rtl\" : \"ltr\",\n translations,\n availableLocales,\n setLocale: switchLocale,\n formatMoney: (amount: number, currency?: string) => {\n const ccy = (currency || safeCurrency).toUpperCase();\n if (ccy !== safeCurrency) {\n // Override-currency path is rare; pay the formatter cost only here.\n // Empty/invalid override falls back to the store's safeCurrency\n // before this branch via the `||` above, so we never construct\n // an Intl.NumberFormat with `currency: \"\"`.\n try {\n return new Intl.NumberFormat(intlLocale, {\n style: \"currency\",\n currency: ccy,\n }).format(amount);\n } catch {\n return moneyFmt.format(amount);\n }\n }\n return moneyFmt.format(amount);\n },\n formatDate: (date: string | Date) =>\n dateFmt.format(typeof date === \"string\" ? new Date(date) : date),\n formatNumber: (n: number, options?: Intl.NumberFormatOptions) => {\n if (!options) return defaultNumberFmt.format(n);\n try {\n return new Intl.NumberFormat(intlLocale, options).format(n);\n } catch {\n return String(n);\n }\n },\n }),\n [\n locale,\n translations,\n safeCurrency,\n moneyFmt,\n dateFmt,\n availableLocales,\n switchLocale,\n intlLocale,\n defaultNumberFmt,\n ],\n );\n\n return (\n <ShopContext.Provider value={store}>\n <ThemeSettingsContext.Provider value={themeSettings}>\n <CurrentTemplateContext.Provider value={currentTemplate}>\n <PageContext.Provider value={pageValue}>\n <LocalizationContext.Provider value={localization}>\n <CartContext.Provider value={cartValue}>\n <CustomerContext.Provider value={customerState}>\n <CustomerActionsContext.Provider value={customerActions}>\n <NavigationContext.Provider value={navigation ?? {}}>\n {children}\n </NavigationContext.Provider>\n </CustomerActionsContext.Provider>\n </CustomerContext.Provider>\n </CartContext.Provider>\n </LocalizationContext.Provider>\n </PageContext.Provider>\n </CurrentTemplateContext.Provider>\n </ThemeSettingsContext.Provider>\n </ShopContext.Provider>\n );\n}\n","\"use client\";\nimport type { ReactNode } from \"react\";\nimport { ProductContext } from \"../contexts\";\nimport type { Product } from \"../types/entities\";\n\ninterface ProductProviderProps {\n product: Product;\n children: ReactNode;\n}\n\nexport function ProductProvider({ product, children }: ProductProviderProps) {\n return <ProductContext.Provider value={product}>{children}</ProductContext.Provider>;\n}\n","/**\n * `applyGlobalStyleTokens(globalSettings, el)` — Phase 3.5.\n *\n * Bridges a store's **global theme settings** (colors, fonts, layout) to\n * **CSS custom properties** on the bundle's mount root, so editing a color\n * or font in Theme Settings actually re-paints the storefront. Before this,\n * themes shipped static CSS tokens that nothing wrote to → the pickers were\n * a silent no-op.\n *\n * ## Token contract (canonical names every theme can rely on)\n *\n * For each global setting `<id>` we set `--theme-<id>` verbatim (colors as\n * their value, fonts resolved to a CSS font stack, other scalars as-is).\n * Themes consume these with the current static value as a fallback:\n *\n * --by-cream: var(--theme-background_color, #f7f1e8);\n * --by-espresso: var(--theme-primary_color, #3a2418);\n * --by-font-serif: var(--theme-heading_font, \"Cormorant Garamond\", serif);\n *\n * In addition, well-known ids are aliased to **role** tokens so themes that\n * prefer semantic names share one vocabulary:\n *\n * colors → --theme-color-{background,text,primary,secondary,accent,border,button}\n * fonts → --theme-font-{heading,body}\n *\n * `color_scheme` / `color_scheme_group` settings (object values keyed by role)\n * emit `--scheme-<id>-<role>`.\n *\n * The helper is **idempotent** and safe to call on every `applyDraft` so the\n * customizer's live preview re-paints as the merchant drags a color.\n */\n\ntype GlobalSettings = Record<string, unknown> | null | undefined;\n\n/** id → canonical color role. Covers both `<role>_color` and `color_<role>`. */\nconst COLOR_ROLE_ALIASES: Record<string, string> = {\n background_color: \"background\",\n color_background: \"background\",\n bg_color: \"background\",\n text_color: \"text\",\n color_text: \"text\",\n primary_color: \"primary\",\n color_primary: \"primary\",\n secondary_color: \"secondary\",\n color_secondary: \"secondary\",\n accent_color: \"accent\",\n color_accent: \"accent\",\n border_color: \"border\",\n color_border: \"border\",\n button_color: \"button\",\n color_button: \"button\",\n button_text_color: \"button-text\",\n color_button_text: \"button-text\",\n};\n\n/** id → canonical font role. */\nconst FONT_ROLE_ALIASES: Record<string, string> = {\n heading_font: \"heading\",\n font_heading: \"heading\",\n headings_font: \"heading\",\n body_font: \"body\",\n font_body: \"body\",\n text_font: \"body\",\n};\n\n/**\n * Font token → CSS stack + optional Google Fonts href. A `font_picker`/select\n * stores a token (e.g. \"cormorant\"); we resolve it to a real stack and inject\n * the webfont so a picked font actually loads. Unknown tokens fall through and\n * are used verbatim as the family (so a theme can store a raw stack too).\n */\nconst FONT_REGISTRY: Record<string, { stack: string; href?: string }> = {\n cormorant: {\n stack: '\"Cormorant Garamond\", Georgia, \"Times New Roman\", serif',\n href: \"https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;0,700;1,400&display=swap\",\n },\n \"dm-sans\": {\n stack: '\"DM Sans\", system-ui, -apple-system, \"Segoe UI\", sans-serif',\n href: \"https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,400;0,9..40,500;0,9..40,700&display=swap\",\n },\n playfair: {\n stack: '\"Playfair Display\", Georgia, serif',\n href: \"https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;500;600;700&display=swap\",\n },\n inter: {\n stack: '\"Inter\", system-ui, -apple-system, sans-serif',\n href: \"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap\",\n },\n poppins: {\n stack: '\"Poppins\", system-ui, sans-serif',\n href: \"https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap\",\n },\n montserrat: {\n stack: '\"Montserrat\", system-ui, sans-serif',\n href: \"https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap\",\n },\n lora: {\n stack: '\"Lora\", Georgia, serif',\n href: \"https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400;0,500;0,600;1,400&display=swap\",\n },\n cairo: {\n stack: '\"Cairo\", system-ui, sans-serif',\n href: \"https://fonts.googleapis.com/css2?family=Cairo:wght@400;500;600;700&display=swap\",\n },\n tajawal: {\n stack: '\"Tajawal\", system-ui, sans-serif',\n href: \"https://fonts.googleapis.com/css2?family=Tajawal:wght@400;500;700&display=swap\",\n },\n};\n\nconst COLOR_RE = /^(#([0-9a-f]{3,8})|rgba?\\(|hsla?\\(|color\\(|var\\()/i;\n\nfunction isColorValue(v: unknown): v is string {\n return typeof v === \"string\" && COLOR_RE.test(v.trim());\n}\n\nfunction isFontToken(v: unknown): v is string {\n return typeof v === \"string\" && Object.prototype.hasOwnProperty.call(FONT_REGISTRY, v);\n}\n\n/** Idempotently inject a webfont <link> into <head>. */\nfunction injectFontLink(href: string): void {\n if (typeof document === \"undefined\" || !href) return;\n const existing = document.querySelector(\n `link[data-numu-font][href=\"${href}\"]`,\n );\n if (existing) return;\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = href;\n link.setAttribute(\"data-numu-font\", \"\");\n document.head.appendChild(link);\n}\n\n/** Pure registry lookup — no webfont injection. */\nfunction lookupFontStack(value: string): string {\n return FONT_REGISTRY[value]?.stack ?? value;\n}\n\n/**\n * Resolve a font setting value to a CSS stack. Known tokens map through the\n * registry (and load the webfont); anything else is treated as a literal\n * family/stack the theme author supplied.\n */\nexport function resolveFontStack(value: string): string {\n const entry = FONT_REGISTRY[value];\n if (entry) {\n if (entry.href) injectFontLink(entry.href);\n return entry.stack;\n }\n return value;\n}\n\n/** Result of `computeGlobalStyleTokens` — everything a host needs to paint\n * global settings without a DOM. */\nexport interface ComputedStyleTokens {\n /** CSS custom properties to set on the theme's mount root. */\n cssVars: Record<string, string>;\n /** Google-Fonts stylesheet hrefs for any registry fonts in use. */\n fontHrefs: string[];\n}\n\n/**\n * Pure half of `applyGlobalStyleTokens`: compute the exact CSS custom\n * properties (and webfont hrefs) a settings object maps to, without touching\n * any DOM. This is what lets a host SERVER-render a theme with the same vars\n * the bundle applies on mount — both sides call this one function, so the\n * values cannot drift (drift = unstyled flash or hydration noise).\n *\n * Includes the explicit `heading_font` / `body_font` resolution that\n * `mountTheme` historically layered on top: any string value for those two\n * ids resolves through the registry (or passes verbatim) so a picked font\n * gets a real stack even when it isn't a known token.\n */\nexport function computeGlobalStyleTokens(\n globalSettings: GlobalSettings,\n): ComputedStyleTokens {\n const cssVars: Record<string, string> = {};\n const fontHrefs: string[] = [];\n if (!globalSettings || typeof globalSettings !== \"object\") {\n return { cssVars, fontHrefs };\n }\n\n const pushHref = (href?: string) => {\n if (href && !fontHrefs.includes(href)) fontHrefs.push(href);\n };\n\n for (const [key, value] of Object.entries(globalSettings)) {\n if (!key || key.startsWith(\"__\")) continue;\n\n // color_scheme / color_scheme_group → object of role:color\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n for (const [role, c] of Object.entries(value as Record<string, unknown>)) {\n if (isColorValue(c)) cssVars[`--scheme-${key}-${role}`] = c;\n }\n continue;\n }\n\n if (isColorValue(value)) {\n cssVars[`--theme-${key}`] = value.trim();\n const role = COLOR_ROLE_ALIASES[key];\n if (role) cssVars[`--theme-color-${role}`] = value.trim();\n continue;\n }\n\n if (isFontToken(value)) {\n const entry = FONT_REGISTRY[value];\n cssVars[`--theme-${key}`] = entry.stack;\n const role = FONT_ROLE_ALIASES[key];\n if (role) cssVars[`--theme-font-${role}`] = entry.stack;\n pushHref(entry.href);\n continue;\n }\n\n // Plain scalar (layout values like page_width \"1240px\", spacing, etc.).\n if (typeof value === \"string\" || typeof value === \"number\") {\n const v = String(value).trim();\n if (v) cssVars[`--theme-${key}`] = v;\n }\n }\n\n // Explicit heading/body resolution (formerly done by mountTheme's effect):\n // non-registry font names fall through the scalar branch verbatim above;\n // these two ids always get the resolved stack + webfont.\n for (const id of [\"heading_font\", \"body_font\"] as const) {\n const value = (globalSettings as Record<string, unknown>)[id];\n if (typeof value === \"string\" && value.trim()) {\n cssVars[`--theme-${id}`] = lookupFontStack(value);\n pushHref(FONT_REGISTRY[value]?.href);\n }\n }\n\n return { cssVars, fontHrefs };\n}\n\n/**\n * Map a store's global settings onto CSS custom properties on `el`. Call on\n * mount and on every `applyDraft` (live preview). No-op when `el` or the\n * settings are missing. Reserved `__`-prefixed keys (e.g. `__translations`)\n * are skipped. Thin DOM shell over `computeGlobalStyleTokens`.\n */\nexport function applyGlobalStyleTokens(\n globalSettings: GlobalSettings,\n el: HTMLElement | null | undefined,\n): void {\n if (!el || !globalSettings || typeof globalSettings !== \"object\") return;\n const { cssVars, fontHrefs } = computeGlobalStyleTokens(globalSettings);\n const style = el.style;\n for (const [prop, value] of Object.entries(cssVars)) {\n style.setProperty(prop, value);\n }\n for (const href of fontHrefs) injectFontLink(href);\n}\n","\"use client\";\n\n/**\n * `mountTheme(el, ctx, renderApp)` — the canonical V3 bundle entry helper.\n *\n * ## Why this exists\n *\n * Every theme bundle exports `mount(el, ctx): MountResult`. Historically each\n * theme hand-wrote that function, and the wiring it needs is non-trivial and\n * easy to get wrong:\n *\n * 1. **Forward the real catalog.** The host ships the page's products /\n * collections in `ctx.page.data` (home + listing routes) and the product\n * in `ctx.page.data.product` (PDP). A theme that doesn't pass these into\n * `NuMuProvider` (+ wrap the PDP in `<ProductProvider>`) sees\n * `useProducts()` / `useProductOptional()` return empty on a REAL store —\n * so product sections render \"No products yet\" or fall back to demo data\n * on a stocked merchant. This was the single most common BYOT bug:\n * only bon-younes wired it; the other 13 themes dropped the catalog.\n *\n * 2. **Apply global style tokens.** Merchant-chosen colors/fonts live in\n * `themeSettings.global_settings`; they only paint if the bundle calls\n * `applyGlobalStyleTokens` on its mount root (and resolves font tokens\n * to real stacks + injects the webfont link). Themes that skipped this\n * ignored every color/font picker.\n *\n * 3. **Forward navigation.** `useNavigation(handle)` only resolves the\n * header/footer menus the host pre-resolved if the bundle passes\n * `ctx.navigation` into `NuMuProvider`.\n *\n * 4. **Live-preview + lifecycle.** The customizer streams draft settings via\n * the host's `applyDraft`; the bundle must hold them in state and re-paint\n * the style tokens on every draft. And it must return a `MountResult`\n * (`cleanup` + `applyDraft`) the host's `ByotThemeBoundary` understands.\n *\n * `mountTheme` does all of that once, so a theme's `main.tsx` collapses to:\n *\n * ```tsx\n * import { mountTheme } from \"@numueg/theme-sdk\";\n * export function mount(el, ctx) {\n * return mountTheme(el, ctx, ({ currentTemplate }) =>\n * <ThemeApp currentTemplate={currentTemplate} />,\n * );\n * }\n * ```\n *\n * The theme owns only its section list (`ThemeApp`). Everything in the list\n * above is handled here — fix it once, every theme benefits.\n *\n * ## Both ctx shapes\n *\n * The host (numu-storefront `ByotThemeBoundary`) passes\n * `{ themeSettings, storeData, page, locale, demo, navigation }`. Older / dev\n * contexts used `{ store, currentTemplate }`. We normalise both so a bundle\n * built against this helper works regardless of which host calls it.\n */\n\nimport {\n StrictMode,\n forwardRef,\n useEffect,\n useImperativeHandle,\n useState,\n type ReactElement,\n type ReactNode,\n} from \"react\";\nimport { createRoot, hydrateRoot, type Root } from \"react-dom/client\";\n\nimport { NuMuProvider } from \"./components/NuMuProvider\";\nimport { ProductProvider } from \"./components/ProductProvider\";\nimport { applyGlobalStyleTokens } from \"./utils/styleTokens\";\nimport type {\n Store,\n Cart,\n Customer,\n Product,\n Collection,\n} from \"./types/entities\";\nimport type { ThemeSettingsV3, MountResult } from \"./types/theme\";\nimport type { MenuItemData } from \"./contexts\";\n\n/** Minimal page descriptor the host forwards in the mount context. */\nexport interface ThemeMountPage {\n type?: string;\n handle?: string;\n title?: string;\n data?: Record<string, unknown>;\n}\n\n/**\n * The mount context a host (or dev harness) passes to a bundle's `mount`.\n * Accepts both the current storefront shape (`storeData`/`page`) and the\n * legacy/dev shape (`store`/`currentTemplate`); `mountTheme` normalises them.\n */\nexport interface ThemeMountContext {\n // Current storefront contract\n storeData?: Store;\n page?: ThemeMountPage;\n // Legacy / dev contract\n store?: Store;\n currentTemplate?: string;\n // Common\n themeSettings: ThemeSettingsV3;\n initialCart?: Cart;\n customer?: Customer | null;\n locale?: string;\n translations?: Record<string, string>;\n /** AUTHORITATIVE marketplace-preview flag from the host (true only for the\n * catalog \"Try theme\" preview). Themes with demo-image fallbacks gate on\n * it so a real installed store never shows demo imagery. */\n demo?: boolean;\n /** Store navigation menus keyed by handle, resolved server-side. */\n navigation?: Record<string, MenuItemData[]>;\n /**\n * Host signal that the container already holds server-rendered HTML for\n * this exact ctx (produced via `createApp` from `defineThemeEntry`).\n * `mountTheme` then adopts it with `hydrateRoot` instead of re-rendering\n * from scratch. Ignored when the container is empty, so a host can pass\n * it optimistically and still get a plain client mount on SSR failure.\n */\n hydrate?: boolean;\n [extra: string]: unknown;\n}\n\n/** Arguments handed to a theme's render callback on every (re)render. */\nexport interface ThemeRenderArgs {\n /** Active template key — \"home\" | \"product\" | \"collection\" | \"cart\" | … */\n currentTemplate: string;\n /** Marketplace-preview flag (see ThemeMountContext.demo). */\n demo: boolean;\n /** The raw host page descriptor (type/handle/data), or null. */\n page: ThemeMountPage | null;\n /** Normalised store record (never undefined). */\n store: Store;\n /** Live theme settings (reflects customizer drafts via applyDraft). */\n themeSettings: ThemeSettingsV3;\n}\n\ninterface DraftHandle {\n applyDraft: (next: ThemeSettingsV3) => void;\n}\n\n/** Normalise the two ctx shapes' store slot; never return undefined — SDK\n * code reads `store.currency` without optional chaining and would throw.\n * Also maps the storefront's snake_case `default_currency` onto `currency`\n * when the latter is missing (pre-0.3 scaffolds did this per-theme; doing\n * it here keeps server render and client hydrate byte-identical). */\nfunction pickStore(ctx: ThemeMountContext): Store {\n const s = ctx.storeData ?? ctx.store;\n if (s) {\n const raw = s as Store & { default_currency?: string };\n if (!raw.currency && raw.default_currency) {\n return { ...raw, currency: raw.default_currency };\n }\n return s;\n }\n return {\n id: \"unknown\",\n name: \"Store\",\n slug: \"store\",\n currency: \"EGP\",\n default_language: \"en\",\n use_nextjs_storefront: true,\n } as Store;\n}\n\n/** Resolve the active template from either contract, defaulting to \"home\". */\nfunction pickTemplate(ctx: ThemeMountContext): string {\n if (typeof ctx.currentTemplate === \"string\" && ctx.currentTemplate) {\n return ctx.currentTemplate;\n }\n const pageType = ctx.page?.type;\n if (typeof pageType === \"string\" && pageType) return pageType;\n return \"home\";\n}\n\n/** Resolve the demo flag: explicit host flag wins; else infer from empty\n * templates (the marketplace preview ships none → render bundled preset). */\nfunction pickDemo(ctx: ThemeMountContext, themeSettings: ThemeSettingsV3): boolean {\n if (typeof ctx.demo === \"boolean\") return ctx.demo;\n const t = themeSettings.templates;\n return !t || Object.keys(t).length === 0;\n}\n\n/**\n * Bridge that holds live draft settings, re-applies global style tokens on\n * every change, and wires the full provider stack (catalog + nav) around the\n * theme's app. Exposes `applyDraft` so the host can stream customizer edits.\n */\nconst ThemeMountBridge = forwardRef<\n DraftHandle,\n {\n ctx: ThemeMountContext;\n /** Null when rendered off-DOM (`createApp` for server rendering); the\n * style-token effect is a no-op there — the host SSRs the same vars\n * via `computeGlobalStyleTokens`. */\n mountEl: HTMLElement | null;\n renderApp: (args: ThemeRenderArgs) => ReactNode;\n }\n>(function ThemeMountBridge({ ctx, mountEl, renderApp }, ref) {\n const [themeSettings, setThemeSettings] = useState<ThemeSettingsV3>(\n ctx.themeSettings,\n );\n useImperativeHandle(\n ref,\n () => ({\n applyDraft: (next) =>\n setThemeSettings((prev) => (prev === next ? prev : next)),\n }),\n [],\n );\n\n // Global settings (colors/fonts/layout) → CSS custom properties on the\n // mount root. Re-runs on every draft so the customizer's live preview\n // re-paints as a merchant drags a color or picks a font.\n // (applyGlobalStyleTokens resolves heading/body fonts to real stacks and\n // injects webfont links — see computeGlobalStyleTokens, which is the\n // single source of truth shared with hosts that SSR these vars.)\n useEffect(() => {\n if (!mountEl) return;\n const gs = (themeSettings.global_settings ?? {}) as Record<string, unknown>;\n applyGlobalStyleTokens(gs, mountEl);\n }, [themeSettings, mountEl]);\n\n const store = pickStore(ctx);\n const template = pickTemplate(ctx);\n const demo = pickDemo(ctx, themeSettings);\n\n // Real catalog the host forwards: home/listing routes ship\n // page.data.{products,collections}; the PDP ships page.data.product.\n // Feeding these into NuMuProvider (+ ProductProvider) is what makes\n // useProducts()/useProduct() return the merchant's ACTUAL catalog.\n const pageData = (ctx.page?.data ?? {}) as {\n products?: Product[];\n collections?: Collection[];\n product?: Product;\n };\n\n const app = renderApp({\n currentTemplate: template,\n demo,\n page: ctx.page ?? null,\n store,\n themeSettings,\n });\n\n return (\n <NuMuProvider\n store={store}\n themeSettings={themeSettings}\n initialCart={ctx.initialCart}\n customer={ctx.customer}\n locale={ctx.locale}\n translations={ctx.translations}\n navigation={ctx.navigation}\n initialProducts={pageData.products}\n initialCollections={pageData.collections}\n currentTemplate={template}\n >\n {pageData.product ? (\n <ProductProvider product={pageData.product}>{app}</ProductProvider>\n ) : (\n app\n )}\n </NuMuProvider>\n );\n});\n\n/**\n * Build the canonical theme element tree for a ctx. BOTH render paths go\n * through here — `mountTheme` (client mount/hydrate) and `createApp`\n * (host-side `renderToString`) — so the server markup and the hydration\n * tree are the same React tree by construction. `mountEl` is a prop, not\n * DOM output, so it differing between server (null) and client (the\n * container) cannot cause a hydration mismatch.\n */\nexport function buildThemeElement(\n ctx: ThemeMountContext,\n mountEl: HTMLElement | null,\n renderApp: (args: ThemeRenderArgs) => ReactNode,\n ref?: (h: DraftHandle | null) => void,\n): ReactElement {\n return (\n <StrictMode>\n <ThemeMountBridge ctx={ctx} mountEl={mountEl} renderApp={renderApp} ref={ref} />\n </StrictMode>\n );\n}\n\n/**\n * Mount a V3 theme. Owns the React root, the provider stack (catalog + nav +\n * style tokens), and the live-preview draft cycle. Returns the host-contract\n * `MountResult` (`cleanup` + `applyDraft`).\n *\n * When the host passes `ctx.hydrate === true` and the container already\n * holds server-rendered HTML (produced by this theme's `createApp` with the\n * identical ctx), the tree is adopted via `hydrateRoot` — no re-render, no\n * flash. An empty container downgrades to a plain client mount so hosts can\n * pass the flag optimistically.\n *\n * @param el the host-supplied container element\n * @param ctx the mount context (either host or legacy/dev shape)\n * @param renderApp returns the theme's section tree for the current args\n */\nexport function mountTheme(\n el: HTMLElement,\n ctx: ThemeMountContext,\n renderApp: (args: ThemeRenderArgs) => ReactNode,\n): MountResult {\n const handleRef = { current: null as DraftHandle | null };\n const element = buildThemeElement(ctx, el, renderApp, (h) => {\n handleRef.current = h;\n });\n\n const shouldHydrate = ctx.hydrate === true && el.firstElementChild !== null;\n let root: Root;\n if (shouldHydrate) {\n root = hydrateRoot(el, element);\n } else {\n root = createRoot(el);\n root.render(element);\n }\n\n return {\n applyDraft: (next) => handleRef.current?.applyDraft(next),\n cleanup: () => {\n root.unmount();\n handleRef.current = null;\n },\n };\n}\n","\"use client\";\n\n/**\n * `defineThemeEntry(renderApp)` — one-call theme entry that yields BOTH\n * halves of the V3 contract from a single component:\n *\n * - `mount(el, ctx)` — the client entry every host already calls\n * (now hydration-aware via `ctx.hydrate`).\n * - `createApp(ctx)` — the same React tree as a plain element, so the\n * host can `renderToString(createApp(ctx))` on the\n * server and ship real HTML before any JS runs.\n *\n * ```tsx\n * // src/main.tsx\n * import { defineThemeEntry } from \"@numueg/theme-sdk\";\n *\n * const entry = defineThemeEntry(({ currentTemplate }) => (\n * <ThemeApp currentTemplate={currentTemplate} />\n * ));\n *\n * export const mount = entry.mount;\n * export const createApp = entry.createApp;\n * ```\n *\n * Why both MUST come from one definition: hydration only succeeds when the\n * server markup and the client tree are identical. Routing both through\n * `buildThemeElement` makes that true by construction — a theme cannot\n * accidentally ship a `createApp` that disagrees with its `mount`.\n *\n * Themes that only export `mount` keep working exactly as before; they are\n * simply never server-rendered (the host detects the missing `createApp`\n * and falls back to today's client-only mount).\n */\n\nimport type { ReactElement, ReactNode } from \"react\";\n\nimport {\n buildThemeElement,\n mountTheme,\n type ThemeMountContext,\n type ThemeRenderArgs,\n} from \"./mount\";\nimport type { MountResult } from \"./types/theme\";\n\n/** The pair of entry points a V3 theme bundle exports. */\nexport interface ThemeEntry {\n /** Client entry — host contract `mount(el, ctx): MountResult`. */\n mount: (el: HTMLElement, ctx: ThemeMountContext) => MountResult;\n /**\n * Server entry — returns the exact element tree `mount` would render,\n * for host-side `renderToString`. Must stay side-effect free: no DOM\n * access happens until React effects run (which they don't on the\n * server).\n */\n createApp: (ctx: ThemeMountContext) => ReactElement;\n}\n\nexport function defineThemeEntry(\n renderApp: (args: ThemeRenderArgs) => ReactNode,\n): ThemeEntry {\n return {\n mount: (el, ctx) => mountTheme(el, ctx, renderApp),\n createApp: (ctx) => buildThemeElement(ctx, null, renderApp),\n };\n}\n","\"use client\";\nimport type { ReactNode } from \"react\";\nimport { CollectionContext } from \"../contexts\";\nimport type { Collection } from \"../types/entities\";\n\ninterface CollectionProviderProps {\n collection: Collection;\n children: ReactNode;\n}\n\nexport function CollectionProvider({ collection, children }: CollectionProviderProps) {\n return <CollectionContext.Provider value={collection}>{children}</CollectionContext.Provider>;\n}\n","\"use client\";\n\nimport { createElement, type ElementType, type ReactNode } from \"react\";\nimport { useLocalization } from \"../hooks/useLocalization\";\nimport { useShop } from \"../hooks/useShop\";\n\ninterface MoneyProps {\n /** Amount in major units (e.g. dollars, not cents). */\n amount: number;\n /** ISO-4217 currency code. Defaults to the active store's currency. */\n currency?: string;\n /**\n * When the same product has both a sale price and a compare-at price,\n * pass the higher (compare-at) value here and we'll render it with a\n * strike-through next to the active price. Skipped when undefined or\n * <= the main amount.\n */\n compareAt?: number;\n className?: string;\n /** Custom HTML element tag — defaults to `span`. */\n as?: ElementType;\n}\n\n/**\n * <Money amount={49.99} /> — formatted price, locale-aware.\n *\n * Wraps useLocalization().formatMoney so theme code stops re-implementing\n * Intl.NumberFormat. Renders inline with `dir=\"auto\"` so the digits\n * flow naturally in RTL (Arabic) without flipping the currency symbol.\n *\n * Usage:\n * <Money amount={product.price} compareAt={product.compare_at_price} />\n */\nexport function Money({\n amount,\n currency,\n compareAt,\n className,\n as = \"span\",\n}: MoneyProps) {\n const { formatMoney } = useLocalization();\n const shop = useShop();\n const ccy = currency || shop?.currency;\n const showCompare = compareAt != null && compareAt > amount;\n\n const children: ReactNode[] = [\n <span key=\"amt\">{formatMoney(amount, ccy)}</span>,\n ];\n if (showCompare) {\n children.push(\" \");\n children.push(\n <s key=\"cmp\" style={{ opacity: 0.6 }}>\n {formatMoney(compareAt, ccy)}\n </s>,\n );\n }\n\n return createElement(\n as,\n { className, dir: \"auto\" },\n children,\n );\n}\n","import type { CSSProperties } from \"react\";\n\n/**\n * Non-destructive image framing transform (focal / zoom / rotation).\n *\n * An image setting value may carry optional `transform` metadata\n * (`{ url, alt, transform }`). The original asset is never modified — the\n * storefront reproduces the framing purely from these numbers via CSS, so the\n * SAME uploaded image can be framed differently per placement (hero vs card).\n *\n * Hoisted into the SDK (was duplicated in every theme's `_shared.ts` and in\n * the merchant-hub editor's `imageTransform.ts`). The editor copy MUST stay\n * equivalent so its preview matches the storefront render exactly.\n */\nexport interface ImageTransform {\n v: 1;\n focal?: { x: number; y: number }; // 0..1, default center\n zoom?: number; // 1..4, default 1\n rotation?: number; // degrees, default 0\n fit?: \"cover\" | \"contain\";\n}\n\nconst _clampT = (n: number, lo: number, hi: number): number =>\n Math.min(hi, Math.max(lo, Number.isFinite(n) ? n : lo));\n\n/** Read the transform off an image setting value (string | {url,alt,transform}). */\nexport function asImageTransform(v: unknown): ImageTransform | undefined {\n if (v && typeof v === \"object\" && \"transform\" in v) {\n const t = (v as { transform?: unknown }).transform;\n if (t && typeof t === \"object\") return t as ImageTransform;\n }\n return undefined;\n}\n\n/**\n * CSS reproducing the transform on an `<img>` that fills a fixed-aspect,\n * overflow-hidden frame. Default fit is `cover` (Shopify-style: the image\n * fills its frame, cropping to the focal point) — pass `\"contain\"` only for\n * placements that must show the whole image (e.g. a logo). Empty object when\n * there is no transform AND the caller wants the section's own className to\n * decide; pass an explicit `fit` to force a default even without a transform.\n */\nexport function applyImageTransform(\n t: ImageTransform | undefined | null,\n fit: \"cover\" | \"contain\" = \"cover\",\n): CSSProperties {\n if (!t) return { objectFit: fit };\n const fx = Math.round(_clampT(t.focal?.x ?? 0.5, 0, 1) * 1e4) / 100;\n const fy = Math.round(_clampT(t.focal?.y ?? 0.5, 0, 1) * 1e4) / 100;\n const zoom = _clampT(t.zoom ?? 1, 1, 4);\n const rot = (((t.rotation ?? 0) % 360) + 360) % 360;\n const effFit = t.fit ?? fit;\n const style: CSSProperties = {\n transform: `scale(${zoom}) rotate(${rot}deg)`,\n transformOrigin: `${fx}% ${fy}%`,\n objectFit: effFit,\n };\n if (effFit === \"cover\") style.objectPosition = `${fx}% ${fy}%`;\n return style;\n}\n\n/**\n * focalSrc — build a URL for a server-side, focal-point-aware image transform.\n *\n * OPT-IN helper. A theme that wants a bandwidth-efficient SMART CROP for a big\n * image (typically a hero) calls this to point the <img src> at the storefront's\n * `/api/image-transform` endpoint with focal/aspect params. The endpoint honors\n * them only when Cloudflare Image Resizing is enabled on the zone\n * (NUMU_CF_IMAGE_RESIZING=1); otherwise it gracefully ignores them and serves a\n * plain resized image — so the theme's CSS `applyImageTransform` framing remains\n * the correctness baseline either way. This is purely a perf optimization.\n *\n * Returns a RELATIVE path (`/api/image-transform?...`) — the SDK runs\n * same-origin inside the storefront, matching how <Form>/useShop build URLs.\n *\n * @example\n * <img\n * src={focalSrc(hero.url, { width: 1600, focal: t?.focal, aspect: \"16/9\" })}\n * style={applyImageTransform(t, \"cover\")} // CSS still frames as fallback\n * />\n */\nexport interface FocalSrcOptions {\n /** Target width in px (e.g. 1600 for a desktop hero). Required for a crop. */\n width?: number;\n /** Focal point, normalized 0..1 (0.5,0.5 = center). */\n focal?: { x?: number; y?: number };\n /** Target aspect ratio \"W/H\" (e.g. \"16/9\"); drives the crop box height. */\n aspect?: string;\n /** Crop mode. Default \"cover\". */\n fit?: \"cover\" | \"contain\";\n /** Quality 1..100. */\n quality?: number;\n /** Output format. */\n format?: \"webp\" | \"avif\" | \"jpeg\" | \"jpg\" | \"png\";\n}\n\nconst clamp01 = (n: number) => Math.min(1, Math.max(0, n));\n\nexport function focalSrc(\n url: string | null | undefined,\n options: FocalSrcOptions = {},\n): string {\n if (!url) return \"\";\n // data: URIs and already-transformed URLs pass through untouched.\n if (url.startsWith(\"data:\") || /[?&](fp-x|fp-y)=/.test(url)) return url;\n\n const p = new URLSearchParams();\n p.set(\"url\", url);\n if (options.width) p.set(\"w\", String(Math.round(options.width)));\n if (options.focal?.x != null) p.set(\"fp-x\", String(clamp01(options.focal.x)));\n if (options.focal?.y != null) p.set(\"fp-y\", String(clamp01(options.focal.y)));\n if (options.aspect) p.set(\"ar\", options.aspect);\n if (options.fit) p.set(\"fit\", options.fit);\n if (options.quality) p.set(\"q\", String(Math.min(100, Math.max(1, Math.round(options.quality)))));\n if (options.format) p.set(\"f\", options.format.toLowerCase());\n\n return `/api/image-transform?${p.toString()}`;\n}\n","\"use client\";\n\nimport type { CSSProperties, ImgHTMLAttributes } from \"react\";\nimport { applyImageTransform, type ImageTransform } from \"../utils/imageTransform\";\n\ninterface ImageProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, \"src\" | \"srcSet\"> {\n src: string | undefined | null;\n alt: string;\n /**\n * Comma-separated breakpoints for the `sizes` attribute. Default\n * matches a typical responsive grid:\n * \"(min-width: 1024px) 25vw, (min-width: 640px) 50vw, 100vw\"\n */\n sizes?: string;\n /**\n * When true (default), generate a `srcSet` with several widths.\n * Disable for above-the-fold hero images where you want a single\n * source under direct theme control.\n */\n responsive?: boolean;\n /**\n * Loading strategy. Default \"lazy\" matches Shopify themes; pass\n * \"eager\" for above-the-fold imagery.\n */\n loading?: \"eager\" | \"lazy\";\n /**\n * Shopify-style frame. When set (e.g. \"3/4\", \"16/9\", \"1/1\") the image is\n * wrapped in a fixed-aspect, overflow-hidden box and the `<img>` fills it.\n * Combined with `objectFit=\"cover\"` (the default) this guarantees the image\n * ALWAYS fits its frame — no letterboxing, no overflow — cropping to the\n * focal point. Omit to render a bare `<img>` (legacy behavior).\n */\n aspectRatio?: string;\n /**\n * How the image fills its box. Default \"cover\" (fill + crop) — the merchant\n * never sees a letterboxed/squashed image. Use \"contain\" for logos/badges\n * that must show in full.\n */\n objectFit?: \"cover\" | \"contain\" | \"fill\" | \"scale-down\" | \"none\";\n /** CSS object-position (e.g. \"50% 50%\"). Ignored if `transform` is set. */\n objectPosition?: string;\n /**\n * Non-destructive focal/zoom/rotation metadata from the image setting value\n * (`asImageTransform(setting)`). When present it drives object-fit +\n * object-position + scale/rotate so the editor preview and the live render\n * match exactly. Overrides `objectFit`/`objectPosition`.\n */\n transform?: ImageTransform | null;\n}\n\nconst DEFAULT_WIDTHS = [320, 480, 640, 768, 1024, 1280, 1600, 1920];\n\n/**\n * Build a srcSet string from a base image URL by appending a width\n * query param. Works for any CDN that honors `?w=` (R2 image-resizing,\n * Cloudflare Images, Imgix-compatibles). Hosts that ignore the param\n * just serve the original; not a regression.\n *\n * If the URL already has query params we preserve them; if it already\n * has a width directive we pass through unchanged (assume the theme\n * author knows what they want).\n */\nfunction buildSrcSet(src: string, widths: number[] = DEFAULT_WIDTHS): string {\n if (/[?&]w=\\d+/.test(src)) return \"\";\n const sep = src.includes(\"?\") ? \"&\" : \"?\";\n return widths.map((w) => `${src}${sep}w=${w} ${w}w`).join(\", \");\n}\n\n/**\n * <Image> — drop-in replacement for `<img>` with srcSet + lazy loading\n * defaults. Themes should use this everywhere they'd otherwise write a\n * raw `<img>` so merchant-uploaded images get responsive variants and\n * lazy loading without per-section work.\n *\n * If `src` is empty/null, renders a placeholder div so the layout\n * doesn't shift while a merchant configures images in the customizer.\n */\nexport function Image({\n src,\n alt,\n sizes = \"(min-width: 1024px) 25vw, (min-width: 640px) 50vw, 100vw\",\n responsive = true,\n loading = \"lazy\",\n aspectRatio,\n objectFit,\n objectPosition,\n transform,\n className,\n style,\n ...rest\n}: ImageProps) {\n // Frame mode: a fixed-aspect, overflow-hidden wrapper the <img> fills. This\n // is what guarantees \"the image always fits its frame\" regardless of the\n // uploaded image's own aspect ratio.\n const framed = Boolean(aspectRatio);\n\n if (!src) {\n const placeholder = (\n <div\n className={framed ? undefined : className}\n role=\"img\"\n aria-label={alt}\n style={{\n backgroundColor: \"rgba(0,0,0,0.05)\",\n display: \"block\",\n width: \"100%\",\n height: framed ? \"100%\" : undefined,\n ...(framed ? {} : style),\n }}\n />\n );\n if (!framed) return placeholder;\n return (\n <span\n className={className}\n style={{ display: \"block\", aspectRatio, overflow: \"hidden\", ...style }}\n >\n {placeholder}\n </span>\n );\n }\n\n const srcSet = responsive ? buildSrcSet(src) : undefined;\n\n // Resolve the fit styling. An explicit transform wins (focal/zoom/rotate).\n // Inside a frame, default to cover so the image always fills it. Without a\n // frame, only apply a fit when the caller explicitly asked — preserving the\n // legacy bare-<img> behavior (and never overriding a className like\n // `object-contain` with an inline style).\n const effFit = objectFit ?? (framed ? \"cover\" : undefined);\n const fitStyle: CSSProperties = transform\n ? applyImageTransform(transform, effFit === \"contain\" ? \"contain\" : \"cover\")\n : {\n ...(effFit ? { objectFit: effFit } : {}),\n ...(objectPosition ? { objectPosition } : {}),\n };\n\n const img = (\n <img\n src={src}\n alt={alt}\n srcSet={srcSet || undefined}\n sizes={srcSet ? sizes : undefined}\n loading={loading}\n decoding=\"async\"\n className={framed ? undefined : className}\n style={\n framed\n ? { width: \"100%\", height: \"100%\", display: \"block\", ...fitStyle }\n : { ...fitStyle, ...style }\n }\n {...rest}\n />\n );\n\n if (!framed) return img;\n return (\n <span\n className={className}\n style={{\n display: \"block\",\n position: \"relative\",\n width: \"100%\",\n aspectRatio,\n overflow: \"hidden\",\n ...style,\n }}\n >\n {img}\n </span>\n );\n}\n","\"use client\";\n\nimport type { AnchorHTMLAttributes, ReactNode } from \"react\";\nimport { useShop } from \"../hooks/useShop\";\n\ninterface LinkProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, \"href\"> {\n /**\n * Path relative to the storefront root, e.g. \"/products/foo\",\n * \"/collections/all\", \"/cart\", \"/pages/about\". External URLs (with\n * a protocol) are passed through unchanged.\n */\n to: string;\n children: ReactNode;\n}\n\nconst ABSOLUTE_URL = /^[a-z]+:|^\\/\\//i;\n\n/**\n * Route-aware <Link>. Themes write paths as `/products/<slug>` (matches\n * the production subdomain root). The storefront proxy rewrites those\n * under `/<subdomain>/...` in dev path-segment routing; in production\n * the subdomain hostname does the same job at the edge.\n *\n * For plain anchor behavior — server-rendered HTML, full page nav — we\n * just emit a regular `<a>`. Themes that want client-side transitions\n * can wrap this in their own router-aware component; in practice\n * storefront pages are SSR'd so a full nav is fine and predictable.\n *\n * External URLs (have a protocol or start with `//`) pass through\n * unchanged so social-media links, CDN paths, etc. work without\n * special casing.\n */\nexport function Link({ to, children, ...rest }: LinkProps) {\n const shop = useShop();\n const isAbsolute = ABSOLUTE_URL.test(to);\n let href = to;\n if (!isAbsolute && shop && !to.startsWith(\"/\")) {\n // Relative paths like \"products/foo\" treated as siblings of current.\n // Most themes use leading slashes; this is a defensive fallback.\n href = `/${to}`;\n }\n return (\n <a href={href} {...rest}>\n {children}\n </a>\n );\n}\n","\"use client\";\n\nimport { useState, type ButtonHTMLAttributes, type ReactNode } from \"react\";\nimport { useCart } from \"../hooks/useCart\";\nimport type { Product, ProductVariant } from \"../types/entities\";\n\ninterface AddToCartButtonProps\n extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"onClick\" | \"disabled\"> {\n product: Product;\n variant?: ProductVariant;\n quantity?: number;\n /** Custom labels — fallbacks are English defaults. */\n label?: ReactNode;\n loadingLabel?: ReactNode;\n soldOutLabel?: ReactNode;\n errorLabel?: ReactNode;\n /** Called after successful addition. Useful for analytics events. */\n onAdded?: (product: Product, variant?: ProductVariant) => void;\n}\n\n/**\n * Themed Add-to-Cart button with built-in loading/disabled/error states.\n *\n * Wraps useCart().addItem and tracks its own UX state machine:\n * idle → adding → idle (or → error briefly, then idle)\n *\n * Renders a regular `<button>` so themes style it with whatever class\n * names they want — we only own the disabled/aria-busy logic and label\n * swaps. If the variant (or product) is out of stock, button is\n * disabled and shows soldOutLabel.\n *\n * Doesn't trap navigation — for \"buy now\" flows that should redirect\n * to checkout, themes wrap this in their own `<a>` after onAdded.\n */\nexport function AddToCartButton({\n product,\n variant,\n quantity = 1,\n label = \"Add to cart\",\n loadingLabel = \"Adding…\",\n soldOutLabel = \"Sold out\",\n errorLabel = \"Couldn't add — try again\",\n onAdded,\n ...rest\n}: AddToCartButtonProps) {\n const { addItem } = useCart();\n const [state, setState] = useState<\"idle\" | \"adding\" | \"error\">(\"idle\");\n\n const inStock = variant?.in_stock ?? product.in_stock;\n if (!inStock) {\n return (\n <button\n type=\"button\"\n disabled\n aria-disabled=\"true\"\n {...rest}\n >\n {soldOutLabel}\n </button>\n );\n }\n\n async function handleClick() {\n if (state === \"adding\") return;\n setState(\"adding\");\n try {\n await addItem(product.id, variant?.id, quantity);\n setState(\"idle\");\n onAdded?.(product, variant);\n } catch {\n setState(\"error\");\n // Auto-clear after 2s so the merchant can try again.\n setTimeout(() => setState(\"idle\"), 2000);\n }\n }\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={state === \"adding\"}\n aria-busy={state === \"adding\"}\n {...rest}\n >\n {state === \"adding\"\n ? loadingLabel\n : state === \"error\"\n ? errorLabel\n : label}\n </button>\n );\n}\n","\"use client\";\n\nimport {\n Component,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\n\ninterface SectionProps extends HTMLAttributes<HTMLElement> {\n /** Section instance id (the order key in templates). Required for the\n * customizer's click-to-select to work. */\n id: string;\n /** Section type as registered in the theme registry / schemas. */\n type: string;\n /** Section group id (header / footer / announcement-bar) when this\n * section is mounted inside a group rather than a page template. */\n groupId?: string;\n /** Override the fallback shown when this section throws. Defaults to\n * a small inline error card (visible to the merchant in the customizer,\n * invisible to live shoppers — see CSS comment below). */\n errorFallback?: ReactNode;\n children: ReactNode;\n}\n\n// ── Section ErrorBoundary ───────────────────────────────────────────────────\n//\n// One thrown section used to take down the whole bundle's React tree —\n// every other section unmounted along with the bad one, leaving the\n// merchant with a blank storefront and no way to find the offender.\n//\n// We catch render/lifecycle errors at the per-section seam so a bug in\n// \"Hero v2\" doesn't break the perfectly fine \"Newsletter\" section\n// rendered on the same page. The boundary:\n//\n// 1. Logs the error + section context to console.error so the dev\n// console makes the offender obvious.\n// 2. Re-renders a fallback (defaults to a small error card; theme\n// can override via the `errorFallback` prop).\n// 3. Posts `numu:editor:section-error` to window.parent so the V3\n// customizer can highlight the offending section in its tree.\n//\n// The boundary is INSIDE the `<section data-section-id>` wrapper, so\n// the data attributes still let the customizer click-select the bad\n// section even when its body crashed — merchants can delete it.\n\ninterface BoundaryState {\n error: Error | null;\n}\n\ninterface SectionErrorBoundaryProps {\n sectionId: string;\n sectionType: string;\n fallback: ReactNode;\n children: ReactNode;\n}\n\nclass SectionErrorBoundary extends Component<\n SectionErrorBoundaryProps,\n BoundaryState\n> {\n state: BoundaryState = { error: null };\n\n static getDerivedStateFromError(error: Error): BoundaryState {\n return { error };\n }\n\n componentDidCatch(error: Error) {\n // Match the host's <ByotThemeBoundary> log shape so the prefix is\n // recognizable in the iframe console even when both boundaries fire.\n console.error(\n `[Section ${this.props.sectionType}#${this.props.sectionId}] threw:`,\n error,\n );\n if (typeof window !== \"undefined\" && window.parent !== window) {\n try {\n window.parent.postMessage(\n {\n type: \"numu:editor:section-error\",\n payload: {\n sectionId: this.props.sectionId,\n sectionType: this.props.sectionType,\n message: error.message,\n },\n },\n \"*\",\n );\n } catch {\n // Cross-origin postMessage with `*` is permissive enough that\n // this branch is for true edge cases (sandboxed iframe with\n // disallow-script). Nothing useful to do.\n }\n }\n }\n\n render() {\n if (this.state.error) return this.props.fallback;\n return this.props.children;\n }\n}\n\nfunction defaultSectionFallback(\n sectionType: string,\n sectionId: string,\n): ReactNode {\n return (\n <div\n role=\"alert\"\n data-numu-section-error=\"true\"\n style={{\n padding: \"1rem\",\n border: \"1px dashed #f87171\",\n background: \"#fef2f2\",\n color: \"#b91c1c\",\n fontFamily:\n \"system-ui, -apple-system, BlinkMacSystemFont, sans-serif\",\n fontSize: \"0.875rem\",\n lineHeight: 1.5,\n borderRadius: \"0.375rem\",\n margin: \"0.5rem 0\",\n }}\n >\n <div style={{ fontWeight: 600, marginBottom: \"0.25rem\" }}>\n Section failed to render\n </div>\n <div style={{ opacity: 0.9 }}>\n <code style={{ fontFamily: \"monospace\" }}>{sectionType}</code> threw\n an error. Check the browser console for details.\n </div>\n <div\n style={{\n opacity: 0.6,\n fontSize: \"0.75rem\",\n marginTop: \"0.25rem\",\n fontFamily: \"monospace\",\n }}\n >\n section #{sectionId}\n </div>\n </div>\n );\n}\n\n/**\n * <Section> — wrapper that emits the `data-section-id` / `data-section-type`\n * attributes the storefront's PreviewBridge needs to relay clicks back\n * to the V3 customizer for \"select section X\" navigation.\n *\n * Use this around the top-level element of every section component:\n *\n * export default function Hero({ settings, ...sectionMeta }) {\n * return (\n * <Section id={sectionMeta.id} type=\"hero\">\n * <h1>{settings.headline}</h1>\n * </Section>\n * );\n * }\n *\n * Without `data-section-id` on a real DOM ancestor, clicking anywhere\n * in the section in the customizer iframe falls through to the page\n * background and the merchant has to use the section list panel to\n * select sections — slow and confusing.\n *\n * Errors thrown by `children` are caught by an internal ErrorBoundary\n * so one bad section doesn't unmount its siblings. Customize the\n * fallback via `errorFallback`.\n */\nexport function Section({\n id,\n type,\n groupId,\n errorFallback,\n children,\n ...rest\n}: SectionProps) {\n return (\n <section\n data-section-id={id}\n data-section-type={type}\n data-group-id={groupId}\n {...rest}\n >\n <SectionErrorBoundary\n sectionId={id}\n sectionType={type}\n fallback={errorFallback ?? defaultSectionFallback(type, id)}\n >\n {children}\n </SectionErrorBoundary>\n </section>\n );\n}\n\ninterface BlockProps extends HTMLAttributes<HTMLDivElement> {\n /** Block instance id within its parent section. */\n id: string;\n type: string;\n /** Override the fallback shown when this block throws. */\n errorFallback?: ReactNode;\n children: ReactNode;\n}\n\n/**\n * <Block> — analog to <Section> for nested block selection. Same DOM\n * attribute contract; PreviewBridge reads `data-block-id` and reports\n * the block as selected when its child clicks bubble up.\n *\n * Wraps `children` in the same per-instance ErrorBoundary as <Section>\n * so a bad block within a section isolates its failure.\n */\nexport function Block({ id, type, errorFallback, children, ...rest }: BlockProps) {\n return (\n <div data-block-id={id} data-block-type={type} {...rest}>\n <SectionErrorBoundary\n sectionId={id}\n sectionType={type}\n fallback={errorFallback ?? defaultSectionFallback(type, id)}\n >\n {children}\n </SectionErrorBoundary>\n </div>\n );\n}\n","\"use client\";\n\nimport {\n useState,\n type FormEvent,\n type FormHTMLAttributes,\n type ReactNode,\n} from \"react\";\n\ninterface FormProps\n extends Omit<\n FormHTMLAttributes<HTMLFormElement>,\n \"onSubmit\" | \"method\" | \"action\" | \"children\" | \"onError\"\n > {\n /**\n * Endpoint to POST/etc. the form values to. Should be one of the\n * storefront's `/api/*` proxy routes — they handle CSRF + cookie\n * forwarding + idempotency on the way to FastAPI.\n */\n action: string;\n /**\n * HTTP method. POST is the typical theme use-case (newsletter,\n * contact, customer login, address create). GET is supported for\n * search-style forms.\n */\n method?: \"POST\" | \"GET\" | \"PUT\" | \"DELETE\";\n /**\n * Called with the JSON-decoded response body on success. Use to\n * trigger a toast, redirect, etc. Theme owns the UX.\n */\n onSuccess?: (response: unknown) => void;\n /**\n * Called with the Error on failure. Falls through to the default\n * error label otherwise.\n */\n onError?: (error: Error) => void;\n /**\n * Render-prop access to the in-flight state if the theme wants to\n * show its own loading / disabled / error UI. Default `children`\n * behavior just lets the form's inputs and submit button render —\n * we don't impose styling.\n */\n children?:\n | ReactNode\n | ((state: { submitting: boolean; error: Error | null }) => ReactNode);\n}\n\nconst ABSOLUTE_URL = /^[a-z]+:|^\\/\\//i;\n\nfunction readCsrfCookie(): string | null {\n if (typeof document === \"undefined\") return null;\n const m = document.cookie.match(/(?:^|;\\s*)numu_csrf=([^;]+)/);\n return m ? decodeURIComponent(m[1]) : null;\n}\n\nfunction newIdempotencyKey(): string {\n if (typeof crypto !== \"undefined\" && \"randomUUID\" in crypto) {\n return crypto.randomUUID();\n }\n return `${Date.now()}-${Math.random().toString(36).slice(2)}`;\n}\n\n/**\n * <Form action=\"/api/cart/add\" method=\"POST\" onSuccess={...}>\n *\n * Theme-friendly wrapper around `<form>` that handles:\n * - CSRF: reads `numu_csrf` cookie, sends as `x-numu-csrf` header on\n * every mutating request. Same wire format as <NuMuProvider>'s\n * cart machinery — interoperates seamlessly.\n * - Idempotency: mints a UUID per submit, sends as\n * `x-numu-idempotency-key`. Backend dedupes if it supports the\n * header (cart endpoints today; more later).\n * - Submit lifecycle: tracks `submitting` + `error` state and\n * either passes them to a render-prop child or wires them to a\n * submit-button's `disabled` automatically.\n * - Throws away page navigation: `onSubmit` calls preventDefault and\n * fetches via JSON. Themes that want classic POST-and-navigate\n * can drop down to a plain `<form>`.\n *\n * Refuses to submit to absolute URLs (must point at the storefront\n * itself or an `/api/*` proxy) so a misconfigured theme can't leak\n * customer data to a third party origin.\n */\nexport function Form({\n action,\n method = \"POST\",\n onSuccess,\n onError,\n children,\n ...rest\n}: FormProps) {\n const [submitting, setSubmitting] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n async function handleSubmit(e: FormEvent<HTMLFormElement>) {\n e.preventDefault();\n\n if (ABSOLUTE_URL.test(action)) {\n const err = new Error(\n `<Form action> must be a same-origin path (got \"${action}\"). ` +\n `Use a /api/* proxy route or your route handler.`,\n );\n setError(err);\n onError?.(err);\n return;\n }\n\n setSubmitting(true);\n setError(null);\n try {\n const formData = new FormData(e.currentTarget);\n const isMutation = method !== \"GET\";\n\n // Convert FormData → JSON. Themes can pass `data-numu-multipart=\"true\"`\n // on the form to opt into multipart instead (file uploads).\n const isMultipart =\n e.currentTarget.dataset?.numuMultipart === \"true\";\n\n const headers: Record<string, string> = {};\n if (!isMultipart) headers[\"Content-Type\"] = \"application/json\";\n if (isMutation) {\n const csrf = readCsrfCookie();\n if (csrf) headers[\"x-numu-csrf\"] = csrf;\n headers[\"x-numu-idempotency-key\"] = newIdempotencyKey();\n }\n\n let url = action;\n let body: BodyInit | undefined;\n if (method === \"GET\") {\n const params = new URLSearchParams();\n for (const [k, v] of formData.entries()) {\n if (typeof v === \"string\") params.append(k, v);\n }\n const sep = action.includes(\"?\") ? \"&\" : \"?\";\n url = `${action}${sep}${params.toString()}`;\n } else if (isMultipart) {\n body = formData;\n } else {\n const obj: Record<string, FormDataEntryValue> = {};\n for (const [k, v] of formData.entries()) obj[k] = v;\n body = JSON.stringify(obj);\n }\n\n const res = await fetch(url, { method, headers, body });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(\n `${method} ${action} failed: ${res.status} ${res.statusText}${\n text ? ` — ${text.slice(0, 200)}` : \"\"\n }`,\n );\n }\n const json = res.headers\n .get(\"content-type\")\n ?.includes(\"application/json\")\n ? await res.json()\n : await res.text();\n onSuccess?.(json);\n } catch (err) {\n const e2 = err instanceof Error ? err : new Error(String(err));\n setError(e2);\n onError?.(e2);\n } finally {\n setSubmitting(false);\n }\n }\n\n return (\n <form\n onSubmit={handleSubmit}\n method={method}\n action={action}\n aria-busy={submitting}\n {...rest}\n >\n {typeof children === \"function\"\n ? children({ submitting, error })\n : children}\n </form>\n );\n}\n","\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport type { Product } from \"../types/entities\";\nimport { Image } from \"./Image\";\nimport { Money } from \"./Money\";\nimport { Link } from \"./Link\";\nimport { AddToCartButton } from \"./AddToCartButton\";\n\n/**\n * Opinionated product tile.\n *\n * Themes drop this anywhere a product list is needed — collection\n * pages, search results, recommendations, recently-viewed grids.\n * Renders image + title + price (with compare-at strike-through when\n * present) + an optional \"Sold out\" badge + AddToCartButton.\n *\n * The component is **unstyled by default** — it ships only structural\n * markup with stable class names. Themes provide the CSS. Class names\n * use a `numu-product-card__*` BEM convention so themes can target\n * pieces without grep-and-replace if NUMU later renames anything.\n *\n * Class hooks:\n * .numu-product-card — root <article>\n * .numu-product-card__link — wrapping <a>\n * .numu-product-card__media — image container\n * .numu-product-card__image — the <img> itself\n * .numu-product-card__badge — \"Sold out\" overlay\n * .numu-product-card__title — title <h3>\n * .numu-product-card__price — price wrapper\n * .numu-product-card__cta — CTA wrapper (AddToCartButton)\n *\n * Themes can override any piece by passing `slots`:\n * <ProductCard product={p} slots={{ price: <CustomPrice /> }} />\n *\n * For deeper customization, themes should compose the primitives\n * (Image / Money / Link / AddToCartButton) directly instead.\n */\nexport interface ProductCardSlots {\n /** Replaces the badge area (default: \"Sold out\" when out of stock, else nothing). */\n badge?: ReactNode;\n /** Replaces the title `<h3>` block. */\n title?: ReactNode;\n /** Replaces the price `<Money>` block. */\n price?: ReactNode;\n /** Replaces the AddToCartButton. Pass `null` to hide it. */\n cta?: ReactNode | null;\n}\n\nexport interface ProductCardProps {\n product: Product;\n /** Override the link target. Default: `/products/{slug}`. */\n href?: string;\n className?: string;\n slots?: ProductCardSlots;\n /**\n * Image sizing hint for the responsive srcSet. Default: a 4-up grid\n * sizing (~25vw at desktop, ~50vw at tablet, ~100vw at mobile).\n * Override when rendering in a different layout density.\n */\n imageSizes?: string;\n}\n\nfunction joinClass(...names: Array<string | undefined | null | false>): string {\n return names.filter(Boolean).join(\" \");\n}\n\nexport function ProductCard({\n product,\n href,\n className,\n slots,\n imageSizes,\n}: ProductCardProps) {\n const target = href ?? `/products/${product.slug}`;\n const firstImage = product.images?.[0];\n const inStock = product.in_stock;\n\n const badge =\n slots?.badge !== undefined\n ? slots.badge\n : inStock\n ? null\n : (\n <span className=\"numu-product-card__badge\">Sold out</span>\n );\n\n return (\n <article className={joinClass(\"numu-product-card\", className)}>\n <Link to={target} className=\"numu-product-card__link\">\n <div className=\"numu-product-card__media\">\n <Image\n src={firstImage?.url}\n alt={firstImage?.alt || product.name}\n sizes={imageSizes}\n className=\"numu-product-card__image\"\n />\n {badge}\n </div>\n {slots?.title ?? (\n <h3 className=\"numu-product-card__title\">{product.name}</h3>\n )}\n {slots?.price ?? (\n <div className=\"numu-product-card__price\">\n <Money\n amount={product.price}\n compareAt={product.compare_at_price}\n currency={product.currency}\n />\n </div>\n )}\n </Link>\n {slots?.cta === null\n ? null\n : (\n <div className=\"numu-product-card__cta\">\n {slots?.cta ?? <AddToCartButton product={product} />}\n </div>\n )}\n </article>\n );\n}\n","\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport type { Collection } from \"../types/entities\";\nimport { Image } from \"./Image\";\nimport { Link } from \"./Link\";\n\n/**\n * Opinionated collection tile.\n *\n * Renders a single collection's hero image + name + product count.\n * Used by collection-list sections, footer \"Featured collections\"\n * blocks, and search-result mixed views.\n *\n * Unstyled by default; themes ship the CSS. Class hooks:\n * .numu-collection-card — root <article>\n * .numu-collection-card__link — wrapping <a>\n * .numu-collection-card__media — image container\n * .numu-collection-card__image — the <img>\n * .numu-collection-card__title — title <h3>\n * .numu-collection-card__count — product count line\n */\nexport interface CollectionCardSlots {\n title?: ReactNode;\n /** Replaces the \"N products\" line. Pass null to hide it. */\n count?: ReactNode | null;\n}\n\nexport interface CollectionCardProps {\n collection: Collection;\n /** Override the link target. Default: `/collections/{slug}`. */\n href?: string;\n className?: string;\n slots?: CollectionCardSlots;\n imageSizes?: string;\n}\n\nfunction joinClass(...names: Array<string | undefined | null | false>): string {\n return names.filter(Boolean).join(\" \");\n}\n\nexport function CollectionCard({\n collection,\n href,\n className,\n slots,\n imageSizes,\n}: CollectionCardProps) {\n const target = href ?? `/collections/${collection.slug}`;\n const productCount =\n typeof collection.product_count === \"number\"\n ? collection.product_count\n : undefined;\n\n return (\n <article className={joinClass(\"numu-collection-card\", className)}>\n <Link to={target} className=\"numu-collection-card__link\">\n <div className=\"numu-collection-card__media\">\n <Image\n src={collection.image_url}\n alt={collection.name}\n sizes={imageSizes}\n className=\"numu-collection-card__image\"\n />\n </div>\n {slots?.title ?? (\n <h3 className=\"numu-collection-card__title\">{collection.name}</h3>\n )}\n {slots?.count === null\n ? null\n : (slots?.count ?? (\n productCount !== undefined && (\n <p className=\"numu-collection-card__count\">\n {productCount === 1 ? \"1 product\" : `${productCount} products`}\n </p>\n )\n ))}\n </Link>\n </article>\n );\n}\n","\"use client\";\n\nimport { useEffect, useMemo, useState } from \"react\";\n\n/**\n * <RichText html=... /> — sanitized HTML renderer.\n *\n * Wraps `dangerouslySetInnerHTML` so theme code stops calling it\n * directly with merchant-supplied content. Themes that need to render\n * rich-text fields (product descriptions, page bodies, blog articles,\n * policy bodies) go through this so an XSS in a single field can't\n * cross-contaminate the whole storefront.\n *\n * **Why a built-in allowlist sanitizer instead of DOMPurify?**\n * The audit plan called for DOMPurify, but adding it as a hard dep\n * inflates every theme bundle by ~12KB gzipped — and the merchant-\n * editable surface is small enough (a fixed set of formatting tags +\n * links + images) that a curated allowlist is both smaller AND easier\n * to reason about. If a theme needs richer sanitization (embeds,\n * iframes, MathML), it can import DOMPurify directly and pre-sanitize\n * before passing the result here.\n *\n * Allowed tags:\n * p, br, hr, h1-h6, blockquote, pre, code,\n * strong, b, em, i, u, s, sub, sup, mark,\n * ul, ol, li, dl, dt, dd,\n * a (href, target, rel only),\n * img (src, alt, width, height, loading only — http(s) URLs only),\n * table, thead, tbody, tr, th, td,\n * span, div (with class attribute only).\n *\n * Stripped:\n * <script>, <style>, <iframe>, <object>, <embed>, <link>, <meta>,\n * form/input, on*= handlers, javascript:/data: URLs, srcset on\n * <img> (we let the storefront's image-transform handle that\n * uniformly).\n */\nexport interface RichTextProps {\n html: string | null | undefined;\n className?: string;\n /** Element to render — defaults to `<div>`. Use `<article>` for body content. */\n as?: \"div\" | \"article\" | \"section\" | \"aside\";\n}\n\nconst ALLOWED_TAGS: ReadonlySet<string> = new Set([\n \"p\", \"br\", \"hr\",\n \"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\",\n \"blockquote\", \"pre\", \"code\",\n \"strong\", \"b\", \"em\", \"i\", \"u\", \"s\", \"sub\", \"sup\", \"mark\",\n \"ul\", \"ol\", \"li\", \"dl\", \"dt\", \"dd\",\n \"a\", \"img\",\n \"table\", \"thead\", \"tbody\", \"tr\", \"th\", \"td\",\n \"span\", \"div\",\n]);\n\nconst ALLOWED_ATTRS_BY_TAG: Record<string, ReadonlySet<string>> = {\n a: new Set([\"href\", \"target\", \"rel\", \"class\", \"title\"]),\n img: new Set([\"src\", \"alt\", \"width\", \"height\", \"loading\", \"class\"]),\n span: new Set([\"class\"]),\n div: new Set([\"class\"]),\n p: new Set([\"class\"]),\n h1: new Set([\"class\"]), h2: new Set([\"class\"]), h3: new Set([\"class\"]),\n h4: new Set([\"class\"]), h5: new Set([\"class\"]), h6: new Set([\"class\"]),\n blockquote: new Set([\"class\"]),\n pre: new Set([\"class\"]),\n code: new Set([\"class\"]),\n ul: new Set([\"class\"]), ol: new Set([\"class\"]), li: new Set([\"class\"]),\n table: new Set([\"class\"]),\n thead: new Set([\"class\"]), tbody: new Set([\"class\"]),\n tr: new Set([\"class\"]), th: new Set([\"class\"]), td: new Set([\"class\"]),\n};\n\nconst URL_SAFE_PROTOCOLS = /^(https?|mailto|tel):/i;\n\nfunction isSafeUrl(url: string): boolean {\n const trimmed = url.trim();\n if (!trimmed) return false;\n // Relative paths are fine.\n if (trimmed.startsWith(\"/\") || trimmed.startsWith(\"#\") || trimmed.startsWith(\"?\")) {\n return true;\n }\n // Protocol-bearing — only http/https/mailto/tel.\n return URL_SAFE_PROTOCOLS.test(trimmed);\n}\n\n/**\n * Sanitize an HTML string against the allowlist above. Runs server-\n * AND client-side because rich-text fields are server-rendered for SEO.\n *\n * Implementation note: We use DOMParser when available (browser) for\n * structural correctness; on server we fall through a regex-based\n * pass that handles the common formatting tags + escapes everything\n * else. The server pass is intentionally conservative — themes that\n * need server-rendered rich content with edge-case structure should\n * sanitize on the API tier and pass the sanitized HTML through\n * `bypassSanitize` (escape hatch below).\n */\nexport function sanitizeHtml(input: string): string {\n if (!input) return \"\";\n if (typeof window === \"undefined\" || typeof DOMParser === \"undefined\") {\n return sanitizeHtmlServer(input);\n }\n return sanitizeHtmlClient(input);\n}\n\nfunction sanitizeHtmlClient(input: string): string {\n const doc = new DOMParser().parseFromString(\n `<div>${input}</div>`,\n \"text/html\",\n );\n const root = doc.body.firstElementChild;\n if (!root) return \"\";\n walk(root);\n return root.innerHTML;\n}\n\nfunction walk(node: Element): void {\n const children = Array.from(node.children);\n for (const child of children) {\n const tag = child.tagName.toLowerCase();\n if (!ALLOWED_TAGS.has(tag)) {\n // Replace forbidden tag with its sanitized text content. Drops\n // entire subtree if the tag is one we never want (script/style).\n if (tag === \"script\" || tag === \"style\" || tag === \"iframe\" || tag === \"object\" || tag === \"embed\") {\n child.remove();\n } else {\n const text = child.textContent || \"\";\n child.replaceWith(document.createTextNode(text));\n }\n continue;\n }\n // Strip disallowed attributes.\n const allowed = ALLOWED_ATTRS_BY_TAG[tag] || new Set<string>();\n for (const attr of Array.from(child.attributes)) {\n const name = attr.name.toLowerCase();\n // on*= handlers → always strip.\n if (name.startsWith(\"on\")) {\n child.removeAttribute(attr.name);\n continue;\n }\n if (!allowed.has(name)) {\n child.removeAttribute(attr.name);\n continue;\n }\n // URL-bearing attrs → protocol-check.\n if ((name === \"href\" || name === \"src\") && !isSafeUrl(attr.value)) {\n child.removeAttribute(attr.name);\n continue;\n }\n }\n // Anchor hardening: every external link gets rel=\"noopener noreferrer\"\n // when target=\"_blank\" is set. Stops reverse-tabnabbing without the\n // theme dev having to remember.\n if (tag === \"a\" && child.getAttribute(\"target\") === \"_blank\") {\n child.setAttribute(\"rel\", \"noopener noreferrer\");\n }\n walk(child);\n }\n}\n\n/**\n * Server-side fallback. We don't have a DOM here, so we do an\n * HTML-entity-escape and unescape only the allowed inline formatting\n * tags. This is conservative — block-level tags work but with limited\n * attribute support.\n */\nfunction sanitizeHtmlServer(input: string): string {\n // Strip dangerous blocks entirely.\n let s = input\n .replace(/<script[\\s\\S]*?<\\/script>/gi, \"\")\n .replace(/<style[\\s\\S]*?<\\/style>/gi, \"\")\n .replace(/<iframe[\\s\\S]*?<\\/iframe>/gi, \"\")\n .replace(/<object[\\s\\S]*?<\\/object>/gi, \"\")\n .replace(/<embed[\\s\\S]*?<\\/embed>/gi, \"\")\n .replace(/<link[\\s\\S]*?>/gi, \"\")\n .replace(/<meta[\\s\\S]*?>/gi, \"\");\n // Strip on*= attrs.\n s = s.replace(/\\s+on\\w+\\s*=\\s*(\"[^\"]*\"|'[^']*'|[^\\s>]+)/gi, \"\");\n // Strip javascript:/data: in href/src.\n s = s.replace(\n /\\s+(href|src)\\s*=\\s*(\"[^\"]*\"|'[^']*'|[^\\s>]+)/gi,\n (full, attr, val) => {\n const cleaned = String(val).replace(/^['\"]|['\"]$/g, \"\");\n return isSafeUrl(cleaned) ? full : \"\";\n },\n );\n return s;\n}\n\nexport function RichText({ html, className, as = \"div\" }: RichTextProps) {\n // Hydration-stable two-pass sanitize: the FIRST client render must produce\n // the same string the server produced, so when the theme is server-rendered\n // (`createApp` + hydrateRoot) the dangerouslySetInnerHTML payloads match.\n // The regex pass and the DOMParser pass can legitimately differ on edge\n // cases (attribute ordering, entity normalisation), so we render the\n // server-algorithm output first everywhere and upgrade to the structural\n // DOMParser sanitize after mount.\n const [domReady, setDomReady] = useState(false);\n useEffect(() => {\n setDomReady(true);\n }, []);\n const safe = useMemo(\n () => (domReady ? sanitizeHtml(html || \"\") : sanitizeHtmlServer(html || \"\")),\n [html, domReady],\n );\n if (!safe) return null;\n const Tag = as;\n return (\n <Tag\n className={className}\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{ __html: safe }}\n />\n );\n}\n","\"use client\";\n\nimport { useCallback } from \"react\";\nimport { useCurrency } from \"../hooks/useCurrency\";\n\n/**\n * <CurrencySwitcher /> — wired in Phase 6.\n *\n * Reads presentment currencies + the persisted selection from\n * `useCurrency()`, which talks to\n * `/api/storefront/store/{id}/currencies`. Changing the dropdown\n * writes the `numu_currency` cookie via the hook, which then\n * propagates to `<Money>`'s display.\n *\n * Renders nothing when the store offers only one currency — themes\n * can drop the component into a layout without conditional render.\n *\n * Pass `render` to take over the markup completely (e.g. a custom\n * dropdown component or a flag-icon grid).\n */\n\nexport interface CurrencySwitcherProps {\n className?: string;\n onSelect?: (currency: string) => void;\n render?: (state: {\n currencies: string[];\n current: string;\n onChange: (next: string) => void;\n }) => React.ReactNode;\n}\n\nexport function CurrencySwitcher({\n className,\n onSelect,\n render,\n}: CurrencySwitcherProps) {\n const { presentment, selected, setSelected, loading } = useCurrency();\n\n const handleChange = useCallback(\n (next: string) => {\n if (next === selected) return;\n setSelected(next);\n onSelect?.(next);\n },\n [selected, setSelected, onSelect],\n );\n\n // No alternatives, or still loading the list. We don't want to\n // briefly flash a 1-option dropdown while the API resolves.\n if (loading) return null;\n if (presentment.length <= 1) return null;\n\n if (render) {\n return (\n <>\n {render({\n currencies: presentment,\n current: selected,\n onChange: handleChange,\n })}\n </>\n );\n }\n\n return (\n <select\n className={className ?? \"numu-currency-switcher\"}\n value={selected}\n onChange={(e) => handleChange(e.target.value)}\n aria-label=\"Currency\"\n >\n {presentment.map((c) => (\n <option key={c} value={c}>\n {c}\n </option>\n ))}\n </select>\n );\n}\n","\"use client\";\n\nimport { useCallback } from \"react\";\nimport { useShop } from \"../hooks/useShop\";\nimport { useLocalization } from \"../hooks/useLocalization\";\n\n/**\n * <LocaleSwitcher /> — language toggle for stores with multiple locales.\n *\n * v1 supports Arabic + English (the storefront's default_language gates\n * which one is the \"primary\"). This component:\n * - Reads `store.available_locales` (or falls back to\n * [default_language, \"en\"] for stores that haven't been migrated yet).\n * - Renders nothing when there's only one locale.\n * - On change, sets a `numu_locale` cookie + reloads the page so the\n * server-rendered layout picks up the new locale (the storefront\n * middleware reads the cookie and stamps `<html lang/dir>`\n * accordingly).\n *\n * Why a hard reload instead of client-side state swap:\n * Locale impacts SSR-rendered content (currency formatting, product\n * field translations, page metadata). Client-side toggling would\n * leave the SSR output inconsistent until the next navigation.\n * One reload trades a brief flicker for guaranteed correctness.\n */\n\nconst LANG_LABELS: Record<string, string> = {\n ar: \"العربية\",\n en: \"English\",\n fr: \"Français\",\n he: \"עברית\",\n fa: \"فارسی\",\n ur: \"اردو\",\n es: \"Español\",\n de: \"Deutsch\",\n};\n\nexport interface LocaleSwitcherProps {\n className?: string;\n onSelect?: (locale: string) => void;\n /** Custom renderer. Receives the resolved locale list + current selection. */\n render?: (state: {\n locales: string[];\n current: string;\n labelFor: (code: string) => string;\n onChange: (next: string) => void;\n }) => React.ReactNode;\n}\n\nexport function LocaleSwitcher({\n className,\n onSelect,\n render,\n}: LocaleSwitcherProps) {\n const shop = useShop();\n const { locale } = useLocalization();\n const available =\n (shop as unknown as { available_locales?: string[] }).available_locales || [];\n // Fallback for stores that don't yet expose available_locales: assume\n // the store's default_language plus English when they differ.\n const list =\n available.length > 0\n ? available\n : shop.default_language === \"en\"\n ? [\"en\"]\n : Array.from(new Set([shop.default_language, \"en\"]));\n\n const labelFor = useCallback((code: string): string => {\n return LANG_LABELS[code] || code.toUpperCase();\n }, []);\n\n const handleChange = useCallback(\n (next: string) => {\n if (next === locale) return;\n onSelect?.(next);\n if (typeof document !== \"undefined\") {\n const oneYear = 60 * 60 * 24 * 365;\n document.cookie = `numu_locale=${encodeURIComponent(next)}; path=/; max-age=${oneYear}; samesite=lax`;\n }\n // Hard reload so SSR re-runs with the new locale. Use replace()\n // so the locale toggle doesn't pollute browser back history.\n if (typeof window !== \"undefined\") {\n window.location.reload();\n }\n },\n [locale, onSelect],\n );\n\n if (list.length <= 1) return null;\n\n if (render) {\n return <>{render({ locales: list, current: locale, labelFor, onChange: handleChange })}</>;\n }\n\n return (\n <select\n className={className ?? \"numu-locale-switcher\"}\n value={locale}\n onChange={(e) => handleChange(e.target.value)}\n aria-label=\"Language\"\n >\n {list.map((l) => (\n <option key={l} value={l}>\n {labelFor(l)}\n </option>\n ))}\n </select>\n );\n}\n","\"use client\";\n\n/**\n * <EditableText> / <EditableImage> — V3 SDK editor-affordance markers.\n *\n * These are the \"I want to edit this\" hooks for V3 themes. They render\n * a normal element (span / img) on live storefronts, but inside the\n * customizer iframe they:\n *\n * 1. Stamp a `data-numu-editable` attribute so the storefront's\n * PreviewBridge can scope click-to-select to specific fields\n * (rather than the whole section).\n * 2. Show a subtle hover affordance (dotted underline / ring) so the\n * merchant discovers what's editable inline.\n * 3. Bubble up a `numu:editor:select-field` postMessage on click,\n * so the dashboard can scroll the matching setting input into\n * view + focus it.\n *\n * Editor mode is detected the same way PreviewBridge does — query\n * params `editor=v3` OR `preview=true`. Outside the editor, these are\n * pass-through `<span>` / `<img>` with no extra cost.\n *\n * Usage in a V3 section:\n *\n * import { EditableText, EditableImage } from \"@numueg/theme-sdk\";\n *\n * export default function Hero({ instance }: SectionProps) {\n * const { settings } = instance;\n * return (\n * <>\n * <EditableText\n * settingId=\"headline\"\n * sectionId={instance.id}\n * value={settings.headline}\n * as=\"h1\"\n * className=\"text-4xl\"\n * />\n * <EditableImage\n * settingId=\"hero_image\"\n * sectionId={instance.id}\n * src={settings.hero_image}\n * alt={settings.image_alt}\n * />\n * </>\n * );\n * }\n *\n * Why two components instead of one polymorphic `<Editable>`? Text and\n * image have different click semantics (text → focus the matching\n * setting; image → open the media picker) and different DOM shapes,\n * and we want the JSX to read naturally. Future field types (link,\n * color picker, video) get their own component pair.\n */\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useState,\n type ElementType,\n type HTMLAttributes,\n type ImgHTMLAttributes,\n type ReactNode,\n} from \"react\";\n\n// ─── Editor-mode detection ──────────────────────────────────────────────────\n\n/**\n * The detection runs lazily (after mount) to keep SSR HTML identical\n * to the first client paint. If we read window.location during render,\n * we'd return false on the server and true on the client → hydration\n * mismatch. By gating on a useEffect-set state, the initial paint\n * never adds editor-only attributes, and they appear on the second\n * paint (one tick later, after the bridge is awake anyway).\n */\nfunction useIsEditor(): boolean {\n const [isEditor, setIsEditor] = useState(false);\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n try {\n const params = new URLSearchParams(window.location.search);\n const flag =\n params.get(\"editor\") === \"v3\" || params.get(\"preview\") === \"true\";\n // The iframe-only check: the merchant's customizer renders this\n // bundle inside an iframe. On a \"plain\" preview tab (no parent\n // window), we keep the editor-mode markers off — they'd be\n // useless to a merchant browsing their own storefront in a\n // separate tab.\n const inFrame = window.parent !== window;\n setIsEditor(flag && inFrame);\n } catch {\n // No-op — SSR / sandboxed environments fall through to false.\n }\n }, []);\n return isEditor;\n}\n\n/**\n * Post a \"this field was clicked\" event to the dashboard so the editor\n * can scroll the matching setting input into view + focus it.\n *\n * Origin is `*` because the parent's origin varies (dev / staging /\n * prod / different merchant subdomains). The dashboard side enforces\n * origin matching for INBOUND messages from the iframe, so an\n * attacker can't spoof a select-field event by hijacking\n * postMessage — the dashboard's origin gate drops anything not from\n * the storefront's exact origin.\n */\nfunction postFieldSelected(\n sectionId: string,\n settingId: string,\n blockId?: string | null,\n): void {\n if (typeof window === \"undefined\") return;\n if (window.parent === window) return;\n try {\n window.parent.postMessage(\n {\n type: \"numu:editor:select-field\",\n payload: {\n sectionId,\n blockId: blockId ?? null,\n settingId,\n },\n },\n \"*\",\n );\n } catch {\n /* parent gone / sandboxed strictly — no-op */\n }\n}\n\n// ─── EditableText ───────────────────────────────────────────────────────────\n\nexport interface EditableTextProps\n extends Omit<HTMLAttributes<HTMLElement>, \"children\"> {\n /** The section instance id (key inside templates.<page>.sections). */\n sectionId: string;\n /** Optional block id when the field lives inside a section block. */\n blockId?: string | null;\n /** The setting key from the section's schema (e.g. \"headline\"). */\n settingId: string;\n /** The current text value (may be HTML for inline_richtext settings). */\n value: string | undefined | null;\n /**\n * Element to render. Defaults to `<span>` so the component is\n * inline-compatible. Pass \"h1\" / \"h2\" / \"p\" / \"div\" for block-level\n * usage.\n */\n as?: ElementType;\n /**\n * Set to true to render the value as HTML (for inline_richtext\n * settings whose stored form is `<b>Welcome</b>`). Defaults to false\n * — plain-text fields are rendered as a text node.\n */\n html?: boolean;\n /** Empty-state placeholder shown when value is \"\" / null. */\n placeholder?: ReactNode;\n}\n\nexport const EditableText = forwardRef<HTMLElement, EditableTextProps>(\n function EditableText(\n {\n sectionId,\n blockId,\n settingId,\n value,\n as: Component = \"span\",\n html = false,\n placeholder,\n className,\n onClick,\n style,\n ...rest\n },\n ref,\n ) {\n const isEditor = useIsEditor();\n\n const handleClick = useCallback(\n (e: React.MouseEvent<HTMLElement>) => {\n // Forward the click first so themes that wired their own\n // handler keep working.\n onClick?.(e);\n if (!isEditor) return;\n // The whole point: route the click to the matching setting\n // input. Stop propagation only when the editor is open so we\n // don't double-fire the section-level click-to-select handler\n // that PreviewBridge installs at the document level. Themes\n // can still receive the click via their own onClick prop\n // (already invoked above).\n e.stopPropagation();\n postFieldSelected(sectionId, settingId, blockId);\n },\n [isEditor, onClick, sectionId, settingId, blockId],\n );\n\n const editorAttrs = useMemo(\n () =>\n isEditor\n ? {\n \"data-numu-editable\": \"text\",\n \"data-numu-section-id\": sectionId,\n \"data-numu-setting-id\": settingId,\n \"data-numu-block-id\": blockId ?? undefined,\n role: \"button\" as const,\n tabIndex: 0,\n }\n : {},\n [isEditor, sectionId, settingId, blockId],\n );\n\n const effectiveStyle = isEditor\n ? {\n ...style,\n cursor: \"text\" as const,\n // Subtle dotted underline so the merchant discovers what's\n // editable. The dashed style + inherited color keeps the\n // affordance from clashing with the theme's typography.\n textDecoration: \"underline dotted rgba(99, 102, 241, 0.7)\",\n textUnderlineOffset: \"4px\",\n }\n : style;\n\n const isEmpty = value == null || value === \"\";\n const display = isEmpty && placeholder !== undefined ? placeholder : value ?? \"\";\n\n if (html && typeof display === \"string\") {\n return (\n <Component\n ref={ref}\n className={className}\n style={effectiveStyle}\n onClick={handleClick}\n dangerouslySetInnerHTML={{ __html: display }}\n {...editorAttrs}\n {...rest}\n />\n );\n }\n return (\n <Component\n ref={ref}\n className={className}\n style={effectiveStyle}\n onClick={handleClick}\n {...editorAttrs}\n {...rest}\n >\n {display}\n </Component>\n );\n },\n);\n\n// ─── EditableImage ──────────────────────────────────────────────────────────\n\nexport interface EditableImageProps\n extends Omit<ImgHTMLAttributes<HTMLImageElement>, \"src\"> {\n sectionId: string;\n blockId?: string | null;\n settingId: string;\n /** Image src — may be empty/undefined if the merchant hasn't picked one yet. */\n src: string | undefined | null;\n /** Placeholder src shown when `src` is empty. Defaults to a 1x1 transparent gif. */\n emptyPlaceholderSrc?: string;\n}\n\nconst EMPTY_GIF =\n \"data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==\";\n\nexport const EditableImage = forwardRef<HTMLImageElement, EditableImageProps>(\n function EditableImage(\n {\n sectionId,\n blockId,\n settingId,\n src,\n alt,\n emptyPlaceholderSrc,\n className,\n onClick,\n style,\n ...rest\n },\n ref,\n ) {\n const isEditor = useIsEditor();\n const isEmpty = !src;\n\n const handleClick = useCallback(\n (e: React.MouseEvent<HTMLImageElement>) => {\n onClick?.(e);\n if (!isEditor) return;\n e.stopPropagation();\n postFieldSelected(sectionId, settingId, blockId);\n },\n [isEditor, onClick, sectionId, settingId, blockId],\n );\n\n const editorAttrs = useMemo(\n () =>\n isEditor\n ? {\n \"data-numu-editable\": \"image\",\n \"data-numu-section-id\": sectionId,\n \"data-numu-setting-id\": settingId,\n \"data-numu-block-id\": blockId ?? undefined,\n role: \"button\" as const,\n tabIndex: 0,\n }\n : {},\n [isEditor, sectionId, settingId, blockId],\n );\n\n const effectiveStyle = isEditor\n ? {\n ...style,\n cursor: \"pointer\" as const,\n outline: isEmpty\n ? \"2px dashed rgba(99, 102, 241, 0.6)\"\n : \"2px dashed transparent\",\n outlineOffset: \"-2px\",\n }\n : style;\n\n const effectiveSrc = src || emptyPlaceholderSrc || EMPTY_GIF;\n const effectiveAlt = alt ?? \"\";\n\n return (\n <img\n ref={ref}\n src={effectiveSrc}\n alt={effectiveAlt}\n className={className}\n style={effectiveStyle}\n onClick={handleClick}\n {...editorAttrs}\n {...rest}\n />\n );\n },\n);\n","/**\n * Icon — the shared icon set for the `icon_picker` setting type.\n *\n * Names are the stored setting values. BOTH the merchant-hub editor's icon\n * grid AND themes render through this same map, so a picked icon looks\n * identical in the customizer and on the storefront.\n *\n * We ship inline SVG (no icon-library dependency) on purpose: the SDK is the\n * host-provided runtime singleton, and keeping it dependency-free avoids\n * bundling an icon library into every storefront. Each entry below is the\n * inner markup of a 24×24 stroke icon; <Icon> wraps it with the shared\n * stroke attributes and sizing.\n *\n * ⚠️ KEEP IN SYNC with the editor's copy in\n * numo-merchant-hub/src/features/theme-editor-v3/components/inputs/SettingInputV3.tsx\n * (the ICON_DEFS in IconPickerButton). The keys are the contract between\n * the picker and this renderer — a name the picker offers must exist here\n * or the theme falls back to a neutral glyph.\n */\n\nexport const ICON_DEFS: Record<string, string> = {\n star: '<polygon points=\"12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2\"/>',\n heart:\n '<path d=\"M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.29 1.51 4.04 3 5.5l7 7Z\"/>',\n check: '<path d=\"M20 6 9 17l-5-5\"/>',\n \"check-circle\": '<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"m9 12 2 2 4-4\"/>',\n shield: '<path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10Z\"/>',\n \"shield-check\":\n '<path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10Z\"/><path d=\"m9 12 2 2 4-4\"/>',\n truck:\n '<path d=\"M10 17h4V5H2v12h3\"/><path d=\"M20 17h2v-3.34a4 4 0 0 0-1.17-2.83L19 9h-5v8h1\"/><circle cx=\"7.5\" cy=\"17.5\" r=\"2.5\"/><circle cx=\"17.5\" cy=\"17.5\" r=\"2.5\"/>',\n \"shopping-bag\":\n '<path d=\"M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4Z\"/><path d=\"M3 6h18\"/><path d=\"M16 10a4 4 0 0 1-8 0\"/>',\n \"shopping-cart\":\n '<circle cx=\"8\" cy=\"21\" r=\"1\"/><circle cx=\"19\" cy=\"21\" r=\"1\"/><path d=\"M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12\"/>',\n gift:\n '<rect x=\"3\" y=\"8\" width=\"18\" height=\"4\" rx=\"1\"/><path d=\"M12 8v13\"/><path d=\"M19 12v7a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-7\"/><path d=\"M7.5 8a2.5 2.5 0 0 1 0-5C9 3 10.5 4.5 12 8c1.5-3.5 3-5 4.5-5a2.5 2.5 0 0 1 0 5\"/>',\n tag: '<path d=\"M20.59 13.41 13.42 20.6a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82Z\"/><circle cx=\"7\" cy=\"7\" r=\"1\"/>',\n zap: '<polygon points=\"13 2 3 14 12 14 11 22 21 10 12 10 13 2\"/>',\n sparkles:\n '<path d=\"M12 3 13.9 9.2 20 11l-6.1 1.8L12 19l-1.9-6.2L4 11l6.1-1.8L12 3Z\"/><path d=\"M5 3v4\"/><path d=\"M3 5h4\"/><path d=\"M19 17v4\"/><path d=\"M17 19h4\"/>',\n flame:\n '<path d=\"M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.07-2.14-.22-4.05 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.15.43-2.29 1-3a2.5 2.5 0 0 0 2.5 2.5Z\"/>',\n leaf:\n '<path d=\"M11 20A7 7 0 0 1 9.8 6.1C15.5 5 17 4.48 19 2c1 2 2 4.18 2 8 0 5.5-4.78 10-10 10Z\"/><path d=\"M2 21c0-3 1.85-5.36 5.08-6\"/>',\n globe:\n '<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M2 12h20\"/><path d=\"M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10Z\"/>',\n \"map-pin\":\n '<path d=\"M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z\"/><circle cx=\"12\" cy=\"10\" r=\"3\"/>',\n phone:\n '<path d=\"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.36 1.9.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.91.34 1.85.57 2.81.7A2 2 0 0 1 22 16.92Z\"/>',\n mail:\n '<rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\"/><path d=\"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\"/>',\n clock: '<circle cx=\"12\" cy=\"12\" r=\"10\"/><polyline points=\"12 6 12 12 16 14\"/>',\n lock:\n '<rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\"/><path d=\"M7 11V7a5 5 0 0 1 10 0v4\"/>',\n headphones:\n '<path d=\"M3 14h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7a9 9 0 0 1 18 0v7a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3\"/>',\n percent:\n '<line x1=\"19\" x2=\"5\" y1=\"5\" y2=\"19\"/><circle cx=\"6.5\" cy=\"6.5\" r=\"2.5\"/><circle cx=\"17.5\" cy=\"17.5\" r=\"2.5\"/>',\n users:\n '<path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\"/><circle cx=\"9\" cy=\"7\" r=\"4\"/><path d=\"M22 21v-2a4 4 0 0 0-3-3.87\"/><path d=\"M16 3.13a4 4 0 0 1 0 7.75\"/>',\n home:\n '<path d=\"m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z\"/><polyline points=\"9 22 9 12 15 12 15 22\"/>',\n store:\n '<path d=\"M2 7l2-4h16l2 4\"/><path d=\"M4 7v13a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1V7\"/><path d=\"M2 7h20\"/><path d=\"M9 21v-6h6v6\"/>',\n bell:\n '<path d=\"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9\"/><path d=\"M10.3 21a1.94 1.94 0 0 0 3.4 0\"/>',\n camera:\n '<path d=\"M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z\"/><circle cx=\"12\" cy=\"13\" r=\"3\"/>',\n image:\n '<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" ry=\"2\"/><circle cx=\"9\" cy=\"9\" r=\"2\"/><path d=\"m21 15-3.09-3.09a2 2 0 0 0-2.82 0L6 21\"/>',\n smile:\n '<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M8 14s1.5 2 4 2 4-2 4-2\"/><line x1=\"9\" x2=\"9.01\" y1=\"9\" y2=\"9\"/><line x1=\"15\" x2=\"15.01\" y1=\"9\" y2=\"9\"/>',\n send: '<path d=\"m22 2-7 20-4-9-9-4Z\"/><path d=\"M22 2 11 13\"/>',\n \"message-circle\":\n '<path d=\"M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5Z\"/>',\n search: '<circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"m21 21-4.3-4.3\"/>',\n package:\n '<path d=\"M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z\"/><path d=\"m3.3 7 8.7 5 8.7-5\"/><path d=\"M12 22V12\"/>',\n award:\n '<circle cx=\"12\" cy=\"8\" r=\"6\"/><path d=\"M15.477 12.89 17 22l-5-3-5 3 1.523-9.11\"/>',\n coffee:\n '<path d=\"M10 2v2\"/><path d=\"M14 2v2\"/><path d=\"M6 2v2\"/><path d=\"M16 8a1 1 0 0 1 1 1v8a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1h14a4 4 0 1 1 0 8h-1\"/>',\n};\n\nexport const ICON_NAMES: string[] = Object.keys(ICON_DEFS);\n\n/** Public alias for the icon name → inner-SVG map. */\nexport const IconMap = ICON_DEFS;\n\nexport interface IconProps {\n /** Icon name from {@link ICON_NAMES}. Unknown names render a neutral glyph. */\n name: string;\n /** Pixel size (width === height). Defaults to 24. */\n size?: number | string;\n strokeWidth?: number;\n className?: string;\n /** Accessible label. When omitted the icon is treated as decorative. */\n title?: string;\n}\n\nconst FALLBACK = ICON_DEFS[\"check-circle\"];\n\n/**\n * Render an icon by name from the shared {@link ICON_DEFS} set. Inherits color\n * from `currentColor`, so set the parent's text color to recolor it.\n */\nexport function Icon({\n name,\n size = 24,\n strokeWidth = 2,\n className,\n title,\n}: IconProps) {\n const inner = ICON_DEFS[name] ?? FALLBACK;\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n role={title ? \"img\" : undefined}\n aria-hidden={title ? undefined : true}\n aria-label={title}\n dangerouslySetInnerHTML={{ __html: inner }}\n />\n );\n}\n","import type {\n ThemeSettingsV3,\n SectionGroup,\n SectionInstance,\n PageTemplate,\n} from \"../types/theme\";\n\n/**\n * Default theme id when neither the V3 payload nor the legacy `theme.base_theme`\n * is set. Sourced from the env at build time so it stays in sync with the\n * backend's `NUMU_DEFAULT_THEME_ID`.\n *\n * Read once: SDK code that runs in browsers can't read env at runtime, but\n * tsup inlines `process.env.*` at build time when configured to do so.\n */\nconst DEFAULT_THEME_ID =\n (typeof process !== \"undefined\" &&\n process.env?.NUMU_DEFAULT_THEME_ID) ||\n \"modern\";\n\n/**\n * Dual-Read normalization: converts V1/V2 legacy payloads to V3 in memory.\n * Portable — works in both Node.js (SSR) and browser.\n *\n * Output must match the backend's `normalize_legacy_to_v3()` byte-for-byte\n * on the same input. The unit test in __tests__/normalize.test.ts asserts\n * this. If you change the shape here, update the backend mapper too —\n * otherwise stores rendered via SDK and stores rendered via SSR will\n * disagree on what the page contains.\n */\nexport function resolveThemeSettings(\n raw: Record<string, unknown> | null | undefined,\n): ThemeSettingsV3 {\n const safeRaw = (raw ?? {}) as Record<string, unknown>;\n\n // Already V3 — pass through unchanged.\n if (safeRaw.schema_version === 3) {\n return safeRaw as unknown as ThemeSettingsV3;\n }\n\n const themeBlock = (safeRaw.theme as Record<string, unknown>) || {};\n const themeId =\n (typeof themeBlock.base_theme === \"string\" && themeBlock.base_theme) ||\n DEFAULT_THEME_ID;\n\n const globalSettings: Record<string, unknown> = {};\n for (const key of [\n \"primary_color\",\n \"secondary_color\",\n \"font_family\",\n \"logo_url\",\n ]) {\n if (themeBlock[key] !== undefined) globalSettings[key] = themeBlock[key];\n }\n if (safeRaw.identity) globalSettings.identity = safeRaw.identity;\n\n const sections: Record<string, SectionInstance> = {};\n const order: string[] = [];\n\n const hero = safeRaw.hero as Record<string, unknown> | undefined;\n if (hero) {\n sections[\"hero_1\"] = {\n type: \"hero\",\n settings: {\n // Mirrors backend `normalize_legacy_to_v3` exactly — includes\n // headline_ar so Arabic content survives the round-trip.\n headline: hero.headline ?? \"\",\n headline_ar: hero.headline_ar ?? \"\",\n subtitle: hero.subtitle ?? \"\",\n background_image: hero.hero_image_url ?? \"\",\n cta_text: hero.cta_text ?? \"\",\n cta_link: hero.cta_link ?? \"\",\n },\n };\n order.push(\"hero_1\");\n }\n\n const products = safeRaw.products as Record<string, unknown> | undefined;\n if (products) {\n sections[\"featured_1\"] = {\n type: \"featured-products\",\n settings: products,\n };\n order.push(\"featured_1\");\n }\n\n const templates: Record<string, PageTemplate> = {};\n if (Object.keys(sections).length > 0) {\n templates[\"home\"] = { name: \"Home\", sections, order };\n }\n\n const sectionGroups: Record<string, SectionGroup> = {\n header: {\n name: \"Header Group\",\n sections: {\n header_1: {\n type: \"header\",\n settings: (safeRaw.header as Record<string, unknown>) || {},\n },\n },\n order: [\"header_1\"],\n },\n footer: {\n name: \"Footer Group\",\n sections: {\n footer_1: {\n type: \"footer\",\n settings: (safeRaw.footer as Record<string, unknown>) || {},\n },\n },\n order: [\"footer_1\"],\n },\n };\n\n let externalTheme: ThemeSettingsV3[\"external_theme\"] = null;\n const ext = safeRaw.external_theme as\n | { bundle_url?: unknown; css_url?: unknown; mode?: unknown }\n | undefined;\n if (\n ext &&\n typeof ext === \"object\" &&\n typeof ext.bundle_url === \"string\" &&\n ext.bundle_url\n ) {\n externalTheme = {\n bundle_url: ext.bundle_url,\n css_url: typeof ext.css_url === \"string\" ? ext.css_url : null,\n mode: typeof ext.mode === \"string\" ? ext.mode : \"production\",\n };\n }\n\n return {\n schema_version: 3,\n theme_id: themeId,\n global_settings: globalSettings,\n templates,\n section_groups: sectionGroups,\n external_theme: externalTheme,\n };\n}\n","\"use client\";\n\n/**\n * Module Federation singleton sharing for @numueg/theme-sdk.\n *\n * Why this exists:\n * BYOT bundles (loaded at runtime as cross-origin ESM modules) need to\n * share React + the SDK with the host storefront. Otherwise React's\n * internal \"two copies\" check trips and hooks crash. The host registers\n * its singletons here; the BYOT bundle reads them via the SDK shim.\n *\n * Threat model:\n * We do NOT want third-party scripts (analytics, chat widgets, BYOT\n * community themes) to read PII off the SDK. The earlier version stored\n * the SDK on `window.__NUMU_SDK__` — anything in the page could read it\n * and call `useCustomer()` etc.\n *\n * Mitigation:\n * The singleton is keyed by a Symbol that's only handed to consumers\n * we've verified (the storefront's BYOT entry function passes it to the\n * bundle's `setup()`). Symbols can't be enumerated through `window` or\n * `Object.getOwnPropertyNames`, so a leaked global reference doesn't\n * yield SDK access.\n *\n * For maximum safety we also expose `clearSdkSingleton()` so the host\n * can revoke after a BYOT theme is unmounted.\n */\n\ninterface SdkSingleton {\n useShop: unknown;\n useProduct: unknown;\n useCollection: unknown;\n useCart: unknown;\n useCustomer: unknown;\n useThemeSettings: unknown;\n useLocalization: unknown;\n usePage: unknown;\n useSection: unknown;\n NuMuProvider: unknown;\n ProductProvider: unknown;\n CollectionProvider: unknown;\n}\n\ninterface ReactSingleton {\n React: unknown;\n ReactDOM: unknown;\n}\n\n// We pin the slot keys via `Symbol.for(name)` so ALL copies of this\n// SDK module — even when bundled with a BYOT theme — resolve to the\n// SAME Symbol identity through the global Symbol registry. The\n// previous implementation also wrote the Symbol back to a string-keyed\n// `globalThis[\"__NUMU_SDK_SLOT__\"]` slot \"so multiple module copies\n// could find it\" — but `Symbol.for()` already supplies that identity\n// (that's its entire purpose), and writing to a string-keyed\n// globalThis property put the slot name into `Object.keys(globalThis)`,\n// breaking the Principle II \"not enumerable\" privacy contract.\n//\n// What's still public:\n// - The Symbol's *name* is in the global Symbol registry. A motivated\n// attacker who knows the name can call Symbol.for() to recover the\n// same Symbol. Privacy here is obscurity-through-naming, not crypto.\n// - The actual SDK object lives at `globalThis[symbol]` — invisible\n// to `Object.keys`, `Object.getOwnPropertyNames`, and accidental\n// enumeration by third-party scripts that don't know to call\n// `Object.getOwnPropertySymbols`.\nfunction sdkSlot(): symbol {\n return Symbol.for(\"@numueg/theme-sdk:singleton\");\n}\n\nfunction reactSlot(): symbol {\n return Symbol.for(\"@numueg/theme-sdk:react\");\n}\n\nexport function registerSdkSingleton(sdk: SdkSingleton): void {\n if (typeof globalThis === \"undefined\") return;\n (globalThis as Record<symbol, unknown>)[sdkSlot()] = sdk;\n}\n\nexport function getSdkSingleton(): SdkSingleton | null {\n if (typeof globalThis === \"undefined\") return null;\n return (\n ((globalThis as Record<symbol, unknown>)[sdkSlot()] as SdkSingleton) ??\n null\n );\n}\n\nexport function clearSdkSingleton(): void {\n if (typeof globalThis === \"undefined\") return;\n delete (globalThis as Record<symbol, unknown>)[sdkSlot()];\n}\n\nexport function registerReactSingleton(\n react: unknown,\n reactDom: unknown,\n): void {\n if (typeof globalThis === \"undefined\") return;\n (globalThis as Record<symbol, unknown>)[reactSlot()] = {\n React: react,\n ReactDOM: reactDom,\n } satisfies ReactSingleton;\n}\n\nexport function getReactSingleton(): ReactSingleton | null {\n if (typeof globalThis === \"undefined\") return null;\n return (\n ((globalThis as Record<symbol, unknown>)[\n reactSlot()\n ] as ReactSingleton) ?? null\n );\n}\n\nexport function isSdkAvailable(): boolean {\n return getSdkSingleton() !== null;\n}\n","/**\n * Dynamic sources — Shopify-parity feature that lets merchants bind a\n * section setting to a value that's pulled from store data at render\n * time instead of being a literal authored value.\n *\n * Stored shape:\n * { __numu_source: \"<path>\" }\n *\n * Paths use dot notation against the resolution context:\n * - `product.title` / `product.description` / `product.price` /\n * `product.image` / `product.first_image_url`\n * - `collection.title` / `collection.description` / `collection.image`\n * - `store.name` / `store.description`\n *\n * Why a reserved discriminant key (`__numu_source`)?\n *\n * Setting values today are plain literals (`\"Hero headline\"`,\n * `12345`, `true`). Themes that read settings as strings/numbers\n * would break if we suddenly stored an object. The reserved key\n * tags object-shape values so the resolver only intercepts the ones\n * it knows about. Anything else (e.g. the `{ url, alt }` shape from\n * the image picker, or a future structured setting) passes through.\n *\n * Bindable-by-type matrix (enforced in the customizer's source picker):\n *\n * text | product.title, product.description (snippet),\n * | collection.title, collection.description (snippet),\n * | store.name, store.description\n * textarea | same as text + full descriptions\n * richtext | full descriptions only\n * url | not bindable yet — product/collection URLs require\n * | the host's route resolver; deferred to a follow-up.\n * image_picker | product.image, collection.image, store.logo\n * number/range | product.price (raw cents) — risky because format\n * | varies. Deferred.\n * color/checkbox/select/radio/font | not bindable.\n *\n * Themes consume dynamic sources via `useResolvedSettings(instance)`\n * which returns the section's settings map with every dynamic ref\n * pre-resolved against the active product/collection/store context.\n * Literal values pass through unchanged.\n */\n\nimport type { Collection, Product, Store } from \"../types/entities\";\n\n/** Stored shape for a dynamic source reference. */\nexport interface DynamicSourceRef {\n __numu_source: string;\n}\n\n/**\n * Type guard. True when `value` is a dynamic source reference object.\n * Order matters: we check the discriminant key BEFORE assuming the\n * value is anything else, so an `{ __numu_source: \"...\" }` from the\n * draft doesn't get treated as a literal record.\n */\nexport function isDynamicSource(value: unknown): value is DynamicSourceRef {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { __numu_source?: unknown }).__numu_source === \"string\"\n );\n}\n\n/**\n * Build a fresh dynamic source ref. Pure helper used by the customizer\n * when the merchant clicks a source in the picker.\n */\nexport function dynamicSource(path: string): DynamicSourceRef {\n return { __numu_source: path };\n}\n\n/** Resolution context for `resolveDynamicValue`. Each field is\n * independently optional so callers can pass only what's relevant\n * (e.g. cart template skips product/collection). */\nexport interface DynamicResolveContext {\n product?: Product | null;\n collection?: Collection | null;\n store?: Pick<Store, \"name\" | \"description\" | \"logo_url\"> | null;\n}\n\n/**\n * Look up the path inside the resolution context. Returns `null` when\n * the source is unknown OR the context doesn't have the resource\n * needed to resolve it (e.g. `product.title` when no product is in\n * context). The customizer's source picker already hides incompatible\n * sources, so this fallback only fires during preview navigation\n * (merchant flips to a product template before the picker re-renders).\n */\nexport function resolveSourcePath(\n path: string,\n ctx: DynamicResolveContext,\n): unknown {\n const [root, ...rest] = path.split(\".\");\n switch (root) {\n case \"product\": {\n const p = ctx.product;\n if (!p) return null;\n return resolveProductField(p, rest.join(\".\"));\n }\n case \"collection\": {\n const c = ctx.collection;\n if (!c) return null;\n return resolveCollectionField(c, rest.join(\".\"));\n }\n case \"store\": {\n const s = ctx.store;\n if (!s) return null;\n return resolveStoreField(s, rest.join(\".\"));\n }\n default:\n return null;\n }\n}\n\nfunction resolveProductField(p: Product, field: string): unknown {\n switch (field) {\n case \"title\":\n case \"name\":\n return p.name;\n case \"description\":\n return p.description ?? \"\";\n case \"description_snippet\":\n // 200-char excerpt — useful for short-description settings that\n // would otherwise inherit a full HTML body.\n return (p.description ?? \"\").replace(/<[^>]+>/g, \" \").trim().slice(0, 200);\n case \"price\":\n return p.price;\n case \"sku\":\n // SKU lives on the default variant in most stores.\n return p.variants?.[0]?.sku ?? null;\n case \"image\":\n case \"first_image_url\":\n return p.images?.[0]?.url ?? null;\n case \"slug\":\n return p.slug;\n default:\n return null;\n }\n}\n\nfunction resolveCollectionField(c: Collection, field: string): unknown {\n switch (field) {\n case \"title\":\n case \"name\":\n return c.name;\n case \"description\":\n return c.description ?? \"\";\n case \"description_snippet\":\n return (c.description ?? \"\").replace(/<[^>]+>/g, \" \").trim().slice(0, 200);\n case \"image\":\n return c.image_url ?? null;\n case \"slug\":\n return c.slug;\n case \"product_count\":\n return c.product_count ?? null;\n default:\n return null;\n }\n}\n\nfunction resolveStoreField(\n s: Pick<Store, \"name\" | \"description\" | \"logo_url\">,\n field: string,\n): unknown {\n switch (field) {\n case \"name\":\n return s.name ?? \"\";\n case \"description\":\n return s.description ?? \"\";\n case \"logo\":\n return s.logo_url ?? null;\n default:\n return null;\n }\n}\n\n/**\n * Resolve a single setting value. Literal values pass through\n * unchanged; dynamic references resolve against the context. Returns\n * `null` (not the original ref) when resolution fails, so themes can\n * branch on the null and either render a placeholder or hide the\n * element entirely.\n */\nexport function resolveDynamicValue<T = unknown>(\n value: unknown,\n ctx: DynamicResolveContext,\n): T | null {\n if (!isDynamicSource(value)) return value as T;\n return resolveSourcePath(value.__numu_source, ctx) as T | null;\n}\n\n/**\n * Walk every key of a settings map and resolve every dynamic\n * reference. Pure helper backing `useResolvedSettings`.\n *\n * The generic is unconstrained on purpose. Theme authors typically\n * type their settings as `interface HeroSettings { headline?: string }`,\n * and TypeScript interfaces don't implicitly satisfy\n * `Record<string, unknown>` — there's no index signature on an\n * interface. Leaving `T` open lets us pass through whatever shape the\n * caller declared and still return the resolved-but-same shape.\n */\nexport function resolveSettingsMap<T = Record<string, unknown>>(\n settings: T,\n ctx: DynamicResolveContext,\n): T {\n if (!settings || typeof settings !== \"object\") return settings;\n const input = settings as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n for (const key of Object.keys(input)) {\n const v = input[key];\n if (isDynamicSource(v)) {\n const resolved = resolveSourcePath(v.__numu_source, ctx);\n // Preserve nullish from resolution failure so the consumer can\n // detect \"I asked for product.title but no product is active.\"\n out[key] = resolved;\n } else {\n out[key] = v;\n }\n }\n return out as T;\n}\n","\"use client\";\nimport { useContext, useMemo } from \"react\";\nimport { ProductContext, CollectionContext, ShopContext } from \"../contexts\";\nimport type { BlockInstance, SectionInstance } from \"../types/theme\";\nimport {\n type DynamicResolveContext,\n resolveSettingsMap,\n} from \"../utils/dynamicSources\";\n\n/**\n * Resolve every dynamic source in a section's settings against the\n * active product / collection / store contexts.\n *\n * Section components that want to support merchant-bound fields call\n * this in place of reading `instance.settings` directly:\n *\n * const settings = useResolvedSettings(instance);\n *\n * Literal values pass through; `{ __numu_source: \"product.title\" }`\n * becomes the current product's title when the section is rendered\n * inside a `<ProductProvider>`. The returned object is memoized on\n * the upstream contexts so themes can pass it straight into\n * `useMemo` deps without retriggering renders.\n *\n * When the bound resource isn't in context (e.g. `product.*` on a\n * non-product template), the resolved value is `null`. Themes can\n * detect this and render a placeholder or hide the affected element.\n *\n * Note: the SectionContext provider already supplies the `instance`\n * to children of `<Section>` — but we take it explicitly so section\n * components can call this hook before they've descended into\n * SectionContext (i.e. at the top of their render function, alongside\n * destructuring `settings` from props).\n */\nexport function useResolvedSettings<T = Record<string, unknown>>(\n instance: SectionInstance | BlockInstance | null | undefined,\n): T {\n const product = useContext(ProductContext);\n const collection = useContext(CollectionContext);\n const store = useContext(ShopContext);\n\n // Stabilize the resolution context object so the memo only invalidates\n // when one of the upstream values actually changes. Without this each\n // render would build a fresh `{ product, collection, store }` and the\n // useMemo dep array would never hit.\n const ctx = useMemo<DynamicResolveContext>(\n () => ({ product, collection, store }),\n [product, collection, store],\n );\n\n return useMemo(() => {\n const settings = (instance?.settings ?? {}) as T;\n return resolveSettingsMap<T>(settings, ctx);\n }, [instance, ctx]);\n}\n","/**\n * Section + block authoring helpers.\n *\n * `defineSection` and `defineBlock` bind a JSON schema to its render\n * component so theme authors don't keep two files in sync by hand.\n * The plugin ships the schema half (writes `schemas/sections/<type>.json`\n * for the customizer), the runtime imports the component half — both\n * sourced from the same factory call.\n *\n * Why factories instead of two separate files:\n * Pre-Phase-2 layout was:\n * theme/main.tsx → registers components\n * theme/schemas/sections/Hero.json → declares schema\n * Drift was the bug. Renaming a setting required edits in two places;\n * adding a new section meant remembering to update three lists.\n * Factories collapse that into a single export the plugin and runtime\n * both read.\n *\n * Usage:\n * // sections/Hero.tsx\n * import { defineSection } from \"@numueg/theme-sdk\";\n * export default defineSection({\n * schema: {\n * type: \"hero\",\n * name: \"Hero\",\n * settings: [{ type: \"text\", id: \"heading\", label: \"Heading\" }],\n * presets: [{ name: \"Hero — Centered\", settings: { heading: \"Welcome\" } }],\n * },\n * render: ({ settings }) => <h1>{settings.heading}</h1>,\n * });\n *\n * The plugin's section-discovery scan picks up files under\n * `src/sections/**\\/*.{tsx,ts}` whose default export is a section\n * definition. No registration list needed.\n */\n\nimport type { ComponentType } from \"react\";\nimport type {\n BlockProps,\n BlockSchema,\n SectionProps,\n SectionSchema,\n} from \"../types/theme\";\n\nconst SECTION_MARKER = Symbol.for(\"numu.theme.section\");\nconst BLOCK_MARKER = Symbol.for(\"numu.theme.block\");\n\n/**\n * A defined section: paired schema + render component.\n *\n * The marker symbol lets the plugin's discovery scan identify section\n * definitions without depending on a structural shape that themes might\n * accidentally collide with.\n */\nexport interface DefinedSection {\n schema: SectionSchema;\n render: ComponentType<SectionProps>;\n readonly [SECTION_MARKER]: true;\n}\n\nexport interface DefinedBlock {\n schema: BlockSchema;\n render: ComponentType<BlockProps>;\n readonly [BLOCK_MARKER]: true;\n}\n\nexport interface DefineSectionInput {\n schema: SectionSchema;\n render: ComponentType<SectionProps>;\n}\n\nexport interface DefineBlockInput {\n schema: BlockSchema;\n render: ComponentType<BlockProps>;\n}\n\n/**\n * Bind a section schema to its renderer.\n *\n * Validates at runtime that `schema.type` is a stable identifier\n * (lowercase + dashes/underscores) — drift here breaks the plugin's\n * codegen step (which writes `__generated__/sections.d.ts` keyed off\n * `schema.type`).\n */\nexport function defineSection(input: DefineSectionInput): DefinedSection {\n if (!input?.schema?.type) {\n throw new Error(\n \"defineSection: `schema.type` is required and must be a stable string id.\",\n );\n }\n if (!/^[a-z][a-z0-9_-]*$/.test(input.schema.type)) {\n throw new Error(\n `defineSection: section type '${input.schema.type}' must be lowercase alphanumeric ` +\n `with dashes/underscores. The codegen step uses this as a TS key.`,\n );\n }\n if (typeof input.render !== \"function\") {\n throw new Error(\n \"defineSection: `render` must be a React component function.\",\n );\n }\n return Object.freeze({\n schema: input.schema,\n render: input.render,\n [SECTION_MARKER]: true as const,\n });\n}\n\nexport function defineBlock(input: DefineBlockInput): DefinedBlock {\n if (!input?.schema?.type) {\n throw new Error(\"defineBlock: `schema.type` is required.\");\n }\n if (!/^[a-z@][a-z0-9_/-]*$/i.test(input.schema.type)) {\n throw new Error(\n `defineBlock: block type '${input.schema.type}' has illegal chars. ` +\n `Use a-z, 0-9, dashes/underscores; @app/<slug>/<block> form is also accepted.`,\n );\n }\n if (typeof input.render !== \"function\") {\n throw new Error(\n \"defineBlock: `render` must be a React component function.\",\n );\n }\n return Object.freeze({\n schema: input.schema,\n render: input.render,\n [BLOCK_MARKER]: true as const,\n });\n}\n\nexport function isDefinedSection(v: unknown): v is DefinedSection {\n return (\n typeof v === \"object\" &&\n v !== null &&\n (v as Record<symbol, unknown>)[SECTION_MARKER] === true\n );\n}\n\nexport function isDefinedBlock(v: unknown): v is DefinedBlock {\n return (\n typeof v === \"object\" &&\n v !== null &&\n (v as Record<symbol, unknown>)[BLOCK_MARKER] === true\n );\n}\n\n/**\n * Build a section registry from a Vite glob import.\n *\n * Themes call this at the top of their `main.tsx`:\n *\n * const sectionModules = import.meta.glob<{ default: DefinedSection }>(\n * \"./sections/*.tsx\", { eager: true });\n * const sections = collectSections(sectionModules);\n *\n * The returned object is keyed by `schema.type` for direct lookup at\n * render time. Modules whose default export isn't a DefinedSection are\n * skipped with a console warning (drops a half-migrated section without\n * breaking the rest of the bundle).\n */\nexport function collectSections<T extends Record<string, unknown>>(\n modules: T,\n): Record<string, DefinedSection> {\n const out: Record<string, DefinedSection> = {};\n for (const [path, mod] of Object.entries(modules)) {\n const def = (mod as { default?: unknown }).default;\n if (!isDefinedSection(def)) {\n if (typeof console !== \"undefined\") {\n console.warn(\n `[numu] ${path}: default export is not a defineSection() result; skipped.`,\n );\n }\n continue;\n }\n if (out[def.schema.type]) {\n throw new Error(\n `[numu] duplicate section type '${def.schema.type}': ` +\n `previously defined, now also defined in ${path}.`,\n );\n }\n out[def.schema.type] = def;\n }\n return out;\n}\n\nexport function collectBlocks<T extends Record<string, unknown>>(\n modules: T,\n): Record<string, DefinedBlock> {\n const out: Record<string, DefinedBlock> = {};\n for (const [path, mod] of Object.entries(modules)) {\n const def = (mod as { default?: unknown }).default;\n if (!isDefinedBlock(def)) {\n if (typeof console !== \"undefined\") {\n console.warn(\n `[numu] ${path}: default export is not a defineBlock() result; skipped.`,\n );\n }\n continue;\n }\n if (out[def.schema.type]) {\n throw new Error(\n `[numu] duplicate block type '${def.schema.type}': ` +\n `previously defined, now also defined in ${path}.`,\n );\n }\n out[def.schema.type] = def;\n }\n return out;\n}\n","/**\n * `assetUrl(name)` — resolve a theme-bundled asset's runtime URL.\n *\n * Themes ship static assets (images, fonts, JSON) under `assets/`.\n * The plugin copies each asset to `dist/assets/` with a content-hashed\n * filename and writes a manifest (`asset-manifest.json`) mapping each\n * source path to the hashed name.\n *\n * At runtime this function reads the manifest off the runtime window\n * object (`window.__NUMU_ASSET_MANIFEST`) — populated by the storefront's\n * `<RuntimeImportMap>` component when the theme bundle is loaded —\n * and returns the absolute URL to the hashed file.\n *\n * Why a runtime helper instead of bake-time string interpolation:\n * The same theme bundle is reused across hosted stores. The asset\n * base URL differs per environment (CDN vs local dev) and per store\n * (subdomain vs custom domain). Resolving at runtime keeps a single\n * bundle deployable across all of them.\n *\n * Usage:\n * <Image src={assetUrl(\"hero.jpg\")} alt=\"...\" />\n * <link rel=\"preload\" as=\"font\" href={assetUrl(\"fonts/Inter.woff2\")} />\n *\n * Behavior when the manifest is missing or the asset isn't listed:\n * Returns the original `name` (prefixed with the conventional\n * `/assets/` path) as a fallback. This keeps dev workable when the\n * plugin's asset-pipeline step hasn't run yet, and surfaces obviously-\n * wrong asset names as 404s rather than silent failures.\n */\n\ninterface AssetManifest {\n /** Map of source asset path → hashed filename in dist/assets/ */\n [sourcePath: string]: string;\n}\n\ninterface AssetRuntimeConfig {\n /** Manifest written by the plugin at build time and injected at runtime. */\n __NUMU_ASSET_MANIFEST?: AssetManifest;\n /**\n * Optional CDN/path prefix. Defaults to \"/assets/\" — themes hosted on\n * a CDN can override by setting this on `window` before mount.\n */\n __NUMU_ASSET_BASE_URL?: string;\n}\n\nfunction getRuntime(): AssetRuntimeConfig {\n if (typeof window !== \"undefined\") {\n return window as unknown as AssetRuntimeConfig;\n }\n // Server-side render (host SSR worker): the host injects the manifest and\n // base URL onto globalThis before calling createApp, so server markup\n // resolves the same hashed URLs the client would — no <img src> hydration\n // patch-up.\n if (typeof globalThis !== \"undefined\") {\n return globalThis as unknown as AssetRuntimeConfig;\n }\n return {};\n}\n\nexport function assetUrl(name: string): string {\n if (!name) return \"\";\n // Already-absolute or already-resolved (starts with /, http://, https://) →\n // pass through. Theme code that mixes hand-written paths with assetUrl()\n // is fine, this is just a no-op for those.\n if (/^https?:\\/\\//i.test(name) || name.startsWith(\"//\")) return name;\n\n const runtime = getRuntime();\n const manifest = runtime.__NUMU_ASSET_MANIFEST;\n const base = runtime.__NUMU_ASSET_BASE_URL || \"/assets/\";\n\n // Normalize: strip leading \"./\" or \"assets/\" so callers can write\n // `assetUrl(\"hero.jpg\")` or `assetUrl(\"./hero.jpg\")` interchangeably.\n let key = name.replace(/^\\.\\//, \"\");\n if (key.startsWith(\"/\")) key = key.slice(1);\n if (key.startsWith(\"assets/\")) key = key.slice(\"assets/\".length);\n\n const hashed = manifest?.[key];\n // No manifest hit → fall back to the bare path under base. Keeps dev\n // (where the plugin watch hasn't emitted a manifest yet) workable.\n const filename = hashed || key;\n // Ensure exactly one slash between base and filename.\n const cleanBase = base.endsWith(\"/\") ? base : `${base}/`;\n return `${cleanBase}${filename}`;\n}\n","/**\n * Theme-bundled locale files: load + merge.\n *\n * The plugin discovers `locales/<code>.json` (and the fallback\n * `locales/en.default.json`) and bakes them into the bundle as a map\n * keyed by locale code. The runtime calls `pickTranslations(map, locale)`\n * to resolve the right one, with English fallback for missing keys.\n *\n * Conventions:\n * - locales/en.default.json is the canonical English source. It's\n * the fallback for any other locale's missing keys.\n * - locales/ar.json (and friends) override or extend the default.\n * - Nested keys are flattened with dot notation: `{\"hero\": {\"cta\": \"Buy\"}}`\n * becomes `\"hero.cta\"` for `t(\"hero.cta\")` to look up.\n *\n * Why flatten:\n * `useTranslation()` returns `t(key)` which expects a string lookup —\n * structured access would force every theme to write\n * `translations.hero?.cta ?? \"Buy\"`. Flattening keeps the call site\n * short and matches Shopify's `t` semantics.\n */\n\nexport interface LocaleMessages {\n [key: string]: string;\n}\n\nexport interface LocaleBundle {\n /** Locale code → flat key/value messages. */\n [locale: string]: LocaleMessages;\n}\n\n/**\n * Recursively flatten a nested locale object into dot-keyed strings.\n *\n * Non-string leaves are skipped with a console warning — translations\n * are user-facing strings; numbers and booleans don't belong in a\n * locale file (they should be in schema settings).\n */\nexport function flattenMessages(\n source: Record<string, unknown>,\n prefix = \"\",\n): LocaleMessages {\n const out: LocaleMessages = {};\n for (const [key, val] of Object.entries(source)) {\n const fullKey = prefix ? `${prefix}.${key}` : key;\n if (val === null || val === undefined) continue;\n if (typeof val === \"string\") {\n out[fullKey] = val;\n } else if (typeof val === \"object\" && !Array.isArray(val)) {\n Object.assign(\n out,\n flattenMessages(val as Record<string, unknown>, fullKey),\n );\n } else if (typeof console !== \"undefined\") {\n console.warn(\n `[numu] locale key '${fullKey}' has non-string value (${typeof val}); skipped.`,\n );\n }\n }\n return out;\n}\n\n/**\n * Resolve the messages map for the requested locale, falling back to\n * \"en\" then \"en.default\" then an empty map. Missing keys in the\n * requested locale are filled from \"en\" (so an Arabic translation\n * file with 90% coverage doesn't show empty strings for the missing\n * 10%; English shows through).\n */\nexport function pickTranslations(\n bundle: LocaleBundle,\n locale: string,\n): LocaleMessages {\n const fallback = bundle[\"en\"] || bundle[\"en.default\"] || {};\n const requested = bundle[locale];\n if (!requested) return fallback;\n // Merge: fallback < requested. The requested locale wins per-key;\n // any key the requested locale doesn't define falls through to en.\n return { ...fallback, ...requested };\n}\n\n/**\n * Build a LocaleBundle from raw imports. Themes call this in their\n * `main.tsx` after a Vite glob import:\n *\n * const localeModules = import.meta.glob<Record<string, unknown>>(\n * \"./locales/*.json\", { eager: true, import: \"default\" });\n * const translations = buildLocaleBundle(localeModules);\n *\n * `localeModules` keys are paths like `./locales/ar.json`; we strip\n * the directory + extension to get the locale code, and flatten each\n * value.\n */\nexport function buildLocaleBundle<T extends Record<string, unknown>>(\n modules: T,\n): LocaleBundle {\n const bundle: LocaleBundle = {};\n for (const [path, raw] of Object.entries(modules)) {\n const m = /\\/([^/]+)\\.json$/.exec(path);\n if (!m) continue;\n let code = m[1];\n // `en.default` → keep as-is so pickTranslations can find it; theme\n // devs naming the file that way is a soft signal that this is the\n // canonical English source.\n if (code !== \"en.default\") {\n // Strip trailing \".default\" from any other code (someone might\n // write `ar.default.json` by mistake).\n code = code.replace(/\\.default$/, \"\");\n }\n const value = raw as unknown;\n if (typeof value === \"object\" && value !== null) {\n bundle[code] = flattenMessages(value as Record<string, unknown>);\n }\n }\n return bundle;\n}\n"]}
|