panelui-web 0.2.0 → 0.4.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/dist/components/command-dock/index.d.ts +23 -2
- package/dist/components/command-dock/index.js +22 -2
- package/dist/components/day-grid/index.d.ts +45 -1
- package/dist/components/day-grid/index.js +40 -1
- package/dist/components/feedback/index.d.ts +50 -1
- package/dist/components/feedback/index.js +43 -1
- package/dist/components/flow/index.d.ts +61 -3
- package/dist/components/flow/index.js +65 -9
- package/dist/components/frame/index.d.ts +6 -4
- package/dist/components/frame/index.js +7 -2
- package/dist/components/kpi/index.d.ts +3 -1
- package/dist/components/kpi/index.js +6 -3
- package/dist/components/lane-board/index.d.ts +9 -1
- package/dist/components/lane-board/index.js +8 -1
- package/dist/components/not-found/glyphs.d.ts +26 -0
- package/dist/components/not-found/glyphs.js +141 -0
- package/dist/components/not-found/index.d.ts +118 -0
- package/dist/components/not-found/index.js +791 -0
- package/dist/components/planet/index.d.ts +24 -1
- package/dist/components/planet/index.js +27 -6
- package/dist/components/range-meter/index.d.ts +30 -2
- package/dist/components/range-meter/index.js +27 -2
- package/dist/components/stat/index.d.ts +106 -0
- package/dist/components/stat/index.js +72 -0
- package/dist/components/tilt-card/index.d.ts +23 -2
- package/dist/components/tilt-card/index.js +19 -2
- package/dist/index.d.ts +10 -8
- package/dist/index.js +10 -8
- package/package.json +1 -1
|
@@ -8,7 +8,12 @@
|
|
|
8
8
|
* <CommandDock.Panel>
|
|
9
9
|
* <CommandDock.Input placeholder="What do you want to find?" />
|
|
10
10
|
* <CommandDock.Results>
|
|
11
|
-
* {rows.map((row) =>
|
|
11
|
+
* {rows.map((row) => (
|
|
12
|
+
* <CommandDock.Row key={row.id}>
|
|
13
|
+
* <CommandDock.RowTitle>{row.title}</CommandDock.RowTitle>
|
|
14
|
+
* <CommandDock.RowMeta>{row.where}</CommandDock.RowMeta>
|
|
15
|
+
* </CommandDock.Row>
|
|
16
|
+
* ))}
|
|
12
17
|
* </CommandDock.Results>
|
|
13
18
|
* </CommandDock.Panel>
|
|
14
19
|
* </CommandDock>
|
|
@@ -99,6 +104,20 @@ declare function CommandDockRow({ className, onSelect, children, ...props }: Com
|
|
|
99
104
|
declare namespace CommandDockRow {
|
|
100
105
|
var displayName: string;
|
|
101
106
|
}
|
|
107
|
+
export interface CommandDockRowTitleProps extends ComponentProps<'span'> {
|
|
108
|
+
}
|
|
109
|
+
/** What a row is, in a line that takes the row's spare width and truncates. */
|
|
110
|
+
declare function CommandDockRowTitle({ className, ...props }: CommandDockRowTitleProps): import("react").JSX.Element;
|
|
111
|
+
declare namespace CommandDockRowTitle {
|
|
112
|
+
var displayName: string;
|
|
113
|
+
}
|
|
114
|
+
export interface CommandDockRowMetaProps extends ComponentProps<'span'> {
|
|
115
|
+
}
|
|
116
|
+
/** Something short at the end of a row, quieter than its title: a date, a place. */
|
|
117
|
+
declare function CommandDockRowMeta({ className, ...props }: CommandDockRowMetaProps): import("react").JSX.Element;
|
|
118
|
+
declare namespace CommandDockRowMeta {
|
|
119
|
+
var displayName: string;
|
|
120
|
+
}
|
|
102
121
|
export interface CommandDockStatusProps extends ComponentProps<'div'> {
|
|
103
122
|
children?: ReactNode;
|
|
104
123
|
}
|
|
@@ -113,6 +132,8 @@ export declare const CommandDock: typeof CommandDockRoot & {
|
|
|
113
132
|
Input: typeof CommandDockInput;
|
|
114
133
|
Results: typeof CommandDockResults;
|
|
115
134
|
Row: typeof CommandDockRow;
|
|
135
|
+
RowTitle: typeof CommandDockRowTitle;
|
|
136
|
+
RowMeta: typeof CommandDockRowMeta;
|
|
116
137
|
Status: typeof CommandDockStatus;
|
|
117
138
|
};
|
|
118
|
-
export { CommandDockTrigger, CommandDockPanel, CommandDockInput, CommandDockResults, CommandDockRow, CommandDockStatus, };
|
|
139
|
+
export { CommandDockTrigger, CommandDockPanel, CommandDockInput, CommandDockResults, CommandDockRow, CommandDockRowTitle, CommandDockRowMeta, CommandDockStatus, };
|
|
@@ -10,7 +10,12 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
10
10
|
* <CommandDock.Panel>
|
|
11
11
|
* <CommandDock.Input placeholder="What do you want to find?" />
|
|
12
12
|
* <CommandDock.Results>
|
|
13
|
-
* {rows.map((row) =>
|
|
13
|
+
* {rows.map((row) => (
|
|
14
|
+
* <CommandDock.Row key={row.id}>
|
|
15
|
+
* <CommandDock.RowTitle>{row.title}</CommandDock.RowTitle>
|
|
16
|
+
* <CommandDock.RowMeta>{row.where}</CommandDock.RowMeta>
|
|
17
|
+
* </CommandDock.Row>
|
|
18
|
+
* ))}
|
|
14
19
|
* </CommandDock.Results>
|
|
15
20
|
* </CommandDock.Panel>
|
|
16
21
|
* </CommandDock>
|
|
@@ -63,6 +68,9 @@ const commandDockVariants = tv({
|
|
|
63
68
|
resultsClip: 'min-h-0 overflow-hidden',
|
|
64
69
|
resultsInner: 'flex flex-col gap-0.5 border-t p-1.5',
|
|
65
70
|
row: 'flex items-center gap-3 rounded-xl px-2.5 py-2 text-sm transition-[opacity,translate] duration-300 ease-out starting:translate-y-1.5 starting:opacity-0 motion-reduce:transition-none [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground',
|
|
71
|
+
// A row's subject takes the room and truncates; its meta keeps its width.
|
|
72
|
+
rowTitle: 'min-w-0 flex-1 truncate font-medium',
|
|
73
|
+
rowMeta: 'shrink-0 text-muted-foreground',
|
|
66
74
|
status: 'flex items-center gap-2 px-2.5 py-2 text-sm text-muted-foreground',
|
|
67
75
|
dots: 'flex gap-1',
|
|
68
76
|
dot: 'size-1 animate-pulse rounded-full bg-muted-foreground',
|
|
@@ -220,6 +228,16 @@ function CommandDockRow({ className, onSelect, children, ...props }) {
|
|
|
220
228
|
return (_jsx("div", { role: "listitem", ...props, children: onSelect ? (_jsx("button", { type: "button", onClick: onSelect, className: slots.row({ className: ['w-full text-start', className] }), children: children })) : (_jsx("div", { className: slots.row({ className }), children: children })) }));
|
|
221
229
|
}
|
|
222
230
|
CommandDockRow.displayName = 'CommandDock.Row';
|
|
231
|
+
/** What a row is, in a line that takes the row's spare width and truncates. */
|
|
232
|
+
function CommandDockRowTitle({ className, ...props }) {
|
|
233
|
+
return (_jsx("span", { "data-slot": "command-dock-row-title", className: commandDockVariants().rowTitle({ className }), ...props }));
|
|
234
|
+
}
|
|
235
|
+
CommandDockRowTitle.displayName = 'CommandDock.RowTitle';
|
|
236
|
+
/** Something short at the end of a row, quieter than its title: a date, a place. */
|
|
237
|
+
function CommandDockRowMeta({ className, ...props }) {
|
|
238
|
+
return (_jsx("span", { "data-slot": "command-dock-row-meta", className: commandDockVariants().rowMeta({ className }), ...props }));
|
|
239
|
+
}
|
|
240
|
+
CommandDockRowMeta.displayName = 'CommandDock.RowMeta';
|
|
223
241
|
/** Shown under the rows while `busy`: three dots, and words if you give it some. */
|
|
224
242
|
function CommandDockStatus({ className, children = 'Working', ...props }) {
|
|
225
243
|
const slots = commandDockVariants();
|
|
@@ -232,8 +250,10 @@ export const CommandDock = Object.assign(CommandDockRoot, {
|
|
|
232
250
|
Input: CommandDockInput,
|
|
233
251
|
Results: CommandDockResults,
|
|
234
252
|
Row: CommandDockRow,
|
|
253
|
+
RowTitle: CommandDockRowTitle,
|
|
254
|
+
RowMeta: CommandDockRowMeta,
|
|
235
255
|
Status: CommandDockStatus,
|
|
236
256
|
});
|
|
237
257
|
/* By name as well, for a Server Component, which cannot dot into a client
|
|
238
258
|
module. */
|
|
239
|
-
export { CommandDockTrigger, CommandDockPanel, CommandDockInput, CommandDockResults, CommandDockRow, CommandDockStatus, };
|
|
259
|
+
export { CommandDockTrigger, CommandDockPanel, CommandDockInput, CommandDockResults, CommandDockRow, CommandDockRowTitle, CommandDockRowMeta, CommandDockStatus, };
|
|
@@ -81,7 +81,51 @@ declare function DayGridLegend({ color, less, more, className, ...props }: DayGr
|
|
|
81
81
|
declare namespace DayGridLegend {
|
|
82
82
|
var displayName: string;
|
|
83
83
|
}
|
|
84
|
+
export interface DayGridWeekdaysProps extends Omit<ComponentProps<'div'>, 'children'> {
|
|
85
|
+
/**
|
|
86
|
+
* The name written beside each row, first row first. An empty string leaves
|
|
87
|
+
* a row unnamed. Default Monday to Sunday with every other name left out.
|
|
88
|
+
*/
|
|
89
|
+
labels?: string[];
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* The days of the week down the side of a grid that runs a week to a column.
|
|
93
|
+
* Put it beside the grid, in a row with it. Hidden from screen readers, which
|
|
94
|
+
* are given each day's own label.
|
|
95
|
+
*/
|
|
96
|
+
declare function DayGridWeekdays({ labels, className, style, ...props }: DayGridWeekdaysProps): import("react").JSX.Element;
|
|
97
|
+
declare namespace DayGridWeekdays {
|
|
98
|
+
var displayName: string;
|
|
99
|
+
}
|
|
100
|
+
export interface DayGridCaptionProps extends ComponentProps<'div'> {
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* What the picked day holds, written out beside the grid: a `DayGrid.Title`
|
|
104
|
+
* over a `DayGrid.Description`. Read out politely each time the pick changes.
|
|
105
|
+
*/
|
|
106
|
+
declare function DayGridCaption({ className, ...props }: DayGridCaptionProps): import("react").JSX.Element;
|
|
107
|
+
declare namespace DayGridCaption {
|
|
108
|
+
var displayName: string;
|
|
109
|
+
}
|
|
110
|
+
export interface DayGridTitleProps extends ComponentProps<'p'> {
|
|
111
|
+
}
|
|
112
|
+
/** The picked day's figure: "17 merged". */
|
|
113
|
+
declare function DayGridTitle({ className, ...props }: DayGridTitleProps): import("react").JSX.Element;
|
|
114
|
+
declare namespace DayGridTitle {
|
|
115
|
+
var displayName: string;
|
|
116
|
+
}
|
|
117
|
+
export interface DayGridDescriptionProps extends ComponentProps<'p'> {
|
|
118
|
+
}
|
|
119
|
+
/** The picked day's date, quieter, under its figure. */
|
|
120
|
+
declare function DayGridDescription({ className, ...props }: DayGridDescriptionProps): import("react").JSX.Element;
|
|
121
|
+
declare namespace DayGridDescription {
|
|
122
|
+
var displayName: string;
|
|
123
|
+
}
|
|
84
124
|
export declare const DayGrid: typeof DayGridRoot & {
|
|
85
125
|
Legend: typeof DayGridLegend;
|
|
126
|
+
Weekdays: typeof DayGridWeekdays;
|
|
127
|
+
Caption: typeof DayGridCaption;
|
|
128
|
+
Title: typeof DayGridTitle;
|
|
129
|
+
Description: typeof DayGridDescription;
|
|
86
130
|
};
|
|
87
|
-
export { DayGridLegend };
|
|
131
|
+
export { DayGridLegend, DayGridWeekdays, DayGridCaption, DayGridTitle, DayGridDescription };
|
|
@@ -46,6 +46,13 @@ const dayGridVariants = tv({
|
|
|
46
46
|
dot: 'block size-full rounded-full [scale:calc(var(--pu-size)*(1+var(--pu-lens,0)*0.5)*var(--pu-in,1))] transition-[scale,box-shadow] duration-200 ease-[cubic-bezier(0.34,1.56,0.64,1)] motion-reduce:transition-none',
|
|
47
47
|
tag: 'pointer-events-none absolute z-20 whitespace-nowrap rounded-lg bg-foreground px-2 py-1 text-xs font-medium text-background shadow-lg',
|
|
48
48
|
legend: 'flex items-center gap-1.5 text-xs text-muted-foreground',
|
|
49
|
+
// One row per day, matching the grid's own rows, so each name sits level with its days.
|
|
50
|
+
weekdays: 'grid gap-1 text-xs leading-none text-muted-foreground',
|
|
51
|
+
weekday: 'flex items-center',
|
|
52
|
+
// The picked day, written out under the grid.
|
|
53
|
+
caption: 'flex flex-col gap-0.5',
|
|
54
|
+
title: 'text-sm font-medium',
|
|
55
|
+
description: 'text-sm text-muted-foreground',
|
|
49
56
|
swatch: 'flex size-4 items-center justify-center',
|
|
50
57
|
},
|
|
51
58
|
variants: {
|
|
@@ -243,9 +250,41 @@ function DayGridLegend({ color = 'primary', less = 'Less', more = 'More', classN
|
|
|
243
250
|
return (_jsxs("div", { className: slots.legend({ className }), ...props, children: [_jsx("span", { children: less }), LEVELS.map((level) => (_jsx("span", { "aria-hidden": "true", className: slots.swatch(), children: _jsx("span", { className: dayGridVariants({ level }).dot({ className: 'shadow-none' }) }) }, level))), _jsx("span", { children: more })] }));
|
|
244
251
|
}
|
|
245
252
|
DayGridLegend.displayName = 'DayGrid.Legend';
|
|
253
|
+
/**
|
|
254
|
+
* The days of the week down the side of a grid that runs a week to a column.
|
|
255
|
+
* Put it beside the grid, in a row with it. Hidden from screen readers, which
|
|
256
|
+
* are given each day's own label.
|
|
257
|
+
*/
|
|
258
|
+
function DayGridWeekdays({ labels = ['Mon', '', 'Wed', '', 'Fri', '', 'Sun'], className, style, ...props }) {
|
|
259
|
+
const slots = dayGridVariants();
|
|
260
|
+
return (_jsx("div", { "aria-hidden": "true", "data-slot": "day-grid-weekdays", className: slots.weekdays({ className }), style: { gridTemplateRows: `repeat(${labels.length}, minmax(0, 1fr))`, ...style }, ...props, children: labels.map((day, index) => (_jsx("span", { className: slots.weekday(), children: day }, index))) }));
|
|
261
|
+
}
|
|
262
|
+
DayGridWeekdays.displayName = 'DayGrid.Weekdays';
|
|
263
|
+
/**
|
|
264
|
+
* What the picked day holds, written out beside the grid: a `DayGrid.Title`
|
|
265
|
+
* over a `DayGrid.Description`. Read out politely each time the pick changes.
|
|
266
|
+
*/
|
|
267
|
+
function DayGridCaption({ className, ...props }) {
|
|
268
|
+
return (_jsx("div", { "aria-live": "polite", "data-slot": "day-grid-caption", className: dayGridVariants().caption({ className }), ...props }));
|
|
269
|
+
}
|
|
270
|
+
DayGridCaption.displayName = 'DayGrid.Caption';
|
|
271
|
+
/** The picked day's figure: "17 merged". */
|
|
272
|
+
function DayGridTitle({ className, ...props }) {
|
|
273
|
+
return _jsx("p", { "data-slot": "day-grid-title", className: dayGridVariants().title({ className }), ...props });
|
|
274
|
+
}
|
|
275
|
+
DayGridTitle.displayName = 'DayGrid.Title';
|
|
276
|
+
/** The picked day's date, quieter, under its figure. */
|
|
277
|
+
function DayGridDescription({ className, ...props }) {
|
|
278
|
+
return (_jsx("p", { "data-slot": "day-grid-description", className: dayGridVariants().description({ className }), ...props }));
|
|
279
|
+
}
|
|
280
|
+
DayGridDescription.displayName = 'DayGrid.Description';
|
|
246
281
|
export const DayGrid = Object.assign(DayGridRoot, {
|
|
247
282
|
Legend: DayGridLegend,
|
|
283
|
+
Weekdays: DayGridWeekdays,
|
|
284
|
+
Caption: DayGridCaption,
|
|
285
|
+
Title: DayGridTitle,
|
|
286
|
+
Description: DayGridDescription,
|
|
248
287
|
});
|
|
249
288
|
/* By name as well, for a Server Component, which cannot dot into a client
|
|
250
289
|
module. */
|
|
251
|
-
export { DayGridLegend };
|
|
290
|
+
export { DayGridLegend, DayGridWeekdays, DayGridCaption, DayGridTitle, DayGridDescription };
|
|
@@ -95,6 +95,52 @@ declare function FeedbackField({ value, onValueChange, minHeight, maxHeight, cla
|
|
|
95
95
|
declare namespace FeedbackField {
|
|
96
96
|
var displayName: string;
|
|
97
97
|
}
|
|
98
|
+
export interface FeedbackDescriptionProps extends ComponentProps<'p'> {
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Body text in the panel, in place of the field: a thank-you once the message
|
|
102
|
+
* has gone. In a dialog it is also what the dialog is described as.
|
|
103
|
+
*/
|
|
104
|
+
declare function FeedbackDescription({ className, ...props }: FeedbackDescriptionProps): import("react").JSX.Element;
|
|
105
|
+
declare namespace FeedbackDescription {
|
|
106
|
+
var displayName: string;
|
|
107
|
+
}
|
|
108
|
+
export interface FeedbackMessageProps extends ComponentProps<'p'> {
|
|
109
|
+
/**
|
|
110
|
+
* `muted` for a running note, read out politely as it changes: how much is
|
|
111
|
+
* left to write. `destructive` for a failure, announced at once. Default
|
|
112
|
+
* `muted`.
|
|
113
|
+
*/
|
|
114
|
+
tone?: 'muted' | 'destructive';
|
|
115
|
+
}
|
|
116
|
+
/** A short line under the field. Figures in it keep their width as they change. */
|
|
117
|
+
declare function FeedbackMessage({ tone, className, ...props }: FeedbackMessageProps): import("react").JSX.Element;
|
|
118
|
+
declare namespace FeedbackMessage {
|
|
119
|
+
var displayName: string;
|
|
120
|
+
}
|
|
121
|
+
export interface FeedbackRatingProps extends Omit<ComponentProps<'div'>, 'children'> {
|
|
122
|
+
/** The highest score. The scores run from 1 to this. Default 5. */
|
|
123
|
+
max?: number;
|
|
124
|
+
/** Called with the score that was pressed. */
|
|
125
|
+
onValueChange?: (value: number) => void;
|
|
126
|
+
/** The word under the lowest score. */
|
|
127
|
+
startLabel?: ReactNode;
|
|
128
|
+
/** The word under the highest score. */
|
|
129
|
+
endLabel?: ReactNode;
|
|
130
|
+
/**
|
|
131
|
+
* The least height it takes, in pixels. Match the field's `minHeight` on the
|
|
132
|
+
* step that follows, so the dialog keeps its size between the two.
|
|
133
|
+
*/
|
|
134
|
+
minHeight?: number;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* A row of round buttons, one per score, with a word under each end. Use it
|
|
138
|
+
* as the first step of a dialog, and ask for the words once a score is in.
|
|
139
|
+
*/
|
|
140
|
+
declare function FeedbackRating({ max, onValueChange, startLabel, endLabel, minHeight, className, style, ...props }: FeedbackRatingProps): import("react").JSX.Element;
|
|
141
|
+
declare namespace FeedbackRating {
|
|
142
|
+
var displayName: string;
|
|
143
|
+
}
|
|
98
144
|
export interface FeedbackFooterProps extends ComponentProps<'div'> {
|
|
99
145
|
}
|
|
100
146
|
/** The action row, in the band under the panel. */
|
|
@@ -128,8 +174,11 @@ export declare const Feedback: typeof FeedbackRoot & {
|
|
|
128
174
|
Title: typeof FeedbackTitle;
|
|
129
175
|
Close: typeof FeedbackClose;
|
|
130
176
|
Field: typeof FeedbackField;
|
|
177
|
+
Description: typeof FeedbackDescription;
|
|
178
|
+
Message: typeof FeedbackMessage;
|
|
179
|
+
Rating: typeof FeedbackRating;
|
|
131
180
|
Footer: typeof FeedbackFooter;
|
|
132
181
|
Cancel: typeof FeedbackCancel;
|
|
133
182
|
Submit: typeof FeedbackSubmit;
|
|
134
183
|
};
|
|
135
|
-
export { FeedbackTrigger, FeedbackContent, FeedbackPanel, FeedbackTitle, FeedbackClose, FeedbackField, FeedbackFooter, FeedbackCancel, FeedbackSubmit, };
|
|
184
|
+
export { FeedbackTrigger, FeedbackContent, FeedbackPanel, FeedbackTitle, FeedbackClose, FeedbackField, FeedbackDescription, FeedbackMessage, FeedbackRating, FeedbackFooter, FeedbackCancel, FeedbackSubmit, };
|
|
@@ -84,6 +84,14 @@ const feedbackVariants = tv({
|
|
|
84
84
|
// over the ends of its lines.
|
|
85
85
|
scrollbar: 'my-1 -me-3.5 flex w-1.5 opacity-0 transition-opacity delay-300 data-hovering:opacity-100 data-hovering:delay-0 data-hovering:duration-100 data-scrolling:opacity-100 data-scrolling:delay-0 data-scrolling:duration-100',
|
|
86
86
|
thumb: 'relative flex-1 rounded-full bg-foreground/20',
|
|
87
|
+
// Body text in the well, set like what is written in the field.
|
|
88
|
+
description: 'text-[17px] leading-6 text-muted-foreground',
|
|
89
|
+
// A line under the field: how much is left to write, or what went wrong.
|
|
90
|
+
message: 'text-sm tabular-nums',
|
|
91
|
+
rating: 'flex flex-col justify-center gap-3',
|
|
92
|
+
ratingScores: 'flex justify-between gap-2',
|
|
93
|
+
ratingScore: 'flex size-12 cursor-pointer items-center justify-center rounded-full bg-foreground/10 text-lg font-semibold transition-colors hover:bg-primary hover:text-primary-foreground',
|
|
94
|
+
ratingEnds: 'flex justify-between text-sm text-muted-foreground',
|
|
87
95
|
// Held in from the shell's edge further than the panel is. A row the full
|
|
88
96
|
// width would read as a third edge of the dialog, not as two buttons.
|
|
89
97
|
footer: 'flex items-center gap-3.5 px-[18px] pb-2.5 pt-4',
|
|
@@ -102,6 +110,10 @@ const feedbackVariants = tv({
|
|
|
102
110
|
disabled: {
|
|
103
111
|
true: { action: 'cursor-not-allowed active:scale-100' },
|
|
104
112
|
},
|
|
113
|
+
messageTone: {
|
|
114
|
+
muted: { message: 'text-muted-foreground' },
|
|
115
|
+
destructive: { message: 'text-destructive' },
|
|
116
|
+
},
|
|
105
117
|
},
|
|
106
118
|
compoundVariants: [
|
|
107
119
|
// Fainter than Cancel's own tint on purpose. Matched, they would read as
|
|
@@ -233,6 +245,33 @@ function FeedbackField({ value, onValueChange, minHeight = 200, maxHeight = 360,
|
|
|
233
245
|
}, onKeyDown: handleKeyDown, className: slots.field({ className }), style: { minHeight, ...style }, ...props }) }) }), _jsx(ScrollArea.Scrollbar, { orientation: "vertical", className: slots.scrollbar(), children: _jsx(ScrollArea.Thumb, { className: slots.thumb() }) })] }));
|
|
234
246
|
}
|
|
235
247
|
FeedbackField.displayName = 'Feedback.Field';
|
|
248
|
+
/**
|
|
249
|
+
* Body text in the panel, in place of the field: a thank-you once the message
|
|
250
|
+
* has gone. In a dialog it is also what the dialog is described as.
|
|
251
|
+
*/
|
|
252
|
+
function FeedbackDescription({ className, ...props }) {
|
|
253
|
+
const { inline } = useFeedback('Feedback.Description');
|
|
254
|
+
const slots = feedbackVariants();
|
|
255
|
+
if (inline)
|
|
256
|
+
return _jsx("p", { className: slots.description({ className }), ...props });
|
|
257
|
+
return _jsx(Dialog.Description, { className: slots.description({ className }), ...props });
|
|
258
|
+
}
|
|
259
|
+
FeedbackDescription.displayName = 'Feedback.Description';
|
|
260
|
+
/** A short line under the field. Figures in it keep their width as they change. */
|
|
261
|
+
function FeedbackMessage({ tone = 'muted', className, ...props }) {
|
|
262
|
+
const slots = feedbackVariants({ messageTone: tone });
|
|
263
|
+
return (_jsx("p", { role: tone === 'destructive' ? 'alert' : undefined, "aria-live": tone === 'destructive' ? undefined : 'polite', className: slots.message({ className }), ...props }));
|
|
264
|
+
}
|
|
265
|
+
FeedbackMessage.displayName = 'Feedback.Message';
|
|
266
|
+
/**
|
|
267
|
+
* A row of round buttons, one per score, with a word under each end. Use it
|
|
268
|
+
* as the first step of a dialog, and ask for the words once a score is in.
|
|
269
|
+
*/
|
|
270
|
+
function FeedbackRating({ max = 5, onValueChange, startLabel, endLabel, minHeight, className, style, ...props }) {
|
|
271
|
+
const slots = feedbackVariants();
|
|
272
|
+
return (_jsxs("div", { className: slots.rating({ className }), style: { minHeight, ...style }, ...props, children: [_jsx("div", { className: slots.ratingScores(), children: Array.from({ length: max }, (_, index) => index + 1).map((value) => (_jsx("button", { type: "button", "aria-label": `${value} out of ${max}`, onClick: () => onValueChange?.(value), className: slots.ratingScore(), children: value }, value))) }), startLabel !== undefined || endLabel !== undefined ? (_jsxs("div", { className: slots.ratingEnds(), children: [_jsx("span", { children: startLabel }), _jsx("span", { children: endLabel })] })) : null] }));
|
|
273
|
+
}
|
|
274
|
+
FeedbackRating.displayName = 'Feedback.Rating';
|
|
236
275
|
/** The action row, in the band under the panel. */
|
|
237
276
|
function FeedbackFooter({ className, ...props }) {
|
|
238
277
|
const slots = feedbackVariants();
|
|
@@ -274,10 +313,13 @@ export const Feedback = Object.assign(FeedbackRoot, {
|
|
|
274
313
|
Title: FeedbackTitle,
|
|
275
314
|
Close: FeedbackClose,
|
|
276
315
|
Field: FeedbackField,
|
|
316
|
+
Description: FeedbackDescription,
|
|
317
|
+
Message: FeedbackMessage,
|
|
318
|
+
Rating: FeedbackRating,
|
|
277
319
|
Footer: FeedbackFooter,
|
|
278
320
|
Cancel: FeedbackCancel,
|
|
279
321
|
Submit: FeedbackSubmit,
|
|
280
322
|
});
|
|
281
323
|
/* The parts by name, for a Server Component, which cannot dot into a client
|
|
282
324
|
module. `<FeedbackContent>` there is `<Feedback.Content>` everywhere else. */
|
|
283
|
-
export { FeedbackTrigger, FeedbackContent, FeedbackPanel, FeedbackTitle, FeedbackClose, FeedbackField, FeedbackFooter, FeedbackCancel, FeedbackSubmit, };
|
|
325
|
+
export { FeedbackTrigger, FeedbackContent, FeedbackPanel, FeedbackTitle, FeedbackClose, FeedbackField, FeedbackDescription, FeedbackMessage, FeedbackRating, FeedbackFooter, FeedbackCancel, FeedbackSubmit, };
|
|
@@ -4,7 +4,12 @@
|
|
|
4
4
|
* ```tsx
|
|
5
5
|
* <Flow>
|
|
6
6
|
* <Flow.Background variant="dots" />
|
|
7
|
-
* <Flow.Node id="source" position={{ x: 24, y: 40 }}
|
|
7
|
+
* <Flow.Node id="source" position={{ x: 24, y: 40 }}>
|
|
8
|
+
* <Flow.NodeContent>
|
|
9
|
+
* <Flow.NodeTitle>Source</Flow.NodeTitle>
|
|
10
|
+
* <Flow.NodeDescription>main</Flow.NodeDescription>
|
|
11
|
+
* </Flow.NodeContent>
|
|
12
|
+
* </Flow.Node>
|
|
8
13
|
* <Flow.Node id="build" position={{ x: 24, y: 200 }}>…</Flow.Node>
|
|
9
14
|
* <Flow.Edge from="source" to="build" dashed animated arrow />
|
|
10
15
|
* <Flow.Controls />
|
|
@@ -128,7 +133,7 @@ export interface FlowNodeProps extends Omit<ComponentProps<'div'>, 'id'> {
|
|
|
128
133
|
/** How far one arrow key press moves it, in pixels. Shift moves four times as far. */
|
|
129
134
|
moveStep?: number;
|
|
130
135
|
}
|
|
131
|
-
/** A box on the graph.
|
|
136
|
+
/** A box on the graph. Fill it with the node parts below, or with anything of your own. */
|
|
132
137
|
declare function FlowNode({ id, position, draggable, selected, onPress, onDelete, moveStep, className, style, children, ...props }: FlowNodeProps): import("react").JSX.Element;
|
|
133
138
|
declare namespace FlowNode {
|
|
134
139
|
var displayName: string;
|
|
@@ -145,6 +150,53 @@ declare function FlowGroup({ id, position, draggable, selected: _selected, onPre
|
|
|
145
150
|
declare namespace FlowGroup {
|
|
146
151
|
var displayName: string;
|
|
147
152
|
}
|
|
153
|
+
export interface FlowNodeHeaderProps extends ComponentProps<'div'> {
|
|
154
|
+
}
|
|
155
|
+
/** A strip across the top of a node, ruled off from the rest: a step number and a state. */
|
|
156
|
+
declare function FlowNodeHeader({ className, ...props }: FlowNodeHeaderProps): import("react").JSX.Element;
|
|
157
|
+
declare namespace FlowNodeHeader {
|
|
158
|
+
var displayName: string;
|
|
159
|
+
}
|
|
160
|
+
export interface FlowNodeContentProps extends ComponentProps<'div'> {
|
|
161
|
+
}
|
|
162
|
+
/** The body of a node, with the node's padding: a title over a description. */
|
|
163
|
+
declare function FlowNodeContent({ className, ...props }: FlowNodeContentProps): import("react").JSX.Element;
|
|
164
|
+
declare namespace FlowNodeContent {
|
|
165
|
+
var displayName: string;
|
|
166
|
+
}
|
|
167
|
+
export interface FlowNodeTitleProps extends ComponentProps<'p'> {
|
|
168
|
+
}
|
|
169
|
+
/** What the node is. */
|
|
170
|
+
declare function FlowNodeTitle({ className, ...props }: FlowNodeTitleProps): import("react").JSX.Element;
|
|
171
|
+
declare namespace FlowNodeTitle {
|
|
172
|
+
var displayName: string;
|
|
173
|
+
}
|
|
174
|
+
export interface FlowNodeDescriptionProps extends ComponentProps<'p'> {
|
|
175
|
+
}
|
|
176
|
+
/** A quieter line about the node. Smaller inside a `Flow.GroupItem`. */
|
|
177
|
+
declare function FlowNodeDescription({ className, ...props }: FlowNodeDescriptionProps): import("react").JSX.Element;
|
|
178
|
+
declare namespace FlowNodeDescription {
|
|
179
|
+
var displayName: string;
|
|
180
|
+
}
|
|
181
|
+
export interface FlowNodeBadgeProps extends Omit<ComponentProps<'span'>, 'color'> {
|
|
182
|
+
/** Which of the theme's roles it is tinted with. `muted` is grey. Default `muted`. */
|
|
183
|
+
color?: FlowColor | 'muted';
|
|
184
|
+
}
|
|
185
|
+
/** A word in a pill, for a node's state: done, now, waiting. */
|
|
186
|
+
declare function FlowNodeBadge({ color, className, ...props }: FlowNodeBadgeProps): import("react").JSX.Element;
|
|
187
|
+
declare namespace FlowNodeBadge {
|
|
188
|
+
var displayName: string;
|
|
189
|
+
}
|
|
190
|
+
export interface FlowGroupItemProps extends ComponentProps<'div'> {
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* One thing inside a `Flow.Group` that is not a node of its own: an icon
|
|
194
|
+
* beside a `Flow.NodeContent`. It moves with the group and edges cannot join it.
|
|
195
|
+
*/
|
|
196
|
+
declare function FlowGroupItem({ className, ...props }: FlowGroupItemProps): import("react").JSX.Element;
|
|
197
|
+
declare namespace FlowGroupItem {
|
|
198
|
+
var displayName: string;
|
|
199
|
+
}
|
|
148
200
|
export interface FlowHandleProps extends Omit<ComponentProps<'span'>, 'id'> {
|
|
149
201
|
/** A name for this handle, so an edge can be joined to it and not only to the node. */
|
|
150
202
|
id?: string;
|
|
@@ -228,8 +280,14 @@ export declare const Flow: typeof FlowRoot & {
|
|
|
228
280
|
Handle: typeof FlowHandle;
|
|
229
281
|
Edge: typeof FlowEdge;
|
|
230
282
|
Group: typeof FlowGroup;
|
|
283
|
+
GroupItem: typeof FlowGroupItem;
|
|
284
|
+
NodeHeader: typeof FlowNodeHeader;
|
|
285
|
+
NodeContent: typeof FlowNodeContent;
|
|
286
|
+
NodeTitle: typeof FlowNodeTitle;
|
|
287
|
+
NodeDescription: typeof FlowNodeDescription;
|
|
288
|
+
NodeBadge: typeof FlowNodeBadge;
|
|
231
289
|
Controls: typeof FlowControls;
|
|
232
290
|
MiniMap: typeof FlowMiniMap;
|
|
233
291
|
};
|
|
234
|
-
export { FlowBackground, FlowNode, FlowHandle, FlowEdge, FlowGroup, FlowControls, FlowMiniMap };
|
|
292
|
+
export { FlowBackground, FlowNode, FlowHandle, FlowEdge, FlowGroup, FlowGroupItem, FlowNodeHeader, FlowNodeContent, FlowNodeTitle, FlowNodeDescription, FlowNodeBadge, FlowControls, FlowMiniMap, };
|
|
235
293
|
export type { FlowSide, FlowRect, FlowPoint };
|
|
@@ -6,7 +6,12 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
6
6
|
* ```tsx
|
|
7
7
|
* <Flow>
|
|
8
8
|
* <Flow.Background variant="dots" />
|
|
9
|
-
* <Flow.Node id="source" position={{ x: 24, y: 40 }}
|
|
9
|
+
* <Flow.Node id="source" position={{ x: 24, y: 40 }}>
|
|
10
|
+
* <Flow.NodeContent>
|
|
11
|
+
* <Flow.NodeTitle>Source</Flow.NodeTitle>
|
|
12
|
+
* <Flow.NodeDescription>main</Flow.NodeDescription>
|
|
13
|
+
* </Flow.NodeContent>
|
|
14
|
+
* </Flow.Node>
|
|
10
15
|
* <Flow.Node id="build" position={{ x: 24, y: 200 }}>…</Flow.Node>
|
|
11
16
|
* <Flow.Edge from="source" to="build" dashed animated arrow />
|
|
12
17
|
* <Flow.Controls />
|
|
@@ -50,6 +55,15 @@ const flowVariants = tv({
|
|
|
50
55
|
node: 'absolute left-0 top-0 z-10 cursor-grab rounded-2xl border bg-card text-card-foreground shadow-sm outline-none transition-shadow focus-visible:ring-2 focus-visible:ring-ring active:cursor-grabbing',
|
|
51
56
|
group: 'absolute left-0 top-0 cursor-grab rounded-3xl border border-dashed bg-muted/40 p-3 pt-8 outline-none focus-visible:ring-2 focus-visible:ring-ring active:cursor-grabbing',
|
|
52
57
|
groupLabel: 'absolute start-4 top-2.5 text-xs font-medium uppercase tracking-wider text-muted-foreground',
|
|
58
|
+
// What goes inside a node. The padding is on the parts, so a header can
|
|
59
|
+
// draw its rule from edge to edge.
|
|
60
|
+
nodeHeader: 'flex items-center justify-between gap-3 border-b px-4 py-2.5',
|
|
61
|
+
// Inside a group item the item already has its padding.
|
|
62
|
+
nodeContent: 'px-4 py-3 in-data-[slot=flow-group-item]:p-0',
|
|
63
|
+
nodeTitle: 'text-sm font-medium',
|
|
64
|
+
nodeDescription: 'text-sm text-muted-foreground in-data-[slot=flow-group-item]:text-xs',
|
|
65
|
+
nodeBadge: 'rounded-full bg-[color-mix(in_oklab,var(--pu-color)_14%,transparent)] px-2 py-0.5 text-xs font-medium text-[var(--pu-color)]',
|
|
66
|
+
groupItem: 'flex items-center gap-3 rounded-xl border bg-card px-3 py-2.5 [&_svg]:size-4 [&_svg]:text-muted-foreground',
|
|
53
67
|
handle: 'absolute z-20 size-3 -translate-x-1/2 -translate-y-1/2 cursor-crosshair rounded-full border-2 border-background bg-muted-foreground outline-none transition-[scale,background-color] hover:scale-150 hover:bg-foreground focus-visible:ring-2 focus-visible:ring-ring',
|
|
54
68
|
edge: 'pointer-events-none absolute left-0 top-0 size-px overflow-visible text-[var(--pu-color)]',
|
|
55
69
|
controls: 'absolute flex flex-col divide-y divide-border overflow-hidden rounded-xl border bg-card text-card-foreground shadow-sm',
|
|
@@ -58,13 +72,16 @@ const flowVariants = tv({
|
|
|
58
72
|
},
|
|
59
73
|
variants: {
|
|
60
74
|
color: {
|
|
61
|
-
primary: { edge: '[--pu-color:var(--primary)]' },
|
|
62
|
-
info: { edge: '[--pu-color:var(--info)]' },
|
|
63
|
-
success: { edge: '[--pu-color:var(--success)]' },
|
|
64
|
-
warning: { edge: '[--pu-color:var(--warning)]' },
|
|
65
|
-
destructive: { edge: '[--pu-color:var(--destructive)]' },
|
|
75
|
+
primary: { edge: '[--pu-color:var(--primary)]', nodeBadge: '[--pu-color:var(--primary)]' },
|
|
76
|
+
info: { edge: '[--pu-color:var(--info)]', nodeBadge: '[--pu-color:var(--info)]' },
|
|
77
|
+
success: { edge: '[--pu-color:var(--success)]', nodeBadge: '[--pu-color:var(--success)]' },
|
|
78
|
+
warning: { edge: '[--pu-color:var(--warning)]', nodeBadge: '[--pu-color:var(--warning)]' },
|
|
79
|
+
destructive: { edge: '[--pu-color:var(--destructive)]', nodeBadge: '[--pu-color:var(--destructive)]' },
|
|
66
80
|
// The colour of a hairline that is meant to be seen but not looked at.
|
|
67
|
-
muted: {
|
|
81
|
+
muted: {
|
|
82
|
+
edge: '[--pu-color:var(--muted-foreground)]',
|
|
83
|
+
nodeBadge: 'bg-muted text-muted-foreground',
|
|
84
|
+
},
|
|
68
85
|
},
|
|
69
86
|
selected: { true: { node: 'z-20 ring-2 ring-ring' } },
|
|
70
87
|
position: {
|
|
@@ -474,7 +491,7 @@ function useMovable({ id, position, draggable, onPress, onDelete, moveStep, }) {
|
|
|
474
491
|
},
|
|
475
492
|
};
|
|
476
493
|
}
|
|
477
|
-
/** A box on the graph.
|
|
494
|
+
/** A box on the graph. Fill it with the node parts below, or with anything of your own. */
|
|
478
495
|
function FlowNode({ id, position, draggable = true, selected = false, onPress, onDelete, moveStep, className, style, children, ...props }) {
|
|
479
496
|
const movable = useMovable({ id, position, draggable, onPress, onDelete, moveStep });
|
|
480
497
|
return (_jsx(NodeContext.Provider, { value: id, children: _jsx("div", { ref: movable.element, "data-flow-node": id, tabIndex: 0, "aria-roledescription": "Node", "aria-selected": selected || undefined, className: flowVariants({ selected }).node({ className }), style: { ...movable.style, ...style }, ...movable.handlers, ...props, children: children }) }));
|
|
@@ -489,6 +506,39 @@ function FlowGroup({ id, position, draggable = true, selected: _selected, onPres
|
|
|
489
506
|
return (_jsx(NodeContext.Provider, { value: id, children: _jsxs("div", { ref: movable.element, "data-flow-node": id, tabIndex: 0, "aria-roledescription": "Group", className: flowVariants().group({ className }), style: { ...movable.style, ...style }, ...movable.handlers, ...props, children: [label !== undefined ? _jsx("span", { className: flowVariants().groupLabel(), children: label }) : null, children] }) }));
|
|
490
507
|
}
|
|
491
508
|
FlowGroup.displayName = 'Flow.Group';
|
|
509
|
+
/** A strip across the top of a node, ruled off from the rest: a step number and a state. */
|
|
510
|
+
function FlowNodeHeader({ className, ...props }) {
|
|
511
|
+
return _jsx("div", { "data-slot": "flow-node-header", className: flowVariants().nodeHeader({ className }), ...props });
|
|
512
|
+
}
|
|
513
|
+
FlowNodeHeader.displayName = 'Flow.NodeHeader';
|
|
514
|
+
/** The body of a node, with the node's padding: a title over a description. */
|
|
515
|
+
function FlowNodeContent({ className, ...props }) {
|
|
516
|
+
return _jsx("div", { "data-slot": "flow-node-content", className: flowVariants().nodeContent({ className }), ...props });
|
|
517
|
+
}
|
|
518
|
+
FlowNodeContent.displayName = 'Flow.NodeContent';
|
|
519
|
+
/** What the node is. */
|
|
520
|
+
function FlowNodeTitle({ className, ...props }) {
|
|
521
|
+
return _jsx("p", { "data-slot": "flow-node-title", className: flowVariants().nodeTitle({ className }), ...props });
|
|
522
|
+
}
|
|
523
|
+
FlowNodeTitle.displayName = 'Flow.NodeTitle';
|
|
524
|
+
/** A quieter line about the node. Smaller inside a `Flow.GroupItem`. */
|
|
525
|
+
function FlowNodeDescription({ className, ...props }) {
|
|
526
|
+
return (_jsx("p", { "data-slot": "flow-node-description", className: flowVariants().nodeDescription({ className }), ...props }));
|
|
527
|
+
}
|
|
528
|
+
FlowNodeDescription.displayName = 'Flow.NodeDescription';
|
|
529
|
+
/** A word in a pill, for a node's state: done, now, waiting. */
|
|
530
|
+
function FlowNodeBadge({ color = 'muted', className, ...props }) {
|
|
531
|
+
return (_jsx("span", { "data-slot": "flow-node-badge", className: flowVariants({ color }).nodeBadge({ className }), ...props }));
|
|
532
|
+
}
|
|
533
|
+
FlowNodeBadge.displayName = 'Flow.NodeBadge';
|
|
534
|
+
/**
|
|
535
|
+
* One thing inside a `Flow.Group` that is not a node of its own: an icon
|
|
536
|
+
* beside a `Flow.NodeContent`. It moves with the group and edges cannot join it.
|
|
537
|
+
*/
|
|
538
|
+
function FlowGroupItem({ className, ...props }) {
|
|
539
|
+
return _jsx("div", { "data-slot": "flow-group-item", className: flowVariants().groupItem({ className }), ...props });
|
|
540
|
+
}
|
|
541
|
+
FlowGroupItem.displayName = 'Flow.GroupItem';
|
|
492
542
|
const SIDE_STYLE = {
|
|
493
543
|
top: (offset) => ({ left: `${offset * 100}%`, top: '0%' }),
|
|
494
544
|
bottom: (offset) => ({ left: `${offset * 100}%`, top: '100%' }),
|
|
@@ -589,9 +639,15 @@ export const Flow = Object.assign(FlowRoot, {
|
|
|
589
639
|
Handle: FlowHandle,
|
|
590
640
|
Edge: FlowEdge,
|
|
591
641
|
Group: FlowGroup,
|
|
642
|
+
GroupItem: FlowGroupItem,
|
|
643
|
+
NodeHeader: FlowNodeHeader,
|
|
644
|
+
NodeContent: FlowNodeContent,
|
|
645
|
+
NodeTitle: FlowNodeTitle,
|
|
646
|
+
NodeDescription: FlowNodeDescription,
|
|
647
|
+
NodeBadge: FlowNodeBadge,
|
|
592
648
|
Controls: FlowControls,
|
|
593
649
|
MiniMap: FlowMiniMap,
|
|
594
650
|
});
|
|
595
651
|
/* By name as well, for a Server Component, which cannot dot into a client
|
|
596
652
|
module. */
|
|
597
|
-
export { FlowBackground, FlowNode, FlowHandle, FlowEdge, FlowGroup, FlowControls, FlowMiniMap };
|
|
653
|
+
export { FlowBackground, FlowNode, FlowHandle, FlowEdge, FlowGroup, FlowGroupItem, FlowNodeHeader, FlowNodeContent, FlowNodeTitle, FlowNodeDescription, FlowNodeBadge, FlowControls, FlowMiniMap, };
|
|
@@ -44,8 +44,9 @@
|
|
|
44
44
|
* ## Rows divide themselves
|
|
45
45
|
*
|
|
46
46
|
* The panel draws the hairline between its children, so no row has to know
|
|
47
|
-
* whether it is first.
|
|
48
|
-
*
|
|
47
|
+
* whether it is first. Under `band` it draws none: a figure and its chart are
|
|
48
|
+
* one thing, not two rows. A row with `href` is a link and one with `onClick`
|
|
49
|
+
* is a button, each with the hover and focus a pressable row should have, and
|
|
49
50
|
* `chevron` marks one that leads somewhere.
|
|
50
51
|
*
|
|
51
52
|
* ## It renders on the server
|
|
@@ -58,7 +59,8 @@ export type FrameVariant = 'default' | 'band' | 'inset' | 'plain';
|
|
|
58
59
|
export interface FrameProps extends ComponentProps<'div'> {
|
|
59
60
|
/**
|
|
60
61
|
* `default` sets the panel in a tray. `band` holds a bordered card in a
|
|
61
|
-
* thin muted band, for a widget showing one figure or chart
|
|
62
|
+
* thin muted band, for a widget showing one figure or chart, and its panel
|
|
63
|
+
* draws no rule between its children. `inset` floats
|
|
62
64
|
* the panel in a recessed band and gives `Frame.Footer` somewhere to sit.
|
|
63
65
|
* `plain` drops the shell, for a frame inside a container that already draws
|
|
64
66
|
* its own edge.
|
|
@@ -104,7 +106,7 @@ declare namespace FrameAction {
|
|
|
104
106
|
}
|
|
105
107
|
export interface FramePanelProps extends ComponentProps<'div'> {
|
|
106
108
|
}
|
|
107
|
-
/** The card the rows sit on. It draws the hairline between its children
|
|
109
|
+
/** The card the rows sit on. It draws the hairline between its children, except under `band`. */
|
|
108
110
|
declare function FramePanel({ className, ...props }: FramePanelProps): import("react").JSX.Element;
|
|
109
111
|
declare namespace FramePanel {
|
|
110
112
|
var displayName: string;
|
|
@@ -9,8 +9,11 @@ const frameVariants = tv({
|
|
|
9
9
|
slots: {
|
|
10
10
|
root: 'group/frame flex flex-col text-foreground',
|
|
11
11
|
header: [
|
|
12
|
-
'grid grid-cols-[minmax(0,1fr)] items-center gap-x-3
|
|
12
|
+
'grid grid-cols-[minmax(0,1fr)] items-center gap-x-3 px-4 pt-2.5 pb-3',
|
|
13
13
|
'has-data-[slot=frame-action]:grid-cols-[minmax(0,1fr)_auto]',
|
|
14
|
+
// The action spans two rows, so with no description the second is empty
|
|
15
|
+
// and a gap under the title would only add height.
|
|
16
|
+
'has-data-[slot=frame-description]:gap-y-0.5',
|
|
14
17
|
'group-data-[variant=inset]/frame:px-3 group-data-[variant=inset]/frame:pt-1 group-data-[variant=inset]/frame:pb-2.5',
|
|
15
18
|
'group-data-[variant=plain]/frame:px-1',
|
|
16
19
|
'group-data-[variant=band]/frame:px-3.5 group-data-[variant=band]/frame:py-2.5',
|
|
@@ -32,6 +35,8 @@ const frameVariants = tv({
|
|
|
32
35
|
// The panel's shape follows the root's variant, read from its data attribute.
|
|
33
36
|
panel: [
|
|
34
37
|
'flex flex-col divide-y overflow-hidden bg-card text-card-foreground',
|
|
38
|
+
// A band holds one figure, not a list of rows, so nothing in it is ruled off.
|
|
39
|
+
'group-data-[variant=band]/frame:divide-y-0',
|
|
35
40
|
'group-data-[variant=default]/frame:rounded-t-2xl group-data-[variant=default]/frame:border-t',
|
|
36
41
|
'group-data-[variant=plain]/frame:rounded-3xl group-data-[variant=plain]/frame:border group-data-[variant=plain]/frame:shadow-xs',
|
|
37
42
|
'group-data-[variant=inset]/frame:rounded-[30px] group-data-[variant=inset]/frame:bg-popover group-data-[variant=inset]/frame:text-popover-foreground group-data-[variant=inset]/frame:shadow-xs',
|
|
@@ -109,7 +114,7 @@ function FrameAction({ className, ...props }) {
|
|
|
109
114
|
return _jsx("div", { "data-slot": "frame-action", className: frameVariants().action({ className }), ...props });
|
|
110
115
|
}
|
|
111
116
|
FrameAction.displayName = 'Frame.Action';
|
|
112
|
-
/** The card the rows sit on. It draws the hairline between its children
|
|
117
|
+
/** The card the rows sit on. It draws the hairline between its children, except under `band`. */
|
|
113
118
|
function FramePanel({ className, ...props }) {
|
|
114
119
|
return _jsx("div", { "data-slot": "frame-panel", className: frameVariants().panel({ className }), ...props });
|
|
115
120
|
}
|
|
@@ -187,9 +187,11 @@ declare namespace KpiSeparator {
|
|
|
187
187
|
export interface KpiGroupProps extends ComponentProps<'div'> {
|
|
188
188
|
/** Side by side with upright rules, or stacked with level ones. */
|
|
189
189
|
orientation?: 'horizontal' | 'vertical';
|
|
190
|
+
/** Draws the group as a card of its own, for a group not already inside one. */
|
|
191
|
+
surface?: boolean;
|
|
190
192
|
}
|
|
191
193
|
/** Several metrics as one panel, with a rule between each and the next. */
|
|
192
|
-
declare function KpiGroup({ orientation, className, ...props }: KpiGroupProps): import("react").JSX.Element;
|
|
194
|
+
declare function KpiGroup({ orientation, surface, className, ...props }: KpiGroupProps): import("react").JSX.Element;
|
|
193
195
|
declare namespace KpiGroup {
|
|
194
196
|
var displayName: string;
|
|
195
197
|
}
|