@weaverse/next 0.1.0-alpha.5 → 0.1.0-alpha.7
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 +101 -3
- package/dist/{chunk-O2TG2NYL.mjs → chunk-6PMZ77RA.mjs} +59 -3
- package/dist/chunk-6PMZ77RA.mjs.map +1 -0
- package/dist/index.d.mts +49 -4
- package/dist/index.d.ts +49 -4
- package/dist/index.js +125 -17
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +68 -20
- package/dist/index.mjs.map +1 -1
- package/dist/{types-DvwaU20C.d.mts → seo-B9yNko4W.d.mts} +72 -4
- package/dist/{types-DvwaU20C.d.ts → seo-B9yNko4W.d.ts} +72 -4
- package/dist/server.d.mts +3 -3
- package/dist/server.d.ts +3 -3
- package/dist/server.js +134 -1
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +78 -2
- package/dist/server.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-O2TG2NYL.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -11,8 +11,9 @@ It is the Next equivalent of the useful parts of `@weaverse/hydrogen`, but the a
|
|
|
11
11
|
- Package status: alpha (`0.1.0-alpha.x`).
|
|
12
12
|
- Target runtime: Next App Router.
|
|
13
13
|
- Peer dependencies: `next >=14`, `react >=19`, `react-dom >=19`.
|
|
14
|
-
- Studio bridge: supported through the
|
|
14
|
+
- Studio bridge: supported through the dedicated Next Studio bridge script (`/static/studio/next/*`) plus Next-native runtime callbacks.
|
|
15
15
|
- Resource-picker revalidation: supported through per-item loader revalidation, not full-page `router.refresh()` on the happy path.
|
|
16
|
+
- Low-risk Hydrogen parity helpers: custom-page sitemap fetching, Next metadata conversion, and resource-picker type aliases are available.
|
|
16
17
|
|
|
17
18
|
## Quick answers for the team
|
|
18
19
|
|
|
@@ -127,6 +128,7 @@ packages/next/src/
|
|
|
127
128
|
use-weaverse-next-studio.tsx # Next-native Studio binder using next/navigation
|
|
128
129
|
revalidate-item.ts # client per-item loader revalidation
|
|
129
130
|
request-info.ts # Studio-compatible request info
|
|
131
|
+
seo.ts # Next Metadata-compatible page SEO helpers
|
|
130
132
|
theme-settings-store.ts # Studio-compatible theme settings store
|
|
131
133
|
types.ts # shared public types
|
|
132
134
|
server/
|
|
@@ -160,6 +162,7 @@ Main exports:
|
|
|
160
162
|
- `createWeaverseNextRevalidateHandler(config)` — route-handler factory for Studio per-item loader revalidation.
|
|
161
163
|
- `getWeaverseNextConfigs(...)` — config/env/query resolution.
|
|
162
164
|
- `normalizeNextPageUrl(...)` / `resolveRequestUrl(...)` — stable page URL helpers.
|
|
165
|
+
- `getWeaverseNextSeoMetadata(...)` / `formatWeaverseNextSeoMetadata(...)` — convert Weaverse `page.seo` into a Next Metadata-compatible object.
|
|
163
166
|
|
|
164
167
|
### `createWeaverseNextServerClient`
|
|
165
168
|
|
|
@@ -241,6 +244,7 @@ let theme = await weaverse.loadThemeSettings()
|
|
|
241
244
|
| --- | --- |
|
|
242
245
|
| `loadPage(input?)` | Fetches the page from `/api/public/project`, builds `WeaverseNextLoaderData`, runs component loaders, and returns page/project/config data. In section preview mode it can synthesize a single-section preview page. |
|
|
243
246
|
| `loadThemeSettings(options?)` | Fetches `/api/public/project_configs`, merges schema defaults under merchant settings, returns theme settings/static content/schema data for design mode. |
|
|
247
|
+
| `fetchCustomPages(options?)` | Fetches published custom pages from `/api/public/v1/projects/:projectId/custom-pages` for sitemap generation, paginating automatically and returning partial results if a later page fails. |
|
|
244
248
|
| `fetchWithCache<T>(url, options?)` | Next-aware fetch helper. Uses `cache: 'no-store'` in design/revision preview and `next: { revalidate, tags }` in published mode. |
|
|
245
249
|
| `resolveProjectId()` / `projectId` | Resolves project id from Studio query, config function/string, or env. |
|
|
246
250
|
| `components` | Server component registry. Components may include `schema` and optional `loader`. |
|
|
@@ -272,6 +276,43 @@ Loader args match the page-load and revalidation paths:
|
|
|
272
276
|
- `weaverse` — server/client object with `weaverse.storefront` compatibility alias.
|
|
273
277
|
- `context` — request context.
|
|
274
278
|
|
|
279
|
+
### SEO metadata
|
|
280
|
+
|
|
281
|
+
Use the server entry in `generateMetadata()` to map Weaverse `page.seo` into a Next Metadata-compatible object:
|
|
282
|
+
|
|
283
|
+
```ts
|
|
284
|
+
// app/pages/[handle]/page.tsx
|
|
285
|
+
import { getWeaverseNextSeoMetadata } from '@weaverse/next/server'
|
|
286
|
+
|
|
287
|
+
export async function generateMetadata(props: {
|
|
288
|
+
params: Promise<{ handle: string }>
|
|
289
|
+
searchParams: Promise<Record<string, string | string[] | undefined>>
|
|
290
|
+
}) {
|
|
291
|
+
let { handle } = await props.params
|
|
292
|
+
let weaverse = await getWeaverseServerClient(props.searchParams, `/pages/${handle}`)
|
|
293
|
+
let data = await weaverse.loadPage({ type: 'PAGE', handle })
|
|
294
|
+
return getWeaverseNextSeoMetadata(data)
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
The helper is pure and does not import `next/*`; its return shape is intentionally structural so the app can type it as `Metadata` if desired.
|
|
299
|
+
|
|
300
|
+
### Custom pages for sitemap generation
|
|
301
|
+
|
|
302
|
+
`fetchCustomPages()` mirrors Hydrogen's sitemap helper and accepts Next cache knobs:
|
|
303
|
+
|
|
304
|
+
```ts
|
|
305
|
+
let weaverse = await getWeaverseServerClient(Promise.resolve({}), '/')
|
|
306
|
+
let pages = await weaverse.fetchCustomPages({
|
|
307
|
+
locale: 'en-us',
|
|
308
|
+
limit: 100,
|
|
309
|
+
revalidate: 3600,
|
|
310
|
+
tags: ['weaverse:custom-pages'],
|
|
311
|
+
})
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
It paginates until the API returns `nextCursor: null`; if a later page fails, it returns the pages already fetched instead of throwing.
|
|
315
|
+
|
|
275
316
|
## Rendering in a Next route
|
|
276
317
|
|
|
277
318
|
Typical shape:
|
|
@@ -331,6 +372,57 @@ export function WeaversePage({ data }: { data: WeaverseNextLoaderData }) {
|
|
|
331
372
|
}
|
|
332
373
|
```
|
|
333
374
|
|
|
375
|
+
## Root theme provider
|
|
376
|
+
|
|
377
|
+
Global modules (`Header`, `Footer`, popups, a CSS-var bridge) render once in
|
|
378
|
+
`app/layout.tsx`, outside any route's `WeaverseNextProvider`. Mount
|
|
379
|
+
`WeaverseNextRootProvider` there so `useThemeSettings()` works for them too,
|
|
380
|
+
and so route-level providers share one theme settings store instead of each
|
|
381
|
+
creating their own — matching Hydrogen's root-owned `withWeaverse()` store.
|
|
382
|
+
|
|
383
|
+
```tsx
|
|
384
|
+
// app/layout.tsx
|
|
385
|
+
import { WeaverseNextRootProvider } from '@weaverse/next'
|
|
386
|
+
import { getWeaverseServerClient } from './weaverse-next/server'
|
|
387
|
+
|
|
388
|
+
export default async function RootLayout({
|
|
389
|
+
children,
|
|
390
|
+
}: {
|
|
391
|
+
children: React.ReactNode
|
|
392
|
+
}) {
|
|
393
|
+
let weaverse = await getWeaverseServerClient(Promise.resolve({}), '/')
|
|
394
|
+
let theme = await weaverse.loadThemeSettings()
|
|
395
|
+
|
|
396
|
+
return (
|
|
397
|
+
<html lang="en">
|
|
398
|
+
<body>
|
|
399
|
+
<WeaverseNextRootProvider
|
|
400
|
+
initialThemeSettings={theme.theme}
|
|
401
|
+
themeSchema={theme.schema}
|
|
402
|
+
>
|
|
403
|
+
<Header />
|
|
404
|
+
{children}
|
|
405
|
+
<Footer />
|
|
406
|
+
</WeaverseNextRootProvider>
|
|
407
|
+
</body>
|
|
408
|
+
</html>
|
|
409
|
+
)
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
A route's `WeaverseNextProvider` automatically adopts the root store when one
|
|
414
|
+
is mounted above it, instead of creating a second one — so Studio's live
|
|
415
|
+
edits reach both the root modules and the page renderer. The root's initial
|
|
416
|
+
theme is authoritative for SSR: routes should not load their own theme
|
|
417
|
+
settings in the final starter. If a route still carries
|
|
418
|
+
`themeSettings`/`client.themeSettings` (e.g. mid-migration), that data merges
|
|
419
|
+
into the root store in a client-only effect after mount, not during render —
|
|
420
|
+
so SSR always renders the root's value, with no render-phase mutation of the
|
|
421
|
+
shared store. Apps that don't mount `WeaverseNextRootProvider` see no
|
|
422
|
+
behavior change: `WeaverseNextProvider` falls back to creating its own store
|
|
423
|
+
and still renders `themeSettings`/`client.themeSettings` synchronously on
|
|
424
|
+
SSR, same as before.
|
|
425
|
+
|
|
334
426
|
## Studio setup
|
|
335
427
|
|
|
336
428
|
Studio has two separate pieces.
|
|
@@ -366,6 +458,13 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
|
|
366
458
|
}
|
|
367
459
|
```
|
|
368
460
|
|
|
461
|
+
Mounting it in the root layout (rather than per-page) also covers App Router
|
|
462
|
+
routes that never render `WeaverseNextRenderer`, such as `not-found.tsx` and
|
|
463
|
+
`error.tsx` — Studio needs the bridge script loaded before a page tree
|
|
464
|
+
exists, and the root layout still renders around those routes. This is
|
|
465
|
+
SSR-safe: `WeaverseNextStudioConnect` only touches `document` inside a
|
|
466
|
+
`useEffect`, so it is a no-op during server rendering.
|
|
467
|
+
|
|
369
468
|
### 2. Page-level runtime binding
|
|
370
469
|
|
|
371
470
|
`WeaverseNextRenderer` creates and binds the page runtime. Internally, `WeaverseNextStudio` maps Studio internals to Next App Router:
|
|
@@ -443,6 +542,5 @@ app/collections/[handle]/page.tsx # collection route Weaverse load
|
|
|
443
542
|
|
|
444
543
|
- This package is still alpha; API names may change before stable.
|
|
445
544
|
- Next does not provide Hydrogen's global React Router loader context, so apps should keep a small `getWeaverseServerClient(...)` helper.
|
|
545
|
+
- Translation/static-text sidecar parity, multiple Weaverse runtimes on one URL, and global sections are later hardening items.
|
|
446
546
|
- Full Shopify request-handler/redirect parity is app-level follow-up work, not owned by this package yet.
|
|
447
|
-
- Translation/static-text sidecar parity, multiple Weaverse runtimes on one URL, and 404/error-route Studio connection are later hardening items.
|
|
448
|
-
- The Studio bridge currently reuses the existing Studio bridge bundle until a Next-specific bundle is proven necessary.
|
|
@@ -158,6 +158,62 @@ function buildWeaverseNextRequestInfo(context) {
|
|
|
158
158
|
};
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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-6PMZ77RA.mjs.map
|
|
219
|
+
//# sourceMappingURL=chunk-6PMZ77RA.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-6PMZ77RA.mjs","sourcesContent":["import type { SchemaType } from '@weaverse/schema'\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 | 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,8 @@
|
|
|
1
1
|
import { Weaverse } from '@weaverse/react';
|
|
2
2
|
export { isBrowser, isIframe, useChildInstances, useItemInstance, useParentInstance, useWeaverse } from '@weaverse/react';
|
|
3
3
|
export { InspectorGroup, PageType, SchemaType, createSchema } from '@weaverse/schema';
|
|
4
|
-
import {
|
|
5
|
-
export { W as WeaverseCollection,
|
|
4
|
+
import { g as WeaverseNextClientConfig, f as WeaverseNextClient, h as WeaverseNextCommerceContext, w as WeaverseNextRequestContext, s as WeaverseNextLoaderData, x as WeaverseNextRequestInfo, j as WeaverseNextComponentData, H as WeaverseNextThemeSettingsStore, z as WeaverseNextRuntimeInternal, y as WeaverseNextRuntimeConfig } from './seo-B9yNko4W.mjs';
|
|
5
|
+
export { W as WeaverseArticle, a as WeaverseBlog, b as WeaverseCollection, c as WeaverseMetaObject, i as WeaverseNextComponent, k as WeaverseNextComponentLoaderArgs, l as WeaverseNextComponentProps, n as WeaverseNextCustomPageEntry, o as WeaverseNextFetchCustomPagesOptions, q as WeaverseNextI18n, r as WeaverseNextLoadPageInput, t as WeaverseNextPageAssignment, u as WeaverseNextPageData, A as WeaverseNextSeoMetadata, E as WeaverseNextStorefront, I as WeaverseProduct, J as formatWeaverseNextSeoMetadata, K as getWeaverseNextSeoMetadata } from './seo-B9yNko4W.mjs';
|
|
6
6
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
7
7
|
import * as react from 'react';
|
|
8
8
|
import { ReactNode } from 'react';
|
|
@@ -143,6 +143,37 @@ interface RevalidateItemRuntimeLike {
|
|
|
143
143
|
*/
|
|
144
144
|
declare function revalidateWeaverseNextItem(runtime: RevalidateItemRuntimeLike, draftItem: WeaverseNextComponentData, endpoint?: string): Promise<void>;
|
|
145
145
|
|
|
146
|
+
interface WeaverseNextRootContextValue {
|
|
147
|
+
themeSettingsStore: WeaverseNextThemeSettingsStore;
|
|
148
|
+
}
|
|
149
|
+
interface WeaverseNextRootProviderProps {
|
|
150
|
+
children: ReactNode;
|
|
151
|
+
/** Root-loaded theme settings (published-mode fetch, no design-mode context). */
|
|
152
|
+
initialThemeSettings?: Record<string, unknown>;
|
|
153
|
+
publicEnv?: Record<string, string | undefined>;
|
|
154
|
+
themeSchema?: unknown;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Root-scoped client boundary that owns the single `WeaverseNextThemeSettingsStore`
|
|
158
|
+
* for the whole app session, matching Hydrogen's `withWeaverse()` root store.
|
|
159
|
+
* Mount once in `app/layout.tsx`, above `Header`/`Footer`/global modules and any
|
|
160
|
+
* route-level `WeaverseNextProvider`.
|
|
161
|
+
*
|
|
162
|
+
* Also renders `WeaverseNextContext` with a minimal value so `useThemeSettings()`
|
|
163
|
+
* works for components mounted directly under this provider, even without a
|
|
164
|
+
* route-level `WeaverseNextProvider` above them.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```tsx
|
|
168
|
+
* <WeaverseNextRootProvider initialThemeSettings={theme.theme} themeSchema={theme.schema}>
|
|
169
|
+
* <Header />
|
|
170
|
+
* {children}
|
|
171
|
+
* <Footer />
|
|
172
|
+
* </WeaverseNextRootProvider>
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
declare function WeaverseNextRootProvider(props: WeaverseNextRootProviderProps): react_jsx_runtime.JSX.Element;
|
|
176
|
+
|
|
146
177
|
declare global {
|
|
147
178
|
interface Window {
|
|
148
179
|
__weaverse?: WeaverseNextRuntime;
|
|
@@ -177,11 +208,25 @@ interface WeaverseNextStudioBridgeProps {
|
|
|
177
208
|
/** Page-level Studio runtime binder. */
|
|
178
209
|
declare function WeaverseNextStudioBridge(props: WeaverseNextStudioBridgeProps): null;
|
|
179
210
|
|
|
211
|
+
interface LoadWeaverseNextStudioScriptOptions {
|
|
212
|
+
storefrontHostname?: string;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Resolve and append the Next Studio bridge script for the given request
|
|
216
|
+
* context, deduping by src. SSR-safe (no-op without `document`) so it can run
|
|
217
|
+
* unconditionally from a root layout/error boundary before any page tree or
|
|
218
|
+
* runtime exists — e.g. App Router `not-found.tsx` / `error.tsx` routes.
|
|
219
|
+
*/
|
|
220
|
+
declare function loadWeaverseNextStudioScript(context?: WeaverseNextRequestContext, options?: LoadWeaverseNextStudioScriptOptions): void;
|
|
180
221
|
interface WeaverseNextStudioConnectProps {
|
|
181
222
|
context?: WeaverseNextRequestContext;
|
|
182
223
|
storefrontHostname?: string;
|
|
183
224
|
}
|
|
184
|
-
/**
|
|
225
|
+
/**
|
|
226
|
+
* Root-level Studio script connector for Next client boundaries. Mount once
|
|
227
|
+
* near the app root (e.g. root layout) so it also covers routes that never
|
|
228
|
+
* render `WeaverseNextRenderer`, such as `not-found.tsx` / `error.tsx`.
|
|
229
|
+
*/
|
|
185
230
|
declare function WeaverseNextStudioConnect(props: WeaverseNextStudioConnectProps): null;
|
|
186
231
|
|
|
187
232
|
/**
|
|
@@ -276,4 +321,4 @@ interface WeaverseNextStudioProps extends CreateWeaverseNextStudioInternalsOptio
|
|
|
276
321
|
*/
|
|
277
322
|
declare function WeaverseNextStudio(props: WeaverseNextStudioProps): react_jsx_runtime.JSX.Element;
|
|
278
323
|
|
|
279
|
-
export { type CreateWeaverseNextStudioInternalsOptions, type CreateWeaverseNextThemeSettingsStoreOptions, DEFAULT_REVALIDATE_ENDPOINT, type ResolveWeaverseNextStudioScriptSrcOptions, type RevalidateItemRuntimeLike, type RunComponentLoadersArgs, WeaverseNextClient, WeaverseNextClientConfig, WeaverseNextCommerceContext, WeaverseNextComponentData, WeaverseNextLoaderData, WeaverseNextProvider, type WeaverseNextProviderProps, WeaverseNextRenderer, type WeaverseNextRendererProps, WeaverseNextRequestContext, WeaverseNextRequestInfo, type WeaverseNextRouterLike, WeaverseNextRuntime, WeaverseNextRuntimeConfig, WeaverseNextRuntimeInternal, WeaverseNextStudio, WeaverseNextStudioBridge, type WeaverseNextStudioBridgeProps, WeaverseNextStudioConnect, type WeaverseNextStudioConnectProps, type WeaverseNextStudioInternals, type WeaverseNextStudioProps, WeaverseNextThemeSettingsStore, bindWeaverseNextStudioRuntime, buildWeaverseNextRequestInfo, createWeaverseNextClient, createWeaverseNextRuntime, createWeaverseNextStudioInternals, createWeaverseNextThemeSettingsStore, resolveWeaverseNextStudioScriptSrc, revalidateWeaverseNextItem, runWeaverseComponentLoaders, useThemeSettings, useWeaverseCommerce, useWeaverseNextStudioInternals, useWeaversePageData, useWeaverseRootData };
|
|
324
|
+
export { type CreateWeaverseNextStudioInternalsOptions, type CreateWeaverseNextThemeSettingsStoreOptions, DEFAULT_REVALIDATE_ENDPOINT, type LoadWeaverseNextStudioScriptOptions, type ResolveWeaverseNextStudioScriptSrcOptions, type RevalidateItemRuntimeLike, type RunComponentLoadersArgs, WeaverseNextClient, WeaverseNextClientConfig, WeaverseNextCommerceContext, WeaverseNextComponentData, WeaverseNextLoaderData, 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, WeaverseNextThemeSettingsStore, bindWeaverseNextStudioRuntime, buildWeaverseNextRequestInfo, createWeaverseNextClient, createWeaverseNextRuntime, createWeaverseNextStudioInternals, createWeaverseNextThemeSettingsStore, loadWeaverseNextStudioScript, resolveWeaverseNextStudioScriptSrc, revalidateWeaverseNextItem, runWeaverseComponentLoaders, useThemeSettings, useWeaverseCommerce, useWeaverseNextStudioInternals, useWeaversePageData, useWeaverseRootData };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Weaverse } from '@weaverse/react';
|
|
2
2
|
export { isBrowser, isIframe, useChildInstances, useItemInstance, useParentInstance, useWeaverse } from '@weaverse/react';
|
|
3
3
|
export { InspectorGroup, PageType, SchemaType, createSchema } from '@weaverse/schema';
|
|
4
|
-
import {
|
|
5
|
-
export { W as WeaverseCollection,
|
|
4
|
+
import { g as WeaverseNextClientConfig, f as WeaverseNextClient, h as WeaverseNextCommerceContext, w as WeaverseNextRequestContext, s as WeaverseNextLoaderData, x as WeaverseNextRequestInfo, j as WeaverseNextComponentData, H as WeaverseNextThemeSettingsStore, z as WeaverseNextRuntimeInternal, y as WeaverseNextRuntimeConfig } from './seo-B9yNko4W.js';
|
|
5
|
+
export { W as WeaverseArticle, a as WeaverseBlog, b as WeaverseCollection, c as WeaverseMetaObject, i as WeaverseNextComponent, k as WeaverseNextComponentLoaderArgs, l as WeaverseNextComponentProps, n as WeaverseNextCustomPageEntry, o as WeaverseNextFetchCustomPagesOptions, q as WeaverseNextI18n, r as WeaverseNextLoadPageInput, t as WeaverseNextPageAssignment, u as WeaverseNextPageData, A as WeaverseNextSeoMetadata, E as WeaverseNextStorefront, I as WeaverseProduct, J as formatWeaverseNextSeoMetadata, K as getWeaverseNextSeoMetadata } from './seo-B9yNko4W.js';
|
|
6
6
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
7
7
|
import * as react from 'react';
|
|
8
8
|
import { ReactNode } from 'react';
|
|
@@ -143,6 +143,37 @@ interface RevalidateItemRuntimeLike {
|
|
|
143
143
|
*/
|
|
144
144
|
declare function revalidateWeaverseNextItem(runtime: RevalidateItemRuntimeLike, draftItem: WeaverseNextComponentData, endpoint?: string): Promise<void>;
|
|
145
145
|
|
|
146
|
+
interface WeaverseNextRootContextValue {
|
|
147
|
+
themeSettingsStore: WeaverseNextThemeSettingsStore;
|
|
148
|
+
}
|
|
149
|
+
interface WeaverseNextRootProviderProps {
|
|
150
|
+
children: ReactNode;
|
|
151
|
+
/** Root-loaded theme settings (published-mode fetch, no design-mode context). */
|
|
152
|
+
initialThemeSettings?: Record<string, unknown>;
|
|
153
|
+
publicEnv?: Record<string, string | undefined>;
|
|
154
|
+
themeSchema?: unknown;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Root-scoped client boundary that owns the single `WeaverseNextThemeSettingsStore`
|
|
158
|
+
* for the whole app session, matching Hydrogen's `withWeaverse()` root store.
|
|
159
|
+
* Mount once in `app/layout.tsx`, above `Header`/`Footer`/global modules and any
|
|
160
|
+
* route-level `WeaverseNextProvider`.
|
|
161
|
+
*
|
|
162
|
+
* Also renders `WeaverseNextContext` with a minimal value so `useThemeSettings()`
|
|
163
|
+
* works for components mounted directly under this provider, even without a
|
|
164
|
+
* route-level `WeaverseNextProvider` above them.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```tsx
|
|
168
|
+
* <WeaverseNextRootProvider initialThemeSettings={theme.theme} themeSchema={theme.schema}>
|
|
169
|
+
* <Header />
|
|
170
|
+
* {children}
|
|
171
|
+
* <Footer />
|
|
172
|
+
* </WeaverseNextRootProvider>
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
declare function WeaverseNextRootProvider(props: WeaverseNextRootProviderProps): react_jsx_runtime.JSX.Element;
|
|
176
|
+
|
|
146
177
|
declare global {
|
|
147
178
|
interface Window {
|
|
148
179
|
__weaverse?: WeaverseNextRuntime;
|
|
@@ -177,11 +208,25 @@ interface WeaverseNextStudioBridgeProps {
|
|
|
177
208
|
/** Page-level Studio runtime binder. */
|
|
178
209
|
declare function WeaverseNextStudioBridge(props: WeaverseNextStudioBridgeProps): null;
|
|
179
210
|
|
|
211
|
+
interface LoadWeaverseNextStudioScriptOptions {
|
|
212
|
+
storefrontHostname?: string;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Resolve and append the Next Studio bridge script for the given request
|
|
216
|
+
* context, deduping by src. SSR-safe (no-op without `document`) so it can run
|
|
217
|
+
* unconditionally from a root layout/error boundary before any page tree or
|
|
218
|
+
* runtime exists — e.g. App Router `not-found.tsx` / `error.tsx` routes.
|
|
219
|
+
*/
|
|
220
|
+
declare function loadWeaverseNextStudioScript(context?: WeaverseNextRequestContext, options?: LoadWeaverseNextStudioScriptOptions): void;
|
|
180
221
|
interface WeaverseNextStudioConnectProps {
|
|
181
222
|
context?: WeaverseNextRequestContext;
|
|
182
223
|
storefrontHostname?: string;
|
|
183
224
|
}
|
|
184
|
-
/**
|
|
225
|
+
/**
|
|
226
|
+
* Root-level Studio script connector for Next client boundaries. Mount once
|
|
227
|
+
* near the app root (e.g. root layout) so it also covers routes that never
|
|
228
|
+
* render `WeaverseNextRenderer`, such as `not-found.tsx` / `error.tsx`.
|
|
229
|
+
*/
|
|
185
230
|
declare function WeaverseNextStudioConnect(props: WeaverseNextStudioConnectProps): null;
|
|
186
231
|
|
|
187
232
|
/**
|
|
@@ -276,4 +321,4 @@ interface WeaverseNextStudioProps extends CreateWeaverseNextStudioInternalsOptio
|
|
|
276
321
|
*/
|
|
277
322
|
declare function WeaverseNextStudio(props: WeaverseNextStudioProps): react_jsx_runtime.JSX.Element;
|
|
278
323
|
|
|
279
|
-
export { type CreateWeaverseNextStudioInternalsOptions, type CreateWeaverseNextThemeSettingsStoreOptions, DEFAULT_REVALIDATE_ENDPOINT, type ResolveWeaverseNextStudioScriptSrcOptions, type RevalidateItemRuntimeLike, type RunComponentLoadersArgs, WeaverseNextClient, WeaverseNextClientConfig, WeaverseNextCommerceContext, WeaverseNextComponentData, WeaverseNextLoaderData, WeaverseNextProvider, type WeaverseNextProviderProps, WeaverseNextRenderer, type WeaverseNextRendererProps, WeaverseNextRequestContext, WeaverseNextRequestInfo, type WeaverseNextRouterLike, WeaverseNextRuntime, WeaverseNextRuntimeConfig, WeaverseNextRuntimeInternal, WeaverseNextStudio, WeaverseNextStudioBridge, type WeaverseNextStudioBridgeProps, WeaverseNextStudioConnect, type WeaverseNextStudioConnectProps, type WeaverseNextStudioInternals, type WeaverseNextStudioProps, WeaverseNextThemeSettingsStore, bindWeaverseNextStudioRuntime, buildWeaverseNextRequestInfo, createWeaverseNextClient, createWeaverseNextRuntime, createWeaverseNextStudioInternals, createWeaverseNextThemeSettingsStore, resolveWeaverseNextStudioScriptSrc, revalidateWeaverseNextItem, runWeaverseComponentLoaders, useThemeSettings, useWeaverseCommerce, useWeaverseNextStudioInternals, useWeaversePageData, useWeaverseRootData };
|
|
324
|
+
export { type CreateWeaverseNextStudioInternalsOptions, type CreateWeaverseNextThemeSettingsStoreOptions, DEFAULT_REVALIDATE_ENDPOINT, type LoadWeaverseNextStudioScriptOptions, type ResolveWeaverseNextStudioScriptSrcOptions, type RevalidateItemRuntimeLike, type RunComponentLoadersArgs, WeaverseNextClient, WeaverseNextClientConfig, WeaverseNextCommerceContext, WeaverseNextComponentData, WeaverseNextLoaderData, 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, WeaverseNextThemeSettingsStore, bindWeaverseNextStudioRuntime, buildWeaverseNextRequestInfo, createWeaverseNextClient, createWeaverseNextRuntime, createWeaverseNextStudioInternals, createWeaverseNextThemeSettingsStore, loadWeaverseNextStudioScript, resolveWeaverseNextStudioScriptSrc, revalidateWeaverseNextItem, runWeaverseComponentLoaders, useThemeSettings, useWeaverseCommerce, useWeaverseNextStudioInternals, useWeaversePageData, useWeaverseRootData };
|
package/dist/index.js
CHANGED
|
@@ -158,18 +158,61 @@ function createWeaverseNextThemeSettingsStore(options = {}) {
|
|
|
158
158
|
};
|
|
159
159
|
return store;
|
|
160
160
|
}
|
|
161
|
+
var WeaverseNextRootContext = react$1.createContext(null);
|
|
162
|
+
function WeaverseNextRootProvider(props) {
|
|
163
|
+
let { children, initialThemeSettings, themeSchema, publicEnv } = props;
|
|
164
|
+
let storeRef = react$1.useRef(null);
|
|
165
|
+
if (!storeRef.current) {
|
|
166
|
+
storeRef.current = createWeaverseNextThemeSettingsStore({
|
|
167
|
+
publicEnv,
|
|
168
|
+
schema: themeSchema,
|
|
169
|
+
settings: initialThemeSettings
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
let themeSettingsStore = storeRef.current;
|
|
173
|
+
let appliedThemeSettingsRef = react$1.useRef(initialThemeSettings);
|
|
174
|
+
react$1.useEffect(() => {
|
|
175
|
+
if (initialThemeSettings && appliedThemeSettingsRef.current !== initialThemeSettings) {
|
|
176
|
+
themeSettingsStore.updateThemeSettings(initialThemeSettings);
|
|
177
|
+
appliedThemeSettingsRef.current = initialThemeSettings;
|
|
178
|
+
}
|
|
179
|
+
}, [initialThemeSettings, themeSettingsStore]);
|
|
180
|
+
let rootContextValue = react$1.useMemo(
|
|
181
|
+
() => ({ themeSettingsStore }),
|
|
182
|
+
[themeSettingsStore]
|
|
183
|
+
);
|
|
184
|
+
let contextValue = react$1.useMemo(
|
|
185
|
+
() => ({
|
|
186
|
+
themeSettings: themeSettingsStore.getSnapshot(),
|
|
187
|
+
themeSettingsStore
|
|
188
|
+
}),
|
|
189
|
+
[themeSettingsStore]
|
|
190
|
+
);
|
|
191
|
+
return /* @__PURE__ */ jsxRuntime.jsx(WeaverseNextRootContext.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(WeaverseNextContext.Provider, { value: contextValue, children }) });
|
|
192
|
+
}
|
|
161
193
|
var EMPTY_THEME_SETTINGS = {};
|
|
162
194
|
var WeaverseNextContext = react$1.createContext(null);
|
|
163
195
|
function WeaverseNextProvider(props) {
|
|
164
196
|
let { children, client, rootData, pageData, commerce, themeSettings } = props;
|
|
197
|
+
let rootContext = react$1.useContext(WeaverseNextRootContext);
|
|
165
198
|
let themeSettingsValue = themeSettings ?? client?.themeSettings ?? EMPTY_THEME_SETTINGS;
|
|
166
|
-
let
|
|
167
|
-
()
|
|
199
|
+
let ownThemeSettingsStore = react$1.useMemo(() => {
|
|
200
|
+
if (rootContext) {
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
return createWeaverseNextThemeSettingsStore({
|
|
168
204
|
schema: client?.themeSchema,
|
|
169
205
|
settings: themeSettingsValue
|
|
170
|
-
})
|
|
171
|
-
|
|
172
|
-
|
|
206
|
+
});
|
|
207
|
+
}, [rootContext, client?.themeSchema, themeSettingsValue]);
|
|
208
|
+
let themeSettingsStore = rootContext?.themeSettingsStore ?? ownThemeSettingsStore;
|
|
209
|
+
let mergedIntoRootRef = react$1.useRef(void 0);
|
|
210
|
+
react$1.useEffect(() => {
|
|
211
|
+
if (rootContext && themeSettingsValue !== EMPTY_THEME_SETTINGS && mergedIntoRootRef.current !== themeSettingsValue) {
|
|
212
|
+
rootContext.themeSettingsStore.updateThemeSettings(themeSettingsValue);
|
|
213
|
+
mergedIntoRootRef.current = themeSettingsValue;
|
|
214
|
+
}
|
|
215
|
+
}, [rootContext, themeSettingsValue]);
|
|
173
216
|
let value = react$1.useMemo(
|
|
174
217
|
() => ({
|
|
175
218
|
client,
|
|
@@ -675,6 +718,62 @@ var WeaverseNextRenderer = react$1.memo(function WeaverseNextRendererComponent(p
|
|
|
675
718
|
] });
|
|
676
719
|
});
|
|
677
720
|
|
|
721
|
+
// src/seo.ts
|
|
722
|
+
function hasOpenGraphContent(seo) {
|
|
723
|
+
return Boolean(seo?.title || seo?.description || seo?.image || seo?.type);
|
|
724
|
+
}
|
|
725
|
+
function hasTwitterContent(seo) {
|
|
726
|
+
return Boolean(seo?.title || seo?.description || seo?.image || seo?.cardType);
|
|
727
|
+
}
|
|
728
|
+
function formatWeaverseNextSeoMetadata(seo) {
|
|
729
|
+
let index = seo?.robots?.index !== false;
|
|
730
|
+
let follow = seo?.robots?.follow !== false;
|
|
731
|
+
let metadata = {
|
|
732
|
+
robots: { index, follow }
|
|
733
|
+
};
|
|
734
|
+
if (!seo) {
|
|
735
|
+
return metadata;
|
|
736
|
+
}
|
|
737
|
+
if (seo.title) {
|
|
738
|
+
metadata.title = seo.title;
|
|
739
|
+
}
|
|
740
|
+
if (seo.description) {
|
|
741
|
+
metadata.description = seo.description;
|
|
742
|
+
}
|
|
743
|
+
if (seo.keywords) {
|
|
744
|
+
metadata.keywords = seo.keywords;
|
|
745
|
+
}
|
|
746
|
+
if (seo.canonicalUrl) {
|
|
747
|
+
metadata.alternates = { canonical: seo.canonicalUrl };
|
|
748
|
+
}
|
|
749
|
+
let openGraph = seo.openGraph;
|
|
750
|
+
if (hasOpenGraphContent(openGraph)) {
|
|
751
|
+
metadata.openGraph = {
|
|
752
|
+
title: openGraph?.title,
|
|
753
|
+
description: openGraph?.description,
|
|
754
|
+
images: openGraph?.image ? [openGraph.image] : void 0,
|
|
755
|
+
type: openGraph?.type || "website"
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
let twitter = seo.twitter;
|
|
759
|
+
if (hasTwitterContent(twitter)) {
|
|
760
|
+
metadata.twitter = {
|
|
761
|
+
card: twitter?.cardType || "summary",
|
|
762
|
+
title: twitter?.title,
|
|
763
|
+
description: twitter?.description,
|
|
764
|
+
images: twitter?.image ? [twitter.image] : void 0
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
return metadata;
|
|
768
|
+
}
|
|
769
|
+
function getWeaverseNextSeoMetadata(data) {
|
|
770
|
+
if (!data) {
|
|
771
|
+
return formatWeaverseNextSeoMetadata(null);
|
|
772
|
+
}
|
|
773
|
+
let page = "items" in data && "id" in data ? data : data.page ?? null;
|
|
774
|
+
return formatWeaverseNextSeoMetadata(page?.seo ?? null);
|
|
775
|
+
}
|
|
776
|
+
|
|
678
777
|
// src/studio-script-src.ts
|
|
679
778
|
var TRUSTED_STUDIO_DOMAINS = ["weaverse.io", "weaverse.dev"];
|
|
680
779
|
function isLoopbackHostname(hostname) {
|
|
@@ -764,21 +863,26 @@ function loadScript(src) {
|
|
|
764
863
|
document.head.appendChild(script);
|
|
765
864
|
loadedScriptSrcs.add(src);
|
|
766
865
|
}
|
|
866
|
+
function loadWeaverseNextStudioScript(context, options = {}) {
|
|
867
|
+
let resolvedContext = context;
|
|
868
|
+
if (!resolvedContext && typeof window !== "undefined") {
|
|
869
|
+
resolvedContext = {
|
|
870
|
+
searchParams: new URLSearchParams(window.location.search),
|
|
871
|
+
url: window.location.href
|
|
872
|
+
};
|
|
873
|
+
}
|
|
874
|
+
let src = resolveWeaverseNextStudioScriptSrc(resolvedContext, {
|
|
875
|
+
storefrontHostname: options.storefrontHostname ?? (typeof window === "undefined" ? void 0 : window.location.hostname)
|
|
876
|
+
});
|
|
877
|
+
if (src) {
|
|
878
|
+
loadScript(src);
|
|
879
|
+
}
|
|
880
|
+
}
|
|
767
881
|
function WeaverseNextStudioConnect(props) {
|
|
768
882
|
react$1.useEffect(() => {
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
context = {
|
|
772
|
-
searchParams: new URLSearchParams(window.location.search),
|
|
773
|
-
url: window.location.href
|
|
774
|
-
};
|
|
775
|
-
}
|
|
776
|
-
let src = resolveWeaverseNextStudioScriptSrc(context, {
|
|
777
|
-
storefrontHostname: props.storefrontHostname ?? (typeof window === "undefined" ? void 0 : window.location.hostname)
|
|
883
|
+
loadWeaverseNextStudioScript(props.context, {
|
|
884
|
+
storefrontHostname: props.storefrontHostname
|
|
778
885
|
});
|
|
779
|
-
if (src) {
|
|
780
|
-
loadScript(src);
|
|
781
|
-
}
|
|
782
886
|
}, [props.context, props.storefrontHostname]);
|
|
783
887
|
return null;
|
|
784
888
|
}
|
|
@@ -814,6 +918,7 @@ Object.defineProperty(exports, "createSchema", {
|
|
|
814
918
|
exports.DEFAULT_REVALIDATE_ENDPOINT = DEFAULT_REVALIDATE_ENDPOINT;
|
|
815
919
|
exports.WeaverseNextProvider = WeaverseNextProvider;
|
|
816
920
|
exports.WeaverseNextRenderer = WeaverseNextRenderer;
|
|
921
|
+
exports.WeaverseNextRootProvider = WeaverseNextRootProvider;
|
|
817
922
|
exports.WeaverseNextRuntime = WeaverseNextRuntime;
|
|
818
923
|
exports.WeaverseNextStudio = WeaverseNextStudio;
|
|
819
924
|
exports.WeaverseNextStudioBridge = WeaverseNextStudioBridge;
|
|
@@ -824,6 +929,9 @@ exports.createWeaverseNextClient = createWeaverseNextClient;
|
|
|
824
929
|
exports.createWeaverseNextRuntime = createWeaverseNextRuntime;
|
|
825
930
|
exports.createWeaverseNextStudioInternals = createWeaverseNextStudioInternals;
|
|
826
931
|
exports.createWeaverseNextThemeSettingsStore = createWeaverseNextThemeSettingsStore;
|
|
932
|
+
exports.formatWeaverseNextSeoMetadata = formatWeaverseNextSeoMetadata;
|
|
933
|
+
exports.getWeaverseNextSeoMetadata = getWeaverseNextSeoMetadata;
|
|
934
|
+
exports.loadWeaverseNextStudioScript = loadWeaverseNextStudioScript;
|
|
827
935
|
exports.resolveWeaverseNextStudioScriptSrc = resolveWeaverseNextStudioScriptSrc;
|
|
828
936
|
exports.revalidateWeaverseNextItem = revalidateWeaverseNextItem;
|
|
829
937
|
exports.runWeaverseComponentLoaders = runWeaverseComponentLoaders;
|