@springbrand/message-panel 0.1.0 → 0.1.2

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.
Files changed (99) hide show
  1. package/dist/demo/camel-chat-showcase.d.ts +1 -0
  2. package/dist/demo/camel-chat-showcase.js +1007 -0
  3. package/dist/demo/fixtures.d.ts +32 -0
  4. package/dist/demo/fixtures.js +250 -0
  5. package/dist/demo/index.js +4 -0
  6. package/dist/demo/message-panel-chat-showcase.d.ts +1 -0
  7. package/dist/demo/message-panel-chat-showcase.js +114 -0
  8. package/dist/demo/message-panel-gallery.d.ts +1 -0
  9. package/dist/demo/message-panel-gallery.js +130 -0
  10. package/dist/src/adapters/ai-sdk.d.ts +4 -0
  11. package/dist/src/adapters/ai-sdk.js +25 -0
  12. package/dist/src/camel/camel-chat-messages.d.ts +44 -0
  13. package/dist/src/camel/camel-chat-messages.js +421 -0
  14. package/dist/src/camel/camel-model-select.d.ts +13 -0
  15. package/dist/src/camel/camel-model-select.js +7 -0
  16. package/dist/src/camel/camel-plan-bar.d.ts +5 -0
  17. package/dist/src/camel/camel-plan-bar.js +24 -0
  18. package/dist/src/camel/camel-prompt-input.d.ts +32 -0
  19. package/dist/src/camel/camel-prompt-input.js +182 -0
  20. package/dist/src/camel/camel-tool-presentation.d.ts +21 -0
  21. package/dist/src/camel/camel-tool-presentation.js +784 -0
  22. package/dist/src/camel/camel-turn.d.ts +57 -0
  23. package/dist/src/camel/camel-turn.js +203 -0
  24. package/dist/src/camel/index.js +7 -0
  25. package/dist/src/camel/turn-summary-bar.d.ts +8 -0
  26. package/dist/src/camel/turn-summary-bar.js +12 -0
  27. package/dist/src/chat-summary-panel.d.ts +22 -0
  28. package/dist/src/chat-summary-panel.js +26 -0
  29. package/dist/src/composer/chat-composer.d.ts +4 -0
  30. package/dist/src/composer/chat-composer.js +90 -0
  31. package/dist/src/composer/composer-attachments.d.ts +13 -0
  32. package/dist/src/composer/composer-attachments.js +47 -0
  33. package/dist/src/composer/composer-trigger-popover.d.ts +31 -0
  34. package/dist/src/composer/composer-trigger-popover.js +29 -0
  35. package/dist/src/composer/composer.d.ts +15 -0
  36. package/dist/src/composer/composer.js +180 -0
  37. package/dist/src/composer/drop-controller.d.ts +8 -0
  38. package/dist/src/composer/drop-controller.js +69 -0
  39. package/dist/src/composer/index.js +6 -0
  40. package/dist/src/composer/types.d.ts +62 -0
  41. package/dist/src/composer/types.js +1 -0
  42. package/dist/src/contracts.d.ts +94 -0
  43. package/dist/src/contracts.js +1 -0
  44. package/dist/src/conversation.d.ts +13 -0
  45. package/dist/src/conversation.js +18 -0
  46. package/dist/src/index.js +12 -0
  47. package/dist/src/internal/cn.d.ts +1 -0
  48. package/dist/src/internal/cn.js +3 -0
  49. package/dist/src/message-panel.d.ts +4 -0
  50. package/dist/src/message-panel.js +144 -0
  51. package/dist/src/message.d.ts +36 -0
  52. package/dist/src/message.js +83 -0
  53. package/dist/src/parts/index.d.ts +187 -0
  54. package/dist/src/parts/index.js +332 -0
  55. package/dist/src/parts/kind.d.ts +3 -0
  56. package/dist/src/parts/kind.js +69 -0
  57. package/dist/src/parts/plan.d.ts +10 -0
  58. package/dist/src/parts/plan.js +40 -0
  59. package/dist/src/parts/primitives.d.ts +70 -0
  60. package/dist/src/parts/primitives.js +153 -0
  61. package/dist/src/registry.d.ts +4 -0
  62. package/dist/src/registry.js +31 -0
  63. package/dist/src/status.d.ts +26 -0
  64. package/dist/src/status.js +74 -0
  65. package/package.json +17 -8
  66. package/demo/camel-chat-showcase.tsx +0 -1265
  67. package/demo/fixtures.ts +0 -292
  68. package/demo/message-panel-chat-showcase.tsx +0 -250
  69. package/demo/message-panel-gallery.tsx +0 -389
  70. package/src/adapters/ai-sdk.ts +0 -32
  71. package/src/camel/camel-chat-messages.tsx +0 -1420
  72. package/src/camel/camel-model-select.tsx +0 -88
  73. package/src/camel/camel-plan-bar.tsx +0 -115
  74. package/src/camel/camel-prompt-input.tsx +0 -540
  75. package/src/camel/camel-tool-presentation.tsx +0 -1270
  76. package/src/camel/camel-turn.ts +0 -315
  77. package/src/camel/turn-summary-bar.tsx +0 -81
  78. package/src/chat-summary-panel.tsx +0 -229
  79. package/src/composer/chat-composer.tsx +0 -216
  80. package/src/composer/composer-attachments.tsx +0 -138
  81. package/src/composer/composer-trigger-popover.tsx +0 -236
  82. package/src/composer/composer.tsx +0 -425
  83. package/src/composer/drop-controller.ts +0 -80
  84. package/src/composer/types.ts +0 -79
  85. package/src/contracts.ts +0 -139
  86. package/src/conversation.tsx +0 -76
  87. package/src/internal/cn.ts +0 -3
  88. package/src/message-panel.tsx +0 -368
  89. package/src/message.tsx +0 -254
  90. package/src/parts/index.tsx +0 -1149
  91. package/src/parts/kind.ts +0 -67
  92. package/src/parts/plan.ts +0 -63
  93. package/src/parts/primitives.tsx +0 -439
  94. package/src/registry.ts +0 -44
  95. package/src/status.tsx +0 -132
  96. /package/{demo/index.ts → dist/demo/index.d.ts} +0 -0
  97. /package/{src/camel/index.ts → dist/src/camel/index.d.ts} +0 -0
  98. /package/{src/composer/index.ts → dist/src/composer/index.d.ts} +0 -0
  99. /package/{src/index.ts → dist/src/index.d.ts} +0 -0
