@valbuild/tanstack 0.139.2 → 0.140.2

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 (29) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +51 -4
  3. package/client/dist/valbuild-tanstack-client.cjs.dev.js +53 -6
  4. package/client/dist/valbuild-tanstack-client.cjs.prod.js +53 -6
  5. package/client/dist/valbuild-tanstack-client.esm.js +53 -6
  6. package/dist/{ValOverlayContext-5f1d8da4.cjs.prod.js → ValOverlayContext-2739cc60.cjs.prod.js} +4 -2
  7. package/dist/{ValOverlayContext-5bc3830f.esm.js → ValOverlayContext-28101df3.esm.js} +4 -2
  8. package/dist/{ValOverlayContext-3ec15518.cjs.dev.js → ValOverlayContext-bafe3de9.cjs.dev.js} +4 -2
  9. package/dist/{createForOfIteratorHelper-e75681d7.cjs.dev.js → createForOfIteratorHelper-4497beef.cjs.dev.js} +2 -0
  10. package/dist/{createForOfIteratorHelper-485c2ce1.esm.js → createForOfIteratorHelper-93a62170.esm.js} +1 -1
  11. package/dist/{createForOfIteratorHelper-0324e063.cjs.prod.js → createForOfIteratorHelper-9afd7d2d.cjs.prod.js} +2 -0
  12. package/dist/declarations/src/ValDraft.d.ts +21 -0
  13. package/dist/declarations/src/ValProvider.d.ts +1 -0
  14. package/dist/declarations/src/external_exempt_from_val_quickjs.d.ts +1 -0
  15. package/dist/declarations/src/server/index.d.ts +1 -0
  16. package/dist/declarations/src/server/initValContent.d.ts +30 -0
  17. package/dist/{routeFromVal-6693e037.cjs.prod.js → routeFromVal-0b39e8e3.cjs.prod.js} +1 -1
  18. package/dist/{routeFromVal-728295a0.esm.js → routeFromVal-1221e70d.esm.js} +1 -1
  19. package/dist/{routeFromVal-a9147ceb.cjs.dev.js → routeFromVal-97111bfd.cjs.dev.js} +1 -1
  20. package/dist/valbuild-tanstack.cjs.dev.js +50 -12
  21. package/dist/valbuild-tanstack.cjs.prod.js +50 -12
  22. package/dist/valbuild-tanstack.esm.js +50 -12
  23. package/dist/{version-d0b1c2c5.esm.js → version-6d26340d.esm.js} +1 -1
  24. package/dist/{version-f6f044c2.cjs.prod.js → version-7dd0b309.cjs.dev.js} +1 -1
  25. package/dist/{version-4cc54e05.cjs.dev.js → version-a29cfb8e.cjs.prod.js} +1 -1
  26. package/package.json +7 -7
  27. package/server/dist/valbuild-tanstack-server.cjs.dev.js +478 -152
  28. package/server/dist/valbuild-tanstack-server.cjs.prod.js +478 -152
  29. package/server/dist/valbuild-tanstack-server.esm.js +479 -153
@@ -3,6 +3,7 @@ import { ValConfig, ValModules, type ResolvableModule } from "@valbuild/core";
3
3
  import { type RequestScopedMemo } from "@valbuild/shared/internal";
4
4
  import { ValServer, type ValPatchStore } from "@valbuild/server";
5
5
  import { type ValDraftMode } from "./valDraftMode.js";
6
+ import type { ValDraft } from "../ValDraft.js";
6
7
  import type { ValHttpMode } from "./initValServer.js";
