@weaverse/next 0.1.0-alpha.9 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/README.md +161 -73
  2. package/dist/{chunk-6PMZ77RA.mjs → chunk-OSC5HR5V.mjs} +117 -8
  3. package/dist/chunk-OSC5HR5V.mjs.map +1 -0
  4. package/dist/client-boundary.js +1425 -0
  5. package/dist/client-boundary.js.map +1 -0
  6. package/dist/client-boundary.mjs +1395 -0
  7. package/dist/client-boundary.mjs.map +1 -0
  8. package/dist/index.js +292 -1003
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.mjs +90 -966
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/server.js +321 -91
  13. package/dist/server.js.map +1 -1
  14. package/dist/server.mjs +205 -28
  15. package/dist/server.mjs.map +1 -1
  16. package/dist/types/client-boundary.d.ts +25 -0
  17. package/dist/types/client-boundary.d.ts.map +1 -0
  18. package/dist/types/client.d.ts +16 -0
  19. package/dist/types/client.d.ts.map +1 -0
  20. package/dist/types/hooks.d.ts +20 -0
  21. package/dist/types/hooks.d.ts.map +1 -0
  22. package/dist/types/index.d.ts +33 -0
  23. package/dist/types/index.d.ts.map +1 -0
  24. package/dist/types/item.d.ts +60 -0
  25. package/dist/types/item.d.ts.map +1 -0
  26. package/dist/types/loader.d.ts +25 -0
  27. package/dist/types/loader.d.ts.map +1 -0
  28. package/dist/types/main.d.ts +11 -0
  29. package/dist/types/main.d.ts.map +1 -0
  30. package/dist/types/provider.d.ts +82 -0
  31. package/dist/types/provider.d.ts.map +1 -0
  32. package/dist/types/registry.d.ts +15 -0
  33. package/dist/types/registry.d.ts.map +1 -0
  34. package/dist/types/renderer.d.ts +21 -0
  35. package/dist/types/renderer.d.ts.map +1 -0
  36. package/dist/types/request-info.d.ts +19 -0
  37. package/dist/types/request-info.d.ts.map +1 -0
  38. package/dist/types/revalidate-item.d.ts +82 -0
  39. package/dist/types/revalidate-item.d.ts.map +1 -0
  40. package/dist/types/root-provider.d.ts +62 -0
  41. package/dist/types/root-provider.d.ts.map +1 -0
  42. package/dist/types/runtime.d.ts +113 -0
  43. package/dist/types/runtime.d.ts.map +1 -0
  44. package/dist/types/seo.d.ts +55 -0
  45. package/dist/types/seo.d.ts.map +1 -0
  46. package/dist/types/server/configs.d.ts +27 -0
  47. package/dist/types/server/configs.d.ts.map +1 -0
  48. package/dist/types/server/normalize-page-url.d.ts +19 -0
  49. package/dist/types/server/normalize-page-url.d.ts.map +1 -0
  50. package/dist/types/server/revalidate-handler.d.ts +55 -0
  51. package/dist/types/server/revalidate-handler.d.ts.map +1 -0
  52. package/dist/types/server/server-client.d.ts +21 -0
  53. package/dist/types/server/server-client.d.ts.map +1 -0
  54. package/dist/types/server.d.ts +19 -0
  55. package/dist/types/server.d.ts.map +1 -0
  56. package/dist/types/studio-bridge.d.ts +16 -0
  57. package/dist/types/studio-bridge.d.ts.map +1 -0
  58. package/dist/types/studio-connect.d.ts +27 -0
  59. package/dist/types/studio-connect.d.ts.map +1 -0
  60. package/dist/types/studio-router.d.ts +50 -0
  61. package/dist/types/studio-router.d.ts.map +1 -0
  62. package/dist/types/studio-script-src.d.ts +12 -0
  63. package/dist/types/studio-script-src.d.ts.map +1 -0
  64. package/dist/types/theme-settings-store.d.ts +18 -0
  65. package/dist/types/theme-settings-store.d.ts.map +1 -0
  66. package/dist/types/translate.d.ts +56 -0
  67. package/dist/types/translate.d.ts.map +1 -0
  68. package/dist/types/translation-context.d.ts +109 -0
  69. package/dist/types/translation-context.d.ts.map +1 -0
  70. package/dist/types/translation-store.d.ts +44 -0
  71. package/dist/types/translation-store.d.ts.map +1 -0
  72. package/dist/types/types.d.ts +665 -0
  73. package/dist/types/types.d.ts.map +1 -0
  74. package/dist/types/use-weaverse-next-studio.d.ts +34 -0
  75. package/dist/types/use-weaverse-next-studio.d.ts.map +1 -0
  76. package/dist/types/utils.d.ts +22 -0
  77. package/dist/types/utils.d.ts.map +1 -0
  78. package/package.json +12 -27
  79. package/src/client-boundary.ts +50 -0
  80. package/src/client.ts +102 -0
  81. package/src/hooks.ts +50 -0
  82. package/src/index.ts +143 -0
  83. package/src/item.ts +167 -0
  84. package/src/loader.ts +135 -0
  85. package/src/main.tsx +45 -0
  86. package/src/provider.tsx +223 -0
  87. package/src/registry.ts +63 -0
  88. package/src/renderer.tsx +100 -0
  89. package/src/request-info.ts +124 -0
  90. package/src/revalidate-item.ts +211 -0
  91. package/src/root-provider.tsx +180 -0
  92. package/src/runtime.ts +555 -0
  93. package/src/seo.ts +157 -0
  94. package/src/server/configs.ts +178 -0
  95. package/src/server/normalize-page-url.ts +73 -0
  96. package/src/server/revalidate-handler.ts +357 -0
  97. package/src/server/server-client.ts +728 -0
  98. package/src/server.ts +67 -0
  99. package/src/studio-bridge.tsx +82 -0
  100. package/src/studio-connect.tsx +88 -0
  101. package/src/studio-router.ts +85 -0
  102. package/src/studio-script-src.ts +128 -0
  103. package/src/theme-settings-store.ts +47 -0
  104. package/src/translate.ts +125 -0
  105. package/src/translation-context.tsx +182 -0
  106. package/src/translation-store.ts +69 -0
  107. package/src/types.ts +753 -0
  108. package/src/use-weaverse-next-studio.tsx +106 -0
  109. package/src/utils.ts +49 -0
  110. package/dist/chunk-6PMZ77RA.mjs.map +0 -1
  111. package/dist/index.d.mts +0 -580
  112. package/dist/index.d.ts +0 -580
  113. package/dist/seo-Dos9t22_.d.mts +0 -477
  114. package/dist/seo-Dos9t22_.d.ts +0 -477
  115. package/dist/server.d.mts +0 -99
  116. package/dist/server.d.ts +0 -99
