@barefootjs/client 0.27.0 → 0.28.1
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/runtime/claim-slots.d.ts +69 -4
- package/dist/runtime/claim-slots.d.ts.map +1 -1
- package/dist/runtime/component.d.ts +11 -1
- package/dist/runtime/component.d.ts.map +1 -1
- package/dist/runtime/index.d.ts +2 -1
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +322 -31
- package/dist/runtime/map-array-lazy.d.ts +164 -0
- package/dist/runtime/map-array-lazy.d.ts.map +1 -0
- package/dist/runtime/map-array.d.ts +35 -0
- package/dist/runtime/map-array.d.ts.map +1 -1
- package/dist/runtime/qsa-item.d.ts +7 -0
- package/dist/runtime/qsa-item.d.ts.map +1 -1
- package/dist/runtime/registry.d.ts.map +1 -1
- package/dist/runtime/standalone.js +310 -20
- package/package.json +2 -2
- package/src/runtime/claim-slots.ts +212 -14
- package/src/runtime/component.ts +116 -3
- package/src/runtime/index.ts +5 -1
- package/src/runtime/map-array-lazy.ts +470 -0
- package/src/runtime/map-array.ts +68 -11
- package/src/runtime/qsa-item.ts +9 -3
- package/src/runtime/registry.ts +5 -3
|
@@ -1550,9 +1550,7 @@ function upsertChild(parent, name, slotId, props, key, anchorScope) {
|
|
|
1550
1550
|
const ph = parent.getAttribute(BF_PLACEHOLDER) === phId ? parent : parent.querySelector(`[${BF_PLACEHOLDER}="${phId}"]`);
|
|
1551
1551
|
if (ph) {
|
|
1552
1552
|
const slot = slotId ? buildSlotInfo(parent, slotId, anchorScope) : undefined;
|
|
1553
|
-
|
|
1554
|
-
ph.replaceWith(comp);
|
|
1555
|
-
return comp;
|
|
1553
|
+
return createComponent(name, props, key, slot, ph);
|
|
1556
1554
|
}
|
|
1557
1555
|
return null;
|
|
1558
1556
|
}
|
|
@@ -1758,11 +1756,30 @@ var _parentScopeId = null;
|
|
|
1758
1756
|
function setParentScopeId(id) {
|
|
1759
1757
|
_parentScopeId = id;
|
|
1760
1758
|
}
|
|
1761
|
-
|
|
1759
|
+
var _rowMountPoint = null;
|
|
1760
|
+
function setRowMountPoint(p) {
|
|
1761
|
+
const prev = _rowMountPoint;
|
|
1762
|
+
_rowMountPoint = p;
|
|
1763
|
+
return prev;
|
|
1764
|
+
}
|
|
1765
|
+
function takeRowMountPoint() {
|
|
1766
|
+
const p = _rowMountPoint;
|
|
1767
|
+
_rowMountPoint = null;
|
|
1768
|
+
return p;
|
|
1769
|
+
}
|
|
1770
|
+
function createComponent(nameOrDef, props = {}, key, slot, mountAt) {
|
|
1771
|
+
const element = materializeComponent(nameOrDef, props, key, slot, mountAt);
|
|
1772
|
+
if (mountAt && mountAt.parentNode && element !== mountAt) {
|
|
1773
|
+
mountAt.replaceWith(element);
|
|
1774
|
+
}
|
|
1775
|
+
return element;
|
|
1776
|
+
}
|
|
1777
|
+
function materializeComponent(nameOrDef, props = {}, key, slot, mountAt) {
|
|
1762
1778
|
if (props == null)
|
|
1763
1779
|
props = {};
|
|
1780
|
+
const rowMount = mountAt ? null : takeRowMountPoint();
|
|
1764
1781
|
if (typeof nameOrDef !== "string") {
|
|
1765
|
-
return createComponentFromDef(nameOrDef, props, key);
|
|
1782
|
+
return createComponentFromDef(nameOrDef, props, key, mountAt, rowMount);
|
|
1766
1783
|
}
|
|
1767
1784
|
const name = nameOrDef;
|
|
1768
1785
|
const templateFn = getTemplate(name);
|
|
@@ -1822,8 +1839,13 @@ function createComponent(nameOrDef, props = {}, key, slot) {
|
|
|
1822
1839
|
if (key !== undefined) {
|
|
1823
1840
|
element.setAttribute(BF_KEY, String(key));
|
|
1824
1841
|
}
|
|
1825
|
-
const prevScope = setCurrentScope(element);
|
|
1826
1842
|
const rootIsDeferredPlaceholder = element.hasAttribute(BF_PLACEHOLDER);
|
|
1843
|
+
if (mountAt && !rootIsDeferredPlaceholder) {
|
|
1844
|
+
mountAt.replaceWith(element);
|
|
1845
|
+
} else if (rowMount && !rootIsDeferredPlaceholder) {
|
|
1846
|
+
rowMount.container.insertBefore(element, rowMount.anchor);
|
|
1847
|
+
}
|
|
1848
|
+
const prevScope = setCurrentScope(element);
|
|
1827
1849
|
let placeholderWrapper = null;
|
|
1828
1850
|
if (rootIsDeferredPlaceholder) {
|
|
1829
1851
|
placeholderWrapper = parseHTML("<div></div>").firstChild;
|
|
@@ -1964,7 +1986,7 @@ function insertGetterChildren(element, children) {
|
|
|
1964
1986
|
element.appendChild(document.createTextNode(String(children)));
|
|
1965
1987
|
}
|
|
1966
1988
|
}
|
|
1967
|
-
function createComponentFromDef(def, props, key) {
|
|
1989
|
+
function createComponentFromDef(def, props, key, mountAt, rowMount) {
|
|
1968
1990
|
if (!def.template) {
|
|
1969
1991
|
throw new Error("[BarefootJS] createComponent with ComponentDef requires a template function");
|
|
1970
1992
|
}
|
|
@@ -1983,6 +2005,11 @@ function createComponentFromDef(def, props, key) {
|
|
|
1983
2005
|
if (key !== undefined) {
|
|
1984
2006
|
element.setAttribute(BF_KEY, String(key));
|
|
1985
2007
|
}
|
|
2008
|
+
if (mountAt) {
|
|
2009
|
+
mountAt.replaceWith(element);
|
|
2010
|
+
} else if (rowMount) {
|
|
2011
|
+
rowMount.container.insertBefore(element, rowMount.anchor);
|
|
2012
|
+
}
|
|
1986
2013
|
def.init(element, props);
|
|
1987
2014
|
hydratedScopes.add(element);
|
|
1988
2015
|
return element;
|
|
@@ -2163,9 +2190,7 @@ function upsertChildItem(primaryEl, name, slotId, props, key, anchorScope) {
|
|
|
2163
2190
|
const ph = qsaItem(primaryEl, `[data-bf-ph="${phId}"]`);
|
|
2164
2191
|
if (ph) {
|
|
2165
2192
|
const slot = slotId ? buildSlotInfo(primaryEl, slotId, anchorScope) : undefined;
|
|
2166
|
-
|
|
2167
|
-
ph.replaceWith(comp);
|
|
2168
|
-
return comp;
|
|
2193
|
+
return createComponent(name, props, key, slot, ph);
|
|
2169
2194
|
}
|
|
2170
2195
|
return null;
|
|
2171
2196
|
}
|
|
@@ -2277,7 +2302,7 @@ function removeScope(scope) {
|
|
|
2277
2302
|
ex.remove();
|
|
2278
2303
|
}
|
|
2279
2304
|
}
|
|
2280
|
-
function createItemScope(item, index, renderItem, existingPrimary, existingExtras, existingStart) {
|
|
2305
|
+
function createItemScope(item, index, renderItem, existingPrimary, existingExtras, existingStart, rowMount) {
|
|
2281
2306
|
let primaryEl;
|
|
2282
2307
|
let dispose;
|
|
2283
2308
|
let setItem;
|
|
@@ -2287,7 +2312,14 @@ function createItemScope(item, index, renderItem, existingPrimary, existingExtra
|
|
|
2287
2312
|
dispose = d;
|
|
2288
2313
|
const [itemAccessor, itemSetter] = createSignal(item);
|
|
2289
2314
|
setItem = itemSetter;
|
|
2290
|
-
|
|
2315
|
+
const ownsRowMount = !existingPrimary && !!rowMount;
|
|
2316
|
+
const prevRowMount = ownsRowMount ? setRowMountPoint(rowMount) : null;
|
|
2317
|
+
try {
|
|
2318
|
+
primaryEl = renderItem(itemAccessor, index, existingPrimary);
|
|
2319
|
+
} finally {
|
|
2320
|
+
if (ownsRowMount)
|
|
2321
|
+
setRowMountPoint(prevRowMount);
|
|
2322
|
+
}
|
|
2291
2323
|
if (existingPrimary) {
|
|
2292
2324
|
extras = existingExtras ?? [];
|
|
2293
2325
|
startMarker = existingStart ?? null;
|
|
@@ -2301,6 +2333,9 @@ function createItemScope(item, index, renderItem, existingPrimary, existingExtra
|
|
|
2301
2333
|
}
|
|
2302
2334
|
return;
|
|
2303
2335
|
});
|
|
2336
|
+
if (rowMount && !existingPrimary && extras.length > 0 && primaryEl.parentNode) {
|
|
2337
|
+
primaryEl.remove();
|
|
2338
|
+
}
|
|
2304
2339
|
return { startMarker, primaryEl, extras, dispose, setItem };
|
|
2305
2340
|
}
|
|
2306
2341
|
function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
|
|
@@ -2342,7 +2377,7 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
|
|
|
2342
2377
|
for (let i2 = existingRanges.length;i2 < items.length; i2++) {
|
|
2343
2378
|
const item = items[i2];
|
|
2344
2379
|
const key = getKey ? getKey(item, i2) : String(i2);
|
|
2345
|
-
const scope = createItemScope(item, i2, renderItem);
|
|
2380
|
+
const scope = createItemScope(item, i2, renderItem, undefined, undefined, undefined, { container, anchor });
|
|
2346
2381
|
if (!scope.primaryEl.dataset.key)
|
|
2347
2382
|
scope.primaryEl.setAttribute(BF_KEY, key);
|
|
2348
2383
|
scopes.set(key, scope);
|
|
@@ -2421,7 +2456,7 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
|
|
|
2421
2456
|
existing.setItem(item);
|
|
2422
2457
|
desiredOrder.push(existing);
|
|
2423
2458
|
} else {
|
|
2424
|
-
const scope = createItemScope(item, i2, renderItem);
|
|
2459
|
+
const scope = createItemScope(item, i2, renderItem, undefined, undefined, undefined, { container, anchor });
|
|
2425
2460
|
if (!scope.primaryEl.dataset.key)
|
|
2426
2461
|
scope.primaryEl.setAttribute(BF_KEY, key);
|
|
2427
2462
|
scopes.set(key, scope);
|
|
@@ -2617,6 +2652,197 @@ function mapArrayAnchored(accessor, container, getKey, renderItem, markerId, bfI
|
|
|
2617
2652
|
}
|
|
2618
2653
|
}, bfId);
|
|
2619
2654
|
}
|
|
2655
|
+
// src/runtime/map-array-lazy.ts
|
|
2656
|
+
function mapArrayLazy(accessor, container, getKey, plan, markerId, bfId) {
|
|
2657
|
+
if (!container)
|
|
2658
|
+
return;
|
|
2659
|
+
const entries = new Map;
|
|
2660
|
+
let entryList = [];
|
|
2661
|
+
let hydrated = false;
|
|
2662
|
+
const needsResubscribe = plan.applyOuter !== undefined;
|
|
2663
|
+
const [generation, bumpGeneration] = needsResubscribe ? createSignal(0) : [null, null];
|
|
2664
|
+
let stranded = false;
|
|
2665
|
+
const markStranded = () => {
|
|
2666
|
+
if (needsResubscribe)
|
|
2667
|
+
stranded = true;
|
|
2668
|
+
};
|
|
2669
|
+
const flushStranded = () => {
|
|
2670
|
+
if (stranded && bumpGeneration) {
|
|
2671
|
+
stranded = false;
|
|
2672
|
+
bumpGeneration((n) => n + 1);
|
|
2673
|
+
}
|
|
2674
|
+
};
|
|
2675
|
+
let cachedStart = null;
|
|
2676
|
+
let cachedEnd = null;
|
|
2677
|
+
const resolveMarkers = () => {
|
|
2678
|
+
if (cachedStart && cachedEnd && cachedStart.isConnected && cachedEnd.isConnected) {
|
|
2679
|
+
return { start: cachedStart, end: cachedEnd };
|
|
2680
|
+
}
|
|
2681
|
+
const found = findLoopMarkers2(container, markerId);
|
|
2682
|
+
cachedStart = found.start;
|
|
2683
|
+
cachedEnd = found.end;
|
|
2684
|
+
return found;
|
|
2685
|
+
};
|
|
2686
|
+
const createEntry = (item, index, key) => {
|
|
2687
|
+
const entry = {
|
|
2688
|
+
key,
|
|
2689
|
+
primaryEl: undefined,
|
|
2690
|
+
item,
|
|
2691
|
+
refs: null,
|
|
2692
|
+
last: null
|
|
2693
|
+
};
|
|
2694
|
+
entry.primaryEl = untrack(() => plan.createRow(entry, index));
|
|
2695
|
+
if (!entry.primaryEl.dataset.key)
|
|
2696
|
+
entry.primaryEl.setAttribute(BF_KEY, key);
|
|
2697
|
+
markStranded();
|
|
2698
|
+
return entry;
|
|
2699
|
+
};
|
|
2700
|
+
createEffect(() => {
|
|
2701
|
+
const items = accessor();
|
|
2702
|
+
if (!items)
|
|
2703
|
+
return;
|
|
2704
|
+
const { start: startMarker, end: endMarker } = resolveMarkers();
|
|
2705
|
+
const anchor = endMarker ?? null;
|
|
2706
|
+
if (!hydrated) {
|
|
2707
|
+
hydrated = true;
|
|
2708
|
+
const doms = [];
|
|
2709
|
+
for (let node = startMarker ? startMarker.nextSibling : container.firstChild;node && node !== anchor; node = node.nextSibling) {
|
|
2710
|
+
if (node.nodeType === Node.ELEMENT_NODE)
|
|
2711
|
+
doms.push(node);
|
|
2712
|
+
}
|
|
2713
|
+
if (doms.length > 0 && entries.size === 0) {
|
|
2714
|
+
const list = [];
|
|
2715
|
+
const shared = Math.min(doms.length, items.length);
|
|
2716
|
+
for (let i2 = 0;i2 < shared; i2++) {
|
|
2717
|
+
const el = doms[i2];
|
|
2718
|
+
const ssrKey = el.getAttribute(BF_KEY);
|
|
2719
|
+
const key = ssrKey !== null ? ssrKey : getKey ? getKey(items[i2], i2) : String(i2);
|
|
2720
|
+
const entry = { key, primaryEl: el, item: items[i2], refs: null, last: null };
|
|
2721
|
+
entries.set(key, entry);
|
|
2722
|
+
list.push(entry);
|
|
2723
|
+
}
|
|
2724
|
+
for (let i2 = doms.length;i2 < items.length; i2++) {
|
|
2725
|
+
const item = items[i2];
|
|
2726
|
+
const key = getKey ? getKey(item, i2) : String(i2);
|
|
2727
|
+
const entry = createEntry(item, i2, key);
|
|
2728
|
+
entries.set(key, entry);
|
|
2729
|
+
list.push(entry);
|
|
2730
|
+
container.insertBefore(entry.primaryEl, anchor);
|
|
2731
|
+
}
|
|
2732
|
+
for (let i2 = items.length;i2 < doms.length; i2++)
|
|
2733
|
+
doms[i2].remove();
|
|
2734
|
+
entryList = list;
|
|
2735
|
+
flushStranded();
|
|
2736
|
+
return;
|
|
2737
|
+
}
|
|
2738
|
+
}
|
|
2739
|
+
if (items.length === 0) {
|
|
2740
|
+
if (entries.size > 0) {
|
|
2741
|
+
if (startMarker && endMarker) {
|
|
2742
|
+
const range = document.createRange();
|
|
2743
|
+
range.setStartAfter(startMarker);
|
|
2744
|
+
range.setEndBefore(endMarker);
|
|
2745
|
+
range.deleteContents();
|
|
2746
|
+
} else {
|
|
2747
|
+
let actualNodeCount = 0;
|
|
2748
|
+
for (let node = container.firstChild;node; node = node.nextSibling)
|
|
2749
|
+
actualNodeCount++;
|
|
2750
|
+
if (actualNodeCount === entries.size) {
|
|
2751
|
+
container.textContent = "";
|
|
2752
|
+
} else {
|
|
2753
|
+
for (const entry of entries.values())
|
|
2754
|
+
entry.primaryEl.remove();
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
2757
|
+
entries.clear();
|
|
2758
|
+
entryList = [];
|
|
2759
|
+
}
|
|
2760
|
+
return;
|
|
2761
|
+
}
|
|
2762
|
+
const newKeys = new Set;
|
|
2763
|
+
const warnedKeys = new Set;
|
|
2764
|
+
const desiredOrder = [];
|
|
2765
|
+
for (let i2 = 0;i2 < items.length; i2++) {
|
|
2766
|
+
const item = items[i2];
|
|
2767
|
+
const key = getKey ? getKey(item, i2) : String(i2);
|
|
2768
|
+
if (newKeys.has(key) && !warnedKeys.has(key)) {
|
|
2769
|
+
warnedKeys.add(key);
|
|
2770
|
+
console.warn(`[BarefootJS] mapArrayLazy: duplicate key "${key}" — items with this key collapse to a single DOM row, ` + `so only the last one renders. Use a per-item identifier (e.g. \`key={item.id}\`) for correct reconciliation.`);
|
|
2771
|
+
}
|
|
2772
|
+
newKeys.add(key);
|
|
2773
|
+
const existing = entries.get(key);
|
|
2774
|
+
if (existing) {
|
|
2775
|
+
if (!Object.is(existing.item, item)) {
|
|
2776
|
+
const prevItem = existing.item;
|
|
2777
|
+
existing.item = item;
|
|
2778
|
+
untrack(() => plan.applyItem(existing, prevItem));
|
|
2779
|
+
markStranded();
|
|
2780
|
+
}
|
|
2781
|
+
desiredOrder.push(existing);
|
|
2782
|
+
} else {
|
|
2783
|
+
const entry = createEntry(item, i2, key);
|
|
2784
|
+
entries.set(key, entry);
|
|
2785
|
+
desiredOrder.push(entry);
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2788
|
+
for (const [key, entry] of entries) {
|
|
2789
|
+
if (!newKeys.has(key)) {
|
|
2790
|
+
if (entry.primaryEl.parentNode)
|
|
2791
|
+
entry.primaryEl.remove();
|
|
2792
|
+
entries.delete(key);
|
|
2793
|
+
}
|
|
2794
|
+
}
|
|
2795
|
+
const primaryElToDesiredIndex = new Map;
|
|
2796
|
+
for (let i2 = 0;i2 < desiredOrder.length; i2++) {
|
|
2797
|
+
primaryElToDesiredIndex.set(desiredOrder[i2].primaryEl, i2);
|
|
2798
|
+
}
|
|
2799
|
+
const domOrderIndices = [];
|
|
2800
|
+
for (let node = startMarker ? startMarker.nextSibling : container.firstChild;node && node !== anchor; node = node.nextSibling) {
|
|
2801
|
+
if (node.nodeType !== Node.ELEMENT_NODE)
|
|
2802
|
+
continue;
|
|
2803
|
+
const idx = primaryElToDesiredIndex.get(node);
|
|
2804
|
+
if (idx !== undefined)
|
|
2805
|
+
domOrderIndices.push(idx);
|
|
2806
|
+
}
|
|
2807
|
+
const stationary = new Array(desiredOrder.length).fill(false);
|
|
2808
|
+
for (const pos of longestIncreasingSubsequenceIndices(domOrderIndices)) {
|
|
2809
|
+
stationary[domOrderIndices[pos]] = true;
|
|
2810
|
+
}
|
|
2811
|
+
let i = 0;
|
|
2812
|
+
while (i < desiredOrder.length) {
|
|
2813
|
+
if (stationary[i]) {
|
|
2814
|
+
i++;
|
|
2815
|
+
continue;
|
|
2816
|
+
}
|
|
2817
|
+
let j = i;
|
|
2818
|
+
while (j < desiredOrder.length && !stationary[j])
|
|
2819
|
+
j++;
|
|
2820
|
+
const before = j < desiredOrder.length ? desiredOrder[j].primaryEl : anchor;
|
|
2821
|
+
if (j - i === 1) {
|
|
2822
|
+
container.insertBefore(desiredOrder[i].primaryEl, before);
|
|
2823
|
+
} else {
|
|
2824
|
+
const runFragment = document.createDocumentFragment();
|
|
2825
|
+
for (let k = i;k < j; k++)
|
|
2826
|
+
runFragment.appendChild(desiredOrder[k].primaryEl);
|
|
2827
|
+
container.insertBefore(runFragment, before);
|
|
2828
|
+
}
|
|
2829
|
+
i = j;
|
|
2830
|
+
}
|
|
2831
|
+
entryList = desiredOrder;
|
|
2832
|
+
flushStranded();
|
|
2833
|
+
}, bfId);
|
|
2834
|
+
if (plan.applyOuter) {
|
|
2835
|
+
const applyOuter = plan.applyOuter.bind(plan);
|
|
2836
|
+
let seed = true;
|
|
2837
|
+
createEffect(() => {
|
|
2838
|
+
if (generation)
|
|
2839
|
+
generation();
|
|
2840
|
+
const isSeed = seed;
|
|
2841
|
+
seed = false;
|
|
2842
|
+
applyOuter(entryList, isSeed);
|
|
2843
|
+
});
|
|
2844
|
+
}
|
|
2845
|
+
}
|
|
2620
2846
|
// src/runtime/patch-leaf.ts
|
|
2621
2847
|
function patchLeaf(el, html) {
|
|
2622
2848
|
const tpl = document.createElement("template");
|
|
@@ -2723,11 +2949,11 @@ function claimMarkerlessText(root, spec) {
|
|
|
2723
2949
|
}
|
|
2724
2950
|
const existing = parent.childNodes[idx];
|
|
2725
2951
|
if (existing && existing.nodeType === Node.TEXT_NODE) {
|
|
2726
|
-
return { kind: "text",
|
|
2952
|
+
return { kind: "text", ref: existing };
|
|
2727
2953
|
}
|
|
2728
2954
|
const node = document.createTextNode("");
|
|
2729
2955
|
parent.insertBefore(node, existing ?? null);
|
|
2730
|
-
return { kind: "text", node };
|
|
2956
|
+
return { kind: "text", ref: node };
|
|
2731
2957
|
}
|
|
2732
2958
|
function claimOne(root, spec) {
|
|
2733
2959
|
if (spec.kind === "text" && spec.markerless) {
|
|
@@ -2737,7 +2963,8 @@ function claimOne(root, spec) {
|
|
|
2737
2963
|
if (!anchor)
|
|
2738
2964
|
return null;
|
|
2739
2965
|
if (spec.kind === "text") {
|
|
2740
|
-
|
|
2966
|
+
const next = anchor.nextSibling;
|
|
2967
|
+
return { kind: "text", ref: next?.nodeType === Node.TEXT_NODE ? next : anchor };
|
|
2741
2968
|
}
|
|
2742
2969
|
const end = findMarkupEnd(anchor);
|
|
2743
2970
|
if (!end) {
|
|
@@ -2746,8 +2973,42 @@ function claimOne(root, spec) {
|
|
|
2746
2973
|
}
|
|
2747
2974
|
return { kind: "markup", start: anchor, end, last: undefined };
|
|
2748
2975
|
}
|
|
2749
|
-
function
|
|
2750
|
-
|
|
2976
|
+
function materializeText(slot) {
|
|
2977
|
+
const anchor = slot.ref;
|
|
2978
|
+
const parent = anchor.parentNode;
|
|
2979
|
+
if (!parent)
|
|
2980
|
+
return null;
|
|
2981
|
+
const node = document.createTextNode("");
|
|
2982
|
+
parent.insertBefore(node, anchor.nextSibling);
|
|
2983
|
+
slot.ref = node;
|
|
2984
|
+
return node;
|
|
2985
|
+
}
|
|
2986
|
+
function readText(slot) {
|
|
2987
|
+
return slot.ref.nodeType === Node.TEXT_NODE ? slot.ref.nodeValue ?? "" : "";
|
|
2988
|
+
}
|
|
2989
|
+
function writeText(slot, value) {
|
|
2990
|
+
const node = slot.ref.nodeType === Node.TEXT_NODE ? slot.ref : materializeText(slot);
|
|
2991
|
+
if (!node)
|
|
2992
|
+
return;
|
|
2993
|
+
node.nodeValue = String(value ?? "");
|
|
2994
|
+
}
|
|
2995
|
+
function textOrNode(value) {
|
|
2996
|
+
if (typeof Node !== "undefined" && value instanceof Node)
|
|
2997
|
+
return value;
|
|
2998
|
+
return String(value);
|
|
2999
|
+
}
|
|
3000
|
+
function promoteTextToMarkup(slot, id) {
|
|
3001
|
+
const anchor = slot.ref.nodeType === Node.COMMENT_NODE ? slot.ref : isSlotComment(slot.ref.previousSibling, id) ? slot.ref.previousSibling : null;
|
|
3002
|
+
if (!anchor) {
|
|
3003
|
+
console.warn(`[barefootjs] slot ${id} was claimed as text and received a Node, but has no anchor marker to promote from; write ignored`);
|
|
3004
|
+
return null;
|
|
3005
|
+
}
|
|
3006
|
+
const end = findMarkupEnd(anchor);
|
|
3007
|
+
if (!end) {
|
|
3008
|
+
console.warn(`[barefootjs] slot ${id} was claimed as text and received a Node, but has no end marker; write ignored`);
|
|
3009
|
+
return null;
|
|
3010
|
+
}
|
|
3011
|
+
return { kind: "markup", start: anchor, end, last: undefined };
|
|
2751
3012
|
}
|
|
2752
3013
|
function clearMarkupRange(start, end) {
|
|
2753
3014
|
const parent = end.parentNode;
|
|
@@ -2791,19 +3052,37 @@ function writeSlot(refs, id, value) {
|
|
|
2791
3052
|
return;
|
|
2792
3053
|
}
|
|
2793
3054
|
if (ref.kind === "text") {
|
|
3055
|
+
if (typeof Node !== "undefined" && value instanceof Node) {
|
|
3056
|
+
const promoted = promoteTextToMarkup(ref, id);
|
|
3057
|
+
if (!promoted)
|
|
3058
|
+
return;
|
|
3059
|
+
refs.set(id, promoted);
|
|
3060
|
+
writeMarkup(promoted, value);
|
|
3061
|
+
return;
|
|
3062
|
+
}
|
|
2794
3063
|
writeText(ref, value);
|
|
2795
3064
|
} else {
|
|
2796
3065
|
writeMarkup(ref, value);
|
|
2797
3066
|
}
|
|
2798
3067
|
}
|
|
3068
|
+
function readSlot(refs, id) {
|
|
3069
|
+
const ref = refs.get(id);
|
|
3070
|
+
if (!ref || ref.kind !== "text")
|
|
3071
|
+
return null;
|
|
3072
|
+
return readText(ref);
|
|
3073
|
+
}
|
|
2799
3074
|
function claimSlots(root, plan) {
|
|
3075
|
+
const refs = claimRefs(root, plan);
|
|
3076
|
+
return { write: (id, value) => writeSlot(refs, id, value) };
|
|
3077
|
+
}
|
|
3078
|
+
function claimRefs(root, plan) {
|
|
2800
3079
|
const refs = new Map;
|
|
2801
3080
|
for (const spec of plan) {
|
|
2802
3081
|
const ref = claimOne(root, spec);
|
|
2803
3082
|
if (ref)
|
|
2804
3083
|
refs.set(spec.id, ref);
|
|
2805
3084
|
}
|
|
2806
|
-
return
|
|
3085
|
+
return refs;
|
|
2807
3086
|
}
|
|
2808
3087
|
function lazySlots(root, plan) {
|
|
2809
3088
|
let claimed = null;
|
|
@@ -2813,6 +3092,14 @@ function lazySlots(root, plan) {
|
|
|
2813
3092
|
claimed.write(id, value);
|
|
2814
3093
|
};
|
|
2815
3094
|
}
|
|
3095
|
+
function lazyClaimSlots(root, plan) {
|
|
3096
|
+
let refs = null;
|
|
3097
|
+
const ensure = () => refs ??= claimRefs(root, plan);
|
|
3098
|
+
return {
|
|
3099
|
+
write: (id, value) => writeSlot(ensure(), id, value),
|
|
3100
|
+
read: (id) => readSlot(ensure(), id)
|
|
3101
|
+
};
|
|
3102
|
+
}
|
|
2816
3103
|
// src/runtime/style.ts
|
|
2817
3104
|
function styleToCss(value) {
|
|
2818
3105
|
if (value == null)
|
|
@@ -3336,6 +3623,7 @@ export {
|
|
|
3336
3623
|
upsertChild,
|
|
3337
3624
|
unwrap,
|
|
3338
3625
|
untrack,
|
|
3626
|
+
textOrNode,
|
|
3339
3627
|
textNodeAfterComment as tAfter,
|
|
3340
3628
|
styleToCss,
|
|
3341
3629
|
spreadAttrs,
|
|
@@ -3359,9 +3647,11 @@ export {
|
|
|
3359
3647
|
parseHTML,
|
|
3360
3648
|
onMount,
|
|
3361
3649
|
onCleanup,
|
|
3650
|
+
mapArrayLazy,
|
|
3362
3651
|
mapArrayAnchored,
|
|
3363
3652
|
mapArray,
|
|
3364
3653
|
lazySlots,
|
|
3654
|
+
lazyClaimSlots,
|
|
3365
3655
|
isSSRPortal,
|
|
3366
3656
|
insert,
|
|
3367
3657
|
initChild,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.1",
|
|
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.28.1"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
61
|
"@barefootjs/jsx": ">=0.2.0"
|