@weaverse/next 0.1.0-alpha.0 → 0.1.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.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
 
@@ -26,13 +27,84 @@ function generateDataFromSchema(schema) {
26
27
  }
27
28
 
28
29
  // src/item.ts
30
+ function flattenItemData(update) {
31
+ let { data, ...rest } = update;
32
+ if (!(data && typeof data === "object" && !Array.isArray(data))) {
33
+ return rest;
34
+ }
35
+ return { ...data, ...rest };
36
+ }
37
+ var deferredItemUpdates = null;
38
+ function collectDeferredItemUpdates(create) {
39
+ let previousQueue = deferredItemUpdates;
40
+ let queue = /* @__PURE__ */ new Set();
41
+ deferredItemUpdates = queue;
42
+ try {
43
+ return [create(), [...queue]];
44
+ } finally {
45
+ deferredItemUpdates = previousQueue;
46
+ }
47
+ }
29
48
  var WeaverseNextItem = class extends react.WeaverseItemStore {
49
+ /**
50
+ * Cached merged snapshot (base `_store` + translations). Reset whenever the
51
+ * `_store` ref or the item's translation entry ref changes, so
52
+ * `useSyncExternalStore` sees a stable object between unrelated re-renders.
53
+ */
54
+ _cachedSnapshot = null;
55
+ _snapshotStoreRef = null;
56
+ _snapshotTranslationRef = null;
30
57
  constructor(initialData, weaverse) {
31
58
  super(initialData, weaverse);
32
- let { data, ...rest } = initialData;
33
59
  let schemaData = generateDataFromSchema(this.Element?.schema);
34
- Object.assign(this._store, schemaData, data, rest);
60
+ Object.assign(this._store, schemaData, flattenItemData(initialData));
35
61
  }
62
+ /**
63
+ * Flatten nested `data` on updates exactly like the constructor does. Core's
64
+ * `initProject()` calls `setData(item)` when a new runtime serves a page
65
+ * whose item instances already exist (e.g. locale/client navigation), and
66
+ * the inherited shallow merge would leave stale top-level props behind.
67
+ * Assigning through the inherited `data` setter swaps the `_store` ref,
68
+ * which invalidates the memoized snapshot below. The subscriber emit is
69
+ * queued instead of fired when a render-phase deferral is active (see
70
+ * `collectDeferredItemUpdates`).
71
+ */
72
+ setData = (update) => {
73
+ this.data = flattenItemData(update);
74
+ if (deferredItemUpdates) {
75
+ deferredItemUpdates.add(this);
76
+ } else {
77
+ this.triggerUpdate();
78
+ }
79
+ return this.data;
80
+ };
81
+ /**
82
+ * Overlay item-level translations onto the base store when the runtime is in
83
+ * translation mode. Mirrors Hydrogen's `WeaverseHydrogenItem.getSnapShot()`:
84
+ * memoized by `_store` ref + translation entry ref so the returned object is
85
+ * referentially stable, and a fast path that returns the base store untouched
86
+ * when the item has no translations.
87
+ */
88
+ getSnapShot = () => {
89
+ let base = this._store;
90
+ let translations = this.weaverse.translationMap[this._id];
91
+ if (!translations) {
92
+ return base;
93
+ }
94
+ if (this._cachedSnapshot && this._snapshotStoreRef === base && this._snapshotTranslationRef === translations) {
95
+ return this._cachedSnapshot;
96
+ }
97
+ let merged = { ...base };
98
+ for (let [key, entry] of Object.entries(translations)) {
99
+ if (entry.translatedValue !== void 0) {
100
+ merged[key] = entry.translatedValue;
101
+ }
102
+ }
103
+ this._cachedSnapshot = merged;
104
+ this._snapshotStoreRef = base;
105
+ this._snapshotTranslationRef = translations;
106
+ return merged;
107
+ };
36
108
  };
