@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
@@ -5,11 +5,20 @@ export type TableProps = {
5
5
  style?: React.CSSProperties;
6
6
  } & React.TableHTMLAttributes<HTMLTableElement>;
7
7
  export declare const Table: React.MemoExoticComponent<({ children, className, style, ...rest }: TableProps) => React.JSX.Element>;
8
+ /**
9
+ * `"card"` (the default) paints the body and every row with the card fill —
10
+ * a table that is an object of its own. `"list"` is a list of rows on the
11
+ * sheet: no fill of its own, only the hovered row takes an alpha highlight
12
+ * (packages/ui/DESIGN.md, "a list row has NO fill of its own").
13
+ */
14
+ export type TableVariant = "card" | "list";
8
15
  export type TableBodyProps = {
9
16
  children?: React.ReactNode;
10
17
  className?: string;
18
+ /** See {@link TableVariant}. Rows inside take it unless they say otherwise. */
19
+ variant?: TableVariant;
11
20
  } & React.HTMLAttributes<HTMLTableSectionElement>;
12
- export declare const TableBody: React.MemoExoticComponent<({ children, className, ...rest }: TableBodyProps) => React.JSX.Element>;
21
+ export declare const TableBody: React.MemoExoticComponent<({ children, className, variant, ...rest }: TableBodyProps) => React.JSX.Element>;
13
22
  export type TableHeaderProps = {
14
23
  children?: React.ReactNode;
15
24
  className?: string;
@@ -18,13 +27,19 @@ export declare const TableHeader: React.MemoExoticComponent<({ children, classNa
18
27
  export type TableRowProps = {
19
28
  children?: React.ReactNode;
20
29
  className?: string;
21
- onClick?: React.MouseEventHandler<any>;
30
+ onClick?: React.MouseEventHandler<HTMLTableRowElement>;
22
31
  style?: React.CSSProperties;
32
+ /** The rendered `<tr>`, e.g. for an IntersectionObserver. */
33
+ ref?: React.Ref<HTMLTableRowElement>;
34
+ /** See {@link TableVariant}. Defaults to the enclosing {@link TableBody}'s. */
35
+ variant?: TableVariant;
23
36
  } & React.HTMLAttributes<HTMLTableRowElement>;
24
- export declare const TableRow: React.MemoExoticComponent<({ children, className, onClick, style, ...rest }: TableRowProps) => React.JSX.Element>;
37
+ export declare const TableRow: React.MemoExoticComponent<({ children, className, onClick, style, ref, variant, ...rest }: TableRowProps) => React.JSX.Element>;
25
38
  export type TableCellProps = {
26
39
  children?: React.ReactNode;
40
+ /** Render as a header cell (`th`). Implied inside {@link TableHeader}. */
27
41
  header?: boolean;
42
+ /** Defaults to `col` for a cell inside {@link TableHeader}. */
28
43
  scope?: string;
29
44
  className?: string;
30
45
  style?: React.CSSProperties;
@@ -0,0 +1,69 @@
1
+ "use client";
2
+ import { defaultBorderMixin } from "../styles.es.js";
3
+ import { cls } from "../util/cls.es.js";
4
+ import React from "react";
5
+ import { jsx } from "react/jsx-runtime";
6
+ //#region src/components/Table.tsx
7
+ var Table = React.memo(({ children, className, style, ...rest }) => /* @__PURE__ */ jsx("table", {
8
+ className: cls("text-left text-text-primary dark:text-text-primary-dark rounded-lg overflow-x-auto", className),
9
+ style,
10
+ ...rest,
11
+ children
12
+ }));
13
+ /** The variant a {@link TableBody} gives the rows inside it. */
14
+ var TableVariantContext = React.createContext("card");
15
+ var TableBody = React.memo(({ children, className, variant = "card", ...rest }) => /* @__PURE__ */ jsx("tbody", {
16
+ className: cls(variant === "card" && "bg-surface-card", "text-sm divide-y divide-hairline", className),
17
+ ...rest,
18
+ children: /* @__PURE__ */ jsx(TableVariantContext.Provider, {
19
+ value: variant,
20
+ children
21
+ })
22
+ }));
23
+ /**
24
+ * True for a cell rendered inside {@link TableHeader}, so it renders as a
25
+ * column header (`th scope="col"`) without having to pass `header`.
26
+ */
27
+ var TableHeaderContext = React.createContext(false);
28
+ var TableHeader = React.memo(({ children, className, ...rest }) => /* @__PURE__ */ jsx("thead", {
29
+ ...rest,
30
+ children: /* @__PURE__ */ jsx("tr", {
31
+ className: cls(defaultBorderMixin, "text-sm font-medium text-surface-700 dark:text-surface-accent-300", "bg-surface-sheet border-b", className),
32
+ children: /* @__PURE__ */ jsx(TableHeaderContext.Provider, {
33
+ value: true,
34
+ children
35
+ })
36
+ })
37
+ }));
38
+ var TableRow = React.memo(({ children, className, onClick, style, ref, variant, ...rest }) => {
39
+ const bodyVariant = React.useContext(TableVariantContext);
40
+ const card = (variant ?? bodyVariant) === "card";
41
+ return /* @__PURE__ */ jsx("tr", {
42
+ ref,
43
+ onClick,
44
+ style,
45
+ className: cls(card && "bg-surface-card", onClick ? cls("transition-colors duration-150 cursor-pointer", card ? "hover:bg-surface-card-hover" : "hover:bg-surface-hover") : "", className),
46
+ ...rest,
47
+ children
48
+ });
49
+ });
50
+ var TableCell = React.memo(({ children, header = false, scope, align, className, style, colspan, ...rest }) => {
51
+ const inHeader = React.useContext(TableHeaderContext);
52
+ return /* @__PURE__ */ jsx(header || inHeader ? "th" : "td", {
53
+ scope: scope ?? (inHeader ? "col" : void 0),
54
+ colSpan: colspan,
55
+ style,
56
+ className: cls("px-4 py-3 text-clip ", align === "center" ? "text-center" : align === "right" ? "text-right" : "text-left", className),
57
+ ...rest,
58
+ children
59
+ });
60
+ });
61
+ Table.displayName = "Table";
62
+ TableBody.displayName = "TableBody";
63
+ TableHeader.displayName = "TableHeader";
64
+ TableRow.displayName = "TableRow";
65
+ TableCell.displayName = "TableCell";
66
+ //#endregion
67
+ export { Table, TableBody, TableCell, TableHeader, TableRow };
68
+
69
+ //# sourceMappingURL=Table.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Table.es.js","names":[],"sources":["../../src/components/Table.tsx"],"sourcesContent":["\n\"use client\";\n\nimport React from \"react\";\nimport { defaultBorderMixin } from \"../styles\";\nimport { cls } from \"../util\";\n\nexport type TableProps = {\n children: React.ReactNode;\n className?: string;\n style?: React.CSSProperties;\n} & React.TableHTMLAttributes<HTMLTableElement>;\n\nexport const Table = React.memo(({\n children,\n className,\n style,\n ...rest\n }: TableProps) => (\n <table\n className={cls(\"text-left text-text-primary dark:text-text-primary-dark rounded-lg overflow-x-auto\", className)}\n style={style}\n {...rest}\n >\n {children}\n </table>\n));\n\n/**\n * `\"card\"` (the default) paints the body and every row with the card fill —\n * a table that is an object of its own. `\"list\"` is a list of rows on the\n * sheet: no fill of its own, only the hovered row takes an alpha highlight\n * (packages/ui/DESIGN.md, \"a list row has NO fill of its own\").\n */\nexport type TableVariant = \"card\" | \"list\";\n\n/** The variant a {@link TableBody} gives the rows inside it. */\nconst TableVariantContext = React.createContext<TableVariant>(\"card\");\n\nexport type TableBodyProps = {\n children?: React.ReactNode;\n className?: string;\n /** See {@link TableVariant}. Rows inside take it unless they say otherwise. */\n variant?: TableVariant;\n} & React.HTMLAttributes<HTMLTableSectionElement>;\n\nexport const TableBody = React.memo(({\n children,\n className,\n variant = \"card\",\n ...rest\n }: TableBodyProps) => (\n <tbody\n className={cls(variant === \"card\" && \"bg-surface-card\", \"text-sm divide-y divide-hairline\", className)}\n {...rest}\n >\n <TableVariantContext.Provider value={variant}>\n {children}\n </TableVariantContext.Provider>\n </tbody>\n));\n\nexport type TableHeaderProps = {\n children?: React.ReactNode;\n className?: string;\n} & React.HTMLAttributes<HTMLTableSectionElement>;\n\n/**\n * True for a cell rendered inside {@link TableHeader}, so it renders as a\n * column header (`th scope=\"col\"`) without having to pass `header`.\n */\nconst TableHeaderContext = React.createContext(false);\n\nexport const TableHeader = React.memo(({\n children,\n className,\n ...rest\n }: TableHeaderProps) => (\n <thead {...rest}>\n <tr\n className={cls(\n defaultBorderMixin,\n \"text-sm font-medium text-surface-700 dark:text-surface-accent-300\",\n \"bg-surface-sheet border-b\",\n className\n )}\n >\n <TableHeaderContext.Provider value={true}>\n {children}\n </TableHeaderContext.Provider>\n </tr>\n </thead>\n));\n\nexport type TableRowProps = {\n children?: React.ReactNode;\n className?: string;\n onClick?: React.MouseEventHandler<HTMLTableRowElement>;\n style?: React.CSSProperties;\n /** The rendered `<tr>`, e.g. for an IntersectionObserver. */\n ref?: React.Ref<HTMLTableRowElement>;\n /** See {@link TableVariant}. Defaults to the enclosing {@link TableBody}'s. */\n variant?: TableVariant;\n} & React.HTMLAttributes<HTMLTableRowElement>;\n\nexport const TableRow = React.memo(({\n children,\n className,\n onClick,\n style,\n ref,\n variant,\n ...rest\n }: TableRowProps) => {\n const bodyVariant = React.useContext(TableVariantContext);\n const card = (variant ?? bodyVariant) === \"card\";\n return (\n <tr\n ref={ref}\n onClick={onClick}\n style={style}\n className={cls(\n card && \"bg-surface-card\",\n onClick ? cls(\"transition-colors duration-150 cursor-pointer\", card ? \"hover:bg-surface-card-hover\" : \"hover:bg-surface-hover\") : \"\",\n className\n )}\n {...rest}\n >\n {children}\n </tr>\n );\n});\n\nexport type TableCellProps = {\n children?: React.ReactNode;\n /** Render as a header cell (`th`). Implied inside {@link TableHeader}. */\n header?: boolean;\n /** Defaults to `col` for a cell inside {@link TableHeader}. */\n scope?: string;\n className?: string;\n style?: React.CSSProperties;\n align?: \"left\" | \"center\" | \"right\";\n colspan?: number;\n} & React.HTMLAttributes<HTMLTableCellElement>;\n\nexport const TableCell = React.memo(({\n children,\n header = false,\n scope,\n align,\n className,\n style,\n colspan,\n ...rest\n }: TableCellProps) => {\n const inHeader = React.useContext(TableHeaderContext);\n const isHeader = header || inHeader;\n const Tag = isHeader ? \"th\" : \"td\";\n return (\n <Tag\n scope={scope ?? (inHeader ? \"col\" : undefined)}\n colSpan={colspan}\n style={style}\n className={cls(\n \"px-4 py-3 text-clip \",\n align === \"center\" ? \"text-center\" : (align === \"right\" ? \"text-right\" : \"text-left\"),\n className\n )}\n {...rest}\n >\n {children}\n </Tag>\n );\n});\n\nTable.displayName = \"Table\";\nTableBody.displayName = \"TableBody\";\nTableHeader.displayName = \"TableHeader\";\nTableRow.displayName = \"TableRow\";\nTableCell.displayName = \"TableCell\";\n"],"mappings":";;;;;;AAaA,IAAa,QAAQ,MAAM,MAAM,EACP,UACA,WACA,OACA,GAAG,WAEzB,oBAAC,SAAD;CACI,WAAW,IAAI,sFAAsF,SAAS;CACvG;CACP,GAAI;CAEH;AACE,CAAA,CACV;;AAWD,IAAM,sBAAsB,MAAM,cAA4B,MAAM;AASpE,IAAa,YAAY,MAAM,MAAM,EACP,UACA,WACA,UAAU,QACV,GAAG,WAE7B,oBAAC,SAAD;CACI,WAAW,IAAI,YAAY,UAAU,mBAAmB,oCAAoC,SAAS;CACrG,GAAI;WAER,oBAAC,oBAAoB,UAArB;EAA8B,OAAO;EAChC;CACyB,CAAA;AACvB,CAAA,CACV;;;;;AAWD,IAAM,qBAAqB,MAAM,cAAc,KAAK;AAEpD,IAAa,cAAc,MAAM,MAAM,EACP,UACA,WACA,GAAG,WAE/B,oBAAC,SAAD;CAAO,GAAI;WACX,oBAAC,MAAD;EACI,WAAW,IACP,oBACA,qEACA,6BACA,SACJ;YAEA,oBAAC,mBAAmB,UAApB;GAA6B,OAAO;GAC/B;EACwB,CAAA;CAC7B,CAAA;AACG,CAAA,CACV;AAaD,IAAa,WAAW,MAAM,MAAM,EACP,UACA,WACA,SACA,OACA,KACA,SACA,GAAG,WACc;CAC1C,MAAM,cAAc,MAAM,WAAW,mBAAmB;CACxD,MAAM,QAAQ,WAAW,iBAAiB;CAC1C,OACI,oBAAC,MAAD;EACS;EACI;EACF;EACP,WAAW,IACP,QAAQ,mBACR,UAAU,IAAI,iDAAiD,OAAO,gCAAgC,wBAAwB,IAAI,IAClI,SACJ;EACA,GAAI;EAEH;CACD,CAAA;AAEZ,CAAC;AAcD,IAAa,YAAY,MAAM,MAAM,EACP,UACA,SAAS,OACT,OACA,OACA,WACA,OACA,SACA,GAAG,WACe;CAC5C,MAAM,WAAW,MAAM,WAAW,kBAAkB;CAGpD,OACI,oBAHa,UAAU,WACJ,OAAO,MAE1B;EACI,OAAO,UAAU,WAAW,QAAQ,KAAA;EACpC,SAAS;EACF;EACP,WAAW,IACP,wBACA,UAAU,WAAW,gBAAiB,UAAU,UAAU,eAAe,aACzE,SACJ;EACA,GAAI;EAEH;CACA,CAAA;AAEb,CAAC;AAED,MAAM,cAAc;AACpB,UAAU,cAAc;AACxB,YAAY,cAAc;AAC1B,SAAS,cAAc;AACvB,UAAU,cAAc"}
@@ -0,0 +1,101 @@
1
+ import "../styles.es.js";
2
+ import { cls } from "../util/cls.es.js";
3
+ import { iconSize } from "../icons/Icon.es.js";
4
+ import { createContext, useContext, useEffect, useMemo, useRef, useState } from "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
7
+ import * as TabsPrimitive from "@radix-ui/react-tabs";
8
+ //#region src/components/Tabs.tsx
9
+ var TabsContext = createContext({ variant: "standard" });
10
+ function Tabs({ value, onValueChange, className, innerClassName, variant = "standard", children }) {
11
+ const scrollContainerRef = useRef(null);
12
+ const [showLeftScroll, setShowLeftScroll] = useState(false);
13
+ const [showRightScroll, setShowRightScroll] = useState(false);
14
+ const [isScrollable, setIsScrollable] = useState(false);
15
+ const checkScroll = () => {
16
+ if (scrollContainerRef.current) {
17
+ const { scrollLeft, scrollWidth, clientWidth } = scrollContainerRef.current;
18
+ setShowLeftScroll(scrollLeft > 0);
19
+ setShowRightScroll(Math.ceil(scrollLeft + clientWidth) < scrollWidth);
20
+ setIsScrollable(scrollWidth > clientWidth);
21
+ }
22
+ };
23
+ useEffect(() => {
24
+ checkScroll();
25
+ window.addEventListener("resize", checkScroll);
26
+ let observer;
27
+ if (scrollContainerRef.current) {
28
+ observer = new ResizeObserver(checkScroll);
29
+ observer.observe(scrollContainerRef.current);
30
+ if (scrollContainerRef.current.firstElementChild) observer.observe(scrollContainerRef.current.firstElementChild);
31
+ }
32
+ return () => {
33
+ window.removeEventListener("resize", checkScroll);
34
+ observer?.disconnect();
35
+ };
36
+ }, [children]);
37
+ const scroll = (direction) => {
38
+ if (scrollContainerRef.current) {
39
+ const container = scrollContainerRef.current;
40
+ const scrollAmount = Math.max(container.clientWidth / 2, 200);
41
+ const targetScroll = container.scrollLeft + (direction === "left" ? -scrollAmount : scrollAmount);
42
+ container.scrollTo({
43
+ left: targetScroll,
44
+ behavior: "smooth"
45
+ });
46
+ }
47
+ };
48
+ const contextValue = useMemo(() => ({ variant }), [variant]);
49
+ return /* @__PURE__ */ jsx(TabsContext.Provider, {
50
+ value: contextValue,
51
+ children: /* @__PURE__ */ jsxs(TabsPrimitive.Root, {
52
+ value,
53
+ onValueChange,
54
+ className: cls("relative flex flex-row items-center min-w-0 w-full", className),
55
+ children: [
56
+ isScrollable && /* @__PURE__ */ jsx("button", {
57
+ type: "button",
58
+ disabled: !showLeftScroll,
59
+ "aria-label": "Scroll tabs left",
60
+ onClick: () => scroll("left"),
61
+ className: cls("absolute left-0 top-1/2 -translate-y-1/2 z-10 flex items-center justify-center rounded-md transition-all h-8 w-6", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-surface-400", !showLeftScroll ? "pointer-events-none opacity-0" : "text-surface-600 dark:text-surface-400 hover:bg-surface-hover", "bg-surface-card border shadow-sm", "border-hairline"),
62
+ children: /* @__PURE__ */ jsx(ChevronLeftIcon, { size: iconSize.smallest })
63
+ }),
64
+ /* @__PURE__ */ jsx("div", {
65
+ ref: scrollContainerRef,
66
+ className: "flex-1 overflow-x-auto no-scrollbar min-w-0",
67
+ onScroll: checkScroll,
68
+ style: {
69
+ scrollbarWidth: "none",
70
+ msOverflowStyle: "none"
71
+ },
72
+ children: /* @__PURE__ */ jsx(TabsPrimitive.List, {
73
+ className: cls(variant === "standard" && "inline-flex h-9 items-center justify-start rounded-md bg-surface-field p-1 text-surface-600 dark:text-surface-400 gap-2", variant === "boxy" && "flex items-end h-full", variant === "pill" && "flex items-center gap-0.5", innerClassName),
74
+ children
75
+ })
76
+ }),
77
+ isScrollable && /* @__PURE__ */ jsx("button", {
78
+ type: "button",
79
+ disabled: !showRightScroll,
80
+ "aria-label": "Scroll tabs right",
81
+ onClick: () => scroll("right"),
82
+ className: cls("absolute right-0 top-1/2 -translate-y-1/2 z-10 flex items-center justify-center rounded-md transition-all h-8 w-6", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-surface-400", !showRightScroll ? "pointer-events-none opacity-0" : "text-surface-600 dark:text-surface-400 hover:bg-surface-hover", "bg-surface-card border shadow-sm", "border-hairline"),
83
+ children: /* @__PURE__ */ jsx(ChevronRightIcon, { size: iconSize.smallest })
84
+ })
85
+ ]
86
+ })
87
+ });
88
+ }
89
+ function Tab({ value, className, innerClassName, children, disabled }) {
90
+ const { variant } = useContext(TabsContext);
91
+ return /* @__PURE__ */ jsx(TabsPrimitive.Trigger, {
92
+ value,
93
+ disabled,
94
+ className: cls("inline-flex items-center justify-center whitespace-nowrap text-sm font-medium transition-all", "focus-visible:outline-none focus-visible:ring-surface-400", "disabled:pointer-events-none disabled:opacity-50", variant === "standard" && "rounded-md px-3 py-1 data-[state=active]:bg-surface-lifted data-[state=active]:text-surface-900 data-[state=active]:shadow-sm dark:data-[state=active]:text-surface-50", variant === "boxy" && cls("flex-shrink-0 flex items-center gap-1.5 px-3.5 h-9 cursor-pointer text-xs font-medium transition-colors group relative box-border", "rounded-t-lg -mb-px border border-transparent border-b-0", "data-[state=active]:bg-surface-card data-[state=active]:border-hairline", "data-[state=active]:text-text-primary dark:data-[state=active]:text-text-primary-dark", "text-text-secondary dark:text-text-secondary-dark hover:bg-surface-hover"), variant === "pill" && cls("px-2 py-0.5 rounded-md text-[10px] font-medium transition-colors", "data-[state=active]:bg-primary/10 data-[state=active]:text-primary dark:data-[state=active]:bg-primary/20 dark:data-[state=active]:text-primary", "text-text-disabled dark:text-text-disabled-dark hover:text-text-secondary dark:hover:text-text-secondary-dark"), className, variant === "standard" && innerClassName),
95
+ children
96
+ });
97
+ }
98
+ //#endregion
99
+ export { Tab, Tabs };
100
+
101
+ //# sourceMappingURL=Tabs.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Tabs.es.js","names":[],"sources":["../../src/components/Tabs.tsx"],"sourcesContent":["\nimport React, { createContext, useContext, useRef, useState, useEffect, useMemo } from \"react\";\nimport * as TabsPrimitive from \"@radix-ui/react-tabs\";\nimport { cls } from \"../util\";\nimport { defaultBorderMixin } from \"../styles\";\n\nexport type TabVariant = \"standard\" | \"boxy\" | \"pill\";\n\nconst TabsContext = createContext<{ variant: TabVariant }>({ variant: \"standard\" });\nimport { IconButton } from \"./IconButton\";\nimport { ChevronLeftIcon, ChevronRightIcon } from \"lucide-react\";\nimport { iconSize } from \"../icons/Icon\";\n\nexport type TabsProps = {\n value: string,\n children: React.ReactNode,\n innerClassName?: string,\n className?: string,\n variant?: TabVariant,\n onValueChange: (value: string) => void\n};\n\nexport function Tabs({\n value,\n onValueChange,\n className,\n innerClassName,\n variant = \"standard\",\n children\n}: TabsProps) {\n const scrollContainerRef = useRef<HTMLDivElement>(null);\n const [showLeftScroll, setShowLeftScroll] = useState(false);\n const [showRightScroll, setShowRightScroll] = useState(false);\n const [isScrollable, setIsScrollable] = useState(false);\n\n const checkScroll = () => {\n if (scrollContainerRef.current) {\n const { scrollLeft, scrollWidth, clientWidth } = scrollContainerRef.current;\n setShowLeftScroll(scrollLeft > 0);\n setShowRightScroll(Math.ceil(scrollLeft + clientWidth) < scrollWidth);\n setIsScrollable(scrollWidth > clientWidth);\n }\n };\n\n useEffect(() => {\n checkScroll();\n window.addEventListener(\"resize\", checkScroll);\n\n let observer: ResizeObserver;\n if (scrollContainerRef.current) {\n observer = new ResizeObserver(checkScroll);\n observer.observe(scrollContainerRef.current);\n if (scrollContainerRef.current.firstElementChild) {\n observer.observe(scrollContainerRef.current.firstElementChild);\n }\n }\n\n return () => {\n window.removeEventListener(\"resize\", checkScroll);\n observer?.disconnect();\n };\n }, [children]);\n\n const scroll = (direction: \"left\" | \"right\") => {\n if (scrollContainerRef.current) {\n const container = scrollContainerRef.current;\n const scrollAmount = Math.max(container.clientWidth / 2, 200);\n const targetScroll = container.scrollLeft + (direction === \"left\" ? -scrollAmount : scrollAmount);\n\n container.scrollTo({\n left: targetScroll,\n behavior: \"smooth\"\n });\n // checkScroll will be called by onScroll event\n }\n };\n\n const contextValue = useMemo(() => ({ variant }), [variant]);\n\n return <TabsContext.Provider value={contextValue}>\n <TabsPrimitive.Root\n value={value}\n onValueChange={onValueChange}\n className={cls(\"relative flex flex-row items-center min-w-0 w-full\", className)}\n >\n {isScrollable && (\n <button\n type=\"button\"\n disabled={!showLeftScroll}\n aria-label=\"Scroll tabs left\"\n onClick={() => scroll(\"left\")}\n className={cls(\n \"absolute left-0 top-1/2 -translate-y-1/2 z-10 flex items-center justify-center rounded-md transition-all h-8 w-6\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-surface-400\",\n !showLeftScroll ? \"pointer-events-none opacity-0\" : \"text-surface-600 dark:text-surface-400 hover:bg-surface-hover\",\n \"bg-surface-card border shadow-sm\", defaultBorderMixin\n )}\n >\n <ChevronLeftIcon size={iconSize.smallest}/>\n </button>\n )}\n <div\n ref={scrollContainerRef}\n className=\"flex-1 overflow-x-auto no-scrollbar min-w-0\"\n onScroll={checkScroll}\n style={{ scrollbarWidth: \"none\",\nmsOverflowStyle: \"none\" }}\n >\n <TabsPrimitive.List className={cls(\n // A segmented track is a region, not an object: an inset fill and no border.\n variant === \"standard\" && \"inline-flex h-9 items-center justify-start rounded-md bg-surface-field p-1 text-surface-600 dark:text-surface-400 gap-2\",\n // Folder tabs sit on the strip's bottom edge, so the list aligns\n // them to the end; the active tab overlaps that edge by 1px.\n variant === \"boxy\" && \"flex items-end h-full\",\n variant === \"pill\" && \"flex items-center gap-0.5\",\n innerClassName)\n }>\n {children}\n </TabsPrimitive.List>\n </div>\n {isScrollable && (\n <button\n type=\"button\"\n disabled={!showRightScroll}\n aria-label=\"Scroll tabs right\"\n onClick={() => scroll(\"right\")}\n className={cls(\n \"absolute right-0 top-1/2 -translate-y-1/2 z-10 flex items-center justify-center rounded-md transition-all h-8 w-6\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-surface-400\",\n !showRightScroll ? \"pointer-events-none opacity-0\" : \"text-surface-600 dark:text-surface-400 hover:bg-surface-hover\",\n \"bg-surface-card border shadow-sm\", defaultBorderMixin\n )}\n >\n <ChevronRightIcon size={iconSize.smallest}/>\n </button>\n )}\n </TabsPrimitive.Root>\n </TabsContext.Provider>;\n}\n\nexport type TabProps = {\n value: string,\n className?: string,\n innerClassName?: string,\n children: React.ReactNode,\n disabled?: boolean\n};\n\nexport function Tab({\n value,\n className,\n innerClassName,\n children,\n disabled\n}: TabProps) {\n const { variant } = useContext(TabsContext);\n\n return (\n <TabsPrimitive.Trigger\n value={value}\n disabled={disabled}\n className={cls(\n \"inline-flex items-center justify-center whitespace-nowrap text-sm font-medium transition-all\",\n // Colour only. The width and the inset come from the global rule:\n // the tab list scrolls horizontally, so a ring 2px out — with a\n // further 2px of offset — was clipped by the scrollport on the\n // first and last tab. `ring-offset-white` went with it; with an\n // inset ring there is no offset for it to colour.\n \"focus-visible:outline-none focus-visible:ring-surface-400\",\n \"disabled:pointer-events-none disabled:opacity-50\",\n variant === \"standard\" && \"rounded-md px-3 py-1 data-[state=active]:bg-surface-lifted data-[state=active]:text-surface-900 data-[state=active]:shadow-sm dark:data-[state=active]:text-surface-50\",\n // A folder tab. The active one is cut from the same surface as the\n // panel it opens and sits over the strip's hairline (`-mb-px`), so\n // it reads as CONNECTED to what it shows rather than underlined,\n // and the primary is not spent on it. The vertical dividers and\n // the blue underline this variant used to draw were the boxiest\n // thing on the record view; the reference separates tabs with\n // nothing but their own rounded tops.\n variant === \"boxy\" && cls(\n \"flex-shrink-0 flex items-center gap-1.5 px-3.5 h-9 cursor-pointer text-xs font-medium transition-colors group relative box-border\",\n \"rounded-t-lg -mb-px border border-transparent border-b-0\",\n \"data-[state=active]:bg-surface-card data-[state=active]:border-hairline\",\n \"data-[state=active]:text-text-primary dark:data-[state=active]:text-text-primary-dark\",\n \"text-text-secondary dark:text-text-secondary-dark hover:bg-surface-hover\"\n ),\n variant === \"pill\" && cls(\n \"px-2 py-0.5 rounded-md text-[10px] font-medium transition-colors\",\n \"data-[state=active]:bg-primary/10 data-[state=active]:text-primary dark:data-[state=active]:bg-primary/20 dark:data-[state=active]:text-primary\",\n \"text-text-disabled dark:text-text-disabled-dark hover:text-text-secondary dark:hover:text-text-secondary-dark\"\n ),\n className,\n variant === \"standard\" && innerClassName\n )}\n >\n {children}\n </TabsPrimitive.Trigger>\n );\n}\n"],"mappings":"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"}
@@ -20,10 +20,6 @@ export type TextFieldProps<T extends string | number> = {
20
20
  inputClassName?: string;
21
21
  inputStyle?: React.CSSProperties;
22
22
  inputRef?: React.ForwardedRef<any>;
23
- /**
24
- * Maximum number of rows to display.
25
- */
26
- maxRows?: number | string;
27
23
  /**
28
24
  * Minimum number of rows to display.
29
25
  * @default 1
@@ -50,10 +46,6 @@ export declare const TextField: React.ForwardRefExoticComponent<{
50
46
  inputClassName?: string;
51
47
  inputStyle?: React.CSSProperties;
52
48
  inputRef?: React.ForwardedRef<any>;
53
- /**
54
- * Maximum number of rows to display.
55
- */
56
- maxRows?: number | string;
57
49
  /**
58
50
  * Minimum number of rows to display.
59
51
  * @default 1
@@ -0,0 +1,111 @@
1
+ "use client";
2
+ import { fieldBackgroundDisabledMixin, fieldBackgroundHoverMixin, fieldBackgroundInvisibleMixin, fieldBackgroundMixin, focusedInvisibleMixin } from "../styles.es.js";
3
+ import { cls } from "../util/cls.es.js";
4
+ import { InputLabel } from "./InputLabel.es.js";
5
+ import React, { forwardRef, useEffect, useId, useRef } from "react";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ //#region src/components/TextField.tsx
8
+ var TextField = forwardRef(({ value, onChange, onFocus, onBlur, label, type = "text", multiline = false, invisible, minRows, disabled, error, endAdornment, autoFocus, placeholder, size = "large", className, style, inputClassName, inputStyle, inputRef: inputRefProp, ...inputProps }, ref) => {
9
+ const fallbackRef = useRef(null);
10
+ const inputRef = inputRefProp ?? fallbackRef;
11
+ const autoId = useId();
12
+ const inputId = inputProps.id ?? autoId;
13
+ const labelId = `${inputId}-label`;
14
+ const [focused, setFocused] = React.useState(false);
15
+ const hasValue = value !== void 0 && value !== null && value !== "";
16
+ const handleFocus = (event) => {
17
+ setFocused(true);
18
+ onFocus?.(event);
19
+ };
20
+ const handleBlur = (event) => {
21
+ setFocused(false);
22
+ onBlur?.(event);
23
+ };
24
+ useEffect(() => {
25
+ const element = inputRef && "current" in inputRef ? inputRef.current : null;
26
+ if (element && document.activeElement === element) setFocused(true);
27
+ }, []);
28
+ const handleWheel = (event) => {
29
+ if (type === "number") event.currentTarget.blur();
30
+ inputProps.onWheel?.(event);
31
+ };
32
+ const input = multiline ? /* @__PURE__ */ jsx("textarea", {
33
+ ...inputProps,
34
+ ref: inputRef,
35
+ id: inputId,
36
+ "aria-labelledby": label ? labelId : inputProps["aria-labelledby"],
37
+ "aria-invalid": error || void 0,
38
+ "aria-disabled": disabled || void 0,
39
+ disabled,
40
+ placeholder: focused || hasValue || !label ? placeholder : void 0,
41
+ autoFocus,
42
+ rows: typeof minRows === "string" ? parseInt(minRows) : minRows ?? 3,
43
+ value: value ?? "",
44
+ onChange,
45
+ onFocus: handleFocus,
46
+ onBlur: handleBlur,
47
+ style: inputStyle,
48
+ className: cls(invisible ? focusedInvisibleMixin : "", "rounded-lg resize-none w-full outline-none text-sm bg-transparent min-h-[64px] px-3", label ? "pt-8 pb-2" : "py-2", disabled && "outline-none opacity-50 text-surface-accent-600 dark:text-surface-accent-500", inputClassName)
49
+ }) : /* @__PURE__ */ jsx("input", {
50
+ ...inputProps,
51
+ ref: inputRef,
52
+ id: inputId,
53
+ "aria-labelledby": label ? labelId : inputProps["aria-labelledby"],
54
+ "aria-invalid": error || void 0,
55
+ "aria-disabled": disabled || void 0,
56
+ disabled,
57
+ style: inputStyle,
58
+ className: cls("w-full outline-none bg-transparent leading-normal px-3 text-sm", "rounded-lg", invisible ? focusedInvisibleMixin : "", {
59
+ "min-h-[28px]": size === "smallest",
60
+ "min-h-[32px]": size === "small",
61
+ "min-h-[40px]": size === "medium",
62
+ "min-h-[48px]": size === "large"
63
+ }, label ? {
64
+ smallest: "pt-4 pb-1",
65
+ small: "pt-5 pb-1",
66
+ medium: "pt-6 pb-2",
67
+ large: "pt-8 pb-2"
68
+ }[size] : size === "smallest" ? "py-0.5" : size === "small" ? "py-1" : "py-2", endAdornment ? "pr-12" : "pr-3", disabled && "outline-none opacity-65 dark:opacity-60 text-surface-accent-800 dark:text-white", inputClassName),
69
+ placeholder: focused || hasValue || !label ? placeholder : void 0,
70
+ autoFocus,
71
+ onFocus: handleFocus,
72
+ onBlur: handleBlur,
73
+ onWheel: handleWheel,
74
+ type,
75
+ value: type === "number" && Number.isNaN(value) ? "" : value ?? "",
76
+ onChange
77
+ });
78
+ return /* @__PURE__ */ jsxs("div", {
79
+ ref,
80
+ className: cls("rounded-lg relative max-w-full", invisible ? fieldBackgroundInvisibleMixin : fieldBackgroundMixin, disabled ? fieldBackgroundDisabledMixin : invisible ? "" : fieldBackgroundHoverMixin, error ? "border border-red-500 dark:border-red-600" : "", {
81
+ "min-h-[28px]": size === "smallest",
82
+ "min-h-[32px]": size === "small",
83
+ "min-h-[40px]": size === "medium",
84
+ "min-h-[48px]": size === "large"
85
+ }, className),
86
+ style,
87
+ children: [
88
+ label && /* @__PURE__ */ jsx(InputLabel, {
89
+ id: labelId,
90
+ htmlFor: inputId,
91
+ className: cls("pointer-events-none absolute", size === "large" ? "top-1" : "top-[-1px]", !error ? focused ? "text-primary dark:text-primary" : "text-text-secondary dark:text-text-secondary-dark" : "text-red-500 dark:text-red-600", disabled ? "text-text-disabled dark:text-text-disabled-dark" : ""),
92
+ shrink: hasValue || focused,
93
+ children: label
94
+ }),
95
+ input,
96
+ endAdornment && /* @__PURE__ */ jsx("div", {
97
+ className: cls("flex flex-row justify-center items-center absolute h-full right-0 top-0", {
98
+ "mr-4": size === "large",
99
+ "mr-3": size === "medium",
100
+ "mr-2": size === "small" || size === "smallest"
101
+ }),
102
+ children: endAdornment
103
+ })
104
+ ]
105
+ });
106
+ });
107
+ TextField.displayName = "TextField";
108
+ //#endregion
109
+ export { TextField };
110
+
111
+ //# sourceMappingURL=TextField.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TextField.es.js","names":[],"sources":["../../src/components/TextField.tsx"],"sourcesContent":["\"use client\";\nimport React, { ForwardedRef, forwardRef, useEffect, useId, useRef } from \"react\";\n\nimport {\n fieldBackgroundDisabledMixin,\n fieldBackgroundHoverMixin,\n fieldBackgroundInvisibleMixin,\n fieldBackgroundMixin,\n focusedInvisibleMixin\n} from \"../styles\";\nimport { InputLabel } from \"./InputLabel\";\nimport { cls } from \"../util\";\n\nexport type InputType =\n | \"text\"\n | \"number\"\n | \"phone\"\n | \"email\"\n | \"password\"\n | \"search\"\n | \"url\"\n | \"date\"\n | \"time\"\n | \"datetime-local\"\n | \"month\"\n | \"week\"\n | \"color\";\n\nexport type TextFieldProps<T extends string | number> = {\n type?: InputType;\n value?: T;\n onChange?: (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;\n onFocus?: React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;\n onBlur?: React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;\n label?: React.ReactNode;\n multiline?: boolean;\n disabled?: boolean;\n invisible?: boolean;\n error?: boolean;\n endAdornment?: React.ReactNode;\n autoFocus?: boolean;\n placeholder?: string;\n size?: \"smallest\" | \"small\" | \"medium\" | \"large\";\n className?: string;\n style?: React.CSSProperties;\n inputClassName?: string;\n inputStyle?: React.CSSProperties;\n inputRef?: React.ForwardedRef<any>;\n /**\n * Minimum number of rows to display.\n * @default 1\n */\n minRows?: number | string;\n} & Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\" | \"value\" | \"onFocus\" | \"onBlur\">;\n\nexport const TextField = forwardRef<HTMLDivElement, TextFieldProps<string | number>>(\n <T extends string | number>(\n {\n value,\n onChange,\n onFocus,\n onBlur,\n label,\n type = \"text\",\n multiline = false,\n invisible,\n minRows,\n disabled,\n error,\n endAdornment,\n autoFocus,\n placeholder,\n size = \"large\",\n className,\n style,\n inputClassName,\n inputStyle,\n inputRef: inputRefProp,\n ...inputProps\n }: TextFieldProps<T>,\n ref: ForwardedRef<HTMLDivElement>\n ) => {\n\n const fallbackRef = useRef(null);\n const inputRef = inputRefProp ?? fallbackRef;\n const autoId = useId();\n const inputId = inputProps.id ?? autoId;\n const labelId = `${inputId}-label`;\n\n const [focused, setFocused] = React.useState(false);\n const hasValue = value !== undefined && value !== null && value !== \"\";\n\n // The field tracks focus for its label, and the caller still hears about\n // it: `DebouncedTextField` flushes on blur, and a form marks a field\n // touched on blur.\n const handleFocus = (event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => {\n setFocused(true);\n onFocus?.(event);\n };\n const handleBlur = (event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => {\n setFocused(false);\n onBlur?.(event);\n };\n\n useEffect(() => {\n const element = inputRef && \"current\" in inputRef ? inputRef.current : null;\n if (element && document.activeElement === element) {\n setFocused(true);\n }\n }, []);\n\n // A focused number input steps its value on wheel, so scrolling the page\n // past one edited it. It gives up the focus instead. A React handler\n // rather than a listener on `inputRef.current`: a callback ref has no\n // `current`, and reading one crashed the render.\n const handleWheel = (event: React.WheelEvent<HTMLInputElement>) => {\n if (type === \"number\") event.currentTarget.blur();\n inputProps.onWheel?.(event);\n };\n\n const input = multiline ? (\n <textarea\n {...(inputProps as React.TextareaHTMLAttributes<HTMLTextAreaElement>)}\n ref={inputRef}\n id={inputId}\n // Falls back to the caller's own value rather than to `undefined`:\n // this sits after the spread, so hardcoding `undefined` silently\n // erased an `aria-labelledby` a consumer had passed, and the\n // unlabelled field it was meant to name stayed unnamed.\n aria-labelledby={label ? labelId : inputProps[\"aria-labelledby\"]}\n aria-invalid={error || undefined}\n aria-disabled={disabled || undefined}\n disabled={disabled}\n placeholder={focused || hasValue || !label ? placeholder : undefined}\n autoFocus={autoFocus}\n rows={typeof minRows === \"string\" ? parseInt(minRows) : (minRows ?? 3)}\n value={value ?? \"\"}\n onChange={onChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n style={inputStyle}\n className={cls(\n invisible ? focusedInvisibleMixin : \"\",\n \"rounded-lg resize-none w-full outline-none text-sm bg-transparent min-h-[64px] px-3\",\n label ? \"pt-8 pb-2\" : \"py-2\",\n disabled && \"outline-none opacity-50 text-surface-accent-600 dark:text-surface-accent-500\",\n inputClassName\n )}\n />\n ) : (\n <input\n {...inputProps}\n ref={inputRef}\n id={inputId}\n // See the textarea branch: preserve a caller-supplied\n // `aria-labelledby` instead of overwriting it with `undefined`.\n aria-labelledby={label ? labelId : inputProps[\"aria-labelledby\"]}\n aria-invalid={error || undefined}\n aria-disabled={disabled || undefined}\n disabled={disabled}\n style={inputStyle}\n className={cls(\n \"w-full outline-none bg-transparent leading-normal px-3 text-sm\",\n \"rounded-lg\",\n invisible ? focusedInvisibleMixin : \"\",\n // No fill, hover or disabled tint on the input itself: the\n // wrapper carries all three. Both used to carry the hover\n // fill, so a hovered field painted the alpha twice — once on\n // the box and once on the input a pixel inside its border,\n // at the same radius — and read as a box inside a box.\n {\n \"min-h-[28px]\": size === \"smallest\",\n \"min-h-[32px]\": size === \"small\",\n \"min-h-[40px]\": size === \"medium\",\n \"min-h-[48px]\": size === \"large\"\n },\n /* A shrunk label occupies roughly the first 16px of the\n box (`top-[-1px]`, translated down 2px, ~15px tall at\n scale-75). `pt-4` put the value's first line at exactly\n 16px, so label and content shared a row: a labelled\n `small` field with a placeholder rendered \"Name\" on top\n of \"e.g. Analytics Pipeline\". `large` was never affected\n — it reserves `pt-8`. */\n label\n // Labelled fields sit exactly 16px above the unlabelled\n // scale (44/48/56/64 against 28/32/40/48). smallest,\n // small and medium all used to share `pt-5 pb-1.5`, so\n // they rendered at an identical 50px and `size` looked\n // inert whenever a label was present.\n ? { smallest: \"pt-4 pb-1\", small: \"pt-5 pb-1\", medium: \"pt-6 pb-2\", large: \"pt-8 pb-2\" }[size]\n : size === \"smallest\"\n ? \"py-0.5\"\n : size === \"small\"\n ? \"py-1\"\n : \"py-2\",\n endAdornment ? \"pr-12\" : \"pr-3\",\n disabled &&\n \"outline-none opacity-65 dark:opacity-60 text-surface-accent-800 dark:text-white\",\n inputClassName\n )}\n placeholder={focused || hasValue || !label ? placeholder : undefined}\n autoFocus={autoFocus}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onWheel={handleWheel}\n type={type}\n value={type === \"number\" && Number.isNaN(value) ? \"\" : value ?? \"\"}\n onChange={onChange}\n />\n );\n\n return (\n <div\n ref={ref}\n className={cls(\n \"rounded-lg relative max-w-full\",\n invisible ? fieldBackgroundInvisibleMixin : fieldBackgroundMixin,\n // An invisible field has no hover fill of its own: whatever frames it (a table cell) carries the hover.\n disabled ? fieldBackgroundDisabledMixin : (invisible ? \"\" : fieldBackgroundHoverMixin),\n error ? \"border border-red-500 dark:border-red-600\" : \"\",\n {\n \"min-h-[28px]\": size === \"smallest\",\n \"min-h-[32px]\": size === \"small\",\n \"min-h-[40px]\": size === \"medium\",\n \"min-h-[48px]\": size === \"large\"\n },\n className\n )}\n style={style}\n >\n {label && (\n <InputLabel\n id={labelId}\n htmlFor={inputId}\n className={cls(\n \"pointer-events-none absolute\",\n size === \"large\" ? \"top-1\" : \"top-[-1px]\",\n !error\n ? focused\n ? \"text-primary dark:text-primary\"\n : \"text-text-secondary dark:text-text-secondary-dark\"\n : \"text-red-500 dark:text-red-600\",\n // A disabled field's LABEL is the one part that must\n // stay readable — it is what tells you which field\n // you cannot edit. `opacity-50` halved the alpha of\n // an already-muted #737373, landing near 2.2:1 over\n // the field fill; the label was effectively gone.\n //\n // The value below it keeps its own `opacity-50`,\n // which is the correct signal: the CONTENT is\n // inactive. Naming the field is not content.\n disabled ? \"text-text-disabled dark:text-text-disabled-dark\" : \"\"\n )}\n shrink={hasValue || focused}\n >\n {label}\n </InputLabel>\n )}\n\n {input}\n\n {endAdornment && (\n <div\n className={cls(\n \"flex flex-row justify-center items-center absolute h-full right-0 top-0\",\n {\n \"mr-4\": size === \"large\",\n \"mr-3\": size === \"medium\",\n \"mr-2\": size === \"small\" || size === \"smallest\"\n }\n )}\n >\n {endAdornment}\n </div>\n )}\n </div>\n );\n }\n);\n\nTextField.displayName = \"TextField\";\n"],"mappings":"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"}
@@ -0,0 +1,187 @@
1
+ "use client";
2
+ import { cls } from "../util/cls.es.js";
3
+ import { debounce } from "../util/debounce.es.js";
4
+ import * as React$1 from "react";
5
+ import { useLayoutEffect } from "react";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ import * as ReactDOM from "react-dom";
8
+ //#region src/components/TextareaAutosize.tsx
9
+ function getStyleValue(value) {
10
+ return parseInt(value, 10) || 0;
11
+ }
12
+ var styles = { shadow: {
13
+ visibility: "hidden",
14
+ position: "absolute",
15
+ overflow: "hidden",
16
+ height: 0,
17
+ top: 0,
18
+ left: 0,
19
+ transform: "translateZ(0)"
20
+ } };
21
+ function isEmpty(obj) {
22
+ return obj === void 0 || obj === null || Object.keys(obj).length === 0 || obj.outerHeightStyle === 0 && !obj.overflow;
23
+ }
24
+ var TextareaAutosize = React$1.forwardRef(function TextareaAutosize(props, ref) {
25
+ const { onChange, onScroll, onResize, maxRows, minRows = 1, style, value, onFocus, onBlur, sizeRef, ignoreBoxSizing, ...other } = props;
26
+ const { current: isControlled } = React$1.useRef(value != null);
27
+ const inputRef = React$1.useRef(null);
28
+ const handleRef = useForkRef(ref, inputRef);
29
+ const shadowRef = React$1.useRef(null);
30
+ const renders = React$1.useRef(0);
31
+ const [state, setState] = React$1.useState({ outerHeightStyle: 0 });
32
+ const getUpdatedState = React$1.useCallback(() => {
33
+ const input = inputRef.current;
34
+ if (typeof window === "undefined") return { outerHeightStyle: 0 };
35
+ const computedStyle = window.getComputedStyle(input);
36
+ if (computedStyle.width === "0px") return { outerHeightStyle: 0 };
37
+ const sizeReferenceElement = sizeRef?.current ?? shadowRef.current;
38
+ const inputShallow = shadowRef.current;
39
+ sizeReferenceElement.style.width = computedStyle.width;
40
+ inputShallow.value = input.value || props.placeholder || "x";
41
+ if (inputShallow.value.slice(-1) === "\n") inputShallow.value += " ";
42
+ const boxSizing = computedStyle.boxSizing;
43
+ const padding = getStyleValue(computedStyle.paddingBottom) + getStyleValue(computedStyle.paddingTop);
44
+ const border = getStyleValue(computedStyle.borderBottomWidth) + getStyleValue(computedStyle.borderTopWidth);
45
+ const minHeight = getStyleValue(computedStyle.minHeight);
46
+ const innerHeight = sizeReferenceElement.scrollHeight;
47
+ inputShallow.value = "x";
48
+ const singleRowHeight = sizeReferenceElement.scrollHeight;
49
+ let outerHeight = innerHeight;
50
+ if (minRows) outerHeight = Math.max(Number(minRows) * singleRowHeight, outerHeight);
51
+ if (maxRows) outerHeight = Math.min(Number(maxRows) * singleRowHeight, outerHeight);
52
+ outerHeight = Math.max(outerHeight, singleRowHeight, minHeight);
53
+ return {
54
+ outerHeightStyle: outerHeight + (!ignoreBoxSizing && boxSizing === "border-box" ? padding + border : 0),
55
+ overflow: Math.abs(outerHeight - innerHeight) <= 1
56
+ };
57
+ }, [
58
+ maxRows,
59
+ minRows,
60
+ props.placeholder
61
+ ]);
62
+ const updateState = React$1.useCallback((prevState, newState) => {
63
+ const { outerHeightStyle, overflow } = newState;
64
+ if (renders.current < 20 && (outerHeightStyle > 0 && Math.abs((prevState.outerHeightStyle || 0) - outerHeightStyle) > 1 || prevState.overflow !== overflow)) {
65
+ renders.current += 1;
66
+ return {
67
+ overflow,
68
+ outerHeightStyle
69
+ };
70
+ }
71
+ if (process.env.NODE_ENV !== "production") {
72
+ if (renders.current === 20) console.error(["MUI: Too many re-renders. The layout is unstable.", "TextareaAutosize limits the number of renders to prevent an infinite loop."].join("\n"));
73
+ }
74
+ return prevState;
75
+ }, []);
76
+ const syncHeight = React$1.useCallback(() => {
77
+ const newState = getUpdatedState();
78
+ if (isEmpty(newState)) return;
79
+ if (onResize) onResize(newState);
80
+ setState((prevState) => {
81
+ return updateState(prevState, newState);
82
+ });
83
+ }, [
84
+ getUpdatedState,
85
+ onResize,
86
+ updateState
87
+ ]);
88
+ const syncHeightWithFlushSync = React$1.useCallback(() => {
89
+ const newState = getUpdatedState();
90
+ if (isEmpty(newState)) return;
91
+ ReactDOM.flushSync(() => {
92
+ setState((prevState) => {
93
+ return updateState(prevState, newState);
94
+ });
95
+ });
96
+ }, [getUpdatedState, updateState]);
97
+ React$1.useEffect(() => {
98
+ const handleResize = debounce(() => {
99
+ renders.current = 0;
100
+ if (inputRef.current) syncHeightWithFlushSync();
101
+ });
102
+ let resizeObserver;
103
+ const input = inputRef.current;
104
+ const containerWindow = window;
105
+ if (typeof window === "undefined") return;
106
+ containerWindow.addEventListener("resize", handleResize);
107
+ if (typeof ResizeObserver !== "undefined") {
108
+ resizeObserver = new ResizeObserver(handleResize);
109
+ resizeObserver.observe(input);
110
+ }
111
+ return () => {
112
+ handleResize.clear();
113
+ containerWindow.removeEventListener("resize", handleResize);
114
+ if (resizeObserver) resizeObserver.disconnect();
115
+ };
116
+ }, [syncHeightWithFlushSync]);
117
+ const styleKey = style ? JSON.stringify(style) : "";
118
+ useLayoutEffect(() => {
119
+ syncHeight();
120
+ }, [
121
+ syncHeight,
122
+ value,
123
+ props.className,
124
+ props.shadowClassName,
125
+ styleKey,
126
+ sizeRef,
127
+ ignoreBoxSizing
128
+ ]);
129
+ React$1.useEffect(() => {
130
+ renders.current = 0;
131
+ }, [value]);
132
+ const handleChange = (event) => {
133
+ renders.current = 0;
134
+ if (!isControlled) syncHeight();
135
+ if (onChange) onChange(event);
136
+ };
137
+ return /* @__PURE__ */ jsxs(React$1.Fragment, { children: [/* @__PURE__ */ jsx("textarea", {
138
+ value,
139
+ onChange: handleChange,
140
+ className: props.className,
141
+ ref: handleRef,
142
+ onFocus,
143
+ onBlur,
144
+ rows: minRows,
145
+ style: {
146
+ height: state.outerHeightStyle,
147
+ overflow: state.overflow ? "hidden" : void 0,
148
+ ...style
149
+ },
150
+ onScroll,
151
+ ...other
152
+ }), /* @__PURE__ */ jsx("textarea", {
153
+ "aria-hidden": true,
154
+ className: cls(props.className, props.shadowClassName),
155
+ readOnly: true,
156
+ ref: shadowRef,
157
+ tabIndex: -1,
158
+ style: {
159
+ padding: 0,
160
+ ...styles.shadow,
161
+ ...style
162
+ }
163
+ })] });
164
+ });
165
+ function useForkRef(...refs) {
166
+ /**
167
+ * This will create a new function if the refs passed to this hook change and are all defined.
168
+ * This means react will call the old forkRef with `null` and the new forkRef
169
+ * with the ref. Cleanup naturally emerges from this behavior.
170
+ */
171
+ return React$1.useMemo(() => {
172
+ if (refs.every((ref) => ref == null)) return null;
173
+ return (instance) => {
174
+ refs.forEach((ref) => {
175
+ setRef(ref, instance);
176
+ });
177
+ };
178
+ }, refs);
179
+ }
180
+ function setRef(ref, value) {
181
+ if (typeof ref === "function") ref(value);
182
+ else if (ref) ref.current = value;
183
+ }
184
+ //#endregion
185
+ export { TextareaAutosize };
186
+
187
+ //# sourceMappingURL=TextareaAutosize.es.js.map