@ciridae/ui 1.0.5 → 1.0.9
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 +3 -2
- package/dist/chat/conversation-source.d.ts +1 -3
- package/dist/chat/message-text.js +6 -6
- package/dist/chat/use-chat-conversation.d.ts +7 -2
- package/dist/chat/use-chat-conversation.js +2 -1
- package/dist/components/activity-feed.d.ts +0 -1
- package/dist/components/activity-feed.js +6 -7
- package/dist/components/agent-work.d.ts +5 -1
- package/dist/components/agent-work.js +27 -13
- package/dist/components/app-frame.d.ts +3 -17
- package/dist/components/app-frame.js +11 -30
- package/dist/components/app-navigation.d.ts +5 -6
- package/dist/components/app-navigation.js +65 -40
- package/dist/components/badge.d.ts +0 -4
- package/dist/components/badge.js +17 -27
- package/dist/components/bulk-action-bar.js +2 -2
- package/dist/components/button.js +41 -50
- package/dist/components/calendar.js +5 -8
- package/dist/components/centered-page.js +4 -4
- package/dist/components/chart.js +3 -4
- package/dist/components/chat-client-source.js +55 -34
- package/dist/components/chat-page.js +1 -1
- package/dist/components/chat-sheet.d.ts +30 -20
- package/dist/components/chat-sheet.js +109 -51
- package/dist/components/chat.d.ts +27 -56
- package/dist/components/chat.js +151 -129
- package/dist/components/checkbox-item.js +4 -4
- package/dist/components/checkbox-list.js +6 -6
- package/dist/components/chip.js +2 -2
- package/dist/components/collapsible.js +3 -3
- package/dist/components/color-theme.d.ts +3 -6
- package/dist/components/color-theme.js +10 -11
- package/dist/components/column-settings.js +3 -3
- package/dist/components/command-menu.d.ts +1 -2
- package/dist/components/command-menu.js +56 -77
- package/dist/components/command-palette.js +5 -2
- package/dist/components/copyable-id.js +5 -5
- package/dist/components/data-display.d.ts +1 -7
- package/dist/components/data-display.js +32 -55
- package/dist/components/data-grid.d.ts +4 -7
- package/dist/components/data-grid.js +106 -90
- package/dist/components/date-range-picker.js +4 -5
- package/dist/components/document-viewer.js +23 -23
- package/dist/components/drawer.d.ts +2 -1
- package/dist/components/drawer.js +45 -20
- package/dist/components/dropzone.js +13 -13
- package/dist/components/editable-field.d.ts +2 -12
- package/dist/components/editable-field.js +13 -26
- package/dist/components/email-input.js +2 -3
- package/dist/components/environment-frame.js +7 -7
- package/dist/components/expandable-text.js +2 -2
- package/dist/components/feedback-screenshot.js +7 -7
- package/dist/components/feedback-sheet.js +8 -8
- package/dist/components/filter-bar.js +41 -27
- package/dist/components/form-controls.d.ts +3 -6
- package/dist/components/form-controls.js +15 -22
- package/dist/components/form-layout.d.ts +6 -6
- package/dist/components/form-layout.js +10 -16
- package/dist/components/glass-menu.d.ts +2 -0
- package/dist/components/glass-menu.js +14 -18
- package/dist/components/gradient-edge.d.ts +0 -1
- package/dist/components/gradient-edge.js +8 -9
- package/dist/components/icon.js +1 -1
- package/dist/components/input.js +18 -17
- package/dist/components/keycap.d.ts +2 -6
- package/dist/components/keycap.js +4 -12
- package/dist/components/layout.js +11 -10
- package/dist/components/lightbox.js +8 -8
- package/dist/components/link.js +1 -1
- package/dist/components/locale.d.ts +23 -7
- package/dist/components/locale.js +19 -7
- package/dist/components/log-entry.d.ts +2 -14
- package/dist/components/log-entry.js +11 -22
- package/dist/components/log-list.js +1 -1
- package/dist/components/mention-input.js +13 -14
- package/dist/components/menu.d.ts +7 -4
- package/dist/components/menu.js +23 -10
- package/dist/components/meter.d.ts +2 -3
- package/dist/components/meter.js +12 -16
- package/dist/components/navigation.d.ts +0 -7
- package/dist/components/navigation.js +3 -12
- package/dist/components/notification-tray.js +7 -7
- package/dist/components/overlays.d.ts +5 -2
- package/dist/components/overlays.js +24 -24
- package/dist/components/panel.js +3 -3
- package/dist/components/progress.js +2 -2
- package/dist/components/radio-card.d.ts +1 -1
- package/dist/components/radio-card.js +9 -9
- package/dist/components/record.d.ts +2 -4
- package/dist/components/record.js +19 -32
- package/dist/components/scroll-area.js +10 -10
- package/dist/components/segmented-bar.js +9 -9
- package/dist/components/select.d.ts +3 -5
- package/dist/components/select.js +26 -44
- package/dist/components/settings.js +1 -1
- package/dist/components/shell-skeleton.js +1 -1
- package/dist/components/shell.d.ts +1 -1
- package/dist/components/shell.js +69 -24
- package/dist/components/side-panel.js +3 -3
- package/dist/components/sidebar.d.ts +0 -5
- package/dist/components/sidebar.js +25 -33
- package/dist/components/single-line-text.js +3 -4
- package/dist/components/site-banner.js +4 -4
- package/dist/components/skeleton.js +19 -22
- package/dist/components/skeletons.d.ts +0 -3
- package/dist/components/skeletons.js +5 -10
- package/dist/components/stages.d.ts +6 -3
- package/dist/components/stages.js +77 -105
- package/dist/components/stat-card.d.ts +2 -5
- package/dist/components/stat-card.js +23 -31
- package/dist/components/status-banner.js +6 -6
- package/dist/components/status.js +3 -3
- package/dist/components/steps.js +2 -2
- package/dist/components/switch.js +1 -1
- package/dist/components/tabs.js +15 -18
- package/dist/components/theme-customizer.d.ts +5 -8
- package/dist/components/theme-customizer.js +9 -41
- package/dist/components/theme-toggle.d.ts +0 -1
- package/dist/components/theme-toggle.js +6 -11
- package/dist/components/toast.d.ts +1 -7
- package/dist/components/toast.js +19 -22
- package/dist/components/user-chip.js +8 -8
- package/dist/components/wizard.js +6 -4
- package/dist/preset.d.ts +1 -2
- package/dist/preset.js +39 -89
- package/dist/styled-system/css/conditions.mjs +1 -1
- package/dist/styled-system/css/css.mjs +1 -1
- package/dist/styled-system/styles.css +805 -1279
- package/dist/styled-system/tokens/index.mjs +74 -1926
- package/dist/styled-system/tokens/tokens.d.ts +18 -33
- package/dist/styled-system/types/conditions.d.ts +0 -74
- package/dist/styled-system/types/prop-type.d.ts +15 -40
- package/dist/styled-system/types/style-props.d.ts +705 -705
- package/dist/theme/color.d.ts +0 -1
- package/dist/theme/color.js +0 -16
- package/dist/theme/derive.d.ts +3 -3
- package/dist/theme/derive.js +9 -32
- package/dist/theme/index.d.ts +1 -2
- package/dist/theme/index.js +3 -5
- package/dist/theme/options.d.ts +2 -4
- package/dist/theme/options.js +0 -1
- package/dist/theme/{palettes.d.ts → palette.d.ts} +12 -23
- package/dist/theme/palette.js +127 -0
- package/dist/theme/tokens.d.ts +8 -13
- package/dist/theme/tokens.js +38 -92
- package/package.json +1 -1
- package/dist/theme/palettes.js +0 -254
package/README.md
CHANGED
|
@@ -11,7 +11,8 @@ npm install @ciridae/ui
|
|
|
11
11
|
Use the published package for new and updated consumers.
|
|
12
12
|
|
|
13
13
|
Panda generates the component styles in your app. Add the preset, scan the package output, and
|
|
14
|
-
recognise its `css` import alias
|
|
14
|
+
recognise its `css` import alias. The components use only this preset's tokens; add
|
|
15
|
+
`"@pandacss/preset-panda"` before it only if your own styles use Panda's stock tokens:
|
|
15
16
|
|
|
16
17
|
```ts
|
|
17
18
|
// panda.config.ts
|
|
@@ -19,7 +20,7 @@ import { ciridaePreset } from "@ciridae/ui/preset";
|
|
|
19
20
|
import { defineConfig } from "@pandacss/dev";
|
|
20
21
|
|
|
21
22
|
export default defineConfig({
|
|
22
|
-
presets: [
|
|
23
|
+
presets: [ciridaePreset],
|
|
23
24
|
importMap: { css: ["#primitives/css", "styled-system/css"] },
|
|
24
25
|
include: ["./src/**/*.{ts,tsx}", "./node_modules/@ciridae/ui/dist/**/*.js"],
|
|
25
26
|
});
|
|
@@ -27,11 +27,9 @@ export type ChatConversationItem = {
|
|
|
27
27
|
message?: string;
|
|
28
28
|
retry: () => void;
|
|
29
29
|
};
|
|
30
|
-
/**
|
|
30
|
+
/** Beyond its Markdown's, such as the values it read, as cards. */
|
|
31
31
|
sources?: readonly ChatSource[];
|
|
32
|
-
/** Buttons under the reply for what it suggests doing on the page. */
|
|
33
32
|
suggestedActions?: ReactNode;
|
|
34
|
-
/** A closing line under the reply, such as what it read. */
|
|
35
33
|
footnote?: ReactNode;
|
|
36
34
|
}
|
|
37
35
|
/**
|
|
@@ -14,7 +14,7 @@ const text = css({
|
|
|
14
14
|
overflowWrap: "anywhere",
|
|
15
15
|
"& :is(p, ul, ol, pre, table, blockquote, h1, h2, h3, h4, h5, h6, hr)": { margin: "none" },
|
|
16
16
|
"& p": { whiteSpace: "pre-line" },
|
|
17
|
-
"& :is(h1, h2, h3, h4, h5, h6)": { fontSize: "inherit", fontWeight: "semibold" },
|
|
17
|
+
"& :is(h1, h2, h3, h4, h5, h6)": { fontSize: "[inherit]", fontWeight: "semibold" },
|
|
18
18
|
"& :is(ul, ol)": { paddingInlineStart: "layout.clusterGap" },
|
|
19
19
|
"& li > :is(ul, ol)": { marginBlockStart: "control.trackInset" },
|
|
20
20
|
"& li + li": { marginBlockStart: "control.trackInset" },
|
|
@@ -38,7 +38,7 @@ const text = css({
|
|
|
38
38
|
"& hr": { border: "0", borderTop: "1px solid token(colors.border.control)" },
|
|
39
39
|
"& table": {
|
|
40
40
|
display: "block",
|
|
41
|
-
maxWidth: "
|
|
41
|
+
maxWidth: "full",
|
|
42
42
|
overflowX: "auto",
|
|
43
43
|
borderCollapse: "collapse",
|
|
44
44
|
fontVariantNumeric: "tabular-nums",
|
|
@@ -52,12 +52,12 @@ const text = css({
|
|
|
52
52
|
overflowWrap: "normal",
|
|
53
53
|
},
|
|
54
54
|
"& th": { fontWeight: "medium" },
|
|
55
|
-
"& a:not([data-mention])": { color: "inherit", textDecoration: "underline" },
|
|
55
|
+
"& a:not([data-mention])": { color: "[inherit]", textDecoration: "underline" },
|
|
56
56
|
});
|
|
57
57
|
const mention = css({
|
|
58
58
|
display: "inline-flex",
|
|
59
59
|
alignItems: "center",
|
|
60
|
-
maxWidth: "
|
|
60
|
+
maxWidth: "full",
|
|
61
61
|
paddingInline: "control.iconGap",
|
|
62
62
|
border: "1px solid token(colors.border.control)",
|
|
63
63
|
borderRadius: "keycap",
|
|
@@ -101,8 +101,8 @@ const plainText = css({
|
|
|
101
101
|
paddingInline: "none",
|
|
102
102
|
border: "0",
|
|
103
103
|
background: "transparent",
|
|
104
|
-
color: "inherit",
|
|
105
|
-
fontSize: "inherit",
|
|
104
|
+
color: "[inherit]",
|
|
105
|
+
fontSize: "[inherit]",
|
|
106
106
|
fontWeight: "semibold",
|
|
107
107
|
_hover: { background: "transparent", textDecoration: "underline" },
|
|
108
108
|
},
|
|
@@ -10,9 +10,14 @@ export type PendingMessage = {
|
|
|
10
10
|
attachments: readonly Attachment[];
|
|
11
11
|
/** When the user sent it, as epoch milliseconds, so it groups with the messages around it. */
|
|
12
12
|
sentAt: number;
|
|
13
|
+
} & ({
|
|
13
14
|
/** `posted` once the service accepted it, until the conversation's items include it. */
|
|
14
|
-
state: "sending" | "posted"
|
|
15
|
-
}
|
|
15
|
+
state: "sending" | "posted";
|
|
16
|
+
} | {
|
|
17
|
+
state: "failed";
|
|
18
|
+
/** Why this message did not send, from the error its send threw. */
|
|
19
|
+
failureMessage: string;
|
|
20
|
+
});
|
|
16
21
|
export type ChatConversationState = {
|
|
17
22
|
conversation: Conversation | undefined;
|
|
18
23
|
items: readonly Item[];
|
|
@@ -106,7 +106,8 @@ export function useChatConversation({ client, conversationId, onConversationCrea
|
|
|
106
106
|
setPendingMessages((existing) => existing.filter((message) => message.localId !== localId));
|
|
107
107
|
}
|
|
108
108
|
catch (error) {
|
|
109
|
-
|
|
109
|
+
const failureMessage = error instanceof Error ? error.message : String(error);
|
|
110
|
+
setPendingMessages((existing) => existing.map((message) => message.localId === localId ? { ...message, state: "failed", failureMessage } : message));
|
|
110
111
|
throw error;
|
|
111
112
|
}
|
|
112
113
|
}, [client, conversationId, onConversationCreated, queryClient]);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { type ReactNode, type RefObject } from "react";
|
|
2
2
|
import { type CiridaeLabels } from "./locale.js";
|
|
3
3
|
import { type UserChipProps } from "./user-chip.js";
|
|
4
|
-
export { LogActor, LogEntry, LogGroupHeader, type LogActorProps, type LogEntryProps, type LogGroupHeaderProps, } from "./log-entry.js";
|
|
5
4
|
export type ActivityFeedActor = Pick<UserChipProps, "name" | "kind" | "src" | "icon" | "profile">;
|
|
6
5
|
export type ActivityFeedUpdate = {
|
|
7
6
|
kind: "update";
|
|
@@ -14,7 +14,6 @@ import { Toolbar } from "./layout.js";
|
|
|
14
14
|
import { useCiridaeLocale } from "./locale.js";
|
|
15
15
|
import { MentionChip, openMentionPicker, readMentions, } from "./mention-input.js";
|
|
16
16
|
import { UserName } from "./user-chip.js";
|
|
17
|
-
export { LogActor, LogEntry, LogGroupHeader, } from "./log-entry.js";
|
|
18
17
|
const FILTERS = [
|
|
19
18
|
{ value: "all", label: "all", empty: "noActivity" },
|
|
20
19
|
{ value: "comments", label: "comments", empty: "noComments" },
|
|
@@ -78,14 +77,14 @@ const updateRun = css({
|
|
|
78
77
|
gridTemplateColumns: "minmax(0, 1fr)",
|
|
79
78
|
justifyItems: "center",
|
|
80
79
|
gap: "layout.tightGap",
|
|
81
|
-
maxWidth: "
|
|
80
|
+
maxWidth: "full",
|
|
82
81
|
});
|
|
83
82
|
// The actors give way to an ellipsis before the count does.
|
|
84
83
|
const runToggle = css({
|
|
85
84
|
display: "inline-flex",
|
|
86
85
|
alignItems: "center",
|
|
87
86
|
gap: "layout.tightGap",
|
|
88
|
-
maxWidth: "
|
|
87
|
+
maxWidth: "full",
|
|
89
88
|
padding: "none",
|
|
90
89
|
border: "0",
|
|
91
90
|
background: "transparent",
|
|
@@ -94,8 +93,8 @@ const runToggle = css({
|
|
|
94
93
|
cursor: "pointer",
|
|
95
94
|
_hover: { color: "fg.primary" },
|
|
96
95
|
_focusVisible: { focusRing: "outer" },
|
|
97
|
-
"& > svg": {
|
|
98
|
-
"&[aria-expanded=true] > svg": { rotate: "90deg", _rtl: { rotate: "-90deg" } },
|
|
96
|
+
"& > svg": { transitionProperty: "[rotate]", transitionDuration: "fast" },
|
|
97
|
+
"&[aria-expanded=true] > svg": { rotate: "[90deg]", _rtl: { rotate: "[-90deg]" } },
|
|
99
98
|
"& > [data-actors]": { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
|
|
100
99
|
"& > [data-count]": { flexShrink: "0", whiteSpace: "nowrap" },
|
|
101
100
|
});
|
|
@@ -114,7 +113,7 @@ const chip = css({
|
|
|
114
113
|
display: "inline-flex",
|
|
115
114
|
alignItems: "center",
|
|
116
115
|
gap: "layout.tightGap",
|
|
117
|
-
maxWidth: "
|
|
116
|
+
maxWidth: "full",
|
|
118
117
|
minWidth: "0",
|
|
119
118
|
paddingBlock: "control.trackInset",
|
|
120
119
|
paddingInline: "control.iconGap",
|
|
@@ -151,7 +150,7 @@ const thumbnail = css({
|
|
|
151
150
|
_focusVisible: { focusRing: "outer" },
|
|
152
151
|
"& img": {
|
|
153
152
|
display: "block",
|
|
154
|
-
maxWidth: "
|
|
153
|
+
maxWidth: "full",
|
|
155
154
|
width: "auto",
|
|
156
155
|
height: "skeleton.medium",
|
|
157
156
|
objectFit: "cover",
|
|
@@ -70,7 +70,11 @@ export type AgentWorkButtonProps = {
|
|
|
70
70
|
export declare function AgentWorkButton({ tasks, title, className }: AgentWorkButtonProps): import("react").JSX.Element | null;
|
|
71
71
|
export type AgentTaskCardProps = {
|
|
72
72
|
task: AgentTask;
|
|
73
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Sends the user's approval or answer. The card's buttons wait while it runs, and if it rejects
|
|
75
|
+
* the card shows its error and takes another reply; the card goes once the task moves on.
|
|
76
|
+
*/
|
|
77
|
+
onReply: (task: AgentTask, reply: AgentTaskReply) => Promise<void>;
|
|
74
78
|
};
|
|
75
79
|
/** The agent asking: a waiting task's question, its details, and Deny / Approve or the answers. */
|
|
76
80
|
export declare function AgentTaskCard({ task, onReply }: AgentTaskCardProps): import("react").JSX.Element | null;
|
|
@@ -60,7 +60,7 @@ const nowLine = css({
|
|
|
60
60
|
});
|
|
61
61
|
const waitingRow = css({
|
|
62
62
|
display: "block",
|
|
63
|
-
width: "
|
|
63
|
+
width: "full",
|
|
64
64
|
paddingBlock: "control.compactBlock",
|
|
65
65
|
paddingInline: "menu.itemInline",
|
|
66
66
|
border: "0",
|
|
@@ -82,7 +82,7 @@ const summaryBar = css({
|
|
|
82
82
|
display: "flex",
|
|
83
83
|
alignItems: "center",
|
|
84
84
|
gap: "control.iconGap",
|
|
85
|
-
width: "
|
|
85
|
+
width: "full",
|
|
86
86
|
minHeight: "control.small",
|
|
87
87
|
paddingBlock: "layout.tightGap",
|
|
88
88
|
paddingInline: "panel.comfortable",
|
|
@@ -103,11 +103,11 @@ const summaryBar = css({
|
|
|
103
103
|
textOverflow: "ellipsis",
|
|
104
104
|
whiteSpace: "nowrap",
|
|
105
105
|
},
|
|
106
|
-
"& > svg:last-child": {
|
|
107
|
-
"&[aria-expanded=true] > svg:last-child": { rotate: "180deg" },
|
|
106
|
+
"& > svg:last-child": { transitionProperty: "[rotate]", transitionDuration: "fast" },
|
|
107
|
+
"&[aria-expanded=true] > svg:last-child": { rotate: "[180deg]" },
|
|
108
108
|
});
|
|
109
109
|
const summaryLists = css({
|
|
110
|
-
maxHeight: "50vh",
|
|
110
|
+
maxHeight: "[50vh]",
|
|
111
111
|
overflowY: "auto",
|
|
112
112
|
borderBottom: "1px solid token(colors.border.control)",
|
|
113
113
|
});
|
|
@@ -167,7 +167,7 @@ export function AgentWorkButton({ tasks, title, className }) {
|
|
|
167
167
|
const askCard = css({
|
|
168
168
|
display: "grid",
|
|
169
169
|
gap: "control.iconGap",
|
|
170
|
-
width: "
|
|
170
|
+
width: "full",
|
|
171
171
|
maxWidth: "chat.bubble",
|
|
172
172
|
paddingBlock: "control.block",
|
|
173
173
|
paddingInline: "control.compactInline",
|
|
@@ -176,9 +176,9 @@ const askCard = css({
|
|
|
176
176
|
background: "bg.card",
|
|
177
177
|
fontSize: "caption",
|
|
178
178
|
lineHeight: "log",
|
|
179
|
-
outline: "
|
|
179
|
+
outline: "0",
|
|
180
180
|
scrollMarginBlock: "panel.default",
|
|
181
|
-
transitionProperty: "border-color, box-shadow",
|
|
181
|
+
transitionProperty: "[border-color, box-shadow]",
|
|
182
182
|
transitionDuration: "fast",
|
|
183
183
|
"&[data-highlighted]": { borderColor: "border.focus", boxShadow: "focus" },
|
|
184
184
|
});
|
|
@@ -192,13 +192,14 @@ const detailList = css({
|
|
|
192
192
|
"& > dt": { color: "fg.muted", whiteSpace: "nowrap" },
|
|
193
193
|
"& > dd": { margin: "none", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
|
|
194
194
|
});
|
|
195
|
+
const replyError = css({ color: "accent.red", fontSize: "code", lineHeight: "compact" });
|
|
195
196
|
const cardActions = css({ display: "flex", justifyContent: "flex-end", gap: "layout.controlGap" });
|
|
196
197
|
const optionList = css({
|
|
197
|
-
marginInline: "calc(token(spacing.control.compactInline) * -1)",
|
|
198
|
-
marginBlockEnd: "calc(token(spacing.control.block) * -1)",
|
|
198
|
+
marginInline: "[calc(token(spacing.control.compactInline) * -1)]",
|
|
199
|
+
marginBlockEnd: "[calc(token(spacing.control.block) * -1)]",
|
|
199
200
|
"& > button": {
|
|
200
201
|
display: "block",
|
|
201
|
-
width: "
|
|
202
|
+
width: "full",
|
|
202
203
|
paddingBlock: "control.compactBlock",
|
|
203
204
|
paddingInline: "control.compactInline",
|
|
204
205
|
border: "0",
|
|
@@ -208,8 +209,9 @@ const optionList = css({
|
|
|
208
209
|
font: "inherit",
|
|
209
210
|
textAlign: "start",
|
|
210
211
|
cursor: "pointer",
|
|
211
|
-
|
|
212
|
+
"&:enabled:hover": { background: "bg.hover" },
|
|
212
213
|
_focusVisible: { focusRing: "inset" },
|
|
214
|
+
_disabled: { opacity: "disabled", cursor: "not-allowed" },
|
|
213
215
|
"&:last-child": { borderBottomLeftRadius: "field", borderBottomRightRadius: "field" },
|
|
214
216
|
"& > span": { display: "block", color: "fg.muted", fontSize: "code" },
|
|
215
217
|
},
|
|
@@ -217,8 +219,20 @@ const optionList = css({
|
|
|
217
219
|
/** The agent asking: a waiting task's question, its details, and Deny / Approve or the answers. */
|
|
218
220
|
export function AgentTaskCard({ task, onReply }) {
|
|
219
221
|
const { labels } = useCiridaeLocale();
|
|
222
|
+
const [replyState, setReplyState] = useState({ kind: "unanswered" });
|
|
220
223
|
const { ask } = task;
|
|
221
224
|
if (!ask)
|
|
222
225
|
return null;
|
|
223
|
-
|
|
226
|
+
const sendReply = (reply) => {
|
|
227
|
+
setReplyState({ kind: "sending", reply });
|
|
228
|
+
onReply(task, reply).catch((error) => setReplyState({
|
|
229
|
+
kind: "failed",
|
|
230
|
+
message: error instanceof Error ? error.message : String(error),
|
|
231
|
+
}));
|
|
232
|
+
};
|
|
233
|
+
const sending = replyState.kind === "sending";
|
|
234
|
+
const sendingDecision = (decision) => replyState.kind === "sending" &&
|
|
235
|
+
replyState.reply.kind === "decision" &&
|
|
236
|
+
replyState.reply.decision === decision;
|
|
237
|
+
return (_jsxs("div", { id: agentTaskAnchorId(task.id), className: askCard, tabIndex: -1, "data-ciridae-ui": "", children: [_jsx("span", { children: ask.text }), ask.kind === "approval" && ask.details && ask.details.length > 0 && (_jsx("dl", { className: detailList, children: ask.details.map((detail) => (_jsxs(Fragment, { children: [_jsx("dt", { children: detail.label }), _jsx("dd", { children: detail.value })] }, detail.label))) })), replyState.kind === "failed" && (_jsx("span", { className: replyError, role: "alert", children: replyState.message })), ask.kind === "approval" ? (_jsxs("div", { className: cardActions, children: [_jsx(Button, { variant: "secondary", disabled: sending, loading: sendingDecision("deny"), onClick: () => sendReply({ kind: "decision", decision: "deny" }), children: labels.chat.deny }), _jsx(Button, { disabled: sending, loading: sendingDecision("allow"), onClick: () => sendReply({ kind: "decision", decision: "allow" }), children: labels.chat.approve })] })) : (_jsx("div", { className: optionList, children: ask.options.map((option) => (_jsxs("button", { type: "button", disabled: sending, onClick: () => sendReply({ kind: "answer", answer: option.label }), children: [option.label, option.description && _jsx("span", { children: option.description })] }, option.label))) }))] }));
|
|
224
238
|
}
|
|
@@ -1,26 +1,15 @@
|
|
|
1
|
-
import { type PaletteName } from "../theme/index.js";
|
|
2
1
|
import { type AppNavigationProps } from "./app-navigation.js";
|
|
3
2
|
import { type HotkeyChord } from "./hotkeys.js";
|
|
4
3
|
import { type MenuItem } from "./menu.js";
|
|
5
4
|
import type { ComponentProps, ReactNode } from "react";
|
|
6
|
-
/** The palette the reader shows, which the host keeps, such as in storage, for `ThemeProvider`. */
|
|
7
|
-
export type PaletteChoice = {
|
|
8
|
-
/** `undefined` is the stylesheet's own palette, `ciridae`. */
|
|
9
|
-
value: PaletteName | undefined;
|
|
10
|
-
onValueChange: (palette: PaletteName) => void;
|
|
11
|
-
};
|
|
12
5
|
/** The color theme submenu: system, light or dark. */
|
|
13
6
|
export declare function useColorThemeMenuItem(): MenuItem;
|
|
14
|
-
/** The palette submenu over the kit's palettes. */
|
|
15
|
-
export declare function usePaletteMenuItem(choice: PaletteChoice): MenuItem;
|
|
16
7
|
export type AccountMenuProps = {
|
|
17
8
|
avatar: ReactNode;
|
|
18
9
|
name: string;
|
|
19
10
|
detail?: ReactNode;
|
|
20
11
|
/** The app's own entries, such as Edit profile, above the color theme. */
|
|
21
12
|
items?: readonly MenuItem[];
|
|
22
|
-
/** Adds a palette submenu after the color theme. */
|
|
23
|
-
palette?: PaletteChoice;
|
|
24
13
|
/** The last entry, in the danger color. */
|
|
25
14
|
signOut?: {
|
|
26
15
|
onSelect: () => void;
|
|
@@ -30,18 +19,15 @@ export type AccountMenuProps = {
|
|
|
30
19
|
/** The avatar alone, for the rail and the phone header. */
|
|
31
20
|
compact?: boolean;
|
|
32
21
|
};
|
|
33
|
-
|
|
34
|
-
export declare function AccountMenu({ avatar, name, detail, items, palette, signOut, compact, }: AccountMenuProps): import("react").JSX.Element;
|
|
22
|
+
export declare function AccountMenu({ avatar, name, detail, items, signOut, compact, }: AccountMenuProps): import("react").JSX.Element;
|
|
35
23
|
export type AssistantLauncherProps = Omit<ComponentProps<"button">, "children"> & {
|
|
36
|
-
/**
|
|
24
|
+
/** The rail's button is named by it. */
|
|
37
25
|
label: string;
|
|
38
26
|
icon: ReactNode;
|
|
39
|
-
/** The
|
|
27
|
+
/** The host binds it. */
|
|
40
28
|
hotkey?: HotkeyChord;
|
|
41
|
-
/** The icon alone, round, for the rail. */
|
|
42
29
|
compact?: boolean;
|
|
43
30
|
};
|
|
44
|
-
/** Opens the app's assistant from the sidebar's foot: a raised pill, or a round icon in the rail. */
|
|
45
31
|
export declare function AssistantLauncher({ label, icon: launcherIcon, hotkey, compact, className, ...props }: AssistantLauncherProps): import("react").JSX.Element;
|
|
46
32
|
/** A footer control drawn for every width: a sidebar row, a rail icon and a phone-header icon. */
|
|
47
33
|
export type AppFrameItem = {
|
|
@@ -3,12 +3,11 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
3
3
|
* The app's frame, composed from the shell's pieces: the sidebar that folds to a rail and then
|
|
4
4
|
* into the phone menu, its footer rows and account menu drawn for each width, and, given a
|
|
5
5
|
* `title`, the main panel's header too. `AccountMenu` is the signed-in account's menu: the app's
|
|
6
|
-
* own entries, the color theme
|
|
6
|
+
* own entries, the color theme, and sign out. Auth stays with the host, which passes
|
|
7
7
|
* sign-out as an action. `AssistantLauncher` opens the app's assistant from the sidebar's foot.
|
|
8
8
|
*/
|
|
9
|
-
import { ArrowClockwiseIcon, CaretUpIcon, CircleHalfIcon,
|
|
9
|
+
import { ArrowClockwiseIcon, CaretUpIcon, CircleHalfIcon, PulseIcon, SignOutIcon, } from "@phosphor-icons/react";
|
|
10
10
|
import { css, cx } from "#primitives/css";
|
|
11
|
-
import { PALETTE_NAMES } from "../theme/index.js";
|
|
12
11
|
import { AppNavigation } from "./app-navigation.js";
|
|
13
12
|
import { Button, IconButton } from "./button.js";
|
|
14
13
|
import { useColorTheme } from "./color-theme.js";
|
|
@@ -18,6 +17,7 @@ import { ShortcutHint } from "./keycap.js";
|
|
|
18
17
|
import { Link } from "./link.js";
|
|
19
18
|
import { useCiridaeLocale } from "./locale.js";
|
|
20
19
|
import { Menu } from "./menu.js";
|
|
20
|
+
import { Tooltip } from "./overlays.js";
|
|
21
21
|
import { AppAccountButton, AppBreadcrumbs, AppContent, AppHeader, AppHeaderActions, AppHeaderCompact, AppMain, AppShell, AppSidebar, AppSidebarFooter, AppSidebarFootnote, AppSidebarGroup, AppSidebarNav, AppSidebarOnly, AppSidebarRail, } from "./shell.js";
|
|
22
22
|
import { SidebarItem } from "./sidebar.js";
|
|
23
23
|
import { useNewVersionAvailable } from "./use-new-version-available.js";
|
|
@@ -40,24 +40,7 @@ export function useColorThemeMenuItem() {
|
|
|
40
40
|
})),
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
|
-
|
|
44
|
-
export function usePaletteMenuItem(choice) {
|
|
45
|
-
return paletteMenuItem(choice, useCiridaeLocale().labels);
|
|
46
|
-
}
|
|
47
|
-
function paletteMenuItem({ value, onValueChange }, labels) {
|
|
48
|
-
const selected = value ?? "ciridae";
|
|
49
|
-
return {
|
|
50
|
-
label: labels.themeCustomizer.palette,
|
|
51
|
-
icon: _jsx(PaletteIcon, { className: icon({ size: "small" }) }),
|
|
52
|
-
items: PALETTE_NAMES.map((name) => ({
|
|
53
|
-
label: labels.themeCustomizer.paletteName(name),
|
|
54
|
-
checked: selected === name,
|
|
55
|
-
onSelect: () => onValueChange(name),
|
|
56
|
-
})),
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
/** The signed-in account's menu: the app's entries, the color theme and palette, then sign out. */
|
|
60
|
-
export function AccountMenu({ avatar, name, detail, items = [], palette, signOut, compact = false, }) {
|
|
43
|
+
export function AccountMenu({ avatar, name, detail, items = [], signOut, compact = false, }) {
|
|
61
44
|
const { labels } = useCiridaeLocale();
|
|
62
45
|
const colorThemeItem = useColorThemeMenuItem();
|
|
63
46
|
return (_jsx(Menu
|
|
@@ -66,10 +49,9 @@ export function AccountMenu({ avatar, name, detail, items = [], palette, signOut
|
|
|
66
49
|
, {
|
|
67
50
|
// In the sidebar the menu is as wide as the account row it opens from, as the design draws
|
|
68
51
|
// it, so it covers whatever sits above that row; the avatar alone opens a menu of its own width.
|
|
69
|
-
matchTriggerWidth: !compact, trigger: _jsx(AppAccountButton, { "aria-label": labels.accountMenu.menu, avatar: avatar, compact: compact, detail: detail, name: name, trailing: _jsx(CaretUpIcon, { className: icon({ size: "small" }) }) }), items: [
|
|
52
|
+
matchTriggerWidth: !compact, triggerTooltip: compact ? labels.accountMenu.menu : undefined, trigger: _jsx(AppAccountButton, { "aria-label": labels.accountMenu.menu, avatar: avatar, compact: compact, detail: detail, name: name, trailing: _jsx(CaretUpIcon, { className: icon({ size: "small" }) }) }), items: [
|
|
70
53
|
...items,
|
|
71
54
|
colorThemeItem,
|
|
72
|
-
...(palette ? [paletteMenuItem(palette, labels)] : []),
|
|
73
55
|
...(signOut
|
|
74
56
|
? [
|
|
75
57
|
{ separator: true },
|
|
@@ -83,18 +65,17 @@ export function AccountMenu({ avatar, name, detail, items = [], palette, signOut
|
|
|
83
65
|
: []),
|
|
84
66
|
] }));
|
|
85
67
|
}
|
|
86
|
-
// A raised pill on the canvas; in the rail, a round button with the same face.
|
|
87
68
|
const assistantLauncher = css({
|
|
88
69
|
display: "flex",
|
|
89
70
|
alignItems: "center",
|
|
90
71
|
gap: "control.iconGap",
|
|
91
|
-
width: "
|
|
72
|
+
width: "full",
|
|
92
73
|
height: "control.default",
|
|
93
74
|
paddingInlineStart: "control.compactInline",
|
|
94
75
|
paddingInlineEnd: "control.launcherInlineEnd",
|
|
95
76
|
border: "1px solid token(colors.border.canvas)",
|
|
96
77
|
borderRadius: "shell",
|
|
97
|
-
background: "token(gradients.raised)",
|
|
78
|
+
background: "[token(gradients.raised)]",
|
|
98
79
|
color: "fg.primary",
|
|
99
80
|
font: "inherit",
|
|
100
81
|
fontWeight: "medium",
|
|
@@ -113,15 +94,15 @@ const assistantLauncher = css({
|
|
|
113
94
|
borderRadius: "round",
|
|
114
95
|
},
|
|
115
96
|
});
|
|
116
|
-
/** Opens the app's assistant from the sidebar's foot: a raised pill, or a round icon in the rail. */
|
|
117
97
|
export function AssistantLauncher({ label, icon: launcherIcon, hotkey, compact = false, className, ...props }) {
|
|
118
|
-
|
|
98
|
+
const launcher = (_jsxs("button", { type: "button", "aria-label": compact ? label : undefined, ...props, className: cx(assistantLauncher, className), "data-ciridae-ui": "", "data-compact": compact || undefined, children: [launcherIcon, !compact && (_jsxs(_Fragment, { children: [_jsx("span", { "data-label": "", children: label }), hotkey && _jsx(ShortcutHint, { boxed: true, hotkey: hotkey })] }))] }));
|
|
99
|
+
return compact ? (_jsx(Tooltip, { content: label, side: "inline-end", children: launcher })) : (launcher);
|
|
119
100
|
}
|
|
120
101
|
/** The app's frame: the sidebar for every width, its footer and account, and the page. */
|
|
121
102
|
export function AppFrame({ title, actions, sidebarTop, sidebarRail, navigation, sidebar, sidebarFooter, items = [], footnote, buildSha = null, statusUrl, railActions, compactActions, account, overlays, children, }) {
|
|
122
103
|
const { labels } = useCiridaeLocale();
|
|
123
|
-
const statusLink = statusUrl
|
|
124
|
-
const sidebarFoot = (_jsxs(_Fragment, { children: [(sidebarFooter || buildSha !== null || items.length > 0) && (_jsxs(AppSidebarOnly, { children: [sidebarFooter, buildSha !== null && _jsx(BuildUpdateButton, { buildSha: buildSha }), items.map((item) => (_jsx(SidebarItem, { "aria-pressed": item.pressed, icon: item.icon, onClick: item.onClick, children: item.label }, item.id)))] })), _jsxs(AppSidebarFootnote, { children: [footnote, statusUrl && (_jsxs(_Fragment, { children: [_jsx(Link, { external: true, tone: "muted", href: statusUrl, children: labels.appFrame.status }), _jsx("span", { "aria-hidden": "true", children: "\u00B7" })] })), _jsx("code", { title: buildSha ?? undefined, children: buildSha ? buildSha.slice(0, 7) : labels.appFrame.localBuild })] }), (railActions || statusLink || items.length > 0) && (_jsxs(AppSidebarOnly, { rail: true, children: [items.map((item) => (_jsx(SidebarItem, { "aria-label": item.label, "aria-pressed": item.pressed, icon: item.icon, onClick: item.onClick }, item.id))), railActions, statusLink] })), account && (_jsxs(_Fragment, { children: [_jsx(AppSidebarOnly, { children: _jsx(AccountMenu, { ...account }) }), _jsx(AppSidebarOnly, { rail: true, children: _jsx(AccountMenu, { ...account, compact: true }) })] }))] }));
|
|
104
|
+
const statusLink = statusUrl ? (_jsx(IconButton, { "aria-label": labels.appFrame.status, nativeButton: false, render: _jsx("a", { href: statusUrl, target: "_blank", rel: "noreferrer" }), children: _jsx(PulseIcon, { className: icon() }) })) : undefined;
|
|
105
|
+
const sidebarFoot = (_jsxs(_Fragment, { children: [(sidebarFooter || buildSha !== null || items.length > 0) && (_jsxs(AppSidebarOnly, { children: [sidebarFooter, buildSha !== null && _jsx(BuildUpdateButton, { buildSha: buildSha }), items.map((item) => (_jsx(SidebarItem, { "aria-pressed": item.pressed, icon: item.icon, onClick: item.onClick, children: item.label }, item.id)))] })), _jsxs(AppSidebarFootnote, { children: [footnote, statusUrl && (_jsxs(_Fragment, { children: [_jsx(Link, { external: true, tone: "muted", href: statusUrl, children: labels.appFrame.status }), _jsx("span", { "aria-hidden": "true", children: "\u00B7" })] })), _jsx("code", { title: buildSha ?? undefined, children: buildSha ? buildSha.slice(0, 7) : labels.appFrame.localBuild })] }), (railActions || statusLink || items.length > 0) && (_jsxs(AppSidebarOnly, { rail: true, children: [items.map((item) => (_jsx(Tooltip, { content: item.label, side: "inline-end", children: _jsx(SidebarItem, { "aria-label": item.label, "aria-pressed": item.pressed, icon: item.icon, onClick: item.onClick }) }, item.id))), railActions, statusLink && (_jsx(Tooltip, { content: labels.appFrame.status, side: "inline-end", children: statusLink }))] })), account && (_jsxs(_Fragment, { children: [_jsx(AppSidebarOnly, { children: _jsx(AccountMenu, { ...account }) }), _jsx(AppSidebarOnly, { rail: true, children: _jsx(AccountMenu, { ...account, compact: true }) })] }))] }));
|
|
125
106
|
return (_jsxs(AppShell, { children: [_jsx(KeyboardShortcuts, {}), navigation ? (_jsx(AppNavigation, { ...navigation, header: sidebarTop, railHeader: sidebarRail, footer: sidebarFoot })) : (_jsxs(AppSidebar, { children: [_jsx(AppSidebarGroup, { children: sidebarTop }), _jsx(AppSidebarRail, { children: sidebarRail }), sidebar && _jsx(AppSidebarNav, { children: sidebar }), _jsx(AppSidebarFooter, { children: sidebarFoot })] })), title === undefined ? (children) : (_jsxs(AppMain, { children: [_jsx(AppHeader, { actions: _jsxs(AppHeaderActions, { children: [actions, _jsxs(AppHeaderCompact, { children: [compactActions, statusLink, items.map((item) => (_jsx(IconButton, { "aria-label": item.label, "aria-pressed": item.pressed, onClick: item.onClick, children: item.icon }, item.id))), account && _jsx(AccountMenu, { ...account, compact: true })] })] }), children: _jsx(AppBreadcrumbs, { children: title }) }), _jsx(AppContent, { children: children })] })), overlays] }));
|
|
126
107
|
}
|
|
127
108
|
/** Only mounted for a named build, so local previews do not need a query provider. */
|
|
@@ -58,11 +58,12 @@ export type AppNavigationProps = Omit<ComponentProps<"aside">, "children"> & {
|
|
|
58
58
|
}>;
|
|
59
59
|
};
|
|
60
60
|
/**
|
|
61
|
-
* Whether the sidebar has room to
|
|
62
|
-
*
|
|
63
|
-
* out of room, so it does not flicker at the
|
|
61
|
+
* Whether the sidebar has room to unfold every section: the free space between its navigation and
|
|
62
|
+
* its footer covers the `hiddenRows` its folds hide, less the More rows unfolding removes. Once it
|
|
63
|
+
* has, it loses it only when the navigation runs out of room, so it does not flicker at the
|
|
64
|
+
* threshold.
|
|
64
65
|
*/
|
|
65
|
-
export declare function useSidebarRoom(
|
|
66
|
+
export declare function useSidebarRoom(hiddenRows: number): {
|
|
66
67
|
navRef: import("react").RefObject<HTMLDivElement | null>;
|
|
67
68
|
footerRef: import("react").RefObject<HTMLDivElement | null>;
|
|
68
69
|
roomy: boolean;
|
|
@@ -80,7 +81,6 @@ export type WorkspaceMarkProps = {
|
|
|
80
81
|
size?: "regular" | "small";
|
|
81
82
|
className?: string;
|
|
82
83
|
};
|
|
83
|
-
/** A workspace's mark: its name's first letter on a square tile. */
|
|
84
84
|
export declare function WorkspaceMark({ name, current, size, className, }: WorkspaceMarkProps): import("react").JSX.Element;
|
|
85
85
|
export type WorkspaceSwitcherProps = {
|
|
86
86
|
workspaces: readonly Workspace[];
|
|
@@ -89,5 +89,4 @@ export type WorkspaceSwitcherProps = {
|
|
|
89
89
|
/** The mark alone, for the rail. */
|
|
90
90
|
compact?: boolean;
|
|
91
91
|
};
|
|
92
|
-
/** The current workspace, opening a menu of every workspace the reader belongs to, current checked. */
|
|
93
92
|
export declare function WorkspaceSwitcher({ workspaces, currentId, onSelect, compact, }: WorkspaceSwitcherProps): import("react").JSX.Element;
|