@weaverse/next 0.1.0-alpha.7 → 0.1.0-alpha.9

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
@@ -27,13 +27,84 @@ function generateDataFromSchema(schema) {
27
27
  }
28
28
 
29
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
+ }
30
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;
31
57
  constructor(initialData, weaverse) {
32
58
  super(initialData, weaverse);
33
- let { data, ...rest } = initialData;
34
59
  let schemaData = generateDataFromSchema(this.Element?.schema);
35
- Object.assign(this._store, schemaData, data, rest);
60
+ Object.assign(this._store, schemaData, flattenItemData(initialData));
36
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
+ };
37
108
  };
38
109
  function ensureNextItemConstructor() {
39
110
  if (!react.Weaverse.ItemConstructor || react.Weaverse.ItemConstructor === react.WeaverseItemStore || react.Weaverse.ItemConstructor === WeaverseNextItem) {
@@ -158,9 +229,136 @@ function createWeaverseNextThemeSettingsStore(options = {}) {
158
229
  };
159
230
  return store;
160
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;
161
351
  var WeaverseNextRootContext = react$1.createContext(null);
162
352
  function WeaverseNextRootProvider(props) {
163
- let { children, initialThemeSettings, themeSchema, publicEnv } = props;
353
+ let {
354
+ children,
355
+ initialThemeSettings,
356
+ merchantOverrides,
357
+ staticContent,
358
+ t,
359
+ themeSchema,
360
+ publicEnv
361
+ } = props;
164
362
  let storeRef = react$1.useRef(null);
165
363
  if (!storeRef.current) {
166
364
  storeRef.current = createWeaverseNextThemeSettingsStore({
@@ -170,6 +368,11 @@ function WeaverseNextRootProvider(props) {
170
368
  });
171
369
  }
172
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;
173
376
  let appliedThemeSettingsRef = react$1.useRef(initialThemeSettings);
174
377
  react$1.useEffect(() => {
175
378
  if (initialThemeSettings && appliedThemeSettingsRef.current !== initialThemeSettings) {
@@ -177,25 +380,59 @@ function WeaverseNextRootProvider(props) {
177
380
  appliedThemeSettingsRef.current = initialThemeSettings;
178
381
  }
179
382
  }, [initialThemeSettings, themeSettingsStore]);
383
+ let resolvedStaticContent = staticContent ?? getSchemaStaticContent(themeSchema);
180
384
  let rootContextValue = react$1.useMemo(
181
- () => ({ themeSettingsStore }),
182
- [themeSettingsStore]
385
+ () => ({
386
+ merchantOverrides,
387
+ staticContent: resolvedStaticContent,
388
+ themeSettingsStore,
389
+ translationStore
390
+ }),
391
+ [
392
+ merchantOverrides,
393
+ resolvedStaticContent,
394
+ themeSettingsStore,
395
+ translationStore
396
+ ]
183
397
  );
184
398
  let contextValue = react$1.useMemo(
185
399
  () => ({
400
+ merchantOverrides,
186
401
  themeSettings: themeSettingsStore.getSnapshot(),
187
- themeSettingsStore
402
+ themeSettingsStore,
403
+ translationStore
188
404
  }),
189
- [themeSettingsStore]
405
+ [merchantOverrides, themeSettingsStore, translationStore]
190
406
  );
191
- return /* @__PURE__ */ jsxRuntime.jsx(WeaverseNextRootContext.Provider, { value: rootContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(WeaverseNextContext.Provider, { value: contextValue, children }) });
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
+ ) }) });
192
417
  }
193
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
+ }
194
424
  var WeaverseNextContext = react$1.createContext(null);
195
425
  function WeaverseNextProvider(props) {
196
426
  let { children, client, rootData, pageData, commerce, themeSettings } = props;
197
427
  let rootContext = react$1.useContext(WeaverseNextRootContext);
198
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;
199
436
  let ownThemeSettingsStore = react$1.useMemo(() => {
200
437
  if (rootContext) {
201
438
  return null;
@@ -219,12 +456,31 @@ function WeaverseNextProvider(props) {
219
456
  rootData,
220
457
  pageData,
221
458
  commerce: commerce ?? client?.commerce,
459
+ merchantOverrides,
222
460
  themeSettings: themeSettingsStore.getSnapshot(),
223
- themeSettingsStore
461
+ themeSettingsStore,
462
+ translationStore
224
463
  }),
225
- [client, rootData, pageData, commerce, themeSettingsStore]
464
+ [
465
+ client,
466
+ rootData,
467
+ pageData,
468
+ commerce,
469
+ merchantOverrides,
470
+ themeSettingsStore,
471
+ translationStore
472
+ ]
226
473
  );
227
- 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
+ ) });
228
484
  }
