@ravileal/ui 0.0.0-stage → 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 (56) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +241 -2
  3. package/dist/components/Alert.d.ts +14 -0
  4. package/dist/components/Avatar.d.ts +11 -0
  5. package/dist/components/Badge.d.ts +23 -0
  6. package/dist/components/Button.d.ts +20 -0
  7. package/dist/components/Card.d.ts +36 -0
  8. package/dist/components/Checkbox.d.ts +7 -0
  9. package/dist/components/ColorPicker.d.ts +33 -0
  10. package/dist/components/Combobox.d.ts +23 -0
  11. package/dist/components/ConfirmModal.d.ts +14 -0
  12. package/dist/components/CopyValue.d.ts +31 -0
  13. package/dist/components/DataTable.d.ts +27 -0
  14. package/dist/components/DatePicker.d.ts +33 -0
  15. package/dist/components/Drawer.d.ts +16 -0
  16. package/dist/components/Dropdown.d.ts +51 -0
  17. package/dist/components/DropdownMenu.d.ts +26 -0
  18. package/dist/components/EmptyState.d.ts +10 -0
  19. package/dist/components/FileUpload.d.ts +14 -0
  20. package/dist/components/FormField.d.ts +24 -0
  21. package/dist/components/InlineEditorCard.d.ts +19 -0
  22. package/dist/components/ListScreen.d.ts +48 -0
  23. package/dist/components/Modal.d.ts +22 -0
  24. package/dist/components/MonthSelector.d.ts +24 -0
  25. package/dist/components/NumberStepper.d.ts +16 -0
  26. package/dist/components/PageHeader.d.ts +11 -0
  27. package/dist/components/Portal.d.ts +11 -0
  28. package/dist/components/ProgressBar.d.ts +13 -0
  29. package/dist/components/Radio.d.ts +5 -0
  30. package/dist/components/RowActions.d.ts +17 -0
  31. package/dist/components/ScreenSkeleton.d.ts +26 -0
  32. package/dist/components/SearchInput.d.ts +13 -0
  33. package/dist/components/SegmentedControl.d.ts +16 -0
  34. package/dist/components/Skeleton.d.ts +14 -0
  35. package/dist/components/Slider.d.ts +17 -0
  36. package/dist/components/Spinner.d.ts +8 -0
  37. package/dist/components/Switch.d.ts +15 -0
  38. package/dist/components/Tabs.d.ts +15 -0
  39. package/dist/components/TextInput.d.ts +13 -0
  40. package/dist/components/Textarea.d.ts +6 -0
  41. package/dist/components/Toast.d.ts +21 -0
  42. package/dist/components/Tooltip.d.ts +22 -0
  43. package/dist/components/VisuallyHidden.d.ts +6 -0
  44. package/dist/index.d.ts +82 -0
  45. package/dist/index.js +3253 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/internal/ScreenCaptureOverlay.d.ts +16 -0
  48. package/dist/internal/clipboard.d.ts +11 -0
  49. package/dist/internal/color.utils.d.ts +21 -0
  50. package/dist/internal/screen-color-picker.d.ts +12 -0
  51. package/dist/internal/tone.d.ts +1 -0
  52. package/dist/internal/useFocusTrap.d.ts +7 -0
  53. package/dist/internal/useIsomorphicLayoutEffect.d.ts +6 -0
  54. package/dist/internal/usePopover.d.ts +30 -0
  55. package/dist/styles.css +1702 -0
  56. package/package.json +105 -4
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2026 Ravi Leal
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,242 @@
1
- # Temporary Holding Version
1
+ # @ravileal/ui
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Reusable React UI primitives with a themeable CSS-variable design system.
4
+
5
+ - Repository: https://github.com/ravileal/ui
6
+ - Storybook: https://ravileal.github.io/ui/
7
+
8
+ The library is intentionally small and domain-agnostic. It contains the
9
+ presentational primitives used by `couple-finance` and other personal React
10
+ projects. Finance-specific screens and components stay in their application.
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ pnpm add @ravileal/ui
16
+ # or
17
+ npm install @ravileal/ui
18
+ ```
19
+
20
+ React and React DOM are peer dependencies:
21
+
22
+ ```bash
23
+ pnpm add react react-dom
24
+ ```
25
+
26
+ ## Styles
27
+
28
+ Import the stylesheet once in your application entry point (or in the root
29
+ layout for Next.js):
30
+
31
+ ```ts
32
+ import '@ravileal/ui/styles.css';
33
+ ```
34
+
35
+ The stylesheet is wrapped in `@layer ravileal-ui` and does not ship a global
36
+ reset or a font. Add your own reset/typography if needed.
37
+
38
+ ## Theme
39
+
40
+ All tokens are namespaced with `--ui-*` to avoid collisions:
41
+
42
+ ```css
43
+ :root {
44
+ --ui-bg: #0b1422;
45
+ --ui-surface: #101c2e;
46
+ --ui-surface-2: #17273a;
47
+ --ui-border: #24384f;
48
+ --ui-text: #eaf0f8;
49
+ --ui-text-2: #9fb4cd;
50
+ --ui-text-3: #7b93b0;
51
+ --ui-accent: #00c9a7;
52
+ --ui-blue: #4f7cff;
53
+ --ui-green: #22c55e;
54
+ --ui-red: #f87171;
55
+ --ui-amber: #f59e0b;
56
+ --ui-purple: #a855f7;
57
+ --ui-shadow: 0 4px 24px rgba(0, 0, 0, 0.5);
58
+ --ui-shadow-lg: 0 16px 48px rgba(0, 0, 0, 0.5);
59
+ --ui-overlay: rgba(0, 0, 0, 0.6);
60
+ --ui-on-accent: #ffffff;
61
+ }
62
+ ```
63
+
64
+ Override any token on `:root`, a container, or a theme selector. The library
65
+ ships light defaults under `[data-ui-theme='light']` and `.ui-theme-light`:
66
+
67
+ ```tsx
68
+ <html data-ui-theme="light">
69
+ ```
70
+
71
+ ## Usage
72
+
73
+ ```tsx
74
+ import { useState } from 'react';
75
+ import { Dropdown, Modal } from '@ravileal/ui';
76
+ import '@ravileal/ui/styles.css';
77
+
78
+ export function Example() {
79
+ const [open, setOpen] = useState(false);
80
+ const [value, setValue] = useState('food');
81
+
82
+ return (
83
+ <>
84
+ <Dropdown
85
+ ariaLabel="Category"
86
+ value={value}
87
+ onChange={setValue}
88
+ options={[
89
+ { value: 'food', label: 'Food', color: '#00c9a7' },
90
+ { value: 'home', label: 'Home', color: '#4f7cff' },
91
+ ]}
92
+ />
93
+ <button type="button" onClick={() => setOpen(true)}>
94
+ Open
95
+ </button>
96
+ <Modal open={open} title="Settings" onClose={() => setOpen(false)}>
97
+ Content
98
+ </Modal>
99
+ </>
100
+ );
101
+ }
102
+ ```
103
+
104
+ ## Components
105
+
106
+ **Actions and feedback**
107
+
108
+ - `Button`, `IconButton`
109
+ - `Spinner`, `ProgressBar`
110
+ - `Alert`
111
+ - `Badge`, `Chip`
112
+ - `ToastProvider`, `useToast`
113
+
114
+ **Forms**
115
+
116
+ - `TextInput`, `Textarea`
117
+ - `FormField`
118
+ - `Switch`
119
+ - `Slider`
120
+ - `SearchInput`
121
+ - `Checkbox`, `Radio`
122
+ - `NumberStepper`
123
+ - `Dropdown`
124
+ - `Combobox`
125
+ - `DatePicker`
126
+ - `MonthSelector`
127
+ - `ColorPicker`
128
+
129
+ **Layout and navigation**
130
+
131
+ - `Card`, `CardHeader`, `CardBody`, `CardFooter`, `Section`
132
+ - `EmptyState`
133
+ - `PageHeader`
134
+ - `ListScreen`, `ListCard`, `ListRow`, `ListSearch`, `ListEmptyState`
135
+ - `Tabs`, `SegmentedControl`
136
+ - `DropdownMenu` (also exported as `Menu`)
137
+ - `Drawer` (also exported as `Sheet`)
138
+ - `DataTable`
139
+ - `FileUpload` (also exported as `Dropzone`)
140
+
141
+ **Overlays and utilities**
142
+
143
+ - `Modal`, `ConfirmModal`
144
+ - `Tooltip`
145
+ - `Avatar`
146
+ - `CopyValue`
147
+ - `InlineEditorCard`
148
+ - `RowActions`
149
+ - `Skeleton`, `SkeletonStatus`, `PageSkeleton`, `PageHeaderSkeleton`, `SearchSkeleton`, `ListCardSkeleton`, `DetailRowsSkeleton`
150
+ - `Portal`
151
+ - `VisuallyHidden`
152
+
153
+ Every component exports its prop types. `CopyValue` accepts `formatValue` and
154
+ `copyValue` so the consumer owns currency/locale formatting. `MonthSelector`
155
+ accepts its month list as `options`. `DatePicker` accepts `locale`, weekday
156
+ labels and navigation labels. `ColorPicker` accepts a `labels` object.
157
+ `Button` accepts `variant` (`primary`, `secondary`, `ghost`, `danger`), `size`
158
+ and `loading`.
159
+
160
+ ```tsx
161
+ import { useState } from 'react';
162
+ import { Button, FormField, Switch, TextInput, ToastProvider, useToast } from '@ravileal/ui';
163
+
164
+ function SettingsForm() {
165
+ const [checked, setChecked] = useState(true);
166
+ const { showToast } = useToast();
167
+
168
+ return (
169
+ <div style={{ display: 'grid', gap: 16 }}>
170
+ <FormField label="Partner name" hint="Shown in reports" required>
171
+ <TextInput />
172
+ </FormField>
173
+ <Switch checked={checked} onChange={setChecked} label="Monthly summary" />
174
+ <Button onClick={() => showToast({ title: 'Saved', tone: 'success' })}>Save</Button>
175
+ </div>
176
+ );
177
+ }
178
+
179
+ export function Settings() {
180
+ return (
181
+ <ToastProvider>
182
+ <SettingsForm />
183
+ </ToastProvider>
184
+ );
185
+ }
186
+ ```
187
+
188
+ ## Next.js
189
+
190
+ The package entry is a client boundary (`"use client"`). Import the stylesheet
191
+ in the root layout:
192
+
193
+ ```tsx
194
+ // app/layout.tsx
195
+ import '@ravileal/ui/styles.css';
196
+ ```
197
+
198
+ The components render safely with `ReactDOMServer`; browser-only features
199
+ (portals, eyedropper, clipboard) are initialized after mount or inside event
200
+ handlers.
201
+
202
+ ## Local development with `couple-finance`
203
+
204
+ In this repository:
205
+
206
+ ```bash
207
+ pnpm build
208
+ pnpm link --global
209
+ ```
210
+
211
+ In the consuming project:
212
+
213
+ ```bash
214
+ pnpm link --global @ravileal/ui
215
+ ```
216
+
217
+ Remove the link before committing and use the published semver range. Keep
218
+ React as a peer dependency to avoid duplicate React copies.
219
+
220
+ ## Release
221
+
222
+ Releases use semantic-release based on
223
+ [`ravileal/semantic-release`](https://github.com/ravileal/semantic-release).
224
+ The release workflow is initially manual (`workflow_dispatch`) so it cannot fail
225
+ before the npm automation token exists. Add the `NPM_TOKEN` repository secret,
226
+ publish the first `0.1.0` and tag `release-0.1.0`, then enable the `push` trigger
227
+ on `main` in `.github/workflows/release.yml`.
228
+
229
+ The semantic-release config uses the `release-${version}` tag format in
230
+ production, matching the reference template.
231
+
232
+ ## Development
233
+
234
+ ```bash
235
+ pnpm install
236
+ pnpm lint
237
+ pnpm typecheck
238
+ pnpm test
239
+ pnpm build
240
+ pnpm storybook
241
+ pnpm build-storybook
242
+ ```
@@ -0,0 +1,14 @@
1
+ import { CSSProperties, ReactNode } from 'react';
2
+ import { Tone } from '../internal/tone';
3
+ export interface AlertProps {
4
+ children: ReactNode;
5
+ tone?: Exclude<Tone, 'accent' | 'purple'>;
6
+ title?: ReactNode;
7
+ action?: ReactNode;
8
+ onDismiss?: () => void;
9
+ dismissLabel?: string;
10
+ role?: 'alert' | 'status';
11
+ className?: string;
12
+ style?: CSSProperties;
13
+ }
14
+ export default function Alert({ children, tone, title, action, onDismiss, dismissLabel, role, className, style, }: AlertProps): import('react').JSX.Element;
@@ -0,0 +1,11 @@
1
+ import { CSSProperties } from 'react';
2
+ export interface AvatarProps {
3
+ name: string;
4
+ color: string;
5
+ size?: number;
6
+ className?: string;
7
+ style?: CSSProperties;
8
+ /** Accessible name. Defaults to `name`; pass an empty string to hide it. */
9
+ ariaLabel?: string;
10
+ }
11
+ export default function Avatar({ name, color, size, className, style, ariaLabel, }: AvatarProps): import('react').JSX.Element;
@@ -0,0 +1,23 @@
1
+ import { CSSProperties, ReactNode } from 'react';
2
+ import { Tone } from '../internal/tone';
3
+ export type BadgeVariant = 'soft' | 'solid' | 'outline';
4
+ export interface BadgeProps {
5
+ children: ReactNode;
6
+ tone?: Tone;
7
+ variant?: BadgeVariant;
8
+ dot?: boolean;
9
+ className?: string;
10
+ style?: CSSProperties;
11
+ }
12
+ export declare function Badge({ children, tone, variant, dot, className, style, }: BadgeProps): import('react').JSX.Element;
13
+ export interface ChipProps {
14
+ children: ReactNode;
15
+ tone?: Tone;
16
+ variant?: BadgeVariant;
17
+ leadingIcon?: ReactNode;
18
+ onRemove?: () => void;
19
+ removeLabel?: string;
20
+ className?: string;
21
+ style?: CSSProperties;
22
+ }
23
+ export declare function Chip({ children, tone, variant, leadingIcon, onRemove, removeLabel, className, style, }: ChipProps): import('react').JSX.Element;
@@ -0,0 +1,20 @@
1
+ import { ButtonHTMLAttributes, ReactNode } from 'react';
2
+ export type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'danger';
3
+ export type ButtonSize = 'sm' | 'md' | 'lg';
4
+ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
5
+ variant?: ButtonVariant;
6
+ size?: ButtonSize;
7
+ loading?: boolean;
8
+ loadingLabel?: string;
9
+ leadingIcon?: ReactNode;
10
+ trailingIcon?: ReactNode;
11
+ fullWidth?: boolean;
12
+ }
13
+ declare const Button: import('react').ForwardRefExoticComponent<ButtonProps & import('react').RefAttributes<HTMLButtonElement>>;
14
+ export interface IconButtonProps extends Omit<ButtonProps, 'children' | 'leadingIcon' | 'trailingIcon'> {
15
+ /** Accessible name for the icon-only button. */
16
+ 'aria-label': string;
17
+ children: ReactNode;
18
+ }
19
+ export declare const IconButton: import('react').ForwardRefExoticComponent<IconButtonProps & import('react').RefAttributes<HTMLButtonElement>>;
20
+ export default Button;
@@ -0,0 +1,36 @@
1
+ import { CSSProperties, ReactNode } from 'react';
2
+ export interface CardProps {
3
+ children: ReactNode;
4
+ padding?: 'none' | 'sm' | 'md' | 'lg';
5
+ className?: string;
6
+ style?: CSSProperties;
7
+ }
8
+ export declare function Card({ children, padding, className, style }: CardProps): import('react').JSX.Element;
9
+ export interface CardHeaderProps {
10
+ title: ReactNode;
11
+ subtitle?: ReactNode;
12
+ actions?: ReactNode;
13
+ className?: string;
14
+ }
15
+ export declare function CardHeader({ title, subtitle, actions, className }: CardHeaderProps): import('react').JSX.Element;
16
+ export declare function CardBody({ children, className, style, }: {
17
+ children: ReactNode;
18
+ className?: string;
19
+ style?: CSSProperties;
20
+ }): import('react').JSX.Element;
21
+ export declare function CardFooter({ children, className, style, }: {
22
+ children: ReactNode;
23
+ className?: string;
24
+ style?: CSSProperties;
25
+ }): import('react').JSX.Element;
26
+ export interface SectionProps {
27
+ title: ReactNode;
28
+ subtitle?: ReactNode;
29
+ actions?: ReactNode;
30
+ children: ReactNode;
31
+ className?: string;
32
+ contentClassName?: string;
33
+ style?: CSSProperties;
34
+ }
35
+ /** Card with a standard header and body — the Settings-style section pattern. */
36
+ export declare function Section({ title, subtitle, actions, children, className, contentClassName, style, }: SectionProps): import('react').JSX.Element;
@@ -0,0 +1,7 @@
1
+ import { ComponentPropsWithRef } from 'react';
2
+ export interface CheckboxProps extends Omit<ComponentPropsWithRef<'input'>, 'type' | 'size'> {
3
+ size?: 'sm' | 'md';
4
+ /** Visually marks a partial selection (DOM `indeterminate` is not an attribute). */
5
+ indeterminate?: boolean;
6
+ }
7
+ export default function Checkbox({ size, className, indeterminate, ...props }: CheckboxProps): import('react').JSX.Element;
@@ -0,0 +1,33 @@
1
+ import { CSSProperties } from 'react';
2
+ export interface ColorPickerLabels {
3
+ picker?: string;
4
+ saturationAndBrightness?: string;
5
+ hue?: string;
6
+ hexColor?: string;
7
+ pickFromScreen?: string;
8
+ presetColors?: string;
9
+ presetColor?: (hex: string) => string;
10
+ red?: string;
11
+ green?: string;
12
+ blue?: string;
13
+ cancel?: string;
14
+ done?: string;
15
+ clickToPick?: string;
16
+ saturationValueText?: (saturation: number, brightness: number) => string;
17
+ }
18
+ export interface ColorPickerProps {
19
+ value: string;
20
+ onChange: (color: string) => void;
21
+ /** Swatches offered by the caller (customizable per usage). */
22
+ presets: string[];
23
+ ariaLabel?: string;
24
+ labels?: ColorPickerLabels;
25
+ className?: string;
26
+ style?: CSSProperties;
27
+ }
28
+ /**
29
+ * Full colour picker styled with the library tokens (replaces the native
30
+ * browser dialog): saturation/brightness area, hue slider, hex + RGB fields,
31
+ * optional screen eyedropper and preset swatches.
32
+ */
33
+ export declare function ColorPicker({ value, onChange, presets, ariaLabel, labels, className, style, }: ColorPickerProps): import('react').JSX.Element;
@@ -0,0 +1,23 @@
1
+ import { CSSProperties } from 'react';
2
+ export interface ComboboxOption {
3
+ value: string;
4
+ label: string;
5
+ description?: string;
6
+ disabled?: boolean;
7
+ }
8
+ export interface ComboboxProps {
9
+ value: string;
10
+ onChange: (value: string) => void;
11
+ options: ComboboxOption[];
12
+ ariaLabel: string;
13
+ placeholder?: string;
14
+ noResultsLabel?: string;
15
+ disabled?: boolean;
16
+ className?: string;
17
+ style?: CSSProperties;
18
+ }
19
+ /**
20
+ * Searchable single-select. The input filters the listbox; the selected value
21
+ * is shown when the popover is closed.
22
+ */
23
+ export default function Combobox({ value, onChange, options, ariaLabel, placeholder, noResultsLabel, disabled, className, style, }: ComboboxProps): import('react').JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { CSSProperties } from 'react';
2
+ export interface ConfirmModalProps {
3
+ open: boolean;
4
+ title: string;
5
+ message: string;
6
+ onConfirm: () => void;
7
+ onCancel: () => void;
8
+ danger?: boolean;
9
+ confirmLabel?: string;
10
+ cancelLabel?: string;
11
+ panelStyle?: CSSProperties;
12
+ panelClassName?: string;
13
+ }
14
+ export default function ConfirmModal({ open, title, message, onConfirm, onCancel, danger, confirmLabel, cancelLabel, panelStyle, panelClassName, }: ConfirmModalProps): import('react').JSX.Element;
@@ -0,0 +1,31 @@
1
+ import { CSSProperties, ReactNode } from 'react';
2
+ export interface CopyValueLabels {
3
+ copied?: string;
4
+ clickToCopy?: string;
5
+ tooltip?: string;
6
+ }
7
+ export interface CopyValueProps {
8
+ /** Raw value copied to the clipboard. */
9
+ value: number | string;
10
+ /** Visible content; defaults to `formatValue(value)`. */
11
+ children?: ReactNode;
12
+ /** Accessible name of the copy affordance. */
13
+ ariaLabel: string;
14
+ /** Formats the visible value. Defaults to `String(value)`. */
15
+ formatValue?: (value: number | string) => ReactNode;
16
+ /** Serializes the value copied to the clipboard. Defaults to `String(value)`. */
17
+ copyValue?: (value: number | string) => string;
18
+ /** Label shown in the tooltip above the copied value. */
19
+ tooltipLabel?: string;
20
+ labels?: CopyValueLabels;
21
+ className?: string;
22
+ style?: CSSProperties;
23
+ /** Style for the tooltip trigger wrapper (e.g. right alignment in a header). */
24
+ wrapperStyle?: CSSProperties;
25
+ }
26
+ /**
27
+ * Click-to-copy value. The panel is informational only (the click itself
28
+ * copies). Formatting and clipboard serialization are injectable so the
29
+ * component stays independent from an application's currency helpers.
30
+ */
31
+ export default function CopyValue({ value, children, ariaLabel, formatValue, copyValue, tooltipLabel, labels, className, style, wrapperStyle, }: CopyValueProps): import('react').JSX.Element;
@@ -0,0 +1,27 @@
1
+ import { CSSProperties, ReactNode } from 'react';
2
+ export interface DataTableColumn<T> {
3
+ key: string;
4
+ header: ReactNode;
5
+ render?: (row: T, index: number) => ReactNode;
6
+ sortable?: boolean;
7
+ align?: 'left' | 'center' | 'right';
8
+ width?: number | string;
9
+ }
10
+ export interface DataTableSort {
11
+ key: string;
12
+ direction: 'asc' | 'desc';
13
+ }
14
+ export interface DataTableProps<T> {
15
+ columns: DataTableColumn<T>[];
16
+ rows: T[];
17
+ rowKey: (row: T, index: number) => string;
18
+ ariaLabel?: string;
19
+ caption?: ReactNode;
20
+ sort?: DataTableSort;
21
+ onSortChange?: (sort: DataTableSort) => void;
22
+ emptyState?: ReactNode;
23
+ onRowClick?: (row: T) => void;
24
+ className?: string;
25
+ style?: CSSProperties;
26
+ }
27
+ export declare function DataTable<T>({ columns, rows, rowKey, ariaLabel, caption, sort, onSortChange, emptyState, onRowClick, className, style, }: DataTableProps<T>): import('react').JSX.Element;
@@ -0,0 +1,33 @@
1
+ import { CSSProperties } from 'react';
2
+ export interface DatePickerProps {
3
+ /** ISO date (`YYYY-MM-DD`) or empty string. */
4
+ value: string;
5
+ onChange: (value: string) => void;
6
+ ariaLabel?: string;
7
+ placeholder?: string;
8
+ disabled?: boolean;
9
+ invalid?: boolean;
10
+ /** Trigger label style: `friendly` = "Mar 30, 2026", `short` = "03/30/2026". */
11
+ format?: 'friendly' | 'short';
12
+ /** `sm` for compact table cells, `md` for form fields (matches input height). */
13
+ size?: 'sm' | 'md';
14
+ fontSize?: number;
15
+ /** Extra style for the trigger button (e.g. tighter horizontal padding in a narrow cell). */
16
+ triggerStyle?: CSSProperties;
17
+ /** BCP 47 locale used for formatting month/weekday labels. Defaults to `en-US`. */
18
+ locale?: string;
19
+ /** Overrides the narrow weekday labels. The list starts on Sunday. */
20
+ weekdayLabels?: string[];
21
+ previousMonthLabel?: string;
22
+ nextMonthLabel?: string;
23
+ clearLabel?: string;
24
+ todayLabel?: string;
25
+ className?: string;
26
+ style?: CSSProperties;
27
+ }
28
+ /**
29
+ * Themed calendar trigger. The month grid is portaled and follows the shared
30
+ * popover behavior (flip/reposition/outside-click/Escape) so it is never clipped
31
+ * and matches the design system instead of the native OS date picker.
32
+ */
33
+ export default function DatePicker({ value, onChange, ariaLabel, placeholder, disabled, invalid, format, size, fontSize, triggerStyle, locale, weekdayLabels, previousMonthLabel, nextMonthLabel, clearLabel, todayLabel, className, style, }: DatePickerProps): import('react').JSX.Element;
@@ -0,0 +1,16 @@
1
+ import { CSSProperties, ReactNode } from 'react';
2
+ export interface DrawerProps {
3
+ open: boolean;
4
+ onClose: () => void;
5
+ title: string;
6
+ children: ReactNode;
7
+ footer?: ReactNode;
8
+ side?: 'left' | 'right';
9
+ width?: number | string;
10
+ closeLabel?: string;
11
+ className?: string;
12
+ style?: CSSProperties;
13
+ bodyClassName?: string;
14
+ }
15
+ export declare function Drawer({ open, onClose, title, children, footer, side, width, closeLabel, className, style, bodyClassName, }: DrawerProps): import('react').ReactPortal | null;
16
+ export { Drawer as Sheet };
@@ -0,0 +1,51 @@
1
+ import { CSSProperties, ReactNode } from 'react';
2
+ export interface DropdownOption {
3
+ value: string;
4
+ label: string;
5
+ /** Optional swatch color rendered as a dot in the option (and in the trigger when `dot`). */
6
+ color?: string;
7
+ /** Optional leading icon rendered in the option (and in the trigger when selected). */
8
+ icon?: ReactNode;
9
+ /** Optional tooltip shown while hovering the option (e.g. the raw card number). */
10
+ hint?: string;
11
+ /** Label of the hint tooltip. */
12
+ hintLabel?: string;
13
+ /**
14
+ * Nested options revealed when this one is selected. The parent is not
15
+ * committed: the user must pick one of the children (used when an alias
16
+ * groups several card patterns).
17
+ */
18
+ children?: DropdownOption[];
19
+ }
20
+ export interface DropdownProps {
21
+ value: string;
22
+ onChange: (value: string) => void;
23
+ options: DropdownOption[];
24
+ ariaLabel: string;
25
+ /** Shown by the trigger when `value` matches no option. */
26
+ placeholder?: string;
27
+ title?: string;
28
+ /** Trigger text color (falls back to `var(--ui-text-2)`). */
29
+ color?: string;
30
+ /** Render a color dot before the value when a `color` is given. */
31
+ dot?: boolean;
32
+ fontSize?: number;
33
+ fontWeight?: number;
34
+ /** `sm` for compact table cells, `md` for form fields (matches input height). */
35
+ size?: 'sm' | 'md';
36
+ /** When false the trigger shrinks to its content (e.g. filter bars). */
37
+ fullWidth?: boolean;
38
+ disabled?: boolean;
39
+ maxHeight?: number;
40
+ /** Notifies the owner when the list opens/closes (used to suppress trigger tooltips). */
41
+ onOpenChange?: (open: boolean) => void;
42
+ className?: string;
43
+ style?: CSSProperties;
44
+ }
45
+ /**
46
+ * Accessible custom select. The option list is rendered in a portal so it is
47
+ * never clipped by ancestor `overflow: hidden` (transaction rows live inside
48
+ * grouped containers that clip), and is styled with the app theme + custom
49
+ * scrollbar instead of the native OS dropdown.
50
+ */
51
+ export default function Dropdown({ value, onChange, options, ariaLabel, placeholder, title, color, dot, fontSize, fontWeight, size, fullWidth, disabled, maxHeight, onOpenChange, className, style, }: DropdownProps): import('react').JSX.Element;
@@ -0,0 +1,26 @@
1
+ import { CSSProperties, ReactNode } from 'react';
2
+ export interface DropdownMenuItem {
3
+ type?: 'item';
4
+ id: string;
5
+ label: ReactNode;
6
+ icon?: ReactNode;
7
+ disabled?: boolean;
8
+ danger?: boolean;
9
+ onSelect?: () => void;
10
+ }
11
+ export interface DropdownMenuSeparator {
12
+ type: 'separator';
13
+ id?: string;
14
+ }
15
+ export type DropdownMenuEntry = DropdownMenuItem | DropdownMenuSeparator;
16
+ export interface DropdownMenuProps {
17
+ /** Trigger content (rendered inside the menu button). */
18
+ trigger: ReactNode;
19
+ items: DropdownMenuEntry[];
20
+ ariaLabel: string;
21
+ align?: 'start' | 'end';
22
+ className?: string;
23
+ style?: CSSProperties;
24
+ }
25
+ export declare function DropdownMenu({ trigger, items, ariaLabel, align, className, style, }: DropdownMenuProps): import('react').JSX.Element;
26
+ export { DropdownMenu as Menu };
@@ -0,0 +1,10 @@
1
+ import { CSSProperties, ReactNode } from 'react';
2
+ export interface EmptyStateProps {
3
+ title: ReactNode;
4
+ description?: ReactNode;
5
+ icon?: ReactNode;
6
+ action?: ReactNode;
7
+ className?: string;
8
+ style?: CSSProperties;
9
+ }
10
+ export default function EmptyState({ title, description, icon, action, className, style, }: EmptyStateProps): import('react').JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { CSSProperties, ReactNode } from 'react';
2
+ export interface FileUploadProps {
3
+ onFiles: (files: File[]) => void;
4
+ accept?: string;
5
+ multiple?: boolean;
6
+ disabled?: boolean;
7
+ label?: ReactNode;
8
+ hint?: ReactNode;
9
+ className?: string;
10
+ style?: CSSProperties;
11
+ inputId?: string;
12
+ }
13
+ export declare function FileUpload({ onFiles, accept, multiple, disabled, label, hint, className, style, inputId, }: FileUploadProps): import('react').JSX.Element;
14
+ export { FileUpload as Dropzone };