@barefootjs/client 0.33.1 → 0.33.3
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/csr-adapter.js +21 -14
- package/dist/runtime/component.d.ts +52 -1
- package/dist/runtime/component.d.ts.map +1 -1
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +154 -54
- package/dist/runtime/map-array-lazy.d.ts +6 -1
- package/dist/runtime/map-array-lazy.d.ts.map +1 -1
- package/dist/runtime/map-array.d.ts +11 -1
- package/dist/runtime/map-array.d.ts.map +1 -1
- package/dist/runtime/qsa-item.d.ts.map +1 -1
- package/dist/runtime/registry.d.ts.map +1 -1
- package/dist/runtime/standalone.js +154 -54
- package/dist/runtime/types.d.ts +19 -1
- package/dist/runtime/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/runtime/component.ts +347 -30
- package/src/runtime/hydrate.ts +11 -2
- package/src/runtime/index.ts +1 -0
- package/src/runtime/map-array-lazy.ts +15 -4
- package/src/runtime/map-array.ts +186 -29
- package/src/runtime/qsa-item.ts +3 -1
- package/src/runtime/registry.ts +4 -1
- package/src/runtime/types.ts +19 -1
|
@@ -1737,8 +1737,7 @@ function hydrateCommentScope(comment) {
|
|
|
1737
1737
|
if (hydratedScopes.has(proxyEl))
|
|
1738
1738
|
return;
|
|
1739
1739
|
commentScopeRegistry.set(proxyEl, { commentNode: comment, scopeId });
|
|
1740
|
-
const
|
|
1741
|
-
const props = parsed[name] ?? {};
|
|
1740
|
+
const props = parseProps(propsJson || null, `comment scope ${scopeId}`);
|
|
1742
1741
|
runInit(proxyEl, def, props);
|
|
1743
1742
|
}
|
|
1744
1743
|
function nextElementSibling2(node) {
|
|
@@ -1775,25 +1774,25 @@ function mountRowRoot(el) {
|
|
|
1775
1774
|
}
|
|
1776
1775
|
return el;
|
|
1777
1776
|
}
|
|
1778
|
-
function createComponent(nameOrDef, props = {}, key, slot, mountAt) {
|
|
1779
|
-
const element = materializeComponent(nameOrDef, props, key, slot, mountAt);
|
|
1777
|
+
function createComponent(nameOrDef, props = {}, key, slot, mountAt, keyAttrName2 = BF_KEY) {
|
|
1778
|
+
const element = materializeComponent(nameOrDef, props, key, slot, mountAt, keyAttrName2);
|
|
1780
1779
|
if (mountAt && mountAt.parentNode && element !== mountAt) {
|
|
1781
1780
|
mountAt.replaceWith(element);
|
|
1782
1781
|
}
|
|
1783
1782
|
return element;
|
|
1784
1783
|
}
|
|
1785
|
-
function materializeComponent(nameOrDef, props = {}, key, slot, mountAt) {
|
|
1784
|
+
function materializeComponent(nameOrDef, props = {}, key, slot, mountAt, keyAttrName2 = BF_KEY) {
|
|
1786
1785
|
if (props == null)
|
|
1787
1786
|
props = {};
|
|
1788
1787
|
const rowMount = mountAt ? null : takeRowMountPoint();
|
|
1789
1788
|
if (typeof nameOrDef !== "string") {
|
|
1790
|
-
return createComponentFromDef(nameOrDef, props, key, mountAt, rowMount);
|
|
1789
|
+
return createComponentFromDef(nameOrDef, props, key, mountAt, rowMount, keyAttrName2);
|
|
1791
1790
|
}
|
|
1792
1791
|
const name = nameOrDef;
|
|
1793
1792
|
const templateFn = getTemplate(name);
|
|
1794
1793
|
if (!templateFn) {
|
|
1795
1794
|
console.warn(`[BarefootJS] Template not found for component: ${name}`);
|
|
1796
|
-
return createPlaceholder(name, key);
|
|
1795
|
+
return createPlaceholder(name, key, keyAttrName2);
|
|
1797
1796
|
}
|
|
1798
1797
|
const childrenDescriptor = Object.getOwnPropertyDescriptor(props, "children");
|
|
1799
1798
|
const childrenIsGetter = childrenDescriptor != null && typeof childrenDescriptor.get === "function";
|
|
@@ -1818,13 +1817,16 @@ function materializeComponent(nameOrDef, props = {}, key, slot, mountAt) {
|
|
|
1818
1817
|
});
|
|
1819
1818
|
const def = getRegisteredDef(name);
|
|
1820
1819
|
const isCommentWrapper = def?.comment === true;
|
|
1820
|
+
const isFragmentRoot = def?.fragmentRoot === true;
|
|
1821
1821
|
const derivedScopeId = slot?.parent && slot.mount ? `${slot.parent}_${slot.mount}` : null;
|
|
1822
|
-
const scopeId = isCommentWrapper ? null : derivedScopeId ?? `${def?.name ?? name}_${generateId()}`;
|
|
1822
|
+
const scopeId = isCommentWrapper && !isFragmentRoot ? null : derivedScopeId ?? `${def?.name ?? name}_${generateId()}`;
|
|
1823
1823
|
const prevParentScopeId = _parentScopeId;
|
|
1824
1824
|
if (scopeId) {
|
|
1825
1825
|
_parentScopeId = scopeId;
|
|
1826
1826
|
} else if (slot?.parent) {
|
|
1827
1827
|
_parentScopeId = slot.parent;
|
|
1828
|
+
} else if (!_parentScopeId) {
|
|
1829
|
+
_parentScopeId = `${def?.name ?? name}_${generateId()}`;
|
|
1828
1830
|
}
|
|
1829
1831
|
let html;
|
|
1830
1832
|
try {
|
|
@@ -1832,12 +1834,18 @@ function materializeComponent(nameOrDef, props = {}, key, slot, mountAt) {
|
|
|
1832
1834
|
} finally {
|
|
1833
1835
|
_parentScopeId = prevParentScopeId;
|
|
1834
1836
|
}
|
|
1835
|
-
const
|
|
1837
|
+
const parsedFragment = parseHTML(html.trim());
|
|
1838
|
+
const roots = isFragmentRoot ? Array.from(parsedFragment.childNodes) : parsedFragment.firstChild ? [parsedFragment.firstChild] : [];
|
|
1839
|
+
const element = isFragmentRoot ? roots.find((node) => node.nodeType === Node.ELEMENT_NODE) : roots[0];
|
|
1840
|
+
if (isFragmentRoot && roots.length > 0 && !element) {
|
|
1841
|
+
console.warn(`[BarefootJS] Fragment-root component ${name} rendered no element root; ` + "a scope needs at least one element to attach to. Wrap the content in an element.");
|
|
1842
|
+
return createPlaceholder(name, key, keyAttrName2);
|
|
1843
|
+
}
|
|
1836
1844
|
if (!element) {
|
|
1837
1845
|
console.warn(`[BarefootJS] Template returned empty HTML for component: ${name}`);
|
|
1838
|
-
return createPlaceholder(name, key);
|
|
1846
|
+
return createPlaceholder(name, key, keyAttrName2);
|
|
1839
1847
|
}
|
|
1840
|
-
if (scopeId) {
|
|
1848
|
+
if (scopeId && !isFragmentRoot) {
|
|
1841
1849
|
element.setAttribute(BF_SCOPE, scopeId);
|
|
1842
1850
|
}
|
|
1843
1851
|
if (slot) {
|
|
@@ -1846,13 +1854,38 @@ function materializeComponent(nameOrDef, props = {}, key, slot, mountAt) {
|
|
|
1846
1854
|
element.setAttribute(BF_AT, slot.mount);
|
|
1847
1855
|
}
|
|
1848
1856
|
if (key !== undefined) {
|
|
1849
|
-
element.setAttribute(
|
|
1857
|
+
element.setAttribute(keyAttrName2, String(key));
|
|
1858
|
+
}
|
|
1859
|
+
const fragmentComments = isFragmentRoot && scopeId ? {
|
|
1860
|
+
start: document.createComment(`${BF_SCOPE_COMMENT_PREFIX}${scopeId}`),
|
|
1861
|
+
end: document.createComment(`${BF_SCOPE_COMMENT_END_PREFIX}${scopeId}`)
|
|
1862
|
+
} : null;
|
|
1863
|
+
if (fragmentComments) {
|
|
1864
|
+
commentScopeRegistry.set(element, { commentNode: fragmentComments.start, scopeId });
|
|
1850
1865
|
}
|
|
1851
1866
|
const rootIsDeferredPlaceholder = element.hasAttribute(BF_PLACEHOLDER);
|
|
1867
|
+
let bareFragment = null;
|
|
1852
1868
|
if (mountAt && !rootIsDeferredPlaceholder) {
|
|
1853
|
-
|
|
1869
|
+
if (fragmentComments) {
|
|
1870
|
+
mountAt.replaceWith(fragmentComments.start, ...roots, fragmentComments.end);
|
|
1871
|
+
} else {
|
|
1872
|
+
mountAt.replaceWith(element);
|
|
1873
|
+
}
|
|
1854
1874
|
} else if (rowMount && !rootIsDeferredPlaceholder) {
|
|
1855
|
-
|
|
1875
|
+
if (fragmentComments) {
|
|
1876
|
+
rowMount.container.insertBefore(fragmentComments.start, rowMount.anchor);
|
|
1877
|
+
rowMount.container.insertBefore(element, rowMount.anchor);
|
|
1878
|
+
rowMount.container.insertBefore(fragmentComments.end, rowMount.anchor);
|
|
1879
|
+
element.__bfScopeComments = fragmentComments;
|
|
1880
|
+
if (roots.length > 1) {
|
|
1881
|
+
console.warn(`[BarefootJS] Fragment-root component ${name} used as a loop row renders ` + `${roots.length} top-level nodes; only the first element is connected here. ` + "See https://github.com/piconic-ai/barefootjs/issues/2733");
|
|
1882
|
+
}
|
|
1883
|
+
} else {
|
|
1884
|
+
rowMount.container.insertBefore(element, rowMount.anchor);
|
|
1885
|
+
}
|
|
1886
|
+
} else if (fragmentComments && !rootIsDeferredPlaceholder) {
|
|
1887
|
+
bareFragment = document.createDocumentFragment();
|
|
1888
|
+
bareFragment.append(fragmentComments.start, ...roots, fragmentComments.end);
|
|
1856
1889
|
}
|
|
1857
1890
|
const prevScope = setCurrentScope(element);
|
|
1858
1891
|
let placeholderWrapper = null;
|
|
@@ -1880,18 +1913,30 @@ function materializeComponent(nameOrDef, props = {}, key, slot, mountAt) {
|
|
|
1880
1913
|
}
|
|
1881
1914
|
setCurrentScope(prevScope);
|
|
1882
1915
|
hydratedScopes.add(element);
|
|
1883
|
-
return element;
|
|
1916
|
+
return bareFragment ?? element;
|
|
1917
|
+
}
|
|
1918
|
+
var FIRST_TAG_PATTERN = /<([a-zA-Z][^\s/>]*)/;
|
|
1919
|
+
var TAG_HEAD_PATTERN = /^(<[a-zA-Z][^\s/>]*)/;
|
|
1920
|
+
function spliceAttrsAfterFirstTag(html, attrs) {
|
|
1921
|
+
const firstElMatch = html.match(FIRST_TAG_PATTERN);
|
|
1922
|
+
if (!firstElMatch)
|
|
1923
|
+
return html;
|
|
1924
|
+
const insertPos = firstElMatch.index;
|
|
1925
|
+
return html.slice(0, insertPos) + html.slice(insertPos).replace(TAG_HEAD_PATTERN, `$1${attrs}`);
|
|
1884
1926
|
}
|
|
1885
1927
|
function renderChild(name, props, key, slotSuffix) {
|
|
1886
1928
|
const templateFn = getTemplate(name);
|
|
1887
1929
|
const suffix = slotSuffix ? `_${slotSuffix}` : "";
|
|
1888
|
-
const
|
|
1930
|
+
const def = getRegisteredDef(name);
|
|
1931
|
+
const displayName = def?.name ?? name;
|
|
1932
|
+
const isFragmentRoot = def?.fragmentRoot === true;
|
|
1889
1933
|
const scopePrefix = _parentScopeId && slotSuffix ? _parentScopeId : `${displayName}_${generateId()}`;
|
|
1934
|
+
const scopeId = `${scopePrefix}${suffix}`;
|
|
1890
1935
|
const keyAttr = key !== undefined ? ` ${BF_KEY}="${key}"` : "";
|
|
1891
1936
|
const slotAttrs = _parentScopeId && slotSuffix ? ` ${BF_HOST}="${_parentScopeId}" ${BF_AT}="${slotSuffix}"` : "";
|
|
1892
|
-
const bfsAttr = `${BF_SCOPE}="${
|
|
1937
|
+
const bfsAttr = `${BF_SCOPE}="${scopeId}"`;
|
|
1893
1938
|
if (!templateFn) {
|
|
1894
|
-
return `<div ${bfsAttr}${slotAttrs}${keyAttr}></div>`;
|
|
1939
|
+
return isFragmentRoot ? `<!--${BF_SCOPE_COMMENT_PREFIX}${scopeId}--><div></div><!--${BF_SCOPE_COMMENT_END_PREFIX}${scopeId}-->` : `<div ${bfsAttr}${slotAttrs}${keyAttr}></div>`;
|
|
1895
1940
|
}
|
|
1896
1941
|
const prevParentScopeId = _parentScopeId;
|
|
1897
1942
|
_parentScopeId = `${scopePrefix}${suffix}`;
|
|
@@ -1902,7 +1947,12 @@ function renderChild(name, props, key, slotSuffix) {
|
|
|
1902
1947
|
_parentScopeId = prevParentScopeId;
|
|
1903
1948
|
}
|
|
1904
1949
|
let html = raw.trim().replace(PLACEHOLDER_ATTR_PATTERN, _parentScopeId ? ` bf-s="${_parentScopeId}"` : "");
|
|
1905
|
-
|
|
1950
|
+
if (isFragmentRoot) {
|
|
1951
|
+
const hostSuffix = _parentScopeId && slotSuffix ? `|h=${_parentScopeId}|m=${slotSuffix}` : "";
|
|
1952
|
+
const keyedHtml = keyAttr ? spliceAttrsAfterFirstTag(html, keyAttr) : html;
|
|
1953
|
+
return `<!--${BF_SCOPE_COMMENT_PREFIX}${scopeId}${hostSuffix}-->${keyedHtml}<!--${BF_SCOPE_COMMENT_END_PREFIX}${scopeId}-->`;
|
|
1954
|
+
}
|
|
1955
|
+
const firstElMatch = html.match(FIRST_TAG_PATTERN);
|
|
1906
1956
|
if (!firstElMatch)
|
|
1907
1957
|
return html;
|
|
1908
1958
|
const insertPos = firstElMatch.index;
|
|
@@ -1911,20 +1961,20 @@ function renderChild(name, props, key, slotSuffix) {
|
|
|
1911
1961
|
if (ROOT_HAS_BFS_PATTERN.test(afterInsert)) {
|
|
1912
1962
|
if (!extraAttrs)
|
|
1913
1963
|
return html;
|
|
1914
|
-
return html.slice(0, insertPos) + afterInsert.replace(
|
|
1964
|
+
return html.slice(0, insertPos) + afterInsert.replace(TAG_HEAD_PATTERN, `$1${extraAttrs}`);
|
|
1915
1965
|
}
|
|
1916
|
-
return html.slice(0, insertPos) + afterInsert.replace(
|
|
1966
|
+
return html.slice(0, insertPos) + afterInsert.replace(TAG_HEAD_PATTERN, `$1 ${bfsAttr}${extraAttrs}`);
|
|
1917
1967
|
}
|
|
1918
1968
|
var PLACEHOLDER_ATTR_PATTERN = new RegExp(`\\s+bf-s="${BF_PARENT_SCOPE_PLACEHOLDER}"`, "g");
|
|
1919
1969
|
var ROOT_HAS_BFS_PATTERN = /^<\w+[^>]*\sbf-s="/;
|
|
1920
1970
|
function generateId() {
|
|
1921
1971
|
return Math.random().toString(36).slice(2, 8);
|
|
1922
1972
|
}
|
|
1923
|
-
function createPlaceholder(name, key) {
|
|
1973
|
+
function createPlaceholder(name, key, keyAttrName2 = BF_KEY) {
|
|
1924
1974
|
const el = document.createElement("div");
|
|
1925
1975
|
el.setAttribute(BF_SCOPE, `${name}_placeholder`);
|
|
1926
1976
|
if (key !== undefined) {
|
|
1927
|
-
el.setAttribute(
|
|
1977
|
+
el.setAttribute(keyAttrName2, String(key));
|
|
1928
1978
|
}
|
|
1929
1979
|
el.textContent = `[${name}]`;
|
|
1930
1980
|
el.style.cssText = "color: red; border: 1px dashed red; padding: 4px;";
|
|
@@ -1973,6 +2023,9 @@ function escapeTextOrMarkup(value) {
|
|
|
1973
2023
|
return value[BF_MARKUP_BRAND];
|
|
1974
2024
|
return escapeText(value);
|
|
1975
2025
|
}
|
|
2026
|
+
function markupOrEmpty(value) {
|
|
2027
|
+
return value == null ? "" : value;
|
|
2028
|
+
}
|
|
1976
2029
|
function escapeTextOrNode(value) {
|
|
1977
2030
|
if (isBfMarkup(value))
|
|
1978
2031
|
return value[BF_MARKUP_BRAND];
|
|
@@ -2034,7 +2087,7 @@ function insertGetterChildren(element, children) {
|
|
|
2034
2087
|
element.appendChild(document.createTextNode(String(children)));
|
|
2035
2088
|
}
|
|
2036
2089
|
}
|
|
2037
|
-
function createComponentFromDef(def, props, key, mountAt, rowMount) {
|
|
2090
|
+
function createComponentFromDef(def, props, key, mountAt, rowMount, keyAttrName2 = BF_KEY) {
|
|
2038
2091
|
if (!def.template) {
|
|
2039
2092
|
throw new Error("[BarefootJS] createComponent with ComponentDef requires a template function");
|
|
2040
2093
|
}
|
|
@@ -2051,7 +2104,7 @@ function createComponentFromDef(def, props, key, mountAt, rowMount) {
|
|
|
2051
2104
|
const scopeId = `${name}_${generateId()}`;
|
|
2052
2105
|
element.setAttribute(BF_SCOPE, scopeId);
|
|
2053
2106
|
if (key !== undefined) {
|
|
2054
|
-
element.setAttribute(
|
|
2107
|
+
element.setAttribute(keyAttrName2, String(key));
|
|
2055
2108
|
}
|
|
2056
2109
|
if (mountAt) {
|
|
2057
2110
|
mountAt.replaceWith(element);
|
|
@@ -2243,6 +2296,11 @@ function upsertChildItem(primaryEl, name, slotId, props, key, anchorScope) {
|
|
|
2243
2296
|
return null;
|
|
2244
2297
|
}
|
|
2245
2298
|
// src/runtime/map-array.ts
|
|
2299
|
+
function scopeIdOf(start) {
|
|
2300
|
+
const rest = (start.nodeValue ?? "").slice(BF_SCOPE_COMMENT_PREFIX.length);
|
|
2301
|
+
const pipe = rest.indexOf("|");
|
|
2302
|
+
return pipe >= 0 ? rest.slice(0, pipe) : rest;
|
|
2303
|
+
}
|
|
2246
2304
|
function findLoopMarkers2(container, markerId) {
|
|
2247
2305
|
let start = null;
|
|
2248
2306
|
let end = null;
|
|
@@ -2280,31 +2338,55 @@ function findItemRanges(start, end) {
|
|
|
2280
2338
|
const ranges = [];
|
|
2281
2339
|
let current = null;
|
|
2282
2340
|
let sawItemMarker = false;
|
|
2341
|
+
let pendingScopeStart = null;
|
|
2342
|
+
let openScopeComments = null;
|
|
2283
2343
|
let node = start.nextSibling;
|
|
2284
2344
|
while (node && node !== end) {
|
|
2285
|
-
if (node.nodeType === Node.COMMENT_NODE
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2345
|
+
if (node.nodeType === Node.COMMENT_NODE) {
|
|
2346
|
+
const value = node.nodeValue ?? "";
|
|
2347
|
+
if (value === BF_LOOP_ITEM) {
|
|
2348
|
+
sawItemMarker = true;
|
|
2349
|
+
current = { startMarker: node, primaryEl: null, extras: [], scopeComments: null };
|
|
2350
|
+
ranges.push(current);
|
|
2351
|
+
} else if (value.startsWith(BF_SCOPE_COMMENT_PREFIX)) {
|
|
2352
|
+
pendingScopeStart = node;
|
|
2353
|
+
} else if (openScopeComments && value === BF_SCOPE_COMMENT_END_PREFIX + scopeIdOf(openScopeComments.start)) {
|
|
2354
|
+
openScopeComments.end = node;
|
|
2355
|
+
openScopeComments = null;
|
|
2356
|
+
}
|
|
2289
2357
|
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
|
2290
2358
|
const el = node;
|
|
2359
|
+
let scopeComments = null;
|
|
2360
|
+
if (pendingScopeStart) {
|
|
2361
|
+
scopeComments = { start: pendingScopeStart, end: null };
|
|
2362
|
+
openScopeComments = scopeComments;
|
|
2363
|
+
pendingScopeStart = null;
|
|
2364
|
+
}
|
|
2291
2365
|
if (sawItemMarker) {
|
|
2292
|
-
if (!current.primaryEl)
|
|
2366
|
+
if (!current.primaryEl) {
|
|
2293
2367
|
current.primaryEl = el;
|
|
2294
|
-
|
|
2368
|
+
current.scopeComments = scopeComments;
|
|
2369
|
+
} else
|
|
2295
2370
|
current.extras.push(el);
|
|
2296
2371
|
} else {
|
|
2297
|
-
ranges.push({ startMarker: null, primaryEl: el, extras: [] });
|
|
2372
|
+
ranges.push({ startMarker: null, primaryEl: el, extras: [], scopeComments });
|
|
2298
2373
|
}
|
|
2299
2374
|
}
|
|
2300
2375
|
node = node.nextSibling;
|
|
2301
2376
|
}
|
|
2302
|
-
return ranges.filter((r) => r.primaryEl !== null)
|
|
2377
|
+
return ranges.filter((r) => r.primaryEl !== null).map((r) => ({
|
|
2378
|
+
...r,
|
|
2379
|
+
scopeComments: r.scopeComments?.end ? r.scopeComments : null
|
|
2380
|
+
}));
|
|
2303
2381
|
}
|
|
2304
2382
|
function insertScope(scope, target, anchor) {
|
|
2305
2383
|
if (scope.startMarker)
|
|
2306
2384
|
target.insertBefore(scope.startMarker, anchor);
|
|
2385
|
+
if (scope.scopeComments)
|
|
2386
|
+
target.insertBefore(scope.scopeComments.start, anchor);
|
|
2307
2387
|
target.insertBefore(scope.primaryEl, anchor);
|
|
2388
|
+
if (scope.scopeComments)
|
|
2389
|
+
target.insertBefore(scope.scopeComments.end, anchor);
|
|
2308
2390
|
for (const ex of scope.extras)
|
|
2309
2391
|
target.insertBefore(ex, anchor);
|
|
2310
2392
|
}
|
|
@@ -2343,19 +2425,24 @@ function longestIncreasingSubsequenceIndices(arr) {
|
|
|
2343
2425
|
function removeScope(scope) {
|
|
2344
2426
|
if (scope.startMarker?.parentNode)
|
|
2345
2427
|
scope.startMarker.remove();
|
|
2428
|
+
if (scope.scopeComments?.start.parentNode)
|
|
2429
|
+
scope.scopeComments.start.remove();
|
|
2346
2430
|
if (scope.primaryEl.parentNode)
|
|
2347
2431
|
scope.primaryEl.remove();
|
|
2432
|
+
if (scope.scopeComments?.end.parentNode)
|
|
2433
|
+
scope.scopeComments.end.remove();
|
|
2348
2434
|
for (const ex of scope.extras) {
|
|
2349
2435
|
if (ex.parentNode)
|
|
2350
2436
|
ex.remove();
|
|
2351
2437
|
}
|
|
2352
2438
|
}
|
|
2353
|
-
function createItemScope(item, index, renderItem, existingPrimary, existingExtras, existingStart, rowMount) {
|
|
2439
|
+
function createItemScope(item, index, renderItem, existingPrimary, existingExtras, existingStart, existingScopeComments, rowMount) {
|
|
2354
2440
|
let primaryEl;
|
|
2355
2441
|
let dispose;
|
|
2356
2442
|
let setItem;
|
|
2357
2443
|
let extras = [];
|
|
2358
2444
|
let startMarker = null;
|
|
2445
|
+
let scopeComments = null;
|
|
2359
2446
|
createRoot((d) => {
|
|
2360
2447
|
dispose = d;
|
|
2361
2448
|
const [itemAccessor, itemSetter] = createSignal(item);
|
|
@@ -2378,6 +2465,7 @@ function createItemScope(item, index, renderItem, existingPrimary, existingExtra
|
|
|
2378
2465
|
if (existingPrimary) {
|
|
2379
2466
|
extras = existingExtras ?? [];
|
|
2380
2467
|
startMarker = existingStart ?? null;
|
|
2468
|
+
scopeComments = existingScopeComments ?? null;
|
|
2381
2469
|
} else {
|
|
2382
2470
|
const stashed = primaryEl.__bfExtras;
|
|
2383
2471
|
if (stashed && stashed.length > 0) {
|
|
@@ -2385,15 +2473,19 @@ function createItemScope(item, index, renderItem, existingPrimary, existingExtra
|
|
|
2385
2473
|
startMarker = document.createComment(BF_LOOP_ITEM);
|
|
2386
2474
|
}
|
|
2387
2475
|
delete primaryEl.__bfExtras;
|
|
2476
|
+
const stashedScopeComments = primaryEl.__bfScopeComments;
|
|
2477
|
+
if (stashedScopeComments)
|
|
2478
|
+
scopeComments = stashedScopeComments;
|
|
2479
|
+
delete primaryEl.__bfScopeComments;
|
|
2388
2480
|
}
|
|
2389
2481
|
return;
|
|
2390
2482
|
});
|
|
2391
2483
|
if (rowMount && !existingPrimary && extras.length > 0 && primaryEl.parentNode) {
|
|
2392
2484
|
primaryEl.remove();
|
|
2393
2485
|
}
|
|
2394
|
-
return { startMarker, primaryEl, extras, dispose, setItem };
|
|
2486
|
+
return { startMarker, primaryEl, extras, scopeComments, dispose, setItem };
|
|
2395
2487
|
}
|
|
2396
|
-
function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
|
|
2488
|
+
function mapArray(accessor, container, getKey, renderItem, markerId, bfId, keyAttrName2 = BF_KEY) {
|
|
2397
2489
|
if (!container)
|
|
2398
2490
|
return;
|
|
2399
2491
|
const scopes = new Map;
|
|
@@ -2417,24 +2509,26 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
|
|
|
2417
2509
|
const anchor = endMarker ?? null;
|
|
2418
2510
|
if (!hydrated) {
|
|
2419
2511
|
hydrated = true;
|
|
2420
|
-
const existingRanges = startMarker ? findItemRanges(startMarker, endMarker) : Array.from(container.children).map((el) => ({ startMarker: null, primaryEl: el, extras: [] }));
|
|
2421
|
-
const needsHydration = existingRanges.length > 0
|
|
2512
|
+
const existingRanges = startMarker ? findItemRanges(startMarker, endMarker) : Array.from(container.children).map((el) => ({ startMarker: null, primaryEl: el, extras: [], scopeComments: null }));
|
|
2513
|
+
const needsHydration = existingRanges.length > 0;
|
|
2422
2514
|
if (needsHydration) {
|
|
2423
2515
|
for (let i2 = 0;i2 < existingRanges.length && i2 < items.length; i2++) {
|
|
2424
2516
|
const range = existingRanges[i2];
|
|
2425
2517
|
const item = items[i2];
|
|
2426
2518
|
const key = getKey ? getKey(item, i2) : String(i2);
|
|
2427
|
-
range.primaryEl.
|
|
2428
|
-
|
|
2519
|
+
if (getKey && !range.primaryEl.getAttribute(keyAttrName2)) {
|
|
2520
|
+
range.primaryEl.setAttribute(keyAttrName2, key);
|
|
2521
|
+
}
|
|
2522
|
+
const scope = createItemScope(item, i2, renderItem, range.primaryEl, range.extras, range.startMarker, range.scopeComments);
|
|
2429
2523
|
scopes.set(key, scope);
|
|
2430
2524
|
hydratedScopes.add(range.primaryEl);
|
|
2431
2525
|
}
|
|
2432
2526
|
for (let i2 = existingRanges.length;i2 < items.length; i2++) {
|
|
2433
2527
|
const item = items[i2];
|
|
2434
2528
|
const key = getKey ? getKey(item, i2) : String(i2);
|
|
2435
|
-
const scope = createItemScope(item, i2, renderItem, undefined, undefined, undefined, { container, anchor });
|
|
2436
|
-
if (!scope.primaryEl.
|
|
2437
|
-
scope.primaryEl.setAttribute(
|
|
2529
|
+
const scope = createItemScope(item, i2, renderItem, undefined, undefined, undefined, undefined, { container, anchor });
|
|
2530
|
+
if (getKey && !scope.primaryEl.getAttribute(keyAttrName2))
|
|
2531
|
+
scope.primaryEl.setAttribute(keyAttrName2, key);
|
|
2438
2532
|
scopes.set(key, scope);
|
|
2439
2533
|
insertScope(scope, container, anchor);
|
|
2440
2534
|
}
|
|
@@ -2442,8 +2536,12 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
|
|
|
2442
2536
|
const range = existingRanges[i2];
|
|
2443
2537
|
if (range.startMarker?.parentNode)
|
|
2444
2538
|
range.startMarker.remove();
|
|
2539
|
+
if (range.scopeComments?.start.parentNode)
|
|
2540
|
+
range.scopeComments.start.remove();
|
|
2445
2541
|
if (range.primaryEl.parentNode)
|
|
2446
2542
|
range.primaryEl.remove();
|
|
2543
|
+
if (range.scopeComments?.end.parentNode)
|
|
2544
|
+
range.scopeComments.end.remove();
|
|
2447
2545
|
for (const ex of range.extras) {
|
|
2448
2546
|
if (ex.parentNode)
|
|
2449
2547
|
ex.remove();
|
|
@@ -2453,14 +2551,15 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
|
|
|
2453
2551
|
}
|
|
2454
2552
|
}
|
|
2455
2553
|
if (scopes.size === 0) {
|
|
2456
|
-
const loopRanges = startMarker ? findItemRanges(startMarker, endMarker) : Array.from(container.children).map((el) => ({ startMarker: null, primaryEl: el, extras: [] }));
|
|
2554
|
+
const loopRanges = startMarker ? findItemRanges(startMarker, endMarker) : Array.from(container.children).map((el) => ({ startMarker: null, primaryEl: el, extras: [], scopeComments: null }));
|
|
2457
2555
|
for (const range of loopRanges) {
|
|
2458
|
-
const existingKey = range.primaryEl.
|
|
2556
|
+
const existingKey = range.primaryEl.getAttribute(keyAttrName2);
|
|
2459
2557
|
if (existingKey && !scopes.has(existingKey)) {
|
|
2460
2558
|
scopes.set(existingKey, {
|
|
2461
2559
|
startMarker: range.startMarker,
|
|
2462
2560
|
primaryEl: range.primaryEl,
|
|
2463
2561
|
extras: range.extras,
|
|
2562
|
+
scopeComments: range.scopeComments,
|
|
2464
2563
|
dispose: () => {},
|
|
2465
2564
|
setItem: () => {}
|
|
2466
2565
|
});
|
|
@@ -2479,7 +2578,7 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
|
|
|
2479
2578
|
} else {
|
|
2480
2579
|
let expectedNodeCount = 0;
|
|
2481
2580
|
for (const scope of scopes.values()) {
|
|
2482
|
-
expectedNodeCount += 1 + scope.extras.length + (scope.startMarker ? 1 : 0);
|
|
2581
|
+
expectedNodeCount += 1 + scope.extras.length + (scope.startMarker ? 1 : 0) + (scope.scopeComments ? 2 : 0);
|
|
2483
2582
|
}
|
|
2484
2583
|
let actualNodeCount = 0;
|
|
2485
2584
|
for (let node = container.firstChild;node; node = node.nextSibling)
|
|
@@ -2511,9 +2610,9 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
|
|
|
2511
2610
|
existing.setItem(item);
|
|
2512
2611
|
desiredOrder.push(existing);
|
|
2513
2612
|
} else {
|
|
2514
|
-
const scope = createItemScope(item, i2, renderItem, undefined, undefined, undefined, { container, anchor });
|
|
2515
|
-
if (!scope.primaryEl.
|
|
2516
|
-
scope.primaryEl.setAttribute(
|
|
2613
|
+
const scope = createItemScope(item, i2, renderItem, undefined, undefined, undefined, undefined, { container, anchor });
|
|
2614
|
+
if (getKey && !scope.primaryEl.getAttribute(keyAttrName2))
|
|
2615
|
+
scope.primaryEl.setAttribute(keyAttrName2, key);
|
|
2517
2616
|
scopes.set(key, scope);
|
|
2518
2617
|
desiredOrder.push(scope);
|
|
2519
2618
|
}
|
|
@@ -2550,7 +2649,7 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
|
|
|
2550
2649
|
let j = i;
|
|
2551
2650
|
while (j < desiredOrder.length && !stationary[j])
|
|
2552
2651
|
j++;
|
|
2553
|
-
const before = j < desiredOrder.length ? desiredOrder[j].startMarker ?? desiredOrder[j].primaryEl : anchor;
|
|
2652
|
+
const before = j < desiredOrder.length ? desiredOrder[j].startMarker ?? desiredOrder[j].scopeComments?.start ?? desiredOrder[j].primaryEl : anchor;
|
|
2554
2653
|
if (j - i === 1) {
|
|
2555
2654
|
insertScope(desiredOrder[i], container, before);
|
|
2556
2655
|
} else {
|
|
@@ -2708,7 +2807,7 @@ function mapArrayAnchored(accessor, container, getKey, renderItem, markerId, bfI
|
|
|
2708
2807
|
}, bfId);
|
|
2709
2808
|
}
|
|
2710
2809
|
// src/runtime/map-array-lazy.ts
|
|
2711
|
-
function mapArrayLazy(accessor, container, getKey, plan, markerId, bfId) {
|
|
2810
|
+
function mapArrayLazy(accessor, container, getKey, plan, markerId, bfId, keyAttrName2 = BF_KEY) {
|
|
2712
2811
|
if (!container)
|
|
2713
2812
|
return;
|
|
2714
2813
|
const entries = new Map;
|
|
@@ -2747,8 +2846,8 @@ function mapArrayLazy(accessor, container, getKey, plan, markerId, bfId) {
|
|
|
2747
2846
|
last: null
|
|
2748
2847
|
};
|
|
2749
2848
|
entry.primaryEl = untrack(() => plan.createRow(entry, index));
|
|
2750
|
-
if (!entry.primaryEl.
|
|
2751
|
-
entry.primaryEl.setAttribute(
|
|
2849
|
+
if (getKey && !entry.primaryEl.getAttribute(keyAttrName2))
|
|
2850
|
+
entry.primaryEl.setAttribute(keyAttrName2, key);
|
|
2752
2851
|
markStranded();
|
|
2753
2852
|
return entry;
|
|
2754
2853
|
};
|
|
@@ -2770,7 +2869,7 @@ function mapArrayLazy(accessor, container, getKey, plan, markerId, bfId) {
|
|
|
2770
2869
|
const shared = Math.min(doms.length, items.length);
|
|
2771
2870
|
for (let i2 = 0;i2 < shared; i2++) {
|
|
2772
2871
|
const el = doms[i2];
|
|
2773
|
-
const ssrKey = el.getAttribute(
|
|
2872
|
+
const ssrKey = el.getAttribute(keyAttrName2);
|
|
2774
2873
|
const key = ssrKey !== null ? ssrKey : getKey ? getKey(items[i2], i2) : String(i2);
|
|
2775
2874
|
const entry = { key, primaryEl: el, item: items[i2], refs: null, last: null };
|
|
2776
2875
|
entries.set(key, entry);
|
|
@@ -3712,6 +3811,7 @@ export {
|
|
|
3712
3811
|
onMount,
|
|
3713
3812
|
onCleanup,
|
|
3714
3813
|
mountRowRoot,
|
|
3814
|
+
markupOrEmpty,
|
|
3715
3815
|
mapArrayLazy,
|
|
3716
3816
|
mapArrayAnchored,
|
|
3717
3817
|
mapArray,
|
package/dist/runtime/types.d.ts
CHANGED
|
@@ -20,7 +20,25 @@ export interface ComponentDef {
|
|
|
20
20
|
init: InitFn;
|
|
21
21
|
/** Template function for client-side component creation */
|
|
22
22
|
template?: (props: Record<string, unknown>) => string;
|
|
23
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* When true, this component's scope has no `bf-s`-carrying element of
|
|
25
|
+
* its own — a proxy element stands in for it. Set for TWO distinct
|
|
26
|
+
* shapes (see `fragmentRoot` below, which tells them apart):
|
|
27
|
+
* - a genuine fragment root (`<>...</>`), where the proxy is the
|
|
28
|
+
* fragment's own rendered content;
|
|
29
|
+
* - a root that is itself a single child component call, where the
|
|
30
|
+
* proxy is that child's own already-scoped element (#2649).
|
|
31
|
+
*/
|
|
24
32
|
comment?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* True only for the genuine-fragment-root shape of `comment` above
|
|
35
|
+
* (`ir.root.type === 'fragment'`) — never for the root-is-a-child-call
|
|
36
|
+
* shape. `materializeComponent` (component.ts) uses this to decide
|
|
37
|
+
* whether a CSR mount must generate its OWN scope id (fragment root: yes,
|
|
38
|
+
* so nested `renderChild()` calls get parent-prefixed naming matching
|
|
39
|
+
* SSR/hydrate) or leave the scope id null to avoid overwriting the
|
|
40
|
+
* child's own (#2649's shape, #2722).
|
|
41
|
+
*/
|
|
42
|
+
fragmentRoot?: boolean;
|
|
25
43
|
}
|
|
26
44
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;AAE7E;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAA;IACZ,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAA;IACrD
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;AAE7E;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAA;IACZ,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAA;IACrD;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/client",
|
|
3
|
-
"version": "0.33.
|
|
3
|
+
"version": "0.33.3",
|
|
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.33.
|
|
58
|
+
"@barefootjs/shared": "0.33.3"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
61
|
"@barefootjs/jsx": ">=0.2.0"
|