@numueg/theme-sdk 0.2.3 → 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/dist/{entities-C8B2U-V0.d.mts → entities-6MGANln7.d.mts} +45 -1
- package/dist/{entities-C8B2U-V0.d.ts → entities-6MGANln7.d.ts} +45 -1
- package/dist/index.cjs +110 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +125 -5
- package/dist/index.d.ts +125 -5
- package/dist/index.mjs +107 -41
- 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 +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { A as Address, a as CartItem, O as Order, d as OrderItem, f as ProductImage,
|
|
1
|
+
import { i as Store, e as Product, b as Collection, C as Cart, c as Customer, P as Page, S as SizeChart, g as ProductVariant } from './entities-6MGANln7.mjs';
|
|
2
|
+
export { A as Address, a as CartItem, O as Order, d as OrderItem, f as ProductImage, j as ProductOption, h as SizeChartMode } from './entities-6MGANln7.mjs';
|
|
3
3
|
import { T as ThemeSettingsV3, c as SectionInstance, M as MountResult, B as BlockInstance, b as BlockSchema, a as BlockProps$1, f as SectionSchema, e as SectionProps$1 } from './theme-D0QybTQS.mjs';
|
|
4
4
|
export { E as ExternalThemeMetadata, h as MAX_BLOCK_DEPTH, P as PageTemplate, i as PresetBlock, S as SectionGroup, d as SectionPreset, g as SettingDefinition } from './theme-D0QybTQS.mjs';
|
|
5
5
|
import * as react from 'react';
|
|
6
|
-
import { ReactNode, ElementType, CSSProperties, ImgHTMLAttributes, AnchorHTMLAttributes, ButtonHTMLAttributes, HTMLAttributes, FormHTMLAttributes, ComponentType } from 'react';
|
|
6
|
+
import { ReactNode, ReactElement, ElementType, CSSProperties, ImgHTMLAttributes, AnchorHTMLAttributes, ButtonHTMLAttributes, HTMLAttributes, FormHTMLAttributes, ComponentType } from 'react';
|
|
7
7
|
export { resolveThemeSettings } from './normalize.mjs';
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -744,6 +744,33 @@ declare function useRelatedProducts(productId: string | null | undefined, option
|
|
|
744
744
|
limit?: number;
|
|
745
745
|
}): RelatedProductsState;
|
|
746
746
|
|
|
747
|
+
/**
|
|
748
|
+
* useProductSizeChart — resolve the size chart to show for a product.
|
|
749
|
+
*
|
|
750
|
+
* The merchant hub writes the per-product chart to
|
|
751
|
+
* `product.attributes.size_chart` and the store-wide default to
|
|
752
|
+
* `store.settings.size_chart`, with an explicit `mode`:
|
|
753
|
+
*
|
|
754
|
+
* "off" → never show, even if a store default exists
|
|
755
|
+
* "custom" → use the product's own chart
|
|
756
|
+
* "default" → fall back to the store-wide chart
|
|
757
|
+
* (legacy) → no `mode`: a populated product chart wins, else the default
|
|
758
|
+
*
|
|
759
|
+
* This hook centralises that precedence so every theme resolves it identically
|
|
760
|
+
* (the backend `SizeChartSchema` validator and the hub editor share the same
|
|
761
|
+
* shape). Returns `null` when there is nothing to show — render the size-guide
|
|
762
|
+
* trigger only when this is non-null.
|
|
763
|
+
*
|
|
764
|
+
* @param productOverride - resolve against this product instead of the one in
|
|
765
|
+
* context (e.g. when rendering a chart for a related/quick-view product).
|
|
766
|
+
*/
|
|
767
|
+
declare function useProductSizeChart(productOverride?: Product | null): SizeChart | null;
|
|
768
|
+
/**
|
|
769
|
+
* Pure resolver (no React) — exported so non-hook code (SSR helpers, tests)
|
|
770
|
+
* can apply the same precedence.
|
|
771
|
+
*/
|
|
772
|
+
declare function resolveSizeChart(productAttributes: Record<string, unknown> | undefined, storeSettings: Record<string, unknown> | undefined): SizeChart | null;
|
|
773
|
+
|
|
747
774
|
/**
|
|
748
775
|
* Multi-currency presentment — Phase 6.
|
|
749
776
|
*
|
|
@@ -1155,6 +1182,14 @@ interface ThemeMountContext {
|
|
|
1155
1182
|
demo?: boolean;
|
|
1156
1183
|
/** Store navigation menus keyed by handle, resolved server-side. */
|
|
1157
1184
|
navigation?: Record<string, MenuItemData[]>;
|
|
1185
|
+
/**
|
|
1186
|
+
* Host signal that the container already holds server-rendered HTML for
|
|
1187
|
+
* this exact ctx (produced via `createApp` from `defineThemeEntry`).
|
|
1188
|
+
* `mountTheme` then adopts it with `hydrateRoot` instead of re-rendering
|
|
1189
|
+
* from scratch. Ignored when the container is empty, so a host can pass
|
|
1190
|
+
* it optimistically and still get a plain client mount on SSR failure.
|
|
1191
|
+
*/
|
|
1192
|
+
hydrate?: boolean;
|
|
1158
1193
|
[extra: string]: unknown;
|
|
1159
1194
|
}
|
|
1160
1195
|
/** Arguments handed to a theme's render callback on every (re)render. */
|
|
@@ -1170,17 +1205,81 @@ interface ThemeRenderArgs {
|
|
|
1170
1205
|
/** Live theme settings (reflects customizer drafts via applyDraft). */
|
|
1171
1206
|
themeSettings: ThemeSettingsV3;
|
|
1172
1207
|
}
|
|
1208
|
+
interface DraftHandle {
|
|
1209
|
+
applyDraft: (next: ThemeSettingsV3) => void;
|
|
1210
|
+
}
|
|
1211
|
+
/**
|
|
1212
|
+
* Build the canonical theme element tree for a ctx. BOTH render paths go
|
|
1213
|
+
* through here — `mountTheme` (client mount/hydrate) and `createApp`
|
|
1214
|
+
* (host-side `renderToString`) — so the server markup and the hydration
|
|
1215
|
+
* tree are the same React tree by construction. `mountEl` is a prop, not
|
|
1216
|
+
* DOM output, so it differing between server (null) and client (the
|
|
1217
|
+
* container) cannot cause a hydration mismatch.
|
|
1218
|
+
*/
|
|
1219
|
+
declare function buildThemeElement(ctx: ThemeMountContext, mountEl: HTMLElement | null, renderApp: (args: ThemeRenderArgs) => ReactNode, ref?: (h: DraftHandle | null) => void): ReactElement;
|
|
1173
1220
|
/**
|
|
1174
1221
|
* Mount a V3 theme. Owns the React root, the provider stack (catalog + nav +
|
|
1175
1222
|
* style tokens), and the live-preview draft cycle. Returns the host-contract
|
|
1176
1223
|
* `MountResult` (`cleanup` + `applyDraft`).
|
|
1177
1224
|
*
|
|
1225
|
+
* When the host passes `ctx.hydrate === true` and the container already
|
|
1226
|
+
* holds server-rendered HTML (produced by this theme's `createApp` with the
|
|
1227
|
+
* identical ctx), the tree is adopted via `hydrateRoot` — no re-render, no
|
|
1228
|
+
* flash. An empty container downgrades to a plain client mount so hosts can
|
|
1229
|
+
* pass the flag optimistically.
|
|
1230
|
+
*
|
|
1178
1231
|
* @param el the host-supplied container element
|
|
1179
1232
|
* @param ctx the mount context (either host or legacy/dev shape)
|
|
1180
1233
|
* @param renderApp returns the theme's section tree for the current args
|
|
1181
1234
|
*/
|
|
1182
1235
|
declare function mountTheme(el: HTMLElement, ctx: ThemeMountContext, renderApp: (args: ThemeRenderArgs) => ReactNode): MountResult;
|
|
1183
1236
|
|
|
1237
|
+
/**
|
|
1238
|
+
* `defineThemeEntry(renderApp)` — one-call theme entry that yields BOTH
|
|
1239
|
+
* halves of the V3 contract from a single component:
|
|
1240
|
+
*
|
|
1241
|
+
* - `mount(el, ctx)` — the client entry every host already calls
|
|
1242
|
+
* (now hydration-aware via `ctx.hydrate`).
|
|
1243
|
+
* - `createApp(ctx)` — the same React tree as a plain element, so the
|
|
1244
|
+
* host can `renderToString(createApp(ctx))` on the
|
|
1245
|
+
* server and ship real HTML before any JS runs.
|
|
1246
|
+
*
|
|
1247
|
+
* ```tsx
|
|
1248
|
+
* // src/main.tsx
|
|
1249
|
+
* import { defineThemeEntry } from "@numueg/theme-sdk";
|
|
1250
|
+
*
|
|
1251
|
+
* const entry = defineThemeEntry(({ currentTemplate }) => (
|
|
1252
|
+
* <ThemeApp currentTemplate={currentTemplate} />
|
|
1253
|
+
* ));
|
|
1254
|
+
*
|
|
1255
|
+
* export const mount = entry.mount;
|
|
1256
|
+
* export const createApp = entry.createApp;
|
|
1257
|
+
* ```
|
|
1258
|
+
*
|
|
1259
|
+
* Why both MUST come from one definition: hydration only succeeds when the
|
|
1260
|
+
* server markup and the client tree are identical. Routing both through
|
|
1261
|
+
* `buildThemeElement` makes that true by construction — a theme cannot
|
|
1262
|
+
* accidentally ship a `createApp` that disagrees with its `mount`.
|
|
1263
|
+
*
|
|
1264
|
+
* Themes that only export `mount` keep working exactly as before; they are
|
|
1265
|
+
* simply never server-rendered (the host detects the missing `createApp`
|
|
1266
|
+
* and falls back to today's client-only mount).
|
|
1267
|
+
*/
|
|
1268
|
+
|
|
1269
|
+
/** The pair of entry points a V3 theme bundle exports. */
|
|
1270
|
+
interface ThemeEntry {
|
|
1271
|
+
/** Client entry — host contract `mount(el, ctx): MountResult`. */
|
|
1272
|
+
mount: (el: HTMLElement, ctx: ThemeMountContext) => MountResult;
|
|
1273
|
+
/**
|
|
1274
|
+
* Server entry — returns the exact element tree `mount` would render,
|
|
1275
|
+
* for host-side `renderToString`. Must stay side-effect free: no DOM
|
|
1276
|
+
* access happens until React effects run (which they don't on the
|
|
1277
|
+
* server).
|
|
1278
|
+
*/
|
|
1279
|
+
createApp: (ctx: ThemeMountContext) => ReactElement;
|
|
1280
|
+
}
|
|
1281
|
+
declare function defineThemeEntry(renderApp: (args: ThemeRenderArgs) => ReactNode): ThemeEntry;
|
|
1282
|
+
|
|
1184
1283
|
interface NuMuProviderProps {
|
|
1185
1284
|
store: Store;
|
|
1186
1285
|
themeSettings: ThemeSettingsV3;
|
|
@@ -2126,11 +2225,32 @@ type GlobalSettings = Record<string, unknown> | null | undefined;
|
|
|
2126
2225
|
* family/stack the theme author supplied.
|
|
2127
2226
|
*/
|
|
2128
2227
|
declare function resolveFontStack(value: string): string;
|
|
2228
|
+
/** Result of `computeGlobalStyleTokens` — everything a host needs to paint
|
|
2229
|
+
* global settings without a DOM. */
|
|
2230
|
+
interface ComputedStyleTokens {
|
|
2231
|
+
/** CSS custom properties to set on the theme's mount root. */
|
|
2232
|
+
cssVars: Record<string, string>;
|
|
2233
|
+
/** Google-Fonts stylesheet hrefs for any registry fonts in use. */
|
|
2234
|
+
fontHrefs: string[];
|
|
2235
|
+
}
|
|
2236
|
+
/**
|
|
2237
|
+
* Pure half of `applyGlobalStyleTokens`: compute the exact CSS custom
|
|
2238
|
+
* properties (and webfont hrefs) a settings object maps to, without touching
|
|
2239
|
+
* any DOM. This is what lets a host SERVER-render a theme with the same vars
|
|
2240
|
+
* the bundle applies on mount — both sides call this one function, so the
|
|
2241
|
+
* values cannot drift (drift = unstyled flash or hydration noise).
|
|
2242
|
+
*
|
|
2243
|
+
* Includes the explicit `heading_font` / `body_font` resolution that
|
|
2244
|
+
* `mountTheme` historically layered on top: any string value for those two
|
|
2245
|
+
* ids resolves through the registry (or passes verbatim) so a picked font
|
|
2246
|
+
* gets a real stack even when it isn't a known token.
|
|
2247
|
+
*/
|
|
2248
|
+
declare function computeGlobalStyleTokens(globalSettings: GlobalSettings): ComputedStyleTokens;
|
|
2129
2249
|
/**
|
|
2130
2250
|
* Map a store's global settings onto CSS custom properties on `el`. Call on
|
|
2131
2251
|
* mount and on every `applyDraft` (live preview). No-op when `el` or the
|
|
2132
2252
|
* settings are missing. Reserved `__`-prefixed keys (e.g. `__translations`)
|
|
2133
|
-
* are skipped.
|
|
2253
|
+
* are skipped. Thin DOM shell over `computeGlobalStyleTokens`.
|
|
2134
2254
|
*/
|
|
2135
2255
|
declare function applyGlobalStyleTokens(globalSettings: GlobalSettings, el: HTMLElement | null | undefined): void;
|
|
2136
2256
|
|
|
@@ -2192,4 +2312,4 @@ declare function pickTranslations(bundle: LocaleBundle, locale: string): LocaleM
|
|
|
2192
2312
|
*/
|
|
2193
2313
|
declare function buildLocaleBundle<T extends Record<string, unknown>>(modules: T): LocaleBundle;
|
|
2194
2314
|
|
|
2195
|
-
export { AddToCartButton, type AddressInput, type AnalyticsApi, type AnalyticsPayload, type AppManifestBlock, type AppPayload, type AppState, Block, BlockInstance, BlockProps$1 as BlockProps, BlockSchema, Cart, CartContext, type CheckoutAddress, type CheckoutApi, type CheckoutSessionState, type CheckoutStep, Collection, CollectionCard, type CollectionCardProps, type CollectionCardSlots, CollectionContext, CollectionProvider, type CurrencyConfig, type CurrencyState, CurrencySwitcher, type CurrencySwitcherProps, Customer, type CustomerAddress, type CustomerAddressesState, CustomerContext, type DefineBlockInput, type DefineSectionInput, type DefinedBlock, type DefinedSection, type DynamicResolveContext, type DynamicSourceRef, EditableImage, type EditableImageProps, EditableText, type EditableTextProps, type FocalSrcOptions, Form, type GiftCardBalance, ICON_NAMES, Icon, IconMap, type IconProps, Image, type ImageTransform, Link, type LocaleBundle, type LocaleMessages, LocaleSwitcher, type LocaleSwitcherProps, LocalizationContext, type MenuItemData, Money, MountResult, NavigationContext, type NavigationItem, type NavigationState, NuMuProvider, type OrderDetail, type OrderListEntry, type OrderListState, type OrderState, Page, PageContext, type PlaceOrderResult, Product, ProductCard, type ProductCardProps, type ProductCardSlots, ProductContext, ProductProvider, ProductVariant, type RelatedProductsState, type ReorderResult, type ReorderSkipReason, type ReorderSkippedItem, RichText, type RichTextProps, type SearchResults, type SearchState, Section, SectionContext, SectionInstance, SectionProps$1 as SectionProps, SectionSchema, type ShippingRateOption, ShopContext, type ShopWithHelpers, Store, type ThemeMountContext, type ThemeMountPage, type ThemeRenderArgs, ThemeSettingsContext, ThemeSettingsV3, type UseGiftCardBalance, type UseReorder, type UseSearchOptions, type UseShippingRatesOptions, type UseShippingRatesState, type UseVariantSelection, type WishlistItem, type WishlistState, applyGlobalStyleTokens, applyImageTransform, asImageTransform, assetUrl, availableValues, buildLocaleBundle, clearSdkSingleton, collectBlocks, collectSections, defaultVariant, defineBlock, defineSection, dynamicSource, findVariantByOptions, flattenMessages, focalSrc, getReactSingleton, getSdkSingleton, isDefinedBlock, isDefinedSection, isDynamicSource, isSdkAvailable, mountTheme, pickTranslations, registerReactSingleton, registerSdkSingleton, resolveDynamicValue, resolveFontStack, resolveSettingsMap, resolveSourcePath, sanitizeHtml, useAnalytics, useApp, useCart, useCheckout, useCollection, useCollectionOptional, useCollections, useCurrency, useCurrentTemplate, useCustomer, useCustomerActions, useCustomerAddresses, useDirection, useFieldTranslation, useGiftCardBalance, useImage, useLocale, useLocalization, useMoney, useNavigation, useNumberFormat, useOrder, useOrders, usePage, useProduct, useProductOptional, useProducts, useRelatedProducts, useReorder, useResolvedSettings, useSearch, useSection, useSectionOptional, useShippingRates, useShop, useThemeSettings, useTranslation, useVariantSelection, useWishlist };
|
|
2315
|
+
export { AddToCartButton, type AddressInput, type AnalyticsApi, type AnalyticsPayload, type AppManifestBlock, type AppPayload, type AppState, Block, BlockInstance, BlockProps$1 as BlockProps, BlockSchema, Cart, CartContext, type CheckoutAddress, type CheckoutApi, type CheckoutSessionState, type CheckoutStep, Collection, CollectionCard, type CollectionCardProps, type CollectionCardSlots, CollectionContext, CollectionProvider, type ComputedStyleTokens, type CurrencyConfig, type CurrencyState, CurrencySwitcher, type CurrencySwitcherProps, Customer, type CustomerAddress, type CustomerAddressesState, CustomerContext, type DefineBlockInput, type DefineSectionInput, type DefinedBlock, type DefinedSection, type DynamicResolveContext, type DynamicSourceRef, EditableImage, type EditableImageProps, EditableText, type EditableTextProps, type FocalSrcOptions, Form, type GiftCardBalance, ICON_NAMES, Icon, IconMap, type IconProps, Image, type ImageTransform, Link, type LocaleBundle, type LocaleMessages, LocaleSwitcher, type LocaleSwitcherProps, LocalizationContext, type MenuItemData, Money, MountResult, NavigationContext, type NavigationItem, type NavigationState, NuMuProvider, type OrderDetail, type OrderListEntry, type OrderListState, type OrderState, Page, PageContext, type PlaceOrderResult, Product, ProductCard, type ProductCardProps, type ProductCardSlots, ProductContext, ProductProvider, ProductVariant, type RelatedProductsState, type ReorderResult, type ReorderSkipReason, type ReorderSkippedItem, RichText, type RichTextProps, type SearchResults, type SearchState, Section, SectionContext, SectionInstance, SectionProps$1 as SectionProps, SectionSchema, type ShippingRateOption, ShopContext, type ShopWithHelpers, SizeChart, Store, type ThemeEntry, type ThemeMountContext, type ThemeMountPage, type ThemeRenderArgs, ThemeSettingsContext, ThemeSettingsV3, type UseGiftCardBalance, type UseReorder, type UseSearchOptions, type UseShippingRatesOptions, type UseShippingRatesState, type UseVariantSelection, type WishlistItem, type WishlistState, applyGlobalStyleTokens, applyImageTransform, asImageTransform, assetUrl, availableValues, buildLocaleBundle, buildThemeElement, clearSdkSingleton, collectBlocks, collectSections, computeGlobalStyleTokens, defaultVariant, defineBlock, defineSection, defineThemeEntry, dynamicSource, findVariantByOptions, flattenMessages, focalSrc, getReactSingleton, getSdkSingleton, isDefinedBlock, isDefinedSection, isDynamicSource, isSdkAvailable, mountTheme, pickTranslations, registerReactSingleton, registerSdkSingleton, resolveDynamicValue, resolveFontStack, resolveSettingsMap, resolveSizeChart, resolveSourcePath, sanitizeHtml, useAnalytics, useApp, useCart, useCheckout, useCollection, useCollectionOptional, useCollections, useCurrency, useCurrentTemplate, useCustomer, useCustomerActions, useCustomerAddresses, useDirection, useFieldTranslation, useGiftCardBalance, useImage, useLocale, useLocalization, useMoney, useNavigation, useNumberFormat, useOrder, useOrders, usePage, useProduct, useProductOptional, useProductSizeChart, useProducts, useRelatedProducts, useReorder, useResolvedSettings, useSearch, useSection, useSectionOptional, useShippingRates, useShop, useThemeSettings, useTranslation, useVariantSelection, useWishlist };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { A as Address, a as CartItem, O as Order, d as OrderItem, f as ProductImage,
|
|
1
|
+
import { i as Store, e as Product, b as Collection, C as Cart, c as Customer, P as Page, S as SizeChart, g as ProductVariant } from './entities-6MGANln7.js';
|
|
2
|
+
export { A as Address, a as CartItem, O as Order, d as OrderItem, f as ProductImage, j as ProductOption, h as SizeChartMode } from './entities-6MGANln7.js';
|
|
3
3
|
import { T as ThemeSettingsV3, c as SectionInstance, M as MountResult, B as BlockInstance, b as BlockSchema, a as BlockProps$1, f as SectionSchema, e as SectionProps$1 } from './theme-D0QybTQS.js';
|
|
4
4
|
export { E as ExternalThemeMetadata, h as MAX_BLOCK_DEPTH, P as PageTemplate, i as PresetBlock, S as SectionGroup, d as SectionPreset, g as SettingDefinition } from './theme-D0QybTQS.js';
|
|
5
5
|
import * as react from 'react';
|
|
6
|
-
import { ReactNode, ElementType, CSSProperties, ImgHTMLAttributes, AnchorHTMLAttributes, ButtonHTMLAttributes, HTMLAttributes, FormHTMLAttributes, ComponentType } from 'react';
|
|
6
|
+
import { ReactNode, ReactElement, ElementType, CSSProperties, ImgHTMLAttributes, AnchorHTMLAttributes, ButtonHTMLAttributes, HTMLAttributes, FormHTMLAttributes, ComponentType } from 'react';
|
|
7
7
|
export { resolveThemeSettings } from './normalize.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -744,6 +744,33 @@ declare function useRelatedProducts(productId: string | null | undefined, option
|
|
|
744
744
|
limit?: number;
|
|
745
745
|
}): RelatedProductsState;
|
|
746
746
|
|
|
747
|
+
/**
|
|
748
|
+
* useProductSizeChart — resolve the size chart to show for a product.
|
|
749
|
+
*
|
|
750
|
+
* The merchant hub writes the per-product chart to
|
|
751
|
+
* `product.attributes.size_chart` and the store-wide default to
|
|
752
|
+
* `store.settings.size_chart`, with an explicit `mode`:
|
|
753
|
+
*
|
|
754
|
+
* "off" → never show, even if a store default exists
|
|
755
|
+
* "custom" → use the product's own chart
|
|
756
|
+
* "default" → fall back to the store-wide chart
|
|
757
|
+
* (legacy) → no `mode`: a populated product chart wins, else the default
|
|
758
|
+
*
|
|
759
|
+
* This hook centralises that precedence so every theme resolves it identically
|
|
760
|
+
* (the backend `SizeChartSchema` validator and the hub editor share the same
|
|
761
|
+
* shape). Returns `null` when there is nothing to show — render the size-guide
|
|
762
|
+
* trigger only when this is non-null.
|
|
763
|
+
*
|
|
764
|
+
* @param productOverride - resolve against this product instead of the one in
|
|
765
|
+
* context (e.g. when rendering a chart for a related/quick-view product).
|
|
766
|
+
*/
|
|
767
|
+
declare function useProductSizeChart(productOverride?: Product | null): SizeChart | null;
|
|
768
|
+
/**
|
|
769
|
+
* Pure resolver (no React) — exported so non-hook code (SSR helpers, tests)
|
|
770
|
+
* can apply the same precedence.
|
|
771
|
+
*/
|
|
772
|
+
declare function resolveSizeChart(productAttributes: Record<string, unknown> | undefined, storeSettings: Record<string, unknown> | undefined): SizeChart | null;
|
|
773
|
+
|
|
747
774
|
/**
|
|
748
775
|
* Multi-currency presentment — Phase 6.
|
|
749
776
|
*
|
|
@@ -1155,6 +1182,14 @@ interface ThemeMountContext {
|
|
|
1155
1182
|
demo?: boolean;
|
|
1156
1183
|
/** Store navigation menus keyed by handle, resolved server-side. */
|
|
1157
1184
|
navigation?: Record<string, MenuItemData[]>;
|
|
1185
|
+
/**
|
|
1186
|
+
* Host signal that the container already holds server-rendered HTML for
|
|
1187
|
+
* this exact ctx (produced via `createApp` from `defineThemeEntry`).
|
|
1188
|
+
* `mountTheme` then adopts it with `hydrateRoot` instead of re-rendering
|
|
1189
|
+
* from scratch. Ignored when the container is empty, so a host can pass
|
|
1190
|
+
* it optimistically and still get a plain client mount on SSR failure.
|
|
1191
|
+
*/
|
|
1192
|
+
hydrate?: boolean;
|
|
1158
1193
|
[extra: string]: unknown;
|
|
1159
1194
|
}
|
|
1160
1195
|
/** Arguments handed to a theme's render callback on every (re)render. */
|
|
@@ -1170,17 +1205,81 @@ interface ThemeRenderArgs {
|
|
|
1170
1205
|
/** Live theme settings (reflects customizer drafts via applyDraft). */
|
|
1171
1206
|
themeSettings: ThemeSettingsV3;
|
|
1172
1207
|
}
|
|
1208
|
+
interface DraftHandle {
|
|
1209
|
+
applyDraft: (next: ThemeSettingsV3) => void;
|
|
1210
|
+
}
|
|
1211
|
+
/**
|
|
1212
|
+
* Build the canonical theme element tree for a ctx. BOTH render paths go
|
|
1213
|
+
* through here — `mountTheme` (client mount/hydrate) and `createApp`
|
|
1214
|
+
* (host-side `renderToString`) — so the server markup and the hydration
|
|
1215
|
+
* tree are the same React tree by construction. `mountEl` is a prop, not
|
|
1216
|
+
* DOM output, so it differing between server (null) and client (the
|
|
1217
|
+
* container) cannot cause a hydration mismatch.
|
|
1218
|
+
*/
|
|
1219
|
+
declare function buildThemeElement(ctx: ThemeMountContext, mountEl: HTMLElement | null, renderApp: (args: ThemeRenderArgs) => ReactNode, ref?: (h: DraftHandle | null) => void): ReactElement;
|
|
1173
1220
|
/**
|
|
1174
1221
|
* Mount a V3 theme. Owns the React root, the provider stack (catalog + nav +
|
|
1175
1222
|
* style tokens), and the live-preview draft cycle. Returns the host-contract
|
|
1176
1223
|
* `MountResult` (`cleanup` + `applyDraft`).
|
|
1177
1224
|
*
|
|
1225
|
+
* When the host passes `ctx.hydrate === true` and the container already
|
|
1226
|
+
* holds server-rendered HTML (produced by this theme's `createApp` with the
|
|
1227
|
+
* identical ctx), the tree is adopted via `hydrateRoot` — no re-render, no
|
|
1228
|
+
* flash. An empty container downgrades to a plain client mount so hosts can
|
|
1229
|
+
* pass the flag optimistically.
|
|
1230
|
+
*
|
|
1178
1231
|
* @param el the host-supplied container element
|
|
1179
1232
|
* @param ctx the mount context (either host or legacy/dev shape)
|
|
1180
1233
|
* @param renderApp returns the theme's section tree for the current args
|
|
1181
1234
|
*/
|
|
1182
1235
|
declare function mountTheme(el: HTMLElement, ctx: ThemeMountContext, renderApp: (args: ThemeRenderArgs) => ReactNode): MountResult;
|
|
1183
1236
|
|
|
1237
|
+
/**
|
|
1238
|
+
* `defineThemeEntry(renderApp)` — one-call theme entry that yields BOTH
|
|
1239
|
+
* halves of the V3 contract from a single component:
|
|
1240
|
+
*
|
|
1241
|
+
* - `mount(el, ctx)` — the client entry every host already calls
|
|
1242
|
+
* (now hydration-aware via `ctx.hydrate`).
|
|
1243
|
+
* - `createApp(ctx)` — the same React tree as a plain element, so the
|
|
1244
|
+
* host can `renderToString(createApp(ctx))` on the
|
|
1245
|
+
* server and ship real HTML before any JS runs.
|
|
1246
|
+
*
|
|
1247
|
+
* ```tsx
|
|
1248
|
+
* // src/main.tsx
|
|
1249
|
+
* import { defineThemeEntry } from "@numueg/theme-sdk";
|
|
1250
|
+
*
|
|
1251
|
+
* const entry = defineThemeEntry(({ currentTemplate }) => (
|
|
1252
|
+
* <ThemeApp currentTemplate={currentTemplate} />
|
|
1253
|
+
* ));
|
|
1254
|
+
*
|
|
1255
|
+
* export const mount = entry.mount;
|
|
1256
|
+
* export const createApp = entry.createApp;
|
|
1257
|
+
* ```
|
|
1258
|
+
*
|
|
1259
|
+
* Why both MUST come from one definition: hydration only succeeds when the
|
|
1260
|
+
* server markup and the client tree are identical. Routing both through
|
|
1261
|
+
* `buildThemeElement` makes that true by construction — a theme cannot
|
|
1262
|
+
* accidentally ship a `createApp` that disagrees with its `mount`.
|
|
1263
|
+
*
|
|
1264
|
+
* Themes that only export `mount` keep working exactly as before; they are
|
|
1265
|
+
* simply never server-rendered (the host detects the missing `createApp`
|
|
1266
|
+
* and falls back to today's client-only mount).
|
|
1267
|
+
*/
|
|
1268
|
+
|
|
1269
|
+
/** The pair of entry points a V3 theme bundle exports. */
|
|
1270
|
+
interface ThemeEntry {
|
|
1271
|
+
/** Client entry — host contract `mount(el, ctx): MountResult`. */
|
|
1272
|
+
mount: (el: HTMLElement, ctx: ThemeMountContext) => MountResult;
|
|
1273
|
+
/**
|
|
1274
|
+
* Server entry — returns the exact element tree `mount` would render,
|
|
1275
|
+
* for host-side `renderToString`. Must stay side-effect free: no DOM
|
|
1276
|
+
* access happens until React effects run (which they don't on the
|
|
1277
|
+
* server).
|
|
1278
|
+
*/
|
|
1279
|
+
createApp: (ctx: ThemeMountContext) => ReactElement;
|
|
1280
|
+
}
|
|
1281
|
+
declare function defineThemeEntry(renderApp: (args: ThemeRenderArgs) => ReactNode): ThemeEntry;
|
|
1282
|
+
|
|
1184
1283
|
interface NuMuProviderProps {
|
|
1185
1284
|
store: Store;
|
|
1186
1285
|
themeSettings: ThemeSettingsV3;
|
|
@@ -2126,11 +2225,32 @@ type GlobalSettings = Record<string, unknown> | null | undefined;
|
|
|
2126
2225
|
* family/stack the theme author supplied.
|
|
2127
2226
|
*/
|
|
2128
2227
|
declare function resolveFontStack(value: string): string;
|
|
2228
|
+
/** Result of `computeGlobalStyleTokens` — everything a host needs to paint
|
|
2229
|
+
* global settings without a DOM. */
|
|
2230
|
+
interface ComputedStyleTokens {
|
|
2231
|
+
/** CSS custom properties to set on the theme's mount root. */
|
|
2232
|
+
cssVars: Record<string, string>;
|
|
2233
|
+
/** Google-Fonts stylesheet hrefs for any registry fonts in use. */
|
|
2234
|
+
fontHrefs: string[];
|
|
2235
|
+
}
|
|
2236
|
+
/**
|
|
2237
|
+
* Pure half of `applyGlobalStyleTokens`: compute the exact CSS custom
|
|
2238
|
+
* properties (and webfont hrefs) a settings object maps to, without touching
|
|
2239
|
+
* any DOM. This is what lets a host SERVER-render a theme with the same vars
|
|
2240
|
+
* the bundle applies on mount — both sides call this one function, so the
|
|
2241
|
+
* values cannot drift (drift = unstyled flash or hydration noise).
|
|
2242
|
+
*
|
|
2243
|
+
* Includes the explicit `heading_font` / `body_font` resolution that
|
|
2244
|
+
* `mountTheme` historically layered on top: any string value for those two
|
|
2245
|
+
* ids resolves through the registry (or passes verbatim) so a picked font
|
|
2246
|
+
* gets a real stack even when it isn't a known token.
|
|
2247
|
+
*/
|
|
2248
|
+
declare function computeGlobalStyleTokens(globalSettings: GlobalSettings): ComputedStyleTokens;
|
|
2129
2249
|
/**
|
|
2130
2250
|
* Map a store's global settings onto CSS custom properties on `el`. Call on
|
|
2131
2251
|
* mount and on every `applyDraft` (live preview). No-op when `el` or the
|
|
2132
2252
|
* settings are missing. Reserved `__`-prefixed keys (e.g. `__translations`)
|
|
2133
|
-
* are skipped.
|
|
2253
|
+
* are skipped. Thin DOM shell over `computeGlobalStyleTokens`.
|
|
2134
2254
|
*/
|
|
2135
2255
|
declare function applyGlobalStyleTokens(globalSettings: GlobalSettings, el: HTMLElement | null | undefined): void;
|
|
2136
2256
|
|
|
@@ -2192,4 +2312,4 @@ declare function pickTranslations(bundle: LocaleBundle, locale: string): LocaleM
|
|
|
2192
2312
|
*/
|
|
2193
2313
|
declare function buildLocaleBundle<T extends Record<string, unknown>>(modules: T): LocaleBundle;
|
|
2194
2314
|
|
|
2195
|
-
export { AddToCartButton, type AddressInput, type AnalyticsApi, type AnalyticsPayload, type AppManifestBlock, type AppPayload, type AppState, Block, BlockInstance, BlockProps$1 as BlockProps, BlockSchema, Cart, CartContext, type CheckoutAddress, type CheckoutApi, type CheckoutSessionState, type CheckoutStep, Collection, CollectionCard, type CollectionCardProps, type CollectionCardSlots, CollectionContext, CollectionProvider, type CurrencyConfig, type CurrencyState, CurrencySwitcher, type CurrencySwitcherProps, Customer, type CustomerAddress, type CustomerAddressesState, CustomerContext, type DefineBlockInput, type DefineSectionInput, type DefinedBlock, type DefinedSection, type DynamicResolveContext, type DynamicSourceRef, EditableImage, type EditableImageProps, EditableText, type EditableTextProps, type FocalSrcOptions, Form, type GiftCardBalance, ICON_NAMES, Icon, IconMap, type IconProps, Image, type ImageTransform, Link, type LocaleBundle, type LocaleMessages, LocaleSwitcher, type LocaleSwitcherProps, LocalizationContext, type MenuItemData, Money, MountResult, NavigationContext, type NavigationItem, type NavigationState, NuMuProvider, type OrderDetail, type OrderListEntry, type OrderListState, type OrderState, Page, PageContext, type PlaceOrderResult, Product, ProductCard, type ProductCardProps, type ProductCardSlots, ProductContext, ProductProvider, ProductVariant, type RelatedProductsState, type ReorderResult, type ReorderSkipReason, type ReorderSkippedItem, RichText, type RichTextProps, type SearchResults, type SearchState, Section, SectionContext, SectionInstance, SectionProps$1 as SectionProps, SectionSchema, type ShippingRateOption, ShopContext, type ShopWithHelpers, Store, type ThemeMountContext, type ThemeMountPage, type ThemeRenderArgs, ThemeSettingsContext, ThemeSettingsV3, type UseGiftCardBalance, type UseReorder, type UseSearchOptions, type UseShippingRatesOptions, type UseShippingRatesState, type UseVariantSelection, type WishlistItem, type WishlistState, applyGlobalStyleTokens, applyImageTransform, asImageTransform, assetUrl, availableValues, buildLocaleBundle, clearSdkSingleton, collectBlocks, collectSections, defaultVariant, defineBlock, defineSection, dynamicSource, findVariantByOptions, flattenMessages, focalSrc, getReactSingleton, getSdkSingleton, isDefinedBlock, isDefinedSection, isDynamicSource, isSdkAvailable, mountTheme, pickTranslations, registerReactSingleton, registerSdkSingleton, resolveDynamicValue, resolveFontStack, resolveSettingsMap, resolveSourcePath, sanitizeHtml, useAnalytics, useApp, useCart, useCheckout, useCollection, useCollectionOptional, useCollections, useCurrency, useCurrentTemplate, useCustomer, useCustomerActions, useCustomerAddresses, useDirection, useFieldTranslation, useGiftCardBalance, useImage, useLocale, useLocalization, useMoney, useNavigation, useNumberFormat, useOrder, useOrders, usePage, useProduct, useProductOptional, useProducts, useRelatedProducts, useReorder, useResolvedSettings, useSearch, useSection, useSectionOptional, useShippingRates, useShop, useThemeSettings, useTranslation, useVariantSelection, useWishlist };
|
|
2315
|
+
export { AddToCartButton, type AddressInput, type AnalyticsApi, type AnalyticsPayload, type AppManifestBlock, type AppPayload, type AppState, Block, BlockInstance, BlockProps$1 as BlockProps, BlockSchema, Cart, CartContext, type CheckoutAddress, type CheckoutApi, type CheckoutSessionState, type CheckoutStep, Collection, CollectionCard, type CollectionCardProps, type CollectionCardSlots, CollectionContext, CollectionProvider, type ComputedStyleTokens, type CurrencyConfig, type CurrencyState, CurrencySwitcher, type CurrencySwitcherProps, Customer, type CustomerAddress, type CustomerAddressesState, CustomerContext, type DefineBlockInput, type DefineSectionInput, type DefinedBlock, type DefinedSection, type DynamicResolveContext, type DynamicSourceRef, EditableImage, type EditableImageProps, EditableText, type EditableTextProps, type FocalSrcOptions, Form, type GiftCardBalance, ICON_NAMES, Icon, IconMap, type IconProps, Image, type ImageTransform, Link, type LocaleBundle, type LocaleMessages, LocaleSwitcher, type LocaleSwitcherProps, LocalizationContext, type MenuItemData, Money, MountResult, NavigationContext, type NavigationItem, type NavigationState, NuMuProvider, type OrderDetail, type OrderListEntry, type OrderListState, type OrderState, Page, PageContext, type PlaceOrderResult, Product, ProductCard, type ProductCardProps, type ProductCardSlots, ProductContext, ProductProvider, ProductVariant, type RelatedProductsState, type ReorderResult, type ReorderSkipReason, type ReorderSkippedItem, RichText, type RichTextProps, type SearchResults, type SearchState, Section, SectionContext, SectionInstance, SectionProps$1 as SectionProps, SectionSchema, type ShippingRateOption, ShopContext, type ShopWithHelpers, SizeChart, Store, type ThemeEntry, type ThemeMountContext, type ThemeMountPage, type ThemeRenderArgs, ThemeSettingsContext, ThemeSettingsV3, type UseGiftCardBalance, type UseReorder, type UseSearchOptions, type UseShippingRatesOptions, type UseShippingRatesState, type UseVariantSelection, type WishlistItem, type WishlistState, applyGlobalStyleTokens, applyImageTransform, asImageTransform, assetUrl, availableValues, buildLocaleBundle, buildThemeElement, clearSdkSingleton, collectBlocks, collectSections, computeGlobalStyleTokens, defaultVariant, defineBlock, defineSection, defineThemeEntry, dynamicSource, findVariantByOptions, flattenMessages, focalSrc, getReactSingleton, getSdkSingleton, isDefinedBlock, isDefinedSection, isDynamicSource, isSdkAvailable, mountTheme, pickTranslations, registerReactSingleton, registerSdkSingleton, resolveDynamicValue, resolveFontStack, resolveSettingsMap, resolveSizeChart, resolveSourcePath, sanitizeHtml, useAnalytics, useApp, useCart, useCheckout, useCollection, useCollectionOptional, useCollections, useCurrency, useCurrentTemplate, useCustomer, useCustomerActions, useCustomerAddresses, useDirection, useFieldTranslation, useGiftCardBalance, useImage, useLocale, useLocalization, useMoney, useNavigation, useNumberFormat, useOrder, useOrders, usePage, useProduct, useProductOptional, useProductSizeChart, useProducts, useRelatedProducts, useReorder, useResolvedSettings, useSearch, useSection, useSectionOptional, useShippingRates, useShop, useThemeSettings, useTranslation, useVariantSelection, useWishlist };
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createContext, forwardRef, useState, useImperativeHandle, useEffect, useCallback, useMemo, useRef, useContext, StrictMode, createElement, Component } from 'react';
|
|
2
|
-
import { createRoot } from 'react-dom/client';
|
|
2
|
+
import { hydrateRoot, createRoot } from 'react-dom/client';
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
|
|
5
5
|
// src/types/theme.ts
|
|
@@ -940,6 +940,29 @@ function useRelatedProducts(productId, options = {}) {
|
|
|
940
940
|
}, [productId, limit]);
|
|
941
941
|
return { items, loading, error };
|
|
942
942
|
}
|
|
943
|
+
function useProductSizeChart(productOverride) {
|
|
944
|
+
const ctxProduct = useProductOptional();
|
|
945
|
+
const product = productOverride ?? ctxProduct;
|
|
946
|
+
const shop = useShop();
|
|
947
|
+
const storeSettings = shop?.settings;
|
|
948
|
+
return useMemo(
|
|
949
|
+
() => resolveSizeChart(product?.attributes, storeSettings),
|
|
950
|
+
[product?.attributes, storeSettings]
|
|
951
|
+
);
|
|
952
|
+
}
|
|
953
|
+
function hasRows(c) {
|
|
954
|
+
return !!c && typeof c === "object" && Array.isArray(c.rows) && c.rows.length > 0;
|
|
955
|
+
}
|
|
956
|
+
function resolveSizeChart(productAttributes, storeSettings) {
|
|
957
|
+
const product = productAttributes?.size_chart;
|
|
958
|
+
const storeDefault = storeSettings?.size_chart;
|
|
959
|
+
if (product?.mode === "off") return null;
|
|
960
|
+
if (product?.mode === "custom") return hasRows(product) ? product : null;
|
|
961
|
+
if (product?.mode === "default") return hasRows(storeDefault) ? storeDefault : null;
|
|
962
|
+
if (hasRows(product)) return product;
|
|
963
|
+
if (hasRows(storeDefault)) return storeDefault;
|
|
964
|
+
return null;
|
|
965
|
+
}
|
|
943
966
|
var COOKIE_NAME = "numu_currency";
|
|
944
967
|
var COOKIE_MAX_AGE = 60 * 60 * 24 * 30;
|
|
945
968
|
function readCookie(name) {
|
|
@@ -1989,6 +2012,9 @@ function injectFontLink(href) {
|
|
|
1989
2012
|
link.setAttribute("data-numu-font", "");
|
|
1990
2013
|
document.head.appendChild(link);
|
|
1991
2014
|
}
|
|
2015
|
+
function lookupFontStack(value) {
|
|
2016
|
+
return FONT_REGISTRY[value]?.stack ?? value;
|
|
2017
|
+
}
|
|
1992
2018
|
function resolveFontStack(value) {
|
|
1993
2019
|
const entry = FONT_REGISTRY[value];
|
|
1994
2020
|
if (entry) {
|
|
@@ -1997,39 +2023,69 @@ function resolveFontStack(value) {
|
|
|
1997
2023
|
}
|
|
1998
2024
|
return value;
|
|
1999
2025
|
}
|
|
2000
|
-
function
|
|
2001
|
-
|
|
2002
|
-
const
|
|
2026
|
+
function computeGlobalStyleTokens(globalSettings) {
|
|
2027
|
+
const cssVars = {};
|
|
2028
|
+
const fontHrefs = [];
|
|
2029
|
+
if (!globalSettings || typeof globalSettings !== "object") {
|
|
2030
|
+
return { cssVars, fontHrefs };
|
|
2031
|
+
}
|
|
2032
|
+
const pushHref = (href) => {
|
|
2033
|
+
if (href && !fontHrefs.includes(href)) fontHrefs.push(href);
|
|
2034
|
+
};
|
|
2003
2035
|
for (const [key, value] of Object.entries(globalSettings)) {
|
|
2004
2036
|
if (!key || key.startsWith("__")) continue;
|
|
2005
2037
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
2006
2038
|
for (const [role, c] of Object.entries(value)) {
|
|
2007
|
-
if (isColorValue(c))
|
|
2039
|
+
if (isColorValue(c)) cssVars[`--scheme-${key}-${role}`] = c;
|
|
2008
2040
|
}
|
|
2009
2041
|
continue;
|
|
2010
2042
|
}
|
|
2011
2043
|
if (isColorValue(value)) {
|
|
2012
|
-
|
|
2044
|
+
cssVars[`--theme-${key}`] = value.trim();
|
|
2013
2045
|
const role = COLOR_ROLE_ALIASES[key];
|
|
2014
|
-
if (role)
|
|
2046
|
+
if (role) cssVars[`--theme-color-${role}`] = value.trim();
|
|
2015
2047
|
continue;
|
|
2016
2048
|
}
|
|
2017
2049
|
if (isFontToken(value)) {
|
|
2018
|
-
const
|
|
2019
|
-
|
|
2050
|
+
const entry = FONT_REGISTRY[value];
|
|
2051
|
+
cssVars[`--theme-${key}`] = entry.stack;
|
|
2020
2052
|
const role = FONT_ROLE_ALIASES[key];
|
|
2021
|
-
if (role)
|
|
2053
|
+
if (role) cssVars[`--theme-font-${role}`] = entry.stack;
|
|
2054
|
+
pushHref(entry.href);
|
|
2022
2055
|
continue;
|
|
2023
2056
|
}
|
|
2024
2057
|
if (typeof value === "string" || typeof value === "number") {
|
|
2025
2058
|
const v = String(value).trim();
|
|
2026
|
-
if (v)
|
|
2059
|
+
if (v) cssVars[`--theme-${key}`] = v;
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
for (const id of ["heading_font", "body_font"]) {
|
|
2063
|
+
const value = globalSettings[id];
|
|
2064
|
+
if (typeof value === "string" && value.trim()) {
|
|
2065
|
+
cssVars[`--theme-${id}`] = lookupFontStack(value);
|
|
2066
|
+
pushHref(FONT_REGISTRY[value]?.href);
|
|
2027
2067
|
}
|
|
2028
2068
|
}
|
|
2069
|
+
return { cssVars, fontHrefs };
|
|
2070
|
+
}
|
|
2071
|
+
function applyGlobalStyleTokens(globalSettings, el) {
|
|
2072
|
+
if (!el || !globalSettings || typeof globalSettings !== "object") return;
|
|
2073
|
+
const { cssVars, fontHrefs } = computeGlobalStyleTokens(globalSettings);
|
|
2074
|
+
const style = el.style;
|
|
2075
|
+
for (const [prop, value] of Object.entries(cssVars)) {
|
|
2076
|
+
style.setProperty(prop, value);
|
|
2077
|
+
}
|
|
2078
|
+
for (const href of fontHrefs) injectFontLink(href);
|
|
2029
2079
|
}
|
|
2030
2080
|
function pickStore(ctx) {
|
|
2031
2081
|
const s = ctx.storeData ?? ctx.store;
|
|
2032
|
-
if (s)
|
|
2082
|
+
if (s) {
|
|
2083
|
+
const raw = s;
|
|
2084
|
+
if (!raw.currency && raw.default_currency) {
|
|
2085
|
+
return { ...raw, currency: raw.default_currency };
|
|
2086
|
+
}
|
|
2087
|
+
return s;
|
|
2088
|
+
}
|
|
2033
2089
|
return {
|
|
2034
2090
|
id: "unknown",
|
|
2035
2091
|
name: "Store",
|
|
@@ -2064,19 +2120,9 @@ var ThemeMountBridge = forwardRef(function ThemeMountBridge2({ ctx, mountEl, ren
|
|
|
2064
2120
|
[]
|
|
2065
2121
|
);
|
|
2066
2122
|
useEffect(() => {
|
|
2123
|
+
if (!mountEl) return;
|
|
2067
2124
|
const gs = themeSettings.global_settings ?? {};
|
|
2068
2125
|
applyGlobalStyleTokens(gs, mountEl);
|
|
2069
|
-
const headingFont = gs.heading_font;
|
|
2070
|
-
if (typeof headingFont === "string" && headingFont.trim()) {
|
|
2071
|
-
mountEl.style.setProperty(
|
|
2072
|
-
"--theme-heading_font",
|
|
2073
|
-
resolveFontStack(headingFont)
|
|
2074
|
-
);
|
|
2075
|
-
}
|
|
2076
|
-
const bodyFont = gs.body_font;
|
|
2077
|
-
if (typeof bodyFont === "string" && bodyFont.trim()) {
|
|
2078
|
-
mountEl.style.setProperty("--theme-body_font", resolveFontStack(bodyFont));
|
|
2079
|
-
}
|
|
2080
2126
|
}, [themeSettings, mountEl]);
|
|
2081
2127
|
const store = pickStore(ctx);
|
|
2082
2128
|
const template = pickTemplate(ctx);
|
|
@@ -2106,22 +2152,22 @@ var ThemeMountBridge = forwardRef(function ThemeMountBridge2({ ctx, mountEl, ren
|
|
|
2106
2152
|
}
|
|
2107
2153
|
);
|
|
2108
2154
|
});
|
|
2155
|
+
function buildThemeElement(ctx, mountEl, renderApp, ref) {
|
|
2156
|
+
return /* @__PURE__ */ jsx(StrictMode, { children: /* @__PURE__ */ jsx(ThemeMountBridge, { ctx, mountEl, renderApp, ref }) });
|
|
2157
|
+
}
|
|
2109
2158
|
function mountTheme(el, ctx, renderApp) {
|
|
2110
|
-
const root = createRoot(el);
|
|
2111
2159
|
const handleRef = { current: null };
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
) })
|
|
2124
|
-
);
|
|
2160
|
+
const element = buildThemeElement(ctx, el, renderApp, (h) => {
|
|
2161
|
+
handleRef.current = h;
|
|
2162
|
+
});
|
|
2163
|
+
const shouldHydrate = ctx.hydrate === true && el.firstElementChild !== null;
|
|
2164
|
+
let root;
|
|
2165
|
+
if (shouldHydrate) {
|
|
2166
|
+
root = hydrateRoot(el, element);
|
|
2167
|
+
} else {
|
|
2168
|
+
root = createRoot(el);
|
|
2169
|
+
root.render(element);
|
|
2170
|
+
}
|
|
2125
2171
|
return {
|
|
2126
2172
|
applyDraft: (next) => handleRef.current?.applyDraft(next),
|
|
2127
2173
|
cleanup: () => {
|
|
@@ -2130,6 +2176,14 @@ function mountTheme(el, ctx, renderApp) {
|
|
|
2130
2176
|
}
|
|
2131
2177
|
};
|
|
2132
2178
|
}
|
|
2179
|
+
|
|
2180
|
+
// src/entry.tsx
|
|
2181
|
+
function defineThemeEntry(renderApp) {
|
|
2182
|
+
return {
|
|
2183
|
+
mount: (el, ctx) => mountTheme(el, ctx, renderApp),
|
|
2184
|
+
createApp: (ctx) => buildThemeElement(ctx, null, renderApp)
|
|
2185
|
+
};
|
|
2186
|
+
}
|
|
2133
2187
|
function CollectionProvider({ collection, children }) {
|
|
2134
2188
|
return /* @__PURE__ */ jsx(CollectionContext.Provider, { value: collection, children });
|
|
2135
2189
|
}
|
|
@@ -2753,7 +2807,14 @@ function sanitizeHtmlServer(input) {
|
|
|
2753
2807
|
return s;
|
|
2754
2808
|
}
|
|
2755
2809
|
function RichText({ html, className, as = "div" }) {
|
|
2756
|
-
const
|
|
2810
|
+
const [domReady, setDomReady] = useState(false);
|
|
2811
|
+
useEffect(() => {
|
|
2812
|
+
setDomReady(true);
|
|
2813
|
+
}, []);
|
|
2814
|
+
const safe = useMemo(
|
|
2815
|
+
() => domReady ? sanitizeHtml(html || "") : sanitizeHtmlServer(html || ""),
|
|
2816
|
+
[html, domReady]
|
|
2817
|
+
);
|
|
2757
2818
|
if (!safe) return null;
|
|
2758
2819
|
const Tag = as;
|
|
2759
2820
|
return /* @__PURE__ */ jsx(
|
|
@@ -3419,8 +3480,13 @@ function collectBlocks(modules) {
|
|
|
3419
3480
|
|
|
3420
3481
|
// src/utils/assetUrl.ts
|
|
3421
3482
|
function getRuntime() {
|
|
3422
|
-
if (typeof window
|
|
3423
|
-
|
|
3483
|
+
if (typeof window !== "undefined") {
|
|
3484
|
+
return window;
|
|
3485
|
+
}
|
|
3486
|
+
if (typeof globalThis !== "undefined") {
|
|
3487
|
+
return globalThis;
|
|
3488
|
+
}
|
|
3489
|
+
return {};
|
|
3424
3490
|
}
|
|
3425
3491
|
function assetUrl(name) {
|
|
3426
3492
|
if (!name) return "";
|
|
@@ -3481,6 +3547,6 @@ function buildLocaleBundle(modules) {
|
|
|
3481
3547
|
return bundle;
|
|
3482
3548
|
}
|
|
3483
3549
|
|
|
3484
|
-
export { AddToCartButton, Block, CartContext, CollectionCard, CollectionContext, CollectionProvider, CurrencySwitcher, CustomerContext, EditableImage, EditableText, Form, ICON_NAMES, Icon, IconMap, Image, Link, LocaleSwitcher, LocalizationContext, MAX_BLOCK_DEPTH, Money, NavigationContext, NuMuProvider, PageContext, ProductCard, ProductContext, ProductProvider, RichText, Section, SectionContext, ShopContext, ThemeSettingsContext, applyGlobalStyleTokens, applyImageTransform, asImageTransform, assetUrl, availableValues, buildLocaleBundle, clearSdkSingleton, collectBlocks, collectSections, defaultVariant, defineBlock, defineSection, dynamicSource, findVariantByOptions, flattenMessages, focalSrc, getReactSingleton, getSdkSingleton, isDefinedBlock, isDefinedSection, isDynamicSource, isSdkAvailable, mountTheme, pickTranslations, registerReactSingleton, registerSdkSingleton, resolveDynamicValue, resolveFontStack, resolveSettingsMap, resolveSourcePath, resolveThemeSettings, sanitizeHtml, useAnalytics, useApp, useCart, useCheckout, useCollection, useCollectionOptional, useCollections, useCurrency, useCurrentTemplate, useCustomer, useCustomerActions, useCustomerAddresses, useDirection, useFieldTranslation, useGiftCardBalance, useImage, useLocale, useLocalization, useMoney, useNavigation, useNumberFormat, useOrder, useOrders, usePage, useProduct, useProductOptional, useProducts, useRelatedProducts, useReorder, useResolvedSettings, useSearch, useSection, useSectionOptional, useShippingRates, useShop, useThemeSettings, useTranslation, useVariantSelection, useWishlist };
|
|
3550
|
+
export { AddToCartButton, Block, CartContext, CollectionCard, CollectionContext, CollectionProvider, CurrencySwitcher, CustomerContext, EditableImage, EditableText, Form, ICON_NAMES, Icon, IconMap, Image, Link, LocaleSwitcher, LocalizationContext, MAX_BLOCK_DEPTH, Money, NavigationContext, NuMuProvider, PageContext, ProductCard, ProductContext, ProductProvider, RichText, Section, SectionContext, ShopContext, ThemeSettingsContext, applyGlobalStyleTokens, applyImageTransform, asImageTransform, assetUrl, availableValues, buildLocaleBundle, buildThemeElement, clearSdkSingleton, collectBlocks, collectSections, computeGlobalStyleTokens, defaultVariant, defineBlock, defineSection, defineThemeEntry, dynamicSource, findVariantByOptions, flattenMessages, focalSrc, getReactSingleton, getSdkSingleton, isDefinedBlock, isDefinedSection, isDynamicSource, isSdkAvailable, mountTheme, pickTranslations, registerReactSingleton, registerSdkSingleton, resolveDynamicValue, resolveFontStack, resolveSettingsMap, resolveSizeChart, resolveSourcePath, resolveThemeSettings, sanitizeHtml, useAnalytics, useApp, useCart, useCheckout, useCollection, useCollectionOptional, useCollections, useCurrency, useCurrentTemplate, useCustomer, useCustomerActions, useCustomerAddresses, useDirection, useFieldTranslation, useGiftCardBalance, useImage, useLocale, useLocalization, useMoney, useNavigation, useNumberFormat, useOrder, useOrders, usePage, useProduct, useProductOptional, useProductSizeChart, useProducts, useRelatedProducts, useReorder, useResolvedSettings, useSearch, useSection, useSectionOptional, useShippingRates, useShop, useThemeSettings, useTranslation, useVariantSelection, useWishlist };
|
|
3485
3551
|
//# sourceMappingURL=index.mjs.map
|
|
3486
3552
|
//# sourceMappingURL=index.mjs.map
|