@weaverse/hydrogen 5.9.5 → 5.10.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/dist/index.d.mts CHANGED
@@ -8,7 +8,7 @@ import { createWithCache, CachingStrategy, I18nBase, HydrogenContext, HydrogenEn
8
8
  export { CachingStrategy } from '@shopify/hydrogen';
9
9
  import { LoaderFunctionArgs, AppLoadContext } from '@shopify/remix-oxygen';
10
10
  import * as React$1 from 'react';
11
- import { ComponentType, JSX, ForwardRefExoticComponent } from 'react';
11
+ import { ReactNode, ComponentType, JSX, ForwardRefExoticComponent } from 'react';
12
12
  import { NavigateFunction, UIMatch } from 'react-router';
13
13
  import * as react_jsx_runtime from 'react/jsx-runtime';
14
14
 
@@ -33,6 +33,76 @@ declare class ThemeSettingsStore {
33
33
  destroy: () => void;
34
34
  }
35
35
 
36
+ /**
37
+ * Traverse a nested object by dot-path.
38
+ *
39
+ * @example
40
+ * getNestedKey({ cart: { title: 'Cart' } }, 'cart.title') // => 'Cart'
41
+ * getNestedKey({}, 'cart.title', 'fallback') // => 'fallback'
42
+ */
43
+ declare function getNestedKey(obj: Record<string, unknown>, path: string, fallback?: string): string | undefined;
44
+ /**
45
+ * Replace `{{variable}}` patterns in a string with provided values.
46
+ *
47
+ * @example
48
+ * interpolate('Hello {{name}}!', { name: 'World' }) // => 'Hello World!'
49
+ * interpolate('-{{percentage}}% Off', { percentage: 15 }) // => '-15% Off'
50
+ */
51
+ declare function interpolate(template: string, variables?: Record<string, string | number>): string;
52
+ /**
53
+ * Signature for a translation function.
54
+ */
55
+ type TranslateFunction = (key: string, variables?: Record<string, string | number>) => string;
56
+ type ThemeTextValue = {
57
+ /**
58
+ * Translate a key with optional variable interpolation.
59
+ *
60
+ * Priority chain (highest wins):
61
+ * 1. External `t` (passed into `withWeaverse` / `ThemeTextProvider`)
62
+ * 2. `merchantOverrides` (DB overrides for the current locale)
63
+ * 3. `staticContent` (theme default JSON)
64
+ * 4. The key itself (fallback)
65
+ *
66
+ * @example
67
+ * t('cart.title') // => "Cart"
68
+ * t('badge.sale', { percentage: 15 }) // => "-15% Off"
69
+ */
70
+ t: TranslateFunction;
71
+ };
72
+ type ThemeTextProviderProps = {
73
+ staticContent: Record<string, unknown>;
74
+ merchantOverrides?: Record<string, unknown>;
75
+ /**
76
+ * Optional external translation function.
77
+ * When provided it becomes the **highest-priority** source:
78
+ * if it returns a non-empty string that differs from the raw key,
79
+ * that value is used; otherwise the internal resolution chain continues.
80
+ */
81
+ t?: TranslateFunction;
82
+ children: ReactNode;
83
+ };
84
+ /**
85
+ * Provider that wraps the app to expose the `t()` function.
86
+ *
87
+ * - `staticContent` – the theme's default locale JSON (from themeSchema.i18n)
88
+ * - `merchantOverrides` – locale-specific overrides fetched from the API
89
+ */
90
+ declare function ThemeTextProvider({ staticContent, merchantOverrides, t: externalT, children, }: ThemeTextProviderProps): react_jsx_runtime.JSX.Element;
91
+ /**
92
+ * Hook to access the theme text `t()` function.
93
+ *
94
+ * Must be used inside a component wrapped by `withWeaverse` or `ThemeTextProvider`.
95
+ *
96
+ * @example
97
+ * ```tsx
98
+ * function CartTitle() {
99
+ * const { t } = useThemeText()
100
+ * return <h2>{t('cart.title')}</h2>
101
+ * }
102
+ * ```
103
+ */
104
+ declare function useThemeText(): ThemeTextValue;
105
+
36
106
  declare class WeaverseHydrogenItem extends WeaverseItemStore {
37
107
  weaverse: WeaverseHydrogen;
38
108
  constructor(initialData: HydrogenComponentData, weaverse: WeaverseHydrogen);
@@ -86,24 +156,36 @@ declare const WeaverseHydrogenRoot: React$1.MemoExoticComponent<({ components, e
86
156
  }>;
87
157
  }) => react_jsx_runtime.JSX.Element>;
88
158
  /**
89
- * Higher-order component that wraps your app with Weaverse theme settings context.
90
- * Provides theme settings to all child components via React context.
159
+ * Options for the `withWeaverse` HOC.
160
+ */
161
+ type WithWeaverseOptions = {
162
+ /**
163
+ * Optional external translation function (e.g. from Shopify i18n).
164
+ * When provided it becomes the **highest-priority** source
165
+ * in the `t()` resolution chain exposed by `useThemeText()`.
166
+ */
167
+ t?: TranslateFunction;
168
+ };
169
+ /**
170
+ * Higher-order component that wraps your app with Weaverse theme settings
171
+ * and translation context.
91
172
  *
92
173
  * @param Component - The root component to wrap
93
- * @returns Wrapped component with theme settings provider
174
+ * @param options - Optional configuration (e.g. an external `t` function)
175
+ * @returns Wrapped component with theme settings + translation providers
94
176
  *
95
177
  * @example
96
178
  * ```typescript
97
179
  * import { withWeaverse } from '@weaverse/hydrogen'
98
180
  *
99
- * function App() {
100
- * return <div>My App</div>
101
- * }
102
- *
181
+ * // Basic usage
103
182
  * export default withWeaverse(App)
183
+ *
184
+ * // With external translation function
185
+ * export default withWeaverse(App, { t: myI18nFunction })
104
186
  * ```
105
187
  */
106
- declare function withWeaverse(Component: ComponentType<any>): (props: JSX.IntrinsicAttributes) => react_jsx_runtime.JSX.Element;
188
+ declare function withWeaverse(Component: ComponentType<any>, options?: WithWeaverseOptions): (props: JSX.IntrinsicAttributes) => react_jsx_runtime.JSX.Element;
107
189
  /**
108
190
  * React hook to access Weaverse theme settings from anywhere in your component tree.
109
191
  * Must be used within a component wrapped by `withWeaverse` or inside `WeaverseHydrogenRoot`.
@@ -258,6 +340,12 @@ declare class WeaverseClient {
258
340
  * ```
259
341
  */
260
342
  loadThemeSettings: (strategy?: CachingStrategy) => Promise<ThemeSettingsResponse>;
343
+ /**
344
+ * Fetch locale-specific merchant overrides from the translation API.
345
+ * Returns a nested JSON object with translated values.
346
+ * Falls back to empty object on error to avoid blocking theme rendering.
347
+ */
348
+ private fetchMerchantOverrides;
261
349
  /**
262
350
  * Generate fallback page with default structure when page data is unavailable.
263
351
  * Used internally when API returns no page or when page needs default content.
@@ -443,6 +531,9 @@ type WeaverseI18n = I18nBase & {
443
531
  [key: string]: any;
444
532
  };
445
533
  type HydrogenThemeSchema = {
534
+ betaFlags?: {
535
+ contentManager?: boolean;
536
+ };
446
537
  info: {
447
538
  name: string;
448
539
  version: string;
@@ -458,6 +549,7 @@ type HydrogenThemeSchema = {
458
549
  urlStructure: 'url-path' | 'subdomain' | 'top-level-domain';
459
550
  defaultLocale: WeaverseI18n;
460
551
  shopLocales: WeaverseI18n[];
552
+ staticContent?: Record<string, unknown>;
461
553
  };
462
554
  };
463
555
  type FetchProjectRequestBody = {
@@ -620,6 +712,10 @@ type ThemeSettingsResponse = {
620
712
  theme?: HydrogenThemeSettings;
621
713
  schema?: HydrogenThemeSchema;
622
714
  publicEnv?: PublicEnv;
715
+ /** Theme's default locale JSON from themeSchema.i18n.staticContent */
716
+ staticContent?: Record<string, unknown>;
717
+ /** Locale-specific merchant overrides from the API */
718
+ merchantOverrides?: Record<string, unknown>;
623
719
  _error?: string;
624
720
  _loadFailed?: boolean;
625
721
  };
