@barefootjs/client 0.26.3 → 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 +4 -4
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +206 -206
- package/dist/runtime/loop-markers.d.ts +26 -0
- package/dist/runtime/loop-markers.d.ts.map +1 -0
- package/dist/runtime/patch-leaf.d.ts +17 -0
- package/dist/runtime/patch-leaf.d.ts.map +1 -0
- package/dist/runtime/standalone.js +206 -206
- 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 +17 -6
- package/src/runtime/insert.ts +1 -1
- package/src/runtime/loop-markers.ts +100 -0
- package/src/runtime/patch-leaf.ts +41 -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/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/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;
|
|
@@ -2792,6 +2617,202 @@ function mapArrayAnchored(accessor, container, getKey, renderItem, markerId, bfI
|
|
|
2792
2617
|
}
|
|
2793
2618
|
}, bfId);
|
|
2794
2619
|
}
|
|
2620
|
+
// src/runtime/patch-leaf.ts
|
|
2621
|
+
function patchLeaf(el, html) {
|
|
2622
|
+
const tpl = document.createElement("template");
|
|
2623
|
+
tpl.innerHTML = html;
|
|
2624
|
+
const next = tpl.content.firstElementChild;
|
|
2625
|
+
if (!next)
|
|
2626
|
+
return;
|
|
2627
|
+
if (next.tagName !== el.tagName) {
|
|
2628
|
+
console.warn("[barefootjs] flatMap leaf root tag changed under a stable key " + `(<${el.tagName.toLowerCase()}> -> <${next.tagName.toLowerCase()}>); ` + "give each branch its own key so the node is replaced instead of patched.");
|
|
2629
|
+
}
|
|
2630
|
+
for (const name of el.getAttributeNames()) {
|
|
2631
|
+
if (name === "data-key")
|
|
2632
|
+
continue;
|
|
2633
|
+
if (!next.hasAttribute(name))
|
|
2634
|
+
el.removeAttribute(name);
|
|
2635
|
+
}
|
|
2636
|
+
for (const name of next.getAttributeNames()) {
|
|
2637
|
+
if (name === "data-key")
|
|
2638
|
+
continue;
|
|
2639
|
+
const value = next.getAttribute(name);
|
|
2640
|
+
if (value !== null && el.getAttribute(name) !== value)
|
|
2641
|
+
el.setAttribute(name, value);
|
|
2642
|
+
}
|
|
2643
|
+
el.replaceChildren(...Array.from(next.childNodes));
|
|
2644
|
+
}
|
|
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) {
|
|
2660
|
+
const marker = `bf:${id}`;
|
|
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)) {
|
|
2665
|
+
if (comment.nodeValue !== marker)
|
|
2666
|
+
continue;
|
|
2667
|
+
if (parentOwned)
|
|
2668
|
+
return comment;
|
|
2669
|
+
let owned = true;
|
|
2670
|
+
for (let el = comment.parentElement;el && el !== boundary; el = el.parentElement) {
|
|
2671
|
+
if (el.hasAttribute(BF_SCOPE)) {
|
|
2672
|
+
owned = false;
|
|
2673
|
+
break;
|
|
2674
|
+
}
|
|
2675
|
+
}
|
|
2676
|
+
if (owned)
|
|
2677
|
+
return comment;
|
|
2678
|
+
}
|
|
2679
|
+
return null;
|
|
2680
|
+
}
|
|
2681
|
+
function findMarkupEnd(start) {
|
|
2682
|
+
let depth = 0;
|
|
2683
|
+
let node = start.nextSibling;
|
|
2684
|
+
while (node) {
|
|
2685
|
+
if (node.nodeType === Node.COMMENT_NODE) {
|
|
2686
|
+
const value = node.nodeValue ?? "";
|
|
2687
|
+
if (value.startsWith("bf:")) {
|
|
2688
|
+
depth++;
|
|
2689
|
+
} else if (value === "/") {
|
|
2690
|
+
if (depth === 0)
|
|
2691
|
+
return node;
|
|
2692
|
+
depth--;
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2695
|
+
node = node.nextSibling;
|
|
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);
|
|
2743
|
+
if (!end) {
|
|
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;
|
|
2776
|
+
return;
|
|
2777
|
+
}
|
|
2778
|
+
const text = String(value ?? "");
|
|
2779
|
+
if (text === ref.last)
|
|
2780
|
+
return;
|
|
2781
|
+
clearMarkupRange(start, end);
|
|
2782
|
+
const tpl = document.createElement("template");
|
|
2783
|
+
tpl.innerHTML = text;
|
|
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
|
+
};
|
|
2815
|
+
}
|
|
2795
2816
|
// src/runtime/style.ts
|
|
2796
2817
|
function styleToCss(value) {
|
|
2797
2818
|
if (value == null)
|
|
@@ -3233,26 +3254,6 @@ function __bfText(current, value) {
|
|
|
3233
3254
|
}
|
|
3234
3255
|
return textNode;
|
|
3235
3256
|
}
|
|
3236
|
-
// src/runtime/client-marker.ts
|
|
3237
|
-
function updateClientMarker(scope, id, value) {
|
|
3238
|
-
if (!scope)
|
|
3239
|
-
return;
|
|
3240
|
-
const marker = `bf-client:${id}`;
|
|
3241
|
-
const walker = document.createTreeWalker(scope, NodeFilter.SHOW_COMMENT);
|
|
3242
|
-
while (walker.nextNode()) {
|
|
3243
|
-
if (walker.currentNode.nodeValue === marker) {
|
|
3244
|
-
const comment = walker.currentNode;
|
|
3245
|
-
let textNode = comment.nextSibling;
|
|
3246
|
-
if (textNode?.nodeType !== Node.TEXT_NODE || !textNode.nodeValue?.startsWith("")) {
|
|
3247
|
-
textNode = document.createTextNode("" + String(value ?? ""));
|
|
3248
|
-
comment.parentNode?.insertBefore(textNode, comment.nextSibling);
|
|
3249
|
-
} else {
|
|
3250
|
-
textNode.nodeValue = "" + String(value ?? "");
|
|
3251
|
-
}
|
|
3252
|
-
return;
|
|
3253
|
-
}
|
|
3254
|
-
}
|
|
3255
|
-
}
|
|
3256
3257
|
// src/runtime/render.ts
|
|
3257
3258
|
function render(container, nameOrDef, props = {}) {
|
|
3258
3259
|
let name;
|
|
@@ -3333,7 +3334,6 @@ export {
|
|
|
3333
3334
|
useContext,
|
|
3334
3335
|
upsertChildItem,
|
|
3335
3336
|
upsertChild,
|
|
3336
|
-
updateClientMarker,
|
|
3337
3337
|
unwrap,
|
|
3338
3338
|
untrack,
|
|
3339
3339
|
textNodeAfterComment as tAfter,
|
|
@@ -3349,19 +3349,19 @@ export {
|
|
|
3349
3349
|
rehydrateAll,
|
|
3350
3350
|
registerTemplate,
|
|
3351
3351
|
registerComponent,
|
|
3352
|
-
reconcileList,
|
|
3353
|
-
reconcileElements,
|
|
3354
3352
|
queryHref,
|
|
3355
3353
|
qsaItem,
|
|
3356
3354
|
qsaChildScopes,
|
|
3357
3355
|
qsaChildScope,
|
|
3358
3356
|
qsa,
|
|
3359
3357
|
provideContext,
|
|
3358
|
+
patchLeaf,
|
|
3360
3359
|
parseHTML,
|
|
3361
3360
|
onMount,
|
|
3362
3361
|
onCleanup,
|
|
3363
3362
|
mapArrayAnchored,
|
|
3364
3363
|
mapArray,
|
|
3364
|
+
lazySlots,
|
|
3365
3365
|
isSSRPortal,
|
|
3366
3366
|
insert,
|
|
3367
3367
|
initChild,
|
|
@@ -3370,10 +3370,8 @@ export {
|
|
|
3370
3370
|
hasTemplate,
|
|
3371
3371
|
getTemplate,
|
|
3372
3372
|
getRegisteredDef,
|
|
3373
|
-
getPropsUpdateFn,
|
|
3374
3373
|
getLoopNodes,
|
|
3375
3374
|
getLoopChildren,
|
|
3376
|
-
getComponentProps,
|
|
3377
3375
|
getComponentInit,
|
|
3378
3376
|
forwardProps,
|
|
3379
3377
|
formatDate,
|
|
@@ -3381,6 +3379,7 @@ export {
|
|
|
3381
3379
|
findSiblingSlot,
|
|
3382
3380
|
findScope,
|
|
3383
3381
|
find,
|
|
3382
|
+
escapeTextOrNode,
|
|
3384
3383
|
escapeText,
|
|
3385
3384
|
escapeAttr,
|
|
3386
3385
|
endTurn,
|
|
@@ -3399,6 +3398,7 @@ export {
|
|
|
3399
3398
|
createContext,
|
|
3400
3399
|
createComponent,
|
|
3401
3400
|
cleanupPortalPlaceholder,
|
|
3401
|
+
claimSlots,
|
|
3402
3402
|
beginTurn,
|
|
3403
3403
|
batch,
|
|
3404
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,
|