@hueest/xray 0.6.0 → 0.7.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/LICENSE +21 -0
- package/README.md +14 -12
- package/dist/client.d.ts +42 -51
- package/dist/client.js +134 -141
- package/dist/core.d.ts +34 -44
- package/dist/core.js +27 -33
- package/dist/css-escape-DJ-BsrNm.js +47 -0
- package/dist/hud.d.ts +7 -8
- package/dist/hud.js +5 -5
- package/dist/index.d.ts +251 -284
- package/dist/index.js +292 -338
- package/dist/measure-CUQxB-Ic.d.ts +524 -0
- package/dist/{plate-BwJUgHDc.js → plate-CXIh5_OB.js} +52 -59
- package/dist/react.core-BS2yvqeh.js +301 -0
- package/dist/react.core-BkJoCgWJ.d.ts +115 -0
- package/dist/react.d.ts +11 -13
- package/dist/react.dev.d.ts +4 -6
- package/dist/react.dev.js +54 -61
- package/dist/react.js +21 -21
- package/dist/{project-BAXKpnfF.js → serialize-Cj-EHvMv.js} +872 -1026
- package/package.json +8 -6
- package/virtual.d.ts +25 -32
- package/dist/css-escape-N7bOusGW.js +0 -52
- package/dist/react.core-DeEli0Lp.js +0 -307
- package/dist/react.core-sJfIcaXX.d.ts +0 -102
- package/dist/serialize-BqbQVxYl.d.ts +0 -564
package/dist/react.dev.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as BOUNDARY_ATTR } from "./plate-
|
|
2
|
-
import { a as markStitchesLive, c as useSkeletonTiming, i as isStitchLive, n as collectStitchNames, o as renderPlate, r as isRenderProp, s as resolveContent, t as SuspendWhileLoading } from "./react.core-
|
|
1
|
+
import { n as BOUNDARY_ATTR } from "./plate-CXIh5_OB.js";
|
|
2
|
+
import { a as markStitchesLive, c as useSkeletonTiming, i as isStitchLive, n as collectStitchNames, o as renderPlate, r as isRenderProp, s as resolveContent, t as SuspendWhileLoading } from "./react.core-BS2yvqeh.js";
|
|
3
3
|
import { Suspense, useCallback, useEffect, useRef, useState, useSyncExternalStore } from "react";
|
|
4
4
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
//#region src/react.dev.tsx
|
|
@@ -16,36 +16,31 @@ function useReplayOn() {
|
|
|
16
16
|
return useSyncExternalStore(replay?.subscribe ?? noSubscribe, replay?.get ?? alwaysFalse, alwaysFalse);
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
|
-
* The Fixtures (ADR 0015) seam, applied at the ready (`loading=false`) path right
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* confirmed).
|
|
19
|
+
* The Fixtures (ADR 0015) seam, applied at the ready (`loading=false`) path right before
|
|
20
|
+
* `resolveContent`. It is the ONE place Record reads `data` and Replay substitutes it — the
|
|
21
|
+
* render-prop `data` argument is in scope here.
|
|
23
22
|
*
|
|
24
|
-
* Replay: when the toggle is on and a Fixture exists, the recorded `data` is
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* width
|
|
31
|
-
*
|
|
32
|
-
* no new capture trigger (open Q2, confirmed — capture follows whatever renders,
|
|
33
|
-
* ADR 0002).
|
|
23
|
+
* Replay: when the toggle is on and a Fixture exists, the recorded `data` is substituted for the
|
|
24
|
+
* live `data` according to `replayMode` — `'prefer'` always uses the Fixture; `'missing-only'` uses
|
|
25
|
+
* it only when live `data` is NULLISH (`missing ≡ nullish`, so an empty array/object is present and
|
|
26
|
+
* stays capturable). The substituted value is returned synchronously so it feeds `resolveContent`
|
|
27
|
+
* for THIS render; the capture-all sweep only re-renders at each width and reads the SAME Fixture
|
|
28
|
+
* from the store (which the sweep never changes per width), so every View is captured from one
|
|
29
|
+
* width-independent Fixture with no new capture trigger (capture follows whatever renders, ADR
|
|
30
|
+
* 0002).
|
|
34
31
|
*
|
|
35
|
-
* Record: the live `data` is registered (in an effect, so render stays pure) so
|
|
36
|
-
* the
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* other.
|
|
32
|
+
* Record: the live `data` is registered (in an effect, so render stays pure) so the HUD button and
|
|
33
|
+
* the auto modes always have the current input in scope. The auto modes (`'first-ready'`,
|
|
34
|
+
* `'always'`) fire from the same effect; `'manual'` (the default) records nothing automatically.
|
|
35
|
+
* Register and auto-record the LIVE `data`, never the replayed value, so Replay and Record never
|
|
36
|
+
* feed each other.
|
|
41
37
|
*
|
|
42
|
-
* Only the render-prop children form is the `data` seam (ADR 0014/0015), so
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* still a render prop and participates exactly as any other.
|
|
38
|
+
* Only the render-prop children form is the `data` seam (ADR 0014/0015), so Fixtures apply to it
|
|
39
|
+
* alone: `renderProp` gates participation. A plain-children Skeleton has no `data` input, so it
|
|
40
|
+
* must NOT register, auto-record, or replay — the hook is a pass-through for it, which keeps a
|
|
41
|
+
* never-registered plain name out of `recordAll` and lets `record(name)` throw loudly (no
|
|
42
|
+
* render-prop data) as the store contract documents. A render-prop Skeleton passed
|
|
43
|
+
* `data={undefined}` is still a render prop and participates exactly as any other.
|
|
49
44
|
*/
|
|
50
45
|
function useFixtureData(name, data, renderProp) {
|
|
51
46
|
const replayOn = useReplayOn();
|
|
@@ -72,8 +67,8 @@ function useFixtureData(name, data, renderProp) {
|
|
|
72
67
|
return recordedFixture.data;
|
|
73
68
|
}
|
|
74
69
|
/**
|
|
75
|
-
* The plate to render: the freshest capture from the client store (hot-swapped
|
|
76
|
-
*
|
|
70
|
+
* The plate to render: the freshest capture from the client store (hot-swapped in place, no
|
|
71
|
+
* remount) when present, else the imported prop.
|
|
77
72
|
*/
|
|
78
73
|
function useLivePlate(plate) {
|
|
79
74
|
const store = globalThis.__XRAY__?.plates;
|
|
@@ -82,10 +77,9 @@ function useLivePlate(plate) {
|
|
|
82
77
|
return useSyncExternalStore(subscribe, getSnapshot, () => plate);
|
|
83
78
|
}
|
|
84
79
|
/**
|
|
85
|
-
* Dev `<Skeleton>`: production behavior plus the Light Box override, the
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* `react.tsx`.
|
|
80
|
+
* Dev `<Skeleton>`: production behavior plus the Light Box override, the live-store hot-swap, and
|
|
81
|
+
* browse-time capture. The xray plugin aliases `@hueest/xray/react` to this module in `serve`;
|
|
82
|
+
* production gets the lean `react.tsx`.
|
|
89
83
|
*/
|
|
90
84
|
function Skeleton(props) {
|
|
91
85
|
const { plate, css, loading = false, suspense = false, fallback, delay, children, data, captureWalker, maxNodes, maxBreadth, maxDepth } = props;
|
|
@@ -132,10 +126,10 @@ function Content(props) {
|
|
|
132
126
|
return /* @__PURE__ */ jsx(CaptureBoundary, { ...props });
|
|
133
127
|
}
|
|
134
128
|
/**
|
|
135
|
-
* Assemble the per-site Collect limits (ADR 0022) from the flat `<Skeleton>` props
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
129
|
+
* Assemble the per-site Collect limits (ADR 0022) from the flat `<Skeleton>` props into the nested
|
|
130
|
+
* shape `captured` expects, or `undefined` when none are set (so the client's plugin defaults
|
|
131
|
+
* apply). Called inside the capture effect, keyed on the flat primitives, so it never builds an
|
|
132
|
+
* object during render.
|
|
139
133
|
*/
|
|
140
134
|
function collectLimits(maxNodes, maxBreadth, maxDepth) {
|
|
141
135
|
if (maxNodes === void 0 && maxBreadth === void 0 && maxDepth === void 0) return void 0;
|
|
@@ -146,12 +140,11 @@ function collectLimits(maxNodes, maxBreadth, maxDepth) {
|
|
|
146
140
|
};
|
|
147
141
|
}
|
|
148
142
|
/**
|
|
149
|
-
* `root="auto"` (default): the existing `display:contents` boundary wrapper marks
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
* plain children do.
|
|
143
|
+
* `root="auto"` (default): the existing `display:contents` boundary wrapper marks the capture seam
|
|
144
|
+
* so a parent capture stops here and references this plate by name rather than re-serializing the
|
|
145
|
+
* content (ADR 0006). A render prop is called with the verbatim `data` and a no-op `ref` (the
|
|
146
|
+
* wrapper, not the consumer's element, carries the marker); its result renders inside the wrapper
|
|
147
|
+
* exactly as plain children do.
|
|
155
148
|
*/
|
|
156
149
|
function CaptureBoundary({ plate, delay, children, data, captureWalker, maxNodes, maxBreadth, maxDepth }) {
|
|
157
150
|
const ref = useRef(null);
|
|
@@ -181,17 +174,15 @@ function CaptureBoundary({ plate, delay, children, data, captureWalker, maxNodes
|
|
|
181
174
|
});
|
|
182
175
|
}
|
|
183
176
|
/**
|
|
184
|
-
* `root="manual"` (ADR 0014): no wrapper. The render prop is handed a CALLBACK
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
* `BOUNDARY_ATTR ?? ROOT_ATTR`) and cannot tell a manual root from an auto one.
|
|
177
|
+
* `root="manual"` (ADR 0014): no wrapper. The render prop is handed a CALLBACK ref that, when
|
|
178
|
+
* spread onto the consumer's root element, writes the existing `data-xr-boundary` marker onto it
|
|
179
|
+
* and registers it as the capture root, so a parent capture reads the identical marker
|
|
180
|
+
* (`measure.ts` does `BOUNDARY_ATTR ?? ROOT_ATTR`) and cannot tell a manual root from an auto one.
|
|
189
181
|
*
|
|
190
|
-
* If the consumer forgets to spread the ref, the marker never lands and the
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
* when it did not.
|
|
182
|
+
* If the consumer forgets to spread the ref, the marker never lands and the parent capture descends
|
|
183
|
+
* into and silently swallows this subtree's DOM: the exact stitch-isolation breakage ADR 0006
|
|
184
|
+
* prevents, and the worst failure xray can produce. A dev-time effect asserts the ref fired and
|
|
185
|
+
* loudly `console.error`s when it did not.
|
|
195
186
|
*/
|
|
196
187
|
function ManualBoundary({ plate, delay, children, data, captureWalker, maxNodes, maxBreadth, maxDepth }) {
|
|
197
188
|
const disposeRef = useRef(void 0);
|
|
@@ -222,9 +213,11 @@ function ManualBoundary({ plate, delay, children, data, captureWalker, maxNodes,
|
|
|
222
213
|
}, [plate.name]);
|
|
223
214
|
return /* @__PURE__ */ jsx(Fragment$1, { children: resolveContent(children, useFixtureData(plate.name, data, isRenderProp(children)), ref) });
|
|
224
215
|
}
|
|
225
|
-
/**
|
|
226
|
-
*
|
|
227
|
-
* hot-swap (which pushes a refs-less plate).
|
|
216
|
+
/**
|
|
217
|
+
* Render a plate's skeleton, seeding the live store from its resolved refs so a stitch resolves
|
|
218
|
+
* before its child is re-captured and survives a parent hot-swap (which pushes a refs-less plate).
|
|
219
|
+
* Never overwrites a live capture.
|
|
220
|
+
*/
|
|
228
221
|
function PlateView({ plate, css, fallback, nested = false, rootRef, instant }) {
|
|
229
222
|
useEffect(() => {
|
|
230
223
|
const store = globalThis.__XRAY__?.plates;
|
|
@@ -238,9 +231,9 @@ function PlateView({ plate, css, fallback, nested = false, rootRef, instant }) {
|
|
|
238
231
|
}), nested, rootRef, instant, css);
|
|
239
232
|
}
|
|
240
233
|
/**
|
|
241
|
-
* A stitch in dev: resolve the child plate from the live store (so re-capturing
|
|
242
|
-
*
|
|
243
|
-
*
|
|
234
|
+
* A stitch in dev: resolve the child plate from the live store (so re-capturing it hot-swaps it
|
|
235
|
+
* inside every parent), falling back to the parent's statically imported `refs` until the first
|
|
236
|
+
* capture lands.
|
|
244
237
|
*/
|
|
245
238
|
function RefNode({ name, staticRefs }) {
|
|
246
239
|
const store = globalThis.__XRAY__?.plates;
|
package/dist/react.js
CHANGED
|
@@ -1,33 +1,32 @@
|
|
|
1
|
-
import { a as markStitchesLive, c as useSkeletonTiming, i as isStitchLive, n as collectStitchNames, o as renderPlate, s as resolveContent, t as SuspendWhileLoading } from "./react.core-
|
|
1
|
+
import { a as markStitchesLive, c as useSkeletonTiming, i as isStitchLive, n as collectStitchNames, o as renderPlate, s as resolveContent, t as SuspendWhileLoading } from "./react.core-BS2yvqeh.js";
|
|
2
2
|
import { Suspense, useEffect, useRef, useState } from "react";
|
|
3
3
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
4
4
|
//#region src/react.tsx
|
|
5
5
|
/**
|
|
6
6
|
* React adapter for rendering committed Plates through `<Skeleton>`.
|
|
7
7
|
*
|
|
8
|
-
* In production this adapter
|
|
9
|
-
* During `vite serve`, `xrayVitePlugin()` aliases this
|
|
10
|
-
* so ready children can be captured without shipping the capture client,
|
|
11
|
-
* Light Box code in production builds.
|
|
8
|
+
* In production this adapter renders only committed Plate data (its only hooks are the
|
|
9
|
+
* display-timing and instant-reveal ones). During `vite serve`, `xrayVitePlugin()` aliases this
|
|
10
|
+
* export to the dev adapter so ready children can be captured without shipping the capture client,
|
|
11
|
+
* HUD, or Light Box code in production builds.
|
|
12
12
|
*
|
|
13
13
|
* @module @hueest/xray/react
|
|
14
14
|
*/
|
|
15
15
|
/**
|
|
16
16
|
* Render a committed Plate while content is loading.
|
|
17
17
|
*
|
|
18
|
-
* Use `loading` when your data source exposes an explicit pending state. Use
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
18
|
+
* Use `loading` when your data source exposes an explicit pending state. Use `suspense` when the
|
|
19
|
+
* child suspends; in that mode `<Skeleton>` is the Suspense boundary and the Plate is the fallback.
|
|
20
|
+
* You can also render a bare Skeleton with no children when another framework or router owns the
|
|
21
|
+
* loading boundary.
|
|
22
22
|
*
|
|
23
|
-
* In dev, the plugin aliases this component to the dev adapter. When children
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* instead of serializing the child subtree again.
|
|
23
|
+
* In dev, the plugin aliases this component to the dev adapter. When children are ready, that
|
|
24
|
+
* adapter marks the capture boundary, waits for the subtree to settle, and sends the rendered DOM
|
|
25
|
+
* to the xray client. Nested `<Skeleton>` boundaries become Stitches so a parent Plate records a
|
|
26
|
+
* child Plate reference instead of serializing the child subtree again.
|
|
28
27
|
*
|
|
29
|
-
* In production this component ships no capture client, HUD, Light Box, store,
|
|
30
|
-
*
|
|
28
|
+
* In production this component ships no capture client, HUD, Light Box, store, or subscriptions.
|
|
29
|
+
* Stitches resolve from the statically imported `refs` graph.
|
|
31
30
|
*/
|
|
32
31
|
function Skeleton(props) {
|
|
33
32
|
const { plate, css, loading = false, suspense = false, fallback, children, data } = props;
|
|
@@ -57,11 +56,12 @@ function PlateView({ plate, css, fallback, rootRef, instant }) {
|
|
|
57
56
|
if (!plate.chunks) return /* @__PURE__ */ jsx(Fragment$1, { children: fallback ?? null });
|
|
58
57
|
return renderStatic(plate, false, rootRef, instant, css);
|
|
59
58
|
}
|
|
60
|
-
/**
|
|
61
|
-
*
|
|
62
|
-
* `instant` flag (ADR 0020) and the inline
|
|
63
|
-
* the outermost root only; nested stitches pass neither, so
|
|
64
|
-
* never marks or styles a nested root.
|
|
59
|
+
/**
|
|
60
|
+
* Resolve stitches statically through the import graph (ADR 0006) — pure recursion, no store, no
|
|
61
|
+
* subscription. An unknown child renders nothing. The `instant` flag (ADR 0020) and the inline
|
|
62
|
+
* `css` (two-artifact contract) ride the outermost root only; nested stitches pass neither, so
|
|
63
|
+
* `renderPlate` never marks or styles a nested root.
|
|
64
|
+
*/
|
|
65
65
|
function renderStatic(plate, nested, rootRef, instant, css) {
|
|
66
66
|
return renderPlate(plate, (name) => {
|
|
67
67
|
const child = plate.refs?.[name];
|