229
485
 
230
486
  // src/hooks.ts
@@ -452,9 +708,31 @@ var WeaverseNextRuntime = class extends react.Weaverse {
452
708
  isPreviewMode;
453
709
  isRevisionPreview;
454
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
+ */
455
717
  translationMap = {};
456
- translationLocale = "";
457
- translationLanguageId = "";
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 = [];
458
736
  constructor(config) {
459
737
  let { client, data } = config;
460
738
  let page = getRenderablePage(data);
@@ -476,7 +754,9 @@ var WeaverseNextRuntime = class extends react.Weaverse {
476
754
  this.isPreviewMode = requestContext?.isPreviewMode ?? false;
477
755
  this.isRevisionPreview = requestContext?.isRevisionPreview ?? false;
478
756
  this.sectionType = requestContext?.sectionType;
757
+ let translationStore = config.translationStore ?? new TranslationStore();
479
758
  this.internal = {
759
+ merchantOverrides: config.merchantOverrides,
480
760
  navigate: config.navigate,
481
761
  pageAssignment: data.pageAssignment,
482
762
  project: data.project,
@@ -484,17 +764,119 @@ var WeaverseNextRuntime = class extends react.Weaverse {
484
764
  themeSettingsStore: config.themeSettingsStore ?? createWeaverseNextThemeSettingsStore({
485
765
  schema: client?.themeSchema,
486
766
  settings: client?.themeSettings
487
- })
767
+ }),
768
+ translationStore,
769
+ themeTextStore: translationStore
488
770
  };
771
+ this.extractTranslationSidecar();
489
772
  }
490
- extractTranslationSidecar = () => void 0;
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
+ */
491
798
  setTranslationSidecar = (map = {}, locale = "", languageId = "") => {
492
799
  this.translationMap = map;
493
800
  this.translationLocale = locale;
494
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
+ }
495
879
  };
496
- updateTranslation = () => void 0;
497
- getTranslationChanges = () => void 0;
498
880
  };