package/dist/index.mjs CHANGED
@@ -1,189 +1,97 @@
1
- import { buildWeaverseNextRequestInfo, generateDataFromSchema } from './chunk-6PMZ77RA.mjs';
2
- export { buildWeaverseNextRequestInfo, formatWeaverseNextSeoMetadata, getWeaverseNextSeoMetadata, runWeaverseComponentLoaders } from './chunk-6PMZ77RA.mjs';
3
- import { WeaverseRoot, Weaverse, WeaverseItemStore, useSafeExternalStore } from '@weaverse/react';
4
- export { isBrowser, isIframe, useChildInstances, useItemInstance, useParentInstance, useWeaverse } from '@weaverse/react';
5
- import { createSchema } from '@weaverse/schema';
6
- export { createSchema } from '@weaverse/schema';
7
- import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
8
- import { createContext, memo, useContext, useMemo, useEffect, useLayoutEffect, useRef, useSyncExternalStore } from 'react';
9
- import { useRouter } from 'next/navigation';
1
+ export { DEFAULT_REVALIDATE_ENDPOINT, buildWeaverseNextRequestInfo, buildWeaverseNextRevalidateRouteContext, formatWeaverseNextSeoMetadata, generateDataFromSchema, getWeaverseNextSeoMetadata, isBrowser, isIframe, revalidateWeaverseNextItem, runWeaverseComponentLoaders } from './chunk-OSC5HR5V.mjs';
2
+ export * from '@weaverse/schema';
3
+ export { ThemeTextProvider, TranslationProvider, WeaverseNextProvider, WeaverseNextRenderer, WeaverseNextRootProvider, WeaverseNextRuntime, WeaverseNextStudio, WeaverseNextStudioBridge, WeaverseNextStudioConnect, bindWeaverseNextStudioRuntime, createWeaverseNextClient, createWeaverseNextRuntime, loadWeaverseNextStudioScript, useChildInstances, useItemInstance, useParentInstance, useThemeSettings, useThemeText, useTranslation, useWeaverse, useWeaverseCommerce, useWeaverseNextStudioInternals, useWeaversePageData, useWeaverseRootData } from './client-boundary.mjs';
10
4
 
