@valbuild/tanstack 0.139.1 → 0.140.0
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/CHANGELOG.md +59 -0
- package/README.md +51 -4
- package/client/dist/valbuild-tanstack-client.cjs.dev.js +53 -6
- package/client/dist/valbuild-tanstack-client.cjs.prod.js +53 -6
- package/client/dist/valbuild-tanstack-client.esm.js +53 -6
- package/dist/{ValOverlayContext-5f1d8da4.cjs.prod.js → ValOverlayContext-2739cc60.cjs.prod.js} +4 -2
- package/dist/{ValOverlayContext-5bc3830f.esm.js → ValOverlayContext-28101df3.esm.js} +4 -2
- package/dist/{ValOverlayContext-3ec15518.cjs.dev.js → ValOverlayContext-bafe3de9.cjs.dev.js} +4 -2
- package/dist/{createForOfIteratorHelper-e75681d7.cjs.dev.js → createForOfIteratorHelper-4497beef.cjs.dev.js} +2 -0
- package/dist/{createForOfIteratorHelper-485c2ce1.esm.js → createForOfIteratorHelper-93a62170.esm.js} +1 -1
- package/dist/{createForOfIteratorHelper-0324e063.cjs.prod.js → createForOfIteratorHelper-9afd7d2d.cjs.prod.js} +2 -0
- package/dist/declarations/src/ValDraft.d.ts +21 -0
- package/dist/declarations/src/ValProvider.d.ts +1 -0
- package/dist/declarations/src/external_exempt_from_val_quickjs.d.ts +1 -0
- package/dist/declarations/src/server/index.d.ts +1 -0
- package/dist/declarations/src/server/initValContent.d.ts +30 -0
- package/dist/{routeFromVal-6693e037.cjs.prod.js → routeFromVal-0b39e8e3.cjs.prod.js} +1 -1
- package/dist/{routeFromVal-728295a0.esm.js → routeFromVal-1221e70d.esm.js} +1 -1
- package/dist/{routeFromVal-a9147ceb.cjs.dev.js → routeFromVal-97111bfd.cjs.dev.js} +1 -1
- package/dist/valbuild-tanstack.cjs.dev.js +50 -12
- package/dist/valbuild-tanstack.cjs.prod.js +50 -12
- package/dist/valbuild-tanstack.esm.js +50 -12
- package/dist/{version-7d6c8558.cjs.dev.js → version-0cfddc38.cjs.dev.js} +1 -1
- package/dist/{version-0911ff0a.cjs.prod.js → version-24675097.cjs.prod.js} +1 -1
- package/dist/{version-121c6f89.esm.js → version-e61be600.esm.js} +1 -1
- package/package.json +7 -7
- package/server/dist/valbuild-tanstack-server.cjs.dev.js +478 -152
- package/server/dist/valbuild-tanstack-server.cjs.prod.js +478 -152
- package/server/dist/valbuild-tanstack-server.esm.js +479 -153
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,64 @@
|
|
|
1
1
|
# @valbuild/tanstack
|
|
2
2
|
|
|
3
|
+
## 0.140.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#793](https://github.com/valbuild/val/pull/793) [`092e6a7`](https://github.com/valbuild/val/commit/092e6a7f78bcfcf4c6cecaf34407fdfc580ebbc1) Thanks [@freekh](https://github.com/freekh)! - A draft page on TanStack Start is now rendered as the draft by the server, so it no longer shows the published text first and the draft a moment later — most noticeable when you reload right after publishing.
|
|
8
|
+
|
|
9
|
+
Read the request's draft in your site layout's loader and pass it to `ValProvider`:
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
// src/val/server.ts
|
|
13
|
+
export const { fetchValDraft /* , fetchVal, ... */ } = initValContent(
|
|
14
|
+
config,
|
|
15
|
+
valModules,
|
|
16
|
+
{ draftMode },
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
// src/routes/_site.tsx
|
|
20
|
+
const getValDraft = createServerFn().handler(() => fetchValDraft());
|
|
21
|
+
|
|
22
|
+
export const Route = createFileRoute("/_site")({
|
|
23
|
+
loader: () => (typeof document === "undefined" ? getValDraft() : null),
|
|
24
|
+
component: SiteLayout,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
function SiteLayout() {
|
|
28
|
+
const draft = Route.useLoaderData();
|
|
29
|
+
return (
|
|
30
|
+
<ValProvider config={config} suspend draft={draft}>
|
|
31
|
+
{/* ... */}
|
|
32
|
+
</ValProvider>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Visitors pay one cookie lookup and nothing else. Without `draft`, pages behave as before. Edited `.jsonValues()` entries are rendered as the draft too; the others render from the build, as they do for visitors.
|
|
38
|
+
|
|
39
|
+
Also: a draft's `.jsonValues()` entries now include changes that were published after the build being served, instead of showing the old value until the next build is live.
|
|
40
|
+
|
|
41
|
+
Also: a renamed or duplicated `.jsonValues()` entry now has its content in the draft, on the page and when the Studio reads the entry, instead of failing to load until it is published.
|
|
42
|
+
|
|
43
|
+
- Updated dependencies [[`cb93874`](https://github.com/valbuild/val/commit/cb938748aec15fd0ac3814c1696a2dd78ad63c27), [`092e6a7`](https://github.com/valbuild/val/commit/092e6a7f78bcfcf4c6cecaf34407fdfc580ebbc1)]:
|
|
44
|
+
- @valbuild/ui@0.140.0
|
|
45
|
+
- @valbuild/server@0.140.0
|
|
46
|
+
- @valbuild/shared@0.140.0
|
|
47
|
+
- @valbuild/react@0.140.0
|
|
48
|
+
- @valbuild/language-server@0.140.0
|
|
49
|
+
- @valbuild/mcp@0.140.0
|
|
50
|
+
|
|
51
|
+
## 0.139.2
|
|
52
|
+
|
|
53
|
+
### Patch Changes
|
|
54
|
+
|
|
55
|
+
- Updated dependencies [[`4d9e12c`](https://github.com/valbuild/val/commit/4d9e12c5286f981c7a8a7820db1bf580e327d2ea), [`1c3eb3a`](https://github.com/valbuild/val/commit/1c3eb3af91f6dfeff94a95d80d5291a1acf1baf2)]:
|
|
56
|
+
- @valbuild/ui@0.139.2
|
|
57
|
+
- @valbuild/react@0.139.2
|
|
58
|
+
- @valbuild/server@0.139.2
|
|
59
|
+
- @valbuild/language-server@0.139.2
|
|
60
|
+
- @valbuild/mcp@0.139.2
|
|
61
|
+
|
|
3
62
|
## 0.139.1
|
|
4
63
|
|
|
5
64
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -209,6 +209,9 @@ export const Route = createFileRoute("/_site")({
|
|
|
209
209
|
});
|
|
210
210
|
```
|
|
211
211
|
|
|
212
|
+
Add the `draft` prop from [Preview and draft mode](#preview-and-draft-mode) so a
|
|
213
|
+
draft page is rendered as the draft on the server too.
|
|
214
|
+
|
|
212
215
|
A pathless layout adds no URL segment: `_site.index.tsx` is still `/`. Val
|
|
213
216
|
modules named after those files follow the same rule, so
|
|
214
217
|
`_site.posts.$postId.val.ts` holds `/posts/...` keys.
|
|
@@ -234,9 +237,10 @@ export const {
|
|
|
234
237
|
## Reading content
|
|
235
238
|
|
|
236
239
|
**Prefer the hooks.** They work in both places a component runs: during SSR they
|
|
237
|
-
resolve the published content,
|
|
238
|
-
|
|
239
|
-
with
|
|
240
|
+
resolve the published content — or, when `ValProvider` is given the request's
|
|
241
|
+
draft (see [Preview and draft mode](#preview-and-draft-mode)), the draft — and in
|
|
242
|
+
a browser with the Studio open they resolve what the editor currently holds, so
|
|
243
|
+
an edit appears as it is typed, with no round trip and no loader.
|
|
240
244
|
|
|
241
245
|
```tsx
|
|
242
246
|
function Page() {
|
|
@@ -330,10 +334,52 @@ its own, so this package brings a cookie (`val_draft_mode`, `valDraftMode()` in
|
|
|
330
334
|
read also carries Val's session cookie, which is a signed JWT the server
|
|
331
335
|
verifies, so a forged draft cookie gets published content.
|
|
332
336
|
|
|
337
|
+
**Render the draft on the server, too.** Without it the server renders the
|
|
338
|
+
PUBLISHED page and the browser swaps the draft in once the overlay has loaded,
|
|
339
|
+
so every draft page load shows the old text first and the new text a moment
|
|
340
|
+
later. Read the request's draft in the site layout's loader and hand it to the
|
|
341
|
+
provider:
|
|
342
|
+
|
|
343
|
+
```tsx
|
|
344
|
+
// src/val/server.ts: add `fetchValDraft` to what initValContent returns
|
|
345
|
+
export const { fetchValDraft /* , fetchVal, ... */ } = initValContent(
|
|
346
|
+
config,
|
|
347
|
+
valModules,
|
|
348
|
+
{ draftMode },
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
// src/routes/_site.tsx
|
|
352
|
+
const getValDraft = createServerFn().handler(() => fetchValDraft());
|
|
353
|
+
|
|
354
|
+
export const Route = createFileRoute("/_site")({
|
|
355
|
+
// On the server only: the overlay keeps the page up to date after that.
|
|
356
|
+
loader: () => (typeof document === "undefined" ? getValDraft() : null),
|
|
357
|
+
component: SiteLayout,
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
function SiteLayout() {
|
|
361
|
+
const draft = Route.useLoaderData();
|
|
362
|
+
return (
|
|
363
|
+
<ValProvider config={config} suspend draft={draft}>
|
|
364
|
+
{/* ... */}
|
|
365
|
+
</ValProvider>
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
`fetchValDraft` returns `null` — after one cookie lookup, with no read — unless
|
|
371
|
+
the request is in draft mode, so visitors pay nothing. In draft mode it returns
|
|
372
|
+
the modules the draft changes, which the server renders with and the browser
|
|
373
|
+
hydrates from: both produce the same page, showing the draft from the first
|
|
374
|
+
paint. It becomes click-to-editable as each component finishes hydrating, and
|
|
375
|
+
the overlay takes over from there.
|
|
376
|
+
|
|
333
377
|
`suspend` on `ValProvider` makes `useValStega` / `useValRouteStega` wait for
|
|
334
378
|
draft data before rendering, so a page that exists **only** in an unpublished
|
|
335
379
|
draft renders instead of 404ing. Visitors without the Val Enable cookie pay
|
|
336
|
-
nothing for it. It needs React 19 and a `<Suspense>` boundary (see above).
|
|
380
|
+
nothing for it. It needs React 19 and a `<Suspense>` boundary (see above). With
|
|
381
|
+
`draft` given, the server already has that page's content, so its first render
|
|
382
|
+
does not 404 either.
|
|
337
383
|
|
|
338
384
|
## Images
|
|
339
385
|
|
|
@@ -370,6 +416,7 @@ SDK of your choice. See [`@valbuild/mcp`](https://www.npmjs.com/package/@valbuil
|
|
|
370
416
|
| `valNextAppRouter` | `valApiHandler` — a `Request` in, a `Response` out |
|
|
371
417
|
| `ValImage` wraps `next/image` | `ValImage` is an `<img>` |
|
|
372
418
|
| `fetchVal` in a Server Component | hooks in components; `createServerFn` for loaders |
|
|
419
|
+
| client hooks render published SSR | `ValProvider draft` renders the draft during SSR |
|
|
373
420
|
|
|
374
421
|
## Schema reference
|
|
375
422
|
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var routeFromVal = require('../../dist/routeFromVal-
|
|
5
|
+
var routeFromVal = require('../../dist/routeFromVal-97111bfd.cjs.dev.js');
|
|
6
6
|
var core = require('@valbuild/core');
|
|
7
7
|
var stega = require('@valbuild/react/stega');
|
|
8
8
|
var React = require('react');
|
|
9
|
-
var ValOverlayContext = require('../../dist/ValOverlayContext-
|
|
10
|
-
require('../../dist/createForOfIteratorHelper-
|
|
9
|
+
var ValOverlayContext = require('../../dist/ValOverlayContext-bafe3de9.cjs.dev.js');
|
|
10
|
+
require('../../dist/createForOfIteratorHelper-4497beef.cjs.dev.js');
|
|
11
11
|
require('@valbuild/shared/client');
|
|
12
12
|
require('@valbuild/core/patch');
|
|
13
13
|
require('react/jsx-runtime');
|
|
@@ -16,10 +16,55 @@ function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e };
|
|
|
16
16
|
|
|
17
17
|
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
18
18
|
|
|
19
|
+
var subscribeNever = function subscribeNever() {
|
|
20
|
+
return function () {};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* `false` for the server's render and for this component's hydration render,
|
|
25
|
+
* `true` for every render after.
|
|
26
|
+
*
|
|
27
|
+
* Per component, which is the point: React reads `getServerSnapshot` while it
|
|
28
|
+
* hydrates a component and `getSnapshot` otherwise, and re-renders the
|
|
29
|
+
* component right after hydrating it when the two differ. So a component that
|
|
30
|
+
* hydrates late -- a route split out into its own chunk -- still renders its
|
|
31
|
+
* hydration pass as the server did, however long after the rest of the page.
|
|
32
|
+
*/
|
|
33
|
+
function useHydrated() {
|
|
34
|
+
return React__default["default"].useSyncExternalStore(subscribeNever, function () {
|
|
35
|
+
return true;
|
|
36
|
+
}, function () {
|
|
37
|
+
return false;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Whether the content this component renders carries its edit tags.
|
|
43
|
+
*
|
|
44
|
+
* Always in draft mode -- except, on a page rendered from a server-read draft,
|
|
45
|
+
* for the server's render and for this component's own hydration render: then
|
|
46
|
+
* the draft text goes out without them, and the render React does right after
|
|
47
|
+
* hydrating the component puts them in.
|
|
48
|
+
*
|
|
49
|
+
* Because JSX auto-tagging turns a tagged string into a `data-val-path`
|
|
50
|
+
* attribute as the element is created, and the switch for it is process-wide.
|
|
51
|
+
* The server cannot be relied on to tag (whether the patched JSX runtime is
|
|
52
|
+
* the one it renders with depends on how it was bundled), and no page-wide
|
|
53
|
+
* moment means "everything has hydrated": a split-out route, or a lazy child
|
|
54
|
+
* handed a string as a prop, hydrates after the rest of the page. A string
|
|
55
|
+
* with no tags in it has nothing to tag, wherever it is rendered and whatever
|
|
56
|
+
* the switch says -- so the server's HTML and every hydration render agree.
|
|
57
|
+
*/
|
|
58
|
+
function useEncodesEditTags(context) {
|
|
59
|
+
var hydrated = useHydrated();
|
|
60
|
+
return !!context.draftMode && (!context.serverDraft || hydrated);
|
|
61
|
+
}
|
|
62
|
+
|
|
19
63
|
/** What `useVal` gives back — see `ResolvedVal` in `@valbuild/react/stega`. */
|
|
20
64
|
|
|
21
65
|
function useValStega(selector) {
|
|
22
66
|
var valOverlayContext = ValOverlayContext.useValOverlayContext();
|
|
67
|
+
var encodes = useEncodesEditTags(valOverlayContext);
|
|
23
68
|
var moduleIds = React__default["default"].useMemo(function () {
|
|
24
69
|
return stega.getModuleIds(selector);
|
|
25
70
|
}, [selector]);
|
|
@@ -72,7 +117,7 @@ function useValStega(selector) {
|
|
|
72
117
|
React__default["default"].use(store.waitForLoad(moduleIds));
|
|
73
118
|
}
|
|
74
119
|
return stega.stegaEncode(selector, {
|
|
75
|
-
disabled: !
|
|
120
|
+
disabled: !encodes,
|
|
76
121
|
getModule: function getModule(moduleId) {
|
|
77
122
|
if (moduleMap && valOverlayContext.draftMode) {
|
|
78
123
|
return moduleMap[moduleId];
|
|
@@ -159,6 +204,7 @@ var jsonEntryPromiseCache = new Map();
|
|
|
159
204
|
*/
|
|
160
205
|
function useValKeyStega(selector, key) {
|
|
161
206
|
var valOverlayContext = ValOverlayContext.useValOverlayContext();
|
|
207
|
+
var encodes = useEncodesEditTags(valOverlayContext);
|
|
162
208
|
// A view is a pointer: everything below reads a path, a schema and a source
|
|
163
209
|
// off this, and a pointer has none of them. See `resolveViewedModule`.
|
|
164
210
|
var valModule = core.Internal.resolveViewedModule(selector);
|
|
@@ -175,7 +221,7 @@ function useValKeyStega(selector, key) {
|
|
|
175
221
|
content = readCommittedJsonEntry(valModule, key);
|
|
176
222
|
}
|
|
177
223
|
return stega.stegaEncode(content, {
|
|
178
|
-
disabled: !
|
|
224
|
+
disabled: !encodes,
|
|
179
225
|
root: routeFromVal.getJsonEntryStegaRoot(valModule, key)
|
|
180
226
|
});
|
|
181
227
|
}
|
|
@@ -234,6 +280,7 @@ function useValRouteStega(selector, params) {
|
|
|
234
280
|
// router `val` is unused (we resolve a single entry below instead); for any
|
|
235
281
|
// other router `draftSource` is.
|
|
236
282
|
var val = useValStega(valModule);
|
|
283
|
+
var encodes = useEncodesEditTags(valOverlayContext);
|
|
237
284
|
var draftSource = useDraftModuleSource(valModule && core.Internal.getValPath(valModule) || undefined);
|
|
238
285
|
var resolvedParams = resolveParams(params);
|
|
239
286
|
// Careful: null means there was an error - undefined means no params
|
|
@@ -263,7 +310,7 @@ function useValRouteStega(selector, params) {
|
|
|
263
310
|
return null;
|
|
264
311
|
}
|
|
265
312
|
return stega.stegaEncode(content, {
|
|
266
|
-
disabled: !
|
|
313
|
+
disabled: !encodes,
|
|
267
314
|
root: routeFromVal.getJsonEntryStegaRoot(valModule, url)
|
|
268
315
|
});
|
|
269
316
|
}
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var routeFromVal = require('../../dist/routeFromVal-
|
|
5
|
+
var routeFromVal = require('../../dist/routeFromVal-0b39e8e3.cjs.prod.js');
|
|
6
6
|
var core = require('@valbuild/core');
|
|
7
7
|
var stega = require('@valbuild/react/stega');
|
|
8
8
|
var React = require('react');
|
|
9
|
-
var ValOverlayContext = require('../../dist/ValOverlayContext-
|
|
10
|
-
require('../../dist/createForOfIteratorHelper-
|
|
9
|
+
var ValOverlayContext = require('../../dist/ValOverlayContext-2739cc60.cjs.prod.js');
|
|
10
|
+
require('../../dist/createForOfIteratorHelper-9afd7d2d.cjs.prod.js');
|
|
11
11
|
require('@valbuild/shared/client');
|
|
12
12
|
require('@valbuild/core/patch');
|
|
13
13
|
require('react/jsx-runtime');
|
|
@@ -16,10 +16,55 @@ function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e };
|
|
|
16
16
|
|
|
17
17
|
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
18
18
|
|
|
19
|
+
var subscribeNever = function subscribeNever() {
|
|
20
|
+
return function () {};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* `false` for the server's render and for this component's hydration render,
|
|
25
|
+
* `true` for every render after.
|
|
26
|
+
*
|
|
27
|
+
* Per component, which is the point: React reads `getServerSnapshot` while it
|
|
28
|
+
* hydrates a component and `getSnapshot` otherwise, and re-renders the
|
|
29
|
+
* component right after hydrating it when the two differ. So a component that
|
|
30
|
+
* hydrates late -- a route split out into its own chunk -- still renders its
|
|
31
|
+
* hydration pass as the server did, however long after the rest of the page.
|
|
32
|
+
*/
|
|
33
|
+
function useHydrated() {
|
|
34
|
+
return React__default["default"].useSyncExternalStore(subscribeNever, function () {
|
|
35
|
+
return true;
|
|
36
|
+
}, function () {
|
|
37
|
+
return false;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Whether the content this component renders carries its edit tags.
|
|
43
|
+
*
|
|
44
|
+
* Always in draft mode -- except, on a page rendered from a server-read draft,
|
|
45
|
+
* for the server's render and for this component's own hydration render: then
|
|
46
|
+
* the draft text goes out without them, and the render React does right after
|
|
47
|
+
* hydrating the component puts them in.
|
|
48
|
+
*
|
|
49
|
+
* Because JSX auto-tagging turns a tagged string into a `data-val-path`
|
|
50
|
+
* attribute as the element is created, and the switch for it is process-wide.
|
|
51
|
+
* The server cannot be relied on to tag (whether the patched JSX runtime is
|
|
52
|
+
* the one it renders with depends on how it was bundled), and no page-wide
|
|
53
|
+
* moment means "everything has hydrated": a split-out route, or a lazy child
|
|
54
|
+
* handed a string as a prop, hydrates after the rest of the page. A string
|
|
55
|
+
* with no tags in it has nothing to tag, wherever it is rendered and whatever
|
|
56
|
+
* the switch says -- so the server's HTML and every hydration render agree.
|
|
57
|
+
*/
|
|
58
|
+
function useEncodesEditTags(context) {
|
|
59
|
+
var hydrated = useHydrated();
|
|
60
|
+
return !!context.draftMode && (!context.serverDraft || hydrated);
|
|
61
|
+
}
|
|
62
|
+
|
|
19
63
|
/** What `useVal` gives back — see `ResolvedVal` in `@valbuild/react/stega`. */
|
|
20
64
|
|
|
21
65
|
function useValStega(selector) {
|
|
22
66
|
var valOverlayContext = ValOverlayContext.useValOverlayContext();
|
|
67
|
+
var encodes = useEncodesEditTags(valOverlayContext);
|
|
23
68
|
var moduleIds = React__default["default"].useMemo(function () {
|
|
24
69
|
return stega.getModuleIds(selector);
|
|
25
70
|
}, [selector]);
|
|
@@ -72,7 +117,7 @@ function useValStega(selector) {
|
|
|
72
117
|
React__default["default"].use(store.waitForLoad(moduleIds));
|
|
73
118
|
}
|
|
74
119
|
return stega.stegaEncode(selector, {
|
|
75
|
-
disabled: !
|
|
120
|
+
disabled: !encodes,
|
|
76
121
|
getModule: function getModule(moduleId) {
|
|
77
122
|
if (moduleMap && valOverlayContext.draftMode) {
|
|
78
123
|
return moduleMap[moduleId];
|
|
@@ -159,6 +204,7 @@ var jsonEntryPromiseCache = new Map();
|
|
|
159
204
|
*/
|
|
160
205
|
function useValKeyStega(selector, key) {
|
|
161
206
|
var valOverlayContext = ValOverlayContext.useValOverlayContext();
|
|
207
|
+
var encodes = useEncodesEditTags(valOverlayContext);
|
|
162
208
|
// A view is a pointer: everything below reads a path, a schema and a source
|
|
163
209
|
// off this, and a pointer has none of them. See `resolveViewedModule`.
|
|
164
210
|
var valModule = core.Internal.resolveViewedModule(selector);
|
|
@@ -175,7 +221,7 @@ function useValKeyStega(selector, key) {
|
|
|
175
221
|
content = readCommittedJsonEntry(valModule, key);
|
|
176
222
|
}
|
|
177
223
|
return stega.stegaEncode(content, {
|
|
178
|
-
disabled: !
|
|
224
|
+
disabled: !encodes,
|
|
179
225
|
root: routeFromVal.getJsonEntryStegaRoot(valModule, key)
|
|
180
226
|
});
|
|
181
227
|
}
|
|
@@ -234,6 +280,7 @@ function useValRouteStega(selector, params) {
|
|
|
234
280
|
// router `val` is unused (we resolve a single entry below instead); for any
|
|
235
281
|
// other router `draftSource` is.
|
|
236
282
|
var val = useValStega(valModule);
|
|
283
|
+
var encodes = useEncodesEditTags(valOverlayContext);
|
|
237
284
|
var draftSource = useDraftModuleSource(valModule && core.Internal.getValPath(valModule) || undefined);
|
|
238
285
|
var resolvedParams = resolveParams(params);
|
|
239
286
|
// Careful: null means there was an error - undefined means no params
|
|
@@ -263,7 +310,7 @@ function useValRouteStega(selector, params) {
|
|
|
263
310
|
return null;
|
|
264
311
|
}
|
|
265
312
|
return stega.stegaEncode(content, {
|
|
266
|
-
disabled: !
|
|
313
|
+
disabled: !encodes,
|
|
267
314
|
root: routeFromVal.getJsonEntryStegaRoot(valModule, url)
|
|
268
315
|
});
|
|
269
316
|
}
|
|
@@ -1,17 +1,62 @@
|
|
|
1
|
-
import { g as getJsonEntryStegaRoot, _ as _typeof, i as isJsonValuesRecordSchema, a as getValRouteUrlFromVal, b as initValRouteFromVal } from '../../dist/routeFromVal-
|
|
1
|
+
import { g as getJsonEntryStegaRoot, _ as _typeof, i as isJsonValuesRecordSchema, a as getValRouteUrlFromVal, b as initValRouteFromVal } from '../../dist/routeFromVal-1221e70d.esm.js';
|
|
2
2
|
import { Internal } from '@valbuild/core';
|
|
3
3
|
import { getModuleIds, stegaEncode } from '@valbuild/react/stega';
|
|
4
4
|
import React from 'react';
|
|
5
|
-
import { u as useValOverlayContext } from '../../dist/ValOverlayContext-
|
|
6
|
-
import '../../dist/createForOfIteratorHelper-
|
|
5
|
+
import { u as useValOverlayContext } from '../../dist/ValOverlayContext-28101df3.esm.js';
|
|
6
|
+
import '../../dist/createForOfIteratorHelper-93a62170.esm.js';
|
|
7
7
|
import '@valbuild/shared/client';
|
|
8
8
|
import '@valbuild/core/patch';
|
|
9
9
|
import 'react/jsx-runtime';
|
|
10
10
|
|
|
11
|
+
var subscribeNever = function subscribeNever() {
|
|
12
|
+
return function () {};
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* `false` for the server's render and for this component's hydration render,
|
|
17
|
+
* `true` for every render after.
|
|
18
|
+
*
|
|
19
|
+
* Per component, which is the point: React reads `getServerSnapshot` while it
|
|
20
|
+
* hydrates a component and `getSnapshot` otherwise, and re-renders the
|
|
21
|
+
* component right after hydrating it when the two differ. So a component that
|
|
22
|
+
* hydrates late -- a route split out into its own chunk -- still renders its
|
|
23
|
+
* hydration pass as the server did, however long after the rest of the page.
|
|
24
|
+
*/
|
|
25
|
+
function useHydrated() {
|
|
26
|
+
return React.useSyncExternalStore(subscribeNever, function () {
|
|
27
|
+
return true;
|
|
28
|
+
}, function () {
|
|
29
|
+
return false;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Whether the content this component renders carries its edit tags.
|
|
35
|
+
*
|
|
36
|
+
* Always in draft mode -- except, on a page rendered from a server-read draft,
|
|
37
|
+
* for the server's render and for this component's own hydration render: then
|
|
38
|
+
* the draft text goes out without them, and the render React does right after
|
|
39
|
+
* hydrating the component puts them in.
|
|
40
|
+
*
|
|
41
|
+
* Because JSX auto-tagging turns a tagged string into a `data-val-path`
|
|
42
|
+
* attribute as the element is created, and the switch for it is process-wide.
|
|
43
|
+
* The server cannot be relied on to tag (whether the patched JSX runtime is
|
|
44
|
+
* the one it renders with depends on how it was bundled), and no page-wide
|
|
45
|
+
* moment means "everything has hydrated": a split-out route, or a lazy child
|
|
46
|
+
* handed a string as a prop, hydrates after the rest of the page. A string
|
|
47
|
+
* with no tags in it has nothing to tag, wherever it is rendered and whatever
|
|
48
|
+
* the switch says -- so the server's HTML and every hydration render agree.
|
|
49
|
+
*/
|
|
50
|
+
function useEncodesEditTags(context) {
|
|
51
|
+
var hydrated = useHydrated();
|
|
52
|
+
return !!context.draftMode && (!context.serverDraft || hydrated);
|
|
53
|
+
}
|
|
54
|
+
|
|
11
55
|
/** What `useVal` gives back — see `ResolvedVal` in `@valbuild/react/stega`. */
|
|
12
56
|
|
|
13
57
|
function useValStega(selector) {
|
|
14
58
|
var valOverlayContext = useValOverlayContext();
|
|
59
|
+
var encodes = useEncodesEditTags(valOverlayContext);
|
|
15
60
|
var moduleIds = React.useMemo(function () {
|
|
16
61
|
return getModuleIds(selector);
|
|
17
62
|
}, [selector]);
|
|
@@ -64,7 +109,7 @@ function useValStega(selector) {
|
|
|
64
109
|
React.use(store.waitForLoad(moduleIds));
|
|
65
110
|
}
|
|
66
111
|
return stegaEncode(selector, {
|
|
67
|
-
disabled: !
|
|
112
|
+
disabled: !encodes,
|
|
68
113
|
getModule: function getModule(moduleId) {
|
|
69
114
|
if (moduleMap && valOverlayContext.draftMode) {
|
|
70
115
|
return moduleMap[moduleId];
|
|
@@ -151,6 +196,7 @@ var jsonEntryPromiseCache = new Map();
|
|
|
151
196
|
*/
|
|
152
197
|
function useValKeyStega(selector, key) {
|
|
153
198
|
var valOverlayContext = useValOverlayContext();
|
|
199
|
+
var encodes = useEncodesEditTags(valOverlayContext);
|
|
154
200
|
// A view is a pointer: everything below reads a path, a schema and a source
|
|
155
201
|
// off this, and a pointer has none of them. See `resolveViewedModule`.
|
|
156
202
|
var valModule = Internal.resolveViewedModule(selector);
|
|
@@ -167,7 +213,7 @@ function useValKeyStega(selector, key) {
|
|
|
167
213
|
content = readCommittedJsonEntry(valModule, key);
|
|
168
214
|
}
|
|
169
215
|
return stegaEncode(content, {
|
|
170
|
-
disabled: !
|
|
216
|
+
disabled: !encodes,
|
|
171
217
|
root: getJsonEntryStegaRoot(valModule, key)
|
|
172
218
|
});
|
|
173
219
|
}
|
|
@@ -226,6 +272,7 @@ function useValRouteStega(selector, params) {
|
|
|
226
272
|
// router `val` is unused (we resolve a single entry below instead); for any
|
|
227
273
|
// other router `draftSource` is.
|
|
228
274
|
var val = useValStega(valModule);
|
|
275
|
+
var encodes = useEncodesEditTags(valOverlayContext);
|
|
229
276
|
var draftSource = useDraftModuleSource(valModule && Internal.getValPath(valModule) || undefined);
|
|
230
277
|
var resolvedParams = resolveParams(params);
|
|
231
278
|
// Careful: null means there was an error - undefined means no params
|
|
@@ -255,7 +302,7 @@ function useValRouteStega(selector, params) {
|
|
|
255
302
|
return null;
|
|
256
303
|
}
|
|
257
304
|
return stegaEncode(content, {
|
|
258
|
-
disabled: !
|
|
305
|
+
disabled: !encodes,
|
|
259
306
|
root: getJsonEntryStegaRoot(valModule, url)
|
|
260
307
|
});
|
|
261
308
|
}
|
package/dist/{ValOverlayContext-5f1d8da4.cjs.prod.js → ValOverlayContext-2739cc60.cjs.prod.js}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var createForOfIteratorHelper = require('./createForOfIteratorHelper-
|
|
3
|
+
var createForOfIteratorHelper = require('./createForOfIteratorHelper-9afd7d2d.cjs.prod.js');
|
|
4
4
|
var patch = require('@valbuild/core/patch');
|
|
5
5
|
var React = require('react');
|
|
6
6
|
var jsxRuntime = require('react/jsx-runtime');
|
|
@@ -273,6 +273,7 @@ function ValOverlayProvider(_ref) {
|
|
|
273
273
|
suspend = _ref.suspend,
|
|
274
274
|
draftModeReady = _ref.draftModeReady,
|
|
275
275
|
draftSourcesSynced = _ref.draftSourcesSynced,
|
|
276
|
+
serverDraft = _ref.serverDraft,
|
|
276
277
|
children = _ref.children;
|
|
277
278
|
return /*#__PURE__*/jsxRuntime.jsx(ValOverlayContext.Provider, {
|
|
278
279
|
value: {
|
|
@@ -280,7 +281,8 @@ function ValOverlayProvider(_ref) {
|
|
|
280
281
|
draftMode: draftMode,
|
|
281
282
|
suspend: suspend,
|
|
282
283
|
draftModeReady: draftModeReady,
|
|
283
|
-
draftSourcesSynced: draftSourcesSynced
|
|
284
|
+
draftSourcesSynced: draftSourcesSynced,
|
|
285
|
+
serverDraft: serverDraft
|
|
284
286
|
},
|
|
285
287
|
children: children
|
|
286
288
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as _toPropertyKey, b as _createForOfIteratorHelper, d as _defineProperty } from './createForOfIteratorHelper-
|
|
1
|
+
import { c as _toPropertyKey, b as _createForOfIteratorHelper, d as _defineProperty } from './createForOfIteratorHelper-93a62170.esm.js';
|
|
2
2
|
import { deepEqual } from '@valbuild/core/patch';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { jsx } from 'react/jsx-runtime';
|
|
@@ -267,6 +267,7 @@ function ValOverlayProvider(_ref) {
|
|
|
267
267
|
suspend = _ref.suspend,
|
|
268
268
|
draftModeReady = _ref.draftModeReady,
|
|
269
269
|
draftSourcesSynced = _ref.draftSourcesSynced,
|
|
270
|
+
serverDraft = _ref.serverDraft,
|
|
270
271
|
children = _ref.children;
|
|
271
272
|
return /*#__PURE__*/jsx(ValOverlayContext.Provider, {
|
|
272
273
|
value: {
|
|
@@ -274,7 +275,8 @@ function ValOverlayProvider(_ref) {
|
|
|
274
275
|
draftMode: draftMode,
|
|
275
276
|
suspend: suspend,
|
|
276
277
|
draftModeReady: draftModeReady,
|
|
277
|
-
draftSourcesSynced: draftSourcesSynced
|
|
278
|
+
draftSourcesSynced: draftSourcesSynced,
|
|
279
|
+
serverDraft: serverDraft
|
|
278
280
|
},
|
|
279
281
|
children: children
|
|
280
282
|
});
|
package/dist/{ValOverlayContext-3ec15518.cjs.dev.js → ValOverlayContext-bafe3de9.cjs.dev.js}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var createForOfIteratorHelper = require('./createForOfIteratorHelper-
|
|
3
|
+
var createForOfIteratorHelper = require('./createForOfIteratorHelper-4497beef.cjs.dev.js');
|
|
4
4
|
var patch = require('@valbuild/core/patch');
|
|
5
5
|
var React = require('react');
|
|
6
6
|
var jsxRuntime = require('react/jsx-runtime');
|
|
@@ -273,6 +273,7 @@ function ValOverlayProvider(_ref) {
|
|
|
273
273
|
suspend = _ref.suspend,
|
|
274
274
|
draftModeReady = _ref.draftModeReady,
|
|
275
275
|
draftSourcesSynced = _ref.draftSourcesSynced,
|
|
276
|
+
serverDraft = _ref.serverDraft,
|
|
276
277
|
children = _ref.children;
|
|
277
278
|
return /*#__PURE__*/jsxRuntime.jsx(ValOverlayContext.Provider, {
|
|
278
279
|
value: {
|
|
@@ -280,7 +281,8 @@ function ValOverlayProvider(_ref) {
|
|
|
280
281
|
draftMode: draftMode,
|
|
281
282
|
suspend: suspend,
|
|
282
283
|
draftModeReady: draftModeReady,
|
|
283
|
-
draftSourcesSynced: draftSourcesSynced
|
|
284
|
+
draftSourcesSynced: draftSourcesSynced,
|
|
285
|
+
serverDraft: serverDraft
|
|
284
286
|
},
|
|
285
287
|
children: children
|
|
286
288
|
});
|
|
@@ -150,8 +150,10 @@ function _createForOfIteratorHelper(r, e) {
|
|
|
150
150
|
};
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
+
exports._arrayLikeToArray = _arrayLikeToArray;
|
|
153
154
|
exports._createForOfIteratorHelper = _createForOfIteratorHelper;
|
|
154
155
|
exports._defineProperty = _defineProperty;
|
|
155
156
|
exports._objectSpread2 = _objectSpread2;
|
|
156
157
|
exports._slicedToArray = _slicedToArray;
|
|
157
158
|
exports._toPropertyKey = _toPropertyKey;
|
|
159
|
+
exports._unsupportedIterableToArray = _unsupportedIterableToArray;
|
package/dist/{createForOfIteratorHelper-485c2ce1.esm.js → createForOfIteratorHelper-93a62170.esm.js}
RENAMED
|
@@ -148,4 +148,4 @@ function _createForOfIteratorHelper(r, e) {
|
|
|
148
148
|
};
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
export { _objectSpread2 as _, _slicedToArray as a, _createForOfIteratorHelper as b, _toPropertyKey as c, _defineProperty as d };
|
|
151
|
+
export { _objectSpread2 as _, _slicedToArray as a, _createForOfIteratorHelper as b, _toPropertyKey as c, _defineProperty as d, _arrayLikeToArray as e, _unsupportedIterableToArray as f };
|
|
@@ -150,8 +150,10 @@ function _createForOfIteratorHelper(r, e) {
|
|
|
150
150
|
};
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
+
exports._arrayLikeToArray = _arrayLikeToArray;
|
|
153
154
|
exports._createForOfIteratorHelper = _createForOfIteratorHelper;
|
|
154
155
|
exports._defineProperty = _defineProperty;
|
|
155
156
|
exports._objectSpread2 = _objectSpread2;
|
|
156
157
|
exports._slicedToArray = _slicedToArray;
|
|
157
158
|
exports._toPropertyKey = _toPropertyKey;
|
|
159
|
+
exports._unsupportedIterableToArray = _unsupportedIterableToArray;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Json, ModuleFilePath } from "@valbuild/core";
|
|
2
|
+
/**
|
|
3
|
+
* What a draft page shows, read by the server for the request that renders it.
|
|
4
|
+
*
|
|
5
|
+
* The source of every module the editor's draft CHANGES -- the ones with
|
|
6
|
+
* patches applied, published-not-yet-built ones included -- and nothing
|
|
7
|
+
* else: a module without changes is the build's own source, which the page
|
|
8
|
+
* already has. Handed to `<ValProvider draft>` so the server's render and the
|
|
9
|
+
* browser's first render resolve the same text, and the page never shows the
|
|
10
|
+
* published version first and the draft a moment later.
|
|
11
|
+
*
|
|
12
|
+
* A `.jsonValues()` module is in the shape the Studio's own store gives it: the
|
|
13
|
+
* entries the draft edits hold their content, and every other entry is the
|
|
14
|
+
* thunkless marker the hooks resolve from the bundle.
|
|
15
|
+
*
|
|
16
|
+
* Plain JSON, because it travels from a server function to the browser in the
|
|
17
|
+
* page's loader data. `fetchValDraft` in `@valbuild/tanstack/server` reads it.
|
|
18
|
+
*/
|
|
19
|
+
export type ValDraft = {
|
|
20
|
+
sources: Record<ModuleFilePath, Json>;
|
|
21
|
+
};
|
|
@@ -15,6 +15,7 @@ export { type SelectorSource, type SelectorOf, GenericSelector, } from "@valbuil
|
|
|
15
15
|
export { ValRichText } from "@valbuild/react/internal";
|
|
16
16
|
export { type ValEncodedString, type File, type Image, type RichText, } from "@valbuild/react/stega";
|
|
17
17
|
export { ValProvider } from "./ValProvider.js";
|
|
18
|
+
export type { ValDraft } from "./ValDraft.js";
|
|
18
19
|
export { ValImage, type ValImageProps } from "./ValImage.js";
|
|
19
20
|
export { ValApp } from "./ValApp.js";
|
|
20
21
|
export { ValModulesClient, useRegisterValModules } from "./ValModulesClient.js";
|
|
@@ -2,6 +2,7 @@ export { initValServer } from "./initValServer.js";
|
|
|
2
2
|
export { InMemoryPatchStore, type ValPatchStore } from "@valbuild/server";
|
|
3
3
|
export type { ValHttpMode } from "./initValServer.js";
|
|
4
4
|
export { initValContent } from "./initValContent.js";
|
|
5
|
+
export type { ValDraft } from "../ValDraft.js";
|
|
5
6
|
export { valDraftMode, hasValEnableCookieOnServer, VAL_DRAFT_MODE_COOKIE, type ValDraftMode, } from "./valDraftMode.js";
|
|
6
7
|
export { initValMcp } from "./initValMcp.js";
|
|
7
8
|
export { createPrettierFormatter, type PrettierLike, type ValFormatter, } from "@valbuild/server";
|