@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,302 @@
1
+ import { cls } from "../../util/cls.es.js";
2
+ import { iconSize } from "../../icons/Icon.es.js";
3
+ import { BooleanSwitch } from "../../components/BooleanSwitch.es.js";
4
+ import { Typography } from "../../components/Typography.es.js";
5
+ import { Chip } from "../../components/Chip.es.js";
6
+ import { Tooltip } from "../../components/Tooltip.es.js";
7
+ import { Markdown } from "../../components/Markdown.es.js";
8
+ import "react";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ import { ImageIcon } from "lucide-react";
11
+ //#region src/views/CollectionView/DefaultCellRenderer.tsx
12
+ /**
13
+ * Resolve an enum key to its display label and optional color.
14
+ */
15
+ function resolveEnumLabel(enumValues, value) {
16
+ if (!enumValues) return void 0;
17
+ const key = String(value);
18
+ if (enumValues instanceof Map) {
19
+ const config = enumValues.get(value);
20
+ if (!config) return void 0;
21
+ if (typeof config === "string") return { label: config };
22
+ return {
23
+ label: config.label,
24
+ color: config.color
25
+ };
26
+ }
27
+ const config = enumValues[key];
28
+ if (!config) return void 0;
29
+ if (typeof config === "string") return { label: config };
30
+ return {
31
+ label: config.label,
32
+ color: config.color
33
+ };
34
+ }
35
+ /**
36
+ * Format a date value using Intl.DateTimeFormat.
37
+ */
38
+ function formatDate(value, includeTime) {
39
+ if (value == null) return "—";
40
+ const date = value instanceof Date ? value : new Date(String(value));
41
+ if (isNaN(date.getTime())) return String(value);
42
+ const options = includeTime ? {
43
+ year: "numeric",
44
+ month: "short",
45
+ day: "numeric",
46
+ hour: "2-digit",
47
+ minute: "2-digit"
48
+ } : {
49
+ year: "numeric",
50
+ month: "short",
51
+ day: "numeric"
52
+ };
53
+ return new Intl.DateTimeFormat(void 0, options).format(date);
54
+ }
55
+ /**
56
+ * Type guard for geopoint-like objects.
57
+ */
58
+ function isGeoPoint(value) {
59
+ if (typeof value !== "object" || value === null) return false;
60
+ const obj = value;
61
+ return typeof obj.lat === "number" && typeof obj.lng === "number";
62
+ }
63
+ /**
64
+ * Default cell renderer for the headless CollectionView.
65
+ * Handles all built-in property types without depending on any Rebase core types.
66
+ *
67
+ * @group Preview components
68
+ */
69
+ function DefaultCellRenderer({ row, propertyKey, property, value, size, width, height }) {
70
+ if (value === null || value === void 0) return /* @__PURE__ */ jsx(Typography, {
71
+ variant: "body2",
72
+ color: "secondary",
73
+ className: "px-1",
74
+ children: "—"
75
+ });
76
+ if (property.Preview) {
77
+ const PreviewComponent = property.Preview;
78
+ return /* @__PURE__ */ jsx(PreviewComponent, {
79
+ row,
80
+ propertyKey,
81
+ property,
82
+ value,
83
+ size,
84
+ width,
85
+ height
86
+ });
87
+ }
88
+ switch (property.type) {
89
+ case "string": return renderString(property, value);
90
+ case "number": return renderNumber(property, value);
91
+ case "boolean": return renderBoolean(value);
92
+ case "date": return renderDate(property, value);
93
+ case "array": return renderArray(property, value);
94
+ case "map": return renderMap(value);
95
+ case "reference":
96
+ case "relation": return renderReference(value);
97
+ case "geopoint": return renderGeopoint(value);
98
+ default: return /* @__PURE__ */ jsx(Typography, {
99
+ variant: "body2",
100
+ color: "secondary",
101
+ noWrap: true,
102
+ className: "px-1",
103
+ children: JSON.stringify(value)
104
+ });
105
+ }
106
+ }
107
+ function renderString(property, value) {
108
+ const strValue = String(value);
109
+ if (property.enum) {
110
+ const resolved = resolveEnumLabel(property.enum, value);
111
+ return /* @__PURE__ */ jsx(Chip, {
112
+ size: "small",
113
+ colorScheme: resolved?.color ? {
114
+ color: resolved.color,
115
+ text: "#fff"
116
+ } : void 0,
117
+ children: resolved?.label ?? strValue
118
+ });
119
+ }
120
+ if (property.previewAsTag) return /* @__PURE__ */ jsx(Chip, {
121
+ size: "small",
122
+ children: strValue
123
+ });
124
+ if (property.url) return /* @__PURE__ */ jsx(Typography, {
125
+ variant: "body2",
126
+ noWrap: true,
127
+ component: "a",
128
+ href: typeof property.url === "string" ? property.url : strValue,
129
+ target: "_blank",
130
+ rel: "noopener noreferrer",
131
+ className: cls("px-1 text-primary hover:underline cursor-pointer"),
132
+ children: strValue
133
+ });
134
+ if (property.email) return /* @__PURE__ */ jsx(Typography, {
135
+ variant: "body2",
136
+ noWrap: true,
137
+ component: "a",
138
+ href: `mailto:${strValue}`,
139
+ className: cls("px-1 text-primary hover:underline cursor-pointer"),
140
+ children: strValue
141
+ });
142
+ if (property.markdown) return /* @__PURE__ */ jsx("div", {
143
+ className: "px-1 max-h-[100px] overflow-hidden",
144
+ children: /* @__PURE__ */ jsx(Markdown, {
145
+ source: strValue,
146
+ size: "small"
147
+ })
148
+ });
149
+ if (property.storage) return /* @__PURE__ */ jsxs("div", {
150
+ className: cls("px-1 flex items-center justify-center", "w-[40px] h-[40px] rounded overflow-hidden"),
151
+ children: [strValue ? /* @__PURE__ */ jsx("img", {
152
+ src: strValue,
153
+ alt: "",
154
+ className: "w-full h-full object-cover",
155
+ onError: (e) => {
156
+ const target = e.currentTarget;
157
+ target.style.display = "none";
158
+ const fallback = target.nextElementSibling;
159
+ if (fallback instanceof HTMLElement) fallback.style.display = "flex";
160
+ }
161
+ }) : null, /* @__PURE__ */ jsx("div", {
162
+ className: cls("w-full h-full items-center justify-center rounded", "bg-surface-raised text-text-secondary dark:text-text-secondary-dark", strValue ? "hidden" : "flex"),
163
+ children: /* @__PURE__ */ jsx(ImageIcon, { size: iconSize.small })
164
+ })]
165
+ });
166
+ return /* @__PURE__ */ jsx(Tooltip, {
167
+ title: strValue.length > 50 ? strValue : void 0,
168
+ side: "bottom",
169
+ children: /* @__PURE__ */ jsx(Typography, {
170
+ variant: "body2",
171
+ noWrap: true,
172
+ className: "px-1",
173
+ children: strValue
174
+ })
175
+ });
176
+ }
177
+ function renderNumber(property, value) {
178
+ const numStr = String(value);
179
+ if (property.enum) {
180
+ const resolved = resolveEnumLabel(property.enum, value);
181
+ return /* @__PURE__ */ jsx(Chip, {
182
+ size: "small",
183
+ colorScheme: resolved?.color ? {
184
+ color: resolved.color,
185
+ text: "#fff"
186
+ } : void 0,
187
+ children: resolved?.label ?? numStr
188
+ });
189
+ }
190
+ return /* @__PURE__ */ jsx(Typography, {
191
+ variant: "body2",
192
+ noWrap: true,
193
+ align: "right",
194
+ className: "px-1 tabular-nums",
195
+ children: numStr
196
+ });
197
+ }
198
+ function renderBoolean(value) {
199
+ return /* @__PURE__ */ jsx("div", {
200
+ className: "px-1 flex items-center",
201
+ children: /* @__PURE__ */ jsx(BooleanSwitch, {
202
+ value: !!value,
203
+ size: "small",
204
+ disabled: true
205
+ })
206
+ });
207
+ }
208
+ function renderDate(property, value) {
209
+ return /* @__PURE__ */ jsx(Typography, {
210
+ variant: "body2",
211
+ noWrap: true,
212
+ className: "px-1 tabular-nums",
213
+ children: formatDate(value, property.mode === "date_time")
214
+ });
215
+ }
216
+ function renderArray(property, value) {
217
+ if (!Array.isArray(value)) return /* @__PURE__ */ jsx(Typography, {
218
+ variant: "body2",
219
+ color: "secondary",
220
+ className: "px-1",
221
+ children: "—"
222
+ });
223
+ if (property.of?.enum && value.length > 0) return /* @__PURE__ */ jsx("div", {
224
+ className: "px-1 flex flex-wrap gap-1 overflow-hidden",
225
+ children: value.map((item, i) => {
226
+ const resolved = resolveEnumLabel(property.of.enum, item);
227
+ return /* @__PURE__ */ jsx(Chip, {
228
+ size: "smallest",
229
+ colorScheme: resolved?.color ? {
230
+ color: resolved.color,
231
+ text: "#fff"
232
+ } : void 0,
233
+ children: resolved?.label ?? String(item)
234
+ }, i);
235
+ })
236
+ });
237
+ if (value.length > 0 && value.every((item) => typeof item === "string")) return /* @__PURE__ */ jsx(Typography, {
238
+ variant: "body2",
239
+ noWrap: true,
240
+ className: "px-1",
241
+ children: value.join(", ")
242
+ });
243
+ return /* @__PURE__ */ jsxs(Typography, {
244
+ variant: "body2",
245
+ color: "secondary",
246
+ className: "px-1",
247
+ children: [
248
+ value.length,
249
+ " ",
250
+ value.length === 1 ? "item" : "items"
251
+ ]
252
+ });
253
+ }
254
+ function renderMap(value) {
255
+ if (typeof value !== "object" || value === null) return /* @__PURE__ */ jsx(Typography, {
256
+ variant: "body2",
257
+ color: "secondary",
258
+ className: "px-1",
259
+ children: "—"
260
+ });
261
+ const fieldCount = Object.keys(value).length;
262
+ return /* @__PURE__ */ jsxs(Typography, {
263
+ variant: "body2",
264
+ color: "secondary",
265
+ className: "px-1",
266
+ children: [
267
+ fieldCount,
268
+ " ",
269
+ fieldCount === 1 ? "field" : "fields"
270
+ ]
271
+ });
272
+ }
273
+ function renderReference(value) {
274
+ return /* @__PURE__ */ jsx(Typography, {
275
+ variant: "body2",
276
+ noWrap: true,
277
+ className: "px-1",
278
+ children: String(value)
279
+ });
280
+ }
281
+ function renderGeopoint(value) {
282
+ if (isGeoPoint(value)) return /* @__PURE__ */ jsxs(Typography, {
283
+ variant: "body2",
284
+ noWrap: true,
285
+ className: "px-1 tabular-nums",
286
+ children: [
287
+ value.lat.toFixed(6),
288
+ ", ",
289
+ value.lng.toFixed(6)
290
+ ]
291
+ });
292
+ return /* @__PURE__ */ jsx(Typography, {
293
+ variant: "body2",
294
+ color: "secondary",
295
+ className: "px-1",
296
+ children: String(value)
297
+ });
298
+ }
299
+ //#endregion
300
+ export { DefaultCellRenderer };
301
+
302
+ //# sourceMappingURL=DefaultCellRenderer.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DefaultCellRenderer.es.js","names":[],"sources":["../../../src/views/CollectionView/DefaultCellRenderer.tsx"],"sourcesContent":["import React from \"react\";\nimport { ImageIcon } from \"lucide-react\";\nimport { cls } from \"../../util\";\nimport { Typography } from \"../../components/Typography\";\nimport { Chip } from \"../../components/Chip\";\nimport { BooleanSwitch } from \"../../components/BooleanSwitch\";\nimport { Markdown } from \"../../components/Markdown\";\nimport { Tooltip } from \"../../components/Tooltip\";\nimport { iconSize } from \"../../icons\";\nimport type { CellRendererProps, CollectionPropertyConfig, CollectionEnumValueConfig } from \"./CollectionViewTypes\";\n\n// ——— Helpers ———\n\n/**\n * Resolve an enum key to its display label and optional color.\n */\nfunction resolveEnumLabel(\n enumValues: CollectionPropertyConfig[\"enum\"],\n value: unknown\n): { label: string; color?: string } | undefined {\n if (!enumValues) return undefined;\n const key = String(value);\n if (enumValues instanceof Map) {\n const config: CollectionEnumValueConfig | undefined = enumValues.get(value as string | number);\n if (!config) return undefined;\n if (typeof config === \"string\") return { label: config };\n return { label: config.label, color: config.color };\n }\n const config: CollectionEnumValueConfig | undefined = enumValues[key];\n if (!config) return undefined;\n if (typeof config === \"string\") return { label: config };\n return { label: config.label, color: config.color };\n}\n\n/**\n * Format a date value using Intl.DateTimeFormat.\n */\nfunction formatDate(value: unknown, includeTime: boolean): string {\n if (value == null) return \"—\";\n const date = value instanceof Date ? value : new Date(String(value));\n if (isNaN(date.getTime())) return String(value);\n\n const options: Intl.DateTimeFormatOptions = includeTime\n ? { year: \"numeric\", month: \"short\", day: \"numeric\", hour: \"2-digit\", minute: \"2-digit\" }\n : { year: \"numeric\", month: \"short\", day: \"numeric\" };\n\n return new Intl.DateTimeFormat(undefined, options).format(date);\n}\n\n/**\n * Type guard for geopoint-like objects.\n */\nfunction isGeoPoint(value: unknown): value is { lat: number; lng: number } {\n if (typeof value !== \"object\" || value === null) return false;\n const obj = value as Record<string, unknown>;\n return typeof obj.lat === \"number\" && typeof obj.lng === \"number\";\n}\n\n// ——— Component ———\n\n/**\n * Default cell renderer for the headless CollectionView.\n * Handles all built-in property types without depending on any Rebase core types.\n *\n * @group Preview components\n */\nexport function DefaultCellRenderer({\n row,\n propertyKey,\n property,\n value,\n size,\n width,\n height\n}: CellRendererProps) {\n\n // 1. Null / undefined → em-dash\n if (value === null || value === undefined) {\n return (\n <Typography variant=\"body2\"\n color=\"secondary\"\n className=\"px-1\">\n —\n </Typography>\n );\n }\n\n // 2. Custom Preview component override\n if (property.Preview) {\n const PreviewComponent = property.Preview;\n return (\n <PreviewComponent\n row={row}\n propertyKey={propertyKey}\n property={property}\n value={value}\n size={size}\n width={width}\n height={height}\n />\n );\n }\n\n // ——— Type-specific renderers ———\n\n switch (property.type) {\n case \"string\":\n return renderString(property, value);\n\n case \"number\":\n return renderNumber(property, value);\n\n case \"boolean\":\n return renderBoolean(value);\n\n case \"date\":\n return renderDate(property, value);\n\n case \"array\":\n return renderArray(property, value);\n\n case \"map\":\n return renderMap(value);\n\n case \"reference\":\n case \"relation\":\n return renderReference(value);\n\n case \"geopoint\":\n return renderGeopoint(value);\n\n default:\n return (\n <Typography variant=\"body2\"\n color=\"secondary\"\n noWrap\n className=\"px-1\">\n {JSON.stringify(value)}\n </Typography>\n );\n }\n}\n\n// ——— Per-type render functions ———\n\nfunction renderString(property: CollectionPropertyConfig, value: unknown): React.ReactElement {\n const strValue = String(value);\n\n // Enum → Chip\n if (property.enum) {\n const resolved = resolveEnumLabel(property.enum, value);\n return (\n <Chip size=\"small\"\n colorScheme={resolved?.color ? { color: resolved.color, text: \"#fff\" } : undefined}>\n {resolved?.label ?? strValue}\n </Chip>\n );\n }\n\n // Preview as tag → Chip\n if (property.previewAsTag) {\n return (\n <Chip size=\"small\">\n {strValue}\n </Chip>\n );\n }\n\n // URL → clickable link\n if (property.url) {\n const href = typeof property.url === \"string\" ? property.url : strValue;\n return (\n <Typography variant=\"body2\"\n noWrap\n component=\"a\"\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={cls(\n \"px-1 text-primary hover:underline cursor-pointer\"\n )}>\n {strValue}\n </Typography>\n );\n }\n\n // Email → mailto link\n if (property.email) {\n return (\n <Typography variant=\"body2\"\n noWrap\n component=\"a\"\n href={`mailto:${strValue}`}\n className={cls(\n \"px-1 text-primary hover:underline cursor-pointer\"\n )}>\n {strValue}\n </Typography>\n );\n }\n\n // Markdown → rendered markdown\n if (property.markdown) {\n return (\n <div className=\"px-1 max-h-[100px] overflow-hidden\">\n <Markdown source={strValue} size=\"small\" />\n </div>\n );\n }\n\n // Storage → image preview with fallback\n if (property.storage) {\n return (\n <div className={cls(\n \"px-1 flex items-center justify-center\",\n \"w-[40px] h-[40px] rounded overflow-hidden\"\n )}>\n {strValue ? (\n <img\n src={strValue}\n alt=\"\"\n className=\"w-full h-full object-cover\"\n onError={(e) => {\n const target = e.currentTarget;\n target.style.display = \"none\";\n const fallback = target.nextElementSibling;\n if (fallback instanceof HTMLElement) {\n fallback.style.display = \"flex\";\n }\n }}\n />\n ) : null}\n <div className={cls(\n \"w-full h-full items-center justify-center rounded\",\n \"bg-surface-raised text-text-secondary dark:text-text-secondary-dark\",\n strValue ? \"hidden\" : \"flex\"\n )}>\n <ImageIcon size={iconSize.small} />\n </div>\n </div>\n );\n }\n\n // Default string → truncated text\n return (\n <Tooltip title={strValue.length > 50 ? strValue : undefined}\n side=\"bottom\">\n <Typography variant=\"body2\"\n noWrap\n className=\"px-1\">\n {strValue}\n </Typography>\n </Tooltip>\n );\n}\n\nfunction renderNumber(property: CollectionPropertyConfig, value: unknown): React.ReactElement {\n const numStr = String(value);\n\n // Enum → Chip\n if (property.enum) {\n const resolved = resolveEnumLabel(property.enum, value);\n return (\n <Chip size=\"small\"\n colorScheme={resolved?.color ? { color: resolved.color, text: \"#fff\" } : undefined}>\n {resolved?.label ?? numStr}\n </Chip>\n );\n }\n\n // Default → right-aligned\n return (\n <Typography variant=\"body2\"\n noWrap\n align=\"right\"\n className=\"px-1 tabular-nums\">\n {numStr}\n </Typography>\n );\n}\n\nfunction renderBoolean(value: unknown): React.ReactElement {\n return (\n <div className=\"px-1 flex items-center\">\n <BooleanSwitch value={!!value}\n size=\"small\"\n disabled />\n </div>\n );\n}\n\nfunction renderDate(property: CollectionPropertyConfig, value: unknown): React.ReactElement {\n const includeTime = property.mode === \"date_time\";\n const formatted = formatDate(value, includeTime);\n\n return (\n <Typography variant=\"body2\"\n noWrap\n className=\"px-1 tabular-nums\">\n {formatted}\n </Typography>\n );\n}\n\nfunction renderArray(property: CollectionPropertyConfig, value: unknown): React.ReactElement {\n if (!Array.isArray(value)) {\n return (\n <Typography variant=\"body2\"\n color=\"secondary\"\n className=\"px-1\">\n —\n </Typography>\n );\n }\n\n // Array of enum values → row of chips\n if (property.of?.enum && value.length > 0) {\n return (\n <div className=\"px-1 flex flex-wrap gap-1 overflow-hidden\">\n {value.map((item, i) => {\n const resolved = resolveEnumLabel(property.of!.enum, item);\n return (\n <Chip key={i}\n size=\"smallest\"\n colorScheme={resolved?.color ? { color: resolved.color, text: \"#fff\" } : undefined}>\n {resolved?.label ?? String(item)}\n </Chip>\n );\n })}\n </div>\n );\n }\n\n // Array of strings → comma-separated\n if (value.length > 0 && value.every((item) => typeof item === \"string\")) {\n return (\n <Typography variant=\"body2\"\n noWrap\n className=\"px-1\">\n {(value as string[]).join(\", \")}\n </Typography>\n );\n }\n\n // Generic array → item count\n return (\n <Typography variant=\"body2\"\n color=\"secondary\"\n className=\"px-1\">\n {value.length} {value.length === 1 ? \"item\" : \"items\"}\n </Typography>\n );\n}\n\nfunction renderMap(value: unknown): React.ReactElement {\n if (typeof value !== \"object\" || value === null) {\n return (\n <Typography variant=\"body2\"\n color=\"secondary\"\n className=\"px-1\">\n —\n </Typography>\n );\n }\n\n const fieldCount = Object.keys(value as Record<string, unknown>).length;\n return (\n <Typography variant=\"body2\"\n color=\"secondary\"\n className=\"px-1\">\n {fieldCount} {fieldCount === 1 ? \"field\" : \"fields\"}\n </Typography>\n );\n}\n\nfunction renderReference(value: unknown): React.ReactElement {\n return (\n <Typography variant=\"body2\"\n noWrap\n className=\"px-1\">\n {String(value)}\n </Typography>\n );\n}\n\nfunction renderGeopoint(value: unknown): React.ReactElement {\n if (isGeoPoint(value)) {\n return (\n <Typography variant=\"body2\"\n noWrap\n className=\"px-1 tabular-nums\">\n {value.lat.toFixed(6)}, {value.lng.toFixed(6)}\n </Typography>\n );\n }\n\n return (\n <Typography variant=\"body2\"\n color=\"secondary\"\n className=\"px-1\">\n {String(value)}\n </Typography>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ //#region src/views/CollectionView/resolveTitleProperty.ts
2
+ /**
3
+ * Pick the property that acts as a row's title.
4
+ *
5
+ * Headless mirror of the ranking in `@rebasepro/common`: identifiers are kept
6
+ * out of the title slot structurally (the id property, images, hidden fields),
7
+ * and among what is left a plain text field beats a description, an enum or a
8
+ * relation. Falls back to the id property only when a collection has nothing
9
+ * else to show.
10
+ */
11
+ function resolveTitlePropertyKey(order, properties, idProperty, titleProperty) {
12
+ if (titleProperty) return titleProperty;
13
+ const SCORE = {
14
+ RELATION: 10,
15
+ LONG_TEXT: 20,
16
+ ENUM: 30,
17
+ EMAIL: 45,
18
+ PLAIN_TEXT: 60,
19
+ NAMED: 100
20
+ };
21
+ const titleLikeKeys = /* @__PURE__ */ new Set([
22
+ "name",
23
+ "fullname",
24
+ "displayname",
25
+ "title",
26
+ "label",
27
+ "heading",
28
+ "subject",
29
+ "username",
30
+ "nickname"
31
+ ]);
32
+ let best;
33
+ order.forEach((key) => {
34
+ const property = properties[key];
35
+ if (!property || property.hideFromCollection) return;
36
+ if (key === idProperty) return;
37
+ if (property.storage || property.url === "image") return;
38
+ let score;
39
+ if (property.type === "relation" || property.type === "reference") score = SCORE.RELATION;
40
+ else if (property.type !== "string") return;
41
+ else if (property.enum) score = SCORE.ENUM;
42
+ else if (property.multiline || property.markdown) score = SCORE.LONG_TEXT;
43
+ else if (property.email) score = SCORE.EMAIL;
44
+ else if (titleLikeKeys.has(key.toLowerCase().replace(/[^a-z0-9]/g, ""))) score = SCORE.NAMED;
45
+ else score = SCORE.PLAIN_TEXT;
46
+ if (!best || score > best.score) best = {
47
+ key,
48
+ score
49
+ };
50
+ });
51
+ return best?.key ?? idProperty;
52
+ }
53
+ //#endregion
54
+ export { resolveTitlePropertyKey };
55
+
56
+ //# sourceMappingURL=resolveTitleProperty.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveTitleProperty.es.js","names":[],"sources":["../../../src/views/CollectionView/resolveTitleProperty.ts"],"sourcesContent":["import type { CollectionPropertyConfig } from \"./CollectionViewTypes\";\n\n/**\n * Pick the property that acts as a row's title.\n *\n * Headless mirror of the ranking in `@rebasepro/common`: identifiers are kept\n * out of the title slot structurally (the id property, images, hidden fields),\n * and among what is left a plain text field beats a description, an enum or a\n * relation. Falls back to the id property only when a collection has nothing\n * else to show.\n */\nexport function resolveTitlePropertyKey(\n order: string[],\n properties: Record<string, CollectionPropertyConfig>,\n idProperty: string,\n titleProperty?: string\n): string {\n if (titleProperty) return titleProperty;\n\n const SCORE = {\n RELATION: 10,\n LONG_TEXT: 20,\n ENUM: 30,\n EMAIL: 45,\n PLAIN_TEXT: 60,\n NAMED: 100\n };\n const titleLikeKeys = new Set([\"name\", \"fullname\", \"displayname\", \"title\", \"label\", \"heading\", \"subject\", \"username\", \"nickname\"]);\n\n let best: { key: string; score: number } | undefined;\n\n order.forEach(key => {\n const property = properties[key];\n if (!property || property.hideFromCollection) return;\n if (key === idProperty) return;\n if (property.storage || property.url === \"image\") return;\n\n let score: number;\n if (property.type === \"relation\" || property.type === \"reference\") score = SCORE.RELATION;\n else if (property.type !== \"string\") return;\n else if (property.enum) score = SCORE.ENUM;\n else if (property.multiline || property.markdown) score = SCORE.LONG_TEXT;\n else if (property.email) score = SCORE.EMAIL;\n else if (titleLikeKeys.has(key.toLowerCase().replace(/[^a-z0-9]/g, \"\"))) score = SCORE.NAMED;\n else score = SCORE.PLAIN_TEXT;\n\n if (!best || score > best.score) best = { key,\nscore };\n });\n\n return best?.key ?? idProperty;\n}\n"],"mappings":";;;;;;;;;;AAWA,SAAgB,wBACZ,OACA,YACA,YACA,eACM;CACN,IAAI,eAAe,OAAO;CAE1B,MAAM,QAAQ;EACV,UAAU;EACV,WAAW;EACX,MAAM;EACN,OAAO;EACP,YAAY;EACZ,OAAO;CACX;CACA,MAAM,gCAAgB,IAAI,IAAI;EAAC;EAAQ;EAAY;EAAe;EAAS;EAAS;EAAW;EAAW;EAAY;CAAU,CAAC;CAEjI,IAAI;CAEJ,MAAM,SAAQ,QAAO;EACjB,MAAM,WAAW,WAAW;EAC5B,IAAI,CAAC,YAAY,SAAS,oBAAoB;EAC9C,IAAI,QAAQ,YAAY;EACxB,IAAI,SAAS,WAAW,SAAS,QAAQ,SAAS;EAElD,IAAI;EACJ,IAAI,SAAS,SAAS,cAAc,SAAS,SAAS,aAAa,QAAQ,MAAM;OAC5E,IAAI,SAAS,SAAS,UAAU;OAChC,IAAI,SAAS,MAAM,QAAQ,MAAM;OACjC,IAAI,SAAS,aAAa,SAAS,UAAU,QAAQ,MAAM;OAC3D,IAAI,SAAS,OAAO,QAAQ,MAAM;OAClC,IAAI,cAAc,IAAI,IAAI,YAAY,CAAC,CAAC,QAAQ,cAAc,EAAE,CAAC,GAAG,QAAQ,MAAM;OAClF,QAAQ,MAAM;EAEnB,IAAI,CAAC,QAAQ,QAAQ,KAAK,OAAO,OAAO;GAAE;GAClD;EAAM;CACF,CAAC;CAED,OAAO,MAAM,OAAO;AACxB"}
@@ -0,0 +1,19 @@
1
+ //#region src/views/CollectionView/utils.ts
2
+ /**
3
+ * Traverse an object by dot-separated path.
4
+ * Returns `undefined` if any segment is missing.
5
+ */
6
+ function getValueInPath(obj, path) {
7
+ if (!obj) return void 0;
8
+ const parts = path.split(".");
9
+ let current = obj;
10
+ for (const part of parts) {
11
+ if (current === null || current === void 0 || typeof current !== "object") return void 0;
12
+ current = current[part];
13
+ }
14
+ return current;
15
+ }
16
+ //#endregion
17
+ export { getValueInPath };
18
+
19
+ //# sourceMappingURL=utils.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.es.js","names":[],"sources":["../../../src/views/CollectionView/utils.ts"],"sourcesContent":["/**\n * Traverse an object by dot-separated path.\n * Returns `undefined` if any segment is missing.\n */\nexport function getValueInPath(obj: Record<string, unknown> | undefined, path: string): unknown {\n if (!obj) return undefined;\n const parts = path.split(\".\");\n let current: unknown = obj;\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== \"object\") return undefined;\n current = (current as Record<string, unknown>)[part];\n }\n return current;\n}\n"],"mappings":";;;;;AAIA,SAAgB,eAAe,KAA0C,MAAuB;CAC5F,IAAI,CAAC,KAAK,OAAO,KAAA;CACjB,MAAM,QAAQ,KAAK,MAAM,GAAG;CAC5B,IAAI,UAAmB;CACvB,KAAK,MAAM,QAAQ,OAAO;EACtB,IAAI,YAAY,QAAQ,YAAY,KAAA,KAAa,OAAO,YAAY,UAAU,OAAO,KAAA;EACrF,UAAW,QAAoC;CACnD;CACA,OAAO;AACX"}
@@ -0,0 +1,237 @@
1
+ import { cls } from "../../util/cls.es.js";
2
+ import { BoardColumn } from "./BoardColumn.es.js";
3
+ import { placeDroppedCard } from "./placement.es.js";
4
+ import { useEffect, useRef, useState } from "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { createPortal } from "react-dom";
7
+ import { SortableContext, arrayMove } from "@dnd-kit/sortable";
8
+ import { DndContext, DragOverlay, PointerSensor, closestCorners, useSensor, useSensors } from "@dnd-kit/core";
9
+ //#region src/views/Kanban/Board.tsx
10
+ function Board({ data, columns: columnsProp, columnLabels, columnColors, className, assignColumn, allowColumnReorder = false, onColumnReorder, onItemsReorder, ItemComponent, columnLoadingState, onLoadMoreColumn, onAddItemToColumn, AddColumnComponent }) {
11
+ const [activeItem, setActiveItem] = useState(null);
12
+ const [isDragging, setIsDragging] = useState(false);
13
+ const [dragOverColumnId, setDragOverColumnId] = useState(null);
14
+ /**
15
+ * Which column the card was picked up from.
16
+ *
17
+ * `handleDragOver` moves the card between columns in `itemMapState` while
18
+ * the pointer is still down — that is what makes the gap open up under the
19
+ * cursor. So by the time the drop is handled, looking the card up by id
20
+ * finds it in its *destination*, and the board was reporting the move as
21
+ * source === target: a cross-column drop looked like a plain reorder and
22
+ * the column property was never written. The card snapped back on the next
23
+ * fetch.
24
+ */
25
+ const dragSourceColumnRef = useRef(null);
26
+ const [itemMapState, setItemMapState] = useState(() => {
27
+ const dataColumnMap = data.reduce((prev, item) => ({
28
+ ...prev,
29
+ [item.id]: assignColumn(item)
30
+ }), {});
31
+ return columnsProp.reduce((previous, column) => ({
32
+ ...previous,
33
+ [column]: data.filter((item) => dataColumnMap[item.id] === column)
34
+ }), {});
35
+ });
36
+ const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 5 } }));
37
+ useEffect(() => {
38
+ if (isDragging) return;
39
+ const dataColumnMap = data.reduce((prev, item) => ({
40
+ ...prev,
41
+ [item.id]: assignColumn(item)
42
+ }), {});
43
+ const newItemMap = columnsProp.reduce((previous, column) => ({
44
+ ...previous,
45
+ [column]: data.filter((item) => dataColumnMap[item.id] === column)
46
+ }), {});
47
+ setItemMapState((prevMap) => {
48
+ let changed = false;
49
+ for (const col of columnsProp) {
50
+ const prevItems = prevMap[col] ?? [];
51
+ const newItems = newItemMap[col] ?? [];
52
+ if (prevItems.length !== newItems.length) {
53
+ changed = true;
54
+ continue;
55
+ }
56
+ for (let i = 0; i < prevItems.length; i++) if (prevItems[i].id !== newItems[i].id || prevItems[i].data !== newItems[i].data) {
57
+ changed = true;
58
+ break;
59
+ }
60
+ }
61
+ if (!changed) return prevMap;
62
+ const updated = {};
63
+ for (const col of columnsProp) {
64
+ const prevItems = prevMap[col] ?? [];
65
+ const newItems = newItemMap[col] ?? [];
66
+ const prevById = /* @__PURE__ */ new Map();
67
+ for (const item of prevItems) prevById.set(item.id, item);
68
+ updated[col] = newItems.map((newItem) => {
69
+ const prev = prevById.get(newItem.id);
70
+ if (prev && prev.data === newItem.data) return prev;
71
+ return newItem;
72
+ });
73
+ }
74
+ return updated;
75
+ });
76
+ }, [
77
+ data,
78
+ columnsProp,
79
+ assignColumn
80
+ ]);
81
+ const findColumnByItemId = (id) => {
82
+ return Object.keys(itemMapState).find((col) => itemMapState[col]?.some((i) => i.id === id));
83
+ };
84
+ const handleDragStart = (event) => {
85
+ setIsDragging(true);
86
+ setDragOverColumnId(null);
87
+ const { active } = event;
88
+ if (active.data.current?.type === "ITEM") {
89
+ const columnId = findColumnByItemId(active.id);
90
+ dragSourceColumnRef.current = columnId ?? null;
91
+ if (columnId) {
92
+ const item = itemMapState[columnId]?.find((i) => i.id === active.id);
93
+ setActiveItem(item || null);
94
+ }
95
+ }
96
+ };
97
+ const handleDragOver = (event) => {
98
+ const { active, over } = event;
99
+ if (!over) {
100
+ setDragOverColumnId(null);
101
+ return;
102
+ }
103
+ let currentHoveredColumnId = null;
104
+ const overId = over.id;
105
+ const overDataType = over.data.current?.type;
106
+ if (overDataType === "ITEM-LIST" || overDataType === "COLUMN") currentHoveredColumnId = overId;
107
+ else if (overDataType === "ITEM") currentHoveredColumnId = findColumnByItemId(overId) || null;
108
+ else if (columnsProp.includes(overId)) currentHoveredColumnId = overId;
109
+ setDragOverColumnId(currentHoveredColumnId);
110
+ if (active.data.current?.type !== "ITEM") return;
111
+ const activeId = active.id;
112
+ const activeItemColumn = findColumnByItemId(activeId);
113
+ let overColumnForMove = findColumnByItemId(overId);
114
+ if (!overColumnForMove && overDataType === "ITEM-LIST") overColumnForMove = overId;
115
+ if (!overColumnForMove && columnsProp.includes(overId)) overColumnForMove = overId;
116
+ if (!activeItemColumn || !overColumnForMove) return;
117
+ if (activeItemColumn === overColumnForMove) return;
118
+ if (itemMapState[overColumnForMove]?.some((i) => i.id === activeId)) return;
119
+ setItemMapState((currentMap) => {
120
+ const activeItems = [...currentMap[activeItemColumn] || []];
121
+ const overItems = [...currentMap[overColumnForMove] || []];
122
+ const activeIndex = activeItems.findIndex((i) => i.id === activeId);
123
+ if (activeIndex === -1) return currentMap;
124
+ let overIndex;
125
+ if (overDataType === "ITEM-LIST" || columnsProp.includes(overId) && !findColumnByItemId(overId)) overIndex = overItems.length;
126
+ else {
127
+ overIndex = overItems.findIndex((i) => i.id === overId);
128
+ if (overIndex !== -1) {
129
+ const modifier = (active.rect.current.translated?.top ?? 0) + (active.rect.current.translated?.height ?? 0) / 2 > (over?.rect.top ?? 0) + (over?.rect.height ?? 0) / 2 ? 1 : 0;
130
+ overIndex = overIndex >= 0 ? overIndex + modifier : overItems.length;
131
+ } else overIndex = overItems.length;
132
+ }
133
+ const newItemMap = { ...currentMap };
134
+ const [moved] = activeItems.splice(activeIndex, 1);
135
+ overItems.splice(overIndex, 0, moved);
136
+ newItemMap[activeItemColumn] = activeItems;
137
+ newItemMap[overColumnForMove] = overItems;
138
+ return newItemMap;
139
+ });
140
+ };
141
+ const handleDragCancel = () => {
142
+ setIsDragging(false);
143
+ setActiveItem(null);
144
+ setDragOverColumnId(null);
145
+ dragSourceColumnRef.current = null;
146
+ };
147
+ const handleDragEnd = (event) => {
148
+ const { active, over } = event;
149
+ const sourceColumn = dragSourceColumnRef.current;
150
+ setIsDragging(false);
151
+ setActiveItem(null);
152
+ setDragOverColumnId(null);
153
+ dragSourceColumnRef.current = null;
154
+ if (!over) return;
155
+ const activeId = active.id;
156
+ const overId = over.id;
157
+ if (active.data.current?.type === "COLUMN") {
158
+ if (activeId !== overId) {
159
+ const oldIndex = columnsProp.indexOf(activeId);
160
+ const newIndex = columnsProp.indexOf(overId);
161
+ if (oldIndex !== -1 && newIndex !== -1) {
162
+ const reordered = arrayMove(columnsProp, oldIndex, newIndex);
163
+ onColumnReorder?.(reordered);
164
+ }
165
+ }
166
+ return;
167
+ }
168
+ const currentCol = findColumnByItemId(activeId);
169
+ let targetCol = findColumnByItemId(overId);
170
+ if (!targetCol) {
171
+ if (over.data.current?.type === "ITEM-LIST" || columnsProp.includes(overId)) targetCol = overId;
172
+ }
173
+ targetCol = targetCol ?? currentCol;
174
+ if (!currentCol || !targetCol) return;
175
+ const targetItems = itemMapState[targetCol] || [];
176
+ const movedItem = (itemMapState[currentCol] || []).find((i) => i.id === activeId);
177
+ if (!movedItem) return;
178
+ const finalTargetItems = placeDroppedCard({
179
+ targetItems,
180
+ movedItem,
181
+ overId,
182
+ changedColumn: (sourceColumn ?? currentCol) !== targetCol
183
+ });
184
+ onItemsReorder?.(finalTargetItems, {
185
+ itemId: activeId,
186
+ sourceColumn: sourceColumn ?? currentCol,
187
+ targetColumn: targetCol
188
+ });
189
+ };
190
+ return /* @__PURE__ */ jsxs(DndContext, {
191
+ sensors,
192
+ collisionDetection: closestCorners,
193
+ onDragStart: handleDragStart,
194
+ onDragOver: handleDragOver,
195
+ onDragEnd: handleDragEnd,
196
+ onDragCancel: handleDragCancel,
197
+ children: [/* @__PURE__ */ jsxs("div", {
198
+ className: cls("flex flex-row h-full w-full overflow-x-auto p-4 select-none items-start", className),
199
+ children: [/* @__PURE__ */ jsx(SortableContext, {
200
+ items: columnsProp,
201
+ children: columnsProp.map((col, index) => {
202
+ const colItems = itemMapState[col] || [];
203
+ const loadingState = columnLoadingState?.[col];
204
+ return /* @__PURE__ */ jsx(BoardColumn, {
205
+ id: String(col),
206
+ title: columnLabels?.[col] ?? String(col),
207
+ items: colItems,
208
+ index,
209
+ ItemComponent,
210
+ isDragging,
211
+ isDragOverColumn: dragOverColumnId === String(col),
212
+ allowReorder: allowColumnReorder,
213
+ loading: loadingState?.loading,
214
+ hasMore: loadingState?.hasMore,
215
+ error: loadingState?.error,
216
+ totalCount: loadingState?.totalCount,
217
+ color: columnColors?.[col],
218
+ onLoadMore: onLoadMoreColumn ? () => onLoadMoreColumn(col) : void 0,
219
+ onAddItem: onAddItemToColumn ? () => onAddItemToColumn(col) : void 0
220
+ }, String(col));
221
+ })
222
+ }), AddColumnComponent]
223
+ }), typeof document !== "undefined" && createPortal(/* @__PURE__ */ jsx(DragOverlay, {
224
+ dropAnimation: null,
225
+ zIndex: 9999,
226
+ children: activeItem && /* @__PURE__ */ jsx(ItemComponent, {
227
+ item: activeItem,
228
+ isDragging: true,
229
+ isClone: true
230
+ })
231
+ }), document.body)]
232
+ });
233
+ }
234
+ //#endregion
235
+ export { Board };
236
+
237
+ //# sourceMappingURL=Board.es.js.map