@fogui/react 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.
@@ -0,0 +1,69 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React from 'react';
3
+ import { U as UseFogUIReturn } from './index-BcLda68r.mjs';
4
+ export { d as ComponentBlock, C as ContentBlock, D as DynamicComponent, F as FogUIConfig, f as FogUIRenderer, b as FogUIResponse, S as StreamEvent, c as TextBlock, e as ThinkingItem, T as TransformOptions, a as TransformResult, g as defaultComponentRegistry } from './index-BcLda68r.mjs';
5
+
6
+ interface FogUIContextValue {
7
+ apiKey: string;
8
+ endpoint: string;
9
+ }
10
+ interface FogUIProviderProps {
11
+ children: React.ReactNode;
12
+ /**
13
+ * Your FogUI API key (get it from https://fogui.dev/dashboard)
14
+ */
15
+ apiKey: string;
16
+ }
17
+ /**
18
+ * FogUIProvider - Provides FogUI configuration to the component tree.
19
+ *
20
+ * @example
21
+ * ```tsx
22
+ * import { FogUIProvider } from '@fogui/react';
23
+ *
24
+ * function App() {
25
+ * return (
26
+ * <FogUIProvider apiKey="fog_xxxx">
27
+ * <MyApp />
28
+ * </FogUIProvider>
29
+ * );
30
+ * }
31
+ * ```
32
+ */
33
+ declare function FogUIProvider({ children, apiKey }: FogUIProviderProps): react_jsx_runtime.JSX.Element;
34
+ /**
35
+ * Hook to access FogUI context
36
+ * @internal
37
+ */
38
+ declare function useFogUIContext(): FogUIContextValue;
39
+
40
+ /**
41
+ * useFogUI - Main hook for transforming LLM output into structured UI.
42
+ *
43
+ * @example
44
+ * ```tsx
45
+ * import { useFogUI, FogUIRenderer } from '@fogui/react';
46
+ *
47
+ * function Chat() {
48
+ * const { transform, isLoading } = useFogUI();
49
+ * const [ui, setUI] = useState(null);
50
+ *
51
+ * const handleLLMResponse = async (llmOutput: string) => {
52
+ * const result = await transform(llmOutput);
53
+ * if (result.success) {
54
+ * setUI(result.result);
55
+ * }
56
+ * };
57
+ *
58
+ * return (
59
+ * <div>
60
+ * {isLoading && <p>Transforming...</p>}
61
+ * {ui && <FogUIRenderer response={ui} />}
62
+ * </div>
63
+ * );
64
+ * }
65
+ * ```
66
+ */
67
+ declare function useFogUI(): UseFogUIReturn;
68
+
69
+ export { FogUIProvider, type FogUIProviderProps, UseFogUIReturn, useFogUI, useFogUIContext };
@@ -0,0 +1,69 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React from 'react';
3
+ import { U as UseFogUIReturn } from './index-BcLda68r.js';
4
+ export { d as ComponentBlock, C as ContentBlock, D as DynamicComponent, F as FogUIConfig, f as FogUIRenderer, b as FogUIResponse, S as StreamEvent, c as TextBlock, e as ThinkingItem, T as TransformOptions, a as TransformResult, g as defaultComponentRegistry } from './index-BcLda68r.js';
5
+
6
+ interface FogUIContextValue {
7
+ apiKey: string;
8
+ endpoint: string;
9
+ }
10
+ interface FogUIProviderProps {
11
+ children: React.ReactNode;
12
+ /**
13
+ * Your FogUI API key (get it from https://fogui.dev/dashboard)
14
+ */
15
+ apiKey: string;
16
+ }
17
+ /**
18
+ * FogUIProvider - Provides FogUI configuration to the component tree.
19
+ *
20
+ * @example
21
+ * ```tsx
22
+ * import { FogUIProvider } from '@fogui/react';
23
+ *
24
+ * function App() {
25
+ * return (
26
+ * <FogUIProvider apiKey="fog_xxxx">
27
+ * <MyApp />
28
+ * </FogUIProvider>
29
+ * );
30
+ * }
31
+ * ```
32
+ */
33
+ declare function FogUIProvider({ children, apiKey }: FogUIProviderProps): react_jsx_runtime.JSX.Element;
34
+ /**
35
+ * Hook to access FogUI context
36
+ * @internal
37
+ */
38
+ declare function useFogUIContext(): FogUIContextValue;
39
+
40
+ /**
41
+ * useFogUI - Main hook for transforming LLM output into structured UI.
42
+ *
43
+ * @example
44
+ * ```tsx
45
+ * import { useFogUI, FogUIRenderer } from '@fogui/react';
46
+ *
47
+ * function Chat() {
48
+ * const { transform, isLoading } = useFogUI();
49
+ * const [ui, setUI] = useState(null);
50
+ *
51
+ * const handleLLMResponse = async (llmOutput: string) => {
52
+ * const result = await transform(llmOutput);
53
+ * if (result.success) {
54
+ * setUI(result.result);
55
+ * }
56
+ * };
57
+ *
58
+ * return (
59
+ * <div>
60
+ * {isLoading && <p>Transforming...</p>}
61
+ * {ui && <FogUIRenderer response={ui} />}
62
+ * </div>
63
+ * );
64
+ * }
65
+ * ```
66
+ */
67
+ declare function useFogUI(): UseFogUIReturn;
68
+
69
+ export { FogUIProvider, type FogUIProviderProps, UseFogUIReturn, useFogUI, useFogUIContext };
package/dist/index.js ADDED
@@ -0,0 +1,234 @@
1
+ 'use strict';
2
+
3
+ var React2 = require('react');
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+
6
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
+
8
+ var React2__default = /*#__PURE__*/_interopDefault(React2);
9
+
10
+ // src/FogUIProvider.tsx
11
+ var FOGUI_API_ENDPOINT = "https://api.fogui.dev";
12
+ var FogUIContext = React2.createContext(null);
13
+ function FogUIProvider({ children, apiKey }) {
14
+ if (!apiKey) {
15
+ console.warn("[FogUI] API key is required. Get one at https://fogui.dev/dashboard");
16
+ }
17
+ const value = React2.useMemo(() => ({
18
+ apiKey,
19
+ endpoint: FOGUI_API_ENDPOINT
20
+ }), [apiKey]);
21
+ return /* @__PURE__ */ jsxRuntime.jsx(FogUIContext.Provider, { value, children });
22
+ }
23
+ function useFogUIContext() {
24
+ const context = React2.useContext(FogUIContext);
25
+ if (!context) {
26
+ throw new Error('useFogUI must be used within a FogUIProvider. Wrap your app with <FogUIProvider apiKey="...">');
27
+ }
28
+ return context;
29
+ }
30
+ function useFogUI() {
31
+ const { endpoint, apiKey } = useFogUIContext();
32
+ const [isLoading, setIsLoading] = React2.useState(false);
33
+ const [error, setError] = React2.useState(null);
34
+ const transform = React2.useCallback(async (content, options = {}) => {
35
+ setIsLoading(true);
36
+ setError(null);
37
+ try {
38
+ const response = await fetch(`${endpoint}/fogui/transform`, {
39
+ method: "POST",
40
+ headers: {
41
+ "Content-Type": "application/json",
42
+ "Authorization": `Bearer ${apiKey}`
43
+ },
44
+ body: JSON.stringify({
45
+ content,
46
+ context: options.intent || options.preferredComponents || options.instructions ? {
47
+ intent: options.intent,
48
+ preferredComponents: options.preferredComponents,
49
+ instructions: options.instructions
50
+ } : void 0
51
+ })
52
+ });
53
+ if (!response.ok) {
54
+ const errorData = await response.json().catch(() => ({}));
55
+ throw new Error(errorData.error || `HTTP ${response.status}`);
56
+ }
57
+ const result = await response.json();
58
+ if (!result.success) {
59
+ setError(result.error || "Transformation failed");
60
+ }
61
+ return result;
62
+ } catch (err) {
63
+ const message = err instanceof Error ? err.message : "Unknown error";
64
+ setError(message);
65
+ return { success: false, error: message };
66
+ } finally {
67
+ setIsLoading(false);
68
+ }
69
+ }, [endpoint, apiKey]);
70
+ const transformStream = React2.useCallback(async function* (content, options = {}) {
71
+ setIsLoading(true);
72
+ setError(null);
73
+ try {
74
+ const response = await fetch(`${endpoint}/fogui/transform/stream`, {
75
+ method: "POST",
76
+ headers: {
77
+ "Content-Type": "application/json",
78
+ "Authorization": `Bearer ${apiKey}`
79
+ },
80
+ body: JSON.stringify({
81
+ content,
82
+ context: options.intent || options.instructions ? {
83
+ intent: options.intent,
84
+ instructions: options.instructions
85
+ } : void 0,
86
+ streaming: true
87
+ })
88
+ });
89
+ if (!response.ok) {
90
+ throw new Error(`HTTP ${response.status}`);
91
+ }
92
+ const reader = response.body?.getReader();
93
+ if (!reader) {
94
+ throw new Error("No response body");
95
+ }
96
+ const decoder = new TextDecoder();
97
+ let buffer = "";
98
+ let currentEvent = "";
99
+ while (true) {
100
+ const { done, value } = await reader.read();
101
+ if (done) break;
102
+ buffer += decoder.decode(value, { stream: true });
103
+ const lines = buffer.split("\n");
104
+ buffer = lines.pop() || "";
105
+ for (const line of lines) {
106
+ if (line.startsWith("event:")) {
107
+ currentEvent = line.substring(6).trim();
108
+ } else if (line.startsWith("data:")) {
109
+ const data = line.substring(5).trim();
110
+ if (data === "[DONE]") {
111
+ yield { type: "done", data: null };
112
+ continue;
113
+ }
114
+ if (data) {
115
+ try {
116
+ const parsed = JSON.parse(data);
117
+ yield { type: currentEvent, data: parsed };
118
+ } catch {
119
+ if (currentEvent === "chunk") {
120
+ yield { type: "chunk", data };
121
+ }
122
+ }
123
+ }
124
+ }
125
+ }
126
+ }
127
+ } catch (err) {
128
+ const message = err instanceof Error ? err.message : "Unknown error";
129
+ setError(message);
130
+ yield { type: "error", data: { error: message } };
131
+ } finally {
132
+ setIsLoading(false);
133
+ }
134
+ }, [endpoint, apiKey]);
135
+ const clearError = React2.useCallback(() => {
136
+ setError(null);
137
+ }, []);
138
+ return {
139
+ transform,
140
+ transformStream,
141
+ isLoading,
142
+ error,
143
+ clearError
144
+ };
145
+ }
146
+ function DefaultCard({ title, description, data }) {
147
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { border: "1px solid #e5e7eb", borderRadius: "8px", padding: "16px", marginBottom: "12px" }, children: [
148
+ title && /* @__PURE__ */ jsxRuntime.jsx("h3", { style: { margin: "0 0 8px", fontSize: "18px", fontWeight: 600 }, children: title }),
149
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: "0 0 12px", color: "#6b7280" }, children: description }),
150
+ data && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "14px" }, children: Object.entries(data).map(([key, value]) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", padding: "4px 0" }, children: [
151
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#6b7280" }, children: key }),
152
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 500 }, children: String(value) })
153
+ ] }, key)) })
154
+ ] });
155
+ }
156
+ function DefaultList({ title, items }) {
157
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginBottom: "12px" }, children: [
158
+ title && /* @__PURE__ */ jsxRuntime.jsx("h3", { style: { margin: "0 0 12px", fontSize: "18px", fontWeight: 600 }, children: title }),
159
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { style: { margin: 0, paddingLeft: "20px" }, children: items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { style: { marginBottom: "8px" }, children: typeof item === "object" ? JSON.stringify(item) : String(item) }, i)) })
160
+ ] });
161
+ }
162
+ function DefaultTable({ columns, rows }) {
163
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { overflowX: "auto", marginBottom: "12px" }, children: /* @__PURE__ */ jsxRuntime.jsxs("table", { style: { width: "100%", borderCollapse: "collapse", fontSize: "14px" }, children: [
164
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsx("tr", { children: columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx("th", { style: { textAlign: "left", padding: "12px 8px", borderBottom: "2px solid #e5e7eb", fontWeight: 600 }, children: col }, col)) }) }),
165
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: rows.map((row, i) => /* @__PURE__ */ jsxRuntime.jsx("tr", { children: columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx("td", { style: { padding: "12px 8px", borderBottom: "1px solid #e5e7eb" }, children: String(row[col] ?? "") }, col)) }, i)) })
166
+ ] }) });
167
+ }
168
+ function DefaultCallout({ title, message, variant = "info" }) {
169
+ const colors = {
170
+ info: { bg: "#eff6ff", border: "#3b82f6", text: "#1e40af" },
171
+ warning: { bg: "#fffbeb", border: "#f59e0b", text: "#92400e" },
172
+ tip: { bg: "#f0fdf4", border: "#22c55e", text: "#166534" }
173
+ };
174
+ const c = colors[variant];
175
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { backgroundColor: c.bg, borderLeft: `4px solid ${c.border}`, padding: "12px 16px", marginBottom: "12px", borderRadius: "0 8px 8px 0" }, children: [
176
+ title && /* @__PURE__ */ jsxRuntime.jsx("strong", { style: { color: c.text, display: "block", marginBottom: "4px" }, children: title }),
177
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: c.text }, children: message })
178
+ ] });
179
+ }
180
+ var defaultComponentRegistry = {
181
+ card: DefaultCard,
182
+ list: DefaultList,
183
+ table: DefaultTable,
184
+ callout: DefaultCallout
185
+ };
186
+ function DynamicComponent({ block, registry = defaultComponentRegistry }) {
187
+ const { componentType, props } = block;
188
+ const Component = registry[componentType];
189
+ if (!Component) {
190
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "12px", backgroundColor: "#fef3c7", border: "1px solid #fcd34d", borderRadius: "8px", fontSize: "14px" }, children: [
191
+ /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
192
+ "Unknown component: ",
193
+ componentType
194
+ ] }),
195
+ /* @__PURE__ */ jsxRuntime.jsx("pre", { style: { margin: "8px 0 0", fontSize: "12px", overflow: "auto" }, children: JSON.stringify(props, null, 2) })
196
+ ] });
197
+ }
198
+ return /* @__PURE__ */ jsxRuntime.jsx(Component, { ...props });
199
+ }
200
+ function FogUIRenderer({ response, componentRegistry, className }) {
201
+ const registry = componentRegistry || defaultComponentRegistry;
202
+ if (!response || !response.content) {
203
+ return null;
204
+ }
205
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: response.content.map((block, index) => /* @__PURE__ */ jsxRuntime.jsx(
206
+ ContentBlockRenderer,
207
+ {
208
+ block,
209
+ registry
210
+ },
211
+ index
212
+ )) });
213
+ }
214
+ function ContentBlockRenderer({ block, registry }) {
215
+ if (block.type === "text") {
216
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginBottom: "12px", lineHeight: 1.6 }, children: block.value.split("\n").map((line, i) => /* @__PURE__ */ jsxRuntime.jsxs(React2__default.default.Fragment, { children: [
217
+ line,
218
+ i < block.value.split("\n").length - 1 && /* @__PURE__ */ jsxRuntime.jsx("br", {})
219
+ ] }, i)) });
220
+ }
221
+ if (block.type === "component") {
222
+ return /* @__PURE__ */ jsxRuntime.jsx(DynamicComponent, { block, registry });
223
+ }
224
+ return null;
225
+ }
226
+
227
+ exports.DynamicComponent = DynamicComponent;
228
+ exports.FogUIProvider = FogUIProvider;
229
+ exports.FogUIRenderer = FogUIRenderer;
230
+ exports.defaultComponentRegistry = defaultComponentRegistry;
231
+ exports.useFogUI = useFogUI;
232
+ exports.useFogUIContext = useFogUIContext;
233
+ //# sourceMappingURL=index.js.map
234
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/FogUIProvider.tsx","../src/useFogUI.ts","../src/components/ComponentRegistry.tsx","../src/components/FogUIRenderer.tsx"],"names":["createContext","useMemo","jsx","useContext","useState","useCallback","jsxs","React"],"mappings":"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","file":"index.js","sourcesContent":["import React, { createContext, useContext, useMemo } from 'react';\n\n/**\n * FogUI Platform API endpoint\n */\nconst FOGUI_API_ENDPOINT = 'https://api.fogui.dev';\n\ninterface FogUIContextValue {\n apiKey: string;\n endpoint: string;\n}\n\nconst FogUIContext = createContext<FogUIContextValue | null>(null);\n\nexport interface FogUIProviderProps {\n children: React.ReactNode;\n /**\n * Your FogUI API key (get it from https://fogui.dev/dashboard)\n */\n apiKey: string;\n}\n\n/**\n * FogUIProvider - Provides FogUI configuration to the component tree.\n * \n * @example\n * ```tsx\n * import { FogUIProvider } from '@fogui/react';\n * \n * function App() {\n * return (\n * <FogUIProvider apiKey=\"fog_xxxx\">\n * <MyApp />\n * </FogUIProvider>\n * );\n * }\n * ```\n */\nexport function FogUIProvider({ children, apiKey }: FogUIProviderProps) {\n if (!apiKey) {\n console.warn('[FogUI] API key is required. Get one at https://fogui.dev/dashboard');\n }\n\n const value = useMemo<FogUIContextValue>(() => ({\n apiKey,\n endpoint: FOGUI_API_ENDPOINT,\n }), [apiKey]);\n\n return (\n <FogUIContext.Provider value={value}>\n {children}\n </FogUIContext.Provider>\n );\n}\n\n/**\n * Hook to access FogUI context\n * @internal\n */\nexport function useFogUIContext(): FogUIContextValue {\n const context = useContext(FogUIContext);\n if (!context) {\n throw new Error('useFogUI must be used within a FogUIProvider. Wrap your app with <FogUIProvider apiKey=\"...\">');\n }\n return context;\n}\n","import { useState, useCallback } from 'react';\nimport { useFogUIContext } from './FogUIProvider';\nimport type { TransformOptions, TransformResult, UseFogUIReturn, StreamEvent } from './types';\n\n/**\n * useFogUI - Main hook for transforming LLM output into structured UI.\n * \n * @example\n * ```tsx\n * import { useFogUI, FogUIRenderer } from '@fogui/react';\n * \n * function Chat() {\n * const { transform, isLoading } = useFogUI();\n * const [ui, setUI] = useState(null);\n * \n * const handleLLMResponse = async (llmOutput: string) => {\n * const result = await transform(llmOutput);\n * if (result.success) {\n * setUI(result.result);\n * }\n * };\n * \n * return (\n * <div>\n * {isLoading && <p>Transforming...</p>}\n * {ui && <FogUIRenderer response={ui} />}\n * </div>\n * );\n * }\n * ```\n */\nexport function useFogUI(): UseFogUIReturn {\n const { endpoint, apiKey } = useFogUIContext();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n /**\n * Transform raw LLM text into structured UI (non-streaming)\n */\n const transform = useCallback(async (\n content: string,\n options: TransformOptions = {}\n ): Promise<TransformResult> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const response = await fetch(`${endpoint}/fogui/transform`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n content,\n context: options.intent || options.preferredComponents || options.instructions ? {\n intent: options.intent,\n preferredComponents: options.preferredComponents,\n instructions: options.instructions,\n } : undefined,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n throw new Error(errorData.error || `HTTP ${response.status}`);\n }\n\n const result: TransformResult = await response.json();\n \n if (!result.success) {\n setError(result.error || 'Transformation failed');\n }\n\n return result;\n\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Unknown error';\n setError(message);\n return { success: false, error: message };\n } finally {\n setIsLoading(false);\n }\n }, [endpoint, apiKey]);\n\n /**\n * Transform with streaming - returns an async generator\n */\n const transformStream = useCallback(async function* (\n content: string,\n options: TransformOptions = {}\n ): AsyncGenerator<StreamEvent> {\n setIsLoading(true);\n setError(null);\n\n try {\n const response = await fetch(`${endpoint}/fogui/transform/stream`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`,\n },\n body: JSON.stringify({\n content,\n context: options.intent || options.instructions ? {\n intent: options.intent,\n instructions: options.instructions,\n } : undefined,\n streaming: true,\n }),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error('No response body');\n }\n\n const decoder = new TextDecoder();\n let buffer = '';\n let currentEvent = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (line.startsWith('event:')) {\n currentEvent = line.substring(6).trim();\n } else if (line.startsWith('data:')) {\n const data = line.substring(5).trim();\n \n if (data === '[DONE]') {\n yield { type: 'done', data: null };\n continue;\n }\n\n if (data) {\n try {\n const parsed = JSON.parse(data);\n yield { type: currentEvent as StreamEvent['type'], data: parsed };\n } catch {\n if (currentEvent === 'chunk') {\n yield { type: 'chunk', data };\n }\n }\n }\n }\n }\n }\n\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Unknown error';\n setError(message);\n yield { type: 'error', data: { error: message } };\n } finally {\n setIsLoading(false);\n }\n }, [endpoint, apiKey]);\n\n const clearError = useCallback(() => {\n setError(null);\n }, []);\n\n return {\n transform,\n transformStream,\n isLoading,\n error,\n clearError,\n };\n}\n","import React from 'react';\nimport type { ComponentBlock } from '../types';\n\n/**\n * Default component implementations.\n * These provide basic rendering - users should customize for their design system.\n */\n\n// Card Component\nfunction DefaultCard({ title, description, data }: { title?: string; description?: string; data?: Record<string, unknown> }) {\n return (\n <div style={{ border: '1px solid #e5e7eb', borderRadius: '8px', padding: '16px', marginBottom: '12px' }}>\n {title && <h3 style={{ margin: '0 0 8px', fontSize: '18px', fontWeight: 600 }}>{title}</h3>}\n {description && <p style={{ margin: '0 0 12px', color: '#6b7280' }}>{description}</p>}\n {data && (\n <div style={{ fontSize: '14px' }}>\n {Object.entries(data).map(([key, value]) => (\n <div key={key} style={{ display: 'flex', justifyContent: 'space-between', padding: '4px 0' }}>\n <span style={{ color: '#6b7280' }}>{key}</span>\n <span style={{ fontWeight: 500 }}>{String(value)}</span>\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n\n// List Component\nfunction DefaultList({ title, items }: { title?: string; items: unknown[] }) {\n return (\n <div style={{ marginBottom: '12px' }}>\n {title && <h3 style={{ margin: '0 0 12px', fontSize: '18px', fontWeight: 600 }}>{title}</h3>}\n <ul style={{ margin: 0, paddingLeft: '20px' }}>\n {items.map((item, i) => (\n <li key={i} style={{ marginBottom: '8px' }}>\n {typeof item === 'object' ? JSON.stringify(item) : String(item)}\n </li>\n ))}\n </ul>\n </div>\n );\n}\n\n// Table Component\nfunction DefaultTable({ columns, rows }: { columns: string[]; rows: Record<string, unknown>[] }) {\n return (\n <div style={{ overflowX: 'auto', marginBottom: '12px' }}>\n <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: '14px' }}>\n <thead>\n <tr>\n {columns.map((col) => (\n <th key={col} style={{ textAlign: 'left', padding: '12px 8px', borderBottom: '2px solid #e5e7eb', fontWeight: 600 }}>\n {col}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((row, i) => (\n <tr key={i}>\n {columns.map((col) => (\n <td key={col} style={{ padding: '12px 8px', borderBottom: '1px solid #e5e7eb' }}>\n {String(row[col] ?? '')}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\n// Callout Component\nfunction DefaultCallout({ title, message, variant = 'info' }: { title?: string; message: string; variant?: 'info' | 'warning' | 'tip' }) {\n const colors = {\n info: { bg: '#eff6ff', border: '#3b82f6', text: '#1e40af' },\n warning: { bg: '#fffbeb', border: '#f59e0b', text: '#92400e' },\n tip: { bg: '#f0fdf4', border: '#22c55e', text: '#166534' },\n };\n const c = colors[variant];\n return (\n <div style={{ backgroundColor: c.bg, borderLeft: `4px solid ${c.border}`, padding: '12px 16px', marginBottom: '12px', borderRadius: '0 8px 8px 0' }}>\n {title && <strong style={{ color: c.text, display: 'block', marginBottom: '4px' }}>{title}</strong>}\n <span style={{ color: c.text }}>{message}</span>\n </div>\n );\n}\n\n/**\n * Default component registry mapping componentType to React components.\n * Users can override this with their own components.\n */\nexport const defaultComponentRegistry: Record<string, React.ComponentType<any>> = {\n card: DefaultCard,\n list: DefaultList,\n table: DefaultTable,\n callout: DefaultCallout,\n};\n\ninterface DynamicComponentProps {\n block: ComponentBlock;\n registry?: Record<string, React.ComponentType<any>>;\n}\n\n/**\n * DynamicComponent - Renders a component based on componentType.\n */\nexport function DynamicComponent({ block, registry = defaultComponentRegistry }: DynamicComponentProps) {\n const { componentType, props } = block;\n const Component = registry[componentType];\n\n if (!Component) {\n return (\n <div style={{ padding: '12px', backgroundColor: '#fef3c7', border: '1px solid #fcd34d', borderRadius: '8px', fontSize: '14px' }}>\n <strong>Unknown component: {componentType}</strong>\n <pre style={{ margin: '8px 0 0', fontSize: '12px', overflow: 'auto' }}>\n {JSON.stringify(props, null, 2)}\n </pre>\n </div>\n );\n }\n\n return <Component {...props} />;\n}\n","import React from 'react';\nimport type { FogUIResponse, ContentBlock } from '../types';\nimport { DynamicComponent, defaultComponentRegistry } from './ComponentRegistry';\n\ninterface FogUIRendererProps {\n /**\n * The FogUIResponse to render\n */\n response: FogUIResponse;\n /**\n * Custom component registry to override default components\n */\n componentRegistry?: Record<string, React.ComponentType<any>>;\n /**\n * Custom className for the container\n */\n className?: string;\n}\n\n/**\n * FogUIRenderer - Renders a FogUIResponse as React components.\n * \n * @example\n * ```tsx\n * import { FogUIRenderer } from '@fogui/react';\n * \n * function Chat({ response }) {\n * return <FogUIRenderer response={response} />;\n * }\n * ```\n */\nexport function FogUIRenderer({ response, componentRegistry, className }: FogUIRendererProps) {\n const registry = componentRegistry || defaultComponentRegistry;\n\n if (!response || !response.content) {\n return null;\n }\n\n return (\n <div className={className}>\n {response.content.map((block, index) => (\n <ContentBlockRenderer \n key={index} \n block={block} \n registry={registry}\n />\n ))}\n </div>\n );\n}\n\ninterface ContentBlockRendererProps {\n block: ContentBlock;\n registry: Record<string, React.ComponentType<any>>;\n}\n\nfunction ContentBlockRenderer({ block, registry }: ContentBlockRendererProps) {\n if (block.type === 'text') {\n return (\n <div style={{ marginBottom: '12px', lineHeight: 1.6 }}>\n {block.value.split('\\n').map((line, i) => (\n <React.Fragment key={i}>\n {line}\n {i < block.value.split('\\n').length - 1 && <br />}\n </React.Fragment>\n ))}\n </div>\n );\n }\n\n if (block.type === 'component') {\n return <DynamicComponent block={block} registry={registry} />;\n }\n\n return null;\n}\n"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,223 @@
1
+ import React2, { createContext, useMemo, useContext, useState, useCallback } from 'react';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+
4
+ // src/FogUIProvider.tsx
5
+ var FOGUI_API_ENDPOINT = "https://api.fogui.dev";
6
+ var FogUIContext = createContext(null);
7
+ function FogUIProvider({ children, apiKey }) {
8
+ if (!apiKey) {
9
+ console.warn("[FogUI] API key is required. Get one at https://fogui.dev/dashboard");
10
+ }
11
+ const value = useMemo(() => ({
12
+ apiKey,
13
+ endpoint: FOGUI_API_ENDPOINT
14
+ }), [apiKey]);
15
+ return /* @__PURE__ */ jsx(FogUIContext.Provider, { value, children });
16
+ }
17
+ function useFogUIContext() {
18
+ const context = useContext(FogUIContext);
19
+ if (!context) {
20
+ throw new Error('useFogUI must be used within a FogUIProvider. Wrap your app with <FogUIProvider apiKey="...">');
21
+ }
22
+ return context;
23
+ }
24
+ function useFogUI() {
25
+ const { endpoint, apiKey } = useFogUIContext();
26
+ const [isLoading, setIsLoading] = useState(false);
27
+ const [error, setError] = useState(null);
28
+ const transform = useCallback(async (content, options = {}) => {
29
+ setIsLoading(true);
30
+ setError(null);
31
+ try {
32
+ const response = await fetch(`${endpoint}/fogui/transform`, {
33
+ method: "POST",
34
+ headers: {
35
+ "Content-Type": "application/json",
36
+ "Authorization": `Bearer ${apiKey}`
37
+ },
38
+ body: JSON.stringify({
39
+ content,
40
+ context: options.intent || options.preferredComponents || options.instructions ? {
41
+ intent: options.intent,
42
+ preferredComponents: options.preferredComponents,
43
+ instructions: options.instructions
44
+ } : void 0
45
+ })
46
+ });
47
+ if (!response.ok) {
48
+ const errorData = await response.json().catch(() => ({}));
49
+ throw new Error(errorData.error || `HTTP ${response.status}`);
50
+ }
51
+ const result = await response.json();
52
+ if (!result.success) {
53
+ setError(result.error || "Transformation failed");
54
+ }
55
+ return result;
56
+ } catch (err) {
57
+ const message = err instanceof Error ? err.message : "Unknown error";
58
+ setError(message);
59
+ return { success: false, error: message };
60
+ } finally {
61
+ setIsLoading(false);
62
+ }
63
+ }, [endpoint, apiKey]);
64
+ const transformStream = useCallback(async function* (content, options = {}) {
65
+ setIsLoading(true);
66
+ setError(null);
67
+ try {
68
+ const response = await fetch(`${endpoint}/fogui/transform/stream`, {
69
+ method: "POST",
70
+ headers: {
71
+ "Content-Type": "application/json",
72
+ "Authorization": `Bearer ${apiKey}`
73
+ },
74
+ body: JSON.stringify({
75
+ content,
76
+ context: options.intent || options.instructions ? {
77
+ intent: options.intent,
78
+ instructions: options.instructions
79
+ } : void 0,
80
+ streaming: true
81
+ })
82
+ });
83
+ if (!response.ok) {
84
+ throw new Error(`HTTP ${response.status}`);
85
+ }
86
+ const reader = response.body?.getReader();
87
+ if (!reader) {
88
+ throw new Error("No response body");
89
+ }
90
+ const decoder = new TextDecoder();
91
+ let buffer = "";
92
+ let currentEvent = "";
93
+ while (true) {
94
+ const { done, value } = await reader.read();
95
+ if (done) break;
96
+ buffer += decoder.decode(value, { stream: true });
97
+ const lines = buffer.split("\n");
98
+ buffer = lines.pop() || "";
99
+ for (const line of lines) {
100
+ if (line.startsWith("event:")) {
101
+ currentEvent = line.substring(6).trim();
102
+ } else if (line.startsWith("data:")) {
103
+ const data = line.substring(5).trim();
104
+ if (data === "[DONE]") {
105
+ yield { type: "done", data: null };
106
+ continue;
107
+ }
108
+ if (data) {
109
+ try {
110
+ const parsed = JSON.parse(data);
111
+ yield { type: currentEvent, data: parsed };
112
+ } catch {
113
+ if (currentEvent === "chunk") {
114
+ yield { type: "chunk", data };
115
+ }
116
+ }
117
+ }
118
+ }
119
+ }
120
+ }
121
+ } catch (err) {
122
+ const message = err instanceof Error ? err.message : "Unknown error";
123
+ setError(message);
124
+ yield { type: "error", data: { error: message } };
125
+ } finally {
126
+ setIsLoading(false);
127
+ }
128
+ }, [endpoint, apiKey]);
129
+ const clearError = useCallback(() => {
130
+ setError(null);
131
+ }, []);
132
+ return {
133
+ transform,
134
+ transformStream,
135
+ isLoading,
136
+ error,
137
+ clearError
138
+ };
139
+ }
140
+ function DefaultCard({ title, description, data }) {
141
+ return /* @__PURE__ */ jsxs("div", { style: { border: "1px solid #e5e7eb", borderRadius: "8px", padding: "16px", marginBottom: "12px" }, children: [
142
+ title && /* @__PURE__ */ jsx("h3", { style: { margin: "0 0 8px", fontSize: "18px", fontWeight: 600 }, children: title }),
143
+ description && /* @__PURE__ */ jsx("p", { style: { margin: "0 0 12px", color: "#6b7280" }, children: description }),
144
+ data && /* @__PURE__ */ jsx("div", { style: { fontSize: "14px" }, children: Object.entries(data).map(([key, value]) => /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", padding: "4px 0" }, children: [
145
+ /* @__PURE__ */ jsx("span", { style: { color: "#6b7280" }, children: key }),
146
+ /* @__PURE__ */ jsx("span", { style: { fontWeight: 500 }, children: String(value) })
147
+ ] }, key)) })
148
+ ] });
149
+ }
150
+ function DefaultList({ title, items }) {
151
+ return /* @__PURE__ */ jsxs("div", { style: { marginBottom: "12px" }, children: [
152
+ title && /* @__PURE__ */ jsx("h3", { style: { margin: "0 0 12px", fontSize: "18px", fontWeight: 600 }, children: title }),
153
+ /* @__PURE__ */ jsx("ul", { style: { margin: 0, paddingLeft: "20px" }, children: items.map((item, i) => /* @__PURE__ */ jsx("li", { style: { marginBottom: "8px" }, children: typeof item === "object" ? JSON.stringify(item) : String(item) }, i)) })
154
+ ] });
155
+ }
156
+ function DefaultTable({ columns, rows }) {
157
+ return /* @__PURE__ */ jsx("div", { style: { overflowX: "auto", marginBottom: "12px" }, children: /* @__PURE__ */ jsxs("table", { style: { width: "100%", borderCollapse: "collapse", fontSize: "14px" }, children: [
158
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: columns.map((col) => /* @__PURE__ */ jsx("th", { style: { textAlign: "left", padding: "12px 8px", borderBottom: "2px solid #e5e7eb", fontWeight: 600 }, children: col }, col)) }) }),
159
+ /* @__PURE__ */ jsx("tbody", { children: rows.map((row, i) => /* @__PURE__ */ jsx("tr", { children: columns.map((col) => /* @__PURE__ */ jsx("td", { style: { padding: "12px 8px", borderBottom: "1px solid #e5e7eb" }, children: String(row[col] ?? "") }, col)) }, i)) })
160
+ ] }) });
161
+ }
162
+ function DefaultCallout({ title, message, variant = "info" }) {
163
+ const colors = {
164
+ info: { bg: "#eff6ff", border: "#3b82f6", text: "#1e40af" },
165
+ warning: { bg: "#fffbeb", border: "#f59e0b", text: "#92400e" },
166
+ tip: { bg: "#f0fdf4", border: "#22c55e", text: "#166534" }
167
+ };
168
+ const c = colors[variant];
169
+ return /* @__PURE__ */ jsxs("div", { style: { backgroundColor: c.bg, borderLeft: `4px solid ${c.border}`, padding: "12px 16px", marginBottom: "12px", borderRadius: "0 8px 8px 0" }, children: [
170
+ title && /* @__PURE__ */ jsx("strong", { style: { color: c.text, display: "block", marginBottom: "4px" }, children: title }),
171
+ /* @__PURE__ */ jsx("span", { style: { color: c.text }, children: message })
172
+ ] });
173
+ }
174
+ var defaultComponentRegistry = {
175
+ card: DefaultCard,
176
+ list: DefaultList,
177
+ table: DefaultTable,
178
+ callout: DefaultCallout
179
+ };
180
+ function DynamicComponent({ block, registry = defaultComponentRegistry }) {
181
+ const { componentType, props } = block;
182
+ const Component = registry[componentType];
183
+ if (!Component) {
184
+ return /* @__PURE__ */ jsxs("div", { style: { padding: "12px", backgroundColor: "#fef3c7", border: "1px solid #fcd34d", borderRadius: "8px", fontSize: "14px" }, children: [
185
+ /* @__PURE__ */ jsxs("strong", { children: [
186
+ "Unknown component: ",
187
+ componentType
188
+ ] }),
189
+ /* @__PURE__ */ jsx("pre", { style: { margin: "8px 0 0", fontSize: "12px", overflow: "auto" }, children: JSON.stringify(props, null, 2) })
190
+ ] });
191
+ }
192
+ return /* @__PURE__ */ jsx(Component, { ...props });
193
+ }
194
+ function FogUIRenderer({ response, componentRegistry, className }) {
195
+ const registry = componentRegistry || defaultComponentRegistry;
196
+ if (!response || !response.content) {
197
+ return null;
198
+ }
199
+ return /* @__PURE__ */ jsx("div", { className, children: response.content.map((block, index) => /* @__PURE__ */ jsx(
200
+ ContentBlockRenderer,
201
+ {
202
+ block,
203
+ registry
204
+ },
205
+ index
206
+ )) });
207
+ }
208
+ function ContentBlockRenderer({ block, registry }) {
209
+ if (block.type === "text") {
210
+ return /* @__PURE__ */ jsx("div", { style: { marginBottom: "12px", lineHeight: 1.6 }, children: block.value.split("\n").map((line, i) => /* @__PURE__ */ jsxs(React2.Fragment, { children: [
211
+ line,
212
+ i < block.value.split("\n").length - 1 && /* @__PURE__ */ jsx("br", {})
213
+ ] }, i)) });
214
+ }
215
+ if (block.type === "component") {
216
+ return /* @__PURE__ */ jsx(DynamicComponent, { block, registry });
217
+ }
218
+ return null;
219
+ }
220
+
221
+ export { DynamicComponent, FogUIProvider, FogUIRenderer, defaultComponentRegistry, useFogUI, useFogUIContext };
222
+ //# sourceMappingURL=index.mjs.map
223
+ //# sourceMappingURL=index.mjs.map