@schandlergarcia/sf-web-components 1.8.0 → 1.9.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.
Files changed (78) hide show
  1. package/dist/components/library/cards/SemanticTableCard.d.ts +1 -1
  2. package/dist/components/library/chat/ChatBar.d.ts +14 -11
  3. package/dist/components/library/chat/ChatBar.js +2 -3
  4. package/dist/components/library/chat/ChatBar.js.map +1 -1
  5. package/dist/components/library/chat/ChatInput.d.ts +9 -8
  6. package/dist/components/library/chat/ChatInput.js.map +1 -1
  7. package/dist/components/library/chat/ChatMessage.d.ts +17 -4
  8. package/dist/components/library/chat/ChatMessage.js.map +1 -1
  9. package/dist/components/library/chat/ChatMessageList.d.ts +11 -8
  10. package/dist/components/library/chat/ChatMessageList.js.map +1 -1
  11. package/dist/components/library/chat/ChatPanel.d.ts +16 -12
  12. package/dist/components/library/chat/ChatPanel.js +8 -9
  13. package/dist/components/library/chat/ChatPanel.js.map +1 -1
  14. package/dist/components/library/chat/ChatSuggestions.d.ts +5 -4
  15. package/dist/components/library/chat/ChatSuggestions.js +2 -3
  16. package/dist/components/library/chat/ChatSuggestions.js.map +1 -1
  17. package/dist/components/library/chat/ChatToolCall.d.ts +11 -3
  18. package/dist/components/library/chat/ChatToolCall.js.map +1 -1
  19. package/dist/components/library/chat/ChatTypingIndicator.d.ts +4 -3
  20. package/dist/components/library/chat/ChatTypingIndicator.js +2 -3
  21. package/dist/components/library/chat/ChatTypingIndicator.js.map +1 -1
  22. package/dist/components/library/chat/ChatWelcome.d.ts +9 -7
  23. package/dist/components/library/chat/ChatWelcome.js +6 -7
  24. package/dist/components/library/chat/ChatWelcome.js.map +1 -1
  25. package/dist/components/library/chat/index.d.ts +10 -0
  26. package/dist/components/library/chat/useChatState.d.ts +36 -11
  27. package/dist/components/library/chat/useChatState.js +63 -46
  28. package/dist/components/library/chat/useChatState.js.map +1 -1
  29. package/dist/components/library/data/DataModeProvider.d.ts +15 -11
  30. package/dist/components/library/data/DataModeProvider.js +1 -1
  31. package/dist/components/library/data/DataModeProvider.js.map +1 -1
  32. package/dist/components/library/data/DataModeToggle.d.ts +4 -3
  33. package/dist/components/library/data/DataModeToggle.js +4 -5
  34. package/dist/components/library/data/DataModeToggle.js.map +1 -1
  35. package/dist/components/library/data/chartDataProvider.d.ts +41 -3
  36. package/dist/components/library/data/filterUtils.d.ts +38 -9
  37. package/dist/components/library/data/filterUtils.js.map +1 -1
  38. package/dist/components/library/data/useDataSource.d.ts +6 -4
  39. package/dist/components/library/data/useDataSource.js.map +1 -1
  40. package/dist/components/library/data/usePageFilters.d.ts +31 -5
  41. package/dist/components/library/data/usePageFilters.js +6 -2
  42. package/dist/components/library/data/usePageFilters.js.map +1 -1
  43. package/dist/components/library/index.d.ts +92 -73
  44. package/dist/components/library/index.js +25 -25
  45. package/dist/components/library/index.js.map +1 -1
  46. package/dist/components/library/skeletons/CardSkeleton.d.ts +5 -4
  47. package/dist/components/library/skeletons/CardSkeleton.js +2 -3
  48. package/dist/components/library/skeletons/CardSkeleton.js.map +1 -1
  49. package/dist/components/library/theme/AppThemeProvider.d.ts +13 -50
  50. package/dist/components/library/theme/AppThemeProvider.js.map +1 -1
  51. package/dist/components/library/theme/tokens.d.ts +45 -44
  52. package/dist/components/library/theme/tokens.js.map +1 -1
  53. package/package.json +1 -1
  54. package/src/components/library/cards/SemanticMetricCard.tsx +1 -1
  55. package/src/components/library/cards/SemanticTableCard.tsx +3 -3
  56. package/src/components/library/chat/{ChatBar.jsx → ChatBar.tsx} +19 -8
  57. package/src/components/library/chat/{ChatInput.jsx → ChatInput.tsx} +13 -11
  58. package/src/components/library/chat/{ChatMessage.jsx → ChatMessage.tsx} +22 -9
  59. package/src/components/library/chat/{ChatMessageList.jsx → ChatMessageList.tsx} +13 -11
  60. package/src/components/library/chat/{ChatPanel.jsx → ChatPanel.tsx} +16 -13
  61. package/src/components/library/chat/{ChatSuggestions.jsx → ChatSuggestions.tsx} +6 -5
  62. package/src/components/library/chat/{ChatToolCall.jsx → ChatToolCall.tsx} +14 -4
  63. package/src/components/library/chat/{ChatTypingIndicator.jsx → ChatTypingIndicator.tsx} +5 -2
  64. package/src/components/library/chat/{ChatWelcome.jsx → ChatWelcome.tsx} +9 -7
  65. package/src/components/library/chat/index.tsx +26 -0
  66. package/src/components/library/chat/useChatState.tsx +181 -0
  67. package/src/components/library/data/{DataModeProvider.jsx → DataModeProvider.tsx} +25 -8
  68. package/src/components/library/data/{DataModeToggle.jsx → DataModeToggle.tsx} +5 -2
  69. package/src/components/library/data/{chartDataProvider.jsx → chartDataProvider.tsx} +49 -5
  70. package/src/components/library/data/{filterUtils.jsx → filterUtils.tsx} +58 -12
  71. package/src/components/library/data/{useDataSource.jsx → useDataSource.tsx} +9 -2
  72. package/src/components/library/data/{usePageFilters.jsx → usePageFilters.tsx} +49 -9
  73. package/src/components/library/{index.jsx → index.ts} +14 -14
  74. package/src/components/library/skeletons/{CardSkeleton.jsx → CardSkeleton.tsx} +5 -4
  75. package/src/components/library/theme/{AppThemeProvider.jsx → AppThemeProvider.tsx} +20 -7
  76. package/src/components/library/theme/{tokens.jsx → tokens.tsx} +37 -3
  77. package/src/components/library/chat/index.jsx +0 -10
  78. package/src/components/library/chat/useChatState.jsx +0 -130
@@ -1,10 +1,12 @@
1
+ import React from "react";
2
+ export interface ChatWelcomeProps {
3
+ title?: string;
4
+ subtitle?: string;
5
+ suggestions?: string[];
6
+ onSuggestion?: (text: string) => void;
7
+ icon?: React.ReactNode;
8
+ }
1
9
  /**
2
10
  * Empty-state welcome screen shown before the first message.
3
- *
4
- * @param {string} title — welcome heading
5
- * @param {string} subtitle — description text
6
- * @param {string[]} suggestions — starter prompt suggestions
7
- * @param {Function} onSuggestion — (text) => void
8
- * @param {React.ReactNode} icon — custom icon override
9
11
  */
10
- export default function ChatWelcome({ title, subtitle, suggestions, onSuggestion, icon, }: string): import("react/jsx-runtime").JSX.Element;
12
+ export default function ChatWelcome({ title, subtitle, suggestions, onSuggestion, icon, }: ChatWelcomeProps): import("react/jsx-runtime").JSX.Element;
@@ -1,8 +1,7 @@
1
1
  import { jsxs as a, jsx as e } from "react/jsx-runtime";
