@lastbrain/ai-ui-react 1.0.3

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.
Files changed (70) hide show
  1. package/README.md +84 -0
  2. package/dist/components/AiChipLabel.d.ts +8 -0
  3. package/dist/components/AiChipLabel.d.ts.map +1 -0
  4. package/dist/components/AiChipLabel.js +39 -0
  5. package/dist/components/AiImageButton.d.ts +8 -0
  6. package/dist/components/AiImageButton.d.ts.map +1 -0
  7. package/dist/components/AiImageButton.js +36 -0
  8. package/dist/components/AiInput.d.ts +7 -0
  9. package/dist/components/AiInput.d.ts.map +1 -0
  10. package/dist/components/AiInput.js +77 -0
  11. package/dist/components/AiModelSelect.d.ts +10 -0
  12. package/dist/components/AiModelSelect.d.ts.map +1 -0
  13. package/dist/components/AiModelSelect.js +5 -0
  14. package/dist/components/AiPromptPanel.d.ts +22 -0
  15. package/dist/components/AiPromptPanel.d.ts.map +1 -0
  16. package/dist/components/AiPromptPanel.js +30 -0
  17. package/dist/components/AiSelect.d.ts +8 -0
  18. package/dist/components/AiSelect.d.ts.map +1 -0
  19. package/dist/components/AiSelect.js +38 -0
  20. package/dist/components/AiSettingsButton.d.ts +11 -0
  21. package/dist/components/AiSettingsButton.d.ts.map +1 -0
  22. package/dist/components/AiSettingsButton.js +16 -0
  23. package/dist/components/AiTextarea.d.ts +7 -0
  24. package/dist/components/AiTextarea.d.ts.map +1 -0
  25. package/dist/components/AiTextarea.js +79 -0
  26. package/dist/context/AiProvider.d.ts +18 -0
  27. package/dist/context/AiProvider.d.ts.map +1 -0
  28. package/dist/context/AiProvider.js +20 -0
  29. package/dist/hooks/useAiCallImage.d.ts +12 -0
  30. package/dist/hooks/useAiCallImage.d.ts.map +1 -0
  31. package/dist/hooks/useAiCallImage.js +29 -0
  32. package/dist/hooks/useAiCallText.d.ts +12 -0
  33. package/dist/hooks/useAiCallText.d.ts.map +1 -0
  34. package/dist/hooks/useAiCallText.js +29 -0
  35. package/dist/hooks/useAiClient.d.ts +12 -0
  36. package/dist/hooks/useAiClient.d.ts.map +1 -0
  37. package/dist/hooks/useAiClient.js +13 -0
  38. package/dist/hooks/useAiModels.d.ts +13 -0
  39. package/dist/hooks/useAiModels.d.ts.map +1 -0
  40. package/dist/hooks/useAiModels.js +32 -0
  41. package/dist/hooks/useAiStatus.d.ts +13 -0
  42. package/dist/hooks/useAiStatus.d.ts.map +1 -0
  43. package/dist/hooks/useAiStatus.js +32 -0
  44. package/dist/hooks/usePrompts.d.ts +35 -0
  45. package/dist/hooks/usePrompts.d.ts.map +1 -0
  46. package/dist/hooks/usePrompts.js +125 -0
  47. package/dist/index.d.ts +17 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +20 -0
  50. package/dist/types.d.ts +20 -0
  51. package/dist/types.d.ts.map +1 -0
  52. package/dist/types.js +1 -0
  53. package/package.json +60 -0
  54. package/src/components/AiChipLabel.tsx +88 -0
  55. package/src/components/AiImageButton.tsx +87 -0
  56. package/src/components/AiInput.tsx +150 -0
  57. package/src/components/AiModelSelect.tsx +37 -0
  58. package/src/components/AiPromptPanel.tsx +120 -0
  59. package/src/components/AiSelect.tsx +91 -0
  60. package/src/components/AiSettingsButton.tsx +111 -0
  61. package/src/components/AiTextarea.tsx +152 -0
  62. package/src/context/AiProvider.tsx +44 -0
  63. package/src/hooks/useAiCallImage.ts +49 -0
  64. package/src/hooks/useAiCallText.ts +49 -0
  65. package/src/hooks/useAiClient.ts +23 -0
  66. package/src/hooks/useAiModels.ts +50 -0
  67. package/src/hooks/useAiStatus.ts +50 -0
  68. package/src/hooks/usePrompts.ts +187 -0
  69. package/src/index.ts +23 -0
  70. package/src/types.ts +20 -0
