@underverse-ui/underverse 1.0.112 → 1.0.115

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/index.cjs CHANGED
@@ -7692,6 +7692,7 @@ var Combobox = ({
7692
7692
  id: `${resolvedId}-listbox`,
7693
7693
  role: "listbox",
7694
7694
  "aria-labelledby": labelId,
7695
+ "data-os-ignore": virtualized ? "" : void 0,
7695
7696
  className: cn("overflow-y-auto overscroll-contain", (!useOverlayScrollbar || virtualized) && comboboxScrollClassName),
7696
7697
  style: { maxHeight },
7697
7698
  children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: cn(size === "sm" ? "p-1" : size === "lg" ? "p-2" : "p-1.5"), children: loading2 ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "px-3 py-10 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col items-center gap-3 animate-in fade-in-0 zoom-in-95 duration-300", children: [
@@ -15948,19 +15949,19 @@ var MultiCombobox = ({
15948
15949
  },
15949
15950
  "data-index": virtualItem?.index,
15950
15951
  style: itemStyle,
15952
+ className: cn(virtualItem && "list-none"),
15951
15953
  onClick: (e) => {
15952
15954
  e.preventDefault();
15953
15955
  e.stopPropagation();
15954
15956
  if (!isDisabled) toggleSelect(item.value);
15955
15957
  inputRef.current?.focus();
15956
15958
  },
15957
- className: cn("dropdown-item", isDisabled && "opacity-50 cursor-not-allowed pointer-events-none"),
15958
- children: renderOption(item, isSelected)
15959
+ children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: cn("dropdown-item", isDisabled && "opacity-50 cursor-not-allowed pointer-events-none"), children: renderOption(item, isSelected) })
15959
15960
  },
15960
15961
  item.value
15961
15962
  );
15962
15963
  }
15963
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
15964
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
15964
15965
  "li",
15965
15966
  {
15966
15967
  ref: (node) => {
@@ -15969,37 +15970,43 @@ var MultiCombobox = ({
15969
15970
  },
15970
15971
  "data-index": virtualItem?.index,
15971
15972
  style: itemStyle,
15973
+ className: cn(virtualItem && "list-none"),
15972
15974
  onClick: (e) => {
15973
15975
  e.preventDefault();
15974
15976
  e.stopPropagation();
15975
15977
  if (!isDisabled) toggleSelect(item.value);
15976
15978
  inputRef.current?.focus();
15977
15979
  },
15978
- className: cn(
15979
- "dropdown-item flex cursor-pointer items-center gap-3 rounded-full transition-all duration-200",
15980
- sizeStyles8[size].item,
15981
- "hover:bg-accent/70 hover:shadow-sm",
15982
- index === activeIndex && "bg-accent/60",
15983
- isSelected && "bg-primary/10 text-primary font-medium",
15984
- isDisabled && "opacity-40 cursor-not-allowed pointer-events-none"
15985
- ),
15986
- children: [
15987
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
15988
- "span",
15989
- {
15990
- className: cn(
15991
- "shrink-0 w-5 h-5 flex items-center justify-center rounded-md border-2 transition-all duration-200",
15992
- isSelected ? "bg-primary border-primary text-primary-foreground" : "border-muted-foreground/30 bg-transparent"
15980
+ children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
15981
+ "div",
15982
+ {
15983
+ className: cn(
15984
+ "dropdown-item flex cursor-pointer items-center gap-3 rounded-full transition-all duration-200",
15985
+ sizeStyles8[size].item,
15986
+ "hover:bg-accent/70 hover:shadow-sm",
15987
+ index === activeIndex && "bg-accent/60",
15988
+ isSelected && "bg-primary/10 text-primary font-medium",
15989
+ isDisabled && "opacity-40 cursor-not-allowed pointer-events-none"
15990
+ ),
15991
+ children: [
15992
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
15993
+ "span",
15994
+ {
15995
+ className: cn(
15996
+ "shrink-0 w-5 h-5 flex items-center justify-center rounded-md border-2 transition-all duration-200",
15997
+ isSelected ? "bg-primary border-primary text-primary-foreground" : "border-muted-foreground/30 bg-transparent"
15998
+ ),
15999
+ children: isSelected && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_lucide_react24.Check, { className: "w-3 h-3" })
16000
+ }
15993
16001
  ),
15994
- children: isSelected && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_lucide_react24.Check, { className: "w-3 h-3" })
15995
- }
15996
- ),
15997
- optionIcon && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "shrink-0 w-5 h-5 flex items-center justify-center text-muted-foreground", children: optionIcon }),
15998
- /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex-1 min-w-0", children: [
15999
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: cn("truncate", isSelected && "font-medium text-primary"), children: item.label }),
16000
- optionDesc && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "text-xs text-muted-foreground truncate mt-0.5", children: optionDesc })
16001
- ] })
16002
- ]
16002
+ optionIcon && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "shrink-0 w-5 h-5 flex items-center justify-center text-muted-foreground", children: optionIcon }),
16003
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex-1 min-w-0", children: [
16004
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: cn("truncate", isSelected && "font-medium text-primary"), children: item.label }),
16005
+ optionDesc && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "text-xs text-muted-foreground truncate mt-0.5", children: optionDesc })
16006
+ ] })
16007
+ ]
16008
+ }
16009
+ )
16003
16010
  },
16004
16011
  item.value
16005
16012
  );
