@rebasepro/ui 0.24.0 → 0.24.1-canary.gcb918fc

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 (241) hide show
  1. package/dist/components/Alert.d.ts +6 -0
  2. package/dist/components/Alert.es.js +82 -0
  3. package/dist/components/Alert.es.js.map +1 -0
  4. package/dist/components/Autocomplete.es.js +53 -0
  5. package/dist/components/Autocomplete.es.js.map +1 -0
  6. package/dist/components/Avatar.d.ts +3 -1
  7. package/dist/components/Avatar.es.js +37 -0
  8. package/dist/components/Avatar.es.js.map +1 -0
  9. package/dist/components/Badge.es.js +27 -0
  10. package/dist/components/Badge.es.js.map +1 -0
  11. package/dist/components/BooleanSwitch.es.js +75 -0
  12. package/dist/components/BooleanSwitch.es.js.map +1 -0
  13. package/dist/components/BooleanSwitchWithLabel.es.js +55 -0
  14. package/dist/components/BooleanSwitchWithLabel.es.js.map +1 -0
  15. package/dist/components/Button.es.js +58 -0
  16. package/dist/components/Button.es.js.map +1 -0
  17. package/dist/components/Card.es.js +26 -0
  18. package/dist/components/Card.es.js.map +1 -0
  19. package/dist/components/CenteredView.es.js +23 -0
  20. package/dist/components/CenteredView.es.js.map +1 -0
  21. package/dist/components/Checkbox.es.js +62 -0
  22. package/dist/components/Checkbox.es.js.map +1 -0
  23. package/dist/components/Chip.es.js +72 -0
  24. package/dist/components/Chip.es.js.map +1 -0
  25. package/dist/components/CircularProgress.es.js +28 -0
  26. package/dist/components/CircularProgress.es.js.map +1 -0
  27. package/dist/components/CircularProgressCenter.es.js +30 -0
  28. package/dist/components/CircularProgressCenter.es.js.map +1 -0
  29. package/dist/components/Collapse.es.js +57 -0
  30. package/dist/components/Collapse.es.js.map +1 -0
  31. package/dist/components/ColorPicker.es.js +89 -0
  32. package/dist/components/ColorPicker.es.js.map +1 -0
  33. package/dist/components/Container.es.js +31 -0
  34. package/dist/components/Container.es.js.map +1 -0
  35. package/dist/components/DateTimeField.d.ts +11 -1
  36. package/dist/components/DateTimeField.es.js +253 -0
  37. package/dist/components/DateTimeField.es.js.map +1 -0
  38. package/dist/components/DebouncedTextField.es.js +93 -0
  39. package/dist/components/DebouncedTextField.es.js.map +1 -0
  40. package/dist/components/Dialog.es.js +98 -0
  41. package/dist/components/Dialog.es.js.map +1 -0
  42. package/dist/components/DialogActions.es.js +15 -0
  43. package/dist/components/DialogActions.es.js.map +1 -0
  44. package/dist/components/DialogContent.es.js +18 -0
  45. package/dist/components/DialogContent.es.js.map +1 -0
  46. package/dist/components/DialogTitle.es.js +26 -0
  47. package/dist/components/DialogTitle.es.js.map +1 -0
  48. package/dist/components/ErrorBoundary.es.js +158 -0
  49. package/dist/components/ErrorBoundary.es.js.map +1 -0
  50. package/dist/components/ExpandablePanel.es.js +91 -0
  51. package/dist/components/ExpandablePanel.es.js.map +1 -0
  52. package/dist/components/FileUpload.es.js +58 -0
  53. package/dist/components/FileUpload.es.js.map +1 -0
  54. package/dist/components/FilterChip.es.js +31 -0
  55. package/dist/components/FilterChip.es.js.map +1 -0
  56. package/dist/components/IconButton.es.js +52 -0
  57. package/dist/components/IconButton.es.js.map +1 -0
  58. package/dist/components/InfoLabel.es.js +18 -0
  59. package/dist/components/InfoLabel.es.js.map +1 -0
  60. package/dist/components/InputLabel.es.js +27 -0
  61. package/dist/components/InputLabel.es.js.map +1 -0
  62. package/dist/components/Label.es.js +18 -0
  63. package/dist/components/Label.es.js.map +1 -0
  64. package/dist/components/LoadingButton.es.js +21 -0
  65. package/dist/components/LoadingButton.es.js.map +1 -0
  66. package/dist/components/Markdown.es.js +88 -0
  67. package/dist/components/Markdown.es.js.map +1 -0
  68. package/dist/components/Menu.es.js +46 -0
  69. package/dist/components/Menu.es.js.map +1 -0
  70. package/dist/components/Menubar.es.js +142 -0
  71. package/dist/components/Menubar.es.js.map +1 -0
  72. package/dist/components/MultiSelect.d.ts +1 -7
  73. package/dist/components/MultiSelect.es.js +271 -0
  74. package/dist/components/MultiSelect.es.js.map +1 -0
  75. package/dist/components/Paper.es.js +16 -0
  76. package/dist/components/Paper.es.js.map +1 -0
  77. package/dist/components/Popover.es.js +113 -0
  78. package/dist/components/Popover.es.js.map +1 -0
  79. package/dist/components/RadioGroup.es.js +30 -0
  80. package/dist/components/RadioGroup.es.js.map +1 -0
  81. package/dist/components/ResizablePanels.d.ts +3 -1
  82. package/dist/components/ResizablePanels.es.js +137 -0
  83. package/dist/components/ResizablePanels.es.js.map +1 -0
  84. package/dist/components/SearchBar.es.js +82 -0
  85. package/dist/components/SearchBar.es.js.map +1 -0
  86. package/dist/components/Select.d.ts +8 -1
  87. package/dist/components/Select.es.js +300 -0
  88. package/dist/components/Select.es.js.map +1 -0
  89. package/dist/components/Separator.es.js +20 -0
  90. package/dist/components/Separator.es.js.map +1 -0
  91. package/dist/components/Sheet.es.js +73 -0
  92. package/dist/components/Sheet.es.js.map +1 -0
  93. package/dist/components/Skeleton.es.js +33 -0
  94. package/dist/components/Skeleton.es.js.map +1 -0
  95. package/dist/components/Slider.es.js +56 -0
  96. package/dist/components/Slider.es.js.map +1 -0
  97. package/dist/components/Table.d.ts +18 -3
  98. package/dist/components/Table.es.js +69 -0
  99. package/dist/components/Table.es.js.map +1 -0
  100. package/dist/components/Tabs.es.js +101 -0
  101. package/dist/components/Tabs.es.js.map +1 -0
  102. package/dist/components/TextField.d.ts +0 -8
  103. package/dist/components/TextField.es.js +111 -0
  104. package/dist/components/TextField.es.js.map +1 -0
  105. package/dist/components/TextareaAutosize.es.js +187 -0
  106. package/dist/components/TextareaAutosize.es.js.map +1 -0
  107. package/dist/components/ToggleButtonGroup.d.ts +6 -1
  108. package/dist/components/ToggleButtonGroup.es.js +35 -0
  109. package/dist/components/ToggleButtonGroup.es.js.map +1 -0
  110. package/dist/components/Tooltip.d.ts +24 -0
  111. package/dist/components/Tooltip.es.js +165 -0
  112. package/dist/components/Tooltip.es.js.map +1 -0
  113. package/dist/components/Typography.es.js +85 -0
  114. package/dist/components/Typography.es.js.map +1 -0
  115. package/dist/components/VirtualTable/VirtualTable.es.js +516 -0
  116. package/dist/components/VirtualTable/VirtualTable.es.js.map +1 -0
  117. package/dist/components/VirtualTable/VirtualTableCell.d.ts +1 -1
  118. package/dist/components/VirtualTable/VirtualTableCell.es.js +40 -0
  119. package/dist/components/VirtualTable/VirtualTableCell.es.js.map +1 -0
  120. package/dist/components/VirtualTable/VirtualTableHeader.es.js +209 -0
  121. package/dist/components/VirtualTable/VirtualTableHeader.es.js.map +1 -0
  122. package/dist/components/VirtualTable/VirtualTableHeaderRow.es.js +166 -0
  123. package/dist/components/VirtualTable/VirtualTableHeaderRow.es.js.map +1 -0
  124. package/dist/components/VirtualTable/VirtualTableProps.d.ts +13 -2
  125. package/dist/components/VirtualTable/VirtualTableRow.d.ts +6 -7
  126. package/dist/components/VirtualTable/VirtualTableRow.es.js +41 -0
  127. package/dist/components/VirtualTable/VirtualTableRow.es.js.map +1 -0
  128. package/dist/components/VirtualTable/fields/VirtualTableDateField.d.ts +2 -1
  129. package/dist/components/VirtualTable/fields/VirtualTableDateField.es.js +71 -0
  130. package/dist/components/VirtualTable/fields/VirtualTableDateField.es.js.map +1 -0
  131. package/dist/components/VirtualTable/fields/VirtualTableInput.es.js +73 -0
  132. package/dist/components/VirtualTable/fields/VirtualTableInput.es.js.map +1 -0
  133. package/dist/components/VirtualTable/fields/VirtualTableNumberInput.es.js +47 -0
  134. package/dist/components/VirtualTable/fields/VirtualTableNumberInput.es.js.map +1 -0
  135. package/dist/components/VirtualTable/fields/VirtualTableSelect.es.js +83 -0
  136. package/dist/components/VirtualTable/fields/VirtualTableSelect.es.js.map +1 -0
  137. package/dist/components/VirtualTable/fields/VirtualTableSwitch.es.js +22 -0
  138. package/dist/components/VirtualTable/fields/VirtualTableSwitch.es.js.map +1 -0
  139. package/dist/components/VirtualTable/selection/SelectionContext.es.js +23 -0
  140. package/dist/components/VirtualTable/selection/SelectionContext.es.js.map +1 -0
  141. package/dist/components/VirtualTable/selection/SelectionStore.es.js +43 -0
  142. package/dist/components/VirtualTable/selection/SelectionStore.es.js.map +1 -0
  143. package/dist/components/VirtualTable/types.d.ts +1 -1
  144. package/dist/components/common/SelectInputLabel.es.js +28 -0
  145. package/dist/components/common/SelectInputLabel.es.js.map +1 -0
  146. package/dist/components/index.es.js +64 -0
  147. package/dist/hooks/PortalContainerContext.es.js +40 -0
  148. package/dist/hooks/PortalContainerContext.es.js.map +1 -0
  149. package/dist/hooks/UiLabelsContext.d.ts +63 -0
  150. package/dist/hooks/UiLabelsContext.es.js +59 -0
  151. package/dist/hooks/UiLabelsContext.es.js.map +1 -0
  152. package/dist/hooks/useDebounceCallback.es.js +15 -0
  153. package/dist/hooks/useDebounceCallback.es.js.map +1 -0
  154. package/dist/hooks/useDebounceValue.es.js +19 -0
  155. package/dist/hooks/useDebounceValue.es.js.map +1 -0
  156. package/dist/hooks/useDebouncedCallback.es.js +36 -0
  157. package/dist/hooks/useDebouncedCallback.es.js.map +1 -0
  158. package/dist/hooks/useInjectStyles.es.js +27 -0
  159. package/dist/hooks/useInjectStyles.es.js.map +1 -0
  160. package/dist/hooks/useIsDarkMode.es.js +61 -0
  161. package/dist/hooks/useIsDarkMode.es.js.map +1 -0
  162. package/dist/hooks/useModalFocus.es.js +81 -0
  163. package/dist/hooks/useModalFocus.es.js.map +1 -0
  164. package/dist/hooks/useOutsideAlerter.es.js +41 -0
  165. package/dist/hooks/useOutsideAlerter.es.js.map +1 -0
  166. package/dist/hooks/useRestoreInterruptedFocus.es.js +61 -0
  167. package/dist/hooks/useRestoreInterruptedFocus.es.js.map +1 -0
  168. package/dist/icons/GitHubIcon.es.js +23 -0
  169. package/dist/icons/GitHubIcon.es.js.map +1 -0
  170. package/dist/icons/HandleIcon.es.js +60 -0
  171. package/dist/icons/HandleIcon.es.js.map +1 -0
  172. package/dist/icons/Icon.es.js +25 -0
  173. package/dist/icons/Icon.es.js.map +1 -0
  174. package/dist/icons/LucideIconByName.d.ts +12 -9
  175. package/dist/icons/LucideIconByName.es.js +83 -0
  176. package/dist/icons/LucideIconByName.es.js.map +1 -0
  177. package/dist/icons/cool_icon_keys.es.js +55 -0
  178. package/dist/icons/cool_icon_keys.es.js.map +1 -0
  179. package/dist/icons/icon_keys.es.js +1941 -0
  180. package/dist/icons/icon_keys.es.js.map +1 -0
  181. package/dist/icons/index.d.ts +4 -3
  182. package/dist/icons/index.es.js +8 -0
  183. package/dist/icons/lucide_icon_map.d.ts +12 -0
  184. package/dist/icons/lucide_icon_map.es.js +2 -0
  185. package/dist/index.d.ts +2 -0
  186. package/dist/index.es.js +87 -9563
  187. package/dist/styles.es.js +158 -0
  188. package/dist/styles.es.js.map +1 -0
  189. package/dist/util/chip_colors.es.js +290 -0
  190. package/dist/util/chip_colors.es.js.map +1 -0
  191. package/dist/util/cls.es.js +10 -0
  192. package/dist/util/cls.es.js.map +1 -0
  193. package/dist/util/debounce.es.js +22 -0
  194. package/dist/util/debounce.es.js.map +1 -0
  195. package/dist/util/hash.es.js +16 -0
  196. package/dist/util/hash.es.js.map +1 -0
  197. package/dist/util/keys.es.js +37 -0
  198. package/dist/util/keys.es.js.map +1 -0
  199. package/dist/util/lazy_chunk.es.js +96 -0
  200. package/dist/util/lazy_chunk.es.js.map +1 -0
  201. package/dist/views/CardView.d.ts +26 -2
  202. package/dist/views/CardView.es.js +435 -0
  203. package/dist/views/CardView.es.js.map +1 -0
  204. package/dist/views/CollectionView/CollectionCardView.es.js +179 -0
  205. package/dist/views/CollectionView/CollectionCardView.es.js.map +1 -0
  206. package/dist/views/CollectionView/CollectionKanbanView.es.js +172 -0
  207. package/dist/views/CollectionView/CollectionKanbanView.es.js.map +1 -0
  208. package/dist/views/CollectionView/CollectionListView.es.js +156 -0
  209. package/dist/views/CollectionView/CollectionListView.es.js.map +1 -0
  210. package/dist/views/CollectionView/CollectionTableView.es.js +149 -0
  211. package/dist/views/CollectionView/CollectionTableView.es.js.map +1 -0
  212. package/dist/views/CollectionView/CollectionView.es.js +197 -0
  213. package/dist/views/CollectionView/CollectionView.es.js.map +1 -0
  214. package/dist/views/CollectionView/CollectionViewToolbar.es.js +155 -0
  215. package/dist/views/CollectionView/CollectionViewToolbar.es.js.map +1 -0
  216. package/dist/views/CollectionView/DefaultCellRenderer.es.js +302 -0
  217. package/dist/views/CollectionView/DefaultCellRenderer.es.js.map +1 -0
  218. package/dist/views/CollectionView/resolveTitleProperty.es.js +56 -0
  219. package/dist/views/CollectionView/resolveTitleProperty.es.js.map +1 -0
  220. package/dist/views/CollectionView/utils.es.js +19 -0
  221. package/dist/views/CollectionView/utils.es.js.map +1 -0
  222. package/dist/views/Kanban/Board.es.js +237 -0
  223. package/dist/views/Kanban/Board.es.js.map +1 -0
  224. package/dist/views/Kanban/BoardColumn.es.js +81 -0
  225. package/dist/views/Kanban/BoardColumn.es.js.map +1 -0
  226. package/dist/views/Kanban/BoardColumnTitle.es.js +27 -0
  227. package/dist/views/Kanban/BoardColumnTitle.es.js.map +1 -0
  228. package/dist/views/Kanban/BoardSortableList.es.js +98 -0
  229. package/dist/views/Kanban/BoardSortableList.es.js.map +1 -0
  230. package/dist/views/Kanban/placement.es.js +27 -0
  231. package/dist/views/Kanban/placement.es.js.map +1 -0
  232. package/dist/views/KanbanView.es.js +11 -0
  233. package/dist/views/KanbanView.es.js.map +1 -0
  234. package/dist/views/ListView.d.ts +15 -2
  235. package/dist/views/ListView.es.js +245 -0
  236. package/dist/views/ListView.es.js.map +1 -0
  237. package/dist/views/useScrollParentRestoration.d.ts +8 -1
  238. package/dist/views/useScrollParentRestoration.es.js +75 -0
  239. package/dist/views/useScrollParentRestoration.es.js.map +1 -0
  240. package/package.json +2 -2
  241. package/dist/index.es.js.map +0 -1
