@weaverse/next 0.1.0-alpha.1 → 0.1.0-alpha.11
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/README.md +521 -108
- package/dist/{chunk-SS6QUKYY.mjs → chunk-XXGMPTWH.mjs} +74 -4
- package/dist/chunk-XXGMPTWH.mjs.map +1 -0
- package/dist/index.d.mts +423 -16
- package/dist/index.d.ts +423 -16
- package/dist/index.js +678 -45
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +588 -46
- package/dist/index.mjs.map +1 -1
- package/dist/{types-DvEeLX6L.d.mts → seo-CgO21rLg.d.mts} +205 -9
- package/dist/{types-DvEeLX6L.d.ts → seo-CgO21rLg.d.ts} +205 -9
- package/dist/server.d.mts +43 -4
- package/dist/server.d.ts +43 -4
- package/dist/server.js +248 -18
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +177 -19
- package/dist/server.mjs.map +1 -1
- package/package.json +8 -3
- package/dist/chunk-SS6QUKYY.mjs.map +0 -1
|
@@ -133,8 +133,22 @@ function toQueryRecord(searchParams) {
|
|
|
133
133
|
}
|
|
134
134
|
return queries;
|
|
135
135
|
}
|
|
136
|
+
var TRANSIENT_STUDIO_PARAMS = /* @__PURE__ */ new Set([
|
|
137
|
+
"weaverseDraftItem",
|
|
138
|
+
// Legacy name from the original design-mode draft-item spike. Keep it out of
|
|
139
|
+
// runtime requestInfo too, in case an older Builder bundle is in front of a
|
|
140
|
+
// newer Next storefront.
|
|
141
|
+
"__weaverseDraftItem"
|
|
142
|
+
]);
|
|
143
|
+
function getRequestInfoSearchParams(context) {
|
|
144
|
+
let searchParams = new URLSearchParams(getSearchParamsFromContext(context));
|
|
145
|
+
for (let key of TRANSIENT_STUDIO_PARAMS) {
|
|
146
|
+
searchParams.delete(key);
|
|
147
|
+
}
|
|
148
|
+
return searchParams;
|
|
149
|
+
}
|
|
136
150
|
function buildWeaverseNextRequestInfo(context) {
|
|
137
|
-
let searchParams =
|
|
151
|
+
let searchParams = getRequestInfoSearchParams(context);
|
|
138
152
|
let search = searchParams.toString();
|
|
139
153
|
return {
|
|
140
154
|
pathname: getPathnameFromContext(context),
|
|
@@ -144,6 +158,62 @@ function buildWeaverseNextRequestInfo(context) {
|
|
|
144
158
|
};
|
|
145
159
|
}
|
|
146
160
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
161
|
+
// src/seo.ts
|
|
162
|
+
function hasOpenGraphContent(seo) {
|
|
163
|
+
return Boolean(seo?.title || seo?.description || seo?.image || seo?.type);
|
|
164
|
+
}
|
|
165
|
+
function hasTwitterContent(seo) {
|
|
166
|
+
return Boolean(seo?.title || seo?.description || seo?.image || seo?.cardType);
|
|
167
|
+
}
|
|
168
|
+
function formatWeaverseNextSeoMetadata(seo) {
|
|
169
|
+
let index = seo?.robots?.index !== false;
|
|
170
|
+
let follow = seo?.robots?.follow !== false;
|
|
171
|
+
let metadata = {
|
|
172
|
+
robots: { index, follow }
|
|
173
|
+
};
|
|
174
|
+
if (!seo) {
|
|
175
|
+
return metadata;
|
|
176
|
+
}
|
|
177
|
+
if (seo.title) {
|
|
178
|
+
metadata.title = seo.title;
|
|
179
|
+
}
|
|
180
|
+
if (seo.description) {
|
|
181
|
+
metadata.description = seo.description;
|
|
182
|
+
}
|
|
183
|
+
if (seo.keywords) {
|
|
184
|
+
metadata.keywords = seo.keywords;
|
|
185
|
+
}
|
|
186
|
+
if (seo.canonicalUrl) {
|
|
187
|
+
metadata.alternates = { canonical: seo.canonicalUrl };
|
|
188
|
+
}
|
|
189
|
+
let openGraph = seo.openGraph;
|
|
190
|
+
if (hasOpenGraphContent(openGraph)) {
|
|
191
|
+
metadata.openGraph = {
|
|
192
|
+
title: openGraph?.title,
|
|
193
|
+
description: openGraph?.description,
|
|
194
|
+
images: openGraph?.image ? [openGraph.image] : void 0,
|
|
195
|
+
type: openGraph?.type || "website"
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
let twitter = seo.twitter;
|
|
199
|
+
if (hasTwitterContent(twitter)) {
|
|
200
|
+
metadata.twitter = {
|
|
201
|
+
card: twitter?.cardType || "summary",
|
|
202
|
+
title: twitter?.title,
|
|
203
|
+
description: twitter?.description,
|
|
204
|
+
images: twitter?.image ? [twitter.image] : void 0
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
return metadata;
|
|
208
|
+
}
|
|
209
|
+
function getWeaverseNextSeoMetadata(data) {
|
|
210
|
+
if (!data) {
|
|
211
|
+
return formatWeaverseNextSeoMetadata(null);
|
|
212
|
+
}
|
|
213
|
+
let page = "items" in data && "id" in data ? data : data.page ?? null;
|
|
214
|
+
return formatWeaverseNextSeoMetadata(page?.seo ?? null);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export { buildWeaverseNextRequestInfo, formatWeaverseNextSeoMetadata, generateDataFromSchema, getWeaverseNextSeoMetadata, runWeaverseComponentLoaders };
|
|
218
|
+
//# sourceMappingURL=chunk-XXGMPTWH.mjs.map
|
|
219
|
+
//# sourceMappingURL=chunk-XXGMPTWH.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts","../src/loader.ts","../src/request-info.ts","../src/seo.ts"],"names":[],"mappings":"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","file":"chunk-XXGMPTWH.mjs","sourcesContent":["import type { SchemaType } from '@weaverse/schema'\nimport type { WeaverseNextThemeSchema } from './types'\n\n/**\n * Generate default component data from a schema's `settings` inputs.\n *\n * Mirrors Hydrogen's `generateDataFromSchema` (settings → `{ [name]:\n * defaultValue }`) but is kept local so `@weaverse/next` doesn't depend on\n * `@weaverse/hydrogen`. Falls back to the deprecated `inspector` array when a\n * schema predates `settings`.\n */\nexport function generateDataFromSchema(\n schema: SchemaType | WeaverseNextThemeSchema | undefined\n): Record<string, unknown> {\n let data: Record<string, unknown> = {}\n if (!schema) {\n return data\n }\n\n let groups =\n (schema.settings as {\n inputs?: { name?: string; defaultValue?: unknown }[]\n }[]) ??\n (schema as { inspector?: typeof groups }).inspector ??\n []\n\n for (let group of groups) {\n for (let input of group?.inputs ?? []) {\n let { name, defaultValue } = input\n if (name && defaultValue !== null && defaultValue !== undefined) {\n data[name] = defaultValue\n }\n }\n }\n\n return data\n}\n","import type {\n WeaverseNextClient,\n WeaverseNextCommerceContext,\n WeaverseNextComponent,\n WeaverseNextComponentData,\n WeaverseNextLoaderData,\n WeaverseNextRequestContext,\n} from './types'\nimport { generateDataFromSchema } from './utils'\n\nexport interface RunComponentLoadersArgs {\n client: WeaverseNextClient\n commerce?: WeaverseNextCommerceContext\n context?: WeaverseNextRequestContext\n /** Page payload to walk; defaults to `client.data`. */\n data?: WeaverseNextLoaderData | null\n}\n\nfunction isItemNode(node: unknown): node is WeaverseNextComponentData {\n return (\n typeof node === 'object' &&\n node !== null &&\n typeof (node as WeaverseNextComponentData).type === 'string'\n )\n}\n\nfunction cloneItem(item: WeaverseNextComponentData): WeaverseNextComponentData {\n return {\n ...item,\n children: Array.isArray(item.children)\n ? item.children.map((child) =>\n isItemNode(child) ? cloneItem(child) : { ...child }\n )\n : item.children,\n }\n}\n\n/**\n * Walk a serialized page tree and run each registered component's `loader`,\n * attaching the result to the item as `loaderData`.\n *\n * Loaders receive explicit `commerce.storefront` (and `weaverse.storefront` as\n * a compatibility alias via the client). Children are walked recursively when\n * they are inline item objects; flat `items` arrays are covered by the\n * top-level walk.\n *\n * @returns a cloned `data` object with `loaderData` attached to cloned items.\n */\nexport async function runWeaverseComponentLoaders(\n args: RunComponentLoadersArgs\n): Promise<WeaverseNextLoaderData | null> {\n let { client, context, commerce } = args\n let sourceData = args.data ?? client.data\n if (!sourceData) {\n return null\n }\n if (!sourceData.page.items.length) {\n return sourceData\n }\n\n let data: WeaverseNextLoaderData = {\n ...sourceData,\n page: {\n ...sourceData.page,\n items: sourceData.page.items.map(cloneItem),\n },\n }\n let items = data.page.items\n\n let componentMap = new Map<string, WeaverseNextComponent>()\n for (let component of client.components) {\n if (component?.schema?.type) {\n componentMap.set(component.schema.type, component)\n }\n }\n\n let visited = new Set<string>()\n let resolvedContext = context ?? client.requestContext\n let resolvedCommerce = commerce ?? client.commerce\n\n // Per-call `weaverse` alias. When a request-scoped `commerce` is passed, the\n // `weaverse.storefront` compatibility alias must resolve to *that* storefront,\n // not the client's construction-time commerce. Pilot-style loaders call\n // `weaverse.storefront.query(...)`, so a stale alias would query the wrong\n // (or an undefined) storefront. When no override is given we reuse the client\n // as-is to preserve its prototype getters.\n let resolvedWeaverse: WeaverseNextClient =\n resolvedCommerce === client.commerce\n ? client\n : {\n ...client,\n commerce: resolvedCommerce,\n storefront: resolvedCommerce?.storefront,\n }\n\n async function walk(nodes: WeaverseNextComponentData[]) {\n for (let item of nodes) {\n if (!item || visited.has(item.id)) {\n continue\n }\n visited.add(item.id)\n\n let component = componentMap.get(item.type)\n if (component?.loader) {\n try {\n item.loaderData = await component.loader({\n data: { ...generateDataFromSchema(component.schema), ...item.data },\n weaverse: resolvedWeaverse,\n context: resolvedContext,\n commerce: resolvedCommerce,\n })\n } catch (error) {\n console.warn('❌ Item loader run failed.', item.type, item.id, error)\n }\n }\n\n let children = item.children\n if (Array.isArray(children)) {\n let inlineChildren = children.filter(\n isItemNode\n ) as WeaverseNextComponentData[]\n if (inlineChildren.length) {\n await walk(inlineChildren)\n }\n }\n }\n }\n\n await walk(items)\n return data\n}\n","import type {\n WeaverseNextRequestContext,\n WeaverseNextRequestInfo,\n} from './types'\n\nfunction toUrl(value: string | URL): URL {\n return typeof value === 'string' ? new URL(value, 'http://localhost') : value\n}\n\nfunction getSearchParamsFromContext(\n context?: WeaverseNextRequestContext\n): URLSearchParams {\n if (context?.searchParams) {\n return new URLSearchParams(context.searchParams)\n }\n\n if (context?.url) {\n let url = toUrl(context.url)\n return new URLSearchParams(url.searchParams)\n }\n\n return new URLSearchParams()\n}\n\nfunction getPathnameFromContext(context?: WeaverseNextRequestContext): string {\n if (context?.pathname) {\n return context.pathname\n }\n\n if (context?.url) {\n let url = toUrl(context.url)\n return url.pathname || '/'\n }\n\n return '/'\n}\n\nfunction coerceQueryValue(value: string): string | boolean {\n if (value === 'true') {\n return true\n }\n if (value === 'false') {\n return false\n }\n return value\n}\n\nfunction toQueryRecord(\n searchParams: URLSearchParams\n): Record<string, string | boolean> {\n let queries: Record<string, string | boolean> = {}\n for (let [key, value] of searchParams.entries()) {\n queries[key] = coerceQueryValue(value)\n }\n return queries\n}\n\nconst TRANSIENT_STUDIO_PARAMS = new Set([\n 'weaverseDraftItem',\n // Legacy name from the original design-mode draft-item spike. Keep it out of\n // runtime requestInfo too, in case an older Builder bundle is in front of a\n // newer Next storefront.\n '__weaverseDraftItem',\n])\n\nfunction getRequestInfoSearchParams(\n context?: WeaverseNextRequestContext\n): URLSearchParams {\n let searchParams = new URLSearchParams(getSearchParamsFromContext(context))\n for (let key of TRANSIENT_STUDIO_PARAMS) {\n searchParams.delete(key)\n }\n return searchParams\n}\n\n/**\n * Build the Hydrogen-like request info shape consumed by the Studio bridge.\n * Duplicate query keys keep the last value, matching `URLSearchParams` iteration\n * assignment and Hydrogen's practical query-object behavior.\n */\nexport function buildWeaverseNextRequestInfo(\n context?: WeaverseNextRequestContext\n): WeaverseNextRequestInfo {\n let searchParams = getRequestInfoSearchParams(context)\n let search = searchParams.toString()\n\n return {\n pathname: getPathnameFromContext(context),\n search: search ? `?${search}` : '',\n queries: toQueryRecord(searchParams),\n ...(context?.i18n ? { i18n: context.i18n } : {}),\n }\n}\n","import type { PageSEOData } from '@weaverse/schema'\nimport type { WeaverseNextLoaderData, WeaverseNextPageData } from './types'\n\nexport interface WeaverseNextSeoMetadata {\n alternates?: { canonical?: string }\n description?: string\n keywords?: string\n openGraph?: {\n description?: string\n images?: string[]\n title?: string\n type?: string\n }\n robots: {\n follow: boolean\n index: boolean\n }\n title?: string\n twitter?: {\n card?: string\n description?: string\n images?: string[]\n title?: string\n }\n}\n\nfunction hasOpenGraphContent(seo: PageSEOData['openGraph']): boolean {\n return Boolean(seo?.title || seo?.description || seo?.image || seo?.type)\n}\n\nfunction hasTwitterContent(seo: PageSEOData['twitter']): boolean {\n return Boolean(seo?.title || seo?.description || seo?.image || seo?.cardType)\n}\n\nexport function formatWeaverseNextSeoMetadata(\n seo: PageSEOData | null | undefined\n): WeaverseNextSeoMetadata {\n let index = seo?.robots?.index !== false\n let follow = seo?.robots?.follow !== false\n let metadata: WeaverseNextSeoMetadata = {\n robots: { index, follow },\n }\n\n if (!seo) {\n return metadata\n }\n\n if (seo.title) {\n metadata.title = seo.title\n }\n if (seo.description) {\n metadata.description = seo.description\n }\n if (seo.keywords) {\n metadata.keywords = seo.keywords\n }\n if (seo.canonicalUrl) {\n metadata.alternates = { canonical: seo.canonicalUrl }\n }\n\n let openGraph = seo.openGraph\n if (hasOpenGraphContent(openGraph)) {\n metadata.openGraph = {\n title: openGraph?.title,\n description: openGraph?.description,\n images: openGraph?.image ? [openGraph.image] : undefined,\n type: openGraph?.type || 'website',\n }\n }\n\n let twitter = seo.twitter\n if (hasTwitterContent(twitter)) {\n metadata.twitter = {\n card: twitter?.cardType || 'summary',\n title: twitter?.title,\n description: twitter?.description,\n images: twitter?.image ? [twitter.image] : undefined,\n }\n }\n\n return metadata\n}\n\nexport function getWeaverseNextSeoMetadata(\n data:\n | WeaverseNextLoaderData\n | WeaverseNextPageData\n | { page?: WeaverseNextPageData | null }\n | null\n | undefined\n): WeaverseNextSeoMetadata {\n if (!data) {\n return formatWeaverseNextSeoMetadata(null)\n }\n let page =\n 'items' in data && 'id' in data\n ? (data as WeaverseNextPageData)\n : ((data as { page?: WeaverseNextPageData | null }).page ?? null)\n return formatWeaverseNextSeoMetadata(page?.seo ?? null)\n}\n"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { Weaverse } from '@weaverse/react';
|
|
1
|
+
import { WeaverseItemStore, Weaverse, ElementData } from '@weaverse/react';
|
|
2
2
|
export { isBrowser, isIframe, useChildInstances, useItemInstance, useParentInstance, useWeaverse } from '@weaverse/react';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import { SchemaType } from '@weaverse/schema';
|
|
4
|
+
export * from '@weaverse/schema';
|
|
5
|
+
import { h as WeaverseNextClientConfig, g as WeaverseNextClient, i as WeaverseNextCommerceContext, x as WeaverseNextRequestContext, t as WeaverseNextLoaderData, a as TranslationStore, y as WeaverseNextRequestInfo, k as WeaverseNextComponentData, J as WeaverseNextThemeSettingsStore, G as WeaverseNextThemeSchema, A as WeaverseNextRuntimeInternal, N as WeaverseNextTranslationMap, v as WeaverseNextPageData, z as WeaverseNextRuntimeConfig, K as WeaverseNextTranslationChanges } from './seo-CgO21rLg.mjs';
|
|
6
|
+
export { T as ThemeTextStore, W as WeaverseArticle, b as WeaverseBlog, c as WeaverseCollection, d as WeaverseMetaObject, j as WeaverseNextComponent, l as WeaverseNextComponentLoaderArgs, m as WeaverseNextComponentProps, o as WeaverseNextCustomPageEntry, p as WeaverseNextFetchCustomPagesOptions, r as WeaverseNextI18n, s as WeaverseNextLoadPageInput, u as WeaverseNextPageAssignment, B as WeaverseNextSeoMetadata, F as WeaverseNextStorefront, L as WeaverseNextTranslationEntry, M as WeaverseNextTranslationItemEntry, O as WeaverseNextTranslationMapEntry, P as WeaverseProduct, Q as formatWeaverseNextSeoMetadata, R as getWeaverseNextSeoMetadata } from './seo-CgO21rLg.mjs';
|
|
6
7
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
7
8
|
import * as react from 'react';
|
|
8
9
|
import { ReactNode } from 'react';
|
|
@@ -61,15 +62,157 @@ interface RunComponentLoadersArgs {
|
|
|
61
62
|
*/
|
|
62
63
|
declare function runWeaverseComponentLoaders(args: RunComponentLoadersArgs): Promise<WeaverseNextLoaderData | null>;
|
|
63
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Traverse a nested object by dot-path.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* getNestedKey({ cart: { title: 'Cart' } }, 'cart.title') // => 'Cart'
|
|
70
|
+
* getNestedKey({}, 'cart.title', 'fallback') // => 'fallback'
|
|
71
|
+
*/
|
|
72
|
+
declare function getNestedKey(obj: Record<string, unknown>, path: string, fallback?: string): string | undefined;
|
|
73
|
+
/**
|
|
74
|
+
* Replace `{{variable}}` patterns in a string with provided values.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* interpolate('Hello {{name}}!', { name: 'World' }) // => 'Hello World!'
|
|
78
|
+
* interpolate('-{{percentage}}% Off', { percentage: 15 }) // => '-15% Off'
|
|
79
|
+
*/
|
|
80
|
+
declare function interpolate(template: string, variables?: Record<string, string | number>): string;
|
|
81
|
+
/**
|
|
82
|
+
* Signature for a translation function.
|
|
83
|
+
*/
|
|
84
|
+
type TranslateFunction = (key: string, variables?: Record<string, string | number>) => string;
|
|
85
|
+
interface TranslationValue {
|
|
86
|
+
/** Active-locale translated keys loaded from the storefront API. */
|
|
87
|
+
merchantOverrides: Record<string, unknown> | null;
|
|
88
|
+
/**
|
|
89
|
+
* Translate a key with optional variable interpolation.
|
|
90
|
+
*
|
|
91
|
+
* Priority chain (highest wins):
|
|
92
|
+
* 1. External `t` (passed into `WeaverseNextRootProvider` / `TranslationProvider`)
|
|
93
|
+
* 2. Design overrides (live Builder edits from `TranslationStore`)
|
|
94
|
+
* 3. `merchantOverrides` (DB/API overrides for the current locale)
|
|
95
|
+
* 4. `staticContent` (theme default JSON)
|
|
96
|
+
* 5. The key itself (fallback)
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* t('cart.title') // => "Cart"
|
|
100
|
+
* t('badge.sale', { percentage: 15 }) // => "-15% Off"
|
|
101
|
+
*/
|
|
102
|
+
t: TranslateFunction;
|
|
103
|
+
/**
|
|
104
|
+
* @deprecated Use {@link TranslationValue.translationStore} instead. Kept as a
|
|
105
|
+
* backward-compatible alias pointing at the same store instance.
|
|
106
|
+
*/
|
|
107
|
+
themeTextStore: TranslationStore | null;
|
|
108
|
+
/** Exposed so the runtime/Studio bridge can attach it to `internal`. */
|
|
109
|
+
translationStore: TranslationStore | null;
|
|
110
|
+
}
|
|
111
|
+
interface TranslationProviderProps {
|
|
112
|
+
children: ReactNode;
|
|
113
|
+
merchantOverrides?: Record<string, unknown>;
|
|
114
|
+
staticContent: Record<string, unknown>;
|
|
115
|
+
/**
|
|
116
|
+
* Optional external translation function.
|
|
117
|
+
* When provided it becomes the **highest-priority** source:
|
|
118
|
+
* if it returns a non-empty string that differs from the raw key,
|
|
119
|
+
* that value is used; otherwise the internal resolution chain continues.
|
|
120
|
+
*/
|
|
121
|
+
t?: TranslateFunction;
|
|
122
|
+
/**
|
|
123
|
+
* @deprecated Use {@link TranslationProviderProps.translationStore} instead.
|
|
124
|
+
* Still accepted for backward compatibility; ignored when `translationStore`
|
|
125
|
+
* is also provided.
|
|
126
|
+
*/
|
|
127
|
+
themeTextStore?: TranslationStore | null;
|
|
128
|
+
/** Optional store for live design-mode text overrides from the builder. */
|
|
129
|
+
translationStore?: TranslationStore | null;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Build the `t()` translation function over a fixed set of sources.
|
|
133
|
+
*
|
|
134
|
+
* Resolution order, highest priority first:
|
|
135
|
+
* 1. `externalT` – host i18n (e.g. Shopify), unless it echoes the key
|
|
136
|
+
* 2. `designOverrides` – live design-mode edits, flat dot-path keys
|
|
137
|
+
* 3. `merchantOverrides` – locale overrides from the API, nested
|
|
138
|
+
* 4. `staticContent` – the theme's default locale JSON
|
|
139
|
+
* 5. the key itself
|
|
140
|
+
*
|
|
141
|
+
* Design overrides are looked up per-key (own properties only) rather than
|
|
142
|
+
* merged into `merchantOverrides`: a flat key like `cart.title` must override
|
|
143
|
+
* exactly that leaf without wiping sibling keys (`cart.subtitle`), and a
|
|
144
|
+
* per-key own-property lookup never builds nested objects from
|
|
145
|
+
* merchant-controlled keys, so it cannot pollute `Object.prototype`.
|
|
146
|
+
*/
|
|
147
|
+
declare function createTranslate(sources: {
|
|
148
|
+
staticContent: Record<string, unknown>;
|
|
149
|
+
merchantOverrides?: Record<string, unknown>;
|
|
150
|
+
designOverrides?: Record<string, string>;
|
|
151
|
+
externalT?: TranslateFunction;
|
|
152
|
+
}): TranslateFunction;
|
|
153
|
+
/**
|
|
154
|
+
* Provider that wraps the app to expose the `t()` function.
|
|
155
|
+
*
|
|
156
|
+
* - `staticContent` – the theme's default locale JSON (from themeSchema.i18n)
|
|
157
|
+
* - `merchantOverrides` – locale-specific overrides fetched from the API
|
|
158
|
+
* - `translationStore` – optional store for live design-mode text overrides
|
|
159
|
+
* (the deprecated `themeTextStore` prop is accepted as a fallback)
|
|
160
|
+
*/
|
|
161
|
+
declare function TranslationProvider({ staticContent, merchantOverrides, t: externalT, translationStore, themeTextStore, children, }: TranslationProviderProps): react_jsx_runtime.JSX.Element;
|
|
162
|
+
/**
|
|
163
|
+
* Hook to access the translation `t()` function.
|
|
164
|
+
*
|
|
165
|
+
* Must be used inside a component wrapped by `WeaverseNextRootProvider` or
|
|
166
|
+
* `TranslationProvider`.
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* ```tsx
|
|
170
|
+
* function CartTitle() {
|
|
171
|
+
* let { t } = useTranslation()
|
|
172
|
+
* return <h2>{t('cart.title')}</h2>
|
|
173
|
+
* }
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
declare function useTranslation(): TranslationValue;
|
|
177
|
+
/**
|
|
178
|
+
* @deprecated Use {@link TranslationProvider} instead.
|
|
179
|
+
*/
|
|
180
|
+
declare const ThemeTextProvider: typeof TranslationProvider;
|
|
181
|
+
/**
|
|
182
|
+
* @deprecated Use {@link useTranslation} instead.
|
|
183
|
+
*/
|
|
184
|
+
declare const useThemeText: typeof useTranslation;
|
|
185
|
+
/**
|
|
186
|
+
* @deprecated Use {@link TranslationValue} instead.
|
|
187
|
+
*/
|
|
188
|
+
type ThemeTextValue = TranslationValue;
|
|
189
|
+
/**
|
|
190
|
+
* @deprecated Use {@link TranslationProviderProps} instead.
|
|
191
|
+
*/
|
|
192
|
+
type ThemeTextProviderProps = TranslationProviderProps;
|
|
193
|
+
|
|
64
194
|
interface WeaverseNextProviderProps {
|
|
65
195
|
children: ReactNode;
|
|
66
196
|
client?: WeaverseNextClient;
|
|
67
197
|
/** App-provided commerce context (storefront/cart/customer). */
|
|
68
198
|
commerce?: WeaverseNextCommerceContext;
|
|
199
|
+
/**
|
|
200
|
+
* Active-locale static-text overrides (nested, from `loadThemeSettings()`).
|
|
201
|
+
* Adopts the root provider's `merchantOverrides` when omitted.
|
|
202
|
+
*/
|
|
203
|
+
merchantOverrides?: Record<string, unknown>;
|
|
69
204
|
/** Explicit page/route commerce data (replaces section-level `useLoaderData`). */
|
|
70
205
|
pageData?: unknown;
|
|
71
206
|
/** Explicit root/global data (replaces `useRouteLoaderData('root')`). */
|
|
72
207
|
rootData?: unknown;
|
|
208
|
+
/**
|
|
209
|
+
* Theme default locale JSON (`loadThemeSettings().staticContent`). Adopts the
|
|
210
|
+
* root provider's `staticContent` when omitted, then falls back to
|
|
211
|
+
* `client.themeSchema.i18n.staticContent`.
|
|
212
|
+
*/
|
|
213
|
+
staticContent?: Record<string, unknown>;
|
|
214
|
+
/** Optional external translation function (host i18n); highest priority in `t()`. */
|
|
215
|
+
t?: TranslateFunction;
|
|
73
216
|
/** Theme settings override; falls back to `client.themeSettings`. */
|
|
74
217
|
themeSettings?: Record<string, unknown>;
|
|
75
218
|
}
|
|
@@ -118,6 +261,114 @@ declare const WeaverseNextRenderer: react.MemoExoticComponent<(props: WeaverseNe
|
|
|
118
261
|
*/
|
|
119
262
|
declare function buildWeaverseNextRequestInfo(context?: WeaverseNextRequestContext): WeaverseNextRequestInfo;
|
|
120
263
|
|
|
264
|
+
declare const DEFAULT_REVALIDATE_ENDPOINT = "/api/weaverse/revalidate";
|
|
265
|
+
/**
|
|
266
|
+
* Minimal runtime surface the in-place apply needs. Structural (not the
|
|
267
|
+
* concrete `WeaverseNextRuntime` class) so unit tests can drive it with a
|
|
268
|
+
* plain mock.
|
|
269
|
+
*/
|
|
270
|
+
interface RevalidateItemRuntimeLike {
|
|
271
|
+
itemInstances: Map<string, {
|
|
272
|
+
setData: (update: Record<string, unknown>) => unknown;
|
|
273
|
+
}>;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Studio per-item loader revalidation: POST the unsaved draft item to the
|
|
277
|
+
* app's revalidate route (see `createWeaverseNextRevalidateHandler`) and apply
|
|
278
|
+
* the returned `loaderData` to the live item instance in place.
|
|
279
|
+
*
|
|
280
|
+
* No `router.refresh()` is involved, so the RSC tree is never re-applied — no
|
|
281
|
+
* page remount, no scroll reset, and the draft payload never touches the URL.
|
|
282
|
+
*
|
|
283
|
+
* Throws on any failure (missing route, non-OK response, unknown item) so the
|
|
284
|
+
* Builder Studio bridge can detect the miss and fall back to its legacy
|
|
285
|
+
* refresh-based revalidation for this window.
|
|
286
|
+
*/
|
|
287
|
+
declare function revalidateWeaverseNextItem(runtime: RevalidateItemRuntimeLike, draftItem: WeaverseNextComponentData, endpoint?: string): Promise<void>;
|
|
288
|
+
|
|
289
|
+
interface WeaverseNextRootContextValue {
|
|
290
|
+
/** Active-locale static-text overrides shared with route-level providers. */
|
|
291
|
+
merchantOverrides?: Record<string, unknown>;
|
|
292
|
+
/** Theme default locale JSON shared with route-level providers. */
|
|
293
|
+
staticContent: Record<string, unknown>;
|
|
294
|
+
themeSettingsStore: WeaverseNextThemeSettingsStore;
|
|
295
|
+
/** Single live design-mode static-text override store for the whole session. */
|
|
296
|
+
translationStore: TranslationStore;
|
|
297
|
+
}
|
|
298
|
+
interface WeaverseNextRootProviderProps {
|
|
299
|
+
children: ReactNode;
|
|
300
|
+
/** Root-loaded theme settings (published-mode fetch, no design-mode context). */
|
|
301
|
+
initialThemeSettings?: Record<string, unknown>;
|
|
302
|
+
/** Active-locale static-text overrides from `loadThemeSettings().merchantOverrides`. */
|
|
303
|
+
merchantOverrides?: Record<string, unknown>;
|
|
304
|
+
publicEnv?: Record<string, string | undefined>;
|
|
305
|
+
/**
|
|
306
|
+
* Theme default locale JSON (`loadThemeSettings().staticContent`). Falls back
|
|
307
|
+
* to `themeSchema.i18n.staticContent` when omitted.
|
|
308
|
+
*/
|
|
309
|
+
staticContent?: Record<string, unknown>;
|
|
310
|
+
/** Optional external translation function (host i18n); highest priority in `t()`. */
|
|
311
|
+
t?: TranslateFunction;
|
|
312
|
+
themeSchema?: WeaverseNextThemeSchema;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Root-scoped client boundary that owns the single `WeaverseNextThemeSettingsStore`
|
|
316
|
+
* for the whole app session, matching Hydrogen's `withWeaverse()` root store.
|
|
317
|
+
* Mount once in `app/layout.tsx`, above `Header`/`Footer`/global modules and any
|
|
318
|
+
* route-level `WeaverseNextProvider`.
|
|
319
|
+
*
|
|
320
|
+
* Also renders `WeaverseNextContext` with a minimal value so `useThemeSettings()`
|
|
321
|
+
* works for components mounted directly under this provider, even without a
|
|
322
|
+
* route-level `WeaverseNextProvider` above them.
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* ```tsx
|
|
326
|
+
* <WeaverseNextRootProvider initialThemeSettings={theme.theme} themeSchema={theme.schema}>
|
|
327
|
+
* <Header />
|
|
328
|
+
* {children}
|
|
329
|
+
* <Footer />
|
|
330
|
+
* </WeaverseNextRootProvider>
|
|
331
|
+
* ```
|
|
332
|
+
*/
|
|
333
|
+
declare function WeaverseNextRootProvider(props: WeaverseNextRootProviderProps): react_jsx_runtime.JSX.Element;
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Item store that flattens the serialized item's nested `data` field onto the
|
|
337
|
+
* store and seeds schema defaults — same shape Hydrogen produces, so the
|
|
338
|
+
* shared `@weaverse/react` renderer can spread props at the top level.
|
|
339
|
+
*/
|
|
340
|
+
declare class WeaverseNextItem extends WeaverseItemStore {
|
|
341
|
+
weaverse: WeaverseNextRuntime;
|
|
342
|
+
/**
|
|
343
|
+
* Cached merged snapshot (base `_store` + translations). Reset whenever the
|
|
344
|
+
* `_store` ref or the item's translation entry ref changes, so
|
|
345
|
+
* `useSyncExternalStore` sees a stable object between unrelated re-renders.
|
|
346
|
+
*/
|
|
347
|
+
private _cachedSnapshot;
|
|
348
|
+
private _snapshotStoreRef;
|
|
349
|
+
private _snapshotTranslationRef;
|
|
350
|
+
constructor(initialData: WeaverseNextComponentData, weaverse: Weaverse);
|
|
351
|
+
/**
|
|
352
|
+
* Flatten nested `data` on updates exactly like the constructor does. Core's
|
|
353
|
+
* `initProject()` calls `setData(item)` when a new runtime serves a page
|
|
354
|
+
* whose item instances already exist (e.g. locale/client navigation), and
|
|
355
|
+
* the inherited shallow merge would leave stale top-level props behind.
|
|
356
|
+
* Assigning through the inherited `data` setter swaps the `_store` ref,
|
|
357
|
+
* which invalidates the memoized snapshot below. The subscriber emit is
|
|
358
|
+
* queued instead of fired when a render-phase deferral is active (see
|
|
359
|
+
* `collectDeferredItemUpdates`).
|
|
360
|
+
*/
|
|
361
|
+
setData: (update: Omit<ElementData, "id" | "type">) => ElementData;
|
|
362
|
+
/**
|
|
363
|
+
* Overlay item-level translations onto the base store when the runtime is in
|
|
364
|
+
* translation mode. Mirrors Hydrogen's `WeaverseHydrogenItem.getSnapShot()`:
|
|
365
|
+
* memoized by `_store` ref + translation entry ref so the returned object is
|
|
366
|
+
* referentially stable, and a fast path that returns the base store untouched
|
|
367
|
+
* when the item has no translations.
|
|
368
|
+
*/
|
|
369
|
+
getSnapShot: () => ElementData;
|
|
370
|
+
}
|
|
371
|
+
|
|
121
372
|
declare global {
|
|
122
373
|
interface Window {
|
|
123
374
|
__weaverse?: WeaverseNextRuntime;
|
|
@@ -131,14 +382,76 @@ declare class WeaverseNextRuntime extends Weaverse {
|
|
|
131
382
|
isPreviewMode: boolean;
|
|
132
383
|
isRevisionPreview: boolean;
|
|
133
384
|
sectionType?: string;
|
|
134
|
-
|
|
385
|
+
/**
|
|
386
|
+
* Translation map received from Builder in design mode, keyed by item ID.
|
|
387
|
+
* `WeaverseNextItem.getSnapShot()` overlays these onto the data handed to
|
|
388
|
+
* components, so translations render without mutating the base `_store`.
|
|
389
|
+
*/
|
|
390
|
+
translationMap: WeaverseNextTranslationMap;
|
|
135
391
|
translationLocale: string;
|
|
136
392
|
translationLanguageId: string;
|
|
393
|
+
/**
|
|
394
|
+
* Fresh page data captured while React was rendering. Runtime reuse happens
|
|
395
|
+
* inside the renderer's render phase (`useMemo`), where applying it through
|
|
396
|
+
* `setProjectData()` would emit item updates to `useSyncExternalStore`
|
|
397
|
+
* subscribers mid-render. The renderer applies it post-commit via
|
|
398
|
+
* `flushRenderPhaseUpdates()`. Never set on design-mode runtimes — the live
|
|
399
|
+
* Studio tree owns the page data there.
|
|
400
|
+
*/
|
|
401
|
+
pendingProjectData?: WeaverseNextPageData & {
|
|
402
|
+
rootId: string;
|
|
403
|
+
};
|
|
404
|
+
/**
|
|
405
|
+
* Reused item instances whose data was refreshed while this runtime was
|
|
406
|
+
* constructed during render (core `initProject()` calls `setData()` on
|
|
407
|
+
* them). Their data is already fresh; only the subscriber notification was
|
|
408
|
+
* deferred to `flushRenderPhaseUpdates()`.
|
|
409
|
+
*/
|
|
410
|
+
pendingItemUpdates: WeaverseNextItem[];
|
|
137
411
|
constructor(config: WeaverseNextRuntimeConfig);
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
412
|
+
/**
|
|
413
|
+
* Pull `translationMap` / `translationLocale` / `translationLanguageId` off
|
|
414
|
+
* the current page data (Builder attaches them in design mode). Unlike
|
|
415
|
+
* Hydrogen, this also clears the sidecar to defaults when the new page data
|
|
416
|
+
* carries none, so a reused runtime / project-data swap can't leave a stale
|
|
417
|
+
* map overlaying the fresh tree.
|
|
418
|
+
*/
|
|
419
|
+
extractTranslationSidecar: () => void;
|
|
420
|
+
/**
|
|
421
|
+
* Replace the translation sidecar (Builder pushes this when translation data
|
|
422
|
+
* arrives or the active language changes) and refresh every item so their
|
|
423
|
+
* merged snapshots recompute.
|
|
424
|
+
*/
|
|
425
|
+
setTranslationSidecar: (map?: WeaverseNextTranslationMap, locale?: string, languageId?: string) => void;
|
|
426
|
+
/**
|
|
427
|
+
* Update a single translatable field for one item. Assigns a new per-item
|
|
428
|
+
* entry object so `WeaverseNextItem.getSnapShot()`'s translation-ref cache
|
|
429
|
+
* invalidates, then triggers only that item's subscribers.
|
|
430
|
+
*/
|
|
431
|
+
updateTranslation: (itemId: string, key: string, originalValue: string, translatedValue: string) => void;
|
|
432
|
+
/**
|
|
433
|
+
* Collect translation changes for the save flow. Returns `undefined` unless
|
|
434
|
+
* both the locale and language ID are set and at least one entry exists;
|
|
435
|
+
* each entry key is namespaced as `data.<field>` to match Builder.
|
|
436
|
+
*/
|
|
437
|
+
getTranslationChanges: () => WeaverseNextTranslationChanges | undefined;
|
|
438
|
+
/**
|
|
439
|
+
* Re-extract the translation sidecar whenever project data is replaced (route
|
|
440
|
+
* change / non-design reuse), before rebuilding item stores. Takes the
|
|
441
|
+
* renderable page shape (`rootId` resolved) that `getRenderablePage()` and
|
|
442
|
+
* the reuse branch pass in.
|
|
443
|
+
*/
|
|
444
|
+
setProjectData: (data: WeaverseNextPageData & {
|
|
445
|
+
rootId: string;
|
|
446
|
+
}) => void;
|
|
447
|
+
/**
|
|
448
|
+
* Apply updates deferred off the render phase: swap in any pending page data
|
|
449
|
+
* captured on runtime reuse, then notify items whose data was refreshed
|
|
450
|
+
* during construction. The renderer calls this from a layout effect right
|
|
451
|
+
* after commit, so subscribers re-render before paint (no content flash) and
|
|
452
|
+
* without React's setState-in-render warning.
|
|
453
|
+
*/
|
|
454
|
+
flushRenderPhaseUpdates: () => void;
|
|
142
455
|
}
|
|
143
456
|
declare function createWeaverseNextRuntime(config: WeaverseNextRuntimeConfig): WeaverseNextRuntime;
|
|
144
457
|
declare function bindWeaverseNextStudioRuntime(runtime: WeaverseNextRuntime): boolean;
|
|
@@ -146,32 +459,86 @@ declare function bindWeaverseNextStudioRuntime(runtime: WeaverseNextRuntime): bo
|
|
|
146
459
|
interface WeaverseNextStudioBridgeProps {
|
|
147
460
|
navigate?: WeaverseNextRuntimeInternal['navigate'];
|
|
148
461
|
revalidate?: WeaverseNextRuntimeInternal['revalidate'];
|
|
462
|
+
revalidateItem?: WeaverseNextRuntimeInternal['revalidateItem'];
|
|
149
463
|
runtime: WeaverseNextRuntime;
|
|
150
464
|
}
|
|
151
465
|
/** Page-level Studio runtime binder. */
|
|
152
466
|
declare function WeaverseNextStudioBridge(props: WeaverseNextStudioBridgeProps): null;
|
|
153
467
|
|
|
468
|
+
interface LoadWeaverseNextStudioScriptOptions {
|
|
469
|
+
storefrontHostname?: string;
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Resolve and append the Next Studio bridge script for the given request
|
|
473
|
+
* context, deduping by src. SSR-safe (no-op without `document`) so it can run
|
|
474
|
+
* unconditionally from a root layout/error boundary before any page tree or
|
|
475
|
+
* runtime exists — e.g. App Router `not-found.tsx` / `error.tsx` routes.
|
|
476
|
+
*/
|
|
477
|
+
declare function loadWeaverseNextStudioScript(context?: WeaverseNextRequestContext, options?: LoadWeaverseNextStudioScriptOptions): void;
|
|
154
478
|
interface WeaverseNextStudioConnectProps {
|
|
155
479
|
context?: WeaverseNextRequestContext;
|
|
156
480
|
storefrontHostname?: string;
|
|
157
481
|
}
|
|
158
|
-
/**
|
|
482
|
+
/**
|
|
483
|
+
* Root-level Studio script connector for Next client boundaries. Mount once
|
|
484
|
+
* near the app root (e.g. root layout) so it also covers routes that never
|
|
485
|
+
* render `WeaverseNextRenderer`, such as `not-found.tsx` / `error.tsx`.
|
|
486
|
+
*/
|
|
159
487
|
declare function WeaverseNextStudioConnect(props: WeaverseNextStudioConnectProps): null;
|
|
160
488
|
|
|
489
|
+
/**
|
|
490
|
+
* Minimal structural shape of the Next App Router returned by `useRouter()`
|
|
491
|
+
* (`next/navigation`) that the Studio bridge needs. Declared locally — rather
|
|
492
|
+
* than importing `AppRouterInstance` from `next` — so the adapter stays a pure
|
|
493
|
+
* function that unit tests can drive with a plain mock and never pulls
|
|
494
|
+
* `next/navigation` into the test graph.
|
|
495
|
+
*/
|
|
496
|
+
interface WeaverseNextRouterLike {
|
|
497
|
+
push: (href: string, options?: {
|
|
498
|
+
scroll?: boolean;
|
|
499
|
+
}) => void;
|
|
500
|
+
refresh: () => void;
|
|
501
|
+
replace: (href: string, options?: {
|
|
502
|
+
scroll?: boolean;
|
|
503
|
+
}) => void;
|
|
504
|
+
}
|
|
505
|
+
/** Resolved Studio navigation/revalidation callbacks for a Next runtime. */
|
|
506
|
+
interface WeaverseNextStudioInternals {
|
|
507
|
+
navigate: NonNullable<WeaverseNextRuntimeInternal['navigate']>;
|
|
508
|
+
revalidate: NonNullable<WeaverseNextRuntimeInternal['revalidate']>;
|
|
509
|
+
}
|
|
510
|
+
interface CreateWeaverseNextStudioInternalsOptions {
|
|
511
|
+
/** Use `router.replace` instead of `router.push` for navigation. */
|
|
512
|
+
replace?: boolean;
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Build Studio `navigate` / `revalidate` callbacks from a Next App Router.
|
|
516
|
+
*
|
|
517
|
+
* Maps Hydrogen's React Router semantics onto Next App Router:
|
|
518
|
+
* - `navigate(to, { preventScrollReset })` → `router.push(to, { scroll })`,
|
|
519
|
+
* where `scroll` is the inverse of `preventScrollReset`. Studio passes
|
|
520
|
+
* `preventScrollReset` for in-place edits so the preview viewport is kept,
|
|
521
|
+
* matching React Router's `navigate({ preventScrollReset })`.
|
|
522
|
+
* - `revalidate()` → `router.refresh()`, the App Router's loader-backed refresh
|
|
523
|
+
* and the closest equivalent to React Router's `useRevalidator`.
|
|
524
|
+
*
|
|
525
|
+
* Pure (no React, no `next/navigation`) so it is unit-testable with a mock
|
|
526
|
+
* router; the {@link WeaverseNextRouterLike} contract is the only coupling.
|
|
527
|
+
*/
|
|
528
|
+
declare function createWeaverseNextStudioInternals(router: WeaverseNextRouterLike, options?: CreateWeaverseNextStudioInternalsOptions): WeaverseNextStudioInternals;
|
|
529
|
+
|
|
161
530
|
interface ResolveWeaverseNextStudioScriptSrcOptions {
|
|
162
|
-
framework?: 'hydrogen' | 'next';
|
|
163
531
|
storefrontHostname?: string;
|
|
164
532
|
}
|
|
165
533
|
/**
|
|
166
|
-
* Resolve the Studio script URL from request/search context.
|
|
167
|
-
*
|
|
168
|
-
* incompatibility requires a dedicated Next bundle.
|
|
534
|
+
* Resolve the Studio script URL from request/search context. `@weaverse/next`
|
|
535
|
+
* uses the dedicated Next bridge path served by Builder.
|
|
169
536
|
*/
|
|
170
537
|
declare function resolveWeaverseNextStudioScriptSrc(context?: WeaverseNextRequestContext, options?: ResolveWeaverseNextStudioScriptSrcOptions): string | null;
|
|
171
538
|
|
|
172
539
|
interface CreateWeaverseNextThemeSettingsStoreOptions {
|
|
173
540
|
publicEnv?: Record<string, string | undefined>;
|
|
174
|
-
schema?:
|
|
541
|
+
schema?: WeaverseNextThemeSchema;
|
|
175
542
|
settings?: Record<string, unknown>;
|
|
176
543
|
}
|
|
177
544
|
/**
|
|
@@ -181,4 +548,44 @@ interface CreateWeaverseNextThemeSettingsStoreOptions {
|
|
|
181
548
|
*/
|
|
182
549
|
declare function createWeaverseNextThemeSettingsStore(options?: CreateWeaverseNextThemeSettingsStoreOptions): WeaverseNextThemeSettingsStore;
|
|
183
550
|
|
|
184
|
-
|
|
551
|
+
/**
|
|
552
|
+
* Resolve stable Studio `navigate` / `revalidate` callbacks from the Next App
|
|
553
|
+
* Router. `useRouter()` is stable across renders, but the derived callbacks are
|
|
554
|
+
* cached in a ref keyed on the router instance so the bridge's bind effect
|
|
555
|
+
* (which depends on `navigate` / `revalidate` identity) doesn't re-run — and
|
|
556
|
+
* re-`refreshStudio` — on every render.
|
|
557
|
+
*/
|
|
558
|
+
declare function useWeaverseNextStudioInternals(options?: CreateWeaverseNextStudioInternalsOptions): WeaverseNextStudioInternals;
|
|
559
|
+
interface WeaverseNextStudioProps extends CreateWeaverseNextStudioInternalsOptions {
|
|
560
|
+
/**
|
|
561
|
+
* Route the app mounted with `createWeaverseNextRevalidateHandler`.
|
|
562
|
+
* Defaults to `/api/weaverse/revalidate`.
|
|
563
|
+
*/
|
|
564
|
+
revalidateEndpoint?: string;
|
|
565
|
+
runtime: WeaverseNextRuntime;
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Page-level Studio binder wired to the Next App Router. Mirrors Hydrogen's
|
|
569
|
+
* `useStudio` (which binds the runtime and feeds it React Router's `navigate` /
|
|
570
|
+
* `revalidate`): it resolves the App Router callbacks via
|
|
571
|
+
* {@link useWeaverseNextStudioInternals} and hands them to
|
|
572
|
+
* {@link WeaverseNextStudioBridge}, so consuming apps get Studio navigation and
|
|
573
|
+
* revalidation without manually wiring `next/navigation`.
|
|
574
|
+
*
|
|
575
|
+
* Client-only — it is the single place `@weaverse/next` touches
|
|
576
|
+
* `next/navigation`, keeping the runtime/renderer and `@weaverse/next/server`
|
|
577
|
+
* free of router imports.
|
|
578
|
+
*/
|
|
579
|
+
declare function WeaverseNextStudio(props: WeaverseNextStudioProps): react_jsx_runtime.JSX.Element;
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* Generate default component data from a schema's `settings` inputs.
|
|
583
|
+
*
|
|
584
|
+
* Mirrors Hydrogen's `generateDataFromSchema` (settings → `{ [name]:
|
|
585
|
+
* defaultValue }`) but is kept local so `@weaverse/next` doesn't depend on
|
|
586
|
+
* `@weaverse/hydrogen`. Falls back to the deprecated `inspector` array when a
|
|
587
|
+
* schema predates `settings`.
|
|
588
|
+
*/
|
|
589
|
+
declare function generateDataFromSchema(schema: SchemaType | WeaverseNextThemeSchema | undefined): Record<string, unknown>;
|
|
590
|
+
|
|
591
|
+
export { type CreateWeaverseNextStudioInternalsOptions, type CreateWeaverseNextThemeSettingsStoreOptions, DEFAULT_REVALIDATE_ENDPOINT, type LoadWeaverseNextStudioScriptOptions, type ResolveWeaverseNextStudioScriptSrcOptions, type RevalidateItemRuntimeLike, type RunComponentLoadersArgs, ThemeTextProvider, type ThemeTextProviderProps, type ThemeTextValue, type TranslateFunction, TranslationProvider, type TranslationProviderProps, TranslationStore, type TranslationValue, WeaverseNextClient, WeaverseNextClientConfig, WeaverseNextCommerceContext, WeaverseNextComponentData, WeaverseNextLoaderData, WeaverseNextPageData, WeaverseNextProvider, type WeaverseNextProviderProps, WeaverseNextRenderer, type WeaverseNextRendererProps, WeaverseNextRequestContext, WeaverseNextRequestInfo, type WeaverseNextRootContextValue, WeaverseNextRootProvider, type WeaverseNextRootProviderProps, type WeaverseNextRouterLike, WeaverseNextRuntime, WeaverseNextRuntimeConfig, WeaverseNextRuntimeInternal, WeaverseNextStudio, WeaverseNextStudioBridge, type WeaverseNextStudioBridgeProps, WeaverseNextStudioConnect, type WeaverseNextStudioConnectProps, type WeaverseNextStudioInternals, type WeaverseNextStudioProps, WeaverseNextThemeSchema, WeaverseNextThemeSettingsStore, WeaverseNextTranslationChanges, WeaverseNextTranslationMap, bindWeaverseNextStudioRuntime, buildWeaverseNextRequestInfo, createTranslate, createWeaverseNextClient, createWeaverseNextRuntime, createWeaverseNextStudioInternals, createWeaverseNextThemeSettingsStore, generateDataFromSchema, getNestedKey, interpolate, loadWeaverseNextStudioScript, resolveWeaverseNextStudioScriptSrc, revalidateWeaverseNextItem, runWeaverseComponentLoaders, useThemeSettings, useThemeText, useTranslation, useWeaverseCommerce, useWeaverseNextStudioInternals, useWeaversePageData, useWeaverseRootData };
|