@@ -16065,6 +16072,7 @@ var MultiCombobox = ({
16065
16072
  role: "listbox",
16066
16073
  "aria-multiselectable": "true",
16067
16074
  ref: optionsListRef,
16075
+ "data-os-ignore": virtualized ? "" : void 0,
16068
16076
  style: { maxHeight },
16069
16077
  className: cn(
16070
16078
  "overflow-y-auto p-1.5",
@@ -17467,6 +17475,7 @@ function OverlayControls({
17467
17475
 
17468
17476
  // src/components/CategoryTreeSelect.tsx
17469
17477
  var import_react22 = require("react");
17478
+ var import_react_virtual3 = require("@tanstack/react-virtual");
17470
17479
  var import_lucide_react26 = require("lucide-react");
17471
17480
  var import_jsx_runtime49 = require("react/jsx-runtime");
17472
17481
  var defaultLabels = {
@@ -17480,6 +17489,7 @@ var TREE_NODE_INDENT_REM = 1;
17480
17489
  var TREE_BRANCH_OFFSET_CLASS = "ml-1.5 pl-1.5";
17481
17490
  var TREE_NODE_GAP_CLASS = "gap-1.5";
17482
17491
  var TREE_EXPANDER_PLACEHOLDER_CLASS = "w-5";
17492
+ var CATEGORY_TREE_DROPDOWN_MAX_HEIGHT = 320;
17483
17493
  function getAncestorPathIds(categories, targetId) {
17484
17494
  const byId = new Map(categories.map((category) => [category.id, category]));
17485
17495
  const expanded = /* @__PURE__ */ new Set();
@@ -17558,6 +17568,24 @@ function pruneAncestorSelection(categories, childrenMap, selected, fromCategoryI
17558
17568
  function toCategoryOrderSelection(categories, selected) {
17559
17569
  return categories.map((category) => category.id).filter((categoryId) => selected.has(categoryId));
17560
17570
  }
17571
+ function flattenVisibleCategories(roots, childrenMap, expandedNodes, expandAllVisibleBranches) {
17572
+ const rows = [];
17573
+ const stack = roots.map((category) => ({ category, level: 0, path: /* @__PURE__ */ new Set() })).reverse();
17574
+ while (stack.length > 0) {
17575
+ const { category, level, path } = stack.pop();
17576
+ if (path.has(category.id)) continue;
17577
+ rows.push({ category, level });
17578
+ const children = childrenMap.get(category.id) ?? [];
17579
+ const isExpanded = children.length > 0 && (expandAllVisibleBranches || expandedNodes.has(category.id));
17580
+ if (!isExpanded) continue;
17581
+ const nextPath = new Set(path);
17582
+ nextPath.add(category.id);
17583
+ for (let index = children.length - 1; index >= 0; index -= 1) {
17584
+ stack.push({ category: children[index], level: level + 1, path: nextPath });
17585
+ }
17586
+ }
17587
+ return rows;
17588
+ }
17561
17589
  function CategoryTreeSelect(props) {
17562
17590
  const tv = useSmartTranslations("ValidationInput");
17563
17591
  const {
@@ -17586,6 +17614,15 @@ function CategoryTreeSelect(props) {
17586
17614
  className,
17587
17615
  useOverlayScrollbar = false,
17588
17616
  leafOnlySelect = false,
17617
+ virtualized = false,
17618
+ estimatedItemHeight = 44,
17619
+ overscan = 8,
17620
+ maxInitialOptions,
17621
+ searchMode = "auto",
17622
+ onSearchChange,
17623
+ searchDebounceMs = 0,
17624
+ minSearchLength = 0,
17625
+ showSearchPromptWhenEmptyQuery = false,
17589
17626
  singleSelect = false
17590
17627
  } = props;
17591
17628
  const [isOpen, setIsOpen] = (0, import_react22.useState)(false);
@@ -17593,10 +17630,13 @@ function CategoryTreeSelect(props) {
17593
17630
  () => getInitialExpandedNodes(categories, { defaultExpanded, defaultExpandedIds, expandToId, viewOnly, inline })
17594
17631
  );
17595
17632
  const [query, setQuery] = (0, import_react22.useState)("");
17633
+ const [activeIndex, setActiveIndex] = (0, import_react22.useState)(null);
17596
17634
  const [localRequiredError, setLocalRequiredError] = (0, import_react22.useState)();
17597
17635
  const searchInputRef = (0, import_react22.useRef)(null);
17598
17636
  const dropdownViewportRef = (0, import_react22.useRef)(null);
17599
- useOverlayScrollbarTarget(dropdownViewportRef, { enabled: useOverlayScrollbar });
17637
+ useOverlayScrollbarTarget(dropdownViewportRef, {
17638
+ enabled: isOpen && useOverlayScrollbar && !virtualized && !inline && !viewOnly
17639
+ });
17600
17640
  const autoId = (0, import_react22.useId)();
17601
17641
  const resolvedId = id ? String(id) : `category-tree-select-${autoId}`;
17602
17642
  const labelId = label ? `${resolvedId}-label` : void 0;
@@ -17616,7 +17656,7 @@ function CategoryTreeSelect(props) {
17616
17656
  const parentCategories2 = [];
17617
17657
  for (const cat of categories) byId2.set(cat.id, cat);
17618
17658
  for (const cat of categories) {
17619
- if (cat.parent_id == null) {
17659
+ if (cat.parent_id == null || !byId2.has(cat.parent_id)) {
17620
17660
  parentCategories2.push(cat);
17621
17661
  continue;
17622
17662
  }
@@ -17625,12 +17665,19 @@ function CategoryTreeSelect(props) {
17625
17665
  }
17626
17666
  return { parentCategories: parentCategories2, childrenMap: childrenMap2, byId: byId2 };
17627
17667
  }, [categories]);
17628
- const isSearchEnabled = (0, import_react22.useMemo)(() => enableSearch ?? categories.length > 10, [enableSearch, categories.length]);
17629
- const normalizedQuery = (0, import_react22.useMemo)(() => query.trim().toLowerCase(), [query]);
17668
+ const isSearchEnabled = (0, import_react22.useMemo)(
17669
+ () => enableSearch ?? (categories.length > 10 || searchMode === "manual" || minSearchLength > 0 || !!onSearchChange),
17670
+ [categories.length, enableSearch, minSearchLength, onSearchChange, searchMode]
17671
+ );
17672
+ const trimmedQuery = (0, import_react22.useMemo)(() => query.trim(), [query]);
17673
+ const normalizedQuery = (0, import_react22.useMemo)(() => trimmedQuery.toLowerCase(), [trimmedQuery]);
17674
+ const queryMeetsMinimum = trimmedQuery.length >= minSearchLength;
17675
+ const shouldPromptForSearch = minSearchLength > 0 && !queryMeetsMinimum && (searchMode === "manual" || showSearchPromptWhenEmptyQuery);
17630
17676
  const isSearchMode = isSearchEnabled && normalizedQuery.length > 0;
17677
+ const shouldAutoExpandSearchResults = searchMode === "auto" && isSearchMode;
17631
17678
  const effectiveExpandedNodes = (0, import_react22.useMemo)(() => getExpandedNodesState(expandedIds, expandedNodes), [expandedIds, expandedNodes]);
17632
17679
  const visibleIds = (0, import_react22.useMemo)(() => {
17633
- if (!isSearchMode) return null;
17680
+ if (shouldPromptForSearch || !isSearchMode || searchMode === "manual") return null;
17634
17681
  const matches = categories.filter((c) => c.name.toLowerCase().includes(normalizedQuery));
17635
17682
  if (matches.length === 0) return /* @__PURE__ */ new Set();
17636
17683
  const visible = /* @__PURE__ */ new Set();
@@ -17667,7 +17714,14 @@ function CategoryTreeSelect(props) {
17667
17714
  addDescendants(m.id);
17668
17715
  }
17669
17716
  return visible;
17670
- }, [byId, categories, childrenMap, isSearchMode, normalizedQuery]);
17717
+ }, [byId, categories, childrenMap, isSearchMode, normalizedQuery, searchMode, shouldPromptForSearch]);
17718
+ (0, import_react22.useEffect)(() => {
17719
+ if (!onSearchChange) return;
17720
+ const timeoutId = window.setTimeout(() => {
17721
+ onSearchChange(trimmedQuery);
17722
+ }, Math.max(0, searchDebounceMs));
17723
+ return () => window.clearTimeout(timeoutId);
17724
+ }, [onSearchChange, searchDebounceMs, trimmedQuery]);
17671
17725
  (0, import_react22.useEffect)(() => {
17672
17726
  if (!isOpen) return;
17673
17727
  if (!isSearchEnabled) return;
@@ -17680,7 +17734,7 @@ function CategoryTreeSelect(props) {
17680
17734
  }
17681
17735
  }, [disabled, required, valueArray.length]);
17682
17736
  const toggleExpand = (id2) => {
17683
- if (isSearchMode) return;
17737
+ if (shouldAutoExpandSearchResults) return;
17684
17738
  const newExpanded = new Set(effectiveExpandedNodes);
17685
17739
  if (newExpanded.has(id2)) {
17686
17740
  newExpanded.delete(id2);
@@ -17731,27 +17785,137 @@ function CategoryTreeSelect(props) {
17731
17785
  onChange(toCategoryOrderSelection(categories, newSelected));
17732
17786
  }
17733
17787
  };
17734
- const renderCategory = (category, level = 0) => {
17788
+ const effectiveParentCategories = (0, import_react22.useMemo)(() => {
17789
+ if (shouldPromptForSearch) return [];
17790
+ if (!isSearchMode || searchMode === "manual") return parentCategories;
17791
+ return parentCategories.filter((c) => visibleIds?.has(c.id));
17792
+ }, [isSearchMode, parentCategories, searchMode, shouldPromptForSearch, visibleIds]);
17793
+ const effectiveChildrenMap = (0, import_react22.useMemo)(() => {
17794
+ if (shouldPromptForSearch || !isSearchMode || !visibleIds || searchMode === "manual") return childrenMap;
17795
+ const nextChildrenMap = /* @__PURE__ */ new Map();
17796
+ for (const [parentId, children] of childrenMap.entries()) {
17797
+ nextChildrenMap.set(
17798
+ parentId,
17799
+ children.filter((child) => visibleIds.has(child.id))
17800
+ );
17801
+ }
17802
+ return nextChildrenMap;
17803
+ }, [childrenMap, isSearchMode, searchMode, shouldPromptForSearch, visibleIds]);
17804
+ const flattenedRows = (0, import_react22.useMemo)(() => {
17805
+ if (shouldPromptForSearch) return [];
17806
+ const rows = flattenVisibleCategories(effectiveParentCategories, effectiveChildrenMap, effectiveExpandedNodes, shouldAutoExpandSearchResults);
17807
+ if (trimmedQuery || maxInitialOptions === void 0 || maxInitialOptions < 1) {
17808
+ return rows;
17809
+ }
17810
+ const limitedRows = rows.slice(0, maxInitialOptions);
17811
+ const includedIds = new Set(limitedRows.map((row) => row.category.id));
17812
+ const pinnedIds = /* @__PURE__ */ new Set();
17813
+ for (const selectedId of selectedIds) {
17814
+ for (const ancestorId of getAncestorPathIds(categories, selectedId)) {
17815
+ pinnedIds.add(ancestorId);
17816
+ }
17817
+ }
17818
+ if (typeof expandToId === "number") {
17819
+ for (const ancestorId of getAncestorPathIds(categories, expandToId)) {
17820
+ pinnedIds.add(ancestorId);
17821
+ }
17822
+ }
17823
+ for (const row of rows) {
17824
+ if (!pinnedIds.has(row.category.id) || includedIds.has(row.category.id)) continue;
17825
+ limitedRows.push(row);
17826
+ includedIds.add(row.category.id);
17827
+ }
17828
+ return limitedRows;
17829
+ }, [
17830
+ categories,
17831
+ effectiveChildrenMap,
17832
+ effectiveExpandedNodes,
17833
+ effectiveParentCategories,
17834
+ expandToId,
17835
+ maxInitialOptions,
17836
+ selectedIds,
17837
+ shouldAutoExpandSearchResults,
17838
+ shouldPromptForSearch,
17839
+ trimmedQuery
17840
+ ]);
17841
+ const canVirtualize = virtualized && !inline && !viewOnly;
17842
+ const treeVirtualizer = (0, import_react_virtual3.useVirtualizer)({
17843
+ count: canVirtualize ? flattenedRows.length : 0,
17844
+ getScrollElement: () => dropdownViewportRef.current,
17845
+ estimateSize: () => estimatedItemHeight,
17846
+ initialRect: { width: 0, height: CATEGORY_TREE_DROPDOWN_MAX_HEIGHT },
17847
+ overscan,
17848
+ enabled: canVirtualize
17849
+ });
17850
+ const virtualRows = canVirtualize ? treeVirtualizer.getVirtualItems() : [];
17851
+ const scrollVirtualTreeToStart = () => {
17852
+ if (!canVirtualize || flattenedRows.length === 0) return;
17853
+ treeVirtualizer.scrollToIndex(0, { align: "start" });
17854
+ };
17855
+ const moveActiveVirtualRow = (direction) => {
17856
+ if (!canVirtualize || flattenedRows.length === 0) return;
17857
+ const nextIndex = activeIndex === null ? direction === 1 ? 0 : flattenedRows.length - 1 : (activeIndex + direction + flattenedRows.length) % flattenedRows.length;
17858
+ setActiveIndex(nextIndex);
17859
+ treeVirtualizer.scrollToIndex(nextIndex, { align: "auto" });
17860
+ };
17861
+ const handleVirtualTreeKeyDown = (event) => {
17862
+ if (!canVirtualize) return;
17863
+ if (event.key === "ArrowDown") {
17864
+ event.preventDefault();
17865
+ moveActiveVirtualRow(1);
17866
+ return;
17867
+ }
17868
+ if (event.key === "ArrowUp") {
17869
+ event.preventDefault();
17870
+ moveActiveVirtualRow(-1);
17871
+ return;
17872
+ }
17873
+ if (event.key === "Enter" && activeIndex !== null) {
17874
+ const row = flattenedRows[activeIndex];
17875
+ if (!row) return;
17876
+ event.preventDefault();
17877
+ handleSelect(row.category.id, row.category);
17878
+ }
17879
+ };
17880
+ (0, import_react22.useEffect)(() => {
17881
+ setActiveIndex(null);
17882
+ }, [flattenedRows]);
17883
+ const renderCategoryRow = (category, level = 0, virtualItem) => {
17735
17884
  const children = effectiveChildrenMap.get(category.id) || [];
17736
17885
  const hasChildren = children.length > 0;
17737
- const isExpanded = hasChildren && (isSearchMode || effectiveExpandedNodes.has(category.id));
17886
+ const isExpanded = hasChildren && (shouldAutoExpandSearchResults || effectiveExpandedNodes.has(category.id));
17738
17887
  const isSelected = selectedIds.has(category.id);
17739
17888
  const isSelectable = !viewOnly && (!leafOnlySelect || !hasChildren);
17889
+ const isActive = virtualItem?.index === activeIndex;
17890
+ const rowStyle = virtualItem ? {
17891
+ position: "absolute",
17892
+ top: 0,
17893
+ left: 0,
17894
+ width: "100%",
17895
+ transform: `translateY(${virtualItem.start}px)`
17896
+ } : void 0;
17740
17897
  return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
17741
17898
  "div",
17742
17899
  {
17743
- className: "min-w-0 animate-in fade-in-50 duration-200 [content-visibility:auto] [contain-intrinsic-size:44px]",
17744
- style: { animationDelay: `${level * 30}ms` },
17900
+ ref: virtualItem ? treeVirtualizer.measureElement : void 0,
17901
+ "data-index": virtualItem?.index,
17902
+ className: cn("min-w-0 [content-visibility:auto] [contain-intrinsic-size:44px]", !virtualItem && "animate-in fade-in-50 duration-200"),
17903
+ style: { animationDelay: virtualItem ? void 0 : `${level * 30}ms`, ...rowStyle },
17745
17904
  children: [
17746
17905
  /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
17747
17906
  "div",
17748
17907
  {
17908
+ role: "treeitem",
17909
+ "aria-level": level + 1,
17910
+ "aria-expanded": hasChildren ? isExpanded : void 0,
17911
+ "aria-selected": viewOnly ? void 0 : isSelected,
17749
17912
  onClick: () => !viewOnly && handleSelect(category.id, category),
17750
17913
  className: cn(
17751
17914
  "relative flex min-w-0 items-center px-3 py-2.5 min-h-11 transition-all duration-200 rounded-3xl",
17752
17915
  TREE_NODE_GAP_CLASS,
17753
17916
  !viewOnly && (isSelectable ? "cursor-pointer" : "cursor-default"),
17754
17917
  isSelectable && !isSelected && "hover:bg-accent/50",
17918
+ canVirtualize && isActive && "bg-accent/50",
17755
17919
  // Selected state - đồng bộ cho tất cả
17756
17920
  !viewOnly && isSelected && "bg-accent/40"
17757
17921
  ),
@@ -17761,6 +17925,7 @@ function CategoryTreeSelect(props) {
17761
17925
  "button",
17762
17926
  {
17763
17927
  type: "button",
17928
+ "aria-label": isExpanded ? `Collapse ${category.name}` : `Expand ${category.name}`,
17764
17929
  onClick: (e) => {
17765
17930
  e.stopPropagation();
17766
17931
  toggleExpand(category.id);
@@ -17770,9 +17935,9 @@ function CategoryTreeSelect(props) {
17770
17935
  "hover:scale-110 active:scale-95",
17771
17936
  "focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50",
17772
17937
  isExpanded && "text-primary",
17773
- isSearchMode && "opacity-60 cursor-not-allowed hover:scale-100 active:scale-100"
17938
+ shouldAutoExpandSearchResults && "opacity-60 cursor-not-allowed hover:scale-100 active:scale-100"
17774
17939
  ),
17775
- disabled: isSearchMode,
17940
+ disabled: shouldAutoExpandSearchResults,
17776
17941
  children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: cn("transition-transform duration-200", isExpanded && "rotate-90"), children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_lucide_react26.ChevronRight, { className: "w-4 h-4" }) })
17777
17942
  }
17778
17943
  ) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: TREE_EXPANDER_PLACEHOLDER_CLASS }),
@@ -17803,15 +17968,16 @@ function CategoryTreeSelect(props) {
17803
17968
  ]
17804
17969
  }
17805
17970
  ),
17806
- hasChildren && isExpanded && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
17971
+ !virtualItem && hasChildren && isExpanded && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
17807
17972
  "div",
17808
17973
  {
17974
+ role: "group",
17809
17975
  className: cn(
17810
17976
  TREE_BRANCH_OFFSET_CLASS,
17811
17977
  "border-l-2 border-dashed border-border/50",
17812
17978
  "animate-in slide-in-from-top-2 fade-in-50 duration-200"
17813
17979
  ),
17814
- children: children.map((child) => renderCategory(child, level + 1))
17980
+ children: children.map((child) => renderCategoryRow(child, level + 1))
17815
17981
  }
17816
17982
  )
17817
17983
  ]
@@ -17828,7 +17994,11 @@ function CategoryTreeSelect(props) {
17828
17994
  {
17829
17995
  ref: searchInputRef,
17830
17996
  value: query,
17831
- onChange: (e) => setQuery(e.target.value),
17997
+ onChange: (e) => {
17998
+ setQuery(e.target.value);
17999
+ scrollVirtualTreeToStart();
18000
+ },
18001
+ onKeyDown: handleVirtualTreeKeyDown,
17832
18002
  placeholder: mergedLabels.searchPlaceholder,
17833
18003
  className: cn(
17834
18004
  "peer w-full rounded-full bg-background/90 py-2.5 pl-10 pr-10 text-sm shadow-sm",
@@ -17845,6 +18015,7 @@ function CategoryTreeSelect(props) {
17845
18015
  type: "button",
17846
18016
  onClick: () => {
17847
18017
  setQuery("");
18018
+ scrollVirtualTreeToStart();
17848
18019
  searchInputRef.current?.focus();
17849
18020
  },
17850
18021
  className: cn(
@@ -17859,24 +18030,40 @@ function CategoryTreeSelect(props) {
17859
18030
  )
17860
18031
  ] }) });
17861
18032
  };
17862
- const effectiveParentCategories = (0, import_react22.useMemo)(() => {
17863
- if (!isSearchMode) return parentCategories;
17864
- return parentCategories.filter((c) => visibleIds?.has(c.id));
17865
- }, [isSearchMode, parentCategories, visibleIds]);
17866
- let effectiveChildrenMap = childrenMap;
17867
- if (isSearchMode && visibleIds) {
17868
- effectiveChildrenMap = /* @__PURE__ */ new Map();
17869
- for (const [parentId, children] of childrenMap.entries()) {
17870
- effectiveChildrenMap.set(
17871
- parentId,
17872
- children.filter((child) => visibleIds.has(child.id))
17873
- );
17874
- }
17875
- }
17876
- const renderTreeContent = () => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "space-y-0.5 overflow-x-hidden", children: effectiveParentCategories.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex flex-col items-center justify-center py-8 text-center", children: [
18033
+ const renderTreeContent = () => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "space-y-0.5 overflow-x-hidden", children: shouldPromptForSearch ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex flex-col items-center justify-center py-8 text-center", children: [
18034
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "w-12 h-12 rounded-2xl bg-muted/50 flex items-center justify-center mb-3", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_lucide_react26.Search, { className: "w-6 h-6 text-muted-foreground/50" }) }),
18035
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "text-sm text-muted-foreground", children: [
18036
+ "Type at least ",
18037
+ minSearchLength,
18038
+ " characters to search"
18039
+ ] })
18040
+ ] }) : effectiveParentCategories.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex flex-col items-center justify-center py-8 text-center", children: [
17877
18041
  /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "w-12 h-12 rounded-2xl bg-muted/50 flex items-center justify-center mb-3", children: isSearchMode ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_lucide_react26.SearchX, { className: "w-6 h-6 text-muted-foreground/50" }) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_lucide_react26.Layers, { className: "w-6 h-6 text-muted-foreground/50" }) }),
