@barefootjs/client 0.26.4 → 0.27.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/dist/reactive.d.ts.map +1 -1
- package/dist/runtime/claim-slots.d.ts +157 -0
- package/dist/runtime/claim-slots.d.ts.map +1 -0
- package/dist/runtime/component.d.ts +29 -17
- package/dist/runtime/component.d.ts.map +1 -1
- package/dist/runtime/dynamic-text.d.ts +24 -1
- package/dist/runtime/dynamic-text.d.ts.map +1 -1
- package/dist/runtime/index.d.ts +3 -5
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +151 -234
- package/dist/runtime/loop-markers.d.ts +26 -0
- package/dist/runtime/loop-markers.d.ts.map +1 -0
- package/dist/runtime/standalone.js +151 -234
- package/package.json +2 -2
- package/src/reactive.ts +2 -1
- package/src/runtime/claim-slots.ts +449 -0
- package/src/runtime/component.ts +39 -69
- package/src/runtime/dynamic-text.ts +24 -1
- package/src/runtime/index.ts +16 -7
- package/src/runtime/insert.ts +1 -1
- package/src/runtime/loop-markers.ts +100 -0
- package/dist/runtime/client-marker.d.ts +0 -21
- package/dist/runtime/client-marker.d.ts.map +0 -1
- package/dist/runtime/list.d.ts +0 -21
- package/dist/runtime/list.d.ts.map +0 -1
- package/dist/runtime/patch-slot-range.d.ts +0 -47
- package/dist/runtime/patch-slot-range.d.ts.map +0 -1
- package/dist/runtime/reconcile-elements.d.ts +0 -44
- package/dist/runtime/reconcile-elements.d.ts.map +0 -1
- package/src/runtime/client-marker.ts +0 -46
- package/src/runtime/list.ts +0 -47
- package/src/runtime/patch-slot-range.ts +0 -105
- package/src/runtime/reconcile-elements.ts +0 -391
|
@@ -1758,8 +1758,6 @@ var _parentScopeId = null;
|
|
|
1758
1758
|
function setParentScopeId(id) {
|
|
1759
1759
|
_parentScopeId = id;
|
|
1760
1760
|
}
|
|
1761
|
-
var propsUpdateMap = new WeakMap;
|
|
1762
|
-
var propsMap = new WeakMap;
|
|
1763
1761
|
function createComponent(nameOrDef, props = {}, key, slot) {
|
|
1764
1762
|
if (props == null)
|
|
1765
1763
|
props = {};
|
|
@@ -1851,24 +1849,8 @@ function createComponent(nameOrDef, props = {}, key, slot) {
|
|
|
1851
1849
|
}
|
|
1852
1850
|
setCurrentScope(prevScope);
|
|
1853
1851
|
hydratedScopes.add(element);
|
|
1854
|
-
propsMap.set(element, props);
|
|
1855
|
-
registerPropsUpdate(element, name, props);
|
|
1856
1852
|
return element;
|
|
1857
1853
|
}
|
|
1858
|
-
function getComponentProps(element) {
|
|
1859
|
-
return propsMap.get(element);
|
|
1860
|
-
}
|
|
1861
|
-
function registerPropsUpdate(element, name, _initialProps) {
|
|
1862
|
-
propsUpdateMap.set(element, (newProps) => {
|
|
1863
|
-
const init = getComponentInit(name);
|
|
1864
|
-
if (init) {
|
|
1865
|
-
init(element, newProps);
|
|
1866
|
-
}
|
|
1867
|
-
});
|
|
1868
|
-
}
|
|
1869
|
-
function getPropsUpdateFn(element) {
|
|
1870
|
-
return propsUpdateMap.get(element);
|
|
1871
|
-
}
|
|
1872
1854
|
function renderChild(name, props, key, slotSuffix) {
|
|
1873
1855
|
const templateFn = getTemplate(name);
|
|
1874
1856
|
const suffix = slotSuffix ? `_${slotSuffix}` : "";
|
|
@@ -1934,6 +1916,11 @@ function escapeText(value) {
|
|
|
1934
1916
|
return "";
|
|
1935
1917
|
return escapeAttr(value);
|
|
1936
1918
|
}
|
|
1919
|
+
function escapeTextOrNode(value) {
|
|
1920
|
+
if (typeof Node !== "undefined" && value instanceof Node)
|
|
1921
|
+
return value;
|
|
1922
|
+
return escapeText(value);
|
|
1923
|
+
}
|
|
1937
1924
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
1938
1925
|
function parseHTML(html, parent) {
|
|
1939
1926
|
const tpl = document.createElement("template");
|
|
@@ -1998,7 +1985,6 @@ function createComponentFromDef(def, props, key) {
|
|
|
1998
1985
|
}
|
|
1999
1986
|
def.init(element, props);
|
|
2000
1987
|
hydratedScopes.add(element);
|
|
2001
|
-
propsMap.set(element, props);
|
|
2002
1988
|
return element;
|
|
2003
1989
|
}
|
|
2004
1990
|
|
|
@@ -2056,7 +2042,7 @@ function createPortal(children, container = document.body, options) {
|
|
|
2056
2042
|
}
|
|
2057
2043
|
};
|
|
2058
2044
|
}
|
|
2059
|
-
// src/runtime/
|
|
2045
|
+
// src/runtime/loop-markers.ts
|
|
2060
2046
|
function findLoopMarkers(container, markerId) {
|
|
2061
2047
|
let startMarker = null;
|
|
2062
2048
|
let endMarker = null;
|
|
@@ -2101,14 +2087,6 @@ function getElementsBetweenMarkers(start, end) {
|
|
|
2101
2087
|
}
|
|
2102
2088
|
return elements;
|
|
2103
2089
|
}
|
|
2104
|
-
function removeElementsBetweenMarkers(start, end) {
|
|
2105
|
-
let node = start.nextSibling;
|
|
2106
|
-
while (node && node !== end) {
|
|
2107
|
-
const next = node.nextSibling;
|
|
2108
|
-
node.parentNode?.removeChild(node);
|
|
2109
|
-
node = next;
|
|
2110
|
-
}
|
|
2111
|
-
}
|
|
2112
2090
|
function getLoopChildren(container, markerId) {
|
|
2113
2091
|
const { startMarker, endMarker } = findLoopMarkers(container, markerId);
|
|
2114
2092
|
if (startMarker && endMarker) {
|
|
@@ -2129,159 +2107,6 @@ function getLoopNodes(container, markerId) {
|
|
|
2129
2107
|
}
|
|
2130
2108
|
return Array.from(container.childNodes);
|
|
2131
2109
|
}
|
|
2132
|
-
function reconcileElements(container, items, getKey, renderItem, firstElement, markerId) {
|
|
2133
|
-
if (!container || !items)
|
|
2134
|
-
return;
|
|
2135
|
-
const { startMarker, endMarker } = findLoopMarkers(container, markerId);
|
|
2136
|
-
const existingByKey = new Map;
|
|
2137
|
-
let hasKeyedChildren = false;
|
|
2138
|
-
const loopChildren = startMarker ? getElementsBetweenMarkers(startMarker, endMarker) : Array.from(container.children);
|
|
2139
|
-
for (const child of loopChildren) {
|
|
2140
|
-
const el = child;
|
|
2141
|
-
const key = el.dataset?.key;
|
|
2142
|
-
if (key !== undefined) {
|
|
2143
|
-
existingByKey.set(key, el);
|
|
2144
|
-
hasKeyedChildren = true;
|
|
2145
|
-
}
|
|
2146
|
-
}
|
|
2147
|
-
if (!hasKeyedChildren) {
|
|
2148
|
-
if (items.length === 0) {
|
|
2149
|
-
if (startMarker) {
|
|
2150
|
-
removeElementsBetweenMarkers(startMarker, endMarker);
|
|
2151
|
-
} else {
|
|
2152
|
-
container.innerHTML = "";
|
|
2153
|
-
}
|
|
2154
|
-
return;
|
|
2155
|
-
}
|
|
2156
|
-
const fragment = document.createDocumentFragment();
|
|
2157
|
-
for (let i = 0;i < items.length; i++) {
|
|
2158
|
-
const el = i === 0 && firstElement ? firstElement : renderItem(items[i], i);
|
|
2159
|
-
const key = getKey ? getKey(items[i], i) : String(i);
|
|
2160
|
-
if (!el.dataset.key)
|
|
2161
|
-
el.setAttribute(BF_KEY, key);
|
|
2162
|
-
fragment.appendChild(el);
|
|
2163
|
-
}
|
|
2164
|
-
if (startMarker) {
|
|
2165
|
-
removeElementsBetweenMarkers(startMarker, endMarker);
|
|
2166
|
-
endMarker.parentNode.insertBefore(fragment, endMarker);
|
|
2167
|
-
} else {
|
|
2168
|
-
container.innerHTML = "";
|
|
2169
|
-
container.appendChild(fragment);
|
|
2170
|
-
}
|
|
2171
|
-
return;
|
|
2172
|
-
}
|
|
2173
|
-
let insertAnchor = endMarker ?? null;
|
|
2174
|
-
if (!startMarker) {
|
|
2175
|
-
let foundKeyed = false;
|
|
2176
|
-
for (const child of Array.from(container.childNodes)) {
|
|
2177
|
-
if (child.nodeType === Node.ELEMENT_NODE && child.dataset.key !== undefined) {
|
|
2178
|
-
foundKeyed = true;
|
|
2179
|
-
} else if (foundKeyed) {
|
|
2180
|
-
insertAnchor = child;
|
|
2181
|
-
break;
|
|
2182
|
-
}
|
|
2183
|
-
}
|
|
2184
|
-
}
|
|
2185
|
-
let focusedKey = null;
|
|
2186
|
-
const activeEl = document.activeElement;
|
|
2187
|
-
if (activeEl && activeEl !== document.body) {
|
|
2188
|
-
const tag = activeEl.tagName;
|
|
2189
|
-
if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT" || activeEl.isContentEditable) {
|
|
2190
|
-
for (const [key, el] of existingByKey) {
|
|
2191
|
-
if (el.contains(activeEl)) {
|
|
2192
|
-
focusedKey = key;
|
|
2193
|
-
break;
|
|
2194
|
-
}
|
|
2195
|
-
}
|
|
2196
|
-
}
|
|
2197
|
-
}
|
|
2198
|
-
const desiredElements = [];
|
|
2199
|
-
const toRemove = [];
|
|
2200
|
-
let focusTarget = null;
|
|
2201
|
-
for (let i = 0;i < items.length; i++) {
|
|
2202
|
-
const item = items[i];
|
|
2203
|
-
const key = getKey ? getKey(item, i) : String(i);
|
|
2204
|
-
const createEl = () => i === 0 && firstElement ? firstElement : renderItem(item, i);
|
|
2205
|
-
const existing = existingByKey.get(key);
|
|
2206
|
-
if (existing) {
|
|
2207
|
-
existingByKey.delete(key);
|
|
2208
|
-
if (existing.getAttribute(BF_SCOPE) && !hydratedScopes.has(existing)) {
|
|
2209
|
-
const newEl = createEl();
|
|
2210
|
-
if (!newEl.dataset.key)
|
|
2211
|
-
newEl.setAttribute(BF_KEY, key);
|
|
2212
|
-
desiredElements.push(newEl);
|
|
2213
|
-
toRemove.push(existing);
|
|
2214
|
-
} else if (focusedKey === key) {
|
|
2215
|
-
const newEl = createEl();
|
|
2216
|
-
if (!newEl.dataset.key)
|
|
2217
|
-
newEl.setAttribute(BF_KEY, key);
|
|
2218
|
-
focusTarget = prepareInputTransfer(existing, newEl);
|
|
2219
|
-
desiredElements.push(newEl);
|
|
2220
|
-
toRemove.push(existing);
|
|
2221
|
-
} else {
|
|
2222
|
-
const newEl = createEl();
|
|
2223
|
-
if (!newEl.dataset.key)
|
|
2224
|
-
newEl.setAttribute(BF_KEY, key);
|
|
2225
|
-
desiredElements.push(newEl);
|
|
2226
|
-
toRemove.push(existing);
|
|
2227
|
-
}
|
|
2228
|
-
} else {
|
|
2229
|
-
const el = createEl();
|
|
2230
|
-
if (!el.dataset.key)
|
|
2231
|
-
el.setAttribute(BF_KEY, key);
|
|
2232
|
-
desiredElements.push(el);
|
|
2233
|
-
}
|
|
2234
|
-
}
|
|
2235
|
-
for (const el of existingByKey.values()) {
|
|
2236
|
-
toRemove.push(el);
|
|
2237
|
-
}
|
|
2238
|
-
for (const el of toRemove) {
|
|
2239
|
-
if (el.parentNode)
|
|
2240
|
-
el.remove();
|
|
2241
|
-
}
|
|
2242
|
-
for (const el of desiredElements) {
|
|
2243
|
-
container.insertBefore(el, insertAnchor);
|
|
2244
|
-
}
|
|
2245
|
-
if (focusTarget) {
|
|
2246
|
-
focusTarget.target.focus();
|
|
2247
|
-
if (typeof focusTarget.selectionStart === "number") {
|
|
2248
|
-
focusTarget.target.selectionStart = focusTarget.selectionStart;
|
|
2249
|
-
focusTarget.target.selectionEnd = focusTarget.selectionEnd;
|
|
2250
|
-
}
|
|
2251
|
-
}
|
|
2252
|
-
}
|
|
2253
|
-
function prepareInputTransfer(oldEl, newEl) {
|
|
2254
|
-
const focused = oldEl.contains(document.activeElement) ? document.activeElement : null;
|
|
2255
|
-
if (!focused)
|
|
2256
|
-
return null;
|
|
2257
|
-
const tag = focused.tagName;
|
|
2258
|
-
const oldInputs = Array.from(oldEl.querySelectorAll(tag));
|
|
2259
|
-
const idx = oldInputs.indexOf(focused);
|
|
2260
|
-
if (idx < 0)
|
|
2261
|
-
return null;
|
|
2262
|
-
const newInputs = Array.from(newEl.querySelectorAll(tag));
|
|
2263
|
-
const target = newInputs[idx];
|
|
2264
|
-
if (!target)
|
|
2265
|
-
return null;
|
|
2266
|
-
target.value = focused.value;
|
|
2267
|
-
return {
|
|
2268
|
-
target,
|
|
2269
|
-
selectionStart: focused.selectionStart,
|
|
2270
|
-
selectionEnd: focused.selectionEnd
|
|
2271
|
-
};
|
|
2272
|
-
}
|
|
2273
|
-
|
|
2274
|
-
// src/runtime/list.ts
|
|
2275
|
-
function reconcileList(container, items, getKey, renderItem) {
|
|
2276
|
-
if (!container || !items)
|
|
2277
|
-
return;
|
|
2278
|
-
if (items.length === 0) {
|
|
2279
|
-
container.innerHTML = "";
|
|
2280
|
-
return;
|
|
2281
|
-
}
|
|
2282
|
-
const firstElement = renderItem(items[0], 0);
|
|
2283
|
-
reconcileElements(container, items, getKey, renderItem, firstElement);
|
|
2284
|
-
}
|
|
2285
2110
|
// src/runtime/qsa-item.ts
|
|
2286
2111
|
function* itemRootElements(primaryEl) {
|
|
2287
2112
|
yield primaryEl;
|
|
@@ -2817,35 +2642,44 @@ function patchLeaf(el, html) {
|
|
|
2817
2642
|
}
|
|
2818
2643
|
el.replaceChildren(...Array.from(next.childNodes));
|
|
2819
2644
|
}
|
|
2820
|
-
// src/runtime/
|
|
2821
|
-
function
|
|
2645
|
+
// src/runtime/claim-slots.ts
|
|
2646
|
+
function resolvePath(root, path) {
|
|
2647
|
+
let node = root;
|
|
2648
|
+
for (const index of path) {
|
|
2649
|
+
const child = node.childNodes[index];
|
|
2650
|
+
if (!child)
|
|
2651
|
+
return null;
|
|
2652
|
+
node = child;
|
|
2653
|
+
}
|
|
2654
|
+
return node;
|
|
2655
|
+
}
|
|
2656
|
+
function isSlotComment(node, id) {
|
|
2657
|
+
return node != null && node.nodeType === Node.COMMENT_NODE && node.nodeValue === `bf:${id}`;
|
|
2658
|
+
}
|
|
2659
|
+
function findOwnedMarker(root, id) {
|
|
2822
2660
|
const marker = `bf:${id}`;
|
|
2823
|
-
|
|
2824
|
-
const
|
|
2825
|
-
|
|
2826
|
-
|
|
2661
|
+
const parentOwned = id.startsWith(BF_PARENT_OWNED_PREFIX);
|
|
2662
|
+
const registryInfo = commentScopeRegistry.get(root);
|
|
2663
|
+
const boundary = registryInfo ? registryInfo.commentNode.parentElement : root;
|
|
2664
|
+
for (const comment of commentsInScope(root)) {
|
|
2827
2665
|
if (comment.nodeValue !== marker)
|
|
2828
2666
|
continue;
|
|
2667
|
+
if (parentOwned)
|
|
2668
|
+
return comment;
|
|
2829
2669
|
let owned = true;
|
|
2830
|
-
for (let el = comment.parentElement;el && el !==
|
|
2670
|
+
for (let el = comment.parentElement;el && el !== boundary; el = el.parentElement) {
|
|
2831
2671
|
if (el.hasAttribute(BF_SCOPE)) {
|
|
2832
2672
|
owned = false;
|
|
2833
2673
|
break;
|
|
2834
2674
|
}
|
|
2835
2675
|
}
|
|
2836
|
-
if (owned)
|
|
2837
|
-
|
|
2838
|
-
break;
|
|
2839
|
-
}
|
|
2840
|
-
}
|
|
2841
|
-
const parent = start?.parentNode;
|
|
2842
|
-
if (!start || !parent) {
|
|
2843
|
-
console.warn(`[barefootjs] preamble region marker bf:${id} not found in row; skipping patch`);
|
|
2844
|
-
return;
|
|
2676
|
+
if (owned)
|
|
2677
|
+
return comment;
|
|
2845
2678
|
}
|
|
2679
|
+
return null;
|
|
2680
|
+
}
|
|
2681
|
+
function findMarkupEnd(start) {
|
|
2846
2682
|
let depth = 0;
|
|
2847
|
-
let end = null;
|
|
2848
|
-
const toRemove = [];
|
|
2849
2683
|
let node = start.nextSibling;
|
|
2850
2684
|
while (node) {
|
|
2851
2685
|
if (node.nodeType === Node.COMMENT_NODE) {
|
|
@@ -2853,25 +2687,131 @@ function patchSlotRange(scope, id, html) {
|
|
|
2853
2687
|
if (value.startsWith("bf:")) {
|
|
2854
2688
|
depth++;
|
|
2855
2689
|
} else if (value === "/") {
|
|
2856
|
-
if (depth === 0)
|
|
2857
|
-
|
|
2858
|
-
break;
|
|
2859
|
-
}
|
|
2690
|
+
if (depth === 0)
|
|
2691
|
+
return node;
|
|
2860
2692
|
depth--;
|
|
2861
2693
|
}
|
|
2862
2694
|
}
|
|
2863
|
-
toRemove.push(node);
|
|
2864
2695
|
node = node.nextSibling;
|
|
2865
2696
|
}
|
|
2697
|
+
return null;
|
|
2698
|
+
}
|
|
2699
|
+
function resolveAnchor(root, spec) {
|
|
2700
|
+
if (spec.path.length > 0) {
|
|
2701
|
+
const resolved = resolvePath(root, spec.path);
|
|
2702
|
+
if (isSlotComment(resolved, spec.id))
|
|
2703
|
+
return resolved;
|
|
2704
|
+
console.warn(`[barefootjs] claim path for slot ${spec.id} did not resolve to its bf:${spec.id} marker; falling back to a scan`);
|
|
2705
|
+
}
|
|
2706
|
+
const found = findOwnedMarker(root, spec.id);
|
|
2707
|
+
if (!found) {
|
|
2708
|
+
console.warn(`[barefootjs] slot ${spec.id} marker not found; skipping`);
|
|
2709
|
+
}
|
|
2710
|
+
return found;
|
|
2711
|
+
}
|
|
2712
|
+
function claimMarkerlessText(root, spec) {
|
|
2713
|
+
if (spec.path.length === 0) {
|
|
2714
|
+
console.warn(`[barefootjs] markerless slot ${spec.id} has an empty path; skipping`);
|
|
2715
|
+
return null;
|
|
2716
|
+
}
|
|
2717
|
+
const parentPath = spec.path.slice(0, -1);
|
|
2718
|
+
const idx = spec.path[spec.path.length - 1];
|
|
2719
|
+
const parent = resolvePath(root, parentPath);
|
|
2720
|
+
if (!parent) {
|
|
2721
|
+
console.warn(`[barefootjs] markerless claim path for slot ${spec.id} did not resolve to a parent node; skipping`);
|
|
2722
|
+
return null;
|
|
2723
|
+
}
|
|
2724
|
+
const existing = parent.childNodes[idx];
|
|
2725
|
+
if (existing && existing.nodeType === Node.TEXT_NODE) {
|
|
2726
|
+
return { kind: "text", node: existing };
|
|
2727
|
+
}
|
|
2728
|
+
const node = document.createTextNode("");
|
|
2729
|
+
parent.insertBefore(node, existing ?? null);
|
|
2730
|
+
return { kind: "text", node };
|
|
2731
|
+
}
|
|
2732
|
+
function claimOne(root, spec) {
|
|
2733
|
+
if (spec.kind === "text" && spec.markerless) {
|
|
2734
|
+
return claimMarkerlessText(root, spec);
|
|
2735
|
+
}
|
|
2736
|
+
const anchor = resolveAnchor(root, spec);
|
|
2737
|
+
if (!anchor)
|
|
2738
|
+
return null;
|
|
2739
|
+
if (spec.kind === "text") {
|
|
2740
|
+
return { kind: "text", node: textNodeAfterComment(anchor) };
|
|
2741
|
+
}
|
|
2742
|
+
const end = findMarkupEnd(anchor);
|
|
2866
2743
|
if (!end) {
|
|
2867
|
-
console.warn(`[barefootjs]
|
|
2744
|
+
console.warn(`[barefootjs] slot ${spec.id} has no end marker; skipping`);
|
|
2745
|
+
return null;
|
|
2746
|
+
}
|
|
2747
|
+
return { kind: "markup", start: anchor, end, last: undefined };
|
|
2748
|
+
}
|
|
2749
|
+
function writeText(ref, value) {
|
|
2750
|
+
ref.node.nodeValue = String(value ?? "");
|
|
2751
|
+
}
|
|
2752
|
+
function clearMarkupRange(start, end) {
|
|
2753
|
+
const parent = end.parentNode;
|
|
2754
|
+
if (!parent)
|
|
2755
|
+
return;
|
|
2756
|
+
let node = start.nextSibling;
|
|
2757
|
+
while (node && node !== end) {
|
|
2758
|
+
const next = node.nextSibling;
|
|
2759
|
+
parent.removeChild(node);
|
|
2760
|
+
node = next;
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
function writeMarkup(ref, value) {
|
|
2764
|
+
const { start, end } = ref;
|
|
2765
|
+
const parent = end.parentNode;
|
|
2766
|
+
if (!parent)
|
|
2767
|
+
return;
|
|
2768
|
+
if (value != null && value.__isSlot)
|
|
2769
|
+
return;
|
|
2770
|
+
if (typeof Node !== "undefined" && value instanceof Node) {
|
|
2771
|
+
if (value === ref.last)
|
|
2772
|
+
return;
|
|
2773
|
+
clearMarkupRange(start, end);
|
|
2774
|
+
parent.insertBefore(value, end);
|
|
2775
|
+
ref.last = value;
|
|
2868
2776
|
return;
|
|
2869
2777
|
}
|
|
2870
|
-
|
|
2871
|
-
|
|
2778
|
+
const text = String(value ?? "");
|
|
2779
|
+
if (text === ref.last)
|
|
2780
|
+
return;
|
|
2781
|
+
clearMarkupRange(start, end);
|
|
2872
2782
|
const tpl = document.createElement("template");
|
|
2873
|
-
tpl.innerHTML =
|
|
2783
|
+
tpl.innerHTML = text;
|
|
2874
2784
|
parent.insertBefore(tpl.content, end);
|
|
2785
|
+
ref.last = text;
|
|
2786
|
+
}
|
|
2787
|
+
function writeSlot(refs, id, value) {
|
|
2788
|
+
const ref = refs.get(id);
|
|
2789
|
+
if (!ref) {
|
|
2790
|
+
console.warn(`[barefootjs] no claimed slot for id ${id}; write ignored`);
|
|
2791
|
+
return;
|
|
2792
|
+
}
|
|
2793
|
+
if (ref.kind === "text") {
|
|
2794
|
+
writeText(ref, value);
|
|
2795
|
+
} else {
|
|
2796
|
+
writeMarkup(ref, value);
|
|
2797
|
+
}
|
|
2798
|
+
}
|
|
2799
|
+
function claimSlots(root, plan) {
|
|
2800
|
+
const refs = new Map;
|
|
2801
|
+
for (const spec of plan) {
|
|
2802
|
+
const ref = claimOne(root, spec);
|
|
2803
|
+
if (ref)
|
|
2804
|
+
refs.set(spec.id, ref);
|
|
2805
|
+
}
|
|
2806
|
+
return { write: (id, value) => writeSlot(refs, id, value) };
|
|
2807
|
+
}
|
|
2808
|
+
function lazySlots(root, plan) {
|
|
2809
|
+
let claimed = null;
|
|
2810
|
+
return (id, value) => {
|
|
2811
|
+
if (!claimed)
|
|
2812
|
+
claimed = claimSlots(root, plan);
|
|
2813
|
+
claimed.write(id, value);
|
|
2814
|
+
};
|
|
2875
2815
|
}
|
|
2876
2816
|
// src/runtime/style.ts
|
|
2877
2817
|
function styleToCss(value) {
|
|
@@ -3314,26 +3254,6 @@ function __bfText(current, value) {
|
|
|
3314
3254
|
}
|
|
3315
3255
|
return textNode;
|
|
3316
3256
|
}
|
|
3317
|
-
// src/runtime/client-marker.ts
|
|
3318
|
-
function updateClientMarker(scope, id, value) {
|
|
3319
|
-
if (!scope)
|
|
3320
|
-
return;
|
|
3321
|
-
const marker = `bf-client:${id}`;
|
|
3322
|
-
const walker = document.createTreeWalker(scope, NodeFilter.SHOW_COMMENT);
|
|
3323
|
-
while (walker.nextNode()) {
|
|
3324
|
-
if (walker.currentNode.nodeValue === marker) {
|
|
3325
|
-
const comment = walker.currentNode;
|
|
3326
|
-
let textNode = comment.nextSibling;
|
|
3327
|
-
if (textNode?.nodeType !== Node.TEXT_NODE || !textNode.nodeValue?.startsWith("")) {
|
|
3328
|
-
textNode = document.createTextNode("" + String(value ?? ""));
|
|
3329
|
-
comment.parentNode?.insertBefore(textNode, comment.nextSibling);
|
|
3330
|
-
} else {
|
|
3331
|
-
textNode.nodeValue = "" + String(value ?? "");
|
|
3332
|
-
}
|
|
3333
|
-
return;
|
|
3334
|
-
}
|
|
3335
|
-
}
|
|
3336
|
-
}
|
|
3337
3257
|
// src/runtime/render.ts
|
|
3338
3258
|
function render(container, nameOrDef, props = {}) {
|
|
3339
3259
|
let name;
|
|
@@ -3414,7 +3334,6 @@ export {
|
|
|
3414
3334
|
useContext,
|
|
3415
3335
|
upsertChildItem,
|
|
3416
3336
|
upsertChild,
|
|
3417
|
-
updateClientMarker,
|
|
3418
3337
|
unwrap,
|
|
3419
3338
|
untrack,
|
|
3420
3339
|
textNodeAfterComment as tAfter,
|
|
@@ -3430,21 +3349,19 @@ export {
|
|
|
3430
3349
|
rehydrateAll,
|
|
3431
3350
|
registerTemplate,
|
|
3432
3351
|
registerComponent,
|
|
3433
|
-
reconcileList,
|
|
3434
|
-
reconcileElements,
|
|
3435
3352
|
queryHref,
|
|
3436
3353
|
qsaItem,
|
|
3437
3354
|
qsaChildScopes,
|
|
3438
3355
|
qsaChildScope,
|
|
3439
3356
|
qsa,
|
|
3440
3357
|
provideContext,
|
|
3441
|
-
patchSlotRange,
|
|
3442
3358
|
patchLeaf,
|
|
3443
3359
|
parseHTML,
|
|
3444
3360
|
onMount,
|
|
3445
3361
|
onCleanup,
|
|
3446
3362
|
mapArrayAnchored,
|
|
3447
3363
|
mapArray,
|
|
3364
|
+
lazySlots,
|
|
3448
3365
|
isSSRPortal,
|
|
3449
3366
|
insert,
|
|
3450
3367
|
initChild,
|
|
@@ -3453,10 +3370,8 @@ export {
|
|
|
3453
3370
|
hasTemplate,
|
|
3454
3371
|
getTemplate,
|
|
3455
3372
|
getRegisteredDef,
|
|
3456
|
-
getPropsUpdateFn,
|
|
3457
3373
|
getLoopNodes,
|
|
3458
3374
|
getLoopChildren,
|
|
3459
|
-
getComponentProps,
|
|
3460
3375
|
getComponentInit,
|
|
3461
3376
|
forwardProps,
|
|
3462
3377
|
formatDate,
|
|
@@ -3464,6 +3379,7 @@ export {
|
|
|
3464
3379
|
findSiblingSlot,
|
|
3465
3380
|
findScope,
|
|
3466
3381
|
find,
|
|
3382
|
+
escapeTextOrNode,
|
|
3467
3383
|
escapeText,
|
|
3468
3384
|
escapeAttr,
|
|
3469
3385
|
endTurn,
|
|
@@ -3482,6 +3398,7 @@ export {
|
|
|
3482
3398
|
createContext,
|
|
3483
3399
|
createComponent,
|
|
3484
3400
|
cleanupPortalPlaceholder,
|
|
3401
|
+
claimSlots,
|
|
3485
3402
|
beginTurn,
|
|
3486
3403
|
batch,
|
|
3487
3404
|
applyRestAttrs,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"description": "BarefootJS client package: reactive primitives (SSR-safe) plus browser runtime under the `/runtime` subpath (compiler target)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"directory": "packages/client"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@barefootjs/shared": "0.
|
|
58
|
+
"@barefootjs/shared": "0.27.0"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
61
|
"@barefootjs/jsx": ">=0.2.0"
|
package/src/reactive.ts
CHANGED
|
@@ -319,7 +319,8 @@ export function createSignal<T>(initialValue: T, __bfId?: string): Signal<T> {
|
|
|
319
319
|
export function createEffect(fn: EffectFn, __bfId?: string, __bfKind: SubscriberKind = 'effect'): void {
|
|
320
320
|
// Note: Nested effects are now allowed. runEffect() properly saves/restores
|
|
321
321
|
// prevEffect, so nested effects correctly track their own dependencies.
|
|
322
|
-
// This enables synchronous component initialization
|
|
322
|
+
// This enables synchronous component initialization inside loop reconcilers
|
|
323
|
+
// (mapArray/mapArrayAnchored).
|
|
323
324
|
|
|
324
325
|
const effect: EffectContext = {
|
|
325
326
|
fn,
|