7
8
  /**
8
9
  * The `modules` map every `fetchVal` in one request shares.
@@ -58,6 +59,30 @@ export declare const initFetchValStega: (config: ValConfig, valApiEndpoints: str
58
59
  value: string;
59
60
  } | undefined;
60
61
  }>, getDraftSourcesScope: GetDraftSourcesScope) => <T extends Resolvable>(selector: T) => Promise<ResolvedVal<T>>;
62
+ /** What `fetchValDraft` reads: the tree, the entries, and the patches' ops. */
63
+ export type DraftValServer = {
64
+ "/sources/~": ValServer["/sources/~"];
65
+ "/json": ValServer["/json"];
66
+ "/patches": Pick<ValServer["/patches"], "GET">;
67
+ };
68
+ /**
69
+ * The draft a page in this request should start from, or `null` for none.
70
+ *
71
+ * `null` -- and no read at all -- unless draft mode is on: a visitor pays one
72
+ * cookie lookup. Otherwise the SAME read every
73
+ * `fetchVal` in the request shares (`loadDraftSources`, memoised per request),
74
+ * cut down to the modules the draft changes. See `ValDraft`.
75
+ *
76
+ * Exists because the hooks render on the server too, and had no draft there:
77
+ * a draft page was rendered as the published site and only then replaced, in
78
+ * the browser, by what the editor holds -- old text first on every load.
79
+ */
80
+ export declare const initFetchValDraft: (valServerPromise: Promise<DraftValServer>, isEnabled: () => Promise<boolean>, getCookies: () => Promise<{
81
+ get(name: string): {
82
+ name: string;
83
+ value: string;
84
+ } | undefined;
85
+ }>, getDraftSourcesScope: GetDraftSourcesScope) => () => Promise<ValDraft | null>;
61
86
  declare const initFetchValRouteStega: (config: ValConfig, valApiEndpoints: string, valServerPromise: Promise<RouteReaderValServer>, isEnabled: () => Promise<boolean>, getHeaders: () => Promise<{
62
87
  get(name: string): string | null;
63
88
  }>, getCookies: () => Promise<{
@@ -216,5 +241,10 @@ export declare function initValContent(config: ValConfig, valModules: ValModules
216
241
  fetchValKeyStega: ReturnType<typeof initFetchValKeyStega>;
217
242
  fetchValRouteStega: ReturnType<typeof initFetchValRouteStega>;
218
243
  fetchValRouteUrl: ReturnType<typeof initFetchValRouteUrl>;
244
+ /**
245
+ * The draft for `<ValProvider draft>`, or `null`. Call it from a server
246
+ * function in the site layout's loader -- see `ValDraft`.
247
+ */
248
+ fetchValDraft: ReturnType<typeof initFetchValDraft>;
219
249
  };
220
250
  export {};
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var createForOfIteratorHelper = require('./createForOfIteratorHelper-0324e063.cjs.prod.js');
3
+ var createForOfIteratorHelper = require('./createForOfIteratorHelper-9afd7d2d.cjs.prod.js');
4
4
  var core = require('@valbuild/core');
5
5
  var client = require('@valbuild/shared/client');
6
6
 
@@ -1,4 +1,4 @@
1
- import { a as _slicedToArray, _ as _objectSpread2, b as _createForOfIteratorHelper } from './createForOfIteratorHelper-485c2ce1.esm.js';
1
+ import { a as _slicedToArray, _ as _objectSpread2, b as _createForOfIteratorHelper } from './createForOfIteratorHelper-93a62170.esm.js';
2
2
  import { RecordSchema, Internal } from '@valbuild/core';
3
3
  import { getTanStackRouterSourceFolder, getPatternFromModuleFilePath, parseRoutePattern } from '@valbuild/shared/client';
4
4
 
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var createForOfIteratorHelper = require('./createForOfIteratorHelper-e75681d7.cjs.dev.js');
3
+ var createForOfIteratorHelper = require('./createForOfIteratorHelper-4497beef.cjs.dev.js');
4
4
  var core = require('@valbuild/core');
5
5
  var client = require('@valbuild/shared/client');
6
6
 
@@ -2,15 +2,15 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var version = require('./version-4cc54e05.cjs.dev.js');
6
- var createForOfIteratorHelper = require('./createForOfIteratorHelper-e75681d7.cjs.dev.js');
5
+ var version = require('./version-7dd0b309.cjs.dev.js');
6
+ var createForOfIteratorHelper = require('./createForOfIteratorHelper-4497beef.cjs.dev.js');
7
7
  var core = require('@valbuild/core');
8
8
  var stega = require('@valbuild/react/stega');
9
9
  var internal = require('@valbuild/react/internal');
10
10
  var ui = require('@valbuild/ui');
11
11
  var reactRouter = require('@tanstack/react-router');
12
12
  var React = require('react');
13
- var ValOverlayContext = require('./ValOverlayContext-3ec15518.cjs.dev.js');
13
+ var ValOverlayContext = require('./ValOverlayContext-bafe3de9.cjs.dev.js');
14
14
  var client = require('@valbuild/shared/client');
15
15
  var jsxRuntime = require('react/jsx-runtime');
16
16
  require('@valbuild/core/patch');
@@ -856,6 +856,16 @@ function shouldSafetyRefresh(state) {
856
856
  return true;
857
857
  }
858
858
 
859
+ /**
860
+ * Shows the Overlay menu and updates the store which the client side useVal hook uses to display data.
861
+ */
862
+ /**
863
+ * The floor between server re-renders.
864
+ *
865
+ * `router.invalidate()` re-runs every loader of the current match tree — there
866
+ * is no per-module invalidation — so this is about not queueing a round trip
867
+ * per keystroke, not about batching for its own sake.
868
+ */
859
869
  var REFRESH_INTERVAL_MS = 500;
860
870
 
861
871
  /**
@@ -927,7 +937,7 @@ var DRAFT_HANDSHAKE_POLL_MS = 100;
927
937
  */
928
938
  var DRAFT_HANDSHAKE_TIMEOUT_MS = 10000;
929
939
  var ValTanStackProvider = function ValTanStackProvider(props) {
930
- var _draftModeReady$curre2;
940
+ var _props$draft, _draftModeReady$curre2;
931
941
  // TODO: use config:
932
942
  var route = "/api/val";
933
943
  /**
@@ -967,15 +977,35 @@ var ValTanStackProvider = function ValTanStackProvider(props) {
967
977
  }, _callee);
968
978
  })), [route]);
969
979
 
980
+ /**
981
+ * The draft the page was rendered with, as it was at mount.
982
+ *
983
+ * A ref, not the prop: the server and the browser's first render must start
984
+ * from the same thing, and a later prop -- the loader running again on a
985
+ * client navigation, where it reads nothing -- must not reset a store the
986
+ * overlay has been updating since.
987
+ */
988
+ var initialDraft = React__default["default"].useRef((_props$draft = props.draft) !== null && _props$draft !== void 0 ? _props$draft : null).current;
970
989
  // TODO: move below into react package
971
990
  var valStore = React__default["default"].useMemo(function () {
972
- return new ValOverlayContext.ValExternalStore();
973
- }, []);
991
+ var store = new ValOverlayContext.ValExternalStore();
992
+ if (initialDraft !== null) {
993
+ for (var _i = 0, _Object$entries = Object.entries(initialDraft.sources); _i < _Object$entries.length; _i++) {
994
+ var _Object$entries$_i = createForOfIteratorHelper._slicedToArray(_Object$entries[_i], 2),
995
+ path = _Object$entries$_i[0],
996
+ source = _Object$entries$_i[1];
997
+ store.update(path, source);
998
+ }
999
+ }
1000
+ return store;
1001
+ }, [initialDraft]);
974
1002
  // Whether useValStega should actually suspend. False during SSR and the
975
- // hydration render — the server store is never populated (draft data
976
- // arrives via browser CustomEvents only), so suspending there would just
977
- // stall into the waitForLoad timeout, and hydration must render the static
978
- // source so it matches the server HTML exactly. Activated post-hydration
1003
+ // hydration render. Two paths: without `draft` the server store is empty
1004
+ // (draft data arrives via browser CustomEvents only), so suspending there
1005
+ // would just stall into the waitForLoad timeout, and hydration must render
1006
+ // the static source so it matches the server HTML exactly; with `draft` the
1007
+ // store is seeded above on BOTH sides, so SSR and hydration already render
1008
+ // the draft and there is nothing to wait for. Keep the seed if this changes. Activated post-hydration
979
1009
  // (in an effect, only when the Val Enable cookie is present) inside a
980
1010
  // transition: React keeps the static content visible while hooks suspend
981
1011
  // and then swaps to draft data as a normal update — no Suspense fallback
@@ -992,7 +1022,9 @@ var ValTanStackProvider = function ValTanStackProvider(props) {
992
1022
  * protocol. Without this the page could only wait out `waitForLoad`'s timeout,
993
1023
  * ten seconds per module nobody had edited.
994
1024
  */
995
- var _React$useState3 = React__default["default"].useState(false),
1025
+ // A server-read draft is everything there is: a module missing from it has
1026
+ // no changes, so there is nothing more to wait for.
1027
+ var _React$useState3 = React__default["default"].useState(initialDraft !== null),
996
1028
  _React$useState4 = createForOfIteratorHelper._slicedToArray(_React$useState3, 2),
997
1029
  draftSourcesSynced = _React$useState4[0],
998
1030
  setDraftSourcesSynced = _React$useState4[1];
@@ -1017,7 +1049,9 @@ var ValTanStackProvider = function ValTanStackProvider(props) {
1017
1049
  _React$useState8 = createForOfIteratorHelper._slicedToArray(_React$useState7, 2),
1018
1050
  isCanvas = _React$useState8[0],
1019
1051
  setIsCanvas = _React$useState8[1];
1020
- var _React$useState9 = React__default["default"].useState(null),
1052
+ // Known on the server when it read a draft: `fetchValDraft` only reads one
1053
+ // in draft mode. Otherwise unknown until `/draft/stat` answers.
1054
+ var _React$useState9 = React__default["default"].useState(initialDraft !== null ? true : null),
1021
1055
  _React$useState0 = createForOfIteratorHelper._slicedToArray(_React$useState9, 2),
1022
1056
  draftMode = _React$useState0[0],
1023
1057
  setDraftMode = _React$useState0[1];
@@ -1380,6 +1414,9 @@ var ValTanStackProvider = function ValTanStackProvider(props) {
1380
1414
  stega.SET_AUTO_TAG_JSX_ENABLED(false);
1381
1415
  } else {
1382
1416
  if (draftMode) {
1417
+ // Safe for a page rendered from a server draft too: what a component
1418
+ // renders while it hydrates has no edit tags to turn into attributes
1419
+ // (`useEncodesEditTags`), so this cannot reach one still hydrating.
1383
1420
  stega.SET_AUTO_TAG_JSX_ENABLED(true);
1384
1421
  var reactServerComponentRefreshListener = function reactServerComponentRefreshListener(event) {
1385
1422
  if (event instanceof CustomEvent) {
@@ -1513,6 +1550,7 @@ var ValTanStackProvider = function ValTanStackProvider(props) {
1513
1550
  draftMode: draftMode,
1514
1551
  draftModeReady: (_draftModeReady$curre2 = draftModeReady.current) === null || _draftModeReady$curre2 === void 0 ? void 0 : _draftModeReady$curre2.promise,
1515
1552
  draftSourcesSynced: draftSourcesSynced,
1553
+ serverDraft: initialDraft !== null,
1516
1554
  suspend: suspendActive,
1517
1555
  store: valStore,
1518
1556
  children: [props.children, dropZone !== null && !spaLoaded && mountOverlay &&
@@ -2,15 +2,15 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var version = require('./version-f6f044c2.cjs.prod.js');
6
- var createForOfIteratorHelper = require('./createForOfIteratorHelper-0324e063.cjs.prod.js');
5
+ var version = require('./version-a29cfb8e.cjs.prod.js');
6
+ var createForOfIteratorHelper = require('./createForOfIteratorHelper-9afd7d2d.cjs.prod.js');
7
7
  var core = require('@valbuild/core');
8
8
  var stega = require('@valbuild/react/stega');
9
9
  var internal = require('@valbuild/react/internal');
10
10
  var ui = require('@valbuild/ui');
11
11
  var reactRouter = require('@tanstack/react-router');
12
12
  var React = require('react');
13
- var ValOverlayContext = require('./ValOverlayContext-5f1d8da4.cjs.prod.js');
13
+ var ValOverlayContext = require('./ValOverlayContext-2739cc60.cjs.prod.js');
14
14
  var client = require('@valbuild/shared/client');
15
15
  var jsxRuntime = require('react/jsx-runtime');
16
16
  require('@valbuild/core/patch');
@@ -856,6 +856,16 @@ function shouldSafetyRefresh(state) {
856
856
  return true;
857
857
  }
858
858
 
859
+ /**
860
+ * Shows the Overlay menu and updates the store which the client side useVal hook uses to display data.
861
+ */
862
+ /**
863
+ * The floor between server re-renders.
864
+ *
865
+ * `router.invalidate()` re-runs every loader of the current match tree — there
866
+ * is no per-module invalidation — so this is about not queueing a round trip
867
+ * per keystroke, not about batching for its own sake.
868
+ */
859
869
  var REFRESH_INTERVAL_MS = 500;
860
870
 
861
871
  /**
@@ -927,7 +937,7 @@ var DRAFT_HANDSHAKE_POLL_MS = 100;
927
937
  */
928
938
  var DRAFT_HANDSHAKE_TIMEOUT_MS = 10000;
929
939
  var ValTanStackProvider = function ValTanStackProvider(props) {
930
- var _draftModeReady$curre2;
940
+ var _props$draft, _draftModeReady$curre2;
931
941
  // TODO: use config:
932
942
  var route = "/api/val";
933
943
  /**
@@ -967,15 +977,35 @@ var ValTanStackProvider = function ValTanStackProvider(props) {
967
977
  }, _callee);
968
978
  })), [route]);
969
979
 
980
+ /**
981
+ * The draft the page was rendered with, as it was at mount.
982
+ *
983
+ * A ref, not the prop: the server and the browser's first render must start
984
+ * from the same thing, and a later prop -- the loader running again on a
985
+ * client navigation, where it reads nothing -- must not reset a store the
986
+ * overlay has been updating since.
987
+ */
988
+ var initialDraft = React__default["default"].useRef((_props$draft = props.draft) !== null && _props$draft !== void 0 ? _props$draft : null).current;
970
989
  // TODO: move below into react package
971
990
  var valStore = React__default["default"].useMemo(function () {
972
- return new ValOverlayContext.ValExternalStore();
973
- }, []);
991
+ var store = new ValOverlayContext.ValExternalStore();
992
+ if (initialDraft !== null) {
993
+ for (var _i = 0, _Object$entries = Object.entries(initialDraft.sources); _i < _Object$entries.length; _i++) {
994
+ var _Object$entries$_i = createForOfIteratorHelper._slicedToArray(_Object$entries[_i], 2),
995
+ path = _Object$entries$_i[0],
996
+ source = _Object$entries$_i[1];
997
+ store.update(path, source);
998
+ }
999
+ }
1000
+ return store;
1001
+ }, [initialDraft]);
974
1002
  // Whether useValStega should actually suspend. False during SSR and the
975
- // hydration render — the server store is never populated (draft data
976
- // arrives via browser CustomEvents only), so suspending there would just
977
- // stall into the waitForLoad timeout, and hydration must render the static
978
- // source so it matches the server HTML exactly. Activated post-hydration
1003
+ // hydration render. Two paths: without `draft` the server store is empty
1004
+ // (draft data arrives via browser CustomEvents only), so suspending there
1005
+ // would just stall into the waitForLoad timeout, and hydration must render
1006
+ // the static source so it matches the server HTML exactly; with `draft` the
1007
+ // store is seeded above on BOTH sides, so SSR and hydration already render
1008
+ // the draft and there is nothing to wait for. Keep the seed if this changes. Activated post-hydration
979
1009
  // (in an effect, only when the Val Enable cookie is present) inside a
980
1010
  // transition: React keeps the static content visible while hooks suspend
981
1011
  // and then swaps to draft data as a normal update — no Suspense fallback
@@ -992,7 +1022,9 @@ var ValTanStackProvider = function ValTanStackProvider(props) {
992
1022
  * protocol. Without this the page could only wait out `waitForLoad`'s timeout,
993
1023
  * ten seconds per module nobody had edited.
994
1024
  */
995
- var _React$useState3 = React__default["default"].useState(false),
1025
+ // A server-read draft is everything there is: a module missing from it has
1026
+ // no changes, so there is nothing more to wait for.
1027
+ var _React$useState3 = React__default["default"].useState(initialDraft !== null),
996
1028
  _React$useState4 = createForOfIteratorHelper._slicedToArray(_React$useState3, 2),
997
1029
  draftSourcesSynced = _React$useState4[0],
998
1030
  setDraftSourcesSynced = _React$useState4[1];
@@ -1017,7 +1049,9 @@ var ValTanStackProvider = function ValTanStackProvider(props) {
1017
1049
  _React$useState8 = createForOfIteratorHelper._slicedToArray(_React$useState7, 2),
1018
1050
  isCanvas = _React$useState8[0],
1019
1051
  setIsCanvas = _React$useState8[1];
1020
- var _React$useState9 = React__default["default"].useState(null),
1052
+ // Known on the server when it read a draft: `fetchValDraft` only reads one
1053
+ // in draft mode. Otherwise unknown until `/draft/stat` answers.
1054
+ var _React$useState9 = React__default["default"].useState(initialDraft !== null ? true : null),
1021
1055
  _React$useState0 = createForOfIteratorHelper._slicedToArray(_React$useState9, 2),
1022
1056
  draftMode = _React$useState0[0],
1023
1057
  setDraftMode = _React$useState0[1];
@@ -1380,6 +1414,9 @@ var ValTanStackProvider = function ValTanStackProvider(props) {
1380
1414
  stega.SET_AUTO_TAG_JSX_ENABLED(false);
1381
1415
  } else {
1382
1416
  if (draftMode) {
1417
+ // Safe for a page rendered from a server draft too: what a component
1418
+ // renders while it hydrates has no edit tags to turn into attributes
1419
+ // (`useEncodesEditTags`), so this cannot reach one still hydrating.
1383
1420
  stega.SET_AUTO_TAG_JSX_ENABLED(true);
1384
1421
  var reactServerComponentRefreshListener = function reactServerComponentRefreshListener(event) {
1385
1422
  if (event instanceof CustomEvent) {
@@ -1513,6 +1550,7 @@ var ValTanStackProvider = function ValTanStackProvider(props) {
1513
1550
  draftMode: draftMode,
1514
1551
  draftModeReady: (_draftModeReady$curre2 = draftModeReady.current) === null || _draftModeReady$curre2 === void 0 ? void 0 : _draftModeReady$curre2.promise,
1515
1552
  draftSourcesSynced: draftSourcesSynced,
1553
+ serverDraft: initialDraft !== null,
1516
1554
  suspend: suspendActive,
1517
1555
  store: valStore,
1518
1556
  children: [props.children, dropZone !== null && !spaLoaded && mountOverlay &&
@@ -1,5 +1,5 @@
1
- import { _ as _asyncToGenerator, a as _regenerator, r as readValEnableCookie, V as VERSION$1 } from './version-d0b1c2c5.esm.js';
2
- import { _ as _objectSpread2, a as _slicedToArray, b as _createForOfIteratorHelper } from './createForOfIteratorHelper-485c2ce1.esm.js';
1
+ import { _ as _asyncToGenerator, a as _regenerator, r as readValEnableCookie, V as VERSION$1 } from './version-6d26340d.esm.js';
2
+ import { _ as _objectSpread2, a as _slicedToArray, b as _createForOfIteratorHelper } from './createForOfIteratorHelper-93a62170.esm.js';
3
3
  import { Internal as Internal$1, initVal as initVal$1, DEFAULT_CONTENT_HOST } from '@valbuild/core';
4
4
  import * as core from '@valbuild/core';
5
5
  export { core as expr };
@@ -9,7 +9,7 @@ export { ValRichText } from '@valbuild/react/internal';
9
9
  import { VERSION, VAL_APP_PATH, VAL_OVERLAY_ID, VAL_APP_ID } from '@valbuild/ui';
10
10
  import { useRouter, useRouterState } from '@tanstack/react-router';
11
11
  import React, { useEffect, useState, useRef } from 'react';
12
- import { V as ValExternalStore, a as ValOverlayProvider } from './ValOverlayContext-5bc3830f.esm.js';
12
+ import { V as ValExternalStore, a as ValOverlayProvider } from './ValOverlayContext-28101df3.esm.js';
13
13
  import { VAL_CONFIG_SESSION_STORAGE_KEY, VAL_THEME_SESSION_STORAGE_KEY, VAL_CANVAS_MESSAGE, DEFAULT_CANVAS_SELECTION, DEFAULT_CANVAS_SELECTION_SOFT, isValCanvasStudioMessage, isValCanvasFrame } from '@valbuild/shared/client';
14
14
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
15
15
  import '@valbuild/core/patch';
@@ -832,6 +832,16 @@ function shouldSafetyRefresh(state) {
832
832
  return true;
833
833
  }
834
834
 
835
+ /**
836
+ * Shows the Overlay menu and updates the store which the client side useVal hook uses to display data.
837
+ */
838
+ /**
839
+ * The floor between server re-renders.
840
+ *
841
+ * `router.invalidate()` re-runs every loader of the current match tree — there
842
+ * is no per-module invalidation — so this is about not queueing a round trip
843
+ * per keystroke, not about batching for its own sake.
844
+ */
835
845
  var REFRESH_INTERVAL_MS = 500;
836
846
 
837
847
  /**
@@ -903,7 +913,7 @@ var DRAFT_HANDSHAKE_POLL_MS = 100;
903
913
  */
904
914
  var DRAFT_HANDSHAKE_TIMEOUT_MS = 10000;
905
915
  var ValTanStackProvider = function ValTanStackProvider(props) {
906
- var _draftModeReady$curre2;
916
+ var _props$draft, _draftModeReady$curre2;
907
917
  // TODO: use config:
908
918
  var route = "/api/val";
909
919
  /**
@@ -943,15 +953,35 @@ var ValTanStackProvider = function ValTanStackProvider(props) {
943
953
  }, _callee);
944
954
  })), [route]);
945
955
 
956
+ /**
957
+ * The draft the page was rendered with, as it was at mount.
958
+ *
959
+ * A ref, not the prop: the server and the browser's first render must start
960
+ * from the same thing, and a later prop -- the loader running again on a
961
+ * client navigation, where it reads nothing -- must not reset a store the
962
+ * overlay has been updating since.
963
+ */
964
+ var initialDraft = React.useRef((_props$draft = props.draft) !== null && _props$draft !== void 0 ? _props$draft : null).current;
946
965
  // TODO: move below into react package
947
966
  var valStore = React.useMemo(function () {
948
- return new ValExternalStore();
949
- }, []);
967
+ var store = new ValExternalStore();
968
+ if (initialDraft !== null) {
969
+ for (var _i = 0, _Object$entries = Object.entries(initialDraft.sources); _i < _Object$entries.length; _i++) {
970
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
971
+ path = _Object$entries$_i[0],
972
+ source = _Object$entries$_i[1];
973
+ store.update(path, source);
974
+ }
975
+ }
976
+ return store;
977
+ }, [initialDraft]);
950
978
  // Whether useValStega should actually suspend. False during SSR and the
951
- // hydration render — the server store is never populated (draft data
952
- // arrives via browser CustomEvents only), so suspending there would just
953
- // stall into the waitForLoad timeout, and hydration must render the static
954
- // source so it matches the server HTML exactly. Activated post-hydration
979
+ // hydration render. Two paths: without `draft` the server store is empty
980
+ // (draft data arrives via browser CustomEvents only), so suspending there
981
+ // would just stall into the waitForLoad timeout, and hydration must render
982
+ // the static source so it matches the server HTML exactly; with `draft` the
983
+ // store is seeded above on BOTH sides, so SSR and hydration already render
984
+ // the draft and there is nothing to wait for. Keep the seed if this changes. Activated post-hydration
955
985
  // (in an effect, only when the Val Enable cookie is present) inside a
956
986
  // transition: React keeps the static content visible while hooks suspend
957
987
  // and then swaps to draft data as a normal update — no Suspense fallback
@@ -968,7 +998,9 @@ var ValTanStackProvider = function ValTanStackProvider(props) {
968
998
  * protocol. Without this the page could only wait out `waitForLoad`'s timeout,
969
999
  * ten seconds per module nobody had edited.
970
1000
  */
971
- var _React$useState3 = React.useState(false),
1001
+ // A server-read draft is everything there is: a module missing from it has
1002
+ // no changes, so there is nothing more to wait for.
1003
+ var _React$useState3 = React.useState(initialDraft !== null),
972
1004
  _React$useState4 = _slicedToArray(_React$useState3, 2),
973
1005
  draftSourcesSynced = _React$useState4[0],
974
1006
  setDraftSourcesSynced = _React$useState4[1];
@@ -993,7 +1025,9 @@ var ValTanStackProvider = function ValTanStackProvider(props) {
993
1025
  _React$useState8 = _slicedToArray(_React$useState7, 2),
994
1026
  isCanvas = _React$useState8[0],
995
1027
  setIsCanvas = _React$useState8[1];
996
- var _React$useState9 = React.useState(null),
1028
+ // Known on the server when it read a draft: `fetchValDraft` only reads one
1029
+ // in draft mode. Otherwise unknown until `/draft/stat` answers.
1030
+ var _React$useState9 = React.useState(initialDraft !== null ? true : null),
997
1031
  _React$useState0 = _slicedToArray(_React$useState9, 2),
998
1032
  draftMode = _React$useState0[0],
999
1033
  setDraftMode = _React$useState0[1];
@@ -1356,6 +1390,9 @@ var ValTanStackProvider = function ValTanStackProvider(props) {
1356
1390
  SET_AUTO_TAG_JSX_ENABLED(false);
1357
1391
  } else {
1358
1392
  if (draftMode) {
1393
+ // Safe for a page rendered from a server draft too: what a component
1394
+ // renders while it hydrates has no edit tags to turn into attributes
1395
+ // (`useEncodesEditTags`), so this cannot reach one still hydrating.
1359
1396
  SET_AUTO_TAG_JSX_ENABLED(true);
1360
1397
  var reactServerComponentRefreshListener = function reactServerComponentRefreshListener(event) {
1361
1398
  if (event instanceof CustomEvent) {
@@ -1489,6 +1526,7 @@ var ValTanStackProvider = function ValTanStackProvider(props) {
1489
1526
  draftMode: draftMode,
1490
1527
  draftModeReady: (_draftModeReady$curre2 = draftModeReady.current) === null || _draftModeReady$curre2 === void 0 ? void 0 : _draftModeReady$curre2.promise,
1491
1528
  draftSourcesSynced: draftSourcesSynced,
1529
+ serverDraft: initialDraft !== null,
1492
1530
  suspend: suspendActive,
1493
1531
  store: valStore,
1494
1532
  children: [props.children, dropZone !== null && !spaLoaded && mountOverlay &&
@@ -210,7 +210,7 @@ var packageJson = {
210
210
  "tanstack-router",
211
211
  "react"
212
212
  ],
213
- version: "0.139.2",
213
+ version: "0.140.2",
214
214
  scripts: {
215
215
  typecheck: "tsc --noEmit",
216
216
  test: "jest"
@@ -212,7 +212,7 @@ var packageJson = {
212
212
  "tanstack-router",
213
213
  "react"
214
214
  ],
215
- version: "0.139.2",
215
+ version: "0.140.2",
216
216
  scripts: {
217
217
  typecheck: "tsc --noEmit",
218
218
  test: "jest"
@@ -212,7 +212,7 @@ var packageJson = {
212
212
  "tanstack-router",
213
213
  "react"
214
214
  ],
215
- version: "0.139.2",
215
+ version: "0.140.2",
216
216
  scripts: {
217
217
  typecheck: "tsc --noEmit",
218
218
  test: "jest"
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "tanstack-router",
15
15
  "react"
16
16
  ],
17
- "version": "0.139.2",
17
+ "version": "0.140.2",
18
18
  "main": "dist/valbuild-tanstack.cjs.js",
19
19
  "module": "dist/valbuild-tanstack.esm.js",
20
20
  "exports": {
@@ -43,12 +43,12 @@
43
43
  },
44
44
  "dependencies": {
45
45
  "@valbuild/core": "0.139.1",
46
- "@valbuild/language-server": "0.139.2",
47
- "@valbuild/mcp": "0.139.2",
48
- "@valbuild/react": "0.139.2",
49
- "@valbuild/server": "0.139.2",
50
- "@valbuild/shared": "0.139.1",
51
- "@valbuild/ui": "0.139.2"
46
+ "@valbuild/language-server": "0.140.2",
47
+ "@valbuild/mcp": "0.140.2",
48
+ "@valbuild/react": "0.140.2",
49
+ "@valbuild/shared": "0.140.2",
50
+ "@valbuild/server": "0.140.2",
51
+ "@valbuild/ui": "0.140.2"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@tanstack/react-router": "^1.170.41",