@@ -924,4 +1020,4 @@ declare const IMAGES_PLACEHOLDERS: {
924
1020
  product_18: string;
925
1021
  };
926
1022
 
927
- export { type CacheResponseValidator, type ComponentDataValue, type ComponentLoaderArgs, type CreateHydrogenSchemaOptions, type DirectFetchResponse, type FetchProjectPayload, type FetchProjectRequestBody, type HydrogenComponent, type HydrogenComponentData, type HydrogenComponentPresets, type HydrogenComponentProps, type HydrogenComponentSchema, type HydrogenElement, type HydrogenPageAssignment, type HydrogenPageData, type HydrogenProjectType, type HydrogenSchemaValidationResult, type HydrogenThemeSchema, type HydrogenThemeSettings, IMAGES_PLACEHOLDERS, type LoadPageParams, type ProjectIdValidationResult, type ProjectIdValue, type PublicEnv, type RouteLoaderArgs, type ThemeSettingsResponse, type WeaverseArticle, type WeaverseBlog, WeaverseClient, type WeaverseClientArgs, type WeaverseCollection, type WeaverseDataContext, WeaverseError, WeaverseHydrogen, WeaverseHydrogenItem, type WeaverseHydrogenParams, WeaverseHydrogenRoot, type WeaverseI18n, type WeaverseInternal, type WeaverseLoaderData, type WeaverseLoaderRequestInfo, type WeaverseMetaObject, type WeaverseProduct, type WeaverseProjectConfigs, type WeaverseStudioQueries, type WithCacheFetchResponse, createWeaverseDataContext, defaultComponents, generateDataFromSchema, getPreviewData, getRequestQueries, getSelectedProductOptions, getWeaverseConfigs, hasError, hasWeaverseStudio, isFetchProjectPayload, isProjectIdFunction, isThemeSettingsResponse, isValidHydrogenSchema, isWithCacheFetchResponse, registerComponent, useThemeSettings, useWeaverseDataContext, withWeaverse };
1023
+ export { type CacheResponseValidator, type ComponentDataValue, type ComponentLoaderArgs, type CreateHydrogenSchemaOptions, type DirectFetchResponse, type FetchProjectPayload, type FetchProjectRequestBody, type HydrogenComponent, type HydrogenComponentData, type HydrogenComponentPresets, type HydrogenComponentProps, type HydrogenComponentSchema, type HydrogenElement, type HydrogenPageAssignment, type HydrogenPageData, type HydrogenProjectType, type HydrogenSchemaValidationResult, type HydrogenThemeSchema, type HydrogenThemeSettings, IMAGES_PLACEHOLDERS, type LoadPageParams, type ProjectIdValidationResult, type ProjectIdValue, type PublicEnv, type RouteLoaderArgs, type ThemeSettingsResponse, ThemeTextProvider, type ThemeTextProviderProps, type ThemeTextValue, type TranslateFunction, type WeaverseArticle, type WeaverseBlog, WeaverseClient, type WeaverseClientArgs, type WeaverseCollection, type WeaverseDataContext, WeaverseError, WeaverseHydrogen, WeaverseHydrogenItem, type WeaverseHydrogenParams, WeaverseHydrogenRoot, type WeaverseI18n, type WeaverseInternal, type WeaverseLoaderData, type WeaverseLoaderRequestInfo, type WeaverseMetaObject, type WeaverseProduct, type WeaverseProjectConfigs, type WeaverseStudioQueries, type WithCacheFetchResponse, type WithWeaverseOptions, createWeaverseDataContext, defaultComponents, generateDataFromSchema, getNestedKey, getPreviewData, getRequestQueries, getSelectedProductOptions, getWeaverseConfigs, hasError, hasWeaverseStudio, interpolate, isFetchProjectPayload, isProjectIdFunction, isThemeSettingsResponse, isValidHydrogenSchema, isWithCacheFetchResponse, registerComponent, useThemeSettings, useThemeText, useWeaverseDataContext, withWeaverse };
package/dist/index.d.ts CHANGED
@@ -8,7 +8,7 @@ import { createWithCache, CachingStrategy, I18nBase, HydrogenContext, HydrogenEn
8
8
  export { CachingStrategy } from '@shopify/hydrogen';
9
9
  import { LoaderFunctionArgs, AppLoadContext } from '@shopify/remix-oxygen';
10
10
  import * as React$1 from 'react';
11
- import { ComponentType, JSX, ForwardRefExoticComponent } from 'react';
11
+ import { ReactNode, ComponentType, JSX, ForwardRefExoticComponent } from 'react';
12
12
  import { NavigateFunction, UIMatch } from 'react-router';
13
13
  import * as react_jsx_runtime from 'react/jsx-runtime';
14
14
 
@@ -33,6 +33,76 @@ declare class ThemeSettingsStore {
33
33
  destroy: () => void;
34
34
  }
35
35
 
36
+ /**
37
+ * Traverse a nested object by dot-path.
38
+ *
39
+ * @example
40
+ * getNestedKey({ cart: { title: 'Cart' } }, 'cart.title') // => 'Cart'
41
+ * getNestedKey({}, 'cart.title', 'fallback') // => 'fallback'
42
+ */
43
+ declare function getNestedKey(obj: Record<string, unknown>, path: string, fallback?: string): string | undefined;
44
+ /**
45
+ * Replace `{{variable}}` patterns in a string with provided values.
46
+ *
47
+ * @example
48
+ * interpolate('Hello {{name}}!', { name: 'World' }) // => 'Hello World!'
49
+ * interpolate('-{{percentage}}% Off', { percentage: 15 }) // => '-15% Off'
50
+ */
51
+ declare function interpolate(template: string, variables?: Record<string, string | number>): string;
52
+ /**
53
+ * Signature for a translation function.
54
+ */
55
+ type TranslateFunction = (key: string, variables?: Record<string, string | number>) => string;
56
+ type ThemeTextValue = {
57
+ /**
58
+ * Translate a key with optional variable interpolation.
59
+ *
60
+ * Priority chain (highest wins):
61
+ * 1. External `t` (passed into `withWeaverse` / `ThemeTextProvider`)
62
+ * 2. `merchantOverrides` (DB overrides for the current locale)
63
+ * 3. `staticContent` (theme default JSON)
64
+ * 4. The key itself (fallback)
65
+ *
66
+ * @example
67
+ * t('cart.title') // => "Cart"
68
+ * t('badge.sale', { percentage: 15 }) // => "-15% Off"
69
+ */
70
+ t: TranslateFunction;
71
+ };
72
+ type ThemeTextProviderProps = {
73
+ staticContent: Record<string, unknown>;
74
+ merchantOverrides?: Record<string, unknown>;
75
+ /**
76
+ * Optional external translation function.
77
+ * When provided it becomes the **highest-priority** source:
78
+ * if it returns a non-empty string that differs from the raw key,
79
+ * that value is used; otherwise the internal resolution chain continues.
80
+ */
81
+ t?: TranslateFunction;
82
+ children: ReactNode;
83
+ };
84
+ /**
85
+ * Provider that wraps the app to expose the `t()` function.
86
+ *
87
+ * - `staticContent` – the theme's default locale JSON (from themeSchema.i18n)
88
+ * - `merchantOverrides` – locale-specific overrides fetched from the API
89
+ */
90
+ declare function ThemeTextProvider({ staticContent, merchantOverrides, t: externalT, children, }: ThemeTextProviderProps): react_jsx_runtime.JSX.Element;
91
+ /**
92
+ * Hook to access the theme text `t()` function.
93
+ *
94
+ * Must be used inside a component wrapped by `withWeaverse` or `ThemeTextProvider`.
95
+ *
96
+ * @example
97
+ * ```tsx
98
+ * function CartTitle() {
99
+ * const { t } = useThemeText()
100
+ * return <h2>{t('cart.title')}</h2>
101
+ * }
102
+ * ```
103
+ */
104
+ declare function useThemeText(): ThemeTextValue;
105
+
36
106
  declare class WeaverseHydrogenItem extends WeaverseItemStore {
37
107
  weaverse: WeaverseHydrogen;
38
108
  constructor(initialData: HydrogenComponentData, weaverse: WeaverseHydrogen);
@@ -86,24 +156,36 @@ declare const WeaverseHydrogenRoot: React$1.MemoExoticComponent<({ components, e
86
156
  }>;
87
157
  }) => react_jsx_runtime.JSX.Element>;
88
158
  /**
89
- * Higher-order component that wraps your app with Weaverse theme settings context.
90
- * Provides theme settings to all child components via React context.
159
+ * Options for the `withWeaverse` HOC.
160
+ */
161
+ type WithWeaverseOptions = {
162
+ /**
163
+ * Optional external translation function (e.g. from Shopify i18n).
164
+ * When provided it becomes the **highest-priority** source
165
+ * in the `t()` resolution chain exposed by `useThemeText()`.
166
+ */
167
+ t?: TranslateFunction;
168
+ };
169
+ /**
170
+ * Higher-order component that wraps your app with Weaverse theme settings
171
+ * and translation context.
91
172
  *
92
173
  * @param Component - The root component to wrap
93
- * @returns Wrapped component with theme settings provider
174
+ * @param options - Optional configuration (e.g. an external `t` function)
175
+ * @returns Wrapped component with theme settings + translation providers
94
176
  *
95
177
  * @example
96
178
  * ```typescript
97
179
  * import { withWeaverse } from '@weaverse/hydrogen'
98
180
  *
99
- * function App() {
100
- * return <div>My App</div>
101
- * }
102
- *
181
+ * // Basic usage
103
182
  * export default withWeaverse(App)
183
+ *
184
+ * // With external translation function
185
+ * export default withWeaverse(App, { t: myI18nFunction })
104
186
  * ```
105
187
  */
106
- declare function withWeaverse(Component: ComponentType<any>): (props: JSX.IntrinsicAttributes) => react_jsx_runtime.JSX.Element;
188
+ declare function withWeaverse(Component: ComponentType<any>, options?: WithWeaverseOptions): (props: JSX.IntrinsicAttributes) => react_jsx_runtime.JSX.Element;
107
189
  /**
108
190
  * React hook to access Weaverse theme settings from anywhere in your component tree.
109
191
  * Must be used within a component wrapped by `withWeaverse` or inside `WeaverseHydrogenRoot`.
@@ -258,6 +340,12 @@ declare class WeaverseClient {
258
340
  * ```
259
341
  */
260
342
  loadThemeSettings: (strategy?: CachingStrategy) => Promise<ThemeSettingsResponse>;
343
+ /**
344
+ * Fetch locale-specific merchant overrides from the translation API.
345
+ * Returns a nested JSON object with translated values.
346
+ * Falls back to empty object on error to avoid blocking theme rendering.
347
+ */
348
+ private fetchMerchantOverrides;
261
349
  /**
262
350
  * Generate fallback page with default structure when page data is unavailable.
263
351
  * Used internally when API returns no page or when page needs default content.
@@ -443,6 +531,9 @@ type WeaverseI18n = I18nBase & {
443
531
  [key: string]: any;
444
532
  };
445
533
  type HydrogenThemeSchema = {
534
+ betaFlags?: {
535
+ contentManager?: boolean;
536
+ };
446
537
  info: {
447
538
  name: string;
448
539
  version: string;
@@ -458,6 +549,7 @@ type HydrogenThemeSchema = {
458
549
  urlStructure: 'url-path' | 'subdomain' | 'top-level-domain';
459
550
  defaultLocale: WeaverseI18n;
460
551
  shopLocales: WeaverseI18n[];
552
+ staticContent?: Record<string, unknown>;
461
553
  };
462
554
  };
463
555
  type FetchProjectRequestBody = {
@@ -620,6 +712,10 @@ type ThemeSettingsResponse = {
620
712
  theme?: HydrogenThemeSettings;
621
713
  schema?: HydrogenThemeSchema;
622
714
  publicEnv?: PublicEnv;
715
+ /** Theme's default locale JSON from themeSchema.i18n.staticContent */
716
+ staticContent?: Record<string, unknown>;
717
+ /** Locale-specific merchant overrides from the API */
718
+ merchantOverrides?: Record<string, unknown>;
623
719
  _error?: string;
624
720
  _loadFailed?: boolean;
625
721
  };
