@tulipfarm/sprout 0.3.1 → 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/README.md +45 -40
- package/dist/components/accordion.d.ts +2 -2
- package/dist/components/accordion.js +9 -9
- package/dist/components/agent-fanout.d.ts +2 -2
- package/dist/components/agent-fanout.js +65 -87
- package/dist/components/alert-dialog.d.ts +6 -6
- package/dist/components/alert-dialog.js +20 -20
- package/dist/components/alert.d.ts +6 -6
- package/dist/components/alert.js +13 -13
- package/dist/components/aspect-ratio.d.ts +2 -2
- package/dist/components/aspect-ratio.js +2 -2
- package/dist/components/attachment.d.ts +17 -17
- package/dist/components/attachment.js +82 -115
- package/dist/components/avatar.d.ts +10 -10
- package/dist/components/avatar.js +14 -14
- package/dist/components/badge.d.ts +4 -4
- package/dist/components/badge.js +18 -18
- package/dist/components/board.d.ts +107 -0
- package/dist/components/board.js +640 -0
- package/dist/components/brand-icon.d.ts +6 -6
- package/dist/components/brand-icon.js +55 -63
- package/dist/components/breadcrumb.d.ts +11 -11
- package/dist/components/breadcrumb.js +16 -18
- package/dist/components/button-group.d.ts +6 -6
- package/dist/components/button-group.js +14 -14
- package/dist/components/button.d.ts +11 -11
- package/dist/components/button.js +46 -56
- package/dist/components/calendar.d.ts +5 -5
- package/dist/components/calendar.js +44 -53
- package/dist/components/canvas.d.ts +4 -4
- package/dist/components/canvas.js +39 -46
- package/dist/components/card.d.ts +6 -6
- package/dist/components/card.js +17 -17
- package/dist/components/carousel.d.ts +7 -7
- package/dist/components/carousel.js +57 -75
- package/dist/components/chart.d.ts +5 -112
- package/dist/components/chart.js +5 -172
- package/dist/components/chat-confirmation.d.ts +10 -10
- package/dist/components/chat-confirmation.js +32 -38
- package/dist/components/chat-input.d.ts +4 -4
- package/dist/components/chat-input.js +74 -81
- package/dist/components/chat-plan.d.ts +2 -2
- package/dist/components/chat-plan.js +15 -20
- package/dist/components/chat-sources.d.ts +8 -8
- package/dist/components/chat-sources.js +18 -27
- package/dist/components/checkbox.d.ts +1 -1
- package/dist/components/checkbox.js +9 -9
- package/dist/components/choice-list.d.ts +2 -2
- package/dist/components/choice-list.js +16 -18
- package/dist/components/code-block.d.ts +5 -5
- package/dist/components/code-block.js +26 -26
- package/dist/components/collapsible.d.ts +1 -1
- package/dist/components/collapsible.js +7 -11
- package/dist/components/combobox.d.ts +3 -3
- package/dist/components/combobox.js +24 -24
- package/dist/components/command.d.ts +13 -13
- package/dist/components/command.js +61 -73
- package/dist/components/context-menu.d.ts +5 -5
- package/dist/components/context-menu.js +22 -22
- package/dist/components/dialog.d.ts +6 -6
- package/dist/components/dialog.js +23 -28
- package/dist/components/direction.d.ts +1 -1
- package/dist/components/direction.js +1 -1
- package/dist/components/dropdown-menu.d.ts +5 -5
- package/dist/components/dropdown-menu.js +20 -20
- package/dist/components/field.d.ts +11 -11
- package/dist/components/field.js +41 -61
- package/dist/components/file-explorer.d.ts +2 -2
- package/dist/components/file-explorer.js +89 -105
- package/dist/components/file-viewer.d.ts +10 -10
- package/dist/components/file-viewer.js +112 -140
- package/dist/components/form.d.ts +7 -7
- package/dist/components/form.js +24 -28
- package/dist/components/glass-banner.d.ts +3 -3
- package/dist/components/glass-banner.js +21 -24
- package/dist/components/gradient-banner.d.ts +5 -5
- package/dist/components/gradient-banner.js +13 -22
- package/dist/components/hover-card.d.ts +4 -4
- package/dist/components/hover-card.js +6 -6
- package/dist/components/input-group.d.ts +11 -11
- package/dist/components/input-group.js +22 -36
- package/dist/components/input-otp.d.ts +10 -10
- package/dist/components/input-otp.js +13 -15
- package/dist/components/input.d.ts +1 -1
- package/dist/components/input.js +7 -7
- package/dist/components/kbd.d.ts +3 -3
- package/dist/components/kbd.js +5 -5
- package/dist/components/label.d.ts +2 -2
- package/dist/components/label.js +2 -2
- package/dist/components/mention-list.d.ts +3 -3
- package/dist/components/mention-list.js +10 -10
- package/dist/components/menubar.d.ts +6 -6
- package/dist/components/menubar.js +22 -22
- package/dist/components/message-actions.d.ts +2 -2
- package/dist/components/message-actions.js +29 -31
- package/dist/components/message-response.d.ts +3 -3
- package/dist/components/message-response.js +18 -18
- package/dist/components/message-scroller.d.ts +12 -12
- package/dist/components/message-scroller.js +44 -56
- package/dist/components/message.d.ts +11 -11
- package/dist/components/message.js +25 -25
- package/dist/components/navigation-menu.d.ts +2 -2
- package/dist/components/navigation-menu.js +15 -15
- package/dist/components/notice-banner.d.ts +2 -2
- package/dist/components/notice-banner.js +2 -2
- package/dist/components/page-content.d.ts +2 -2
- package/dist/components/page-content.js +2 -2
- package/dist/components/page-header.d.ts +1 -1
- package/dist/components/page-header.js +16 -16
- package/dist/components/pagination.d.ts +9 -9
- package/dist/components/pagination.js +17 -17
- package/dist/components/plan-outline.d.ts +2 -2
- package/dist/components/plan-outline.js +43 -60
- package/dist/components/popover.d.ts +6 -6
- package/dist/components/popover.js +15 -15
- package/dist/components/presence-cursor.d.ts +2 -2
- package/dist/components/presence-cursor.js +3 -3
- package/dist/components/progress.d.ts +1 -1
- package/dist/components/progress.js +8 -8
- package/dist/components/prompt-list.d.ts +3 -3
- package/dist/components/prompt-list.js +6 -6
- package/dist/components/questionnaire.d.ts +19 -19
- package/dist/components/questionnaire.js +183 -242
- package/dist/components/radio-group.d.ts +2 -2
- package/dist/components/radio-group.js +6 -6
- package/dist/components/reasoning-effort.d.ts +3 -3
- package/dist/components/reasoning-effort.js +9 -12
- package/dist/components/record-list.d.ts +66 -0
- package/dist/components/record-list.js +151 -0
- package/dist/components/resizable.d.ts +5 -5
- package/dist/components/resizable.js +76 -102
- package/dist/components/result-card.d.ts +4 -4
- package/dist/components/result-card.js +42 -53
- package/dist/components/result-notice.d.ts +18 -0
- package/dist/components/result-notice.js +29 -0
- package/dist/components/review-card.d.ts +6 -6
- package/dist/components/review-card.js +18 -18
- package/dist/components/rich-text-editor.d.ts +2 -2
- package/dist/components/rich-text-editor.js +56 -72
- package/dist/components/schema-diagram.d.ts +3 -3
- package/dist/components/schema-diagram.js +39 -53
- package/dist/components/scroll-area.d.ts +1 -1
- package/dist/components/scroll-area.js +10 -14
- package/dist/components/search-dialog.d.ts +6 -6
- package/dist/components/search-dialog.js +16 -16
- package/dist/components/search-field.d.ts +1 -1
- package/dist/components/search-field.js +11 -11
- package/dist/components/select.d.ts +3 -3
- package/dist/components/select.js +20 -20
- package/dist/components/selection-slot.d.ts +2 -2
- package/dist/components/selection-slot.js +6 -9
- package/dist/components/separator.d.ts +15 -15
- package/dist/components/separator.js +22 -27
- package/dist/components/settings-list.d.ts +3 -3
- package/dist/components/settings-list.js +5 -5
- package/dist/components/sheet.d.ts +6 -6
- package/dist/components/sheet.js +27 -27
- package/dist/components/sidebar.d.ts +22 -22
- package/dist/components/sidebar.js +57 -58
- package/dist/components/skeleton.d.ts +5 -5
- package/dist/components/skeleton.js +14 -21
- package/dist/components/slider.d.ts +2 -2
- package/dist/components/slider.js +6 -6
- package/dist/components/spinner.d.ts +5 -5
- package/dist/components/spinner.js +22 -26
- package/dist/components/sql-viewer.d.ts +14 -14
- package/dist/components/sql-viewer.js +99 -128
- package/dist/components/state-panel-samples.d.ts +2 -2
- package/dist/components/state-panel-samples.js +209 -245
- package/dist/components/state-panel.d.ts +2 -35
- package/dist/components/state-panel.js +2 -29
- package/dist/components/state-sample.d.ts +7 -7
- package/dist/components/state-sample.js +18 -31
- package/dist/components/switch.d.ts +1 -1
- package/dist/components/switch.js +7 -7
- package/dist/components/table-nuqs.d.ts +2 -2
- package/dist/components/table-nuqs.js +11 -12
- package/dist/components/table.d.ts +4 -4
- package/dist/components/table.js +166 -235
- package/dist/components/tabs.d.ts +2 -2
- package/dist/components/tabs.js +12 -12
- package/dist/components/textarea.d.ts +2 -2
- package/dist/components/textarea.js +6 -8
- package/dist/components/timeline.d.ts +3 -0
- package/dist/components/timeline.js +3 -0
- package/dist/components/toast.d.ts +2 -2
- package/dist/components/toast.js +19 -25
- package/dist/components/toggle-group.d.ts +2 -2
- package/dist/components/toggle-group.js +18 -20
- package/dist/components/toggle.d.ts +2 -2
- package/dist/components/toggle.js +8 -8
- package/dist/components/tool-activity.d.ts +1 -1
- package/dist/components/tool-activity.js +83 -110
- package/dist/components/toolbar-status.d.ts +2 -2
- package/dist/components/toolbar-status.js +7 -7
- package/dist/components/tooltip.d.ts +5 -5
- package/dist/components/tooltip.js +12 -11
- package/dist/components/typed-text.d.ts +2 -2
- package/dist/components/typed-text.js +10 -12
- package/dist/components/view-switcher.d.ts +51 -0
- package/dist/components/view-switcher.js +114 -0
- package/dist/index.d.ts +98 -93
- package/dist/index.js +98 -93
- package/dist/internal/chart-kit.d.ts +142 -0
- package/dist/internal/chart-kit.js +200 -0
- package/dist/internal/charts/bars.d.ts +61 -0
- package/dist/internal/charts/bars.js +86 -0
- package/dist/internal/charts/lines.d.ts +67 -0
- package/dist/internal/charts/lines.js +70 -0
- package/dist/internal/charts/more.d.ts +77 -0
- package/dist/internal/charts/more.js +68 -0
- package/dist/internal/charts/parts.d.ts +54 -0
- package/dist/internal/charts/parts.js +82 -0
- package/dist/internal/charts/timeline-dates.d.ts +38 -0
- package/dist/internal/charts/timeline-dates.js +113 -0
- package/dist/internal/charts/timeline-window.d.ts +31 -0
- package/dist/internal/charts/timeline-window.js +26 -0
- package/dist/internal/charts/timeline.d.ts +72 -0
- package/dist/internal/charts/timeline.js +287 -0
- package/dist/internal/classes.d.ts +1 -1
- package/dist/internal/classes.js +7 -9
- package/dist/internal/code-tokens.d.ts +2 -2
- package/dist/internal/code-tokens.js +12 -12
- package/dist/internal/fieldset.d.ts +1 -1
- package/dist/internal/fieldset.js +6 -6
- package/dist/internal/file-kind.d.ts +1 -1
- package/dist/internal/file-kind.js +43 -51
- package/dist/internal/flow.d.ts +4 -4
- package/dist/internal/flow.js +20 -23
- package/dist/internal/languages.js +999 -999
- package/dist/internal/message-scroller.d.ts +3 -3
- package/dist/internal/message-scroller.js +64 -112
- package/dist/internal/pressable.d.ts +1 -1
- package/dist/internal/pressable.js +7 -7
- package/dist/internal/state-panel.d.ts +35 -0
- package/dist/internal/state-panel.js +22 -0
- package/dist/internal/syntax.d.ts +2 -2
- package/dist/internal/syntax.js +36 -47
- package/dist/styles/accordion.css +3 -5
- package/dist/styles/agent-fanout.css +64 -60
- package/dist/styles/alert-dialog.css +12 -26
- package/dist/styles/alert.css +10 -15
- package/dist/styles/attachment.css +51 -93
- package/dist/styles/avatar.css +17 -24
- package/dist/styles/badge.css +11 -36
- package/dist/styles/board.css +571 -0
- package/dist/styles/brand-icon.css +7 -8
- package/dist/styles/breadcrumb.css +4 -7
- package/dist/styles/button-group.css +8 -14
- package/dist/styles/button.css +22 -27
- package/dist/styles/calendar.css +24 -36
- package/dist/styles/canvas.css +2 -3
- package/dist/styles/card.css +7 -23
- package/dist/styles/carousel.css +11 -12
- package/dist/styles/chart.css +215 -31
- package/dist/styles/chat-input.css +15 -39
- package/dist/styles/chat-plan.css +3 -4
- package/dist/styles/chat-sources.css +3 -6
- package/dist/styles/checkbox.css +11 -25
- package/dist/styles/choice-list.css +17 -31
- package/dist/styles/code-block.css +11 -25
- package/dist/styles/collapsible.css +10 -15
- package/dist/styles/combobox.css +11 -15
- package/dist/styles/command.css +5 -8
- package/dist/styles/context-menu.css +2 -2
- package/dist/styles/dialog.css +5 -16
- package/dist/styles/dropdown-menu.css +2 -2
- package/dist/styles/field.css +15 -21
- package/dist/styles/file-explorer.css +19 -33
- package/dist/styles/file-viewer.css +13 -17
- package/dist/styles/form.css +3 -3
- package/dist/styles/glass-banner.css +12 -47
- package/dist/styles/gradient-banner.css +17 -35
- package/dist/styles/hover-card.css +9 -15
- package/dist/styles/index.css +116 -108
- package/dist/styles/input-group.css +25 -41
- package/dist/styles/input-otp.css +5 -6
- package/dist/styles/input.css +5 -5
- package/dist/styles/kbd.css +1 -1
- package/dist/styles/label.css +9 -30
- package/dist/styles/mention-list.css +6 -8
- package/dist/styles/menubar.css +5 -6
- package/dist/styles/message-actions.css +1 -1
- package/dist/styles/message-response.css +3 -5
- package/dist/styles/message-scroller.css +14 -21
- package/dist/styles/message.css +23 -60
- package/dist/styles/navigation-menu.css +14 -29
- package/dist/styles/notice-banner.css +1 -2
- package/dist/styles/page-header.css +7 -10
- package/dist/styles/pagination.css +1 -4
- package/dist/styles/plan-outline.css +20 -37
- package/dist/styles/popover.css +10 -19
- package/dist/styles/presence-cursor.css +1 -2
- package/dist/styles/progress.css +2 -4
- package/dist/styles/prompt-list.css +6 -17
- package/dist/styles/questionnaire.css +16 -40
- package/dist/styles/radio-group.css +12 -23
- package/dist/styles/reasoning-effort.css +8 -15
- package/dist/styles/record-list.css +243 -0
- package/dist/styles/resizable.css +10 -11
- package/dist/styles/result-card.css +3 -3
- package/dist/styles/result-notice.css +80 -0
- package/dist/styles/review-card.css +2 -3
- package/dist/styles/rich-text-editor.css +1 -2
- package/dist/styles/schema-diagram.css +12 -17
- package/dist/styles/scroll-area.css +8 -10
- package/dist/styles/search-dialog.css +1 -5
- package/dist/styles/search-field.css +1 -2
- package/dist/styles/select.css +7 -7
- package/dist/styles/selection-slot.css +1 -2
- package/dist/styles/separator.css +7 -8
- package/dist/styles/settings-list.css +1 -2
- package/dist/styles/sheet.css +40 -73
- package/dist/styles/sidebar.css +17 -21
- package/dist/styles/skeleton.css +9 -11
- package/dist/styles/slider.css +11 -21
- package/dist/styles/spinner.css +2 -2
- package/dist/styles/sql-viewer.css +29 -29
- package/dist/styles/state-panel.css +8 -9
- package/dist/styles/state-sample.css +20 -33
- package/dist/styles/switch.css +11 -18
- package/dist/styles/table.css +51 -77
- package/dist/styles/tabs.css +12 -16
- package/dist/styles/textarea.css +3 -3
- package/dist/styles/themes/chatgpt.css +11 -23
- package/dist/styles/themes/claude.css +12 -24
- package/dist/styles/themes/cloudflare.css +11 -23
- package/dist/styles/themes/discord.css +11 -23
- package/dist/styles/themes/github.css +11 -23
- package/dist/styles/themes/grok.css +11 -23
- package/dist/styles/themes/linear.css +12 -25
- package/dist/styles/themes/neutral.css +11 -23
- package/dist/styles/themes/notion.css +11 -23
- package/dist/styles/themes/perplexity.css +11 -23
- package/dist/styles/themes/raycast.css +11 -23
- package/dist/styles/themes/spotify.css +11 -23
- package/dist/styles/themes/stripe.css +11 -23
- package/dist/styles/themes/supabase.css +11 -23
- package/dist/styles/themes/tulipfarm.css +9 -10
- package/dist/styles/themes/vercel.css +12 -25
- package/dist/styles/timeline.css +276 -0
- package/dist/styles/toast.css +13 -20
- package/dist/styles/toggle-group.css +17 -23
- package/dist/styles/toggle.css +8 -8
- package/dist/styles/tool-activity.css +7 -13
- package/dist/styles/toolbar-status.css +2 -7
- package/dist/styles/tooltip.css +15 -21
- package/dist/styles/view-switcher.css +279 -0
- package/package.json +21 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Radio as BaseRadio } from
|
|
2
|
-
import { RadioGroup as BaseRadioGroup } from
|
|
1
|
+
import { Radio as BaseRadio } from '@base-ui/react/radio';
|
|
2
|
+
import { RadioGroup as BaseRadioGroup } from '@base-ui/react/radio-group';
|
|
3
3
|
export type RadioGroupProps<Value = string> = BaseRadioGroup.Props<Value>;
|
|
4
4
|
export type RadioGroupItemProps<Value = string> = BaseRadio.Root.Props<Value>;
|
|
5
5
|
/**
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { Radio as BaseRadio } from
|
|
4
|
-
import { RadioGroup as BaseRadioGroup } from
|
|
5
|
-
import { stateClassName } from
|
|
3
|
+
import { Radio as BaseRadio } from '@base-ui/react/radio';
|
|
4
|
+
import { RadioGroup as BaseRadioGroup } from '@base-ui/react/radio-group';
|
|
5
|
+
import { stateClassName } from '../internal/classes.js';
|
|
6
6
|
/**
|
|
7
7
|
* A set of radios where one value is chosen. Arrow keys move between items
|
|
8
8
|
* and select them. Name the group with `aria-label` or `aria-labelledby`.
|
|
9
9
|
* Children may include a legend, helper, or error next to the items.
|
|
10
10
|
*/
|
|
11
11
|
export function RadioGroup({ className, ...props }) {
|
|
12
|
-
return (_jsx(BaseRadioGroup, { "data-slot": "radio-group", ...props, className: stateClassName(
|
|
12
|
+
return (_jsx(BaseRadioGroup, { "data-slot": "radio-group", ...props, className: stateClassName('sprout-radio-group', className) }));
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
15
|
* A 16px radio with a larger hit area. Name it with a wrapping `Label`, a
|
|
@@ -17,5 +17,5 @@ export function RadioGroup({ className, ...props }) {
|
|
|
17
17
|
* to draw a danger ring.
|
|
18
18
|
*/
|
|
19
19
|
export function RadioGroupItem({ className, ...props }) {
|
|
20
|
-
return (_jsx(BaseRadio.Root, { "data-slot": "radio-group-item", ...props, className: stateClassName(
|
|
20
|
+
return (_jsx(BaseRadio.Root, { "data-slot": "radio-group-item", ...props, className: stateClassName('sprout-radio-group-item', className), children: _jsx(BaseRadio.Indicator, { "data-slot": "radio-group-indicator", className: "sprout-radio-group-indicator" }) }));
|
|
21
21
|
}
|
|
@@ -11,9 +11,9 @@ export interface ReasoningEffortProps {
|
|
|
11
11
|
*/
|
|
12
12
|
label?: string | undefined;
|
|
13
13
|
/** Names the slider. Defaults to "Reasoning effort". */
|
|
14
|
-
|
|
14
|
+
'aria-label'?: string | undefined;
|
|
15
15
|
/** Points at visible text that names the slider, instead of `aria-label`. */
|
|
16
|
-
|
|
16
|
+
'aria-labelledby'?: string | undefined;
|
|
17
17
|
className?: string | undefined;
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
@@ -21,4 +21,4 @@ export interface ReasoningEffortProps {
|
|
|
21
21
|
* a bubble grows out of the track and shows `label` and the level name.
|
|
22
22
|
* Release snaps the thumb to the nearest level.
|
|
23
23
|
*/
|
|
24
|
-
export declare function ReasoningEffort({ levels, value, onValueChange, label,
|
|
24
|
+
export declare function ReasoningEffort({ levels, value, onValueChange, label, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, className, }: ReasoningEffortProps): import("react").JSX.Element;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useEffect, useId, useLayoutEffect, useRef, useState
|
|
4
|
-
import { cn } from
|
|
3
|
+
import { useEffect, useId, useLayoutEffect, useRef, useState } from 'react';
|
|
4
|
+
import { cn } from '../internal/classes.js';
|
|
5
5
|
const TRACK = 256;
|
|
6
6
|
const HEIGHT = 32;
|
|
7
7
|
const RADIUS = HEIGHT / 2;
|
|
@@ -27,8 +27,7 @@ function smoothstep(t) {
|
|
|
27
27
|
return x * x * (3 - 2 * x);
|
|
28
28
|
}
|
|
29
29
|
function reducedMotion() {
|
|
30
|
-
return
|
|
31
|
-
window.matchMedia?.("(prefers-reduced-motion: reduce)").matches);
|
|
30
|
+
return typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches;
|
|
32
31
|
}
|
|
33
32
|
function plateauFor(textW) {
|
|
34
33
|
return Math.max(8, textW + TEXT_SIDE * 2 - SHOULDER * 2);
|
|
@@ -136,7 +135,7 @@ function shellPath(cx, open, plateauW) {
|
|
|
136
135
|
cmds.push(`A${RADIUS} ${RADIUS} 0 0 1 ${crownR} ${trackBot}`);
|
|
137
136
|
}
|
|
138
137
|
cmds.push(`H${crownL}Z`);
|
|
139
|
-
return cmds.join(
|
|
138
|
+
return cmds.join('');
|
|
140
139
|
}
|
|
141
140
|
function useTween(target, duration, delay = 0) {
|
|
142
141
|
const ref = useRef(target);
|
|
@@ -171,7 +170,7 @@ function useTween(target, duration, delay = 0) {
|
|
|
171
170
|
* a bubble grows out of the track and shows `label` and the level name.
|
|
172
171
|
* Release snaps the thumb to the nearest level.
|
|
173
172
|
*/
|
|
174
|
-
export function ReasoningEffort({ levels, value, onValueChange, label,
|
|
173
|
+
export function ReasoningEffort({ levels, value, onValueChange, label, 'aria-label': ariaLabel = 'Reasoning effort', 'aria-labelledby': ariaLabelledBy, className, }) {
|
|
175
174
|
const max = Math.max(0, levels.length - 1);
|
|
176
175
|
const current = clamp(Math.round(value), 0, max);
|
|
177
176
|
const trackRef = useRef(null);
|
|
@@ -246,14 +245,12 @@ export function ReasoningEffort({ levels, value, onValueChange, label, "aria-lab
|
|
|
246
245
|
if (w > 0 && Math.abs(w - textW) > 0.4)
|
|
247
246
|
setTextW(w);
|
|
248
247
|
}, [level, label, textW]);
|
|
249
|
-
return (_jsxs("div", { "data-slot": "reasoning-effort", "data-dragging": dragging, className: cn(
|
|
248
|
+
return (_jsxs("div", { "data-slot": "reasoning-effort", "data-dragging": dragging, className: cn('sprout-reasoning-effort', className), children: [_jsxs("svg", { className: "sprout-reasoning-effort-shell", viewBox: `0 0 ${TRACK} ${BUMP_H + HEIGHT}`, "aria-hidden": "true", children: [_jsx("defs", { children: _jsxs("linearGradient", { id: gradId, x1: "0", y1: "0", x2: "0", y2: "1", children: [_jsx("stop", { offset: "0", className: "sprout-reasoning-effort-stop-top" }), _jsx("stop", { offset: "1", className: "sprout-reasoning-effort-stop-bottom" })] }) }), _jsx("path", { "data-slot": "reasoning-effort-shell", d: shellPath(center, open, plateauW), fill: `url(#${gradId})`, strokeWidth: "0.5", strokeLinejoin: "round", vectorEffect: "non-scaling-stroke" })] }), _jsx("div", { ref: labelRef, "data-slot": "reasoning-effort-bubble", "aria-hidden": "true", className: "sprout-reasoning-effort-bubble", style: {
|
|
250
249
|
left: labelX,
|
|
251
250
|
opacity: reveal,
|
|
252
|
-
filter: reveal > 0.98
|
|
253
|
-
? undefined
|
|
254
|
-
: `blur(${((1 - reveal) * 3).toFixed(2)}px)`,
|
|
251
|
+
filter: reveal > 0.98 ? undefined : `blur(${((1 - reveal) * 3).toFixed(2)}px)`,
|
|
255
252
|
transform: `translate(-50%, ${3 * (1 - open)}px)`,
|
|
256
|
-
}, children: _jsxs("span", { className: "sprout-reasoning-effort-bubble-text", children: [label &&
|
|
253
|
+
}, children: _jsxs("span", { className: "sprout-reasoning-effort-bubble-text", children: [label && _jsx("span", { className: "sprout-reasoning-effort-bubble-label", children: label }), _jsx("span", { className: "sprout-reasoning-effort-bubble-level", children: level })] }, level) }), _jsxs("div", { ref: trackRef, role: "slider", tabIndex: 0, "data-slot": "reasoning-effort-track", "aria-label": ariaLabelledBy ? undefined : ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-orientation": "horizontal", "aria-valuemin": 0, "aria-valuemax": max, "aria-valuenow": current, "aria-valuetext": levels[current], className: "sprout-reasoning-effort-track", onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, onPointerCancel: onPointerUp, onKeyDown: onKeyDown, children: [_jsx("div", { "data-slot": "reasoning-effort-fill", className: "sprout-reasoning-effort-fill", style: { width: fillW } }), _jsx("div", { "data-slot": "reasoning-effort-thumb", className: "sprout-reasoning-effort-thumb", style: {
|
|
257
254
|
left: thumbLeft,
|
|
258
255
|
width: thumbW,
|
|
259
256
|
height: REST_H,
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { type ReactNode, type Ref } from 'react';
|
|
2
|
+
export declare const recordListStatusNames: readonly ["ready", "loading", "error"];
|
|
3
|
+
export declare const recordListDensityNames: readonly ["default", "compact"];
|
|
4
|
+
export type RecordListStatus = (typeof recordListStatusNames)[number];
|
|
5
|
+
export type RecordListDensity = (typeof recordListDensityNames)[number];
|
|
6
|
+
/** The most labelled values a row shows. Extra values are left out. */
|
|
7
|
+
export declare const recordListMaxValues = 4;
|
|
8
|
+
export interface RecordListItem {
|
|
9
|
+
id: string;
|
|
10
|
+
/** Plain text name of the record. Screen readers use it, and it shows in full on hover. */
|
|
11
|
+
title: string;
|
|
12
|
+
}
|
|
13
|
+
export interface RecordListValue {
|
|
14
|
+
/** The field name, such as "Assignee". */
|
|
15
|
+
label: string;
|
|
16
|
+
value: ReactNode;
|
|
17
|
+
/** Full text for the hover hint when `value` is not a string or number. */
|
|
18
|
+
text?: string | undefined;
|
|
19
|
+
}
|
|
20
|
+
export interface RecordListHandle {
|
|
21
|
+
/**
|
|
22
|
+
* Moves focus to the first row, or to the empty or error state when there
|
|
23
|
+
* are no rows. While `status` is `"loading"` it waits for the next render
|
|
24
|
+
* that is not loading. Call it after a page change.
|
|
25
|
+
*/
|
|
26
|
+
focusFirst: () => void;
|
|
27
|
+
}
|
|
28
|
+
export interface RecordListProps<T extends RecordListItem> {
|
|
29
|
+
/** Rows on the current page, in order. */
|
|
30
|
+
items: T[];
|
|
31
|
+
/** Accessible name of the list, such as "Tickets". The row count is added to it. */
|
|
32
|
+
label: string;
|
|
33
|
+
/** Title content, such as an icon or key before the text. Screen readers still use `item.title`. */
|
|
34
|
+
renderTitle?: ((item: T) => ReactNode) | undefined;
|
|
35
|
+
/** Labelled values under the title. Only the first four show; leave out empty values. */
|
|
36
|
+
values?: ((item: T) => RecordListValue[]) | undefined;
|
|
37
|
+
/** Choice badges, such as status and tags. Leave out empty choices. */
|
|
38
|
+
badges?: ((item: T) => ReactNode) | undefined;
|
|
39
|
+
/** Row actions, such as an Edit button and a `DropdownMenu`. Clicks here do not open the row. */
|
|
40
|
+
renderActions?: ((item: T) => ReactNode) | undefined;
|
|
41
|
+
/** Click or Enter on a row. Open your own Sheet or Dialog here. */
|
|
42
|
+
onItemOpen?: ((item: T) => void) | undefined;
|
|
43
|
+
/** `"loading"` dims the current rows, or shows skeleton rows when there are none. Defaults to `"ready"`. */
|
|
44
|
+
status?: RecordListStatus | undefined;
|
|
45
|
+
/** Error description. Defaults to a short generic message. */
|
|
46
|
+
error?: ReactNode;
|
|
47
|
+
/** Shows a "Try again" button in the error state. */
|
|
48
|
+
onRetry?: (() => void) | undefined;
|
|
49
|
+
/** Shown when `items` is empty and ready. Pass a `StatePanel` or text. */
|
|
50
|
+
empty?: ReactNode;
|
|
51
|
+
/** Shown under the rows, inside the panel. Put the app's `Pagination` here. */
|
|
52
|
+
footer?: ReactNode;
|
|
53
|
+
/** `"compact"` uses less padding for dense pages. Defaults to `"default"`. */
|
|
54
|
+
density?: RecordListDensity | undefined;
|
|
55
|
+
/** Gets `focusFirst()` for moving focus after a page change. */
|
|
56
|
+
ref?: Ref<RecordListHandle> | undefined;
|
|
57
|
+
className?: string | undefined;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* A reading and triage list of records: one row per record on the current
|
|
61
|
+
* page, with a title, up to four labelled values, choice badges, and row
|
|
62
|
+
* actions. The list is one tab stop. Arrow keys, Home, and End move between
|
|
63
|
+
* rows, Enter opens a row, and Tab reaches the focused row's actions. The app
|
|
64
|
+
* owns data, paging, and what the actions do.
|
|
65
|
+
*/
|
|
66
|
+
export declare function RecordList<T extends RecordListItem>({ items, label, renderTitle, values, badges, renderActions, onItemOpen, status, error, onRetry, empty, footer, density, ref, className, }: RecordListProps<T>): import("react").JSX.Element;
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useId, useImperativeHandle, useLayoutEffect, useRef, useState, } from 'react';
|
|
4
|
+
import { cn } from '../internal/classes.js';
|
|
5
|
+
import { Button } from './button.js';
|
|
6
|
+
import { Skeleton, SkeletonGroup } from './skeleton.js';
|
|
7
|
+
import { StatePanel } from '../internal/state-panel.js';
|
|
8
|
+
export const recordListStatusNames = ['ready', 'loading', 'error'];
|
|
9
|
+
export const recordListDensityNames = ['default', 'compact'];
|
|
10
|
+
/** The most labelled values a row shows. Extra values are left out. */
|
|
11
|
+
export const recordListMaxValues = 4;
|
|
12
|
+
const SKELETON_ROWS = 5;
|
|
13
|
+
const ROW = 'data-record-list-row';
|
|
14
|
+
const SAVED_TAB = 'data-record-list-tabindex';
|
|
15
|
+
const FOCUSABLE = 'a[href], area[href], button, input, select, textarea, iframe, summary, [contenteditable=""], [contenteditable="true"], [tabindex]';
|
|
16
|
+
const rowsName = (label, count) => `${label}, ${count} ${count === 1 ? 'row' : 'rows'}`;
|
|
17
|
+
const hint = (entry) => entry.text ?? (typeof entry.value === 'string' || typeof entry.value === 'number' ? String(entry.value) : undefined);
|
|
18
|
+
/** Keeps only the active row's own controls in the tab order, so Tab leaves the list after them. */
|
|
19
|
+
function syncTabStops(list) {
|
|
20
|
+
for (const row of list.querySelectorAll(`[${ROW}]`)) {
|
|
21
|
+
const active = row.tabIndex === 0;
|
|
22
|
+
for (const control of row.querySelectorAll(FOCUSABLE)) {
|
|
23
|
+
if (active) {
|
|
24
|
+
const saved = control.getAttribute(SAVED_TAB);
|
|
25
|
+
if (saved === null)
|
|
26
|
+
continue;
|
|
27
|
+
if (saved === '')
|
|
28
|
+
control.removeAttribute('tabindex');
|
|
29
|
+
else
|
|
30
|
+
control.setAttribute('tabindex', saved);
|
|
31
|
+
control.removeAttribute(SAVED_TAB);
|
|
32
|
+
}
|
|
33
|
+
else if (!control.hasAttribute(SAVED_TAB) && control.tabIndex >= 0) {
|
|
34
|
+
control.setAttribute(SAVED_TAB, control.getAttribute('tabindex') ?? '');
|
|
35
|
+
control.setAttribute('tabindex', '-1');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function SkeletonRows() {
|
|
41
|
+
return (_jsx(SkeletonGroup, { label: "Loading rows", gap: "sm", className: "sprout-record-list-skeleton", "data-slot": "record-list-skeleton", children: Array.from({ length: SKELETON_ROWS }, (_, index) => (_jsxs("div", { className: "sprout-record-list-skeleton-row", children: [_jsxs("div", { className: "sprout-record-list-skeleton-main", children: [_jsx(Skeleton, { className: "sprout-record-list-skeleton-title" }), _jsx(Skeleton, { className: "sprout-record-list-skeleton-values" })] }), _jsx(Skeleton, { shape: "action" })] }, index))) }));
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* A reading and triage list of records: one row per record on the current
|
|
45
|
+
* page, with a title, up to four labelled values, choice badges, and row
|
|
46
|
+
* actions. The list is one tab stop. Arrow keys, Home, and End move between
|
|
47
|
+
* rows, Enter opens a row, and Tab reaches the focused row's actions. The app
|
|
48
|
+
* owns data, paging, and what the actions do.
|
|
49
|
+
*/
|
|
50
|
+
export function RecordList({ items, label, renderTitle, values, badges, renderActions, onItemOpen, status = 'ready', error, onRetry, empty, footer, density = 'default', ref, className, }) {
|
|
51
|
+
const id = useId();
|
|
52
|
+
const listRef = useRef(null);
|
|
53
|
+
const stateRef = useRef(null);
|
|
54
|
+
const pendingFocus = useRef(false);
|
|
55
|
+
const [activeId, setActiveId] = useState(null);
|
|
56
|
+
const loading = status === 'loading';
|
|
57
|
+
const showRows = status !== 'error' && items.length > 0;
|
|
58
|
+
const current = items.some(item => item.id === activeId) ? activeId : (items[0]?.id ?? null);
|
|
59
|
+
const rowOf = useCallback((itemId) => [...(listRef.current?.querySelectorAll(`[${ROW}]`) ?? [])].find(row => row.dataset.recordListRow === itemId), []);
|
|
60
|
+
const flushFocus = useCallback(() => {
|
|
61
|
+
if (!pendingFocus.current || loading)
|
|
62
|
+
return;
|
|
63
|
+
pendingFocus.current = false;
|
|
64
|
+
if (showRows && items[0]) {
|
|
65
|
+
setActiveId(items[0].id);
|
|
66
|
+
rowOf(items[0].id)?.focus();
|
|
67
|
+
}
|
|
68
|
+
else
|
|
69
|
+
stateRef.current?.focus();
|
|
70
|
+
}, [items, loading, rowOf, showRows]);
|
|
71
|
+
const latestFlush = useRef(flushFocus);
|
|
72
|
+
useLayoutEffect(() => {
|
|
73
|
+
latestFlush.current = flushFocus;
|
|
74
|
+
flushFocus();
|
|
75
|
+
});
|
|
76
|
+
useImperativeHandle(ref, () => ({
|
|
77
|
+
focusFirst() {
|
|
78
|
+
pendingFocus.current = true;
|
|
79
|
+
// A task, not a microtask, so a switch to loading queued in the same handler commits first.
|
|
80
|
+
setTimeout(() => latestFlush.current());
|
|
81
|
+
},
|
|
82
|
+
}), []);
|
|
83
|
+
useLayoutEffect(() => {
|
|
84
|
+
const list = listRef.current;
|
|
85
|
+
if (!list)
|
|
86
|
+
return;
|
|
87
|
+
syncTabStops(list);
|
|
88
|
+
const observer = new MutationObserver(() => syncTabStops(list));
|
|
89
|
+
observer.observe(list, { childList: true, subtree: true });
|
|
90
|
+
return () => observer.disconnect();
|
|
91
|
+
});
|
|
92
|
+
const move = (event) => {
|
|
93
|
+
const row = event.target;
|
|
94
|
+
if (!row.hasAttribute(ROW) || event.altKey || event.ctrlKey || event.metaKey)
|
|
95
|
+
return;
|
|
96
|
+
const index = items.findIndex(item => item.id === row.dataset.recordListRow);
|
|
97
|
+
const item = items[index];
|
|
98
|
+
if (!item)
|
|
99
|
+
return;
|
|
100
|
+
if (event.key === 'Enter') {
|
|
101
|
+
if (!onItemOpen || event.repeat)
|
|
102
|
+
return;
|
|
103
|
+
event.preventDefault();
|
|
104
|
+
onItemOpen(item);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const target = event.key === 'ArrowDown'
|
|
108
|
+
? items[Math.min(index + 1, items.length - 1)]
|
|
109
|
+
: event.key === 'ArrowUp'
|
|
110
|
+
? items[Math.max(index - 1, 0)]
|
|
111
|
+
: event.key === 'Home'
|
|
112
|
+
? items[0]
|
|
113
|
+
: event.key === 'End'
|
|
114
|
+
? items.at(-1)
|
|
115
|
+
: undefined;
|
|
116
|
+
if (!target || event.shiftKey)
|
|
117
|
+
return;
|
|
118
|
+
event.preventDefault();
|
|
119
|
+
setActiveId(target.id);
|
|
120
|
+
rowOf(target.id)?.focus();
|
|
121
|
+
};
|
|
122
|
+
const open = (event, item) => {
|
|
123
|
+
const target = event.target;
|
|
124
|
+
const row = event.currentTarget;
|
|
125
|
+
// Portaled menus bubble through React, so check the DOM too.
|
|
126
|
+
if (!onItemOpen || !row.contains(target))
|
|
127
|
+
return;
|
|
128
|
+
const control = target.closest(FOCUSABLE);
|
|
129
|
+
if (control && control !== row && row.contains(control))
|
|
130
|
+
return;
|
|
131
|
+
if (target.closest('[data-slot="record-list-actions"]'))
|
|
132
|
+
return;
|
|
133
|
+
if (window.getSelection()?.toString())
|
|
134
|
+
return;
|
|
135
|
+
onItemOpen(item);
|
|
136
|
+
};
|
|
137
|
+
const emptyContent = empty === undefined ? (_jsx(StatePanel, { kind: "empty", heading: "h3", title: "No rows to show", description: "Rows show here when they are added or match the search and filters." })) : typeof empty === 'string' ? (_jsx("p", { className: "sprout-record-list-empty-text", children: empty })) : (empty);
|
|
138
|
+
return (_jsxs("div", { "data-slot": "record-list", "data-density": density, "data-status": status, className: cn('sprout-record-list', className), children: [status === 'error' ? (_jsx("div", { ref: stateRef, tabIndex: -1, "data-slot": "record-list-state", className: "sprout-record-list-state", children: _jsx(StatePanel, { kind: "error", heading: "h3", title: "Rows did not load", description: error ?? 'Something went wrong while loading the rows.', children: onRetry ? (_jsx(Button, { variant: "outline", onClick: onRetry, children: "Try again" })) : null }) })) : showRows ? (_jsxs(_Fragment, { children: [_jsx("ul", { ref: listRef, "aria-label": rowsName(label, items.length), "aria-busy": loading || undefined, "data-slot": "record-list-items", className: "sprout-record-list-items", onKeyDown: move, children: items.map((item, index) => {
|
|
139
|
+
const shown = values?.(item).slice(0, recordListMaxValues) ?? [];
|
|
140
|
+
const badgeContent = badges?.(item);
|
|
141
|
+
const hasBadges = badgeContent != null && badgeContent !== false;
|
|
142
|
+
const actions = renderActions?.(item);
|
|
143
|
+
const valuesId = `${id}-${index}-values`;
|
|
144
|
+
const badgesId = `${id}-${index}-badges`;
|
|
145
|
+
const described = [shown.length > 0 && valuesId, hasBadges && badgesId].filter(Boolean).join(' ');
|
|
146
|
+
return (_jsxs("li", { "data-record-list-row": item.id, tabIndex: item.id === current ? 0 : -1, "aria-label": item.title, "aria-describedby": described || undefined, "data-slot": "record-list-item", "data-openable": onItemOpen ? '' : undefined, className: "sprout-record-list-item", onFocus: event => {
|
|
147
|
+
if (event.currentTarget.contains(event.target))
|
|
148
|
+
setActiveId(item.id);
|
|
149
|
+
}, onClick: event => open(event, item), children: [_jsx("div", { "data-slot": "record-list-title", className: "sprout-record-list-title", title: item.title, children: renderTitle ? renderTitle(item) : item.title }), shown.length > 0 && (_jsx("dl", { id: valuesId, "data-slot": "record-list-values", className: "sprout-record-list-values", children: shown.map((entry, position) => (_jsxs("div", { className: "sprout-record-list-value", children: [_jsx("dt", { children: entry.label }), _jsx("dd", { title: hint(entry), children: entry.value })] }, `${entry.label}-${position}`))) })), hasBadges && (_jsx("div", { id: badgesId, "data-slot": "record-list-badges", className: "sprout-record-list-badges", children: badgeContent })), actions != null && actions !== false && (_jsx("div", { "data-slot": "record-list-actions", className: "sprout-record-list-actions", children: actions }))] }, item.id));
|
|
150
|
+
}) }), _jsx("span", { role: "status", className: "sprout-record-list-sr-only", children: loading ? 'Loading rows…' : '' })] })) : (_jsx("div", { ref: stateRef, tabIndex: -1, "data-slot": "record-list-state", className: "sprout-record-list-state", children: loading ? _jsx(SkeletonRows, {}) : emptyContent })), footer != null && footer !== false && (_jsx("div", { "data-slot": "record-list-footer", className: "sprout-record-list-footer", children: footer }))] }));
|
|
151
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ComponentProps } from
|
|
1
|
+
import { type ComponentProps } from 'react';
|
|
2
2
|
export declare const resizableOrientationNames: readonly ["horizontal", "vertical"];
|
|
3
3
|
/** `"horizontal"` places panels side by side. `"vertical"` stacks them. */
|
|
4
4
|
export type ResizableOrientation = (typeof resizableOrientationNames)[number];
|
|
@@ -13,7 +13,7 @@ export interface ResizableLayoutChangeDetails {
|
|
|
13
13
|
/** True for pointer and keyboard resizes. False for mount and container changes. */
|
|
14
14
|
isUserInteraction: boolean;
|
|
15
15
|
}
|
|
16
|
-
export interface ResizablePanelGroupProps extends ComponentProps<
|
|
16
|
+
export interface ResizablePanelGroupProps extends ComponentProps<'div'> {
|
|
17
17
|
/** `"horizontal"` (default) places panels side by side. `"vertical"` stacks them. */
|
|
18
18
|
orientation?: ResizableOrientation;
|
|
19
19
|
/** Starting sizes by panel `id`, such as a layout saved by `useResizableLayout`. */
|
|
@@ -25,7 +25,7 @@ export interface ResizablePanelGroupProps extends ComponentProps<"div"> {
|
|
|
25
25
|
}
|
|
26
26
|
/** A row or column of resizable panels separated by `ResizableHandle`s. */
|
|
27
27
|
export declare function ResizablePanelGroup({ orientation, defaultLayout, onLayoutChange, onLayoutChanged, className, children, ref, ...props }: ResizablePanelGroupProps): import("react").JSX.Element;
|
|
28
|
-
export interface ResizablePanelProps extends Omit<ComponentProps<
|
|
28
|
+
export interface ResizablePanelProps extends Omit<ComponentProps<'div'>, 'id'> {
|
|
29
29
|
/** Key for this panel in layouts. Set it when saving layouts or showing panels conditionally. */
|
|
30
30
|
id?: string;
|
|
31
31
|
/** Starting size. Panels without one share the space that is left. */
|
|
@@ -37,7 +37,7 @@ export interface ResizablePanelProps extends Omit<ComponentProps<"div">, "id"> {
|
|
|
37
37
|
}
|
|
38
38
|
/** One resizable region. It must be a direct child of `ResizablePanelGroup`. */
|
|
39
39
|
export declare function ResizablePanel({ id: idProp, defaultSize, minSize, maxSize, className, style, ref, ...props }: ResizablePanelProps): import("react").JSX.Element;
|
|
40
|
-
export interface ResizableHandleProps extends ComponentProps<
|
|
40
|
+
export interface ResizableHandleProps extends ComponentProps<'div'> {
|
|
41
41
|
/** Shows a small grip on the line, for splits people resize often. */
|
|
42
42
|
withHandle?: boolean;
|
|
43
43
|
}
|
|
@@ -54,7 +54,7 @@ export interface UseResizableLayoutOptions {
|
|
|
54
54
|
/** Only save sizes the person chose, not the starting layout. */
|
|
55
55
|
onlySaveAfterUserInteractions?: boolean | undefined;
|
|
56
56
|
/** Where to save. Defaults to `localStorage`. */
|
|
57
|
-
storage?: Pick<Storage,
|
|
57
|
+
storage?: Pick<Storage, 'getItem' | 'setItem'> | undefined;
|
|
58
58
|
}
|
|
59
59
|
export interface ResizableLayoutStore {
|
|
60
60
|
defaultLayout: ResizableLayout | undefined;
|