@@ -0,0 +1,179 @@
1
+ "use client";
2
+ import "../../styles.es.js";
3
+ import { cls } from "../../util/cls.es.js";
4
+ import { Card } from "../../components/Card.es.js";
5
+ import { Typography } from "../../components/Typography.es.js";
6
+ import { Checkbox } from "../../components/Checkbox.es.js";
7
+ import { useUiLabels } from "../../hooks/UiLabelsContext.es.js";
8
+ import { CardView } from "../CardView.es.js";
9
+ import { DefaultCellRenderer } from "./DefaultCellRenderer.es.js";
10
+ import { getValueInPath } from "./utils.es.js";
11
+ import { resolveTitlePropertyKey } from "./resolveTitleProperty.es.js";
12
+ import { useCallback, useMemo } from "react";
13
+ import { jsx, jsxs } from "react/jsx-runtime";
14
+ //#region src/views/CollectionView/CollectionCardView.tsx
15
+ /**
16
+ * Headless card grid view that wraps {@link CardView}.
17
+ *
18
+ * Renders each item as a card with an optional image, title,
19
+ * preview properties, and selection support.
20
+ *
21
+ * @group Collection View
22
+ */
23
+ function CollectionCardView({ dataController, properties, propertiesOrder, idProperty = "id", titleProperty, onRowClick, cellRenderer, size = "m", selectionEnabled, selectionController, highlightedItems, emptyComponent, className }) {
24
+ const labels = useUiLabels();
25
+ const order = useMemo(() => propertiesOrder ?? Object.keys(properties), [propertiesOrder, properties]);
26
+ const titlePropertyKey = useMemo(() => resolveTitlePropertyKey(order, properties, idProperty, titleProperty), [
27
+ titleProperty,
28
+ order,
29
+ properties,
30
+ idProperty
31
+ ]);
32
+ const imageProperty = useMemo(() => {
33
+ for (const key of order) {
34
+ const prop = properties[key];
35
+ if (prop && prop.type === "string" && prop.storage) return key;
36
+ }
37
+ }, [order, properties]);
38
+ const previewProperties = useMemo(() => {
39
+ const result = [];
40
+ for (const key of order) {
41
+ if (key === titlePropertyKey || key === imageProperty) continue;
42
+ const prop = properties[key];
43
+ if (prop && !prop.hideFromCollection) {
44
+ result.push({
45
+ key,
46
+ property: prop
47
+ });
48
+ if (result.length >= 3) break;
49
+ }
50
+ }
51
+ return result;
52
+ }, [
53
+ order,
54
+ properties,
55
+ titlePropertyKey,
56
+ imageProperty
57
+ ]);
58
+ const selectedIds = useMemo(() => {
59
+ if (!selectionController?.selectedItems) return void 0;
60
+ const ids = /* @__PURE__ */ new Set();
61
+ for (const item of selectionController.selectedItems) {
62
+ const id = getValueInPath(item, idProperty);
63
+ if (id !== void 0 && id !== null) ids.add(id);
64
+ }
65
+ return ids;
66
+ }, [selectionController?.selectedItems, idProperty]);
67
+ const highlightedIds = useMemo(() => {
68
+ if (!highlightedItems) return void 0;
69
+ const ids = /* @__PURE__ */ new Set();
70
+ for (const item of highlightedItems) {
71
+ const id = getValueInPath(item, idProperty);
72
+ if (id !== void 0 && id !== null) ids.add(id);
73
+ }
74
+ return ids;
75
+ }, [highlightedItems, idProperty]);
76
+ const handleSelectionChange = useCallback((item, selected) => {
77
+ if (!selectionController) return;
78
+ selectionController.setSelectedItems((prev) => {
79
+ if (selected) return [...prev, item];
80
+ const itemId = getValueInPath(item, idProperty);
81
+ return prev.filter((existing) => {
82
+ return getValueInPath(existing, idProperty) !== itemId;
83
+ });
84
+ });
85
+ }, [selectionController, idProperty]);
86
+ const renderCard = useCallback((item, extra) => {
87
+ const titleValue = getValueInPath(item, titlePropertyKey);
88
+ const imageValue = imageProperty ? getValueInPath(item, imageProperty) : void 0;
89
+ const hasImage = typeof imageValue === "string" && imageValue.length > 0;
90
+ return /* @__PURE__ */ jsxs(Card, {
91
+ onClick: (e) => {
92
+ if (e) extra.onClick(e);
93
+ },
94
+ className: cls("overflow-hidden relative", extra.selected && "bg-primary-bg/30 dark:bg-primary-bg/10 ring-1 ring-primary/75", extra.highlighted && !extra.selected && "ring-1 ring-primary/50"),
95
+ children: [
96
+ imageProperty && (hasImage ? /* @__PURE__ */ jsx("img", {
97
+ src: imageValue,
98
+ alt: "",
99
+ className: "w-full h-32 object-cover rounded-t-lg"
100
+ }) : /* @__PURE__ */ jsx("div", { className: cls("h-24 rounded-t-lg", "bg-surface-field border border-hairline") })),
101
+ selectionEnabled && /* @__PURE__ */ jsx("div", {
102
+ className: "absolute top-2 right-2",
103
+ onClick: (e) => e.stopPropagation(),
104
+ children: /* @__PURE__ */ jsx(Checkbox, {
105
+ "aria-label": labels.select,
106
+ checked: extra.selected,
107
+ onCheckedChange: extra.onSelectionChange,
108
+ size: "small"
109
+ })
110
+ }),
111
+ /* @__PURE__ */ jsx(Typography, {
112
+ variant: "subtitle2",
113
+ noWrap: true,
114
+ className: "px-3 pt-2 pb-1",
115
+ children: String(titleValue ?? "")
116
+ }),
117
+ previewProperties.map(({ key, property }) => {
118
+ const value = getValueInPath(item, key);
119
+ if (cellRenderer) {
120
+ const custom = cellRenderer({
121
+ row: item,
122
+ propertyKey: key,
123
+ property,
124
+ value,
125
+ size: "small"
126
+ });
127
+ if (custom !== void 0) return /* @__PURE__ */ jsx("div", {
128
+ className: "px-3 py-0.5",
129
+ children: custom
130
+ }, key);
131
+ }
132
+ return /* @__PURE__ */ jsx("div", {
133
+ className: "px-3 py-0.5",
134
+ children: /* @__PURE__ */ jsx(DefaultCellRenderer, {
135
+ row: item,
136
+ propertyKey: key,
137
+ property,
138
+ value,
139
+ size: "small"
140
+ })
141
+ }, key);
142
+ }),
143
+ /* @__PURE__ */ jsx("div", { className: "pb-2" })
144
+ ]
145
+ });
146
+ }, [
147
+ titlePropertyKey,
148
+ imageProperty,
149
+ previewProperties,
150
+ cellRenderer,
151
+ selectionEnabled,
152
+ labels
153
+ ]);
154
+ return /* @__PURE__ */ jsx("div", {
155
+ className: cls("w-full h-full overflow-auto", className),
156
+ children: /* @__PURE__ */ jsx(CardView, {
157
+ data: dataController.data,
158
+ dataLoading: dataController.loading,
159
+ noMoreToLoad: dataController.noMoreToLoad,
160
+ dataLoadingError: dataController.error,
161
+ itemCount: dataController.itemCount,
162
+ setItemCount: dataController.setItemCount,
163
+ pageSize: dataController.pageSize,
164
+ paginationEnabled: dataController.paginationEnabled,
165
+ onItemClick: onRowClick,
166
+ selectedIds,
167
+ highlightedIds,
168
+ selectionEnabled: !!selectionEnabled,
169
+ onSelectionChange: handleSelectionChange,
170
+ size,
171
+ renderCard,
172
+ emptyComponent
173
+ })
174
+ });
175
+ }
176
+ //#endregion
177
+ export { CollectionCardView };
178
+
179
+ //# sourceMappingURL=CollectionCardView.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CollectionCardView.es.js","names":[],"sources":["../../../src/views/CollectionView/CollectionCardView.tsx"],"sourcesContent":["\"use client\";\nimport React, { useCallback, useMemo } from \"react\";\nimport { CardView } from \"../CardView\";\nimport { Card } from \"../../components/Card\";\nimport { Typography } from \"../../components/Typography\";\nimport { Checkbox } from \"../../components/Checkbox\";\nimport { DefaultCellRenderer } from \"./DefaultCellRenderer\";\nimport { cls } from \"../../util\";\nimport { useUiLabels } from \"../../hooks/UiLabelsContext\";\nimport { cardSelectedMixin, fieldBackgroundMixin } from \"../../styles\";\nimport type {\n CollectionPropertyConfig,\n CollectionDataController,\n CellRendererOverride,\n CollectionViewSize,\n CollectionSelectionController,\n} from \"./CollectionViewTypes\";\nimport { resolveTitlePropertyKey } from \"./resolveTitleProperty\";\n\nimport { getValueInPath } from \"./utils\";\n\n/**\n * Props for the {@link CollectionCardView} component.\n * @group Collection View\n */\nexport type CollectionCardViewProps<T = Record<string, unknown>> = {\n dataController: CollectionDataController<T>;\n properties: Record<string, CollectionPropertyConfig>;\n propertiesOrder?: string[];\n idProperty?: string;\n titleProperty?: string;\n onRowClick?: (row: T) => void;\n cellRenderer?: CellRendererOverride<T>;\n size?: CollectionViewSize;\n selectionEnabled?: boolean;\n selectionController?: CollectionSelectionController<T>;\n highlightedItems?: T[];\n emptyComponent?: React.ReactNode;\n className?: string;\n};\n\n/**\n * Headless card grid view that wraps {@link CardView}.\n *\n * Renders each item as a card with an optional image, title,\n * preview properties, and selection support.\n *\n * @group Collection View\n */\nexport function CollectionCardView<T extends Record<string, unknown> = Record<string, unknown>>({\n dataController,\n properties,\n propertiesOrder,\n idProperty = \"id\",\n titleProperty,\n onRowClick,\n cellRenderer,\n size = \"m\",\n selectionEnabled,\n selectionController,\n highlightedItems,\n emptyComponent,\n className,\n}: CollectionCardViewProps<T>) {\n const labels = useUiLabels();\n const order = useMemo(\n () => propertiesOrder ?? Object.keys(properties),\n [propertiesOrder, properties]\n );\n\n // ── Resolve title property ───────────────────────────────────────\n const titlePropertyKey = useMemo(\n () => resolveTitlePropertyKey(order, properties, idProperty, titleProperty),\n [titleProperty, order, properties, idProperty]\n );\n\n // ── Resolve image property ───────────────────────────────────────\n const imageProperty = useMemo(() => {\n for (const key of order) {\n const prop = properties[key];\n if (prop && prop.type === \"string\" && prop.storage) {\n return key;\n }\n }\n return undefined;\n }, [order, properties]);\n\n // ── Preview properties (up to 3) ─────────────────────────────────\n const previewProperties = useMemo(() => {\n const result: { key: string; property: CollectionPropertyConfig }[] = [];\n for (const key of order) {\n if (key === titlePropertyKey || key === imageProperty) continue;\n const prop = properties[key];\n if (prop && !prop.hideFromCollection) {\n result.push({ key, property: prop });\n if (result.length >= 3) break;\n }\n }\n return result;\n }, [order, properties, titlePropertyKey, imageProperty]);\n\n // ── Selection IDs ────────────────────────────────────────────────\n const selectedIds = useMemo(() => {\n if (!selectionController?.selectedItems) return undefined;\n const ids = new Set<string | number>();\n for (const item of selectionController.selectedItems) {\n const id = getValueInPath(item as Record<string, unknown>, idProperty);\n if (id !== undefined && id !== null) {\n ids.add(id as string | number);\n }\n }\n return ids;\n }, [selectionController?.selectedItems, idProperty]);\n\n // ── Highlighted IDs ──────────────────────────────────────────────\n const highlightedIds = useMemo(() => {\n if (!highlightedItems) return undefined;\n const ids = new Set<string | number>();\n for (const item of highlightedItems) {\n const id = getValueInPath(item as Record<string, unknown>, idProperty);\n if (id !== undefined && id !== null) {\n ids.add(id as string | number);\n }\n }\n return ids;\n }, [highlightedItems, idProperty]);\n\n // ── Selection handler ────────────────────────────────────────────\n const handleSelectionChange = useCallback(\n (item: T, selected: boolean) => {\n if (!selectionController) return;\n selectionController.setSelectedItems((prev) => {\n if (selected) {\n return [...prev, item];\n }\n const itemId = getValueInPath(item as Record<string, unknown>, idProperty);\n return prev.filter((existing) => {\n const existingId = getValueInPath(existing as Record<string, unknown>, idProperty);\n return existingId !== itemId;\n });\n });\n },\n [selectionController, idProperty]\n );\n\n // ── Render card ──────────────────────────────────────────────────\n const renderCard = useCallback(\n (\n item: T,\n extra: {\n selected: boolean;\n highlighted: boolean;\n onSelectionChange: (selected: boolean) => void;\n onClick: (e: React.MouseEvent) => void;\n }\n ): React.ReactNode => {\n const titleValue = getValueInPath(item as Record<string, unknown>, titlePropertyKey);\n const imageValue = imageProperty\n ? getValueInPath(item as Record<string, unknown>, imageProperty)\n : undefined;\n const hasImage = typeof imageValue === \"string\" && imageValue.length > 0;\n\n return (\n <Card\n onClick={(e) => { if (e) extra.onClick(e); }}\n className={cls(\n \"overflow-hidden relative\",\n extra.selected && cardSelectedMixin,\n extra.highlighted && !extra.selected && \"ring-1 ring-primary/50\"\n )}\n >\n {/* Image */}\n {imageProperty && (\n hasImage ? (\n <img\n src={imageValue as string}\n alt=\"\"\n className=\"w-full h-32 object-cover rounded-t-lg\"\n />\n ) : (\n <div className={cls(\"h-24 rounded-t-lg\", fieldBackgroundMixin)} />\n )\n )}\n\n {/* Selection checkbox */}\n {selectionEnabled && (\n <div\n className=\"absolute top-2 right-2\"\n onClick={(e) => e.stopPropagation()}\n >\n <Checkbox\n aria-label={labels.select}\n checked={extra.selected}\n onCheckedChange={extra.onSelectionChange}\n size=\"small\"\n />\n </div>\n )}\n\n {/* Title */}\n <Typography variant=\"subtitle2\" noWrap className=\"px-3 pt-2 pb-1\">\n {String(titleValue ?? \"\")}\n </Typography>\n\n {/* Preview properties */}\n {previewProperties.map(({ key, property }) => {\n const value = getValueInPath(item as Record<string, unknown>, key);\n\n if (cellRenderer) {\n const custom = cellRenderer({\n row: item,\n propertyKey: key,\n property,\n value,\n size: \"small\",\n });\n if (custom !== undefined) {\n return (\n <div key={key} className=\"px-3 py-0.5\">\n {custom}\n </div>\n );\n }\n }\n\n return (\n <div key={key} className=\"px-3 py-0.5\">\n <DefaultCellRenderer\n row={item}\n propertyKey={key}\n property={property}\n value={value}\n size=\"small\"\n />\n </div>\n );\n })}\n\n <div className=\"pb-2\" />\n </Card>\n );\n },\n [titlePropertyKey, imageProperty, previewProperties, cellRenderer, selectionEnabled, labels]\n );\n\n return (\n <div className={cls(\"w-full h-full overflow-auto\", className)}>\n <CardView<T>\n data={dataController.data}\n dataLoading={dataController.loading}\n noMoreToLoad={dataController.noMoreToLoad}\n dataLoadingError={dataController.error}\n itemCount={dataController.itemCount}\n setItemCount={dataController.setItemCount}\n pageSize={dataController.pageSize}\n paginationEnabled={dataController.paginationEnabled}\n onItemClick={onRowClick}\n selectedIds={selectedIds}\n highlightedIds={highlightedIds}\n selectionEnabled={!!selectionEnabled}\n onSelectionChange={handleSelectionChange}\n size={size}\n renderCard={renderCard}\n emptyComponent={emptyComponent}\n />\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,172 @@
1
+ "use client";
2
+ import { cardClickableMixin } from "../../styles.es.js";
3
+ import { cls } from "../../util/cls.es.js";
4
+ import { Card } from "../../components/Card.es.js";
5
+ import { Typography } from "../../components/Typography.es.js";
6
+ import { KanbanView } from "../KanbanView.es.js";
7
+ import { DefaultCellRenderer } from "./DefaultCellRenderer.es.js";
8
+ import { getValueInPath } from "./utils.es.js";
9
+ import { resolveTitlePropertyKey } from "./resolveTitleProperty.es.js";
10
+ import { useCallback, useMemo } from "react";
11
+ import { jsx, jsxs } from "react/jsx-runtime";
12
+ //#region src/views/CollectionView/CollectionKanbanView.tsx
13
+ function getEnumLabel(enumConfig, key) {
14
+ if (!enumConfig) return key;
15
+ if (enumConfig instanceof Map) {
16
+ const cfg = enumConfig.get(key);
17
+ if (!cfg) return key;
18
+ return typeof cfg === "string" ? cfg : cfg.label;
19
+ }
20
+ const cfg = enumConfig[key];
21
+ if (!cfg) return key;
22
+ return typeof cfg === "string" ? cfg : cfg.label;
23
+ }
24
+ /**
25
+ * Headless kanban view that wraps {@link KanbanView}.
26
+ *
27
+ * Groups data by a kanban property's enum values into columns.
28
+ * Each card displays a title and 1–2 preview properties.
29
+ *
30
+ * @group Collection View
31
+ */
32
+ function CollectionKanbanView({ dataController, properties, propertiesOrder, idProperty = "id", titleProperty, kanbanProperty, onRowClick, cellRenderer, emptyComponent, onRowCreate, className }) {
33
+ const order = useMemo(() => propertiesOrder ?? Object.keys(properties), [propertiesOrder, properties]);
34
+ const columns = useMemo(() => {
35
+ const kanbanConfig = properties[kanbanProperty];
36
+ if (kanbanConfig?.enum) {
37
+ if (kanbanConfig.enum instanceof Map) return Array.from(kanbanConfig.enum.keys()).map(String);
38
+ return Object.keys(kanbanConfig.enum);
39
+ }
40
+ const seen = /* @__PURE__ */ new Set();
41
+ for (const row of dataController.data) {
42
+ const val = getValueInPath(row, kanbanProperty);
43
+ if (val !== null && val !== void 0) seen.add(String(val));
44
+ }
45
+ return Array.from(seen);
46
+ }, [
47
+ properties,
48
+ kanbanProperty,
49
+ dataController.data
50
+ ]);
51
+ const columnLabels = useMemo(() => {
52
+ const kanbanConfig = properties[kanbanProperty];
53
+ const labels = {};
54
+ for (const col of columns) labels[col] = getEnumLabel(kanbanConfig?.enum, col);
55
+ return labels;
56
+ }, [
57
+ properties,
58
+ kanbanProperty,
59
+ columns
60
+ ]);
61
+ const titlePropertyKey = useMemo(() => resolveTitlePropertyKey(order, properties, idProperty, titleProperty), [
62
+ titleProperty,
63
+ order,
64
+ properties,
65
+ idProperty
66
+ ]);
67
+ const previewProperties = useMemo(() => {
68
+ const result = [];
69
+ for (const key of order) {
70
+ if (key === titlePropertyKey || key === kanbanProperty) continue;
71
+ const prop = properties[key];
72
+ if (prop && !prop.hideFromCollection) {
73
+ result.push({
74
+ key,
75
+ property: prop
76
+ });
77
+ if (result.length >= 2) break;
78
+ }
79
+ }
80
+ return result;
81
+ }, [
82
+ order,
83
+ properties,
84
+ titlePropertyKey,
85
+ kanbanProperty
86
+ ]);
87
+ const boardItems = useMemo(() => {
88
+ return dataController.data.map((row, index) => {
89
+ const id = getValueInPath(row, idProperty);
90
+ return {
91
+ id: id !== null && id !== void 0 ? String(id) : String(index),
92
+ data: row
93
+ };
94
+ });
95
+ }, [dataController.data, idProperty]);
96
+ const assignColumn = useCallback((item) => {
97
+ const val = getValueInPath(item.data, kanbanProperty);
98
+ const strVal = val !== null && val !== void 0 ? String(val) : "";
99
+ if (columns.includes(strVal)) return strVal;
100
+ return columns[0] ?? "";
101
+ }, [kanbanProperty, columns]);
102
+ const ItemComponent = useMemo(() => {
103
+ function KanbanCard(props) {
104
+ const { item } = props;
105
+ const titleValue = getValueInPath(item.data, titlePropertyKey);
106
+ return /* @__PURE__ */ jsxs(Card, {
107
+ onClick: () => onRowClick?.(item.data),
108
+ className: cls("p-3", cardClickableMixin, props.isDragging && "bg-primary-bg/30 dark:bg-primary-bg/10 ring-1 ring-primary/75", props.isDragging && "shadow-lg opacity-75"),
109
+ children: [/* @__PURE__ */ jsx(Typography, {
110
+ variant: "subtitle2",
111
+ noWrap: true,
112
+ children: String(titleValue ?? "")
113
+ }), previewProperties.map(({ key, property }) => {
114
+ const value = getValueInPath(item.data, key);
115
+ if (cellRenderer) {
116
+ const custom = cellRenderer({
117
+ row: item.data,
118
+ propertyKey: key,
119
+ property,
120
+ value,
121
+ size: "tiny"
122
+ });
123
+ if (custom !== void 0) return /* @__PURE__ */ jsx("div", {
124
+ className: "mt-1",
125
+ children: custom
126
+ }, key);
127
+ }
128
+ return /* @__PURE__ */ jsx("div", {
129
+ className: "mt-1",
130
+ children: /* @__PURE__ */ jsx(DefaultCellRenderer, {
131
+ row: item.data,
132
+ propertyKey: key,
133
+ property,
134
+ value,
135
+ size: "tiny"
136
+ })
137
+ }, key);
138
+ })]
139
+ });
140
+ }
141
+ return KanbanCard;
142
+ }, [
143
+ titlePropertyKey,
144
+ previewProperties,
145
+ cellRenderer,
146
+ onRowClick
147
+ ]);
148
+ const handleAddItemToColumn = useCallback((column) => {
149
+ onRowCreate?.({ [kanbanProperty]: column });
150
+ }, [onRowCreate, kanbanProperty]);
151
+ if (columns.length === 0 && !dataController.loading) return /* @__PURE__ */ jsx("div", {
152
+ className: "flex items-center justify-center p-8",
153
+ children: emptyComponent ?? /* @__PURE__ */ jsx(Typography, {
154
+ variant: "body2",
155
+ color: "secondary",
156
+ children: "No columns available for kanban view."
157
+ })
158
+ });
159
+ return /* @__PURE__ */ jsx(KanbanView, {
160
+ columns,
161
+ columnLabels,
162
+ data: boardItems,
163
+ assignColumn,
164
+ ItemComponent,
165
+ onAddItemToColumn: onRowCreate ? handleAddItemToColumn : void 0,
166
+ className
167
+ });
168
+ }
169
+ //#endregion
170
+ export { CollectionKanbanView };
171
+
172
+ //# sourceMappingURL=CollectionKanbanView.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CollectionKanbanView.es.js","names":[],"sources":["../../../src/views/CollectionView/CollectionKanbanView.tsx"],"sourcesContent":["\"use client\";\nimport React, { useCallback, useMemo } from \"react\";\nimport { KanbanView } from \"../KanbanView\";\nimport type { BoardItem, BoardItemViewProps } from \"../KanbanView\";\nimport { Card } from \"../../components/Card\";\nimport { Typography } from \"../../components/Typography\";\nimport { DefaultCellRenderer } from \"./DefaultCellRenderer\";\nimport { cls } from \"../../util\";\nimport { cardClickableMixin, cardSelectedMixin } from \"../../styles\";\nimport type {\n CollectionPropertyConfig,\n CollectionDataController,\n CellRendererOverride,\n CollectionSelectionController,\n CollectionEnumValueConfig,\n} from \"./CollectionViewTypes\";\nimport { resolveTitlePropertyKey } from \"./resolveTitleProperty\";\n\nimport { getValueInPath } from \"./utils\";\n\nfunction getEnumLabel(enumConfig: CollectionPropertyConfig[\"enum\"], key: string): string {\n if (!enumConfig) return key;\n if (enumConfig instanceof Map) {\n const cfg: CollectionEnumValueConfig | undefined = enumConfig.get(key);\n if (!cfg) return key;\n return typeof cfg === \"string\" ? cfg : cfg.label;\n }\n const cfg: CollectionEnumValueConfig | undefined = enumConfig[key];\n if (!cfg) return key;\n return typeof cfg === \"string\" ? cfg : cfg.label;\n}\n\n/**\n * Props for the {@link CollectionKanbanView} component.\n * @group Collection View\n */\nexport type CollectionKanbanViewProps<T = Record<string, unknown>> = {\n dataController: CollectionDataController<T>;\n properties: Record<string, CollectionPropertyConfig>;\n propertiesOrder?: string[];\n idProperty?: string;\n titleProperty?: string;\n kanbanProperty: string;\n onRowClick?: (row: T) => void;\n cellRenderer?: CellRendererOverride<T>;\n selectionEnabled?: boolean;\n selectionController?: CollectionSelectionController<T>;\n highlightedItems?: T[];\n emptyComponent?: React.ReactNode;\n onRowCreate?: (defaults?: Record<string, unknown>) => void;\n className?: string;\n};\n\n/**\n * Headless kanban view that wraps {@link KanbanView}.\n *\n * Groups data by a kanban property's enum values into columns.\n * Each card displays a title and 1–2 preview properties.\n *\n * @group Collection View\n */\nexport function CollectionKanbanView<T extends Record<string, unknown> = Record<string, unknown>>({\n dataController,\n properties,\n propertiesOrder,\n idProperty = \"id\",\n titleProperty,\n kanbanProperty,\n onRowClick,\n cellRenderer,\n emptyComponent,\n onRowCreate,\n className,\n}: CollectionKanbanViewProps<T>) {\n const order = useMemo(\n () => propertiesOrder ?? Object.keys(properties),\n [propertiesOrder, properties]\n );\n\n // ── Resolve kanban columns ───────────────────────────────────────\n const columns = useMemo<string[]>(() => {\n const kanbanConfig = properties[kanbanProperty];\n if (kanbanConfig?.enum) {\n if (kanbanConfig.enum instanceof Map) {\n return Array.from(kanbanConfig.enum.keys()).map(String);\n }\n return Object.keys(kanbanConfig.enum);\n }\n // Deduce from data\n const seen = new Set<string>();\n for (const row of dataController.data) {\n const val = getValueInPath(row as Record<string, unknown>, kanbanProperty);\n if (val !== null && val !== undefined) {\n seen.add(String(val));\n }\n }\n return Array.from(seen);\n }, [properties, kanbanProperty, dataController.data]);\n\n // ── Column labels ────────────────────────────────────────────────\n const columnLabels = useMemo(() => {\n const kanbanConfig = properties[kanbanProperty];\n const labels: Record<string, string> = {};\n for (const col of columns) {\n labels[col] = getEnumLabel(kanbanConfig?.enum, col);\n }\n return labels;\n }, [properties, kanbanProperty, columns]);\n\n // ── Resolve title property ───────────────────────────────────────\n const titlePropertyKey = useMemo(\n () => resolveTitlePropertyKey(order, properties, idProperty, titleProperty),\n [titleProperty, order, properties, idProperty]\n );\n\n // ── Preview properties (up to 2) ─────────────────────────────────\n const previewProperties = useMemo(() => {\n const result: { key: string; property: CollectionPropertyConfig }[] = [];\n for (const key of order) {\n if (key === titlePropertyKey || key === kanbanProperty) continue;\n const prop = properties[key];\n if (prop && !prop.hideFromCollection) {\n result.push({ key, property: prop });\n if (result.length >= 2) break;\n }\n }\n return result;\n }, [order, properties, titlePropertyKey, kanbanProperty]);\n\n // ── Convert data to BoardItem<T>[] ───────────────────────────────\n const boardItems = useMemo<BoardItem<T>[]>(() => {\n return dataController.data.map((row, index) => {\n const id = getValueInPath(row as Record<string, unknown>, idProperty);\n return {\n id: id !== null && id !== undefined ? String(id) : String(index),\n data: row,\n };\n });\n }, [dataController.data, idProperty]);\n\n // ── Assign column ────────────────────────────────────────────────\n const assignColumn = useCallback(\n (item: BoardItem<T>): string => {\n const val = getValueInPath(item.data as Record<string, unknown>, kanbanProperty);\n const strVal = val !== null && val !== undefined ? String(val) : \"\";\n if (columns.includes(strVal)) return strVal;\n return columns[0] ?? \"\";\n },\n [kanbanProperty, columns]\n );\n\n // ── Item component ───────────────────────────────────────────────\n const ItemComponent = useMemo(() => {\n function KanbanCard(props: BoardItemViewProps<T>) {\n const { item } = props;\n const titleValue = getValueInPath(\n item.data as Record<string, unknown>,\n titlePropertyKey\n );\n\n return (\n <Card\n onClick={() => onRowClick?.(item.data)}\n className={cls(\n \"p-3\",\n cardClickableMixin,\n props.isDragging && cardSelectedMixin,\n props.isDragging && \"shadow-lg opacity-75\"\n )}\n >\n <Typography variant=\"subtitle2\" noWrap>\n {String(titleValue ?? \"\")}\n </Typography>\n {previewProperties.map(({ key, property }) => {\n const value = getValueInPath(\n item.data as Record<string, unknown>,\n key\n );\n\n if (cellRenderer) {\n const custom = cellRenderer({\n row: item.data,\n propertyKey: key,\n property,\n value,\n size: \"tiny\",\n });\n if (custom !== undefined) {\n return (\n <div key={key} className=\"mt-1\">\n {custom}\n </div>\n );\n }\n }\n\n return (\n <div key={key} className=\"mt-1\">\n <DefaultCellRenderer\n row={item.data}\n propertyKey={key}\n property={property}\n value={value}\n size=\"tiny\"\n />\n </div>\n );\n })}\n </Card>\n );\n }\n return KanbanCard;\n }, [titlePropertyKey, previewProperties, cellRenderer, onRowClick]);\n\n // ── Add item to column ───────────────────────────────────────────\n const handleAddItemToColumn = useCallback(\n (column: string) => {\n onRowCreate?.({ [kanbanProperty]: column });\n },\n [onRowCreate, kanbanProperty]\n );\n\n if (columns.length === 0 && !dataController.loading) {\n return (\n <div className=\"flex items-center justify-center p-8\">\n {emptyComponent ?? (\n <Typography variant=\"body2\" color=\"secondary\">\n No columns available for kanban view.\n </Typography>\n )}\n </div>\n );\n }\n\n return (\n <KanbanView<T, string>\n columns={columns}\n columnLabels={columnLabels as Record<string, string>}\n data={boardItems}\n assignColumn={assignColumn}\n ItemComponent={ItemComponent}\n onAddItemToColumn={onRowCreate ? handleAddItemToColumn : undefined}\n className={className}\n />\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,156 @@
1
+ "use client";
2
+ import { cls } from "../../util/cls.es.js";
3
+ import { Typography } from "../../components/Typography.es.js";
4
+ import { Checkbox } from "../../components/Checkbox.es.js";
5
+ import { useUiLabels } from "../../hooks/UiLabelsContext.es.js";
6
+ import { ListView } from "../ListView.es.js";
7
+ import { DefaultCellRenderer } from "./DefaultCellRenderer.es.js";
8
+ import { getValueInPath } from "./utils.es.js";
9
+ import { resolveTitlePropertyKey } from "./resolveTitleProperty.es.js";
10
+ import React, { useCallback, useMemo } from "react";
11
+ import { jsx, jsxs } from "react/jsx-runtime";
12
+ //#region src/views/CollectionView/CollectionListView.tsx
13
+ /**
14
+ * Headless list view that wraps {@link ListView}.
15
+ *
16
+ * Each row displays a title (bold), subtitle with 1–2 secondary property values,
17
+ * and optional selection support.
18
+ *
19
+ * @group Collection View
20
+ */
21
+ function CollectionListView({ dataController, properties, propertiesOrder, idProperty = "id", titleProperty, onRowClick, cellRenderer, size = "m", selectionEnabled, selectionController, highlightedItems, emptyComponent, className }) {
22
+ const labels = useUiLabels();
23
+ const order = useMemo(() => propertiesOrder ?? Object.keys(properties), [propertiesOrder, properties]);
24
+ const titlePropertyKey = useMemo(() => resolveTitlePropertyKey(order, properties, idProperty, titleProperty), [
25
+ titleProperty,
26
+ order,
27
+ properties,
28
+ idProperty
29
+ ]);
30
+ const subtitleProperties = useMemo(() => {
31
+ const result = [];
32
+ for (const key of order) {
33
+ if (key === titlePropertyKey) continue;
34
+ const prop = properties[key];
35
+ if (prop && !prop.hideFromCollection) {
36
+ result.push({
37
+ key,
38
+ property: prop
39
+ });
40
+ if (result.length >= 2) break;
41
+ }
42
+ }
43
+ return result;
44
+ }, [
45
+ order,
46
+ properties,
47
+ titlePropertyKey
48
+ ]);
49
+ const selectedIds = useMemo(() => {
50
+ if (!selectionController?.selectedItems) return void 0;
51
+ const ids = /* @__PURE__ */ new Set();
52
+ for (const item of selectionController.selectedItems) {
53
+ const id = getValueInPath(item, idProperty);
54
+ if (id !== void 0 && id !== null) ids.add(id);
55
+ }
56
+ return ids;
57
+ }, [selectionController?.selectedItems, idProperty]);
58
+ const highlightedIds = useMemo(() => {
59
+ if (!highlightedItems) return void 0;
60
+ const ids = /* @__PURE__ */ new Set();
61
+ for (const item of highlightedItems) {
62
+ const id = getValueInPath(item, idProperty);
63
+ if (id !== void 0 && id !== null) ids.add(id);
64
+ }
65
+ return ids;
66
+ }, [highlightedItems, idProperty]);
67
+ const handleSelectionChange = useCallback((item, selected) => {
68
+ if (!selectionController) return;
69
+ selectionController.setSelectedItems((prev) => {
70
+ if (selected) return [...prev, item];
71
+ const itemId = getValueInPath(item, idProperty);
72
+ return prev.filter((existing) => {
73
+ return getValueInPath(existing, idProperty) !== itemId;
74
+ });
75
+ });
76
+ }, [selectionController, idProperty]);
77
+ const renderRow = useCallback((params) => {
78
+ const { item, style, className: rowClassName, selected, highlighted, onClick, onSelectionChange } = params;
79
+ const titleValue = getValueInPath(item, titlePropertyKey);
80
+ return /* @__PURE__ */ jsxs("div", {
81
+ style,
82
+ className: cls("flex items-center gap-3 px-4 cursor-pointer", "hover:bg-surface-hover", "transition-colors duration-100", selected && "bg-primary-bg", highlighted && "bg-surface-raised", rowClassName),
83
+ onClick,
84
+ children: [selectionEnabled && /* @__PURE__ */ jsx("div", {
85
+ className: "flex-shrink-0",
86
+ onClick: (e) => e.stopPropagation(),
87
+ children: /* @__PURE__ */ jsx(Checkbox, {
88
+ "aria-label": labels.select,
89
+ checked: selected,
90
+ onCheckedChange: onSelectionChange,
91
+ size: "small"
92
+ })
93
+ }), /* @__PURE__ */ jsxs("div", {
94
+ className: "flex-1 min-w-0 py-1",
95
+ children: [/* @__PURE__ */ jsx(Typography, {
96
+ variant: "subtitle2",
97
+ noWrap: true,
98
+ children: String(titleValue ?? "")
99
+ }), subtitleProperties.length > 0 && /* @__PURE__ */ jsx("div", {
100
+ className: "flex items-center gap-2",
101
+ children: subtitleProperties.map(({ key, property }) => {
102
+ const value = getValueInPath(item, key);
103
+ if (cellRenderer) {
104
+ const custom = cellRenderer({
105
+ row: item,
106
+ propertyKey: key,
107
+ property,
108
+ value,
109
+ size: "tiny"
110
+ });
111
+ if (custom !== void 0) return /* @__PURE__ */ jsx(React.Fragment, { children: custom }, key);
112
+ }
113
+ return /* @__PURE__ */ jsx(React.Fragment, { children: /* @__PURE__ */ jsx(DefaultCellRenderer, {
114
+ row: item,
115
+ propertyKey: key,
116
+ property,
117
+ value,
118
+ size: "tiny"
119
+ }) }, key);
120
+ })
121
+ })]
122
+ })]
123
+ });
124
+ }, [
125
+ titlePropertyKey,
126
+ subtitleProperties,
127
+ cellRenderer,
128
+ selectionEnabled,
129
+ labels
130
+ ]);
131
+ return /* @__PURE__ */ jsx("div", {
132
+ className: cls("w-full h-full overflow-auto", className),
133
+ children: /* @__PURE__ */ jsx(ListView, {
134
+ data: dataController.data,
135
+ dataLoading: dataController.loading,
136
+ noMoreToLoad: dataController.noMoreToLoad,
137
+ dataLoadingError: dataController.error,
138
+ itemCount: dataController.itemCount,
139
+ setItemCount: dataController.setItemCount,
140
+ pageSize: dataController.pageSize,
141
+ paginationEnabled: dataController.paginationEnabled,
142
+ onItemClick: onRowClick,
143
+ selectedIds,
144
+ highlightedIds,
145
+ selectionEnabled: !!selectionEnabled,
146
+ onSelectionChange: handleSelectionChange,
147
+ size,
148
+ renderRow,
149
+ emptyComponent
150
+ })
151
+ });
152
+ }
153
+ //#endregion
154
+ export { CollectionListView };
155
+
156
+ //# sourceMappingURL=CollectionListView.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CollectionListView.es.js","names":[],"sources":["../../../src/views/CollectionView/CollectionListView.tsx"],"sourcesContent":["\"use client\";\nimport React, { useCallback, useMemo } from \"react\";\nimport { ListView } from \"../ListView\";\nimport { Typography } from \"../../components/Typography\";\nimport { Checkbox } from \"../../components/Checkbox\";\nimport { DefaultCellRenderer } from \"./DefaultCellRenderer\";\nimport { cls } from \"../../util\";\nimport { useUiLabels } from \"../../hooks/UiLabelsContext\";\nimport type {\n CollectionPropertyConfig,\n CollectionDataController,\n CellRendererOverride,\n CollectionViewSize,\n CollectionSelectionController,\n} from \"./CollectionViewTypes\";\nimport { resolveTitlePropertyKey } from \"./resolveTitleProperty\";\n\nimport { getValueInPath } from \"./utils\";\n\n/**\n * Props for the {@link CollectionListView} component.\n * @group Collection View\n */\nexport type CollectionListViewProps<T = Record<string, unknown>> = {\n dataController: CollectionDataController<T>;\n properties: Record<string, CollectionPropertyConfig>;\n propertiesOrder?: string[];\n idProperty?: string;\n titleProperty?: string;\n onRowClick?: (row: T) => void;\n cellRenderer?: CellRendererOverride<T>;\n size?: CollectionViewSize;\n selectionEnabled?: boolean;\n selectionController?: CollectionSelectionController<T>;\n highlightedItems?: T[];\n emptyComponent?: React.ReactNode;\n className?: string;\n};\n\n/**\n * Headless list view that wraps {@link ListView}.\n *\n * Each row displays a title (bold), subtitle with 1–2 secondary property values,\n * and optional selection support.\n *\n * @group Collection View\n */\nexport function CollectionListView<T extends Record<string, unknown> = Record<string, unknown>>({\n dataController,\n properties,\n propertiesOrder,\n idProperty = \"id\",\n titleProperty,\n onRowClick,\n cellRenderer,\n size = \"m\",\n selectionEnabled,\n selectionController,\n highlightedItems,\n emptyComponent,\n className,\n}: CollectionListViewProps<T>) {\n const labels = useUiLabels();\n const order = useMemo(\n () => propertiesOrder ?? Object.keys(properties),\n [propertiesOrder, properties]\n );\n\n // ── Resolve title property ───────────────────────────────────────\n const titlePropertyKey = useMemo(\n () => resolveTitlePropertyKey(order, properties, idProperty, titleProperty),\n [titleProperty, order, properties, idProperty]\n );\n\n // ── Subtitle properties (up to 2) ────────────────────────────────\n const subtitleProperties = useMemo(() => {\n const result: { key: string; property: CollectionPropertyConfig }[] = [];\n for (const key of order) {\n if (key === titlePropertyKey) continue;\n const prop = properties[key];\n if (prop && !prop.hideFromCollection) {\n result.push({ key, property: prop });\n if (result.length >= 2) break;\n }\n }\n return result;\n }, [order, properties, titlePropertyKey]);\n\n // ── Selection IDs ────────────────────────────────────────────────\n const selectedIds = useMemo(() => {\n if (!selectionController?.selectedItems) return undefined;\n const ids = new Set<string | number>();\n for (const item of selectionController.selectedItems) {\n const id = getValueInPath(item as Record<string, unknown>, idProperty);\n if (id !== undefined && id !== null) {\n ids.add(id as string | number);\n }\n }\n return ids;\n }, [selectionController?.selectedItems, idProperty]);\n\n // ── Highlighted IDs ──────────────────────────────────────────────\n const highlightedIds = useMemo(() => {\n if (!highlightedItems) return undefined;\n const ids = new Set<string | number>();\n for (const item of highlightedItems) {\n const id = getValueInPath(item as Record<string, unknown>, idProperty);\n if (id !== undefined && id !== null) {\n ids.add(id as string | number);\n }\n }\n return ids;\n }, [highlightedItems, idProperty]);\n\n // ── Selection handler ────────────────────────────────────────────\n const handleSelectionChange = useCallback(\n (item: T, selected: boolean) => {\n if (!selectionController) return;\n selectionController.setSelectedItems((prev) => {\n if (selected) {\n return [...prev, item];\n }\n const itemId = getValueInPath(item as Record<string, unknown>, idProperty);\n return prev.filter((existing) => {\n const existingId = getValueInPath(existing as Record<string, unknown>, idProperty);\n return existingId !== itemId;\n });\n });\n },\n [selectionController, idProperty]\n );\n\n // ── Render row ───────────────────────────────────────────────────\n const renderRow = useCallback(\n (params: {\n item: T;\n index: number;\n style: React.CSSProperties;\n className: string;\n selected: boolean;\n highlighted: boolean;\n isLast: boolean;\n onClick: (e: React.MouseEvent) => void;\n onSelectionChange: (selected: boolean) => void;\n }): React.ReactNode => {\n const { item, style, className: rowClassName, selected, highlighted, onClick, onSelectionChange } = params;\n const titleValue = getValueInPath(item as Record<string, unknown>, titlePropertyKey);\n\n return (\n <div\n style={style}\n className={cls(\n \"flex items-center gap-3 px-4 cursor-pointer\",\n \"hover:bg-surface-hover\",\n \"transition-colors duration-100\",\n selected && \"bg-primary-bg\",\n highlighted && \"bg-surface-raised\",\n rowClassName\n )}\n onClick={onClick}\n >\n {/* Selection checkbox */}\n {selectionEnabled && (\n <div className=\"flex-shrink-0\" onClick={(e) => e.stopPropagation()}>\n <Checkbox\n aria-label={labels.select}\n checked={selected}\n onCheckedChange={onSelectionChange}\n size=\"small\"\n />\n </div>\n )}\n\n {/* Content */}\n <div className=\"flex-1 min-w-0 py-1\">\n {/* Title */}\n <Typography variant=\"subtitle2\" noWrap>\n {String(titleValue ?? \"\")}\n </Typography>\n\n {/* Subtitle properties */}\n {subtitleProperties.length > 0 && (\n <div className=\"flex items-center gap-2\">\n {subtitleProperties.map(({ key, property }) => {\n const value = getValueInPath(item as Record<string, unknown>, key);\n\n if (cellRenderer) {\n const custom = cellRenderer({\n row: item,\n propertyKey: key,\n property,\n value,\n size: \"tiny\",\n });\n if (custom !== undefined) {\n return <React.Fragment key={key}>{custom}</React.Fragment>;\n }\n }\n\n return (\n <React.Fragment key={key}>\n <DefaultCellRenderer\n row={item}\n propertyKey={key}\n property={property}\n value={value}\n size=\"tiny\"\n />\n </React.Fragment>\n );\n })}\n </div>\n )}\n </div>\n </div>\n );\n },\n [titlePropertyKey, subtitleProperties, cellRenderer, selectionEnabled, labels]\n );\n\n return (\n <div className={cls(\"w-full h-full overflow-auto\", className)}>\n <ListView<T>\n data={dataController.data}\n dataLoading={dataController.loading}\n noMoreToLoad={dataController.noMoreToLoad}\n dataLoadingError={dataController.error}\n itemCount={dataController.itemCount}\n setItemCount={dataController.setItemCount}\n pageSize={dataController.pageSize}\n paginationEnabled={dataController.paginationEnabled}\n onItemClick={onRowClick}\n selectedIds={selectedIds}\n highlightedIds={highlightedIds}\n selectionEnabled={!!selectionEnabled}\n onSelectionChange={handleSelectionChange}\n size={size}\n renderRow={renderRow}\n emptyComponent={emptyComponent}\n />\n </div>\n );\n}\n"],"mappings":"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"}