@agent-native/toolkit 0.9.1 → 0.10.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/agent-native.eject.json +71 -0
- package/dist/chat-history/ChatHistoryRail.d.ts +15 -1
- package/dist/chat-history/ChatHistoryRail.d.ts.map +1 -1
- package/dist/chat-history/ChatHistoryRail.js +26 -13
- package/dist/chat-history/ChatHistoryRail.js.map +1 -1
- package/dist/chat-history/ChatHistoryRail.spec.js +77 -1
- package/dist/chat-history/ChatHistoryRail.spec.js.map +1 -1
- package/dist/chat-history/index.d.ts +2 -1
- package/dist/chat-history/index.d.ts.map +1 -1
- package/dist/chat-history/index.js +2 -1
- package/dist/chat-history/index.js.map +1 -1
- package/dist/chat-history/useChatHistoryRailController.d.ts +26 -0
- package/dist/chat-history/useChatHistoryRailController.d.ts.map +1 -0
- package/dist/chat-history/useChatHistoryRailController.js +36 -0
- package/dist/chat-history/useChatHistoryRailController.js.map +1 -0
- package/dist/chat-history/useChatHistoryRailController.spec.d.ts +2 -0
- package/dist/chat-history/useChatHistoryRailController.spec.d.ts.map +1 -0
- package/dist/chat-history/useChatHistoryRailController.spec.js +101 -0
- package/dist/chat-history/useChatHistoryRailController.spec.js.map +1 -0
- package/dist/chat-history.css +2 -0
- package/dist/composer/ComposerPlusMenu.js +1 -1
- package/dist/composer/ComposerPlusMenu.js.map +1 -1
- package/dist/composer/PromptComposer.d.ts +1 -0
- package/dist/composer/PromptComposer.d.ts.map +1 -1
- package/dist/composer/PromptComposer.js +26 -5
- package/dist/composer/PromptComposer.js.map +1 -1
- package/dist/composer/PromptComposer.spec.js +8 -1
- package/dist/composer/PromptComposer.spec.js.map +1 -1
- package/dist/composer/RealtimeVoiceMode.d.ts.map +1 -1
- package/dist/composer/RealtimeVoiceMode.js +56 -11
- package/dist/composer/RealtimeVoiceMode.js.map +1 -1
- package/dist/composer/RealtimeVoiceMode.spec.js +59 -7
- package/dist/composer/RealtimeVoiceMode.spec.js.map +1 -1
- package/dist/composer/useRealtimeVoiceMode.d.ts +7 -0
- package/dist/composer/useRealtimeVoiceMode.d.ts.map +1 -1
- package/dist/composer/useRealtimeVoiceMode.js +110 -6
- package/dist/composer/useRealtimeVoiceMode.js.map +1 -1
- package/dist/composer/useRealtimeVoiceMode.spec.js +74 -2
- package/dist/composer/useRealtimeVoiceMode.spec.js.map +1 -1
- package/dist/conformance/__fixtures__/css-in-js-adapter.d.ts +7 -0
- package/dist/conformance/__fixtures__/css-in-js-adapter.d.ts.map +1 -0
- package/dist/conformance/__fixtures__/css-in-js-adapter.js +84 -0
- package/dist/conformance/__fixtures__/css-in-js-adapter.js.map +1 -0
- package/dist/conformance/conformance.spec.d.ts +2 -0
- package/dist/conformance/conformance.spec.d.ts.map +1 -0
- package/dist/conformance/conformance.spec.js +87 -0
- package/dist/conformance/conformance.spec.js.map +1 -0
- package/dist/conformance/index.d.ts +4 -0
- package/dist/conformance/index.d.ts.map +1 -0
- package/dist/conformance/index.js +4 -0
- package/dist/conformance/index.js.map +1 -0
- package/dist/conformance/runner.d.ts +12 -0
- package/dist/conformance/runner.d.ts.map +1 -0
- package/dist/conformance/runner.js +515 -0
- package/dist/conformance/runner.js.map +1 -0
- package/dist/conformance/types.d.ts +26 -0
- package/dist/conformance/types.d.ts.map +1 -0
- package/dist/conformance/types.js +13 -0
- package/dist/conformance/types.js.map +1 -0
- package/dist/conformance/version.d.ts +6 -0
- package/dist/conformance/version.d.ts.map +1 -0
- package/dist/conformance/version.js +14 -0
- package/dist/conformance/version.js.map +1 -0
- package/dist/design-system/components.d.ts +64 -0
- package/dist/design-system/components.d.ts.map +1 -0
- package/dist/design-system/components.js +50 -0
- package/dist/design-system/components.js.map +1 -0
- package/dist/design-system/context.d.ts +11 -0
- package/dist/design-system/context.d.ts.map +1 -0
- package/dist/design-system/context.js +17 -0
- package/dist/design-system/context.js.map +1 -0
- package/dist/design-system/default-adapter.d.ts +3 -0
- package/dist/design-system/default-adapter.d.ts.map +1 -0
- package/dist/design-system/default-adapter.js +166 -0
- package/dist/design-system/default-adapter.js.map +1 -0
- package/dist/design-system/default-adapter.spec.d.ts +2 -0
- package/dist/design-system/default-adapter.spec.d.ts.map +1 -0
- package/dist/design-system/default-adapter.spec.js +96 -0
- package/dist/design-system/default-adapter.spec.js.map +1 -0
- package/dist/design-system/definition.d.ts +9 -0
- package/dist/design-system/definition.d.ts.map +1 -0
- package/dist/design-system/definition.js +4 -0
- package/dist/design-system/definition.js.map +1 -0
- package/dist/design-system/design-system.spec.d.ts +2 -0
- package/dist/design-system/design-system.spec.d.ts.map +1 -0
- package/dist/design-system/design-system.spec.js +121 -0
- package/dist/design-system/design-system.spec.js.map +1 -0
- package/dist/design-system/error-boundary.d.ts +18 -0
- package/dist/design-system/error-boundary.d.ts.map +1 -0
- package/dist/design-system/error-boundary.js +16 -0
- package/dist/design-system/error-boundary.js.map +1 -0
- package/dist/design-system/index.d.ts +8 -0
- package/dist/design-system/index.d.ts.map +1 -0
- package/dist/design-system/index.js +8 -0
- package/dist/design-system/index.js.map +1 -0
- package/dist/design-system/theme.d.ts +30 -0
- package/dist/design-system/theme.d.ts.map +1 -0
- package/dist/design-system/theme.js +95 -0
- package/dist/design-system/theme.js.map +1 -0
- package/dist/design-system/theme.spec.d.ts +2 -0
- package/dist/design-system/theme.spec.d.ts.map +1 -0
- package/dist/design-system/theme.spec.js +43 -0
- package/dist/design-system/theme.spec.js.map +1 -0
- package/dist/design-system/types.d.ts +288 -0
- package/dist/design-system/types.d.ts.map +1 -0
- package/dist/design-system/types.js +2 -0
- package/dist/design-system/types.js.map +1 -0
- package/dist/editor/SharedRichEditor.d.ts.map +1 -1
- package/dist/editor/SharedRichEditor.js +3 -2
- package/dist/editor/SharedRichEditor.js.map +1 -1
- package/dist/editor/SlashCommandMenu.d.ts +8 -0
- package/dist/editor/SlashCommandMenu.d.ts.map +1 -1
- package/dist/editor/SlashCommandMenu.js +6 -0
- package/dist/editor/SlashCommandMenu.js.map +1 -1
- package/dist/editor/SlashCommandMenu.spec.d.ts +2 -0
- package/dist/editor/SlashCommandMenu.spec.d.ts.map +1 -0
- package/dist/editor/SlashCommandMenu.spec.js +20 -0
- package/dist/editor/SlashCommandMenu.spec.js.map +1 -0
- package/dist/editor/index.d.ts +1 -1
- package/dist/editor/index.d.ts.map +1 -1
- package/dist/editor/index.js +1 -1
- package/dist/editor/index.js.map +1 -1
- package/dist/provider.d.ts +4 -3
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +46 -4
- package/dist/provider.js.map +1 -1
- package/dist/styles.css +52 -23
- package/dist/ui/button.d.ts +5 -0
- package/dist/ui/button.d.ts.map +1 -1
- package/dist/ui/button.js +25 -4
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/dialog.d.ts +4 -0
- package/dist/ui/dialog.d.ts.map +1 -1
- package/dist/ui/dialog.js +2 -2
- package/dist/ui/dialog.js.map +1 -1
- package/dist/ui/popover.d.ts +1 -0
- package/dist/ui/popover.d.ts.map +1 -1
- package/dist/ui/popover.js +2 -2
- package/dist/ui/popover.js.map +1 -1
- package/dist/ui/select.d.ts +3 -1
- package/dist/ui/select.d.ts.map +1 -1
- package/dist/ui/select.js +1 -1
- package/dist/ui/select.js.map +1 -1
- package/dist/ui/sidebar.d.ts +6 -2
- package/dist/ui/sidebar.d.ts.map +1 -1
- package/dist/ui/sidebar.js +12 -15
- package/dist/ui/sidebar.js.map +1 -1
- package/dist/ui/tooltip.d.ts +3 -1
- package/dist/ui/tooltip.d.ts.map +1 -1
- package/dist/ui/tooltip.js +2 -2
- package/dist/ui/tooltip.js.map +1 -1
- package/package.json +31 -1
- package/src/chat-history/ChatHistoryRail.spec.tsx +174 -0
- package/src/chat-history/ChatHistoryRail.tsx +100 -39
- package/src/chat-history/index.ts +9 -0
- package/src/chat-history/useChatHistoryRailController.spec.tsx +131 -0
- package/src/chat-history/useChatHistoryRailController.ts +76 -0
- package/src/chat-history.css +2 -0
- package/src/composer/ComposerPlusMenu.tsx +11 -8
- package/src/composer/PromptComposer.spec.ts +12 -1
- package/src/composer/PromptComposer.tsx +32 -7
- package/src/composer/RealtimeVoiceMode.spec.tsx +117 -9
- package/src/composer/RealtimeVoiceMode.tsx +119 -31
- package/src/composer/useRealtimeVoiceMode.spec.ts +101 -1
- package/src/composer/useRealtimeVoiceMode.tsx +124 -9
- package/src/conformance/__fixtures__/css-in-js-adapter.tsx +401 -0
- package/src/conformance/conformance.spec.tsx +143 -0
- package/src/conformance/index.ts +3 -0
- package/src/conformance/runner.tsx +862 -0
- package/src/conformance/types.ts +45 -0
- package/src/conformance/version.ts +22 -0
- package/src/design-system/components.tsx +146 -0
- package/src/design-system/context.tsx +31 -0
- package/src/design-system/default-adapter.spec.tsx +143 -0
- package/src/design-system/default-adapter.tsx +915 -0
- package/src/design-system/definition.ts +14 -0
- package/src/design-system/design-system.spec.tsx +183 -0
- package/src/design-system/error-boundary.tsx +37 -0
- package/src/design-system/index.ts +7 -0
- package/src/design-system/theme.spec.ts +61 -0
- package/src/design-system/theme.ts +145 -0
- package/src/design-system/types.ts +363 -0
- package/src/editor/SharedRichEditor.tsx +13 -2
- package/src/editor/SlashCommandMenu.spec.ts +33 -0
- package/src/editor/SlashCommandMenu.tsx +20 -0
- package/src/editor/index.ts +2 -0
- package/src/provider.tsx +98 -5
- package/src/styles.css +52 -23
- package/src/ui/button.tsx +95 -6
- package/src/ui/dialog.tsx +48 -23
- package/src/ui/popover.tsx +16 -2
- package/src/ui/select.tsx +7 -3
- package/src/ui/sidebar.tsx +47 -48
- package/src/ui/tooltip.tsx +7 -3
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ComponentType,
|
|
3
|
+
CSSProperties,
|
|
4
|
+
KeyboardEvent as ReactKeyboardEvent,
|
|
5
|
+
MouseEvent as ReactMouseEvent,
|
|
6
|
+
ReactElement,
|
|
7
|
+
ReactNode,
|
|
8
|
+
Ref,
|
|
9
|
+
RefObject,
|
|
10
|
+
} from "react";
|
|
11
|
+
|
|
12
|
+
export const DESIGN_SYSTEM_CONTRACT_VERSION = 1 as const;
|
|
13
|
+
|
|
14
|
+
export type DesignSystemIntent = "primary" | "neutral" | "danger";
|
|
15
|
+
export type DesignSystemEmphasis = "solid" | "outline" | "ghost";
|
|
16
|
+
export type DesignSystemSize = "compact" | "default" | "large";
|
|
17
|
+
export type DesignSystemTone =
|
|
18
|
+
| "neutral"
|
|
19
|
+
| "info"
|
|
20
|
+
| "success"
|
|
21
|
+
| "warning"
|
|
22
|
+
| "danger";
|
|
23
|
+
export type DesignSystemPlacement = "top" | "right" | "bottom" | "left";
|
|
24
|
+
export type DesignSystemAlign = "start" | "center" | "end";
|
|
25
|
+
export type DesignSystemKey = string | number;
|
|
26
|
+
export type DesignSystemPressEvent =
|
|
27
|
+
| ReactMouseEvent<HTMLElement>
|
|
28
|
+
| ReactKeyboardEvent<HTMLElement>;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Styling hooks are optional interoperability affordances. Adapters must not
|
|
32
|
+
* rely on either hook being present, and Toolkit views must not pass
|
|
33
|
+
* framework-specific utility classes through this contract.
|
|
34
|
+
*/
|
|
35
|
+
export interface DesignSystemStyleProps {
|
|
36
|
+
className?: string;
|
|
37
|
+
style?: CSSProperties;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface DesignSystemAccessibleProps {
|
|
41
|
+
id?: string;
|
|
42
|
+
title?: string;
|
|
43
|
+
"aria-label"?: string;
|
|
44
|
+
"aria-labelledby"?: string;
|
|
45
|
+
"aria-describedby"?: string;
|
|
46
|
+
"aria-controls"?: string;
|
|
47
|
+
"aria-expanded"?: boolean;
|
|
48
|
+
"aria-haspopup"?: boolean | "dialog" | "grid" | "listbox" | "menu" | "tree";
|
|
49
|
+
"aria-pressed"?: boolean | "mixed";
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface DesignSystemOverlayProps extends DesignSystemStyleProps {
|
|
53
|
+
portalContainer?: Element | null;
|
|
54
|
+
placement?: DesignSystemPlacement;
|
|
55
|
+
align?: DesignSystemAlign;
|
|
56
|
+
collisionPadding?: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface ActionButtonProps
|
|
60
|
+
extends DesignSystemStyleProps, DesignSystemAccessibleProps {
|
|
61
|
+
children?: ReactNode;
|
|
62
|
+
intent?: DesignSystemIntent;
|
|
63
|
+
emphasis?: DesignSystemEmphasis;
|
|
64
|
+
size?: DesignSystemSize;
|
|
65
|
+
pending?: boolean;
|
|
66
|
+
disabled?: boolean;
|
|
67
|
+
type?: "button" | "submit" | "reset";
|
|
68
|
+
leadingIcon?: ReactNode;
|
|
69
|
+
trailingIcon?: ReactNode;
|
|
70
|
+
onPress?: (event?: DesignSystemPressEvent) => void;
|
|
71
|
+
elementRef?: Ref<HTMLButtonElement>;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface IconButtonProps
|
|
75
|
+
extends DesignSystemStyleProps, DesignSystemAccessibleProps {
|
|
76
|
+
label: string;
|
|
77
|
+
icon: ReactNode;
|
|
78
|
+
intent?: DesignSystemIntent;
|
|
79
|
+
emphasis?: DesignSystemEmphasis;
|
|
80
|
+
size?: DesignSystemSize;
|
|
81
|
+
pending?: boolean;
|
|
82
|
+
disabled?: boolean;
|
|
83
|
+
type?: "button" | "submit" | "reset";
|
|
84
|
+
onPress?: (event?: DesignSystemPressEvent) => void;
|
|
85
|
+
elementRef?: Ref<HTMLButtonElement>;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export type DesignSystemTextInputType =
|
|
89
|
+
| "text"
|
|
90
|
+
| "email"
|
|
91
|
+
| "password"
|
|
92
|
+
| "search"
|
|
93
|
+
| "tel"
|
|
94
|
+
| "url";
|
|
95
|
+
|
|
96
|
+
export interface TextFieldProps
|
|
97
|
+
extends DesignSystemStyleProps, DesignSystemAccessibleProps {
|
|
98
|
+
value: string;
|
|
99
|
+
onChange: (value: string) => void;
|
|
100
|
+
label?: ReactNode;
|
|
101
|
+
description?: ReactNode;
|
|
102
|
+
errorMessage?: ReactNode;
|
|
103
|
+
placeholder?: string;
|
|
104
|
+
/** Optional native datalist id for editable fields with suggestions. */
|
|
105
|
+
list?: string;
|
|
106
|
+
name?: string;
|
|
107
|
+
type?: DesignSystemTextInputType;
|
|
108
|
+
inputMode?:
|
|
109
|
+
| "none"
|
|
110
|
+
| "text"
|
|
111
|
+
| "tel"
|
|
112
|
+
| "url"
|
|
113
|
+
| "email"
|
|
114
|
+
| "numeric"
|
|
115
|
+
| "decimal"
|
|
116
|
+
| "search";
|
|
117
|
+
autoComplete?: string;
|
|
118
|
+
autoFocus?: boolean;
|
|
119
|
+
required?: boolean;
|
|
120
|
+
readOnly?: boolean;
|
|
121
|
+
disabled?: boolean;
|
|
122
|
+
invalid?: boolean;
|
|
123
|
+
leadingContent?: ReactNode;
|
|
124
|
+
trailingContent?: ReactNode;
|
|
125
|
+
onBlur?: () => void;
|
|
126
|
+
onFocus?: () => void;
|
|
127
|
+
onKeyDown?: (event: ReactKeyboardEvent<HTMLElement>) => void;
|
|
128
|
+
inputRef?: Ref<HTMLInputElement>;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface TextAreaProps
|
|
132
|
+
extends DesignSystemStyleProps, DesignSystemAccessibleProps {
|
|
133
|
+
value: string;
|
|
134
|
+
onChange: (value: string) => void;
|
|
135
|
+
label?: ReactNode;
|
|
136
|
+
description?: ReactNode;
|
|
137
|
+
errorMessage?: ReactNode;
|
|
138
|
+
placeholder?: string;
|
|
139
|
+
name?: string;
|
|
140
|
+
rows?: number;
|
|
141
|
+
maxLength?: number;
|
|
142
|
+
autoFocus?: boolean;
|
|
143
|
+
required?: boolean;
|
|
144
|
+
readOnly?: boolean;
|
|
145
|
+
disabled?: boolean;
|
|
146
|
+
invalid?: boolean;
|
|
147
|
+
onBlur?: () => void;
|
|
148
|
+
onFocus?: () => void;
|
|
149
|
+
onKeyDown?: (event: ReactKeyboardEvent<HTMLElement>) => void;
|
|
150
|
+
textAreaRef?: Ref<HTMLTextAreaElement>;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export interface SpinnerProps
|
|
154
|
+
extends DesignSystemStyleProps, DesignSystemAccessibleProps {
|
|
155
|
+
label?: string;
|
|
156
|
+
size?: DesignSystemSize;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export interface SkeletonProps
|
|
160
|
+
extends DesignSystemStyleProps, DesignSystemAccessibleProps {
|
|
161
|
+
width?: string | number;
|
|
162
|
+
height?: string | number;
|
|
163
|
+
shape?: "line" | "rectangle" | "circle";
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export interface StatusProps
|
|
167
|
+
extends DesignSystemStyleProps, DesignSystemAccessibleProps {
|
|
168
|
+
children: ReactNode;
|
|
169
|
+
tone?: DesignSystemTone;
|
|
170
|
+
icon?: ReactNode;
|
|
171
|
+
size?: DesignSystemSize;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export interface SurfaceProps
|
|
175
|
+
extends DesignSystemStyleProps, DesignSystemAccessibleProps {
|
|
176
|
+
children: ReactNode;
|
|
177
|
+
as?: "div" | "section" | "article" | "aside";
|
|
178
|
+
elevation?: "none" | "low" | "medium";
|
|
179
|
+
padding?: "none" | "compact" | "default" | "spacious";
|
|
180
|
+
interactive?: boolean;
|
|
181
|
+
onPress?: (event?: DesignSystemPressEvent) => void;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export interface AvatarProps
|
|
185
|
+
extends DesignSystemStyleProps, DesignSystemAccessibleProps {
|
|
186
|
+
name: string;
|
|
187
|
+
src?: string | null;
|
|
188
|
+
fallback?: ReactNode;
|
|
189
|
+
size?: DesignSystemSize;
|
|
190
|
+
status?: "online" | "offline" | "busy" | "away";
|
|
191
|
+
imageRef?: Ref<HTMLImageElement>;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export interface TooltipProps extends DesignSystemOverlayProps {
|
|
195
|
+
trigger: ReactElement;
|
|
196
|
+
content: ReactNode;
|
|
197
|
+
open?: boolean;
|
|
198
|
+
defaultOpen?: boolean;
|
|
199
|
+
onOpenChange?: (open: boolean) => void;
|
|
200
|
+
delayMs?: number;
|
|
201
|
+
disabled?: boolean;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export interface MenuItem {
|
|
205
|
+
id: DesignSystemKey;
|
|
206
|
+
label: ReactNode;
|
|
207
|
+
description?: ReactNode;
|
|
208
|
+
icon?: ReactNode;
|
|
209
|
+
shortcut?: ReactNode;
|
|
210
|
+
disabled?: boolean;
|
|
211
|
+
intent?: Extract<DesignSystemIntent, "neutral" | "danger">;
|
|
212
|
+
selected?: boolean;
|
|
213
|
+
children?: readonly MenuItem[];
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export interface MenuSection {
|
|
217
|
+
id: DesignSystemKey;
|
|
218
|
+
label?: ReactNode;
|
|
219
|
+
items: readonly MenuItem[];
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export interface MenuProps extends DesignSystemOverlayProps {
|
|
223
|
+
trigger: ReactElement;
|
|
224
|
+
items?: readonly MenuItem[];
|
|
225
|
+
sections?: readonly MenuSection[];
|
|
226
|
+
open?: boolean;
|
|
227
|
+
defaultOpen?: boolean;
|
|
228
|
+
onOpenChange?: (open: boolean) => void;
|
|
229
|
+
onAction: (id: DesignSystemKey) => void;
|
|
230
|
+
closeOnAction?: boolean;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export interface PopoverProps extends DesignSystemOverlayProps {
|
|
234
|
+
trigger: ReactElement;
|
|
235
|
+
children: ReactNode;
|
|
236
|
+
open?: boolean;
|
|
237
|
+
defaultOpen?: boolean;
|
|
238
|
+
onOpenChange?: (open: boolean) => void;
|
|
239
|
+
modal?: boolean;
|
|
240
|
+
dismissible?: boolean;
|
|
241
|
+
initialFocusRef?: RefObject<HTMLElement | null>;
|
|
242
|
+
restoreFocusRef?: RefObject<HTMLElement | null>;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export interface DialogProps extends DesignSystemOverlayProps {
|
|
246
|
+
open: boolean;
|
|
247
|
+
onOpenChange: (open: boolean) => void;
|
|
248
|
+
title: ReactNode;
|
|
249
|
+
children: ReactNode;
|
|
250
|
+
description?: ReactNode;
|
|
251
|
+
footer?: ReactNode;
|
|
252
|
+
trigger?: ReactElement;
|
|
253
|
+
size?: "small" | "medium" | "large" | "fullscreen";
|
|
254
|
+
dismissible?: boolean;
|
|
255
|
+
closeLabel?: string;
|
|
256
|
+
initialFocusRef?: RefObject<HTMLElement | null>;
|
|
257
|
+
restoreFocusRef?: RefObject<HTMLElement | null>;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export interface PickerOption<Value extends DesignSystemKey = string> {
|
|
261
|
+
value: Value;
|
|
262
|
+
label: ReactNode;
|
|
263
|
+
textValue?: string;
|
|
264
|
+
description?: ReactNode;
|
|
265
|
+
icon?: ReactNode;
|
|
266
|
+
disabled?: boolean;
|
|
267
|
+
keywords?: readonly string[];
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export interface PickerProps<Value extends DesignSystemKey = string>
|
|
271
|
+
extends DesignSystemOverlayProps, DesignSystemAccessibleProps {
|
|
272
|
+
mode: "select" | "combobox";
|
|
273
|
+
options: readonly PickerOption<Value>[];
|
|
274
|
+
value: Value | null;
|
|
275
|
+
onChange: (value: Value | null) => void;
|
|
276
|
+
label?: ReactNode;
|
|
277
|
+
description?: ReactNode;
|
|
278
|
+
errorMessage?: ReactNode;
|
|
279
|
+
placeholder?: string;
|
|
280
|
+
searchValue?: string;
|
|
281
|
+
onSearchChange?: (value: string) => void;
|
|
282
|
+
open?: boolean;
|
|
283
|
+
onOpenChange?: (open: boolean) => void;
|
|
284
|
+
emptyContent?: ReactNode;
|
|
285
|
+
loadingContent?: ReactNode;
|
|
286
|
+
loading?: boolean;
|
|
287
|
+
required?: boolean;
|
|
288
|
+
disabled?: boolean;
|
|
289
|
+
invalid?: boolean;
|
|
290
|
+
pickerRef?: Ref<HTMLElement>;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export interface CheckboxProps
|
|
294
|
+
extends DesignSystemStyleProps, DesignSystemAccessibleProps {
|
|
295
|
+
checked: boolean;
|
|
296
|
+
onChange: (checked: boolean) => void;
|
|
297
|
+
label?: ReactNode;
|
|
298
|
+
description?: ReactNode;
|
|
299
|
+
indeterminate?: boolean;
|
|
300
|
+
required?: boolean;
|
|
301
|
+
disabled?: boolean;
|
|
302
|
+
invalid?: boolean;
|
|
303
|
+
inputRef?: Ref<HTMLButtonElement>;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
export interface SwitchProps
|
|
307
|
+
extends DesignSystemStyleProps, DesignSystemAccessibleProps {
|
|
308
|
+
checked: boolean;
|
|
309
|
+
onChange: (checked: boolean) => void;
|
|
310
|
+
label?: ReactNode;
|
|
311
|
+
description?: ReactNode;
|
|
312
|
+
disabled?: boolean;
|
|
313
|
+
inputRef?: Ref<HTMLButtonElement>;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export interface TabItem<Value extends DesignSystemKey = string> {
|
|
317
|
+
value: Value;
|
|
318
|
+
label: ReactNode;
|
|
319
|
+
content: ReactNode;
|
|
320
|
+
disabled?: boolean;
|
|
321
|
+
icon?: ReactNode;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export interface TabsProps<Value extends DesignSystemKey = string>
|
|
325
|
+
extends DesignSystemStyleProps, DesignSystemAccessibleProps {
|
|
326
|
+
items: readonly TabItem<Value>[];
|
|
327
|
+
value: Value;
|
|
328
|
+
onChange: (value: Value) => void;
|
|
329
|
+
orientation?: "horizontal" | "vertical";
|
|
330
|
+
activationMode?: "automatic" | "manual";
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
export interface PickerComponent {
|
|
334
|
+
<Value extends DesignSystemKey = string>(
|
|
335
|
+
props: PickerProps<Value>,
|
|
336
|
+
): ReactNode;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export interface TabsComponent {
|
|
340
|
+
<Value extends DesignSystemKey = string>(props: TabsProps<Value>): ReactNode;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export interface DesignSystemComponents {
|
|
344
|
+
ActionButton: ComponentType<ActionButtonProps>;
|
|
345
|
+
IconButton: ComponentType<IconButtonProps>;
|
|
346
|
+
TextField: ComponentType<TextFieldProps>;
|
|
347
|
+
TextArea: ComponentType<TextAreaProps>;
|
|
348
|
+
Spinner: ComponentType<SpinnerProps>;
|
|
349
|
+
Skeleton: ComponentType<SkeletonProps>;
|
|
350
|
+
Status: ComponentType<StatusProps>;
|
|
351
|
+
Surface: ComponentType<SurfaceProps>;
|
|
352
|
+
Avatar: ComponentType<AvatarProps>;
|
|
353
|
+
Tooltip: ComponentType<TooltipProps>;
|
|
354
|
+
Menu: ComponentType<MenuProps>;
|
|
355
|
+
Popover: ComponentType<PopoverProps>;
|
|
356
|
+
Dialog: ComponentType<DialogProps>;
|
|
357
|
+
Picker: PickerComponent;
|
|
358
|
+
Checkbox: ComponentType<CheckboxProps>;
|
|
359
|
+
Switch: ComponentType<SwitchProps>;
|
|
360
|
+
Tabs: TabsComponent;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export type DesignSystemComponentName = keyof DesignSystemComponents;
|
|
@@ -14,7 +14,12 @@ import {
|
|
|
14
14
|
type SharedEditorFeatures,
|
|
15
15
|
} from "./extensions.js";
|
|
16
16
|
import type { ImageUploadFn } from "./ImageExtension.js";
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
DEFAULT_SLASH_COMMANDS,
|
|
19
|
+
filterSlashCommandItems,
|
|
20
|
+
SlashCommandMenu,
|
|
21
|
+
type SlashCommandItem,
|
|
22
|
+
} from "./SlashCommandMenu.js";
|
|
18
23
|
import {
|
|
19
24
|
useCollabReconcile,
|
|
20
25
|
getEditorMarkdown,
|
|
@@ -200,6 +205,12 @@ export function SharedRichEditor({
|
|
|
200
205
|
|
|
201
206
|
const collab = !!ydoc;
|
|
202
207
|
|
|
208
|
+
const effectiveSlashItems = useMemo(
|
|
209
|
+
() =>
|
|
210
|
+
filterSlashCommandItems(slashItems ?? DEFAULT_SLASH_COMMANDS, features),
|
|
211
|
+
[features, slashItems],
|
|
212
|
+
);
|
|
213
|
+
|
|
203
214
|
// The collab hook needs the editor, but useEditor's `onUpdate` needs the
|
|
204
215
|
// hook's guards. Break the cycle with a ref: `onUpdate` reads the guards
|
|
205
216
|
// through `guardsRef`, which is populated right after the hook runs below.
|
|
@@ -313,7 +324,7 @@ export function SharedRichEditor({
|
|
|
313
324
|
<BubbleToolbar editor={editor} buildItems={buildBubbleItems} />
|
|
314
325
|
) : null}
|
|
315
326
|
{editable ? (
|
|
316
|
-
<SlashCommandMenu editor={editor} items={
|
|
327
|
+
<SlashCommandMenu editor={editor} items={effectiveSlashItems} />
|
|
317
328
|
) : null}
|
|
318
329
|
<EditorContent editor={editor} />
|
|
319
330
|
</div>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
DEFAULT_SLASH_COMMANDS,
|
|
5
|
+
filterSlashCommandItems,
|
|
6
|
+
} from "./SlashCommandMenu.js";
|
|
7
|
+
|
|
8
|
+
describe("filterSlashCommandItems", () => {
|
|
9
|
+
it("hides commands whose editor extensions are disabled", () => {
|
|
10
|
+
const commands = filterSlashCommandItems(DEFAULT_SLASH_COMMANDS, {
|
|
11
|
+
codeBlock: false,
|
|
12
|
+
tables: false,
|
|
13
|
+
tasks: false,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
expect(commands.map((command) => command.title)).not.toEqual(
|
|
17
|
+
expect.arrayContaining(["Code block", "Table", "To-do list"]),
|
|
18
|
+
);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("keeps commands enabled when their feature is unspecified", () => {
|
|
22
|
+
const commands = filterSlashCommandItems(DEFAULT_SLASH_COMMANDS, {
|
|
23
|
+
tasks: false,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
expect(commands.map((command) => command.title)).toEqual(
|
|
27
|
+
expect.arrayContaining(["Code block", "Table"]),
|
|
28
|
+
);
|
|
29
|
+
expect(commands.map((command) => command.title)).not.toContain(
|
|
30
|
+
"To-do list",
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -22,9 +22,26 @@ export interface SlashCommandItem {
|
|
|
22
22
|
searchText?: string;
|
|
23
23
|
/** Short text glyph shown in the menu (T, H1, tbl, …). */
|
|
24
24
|
icon: string;
|
|
25
|
+
/** Hide this command when the shared editor feature is disabled. */
|
|
26
|
+
requires?: "tables" | "tasks" | "codeBlock";
|
|
25
27
|
action: (editor: Editor) => void;
|
|
26
28
|
}
|
|
27
29
|
|
|
30
|
+
export interface SlashCommandFeatureFlags {
|
|
31
|
+
tables?: boolean;
|
|
32
|
+
tasks?: boolean;
|
|
33
|
+
codeBlock?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function filterSlashCommandItems(
|
|
37
|
+
items: readonly SlashCommandItem[],
|
|
38
|
+
features?: SlashCommandFeatureFlags,
|
|
39
|
+
): SlashCommandItem[] {
|
|
40
|
+
return items.filter(
|
|
41
|
+
(item) => !item.requires || features?.[item.requires] !== false,
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
28
45
|
/**
|
|
29
46
|
* The default block commands — Plan's current set. Apps pass their own `items`
|
|
30
47
|
* (typically `[...DEFAULT_SLASH_COMMANDS, ...extra]`) to extend it.
|
|
@@ -73,6 +90,7 @@ export const DEFAULT_SLASH_COMMANDS: SlashCommandItem[] = [
|
|
|
73
90
|
title: "To-do list",
|
|
74
91
|
description: "Checklist items",
|
|
75
92
|
icon: "[]",
|
|
93
|
+
requires: "tasks",
|
|
76
94
|
action: (editor) => editor.chain().focus().toggleTaskList().run(),
|
|
77
95
|
},
|
|
78
96
|
{
|
|
@@ -85,6 +103,7 @@ export const DEFAULT_SLASH_COMMANDS: SlashCommandItem[] = [
|
|
|
85
103
|
title: "Code block",
|
|
86
104
|
description: "Code snippet",
|
|
87
105
|
icon: "<>",
|
|
106
|
+
requires: "codeBlock",
|
|
88
107
|
action: (editor) => editor.chain().focus().toggleCodeBlock().run(),
|
|
89
108
|
},
|
|
90
109
|
{
|
|
@@ -97,6 +116,7 @@ export const DEFAULT_SLASH_COMMANDS: SlashCommandItem[] = [
|
|
|
97
116
|
title: "Table",
|
|
98
117
|
description: "Three by three table",
|
|
99
118
|
icon: "tbl",
|
|
119
|
+
requires: "tables",
|
|
100
120
|
action: (editor) =>
|
|
101
121
|
editor
|
|
102
122
|
.chain()
|
package/src/editor/index.ts
CHANGED
|
@@ -25,8 +25,10 @@ export {
|
|
|
25
25
|
SlashCommandMenu,
|
|
26
26
|
DEFAULT_SLASH_COMMANDS,
|
|
27
27
|
createImageSlashCommand,
|
|
28
|
+
filterSlashCommandItems,
|
|
28
29
|
type SlashCommandItem,
|
|
29
30
|
type SlashCommandMenuProps,
|
|
31
|
+
type SlashCommandFeatureFlags,
|
|
30
32
|
} from "./SlashCommandMenu.js";
|
|
31
33
|
export {
|
|
32
34
|
SharedImage,
|
package/src/provider.tsx
CHANGED
|
@@ -1,20 +1,33 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createContext,
|
|
3
3
|
useContext,
|
|
4
|
+
useEffect,
|
|
4
5
|
useMemo,
|
|
6
|
+
type ElementType,
|
|
5
7
|
type ReactNode,
|
|
6
8
|
type ComponentType,
|
|
7
9
|
} from "react";
|
|
8
10
|
|
|
11
|
+
import {
|
|
12
|
+
DesignSystemContext,
|
|
13
|
+
LegacyButtonRenderContext,
|
|
14
|
+
type DesignSystemContextValue,
|
|
15
|
+
} from "./design-system/context.js";
|
|
16
|
+
import type { DesignSystemDefinition } from "./design-system/definition.js";
|
|
17
|
+
import type {
|
|
18
|
+
ActionButtonProps,
|
|
19
|
+
DesignSystemComponents,
|
|
20
|
+
} from "./design-system/types.js";
|
|
9
21
|
import type { ButtonProps } from "./ui/button.js";
|
|
10
22
|
|
|
11
23
|
export interface ToolkitComponents {
|
|
12
24
|
Button?: ComponentType<ButtonProps>;
|
|
13
25
|
}
|
|
14
26
|
|
|
15
|
-
interface ToolkitProviderProps {
|
|
27
|
+
export interface ToolkitProviderProps {
|
|
16
28
|
children: ReactNode;
|
|
17
29
|
components?: ToolkitComponents;
|
|
30
|
+
designSystem?: DesignSystemDefinition;
|
|
18
31
|
}
|
|
19
32
|
|
|
20
33
|
const ToolkitComponentsContext = createContext<ToolkitComponents>({});
|
|
@@ -22,17 +35,97 @@ const ToolkitComponentsContext = createContext<ToolkitComponents>({});
|
|
|
22
35
|
export function ToolkitProvider({
|
|
23
36
|
children,
|
|
24
37
|
components,
|
|
38
|
+
designSystem,
|
|
25
39
|
}: ToolkitProviderProps) {
|
|
26
40
|
const parent = useContext(ToolkitComponentsContext);
|
|
27
|
-
const
|
|
41
|
+
const parentDesignSystem = useContext(DesignSystemContext);
|
|
42
|
+
const value = useMemo<ToolkitComponents>(
|
|
28
43
|
() => ({ ...parent, ...components }),
|
|
29
44
|
[parent, components],
|
|
30
45
|
);
|
|
46
|
+
const mergedDefinition = useMemo<DesignSystemDefinition | undefined>(() => {
|
|
47
|
+
if (!designSystem) return parentDesignSystem.definition;
|
|
48
|
+
return {
|
|
49
|
+
...parentDesignSystem.definition,
|
|
50
|
+
...designSystem,
|
|
51
|
+
components: {
|
|
52
|
+
...parentDesignSystem.definition?.components,
|
|
53
|
+
...designSystem.components,
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}, [designSystem, parentDesignSystem.definition]);
|
|
57
|
+
const legacyActionButton = useMemo<
|
|
58
|
+
DesignSystemComponents["ActionButton"] | undefined
|
|
59
|
+
>(() => {
|
|
60
|
+
if (!value.Button) return parentDesignSystem.legacyActionButton;
|
|
61
|
+
const LegacyButton = value.Button as ElementType<
|
|
62
|
+
ButtonProps & { ref?: ActionButtonProps["elementRef"] }
|
|
63
|
+
>;
|
|
64
|
+
return function LegacyActionButton({
|
|
65
|
+
children,
|
|
66
|
+
intent,
|
|
67
|
+
emphasis,
|
|
68
|
+
size,
|
|
69
|
+
pending,
|
|
70
|
+
leadingIcon,
|
|
71
|
+
trailingIcon,
|
|
72
|
+
onPress,
|
|
73
|
+
elementRef,
|
|
74
|
+
...props
|
|
75
|
+
}: ActionButtonProps) {
|
|
76
|
+
const variant =
|
|
77
|
+
emphasis === "ghost"
|
|
78
|
+
? "ghost"
|
|
79
|
+
: emphasis === "outline"
|
|
80
|
+
? "outline"
|
|
81
|
+
: intent === "danger"
|
|
82
|
+
? "destructive"
|
|
83
|
+
: intent === "primary"
|
|
84
|
+
? "default"
|
|
85
|
+
: "secondary";
|
|
86
|
+
const legacySize =
|
|
87
|
+
size === "compact" ? "sm" : size === "large" ? "lg" : "default";
|
|
88
|
+
return (
|
|
89
|
+
<LegacyButtonRenderContext.Provider value={true}>
|
|
90
|
+
<LegacyButton
|
|
91
|
+
{...props}
|
|
92
|
+
ref={elementRef}
|
|
93
|
+
variant={variant}
|
|
94
|
+
size={legacySize}
|
|
95
|
+
disabled={props.disabled || pending}
|
|
96
|
+
aria-busy={pending || undefined}
|
|
97
|
+
onClick={(event) => onPress?.(event)}
|
|
98
|
+
>
|
|
99
|
+
{leadingIcon}
|
|
100
|
+
{children}
|
|
101
|
+
{trailingIcon}
|
|
102
|
+
</LegacyButton>
|
|
103
|
+
</LegacyButtonRenderContext.Provider>
|
|
104
|
+
);
|
|
105
|
+
};
|
|
106
|
+
}, [parentDesignSystem.legacyActionButton, value.Button]);
|
|
107
|
+
const designSystemValue = useMemo<DesignSystemContextValue>(
|
|
108
|
+
() => ({ definition: mergedDefinition, legacyActionButton }),
|
|
109
|
+
[legacyActionButton, mergedDefinition],
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
if (!mergedDefinition?.components?.ActionButton || !value.Button) return;
|
|
114
|
+
const isDevelopment =
|
|
115
|
+
(import.meta as ImportMeta & { env?: { DEV?: boolean } }).env?.DEV ??
|
|
116
|
+
true;
|
|
117
|
+
if (!isDevelopment) return;
|
|
118
|
+
console.warn(
|
|
119
|
+
"[agent-native] ToolkitProvider received both designSystem.components.ActionButton and legacy components.Button. ActionButton takes precedence.",
|
|
120
|
+
);
|
|
121
|
+
}, [mergedDefinition?.components?.ActionButton, value.Button]);
|
|
31
122
|
|
|
32
123
|
return (
|
|
33
|
-
<
|
|
34
|
-
{
|
|
35
|
-
|
|
124
|
+
<DesignSystemContext.Provider value={designSystemValue}>
|
|
125
|
+
<ToolkitComponentsContext.Provider value={value}>
|
|
126
|
+
{children}
|
|
127
|
+
</ToolkitComponentsContext.Provider>
|
|
128
|
+
</DesignSystemContext.Provider>
|
|
36
129
|
);
|
|
37
130
|
}
|
|
38
131
|
|