37
109
  function ensureNextItemConstructor() {
38
110
  if (!react.Weaverse.ItemConstructor || react.Weaverse.ItemConstructor === react.WeaverseItemStore || react.Weaverse.ItemConstructor === WeaverseNextItem) {
@@ -132,20 +204,283 @@ var NextClient = class {
132
204
  function createWeaverseNextClient(config) {
133
205
  return new NextClient(config);
134
206
  }
207
+
208
+ // src/theme-settings-store.ts
209
+ function createWeaverseNextThemeSettingsStore(options = {}) {
210
+ let listeners = /* @__PURE__ */ new Set();
211
+ let store = {
212
+ publicEnv: options.publicEnv,
213
+ schema: options.schema,
214
+ settings: { ...options.settings ?? {} },
215
+ getServerSnapshot: () => store.settings,
216
+ getSnapshot: () => store.settings,
217
+ subscribe: (listener) => {
218
+ listeners.add(listener);
219
+ return () => {
220
+ listeners.delete(listener);
221
+ };
222
+ },
223
+ updateThemeSettings: (next) => {
224
+ store.settings = { ...store.settings, ...next };
225
+ for (let listener of listeners) {
226
+ listener();
227
+ }
228
+ }
229
+ };
230
+ return store;
231
+ }
232
+ function getNestedKey(obj, path, fallback) {
233
+ let keys = path.split(".");
234
+ let current = obj;
235
+ for (let key of keys) {
236
+ if (current == null || typeof current !== "object") {
237
+ return fallback;
238
+ }
239
+ current = current[key];
240
+ }
241
+ if (typeof current === "string") {
242
+ return current;
243
+ }
244
+ return fallback;
245
+ }
246
+ function interpolate(template, variables) {
247
+ if (!variables) {
248
+ return template;
249
+ }
250
+ return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
251
+ let value = variables[key];
252
+ return value === void 0 ? match : String(value);
253
+ });
254
+ }
255
+ var TranslationContext = react$1.createContext(null);
256
+ TranslationContext.displayName = "WeaverseNextTranslationContext";
257
+ function createTranslate(sources) {
258
+ let { staticContent, merchantOverrides, designOverrides, externalT } = sources;
259
+ return (key, variables) => {
260
+ if (externalT) {
261
+ let external = externalT(key, variables);
262
+ if (external && external !== key) {
263
+ return external;
264
+ }
265
+ }
266
+ let design = designOverrides && Object.hasOwn(designOverrides, key) ? designOverrides[key] : void 0;
267
+ let override = merchantOverrides ? getNestedKey(merchantOverrides, key) : void 0;
268
+ let staticValue = getNestedKey(staticContent, key);
269
+ let raw = design ?? override ?? staticValue ?? key;
270
+ return interpolate(raw, variables);
271
+ };
272
+ }
273
+ var EMPTY = {};
274
+ var NOOP_SUBSCRIBE = () => () => {
275
+ };
276
+ var NOOP_SNAPSHOT = () => EMPTY;
277
+ function TranslationProvider({
278
+ staticContent,
279
+ merchantOverrides,
280
+ t: externalT,
281
+ translationStore,
282
+ themeTextStore,
283
+ children
284
+ }) {
285
+ let store = translationStore ?? themeTextStore ?? null;
286
+ let designOverrides = react.useSafeExternalStore(
287
+ store?.subscribe ?? NOOP_SUBSCRIBE,
288
+ store?.getSnapshot ?? NOOP_SNAPSHOT,
289
+ store?.getServerSnapshot ?? NOOP_SNAPSHOT
290
+ );
291
+ let value = react$1.useMemo(
292
+ () => ({
293
+ t: createTranslate({
294
+ staticContent,
295
+ merchantOverrides,
296
+ designOverrides,
297
+ externalT
298
+ }),
299
+ translationStore: store,
300
+ // Deprecated alias — same instance, kept for backward compatibility.
301
+ themeTextStore: store,
302
+ merchantOverrides: merchantOverrides ?? null
303
+ }),
304
+ [staticContent, merchantOverrides, designOverrides, externalT, store]
305
+ );
306
+ return /* @__PURE__ */ jsxRuntime.jsx(TranslationContext.Provider, { value, children });
307
+ }
308
+ function useTranslation() {
309
+ let ctx = react$1.useContext(TranslationContext);
310
+ if (!ctx) {
311
+ throw new Error(
312
+ "useTranslation must be used within <TranslationProvider>. Wrap your app with <WeaverseNextRootProvider>."
313
+ );
314
+ }
315
+ return ctx;
316
+ }
317
+ var ThemeTextProvider = TranslationProvider;
318
+ var useThemeText = useTranslation;
319
+
320
+ // src/translation-store.ts
321
+ var TranslationStore = class {
322
+ overrides = {};
323
+ listeners = /* @__PURE__ */ new Set();
324
+ setOverrides = (overrides) => {
325
+ this.overrides = { ...overrides };
326
+ this.emit();
327
+ };
328
+ updateOverrides = (newOverrides) => {
329
+ this.overrides = { ...this.overrides, ...newOverrides };
330
+ this.emit();
331
+ };
332
+ getSnapshot = () => this.overrides;
333
+ getServerSnapshot = () => this.overrides;
334
+ subscribe = (callback) => {
335
+ this.listeners.add(callback);
336
+ return () => {
337
+ this.listeners.delete(callback);
338
+ };
339
+ };
340
+ emit = () => {
341
+ for (const listener of Array.from(this.listeners)) {
342
+ try {
343
+ listener();
344
+ } catch (error) {
345
+ console.error("TranslationStore: Listener error", error);
346
+ }
347
+ }
348
+ };
349
+ };
350
+ var ThemeTextStore = TranslationStore;
351
+ var WeaverseNextRootContext = react$1.createContext(null);
352
+ function WeaverseNextRootProvider(props) {
353
+ let {
354
+ children,
355
+ initialThemeSettings,
356
+ merchantOverrides,
357
+ staticContent,
358
+ t,
359
+ themeSchema,
360
+ publicEnv
361
+ } = props;
362
+ let storeRef = react$1.useRef(null);
363
+ if (!storeRef.current) {
364
+ storeRef.current = createWeaverseNextThemeSettingsStore({
365
+ publicEnv,
366
+ schema: themeSchema,
367
+ settings: initialThemeSettings
368
+ });
369
+ }
370
+ let themeSettingsStore = storeRef.current;
371
+ let translationStoreRef = react$1.useRef(null);
372
+ if (!translationStoreRef.current) {
373
+ translationStoreRef.current = new TranslationStore();
374
+ }
375
+ let translationStore = translationStoreRef.current;
376
+ let appliedThemeSettingsRef = react$1.useRef(initialThemeSettings);
377
+ react$1.useEffect(() => {
378
+ if (initialThemeSettings && appliedThemeSettingsRef.current !== initialThemeSettings) {
379
+ themeSettingsStore.updateThemeSettings(initialThemeSettings);
380
+ appliedThemeSettingsRef.current = initialThemeSettings;
381
+ }
382
+ }, [initialThemeSettings, themeSettingsStore]);
383
+ let resolvedStaticContent = staticContent ?? getSchemaStaticContent(themeSchema);
384
+ let rootContextValue = react$1.useMemo(
385
+ () => ({
386
+ merchantOverrides,
387
+ staticContent: resolvedStaticContent,
388
+ themeSettingsStore,
389
+ translationStore
390
+ }),
391
+ [
392
+ merchantOverrides,
393
+ resolvedStaticContent,
394
+ themeSettingsStore,
395
+ translationStore
396
+ ]
397
+ );
398
+ let contextValue = react$1.useMemo(
399
+ () => ({
400
+ merchantOverrides,
401
+ themeSettings: themeSettingsStore.getSnapshot(),
402
+ themeSettingsStore,
403
+ translationStore
404
+ }),
405
+ [merchantOverrides, themeSettingsStore, translationStore]
406
+ );
407
+ return /* @__PURE__ */ jsxRuntime.jsx(WeaverseNextRootContext.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(WeaverseNextContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
408
+ TranslationProvider,
409
+ {
410
+ merchantOverrides,
411
+ staticContent: resolvedStaticContent,
412
+ t,
413
+ translationStore,
414
+ children
415
+ }
416
+ ) }) });
417
+ }
418
+ var EMPTY_THEME_SETTINGS = {};
419
+ var EMPTY_STATIC_CONTENT = {};
420
+ function getSchemaStaticContent(schema) {
421
+ let i18n = schema?.i18n;
422
+ return i18n?.staticContent ?? EMPTY_STATIC_CONTENT;
423
+ }
135
424
  var WeaverseNextContext = react$1.createContext(null);
