@12-apps/ui 6.24.8 → 6.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/dist/_internal/components/data-display/DataViews/DataViewsGrid.js +19 -19
  2. package/dist/_internal/components/data-display/DataViews/DataViewsTableBase.js +20 -20
  3. package/dist/_internal/components/data-display/DataViews/data-views-category-pill.js +15 -15
  4. package/dist/_internal/components/data-display/DataViews/data-views-filter-panel.js +16 -16
  5. package/dist/_internal/components/data-display/DataViews/data-views-grid-parts.js +18 -18
  6. package/dist/_internal/components/data-display/DataViews/data-views-inline-bar.js +16 -16
  7. package/dist/_internal/components/form/CategorySelect/CategoryPanel.js +8 -8
  8. package/dist/_internal/components/form/CategorySelect/CategoryPanelFoot.js +2 -2
  9. package/dist/_internal/components/form/CategorySelect/CategoryPanelHead.js +2 -2
  10. package/dist/_internal/components/form/CategorySelect/CategoryPanelList.js +4 -4
  11. package/dist/_internal/components/form/CategorySelect/CategoryQuickActions.js +2 -2
  12. package/dist/_internal/components/form/CategorySelect/CategoryRows.js +7 -9
  13. package/dist/_internal/components/form/CategorySelect/CategorySelect.js +14 -14
  14. package/dist/_internal/components/form/CategorySelect/CategorySelect.styles.js +3 -1
  15. package/dist/_internal/components/form/CategorySelect/CategoryTrigger.js +2 -2
  16. package/dist/_internal/components/form/CategorySelect/category-keyboard.js +2 -2
  17. package/dist/_internal/components/form/CategorySelect/category-tree.js +11 -3
  18. package/dist/_internal/components/form/CategorySelect/useCategoryCommit.js +2 -2
  19. package/dist/_internal/components/form/CategorySelect/useCategoryKeyHandler.js +3 -3
  20. package/dist/_internal/components/form/CategorySelect/useCategorySelect.js +2 -2
  21. package/dist/_internal/components/form/total-form/Fields/CategoryField.js +15 -15
  22. package/dist/_internal/components/form/total-form/Fields/index.js +16 -16
  23. package/dist/{chunk-NLJV4CPF.js → chunk-7MN6I5NK.js} +2 -2
  24. package/dist/{chunk-PN5CQKA2.js → chunk-AXTLFK4T.js} +2 -2
  25. package/dist/{chunk-4TXIZ5WI.js → chunk-CJUOBTLL.js} +2 -2
  26. package/dist/{chunk-E3PUH5IF.js → chunk-EQ7PWGBN.js} +2 -2
  27. package/dist/{chunk-EJQW2IYW.js → chunk-FPFUXRD2.js} +2 -2
  28. package/dist/{chunk-KIHQE5YA.js → chunk-GVDJQMFI.js} +2 -2
  29. package/dist/{chunk-OFOYMZRY.js → chunk-NPN7JTRM.js} +22 -47
  30. package/dist/chunk-NPN7JTRM.js.map +1 -0
  31. package/dist/{chunk-OVLNF4AZ.js → chunk-P7IVAMAU.js} +24 -35
  32. package/dist/chunk-P7IVAMAU.js.map +1 -0
  33. package/dist/chunk-PN4HVM43.js +160 -0
  34. package/dist/chunk-PN4HVM43.js.map +1 -0
  35. package/dist/{chunk-WWM2YTW4.js → chunk-R2AZOWEZ.js} +21 -27
  36. package/dist/chunk-R2AZOWEZ.js.map +1 -0
  37. package/dist/{chunk-2GB5CIN6.js → chunk-RZVUY2MO.js} +8 -4
  38. package/dist/chunk-RZVUY2MO.js.map +1 -0
  39. package/dist/{chunk-FBI6QB3O.js → chunk-TVPPA4RD.js} +3 -3
  40. package/dist/{chunk-ISH42UC7.js → chunk-USJPZ5Q7.js} +2 -2
  41. package/dist/{chunk-ZUIJ3N7N.js → chunk-V6Z4XS3I.js} +5 -3
  42. package/dist/chunk-V6Z4XS3I.js.map +1 -0
  43. package/dist/{chunk-JM64OEU6.js → chunk-WAPJ2DL3.js} +10 -13
  44. package/dist/chunk-WAPJ2DL3.js.map +1 -0
  45. package/dist/{chunk-KFWIOFMS.js → chunk-WM6Y2S6W.js} +2 -2
  46. package/dist/{chunk-ZAB65STX.js → chunk-XHHR6G35.js} +2 -2
  47. package/dist/{chunk-WIT3Y7JT.js → chunk-Y2B3I3IH.js} +2 -2
  48. package/dist/{chunk-R6SNYC3D.js → chunk-Y3KRUT7O.js} +2 -2
  49. package/dist/{chunk-TPLKJHNN.js → chunk-ZC7RQDZ5.js} +8 -7
  50. package/dist/chunk-ZC7RQDZ5.js.map +1 -0
  51. package/dist/{chunk-TFO6GBW7.js → chunk-ZS44PY7T.js} +5 -1
  52. package/dist/chunk-ZS44PY7T.js.map +1 -0
  53. package/dist/{chunk-AJ6XEO4E.js → chunk-ZUY65MFH.js} +2 -2
  54. package/dist/data-display/DataViews.js +20 -20
  55. package/dist/form/CategorySelect.js +24 -16
  56. package/dist/form/total-form.js +16 -16
  57. package/dist/types/components/form/CategorySelect/CategoryPanel.d.ts.map +1 -1
  58. package/dist/types/components/form/CategorySelect/CategoryPanelList.d.ts +6 -0
  59. package/dist/types/components/form/CategorySelect/CategoryPanelList.d.ts.map +1 -1
  60. package/dist/types/components/form/CategorySelect/CategoryQuickActions.d.ts.map +1 -1
  61. package/dist/types/components/form/CategorySelect/CategoryRows.d.ts +12 -24
  62. package/dist/types/components/form/CategorySelect/CategoryRows.d.ts.map +1 -1
  63. package/dist/types/components/form/CategorySelect/CategorySelect.d.ts +10 -7
  64. package/dist/types/components/form/CategorySelect/CategorySelect.d.ts.map +1 -1
  65. package/dist/types/components/form/CategorySelect/CategorySelect.styles.d.ts +11 -0
  66. package/dist/types/components/form/CategorySelect/CategorySelect.styles.d.ts.map +1 -1
  67. package/dist/types/components/form/CategorySelect/CategorySelect.types.d.ts +10 -2
  68. package/dist/types/components/form/CategorySelect/CategorySelect.types.d.ts.map +1 -1
  69. package/dist/types/components/form/CategorySelect/category-keyboard.d.ts.map +1 -1
  70. package/dist/types/components/form/CategorySelect/category-tree.d.ts +52 -20
  71. package/dist/types/components/form/CategorySelect/category-tree.d.ts.map +1 -1
  72. package/dist/types/components/form/CategorySelect/index.d.ts +1 -1
  73. package/dist/types/components/form/CategorySelect/index.d.ts.map +1 -1
  74. package/dist/types/components/form/CategorySelect/useCategorySelect.d.ts +2 -0
  75. package/dist/types/components/form/CategorySelect/useCategorySelect.d.ts.map +1 -1
  76. package/package.json +1 -1
  77. package/src/components/form/CategorySelect/CategoryPanel.tsx +1 -0
  78. package/src/components/form/CategorySelect/CategoryPanelList.tsx +42 -34
  79. package/src/components/form/CategorySelect/CategoryQuickActions.tsx +6 -4
  80. package/src/components/form/CategorySelect/CategoryRows.tsx +45 -81
  81. package/src/components/form/CategorySelect/CategorySelect.md +47 -13
  82. package/src/components/form/CategorySelect/CategorySelect.styles.ts +13 -0
  83. package/src/components/form/CategorySelect/CategorySelect.tsx +16 -14
  84. package/src/components/form/CategorySelect/CategorySelect.types.ts +10 -2
  85. package/src/components/form/CategorySelect/category-keyboard.ts +27 -31
  86. package/src/components/form/CategorySelect/category-tree.ts +143 -63
  87. package/src/components/form/CategorySelect/index.ts +4 -0
  88. package/src/components/form/CategorySelect/useCategorySelect.ts +15 -1
  89. package/dist/chunk-2GB5CIN6.js.map +0 -1
  90. package/dist/chunk-JM64OEU6.js.map +0 -1
  91. package/dist/chunk-LR6MSKTT.js +0 -124
  92. package/dist/chunk-LR6MSKTT.js.map +0 -1
  93. package/dist/chunk-OFOYMZRY.js.map +0 -1
  94. package/dist/chunk-OVLNF4AZ.js.map +0 -1
  95. package/dist/chunk-TFO6GBW7.js.map +0 -1
  96. package/dist/chunk-TPLKJHNN.js.map +0 -1
  97. package/dist/chunk-WWM2YTW4.js.map +0 -1
  98. package/dist/chunk-ZUIJ3N7N.js.map +0 -1
  99. /package/dist/{chunk-NLJV4CPF.js.map → chunk-7MN6I5NK.js.map} +0 -0
  100. /package/dist/{chunk-PN5CQKA2.js.map → chunk-AXTLFK4T.js.map} +0 -0
  101. /package/dist/{chunk-4TXIZ5WI.js.map → chunk-CJUOBTLL.js.map} +0 -0
  102. /package/dist/{chunk-E3PUH5IF.js.map → chunk-EQ7PWGBN.js.map} +0 -0
  103. /package/dist/{chunk-EJQW2IYW.js.map → chunk-FPFUXRD2.js.map} +0 -0
  104. /package/dist/{chunk-KIHQE5YA.js.map → chunk-GVDJQMFI.js.map} +0 -0
  105. /package/dist/{chunk-FBI6QB3O.js.map → chunk-TVPPA4RD.js.map} +0 -0
  106. /package/dist/{chunk-ISH42UC7.js.map → chunk-USJPZ5Q7.js.map} +0 -0
  107. /package/dist/{chunk-KFWIOFMS.js.map → chunk-WM6Y2S6W.js.map} +0 -0
  108. /package/dist/{chunk-ZAB65STX.js.map → chunk-XHHR6G35.js.map} +0 -0
  109. /package/dist/{chunk-WIT3Y7JT.js.map → chunk-Y2B3I3IH.js.map} +0 -0
  110. /package/dist/{chunk-R6SNYC3D.js.map → chunk-Y3KRUT7O.js.map} +0 -0
  111. /package/dist/{chunk-AJ6XEO4E.js.map → chunk-ZUY65MFH.js.map} +0 -0