17878
18042
  /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "text-sm text-muted-foreground", children: isSearchMode ? mergedLabels.noResultsText : mergedLabels.emptyText })
17879
- ] }) : effectiveParentCategories.map((cat) => renderCategory(cat)) });
18043
+ ] }) : effectiveParentCategories.map((cat) => renderCategoryRow(cat)) });
18044
+ const renderVirtualTreeContent = () => {
18045
+ if (shouldPromptForSearch) {
18046
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex flex-col items-center justify-center py-8 text-center", children: [
18047
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "w-12 h-12 rounded-2xl bg-muted/50 flex items-center justify-center mb-3", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_lucide_react26.Search, { className: "w-6 h-6 text-muted-foreground/50" }) }),
18048
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "text-sm text-muted-foreground", children: [
18049
+ "Type at least ",
18050
+ minSearchLength,
18051
+ " characters to search"
18052
+ ] })
18053
+ ] });
18054
+ }
18055
+ if (flattenedRows.length === 0) {
18056
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex flex-col items-center justify-center py-8 text-center", children: [
18057
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "w-12 h-12 rounded-2xl bg-muted/50 flex items-center justify-center mb-3", children: isSearchMode ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_lucide_react26.SearchX, { className: "w-6 h-6 text-muted-foreground/50" }) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_lucide_react26.Layers, { className: "w-6 h-6 text-muted-foreground/50" }) }),
18058
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "text-sm text-muted-foreground", children: isSearchMode ? mergedLabels.noResultsText : mergedLabels.emptyText })
18059
+ ] });
18060
+ }
18061
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "relative overflow-x-hidden", style: { height: `${treeVirtualizer.getTotalSize()}px` }, children: virtualRows.map((virtualRow) => {
18062
+ const row = flattenedRows[virtualRow.index];
18063
+ if (!row) return null;
18064
+ return renderCategoryRow(row.category, row.level, virtualRow);
18065
+ }) });
18066
+ };
17880
18067
  const renderLabel = () => label ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
