@tulipfarm/sprout 0.3.0 → 0.3.1
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
CHANGED
|
@@ -98,7 +98,7 @@ for notes on each one.
|
|
|
98
98
|
|
|
99
99
|
<!-- bundle-size:start -->
|
|
100
100
|
|
|
101
|
-
Full library: **786.
|
|
101
|
+
Full library: **786.4 kB** gzip. Each component path is smaller. Sizes are minified, with React and other peer dependencies left out.
|
|
102
102
|
|
|
103
103
|
<details>
|
|
104
104
|
<summary>Size of each component</summary>
|
|
@@ -168,7 +168,7 @@ Full library: **786.3 kB** gzip. Each component path is smaller. Sizes are minif
|
|
|
168
168
|
| `radio-group` | 80.8 kB | 27.9 kB | 24.7 kB |
|
|
169
169
|
| `reasoning-effort` | 35.5 kB | 12.0 kB | 10.5 kB |
|
|
170
170
|
| `resizable` | 39.4 kB | 13.4 kB | 11.8 kB |
|
|
171
|
-
| `result-card` | 240.
|
|
171
|
+
| `result-card` | 240.3 kB | 85.1 kB | 72.1 kB |
|
|
172
172
|
| `review-card` | 61.6 kB | 21.0 kB | 18.4 kB |
|
|
173
173
|
| `rich-text-editor` | 442.5 kB | 140.2 kB | 119.8 kB |
|
|
174
174
|
| `schema-diagram` | 247.9 kB | 82.9 kB | 71.2 kB |
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ComponentProps } from "react";
|
|
1
|
+
import { type ComponentProps, type ReactNode } from "react";
|
|
2
2
|
export declare const chatConfirmationStateNames: readonly ["pending", "submitting", "approved", "rejected", "expired", "cancelled", "error"];
|
|
3
3
|
export type ChatConfirmationDecision = "approve" | "reject";
|
|
4
4
|
export type ConfirmationState = {
|
|
@@ -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;
|
|
@@ -41,7 +41,7 @@ const outcomes = {
|
|
|
41
41
|
* Built on `ReviewCard`: it folds once decided, and when the decision was
|
|
42
42
|
* made from inside the card, focus moves to the outcome.
|
|
43
43
|
*/
|
|
44
|
-
export function ChatConfirmation({ title, description, details, state, onDecision, disabled = false, className, ...props }) {
|
|
44
|
+
export function ChatConfirmation({ title, description, details, state, onDecision, disabled = false, approveLabel = "Approve action", className, ...props }) {
|
|
45
45
|
const done = settledKinds.has(state.kind);
|
|
46
46
|
const section = useRef(null);
|
|
47
47
|
const result = useRef(null);
|
|
@@ -58,5 +58,5 @@ export function ChatConfirmation({ title, description, details, state, onDecisio
|
|
|
58
58
|
const submitting = state.kind === "submitting";
|
|
59
59
|
const busy = (decision) => state.kind === "submitting" && state.decision === decision;
|
|
60
60
|
const outcome = outcomes[state.kind];
|
|
61
|
-
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" }),
|
|
61
|
+
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
62
|
}
|
|
@@ -10,10 +10,15 @@ export type ResultAppAction = {
|
|
|
10
10
|
label: string;
|
|
11
11
|
state: ResultAppActionState;
|
|
12
12
|
};
|
|
13
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* One app that took part in a result. `brand: null` shows `icon`, or a
|
|
15
|
+
* generic plug when no icon is given.
|
|
16
|
+
*/
|
|
14
17
|
export type ResultApp = {
|
|
15
18
|
brand: Brand | null;
|
|
16
19
|
name: string;
|
|
20
|
+
/** Shown when `brand` is null, such as a table icon for your own data. */
|
|
21
|
+
icon?: ReactNode;
|
|
17
22
|
actions: readonly ResultAppAction[];
|
|
18
23
|
};
|
|
19
24
|
export type ResultCardAction = {
|
|
@@ -77,12 +77,12 @@ function AppActionsPopover({ apps, overflow = false, disabled, }) {
|
|
|
77
77
|
const title = overflow
|
|
78
78
|
? `${apps.length} more ${apps.length === 1 ? "app" : "apps"}`
|
|
79
79
|
: `${first.name} actions`;
|
|
80
|
-
return (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { openOnHover: true, delay: 800, closeDelay: 200, render: _jsx(BrandTile, { size: "action", render: _jsx(Button, { variant: "ghost", size: "icon", disabled: disabled }) }), "aria-label": title, children: overflow ? (_jsxs("span", { className: "sprout-result-card-overflow", children: ["+", apps.length] })) : first.brand ? (_jsx(BrandIcon, { brand: first.brand, size: "fill" })) : (_jsx(Plug, { size: 18, "aria-hidden": "true" })) }), _jsxs(PopoverContent, { size: "app-actions", align: "start", sideOffset: 8, initialFocus: (interaction) => interaction !== "mouse", children: [_jsx(PopoverTitle, { children: title }), _jsx(ResultAppActions, { apps: apps, showAppNames: overflow })] })] }));
|
|
80
|
+
return (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { openOnHover: true, delay: 800, closeDelay: 200, render: _jsx(BrandTile, { size: "action", render: _jsx(Button, { variant: "ghost", size: "icon", disabled: disabled }) }), "aria-label": title, children: overflow ? (_jsxs("span", { className: "sprout-result-card-overflow", children: ["+", apps.length] })) : first.brand ? (_jsx(BrandIcon, { brand: first.brand, size: "fill" })) : first.icon ? (_jsx("span", { "aria-hidden": "true", className: "sprout-result-app-icon", children: first.icon })) : (_jsx(Plug, { size: 18, "aria-hidden": "true" })) }), _jsxs(PopoverContent, { size: "app-actions", align: "start", sideOffset: 8, initialFocus: (interaction) => interaction !== "mouse", children: [_jsx(PopoverTitle, { children: title }), _jsx(ResultAppActions, { apps: apps, showAppNames: overflow })] })] }));
|
|
81
81
|
}
|
|
82
82
|
/**
|
|
83
83
|
* The actions each app took, grouped by app. A check marks completed
|
|
84
84
|
* actions; every other state is spelled out, such as “Unconfirmed:”.
|
|
85
85
|
*/
|
|
86
86
|
export function ResultAppActions({ apps, showAppNames = true, className, ...props }) {
|
|
87
|
-
return (_jsx("div", { "data-slot": "result-app-actions", ...props, className: cn("sprout-result-app-actions", className), children: apps.map((app) => (_jsxs("section", { "aria-label": app.name, className: "sprout-result-app", children: [showAppNames && (_jsxs("div", { className: "sprout-result-app-name", children: [app.brand ? (_jsx(BrandIcon, { brand: app.brand, size: "glyph" })) : (_jsx(Plug, { size: 20, "aria-hidden": "true" })), _jsx("h4", { children: app.name })] })), app.actions.length === 0 ? (_jsx("p", { className: "sprout-result-app-empty", children: "No action details were recorded." })) : (_jsx("ul", { className: "sprout-result-app-list", children: app.actions.map((action, index) => (_jsxs("li", { "data-state": action.state, className: "sprout-result-app-action", children: [action.state === "completed" ? (_jsxs("span", { className: "sprout-result-app-check", children: [_jsx(Check, { size: 16, "aria-hidden": "true" }), _jsx("span", { className: "sprout-result-sr-only", children: "Completed:" })] })) : (_jsx("span", { className: "sprout-result-app-prefix", children: actionPrefixes[action.state] })), _jsx("span", { className: "sprout-result-app-label", children: action.label })] }, `${action.label}:${index}`))) }))] }, app.brand ?? app.name))) }));
|
|
87
|
+
return (_jsx("div", { "data-slot": "result-app-actions", ...props, className: cn("sprout-result-app-actions", className), children: apps.map((app) => (_jsxs("section", { "aria-label": app.name, className: "sprout-result-app", children: [showAppNames && (_jsxs("div", { className: "sprout-result-app-name", children: [app.brand ? (_jsx(BrandIcon, { brand: app.brand, size: "glyph" })) : app.icon ? (_jsx("span", { "aria-hidden": "true", className: "sprout-result-app-icon", children: app.icon })) : (_jsx(Plug, { size: 20, "aria-hidden": "true" })), _jsx("h4", { children: app.name })] })), app.actions.length === 0 ? (_jsx("p", { className: "sprout-result-app-empty", children: "No action details were recorded." })) : (_jsx("ul", { className: "sprout-result-app-list", children: app.actions.map((action, index) => (_jsxs("li", { "data-state": action.state, className: "sprout-result-app-action", children: [action.state === "completed" ? (_jsxs("span", { className: "sprout-result-app-check", children: [_jsx(Check, { size: 16, "aria-hidden": "true" }), _jsx("span", { className: "sprout-result-sr-only", children: "Completed:" })] })) : (_jsx("span", { className: "sprout-result-app-prefix", children: actionPrefixes[action.state] })), _jsx("span", { className: "sprout-result-app-label", children: action.label })] }, `${action.label}:${index}`))) }))] }, app.brand ?? app.name))) }));
|
|
88
88
|
}
|
|
@@ -150,6 +150,20 @@
|
|
|
150
150
|
.sprout-result-app-name > svg {
|
|
151
151
|
flex-shrink: 0;
|
|
152
152
|
}
|
|
153
|
+
.sprout-result-app-icon {
|
|
154
|
+
display: inline-flex;
|
|
155
|
+
flex-shrink: 0;
|
|
156
|
+
width: 18px;
|
|
157
|
+
height: 18px;
|
|
158
|
+
}
|
|
159
|
+
.sprout-result-app-name > .sprout-result-app-icon {
|
|
160
|
+
width: 20px;
|
|
161
|
+
height: 20px;
|
|
162
|
+
}
|
|
163
|
+
.sprout-result-app-icon > svg {
|
|
164
|
+
width: 100%;
|
|
165
|
+
height: 100%;
|
|
166
|
+
}
|
|
153
167
|
.sprout-result-app-name h4 {
|
|
154
168
|
margin: 0;
|
|
155
169
|
color: var(--sprout-text);
|