@@ -924,4 +1020,4 @@ declare const IMAGES_PLACEHOLDERS: {
924
1020
  product_18: string;
925
1021
  };
926
1022
 
927
- export { type CacheResponseValidator, type ComponentDataValue, type ComponentLoaderArgs, type CreateHydrogenSchemaOptions, type DirectFetchResponse, type FetchProjectPayload, type FetchProjectRequestBody, type HydrogenComponent, type HydrogenComponentData, type HydrogenComponentPresets, type HydrogenComponentProps, type HydrogenComponentSchema, type HydrogenElement, type HydrogenPageAssignment, type HydrogenPageData, type HydrogenProjectType, type HydrogenSchemaValidationResult, type HydrogenThemeSchema, type HydrogenThemeSettings, IMAGES_PLACEHOLDERS, type LoadPageParams, type ProjectIdValidationResult, type ProjectIdValue, type PublicEnv, type RouteLoaderArgs, type ThemeSettingsResponse, type WeaverseArticle, type WeaverseBlog, WeaverseClient, type WeaverseClientArgs, type WeaverseCollection, type WeaverseDataContext, WeaverseError, WeaverseHydrogen, WeaverseHydrogenItem, type WeaverseHydrogenParams, WeaverseHydrogenRoot, type WeaverseI18n, type WeaverseInternal, type WeaverseLoaderData, type WeaverseLoaderRequestInfo, type WeaverseMetaObject, type WeaverseProduct, type WeaverseProjectConfigs, type WeaverseStudioQueries, type WithCacheFetchResponse, createWeaverseDataContext, defaultComponents, generateDataFromSchema, getPreviewData, getRequestQueries, getSelectedProductOptions, getWeaverseConfigs, hasError, hasWeaverseStudio, isFetchProjectPayload, isProjectIdFunction, isThemeSettingsResponse, isValidHydrogenSchema, isWithCacheFetchResponse, registerComponent, useThemeSettings, useWeaverseDataContext, withWeaverse };
1023
+ export { type CacheResponseValidator, type ComponentDataValue, type ComponentLoaderArgs, type CreateHydrogenSchemaOptions, type DirectFetchResponse, type FetchProjectPayload, type FetchProjectRequestBody, type HydrogenComponent, type HydrogenComponentData, type HydrogenComponentPresets, type HydrogenComponentProps, type HydrogenComponentSchema, type HydrogenElement, type HydrogenPageAssignment, type HydrogenPageData, type HydrogenProjectType, type HydrogenSchemaValidationResult, type HydrogenThemeSchema, type HydrogenThemeSettings, IMAGES_PLACEHOLDERS, type LoadPageParams, type ProjectIdValidationResult, type ProjectIdValue, type PublicEnv, type RouteLoaderArgs, type ThemeSettingsResponse, ThemeTextProvider, type ThemeTextProviderProps, type ThemeTextValue, type TranslateFunction, type WeaverseArticle, type WeaverseBlog, WeaverseClient, type WeaverseClientArgs, type WeaverseCollection, type WeaverseDataContext, WeaverseError, WeaverseHydrogen, WeaverseHydrogenItem, type WeaverseHydrogenParams, WeaverseHydrogenRoot, type WeaverseI18n, type WeaverseInternal, type WeaverseLoaderData, type WeaverseLoaderRequestInfo, type WeaverseMetaObject, type WeaverseProduct, type WeaverseProjectConfigs, type WeaverseStudioQueries, type WithCacheFetchResponse, type WithWeaverseOptions, createWeaverseDataContext, defaultComponents, generateDataFromSchema, getNestedKey, getPreviewData, getRequestQueries, getSelectedProductOptions, getWeaverseConfigs, hasError, hasWeaverseStudio, interpolate, isFetchProjectPayload, isProjectIdFunction, isThemeSettingsResponse, isValidHydrogenSchema, isWithCacheFetchResponse, registerComponent, useThemeSettings, useThemeText, useWeaverseDataContext, withWeaverse };
package/dist/index.js CHANGED
@@ -4,8 +4,8 @@ var hydrogen = require('@shopify/hydrogen');
4
4
  var react = require('@weaverse/react');
