@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,158 @@
1
+ import { cls } from "../util/cls.es.js";
2
+ import { iconSize } from "../icons/Icon.es.js";
3
+ import { Button } from "./Button.es.js";
4
+ import { Typography } from "./Typography.es.js";
5
+ import { isChunkLoadError } from "../util/lazy_chunk.es.js";
6
+ import React from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ import { AlertCircleIcon, ArrowLeftIcon, ChevronDownIcon, ChevronUpIcon, RefreshCwIcon, ShieldAlertIcon } from "lucide-react";
9
+ //#region src/components/ErrorBoundary.tsx
10
+ /**
11
+ * The one error a user can fix themselves. A deploy replaces the hashed chunk
12
+ * files, so a tab opened before it cannot load any lazy view it has not already
13
+ * fetched — with the browser's raw message ("Failed to fetch dynamically
14
+ * imported module: …") this reads as a broken build rather than a stale tab.
15
+ */
16
+ var CHUNK_ERROR_DESCRIPTION = "This app was updated while the tab was open, so part of it could not be loaded. Reload to continue.";
17
+ /**
18
+ * Checks whether the error message relates to missing permissions or
19
+ * authorization failures. Used to show a friendlier message in fullPage mode.
20
+ */
21
+ function isPermissionError(error) {
22
+ if (!error) return false;
23
+ const msg = error.message?.toLowerCase() ?? "";
24
+ const code = error.code?.toLowerCase() ?? "";
25
+ return msg.includes("permission") || msg.includes("insufficient") || msg.includes("unauthorized") || msg.includes("forbidden") || msg.includes("access denied") || code === "permission_denied" || code === "insufficient_permissions" || error.status === 403;
26
+ }
27
+ var ErrorBoundary = class extends React.Component {
28
+ constructor(props) {
29
+ super(props);
30
+ this.state = {
31
+ error: null,
32
+ showDetails: false
33
+ };
34
+ }
35
+ static getDerivedStateFromError(error) {
36
+ return { error };
37
+ }
38
+ componentDidCatch(error, _errorInfo) {
39
+ console.error(error);
40
+ }
41
+ handleReset = () => {
42
+ this.setState({
43
+ error: null,
44
+ showDetails: false
45
+ });
46
+ this.props.onReset?.();
47
+ };
48
+ handleReload = () => {
49
+ window.location.reload();
50
+ };
51
+ toggleDetails = () => {
52
+ this.setState((prev) => ({ showDetails: !prev.showDetails }));
53
+ };
54
+ render() {
55
+ if (this.state.error) {
56
+ if (this.props.fullPage) return this.renderFullPage();
57
+ return this.renderInline();
58
+ }
59
+ return this.props.children;
60
+ }
61
+ renderInline() {
62
+ const isStaleChunk = isChunkLoadError(this.state.error);
63
+ return /* @__PURE__ */ jsxs("div", {
64
+ className: "flex flex-col m-2 items-start",
65
+ children: [
66
+ /* @__PURE__ */ jsxs("div", {
67
+ className: "flex items-center m-2",
68
+ children: [isStaleChunk ? /* @__PURE__ */ jsx(RefreshCwIcon, {
69
+ className: "text-text-secondary dark:text-text-secondary-dark",
70
+ size: iconSize.small
71
+ }) : /* @__PURE__ */ jsx(AlertCircleIcon, {
72
+ className: "text-red-500 dark:text-red-400",
73
+ size: iconSize.small
74
+ }), /* @__PURE__ */ jsx("div", {
75
+ className: "ml-4",
76
+ children: isStaleChunk ? "New version available" : "Error"
77
+ })]
78
+ }),
79
+ /* @__PURE__ */ jsx(Typography, {
80
+ variant: "caption",
81
+ children: isStaleChunk ? CHUNK_ERROR_DESCRIPTION : this.state.error?.message ?? "See the error in the console"
82
+ }),
83
+ isStaleChunk && /* @__PURE__ */ jsxs(Button, {
84
+ variant: "outlined",
85
+ color: "neutral",
86
+ size: "small",
87
+ className: "mt-3 ml-2",
88
+ onClick: this.handleReload,
89
+ children: [/* @__PURE__ */ jsx(RefreshCwIcon, { size: 16 }), "Reload"]
90
+ })
91
+ ]
92
+ });
93
+ }
94
+ renderFullPage() {
95
+ const { error, showDetails } = this.state;
96
+ const isPermission = isPermissionError(error);
97
+ const isStaleChunk = !isPermission && isChunkLoadError(error);
98
+ const Icon = isPermission ? ShieldAlertIcon : isStaleChunk ? RefreshCwIcon : AlertCircleIcon;
99
+ const title = isPermission ? "Access denied" : isStaleChunk ? "New version available" : "Something went wrong";
100
+ const description = isPermission ? "You don't have permission to access this resource. Please check your account permissions or contact your administrator." : isStaleChunk ? CHUNK_ERROR_DESCRIPTION : "An unexpected error occurred. You can try reloading the page or going back.";
101
+ return /* @__PURE__ */ jsx("div", {
102
+ className: cls("flex items-center justify-center min-h-[400px] h-full w-full", "bg-surface-sheet"),
103
+ children: /* @__PURE__ */ jsxs("div", {
104
+ className: "flex flex-col items-center max-w-md px-6 py-10 text-center",
105
+ children: [
106
+ /* @__PURE__ */ jsx("div", {
107
+ className: cls("flex items-center justify-center w-14 h-14 rounded-xl mb-6", isPermission ? "bg-amber-100 dark:bg-amber-900/30" : isStaleChunk ? "bg-surface-raised" : "bg-red-100 dark:bg-red-900/30"),
108
+ children: /* @__PURE__ */ jsx(Icon, {
109
+ size: 28,
110
+ className: isPermission ? "text-amber-600 dark:text-amber-400" : isStaleChunk ? "text-text-secondary dark:text-text-secondary-dark" : "text-red-500 dark:text-red-400"
111
+ })
112
+ }),
113
+ /* @__PURE__ */ jsx(Typography, {
114
+ variant: "h6",
115
+ className: "text-text-primary dark:text-text-primary-dark mb-2",
116
+ children: title
117
+ }),
118
+ /* @__PURE__ */ jsx(Typography, {
119
+ variant: "body2",
120
+ className: "text-text-secondary dark:text-text-secondary-dark mb-8",
121
+ children: description
122
+ }),
123
+ /* @__PURE__ */ jsxs("div", {
124
+ className: "flex gap-3",
125
+ children: [!isStaleChunk && /* @__PURE__ */ jsxs(Button, {
126
+ variant: "outlined",
127
+ color: "neutral",
128
+ size: "medium",
129
+ onClick: this.handleReset,
130
+ children: [/* @__PURE__ */ jsx(ArrowLeftIcon, { size: 16 }), "Try again"]
131
+ }), /* @__PURE__ */ jsxs(Button, {
132
+ variant: "filled",
133
+ color: "primary",
134
+ size: "medium",
135
+ onClick: this.handleReload,
136
+ children: [/* @__PURE__ */ jsx(RefreshCwIcon, { size: 16 }), "Reload page"]
137
+ })]
138
+ }),
139
+ !isStaleChunk && error?.message && /* @__PURE__ */ jsxs("div", {
140
+ className: "mt-8 w-full",
141
+ children: [/* @__PURE__ */ jsxs("button", {
142
+ onClick: this.toggleDetails,
143
+ className: cls("flex items-center gap-1 mx-auto text-xs", "text-text-disabled dark:text-text-disabled-dark", "hover:text-text-secondary dark:hover:text-text-secondary-dark", "transition-colors cursor-pointer bg-transparent border-none p-0"),
144
+ children: ["Technical details", showDetails ? /* @__PURE__ */ jsx(ChevronUpIcon, { size: 14 }) : /* @__PURE__ */ jsx(ChevronDownIcon, { size: 14 })]
145
+ }), showDetails && /* @__PURE__ */ jsx("div", {
146
+ className: cls("mt-3 p-3 rounded-lg text-left text-xs", "bg-surface-field", "text-text-secondary dark:text-text-secondary-dark", "font-mono break-all"),
147
+ children: error.message
148
+ })]
149
+ })
150
+ ]
151
+ })
152
+ });
153
+ }
154
+ };
155
+ //#endregion
156
+ export { ErrorBoundary };
157
+
158
+ //# sourceMappingURL=ErrorBoundary.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErrorBoundary.es.js","names":[],"sources":["../../src/components/ErrorBoundary.tsx"],"sourcesContent":["\nimport React, { ErrorInfo, PropsWithChildren } from \"react\";\n\nimport { AlertCircleIcon, ShieldAlertIcon, RefreshCwIcon, ArrowLeftIcon, ChevronDownIcon, ChevronUpIcon } from \"lucide-react\";\nimport { iconSize } from \"../icons/Icon\";\nimport { Typography } from \"./Typography\";\nimport { Button } from \"./Button\";\nimport { cls } from \"../util\";\nimport { isChunkLoadError } from \"../util/lazy_chunk\";\n\n/**\n * The one error a user can fix themselves. A deploy replaces the hashed chunk\n * files, so a tab opened before it cannot load any lazy view it has not already\n * fetched — with the browser's raw message (\"Failed to fetch dynamically\n * imported module: …\") this reads as a broken build rather than a stale tab.\n */\nconst CHUNK_ERROR_DESCRIPTION =\n \"This app was updated while the tab was open, so part of it could not be loaded. Reload to continue.\";\n\n/**\n * Checks whether the error message relates to missing permissions or\n * authorization failures. Used to show a friendlier message in fullPage mode.\n */\nfunction isPermissionError(error: Error | null): boolean {\n if (!error) return false;\n const msg = error.message?.toLowerCase() ?? \"\";\n const code = (error as { code?: string }).code?.toLowerCase() ?? \"\";\n return msg.includes(\"permission\")\n || msg.includes(\"insufficient\")\n || msg.includes(\"unauthorized\")\n || msg.includes(\"forbidden\")\n || msg.includes(\"access denied\")\n || code === \"permission_denied\"\n || code === \"insufficient_permissions\"\n || (error as { status?: number }).status === 403;\n}\n\nexport interface ErrorBoundaryProps {\n /**\n * When true, renders a full-page centered error screen instead of the\n * compact inline error. Intended for wrapping top-level app roots or\n * major route sections.\n */\n fullPage?: boolean;\n /**\n * Optional callback invoked when the user clicks \"Try again\". If provided,\n * the boundary resets its error state and calls this handler. If omitted,\n * the \"Try again\" button resets the boundary state, re-mounting children.\n */\n onReset?: () => void;\n}\n\ninterface ErrorBoundaryState {\n error: Error | null;\n showDetails: boolean;\n}\n\nexport class ErrorBoundary extends React.Component<PropsWithChildren<ErrorBoundaryProps>, ErrorBoundaryState> {\n constructor(props: PropsWithChildren<ErrorBoundaryProps>) {\n super(props);\n this.state = { error: null,\nshowDetails: false };\n }\n\n static getDerivedStateFromError(error: Error) {\n return { error };\n }\n\n componentDidCatch(error: Error, _errorInfo: ErrorInfo) {\n console.error(error);\n }\n\n private handleReset = () => {\n this.setState({ error: null,\nshowDetails: false });\n this.props.onReset?.();\n };\n\n private handleReload = () => {\n window.location.reload();\n };\n\n private toggleDetails = () => {\n this.setState(prev => ({ showDetails: !prev.showDetails }));\n };\n\n render() {\n if (this.state.error) {\n if (this.props.fullPage) {\n return this.renderFullPage();\n }\n return this.renderInline();\n }\n\n return this.props.children;\n }\n\n private renderInline() {\n const isStaleChunk = isChunkLoadError(this.state.error);\n return (\n <div className=\"flex flex-col m-2 items-start\">\n <div className=\"flex items-center m-2\">\n {isStaleChunk\n ? <RefreshCwIcon className={\"text-text-secondary dark:text-text-secondary-dark\"}\n size={iconSize.small}/>\n : <AlertCircleIcon className={\"text-red-500 dark:text-red-400\"} size={iconSize.small}/>}\n <div className=\"ml-4\">{isStaleChunk ? \"New version available\" : \"Error\"}</div>\n </div>\n <Typography variant={\"caption\"}>\n {isStaleChunk\n ? CHUNK_ERROR_DESCRIPTION\n : this.state.error?.message ?? \"See the error in the console\"}\n </Typography>\n {isStaleChunk && <Button variant=\"outlined\"\n color=\"neutral\"\n size=\"small\"\n className=\"mt-3 ml-2\"\n onClick={this.handleReload}>\n <RefreshCwIcon size={16}/>\n Reload\n </Button>}\n </div>\n );\n }\n\n private renderFullPage() {\n const { error, showDetails } = this.state;\n const isPermission = isPermissionError(error);\n // Neither a fault nor a denial: the app is fine, this tab is behind it.\n const isStaleChunk = !isPermission && isChunkLoadError(error);\n\n const Icon = isPermission ? ShieldAlertIcon : isStaleChunk ? RefreshCwIcon : AlertCircleIcon;\n const title = isPermission\n ? \"Access denied\"\n : isStaleChunk\n ? \"New version available\"\n : \"Something went wrong\";\n const description = isPermission\n ? \"You don't have permission to access this resource. Please check your account permissions or contact your administrator.\"\n : isStaleChunk\n ? CHUNK_ERROR_DESCRIPTION\n : \"An unexpected error occurred. You can try reloading the page or going back.\";\n\n return (\n <div className={cls(\n \"flex items-center justify-center min-h-[400px] h-full w-full\",\n \"bg-surface-sheet\"\n )}>\n <div className=\"flex flex-col items-center max-w-md px-6 py-10 text-center\">\n <div className={cls(\n \"flex items-center justify-center w-14 h-14 rounded-xl mb-6\",\n isPermission\n ? \"bg-amber-100 dark:bg-amber-900/30\"\n : isStaleChunk\n ? \"bg-surface-raised\"\n : \"bg-red-100 dark:bg-red-900/30\"\n )}>\n <Icon\n size={28}\n className={isPermission\n ? \"text-amber-600 dark:text-amber-400\"\n : isStaleChunk\n ? \"text-text-secondary dark:text-text-secondary-dark\"\n : \"text-red-500 dark:text-red-400\"}\n />\n </div>\n\n <Typography variant={\"h6\"}\n className=\"text-text-primary dark:text-text-primary-dark mb-2\">\n {title}\n </Typography>\n\n <Typography variant={\"body2\"}\n className=\"text-text-secondary dark:text-text-secondary-dark mb-8\">\n {description}\n </Typography>\n\n <div className=\"flex gap-3\">\n {/* React caches a `lazy()` rejection: re-mounting the\n children re-throws without re-running the import, so\n \"Try again\" cannot recover a missing chunk. */}\n {!isStaleChunk && <Button\n variant=\"outlined\"\n color=\"neutral\"\n size=\"medium\"\n onClick={this.handleReset}\n >\n <ArrowLeftIcon size={16}/>\n Try again\n </Button>}\n <Button\n variant=\"filled\"\n color=\"primary\"\n size=\"medium\"\n onClick={this.handleReload}\n >\n <RefreshCwIcon size={16}/>\n Reload page\n </Button>\n </div>\n\n {/* For a stale chunk the message *is* the description\n above; repeating it under a disclosure adds nothing. */}\n {!isStaleChunk && error?.message && (\n <div className=\"mt-8 w-full\">\n <button\n onClick={this.toggleDetails}\n className={cls(\n \"flex items-center gap-1 mx-auto text-xs\",\n \"text-text-disabled dark:text-text-disabled-dark\",\n \"hover:text-text-secondary dark:hover:text-text-secondary-dark\",\n \"transition-colors cursor-pointer bg-transparent border-none p-0\"\n )}\n >\n Technical details\n {showDetails\n ? <ChevronUpIcon size={14}/>\n : <ChevronDownIcon size={14}/>}\n </button>\n {showDetails && (\n <div className={cls(\n \"mt-3 p-3 rounded-lg text-left text-xs\",\n \"bg-surface-field\",\n \"text-text-secondary dark:text-text-secondary-dark\",\n \"font-mono break-all\"\n )}>\n {error.message}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAgBA,IAAM,0BACF;;;;;AAMJ,SAAS,kBAAkB,OAA8B;CACrD,IAAI,CAAC,OAAO,OAAO;CACnB,MAAM,MAAM,MAAM,SAAS,YAAY,KAAK;CAC5C,MAAM,OAAQ,MAA4B,MAAM,YAAY,KAAK;CACjE,OAAO,IAAI,SAAS,YAAY,KACzB,IAAI,SAAS,cAAc,KAC3B,IAAI,SAAS,cAAc,KAC3B,IAAI,SAAS,WAAW,KACxB,IAAI,SAAS,eAAe,KAC5B,SAAS,uBACT,SAAS,8BACR,MAA8B,WAAW;AACrD;AAsBA,IAAa,gBAAb,cAAmC,MAAM,UAAqE;CAC1G,YAAY,OAA8C;EACtD,MAAM,KAAK;EACX,KAAK,QAAQ;GAAE,OAAO;GAC9B,aAAa;EAAM;CACf;CAEA,OAAO,yBAAyB,OAAc;EAC1C,OAAO,EAAE,MAAM;CACnB;CAEA,kBAAkB,OAAc,YAAuB;EACnD,QAAQ,MAAM,KAAK;CACvB;CAEA,oBAA4B;EACxB,KAAK,SAAS;GAAE,OAAO;GAC/B,aAAa;EAAM,CAAC;EACZ,KAAK,MAAM,UAAU;CACzB;CAEA,qBAA6B;EACzB,OAAO,SAAS,OAAO;CAC3B;CAEA,sBAA8B;EAC1B,KAAK,UAAS,UAAS,EAAE,aAAa,CAAC,KAAK,YAAY,EAAE;CAC9D;CAEA,SAAS;EACL,IAAI,KAAK,MAAM,OAAO;GAClB,IAAI,KAAK,MAAM,UACX,OAAO,KAAK,eAAe;GAE/B,OAAO,KAAK,aAAa;EAC7B;EAEA,OAAO,KAAK,MAAM;CACtB;CAEA,eAAuB;EACnB,MAAM,eAAe,iBAAiB,KAAK,MAAM,KAAK;EACtD,OACI,qBAAC,OAAD;GAAK,WAAU;aAAf;IACI,qBAAC,OAAD;KAAK,WAAU;eAAf,CACK,eACK,oBAAC,eAAD;MAAe,WAAW;MACX,MAAM,SAAS;KAAO,CAAA,IACrC,oBAAC,iBAAD;MAAiB,WAAW;MAAkC,MAAM,SAAS;KAAO,CAAA,GAC1F,oBAAC,OAAD;MAAK,WAAU;gBAAQ,eAAe,0BAA0B;KAAa,CAAA,CAC5E;;IACL,oBAAC,YAAD;KAAY,SAAS;eAChB,eACK,0BACA,KAAK,MAAM,OAAO,WAAW;IAC3B,CAAA;IACX,gBAAgB,qBAAC,QAAD;KAAQ,SAAQ;KACR,OAAM;KACN,MAAK;KACL,WAAU;KACV,SAAS,KAAK;eAJtB,CAKb,oBAAC,eAAD,EAAe,MAAM,GAAI,CAAA,GAAC,QAEtB;;GACP;;CAEb;CAEA,iBAAyB;EACrB,MAAM,EAAE,OAAO,gBAAgB,KAAK;EACpC,MAAM,eAAe,kBAAkB,KAAK;EAE5C,MAAM,eAAe,CAAC,gBAAgB,iBAAiB,KAAK;EAE5D,MAAM,OAAO,eAAe,kBAAkB,eAAe,gBAAgB;EAC7E,MAAM,QAAQ,eACR,kBACA,eACI,0BACA;EACV,MAAM,cAAc,eACd,4HACA,eACI,0BACA;EAEV,OACI,oBAAC,OAAD;GAAK,WAAW,IACZ,gEACA,kBACJ;aACI,qBAAC,OAAD;IAAK,WAAU;cAAf;KACI,oBAAC,OAAD;MAAK,WAAW,IACZ,8DACA,eACM,sCACA,eACI,sBACA,+BACd;gBACI,oBAAC,MAAD;OACI,MAAM;OACN,WAAW,eACL,uCACA,eACI,sDACA;MACb,CAAA;KACA,CAAA;KAEL,oBAAC,YAAD;MAAY,SAAS;MACT,WAAU;gBACjB;KACO,CAAA;KAEZ,oBAAC,YAAD;MAAY,SAAS;MACT,WAAU;gBACjB;KACO,CAAA;KAEZ,qBAAC,OAAD;MAAK,WAAU;gBAAf,CAIK,CAAC,gBAAgB,qBAAC,QAAD;OACd,SAAQ;OACR,OAAM;OACN,MAAK;OACL,SAAS,KAAK;iBAJA,CAMd,oBAAC,eAAD,EAAe,MAAM,GAAI,CAAA,GAAC,WAEtB;UACR,qBAAC,QAAD;OACI,SAAQ;OACR,OAAM;OACN,MAAK;OACL,SAAS,KAAK;iBAJlB,CAMI,oBAAC,eAAD,EAAe,MAAM,GAAI,CAAA,GAAC,aAEtB;QACP;;KAIJ,CAAC,gBAAgB,OAAO,WACrB,qBAAC,OAAD;MAAK,WAAU;gBAAf,CACI,qBAAC,UAAD;OACI,SAAS,KAAK;OACd,WAAW,IACP,2CACA,mDACA,iEACA,iEACJ;iBAPJ,CAQC,qBAEI,cACK,oBAAC,eAAD,EAAe,MAAM,GAAI,CAAA,IACzB,oBAAC,iBAAD,EAAiB,MAAM,GAAI,CAAA,CAC7B;UACP,eACG,oBAAC,OAAD;OAAK,WAAW,IACZ,yCACA,oBACA,qDACA,qBACJ;iBACK,MAAM;MACN,CAAA,CAER;;IAER;;EACJ,CAAA;CAEb;AACJ"}
@@ -0,0 +1,91 @@
1
+ "use client";
2
+ import "../styles.es.js";
3
+ import { cls } from "../util/cls.es.js";
4
+ import { useInjectStyles } from "../hooks/useInjectStyles.es.js";
5
+ import { useEffect, useState } from "react";
6
+ import * as Collapsible from "@radix-ui/react-collapsible";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
+ import { ChevronDownIcon } from "lucide-react";
9
+ //#region src/components/ExpandablePanel.tsx
10
+ function ExpandablePanel({ title, children, invisible = false, expanded, onExpandedChange, initiallyExpanded = true, titleClassName, asField, className, innerClassName }) {
11
+ useInjectStyles("ExpandablePanel", `
12
+ .CollapsibleContent {
13
+ overflow: hidden;
14
+ }
15
+ .CollapsibleContent[data-state='open'] {
16
+ animation: expandablePanelSlideDown 220ms ease-out
17
+ }
18
+ .CollapsibleContent[data-state='closed'] {
19
+ animation: expandablePanelSlideUp 220ms ease-out;
20
+ }
21
+
22
+ @keyframes expandablePanelSlideDown {
23
+ from {
24
+ height: 0;
25
+ }
26
+ to {
27
+ height: var(--radix-collapsible-content-height);
28
+ }
29
+ }
30
+
31
+ @keyframes expandablePanelSlideUp {
32
+ from {
33
+ height: var(--radix-collapsible-content-height);
34
+ }
35
+ to {
36
+ height: 0;
37
+ }
38
+ }
39
+
40
+ @media (prefers-reduced-motion: reduce) {
41
+ .CollapsibleContent[data-state] {
42
+ animation: none;
43
+ }
44
+ }`);
45
+ const [open, setOpen] = useState(expanded !== void 0 ? expanded : initiallyExpanded);
46
+ const [allowOverflow, setAllowOverflow] = useState(open);
47
+ useEffect(() => {
48
+ if (open) setTimeout(() => {
49
+ setAllowOverflow(true);
50
+ }, 220);
51
+ else setAllowOverflow(false);
52
+ }, [open]);
53
+ useEffect(() => {
54
+ if (expanded !== void 0) setOpen(expanded);
55
+ }, [expanded]);
56
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(Collapsible.Root, {
57
+ className: cls(!invisible && "border-hairline border", "rounded-lg", "w-full", className),
58
+ open,
59
+ onOpenChange: (updatedOpen) => {
60
+ onExpandedChange?.(updatedOpen);
61
+ setOpen(updatedOpen);
62
+ },
63
+ children: [/* @__PURE__ */ jsx(Collapsible.Trigger, {
64
+ asChild: true,
65
+ children: /* @__PURE__ */ jsxs("div", {
66
+ className: cls("rounded-t-lg flex items-center justify-between w-full min-h-[52px]", "hover:bg-surface-hover active:bg-surface-active", invisible ? "border-b px-2" : "p-4", open ? "py-6" : "py-4", "transition-all duration-200 motion-reduce:transition-none", invisible && "border-hairline", asField && "bg-surface-field border border-hairline", titleClassName, "cursor-pointer"),
67
+ role: "button",
68
+ tabIndex: 0,
69
+ "aria-expanded": open,
70
+ onKeyDown: (event) => {
71
+ if (event.target !== event.currentTarget) return;
72
+ if (event.key !== "Enter" && event.key !== " ") return;
73
+ event.preventDefault();
74
+ event.currentTarget.click();
75
+ },
76
+ children: [title, /* @__PURE__ */ jsx(ChevronDownIcon, { className: cls("transition", open ? "rotate-180" : "") })]
77
+ })
78
+ }), /* @__PURE__ */ jsx(Collapsible.Content, {
79
+ className: cls("CollapsibleContent"),
80
+ style: { overflow: allowOverflow ? "visible" : "hidden" },
81
+ children: /* @__PURE__ */ jsx("div", {
82
+ className: innerClassName,
83
+ children
84
+ })
85
+ })]
86
+ }) });
87
+ }
88
+ //#endregion
89
+ export { ExpandablePanel };
90
+
91
+ //# sourceMappingURL=ExpandablePanel.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpandablePanel.es.js","names":[],"sources":["../../src/components/ExpandablePanel.tsx"],"sourcesContent":["\n\"use client\";\nimport React, { PropsWithChildren, useEffect, useState } from \"react\";\n\nimport * as Collapsible from \"@radix-ui/react-collapsible\";\nimport { defaultBorderMixin, fieldBackgroundMixin } from \"../styles\";\nimport { ChevronDownIcon } from \"lucide-react\";\nimport { cls } from \"../util\";\nimport { useInjectStyles } from \"../hooks\";\n\nexport function ExpandablePanel({\n title,\n children,\n invisible = false,\n expanded,\n onExpandedChange,\n initiallyExpanded = true,\n titleClassName,\n asField,\n className,\n innerClassName\n }: PropsWithChildren<{\n title: React.ReactNode,\n invisible?: boolean,\n initiallyExpanded?: boolean;\n expanded?: boolean;\n onExpandedChange?: (expanded: boolean) => void,\n titleClassName?: string,\n asField?: boolean,\n className?: string,\n innerClassName?: string\n}>) {\n\n useInjectStyles(\"ExpandablePanel\", `\n.CollapsibleContent {\n overflow: hidden;\n}\n.CollapsibleContent[data-state='open'] {\n animation: expandablePanelSlideDown 220ms ease-out\n}\n.CollapsibleContent[data-state='closed'] {\n animation: expandablePanelSlideUp 220ms ease-out;\n}\n\n@keyframes expandablePanelSlideDown {\n from {\n height: 0;\n }\n to {\n height: var(--radix-collapsible-content-height);\n }\n}\n\n@keyframes expandablePanelSlideUp {\n from {\n height: var(--radix-collapsible-content-height);\n }\n to {\n height: 0;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .CollapsibleContent[data-state] {\n animation: none;\n }\n}`);\n\n const [open, setOpen] = useState(expanded !== undefined ? expanded : initiallyExpanded);\n const [allowOverflow, setAllowOverflow] = useState(open);\n\n useEffect(() => {\n if (open) {\n setTimeout(() => {\n setAllowOverflow(true);\n }, 220);\n } else {\n setAllowOverflow(false);\n }\n }, [open]);\n\n useEffect(() => {\n if (expanded !== undefined)\n setOpen(expanded);\n }, [expanded]);\n\n return (<>\n <Collapsible.Root\n className={cls(\n !invisible && defaultBorderMixin + \" border\",\n \"rounded-lg\",\n \"w-full\",\n className\n )}\n open={open}\n onOpenChange={(updatedOpen: boolean) => {\n onExpandedChange?.(updatedOpen);\n setOpen(updatedOpen);\n }}>\n\n <Collapsible.Trigger asChild>\n <div\n className={cls(\n \"rounded-t-lg flex items-center justify-between w-full min-h-[52px]\",\n \"hover:bg-surface-hover active:bg-surface-active\",\n invisible ? \"border-b px-2\" : \"p-4\",\n open ? \"py-6\" : \"py-4\",\n \"transition-all duration-200 motion-reduce:transition-none\",\n invisible && defaultBorderMixin,\n asField && fieldBackgroundMixin,\n titleClassName,\n \"cursor-pointer\"\n )}\n role=\"button\"\n tabIndex={0}\n aria-expanded={open}\n // A role=\"button\" has to answer Enter and Space itself:\n // Radix's trigger listens for click only, and a div does\n // not turn a key into a click, so the header took focus and\n // then ignored the keyboard. Only for keys pressed on the\n // header — a control inside the title keeps its own keys.\n onKeyDown={(event) => {\n if (event.target !== event.currentTarget) return;\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault(); // Space would scroll the page\n event.currentTarget.click();\n }}\n >\n {title}\n <ChevronDownIcon className={cls(\"transition\", open ? \"rotate-180\" : \"\")}/>\n </div>\n </Collapsible.Trigger>\n\n <Collapsible.Content\n className={cls(\"CollapsibleContent\")}\n style={{\n overflow: allowOverflow ? \"visible\" : \"hidden\"\n }}\n >\n <div className={innerClassName}>\n {children}\n </div>\n </Collapsible.Content>\n </Collapsible.Root>\n </>\n )\n}\n"],"mappings":";;;;;;;;;AAUA,SAAgB,gBAAgB,EACI,OACA,UACA,YAAY,OACZ,UACA,kBACA,oBAAoB,MACpB,gBACA,SACA,WACA,kBAWhC;CAEA,gBAAgB,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiCrC;CAEE,MAAM,CAAC,MAAM,WAAW,SAAS,aAAa,KAAA,IAAY,WAAW,iBAAiB;CACtF,MAAM,CAAC,eAAe,oBAAoB,SAAS,IAAI;CAEvD,gBAAgB;EACZ,IAAI,MACA,iBAAiB;GACb,iBAAiB,IAAI;EACzB,GAAG,GAAG;OAEN,iBAAiB,KAAK;CAE9B,GAAG,CAAC,IAAI,CAAC;CAET,gBAAgB;EACZ,IAAI,aAAa,KAAA,GACb,QAAQ,QAAQ;CACxB,GAAG,CAAC,QAAQ,CAAC;CAEb,OAAQ,oBAAA,UAAA,EAAA,UACA,qBAAC,YAAY,MAAb;EACI,WAAW,IACP,CAAC,aAAA,0BACD,cACA,UACA,SACJ;EACM;EACN,eAAe,gBAAyB;GACpC,mBAAmB,WAAW;GAC9B,QAAQ,WAAW;EACvB;YAXJ,CAaI,oBAAC,YAAY,SAAb;GAAqB,SAAA;aACjB,qBAAC,OAAD;IACI,WAAW,IACP,sEACA,mDACA,YAAY,kBAAkB,OAC9B,OAAO,SAAS,QAChB,6DACA,aAAA,mBACA,WAAA,2CACA,gBACA,gBACJ;IACA,MAAK;IACL,UAAU;IACV,iBAAe;IAMf,YAAY,UAAU;KAClB,IAAI,MAAM,WAAW,MAAM,eAAe;KAC1C,IAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,KAAK;KAChD,MAAM,eAAe;KACrB,MAAM,cAAc,MAAM;IAC9B;cAzBJ,CA2BK,OACD,oBAAC,iBAAD,EAAiB,WAAW,IAAI,cAAc,OAAO,eAAe,EAAE,EAAG,CAAA,CACxE;;EACY,CAAA,GAErB,oBAAC,YAAY,SAAb;GACI,WAAW,IAAI,oBAAoB;GACnC,OAAO,EACH,UAAU,gBAAgB,YAAY,SAC1C;aAEA,oBAAC,OAAD;IAAK,WAAW;IACX;GACA,CAAA;EACY,CAAA,CACP;IACpB,CAAA;AAEV"}
@@ -0,0 +1,58 @@
1
+ "use client";
2
+ import { fieldBackgroundHoverMixin, fieldBackgroundMixin } from "../styles.es.js";
3
+ import { cls } from "../util/cls.es.js";
4
+ import { Typography } from "./Typography.es.js";
5
+ import "react";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ import { useDropzone } from "react-dropzone";
8
+ //#region src/components/FileUpload.tsx
9
+ function FileUpload({ accept, onFilesAdded, onFilesRejected, maxSize, disabled, maxFiles, title, uploadDescription, children, preventDropOnDocument = true, size }) {
10
+ const { getRootProps, getInputProps, isDragActive, isDragAccept, isDragReject } = useDropzone({
11
+ accept,
12
+ noDragEventsBubbling: true,
13
+ maxSize,
14
+ onDrop: onFilesAdded,
15
+ onDropRejected: onFilesRejected,
16
+ disabled,
17
+ maxFiles,
18
+ preventDropOnDocument
19
+ });
20
+ return /* @__PURE__ */ jsxs("div", {
21
+ ...getRootProps(),
22
+ role: "button",
23
+ "aria-label": typeof title === "string" ? title : typeof uploadDescription === "string" ? uploadDescription : "Upload file",
24
+ "aria-disabled": disabled || void 0,
25
+ className: cls(fieldBackgroundMixin, "flex gap-2", "p-4 box-border relative items-center border-2 border-solid border-transparent outline-hidden rounded-lg duration-200 ease-[cubic-bezier(0.4,0,0.2,1)] focus:border-primary", {
26
+ "h-44": size === "large",
27
+ "h-28": size === "medium",
28
+ "h-16": size === "small",
29
+ "cursor-pointer": !disabled,
30
+ [fieldBackgroundHoverMixin]: !isDragActive,
31
+ "transition-colors duration-200 ease-[cubic-bezier(0,0,0.2,1)] border-red-500": isDragReject,
32
+ "transition-colors duration-200 ease-[cubic-bezier(0,0,0.2,1)] border-green-500": isDragAccept
33
+ }),
34
+ children: [
35
+ /* @__PURE__ */ jsx(Typography, {
36
+ variant: "caption",
37
+ color: "secondary",
38
+ className: "absolute top-2 left-3.5 cursor-inherit",
39
+ children: title
40
+ }),
41
+ /* @__PURE__ */ jsx("input", { ...getInputProps() }),
42
+ children,
43
+ /* @__PURE__ */ jsx("div", {
44
+ className: "grow h-28 box-border flex flex-col items-center justify-center text-center",
45
+ children: /* @__PURE__ */ jsx(Typography, {
46
+ align: "center",
47
+ variant: "label",
48
+ className: "flex flex-row gap-2 justify-center",
49
+ children: uploadDescription
50
+ })
51
+ })
52
+ ]
53
+ });
54
+ }
55
+ //#endregion
56
+ export { FileUpload };
57
+
58
+ //# sourceMappingURL=FileUpload.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileUpload.es.js","names":[],"sources":["../../src/components/FileUpload.tsx"],"sourcesContent":["\"use client\";\nimport React from \"react\";\nimport { useDropzone } from \"react-dropzone\";\nimport { fieldBackgroundHoverMixin, fieldBackgroundMixin } from \"../styles\";\nimport { cls } from \"../util\";\nimport { Typography } from \"./Typography\";\n\nexport interface FileUploadError {\n message: string;\n code: string;\n}\n\nexport type OnFileUploadRejected = (fileRejections: {\n file: File;\n errors: readonly FileUploadError[];\n}[], event: object) => void;\n\nexport type OnFilesUploadAdded = (files: File[]) => void;\n\nexport type FileUploadProps = {\n // e.g. accept={{ \"*/image\": [] }}\n accept?: Record<string, string[]>,\n onFilesAdded: OnFilesUploadAdded,\n onFilesRejected?: OnFileUploadRejected,\n maxSize?: number,\n disabled?: boolean;\n maxFiles?: number;\n title?: React.ReactNode;\n uploadDescription?: React.ReactNode;\n preventDropOnDocument?: boolean;\n size?: \"small\" | \"medium\" | \"large\";\n};\n\nexport function FileUpload({\n accept,\n onFilesAdded,\n onFilesRejected,\n maxSize,\n disabled,\n maxFiles,\n title,\n uploadDescription,\n children,\n preventDropOnDocument = true,\n size\n}: React.PropsWithChildren<FileUploadProps>) {\n\n const {\n getRootProps,\n getInputProps,\n isDragActive,\n isDragAccept,\n isDragReject\n } = useDropzone({\n accept,\n noDragEventsBubbling: true,\n maxSize,\n onDrop: onFilesAdded,\n onDropRejected: onFilesRejected,\n disabled,\n maxFiles,\n preventDropOnDocument\n }\n );\n return <div\n {...getRootProps()}\n role=\"button\"\n aria-label={typeof title === \"string\" ? title : (typeof uploadDescription === \"string\" ? uploadDescription : \"Upload file\")}\n aria-disabled={disabled || undefined}\n className={cls(\n fieldBackgroundMixin,\n \"flex gap-2\",\n \"p-4 box-border relative items-center border-2 border-solid border-transparent outline-hidden rounded-lg duration-200 ease-[cubic-bezier(0.4,0,0.2,1)] focus:border-primary\",\n {\n \"h-44\": size === \"large\",\n \"h-28\": size === \"medium\",\n \"h-16\": size === \"small\",\n \"cursor-pointer\": !disabled,\n [fieldBackgroundHoverMixin]: !isDragActive,\n \"transition-colors duration-200 ease-[cubic-bezier(0,0,0.2,1)] border-red-500\": isDragReject,\n \"transition-colors duration-200 ease-[cubic-bezier(0,0,0.2,1)] border-green-500\": isDragAccept\n })}>\n\n <Typography variant={\"caption\"} color={\"secondary\"} className={\"absolute top-2 left-3.5 cursor-inherit\"}>\n {title}\n </Typography>\n\n <input\n {...getInputProps()}/>\n\n {children}\n\n <div\n className=\"grow h-28 box-border flex flex-col items-center justify-center text-center\">\n <Typography align={\"center\"}\n variant={\"label\"}\n className={\"flex flex-row gap-2 justify-center\"}>\n {uploadDescription}\n </Typography>\n </div>\n\n </div>\n}\n"],"mappings":";;;;;;;;AAiCA,SAAgB,WAAW,EACvB,QACA,cACA,iBACA,SACA,UACA,UACA,OACA,mBACA,UACA,wBAAwB,MACxB,QACyC;CAEzC,MAAM,EACF,cACA,eACA,cACA,cACA,iBACA,YAAY;EACZ;EACA,sBAAsB;EACtB;EACA,QAAQ;EACR,gBAAgB;EAChB;EACA;EACA;CACJ,CACA;CACA,OAAO,qBAAC,OAAD;EACH,GAAI,aAAa;EACjB,MAAK;EACL,cAAY,OAAO,UAAU,WAAW,QAAS,OAAO,sBAAsB,WAAW,oBAAoB;EAC7G,iBAAe,YAAY,KAAA;EAC3B,WAAW,IACP,sBACA,cACA,8KACA;GACI,QAAQ,SAAS;GACjB,QAAQ,SAAS;GACjB,QAAQ,SAAS;GACjB,kBAAkB,CAAC;IAClB,4BAA4B,CAAC;GAC9B,gFAAgF;GAChF,kFAAkF;EACtF,CAAC;YAjBF;GAmBH,oBAAC,YAAD;IAAY,SAAS;IAAW,OAAO;IAAa,WAAW;cAC1D;GACO,CAAA;GAEZ,oBAAC,SAAD,EACI,GAAI,cAAc,EAAG,CAAA;GAExB;GAED,oBAAC,OAAD;IACI,WAAU;cACV,oBAAC,YAAD;KAAY,OAAO;KACf,SAAS;KACT,WAAW;eACV;IACO,CAAA;GACX,CAAA;EAEJ;;AACT"}
@@ -0,0 +1,31 @@
1
+ import { cls } from "../util/cls.es.js";
2
+ import React from "react";
3
+ import { jsxs } from "react/jsx-runtime";
4
+ //#region src/components/FilterChip.tsx
5
+ var sizeClasses = {
6
+ small: "px-2 py-0.5 text-xs",
7
+ medium: "px-2.5 py-1 text-xs"
8
+ };
9
+ /**
10
+ * A toggle chip used for filter presets and similar multi-select controls.
11
+ *
12
+ * Reads as a text tab: no fill at rest, the alpha highlight when active. It
13
+ * shares no grammar with the tinted enum {@link Chip}, which carries a hue.
14
+ *
15
+ * @group Interactive components
16
+ */
17
+ var FilterChip = React.forwardRef(function FilterChip({ children, active = false, onClick, icon, size = "medium", className, disabled = false, ...rest }, ref) {
18
+ return /* @__PURE__ */ jsxs("button", {
19
+ ref,
20
+ type: "button",
21
+ onClick,
22
+ disabled,
23
+ className: cls("inline-flex items-center gap-1 rounded-md", "font-medium whitespace-nowrap select-none shrink-0", "transition-colors duration-150", "focus-visible:outline-none focus-visible:ring-primary/50", sizeClasses[size], !disabled && "cursor-pointer", active ? "bg-surface-active text-text-primary dark:text-text-primary-dark" : cls("bg-transparent text-text-secondary dark:text-text-secondary-dark", !disabled && "hover:bg-surface-hover"), disabled && "opacity-50 cursor-not-allowed", className),
24
+ ...rest,
25
+ children: [icon, children]
26
+ });
27
+ });
28
+ //#endregion
29
+ export { FilterChip };
30
+
31
+ //# sourceMappingURL=FilterChip.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FilterChip.es.js","names":[],"sources":["../../src/components/FilterChip.tsx"],"sourcesContent":["import React from \"react\";\nimport { cls } from \"../util\";\n\nexport interface FilterChipProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"children\"> {\n /**\n * The text label displayed on the chip.\n */\n children: React.ReactNode;\n /**\n * Whether the chip is currently in an active/selected state.\n */\n active?: boolean;\n /**\n * Optional icon rendered before the label.\n */\n icon?: React.ReactNode;\n /**\n * Size variant.\n * @default \"medium\"\n */\n size?: \"small\" | \"medium\";\n /**\n * Whether the chip is disabled.\n */\n disabled?: boolean;\n}\n\nconst sizeClasses = {\n small: \"px-2 py-0.5 text-xs\",\n medium: \"px-2.5 py-1 text-xs\"\n};\n\n/**\n * A toggle chip used for filter presets and similar multi-select controls.\n *\n * Reads as a text tab: no fill at rest, the alpha highlight when active. It\n * shares no grammar with the tinted enum {@link Chip}, which carries a hue.\n *\n * @group Interactive components\n */\nexport const FilterChip = React.forwardRef<HTMLButtonElement, FilterChipProps>(function FilterChip({\n children,\n active = false,\n onClick,\n icon,\n size = \"medium\",\n className,\n disabled = false,\n ...rest\n}: FilterChipProps, ref) {\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={onClick}\n disabled={disabled}\n className={cls(\n \"inline-flex items-center gap-1 rounded-md\",\n \"font-medium whitespace-nowrap select-none shrink-0\",\n \"transition-colors duration-150\",\n // Colour only, no width: the 2px comes from the global inset ring, which a\n // chip needs because the preset row it sits in is a horizontal\n // scroller — an outset ring on the first or last chip was cut off\n // by the scrollport edge.\n \"focus-visible:outline-none focus-visible:ring-primary/50\",\n sizeClasses[size],\n !disabled && \"cursor-pointer\",\n // Hover is one step along the same ramp the chip already sits\n // on, the way every other hoverable surface here moves. It used\n // to be `hover:bg-primary/5` for the inactive chip, which\n // *replaces* the resting fill with a tint fainter than it — so\n // pointing at a chip made its background vanish. The active chip\n // had no hover state at all.\n // These are view presets, not enum values, so they take the row\n // grammar (an alpha highlight for the active one, text otherwise)\n // and not the chip grammar (a hue tint). A primary ring here made\n // every preset look like a selected enum cell.\n active\n ? \"bg-surface-active text-text-primary dark:text-text-primary-dark\"\n : cls(\n \"bg-transparent text-text-secondary dark:text-text-secondary-dark\",\n !disabled && \"hover:bg-surface-hover\"\n ),\n disabled && \"opacity-50 cursor-not-allowed\",\n className\n )}\n {...rest}\n >\n {icon}\n {children}\n </button>\n );\n});\n"],"mappings":";;;;AA2BA,IAAM,cAAc;CAChB,OAAO;CACP,QAAQ;AACZ;;;;;;;;;AAUA,IAAa,aAAa,MAAM,WAA+C,SAAS,WAAW,EAC/F,UACA,SAAS,OACT,SACA,MACA,OAAO,UACP,WACA,WAAW,OACX,GAAG,QACa,KAAK;CACrB,OACI,qBAAC,UAAD;EACS;EACL,MAAK;EACI;EACC;EACV,WAAW,IACP,6CACA,sDACA,kCAKA,4DACA,YAAY,OACZ,CAAC,YAAY,kBAWb,SACM,oEACA,IACE,oEACA,CAAC,YAAY,wBACjB,GACJ,YAAY,iCACZ,SACJ;EACA,GAAI;YAnCR,CAqCK,MACA,QACG;;AAEhB,CAAC"}
@@ -0,0 +1,52 @@
1
+ "use client";
2
+ import { cls } from "../util/cls.es.js";
3
+ import React from "react";
4
+ import { jsx } from "react/jsx-runtime";
5
+ //#region src/components/IconButton.tsx
6
+ var buttonClasses = "motion-safe:hover:scale-[1.04] motion-safe:active:scale-95 transition-transform";
7
+ var baseClasses = "inline-flex items-center justify-center text-sm font-medium focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 transition-colors ease-in-out duration-150 [&>svg]:shrink-0";
8
+ var colorClasses = "text-surface-accent-500 visited:text-surface-accent-500 dark:text-surface-accent-300 dark:visited:text-surface-accent-300";
9
+ var sizeClasses = {
10
+ medium: "w-10 !h-10 min-w-10 min-h-10 p-2",
11
+ small: "w-8 !h-8 min-w-8 min-h-8 p-2",
12
+ smallest: "w-7 !h-7 min-w-7 min-h-7 p-2",
13
+ large: "w-12 !h-12 min-w-12 min-h-12 p-2"
14
+ };
15
+ var shapeClasses = {
16
+ circular: "rounded-full",
17
+ square: "rounded-md"
18
+ };
19
+ /** Icon size used when the caller doesn't set one on the child. */
20
+ var defaultIconSize = {
21
+ smallest: 16,
22
+ small: 18,
23
+ medium: 20,
24
+ large: 24
25
+ };
26
+ var IconButtonInner = ({ children, className, size = "medium", variant = "ghost", shape = "circular", disabled, toggled, component, onClick, ...props }, ref) => {
27
+ const bgClasses = variant === "ghost" ? "bg-transparent hover:bg-surface-hover" : "bg-surface-raised hover:bg-surface-raised-hover";
28
+ const Component = component || "button";
29
+ const isNativeButton = Component === "button";
30
+ const sizedChildren = React.Children.map(children, (child) => {
31
+ if (!React.isValidElement(child)) return child;
32
+ if (child.props.size !== void 0) return child;
33
+ return React.cloneElement(child, { size: defaultIconSize[size] });
34
+ });
35
+ return /* @__PURE__ */ jsx(Component, {
36
+ type: isNativeButton ? "button" : void 0,
37
+ role: isNativeButton ? void 0 : "button",
38
+ ref,
39
+ disabled: isNativeButton ? disabled : void 0,
40
+ "aria-disabled": disabled || void 0,
41
+ tabIndex: disabled ? -1 : void 0,
42
+ onClick: disabled ? void 0 : onClick,
43
+ ...props,
44
+ className: cls(disabled ? "opacity-50 pointer-events-none" : "cursor-pointer", toggled ? "outline outline-2 outline-primary" : "", "text-inherit dark:text-inherit", colorClasses, bgClasses, baseClasses, buttonClasses, shapeClasses[shape], sizeClasses[size], className),
45
+ children: sizedChildren
46
+ });
47
+ };
48
+ var IconButton = React.forwardRef(IconButtonInner);
49
+ //#endregion
50
+ export { IconButton };
51
+
52
+ //# sourceMappingURL=IconButton.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IconButton.es.js","names":[],"sources":["../../src/components/IconButton.tsx"],"sourcesContent":["\"use client\";\nimport React from \"react\";\nimport { cls } from \"../util\";\n\ntype IconButtonOwnProps<C extends React.ElementType> = {\n size?: \"medium\" | \"small\" | \"smallest\" | \"large\";\n variant?: \"ghost\" | \"filled\",\n shape?: \"circular\" | \"square\",\n disabled?: boolean;\n toggled?: boolean;\n component?: C;\n onClick?: React.MouseEventHandler<HTMLElement>;\n className?: string;\n children?: React.ReactNode;\n \"aria-label\"?: string;\n};\n\n/**\n * The kit's own props, plus those of the element it renders (`button`, or\n * `component`). Typed against that element rather than `any`: a misspelt or\n * invented prop is a compile error, not an attribute on the DOM. `color` is\n * left out — it is an obsolete HTML attribute that does nothing, and callers\n * wrote `color=\"primary\"` expecting the accent icon `Button`'s `color` gives.\n */\nexport type IconButtonProps<C extends React.ElementType = \"button\"> =\n IconButtonOwnProps<C> & Omit<React.ComponentPropsWithoutRef<C>, keyof IconButtonOwnProps<C> | \"color\">;\n\nconst buttonClasses = \"motion-safe:hover:scale-[1.04] motion-safe:active:scale-95 transition-transform\";\n// `[&>svg]:shrink-0` is load-bearing: without it flex compresses the icon to\n// whatever width is left after padding, so an 18px icon in a 28px button\n// rendered 12x18 — visibly squashed rather than merely small.\nconst baseClasses = \"inline-flex items-center justify-center text-sm font-medium focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50 transition-colors ease-in-out duration-150 [&>svg]:shrink-0\";\nconst colorClasses = \"text-surface-accent-500 visited:text-surface-accent-500 dark:text-surface-accent-300 dark:visited:text-surface-accent-300\";\n// Padding stays a flat p-2 (as it always was). Callers pass their own icon\n// sizes, so tightening it here shrinks the content box under an icon that was\n// sized for the old one and makes the icon overflow. `shrink-0` above is what\n// actually fixes the squashing — the icon keeps its own dimensions and simply\n// eats into the padding.\nconst sizeClasses = {\n medium: \"w-10 !h-10 min-w-10 min-h-10 p-2\",\n small: \"w-8 !h-8 min-w-8 min-h-8 p-2\",\n smallest: \"w-7 !h-7 min-w-7 min-h-7 p-2\",\n large: \"w-12 !h-12 min-w-12 min-h-12 p-2\"\n}\nconst shapeClasses = {\n circular: \"rounded-full\",\n square: \"rounded-md\"\n}\n\n/** Icon size used when the caller doesn't set one on the child. */\nconst defaultIconSize = {\n smallest: 16,\n small: 18,\n medium: 20,\n large: 24\n} as const;\n\nconst IconButtonInner = <C extends React.ElementType = \"button\">({\n children,\n className,\n size = \"medium\",\n variant = \"ghost\",\n shape = \"circular\",\n disabled,\n toggled,\n component,\n onClick,\n ...props\n }: IconButtonProps<C>, ref: React.ForwardedRef<HTMLButtonElement>) => {\n\n const bgClasses = variant === \"ghost\" ? \"bg-transparent hover:bg-surface-hover\" : \"bg-surface-raised hover:bg-surface-raised-hover\";\n const Component: React.ElementType = component || \"button\";\n const isNativeButton = Component === \"button\";\n\n // Give the icon a size that matches the button when the caller didn't pick\n // one. Without this a bare <IconButton size=\"smallest\"><PencilIcon/></…>\n // renders lucide's 24px default inside a 28px button, so icon size ended up\n // depending on whether each call site happened to pass one — which is what\n // made a row of icon buttons look randomly sized. An explicit `size` on the\n // child always wins.\n const sizedChildren = React.Children.map(children, (child) => {\n if (!React.isValidElement(child)) return child;\n if ((child.props as { size?: unknown }).size !== undefined) return child;\n return React.cloneElement(child as React.ReactElement<{ size?: number }>,\n { size: defaultIconSize[size] });\n });\n return (\n <Component\n type={isNativeButton ? \"button\" : undefined}\n role={isNativeButton ? undefined : \"button\"}\n ref={ref}\n // Natively disabled, not only `aria-disabled`: a button that disables\n // itself on click keeps the focus, and Enter or Space fired it again.\n disabled={isNativeButton ? disabled : undefined}\n aria-disabled={disabled || undefined}\n tabIndex={disabled ? -1 : undefined}\n // Any other element has no native `disabled`, so the click is dropped here.\n onClick={disabled ? undefined : onClick}\n {...props}\n className={cls(\n disabled ? \"opacity-50 pointer-events-none\" : \"cursor-pointer\",\n toggled ? \"outline outline-2 outline-primary\" : \"\",\n \"text-inherit dark:text-inherit\",\n colorClasses,\n bgClasses,\n baseClasses,\n buttonClasses,\n shapeClasses[shape],\n sizeClasses[size],\n className\n )}>\n {sizedChildren}\n </Component>\n );\n};\n\nexport const IconButton = React.forwardRef(IconButtonInner as React.ForwardRefRenderFunction<HTMLButtonElement, IconButtonProps<React.ElementType>>) as\n <C extends React.ElementType = \"button\">(props: IconButtonProps<C> & React.RefAttributes<HTMLButtonElement>) => React.ReactElement | null;\n"],"mappings":";;;;;AA2BA,IAAM,gBAAgB;AAItB,IAAM,cAAc;AACpB,IAAM,eAAe;AAMrB,IAAM,cAAc;CAChB,QAAQ;CACR,OAAO;CACP,UAAU;CACV,OAAO;AACX;AACA,IAAM,eAAe;CACjB,UAAU;CACV,QAAQ;AACZ;;AAGA,IAAM,kBAAkB;CACpB,UAAU;CACV,OAAO;CACP,QAAQ;CACR,OAAO;AACX;AAEA,IAAM,mBAA2D,EACI,UACA,WACA,OAAO,UACP,UAAU,SACV,QAAQ,YACR,UACA,SACA,WACA,SACA,GAAG,SACgB,QAA+C;CAEnI,MAAM,YAAY,YAAY,UAAU,0CAA0C;CAClF,MAAM,YAA+B,aAAa;CAClD,MAAM,iBAAiB,cAAc;CAQrC,MAAM,gBAAgB,MAAM,SAAS,IAAI,WAAW,UAAU;EAC1D,IAAI,CAAC,MAAM,eAAe,KAAK,GAAG,OAAO;EACzC,IAAK,MAAM,MAA6B,SAAS,KAAA,GAAW,OAAO;EACnE,OAAO,MAAM,aAAa,OACtB,EAAE,MAAM,gBAAgB,MAAM,CAAC;CACvC,CAAC;CACD,OACI,oBAAC,WAAD;EACI,MAAM,iBAAiB,WAAW,KAAA;EAClC,MAAM,iBAAiB,KAAA,IAAY;EAC9B;EAGL,UAAU,iBAAiB,WAAW,KAAA;EACtC,iBAAe,YAAY,KAAA;EAC3B,UAAU,WAAW,KAAK,KAAA;EAE1B,SAAS,WAAW,KAAA,IAAY;EAChC,GAAI;EACJ,WAAW,IACP,WAAW,mCAAmC,kBAC9C,UAAU,sCAAsC,IAChD,kCACA,cACA,WACA,aACA,eACA,aAAa,QACb,YAAY,OACZ,SACJ;YACC;CACM,CAAA;AAEnB;AAEA,IAAa,aAAa,MAAM,WAAW,eAAwG"}
@@ -0,0 +1,18 @@
1
+ import { cls } from "../util/cls.es.js";
2
+ import "react";
3
+ import { jsx } from "react/jsx-runtime";
4
+ //#region src/components/InfoLabel.tsx
5
+ var colorClasses = {
6
+ info: "bg-blue-500/8 dark:bg-blue-500/12 text-blue-800 dark:text-blue-200 border border-blue-500/20 dark:border-blue-500/25",
7
+ warn: "bg-amber-500/8 dark:bg-amber-500/12 text-amber-800 dark:text-amber-200 border border-amber-500/20 dark:border-amber-500/25"
8
+ };
9
+ function InfoLabel({ children, mode = "info" }) {
10
+ return /* @__PURE__ */ jsx("div", {
11
+ className: cls("my-3 py-2 px-4 rounded-lg text-sm font-medium leading-snug", colorClasses[mode]),
12
+ children
13
+ });
14
+ }
15
+ //#endregion
16
+ export { InfoLabel };
17
+
18
+ //# sourceMappingURL=InfoLabel.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InfoLabel.es.js","names":[],"sources":["../../src/components/InfoLabel.tsx"],"sourcesContent":["import React from \"react\";\nimport { cls } from \"../util\";\n\nconst colorClasses = {\n info: \"bg-blue-500/8 dark:bg-blue-500/12 text-blue-800 dark:text-blue-200 border border-blue-500/20 dark:border-blue-500/25\",\n warn: \"bg-amber-500/8 dark:bg-amber-500/12 text-amber-800 dark:text-amber-200 border border-amber-500/20 dark:border-amber-500/25\"\n}\n\nexport function InfoLabel({\n children,\n mode = \"info\"\n }: {\n children: React.ReactNode,\n mode?: \"info\" | \"warn\"\n}) {\n\n return (\n <div\n className={cls(\"my-3 py-2 px-4 rounded-lg text-sm font-medium leading-snug\", colorClasses[mode])}>\n {children}\n </div>\n )\n}\n"],"mappings":";;;;AAGA,IAAM,eAAe;CACjB,MAAM;CACN,MAAM;AACV;AAEA,SAAgB,UAAU,EACI,UACA,OAAO,UAIlC;CAEC,OACI,oBAAC,OAAD;EACI,WAAW,IAAI,8DAA8D,aAAa,KAAK;EAC9F;CACA,CAAA;AAEb"}
@@ -0,0 +1,27 @@
1
+ "use client";
2
+ import { defaultBorderMixin } from "../styles.es.js";
3
+ import { cls } from "../util/cls.es.js";
4
+ import * as React$1 from "react";
5
+ import { jsx } from "react/jsx-runtime";
6
+ //#region src/components/InputLabel.tsx
7
+ var defaultClasses = {
8
+ root: "origin-left transition-transform block whitespace-nowrap overflow-hidden text-ellipsis max-w-full",
9
+ shrink: "transform translate-y-[2px] scale-75 translate-x-[12px]",
10
+ expanded: "translate-x-[16px] top-0 transform translate-y-[16px] scale-100"
11
+ };
12
+ var InputLabel = React$1.forwardRef(function InputLabel(inProps, ref) {
13
+ const { shrink, className, ...other } = inProps;
14
+ return /* @__PURE__ */ jsx("label", {
15
+ className: cls("text-sm font-medium peer-disabled:cursor-not-allowed", defaultBorderMixin, cls(defaultClasses.root, {
16
+ [defaultClasses.shrink]: shrink,
17
+ [defaultClasses.expanded]: !shrink
18
+ }, className)),
19
+ "data-shrink": shrink,
20
+ ref,
21
+ ...other
22
+ });
23
+ });
24
+ //#endregion
25
+ export { InputLabel };
26
+
27
+ //# sourceMappingURL=InputLabel.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InputLabel.es.js","names":[],"sources":["../../src/components/InputLabel.tsx"],"sourcesContent":["\"use client\";\nimport * as React from \"react\";\nimport { cls } from \"../util\";\nimport { defaultBorderMixin } from \"../styles\";\n\nexport type InputLabelProps = {\n children?: React.ReactNode;\n className?: string;\n shrink?: boolean;\n} & React.LabelHTMLAttributes<HTMLLabelElement>;\n\nconst defaultClasses = {\n root: \"origin-left transition-transform block whitespace-nowrap overflow-hidden text-ellipsis max-w-full\",\n shrink: \"transform translate-y-[2px] scale-75 translate-x-[12px]\",\n expanded: \"translate-x-[16px] top-0 transform translate-y-[16px] scale-100\"\n};\n\nexport const InputLabel = React.forwardRef<HTMLLabelElement, InputLabelProps>(function InputLabel(inProps, ref) {\n const {\n shrink,\n className,\n ...other\n } = inProps;\n\n const computedClassName = cls(defaultClasses.root,\n {\n [defaultClasses.shrink]: shrink,\n [defaultClasses.expanded]: !shrink\n }, className);\n\n return (\n <label\n className={cls(\"text-sm font-medium peer-disabled:cursor-not-allowed\",\n defaultBorderMixin, computedClassName)}\n data-shrink={shrink}\n ref={ref}\n {...other}\n />\n );\n});\n"],"mappings":";;;;;;AAWA,IAAM,iBAAiB;CACnB,MAAM;CACN,QAAQ;CACR,UAAU;AACd;AAEA,IAAa,aAAa,QAAM,WAA8C,SAAS,WAAW,SAAS,KAAK;CAC5G,MAAM,EACF,QACA,WACA,GAAG,UACH;CAQJ,OACI,oBAAC,SAAD;EACI,WAAW,IAAI,wDACX,oBATc,IAAI,eAAe,MACzC;IACK,eAAe,SAAS;IACxB,eAAe,WAAW,CAAC;EAChC,GAAG,SAKyB,CAAiB;EACzC,eAAa;EACR;EACL,GAAI;CACP,CAAA;AAET,CAAC"}
@@ -0,0 +1,18 @@
1
+ "use client";
2
+ import { defaultBorderMixin } from "../styles.es.js";
3
+ import { cls } from "../util/cls.es.js";
4
+ import * as React$1 from "react";
5
+ import { jsx } from "react/jsx-runtime";
6
+ import * as LabelPrimitive from "@radix-ui/react-label";
7
+ //#region src/components/Label.tsx
8
+ var Label = React$1.forwardRef(({ className, border, onClick, ...props }, ref) => /* @__PURE__ */ jsx(LabelPrimitive.Root, {
9
+ ref,
10
+ onClick,
11
+ className: cls("text-sm font-medium peer-disabled:cursor-not-allowed", border && "border border-hairline-strong rounded-md px-3 py-1.5", onClick && "hover:cursor-pointer hover:bg-surface-hover", defaultBorderMixin, className),
12
+ ...props
13
+ }));
14
+ Label.displayName = LabelPrimitive.Root.displayName;
15
+ //#endregion
16
+ export { Label };
17
+
18
+ //# sourceMappingURL=Label.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Label.es.js","names":[],"sources":["../../src/components/Label.tsx"],"sourcesContent":["\"use client\";\nimport * as React from \"react\"\nimport * as LabelPrimitive from \"@radix-ui/react-label\"\nimport { cls } from \"../util\";\nimport { defaultBorderMixin } from \"../styles\";\n\ntype LabelProps = React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & {\n border?: boolean,\n onClick?: React.MouseEventHandler<HTMLLabelElement>\n};\nconst Label = React.forwardRef<\n React.ElementRef<typeof LabelPrimitive.Root>,\n LabelProps\n>(({\n className,\n border,\n onClick,\n ...props\n }, ref) => (\n <LabelPrimitive.Root\n ref={ref}\n onClick={onClick}\n className={cls(\"text-sm font-medium peer-disabled:cursor-not-allowed\",\n border && \"border border-hairline-strong rounded-md px-3 py-1.5\",\n onClick && \"hover:cursor-pointer hover:bg-surface-hover\",\n defaultBorderMixin, className)}\n {...props}\n />\n))\nLabel.displayName = LabelPrimitive.Root.displayName\n\nexport { Label }\n"],"mappings":";;;;;;;AAUA,IAAM,QAAQ,QAAM,YAGjB,EACI,WACA,QACA,SACA,GAAG,SACJ,QACF,oBAAC,eAAe,MAAhB;CACS;CACI;CACT,WAAW,IAAI,wDACX,UAAU,wDACV,WAAW,+CACX,oBAAoB,SAAS;CACjC,GAAI;AACP,CAAA,CACJ;AACD,MAAM,cAAc,eAAe,KAAK"}
@@ -0,0 +1,21 @@
1
+ import { Button } from "./Button.es.js";
2
+ import { CircularProgress } from "./CircularProgress.es.js";
3
+ import "react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ //#region src/components/LoadingButton.tsx
6
+ function LoadingButton({ children, loading, startIcon, ...props }) {
7
+ const buttonProps = props;
8
+ return /* @__PURE__ */ jsxs(Button, {
9
+ ...buttonProps,
10
+ disabled: loading || buttonProps.disabled,
11
+ children: [
12
+ loading && /* @__PURE__ */ jsx(CircularProgress, { size: "smallest" }),
13
+ !loading && startIcon,
14
+ children
15
+ ]
16
+ });
17
+ }
18
+ //#endregion
19
+ export { LoadingButton };
20
+
21
+ //# sourceMappingURL=LoadingButton.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoadingButton.es.js","names":[],"sources":["../../src/components/LoadingButton.tsx"],"sourcesContent":["import React from \"react\";\nimport { Button, ButtonProps } from \"./Button\";\nimport { CircularProgress } from \"./CircularProgress\";\n\nexport type LoadingButtonProps<P extends React.ElementType = \"button\"> = ButtonProps<P> & {\n startIcon?: React.ReactNode;\n loading?: boolean;\n}\n\nexport function LoadingButton<P extends React.ElementType = \"button\">({\n children,\n loading,\n startIcon,\n ...props\n }: LoadingButtonProps<P>) {\n // What is left is exactly the Button's props for the same element. The\n // compiler cannot see through `Omit` over a generic element type, so it is\n // told once, here, rather than every caller being typed as `any`.\n const buttonProps = props as ButtonProps<P>;\n return (\n <Button<P>\n {...buttonProps}\n disabled={loading || buttonProps.disabled}\n >\n {loading && (\n <CircularProgress size={\"smallest\"}/>\n )}\n {!loading && startIcon}\n {children}\n </Button>\n );\n};\n"],"mappings":";;;;;AASA,SAAgB,cAAsD,EACI,UACA,SACA,WACA,GAAG,SACmB;CAI5F,MAAM,cAAc;CACpB,OACI,qBAAC,QAAD;EACI,GAAI;EACJ,UAAU,WAAW,YAAY;YAFrC;GAIK,WACG,oBAAC,kBAAD,EAAkB,MAAM,WAAY,CAAA;GAEvC,CAAC,WAAW;GACZ;EACG;;AAEhB"}