11
- function flattenItemData(update) {
12
- let { data, ...rest } = update;
13
- if (!(data && typeof data === "object" && !Array.isArray(data))) {
14
- return rest;
15
- }
16
- return { ...data, ...rest };
17
- }
18
- var deferredItemUpdates = null;
19
- function collectDeferredItemUpdates(create) {
20
- let previousQueue = deferredItemUpdates;
21
- let queue = /* @__PURE__ */ new Set();
22
- deferredItemUpdates = queue;
23
- try {
24
- return [create(), [...queue]];
25
- } finally {
26
- deferredItemUpdates = previousQueue;
5
+ // src/studio-router.ts
6
+ function shouldResetScroll(options) {
7
+ if (!options || typeof options !== "object") {
8
+ return true;
27
9
  }
10
+ return !options.preventScrollReset;
28
11
  }
29
- var WeaverseNextItem = class extends WeaverseItemStore {
30
- /**
31
- * Cached merged snapshot (base `_store` + translations). Reset whenever the
32
- * `_store` ref or the item's translation entry ref changes, so
33
- * `useSyncExternalStore` sees a stable object between unrelated re-renders.
34
- */
35
- _cachedSnapshot = null;
36
- _snapshotStoreRef = null;
37
- _snapshotTranslationRef = null;
38
- constructor(initialData, weaverse) {
39
- super(initialData, weaverse);
40
- let schemaData = generateDataFromSchema(this.Element?.schema);
41
- Object.assign(this._store, schemaData, flattenItemData(initialData));
42
- }
43
- /**
44
- * Flatten nested `data` on updates exactly like the constructor does. Core's
45
- * `initProject()` calls `setData(item)` when a new runtime serves a page
46
- * whose item instances already exist (e.g. locale/client navigation), and
47
- * the inherited shallow merge would leave stale top-level props behind.
48
- * Assigning through the inherited `data` setter swaps the `_store` ref,
49
- * which invalidates the memoized snapshot below. The subscriber emit is
50
- * queued instead of fired when a render-phase deferral is active (see
51
- * `collectDeferredItemUpdates`).
52
- */
53
- setData = (update) => {
54
- this.data = flattenItemData(update);
55
- if (deferredItemUpdates) {
56
- deferredItemUpdates.add(this);
57
- } else {
58
- this.triggerUpdate();
59
- }
60
- return this.data;
61
- };
62
- /**
63
- * Overlay item-level translations onto the base store when the runtime is in
64
- * translation mode. Mirrors Hydrogen's `WeaverseHydrogenItem.getSnapShot()`:
65
- * memoized by `_store` ref + translation entry ref so the returned object is
66
- * referentially stable, and a fast path that returns the base store untouched
67
- * when the item has no translations.
68
- */
69
- getSnapShot = () => {
70
- let base = this._store;
71
- let translations = this.weaverse.translationMap[this._id];
72
- if (!translations) {
73
- return base;
74
- }
75
- if (this._cachedSnapshot && this._snapshotStoreRef === base && this._snapshotTranslationRef === translations) {
76
- return this._cachedSnapshot;
77
- }
78
- let merged = { ...base };
79
- for (let [key, entry] of Object.entries(translations)) {
80
- if (entry.translatedValue !== void 0) {
81
- merged[key] = entry.translatedValue;
12
+ function createWeaverseNextStudioInternals(router, options = {}) {
13
+ return {
14
+ navigate: (to, navigateOptions) => {
15
+ let scroll = shouldResetScroll(navigateOptions);
16
+ if (options.replace) {
17
+ router.replace(to, { scroll });
18
+ } else {
19
+ router.push(to, { scroll });
82
20
  }
21
+ },
22
+ revalidate: () => {
23
+ router.refresh();
83
24
  }
84
- this._cachedSnapshot = merged;
85
- this._snapshotStoreRef = base;
86
- this._snapshotTranslationRef = translations;
87
- return merged;
88
25
  };
89
- };
90
- function ensureNextItemConstructor() {
91
- if (!Weaverse.ItemConstructor || Weaverse.ItemConstructor === WeaverseItemStore || Weaverse.ItemConstructor === WeaverseNextItem) {
92
- Weaverse.ItemConstructor = WeaverseNextItem;
93
- }
94
- }
95
- function Main(props) {
96
- let { children, loaderData, ...rest } = props;
97
- return /* @__PURE__ */ jsx("div", { ...rest, children });
98
26
  }
99
- Main.displayName = "main";
100
- var mainSchema = createSchema({
101
- type: "main",
102
- title: "Main"
103
- });
104
- var defaultMainComponent = {
105
- default: Main,
106
- schema: mainSchema
107
- };
108
27
 
109
- // src/registry.ts
110
- var MAIN_TYPE = "main";
111
- var registeredComponentTypes = /* @__PURE__ */ new Set();
112
- function registerWeaverseNextComponents(components) {
113
- ensureNextItemConstructor();
114
- let hasUserMain = components.some(
115
- (component) => component.schema?.type === MAIN_TYPE
28
+ // src/studio-script-src.ts
29
+ var TRUSTED_STUDIO_DOMAINS = ["weaverse.io", "weaverse.dev"];
30
+ function isLoopbackHostname(hostname) {
31
+ return hostname === "localhost" || hostname === "127.0.0.1" || hostname.endsWith(".localhost");
32
+ }
33
+ function normalizeOrigin(value) {
34
+ if (!value) {
35
+ return null;
36
+ }
37
+ try {
38
+ return new URL(value).origin;
39
+ } catch {
40
+ return null;
41
+ }
42
+ }
43
+ function isTrustedStudioOrigin(origin, storefrontHostname) {
44
+ let parsed;
45
+ try {
46
+ parsed = new URL(origin);
47
+ } catch {
48
+ return false;
49
+ }
50
+ let { hostname, protocol } = parsed;
51
+ if (isLoopbackHostname(storefrontHostname) && isLoopbackHostname(hostname)) {
52
+ return protocol === "http:" || protocol === "https:";
53
+ }
54
+ if (protocol !== "https:") {
55
+ return false;
56
+ }
57
+ return TRUSTED_STUDIO_DOMAINS.some(
58
+ (domain) => hostname === domain || hostname.endsWith(`.${domain}`)
116
59
  );
117
- let effectiveComponents = hasUserMain ? components : [defaultMainComponent, ...components];
118
- for (let component of effectiveComponents) {
119
- let type = component.schema.type;
120
- let element = {
121
- type,
122
- Component: component.default,
123
- schema: component.schema,
124
- loader: component.loader
125
- };
126
- if (type === MAIN_TYPE && hasUserMain) {
127
- Weaverse.elementRegistry.set(type, element);
128
- registeredComponentTypes.add(type);
129
- continue;
130
- }
131
- if (type && !registeredComponentTypes.has(type)) {
132
- Weaverse.registerElement(element);
133
- registeredComponentTypes.add(type);
134
- }
60
+ }
61
+ function toSearchParams(context) {
62
+ if (context?.searchParams) {
63
+ return new URLSearchParams(context.searchParams);
135
64
  }
65
+ if (context?.url) {
66
+ let url = typeof context.url === "string" ? new URL(context.url, "http://localhost") : context.url;
67
+ return new URLSearchParams(url.searchParams);
68
+ }
69
+ return new URLSearchParams();
136
70
  }
137
-
138
- // src/client.ts
139
- var NextClient = class {
140
- projectId;
141
- components;
142
- themeSchema;
143
- themeSettings;
144
- requestContext;
145
- commerce;
146
- data = null;
147
- dataContext = {};
148
- _fetchPage;
149
- _fetchThemeSettings;
150
- constructor(config) {
151
- this.projectId = config.projectId;
152
- this.components = config.components;
153
- registerWeaverseNextComponents(this.components);
154
- this.themeSchema = config.themeSchema;
155
- this.themeSettings = {
156
- ...generateDataFromSchema(config.themeSchema),
157
- ...config.themeSettings
158
- };
159
- this.requestContext = config.requestContext;
160
- this.commerce = config.commerce;
161
- this._fetchPage = config.fetchPage;
162
- this._fetchThemeSettings = config.fetchThemeSettings;
71
+ function last(searchParams, key) {
72
+ let values = searchParams.getAll(key);
73
+ return values.length ? values.at(-1) ?? null : null;
74
+ }
75
+ function resolveWeaverseNextStudioScriptSrc(context, options = {}) {
76
+ let searchParams = toSearchParams(context);
77
+ let isDesignMode = context?.isDesignMode ?? last(searchParams, "isDesignMode") === "true";
78
+ let isPreviewMode = context?.isPreviewMode ?? last(searchParams, "isPreviewMode") === "true";
79
+ let isRevisionPreview = context?.isRevisionPreview ?? Boolean(last(searchParams, "__revisionId"));
80
+ if (!(isDesignMode || isPreviewMode || isRevisionPreview)) {
81
+ return null;
163
82
  }
164
- /** Compatibility alias so loaders can call `weaverse.storefront.query(...)`. */
165
- get storefront() {
166
- return this.commerce?.storefront;
83
+ let origin = normalizeOrigin(last(searchParams, "weaverseHost"));
84
+ if (!origin) {
85
+ return null;
167
86
  }
168
- loadPage = (input = {}) => {
169
- if (!this._fetchPage) {
170
- throw new Error(
171
- "[WeaverseNextClient] loadPage requires a `fetchPage` function in client config."
172
- );
173
- }
174
- return this._fetchPage(input);
175
- };
176
- loadThemeSettings = (context) => {
177
- if (!this._fetchThemeSettings) {
178
- throw new Error(
179
- "[WeaverseNextClient] loadThemeSettings requires a `fetchThemeSettings` function in client config."
180
- );
181
- }
182
- return this._fetchThemeSettings(context ?? this.requestContext);
183
- };
184
- };
185
- function createWeaverseNextClient(config) {
186
- return new NextClient(config);
87
+ let storefrontHostname = options.storefrontHostname ?? "";
88
+ if (!isTrustedStudioOrigin(origin, storefrontHostname)) {
89
+ return null;
90
+ }
91
+ let bundle = isPreviewMode || isRevisionPreview ? "preview.js" : "index.js";
92
+ let version = last(searchParams, "weaverseVersion");
93
+ let url = `${origin}/static/studio/next/${bundle}`;
94
+ return version ? `${url}?v=${encodeURIComponent(version)}` : url;
187
95
  }
188
96
 
189
97
  // src/theme-settings-store.ts
@@ -210,6 +118,8 @@ function createWeaverseNextThemeSettingsStore(options = {}) {
210
118
  };
211
119
  return store;
212
120
  }
121
+
122
+ // src/translate.ts
213
123
  function getNestedKey(obj, path, fallback) {
214
124
  let keys = path.split(".");
215
125
  let current = obj;
@@ -233,8 +143,6 @@ function interpolate(template, variables) {
233
143
  return value === void 0 ? match : String(value);
234
144
  });
235
145
  }
236
- var TranslationContext = createContext(null);
237
- TranslationContext.displayName = "WeaverseNextTranslationContext";
238
146
  function createTranslate(sources) {
239
147
  let { staticContent, merchantOverrides, designOverrides, externalT } = sources;
240
148
  return (key, variables) => {
@@ -251,67 +159,27 @@ function createTranslate(sources) {
251
159
  return interpolate(raw, variables);
252
160
  };
253
161
  }
254
- var EMPTY = {};
255
- var NOOP_SUBSCRIBE = () => () => {
256
- };
257
- var NOOP_SNAPSHOT = () => EMPTY;
258
- function TranslationProvider({
259
- staticContent,
260
- merchantOverrides,
261
- t: externalT,
262
- translationStore,
263
- themeTextStore,
264
- children
265
- }) {
266
- let store = translationStore ?? themeTextStore ?? null;
267
- let designOverrides = useSafeExternalStore(
268
- store?.subscribe ?? NOOP_SUBSCRIBE,
269
- store?.getSnapshot ?? NOOP_SNAPSHOT,
270
- store?.getServerSnapshot ?? NOOP_SNAPSHOT
271
- );
272
- let value = useMemo(
273
- () => ({
274
- t: createTranslate({
275
- staticContent,
276
- merchantOverrides,
277
- designOverrides,
278
- externalT
279
- }),
280
- translationStore: store,
281
- // Deprecated alias — same instance, kept for backward compatibility.
282
- themeTextStore: store,
283
- merchantOverrides: merchantOverrides ?? null
284
- }),
285
- [staticContent, merchantOverrides, designOverrides, externalT, store]
286
- );
287
- return /* @__PURE__ */ jsx(TranslationContext.Provider, { value, children });
288
- }
289
- function useTranslation() {
290
- let ctx = useContext(TranslationContext);
291
- if (!ctx) {
292
- throw new Error(
293
- "useTranslation must be used within <TranslationProvider>. Wrap your app with <WeaverseNextRootProvider>."
294
- );
295
- }
296
- return ctx;
297
- }
298
- var ThemeTextProvider = TranslationProvider;
299
- var useThemeText = useTranslation;
300
162
 
301
163
  // src/translation-store.ts
302
164
  var TranslationStore = class {
165
+ /** Current flat translation overrides keyed by dot path. */
303
166
  overrides = {};
304
167
  listeners = /* @__PURE__ */ new Set();
168
+ /** Replace every override and notify subscribers. */
305
169
  setOverrides = (overrides) => {
306
170
  this.overrides = { ...overrides };
307
171
  this.emit();
308
172
  };
173
+ /** Merge changed overrides into the current values and notify subscribers. */
309
174
  updateOverrides = (newOverrides) => {
310
175
  this.overrides = { ...this.overrides, ...newOverrides };
311
176
  this.emit();
312
177
  };
178
+ /** Return the current client-side override snapshot. */
313
179
  getSnapshot = () => this.overrides;
180
+ /** Return the override snapshot used during server rendering. */
314
181
  getServerSnapshot = () => this.overrides;
182
+ /** Subscribe to override changes and return an unsubscribe function. */
315
183
  subscribe = (callback) => {
316
184
  this.listeners.add(callback);
317
185
  return () => {
@@ -329,751 +197,7 @@ var TranslationStore = class {
329
197
  };
330
198
  };
331
199
  var ThemeTextStore = TranslationStore;
332
- var WeaverseNextRootContext = createContext(null);
333
- function WeaverseNextRootProvider(props) {
334
- let {
335
- children,
336
- initialThemeSettings,
337
- merchantOverrides,
338
- staticContent,
339
- t,
340
- themeSchema,
341
- publicEnv
342
- } = props;
343
- let storeRef = useRef(null);
344
- if (!storeRef.current) {
345
- storeRef.current = createWeaverseNextThemeSettingsStore({
346
- publicEnv,
347
- schema: themeSchema,
348
- settings: initialThemeSettings
349
- });
350
- }
351
- let themeSettingsStore = storeRef.current;
352
- let translationStoreRef = useRef(null);
353
- if (!translationStoreRef.current) {
354
- translationStoreRef.current = new TranslationStore();
355
- }
356
- let translationStore = translationStoreRef.current;
357
- let appliedThemeSettingsRef = useRef(initialThemeSettings);
358
- useEffect(() => {
359
- if (initialThemeSettings && appliedThemeSettingsRef.current !== initialThemeSettings) {
360
- themeSettingsStore.updateThemeSettings(initialThemeSettings);
361
- appliedThemeSettingsRef.current = initialThemeSettings;
362
- }
363
- }, [initialThemeSettings, themeSettingsStore]);
364
- let resolvedStaticContent = staticContent ?? getSchemaStaticContent(themeSchema);
365
- let rootContextValue = useMemo(
366
- () => ({
367
- merchantOverrides,
368
- staticContent: resolvedStaticContent,
369
- themeSettingsStore,
370
- translationStore
371
- }),
372
- [
373
- merchantOverrides,
374
- resolvedStaticContent,
375
- themeSettingsStore,
376
- translationStore
377
- ]
378
- );
379
- let contextValue = useMemo(
380
- () => ({
381
- merchantOverrides,
382
- themeSettings: themeSettingsStore.getSnapshot(),
383
- themeSettingsStore,
384
- translationStore
385
- }),
386
- [merchantOverrides, themeSettingsStore, translationStore]
387
- );
388
- return /* @__PURE__ */ jsx(WeaverseNextRootContext.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsx(WeaverseNextContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
389
- TranslationProvider,
390
- {
391
- merchantOverrides,
392
- staticContent: resolvedStaticContent,
393
- t,
394
- translationStore,
395
- children
396
- }
397
- ) }) });
398
- }
399
- var EMPTY_THEME_SETTINGS = {};
400
- var EMPTY_STATIC_CONTENT = {};
401
- function getSchemaStaticContent(schema) {
402
- let i18n = schema?.i18n;
403
- return i18n?.staticContent ?? EMPTY_STATIC_CONTENT;
404
- }
405
- var WeaverseNextContext = createContext(null);
406
- function WeaverseNextProvider(props) {
407
- let { children, client, rootData, pageData, commerce, themeSettings } = props;
408
- let rootContext = useContext(WeaverseNextRootContext);
409
- let themeSettingsValue = themeSettings ?? client?.themeSettings ?? EMPTY_THEME_SETTINGS;
410
- let ownTranslationStoreRef = useRef(null);
411
- if (!(rootContext || ownTranslationStoreRef.current)) {
412
- ownTranslationStoreRef.current = new TranslationStore();
413
- }
414
- let translationStore = rootContext?.translationStore ?? ownTranslationStoreRef.current;
415
- let staticContent = props.staticContent ?? rootContext?.staticContent ?? getSchemaStaticContent(client?.themeSchema);
416
- let merchantOverrides = props.merchantOverrides ?? rootContext?.merchantOverrides;
417
- let ownThemeSettingsStore = useMemo(() => {
418
- if (rootContext) {
419
- return null;
420
- }
421
- return createWeaverseNextThemeSettingsStore({
422
- schema: client?.themeSchema,
423
- settings: themeSettingsValue
424
- });
425
- }, [rootContext, client?.themeSchema, themeSettingsValue]);
426
- let themeSettingsStore = rootContext?.themeSettingsStore ?? ownThemeSettingsStore;
427
- let mergedIntoRootRef = useRef(void 0);
428
- useEffect(() => {
429
- if (rootContext && themeSettingsValue !== EMPTY_THEME_SETTINGS && mergedIntoRootRef.current !== themeSettingsValue) {
430
- rootContext.themeSettingsStore.updateThemeSettings(themeSettingsValue);
431
- mergedIntoRootRef.current = themeSettingsValue;
432
- }
433
- }, [rootContext, themeSettingsValue]);
434
- let value = useMemo(
435
- () => ({
436
- client,
437
- rootData,
438
- pageData,
439
- commerce: commerce ?? client?.commerce,
440
- merchantOverrides,
441
- themeSettings: themeSettingsStore.getSnapshot(),
442
- themeSettingsStore,
443
- translationStore
444
- }),
445
- [
446
- client,
447
- rootData,
448
- pageData,
449
- commerce,
450
- merchantOverrides,
451
- themeSettingsStore,
452
- translationStore
453
- ]
454
- );
455
- return /* @__PURE__ */ jsx(WeaverseNextContext.Provider, { value, children: /* @__PURE__ */ jsx(
456
- TranslationProvider,
457
- {
458
- merchantOverrides,
459
- staticContent,
460
- t: props.t,
461
- translationStore,
462
- children
463
- }
464
- ) });
465
- }
466
-
467
- // src/hooks.ts
468
- var OUTSIDE_PROVIDER_ERROR = "must be used inside a <WeaverseNextProvider>.";
469
- function useWeaverseNextContext(hookName) {
470
- let context = useContext(WeaverseNextContext);
471
- if (!context) {
472
- throw new Error(`[@weaverse/next] ${hookName} ${OUTSIDE_PROVIDER_ERROR}`);
473
- }
474
- return context;
475
- }
476
- function useWeaverseRootData() {
477
- return useWeaverseNextContext("useWeaverseRootData").rootData;
478
- }
479
- function useWeaversePageData() {
480
- return useWeaverseNextContext("useWeaversePageData").pageData;
481
- }
482
- function useWeaverseCommerce() {
483
- return useWeaverseNextContext("useWeaverseCommerce").commerce;
484
- }
485
- function useThemeSettings() {
486
- let { themeSettingsStore } = useWeaverseNextContext("useThemeSettings");
487
- return useSyncExternalStore(
488
- themeSettingsStore.subscribe,
489
- themeSettingsStore.getSnapshot,
490
- themeSettingsStore.getServerSnapshot
491
- );
492
- }
493
- function getRuntimeWindow() {
494
- return typeof window === "undefined" ? void 0 : window;
495
- }
496
- function getRenderablePage(data) {
497
- let page = data.page;
498
- let rootId = page.rootId ?? page.items.find((item) => item.type === "main")?.id ?? page.items[0]?.id ?? page.id;
499
- return { ...page, rootId };
500
- }
501
- function getConfigString(configs, key) {
502
- let value = configs?.[key];
503
- return typeof value === "string" ? value : void 0;
504
- }
505
- function getRecordString(record, key) {
506
- let value = record?.[key];
507
- return typeof value === "string" ? value : void 0;
508
- }
509
- function resolveProjectId(client, data, fallback) {
510
- let projectId = client?.projectId;
511
- if (projectId) {
512
- return projectId;
513
- }
514
- let configProjectId = getConfigString(data.configs, "projectId");
515
- if (configProjectId) {
516
- return configProjectId;
517
- }
518
- return getRecordString(data.project, "id") ?? fallback;
519
- }
520
- function resolveDataContext(config) {
521
- if (config.dataContext) {
522
- return config.dataContext;
523
- }
524
- if (config.client?.dataContext) {
525
- return config.client.dataContext;
526
- }
527
- return {};
528
- }
529
- function getRuntimeKey(pageId, requestInfo) {
530
- return `${pageId}:${requestInfo.pathname}:${requestInfo.search}`;
531
- }
532
- function registerRuntime(runtime) {
533
- let runtimeWindow = getRuntimeWindow();
534
- if (!runtimeWindow) {
535
- return;
536
- }
537
- runtimeWindow.__weaverses ??= {};
538
- runtimeWindow.__weaverses[runtime.pageId] = runtime;
539
- runtimeWindow.__weaverse = runtime;
540
- }
541
- var WeaverseNextRuntime = class extends Weaverse {
542
- pageId;
543
- internal;
544
- requestInfo;
545
- isPreviewMode;
546
- isRevisionPreview;
547
- sectionType;
548
- // ─── Item-level translation sidecar (design mode only) ─────────────
549
- /**
550
- * Translation map received from Builder in design mode, keyed by item ID.
551
- * `WeaverseNextItem.getSnapShot()` overlays these onto the data handed to
552
- * components, so translations render without mutating the base `_store`.
553
- */
554
- translationMap = {};
555
- translationLocale = String();
556
- translationLanguageId = String();
557
- /**
558
- * Fresh page data captured while React was rendering. Runtime reuse happens
559
- * inside the renderer's render phase (`useMemo`), where applying it through
560
- * `setProjectData()` would emit item updates to `useSyncExternalStore`
561
- * subscribers mid-render. The renderer applies it post-commit via
562
- * `flushRenderPhaseUpdates()`. Never set on design-mode runtimes — the live
563
- * Studio tree owns the page data there.
564
- */
565
- pendingProjectData;
566
- /**
567
- * Reused item instances whose data was refreshed while this runtime was
568
- * constructed during render (core `initProject()` calls `setData()` on
569
- * them). Their data is already fresh; only the subscriber notification was
570
- * deferred to `flushRenderPhaseUpdates()`.
571
- */
572
- pendingItemUpdates = [];
573
- constructor(config) {
574
- let { client, data } = config;
575
- let page = getRenderablePage(data);
576
- let configs = data.configs;
577
- let requestContext = client?.requestContext;
578
- let projectId = resolveProjectId(client, data, page.id);
579
- ensureNextItemConstructor();
580
- super({
581
- projectId,
582
- data: page,
583
- isDesignMode: requestContext?.isDesignMode ?? false,
584
- weaverseHost: getConfigString(configs, "weaverseHost"),
585
- weaverseVersion: getConfigString(configs, "weaverseVersion")
586
- });
587
- this.pageId = page.id;
588
- this.dataContext = resolveDataContext(config);
589
- this.requestInfo = buildWeaverseNextRequestInfo(requestContext);
590
- this.isDesignMode = requestContext?.isDesignMode ?? false;
591
- this.isPreviewMode = requestContext?.isPreviewMode ?? false;
592
- this.isRevisionPreview = requestContext?.isRevisionPreview ?? false;
593
- this.sectionType = requestContext?.sectionType;
594
- let translationStore = config.translationStore ?? new TranslationStore();
595
- this.internal = {
596
- merchantOverrides: config.merchantOverrides,
597
- navigate: config.navigate,
598
- pageAssignment: data.pageAssignment,
599
- project: data.project,
600
- revalidate: config.revalidate,
601
- themeSettingsStore: config.themeSettingsStore ?? createWeaverseNextThemeSettingsStore({
602
- schema: client?.themeSchema,
603
- settings: client?.themeSettings
604
- }),
605
- translationStore,
606
- themeTextStore: translationStore
607
- };
608
- this.extractTranslationSidecar();
609
- }
610
- /**
611
- * Pull `translationMap` / `translationLocale` / `translationLanguageId` off
612
- * the current page data (Builder attaches them in design mode). Unlike
613
- * Hydrogen, this also clears the sidecar to defaults when the new page data
614
- * carries none, so a reused runtime / project-data swap can't leave a stale
615
- * map overlaying the fresh tree.
616
- */
617
- extractTranslationSidecar = () => {
618
- let pageData = this.data;
619
- let translationMap = pageData?.translationMap;
620
- if (translationMap) {
621
- this.translationMap = translationMap;
622
- this.translationLocale = pageData?.translationLocale || "";
623
- this.translationLanguageId = pageData?.translationLanguageId || "";
624
- } else {
625
- this.translationMap = {};
626
- this.translationLocale = "";
627
- this.translationLanguageId = "";
628
- }
629
- };
630
- /**
631
- * Replace the translation sidecar (Builder pushes this when translation data
632
- * arrives or the active language changes) and refresh every item so their
633
- * merged snapshots recompute.
634
- */
635
- setTranslationSidecar = (map = {}, locale = "", languageId = "") => {
636
- this.translationMap = map;
637
- this.translationLocale = locale;
638
- this.translationLanguageId = languageId;
639
- this.refreshAllItems();
640
- };
641
- /**
642
- * Update a single translatable field for one item. Assigns a new per-item
643
- * entry object so `WeaverseNextItem.getSnapShot()`'s translation-ref cache
644
- * invalidates, then triggers only that item's subscribers.
645
- */
646
- updateTranslation = (itemId, key, originalValue, translatedValue) => {
647
- if (!this.translationMap[itemId]) {
648
- this.translationMap[itemId] = {};
649
- }
650
- this.translationMap[itemId] = {
651
- ...this.translationMap[itemId],
652
- [key]: { originalValue, translatedValue }
653
- };
654
- let instance = this.itemInstances.get(itemId);
655
- if (instance) {
656
- instance.triggerUpdate();
657
- }
658
- };
659
- /**
660
- * Collect translation changes for the save flow. Returns `undefined` unless
661
- * both the locale and language ID are set and at least one entry exists;
662
- * each entry key is namespaced as `data.<field>` to match Builder.
663
- */
664
- getTranslationChanges = () => {
665
- let languageId = this.translationLanguageId;
666
- if (!(this.translationLocale && languageId)) {
667
- return;
668
- }
669
- let entries = [];
670
- for (let [itemId, fields] of Object.entries(this.translationMap)) {
671
- for (let [key, entry] of Object.entries(fields)) {
672
- entries.push({
673
- itemId,
674
- key: `data.${key}`,
675
- originalValue: entry.originalValue,
676
- translatedValue: entry.translatedValue
677
- });
678
- }
679
- }
680
- if (entries.length === 0) {
681
- return;
682
- }
683
- return { languageId, entries };
684
- };
685
- /**
686
- * Re-extract the translation sidecar whenever project data is replaced (route
687
- * change / non-design reuse), before rebuilding item stores. Takes the
688
- * renderable page shape (`rootId` resolved) that `getRenderablePage()` and
689
- * the reuse branch pass in.
690
- */
691
- setProjectData = (data) => {
692
- this.data = data;
693
- this.extractTranslationSidecar();
694
- this.initProject();
695
- };
696
- /**
697
- * Apply updates deferred off the render phase: swap in any pending page data
698
- * captured on runtime reuse, then notify items whose data was refreshed
699
- * during construction. The renderer calls this from a layout effect right
700
- * after commit, so subscribers re-render before paint (no content flash) and
701
- * without React's setState-in-render warning.
702
- */
703
- flushRenderPhaseUpdates = () => {
704
- let pendingData = this.pendingProjectData;
705
- if (pendingData) {
706
- this.pendingProjectData = void 0;
707
- this.setProjectData(pendingData);
708
- }
709
- let pendingItems = this.pendingItemUpdates;
710
- if (pendingItems.length > 0) {
711
- this.pendingItemUpdates = [];
712
- for (let item of pendingItems) {
713
- item.triggerUpdate();
714
- }
715
- }
716
- };
717
- };
718
- function createWeaverseNextRuntime(config) {
719
- let requestInfo = buildWeaverseNextRequestInfo(config.client?.requestContext);
720
- let page = getRenderablePage(config.data);
721
- let runtimeWindow = getRuntimeWindow();
722
- let existing = runtimeWindow?.__weaverses?.[page.id];
723
- let requestKey = getRuntimeKey(page.id, requestInfo);
724
- if (existing?.__weaverseNextRequestKey === requestKey) {
725
- let nextIsDesignMode = config.client?.requestContext?.isDesignMode ?? false;
726
- if (existing.isDesignMode || nextIsDesignMode) {
727
- existing.pendingProjectData = void 0;
728
- } else {
729
- existing.pendingProjectData = page;
730
- }
731
- existing.__weaverseNextLatestData = page;
732
- existing.dataContext = resolveDataContext(config);
733
- existing.requestInfo = requestInfo;
734
- existing.projectId = resolveProjectId(config.client, config.data, page.id);
735
- existing.isDesignMode = nextIsDesignMode;
736
- existing.isPreviewMode = config.client?.requestContext?.isPreviewMode ?? false;
737
- existing.isRevisionPreview = config.client?.requestContext?.isRevisionPreview ?? false;
738
- existing.sectionType = config.client?.requestContext?.sectionType;
739
- existing.weaverseHost = getConfigString(config.data.configs, "weaverseHost") ?? existing.weaverseHost;
740
- existing.weaverseVersion = getConfigString(config.data.configs, "weaverseVersion") ?? existing.weaverseVersion;
741
- existing.internal.pageAssignment = config.data.pageAssignment;
742
- existing.internal.project = config.data.project;
743
- if (config.navigate) {
744
- existing.internal.navigate = config.navigate;
745
- }
746
- if (config.revalidate) {
747
- existing.internal.revalidate = config.revalidate;
748
- }
749
- if (config.themeSettingsStore) {
750
- existing.internal.themeSettingsStore = config.themeSettingsStore;
751
- }
752
- if (config.translationStore) {
753
- existing.internal.translationStore = config.translationStore;
754
- existing.internal.themeTextStore = config.translationStore;
755
- }
756
- existing.internal.merchantOverrides = config.merchantOverrides;
757
- registerRuntime(existing);
758
- return existing;
759
- }
760
- let [runtime, refreshedItems] = collectDeferredItemUpdates(
761
- () => new WeaverseNextRuntime(config)
762
- );
763
- runtime.pendingItemUpdates = refreshedItems;
764
- runtime.__weaverseNextRequestKey = requestKey;
765
- runtime.__weaverseNextLatestData = page;
766
- registerRuntime(runtime);
767
- return runtime;
768
- }
769
- function bindWeaverseNextStudioRuntime(runtime) {
770
- if (!runtime.isDesignMode) {
771
- return false;
772
- }
773
- let studio = getRuntimeWindow()?.weaverseStudio;
774
- if (!studio) {
775
- return false;
776
- }
777
- let boundRuntime = runtime;
778
- if (!boundRuntime.__weaverseNextStudioBound) {
779
- studio.init?.(runtime);
780
- boundRuntime.__weaverseNextStudioBound = true;
781
- return true;
782
- }
783
- studio.refreshStudio?.({
784
- data: boundRuntime.__weaverseNextLatestData ?? runtime.data,
785
- pageId: runtime.pageId,
786
- requestInfo: runtime.requestInfo
787
- });
788
- return true;
789
- }
790
-
791
- // src/revalidate-item.ts
792
- var DEFAULT_REVALIDATE_ENDPOINT = "/api/weaverse/revalidate";
793
- async function revalidateWeaverseNextItem(runtime, draftItem, endpoint = DEFAULT_REVALIDATE_ENDPOINT) {
794
- let instance = runtime.itemInstances.get(draftItem.id);
795
- if (!instance) {
796
- throw new Error(
797
- `[weaverse-next] No live item instance for "${draftItem.id}".`
798
- );
799
- }
800
- let response = await fetch(endpoint, {
801
- method: "POST",
802
- headers: { "Content-Type": "application/json" },
803
- body: JSON.stringify({ draftItem })
804
- });
805
- if (!response.ok) {
806
- throw new Error(
807
- `[weaverse-next] Revalidate endpoint responded ${response.status}.`
808
- );
809
- }
810
- let { loaderData } = await response.json();
811
- instance.setData({ loaderData: loaderData ?? null });
812
- }
813
- var STUDIO_BIND_RETRY_INTERVAL_MS = 50;
814
- var STUDIO_BIND_MAX_ATTEMPTS = 100;
815
- function WeaverseNextStudioBridge(props) {
816
- let { runtime, navigate, revalidate, revalidateItem } = props;
817
- let lastRuntimeRef = useRef(runtime);
818
- let lastRuntimeDataRef = useRef(runtime.data);
819
- let lastRequestInfoRef = useRef(runtime.requestInfo);
820
- useEffect(() => {
821
- if (navigate) {
822
- runtime.internal.navigate = navigate;
823
- }
824
- if (revalidate) {
825
- runtime.internal.revalidate = revalidate;
826
- }
827
- if (revalidateItem) {
828
- runtime.internal.revalidateItem = revalidateItem;
829
- }
830
- if (bindWeaverseNextStudioRuntime(runtime) || !runtime.isDesignMode) {
831
- return;
832
- }
833
- let attempts = 0;
834
- let interval = window.setInterval(() => {
835
- attempts += 1;
836
- if (bindWeaverseNextStudioRuntime(runtime) || attempts >= STUDIO_BIND_MAX_ATTEMPTS) {
837
- window.clearInterval(interval);
838
- }
839
- }, STUDIO_BIND_RETRY_INTERVAL_MS);
840
- return () => window.clearInterval(interval);
841
- }, [runtime, navigate, revalidate, revalidateItem]);
842
- useEffect(() => {
843
- if (lastRuntimeRef.current !== runtime) {
844
- lastRuntimeRef.current = runtime;
845
- lastRuntimeDataRef.current = runtime.data;
846
- lastRequestInfoRef.current = runtime.requestInfo;
847
- return;
848
- }
849
- if (lastRuntimeDataRef.current === runtime.data && lastRequestInfoRef.current === runtime.requestInfo) {
850
- return;
851
- }
852
- lastRuntimeDataRef.current = runtime.data;
853
- lastRequestInfoRef.current = runtime.requestInfo;
854
- bindWeaverseNextStudioRuntime(runtime);
855
- }, [runtime, runtime.data, runtime.requestInfo]);
856
- return null;
857
- }
858
-
859
- // src/studio-router.ts
860
- function shouldResetScroll(options) {
861
- if (!options || typeof options !== "object") {
862
- return true;
863
- }
864
- return !options.preventScrollReset;
865
- }
866
- function createWeaverseNextStudioInternals(router, options = {}) {
867
- return {
868
- navigate: (to, navigateOptions) => {
869
- let scroll = shouldResetScroll(navigateOptions);
870
- if (options.replace) {
871
- router.replace(to, { scroll });
872
- } else {
873
- router.push(to, { scroll });
874
- }
875
- },
876
- revalidate: () => {
877
- router.refresh();
878
- }
879
- };
880
- }
881
- function useWeaverseNextStudioInternals(options) {
882
- let router = useRouter();
883
- let ref = useRef(null);
884
- if (!ref.current || ref.current.router !== router || ref.current.replace !== options?.replace) {
885
- ref.current = {
886
- internals: createWeaverseNextStudioInternals(router, options),
887
- replace: options?.replace,
888
- router
889
- };
890
- }
891
- return ref.current.internals;
892
- }
893
- function WeaverseNextStudio(props) {
894
- let { runtime, replace, revalidateEndpoint } = props;
895
- let { navigate, revalidate } = useWeaverseNextStudioInternals({ replace });
896
- let endpoint = revalidateEndpoint ?? DEFAULT_REVALIDATE_ENDPOINT;
897
- let revalidateItemRef = useRef(null);
898
- if (revalidateItemRef.current?.endpoint !== endpoint || revalidateItemRef.current.runtime !== runtime) {
899
- revalidateItemRef.current = {
900
- endpoint,
901
- revalidateItem: (draftItem) => revalidateWeaverseNextItem(runtime, draftItem, endpoint),
902
- runtime
903
- };
904
- }
905
- return /* @__PURE__ */ jsx(
906
- WeaverseNextStudioBridge,
907
- {
908
- navigate,
909
- revalidate,
910
- revalidateItem: revalidateItemRef.current.revalidateItem,
911
- runtime
912
- }
913
- );
914
- }
915
- var EMPTY_DATA_CONTEXT = {};
916
- var useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
917
- function getRenderablePage2(data) {
918
- let page = data?.page;
919
- if (!page) {
920
- return null;
921
- }
922
- let rootId = page.rootId ?? page.items.find((item) => item.type === "main")?.id ?? page.items[0]?.id ?? page.id;
923
- return { ...page, rootId };
924
- }
925
- var WeaverseNextRenderer = memo(function WeaverseNextRendererComponent(props) {
926
- let context = useContext(WeaverseNextContext);
927
- let client = props.client ?? context?.client;
928
- let data = props.data ?? client?.data ?? null;
929
- let dataContext = props.dataContext ?? client?.dataContext ?? EMPTY_DATA_CONTEXT;
930
- let page = useMemo(() => getRenderablePage2(data), [data]);
931
- let weaverse = useMemo(() => {
932
- if (!page) {
933
- return null;
934
- }
935
- return createWeaverseNextRuntime({
936
- client,
937
- data: { ...data, page },
938
- dataContext,
939
- merchantOverrides: context?.merchantOverrides,
940
- themeSettingsStore: context?.themeSettingsStore,
941
- translationStore: context?.translationStore
942
- });
943
- }, [
944
- client,
945
- page,
946
- data,
947
- dataContext,
948
- context?.merchantOverrides,
949
- context?.themeSettingsStore,
950
- context?.translationStore
951
- ]);
952
- useIsomorphicLayoutEffect(() => {
953
- weaverse?.flushRenderPhaseUpdates();
954
- }, [weaverse]);
955
- if (!weaverse) {
956
- return null;
957
- }
958
- return /* @__PURE__ */ jsxs(Fragment, { children: [
959
- /* @__PURE__ */ jsx(WeaverseRoot, { context: weaverse }),
960
- /* @__PURE__ */ jsx(WeaverseNextStudio, { runtime: weaverse })
961
- ] });
962
- });
963
-
964
- // src/studio-script-src.ts
965
- var TRUSTED_STUDIO_DOMAINS = ["weaverse.io", "weaverse.dev"];
966
- function isLoopbackHostname(hostname) {
967
- return hostname === "localhost" || hostname === "127.0.0.1" || hostname.endsWith(".localhost");
968
- }
969
- function normalizeOrigin(value) {
970
- if (!value) {
971
- return null;
972
- }
973
- try {
974
- return new URL(value).origin;
975
- } catch {
976
- return null;
977
- }
978
- }
979
- function isTrustedStudioOrigin(origin, storefrontHostname) {
980
- let parsed;
981
- try {
982
- parsed = new URL(origin);
983
- } catch {
984
- return false;
985
- }
986
- let { hostname, protocol } = parsed;
987
- if (isLoopbackHostname(storefrontHostname) && isLoopbackHostname(hostname)) {
988
- return protocol === "http:" || protocol === "https:";
989
- }
990
- if (protocol !== "https:") {
991
- return false;
992
- }
993
- return TRUSTED_STUDIO_DOMAINS.some(
994
- (domain) => hostname === domain || hostname.endsWith(`.${domain}`)
995
- );
996
- }
997
- function toSearchParams(context) {
998
- if (context?.searchParams) {
999
- return new URLSearchParams(context.searchParams);
1000
- }
1001
- if (context?.url) {
1002
- let url = typeof context.url === "string" ? new URL(context.url, "http://localhost") : context.url;
1003
- return new URLSearchParams(url.searchParams);
1004
- }
1005
- return new URLSearchParams();
1006
- }
1007
- function last(searchParams, key) {
1008
- let values = searchParams.getAll(key);
1009
- return values.length ? values.at(-1) ?? null : null;
1010
- }
1011
- function resolveWeaverseNextStudioScriptSrc(context, options = {}) {
1012
- let searchParams = toSearchParams(context);
1013
- let isDesignMode = context?.isDesignMode ?? last(searchParams, "isDesignMode") === "true";
1014
- let isPreviewMode = context?.isPreviewMode ?? last(searchParams, "isPreviewMode") === "true";
1015
- let isRevisionPreview = context?.isRevisionPreview ?? Boolean(last(searchParams, "__revisionId"));
1016
- if (!(isDesignMode || isPreviewMode || isRevisionPreview)) {
1017
- return null;
1018
- }
1019
- let origin = normalizeOrigin(last(searchParams, "weaverseHost"));
1020
- if (!origin) {
1021
- return null;
1022
- }
1023
- let storefrontHostname = options.storefrontHostname ?? "";
1024
- if (!isTrustedStudioOrigin(origin, storefrontHostname)) {
1025
- return null;
1026
- }
1027
- let bundle = isDesignMode ? "index.js" : "preview.js";
1028
- let version = last(searchParams, "weaverseVersion");
1029
- let url = `${origin}/static/studio/next/${bundle}`;
1030
- return version ? `${url}?v=${encodeURIComponent(version)}` : url;
1031
- }
1032
-
1033
- // src/studio-connect.tsx
1034
- var loadedScriptSrcs = /* @__PURE__ */ new Set();
1035
- function loadScript(src) {
1036
- if (typeof document === "undefined") {
1037
- return;
1038
- }
1039
- if (loadedScriptSrcs.has(src)) {
1040
- return;
1041
- }
1042
- let existing = document.querySelector(`script[src="${src}"]`);
1043
- if (existing) {
1044
- loadedScriptSrcs.add(src);
1045
- return;
1046
- }
1047
- let script = document.createElement("script");
1048
- script.async = true;
1049
- script.src = src;
1050
- document.head.appendChild(script);
1051
- loadedScriptSrcs.add(src);
1052
- }
1053
- function loadWeaverseNextStudioScript(context, options = {}) {
1054
- let resolvedContext = context;
1055
- if (!resolvedContext && typeof window !== "undefined") {
1056
- resolvedContext = {
1057
- searchParams: new URLSearchParams(window.location.search),
1058
- url: window.location.href
1059
- };
1060
- }
1061
- let src = resolveWeaverseNextStudioScriptSrc(resolvedContext, {
1062
- storefrontHostname: options.storefrontHostname ?? (typeof window === "undefined" ? void 0 : window.location.hostname)
1063
- });
1064
- if (src) {
1065
- loadScript(src);
1066
- }
1067
- }
1068
- function WeaverseNextStudioConnect(props) {
1069
- useEffect(() => {
1070
- loadWeaverseNextStudioScript(props.context, {
1071
- storefrontHostname: props.storefrontHostname
1072
- });
1073
- }, [props.context, props.storefrontHostname]);
1074
- return null;
1075
- }
1076
200
 
1077
- export { DEFAULT_REVALIDATE_ENDPOINT, ThemeTextProvider, ThemeTextStore, TranslationProvider, TranslationStore, WeaverseNextProvider, WeaverseNextRenderer, WeaverseNextRootProvider, WeaverseNextRuntime, WeaverseNextStudio, WeaverseNextStudioBridge, WeaverseNextStudioConnect, bindWeaverseNextStudioRuntime, createTranslate, createWeaverseNextClient, createWeaverseNextRuntime, createWeaverseNextStudioInternals, createWeaverseNextThemeSettingsStore, getNestedKey, interpolate, loadWeaverseNextStudioScript, resolveWeaverseNextStudioScriptSrc, revalidateWeaverseNextItem, useThemeSettings, useThemeText, useTranslation, useWeaverseCommerce, useWeaverseNextStudioInternals, useWeaversePageData, useWeaverseRootData };
201
+ export { ThemeTextStore, TranslationStore, createTranslate, createWeaverseNextStudioInternals, createWeaverseNextThemeSettingsStore, getNestedKey, interpolate, resolveWeaverseNextStudioScriptSrc };
1078
202
  //# sourceMappingURL=index.mjs.map
1079
203
  //# sourceMappingURL=index.mjs.map