@anvia/cli 1.0.0-rc.10

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 ADDED
@@ -0,0 +1,15 @@
1
+ # @anvia/cli
2
+
3
+ Install editable, app-owned UI components on top of the headless `@anvia/react-ui` primitives.
4
+
5
+ ```sh
6
+ pnpm dlx @anvia/cli init vite
7
+ pnpm dlx @anvia/cli add chat
8
+ ```
9
+
10
+ `init` configures shadcn in an existing Next.js or Vite application. It does not create an app.
11
+ `add` writes components below the `components` alias from `components.json` (normally
12
+ `src/components/anvia`) and installs the matching `@anvia/react-ui` release.
13
+
14
+ Available items: `chat`, `thread`, `message`, `composer`, `attachment`, `markdown`, and
15
+ `tool-fallback`.
@@ -0,0 +1,135 @@
1
+ // src/index.ts
2
+ import { spawnSync } from "child_process";
3
+ import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "fs";
4
+ import { createRequire } from "module";
5
+ import { tmpdir } from "os";
6
+ import { basename, join } from "path";
7
+ import { fileURLToPath } from "url";
8
+ var registryItemNames = [
9
+ "chat",
10
+ "thread",
11
+ "message",
12
+ "composer",
13
+ "attachment",
14
+ "markdown",
15
+ "tool-fallback"
16
+ ];
17
+ var itemFiles = {
18
+ attachment: ["attachment.tsx"],
19
+ chat: [
20
+ "attachment.tsx",
21
+ "markdown.tsx",
22
+ "tool-fallback.tsx",
23
+ "message.tsx",
24
+ "composer.tsx",
25
+ "thread.tsx",
26
+ "chat.tsx"
27
+ ],
28
+ composer: ["attachment.tsx", "composer.tsx"],
29
+ markdown: ["markdown.tsx"],
30
+ message: ["attachment.tsx", "markdown.tsx", "tool-fallback.tsx", "message.tsx"],
31
+ thread: ["attachment.tsx", "markdown.tsx", "tool-fallback.tsx", "message.tsx", "thread.tsx"],
32
+ "tool-fallback": ["tool-fallback.tsx"]
33
+ };
34
+ var revealCss = {
35
+ "@keyframes anvia-stream-gradient-settle": {
36
+ to: {
37
+ opacity: "1"
38
+ }
39
+ },
40
+ "@layer components": {
41
+ '.anvia-markdown [data-state="revealing"]': {
42
+ animation: "anvia-stream-gradient-settle var(--anvia-stream-reveal-duration, 180ms) linear both",
43
+ opacity: "var(--anvia-stream-reveal-opacity, 1)"
44
+ },
45
+ "@media (prefers-reduced-motion: reduce)": {
46
+ '.anvia-markdown [data-state="revealing"]': {
47
+ animation: "none",
48
+ opacity: "1"
49
+ }
50
+ }
51
+ }
52
+ };
53
+ function createRegistryItem(name, options = {}) {
54
+ const packageVersion = options.packageVersion ?? currentPackageVersion();
55
+ const registryDirectory = options.registryDirectory ?? bundledRegistryDirectory();
56
+ const files = itemFiles[name].map((filename) => ({
57
+ content: readFileSync(join(registryDirectory, filename), "utf8"),
58
+ path: `registry/anvia/${filename}`,
59
+ target: `@components/anvia/${filename}`,
60
+ type: "registry:component"
61
+ }));
62
+ const item = {
63
+ $schema: "https://ui.shadcn.com/schema/registry-item.json",
64
+ dependencies: [`@anvia/react-ui@${packageVersion}`],
65
+ description: registryItemDescription(name),
66
+ files,
67
+ name,
68
+ title: `Anvia ${name}`,
69
+ type: files.length === 1 ? "registry:component" : "registry:block"
70
+ };
71
+ if (name === "chat" || name === "markdown" || name === "message" || name === "thread") {
72
+ item.css = revealCss;
73
+ }
74
+ return item;
75
+ }
76
+ function initializeProject(options = {}) {
77
+ const cwd = options.cwd ?? process.cwd();
78
+ const args = ["init", "--cwd", cwd, "--yes", "--no-monorepo", "--base", "radix"];
79
+ if (options.template !== void 0) args.push("--template", options.template);
80
+ if (options.force === true) args.push("--force");
81
+ runShadcn(args);
82
+ }
83
+ function addRegistryItem(name, options = {}) {
84
+ const cwd = options.cwd ?? process.cwd();
85
+ const temporaryDirectory = mkdtempSync(join(tmpdir(), "anvia-registry-"));
86
+ const itemPath = join(temporaryDirectory, `${name}.json`);
87
+ try {
88
+ writeFileSync(itemPath, `${JSON.stringify(createRegistryItem(name), null, 2)}
89
+ `);
90
+ const args = ["add", itemPath, "--cwd", cwd, "--yes"];
91
+ if (options.overwrite === true) args.push("--overwrite");
92
+ runShadcn(args);
93
+ } finally {
94
+ rmSync(temporaryDirectory, { force: true, recursive: true });
95
+ }
96
+ }
97
+ function isRegistryItemName(value) {
98
+ return registryItemNames.includes(value);
99
+ }
100
+ function runShadcn(args) {
101
+ const require2 = createRequire(import.meta.url);
102
+ const shadcnEntry = require2.resolve("shadcn");
103
+ const result = spawnSync(process.execPath, [shadcnEntry, ...args], {
104
+ encoding: "utf8",
105
+ stdio: "inherit"
106
+ });
107
+ if (result.error !== void 0) throw result.error;
108
+ if (result.status !== 0) {
109
+ throw new Error(`shadcn ${args[0] ?? "command"} failed with exit code ${result.status}.`);
110
+ }
111
+ }
112
+ function bundledRegistryDirectory() {
113
+ return fileURLToPath(new URL("./registry/", import.meta.url));
114
+ }
115
+ function currentPackageVersion() {
116
+ const manifestPath = fileURLToPath(new URL("../package.json", import.meta.url));
117
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
118
+ if (typeof manifest.version !== "string") {
119
+ throw new Error(`Missing package version in ${basename(manifestPath)}.`);
120
+ }
121
+ return manifest.version;
122
+ }
123
+ function registryItemDescription(name) {
124
+ if (name === "chat") return "A complete editable Anvia chat interface.";
125
+ return `Editable Anvia ${name} UI.`;
126
+ }
127
+
128
+ export {
129
+ registryItemNames,
130
+ createRegistryItem,
131
+ initializeProject,
132
+ addRegistryItem,
133
+ isRegistryItemName
134
+ };
135
+ //# sourceMappingURL=chunk-TE2ODJOV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport { mkdtempSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { tmpdir } from \"node:os\";\nimport { basename, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport const registryItemNames = [\n \"chat\",\n \"thread\",\n \"message\",\n \"composer\",\n \"attachment\",\n \"markdown\",\n \"tool-fallback\",\n] as const;\n\nexport type RegistryItemName = (typeof registryItemNames)[number];\n\ntype RegistryFile = {\n content: string;\n path: string;\n target: string;\n type: \"registry:component\";\n};\n\ntype RegistryCss = {\n [rule: string]: RegistryCss | string;\n};\n\nexport type AnviaRegistryItem = {\n $schema: string;\n css?: RegistryCss;\n dependencies: string[];\n description: string;\n files: RegistryFile[];\n name: RegistryItemName;\n title: string;\n type: \"registry:block\" | \"registry:component\";\n};\n\nconst itemFiles: Record<RegistryItemName, readonly string[]> = {\n attachment: [\"attachment.tsx\"],\n chat: [\n \"attachment.tsx\",\n \"markdown.tsx\",\n \"tool-fallback.tsx\",\n \"message.tsx\",\n \"composer.tsx\",\n \"thread.tsx\",\n \"chat.tsx\",\n ],\n composer: [\"attachment.tsx\", \"composer.tsx\"],\n markdown: [\"markdown.tsx\"],\n message: [\"attachment.tsx\", \"markdown.tsx\", \"tool-fallback.tsx\", \"message.tsx\"],\n thread: [\"attachment.tsx\", \"markdown.tsx\", \"tool-fallback.tsx\", \"message.tsx\", \"thread.tsx\"],\n \"tool-fallback\": [\"tool-fallback.tsx\"],\n};\n\nconst revealCss = {\n \"@keyframes anvia-stream-gradient-settle\": {\n to: {\n opacity: \"1\",\n },\n },\n \"@layer components\": {\n '.anvia-markdown [data-state=\"revealing\"]': {\n animation:\n \"anvia-stream-gradient-settle var(--anvia-stream-reveal-duration, 180ms) linear both\",\n opacity: \"var(--anvia-stream-reveal-opacity, 1)\",\n },\n \"@media (prefers-reduced-motion: reduce)\": {\n '.anvia-markdown [data-state=\"revealing\"]': {\n animation: \"none\",\n opacity: \"1\",\n },\n },\n },\n} satisfies RegistryCss;\n\nexport function createRegistryItem(\n name: RegistryItemName,\n options: { packageVersion?: string; registryDirectory?: string } = {},\n): AnviaRegistryItem {\n const packageVersion = options.packageVersion ?? currentPackageVersion();\n const registryDirectory = options.registryDirectory ?? bundledRegistryDirectory();\n const files = itemFiles[name].map((filename) => ({\n content: readFileSync(join(registryDirectory, filename), \"utf8\"),\n path: `registry/anvia/${filename}`,\n target: `@components/anvia/${filename}`,\n type: \"registry:component\" as const,\n }));\n const item: AnviaRegistryItem = {\n $schema: \"https://ui.shadcn.com/schema/registry-item.json\",\n dependencies: [`@anvia/react-ui@${packageVersion}`],\n description: registryItemDescription(name),\n files,\n name,\n title: `Anvia ${name}`,\n type: files.length === 1 ? \"registry:component\" : \"registry:block\",\n };\n if (name === \"chat\" || name === \"markdown\" || name === \"message\" || name === \"thread\") {\n item.css = revealCss;\n }\n return item;\n}\n\nexport function initializeProject(\n options: { cwd?: string; force?: boolean; template?: \"next\" | \"vite\" } = {},\n): void {\n const cwd = options.cwd ?? process.cwd();\n const args = [\"init\", \"--cwd\", cwd, \"--yes\", \"--no-monorepo\", \"--base\", \"radix\"];\n if (options.template !== undefined) args.push(\"--template\", options.template);\n if (options.force === true) args.push(\"--force\");\n runShadcn(args);\n}\n\nexport function addRegistryItem(\n name: RegistryItemName,\n options: { cwd?: string; overwrite?: boolean } = {},\n): void {\n const cwd = options.cwd ?? process.cwd();\n const temporaryDirectory = mkdtempSync(join(tmpdir(), \"anvia-registry-\"));\n const itemPath = join(temporaryDirectory, `${name}.json`);\n try {\n writeFileSync(itemPath, `${JSON.stringify(createRegistryItem(name), null, 2)}\\n`);\n const args = [\"add\", itemPath, \"--cwd\", cwd, \"--yes\"];\n if (options.overwrite === true) args.push(\"--overwrite\");\n runShadcn(args);\n } finally {\n rmSync(temporaryDirectory, { force: true, recursive: true });\n }\n}\n\nexport function isRegistryItemName(value: string): value is RegistryItemName {\n return registryItemNames.includes(value as RegistryItemName);\n}\n\nfunction runShadcn(args: string[]): void {\n const require = createRequire(import.meta.url);\n const shadcnEntry = require.resolve(\"shadcn\");\n const result = spawnSync(process.execPath, [shadcnEntry, ...args], {\n encoding: \"utf8\",\n stdio: \"inherit\",\n });\n if (result.error !== undefined) throw result.error;\n if (result.status !== 0) {\n throw new Error(`shadcn ${args[0] ?? \"command\"} failed with exit code ${result.status}.`);\n }\n}\n\nfunction bundledRegistryDirectory(): string {\n return fileURLToPath(new URL(\"./registry/\", import.meta.url));\n}\n\nfunction currentPackageVersion(): string {\n const manifestPath = fileURLToPath(new URL(\"../package.json\", import.meta.url));\n const manifest = JSON.parse(readFileSync(manifestPath, \"utf8\")) as { version?: unknown };\n if (typeof manifest.version !== \"string\") {\n throw new Error(`Missing package version in ${basename(manifestPath)}.`);\n }\n return manifest.version;\n}\n\nfunction registryItemDescription(name: RegistryItemName): string {\n if (name === \"chat\") return \"A complete editable Anvia chat interface.\";\n return `Editable Anvia ${name} UI.`;\n}\n"],"mappings":"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","names":["require"]}
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/cli.js ADDED
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ addRegistryItem,
4
+ initializeProject,
5
+ isRegistryItemName,
6
+ registryItemNames
7
+ } from "./chunk-TE2ODJOV.js";
8
+
9
+ // src/cli.ts
10
+ function main(args) {
11
+ const [command, ...commandArgs] = args;
12
+ const cwd = optionValue(commandArgs, "--cwd");
13
+ const positional = commandArgs.filter(
14
+ (value, index) => !value.startsWith("--") && (index === 0 || commandArgs[index - 1] !== "--cwd")
15
+ );
16
+ if (command === "init") {
17
+ const value = positional[0];
18
+ if (positional.length > 1 || value !== void 0 && value !== "next" && value !== "vite") {
19
+ throw new Error("The init template must be next or vite.");
20
+ }
21
+ const options = {
22
+ force: commandArgs.includes("--force")
23
+ };
24
+ if (cwd !== void 0) options.cwd = cwd;
25
+ if (value === "next" || value === "vite") options.template = value;
26
+ initializeProject(options);
27
+ console.log("Anvia UI configuration is ready.");
28
+ return;
29
+ }
30
+ if (command === "add") {
31
+ const value = positional[0];
32
+ if (value === void 0 || positional.length !== 1 || !isRegistryItemName(value)) {
33
+ throw new Error(`Choose an item: ${registryItemNames.join(", ")}.`);
34
+ }
35
+ const options = {
36
+ overwrite: commandArgs.includes("--overwrite")
37
+ };
38
+ if (cwd !== void 0) options.cwd = cwd;
39
+ addRegistryItem(value, options);
40
+ console.log(`Added Anvia ${value}.`);
41
+ return;
42
+ }
43
+ console.log(`Usage:
44
+ anvia init [next|vite] [--cwd <path>] [--force]
45
+ anvia add <${registryItemNames.join("|")}> [--cwd <path>] [--overwrite]`);
46
+ }
47
+ function optionValue(args, name) {
48
+ const index = args.indexOf(name);
49
+ if (index === -1) return void 0;
50
+ const value = args[index + 1];
51
+ if (value === void 0 || value.startsWith("--")) {
52
+ throw new Error(`${name} requires a value.`);
53
+ }
54
+ return value;
55
+ }
56
+ try {
57
+ main(process.argv.slice(2));
58
+ } catch (error) {
59
+ console.error(error instanceof Error ? error.message : String(error));
60
+ process.exitCode = 1;
61
+ }
62
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { addRegistryItem, initializeProject, isRegistryItemName, registryItemNames } from \"./index\";\n\nfunction main(args: string[]): void {\n const [command, ...commandArgs] = args;\n const cwd = optionValue(commandArgs, \"--cwd\");\n const positional = commandArgs.filter(\n (value, index) =>\n !value.startsWith(\"--\") && (index === 0 || commandArgs[index - 1] !== \"--cwd\"),\n );\n\n if (command === \"init\") {\n const value = positional[0];\n if (positional.length > 1 || (value !== undefined && value !== \"next\" && value !== \"vite\")) {\n throw new Error(\"The init template must be next or vite.\");\n }\n const options: Parameters<typeof initializeProject>[0] = {\n force: commandArgs.includes(\"--force\"),\n };\n if (cwd !== undefined) options.cwd = cwd;\n if (value === \"next\" || value === \"vite\") options.template = value;\n initializeProject(options);\n console.log(\"Anvia UI configuration is ready.\");\n return;\n }\n\n if (command === \"add\") {\n const value = positional[0];\n if (value === undefined || positional.length !== 1 || !isRegistryItemName(value)) {\n throw new Error(`Choose an item: ${registryItemNames.join(\", \")}.`);\n }\n const options: Parameters<typeof addRegistryItem>[1] = {\n overwrite: commandArgs.includes(\"--overwrite\"),\n };\n if (cwd !== undefined) options.cwd = cwd;\n addRegistryItem(value, options);\n console.log(`Added Anvia ${value}.`);\n return;\n }\n\n console.log(`Usage:\n anvia init [next|vite] [--cwd <path>] [--force]\n anvia add <${registryItemNames.join(\"|\")}> [--cwd <path>] [--overwrite]`);\n}\n\nfunction optionValue(args: string[], name: string): string | undefined {\n const index = args.indexOf(name);\n if (index === -1) return undefined;\n const value = args[index + 1];\n if (value === undefined || value.startsWith(\"--\")) {\n throw new Error(`${name} requires a value.`);\n }\n return value;\n}\n\ntry {\n main(process.argv.slice(2));\n} catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exitCode = 1;\n}\n"],"mappings":";;;;;;;;;AAGA,SAAS,KAAK,MAAsB;AAClC,QAAM,CAAC,SAAS,GAAG,WAAW,IAAI;AAClC,QAAM,MAAM,YAAY,aAAa,OAAO;AAC5C,QAAM,aAAa,YAAY;AAAA,IAC7B,CAAC,OAAO,UACN,CAAC,MAAM,WAAW,IAAI,MAAM,UAAU,KAAK,YAAY,QAAQ,CAAC,MAAM;AAAA,EAC1E;AAEA,MAAI,YAAY,QAAQ;AACtB,UAAM,QAAQ,WAAW,CAAC;AAC1B,QAAI,WAAW,SAAS,KAAM,UAAU,UAAa,UAAU,UAAU,UAAU,QAAS;AAC1F,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC3D;AACA,UAAM,UAAmD;AAAA,MACvD,OAAO,YAAY,SAAS,SAAS;AAAA,IACvC;AACA,QAAI,QAAQ,OAAW,SAAQ,MAAM;AACrC,QAAI,UAAU,UAAU,UAAU,OAAQ,SAAQ,WAAW;AAC7D,sBAAkB,OAAO;AACzB,YAAQ,IAAI,kCAAkC;AAC9C;AAAA,EACF;AAEA,MAAI,YAAY,OAAO;AACrB,UAAM,QAAQ,WAAW,CAAC;AAC1B,QAAI,UAAU,UAAa,WAAW,WAAW,KAAK,CAAC,mBAAmB,KAAK,GAAG;AAChF,YAAM,IAAI,MAAM,mBAAmB,kBAAkB,KAAK,IAAI,CAAC,GAAG;AAAA,IACpE;AACA,UAAM,UAAiD;AAAA,MACrD,WAAW,YAAY,SAAS,aAAa;AAAA,IAC/C;AACA,QAAI,QAAQ,OAAW,SAAQ,MAAM;AACrC,oBAAgB,OAAO,OAAO;AAC9B,YAAQ,IAAI,eAAe,KAAK,GAAG;AACnC;AAAA,EACF;AAEA,UAAQ,IAAI;AAAA;AAAA,eAEC,kBAAkB,KAAK,GAAG,CAAC,gCAAgC;AAC1E;AAEA,SAAS,YAAY,MAAgB,MAAkC;AACrE,QAAM,QAAQ,KAAK,QAAQ,IAAI;AAC/B,MAAI,UAAU,GAAI,QAAO;AACzB,QAAM,QAAQ,KAAK,QAAQ,CAAC;AAC5B,MAAI,UAAU,UAAa,MAAM,WAAW,IAAI,GAAG;AACjD,UAAM,IAAI,MAAM,GAAG,IAAI,oBAAoB;AAAA,EAC7C;AACA,SAAO;AACT;AAEA,IAAI;AACF,OAAK,QAAQ,KAAK,MAAM,CAAC,CAAC;AAC5B,SAAS,OAAO;AACd,UAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AACpE,UAAQ,WAAW;AACrB;","names":[]}
@@ -0,0 +1,37 @@
1
+ declare const registryItemNames: readonly ["chat", "thread", "message", "composer", "attachment", "markdown", "tool-fallback"];
2
+ type RegistryItemName = (typeof registryItemNames)[number];
3
+ type RegistryFile = {
4
+ content: string;
5
+ path: string;
6
+ target: string;
7
+ type: "registry:component";
8
+ };
9
+ type RegistryCss = {
10
+ [rule: string]: RegistryCss | string;
11
+ };
12
+ type AnviaRegistryItem = {
13
+ $schema: string;
14
+ css?: RegistryCss;
15
+ dependencies: string[];
16
+ description: string;
17
+ files: RegistryFile[];
18
+ name: RegistryItemName;
19
+ title: string;
20
+ type: "registry:block" | "registry:component";
21
+ };
22
+ declare function createRegistryItem(name: RegistryItemName, options?: {
23
+ packageVersion?: string;
24
+ registryDirectory?: string;
25
+ }): AnviaRegistryItem;
26
+ declare function initializeProject(options?: {
27
+ cwd?: string;
28
+ force?: boolean;
29
+ template?: "next" | "vite";
30
+ }): void;
31
+ declare function addRegistryItem(name: RegistryItemName, options?: {
32
+ cwd?: string;
33
+ overwrite?: boolean;
34
+ }): void;
35
+ declare function isRegistryItemName(value: string): value is RegistryItemName;
36
+
37
+ export { type AnviaRegistryItem, type RegistryItemName, addRegistryItem, createRegistryItem, initializeProject, isRegistryItemName, registryItemNames };
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ import {
2
+ addRegistryItem,
3
+ createRegistryItem,
4
+ initializeProject,
5
+ isRegistryItemName,
6
+ registryItemNames
7
+ } from "./chunk-TE2ODJOV.js";
8
+ export {
9
+ addRegistryItem,
10
+ createRegistryItem,
11
+ initializeProject,
12
+ isRegistryItemName,
13
+ registryItemNames
14
+ };
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,27 @@
1
+ "use client";
2
+
3
+ import { AttachmentPrimitive } from "@anvia/react-ui";
4
+ import type { ComponentProps } from "react";
5
+
6
+ export function Attachment({
7
+ className,
8
+ ...props
9
+ }: ComponentProps<typeof AttachmentPrimitive.Root>) {
10
+ return (
11
+ <AttachmentPrimitive.Root
12
+ className={[
13
+ "flex min-w-0 items-center gap-3 rounded-xl border bg-card px-3 py-2 text-card-foreground shadow-sm",
14
+ className,
15
+ ]
16
+ .filter(Boolean)
17
+ .join(" ")}
18
+ {...props}
19
+ >
20
+ <AttachmentPrimitive.Preview className="size-10 shrink-0 overflow-hidden rounded-lg bg-muted [&_img]:size-full [&_img]:object-cover" />
21
+ <AttachmentPrimitive.Name className="min-w-0 flex-1 truncate text-sm" />
22
+ <AttachmentPrimitive.Remove className="rounded-md px-2 py-1 text-xs text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:pointer-events-none disabled:opacity-50">
23
+ Remove
24
+ </AttachmentPrimitive.Remove>
25
+ </AttachmentPrimitive.Root>
26
+ );
27
+ }
@@ -0,0 +1,8 @@
1
+ "use client";
2
+
3
+ import type { ComponentProps } from "react";
4
+ import { Thread } from "./thread";
5
+
6
+ export function Chat(props: ComponentProps<typeof Thread>) {
7
+ return <Thread {...props} />;
8
+ }
@@ -0,0 +1,56 @@
1
+ "use client";
2
+
3
+ import { ComposerPrimitive } from "@anvia/react-ui";
4
+ import type { ComponentProps } from "react";
5
+ import { Attachment } from "./attachment";
6
+
7
+ type ComposerProps = Omit<ComponentProps<typeof ComposerPrimitive.Root>, "children">;
8
+
9
+ export function Composer({ className, ...props }: ComposerProps) {
10
+ return (
11
+ <ComposerPrimitive.Root
12
+ className={["relative rounded-2xl border bg-background p-2 shadow-lg", className]
13
+ .filter(Boolean)
14
+ .join(" ")}
15
+ {...props}
16
+ >
17
+ <ComposerPrimitive.Attachments className="mb-2 flex flex-wrap gap-2 px-1">
18
+ <Attachment />
19
+ </ComposerPrimitive.Attachments>
20
+ <ComposerPrimitive.Quote className="mx-1 mb-2 rounded-lg border-l-2 border-primary bg-muted px-3 py-2 text-sm" />
21
+ <ComposerPrimitive.Input
22
+ className="min-h-12 max-h-48 overflow-y-auto px-2 py-3 text-sm outline-none [&_.ProseMirror]:outline-none"
23
+ placeholder="Send a message..."
24
+ />
25
+ <ComposerPrimitive.TriggerMenu className="z-50 max-h-72 min-w-56 overflow-auto rounded-xl border bg-popover p-1 text-popover-foreground shadow-md">
26
+ {(trigger) =>
27
+ trigger.loading ? (
28
+ <div className="px-3 py-2 text-sm text-muted-foreground">Loading...</div>
29
+ ) : (
30
+ trigger.items.map((item, index) => (
31
+ <ComposerPrimitive.TriggerItem
32
+ className="flex w-full items-center rounded-lg px-3 py-2 text-left text-sm data-[state=selected]:bg-accent data-[state=disabled]:opacity-50"
33
+ index={index}
34
+ item={item}
35
+ key={item.id}
36
+ />
37
+ ))
38
+ )
39
+ }
40
+ </ComposerPrimitive.TriggerMenu>
41
+ <div className="flex items-center justify-between gap-2 px-1 pb-1">
42
+ <ComposerPrimitive.AddAttachment className="rounded-lg px-3 py-2 text-sm text-muted-foreground hover:bg-muted hover:text-foreground">
43
+ Attach
44
+ </ComposerPrimitive.AddAttachment>
45
+ <div className="flex items-center gap-2">
46
+ <ComposerPrimitive.Stop className="rounded-lg border px-3 py-2 text-sm data-[state=disabled]:hidden">
47
+ Stop
48
+ </ComposerPrimitive.Stop>
49
+ <ComposerPrimitive.Submit className="rounded-lg bg-primary px-4 py-2 text-sm font-medium text-primary-foreground disabled:pointer-events-none disabled:opacity-50">
50
+ Send
51
+ </ComposerPrimitive.Submit>
52
+ </div>
53
+ </div>
54
+ </ComposerPrimitive.Root>
55
+ );
56
+ }
@@ -0,0 +1,21 @@
1
+ "use client";
2
+
3
+ import { MessagePrimitive } from "@anvia/react-ui";
4
+ import type { ComponentProps } from "react";
5
+
6
+ export function Markdown({
7
+ className,
8
+ ...props
9
+ }: ComponentProps<typeof MessagePrimitive.Markdown>) {
10
+ return (
11
+ <MessagePrimitive.Markdown
12
+ className={[
13
+ "anvia-markdown max-w-none text-sm leading-7 text-current [&_a]:text-primary [&_a]:underline [&_a]:underline-offset-2 [&_blockquote]:border-l-2 [&_blockquote]:pl-4 [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_h1]:mt-6 [&_h1]:text-2xl [&_h1]:font-semibold [&_h2]:mt-5 [&_h2]:text-xl [&_h2]:font-semibold [&_h3]:mt-4 [&_h3]:text-lg [&_h3]:font-semibold [&_li]:ml-5 [&_ol]:list-decimal [&_p]:my-3 [&_pre]:overflow-auto [&_pre]:rounded-xl [&_pre]:bg-muted [&_pre]:p-4 [&_strong]:font-semibold [&_table]:w-full [&_ul]:list-disc",
14
+ className,
15
+ ]
16
+ .filter(Boolean)
17
+ .join(" ")}
18
+ {...props}
19
+ />
20
+ );
21
+ }
@@ -0,0 +1,61 @@
1
+ "use client";
2
+
3
+ import { MessagePrimitive, useChatContext, useMessage } from "@anvia/react-ui";
4
+ import type { ComponentProps } from "react";
5
+ import { Attachment } from "./attachment";
6
+ import { Markdown } from "./markdown";
7
+ import { ToolFallback } from "./tool-fallback";
8
+
9
+ export function Message({ className, ...props }: ComponentProps<typeof MessagePrimitive.Root>) {
10
+ const chat = useChatContext();
11
+ const { message } = useMessage();
12
+ const isLastAssistant = message.role === "assistant" && chat.messages.at(-1)?.id === message.id;
13
+
14
+ return (
15
+ <MessagePrimitive.Root
16
+ className={[
17
+ "group flex w-full flex-col gap-2 py-3 data-[role=user]:items-end data-[role=assistant]:items-start",
18
+ className,
19
+ ]
20
+ .filter(Boolean)
21
+ .join(" ")}
22
+ {...props}
23
+ >
24
+ <MessagePrimitive.Content className="max-w-[85%] rounded-2xl bg-muted px-4 py-3 text-sm group-data-[role=user]:bg-primary group-data-[role=user]:text-primary-foreground">
25
+ <MessagePrimitive.Parts
26
+ className="grid gap-2"
27
+ stream={{
28
+ flushImmediately: chat.status === "error",
29
+ isStreaming: chat.status === "streaming" && isLastAssistant,
30
+ resetKey: message.id,
31
+ }}
32
+ >
33
+ {(part) => (
34
+ <MessagePrimitive.Part>
35
+ {part.type === "text" ? <Markdown /> : null}
36
+ {part.type === "reasoning" ? (
37
+ <MessagePrimitive.Reasoning className="text-muted-foreground" />
38
+ ) : null}
39
+ {part.type === "tool" ? <ToolFallback /> : null}
40
+ {part.type === "attachment" ? (
41
+ <MessagePrimitive.Attachment>
42
+ <Attachment />
43
+ </MessagePrimitive.Attachment>
44
+ ) : null}
45
+ {part.type === "data" ? (
46
+ <MessagePrimitive.Data className="overflow-auto whitespace-pre-wrap text-xs" />
47
+ ) : null}
48
+ {part.type === "error" ? (
49
+ <MessagePrimitive.Error className="text-destructive" />
50
+ ) : null}
51
+ </MessagePrimitive.Part>
52
+ )}
53
+ </MessagePrimitive.Parts>
54
+ </MessagePrimitive.Content>
55
+ <MessagePrimitive.Actions className="flex gap-1 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100">
56
+ <MessagePrimitive.Copy className="rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground" />
57
+ <MessagePrimitive.Regenerate className="rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground" />
58
+ </MessagePrimitive.Actions>
59
+ </MessagePrimitive.Root>
60
+ );
61
+ }
@@ -0,0 +1,37 @@
1
+ "use client";
2
+
3
+ import { ThreadPrimitive } from "@anvia/react-ui";
4
+ import type { ComponentProps } from "react";
5
+ import { Composer } from "./composer";
6
+ import { Message } from "./message";
7
+
8
+ type ThreadProps = Omit<ComponentProps<typeof ThreadPrimitive.Root>, "children">;
9
+
10
+ export function Thread({ className, ...props }: ThreadProps) {
11
+ return (
12
+ <ThreadPrimitive.Root
13
+ className={["relative flex h-full min-h-0 flex-col bg-background text-foreground", className]
14
+ .filter(Boolean)
15
+ .join(" ")}
16
+ {...props}
17
+ >
18
+ <ThreadPrimitive.Viewport className="min-h-0 flex-1 overflow-y-auto px-4">
19
+ <div className="mx-auto flex min-h-full w-full max-w-3xl flex-col">
20
+ <ThreadPrimitive.Empty className="m-auto py-16 text-center text-sm text-muted-foreground">
21
+ Start a conversation.
22
+ </ThreadPrimitive.Empty>
23
+ <ThreadPrimitive.Messages className="mt-auto py-4">
24
+ <Message />
25
+ </ThreadPrimitive.Messages>
26
+ <ThreadPrimitive.Error className="mb-3 rounded-xl bg-destructive/10 px-4 py-3 text-sm text-destructive" />
27
+ </div>
28
+ </ThreadPrimitive.Viewport>
29
+ <ThreadPrimitive.ScrollToBottom className="absolute bottom-28 left-1/2 -translate-x-1/2 rounded-full border bg-background px-3 py-2 text-xs shadow-sm data-[state=bottom]:hidden">
30
+ Jump to latest
31
+ </ThreadPrimitive.ScrollToBottom>
32
+ <ThreadPrimitive.ViewportFooter className="mx-auto w-full max-w-3xl px-4 pb-4">
33
+ <Composer />
34
+ </ThreadPrimitive.ViewportFooter>
35
+ </ThreadPrimitive.Root>
36
+ );
37
+ }
@@ -0,0 +1,33 @@
1
+ "use client";
2
+
3
+ import { MessagePrimitive } from "@anvia/react-ui";
4
+ import type { ComponentProps } from "react";
5
+
6
+ export function ToolFallback({
7
+ className,
8
+ ...props
9
+ }: ComponentProps<typeof MessagePrimitive.Tool>) {
10
+ return (
11
+ <MessagePrimitive.Tool
12
+ className={["my-2 overflow-hidden rounded-xl border bg-muted/30 text-sm", className]
13
+ .filter(Boolean)
14
+ .join(" ")}
15
+ {...props}
16
+ >
17
+ <div className="flex items-center justify-between border-b px-3 py-2">
18
+ <MessagePrimitive.ToolName className="font-medium" />
19
+ <MessagePrimitive.ToolStatus className="text-xs text-muted-foreground" />
20
+ </div>
21
+ <details className="group">
22
+ <summary className="cursor-pointer px-3 py-2 text-xs text-muted-foreground">
23
+ Details
24
+ </summary>
25
+ <div className="grid gap-3 border-t p-3">
26
+ <MessagePrimitive.ToolInput className="overflow-auto whitespace-pre-wrap rounded-lg bg-background p-3 text-xs" />
27
+ <MessagePrimitive.ToolOutput className="overflow-auto whitespace-pre-wrap rounded-lg bg-background p-3 text-xs" />
28
+ <MessagePrimitive.ToolError className="rounded-lg bg-destructive/10 p-3 text-destructive" />
29
+ </div>
30
+ </details>
31
+ </MessagePrimitive.Tool>
32
+ );
33
+ }
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@anvia/cli",
3
+ "version": "1.0.0-rc.10",
4
+ "description": "Install editable Anvia UI components into React applications.",
5
+ "author": "anvia",
6
+ "maintainer": "Indra Zulfi",
7
+ "license": "MIT",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/anvia-hq/anvia",
11
+ "directory": "packages/cli"
12
+ },
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "type": "module",
20
+ "bin": {
21
+ "anvia": "./dist/cli.js"
22
+ },
23
+ "exports": {
24
+ ".": {
25
+ "types": "./dist/index.d.ts",
26
+ "import": "./dist/index.js"
27
+ }
28
+ },
29
+ "engines": {
30
+ "node": ">=20.18.1"
31
+ },
32
+ "scripts": {
33
+ "build": "tsup src/index.ts src/cli.ts --format esm --dts --sourcemap --clean && node scripts/copy-registry.mjs && chmod +x dist/cli.js",
34
+ "test": "vitest run",
35
+ "typecheck": "tsc --noEmit && tsc --project registry/tsconfig.json --noEmit"
36
+ },
37
+ "dependencies": {
38
+ "shadcn": "^4.19.0"
39
+ },
40
+ "devDependencies": {
41
+ "@anvia/react-ui": "workspace:*",
42
+ "@types/node": "^24.9.1",
43
+ "@types/react": "^19.2.14",
44
+ "react": "19.2.6",
45
+ "tsup": "^8.5.0",
46
+ "typescript": "^5.9.3",
47
+ "vitest": "^4.0.8"
48
+ }
49
+ }