@rebasepro/cli 0.6.1 → 0.7.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/README.md +0 -1
- package/dist/commands/api-keys.d.ts +1 -0
- package/dist/commands/generate_sdk.d.ts +1 -1
- package/dist/index.es.js +399 -57
- package/dist/index.es.js.map +1 -1
- package/package.json +20 -15
- package/templates/template/backend/package.json +0 -1
- package/templates/template/backend/src/index.ts +1 -1
- package/templates/template/config/collections/posts.ts +1 -3
- package/templates/template/config/collections/tags.ts +1 -3
- package/templates/template/config/collections/users.ts +1 -4
- package/templates/template/package.json +0 -1
- package/templates/template/scripts/example.ts +4 -1
- package/skills/rebase-admin/SKILL.md +0 -710
- package/skills/rebase-api/SKILL.md +0 -662
- package/skills/rebase-api/references/.gitkeep +0 -3
- package/skills/rebase-auth/SKILL.md +0 -1143
- package/skills/rebase-auth/references/.gitkeep +0 -3
- package/skills/rebase-backend-postgres/SKILL.md +0 -633
- package/skills/rebase-backend-postgres/references/.gitkeep +0 -3
- package/skills/rebase-basics/SKILL.md +0 -749
- package/skills/rebase-basics/references/.gitkeep +0 -3
- package/skills/rebase-collections/SKILL.md +0 -1328
- package/skills/rebase-collections/references/.gitkeep +0 -3
- package/skills/rebase-cron-jobs/SKILL.md +0 -699
- package/skills/rebase-cron-jobs/references/.gitkeep +0 -1
- package/skills/rebase-custom-functions/SKILL.md +0 -233
- package/skills/rebase-deployment/SKILL.md +0 -885
- package/skills/rebase-deployment/references/.gitkeep +0 -3
- package/skills/rebase-design-language/SKILL.md +0 -692
- package/skills/rebase-email/SKILL.md +0 -701
- package/skills/rebase-email/references/.gitkeep +0 -1
- package/skills/rebase-entity-history/SKILL.md +0 -485
- package/skills/rebase-entity-history/references/.gitkeep +0 -1
- package/skills/rebase-local-env-setup/SKILL.md +0 -189
- package/skills/rebase-local-env-setup/references/.gitkeep +0 -3
- package/skills/rebase-realtime/SKILL.md +0 -755
- package/skills/rebase-realtime/references/.gitkeep +0 -3
- package/skills/rebase-sdk/SKILL.md +0 -594
- package/skills/rebase-sdk/references/.gitkeep +0 -0
- package/skills/rebase-storage/SKILL.md +0 -765
- package/skills/rebase-storage/references/.gitkeep +0 -3
- package/skills/rebase-studio/SKILL.md +0 -746
- package/skills/rebase-studio/references/.gitkeep +0 -3
- package/skills/rebase-ui-components/SKILL.md +0 -1488
- package/skills/rebase-ui-components/references/.gitkeep +0 -3
- package/skills/rebase-webhooks/SKILL.md +0 -623
- package/skills/rebase-webhooks/references/.gitkeep +0 -1
- package/templates/template/backend/drizzle.config.ts +0 -51
|
@@ -1,1488 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: rebase-ui-components
|
|
3
|
-
description: Guide for using the @rebasepro/ui component library. Use this skill when building UI with Rebase, creating custom views, or needing to know which components are available.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Rebase UI Component Library
|
|
7
|
-
|
|
8
|
-
`@rebasepro/ui` is Rebase's standalone, production-ready component library built on **Tailwind CSS v4** and **Radix UI**. It's fully typed, accessible, and can be used in any React project.
|
|
9
|
-
|
|
10
|
-
> **IMPORTANT FOR AGENTS:** Always import components, hooks, utilities, icons, and style mixins from `@rebasepro/ui`. **Never** add direct `@radix-ui/*` or `lucide-react` dependencies — the UI package re-exports everything you need.
|
|
11
|
-
|
|
12
|
-
## Installation
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
pnpm add @rebasepro/ui
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
## Core Rules
|
|
19
|
-
|
|
20
|
-
1. **Always use `@rebasepro/ui`** for all UI components. Check this skill before creating custom ones.
|
|
21
|
-
2. **Never use `as any`** — use proper types or `unknown`.
|
|
22
|
-
3. **Use `cls()`** for conditional class merging — not template literals.
|
|
23
|
-
4. **Use `Typography`** for all text — never raw `<h1>`, `<p>`, `<span>`.
|
|
24
|
-
5. **Icons come from `lucide-react` via `@rebasepro/ui`** — there are no `ArrowForwardIcon` or `AddIcon` exports. Use real lucide names like `ArrowRightIcon`, `PlusIcon`.
|
|
25
|
-
|
|
26
|
-
## Package Exports
|
|
27
|
-
|
|
28
|
-
The package exports five modules:
|
|
29
|
-
|
|
30
|
-
```ts
|
|
31
|
-
export * from "./components"; // All UI components
|
|
32
|
-
export * from "./styles"; // Tailwind style mixin strings
|
|
33
|
-
export * from "./util"; // cls(), debounce(), chip_colors, keyToIconComponent
|
|
34
|
-
export * from "./icons"; // Icon component, iconSize, lucideIcons map, icon_keys, cool_icon_keys
|
|
35
|
-
export * from "./hooks"; // React hooks
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
|
-
## Components — Complete Reference
|
|
41
|
-
|
|
42
|
-
### Button
|
|
43
|
-
|
|
44
|
-
Polymorphic button with multiple variants and colors.
|
|
45
|
-
|
|
46
|
-
| Prop | Type | Default | Description |
|
|
47
|
-
|------|------|---------|-------------|
|
|
48
|
-
| `variant` | `"filled" \| "outlined" \| "text"` | `"filled"` | Visual style |
|
|
49
|
-
| `color` | `"primary" \| "secondary" \| "text" \| "error" \| "neutral"` | `"neutral"` | Color scheme |
|
|
50
|
-
| `size` | `"small" \| "medium" \| "large" \| "xl" \| "2xl"` | `"medium"` | Size preset |
|
|
51
|
-
| `startIcon` | `ReactNode` | `null` | Icon before label |
|
|
52
|
-
| `fullWidth` | `boolean` | `false` | Stretch to container width |
|
|
53
|
-
| `disabled` | `boolean` | `false` | Disabled state |
|
|
54
|
-
| `component` | `React.ElementType` | `"button"` | Render as a different element (e.g. `"a"`) |
|
|
55
|
-
| `className` | `string` | — | Additional classes |
|
|
56
|
-
| `onClick` | `MouseEventHandler` | — | Click handler |
|
|
57
|
-
|
|
58
|
-
```tsx
|
|
59
|
-
import { Button } from "@rebasepro/ui";
|
|
60
|
-
import { PlusIcon } from "@rebasepro/ui";
|
|
61
|
-
|
|
62
|
-
<Button variant="filled" color="primary" size="large" startIcon={<PlusIcon size={20} />}>
|
|
63
|
-
Create Item
|
|
64
|
-
</Button>
|
|
65
|
-
|
|
66
|
-
<Button variant="outlined" color="error" size="small">Delete</Button>
|
|
67
|
-
<Button variant="text" color="secondary">Cancel</Button>
|
|
68
|
-
|
|
69
|
-
{/* As an anchor */}
|
|
70
|
-
<Button component="a" href="/docs" variant="text" color="primary">
|
|
71
|
-
Go to Docs
|
|
72
|
-
</Button>
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### IconButton
|
|
76
|
-
|
|
77
|
-
Icon-only button with ghost or filled background.
|
|
78
|
-
|
|
79
|
-
| Prop | Type | Default | Description |
|
|
80
|
-
|------|------|---------|-------------|
|
|
81
|
-
| `size` | `"smallest" \| "small" \| "medium" \| "large"` | `"medium"` | Size (6/8/10/12 = 24/32/40/48 px) |
|
|
82
|
-
| `variant` | `"ghost" \| "filled"` | `"ghost"` | Background style |
|
|
83
|
-
| `shape` | `"circular" \| "square"` | `"circular"` | Border radius |
|
|
84
|
-
| `disabled` | `boolean` | — | Disabled state |
|
|
85
|
-
| `toggled` | `boolean` | — | Shows outline ring when toggled |
|
|
86
|
-
| `component` | `React.ElementType` | `"button"` | Polymorphic element |
|
|
87
|
-
| `onClick` | `MouseEventHandler` | — | Click handler |
|
|
88
|
-
| `aria-label` | `string` | — | Required for accessibility |
|
|
89
|
-
|
|
90
|
-
```tsx
|
|
91
|
-
import { IconButton } from "@rebasepro/ui";
|
|
92
|
-
import { SettingsIcon } from "@rebasepro/ui";
|
|
93
|
-
|
|
94
|
-
<IconButton aria-label="Settings" onClick={openSettings}>
|
|
95
|
-
<SettingsIcon size={20} />
|
|
96
|
-
</IconButton>
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
### LoadingButton
|
|
100
|
-
|
|
101
|
-
Extends `Button` with a loading spinner. Automatically disables when loading.
|
|
102
|
-
|
|
103
|
-
| Prop | Type | Default | Description |
|
|
104
|
-
|------|------|---------|-------------|
|
|
105
|
-
| `loading` | `boolean` | — | Shows spinner, hides startIcon, disables button |
|
|
106
|
-
| _...all ButtonProps_ | | | Inherits all Button props |
|
|
107
|
-
|
|
108
|
-
```tsx
|
|
109
|
-
import { LoadingButton } from "@rebasepro/ui";
|
|
110
|
-
|
|
111
|
-
<LoadingButton loading={isSaving} variant="filled" color="primary" onClick={handleSave}>
|
|
112
|
-
Save Changes
|
|
113
|
-
</LoadingButton>
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
### Typography
|
|
117
|
-
|
|
118
|
-
Renders text with semantic HTML elements and consistent styling.
|
|
119
|
-
|
|
120
|
-
| Prop | Type | Default | Description |
|
|
121
|
-
|------|------|---------|-------------|
|
|
122
|
-
| `variant` | `TypographyVariant` (see below) | `"body1"` | Text style |
|
|
123
|
-
| `color` | `"inherit" \| "initial" \| "primary" \| "secondary" \| "disabled" \| "error"` | `"primary"` | Text color |
|
|
124
|
-
| `component` | `React.ElementType` | auto from variant | Override rendered element |
|
|
125
|
-
| `gutterBottom` | `boolean` | `false` | Adds bottom margin |
|
|
126
|
-
| `noWrap` | `boolean` | `false` | Truncate with ellipsis |
|
|
127
|
-
| `paragraph` | `boolean` | `false` | Renders as `<p>` with margin |
|
|
128
|
-
| `align` | `"center" \| "inherit" \| "justify" \| "left" \| "right"` | `"inherit"` | Text alignment |
|
|
129
|
-
| `variantMapping` | `Record<string, string>` | built-in | Override variant→element mapping |
|
|
130
|
-
|
|
131
|
-
**TypographyVariant values:** `"h1"`, `"h2"`, `"h3"`, `"h4"`, `"h5"`, `"h6"`, `"subtitle1"`, `"subtitle2"`, `"label"`, `"body1"`, `"body2"`, `"inherit"`, `"caption"`, `"button"`
|
|
132
|
-
|
|
133
|
-
| Variant | Default Element | CSS Class |
|
|
134
|
-
|---------|----------------|-----------|
|
|
135
|
-
| `h1`–`h6` | `<h1>`–`<h6>` | `typography-h1`–`typography-h6` |
|
|
136
|
-
| `subtitle1`, `subtitle2` | `<h6>` | `typography-subtitle1/2` |
|
|
137
|
-
| `body1`, `body2` | `<p>` | `typography-body1/2` |
|
|
138
|
-
| `label` | `<label>` | `typography-label` |
|
|
139
|
-
| `caption` | `<p>` | `typography-caption` |
|
|
140
|
-
| `button` | `<span>` | `typography-button` |
|
|
141
|
-
|
|
142
|
-
```tsx
|
|
143
|
-
import { Typography } from "@rebasepro/ui";
|
|
144
|
-
|
|
145
|
-
<Typography variant="h4" gutterBottom>Page Title</Typography>
|
|
146
|
-
<Typography variant="body1">Regular text content</Typography>
|
|
147
|
-
<Typography variant="caption" color="secondary">Helper text</Typography>
|
|
148
|
-
<Typography variant="body2" color="error">Validation message</Typography>
|
|
149
|
-
<Typography variant="h6" noWrap>Very long title that will truncate...</Typography>
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
### Container
|
|
153
|
-
|
|
154
|
-
Centered max-width container with responsive padding.
|
|
155
|
-
|
|
156
|
-
| Prop | Type | Default | Description |
|
|
157
|
-
|------|------|---------|-------------|
|
|
158
|
-
| `maxWidth` | `"xs" \| "sm" \| "md" \| "lg" \| "xl" \| "2xl" \| "3xl" \| "4xl" \| "5xl" \| "6xl" \| "7xl"` | `"7xl"` | Maximum width |
|
|
159
|
-
| `className` | `string` | — | Extra classes |
|
|
160
|
-
| `style` | `CSSProperties` | — | Inline styles |
|
|
161
|
-
|
|
162
|
-
```tsx
|
|
163
|
-
import { Container } from "@rebasepro/ui";
|
|
164
|
-
|
|
165
|
-
<Container maxWidth="4xl">
|
|
166
|
-
{/* Content limited to max-w-4xl with mx-auto px-3 md:px-4 */}
|
|
167
|
-
</Container>
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
### Card
|
|
171
|
-
|
|
172
|
-
Bordered card with optional click behavior. Automatically adds keyboard support and `role="button"` when `onClick` is provided.
|
|
173
|
-
|
|
174
|
-
| Prop | Type | Default | Description |
|
|
175
|
-
|------|------|---------|-------------|
|
|
176
|
-
| `onClick` | `(e?: React.MouseEvent) => void` | — | Makes card clickable with hover effects |
|
|
177
|
-
| `className` | `string` | — | Extra classes (padding NOT included — add `p-4`/`p-6`) |
|
|
178
|
-
| `style` | `CSSProperties` | — | Inline styles |
|
|
179
|
-
|
|
180
|
-
> **IMPORTANT FOR AGENTS:** Card does NOT include padding. Always add `className="p-4"` or similar.
|
|
181
|
-
|
|
182
|
-
```tsx
|
|
183
|
-
import { Card, Typography } from "@rebasepro/ui";
|
|
184
|
-
|
|
185
|
-
{/* Static card */}
|
|
186
|
-
<Card className="p-6">
|
|
187
|
-
<Typography variant="h6">Title</Typography>
|
|
188
|
-
<Typography variant="body2" color="secondary">Description</Typography>
|
|
189
|
-
</Card>
|
|
190
|
-
|
|
191
|
-
{/* Clickable card — gets hover effects automatically */}
|
|
192
|
-
<Card className="p-4" onClick={() => navigate("/details")}>
|
|
193
|
-
<Typography variant="body1">Click me</Typography>
|
|
194
|
-
</Card>
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
### Paper
|
|
198
|
-
|
|
199
|
-
Minimal bordered container. Uses `paperMixin` styling: white bg, rounded-md, border.
|
|
200
|
-
|
|
201
|
-
```tsx
|
|
202
|
-
import { Paper } from "@rebasepro/ui";
|
|
203
|
-
<Paper className="p-4">Content</Paper>
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
### CenteredView
|
|
207
|
-
|
|
208
|
-
Centers content vertically and horizontally within a full-height container.
|
|
209
|
-
|
|
210
|
-
```tsx
|
|
211
|
-
import { CenteredView } from "@rebasepro/ui";
|
|
212
|
-
<CenteredView>
|
|
213
|
-
<Typography>Centered content</Typography>
|
|
214
|
-
</CenteredView>
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
### Alert
|
|
218
|
-
|
|
219
|
-
Contextual alert banner with color-coded left border.
|
|
220
|
-
|
|
221
|
-
| Prop | Type | Default | Description |
|
|
222
|
-
|------|------|---------|-------------|
|
|
223
|
-
| `color` | `"error" \| "warning" \| "info" \| "success" \| "base"` | `"info"` | Alert severity |
|
|
224
|
-
| `size` | `"small" \| "medium" \| "large"` | `"medium"` | Padding size |
|
|
225
|
-
| `onDismiss` | `() => void` | — | Shows × dismiss button |
|
|
226
|
-
| `action` | `ReactNode` | — | Action element on right side |
|
|
227
|
-
| `className` | `string` | — | Class for inner content div |
|
|
228
|
-
| `outerClassName` | `string` | — | Class for outer container |
|
|
229
|
-
| `style` | `CSSProperties` | — | Inline styles |
|
|
230
|
-
|
|
231
|
-
```tsx
|
|
232
|
-
import { Alert, Button } from "@rebasepro/ui";
|
|
233
|
-
|
|
234
|
-
<Alert color="error" onDismiss={() => setShow(false)}>
|
|
235
|
-
Something went wrong. Please try again.
|
|
236
|
-
</Alert>
|
|
237
|
-
|
|
238
|
-
<Alert color="success" size="small">
|
|
239
|
-
Record saved successfully!
|
|
240
|
-
</Alert>
|
|
241
|
-
|
|
242
|
-
<Alert color="warning" action={<Button variant="text" size="small">Fix</Button>}>
|
|
243
|
-
Missing required fields
|
|
244
|
-
</Alert>
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
### Chip
|
|
248
|
-
|
|
249
|
-
Colored label/tag with optional icon.
|
|
250
|
-
|
|
251
|
-
| Prop | Type | Default | Description |
|
|
252
|
-
|------|------|---------|-------------|
|
|
253
|
-
| `colorScheme` | `ChipColorScheme \| ChipColorKey` | — | Color. Can be a key string (`"blue"`, `"teal"`, etc.) or a `ChipColorScheme` object |
|
|
254
|
-
| `size` | `"smallest" \| "small" \| "medium" \| "large"` | `"large"` | Size preset |
|
|
255
|
-
| `outlined` | `boolean` | — | Outlined variant with translucent bg |
|
|
256
|
-
| `error` | `boolean` | — | Red error styling |
|
|
257
|
-
| `onClick` | `() => void` | — | Makes chip clickable |
|
|
258
|
-
| `icon` | `ReactNode` | — | Icon rendered after text |
|
|
259
|
-
| `className` | `string` | — | Extra classes |
|
|
260
|
-
|
|
261
|
-
**ChipColorKey values:** `"blue"`, `"teal"`, `"yellow"`, `"pink"`, `"purple"`, `"cyan"`, `"orange"`, `"green"`, `"red"`, `"gray"`, `"indigo"`, `"violet"`, `"fuchsia"`, `"rose"`, `"emerald"`
|
|
262
|
-
|
|
263
|
-
```tsx
|
|
264
|
-
import { Chip } from "@rebasepro/ui";
|
|
265
|
-
|
|
266
|
-
<Chip colorScheme="blue" size="medium">Active</Chip>
|
|
267
|
-
<Chip colorScheme="red" outlined>Urgent</Chip>
|
|
268
|
-
<Chip error>Error</Chip>
|
|
269
|
-
<Chip size="small">Default</Chip>
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
### FilterChip
|
|
273
|
-
|
|
274
|
-
Toggle chip for filter presets. Uses inset box-shadow for stable sizing.
|
|
275
|
-
|
|
276
|
-
| Prop | Type | Default | Description |
|
|
277
|
-
|------|------|---------|-------------|
|
|
278
|
-
| `active` | `boolean` | `false` | Selected/active state |
|
|
279
|
-
| `icon` | `ReactNode` | — | Icon before label |
|
|
280
|
-
| `size` | `"small" \| "medium"` | `"medium"` | Size preset |
|
|
281
|
-
| `disabled` | `boolean` | `false` | Disabled state |
|
|
282
|
-
| `onClick` | handler | — | Click handler |
|
|
283
|
-
|
|
284
|
-
```tsx
|
|
285
|
-
import { FilterChip } from "@rebasepro/ui";
|
|
286
|
-
|
|
287
|
-
<FilterChip active={filter === "active"} onClick={() => setFilter("active")}>
|
|
288
|
-
Active
|
|
289
|
-
</FilterChip>
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
### Dialog, DialogTitle, DialogContent, DialogActions
|
|
293
|
-
|
|
294
|
-
Modal dialog built on Radix Dialog.
|
|
295
|
-
|
|
296
|
-
**Dialog Props:**
|
|
297
|
-
|
|
298
|
-
| Prop | Type | Default | Description |
|
|
299
|
-
|------|------|---------|-------------|
|
|
300
|
-
| `open` | `boolean` | — | Controlled open state |
|
|
301
|
-
| `onOpenChange` | `(open: boolean) => void` | — | Open state callback |
|
|
302
|
-
| `maxWidth` | `"xs" \| "sm" \| "md" \| "lg" \| "xl" \| "2xl"–"7xl" \| "full"` | `"lg"` | Dialog max width |
|
|
303
|
-
| `fullWidth` | `boolean` | `true` | Use 11/12 of available width |
|
|
304
|
-
| `fullHeight` | `boolean` | — | Full height |
|
|
305
|
-
| `fullScreen` | `boolean` | — | Full screen overlay |
|
|
306
|
-
| `scrollable` | `boolean` | `true` | Scrollable content |
|
|
307
|
-
| `modal` | `boolean` | `true` | Modal behavior |
|
|
308
|
-
| `disableInitialFocus` | `boolean` | `true` | Skip auto-focus on open |
|
|
309
|
-
|
|
310
|
-
**DialogTitle Props:**
|
|
311
|
-
|
|
312
|
-
| Prop | Type | Default | Description |
|
|
313
|
-
|------|------|---------|-------------|
|
|
314
|
-
| `variant` | `TypographyVariant` | `"subtitle2"` | Typography variant |
|
|
315
|
-
| `hidden` | `boolean` | — | Visually hidden (for a11y) |
|
|
316
|
-
| `includeMargin` | `boolean` | `true` | Add mt-8 mx-8 margin |
|
|
317
|
-
| `gutterBottom` | `boolean` | `true` | Bottom margin |
|
|
318
|
-
|
|
319
|
-
**DialogContent Props:**
|
|
320
|
-
|
|
321
|
-
| Prop | Type | Default | Description |
|
|
322
|
-
|------|------|---------|-------------|
|
|
323
|
-
| `includeMargin` | `boolean` | `true` | Add my-8 mx-8 margin |
|
|
324
|
-
| `fullHeight` | `boolean` | — | Flex-grow full height |
|
|
325
|
-
|
|
326
|
-
**DialogActions Props:**
|
|
327
|
-
|
|
328
|
-
| Prop | Type | Default | Description |
|
|
329
|
-
|------|------|---------|-------------|
|
|
330
|
-
| `position` | `"sticky" \| "absolute"` | `"sticky"` | Positioning |
|
|
331
|
-
| `translucent` | `boolean` | `true` | Backdrop blur effect |
|
|
332
|
-
|
|
333
|
-
```tsx
|
|
334
|
-
import { Dialog, DialogTitle, DialogContent, DialogActions, Button } from "@rebasepro/ui";
|
|
335
|
-
|
|
336
|
-
function ConfirmDialog({ open, onClose, onConfirm }) {
|
|
337
|
-
return (
|
|
338
|
-
<Dialog open={open} onOpenChange={onClose} maxWidth="sm">
|
|
339
|
-
<DialogTitle>Confirm Action</DialogTitle>
|
|
340
|
-
<DialogContent>
|
|
341
|
-
<Typography>Are you sure you want to proceed?</Typography>
|
|
342
|
-
</DialogContent>
|
|
343
|
-
<DialogActions>
|
|
344
|
-
<Button variant="text" onClick={onClose}>Cancel</Button>
|
|
345
|
-
<Button variant="filled" color="primary" onClick={onConfirm}>
|
|
346
|
-
Confirm
|
|
347
|
-
</Button>
|
|
348
|
-
</DialogActions>
|
|
349
|
-
</Dialog>
|
|
350
|
-
);
|
|
351
|
-
}
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
### Select, SelectItem, SelectGroup
|
|
355
|
-
|
|
356
|
-
Radix-based single-value select dropdown.
|
|
357
|
-
|
|
358
|
-
**Select Props:**
|
|
359
|
-
|
|
360
|
-
| Prop | Type | Default | Description |
|
|
361
|
-
|------|------|---------|-------------|
|
|
362
|
-
| `value` | `string \| number \| boolean` | — | Selected value |
|
|
363
|
-
| `onValueChange` | `(value: T) => void` | — | Value change callback |
|
|
364
|
-
| `size` | `"smallest" \| "small" \| "medium" \| "large"` | `"large"` | Size preset |
|
|
365
|
-
| `label` | `ReactNode \| string` | — | Label (string renders as `SelectInputLabel`) |
|
|
366
|
-
| `placeholder` | `ReactNode` | — | Placeholder when no value |
|
|
367
|
-
| `renderValue` | `(value: T) => ReactNode` | — | Custom value renderer |
|
|
368
|
-
| `disabled` | `boolean` | — | Disabled state |
|
|
369
|
-
| `error` | `boolean` | — | Error styling |
|
|
370
|
-
| `invisible` | `boolean` | — | Transparent background |
|
|
371
|
-
| `fullWidth` | `boolean` | `false` | Full width |
|
|
372
|
-
| `position` | `"item-aligned" \| "popper"` | `"item-aligned"` | Dropdown position |
|
|
373
|
-
| `endAdornment` | `ReactNode` | — | End adornment |
|
|
374
|
-
| `dataType` | `"string" \| "number" \| "boolean"` | `"string"` | Type coercion for value |
|
|
375
|
-
|
|
376
|
-
```tsx
|
|
377
|
-
import { Select, SelectItem, SelectGroup } from "@rebasepro/ui";
|
|
378
|
-
|
|
379
|
-
<Select
|
|
380
|
-
value={status}
|
|
381
|
-
onValueChange={setStatus}
|
|
382
|
-
label="Status"
|
|
383
|
-
placeholder="Select a status"
|
|
384
|
-
size="large"
|
|
385
|
-
>
|
|
386
|
-
<SelectGroup label="Active">
|
|
387
|
-
<SelectItem value="draft">Draft</SelectItem>
|
|
388
|
-
<SelectItem value="published">Published</SelectItem>
|
|
389
|
-
</SelectGroup>
|
|
390
|
-
<SelectItem value="archived">Archived</SelectItem>
|
|
391
|
-
</Select>
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
### MultiSelect, MultiSelectItem
|
|
395
|
-
|
|
396
|
-
Multi-value select with search, chips, select-all, and clear.
|
|
397
|
-
|
|
398
|
-
**MultiSelect Props:**
|
|
399
|
-
|
|
400
|
-
| Prop | Type | Default | Description |
|
|
401
|
-
|------|------|---------|-------------|
|
|
402
|
-
| `value` | `T[]` | — | Selected values |
|
|
403
|
-
| `onValueChange` | `(values: T[]) => void` | — | Change callback |
|
|
404
|
-
| `size` | `"smallest" \| "small" \| "medium" \| "large"` | `"large"` | Size |
|
|
405
|
-
| `label` | `ReactNode \| string` | — | Label |
|
|
406
|
-
| `placeholder` | `ReactNode` | — | Placeholder |
|
|
407
|
-
| `useChips` | `boolean` | `true` | Show selected values as chips |
|
|
408
|
-
| `includeSelectAll` | `boolean` | `true` | Show "(Select All)" option |
|
|
409
|
-
| `includeClear` | `boolean` | `true` | Show clear button |
|
|
410
|
-
| `renderValues` | `(values: T[]) => ReactNode` | — | Custom selected values renderer |
|
|
411
|
-
| `disabled`, `error`, `invisible` | `boolean` | — | State flags |
|
|
412
|
-
|
|
413
|
-
```tsx
|
|
414
|
-
import { MultiSelect, MultiSelectItem } from "@rebasepro/ui";
|
|
415
|
-
|
|
416
|
-
<MultiSelect
|
|
417
|
-
value={selectedTags}
|
|
418
|
-
onValueChange={setSelectedTags}
|
|
419
|
-
label="Tags"
|
|
420
|
-
placeholder="Select tags..."
|
|
421
|
-
>
|
|
422
|
-
<MultiSelectItem value="frontend">Frontend</MultiSelectItem>
|
|
423
|
-
<MultiSelectItem value="backend">Backend</MultiSelectItem>
|
|
424
|
-
<MultiSelectItem value="devops">DevOps</MultiSelectItem>
|
|
425
|
-
</MultiSelect>
|
|
426
|
-
```
|
|
427
|
-
|
|
428
|
-
### TextField
|
|
429
|
-
|
|
430
|
-
Single-line or multiline text input with floating label.
|
|
431
|
-
|
|
432
|
-
| Prop | Type | Default | Description |
|
|
433
|
-
|------|------|---------|-------------|
|
|
434
|
-
| `value` | `string \| number` | — | Input value |
|
|
435
|
-
| `onChange` | `ChangeEventHandler` | — | Change handler |
|
|
436
|
-
| `label` | `ReactNode` | — | Floating label |
|
|
437
|
-
| `type` | `InputType` | `"text"` | `"text" \| "number" \| "email" \| "password" \| "url" \| "search"` etc. |
|
|
438
|
-
| `size` | `"smallest" \| "small" \| "medium" \| "large"` | `"large"` | Height preset |
|
|
439
|
-
| `multiline` | `boolean` | `false` | Renders as textarea |
|
|
440
|
-
| `disabled` | `boolean` | — | Disabled state |
|
|
441
|
-
| `invisible` | `boolean` | — | Transparent bg |
|
|
442
|
-
| `error` | `boolean` | — | Error border |
|
|
443
|
-
| `placeholder` | `string` | — | Placeholder text |
|
|
444
|
-
| `endAdornment` | `ReactNode` | — | Element at input end |
|
|
445
|
-
| `autoFocus` | `boolean` | — | Auto focus |
|
|
446
|
-
|
|
447
|
-
```tsx
|
|
448
|
-
import { TextField } from "@rebasepro/ui";
|
|
449
|
-
|
|
450
|
-
<TextField
|
|
451
|
-
label="Email"
|
|
452
|
-
type="email"
|
|
453
|
-
value={email}
|
|
454
|
-
onChange={(e) => setEmail(e.target.value)}
|
|
455
|
-
size="large"
|
|
456
|
-
error={!isValid}
|
|
457
|
-
/>
|
|
458
|
-
|
|
459
|
-
<TextField
|
|
460
|
-
label="Description"
|
|
461
|
-
multiline
|
|
462
|
-
minRows={3}
|
|
463
|
-
value={desc}
|
|
464
|
-
onChange={(e) => setDesc(e.target.value)}
|
|
465
|
-
/>
|
|
466
|
-
```
|
|
467
|
-
|
|
468
|
-
### DebouncedTextField
|
|
469
|
-
|
|
470
|
-
Wraps `TextField` with 150ms debounce. Flushes on blur. Same props as `TextField`.
|
|
471
|
-
|
|
472
|
-
```tsx
|
|
473
|
-
import { DebouncedTextField } from "@rebasepro/ui";
|
|
474
|
-
|
|
475
|
-
<DebouncedTextField
|
|
476
|
-
label="Search"
|
|
477
|
-
value={searchTerm}
|
|
478
|
-
onChange={(e) => setSearchTerm(e.target.value)}
|
|
479
|
-
/>
|
|
480
|
-
```
|
|
481
|
-
|
|
482
|
-
### Tabs, Tab
|
|
483
|
-
|
|
484
|
-
Tabbed navigation with three visual variants.
|
|
485
|
-
|
|
486
|
-
**Tabs Props:**
|
|
487
|
-
|
|
488
|
-
| Prop | Type | Default | Description |
|
|
489
|
-
|------|------|---------|-------------|
|
|
490
|
-
| `value` | `string` | — | Active tab value |
|
|
491
|
-
| `onValueChange` | `(value: string) => void` | — | Tab change callback |
|
|
492
|
-
| `variant` | `"standard" \| "boxy" \| "pill"` | `"standard"` | Visual style |
|
|
493
|
-
| `className` | `string` | — | Outer container class |
|
|
494
|
-
| `innerClassName` | `string` | — | Tab list class |
|
|
495
|
-
|
|
496
|
-
**Tab Props:**
|
|
497
|
-
|
|
498
|
-
| Prop | Type | Default | Description |
|
|
499
|
-
|------|------|---------|-------------|
|
|
500
|
-
| `value` | `string` | — | Tab identifier |
|
|
501
|
-
| `disabled` | `boolean` | — | Disabled state |
|
|
502
|
-
| `className` | `string` | — | Extra classes |
|
|
503
|
-
|
|
504
|
-
```tsx
|
|
505
|
-
import { Tabs, Tab } from "@rebasepro/ui";
|
|
506
|
-
|
|
507
|
-
<Tabs value={activeTab} onValueChange={setActiveTab} variant="standard">
|
|
508
|
-
<Tab value="general">General</Tab>
|
|
509
|
-
<Tab value="advanced">Advanced</Tab>
|
|
510
|
-
<Tab value="settings">Settings</Tab>
|
|
511
|
-
</Tabs>
|
|
512
|
-
|
|
513
|
-
{/* Boxy variant — bordered tabs with bottom highlight */}
|
|
514
|
-
<Tabs value={tab} onValueChange={setTab} variant="boxy">
|
|
515
|
-
<Tab value="data">Data</Tab>
|
|
516
|
-
<Tab value="schema">Schema</Tab>
|
|
517
|
-
</Tabs>
|
|
518
|
-
|
|
519
|
-
{/* Pill variant — compact rounded pills */}
|
|
520
|
-
<Tabs value={tab} onValueChange={setTab} variant="pill">
|
|
521
|
-
<Tab value="all">All</Tab>
|
|
522
|
-
<Tab value="active">Active</Tab>
|
|
523
|
-
</Tabs>
|
|
524
|
-
```
|
|
525
|
-
|
|
526
|
-
### Sheet
|
|
527
|
-
|
|
528
|
-
Slide-in panel overlay (side drawer) built on Radix Dialog.
|
|
529
|
-
|
|
530
|
-
| Prop | Type | Default | Description |
|
|
531
|
-
|------|------|---------|-------------|
|
|
532
|
-
| `open` | `boolean` | — | Controlled open state |
|
|
533
|
-
| `onOpenChange` | `(open: boolean) => void` | — | Open state change |
|
|
534
|
-
| `side` | `"top" \| "bottom" \| "left" \| "right"` | `"right"` | Slide direction |
|
|
535
|
-
| `modal` | `boolean` | `true` | Modal behavior |
|
|
536
|
-
| `includeBackgroundOverlay` | `boolean` | `true` | Show backdrop blur overlay |
|
|
537
|
-
| `transparent` | `boolean` | — | No shadow/background on panel |
|
|
538
|
-
| `title` | `string` | `"Sheet"` | Accessible title (sr-only) |
|
|
539
|
-
| `className` | `string` | — | Panel class |
|
|
540
|
-
| `overlayClassName` | `string` | — | Overlay class |
|
|
541
|
-
|
|
542
|
-
```tsx
|
|
543
|
-
import { Sheet, Typography, Button } from "@rebasepro/ui";
|
|
544
|
-
|
|
545
|
-
<Sheet open={isOpen} onOpenChange={setIsOpen} side="right">
|
|
546
|
-
<div className="p-6 w-[400px]">
|
|
547
|
-
<Typography variant="h5" gutterBottom>Details</Typography>
|
|
548
|
-
<Typography variant="body1">Panel content here</Typography>
|
|
549
|
-
<Button onClick={() => setIsOpen(false)} className="mt-4">Close</Button>
|
|
550
|
-
</div>
|
|
551
|
-
</Sheet>
|
|
552
|
-
```
|
|
553
|
-
|
|
554
|
-
### Popover
|
|
555
|
-
|
|
556
|
-
Positioned popover built on Radix Popover.
|
|
557
|
-
|
|
558
|
-
| Prop | Type | Default | Description |
|
|
559
|
-
|------|------|---------|-------------|
|
|
560
|
-
| `trigger` | `ReactNode` | — | **Required.** Trigger element |
|
|
561
|
-
| `children` | `ReactNode` | — | Popover content |
|
|
562
|
-
| `open` | `boolean` | — | Controlled open state |
|
|
563
|
-
| `onOpenChange` | `(open: boolean) => void` | — | Open state change |
|
|
564
|
-
| `side` | `"top" \| "right" \| "bottom" \| "left"` | — | Preferred side |
|
|
565
|
-
| `sideOffset` | `number` | `5` | Distance from trigger |
|
|
566
|
-
| `align` | `"start" \| "center" \| "end"` | — | Alignment |
|
|
567
|
-
| `enabled` | `boolean` | `true` | When false, renders trigger only |
|
|
568
|
-
| `modal` | `boolean` | `false` | Modal behavior |
|
|
569
|
-
|
|
570
|
-
```tsx
|
|
571
|
-
import { Popover, Button, Typography } from "@rebasepro/ui";
|
|
572
|
-
|
|
573
|
-
<Popover
|
|
574
|
-
trigger={<Button variant="outlined">Options</Button>}
|
|
575
|
-
side="bottom"
|
|
576
|
-
align="start"
|
|
577
|
-
>
|
|
578
|
-
<div className="p-4">
|
|
579
|
-
<Typography variant="body2">Popover content</Typography>
|
|
580
|
-
</div>
|
|
581
|
-
</Popover>
|
|
582
|
-
```
|
|
583
|
-
|
|
584
|
-
### ExpandablePanel
|
|
585
|
-
|
|
586
|
-
Collapsible panel with animated open/close.
|
|
587
|
-
|
|
588
|
-
| Prop | Type | Default | Description |
|
|
589
|
-
|------|------|---------|-------------|
|
|
590
|
-
| `title` | `ReactNode` | — | **Required.** Panel header |
|
|
591
|
-
| `initiallyExpanded` | `boolean` | `true` | Initial open state |
|
|
592
|
-
| `expanded` | `boolean` | — | Controlled open state |
|
|
593
|
-
| `onExpandedChange` | `(expanded: boolean) => void` | — | Expansion change callback |
|
|
594
|
-
| `invisible` | `boolean` | `false` | Remove border, use border-bottom only |
|
|
595
|
-
| `asField` | `boolean` | — | Apply field background styling |
|
|
596
|
-
| `className` | `string` | — | Root container class |
|
|
597
|
-
| `innerClassName` | `string` | — | Content wrapper class |
|
|
598
|
-
| `titleClassName` | `string` | — | Trigger header class |
|
|
599
|
-
|
|
600
|
-
```tsx
|
|
601
|
-
import { ExpandablePanel, Typography } from "@rebasepro/ui";
|
|
602
|
-
|
|
603
|
-
<ExpandablePanel title={<Typography variant="subtitle2">Advanced Options</Typography>}>
|
|
604
|
-
<div className="p-4">
|
|
605
|
-
{/* panel content */}
|
|
606
|
-
</div>
|
|
607
|
-
</ExpandablePanel>
|
|
608
|
-
|
|
609
|
-
{/* Controlled, initially collapsed */}
|
|
610
|
-
<ExpandablePanel
|
|
611
|
-
title="Filters"
|
|
612
|
-
initiallyExpanded={false}
|
|
613
|
-
invisible
|
|
614
|
-
asField
|
|
615
|
-
>
|
|
616
|
-
{/* filter form fields */}
|
|
617
|
-
</ExpandablePanel>
|
|
618
|
-
```
|
|
619
|
-
|
|
620
|
-
### BooleanSwitch
|
|
621
|
-
|
|
622
|
-
Standalone toggle switch.
|
|
623
|
-
|
|
624
|
-
| Prop | Type | Default | Description |
|
|
625
|
-
|------|------|---------|-------------|
|
|
626
|
-
| `value` | `boolean \| null` | — | Current value |
|
|
627
|
-
| `onValueChange` | `(value: boolean) => void` | — | Change callback |
|
|
628
|
-
| `disabled` | `boolean` | `false` | Disabled state |
|
|
629
|
-
| `size` | `"smallest" \| "small" \| "medium" \| "large"` | `"medium"` | Size preset |
|
|
630
|
-
| `allowIndeterminate` | `boolean` | `false` | Allow null (three-state) |
|
|
631
|
-
|
|
632
|
-
### BooleanSwitchWithLabel
|
|
633
|
-
|
|
634
|
-
Toggle switch with a label. Wraps `BooleanSwitch`.
|
|
635
|
-
|
|
636
|
-
| Prop | Type | Default | Description |
|
|
637
|
-
|------|------|---------|-------------|
|
|
638
|
-
| `label` | `ReactNode` | — | Label text |
|
|
639
|
-
| `position` | `"start" \| "end"` | `"end"` | Label position relative to switch |
|
|
640
|
-
| `invisible` | `boolean` | — | Remove field background |
|
|
641
|
-
| `error` | `boolean` | — | Error state |
|
|
642
|
-
| `fullWidth` | `boolean` | `true` | Full width |
|
|
643
|
-
| `size` | `"smallest" \| "small" \| "medium" \| "large"` | `"medium"` | Size |
|
|
644
|
-
| _...all BooleanSwitchProps_ | | | |
|
|
645
|
-
|
|
646
|
-
```tsx
|
|
647
|
-
import { BooleanSwitchWithLabel } from "@rebasepro/ui";
|
|
648
|
-
|
|
649
|
-
<BooleanSwitchWithLabel
|
|
650
|
-
value={isEnabled}
|
|
651
|
-
onValueChange={setIsEnabled}
|
|
652
|
-
label="Enable notifications"
|
|
653
|
-
size="medium"
|
|
654
|
-
/>
|
|
655
|
-
```
|
|
656
|
-
|
|
657
|
-
### Checkbox
|
|
658
|
-
|
|
659
|
-
Styled checkbox based on Radix Checkbox. See source for full props.
|
|
660
|
-
|
|
661
|
-
### RadioGroup, RadioGroupItem
|
|
662
|
-
|
|
663
|
-
Radio button group built on Radix RadioGroup.
|
|
664
|
-
|
|
665
|
-
| Prop (RadioGroup) | Type | Default | Description |
|
|
666
|
-
|------|------|---------|-------------|
|
|
667
|
-
| `value` | `string` | — | Selected value |
|
|
668
|
-
| `onValueChange` | `(value: string) => void` | — | Change callback |
|
|
669
|
-
| `disabled` | `boolean` | — | Disabled |
|
|
670
|
-
| `loop` | `boolean` | `false` | Keyboard navigation loops |
|
|
671
|
-
|
|
672
|
-
```tsx
|
|
673
|
-
import { RadioGroup, RadioGroupItem } from "@rebasepro/ui";
|
|
674
|
-
|
|
675
|
-
<RadioGroup value={plan} onValueChange={setPlan}>
|
|
676
|
-
<div className="flex items-center gap-2">
|
|
677
|
-
<RadioGroupItem value="free" />
|
|
678
|
-
<label>Free</label>
|
|
679
|
-
</div>
|
|
680
|
-
<div className="flex items-center gap-2">
|
|
681
|
-
<RadioGroupItem value="pro" />
|
|
682
|
-
<label>Pro</label>
|
|
683
|
-
</div>
|
|
684
|
-
</RadioGroup>
|
|
685
|
-
```
|
|
686
|
-
|
|
687
|
-
### Slider
|
|
688
|
-
|
|
689
|
-
Range slider with tooltip, built on Radix Slider.
|
|
690
|
-
|
|
691
|
-
| Prop | Type | Default | Description |
|
|
692
|
-
|------|------|---------|-------------|
|
|
693
|
-
| `value` | `number[]` | — | Current value(s) |
|
|
694
|
-
| `onValueChange` | `(value: number[]) => void` | — | Live change |
|
|
695
|
-
| `onValueCommit` | `(value: number[]) => void` | — | Change on release |
|
|
696
|
-
| `min` | `number` | — | Minimum |
|
|
697
|
-
| `max` | `number` | — | Maximum |
|
|
698
|
-
| `step` | `number` | — | Step size |
|
|
699
|
-
| `disabled` | `boolean` | — | Disabled |
|
|
700
|
-
| `size` | `"small" \| "regular"` | `"regular"` | Track/thumb size |
|
|
701
|
-
|
|
702
|
-
```tsx
|
|
703
|
-
import { Slider } from "@rebasepro/ui";
|
|
704
|
-
|
|
705
|
-
<Slider
|
|
706
|
-
value={[volume]}
|
|
707
|
-
onValueChange={([v]) => setVolume(v)}
|
|
708
|
-
min={0}
|
|
709
|
-
max={100}
|
|
710
|
-
step={1}
|
|
711
|
-
/>
|
|
712
|
-
```
|
|
713
|
-
|
|
714
|
-
### DateTimeField
|
|
715
|
-
|
|
716
|
-
Date/datetime picker using native `<input type="date|datetime-local">`.
|
|
717
|
-
|
|
718
|
-
| Prop | Type | Default | Description |
|
|
719
|
-
|------|------|---------|-------------|
|
|
720
|
-
| `value` | `Date \| null` | — | Date value |
|
|
721
|
-
| `onChange` | `(date: Date \| null) => void` | — | Change callback |
|
|
722
|
-
| `mode` | `"date" \| "date_time"` | `"date"` | Date only or datetime |
|
|
723
|
-
| `disabled` | `boolean` | — | Disabled |
|
|
724
|
-
| `clearable` | `boolean` | — | Show clear button |
|
|
725
|
-
| `error` | `boolean` | — | Error state |
|
|
726
|
-
| `size` | `"smallest" \| "small" \| "medium" \| "large"` | `"large"` | Size |
|
|
727
|
-
| `label` | `ReactNode` | — | Floating label |
|
|
728
|
-
| `timezone` | `string` | local | IANA timezone string |
|
|
729
|
-
|
|
730
|
-
```tsx
|
|
731
|
-
import { DateTimeField } from "@rebasepro/ui";
|
|
732
|
-
|
|
733
|
-
<DateTimeField
|
|
734
|
-
value={dueDate}
|
|
735
|
-
onChange={setDueDate}
|
|
736
|
-
mode="date_time"
|
|
737
|
-
label="Due Date"
|
|
738
|
-
clearable
|
|
739
|
-
timezone="America/New_York"
|
|
740
|
-
/>
|
|
741
|
-
```
|
|
742
|
-
|
|
743
|
-
### ColorPicker
|
|
744
|
-
|
|
745
|
-
Grid of color swatches using `CHIP_COLORS`. For selecting colors for enum values and tags.
|
|
746
|
-
|
|
747
|
-
| Prop | Type | Default | Description |
|
|
748
|
-
|------|------|---------|-------------|
|
|
749
|
-
| `value` | `ChipColorKey` | — | Selected color key |
|
|
750
|
-
| `onChange` | `(key: ChipColorKey \| undefined) => void` | — | Change callback |
|
|
751
|
-
| `size` | `"small" \| "medium"` | `"medium"` | Swatch size |
|
|
752
|
-
| `allowClear` | `boolean` | `true` | Show "Auto" clear option |
|
|
753
|
-
| `disabled` | `boolean` | `false` | Disabled |
|
|
754
|
-
|
|
755
|
-
```tsx
|
|
756
|
-
import { ColorPicker } from "@rebasepro/ui";
|
|
757
|
-
|
|
758
|
-
<ColorPicker value={color} onChange={setColor} />
|
|
759
|
-
```
|
|
760
|
-
|
|
761
|
-
### FileUpload
|
|
762
|
-
|
|
763
|
-
Drag-and-drop file upload zone using `react-dropzone`.
|
|
764
|
-
|
|
765
|
-
| Prop | Type | Default | Description |
|
|
766
|
-
|------|------|---------|-------------|
|
|
767
|
-
| `onFilesAdded` | `(files: File[]) => void` | — | **Required.** Files accepted callback |
|
|
768
|
-
| `onFilesRejected` | handler | — | Files rejected callback |
|
|
769
|
-
| `accept` | `Record<string, string[]>` | — | MIME type filter, e.g. `{ "image/*": [] }` |
|
|
770
|
-
| `maxSize` | `number` | — | Max file size in bytes |
|
|
771
|
-
| `maxFiles` | `number` | — | Max number of files |
|
|
772
|
-
| `disabled` | `boolean` | — | Disabled |
|
|
773
|
-
| `title` | `ReactNode` | — | Top-left caption |
|
|
774
|
-
| `uploadDescription` | `ReactNode` | — | Center description |
|
|
775
|
-
| `size` | `"small" \| "medium" \| "large"` | — | Height: 64/112/176 px |
|
|
776
|
-
|
|
777
|
-
```tsx
|
|
778
|
-
import { FileUpload } from "@rebasepro/ui";
|
|
779
|
-
|
|
780
|
-
<FileUpload
|
|
781
|
-
accept={{ "image/*": [] }}
|
|
782
|
-
onFilesAdded={(files) => handleUpload(files)}
|
|
783
|
-
title="Cover Image"
|
|
784
|
-
uploadDescription="Drop an image or click to browse"
|
|
785
|
-
size="medium"
|
|
786
|
-
/>
|
|
787
|
-
```
|
|
788
|
-
|
|
789
|
-
### SearchBar
|
|
790
|
-
|
|
791
|
-
Debounced search input with clear button and loading state.
|
|
792
|
-
|
|
793
|
-
| Prop | Type | Default | Description |
|
|
794
|
-
|------|------|---------|-------------|
|
|
795
|
-
| `onTextSearch` | `(searchString?: string) => void` | — | Debounced search callback |
|
|
796
|
-
| `placeholder` | `string` | `"Search"` | Placeholder text |
|
|
797
|
-
| `size` | `"smallest" \| "small" \| "medium"` | `"medium"` | Height preset |
|
|
798
|
-
| `expandable` | `boolean` | `false` | Expand on focus |
|
|
799
|
-
| `loading` | `boolean` | — | Show spinner instead of icon |
|
|
800
|
-
| `disabled` | `boolean` | — | Disabled |
|
|
801
|
-
| `autoFocus` | `boolean` | — | Auto focus |
|
|
802
|
-
| `initialValue` | `string` | — | Initial search text |
|
|
803
|
-
|
|
804
|
-
```tsx
|
|
805
|
-
import { SearchBar } from "@rebasepro/ui";
|
|
806
|
-
|
|
807
|
-
<SearchBar
|
|
808
|
-
onTextSearch={(term) => filterItems(term)}
|
|
809
|
-
placeholder="Search items..."
|
|
810
|
-
size="small"
|
|
811
|
-
/>
|
|
812
|
-
```
|
|
813
|
-
|
|
814
|
-
### Table, TableHeader, TableBody, TableRow, TableCell
|
|
815
|
-
|
|
816
|
-
Basic HTML table components with consistent styling.
|
|
817
|
-
|
|
818
|
-
```tsx
|
|
819
|
-
import { Table, TableHeader, TableBody, TableRow, TableCell } from "@rebasepro/ui";
|
|
820
|
-
|
|
821
|
-
<Table>
|
|
822
|
-
<TableHeader>
|
|
823
|
-
<TableCell header>Name</TableCell>
|
|
824
|
-
<TableCell header>Email</TableCell>
|
|
825
|
-
<TableCell header align="right">Actions</TableCell>
|
|
826
|
-
</TableHeader>
|
|
827
|
-
<TableBody>
|
|
828
|
-
{users.map(user => (
|
|
829
|
-
<TableRow key={user.id} onClick={() => selectUser(user)}>
|
|
830
|
-
<TableCell>{user.name}</TableCell>
|
|
831
|
-
<TableCell>{user.email}</TableCell>
|
|
832
|
-
<TableCell align="right">
|
|
833
|
-
<IconButton aria-label="Edit"><PencilIcon size={16} /></IconButton>
|
|
834
|
-
</TableCell>
|
|
835
|
-
</TableRow>
|
|
836
|
-
))}
|
|
837
|
-
</TableBody>
|
|
838
|
-
</Table>
|
|
839
|
-
```
|
|
840
|
-
|
|
841
|
-
**TableCell extra props:** `header` (boolean), `align` (`"left" | "center" | "right"`), `colspan` (number).
|
|
842
|
-
|
|
843
|
-
### VirtualTable
|
|
844
|
-
|
|
845
|
-
High-performance virtualized table for large datasets. Uses `react-window` for windowed rendering. Supports sorting, filtering, column resize, drag-and-drop column reorder, infinite scroll, and frozen columns.
|
|
846
|
-
|
|
847
|
-
Key props: `data`, `columns` (array of `VirtualTableColumn`), `cellRenderer`, `onRowClick`, `onEndReached`, `filter`, `onFilterUpdate`, `sortBy`, `onSortByUpdate`, `loading`, `emptyComponent`.
|
|
848
|
-
|
|
849
|
-
See `VirtualTableProps` and `VirtualTableColumn` types for full API.
|
|
850
|
-
|
|
851
|
-
### ToggleButtonGroup
|
|
852
|
-
|
|
853
|
-
Single-select button group for toggling between options.
|
|
854
|
-
|
|
855
|
-
| Prop | Type | Default | Description |
|
|
856
|
-
|------|------|---------|-------------|
|
|
857
|
-
| `value` | `T extends string` | — | Selected value |
|
|
858
|
-
| `onValueChange` | `(value: T) => void` | — | Change callback |
|
|
859
|
-
| `options` | `ToggleButtonOption<T>[]` | — | Array of `{ value, label, icon?, disabled? }` |
|
|
860
|
-
| `className` | `string` | — | Extra classes |
|
|
861
|
-
|
|
862
|
-
```tsx
|
|
863
|
-
import { ToggleButtonGroup } from "@rebasepro/ui";
|
|
864
|
-
import { LayoutGridIcon, ListIcon } from "@rebasepro/ui";
|
|
865
|
-
|
|
866
|
-
<ToggleButtonGroup
|
|
867
|
-
value={viewMode}
|
|
868
|
-
onValueChange={setViewMode}
|
|
869
|
-
options={[
|
|
870
|
-
{ value: "grid", label: "Grid", icon: <LayoutGridIcon size={16} /> },
|
|
871
|
-
{ value: "list", label: "List", icon: <ListIcon size={16} /> }
|
|
872
|
-
]}
|
|
873
|
-
/>
|
|
874
|
-
```
|
|
875
|
-
|
|
876
|
-
### ResizablePanels
|
|
877
|
-
|
|
878
|
-
Two-panel resizable layout with drag handle.
|
|
879
|
-
|
|
880
|
-
| Prop | Type | Default | Description |
|
|
881
|
-
|------|------|---------|-------------|
|
|
882
|
-
| `firstPanel` | `ReactNode` | — | First panel content |
|
|
883
|
-
| `secondPanel` | `ReactNode` | — | Second panel content |
|
|
884
|
-
| `panelSizePercent` | `number` | — | 0–100, width/height of first panel |
|
|
885
|
-
| `onPanelSizeChange` | `(percent: number) => void` | — | Resize callback |
|
|
886
|
-
| `showFirstPanel` | `boolean` | `true` | Toggle first panel visibility |
|
|
887
|
-
| `showSecondPanel` | `boolean` | `true` | Toggle second panel visibility |
|
|
888
|
-
| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Layout direction |
|
|
889
|
-
| `minPanelSizePx` | `number` | `200` | Minimum panel size in pixels |
|
|
890
|
-
| `animateLayout` | `boolean` | `true` | Animate transitions |
|
|
891
|
-
| `stacked` | `boolean` | `false` | Stack panels absolutely |
|
|
892
|
-
|
|
893
|
-
```tsx
|
|
894
|
-
import { ResizablePanels } from "@rebasepro/ui";
|
|
895
|
-
|
|
896
|
-
<ResizablePanels
|
|
897
|
-
firstPanel={<Sidebar />}
|
|
898
|
-
secondPanel={<MainContent />}
|
|
899
|
-
panelSizePercent={30}
|
|
900
|
-
onPanelSizeChange={setPanelSize}
|
|
901
|
-
minPanelSizePx={250}
|
|
902
|
-
/>
|
|
903
|
-
```
|
|
904
|
-
|
|
905
|
-
### CircularProgress
|
|
906
|
-
|
|
907
|
-
Animated loading spinner.
|
|
908
|
-
|
|
909
|
-
| Prop | Type | Default | Description |
|
|
910
|
-
|------|------|---------|-------------|
|
|
911
|
-
| `size` | `"smallest" \| "small" \| "medium" \| "large"` | — | Size preset |
|
|
912
|
-
|
|
913
|
-
### CircularProgressCenter
|
|
914
|
-
|
|
915
|
-
Full-screen centered loading spinner with optional text message.
|
|
916
|
-
|
|
917
|
-
| Prop | Type | Default | Description |
|
|
918
|
-
|------|------|---------|-------------|
|
|
919
|
-
| `text` | `string` | — | Loading message below spinner |
|
|
920
|
-
| _...CircularProgressProps_ | | | |
|
|
921
|
-
|
|
922
|
-
```tsx
|
|
923
|
-
import { CircularProgressCenter } from "@rebasepro/ui";
|
|
924
|
-
|
|
925
|
-
<CircularProgressCenter text="Loading data..." />
|
|
926
|
-
```
|
|
927
|
-
|
|
928
|
-
### ErrorBoundary
|
|
929
|
-
|
|
930
|
-
React error boundary with inline or full-page error display. Detects permission errors for tailored messaging.
|
|
931
|
-
|
|
932
|
-
| Prop | Type | Default | Description |
|
|
933
|
-
|------|------|---------|-------------|
|
|
934
|
-
| `fullPage` | `boolean` | — | Full-page centered error display |
|
|
935
|
-
| `onReset` | `() => void` | — | Custom reset handler |
|
|
936
|
-
|
|
937
|
-
```tsx
|
|
938
|
-
import { ErrorBoundary } from "@rebasepro/ui";
|
|
939
|
-
|
|
940
|
-
<ErrorBoundary fullPage>
|
|
941
|
-
<App />
|
|
942
|
-
</ErrorBoundary>
|
|
943
|
-
```
|
|
944
|
-
|
|
945
|
-
### Tooltip
|
|
946
|
-
|
|
947
|
-
Tooltip on hover, built on Radix Tooltip.
|
|
948
|
-
|
|
949
|
-
| Prop | Type | Default | Description |
|
|
950
|
-
|------|------|---------|-------------|
|
|
951
|
-
| `title` | `string \| ReactNode` | — | Tooltip content. If falsy, renders children only |
|
|
952
|
-
| `side` | `"top" \| "bottom" \| "left" \| "right"` | `"bottom"` | Tooltip position |
|
|
953
|
-
| `delayDuration` | `number` | `200` | Delay in ms |
|
|
954
|
-
| `sideOffset` | `number` | `4` | Distance from trigger |
|
|
955
|
-
| `align` | `"start" \| "center" \| "end"` | — | Alignment |
|
|
956
|
-
|
|
957
|
-
```tsx
|
|
958
|
-
import { Tooltip, IconButton } from "@rebasepro/ui";
|
|
959
|
-
import { SettingsIcon } from "@rebasepro/ui";
|
|
960
|
-
|
|
961
|
-
<Tooltip title="Open settings" side="bottom">
|
|
962
|
-
<IconButton aria-label="Settings">
|
|
963
|
-
<SettingsIcon size={20} />
|
|
964
|
-
</IconButton>
|
|
965
|
-
</Tooltip>
|
|
966
|
-
```
|
|
967
|
-
|
|
968
|
-
### Other Components
|
|
969
|
-
|
|
970
|
-
| Component | Description |
|
|
971
|
-
|-----------|-------------|
|
|
972
|
-
| `Autocomplete` | Text input with filtered suggestions dropdown |
|
|
973
|
-
| `Avatar` | User avatar circle with image/initials |
|
|
974
|
-
| `Badge` | Small count badge |
|
|
975
|
-
| `Collapse` | Animated show/hide wrapper |
|
|
976
|
-
| `InputLabel` | Floating label used internally by `TextField`. Props: `shrink` |
|
|
977
|
-
| `SelectInputLabel` | Small label above Select/MultiSelect. Props: `error` |
|
|
978
|
-
| `InfoLabel` | Small info label |
|
|
979
|
-
| `Label` | Form label |
|
|
980
|
-
| `Markdown` | Markdown renderer |
|
|
981
|
-
| `Menu` | Context menu |
|
|
982
|
-
| `Menubar` | Horizontal menu bar |
|
|
983
|
-
| `MenuItem` | Menu item |
|
|
984
|
-
| `Paper` | Bordered container |
|
|
985
|
-
| `Separator` | Horizontal/vertical divider |
|
|
986
|
-
| `Skeleton` | Loading placeholder |
|
|
987
|
-
| `TextareaAutosize` | Auto-growing textarea |
|
|
988
|
-
|
|
989
|
-
### Re-exported Radix Primitives
|
|
990
|
-
|
|
991
|
-
These are re-exported so you never need a direct `@radix-ui` dependency:
|
|
992
|
-
|
|
993
|
-
```tsx
|
|
994
|
-
import { Portal, PopoverPrimitive, Slot } from "@rebasepro/ui";
|
|
995
|
-
```
|
|
996
|
-
|
|
997
|
-
- **`Portal`** — `@radix-ui/react-portal`
|
|
998
|
-
- **`PopoverPrimitive`** — `@radix-ui/react-popover` (full primitive API)
|
|
999
|
-
- **`Slot`** — `@radix-ui/react-slot` (for composition)
|
|
1000
|
-
|
|
1001
|
-
---
|
|
1002
|
-
|
|
1003
|
-
## Icon System
|
|
1004
|
-
|
|
1005
|
-
> **WARNING FOR AGENTS:** There are NO `ArrowForwardIcon` or `AddIcon` exports. Use real Lucide icon names: `ArrowRightIcon`, `PlusIcon`, etc.
|
|
1006
|
-
|
|
1007
|
-
### Using Icons
|
|
1008
|
-
|
|
1009
|
-
Icons are re-exported from `lucide-react`. Use the `iconSize` map for consistent sizing:
|
|
1010
|
-
|
|
1011
|
-
```tsx
|
|
1012
|
-
import { PlusIcon, SettingsIcon, Trash2Icon, iconSize } from "@rebasepro/ui";
|
|
1013
|
-
|
|
1014
|
-
// Use iconSize for consistent sizing
|
|
1015
|
-
<PlusIcon size={iconSize.small} /> // 20px
|
|
1016
|
-
<SettingsIcon size={iconSize.medium} /> // 24px
|
|
1017
|
-
<Trash2Icon size={iconSize.large} /> // 28px
|
|
1018
|
-
```
|
|
1019
|
-
|
|
1020
|
-
### `iconSize` Map
|
|
1021
|
-
|
|
1022
|
-
| Key | Value (px) |
|
|
1023
|
-
|-----|-----------|
|
|
1024
|
-
| `smallest` | `16` |
|
|
1025
|
-
| `small` | `20` |
|
|
1026
|
-
| `medium` | `24` |
|
|
1027
|
-
| `large` | `28` |
|
|
1028
|
-
|
|
1029
|
-
### `IconProps` Type
|
|
1030
|
-
|
|
1031
|
-
| Prop | Type | Description |
|
|
1032
|
-
|------|------|-------------|
|
|
1033
|
-
| `size` | `IconSize \| number` | Size in px |
|
|
1034
|
-
| `color` | `IconColor` | `"inherit" \| "primary" \| "secondary" \| "disabled" \| "error" \| "success" \| "warning"` |
|
|
1035
|
-
| `className` | `string` | Extra classes |
|
|
1036
|
-
|
|
1037
|
-
### `colorClassesMapping`
|
|
1038
|
-
|
|
1039
|
-
Maps `IconColor` values to Tailwind classes:
|
|
1040
|
-
|
|
1041
|
-
| Color | Class |
|
|
1042
|
-
|-------|-------|
|
|
1043
|
-
| `"primary"` | `text-primary` |
|
|
1044
|
-
| `"secondary"` | `text-secondary` |
|
|
1045
|
-
| `"error"` | `text-red-500` |
|
|
1046
|
-
| `"success"` | `text-green-500` |
|
|
1047
|
-
| `"warning"` | `text-yellow-500` |
|
|
1048
|
-
| `"disabled"` | `text-text-disabled dark:text-text-disabled-dark` |
|
|
1049
|
-
| `"inherit"` | _(none)_ |
|
|
1050
|
-
|
|
1051
|
-
### `lucideIcons` — Full Icon Map
|
|
1052
|
-
|
|
1053
|
-
```tsx
|
|
1054
|
-
import { lucideIcons } from "@rebasepro/ui";
|
|
1055
|
-
|
|
1056
|
-
// Dynamic lookup by string name
|
|
1057
|
-
const IconComponent = lucideIcons["Database"]; // LucideIcon component
|
|
1058
|
-
<IconComponent size={24} />
|
|
1059
|
-
```
|
|
1060
|
-
|
|
1061
|
-
### `icon_keys` and `cool_icon_keys`
|
|
1062
|
-
|
|
1063
|
-
- **`icon_keys`** — Array of ~1900+ all available Lucide icon name strings.
|
|
1064
|
-
- **`cool_icon_keys`** — Curated subset of ~50 visually distinctive icon names for icon pickers.
|
|
1065
|
-
|
|
1066
|
-
```tsx
|
|
1067
|
-
import { icon_keys, coolIconKeys, lucideIcons } from "@rebasepro/ui";
|
|
1068
|
-
```
|
|
1069
|
-
|
|
1070
|
-
### `keyToIconComponent(key: string): string`
|
|
1071
|
-
|
|
1072
|
-
Converts a snake_case icon key to a PascalCase component name with `Icon` suffix:
|
|
1073
|
-
|
|
1074
|
-
```tsx
|
|
1075
|
-
import { keyToIconComponent } from "@rebasepro/ui";
|
|
1076
|
-
|
|
1077
|
-
keyToIconComponent("arrow_right"); // "ArrowRightIcon"
|
|
1078
|
-
keyToIconComponent("database"); // "DatabaseIcon"
|
|
1079
|
-
```
|
|
1080
|
-
|
|
1081
|
-
### Custom Icons
|
|
1082
|
-
|
|
1083
|
-
- **`GitHubIcon`** — GitHub logo SVG
|
|
1084
|
-
- **`HandleIcon`** — Drag handle dots
|
|
1085
|
-
|
|
1086
|
-
```tsx
|
|
1087
|
-
import { GitHubIcon, HandleIcon } from "@rebasepro/ui";
|
|
1088
|
-
```
|
|
1089
|
-
|
|
1090
|
-
---
|
|
1091
|
-
|
|
1092
|
-
## Style Mixins
|
|
1093
|
-
|
|
1094
|
-
Exported Tailwind class strings for consistent styling. Import and use with `cls()`:
|
|
1095
|
-
|
|
1096
|
-
```tsx
|
|
1097
|
-
import {
|
|
1098
|
-
focusedClasses,
|
|
1099
|
-
focusedDisabled,
|
|
1100
|
-
focusedInvisibleMixin,
|
|
1101
|
-
fieldBackgroundMixin,
|
|
1102
|
-
fieldBackgroundInvisibleMixin,
|
|
1103
|
-
fieldBackgroundDisabledMixin,
|
|
1104
|
-
fieldBackgroundHoverMixin,
|
|
1105
|
-
defaultBorderMixin,
|
|
1106
|
-
paperMixin,
|
|
1107
|
-
cardMixin,
|
|
1108
|
-
cardClickableMixin,
|
|
1109
|
-
cardSelectedMixin
|
|
1110
|
-
} from "@rebasepro/ui";
|
|
1111
|
-
```
|
|
1112
|
-
|
|
1113
|
-
| Mixin | Purpose |
|
|
1114
|
-
|-------|---------|
|
|
1115
|
-
| `focusedClasses` | Focus ring: `ring-2 ring-primary ring-opacity-75` |
|
|
1116
|
-
| `focusedDisabled` | Remove focus ring: `focus-visible:ring-0` |
|
|
1117
|
-
| `focusedInvisibleMixin` | Focus bg for invisible fields |
|
|
1118
|
-
| `fieldBackgroundMixin` | Default field background (light/dark) |
|
|
1119
|
-
| `fieldBackgroundInvisibleMixin` | Transparent field background |
|
|
1120
|
-
| `fieldBackgroundDisabledMixin` | Disabled field background |
|
|
1121
|
-
| `fieldBackgroundHoverMixin` | Field hover background |
|
|
1122
|
-
| `defaultBorderMixin` | Standard border: `border-surface-200/60 dark:border-surface-700/60` |
|
|
1123
|
-
| `paperMixin` | Paper container: white bg, rounded-md, border |
|
|
1124
|
-
| `cardMixin` | Card container: white/dark bg, rounded-md, border, margin |
|
|
1125
|
-
| `cardClickableMixin` | Hover/click effects for interactive cards |
|
|
1126
|
-
| `cardSelectedMixin` | Selected card highlight: `bg-primary-bg/30 ring-1 ring-primary/75` |
|
|
1127
|
-
|
|
1128
|
-
```tsx
|
|
1129
|
-
import { cls, paperMixin, cardClickableMixin } from "@rebasepro/ui";
|
|
1130
|
-
|
|
1131
|
-
<div className={cls(paperMixin, "p-4")}>Paper-styled container</div>
|
|
1132
|
-
```
|
|
1133
|
-
|
|
1134
|
-
---
|
|
1135
|
-
|
|
1136
|
-
## Utility Functions
|
|
1137
|
-
|
|
1138
|
-
### `cls(...classes)`
|
|
1139
|
-
|
|
1140
|
-
Combines `clsx` + `twMerge` for conditional class merging with Tailwind conflict resolution.
|
|
1141
|
-
|
|
1142
|
-
```tsx
|
|
1143
|
-
import { cls } from "@rebasepro/ui";
|
|
1144
|
-
|
|
1145
|
-
<div className={cls(
|
|
1146
|
-
"p-4 rounded-lg",
|
|
1147
|
-
isActive && "bg-blue-500",
|
|
1148
|
-
isDisabled && "opacity-50 cursor-not-allowed"
|
|
1149
|
-
)} />
|
|
1150
|
-
```
|
|
1151
|
-
|
|
1152
|
-
### `debounce(func, wait?)`
|
|
1153
|
-
|
|
1154
|
-
General-purpose debounce function. Returns a debounced function with a `.clear()` method.
|
|
1155
|
-
|
|
1156
|
-
| Param | Type | Default | Description |
|
|
1157
|
-
|-------|------|---------|-------------|
|
|
1158
|
-
| `func` | `Function` | — | Function to debounce |
|
|
1159
|
-
| `wait` | `number` | `166` | Delay in ms |
|
|
1160
|
-
|
|
1161
|
-
```tsx
|
|
1162
|
-
import { debounce } from "@rebasepro/ui";
|
|
1163
|
-
|
|
1164
|
-
const debouncedSearch = debounce((query: string) => {
|
|
1165
|
-
fetchResults(query);
|
|
1166
|
-
}, 300);
|
|
1167
|
-
|
|
1168
|
-
debouncedSearch("hello");
|
|
1169
|
-
debouncedSearch.clear(); // Cancel pending call
|
|
1170
|
-
```
|
|
1171
|
-
|
|
1172
|
-
### `hashString(str)`
|
|
1173
|
-
|
|
1174
|
-
Deterministic 32-bit hash of a string. Returns a positive integer.
|
|
1175
|
-
|
|
1176
|
-
```tsx
|
|
1177
|
-
import { hashString } from "@rebasepro/ui";
|
|
1178
|
-
hashString("my-entity-id"); // e.g. 1234567
|
|
1179
|
-
```
|
|
1180
|
-
|
|
1181
|
-
### Chip Color Utilities
|
|
1182
|
-
|
|
1183
|
-
```tsx
|
|
1184
|
-
import {
|
|
1185
|
-
CHIP_COLORS, // Record<string, ChipColorScheme>
|
|
1186
|
-
getColorSchemeForKey, // (key: ChipColorKey) => ChipColorScheme
|
|
1187
|
-
getColorSchemeForSeed // (seed: string) => ChipColorScheme (deterministic)
|
|
1188
|
-
} from "@rebasepro/ui";
|
|
1189
|
-
```
|
|
1190
|
-
|
|
1191
|
-
**`ChipColorScheme`** type:
|
|
1192
|
-
```ts
|
|
1193
|
-
{
|
|
1194
|
-
color: string; // Light mode background hex
|
|
1195
|
-
text: string; // Light mode text hex
|
|
1196
|
-
darkColor?: string; // Dark mode background hex
|
|
1197
|
-
darkText?: string; // Dark mode text hex
|
|
1198
|
-
}
|
|
1199
|
-
```
|
|
1200
|
-
|
|
1201
|
-
**Available CHIP_COLORS keys:** `blue`, `teal`, `yellow`, `pink`, `purple`, `cyan`, `orange`, `green`, `red`, `gray`, `indigo`, `violet`, `fuchsia`, `rose`, `emerald`
|
|
1202
|
-
|
|
1203
|
-
```tsx
|
|
1204
|
-
// Deterministic color from any string
|
|
1205
|
-
const scheme = getColorSchemeForSeed("user-status-active");
|
|
1206
|
-
<Chip colorScheme={scheme}>Active</Chip>
|
|
1207
|
-
|
|
1208
|
-
// Or by key
|
|
1209
|
-
<Chip colorScheme="blue">Info</Chip>
|
|
1210
|
-
```
|
|
1211
|
-
|
|
1212
|
-
---
|
|
1213
|
-
|
|
1214
|
-
## Hooks
|
|
1215
|
-
|
|
1216
|
-
### `useInjectStyles(key, styles)`
|
|
1217
|
-
|
|
1218
|
-
Injects a `<style>` element into the DOM (idempotent). Respects `PortalContainerContext`.
|
|
1219
|
-
|
|
1220
|
-
```tsx
|
|
1221
|
-
import { useInjectStyles } from "@rebasepro/ui";
|
|
1222
|
-
|
|
1223
|
-
useInjectStyles("MyComponent", `
|
|
1224
|
-
.my-animation { animation: fadeIn 200ms ease-out; }
|
|
1225
|
-
`);
|
|
1226
|
-
```
|
|
1227
|
-
|
|
1228
|
-
### `useOutsideAlerter(ref, onOutsideClick, active?)`
|
|
1229
|
-
|
|
1230
|
-
Calls `onOutsideClick` when a click occurs outside the referenced element. Ignores clicks inside Radix presentation layers.
|
|
1231
|
-
|
|
1232
|
-
```tsx
|
|
1233
|
-
import { useOutsideAlerter } from "@rebasepro/ui";
|
|
1234
|
-
|
|
1235
|
-
const ref = useRef<HTMLDivElement>(null);
|
|
1236
|
-
useOutsideAlerter(ref, () => setOpen(false), isOpen);
|
|
1237
|
-
```
|
|
1238
|
-
|
|
1239
|
-
### `useDebouncedCallback(value, callback, immediate, timeoutMs?)`
|
|
1240
|
-
|
|
1241
|
-
Debounces a callback that fires when `value` changes.
|
|
1242
|
-
|
|
1243
|
-
| Param | Type | Default | Description |
|
|
1244
|
-
|-------|------|---------|-------------|
|
|
1245
|
-
| `value` | `T` | — | Watched value |
|
|
1246
|
-
| `callback` | `() => void` | — | Callback to debounce |
|
|
1247
|
-
| `immediate` | `boolean` | — | If true, flush immediately |
|
|
1248
|
-
| `timeoutMs` | `number` | `300` | Debounce delay |
|
|
1249
|
-
|
|
1250
|
-
### `useDebounceCallback(callback?, delay?)`
|
|
1251
|
-
|
|
1252
|
-
Returns a debounced version of the given callback function.
|
|
1253
|
-
|
|
1254
|
-
| Param | Type | Default | Description |
|
|
1255
|
-
|-------|------|---------|-------------|
|
|
1256
|
-
| `callback` | `Function` | — | Function to debounce |
|
|
1257
|
-
| `delay` | `number` | `200` | Delay in ms |
|
|
1258
|
-
|
|
1259
|
-
### `useDebounceValue(value, delay?)`
|
|
1260
|
-
|
|
1261
|
-
Returns a debounced version of a value.
|
|
1262
|
-
|
|
1263
|
-
| Param | Type | Default | Description |
|
|
1264
|
-
|-------|------|---------|-------------|
|
|
1265
|
-
| `value` | `T` | — | Value to debounce |
|
|
1266
|
-
| `delay` | `number` | `300` | Delay in ms |
|
|
1267
|
-
|
|
1268
|
-
```tsx
|
|
1269
|
-
import { useDebounceValue } from "@rebasepro/ui";
|
|
1270
|
-
|
|
1271
|
-
const debouncedSearch = useDebounceValue(searchText, 200);
|
|
1272
|
-
useEffect(() => { fetchResults(debouncedSearch); }, [debouncedSearch]);
|
|
1273
|
-
```
|
|
1274
|
-
|
|
1275
|
-
### `PortalContainerProvider` and `usePortalContainer()`
|
|
1276
|
-
|
|
1277
|
-
Context provider that controls where Radix portals are rendered. All portal-based components (`Dialog`, `Sheet`, `Select`, `MultiSelect`, `Tooltip`, `Popover`) automatically use this context.
|
|
1278
|
-
|
|
1279
|
-
```tsx
|
|
1280
|
-
import { PortalContainerProvider } from "@rebasepro/ui";
|
|
1281
|
-
|
|
1282
|
-
const containerRef = useRef<HTMLDivElement>(null);
|
|
1283
|
-
|
|
1284
|
-
<div ref={containerRef}>
|
|
1285
|
-
<PortalContainerProvider container={containerRef.current}>
|
|
1286
|
-
{/* All portals render inside this div */}
|
|
1287
|
-
<Select ... />
|
|
1288
|
-
<Dialog ... />
|
|
1289
|
-
</PortalContainerProvider>
|
|
1290
|
-
</div>
|
|
1291
|
-
```
|
|
1292
|
-
|
|
1293
|
-
---
|
|
1294
|
-
|
|
1295
|
-
## Complete Custom View Example
|
|
1296
|
-
|
|
1297
|
-
```tsx
|
|
1298
|
-
import {
|
|
1299
|
-
Container,
|
|
1300
|
-
Typography,
|
|
1301
|
-
Card,
|
|
1302
|
-
Button,
|
|
1303
|
-
TextField,
|
|
1304
|
-
Tabs,
|
|
1305
|
-
Tab,
|
|
1306
|
-
Alert,
|
|
1307
|
-
Chip,
|
|
1308
|
-
SearchBar,
|
|
1309
|
-
Table,
|
|
1310
|
-
TableHeader,
|
|
1311
|
-
TableBody,
|
|
1312
|
-
TableRow,
|
|
1313
|
-
TableCell,
|
|
1314
|
-
Dialog,
|
|
1315
|
-
DialogTitle,
|
|
1316
|
-
DialogContent,
|
|
1317
|
-
DialogActions,
|
|
1318
|
-
cls,
|
|
1319
|
-
iconSize
|
|
1320
|
-
} from "@rebasepro/ui";
|
|
1321
|
-
import { PlusIcon, PencilIcon } from "@rebasepro/ui";
|
|
1322
|
-
import { useState } from "react";
|
|
1323
|
-
|
|
1324
|
-
export function DashboardView() {
|
|
1325
|
-
const [tab, setTab] = useState("all");
|
|
1326
|
-
const [dialogOpen, setDialogOpen] = useState(false);
|
|
1327
|
-
|
|
1328
|
-
return (
|
|
1329
|
-
<Container maxWidth="5xl">
|
|
1330
|
-
<div className="flex justify-between items-center mb-6">
|
|
1331
|
-
<Typography variant="h4">Dashboard</Typography>
|
|
1332
|
-
<Button
|
|
1333
|
-
variant="filled"
|
|
1334
|
-
color="primary"
|
|
1335
|
-
startIcon={<PlusIcon size={iconSize.small} />}
|
|
1336
|
-
onClick={() => setDialogOpen(true)}
|
|
1337
|
-
>
|
|
1338
|
-
New Item
|
|
1339
|
-
</Button>
|
|
1340
|
-
</div>
|
|
1341
|
-
|
|
1342
|
-
<Alert color="info" size="small" className="mb-4">
|
|
1343
|
-
Welcome back! You have 3 items needing review.
|
|
1344
|
-
</Alert>
|
|
1345
|
-
|
|
1346
|
-
<div className="flex gap-4 mb-4">
|
|
1347
|
-
<Tabs value={tab} onValueChange={setTab} variant="standard">
|
|
1348
|
-
<Tab value="all">All</Tab>
|
|
1349
|
-
<Tab value="active">Active</Tab>
|
|
1350
|
-
<Tab value="archived">Archived</Tab>
|
|
1351
|
-
</Tabs>
|
|
1352
|
-
<SearchBar
|
|
1353
|
-
onTextSearch={(term) => console.log(term)}
|
|
1354
|
-
size="small"
|
|
1355
|
-
/>
|
|
1356
|
-
</div>
|
|
1357
|
-
|
|
1358
|
-
<Card className="p-0 overflow-hidden">
|
|
1359
|
-
<Table>
|
|
1360
|
-
<TableHeader>
|
|
1361
|
-
<TableCell header>Name</TableCell>
|
|
1362
|
-
<TableCell header>Status</TableCell>
|
|
1363
|
-
<TableCell header align="right">Actions</TableCell>
|
|
1364
|
-
</TableHeader>
|
|
1365
|
-
<TableBody>
|
|
1366
|
-
<TableRow>
|
|
1367
|
-
<TableCell>Example Item</TableCell>
|
|
1368
|
-
<TableCell>
|
|
1369
|
-
<Chip colorScheme="green" size="small">Active</Chip>
|
|
1370
|
-
</TableCell>
|
|
1371
|
-
<TableCell align="right">
|
|
1372
|
-
<IconButton aria-label="Edit" size="small">
|
|
1373
|
-
<PencilIcon size={iconSize.smallest} />
|
|
1374
|
-
</IconButton>
|
|
1375
|
-
</TableCell>
|
|
1376
|
-
</TableRow>
|
|
1377
|
-
</TableBody>
|
|
1378
|
-
</Table>
|
|
1379
|
-
</Card>
|
|
1380
|
-
|
|
1381
|
-
<Dialog open={dialogOpen} onOpenChange={setDialogOpen} maxWidth="md">
|
|
1382
|
-
<DialogTitle>Create New Item</DialogTitle>
|
|
1383
|
-
<DialogContent>
|
|
1384
|
-
<TextField label="Name" size="large" />
|
|
1385
|
-
</DialogContent>
|
|
1386
|
-
<DialogActions>
|
|
1387
|
-
<Button variant="text" onClick={() => setDialogOpen(false)}>
|
|
1388
|
-
Cancel
|
|
1389
|
-
</Button>
|
|
1390
|
-
<Button variant="filled" color="primary">
|
|
1391
|
-
Create
|
|
1392
|
-
</Button>
|
|
1393
|
-
</DialogActions>
|
|
1394
|
-
</Dialog>
|
|
1395
|
-
</Container>
|
|
1396
|
-
);
|
|
1397
|
-
}
|
|
1398
|
-
```
|
|
1399
|
-
|
|
1400
|
-
## Rich Text Editor (`RichTextEditor`)
|
|
1401
|
-
|
|
1402
|
-
> **IMPORTANT:** `RichTextEditor` lives in `@rebasepro/admin`, NOT in `@rebasepro/ui`. It is a separate heavy entry point (~300 KB) because it bundles ProseMirror.
|
|
1403
|
-
|
|
1404
|
-
A full-featured, block-based WYSIWYG editor with slash commands, bubble menus, image uploads, tables, AI autocomplete, drag-and-drop reordering, and a raw Markdown toggle. Outputs **Markdown**, **JSON** (ProseMirror document tree), and **HTML**.
|
|
1405
|
-
|
|
1406
|
-
### Import
|
|
1407
|
-
|
|
1408
|
-
```ts
|
|
1409
|
-
// The component (heavy — code-split / lazy-load when possible)
|
|
1410
|
-
import { RichTextEditor } from "@rebasepro/admin/editor";
|
|
1411
|
-
|
|
1412
|
-
// Types only (lightweight — from the main entry point)
|
|
1413
|
-
import type { RichTextEditorProps, JSONContent, EditorAIController } from "@rebasepro/admin";
|
|
1414
|
-
```
|
|
1415
|
-
|
|
1416
|
-
> **Note:** The previous export name `RebaseEditor` still works but is deprecated. Always use `RichTextEditor`.
|
|
1417
|
-
|
|
1418
|
-
### Props
|
|
1419
|
-
|
|
1420
|
-
| Prop | Type | Default | Description |
|
|
1421
|
-
|------|------|---------|-------------|
|
|
1422
|
-
| `content` | `JSONContent \| string` | — | Initial content. Pass a markdown string or a ProseMirror JSON document. |
|
|
1423
|
-
| `onMarkdownContentChange` | `(md: string) => void` | — | Called with serialized Markdown on edits |
|
|
1424
|
-
| `onJsonContentChange` | `(json: JSONContent \| null) => void` | — | Called with ProseMirror JSON on edits |
|
|
1425
|
-
| `onHtmlContentChange` | `(html: string) => void` | — | Called with HTML string on edits |
|
|
1426
|
-
| `handleImageUpload` | `(file: File) => Promise<string>` | **required** | Upload handler that returns the image URL |
|
|
1427
|
-
| `version` | `number` | — | Bump to force-reset editor content (e.g. on form discard) |
|
|
1428
|
-
| `textSize` | `"sm" \| "base" \| "lg"` | `"base"` | Prose typography scale |
|
|
1429
|
-
| `highlight` | `{ from: number, to: number }` | — | Highlight a character range (used by AI autocomplete) |
|
|
1430
|
-
| `aiController` | `EditorAIController` | — | AI autocomplete controller |
|
|
1431
|
-
| `disabled` | `boolean` | `false` | Read-only mode |
|
|
1432
|
-
| `markdownConfig` | `MarkdownEditorConfig` | — | Markdown parser options (`html`, `transformPastedText`) |
|
|
1433
|
-
|
|
1434
|
-
### Usage Example
|
|
1435
|
-
|
|
1436
|
-
```tsx
|
|
1437
|
-
import { RichTextEditor } from "@rebasepro/admin/editor";
|
|
1438
|
-
|
|
1439
|
-
function MyEditor() {
|
|
1440
|
-
const [markdown, setMarkdown] = useState("");
|
|
1441
|
-
|
|
1442
|
-
return (
|
|
1443
|
-
<RichTextEditor
|
|
1444
|
-
content={markdown}
|
|
1445
|
-
onMarkdownContentChange={setMarkdown}
|
|
1446
|
-
handleImageUpload={async (file) => {
|
|
1447
|
-
const url = await uploadToStorage(file);
|
|
1448
|
-
return url;
|
|
1449
|
-
}}
|
|
1450
|
-
textSize="base"
|
|
1451
|
-
/>
|
|
1452
|
-
);
|
|
1453
|
-
}
|
|
1454
|
-
```
|
|
1455
|
-
|
|
1456
|
-
### Lazy Loading
|
|
1457
|
-
|
|
1458
|
-
Because the editor is ~300 KB, lazy-load it when it's not immediately visible:
|
|
1459
|
-
|
|
1460
|
-
```tsx
|
|
1461
|
-
import { lazy, Suspense } from "react";
|
|
1462
|
-
import { Skeleton } from "@rebasepro/ui";
|
|
1463
|
-
|
|
1464
|
-
const RichTextEditor = lazy(() =>
|
|
1465
|
-
import("@rebasepro/admin/editor").then(m => ({ default: m.RichTextEditor }))
|
|
1466
|
-
);
|
|
1467
|
-
|
|
1468
|
-
function LazyEditor(props) {
|
|
1469
|
-
return (
|
|
1470
|
-
<Suspense fallback={<Skeleton height={200} className="w-full rounded-md" />}>
|
|
1471
|
-
<RichTextEditor {...props} />
|
|
1472
|
-
</Suspense>
|
|
1473
|
-
);
|
|
1474
|
-
}
|
|
1475
|
-
```
|
|
1476
|
-
|
|
1477
|
-
## Tailwind CSS v4
|
|
1478
|
-
|
|
1479
|
-
Rebase uses Tailwind CSS v4 with CSS-first configuration:
|
|
1480
|
-
- No `tailwind.config.js` — configuration is in CSS
|
|
1481
|
-
- CSS variables for theming
|
|
1482
|
-
- Native cascade layers
|
|
1483
|
-
|
|
1484
|
-
## References
|
|
1485
|
-
|
|
1486
|
-
- **Documentation:** [rebase.pro/docs](https://rebase.pro/docs)
|
|
1487
|
-
- **GitHub:** [github.com/rebasepro/rebase](https://github.com/rebasepro/rebase)
|
|
1488
|
-
- **UI Source:** `packages/ui/src/` in the monorepo
|