@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.
@@ -1330,8 +1330,7 @@ function hydrateCommentScope(comment) {
1330
1330
  if (hydratedScopes.has(proxyEl))
1331
1331
  return;
1332
1332
  commentScopeRegistry.set(proxyEl, { commentNode: comment, scopeId });
1333
- const parsed = parseProps(propsJson || null, `comment scope ${scopeId}`);
1334
- const props = parsed[name] ?? {};
1333
+ const props = parseProps(propsJson || null, `comment scope ${scopeId}`);
1335
1334
  runInit(proxyEl, def, props);
1336
1335
  }
1337
1336
  function nextElementSibling2(node) {
@@ -1369,25 +1368,25 @@ function mountRowRoot(el) {
1369
1368
  }
1370
1369
  return el;
1371
1370
  }
1372
- function createComponent(nameOrDef, props = {}, key, slot, mountAt) {
1373
- const element = materializeComponent(nameOrDef, props, key, slot, mountAt);
1371
+ function createComponent(nameOrDef, props = {}, key, slot, mountAt, keyAttrName2 = BF_KEY) {
1372
+ const element = materializeComponent(nameOrDef, props, key, slot, mountAt, keyAttrName2);
1374
1373
  if (mountAt && mountAt.parentNode && element !== mountAt) {
1375
1374
  mountAt.replaceWith(element);
1376
1375
  }
1377
1376
  return element;
1378
1377
  }
1379
- function materializeComponent(nameOrDef, props = {}, key, slot, mountAt) {
1378
+ function materializeComponent(nameOrDef, props = {}, key, slot, mountAt, keyAttrName2 = BF_KEY) {
1380
1379
  if (props == null)
1381
1380
  props = {};
1382
1381
  const rowMount = mountAt ? null : takeRowMountPoint();
1383
1382
  if (typeof nameOrDef !== "string") {
1384
- return createComponentFromDef(nameOrDef, props, key, mountAt, rowMount);
1383
+ return createComponentFromDef(nameOrDef, props, key, mountAt, rowMount, keyAttrName2);
1385
1384
  }
1386
1385
  const name = nameOrDef;
1387
1386
  const templateFn = getTemplate(name);
1388
1387
  if (!templateFn) {
1389
1388
  console.warn(`[BarefootJS] Template not found for component: ${name}`);
1390
- return createPlaceholder(name, key);
1389
+ return createPlaceholder(name, key, keyAttrName2);
1391
1390
  }
1392
1391
  const childrenDescriptor = Object.getOwnPropertyDescriptor(props, "children");
1393
1392
  const childrenIsGetter = childrenDescriptor != null && typeof childrenDescriptor.get === "function";
@@ -1412,13 +1411,16 @@ function materializeComponent(nameOrDef, props = {}, key, slot, mountAt) {
1412
1411
  });
1413
1412
  const def = getRegisteredDef(name);
1414
1413
  const isCommentWrapper = def?.comment === true;
1414
+ const isFragmentRoot = def?.fragmentRoot === true;
1415
1415
  const derivedScopeId = slot?.parent && slot.mount ? `${slot.parent}_${slot.mount}` : null;
1416
- const scopeId = isCommentWrapper ? null : derivedScopeId ?? `${def?.name ?? name}_${generateId()}`;
1416
+ const scopeId = isCommentWrapper && !isFragmentRoot ? null : derivedScopeId ?? `${def?.name ?? name}_${generateId()}`;
1417
1417
  const prevParentScopeId = _parentScopeId;
1418
1418
  if (scopeId) {
1419
1419
  _parentScopeId = scopeId;
1420
1420
  } else if (slot?.parent) {
1421
1421
  _parentScopeId = slot.parent;
1422
+ } else if (!_parentScopeId) {
1423
+ _parentScopeId = `${def?.name ?? name}_${generateId()}`;
1422
1424
  }
1423
1425
  let html;
1424
1426
  try {
@@ -1426,12 +1428,18 @@ function materializeComponent(nameOrDef, props = {}, key, slot, mountAt) {
1426
1428
  } finally {
1427
1429
  _parentScopeId = prevParentScopeId;
1428
1430
  }
1429
- const element = parseHTML(html.trim()).firstChild;
1431
+ const parsedFragment = parseHTML(html.trim());
1432
+ const roots = isFragmentRoot ? Array.from(parsedFragment.childNodes) : parsedFragment.firstChild ? [parsedFragment.firstChild] : [];
1433
+ const element = isFragmentRoot ? roots.find((node) => node.nodeType === Node.ELEMENT_NODE) : roots[0];
1434
+ if (isFragmentRoot && roots.length > 0 && !element) {
1435
+ 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.");
1436
+ return createPlaceholder(name, key, keyAttrName2);
1437
+ }
1430
1438
  if (!element) {
1431
1439
  console.warn(`[BarefootJS] Template returned empty HTML for component: ${name}`);
1432
- return createPlaceholder(name, key);
1440
+ return createPlaceholder(name, key, keyAttrName2);
1433
1441
  }
1434
- if (scopeId) {
1442
+ if (scopeId && !isFragmentRoot) {
1435
1443
  element.setAttribute(BF_SCOPE, scopeId);
1436
1444
  }
1437
1445
  if (slot) {
@@ -1440,13 +1448,38 @@ function materializeComponent(nameOrDef, props = {}, key, slot, mountAt) {
1440
1448
  element.setAttribute(BF_AT, slot.mount);
1441
1449
  }
1442
1450
  if (key !== undefined) {
1443
- element.setAttribute(BF_KEY, String(key));
1451
+ element.setAttribute(keyAttrName2, String(key));
1452
+ }
1453
+ const fragmentComments = isFragmentRoot && scopeId ? {
1454
+ start: document.createComment(`${BF_SCOPE_COMMENT_PREFIX}${scopeId}`),
1455
+ end: document.createComment(`${BF_SCOPE_COMMENT_END_PREFIX}${scopeId}`)
1456
+ } : null;
1457
+ if (fragmentComments) {
1458
+ commentScopeRegistry.set(element, { commentNode: fragmentComments.start, scopeId });
1444
1459
  }
1445
1460
  const rootIsDeferredPlaceholder = element.hasAttribute(BF_PLACEHOLDER);
1461
+ let bareFragment = null;
1446
1462
  if (mountAt && !rootIsDeferredPlaceholder) {
1447
- mountAt.replaceWith(element);
1463
+ if (fragmentComments) {
1464
+ mountAt.replaceWith(fragmentComments.start, ...roots, fragmentComments.end);
1465
+ } else {
1466
+ mountAt.replaceWith(element);
1467
+ }
1448
1468
  } else if (rowMount && !rootIsDeferredPlaceholder) {
1449
- rowMount.container.insertBefore(element, rowMount.anchor);
1469
+ if (fragmentComments) {
1470
+ rowMount.container.insertBefore(fragmentComments.start, rowMount.anchor);
1471
+ rowMount.container.insertBefore(element, rowMount.anchor);
1472
+ rowMount.container.insertBefore(fragmentComments.end, rowMount.anchor);
1473
+ element.__bfScopeComments = fragmentComments;
1474
+ if (roots.length > 1) {
1475
+ 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");
1476
+ }
1477
+ } else {
1478
+ rowMount.container.insertBefore(element, rowMount.anchor);
1479
+ }
1480
+ } else if (fragmentComments && !rootIsDeferredPlaceholder) {
1481
+ bareFragment = document.createDocumentFragment();
1482
+ bareFragment.append(fragmentComments.start, ...roots, fragmentComments.end);
1450
1483
  }
1451
1484
  const prevScope = setCurrentScope(element);
1452
1485
  let placeholderWrapper = null;
@@ -1474,18 +1507,30 @@ function materializeComponent(nameOrDef, props = {}, key, slot, mountAt) {
1474
1507
  }
1475
1508
  setCurrentScope(prevScope);
1476
1509
  hydratedScopes.add(element);
1477
- return element;
1510
+ return bareFragment ?? element;
1511
+ }
1512
+ var FIRST_TAG_PATTERN = /<([a-zA-Z][^\s/>]*)/;
1513
+ var TAG_HEAD_PATTERN = /^(<[a-zA-Z][^\s/>]*)/;
1514
+ function spliceAttrsAfterFirstTag(html, attrs) {
1515
+ const firstElMatch = html.match(FIRST_TAG_PATTERN);
1516
+ if (!firstElMatch)
1517
+ return html;
1518
+ const insertPos = firstElMatch.index;
1519
+ return html.slice(0, insertPos) + html.slice(insertPos).replace(TAG_HEAD_PATTERN, `$1${attrs}`);
1478
1520
  }
1479
1521
  function renderChild(name, props, key, slotSuffix) {
1480
1522
  const templateFn = getTemplate(name);
1481
1523
  const suffix = slotSuffix ? `_${slotSuffix}` : "";
1482
- const displayName = getRegisteredDef(name)?.name ?? name;
1524
+ const def = getRegisteredDef(name);
1525
+ const displayName = def?.name ?? name;
1526
+ const isFragmentRoot = def?.fragmentRoot === true;
1483
1527
  const scopePrefix = _parentScopeId && slotSuffix ? _parentScopeId : `${displayName}_${generateId()}`;
1528
+ const scopeId = `${scopePrefix}${suffix}`;
1484
1529
  const keyAttr = key !== undefined ? ` ${BF_KEY}="${key}"` : "";
1485
1530
  const slotAttrs = _parentScopeId && slotSuffix ? ` ${BF_HOST}="${_parentScopeId}" ${BF_AT}="${slotSuffix}"` : "";
1486
- const bfsAttr = `${BF_SCOPE}="${scopePrefix}${suffix}"`;
1531
+ const bfsAttr = `${BF_SCOPE}="${scopeId}"`;
1487
1532
  if (!templateFn) {
1488
- return `<div ${bfsAttr}${slotAttrs}${keyAttr}></div>`;
1533
+ return isFragmentRoot ? `<!--${BF_SCOPE_COMMENT_PREFIX}${scopeId}--><div></div><!--${BF_SCOPE_COMMENT_END_PREFIX}${scopeId}-->` : `<div ${bfsAttr}${slotAttrs}${keyAttr}></div>`;
1489
1534
  }
1490
1535
  const prevParentScopeId = _parentScopeId;
1491
1536
  _parentScopeId = `${scopePrefix}${suffix}`;
@@ -1496,7 +1541,12 @@ function renderChild(name, props, key, slotSuffix) {
1496
1541
  _parentScopeId = prevParentScopeId;
1497
1542
  }
1498
1543
  let html = raw.trim().replace(PLACEHOLDER_ATTR_PATTERN, _parentScopeId ? ` bf-s="${_parentScopeId}"` : "");
1499
- const firstElMatch = html.match(/<(\w+)/);
1544
+ if (isFragmentRoot) {
1545
+ const hostSuffix = _parentScopeId && slotSuffix ? `|h=${_parentScopeId}|m=${slotSuffix}` : "";
1546
+ const keyedHtml = keyAttr ? spliceAttrsAfterFirstTag(html, keyAttr) : html;
1547
+ return `<!--${BF_SCOPE_COMMENT_PREFIX}${scopeId}${hostSuffix}-->${keyedHtml}<!--${BF_SCOPE_COMMENT_END_PREFIX}${scopeId}-->`;
1548
+ }
1549
+ const firstElMatch = html.match(FIRST_TAG_PATTERN);
1500
1550
  if (!firstElMatch)
1501
1551
  return html;
1502
1552
  const insertPos = firstElMatch.index;
@@ -1505,20 +1555,20 @@ function renderChild(name, props, key, slotSuffix) {
1505
1555
  if (ROOT_HAS_BFS_PATTERN.test(afterInsert)) {
1506
1556
  if (!extraAttrs)
1507
1557
  return html;
1508
- return html.slice(0, insertPos) + afterInsert.replace(/^(<\w+)/, `$1${extraAttrs}`);
1558
+ return html.slice(0, insertPos) + afterInsert.replace(TAG_HEAD_PATTERN, `$1${extraAttrs}`);
1509
1559
  }
1510
- return html.slice(0, insertPos) + afterInsert.replace(/^(<\w+)/, `$1 ${bfsAttr}${extraAttrs}`);
1560
+ return html.slice(0, insertPos) + afterInsert.replace(TAG_HEAD_PATTERN, `$1 ${bfsAttr}${extraAttrs}`);
1511
1561
  }
1512
1562
  var PLACEHOLDER_ATTR_PATTERN = new RegExp(`\\s+bf-s="${BF_PARENT_SCOPE_PLACEHOLDER}"`, "g");
1513
1563
  var ROOT_HAS_BFS_PATTERN = /^<\w+[^>]*\sbf-s="/;
1514
1564
  function generateId() {
1515
1565
  return Math.random().toString(36).slice(2, 8);
1516
1566
  }
1517
- function createPlaceholder(name, key) {
1567
+ function createPlaceholder(name, key, keyAttrName2 = BF_KEY) {
1518
1568
  const el = document.createElement("div");
1519
1569
  el.setAttribute(BF_SCOPE, `${name}_placeholder`);
1520
1570
  if (key !== undefined) {
1521
- el.setAttribute(BF_KEY, String(key));
1571
+ el.setAttribute(keyAttrName2, String(key));
1522
1572
  }
1523
1573
  el.textContent = `[${name}]`;
1524
1574
  el.style.cssText = "color: red; border: 1px dashed red; padding: 4px;";
@@ -1567,6 +1617,9 @@ function escapeTextOrMarkup(value) {
1567
1617
  return value[BF_MARKUP_BRAND];
1568
1618
  return escapeText(value);
1569
1619
  }
1620
+ function markupOrEmpty(value) {
1621
+ return value == null ? "" : value;
1622
+ }
1570
1623
  function escapeTextOrNode(value) {
1571
1624
  if (isBfMarkup(value))
1572
1625
  return value[BF_MARKUP_BRAND];
@@ -1628,7 +1681,7 @@ function insertGetterChildren(element, children) {
1628
1681
  element.appendChild(document.createTextNode(String(children)));
1629
1682
  }
1630
1683
  }
1631
- function createComponentFromDef(def, props, key, mountAt, rowMount) {
1684
+ function createComponentFromDef(def, props, key, mountAt, rowMount, keyAttrName2 = BF_KEY) {
1632
1685
  if (!def.template) {
1633
1686
  throw new Error("[BarefootJS] createComponent with ComponentDef requires a template function");
1634
1687
  }
@@ -1645,7 +1698,7 @@ function createComponentFromDef(def, props, key, mountAt, rowMount) {
1645
1698
  const scopeId = `${name}_${generateId()}`;
1646
1699
  element.setAttribute(BF_SCOPE, scopeId);
1647
1700
  if (key !== undefined) {
1648
- element.setAttribute(BF_KEY, String(key));
1701
+ element.setAttribute(keyAttrName2, String(key));
1649
1702
  }
1650
1703
  if (mountAt) {
1651
1704
  mountAt.replaceWith(element);
@@ -1838,6 +1891,11 @@ function upsertChildItem(primaryEl, name, slotId, props, key, anchorScope) {
1838
1891
  }
1839
1892
  // src/runtime/map-array.ts
1840
1893
  import { createSignal, createEffect, createRoot as createRoot2 } from "@barefootjs/client/reactive";
1894
+ function scopeIdOf(start) {
1895
+ const rest = (start.nodeValue ?? "").slice(BF_SCOPE_COMMENT_PREFIX.length);
1896
+ const pipe = rest.indexOf("|");
1897
+ return pipe >= 0 ? rest.slice(0, pipe) : rest;
1898
+ }
1841
1899
  function findLoopMarkers2(container, markerId) {
1842
1900
  let start = null;
1843
1901
  let end = null;
@@ -1875,31 +1933,55 @@ function findItemRanges(start, end) {
1875
1933
  const ranges = [];
1876
1934
  let current = null;
1877
1935
  let sawItemMarker = false;
1936
+ let pendingScopeStart = null;
1937
+ let openScopeComments = null;
1878
1938
  let node = start.nextSibling;
1879
1939
  while (node && node !== end) {
1880
- if (node.nodeType === Node.COMMENT_NODE && node.nodeValue === BF_LOOP_ITEM) {
1881
- sawItemMarker = true;
1882
- current = { startMarker: node, primaryEl: null, extras: [] };
1883
- ranges.push(current);
1940
+ if (node.nodeType === Node.COMMENT_NODE) {
1941
+ const value = node.nodeValue ?? "";
1942
+ if (value === BF_LOOP_ITEM) {
1943
+ sawItemMarker = true;
1944
+ current = { startMarker: node, primaryEl: null, extras: [], scopeComments: null };
1945
+ ranges.push(current);
1946
+ } else if (value.startsWith(BF_SCOPE_COMMENT_PREFIX)) {
1947
+ pendingScopeStart = node;
1948
+ } else if (openScopeComments && value === BF_SCOPE_COMMENT_END_PREFIX + scopeIdOf(openScopeComments.start)) {
1949
+ openScopeComments.end = node;
1950
+ openScopeComments = null;
1951
+ }
1884
1952
  } else if (node.nodeType === Node.ELEMENT_NODE) {
1885
1953
  const el = node;
1954
+ let scopeComments = null;
1955
+ if (pendingScopeStart) {
1956
+ scopeComments = { start: pendingScopeStart, end: null };
1957
+ openScopeComments = scopeComments;
1958
+ pendingScopeStart = null;
1959
+ }
1886
1960
  if (sawItemMarker) {
1887
- if (!current.primaryEl)
1961
+ if (!current.primaryEl) {
1888
1962
  current.primaryEl = el;
1889
- else
1963
+ current.scopeComments = scopeComments;
1964
+ } else
1890
1965
  current.extras.push(el);
1891
1966
  } else {
1892
- ranges.push({ startMarker: null, primaryEl: el, extras: [] });
1967
+ ranges.push({ startMarker: null, primaryEl: el, extras: [], scopeComments });
1893
1968
  }
1894
1969
  }
1895
1970
  node = node.nextSibling;
1896
1971
  }
1897
- return ranges.filter((r) => r.primaryEl !== null);
1972
+ return ranges.filter((r) => r.primaryEl !== null).map((r) => ({
1973
+ ...r,
1974
+ scopeComments: r.scopeComments?.end ? r.scopeComments : null
1975
+ }));
1898
1976
  }
1899
1977
  function insertScope(scope, target, anchor) {
1900
1978
  if (scope.startMarker)
1901
1979
  target.insertBefore(scope.startMarker, anchor);
1980
+ if (scope.scopeComments)
1981
+ target.insertBefore(scope.scopeComments.start, anchor);
1902
1982
  target.insertBefore(scope.primaryEl, anchor);
1983
+ if (scope.scopeComments)
1984
+ target.insertBefore(scope.scopeComments.end, anchor);
1903
1985
  for (const ex of scope.extras)
1904
1986
  target.insertBefore(ex, anchor);
1905
1987
  }
@@ -1938,19 +2020,24 @@ function longestIncreasingSubsequenceIndices(arr) {
1938
2020
  function removeScope(scope) {
1939
2021
  if (scope.startMarker?.parentNode)
1940
2022
  scope.startMarker.remove();
2023
+ if (scope.scopeComments?.start.parentNode)
2024
+ scope.scopeComments.start.remove();
1941
2025
  if (scope.primaryEl.parentNode)
1942
2026
  scope.primaryEl.remove();
2027
+ if (scope.scopeComments?.end.parentNode)
2028
+ scope.scopeComments.end.remove();
1943
2029
  for (const ex of scope.extras) {
1944
2030
  if (ex.parentNode)
1945
2031
  ex.remove();
1946
2032
  }
1947
2033
  }
1948
- function createItemScope(item, index, renderItem, existingPrimary, existingExtras, existingStart, rowMount) {
2034
+ function createItemScope(item, index, renderItem, existingPrimary, existingExtras, existingStart, existingScopeComments, rowMount) {
1949
2035
  let primaryEl;
1950
2036
  let dispose;
1951
2037
  let setItem;
1952
2038
  let extras = [];
1953
2039
  let startMarker = null;
2040
+ let scopeComments = null;
1954
2041
  createRoot2((d) => {
1955
2042
  dispose = d;
1956
2043
  const [itemAccessor, itemSetter] = createSignal(item);
@@ -1973,6 +2060,7 @@ function createItemScope(item, index, renderItem, existingPrimary, existingExtra
1973
2060
  if (existingPrimary) {
1974
2061
  extras = existingExtras ?? [];
1975
2062
  startMarker = existingStart ?? null;
2063
+ scopeComments = existingScopeComments ?? null;
1976
2064
  } else {
1977
2065
  const stashed = primaryEl.__bfExtras;
1978
2066
  if (stashed && stashed.length > 0) {
@@ -1980,15 +2068,19 @@ function createItemScope(item, index, renderItem, existingPrimary, existingExtra
1980
2068
  startMarker = document.createComment(BF_LOOP_ITEM);
1981
2069
  }
1982
2070
  delete primaryEl.__bfExtras;
2071
+ const stashedScopeComments = primaryEl.__bfScopeComments;
2072
+ if (stashedScopeComments)
2073
+ scopeComments = stashedScopeComments;
2074
+ delete primaryEl.__bfScopeComments;
1983
2075
  }
1984
2076
  return;
1985
2077
  });
1986
2078
  if (rowMount && !existingPrimary && extras.length > 0 && primaryEl.parentNode) {
1987
2079
  primaryEl.remove();
1988
2080
  }
1989
- return { startMarker, primaryEl, extras, dispose, setItem };
2081
+ return { startMarker, primaryEl, extras, scopeComments, dispose, setItem };
1990
2082
  }
1991
- function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
2083
+ function mapArray(accessor, container, getKey, renderItem, markerId, bfId, keyAttrName2 = BF_KEY) {
1992
2084
  if (!container)
1993
2085
  return;
1994
2086
  const scopes = new Map;
@@ -2012,24 +2104,26 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
2012
2104
  const anchor = endMarker ?? null;
2013
2105
  if (!hydrated) {
2014
2106
  hydrated = true;
2015
- const existingRanges = startMarker ? findItemRanges(startMarker, endMarker) : Array.from(container.children).map((el) => ({ startMarker: null, primaryEl: el, extras: [] }));
2016
- const needsHydration = existingRanges.length > 0 && (!existingRanges[0]?.primaryEl.hasAttribute("data-key") || scopes.size === 0);
2107
+ const existingRanges = startMarker ? findItemRanges(startMarker, endMarker) : Array.from(container.children).map((el) => ({ startMarker: null, primaryEl: el, extras: [], scopeComments: null }));
2108
+ const needsHydration = existingRanges.length > 0;
2017
2109
  if (needsHydration) {
2018
2110
  for (let i2 = 0;i2 < existingRanges.length && i2 < items.length; i2++) {
2019
2111
  const range = existingRanges[i2];
2020
2112
  const item = items[i2];
2021
2113
  const key = getKey ? getKey(item, i2) : String(i2);
2022
- range.primaryEl.setAttribute(BF_KEY, key);
2023
- const scope = createItemScope(item, i2, renderItem, range.primaryEl, range.extras, range.startMarker);
2114
+ if (getKey && !range.primaryEl.getAttribute(keyAttrName2)) {
2115
+ range.primaryEl.setAttribute(keyAttrName2, key);
2116
+ }
2117
+ const scope = createItemScope(item, i2, renderItem, range.primaryEl, range.extras, range.startMarker, range.scopeComments);
2024
2118
  scopes.set(key, scope);
2025
2119
  hydratedScopes.add(range.primaryEl);
2026
2120
  }
2027
2121
  for (let i2 = existingRanges.length;i2 < items.length; i2++) {
2028
2122
  const item = items[i2];
2029
2123
  const key = getKey ? getKey(item, i2) : String(i2);
2030
- const scope = createItemScope(item, i2, renderItem, undefined, undefined, undefined, { container, anchor });
2031
- if (!scope.primaryEl.dataset.key)
2032
- scope.primaryEl.setAttribute(BF_KEY, key);
2124
+ const scope = createItemScope(item, i2, renderItem, undefined, undefined, undefined, undefined, { container, anchor });
2125
+ if (getKey && !scope.primaryEl.getAttribute(keyAttrName2))
2126
+ scope.primaryEl.setAttribute(keyAttrName2, key);
2033
2127
  scopes.set(key, scope);
2034
2128
  insertScope(scope, container, anchor);
2035
2129
  }
@@ -2037,8 +2131,12 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
2037
2131
  const range = existingRanges[i2];
2038
2132
  if (range.startMarker?.parentNode)
2039
2133
  range.startMarker.remove();
2134
+ if (range.scopeComments?.start.parentNode)
2135
+ range.scopeComments.start.remove();
2040
2136
  if (range.primaryEl.parentNode)
2041
2137
  range.primaryEl.remove();
2138
+ if (range.scopeComments?.end.parentNode)
2139
+ range.scopeComments.end.remove();
2042
2140
  for (const ex of range.extras) {
2043
2141
  if (ex.parentNode)
2044
2142
  ex.remove();
@@ -2048,14 +2146,15 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
2048
2146
  }
2049
2147
  }
2050
2148
  if (scopes.size === 0) {
2051
- const loopRanges = startMarker ? findItemRanges(startMarker, endMarker) : Array.from(container.children).map((el) => ({ startMarker: null, primaryEl: el, extras: [] }));
2149
+ const loopRanges = startMarker ? findItemRanges(startMarker, endMarker) : Array.from(container.children).map((el) => ({ startMarker: null, primaryEl: el, extras: [], scopeComments: null }));
2052
2150
  for (const range of loopRanges) {
2053
- const existingKey = range.primaryEl.dataset?.key;
2151
+ const existingKey = range.primaryEl.getAttribute(keyAttrName2);
2054
2152
  if (existingKey && !scopes.has(existingKey)) {
2055
2153
  scopes.set(existingKey, {
2056
2154
  startMarker: range.startMarker,
2057
2155
  primaryEl: range.primaryEl,
2058
2156
  extras: range.extras,
2157
+ scopeComments: range.scopeComments,
2059
2158
  dispose: () => {},
2060
2159
  setItem: () => {}
2061
2160
  });
@@ -2074,7 +2173,7 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
2074
2173
  } else {
2075
2174
  let expectedNodeCount = 0;
2076
2175
  for (const scope of scopes.values()) {
2077
- expectedNodeCount += 1 + scope.extras.length + (scope.startMarker ? 1 : 0);
2176
+ expectedNodeCount += 1 + scope.extras.length + (scope.startMarker ? 1 : 0) + (scope.scopeComments ? 2 : 0);
2078
2177
  }
2079
2178
  let actualNodeCount = 0;
2080
2179
  for (let node = container.firstChild;node; node = node.nextSibling)
@@ -2106,9 +2205,9 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
2106
2205
  existing.setItem(item);
2107
2206
  desiredOrder.push(existing);
2108
2207
  } else {
2109
- const scope = createItemScope(item, i2, renderItem, undefined, undefined, undefined, { container, anchor });
2110
- if (!scope.primaryEl.dataset.key)
2111
- scope.primaryEl.setAttribute(BF_KEY, key);
2208
+ const scope = createItemScope(item, i2, renderItem, undefined, undefined, undefined, undefined, { container, anchor });
2209
+ if (getKey && !scope.primaryEl.getAttribute(keyAttrName2))
2210
+ scope.primaryEl.setAttribute(keyAttrName2, key);
2112
2211
  scopes.set(key, scope);
2113
2212
  desiredOrder.push(scope);
2114
2213
  }
@@ -2145,7 +2244,7 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
2145
2244
  let j = i;
2146
2245
  while (j < desiredOrder.length && !stationary[j])
2147
2246
  j++;
2148
- const before = j < desiredOrder.length ? desiredOrder[j].startMarker ?? desiredOrder[j].primaryEl : anchor;
2247
+ const before = j < desiredOrder.length ? desiredOrder[j].startMarker ?? desiredOrder[j].scopeComments?.start ?? desiredOrder[j].primaryEl : anchor;
2149
2248
  if (j - i === 1) {
2150
2249
  insertScope(desiredOrder[i], container, before);
2151
2250
  } else {
@@ -2304,7 +2403,7 @@ function mapArrayAnchored(accessor, container, getKey, renderItem, markerId, bfI
2304
2403
  }
2305
2404
  // src/runtime/map-array-lazy.ts
2306
2405
  import { createEffect as createEffect2, createSignal as createSignal2, untrack as untrack2 } from "@barefootjs/client/reactive";
2307
- function mapArrayLazy(accessor, container, getKey, plan, markerId, bfId) {
2406
+ function mapArrayLazy(accessor, container, getKey, plan, markerId, bfId, keyAttrName2 = BF_KEY) {
2308
2407
  if (!container)
2309
2408
  return;
2310
2409
  const entries = new Map;
@@ -2343,8 +2442,8 @@ function mapArrayLazy(accessor, container, getKey, plan, markerId, bfId) {
2343
2442
  last: null
2344
2443
  };
2345
2444
  entry.primaryEl = untrack2(() => plan.createRow(entry, index));
2346
- if (!entry.primaryEl.dataset.key)
2347
- entry.primaryEl.setAttribute(BF_KEY, key);
2445
+ if (getKey && !entry.primaryEl.getAttribute(keyAttrName2))
2446
+ entry.primaryEl.setAttribute(keyAttrName2, key);
2348
2447
  markStranded();
2349
2448
  return entry;
2350
2449
  };
@@ -2366,7 +2465,7 @@ function mapArrayLazy(accessor, container, getKey, plan, markerId, bfId) {
2366
2465
  const shared = Math.min(doms.length, items.length);
2367
2466
  for (let i2 = 0;i2 < shared; i2++) {
2368
2467
  const el = doms[i2];
2369
- const ssrKey = el.getAttribute(BF_KEY);
2468
+ const ssrKey = el.getAttribute(keyAttrName2);
2370
2469
  const key = ssrKey !== null ? ssrKey : getKey ? getKey(items[i2], i2) : String(i2);
2371
2470
  const entry = { key, primaryEl: el, item: items[i2], refs: null, last: null };
2372
2471
  entries.set(key, entry);
@@ -3313,6 +3412,7 @@ export {
3313
3412
  onMount,
3314
3413
  onCleanup,
3315
3414
  mountRowRoot,
3415
+ markupOrEmpty,
3316
3416
  mapArrayLazy,
3317
3417
  mapArrayAnchored,
3318
3418
  mapArray,
@@ -159,6 +159,11 @@ export interface LazyRowPlan<T> {
159
159
  * @param plan - Compiler-emitted row plan (see {@link LazyRowPlan})
160
160
  * @param markerId - Scoped loop marker id (`<!--bf-loop:<id>-->`), see #1087
161
161
  * @param bfId - Profiler attribution id for the reconciler effect
162
+ * @param keyAttrName - The row-key attribute NAME this loop resolved at
163
+ * compile time (`IRElement.keyAttr`/`keyAttrName(loop.depth)`,
164
+ * jsx-to-ir.ts). Defaults to `BF_KEY` (plain `'data-key'`),
165
+ * correct at the outermost loop; only a nested loop's
166
+ * compiled call passes a depth-suffixed name (#2753).
162
167
  */
163
- export declare function mapArrayLazy<T>(accessor: () => T[], container: HTMLElement | null, getKey: ((item: T, index: number) => string) | null, plan: LazyRowPlan<T>, markerId?: string, bfId?: string): void;
168
+ export declare function mapArrayLazy<T>(accessor: () => T[], container: HTMLElement | null, getKey: ((item: T, index: number) => string) | null, plan: LazyRowPlan<T>, markerId?: string, bfId?: string, keyAttrName?: string): void;
164
169
  //# sourceMappingURL=map-array-lazy.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"map-array-lazy.d.ts","sourceRoot":"","sources":["../../src/runtime/map-array-lazy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkHG;AAMH;;;GAGG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,WAAW,CAAA;IACtB,IAAI,EAAE,CAAC,CAAA;IACP,iFAAiF;IACjF,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;IACpB,qDAAqD;IACrD,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B;gFAC4E;IAC5E,SAAS,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAAA;IAC7D;;;4EAGwE;IACxE,SAAS,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAA;IACpD;;;;;;;qEAOiE;IACjE,UAAU,CAAC,CAAC,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;CAC1E;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAC5B,QAAQ,EAAE,MAAM,CAAC,EAAE,EACnB,SAAS,EAAE,WAAW,GAAG,IAAI,EAC7B,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,IAAI,EACnD,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EACpB,QAAQ,CAAC,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,GACZ,IAAI,CAqSN"}
1
+ {"version":3,"file":"map-array-lazy.d.ts","sourceRoot":"","sources":["../../src/runtime/map-array-lazy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkHG;AAMH;;;GAGG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,WAAW,CAAA;IACtB,IAAI,EAAE,CAAC,CAAA;IACP,iFAAiF;IACjF,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;IACpB,qDAAqD;IACrD,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B;gFAC4E;IAC5E,SAAS,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAAA;IAC7D;;;4EAGwE;IACxE,SAAS,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAA;IACpD;;;;;;;qEAOiE;IACjE,UAAU,CAAC,CAAC,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;CAC1E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAC5B,QAAQ,EAAE,MAAM,CAAC,EAAE,EACnB,SAAS,EAAE,WAAW,GAAG,IAAI,EAC7B,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,IAAI,EACnD,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EACpB,QAAQ,CAAC,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,EACb,WAAW,GAAE,MAAe,GAC3B,IAAI,CA0SN"}
@@ -62,8 +62,18 @@ export declare function longestIncreasingSubsequenceIndices(arr: number[]): numb
62
62
  * Receives item as signal accessor: item() returns current value.
63
63
  * When `existing` is passed, initializes the SSR-rendered element and returns it.
64
64
  * When `existing` is undefined, creates a new element and returns it.
65
+ * @param keyAttrName - The row-key attribute NAME this loop resolved at
66
+ * compile time (`IRElement.keyAttr`/`keyAttrName(loop.depth)`,
67
+ * jsx-to-ir.ts) — `'data-key'` at the outermost loop,
68
+ * `'data-key-N'` N levels deep. Defaults to `BF_KEY`
69
+ * (plain `'data-key'`), correct for every depth-0 call
70
+ * site; only a nested loop's compiled call passes a
71
+ * depth-suffixed name (#2753 Shape B — see the "Why not
72
+ * stamp unconditionally" note below for why this
73
+ * replaced a hardcoded constant instead of just fixing
74
+ * the value).
65
75
  */
66
- export declare function mapArray<T>(accessor: () => T[], container: HTMLElement | null, getKey: ((item: T, index: number) => string) | null, renderItem: (item: () => T, index: number, existing?: HTMLElement) => HTMLElement, markerId?: string, bfId?: string): void;
76
+ export declare function mapArray<T>(accessor: () => T[], container: HTMLElement | null, getKey: ((item: T, index: number) => string) | null, renderItem: (item: () => T, index: number, existing?: HTMLElement) => HTMLElement, markerId?: string, bfId?: string, keyAttrName?: string): void;
67
77
  /**
68
78
  * Per-item scoped list rendering for whole-item conditionals (#1665).
69
79
  *
@@ -1 +1 @@
1
- {"version":3,"file":"map-array.d.ts","sourceRoot":"","sources":["../../src/runtime/map-array.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAqCH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,WAAW,EACtB,QAAQ,CAAC,EAAE,MAAM,GAChB;IAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,CA+BhD;AA8DD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mCAAmC,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CA2B3E;AA2FD;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EACxB,QAAQ,EAAE,MAAM,CAAC,EAAE,EACnB,SAAS,EAAE,WAAW,GAAG,IAAI,EAC7B,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,IAAI,EACnD,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,WAAW,KAAK,WAAW,EACjF,QAAQ,CAAC,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,GACZ,IAAI,CA6RN;AAqHD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,QAAQ,EAAE,MAAM,CAAC,EAAE,EACnB,SAAS,EAAE,WAAW,GAAG,IAAI,EAC7B,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,IAAI,EACnD,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,gBAAgB,GAAG,OAAO,EAC5F,QAAQ,CAAC,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,GACZ,IAAI,CA+FN"}
1
+ {"version":3,"file":"map-array.d.ts","sourceRoot":"","sources":["../../src/runtime/map-array.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAkEH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,WAAW,EACtB,QAAQ,CAAC,EAAE,MAAM,GAChB;IAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,CA+BhD;AAyHD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mCAAmC,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CA2B3E;AA4GD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EACxB,QAAQ,EAAE,MAAM,CAAC,EAAE,EACnB,SAAS,EAAE,WAAW,GAAG,IAAI,EAC7B,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,IAAI,EACnD,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,WAAW,KAAK,WAAW,EACjF,QAAQ,CAAC,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,EACb,WAAW,GAAE,MAAe,GAC3B,IAAI,CAsUN;AAqHD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,QAAQ,EAAE,MAAM,CAAC,EAAE,EACnB,SAAS,EAAE,WAAW,GAAG,IAAI,EAC7B,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,IAAI,EACnD,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,gBAAgB,GAAG,OAAO,EAC5F,QAAQ,CAAC,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,GACZ,IAAI,CA+FN"}
@@ -1 +1 @@
1
- {"version":3,"file":"qsa-item.d.ts","sourceRoot":"","sources":["../../src/runtime/qsa-item.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AA4CH;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAQnF;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,OAAO,EAClB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EACrB,WAAW,CAAC,EAAE,OAAO,GAAG,IAAI,GAC3B,WAAW,GAAG,IAAI,CAuBpB"}
1
+ {"version":3,"file":"qsa-item.d.ts","sourceRoot":"","sources":["../../src/runtime/qsa-item.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AA4CH;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAQnF;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,OAAO,EAClB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EACrB,WAAW,CAAC,EAAE,OAAO,GAAG,IAAI,GAC3B,WAAW,GAAG,IAAI,CAyBpB"}
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/runtime/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAaxC;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAclE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEjE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,OAAO,GAAG,IAAI,EAC1B,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAClC,IAAI,CAoCN;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EACrB,WAAW,CAAC,EAAE,OAAO,GAAG,IAAI,GAC3B,WAAW,GAAG,IAAI,CAgCpB"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/runtime/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAaxC;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAclE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEjE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,OAAO,GAAG,IAAI,EAC1B,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAClC,IAAI,CAoCN;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EACrB,WAAW,CAAC,EAAE,OAAO,GAAG,IAAI,GAC3B,WAAW,GAAG,IAAI,CAmCpB"}