@@ -1,25 +1,25 @@
1
1
  "use client";
2
2
  import {
3
3
  CategoryField
4
- } from "../../../../../chunk-WIT3Y7JT.js";
4
+ } from "../../../../../chunk-Y2B3I3IH.js";
5
5
  import "../../../../../chunk-4XK6JQ4D.js";
6
6
  import "../../../../../chunk-N5ZWC6CB.js";
7
- import "../../../../../chunk-JM64OEU6.js";
7
+ import "../../../../../chunk-WAPJ2DL3.js";
8
8
  import "../../../../../chunk-LMXWI3DD.js";
9
- import "../../../../../chunk-TPLKJHNN.js";
10
- import "../../../../../chunk-ZUIJ3N7N.js";
11
- import "../../../../../chunk-OVLNF4AZ.js";
12
- import "../../../../../chunk-4TXIZ5WI.js";
13
- import "../../../../../chunk-AJ6XEO4E.js";
14
- import "../../../../../chunk-ZAB65STX.js";
15
- import "../../../../../chunk-KIHQE5YA.js";
16
- import "../../../../../chunk-OFOYMZRY.js";
9
+ import "../../../../../chunk-ZC7RQDZ5.js";
10
+ import "../../../../../chunk-V6Z4XS3I.js";
11
+ import "../../../../../chunk-P7IVAMAU.js";
12
+ import "../../../../../chunk-CJUOBTLL.js";
13
+ import "../../../../../chunk-ZUY65MFH.js";
14
+ import "../../../../../chunk-XHHR6G35.js";
15
+ import "../../../../../chunk-GVDJQMFI.js";
16
+ import "../../../../../chunk-NPN7JTRM.js";
17
17
  import "../../../../../chunk-DMNZD3Q7.js";
18
- import "../../../../../chunk-TFO6GBW7.js";
19
- import "../../../../../chunk-2GB5CIN6.js";
20
- import "../../../../../chunk-ISH42UC7.js";
21
- import "../../../../../chunk-WWM2YTW4.js";
22
- import "../../../../../chunk-LR6MSKTT.js";
18
+ import "../../../../../chunk-ZS44PY7T.js";
19
+ import "../../../../../chunk-RZVUY2MO.js";
20
+ import "../../../../../chunk-USJPZ5Q7.js";
21
+ import "../../../../../chunk-R2AZOWEZ.js";
22
+ import "../../../../../chunk-PN4HVM43.js";
23
23
  import "../../../../../chunk-C3UKR3NT.js";
24
24
  import "../../../../../chunk-IPPTOL53.js";
25
25
  import "../../../../../chunk-7FDU3FIN.js";