@@ -1,216 +0,0 @@
1
- import {
2
- PlusIcon,
3
- SparklesIcon,
4
- } from "lucide-react";
5
- import {
6
- forwardRef,
7
- useEffect,
8
- useMemo,
9
- useState,
10
- type KeyboardEvent,
11
- } from "react";
12
- import { cn } from "../internal/cn";
13
- import { Composer } from "./composer";
14
- import type {
15
- ChatComposerProps,
16
- ComposerCommand,
17
- ComposerToolbarAction,
18
- } from "./types";
19
-
20
- const toolbarIcons = {
21
- plus: PlusIcon,
22
- sparkles: SparklesIcon,
23
- } as const;
24
-
25
- function ToolbarAction({ action }: { action: ComposerToolbarAction }) {
26
- const Icon = action.icon ? toolbarIcons[action.icon] : undefined;
27
- return (
28
- <button
29
- type="button"
30
- className="sb-chat-composer__action"
31
- disabled={action.disabled}
32
- onClick={action.onSelect}
33
- >
34
- {Icon && <Icon size={16} />}
35
- <span>{action.label}</span>
36
- </button>
37
- );
38
- }
39
-
40
- function CommandMenu({
41
- commands,
42
- active,
43
- label,
44
- onActiveChange,
45
- onPick,
46
- }: {
47
- commands: readonly ComposerCommand[];
48
- active: number;
49
- label: string;
50
- onActiveChange: (index: number) => void;
51
- onPick: (command: ComposerCommand) => void;
52
- }) {
53
- return (
54
- <div
55
- className="sb-command-menu"
56
- role="listbox"
57
- aria-label={label}
58
- onMouseDown={(event) => event.preventDefault()}
59
- >
60
- <div className="sb-command-menu__label">{label}</div>
61
- <div className="sb-command-menu__list">
62
- {commands.map((command, index) => (
63
- <button
64
- key={command.name}
65
- type="button"
66
- role="option"
67
- aria-selected={index === active}
68
- onMouseEnter={() => onActiveChange(index)}
69
- onClick={() => onPick(command)}
70
- >
71
- <code>/{command.name}</code>
72
- <span>{command.description}</span>
73
- </button>
74
- ))}
75
- </div>
76
- </div>
77
- );
78
- }
79
-
80
- function ChatComposerInner<TAttachment>(
81
- {
82
- value,
83
- defaultValue = "",
84
- onValueChange,
85
- commands = [],
86
- toolbarActions = [],
87
- variant = "docked",
88
- commandMenuLabel = "命令(↑↓ 选择,回车填入)",
89
- onCommandPick,
90
- onSubmit,
91
- tools,
92
- textareaProps,
93
- className,
94
- ...props
95
- }: ChatComposerProps<TAttachment>,
96
- ref: React.ForwardedRef<HTMLDivElement>,
97
- ) {
98
- const [internalValue, setInternalValue] = useState(defaultValue);
99
- const resolvedValue = value ?? internalValue;
100
- const [dismissed, setDismissed] = useState(false);
101
- const [active, setActive] = useState(0);
102
- const query =
103
- resolvedValue.startsWith("/") && !resolvedValue.includes("\n")
104
- ? resolvedValue.slice(1).trim().toLowerCase()
105
- : null;
106
- const filtered = useMemo(() => {
107
- if (query === null) return [];
108
- if (!query) return [...commands];
109
- return commands.filter(
110
- (command) =>
111
- command.name.toLowerCase().includes(query) ||
112
- command.description.toLowerCase().includes(query),
113
- );
114
- }, [commands, query]);
115
- const menuOpen = !dismissed && query !== null && filtered.length > 0;
116
-
117
- useEffect(() => {
118
- setDismissed(false);
119
- }, [resolvedValue]);
120
-
121
- useEffect(() => {
122
- if (active >= filtered.length) setActive(0);
123
- }, [active, filtered.length]);
124
-
125
- const changeValue = (next: string) => {
126
- if (value === undefined) setInternalValue(next);
127
- onValueChange?.(next);
128
- };
129
-
130
- const pick = (command: ComposerCommand) => {
131
- changeValue(command.prompt);
132
- setDismissed(true);
133
- onCommandPick?.(command);
134
- };
135
-
136
- const handleKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {
137
- textareaProps?.onKeyDown?.(event);
138
- if (event.defaultPrevented || !menuOpen) return;
139
- if (event.key === "Escape") {
140
- event.preventDefault();
141
- setDismissed(true);
142
- return;
143
- }
144
- if (event.key === "ArrowDown" || event.key === "ArrowUp") {
145
- event.preventDefault();
146
- const delta = event.key === "ArrowDown" ? 1 : -1;
147
- setActive(
148
- (current) => (current + delta + filtered.length) % filtered.length,
149
- );
150
- return;
151
- }
152
- if (
153
- (event.key === "Enter" &&
154
- !event.shiftKey &&
155
- !event.nativeEvent.isComposing) ||
156
- event.key === "Tab"
157
- ) {
158
- const command = filtered[active] ?? filtered[0];
159
- if (command) {
160
- event.preventDefault();
161
- pick(command);
162
- }
163
- }
164
- };
165
-
166
- return (
167
- <div
168
- ref={ref}
169
- className={cn("sb-chat-composer", className)}
170
- data-variant={variant}
171
- >
172
- <div className="sb-chat-composer__inner">
173
- {menuOpen && (
174
- <CommandMenu
175
- commands={filtered}
176
- active={active}
177
- label={commandMenuLabel}
178
- onActiveChange={setActive}
179
- onPick={pick}
180
- />
181
- )}
182
- <Composer
183
- {...props}
184
- value={resolvedValue}
185
- onValueChange={changeValue}
186
- onSubmit={async (message) => {
187
- await onSubmit(message);
188
- if (value === undefined) setInternalValue("");
189
- }}
190
- tools={
191
- <>
192
- {tools}
193
- {toolbarActions.map((action) => (
194
- <ToolbarAction key={action.id} action={action} />
195
- ))}
196
- </>
197
- }
198
- textareaProps={{
199
- ...textareaProps,
200
- onKeyDown: handleKeyDown,
201
- onBlur: (event) => {
202
- textareaProps?.onBlur?.(event);
203
- setDismissed(true);
204
- },
205
- }}
206
- />
207
- </div>
208
- </div>
209
- );
210
- }
211
-
212
- export const ChatComposer = forwardRef(ChatComposerInner) as <TAttachment>(
213
- props: ChatComposerProps<TAttachment> & {
214
- ref?: React.ForwardedRef<HTMLDivElement>;
215
- },
216
- ) => React.ReactElement;
@@ -1,138 +0,0 @@
1
- import {
2
- ArrowLeftIcon,
3
- ArrowRightIcon,
4
- FileAudioIcon,
5
- FileCodeIcon,
6
- FileImageIcon,
7
- FileSpreadsheetIcon,
8
- FileTextIcon,
9
- Loader2Icon,
10
- RotateCcwIcon,
11
- XIcon,
12
- } from "lucide-react";
13
- import {
14
- forwardRef,
15
- type ButtonHTMLAttributes,
16
- type HTMLAttributes,
17
- type ReactNode,
18
- } from "react";
19
- import { cn } from "../internal/cn";
20
- import type { ComposerAttachmentView } from "./types";
21
-
22
- function formatSize(bytes?: number): string {
23
- if (!bytes) return "";
24
- if (bytes < 1024) return `${bytes} B`;
25
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
26
- return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
27
- }
28
-
29
- function attachmentIcon(attachment: ComposerAttachmentView) {
30
- const value = `${attachment.mediaType ?? ""} ${attachment.name}`;
31
- if (/image/i.test(value)) return FileImageIcon;
32
- if (/audio/i.test(value)) return FileAudioIcon;
33
- if (/csv|sheet|excel/i.test(value)) return FileSpreadsheetIcon;
34
- if (/code|javascript|typescript|json|html|xml/i.test(value)) return FileCodeIcon;
35
- return FileTextIcon;
36
- }
37
-
38
- export const Attachments = forwardRef<
39
- HTMLDivElement,
40
- HTMLAttributes<HTMLDivElement>
41
- >(({ className, ...props }, ref) => (
42
- <div ref={ref} className={cn("sb-attachments", className)} {...props} />
43
- ));
44
- Attachments.displayName = "Attachments";
45
-
46
- export interface AttachmentPreviewProps extends HTMLAttributes<HTMLDivElement> {
47
- attachment: ComposerAttachmentView;
48
- actions?: ReactNode;
49
- }
50
-
51
- export const AttachmentPreview = forwardRef<
52
- HTMLDivElement,
53
- AttachmentPreviewProps
54
- >(({ attachment, actions, className, ...props }, ref) => {
55
- const Icon = attachmentIcon(attachment);
56
- const isImage =
57
- attachment.mediaType?.startsWith("image/") && Boolean(attachment.url);
58
- const subtitle =
59
- attachment.status === "uploading"
60
- ? "上传中…"
61
- : attachment.status === "error"
62
- ? "上传失败"
63
- : [attachment.note, formatSize(attachment.size)].filter(Boolean).join(" · ");
64
- return (
65
- <div
66
- ref={ref}
67
- className={cn("sb-attachment", className)}
68
- data-status={attachment.status}
69
- {...props}
70
- >
71
- <span className="sb-attachment__preview">
72
- {attachment.status === "uploading" ? (
73
- <Loader2Icon size={18} className="sb-spin" />
74
- ) : isImage ? (
75
- <img src={attachment.url} alt="" />
76
- ) : (
77
- <Icon size={20} />
78
- )}
79
- </span>
80
- <span className="sb-attachment__text">
81
- <strong title={attachment.name}>{attachment.name}</strong>
82
- <small>{subtitle}</small>
83
- </span>
84
- {actions && <span className="sb-attachment__actions">{actions}</span>}
85
- </div>
86
- );
87
- });
88
- AttachmentPreview.displayName = "AttachmentPreview";
89
-
90
- export const AttachmentRemove = forwardRef<
91
- HTMLButtonElement,
92
- ButtonHTMLAttributes<HTMLButtonElement>
93
- >(({ className, children, ...props }, ref) => (
94
- <button
95
- ref={ref}
96
- type="button"
97
- className={cn("sb-attachment__button", className)}
98
- aria-label="移除附件"
99
- {...props}
100
- >
101
- {children ?? <XIcon size={13} />}
102
- </button>
103
- ));
104
- AttachmentRemove.displayName = "AttachmentRemove";
105
-
106
- export function AttachmentRetry(
107
- props: ButtonHTMLAttributes<HTMLButtonElement>,
108
- ) {
109
- return (
110
- <button
111
- type="button"
112
- className={cn("sb-attachment__button", props.className)}
113
- aria-label="重试上传"
114
- {...props}
115
- >
116
- <RotateCcwIcon size={13} />
117
- </button>
118
- );
119
- }
120
-
121
- export function AttachmentReorder({
122
- direction,
123
- ...props
124
- }: ButtonHTMLAttributes<HTMLButtonElement> & {
125
- direction: "left" | "right";
126
- }) {
127
- const Icon = direction === "left" ? ArrowLeftIcon : ArrowRightIcon;
128
- return (
129
- <button
130
- type="button"
131
- className={cn("sb-attachment__button", props.className)}
132
- aria-label={direction === "left" ? "附件左移" : "附件右移"}
133
- {...props}
134
- >
135
- <Icon size={13} />
136
- </button>
137
- );
138
- }
@@ -1,236 +0,0 @@
1
- import {
2
- ComposerPrimitive,
3
- unstable_defaultDirectiveFormatter,
4
- unstable_useTriggerPopoverScopeContext,
5
- type Unstable_DirectiveFormatter,
6
- type Unstable_TriggerItem,
7
- } from "@assistant-ui/react";
8
- import {
9
- ChevronLeftIcon,
10
- ChevronRightIcon,
11
- TerminalIcon,
12
- } from "lucide-react";
13
- import {
14
- memo,
15
- type ComponentPropsWithoutRef,
16
- type FC,
17
- } from "react";
18
- import { cn } from "../internal/cn";
19
-
20
- type IconComponent = FC<{ className?: string }>;
21
-
22
- type DirectiveBehaviorProps = {
23
- formatter?: Unstable_DirectiveFormatter;
24
- onInserted?: (item: Unstable_TriggerItem) => void;
25
- };
26
-
27
- type ActionBehaviorProps = {
28
- formatter?: Unstable_DirectiveFormatter;
29
- onExecute: (item: Unstable_TriggerItem) => void;
30
- removeOnExecute?: boolean;
31
- };
32
-
33
- type ComposerTriggerPopoverBaseProps = Omit<
34
- ComponentPropsWithoutRef<
35
- typeof ComposerPrimitive.Unstable_TriggerPopover
36
- >,
37
- "children"
38
- > & {
39
- iconMap?: Record<string, IconComponent>;
40
- fallbackIcon?: IconComponent;
41
- backLabel?: string;
42
- emptyCategoriesLabel?: string;
43
- emptyItemsLabel?: string;
44
- loadingLabel?: string;
45
- };
46
-
47
- export type ComposerTriggerPopoverProps =
48
- ComposerTriggerPopoverBaseProps &
49
- (
50
- | {
51
- directive: DirectiveBehaviorProps;
52
- action?: never;
53
- }
54
- | {
55
- action: ActionBehaviorProps;
56
- directive?: never;
57
- }
58
- );
59
-
60
- function resolveIcon(
61
- iconKey: string | undefined,
62
- iconMap: Record<string, IconComponent> | undefined,
63
- fallback: IconComponent,
64
- ): IconComponent {
65
- return (iconKey && iconMap?.[iconKey]) || fallback;
66
- }
67
-
68
- function Categories({
69
- iconMap,
70
- fallbackIcon,
71
- emptyLabel,
72
- }: {
73
- iconMap?: Record<string, IconComponent>;
74
- fallbackIcon: IconComponent;
75
- emptyLabel: string;
76
- }) {
77
- return (
78
- <ComposerPrimitive.Unstable_TriggerPopoverCategories>
79
- {(categories) => (
80
- <div className="flex flex-col py-1">
81
- {categories.map((category) => {
82
- const Icon = resolveIcon(
83
- category.id,
84
- iconMap,
85
- fallbackIcon,
86
- );
87
- return (
88
- <ComposerPrimitive.Unstable_TriggerPopoverCategoryItem
89
- key={category.id}
90
- categoryId={category.id}
91
- className="flex cursor-pointer items-center justify-between gap-2 px-3 py-2 text-sm outline-none transition-colors hover:bg-accent focus:bg-accent data-[highlighted]:bg-accent"
92
- >
93
- <span className="flex items-center gap-2">
94
- <Icon className="size-4 text-muted-foreground" />
95
- {category.label}
96
- </span>
97
- <ChevronRightIcon className="size-4 text-muted-foreground" />
98
- </ComposerPrimitive.Unstable_TriggerPopoverCategoryItem>
99
- );
100
- })}
101
- {categories.length === 0 && (
102
- <div className="px-3 py-2 text-sm text-muted-foreground">
103
- {emptyLabel}
104
- </div>
105
- )}
106
- </div>
107
- )}
108
- </ComposerPrimitive.Unstable_TriggerPopoverCategories>
109
- );
110
- }
111
-
112
- function Items({
113
- iconMap,
114
- fallbackIcon,
115
- backLabel,
116
- emptyLabel,
117
- loadingLabel,
118
- }: {
119
- iconMap?: Record<string, IconComponent>;
120
- fallbackIcon: IconComponent;
121
- backLabel: string;
122
- emptyLabel: string;
123
- loadingLabel: string;
124
- }) {
125
- const { isLoading } =
126
- unstable_useTriggerPopoverScopeContext();
127
-
128
- return (
129
- <ComposerPrimitive.Unstable_TriggerPopoverItems>
130
- {(items) => (
131
- <div className="flex flex-col">
132
- <ComposerPrimitive.Unstable_TriggerPopoverBack className="flex cursor-pointer items-center gap-1.5 border-b px-3 py-2 text-xs uppercase tracking-wide text-muted-foreground transition-colors hover:bg-accent">
133
- <ChevronLeftIcon className="size-3.5" />
134
- {backLabel}
135
- </ComposerPrimitive.Unstable_TriggerPopoverBack>
136
- <div className="py-1">
137
- {items.map((item, index) => {
138
- const iconKey =
139
- typeof item.metadata?.icon === "string"
140
- ? item.metadata.icon
141
- : undefined;
142
- const Icon = resolveIcon(
143
- iconKey,
144
- iconMap,
145
- fallbackIcon,
146
- );
147
- return (
148
- <ComposerPrimitive.Unstable_TriggerPopoverItem
149
- key={item.id}
150
- item={item}
151
- index={index}
152
- className="flex w-full cursor-pointer flex-col items-start gap-0.5 px-3 py-2 text-start outline-none transition-colors hover:bg-accent focus:bg-accent data-[highlighted]:bg-accent"
153
- >
154
- <span className="flex items-center gap-2 text-sm font-medium">
155
- <Icon className="size-3.5 text-primary" />
156
- {item.label}
157
- </span>
158
- {item.description && (
159
- <span className="ms-5.5 text-xs leading-tight text-muted-foreground">
160
- {item.description}
161
- </span>
162
- )}
163
- </ComposerPrimitive.Unstable_TriggerPopoverItem>
164
- );
165
- })}
166
- {items.length === 0 && (
167
- <div className="px-3 py-2 text-sm text-muted-foreground">
168
- {isLoading ? loadingLabel : emptyLabel}
169
- </div>
170
- )}
171
- </div>
172
- </div>
173
- )}
174
- </ComposerPrimitive.Unstable_TriggerPopoverItems>
175
- );
176
- }
177
-
178
- const ComposerTriggerPopoverImpl: FC<
179
- ComposerTriggerPopoverProps
180
- > = ({
181
- iconMap,
182
- fallbackIcon = TerminalIcon,
183
- backLabel = "Back",
184
- emptyCategoriesLabel = "No items available",
185
- emptyItemsLabel = "No matching items",
186
- loadingLabel = "Loading…",
187
- className,
188
- directive,
189
- action,
190
- ...props
191
- }) => (
192
- <ComposerPrimitive.Unstable_TriggerPopover
193
- className={cn(
194
- "absolute bottom-full start-0 z-50 mb-2 w-64 overflow-hidden rounded-xl border border-border bg-popover text-popover-foreground shadow-lg",
195
- className,
196
- )}
197
- {...props}
198
- >
199
- {directive ? (
200
- <ComposerPrimitive.Unstable_TriggerPopover.Directive
201
- formatter={
202
- directive.formatter ??
203
- unstable_defaultDirectiveFormatter
204
- }
205
- onInserted={directive.onInserted}
206
- />
207
- ) : (
208
- <ComposerPrimitive.Unstable_TriggerPopover.Action
209
- formatter={
210
- action.formatter ?? unstable_defaultDirectiveFormatter
211
- }
212
- onExecute={action.onExecute}
213
- removeOnExecute={action.removeOnExecute}
214
- />
215
- )}
216
- <Categories
217
- iconMap={iconMap}
218
- fallbackIcon={fallbackIcon}
219
- emptyLabel={emptyCategoriesLabel}
220
- />
221
- <Items
222
- iconMap={iconMap}
223
- fallbackIcon={fallbackIcon}
224
- backLabel={backLabel}
225
- emptyLabel={emptyItemsLabel}
226
- loadingLabel={loadingLabel}
227
- />
228
- </ComposerPrimitive.Unstable_TriggerPopover>
229
- );
230
-
231
- ComposerTriggerPopoverImpl.displayName =
232
- "ComposerTriggerPopover";
233
-
234
- export const ComposerTriggerPopover = memo(
235
- ComposerTriggerPopoverImpl,
236
- ) as FC<ComposerTriggerPopoverProps>;