@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,96 @@
1
+ import React from "react";
2
+ //#region src/util/lazy_chunk.ts
3
+ /**
4
+ * Dynamic imports that survive a redeploy.
5
+ *
6
+ * A built SPA names its chunks by content hash and a deploy replaces the whole
7
+ * `assets/` directory, so a tab opened before the deploy still holds the *old*
8
+ * entry chunk. The first lazy route that tab opens asks for a hash that no
9
+ * longer exists on the server, the import rejects, and the view is dead until
10
+ * the user thinks to reload — which nothing on screen tells them to do. The
11
+ * browser's own wording ("Failed to fetch dynamically imported module: …") reads
12
+ * like a build bug, so this is usually reported as one.
13
+ *
14
+ * `loadChunk` retries once — that covers a transient network failure — and then
15
+ * gives up with an error tagged as a chunk load failure, so `ErrorBoundary` can
16
+ * offer a reload instead of printing the browser's message.
17
+ */
18
+ /**
19
+ * Marker property set on the error thrown after a failed retry. Read by
20
+ * `isChunkLoadError`, which is what the UI matches on.
21
+ */
22
+ var CHUNK_LOAD_ERROR_FLAG = "rebaseChunkLoadError";
23
+ /**
24
+ * Each engine words this differently, and the message is the only signal — none
25
+ * of them use a distinguishable error type. The MIME variants matter as much as
26
+ * the fetch ones: a server whose SPA fallback answers a missing `/assets/x.js`
27
+ * with `index.html` returns 200 HTML, and the browser rejects it as a module.
28
+ */
29
+ var CHUNK_ERROR_PATTERNS = [
30
+ "failed to fetch dynamically imported module",
31
+ "error loading dynamically imported module",
32
+ "importing a module script failed",
33
+ "failed to load module script",
34
+ "expected a javascript",
35
+ "unable to preload css"
36
+ ];
37
+ /**
38
+ * Does this error mean a chunk could not be loaded — rather than the chunk's
39
+ * own code throwing once it did load?
40
+ *
41
+ * Errors raised anywhere are matched, not just ones `loadChunk` produced: React
42
+ * `lazy()` calls that still import directly, and Vite's own CSS preloads, fail
43
+ * the same way and deserve the same recovery.
44
+ */
45
+ function isChunkLoadError(error) {
46
+ if (!error || typeof error !== "object") return false;
47
+ if (error[CHUNK_LOAD_ERROR_FLAG] === true) return true;
48
+ const message = error.message;
49
+ if (typeof message !== "string") return false;
50
+ const lower = message.toLowerCase();
51
+ return CHUNK_ERROR_PATTERNS.some((pattern) => lower.includes(pattern));
52
+ }
53
+ function chunkLoadError(cause) {
54
+ const error = /* @__PURE__ */ new Error("This app was updated while the tab was open, so part of it could not be loaded. Reload to continue.");
55
+ Object.assign(error, {
56
+ [CHUNK_LOAD_ERROR_FLAG]: true,
57
+ cause
58
+ });
59
+ return error;
60
+ }
61
+ /**
62
+ * Run a dynamic import, retrying once before declaring the chunk unreachable.
63
+ *
64
+ * Errors that are not chunk load failures — the imported module throwing while
65
+ * it evaluates, say — are re-thrown untouched and never retried: running a
66
+ * module's side effects twice is worse than the original failure.
67
+ */
68
+ async function loadChunk(loader) {
69
+ try {
70
+ return await loader();
71
+ } catch (error) {
72
+ if (!isChunkLoadError(error)) throw error;
73
+ await new Promise((resolve) => setTimeout(resolve, 250));
74
+ try {
75
+ return await loader();
76
+ } catch (retryError) {
77
+ throw chunkLoadError(retryError);
78
+ }
79
+ }
80
+ }
81
+ /**
82
+ * `React.lazy` with the retry above. A drop-in replacement — use it for every
83
+ * lazy route or dialog, since any one of them can be the first chunk a stale
84
+ * tab reaches for.
85
+ *
86
+ * Note that React caches the rejection: once a lazy component has failed, later
87
+ * renders re-throw without calling the loader again. Resetting an error boundary
88
+ * therefore cannot recover it, which is why the boundary offers a reload.
89
+ */
90
+ function lazyChunk(loader) {
91
+ return React.lazy(() => loadChunk(loader));
92
+ }
93
+ //#endregion
94
+ export { isChunkLoadError, lazyChunk, loadChunk };
95
+
96
+ //# sourceMappingURL=lazy_chunk.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lazy_chunk.es.js","names":[],"sources":["../../src/util/lazy_chunk.ts"],"sourcesContent":["import React from \"react\";\n\n/**\n * Dynamic imports that survive a redeploy.\n *\n * A built SPA names its chunks by content hash and a deploy replaces the whole\n * `assets/` directory, so a tab opened before the deploy still holds the *old*\n * entry chunk. The first lazy route that tab opens asks for a hash that no\n * longer exists on the server, the import rejects, and the view is dead until\n * the user thinks to reload — which nothing on screen tells them to do. The\n * browser's own wording (\"Failed to fetch dynamically imported module: …\") reads\n * like a build bug, so this is usually reported as one.\n *\n * `loadChunk` retries once — that covers a transient network failure — and then\n * gives up with an error tagged as a chunk load failure, so `ErrorBoundary` can\n * offer a reload instead of printing the browser's message.\n */\n\n/**\n * Marker property set on the error thrown after a failed retry. Read by\n * `isChunkLoadError`, which is what the UI matches on.\n */\nconst CHUNK_LOAD_ERROR_FLAG = \"rebaseChunkLoadError\";\n\n/**\n * Each engine words this differently, and the message is the only signal — none\n * of them use a distinguishable error type. The MIME variants matter as much as\n * the fetch ones: a server whose SPA fallback answers a missing `/assets/x.js`\n * with `index.html` returns 200 HTML, and the browser rejects it as a module.\n */\nconst CHUNK_ERROR_PATTERNS = [\n \"failed to fetch dynamically imported module\",\n \"error loading dynamically imported module\",\n \"importing a module script failed\",\n \"failed to load module script\",\n \"expected a javascript\",\n \"unable to preload css\"\n];\n\n/**\n * Does this error mean a chunk could not be loaded — rather than the chunk's\n * own code throwing once it did load?\n *\n * Errors raised anywhere are matched, not just ones `loadChunk` produced: React\n * `lazy()` calls that still import directly, and Vite's own CSS preloads, fail\n * the same way and deserve the same recovery.\n */\nexport function isChunkLoadError(error: unknown): boolean {\n if (!error || typeof error !== \"object\") return false;\n if ((error as Record<string, unknown>)[CHUNK_LOAD_ERROR_FLAG] === true) return true;\n const message = (error as { message?: unknown }).message;\n if (typeof message !== \"string\") return false;\n const lower = message.toLowerCase();\n return CHUNK_ERROR_PATTERNS.some(pattern => lower.includes(pattern));\n}\n\nfunction chunkLoadError(cause: unknown): Error {\n const error = new Error(\n \"This app was updated while the tab was open, so part of it could not be loaded. Reload to continue.\"\n );\n Object.assign(error, { [CHUNK_LOAD_ERROR_FLAG]: true,\ncause });\n return error;\n}\n\n/**\n * Run a dynamic import, retrying once before declaring the chunk unreachable.\n *\n * Errors that are not chunk load failures — the imported module throwing while\n * it evaluates, say — are re-thrown untouched and never retried: running a\n * module's side effects twice is worse than the original failure.\n */\nexport async function loadChunk<T>(loader: () => Promise<T>): Promise<T> {\n try {\n return await loader();\n } catch (error) {\n if (!isChunkLoadError(error)) throw error;\n // A blip resolves inside a few hundred ms; a stale hash never will.\n await new Promise(resolve => setTimeout(resolve, 250));\n try {\n return await loader();\n } catch (retryError) {\n throw chunkLoadError(retryError);\n }\n }\n}\n\n/**\n * `React.lazy` with the retry above. A drop-in replacement — use it for every\n * lazy route or dialog, since any one of them can be the first chunk a stale\n * tab reaches for.\n *\n * Note that React caches the rejection: once a lazy component has failed, later\n * renders re-throw without calling the loader again. Resetting an error boundary\n * therefore cannot recover it, which is why the boundary offers a reload.\n */\nexport function lazyChunk<T extends React.ComponentType<any>>(\n loader: () => Promise<{ default: T }>\n): React.LazyExoticComponent<T> {\n return React.lazy(() => loadChunk(loader));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAsBA,IAAM,wBAAwB;;;;;;;AAQ9B,IAAM,uBAAuB;CACzB;CACA;CACA;CACA;CACA;CACA;AACJ;;;;;;;;;AAUA,SAAgB,iBAAiB,OAAyB;CACtD,IAAI,CAAC,SAAS,OAAO,UAAU,UAAU,OAAO;CAChD,IAAK,MAAkC,2BAA2B,MAAM,OAAO;CAC/E,MAAM,UAAW,MAAgC;CACjD,IAAI,OAAO,YAAY,UAAU,OAAO;CACxC,MAAM,QAAQ,QAAQ,YAAY;CAClC,OAAO,qBAAqB,MAAK,YAAW,MAAM,SAAS,OAAO,CAAC;AACvE;AAEA,SAAS,eAAe,OAAuB;CAC3C,MAAM,wBAAQ,IAAI,MACd,qGACJ;CACA,OAAO,OAAO,OAAO;GAAG,wBAAwB;EACpD;CAAM,CAAC;CACH,OAAO;AACX;;;;;;;;AASA,eAAsB,UAAa,QAAsC;CACrE,IAAI;EACA,OAAO,MAAM,OAAO;CACxB,SAAS,OAAO;EACZ,IAAI,CAAC,iBAAiB,KAAK,GAAG,MAAM;EAEpC,MAAM,IAAI,SAAQ,YAAW,WAAW,SAAS,GAAG,CAAC;EACrD,IAAI;GACA,OAAO,MAAM,OAAO;EACxB,SAAS,YAAY;GACjB,MAAM,eAAe,UAAU;EACnC;CACJ;AACJ;;;;;;;;;;AAWA,SAAgB,UACZ,QAC4B;CAC5B,OAAO,MAAM,WAAW,UAAU,MAAM,CAAC;AAC7C"}
@@ -2,7 +2,12 @@ import React from "react";
2
2
  import { CollectionSize } from "./ListView.js";