17881
18068
  Label,
17882
18069
  {
@@ -17919,8 +18106,10 @@ function CategoryTreeSelect(props) {
17919
18106
  "div",
17920
18107
  {
17921
18108
  id: resolvedId,
18109
+ role: "tree",
17922
18110
  "aria-labelledby": labelId,
17923
18111
  "aria-describedby": describedBy,
18112
+ "aria-multiselectable": singleSelect ? void 0 : true,
17924
18113
  className: cn("rounded-2xl border border-border/60 bg-card/50 backdrop-blur-sm p-3 shadow-sm", disabled && "opacity-50"),
17925
18114
  children: [
17926
18115
  renderSearch(),
@@ -17955,8 +18144,10 @@ function CategoryTreeSelect(props) {
17955
18144
  "div",
17956
18145
  {
17957
18146
  id: resolvedId,
18147
+ role: "tree",
17958
18148
  "aria-labelledby": labelId,
17959
18149
  "aria-describedby": describedBy,
18150
+ "aria-multiselectable": singleSelect ? void 0 : true,
17960
18151
  className: cn("rounded-2xl border border-border/60 bg-card/50 backdrop-blur-sm p-3 shadow-sm", disabled && "opacity-50 pointer-events-none"),
17961
18152
  children: [
17962
18153
  renderSearch(),
@@ -18021,6 +18212,7 @@ function CategoryTreeSelect(props) {
18021
18212
  setIsOpen(nextOpen);
18022
18213
  if (!nextOpen) {
18023
18214
  setQuery("");
18215
+ scrollVirtualTreeToStart();
18024
18216
  }
18025
18217
  };
18026
18218
  let displayText;
@@ -18036,15 +18228,20 @@ function CategoryTreeSelect(props) {
18036
18228
  displayText = mergedLabels.selectedText(selectedCount);
18037
18229
  }
18038
18230
  }
18039
- const dropdownBody = /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex max-h-80 flex-col overflow-hidden", children: [
18231
+ const dropdownBody = /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex flex-col overflow-hidden", style: { maxHeight: CATEGORY_TREE_DROPDOWN_MAX_HEIGHT }, children: [
18040
18232
  renderSearch({ sticky: false, className: "border-b border-border/30 p-2 pb-2" }),
18041
18233
  /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
18042
18234
  "div",
18043
18235
  {
18044
18236
  ref: dropdownViewportRef,
18045
18237
  id: `${resolvedId}-tree`,
18238
+ role: "tree",
18239
+ "aria-multiselectable": singleSelect ? void 0 : true,
18240
+ "data-os-ignore": virtualized ? "" : void 0,
18241
+ tabIndex: canVirtualize ? 0 : void 0,
18242
+ onKeyDown: handleVirtualTreeKeyDown,
18046
18243
  className: cn("min-h-0 flex-1 overflow-auto overflow-x-hidden p-2 pt-2"),
18047
- children: renderTreeContent()
18244
+ children: canVirtualize ? renderVirtualTreeContent() : renderTreeContent()
18048
18245
  }
18049
18246
  )
18050
18247
  ] });
@@ -18099,6 +18296,10 @@ function CategoryTreeSelect(props) {
18099
18296
  if (event.key === "Enter" || event.key === " " || event.key === "ArrowDown") {
18100
18297
  event.preventDefault();
18101
18298
  handleOpenChange(!isOpen);
18299
+ if (event.key === "ArrowDown" && canVirtualize && flattenedRows.length > 0) {
18300
+ setActiveIndex(0);
18301
+ treeVirtualizer.scrollToIndex(0, { align: "start" });
18302
+ }
18102
18303
  }
18103
18304
  },
18104
18305
  className: cn(
@@ -21718,6 +21919,7 @@ var TableCaption = import_react28.default.forwardRef(({ className, ...props }, r
21718
21919
  TableCaption.displayName = "TableCaption";
21719
21920
 
21720
21921
  // src/components/DataTable/DataTable.tsx
21922
+ var import_react_virtual4 = require("@tanstack/react-virtual");
21721
21923
  var import_react38 = __toESM(require("react"), 1);
21722
21924
 
21723
21925
  // src/components/DataTable/components/DataTableBody.tsx
@@ -21790,8 +21992,17 @@ function DataTableBodyRows({
21790
21992
  getStickyColumnStyle,
21791
21993
  getStickyCellClass,
21792
21994
  t,
21793
- labels
21995
+ labels,
21996
+ virtualRows,
21997
+ virtualPaddingTop = 0,
21998
+ virtualPaddingBottom = 0,
21999
+ measureVirtualRow
21794
22000
  }) {
22001
+ const rowsToRender = virtualRows ? virtualRows.map((virtualRow) => ({
22002
+ row: displayedData[virtualRow.index],
22003
+ idx: virtualRow.index,
22004
+ virtualRow
22005
+ })).filter((item) => Boolean(item.row)) : displayedData.map((row, idx) => ({ row, idx, virtualRow: void 0 }));
21795
22006
  return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(TableBody, { children: loading2 ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(TableCell, { colSpan: leafColumns.length, className: "text-center py-8", children: /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("div", { className: "flex items-center justify-center gap-2 text-muted-foreground", children: [
21796
22007
  /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("svg", { className: "animate-spin h-4 w-4", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
21797
22008
  /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
@@ -21808,42 +22019,48 @@ function DataTableBodyRows({
21808
22019
  t("loading"),
21809
22020
  "\u2026"
21810
22021
  ] })
21811
- ] }) }) }) : displayedData.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(TableCell, { colSpan: leafColumns.length, className: "text-center py-6 text-muted-foreground", children: labels?.noData || t("noData") }) }) : displayedData.map((row, idx) => {
21812
- const isStripedRow = striped && idx % 2 === 0;
21813
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
21814
- TableRow,
21815
- {
21816
- className: cn(densityRowClass, isStripedRow ? "bg-surface-1" : "bg-surface-0"),
21817
- style: {
21818
- contentVisibility: "auto",
21819
- containIntrinsicSize: density === "compact" ? "0 36px" : density === "comfortable" ? "0 56px" : "0 48px"
22022
+ ] }) }) }) : displayedData.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(TableCell, { colSpan: leafColumns.length, className: "text-center py-6 text-muted-foreground", children: labels?.noData || t("noData") }) }) : /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(import_jsx_runtime63.Fragment, { children: [
22023
+ virtualPaddingTop > 0 && /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(TableRow, { "aria-hidden": "true", className: "border-0 hover:bg-transparent hover:shadow-none", children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(TableCell, { colSpan: leafColumns.length, className: "p-0", style: { height: virtualPaddingTop } }) }),
22024
+ rowsToRender.map(({ row, idx, virtualRow }) => {
22025
+ const isStripedRow = striped && idx % 2 === 0;
22026
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
22027
+ TableRow,
22028
+ {
22029
+ ref: virtualRow ? measureVirtualRow : void 0,
22030
+ "data-index": virtualRow?.index,
22031
+ className: cn(densityRowClass, isStripedRow ? "bg-surface-1" : "bg-surface-0"),
22032
+ style: {
22033
+ contentVisibility: "auto",
22034
+ containIntrinsicSize: density === "compact" ? "0 36px" : density === "comfortable" ? "0 56px" : "0 48px"
22035
+ },
22036
+ children: leafColumns.map((col, colIdx) => {
22037
+ const value = col.dataIndex ? row[col.dataIndex] : void 0;
22038
+ const prevCol = colIdx > 0 ? leafColumns[colIdx - 1] : null;
22039
+ const isAfterFixedLeft = prevCol?.fixed === "left";
22040
+ const showBorderLeft = columnDividers && colIdx > 0 && !isAfterFixedLeft && !col.fixed;
22041
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
22042
+ TableCell,
22043
+ {
22044
+ "data-underverse-column-key": col.key,
22045
+ style: getStickyColumnStyle(col),
22046
+ className: cn(
22047
+ cellPadding,
22048
+ col.align === "right" && "text-right",
22049
+ col.align === "center" && "text-center",
22050
+ showBorderLeft && "border-l border-border/60",
22051
+ getStickyCellClass(col, isStripedRow)
22052
+ ),
22053
+ children: col.render ? col.render(value, row, idx) : /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(DataTableOverflowText, { text: String(value ?? ""), align: col.align })
22054
+ },
22055
+ col.key
22056
+ );
22057
+ })
21820
22058
  },
21821
- children: leafColumns.map((col, colIdx) => {
21822
- const value = col.dataIndex ? row[col.dataIndex] : void 0;
21823
- const prevCol = colIdx > 0 ? leafColumns[colIdx - 1] : null;
21824
- const isAfterFixedLeft = prevCol?.fixed === "left";
21825
- const showBorderLeft = columnDividers && colIdx > 0 && !isAfterFixedLeft && !col.fixed;
21826
- return /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
21827
- TableCell,
21828
- {
21829
- "data-underverse-column-key": col.key,
21830
- style: getStickyColumnStyle(col),
21831
- className: cn(
21832
- cellPadding,
21833
- col.align === "right" && "text-right",
21834
- col.align === "center" && "text-center",
21835
- showBorderLeft && "border-l border-border/60",
21836
- getStickyCellClass(col, isStripedRow)
21837
- ),
21838
- children: col.render ? col.render(value, row, idx) : /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(DataTableOverflowText, { text: String(value ?? ""), align: col.align })
21839
- },
21840
- col.key
21841
- );
21842
- })
21843
- },
21844
- getRowKey(row, idx)
21845
- );
21846
- }) });
22059
+ getRowKey(row, idx)
22060
+ );
22061
+ }),
22062
+ virtualPaddingBottom > 0 && /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(TableRow, { "aria-hidden": "true", className: "border-0 hover:bg-transparent hover:shadow-none", children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(TableCell, { colSpan: leafColumns.length, className: "p-0", style: { height: virtualPaddingBottom } }) })
22063
+ ] }) });
21847
22064
  }
