@weaverse/next 0.1.0-alpha.1 → 0.1.0-alpha.3
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 +17 -1
- package/dist/{chunk-SS6QUKYY.mjs → chunk-O2TG2NYL.mjs} +17 -3
- package/dist/chunk-O2TG2NYL.mjs.map +1 -0
- package/dist/index.d.mts +67 -1
- package/dist/index.d.ts +67 -1
- package/dist/index.js +67 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +52 -4
- package/dist/index.mjs.map +1 -1
- package/dist/server.js +16 -2
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +2 -2
- package/dist/server.mjs.map +1 -1
- package/package.json +7 -2
- package/dist/chunk-SS6QUKYY.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -61,9 +61,25 @@ packages/next/src/
|
|
|
61
61
|
## Server API (`@weaverse/next/server`)
|
|
62
62
|
|
|
63
63
|
`createWeaverseNextServerClient(config)` returns a client that performs the real
|
|
64
|
-
Weaverse public API fetch — the equivalent of Hydrogen's
|
|
64
|
+
Weaverse public API fetch — the equivalent of Hydrogen/Pilot's
|
|
65
65
|
`context.weaverse.loadPage(...)`.
|
|
66
66
|
|
|
67
|
+
### Next App Router server context model
|
|
68
|
+
|
|
69
|
+
Hydrogen's classic storefront runtime is built on React Router. Its request
|
|
70
|
+
handler accepts `getLoadContext(request)`, creates a Hydrogen context, and React
|
|
71
|
+
Router injects that object into every route loader. That is why a Pilot route can
|
|
72
|
+
call `context.weaverse.loadPage(...)` directly.
|
|
73
|
+
|
|
74
|
+
Next App Router does not inject an app-defined global loader context into
|
|
75
|
+
`app/page.tsx`. A page is a Server Component whose framework-provided inputs are
|
|
76
|
+
`params` and `searchParams`; request-scoped data is read with Next functions such
|
|
77
|
+
as `headers()` / `cookies()`. Hydrogen preview follows that framework model for
|
|
78
|
+
Next examples: fetch in `app/page.tsx` or a server helper, then pass the snapshot
|
|
79
|
+
to client components.
|
|
80
|
+
|
|
81
|
+
So the Next equivalent is explicit server-client creation at the route boundary:
|
|
82
|
+
|
|
67
83
|
```ts
|
|
68
84
|
import { createWeaverseNextServerClient } from '@weaverse/next/server'
|
|
69
85
|
import { components } from '@/weaverse/components'
|
|
@@ -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),
|
|
@@ -145,5 +159,5 @@ function buildWeaverseNextRequestInfo(context) {
|
|
|
145
159
|
}
|
|
146
160
|
|
|
147
161
|
export { buildWeaverseNextRequestInfo, generateDataFromSchema, runWeaverseComponentLoaders };
|
|
148
|
-
//# sourceMappingURL=chunk-
|
|
149
|
-
//# sourceMappingURL=chunk-
|
|
162
|
+
//# sourceMappingURL=chunk-O2TG2NYL.mjs.map
|
|
163
|
+
//# sourceMappingURL=chunk-O2TG2NYL.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts","../src/loader.ts","../src/request-info.ts"],"names":[],"mappings":"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","file":"chunk-O2TG2NYL.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"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -158,6 +158,47 @@ interface WeaverseNextStudioConnectProps {
|
|
|
158
158
|
/** Root-level Studio script connector for Next client boundaries. */
|
|
159
159
|
declare function WeaverseNextStudioConnect(props: WeaverseNextStudioConnectProps): null;
|
|
160
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Minimal structural shape of the Next App Router returned by `useRouter()`
|
|
163
|
+
* (`next/navigation`) that the Studio bridge needs. Declared locally — rather
|
|
164
|
+
* than importing `AppRouterInstance` from `next` — so the adapter stays a pure
|
|
165
|
+
* function that unit tests can drive with a plain mock and never pulls
|
|
166
|
+
* `next/navigation` into the test graph.
|
|
167
|
+
*/
|
|
168
|
+
interface WeaverseNextRouterLike {
|
|
169
|
+
push: (href: string, options?: {
|
|
170
|
+
scroll?: boolean;
|
|
171
|
+
}) => void;
|
|
172
|
+
refresh: () => void;
|
|
173
|
+
replace: (href: string, options?: {
|
|
174
|
+
scroll?: boolean;
|
|
175
|
+
}) => void;
|
|
176
|
+
}
|
|
177
|
+
/** Resolved Studio navigation/revalidation callbacks for a Next runtime. */
|
|
178
|
+
interface WeaverseNextStudioInternals {
|
|
179
|
+
navigate: NonNullable<WeaverseNextRuntimeInternal['navigate']>;
|
|
180
|
+
revalidate: NonNullable<WeaverseNextRuntimeInternal['revalidate']>;
|
|
181
|
+
}
|
|
182
|
+
interface CreateWeaverseNextStudioInternalsOptions {
|
|
183
|
+
/** Use `router.replace` instead of `router.push` for navigation. */
|
|
184
|
+
replace?: boolean;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Build Studio `navigate` / `revalidate` callbacks from a Next App Router.
|
|
188
|
+
*
|
|
189
|
+
* Maps Hydrogen's React Router semantics onto Next App Router:
|
|
190
|
+
* - `navigate(to, { preventScrollReset })` → `router.push(to, { scroll })`,
|
|
191
|
+
* where `scroll` is the inverse of `preventScrollReset`. Studio passes
|
|
192
|
+
* `preventScrollReset` for in-place edits so the preview viewport is kept,
|
|
193
|
+
* matching React Router's `navigate({ preventScrollReset })`.
|
|
194
|
+
* - `revalidate()` → `router.refresh()`, the App Router's loader-backed refresh
|
|
195
|
+
* and the closest equivalent to React Router's `useRevalidator`.
|
|
196
|
+
*
|
|
197
|
+
* Pure (no React, no `next/navigation`) so it is unit-testable with a mock
|
|
198
|
+
* router; the {@link WeaverseNextRouterLike} contract is the only coupling.
|
|
199
|
+
*/
|
|
200
|
+
declare function createWeaverseNextStudioInternals(router: WeaverseNextRouterLike, options?: CreateWeaverseNextStudioInternalsOptions): WeaverseNextStudioInternals;
|
|
201
|
+
|
|
161
202
|
interface ResolveWeaverseNextStudioScriptSrcOptions {
|
|
162
203
|
framework?: 'hydrogen' | 'next';
|
|
163
204
|
storefrontHostname?: string;
|
|
@@ -181,4 +222,29 @@ interface CreateWeaverseNextThemeSettingsStoreOptions {
|
|
|
181
222
|
*/
|
|
182
223
|
declare function createWeaverseNextThemeSettingsStore(options?: CreateWeaverseNextThemeSettingsStoreOptions): WeaverseNextThemeSettingsStore;
|
|
183
224
|
|
|
184
|
-
|
|
225
|
+
/**
|
|
226
|
+
* Resolve stable Studio `navigate` / `revalidate` callbacks from the Next App
|
|
227
|
+
* Router. `useRouter()` is stable across renders, but the derived callbacks are
|
|
228
|
+
* cached in a ref keyed on the router instance so the bridge's bind effect
|
|
229
|
+
* (which depends on `navigate` / `revalidate` identity) doesn't re-run — and
|
|
230
|
+
* re-`refreshStudio` — on every render.
|
|
231
|
+
*/
|
|
232
|
+
declare function useWeaverseNextStudioInternals(options?: CreateWeaverseNextStudioInternalsOptions): WeaverseNextStudioInternals;
|
|
233
|
+
interface WeaverseNextStudioProps extends CreateWeaverseNextStudioInternalsOptions {
|
|
234
|
+
runtime: WeaverseNextRuntime;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Page-level Studio binder wired to the Next App Router. Mirrors Hydrogen's
|
|
238
|
+
* `useStudio` (which binds the runtime and feeds it React Router's `navigate` /
|
|
239
|
+
* `revalidate`): it resolves the App Router callbacks via
|
|
240
|
+
* {@link useWeaverseNextStudioInternals} and hands them to
|
|
241
|
+
* {@link WeaverseNextStudioBridge}, so consuming apps get Studio navigation and
|
|
242
|
+
* revalidation without manually wiring `next/navigation`.
|
|
243
|
+
*
|
|
244
|
+
* Client-only — it is the single place `@weaverse/next` touches
|
|
245
|
+
* `next/navigation`, keeping the runtime/renderer and `@weaverse/next/server`
|
|
246
|
+
* free of router imports.
|
|
247
|
+
*/
|
|
248
|
+
declare function WeaverseNextStudio(props: WeaverseNextStudioProps): react_jsx_runtime.JSX.Element;
|
|
249
|
+
|
|
250
|
+
export { type CreateWeaverseNextStudioInternalsOptions, type CreateWeaverseNextThemeSettingsStoreOptions, type ResolveWeaverseNextStudioScriptSrcOptions, type RunComponentLoadersArgs, WeaverseNextClient, WeaverseNextClientConfig, WeaverseNextCommerceContext, 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, runWeaverseComponentLoaders, useThemeSettings, useWeaverseCommerce, useWeaverseNextStudioInternals, useWeaversePageData, useWeaverseRootData };
|
package/dist/index.d.ts
CHANGED
|
@@ -158,6 +158,47 @@ interface WeaverseNextStudioConnectProps {
|
|
|
158
158
|
/** Root-level Studio script connector for Next client boundaries. */
|
|
159
159
|
declare function WeaverseNextStudioConnect(props: WeaverseNextStudioConnectProps): null;
|
|
160
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Minimal structural shape of the Next App Router returned by `useRouter()`
|
|
163
|
+
* (`next/navigation`) that the Studio bridge needs. Declared locally — rather
|
|
164
|
+
* than importing `AppRouterInstance` from `next` — so the adapter stays a pure
|
|
165
|
+
* function that unit tests can drive with a plain mock and never pulls
|
|
166
|
+
* `next/navigation` into the test graph.
|
|
167
|
+
*/
|
|
168
|
+
interface WeaverseNextRouterLike {
|
|
169
|
+
push: (href: string, options?: {
|
|
170
|
+
scroll?: boolean;
|
|
171
|
+
}) => void;
|
|
172
|
+
refresh: () => void;
|
|
173
|
+
replace: (href: string, options?: {
|
|
174
|
+
scroll?: boolean;
|
|
175
|
+
}) => void;
|
|
176
|
+
}
|
|
177
|
+
/** Resolved Studio navigation/revalidation callbacks for a Next runtime. */
|
|
178
|
+
interface WeaverseNextStudioInternals {
|
|
179
|
+
navigate: NonNullable<WeaverseNextRuntimeInternal['navigate']>;
|
|
180
|
+
revalidate: NonNullable<WeaverseNextRuntimeInternal['revalidate']>;
|
|
181
|
+
}
|
|
182
|
+
interface CreateWeaverseNextStudioInternalsOptions {
|
|
183
|
+
/** Use `router.replace` instead of `router.push` for navigation. */
|
|
184
|
+
replace?: boolean;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Build Studio `navigate` / `revalidate` callbacks from a Next App Router.
|
|
188
|
+
*
|
|
189
|
+
* Maps Hydrogen's React Router semantics onto Next App Router:
|
|
190
|
+
* - `navigate(to, { preventScrollReset })` → `router.push(to, { scroll })`,
|
|
191
|
+
* where `scroll` is the inverse of `preventScrollReset`. Studio passes
|
|
192
|
+
* `preventScrollReset` for in-place edits so the preview viewport is kept,
|
|
193
|
+
* matching React Router's `navigate({ preventScrollReset })`.
|
|
194
|
+
* - `revalidate()` → `router.refresh()`, the App Router's loader-backed refresh
|
|
195
|
+
* and the closest equivalent to React Router's `useRevalidator`.
|
|
196
|
+
*
|
|
197
|
+
* Pure (no React, no `next/navigation`) so it is unit-testable with a mock
|
|
198
|
+
* router; the {@link WeaverseNextRouterLike} contract is the only coupling.
|
|
199
|
+
*/
|
|
200
|
+
declare function createWeaverseNextStudioInternals(router: WeaverseNextRouterLike, options?: CreateWeaverseNextStudioInternalsOptions): WeaverseNextStudioInternals;
|
|
201
|
+
|
|
161
202
|
interface ResolveWeaverseNextStudioScriptSrcOptions {
|
|
162
203
|
framework?: 'hydrogen' | 'next';
|
|
163
204
|
storefrontHostname?: string;
|
|
@@ -181,4 +222,29 @@ interface CreateWeaverseNextThemeSettingsStoreOptions {
|
|
|
181
222
|
*/
|
|
182
223
|
declare function createWeaverseNextThemeSettingsStore(options?: CreateWeaverseNextThemeSettingsStoreOptions): WeaverseNextThemeSettingsStore;
|
|
183
224
|
|
|
184
|
-
|
|
225
|
+
/**
|
|
226
|
+
* Resolve stable Studio `navigate` / `revalidate` callbacks from the Next App
|
|
227
|
+
* Router. `useRouter()` is stable across renders, but the derived callbacks are
|
|
228
|
+
* cached in a ref keyed on the router instance so the bridge's bind effect
|
|
229
|
+
* (which depends on `navigate` / `revalidate` identity) doesn't re-run — and
|
|
230
|
+
* re-`refreshStudio` — on every render.
|
|
231
|
+
*/
|
|
232
|
+
declare function useWeaverseNextStudioInternals(options?: CreateWeaverseNextStudioInternalsOptions): WeaverseNextStudioInternals;
|
|
233
|
+
interface WeaverseNextStudioProps extends CreateWeaverseNextStudioInternalsOptions {
|
|
234
|
+
runtime: WeaverseNextRuntime;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Page-level Studio binder wired to the Next App Router. Mirrors Hydrogen's
|
|
238
|
+
* `useStudio` (which binds the runtime and feeds it React Router's `navigate` /
|
|
239
|
+
* `revalidate`): it resolves the App Router callbacks via
|
|
240
|
+
* {@link useWeaverseNextStudioInternals} and hands them to
|
|
241
|
+
* {@link WeaverseNextStudioBridge}, so consuming apps get Studio navigation and
|
|
242
|
+
* revalidation without manually wiring `next/navigation`.
|
|
243
|
+
*
|
|
244
|
+
* Client-only — it is the single place `@weaverse/next` touches
|
|
245
|
+
* `next/navigation`, keeping the runtime/renderer and `@weaverse/next/server`
|
|
246
|
+
* free of router imports.
|
|
247
|
+
*/
|
|
248
|
+
declare function WeaverseNextStudio(props: WeaverseNextStudioProps): react_jsx_runtime.JSX.Element;
|
|
249
|
+
|
|
250
|
+
export { type CreateWeaverseNextStudioInternalsOptions, type CreateWeaverseNextThemeSettingsStoreOptions, type ResolveWeaverseNextStudioScriptSrcOptions, type RunComponentLoadersArgs, WeaverseNextClient, WeaverseNextClientConfig, WeaverseNextCommerceContext, 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, runWeaverseComponentLoaders, useThemeSettings, useWeaverseCommerce, useWeaverseNextStudioInternals, useWeaversePageData, useWeaverseRootData };
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ var react = require('@weaverse/react');
|
|
|
4
4
|
var schema = require('@weaverse/schema');
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
var react$1 = require('react');
|
|
7
|
+
var navigation = require('next/navigation');
|
|
7
8
|
|
|
8
9
|
// src/index.ts
|
|
9
10
|
|
|
@@ -327,8 +328,22 @@ function toQueryRecord(searchParams) {
|
|
|
327
328
|
}
|
|
328
329
|
return queries;
|
|
329
330
|
}
|
|
331
|
+
var TRANSIENT_STUDIO_PARAMS = /* @__PURE__ */ new Set([
|
|
332
|
+
"weaverseDraftItem",
|
|
333
|
+
// Legacy name from the original design-mode draft-item spike. Keep it out of
|
|
334
|
+
// runtime requestInfo too, in case an older Builder bundle is in front of a
|
|
335
|
+
// newer Next storefront.
|
|
336
|
+
"__weaverseDraftItem"
|
|
337
|
+
]);
|
|
338
|
+
function getRequestInfoSearchParams(context) {
|
|
339
|
+
let searchParams = new URLSearchParams(getSearchParamsFromContext(context));
|
|
340
|
+
for (let key of TRANSIENT_STUDIO_PARAMS) {
|
|
341
|
+
searchParams.delete(key);
|
|
342
|
+
}
|
|
343
|
+
return searchParams;
|
|
344
|
+
}
|
|
330
345
|
function buildWeaverseNextRequestInfo(context) {
|
|
331
|
-
let searchParams =
|
|
346
|
+
let searchParams = getRequestInfoSearchParams(context);
|
|
332
347
|
let search = searchParams.toString();
|
|
333
348
|
return {
|
|
334
349
|
pathname: getPathnameFromContext(context),
|
|
@@ -540,6 +555,53 @@ function WeaverseNextStudioBridge(props) {
|
|
|
540
555
|
}, [runtime, runtime.data, runtime.requestInfo]);
|
|
541
556
|
return null;
|
|
542
557
|
}
|
|
558
|
+
|
|
559
|
+
// src/studio-router.ts
|
|
560
|
+
function shouldResetScroll(options) {
|
|
561
|
+
if (!options || typeof options !== "object") {
|
|
562
|
+
return true;
|
|
563
|
+
}
|
|
564
|
+
return !options.preventScrollReset;
|
|
565
|
+
}
|
|
566
|
+
function createWeaverseNextStudioInternals(router, options = {}) {
|
|
567
|
+
return {
|
|
568
|
+
navigate: (to, navigateOptions) => {
|
|
569
|
+
let scroll = shouldResetScroll(navigateOptions);
|
|
570
|
+
if (options.replace) {
|
|
571
|
+
router.replace(to, { scroll });
|
|
572
|
+
} else {
|
|
573
|
+
router.push(to, { scroll });
|
|
574
|
+
}
|
|
575
|
+
},
|
|
576
|
+
revalidate: () => {
|
|
577
|
+
router.refresh();
|
|
578
|
+
}
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
function useWeaverseNextStudioInternals(options) {
|
|
582
|
+
let router = navigation.useRouter();
|
|
583
|
+
let ref = react$1.useRef(null);
|
|
584
|
+
if (!ref.current || ref.current.router !== router || ref.current.replace !== options?.replace) {
|
|
585
|
+
ref.current = {
|
|
586
|
+
internals: createWeaverseNextStudioInternals(router, options),
|
|
587
|
+
replace: options?.replace,
|
|
588
|
+
router
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
return ref.current.internals;
|
|
592
|
+
}
|
|
593
|
+
function WeaverseNextStudio(props) {
|
|
594
|
+
let { runtime, replace } = props;
|
|
595
|
+
let { navigate, revalidate } = useWeaverseNextStudioInternals({ replace });
|
|
596
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
597
|
+
WeaverseNextStudioBridge,
|
|
598
|
+
{
|
|
599
|
+
navigate,
|
|
600
|
+
revalidate,
|
|
601
|
+
runtime
|
|
602
|
+
}
|
|
603
|
+
);
|
|
604
|
+
}
|
|
543
605
|
var EMPTY_DATA_CONTEXT = {};
|
|
544
606
|
function getRenderablePage2(data) {
|
|
545
607
|
let page = data?.page;
|
|
@@ -571,7 +633,7 @@ var WeaverseNextRenderer = react$1.memo(function WeaverseNextRendererComponent(p
|
|
|
571
633
|
}
|
|
572
634
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
573
635
|
/* @__PURE__ */ jsxRuntime.jsx(react.WeaverseRoot, { context: weaverse }),
|
|
574
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
636
|
+
/* @__PURE__ */ jsxRuntime.jsx(WeaverseNextStudio, { runtime: weaverse })
|
|
575
637
|
] });
|
|
576
638
|
});
|
|
577
639
|
|
|
@@ -715,17 +777,20 @@ Object.defineProperty(exports, "createSchema", {
|
|
|
715
777
|
exports.WeaverseNextProvider = WeaverseNextProvider;
|
|
716
778
|
exports.WeaverseNextRenderer = WeaverseNextRenderer;
|
|
717
779
|
exports.WeaverseNextRuntime = WeaverseNextRuntime;
|
|
780
|
+
exports.WeaverseNextStudio = WeaverseNextStudio;
|
|
718
781
|
exports.WeaverseNextStudioBridge = WeaverseNextStudioBridge;
|
|
719
782
|
exports.WeaverseNextStudioConnect = WeaverseNextStudioConnect;
|
|
720
783
|
exports.bindWeaverseNextStudioRuntime = bindWeaverseNextStudioRuntime;
|
|
721
784
|
exports.buildWeaverseNextRequestInfo = buildWeaverseNextRequestInfo;
|
|
722
785
|
exports.createWeaverseNextClient = createWeaverseNextClient;
|
|
723
786
|
exports.createWeaverseNextRuntime = createWeaverseNextRuntime;
|
|
787
|
+
exports.createWeaverseNextStudioInternals = createWeaverseNextStudioInternals;
|
|
724
788
|
exports.createWeaverseNextThemeSettingsStore = createWeaverseNextThemeSettingsStore;
|
|
725
789
|
exports.resolveWeaverseNextStudioScriptSrc = resolveWeaverseNextStudioScriptSrc;
|
|
726
790
|
exports.runWeaverseComponentLoaders = runWeaverseComponentLoaders;
|
|
727
791
|
exports.useThemeSettings = useThemeSettings;
|
|
728
792
|
exports.useWeaverseCommerce = useWeaverseCommerce;
|
|
793
|
+
exports.useWeaverseNextStudioInternals = useWeaverseNextStudioInternals;
|
|
729
794
|
exports.useWeaversePageData = useWeaversePageData;
|
|
730
795
|
exports.useWeaverseRootData = useWeaverseRootData;
|
|
731
796
|
//# sourceMappingURL=index.js.map
|