3
3
  import { type ViewScrollEvent } from "./useScrollParentRestoration.js";
4
4
  export type CardViewProps<T> = {
5
- data: T[];
5
+ /**
6
+ * The items, in order. A position holding `undefined` is an item that
7
+ * exists but has not been read yet: a placeholder card is drawn in its
8
+ * place, and `renderCard` is not called for it.
9
+ */
10
+ data: (T | undefined)[];
6
11
  dataLoading?: boolean;
7
12
  noMoreToLoad?: boolean;
8
13
  dataLoadingError?: Error;
@@ -17,6 +22,16 @@ export type CardViewProps<T> = {
17
22
  onSelectionChange?: (item: T, selected: boolean) => void;
18
23
  onScroll?: (props: ViewScrollEvent) => void;
19
24
  initialScroll?: number;
25
+ /**
26
+ * Called with the positions in `data` of the cards on screen — the rows
27
+ * of cards on screen, not the ones drawn ahead of them — end exclusive,
28
+ * each time they change. While the grid is still scrolling to
29
+ * `initialScroll`, the cards there.
30
+ */
31
+ onRowsRendered?: (range: {
32
+ start: number;
33
+ end: number;
34
+ }) => void;
20
35
  size?: CollectionSize;
21
36
  renderCard: (item: T, extra: {
22
37
  selected: boolean;
@@ -31,4 +46,13 @@ export type CardViewProps<T> = {
31
46
  }) => React.ReactNode;
32
47
  emptyComponent?: React.ReactNode;
33
48
  };
34
- export declare function CardView<T>({ data, dataLoading, noMoreToLoad, dataLoadingError, itemCount, setItemCount, pageSize, paginationEnabled, onItemClick, selectedIds, highlightedIds, selectionEnabled, onSelectionChange, onScroll, initialScroll, size, renderCard, emptyComponent }: CardViewProps<T>): React.JSX.Element;
49
+ /**
50
+ * A card grid that draws the rows of cards on screen and a couple either side.
51
+ *
52
+ * Every loaded card used to stay mounted — about 22 DOM nodes each, 44,000 at
53
+ * 2,000 cards. The grid looks as it did: each row is a grid with the same
54
+ * column classes and gap, and a row is as tall as its tallest card, measured
55
+ * as it is drawn rather than assumed. Rows not drawn yet count at the average
56
+ * height measured so far.
57
+ */
58
+ export declare function CardView<T>({ data, dataLoading, noMoreToLoad, dataLoadingError, itemCount, setItemCount, pageSize, paginationEnabled, onItemClick, selectedIds, highlightedIds, selectionEnabled, onSelectionChange, onScroll, initialScroll, onRowsRendered, size, renderCard, emptyComponent }: CardViewProps<T>): React.JSX.Element;
@@ -0,0 +1,435 @@
1
+ import { cls } from "../util/cls.es.js";
2
+ import { Card } from "../components/Card.es.js";
3
+ import { CircularProgress } from "../components/CircularProgress.es.js";
4
+ import { Typography } from "../components/Typography.es.js";
5
+ import { useUiLabels } from "../hooks/UiLabelsContext.es.js";
6
+ import { Skeleton } from "../components/Skeleton.es.js";
7
+ import { getScrollParent, useScrollParentRestoration } from "./useScrollParentRestoration.es.js";
8
+ import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ //#region src/views/CardView.tsx
11
+ function getGridColumnsClass(size) {
12
+ switch (size) {
13
+ case "xs": return "grid-cols-4 sm:grid-cols-5 md:grid-cols-6 lg:grid-cols-8 xl:grid-cols-10";
14
+ case "s": return "grid-cols-3 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-6 xl:grid-cols-8";
15
+ case "m": return "grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6";
16
+ case "l": return "grid-cols-2 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-4";
17
+ case "xl": return "grid-cols-1 sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3";
18
+ default: return "grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6";
19
+ }
20
+ }
21
+ /**
22
+ * The column count `getGridColumnsClass` gives at this viewport width — the
23
+ * Tailwind breakpoints are viewport widths. Only a fallback: the count is read
24
+ * off the grid as laid out whenever there is a layout to read it from.
25
+ */
26
+ function columnsAtWidth(size, width) {
27
+ const steps = {
28
+ xs: [
29
+ 4,
30
+ 5,
31
+ 6,
32
+ 8,
33
+ 10
34
+ ],
35
+ s: [
36
+ 3,
37
+ 4,
38
+ 5,
39
+ 6,
40
+ 8
41
+ ],
42
+ m: [
43
+ 2,
44
+ 3,
45
+ 4,
46
+ 5,
47
+ 6
48
+ ],
49
+ l: [
50
+ 2,
51
+ 2,
52
+ 3,
53
+ 4,
54
+ 4
55
+ ],
56
+ xl: [
57
+ 1,
58
+ 2,
59
+ 2,
60
+ 3,
61
+ 3
62
+ ]
63
+ };
64
+ const [base, sm, md, lg, xl] = steps[size] ?? steps.m;
65
+ if (width >= 1280) return xl;
66
+ if (width >= 1024) return lg;
67
+ if (width >= 768) return md;
68
+ if (width >= 640) return sm;
69
+ return base;
70
+ }
71
+ /** The tracks of a laid-out grid, or `undefined` where nothing is laid out. */
72
+ function columnsOf(grid) {
73
+ if (!grid) return void 0;
74
+ const tracks = window.getComputedStyle(grid).gridTemplateColumns;
75
+ if (!tracks || tracks === "none") return void 0;
76
+ const count = tracks.trim().split(/\s+/).filter((track) => !track.startsWith("[")).length;
77
+ return count > 0 ? count : void 0;
78
+ }
79
+ /** A first guess at a row of cards' height, gap included, before one is measured. */
80
+ function defaultRowHeight(size) {
81
+ switch (size) {
82
+ case "xs": return 170;
83
+ case "s": return 220;
84
+ case "l": return 370;
85
+ case "xl": return 440;
86
+ default: return 290;
87
+ }
88
+ }
89
+ /**
90
+ * The average row height measured last, per size and column count, so a grid
91
+ * that mounts again (coming back from a record) places its rows — and the
92
+ * scroll position it restores — with the heights the cards actually had.
93
+ */
94
+ var lastRowHeights = /* @__PURE__ */ new Map();
95
+ /** Rows of cards drawn above and below the screen. */
96
+ var OVERSCAN_ROWS = 2;
97
+ /** The grid's `gap-4`, which a row carries below it as padding. */
98
+ var ROW_GAP = 16;
99
+ /**
100
+ * A card grid that draws the rows of cards on screen and a couple either side.
101
+ *
102
+ * Every loaded card used to stay mounted — about 22 DOM nodes each, 44,000 at
103
+ * 2,000 cards. The grid looks as it did: each row is a grid with the same
104
+ * column classes and gap, and a row is as tall as its tallest card, measured
105
+ * as it is drawn rather than assumed. Rows not drawn yet count at the average
106
+ * height measured so far.
107
+ */
108
+ function CardView({ data, dataLoading = false, noMoreToLoad = false, dataLoadingError, itemCount, setItemCount, pageSize = 50, paginationEnabled = true, onItemClick, selectedIds, highlightedIds, selectionEnabled = true, onSelectionChange, onScroll, initialScroll, onRowsRendered, size = "m", renderCard, emptyComponent }) {
109
+ const labels = useUiLabels();
110
+ const containerRef = useRef(null);
111
+ const rowsRef = useRef(null);
112
+ const probeRef = useRef(null);
113
+ const isLoadingMore = useRef(false);
114
+ const gridColumnsClass = getGridColumnsClass(size);
115
+ const [columns, setColumns] = useState(() => columnsAtWidth(size, typeof window === "undefined" ? 1024 : window.innerWidth));
116
+ const [scrollTop, setScrollTop] = useState(0);
117
+ const [viewportHeight, setViewportHeight] = useState(800);
118
+ const [reported, setReported] = useState({
119
+ top: 0,
120
+ height: 800
121
+ });
122
+ const paginationStateRef = useRef({
123
+ paginationEnabled,
124
+ noMoreToLoad,
125
+ itemCount,
126
+ pageSize
127
+ });
128
+ useEffect(() => {
129
+ paginationStateRef.current = {
130
+ paginationEnabled,
131
+ noMoreToLoad,
132
+ itemCount,
133
+ pageSize
134
+ };
135
+ }, [
136
+ paginationEnabled,
137
+ noMoreToLoad,
138
+ itemCount,
139
+ pageSize
140
+ ]);
141
+ useEffect(() => {
142
+ if (!dataLoading) isLoadingMore.current = false;
143
+ }, [dataLoading]);
144
+ const { pendingScroll } = useScrollParentRestoration({
145
+ containerRef,
146
+ initialScroll,
147
+ onScroll,
148
+ dataLength: data.length
149
+ });
150
+ const readColumns = useCallback(() => {
151
+ const next = columnsOf(probeRef.current) ?? columnsAtWidth(size, window.innerWidth);
152
+ setColumns((current) => current === next ? current : next);
153
+ }, [size]);
154
+ useEffect(() => {
155
+ const el = containerRef.current;
156
+ if (!el) return;
157
+ const scrollEl = getScrollParent(el);
158
+ if (!scrollEl) return;
159
+ let rafId = null;
160
+ const update = () => {
161
+ rafId = null;
162
+ const scrollRect = scrollEl.getBoundingClientRect();
163
+ const rowsTopRelative = (rowsRef.current ?? el).getBoundingClientRect().top - scrollRect.top;
164
+ setScrollTop(Math.max(0, -rowsTopRelative));
165
+ setViewportHeight(scrollRect.height);
166
+ const restoring = pendingScroll.current;
167
+ const top = restoring ? restoring - (scrollEl.scrollTop + rowsTopRelative) : -rowsTopRelative;
168
+ const height = Math.max(0, scrollRect.height + Math.min(0, top));
169
+ setReported((current) => current.top === Math.max(0, top) && current.height === height ? current : {
170
+ top: Math.max(0, top),
171
+ height
172
+ });
173
+ const { paginationEnabled: pe, noMoreToLoad: nm, itemCount: ic, pageSize: ps } = paginationStateRef.current;
174
+ if (pe && !nm && !isLoadingMore.current && scrollEl.scrollHeight - scrollEl.scrollTop - scrollEl.clientHeight < 400) {
175
+ isLoadingMore.current = true;
176
+ setItemCount?.((ic ?? ps) + ps);
177
+ }
178
+ };
179
+ const onScrollEvent = () => {
180
+ if (rafId === null) rafId = requestAnimationFrame(update);
181
+ };
182
+ scrollEl.addEventListener("scroll", onScrollEvent, { passive: true });
183
+ const ro = new ResizeObserver(() => {
184
+ readColumns();
185
+ update();
186
+ });
187
+ ro.observe(scrollEl);
188
+ ro.observe(el);
189
+ readColumns();
190
+ update();
191
+ return () => {
192
+ scrollEl.removeEventListener("scroll", onScrollEvent);
193
+ ro.disconnect();
194
+ if (rafId !== null) cancelAnimationFrame(rafId);
195
+ };
196
+ }, [
197
+ setItemCount,
198
+ readColumns,
199
+ pendingScroll
200
+ ]);
201
+ useLayoutEffect(() => readColumns(), [readColumns, gridColumnsClass]);
202
+ const heightsRef = useRef({
203
+ columns,
204
+ heights: /* @__PURE__ */ new Map()
205
+ });
206
+ if (heightsRef.current.columns !== columns) heightsRef.current = {
207
+ columns,
208
+ heights: /* @__PURE__ */ new Map()
209
+ };
210
+ const [measured, setMeasured] = useState(0);
211
+ const memoryKey = `${size}:${columns}`;
212
+ const observerRef = useRef(null);
213
+ useEffect(() => {
214
+ const observer = new ResizeObserver((entries) => {
215
+ let changed = false;
216
+ const { heights } = heightsRef.current;
217
+ for (const entry of entries) {
218
+ const target = entry.target;
219
+ const row = Number(target.dataset.row);
220
+ if (!Number.isFinite(row) || Number(target.dataset.columns) !== heightsRef.current.columns) continue;
221
+ const height = target.getBoundingClientRect().height;
222
+ if (height > 0 && heights.get(row) !== height) {
223
+ heights.set(row, height);
224
+ changed = true;
225
+ }
226
+ }
227
+ if (changed) setMeasured((n) => n + 1);
228
+ });
229
+ observerRef.current = observer;
230
+ return () => {
231
+ observer.disconnect();
232
+ observerRef.current = null;
233
+ };
234
+ }, []);
235
+ const observeRow = useCallback((element) => {
236
+ const observer = observerRef.current;
237
+ if (!element || !observer) return;
238
+ observer.observe(element);
239
+ return () => observer.unobserve(element);
240
+ }, []);
241
+ const rowCount = Math.ceil(data.length / columns);
242
+ const layout = useMemo(() => {
243
+ const { heights } = heightsRef.current;
244
+ let total = 0;
245
+ heights.forEach((height) => {
246
+ total += height;
247
+ });
248
+ const estimate = heights.size > 0 ? total / heights.size : lastRowHeights.get(memoryKey) ?? defaultRowHeight(size);
249
+ const tops = new Float64Array(rowCount + 1);
250
+ for (let r = 0; r < rowCount; r++) tops[r + 1] = tops[r] + (heights.get(r) ?? estimate);
251
+ return {
252
+ tops,
253
+ estimate
254
+ };
255
+ }, [
256
+ rowCount,
257
+ columns,
258
+ measured,
259
+ memoryKey,
260
+ size
261
+ ]);
262
+ useEffect(() => {
263
+ if (heightsRef.current.heights.size > 0) lastRowHeights.set(memoryKey, layout.estimate);
264
+ }, [layout, memoryKey]);
265
+ /** The row at this offset from the top of the rows. */
266
+ const rowAt = useCallback((offset) => {
267
+ const { tops } = layout;
268
+ let low = 0;
269
+ let high = rowCount;
270
+ while (low < high) {
271
+ const mid = low + high >> 1;
272
+ if (tops[mid + 1] <= offset) low = mid + 1;
273
+ else high = mid;
274
+ }
275
+ return Math.min(low, Math.max(0, rowCount - 1));
276
+ }, [layout, rowCount]);
277
+ const firstRow = rowCount === 0 ? 0 : Math.max(0, rowAt(scrollTop) - OVERSCAN_ROWS);
278
+ const lastRow = rowCount === 0 ? -1 : Math.min(rowCount - 1, rowAt(scrollTop + viewportHeight) + OVERSCAN_ROWS);
279
+ const visibleStart = rowCount === 0 ? 0 : Math.min(data.length, rowAt(reported.top) * columns);
280
+ const visibleEnd = rowCount === 0 || reported.height === 0 ? visibleStart : Math.min(data.length, (rowAt(reported.top + reported.height - 1) + 1) * columns);
281
+ useEffect(() => {
282
+ if (onRowsRendered && data.length > 0) onRowsRendered({
283
+ start: visibleStart,
284
+ end: visibleEnd
285
+ });
286
+ }, [
287
+ visibleStart,
288
+ visibleEnd,
289
+ onRowsRendered
290
+ ]);
291
+ useLayoutEffect(() => {
292
+ const { heights } = heightsRef.current;
293
+ let changed = false;
294
+ rowsRef.current?.querySelectorAll("[data-row]").forEach((element) => {
295
+ const row = Number(element.dataset.row);
296
+ if (heights.has(row)) return;
297
+ const height = element.getBoundingClientRect().height;
298
+ if (height > 0) {
299
+ heights.set(row, height);
300
+ changed = true;
301
+ }
302
+ });
303
+ if (changed) setMeasured((n) => n + 1);
304
+ }, [
305
+ firstRow,
306
+ lastRow,
307
+ columns,
308
+ data
309
+ ]);
310
+ const getItemId = useCallback((item) => {
311
+ if (item && typeof item === "object" && "id" in item) {
312
+ const id = item.id;
313
+ return typeof id === "number" ? id : String(id);
314
+ }
315
+ return String(item);
316
+ }, []);
317
+ const isInitialLoading = dataLoading && data.length === 0 && !dataLoadingError;
318
+ const isEmpty = !dataLoading && data.length === 0 && !dataLoadingError;
319
+ const drawnRows = [];
320
+ for (let r = firstRow; r <= lastRow; r++) {
321
+ const cards = [];
322
+ for (let index = r * columns; index < Math.min(data.length, (r + 1) * columns); index++) {
323
+ const item = data[index];
324
+ if (item === void 0) {
325
+ cards.push(/* @__PURE__ */ jsx(UnreadCard, { height: Math.max(0, layout.estimate - ROW_GAP) }, `__unread_${index}`));
326
+ continue;
327
+ }
328
+ const id = getItemId(item);
329
+ const selected = selectedIds?.has(id) ?? false;
330
+ const highlighted = highlightedIds?.has(id) ?? false;
331
+ const handleClick = (e) => {
332
+ if (e && (e.metaKey || e.ctrlKey) && selectionEnabled) {
333
+ e.preventDefault();
334
+ onSelectionChange?.(item, !selected);
335
+ return;
336
+ }
337
+ onItemClick?.(item);
338
+ };
339
+ const handleSelectionChange = (val) => {
340
+ onSelectionChange?.(item, val);
341
+ };
342
+ cards.push(/* @__PURE__ */ jsx(React.Fragment, { children: renderCard(item, {
343
+ selected,
344
+ highlighted,
345
+ onSelectionChange: handleSelectionChange,
346
+ onClick: handleClick
347
+ }) }, id || index));
348
+ }
349
+ drawnRows.push(/* @__PURE__ */ jsx("div", {
350
+ ref: observeRow,
351
+ "data-row": r,
352
+ "data-columns": columns,
353
+ className: cls("grid gap-4", gridColumnsClass),
354
+ style: r < rowCount - 1 ? { paddingBottom: ROW_GAP } : void 0,
355
+ children: cards
356
+ }, r));
357
+ }
358
+ return /* @__PURE__ */ jsx("div", {
359
+ ref: containerRef,
360
+ className: "w-full p-4",
361
+ children: dataLoadingError && data.length === 0 ? /* @__PURE__ */ jsx("div", {
362
+ className: "h-full flex items-center justify-center p-8",
363
+ children: /* @__PURE__ */ jsx(Typography, {
364
+ className: "text-red-500",
365
+ children: labels.errorLoadingData(dataLoadingError.message)
366
+ })
367
+ }) : isInitialLoading ? /* @__PURE__ */ jsx("div", {
368
+ className: "flex items-center justify-center py-12 px-8",
369
+ children: /* @__PURE__ */ jsx(CircularProgress, { size: "small" })
370
+ }) : isEmpty ? /* @__PURE__ */ jsx("div", {
371
+ className: "w-full flex items-center justify-center py-12 px-8",
372
+ children: emptyComponent ?? /* @__PURE__ */ jsx(Typography, {
373
+ variant: "label",
374
+ color: "secondary",
375
+ children: labels.noEntriesFound
376
+ })
377
+ }) : /* @__PURE__ */ jsxs("div", {
378
+ className: "max-w-7xl mx-auto",
379
+ children: [
380
+ /* @__PURE__ */ jsx("div", {
381
+ ref: probeRef,
382
+ "aria-hidden": true,
383
+ className: cls("grid gap-4 h-0 overflow-hidden", gridColumnsClass)
384
+ }),
385
+ /* @__PURE__ */ jsx("div", {
386
+ ref: rowsRef,
387
+ style: {
388
+ position: "relative",
389
+ height: layout.tops[rowCount]
390
+ },
391
+ children: /* @__PURE__ */ jsx("div", {
392
+ style: {
393
+ position: "absolute",
394
+ top: layout.tops[firstRow] ?? 0,
395
+ left: 0,
396
+ right: 0
397
+ },
398
+ children: drawnRows
399
+ })
400
+ }),
401
+ /* @__PURE__ */ jsxs("div", {
402
+ className: "flex items-center justify-center py-8",
403
+ children: [dataLoading && /* @__PURE__ */ jsx(CircularProgress, { size: "small" }), !dataLoading && noMoreToLoad && data.length > 0 && /* @__PURE__ */ jsx(Typography, {
404
+ variant: "caption",
405
+ color: "secondary",
406
+ children: labels.allEntriesLoaded(data.length)
407
+ })]
408
+ })
409
+ ]
410
+ })
411
+ });
412
+ }
413
+ /** A card that exists but has not been read yet. */
414
+ function UnreadCard({ height }) {
415
+ return /* @__PURE__ */ jsxs(Card, {
416
+ className: "p-3 flex flex-col gap-2",
417
+ style: { height },
418
+ "aria-busy": true,
419
+ children: [
420
+ /* @__PURE__ */ jsx(Skeleton, { className: "grow" }),
421
+ /* @__PURE__ */ jsx(Skeleton, {
422
+ width: 120,
423
+ height: 12
424
+ }),
425
+ /* @__PURE__ */ jsx(Skeleton, {
426
+ width: 80,
427
+ height: 10
428
+ })
429
+ ]
430
+ });
431
+ }
432
+ //#endregion
433
+ export { CardView };
434
+
435
+ //# sourceMappingURL=CardView.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CardView.es.js","names":[],"sources":["../../src/views/CardView.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport {\n Card,\n CircularProgress,\n Skeleton,\n Typography\n} from \"../components\";\nimport { cls } from \"../util\";\nimport { useUiLabels } from \"../hooks/UiLabelsContext\";\n\nimport { CollectionSize } from \"./ListView\";\nimport { getScrollParent, useScrollParentRestoration, type ViewScrollEvent } from \"./useScrollParentRestoration\";\n\nexport type CardViewProps<T> = {\n /**\n * The items, in order. A position holding `undefined` is an item that\n * exists but has not been read yet: a placeholder card is drawn in its\n * place, and `renderCard` is not called for it.\n */\n data: (T | undefined)[];\n dataLoading?: boolean;\n noMoreToLoad?: boolean;\n dataLoadingError?: Error;\n itemCount?: number;\n setItemCount?: (itemCount: number) => void;\n pageSize?: number;\n paginationEnabled?: boolean;\n\n onItemClick?: (item: T) => void;\n selectedIds?: Set<string | number>;\n highlightedIds?: Set<string | number>;\n selectionEnabled?: boolean;\n onSelectionChange?: (item: T, selected: boolean) => void;\n\n onScroll?: (props: ViewScrollEvent) => void;\n initialScroll?: number;\n\n /**\n * Called with the positions in `data` of the cards on screen — the rows\n * of cards on screen, not the ones drawn ahead of them — end exclusive,\n * each time they change. While the grid is still scrolling to\n * `initialScroll`, the cards there.\n */\n onRowsRendered?: (range: { start: number; end: number }) => void;\n\n size?: CollectionSize;\n renderCard: (\n item: T,\n extra: {\n selected: boolean;\n highlighted: boolean;\n onSelectionChange: (selected: boolean) => void;\n /**\n * Absent on a keyboard activation — a card is a `role=\"button\"` and\n * Enter/Space reach this with no event. Only the modifier branch\n * needs one; the click itself does not.\n */\n onClick: (e?: React.MouseEvent) => void;\n }\n ) => React.ReactNode;\n emptyComponent?: React.ReactNode;\n};\n\nfunction getGridColumnsClass(size: CollectionSize): string {\n switch (size) {\n case \"xs\":\n return \"grid-cols-4 sm:grid-cols-5 md:grid-cols-6 lg:grid-cols-8 xl:grid-cols-10\";\n case \"s\":\n return \"grid-cols-3 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-6 xl:grid-cols-8\";\n case \"m\":\n return \"grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6\";\n case \"l\":\n return \"grid-cols-2 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-4\";\n case \"xl\":\n return \"grid-cols-1 sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-3\";\n default:\n return \"grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6\";\n }\n}\n\n/**\n * The column count `getGridColumnsClass` gives at this viewport width — the\n * Tailwind breakpoints are viewport widths. Only a fallback: the count is read\n * off the grid as laid out whenever there is a layout to read it from.\n */\nfunction columnsAtWidth(size: CollectionSize, width: number): number {\n const steps: Record<CollectionSize, [number, number, number, number, number]> = {\n xs: [4, 5, 6, 8, 10],\n s: [3, 4, 5, 6, 8],\n m: [2, 3, 4, 5, 6],\n l: [2, 2, 3, 4, 4],\n xl: [1, 2, 2, 3, 3]\n };\n const [base, sm, md, lg, xl] = steps[size] ?? steps.m;\n if (width >= 1280) return xl;\n if (width >= 1024) return lg;\n if (width >= 768) return md;\n if (width >= 640) return sm;\n return base;\n}\n\n/** The tracks of a laid-out grid, or `undefined` where nothing is laid out. */\nfunction columnsOf(grid: HTMLElement | null): number | undefined {\n if (!grid) return undefined;\n const tracks = window.getComputedStyle(grid).gridTemplateColumns;\n if (!tracks || tracks === \"none\") return undefined;\n const count = tracks.trim().split(/\\s+/).filter(track => !track.startsWith(\"[\")).length;\n return count > 0 ? count : undefined;\n}\n\n/** A first guess at a row of cards' height, gap included, before one is measured. */\nfunction defaultRowHeight(size: CollectionSize): number {\n switch (size) {\n case \"xs\": return 170;\n case \"s\": return 220;\n case \"l\": return 370;\n case \"xl\": return 440;\n default: return 290;\n }\n}\n\n/**\n * The average row height measured last, per size and column count, so a grid\n * that mounts again (coming back from a record) places its rows — and the\n * scroll position it restores — with the heights the cards actually had.\n */\nconst lastRowHeights = new Map<string, number>();\n\n/** Rows of cards drawn above and below the screen. */\nconst OVERSCAN_ROWS = 2;\n/** The grid's `gap-4`, which a row carries below it as padding. */\nconst ROW_GAP = 16;\n\n/**\n * A card grid that draws the rows of cards on screen and a couple either side.\n *\n * Every loaded card used to stay mounted — about 22 DOM nodes each, 44,000 at\n * 2,000 cards. The grid looks as it did: each row is a grid with the same\n * column classes and gap, and a row is as tall as its tallest card, measured\n * as it is drawn rather than assumed. Rows not drawn yet count at the average\n * height measured so far.\n */\nexport function CardView<T>({\n data,\n dataLoading = false,\n noMoreToLoad = false,\n dataLoadingError,\n itemCount,\n setItemCount,\n pageSize = 50,\n paginationEnabled = true,\n\n onItemClick,\n selectedIds,\n highlightedIds,\n selectionEnabled = true,\n onSelectionChange,\n\n onScroll,\n initialScroll,\n onRowsRendered,\n size = \"m\",\n renderCard,\n emptyComponent\n}: CardViewProps<T>) {\n const labels = useUiLabels();\n const containerRef = useRef<HTMLDivElement>(null);\n // The rows' own box: the window of drawn rows is measured against it.\n const rowsRef = useRef<HTMLDivElement>(null);\n // An empty grid with the cards' column classes, to read the column count\n // the breakpoints give right now.\n const probeRef = useRef<HTMLDivElement>(null);\n const isLoadingMore = useRef(false);\n\n const gridColumnsClass = getGridColumnsClass(size);\n const [columns, setColumns] = useState(() =>\n columnsAtWidth(size, typeof window === \"undefined\" ? 1024 : window.innerWidth));\n const [scrollTop, setScrollTop] = useState(0);\n const [viewportHeight, setViewportHeight] = useState(800);\n // Where the cards on screen start, for `onRowsRendered`: the scroll\n // position the grid is being restored to, until it gets there.\n const [reported, setReported] = useState({ top: 0, height: 800 });\n\n // Sync mutable ref with pagination settings to avoid resetting listeners\n const paginationStateRef = useRef({ paginationEnabled, noMoreToLoad, itemCount, pageSize });\n useEffect(() => {\n paginationStateRef.current = { paginationEnabled, noMoreToLoad, itemCount, pageSize };\n }, [paginationEnabled, noMoreToLoad, itemCount, pageSize]);\n\n useEffect(() => {\n if (!dataLoading) isLoadingMore.current = false;\n }, [dataLoading]);\n\n const { pendingScroll } = useScrollParentRestoration({ containerRef, initialScroll, onScroll, dataLength: data.length });\n\n const readColumns = useCallback(() => {\n const next = columnsOf(probeRef.current) ?? columnsAtWidth(size, window.innerWidth);\n setColumns(current => current === next ? current : next);\n }, [size]);\n\n // Infinite scroll, the window of drawn rows, and resizes\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n const scrollEl = getScrollParent(el);\n if (!scrollEl) return;\n\n let rafId: number | null = null;\n\n const update = () => {\n rafId = null;\n const scrollRect = scrollEl.getBoundingClientRect();\n const rowsRect = (rowsRef.current ?? el).getBoundingClientRect();\n const rowsTopRelative = rowsRect.top - scrollRect.top;\n setScrollTop(Math.max(0, -rowsTopRelative));\n setViewportHeight(scrollRect.height);\n const restoring = pendingScroll.current;\n const top = restoring\n ? restoring - (scrollEl.scrollTop + rowsTopRelative)\n : -rowsTopRelative;\n // Only the part of the screen the rows are in: not what is above them.\n const height = Math.max(0, scrollRect.height + Math.min(0, top));\n setReported(current => current.top === Math.max(0, top) && current.height === height\n ? current\n : { top: Math.max(0, top), height });\n\n const { paginationEnabled: pe, noMoreToLoad: nm, itemCount: ic, pageSize: ps } = paginationStateRef.current;\n if (\n pe &&\n !nm &&\n !isLoadingMore.current &&\n scrollEl.scrollHeight - scrollEl.scrollTop - scrollEl.clientHeight < 400\n ) {\n isLoadingMore.current = true;\n setItemCount?.((ic ?? ps) + ps);\n }\n };\n\n const onScrollEvent = () => {\n if (rafId === null) rafId = requestAnimationFrame(update);\n };\n\n scrollEl.addEventListener(\"scroll\", onScrollEvent, { passive: true });\n const ro = new ResizeObserver(() => {\n readColumns();\n update();\n });\n ro.observe(scrollEl);\n ro.observe(el);\n readColumns();\n update();\n\n return () => {\n scrollEl.removeEventListener(\"scroll\", onScrollEvent);\n ro.disconnect();\n if (rafId !== null) cancelAnimationFrame(rafId);\n };\n }, [setItemCount, readColumns, pendingScroll]);\n\n // The size changes the column classes: read the count again.\n useLayoutEffect(() => readColumns(), [readColumns, gridColumnsClass]);\n\n // Row heights as measured, by row. A different column count regroups the\n // cards into different rows, so the heights start over.\n const heightsRef = useRef<{ columns: number; heights: Map<number, number> }>({ columns, heights: new Map() });\n if (heightsRef.current.columns !== columns) heightsRef.current = { columns, heights: new Map() };\n const [measured, setMeasured] = useState(0);\n const memoryKey = `${size}:${columns}`;\n\n const observerRef = useRef<ResizeObserver | null>(null);\n useEffect(() => {\n const observer = new ResizeObserver((entries) => {\n let changed = false;\n const { heights } = heightsRef.current;\n for (const entry of entries) {\n const target = entry.target as HTMLElement;\n const row = Number(target.dataset.row);\n if (!Number.isFinite(row) || Number(target.dataset.columns) !== heightsRef.current.columns) continue;\n const height = target.getBoundingClientRect().height;\n if (height > 0 && heights.get(row) !== height) {\n heights.set(row, height);\n changed = true;\n }\n }\n if (changed) setMeasured(n => n + 1);\n });\n observerRef.current = observer;\n return () => {\n observer.disconnect();\n observerRef.current = null;\n };\n }, []);\n\n const observeRow = useCallback((element: HTMLDivElement | null) => {\n const observer = observerRef.current;\n if (!element || !observer) return;\n observer.observe(element);\n return () => observer.unobserve(element);\n }, []);\n\n const rowCount = Math.ceil(data.length / columns);\n\n // Each row's top, and the height of all of them: measured rows as they\n // are, the others at the average of the measured ones.\n const layout = useMemo(() => {\n const { heights } = heightsRef.current;\n let total = 0;\n heights.forEach((height) => {\n total += height;\n });\n const estimate = heights.size > 0\n ? total / heights.size\n : lastRowHeights.get(memoryKey) ?? defaultRowHeight(size);\n const tops = new Float64Array(rowCount + 1);\n for (let r = 0; r < rowCount; r++) {\n tops[r + 1] = tops[r] + (heights.get(r) ?? estimate);\n }\n return { tops, estimate };\n // `measured` is how a new measurement reaches this memo.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [rowCount, columns, measured, memoryKey, size]);\n\n useEffect(() => {\n if (heightsRef.current.heights.size > 0) lastRowHeights.set(memoryKey, layout.estimate);\n }, [layout, memoryKey]);\n\n /** The row at this offset from the top of the rows. */\n const rowAt = useCallback((offset: number) => {\n const { tops } = layout;\n let low = 0;\n let high = rowCount;\n while (low < high) {\n const mid = (low + high) >> 1;\n if (tops[mid + 1] <= offset) low = mid + 1;\n else high = mid;\n }\n return Math.min(low, Math.max(0, rowCount - 1));\n }, [layout, rowCount]);\n\n const firstRow = rowCount === 0 ? 0 : Math.max(0, rowAt(scrollTop) - OVERSCAN_ROWS);\n const lastRow = rowCount === 0 ? -1 : Math.min(rowCount - 1, rowAt(scrollTop + viewportHeight) + OVERSCAN_ROWS);\n\n // The cards of the rows on screen, by position in `data`.\n const visibleStart = rowCount === 0 ? 0 : Math.min(data.length, rowAt(reported.top) * columns);\n const visibleEnd = rowCount === 0 || reported.height === 0\n ? visibleStart\n : Math.min(data.length, (rowAt(reported.top + reported.height - 1) + 1) * columns);\n useEffect(() => {\n if (onRowsRendered && data.length > 0) onRowsRendered({ start: visibleStart, end: visibleEnd });\n // Not on `data`: a page appended below the screen moves nothing on it.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [visibleStart, visibleEnd, onRowsRendered]);\n\n // A drawn row the observer has not measured — one whose cards changed\n // with the column count, keeping its size — is measured here, before\n // paint. The observer reports every change after that.\n useLayoutEffect(() => {\n const { heights } = heightsRef.current;\n let changed = false;\n rowsRef.current?.querySelectorAll<HTMLElement>(\"[data-row]\").forEach((element) => {\n const row = Number(element.dataset.row);\n if (heights.has(row)) return;\n const height = element.getBoundingClientRect().height;\n if (height > 0) {\n heights.set(row, height);\n changed = true;\n }\n });\n if (changed) setMeasured(n => n + 1);\n }, [firstRow, lastRow, columns, data]);\n\n const getItemId = useCallback((item: T | undefined): string | number => {\n if (item && typeof item === \"object\" && \"id\" in item) {\n const id = (item as Record<\"id\", unknown>).id;\n return typeof id === \"number\" ? id : String(id);\n }\n return String(item);\n }, []);\n\n const isInitialLoading = dataLoading && data.length === 0 && !dataLoadingError;\n const isEmpty = !dataLoading && data.length === 0 && !dataLoadingError;\n\n const drawnRows: React.ReactNode[] = [];\n for (let r = firstRow; r <= lastRow; r++) {\n const cards: React.ReactNode[] = [];\n for (let index = r * columns; index < Math.min(data.length, (r + 1) * columns); index++) {\n const item = data[index];\n if (item === undefined) {\n cards.push(<UnreadCard key={`__unread_${index}`} height={Math.max(0, layout.estimate - ROW_GAP)}/>);\n continue;\n }\n const id = getItemId(item);\n const selected = selectedIds?.has(id) ?? false;\n const highlighted = highlightedIds?.has(id) ?? false;\n\n const handleClick = (e?: React.MouseEvent) => {\n if (e && (e.metaKey || e.ctrlKey) && selectionEnabled) {\n e.preventDefault();\n onSelectionChange?.(item, !selected);\n return;\n }\n onItemClick?.(item);\n };\n\n const handleSelectionChange = (val: boolean) => {\n onSelectionChange?.(item, val);\n };\n\n cards.push(\n <React.Fragment key={id || index}>\n {renderCard(item, {\n selected,\n highlighted,\n onSelectionChange: handleSelectionChange,\n onClick: handleClick\n })}\n </React.Fragment>\n );\n }\n drawnRows.push(\n <div key={r}\n ref={observeRow}\n data-row={r}\n data-columns={columns}\n className={cls(\"grid gap-4\", gridColumnsClass)}\n // The gap between rows, carried by the row above it.\n style={r < rowCount - 1 ? { paddingBottom: ROW_GAP } : undefined}>\n {cards}\n </div>\n );\n }\n\n return (\n <div\n ref={containerRef}\n className=\"w-full p-4\"\n >\n {dataLoadingError && data.length === 0 ? (\n <div className=\"h-full flex items-center justify-center p-8\">\n <Typography className=\"text-red-500\">\n {labels.errorLoadingData(dataLoadingError.message)}\n </Typography>\n </div>\n ) : isInitialLoading ? (\n <div className=\"flex items-center justify-center py-12 px-8\">\n <CircularProgress size=\"small\"/>\n </div>\n ) : isEmpty ? (\n <div className=\"w-full flex items-center justify-center py-12 px-8\">\n {emptyComponent ?? (\n <Typography variant=\"label\" color=\"secondary\">\n {labels.noEntriesFound}\n </Typography>\n )}\n </div>\n ) : (\n <div className=\"max-w-7xl mx-auto\">\n <div ref={probeRef} aria-hidden={true} className={cls(\"grid gap-4 h-0 overflow-hidden\", gridColumnsClass)}/>\n <div ref={rowsRef} style={{ position: \"relative\", height: layout.tops[rowCount] }}>\n <div style={{ position: \"absolute\", top: layout.tops[firstRow] ?? 0, left: 0, right: 0 }}>\n {drawnRows}\n </div>\n </div>\n\n <div className=\"flex items-center justify-center py-8\">\n {dataLoading && (\n <CircularProgress size=\"small\"/>\n )}\n {!dataLoading && noMoreToLoad && data.length > 0 && (\n <Typography variant=\"caption\" color=\"secondary\">\n {labels.allEntriesLoaded(data.length)}\n </Typography>\n )}\n </div>\n </div>\n )}\n </div>\n );\n}\n\n/** A card that exists but has not been read yet. */\nfunction UnreadCard({ height }: { height: number }) {\n return (\n <Card className=\"p-3 flex flex-col gap-2\" style={{ height }} aria-busy={true}>\n <Skeleton className=\"grow\"/>\n <Skeleton width={120} height={12}/>\n <Skeleton width={80} height={10}/>\n </Card>\n );\n}\n"],"mappings":"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"}