2
- import "react";
3
- import { CpuChipIcon as o } from "@heroicons/react/24/solid";
4
- import c from "./ChatSuggestions.js";
5
- function h({
2
+ import { CpuChipIcon as c } from "@heroicons/react/24/solid";
3
+ import d from "./ChatSuggestions.js";
4
+ function x({
6
5
  title: r = "How can I help?",
7
6
  subtitle: l = "Ask me anything about your data, or try one of the suggestions below.",
8
7
  suggestions: t = [],
@@ -10,15 +9,15 @@ function h({
10
9
  icon: n
11
10
  }) {
12
11
  return /* @__PURE__ */ a("div", { className: "flex flex-1 flex-col items-center justify-center gap-4 px-6 py-12 text-center", children: [
13
- n ?? /* @__PURE__ */ e("div", { className: "flex h-14 w-14 items-center justify-center rounded-2xl bg-brand-100 dark:bg-brand-900/40", children: /* @__PURE__ */ e(o, { className: "h-7 w-7 text-brand-600 dark:text-brand-400" }) }),
12
+ n ?? /* @__PURE__ */ e("div", { className: "flex h-14 w-14 items-center justify-center rounded-2xl bg-brand-100 dark:bg-brand-900/40", children: /* @__PURE__ */ e(c, { className: "h-7 w-7 text-brand-600 dark:text-brand-400" }) }),
14
13
  /* @__PURE__ */ a("div", { children: [
15
14
  /* @__PURE__ */ e("h3", { className: "text-base font-semibold text-slate-900 dark:text-slate-50", children: r }),
16
15
  /* @__PURE__ */ e("p", { className: "mt-1 text-sm text-slate-500 dark:text-slate-400", children: l })
17
16
  ] }),
18
- t.length ? /* @__PURE__ */ e("div", { className: "mt-2", children: /* @__PURE__ */ e(c, { suggestions: t, onSelect: s }) }) : null
17
+ t.length ? /* @__PURE__ */ e("div", { className: "mt-2", children: /* @__PURE__ */ e(d, { suggestions: t, onSelect: s }) }) : null
19
18
  ] });
20
19
  }
21
20
  export {
22
- h as default
21
+ x as default
23
22
  };
24
23
  //# sourceMappingURL=ChatWelcome.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatWelcome.js","sources":["../../../../src/components/library/chat/ChatWelcome.jsx"],"sourcesContent":["import React from \"react\";\nimport { CpuChipIcon } from \"@heroicons/react/24/solid\";\nimport ChatSuggestions from \"./ChatSuggestions\";\n\n/**\n * Empty-state welcome screen shown before the first message.\n *\n * @param {string} title — welcome heading\n * @param {string} subtitle — description text\n * @param {string[]} suggestions — starter prompt suggestions\n * @param {Function} onSuggestion (text) => void\n * @param {React.ReactNode} icon custom icon override\n */\nexport default function ChatWelcome({\n title = \"How can I help?\",\n subtitle = \"Ask me anything about your data, or try one of the suggestions below.\",\n suggestions = [],\n onSuggestion,\n icon,\n}) {\n return (\n <div className=\"flex flex-1 flex-col items-center justify-center gap-4 px-6 py-12 text-center\">\n {icon ?? (\n <div className=\"flex h-14 w-14 items-center justify-center rounded-2xl bg-brand-100 dark:bg-brand-900/40\">\n <CpuChipIcon className=\"h-7 w-7 text-brand-600 dark:text-brand-400\" />\n </div>\n )}\n <div>\n <h3 className=\"text-base font-semibold text-slate-900 dark:text-slate-50\">\n {title}\n </h3>\n <p className=\"mt-1 text-sm text-slate-500 dark:text-slate-400\">\n {subtitle}\n </p>\n </div>\n {suggestions.length ? (\n <div className=\"mt-2\">\n <ChatSuggestions suggestions={suggestions} onSelect={onSuggestion} />\n </div>\n ) : null}\n </div>\n );\n}\n"],"names":["ChatWelcome","title","subtitle","suggestions","onSuggestion","icon","jsxs","jsx","CpuChipIcon","ChatSuggestions"],"mappings":";;;;AAaA,SAAwBA,EAAY;AAAA,EAClC,OAAAC,IAAQ;AAAA,EACR,UAAAC,IAAW;AAAA,EACX,aAAAC,IAAc,CAAA;AAAA,EACd,cAAAC;AAAA,EACA,MAAAC;AACF,GAAG;AACD,SACE,gBAAAC,EAAC,OAAA,EAAI,WAAU,iFACZ,UAAA;AAAA,IAAAD,KACC,gBAAAE,EAAC,SAAI,WAAU,4FACb,4BAACC,GAAA,EAAY,WAAU,8CAA6C,EAAA,CACtE;AAAA,sBAED,OAAA,EACC,UAAA;AAAA,MAAA,gBAAAD,EAAC,MAAA,EAAG,WAAU,6DACX,UAAAN,GACH;AAAA,MACA,gBAAAM,EAAC,KAAA,EAAE,WAAU,mDACV,UAAAL,EAAA,CACH;AAAA,IAAA,GACF;AAAA,IACCC,EAAY,SACX,gBAAAI,EAAC,OAAA,EAAI,WAAU,QACb,UAAA,gBAAAA,EAACE,GAAA,EAAgB,aAAAN,GAA0B,UAAUC,EAAA,CAAc,EAAA,CACrE,IACE;AAAA,EAAA,GACN;AAEJ;"}
1
+ {"version":3,"file":"ChatWelcome.js","sources":["../../../../src/components/library/chat/ChatWelcome.tsx"],"sourcesContent":["import React from \"react\";\nimport { CpuChipIcon } from \"@heroicons/react/24/solid\";\nimport ChatSuggestions from \"./ChatSuggestions\";\n\nexport interface ChatWelcomeProps {\n title?: string;\n subtitle?: string;\n suggestions?: string[];\n onSuggestion?: (text: string) => void;\n icon?: React.ReactNode;\n}\n\n/**\n * Empty-state welcome screen shown before the first message.\n */\nexport default function ChatWelcome({\n title = \"How can I help?\",\n subtitle = \"Ask me anything about your data, or try one of the suggestions below.\",\n suggestions = [],\n onSuggestion,\n icon,\n}: ChatWelcomeProps) {\n return (\n <div className=\"flex flex-1 flex-col items-center justify-center gap-4 px-6 py-12 text-center\">\n {icon ?? (\n <div className=\"flex h-14 w-14 items-center justify-center rounded-2xl bg-brand-100 dark:bg-brand-900/40\">\n <CpuChipIcon className=\"h-7 w-7 text-brand-600 dark:text-brand-400\" />\n </div>\n )}\n <div>\n <h3 className=\"text-base font-semibold text-slate-900 dark:text-slate-50\">\n {title}\n </h3>\n <p className=\"mt-1 text-sm text-slate-500 dark:text-slate-400\">\n {subtitle}\n </p>\n </div>\n {suggestions.length ? (\n <div className=\"mt-2\">\n <ChatSuggestions suggestions={suggestions} onSelect={onSuggestion} />\n </div>\n ) : null}\n </div>\n );\n}\n"],"names":["ChatWelcome","title","subtitle","suggestions","onSuggestion","icon","jsxs","jsx","CpuChipIcon","ChatSuggestions"],"mappings":";;;AAeA,SAAwBA,EAAY;AAAA,EAClC,OAAAC,IAAQ;AAAA,EACR,UAAAC,IAAW;AAAA,EACX,aAAAC,IAAc,CAAA;AAAA,EACd,cAAAC;AAAA,EACA,MAAAC;AACF,GAAqB;AACnB,SACE,gBAAAC,EAAC,OAAA,EAAI,WAAU,iFACZ,UAAA;AAAA,IAAAD,KACC,gBAAAE,EAAC,SAAI,WAAU,4FACb,4BAACC,GAAA,EAAY,WAAU,8CAA6C,EAAA,CACtE;AAAA,sBAED,OAAA,EACC,UAAA;AAAA,MAAA,gBAAAD,EAAC,MAAA,EAAG,WAAU,6DACX,UAAAN,GACH;AAAA,MACA,gBAAAM,EAAC,KAAA,EAAE,WAAU,mDACV,UAAAL,EAAA,CACH;AAAA,IAAA,GACF;AAAA,IACCC,EAAY,SACX,gBAAAI,EAAC,OAAA,EAAI,WAAU,QACb,UAAA,gBAAAA,EAACE,GAAA,EAAgB,aAAAN,GAA0B,UAAUC,EAAA,CAAc,EAAA,CACrE,IACE;AAAA,EAAA,GACN;AAEJ;"}
@@ -8,3 +8,13 @@ export { default as ChatSuggestions } from "./ChatSuggestions";
8
8
  export { default as ChatToolCall } from "./ChatToolCall";
9
9
  export { default as ChatWelcome } from "./ChatWelcome";
10
10
  export { default as useChatState } from "./useChatState";
11
+ export type { ChatPanelProps } from "./ChatPanel";
12
+ export type { ChatBarProps } from "./ChatBar";
13
+ export type { ChatMessageListProps } from "./ChatMessageList";
14
+ export type { ChatMessageProps, ChatMessageData } from "./ChatMessage";
15
+ export type { ChatInputProps } from "./ChatInput";
16
+ export type { ChatTypingIndicatorProps } from "./ChatTypingIndicator";
17
+ export type { ChatSuggestionsProps } from "./ChatSuggestions";
18
+ export type { ChatToolCallProps, ToolCall } from "./ChatToolCall";
19
+ export type { ChatWelcomeProps } from "./ChatWelcome";
20
+ export type { UseChatStateOptions, UseChatStateReturn, ChatMessage as ChatMessageType, ChatStateHelpers, } from "./useChatState";
@@ -1,13 +1,41 @@
1
+ import { ToolCall } from "./ChatToolCall";
2
+ export interface ChatMessage {
3
+ id: string;
4
+ role: "user" | "assistant" | "system";
5
+ content?: string;
6
+ timestamp: string;
7
+ components?: unknown[];
8
+ toolCalls?: ToolCall[];
9
+ isError?: boolean;
10
+ isStreaming?: boolean;
11
+ }
12
+ export interface ChatStateHelpers {
13
+ addMessage: (msg: Partial<ChatMessage>) => string;
14
+ updateMessage: (id: string, updates: Partial<ChatMessage>) => void;
15
+ appendChunk: (id: string, chunk: string) => void;
16
+ setStreaming: (streaming: boolean) => void;
17
+ }
18
+ export interface UseChatStateOptions {
19
+ initialMessages?: Partial<ChatMessage>[];
20
+ onSend?: (userMessage: ChatMessage, allMessages: ChatMessage[], helpers: ChatStateHelpers) => Promise<Partial<ChatMessage> | void>;
21
+ }
22
+ export interface UseChatStateReturn {
23
+ messages: ChatMessage[];
24
+ isLoading: boolean;
25
+ isStreaming: boolean;
26
+ error: string | null;
27
+ sendMessage: (content: string, extra?: Partial<ChatMessage>) => Promise<void>;
28
+ addMessage: (msg: Partial<ChatMessage>) => string;
29
+ updateMessage: (id: string, updates: Partial<ChatMessage>) => void;
30
+ appendChunk: (id: string, chunk: string) => void;
31
+ removeMessage: (id: string) => void;
32
+ clearMessages: () => void;
33
+ retryLast: () => void;
34
+ setError: (error: string | null) => void;
35
+ }
1
36
  /**
2
37
  * Core state management hook for AI chat.
3
38
  *
4
- * @param {Object} options
5
- * @param {Array} options.initialMessages — seed the conversation
6
- * @param {Function} options.onSend — async (userMessage, allMessages) => assistantMessage | void
7
- * Return a message object to add it, or use appendChunk / addMessage for streaming.
8
- *
9
- * @returns {Object}
10
- *
11
39
  * @example
12
40
  * const chat = useChatState({
13
41
  * onSend: async (msg, history) => {
@@ -17,7 +45,4 @@
17
45
  * },
18
46
  * });
19
47
  */
20
- export default function useChatState({ initialMessages, onSend }?: {
21
- initialMessages: any[];
22
- onSend: Function;
23
- }): Object;
48
+ export default function useChatState({ initialMessages, onSend }?: UseChatStateOptions): UseChatStateReturn;
@@ -1,77 +1,94 @@
1
- import { useState as g, useRef as k, useCallback as o } from "react";
2
- let v = 1;
3
- function S() {
4
- return `msg-${Date.now()}-${v++}`;
1
+ import { useState as u, useRef as C, useCallback as o } from "react";
2
+ let L = 1;
3
+ function m() {
4
+ return `msg-${Date.now()}-${L++}`;
5
5
  }
6
- function R({ initialMessages: h = [], onSend: I } = {}) {
7
- const [r, a] = g(
8
- () => h.map((e) => ({ id: S(), timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...e }))
9
- ), [x, M] = g(!1), [D, w] = g(!1), [O, l] = g(null), y = k(I);
10
- y.current = I;
6
+ function k({ initialMessages: y = [], onSend: p } = {}) {
7
+ const [r, a] = u(
8
+ () => y.map((e) => ({
9
+ id: m(),
10
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
11
+ role: e.role || "user",
12
+ ...e
13
+ }))
14
+ ), [I, S] = u(!1), [h, M] = u(!1), [x, l] = u(null), w = C(p);
15
+ w.current = p;
11
16
  const c = o((e) => {
12
- const t = { id: S(), timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...e };
13
- return a((s) => [...s, t]), t.id;
14
- }, []), d = o((e, t) => {
17
+ const n = {
18
+ id: m(),
19
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
20
+ role: e.role || "assistant",
21
+ ...e
22
+ };
23
+ return a((s) => [...s, n]), n.id;
24
+ }, []), g = o((e, n) => {
15
25
  a(
16
- (s) => s.map((n) => n.id === e ? { ...n, ...t } : n)
26
+ (s) => s.map((t) => t.id === e ? { ...t, ...n } : t)
17
27
  );
18
- }, []), f = o((e, t) => {
28
+ }, []), d = o((e, n) => {
19
29
  a(
20
30
  (s) => s.map(
21
- (n) => n.id === e ? { ...n, content: (n.content ?? "") + t } : n
31
+ (t) => t.id === e ? { ...t, content: (t.content ?? "") + n } : t
22
32
  )
23
33
  );
24
- }, []), C = o((e) => {
25
- a((t) => t.filter((s) => s.id !== e));
26
- }, []), L = o(() => {
34
+ }, []), D = o((e) => {
35
+ a((n) => n.filter((s) => s.id !== e));
36
+ }, []), E = o(() => {
27
37
  a([]), l(null);
28
- }, []), m = o(
29
- async (e, t = {}) => {
38
+ }, []), f = o(
39
+ async (e, n = {}) => {
30
40
  if (!e?.trim()) return;
31
41
  l(null);
32
- const s = { role: "user", content: e.trim(), ...t }, n = S(), p = { ...s, id: n, timestamp: (/* @__PURE__ */ new Date()).toISOString() };
33
- a((i) => [...i, p]), M(!0);
42
+ const s = {
43
+ role: "user",
44
+ content: e.trim(),
45
+ ...n,
46
+ id: m(),
47
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
48
+ };
49
+ a((t) => [...t, s]), S(!0);
34
50
  try {
35
- const i = [...r, p], u = await y.current?.(p, i, {
51
+ const t = [...r, s], i = await w.current?.(s, t, {
36
52
  addMessage: c,
37
- updateMessage: d,
38
- appendChunk: f,
39
- setStreaming: w
53
+ updateMessage: g,
54
+ appendChunk: d,
55
+ setStreaming: M
40
56
  });
41
- u && typeof u == "object" && u.role && c(u);
42
- } catch (i) {
43
- l(i?.message ?? "Failed to send message"), c({
57
+ i && typeof i == "object" && i.role && c(i);
58
+ } catch (t) {
59
+ const i = t instanceof Error ? t.message : "Failed to send message";
60
+ l(i), c({
44
61
  role: "system",
45
- content: i?.message ?? "Something went wrong. Please try again.",
62
+ content: t instanceof Error ? t.message : "Something went wrong. Please try again.",
46
63
  isError: !0
47
64
  });
48
65
  } finally {
49
- M(!1), w(!1);
66
+ S(!1), M(!1);
50
67
  }
51
68
  },
52
- [r, c, d, f]
53
- ), b = o(() => {
69
+ [r, c, g, d]
70
+ ), O = o(() => {
54
71
  const e = [...r].reverse().find((s) => s.role === "user");
55
72
  if (!e) return;
56
- const t = r.lastIndexOf(e);
57
- a(r.slice(0, t)), l(null), m(e.content);
58
- }, [r, m]);
73
+ const n = r.lastIndexOf(e);
74
+ a(r.slice(0, n)), l(null), f(e.content || "");
75
+ }, [r, f]);
59
76
  return {
60
77
  messages: r,
61
- isLoading: x,
62
- isStreaming: D,
63
- error: O,
64
- sendMessage: m,
78
+ isLoading: I,
79
+ isStreaming: h,
80
+ error: x,
81
+ sendMessage: f,
65
82
  addMessage: c,
66
- updateMessage: d,
67
- appendChunk: f,
68
- removeMessage: C,
69
- clearMessages: L,
70
- retryLast: b,
83
+ updateMessage: g,
84
+ appendChunk: d,
85
+ removeMessage: D,
86
+ clearMessages: E,
87
+ retryLast: O,
71
88
  setError: l
72
89
  };
73
90
  }
74
91
  export {
75
- R as default
92
+ k as default
76
93
  };
77
94
  //# sourceMappingURL=useChatState.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useChatState.js","sources":["../../../../src/components/library/chat/useChatState.jsx"],"sourcesContent":["import { useState, useCallback, useRef } from \"react\";\n\nlet _nextId = 1;\nfunction uid() {\n return `msg-${Date.now()}-${_nextId++}`;\n}\n\n/**\n * Core state management hook for AI chat.\n *\n * @param {Object} options\n * @param {Array} options.initialMessages seed the conversation\n * @param {Function} options.onSend — async (userMessage, allMessages) => assistantMessage | void\n * Return a message object to add it, or use appendChunk / addMessage for streaming.\n *\n * @returns {Object}\n *\n * @example\n * const chat = useChatState({\n * onSend: async (msg, history) => {\n * const res = await fetch(\"/api/chat\", { method: \"POST\", body: JSON.stringify({ messages: history }) });\n * const data = await res.json();\n * return { role: \"assistant\", content: data.reply, components: data.components };\n * },\n * });\n */\nexport default function useChatState({ initialMessages = [], onSend } = {}) {\n const [messages, setMessages] = useState(() =>\n initialMessages.map((m) => ({ id: uid(), timestamp: new Date().toISOString(), ...m }))\n );\n const [isLoading, setIsLoading] = useState(false);\n const [isStreaming, setIsStreaming] = useState(false);\n const [error, setError] = useState(null);\n const onSendRef = useRef(onSend);\n onSendRef.current = onSend;\n\n const addMessage = useCallback((msg) => {\n const full = { id: uid(), timestamp: new Date().toISOString(), ...msg };\n setMessages((prev) => [...prev, full]);\n return full.id;\n }, []);\n\n const updateMessage = useCallback((id, updates) => {\n setMessages((prev) =>\n prev.map((m) => (m.id === id ? { ...m, ...updates } : m))\n );\n }, []);\n\n const appendChunk = useCallback((id, chunk) => {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === id ? { ...m, content: (m.content ?? \"\") + chunk } : m\n )\n );\n }, []);\n\n const removeMessage = useCallback((id) => {\n setMessages((prev) => prev.filter((m) => m.id !== id));\n }, []);\n\n const clearMessages = useCallback(() => {\n setMessages([]);\n setError(null);\n }, []);\n\n const sendMessage = useCallback(\n async (content, extra = {}) => {\n if (!content?.trim()) return;\n setError(null);\n\n const userMsg = { role: \"user\", content: content.trim(), ...extra };\n const userId = uid();\n const fullUser = { ...userMsg, id: userId, timestamp: new Date().toISOString() };\n\n setMessages((prev) => [...prev, fullUser]);\n setIsLoading(true);\n\n try {\n const allMsgs = [...messages, fullUser];\n const result = await onSendRef.current?.(fullUser, allMsgs, {\n addMessage,\n updateMessage,\n appendChunk,\n setStreaming: setIsStreaming,\n });\n\n if (result && typeof result === \"object\" && result.role) {\n addMessage(result);\n }\n } catch (err) {\n setError(err?.message ?? \"Failed to send message\");\n addMessage({\n role: \"system\",\n content: err?.message ?? \"Something went wrong. Please try again.\",\n isError: true,\n });\n } finally {\n setIsLoading(false);\n setIsStreaming(false);\n }\n },\n [messages, addMessage, updateMessage, appendChunk]\n );\n\n const retryLast = useCallback(() => {\n const lastUser = [...messages].reverse().find((m) => m.role === \"user\");\n if (!lastUser) return;\n\n const idx = messages.lastIndexOf(lastUser);\n setMessages(messages.slice(0, idx));\n setError(null);\n\n sendMessage(lastUser.content);\n }, [messages, sendMessage]);\n\n return {\n messages,\n isLoading,\n isStreaming,\n error,\n sendMessage,\n addMessage,\n updateMessage,\n appendChunk,\n removeMessage,\n clearMessages,\n retryLast,\n setError,\n };\n}\n"],"names":["_nextId","uid","useChatState","initialMessages","onSend","messages","setMessages","useState","m","isLoading","setIsLoading","isStreaming","setIsStreaming","error","setError","onSendRef","useRef","addMessage","useCallback","msg","full","prev","updateMessage","id","updates","appendChunk","chunk","removeMessage","clearMessages","sendMessage","content","extra","userMsg","userId","fullUser","allMsgs","result","err","retryLast","lastUser","idx"],"mappings":"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"}
1
+ {"version":3,"file":"useChatState.js","sources":["../../../../src/components/library/chat/useChatState.tsx"],"sourcesContent":["import { useState, useCallback, useRef } from \"react\";\nimport { ToolCall } from \"./ChatToolCall\";\n\nlet _nextId = 1;\nfunction uid(): string {\n return `msg-${Date.now()}-${_nextId++}`;\n}\n\nexport interface ChatMessage {\n id: string;\n role: \"user\" | \"assistant\" | \"system\";\n content?: string;\n timestamp: string;\n components?: unknown[];\n toolCalls?: ToolCall[];\n isError?: boolean;\n isStreaming?: boolean;\n}\n\nexport interface ChatStateHelpers {\n addMessage: (msg: Partial<ChatMessage>) => string;\n updateMessage: (id: string, updates: Partial<ChatMessage>) => void;\n appendChunk: (id: string, chunk: string) => void;\n setStreaming: (streaming: boolean) => void;\n}\n\nexport interface UseChatStateOptions {\n initialMessages?: Partial<ChatMessage>[];\n onSend?: (\n userMessage: ChatMessage,\n allMessages: ChatMessage[],\n helpers: ChatStateHelpers\n ) => Promise<Partial<ChatMessage> | void>;\n}\n\nexport interface UseChatStateReturn {\n messages: ChatMessage[];\n isLoading: boolean;\n isStreaming: boolean;\n error: string | null;\n sendMessage: (content: string, extra?: Partial<ChatMessage>) => Promise<void>;\n addMessage: (msg: Partial<ChatMessage>) => string;\n updateMessage: (id: string, updates: Partial<ChatMessage>) => void;\n appendChunk: (id: string, chunk: string) => void;\n removeMessage: (id: string) => void;\n clearMessages: () => void;\n retryLast: () => void;\n setError: (error: string | null) => void;\n}\n\n/**\n * Core state management hook for AI chat.\n *\n * @example\n * const chat = useChatState({\n * onSend: async (msg, history) => {\n * const res = await fetch(\"/api/chat\", { method: \"POST\", body: JSON.stringify({ messages: history }) });\n * const data = await res.json();\n * return { role: \"assistant\", content: data.reply, components: data.components };\n * },\n * });\n */\nexport default function useChatState({ initialMessages = [], onSend }: UseChatStateOptions = {}): UseChatStateReturn {\n const [messages, setMessages] = useState<ChatMessage[]>(() =>\n initialMessages.map((m) => ({\n id: uid(),\n timestamp: new Date().toISOString(),\n role: m.role || \"user\",\n ...m\n } as ChatMessage))\n );\n const [isLoading, setIsLoading] = useState(false);\n const [isStreaming, setIsStreaming] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const onSendRef = useRef(onSend);\n onSendRef.current = onSend;\n\n const addMessage = useCallback((msg: Partial<ChatMessage>): string => {\n const full: ChatMessage = {\n id: uid(),\n timestamp: new Date().toISOString(),\n role: msg.role || \"assistant\",\n ...msg\n } as ChatMessage;\n setMessages((prev) => [...prev, full]);\n return full.id;\n }, []);\n\n const updateMessage = useCallback((id: string, updates: Partial<ChatMessage>) => {\n setMessages((prev) =>\n prev.map((m) => (m.id === id ? { ...m, ...updates } : m))\n );\n }, []);\n\n const appendChunk = useCallback((id: string, chunk: string) => {\n setMessages((prev) =>\n prev.map((m) =>\n m.id === id ? { ...m, content: (m.content ?? \"\") + chunk } : m\n )\n );\n }, []);\n\n const removeMessage = useCallback((id: string) => {\n setMessages((prev) => prev.filter((m) => m.id !== id));\n }, []);\n\n const clearMessages = useCallback(() => {\n setMessages([]);\n setError(null);\n }, []);\n\n const sendMessage = useCallback(\n async (content: string, extra: Partial<ChatMessage> = {}) => {\n if (!content?.trim()) return;\n setError(null);\n\n const userMsg: ChatMessage = {\n role: \"user\",\n content: content.trim(),\n ...extra,\n id: uid(),\n timestamp: new Date().toISOString()\n } as ChatMessage;\n\n setMessages((prev) => [...prev, userMsg]);\n setIsLoading(true);\n\n try {\n const allMsgs = [...messages, userMsg];\n const result = await onSendRef.current?.(userMsg, allMsgs, {\n addMessage,\n updateMessage,\n appendChunk,\n setStreaming: setIsStreaming,\n });\n\n if (result && typeof result === \"object\" && result.role) {\n addMessage(result);\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : \"Failed to send message\";\n setError(errorMessage);\n addMessage({\n role: \"system\",\n content: err instanceof Error ? err.message : \"Something went wrong. Please try again.\",\n isError: true,\n });\n } finally {\n setIsLoading(false);\n setIsStreaming(false);\n }\n },\n [messages, addMessage, updateMessage, appendChunk]\n );\n\n const retryLast = useCallback(() => {\n const lastUser = [...messages].reverse().find((m) => m.role === \"user\");\n if (!lastUser) return;\n\n const idx = messages.lastIndexOf(lastUser);\n setMessages(messages.slice(0, idx));\n setError(null);\n\n sendMessage(lastUser.content || \"\");\n }, [messages, sendMessage]);\n\n return {\n messages,\n isLoading,\n isStreaming,\n error,\n sendMessage,\n addMessage,\n updateMessage,\n appendChunk,\n removeMessage,\n clearMessages,\n retryLast,\n setError,\n };\n}\n"],"names":["_nextId","uid","useChatState","initialMessages","onSend","messages","setMessages","useState","m","isLoading","setIsLoading","isStreaming","setIsStreaming","error","setError","onSendRef","useRef","addMessage","useCallback","msg","full","prev","updateMessage","id","updates","appendChunk","chunk","removeMessage","clearMessages","sendMessage","content","extra","userMsg","allMsgs","result","err","errorMessage","retryLast","lastUser","idx"],"mappings":"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"}
@@ -1,22 +1,26 @@
1
+ import React from "react";
2
+ export type DataMode = "sample" | "live";
3
+ export interface DataModeContextValue {
4
+ mode: DataMode;
5
+ isSample: boolean;
6
+ isLive: boolean;
7
+ toggle: () => void;
8
+ setMode: (mode: DataMode) => void;
9
+ }
1
10
  /**
2
11
  * Read the current data mode from any component.
3
12
  *
4
13
  * @returns {{ mode: "sample"|"live", isSample: boolean, isLive: boolean, toggle: () => void, setMode: (mode) => void }}
5
14
  */
6
- export function useDataMode(): {
7
- mode: "sample" | "live";
8
- isSample: boolean;
9
- isLive: boolean;
10
- toggle: () => void;
11
- setMode: (mode: any) => void;
12
- };
15
+ export declare function useDataMode(): DataModeContextValue;
16
+ export interface DataModeProviderProps {
17
+ initialMode?: DataMode;
18
+ children: React.ReactNode;
19
+ }
13
20
  /**
14
21
  * Provides global data-mode state (sample vs live) to the component tree.
15
22
  * Persists to localStorage so the choice survives page reloads.
16
23
  *
17
24
  * Wrap once in _app.js alongside AppThemeProvider.
18
25
  */
19
- export default function DataModeProvider({ initialMode, children }: {
20
- initialMode?: string | undefined;
21
- children: any;
22
- }): import("react/jsx-runtime").JSX.Element;
26
+ export default function DataModeProvider({ initialMode, children }: DataModeProviderProps): import("react/jsx-runtime").JSX.Element;
@@ -17,7 +17,7 @@ function v({ initialMode: n = "sample", children: r }) {
17
17
  t.useEffect(() => {
18
18
  try {
19
19
  const e = window.localStorage.getItem(l);
20
- c.includes(e) && a(e);
20
+ e && c.includes(e) && a(e);
21
21
  } catch {
22
22
  }
23
23
  }, []), t.useEffect(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"DataModeProvider.js","sources":["../../../../src/components/library/data/DataModeProvider.jsx"],"sourcesContent":["import React from \"react\";\n\nconst DataModeContext = React.createContext({\n mode: \"sample\",\n isSample: true,\n isLive: false,\n toggle: () => {},\n setMode: () => {},\n});\n\nconst STORAGE_KEY = \"app-data-mode\";\nconst VALID_MODES = [\"sample\", \"live\"];\n\n/**\n * Read the current data mode from any component.\n *\n * @returns {{ mode: \"sample\"|\"live\", isSample: boolean, isLive: boolean, toggle: () => void, setMode: (mode) => void }}\n */\nexport function useDataMode() {\n return React.useContext(DataModeContext);\n}\n\n/**\n * Provides global data-mode state (sample vs live) to the component tree.\n * Persists to localStorage so the choice survives page reloads.\n *\n * Wrap once in _app.js alongside AppThemeProvider.\n */\nexport default function DataModeProvider({ initialMode = \"sample\", children }) {\n const [mode, setModeState] = React.useState(initialMode);\n\n React.useEffect(() => {\n try {\n const stored = window.localStorage.getItem(STORAGE_KEY);\n if (VALID_MODES.includes(stored)) setModeState(stored);\n } catch {\n // SSR or storage unavailable\n }\n }, []);\n\n React.useEffect(() => {\n try {\n window.localStorage.setItem(STORAGE_KEY, mode);\n } catch {\n // ignore\n }\n }, [mode]);\n\n const setMode = React.useCallback((m) => {\n if (VALID_MODES.includes(m)) setModeState(m);\n }, []);\n\n const value = React.useMemo(\n () => ({\n mode,\n isSample: mode === \"sample\",\n isLive: mode === \"live\",\n toggle: () => setModeState((m) => (m === \"sample\" ? \"live\" : \"sample\")),\n setMode,\n }),\n [mode, setMode]\n );\n\n return (\n <DataModeContext.Provider value={value}>{children}</DataModeContext.Provider>\n );\n}\n"],"names":["DataModeContext","React","STORAGE_KEY","VALID_MODES","useDataMode","DataModeProvider","initialMode","children","mode","setModeState","stored","setMode","m","value","jsx"],"mappings":";;AAEA,MAAMA,IAAkBC,EAAM,cAAc;AAAA,EAC1C,MAAM;AAAA,EACN,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,QAAQ,MAAM;AAAA,EAAC;AAAA,EACf,SAAS,MAAM;AAAA,EAAC;AAClB,CAAC,GAEKC,IAAc,iBACdC,IAAc,CAAC,UAAU,MAAM;AAO9B,SAASC,IAAc;AAC5B,SAAOH,EAAM,WAAWD,CAAe;AACzC;AAQA,SAAwBK,EAAiB,EAAE,aAAAC,IAAc,UAAU,UAAAC,KAAY;AAC7E,QAAM,CAACC,GAAMC,CAAY,IAAIR,EAAM,SAASK,CAAW;AAEvDL,EAAAA,EAAM,UAAU,MAAM;AACpB,QAAI;AACF,YAAMS,IAAS,OAAO,aAAa,QAAQR,CAAW;AACtD,MAAIC,EAAY,SAASO,CAAM,OAAgBA,CAAM;AAAA,IACvD,QAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAAA,CAAE,GAELT,EAAM,UAAU,MAAM;AACpB,QAAI;AACF,aAAO,aAAa,QAAQC,GAAaM,CAAI;AAAA,IAC/C,QAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAACA,CAAI,CAAC;AAET,QAAMG,IAAUV,EAAM,YAAY,CAACW,MAAM;AACvC,IAAIT,EAAY,SAASS,CAAC,OAAgBA,CAAC;AAAA,EAC7C,GAAG,CAAA,CAAE,GAECC,IAAQZ,EAAM;AAAA,IAClB,OAAO;AAAA,MACL,MAAAO;AAAA,MACA,UAAUA,MAAS;AAAA,MACnB,QAAQA,MAAS;AAAA,MACjB,QAAQ,MAAMC,EAAa,CAACG,MAAOA,MAAM,WAAW,SAAS,QAAS;AAAA,MACtE,SAAAD;AAAA,IAAA;AAAA,IAEF,CAACH,GAAMG,CAAO;AAAA,EAAA;AAGhB,SACE,gBAAAG,EAACd,EAAgB,UAAhB,EAAyB,OAAAa,GAAe,UAAAN,EAAA,CAAS;AAEtD;"}
1
+ {"version":3,"file":"DataModeProvider.js","sources":["../../../../src/components/library/data/DataModeProvider.tsx"],"sourcesContent":["import React from \"react\";\n\nexport type DataMode = \"sample\" | \"live\";\n\nexport interface DataModeContextValue {\n mode: DataMode;\n isSample: boolean;\n isLive: boolean;\n toggle: () => void;\n setMode: (mode: DataMode) => void;\n}\n\nconst DataModeContext = React.createContext<DataModeContextValue>({\n mode: \"sample\",\n isSample: true,\n isLive: false,\n toggle: () => {},\n setMode: () => {},\n});\n\nconst STORAGE_KEY = \"app-data-mode\";\nconst VALID_MODES: DataMode[] = [\"sample\", \"live\"];\n\n/**\n * Read the current data mode from any component.\n *\n * @returns {{ mode: \"sample\"|\"live\", isSample: boolean, isLive: boolean, toggle: () => void, setMode: (mode) => void }}\n */\nexport function useDataMode(): DataModeContextValue {\n return React.useContext(DataModeContext);\n}\n\nexport interface DataModeProviderProps {\n initialMode?: DataMode;\n children: React.ReactNode;\n}\n\n/**\n * Provides global data-mode state (sample vs live) to the component tree.\n * Persists to localStorage so the choice survives page reloads.\n *\n * Wrap once in _app.js alongside AppThemeProvider.\n */\nexport default function DataModeProvider({ initialMode = \"sample\", children }: DataModeProviderProps) {\n const [mode, setModeState] = React.useState<DataMode>(initialMode);\n\n React.useEffect(() => {\n try {\n const stored = window.localStorage.getItem(STORAGE_KEY);\n if (stored && VALID_MODES.includes(stored as DataMode)) {\n setModeState(stored as DataMode);\n }\n } catch {\n // SSR or storage unavailable\n }\n }, []);\n\n React.useEffect(() => {\n try {\n window.localStorage.setItem(STORAGE_KEY, mode);\n } catch {\n // ignore\n }\n }, [mode]);\n\n const setMode = React.useCallback((m: DataMode) => {\n if (VALID_MODES.includes(m)) setModeState(m);\n }, []);\n\n const value = React.useMemo<DataModeContextValue>(\n () => ({\n mode,\n isSample: mode === \"sample\",\n isLive: mode === \"live\",\n toggle: () => setModeState((m) => (m === \"sample\" ? \"live\" : \"sample\")),\n setMode,\n }),\n [mode, setMode]\n );\n\n return (\n <DataModeContext.Provider value={value}>{children}</DataModeContext.Provider>\n );\n}\n"],"names":["DataModeContext","React","STORAGE_KEY","VALID_MODES","useDataMode","DataModeProvider","initialMode","children","mode","setModeState","stored","setMode","m","value","jsx"],"mappings":";;AAYA,MAAMA,IAAkBC,EAAM,cAAoC;AAAA,EAChE,MAAM;AAAA,EACN,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,QAAQ,MAAM;AAAA,EAAC;AAAA,EACf,SAAS,MAAM;AAAA,EAAC;AAClB,CAAC,GAEKC,IAAc,iBACdC,IAA0B,CAAC,UAAU,MAAM;AAO1C,SAASC,IAAoC;AAClD,SAAOH,EAAM,WAAWD,CAAe;AACzC;AAaA,SAAwBK,EAAiB,EAAE,aAAAC,IAAc,UAAU,UAAAC,KAAmC;AACpG,QAAM,CAACC,GAAMC,CAAY,IAAIR,EAAM,SAAmBK,CAAW;AAEjEL,EAAAA,EAAM,UAAU,MAAM;AACpB,QAAI;AACF,YAAMS,IAAS,OAAO,aAAa,QAAQR,CAAW;AACtD,MAAIQ,KAAUP,EAAY,SAASO,CAAkB,KACnDD,EAAaC,CAAkB;AAAA,IAEnC,QAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAAA,CAAE,GAELT,EAAM,UAAU,MAAM;AACpB,QAAI;AACF,aAAO,aAAa,QAAQC,GAAaM,CAAI;AAAA,IAC/C,QAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAACA,CAAI,CAAC;AAET,QAAMG,IAAUV,EAAM,YAAY,CAACW,MAAgB;AACjD,IAAIT,EAAY,SAASS,CAAC,OAAgBA,CAAC;AAAA,EAC7C,GAAG,CAAA,CAAE,GAECC,IAAQZ,EAAM;AAAA,IAClB,OAAO;AAAA,MACL,MAAAO;AAAA,MACA,UAAUA,MAAS;AAAA,MACnB,QAAQA,MAAS;AAAA,MACjB,QAAQ,MAAMC,EAAa,CAACG,MAAOA,MAAM,WAAW,SAAS,QAAS;AAAA,MACtE,SAAAD;AAAA,IAAA;AAAA,IAEF,CAACH,GAAMG,CAAO;AAAA,EAAA;AAGhB,SACE,gBAAAG,EAACd,EAAgB,UAAhB,EAAyB,OAAAa,GAAe,UAAAN,EAAA,CAAS;AAEtD;"}
@@ -1,7 +1,8 @@
1
+ export interface DataModeToggleProps {
2
+ className?: string;
3
+ }
1
4
  /**
2
5
  * Pill toggle for switching between sample and live data modes.
3
6
  * Place in the AppShell header next to the theme toggle.
4
7
  */
5
- export default function DataModeToggle({ className }: {
6
- className?: string | undefined;
7
- }): import("react/jsx-runtime").JSX.Element;
8
+ export default function DataModeToggle({ className }: DataModeToggleProps): import("react/jsx-runtime").JSX.Element;
@@ -1,8 +1,7 @@
1
1
  import { jsxs as d, jsx as a } from "react/jsx-runtime";
2
- import "react";
3
2
  import { useDataMode as m } from "./DataModeProvider.js";
4
- import { BeakerIcon as l, SignalIcon as i } from "@heroicons/react/24/outline";
5
- function c({ className: o = "" }) {
3
+ import { BeakerIcon as l, SignalIcon as b } from "@heroicons/react/24/outline";
4
+ function g({ className: o = "" }) {
6
5
  const { mode: r, toggle: t } = m(), e = r === "sample";
7
6
  return /* @__PURE__ */ d(
8
7
  "button",
@@ -16,13 +15,13 @@ function c({ className: o = "" }) {
16
15
  ].filter(Boolean).join(" "),
17
16
  "aria-label": `Data mode: ${r}. Click to switch to ${e ? "live" : "sample"}.`,
18
17
  children: [
19
- e ? /* @__PURE__ */ a(l, { className: "h-3.5 w-3.5", "aria-hidden": "true" }) : /* @__PURE__ */ a(i, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
18
+ e ? /* @__PURE__ */ a(l, { className: "h-3.5 w-3.5", "aria-hidden": "true" }) : /* @__PURE__ */ a(b, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
20
19
  e ? "Sample" : "Live"
21
20
  ]
22
21
  }
23
22
  );
24
23
  }
25
24
  export {
26
- c as default
25
+ g as default
27
26
  };
28
27
  //# sourceMappingURL=DataModeToggle.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DataModeToggle.js","sources":["../../../../src/components/library/data/DataModeToggle.jsx"],"sourcesContent":["import React from \"react\";\nimport { useDataMode } from \"./DataModeProvider\";\nimport { BeakerIcon, SignalIcon } from \"@heroicons/react/24/outline\";\n\n/**\n * Pill toggle for switching between sample and live data modes.\n * Place in the AppShell header next to the theme toggle.\n */\nexport default function DataModeToggle({ className = \"\" }) {\n const { mode, toggle } = useDataMode();\n const isSample = mode === \"sample\";\n\n return (\n <button\n type=\"button\"\n onClick={toggle}\n className={[\n \"inline-flex items-center gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs font-semibold shadow-sm transition\",\n isSample\n ? \"border-amber-200 bg-amber-50 text-amber-700 hover:bg-amber-100 dark:border-amber-800 dark:bg-amber-950/40 dark:text-amber-300 dark:hover:bg-amber-950/60\"\n : \"border-emerald-200 bg-emerald-50 text-emerald-700 hover:bg-emerald-100 dark:border-emerald-800 dark:bg-emerald-950/40 dark:text-emerald-300 dark:hover:bg-emerald-950/60\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n aria-label={`Data mode: ${mode}. Click to switch to ${isSample ? \"live\" : \"sample\"}.`}\n >\n {isSample ? (\n <BeakerIcon className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n ) : (\n <SignalIcon className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n )}\n {isSample ? \"Sample\" : \"Live\"}\n </button>\n );\n}\n"],"names":["DataModeToggle","className","mode","toggle","useDataMode","isSample","jsxs","jsx","BeakerIcon","SignalIcon"],"mappings":";;;;AAQA,SAAwBA,EAAe,EAAE,WAAAC,IAAY,MAAM;AACzD,QAAM,EAAE,MAAAC,GAAM,QAAAC,EAAA,IAAWC,EAAA,GACnBC,IAAWH,MAAS;AAE1B,SACE,gBAAAI;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,SAASH;AAAA,MACT,WAAW;AAAA,QACT;AAAA,QACAE,IACI,6JACA;AAAA,QACJJ;AAAA,MAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,MACX,cAAY,cAAcC,CAAI,wBAAwBG,IAAW,SAAS,QAAQ;AAAA,MAEjF,UAAA;AAAA,QAAAA,IACC,gBAAAE,EAACC,GAAA,EAAW,WAAU,eAAc,eAAY,OAAA,CAAO,IAEvD,gBAAAD,EAACE,GAAA,EAAW,WAAU,eAAc,eAAY,QAAO;AAAA,QAExDJ,IAAW,WAAW;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAG7B;"}
1
+ {"version":3,"file":"DataModeToggle.js","sources":["../../../../src/components/library/data/DataModeToggle.tsx"],"sourcesContent":["import { useDataMode } from \"./DataModeProvider\";\nimport { BeakerIcon, SignalIcon } from \"@heroicons/react/24/outline\";\n\nexport interface DataModeToggleProps {\n className?: string;\n}\n\n/**\n * Pill toggle for switching between sample and live data modes.\n * Place in the AppShell header next to the theme toggle.\n */\nexport default function DataModeToggle({ className = \"\" }: DataModeToggleProps) {\n const { mode, toggle } = useDataMode();\n const isSample = mode === \"sample\";\n\n return (\n <button\n type=\"button\"\n onClick={toggle}\n className={[\n \"inline-flex items-center gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs font-semibold shadow-sm transition\",\n isSample\n ? \"border-amber-200 bg-amber-50 text-amber-700 hover:bg-amber-100 dark:border-amber-800 dark:bg-amber-950/40 dark:text-amber-300 dark:hover:bg-amber-950/60\"\n : \"border-emerald-200 bg-emerald-50 text-emerald-700 hover:bg-emerald-100 dark:border-emerald-800 dark:bg-emerald-950/40 dark:text-emerald-300 dark:hover:bg-emerald-950/60\",\n className,\n ]\n .filter(Boolean)\n .join(\" \")}\n aria-label={`Data mode: ${mode}. Click to switch to ${isSample ? \"live\" : \"sample\"}.`}\n >\n {isSample ? (\n <BeakerIcon className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n ) : (\n <SignalIcon className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n )}\n {isSample ? \"Sample\" : \"Live\"}\n </button>\n );\n}\n"],"names":["DataModeToggle","className","mode","toggle","useDataMode","isSample","jsxs","jsx","BeakerIcon","SignalIcon"],"mappings":";;;AAWA,SAAwBA,EAAe,EAAE,WAAAC,IAAY,MAA2B;AAC9E,QAAM,EAAE,MAAAC,GAAM,QAAAC,EAAA,IAAWC,EAAA,GACnBC,IAAWH,MAAS;AAE1B,SACE,gBAAAI;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,SAASH;AAAA,MACT,WAAW;AAAA,QACT;AAAA,QACAE,IACI,6JACA;AAAA,QACJJ;AAAA,MAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,MACX,cAAY,cAAcC,CAAI,wBAAwBG,IAAW,SAAS,QAAQ;AAAA,MAEjF,UAAA;AAAA,QAAAA,IACC,gBAAAE,EAACC,GAAA,EAAW,WAAU,eAAc,eAAY,OAAA,CAAO,IAEvD,gBAAAD,EAACE,GAAA,EAAW,WAAU,eAAc,eAAY,QAAO;AAAA,QAExDJ,IAAW,WAAW;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAG7B;"}
@@ -1,3 +1,41 @@
1
- export function listSemanticIds(): string[];
2
- export function getSemanticDataset(semanticId: any): any;
3
- export function getSemanticMetric(semanticId: any, metricId: any): any;
1
+ export type ChangeType = "positive" | "negative" | "neutral";
2
+ export type MetricColor = "primary" | "success" | "warning" | "danger";
3
+ export type ColumnType = "currency" | "percentage" | "number" | "text";
4
+ export interface SemanticMetric {
5
+ metricId: string;
6
+ title: string;
7
+ subtitle: string;
8
+ value: string;
9
+ change?: string;
10
+ changeType?: ChangeType;
11
+ color?: MetricColor;
12
+ trend?: string;
13
+ }
14
+ export interface TableColumn {
15
+ key: string;
16
+ label: string;
17
+ type?: ColumnType;
18
+ sortable?: boolean;
19
+ mono?: boolean;
20
+ }
21
+ export interface TableRow {
22
+ id: number;
23
+ [key: string]: any;
24
+ }
25
+ export interface SemanticTable {
26
+ title: string;
27
+ subtitle: string;
28
+ columns: TableColumn[];
29
+ rows: TableRow[];
30
+ }
31
+ export interface SemanticDataset {
32
+ title: string;
33
+ metrics?: SemanticMetric[];
34
+ table?: SemanticTable;
35
+ }
36
+ export interface SemanticDatasets {
37
+ [key: string]: SemanticDataset;
38
+ }
39
+ export declare function listSemanticIds(): string[];
40
+ export declare function getSemanticDataset(semanticId: string): SemanticDataset | null;
41
+ export declare function getSemanticMetric(semanticId: string, metricId: string): SemanticMetric | null;
@@ -2,6 +2,38 @@
2
2
  * Pure data utilities for filtering, sorting, and searching.
3
3
  * Stateless — combine with usePageFilters hook for state management.
4
4
  */
5
+ export type SortDirection = "asc" | "desc";
6
+ export interface DateRange {
7
+ start?: Date | string;
8
+ end?: Date | string;
9
+ }
10
+ export type FilterType = "search" | "select" | "toggle" | "dateRange";
11
+ export interface BaseFilterDefinition {
12
+ id: string;
13
+ type: FilterType;
14
+ defaultValue?: any;
15
+ }
16
+ export interface SearchFilterDefinition extends BaseFilterDefinition {
17
+ type: "search";
18
+ keys: string[];
19
+ }
20
+ export interface SelectFilterDefinition extends BaseFilterDefinition {
21
+ type: "select";
22
+ key: string;
23
+ }
24
+ export interface ToggleFilterDefinition extends BaseFilterDefinition {
25
+ type: "toggle";
26
+ key: string;
27
+ matchValue?: any;
28
+ }
29
+ export interface DateRangeFilterDefinition extends BaseFilterDefinition {
30
+ type: "dateRange";
31
+ key: string;
32
+ }
33
+ export type FilterDefinition = SearchFilterDefinition | SelectFilterDefinition | ToggleFilterDefinition | DateRangeFilterDefinition;
34
+ export interface FilterValues {
35
+ [key: string]: any;
36
+ }
5
37
  /**
6
38
  * Text search across multiple keys.
7
39
  * @param {Array} data
@@ -9,7 +41,7 @@
9
41
  * @param {string[]} keys — object keys to search within
10
42
  * @returns {Array} filtered data
11
43
  */
12
- export function filterBySearch(data: any[], query: string, keys?: string[]): any[];
44
+ export declare function filterBySearch<T>(data: T[], query: string, keys?: string[]): T[];
13
45
  /**
14
46
  * Filter rows where key matches a specific value.
15
47
  * Pass "all" or "" to skip filtering.
@@ -18,7 +50,7 @@ export function filterBySearch(data: any[], query: string, keys?: string[]): any
18
50
  * @param {*} value — value to match (exact, case-insensitive for strings)
19
51
  * @returns {Array}
20
52
  */
21
- export function filterByValue(data: any[], key: string, value: any): any[];
53
+ export declare function filterByValue<T>(data: T[], key: string, value: any): T[];
22
54
  /**
23
55
  * Filter rows where a boolean condition is met.
24
56
  * When toggle is off, returns all data (no filtering).
@@ -28,7 +60,7 @@ export function filterByValue(data: any[], key: string, value: any): any[];
28
60
  * @param {*} matchValue — value that key should equal when active (default: truthy check)
29
61
  * @returns {Array}
30
62
  */
31
- export function filterByToggle(data: any[], key: string, isActive: boolean, matchValue: any): any[];
63
+ export declare function filterByToggle<T>(data: T[], key: string, isActive: boolean, matchValue?: any): T[];
32
64
  /**
33
65
  * Filter rows where a date field falls within a range.
34
66
  * @param {Array} data
@@ -36,10 +68,7 @@ export function filterByToggle(data: any[], key: string, isActive: boolean, matc
36
68
  * @param {{ start?: Date|string, end?: Date|string }} range
37
69
  * @returns {Array}
38
70
  */
39
- export function filterByDateRange(data: any[], key: string, range: {
40
- start?: Date | string;
41
- end?: Date | string;
42
- }): any[];
71
+ export declare function filterByDateRange<T>(data: T[], key: string, range: DateRange | null): T[];
43
72
  /**
44
73
  * Sort data by a key.
45
74
  * @param {Array} data
@@ -47,7 +76,7 @@ export function filterByDateRange(data: any[], key: string, range: {
47
76
  * @param {"asc"|"desc"} direction
48
77
  * @returns {Array} new sorted array
49
78
  */
50
- export function sortByKey(data: any[], key: string, direction?: "asc" | "desc"): any[];
79
+ export declare function sortByKey<T>(data: T[], key: string, direction?: SortDirection): T[];
51
80
  /**
52
81
  * Apply a set of filter definitions to data.
53
82
  * Each filter in `filters` has { id, type, key/keys } and `values` holds the current state.
@@ -57,4 +86,4 @@ export function sortByKey(data: any[], key: string, direction?: "asc" | "desc"):
57
86
  * @param {Object} values — current filter values keyed by filter id
58
87
  * @returns {Array} filtered data
59
88
  */
60
- export function applyFilters(data: any[], filters?: any[], values?: Object): any[];
89
+ export declare function applyFilters<T>(data: T[], filters?: FilterDefinition[], values?: FilterValues): T[];