@tulipfarm/sprout 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +13 -11
- 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 +10 -5
- 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 +17 -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,28 +1,28 @@
|
|
|
1
|
-
import { type ComponentProps } from
|
|
1
|
+
import { type ComponentProps, type ReactNode } from 'react';
|
|
2
2
|
export declare const chatConfirmationStateNames: readonly ["pending", "submitting", "approved", "rejected", "expired", "cancelled", "error"];
|
|
3
|
-
export type ChatConfirmationDecision =
|
|
3
|
+
export type ChatConfirmationDecision = 'approve' | 'reject';
|
|
4
4
|
export type ConfirmationState = {
|
|
5
|
-
kind:
|
|
5
|
+
kind: 'pending';
|
|
6
6
|
} | {
|
|
7
|
-
kind:
|
|
7
|
+
kind: 'submitting';
|
|
8
8
|
decision: ChatConfirmationDecision;
|
|
9
9
|
} | {
|
|
10
|
-
kind:
|
|
10
|
+
kind: 'approved';
|
|
11
11
|
} | {
|
|
12
|
-
kind:
|
|
12
|
+
kind: 'rejected';
|
|
13
13
|
} | {
|
|
14
|
-
kind:
|
|
14
|
+
kind: 'expired';
|
|
15
15
|
} | {
|
|
16
|
-
kind:
|
|
16
|
+
kind: 'cancelled';
|
|
17
17
|
} | {
|
|
18
|
-
kind:
|
|
18
|
+
kind: 'error';
|
|
19
19
|
message: string;
|
|
20
20
|
};
|
|
21
21
|
export type ChatConfirmationDetail = {
|
|
22
22
|
label: string;
|
|
23
23
|
value: string;
|
|
24
24
|
};
|
|
25
|
-
export interface ChatConfirmationProps extends Omit<ComponentProps<
|
|
25
|
+
export interface ChatConfirmationProps extends Omit<ComponentProps<'div'>, 'title' | 'children'> {
|
|
26
26
|
/** What the agent wants to do, such as “Remove the Notes field”. */
|
|
27
27
|
title: string;
|
|
28
28
|
/** One line above the facts, such as “Review these changes before approving.” */
|
|
@@ -33,10 +33,12 @@ export interface ChatConfirmationProps extends Omit<ComponentProps<"div">, "titl
|
|
|
33
33
|
onDecision: (decision: ChatConfirmationDecision) => void;
|
|
34
34
|
/** Locks both buttons, such as while the request is refreshing or cannot be verified. */
|
|
35
35
|
disabled?: boolean | undefined;
|
|
36
|
+
/** Names the action on the approve button, such as “Approve 3 drafts”. */
|
|
37
|
+
approveLabel?: ReactNode;
|
|
36
38
|
}
|
|
37
39
|
/**
|
|
38
40
|
* Asks someone in chat to approve or decline an action an agent proposed.
|
|
39
41
|
* Built on `ReviewCard`: it folds once decided, and when the decision was
|
|
40
42
|
* made from inside the card, focus moves to the outcome.
|
|
41
43
|
*/
|
|
42
|
-
export declare function ChatConfirmation({ title, description, details, state, onDecision, disabled, className, ...props }: ChatConfirmationProps): import("react").JSX.Element;
|
|
44
|
+
export declare function ChatConfirmation({ title, description, details, state, onDecision, disabled, approveLabel, className, ...props }: ChatConfirmationProps): import("react").JSX.Element;
|
|
@@ -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, className, ...props }) {
|
|
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, { size: "sm", "aria-label": `${label}: ${selected?.label ??
|
|
202
|
+
const selected = options.find(option => option.id === value);
|
|
203
|
+
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsxs(PopoverTrigger, { render: _jsx(InputGroupButton, { size: "sm", "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-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
|
|
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, { 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
|
|
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;
|