@orbitlabsui/ui 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -0
- package/dist/index.d.ts +444 -0
- package/dist/index.js +1299 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +70 -0
- package/dist/tailwind-preset.d.ts +5 -0
- package/dist/tailwind-preset.js +60 -0
- package/dist/tailwind-preset.js.map +1 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# @orbitlabsui/ui
|
|
2
|
+
|
|
3
|
+
Shared UI components, design tokens, and theme system for internal Orbit projects.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @orbitlabsui/ui
|
|
9
|
+
# peers (if not already present):
|
|
10
|
+
pnpm add react react-dom
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
> Requires Tailwind CSS `3.4.x` in the consuming app.
|
|
14
|
+
|
|
15
|
+
## Setup
|
|
16
|
+
|
|
17
|
+
**1. Add the preset and scan the package in `tailwind.config.js`:**
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
import orbitPreset from '@orbitlabsui/ui/tailwind-preset';
|
|
21
|
+
|
|
22
|
+
export default {
|
|
23
|
+
presets: [orbitPreset],
|
|
24
|
+
content: [
|
|
25
|
+
'./src/**/*.{js,ts,jsx,tsx}',
|
|
26
|
+
// REQUIRED — without this, Tailwind purges @orbitlabsui/ui's classes and
|
|
27
|
+
// components render unstyled:
|
|
28
|
+
'./node_modules/@orbitlabsui/ui/dist/**/*.js',
|
|
29
|
+
],
|
|
30
|
+
};
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**2. Import the tokens CSS once, at your app entry, before your own CSS:**
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import '@orbitlabsui/ui/styles.css';
|
|
37
|
+
import './index.css'; // your Tailwind entry (@import 'tailwindcss/...')
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**3. Wrap your app in the theme provider (enables light/dark):**
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import { ThemeProvider } from '@orbitlabsui/ui';
|
|
44
|
+
|
|
45
|
+
<ThemeProvider>
|
|
46
|
+
<App />
|
|
47
|
+
</ThemeProvider>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Usage
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
import { Button, ThemeToggle } from '@orbitlabsui/ui';
|
|
54
|
+
|
|
55
|
+
<Button variant="primary" icon="plus" iconPosition="leading">New</Button>
|
|
56
|
+
<ThemeToggle />
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Theming
|
|
60
|
+
|
|
61
|
+
Dark mode is class-based (`<html class="dark">`), driven by `ThemeProvider` /
|
|
62
|
+
`ThemeToggle`. Tokens are CSS variables defined in `@orbitlabsui/ui/styles.css`;
|
|
63
|
+
override them in your own CSS to rebrand.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
import React, { ReactNode, CSSProperties } from 'react';
|
|
2
|
+
import * as lucide_react from 'lucide-react';
|
|
3
|
+
import { LucideIcon } from 'lucide-react';
|
|
4
|
+
import { Placement, ExtendedRefs, ReferenceType, FloatingContext, UseInteractionsReturn } from '@floating-ui/react';
|
|
5
|
+
|
|
6
|
+
type ThemeChoice = 'light' | 'dark' | 'system';
|
|
7
|
+
type ResolvedTheme = 'light' | 'dark';
|
|
8
|
+
declare const THEME_STORAGE_KEY = "orbit-theme";
|
|
9
|
+
declare function resolveTheme(choice: ThemeChoice, prefersDark: boolean): ResolvedTheme;
|
|
10
|
+
declare function getStoredTheme(): ThemeChoice;
|
|
11
|
+
declare function storeTheme(choice: ThemeChoice): void;
|
|
12
|
+
declare function systemPrefersDark(): boolean;
|
|
13
|
+
declare function applyThemeClass(resolved: ResolvedTheme): void;
|
|
14
|
+
|
|
15
|
+
interface ThemeContextValue {
|
|
16
|
+
theme: ThemeChoice;
|
|
17
|
+
resolvedTheme: ResolvedTheme;
|
|
18
|
+
setTheme: (choice: ThemeChoice) => void;
|
|
19
|
+
}
|
|
20
|
+
declare function ThemeProvider({ children }: {
|
|
21
|
+
children: React.ReactNode;
|
|
22
|
+
}): React.JSX.Element;
|
|
23
|
+
declare function useTheme(): ThemeContextValue;
|
|
24
|
+
|
|
25
|
+
declare function ThemeToggle(): React.JSX.Element;
|
|
26
|
+
|
|
27
|
+
type Variant = 'primary' | 'secondary' | 'destructive';
|
|
28
|
+
type IconPos = 'none' | 'leading' | 'trailing';
|
|
29
|
+
interface ButtonProps {
|
|
30
|
+
children: React.ReactNode;
|
|
31
|
+
variant?: Variant;
|
|
32
|
+
icon?: 'plus' | 'copy' | 'external-link' | 'github';
|
|
33
|
+
iconPosition?: IconPos;
|
|
34
|
+
onClick?: () => void;
|
|
35
|
+
disabled?: boolean;
|
|
36
|
+
/** Stretch to the container width (e.g. a full-width form/footer action). */
|
|
37
|
+
fullWidth?: boolean;
|
|
38
|
+
}
|
|
39
|
+
declare function Button({ children, variant, icon, iconPosition, onClick, disabled, fullWidth }: ButtonProps): React.JSX.Element;
|
|
40
|
+
|
|
41
|
+
type OverlayPosition = 'center' | 'left' | 'right';
|
|
42
|
+
interface OverlayProps {
|
|
43
|
+
open: boolean;
|
|
44
|
+
onClose: () => void;
|
|
45
|
+
position: OverlayPosition;
|
|
46
|
+
/** Tailwind max-width class applied to the panel, e.g. "max-w-lg". */
|
|
47
|
+
widthClassName: string;
|
|
48
|
+
title?: React.ReactNode;
|
|
49
|
+
description?: React.ReactNode;
|
|
50
|
+
footer?: React.ReactNode;
|
|
51
|
+
hideCloseButton?: boolean;
|
|
52
|
+
closeOnBackdrop?: boolean;
|
|
53
|
+
closeOnEsc?: boolean;
|
|
54
|
+
children: React.ReactNode;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Shared modal-overlay primitive used by Modal and Drawer.
|
|
58
|
+
*
|
|
59
|
+
* Handles the portal, scroll-locking backdrop, focus trap + restore, Escape and
|
|
60
|
+
* outside-press dismissal, enter/exit animation, and the common header/body/footer
|
|
61
|
+
* chrome. Position drives both layout (centered vs edge-docked) and animation.
|
|
62
|
+
*/
|
|
63
|
+
declare function Overlay({ open, onClose, position, widthClassName, title, description, footer, hideCloseButton, closeOnBackdrop, closeOnEsc, children }: OverlayProps): React.JSX.Element;
|
|
64
|
+
|
|
65
|
+
interface AvatarProps {
|
|
66
|
+
name: string;
|
|
67
|
+
initials?: string;
|
|
68
|
+
size?: 'sm' | 'md' | 'lg';
|
|
69
|
+
className?: string;
|
|
70
|
+
}
|
|
71
|
+
declare function Avatar({ name, initials, size, className }: AvatarProps): React.JSX.Element;
|
|
72
|
+
|
|
73
|
+
interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
|
74
|
+
label?: string;
|
|
75
|
+
helperText?: string;
|
|
76
|
+
error?: boolean;
|
|
77
|
+
icon?: LucideIcon;
|
|
78
|
+
}
|
|
79
|
+
declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
|
|
80
|
+
|
|
81
|
+
interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
82
|
+
label?: string;
|
|
83
|
+
helperText?: string;
|
|
84
|
+
error?: boolean;
|
|
85
|
+
}
|
|
86
|
+
declare const Textarea: React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
|
|
87
|
+
|
|
88
|
+
/** Standard rendering for artifact codes (REQ-/BP-/WO-/CO-, project keys).
|
|
89
|
+
* Condensed grey type — the work-order row style, used everywhere. */
|
|
90
|
+
declare function Code({ children, className, }: {
|
|
91
|
+
children: React.ReactNode;
|
|
92
|
+
className?: string;
|
|
93
|
+
}): React.JSX.Element;
|
|
94
|
+
|
|
95
|
+
interface TooltipProps {
|
|
96
|
+
label: React.ReactNode;
|
|
97
|
+
children: React.ReactNode;
|
|
98
|
+
placement?: 'top' | 'bottom' | 'left' | 'right';
|
|
99
|
+
/** Make the trigger wrapper fill its cell and truncate (for table rows). */
|
|
100
|
+
block?: boolean;
|
|
101
|
+
}
|
|
102
|
+
/** Hover/focus tooltip built on floating-ui. */
|
|
103
|
+
declare function Tooltip({ label, children, placement, block }: TooltipProps): React.JSX.Element;
|
|
104
|
+
|
|
105
|
+
interface TabItem {
|
|
106
|
+
id: string;
|
|
107
|
+
label: string;
|
|
108
|
+
icon?: LucideIcon;
|
|
109
|
+
}
|
|
110
|
+
interface TabsProps {
|
|
111
|
+
items: TabItem[];
|
|
112
|
+
value: string;
|
|
113
|
+
onChange: (id: string) => void;
|
|
114
|
+
className?: string;
|
|
115
|
+
}
|
|
116
|
+
/** Controlled, underline-style tab navigation. */
|
|
117
|
+
declare function Tabs({ items, value, onChange, className }: TabsProps): React.JSX.Element;
|
|
118
|
+
|
|
119
|
+
interface NotifyOptions {
|
|
120
|
+
/** Optional secondary line beneath the title. */
|
|
121
|
+
description?: React.ReactNode;
|
|
122
|
+
/** Override the auto-dismiss duration (ms). */
|
|
123
|
+
duration?: number;
|
|
124
|
+
}
|
|
125
|
+
/** Styled, design-system toast helpers. */
|
|
126
|
+
declare const notify: {
|
|
127
|
+
success: (title: React.ReactNode, options?: NotifyOptions) => string;
|
|
128
|
+
error: (title: React.ReactNode, options?: NotifyOptions) => string;
|
|
129
|
+
info: (title: React.ReactNode, options?: NotifyOptions) => string;
|
|
130
|
+
warning: (title: React.ReactNode, options?: NotifyOptions) => string;
|
|
131
|
+
dismiss: (id?: string) => void;
|
|
132
|
+
};
|
|
133
|
+
/** Mount once near the app root so toasts render on every route. */
|
|
134
|
+
declare function AppToaster(): React.JSX.Element;
|
|
135
|
+
|
|
136
|
+
type StatusType = 'in-review' | 'in-progress' | 'backlog' | 'completed' | 'blocked' | 'ready';
|
|
137
|
+
/** Project lifecycle — distinct from artifact StatusType, rendered by the same badge. */
|
|
138
|
+
type ProjectStatus = 'active' | 'archived';
|
|
139
|
+
/** Plan statuses for Requirements & Blueprints — distinct from execution StatusType. */
|
|
140
|
+
type PlanStatusType = 'backlog' | 'scoped' | 'cancelled';
|
|
141
|
+
interface StatusBadgeProps {
|
|
142
|
+
status: StatusType | ProjectStatus | PlanStatusType;
|
|
143
|
+
}
|
|
144
|
+
declare const STATUS_CONFIG: {
|
|
145
|
+
readonly backlog: {
|
|
146
|
+
readonly label: "Backlog";
|
|
147
|
+
readonly Icon: React.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & React.RefAttributes<SVGSVGElement>>;
|
|
148
|
+
readonly fill: "var(--color-neutral-bg)";
|
|
149
|
+
readonly border: "var(--color-neutral-border)";
|
|
150
|
+
readonly color: "var(--color-neutral)";
|
|
151
|
+
};
|
|
152
|
+
readonly ready: {
|
|
153
|
+
readonly label: "Ready";
|
|
154
|
+
readonly Icon: React.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & React.RefAttributes<SVGSVGElement>>;
|
|
155
|
+
readonly fill: "var(--color-info-bg)";
|
|
156
|
+
readonly border: "var(--color-info-border)";
|
|
157
|
+
readonly color: "var(--color-info)";
|
|
158
|
+
};
|
|
159
|
+
readonly 'in-progress': {
|
|
160
|
+
readonly label: "In progress";
|
|
161
|
+
readonly Icon: React.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & React.RefAttributes<SVGSVGElement>>;
|
|
162
|
+
readonly fill: "var(--color-warning-bg)";
|
|
163
|
+
readonly border: "var(--color-warning-border)";
|
|
164
|
+
readonly color: "var(--color-warning)";
|
|
165
|
+
};
|
|
166
|
+
readonly 'in-review': {
|
|
167
|
+
readonly label: "In Review";
|
|
168
|
+
readonly Icon: React.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & React.RefAttributes<SVGSVGElement>>;
|
|
169
|
+
readonly fill: "var(--color-review-bg)";
|
|
170
|
+
readonly border: "var(--color-review-border)";
|
|
171
|
+
readonly color: "var(--color-review)";
|
|
172
|
+
};
|
|
173
|
+
readonly blocked: {
|
|
174
|
+
readonly label: "Blocked";
|
|
175
|
+
readonly Icon: React.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & React.RefAttributes<SVGSVGElement>>;
|
|
176
|
+
readonly fill: "var(--color-danger-bg)";
|
|
177
|
+
readonly border: "var(--color-danger-border)";
|
|
178
|
+
readonly color: "var(--color-danger)";
|
|
179
|
+
};
|
|
180
|
+
readonly completed: {
|
|
181
|
+
readonly label: "Completed";
|
|
182
|
+
readonly Icon: React.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & React.RefAttributes<SVGSVGElement>>;
|
|
183
|
+
readonly fill: "var(--color-success-bg)";
|
|
184
|
+
readonly border: "var(--color-success-border)";
|
|
185
|
+
readonly color: "var(--color-success)";
|
|
186
|
+
};
|
|
187
|
+
};
|
|
188
|
+
/** Project lifecycle statuses — kept separate from STATUS_CONFIG so artifact
|
|
189
|
+
* grouping/boards (which derive columns from STATUS_CONFIG) are unaffected. */
|
|
190
|
+
declare const PROJECT_STATUS_CONFIG: {
|
|
191
|
+
readonly active: {
|
|
192
|
+
readonly label: "Active";
|
|
193
|
+
readonly Icon: React.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & React.RefAttributes<SVGSVGElement>>;
|
|
194
|
+
readonly fill: "var(--color-success-bg)";
|
|
195
|
+
readonly border: "var(--color-success-border)";
|
|
196
|
+
readonly color: "var(--color-success)";
|
|
197
|
+
};
|
|
198
|
+
readonly archived: {
|
|
199
|
+
readonly label: "Archived";
|
|
200
|
+
readonly Icon: React.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & React.RefAttributes<SVGSVGElement>>;
|
|
201
|
+
readonly fill: "var(--color-neutral-bg)";
|
|
202
|
+
readonly border: "var(--color-neutral-border)";
|
|
203
|
+
readonly color: "var(--color-neutral)";
|
|
204
|
+
};
|
|
205
|
+
};
|
|
206
|
+
/** Plan statuses — kept separate from STATUS_CONFIG so artifact execution
|
|
207
|
+
* grouping/boards (which derive columns from STATUS_CONFIG) are unaffected.
|
|
208
|
+
* Used by Requirements & Blueprints. */
|
|
209
|
+
declare const PLAN_STATUS_CONFIG: {
|
|
210
|
+
readonly backlog: {
|
|
211
|
+
readonly label: "Backlog";
|
|
212
|
+
readonly Icon: React.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & React.RefAttributes<SVGSVGElement>>;
|
|
213
|
+
readonly fill: "var(--color-neutral-bg)";
|
|
214
|
+
readonly border: "var(--color-neutral-border)";
|
|
215
|
+
readonly color: "var(--color-neutral)";
|
|
216
|
+
};
|
|
217
|
+
readonly scoped: {
|
|
218
|
+
readonly label: "Scoped";
|
|
219
|
+
readonly Icon: React.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & React.RefAttributes<SVGSVGElement>>;
|
|
220
|
+
readonly fill: "var(--color-info-bg)";
|
|
221
|
+
readonly border: "var(--color-info-border)";
|
|
222
|
+
readonly color: "var(--color-info)";
|
|
223
|
+
};
|
|
224
|
+
readonly cancelled: {
|
|
225
|
+
readonly label: "Cancelled";
|
|
226
|
+
readonly Icon: React.ForwardRefExoticComponent<Omit<lucide_react.LucideProps, "ref"> & React.RefAttributes<SVGSVGElement>>;
|
|
227
|
+
readonly fill: "var(--color-danger-bg)";
|
|
228
|
+
readonly border: "var(--color-danger-border)";
|
|
229
|
+
readonly color: "var(--color-danger)";
|
|
230
|
+
};
|
|
231
|
+
};
|
|
232
|
+
/** Canonical plan-status order for grouping (columns/sections). */
|
|
233
|
+
declare const PLAN_STATUS_ORDER: PlanStatusType[];
|
|
234
|
+
declare function StatusBadge({ status }: StatusBadgeProps): React.JSX.Element;
|
|
235
|
+
|
|
236
|
+
interface EmptyStateTone {
|
|
237
|
+
/** Medallion background. */
|
|
238
|
+
bg: string;
|
|
239
|
+
/** Medallion border color. */
|
|
240
|
+
border: string;
|
|
241
|
+
/** Icon color. */
|
|
242
|
+
color: string;
|
|
243
|
+
}
|
|
244
|
+
interface EmptyStateProps {
|
|
245
|
+
icon: LucideIcon;
|
|
246
|
+
title: React.ReactNode;
|
|
247
|
+
description?: React.ReactNode;
|
|
248
|
+
/** Optional action(s) rendered below the copy, e.g. a Button. */
|
|
249
|
+
action?: React.ReactNode;
|
|
250
|
+
/** Color treatment for the icon medallion. Defaults to neutral gray. */
|
|
251
|
+
tone?: EmptyStateTone;
|
|
252
|
+
className?: string;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Centered empty / placeholder state: an icon medallion, a title, supporting
|
|
256
|
+
* copy, and an optional action. Fills the height of its container so it sits
|
|
257
|
+
* dead-center in a page or panel.
|
|
258
|
+
*/
|
|
259
|
+
declare function EmptyState({ icon: Icon, title, description, action, tone, className }: EmptyStateProps): React.JSX.Element;
|
|
260
|
+
|
|
261
|
+
interface FormSectionProps {
|
|
262
|
+
title?: string;
|
|
263
|
+
description?: string;
|
|
264
|
+
children: React.ReactNode;
|
|
265
|
+
className?: string;
|
|
266
|
+
}
|
|
267
|
+
/** Titled fieldset grouping a vertical stack of fields. */
|
|
268
|
+
declare function FormSection({ title, description, children, className }: FormSectionProps): React.JSX.Element;
|
|
269
|
+
interface FieldProps {
|
|
270
|
+
label: string;
|
|
271
|
+
htmlFor?: string;
|
|
272
|
+
help?: React.ReactNode;
|
|
273
|
+
error?: React.ReactNode;
|
|
274
|
+
children: React.ReactNode;
|
|
275
|
+
}
|
|
276
|
+
/** A single labeled field row with optional help / error text. */
|
|
277
|
+
declare function Field({ label, htmlFor, help, error, children }: FieldProps): React.JSX.Element;
|
|
278
|
+
|
|
279
|
+
type DirtyState = 'clean' | 'dirty' | 'saving' | 'saved';
|
|
280
|
+
/** Small status pill reflecting an editor's save state. */
|
|
281
|
+
declare function DirtyStateIndicator({ state }: {
|
|
282
|
+
state: DirtyState;
|
|
283
|
+
}): React.JSX.Element | null;
|
|
284
|
+
|
|
285
|
+
interface RowAction {
|
|
286
|
+
icon: React.ElementType;
|
|
287
|
+
label: string;
|
|
288
|
+
onClick: () => void;
|
|
289
|
+
/** Render in a destructive (red) hover state. */
|
|
290
|
+
danger?: boolean;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Standard trailing row actions — a group of icon buttons revealed on row
|
|
294
|
+
* hover. Used in every table row and the phases list so actions look and
|
|
295
|
+
* behave identically everywhere. The parent row must have the `group` class.
|
|
296
|
+
*/
|
|
297
|
+
declare function RowActions({ actions }: {
|
|
298
|
+
actions: RowAction[];
|
|
299
|
+
}): React.JSX.Element;
|
|
300
|
+
|
|
301
|
+
/** Renders markdown with design-system typography. */
|
|
302
|
+
declare function Markdown({ children }: {
|
|
303
|
+
children: string;
|
|
304
|
+
}): React.JSX.Element;
|
|
305
|
+
|
|
306
|
+
type Size$1 = 'sm' | 'md' | 'lg';
|
|
307
|
+
interface ModalProps {
|
|
308
|
+
open: boolean;
|
|
309
|
+
onClose: () => void;
|
|
310
|
+
title?: React.ReactNode;
|
|
311
|
+
description?: React.ReactNode;
|
|
312
|
+
footer?: React.ReactNode;
|
|
313
|
+
size?: Size$1;
|
|
314
|
+
hideCloseButton?: boolean;
|
|
315
|
+
closeOnBackdrop?: boolean;
|
|
316
|
+
closeOnEsc?: boolean;
|
|
317
|
+
children: React.ReactNode;
|
|
318
|
+
}
|
|
319
|
+
/** Centered modal dialog with header / body / footer slots. */
|
|
320
|
+
declare function Modal({ open, onClose, title, description, footer, size, hideCloseButton, closeOnBackdrop, closeOnEsc, children }: ModalProps): React.JSX.Element;
|
|
321
|
+
|
|
322
|
+
type Size = 'sm' | 'md' | 'lg';
|
|
323
|
+
interface DrawerProps {
|
|
324
|
+
open: boolean;
|
|
325
|
+
onClose: () => void;
|
|
326
|
+
side?: 'right' | 'left';
|
|
327
|
+
title?: React.ReactNode;
|
|
328
|
+
description?: React.ReactNode;
|
|
329
|
+
footer?: React.ReactNode;
|
|
330
|
+
size?: Size;
|
|
331
|
+
hideCloseButton?: boolean;
|
|
332
|
+
closeOnBackdrop?: boolean;
|
|
333
|
+
closeOnEsc?: boolean;
|
|
334
|
+
children: React.ReactNode;
|
|
335
|
+
}
|
|
336
|
+
/** Side panel that slides in from the left or right edge. */
|
|
337
|
+
declare function Drawer({ open, onClose, side, title, description, footer, size, hideCloseButton, closeOnBackdrop, closeOnEsc, children }: DrawerProps): React.JSX.Element;
|
|
338
|
+
|
|
339
|
+
interface ConfirmDialogProps {
|
|
340
|
+
open: boolean;
|
|
341
|
+
onClose: () => void;
|
|
342
|
+
title: string;
|
|
343
|
+
message: React.ReactNode;
|
|
344
|
+
confirmLabel?: string;
|
|
345
|
+
cancelLabel?: string;
|
|
346
|
+
onConfirm: () => void;
|
|
347
|
+
variant?: 'default' | 'destructive';
|
|
348
|
+
loading?: boolean;
|
|
349
|
+
}
|
|
350
|
+
/** Opinionated confirmation dialog built on Modal. */
|
|
351
|
+
declare function ConfirmDialog({ open, onClose, title, message, confirmLabel, cancelLabel, onConfirm, variant, loading }: ConfirmDialogProps): React.JSX.Element;
|
|
352
|
+
|
|
353
|
+
interface SaveBarProps {
|
|
354
|
+
dirty: boolean;
|
|
355
|
+
onSave: () => void;
|
|
356
|
+
onDiscard: () => void;
|
|
357
|
+
state?: DirtyState;
|
|
358
|
+
saveLabel?: string;
|
|
359
|
+
discardLabel?: string;
|
|
360
|
+
}
|
|
361
|
+
/** Sticky action bar: Save (disabled until dirty) + Discard, with a state pill. */
|
|
362
|
+
declare function SaveBar({ dirty, onSave, onDiscard, state, saveLabel, discardLabel }: SaveBarProps): React.JSX.Element;
|
|
363
|
+
|
|
364
|
+
interface DropdownProps {
|
|
365
|
+
trigger: ReactNode;
|
|
366
|
+
children: ReactNode;
|
|
367
|
+
align?: 'left' | 'right';
|
|
368
|
+
className?: string;
|
|
369
|
+
}
|
|
370
|
+
declare function Dropdown({ trigger, children, align, className }: DropdownProps): React.JSX.Element;
|
|
371
|
+
interface DropdownItemProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
372
|
+
children: ReactNode;
|
|
373
|
+
icon?: React.ElementType;
|
|
374
|
+
danger?: boolean;
|
|
375
|
+
}
|
|
376
|
+
declare function DropdownItem({ children, icon: Icon, danger, className, ...props }: DropdownItemProps): React.JSX.Element;
|
|
377
|
+
|
|
378
|
+
interface SelectOption {
|
|
379
|
+
value: string;
|
|
380
|
+
label: string;
|
|
381
|
+
}
|
|
382
|
+
interface SelectProps {
|
|
383
|
+
label?: string;
|
|
384
|
+
placeholder?: string;
|
|
385
|
+
options: SelectOption[];
|
|
386
|
+
value?: string;
|
|
387
|
+
onChange?: (value: string) => void;
|
|
388
|
+
error?: boolean;
|
|
389
|
+
helperText?: string;
|
|
390
|
+
disabled?: boolean;
|
|
391
|
+
className?: string;
|
|
392
|
+
}
|
|
393
|
+
declare function Select({ label, placeholder, options, value, onChange, error, helperText, disabled, className }: SelectProps): React.JSX.Element;
|
|
394
|
+
|
|
395
|
+
interface ComboboxOption {
|
|
396
|
+
value: string;
|
|
397
|
+
label: string;
|
|
398
|
+
}
|
|
399
|
+
interface ComboboxProps {
|
|
400
|
+
label?: string;
|
|
401
|
+
placeholder?: string;
|
|
402
|
+
options: ComboboxOption[];
|
|
403
|
+
value?: string;
|
|
404
|
+
onChange?: (value: string) => void;
|
|
405
|
+
error?: boolean;
|
|
406
|
+
helperText?: string;
|
|
407
|
+
disabled?: boolean;
|
|
408
|
+
className?: string;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Searchable single-select, built on the shared usePopover (collision-aware
|
|
412
|
+
* positioning + outside-press / escape dismissal + single-open guarantee).
|
|
413
|
+
*/
|
|
414
|
+
declare function Combobox({ label, placeholder, options, value, onChange, error, helperText, disabled, className }: ComboboxProps): React.JSX.Element;
|
|
415
|
+
|
|
416
|
+
interface UsePopoverOptions {
|
|
417
|
+
open: boolean;
|
|
418
|
+
onOpenChange: (open: boolean) => void;
|
|
419
|
+
placement?: Placement;
|
|
420
|
+
/** Distance in px between the trigger and the floating panel. */
|
|
421
|
+
gap?: number;
|
|
422
|
+
/** When true, the floating panel is constrained to (and matches) the trigger width. */
|
|
423
|
+
matchWidth?: boolean;
|
|
424
|
+
role?: 'menu' | 'listbox' | 'dialog';
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Shared, collision-aware popover positioning built on Floating UI.
|
|
428
|
+
*
|
|
429
|
+
* Provides flip (open upward when there's no room below), shift (stay in the
|
|
430
|
+
* viewport horizontally), and size (cap the panel height to available space and
|
|
431
|
+
* optionally match the trigger width). Also wires escape + outside-press dismissal.
|
|
432
|
+
*
|
|
433
|
+
* Spread getReferenceProps() on the trigger and getFloatingProps() on the panel,
|
|
434
|
+
* attach refs.setReference / refs.setFloating, and apply floatingStyles to the panel.
|
|
435
|
+
*/
|
|
436
|
+
declare function usePopover({ open, onOpenChange, placement, gap, matchWidth, role }: UsePopoverOptions): {
|
|
437
|
+
refs: ExtendedRefs<ReferenceType>;
|
|
438
|
+
floatingStyles: CSSProperties;
|
|
439
|
+
context: FloatingContext<ReferenceType>;
|
|
440
|
+
getReferenceProps: UseInteractionsReturn['getReferenceProps'];
|
|
441
|
+
getFloatingProps: UseInteractionsReturn['getFloatingProps'];
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
export { AppToaster, Avatar, Button, Code, Combobox, type ComboboxOption, type ComboboxProps, ConfirmDialog, type DirtyState, DirtyStateIndicator, Drawer, Dropdown, DropdownItem, EmptyState, type EmptyStateTone, Field, FormSection, Input, type InputProps, Markdown, Modal, Overlay, type OverlayPosition, PLAN_STATUS_CONFIG, PLAN_STATUS_ORDER, PROJECT_STATUS_CONFIG, type PlanStatusType, type ProjectStatus, type ResolvedTheme, type RowAction, RowActions, STATUS_CONFIG, SaveBar, Select, type SelectOption, type SelectProps, StatusBadge, type StatusType, THEME_STORAGE_KEY, type TabItem, Tabs, Textarea, type TextareaProps, type ThemeChoice, ThemeProvider, ThemeToggle, Tooltip, applyThemeClass, getStoredTheme, notify, resolveTheme, storeTheme, systemPrefersDark, usePopover, useTheme };
|