@tulipfarm/sprout 0.3.1 → 0.5.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 +75 -68
- package/dist/components/accordion.d.ts +2 -2
- package/dist/components/accordion.js +9 -9
- package/dist/components/agent-avatar.d.ts +27 -0
- package/dist/components/agent-avatar.js +67 -0
- package/dist/components/agent-fanout.d.ts +2 -2
- package/dist/components/agent-fanout.js +65 -87
- package/dist/components/alert-dialog.d.ts +8 -8
- package/dist/components/alert-dialog.js +21 -21
- 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 +18 -18
- package/dist/components/attachment.js +82 -115
- package/dist/components/avatar.d.ts +9 -17
- package/dist/components/avatar.js +14 -51
- 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 +13 -13
- package/dist/components/button.js +31 -57
- 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 +7 -7
- 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 +12 -6
- package/dist/components/combobox.js +27 -26
- 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 +7 -7
- 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 +18 -18
- package/dist/components/input-group.js +25 -39
- package/dist/components/input-otp.d.ts +14 -10
- package/dist/components/input-otp.js +15 -15
- package/dist/components/input.d.ts +3 -3
- 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 +17 -17
- 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 +5 -5
- 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 +3 -3
- 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 +5 -9
- 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 +7 -7
- 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 +8 -8
- package/dist/components/state-sample.js +18 -31
- package/dist/components/switch.d.ts +3 -3
- 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 +4 -4
- package/dist/components/toggle-group.js +18 -20
- package/dist/components/toggle.d.ts +4 -4
- 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 +99 -93
- package/dist/index.js +99 -93
- package/dist/internal/agent-avatar-artwork.d.ts +4 -0
- package/dist/internal/agent-avatar-artwork.js +219 -0
- 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/hash.d.ts +1 -0
- package/dist/internal/hash.js +9 -0
- 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 +56 -98
- package/dist/styles/avatar.css +14 -33
- 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 +9 -15
- package/dist/styles/button.css +45 -175
- 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 +4 -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 +24 -17
- package/dist/styles/command.css +8 -9
- package/dist/styles/context-menu.css +4 -2
- package/dist/styles/dialog.css +5 -16
- package/dist/styles/dropdown-menu.css +4 -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 +16 -39
- package/dist/styles/hover-card.css +9 -15
- package/dist/styles/index.css +121 -112
- package/dist/styles/input-group.css +61 -69
- package/dist/styles/input-otp.css +18 -9
- package/dist/styles/input.css +19 -11
- 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 +9 -8
- 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 +15 -30
- package/dist/styles/notice-banner.css +1 -2
- package/dist/styles/page-header.css +11 -10
- package/dist/styles/pagination.css +12 -6
- 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 +4 -4
- package/dist/styles/result-notice.css +80 -0
- package/dist/styles/review-card.css +2 -3
- package/dist/styles/rich-text-editor.css +4 -5
- 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 +15 -19
- 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 +32 -34
- 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 +62 -81
- package/dist/styles/tabs.css +13 -19
- 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 +23 -29
- package/dist/styles/toggle.css +14 -14
- 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 +297 -0
- package/package.json +25 -1
|
@@ -1,62 +1,56 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
2
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useEffect, useRef } from
|
|
4
|
-
import { ShieldUser } from
|
|
5
|
-
import { cn } from
|
|
6
|
-
import { Button } from
|
|
7
|
-
import { ReviewCard, ReviewRow, ReviewRows
|
|
8
|
-
import { Spinner } from
|
|
3
|
+
import { useEffect, useRef } from 'react';
|
|
4
|
+
import { ShieldUser } from 'reicon-react/icons/ShieldUser';
|
|
5
|
+
import { cn } from '../internal/classes.js';
|
|
6
|
+
import { Button } from './button.js';
|
|
7
|
+
import { ReviewCard, ReviewRow, ReviewRows } from './review-card.js';
|
|
8
|
+
import { Spinner } from './spinner.js';
|
|
9
9
|
export const chatConfirmationStateNames = [
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
'pending',
|
|
11
|
+
'submitting',
|
|
12
|
+
'approved',
|
|
13
|
+
'rejected',
|
|
14
|
+
'expired',
|
|
15
|
+
'cancelled',
|
|
16
|
+
'error',
|
|
17
17
|
];
|
|
18
|
-
const settledKinds = new Set([
|
|
19
|
-
"approved",
|
|
20
|
-
"rejected",
|
|
21
|
-
"expired",
|
|
22
|
-
"cancelled",
|
|
23
|
-
]);
|
|
18
|
+
const settledKinds = new Set(['approved', 'rejected', 'expired', 'cancelled']);
|
|
24
19
|
const badges = {
|
|
25
|
-
pending: { label:
|
|
26
|
-
submitting: { label:
|
|
27
|
-
error: { label:
|
|
28
|
-
approved: { label:
|
|
29
|
-
rejected: { label:
|
|
30
|
-
expired: { label:
|
|
31
|
-
cancelled: { label:
|
|
20
|
+
pending: { label: 'Approval required', variant: 'warning' },
|
|
21
|
+
submitting: { label: 'Approval required', variant: 'warning' },
|
|
22
|
+
error: { label: 'Approval required', variant: 'warning' },
|
|
23
|
+
approved: { label: 'Approved', variant: 'info' },
|
|
24
|
+
rejected: { label: 'Declined', variant: 'secondary' },
|
|
25
|
+
expired: { label: 'Expired', variant: 'secondary' },
|
|
26
|
+
cancelled: { label: 'Cancelled', variant: 'secondary' },
|
|
32
27
|
};
|
|
33
28
|
const outcomes = {
|
|
34
|
-
approved:
|
|
35
|
-
rejected:
|
|
36
|
-
expired:
|
|
37
|
-
cancelled:
|
|
29
|
+
approved: 'Approval recorded. This does not confirm the action has completed.',
|
|
30
|
+
rejected: 'The proposed action was declined.',
|
|
31
|
+
expired: 'This approval expired. No approval was granted.',
|
|
32
|
+
cancelled: 'This approval was cancelled. No approval was granted.',
|
|
38
33
|
};
|
|
39
34
|
/**
|
|
40
35
|
* Asks someone in chat to approve or decline an action an agent proposed.
|
|
41
36
|
* Built on `ReviewCard`: it folds once decided, and when the decision was
|
|
42
37
|
* made from inside the card, focus moves to the outcome.
|
|
43
38
|
*/
|
|
44
|
-
export function ChatConfirmation({ title, description, details, state, onDecision, disabled = false, approveLabel =
|
|
39
|
+
export function ChatConfirmation({ title, description, details, state, onDecision, disabled = false, approveLabel = 'Approve action', className, ...props }) {
|
|
45
40
|
const done = settledKinds.has(state.kind);
|
|
46
41
|
const section = useRef(null);
|
|
47
42
|
const result = useRef(null);
|
|
48
43
|
const submittedHere = useRef(false);
|
|
49
44
|
useEffect(() => {
|
|
50
|
-
if (state.kind ===
|
|
51
|
-
submittedHere.current =
|
|
52
|
-
section.current?.contains(document.activeElement) ?? false;
|
|
45
|
+
if (state.kind === 'submitting')
|
|
46
|
+
submittedHere.current = section.current?.contains(document.activeElement) ?? false;
|
|
53
47
|
if (done && submittedHere.current) {
|
|
54
48
|
result.current?.focus();
|
|
55
49
|
submittedHere.current = false;
|
|
56
50
|
}
|
|
57
51
|
}, [done, state.kind]);
|
|
58
|
-
const submitting = state.kind ===
|
|
59
|
-
const busy = (decision) => state.kind ===
|
|
52
|
+
const submitting = state.kind === 'submitting';
|
|
53
|
+
const busy = (decision) => state.kind === 'submitting' && state.decision === decision;
|
|
60
54
|
const outcome = outcomes[state.kind];
|
|
61
|
-
return (_jsx("div", { ref: section, "data-slot": "chat-confirmation", "data-state": state.kind, ...props, className: cn(
|
|
55
|
+
return (_jsx("div", { ref: section, "data-slot": "chat-confirmation", "data-state": state.kind, ...props, className: cn('sprout-chat-confirmation', className), children: _jsxs(ReviewCard, { icon: _jsx(ShieldUser, { size: 16 }), title: title, badge: badges[state.kind], settled: done, status: state.kind === 'error' || outcome ? (_jsxs(_Fragment, { children: [state.kind === 'error' && (_jsx("p", { role: "alert", className: "sprout-chat-confirmation-error", children: state.message })), outcome && (_jsx("p", { ref: result, tabIndex: -1, role: "status", className: "sprout-chat-confirmation-result", children: outcome }))] })) : undefined, actions: done ? undefined : (_jsxs(_Fragment, { children: [_jsxs(Button, { disabled: disabled || submitting, "aria-busy": busy('approve'), onClick: () => onDecision('approve'), children: [busy('approve') && _jsx(Spinner, { "aria-hidden": "true" }), approveLabel] }), _jsxs(Button, { variant: "ghost", disabled: disabled || submitting, "aria-busy": busy('reject'), onClick: () => onDecision('reject'), children: [busy('reject') && _jsx(Spinner, { "aria-hidden": "true" }), "Decline"] })] })), children: [_jsx("p", { className: "sprout-chat-confirmation-description", children: description }), _jsx(ReviewRows, { children: details.map(detail => (_jsx(ReviewRow, { label: detail.label, children: detail.value }, detail.label))) })] }) }));
|
|
62
56
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { type ReactNode } from
|
|
2
|
-
import { type AttachmentFile } from
|
|
3
|
-
import { type Brand } from
|
|
4
|
-
import { type RichTextValue } from
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type AttachmentFile } from './attachment.js';
|
|
3
|
+
import { type Brand } from './brand-icon.js';
|
|
4
|
+
import { type RichTextValue } from './rich-text-editor.js';
|
|
5
5
|
export declare const chatInputReferenceKindNames: readonly ["agent", "skill", "file"];
|
|
6
6
|
export declare const chatInputStatusNames: readonly ["idle", "streaming"];
|
|
7
7
|
export type ChatInputReferenceKind = (typeof chatInputReferenceKindNames)[number];
|
|
@@ -1,92 +1,92 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { useId, useLayoutEffect, useMemo, useRef, useState
|
|
4
|
-
import { Extension, Node, mergeAttributes
|
|
5
|
-
import { PluginKey } from
|
|
6
|
-
import Suggestion, { exitSuggestion
|
|
7
|
-
import { ArrowUp } from
|
|
8
|
-
import { ChevronDown } from
|
|
9
|
-
import { Folder } from
|
|
10
|
-
import { Plus } from
|
|
11
|
-
import { Sliders } from
|
|
12
|
-
import { X } from
|
|
13
|
-
import { cn } from
|
|
14
|
-
import { FileAttachment } from
|
|
15
|
-
import { BrandIcon } from
|
|
16
|
-
import { Button } from
|
|
17
|
-
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList
|
|
18
|
-
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger, } from
|
|
19
|
-
import { InputGroup, InputGroupAddon, InputGroupButton
|
|
20
|
-
import { MentionList, MentionOption, MentionStatus } from
|
|
21
|
-
import { Popover, PopoverContent, PopoverTrigger } from
|
|
22
|
-
import { RichTextEditor
|
|
23
|
-
import { Tooltip, TooltipContent, TooltipTrigger } from
|
|
24
|
-
export const chatInputReferenceKindNames = [
|
|
25
|
-
export const chatInputStatusNames = [
|
|
3
|
+
import { useId, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
4
|
+
import { Extension, Node, mergeAttributes } from '@tiptap/core';
|
|
5
|
+
import { PluginKey } from '@tiptap/pm/state';
|
|
6
|
+
import Suggestion, { exitSuggestion } from '@tiptap/suggestion';
|
|
7
|
+
import { ArrowUp } from 'reicon-react/icons/ArrowUp';
|
|
8
|
+
import { ChevronDown } from 'reicon-react/icons/ChevronDown';
|
|
9
|
+
import { Folder } from 'reicon-react/icons/Folder';
|
|
10
|
+
import { Plus } from 'reicon-react/icons/Plus';
|
|
11
|
+
import { Sliders } from 'reicon-react/icons/Sliders';
|
|
12
|
+
import { X } from 'reicon-react/icons/X';
|
|
13
|
+
import { cn } from '../internal/classes.js';
|
|
14
|
+
import { FileAttachment } from './attachment.js';
|
|
15
|
+
import { BrandIcon } from './brand-icon.js';
|
|
16
|
+
import { Button } from './button.js';
|
|
17
|
+
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from './command.js';
|
|
18
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger, } from './dropdown-menu.js';
|
|
19
|
+
import { InputGroup, InputGroupAddon, InputGroupButton } from './input-group.js';
|
|
20
|
+
import { MentionList, MentionOption, MentionStatus } from './mention-list.js';
|
|
21
|
+
import { Popover, PopoverContent, PopoverTrigger } from './popover.js';
|
|
22
|
+
import { RichTextEditor } from './rich-text-editor.js';
|
|
23
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from './tooltip.js';
|
|
24
|
+
export const chatInputReferenceKindNames = ['agent', 'skill', 'file'];
|
|
25
|
+
export const chatInputStatusNames = ['idle', 'streaming'];
|
|
26
26
|
const triggers = {
|
|
27
|
-
agent: { char:
|
|
28
|
-
skill: { char:
|
|
29
|
-
file: { char:
|
|
27
|
+
agent: { char: '@', label: 'Agents', empty: 'No agents match.' },
|
|
28
|
+
skill: { char: '/', label: 'Skills', empty: 'No skills match.' },
|
|
29
|
+
file: { char: '#', label: 'Files', empty: 'No files match.' },
|
|
30
30
|
};
|
|
31
31
|
const referenceNode = Node.create({
|
|
32
|
-
name:
|
|
32
|
+
name: 'chatReference',
|
|
33
33
|
inline: true,
|
|
34
|
-
group:
|
|
34
|
+
group: 'inline',
|
|
35
35
|
atom: true,
|
|
36
36
|
selectable: true,
|
|
37
37
|
addAttributes() {
|
|
38
38
|
return {
|
|
39
39
|
kind: {
|
|
40
|
-
default:
|
|
40
|
+
default: 'file',
|
|
41
41
|
rendered: false,
|
|
42
|
-
parseHTML:
|
|
42
|
+
parseHTML: el => el.getAttribute('data-chat-reference'),
|
|
43
43
|
},
|
|
44
44
|
id: {
|
|
45
|
-
default:
|
|
45
|
+
default: '',
|
|
46
46
|
rendered: false,
|
|
47
|
-
parseHTML:
|
|
47
|
+
parseHTML: el => el.getAttribute('data-id'),
|
|
48
48
|
},
|
|
49
49
|
label: {
|
|
50
|
-
default:
|
|
50
|
+
default: '',
|
|
51
51
|
rendered: false,
|
|
52
|
-
parseHTML:
|
|
52
|
+
parseHTML: el => el.getAttribute('data-label'),
|
|
53
53
|
},
|
|
54
54
|
};
|
|
55
55
|
},
|
|
56
56
|
parseHTML() {
|
|
57
|
-
return [{ tag:
|
|
57
|
+
return [{ tag: 'span[data-chat-reference]' }];
|
|
58
58
|
},
|
|
59
59
|
renderHTML({ node, HTMLAttributes }) {
|
|
60
60
|
const kind = node.attrs.kind;
|
|
61
61
|
return [
|
|
62
|
-
|
|
62
|
+
'span',
|
|
63
63
|
mergeAttributes(HTMLAttributes, {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
class:
|
|
64
|
+
'data-chat-reference': kind,
|
|
65
|
+
'data-id': node.attrs.id,
|
|
66
|
+
'data-label': node.attrs.label,
|
|
67
|
+
class: 'sprout-chat-input-reference',
|
|
68
68
|
}),
|
|
69
|
-
`${triggers[kind]?.char ??
|
|
69
|
+
`${triggers[kind]?.char ?? ''}${node.attrs.label}`,
|
|
70
70
|
];
|
|
71
71
|
},
|
|
72
72
|
renderText({ node }) {
|
|
73
73
|
const kind = node.attrs.kind;
|
|
74
|
-
return `${triggers[kind]?.char ??
|
|
74
|
+
return `${triggers[kind]?.char ?? ''}${node.attrs.label}`;
|
|
75
75
|
},
|
|
76
76
|
});
|
|
77
77
|
const linkShortcut = Extension.create({
|
|
78
|
-
name:
|
|
78
|
+
name: 'chatInputLinkShortcut',
|
|
79
79
|
addKeyboardShortcuts() {
|
|
80
80
|
return {
|
|
81
|
-
|
|
82
|
-
if (editor.isActive(
|
|
81
|
+
'Mod-k': ({ editor }) => {
|
|
82
|
+
if (editor.isActive('link'))
|
|
83
83
|
return editor.chain().focus().unsetLink().run();
|
|
84
84
|
const { from, to } = editor.state.selection;
|
|
85
85
|
const text = editor.state.doc.textBetween(from, to).trim();
|
|
86
86
|
const href = /^\S+@\S+\.\S+$/.test(text)
|
|
87
87
|
? `mailto:${text}`
|
|
88
88
|
: /^(https?:\/\/|www\.)\S+$/i.test(text)
|
|
89
|
-
? text.startsWith(
|
|
89
|
+
? text.startsWith('www.')
|
|
90
90
|
? `https://${text}`
|
|
91
91
|
: text
|
|
92
92
|
: null;
|
|
@@ -114,10 +114,10 @@ function triggerExtension(kind, source, onState) {
|
|
|
114
114
|
.focus()
|
|
115
115
|
.insertContentAt(range, [
|
|
116
116
|
{
|
|
117
|
-
type:
|
|
117
|
+
type: 'chatReference',
|
|
118
118
|
attrs: { kind, id: props.id, label: props.label },
|
|
119
119
|
},
|
|
120
|
-
{ type:
|
|
120
|
+
{ type: 'text', text: ' ' },
|
|
121
121
|
])
|
|
122
122
|
.run(),
|
|
123
123
|
render: () => {
|
|
@@ -131,7 +131,7 @@ function triggerExtension(kind, source, onState) {
|
|
|
131
131
|
kind,
|
|
132
132
|
items,
|
|
133
133
|
active: Math.min(active, Math.max(0, items.length - 1)),
|
|
134
|
-
select:
|
|
134
|
+
select: index => {
|
|
135
135
|
const item = items[index];
|
|
136
136
|
if (item)
|
|
137
137
|
current?.command(item);
|
|
@@ -139,33 +139,30 @@ function triggerExtension(kind, source, onState) {
|
|
|
139
139
|
});
|
|
140
140
|
};
|
|
141
141
|
return {
|
|
142
|
-
onStart:
|
|
142
|
+
onStart: props => {
|
|
143
143
|
current = props;
|
|
144
144
|
active = 0;
|
|
145
145
|
publish();
|
|
146
146
|
},
|
|
147
|
-
onUpdate:
|
|
147
|
+
onUpdate: props => {
|
|
148
148
|
current = props;
|
|
149
149
|
active = 0;
|
|
150
150
|
publish();
|
|
151
151
|
},
|
|
152
152
|
onKeyDown: ({ event, view }) => {
|
|
153
|
-
if (event.key ===
|
|
153
|
+
if (event.key === 'Escape') {
|
|
154
154
|
exitSuggestion(view, key);
|
|
155
155
|
return true;
|
|
156
156
|
}
|
|
157
157
|
const count = current?.items.length ?? 0;
|
|
158
158
|
if (!count)
|
|
159
159
|
return false;
|
|
160
|
-
if (event.key ===
|
|
161
|
-
active =
|
|
162
|
-
(active + (event.key === "ArrowDown" ? 1 : count - 1)) %
|
|
163
|
-
count;
|
|
160
|
+
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
|
|
161
|
+
active = (active + (event.key === 'ArrowDown' ? 1 : count - 1)) % count;
|
|
164
162
|
publish();
|
|
165
163
|
return true;
|
|
166
164
|
}
|
|
167
|
-
if ((event.key ===
|
|
168
|
-
event.key === "Tab") {
|
|
165
|
+
if ((event.key === 'Enter' && !event.shiftKey) || event.key === 'Tab') {
|
|
169
166
|
current.command(current.items[active]);
|
|
170
167
|
return true;
|
|
171
168
|
}
|
|
@@ -183,7 +180,7 @@ function triggerExtension(kind, source, onState) {
|
|
|
183
180
|
});
|
|
184
181
|
}
|
|
185
182
|
function hasContent(node) {
|
|
186
|
-
if (node.type ===
|
|
183
|
+
if (node.type === 'chatReference')
|
|
187
184
|
return true;
|
|
188
185
|
if (node.text?.trim())
|
|
189
186
|
return true;
|
|
@@ -191,8 +188,8 @@ function hasContent(node) {
|
|
|
191
188
|
}
|
|
192
189
|
function textDoc(text) {
|
|
193
190
|
return {
|
|
194
|
-
type:
|
|
195
|
-
content: [{ type:
|
|
191
|
+
type: 'doc',
|
|
192
|
+
content: [{ type: 'paragraph', content: [{ type: 'text', text }] }],
|
|
196
193
|
};
|
|
197
194
|
}
|
|
198
195
|
function ModelMark({ model }) {
|
|
@@ -202,8 +199,8 @@ function ModelMark({ model }) {
|
|
|
202
199
|
}
|
|
203
200
|
function OptionPicker({ label, search, options, value, onChange, disabled, icon, align, }) {
|
|
204
201
|
const [open, setOpen] = useState(false);
|
|
205
|
-
const selected = options.find(
|
|
206
|
-
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsxs(PopoverTrigger, { render: _jsx(InputGroupButton, {
|
|
202
|
+
const selected = options.find(option => option.id === value);
|
|
203
|
+
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsxs(PopoverTrigger, { render: _jsx(InputGroupButton, { "aria-label": `${label}: ${selected?.label ?? 'None'}`, disabled: disabled, className: "sprout-chat-input-picker" }), children: [icon(selected), _jsx("span", { className: "sprout-chat-input-picker-label", children: selected?.label ?? label }), _jsx(ChevronDown, { size: 12, "aria-hidden": "true" })] }), _jsx(PopoverContent, { size: "picker", side: "top", align: align, sideOffset: 8, className: "sprout-chat-input-menu", children: _jsxs(Command, { children: [_jsx(CommandInput, { "aria-label": search, placeholder: `${search}…` }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: "No matches." }), _jsx(CommandGroup, { heading: label, children: options.map(option => (_jsxs(CommandItem, { value: `${option.label} ${option.description ?? ''}`, "data-checked": option.id === value, disabled: 'disabled' in option && !!option.disabled, onSelect: () => {
|
|
207
204
|
onChange(option.id);
|
|
208
205
|
setOpen(false);
|
|
209
206
|
}, children: [icon(option), _jsxs("span", { className: "sprout-chat-input-option-text", children: [_jsx("span", { children: option.label }), option.description && (_jsx("span", { className: "sprout-chat-input-option-description", children: option.description }))] })] }, option.id))) })] })] }) })] }));
|
|
@@ -213,7 +210,7 @@ function OptionPicker({ label, search, options, value, onChange, disabled, icon,
|
|
|
213
210
|
* and `#` adds files. The bar holds attach and mode menus, a project picker,
|
|
214
211
|
* a model picker, and send or stop. Starter prompts sit under an empty box.
|
|
215
212
|
*/
|
|
216
|
-
export function ChatInput({ value, onValueChange, onSend, onStop, status =
|
|
213
|
+
export function ChatInput({ value, onValueChange, onSend, onStop, status = 'idle', placeholder = 'Ask anything, @agents, /skills, #files…', streamingPlaceholder = 'Working on your request…', disabled = false, label = 'Message', agents, skills, files, attachments = [], onRemoveAttachment, attachActions, modes, mode = null, onModeChange, projects, project, onProjectChange, models, model, onModelChange, prompts, onPromptSelect, className, }) {
|
|
217
214
|
const editor = useRef(null);
|
|
218
215
|
const form = useRef(null);
|
|
219
216
|
const listId = useId();
|
|
@@ -232,15 +229,15 @@ export function ChatInput({ value, onValueChange, onSend, onStop, status = "idle
|
|
|
232
229
|
referenceNode,
|
|
233
230
|
linkShortcut,
|
|
234
231
|
...chatInputReferenceKindNames
|
|
235
|
-
.filter(
|
|
236
|
-
.map(
|
|
232
|
+
.filter(kind => sources[kind].current)
|
|
233
|
+
.map(kind => triggerExtension(kind, sources[kind], setPanel)),
|
|
237
234
|
],
|
|
238
235
|
// Sources are refs, so only adding or removing a trigger rebuilds the editor.
|
|
239
236
|
[enabled]);
|
|
240
|
-
const streaming = status ===
|
|
237
|
+
const streaming = status === 'streaming';
|
|
241
238
|
const filled = hasContent(value) || attachments.length > 0;
|
|
242
239
|
const canSend = filled && !disabled && !streaming;
|
|
243
|
-
const activeMode = modes?.find(
|
|
240
|
+
const activeMode = modes?.find(option => option.id === mode);
|
|
244
241
|
const optionId = (index) => `${listId}-option-${index}`;
|
|
245
242
|
const panelOpen = !!panel;
|
|
246
243
|
useLayoutEffect(() => {
|
|
@@ -255,25 +252,21 @@ export function ChatInput({ value, onValueChange, onSend, onStop, status = "idle
|
|
|
255
252
|
};
|
|
256
253
|
const fill = (prompt) => {
|
|
257
254
|
editor.current?.setContent(textDoc(prompt.prompt ?? prompt.label));
|
|
258
|
-
editor.current?.editor()?.commands.focus(
|
|
255
|
+
editor.current?.editor()?.commands.focus('end');
|
|
259
256
|
onPromptSelect?.(prompt);
|
|
260
257
|
};
|
|
261
|
-
return (_jsxs("div", { "data-slot": "chat-input", "data-status": status, "data-mode-color": activeMode?.color ?
|
|
258
|
+
return (_jsxs("div", { "data-slot": "chat-input", "data-status": status, "data-mode-color": activeMode?.color ? '' : undefined, style: activeMode?.color
|
|
262
259
|
? {
|
|
263
|
-
|
|
260
|
+
'--sprout-chat-input-mode': activeMode.color,
|
|
264
261
|
}
|
|
265
|
-
: undefined, className: cn(
|
|
262
|
+
: undefined, className: cn('sprout-chat-input', className), children: [_jsxs("form", { ref: form, "aria-label": label, className: "sprout-chat-input-form", onSubmit: event => {
|
|
266
263
|
event.preventDefault();
|
|
267
264
|
send();
|
|
268
|
-
}, children: [_jsxs(InputGroup, { variant: "composer", className: "sprout-chat-input-box", children: [attachments.length > 0 && (_jsx(InputGroupAddon, { align: "block-start", className: "sprout-chat-input-attachments", children: attachments.map(
|
|
269
|
-
? () => onRemoveAttachment(file.id)
|
|
270
|
-
: undefined }, file.id))) })), _jsx(RichTextEditor, { ref: editor, value: value, onChange: onValueChange, onSend: send, extensions: extensions, placeholder: streaming ? streamingPlaceholder : placeholder, disabled: disabled, ariaLabel: label, ariaExpanded: !!panel, ariaControls: panel ? listId : undefined, ariaActiveDescendant: panel?.items.length ? optionId(panel.active) : undefined, className: "sprout-chat-input-editor", toolbarAddon: _jsxs("div", { className: "sprout-chat-input-bar", children: [_jsxs("div", { className: "sprout-chat-input-bar-start", children: [attachActions && attachActions.length > 0 && (_jsxs(DropdownMenu, { children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { render: _jsx(DropdownMenuTrigger, { render: _jsx(InputGroupButton, { size: "icon-sm", "aria-label": "Add files and more", disabled: disabled }) }), children: _jsx(Plus, { size: 16, "aria-hidden": "true" }) }), _jsx(TooltipContent, { children: "Add files and more" })] }), _jsx(DropdownMenuContent, { size: "menu", side: "top", align: "start", className: "sprout-chat-input-menu", children: _jsxs(DropdownMenuGroup, { children: [_jsx(DropdownMenuLabel, { children: "Add" }), attachActions.map((action) => (_jsxs(DropdownMenuItem, { onClick: action.onSelect, children: [action.icon, _jsxs("span", { className: "sprout-chat-input-option-text", children: [_jsx("span", { children: action.label }), action.description && (_jsx("span", { className: "sprout-chat-input-option-description", children: action.description }))] })] }, action.id)))] }) })] })), modes && modes.length > 0 && (_jsxs(DropdownMenu, { children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { render: _jsx(DropdownMenuTrigger, { render: _jsx(InputGroupButton, { size: "icon-sm", "aria-label": `Mode: ${activeMode?.label ?? "Default"}`, disabled: disabled }) }), children: _jsx(Sliders, { size: 16, "aria-hidden": "true" }) }), _jsx(TooltipContent, { children: "Modes" })] }), _jsx(DropdownMenuContent, { size: "menu", side: "top", align: "start", className: "sprout-chat-input-menu", children: _jsxs(DropdownMenuGroup, { children: [_jsx(DropdownMenuLabel, { children: "Mode" }), _jsx(DropdownMenuRadioGroup, { value: mode ?? "", onValueChange: (next) => onModeChange?.(next === mode || !next ? null : String(next)), children: modes.map((option) => (_jsxs(DropdownMenuRadioItem, { value: option.id, closeOnClick: true, style: option.color
|
|
265
|
+
}, children: [_jsxs(InputGroup, { variant: "composer", className: "sprout-chat-input-box", children: [attachments.length > 0 && (_jsx(InputGroupAddon, { align: "block-start", className: "sprout-chat-input-attachments", children: attachments.map(file => (_jsx(FileAttachment, { file: file, variant: "chip", viewable: true, preview: true, onRemove: onRemoveAttachment && !disabled ? () => onRemoveAttachment(file.id) : undefined }, file.id))) })), _jsx(RichTextEditor, { ref: editor, value: value, onChange: onValueChange, onSend: send, extensions: extensions, placeholder: streaming ? streamingPlaceholder : placeholder, disabled: disabled, ariaLabel: label, ariaExpanded: !!panel, ariaControls: panel ? listId : undefined, ariaActiveDescendant: panel?.items.length ? optionId(panel.active) : undefined, className: "sprout-chat-input-editor", toolbarAddon: _jsxs("div", { className: "sprout-chat-input-bar", children: [_jsxs("div", { className: "sprout-chat-input-bar-start", children: [attachActions && attachActions.length > 0 && (_jsxs(DropdownMenu, { children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { render: _jsx(DropdownMenuTrigger, { render: _jsx(InputGroupButton, { size: "icon", "aria-label": "Add files and more", disabled: disabled }) }), children: _jsx(Plus, { size: 16, "aria-hidden": "true" }) }), _jsx(TooltipContent, { children: "Add files and more" })] }), _jsx(DropdownMenuContent, { size: "menu", side: "top", align: "start", className: "sprout-chat-input-menu", children: _jsxs(DropdownMenuGroup, { children: [_jsx(DropdownMenuLabel, { children: "Add" }), attachActions.map(action => (_jsxs(DropdownMenuItem, { onClick: action.onSelect, children: [action.icon, _jsxs("span", { className: "sprout-chat-input-option-text", children: [_jsx("span", { children: action.label }), action.description && (_jsx("span", { className: "sprout-chat-input-option-description", children: action.description }))] })] }, action.id)))] }) })] })), modes && modes.length > 0 && (_jsxs(DropdownMenu, { children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { render: _jsx(DropdownMenuTrigger, { render: _jsx(InputGroupButton, { size: "icon", "aria-label": `Mode: ${activeMode?.label ?? 'Default'}`, disabled: disabled }) }), children: _jsx(Sliders, { size: 16, "aria-hidden": "true" }) }), _jsx(TooltipContent, { children: "Modes" })] }), _jsx(DropdownMenuContent, { size: "menu", side: "top", align: "start", className: "sprout-chat-input-menu", children: _jsxs(DropdownMenuGroup, { children: [_jsx(DropdownMenuLabel, { children: "Mode" }), _jsx(DropdownMenuRadioGroup, { value: mode ?? '', onValueChange: next => onModeChange?.(next === mode || !next ? null : String(next)), children: modes.map(option => (_jsxs(DropdownMenuRadioItem, { value: option.id, closeOnClick: true, style: option.color
|
|
271
266
|
? {
|
|
272
|
-
|
|
267
|
+
'--sprout-chat-input-mode': option.color,
|
|
273
268
|
}
|
|
274
|
-
: undefined, className: option.color
|
|
275
|
-
? "sprout-chat-input-mode-option"
|
|
276
|
-
: undefined, children: [option.icon, _jsxs("span", { className: "sprout-chat-input-option-text", children: [_jsx("span", { children: option.label }), option.description && (_jsx("span", { className: "sprout-chat-input-option-description", children: option.description }))] })] }, option.id))) })] }) })] })), activeMode && (_jsxs(InputGroupButton, { size: "sm", variant: "secondary", className: "sprout-chat-input-mode", "aria-label": `Turn off ${activeMode.label}`, disabled: disabled, onClick: () => onModeChange?.(null), children: [activeMode.icon, _jsx("span", { className: "sprout-chat-input-picker-label", children: activeMode.label }), _jsx(X, { size: 12, "aria-hidden": "true" })] })), projects && projects.length > 0 && (_jsxs(_Fragment, { children: [_jsx("span", { className: "sprout-chat-input-divider", "aria-hidden": "true" }), _jsx(OptionPicker, { label: "Project", search: "Search projects", options: projects, value: project, onChange: (id) => onProjectChange?.(id), disabled: disabled, icon: (option) => option?.icon ?? (_jsx(Folder, { size: 16, "aria-hidden": "true" })), align: "start" })] }))] }), _jsxs("div", { className: "sprout-chat-input-bar-end", children: [models && models.length > 0 && (_jsx(OptionPicker, { label: "Model", search: "Search models", options: models, value: model, onChange: (id) => onModelChange?.(id), disabled: disabled, icon: (option) => option && _jsx(ModelMark, { model: option }), align: "end" })), streaming ? (_jsx(InputGroupButton, { size: "icon-sm", variant: "default", className: "sprout-chat-input-send", "aria-label": "Stop", onClick: onStop, children: _jsx("span", { className: "sprout-chat-input-stop", "aria-hidden": "true" }) })) : (_jsx(InputGroupButton, { type: "submit", size: "icon-sm", variant: canSend ? "default" : "secondary", className: "sprout-chat-input-send", "aria-label": "Send message", disabled: !canSend, children: _jsx(ArrowUp, { size: 16, "aria-hidden": "true" }) }))] })] }) })] }), panel && (_jsx("div", { className: "sprout-chat-input-panel", "data-side": panelBelow ? "bottom" : "top", children: _jsx(MentionList, { id: listId, label: triggers[panel.kind].label, announcement: panel.items.length
|
|
269
|
+
: undefined, className: option.color ? 'sprout-chat-input-mode-option' : undefined, children: [option.icon, _jsxs("span", { className: "sprout-chat-input-option-text", children: [_jsx("span", { children: option.label }), option.description && (_jsx("span", { className: "sprout-chat-input-option-description", children: option.description }))] })] }, option.id))) })] }) })] })), activeMode && (_jsxs(InputGroupButton, { variant: "secondary", className: "sprout-chat-input-mode", "aria-label": `Turn off ${activeMode.label}`, disabled: disabled, onClick: () => onModeChange?.(null), children: [activeMode.icon, _jsx("span", { className: "sprout-chat-input-picker-label", children: activeMode.label }), _jsx(X, { size: 12, "aria-hidden": "true" })] })), projects && projects.length > 0 && (_jsxs(_Fragment, { children: [_jsx("span", { className: "sprout-chat-input-divider", "aria-hidden": "true" }), _jsx(OptionPicker, { label: "Project", search: "Search projects", options: projects, value: project, onChange: id => onProjectChange?.(id), disabled: disabled, icon: option => option?.icon ?? _jsx(Folder, { size: 16, "aria-hidden": "true" }), align: "start" })] }))] }), _jsxs("div", { className: "sprout-chat-input-bar-end", children: [models && models.length > 0 && (_jsx(OptionPicker, { label: "Model", search: "Search models", options: models, value: model, onChange: id => onModelChange?.(id), disabled: disabled, icon: option => option && _jsx(ModelMark, { model: option }), align: "end" })), streaming ? (_jsx(InputGroupButton, { size: "icon", variant: "default", className: "sprout-chat-input-send", "aria-label": "Stop", onClick: onStop, children: _jsx("span", { className: "sprout-chat-input-stop", "aria-hidden": "true" }) })) : (_jsx(InputGroupButton, { type: "submit", size: "icon", variant: canSend ? 'default' : 'secondary', className: "sprout-chat-input-send", "aria-label": "Send message", disabled: !canSend, children: _jsx(ArrowUp, { size: 16, "aria-hidden": "true" }) }))] })] }) })] }), panel && (_jsx("div", { className: "sprout-chat-input-panel", "data-side": panelBelow ? 'bottom' : 'top', children: _jsx(MentionList, { id: listId, label: triggers[panel.kind].label, announcement: panel.items.length
|
|
277
270
|
? `${panel.items.length} ${triggers[panel.kind].label.toLowerCase()}. Use Up and Down to choose, Enter to add, Escape to close.`
|
|
278
|
-
: triggers[panel.kind].empty, status: panel.items.length ? undefined : (_jsx(MentionStatus, { tone: "empty", children: triggers[panel.kind].empty })), children: panel.items.map((item, index) => (_jsx(MentionOption, { id: optionId(index), active: index === panel.active, onSelect: () => panel.select(index), media: item.media, title: item.label, description: item.description }, item.id))) }) }))] }), prompts && prompts.length > 0 && !filled && !streaming && (_jsx("div", { role: "group", "aria-label": "Suggested prompts", className: "sprout-chat-input-prompts", children: prompts.map(
|
|
271
|
+
: triggers[panel.kind].empty, status: panel.items.length ? undefined : (_jsx(MentionStatus, { tone: "empty", children: triggers[panel.kind].empty })), children: panel.items.map((item, index) => (_jsx(MentionOption, { id: optionId(index), active: index === panel.active, onSelect: () => panel.select(index), media: item.media, title: item.label, description: item.description }, item.id))) }) }))] }), prompts && prompts.length > 0 && !filled && !streaming && (_jsx("div", { role: "group", "aria-label": "Suggested prompts", className: "sprout-chat-input-prompts", children: prompts.map(prompt => (_jsxs(Button, { size: "sm", variant: "outline", disabled: disabled, className: "sprout-chat-input-prompt", onClick: () => fill(prompt), children: [prompt.icon, prompt.label] }, prompt.id))) }))] }));
|
|
279
272
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ComponentProps } from
|
|
1
|
+
import type { ComponentProps } from 'react';
|
|
2
2
|
export declare const chatPlanStepStateNames: readonly ["pending", "running", "complete", "error"];
|
|
3
3
|
export type ChatPlanStepState = (typeof chatPlanStepStateNames)[number];
|
|
4
4
|
export type ChatPlanStep = {
|
|
@@ -8,7 +8,7 @@ export type ChatPlanStep = {
|
|
|
8
8
|
detail?: string | undefined;
|
|
9
9
|
state: ChatPlanStepState;
|
|
10
10
|
};
|
|
11
|
-
export interface ChatPlanProps extends Omit<ComponentProps<
|
|
11
|
+
export interface ChatPlanProps extends Omit<ComponentProps<'section'>, 'title' | 'children'> {
|
|
12
12
|
/** The plan name. It names the section and shows above the steps. */
|
|
13
13
|
title: string;
|
|
14
14
|
/** Steps in order. With none, the plan says no steps were proposed yet. */
|
|
@@ -1,27 +1,22 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Check } from
|
|
3
|
-
import { Clock } from
|
|
4
|
-
import { Warning } from
|
|
5
|
-
import { cn } from
|
|
6
|
-
import { Spinner } from
|
|
7
|
-
export const chatPlanStepStateNames = [
|
|
8
|
-
"pending",
|
|
9
|
-
"running",
|
|
10
|
-
"complete",
|
|
11
|
-
"error",
|
|
12
|
-
];
|
|
2
|
+
import { Check } from 'reicon-react/icons/Check';
|
|
3
|
+
import { Clock } from 'reicon-react/icons/Clock';
|
|
4
|
+
import { Warning } from 'reicon-react/icons/Warning';
|
|
5
|
+
import { cn } from '../internal/classes.js';
|
|
6
|
+
import { Spinner } from './spinner.js';
|
|
7
|
+
export const chatPlanStepStateNames = ['pending', 'running', 'complete', 'error'];
|
|
13
8
|
const stateLabels = {
|
|
14
|
-
pending:
|
|
15
|
-
running:
|
|
16
|
-
complete:
|
|
17
|
-
error:
|
|
9
|
+
pending: 'Not started',
|
|
10
|
+
running: 'In progress',
|
|
11
|
+
complete: 'Complete',
|
|
12
|
+
error: 'Failed',
|
|
18
13
|
};
|
|
19
14
|
function StepIcon({ state }) {
|
|
20
|
-
if (state ===
|
|
15
|
+
if (state === 'running')
|
|
21
16
|
return _jsx(Spinner, { "aria-hidden": "true" });
|
|
22
|
-
if (state ===
|
|
17
|
+
if (state === 'complete')
|
|
23
18
|
return _jsx(Check, { size: 16, "aria-hidden": "true" });
|
|
24
|
-
if (state ===
|
|
19
|
+
if (state === 'error')
|
|
25
20
|
return _jsx(Warning, { size: 16, "aria-hidden": "true" });
|
|
26
21
|
return _jsx(Clock, { size: 16, "aria-hidden": "true" });
|
|
27
22
|
}
|
|
@@ -30,6 +25,6 @@ function StepIcon({ state }) {
|
|
|
30
25
|
* in progress, complete, or failed. The header counts completed steps.
|
|
31
26
|
*/
|
|
32
27
|
export function ChatPlan({ title, steps, className, ...props }) {
|
|
33
|
-
const complete = steps.filter(
|
|
34
|
-
return (_jsxs("section", { "data-slot": "chat-plan", "aria-label": title, ...props, className: cn(
|
|
28
|
+
const complete = steps.filter(step => step.state === 'complete').length;
|
|
29
|
+
return (_jsxs("section", { "data-slot": "chat-plan", "aria-label": title, ...props, className: cn('sprout-chat-plan', className), children: [_jsxs("div", { className: "sprout-chat-plan-header", children: [_jsx("h4", { className: "sprout-chat-plan-title", children: title }), _jsxs("span", { className: "sprout-chat-plan-count", children: [complete, " of ", steps.length, " complete"] })] }), steps.length === 0 ? (_jsx("p", { className: "sprout-chat-plan-empty", children: "No steps have been proposed yet." })) : (_jsx("ol", { className: "sprout-chat-plan-steps", children: steps.map(step => (_jsxs("li", { "data-slot": "chat-plan-step", "data-state": step.state, className: "sprout-chat-plan-step", children: [_jsx("span", { className: "sprout-chat-plan-icon", children: _jsx(StepIcon, { state: step.state }) }, step.state), _jsxs("div", { className: "sprout-chat-plan-text", children: [_jsxs("p", { className: "sprout-chat-plan-step-title", children: [step.title, _jsxs("span", { className: "sprout-chat-plan-sr-only", children: [' · ', stateLabels[step.state]] })] }), step.detail && _jsx("p", { className: "sprout-chat-plan-detail", children: step.detail })] })] }, step.id))) }))] }));
|
|
35
30
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ComponentProps } from
|
|
1
|
+
import { type ComponentProps } from 'react';
|
|
2
2
|
export type ChatSource = {
|
|
3
3
|
id: string;
|
|
4
4
|
title: string;
|
|
@@ -18,7 +18,7 @@ export interface InlineCitationProps {
|
|
|
18
18
|
* Enter shows the cited passage and where it comes from.
|
|
19
19
|
*/
|
|
20
20
|
export declare function InlineCitation({ source, number }: InlineCitationProps): import("react").JSX.Element;
|
|
21
|
-
export interface ChatSourcesProps extends Omit<ComponentProps<
|
|
21
|
+
export interface ChatSourcesProps extends Omit<ComponentProps<'div'>, 'children'> {
|
|
22
22
|
/** Sources in citation order. With none, it says no sources were used. */
|
|
23
23
|
sources: readonly ChatSource[];
|
|
24
24
|
/** Start with the list open. */
|
|
@@ -32,19 +32,19 @@ export declare function ChatSources({ sources, defaultOpen, className, ...props
|
|
|
32
32
|
export declare const citationStateKindNames: readonly ["idle", "loading", "ready", "unavailable", "error"];
|
|
33
33
|
export type CitationStateKind = (typeof citationStateKindNames)[number];
|
|
34
34
|
export type CitationState = {
|
|
35
|
-
kind:
|
|
35
|
+
kind: 'idle';
|
|
36
36
|
} | {
|
|
37
|
-
kind:
|
|
37
|
+
kind: 'loading';
|
|
38
38
|
} | {
|
|
39
|
-
kind:
|
|
39
|
+
kind: 'ready';
|
|
40
40
|
title: string;
|
|
41
41
|
location: string;
|
|
42
42
|
excerpt: string;
|
|
43
43
|
} | {
|
|
44
|
-
kind:
|
|
44
|
+
kind: 'unavailable';
|
|
45
45
|
message: string;
|
|
46
46
|
} | {
|
|
47
|
-
kind:
|
|
47
|
+
kind: 'error';
|
|
48
48
|
message: string;
|
|
49
49
|
};
|
|
50
50
|
export interface CheckedCitationProps {
|
|
@@ -61,4 +61,4 @@ export interface CheckedCitationProps {
|
|
|
61
61
|
* click. While checking it shows a spinner; an unavailable source never shows
|
|
62
62
|
* an old passage.
|
|
63
63
|
*/
|
|
64
|
-
export declare function CheckedCitation({ label, state, onOpen, onRetry
|
|
64
|
+
export declare function CheckedCitation({ label, state, onOpen, onRetry }: CheckedCitationProps): import("react").JSX.Element;
|