@@ -0,0 +1,12 @@
1
+ import type { AiTextRequest, AiTextResponse } from "@lastbrain/ai-ui-core";
2
+ export interface UseAiCallTextOptions {
3
+ baseUrl?: string;
4
+ apiKeyId?: string;
5
+ }
6
+ export interface UseAiCallTextResult {
7
+ generateText: (request: AiTextRequest) => Promise<AiTextResponse>;
8
+ loading: boolean;
9
+ error: Error | null;
10
+ }
11
+ export declare function useAiCallText(options?: UseAiCallTextOptions): UseAiCallTextResult;
12
+ //# sourceMappingURL=useAiCallText.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAiCallText.d.ts","sourceRoot":"","sources":["../../src/hooks/useAiCallText.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG3E,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAClE,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED,wBAAgB,aAAa,CAC3B,OAAO,CAAC,EAAE,oBAAoB,GAC7B,mBAAmB,CA6BrB"}
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { useState, useCallback } from "react";
3
+ import { useAiClient } from "./useAiClient";
4
+ export function useAiCallText(options) {
5
+ const client = useAiClient(options);
6
+ const [loading, setLoading] = useState(false);
7
+ const [error, setError] = useState(null);
8
+ const generateText = useCallback(async (request) => {
9
+ setLoading(true);
10
+ setError(null);
11
+ try {
12
+ const result = await client.generateText(request);
13
+ return result;
14
+ }
15
+ catch (err) {
16
+ const error = err instanceof Error ? err : new Error("Failed to generate text");
17
+ setError(error);
18
+ throw error;
19
+ }
20
+ finally {
21
+ setLoading(false);
22
+ }
23
+ }, [client]);
24
+ return {
25
+ generateText,
26
+ loading,
27
+ error,
28
+ };
29
+ }
@@ -0,0 +1,12 @@
1
+ export interface UseAiClientOptions {
2
+ baseUrl?: string;
3
+ apiKeyId?: string;
4
+ }
5
+ export declare function useAiClient(options?: UseAiClientOptions): {
6
+ getModels: () => Promise<import("@lastbrain/ai-ui-core").ModelRef[]>;
7
+ generateText: (req: import("@lastbrain/ai-ui-core").AiTextRequest) => Promise<import("@lastbrain/ai-ui-core").AiTextResponse>;
8
+ generateImage: (req: import("@lastbrain/ai-ui-core").AiImageRequest) => Promise<import("@lastbrain/ai-ui-core").AiImageResponse>;
9
+ embed: (req: import("@lastbrain/ai-ui-core").AiEmbedRequest) => Promise<import("@lastbrain/ai-ui-core").AiEmbedResponse>;
10
+ getStatus: () => Promise<import("@lastbrain/ai-ui-core").AiStatus>;
11
+ };
12
+ //# sourceMappingURL=useAiClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAiClient.d.ts","sourceRoot":"","sources":["../../src/hooks/useAiClient.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,kBAAkB;;;;;;EAWvD"}
@@ -0,0 +1,13 @@
1
+ "use client";
2
+ import { useMemo } from "react";
3
+ import { createClient } from "@lastbrain/ai-ui-core";
4
+ import { useAiContext } from "../context/AiProvider";
5
+ export function useAiClient(options) {
6
+ const context = useAiContext();
7
+ const client = useMemo(() => {
8
+ const baseUrl = options?.baseUrl || context.baseUrl;
9
+ const apiKeyId = options?.apiKeyId || context.apiKeyId;
10
+ return createClient({ baseUrl, apiKeyId });
11
+ }, [options?.baseUrl, options?.apiKeyId, context.baseUrl, context.apiKeyId]);
12
+ return client;
13
+ }
@@ -0,0 +1,13 @@
1
+ import type { ModelRef } from "@lastbrain/ai-ui-core";
2
+ export interface UseAiModelsOptions {
3
+ baseUrl?: string;
4
+ apiKeyId?: string;
5
+ }
6
+ export interface UseAiModelsResult {
7
+ models: ModelRef[] | null;
8
+ loading: boolean;
9
+ error: Error | null;
10
+ refetch: () => void;
11
+ }
12
+ export declare function useAiModels(options?: UseAiModelsOptions): UseAiModelsResult;
13
+ //# sourceMappingURL=useAiModels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAiModels.d.ts","sourceRoot":"","sources":["../../src/hooks/useAiModels.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGtD,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,CA+B3E"}
@@ -0,0 +1,32 @@
1
+ "use client";
2
+ import { useState, useEffect, useCallback } from "react";
3
+ import { useAiClient } from "./useAiClient";
4
+ export function useAiModels(options) {
5
+ const client = useAiClient(options);
6
+ const [models, setModels] = useState(null);
7
+ const [loading, setLoading] = useState(false);
8
+ const [error, setError] = useState(null);
9
+ const fetchModels = useCallback(async () => {
10
+ setLoading(true);
11
+ setError(null);
12
+ try {
13
+ const result = await client.getModels();
14
+ setModels(result);
15
+ }
16
+ catch (err) {
17
+ setError(err instanceof Error ? err : new Error("Failed to fetch models"));
18
+ }
19
+ finally {
20
+ setLoading(false);
21
+ }
22
+ }, [client]);
23
+ useEffect(() => {
24
+ fetchModels();
25
+ }, [fetchModels]);
26
+ return {
27
+ models,
28
+ loading,
29
+ error,
30
+ refetch: fetchModels,
31
+ };
32
+ }
@@ -0,0 +1,13 @@
1
+ import type { AiStatus } from "@lastbrain/ai-ui-core";
2
+ export interface UseAiStatusOptions {
3
+ baseUrl?: string;
4
+ apiKeyId?: string;
5
+ }
6
+ export interface UseAiStatusResult {
7
+ status: AiStatus | null;
8
+ loading: boolean;
9
+ error: Error | null;
10
+ refetch: () => void;
11
+ }
12
+ export declare function useAiStatus(options?: UseAiStatusOptions): UseAiStatusResult;
13
+ //# sourceMappingURL=useAiStatus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAiStatus.d.ts","sourceRoot":"","sources":["../../src/hooks/useAiStatus.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGtD,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,CA+B3E"}
@@ -0,0 +1,32 @@
1
+ "use client";
2
+ import { useState, useEffect, useCallback } from "react";
3
+ import { useAiClient } from "./useAiClient";
4
+ export function useAiStatus(options) {
5
+ const client = useAiClient(options);
6
+ const [status, setStatus] = useState(null);
7
+ const [loading, setLoading] = useState(false);
8
+ const [error, setError] = useState(null);
9
+ const fetchStatus = useCallback(async () => {
10
+ setLoading(true);
11
+ setError(null);
12
+ try {
13
+ const result = await client.getStatus();
14
+ setStatus(result);
15
+ }
16
+ catch (err) {
17
+ setError(err instanceof Error ? err : new Error("Failed to fetch status"));
18
+ }
19
+ finally {
20
+ setLoading(false);
21
+ }
22
+ }, [client]);
23
+ useEffect(() => {
24
+ fetchStatus();
25
+ }, [fetchStatus]);
26
+ return {
27
+ status,
28
+ loading,
29
+ error,
30
+ refetch: fetchStatus,
31
+ };
32
+ }
@@ -0,0 +1,35 @@
1
+ export interface Prompt {
2
+ id: string;
3
+ slug?: string;
4
+ title: string;
5
+ content: string;
6
+ type: "text" | "image";
7
+ is_public: boolean;
8
+ favorite: boolean;
9
+ tags: string[];
10
+ created_at: string;
11
+ updated_at?: string;
12
+ }
13
+ export interface PublicPrompt extends Prompt {
14
+ slug: string;
15
+ views: number;
16
+ used_count: number;
17
+ picked_count: number;
18
+ }
19
+ export interface UsePromptsOptions {
20
+ type?: "text" | "image";
21
+ favorite?: boolean;
22
+ public?: boolean;
23
+ }
24
+ export interface UsePromptsReturn {
25
+ prompts: Prompt[] | PublicPrompt[];
26
+ loading: boolean;
27
+ error: string | null;
28
+ fetchPrompts: (options?: UsePromptsOptions) => Promise<void>;
29
+ createPrompt: (data: Omit<Prompt, "id" | "created_at" | "updated_at">) => Promise<Prompt | null>;
30
+ updatePrompt: (id: string, data: Partial<Prompt>) => Promise<Prompt | null>;
31
+ deletePrompt: (id: string) => Promise<boolean>;
32
+ incrementStat: (promptId: string, statType: "views" | "used" | "picked") => Promise<void>;
33
+ }
34
+ export declare function usePrompts(): UsePromptsReturn;
35
+ //# sourceMappingURL=usePrompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePrompts.d.ts","sourceRoot":"","sources":["../../src/hooks/usePrompts.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAa,SAAQ,MAAM;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,EAAE,GAAG,YAAY,EAAE,CAAC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,YAAY,EAAE,CAAC,OAAO,CAAC,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,YAAY,EAAE,CACZ,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,GAAG,YAAY,GAAG,YAAY,CAAC,KACnD,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5B,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5E,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,aAAa,EAAE,CACb,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,KAClC,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB;AAED,wBAAgB,UAAU,IAAI,gBAAgB,CA2I7C"}
@@ -0,0 +1,125 @@
1
+ "use client";
2
+ import { useState, useCallback } from "react";
3
+ import { useAiContext } from "../context/AiProvider";
4
+ export function usePrompts() {
5
+ const { apiKeyId } = useAiContext();
6
+ const [prompts, setPrompts] = useState([]);
7
+ const [loading, setLoading] = useState(false);
8
+ const [error, setError] = useState(null);
9
+ const fetchPrompts = useCallback(async (options) => {
10
+ try {
11
+ setLoading(true);
12
+ setError(null);
13
+ const params = new URLSearchParams();
14
+ if (options?.type)
15
+ params.append("type", options.type);
16
+ if (options?.favorite !== undefined)
17
+ params.append("favorite", String(options.favorite));
18
+ // Use public route without auth if public=true, otherwise use auth route
19
+ const endpoint = options?.public
20
+ ? `/api/ai/public/prompts?${params}`
21
+ : `/api/ai/auth/prompts?${params}`;
22
+ const response = await fetch(endpoint);
23
+ const data = await response.json();
24
+ if (response.ok) {
25
+ setPrompts(data.prompts || []);
26
+ }
27
+ else {
28
+ setError(data.error || "Failed to fetch prompts");
29
+ }
30
+ }
31
+ catch (err) {
32
+ setError(err instanceof Error ? err.message : "Unknown error");
33
+ }
34
+ finally {
35
+ setLoading(false);
36
+ }
37
+ }, []);
38
+ const createPrompt = useCallback(async (data) => {
39
+ try {
40
+ setError(null);
41
+ const response = await fetch("/api/ai/auth/prompts", {
42
+ method: "POST",
43
+ headers: { "Content-Type": "application/json" },
44
+ body: JSON.stringify(data),
45
+ });
46
+ const result = await response.json();
47
+ if (response.ok) {
48
+ return result.prompt;
49
+ }
50
+ else {
51
+ setError(result.error || "Failed to create prompt");
52
+ return null;
53
+ }
54
+ }
55
+ catch (err) {
56
+ setError(err instanceof Error ? err.message : "Unknown error");
57
+ return null;
58
+ }
59
+ }, []);
60
+ const updatePrompt = useCallback(async (id, data) => {
61
+ try {
62
+ setError(null);
63
+ const response = await fetch("/api/ai/auth/prompts", {
64
+ method: "PUT",
65
+ headers: { "Content-Type": "application/json" },
66
+ body: JSON.stringify({ id, ...data }),
67
+ });
68
+ const result = await response.json();
69
+ if (response.ok) {
70
+ return result.prompt;
71
+ }
72
+ else {
73
+ setError(result.error || "Failed to update prompt");
74
+ return null;
75
+ }
76
+ }
77
+ catch (err) {
78
+ setError(err instanceof Error ? err.message : "Unknown error");
79
+ return null;
80
+ }
81
+ }, []);
82
+ const deletePrompt = useCallback(async (id) => {
83
+ try {
84
+ setError(null);
85
+ const response = await fetch(`/api/ai/auth/prompts?id=${id}`, {
86
+ method: "DELETE",
87
+ });
88
+ const result = await response.json();
89
+ if (response.ok) {
90
+ return true;
91
+ }
92
+ else {
93
+ setError(result.error || "Failed to delete prompt");
94
+ return false;
95
+ }
96
+ }
97
+ catch (err) {
98
+ setError(err instanceof Error ? err.message : "Unknown error");
99
+ return false;
100
+ }
101
+ }, []);
102
+ const incrementStat = useCallback(async (promptId, statType) => {
103
+ try {
104
+ await fetch("/api/ai/auth/prompts/stats", {
105
+ method: "POST",
106
+ headers: { "Content-Type": "application/json" },
107
+ body: JSON.stringify({ prompt_id: promptId, stat_type: statType }),
108
+ });
109
+ }
110
+ catch (err) {
111
+ // Silent fail for stats
112
+ console.error("Failed to increment stat:", err);
113
+ }
114
+ }, []);
115
+ return {
116
+ prompts,
117
+ loading,
118
+ error,
119
+ fetchPrompts,
120
+ createPrompt,
121
+ updatePrompt,
122
+ deletePrompt,
123
+ incrementStat,
124
+ };
125
+ }
@@ -0,0 +1,17 @@
1
+ export * from "./types";
2
+ export * from "./context/AiProvider";
3
+ export * from "./hooks/useAiClient";
4
+ export * from "./hooks/useAiModels";
5
+ export * from "./hooks/useAiStatus";
6
+ export * from "./hooks/useAiCallText";
7
+ export * from "./hooks/useAiCallImage";
8
+ export * from "./hooks/usePrompts";
9
+ export * from "./components/AiPromptPanel";
10
+ export * from "./components/AiModelSelect";
11
+ export * from "./components/AiInput";
12
+ export * from "./components/AiTextarea";
13
+ export * from "./components/AiSelect";
14
+ export * from "./components/AiChipLabel";
15
+ export * from "./components/AiImageButton";
16
+ export * from "./components/AiSettingsButton";
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,SAAS,CAAC;AAGxB,cAAc,sBAAsB,CAAC;AAGrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,+BAA+B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ // Types
2
+ export * from "./types";
3
+ // Context
4
+ export * from "./context/AiProvider";
5
+ // Hooks
6
+ export * from "./hooks/useAiClient";
7
+ export * from "./hooks/useAiModels";
8
+ export * from "./hooks/useAiStatus";
9
+ export * from "./hooks/useAiCallText";
10
+ export * from "./hooks/useAiCallImage";
11
+ export * from "./hooks/usePrompts";
12
+ // Components
13
+ export * from "./components/AiPromptPanel";
14
+ export * from "./components/AiModelSelect";
15
+ export * from "./components/AiInput";
16
+ export * from "./components/AiTextarea";
17
+ export * from "./components/AiSelect";
18
+ export * from "./components/AiChipLabel";
19
+ export * from "./components/AiImageButton";
20
+ export * from "./components/AiSettingsButton";
@@ -0,0 +1,20 @@
1
+ export type ToastType = {
2
+ type: "success" | "error";
3
+ message: string;
4
+ code?: string;
5
+ };
6
+ export type UiMode = "modal" | "drawer";
7
+ export interface BaseAiProps {
8
+ baseUrl?: string;
9
+ apiKeyId?: string;
10
+ type?: UiMode;
11
+ context?: string | null;
12
+ model?: string | null;
13
+ prompt?: string | null;
14
+ editMode?: boolean;
15
+ onValue?: (value: string) => void;
16
+ onToast?: (toast: ToastType) => void;
17
+ disabled?: boolean;
18
+ className?: string;
19
+ }
20
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AACF,MAAM,MAAM,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAExC,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@lastbrain/ai-ui-react",
3
+ "version": "1.0.3",
4
+ "description": "Headless React components for LastBrain AI UI Kit",
5
+ "private": false,
6
+ "type": "module",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs",
14
+ "default": "./dist/index.js"
15
+ }
16
+ },
17
+ "release": {
18
+ "type": "public"
19
+ },
20
+ "keywords": [
21
+ "ai",
22
+ "lastbrain",
23
+ "react",
24
+ "headless",
25
+ "components",
26
+ "ui-kit"
27
+ ],
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/lastpublication/starter.git",
31
+ "directory": "packages/ai-ui-react"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "src"
39
+ ],
40
+ "sideEffects": false,
41
+ "peerDependencies": {
42
+ "react": ">=18.0.0",
43
+ "react-dom": ">=18.0.0"
44
+ },
45
+ "dependencies": {
46
+ "@lastbrain/ai-ui-core": "^1.0.3"
47
+ },
48
+ "devDependencies": {
49
+ "@types/react": "^19.2.0",
50
+ "@types/react-dom": "^19.2.0",
51
+ "react": "^19.2.1",
52
+ "react-dom": "^19.2.1",
53
+ "typescript": "^5.4.0"
54
+ },
55
+ "scripts": {
56
+ "dev": "tsc -p tsconfig.json --watch",
57
+ "build": "tsc -p tsconfig.json",
58
+ "lint": "eslint ."
59
+ }
60
+ }
@@ -0,0 +1,88 @@
1
+ "use client";
2
+
3
+ import { useState, type HTMLAttributes } from "react";
4
+ import type { BaseAiProps } from "../types";
5
+ import { useAiCallText } from "../hooks/useAiCallText";
6
+ import { useAiModels } from "../hooks/useAiModels";
7
+ import { AiPromptPanel } from "./AiPromptPanel";
8
+
9
+ export interface AiChipLabelProps
10
+ extends Omit<BaseAiProps, "type">, HTMLAttributes<HTMLDivElement> {
11
+ label?: string;
12
+ uiMode?: "modal" | "drawer";
13
+ }
14
+
15
+ export function AiChipLabel({
16
+ baseUrl,
17
+ apiKeyId,
18
+ uiMode = "modal",
19
+ context,
20
+ model,
21
+ prompt,
22
+ onValue,
23
+ onToast,
24
+ disabled,
25
+ className,
26
+ label,
27
+ ...divProps
28
+ }: AiChipLabelProps) {
29
+ const [isOpen, setIsOpen] = useState(false);
30
+ const [chipLabel, setChipLabel] = useState(label || "");
31
+
32
+ const { models } = useAiModels({ baseUrl, apiKeyId });
33
+ const { generateText, loading } = useAiCallText({ baseUrl, apiKeyId });
34
+
35
+ const handleOpenPanel = () => {
36
+ setIsOpen(true);
37
+ };
38
+
39
+ const handleClosePanel = () => {
40
+ setIsOpen(false);
41
+ };
42
+
43
+ const handleSubmit = async (
44
+ selectedModel: string,
45
+ selectedPrompt: string
46
+ ) => {
47
+ try {
48
+ const result = await generateText({
49
+ model: selectedModel,
50
+ prompt: selectedPrompt,
51
+ context: context || chipLabel || undefined,
52
+ });
53
+
54
+ if (result.text) {
55
+ setChipLabel(result.text);
56
+ onValue?.(result.text);
57
+ onToast?.({ type: "success", message: "Label generated successfully" });
58
+ }
59
+ } catch (error) {
60
+ onToast?.({ type: "error", message: "Failed to generate label" });
61
+ } finally {
62
+ setIsOpen(false);
63
+ }
64
+ };
65
+
66
+ return (
67
+ <div data-ai-chip-wrapper className={className} {...divProps}>
68
+ <div data-ai-chip-label>{chipLabel || "Generate label"}</div>
69
+ <button
70
+ onClick={handleOpenPanel}
71
+ disabled={disabled || loading}
72
+ data-ai-chip-button
73
+ type="button"
74
+ >
75
+ {loading ? "..." : "✨"}
76
+ </button>
77
+ {isOpen && (
78
+ <AiPromptPanel
79
+ isOpen={isOpen}
80
+ onClose={handleClosePanel}
81
+ onSubmit={handleSubmit}
82
+ uiMode={uiMode}
83
+ models={models || []}
84
+ />
85
+ )}
86
+ </div>
87
+ );
88
+ }
@@ -0,0 +1,87 @@
1
+ "use client";
2
+
3
+ import { useState, type ButtonHTMLAttributes } from "react";
4
+ import type { BaseAiProps } from "../types";
5
+ import { useAiCallImage } from "../hooks/useAiCallImage";
6
+ import { useAiModels } from "../hooks/useAiModels";
7
+ import { AiPromptPanel } from "./AiPromptPanel";
8
+
9
+ export interface AiImageButtonProps
10
+ extends
11
+ Omit<BaseAiProps, "onValue" | "type">,
12
+ ButtonHTMLAttributes<HTMLButtonElement> {
13
+ onImage?: (imageUrl: string) => void;
14
+ uiMode?: "modal" | "drawer";
15
+ }
16
+
17
+ export function AiImageButton({
18
+ baseUrl,
19
+ apiKeyId,
20
+ uiMode = "modal",
21
+ context,
22
+ model,
23
+ prompt,
24
+ onImage,
25
+ onToast,
26
+ disabled,
27
+ className,
28
+ children,
29
+ ...buttonProps
30
+ }: AiImageButtonProps) {
31
+ const [isOpen, setIsOpen] = useState(false);
32
+
33
+ const { models } = useAiModels({ baseUrl, apiKeyId });
34
+ const { generateImage, loading } = useAiCallImage({ baseUrl, apiKeyId });
35
+
36
+ const handleOpenPanel = () => {
37
+ setIsOpen(true);
38
+ };
39
+
40
+ const handleClosePanel = () => {
41
+ setIsOpen(false);
42
+ };
43
+
44
+ const handleSubmit = async (
45
+ selectedModel: string,
46
+ selectedPrompt: string
47
+ ) => {
48
+ try {
49
+ const result = await generateImage({
50
+ model: selectedModel,
51
+ prompt: selectedPrompt,
52
+ });
53
+
54
+ if (result.url) {
55
+ onImage?.(result.url);
56
+ onToast?.({ type: "success", message: "Image generated successfully" });
57
+ }
58
+ } catch (error) {
59
+ onToast?.({ type: "error", message: "Failed to generate image" });
60
+ } finally {
61
+ setIsOpen(false);
62
+ }
63
+ };
64
+
65
+ return (
66
+ <>
67
+ <button
68
+ {...buttonProps}
69
+ onClick={handleOpenPanel}
70
+ disabled={disabled || loading}
71
+ className={className}
72
+ data-ai-image-button
73
+ >
74
+ {loading ? "Generating..." : children || "Generate Image"}
75
+ </button>
76
+ {isOpen && (
77
+ <AiPromptPanel
78
+ isOpen={isOpen}
79
+ onClose={handleClosePanel}
80
+ onSubmit={handleSubmit}
81
+ uiMode={uiMode}
82
+ models={models?.filter((m) => m.type === "image") || []}
83
+ />
84
+ )}
85
+ </>
86
+ );
87
+ }