@@ -1,4 +1,4 @@
1
- import "../../../../../chunk-R6SNYC3D.js";
1
+ import "../../../../../chunk-Y3KRUT7O.js";
2
2
  import {
3
3
  SelectField
4
4
  } from "../../../../../chunk-W4SDVTZC.js";
@@ -7,7 +7,7 @@ import {
7
7
  } from "../../../../../chunk-EOHKZGOZ.js";
8
8
  import {
9
9
  CategoryField
10
- } from "../../../../../chunk-WIT3Y7JT.js";
10
+ } from "../../../../../chunk-Y2B3I3IH.js";
11
11
  import {
12
12
  ToggleField
13
13
  } from "../../../../../chunk-LYMAMKJT.js";
@@ -23,22 +23,22 @@ import "../../../../../chunk-A7LG3AXV.js";
23
23
  import "../../../../../chunk-6XLMTOJ3.js";
24
24
  import "../../../../../chunk-FGK2C7JR.js";
25
25
  import "../../../../../chunk-N5ZWC6CB.js";
26
- import "../../../../../chunk-JM64OEU6.js";
26
+ import "../../../../../chunk-WAPJ2DL3.js";
27
27
  import "../../../../../chunk-LMXWI3DD.js";
28
- import "../../../../../chunk-TPLKJHNN.js";
29
- import "../../../../../chunk-ZUIJ3N7N.js";
30
- import "../../../../../chunk-OVLNF4AZ.js";
31
- import "../../../../../chunk-4TXIZ5WI.js";
32
- import "../../../../../chunk-AJ6XEO4E.js";
33
- import "../../../../../chunk-ZAB65STX.js";
34
- import "../../../../../chunk-KIHQE5YA.js";
35
- import "../../../../../chunk-OFOYMZRY.js";
28
+ import "../../../../../chunk-ZC7RQDZ5.js";
29
+ import "../../../../../chunk-V6Z4XS3I.js";
30
+ import "../../../../../chunk-P7IVAMAU.js";
31
+ import "../../../../../chunk-CJUOBTLL.js";
32
+ import "../../../../../chunk-ZUY65MFH.js";
33
+ import "../../../../../chunk-XHHR6G35.js";
34
+ import "../../../../../chunk-GVDJQMFI.js";
35
+ import "../../../../../chunk-NPN7JTRM.js";
36
36
  import "../../../../../chunk-DMNZD3Q7.js";
37
- import "../../../../../chunk-TFO6GBW7.js";
38
- import "../../../../../chunk-2GB5CIN6.js";
39
- import "../../../../../chunk-ISH42UC7.js";
40
- import "../../../../../chunk-WWM2YTW4.js";
41
- import "../../../../../chunk-LR6MSKTT.js";
37
+ import "../../../../../chunk-ZS44PY7T.js";
38
+ import "../../../../../chunk-RZVUY2MO.js";
39
+ import "../../../../../chunk-USJPZ5Q7.js";
40
+ import "../../../../../chunk-R2AZOWEZ.js";
41
+ import "../../../../../chunk-PN4HVM43.js";
42
42
  import "../../../../../chunk-QYKDY4EI.js";
43
43
  import "../../../../../chunk-4OHRZW7U.js";
44
44
  import "../../../../../chunk-S6YY2WWK.js";
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-5WNQJ5KS.js";
5
5
  import {
6
6
  PillControl
7
- } from "./chunk-EJQW2IYW.js";
7
+ } from "./chunk-FPFUXRD2.js";
8
8
  import {
9
9
  MoreFilters
10
10
  } from "./chunk-PFDM2OIP.js";
@@ -220,4 +220,4 @@ function FilterSlots({
220
220
  export {
221
221
  InlineFilterControls
222
222
  };
223
- //# sourceMappingURL=chunk-NLJV4CPF.js.map
223
+ //# sourceMappingURL=chunk-7MN6I5NK.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  PillControl
3
- } from "./chunk-EJQW2IYW.js";
3
+ } from "./chunk-FPFUXRD2.js";
4
4
  import {
5
5
  PanelRangeField
6
6
  } from "./chunk-DFLTUI7W.js";
@@ -154,4 +154,4 @@ export {
154
154
  GridFilterPanel,
155
155
  FilterDialog
156
156
  };
157
- //# sourceMappingURL=chunk-PN5CQKA2.js.map
157
+ //# sourceMappingURL=chunk-AXTLFK4T.js.map
@@ -7,7 +7,7 @@ import {
7
7
  panelHeadSx,
8
8
  pinnedLabelSx,
9
9
  pinnedSx
10
- } from "./chunk-TFO6GBW7.js";
10
+ } from "./chunk-ZS44PY7T.js";
11
11
 
12
12
  // src/components/form/CategorySelect/CategoryPanelHead.tsx
13
13
  import Box from "@mui/material/Box/index.js";
@@ -144,4 +144,4 @@ export {
144
144
  CategoryPanelHead,
145
145
  CategoryPinnedTray
146
146
  };
147
- //# sourceMappingURL=chunk-4TXIZ5WI.js.map
147
+ //# sourceMappingURL=chunk-CJUOBTLL.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  GridShell
3
- } from "./chunk-FBI6QB3O.js";
3
+ } from "./chunk-TVPPA4RD.js";
4
4
  import {
5
5
  useDataViewsState
6
6
  } from "./chunk-HEBQS7QP.js";
@@ -27,4 +27,4 @@ function DataViewsGrid(props) {
27
27
  export {
28
28
  DataViewsGrid
29
29
  };
30
- //# sourceMappingURL=chunk-E3PUH5IF.js.map
30
+ //# sourceMappingURL=chunk-EQ7PWGBN.js.map
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-4T6W43TO.js";
7
7
  import {
8
8
  CategorySelect
9
- } from "./chunk-JM64OEU6.js";
9
+ } from "./chunk-WAPJ2DL3.js";
10
10
 
11
11
  // src/components/data-display/DataViews/data-views-category-pill.tsx
12
12
  import { jsx } from "react/jsx-runtime";
@@ -79,4 +79,4 @@ export {
79
79
  emitPillDiff,
80
80
  PillControl
81
81
  };
82
- //# sourceMappingURL=chunk-EJQW2IYW.js.map
82
+ //# sourceMappingURL=chunk-FPFUXRD2.js.map
@@ -6,7 +6,7 @@ import {
6
6
  triggerClearSx,
7
7
  triggerCountSx,
8
8
  triggerSx
9
- } from "./chunk-TFO6GBW7.js";
9
+ } from "./chunk-ZS44PY7T.js";
10
10
 
11
11
  // src/components/form/CategorySelect/CategoryTrigger.tsx
