panelui-web 0.1.0 → 0.3.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.
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Card — a surface that holds one thing: a plan, a setting, a summary.
3
+ *
4
+ * ```tsx
5
+ * <Card>
6
+ * <Card.Header>
7
+ * <Card.Title>Storage</Card.Title>
8
+ * <Card.Description>Northwind Studio workspace</Card.Description>
9
+ * <Card.Action><Button variant="ghost">Manage</Button></Card.Action>
10
+ * </Card.Header>
11
+ * <Card.Content>…</Card.Content>
12
+ * <Card.Footer variant="panel">…</Card.Footer>
13
+ * </Card>
14
+ * ```
15
+ *
16
+ * ## The padding is on the parts
17
+ *
18
+ * The card itself draws a surface and nothing inside it, and every part
19
+ * carries its own padding. That is what lets a picture reach the card's
20
+ * corners with nothing but `overflow-hidden` on the card, and what lets a
21
+ * footer be a band set into the bottom of it rather than one more row.
22
+ *
23
+ * ## The action sits beside the heading
24
+ *
25
+ * `Card.Action` is placed in the header's top trailing corner whatever order
26
+ * it is written in, and the title and description keep the rest of the width.
27
+ * A button that belongs to the whole card goes there; one that belongs to the
28
+ * content goes in the content.
29
+ *
30
+ * ## It renders on the server
31
+ *
32
+ * No state, no effects, no handlers of its own: everything that changes with
33
+ * `size` or with the parts present is done in CSS, so a page of cards costs no
34
+ * JavaScript.
35
+ */
36
+ import type { ComponentProps } from 'react';
37
+ export interface CardProps extends ComponentProps<'div'> {
38
+ /** `sm` tightens the padding and the title, for a card in a dense grid. Default `default`. */
39
+ size?: 'default' | 'sm';
40
+ /**
41
+ * The element to render. `article` for a card that stands on its own, `li`
42
+ * for one in a list, `section` for one that groups a part of a page.
43
+ */
44
+ as?: 'div' | 'article' | 'section' | 'li';
45
+ }
46
+ declare function CardRoot({ size, as: Element, className, ...props }: CardProps): import("react").JSX.Element;
47
+ declare namespace CardRoot {
48
+ var displayName: string;
49
+ }
50
+ export interface CardHeaderProps extends ComponentProps<'div'> {
51
+ }
52
+ /** The title, the line under it, and the action beside them. */
53
+ declare function CardHeader({ className, ...props }: CardHeaderProps): import("react").JSX.Element;
54
+ declare namespace CardHeader {
55
+ var displayName: string;
56
+ }
57
+ export interface CardTitleProps extends ComponentProps<'h3'> {
58
+ /** The heading level, to fit the page around the card. Default `h3`. */
59
+ as?: 'h2' | 'h3' | 'h4' | 'div';
60
+ }
61
+ /** What the card is about. A heading, so the page outline includes it. */
62
+ declare function CardTitle({ as: Element, className, ...props }: CardTitleProps): import("react").JSX.Element;
63
+ declare namespace CardTitle {
64
+ var displayName: string;
65
+ }
66
+ export interface CardDescriptionProps extends ComponentProps<'p'> {
67
+ }
68
+ /** A line under the title. */
69
+ declare function CardDescription({ className, ...props }: CardDescriptionProps): import("react").JSX.Element;
70
+ declare namespace CardDescription {
71
+ var displayName: string;
72
+ }
73
+ export interface CardActionProps extends ComponentProps<'div'> {
74
+ }
75
+ /** A control for the whole card, held in the header's top trailing corner. */
76
+ declare function CardAction({ className, ...props }: CardActionProps): import("react").JSX.Element;
77
+ declare namespace CardAction {
78
+ var displayName: string;
79
+ }
80
+ export interface CardContentProps extends ComponentProps<'div'> {
81
+ }
82
+ /** The body. */
83
+ declare function CardContent({ className, ...props }: CardContentProps): import("react").JSX.Element;
84
+ declare namespace CardContent {
85
+ var displayName: string;
86
+ }
87
+ export interface CardFooterProps extends ComponentProps<'div'> {
88
+ /**
89
+ * `plain` continues the card. `panel` is a darker band set into its bottom,
90
+ * for actions. Default `plain`.
91
+ */
92
+ variant?: 'plain' | 'panel';
93
+ }
94
+ /** The row at the bottom, usually the card's actions. */
95
+ declare function CardFooter({ variant, className, ...props }: CardFooterProps): import("react").JSX.Element;
96
+ declare namespace CardFooter {
97
+ var displayName: string;
98
+ }
99
+ export declare const Card: typeof CardRoot & {
100
+ Header: typeof CardHeader;
101
+ Title: typeof CardTitle;
102
+ Description: typeof CardDescription;
103
+ Action: typeof CardAction;
104
+ Content: typeof CardContent;
105
+ Footer: typeof CardFooter;
106
+ };
107
+ export { CardHeader, CardTitle, CardDescription, CardAction, CardContent, CardFooter };
@@ -0,0 +1,88 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { tv } from 'tailwind-variants';
3
+ const cardVariants = tv({
4
+ slots: {
5
+ root: 'group/card flex flex-col rounded-2xl border bg-card text-card-foreground shadow-xs',
6
+ header: [
7
+ 'grid auto-rows-min grid-cols-[minmax(0,1fr)] items-start gap-x-4 gap-y-1.5 p-6',
8
+ 'has-data-[slot=card-action]:grid-cols-[minmax(0,1fr)_auto]',
9
+ 'group-data-[size=sm]/card:gap-y-1 group-data-[size=sm]/card:p-4',
10
+ ],
11
+ title: 'text-lg font-semibold leading-tight tracking-[-0.01em] group-data-[size=sm]/card:text-base',
12
+ description: 'text-sm text-muted-foreground',
13
+ // Its own column, across both of the heading's rows, so a long title wraps
14
+ // beside it instead of underneath it.
15
+ action: 'col-start-2 row-span-2 row-start-1 self-start justify-self-end',
16
+ // `first:` for a card with no header, which would otherwise start flush.
17
+ content: 'px-6 pb-6 first:pt-6 group-data-[size=sm]/card:px-4 group-data-[size=sm]/card:pb-4 group-data-[size=sm]/card:first:pt-4',
18
+ footer: 'flex items-center gap-2',
19
+ },
20
+ variants: {
21
+ footer: {
22
+ /** Part of the card: same surface, continuing the content's padding. */
23
+ plain: {
24
+ footer: 'px-6 pb-6 first:pt-6 group-data-[size=sm]/card:px-4 group-data-[size=sm]/card:pb-4 group-data-[size=sm]/card:first:pt-4',
25
+ },
26
+ /**
27
+ * A band set into the bottom of the card: a rule across its top, a step
28
+ * darker, and the card's own bottom corners. For a footer that is what
29
+ * somebody does with the card, not more of what it says.
30
+ */
31
+ panel: {
32
+ footer: 'mt-auto rounded-b-[calc(var(--radius-2xl)-1px)] border-t bg-muted/60 px-6 py-4 group-data-[size=sm]/card:px-4 group-data-[size=sm]/card:py-3',
33
+ },
34
+ },
35
+ },
36
+ });
37
+ function CardRoot({ size = 'default', as: Element = 'div', className, ...props }) {
38
+ const slots = cardVariants();
39
+ const Tag = Element;
40
+ return _jsx(Tag, { "data-slot": "card", "data-size": size, className: slots.root({ className }), ...props });
41
+ }
42
+ CardRoot.displayName = 'Card';
43
+ /** The title, the line under it, and the action beside them. */
44
+ function CardHeader({ className, ...props }) {
45
+ const slots = cardVariants();
46
+ return _jsx("div", { "data-slot": "card-header", className: slots.header({ className }), ...props });
47
+ }
48
+ CardHeader.displayName = 'Card.Header';
49
+ /** What the card is about. A heading, so the page outline includes it. */
50
+ function CardTitle({ as: Element = 'h3', className, ...props }) {
51
+ const slots = cardVariants();
52
+ const Tag = Element;
53
+ return _jsx(Tag, { "data-slot": "card-title", className: slots.title({ className }), ...props });
54
+ }
55
+ CardTitle.displayName = 'Card.Title';
56
+ /** A line under the title. */
57
+ function CardDescription({ className, ...props }) {
58
+ const slots = cardVariants();
59
+ return _jsx("p", { "data-slot": "card-description", className: slots.description({ className }), ...props });
60
+ }
61
+ CardDescription.displayName = 'Card.Description';
62
+ /** A control for the whole card, held in the header's top trailing corner. */
63
+ function CardAction({ className, ...props }) {
64
+ const slots = cardVariants();
65
+ return _jsx("div", { "data-slot": "card-action", className: slots.action({ className }), ...props });
66
+ }
67
+ CardAction.displayName = 'Card.Action';
68
+ /** The body. */
69
+ function CardContent({ className, ...props }) {
70
+ const slots = cardVariants();
71
+ return _jsx("div", { "data-slot": "card-content", className: slots.content({ className }), ...props });
72
+ }
73
+ CardContent.displayName = 'Card.Content';
74
+ /** The row at the bottom, usually the card's actions. */
75
+ function CardFooter({ variant = 'plain', className, ...props }) {
76
+ const slots = cardVariants({ footer: variant });
77
+ return _jsx("div", { "data-slot": "card-footer", className: slots.footer({ className }), ...props });
78
+ }
79
+ CardFooter.displayName = 'Card.Footer';
80
+ export const Card = Object.assign(CardRoot, {
81
+ Header: CardHeader,
82
+ Title: CardTitle,
83
+ Description: CardDescription,
84
+ Action: CardAction,
85
+ Content: CardContent,
86
+ Footer: CardFooter,
87
+ });
88
+ export { CardHeader, CardTitle, CardDescription, CardAction, CardContent, CardFooter };
@@ -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) => <CommandDock.Row key={row.id}>{row.text}</CommandDock.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) => <CommandDock.Row key={row.id}>{row.text}</CommandDock.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 }}>…</Flow.Node>
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. Whatever is inside it is yours. */
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 };