21848
22065
 
21849
22066
  // src/components/DataTable/components/DataTableHeader.tsx
@@ -22910,6 +23127,9 @@ function DataTable({
22910
23127
  horizontalMode = "auto",
22911
23128
  overflowHidden = true,
22912
23129
  useOverlayScrollbar = false,
23130
+ virtualizedRows = false,
23131
+ estimatedRowHeight,
23132
+ overscan = 8,
22913
23133
  enableHeaderAutoFit = true,
22914
23134
  labels
22915
23135
  }) {
@@ -22965,6 +23185,7 @@ function DataTable({
22965
23185
  console.warn("[DataTable] `rowKey` should be provided when using sort/filter/pagination to keep row identity stable.");
22966
23186
  }, [columns, isServerMode, pageSizeOptions, rowKey]);
22967
23187
  const densityRowClass = density === "compact" ? "h-9" : density === "comfortable" ? "h-14" : "h-12";
23188
+ const defaultEstimatedRowHeight = density === "compact" ? 36 : density === "comfortable" ? 56 : 48;
22968
23189
  const cellPadding = density === "compact" ? "py-1.5 px-3" : density === "comfortable" ? "py-3 px-4" : "py-2.5 px-4";
22969
23190
  const headerTitleClass = size === "sm" ? "text-xs" : size === "lg" ? "text-[15px]" : "text-sm";
22970
23191
  const headerMinHeightClass = size === "sm" ? "min-h-9" : size === "lg" ? "min-h-11" : "min-h-10";
@@ -22992,8 +23213,23 @@ function DataTable({
22992
23213
  };
22993
23214
  const viewportRef = import_react38.default.useRef(null);
22994
23215
  const tableRef = import_react38.default.useRef(null);
23216
+ const canVirtualizeRows = virtualizedRows && !loading2 && displayedData.length > 0;
23217
+ const rowVirtualizer = (0, import_react_virtual4.useVirtualizer)({
23218
+ count: canVirtualizeRows ? displayedData.length : 0,
23219
+ getScrollElement: () => viewportRef.current,
23220
+ estimateSize: () => estimatedRowHeight ?? defaultEstimatedRowHeight,
23221
+ initialRect: {
23222
+ width: 0,
23223
+ height: typeof maxHeight === "number" ? maxHeight : 500
23224
+ },
23225
+ overscan,
23226
+ enabled: canVirtualizeRows
23227
+ });
23228
+ const virtualRows = canVirtualizeRows ? rowVirtualizer.getVirtualItems() : [];
23229
+ const virtualPaddingTop = canVirtualizeRows && virtualRows.length > 0 ? virtualRows[0]?.start ?? 0 : 0;
23230
+ const virtualPaddingBottom = canVirtualizeRows && virtualRows.length > 0 ? Math.max(0, rowVirtualizer.getTotalSize() - (virtualRows[virtualRows.length - 1]?.end ?? 0)) : 0;
22995
23231
  useOverlayScrollbarTarget(viewportRef, {
22996
- enabled: useOverlayScrollbar,
23232
+ enabled: useOverlayScrollbar && !canVirtualizeRows,
22997
23233
  overflowX: overlayOverflowX
22998
23234
  });
22999
23235
  const autoFitColumn = import_react38.default.useCallback((columnKey) => {
@@ -23057,6 +23293,7 @@ function DataTable({
23057
23293
  "div",
23058
23294
  {
23059
23295
  ref: viewportRef,
23296
+ "data-os-ignore": canVirtualizeRows ? "" : void 0,
23060
23297
  className: cn("w-full", viewportOverflowXClass, stickyHeader && "overflow-y-auto"),
23061
23298
  style: stickyHeader ? { maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight } : void 0,
23062
23299
  children: /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
@@ -23108,7 +23345,11 @@ function DataTable({
23108
23345
  getStickyColumnStyle,
23109
23346
  getStickyCellClass,
23110
23347
  t,
23111
- labels
23348
+ labels,
23349
+ virtualRows: canVirtualizeRows ? virtualRows : void 0,
23350
+ virtualPaddingTop: canVirtualizeRows ? virtualPaddingTop : void 0,
23351
+ virtualPaddingBottom: canVirtualizeRows ? virtualPaddingBottom : void 0,
23352
+ measureVirtualRow: canVirtualizeRows ? rowVirtualizer.measureElement : void 0
23112
23353
  }
23113
23354
  )
23114
23355
  ]
@@ -27046,7 +27287,7 @@ function findDiffEnd(a, b, posA, posB) {
27046
27287
  posB -= size;
27047
27288
  }
27048
27289
  }
27049
- var Fragment26 = class _Fragment {
27290
+ var Fragment27 = class _Fragment {
27050
27291
  /**
27051
27292
  @internal
27052
27293
  */
@@ -27338,7 +27579,7 @@ var Fragment26 = class _Fragment {
27338
27579
  throw new RangeError("Can not convert " + nodes + " to a Fragment" + (nodes.nodesBetween ? " (looks like multiple versions of prosemirror-model were loaded)" : ""));
27339
27580
  }
27340
27581
  };
27341
- Fragment26.empty = new Fragment26([], 0);
27582
+ Fragment27.empty = new Fragment27([], 0);
27342
27583
  var found = { index: 0, offset: 0 };
27343
27584
  function retIndex(index, offset) {
27344
27585
  found.index = index;
@@ -27563,7 +27804,7 @@ var Slice = class _Slice {
27563
27804
  let openStart = json.openStart || 0, openEnd = json.openEnd || 0;
27564
27805
  if (typeof openStart != "number" || typeof openEnd != "number")
27565
27806
  throw new RangeError("Invalid input for Slice.fromJSON");
27566
- return new _Slice(Fragment26.fromJSON(schema, json.content), openStart, openEnd);
27807
+ return new _Slice(Fragment27.fromJSON(schema, json.content), openStart, openEnd);
27567
27808
  }
27568
27809
  /**
27569
27810
  Create a slice from a fragment by taking the maximum possible
@@ -27578,7 +27819,7 @@ var Slice = class _Slice {
27578
27819
  return new _Slice(fragment, openStart, openEnd);
27579
27820
  }
27580
27821
  };
27581
- Slice.empty = new Slice(Fragment26.empty, 0, 0);
27822
+ Slice.empty = new Slice(Fragment27.empty, 0, 0);
27582
27823
  function removeRange(content, from, to) {
27583
27824
  let { index, offset } = content.findIndex(from), child = content.maybeChild(index);
27584
27825
  let { index: indexTo, offset: offsetTo } = content.findIndex(to);
@@ -27676,7 +27917,7 @@ function replaceThreeWay($from, $start, $end, $to, depth) {
27676
27917
  addNode(close(openEnd, replaceTwoWay($end, $to, depth + 1)), content);
27677
27918
  }
27678
27919
  addRange($to, null, depth, content);
27679
- return new Fragment26(content);
27920
+ return new Fragment27(content);
27680
27921
  }
27681
27922
  function replaceTwoWay($from, $to, depth) {
27682
27923
  let content = [];
@@ -27686,13 +27927,13 @@ function replaceTwoWay($from, $to, depth) {
27686
27927
  addNode(close(type, replaceTwoWay($from, $to, depth + 1)), content);
27687
27928
  }
27688
27929
  addRange($to, null, depth, content);
27689
- return new Fragment26(content);
27930
+ return new Fragment27(content);
27690
27931
  }
27691
27932
  function prepareSliceForReplace(slice, $along) {
27692
27933
  let extra = $along.depth - slice.openStart, parent = $along.node(extra);
27693
27934
  let node = parent.copy(slice.content);
27694
27935
  for (let i = extra - 1; i >= 0; i--)
27695
- node = $along.node(i).copy(Fragment26.from(node));
27936
+ node = $along.node(i).copy(Fragment27.from(node));
27696
27937
  return {
27697
27938
  start: node.resolveNoCache(slice.openStart + extra),
27698
27939
  end: node.resolveNoCache(node.content.size - slice.openEnd - extra)
@@ -28031,7 +28272,7 @@ var Node2 = class _Node {
28031
28272
  this.type = type;
28032
28273
  this.attrs = attrs;
28033
28274
  this.marks = marks;
28034
- this.content = content || Fragment26.empty;
28275
+ this.content = content || Fragment27.empty;
28035
28276
  }
28036
28277
  /**
28037
28278
  The array of this node's child nodes.
@@ -28336,7 +28577,7 @@ var Node2 = class _Node {
28336
28577
  can optionally pass `start` and `end` indices into the
28337
28578
  replacement fragment.
28338
28579
  */
28339
- canReplace(from, to, replacement = Fragment26.empty, start = 0, end = replacement.childCount) {
28580
+ canReplace(from, to, replacement = Fragment27.empty, start = 0, end = replacement.childCount) {
28340
28581
  let one = this.contentMatchAt(from).matchFragment(replacement, start, end);
28341
28582
  let two = one && one.matchFragment(this.content, to);
28342
28583
  if (!two || !two.validEnd)
@@ -28418,7 +28659,7 @@ var Node2 = class _Node {
28418
28659
  throw new RangeError("Invalid text node in JSON");
28419
28660
  return schema.text(json.text, marks);
28420
28661
  }
28421
- let content = Fragment26.fromJSON(schema, json.content);
28662
+ let content = Fragment27.fromJSON(schema, json.content);
28422
28663
  let node = schema.nodeType(json.type).create(json.attrs, content, marks);
28423
28664
  node.type.checkAttrs(node.attrs);
28424
28665
  return node;
@@ -28514,7 +28755,7 @@ var ContentMatch = class _ContentMatch {
28514
28755
  function search(match, types) {
28515
28756
  let finished = match.matchFragment(after, startIndex);
28516
28757
  if (finished && (!toEnd || finished.validEnd))
28517
- return Fragment26.from(types.map((tp) => tp.createAndFill()));
28758
+ return Fragment27.from(types.map((tp) => tp.createAndFill()));
28518
28759
  for (let i = 0; i < match.next.length; i++) {
28519
28760
  let { type, next } = match.next[i];
28520
28761
  if (!(type.isText || type.hasRequiredAttrs()) && seen.indexOf(next) == -1) {
@@ -29082,7 +29323,7 @@ function mapFragment(fragment, f, parent) {
29082
29323
  child = f(child, parent, i);
29083
29324
  mapped.push(child);
29084
29325
  }
29085
- return Fragment26.fromArray(mapped);
29326
+ return Fragment27.fromArray(mapped);
29086
29327
  }
29087
29328
  var AddMarkStep = class _AddMarkStep extends Step {
29088
29329
  /**
@@ -29199,7 +29440,7 @@ var AddNodeMarkStep = class _AddNodeMarkStep extends Step {
29199
29440
  if (!node)
29200
29441
  return StepResult.fail("No node at mark step's position");
29201
29442
  let updated = node.type.create(node.attrs, null, this.mark.addToSet(node.marks));
29202
- return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment26.from(updated), 0, node.isLeaf ? 0 : 1));
29443
+ return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment27.from(updated), 0, node.isLeaf ? 0 : 1));
29203
29444
  }
29204
29445
  invert(doc) {
29205
29446
  let node = doc.nodeAt(this.pos);
@@ -29245,7 +29486,7 @@ var RemoveNodeMarkStep = class _RemoveNodeMarkStep extends Step {
29245
29486
  if (!node)
29246
29487
  return StepResult.fail("No node at mark step's position");
29247
29488
  let updated = node.type.create(node.attrs, null, this.mark.removeFromSet(node.marks));
29248
- return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment26.from(updated), 0, node.isLeaf ? 0 : 1));
29489
+ return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment27.from(updated), 0, node.isLeaf ? 0 : 1));
29249
29490
  }
29250
29491
  invert(doc) {
29251
29492
  let node = doc.nodeAt(this.pos);
@@ -29446,7 +29687,7 @@ var AttrStep = class _AttrStep extends Step {
29446
29687
  attrs[name] = node.attrs[name];
29447
29688
  attrs[this.attr] = this.value;
29448
29689
  let updated = node.type.create(attrs, null, node.marks);
29449
- return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment26.from(updated), 0, node.isLeaf ? 0 : 1));
29690
+ return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment27.from(updated), 0, node.isLeaf ? 0 : 1));
29450
29691
  }
29451
29692
  getMap() {
29452
29693
  return StepMap.empty;
@@ -29830,7 +30071,7 @@ var NodeSelection2 = class _NodeSelection extends Selection {
29830
30071
  return new _NodeSelection($pos);
29831
30072
  }
29832
30073
  content() {
29833
- return new Slice(Fragment26.from(this.node), 0, 0);
30074
+ return new Slice(Fragment27.from(this.node), 0, 0);
29834
30075
  }
29835
30076
  eq(other) {
29836
30077
  return other instanceof _NodeSelection && other.anchor == this.anchor;
@@ -30558,10 +30799,10 @@ var CellSelection = class CellSelection2 extends Selection {
30558
30799
  }
30559
30800
  rowContent.push(cell);
30560
30801
  }
30561
- rows.push(table.child(row).copy(Fragment26.from(rowContent)));
30802
+ rows.push(table.child(row).copy(Fragment27.from(rowContent)));
30562
30803
  }
30563
30804
  const fragment = this.isColSelection() && this.isRowSelection() ? table : rows;
30564
- return new Slice(Fragment26.from(fragment), 1, 1);
30805
+ return new Slice(Fragment27.from(fragment), 1, 1);
30565
30806
  }
30566
30807
  replace(tr, content = Slice.empty) {
30567
30808
  const mapFrom = tr.steps.length, ranges = this.ranges;
@@ -30573,7 +30814,7 @@ var CellSelection = class CellSelection2 extends Selection {
30573
30814
  if (sel) tr.setSelection(sel);
30574
30815
  }
30575
30816
  replaceWith(tr, node) {
30576
- this.replace(tr, new Slice(Fragment26.from(node), 0, 0));
30817
+ this.replace(tr, new Slice(Fragment27.from(node), 0, 0));
30577
30818
  }
30578
30819
  forEachCell(f) {
30579
30820
  const table = this.$anchorCell.node(-1);