@calliopelabs/ui 0.14.0 → 0.16.0
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 +142 -1
- package/dist/agent/AgentChat.d.ts +8 -1
- package/dist/agent/AgentChat.js +43 -2
- package/dist/agent/WorkflowRenderers.d.ts +61 -0
- package/dist/agent/WorkflowRenderers.js +102 -0
- package/dist/agent/controller.d.ts +19 -0
- package/dist/agent/controller.js +33 -0
- package/dist/agent/copilotkit/CopilotKitAgentProvider.js +2 -2
- package/dist/agent/index.d.ts +4 -2
- package/dist/agent/index.js +3 -1
- package/dist/agent/mock.d.ts +26 -4
- package/dist/agent/mock.js +68 -37
- package/dist/agent/renderers.d.ts +49 -0
- package/dist/agent/renderers.js +27 -0
- package/dist/appearance/brands.d.ts +17 -0
- package/dist/appearance/brands.js +14 -0
- package/dist/chat/MessageBubble.js +1 -1
- package/dist/chat/MessageList.d.ts +9 -2
- package/dist/chat/MessageList.js +11 -8
- package/dist/css/appearance.js +1 -1
- package/dist/css/calliope.css +5 -0
- package/dist/css/tokens.css +5 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +6 -1
- package/dist/primitives/Badge.d.ts +14 -0
- package/dist/primitives/Badge.js +25 -0
- package/dist/primitives/ContextMenu.d.ts +18 -0
- package/dist/primitives/ContextMenu.js +34 -0
- package/dist/primitives/ScrollArea.d.ts +16 -0
- package/dist/primitives/ScrollArea.js +11 -0
- package/dist/primitives/Toast.d.ts +37 -0
- package/dist/primitives/Toast.js +43 -0
- package/dist/primitives/Tooltip.d.ts +16 -0
- package/dist/primitives/Tooltip.js +26 -0
- package/dist/provider/messages.d.ts +69 -0
- package/dist/provider/messages.js +60 -0
- package/dist/theme/css-layer.js +2 -1
- package/dist/theme/tokens.generated.d.ts +3 -0
- package/dist/theme/tokens.generated.js +3 -0
- package/dist/workbench/FileBrowser.d.ts +62 -0
- package/dist/workbench/FileBrowser.js +117 -0
- package/dist/workbench/FileGrid.d.ts +13 -0
- package/dist/workbench/FileGrid.js +114 -0
- package/dist/workbench/FileIcon.d.ts +10 -0
- package/dist/workbench/FileIcon.js +24 -0
- package/dist/workbench/FileList.d.ts +35 -0
- package/dist/workbench/FileList.js +160 -0
- package/dist/workbench/FilePreview.d.ts +66 -0
- package/dist/workbench/FilePreview.js +108 -0
- package/dist/workbench/FileTree.d.ts +37 -0
- package/dist/workbench/FileTree.js +218 -0
- package/dist/workbench/UploadDropzone.d.ts +52 -0
- package/dist/workbench/UploadDropzone.js +115 -0
- package/dist/workbench/dnd.d.ts +17 -0
- package/dist/workbench/dnd.js +77 -0
- package/dist/workbench/index.d.ts +16 -0
- package/dist/workbench/index.js +16 -0
- package/dist/workbench/model.d.ts +72 -0
- package/dist/workbench/model.js +214 -0
- package/dist/workbench/selection.d.ts +16 -0
- package/dist/workbench/selection.js +46 -0
- package/dist/workbench/typeahead.d.ts +15 -0
- package/dist/workbench/typeahead.js +22 -0
- package/package.json +5 -1
package/dist/agent/mock.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Agents from functions: `createFunctionAgent` adapts any function that
|
|
3
|
+
* produces AG-UI events (a non-AG-UI backend, wrapped), and `createMockAgent`
|
|
4
|
+
* plays recorded turns for Storybook and tests. Both are a real
|
|
5
|
+
* `@ag-ui/client` `HttpAgent` whose fetch is answered in the page as a
|
|
6
|
+
* server-sent event stream, never over the network.
|
|
6
7
|
*/
|
|
7
8
|
import { HttpAgent } from "@ag-ui/client";
|
|
8
9
|
import { type Message, type RunAgentInput } from "@ag-ui/core";
|
|
@@ -23,6 +24,27 @@ export interface MockAgentOptions {
|
|
|
23
24
|
/** Every request's input, for a test to read. */
|
|
24
25
|
onRequest?: (input: RunAgentInput) => void;
|
|
25
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* The events of one run, as a function produces them: a list, a promise of
|
|
29
|
+
* one, or an async iterable that yields them as they come. The run's start
|
|
30
|
+
* and finish are added unless the function emits them.
|
|
31
|
+
*/
|
|
32
|
+
export type AgentRunFunction = (input: RunAgentInput, signal: AbortSignal) => Iterable<AgUiEvent> | AsyncIterable<AgUiEvent> | Promise<Iterable<AgUiEvent>>;
|
|
33
|
+
export interface FunctionAgentOptions {
|
|
34
|
+
threadId?: string;
|
|
35
|
+
initialMessages?: Message[];
|
|
36
|
+
initialState?: unknown;
|
|
37
|
+
/** Pause before each event, in ms (a recording played back at reading speed). */
|
|
38
|
+
delay?: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* An AG-UI agent from a function: the adapter for a backend that does not
|
|
42
|
+
* speak AG-UI yet (a request and response endpoint, a custom stream), and
|
|
43
|
+
* the base of `createMockAgent`. It is a real `HttpAgent` whose transport is
|
|
44
|
+
* the function, so the client's parser, verifier and message bookkeeping run
|
|
45
|
+
* as they do against a live endpoint, and `stop` aborts `signal`.
|
|
46
|
+
*/
|
|
47
|
+
export declare function createFunctionAgent(run: AgentRunFunction, { threadId, initialMessages, initialState, delay }?: FunctionAgentOptions): HttpAgent;
|
|
26
48
|
/** An agent that answers from `turns`, streaming each event as SSE. */
|
|
27
49
|
export declare function createMockAgent({ turns, delay, threadId, initialMessages, initialState, onRequest, }: MockAgentOptions): HttpAgent;
|
|
28
50
|
/** An assistant's streamed reply, in `chunks`, as the events that make it. */
|
package/dist/agent/mock.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Agents from functions: `createFunctionAgent` adapts any function that
|
|
3
|
+
* produces AG-UI events (a non-AG-UI backend, wrapped), and `createMockAgent`
|
|
4
|
+
* plays recorded turns for Storybook and tests. Both are a real
|
|
5
|
+
* `@ag-ui/client` `HttpAgent` whose fetch is answered in the page as a
|
|
6
|
+
* server-sent event stream, never over the network.
|
|
6
7
|
*/
|
|
7
8
|
import { HttpAgent } from "@ag-ui/client";
|
|
8
9
|
import { EventType } from "@ag-ui/core";
|
|
@@ -16,56 +17,66 @@ const sleep = (ms, signal) => new Promise((resolve, reject) => {
|
|
|
16
17
|
reject(new DOMException("Aborted", "AbortError"));
|
|
17
18
|
}, { once: true });
|
|
18
19
|
});
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
...events,
|
|
25
|
-
...(ends
|
|
26
|
-
? []
|
|
27
|
-
: [
|
|
28
|
-
{
|
|
29
|
-
type: EventType.RUN_FINISHED,
|
|
30
|
-
threadId: input.threadId,
|
|
31
|
-
runId: input.runId,
|
|
32
|
-
},
|
|
33
|
-
]),
|
|
34
|
-
];
|
|
20
|
+
async function* eventsOf(output) {
|
|
21
|
+
if (Symbol.asyncIterator in output)
|
|
22
|
+
yield* output;
|
|
23
|
+
else
|
|
24
|
+
yield* output;
|
|
35
25
|
}
|
|
36
|
-
/**
|
|
37
|
-
|
|
38
|
-
|
|
26
|
+
/**
|
|
27
|
+
* An AG-UI agent from a function: the adapter for a backend that does not
|
|
28
|
+
* speak AG-UI yet (a request and response endpoint, a custom stream), and
|
|
29
|
+
* the base of `createMockAgent`. It is a real `HttpAgent` whose transport is
|
|
30
|
+
* the function, so the client's parser, verifier and message bookkeeping run
|
|
31
|
+
* as they do against a live endpoint, and `stop` aborts `signal`.
|
|
32
|
+
*/
|
|
33
|
+
export function createFunctionAgent(run, { threadId, initialMessages, initialState, delay = 0 } = {}) {
|
|
39
34
|
const fetch = async (_url, init) => {
|
|
40
35
|
const input = JSON.parse(String(init.body));
|
|
41
|
-
|
|
42
|
-
const index = turn++;
|
|
43
|
-
const script = turns[Math.min(index, turns.length - 1)] ?? [];
|
|
44
|
-
const events = framed(input, typeof script === "function" ? script(input, index) : script);
|
|
45
|
-
const signal = init.signal;
|
|
36
|
+
const signal = init.signal ?? new AbortController().signal;
|
|
46
37
|
const body = new ReadableStream({
|
|
47
38
|
async start(controller) {
|
|
48
39
|
try {
|
|
49
|
-
|
|
40
|
+
let ended = false;
|
|
41
|
+
controller.enqueue(encoder.encode(`data: ${JSON.stringify({ type: EventType.RUN_STARTED, threadId: input.threadId, runId: input.runId })}\n\n`));
|
|
42
|
+
const output = run(input, signal);
|
|
43
|
+
const source = output instanceof Promise ? await output : output;
|
|
44
|
+
for await (const event of eventsOf(source)) {
|
|
50
45
|
if (delay > 0)
|
|
51
46
|
await sleep(delay, signal);
|
|
52
|
-
|
|
53
|
-
await Promise.resolve();
|
|
54
|
-
if (signal?.aborted)
|
|
47
|
+
if (signal.aborted)
|
|
55
48
|
throw new DOMException("Aborted", "AbortError");
|
|
49
|
+
if (event.type === EventType.RUN_STARTED)
|
|
50
|
+
continue;
|
|
51
|
+
if (event.type === EventType.RUN_FINISHED || event.type === EventType.RUN_ERROR)
|
|
52
|
+
ended = true;
|
|
56
53
|
controller.enqueue(encoder.encode(`data: ${JSON.stringify(event)}\n\n`));
|
|
57
54
|
}
|
|
55
|
+
if (!ended) {
|
|
56
|
+
const finished = {
|
|
57
|
+
type: EventType.RUN_FINISHED,
|
|
58
|
+
threadId: input.threadId,
|
|
59
|
+
runId: input.runId,
|
|
60
|
+
};
|
|
61
|
+
controller.enqueue(encoder.encode(`data: ${JSON.stringify(finished)}\n\n`));
|
|
62
|
+
}
|
|
58
63
|
controller.close();
|
|
59
64
|
}
|
|
60
65
|
catch (error) {
|
|
61
|
-
|
|
66
|
+
if (signal.aborted)
|
|
67
|
+
controller.error(error);
|
|
68
|
+
else {
|
|
69
|
+
const failed = {
|
|
70
|
+
type: EventType.RUN_ERROR,
|
|
71
|
+
message: error instanceof Error ? error.message : String(error),
|
|
72
|
+
};
|
|
73
|
+
controller.enqueue(encoder.encode(`data: ${JSON.stringify(failed)}\n\n`));
|
|
74
|
+
controller.close();
|
|
75
|
+
}
|
|
62
76
|
}
|
|
63
77
|
},
|
|
64
78
|
});
|
|
65
|
-
return new Response(body, {
|
|
66
|
-
status: 200,
|
|
67
|
-
headers: { "content-type": "text/event-stream" },
|
|
68
|
-
});
|
|
79
|
+
return new Response(body, { status: 200, headers: { "content-type": "text/event-stream" } });
|
|
69
80
|
};
|
|
70
81
|
return new HttpAgent({
|
|
71
82
|
url: "https://agent.invalid/agui",
|
|
@@ -75,6 +86,26 @@ export function createMockAgent({ turns, delay = 30, threadId, initialMessages,
|
|
|
75
86
|
...(initialState !== undefined ? { initialState: initialState } : {}),
|
|
76
87
|
});
|
|
77
88
|
}
|
|
89
|
+
/** An agent that answers from `turns`, streaming each event as SSE. */
|
|
90
|
+
export function createMockAgent({ turns, delay = 30, threadId, initialMessages, initialState, onRequest, }) {
|
|
91
|
+
let turn = 0;
|
|
92
|
+
return createFunctionAgent(async function* (input) {
|
|
93
|
+
onRequest?.(input);
|
|
94
|
+
const index = turn++;
|
|
95
|
+
const script = turns[Math.min(index, turns.length - 1)] ?? [];
|
|
96
|
+
const events = typeof script === "function" ? script(input, index) : script;
|
|
97
|
+
// Yield once first, so even a delay of 0 streams instead of arriving in one piece.
|
|
98
|
+
for (const event of events) {
|
|
99
|
+
await Promise.resolve();
|
|
100
|
+
yield event;
|
|
101
|
+
}
|
|
102
|
+
}, {
|
|
103
|
+
delay,
|
|
104
|
+
...(threadId ? { threadId } : {}),
|
|
105
|
+
...(initialMessages ? { initialMessages } : {}),
|
|
106
|
+
...(initialState !== undefined ? { initialState } : {}),
|
|
107
|
+
});
|
|
108
|
+
}
|
|
78
109
|
/** An assistant's streamed reply, in `chunks`, as the events that make it. */
|
|
79
110
|
export function textEvents(messageId, ...chunks) {
|
|
80
111
|
return [
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
import { type AgUiInterrupt, type ChatToolCall } from "../chat/model.js";
|
|
3
|
+
import type { CalliopeAgentApi } from "./AgentProvider.js";
|
|
4
|
+
import type { AgentToolRenderProps } from "./tool.js";
|
|
5
|
+
/** What a tool renderer draws from: the call, its arguments and result, and the agent. */
|
|
6
|
+
export interface ToolRendererProps<Args = unknown> extends AgentToolRenderProps<Args> {
|
|
7
|
+
/** The result parsed as JSON, or as text when it is not JSON. */
|
|
8
|
+
result: unknown;
|
|
9
|
+
agent: CalliopeAgentApi;
|
|
10
|
+
}
|
|
11
|
+
/** What a custom-event renderer draws from: the latest value of its event, and the agent. */
|
|
12
|
+
export interface CustomRendererProps<Value = unknown> {
|
|
13
|
+
name: string;
|
|
14
|
+
value: Value;
|
|
15
|
+
/** Every value the event has had under this key, oldest first. */
|
|
16
|
+
history: readonly Value[];
|
|
17
|
+
agent: CalliopeAgentApi;
|
|
18
|
+
}
|
|
19
|
+
/** What an interrupt renderer draws from: the open interrupt and how to answer it. */
|
|
20
|
+
export interface InterruptRendererProps {
|
|
21
|
+
interrupt: AgUiInterrupt;
|
|
22
|
+
/** Answers it; the run resumes once every open interrupt has an answer. */
|
|
23
|
+
resolve: (payload?: unknown) => void;
|
|
24
|
+
cancel: () => void;
|
|
25
|
+
agent: CalliopeAgentApi;
|
|
26
|
+
}
|
|
27
|
+
export interface StateRendererProps<State = unknown> {
|
|
28
|
+
state: State;
|
|
29
|
+
setState: (state: State) => void;
|
|
30
|
+
agent: CalliopeAgentApi;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Generative UI: host components for what the agent emits. A tool call by
|
|
34
|
+
* name (the agent's backend tools as well as the browser's), an AG-UI
|
|
35
|
+
* `CUSTOM` event by name (drawn where it arrived; an event carrying an `id`
|
|
36
|
+
* in its value replaces its earlier values in place, so progress updates
|
|
37
|
+
* one card), an interrupt by reason, and the shared state.
|
|
38
|
+
*/
|
|
39
|
+
export interface AgentRenderers {
|
|
40
|
+
tools?: Readonly<Record<string, React.ComponentType<ToolRendererProps<any>>>>;
|
|
41
|
+
custom?: Readonly<Record<string, React.ComponentType<CustomRendererProps<any>>>>;
|
|
42
|
+
interrupts?: Readonly<Record<string, React.ComponentType<InterruptRendererProps>>>;
|
|
43
|
+
/** Draws the shared state above the conversation. */
|
|
44
|
+
state?: React.ComponentType<StateRendererProps<any>>;
|
|
45
|
+
}
|
|
46
|
+
/** Several registries as one; a later one wins a name. */
|
|
47
|
+
export declare function mergeRenderers(...registries: (AgentRenderers | undefined)[]): AgentRenderers;
|
|
48
|
+
/** A tool's result as a renderer reads it. */
|
|
49
|
+
export declare function parseResult(call: ChatToolCall): unknown;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { parseToolCallArgs } from "../chat/model.js";
|
|
2
|
+
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
3
|
+
/** Several registries as one; a later one wins a name. */
|
|
4
|
+
export function mergeRenderers(...registries) {
|
|
5
|
+
const merged = {
|
|
6
|
+
tools: {},
|
|
7
|
+
custom: {},
|
|
8
|
+
interrupts: {},
|
|
9
|
+
};
|
|
10
|
+
for (const r of registries) {
|
|
11
|
+
if (!r)
|
|
12
|
+
continue;
|
|
13
|
+
merged.tools = { ...merged.tools, ...r.tools };
|
|
14
|
+
merged.custom = { ...merged.custom, ...r.custom };
|
|
15
|
+
merged.interrupts = { ...merged.interrupts, ...r.interrupts };
|
|
16
|
+
if (r.state)
|
|
17
|
+
merged.state = r.state;
|
|
18
|
+
}
|
|
19
|
+
return merged;
|
|
20
|
+
}
|
|
21
|
+
/** A tool's result as a renderer reads it. */
|
|
22
|
+
export function parseResult(call) {
|
|
23
|
+
if (call.result === undefined)
|
|
24
|
+
return undefined;
|
|
25
|
+
const parsed = parseToolCallArgs(call.result);
|
|
26
|
+
return parsed === undefined ? call.result : parsed;
|
|
27
|
+
}
|
|
@@ -163,6 +163,23 @@ export declare const loadrBrand: {
|
|
|
163
163
|
readonly light: "paper";
|
|
164
164
|
};
|
|
165
165
|
};
|
|
166
|
+
/**
|
|
167
|
+
* Calliope AI Deep Data Agent: the family amber on a warm umber sidebar, with
|
|
168
|
+
* charcoal and mist as its defaults. A separate product from Chat Studio, and
|
|
169
|
+
* kept visibly apart from it (Studio blue on black and paper), from Astrolift
|
|
170
|
+
* (green), Zentinelle (teal) and Loadr (blue).
|
|
171
|
+
*/
|
|
172
|
+
export declare const deepDataAgentBrand: {
|
|
173
|
+
readonly id: "deep-data-agent";
|
|
174
|
+
readonly name: "Deep Data Agent";
|
|
175
|
+
readonly accent: "amber";
|
|
176
|
+
readonly sidebar: "#1a150c";
|
|
177
|
+
readonly grounds: readonly ["charcoal", "black", "graphite", "paper", "mist"];
|
|
178
|
+
readonly defaultGround: {
|
|
179
|
+
readonly dark: "charcoal";
|
|
180
|
+
readonly light: "mist";
|
|
181
|
+
};
|
|
182
|
+
};
|
|
166
183
|
/**
|
|
167
184
|
* Cykick: cyan on near-black with square corners, from
|
|
168
185
|
* `ui/theme/native-themes.json` (primary, background, radius 0). Cykick's
|
|
@@ -101,6 +101,20 @@ export const loadrBrand = {
|
|
|
101
101
|
grounds: ["black", "charcoal", "graphite", "paper", "mist"],
|
|
102
102
|
defaultGround: { dark: "charcoal", light: "paper" },
|
|
103
103
|
};
|
|
104
|
+
/**
|
|
105
|
+
* Calliope AI Deep Data Agent: the family amber on a warm umber sidebar, with
|
|
106
|
+
* charcoal and mist as its defaults. A separate product from Chat Studio, and
|
|
107
|
+
* kept visibly apart from it (Studio blue on black and paper), from Astrolift
|
|
108
|
+
* (green), Zentinelle (teal) and Loadr (blue).
|
|
109
|
+
*/
|
|
110
|
+
export const deepDataAgentBrand = {
|
|
111
|
+
id: "deep-data-agent",
|
|
112
|
+
name: "Deep Data Agent",
|
|
113
|
+
accent: "amber",
|
|
114
|
+
sidebar: TOKENS.brand["deep-data-agent"].sidebar,
|
|
115
|
+
grounds: ["charcoal", "black", "graphite", "paper", "mist"],
|
|
116
|
+
defaultGround: { dark: "charcoal", light: "mist" },
|
|
117
|
+
};
|
|
104
118
|
/**
|
|
105
119
|
* Cykick: cyan on near-black with square corners, from
|
|
106
120
|
* `ui/theme/native-themes.json` (primary, background, radius 0). Cykick's
|
|
@@ -22,5 +22,5 @@ export function MessageBubble({ message, renderContent, meta, className }) {
|
|
|
22
22
|
const t = messages.chat;
|
|
23
23
|
const speaker = message.name ?? t.role(message.role);
|
|
24
24
|
const empty = message.content === "";
|
|
25
|
-
return (_jsxs("article", { "aria-label": t.messageFrom(speaker), "aria-busy": message.streaming || undefined, "data-slot": "message-bubble", "data-role": message.role, className: cn("flex min-w-0 flex-col gap-1", ROLE_CLASS[message.role], className), children: [(message.role !== "user" || meta) && (_jsxs("header", { className: "flex min-w-0 items-center gap-2 text-xs text-muted-foreground", children: [message.role !== "user" && _jsx("span", { className: "font-medium", children: speaker }), meta && _jsx("span", { className: "ml-auto flex items-center gap-2", children: meta })] })), message.streaming && empty ? (_jsxs("p", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx(StatusDot, { tone: "info", pulse: true }), t.thinking] })) : (_jsxs("div", { className: "min-w-0 text-sm [overflow-wrap:
|
|
25
|
+
return (_jsxs("article", { "aria-label": t.messageFrom(speaker), "aria-busy": message.streaming || undefined, "data-slot": "message-bubble", "data-role": message.role, className: cn("flex min-w-0 flex-col gap-1", ROLE_CLASS[message.role], className), children: [(message.role !== "user" || meta) && (_jsxs("header", { className: "flex min-w-0 items-center gap-2 text-xs text-muted-foreground", children: [message.role !== "user" && _jsx("span", { className: "font-medium", children: speaker }), meta && _jsx("span", { className: "ml-auto flex items-center gap-2", children: meta })] })), message.streaming && empty ? (_jsxs("p", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx(StatusDot, { tone: "info", pulse: true }), t.thinking] })) : (_jsxs("div", { className: "min-w-0 text-sm [overflow-wrap:break-word]", children: [renderContent ? (renderContent(message.content, message)) : (_jsx("p", { className: "whitespace-pre-wrap", children: message.content })), message.streaming && (_jsxs(_Fragment, { children: [_jsx("span", { "aria-hidden": true, className: "ml-0.5 inline-block h-4 w-1.5 translate-y-0.5 bg-foreground/60 motion-safe:animate-pulse" }), _jsx("span", { className: "sr-only", children: t.writing })] }))] }))] }));
|
|
26
26
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { type ChatContentRenderer } from "./MessageBubble.js";
|
|
3
|
-
import type { ChatToolCall, ChatView } from "./model.js";
|
|
3
|
+
import type { ChatTimelineItem, ChatToolCall, ChatView } from "./model.js";
|
|
4
4
|
import { type ToolCallCardProps } from "./ToolCallCard.js";
|
|
5
5
|
export interface MessageListProps {
|
|
6
6
|
/** The conversation: a `ChatView`, or the part of one the list reads. */
|
|
@@ -15,6 +15,13 @@ export interface MessageListProps {
|
|
|
15
15
|
toolTitle?: (call: ChatToolCall) => string | undefined;
|
|
16
16
|
onApprove?: ToolCallCardProps["onApprove"];
|
|
17
17
|
onDeny?: ToolCallCardProps["onDeny"];
|
|
18
|
+
/**
|
|
19
|
+
* Draws something after a timeline item: generative UI an agent sent
|
|
20
|
+
* between messages (a progress card, an artifact). Called for each item.
|
|
21
|
+
*/
|
|
22
|
+
renderAfter?: (item: ChatTimelineItem) => React.ReactNode;
|
|
23
|
+
/** Drawn after the whole conversation, before a failed run's error: what the run waits on. */
|
|
24
|
+
footer?: React.ReactNode;
|
|
18
25
|
/** Offered beside a failed run's error. */
|
|
19
26
|
onRetry?: () => void;
|
|
20
27
|
/** The first page of history is loading. */
|
|
@@ -33,4 +40,4 @@ export interface MessageListProps {
|
|
|
33
40
|
* changes, so a long conversation streams without virtualization; a host
|
|
34
41
|
* with thousands of turns pages its history.
|
|
35
42
|
*/
|
|
36
|
-
export declare function MessageList({ view, renderContent, renderToolCall, toolTitle, onApprove, onDeny, onRetry, loading, empty, label, className, }: MessageListProps): React.JSX.Element;
|
|
43
|
+
export declare function MessageList({ view, renderContent, renderToolCall, renderAfter, footer, toolTitle, onApprove, onDeny, onRetry, loading, empty, label, className, }: MessageListProps): React.JSX.Element;
|
package/dist/chat/MessageList.js
CHANGED
|
@@ -21,7 +21,7 @@ const PINNED = 48;
|
|
|
21
21
|
* changes, so a long conversation streams without virtualization; a host
|
|
22
22
|
* with thousands of turns pages its history.
|
|
23
23
|
*/
|
|
24
|
-
export function MessageList({ view, renderContent, renderToolCall, toolTitle, onApprove, onDeny, onRetry, loading = false, empty, label, className, }) {
|
|
24
|
+
export function MessageList({ view, renderContent, renderToolCall, renderAfter, footer, toolTitle, onApprove, onDeny, onRetry, loading = false, empty, label, className, }) {
|
|
25
25
|
const { messages } = useUI();
|
|
26
26
|
const t = messages.chat;
|
|
27
27
|
const scroller = React.useRef(null);
|
|
@@ -48,16 +48,19 @@ export function MessageList({ view, renderContent, renderToolCall, toolTitle, on
|
|
|
48
48
|
body = empty ?? _jsx(EmptyState, { title: t.empty, description: t.emptyDescription });
|
|
49
49
|
else
|
|
50
50
|
body = (_jsxs(_Fragment, { children: [view.timeline.map((item) => {
|
|
51
|
+
const after = renderAfter?.(item);
|
|
52
|
+
let node = null;
|
|
51
53
|
if (item.kind === "message") {
|
|
52
54
|
const message = byId.messages.get(item.id);
|
|
53
|
-
|
|
55
|
+
node = message ? _jsx(MemoBubble, { message: message, renderContent: renderContent }) : null;
|
|
54
56
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
else {
|
|
58
|
+
const call = byId.calls.get(item.id);
|
|
59
|
+
const custom = call ? renderToolCall?.(call) : undefined;
|
|
60
|
+
node = !call ? null : custom !== undefined ? (custom) : (_jsx(MemoToolCall, { call: call, title: toolTitle?.(call), onApprove: onApprove, onDeny: onDeny }));
|
|
61
|
+
}
|
|
62
|
+
return (_jsxs(React.Fragment, { children: [node, after] }, `${item.kind === "message" ? "m" : "t"}:${item.id}`));
|
|
63
|
+
}), footer, view.status === "error" && view.error && (_jsxs("div", { role: "alert", className: "flex min-w-0 flex-col gap-2 rounded-lg border border-danger-border bg-danger-bg px-3 py-2 text-sm text-danger-fg sm:flex-row sm:items-center", children: [_jsxs("p", { className: "min-w-0 flex-1 [overflow-wrap:anywhere]", children: [_jsx("span", { className: "font-medium", children: t.runFailed }), ": ", view.error.message] }), onRetry && (_jsx(Button, { variant: "outline", size: "sm", onClick: onRetry, children: t.retry }))] }))] }));
|
|
61
64
|
return (_jsxs("div", { "data-slot": "message-list", className: cn("relative flex min-h-0 flex-col", className), children: [_jsx("div", { ref: scroller, role: "log", "aria-label": label ?? t.conversation, "aria-busy": view.status === "running" || loading || undefined,
|
|
62
65
|
// A scrolling region is reached by keyboard (WCAG 2.1.1).
|
|
63
66
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
package/dist/css/appearance.js
CHANGED
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
d.style.setProperty("--radius",
|
|
65
65
|
(c.corners.indexOf(p.corners) > -1 ? p.corners : c.defaults.corners) + "px");
|
|
66
66
|
};
|
|
67
|
-
var products = {"astrolift":{"product":"astrolift","key":"astrolift.appearance","grounds":{"black":{"mode":"dark","background":"#000000"},"charcoal":{"mode":"dark","background":"#0e0f10"},"graphite":{"mode":"dark","background":"#111214"},"emerald":{"mode":"dark","background":"#050b08"},"paper":{"mode":"light","background":"#faf6ee"},"mist":{"mode":"light","background":"#f2f7f9"}},"accents":["green","copper","ice","periwinkle","amber"],"corners":[0,2,4,10],"minContrast":3,"defaults":{"dark":"graphite","light":"mist","accent":"green","density":"compact","corners":2}},"zentinelle":{"product":"zentinelle","key":"zentinelle.appearance","grounds":{"black":{"mode":"dark","background":"#000000"},"charcoal":{"mode":"dark","background":"#0e0f10"},"graphite":{"mode":"dark","background":"#111214"},"paper":{"mode":"light","background":"#faf6ee"},"mist":{"mode":"light","background":"#f2f7f9"}},"accents":["teal","green","copper","ice","periwinkle","amber"],"corners":[0,2,4,10],"minContrast":3,"defaults":{"dark":"black","light":"mist","accent":"teal","density":"compact","corners":2}},"workbench":{"product":"workbench","key":"workbench.appearance","grounds":{"navy":{"mode":"dark","background":"#0b1120"},"black":{"mode":"dark","background":"#000000"},"charcoal":{"mode":"dark","background":"#0e0f10"},"graphite":{"mode":"dark","background":"#111214"},"paper":{"mode":"light","background":"#faf6ee"},"mist":{"mode":"light","background":"#f2f7f9"}},"accents":["workbench-blue","green","copper","ice","periwinkle","amber"],"corners":[0,2,4,10],"minContrast":3,"defaults":{"dark":"navy","light":"mist","accent":"workbench-blue","density":"compact","corners":2}},"chat-studio":{"product":"chat-studio","key":"chat-studio.appearance","grounds":{"black":{"mode":"dark","background":"#000000"},"charcoal":{"mode":"dark","background":"#0e0f10"},"graphite":{"mode":"dark","background":"#111214"},"paper":{"mode":"light","background":"#faf6ee"},"mist":{"mode":"light","background":"#f2f7f9"}},"accents":["studio-blue","green","copper","ice","periwinkle","amber"],"corners":[0,2,4,10],"minContrast":3,"defaults":{"dark":"black","light":"paper","accent":"studio-blue","density":"compact","corners":2}},"loadr":{"product":"loadr","key":"loadr.appearance","grounds":{"black":{"mode":"dark","background":"#000000"},"charcoal":{"mode":"dark","background":"#0e0f10"},"graphite":{"mode":"dark","background":"#111214"},"paper":{"mode":"light","background":"#faf6ee"},"mist":{"mode":"light","background":"#f2f7f9"}},"accents":["loadr-blue","green","copper","ice","periwinkle","amber"],"corners":[0,2,4,10],"minContrast":3,"defaults":{"dark":"charcoal","light":"paper","accent":"loadr-blue","density":"compact","corners":2}},"cykick":{"product":"cykick","key":"cykick.appearance","grounds":{"black":{"mode":"dark","background":"#000000"},"charcoal":{"mode":"dark","background":"#0e0f10"},"graphite":{"mode":"dark","background":"#111214"},"paper":{"mode":"light","background":"#faf6ee"},"mist":{"mode":"light","background":"#f2f7f9"}},"accents":["cykick-cyan","green","copper","ice","periwinkle","amber"],"corners":[0,2,4,10],"minContrast":3,"defaults":{"dark":"black","light":"mist","accent":"cykick-cyan","density":"compact","corners":0}}};
|
|
67
|
+
var products = {"astrolift":{"product":"astrolift","key":"astrolift.appearance","grounds":{"black":{"mode":"dark","background":"#000000"},"charcoal":{"mode":"dark","background":"#0e0f10"},"graphite":{"mode":"dark","background":"#111214"},"emerald":{"mode":"dark","background":"#050b08"},"paper":{"mode":"light","background":"#faf6ee"},"mist":{"mode":"light","background":"#f2f7f9"}},"accents":["green","copper","ice","periwinkle","amber"],"corners":[0,2,4,10],"minContrast":3,"defaults":{"dark":"graphite","light":"mist","accent":"green","density":"compact","corners":2}},"zentinelle":{"product":"zentinelle","key":"zentinelle.appearance","grounds":{"black":{"mode":"dark","background":"#000000"},"charcoal":{"mode":"dark","background":"#0e0f10"},"graphite":{"mode":"dark","background":"#111214"},"paper":{"mode":"light","background":"#faf6ee"},"mist":{"mode":"light","background":"#f2f7f9"}},"accents":["teal","green","copper","ice","periwinkle","amber"],"corners":[0,2,4,10],"minContrast":3,"defaults":{"dark":"black","light":"mist","accent":"teal","density":"compact","corners":2}},"workbench":{"product":"workbench","key":"workbench.appearance","grounds":{"navy":{"mode":"dark","background":"#0b1120"},"black":{"mode":"dark","background":"#000000"},"charcoal":{"mode":"dark","background":"#0e0f10"},"graphite":{"mode":"dark","background":"#111214"},"paper":{"mode":"light","background":"#faf6ee"},"mist":{"mode":"light","background":"#f2f7f9"}},"accents":["workbench-blue","green","copper","ice","periwinkle","amber"],"corners":[0,2,4,10],"minContrast":3,"defaults":{"dark":"navy","light":"mist","accent":"workbench-blue","density":"compact","corners":2}},"chat-studio":{"product":"chat-studio","key":"chat-studio.appearance","grounds":{"black":{"mode":"dark","background":"#000000"},"charcoal":{"mode":"dark","background":"#0e0f10"},"graphite":{"mode":"dark","background":"#111214"},"paper":{"mode":"light","background":"#faf6ee"},"mist":{"mode":"light","background":"#f2f7f9"}},"accents":["studio-blue","green","copper","ice","periwinkle","amber"],"corners":[0,2,4,10],"minContrast":3,"defaults":{"dark":"black","light":"paper","accent":"studio-blue","density":"compact","corners":2}},"loadr":{"product":"loadr","key":"loadr.appearance","grounds":{"black":{"mode":"dark","background":"#000000"},"charcoal":{"mode":"dark","background":"#0e0f10"},"graphite":{"mode":"dark","background":"#111214"},"paper":{"mode":"light","background":"#faf6ee"},"mist":{"mode":"light","background":"#f2f7f9"}},"accents":["loadr-blue","green","copper","ice","periwinkle","amber"],"corners":[0,2,4,10],"minContrast":3,"defaults":{"dark":"charcoal","light":"paper","accent":"loadr-blue","density":"compact","corners":2}},"cykick":{"product":"cykick","key":"cykick.appearance","grounds":{"black":{"mode":"dark","background":"#000000"},"charcoal":{"mode":"dark","background":"#0e0f10"},"graphite":{"mode":"dark","background":"#111214"},"paper":{"mode":"light","background":"#faf6ee"},"mist":{"mode":"light","background":"#f2f7f9"}},"accents":["cykick-cyan","green","copper","ice","periwinkle","amber"],"corners":[0,2,4,10],"minContrast":3,"defaults":{"dark":"black","light":"mist","accent":"cykick-cyan","density":"compact","corners":0}},"deep-data-agent":{"product":"deep-data-agent","key":"deep-data-agent.appearance","grounds":{"charcoal":{"mode":"dark","background":"#0e0f10"},"black":{"mode":"dark","background":"#000000"},"graphite":{"mode":"dark","background":"#111214"},"paper":{"mode":"light","background":"#faf6ee"},"mist":{"mode":"light","background":"#f2f7f9"}},"accents":["green","copper","ice","periwinkle","amber"],"corners":[0,2,4,10],"minContrast":3,"defaults":{"dark":"charcoal","light":"mist","accent":"amber","density":"compact","corners":2}}};
|
|
68
68
|
var d = document.documentElement;
|
|
69
69
|
var hex = /^#[0-9a-f]{6}$/;
|
|
70
70
|
var has = function (o, k) {
|
package/dist/css/calliope.css
CHANGED
package/dist/css/tokens.css
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export { cn } from "./lib/cn.js";
|
|
|
8
8
|
export { ACCENTS, ACCENT_KEYS, DENSITIES, DENSITY_KEYS, GROUNDS, GROUND_KEYS, MODE_TOKENS, SURFACES, type AccentSpec, type Density, type FamilyAccent, type Ground, type Mode, type StatusName, } from "./theme/tokens.js";
|
|
9
9
|
export { MIN_NON_TEXT_CONTRAST, MIN_TEXT_CONTRAST, contrastRatio, luminance, } from "./theme/contrast.js";
|
|
10
10
|
export { CORNERS, defineProduct, type BrandAccent, type Corners, type Product, type ProductAccent, type ProductConfig, type ProductTheme, } from "./appearance/product.js";
|
|
11
|
-
export { astroliftBrand, chatStudioBrand, cykickBrand, loadrBrand, workbenchBrand, zentinelleBrand, } from "./appearance/brands.js";
|
|
11
|
+
export { astroliftBrand, chatStudioBrand, cykickBrand, deepDataAgentBrand, loadrBrand, workbenchBrand, zentinelleBrand, } from "./appearance/brands.js";
|
|
12
12
|
export { accentContrast, appearanceFromServer, applyAppearance, clearAppearance, inkFor, isCustomAccent, modeFor, normalize, normalizePartial, parseCustomAccent, readAppearance, resolveAppearance, writeAppearance, type Appearance, type CustomAccent, type OrgAppearancePolicy, type ResolvedAppearance, } from "./appearance/appearance.js";
|
|
13
13
|
export { appearanceScript, bootConfig, productStyles, type BootConfig } from "./appearance/boot.js";
|
|
14
14
|
export { BRAND_ACCENT_KEY, brandStyleVars, brandStyles, htmlAttributes, resolveRuntimeBrand, withBrand, type ResolvedRuntimeBrand, type RuntimeBrand, } from "./appearance/runtime-brand.js";
|
|
@@ -62,6 +62,11 @@ export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMe
|
|
|
62
62
|
export { Popover, PopoverAnchor, PopoverContent, PopoverHeader, PopoverTrigger, } from "./primitives/Popover.js";
|
|
63
63
|
export { Tabs, TabsContent, TabsList, TabsTrigger } from "./primitives/Tabs.js";
|
|
64
64
|
export { Skeleton } from "./primitives/Skeleton.js";
|
|
65
|
+
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./primitives/Tooltip.js";
|
|
66
|
+
export { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuSeparator, ContextMenuShortcut, ContextMenuTrigger, } from "./primitives/ContextMenu.js";
|
|
67
|
+
export { ScrollArea, type ScrollAreaProps } from "./primitives/ScrollArea.js";
|
|
68
|
+
export { Badge, badgeVariants, type BadgeProps } from "./primitives/Badge.js";
|
|
69
|
+
export { ToastProvider, useToast, type ToastApi, type ToastOptions, type ToastProviderProps, } from "./primitives/Toast.js";
|
|
65
70
|
export type { WorkflowAction, WorkflowAvailability, WorkflowModule, WorkflowPermissions, WorkflowScope, WorkflowStatus, WorkflowSummary, } from "./workflow/model.js";
|
|
66
71
|
export { WorkflowCard, WorkflowCardSkeleton, type WorkflowCardActions, type WorkflowCardProps, } from "./workflow/WorkflowCard.js";
|
|
67
72
|
export { WorkflowQuestionCard, type WorkflowQuestionCardProps, } from "./workflow/WorkflowQuestionCard.js";
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ export { ACCENTS, ACCENT_KEYS, DENSITIES, DENSITY_KEYS, GROUNDS, GROUND_KEYS, MO
|
|
|
11
11
|
export { MIN_NON_TEXT_CONTRAST, MIN_TEXT_CONTRAST, contrastRatio, luminance, } from "./theme/contrast.js";
|
|
12
12
|
// Product and appearance
|
|
13
13
|
export { CORNERS, defineProduct, } from "./appearance/product.js";
|
|
14
|
-
export { astroliftBrand, chatStudioBrand, cykickBrand, loadrBrand, workbenchBrand, zentinelleBrand, } from "./appearance/brands.js";
|
|
14
|
+
export { astroliftBrand, chatStudioBrand, cykickBrand, deepDataAgentBrand, loadrBrand, workbenchBrand, zentinelleBrand, } from "./appearance/brands.js";
|
|
15
15
|
export { accentContrast, appearanceFromServer, applyAppearance, clearAppearance, inkFor, isCustomAccent, modeFor, normalize, normalizePartial, parseCustomAccent, readAppearance, resolveAppearance, writeAppearance, } from "./appearance/appearance.js";
|
|
16
16
|
export { appearanceScript, bootConfig, productStyles } from "./appearance/boot.js";
|
|
17
17
|
export { BRAND_ACCENT_KEY, brandStyleVars, brandStyles, htmlAttributes, resolveRuntimeBrand, withBrand, } from "./appearance/runtime-brand.js";
|
|
@@ -73,6 +73,11 @@ export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMe
|
|
|
73
73
|
export { Popover, PopoverAnchor, PopoverContent, PopoverHeader, PopoverTrigger, } from "./primitives/Popover.js";
|
|
74
74
|
export { Tabs, TabsContent, TabsList, TabsTrigger } from "./primitives/Tabs.js";
|
|
75
75
|
export { Skeleton } from "./primitives/Skeleton.js";
|
|
76
|
+
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./primitives/Tooltip.js";
|
|
77
|
+
export { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuSeparator, ContextMenuShortcut, ContextMenuTrigger, } from "./primitives/ContextMenu.js";
|
|
78
|
+
export { ScrollArea } from "./primitives/ScrollArea.js";
|
|
79
|
+
export { Badge, badgeVariants } from "./primitives/Badge.js";
|
|
80
|
+
export { ToastProvider, useToast, } from "./primitives/Toast.js";
|
|
76
81
|
export { WorkflowCard, WorkflowCardSkeleton, } from "./workflow/WorkflowCard.js";
|
|
77
82
|
export { WorkflowQuestionCard, } from "./workflow/WorkflowQuestionCard.js";
|
|
78
83
|
export { ANY_FILTER, DEFAULT_WORKFLOW_FILTERS, filterWorkflows, isFiltered, } from "./workflow/gallery.js";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type VariantProps } from "class-variance-authority";
|
|
2
|
+
import type * as React from "react";
|
|
3
|
+
export declare const badgeVariants: (props?: ({
|
|
4
|
+
variant?: "neutral" | "outline" | "primary" | null | undefined;
|
|
5
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
6
|
+
export interface BadgeProps extends React.ComponentProps<"span">, VariantProps<typeof badgeVariants> {
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A small count or label. Not a status: a state with a meaning (running,
|
|
10
|
+
* failed) is a StatusBadge, whose colours never follow the accent. A badge
|
|
11
|
+
* that is only a number needs words for a screen reader, so give it an
|
|
12
|
+
* `aria-label` ("3 unread") or put the noun beside it.
|
|
13
|
+
*/
|
|
14
|
+
export declare function Badge({ className, variant, ...props }: BadgeProps): React.JSX.Element;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cva } from "class-variance-authority";
|
|
3
|
+
import { cn } from "../lib/cn.js";
|
|
4
|
+
export const badgeVariants = cva("inline-flex h-5 w-fit min-w-5 shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border px-1.5 text-xs font-medium whitespace-nowrap tabular-nums [&>svg]:pointer-events-none [&>svg]:size-3", {
|
|
5
|
+
variants: {
|
|
6
|
+
variant: {
|
|
7
|
+
/** Quiet: a count beside a label, a kind ("folder", "beta"). */
|
|
8
|
+
neutral: "border-transparent bg-secondary text-secondary-foreground",
|
|
9
|
+
/** The accent: a new count that wants attention. */
|
|
10
|
+
primary: "border-transparent bg-primary text-primary-foreground",
|
|
11
|
+
/** A hairline only, for dense rows. */
|
|
12
|
+
outline: "border-border bg-transparent text-muted-foreground",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
defaultVariants: { variant: "neutral" },
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* A small count or label. Not a status: a state with a meaning (running,
|
|
19
|
+
* failed) is a StatusBadge, whose colours never follow the accent. A badge
|
|
20
|
+
* that is only a number needs words for a screen reader, so give it an
|
|
21
|
+
* `aria-label` ("3 unread") or put the noun beside it.
|
|
22
|
+
*/
|
|
23
|
+
export function Badge({ className, variant, ...props }) {
|
|
24
|
+
return (_jsx("span", { "data-slot": "badge", "data-variant": variant ?? "neutral", className: cn(badgeVariants({ variant }), className), ...props }));
|
|
25
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ContextMenu as ContextMenuPrimitive } from "radix-ui";
|
|
2
|
+
import type * as React from "react";
|
|
3
|
+
/**
|
|
4
|
+
* The right-click (and Shift+F10, and the context-menu key) menu. Every
|
|
5
|
+
* action in it must also be reachable another way: a toolbar button, a row
|
|
6
|
+
* menu or a shortcut, since touch and many keyboard users never open it.
|
|
7
|
+
*/
|
|
8
|
+
export declare function ContextMenu(props: React.ComponentProps<typeof ContextMenuPrimitive.Root>): React.JSX.Element;
|
|
9
|
+
export declare function ContextMenuTrigger(props: React.ComponentProps<typeof ContextMenuPrimitive.Trigger>): React.JSX.Element;
|
|
10
|
+
export declare function ContextMenuContent({ className, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Content>): React.JSX.Element;
|
|
11
|
+
export declare function ContextMenuGroup(props: React.ComponentProps<typeof ContextMenuPrimitive.Group>): React.JSX.Element;
|
|
12
|
+
export declare function ContextMenuItem({ className, variant, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Item> & {
|
|
13
|
+
variant?: "default" | "destructive";
|
|
14
|
+
}): React.JSX.Element;
|
|
15
|
+
export declare function ContextMenuLabel({ className, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Label>): React.JSX.Element;
|
|
16
|
+
export declare function ContextMenuSeparator({ className, ...props }: React.ComponentProps<typeof ContextMenuPrimitive.Separator>): React.JSX.Element;
|
|
17
|
+
/** The item's keyboard shortcut, right-aligned. Decorative: the shortcut itself is the app's. */
|
|
18
|
+
export declare function ContextMenuShortcut({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { ContextMenu as ContextMenuPrimitive } from "radix-ui";
|
|
4
|
+
import { cn } from "../lib/cn.js";
|
|
5
|
+
/**
|
|
6
|
+
* The right-click (and Shift+F10, and the context-menu key) menu. Every
|
|
7
|
+
* action in it must also be reachable another way: a toolbar button, a row
|
|
8
|
+
* menu or a shortcut, since touch and many keyboard users never open it.
|
|
9
|
+
*/
|
|
10
|
+
export function ContextMenu(props) {
|
|
11
|
+
return _jsx(ContextMenuPrimitive.Root, { "data-slot": "context-menu", ...props });
|
|
12
|
+
}
|
|
13
|
+
export function ContextMenuTrigger(props) {
|
|
14
|
+
return _jsx(ContextMenuPrimitive.Trigger, { "data-slot": "context-menu-trigger", ...props });
|
|
15
|
+
}
|
|
16
|
+
export function ContextMenuContent({ className, ...props }) {
|
|
17
|
+
return (_jsx(ContextMenuPrimitive.Portal, { children: _jsx(ContextMenuPrimitive.Content, { "data-slot": "context-menu-content", className: cn("z-50 max-h-(--radix-context-menu-content-available-height) min-w-40 origin-(--radix-context-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 data-[state=open]:animate-cui-fade-in", className), ...props }) }));
|
|
18
|
+
}
|
|
19
|
+
export function ContextMenuGroup(props) {
|
|
20
|
+
return _jsx(ContextMenuPrimitive.Group, { "data-slot": "context-menu-group", ...props });
|
|
21
|
+
}
|
|
22
|
+
export function ContextMenuItem({ className, variant = "default", ...props }) {
|
|
23
|
+
return (_jsx(ContextMenuPrimitive.Item, { "data-slot": "context-menu-item", "data-variant": variant, className: cn("relative flex cursor-default items-center gap-1.5 rounded-lg px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 data-[variant=destructive]:text-danger-fg data-[variant=destructive]:focus:bg-danger/10 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className), ...props }));
|
|
24
|
+
}
|
|
25
|
+
export function ContextMenuLabel({ className, ...props }) {
|
|
26
|
+
return (_jsx(ContextMenuPrimitive.Label, { "data-slot": "context-menu-label", className: cn("px-1.5 py-1 text-xs font-medium text-muted-foreground", className), ...props }));
|
|
27
|
+
}
|
|
28
|
+
export function ContextMenuSeparator({ className, ...props }) {
|
|
29
|
+
return (_jsx(ContextMenuPrimitive.Separator, { "data-slot": "context-menu-separator", className: cn("-mx-1 my-1 h-px bg-border", className), ...props }));
|
|
30
|
+
}
|
|
31
|
+
/** The item's keyboard shortcut, right-aligned. Decorative: the shortcut itself is the app's. */
|
|
32
|
+
export function ContextMenuShortcut({ className, ...props }) {
|
|
33
|
+
return (_jsx("span", { "data-slot": "context-menu-shortcut", "aria-hidden": true, className: cn("ml-auto pl-4 font-mono text-xs text-muted-foreground", className), ...props }));
|
|
34
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ScrollArea as ScrollAreaPrimitive } from "radix-ui";
|
|
2
|
+
import type * as React from "react";
|
|
3
|
+
export interface ScrollAreaProps extends React.ComponentProps<typeof ScrollAreaPrimitive.Root> {
|
|
4
|
+
/**
|
|
5
|
+
* Names the scrolling region. Given, the viewport is a focusable region so
|
|
6
|
+
* a keyboard can scroll it; leave it out when the content has its own
|
|
7
|
+
* focusable items (a list of links, a tree).
|
|
8
|
+
*/
|
|
9
|
+
label?: string;
|
|
10
|
+
/** Which bars to draw. Defaults to vertical. */
|
|
11
|
+
orientation?: "vertical" | "horizontal" | "both";
|
|
12
|
+
viewportClassName?: string;
|
|
13
|
+
}
|
|
14
|
+
/** A scrolling box with thin, token-coloured bars that look the same on every platform. */
|
|
15
|
+
export declare function ScrollArea({ className, viewportClassName, children, label, orientation, ...props }: ScrollAreaProps): React.JSX.Element;
|
|
16
|
+
export declare function ScrollBar({ className, orientation, ...props }: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>): React.JSX.Element;
|