panelui-web 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +43 -2
  2. package/dist/components/bar-picker/index.d.ts +61 -0
  3. package/dist/components/bar-picker/index.js +139 -0
  4. package/dist/components/command-dock/index.d.ts +118 -0
  5. package/dist/components/command-dock/index.js +239 -0
  6. package/dist/components/day-grid/index.d.ts +87 -0
  7. package/dist/components/day-grid/index.js +251 -0
  8. package/dist/components/feedback/index.d.ts +135 -0
  9. package/dist/components/feedback/index.js +283 -0
  10. package/dist/components/flow/flow-paths.d.ts +94 -0
  11. package/dist/components/flow/flow-paths.js +270 -0
  12. package/dist/components/flow/index.d.ts +235 -0
  13. package/dist/components/flow/index.js +597 -0
  14. package/dist/components/kpi/index.d.ts +211 -0
  15. package/dist/components/kpi/index.js +243 -0
  16. package/dist/components/lane-board/index.d.ts +125 -0
  17. package/dist/components/lane-board/index.js +691 -0
  18. package/dist/components/planet/index.d.ts +132 -0
  19. package/dist/components/planet/index.js +653 -0
  20. package/dist/components/planet/land.d.ts +8 -0
  21. package/dist/components/planet/land.js +122 -0
  22. package/dist/components/range-meter/index.d.ts +70 -0
  23. package/dist/components/range-meter/index.js +170 -0
  24. package/dist/components/rolling-number/index.d.ts +46 -0
  25. package/dist/components/rolling-number/index.js +81 -0
  26. package/dist/components/tilt-card/index.d.ts +60 -0
  27. package/dist/components/tilt-card/index.js +114 -0
  28. package/dist/index.d.ts +12 -0
  29. package/dist/index.js +12 -0
  30. package/dist/lib/cn.d.ts +3 -0
  31. package/dist/lib/cn.js +6 -0
  32. package/package.json +72 -4