5
5
  var schema$1 = require('@weaverse/schema');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
- var reactRouter = require('react-router');
8
7
  var react$1 = require('react');
8
+ var reactRouter = require('react-router');
9
9
  var reactErrorBoundary = require('react-error-boundary');
10
10
 
11
11
  // src/index.ts
@@ -33,6 +33,63 @@ var defaultComponents = [
33
33
  schema
34
34
  }
35
35
  ];
36
+ function getNestedKey(obj, path, fallback) {
37
+ const keys = path.split(".");
38
+ let current = obj;
39
+ for (const key of keys) {
40
+ if (current == null || typeof current !== "object") {
41
+ return fallback;
42
+ }
43
+ current = current[key];
44
+ }
45
+ if (typeof current === "string") {
46
+ return current;
47
+ }
48
+ return fallback;
49
+ }
50
+ function interpolate(template, variables) {
51
+ if (!variables || Object.keys(variables).length === 0) {
52
+ return template;
53
+ }
54
+ return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
55
+ const value = variables[key];
56
+ return value !== void 0 ? String(value) : match;
57
+ });
58
+ }
59
+ var ThemeTextContext = react$1.createContext(null);
60
+ ThemeTextContext.displayName = "WeaverseThemeTextContext";
61
+ function ThemeTextProvider({
62
+ staticContent,
63
+ merchantOverrides,
64
+ t: externalT,
65
+ children
66
+ }) {
67
+ const value = react$1.useMemo(() => {
68
+ const t = (key, variables) => {
69
+ if (externalT) {
70
+ const external = externalT(key, variables);
71
+ if (external && external !== key) {
72
+ return external;
73
+ }
74
+ }
75
+ const override = merchantOverrides ? getNestedKey(merchantOverrides, key) : void 0;
76
+ const staticValue = getNestedKey(staticContent, key);
77
+ const raw = override ?? staticValue ?? key;
78
+ return interpolate(raw, variables);
79
+ };
80
+ return { t };
81
+ }, [staticContent, merchantOverrides, externalT]);
82
+ return /* @__PURE__ */ jsxRuntime.jsx(ThemeTextContext.Provider, { value, children });
83
+ }
84
+ function useThemeText() {
85
+ const ctx = react$1.useContext(ThemeTextContext);
86
+ if (!ctx) {
87
+ throw new Error(
88
+ "useThemeText must be used within <ThemeTextProvider>. Wrap your app with withWeaverse()."
89
+ );
90
+ }
91
+ return ctx;
92
+ }
36
93
  function createFlatDataContext(matches) {
37
94
  const context = {};
38
95
  for (const match of matches) {
@@ -562,10 +619,27 @@ var WeaverseHydrogenRoot = react$1.memo(
562
619
  );
563
620
  var ThemeSettingsProvider = react$1.createContext(null);
564
621
  ThemeSettingsProvider.displayName = "WeaverseThemeSettingsProvider";
565
- function withWeaverse(Component) {
622
+ function withWeaverse(Component, options) {
566
623
  return (props) => {
567
- const { settings } = useThemeSettingsStore();
568
- return /* @__PURE__ */ jsxRuntime.jsx(ThemeSettingsProvider.Provider, { value: settings, children: /* @__PURE__ */ jsxRuntime.jsx(Component, { ...props }) });
624
+ const themeSettingsStore = useThemeSettingsStore();
625
+ const { settings } = themeSettingsStore;
626
+ const themeTextData = useThemeTextData();
627
+ return /* @__PURE__ */ jsxRuntime.jsx(ThemeSettingsProvider.Provider, { value: settings, children: /* @__PURE__ */ jsxRuntime.jsx(
628
+ ThemeTextProvider,
629
+ {
630
+ merchantOverrides: themeTextData.merchantOverrides,
631
+ staticContent: themeTextData.staticContent,
632
+ t: options?.t,
633
+ children: /* @__PURE__ */ jsxRuntime.jsx(Component, { ...props })
634
+ }
635
+ ) });
636
+ };
637
+ }
638
+ function useThemeTextData() {
639
+ const data = reactRouter.useRouteLoaderData("root");
640
+ return {
641
+ staticContent: data?.weaverseTheme?.staticContent ?? {},
642
+ merchantOverrides: data?.weaverseTheme?.merchantOverrides
569
643
  };
570
644
  }
571
645
  function useThemeSettings() {
@@ -981,41 +1055,52 @@ var WeaverseClient = class {
981
1055
  }
982
1056
  const url = this.getApiUrl("project_configs");
983
1057
  const body = JSON.stringify({ isDesignMode, projectId });
984
- let data = await this.fetchWithCache(url, {
985
- method: "POST",
986
- strategy,
987
- body,
988
- headers: {
989
- "Content-Type": "application/json",
990
- Accept: "application/json",
991
- "Accept-Encoding": "gzip, deflate, br"
992
- }
993
- });
994
- if (typeof data !== "object" || data === null) {
1058
+ const [data, merchantOverrides] = await Promise.all([
1059
+ this.fetchWithCache(url, {
1060
+ method: "POST",
1061
+ strategy,
1062
+ body,
1063
+ headers: {
1064
+ "Content-Type": "application/json",
1065
+ Accept: "application/json",
1066
+ "Accept-Encoding": "gzip, deflate, br"
1067
+ }
1068
+ }),
1069
+ this.fetchMerchantOverrides(strategy)
1070
+ ]);
1071
+ let result = data;
1072
+ if (typeof result !== "object" || result === null) {
995
1073
  console.warn(
996
1074
  "Invalid theme settings response format, using defaults:",
997
1075
  {
998
- type: typeof data,
999
- isString: typeof data === "string",
1000
- length: typeof data === "string" ? data.length : "N/A",
1001
- preview: typeof data === "string" ? `${data.substring(0, 50)}...` : String(data)
1076
+ type: typeof result,
1077
+ isString: typeof result === "string",
1078
+ length: typeof result === "string" ? result.length : "N/A",
1079
+ preview: typeof result === "string" ? `${result.substring(0, 50)}...` : String(result)
1002
1080
  }
1003
1081
  );
1004
- data = { theme: defaultThemeSettings };
1082
+ result = { theme: defaultThemeSettings };
1005
1083
  }
1006
1084
  if (this.themeSchema?.settings || this.themeSchema?.inspector) {
1007
- if (!data.theme || typeof data.theme !== "object") {
1008
- data.theme = defaultThemeSettings;
1085
+ if (!result.theme || typeof result.theme !== "object") {
1086
+ result.theme = defaultThemeSettings;
1009
1087
  } else {
1010
- data.theme = {
1088
+ result.theme = {
1011
1089
  ...defaultThemeSettings,
1012
- ...data.theme
1090
+ ...result.theme
1013
1091
  };
1014
1092
  }
1015
1093
  }
1094
+ const staticContent = this.themeSchema?.i18n?.staticContent;
1095
+ if (staticContent) {
1096
+ result.staticContent = staticContent;
1097
+ }
1098
+ if (merchantOverrides) {
1099
+ result.merchantOverrides = merchantOverrides;
1100
+ }
1016
1101
  if (this.configs.isDesignMode) {
1017
- data = {
1018
- ...data,
1102
+ result = {
1103
+ ...result,
1019
1104
  schema: this.themeSchema && typeof this.themeSchema === "object" ? {
1020
1105
  ...this.themeSchema,
1021
1106
  settings: this.themeSchema?.settings?.map((group) => ({
@@ -1034,18 +1119,57 @@ var WeaverseClient = class {
1034
1119
  publicEnv: this.configs.publicEnv
1035
1120
  };
1036
1121
  }
1037
- return data;
1122
+ return result;
1038
1123
  } catch (error) {
1039
1124
  const errorMessage = "Unable to load theme settings";
1040
1125
  const errorDetails = this.extractErrorMessage(error);
1041
1126
  console.error(errorMessage, errorDetails);
1042
1127
  return {
1043
1128
  theme: defaultThemeSettings,
1129
+ staticContent: this.themeSchema?.i18n?.staticContent,
1044
1130
  _error: errorDetails,
1045
1131
  _loadFailed: true
1046
1132
  };
1047
1133
  }
1048
1134
  };
1135
+ /**
1136
+ * Fetch locale-specific merchant overrides from the translation API.
1137
+ * Returns a nested JSON object with translated values.
1138
+ * Falls back to empty object on error to avoid blocking theme rendering.
1139
+ */
1140
+ fetchMerchantOverrides = async (strategy) => {
1141
+ try {
1142
+ const { projectId, weaverseHost } = this.configs;
1143
+ const i18n = this.storefront.i18n;
1144
+ if (!(projectId && weaverseHost)) {
1145
+ return void 0;
1146
+ }
1147
+ const language = (i18n?.language || "en").toLowerCase();
1148
+ const country = (i18n?.country || "us").toLowerCase();
1149
+ const locale = `${language}-${country}`;
1150
+ const url = `${weaverseHost}/api/translation/static?projectId=${projectId}&locale=${locale}`;
1151
+ const overrides = await this.fetchWithCache(
1152
+ url,
1153
+ {
1154
+ method: "GET",
1155
+ strategy,
1156
+ headers: {
1157
+ Accept: "application/json"
1158
+ }
1159
+ }
1160
+ );
1161
+ if (typeof overrides === "object" && overrides !== null) {
1162
+ return overrides;
1163
+ }
1164
+ return void 0;
1165
+ } catch (error) {
1166
+ console.warn(
1167
+ "Unable to load merchant overrides, using theme defaults:",
1168
+ this.extractErrorMessage(error)
1169
+ );
1170
+ return void 0;
1171
+ }
1172
+ };
1049
1173
  /**
1050
1174
  * Generate fallback page with default structure when page data is unavailable.
1051
1175
  * Used internally when API returns no page or when page needs default content.
@@ -1322,6 +1446,7 @@ Object.defineProperty(exports, "useWeaverse", {
1322
1446
  get: function () { return react.useWeaverse; }
1323
1447
  });
1324
1448
  exports.IMAGES_PLACEHOLDERS = IMAGES_PLACEHOLDERS;
1449
+ exports.ThemeTextProvider = ThemeTextProvider;
1325
1450
  exports.WeaverseClient = WeaverseClient;
1326
1451
  exports.WeaverseError = WeaverseError;
1327
1452
  exports.WeaverseHydrogen = WeaverseHydrogen;
@@ -1330,12 +1455,14 @@ exports.WeaverseHydrogenRoot = WeaverseHydrogenRoot;
1330
1455
  exports.createWeaverseDataContext = createWeaverseDataContext;
1331
1456
  exports.defaultComponents = defaultComponents;
1332
1457
  exports.generateDataFromSchema = generateDataFromSchema;
1458
+ exports.getNestedKey = getNestedKey;
1333
1459
  exports.getPreviewData = getPreviewData;
1334
1460
  exports.getRequestQueries = getRequestQueries;
1335
1461
  exports.getSelectedProductOptions = getSelectedProductOptions;
1336
1462
  exports.getWeaverseConfigs = getWeaverseConfigs;
1337
1463
  exports.hasError = hasError;
1338
1464
  exports.hasWeaverseStudio = hasWeaverseStudio;
1465
+ exports.interpolate = interpolate;
1339
1466
  exports.isFetchProjectPayload = isFetchProjectPayload;
1340
1467
  exports.isProjectIdFunction = isProjectIdFunction;
1341
1468
  exports.isThemeSettingsResponse = isThemeSettingsResponse;
@@ -1343,6 +1470,7 @@ exports.isValidHydrogenSchema = isValidHydrogenSchema;
1343
1470
  exports.isWithCacheFetchResponse = isWithCacheFetchResponse;
1344
1471
  exports.registerComponent = registerComponent;
1345
1472
  exports.useThemeSettings = useThemeSettings;
1473
+ exports.useThemeText = useThemeText;
1346
1474
  exports.useWeaverseDataContext = useWeaverseDataContext;
1347
1475
  exports.withWeaverse = withWeaverse;
1348
1476
  Object.keys(schema$1).forEach(function (k) {