@springbrand/message-panel 0.1.2 → 0.1.3-alpha.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/demo/camel-chat-showcase.tsx +1265 -0
- package/demo/fixtures.ts +292 -0
- package/demo/message-panel-chat-showcase.tsx +250 -0
- package/demo/message-panel-gallery.tsx +389 -0
- package/package.json +6 -16
- package/src/adapters/ai-sdk.ts +32 -0
- package/src/camel/camel-chat-messages.tsx +1435 -0
- package/src/camel/camel-model-select.tsx +88 -0
- package/src/camel/camel-plan-bar.tsx +115 -0
- package/src/camel/camel-prompt-input.tsx +547 -0
- package/src/camel/camel-tool-presentation.tsx +1270 -0
- package/src/camel/camel-turn.ts +334 -0
- package/src/camel/turn-summary-bar.tsx +81 -0
- package/src/chat-summary-panel.tsx +229 -0
- package/src/composer/chat-composer.tsx +216 -0
- package/src/composer/composer-attachments.tsx +138 -0
- package/src/composer/composer-trigger-popover.tsx +236 -0
- package/src/composer/composer.tsx +425 -0
- package/src/composer/drop-controller.ts +80 -0
- package/src/composer/types.ts +79 -0
- package/src/contracts.ts +138 -0
- package/src/conversation.tsx +76 -0
- package/src/internal/cn.ts +3 -0
- package/src/message-panel.tsx +368 -0
- package/src/message.tsx +254 -0
- package/src/parts/index.tsx +1149 -0
- package/src/parts/kind.ts +67 -0
- package/src/parts/plan.ts +64 -0
- package/src/parts/primitives.tsx +439 -0
- package/src/registry.ts +44 -0
- package/src/status.tsx +132 -0
- package/dist/demo/camel-chat-showcase.d.ts +0 -1
- package/dist/demo/camel-chat-showcase.js +0 -1007
- package/dist/demo/fixtures.d.ts +0 -32
- package/dist/demo/fixtures.js +0 -250
- package/dist/demo/index.js +0 -4
- package/dist/demo/message-panel-chat-showcase.d.ts +0 -1
- package/dist/demo/message-panel-chat-showcase.js +0 -114
- package/dist/demo/message-panel-gallery.d.ts +0 -1
- package/dist/demo/message-panel-gallery.js +0 -130
- package/dist/src/adapters/ai-sdk.d.ts +0 -4
- package/dist/src/adapters/ai-sdk.js +0 -25
- package/dist/src/camel/camel-chat-messages.d.ts +0 -44
- package/dist/src/camel/camel-chat-messages.js +0 -421
- package/dist/src/camel/camel-model-select.d.ts +0 -13
- package/dist/src/camel/camel-model-select.js +0 -7
- package/dist/src/camel/camel-plan-bar.d.ts +0 -5
- package/dist/src/camel/camel-plan-bar.js +0 -24
- package/dist/src/camel/camel-prompt-input.d.ts +0 -32
- package/dist/src/camel/camel-prompt-input.js +0 -182
- package/dist/src/camel/camel-tool-presentation.d.ts +0 -21
- package/dist/src/camel/camel-tool-presentation.js +0 -784
- package/dist/src/camel/camel-turn.d.ts +0 -57
- package/dist/src/camel/camel-turn.js +0 -203
- package/dist/src/camel/index.js +0 -7
- package/dist/src/camel/turn-summary-bar.d.ts +0 -8
- package/dist/src/camel/turn-summary-bar.js +0 -12
- package/dist/src/chat-summary-panel.d.ts +0 -22
- package/dist/src/chat-summary-panel.js +0 -26
- package/dist/src/composer/chat-composer.d.ts +0 -4
- package/dist/src/composer/chat-composer.js +0 -90
- package/dist/src/composer/composer-attachments.d.ts +0 -13
- package/dist/src/composer/composer-attachments.js +0 -47
- package/dist/src/composer/composer-trigger-popover.d.ts +0 -31
- package/dist/src/composer/composer-trigger-popover.js +0 -29
- package/dist/src/composer/composer.d.ts +0 -15
- package/dist/src/composer/composer.js +0 -180
- package/dist/src/composer/drop-controller.d.ts +0 -8
- package/dist/src/composer/drop-controller.js +0 -69
- package/dist/src/composer/index.js +0 -6
- package/dist/src/composer/types.d.ts +0 -62
- package/dist/src/composer/types.js +0 -1
- package/dist/src/contracts.d.ts +0 -94
- package/dist/src/contracts.js +0 -1
- package/dist/src/conversation.d.ts +0 -13
- package/dist/src/conversation.js +0 -18
- package/dist/src/index.js +0 -12
- package/dist/src/internal/cn.d.ts +0 -1
- package/dist/src/internal/cn.js +0 -3
- package/dist/src/message-panel.d.ts +0 -4
- package/dist/src/message-panel.js +0 -144
- package/dist/src/message.d.ts +0 -36
- package/dist/src/message.js +0 -83
- package/dist/src/parts/index.d.ts +0 -187
- package/dist/src/parts/index.js +0 -332
- package/dist/src/parts/kind.d.ts +0 -3
- package/dist/src/parts/kind.js +0 -69
- package/dist/src/parts/plan.d.ts +0 -10
- package/dist/src/parts/plan.js +0 -40
- package/dist/src/parts/primitives.d.ts +0 -70
- package/dist/src/parts/primitives.js +0 -153
- package/dist/src/registry.d.ts +0 -4
- package/dist/src/registry.js +0 -31
- package/dist/src/status.d.ts +0 -26
- package/dist/src/status.js +0 -74
- /package/{dist/demo/index.d.ts → demo/index.ts} +0 -0
- /package/{dist/src/camel/index.d.ts → src/camel/index.ts} +0 -0
- /package/{dist/src/composer/index.d.ts → src/composer/index.ts} +0 -0
- /package/{dist/src/index.d.ts → src/index.ts} +0 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { CheckIcon, ChevronDownIcon, ZapIcon } from "lucide-react";
|
|
2
|
+
import { Select as SelectPrimitive } from "radix-ui";
|
|
3
|
+
|
|
4
|
+
export interface CamelModelOption {
|
|
5
|
+
value: string;
|
|
6
|
+
label: string;
|
|
7
|
+
hint?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface CamelModelSelectProps {
|
|
11
|
+
value: string;
|
|
12
|
+
options: readonly CamelModelOption[];
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
label?: string;
|
|
15
|
+
onValueChange: (value: string) => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function CamelModelSelect({
|
|
19
|
+
value,
|
|
20
|
+
options,
|
|
21
|
+
disabled,
|
|
22
|
+
label = "Select model",
|
|
23
|
+
onValueChange,
|
|
24
|
+
}: CamelModelSelectProps) {
|
|
25
|
+
const selected = options.find((option) => option.value === value);
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<SelectPrimitive.Root
|
|
29
|
+
value={value}
|
|
30
|
+
disabled={disabled}
|
|
31
|
+
onValueChange={onValueChange}
|
|
32
|
+
>
|
|
33
|
+
<SelectPrimitive.Trigger
|
|
34
|
+
data-camel-model-select=""
|
|
35
|
+
aria-label={label}
|
|
36
|
+
title={label}
|
|
37
|
+
className="inline-flex h-8 max-w-60 shrink-0 items-center justify-center gap-1.5 rounded-md px-1.5 text-sm font-medium text-foreground/90 outline-none transition-colors hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50"
|
|
38
|
+
>
|
|
39
|
+
<ZapIcon
|
|
40
|
+
className="size-[17px] shrink-0 text-foreground/90"
|
|
41
|
+
strokeWidth={1.8}
|
|
42
|
+
/>
|
|
43
|
+
<SelectPrimitive.Value className="max-w-40 truncate text-[15px]">
|
|
44
|
+
{selected?.label ?? value}
|
|
45
|
+
</SelectPrimitive.Value>
|
|
46
|
+
<SelectPrimitive.Icon asChild>
|
|
47
|
+
<ChevronDownIcon
|
|
48
|
+
className="size-4 shrink-0 text-muted-foreground"
|
|
49
|
+
strokeWidth={1.8}
|
|
50
|
+
/>
|
|
51
|
+
</SelectPrimitive.Icon>
|
|
52
|
+
</SelectPrimitive.Trigger>
|
|
53
|
+
<SelectPrimitive.Portal>
|
|
54
|
+
<SelectPrimitive.Content
|
|
55
|
+
data-camel-model-select-content=""
|
|
56
|
+
position="popper"
|
|
57
|
+
align="start"
|
|
58
|
+
sideOffset={4}
|
|
59
|
+
className="z-50 w-72 overflow-hidden rounded-md border border-border bg-popover text-popover-foreground shadow-md data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95"
|
|
60
|
+
>
|
|
61
|
+
<SelectPrimitive.Viewport className="max-h-80 overflow-y-auto p-1">
|
|
62
|
+
{options.map((option) => (
|
|
63
|
+
<SelectPrimitive.Item
|
|
64
|
+
key={option.value}
|
|
65
|
+
value={option.value}
|
|
66
|
+
className="relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50"
|
|
67
|
+
>
|
|
68
|
+
<SelectPrimitive.ItemText className="w-full">
|
|
69
|
+
<span className="flex min-w-0 items-center justify-between gap-3">
|
|
70
|
+
<span className="truncate">{option.label}</span>
|
|
71
|
+
{option.hint && (
|
|
72
|
+
<span className="shrink-0 text-xs text-muted-foreground">
|
|
73
|
+
{option.hint}
|
|
74
|
+
</span>
|
|
75
|
+
)}
|
|
76
|
+
</span>
|
|
77
|
+
</SelectPrimitive.ItemText>
|
|
78
|
+
<SelectPrimitive.ItemIndicator className="absolute right-2 flex size-4 items-center justify-center">
|
|
79
|
+
<CheckIcon className="size-4" />
|
|
80
|
+
</SelectPrimitive.ItemIndicator>
|
|
81
|
+
</SelectPrimitive.Item>
|
|
82
|
+
))}
|
|
83
|
+
</SelectPrimitive.Viewport>
|
|
84
|
+
</SelectPrimitive.Content>
|
|
85
|
+
</SelectPrimitive.Portal>
|
|
86
|
+
</SelectPrimitive.Root>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type { UIMessage } from "ai";
|
|
2
|
+
import { CheckIcon, ChevronDownIcon, CircleIcon } from "lucide-react";
|
|
3
|
+
import { useId, useMemo, useState } from "react";
|
|
4
|
+
import { cn } from "../internal/cn";
|
|
5
|
+
import { projectLatestPlan } from "../parts/plan";
|
|
6
|
+
|
|
7
|
+
export interface CamelPlanBarProps {
|
|
8
|
+
messages: readonly UIMessage[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function CamelPlanBar({ messages }: CamelPlanBarProps) {
|
|
12
|
+
const [open, setOpen] = useState(false);
|
|
13
|
+
const contentId = useId();
|
|
14
|
+
const steps = useMemo(() => projectLatestPlan(messages), [messages]);
|
|
15
|
+
|
|
16
|
+
if (!steps || steps.length === 0) return null;
|
|
17
|
+
|
|
18
|
+
const doneCount = steps.filter((step) => step.status === "done").length;
|
|
19
|
+
const activeIndex = steps.findIndex((step) => step.status !== "done");
|
|
20
|
+
const allDone = activeIndex === -1;
|
|
21
|
+
const headline = steps[allDone ? steps.length - 1 : activeIndex]!;
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<section
|
|
25
|
+
className="shrink-0 bg-background px-4 pt-2"
|
|
26
|
+
data-camel-plan-bar=""
|
|
27
|
+
aria-label="Task progress"
|
|
28
|
+
>
|
|
29
|
+
<div className="mx-auto w-full max-w-3xl rounded-2xl border border-border bg-card shadow-[0_8px_16px_rgb(0_0_0/0.12)]">
|
|
30
|
+
<button
|
|
31
|
+
type="button"
|
|
32
|
+
className="group flex w-full items-center gap-2 rounded-2xl px-4 py-2.5 text-left"
|
|
33
|
+
aria-expanded={open}
|
|
34
|
+
aria-controls={contentId}
|
|
35
|
+
onClick={() => setOpen((current) => !current)}
|
|
36
|
+
>
|
|
37
|
+
<span className="relative flex h-5 min-w-0 flex-1 items-center gap-2 overflow-hidden">
|
|
38
|
+
{allDone ? (
|
|
39
|
+
<CheckIcon className="size-4 shrink-0 text-success" />
|
|
40
|
+
) : (
|
|
41
|
+
<span className="flex size-4 shrink-0 items-center justify-center">
|
|
42
|
+
<span className="size-2 animate-manus-pulse rounded-full bg-primary" />
|
|
43
|
+
</span>
|
|
44
|
+
)}
|
|
45
|
+
<span
|
|
46
|
+
className="min-w-0 truncate text-sm text-foreground"
|
|
47
|
+
title={headline.text}
|
|
48
|
+
>
|
|
49
|
+
{headline.text}
|
|
50
|
+
</span>
|
|
51
|
+
</span>
|
|
52
|
+
<span className="shrink-0 text-[13px] tabular-nums text-muted-foreground">
|
|
53
|
+
{doneCount} / {steps.length}
|
|
54
|
+
</span>
|
|
55
|
+
<ChevronDownIcon
|
|
56
|
+
className={cn(
|
|
57
|
+
"size-4 shrink-0 text-muted-foreground transition-transform duration-200",
|
|
58
|
+
open && "rotate-180",
|
|
59
|
+
)}
|
|
60
|
+
/>
|
|
61
|
+
</button>
|
|
62
|
+
<div
|
|
63
|
+
id={contentId}
|
|
64
|
+
data-camel-plan-content=""
|
|
65
|
+
data-camel-collapsible-content=""
|
|
66
|
+
data-state={open ? "open" : "closed"}
|
|
67
|
+
aria-hidden={!open}
|
|
68
|
+
inert={!open ? true : undefined}
|
|
69
|
+
>
|
|
70
|
+
<div
|
|
71
|
+
data-camel-collapsible-inner=""
|
|
72
|
+
>
|
|
73
|
+
<div className="px-4 pb-3">
|
|
74
|
+
<p className="text-[13px] text-muted-foreground">Task progress</p>
|
|
75
|
+
<div className="mt-2 max-h-72 space-y-2 overflow-y-auto overflow-x-hidden">
|
|
76
|
+
{steps.map((step, index) => {
|
|
77
|
+
const active = !allDone && index === activeIndex;
|
|
78
|
+
return (
|
|
79
|
+
<div
|
|
80
|
+
key={`${index}:${step.text}`}
|
|
81
|
+
className="flex w-full min-w-0 items-center gap-2"
|
|
82
|
+
>
|
|
83
|
+
<span className="flex h-5 w-4 shrink-0 items-center justify-center">
|
|
84
|
+
{step.status === "done" ? (
|
|
85
|
+
<CheckIcon className="size-4 text-success" />
|
|
86
|
+
) : active ? (
|
|
87
|
+
<span className="size-2 animate-manus-pulse rounded-full bg-primary" />
|
|
88
|
+
) : (
|
|
89
|
+
<CircleIcon className="size-3.5 text-muted-foreground/40" />
|
|
90
|
+
)}
|
|
91
|
+
</span>
|
|
92
|
+
<span
|
|
93
|
+
className={cn(
|
|
94
|
+
"min-w-0 flex-1 truncate text-sm",
|
|
95
|
+
active
|
|
96
|
+
? "font-medium text-foreground"
|
|
97
|
+
: step.status === "done"
|
|
98
|
+
? "text-foreground"
|
|
99
|
+
: "text-muted-foreground",
|
|
100
|
+
)}
|
|
101
|
+
title={step.text}
|
|
102
|
+
>
|
|
103
|
+
{step.text}
|
|
104
|
+
</span>
|
|
105
|
+
</div>
|
|
106
|
+
);
|
|
107
|
+
})}
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
</section>
|
|
114
|
+
);
|
|
115
|
+
}
|