@@ -0,0 +1,87 @@
1
+ /**
2
+ * DayGrid — a run of days as a field of dots, each sized by how much happened
3
+ * on it.
4
+ *
5
+ * ```tsx
6
+ * <DayGrid cells={days} columns={7} />
7
+ * <DayGrid.Legend />
8
+ * ```
9
+ *
10
+ * ## Size carries the amount, not only shade
11
+ *
12
+ * A day is level 0 to 4, and its dot grows with the level: a speck for a day
13
+ * with nothing on it, a full disc for the busiest. The period reads the way a
14
+ * halftone print does, heavy where a lot happened and thin where little did,
15
+ * and it still reads for someone who cannot tell two shades of one colour
16
+ * apart.
17
+ *
18
+ * ## The pointer is a lens
19
+ *
20
+ * Dots swell as the pointer comes near and settle as it leaves, so the day
21
+ * under the pointer is the largest thing on the grid and its neighbours lean
22
+ * towards it. The day's `label` is shown in a tag above it. The lens changes
23
+ * nothing about what the grid says; it is there to make one day easy to
24
+ * single out among forty.
25
+ *
26
+ * ## Days you can ask about
27
+ *
28
+ * Pass `onValueChange` and each day becomes a button. The grid then behaves as
29
+ * one control to the keyboard: a single Tab stop, with the arrow keys moving
30
+ * between days, so forty days are not forty presses of Tab.
31
+ */
32
+ import { type ComponentProps, type ReactNode } from 'react';
33
+ /** How much happened on a day: 0 is nothing, 4 is the most. */
34
+ export type DayLevel = 0 | 1 | 2 | 3 | 4;
35
+ /** Which of the theme's roles the dots are drawn in. */
36
+ export type DayGridColor = 'primary' | 'info' | 'success' | 'warning' | 'destructive';
37
+ export interface DayCell {
38
+ level: DayLevel;
39
+ /** What the day is, for the tag and a screen reader: "14 May, 6 commits". */
40
+ label?: string;
41
+ }
42
+ export interface DayGridProps extends Omit<ComponentProps<'div'>, 'children' | 'onChange' | 'color'> {
43
+ /** The days, in order. They fill the grid row by row. */
44
+ cells: DayCell[];
45
+ /** Cells per row. Seven makes each row a week. */
46
+ columns?: number;
47
+ /**
48
+ * Cells per column. Giving this fills the grid column by column, and
49
+ * `columns` is ignored. Seven makes each column a week, which lays a long
50
+ * period out wide and short.
51
+ */
52
+ rows?: number;
53
+ /** Which of the theme's roles the dots are drawn in. */
54
+ color?: DayGridColor;
55
+ /** The index of the selected day, when the caller holds it. */
56
+ value?: number | null;
57
+ /**
58
+ * Called with the index of a day when it is pressed. Passing this makes the
59
+ * days buttons; without it the grid is a picture.
60
+ */
61
+ onValueChange?: (index: number) => void;
62
+ /** Set to `false` for dots that hold still under the pointer. */
63
+ lens?: boolean;
64
+ /** What a screen reader calls the grid. */
65
+ label?: string;
66
+ }
67
+ declare function DayGridRoot({ cells, columns, rows: perColumn, color, value, onValueChange, lens, label, className, style, onPointerMove, onPointerLeave, ...props }: DayGridProps): import("react").JSX.Element;
68
+ declare namespace DayGridRoot {
69
+ var displayName: string;
70
+ }
71
+ export interface DayGridLegendProps extends Omit<ComponentProps<'div'>, 'children' | 'color'> {
72
+ /** The same role the grid is drawn in. */
73
+ color?: DayGridColor;
74
+ /** The word at the quiet end of the scale. */
75
+ less?: ReactNode;
76
+ /** The word at the busy end of the scale. */
77
+ more?: ReactNode;
78
+ }
79
+ /** The five sizes, quietest to busiest, with a word at each end. */
80
+ declare function DayGridLegend({ color, less, more, className, ...props }: DayGridLegendProps): import("react").JSX.Element;
81
+ declare namespace DayGridLegend {
82
+ var displayName: string;
83
+ }
84
+ export declare const DayGrid: typeof DayGridRoot & {
85
+ Legend: typeof DayGridLegend;
86
+ };
87
+ export { DayGridLegend };
@@ -0,0 +1,251 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * DayGrid — a run of days as a field of dots, each sized by how much happened
5
+ * on it.
6
+ *
7
+ * ```tsx
8
+ * <DayGrid cells={days} columns={7} />
9
+ * <DayGrid.Legend />
10
+ * ```
11
+ *
12
+ * ## Size carries the amount, not only shade
13
+ *
14
+ * A day is level 0 to 4, and its dot grows with the level: a speck for a day
15
+ * with nothing on it, a full disc for the busiest. The period reads the way a
16
+ * halftone print does, heavy where a lot happened and thin where little did,
17
+ * and it still reads for someone who cannot tell two shades of one colour
18
+ * apart.
19
+ *
20
+ * ## The pointer is a lens
21
+ *
22
+ * Dots swell as the pointer comes near and settle as it leaves, so the day
23
+ * under the pointer is the largest thing on the grid and its neighbours lean
24
+ * towards it. The day's `label` is shown in a tag above it. The lens changes
25
+ * nothing about what the grid says; it is there to make one day easy to
26
+ * single out among forty.
27
+ *
28
+ * ## Days you can ask about
29
+ *
30
+ * Pass `onValueChange` and each day becomes a button. The grid then behaves as
31
+ * one control to the keyboard: a single Tab stop, with the arrow keys moving
32
+ * between days, so forty days are not forty presses of Tab.
33
+ */
34
+ import { useEffect, useMemo, useRef, useState, } from 'react';
35
+ import { tv } from 'tailwind-variants';
36
+ const dayGridVariants = tv({
37
+ slots: {
38
+ root: 'relative grid w-full gap-1',
39
+ // The cell is the target and keeps its size. Only the dot inside it grows.
40
+ cell: 'relative flex aspect-square w-full items-center justify-center rounded-full outline-none',
41
+ /*
42
+ * One scale made of three parts: how big the level is, how near the
43
+ * pointer is, and whether the grid has arrived yet. Kept as variables so
44
+ * each can change without a class changing.
45
+ */
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
+ 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
+ legend: 'flex items-center gap-1.5 text-xs text-muted-foreground',
49
+ swatch: 'flex size-4 items-center justify-center',
50
+ },
51
+ variants: {
52
+ /*
53
+ * The colour is written to one variable and every dot reads it. The legend
54
+ * is a sibling of the grid, not a child, so it takes the same variant.
55
+ */
56
+ color: {
57
+ primary: { root: '[--pu-color:var(--primary)]', legend: '[--pu-color:var(--primary)]' },
58
+ info: { root: '[--pu-color:var(--info)]', legend: '[--pu-color:var(--info)]' },
59
+ success: { root: '[--pu-color:var(--success)]', legend: '[--pu-color:var(--success)]' },
60
+ warning: { root: '[--pu-color:var(--warning)]', legend: '[--pu-color:var(--warning)]' },
61
+ destructive: {
62
+ root: '[--pu-color:var(--destructive)]',
63
+ legend: '[--pu-color:var(--destructive)]',
64
+ },
65
+ },
66
+ level: {
67
+ 0: { dot: 'bg-muted-foreground/30 [--pu-size:0.2]' },
68
+ 1: { dot: 'bg-[color-mix(in_oklab,var(--pu-color)_45%,transparent)] [--pu-size:0.42]' },
69
+ 2: { dot: 'bg-[color-mix(in_oklab,var(--pu-color)_65%,transparent)] [--pu-size:0.6]' },
70
+ 3: { dot: 'bg-[color-mix(in_oklab,var(--pu-color)_85%,transparent)] [--pu-size:0.8]' },
71
+ // The busiest days carry a little light of their own.
72
+ 4: {
73
+ dot: 'bg-[var(--pu-color)] shadow-[0_0_14px_color-mix(in_oklab,var(--pu-color)_45%,transparent)] [--pu-size:1]',
74
+ },
75
+ },
76
+ interactive: {
77
+ true: {
78
+ cell: 'cursor-pointer focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background',
79
+ },
80
+ },
81
+ selected: {
82
+ true: { cell: 'ring-2 ring-foreground ring-offset-2 ring-offset-background' },
83
+ },
84
+ },
85
+ });
86
+ const LEVELS = [0, 1, 2, 3, 4];
87
+ /** How far the lens reaches, in cells. */
88
+ const LENS_REACH = 2.4;
89
+ /** Milliseconds between one diagonal of dots arriving and the next. */
90
+ const STAGGER = 22;
91
+ function DayGridRoot({ cells, columns = 7, rows: perColumn, color = 'primary', value = null, onValueChange, lens = true, label = 'Activity', className, style, onPointerMove, onPointerLeave, ...props }) {
92
+ const slots = dayGridVariants({ color });
93
+ const root = useRef(null);
94
+ const nodes = useRef([]);
95
+ const frame = useRef(0);
96
+ const interactive = onValueChange !== undefined;
97
+ // The day whose tag is showing: the one under the pointer, or with focus.
98
+ const [pointed, setPointed] = useState(null);
99
+ // The dots start at nothing and arrive along the diagonals.
100
+ const [arrived, setArrived] = useState('no');
101
+ // Which way the days run: along each row, or down each column.
102
+ const byColumn = perColumn !== undefined;
103
+ const across = byColumn ? Math.ceil(cells.length / Math.max(1, perColumn)) : columns;
104
+ const rows = byColumn ? Math.max(1, perColumn) : Math.ceil(cells.length / columns);
105
+ useEffect(() => {
106
+ const start = requestAnimationFrame(() => setArrived('arriving'));
107
+ // Once the last diagonal is in, the delays come off. Left on, they would
108
+ // hold every dot back from the lens by its own share of the stagger.
109
+ const settle = setTimeout(() => setArrived('yes'), (rows + across) * STAGGER + 450);
110
+ return () => {
111
+ cancelAnimationFrame(start);
112
+ clearTimeout(settle);
113
+ };
114
+ }, [rows, across]);
115
+ useEffect(() => () => cancelAnimationFrame(frame.current), []);
116
+ const summary = useMemo(() => {
117
+ const active = cells.filter((cell) => cell.level > 0).length;
118
+ return `${label}: something on ${active} of ${cells.length} days.`;
119
+ }, [cells, label]);
120
+ const moveLens = (event) => {
121
+ onPointerMove?.(event);
122
+ // A finger covers what a lens would show, and has no hover to end it.
123
+ if (event.pointerType === 'touch')
124
+ return;
125
+ const still = !lens || window.matchMedia('(prefers-reduced-motion: reduce)').matches;
126
+ const { clientX, clientY } = event;
127
+ cancelAnimationFrame(frame.current);
128
+ frame.current = requestAnimationFrame(() => {
129
+ let nearest = null;
130
+ let best = Infinity;
131
+ nodes.current.forEach((node, index) => {
132
+ if (!node)
133
+ return;
134
+ const box = node.getBoundingClientRect();
135
+ const distance = Math.hypot(clientX - (box.left + box.width / 2), clientY - (box.top + box.height / 2));
136
+ if (!still) {
137
+ const near = Math.max(0, 1 - distance / (box.width * LENS_REACH));
138
+ // Eased, so the swell has a soft edge and a round top.
139
+ node.style.setProperty('--pu-lens', (near * near * (3 - 2 * near)).toFixed(3));
140
+ }
141
+ if (distance < best && distance < box.width * 0.75) {
142
+ best = distance;
143
+ nearest = index;
144
+ }
145
+ });
146
+ setPointed(nearest);
147
+ });
148
+ };
149
+ const leave = (event) => {
150
+ onPointerLeave?.(event);
151
+ cancelAnimationFrame(frame.current);
152
+ for (const node of nodes.current)
153
+ node?.style.removeProperty('--pu-lens');
154
+ setPointed(null);
155
+ };
156
+ const layout = byColumn
157
+ ? {
158
+ gridTemplateRows: `repeat(${rows}, auto)`,
159
+ gridAutoFlow: 'column',
160
+ gridAutoColumns: 'minmax(0, 1fr)',
161
+ ...style,
162
+ }
163
+ : { gridTemplateColumns: `repeat(${across}, minmax(0, 1fr))`, ...style };
164
+ /** Where a dot is in its entrance, as the styles that put it there. */
165
+ const dotStyle = (index) => {
166
+ if (arrived === 'yes')
167
+ return undefined;
168
+ const diagonal = byColumn
169
+ ? Math.floor(index / rows) + (index % rows)
170
+ : Math.floor(index / across) + (index % across);
171
+ return {
172
+ ['--pu-in']: arrived === 'no' ? 0 : 1,
173
+ transitionDelay: `${diagonal * STAGGER}ms`,
174
+ transitionDuration: '420ms',
175
+ };
176
+ };
177
+ const tag = (() => {
178
+ if (pointed === null)
179
+ return null;
180
+ const text = cells[pointed]?.label;
181
+ const node = nodes.current[pointed];
182
+ const box = root.current;
183
+ if (!text || !node || !box)
184
+ return null;
185
+ const centre = node.offsetLeft + node.offsetWidth / 2;
186
+ // Hung from whichever side keeps it inside the grid.
187
+ const share = centre / box.offsetWidth;
188
+ const shift = share < 0.25 ? '-12%' : share > 0.75 ? '-88%' : '-50%';
189
+ return (_jsx("span", { "aria-hidden": "true", className: slots.tag(), style: { left: centre, top: node.offsetTop - 6, translate: `${shift} -100%` }, children: text }));
190
+ })();
191
+ if (!interactive) {
192
+ return (_jsxs("div", { ref: root, role: "img", "aria-label": summary, className: slots.root({ className }), style: layout, onPointerMove: moveLens, onPointerLeave: leave, ...props, children: [cells.map((cell, index) => {
193
+ const part = dayGridVariants({ level: cell.level });
194
+ return (_jsx("span", { ref: (node) => {
195
+ nodes.current[index] = node;
196
+ }, className: part.cell(), children: _jsx("span", { className: part.dot(), style: dotStyle(index) }) }, index));
197
+ }), tag] }));
198
+ }
199
+ // One Tab stop for the grid: the selected day, or the first.
200
+ const focusable = value !== null && value >= 0 && value < cells.length ? value : 0;
201
+ const onKeyDown = (event, index) => {
202
+ const rtl = getComputedStyle(event.currentTarget).direction === 'rtl';
203
+ const moves = {
204
+ // One day along a row, or one whole column when the days run downwards.
205
+ ArrowLeft: (rtl ? 1 : -1) * (byColumn ? rows : 1),
206
+ ArrowRight: (rtl ? -1 : 1) * (byColumn ? rows : 1),
207
+ ArrowUp: byColumn ? -1 : -across,
208
+ ArrowDown: byColumn ? 1 : across,
209
+ };
210
+ let next;
211
+ if (event.key in moves)
212
+ next = index + (moves[event.key] ?? 0);
213
+ else if (event.key === 'Home')
214
+ next = 0;
215
+ else if (event.key === 'End')
216
+ next = cells.length - 1;
217
+ if (next === undefined || next < 0 || next >= cells.length)
218
+ return;
219
+ event.preventDefault();
220
+ nodes.current[next]?.focus();
221
+ onValueChange(next);
222
+ };
223
+ return (_jsxs("div", { ref: root, role: "group", "aria-label": summary, className: slots.root({ className }), style: layout, onPointerMove: moveLens, onPointerLeave: leave, ...props, children: [cells.map((cell, index) => {
224
+ const part = dayGridVariants({
225
+ level: cell.level,
226
+ interactive: true,
227
+ selected: value === index,
228
+ });
229
+ return (_jsx("button", { ref: (node) => {
230
+ nodes.current[index] = node;
231
+ }, type: "button", "aria-label": cell.label ?? `Day ${index + 1}, level ${cell.level} of 4`, "aria-pressed": value === index, tabIndex: index === focusable ? 0 : -1, onClick: () => onValueChange(index), onKeyDown: (event) => onKeyDown(event, index), onFocus: (event) => {
232
+ // Only for focus that came from the keyboard: a click focuses
233
+ // too, and the pointer is already showing that day's tag.
234
+ if (event.currentTarget.matches(':focus-visible'))
235
+ setPointed(index);
236
+ }, onBlur: () => setPointed((current) => (current === index ? null : current)), className: part.cell(), children: _jsx("span", { className: part.dot(), style: dotStyle(index) }) }, index));
237
+ }), tag] }));
238
+ }
239
+ DayGridRoot.displayName = 'DayGrid';
240
+ /** The five sizes, quietest to busiest, with a word at each end. */
241
+ function DayGridLegend({ color = 'primary', less = 'Less', more = 'More', className, ...props }) {
242
+ const slots = dayGridVariants({ color });
243
+ 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
+ }
245
+ DayGridLegend.displayName = 'DayGrid.Legend';
246
+ export const DayGrid = Object.assign(DayGridRoot, {
247
+ Legend: DayGridLegend,
248
+ });
249
+ /* By name as well, for a Server Component, which cannot dot into a client
250
+ module. */
251
+ export { DayGridLegend };
@@ -0,0 +1,135 @@
1
+ import { type ComponentProps, type ReactElement, type ReactNode } from 'react';
2
+ export interface FeedbackProps {
3
+ children?: ReactNode;
4
+ /** Whether the dialog is open, when the caller holds that. */
5
+ open?: boolean;
6
+ /** Called when the dialog asks to open or close. */
7
+ onOpenChange?: (open: boolean) => void;
8
+ /** Whether it starts open, when the caller does not hold it. */
9
+ defaultOpen?: boolean;
10
+ /** The message, when the caller holds it. Leave unset to let the field keep it. */
11
+ value?: string;
12
+ /** The message to start with, when the caller does not hold it. */
13
+ defaultValue?: string;
14
+ /** Called with the message each time it changes. */
15
+ onValueChange?: (value: string) => void;
16
+ /**
17
+ * Whether a click outside or the Escape key closes the dialog. Turn it off
18
+ * for a message that would be lost by a stray click; Cancel and the close
19
+ * button still work.
20
+ */
21
+ dismissible?: boolean;
22
+ }
23
+ declare function FeedbackRoot({ children, open, onOpenChange, defaultOpen, value, defaultValue, onValueChange, dismissible, }: FeedbackProps): import("react").JSX.Element;
24
+ declare namespace FeedbackRoot {
25
+ var displayName: string;
26
+ }
27
+ export interface FeedbackTriggerProps extends Omit<ComponentProps<'button'>, 'children'> {
28
+ children?: ReactNode;
29
+ /**
30
+ * Your own element to be the trigger, such as a styled button. It is given
31
+ * the click handler and the attributes that tie it to the dialog.
32
+ */
33
+ render?: ReactElement;
34
+ }
35
+ /** What opens the dialog. A plain button unless `render` supplies one. */
36
+ declare function FeedbackTrigger({ render, children, ...props }: FeedbackTriggerProps): import("react").JSX.Element;
37
+ declare namespace FeedbackTrigger {
38
+ var displayName: string;
39
+ }
40
+ export interface FeedbackContentProps extends Omit<ComponentProps<'div'>, 'children'> {
41
+ children?: ReactNode;
42
+ /**
43
+ * Draw it in the page instead of over it: no backdrop, no trigger, always
44
+ * there. For a feedback box that is part of the page, such as the end of an
45
+ * article. `open` is ignored, and Cancel and the close button only report
46
+ * through `onOpenChange`.
47
+ */
48
+ inline?: boolean;
49
+ /** Frost the page behind the dialog instead of only dimming it. */
50
+ blur?: boolean;
51
+ }
52
+ /** The shell: the darker band, and everything set in it. */
53
+ declare function FeedbackContent({ inline, blur, className, children, ...props }: FeedbackContentProps): import("react").JSX.Element;
54
+ declare namespace FeedbackContent {
55
+ var displayName: string;
56
+ }
57
+ export interface FeedbackPanelProps extends ComponentProps<'div'> {
58
+ }
59
+ /** The well set into the shell: the title, the close button and the field. */
60
+ declare function FeedbackPanel({ className, ...props }: FeedbackPanelProps): import("react").JSX.Element;
61
+ declare namespace FeedbackPanel {
62
+ var displayName: string;
63
+ }
64
+ export interface FeedbackTitleProps extends ComponentProps<'h2'> {
65
+ }
66
+ /** The question. In a dialog it is also what the dialog is announced as. */
67
+ declare function FeedbackTitle({ className, ...props }: FeedbackTitleProps): import("react").JSX.Element;
68
+ declare namespace FeedbackTitle {
69
+ var displayName: string;
70
+ }
71
+ export interface FeedbackCloseProps extends Omit<ComponentProps<'button'>, 'children'> {
72
+ /** How the button announces itself to a screen reader. */
73
+ label?: string;
74
+ }
75
+ /** The ✕ in the panel's corner. */
76
+ declare function FeedbackClose({ label, className, onClick, ...props }: FeedbackCloseProps): import("react").JSX.Element;
77
+ declare namespace FeedbackClose {
78
+ var displayName: string;
79
+ }
80
+ export interface FeedbackFieldProps extends Omit<ComponentProps<'textarea'>, 'value' | 'defaultValue' | 'onChange'> {
81
+ /** The message. Leave unset to let the dialog hold it. */
82
+ value?: string;
83
+ /** Called with the message each time it changes. */
84
+ onValueChange?: (value: string) => void;
85
+ /** Room to write in, in pixels, before the field starts to grow. */
86
+ minHeight?: number;
87
+ /** How tall the field may grow, in pixels, before the area round it scrolls. */
88
+ maxHeight?: number;
89
+ }
90
+ /**
91
+ * What is being written. No border and no background of its own: it is
92
+ * already inside a well.
93
+ */
94
+ declare function FeedbackField({ value, onValueChange, minHeight, maxHeight, className, style, onKeyDown, ref, 'aria-label': ariaLabel, ...props }: FeedbackFieldProps): import("react").JSX.Element;
95
+ declare namespace FeedbackField {
96
+ var displayName: string;
97
+ }
98
+ export interface FeedbackFooterProps extends ComponentProps<'div'> {
99
+ }
100
+ /** The action row, in the band under the panel. */
101
+ declare function FeedbackFooter({ className, ...props }: FeedbackFooterProps): import("react").JSX.Element;
102
+ declare namespace FeedbackFooter {
103
+ var displayName: string;
104
+ }
105
+ export interface FeedbackActionProps extends ComponentProps<'button'> {
106
+ }
107
+ /** Discards and closes. Call `preventDefault` in `onClick` to keep it open. */
108
+ declare function FeedbackCancel({ children, className, disabled, onClick, ...props }: FeedbackActionProps): import("react").JSX.Element;
109
+ declare namespace FeedbackCancel {
110
+ var displayName: string;
111
+ }
112
+ export interface FeedbackSubmitProps extends Omit<FeedbackActionProps, 'onSubmit'> {
113
+ /**
114
+ * Called with the message. The dialog stays open: close it yourself once
115
+ * the message has been sent, so a failure still has somewhere to be shown.
116
+ */
117
+ onSubmit?: (value: string) => void;
118
+ }
119
+ /** Sends. Inert while the field is empty, unless `disabled` says otherwise. */
120
+ declare function FeedbackSubmit({ children, className, disabled, onClick, onSubmit, ...props }: FeedbackSubmitProps): import("react").JSX.Element;
121
+ declare namespace FeedbackSubmit {
122
+ var displayName: string;
123
+ }
124
+ export declare const Feedback: typeof FeedbackRoot & {
125
+ Trigger: typeof FeedbackTrigger;
126
+ Content: typeof FeedbackContent;
127
+ Panel: typeof FeedbackPanel;
128
+ Title: typeof FeedbackTitle;
129
+ Close: typeof FeedbackClose;
130
+ Field: typeof FeedbackField;
131
+ Footer: typeof FeedbackFooter;
132
+ Cancel: typeof FeedbackCancel;
133
+ Submit: typeof FeedbackSubmit;
134
+ };
135
+ export { FeedbackTrigger, FeedbackContent, FeedbackPanel, FeedbackTitle, FeedbackClose, FeedbackField, FeedbackFooter, FeedbackCancel, FeedbackSubmit, };