136
425
  function WeaverseNextProvider(props) {
137
426
  let { children, client, rootData, pageData, commerce, themeSettings } = props;
427
+ let rootContext = react$1.useContext(WeaverseNextRootContext);
428
+ let themeSettingsValue = themeSettings ?? client?.themeSettings ?? EMPTY_THEME_SETTINGS;
429
+ let ownTranslationStoreRef = react$1.useRef(null);
430
+ if (!(rootContext || ownTranslationStoreRef.current)) {
431
+ ownTranslationStoreRef.current = new TranslationStore();
432
+ }
433
+ let translationStore = rootContext?.translationStore ?? ownTranslationStoreRef.current;
434
+ let staticContent = props.staticContent ?? rootContext?.staticContent ?? getSchemaStaticContent(client?.themeSchema);
435
+ let merchantOverrides = props.merchantOverrides ?? rootContext?.merchantOverrides;
436
+ let ownThemeSettingsStore = react$1.useMemo(() => {
437
+ if (rootContext) {
438
+ return null;
439
+ }
440
+ return createWeaverseNextThemeSettingsStore({
441
+ schema: client?.themeSchema,
442
+ settings: themeSettingsValue
443
+ });
444
+ }, [rootContext, client?.themeSchema, themeSettingsValue]);
445
+ let themeSettingsStore = rootContext?.themeSettingsStore ?? ownThemeSettingsStore;
446
+ let mergedIntoRootRef = react$1.useRef(void 0);
447
+ react$1.useEffect(() => {
448
+ if (rootContext && themeSettingsValue !== EMPTY_THEME_SETTINGS && mergedIntoRootRef.current !== themeSettingsValue) {
449
+ rootContext.themeSettingsStore.updateThemeSettings(themeSettingsValue);
450
+ mergedIntoRootRef.current = themeSettingsValue;
451
+ }
452
+ }, [rootContext, themeSettingsValue]);
138
453
  let value = react$1.useMemo(
139
454
  () => ({
140
455
  client,
141
456
  rootData,
142
457
  pageData,
143
458
  commerce: commerce ?? client?.commerce,
144
- themeSettings: themeSettings ?? client?.themeSettings ?? {}
459
+ merchantOverrides,
460
+ themeSettings: themeSettingsStore.getSnapshot(),
461
+ themeSettingsStore,
462
+ translationStore
145
463
  }),
146
- [client, rootData, pageData, commerce, themeSettings]
464
+ [
465
+ client,
466
+ rootData,
467
+ pageData,
468
+ commerce,
469
+ merchantOverrides,
470
+ themeSettingsStore,
471
+ translationStore
472
+ ]
147
473
  );
148
- return /* @__PURE__ */ jsxRuntime.jsx(WeaverseNextContext.Provider, { value, children });
474
+ return /* @__PURE__ */ jsxRuntime.jsx(WeaverseNextContext.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsx(
475
+ TranslationProvider,
476
+ {
477
+ merchantOverrides,
478
+ staticContent,
479
+ t: props.t,
480
+ translationStore,
481
+ children
482
+ }
483
+ ) });
149
484
  }
150
485
 
151
486
  // src/hooks.ts
@@ -167,7 +502,12 @@ function useWeaverseCommerce() {
167
502
  return useWeaverseNextContext("useWeaverseCommerce").commerce;
168
503
  }
169
504
  function useThemeSettings() {
170
- return useWeaverseNextContext("useThemeSettings").themeSettings;
505
+ let { themeSettingsStore } = useWeaverseNextContext("useThemeSettings");
506
+ return react$1.useSyncExternalStore(
507
+ themeSettingsStore.subscribe,
508
+ themeSettingsStore.getSnapshot,
509
+ themeSettingsStore.getServerSnapshot
510
+ );
171
511
  }
172
512
 
173
513
  // src/loader.ts
@@ -246,8 +586,498 @@ async function runWeaverseComponentLoaders(args) {
246
586
  await walk(items);
247
587
  return data;
248
588
  }
