@remix-run/ui 0.4.0 → 0.6.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/README.md +74 -1
- package/dist/accordion/index.js +2 -2
- package/dist/accordion/primitives.d.ts +1 -1
- package/dist/accordion/primitives.js.map +1 -1
- package/dist/anchor/index.js.map +1 -1
- package/dist/animation/animate-layout-mixin.js +1 -1
- package/dist/animation/animate-layout-mixin.js.map +1 -1
- package/dist/animation/animate-mixins.js +2 -2
- package/dist/animation/animate-mixins.js.map +1 -1
- package/dist/animation/demos/color-interpolation.js +1 -1
- package/dist/animation/demos/color-interpolation.js.map +1 -1
- package/dist/animation/demos/drag-release.d.ts +1 -1
- package/dist/animation/demos/hold-to-confirm.d.ts +3 -3
- package/dist/animation/demos/material-ripple.js +1 -3
- package/dist/animation/demos/material-ripple.js.map +1 -1
- package/dist/animation/index.js +4 -4
- package/dist/animation/spring.js.map +1 -1
- package/dist/breadcrumbs/index.js +2 -2
- package/dist/button/index.js +25 -25
- package/dist/button/index.js.map +1 -1
- package/dist/checkbox/index.js +11 -9
- package/dist/checkbox/index.js.map +1 -1
- package/dist/combobox/index.js +4 -4
- package/dist/combobox/index.js.map +1 -1
- package/dist/combobox/primitives.d.ts +1 -1
- package/dist/combobox/primitives.js +5 -5
- package/dist/combobox/primitives.js.map +1 -1
- package/dist/dev/refresh.d.ts +1 -0
- package/dist/dev/refresh.js +2 -0
- package/dist/dev/refresh.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +14 -14
- package/dist/input/index.js +9 -9
- package/dist/input/index.js.map +1 -1
- package/dist/jsx-runtime.js +2 -2
- package/dist/listbox/index.js +2 -2
- package/dist/menu/hover-aim.js.map +1 -1
- package/dist/menu/index.js +3 -3
- package/dist/menu/primitives.d.ts +1 -1
- package/dist/menu/primitives.js +6 -6
- package/dist/menu/primitives.js.map +1 -1
- package/dist/popover/index.js +3 -3
- package/dist/popover/scroll-lock.js.map +1 -1
- package/dist/radio/index.js +7 -7
- package/dist/radio/index.js.map +1 -1
- package/dist/runtime/client-entry-boundary.d.ts +14 -0
- package/dist/runtime/client-entry-boundary.js +29 -0
- package/dist/runtime/client-entry-boundary.js.map +1 -0
- package/dist/runtime/component.d.ts +19 -4
- package/dist/runtime/component.js +39 -9
- package/dist/runtime/component.js.map +1 -1
- package/dist/runtime/core/attributes.js +36 -3
- package/dist/runtime/core/attributes.js.map +1 -1
- package/dist/runtime/core/children.d.ts +2 -0
- package/dist/runtime/core/children.js +26 -2
- package/dist/runtime/core/children.js.map +1 -1
- package/dist/runtime/core/props.js +2 -2
- package/dist/runtime/core/vnode.d.ts +3 -3
- package/dist/runtime/core/vnode.js +22 -1
- package/dist/runtime/core/vnode.js.map +1 -1
- package/dist/runtime/create-element.d.ts +2 -2
- package/dist/runtime/create-element.js +3 -2
- package/dist/runtime/create-element.js.map +1 -1
- package/dist/runtime/diff-dom.js +307 -220
- package/dist/runtime/diff-dom.js.map +1 -1
- package/dist/runtime/diff-props.js +3 -3
- package/dist/runtime/dom.d.ts +12 -0
- package/dist/runtime/element-function.d.ts +3 -0
- package/dist/runtime/element-function.js +2 -0
- package/dist/runtime/element-function.js.map +1 -0
- package/dist/runtime/form-navigation.d.ts +25 -0
- package/dist/runtime/form-navigation.js +132 -0
- package/dist/runtime/form-navigation.js.map +1 -0
- package/dist/runtime/frame-resolution.d.ts +5 -0
- package/dist/runtime/frame-resolution.js +10 -0
- package/dist/runtime/frame-resolution.js.map +1 -0
- package/dist/runtime/frame.d.ts +59 -15
- package/dist/runtime/frame.js +383 -114
- package/dist/runtime/frame.js.map +1 -1
- package/dist/runtime/jsx.d.ts +1 -1
- package/dist/runtime/jsx.js +1 -1
- package/dist/runtime/jsx.js.map +1 -1
- package/dist/runtime/key.d.ts +1 -0
- package/dist/runtime/key.js +2 -0
- package/dist/runtime/key.js.map +1 -0
- package/dist/runtime/mixins/attrs-mixin.js +2 -2
- package/dist/runtime/mixins/link-mixin.js +4 -3
- package/dist/runtime/mixins/link-mixin.js.map +1 -1
- package/dist/runtime/mixins/mixin.d.ts +15 -10
- package/dist/runtime/mixins/mixin.js +4 -4
- package/dist/runtime/mixins/mixin.js.map +1 -1
- package/dist/runtime/mixins/on-mixin.js +1 -1
- package/dist/runtime/mixins/ref-mixin.js +1 -1
- package/dist/runtime/module-preloader.d.ts +8 -0
- package/dist/runtime/module-preloader.js +95 -0
- package/dist/runtime/module-preloader.js.map +1 -0
- package/dist/runtime/navigation.d.ts +4 -1
- package/dist/runtime/navigation.js +157 -32
- package/dist/runtime/navigation.js.map +1 -1
- package/dist/runtime/reconcile.d.ts +11 -10
- package/dist/runtime/reconcile.js +549 -421
- package/dist/runtime/reconcile.js.map +1 -1
- package/dist/runtime/refresh.d.ts +28 -0
- package/dist/runtime/refresh.js +31 -0
- package/dist/runtime/refresh.js.map +1 -0
- package/dist/runtime/render.js +1 -1
- package/dist/runtime/render.js.map +1 -1
- package/dist/runtime/run.d.ts +3 -1
- package/dist/runtime/run.js +15 -7
- package/dist/runtime/run.js.map +1 -1
- package/dist/runtime/scheduler.js +8 -16
- package/dist/runtime/scheduler.js.map +1 -1
- package/dist/runtime/to-vnode.d.ts +2 -2
- package/dist/runtime/to-vnode.js +68 -20
- package/dist/runtime/to-vnode.js.map +1 -1
- package/dist/runtime/vdom.d.ts +4 -2
- package/dist/runtime/vdom.js +87 -42
- package/dist/runtime/vdom.js.map +1 -1
- package/dist/runtime/vnode.d.ts +138 -67
- package/dist/runtime/vnode.js +17 -12
- package/dist/runtime/vnode.js.map +1 -1
- package/dist/select/index.js +11 -11
- package/dist/select/index.js.map +1 -1
- package/dist/select/primitives.d.ts +1 -1
- package/dist/select/primitives.js +6 -6
- package/dist/server/stream.d.ts +2 -0
- package/dist/server/stream.js +74 -29
- package/dist/server/stream.js.map +1 -1
- package/dist/shared/focus-styles.d.ts +1 -1
- package/dist/shared/focus-styles.js +1 -1
- package/dist/shared/focus-styles.js.map +1 -1
- package/dist/shared/listbox-popover-styles.js +1 -1
- package/dist/shared/style-values.js +26 -26
- package/dist/shared/style-values.js.map +1 -1
- package/dist/style/css-mixin.js +3 -3
- package/dist/style/index.js +2 -2
- package/dist/style/style.js +25 -6
- package/dist/style/style.js.map +1 -1
- package/dist/style/stylesheet.d.ts +0 -1
- package/dist/style/stylesheet.js +13 -54
- package/dist/style/stylesheet.js.map +1 -1
- package/dist/tabs/index.js +11 -11
- package/dist/tabs/index.js.map +1 -1
- package/dist/tabs/primitives.d.ts +1 -1
- package/dist/test.js +1 -1
- package/dist/toggle/index.js +9 -9
- package/dist/toggle/index.js.map +1 -1
- package/dist/toggle/primitives.d.ts +1 -1
- package/package.json +10 -7
- package/src/animation/animate-mixins.ts +3 -3
- package/src/animation/demos/color-interpolation.tsx +1 -1
- package/src/button/index.ts +24 -24
- package/src/checkbox/index.ts +10 -8
- package/src/combobox/index.tsx +1 -1
- package/src/dev/refresh.ts +1 -0
- package/src/index.ts +1 -1
- package/src/input/index.ts +8 -8
- package/src/radio/index.ts +6 -5
- package/src/runtime/client-entry-boundary.ts +54 -0
- package/src/runtime/component.ts +65 -16
- package/src/runtime/core/attributes.ts +35 -1
- package/src/runtime/core/children.ts +24 -2
- package/src/runtime/core/vnode.ts +25 -4
- package/src/runtime/create-element.ts +6 -5
- package/src/runtime/demos/readme.demo.tsx +4 -4
- package/src/runtime/diff-dom.ts +370 -244
- package/src/runtime/dom.ts +331 -214
- package/src/runtime/element-function.ts +1 -0
- package/src/runtime/event-listeners.ts +1 -1
- package/src/runtime/form-navigation.ts +184 -0
- package/src/runtime/frame-resolution.ts +13 -0
- package/src/runtime/frame.ts +500 -124
- package/src/runtime/jsx.ts +3 -5
- package/src/runtime/key.ts +1 -0
- package/src/runtime/mixins/link-mixin.ts +1 -0
- package/src/runtime/mixins/mixin.ts +21 -18
- package/src/runtime/module-preloader.ts +115 -0
- package/src/runtime/navigation.ts +204 -30
- package/src/runtime/reconcile.ts +762 -759
- package/src/runtime/refresh.ts +46 -0
- package/src/runtime/run.ts +12 -2
- package/src/runtime/scheduler.ts +9 -29
- package/src/runtime/to-vnode.ts +85 -23
- package/src/runtime/vdom.ts +89 -70
- package/src/runtime/vnode.ts +192 -88
- package/src/select/index.tsx +9 -9
- package/src/server/README.md +13 -0
- package/src/server/stream.ts +93 -30
- package/src/shared/focus-styles.ts +1 -1
- package/src/shared/style-values.ts +26 -26
- package/src/style/style.ts +25 -6
- package/src/style/stylesheet.ts +32 -57
- package/src/tabs/index.tsx +12 -11
- package/src/test/README.md +151 -60
- package/src/toggle/index.tsx +9 -7
package/dist/runtime/diff-dom.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { invariant } from
|
|
1
|
+
import { invariant } from './invariant.js';
|
|
2
|
+
import { disposeClientEntryBoundary, getClientEntryBoundaryOwner } from './client-entry-boundary.js';
|
|
3
|
+
const REMIX_PRESERVE_DOM_ATTRIBUTE = 'rmx-preserve-dom';
|
|
2
4
|
export function diffNodes(curr, next, context) {
|
|
3
5
|
let parent = curr[0]?.parentNode ?? context.regionParent ?? null;
|
|
4
6
|
invariant(parent, 'Parent node not found');
|
|
@@ -6,60 +8,7 @@ export function diffNodes(curr, next, context) {
|
|
|
6
8
|
// nodes before the region tail ref rather than appending to the parent.
|
|
7
9
|
let regionTailRef = context.regionTailRef ??
|
|
8
10
|
(curr.length > 0 ? curr[curr.length - 1].nextSibling : null);
|
|
9
|
-
|
|
10
|
-
let nextIndex = 0;
|
|
11
|
-
while (currentIndex < curr.length || nextIndex < next.length) {
|
|
12
|
-
let c = curr[currentIndex];
|
|
13
|
-
let n = next[nextIndex];
|
|
14
|
-
if (!c && n) {
|
|
15
|
-
if (regionTailRef) {
|
|
16
|
-
parent.insertBefore(n, regionTailRef);
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
parent.appendChild(n);
|
|
20
|
-
}
|
|
21
|
-
nextIndex++;
|
|
22
|
-
}
|
|
23
|
-
else if (c && !n) {
|
|
24
|
-
removeNode(c, parent, context);
|
|
25
|
-
currentIndex++;
|
|
26
|
-
}
|
|
27
|
-
else if (c && n) {
|
|
28
|
-
let replacement = getCommentMarkerRangeReplacement(c, n, curr, next, currentIndex, nextIndex, context);
|
|
29
|
-
if (replacement) {
|
|
30
|
-
replaceCommentMarkerRange(replacement, parent, context);
|
|
31
|
-
currentIndex = replacement.currentEndIndex + 1;
|
|
32
|
-
nextIndex = replacement.nextEndIndex + 1;
|
|
33
|
-
continue;
|
|
34
|
-
}
|
|
35
|
-
// Skip hydrated client-entry marker ranges; hydration pass re-renders
|
|
36
|
-
// roots with new props from incoming payload
|
|
37
|
-
if (isVirtualRootStartMarker(c) && isVirtualRootStartMarker(n)) {
|
|
38
|
-
let currentEnd = findHydrationEndMarker(c);
|
|
39
|
-
let nextEnd = findHydrationEndMarker(n);
|
|
40
|
-
let nextData = n.data;
|
|
41
|
-
if (c.data !== nextData)
|
|
42
|
-
c.data = nextData;
|
|
43
|
-
let currentEndIndex = curr.indexOf(currentEnd);
|
|
44
|
-
let nextEndIndex = next.indexOf(nextEnd);
|
|
45
|
-
currentIndex = currentEndIndex + 1;
|
|
46
|
-
nextIndex = nextEndIndex + 1;
|
|
47
|
-
continue;
|
|
48
|
-
}
|
|
49
|
-
let cursor = diffNode(c, n, context);
|
|
50
|
-
if (cursor) {
|
|
51
|
-
let nextEndIndex = next.indexOf(cursor);
|
|
52
|
-
let currentEndIndex = isFrameStartMarker(c) && isFrameEndMarker(cursor)
|
|
53
|
-
? findFrameEndIndex(curr, currentIndex)
|
|
54
|
-
: currentIndex;
|
|
55
|
-
currentIndex = currentEndIndex + 1;
|
|
56
|
-
nextIndex = nextEndIndex + 1;
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
currentIndex++;
|
|
60
|
-
nextIndex++;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
11
|
+
diffSiblingUnits(curr, next, parent, regionTailRef, context);
|
|
63
12
|
}
|
|
64
13
|
function diffNode(current, next, context) {
|
|
65
14
|
// Text -> Text
|
|
@@ -80,40 +29,41 @@ function diffNode(current, next, context) {
|
|
|
80
29
|
return end;
|
|
81
30
|
}
|
|
82
31
|
// Comment -> Comment
|
|
83
|
-
if (isCommentNode(current) && isCommentNode(next)) {
|
|
32
|
+
if (isCommentNode(current) && isCommentNode(next) && markerKindsMatch(current, next)) {
|
|
84
33
|
let newData = next.data;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (
|
|
88
|
-
if (
|
|
34
|
+
let updated = false;
|
|
35
|
+
if (isFrameStartMarker(current)) {
|
|
36
|
+
if (shouldPreserveFrameStartMarker(current, next, context)) {
|
|
37
|
+
if (current.data !== newData) {
|
|
89
38
|
current.data = newData;
|
|
90
|
-
updated = true;
|
|
91
|
-
let frame = context.frameInstances.get(current);
|
|
92
|
-
let nextMarkerData = getFrameMarkerData(next, context);
|
|
93
|
-
if (frame && nextMarkerData) {
|
|
94
|
-
if (nextMarkerData.status === 'resolved') {
|
|
95
|
-
let nextEnd = findFrameEndMarker(next);
|
|
96
|
-
let nextContent = collectFrameContentFragment(current.ownerDocument, next, nextEnd);
|
|
97
|
-
void frame.renderMarkerContent({ ...nextMarkerData, id: getFrameId(next) }, nextContent, {
|
|
98
|
-
signal: context.signal,
|
|
99
|
-
});
|
|
100
|
-
return nextEnd;
|
|
101
|
-
}
|
|
102
|
-
if (frame.isDisplayingResolvedContent()) {
|
|
103
|
-
return findFrameEndMarker(next);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
39
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
40
|
+
updated = true;
|
|
41
|
+
let frame = context.frameInstances.get(current);
|
|
42
|
+
let nextMarkerData = getFrameMarkerData(next, context);
|
|
43
|
+
if (frame && nextMarkerData) {
|
|
44
|
+
if (nextMarkerData.status === 'resolved') {
|
|
45
|
+
let nextEnd = findFrameEndMarker(next);
|
|
46
|
+
let nextContent = collectFrameContentFragment(current.ownerDocument, next, nextEnd);
|
|
47
|
+
void frame.renderMarkerContent({ ...nextMarkerData, id: getFrameId(next) }, nextContent, {
|
|
48
|
+
data: context.data,
|
|
49
|
+
signal: context.signal,
|
|
50
|
+
});
|
|
51
|
+
return nextEnd;
|
|
52
|
+
}
|
|
53
|
+
if (frame.isDisplayingResolvedContent()) {
|
|
54
|
+
return findFrameEndMarker(next);
|
|
55
|
+
}
|
|
111
56
|
}
|
|
112
57
|
}
|
|
113
|
-
if (
|
|
58
|
+
else if (current.data !== newData) {
|
|
59
|
+
disposeFrameStartMarker(current, context);
|
|
114
60
|
current.data = newData;
|
|
61
|
+
updated = true;
|
|
115
62
|
}
|
|
116
63
|
}
|
|
64
|
+
if (!updated && current.data !== newData) {
|
|
65
|
+
current.data = newData;
|
|
66
|
+
}
|
|
117
67
|
return;
|
|
118
68
|
}
|
|
119
69
|
// Element -> Element
|
|
@@ -128,6 +78,8 @@ function diffNode(current, next, context) {
|
|
|
128
78
|
return;
|
|
129
79
|
}
|
|
130
80
|
// Same tag: update attributes then children
|
|
81
|
+
if (shouldPreserveDomElement(current, next))
|
|
82
|
+
return;
|
|
131
83
|
diffElementAttributes(current, next);
|
|
132
84
|
if (shouldPreserveElementChildren(current, next))
|
|
133
85
|
return;
|
|
@@ -164,6 +116,14 @@ function diffElementAttributes(current, next) {
|
|
|
164
116
|
}
|
|
165
117
|
}
|
|
166
118
|
}
|
|
119
|
+
function shouldPreserveDomElement(current, next) {
|
|
120
|
+
if (!next.hasAttribute(REMIX_PRESERVE_DOM_ATTRIBUTE))
|
|
121
|
+
return false;
|
|
122
|
+
if (!current.hasAttribute(REMIX_PRESERVE_DOM_ATTRIBUTE)) {
|
|
123
|
+
current.setAttribute(REMIX_PRESERVE_DOM_ATTRIBUTE, '');
|
|
124
|
+
}
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
167
127
|
function shouldPreserveLiveAttribute(current, next, name) {
|
|
168
128
|
if (name === 'open') {
|
|
169
129
|
if (current instanceof HTMLDetailsElement && next instanceof HTMLDetailsElement) {
|
|
@@ -219,164 +179,253 @@ function isPopoverOpen(element) {
|
|
|
219
179
|
}
|
|
220
180
|
}
|
|
221
181
|
function diffElementChildren(current, next, context) {
|
|
222
|
-
let currentChildren
|
|
223
|
-
|
|
224
|
-
//
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
let node
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
if (key != null)
|
|
231
|
-
keyToIndex.set(key, i);
|
|
182
|
+
let currentChildren;
|
|
183
|
+
// Allow actively managed preload link tags in the head to stay in the document
|
|
184
|
+
// during diffing rather than removing them which aborts the preload in Safari
|
|
185
|
+
if (context.isActiveModulePreload && current === current.ownerDocument.head) {
|
|
186
|
+
currentChildren = [];
|
|
187
|
+
for (let node of current.childNodes) {
|
|
188
|
+
if (!context.isActiveModulePreload(node))
|
|
189
|
+
currentChildren.push(node);
|
|
232
190
|
}
|
|
233
191
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
192
|
+
else {
|
|
193
|
+
currentChildren = Array.from(current.childNodes);
|
|
194
|
+
}
|
|
195
|
+
let nextChildren = Array.from(next.childNodes);
|
|
196
|
+
diffSiblingUnits(currentChildren, nextChildren, current, null, context);
|
|
197
|
+
}
|
|
198
|
+
function diffSiblingUnits(currentNodes, nextNodes, parent, regionTailRef, context) {
|
|
199
|
+
let currentUnits = parseSiblingUnits(currentNodes);
|
|
200
|
+
let nextUnits = parseSiblingUnits(nextNodes);
|
|
201
|
+
let keyToIndex = new Map();
|
|
202
|
+
for (let i = 0; i < currentUnits.length; i++) {
|
|
203
|
+
let key = getSiblingUnitKey(currentUnits[i]);
|
|
204
|
+
if (key !== undefined)
|
|
205
|
+
keyToIndex.set(key, i);
|
|
206
|
+
}
|
|
207
|
+
let used = new Array(currentUnits.length).fill(false);
|
|
208
|
+
let matchIndexForNext = new Array(nextUnits.length).fill(-1);
|
|
209
|
+
// Reserve globally matched keyed elements and semantic boundaries before
|
|
210
|
+
// positionally pairing the remaining ordinary siblings.
|
|
211
|
+
for (let i = 0; i < nextUnits.length; i++) {
|
|
212
|
+
let nextUnit = nextUnits[i];
|
|
238
213
|
let matchIndex = -1;
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
214
|
+
let key = getSiblingUnitKey(nextUnit);
|
|
215
|
+
if (key !== undefined) {
|
|
216
|
+
let keyedIndex = keyToIndex.get(key);
|
|
217
|
+
if (keyedIndex !== undefined &&
|
|
218
|
+
!used[keyedIndex] &&
|
|
219
|
+
siblingUnitsComparable(currentUnits[keyedIndex], nextUnit)) {
|
|
220
|
+
matchIndex = keyedIndex;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// Boundary identities behave like implicit keys. Repeated boundaries with
|
|
224
|
+
// the same identity are paired in source order because server markers do
|
|
225
|
+
// not carry a separate application key.
|
|
226
|
+
if (matchIndex === -1 && nextUnit.kind !== 'node') {
|
|
227
|
+
for (let j = 0; j < currentUnits.length; j++) {
|
|
228
|
+
let currentUnit = currentUnits[j];
|
|
229
|
+
if (used[j] || currentUnit.kind !== nextUnit.kind)
|
|
230
|
+
continue;
|
|
231
|
+
if (shouldPreserveBoundaryUnit(currentUnit, nextUnit, context)) {
|
|
242
232
|
matchIndex = j;
|
|
243
233
|
break;
|
|
244
234
|
}
|
|
245
235
|
}
|
|
246
236
|
}
|
|
247
|
-
else if (isElement(nextChild)) {
|
|
248
|
-
let key = nextChild.getAttribute('data-key');
|
|
249
|
-
if (key != null && keyToIndex.has(key)) {
|
|
250
|
-
let idx = keyToIndex.get(key);
|
|
251
|
-
if (!used[idx])
|
|
252
|
-
matchIndex = idx;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
if (matchIndex === -1) {
|
|
256
|
-
let candidateIndex = i;
|
|
257
|
-
if (candidateIndex < currentChildren.length &&
|
|
258
|
-
!used[candidateIndex] &&
|
|
259
|
-
nodeTypesComparable(currentChildren[candidateIndex], nextChild)) {
|
|
260
|
-
matchIndex = candidateIndex;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
237
|
if (matchIndex !== -1)
|
|
264
238
|
used[matchIndex] = true;
|
|
265
239
|
matchIndexForNext[i] = matchIndex;
|
|
266
240
|
}
|
|
267
|
-
|
|
268
|
-
let
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
// the next end marker, so skip the owned interior nodes here.
|
|
290
|
-
let nextEndIdx = nextChildren.indexOf(cursor);
|
|
291
|
-
let currEndIdx = isFrameStartMarker(curChild) && isFrameEndMarker(cursor)
|
|
292
|
-
? findFrameEndIndex(currentChildren, mi)
|
|
293
|
-
: findHydrationEndIndex(currentChildren, mi);
|
|
294
|
-
// Adjacent marker ranges can pre-match into the next range and leave an
|
|
295
|
-
// orphaned end marker behind. Clear those stale matches first.
|
|
296
|
-
for (let j = i + 1; j <= nextEndIdx; j++) {
|
|
297
|
-
let matchedIndex = matchIndexForNext[j];
|
|
298
|
-
if (matchedIndex > currEndIdx) {
|
|
299
|
-
used[matchedIndex] = false;
|
|
300
|
-
}
|
|
301
|
-
matchIndexForNext[j] = -1;
|
|
302
|
-
}
|
|
303
|
-
// Mark the entire current region as used to avoid removals.
|
|
304
|
-
for (let k = mi; k <= currEndIdx; k++)
|
|
305
|
-
used[k] = true;
|
|
306
|
-
// Preserve both comment markers in committed; skip interior in reorder pass.
|
|
307
|
-
committed[i] = curChild; // start marker
|
|
308
|
-
committed[nextEndIdx] = currentChildren[currEndIdx]; // end marker
|
|
309
|
-
for (let j = i + 1; j < nextEndIdx; j++)
|
|
310
|
-
committed[j] = undefined;
|
|
311
|
-
// Jump to end of region.
|
|
312
|
-
i = nextEndIdx;
|
|
313
|
-
continue;
|
|
314
|
-
}
|
|
315
|
-
committed[i] = curChild;
|
|
316
|
-
}
|
|
317
|
-
else {
|
|
318
|
-
committed[i] = nextChildren[i];
|
|
241
|
+
let remainingCurrentIndexes = [];
|
|
242
|
+
for (let i = 0; i < currentUnits.length; i++) {
|
|
243
|
+
if (!used[i])
|
|
244
|
+
remainingCurrentIndexes.push(i);
|
|
245
|
+
}
|
|
246
|
+
let remainingNextIndexes = [];
|
|
247
|
+
for (let i = 0; i < nextUnits.length; i++) {
|
|
248
|
+
if (matchIndexForNext[i] === -1)
|
|
249
|
+
remainingNextIndexes.push(i);
|
|
250
|
+
}
|
|
251
|
+
let remainingLength = Math.min(remainingCurrentIndexes.length, remainingNextIndexes.length);
|
|
252
|
+
for (let i = 0; i < remainingLength; i++) {
|
|
253
|
+
let currentIndex = remainingCurrentIndexes[i];
|
|
254
|
+
let nextIndex = remainingNextIndexes[i];
|
|
255
|
+
let currentUnit = currentUnits[currentIndex];
|
|
256
|
+
let nextUnit = nextUnits[nextIndex];
|
|
257
|
+
if (currentUnit.kind !== 'node' ||
|
|
258
|
+
nextUnit.kind !== 'node' ||
|
|
259
|
+
getSiblingUnitKey(currentUnit) !== undefined ||
|
|
260
|
+
getSiblingUnitKey(nextUnit) !== undefined ||
|
|
261
|
+
!siblingUnitsComparable(currentUnit, nextUnit)) {
|
|
262
|
+
continue;
|
|
319
263
|
}
|
|
264
|
+
used[currentIndex] = true;
|
|
265
|
+
matchIndexForNext[nextIndex] = currentIndex;
|
|
320
266
|
}
|
|
321
|
-
|
|
322
|
-
let
|
|
323
|
-
|
|
324
|
-
let
|
|
325
|
-
if (
|
|
267
|
+
let committed = new Array(nextUnits.length);
|
|
268
|
+
for (let i = 0; i < nextUnits.length; i++) {
|
|
269
|
+
let matchIndex = matchIndexForNext[i];
|
|
270
|
+
let nextUnit = nextUnits[i];
|
|
271
|
+
if (matchIndex === -1) {
|
|
272
|
+
committed[i] = nextUnit;
|
|
326
273
|
continue;
|
|
327
|
-
|
|
328
|
-
let
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
if (isVirtualRootStartMarker(node) ||
|
|
333
|
-
isVirtualRootEndMarker(node) ||
|
|
334
|
-
isFrameStartMarker(node) ||
|
|
335
|
-
isFrameEndMarker(node)) {
|
|
336
|
-
if (node.parentNode !== current) {
|
|
337
|
-
current.insertBefore(node, ref);
|
|
338
|
-
}
|
|
339
|
-
anchor = node;
|
|
274
|
+
}
|
|
275
|
+
let currentUnit = currentUnits[matchIndex];
|
|
276
|
+
if (currentUnit.kind === 'node' && nextUnit.kind === 'node') {
|
|
277
|
+
diffNode(currentUnit.node, nextUnit.node, context);
|
|
278
|
+
committed[i] = currentUnit;
|
|
340
279
|
continue;
|
|
341
280
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
281
|
+
invariant(currentUnit.kind !== 'node' && nextUnit.kind !== 'node', 'Expected boundaries');
|
|
282
|
+
let replacement = getCommentMarkerRangeReplacement(currentUnit.start, nextUnit.start, currentNodes, nextNodes, currentUnit.startIndex, nextUnit.startIndex, context);
|
|
283
|
+
if (replacement) {
|
|
284
|
+
replaceCommentMarkerRange(replacement, parent, context);
|
|
285
|
+
committed[i] = nextUnit;
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
let cursor = diffNode(currentUnit.start, nextUnit.start, context);
|
|
289
|
+
if (!cursor && currentUnit.kind === 'frame' && nextUnit.kind === 'frame') {
|
|
290
|
+
diffNodes(collectNodesBetween(currentUnit.start, currentUnit.end), nextNodes.slice(nextUnit.startIndex + 1, nextUnit.endIndex), {
|
|
291
|
+
...context,
|
|
292
|
+
regionParent: parent,
|
|
293
|
+
regionTailRef: currentUnit.end,
|
|
294
|
+
});
|
|
349
295
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
296
|
+
committed[i] = currentUnit;
|
|
297
|
+
}
|
|
298
|
+
let anchor = regionTailRef;
|
|
299
|
+
for (let i = committed.length - 1; i >= 0; i--) {
|
|
300
|
+
let unit = committed[i];
|
|
301
|
+
let first = getSiblingUnitFirstNode(unit);
|
|
302
|
+
let ref = anchor?.parentNode === parent ? anchor : null;
|
|
303
|
+
if (unit.kind === 'node' &&
|
|
304
|
+
isPreservedDomElement(unit.node) &&
|
|
305
|
+
unit.node.parentNode === parent) {
|
|
306
|
+
anchor = unit.node;
|
|
307
|
+
continue;
|
|
353
308
|
}
|
|
354
|
-
|
|
355
|
-
if (
|
|
356
|
-
anchor =
|
|
309
|
+
placeSiblingUnitBefore(unit, parent, ref);
|
|
310
|
+
if (first.parentNode === parent)
|
|
311
|
+
anchor = first;
|
|
312
|
+
}
|
|
313
|
+
for (let i = 0; i < currentUnits.length; i++) {
|
|
314
|
+
if (!used[i])
|
|
315
|
+
removeSiblingUnit(currentUnits[i], parent, context);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
function parseSiblingUnits(nodes) {
|
|
319
|
+
let units = [];
|
|
320
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
321
|
+
let node = nodes[i];
|
|
322
|
+
if (isVirtualRootStartMarker(node)) {
|
|
323
|
+
let endIndex = findHydrationEndIndex(nodes, i);
|
|
324
|
+
invariant(endIndex > i, 'Hydration end marker not found');
|
|
325
|
+
let end = nodes[endIndex];
|
|
326
|
+
invariant(isVirtualRootEndMarker(end), 'Expected hydration end marker');
|
|
327
|
+
units.push({ kind: 'hydration', start: node, end, startIndex: i, endIndex });
|
|
328
|
+
i = endIndex;
|
|
329
|
+
continue;
|
|
357
330
|
}
|
|
331
|
+
if (isFrameStartMarker(node)) {
|
|
332
|
+
let endIndex = findFrameEndIndex(nodes, i);
|
|
333
|
+
invariant(endIndex > i, 'Frame end marker not found');
|
|
334
|
+
let end = nodes[endIndex];
|
|
335
|
+
invariant(isFrameEndMarker(end), 'Expected frame end marker');
|
|
336
|
+
units.push({ kind: 'frame', start: node, end, startIndex: i, endIndex });
|
|
337
|
+
i = endIndex;
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
invariant(!isVirtualRootEndMarker(node), 'Unexpected hydration end marker');
|
|
341
|
+
invariant(!isFrameEndMarker(node), 'Unexpected frame end marker');
|
|
342
|
+
units.push({ kind: 'node', node, startIndex: i, endIndex: i });
|
|
358
343
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
344
|
+
return units;
|
|
345
|
+
}
|
|
346
|
+
function getSiblingUnitKey(unit) {
|
|
347
|
+
if (unit.kind !== 'node' || !isElement(unit.node))
|
|
348
|
+
return;
|
|
349
|
+
return unit.node.getAttribute('data-key') ?? undefined;
|
|
350
|
+
}
|
|
351
|
+
function siblingUnitsComparable(current, next) {
|
|
352
|
+
if (current.kind !== next.kind)
|
|
353
|
+
return false;
|
|
354
|
+
if (current.kind !== 'node' || next.kind !== 'node')
|
|
355
|
+
return true;
|
|
356
|
+
return nodeTypesComparable(current.node, next.node);
|
|
357
|
+
}
|
|
358
|
+
function shouldPreserveBoundaryUnit(current, next, context) {
|
|
359
|
+
if (current.kind !== next.kind)
|
|
360
|
+
return false;
|
|
361
|
+
return current.kind === 'frame'
|
|
362
|
+
? shouldPreserveFrameStartMarker(current.start, next.start, context)
|
|
363
|
+
: shouldPreserveHydrationStartMarker(current.start, next.start, context);
|
|
364
|
+
}
|
|
365
|
+
function getSiblingUnitFirstNode(unit) {
|
|
366
|
+
return unit.kind === 'node' ? unit.node : unit.start;
|
|
367
|
+
}
|
|
368
|
+
function placeSiblingUnitBefore(unit, parent, ref) {
|
|
369
|
+
if (unit.kind === 'node') {
|
|
370
|
+
if (unit.node.parentNode !== parent || unit.node.nextSibling !== ref) {
|
|
371
|
+
parent.insertBefore(unit.node, ref);
|
|
364
372
|
}
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
let nodes = collectNodeRange(unit.start, unit.end);
|
|
376
|
+
if (unit.start.parentNode === parent && unit.end.nextSibling === ref)
|
|
377
|
+
return;
|
|
378
|
+
let fragment = unit.start.ownerDocument.createDocumentFragment();
|
|
379
|
+
for (let node of nodes)
|
|
380
|
+
fragment.appendChild(node);
|
|
381
|
+
parent.insertBefore(fragment, ref);
|
|
382
|
+
}
|
|
383
|
+
function removeSiblingUnit(unit, parent, context) {
|
|
384
|
+
if (unit.kind === 'node') {
|
|
385
|
+
removeNode(unit.node, parent, context);
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
for (let node of collectNodeRange(unit.start, unit.end)) {
|
|
389
|
+
removeNode(node, parent, context);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
function collectNodesBetween(start, end) {
|
|
393
|
+
let nodes = [];
|
|
394
|
+
let node = start.nextSibling;
|
|
395
|
+
while (node && node !== end) {
|
|
396
|
+
nodes.push(node);
|
|
397
|
+
node = node.nextSibling;
|
|
365
398
|
}
|
|
399
|
+
return nodes;
|
|
400
|
+
}
|
|
401
|
+
function isPreservedDomElement(node) {
|
|
402
|
+
return isElement(node) && node.hasAttribute(REMIX_PRESERVE_DOM_ATTRIBUTE);
|
|
366
403
|
}
|
|
367
404
|
function nodeTypesComparable(a, b) {
|
|
368
405
|
if (isTextNode(a) && isTextNode(b))
|
|
369
406
|
return true;
|
|
370
407
|
if (isElement(a) && isElement(b))
|
|
371
408
|
return a.tagName === b.tagName;
|
|
372
|
-
if (isVirtualRootStartMarker(a) && isVirtualRootStartMarker(b))
|
|
373
|
-
return true;
|
|
374
|
-
if (isVirtualRootEndMarker(a) && isVirtualRootEndMarker(b))
|
|
375
|
-
return true;
|
|
376
409
|
if (isCommentNode(a) && isCommentNode(b))
|
|
377
|
-
return
|
|
410
|
+
return markerKindsMatch(a, b);
|
|
378
411
|
return false;
|
|
379
412
|
}
|
|
413
|
+
function getMarkerKind(node) {
|
|
414
|
+
if (!isCommentNode(node))
|
|
415
|
+
return undefined;
|
|
416
|
+
if (isFrameStartMarker(node))
|
|
417
|
+
return 'frame-start';
|
|
418
|
+
if (isFrameEndMarker(node))
|
|
419
|
+
return 'frame-end';
|
|
420
|
+
if (isVirtualRootStartMarker(node))
|
|
421
|
+
return 'virtual-root-start';
|
|
422
|
+
if (isVirtualRootEndMarker(node))
|
|
423
|
+
return 'virtual-root-end';
|
|
424
|
+
return undefined;
|
|
425
|
+
}
|
|
426
|
+
function markerKindsMatch(a, b) {
|
|
427
|
+
return getMarkerKind(a) === getMarkerKind(b);
|
|
428
|
+
}
|
|
380
429
|
function isHydrationEndComment(node) {
|
|
381
430
|
return isCommentNode(node) && node.data.trim() === '/rmx:h';
|
|
382
431
|
}
|
|
@@ -398,9 +447,16 @@ function findHydrationEndMarker(start) {
|
|
|
398
447
|
throw new Error('Hydration end marker not found');
|
|
399
448
|
}
|
|
400
449
|
function findHydrationEndIndex(nodes, startIdx) {
|
|
450
|
+
let depth = 1;
|
|
401
451
|
for (let j = startIdx + 1; j < nodes.length; j++) {
|
|
402
|
-
|
|
403
|
-
|
|
452
|
+
let node = nodes[j];
|
|
453
|
+
if (isVirtualRootStartMarker(node))
|
|
454
|
+
depth++;
|
|
455
|
+
if (isHydrationEndComment(node)) {
|
|
456
|
+
depth--;
|
|
457
|
+
if (depth === 0)
|
|
458
|
+
return j;
|
|
459
|
+
}
|
|
404
460
|
}
|
|
405
461
|
return startIdx;
|
|
406
462
|
}
|
|
@@ -451,12 +507,21 @@ function isFrameEndMarker(node) {
|
|
|
451
507
|
function shouldPreserveFrameStartMarker(current, next, context) {
|
|
452
508
|
if (!isFrameStartMarker(next))
|
|
453
509
|
return false;
|
|
454
|
-
let currentData = getFrameMarkerData(current, context);
|
|
455
510
|
let nextData = getFrameMarkerData(next, context);
|
|
456
|
-
|
|
511
|
+
let currentFrame = context.frameInstances.get(current);
|
|
512
|
+
return (currentFrame !== undefined &&
|
|
457
513
|
nextData !== undefined &&
|
|
458
|
-
|
|
459
|
-
|
|
514
|
+
currentFrame.matchesIdentity(nextData.src, nextData.name));
|
|
515
|
+
}
|
|
516
|
+
function shouldPreserveHydrationStartMarker(current, next, context) {
|
|
517
|
+
if (!isVirtualRootStartMarker(next))
|
|
518
|
+
return false;
|
|
519
|
+
let currentOwner = getClientEntryBoundaryOwner(current);
|
|
520
|
+
let nextData = getHydrationMarkerData(next, context);
|
|
521
|
+
return (currentOwner !== undefined &&
|
|
522
|
+
nextData !== undefined &&
|
|
523
|
+
currentOwner.identity.moduleUrl === nextData.moduleUrl &&
|
|
524
|
+
currentOwner.identity.exportName === nextData.exportName);
|
|
460
525
|
}
|
|
461
526
|
function getCommentMarkerRangeReplacement(current, next, currentNodes, nextNodes, currentIndex, nextIndex, context) {
|
|
462
527
|
// Comment markers can represent owned DOM ranges, not standalone comments. If
|
|
@@ -472,6 +537,25 @@ function getCommentMarkerRangeReplacement(current, next, currentNodes, nextNodes
|
|
|
472
537
|
nextEndIndex: findFrameEndIndex(nextNodes, nextIndex),
|
|
473
538
|
};
|
|
474
539
|
}
|
|
540
|
+
if (isVirtualRootStartMarker(current) &&
|
|
541
|
+
isVirtualRootStartMarker(next) &&
|
|
542
|
+
!shouldPreserveHydrationStartMarker(current, next, context)) {
|
|
543
|
+
return {
|
|
544
|
+
currentStart: current,
|
|
545
|
+
nextStart: next,
|
|
546
|
+
currentEndIndex: findHydrationEndIndex(currentNodes, currentIndex),
|
|
547
|
+
nextEndIndex: findHydrationEndIndex(nextNodes, nextIndex),
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
function getHydrationMarkerData(marker, context) {
|
|
552
|
+
let id = getHydrationId(marker);
|
|
553
|
+
return context.data.h?.[id];
|
|
554
|
+
}
|
|
555
|
+
function getHydrationId(marker) {
|
|
556
|
+
let trimmed = marker.data.trim();
|
|
557
|
+
invariant(trimmed.startsWith('rmx:h:'), 'Invalid hydration start marker');
|
|
558
|
+
return trimmed.slice('rmx:h:'.length);
|
|
475
559
|
}
|
|
476
560
|
function getFrameMarkerData(marker, context) {
|
|
477
561
|
let id = getFrameId(marker);
|
|
@@ -483,8 +567,8 @@ function getFrameId(marker) {
|
|
|
483
567
|
return trimmed.slice('rmx:f:'.length);
|
|
484
568
|
}
|
|
485
569
|
function replaceCommentMarkerRange(replacement, parent, context) {
|
|
486
|
-
let currentEnd =
|
|
487
|
-
let nextEnd =
|
|
570
|
+
let currentEnd = findCommentMarkerRangeEnd(replacement.currentStart);
|
|
571
|
+
let nextEnd = findCommentMarkerRangeEnd(replacement.nextStart);
|
|
488
572
|
let nextNodes = collectNodeRange(replacement.nextStart, nextEnd);
|
|
489
573
|
let currentNodes = collectNodeRange(replacement.currentStart, currentEnd);
|
|
490
574
|
for (let node of nextNodes) {
|
|
@@ -494,6 +578,13 @@ function replaceCommentMarkerRange(replacement, parent, context) {
|
|
|
494
578
|
removeNode(node, parent, context);
|
|
495
579
|
}
|
|
496
580
|
}
|
|
581
|
+
function findCommentMarkerRangeEnd(start) {
|
|
582
|
+
if (isFrameStartMarker(start))
|
|
583
|
+
return findFrameEndMarker(start);
|
|
584
|
+
if (isVirtualRootStartMarker(start))
|
|
585
|
+
return findHydrationEndMarker(start);
|
|
586
|
+
throw new Error('Comment marker range start not found');
|
|
587
|
+
}
|
|
497
588
|
function collectNodeRange(start, end) {
|
|
498
589
|
let nodes = [];
|
|
499
590
|
let node = start;
|
|
@@ -528,8 +619,7 @@ function disposeRemovedVirtualRoots(node) {
|
|
|
528
619
|
let next = stack.pop();
|
|
529
620
|
if (!next)
|
|
530
621
|
continue;
|
|
531
|
-
if (
|
|
532
|
-
next.$rmx.dispose();
|
|
622
|
+
if (isVirtualRootStartMarker(next) && disposeClientEntryBoundary(next)) {
|
|
533
623
|
continue;
|
|
534
624
|
}
|
|
535
625
|
for (let child of Array.from(next.childNodes)) {
|
|
@@ -561,9 +651,6 @@ function disposeFrameStartMarker(marker, context) {
|
|
|
561
651
|
function isVirtualRootStartMarker(node) {
|
|
562
652
|
return isCommentNode(node) && node.data.trim().startsWith('rmx:h:');
|
|
563
653
|
}
|
|
564
|
-
function isHydratedVirtualRootStartMarker(node) {
|
|
565
|
-
return isVirtualRootStartMarker(node) && '$rmx' in node;
|
|
566
|
-
}
|
|
567
654
|
function isVirtualRootEndMarker(node) {
|
|
568
655
|
return isCommentNode(node) && node.data.trim() === '/rmx:h';
|
|
569
656
|
}
|