@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
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { BookOpenIcon, BrainIcon, CheckCircle2Icon, ChevronDownIcon, ChevronRightIcon, CircleIcon, ClockIcon, WrenchIcon, XCircleIcon, } from "lucide-react";
|
|
3
|
-
import { createContext, forwardRef, useContext, useMemo, useState, } from "react";
|
|
4
|
-
import { cn } from "../internal/cn";
|
|
5
|
-
import { MessageResponse } from "../message";
|
|
6
|
-
const ReasoningContext = createContext(null);
|
|
7
|
-
export function Reasoning({ isStreaming = false, open, defaultOpen, onOpenChange, duration, className, children, ...props }) {
|
|
8
|
-
const [internalOpen, setInternalOpen] = useState(defaultOpen ?? isStreaming);
|
|
9
|
-
const resolvedOpen = open ?? internalOpen;
|
|
10
|
-
const toggle = () => {
|
|
11
|
-
const next = !resolvedOpen;
|
|
12
|
-
if (open === undefined)
|
|
13
|
-
setInternalOpen(next);
|
|
14
|
-
onOpenChange?.(next);
|
|
15
|
-
};
|
|
16
|
-
const value = useMemo(() => ({ open: resolvedOpen, toggle, isStreaming, duration }), [resolvedOpen, isStreaming, duration]);
|
|
17
|
-
return (_jsx(ReasoningContext.Provider, { value: value, children: _jsx("div", { className: cn("sb-reasoning", className), ...props, children: children }) }));
|
|
18
|
-
}
|
|
19
|
-
export function ReasoningTrigger({ children, className, ...props }) {
|
|
20
|
-
const context = useContext(ReasoningContext);
|
|
21
|
-
if (!context)
|
|
22
|
-
throw new Error("ReasoningTrigger must be used within Reasoning");
|
|
23
|
-
const label = context.isStreaming
|
|
24
|
-
? "Thinking…"
|
|
25
|
-
: context.duration
|
|
26
|
-
? `Thought for ${context.duration}s`
|
|
27
|
-
: "Reasoning";
|
|
28
|
-
return (_jsx("button", { type: "button", className: cn("sb-reasoning__trigger", className), onClick: context.toggle, "aria-expanded": context.open, ...props, children: children ?? (_jsxs(_Fragment, { children: [_jsx(BrainIcon, { size: 16 }), _jsx("span", { children: label }), _jsx(ChevronDownIcon, { size: 16, "aria-hidden": "true" })] })) }));
|
|
29
|
-
}
|
|
30
|
-
export function ReasoningContent({ children, className, ...props }) {
|
|
31
|
-
const context = useContext(ReasoningContext);
|
|
32
|
-
if (!context)
|
|
33
|
-
throw new Error("ReasoningContent must be used within Reasoning");
|
|
34
|
-
if (!context.open)
|
|
35
|
-
return null;
|
|
36
|
-
return (_jsx("div", { className: cn("sb-reasoning__content", className), ...props, children: _jsx(MessageResponse, { streaming: context.isStreaming, children: children }) }));
|
|
37
|
-
}
|
|
38
|
-
const toolStatus = {
|
|
39
|
-
"approval-requested": {
|
|
40
|
-
label: "Awaiting approval",
|
|
41
|
-
icon: _jsx(ClockIcon, { size: 14 }),
|
|
42
|
-
tone: "warning",
|
|
43
|
-
},
|
|
44
|
-
"approval-responded": {
|
|
45
|
-
label: "Responded",
|
|
46
|
-
icon: _jsx(CheckCircle2Icon, { size: 14 }),
|
|
47
|
-
tone: "info",
|
|
48
|
-
},
|
|
49
|
-
"input-available": {
|
|
50
|
-
label: "Running",
|
|
51
|
-
icon: _jsx(ClockIcon, { size: 14 }),
|
|
52
|
-
tone: "running",
|
|
53
|
-
},
|
|
54
|
-
"input-streaming": {
|
|
55
|
-
label: "Pending",
|
|
56
|
-
icon: _jsx(CircleIcon, { size: 14 }),
|
|
57
|
-
tone: "running",
|
|
58
|
-
},
|
|
59
|
-
"output-available": {
|
|
60
|
-
label: "Completed",
|
|
61
|
-
icon: _jsx(CheckCircle2Icon, { size: 14 }),
|
|
62
|
-
tone: "success",
|
|
63
|
-
},
|
|
64
|
-
"output-denied": {
|
|
65
|
-
label: "Denied",
|
|
66
|
-
icon: _jsx(XCircleIcon, { size: 14 }),
|
|
67
|
-
tone: "warning",
|
|
68
|
-
},
|
|
69
|
-
"output-error": {
|
|
70
|
-
label: "Error",
|
|
71
|
-
icon: _jsx(XCircleIcon, { size: 14 }),
|
|
72
|
-
tone: "error",
|
|
73
|
-
},
|
|
74
|
-
};
|
|
75
|
-
export function getStatusBadge(status) {
|
|
76
|
-
const value = toolStatus[status];
|
|
77
|
-
return (_jsxs("span", { className: "sb-tool-line__status", "data-tone": value.tone, children: [value.icon, value.label] }));
|
|
78
|
-
}
|
|
79
|
-
export const Tool = forwardRef(({ className, ...props }, ref) => (_jsx("details", { ref: ref, className: cn("sb-tool-line", className), ...props })));
|
|
80
|
-
Tool.displayName = "Tool";
|
|
81
|
-
export function ToolHeader({ className, title, type, state, toolName, ...props }) {
|
|
82
|
-
const derived = type === "dynamic-tool"
|
|
83
|
-
? toolName ?? "tool"
|
|
84
|
-
: type.split("-").slice(1).join("-");
|
|
85
|
-
return (_jsxs("summary", { className: cn("sb-tool-line__trigger", className), ...props, children: [_jsx(WrenchIcon, { size: 16 }), _jsx("span", { children: title ?? derived }), state !== "output-available" && getStatusBadge(state), _jsx(ChevronRightIcon, { size: 16, className: "sb-tool-line__chevron", "aria-hidden": "true" })] }));
|
|
86
|
-
}
|
|
87
|
-
export const ToolContent = forwardRef(({ className, ...props }, ref) => (_jsx("div", { ref: ref, className: cn("sb-tool-line__details", className), ...props })));
|
|
88
|
-
ToolContent.displayName = "ToolContent";
|
|
89
|
-
export function ToolInput({ input, className, ...props }) {
|
|
90
|
-
return (_jsx("pre", { className: cn("sb-terminal", className), ...props, children: JSON.stringify(input, null, 2) }));
|
|
91
|
-
}
|
|
92
|
-
export function ToolOutput({ output, errorText, className, ...props }) {
|
|
93
|
-
if (output == null && !errorText)
|
|
94
|
-
return null;
|
|
95
|
-
const content = typeof output === "string"
|
|
96
|
-
? output
|
|
97
|
-
: output == null
|
|
98
|
-
? ""
|
|
99
|
-
: JSON.stringify(output, null, 2);
|
|
100
|
-
return (_jsx("pre", { className: cn("sb-terminal", className), "data-error": errorText ? "true" : undefined, ...props, children: errorText || content }));
|
|
101
|
-
}
|
|
102
|
-
const ConfirmationContext = createContext(null);
|
|
103
|
-
export function Confirmation({ state, approval, className, ...props }) {
|
|
104
|
-
const value = useMemo(() => ({ state, approval }), [state, approval]);
|
|
105
|
-
return (_jsx(ConfirmationContext.Provider, { value: value, children: _jsx("div", { className: cn("sb-confirmation", className), ...props }) }));
|
|
106
|
-
}
|
|
107
|
-
function useConfirmation() {
|
|
108
|
-
const context = useContext(ConfirmationContext);
|
|
109
|
-
if (!context)
|
|
110
|
-
throw new Error("Confirmation child must be used within Confirmation");
|
|
111
|
-
return context;
|
|
112
|
-
}
|
|
113
|
-
export const ConfirmationTitle = ({ className, ...props }) => (_jsx("div", { className: cn("sb-confirmation__title", className), ...props }));
|
|
114
|
-
export function ConfirmationRequest({ children }) {
|
|
115
|
-
const { state } = useConfirmation();
|
|
116
|
-
return state === "approval-requested" || state === "pending" ? children : null;
|
|
117
|
-
}
|
|
118
|
-
export function ConfirmationAccepted({ children }) {
|
|
119
|
-
const { state, approval } = useConfirmation();
|
|
120
|
-
return state === "confirmed" || approval?.approved === true ? children : null;
|
|
121
|
-
}
|
|
122
|
-
export function ConfirmationRejected({ children }) {
|
|
123
|
-
const { state, approval } = useConfirmation();
|
|
124
|
-
return state === "cancelled" ||
|
|
125
|
-
state === "output-denied" ||
|
|
126
|
-
approval?.approved === false
|
|
127
|
-
? children
|
|
128
|
-
: null;
|
|
129
|
-
}
|
|
130
|
-
export function ConfirmationActions({ className, ...props }) {
|
|
131
|
-
const { state } = useConfirmation();
|
|
132
|
-
if (state !== "approval-requested" && state !== "pending")
|
|
133
|
-
return null;
|
|
134
|
-
return (_jsx("div", { className: cn("sb-confirmation__actions", className), ...props }));
|
|
135
|
-
}
|
|
136
|
-
export const ConfirmationAction = forwardRef(({ className, ...props }, ref) => (_jsx("button", { ref: ref, type: "button", className: cn("sb-button", className), ...props })));
|
|
137
|
-
ConfirmationAction.displayName = "ConfirmationAction";
|
|
138
|
-
export const Plan = forwardRef(({ className, isStreaming, ...props }, ref) => (_jsx("div", { ref: ref, className: cn("sb-plan", className), "data-streaming": isStreaming ? "true" : undefined, ...props })));
|
|
139
|
-
Plan.displayName = "Plan";
|
|
140
|
-
export const PlanHeader = ({ className, ...props }) => (_jsx("div", { className: cn("sb-plan__header", className), ...props }));
|
|
141
|
-
export const PlanTitle = ({ className, ...props }) => (_jsx("h3", { className: cn("sb-plan__title", className), ...props }));
|
|
142
|
-
export const PlanDescription = ({ className, ...props }) => (_jsx("p", { className: cn("sb-plan__description", className), ...props }));
|
|
143
|
-
export const PlanContent = ({ className, ...props }) => (_jsx("div", { className: cn("sb-plan__content", className), ...props }));
|
|
144
|
-
export const PlanFooter = ({ className, ...props }) => (_jsx("div", { className: cn("sb-plan__footer", className), ...props }));
|
|
145
|
-
export const Sources = forwardRef(({ className, ...props }, ref) => (_jsx("details", { ref: ref, className: cn("sb-sources", className), ...props })));
|
|
146
|
-
Sources.displayName = "Sources";
|
|
147
|
-
export function SourcesTrigger({ count, children, className, ...props }) {
|
|
148
|
-
return (_jsx("summary", { className: cn("sb-sources__trigger", className), ...props, children: children ?? (_jsxs(_Fragment, { children: [_jsxs("span", { children: ["\u6765\u6E90 ", count, " \u4E2A"] }), _jsx(ChevronDownIcon, { size: 15 })] })) }));
|
|
149
|
-
}
|
|
150
|
-
export const SourcesContent = ({ className, ...props }) => (_jsx("div", { className: cn("sb-sources__content", className), ...props }));
|
|
151
|
-
export function Source({ title, children, ...props }) {
|
|
152
|
-
return (_jsx("a", { target: "_blank", rel: "noreferrer", ...props, children: children ?? (_jsxs(_Fragment, { children: [_jsx(BookOpenIcon, { size: 14 }), _jsx("span", { children: title })] })) }));
|
|
153
|
-
}
|
package/dist/src/registry.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { PartRendererDefinition, PartRendererRegistry } from "./contracts";
|
|
2
|
-
export declare function createPartRendererRegistry(definitions: readonly PartRendererDefinition[]): PartRendererRegistry;
|
|
3
|
-
export declare function mergePartRendererRegistries(...registries: Array<PartRendererRegistry | undefined>): PartRendererRegistry;
|
|
4
|
-
export declare const defaultPartRendererRegistry: PartRendererRegistry;
|
package/dist/src/registry.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { DefaultPartRenderer } from "./parts";
|
|
2
|
-
export function createPartRendererRegistry(definitions) {
|
|
3
|
-
const stable = [...definitions];
|
|
4
|
-
return {
|
|
5
|
-
names: stable.map((definition) => definition.name),
|
|
6
|
-
resolve(part) {
|
|
7
|
-
return stable.find((definition) => definition.match(part))?.component;
|
|
8
|
-
},
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
export function mergePartRendererRegistries(...registries) {
|
|
12
|
-
const resolved = registries.filter((registry) => registry !== undefined);
|
|
13
|
-
return {
|
|
14
|
-
names: resolved.flatMap((registry) => registry.names),
|
|
15
|
-
resolve(part) {
|
|
16
|
-
for (const registry of resolved) {
|
|
17
|
-
const component = registry.resolve(part);
|
|
18
|
-
if (component)
|
|
19
|
-
return component;
|
|
20
|
-
}
|
|
21
|
-
return undefined;
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
export const defaultPartRendererRegistry = createPartRendererRegistry([
|
|
26
|
-
{
|
|
27
|
-
name: "default",
|
|
28
|
-
match: () => true,
|
|
29
|
-
component: DefaultPartRenderer,
|
|
30
|
-
},
|
|
31
|
-
]);
|
package/dist/src/status.d.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { type OrbState } from "thinking-orbs";
|
|
2
|
-
import type { MessagePanelStatus } from "./contracts";
|
|
3
|
-
export type PanelVisualState = "empty" | "hydrating" | "thinking" | "streaming" | "ready" | "error" | "recovering" | "background";
|
|
4
|
-
export declare function derivePanelVisualState({ messageCount, status, isHydrating, isRecovering, isServerStreaming, }: {
|
|
5
|
-
messageCount: number;
|
|
6
|
-
status: MessagePanelStatus;
|
|
7
|
-
isHydrating?: boolean;
|
|
8
|
-
isRecovering?: boolean;
|
|
9
|
-
isServerStreaming?: boolean;
|
|
10
|
-
}): PanelVisualState;
|
|
11
|
-
export declare function ThinkingIndicator({ label, state, className, }: {
|
|
12
|
-
label?: string;
|
|
13
|
-
state?: OrbState;
|
|
14
|
-
className?: string;
|
|
15
|
-
}): import("react").JSX.Element;
|
|
16
|
-
export declare function deriveThinkingActivity(part?: unknown): {
|
|
17
|
-
state: OrbState;
|
|
18
|
-
label: string;
|
|
19
|
-
};
|
|
20
|
-
export declare function TopLoadingBar({ status }: {
|
|
21
|
-
status: MessagePanelStatus;
|
|
22
|
-
}): import("react").JSX.Element | null;
|
|
23
|
-
export declare function PanelStatus({ kind, children, }: {
|
|
24
|
-
kind: "hydrating" | "recovering" | "background" | "error";
|
|
25
|
-
children: React.ReactNode;
|
|
26
|
-
}): import("react").JSX.Element;
|
package/dist/src/status.js
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useRef, useState } from "react";
|
|
3
|
-
import { ThinkingOrb } from "thinking-orbs";
|
|
4
|
-
import { cn } from "./internal/cn";
|
|
5
|
-
import { resolvePartKind, toolNameOfPart } from "./parts/kind";
|
|
6
|
-
export function derivePanelVisualState({ messageCount, status, isHydrating = false, isRecovering = false, isServerStreaming = false, }) {
|
|
7
|
-
if (isHydrating)
|
|
8
|
-
return "hydrating";
|
|
9
|
-
if (status === "error")
|
|
10
|
-
return "error";
|
|
11
|
-
if (isRecovering)
|
|
12
|
-
return "recovering";
|
|
13
|
-
if (isServerStreaming)
|
|
14
|
-
return "background";
|
|
15
|
-
if (status === "submitted")
|
|
16
|
-
return "thinking";
|
|
17
|
-
if (status === "streaming")
|
|
18
|
-
return "streaming";
|
|
19
|
-
return messageCount === 0 ? "empty" : "ready";
|
|
20
|
-
}
|
|
21
|
-
export function ThinkingIndicator({ label = "Thinking…", state = "solving", className, }) {
|
|
22
|
-
return (_jsxs("div", { className: cn("sb-thinking", className), role: "status", "aria-label": label, children: [_jsx(ThinkingOrb, { state: state, size: 20, "aria-hidden": "true" }), _jsx("span", { children: label })] }));
|
|
23
|
-
}
|
|
24
|
-
export function deriveThinkingActivity(part) {
|
|
25
|
-
const kind = resolvePartKind(part);
|
|
26
|
-
const toolName = toolNameOfPart(part);
|
|
27
|
-
if (kind === "reasoning")
|
|
28
|
-
return { state: "solving", label: "Reasoning…" };
|
|
29
|
-
if (kind === "text")
|
|
30
|
-
return { state: "composing", label: "Composing answer…" };
|
|
31
|
-
if (["plan", "image", "chart", "dashboard"].includes(kind ?? "") ||
|
|
32
|
-
(toolName != null &&
|
|
33
|
-
/(?:^|[_-])(?:image|chart|artifact|render|write_file)(?:$|[_-])/i.test(toolName))) {
|
|
34
|
-
return { state: "shaping", label: "Shaping result…" };
|
|
35
|
-
}
|
|
36
|
-
if (toolName != null &&
|
|
37
|
-
/(?:^|[_-])(?:search|fetch|browse|browser|web)(?:$|[_-])/i.test(toolName)) {
|
|
38
|
-
return { state: "searching", label: "Searching…" };
|
|
39
|
-
}
|
|
40
|
-
if (toolName != null) {
|
|
41
|
-
return {
|
|
42
|
-
state: "working",
|
|
43
|
-
label: `Running ${toolName.replaceAll("_", " ")}…`,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
return part === undefined
|
|
47
|
-
? { state: "solving", label: "Thinking…" }
|
|
48
|
-
: { state: "working", label: "Working…" };
|
|
49
|
-
}
|
|
50
|
-
export function TopLoadingBar({ status }) {
|
|
51
|
-
const [phase, setPhase] = useState("idle");
|
|
52
|
-
const previous = useRef(status);
|
|
53
|
-
useEffect(() => {
|
|
54
|
-
const before = previous.current;
|
|
55
|
-
previous.current = status;
|
|
56
|
-
if (status === "submitted") {
|
|
57
|
-
setPhase("loading");
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
if (before === "submitted" && status === "streaming") {
|
|
61
|
-
setPhase("done");
|
|
62
|
-
const timeout = window.setTimeout(() => setPhase("idle"), 500);
|
|
63
|
-
return () => window.clearTimeout(timeout);
|
|
64
|
-
}
|
|
65
|
-
if (status !== "streaming")
|
|
66
|
-
setPhase("idle");
|
|
67
|
-
}, [status]);
|
|
68
|
-
if (phase === "idle")
|
|
69
|
-
return null;
|
|
70
|
-
return (_jsx("div", { className: "sb-top-loading", role: "progressbar", "aria-label": "\u7B49\u5F85\u54CD\u5E94", children: _jsx("span", { "data-phase": phase }) }));
|
|
71
|
-
}
|
|
72
|
-
export function PanelStatus({ kind, children, }) {
|
|
73
|
-
return (_jsxs("div", { className: "sb-panel-status", "data-kind": kind, role: kind === "error" ? "alert" : "status", children: [_jsx("span", { "aria-hidden": "true" }), children] }));
|
|
74
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|