249
- var EMPTY_DATA_CONTEXT = {};
589
+
590
+ // src/request-info.ts
591
+ function toUrl(value) {
592
+ return typeof value === "string" ? new URL(value, "http://localhost") : value;
593
+ }
594
+ function getSearchParamsFromContext(context) {
595
+ if (context?.searchParams) {
596
+ return new URLSearchParams(context.searchParams);
597
+ }
598
+ if (context?.url) {
599
+ let url = toUrl(context.url);
600
+ return new URLSearchParams(url.searchParams);
601
+ }
602
+ return new URLSearchParams();
603
+ }
604
+ function getPathnameFromContext(context) {
605
+ if (context?.pathname) {
606
+ return context.pathname;
607
+ }
608
+ if (context?.url) {
609
+ let url = toUrl(context.url);
610
+ return url.pathname || "/";
611
+ }
612
+ return "/";
613
+ }
614
+ function coerceQueryValue(value) {
615
+ if (value === "true") {
616
+ return true;
617
+ }
618
+ if (value === "false") {
619
+ return false;
620
+ }
621
+ return value;
622
+ }
623
+ function toQueryRecord(searchParams) {
624
+ let queries = {};
625
+ for (let [key, value] of searchParams.entries()) {
626
+ queries[key] = coerceQueryValue(value);
627
+ }
628
+ return queries;
629
+ }
630
+ var TRANSIENT_STUDIO_PARAMS = /* @__PURE__ */ new Set([
631
+ "weaverseDraftItem",
632
+ // Legacy name from the original design-mode draft-item spike. Keep it out of
633
+ // runtime requestInfo too, in case an older Builder bundle is in front of a
634
+ // newer Next storefront.
635
+ "__weaverseDraftItem"
636
+ ]);
637
+ function getRequestInfoSearchParams(context) {
638
+ let searchParams = new URLSearchParams(getSearchParamsFromContext(context));
639
+ for (let key of TRANSIENT_STUDIO_PARAMS) {
640
+ searchParams.delete(key);
641
+ }
642
+ return searchParams;
643
+ }
644
+ function buildWeaverseNextRequestInfo(context) {
645
+ let searchParams = getRequestInfoSearchParams(context);
646
+ let search = searchParams.toString();
647
+ return {
648
+ pathname: getPathnameFromContext(context),
649
+ search: search ? `?${search}` : "",
650
+ queries: toQueryRecord(searchParams),
651
+ ...context?.i18n ? { i18n: context.i18n } : {}
652
+ };
653
+ }
654
+
655
+ // src/runtime.ts
656
+ function getRuntimeWindow() {
657
+ return typeof window === "undefined" ? void 0 : window;
658
+ }
250
659
  function getRenderablePage(data) {
660
+ let page = data.page;
661
+ let rootId = page.rootId ?? page.items.find((item) => item.type === "main")?.id ?? page.items[0]?.id ?? page.id;
662
+ return { ...page, rootId };
663
+ }
664
+ function getConfigString(configs, key) {
665
+ let value = configs?.[key];
666
+ return typeof value === "string" ? value : void 0;
667
+ }
668
+ function getRecordString(record, key) {
669
+ let value = record?.[key];
670
+ return typeof value === "string" ? value : void 0;
671
+ }
672
+ function resolveProjectId(client, data, fallback) {
673
+ let projectId = client?.projectId;
674
+ if (projectId) {
675
+ return projectId;
676
+ }
677
+ let configProjectId = getConfigString(data.configs, "projectId");
678
+ if (configProjectId) {
679
+ return configProjectId;
680
+ }
681
+ return getRecordString(data.project, "id") ?? fallback;
682
+ }
683
+ function resolveDataContext(config) {
684
+ if (config.dataContext) {
685
+ return config.dataContext;
686
+ }
687
+ if (config.client?.dataContext) {
688
+ return config.client.dataContext;
689
+ }
690
+ return {};
691
+ }
692
+ function getRuntimeKey(pageId, requestInfo) {
693
+ return `${pageId}:${requestInfo.pathname}:${requestInfo.search}`;
694
+ }
695
+ function registerRuntime(runtime) {
696
+ let runtimeWindow = getRuntimeWindow();
697
+ if (!runtimeWindow) {
698
+ return;
699
+ }
700
+ runtimeWindow.__weaverses ??= {};
701
+ runtimeWindow.__weaverses[runtime.pageId] = runtime;
702
+ runtimeWindow.__weaverse = runtime;
703
+ }
704
+ var WeaverseNextRuntime = class extends react.Weaverse {
705
+ pageId;
706
+ internal;
707
+ requestInfo;
708
+ isPreviewMode;
709
+ isRevisionPreview;
710
+ sectionType;
711
+ // ─── Item-level translation sidecar (design mode only) ─────────────
712
+ /**
713
+ * Translation map received from Builder in design mode, keyed by item ID.
714
+ * `WeaverseNextItem.getSnapShot()` overlays these onto the data handed to
715
+ * components, so translations render without mutating the base `_store`.
716
+ */
717
+ translationMap = {};
718
+ translationLocale = String();
719
+ translationLanguageId = String();
720
+ /**
721
+ * Fresh page data captured while React was rendering. Runtime reuse happens
722
+ * inside the renderer's render phase (`useMemo`), where applying it through
723
+ * `setProjectData()` would emit item updates to `useSyncExternalStore`
724
+ * subscribers mid-render. The renderer applies it post-commit via
725
+ * `flushRenderPhaseUpdates()`. Never set on design-mode runtimes — the live
726
+ * Studio tree owns the page data there.
727
+ */
728
+ pendingProjectData;
729
+ /**
730
+ * Reused item instances whose data was refreshed while this runtime was
731
+ * constructed during render (core `initProject()` calls `setData()` on
732
+ * them). Their data is already fresh; only the subscriber notification was
733
+ * deferred to `flushRenderPhaseUpdates()`.
734
+ */
735
+ pendingItemUpdates = [];
736
+ constructor(config) {
737
+ let { client, data } = config;
738
+ let page = getRenderablePage(data);
739
+ let configs = data.configs;
740
+ let requestContext = client?.requestContext;
741
+ let projectId = resolveProjectId(client, data, page.id);
742
+ ensureNextItemConstructor();
743
+ super({
744
+ projectId,
745
+ data: page,
746
+ isDesignMode: requestContext?.isDesignMode ?? false,
747
+ weaverseHost: getConfigString(configs, "weaverseHost"),
748
+ weaverseVersion: getConfigString(configs, "weaverseVersion")
749
+ });
750
+ this.pageId = page.id;
751
+ this.dataContext = resolveDataContext(config);
752
+ this.requestInfo = buildWeaverseNextRequestInfo(requestContext);
753
+ this.isDesignMode = requestContext?.isDesignMode ?? false;
754
+ this.isPreviewMode = requestContext?.isPreviewMode ?? false;
755
+ this.isRevisionPreview = requestContext?.isRevisionPreview ?? false;
756
+ this.sectionType = requestContext?.sectionType;
757
+ let translationStore = config.translationStore ?? new TranslationStore();
758
+ this.internal = {
759
+ merchantOverrides: config.merchantOverrides,
760
+ navigate: config.navigate,
761
+ pageAssignment: data.pageAssignment,
762
+ project: data.project,
763
+ revalidate: config.revalidate,
764
+ themeSettingsStore: config.themeSettingsStore ?? createWeaverseNextThemeSettingsStore({
765
+ schema: client?.themeSchema,
766
+ settings: client?.themeSettings
767
+ }),
768
+ translationStore,
769
+ themeTextStore: translationStore
770
+ };
771
+ this.extractTranslationSidecar();
772
+ }
773
+ /**
774
+ * Pull `translationMap` / `translationLocale` / `translationLanguageId` off
775
+ * the current page data (Builder attaches them in design mode). Unlike
776
+ * Hydrogen, this also clears the sidecar to defaults when the new page data
777
+ * carries none, so a reused runtime / project-data swap can't leave a stale
778
+ * map overlaying the fresh tree.
779
+ */
780
+ extractTranslationSidecar = () => {
781
+ let pageData = this.data;
782
+ let translationMap = pageData?.translationMap;
783
+ if (translationMap) {
784
+ this.translationMap = translationMap;
785
+ this.translationLocale = pageData?.translationLocale || "";
786
+ this.translationLanguageId = pageData?.translationLanguageId || "";
787
+ } else {
788
+ this.translationMap = {};
789
+ this.translationLocale = "";
790
+ this.translationLanguageId = "";
791
+ }
792
+ };
793
+ /**
794
+ * Replace the translation sidecar (Builder pushes this when translation data
795
+ * arrives or the active language changes) and refresh every item so their
796
+ * merged snapshots recompute.
797
+ */
798
+ setTranslationSidecar = (map = {}, locale = "", languageId = "") => {
799
+ this.translationMap = map;
800
+ this.translationLocale = locale;
801
+ this.translationLanguageId = languageId;
802
+ this.refreshAllItems();
803
+ };
804
+ /**
805
+ * Update a single translatable field for one item. Assigns a new per-item
806
+ * entry object so `WeaverseNextItem.getSnapShot()`'s translation-ref cache
807
+ * invalidates, then triggers only that item's subscribers.
808
+ */
809
+ updateTranslation = (itemId, key, originalValue, translatedValue) => {
810
+ if (!this.translationMap[itemId]) {
811
+ this.translationMap[itemId] = {};
812
+ }
813
+ this.translationMap[itemId] = {
814
+ ...this.translationMap[itemId],
815
+ [key]: { originalValue, translatedValue }
816
+ };
817
+ let instance = this.itemInstances.get(itemId);
818
+ if (instance) {
819
+ instance.triggerUpdate();
820
+ }
821
+ };
822
+ /**
823
+ * Collect translation changes for the save flow. Returns `undefined` unless
824
+ * both the locale and language ID are set and at least one entry exists;
825
+ * each entry key is namespaced as `data.<field>` to match Builder.
826
+ */
827
+ getTranslationChanges = () => {
828
+ let languageId = this.translationLanguageId;
829
+ if (!(this.translationLocale && languageId)) {
830
+ return;
831
+ }
832
+ let entries = [];
833
+ for (let [itemId, fields] of Object.entries(this.translationMap)) {
834
+ for (let [key, entry] of Object.entries(fields)) {
835
+ entries.push({
836
+ itemId,
837
+ key: `data.${key}`,
838
+ originalValue: entry.originalValue,
839
+ translatedValue: entry.translatedValue
840
+ });
841
+ }
842
+ }
843
+ if (entries.length === 0) {
844
+ return;
845
+ }
846
+ return { languageId, entries };
847
+ };
848
+ /**
849
+ * Re-extract the translation sidecar whenever project data is replaced (route
850
+ * change / non-design reuse), before rebuilding item stores. Takes the
851
+ * renderable page shape (`rootId` resolved) that `getRenderablePage()` and
852
+ * the reuse branch pass in.
853
+ */
854
+ setProjectData = (data) => {
855
+ this.data = data;
856
+ this.extractTranslationSidecar();
857
+ this.initProject();
858
+ };
859
+ /**
860
+ * Apply updates deferred off the render phase: swap in any pending page data
861
+ * captured on runtime reuse, then notify items whose data was refreshed
862
+ * during construction. The renderer calls this from a layout effect right
863
+ * after commit, so subscribers re-render before paint (no content flash) and
864
+ * without React's setState-in-render warning.
865
+ */
866
+ flushRenderPhaseUpdates = () => {
867
+ let pendingData = this.pendingProjectData;
868
+ if (pendingData) {
869
+ this.pendingProjectData = void 0;
870
+ this.setProjectData(pendingData);
871
+ }
872
+ let pendingItems = this.pendingItemUpdates;
873
+ if (pendingItems.length > 0) {
874
+ this.pendingItemUpdates = [];
875
+ for (let item of pendingItems) {
876
+ item.triggerUpdate();
877
+ }
878
+ }
879
+ };
880
+ };
881
+ function createWeaverseNextRuntime(config) {
882
+ let requestInfo = buildWeaverseNextRequestInfo(config.client?.requestContext);
883
+ let page = getRenderablePage(config.data);
884
+ let runtimeWindow = getRuntimeWindow();
885
+ let existing = runtimeWindow?.__weaverses?.[page.id];
886
+ let requestKey = getRuntimeKey(page.id, requestInfo);
887
+ if (existing?.__weaverseNextRequestKey === requestKey) {
888
+ let nextIsDesignMode = config.client?.requestContext?.isDesignMode ?? false;
889
+ if (existing.isDesignMode || nextIsDesignMode) {
890
+ existing.pendingProjectData = void 0;
891
+ } else {
892
+ existing.pendingProjectData = page;
893
+ }
894
+ existing.__weaverseNextLatestData = page;
895
+ existing.dataContext = resolveDataContext(config);
896
+ existing.requestInfo = requestInfo;
897
+ existing.projectId = resolveProjectId(config.client, config.data, page.id);
898
+ existing.isDesignMode = nextIsDesignMode;
899
+ existing.isPreviewMode = config.client?.requestContext?.isPreviewMode ?? false;
900
+ existing.isRevisionPreview = config.client?.requestContext?.isRevisionPreview ?? false;
901
+ existing.sectionType = config.client?.requestContext?.sectionType;
902
+ existing.weaverseHost = getConfigString(config.data.configs, "weaverseHost") ?? existing.weaverseHost;
903
+ existing.weaverseVersion = getConfigString(config.data.configs, "weaverseVersion") ?? existing.weaverseVersion;
904
+ existing.internal.pageAssignment = config.data.pageAssignment;
905
+ existing.internal.project = config.data.project;
906
+ if (config.navigate) {
907
+ existing.internal.navigate = config.navigate;
908
+ }
909
+ if (config.revalidate) {
910
+ existing.internal.revalidate = config.revalidate;
911
+ }
912
+ if (config.themeSettingsStore) {
913
+ existing.internal.themeSettingsStore = config.themeSettingsStore;
914
+ }
915
+ if (config.translationStore) {
916
+ existing.internal.translationStore = config.translationStore;
917
+ existing.internal.themeTextStore = config.translationStore;
918
+ }
919
+ existing.internal.merchantOverrides = config.merchantOverrides;
920
+ registerRuntime(existing);
921
+ return existing;
922
+ }
923
+ let [runtime, refreshedItems] = collectDeferredItemUpdates(
924
+ () => new WeaverseNextRuntime(config)
925
+ );
926
+ runtime.pendingItemUpdates = refreshedItems;
927
+ runtime.__weaverseNextRequestKey = requestKey;
928
+ runtime.__weaverseNextLatestData = page;
929
+ registerRuntime(runtime);
930
+ return runtime;
931
+ }
932
+ function bindWeaverseNextStudioRuntime(runtime) {
933
+ if (!runtime.isDesignMode) {
934
+ return false;
935
+ }
936
+ let studio = getRuntimeWindow()?.weaverseStudio;
937
+ if (!studio) {
938
+ return false;
939
+ }
940
+ let boundRuntime = runtime;
941
+ if (!boundRuntime.__weaverseNextStudioBound) {
942
+ studio.init?.(runtime);
943
+ boundRuntime.__weaverseNextStudioBound = true;
944
+ return true;
945
+ }
946
+ studio.refreshStudio?.({
947
+ data: boundRuntime.__weaverseNextLatestData ?? runtime.data,
948
+ pageId: runtime.pageId,
949
+ requestInfo: runtime.requestInfo
950
+ });
951
+ return true;
952
+ }
953
+
954
+ // src/revalidate-item.ts
955
+ var DEFAULT_REVALIDATE_ENDPOINT = "/api/weaverse/revalidate";
956
+ async function revalidateWeaverseNextItem(runtime, draftItem, endpoint = DEFAULT_REVALIDATE_ENDPOINT) {
957
+ let instance = runtime.itemInstances.get(draftItem.id);
958
+ if (!instance) {
959
+ throw new Error(
960
+ `[weaverse-next] No live item instance for "${draftItem.id}".`
961
+ );
962
+ }
963
+ let response = await fetch(endpoint, {
964
+ method: "POST",
965
+ headers: { "Content-Type": "application/json" },
966
+ body: JSON.stringify({ draftItem })
967
+ });
968
+ if (!response.ok) {
969
+ throw new Error(
970
+ `[weaverse-next] Revalidate endpoint responded ${response.status}.`
971
+ );
972
+ }
973
+ let { loaderData } = await response.json();
974
+ instance.setData({ loaderData: loaderData ?? null });
975
+ }
976
+ var STUDIO_BIND_RETRY_INTERVAL_MS = 50;
977
+ var STUDIO_BIND_MAX_ATTEMPTS = 100;
978
+ function WeaverseNextStudioBridge(props) {
979
+ let { runtime, navigate, revalidate, revalidateItem } = props;
980
+ let lastRuntimeRef = react$1.useRef(runtime);
981
+ let lastRuntimeDataRef = react$1.useRef(runtime.data);
982
+ let lastRequestInfoRef = react$1.useRef(runtime.requestInfo);
983
+ react$1.useEffect(() => {
984
+ if (navigate) {
985
+ runtime.internal.navigate = navigate;
986
+ }
987
+ if (revalidate) {
988
+ runtime.internal.revalidate = revalidate;
989
+ }
990
+ if (revalidateItem) {
991
+ runtime.internal.revalidateItem = revalidateItem;
992
+ }
993
+ if (bindWeaverseNextStudioRuntime(runtime) || !runtime.isDesignMode) {
994
+ return;
995
+ }
996
+ let attempts = 0;
997
+ let interval = window.setInterval(() => {
998
+ attempts += 1;
999
+ if (bindWeaverseNextStudioRuntime(runtime) || attempts >= STUDIO_BIND_MAX_ATTEMPTS) {
1000
+ window.clearInterval(interval);
1001
+ }
1002
+ }, STUDIO_BIND_RETRY_INTERVAL_MS);
1003
+ return () => window.clearInterval(interval);
1004
+ }, [runtime, navigate, revalidate, revalidateItem]);
1005
+ react$1.useEffect(() => {
1006
+ if (lastRuntimeRef.current !== runtime) {
1007
+ lastRuntimeRef.current = runtime;
1008
+ lastRuntimeDataRef.current = runtime.data;
1009
+ lastRequestInfoRef.current = runtime.requestInfo;
1010
+ return;
1011
+ }
1012
+ if (lastRuntimeDataRef.current === runtime.data && lastRequestInfoRef.current === runtime.requestInfo) {
1013
+ return;
1014
+ }
1015
+ lastRuntimeDataRef.current = runtime.data;
1016
+ lastRequestInfoRef.current = runtime.requestInfo;
1017
+ bindWeaverseNextStudioRuntime(runtime);
1018
+ }, [runtime, runtime.data, runtime.requestInfo]);
1019
+ return null;
1020
+ }
1021
+
1022
+ // src/studio-router.ts
1023
+ function shouldResetScroll(options) {
1024
+ if (!options || typeof options !== "object") {
1025
+ return true;
1026
+ }
1027
+ return !options.preventScrollReset;
1028
+ }
1029
+ function createWeaverseNextStudioInternals(router, options = {}) {
1030
+ return {
1031
+ navigate: (to, navigateOptions) => {
1032
+ let scroll = shouldResetScroll(navigateOptions);
1033
+ if (options.replace) {
1034
+ router.replace(to, { scroll });
1035
+ } else {
1036
+ router.push(to, { scroll });
1037
+ }
1038
+ },
1039
+ revalidate: () => {
1040
+ router.refresh();
1041
+ }
1042
+ };
1043
+ }
1044
+ function useWeaverseNextStudioInternals(options) {
1045
+ let router = navigation.useRouter();
1046
+ let ref = react$1.useRef(null);
1047
+ if (!ref.current || ref.current.router !== router || ref.current.replace !== options?.replace) {
1048
+ ref.current = {
1049
+ internals: createWeaverseNextStudioInternals(router, options),
1050
+ replace: options?.replace,
1051
+ router
1052
+ };
1053
+ }
1054
+ return ref.current.internals;
1055
+ }
1056
+ function WeaverseNextStudio(props) {
1057
+ let { runtime, replace, revalidateEndpoint } = props;
1058
+ let { navigate, revalidate } = useWeaverseNextStudioInternals({ replace });
1059
+ let endpoint = revalidateEndpoint ?? DEFAULT_REVALIDATE_ENDPOINT;
1060
+ let revalidateItemRef = react$1.useRef(null);
1061
+ if (revalidateItemRef.current?.endpoint !== endpoint || revalidateItemRef.current.runtime !== runtime) {
1062
+ revalidateItemRef.current = {
1063
+ endpoint,
1064
+ revalidateItem: (draftItem) => revalidateWeaverseNextItem(runtime, draftItem, endpoint),
1065
+ runtime
1066
+ };
1067
+ }
1068
+ return /* @__PURE__ */ jsxRuntime.jsx(
1069
+ WeaverseNextStudioBridge,
1070
+ {
1071
+ navigate,
1072
+ revalidate,
1073
+ revalidateItem: revalidateItemRef.current.revalidateItem,
1074
+ runtime
1075
+ }
1076
+ );
1077
+ }
1078
+ var EMPTY_DATA_CONTEXT = {};
1079
+ var useIsomorphicLayoutEffect = typeof window === "undefined" ? react$1.useEffect : react$1.useLayoutEffect;
1080
+ function getRenderablePage2(data) {
251
1081
  let page = data?.page;
252
1082
  if (!page) {
253
1083
  return null;
@@ -260,30 +1090,209 @@ var WeaverseNextRenderer = react$1.memo(function WeaverseNextRendererComponent(p
260
1090
  let client = props.client ?? context?.client;
261
1091
  let data = props.data ?? client?.data ?? null;
262
1092
  let dataContext = props.dataContext ?? client?.dataContext ?? EMPTY_DATA_CONTEXT;
263
- let page = react$1.useMemo(() => getRenderablePage(data), [data]);
1093
+ let page = react$1.useMemo(() => getRenderablePage2(data), [data]);
264
1094
  let weaverse = react$1.useMemo(() => {
265
1095
  if (!page) {
266
1096
  return null;
267
1097
  }
268
- let instance = new react.Weaverse({
269
- projectId: client?.projectId || page.id || "weaverse-next",
270
- data: page
1098
+ return createWeaverseNextRuntime({
1099
+ client,
1100
+ data: { ...data, page },
1101
+ dataContext,
1102
+ merchantOverrides: context?.merchantOverrides,
1103
+ themeSettingsStore: context?.themeSettingsStore,
1104
+ translationStore: context?.translationStore
271
1105
  });
272
- instance.dataContext = dataContext;
273
- instance.isDesignMode = client?.requestContext?.isDesignMode ?? false;
274
- return instance;
275
1106
  }, [
276
- client?.projectId,
277
- client?.requestContext?.isDesignMode,
1107
+ client,
278
1108
  page,
279
- dataContext
1109
+ data,
1110
+ dataContext,
1111
+ context?.merchantOverrides,
1112
+ context?.themeSettingsStore,
1113
+ context?.translationStore
280
1114
  ]);
1115
+ useIsomorphicLayoutEffect(() => {
1116
+ weaverse?.flushRenderPhaseUpdates();
1117
+ }, [weaverse]);
281
1118
  if (!weaverse) {
282
1119
  return null;
283
1120
  }
284
- return /* @__PURE__ */ jsxRuntime.jsx(react.WeaverseRoot, { context: weaverse });
1121
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1122
+ /* @__PURE__ */ jsxRuntime.jsx(react.WeaverseRoot, { context: weaverse }),
1123
+ /* @__PURE__ */ jsxRuntime.jsx(WeaverseNextStudio, { runtime: weaverse })
1124
+ ] });
285
1125
  });
286
1126
 
1127
+ // src/seo.ts
1128
+ function hasOpenGraphContent(seo) {
1129
+ return Boolean(seo?.title || seo?.description || seo?.image || seo?.type);
1130
+ }
1131
+ function hasTwitterContent(seo) {
1132
+ return Boolean(seo?.title || seo?.description || seo?.image || seo?.cardType);
1133
+ }
1134
+ function formatWeaverseNextSeoMetadata(seo) {
1135
+ let index = seo?.robots?.index !== false;
1136
+ let follow = seo?.robots?.follow !== false;
1137
+ let metadata = {
1138
+ robots: { index, follow }
1139
+ };
1140
+ if (!seo) {
1141
+ return metadata;
1142
+ }
1143
+ if (seo.title) {
1144
+ metadata.title = seo.title;
1145
+ }
1146
+ if (seo.description) {
1147
+ metadata.description = seo.description;
1148
+ }
1149
+ if (seo.keywords) {
1150
+ metadata.keywords = seo.keywords;
1151
+ }
1152
+ if (seo.canonicalUrl) {
1153
+ metadata.alternates = { canonical: seo.canonicalUrl };
1154
+ }
1155
+ let openGraph = seo.openGraph;
1156
+ if (hasOpenGraphContent(openGraph)) {
1157
+ metadata.openGraph = {
1158
+ title: openGraph?.title,
1159
+ description: openGraph?.description,
1160
+ images: openGraph?.image ? [openGraph.image] : void 0,
1161
+ type: openGraph?.type || "website"
1162
+ };
1163
+ }
1164
+ let twitter = seo.twitter;
1165
+ if (hasTwitterContent(twitter)) {
1166
+ metadata.twitter = {
1167
+ card: twitter?.cardType || "summary",
1168
+ title: twitter?.title,
1169
+ description: twitter?.description,
1170
+ images: twitter?.image ? [twitter.image] : void 0
1171
+ };
1172
+ }
1173
+ return metadata;
1174
+ }
1175
+ function getWeaverseNextSeoMetadata(data) {
1176
+ if (!data) {
1177
+ return formatWeaverseNextSeoMetadata(null);
1178
+ }
1179
+ let page = "items" in data && "id" in data ? data : data.page ?? null;
1180
+ return formatWeaverseNextSeoMetadata(page?.seo ?? null);
1181
+ }
1182
+
1183
+ // src/studio-script-src.ts
1184
+ var TRUSTED_STUDIO_DOMAINS = ["weaverse.io", "weaverse.dev"];
1185
+ function isLoopbackHostname(hostname) {
1186
+ return hostname === "localhost" || hostname === "127.0.0.1" || hostname.endsWith(".localhost");
1187
+ }
1188
+ function normalizeOrigin(value) {
1189
+ if (!value) {
1190
+ return null;
1191
+ }
1192
+ try {
1193
+ return new URL(value).origin;
1194
+ } catch {
1195
+ return null;
1196
+ }
1197
+ }
1198
+ function isTrustedStudioOrigin(origin, storefrontHostname) {
1199
+ let parsed;
1200
+ try {
1201
+ parsed = new URL(origin);
1202
+ } catch {
1203
+ return false;
1204
+ }
1205
+ let { hostname, protocol } = parsed;
1206
+ if (isLoopbackHostname(storefrontHostname) && isLoopbackHostname(hostname)) {
1207
+ return protocol === "http:" || protocol === "https:";
1208
+ }
1209
+ if (protocol !== "https:") {
1210
+ return false;
1211
+ }
1212
+ return TRUSTED_STUDIO_DOMAINS.some(
1213
+ (domain) => hostname === domain || hostname.endsWith(`.${domain}`)
1214
+ );
1215
+ }
1216
+ function toSearchParams(context) {
1217
+ if (context?.searchParams) {
1218
+ return new URLSearchParams(context.searchParams);
1219
+ }
1220
+ if (context?.url) {
1221
+ let url = typeof context.url === "string" ? new URL(context.url, "http://localhost") : context.url;
1222
+ return new URLSearchParams(url.searchParams);
1223
+ }
1224
+ return new URLSearchParams();
1225
+ }
1226
+ function last(searchParams, key) {
1227
+ let values = searchParams.getAll(key);
1228
+ return values.length ? values.at(-1) ?? null : null;
1229
+ }
1230
+ function resolveWeaverseNextStudioScriptSrc(context, options = {}) {
1231
+ let searchParams = toSearchParams(context);
1232
+ let isDesignMode = context?.isDesignMode ?? last(searchParams, "isDesignMode") === "true";
1233
+ let isPreviewMode = context?.isPreviewMode ?? last(searchParams, "isPreviewMode") === "true";
1234
+ let isRevisionPreview = context?.isRevisionPreview ?? Boolean(last(searchParams, "__revisionId"));
1235
+ if (!(isDesignMode || isPreviewMode || isRevisionPreview)) {
1236
+ return null;
1237
+ }
1238
+ let origin = normalizeOrigin(last(searchParams, "weaverseHost"));
1239
+ if (!origin) {
1240
+ return null;
1241
+ }
1242
+ let storefrontHostname = options.storefrontHostname ?? "";
1243
+ if (!isTrustedStudioOrigin(origin, storefrontHostname)) {
1244
+ return null;
1245
+ }
1246
+ let bundle = isDesignMode ? "index.js" : "preview.js";
1247
+ let version = last(searchParams, "weaverseVersion");
1248
+ let url = `${origin}/static/studio/next/${bundle}`;
1249
+ return version ? `${url}?v=${encodeURIComponent(version)}` : url;
1250
+ }
1251
+
1252
+ // src/studio-connect.tsx
1253
+ var loadedScriptSrcs = /* @__PURE__ */ new Set();
1254
+ function loadScript(src) {
1255
+ if (typeof document === "undefined") {
1256
+ return;
1257
+ }
1258
+ if (loadedScriptSrcs.has(src)) {
1259
+ return;
1260
+ }
1261
+ let existing = document.querySelector(`script[src="${src}"]`);
1262
+ if (existing) {
1263
+ loadedScriptSrcs.add(src);
1264
+ return;
1265
+ }
1266
+ let script = document.createElement("script");
1267
+ script.async = true;
1268
+ script.src = src;
1269
+ document.head.appendChild(script);
1270
+ loadedScriptSrcs.add(src);
1271
+ }
1272
+ function loadWeaverseNextStudioScript(context, options = {}) {
1273
+ let resolvedContext = context;
1274
+ if (!resolvedContext && typeof window !== "undefined") {
1275
+ resolvedContext = {
1276
+ searchParams: new URLSearchParams(window.location.search),
1277
+ url: window.location.href
1278
+ };
1279
+ }
1280
+ let src = resolveWeaverseNextStudioScriptSrc(resolvedContext, {
1281
+ storefrontHostname: options.storefrontHostname ?? (typeof window === "undefined" ? void 0 : window.location.hostname)
1282
+ });
1283
+ if (src) {
1284
+ loadScript(src);
1285
+ }
1286
+ }
1287
+ function WeaverseNextStudioConnect(props) {
1288
+ react$1.useEffect(() => {
1289
+ loadWeaverseNextStudioScript(props.context, {
1290
+ storefrontHostname: props.storefrontHostname
1291
+ });
1292
+ }, [props.context, props.storefrontHostname]);
1293
+ return null;
1294
+ }
1295
+
287
1296
  Object.defineProperty(exports, "isBrowser", {
288
1297
  enumerable: true,
289
1298
  get: function () { return react.isBrowser; }
@@ -308,17 +1317,46 @@ Object.defineProperty(exports, "useWeaverse", {
308
1317
  enumerable: true,
309
1318
  get: function () { return react.useWeaverse; }
310
1319
  });
311
- Object.defineProperty(exports, "createSchema", {
312
- enumerable: true,
313
- get: function () { return schema.createSchema; }
314
- });
1320
+ exports.DEFAULT_REVALIDATE_ENDPOINT = DEFAULT_REVALIDATE_ENDPOINT;
1321
+ exports.ThemeTextProvider = ThemeTextProvider;
1322
+ exports.ThemeTextStore = ThemeTextStore;
1323
+ exports.TranslationProvider = TranslationProvider;
1324
+ exports.TranslationStore = TranslationStore;
315
1325
  exports.WeaverseNextProvider = WeaverseNextProvider;
316
1326
  exports.WeaverseNextRenderer = WeaverseNextRenderer;
1327
+ exports.WeaverseNextRootProvider = WeaverseNextRootProvider;
1328
+ exports.WeaverseNextRuntime = WeaverseNextRuntime;
1329
+ exports.WeaverseNextStudio = WeaverseNextStudio;
1330
+ exports.WeaverseNextStudioBridge = WeaverseNextStudioBridge;
1331
+ exports.WeaverseNextStudioConnect = WeaverseNextStudioConnect;
1332
+ exports.bindWeaverseNextStudioRuntime = bindWeaverseNextStudioRuntime;
1333
+ exports.buildWeaverseNextRequestInfo = buildWeaverseNextRequestInfo;
1334
+ exports.createTranslate = createTranslate;
317
1335
  exports.createWeaverseNextClient = createWeaverseNextClient;
1336
+ exports.createWeaverseNextRuntime = createWeaverseNextRuntime;
1337
+ exports.createWeaverseNextStudioInternals = createWeaverseNextStudioInternals;
1338
+ exports.createWeaverseNextThemeSettingsStore = createWeaverseNextThemeSettingsStore;
1339
+ exports.formatWeaverseNextSeoMetadata = formatWeaverseNextSeoMetadata;
1340
+ exports.generateDataFromSchema = generateDataFromSchema;
1341
+ exports.getNestedKey = getNestedKey;
1342
+ exports.getWeaverseNextSeoMetadata = getWeaverseNextSeoMetadata;
1343
+ exports.interpolate = interpolate;
1344
+ exports.loadWeaverseNextStudioScript = loadWeaverseNextStudioScript;
1345
+ exports.resolveWeaverseNextStudioScriptSrc = resolveWeaverseNextStudioScriptSrc;
1346
+ exports.revalidateWeaverseNextItem = revalidateWeaverseNextItem;
318
1347
  exports.runWeaverseComponentLoaders = runWeaverseComponentLoaders;
319
1348
  exports.useThemeSettings = useThemeSettings;
1349
+ exports.useThemeText = useThemeText;
1350
+ exports.useTranslation = useTranslation;
320
1351
  exports.useWeaverseCommerce = useWeaverseCommerce;
1352
+ exports.useWeaverseNextStudioInternals = useWeaverseNextStudioInternals;
321
1353
  exports.useWeaversePageData = useWeaversePageData;
322
1354
  exports.useWeaverseRootData = useWeaverseRootData;
1355
+ Object.keys(schema).forEach(function (k) {
1356
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
1357
+ enumerable: true,
1358
+ get: function () { return schema[k]; }
1359
+ });
1360
+ });
323
1361
  //# sourceMappingURL=index.js.map
324
1362
  //# sourceMappingURL=index.js.map