12
12
  import Box from "@mui/material/Box/index.js";
@@ -88,4 +88,4 @@ function CategoryTrigger({
88
88
  export {
89
89
  CategoryTrigger
90
90
  };
91
- //# sourceMappingURL=chunk-KIHQE5YA.js.map
91
+ //# sourceMappingURL=chunk-GVDJQMFI.js.map
@@ -9,14 +9,15 @@ import {
9
9
  chevronButtonSx,
10
10
  markSx,
11
11
  radioSx,
12
+ rowIndent,
12
13
  rowMetaSx,
13
14
  rowNameSx,
14
15
  rowSx,
15
16
  sectionHeadSx
16
- } from "./chunk-TFO6GBW7.js";
17
+ } from "./chunk-ZS44PY7T.js";
17
18
  import {
18
19
  highlightSegments
19
- } from "./chunk-LR6MSKTT.js";
20
+ } from "./chunk-PN4HVM43.js";
20
21
 
21
22
  // src/components/form/CategorySelect/CategoryRows.tsx
22
23
  import Box from "@mui/material/Box/index.js";
@@ -44,15 +45,15 @@ function rowMeta(selectedCount, showCounts, count) {
44
45
  if (showCounts && count !== void 0) return { text: String(count), selected: false };
45
46
  return null;
46
47
  }
