@ocai/app-sdk-ui 0.1.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/LICENSE +21 -0
- package/dist/chat/actions.d.ts +9 -0
- package/dist/chat/message.d.ts +6 -0
- package/dist/chat/reasoning.d.ts +17 -0
- package/dist/chat/response.d.ts +5 -0
- package/dist/chat/tool.d.ts +23 -0
- package/dist/chat.css +75 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +286 -0
- package/dist/internal/button.d.ts +10 -0
- package/dist/internal/collapsible.d.ts +6 -0
- package/dist/internal/tooltip.d.ts +7 -0
- package/dist/lib/cn.d.ts +2 -0
- package/dist/tokens.css +158 -0
- package/package.json +67 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ocean AI, LLC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ComponentProps } from 'react';
|
|
2
|
+
import { Button } from '../internal/button';
|
|
3
|
+
export type ActionsProps = ComponentProps<"div">;
|
|
4
|
+
export declare const Actions: ({ className, children, ...props }: ActionsProps) => import("react").JSX.Element;
|
|
5
|
+
export type ActionProps = ComponentProps<typeof Button> & {
|
|
6
|
+
tooltip?: string;
|
|
7
|
+
label?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare const Action: ({ tooltip, children, label, className, variant, size, ...props }: ActionProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { HTMLAttributes } from 'react';
|
|
2
|
+
export type MessageContentVariant = "user" | "assistant";
|
|
3
|
+
export type MessageContentProps = HTMLAttributes<HTMLDivElement> & {
|
|
4
|
+
variant?: MessageContentVariant;
|
|
5
|
+
};
|
|
6
|
+
export declare const MessageContent: ({ children, className, variant, ...props }: MessageContentProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ComponentProps } from 'react';
|
|
2
|
+
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '../internal/collapsible';
|
|
3
|
+
export type ReasoningProps = ComponentProps<typeof Collapsible> & {
|
|
4
|
+
isStreaming?: boolean;
|
|
5
|
+
duration?: number;
|
|
6
|
+
open?: boolean;
|
|
7
|
+
defaultOpen?: boolean;
|
|
8
|
+
onOpenChange?: (open: boolean) => void;
|
|
9
|
+
};
|
|
10
|
+
export declare const Reasoning: import('react').MemoExoticComponent<({ className, isStreaming, duration, open, defaultOpen, onOpenChange, children, ...props }: ReasoningProps) => import("react").JSX.Element>;
|
|
11
|
+
export type ReasoningTriggerProps = ComponentProps<typeof CollapsibleTrigger> & {
|
|
12
|
+
variant?: "reasoning" | "tools";
|
|
13
|
+
label?: string;
|
|
14
|
+
};
|
|
15
|
+
export declare const ReasoningTrigger: import('react').MemoExoticComponent<({ className, children, variant, label, ...props }: ReasoningTriggerProps) => import("react").JSX.Element>;
|
|
16
|
+
export declare const reasoningTextClassName = "grid gap-1 text-sm text-muted-foreground/80 **:text-sm [&_code]:bg-transparent [&_code]:p-0 [&_code]:font-semibold [&_code]:text-foreground [&_li]:my-0 [&_ol]:my-1 [&_p]:my-0 [&_ul]:my-1";
|
|
17
|
+
export declare const ReasoningContent: import('react').MemoExoticComponent<({ className, ...props }: ComponentProps<typeof CollapsibleContent>) => import("react").JSX.Element>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ToolUIPart } from 'ai';
|
|
2
|
+
import { ComponentProps, ReactNode } from 'react';
|
|
3
|
+
import { Collapsible, CollapsibleContent } from '../internal/collapsible';
|
|
4
|
+
export type ToolProps = ComponentProps<typeof Collapsible>;
|
|
5
|
+
export declare const Tool: ({ className, ...props }: ToolProps) => import("react").JSX.Element;
|
|
6
|
+
export type ToolHeaderProps = {
|
|
7
|
+
type: ToolUIPart["type"];
|
|
8
|
+
state: ToolUIPart["state"];
|
|
9
|
+
title?: string;
|
|
10
|
+
className?: string;
|
|
11
|
+
};
|
|
12
|
+
export declare const ToolHeader: ({ className, type, state, title, ...props }: ToolHeaderProps) => import("react").JSX.Element;
|
|
13
|
+
export type ToolContentProps = ComponentProps<typeof CollapsibleContent>;
|
|
14
|
+
export declare const ToolContent: ({ className, ...props }: ToolContentProps) => import("react").JSX.Element;
|
|
15
|
+
export type ToolInputProps = ComponentProps<"div"> & {
|
|
16
|
+
input: ToolUIPart["input"];
|
|
17
|
+
};
|
|
18
|
+
export declare const ToolInput: ({ className, input, ...props }: ToolInputProps) => import("react").JSX.Element;
|
|
19
|
+
export type ToolOutputProps = ComponentProps<"div"> & {
|
|
20
|
+
output: ReactNode;
|
|
21
|
+
errorText: ToolUIPart["errorText"];
|
|
22
|
+
};
|
|
23
|
+
export declare const ToolOutput: ({ className, output, errorText, ...props }: ToolOutputProps) => import("react").JSX.Element | null;
|
package/dist/chat.css
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/* @ocai/app-sdk-ui/chat.css — AI-chat markdown → Notion/Rune-block look
|
|
2
|
+
(prototype: tables + code shell).
|
|
3
|
+
|
|
4
|
+
Consume by importing INSIDE your Tailwind v4 entry stylesheet, after
|
|
5
|
+
tokens.css, so the @apply rules below are compiled by the app's own
|
|
6
|
+
Tailwind pass against that app's theme tokens:
|
|
7
|
+
|
|
8
|
+
@import "tailwindcss";
|
|
9
|
+
@import "@ocai/app-sdk-ui/tokens.css";
|
|
10
|
+
@import "@ocai/app-sdk-ui/chat.css";
|
|
11
|
+
|
|
12
|
+
A plain <link> or JS-side import will NOT work — Tailwind must see the
|
|
13
|
+
@apply rules to resolve text-sm and friends.
|
|
14
|
+
|
|
15
|
+
Streamdown tags every rendered element with `data-streamdown="<name>"` as
|
|
16
|
+
its styling hook (no shadow DOM, no separate stylesheet), so we restyle
|
|
17
|
+
purely in CSS. Scoped to `.ocui-md`, which this package's Response
|
|
18
|
+
component (chat/response.tsx) sets on the Streamdown root; the compound
|
|
19
|
+
`.ocui-md [data-streamdown=…]` selector (specificity 0,2,0) out-specifies
|
|
20
|
+
Streamdown's own single-class utilities within this same `utilities`
|
|
21
|
+
layer. We touch the table grid and the code-block SHELL (border + header)
|
|
22
|
+
only — the shiki-highlighted code body is left alone so syntax colors
|
|
23
|
+
survive. */
|
|
24
|
+
@layer utilities {
|
|
25
|
+
/* --- Tables: Notion-style bordered grid (header row tinted, 1px cell
|
|
26
|
+
borders, per-column min/max width, horizontal scroll on overflow) --- */
|
|
27
|
+
/* Streamdown nests the <table> in TWO "card" wrappers: the outer
|
|
28
|
+
`table-wrapper` (rounded-lg border bg-sidebar p-2 — hosted the now-removed
|
|
29
|
+
controls) AND an inner MarkdownTable div (rounded-md border bg-background)
|
|
30
|
+
that directly wraps the <table>. The inner one carries NO data-streamdown
|
|
31
|
+
hook, so we target it as "the div directly containing the table" via :has.
|
|
32
|
+
Flatten both cards (controls already off via controls={{ table: false }})
|
|
33
|
+
so only the 1px cell grid shows; the outer keeps the my-4 block spacing. */
|
|
34
|
+
.ocui-md [data-streamdown="table-wrapper"] {
|
|
35
|
+
@apply my-4 w-full gap-0 rounded-none border-0 bg-transparent p-0;
|
|
36
|
+
}
|
|
37
|
+
.ocui-md div:has(> [data-streamdown="table"]) {
|
|
38
|
+
@apply w-full overflow-x-auto rounded-none border-0 bg-transparent;
|
|
39
|
+
}
|
|
40
|
+
.ocui-md [data-streamdown="table"] {
|
|
41
|
+
@apply w-full border-collapse rounded-none text-sm;
|
|
42
|
+
}
|
|
43
|
+
/* Match the rune editor's native table palette exactly. rune-react declares
|
|
44
|
+
--rune-table-header-bg (5% fg) and --rune-table-border (10% fg) only inside
|
|
45
|
+
.rune-editor — out of reach in chat — so we mirror the same recipe off the
|
|
46
|
+
global --foreground / --background seeds, which keeps it identical to the
|
|
47
|
+
editor table in BOTH light and dark (bg-muted drifted to 15% in dark). */
|
|
48
|
+
.ocui-md [data-streamdown="table-header"] {
|
|
49
|
+
@apply bg-transparent;
|
|
50
|
+
}
|
|
51
|
+
.ocui-md [data-streamdown="table-header-cell"],
|
|
52
|
+
.ocui-md [data-streamdown="table-cell"] {
|
|
53
|
+
border: 1px solid color-mix(in oklab, var(--foreground) 10%, var(--background));
|
|
54
|
+
@apply px-3 py-1.5 text-left align-top;
|
|
55
|
+
min-width: 120px;
|
|
56
|
+
max-width: 280px;
|
|
57
|
+
}
|
|
58
|
+
.ocui-md [data-streamdown="table-header-cell"] {
|
|
59
|
+
background: color-mix(in oklab, var(--foreground) 5%, var(--background));
|
|
60
|
+
@apply font-medium text-foreground;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* --- Code block: Rune-style shell only. Container gets the rounded border;
|
|
64
|
+
the header strip (language label + copy/download) gets a tinted bar; the
|
|
65
|
+
`code-block-body` (shiki) keeps its own background + token colors. --- */
|
|
66
|
+
.ocui-md [data-streamdown="code-block"] {
|
|
67
|
+
@apply my-4 overflow-hidden rounded-lg border border-border;
|
|
68
|
+
}
|
|
69
|
+
.ocui-md [data-streamdown="code-block-header"] {
|
|
70
|
+
@apply border-b border-border bg-muted/50 px-3 py-1 text-xs text-muted-foreground;
|
|
71
|
+
}
|
|
72
|
+
.ocui-md [data-streamdown="code-block-body"] {
|
|
73
|
+
@apply text-sm;
|
|
74
|
+
}
|
|
75
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { Response } from './chat/response';
|
|
2
|
+
export { MessageContent, type MessageContentProps, type MessageContentVariant, } from './chat/message';
|
|
3
|
+
export { Reasoning, ReasoningContent, ReasoningTrigger, reasoningTextClassName, type ReasoningProps, type ReasoningTriggerProps, } from './chat/reasoning';
|
|
4
|
+
export { Tool, ToolContent, ToolHeader, ToolInput, ToolOutput, type ToolContentProps, type ToolHeaderProps, type ToolInputProps, type ToolOutputProps, type ToolProps, } from './chat/tool';
|
|
5
|
+
export { Action, Actions, type ActionProps, type ActionsProps, } from './chat/actions';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { createMathPlugin as e } from "@streamdown/math";
|
|
3
|
+
import { Streamdown as t } from "streamdown";
|
|
4
|
+
import { clsx as n } from "clsx";
|
|
5
|
+
import { twMerge as r } from "tailwind-merge";
|
|
6
|
+
import { Fragment as i, jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
7
|
+
import { CheckIcon as s, ChevronDownIcon as c, ClockIcon as l, Loader2Icon as u, WrenchIcon as d, XIcon as f } from "lucide-react";
|
|
8
|
+
import { createContext as p, memo as m, useContext as h, useEffect as g, useState as _ } from "react";
|
|
9
|
+
import { Collapsible as v, Slot as y, Tooltip as b } from "radix-ui";
|
|
10
|
+
import { cva as x } from "class-variance-authority";
|
|
11
|
+
//#region src/lib/cn.ts
|
|
12
|
+
function S(...e) {
|
|
13
|
+
return r(n(e));
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/chat/response.tsx
|
|
17
|
+
var C = e({ singleDollarTextMath: !0 });
|
|
18
|
+
function w({ className: e, ...n }) {
|
|
19
|
+
return /* @__PURE__ */ a(t, {
|
|
20
|
+
className: S("ocui-md size-full text-base font-normal leading-6 [&>*:first-child]:mt-0 [&>*:last-child]:mb-0 [&_code]:whitespace-pre-wrap [&_code]:wrap-break-word [&_pre]:max-w-full [&_pre]:overflow-x-auto", e),
|
|
21
|
+
plugins: { math: C },
|
|
22
|
+
controls: { table: !1 },
|
|
23
|
+
...n
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/chat/message.tsx
|
|
28
|
+
var T = {
|
|
29
|
+
user: "w-fit wrap-break-word rounded-md bg-card px-3 py-1.5 text-primary",
|
|
30
|
+
assistant: "bg-transparent px-0 py-0 text-left text-foreground"
|
|
31
|
+
}, E = ({ children: e, className: t, variant: n = "user", ...r }) => /* @__PURE__ */ a("div", {
|
|
32
|
+
className: S("flex flex-col gap-2 overflow-hidden text-base font-normal leading-6", T[n], t),
|
|
33
|
+
...r,
|
|
34
|
+
children: e
|
|
35
|
+
});
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region src/internal/collapsible.tsx
|
|
38
|
+
function D({ ...e }) {
|
|
39
|
+
return /* @__PURE__ */ a(v.Root, {
|
|
40
|
+
"data-slot": "collapsible",
|
|
41
|
+
...e
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function O({ ...e }) {
|
|
45
|
+
return /* @__PURE__ */ a(v.CollapsibleTrigger, {
|
|
46
|
+
"data-slot": "collapsible-trigger",
|
|
47
|
+
...e
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function k({ ...e }) {
|
|
51
|
+
return /* @__PURE__ */ a(v.CollapsibleContent, {
|
|
52
|
+
"data-slot": "collapsible-content",
|
|
53
|
+
...e
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
57
|
+
//#region src/chat/reasoning.tsx
|
|
58
|
+
function A({ prop: e, defaultProp: t, onChange: n }) {
|
|
59
|
+
let [r, i] = _(t), a = e !== void 0;
|
|
60
|
+
return [a ? e : r, (e) => {
|
|
61
|
+
a || i(e), n?.(e);
|
|
62
|
+
}];
|
|
63
|
+
}
|
|
64
|
+
var j = p(null), M = () => {
|
|
65
|
+
let e = h(j);
|
|
66
|
+
if (!e) throw Error("Reasoning components must be used within Reasoning");
|
|
67
|
+
return e;
|
|
68
|
+
}, N = 500, P = m(({ className: e, isStreaming: t = !1, duration: n = 0, open: r, defaultOpen: i = !0, onOpenChange: o, children: s, ...c }) => {
|
|
69
|
+
let [l, u] = A({
|
|
70
|
+
prop: r,
|
|
71
|
+
defaultProp: i,
|
|
72
|
+
onChange: o
|
|
73
|
+
}), [d, f] = _(!1);
|
|
74
|
+
return g(() => {
|
|
75
|
+
if (i && !t && l && !d) {
|
|
76
|
+
let e = setTimeout(() => {
|
|
77
|
+
u(!1), f(!0);
|
|
78
|
+
}, N);
|
|
79
|
+
return () => clearTimeout(e);
|
|
80
|
+
}
|
|
81
|
+
}, [
|
|
82
|
+
t,
|
|
83
|
+
l,
|
|
84
|
+
i,
|
|
85
|
+
u,
|
|
86
|
+
d
|
|
87
|
+
]), /* @__PURE__ */ a(j.Provider, {
|
|
88
|
+
value: {
|
|
89
|
+
isStreaming: t,
|
|
90
|
+
isOpen: l,
|
|
91
|
+
setIsOpen: u,
|
|
92
|
+
duration: n
|
|
93
|
+
},
|
|
94
|
+
children: /* @__PURE__ */ a(D, {
|
|
95
|
+
className: S("not-prose", e),
|
|
96
|
+
onOpenChange: u,
|
|
97
|
+
open: l,
|
|
98
|
+
...c,
|
|
99
|
+
children: s
|
|
100
|
+
})
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
function F({ variant: e, isStreaming: t, duration: n }) {
|
|
104
|
+
let r = e === "tools";
|
|
105
|
+
return t ? r ? "Working…" : "Thinking…" : n > 0 ? r ? `Worked for ${n}s` : `Thought for ${n}s` : r ? "Worked" : "Thought";
|
|
106
|
+
}
|
|
107
|
+
var I = m(({ className: e, children: t, variant: n = "reasoning", label: r, ...s }) => {
|
|
108
|
+
let { isStreaming: l, isOpen: u, duration: f } = M(), p = r ?? F({
|
|
109
|
+
variant: n,
|
|
110
|
+
isStreaming: l,
|
|
111
|
+
duration: f
|
|
112
|
+
});
|
|
113
|
+
return /* @__PURE__ */ a(O, {
|
|
114
|
+
className: S("flex items-center gap-1 rounded-md px-1.5 py-0.5 text-sm text-muted-foreground transition-colors hover:bg-muted hover:text-foreground", e),
|
|
115
|
+
...s,
|
|
116
|
+
children: t ?? /* @__PURE__ */ o(i, { children: [
|
|
117
|
+
n === "tools" && /* @__PURE__ */ a(d, { className: "size-3" }),
|
|
118
|
+
/* @__PURE__ */ a("span", {
|
|
119
|
+
className: S(l && "animate-pulse"),
|
|
120
|
+
children: p
|
|
121
|
+
}),
|
|
122
|
+
/* @__PURE__ */ a(c, { className: S("size-2.5 transition-transform", u ? "rotate-180" : "rotate-0") })
|
|
123
|
+
] })
|
|
124
|
+
});
|
|
125
|
+
}), L = "grid gap-1 text-sm text-muted-foreground/80 **:text-sm [&_code]:bg-transparent [&_code]:p-0 [&_code]:font-semibold [&_code]:text-foreground [&_li]:my-0 [&_ol]:my-1 [&_p]:my-0 [&_ul]:my-1", R = m(({ className: e, ...t }) => /* @__PURE__ */ a(k, {
|
|
126
|
+
className: S(L, "mt-1.5", e),
|
|
127
|
+
...t
|
|
128
|
+
}));
|
|
129
|
+
P.displayName = "Reasoning", I.displayName = "ReasoningTrigger", R.displayName = "ReasoningContent";
|
|
130
|
+
//#endregion
|
|
131
|
+
//#region src/chat/tool.tsx
|
|
132
|
+
var z = ({ className: e, ...t }) => /* @__PURE__ */ a(D, {
|
|
133
|
+
className: S("not-prose w-full rounded-md border border-border", e),
|
|
134
|
+
...t
|
|
135
|
+
}), B = {
|
|
136
|
+
"input-streaming": "Pending",
|
|
137
|
+
"input-available": "Running",
|
|
138
|
+
"approval-requested": "Pending",
|
|
139
|
+
"approval-responded": "Approved",
|
|
140
|
+
"output-available": "Completed",
|
|
141
|
+
"output-error": "Error",
|
|
142
|
+
"output-denied": "Denied"
|
|
143
|
+
}, V = {
|
|
144
|
+
"input-streaming": /* @__PURE__ */ a(u, { className: "size-3.5 animate-spin" }),
|
|
145
|
+
"input-available": /* @__PURE__ */ a(u, { className: "size-3.5 animate-spin" }),
|
|
146
|
+
"approval-requested": /* @__PURE__ */ a(l, { className: "size-3.5" }),
|
|
147
|
+
"approval-responded": /* @__PURE__ */ a(s, { className: "size-3.5" }),
|
|
148
|
+
"output-available": /* @__PURE__ */ a(s, { className: "size-3.5" }),
|
|
149
|
+
"output-error": /* @__PURE__ */ a(f, { className: "size-3.5 text-destructive" }),
|
|
150
|
+
"output-denied": /* @__PURE__ */ a(f, { className: "size-3.5 text-destructive" })
|
|
151
|
+
}, H = ({ state: e }) => /* @__PURE__ */ o("span", {
|
|
152
|
+
className: "flex shrink-0 items-center gap-1 text-xs text-muted-foreground",
|
|
153
|
+
children: [V[e], B[e]]
|
|
154
|
+
}), U = ({ className: e, type: t, state: n, title: r, ...i }) => /* @__PURE__ */ o(O, {
|
|
155
|
+
className: S("group flex w-full min-w-0 items-center justify-between gap-2 rounded-md p-2.5 transition-colors hover:bg-muted/50", e),
|
|
156
|
+
...i,
|
|
157
|
+
children: [/* @__PURE__ */ o("div", {
|
|
158
|
+
className: "flex min-w-0 flex-1 items-center gap-2",
|
|
159
|
+
children: [/* @__PURE__ */ a(d, { className: "size-3.5 shrink-0 text-muted-foreground" }), /* @__PURE__ */ a("span", {
|
|
160
|
+
className: "truncate text-sm font-medium",
|
|
161
|
+
children: r ?? t
|
|
162
|
+
})]
|
|
163
|
+
}), /* @__PURE__ */ o("div", {
|
|
164
|
+
className: "flex shrink-0 items-center gap-2",
|
|
165
|
+
children: [/* @__PURE__ */ a(H, { state: n }), /* @__PURE__ */ a(c, { className: "size-3.5 text-muted-foreground transition-transform group-data-[state=open]:rotate-180" })]
|
|
166
|
+
})]
|
|
167
|
+
}), W = ({ className: e, ...t }) => /* @__PURE__ */ a(k, {
|
|
168
|
+
className: S("data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-popover-foreground outline-hidden data-[state=closed]:animate-out data-[state=open]:animate-in", e),
|
|
169
|
+
...t
|
|
170
|
+
}), G = ({ className: e, input: t, ...n }) => /* @__PURE__ */ o("div", {
|
|
171
|
+
className: S("space-y-1.5 overflow-hidden px-2.5 pb-2.5", e),
|
|
172
|
+
...n,
|
|
173
|
+
children: [/* @__PURE__ */ a("h4", {
|
|
174
|
+
className: "text-xs font-medium tracking-wide text-muted-foreground uppercase",
|
|
175
|
+
children: "Parameters"
|
|
176
|
+
}), /* @__PURE__ */ a("pre", {
|
|
177
|
+
className: "overflow-x-auto rounded-md bg-muted/50 p-2.5 font-mono text-xs",
|
|
178
|
+
children: JSON.stringify(t, null, 2)
|
|
179
|
+
})]
|
|
180
|
+
}), K = ({ className: e, output: t, errorText: n, ...r }) => t || n ? /* @__PURE__ */ o("div", {
|
|
181
|
+
className: S("space-y-1.5 px-2.5 pb-2.5", e),
|
|
182
|
+
...r,
|
|
183
|
+
children: [/* @__PURE__ */ a("h4", {
|
|
184
|
+
className: "text-xs font-medium tracking-wide text-muted-foreground uppercase",
|
|
185
|
+
children: n ? "Error" : "Result"
|
|
186
|
+
}), /* @__PURE__ */ o("div", {
|
|
187
|
+
className: S("overflow-x-auto rounded-md text-xs [&_table]:w-full", n ? "bg-destructive/10 p-2.5 text-destructive" : "bg-muted/50 p-2.5 text-foreground"),
|
|
188
|
+
children: [n && /* @__PURE__ */ a("div", { children: n }), t && /* @__PURE__ */ a("div", { children: t })]
|
|
189
|
+
})]
|
|
190
|
+
}) : null, q = x("group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-colors outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", {
|
|
191
|
+
variants: {
|
|
192
|
+
variant: {
|
|
193
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
194
|
+
outline: "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
|
|
195
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
|
196
|
+
ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
|
|
197
|
+
destructive: "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
|
|
198
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
199
|
+
},
|
|
200
|
+
size: {
|
|
201
|
+
default: "h-7 gap-1.5 px-2 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5",
|
|
202
|
+
xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
203
|
+
sm: "h-6 gap-1 rounded-[min(var(--radius-md),12px)] px-2 text-[0.8rem] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
|
|
204
|
+
lg: "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
|
205
|
+
icon: "size-7",
|
|
206
|
+
"icon-xs": "size-6 rounded-[min(var(--radius-md),10px)] [&_svg:not([class*='size-'])]:size-3",
|
|
207
|
+
"icon-sm": "size-6 rounded-[min(var(--radius-md),12px)]",
|
|
208
|
+
"icon-lg": "size-8"
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
defaultVariants: {
|
|
212
|
+
variant: "default",
|
|
213
|
+
size: "default"
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
function J({ className: e, variant: t = "default", size: n = "default", asChild: r = !1, ...i }) {
|
|
217
|
+
return /* @__PURE__ */ a(r ? y.Root : "button", {
|
|
218
|
+
"data-slot": "button",
|
|
219
|
+
"data-variant": t,
|
|
220
|
+
"data-size": n,
|
|
221
|
+
className: S(q({
|
|
222
|
+
variant: t,
|
|
223
|
+
size: n,
|
|
224
|
+
className: e
|
|
225
|
+
})),
|
|
226
|
+
...i
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
//#endregion
|
|
230
|
+
//#region src/internal/tooltip.tsx
|
|
231
|
+
function Y({ delayDuration: e = 0, ...t }) {
|
|
232
|
+
return /* @__PURE__ */ a(b.Provider, {
|
|
233
|
+
"data-slot": "tooltip-provider",
|
|
234
|
+
delayDuration: e,
|
|
235
|
+
...t
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
function X({ ...e }) {
|
|
239
|
+
return /* @__PURE__ */ a(b.Root, {
|
|
240
|
+
"data-slot": "tooltip",
|
|
241
|
+
...e
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
function Z({ ...e }) {
|
|
245
|
+
return /* @__PURE__ */ a(b.Trigger, {
|
|
246
|
+
"data-slot": "tooltip-trigger",
|
|
247
|
+
...e
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
function Q({ className: e, sideOffset: t = 0, children: n, ...r }) {
|
|
251
|
+
return /* @__PURE__ */ a(b.Portal, { children: /* @__PURE__ */ o(b.Content, {
|
|
252
|
+
"data-slot": "tooltip-content",
|
|
253
|
+
sideOffset: t,
|
|
254
|
+
className: S("z-50 inline-flex w-fit max-w-xs origin-(--radix-tooltip-content-transform-origin) items-center gap-1.5 rounded-md border border-border bg-popover px-3 py-1.5 text-xs text-popover-foreground shadow-md data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-[state=instant-open]:animate-in data-[state=instant-open]:fade-in-0 data-[state=instant-open]:zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95", e),
|
|
255
|
+
...r,
|
|
256
|
+
children: [n, /* @__PURE__ */ a(b.Arrow, { className: "z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] border-r border-b border-border bg-popover fill-popover" })]
|
|
257
|
+
}) });
|
|
258
|
+
}
|
|
259
|
+
//#endregion
|
|
260
|
+
//#region src/chat/actions.tsx
|
|
261
|
+
var $ = ({ className: e, children: t, ...n }) => /* @__PURE__ */ a("div", {
|
|
262
|
+
className: S("flex items-center", e),
|
|
263
|
+
...n,
|
|
264
|
+
children: t
|
|
265
|
+
}), ee = ({ tooltip: e, children: t, label: n, className: r, variant: i = "ghost", size: s = "icon", ...c }) => {
|
|
266
|
+
let l = /* @__PURE__ */ o(J, {
|
|
267
|
+
className: S("relative", r),
|
|
268
|
+
size: s,
|
|
269
|
+
type: "button",
|
|
270
|
+
variant: i,
|
|
271
|
+
...c,
|
|
272
|
+
children: [t, /* @__PURE__ */ a("span", {
|
|
273
|
+
className: "sr-only",
|
|
274
|
+
children: n || e
|
|
275
|
+
})]
|
|
276
|
+
});
|
|
277
|
+
return e ? /* @__PURE__ */ a(Y, {
|
|
278
|
+
delayDuration: 300,
|
|
279
|
+
children: /* @__PURE__ */ o(X, { children: [/* @__PURE__ */ a(Z, {
|
|
280
|
+
asChild: !0,
|
|
281
|
+
children: l
|
|
282
|
+
}), /* @__PURE__ */ a(Q, { children: /* @__PURE__ */ a("p", { children: e }) })] })
|
|
283
|
+
}) : l;
|
|
284
|
+
};
|
|
285
|
+
//#endregion
|
|
286
|
+
export { ee as Action, $ as Actions, E as MessageContent, P as Reasoning, R as ReasoningContent, I as ReasoningTrigger, w as Response, z as Tool, W as ToolContent, U as ToolHeader, G as ToolInput, K as ToolOutput, L as reasoningTextClassName };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { VariantProps } from 'class-variance-authority';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
declare const buttonVariants: (props?: ({
|
|
4
|
+
variant?: "link" | "default" | "outline" | "secondary" | "ghost" | "destructive" | null | undefined;
|
|
5
|
+
size?: "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
|
|
6
|
+
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
7
|
+
declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
|
|
8
|
+
asChild?: boolean;
|
|
9
|
+
}): React.JSX.Element;
|
|
10
|
+
export { Button, buttonVariants };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Collapsible as CollapsiblePrimitive } from 'radix-ui';
|
|
2
|
+
import type * as React from "react";
|
|
3
|
+
declare function Collapsible({ ...props }: React.ComponentProps<typeof CollapsiblePrimitive.Root>): React.JSX.Element;
|
|
4
|
+
declare function CollapsibleTrigger({ ...props }: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>): React.JSX.Element;
|
|
5
|
+
declare function CollapsibleContent({ ...props }: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>): React.JSX.Element;
|
|
6
|
+
export { Collapsible, CollapsibleTrigger, CollapsibleContent };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Tooltip as TooltipPrimitive } from 'radix-ui';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
declare function TooltipProvider({ delayDuration, ...props }: React.ComponentProps<typeof TooltipPrimitive.Provider>): React.JSX.Element;
|
|
4
|
+
declare function Tooltip({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Root>): React.JSX.Element;
|
|
5
|
+
declare function TooltipTrigger({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Trigger>): React.JSX.Element;
|
|
6
|
+
declare function TooltipContent({ className, sideOffset, children, ...props }: React.ComponentProps<typeof TooltipPrimitive.Content>): React.JSX.Element;
|
|
7
|
+
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
|
package/dist/lib/cn.d.ts
ADDED
package/dist/tokens.css
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @ocai/app-sdk-ui/tokens.css — OceanAI shared design tokens.
|
|
3
|
+
*
|
|
4
|
+
* Consume by importing INSIDE your Tailwind v4 entry stylesheet, after
|
|
5
|
+
* tailwindcss itself, so the @theme block below is compiled by the app's
|
|
6
|
+
* Tailwind pass:
|
|
7
|
+
*
|
|
8
|
+
* @import "tailwindcss";
|
|
9
|
+
* @import "@ocai/app-sdk-ui/tokens.css";
|
|
10
|
+
*
|
|
11
|
+
* A plain <link> or JS-side import will NOT work — Tailwind must see the
|
|
12
|
+
* @theme block to generate `bg-background` and friends.
|
|
13
|
+
*
|
|
14
|
+
* Dark mode keys off a `.dark` ancestor class (both OceanAI apps toggle a
|
|
15
|
+
* class on <html>).
|
|
16
|
+
*
|
|
17
|
+
* Theming model: two grayscale seeds (--background, --foreground) drive the
|
|
18
|
+
* whole chromeless set via color-mix(in oklab, fg X%, bg). Tokens that carry
|
|
19
|
+
* chroma (--destructive, --chart-*) stay literal. Light is the authoritative
|
|
20
|
+
* set; .dark overrides the seeds and re-tunes percentages where the recipe
|
|
21
|
+
* hits different optima on a dark surface.
|
|
22
|
+
*
|
|
23
|
+
* Derivation for a target lightness L: X = (L_target − L_bg) / (L_fg − L_bg)
|
|
24
|
+
*
|
|
25
|
+
* Apps re-theme by overriding the two seeds after this import; everything
|
|
26
|
+
* else tracks automatically. The chatbot's original hand-authored palette is
|
|
27
|
+
* this exact derivation with seeds fg 0.145 (light) and bg 0.145 / fg 0.985
|
|
28
|
+
* (dark) — override only the seeds and it renders visually identical.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
@theme inline {
|
|
32
|
+
--color-background: var(--background);
|
|
33
|
+
--color-foreground: var(--foreground);
|
|
34
|
+
--color-card: var(--card);
|
|
35
|
+
--color-card-foreground: var(--card-foreground);
|
|
36
|
+
--color-popover: var(--popover);
|
|
37
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
38
|
+
--color-primary: var(--primary);
|
|
39
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
40
|
+
--color-secondary: var(--secondary);
|
|
41
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
42
|
+
--color-muted: var(--muted);
|
|
43
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
44
|
+
--color-accent: var(--accent);
|
|
45
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
46
|
+
--color-destructive: var(--destructive);
|
|
47
|
+
--color-border: var(--border);
|
|
48
|
+
--color-input: var(--input);
|
|
49
|
+
--color-ring: var(--ring);
|
|
50
|
+
--color-chart-1: var(--chart-1);
|
|
51
|
+
--color-chart-2: var(--chart-2);
|
|
52
|
+
--color-chart-3: var(--chart-3);
|
|
53
|
+
--color-chart-4: var(--chart-4);
|
|
54
|
+
--color-chart-5: var(--chart-5);
|
|
55
|
+
--color-sidebar: var(--sidebar);
|
|
56
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
57
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
58
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
59
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
60
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
61
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
62
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
63
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
64
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
65
|
+
--radius-lg: var(--radius);
|
|
66
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
:root {
|
|
70
|
+
/* The two seeds. Everything chromeless below derives from these. */
|
|
71
|
+
--background: oklch(1 0 0);
|
|
72
|
+
--foreground: oklch(0.293 0 0);
|
|
73
|
+
|
|
74
|
+
--radius: 0.625rem;
|
|
75
|
+
|
|
76
|
+
--card: var(--background);
|
|
77
|
+
--card-foreground: var(--foreground);
|
|
78
|
+
--popover: var(--background);
|
|
79
|
+
--popover-foreground: var(--foreground);
|
|
80
|
+
|
|
81
|
+
--primary: color-mix(in oklab, var(--foreground) 93%, var(--background));
|
|
82
|
+
--primary-foreground: color-mix(in oklab, var(--foreground) 2%, var(--background));
|
|
83
|
+
|
|
84
|
+
--secondary: color-mix(in oklab, var(--foreground) 4%, var(--background));
|
|
85
|
+
--secondary-foreground: color-mix(in oklab, var(--foreground) 93%, var(--background));
|
|
86
|
+
|
|
87
|
+
--muted: color-mix(in oklab, var(--foreground) 4%, var(--background));
|
|
88
|
+
--muted-foreground: color-mix(in oklab, var(--foreground) 52%, var(--background));
|
|
89
|
+
|
|
90
|
+
--accent: color-mix(in oklab, var(--foreground) 4%, var(--background));
|
|
91
|
+
--accent-foreground: color-mix(in oklab, var(--foreground) 93%, var(--background));
|
|
92
|
+
|
|
93
|
+
--border: color-mix(in oklab, var(--foreground) 9%, var(--background));
|
|
94
|
+
--input: color-mix(in oklab, var(--foreground) 9%, var(--background));
|
|
95
|
+
|
|
96
|
+
/* Neutral by default. Apps with a brand accent point this at it
|
|
97
|
+
(zyler: `--ring: var(--editor-accent)`). */
|
|
98
|
+
--ring: color-mix(in oklab, var(--foreground) 42%, var(--background));
|
|
99
|
+
|
|
100
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
101
|
+
|
|
102
|
+
/* Chart series colors carry chroma — literal, not seed-derived. */
|
|
103
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
|
104
|
+
--chart-2: oklch(0.6 0.118 184.704);
|
|
105
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
|
106
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
107
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
108
|
+
|
|
109
|
+
--sidebar: color-mix(in oklab, var(--foreground) 2%, var(--background));
|
|
110
|
+
/* Aliases resolve at use time, so the .dark block below doesn't need to
|
|
111
|
+
repeat them — they track their target's dark value automatically. */
|
|
112
|
+
--sidebar-foreground: var(--foreground);
|
|
113
|
+
--sidebar-primary: var(--primary);
|
|
114
|
+
--sidebar-primary-foreground: var(--primary-foreground);
|
|
115
|
+
--sidebar-accent: var(--accent);
|
|
116
|
+
--sidebar-accent-foreground: var(--accent-foreground);
|
|
117
|
+
--sidebar-border: var(--border);
|
|
118
|
+
--sidebar-ring: var(--ring);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.dark {
|
|
122
|
+
--background: oklch(0.213 0 0);
|
|
123
|
+
--foreground: oklch(0.952 0 0);
|
|
124
|
+
|
|
125
|
+
--card: color-mix(in oklab, var(--foreground) 7%, var(--background));
|
|
126
|
+
--popover: color-mix(in oklab, var(--foreground) 7%, var(--background));
|
|
127
|
+
|
|
128
|
+
--primary: color-mix(in oklab, var(--foreground) 93%, var(--background));
|
|
129
|
+
--primary-foreground: color-mix(in oklab, var(--foreground) 7%, var(--background));
|
|
130
|
+
|
|
131
|
+
--secondary: color-mix(in oklab, var(--foreground) 15%, var(--background));
|
|
132
|
+
--secondary-foreground: var(--foreground);
|
|
133
|
+
|
|
134
|
+
--muted: color-mix(in oklab, var(--foreground) 15%, var(--background));
|
|
135
|
+
--muted-foreground: color-mix(in oklab, var(--foreground) 67%, var(--background));
|
|
136
|
+
|
|
137
|
+
--accent: color-mix(in oklab, var(--foreground) 15%, var(--background));
|
|
138
|
+
--accent-foreground: var(--foreground);
|
|
139
|
+
|
|
140
|
+
/* Solid (not alpha) so every divider reads the same lightness regardless
|
|
141
|
+
of the surface underneath — 18% against bg lands at oklch L≈0.35.
|
|
142
|
+
--input stays alpha: input chrome reads as a translucent surface, not a
|
|
143
|
+
hairline divider. */
|
|
144
|
+
--border: color-mix(in oklab, var(--foreground) 18%, var(--background));
|
|
145
|
+
--input: color-mix(in oklab, var(--foreground) 15%, transparent);
|
|
146
|
+
|
|
147
|
+
--ring: color-mix(in oklab, var(--foreground) 49%, var(--background));
|
|
148
|
+
|
|
149
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
150
|
+
|
|
151
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
|
152
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
153
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
154
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
155
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
156
|
+
|
|
157
|
+
--sidebar: color-mix(in oklab, var(--foreground) 7%, var(--background));
|
|
158
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ocai/app-sdk-ui",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Shared design tokens and AI-app UI primitives for OceanAI products.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./tokens.css": "./dist/tokens.css",
|
|
16
|
+
"./chat.css": "./dist/chat.css",
|
|
17
|
+
"./package.json": "./package.json"
|
|
18
|
+
},
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"!dist/**/*.map"
|
|
25
|
+
],
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/ocai-labs/app-sdk-ui.git",
|
|
29
|
+
"directory": "packages/ui"
|
|
30
|
+
},
|
|
31
|
+
"sideEffects": [
|
|
32
|
+
"*.css"
|
|
33
|
+
],
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"@streamdown/math": "^1.0.0",
|
|
36
|
+
"ai": "^6.0.0",
|
|
37
|
+
"react": "^19.0.0",
|
|
38
|
+
"react-dom": "^19.0.0",
|
|
39
|
+
"streamdown": "^2.5.0"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"class-variance-authority": "^0.7.1",
|
|
43
|
+
"clsx": "^2.1.1",
|
|
44
|
+
"lucide-react": "^1.14.0",
|
|
45
|
+
"radix-ui": "^1.4.3",
|
|
46
|
+
"tailwind-merge": "^3.5.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@streamdown/math": "^1.0.2",
|
|
50
|
+
"@types/node": "^22.0.0",
|
|
51
|
+
"@types/react": "^19.0.0",
|
|
52
|
+
"@types/react-dom": "^19.0.0",
|
|
53
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
54
|
+
"ai": "^6.0.0",
|
|
55
|
+
"react": "^19.0.0",
|
|
56
|
+
"react-dom": "^19.0.0",
|
|
57
|
+
"streamdown": "^2.5.0",
|
|
58
|
+
"typescript": "~5.6.0",
|
|
59
|
+
"vite": "^8.0.16",
|
|
60
|
+
"vite-plugin-dts": "^4.5.4"
|
|
61
|
+
},
|
|
62
|
+
"scripts": {
|
|
63
|
+
"build": "vite build && cp src/tokens.css src/chat/chat.css dist/",
|
|
64
|
+
"dev": "vite build --watch",
|
|
65
|
+
"typecheck": "tsc --noEmit"
|
|
66
|
+
}
|
|
67
|
+
}
|