@scalepad/ui 0.1.0

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 (273) hide show
  1. package/.ai/rules/date-handling.md +39 -0
  2. package/.ai/rules/figma-design-system.md +372 -0
  3. package/.ai/rules/figma-lm-design-system-keys.md +680 -0
  4. package/.ai/rules/file-extensions.md +13 -0
  5. package/.ai/rules/modal-confirmation-mutation.md +56 -0
  6. package/.ai/rules/react-hooks.md +29 -0
  7. package/.ai/rules/styling.md +83 -0
  8. package/AGENTS.md +37 -0
  9. package/README.md +125 -0
  10. package/figma.config.json +9 -0
  11. package/package.json +127 -0
  12. package/scripts/install-ai-rules.mjs +136 -0
  13. package/src/ThemeProvider.tsx +57 -0
  14. package/src/charts.ts +32 -0
  15. package/src/components/ActionCard/ActionCard.css.ts +60 -0
  16. package/src/components/ActionCard/ActionCard.tsx +154 -0
  17. package/src/components/ActionCard/index.ts +2 -0
  18. package/src/components/Anchor/Anchor.tsx +47 -0
  19. package/src/components/Anchor/index.ts +2 -0
  20. package/src/components/AppliedFiltersManagerBar/AppliedFiltersManagerBar.tsx +105 -0
  21. package/src/components/AppliedFiltersManagerBar/FilterBadge.css.ts +23 -0
  22. package/src/components/AppliedFiltersManagerBar/FilterBadge.tsx +50 -0
  23. package/src/components/AppliedFiltersManagerBar/index.ts +5 -0
  24. package/src/components/Badge/Badge.css.ts +72 -0
  25. package/src/components/Badge/Badge.figma.tsx +43 -0
  26. package/src/components/Badge/Badge.tsx +159 -0
  27. package/src/components/Badge/index.ts +2 -0
  28. package/src/components/BreadCrumb/BreadCrumb.tsx +62 -0
  29. package/src/components/BreadCrumb/index.ts +2 -0
  30. package/src/components/BulkActionBar/BulkActionBar.css.ts +26 -0
  31. package/src/components/BulkActionBar/BulkActionBar.tsx +164 -0
  32. package/src/components/BulkActionBar/index.ts +2 -0
  33. package/src/components/Button/Button.css.ts +272 -0
  34. package/src/components/Button/Button.figma.tsx +74 -0
  35. package/src/components/Button/Button.tsx +84 -0
  36. package/src/components/Button/index.ts +2 -0
  37. package/src/components/Charts/ChartTooltip.figma.tsx +33 -0
  38. package/src/components/Charts/ChartTooltip.tsx +101 -0
  39. package/src/components/Charts/MiniBarSparkline.tsx +75 -0
  40. package/src/components/Charts/StackedPatternBarChart.tsx +494 -0
  41. package/src/components/Charts/TrendAreaChart.css.ts +23 -0
  42. package/src/components/Charts/TrendAreaChart.tsx +210 -0
  43. package/src/components/Charts/index.ts +12 -0
  44. package/src/components/CodePanel/CodePanel.css.ts +113 -0
  45. package/src/components/CodePanel/CodePanel.tsx +121 -0
  46. package/src/components/CodePanel/index.ts +2 -0
  47. package/src/components/CommentComposer/CommentComposer.css.ts +60 -0
  48. package/src/components/CommentComposer/CommentComposer.tsx +181 -0
  49. package/src/components/CommentComposer/index.ts +2 -0
  50. package/src/components/ConfirmationModal/ConfirmationModal.tsx +149 -0
  51. package/src/components/ConfirmationModal/index.ts +2 -0
  52. package/src/components/ConfirmationTooltip/ConfirmationTooltip.tsx +132 -0
  53. package/src/components/ConfirmationTooltip/index.ts +2 -0
  54. package/src/components/DataDialog.figma.tsx +33 -0
  55. package/src/components/DataDialog.tsx +46 -0
  56. package/src/components/DataTable/DataTable.tsx +1042 -0
  57. package/src/components/DataTable/RowExpandToggle.tsx +105 -0
  58. package/src/components/DataTable/RowGroupHeader.tsx +190 -0
  59. package/src/components/DataTable/createActionsColumn.tsx +86 -0
  60. package/src/components/DataTable/index.ts +25 -0
  61. package/src/components/DatePicker/CustomRangePicker.tsx +59 -0
  62. package/src/components/DatePicker/DateInput.tsx +329 -0
  63. package/src/components/DatePicker/DateNavigator.tsx +486 -0
  64. package/src/components/DatePicker/DatePicker.tsx +242 -0
  65. package/src/components/DatePicker/MonthlyRangePicker.tsx +231 -0
  66. package/src/components/DatePicker/QuarterlyRangePicker.tsx +224 -0
  67. package/src/components/DatePicker/QuickPicksSidebar.tsx +242 -0
  68. package/src/components/DatePicker/YearlyRangePicker.tsx +171 -0
  69. package/src/components/DatePicker/index.ts +7 -0
  70. package/src/components/DatePicker/types.ts +12 -0
  71. package/src/components/DesignSystemPrimitives/FluidGrid.tsx +44 -0
  72. package/src/components/DesignSystemPrimitives/InteractivePrimitives.tsx +177 -0
  73. package/src/components/DesignSystemPrimitives/LayoutPrimitives.tsx +220 -0
  74. package/src/components/DesignSystemPrimitives/LayoutPrimitives.types.tsx +15 -0
  75. package/src/components/DesignSystemPrimitives/SurfacePrimitives.tsx +46 -0
  76. package/src/components/DesignSystemPrimitives/index.ts +55 -0
  77. package/src/components/Details/Details.css.ts +74 -0
  78. package/src/components/Details/Details.tsx +140 -0
  79. package/src/components/Details/index.ts +2 -0
  80. package/src/components/DownloadCard/DownloadCard.css.ts +22 -0
  81. package/src/components/DownloadCard/DownloadCard.tsx +63 -0
  82. package/src/components/DownloadCard/index.ts +2 -0
  83. package/src/components/Drawer/Drawer.css.ts +32 -0
  84. package/src/components/Drawer/Drawer.tsx +236 -0
  85. package/src/components/Drawer/hooks/useDetailDrawer.ts +61 -0
  86. package/src/components/Drawer/hooks/useDetailDrawerNavigation.ts +125 -0
  87. package/src/components/Drawer/hooks/useDetailDrawerNavigationContext.ts +66 -0
  88. package/src/components/EditableRichText/EditableRichText.css.ts +72 -0
  89. package/src/components/EditableRichText/EditableRichText.tsx +324 -0
  90. package/src/components/EditableRichText/index.ts +2 -0
  91. package/src/components/EditableSelect/EditableSelect.css.ts +62 -0
  92. package/src/components/EditableSelect/EditableSelect.tsx +224 -0
  93. package/src/components/EditableSelect/index.ts +2 -0
  94. package/src/components/EditableText/EditableText.tsx +377 -0
  95. package/src/components/EditableText/index.ts +2 -0
  96. package/src/components/EmptyState/EmptyState.figma.tsx +33 -0
  97. package/src/components/EmptyState/EmptyState.tsx +230 -0
  98. package/src/components/EmptyState/index.ts +2 -0
  99. package/src/components/ErrorBoundary.tsx +135 -0
  100. package/src/components/ErrorState/ErrorState.tsx +197 -0
  101. package/src/components/ErrorState/index.ts +2 -0
  102. package/src/components/FeatureCard.tsx +42 -0
  103. package/src/components/FilterMenu/FilterMenu.figma.tsx +30 -0
  104. package/src/components/FilterMenu/FilterMenu.tsx +198 -0
  105. package/src/components/FilterMenu/FilterSubMenuTypes/BooleanFilterSubmenu.tsx +46 -0
  106. package/src/components/FilterMenu/FilterSubMenuTypes/SearchableFilterSubmenu.tsx +239 -0
  107. package/src/components/FilterMenu/FilterSubMenuTypes/index.ts +8 -0
  108. package/src/components/FilterMenu/defaultFilterSchemas.ts +63 -0
  109. package/src/components/FilterMenu/helpers.ts +115 -0
  110. package/src/components/FilterMenu/index.ts +35 -0
  111. package/src/components/FilterMenu/types.ts +101 -0
  112. package/src/components/IconButton/IconButton.css.ts +272 -0
  113. package/src/components/IconButton/IconButton.figma.tsx +47 -0
  114. package/src/components/IconButton/IconButton.tsx +72 -0
  115. package/src/components/IconButton/README.md +230 -0
  116. package/src/components/IconButton/index.ts +2 -0
  117. package/src/components/InfiniteScrollSentinel.tsx +86 -0
  118. package/src/components/InfiniteScrollTrigger.tsx +78 -0
  119. package/src/components/InfoCard.figma.tsx +47 -0
  120. package/src/components/InfoCard.tsx +216 -0
  121. package/src/components/KbdHint/KbdHint.tsx +23 -0
  122. package/src/components/KbdHint/index.ts +2 -0
  123. package/src/components/LabeledField/LabeledField.tsx +21 -0
  124. package/src/components/LabeledField/index.ts +2 -0
  125. package/src/components/LookupSelect/LookupSelect.css.ts +149 -0
  126. package/src/components/LookupSelect/LookupSelect.tsx +325 -0
  127. package/src/components/LookupSelect/index.ts +2 -0
  128. package/src/components/Menu/Menu.css.ts +89 -0
  129. package/src/components/Menu/Menu.tsx +105 -0
  130. package/src/components/Menu/index.ts +2 -0
  131. package/src/components/MessageBox/MessageBox.tsx +168 -0
  132. package/src/components/MessageBox/index.ts +2 -0
  133. package/src/components/MetricDisplay/MetricDisplay.tsx +55 -0
  134. package/src/components/MetricDisplay/index.ts +1 -0
  135. package/src/components/MultiSelect/MultiSelect.tsx +278 -0
  136. package/src/components/MultiSelect/index.ts +2 -0
  137. package/src/components/Notifications/Notifications.tsx +12 -0
  138. package/src/components/Notifications/README.md +93 -0
  139. package/src/components/Notifications/index.ts +4 -0
  140. package/src/components/Notifications/showToast.tsx +100 -0
  141. package/src/components/PropertyRow/PropertyRow.tsx +96 -0
  142. package/src/components/PropertyRow/index.ts +2 -0
  143. package/src/components/RadioTile/RadioTile.tsx +253 -0
  144. package/src/components/RadioTile/index.ts +2 -0
  145. package/src/components/RichText/FormattingToolbar.css.ts +69 -0
  146. package/src/components/RichText/FormattingToolbar.tsx +112 -0
  147. package/src/components/RichText/RichTextInline.css.ts +54 -0
  148. package/src/components/RichText/RichTextInline.tsx +318 -0
  149. package/src/components/RichText/formattingCommands.ts +181 -0
  150. package/src/components/RichText/formattingTypes.ts +34 -0
  151. package/src/components/RichText/index.ts +49 -0
  152. package/src/components/RichText/richTextExtensions.ts +111 -0
  153. package/src/components/RichText/richTextHelpers.ts +65 -0
  154. package/src/components/RichText/richTextImage.ts +253 -0
  155. package/src/components/RichText/richTextImageHandlers.ts +244 -0
  156. package/src/components/RichText/richTextProse.css.ts +261 -0
  157. package/src/components/RichTextEditor/RichTextEditor.css.ts +82 -0
  158. package/src/components/RichTextEditor/RichTextEditor.tsx +204 -0
  159. package/src/components/RichTextEditor/index.ts +2 -0
  160. package/src/components/RichTextView/RichTextView.css.ts +11 -0
  161. package/src/components/RichTextView/RichTextView.tsx +114 -0
  162. package/src/components/RichTextView/index.ts +2 -0
  163. package/src/components/Schedule/Schedule.tsx +35 -0
  164. package/src/components/SchedulePicker/SchedulePicker.css.ts +42 -0
  165. package/src/components/SchedulePicker/SchedulePicker.tsx +130 -0
  166. package/src/components/SchedulePicker/index.ts +2 -0
  167. package/src/components/SearchableList/types.ts +30 -0
  168. package/src/components/SearchableSubMenu/SearchableSubMenu.css.ts +25 -0
  169. package/src/components/SearchableSubMenu/SearchableSubMenu.tsx +139 -0
  170. package/src/components/SearchableSubMenu/index.ts +2 -0
  171. package/src/components/Select/README.md +114 -0
  172. package/src/components/Select/Select.css.ts +110 -0
  173. package/src/components/Select/Select.tsx +133 -0
  174. package/src/components/Select/index.ts +2 -0
  175. package/src/components/SelectCreatable/SelectCreatable.css.ts +16 -0
  176. package/src/components/SelectCreatable/SelectCreatable.tsx +203 -0
  177. package/src/components/SelectCreatable/index.ts +2 -0
  178. package/src/components/SettingsCard/SettingsCard.tsx +98 -0
  179. package/src/components/SettingsCard/index.ts +2 -0
  180. package/src/components/Sidebar/Sidebar.css.ts +91 -0
  181. package/src/components/Sidebar/Sidebar.tsx +129 -0
  182. package/src/components/Sidebar/index.ts +5 -0
  183. package/src/components/SimpleList/SimpleList.css.ts +12 -0
  184. package/src/components/SimpleList/SimpleList.tsx +44 -0
  185. package/src/components/SimpleList/index.ts +2 -0
  186. package/src/components/SimpleTable/SimpleTable.tsx +296 -0
  187. package/src/components/SimpleTable/index.ts +2 -0
  188. package/src/components/SlashRichTextEditor/SelectionBubbleMenu.css.ts +62 -0
  189. package/src/components/SlashRichTextEditor/SelectionBubbleMenu.tsx +85 -0
  190. package/src/components/SlashRichTextEditor/SlashCommandMenu.css.ts +124 -0
  191. package/src/components/SlashRichTextEditor/SlashCommandMenu.tsx +168 -0
  192. package/src/components/SlashRichTextEditor/SlashRichTextEditor.css.ts +81 -0
  193. package/src/components/SlashRichTextEditor/SlashRichTextEditor.tsx +538 -0
  194. package/src/components/SlashRichTextEditor/SlashSuggestionExtension.ts +48 -0
  195. package/src/components/SlashRichTextEditor/index.ts +13 -0
  196. package/src/components/SlashRichTextEditor/types.ts +48 -0
  197. package/src/components/StatCard/StatCard.css.ts +70 -0
  198. package/src/components/StatCard/StatCard.tsx +201 -0
  199. package/src/components/StatCard/index.ts +1 -0
  200. package/src/components/StatusBadge/StatusBadge.tsx +70 -0
  201. package/src/components/StatusBadge/index.ts +2 -0
  202. package/src/components/StatusIndicator/StatusIndicator.tsx +67 -0
  203. package/src/components/StatusIndicator/index.ts +6 -0
  204. package/src/components/SubNavigation/SubNavigation.css.ts +72 -0
  205. package/src/components/SubNavigation/SubNavigation.tsx +104 -0
  206. package/src/components/SubNavigation/index.ts +2 -0
  207. package/src/components/SuspenseLoader.tsx +22 -0
  208. package/src/components/Table/SortableColumnHeader.tsx +99 -0
  209. package/src/components/Table/TableSkeletonRows.figma.tsx +22 -0
  210. package/src/components/Table/TableSkeletonRows.tsx +113 -0
  211. package/src/components/Table/index.ts +9 -0
  212. package/src/components/TableActionsMenu.tsx +58 -0
  213. package/src/components/TableCard.tsx +29 -0
  214. package/src/components/TableContainer/TableContainer.tsx +86 -0
  215. package/src/components/TableContainer/index.ts +2 -0
  216. package/src/components/TableControlBar/TableControlBar.tsx +156 -0
  217. package/src/components/TableControlBar/TableSelectionButton.tsx +57 -0
  218. package/src/components/TableControlBar/index.ts +13 -0
  219. package/src/components/TableControlBar/useTableControlBar.tsx +314 -0
  220. package/src/components/TableSelection/TableSelection.tsx +43 -0
  221. package/src/components/TableSelection/index.ts +5 -0
  222. package/src/components/Tabs/README.md +76 -0
  223. package/src/components/Tabs/Tabs.css.ts +54 -0
  224. package/src/components/Tabs/Tabs.figma.tsx +47 -0
  225. package/src/components/Tabs/Tabs.tsx +96 -0
  226. package/src/components/Tabs/index.ts +8 -0
  227. package/src/components/TextInput/README.md +98 -0
  228. package/src/components/TextInput/SearchTextInput.figma.tsx +22 -0
  229. package/src/components/TextInput/SearchTextInput.tsx +150 -0
  230. package/src/components/TextInput/TextInput.figma.tsx +44 -0
  231. package/src/components/TextInput/TextInput.tsx +42 -0
  232. package/src/components/TextInput/index.ts +4 -0
  233. package/src/components/ThemeSwitcher.figma.tsx +28 -0
  234. package/src/components/ThemeSwitcher.tsx +69 -0
  235. package/src/components/TrendBadge/TrendBadge.tsx +76 -0
  236. package/src/components/TrendBadge/index.ts +2 -0
  237. package/src/components/TruncatedText.tsx +115 -0
  238. package/src/components/Typography/Text.tsx +74 -0
  239. package/src/components/Typography/Title.tsx +100 -0
  240. package/src/components/Typography/index.ts +4 -0
  241. package/src/geist-fonts.ts +48 -0
  242. package/src/hooks/index.ts +31 -0
  243. package/src/hooks/useFilters.ts +152 -0
  244. package/src/hooks/useInfiniteScroll.ts +62 -0
  245. package/src/hooks/usePlatform.ts +33 -0
  246. package/src/hooks/useServerTable.ts +495 -0
  247. package/src/hooks/useTableSelection.ts +102 -0
  248. package/src/hooks/useTableSort.ts +259 -0
  249. package/src/index.ts +483 -0
  250. package/src/mantine.ts +25 -0
  251. package/src/theme/mantineVars.ts +12 -0
  252. package/src/theme/themeContract.css.ts +131 -0
  253. package/src/theme/themeVars.ts +31 -0
  254. package/src/theme.ts +168 -0
  255. package/src/tokens/color-types.ts +107 -0
  256. package/src/tokens/colors.ts +243 -0
  257. package/src/tokens/index.ts +14 -0
  258. package/src/tokens/radius.ts +17 -0
  259. package/src/tokens/semantic-colors.ts +224 -0
  260. package/src/tokens/semantic-tokens-css.ts +53 -0
  261. package/src/tokens/shadows.ts +11 -0
  262. package/src/tokens/spacing.ts +20 -0
  263. package/src/tokens/text-styles.ts +179 -0
  264. package/src/tokens/typography.ts +40 -0
  265. package/src/tokens/zIndex.ts +27 -0
  266. package/src/types/mantine-theme.d.ts +17 -0
  267. package/src/types/tanstack-table.d.ts +22 -0
  268. package/src/utils/avatar.ts +150 -0
  269. package/src/utils/chartHelpers.ts +53 -0
  270. package/src/utils/color-props.ts +77 -0
  271. package/src/utils/createDesignComponent.tsx +104 -0
  272. package/src/utils/nestFlatRows.ts +111 -0
  273. package/src/utils/withStaticComponents.ts +6 -0
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Design System Text Component
3
+ *
4
+ * Uses a single `variant` prop to control all typography styling (font size,
5
+ * weight, line height, letter spacing) from Figma text-style tokens.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * <Text variant="body1">Default body text</Text>
10
+ * <Text variant="body1.strong">Medium weight body text</Text>
11
+ * <Text variant="caption1" c="text.subdued.default">Small muted text</Text>
12
+ * <Text variant="monospaced">Code-like text</Text>
13
+ * ```
14
+ */
15
+
16
+ import {
17
+ forwardRef,
18
+ type CSSProperties,
19
+ type MouseEventHandler,
20
+ type ReactNode,
21
+ } from 'react';
22
+
23
+ import {
24
+ Text as MantineText,
25
+ type TextProps as MantineTextProps,
26
+ } from '@mantine/core';
27
+
28
+ import {
29
+ textStyleVariants,
30
+ type BodyVariant,
31
+ type TextStyleDefinition,
32
+ } from '../../tokens';
33
+ import { resolveColorToken } from '../../utils/color-props';
34
+
35
+ import type { TextColor } from '../../tokens';
36
+
37
+ /** Typography styling props that are controlled by the variant and should not be set directly */
38
+ type TypographyStyleProps = 'fw' | 'fz' | 'size' | 'lh' | 'ff' | 'lts' | 'fs';
39
+
40
+ export type TextProps = Omit<
41
+ MantineTextProps,
42
+ TypographyStyleProps | 'c' | 'children'
43
+ > & {
44
+ /** Text style variant from the design system. Defaults to 'body1'. */
45
+ variant?: BodyVariant;
46
+ /** Text color - accepts semantic text tokens or 'inherit' */
47
+ c?: TextColor | 'inherit';
48
+ children?: ReactNode;
49
+ onClick?: MouseEventHandler<HTMLDivElement>;
50
+ style?: CSSProperties;
51
+ };
52
+
53
+ export const Text = forwardRef<HTMLParagraphElement, TextProps>(
54
+ ({ variant = 'body1', c, ...rest }, ref) => {
55
+ const variantStyles: TextStyleDefinition = textStyleVariants[variant];
56
+ const resolvedC = resolveColorToken(c);
57
+
58
+ return (
59
+ <MantineText
60
+ ref={ref}
61
+ fw={variantStyles.fontWeight}
62
+ fz={variantStyles.fontSize}
63
+ lh={variantStyles.lineHeight}
64
+ lts={variantStyles.letterSpacing}
65
+ ff={variantStyles.fontFamily}
66
+ tt={variantStyles.textTransform}
67
+ c={resolvedC}
68
+ {...rest}
69
+ />
70
+ );
71
+ },
72
+ );
73
+
74
+ Text.displayName = 'Text';
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Design System Title Component
3
+ *
4
+ * Uses a single `variant` prop to control all typography styling from Figma
5
+ * text-style tokens. An optional `order` prop controls the HTML heading
6
+ * element independently from the visual style.
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * <Title variant="heading1">Page Title</Title>
11
+ * <Title variant="heading2">Section Title</Title>
12
+ * <Title variant="heading2" order={1}>Visually h2, renders as h1</Title>
13
+ * ```
14
+ */
15
+
16
+ import {
17
+ Title as MantineTitle,
18
+ type TitleProps as MantineTitleProps,
19
+ type TitleOrder,
20
+ } from '@mantine/core';
21
+
22
+ import {
23
+ textStyleVariants,
24
+ type HeadingVariant,
25
+ } from '../../tokens/text-styles';
26
+ import { resolveColorToken } from '../../utils/color-props';
27
+
28
+ import type { TextColor } from '../../tokens/color-types';
29
+
30
+ /** Typography styling props that are controlled by the variant and should not be set directly */
31
+ type TypographyStyleProps = 'fw' | 'fz' | 'size' | 'lh' | 'ff' | 'lts' | 'fs';
32
+
33
+ const variantToOrder: Record<HeadingVariant, TitleOrder> = {
34
+ heading1: 1,
35
+ heading2: 2,
36
+ heading3: 3,
37
+ heading4: 4,
38
+ heading5: 5,
39
+ };
40
+
41
+ export type TitleProps = Omit<
42
+ MantineTitleProps,
43
+ TypographyStyleProps | 'c' | 'children' | 'order'
44
+ > & {
45
+ /** Heading style variant from the design system. */
46
+ variant?: HeadingVariant;
47
+ /** HTML heading element (h1-h6). Defaults to match the variant. */
48
+ order?: TitleOrder;
49
+ /** Title color - accepts semantic text tokens or 'inherit' */
50
+ c?: TextColor | 'inherit';
51
+ children?: React.ReactNode;
52
+ };
53
+
54
+ function resolveVariant(
55
+ variant: HeadingVariant | undefined,
56
+ order: TitleOrder | undefined,
57
+ ): HeadingVariant {
58
+ if (variant) {
59
+ return variant;
60
+ }
61
+
62
+ if (order === 1) {
63
+ return 'heading1';
64
+ }
65
+ if (order === 2) {
66
+ return 'heading2';
67
+ }
68
+ if (order === 3) {
69
+ return 'heading3';
70
+ }
71
+ if (order === 4) {
72
+ return 'heading4';
73
+ }
74
+ if (order === 5) {
75
+ return 'heading5';
76
+ }
77
+
78
+ return 'heading4';
79
+ }
80
+
81
+ export function Title({ variant, order, c, ...rest }: TitleProps) {
82
+ const effectiveVariant = resolveVariant(variant, order);
83
+ const variantStyles = textStyleVariants[effectiveVariant];
84
+ const resolvedC = resolveColorToken(c);
85
+ const effectiveOrder = order ?? variantToOrder[effectiveVariant];
86
+
87
+ return (
88
+ <MantineTitle
89
+ order={effectiveOrder}
90
+ fw={variantStyles.fontWeight}
91
+ fz={variantStyles.fontSize}
92
+ lh={variantStyles.lineHeight}
93
+ lts={variantStyles.letterSpacing}
94
+ c={resolvedC}
95
+ {...rest}
96
+ />
97
+ );
98
+ }
99
+
100
+ Title.displayName = 'Title';
@@ -0,0 +1,4 @@
1
+ export { Text } from './Text';
2
+ export type { TextProps } from './Text';
3
+ export { Title } from './Title';
4
+ export type { TitleProps } from './Title';
@@ -0,0 +1,48 @@
1
+ // Import Geist font files as URLs
2
+ import geistSansItalicFont from './assets/Geist-Italic[wght].ttf?url';
3
+ import geistSansFont from './assets/Geist[wght].ttf?url';
4
+ import geistMonoItalicFont from './assets/GeistMono-Italic[wght].ttf?url';
5
+ import geistMonoFont from './assets/GeistMono[wght].ttf?url';
6
+
7
+ // Inject @font-face rules (only once)
8
+ if (
9
+ typeof document !== 'undefined' &&
10
+ !document.getElementById('geist-fonts')
11
+ ) {
12
+ const style = document.createElement('style');
13
+ style.id = 'geist-fonts';
14
+ style.textContent = `
15
+ @font-face {
16
+ font-family: 'Geist Sans';
17
+ src: url('${geistSansFont}') format('truetype');
18
+ font-weight: 100 900;
19
+ font-style: normal;
20
+ font-display: swap;
21
+ }
22
+
23
+ @font-face {
24
+ font-family: 'Geist Sans';
25
+ src: url('${geistSansItalicFont}') format('truetype');
26
+ font-weight: 100 900;
27
+ font-style: italic;
28
+ font-display: swap;
29
+ }
30
+
31
+ @font-face {
32
+ font-family: 'Geist Mono';
33
+ src: url('${geistMonoFont}') format('truetype');
34
+ font-weight: 100 900;
35
+ font-style: normal;
36
+ font-display: swap;
37
+ }
38
+
39
+ @font-face {
40
+ font-family: 'Geist Mono';
41
+ src: url('${geistMonoItalicFont}') format('truetype');
42
+ font-weight: 100 900;
43
+ font-style: italic;
44
+ font-display: swap;
45
+ }
46
+ `;
47
+ document.head.appendChild(style);
48
+ }
@@ -0,0 +1,31 @@
1
+ export { useFilters } from './useFilters';
2
+ export type { UseFiltersOptions, UseFiltersReturn } from './useFilters';
3
+ export { useDetailDrawer } from '../components/Drawer/hooks/useDetailDrawer';
4
+ export type {
5
+ DetailDrawerSearch,
6
+ UseDetailDrawerOptions,
7
+ UseDetailDrawerReturn,
8
+ } from '../components/Drawer/hooks/useDetailDrawer';
9
+ export { useDetailDrawerNavigation } from '../components/Drawer/hooks/useDetailDrawerNavigation';
10
+ export type {
11
+ UseDetailDrawerNavigationOptions,
12
+ UseDetailDrawerNavigationReturn,
13
+ } from '../components/Drawer/hooks/useDetailDrawerNavigation';
14
+ export { useDetailDrawerNavigationContext } from '../components/Drawer/hooks/useDetailDrawerNavigationContext';
15
+ export type {
16
+ DetailDrawerNavigationContext,
17
+ UseDetailDrawerNavigationContextOptions,
18
+ } from '../components/Drawer/hooks/useDetailDrawerNavigationContext';
19
+ export { useInfiniteScroll } from './useInfiniteScroll';
20
+ export type { UseInfiniteScrollOptions } from './useInfiniteScroll';
21
+ export { useServerTable } from './useServerTable';
22
+ export type {
23
+ ListResponse,
24
+ UseServerTableOptions,
25
+ UseServerTableReturn,
26
+ } from './useServerTable';
27
+ export { useTableSelection } from './useTableSelection';
28
+ export type { UseTableSelectionReturn } from './useTableSelection';
29
+ export { useTableSort } from './useTableSort';
30
+ export type { UseTableSortOptions, UseTableSortReturn } from './useTableSort';
31
+ export { usePlatform } from './usePlatform';
@@ -0,0 +1,152 @@
1
+ import { useCallback, useMemo, useState } from 'react';
2
+
3
+ import {
4
+ extractFilterValue,
5
+ updateFilterCategories,
6
+ } from '../components/FilterMenu/helpers';
7
+
8
+ import type { FilterCategory } from '../components/AppliedFiltersManagerBar/AppliedFiltersManagerBar';
9
+ import type { FilterSchema, FilterValue } from '../components/FilterMenu/types';
10
+
11
+ export interface UseFiltersOptions {
12
+ /** Array of filter schemas defining available filters */
13
+ filterSchemas: FilterSchema[];
14
+ /** Optional initial filter state */
15
+ initialFilters?: FilterCategory[];
16
+ }
17
+
18
+ export interface UseFiltersReturn {
19
+ /** Current filter state */
20
+ filters: FilterCategory[];
21
+
22
+ /** Handler to update filter state */
23
+ onChange: (filters: FilterCategory[]) => void;
24
+
25
+ /** Current filter values keyed by schema key */
26
+ filterValues: Record<string, FilterValue>;
27
+
28
+ /** Update a single filter by key */
29
+ updateFilter: (key: string, value: FilterValue) => void;
30
+
31
+ /** Update multiple filters at once */
32
+ updateFilters: (updates: Record<string, FilterValue>) => void;
33
+
34
+ /** Get current value for a specific filter */
35
+ getFilterValue: (key: string) => FilterValue;
36
+
37
+ /** Get a typed change handler for a specific schema */
38
+ getChangeHandler: (schema: FilterSchema) => (value: FilterValue) => void;
39
+
40
+ /** Clear all filters */
41
+ clearFilters: () => void;
42
+ }
43
+
44
+ /**
45
+ * Hook for managing filter state with schema-based filter definitions.
46
+ * Manages filter state internally and provides utilities for updating filters.
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * function MyComponent() {
51
+ * const { filters, onChange, clearFilters } = useFilters({
52
+ * filterSchemas: defaultFilterSchemas,
53
+ * });
54
+ *
55
+ * return (
56
+ * <>
57
+ * <FilterMenu filters={filters} onFiltersChange={onChange} />
58
+ * <AppliedFiltersManagerBar
59
+ * filterCategories={filters}
60
+ * onClearAll={clearFilters}
61
+ * />
62
+ * </>
63
+ * );
64
+ * }
65
+ * ```
66
+ */
67
+ export function useFilters({
68
+ filterSchemas,
69
+ initialFilters = [],
70
+ }: UseFiltersOptions): UseFiltersReturn {
71
+ const [filters, setFilters] = useState<FilterCategory[]>(initialFilters);
72
+
73
+ // Extract filter values from FilterCategory[] structure using schemas
74
+ const filterValues = useMemo(() => {
75
+ const values: Record<string, FilterValue> = {};
76
+ filterSchemas.forEach(schema => {
77
+ values[schema.key] = extractFilterValue(schema, filters);
78
+ });
79
+ return values;
80
+ }, [filterSchemas, filters]);
81
+
82
+ // Handler to update filter state
83
+ const onChange = useCallback((newFilters: FilterCategory[]) => {
84
+ setFilters(newFilters);
85
+ }, []);
86
+
87
+ // Update a single filter by key
88
+ const updateFilter = useCallback(
89
+ (key: string, value: FilterValue) => {
90
+ setFilters(currentFilters => {
91
+ const schema = filterSchemas.find(s => s.key === key);
92
+ if (!schema) return currentFilters;
93
+
94
+ return updateFilterCategories(
95
+ filterSchemas,
96
+ { [key]: value },
97
+ currentFilters,
98
+ );
99
+ });
100
+ },
101
+ [filterSchemas],
102
+ );
103
+
104
+ // Update multiple filters at once
105
+ const updateFilters = useCallback(
106
+ (updates: Record<string, FilterValue>) => {
107
+ setFilters(currentFilters => {
108
+ return updateFilterCategories(filterSchemas, updates, currentFilters);
109
+ });
110
+ },
111
+ [filterSchemas],
112
+ );
113
+
114
+ // Get current value for a specific filter
115
+ const getFilterValue = useCallback(
116
+ (key: string): FilterValue => {
117
+ return (
118
+ filterValues[key] ??
119
+ (filterSchemas.find(s => s.key === key)?.type === 'boolean'
120
+ ? false
121
+ : [])
122
+ );
123
+ },
124
+ [filterValues, filterSchemas],
125
+ );
126
+
127
+ // Get a typed change handler for a specific schema
128
+ const getChangeHandler = useCallback(
129
+ (schema: FilterSchema) => {
130
+ return (value: FilterValue) => {
131
+ updateFilter(schema.key, value);
132
+ };
133
+ },
134
+ [updateFilter],
135
+ );
136
+
137
+ // Clear all filters
138
+ const clearFilters = useCallback(() => {
139
+ setFilters([]);
140
+ }, []);
141
+
142
+ return {
143
+ filters,
144
+ onChange,
145
+ filterValues,
146
+ updateFilter,
147
+ updateFilters,
148
+ getFilterValue,
149
+ getChangeHandler,
150
+ clearFilters,
151
+ };
152
+ }
@@ -0,0 +1,62 @@
1
+ import { useEffect } from 'react';
2
+
3
+ import { useInView } from 'react-intersection-observer';
4
+
5
+ /**
6
+ * Options for the useInfiniteScroll hook
7
+ */
8
+ export interface UseInfiniteScrollOptions {
9
+ /** Whether there are more pages to fetch */
10
+ hasNextPage: boolean;
11
+ /** Whether the next page is currently being fetched */
12
+ isFetchingNextPage: boolean;
13
+ /** Function to call to fetch the next page */
14
+ fetchNextPage: () => void;
15
+ /** Threshold at which to trigger the intersection observer (default: 0) */
16
+ threshold?: number;
17
+ /** Root margin for the intersection observer (default: '100px') */
18
+ rootMargin?: string;
19
+ }
20
+
21
+ /**
22
+ * Custom hook for implementing infinite scroll with automatic fetching
23
+ *
24
+ * @example
25
+ * ```tsx
26
+ * const { data, fetchNextPage, hasNextPage, isFetchingNextPage } =
27
+ * useInfiniteQuery(queryOptions);
28
+ *
29
+ * const { ref } = useInfiniteScroll({
30
+ * hasNextPage,
31
+ * isFetchingNextPage,
32
+ * fetchNextPage,
33
+ * });
34
+ *
35
+ * return (
36
+ * <>
37
+ * {items.map(item => <Item key={item.id} {...item} />)}
38
+ * <div ref={ref} />
39
+ * </>
40
+ * );
41
+ * ```
42
+ */
43
+ export function useInfiniteScroll({
44
+ hasNextPage,
45
+ isFetchingNextPage,
46
+ fetchNextPage,
47
+ threshold = 0,
48
+ rootMargin = '100px',
49
+ }: UseInfiniteScrollOptions) {
50
+ const { ref, inView } = useInView({
51
+ threshold,
52
+ rootMargin,
53
+ });
54
+
55
+ useEffect(() => {
56
+ if (inView && hasNextPage && !isFetchingNextPage) {
57
+ fetchNextPage();
58
+ }
59
+ }, [inView, hasNextPage, isFetchingNextPage, fetchNextPage]);
60
+
61
+ return { ref, inView };
62
+ }
@@ -0,0 +1,33 @@
1
+ import { useMemo } from 'react';
2
+
3
+ type PlatformInfo = {
4
+ isMac: boolean;
5
+ submitModifierLabel: '⌘' | 'Ctrl';
6
+ };
7
+
8
+ function detectIsMac(): boolean {
9
+ if (typeof navigator === 'undefined') {
10
+ return false;
11
+ }
12
+
13
+ const navigatorWithUserAgentData = navigator as Navigator & {
14
+ userAgentData?: { platform?: string };
15
+ };
16
+ const userAgentDataPlatform =
17
+ navigatorWithUserAgentData.userAgentData?.platform;
18
+ const platform =
19
+ userAgentDataPlatform ?? navigator.platform ?? navigator.userAgent;
20
+
21
+ return /mac|iphone|ipad|ipod/i.test(platform);
22
+ }
23
+
24
+ export function usePlatform(): PlatformInfo {
25
+ return useMemo(() => {
26
+ const isMac = detectIsMac();
27
+
28
+ return {
29
+ isMac,
30
+ submitModifierLabel: isMac ? '⌘' : 'Ctrl',
31
+ };
32
+ }, []);
33
+ }