499
881
  function createWeaverseNextRuntime(config) {
500
882
  let requestInfo = buildWeaverseNextRequestInfo(config.client?.requestContext);
@@ -504,8 +886,10 @@ function createWeaverseNextRuntime(config) {
504
886
  let requestKey = getRuntimeKey(page.id, requestInfo);
505
887
  if (existing?.__weaverseNextRequestKey === requestKey) {
506
888
  let nextIsDesignMode = config.client?.requestContext?.isDesignMode ?? false;
507
- if (!(existing.isDesignMode || nextIsDesignMode)) {
508
- existing.setProjectData(page);
889
+ if (existing.isDesignMode || nextIsDesignMode) {
890
+ existing.pendingProjectData = void 0;
891
+ } else {
892
+ existing.pendingProjectData = page;
509
893
  }
510
894
  existing.__weaverseNextLatestData = page;
511
895
  existing.dataContext = resolveDataContext(config);
@@ -528,10 +912,18 @@ function createWeaverseNextRuntime(config) {
528
912
  if (config.themeSettingsStore) {
529
913
  existing.internal.themeSettingsStore = config.themeSettingsStore;
530
914
  }
915
+ if (config.translationStore) {
916
+ existing.internal.translationStore = config.translationStore;
917
+ existing.internal.themeTextStore = config.translationStore;
918
+ }
919
+ existing.internal.merchantOverrides = config.merchantOverrides;
531
920
  registerRuntime(existing);
532
921
  return existing;
533
922
  }
534
- let runtime = new WeaverseNextRuntime(config);
923
+ let [runtime, refreshedItems] = collectDeferredItemUpdates(
924
+ () => new WeaverseNextRuntime(config)
925
+ );
926
+ runtime.pendingItemUpdates = refreshedItems;
535
927
  runtime.__weaverseNextRequestKey = requestKey;
536
928
  runtime.__weaverseNextLatestData = page;
537
929
  registerRuntime(runtime);
@@ -684,6 +1076,7 @@ function WeaverseNextStudio(props) {
684
1076
  );
685
1077
  }
686
1078
  var EMPTY_DATA_CONTEXT = {};
1079
+ var useIsomorphicLayoutEffect = typeof window === "undefined" ? react$1.useEffect : react$1.useLayoutEffect;
687
1080
  function getRenderablePage2(data) {
688
1081
  let page = data?.page;
689
1082
  if (!page) {
@@ -706,9 +1099,22 @@ var WeaverseNextRenderer = react$1.memo(function WeaverseNextRendererComponent(p
706
1099
  client,
707
1100
  data: { ...data, page },
708
1101
  dataContext,
709
- themeSettingsStore: context?.themeSettingsStore
1102
+ merchantOverrides: context?.merchantOverrides,
1103
+ themeSettingsStore: context?.themeSettingsStore,
1104
+ translationStore: context?.translationStore
710
1105
  });
711
- }, [client, page, data, dataContext, context?.themeSettingsStore]);
1106
+ }, [
1107
+ client,
1108
+ page,
1109
+ data,
1110
+ dataContext,
1111
+ context?.merchantOverrides,
1112
+ context?.themeSettingsStore,
1113
+ context?.translationStore
1114
+ ]);
1115
+ useIsomorphicLayoutEffect(() => {
1116
+ weaverse?.flushRenderPhaseUpdates();
1117
+ }, [weaverse]);
712
1118
  if (!weaverse) {
713
1119
  return null;
714
1120
  }
@@ -916,6 +1322,10 @@ Object.defineProperty(exports, "createSchema", {
916
1322
  get: function () { return schema.createSchema; }
917
1323
  });
918
1324
  exports.DEFAULT_REVALIDATE_ENDPOINT = DEFAULT_REVALIDATE_ENDPOINT;
1325
+ exports.ThemeTextProvider = ThemeTextProvider;
1326
+ exports.ThemeTextStore = ThemeTextStore;
1327
+ exports.TranslationProvider = TranslationProvider;
1328
+ exports.TranslationStore = TranslationStore;
919
1329
  exports.WeaverseNextProvider = WeaverseNextProvider;
920
1330
  exports.WeaverseNextRenderer = WeaverseNextRenderer;
921
1331
  exports.WeaverseNextRootProvider = WeaverseNextRootProvider;
@@ -925,17 +1335,22 @@ exports.WeaverseNextStudioBridge = WeaverseNextStudioBridge;
925
1335
  exports.WeaverseNextStudioConnect = WeaverseNextStudioConnect;
926
1336
  exports.bindWeaverseNextStudioRuntime = bindWeaverseNextStudioRuntime;
927
1337
  exports.buildWeaverseNextRequestInfo = buildWeaverseNextRequestInfo;
1338
+ exports.createTranslate = createTranslate;
928
1339
  exports.createWeaverseNextClient = createWeaverseNextClient;
929
1340
  exports.createWeaverseNextRuntime = createWeaverseNextRuntime;
930
1341
  exports.createWeaverseNextStudioInternals = createWeaverseNextStudioInternals;
931
1342
  exports.createWeaverseNextThemeSettingsStore = createWeaverseNextThemeSettingsStore;
932
1343
  exports.formatWeaverseNextSeoMetadata = formatWeaverseNextSeoMetadata;
1344
+ exports.getNestedKey = getNestedKey;
933
1345
  exports.getWeaverseNextSeoMetadata = getWeaverseNextSeoMetadata;
1346
+ exports.interpolate = interpolate;
934
1347
  exports.loadWeaverseNextStudioScript = loadWeaverseNextStudioScript;
935
1348
  exports.resolveWeaverseNextStudioScriptSrc = resolveWeaverseNextStudioScriptSrc;
936
1349
  exports.revalidateWeaverseNextItem = revalidateWeaverseNextItem;
937
1350
  exports.runWeaverseComponentLoaders = runWeaverseComponentLoaders;
938
1351
  exports.useThemeSettings = useThemeSettings;
1352
+ exports.useThemeText = useThemeText;
1353
+ exports.useTranslation = useTranslation;
939
1354
  exports.useWeaverseCommerce = useWeaverseCommerce;
940
1355
  exports.useWeaverseNextStudioInternals = useWeaverseNextStudioInternals;
941
1356
  exports.useWeaversePageData = useWeaversePageData;