@useatlas/react 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +79 -2
- package/dist/{chunk-5SEVKHS5.cjs → chunk-35SCTKSW.js} +100 -7
- package/dist/chunk-35SCTKSW.js.map +1 -0
- package/dist/{chunk-UIRB6L36.cjs → chunk-DZFSZSQB.cjs} +46 -54
- package/dist/chunk-DZFSZSQB.cjs.map +1 -0
- package/dist/{chunk-2WFDP7G5.js → chunk-FMSGREKS.js} +46 -54
- package/dist/chunk-FMSGREKS.js.map +1 -0
- package/dist/{chunk-44HBZYKP.js → chunk-IDXGFWFS.cjs} +109 -3
- package/dist/chunk-IDXGFWFS.cjs.map +1 -0
- package/dist/global.d.ts +36 -0
- package/dist/hooks.cjs +10 -10
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.cts +2 -2
- package/dist/hooks.d.ts +2 -2
- package/dist/hooks.js +3 -3
- package/dist/hooks.js.map +1 -1
- package/dist/index.cjs +385 -265
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +224 -4
- package/dist/index.d.ts +224 -4
- package/dist/index.js +328 -208
- package/dist/index.js.map +1 -1
- package/dist/lib/widget-types.d.ts +232 -0
- package/dist/{result-chart-YLCKBNV4.cjs → result-chart-ANZOT6FL.cjs} +24 -34
- package/dist/result-chart-ANZOT6FL.cjs.map +1 -0
- package/dist/{result-chart-NFAJ4IQ5.js → result-chart-C3EJTN5G.js} +22 -32
- package/dist/result-chart-C3EJTN5G.js.map +1 -0
- package/dist/widget.css +2 -2
- package/dist/widget.js +215 -246
- package/package.json +26 -16
- package/src/components/__tests__/data-table.test.tsx +125 -0
- package/src/components/actions/action-approval-card.tsx +26 -19
- package/src/components/actions/action-status-badge.tsx +3 -3
- package/src/components/atlas-chat.tsx +97 -37
- package/src/components/chart/result-chart.tsx +13 -37
- package/src/components/chat/api-key-bar.tsx +4 -4
- package/src/components/chat/data-table.tsx +42 -3
- package/src/components/chat/error-banner.tsx +108 -5
- package/src/components/chat/follow-up-chips.tsx +1 -1
- package/src/components/chat/managed-auth-card.tsx +6 -6
- package/src/components/conversations/conversation-item.tsx +19 -14
- package/src/components/conversations/conversation-list.tsx +3 -3
- package/src/components/conversations/conversation-sidebar.tsx +15 -4
- package/src/components/conversations/delete-confirmation.tsx +2 -2
- package/src/components/error-boundary.tsx +66 -0
- package/src/components/schema-explorer/schema-explorer.tsx +4 -0
- package/src/env.d.ts +9 -7
- package/src/global.d.ts +36 -0
- package/src/hooks/__tests__/use-atlas-conversations.test.tsx +4 -6
- package/src/hooks/use-atlas-chat.ts +1 -1
- package/src/hooks/use-atlas-conversations.ts +2 -2
- package/src/hooks/use-conversations.ts +60 -68
- package/src/index.ts +8 -0
- package/src/lib/action-types.ts +2 -2
- package/src/lib/helpers.ts +16 -16
- package/src/lib/types.ts +3 -2
- package/src/lib/widget-types.ts +232 -0
- package/src/test-setup.ts +2 -2
- package/dist/chunk-2WFDP7G5.js.map +0 -1
- package/dist/chunk-44HBZYKP.js.map +0 -1
- package/dist/chunk-5SEVKHS5.cjs.map +0 -1
- package/dist/chunk-UIRB6L36.cjs.map +0 -1
- package/dist/result-chart-NFAJ4IQ5.js.map +0 -1
- package/dist/result-chart-YLCKBNV4.cjs.map +0 -1
|
@@ -93,11 +93,11 @@ function useThemeMode() {
|
|
|
93
93
|
}
|
|
94
94
|
function transformMessages(messages) {
|
|
95
95
|
return messages.filter((m) => m.role === "user" || m.role === "assistant").map((m) => {
|
|
96
|
-
const
|
|
96
|
+
const parts = Array.isArray(m.content) ? m.content.filter((p) => p.type === "text").map((p) => ({ type: "text", text: p.text ?? "" })) : [{ type: "text", text: String(m.content) }];
|
|
97
97
|
return {
|
|
98
98
|
id: m.id,
|
|
99
99
|
role: m.role,
|
|
100
|
-
parts
|
|
100
|
+
parts
|
|
101
101
|
};
|
|
102
102
|
});
|
|
103
103
|
}
|
|
@@ -106,14 +106,16 @@ function useConversations(opts) {
|
|
|
106
106
|
const [total, setTotal] = useState(0);
|
|
107
107
|
const [loading, setLoading] = useState(false);
|
|
108
108
|
const [available, setAvailable] = useState(true);
|
|
109
|
+
const [fetchError, setFetchError] = useState(null);
|
|
109
110
|
const [selectedId, setSelectedId] = useState(null);
|
|
110
111
|
const fetchedRef = useRef(false);
|
|
111
|
-
const
|
|
112
|
+
const baseEndpoint = opts.conversationsEndpoint ?? "/api/v1/conversations";
|
|
112
113
|
const fetchList = useCallback(async () => {
|
|
113
114
|
if (!opts.enabled || !available) return;
|
|
114
115
|
setLoading(true);
|
|
116
|
+
setFetchError(null);
|
|
115
117
|
try {
|
|
116
|
-
const res = await fetch(`${opts.apiUrl}
|
|
118
|
+
const res = await fetch(`${opts.apiUrl}${baseEndpoint}?limit=50`, {
|
|
117
119
|
headers: opts.getHeaders(),
|
|
118
120
|
credentials: opts.getCredentials()
|
|
119
121
|
});
|
|
@@ -128,6 +130,7 @@ function useConversations(opts) {
|
|
|
128
130
|
return;
|
|
129
131
|
}
|
|
130
132
|
console.warn(`fetchList: HTTP ${res.status}`, errorBody);
|
|
133
|
+
setFetchError("Failed to load conversations. Please reload the page to try again.");
|
|
131
134
|
return;
|
|
132
135
|
}
|
|
133
136
|
const data = await res.json();
|
|
@@ -135,58 +138,45 @@ function useConversations(opts) {
|
|
|
135
138
|
setTotal(data.total ?? 0);
|
|
136
139
|
fetchedRef.current = true;
|
|
137
140
|
} catch (err) {
|
|
138
|
-
console.warn("fetchList error:", err);
|
|
139
|
-
|
|
140
|
-
networkFailRef.current += 1;
|
|
141
|
-
if (networkFailRef.current >= 3) setAvailable(false);
|
|
142
|
-
}
|
|
141
|
+
console.warn("fetchList error:", err instanceof Error ? err.message : String(err));
|
|
142
|
+
setFetchError("Failed to load conversations. Please reload the page to try again.");
|
|
143
143
|
} finally {
|
|
144
144
|
setLoading(false);
|
|
145
145
|
}
|
|
146
|
-
}, [opts.apiUrl, opts.enabled, opts.getHeaders, opts.getCredentials, available]);
|
|
146
|
+
}, [opts.apiUrl, opts.enabled, opts.getHeaders, opts.getCredentials, available, baseEndpoint]);
|
|
147
147
|
const loadConversation = useCallback(async (id) => {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
return null;
|
|
156
|
-
}
|
|
157
|
-
const data = await res.json();
|
|
158
|
-
return transformMessages(data.messages);
|
|
159
|
-
} catch (err) {
|
|
160
|
-
console.warn("loadConversation error:", err);
|
|
161
|
-
return null;
|
|
148
|
+
const res = await fetch(`${opts.apiUrl}${baseEndpoint}/${id}`, {
|
|
149
|
+
headers: opts.getHeaders(),
|
|
150
|
+
credentials: opts.getCredentials()
|
|
151
|
+
});
|
|
152
|
+
if (!res.ok) {
|
|
153
|
+
console.warn(`loadConversation: HTTP ${res.status} for ${id}`);
|
|
154
|
+
throw new Error(`Failed to load conversation (HTTP ${res.status})`);
|
|
162
155
|
}
|
|
163
|
-
|
|
156
|
+
const data = await res.json();
|
|
157
|
+
return transformMessages(data.messages);
|
|
158
|
+
}, [opts.apiUrl, opts.getHeaders, opts.getCredentials, baseEndpoint]);
|
|
164
159
|
const deleteConversation = useCallback(async (id) => {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
return false;
|
|
174
|
-
}
|
|
175
|
-
setConversations((prev) => prev.filter((c) => c.id !== id));
|
|
176
|
-
setTotal((prev) => Math.max(0, prev - 1));
|
|
177
|
-
if (selectedId === id) setSelectedId(null);
|
|
178
|
-
return true;
|
|
179
|
-
} catch (err) {
|
|
180
|
-
console.warn("deleteConversation error:", err);
|
|
181
|
-
return false;
|
|
160
|
+
const res = await fetch(`${opts.apiUrl}${baseEndpoint}/${id}`, {
|
|
161
|
+
method: "DELETE",
|
|
162
|
+
headers: opts.getHeaders(),
|
|
163
|
+
credentials: opts.getCredentials()
|
|
164
|
+
});
|
|
165
|
+
if (!res.ok) {
|
|
166
|
+
console.warn(`deleteConversation: HTTP ${res.status} for ${id}`);
|
|
167
|
+
throw new Error(`Failed to delete conversation (HTTP ${res.status})`);
|
|
182
168
|
}
|
|
183
|
-
|
|
169
|
+
setConversations((prev) => prev.filter((c) => c.id !== id));
|
|
170
|
+
setTotal((prev) => Math.max(0, prev - 1));
|
|
171
|
+
if (selectedId === id) setSelectedId(null);
|
|
172
|
+
}, [opts.apiUrl, opts.getHeaders, opts.getCredentials, selectedId, baseEndpoint]);
|
|
184
173
|
const starConversation = useCallback(async (id, starred) => {
|
|
185
174
|
setConversations(
|
|
186
175
|
(prev) => prev.map((c) => c.id === id ? { ...c, starred } : c)
|
|
187
176
|
);
|
|
177
|
+
let rolledBack = false;
|
|
188
178
|
try {
|
|
189
|
-
const res = await fetch(`${opts.apiUrl}
|
|
179
|
+
const res = await fetch(`${opts.apiUrl}${baseEndpoint}/${id}/star`, {
|
|
190
180
|
method: "PATCH",
|
|
191
181
|
headers: { ...opts.getHeaders(), "Content-Type": "application/json" },
|
|
192
182
|
credentials: opts.getCredentials(),
|
|
@@ -197,17 +187,18 @@ function useConversations(opts) {
|
|
|
197
187
|
setConversations(
|
|
198
188
|
(prev) => prev.map((c) => c.id === id ? { ...c, starred: !starred } : c)
|
|
199
189
|
);
|
|
200
|
-
|
|
190
|
+
rolledBack = true;
|
|
191
|
+
throw new Error(`Failed to update star (HTTP ${res.status})`);
|
|
201
192
|
}
|
|
202
|
-
return true;
|
|
203
193
|
} catch (err) {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
194
|
+
if (!rolledBack) {
|
|
195
|
+
setConversations(
|
|
196
|
+
(prev) => prev.map((c) => c.id === id ? { ...c, starred: !starred } : c)
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
throw err;
|
|
209
200
|
}
|
|
210
|
-
}, [opts.apiUrl, opts.getHeaders, opts.getCredentials]);
|
|
201
|
+
}, [opts.apiUrl, opts.getHeaders, opts.getCredentials, baseEndpoint]);
|
|
211
202
|
const refresh = useCallback(async () => {
|
|
212
203
|
await fetchList();
|
|
213
204
|
}, [fetchList]);
|
|
@@ -216,6 +207,7 @@ function useConversations(opts) {
|
|
|
216
207
|
total,
|
|
217
208
|
loading,
|
|
218
209
|
available,
|
|
210
|
+
fetchError,
|
|
219
211
|
selectedId,
|
|
220
212
|
setSelectedId,
|
|
221
213
|
fetchList,
|
|
@@ -227,5 +219,5 @@ function useConversations(opts) {
|
|
|
227
219
|
}
|
|
228
220
|
|
|
229
221
|
export { DarkModeContext, OKLCH_RE, THEME_STORAGE_KEY, applyBrandColor, buildThemeInitScript, setTheme, useConversations, useDarkMode, useThemeMode };
|
|
230
|
-
//# sourceMappingURL=chunk-
|
|
231
|
-
//# sourceMappingURL=chunk-
|
|
222
|
+
//# sourceMappingURL=chunk-FMSGREKS.js.map
|
|
223
|
+
//# sourceMappingURL=chunk-FMSGREKS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hooks/theme-init-script.ts","../src/hooks/use-dark-mode.ts","../src/hooks/use-conversations.ts"],"names":[],"mappings":"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","file":"chunk-FMSGREKS.js","sourcesContent":["/**\n * Blocking inline script for layout.tsx — prevents dark-mode flash on load.\n *\n * This file intentionally has NO \"use client\" directive so it can be imported\n * by server components (layout.tsx). The storage key must stay in sync with\n * use-dark-mode.ts.\n */\n\nexport const THEME_STORAGE_KEY = \"atlas-theme\";\n\n/**\n * Returns the inline script string for the blocking `<script>` in layout.tsx.\n * Reads atlas-theme from localStorage and sets the `dark` class before first paint.\n */\nexport function buildThemeInitScript(): string {\n return `try{var t=localStorage.getItem(\"${THEME_STORAGE_KEY}\");var d=t===\"dark\"||(t!==\"light\"&&window.matchMedia(\"(prefers-color-scheme:dark)\").matches);if(d)document.documentElement.classList.add(\"dark\")}catch(e){}`;\n}\n","\"use client\";\n\nimport { createContext, useSyncExternalStore } from \"react\";\n\n// ---------------------------------------------------------------------------\n// Theme types & constants\n// ---------------------------------------------------------------------------\n\nimport { THEME_STORAGE_KEY } from \"./theme-init-script\";\n\nexport type ThemeMode = \"light\" | \"dark\" | \"system\";\n\nexport { THEME_STORAGE_KEY };\n\n/**\n * Default brand color — must match `brand.css` `:root { --atlas-brand }` and\n * the `ATLAS_BRAND_COLOR` default in `packages/api/src/lib/settings.ts`.\n */\nexport const DEFAULT_BRAND_COLOR = \"oklch(0.759 0.148 167.71)\";\n\n/** Basic oklch format check — prevents obviously invalid values from breaking the theme. */\nexport const OKLCH_RE = /^oklch\\(\\s*[\\d.]+\\s+[\\d.]+\\s+[\\d.]+\\s*(?:\\/\\s*[\\d.%]+\\s*)?\\)$/;\n\n// ---------------------------------------------------------------------------\n// Shared state — single source of truth for the chosen mode.\n// Listeners are notified on change so useSyncExternalStore re-renders.\n// ---------------------------------------------------------------------------\n\nlet _mode: ThemeMode = \"system\";\nconst _listeners = new Set<() => void>();\n\nfunction notify() {\n for (const fn of _listeners) fn();\n}\n\n/** Read stored preference (called once on module load in the browser). */\nfunction init() {\n try {\n const stored = localStorage.getItem(THEME_STORAGE_KEY);\n if (stored === \"light\" || stored === \"dark\" || stored === \"system\") {\n _mode = stored;\n }\n } catch (err) {\n console.warn(\"Could not read theme preference from localStorage:\", err);\n }\n}\n\nif (typeof window !== \"undefined\") init();\n\n// ---------------------------------------------------------------------------\n// Derived boolean: is the effective theme dark?\n// ---------------------------------------------------------------------------\n\nfunction systemPrefersDark(): boolean {\n return typeof window !== \"undefined\" && window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n}\n\nfunction resolveIsDark(mode: ThemeMode): boolean {\n if (mode === \"dark\") return true;\n if (mode === \"light\") return false;\n return systemPrefersDark();\n}\n\nfunction applyClass(isDark: boolean) {\n if (typeof document === \"undefined\") return;\n document.documentElement.classList.toggle(\"dark\", isDark);\n}\n\n// ---------------------------------------------------------------------------\n// External store for isDark (reacts to both mode changes AND system changes)\n// ---------------------------------------------------------------------------\n\nfunction subscribeIsDark(onChange: () => void) {\n _listeners.add(onChange);\n\n // Also listen for system preference changes (relevant when mode === \"system\").\n // Apply dark class immediately on OS change so the DOM stays in sync before React re-renders.\n const mq = window.matchMedia(\"(prefers-color-scheme: dark)\");\n const handler = () => {\n applyClass(resolveIsDark(_mode));\n onChange();\n };\n mq.addEventListener(\"change\", handler);\n\n return () => {\n _listeners.delete(onChange);\n mq.removeEventListener(\"change\", handler);\n };\n}\n\nfunction getSnapshotIsDark() {\n return resolveIsDark(_mode);\n}\n\nfunction getServerSnapshotIsDark() {\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// External store for mode\n// ---------------------------------------------------------------------------\n\nfunction subscribeMode(onChange: () => void) {\n _listeners.add(onChange);\n return () => {\n _listeners.delete(onChange);\n };\n}\n\nfunction getSnapshotMode() {\n return _mode;\n}\n\nfunction getServerSnapshotMode(): ThemeMode {\n return \"system\";\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport function setTheme(mode: ThemeMode) {\n _mode = mode;\n const isDark = resolveIsDark(mode);\n applyClass(isDark);\n try {\n localStorage.setItem(THEME_STORAGE_KEY, mode);\n } catch (err) {\n console.warn(\"Could not persist theme preference to localStorage:\", err);\n }\n notify();\n}\n\n/** Apply --atlas-brand on :root so theme tokens update without reload. */\nexport function applyBrandColor(color: string) {\n if (typeof document === \"undefined\") return;\n document.documentElement.style.setProperty(\"--atlas-brand\", color);\n}\n\nexport const DarkModeContext = createContext(false);\n\n/** Returns whether the effective theme is dark. */\nexport function useDarkMode(): boolean {\n return useSyncExternalStore(subscribeIsDark, getSnapshotIsDark, getServerSnapshotIsDark);\n}\n\n/** Returns the current ThemeMode (\"light\" | \"dark\" | \"system\"). */\nexport function useThemeMode(): ThemeMode {\n return useSyncExternalStore(subscribeMode, getSnapshotMode, getServerSnapshotMode);\n}\n","\"use client\";\n\nimport { useState, useCallback, useRef } from \"react\";\nimport type { Conversation, ConversationWithMessages, Message } from \"../lib/types\";\nimport type { UIMessage } from \"@ai-sdk/react\";\n\nexport interface UseConversationsOptions {\n apiUrl: string;\n enabled: boolean;\n getHeaders: () => Record<string, string>;\n getCredentials: () => RequestCredentials;\n /** Custom conversations API endpoint path. Defaults to \"/api/v1/conversations\". */\n conversationsEndpoint?: string;\n}\n\nexport interface UseConversationsReturn {\n conversations: Conversation[];\n total: number;\n loading: boolean;\n available: boolean;\n fetchError: string | null;\n selectedId: string | null;\n setSelectedId: (id: string | null) => void;\n fetchList: () => Promise<void>;\n loadConversation: (id: string) => Promise<UIMessage[]>;\n deleteConversation: (id: string) => Promise<void>;\n starConversation: (id: string, starred: boolean) => Promise<void>;\n refresh: () => Promise<void>;\n}\n\nexport function transformMessages(messages: Message[]): UIMessage[] {\n return messages\n .filter((m) => m.role === \"user\" || m.role === \"assistant\")\n .map((m) => {\n const parts: UIMessage[\"parts\"] = Array.isArray(m.content)\n ? m.content\n .filter((p: { type?: string }) => p.type === \"text\")\n .map((p: { text?: string }) => ({ type: \"text\" as const, text: p.text ?? \"\" }))\n : [{ type: \"text\" as const, text: String(m.content) }];\n\n return {\n id: m.id,\n role: m.role as \"user\" | \"assistant\",\n parts,\n };\n });\n}\n\nexport function useConversations(opts: UseConversationsOptions): UseConversationsReturn {\n const [conversations, setConversations] = useState<Conversation[]>([]);\n const [total, setTotal] = useState(0);\n const [loading, setLoading] = useState(false);\n const [available, setAvailable] = useState(true);\n const [fetchError, setFetchError] = useState<string | null>(null);\n const [selectedId, setSelectedId] = useState<string | null>(null);\n const fetchedRef = useRef(false);\n const baseEndpoint = opts.conversationsEndpoint ?? \"/api/v1/conversations\";\n\n const fetchList = useCallback(async () => {\n if (!opts.enabled || !available) return;\n setLoading(true);\n setFetchError(null);\n try {\n const res = await fetch(`${opts.apiUrl}${baseEndpoint}?limit=50`, {\n headers: opts.getHeaders(),\n credentials: opts.getCredentials(),\n });\n\n if (res.status === 404) {\n setAvailable(false);\n return;\n }\n\n if (!res.ok) {\n // intentionally ignored: response may not be JSON\n const errorBody = await res.json().catch(() => null);\n if (errorBody?.code === \"not_available\") {\n setAvailable(false);\n return;\n }\n console.warn(`fetchList: HTTP ${res.status}`, errorBody);\n setFetchError(\"Failed to load conversations. Please reload the page to try again.\");\n return;\n }\n\n const data = await res.json();\n setConversations(data.conversations ?? []);\n setTotal(data.total ?? 0);\n fetchedRef.current = true;\n } catch (err: unknown) {\n console.warn(\"fetchList error:\", err instanceof Error ? err.message : String(err));\n setFetchError(\"Failed to load conversations. Please reload the page to try again.\");\n } finally {\n setLoading(false);\n }\n }, [opts.apiUrl, opts.enabled, opts.getHeaders, opts.getCredentials, available, baseEndpoint]);\n\n const loadConversation = useCallback(async (id: string): Promise<UIMessage[]> => {\n const res = await fetch(`${opts.apiUrl}${baseEndpoint}/${id}`, {\n headers: opts.getHeaders(),\n credentials: opts.getCredentials(),\n });\n\n if (!res.ok) {\n console.warn(`loadConversation: HTTP ${res.status} for ${id}`);\n throw new Error(`Failed to load conversation (HTTP ${res.status})`);\n }\n\n const data: ConversationWithMessages = await res.json();\n return transformMessages(data.messages);\n }, [opts.apiUrl, opts.getHeaders, opts.getCredentials, baseEndpoint]);\n\n const deleteConversation = useCallback(async (id: string): Promise<void> => {\n const res = await fetch(`${opts.apiUrl}${baseEndpoint}/${id}`, {\n method: \"DELETE\",\n headers: opts.getHeaders(),\n credentials: opts.getCredentials(),\n });\n\n if (!res.ok) {\n console.warn(`deleteConversation: HTTP ${res.status} for ${id}`);\n throw new Error(`Failed to delete conversation (HTTP ${res.status})`);\n }\n\n setConversations((prev) => prev.filter((c) => c.id !== id));\n setTotal((prev) => Math.max(0, prev - 1));\n\n if (selectedId === id) setSelectedId(null);\n }, [opts.apiUrl, opts.getHeaders, opts.getCredentials, selectedId, baseEndpoint]);\n\n const starConversation = useCallback(async (id: string, starred: boolean): Promise<void> => {\n // Optimistic update\n setConversations((prev) =>\n prev.map((c) => (c.id === id ? { ...c, starred } : c)),\n );\n let rolledBack = false;\n try {\n const res = await fetch(`${opts.apiUrl}${baseEndpoint}/${id}/star`, {\n method: \"PATCH\",\n headers: { ...opts.getHeaders(), \"Content-Type\": \"application/json\" },\n credentials: opts.getCredentials(),\n body: JSON.stringify({ starred }),\n });\n\n if (!res.ok) {\n console.warn(`starConversation: HTTP ${res.status} for ${id}`);\n setConversations((prev) =>\n prev.map((c) => (c.id === id ? { ...c, starred: !starred } : c)),\n );\n rolledBack = true;\n throw new Error(`Failed to update star (HTTP ${res.status})`);\n }\n } catch (err: unknown) {\n if (!rolledBack) {\n setConversations((prev) =>\n prev.map((c) => (c.id === id ? { ...c, starred: !starred } : c)),\n );\n }\n throw err;\n }\n }, [opts.apiUrl, opts.getHeaders, opts.getCredentials, baseEndpoint]);\n\n const refresh = useCallback(async () => {\n await fetchList();\n }, [fetchList]);\n\n return {\n conversations,\n total,\n loading,\n available,\n fetchError,\n selectedId,\n setSelectedId,\n fetchList,\n loadConversation,\n deleteConversation,\n starConversation,\n refresh,\n };\n}\n"]}
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
var classVarianceAuthority = require('class-variance-authority');
|
|
5
|
+
var radixUi = require('radix-ui');
|
|
6
|
+
var clsx = require('clsx');
|
|
7
|
+
var tailwindMerge = require('tailwind-merge');
|
|
8
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
9
|
+
|
|
1
10
|
// src/components/chart/chart-detection.ts
|
|
2
11
|
var CHART_COLORS_LIGHT = [
|
|
3
12
|
"#3b82f6",
|
|
@@ -218,7 +227,104 @@ function transformData(rows, recommendation) {
|
|
|
218
227
|
return record;
|
|
219
228
|
});
|
|
220
229
|
}
|
|
230
|
+
function cn(...inputs) {
|
|
231
|
+
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
232
|
+
}
|
|
233
|
+
var buttonVariants = classVarianceAuthority.cva(
|
|
234
|
+
"inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
235
|
+
{
|
|
236
|
+
variants: {
|
|
237
|
+
variant: {
|
|
238
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
239
|
+
destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",
|
|
240
|
+
outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
|
|
241
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
242
|
+
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
243
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
244
|
+
},
|
|
245
|
+
size: {
|
|
246
|
+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
247
|
+
xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
248
|
+
sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
|
|
249
|
+
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
250
|
+
icon: "size-9",
|
|
251
|
+
"icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
|
|
252
|
+
"icon-sm": "size-8",
|
|
253
|
+
"icon-lg": "size-10"
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
defaultVariants: {
|
|
257
|
+
variant: "default",
|
|
258
|
+
size: "default"
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
);
|
|
262
|
+
function Button({
|
|
263
|
+
className,
|
|
264
|
+
variant = "default",
|
|
265
|
+
size = "default",
|
|
266
|
+
asChild = false,
|
|
267
|
+
...props
|
|
268
|
+
}) {
|
|
269
|
+
const Comp = asChild ? radixUi.Slot.Root : "button";
|
|
270
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
271
|
+
Comp,
|
|
272
|
+
{
|
|
273
|
+
"data-slot": "button",
|
|
274
|
+
"data-variant": variant,
|
|
275
|
+
"data-size": size,
|
|
276
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
277
|
+
...props
|
|
278
|
+
}
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
var ErrorBoundary = class extends react.Component {
|
|
282
|
+
constructor(props) {
|
|
283
|
+
super(props);
|
|
284
|
+
this.state = { error: null };
|
|
285
|
+
}
|
|
286
|
+
static getDerivedStateFromError(error) {
|
|
287
|
+
return { error };
|
|
288
|
+
}
|
|
289
|
+
componentDidCatch(error, info) {
|
|
290
|
+
console.error("[ErrorBoundary]", error, info.componentStack);
|
|
291
|
+
this.props.onError?.(error, info);
|
|
292
|
+
}
|
|
293
|
+
resetErrorBoundary = () => {
|
|
294
|
+
this.setState({ error: null });
|
|
295
|
+
};
|
|
296
|
+
render() {
|
|
297
|
+
const { error } = this.state;
|
|
298
|
+
if (!error) return this.props.children;
|
|
299
|
+
if (this.props.fallbackRender) {
|
|
300
|
+
return this.props.fallbackRender(error, this.resetErrorBoundary);
|
|
301
|
+
}
|
|
302
|
+
if (this.props.fallback) {
|
|
303
|
+
return this.props.fallback;
|
|
304
|
+
}
|
|
305
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
306
|
+
"div",
|
|
307
|
+
{
|
|
308
|
+
role: "alert",
|
|
309
|
+
className: cn(
|
|
310
|
+
"flex flex-col items-center gap-3 rounded-lg border border-red-200 bg-red-50 p-4 text-center",
|
|
311
|
+
"dark:border-red-900/50 dark:bg-red-950/20"
|
|
312
|
+
),
|
|
313
|
+
children: [
|
|
314
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-red-700 dark:text-red-400", children: "Something went wrong." }),
|
|
315
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "outline", size: "sm", onClick: this.resetErrorBoundary, children: "Try again" })
|
|
316
|
+
]
|
|
317
|
+
}
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
};
|
|
221
321
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
322
|
+
exports.Button = Button;
|
|
323
|
+
exports.CHART_COLORS_DARK = CHART_COLORS_DARK;
|
|
324
|
+
exports.CHART_COLORS_LIGHT = CHART_COLORS_LIGHT;
|
|
325
|
+
exports.ErrorBoundary = ErrorBoundary;
|
|
326
|
+
exports.cn = cn;
|
|
327
|
+
exports.detectCharts = detectCharts;
|
|
328
|
+
exports.transformData = transformData;
|
|
329
|
+
//# sourceMappingURL=chunk-IDXGFWFS.cjs.map
|
|
330
|
+
//# sourceMappingURL=chunk-IDXGFWFS.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/chart/chart-detection.ts","../src/lib/utils.ts","../src/components/ui/button.tsx","../src/components/error-boundary.tsx"],"names":["twMerge","clsx","cva","Slot","jsx","Component","jsxs"],"mappings":"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","file":"chunk-IDXGFWFS.cjs","sourcesContent":["/* Chart detection — pure functions, zero React deps. Kept framework-agnostic for direct unit testing. */\n\nexport type ColumnType = \"numeric\" | \"date\" | \"categorical\" | \"unknown\";\n\nexport type ClassifiedColumn = {\n index: number;\n header: string;\n type: ColumnType;\n uniqueCount: number;\n};\n\nexport type ChartType = \"bar\" | \"line\" | \"pie\" | \"area\" | \"stacked-bar\" | \"scatter\";\n\nexport type ChartRecommendation = {\n type: ChartType;\n categoryColumn: ClassifiedColumn;\n valueColumns: [ClassifiedColumn, ...ClassifiedColumn[]];\n reason: string;\n};\n\nexport type RechartsRow = Record<string, string | number>;\n\ntype NonChartableResult = {\n chartable: false;\n columns: ClassifiedColumn[];\n};\n\ntype ChartableResult = {\n chartable: true;\n columns: ClassifiedColumn[];\n recommendations: [ChartRecommendation, ...ChartRecommendation[]];\n data: RechartsRow[];\n};\n\nexport type ChartDetectionResult = NonChartableResult | ChartableResult;\n\n/* ------------------------------------------------------------------ */\n/* Color palettes (Tailwind weights) */\n/* ------------------------------------------------------------------ */\n\nexport const CHART_COLORS_LIGHT = [\n \"#3b82f6\", // blue-500\n \"#10b981\", // emerald-500\n \"#f59e0b\", // amber-500\n \"#ef4444\", // red-500\n \"#8b5cf6\", // violet-500\n \"#06b6d4\", // cyan-500\n \"#f97316\", // orange-500\n \"#ec4899\", // pink-500\n];\n\nexport const CHART_COLORS_DARK = [\n \"#60a5fa\", // blue-400\n \"#34d399\", // emerald-400\n \"#fbbf24\", // amber-400\n \"#f87171\", // red-400\n \"#a78bfa\", // violet-400\n \"#22d3ee\", // cyan-400\n \"#fb923c\", // orange-400\n \"#f472b6\", // pink-400\n];\n\n/* ------------------------------------------------------------------ */\n/* Column classification */\n/* ------------------------------------------------------------------ */\n\nconst DATE_HEADER_HINTS = /^(date|month|year|quarter|week|day|period|time|timestamp)$/i;\nconst CATEGORICAL_HEADER_HINTS = /^(name|type|category|status|region|country|industry|department|plan|tier|segment|group|label|source|channel)$/i;\nconst SKIP_HEADER_HINTS = /^(id|uuid|_id|pk|key)$/i;\n\nconst ISO_DATE_RE = /^\\d{4}-\\d{2}/;\nconst MONTH_NAME_RE = /^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i;\nconst YEAR_ONLY_RE = /^(19|20)\\d{2}$/;\nconst QUARTER_RE = /^Q[1-4]\\s*\\d{4}$/i;\n\nexport function classifyColumn(header: string, values: string[]): ColumnType {\n const nonEmpty = values.filter((v) => v !== \"\" && v != null);\n if (nonEmpty.length === 0) return \"unknown\";\n\n // Header hint: skip ID-like columns\n if (SKIP_HEADER_HINTS.test(header)) return \"unknown\";\n\n // Numeric check: >80% parse as finite numbers (date check takes priority for overlapping values)\n const numericCount = nonEmpty.filter((v) => {\n const n = Number(v.replace(/,/g, \"\"));\n return isFinite(n);\n }).length;\n const numericRatio = numericCount / nonEmpty.length;\n\n // Date check: >70% match date patterns (>30% when header hints match)\n const dateCount = nonEmpty.filter(\n (v) => ISO_DATE_RE.test(v) || MONTH_NAME_RE.test(v) || YEAR_ONLY_RE.test(v) || QUARTER_RE.test(v),\n ).length;\n const dateRatio = dateCount / nonEmpty.length;\n\n // Header hint tiebreaker: if header matches date keywords...\n // (a) ...and at least some values look date-like, trust the header\n // (b) ...and values aren't overwhelmingly numeric (catches year-only values)\n if (DATE_HEADER_HINTS.test(header) && dateRatio > 0.3) return \"date\";\n if (DATE_HEADER_HINTS.test(header) && numericRatio < 0.9) return \"date\";\n\n if (dateRatio > 0.7) return \"date\";\n if (numericRatio > 0.8) return \"numeric\";\n\n // Categorical header hint\n if (CATEGORICAL_HEADER_HINTS.test(header)) return \"categorical\";\n\n // Categorical fallback: text values with <50 unique entries (higher cardinality suggests free-text or IDs)\n const unique = new Set(nonEmpty);\n if (unique.size < 50) return \"categorical\";\n\n return \"unknown\";\n}\n\n/* ------------------------------------------------------------------ */\n/* Chart recommendation engine */\n/* ------------------------------------------------------------------ */\n\nexport function detectCharts(headers: string[], rows: string[][]): ChartDetectionResult {\n if (headers.length === 0 || rows.length < 2) {\n return { chartable: false, columns: [] };\n }\n\n // Deduplicate headers so chart dataKey matches transformed data keys\n const seen = new Map<string, number>();\n const dedupedHeaders = headers.map((h) => {\n const count = seen.get(h) ?? 0;\n seen.set(h, count + 1);\n return count > 0 ? `${h}_${count + 1}` : h;\n });\n\n const columns: ClassifiedColumn[] = dedupedHeaders.map((header, index) => {\n const values = rows.map((r) => r[index] ?? \"\");\n const type = classifyColumn(header, values);\n const uniqueCount = new Set(values.filter((v) => v !== \"\")).size;\n return { index, header, type, uniqueCount };\n });\n\n const dateColumns = columns.filter((c) => c.type === \"date\");\n const numericColumns = columns.filter((c) => c.type === \"numeric\");\n const categoricalColumns = columns.filter((c) => c.type === \"categorical\");\n\n if (numericColumns.length === 0) {\n return { chartable: false, columns };\n }\n\n const recommendations: ChartRecommendation[] = [];\n\n // Line: date + numeric (time-series, highest priority)\n if (dateColumns.length >= 1 && numericColumns.length >= 1) {\n recommendations.push({\n type: \"line\",\n categoryColumn: dateColumns[0],\n valueColumns: numericColumns as [ClassifiedColumn, ...ClassifiedColumn[]],\n reason: `Time-series: ${dateColumns[0].header} vs ${numericColumns.map((c) => c.header).join(\", \")}`,\n });\n }\n\n // Area: alternative to line for date + numeric (volume/magnitude over time)\n if (dateColumns.length >= 1 && numericColumns.length >= 1) {\n recommendations.push({\n type: \"area\",\n categoryColumn: dateColumns[0],\n valueColumns: numericColumns as [ClassifiedColumn, ...ClassifiedColumn[]],\n reason: `Volume over time: ${numericColumns.map((c) => c.header).join(\", \")} by ${dateColumns[0].header}`,\n });\n }\n\n // Stacked bar: categorical + multiple numeric columns (part-to-whole comparison)\n if (categoricalColumns.length >= 1 && numericColumns.length >= 2) {\n recommendations.push({\n type: \"stacked-bar\",\n categoryColumn: categoricalColumns[0],\n valueColumns: numericColumns as [ClassifiedColumn, ...ClassifiedColumn[]],\n reason: `Stacked: ${numericColumns.map((c) => c.header).join(\", \")} by ${categoricalColumns[0].header}`,\n });\n }\n\n // Bar: categorical + numeric\n if (categoricalColumns.length >= 1 && numericColumns.length >= 1) {\n recommendations.push({\n type: \"bar\",\n categoryColumn: categoricalColumns[0],\n valueColumns: numericColumns as [ClassifiedColumn, ...ClassifiedColumn[]],\n reason: `Comparison: ${numericColumns.map((c) => c.header).join(\", \")} by ${categoricalColumns[0].header}`,\n });\n }\n\n // Pie: first categorical column (2-7 unique values) + first numeric column\n if (categoricalColumns.length >= 1 && numericColumns.length >= 1) {\n const cat = categoricalColumns[0];\n if (cat.uniqueCount >= 2 && cat.uniqueCount <= 7) {\n recommendations.push({\n type: \"pie\",\n categoryColumn: cat,\n valueColumns: [numericColumns[0]],\n reason: `Distribution: ${numericColumns[0].header} by ${cat.header}`,\n });\n }\n }\n\n // Scatter: 2+ numeric columns (correlation analysis)\n if (numericColumns.length >= 2) {\n const [xCol, yCol, ...rest] = numericColumns;\n const scatterValues = rest.length > 0\n ? [yCol, ...rest] as [ClassifiedColumn, ...ClassifiedColumn[]]\n : [yCol] as [ClassifiedColumn, ...ClassifiedColumn[]];\n recommendations.push({\n type: \"scatter\",\n categoryColumn: xCol,\n valueColumns: scatterValues,\n reason: `Correlation: ${xCol.header} vs ${yCol.header}${rest.length > 0 ? ` (size: ${rest[0].header})` : \"\"}`,\n });\n }\n\n // Fallback: when all columns are numeric, treat first as category axis (often an index or bucket label)\n if (!recommendations.some((r) => r.type === \"bar\") && numericColumns.length >= 2) {\n const first = columns[0];\n const rest = numericColumns.filter((c) => c.index !== first.index);\n if (rest.length >= 1) {\n recommendations.push({\n type: \"bar\",\n categoryColumn: first,\n valueColumns: rest as [ClassifiedColumn, ...ClassifiedColumn[]],\n reason: `Fallback: ${rest.map((c) => c.header).join(\", \")} by ${first.header}`,\n });\n }\n }\n\n // Also allow bar for date columns (as a secondary option after line)\n if (dateColumns.length >= 1 && numericColumns.length >= 1 && !recommendations.some((r) => r.type === \"bar\")) {\n recommendations.push({\n type: \"bar\",\n categoryColumn: dateColumns[0],\n valueColumns: numericColumns as [ClassifiedColumn, ...ClassifiedColumn[]],\n reason: `Comparison: ${numericColumns.map((c) => c.header).join(\", \")} by ${dateColumns[0].header}`,\n });\n }\n\n if (recommendations.length === 0) {\n return { chartable: false, columns };\n }\n\n const data = transformData(rows, recommendations[0]);\n\n return {\n chartable: true,\n columns,\n recommendations: recommendations as [ChartRecommendation, ...ChartRecommendation[]],\n data,\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Data transform */\n/* ------------------------------------------------------------------ */\n\nfunction parseNumericValue(raw: string): number {\n const cleaned = raw.replace(/[$%,\\s]/g, \"\");\n if (cleaned === \"\" || cleaned === \"-\") return 0;\n const num = Number(cleaned);\n return isFinite(num) ? num : 0;\n}\n\nfunction isFiniteNumeric(raw: string): boolean {\n const cleaned = raw.replace(/[$%,\\s]/g, \"\");\n if (cleaned === \"\" || cleaned === \"-\") return false;\n return isFinite(Number(cleaned));\n}\n\nexport function transformData(\n rows: string[][],\n recommendation: ChartRecommendation,\n): RechartsRow[] {\n const catIdx = recommendation.categoryColumn.index;\n const catHeader = recommendation.categoryColumn.header;\n const valIdxs = recommendation.valueColumns.map((c) => c.index);\n\n // Scatter: both axes are numeric — categoryColumn is x, first valueColumn is y, optional z for size\n // Filter out rows where x or y are non-numeric to avoid misleading zero-origin clusters\n if (recommendation.type === \"scatter\") {\n const yIdx = recommendation.valueColumns[0].index;\n return rows.flatMap((row) => {\n const rawX = row[catIdx] ?? \"\";\n const rawY = row[yIdx] ?? \"\";\n if (!isFiniteNumeric(rawX) || !isFiniteNumeric(rawY)) return [];\n const record: RechartsRow = {};\n record[catHeader] = parseNumericValue(rawX);\n for (const vc of recommendation.valueColumns) {\n record[vc.header] = parseNumericValue(row[vc.index] ?? \"0\");\n }\n return [record];\n });\n }\n\n // Cap rows for bar/stacked-bar charts with many categories\n let effectiveRows = rows;\n if ((recommendation.type === \"bar\" || recommendation.type === \"stacked-bar\") && rows.length > 30) {\n // Sort by first value column descending, take top 20\n const valIdx = valIdxs[0];\n effectiveRows = [...rows]\n .sort((a, b) => {\n const av = parseNumericValue(a[valIdx] ?? \"0\");\n const bv = parseNumericValue(b[valIdx] ?? \"0\");\n return bv - av;\n })\n .slice(0, 20);\n }\n\n return effectiveRows.map((row) => {\n const record: RechartsRow = {};\n record[catHeader] = row[catIdx] ?? \"\";\n for (const vc of recommendation.valueColumns) {\n record[vc.header] = parseNumericValue(row[vc.index] ?? \"0\");\n }\n return record;\n });\n}\n","import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"../../lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40\",\n outline:\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n xs: \"h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n icon: \"size-9\",\n \"icon-xs\": \"size-6 rounded-md [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot.Root : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n","\"use client\";\n\nimport { Component, type ReactNode, type ErrorInfo } from \"react\";\nimport { Button } from \"./ui/button\";\nimport { cn } from \"../lib/utils\";\n\ninterface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: ReactNode;\n fallbackRender?: (error: Error, reset: () => void) => ReactNode;\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n}\n\ninterface ErrorBoundaryState {\n error: Error | null;\n}\n\nexport class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { error: null };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { error };\n }\n\n componentDidCatch(error: Error, info: ErrorInfo) {\n console.error(\"[ErrorBoundary]\", error, info.componentStack);\n this.props.onError?.(error, info);\n }\n\n resetErrorBoundary = () => {\n this.setState({ error: null });\n };\n\n render() {\n const { error } = this.state;\n if (!error) return this.props.children;\n\n if (this.props.fallbackRender) {\n return this.props.fallbackRender(error, this.resetErrorBoundary);\n }\n\n if (this.props.fallback) {\n return this.props.fallback;\n }\n\n return (\n <div\n role=\"alert\"\n className={cn(\n \"flex flex-col items-center gap-3 rounded-lg border border-red-200 bg-red-50 p-4 text-center\",\n \"dark:border-red-900/50 dark:bg-red-950/20\",\n )}\n >\n <p className=\"text-sm text-red-700 dark:text-red-400\">\n Something went wrong.\n </p>\n <Button variant=\"outline\" size=\"sm\" onClick={this.resetErrorBoundary}>\n Try again\n </Button>\n </div>\n );\n }\n}\n"]}
|
package/dist/global.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ambient type declarations for the Atlas widget script-tag API.
|
|
3
|
+
*
|
|
4
|
+
* These augment `window.Atlas` and the `Atlas` global so that embedders
|
|
5
|
+
* get full IDE autocomplete and type-checking.
|
|
6
|
+
*
|
|
7
|
+
* **Usage:** Add a triple-slash reference at the top of your script:
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* /// <reference types="@useatlas/react/widget" />
|
|
11
|
+
*
|
|
12
|
+
* window.Atlas?.open();
|
|
13
|
+
* Atlas?.ask("How many users signed up today?");
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import type { AtlasWidget, AtlasWidgetCommand } from "./lib/widget-types";
|
|
18
|
+
|
|
19
|
+
declare global {
|
|
20
|
+
interface Window {
|
|
21
|
+
/**
|
|
22
|
+
* Atlas widget API — available after the widget `<script>` tag loads.
|
|
23
|
+
*
|
|
24
|
+
* Before the script loads, this may be an array of queued commands
|
|
25
|
+
* (`AtlasWidgetCommand[]`) that are replayed once the widget initializes.
|
|
26
|
+
*/
|
|
27
|
+
Atlas?: AtlasWidget | AtlasWidgetCommand[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Atlas widget API — shorthand for `window.Atlas`.
|
|
32
|
+
*
|
|
33
|
+
* May be `undefined` if the widget script has not loaded yet.
|
|
34
|
+
*/
|
|
35
|
+
var Atlas: AtlasWidget | AtlasWidgetCommand[] | undefined;
|
|
36
|
+
}
|
package/dist/hooks.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkDZFSZSQB_cjs = require('./chunk-DZFSZSQB.cjs');
|
|
4
4
|
var react = require('react');
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
var react$1 = require('@ai-sdk/react');
|
|
@@ -52,7 +52,7 @@ function useAtlasChat(options = {}) {
|
|
|
52
52
|
const headers = {};
|
|
53
53
|
if (apiKey) headers["Authorization"] = `Bearer ${apiKey}`;
|
|
54
54
|
return new ai.DefaultChatTransport({
|
|
55
|
-
api: `${apiUrl}/api/chat`,
|
|
55
|
+
api: `${apiUrl}/api/v1/chat`,
|
|
56
56
|
headers,
|
|
57
57
|
credentials: isCrossOrigin ? "include" : void 0,
|
|
58
58
|
body: () => conversationIdRef.current ? { conversationId: conversationIdRef.current } : {},
|
|
@@ -119,7 +119,7 @@ function useAtlasAuth() {
|
|
|
119
119
|
const data = await res.json();
|
|
120
120
|
const mode = data?.checks?.auth?.mode;
|
|
121
121
|
if (!cancelled) {
|
|
122
|
-
if (typeof mode === "string" &&
|
|
122
|
+
if (typeof mode === "string" && chunkDZFSZSQB_cjs.AUTH_MODES.includes(mode)) {
|
|
123
123
|
setAuthMode(mode);
|
|
124
124
|
} else {
|
|
125
125
|
console.warn("[Atlas] Health check returned no valid auth mode:", data);
|
|
@@ -195,13 +195,13 @@ function useAtlasAuth() {
|
|
|
195
195
|
|
|
196
196
|
// src/hooks/use-atlas-theme.ts
|
|
197
197
|
function useAtlasTheme() {
|
|
198
|
-
const theme =
|
|
199
|
-
const isDark =
|
|
198
|
+
const theme = chunkDZFSZSQB_cjs.useThemeMode();
|
|
199
|
+
const isDark = chunkDZFSZSQB_cjs.useDarkMode();
|
|
200
200
|
return {
|
|
201
201
|
theme,
|
|
202
202
|
isDark,
|
|
203
|
-
setTheme:
|
|
204
|
-
applyBrandColor:
|
|
203
|
+
setTheme: chunkDZFSZSQB_cjs.setTheme,
|
|
204
|
+
applyBrandColor: chunkDZFSZSQB_cjs.applyBrandColor
|
|
205
205
|
};
|
|
206
206
|
}
|
|
207
207
|
|
|
@@ -209,7 +209,7 @@ function useAtlasTheme() {
|
|
|
209
209
|
function useAtlasConversations(options = {}) {
|
|
210
210
|
const { apiUrl, apiKey, isCrossOrigin } = useAtlasContext();
|
|
211
211
|
const { enabled = true } = options;
|
|
212
|
-
const inner =
|
|
212
|
+
const inner = chunkDZFSZSQB_cjs.useConversations({
|
|
213
213
|
apiUrl,
|
|
214
214
|
enabled,
|
|
215
215
|
getHeaders: () => {
|
|
@@ -235,11 +235,11 @@ function useAtlasConversations(options = {}) {
|
|
|
235
235
|
|
|
236
236
|
Object.defineProperty(exports, "AUTH_MODES", {
|
|
237
237
|
enumerable: true,
|
|
238
|
-
get: function () { return
|
|
238
|
+
get: function () { return chunkDZFSZSQB_cjs.AUTH_MODES; }
|
|
239
239
|
});
|
|
240
240
|
Object.defineProperty(exports, "parseChatError", {
|
|
241
241
|
enumerable: true,
|
|
242
|
-
get: function () { return
|
|
242
|
+
get: function () { return chunkDZFSZSQB_cjs.parseChatError; }
|
|
243
243
|
});
|
|
244
244
|
exports.AtlasProvider = AtlasProvider;
|
|
245
245
|
exports.useAtlasAuth = useAtlasAuth;
|
package/dist/hooks.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/hooks/provider.tsx","../src/hooks/use-atlas-chat.ts","../src/hooks/use-atlas-auth.ts","../src/hooks/use-atlas-theme.ts","../src/hooks/use-atlas-conversations.ts"],"names":["createContext","useContext","jsx","useState","useRef","useMemo","DefaultChatTransport","input","useChat","useEffect","AUTH_MODES","useThemeMode","useDarkMode","setTheme","applyBrandColor","useConversations"],"mappings":"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","file":"hooks.cjs","sourcesContent":["\"use client\";\n\nimport { createContext, useContext, type ReactNode } from \"react\";\nimport type { AtlasAuthClient } from \"../context\";\n\nexport type { AtlasAuthClient };\n\nexport interface AtlasProviderProps {\n /** Atlas API server URL (e.g. \"https://api.example.com\" or \"\" for same-origin). */\n apiUrl: string;\n /** API key for simple-key auth mode. Sent as Bearer token. Accessible in context by all hooks. */\n apiKey?: string;\n /** Custom auth client for managed auth mode (better-auth compatible). */\n authClient?: AtlasAuthClient;\n children: ReactNode;\n}\n\nexport interface AtlasContextValue {\n apiUrl: string;\n apiKey: string | undefined;\n authClient: AtlasAuthClient;\n isCrossOrigin: boolean;\n}\n\n/** No-op auth client for non-managed auth modes. Warns when auth operations are attempted. */\nconst noopAuthClient: AtlasAuthClient = {\n signIn: {\n email: async () => {\n console.warn(\"[Atlas] signIn called but no authClient was provided to AtlasProvider\");\n return { error: { message: \"Auth client not configured\" } };\n },\n },\n signUp: {\n email: async () => {\n console.warn(\"[Atlas] signUp called but no authClient was provided to AtlasProvider\");\n return { error: { message: \"Auth client not configured\" } };\n },\n },\n signOut: async () => {\n console.warn(\"[Atlas] signOut called but no authClient was provided to AtlasProvider\");\n },\n useSession: () => ({ data: null, isPending: false }),\n};\n\nconst AtlasContext = createContext<AtlasContextValue | null>(null);\n\n/** Access the AtlasProvider context. Throws if used outside <AtlasProvider>. */\nexport function useAtlasContext(): AtlasContextValue {\n const ctx = useContext(AtlasContext);\n if (!ctx) throw new Error(\"useAtlasContext must be used within <AtlasProvider>\");\n return ctx;\n}\n\n/**\n * Lightweight provider for headless Atlas hooks.\n *\n * Wraps your app and supplies API URL, auth credentials, and an optional\n * better-auth client to all Atlas hooks. Derives isCrossOrigin from apiUrl\n * to configure credential handling for cross-origin requests.\n */\nexport function AtlasProvider({\n apiUrl,\n apiKey,\n authClient = noopAuthClient,\n children,\n}: AtlasProviderProps) {\n const isCrossOrigin =\n typeof window !== \"undefined\" &&\n apiUrl !== \"\" &&\n !apiUrl.startsWith(window.location.origin);\n\n return (\n <AtlasContext.Provider value={{ apiUrl, apiKey, authClient, isCrossOrigin }}>\n {children}\n </AtlasContext.Provider>\n );\n}\n","\"use client\";\n\nimport { useState, useRef, useMemo } from \"react\";\nimport { useChat, type UIMessage } from \"@ai-sdk/react\";\nimport { DefaultChatTransport } from \"ai\";\nimport { useAtlasContext } from \"./provider\";\n\nexport type AtlasChatStatus = \"submitted\" | \"streaming\" | \"ready\" | \"error\";\n\nexport interface UseAtlasChatOptions {\n /** Conversation ID to associate with this chat session. The server will append messages to this conversation. To load prior messages, use loadConversation() from useAtlasConversations and pass them via setMessages. */\n initialConversationId?: string;\n /** Called when the server assigns or changes the conversation ID. */\n onConversationIdChange?: (id: string) => void;\n}\n\nexport interface UseAtlasChatReturn {\n messages: UIMessage[];\n /** Replace all messages, or update via callback `(prev) => next`. */\n setMessages: (messages: UIMessage[] | ((prev: UIMessage[]) => UIMessage[])) => void;\n /** Send a text message. Rejects on failure (also surfaces via `error`). */\n sendMessage: (text: string) => Promise<void>;\n /** Current input value (managed by the hook). */\n input: string;\n /** Update the input value. */\n setInput: (input: string) => void;\n /** Chat status from the AI SDK. */\n status: AtlasChatStatus;\n /** Whether the chat is currently loading (streaming or submitted). */\n isLoading: boolean;\n /** Last error, if any. */\n error: Error | null;\n /** Current conversation ID. Initially set from options, updated when the server returns an x-conversation-id header. */\n conversationId: string | null;\n /** Manually set the conversation ID. */\n setConversationId: (id: string | null) => void;\n}\n\nexport function useAtlasChat(options: UseAtlasChatOptions = {}): UseAtlasChatReturn {\n const { apiUrl, apiKey, isCrossOrigin } = useAtlasContext();\n const [conversationId, setConversationId] = useState<string | null>(\n options.initialConversationId ?? null,\n );\n const conversationIdRef = useRef(conversationId);\n conversationIdRef.current = conversationId;\n\n const onChangeRef = useRef(options.onConversationIdChange);\n onChangeRef.current = options.onConversationIdChange;\n\n const transport = useMemo(() => {\n const headers: Record<string, string> = {};\n if (apiKey) headers[\"Authorization\"] = `Bearer ${apiKey}`;\n\n return new DefaultChatTransport({\n api: `${apiUrl}/api/chat`,\n headers,\n credentials: isCrossOrigin ? \"include\" : undefined,\n body: () =>\n conversationIdRef.current\n ? { conversationId: conversationIdRef.current }\n : {},\n fetch: (async (input: RequestInfo | URL, init?: RequestInit) => {\n const response = await globalThis.fetch(input, init);\n const convId = response.headers.get(\"x-conversation-id\");\n if (convId && convId !== conversationIdRef.current) {\n setConversationId(convId);\n onChangeRef.current?.(convId);\n }\n return response;\n }) as typeof fetch,\n });\n }, [apiKey, apiUrl, isCrossOrigin]);\n\n const { messages, setMessages, sendMessage: rawSend, status, error } =\n useChat({ transport });\n\n const [input, setInput] = useState(\"\");\n\n const sendMessage = async (text: string) => {\n const previousInput = input;\n setInput(\"\");\n try {\n await rawSend({ text });\n } catch (err) {\n setInput(previousInput);\n throw err;\n }\n };\n\n return {\n messages,\n setMessages,\n sendMessage,\n input,\n setInput,\n status: status as AtlasChatStatus,\n isLoading: status === \"streaming\" || status === \"submitted\",\n error: error ?? null,\n conversationId,\n setConversationId,\n };\n}\n","\"use client\";\n\nimport { useState, useEffect } from \"react\";\nimport { useAtlasContext } from \"./provider\";\nimport { AUTH_MODES, type AuthMode } from \"../lib/types\";\n\nexport interface UseAtlasAuthReturn {\n /** Auth mode detected from the server's /api/health endpoint. `null` while the initial health check is in flight. */\n authMode: AuthMode | null;\n /** Whether the user is authenticated (based on auth mode, API key, or session). */\n isAuthenticated: boolean;\n /** Session data for managed auth mode. */\n session: { user?: { email?: string } } | null;\n /** Whether auth state is still being resolved (health check or managed session loading). */\n isLoading: boolean;\n /** Error from health check or auth operations. `null` when healthy. */\n error: Error | null;\n /** Sign in with email/password (managed auth). */\n login: (email: string, password: string) => Promise<{ error?: string }>;\n /** Sign up with email/password/name (managed auth). */\n signup: (email: string, password: string, name: string) => Promise<{ error?: string }>;\n /** Sign out (managed auth). */\n logout: () => Promise<{ error?: string }>;\n}\n\nexport function useAtlasAuth(): UseAtlasAuthReturn {\n const { apiUrl, apiKey, authClient, isCrossOrigin } = useAtlasContext();\n const [authMode, setAuthMode] = useState<AuthMode | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const managedSession = authClient.useSession();\n\n useEffect(() => {\n let cancelled = false;\n\n async function fetchHealth(attempt: number): Promise<void> {\n try {\n const res = await fetch(`${apiUrl}/api/health`, {\n credentials: isCrossOrigin ? \"include\" : \"same-origin\",\n });\n if (!res.ok) {\n console.warn(`[Atlas] Health check returned HTTP ${res.status} (attempt ${attempt})`);\n if (attempt < 2 && !cancelled) {\n await new Promise((r) => setTimeout(r, 2000));\n return fetchHealth(attempt + 1);\n }\n if (!cancelled) {\n setError(new Error(`Health check failed with HTTP ${res.status}`));\n setAuthMode(\"none\");\n }\n return;\n }\n const data = await res.json();\n const mode = data?.checks?.auth?.mode;\n if (!cancelled) {\n if (typeof mode === \"string\" && AUTH_MODES.includes(mode as AuthMode)) {\n setAuthMode(mode as AuthMode);\n } else {\n console.warn(\"[Atlas] Health check returned no valid auth mode:\", data);\n setAuthMode(\"none\");\n }\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.warn(`[Atlas] Health check failed (attempt ${attempt}):`, message);\n if (attempt < 2 && !cancelled) {\n await new Promise((r) => setTimeout(r, 2000));\n return fetchHealth(attempt + 1);\n }\n if (!cancelled) {\n setError(err instanceof Error ? err : new Error(message));\n setAuthMode(\"none\");\n }\n }\n }\n\n fetchHealth(1);\n return () => { cancelled = true; };\n }, [apiUrl, isCrossOrigin]);\n\n const isAuthenticated = (() => {\n if (authMode === null) return false;\n if (authMode === \"none\") return true;\n if (authMode === \"simple-key\" || authMode === \"byot\") return !!apiKey;\n if (authMode === \"managed\") return !!managedSession.data?.user;\n return false;\n })();\n\n const login = async (email: string, password: string) => {\n try {\n const result = await authClient.signIn.email({ email, password });\n return { error: result.error?.message };\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Login failed\";\n console.warn(\"[Atlas] login error:\", message);\n return { error: message };\n }\n };\n\n const signup = async (email: string, password: string, name: string) => {\n try {\n const result = await authClient.signUp.email({ email, password, name });\n return { error: result.error?.message };\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Signup failed\";\n console.warn(\"[Atlas] signup error:\", message);\n return { error: message };\n }\n };\n\n const logout = async () => {\n try {\n await authClient.signOut();\n return {};\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Logout failed\";\n console.warn(\"[Atlas] logout error:\", message);\n return { error: message };\n }\n };\n\n return {\n authMode,\n isAuthenticated,\n session: managedSession.data ?? null,\n isLoading: authMode === null || (authMode === \"managed\" && !!managedSession.isPending),\n error,\n login,\n signup,\n logout,\n };\n}\n","\"use client\";\n\nimport {\n useDarkMode,\n useThemeMode,\n setTheme,\n applyBrandColor,\n type ThemeMode,\n} from \"./use-dark-mode\";\n\nexport type { ThemeMode };\n\nexport interface UseAtlasThemeReturn {\n /** Current theme setting: \"light\", \"dark\", or \"system\". */\n theme: ThemeMode;\n /** Whether the effective (resolved) theme is dark. */\n isDark: boolean;\n /** Set the theme mode. Persists to localStorage. */\n setTheme: (mode: ThemeMode) => void;\n /** Apply a brand color (oklch format, e.g. \"oklch(0.759 0.148 167.71)\") via CSS custom property --atlas-brand. */\n applyBrandColor: (color: string) => void;\n}\n\nexport function useAtlasTheme(): UseAtlasThemeReturn {\n const theme = useThemeMode();\n const isDark = useDarkMode();\n\n return {\n theme,\n isDark,\n setTheme,\n applyBrandColor,\n };\n}\n","\"use client\";\n\nimport type { UIMessage } from \"@ai-sdk/react\";\nimport { useAtlasContext } from \"./provider\";\nimport { useConversations } from \"./use-conversations\";\nimport type { Conversation } from \"../lib/types\";\n\nexport interface UseAtlasConversationsOptions {\n /** When false, refresh() becomes a no-op. Defaults to true. */\n enabled?: boolean;\n}\n\nexport interface UseAtlasConversationsReturn {\n conversations: Conversation[];\n total: number;\n isLoading: boolean;\n available: boolean;\n selectedId: string | null;\n setSelectedId: (id: string | null) => void;\n refresh: () => Promise<void>;\n loadConversation: (id: string) => Promise<UIMessage[] | null>;\n deleteConversation: (id: string) => Promise<boolean>;\n starConversation: (id: string, starred: boolean) => Promise<boolean>;\n}\n\n/**\n * Manage conversation history with auth automatically wired from AtlasProvider.\n *\n * Wraps the lower-level `useConversations` hook with context-derived\n * API URL and credentials.\n */\nexport function useAtlasConversations(\n options: UseAtlasConversationsOptions = {},\n): UseAtlasConversationsReturn {\n const { apiUrl, apiKey, isCrossOrigin } = useAtlasContext();\n const { enabled = true } = options;\n\n const inner = useConversations({\n apiUrl,\n enabled,\n getHeaders: () => {\n const headers: Record<string, string> = {};\n if (apiKey) headers[\"Authorization\"] = `Bearer ${apiKey}`;\n return headers;\n },\n getCredentials: () => (isCrossOrigin ? \"include\" : \"same-origin\"),\n });\n\n return {\n conversations: inner.conversations,\n total: inner.total,\n isLoading: inner.loading,\n available: inner.available,\n selectedId: inner.selectedId,\n setSelectedId: inner.setSelectedId,\n refresh: inner.refresh,\n loadConversation: inner.loadConversation,\n deleteConversation: inner.deleteConversation,\n starConversation: inner.starConversation,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/hooks/provider.tsx","../src/hooks/use-atlas-chat.ts","../src/hooks/use-atlas-auth.ts","../src/hooks/use-atlas-theme.ts","../src/hooks/use-atlas-conversations.ts"],"names":["createContext","useContext","jsx","useState","useRef","useMemo","DefaultChatTransport","input","useChat","useEffect","AUTH_MODES","useThemeMode","useDarkMode","setTheme","applyBrandColor","useConversations"],"mappings":"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","file":"hooks.cjs","sourcesContent":["\"use client\";\n\nimport { createContext, useContext, type ReactNode } from \"react\";\nimport type { AtlasAuthClient } from \"../context\";\n\nexport type { AtlasAuthClient };\n\nexport interface AtlasProviderProps {\n /** Atlas API server URL (e.g. \"https://api.example.com\" or \"\" for same-origin). */\n apiUrl: string;\n /** API key for simple-key auth mode. Sent as Bearer token. Accessible in context by all hooks. */\n apiKey?: string;\n /** Custom auth client for managed auth mode (better-auth compatible). */\n authClient?: AtlasAuthClient;\n children: ReactNode;\n}\n\nexport interface AtlasContextValue {\n apiUrl: string;\n apiKey: string | undefined;\n authClient: AtlasAuthClient;\n isCrossOrigin: boolean;\n}\n\n/** No-op auth client for non-managed auth modes. Warns when auth operations are attempted. */\nconst noopAuthClient: AtlasAuthClient = {\n signIn: {\n email: async () => {\n console.warn(\"[Atlas] signIn called but no authClient was provided to AtlasProvider\");\n return { error: { message: \"Auth client not configured\" } };\n },\n },\n signUp: {\n email: async () => {\n console.warn(\"[Atlas] signUp called but no authClient was provided to AtlasProvider\");\n return { error: { message: \"Auth client not configured\" } };\n },\n },\n signOut: async () => {\n console.warn(\"[Atlas] signOut called but no authClient was provided to AtlasProvider\");\n },\n useSession: () => ({ data: null, isPending: false }),\n};\n\nconst AtlasContext = createContext<AtlasContextValue | null>(null);\n\n/** Access the AtlasProvider context. Throws if used outside <AtlasProvider>. */\nexport function useAtlasContext(): AtlasContextValue {\n const ctx = useContext(AtlasContext);\n if (!ctx) throw new Error(\"useAtlasContext must be used within <AtlasProvider>\");\n return ctx;\n}\n\n/**\n * Lightweight provider for headless Atlas hooks.\n *\n * Wraps your app and supplies API URL, auth credentials, and an optional\n * better-auth client to all Atlas hooks. Derives isCrossOrigin from apiUrl\n * to configure credential handling for cross-origin requests.\n */\nexport function AtlasProvider({\n apiUrl,\n apiKey,\n authClient = noopAuthClient,\n children,\n}: AtlasProviderProps) {\n const isCrossOrigin =\n typeof window !== \"undefined\" &&\n apiUrl !== \"\" &&\n !apiUrl.startsWith(window.location.origin);\n\n return (\n <AtlasContext.Provider value={{ apiUrl, apiKey, authClient, isCrossOrigin }}>\n {children}\n </AtlasContext.Provider>\n );\n}\n","\"use client\";\n\nimport { useState, useRef, useMemo } from \"react\";\nimport { useChat, type UIMessage } from \"@ai-sdk/react\";\nimport { DefaultChatTransport } from \"ai\";\nimport { useAtlasContext } from \"./provider\";\n\nexport type AtlasChatStatus = \"submitted\" | \"streaming\" | \"ready\" | \"error\";\n\nexport interface UseAtlasChatOptions {\n /** Conversation ID to associate with this chat session. The server will append messages to this conversation. To load prior messages, use loadConversation() from useAtlasConversations and pass them via setMessages. */\n initialConversationId?: string;\n /** Called when the server assigns or changes the conversation ID. */\n onConversationIdChange?: (id: string) => void;\n}\n\nexport interface UseAtlasChatReturn {\n messages: UIMessage[];\n /** Replace all messages, or update via callback `(prev) => next`. */\n setMessages: (messages: UIMessage[] | ((prev: UIMessage[]) => UIMessage[])) => void;\n /** Send a text message. Rejects on failure (also surfaces via `error`). */\n sendMessage: (text: string) => Promise<void>;\n /** Current input value (managed by the hook). */\n input: string;\n /** Update the input value. */\n setInput: (input: string) => void;\n /** Chat status from the AI SDK. */\n status: AtlasChatStatus;\n /** Whether the chat is currently loading (streaming or submitted). */\n isLoading: boolean;\n /** Last error, if any. */\n error: Error | null;\n /** Current conversation ID. Initially set from options, updated when the server returns an x-conversation-id header. */\n conversationId: string | null;\n /** Manually set the conversation ID. */\n setConversationId: (id: string | null) => void;\n}\n\nexport function useAtlasChat(options: UseAtlasChatOptions = {}): UseAtlasChatReturn {\n const { apiUrl, apiKey, isCrossOrigin } = useAtlasContext();\n const [conversationId, setConversationId] = useState<string | null>(\n options.initialConversationId ?? null,\n );\n const conversationIdRef = useRef(conversationId);\n conversationIdRef.current = conversationId;\n\n const onChangeRef = useRef(options.onConversationIdChange);\n onChangeRef.current = options.onConversationIdChange;\n\n const transport = useMemo(() => {\n const headers: Record<string, string> = {};\n if (apiKey) headers[\"Authorization\"] = `Bearer ${apiKey}`;\n\n return new DefaultChatTransport({\n api: `${apiUrl}/api/v1/chat`,\n headers,\n credentials: isCrossOrigin ? \"include\" : undefined,\n body: () =>\n conversationIdRef.current\n ? { conversationId: conversationIdRef.current }\n : {},\n fetch: (async (input: RequestInfo | URL, init?: RequestInit) => {\n const response = await globalThis.fetch(input, init);\n const convId = response.headers.get(\"x-conversation-id\");\n if (convId && convId !== conversationIdRef.current) {\n setConversationId(convId);\n onChangeRef.current?.(convId);\n }\n return response;\n }) as typeof fetch,\n });\n }, [apiKey, apiUrl, isCrossOrigin]);\n\n const { messages, setMessages, sendMessage: rawSend, status, error } =\n useChat({ transport });\n\n const [input, setInput] = useState(\"\");\n\n const sendMessage = async (text: string) => {\n const previousInput = input;\n setInput(\"\");\n try {\n await rawSend({ text });\n } catch (err) {\n setInput(previousInput);\n throw err;\n }\n };\n\n return {\n messages,\n setMessages,\n sendMessage,\n input,\n setInput,\n status: status as AtlasChatStatus,\n isLoading: status === \"streaming\" || status === \"submitted\",\n error: error ?? null,\n conversationId,\n setConversationId,\n };\n}\n","\"use client\";\n\nimport { useState, useEffect } from \"react\";\nimport { useAtlasContext } from \"./provider\";\nimport { AUTH_MODES, type AuthMode } from \"../lib/types\";\n\nexport interface UseAtlasAuthReturn {\n /** Auth mode detected from the server's /api/health endpoint. `null` while the initial health check is in flight. */\n authMode: AuthMode | null;\n /** Whether the user is authenticated (based on auth mode, API key, or session). */\n isAuthenticated: boolean;\n /** Session data for managed auth mode. */\n session: { user?: { email?: string } } | null;\n /** Whether auth state is still being resolved (health check or managed session loading). */\n isLoading: boolean;\n /** Error from health check or auth operations. `null` when healthy. */\n error: Error | null;\n /** Sign in with email/password (managed auth). */\n login: (email: string, password: string) => Promise<{ error?: string }>;\n /** Sign up with email/password/name (managed auth). */\n signup: (email: string, password: string, name: string) => Promise<{ error?: string }>;\n /** Sign out (managed auth). */\n logout: () => Promise<{ error?: string }>;\n}\n\nexport function useAtlasAuth(): UseAtlasAuthReturn {\n const { apiUrl, apiKey, authClient, isCrossOrigin } = useAtlasContext();\n const [authMode, setAuthMode] = useState<AuthMode | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const managedSession = authClient.useSession();\n\n useEffect(() => {\n let cancelled = false;\n\n async function fetchHealth(attempt: number): Promise<void> {\n try {\n const res = await fetch(`${apiUrl}/api/health`, {\n credentials: isCrossOrigin ? \"include\" : \"same-origin\",\n });\n if (!res.ok) {\n console.warn(`[Atlas] Health check returned HTTP ${res.status} (attempt ${attempt})`);\n if (attempt < 2 && !cancelled) {\n await new Promise((r) => setTimeout(r, 2000));\n return fetchHealth(attempt + 1);\n }\n if (!cancelled) {\n setError(new Error(`Health check failed with HTTP ${res.status}`));\n setAuthMode(\"none\");\n }\n return;\n }\n const data = await res.json();\n const mode = data?.checks?.auth?.mode;\n if (!cancelled) {\n if (typeof mode === \"string\" && AUTH_MODES.includes(mode as AuthMode)) {\n setAuthMode(mode as AuthMode);\n } else {\n console.warn(\"[Atlas] Health check returned no valid auth mode:\", data);\n setAuthMode(\"none\");\n }\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.warn(`[Atlas] Health check failed (attempt ${attempt}):`, message);\n if (attempt < 2 && !cancelled) {\n await new Promise((r) => setTimeout(r, 2000));\n return fetchHealth(attempt + 1);\n }\n if (!cancelled) {\n setError(err instanceof Error ? err : new Error(message));\n setAuthMode(\"none\");\n }\n }\n }\n\n fetchHealth(1);\n return () => { cancelled = true; };\n }, [apiUrl, isCrossOrigin]);\n\n const isAuthenticated = (() => {\n if (authMode === null) return false;\n if (authMode === \"none\") return true;\n if (authMode === \"simple-key\" || authMode === \"byot\") return !!apiKey;\n if (authMode === \"managed\") return !!managedSession.data?.user;\n return false;\n })();\n\n const login = async (email: string, password: string) => {\n try {\n const result = await authClient.signIn.email({ email, password });\n return { error: result.error?.message };\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Login failed\";\n console.warn(\"[Atlas] login error:\", message);\n return { error: message };\n }\n };\n\n const signup = async (email: string, password: string, name: string) => {\n try {\n const result = await authClient.signUp.email({ email, password, name });\n return { error: result.error?.message };\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Signup failed\";\n console.warn(\"[Atlas] signup error:\", message);\n return { error: message };\n }\n };\n\n const logout = async () => {\n try {\n await authClient.signOut();\n return {};\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Logout failed\";\n console.warn(\"[Atlas] logout error:\", message);\n return { error: message };\n }\n };\n\n return {\n authMode,\n isAuthenticated,\n session: managedSession.data ?? null,\n isLoading: authMode === null || (authMode === \"managed\" && !!managedSession.isPending),\n error,\n login,\n signup,\n logout,\n };\n}\n","\"use client\";\n\nimport {\n useDarkMode,\n useThemeMode,\n setTheme,\n applyBrandColor,\n type ThemeMode,\n} from \"./use-dark-mode\";\n\nexport type { ThemeMode };\n\nexport interface UseAtlasThemeReturn {\n /** Current theme setting: \"light\", \"dark\", or \"system\". */\n theme: ThemeMode;\n /** Whether the effective (resolved) theme is dark. */\n isDark: boolean;\n /** Set the theme mode. Persists to localStorage. */\n setTheme: (mode: ThemeMode) => void;\n /** Apply a brand color (oklch format, e.g. \"oklch(0.759 0.148 167.71)\") via CSS custom property --atlas-brand. */\n applyBrandColor: (color: string) => void;\n}\n\nexport function useAtlasTheme(): UseAtlasThemeReturn {\n const theme = useThemeMode();\n const isDark = useDarkMode();\n\n return {\n theme,\n isDark,\n setTheme,\n applyBrandColor,\n };\n}\n","\"use client\";\n\nimport type { UIMessage } from \"@ai-sdk/react\";\nimport { useAtlasContext } from \"./provider\";\nimport { useConversations } from \"./use-conversations\";\nimport type { Conversation } from \"../lib/types\";\n\nexport interface UseAtlasConversationsOptions {\n /** When false, refresh() becomes a no-op. Defaults to true. */\n enabled?: boolean;\n}\n\nexport interface UseAtlasConversationsReturn {\n conversations: Conversation[];\n total: number;\n isLoading: boolean;\n available: boolean;\n selectedId: string | null;\n setSelectedId: (id: string | null) => void;\n refresh: () => Promise<void>;\n loadConversation: (id: string) => Promise<UIMessage[] | null>;\n deleteConversation: (id: string) => Promise<void>;\n starConversation: (id: string, starred: boolean) => Promise<void>;\n}\n\n/**\n * Manage conversation history with auth automatically wired from AtlasProvider.\n *\n * Wraps the lower-level `useConversations` hook with context-derived\n * API URL and credentials.\n */\nexport function useAtlasConversations(\n options: UseAtlasConversationsOptions = {},\n): UseAtlasConversationsReturn {\n const { apiUrl, apiKey, isCrossOrigin } = useAtlasContext();\n const { enabled = true } = options;\n\n const inner = useConversations({\n apiUrl,\n enabled,\n getHeaders: () => {\n const headers: Record<string, string> = {};\n if (apiKey) headers[\"Authorization\"] = `Bearer ${apiKey}`;\n return headers;\n },\n getCredentials: () => (isCrossOrigin ? \"include\" : \"same-origin\"),\n });\n\n return {\n conversations: inner.conversations,\n total: inner.total,\n isLoading: inner.loading,\n available: inner.available,\n selectedId: inner.selectedId,\n setSelectedId: inner.setSelectedId,\n refresh: inner.refresh,\n loadConversation: inner.loadConversation,\n deleteConversation: inner.deleteConversation,\n starConversation: inner.starConversation,\n };\n}\n"]}
|