@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.
- package/LICENSE +15 -0
- package/README.md +241 -2
- package/dist/components/Alert.d.ts +14 -0
- package/dist/components/Avatar.d.ts +11 -0
- package/dist/components/Badge.d.ts +23 -0
- package/dist/components/Button.d.ts +20 -0
- package/dist/components/Card.d.ts +36 -0
- package/dist/components/Checkbox.d.ts +7 -0
- package/dist/components/ColorPicker.d.ts +33 -0
- package/dist/components/Combobox.d.ts +23 -0
- package/dist/components/ConfirmModal.d.ts +14 -0
- package/dist/components/CopyValue.d.ts +31 -0
- package/dist/components/DataTable.d.ts +27 -0
- package/dist/components/DatePicker.d.ts +33 -0
- package/dist/components/Drawer.d.ts +16 -0
- package/dist/components/Dropdown.d.ts +51 -0
- package/dist/components/DropdownMenu.d.ts +26 -0
- package/dist/components/EmptyState.d.ts +10 -0
- package/dist/components/FileUpload.d.ts +14 -0
- package/dist/components/FormField.d.ts +24 -0
- package/dist/components/InlineEditorCard.d.ts +19 -0
- package/dist/components/ListScreen.d.ts +48 -0
- package/dist/components/Modal.d.ts +22 -0
- package/dist/components/MonthSelector.d.ts +24 -0
- package/dist/components/NumberStepper.d.ts +16 -0
- package/dist/components/PageHeader.d.ts +11 -0
- package/dist/components/Portal.d.ts +11 -0
- package/dist/components/ProgressBar.d.ts +13 -0
- package/dist/components/Radio.d.ts +5 -0
- package/dist/components/RowActions.d.ts +17 -0
- package/dist/components/ScreenSkeleton.d.ts +26 -0
- package/dist/components/SearchInput.d.ts +13 -0
- package/dist/components/SegmentedControl.d.ts +16 -0
- package/dist/components/Skeleton.d.ts +14 -0
- package/dist/components/Slider.d.ts +17 -0
- package/dist/components/Spinner.d.ts +8 -0
- package/dist/components/Switch.d.ts +15 -0
- package/dist/components/Tabs.d.ts +15 -0
- package/dist/components/TextInput.d.ts +13 -0
- package/dist/components/Textarea.d.ts +6 -0
- package/dist/components/Toast.d.ts +21 -0
- package/dist/components/Tooltip.d.ts +22 -0
- package/dist/components/VisuallyHidden.d.ts +6 -0
- package/dist/index.d.ts +82 -0
- package/dist/index.js +3253 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/ScreenCaptureOverlay.d.ts +16 -0
- package/dist/internal/clipboard.d.ts +11 -0
- package/dist/internal/color.utils.d.ts +21 -0
- package/dist/internal/screen-color-picker.d.ts +12 -0
- package/dist/internal/tone.d.ts +1 -0
- package/dist/internal/useFocusTrap.d.ts +7 -0
- package/dist/internal/useIsomorphicLayoutEffect.d.ts +6 -0
- package/dist/internal/usePopover.d.ts +30 -0
- package/dist/styles.css +1702 -0
- 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
|
-
#
|
|
1
|
+
# @ravileal/ui
|
|
2
2
|
|
|
3
|
-
|
|
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 };
|