47
- function HeadRowDisclosure({
48
+ function RowDisclosure({
48
49
  option,
49
50
  expanded,
50
- expandable,
51
+ branch,
51
52
  onToggleExpanded,
52
53
  dataTestId,
53
54
  copy
54
55
  }) {
55
- if (!expandable) {
56
+ if (!branch) {
56
57
  return /* @__PURE__ */ jsx(Box, { sx: { width: METRICS.chevronButton, flex: "0 0 auto" } });
57
58
  }
58
59
  return /* @__PURE__ */ jsx(
@@ -72,7 +73,7 @@ function HeadRowDisclosure({
72
73
  }
73
74
  );
74
75
  }
75
- function HeadRowControl({
76
+ function RowControl({
76
77
  checkState,
77
78
  single
78
79
  }) {
@@ -80,15 +81,19 @@ function HeadRowControl({
80
81
  if (single) return /* @__PURE__ */ jsx(CategoryRadio, { on: checkState === "on" });
81
82
  return /* @__PURE__ */ jsx(CategoryCheckbox, { state: checkState });
82
83
  }
83
- function CategoryHeadRow({
84
+ function rowTestId(dataTestId, depth, id) {
85
+ return depth === 0 ? `${dataTestId}-category-${id}` : `${dataTestId}-option-${id}`;
86
+ }
87
+ function CategoryTreeRow({
84
88
  option,
85
89
  query,
90
+ depth,
91
+ branch,
86
92
  expanded,
87
93
  active,
88
94
  sheet,
89
95
  checkState,
90
96
  single,
91
- expandable,
92
97
  selectedCount,
93
98
  showCounts,
94
99
  onToggleExpanded,
@@ -103,58 +108,29 @@ function CategoryHeadRow({
103
108
  component: "div",
104
109
  role: checkState ? "option" : "button",
105
110
  "aria-selected": checkState ? checkState === "on" : void 0,
106
- "aria-expanded": expandable ? expanded : void 0,
107
- "data-testid": `${dataTestId}-category-${option.id}`,
108
- sx: (theme) => rowSx(theme, active, sheet),
111
+ "aria-expanded": branch ? expanded : void 0,
112
+ "data-testid": rowTestId(dataTestId, depth, option.id),
113
+ sx: (theme) => ({ ...rowSx(theme, active, sheet), ...rowIndent(depth) }),
109
114
  onClick: onActivate,
110
115
  children: [
111
116
  /* @__PURE__ */ jsx(
112
- HeadRowDisclosure,
117
+ RowDisclosure,
113
118
  {
114
119
  option,
115
120
  expanded,
116
- expandable,
121
+ branch,
117
122
  onToggleExpanded,
118
123
  dataTestId,
119
124
  copy
120
125
  }
121
126
  ),
122
- /* @__PURE__ */ jsx(HeadRowControl, { checkState, single }),
123
- /* @__PURE__ */ jsx(Box, { component: "span", sx: (theme) => rowNameSx(theme, true), children: /* @__PURE__ */ jsx(HighlightedName, { text: option.name, query }) }),
127
+ /* @__PURE__ */ jsx(RowControl, { checkState, single }),
128
+ /* @__PURE__ */ jsx(Box, { component: "span", sx: (theme) => rowNameSx(theme, depth === 0), children: /* @__PURE__ */ jsx(HighlightedName, { text: option.name, query }) }),
124
129
  meta && /* @__PURE__ */ jsx(Box, { component: "span", sx: (theme) => rowMetaSx(theme, meta.selected), children: meta.text })
125
130
  ]
126
131
  }
127
132
  );
128
133
  }
129
- function SubcategoryRow({
130
- option,
131
- query,
132
- selected,
133
- active,
134
- sheet,
135
- single,
136
- showCounts,
137
- onActivate,
138
- dataTestId
139
- }) {
140
- return /* @__PURE__ */ jsxs(
141
- Box,
142
- {
143
- component: "div",
144
- role: "option",
145
- "aria-selected": selected,
146
- "data-testid": `${dataTestId}-option-${option.id}`,
147
- sx: (theme) => ({ ...rowSx(theme, active, sheet), paddingLeft: "14px" }),
148
- onClick: onActivate,
149
- children: [
150
- /* @__PURE__ */ jsx(Box, { sx: { width: METRICS.chevronButton, flex: "0 0 auto" } }),
151
- single ? /* @__PURE__ */ jsx(CategoryRadio, { on: selected }) : /* @__PURE__ */ jsx(CategoryCheckbox, { state: selected ? "on" : "off" }),
152
- /* @__PURE__ */ jsx(Box, { component: "span", sx: (theme) => rowNameSx(theme, false), children: /* @__PURE__ */ jsx(HighlightedName, { text: option.name, query }) }),
153
- showCounts && option.count !== void 0 && /* @__PURE__ */ jsx(Box, { component: "span", sx: (theme) => rowMetaSx(theme, false), children: option.count })
154
- ]
155
- }
156
- );
157
- }
158
134
  function CategorySectionHeading({
159
135
  option,
160
136
  query
@@ -166,8 +142,7 @@ export {
166
142
  HighlightedName,
167
143
  CategoryCheckbox,
168
144
  CategoryRadio,
169
- CategoryHeadRow,
170
- SubcategoryRow,
145
+ CategoryTreeRow,
171
146
  CategorySectionHeading
172
147
  };
173
- //# sourceMappingURL=chunk-OFOYMZRY.js.map
148
+ //# sourceMappingURL=chunk-NPN7JTRM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/form/CategorySelect/CategoryRows.tsx"],"sourcesContent":["'use client';\n\nimport Box from '@mui/material/Box/index.js';\n\nimport type { CategorySelectCopy } from '../../../copy';\nimport { CheckGlyph, DisclosureGlyph } from './CategoryIcons';\nimport { highlightSegments, type CategoryCheckState } from './category-tree';\nimport {\n checkboxBarSx,\n checkboxSx,\n chevronButtonSx,\n markSx,\n METRICS,\n radioSx,\n rowIndent,\n rowMetaSx,\n rowNameSx,\n rowSx,\n sectionHeadSx,\n} from './CategorySelect.styles';\nimport type { CategorySelectOption } from './CategorySelect.types';\n\n/** A label with the search hit marked. */\nexport function HighlightedName({\n text,\n query,\n}: {\n text: string;\n query: string;\n}): React.JSX.Element {\n const segments = highlightSegments(text, query);\n return (\n <>\n {segments.map((segment, index) =>\n segment.match ? (\n <Box component=\"mark\" key={`${segment.text}-${index}`} sx={markSx}>\n {segment.text}\n </Box>\n ) : (\n <span key={`${segment.text}-${index}`}>{segment.text}</span>\n ),\n )}\n </>\n );\n}\n\n/** Tri-state checkbox. `partial` draws the bar the prototype uses for \"some\". */\nexport function CategoryCheckbox({ state }: { state: CategoryCheckState }): React.JSX.Element {\n return (\n <Box sx={(theme) => checkboxSx(theme, state)} aria-hidden=\"true\">\n {state === 'on' && <CheckGlyph />}\n {state === 'partial' && <Box sx={checkboxBarSx} />}\n </Box>\n );\n}\n\nexport function CategoryRadio({ on }: { on: boolean }): React.JSX.Element {\n return <Box sx={(theme) => radioSx(theme, on)} aria-hidden=\"true\" />;\n}\n\ninterface CategoryTreeRowProps {\n option: CategorySelectOption;\n query: string;\n /** 0 for a top-level category; each level below indents one more step. */\n depth: number;\n /** True when there is something under this row to fold. */\n branch: boolean;\n expanded: boolean;\n active: boolean;\n sheet: boolean;\n /** Absent where the row cannot be picked — a category acting as a frame. */\n checkState?: CategoryCheckState;\n /** Single-select draws a radio for the control: choosing a row is exclusive. */\n single: boolean;\n selectedCount: number;\n showCounts: boolean;\n onToggleExpanded: () => void;\n onActivate: () => void;\n dataTestId: string;\n copy: CategorySelectCopy;\n}\n\n/** The trailing number: how many leaves are picked below, else the item count. */\nfunction rowMeta(\n selectedCount: number,\n showCounts: boolean,\n count: number | undefined,\n): { text: string; selected: boolean } | null {\n if (selectedCount > 0) return { text: String(selectedCount), selected: true };\n if (showCounts && count !== undefined) return { text: String(count), selected: false };\n return null;\n}\n\n/** The disclosure chevron, or the space it would have taken on a leaf row. */\nfunction RowDisclosure({\n option,\n expanded,\n branch,\n onToggleExpanded,\n dataTestId,\n copy,\n}: Pick<\n CategoryTreeRowProps,\n 'option' | 'expanded' | 'branch' | 'onToggleExpanded' | 'dataTestId' | 'copy'\n>): React.JSX.Element {\n if (!branch) {\n return <Box sx={{ width: METRICS.chevronButton, flex: '0 0 auto' }} />;\n }\n return (\n <Box\n component=\"button\"\n type=\"button\"\n tabIndex={-1}\n aria-label={expanded ? copy.collapseCategory(option.name) : copy.expandCategory(option.name)}\n data-testid={`${dataTestId}-expand-${option.id}`}\n sx={(theme) => chevronButtonSx(theme, expanded)}\n onClick={(event: React.MouseEvent) => {\n event.stopPropagation();\n onToggleExpanded();\n }}\n >\n <DisclosureGlyph />\n </Box>\n );\n}\n\n/** The row's selection control, or the space it would have taken on a frame. */\nfunction RowControl({\n checkState,\n single,\n}: Pick<CategoryTreeRowProps, 'checkState' | 'single'>): React.JSX.Element {\n if (!checkState) return <Box sx={{ width: METRICS.boxSize, flex: '0 0 auto' }} />;\n // Single-select commits the moment a row is chosen, so the control is a radio\n // there: a checkbox would promise the accumulation this mode does not do.\n if (single) return <CategoryRadio on={checkState === 'on'} />;\n return <CategoryCheckbox state={checkState} />;\n}\n\n/**\n * The test id a row answers to.\n *\n * Keyed on DEPTH rather than on whether the row has children, because that is\n * what the ids meant when the tree was two levels and specs were written against\n * them: `-category-<id>` is a top-level row — childless or not — and `-option-`\n * is anything filed under one.\n */\nfunction rowTestId(dataTestId: string, depth: number, id: string): string {\n return depth === 0 ? `${dataTestId}-category-${id}` : `${dataTestId}-option-${id}`;\n}\n\n/**\n * One row of the tree: disclosure chevron, optional control, name, meta.\n *\n * The chevron is its OWN button inside the row — clicking it only folds, while\n * clicking the row does the row's job (expand as a frame, or mark when the row\n * is selectable). A LEAF has neither a fold nor a frame to be: it draws no\n * chevron, and it always carries the control, because it is what you pick.\n */\nexport function CategoryTreeRow({\n option,\n query,\n depth,\n branch,\n expanded,\n active,\n sheet,\n checkState,\n single,\n selectedCount,\n showCounts,\n onToggleExpanded,\n onActivate,\n dataTestId,\n copy,\n}: CategoryTreeRowProps): React.JSX.Element {\n const meta = rowMeta(selectedCount, showCounts, option.count);\n return (\n <Box\n component=\"div\"\n role={checkState ? 'option' : 'button'}\n aria-selected={checkState ? checkState === 'on' : undefined}\n aria-expanded={branch ? expanded : undefined}\n data-testid={rowTestId(dataTestId, depth, option.id)}\n sx={(theme) => ({ ...rowSx(theme, active, sheet), ...rowIndent(depth) })}\n onClick={onActivate}\n >\n <RowDisclosure\n option={option}\n expanded={expanded}\n branch={branch}\n onToggleExpanded={onToggleExpanded}\n dataTestId={dataTestId}\n copy={copy}\n />\n <RowControl checkState={checkState} single={single} />\n <Box component=\"span\" sx={(theme) => rowNameSx(theme, depth === 0)}>\n <HighlightedName text={option.name} query={query} />\n </Box>\n {meta && (\n <Box component=\"span\" sx={(theme) => rowMetaSx(theme, meta.selected)}>\n {meta.text}\n </Box>\n )}\n </Box>\n );\n}\n\n/** The category as a non-interactive heading (single-select, leaf-only). */\nexport function CategorySectionHeading({\n option,\n query,\n}: {\n option: CategorySelectOption;\n query: string;\n}): React.JSX.Element {\n return (\n <Box sx={sectionHeadSx}>\n <HighlightedName text={option.name} query={query} />\n </Box>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1,17 +1,17 @@
1
1
  import {
2
- CategoryHeadRow,
3
2
  CategorySectionHeading,
4
- SubcategoryRow
5
- } from "./chunk-OFOYMZRY.js";
3
+ CategoryTreeRow
4
+ } from "./chunk-NPN7JTRM.js";
6
5
  import {
7
6
  emptySx,
8
7
  listSx,
9
8
  skeletonSx
10
- } from "./chunk-TFO6GBW7.js";
9
+ } from "./chunk-ZS44PY7T.js";
11
10
  import {
12
11
  categoryCheckState,
13
- isLeafCategory
14
- } from "./chunk-LR6MSKTT.js";
12
+ isLeafCategory,
13
+ leavesOf
14
+ } from "./chunk-PN4HVM43.js";
15
15
 
16
16
  // src/components/form/CategorySelect/CategoryPanelList.tsx
17
17
  import Box from "@mui/material/Box/index.js";
@@ -60,51 +60,40 @@ function NoResults({
60
60
  ] })
61
61
  ] });
62
62
  }
63
- function CategoryGroupRows({
64
- group,
63
+ function CategoryNodeRows({
64
+ node,
65
+ depth,
65
66
  props
66
67
  }) {
67
68
  const { draft, query, single, allowParentSelection, rowIds, activeIndex, sheet } = props;
68
- const categoryId = group.category.id;
69
+ const categoryId = node.category.id;
70
+ const leaf = isLeafCategory(node);
69
71
  const expanded = props.isExpanded(categoryId);
70
- const selectable = allowParentSelection || isLeafCategory(group);
71
- const asHeading = single && !selectable;
72
- const selectedCount = group.subcategories.filter((sub) => draft.has(sub.id)).length;
72
+ const selectable = allowParentSelection || leaf;
73
+ const asHeading = single && !selectable && !props.deepTree;
74
+ const selectedCount = leaf ? 0 : leavesOf(node).filter((id) => draft.has(id)).length;
73
75
  return /* @__PURE__ */ jsxs(Fragment, { children: [
74
- asHeading ? /* @__PURE__ */ jsx(CategorySectionHeading, { option: group.category, query }) : /* @__PURE__ */ jsx(
75
- CategoryHeadRow,
76
+ asHeading ? /* @__PURE__ */ jsx(CategorySectionHeading, { option: node.category, query }) : /* @__PURE__ */ jsx(
77
+ CategoryTreeRow,
76
78
  {
77
- option: group.category,
79
+ option: node.category,
78
80
  query,
81
+ depth,
82
+ branch: !leaf,
79
83
  expanded,
80
84
  active: rowIds[activeIndex] === categoryId,
81
85
  sheet,
82
- checkState: selectable ? categoryCheckState(group, draft) : void 0,
86
+ ...selectable ? { checkState: categoryCheckState(node, draft) } : {},
83
87
  single,
84
- expandable: !isLeafCategory(group),
85
88
  selectedCount,
86
89
  showCounts: props.showCounts,
87
90
  onToggleExpanded: () => props.onToggleExpanded(categoryId),
88
- onActivate: () => props.onActivateCategory(group),
91
+ onActivate: () => leaf ? props.onActivateSubcategory(categoryId) : props.onActivateCategory(node),
89
92
  dataTestId: props.dataTestId,
90
93
  copy: props.copy
91
94
  }
92
95
  ),
93
- (expanded || asHeading) && group.subcategories.map((sub) => /* @__PURE__ */ jsx(
94
- SubcategoryRow,
95
- {
96
- option: sub,
97
- query,
98
- selected: draft.has(sub.id),
99
- active: rowIds[activeIndex] === sub.id,
100
- sheet,
101
- single,
102
- showCounts: props.showCounts,
103
- onActivate: () => props.onActivateSubcategory(sub.id),
104
- dataTestId: props.dataTestId
105
- },
106
- sub.id
107
- ))
96
+ (expanded || asHeading) && node.subcategories.map((sub) => /* @__PURE__ */ jsx(CategoryNodeRows, { node: sub, depth: depth + 1, props }, sub.category.id))
108
97
  ] });
109
98
  }
110
99
  function CategoryPanelList(props) {
@@ -133,7 +122,7 @@ function CategoryPanelList(props) {
133
122
  }
134
123
  );
135
124
  }
136
- return /* @__PURE__ */ jsx(Fragment, { children: groups.map((group) => /* @__PURE__ */ jsx(CategoryGroupRows, { group, props }, group.category.id)) });
125
+ return /* @__PURE__ */ jsx(Fragment, { children: groups.map((group) => /* @__PURE__ */ jsx(CategoryNodeRows, { node: group, depth: 0, props }, group.category.id)) });
137
126
  };
138
127
  return /* @__PURE__ */ jsx(
139
128
  Box,
@@ -152,4 +141,4 @@ function CategoryPanelList(props) {
152
141
  export {
153
142
  CategoryPanelList
154
143
  };
155
- //# sourceMappingURL=chunk-OVLNF4AZ.js.map
144
+ //# sourceMappingURL=chunk-P7IVAMAU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/form/CategorySelect/CategoryPanelList.tsx"],"sourcesContent":["'use client';\n\nimport type { CategorySelectCopy } from \"../../../copy\";\nimport Box from '@mui/material/Box/index.js';\nimport Button from '@mui/material/Button/index.js';\nimport Skeleton from '@mui/material/Skeleton/index.js';\n\nimport { categoryCheckState, isLeafCategory, leavesOf } from './category-tree';\nimport { CategorySectionHeading, CategoryTreeRow } from './CategoryRows';\nimport { emptySx, listSx, skeletonSx } from './CategorySelect.styles';\nimport type { CategoryGroup } from './CategorySelect.types';\n\n/** The design sets these labels in sentence case, not MUI's default caps. */\nconst SENTENCE_CASE = { textTransform: 'none' } as const;\n\n/** How many skeleton rows stand in for the catalogue while it loads. */\nconst SKELETON_ROWS = 6;\n\ninterface PanelListProps {\n /** The words this panel renders. REQUIRED — no default copy. */\n copy: CategorySelectCopy;\n groups: CategoryGroup[];\n query: string;\n draft: ReadonlySet<string>;\n rowIds: string[];\n activeIndex: number;\n sheet: boolean;\n single: boolean;\n loading: boolean;\n showCounts: boolean;\n allowParentSelection: boolean;\n /**\n * True when the tree has a level BELOW the subcategories. It turns the\n * section-heading treatment off — see {@link CategoryNodeRows}. Derived from\n * the options the panel state already holds, never a caller's decision.\n */\n deepTree: boolean;\n isExpanded: (categoryId: string) => boolean;\n onToggleExpanded: (categoryId: string) => void;\n onActivateCategory: (group: CategoryGroup) => void;\n onActivateSubcategory: (id: string) => void;\n onClearQuery: () => void;\n onCreateCategory?: (name?: string) => void;\n listRef: React.RefObject<HTMLDivElement | null>;\n dataTestId: string;\n}\n\nfunction LoadingRows(): React.JSX.Element {\n return (\n <>\n {Array.from({ length: SKELETON_ROWS }, (_unused, index) => (\n <Skeleton key={index} variant=\"rounded\" sx={skeletonSx} />\n ))}\n </>\n );\n}\n\n/** No categories exist at all — an onboarding moment, not an error. */\nfunction EmptyCatalogue({\n onCreateCategory,\n dataTestId,\n copy,\n}: {\n onCreateCategory?: (name?: string) => void;\n dataTestId: string;\n copy: CategorySelectCopy;\n}): React.JSX.Element {\n return (\n <Box sx={emptySx} data-testid={`${dataTestId}-empty-catalogue`}>\n <strong>{copy.emptyTitle}</strong>\n <p>{copy.purpose}</p>\n {onCreateCategory && (\n <Button variant=\"contained\" size=\"small\" sx={SENTENCE_CASE} onClick={() => onCreateCategory()}>\n {copy.createCategory}\n </Button>\n )}\n </Box>\n );\n}\n\n/** The search found nothing — offer creation, or the way back. */\nfunction NoResults({\n query,\n onClearQuery,\n onCreateCategory,\n dataTestId,\n copy,\n}: {\n query: string;\n onClearQuery: () => void;\n onCreateCategory?: (name?: string) => void;\n dataTestId: string;\n copy: CategorySelectCopy;\n}): React.JSX.Element {\n return (\n <Box sx={emptySx} data-testid={`${dataTestId}-no-results`}>\n <strong>{copy.noResults.title(query)}</strong>\n <p>{copy.noResults.hint}</p>\n <Box sx={{ display: 'flex', gap: '6px', justifyContent: 'center' }}>\n <Button variant=\"outlined\" size=\"small\" sx={SENTENCE_CASE} onClick={onClearQuery}>\n {copy.noResults.clearSearch}\n </Button>\n {onCreateCategory && (\n <Button\n variant=\"contained\"\n size=\"small\"\n sx={SENTENCE_CASE}\n data-testid={`${dataTestId}-create`}\n onClick={() => onCreateCategory(query.trim())}\n >\n {copy.noResults.create(query.trim())}\n </Button>\n )}\n </Box>\n </Box>\n );\n}\n\n/**\n * One node: its heading or its row, then whichever children are visible.\n *\n * The SECTION-HEADING treatment — an inert uppercase label with its children\n * always on show — belongs to a two-level tree and only there. It is what makes\n * the \"mover para…\" picker read as \"category, then the subcategory you pick\",\n * and it works because a two-level category has nothing to fold TO: everything\n * under it is already the thing you came for. A third level breaks both halves\n * at once — the heading has no chevron, so the panel opens onto every item in\n * the catalogue, which is the flat list this component exists to replace. So a\n * deep tree drops the treatment and every frame becomes a foldable row instead.\n */\nfunction CategoryNodeRows({\n node,\n depth,\n props,\n}: {\n node: CategoryGroup;\n depth: number;\n props: PanelListProps;\n}): React.JSX.Element {\n const { draft, query, single, allowParentSelection, rowIds, activeIndex, sheet } = props;\n const categoryId = node.category.id;\n const leaf = isLeafCategory(node);\n const expanded = props.isExpanded(categoryId);\n // A childless category is the leaf, so it is selectable whatever the mode says\n // — the heading reading has no subcategory to point at, and would leave the\n // row inert.\n const selectable = allowParentSelection || leaf;\n const asHeading = single && !selectable && !props.deepTree;\n const selectedCount = leaf ? 0 : leavesOf(node).filter((id) => draft.has(id)).length;\n\n return (\n <>\n {asHeading ? (\n <CategorySectionHeading option={node.category} query={query} />\n ) : (\n <CategoryTreeRow\n option={node.category}\n query={query}\n depth={depth}\n branch={!leaf}\n expanded={expanded}\n active={rowIds[activeIndex] === categoryId}\n sheet={sheet}\n {...(selectable ? { checkState: categoryCheckState(node, draft) } : {})}\n single={single}\n selectedCount={selectedCount}\n showCounts={props.showCounts}\n onToggleExpanded={() => props.onToggleExpanded(categoryId)}\n onActivate={() =>\n leaf ? props.onActivateSubcategory(categoryId) : props.onActivateCategory(node)\n }\n dataTestId={props.dataTestId}\n copy={props.copy}\n />\n )}\n {(expanded || asHeading) &&\n node.subcategories.map((sub) => (\n <CategoryNodeRows key={sub.category.id} node={sub} depth={depth + 1} props={props} />\n ))}\n </>\n );\n}\n\n/** The scrolling body of the panel, including its three non-list states. */\nexport function CategoryPanelList(props: PanelListProps): React.JSX.Element {\n const { groups, loading, query, listRef, sheet, dataTestId, copy } = props;\n\n const body = (): React.JSX.Element => {\n if (loading) return <LoadingRows />;\n if (groups.length === 0 && query.trim().length > 0) {\n return (\n <NoResults copy={copy}\n query={query}\n onClearQuery={props.onClearQuery}\n onCreateCategory={props.onCreateCategory}\n dataTestId={dataTestId}\n />\n );\n }\n if (groups.length === 0) {\n return (\n <EmptyCatalogue copy={copy}\n onCreateCategory={props.onCreateCategory}\n dataTestId={dataTestId}\n />\n );\n }\n return (\n <>\n {groups.map((group) => (\n <CategoryNodeRows key={group.category.id} node={group} depth={0} props={props} />\n ))}\n </>\n );\n };\n\n return (\n <Box\n ref={listRef}\n role=\"listbox\"\n aria-multiselectable={props.single ? undefined : true}\n tabIndex={-1}\n data-testid={`${dataTestId}-list`}\n sx={listSx(sheet)}\n >\n {body()}\n </Box>\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,160 @@
1
+ // src/components/form/CategorySelect/category-tree.ts
2
+ function foldText(text) {
3
+ return text.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase();
4
+ }
5
+ function onParentCycle(startId, parents) {
6
+ const seen = /* @__PURE__ */ new Set([startId]);
7
+ let current = parents.get(startId);
8
+ while (current !== void 0) {
9
+ if (seen.has(current)) return true;
10
+ seen.add(current);
11
+ current = parents.get(current);
12
+ }
13
+ return false;
14
+ }
15
+ function buildCategoryGroups(options) {
16
+ const nodes = /* @__PURE__ */ new Map();
17
+ const parents = /* @__PURE__ */ new Map();
18
+ options.forEach((option) => {
19
+ if (nodes.has(option.id)) return;
20
+ nodes.set(option.id, { category: option, subcategories: [] });
21
+ if (option.parentId && option.parentId !== option.id) parents.set(option.id, option.parentId);
22
+ });
23
+ const roots = [];
24
+ nodes.forEach((node, id) => {
25
+ const parentId = parents.get(id);
26
+ const parent = parentId === void 0 ? void 0 : nodes.get(parentId);
27
+ if (parent && !onParentCycle(id, parents)) parent.subcategories.push(node);
28
+ else roots.push(node);
29
+ });
30
+ return roots;
31
+ }
32
+ function isLeafCategory(group) {
33
+ return group.subcategories.length === 0;
34
+ }
35
+ function collectLeafIds(groups) {
36
+ return groups.flatMap((group) => leavesOf(group));
37
+ }
38
+ function leavesOf(group) {
39
+ if (isLeafCategory(group)) return [group.category.id];
40
+ return group.subcategories.flatMap((sub) => leavesOf(sub));
41
+ }
42
+ function collectBranchIds(groups) {
43
+ return groups.flatMap(
44
+ (group) => isLeafCategory(group) ? [] : [group.category.id, ...collectBranchIds(group.subcategories)]
45
+ );
46
+ }
47
+ function findGroup(groups, id) {
48
+ for (const group of groups) {
49
+ if (group.category.id === id) return group;
50
+ const found = findGroup(group.subcategories, id);
51
+ if (found) return found;
52
+ }
53
+ return void 0;
54
+ }
55
+ function categoryPath(groups, id) {
56
+ for (const group of groups) {
57
+ if (group.category.id === id) return [group.category.name];
58
+ const below = categoryPath(group.subcategories, id);
59
+ if (below) return [group.category.name, ...below];
60
+ }
61
+ return null;
62
+ }
63
+ function treeDepth(groups) {
64
+ return groups.reduce(
65
+ (deepest, group) => Math.max(deepest, 1 + treeDepth(group.subcategories)),
66
+ 0
67
+ );
68
+ }
69
+ function categoryCheckState(group, selected) {
70
+ const leaves = leavesOf(group);
71
+ const hits = leaves.filter((id) => selected.has(id)).length;
72
+ if (hits === 0) return "off";
73
+ return hits === leaves.length ? "on" : "partial";
74
+ }
75
+ function toggleCategoryLeaves(group, selected) {
76
+ const next = new Set(selected);
77
+ const leaves = leavesOf(group);
78
+ const turningOff = categoryCheckState(group, selected) === "on";
79
+ leaves.forEach((id) => turningOff ? next.delete(id) : next.add(id));
80
+ return next;
81
+ }
82
+ function toggleLeaf(id, selected) {
83
+ const next = new Set(selected);
84
+ if (!next.delete(id)) next.add(id);
85
+ return next;
86
+ }
87
+ function summarizeSelection(groups, selected) {
88
+ return groups.flatMap((group) => {
89
+ const state = categoryCheckState(group, selected);
90
+ if (state === "off") return [];
91
+ if (state === "on") {
92
+ return [
93
+ { id: group.category.id, label: group.category.name, whole: !isLeafCategory(group) }
94
+ ];
95
+ }
96
+ return summarizeSelection(group.subcategories, selected);
97
+ });
98
+ }
99
+ function removeChip(groups, chipId, selected) {
100
+ const next = new Set(selected);
101
+ const group = findGroup(groups, chipId);
102
+ if (group) {
103
+ leavesOf(group).forEach((id) => next.delete(id));
104
+ return next;
105
+ }
106
+ next.delete(chipId);
107
+ return next;
108
+ }
109
+ function filterCategoryGroups(groups, query) {
110
+ const needle = foldText(query.trim());
111
+ if (!needle) return groups;
112
+ const walk = (nodes) => nodes.flatMap((node) => {
113
+ if (foldText(node.category.name).includes(needle)) return [node];
114
+ const subcategories = walk(node.subcategories);
115
+ return subcategories.length > 0 ? [{ category: node.category, subcategories }] : [];
116
+ });
117
+ return walk(groups);
118
+ }
119
+ function highlightSegments(text, query) {
120
+ const needle = foldText(query.trim());
121
+ if (!needle) return [{ text, match: false }];
122
+ const at = foldText(text).indexOf(needle);
123
+ if (at < 0) return [{ text, match: false }];
124
+ return [
125
+ { text: text.slice(0, at), match: false },
126
+ { text: text.slice(at, at + needle.length), match: true },
127
+ { text: text.slice(at + needle.length), match: false }
128
+ ].filter((segment) => segment.text.length > 0);
129
+ }
130
+ function flattenRows(groups, isExpanded) {
131
+ const walk = (nodes, depth, parentId) => nodes.flatMap((node) => {
132
+ const id = node.category.id;
133
+ const branch = !isLeafCategory(node);
134
+ const row = { id, depth, branch, ...parentId ? { parentId } : {} };
135
+ if (!branch || !isExpanded(id)) return [row];
136
+ return [row, ...walk(node.subcategories, depth + 1, id)];
137
+ });
138
+ return walk(groups, 0);
139
+ }
140
+
141
+ export {
142
+ foldText,
143
+ buildCategoryGroups,
144
+ isLeafCategory,
145
+ collectLeafIds,
146
+ leavesOf,
147
+ collectBranchIds,
148
+ findGroup,
149
+ categoryPath,
150
+ treeDepth,
151
+ categoryCheckState,
152
+ toggleCategoryLeaves,
153
+ toggleLeaf,
154
+ summarizeSelection,
155
+ removeChip,
156
+ filterCategoryGroups,
157
+ highlightSegments,
158
+ flattenRows
159
+ };
160
+ //# sourceMappingURL=chunk-PN4HVM43.js.map