@lastbrain/ai-ui-react 1.0.67 → 1.0.69

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 (60) hide show
  1. package/dist/components/AiChipLabel.d.ts +8 -3
  2. package/dist/components/AiChipLabel.d.ts.map +1 -1
  3. package/dist/components/AiChipLabel.js +21 -70
  4. package/dist/components/AiContextButton.d.ts +5 -1
  5. package/dist/components/AiContextButton.d.ts.map +1 -1
  6. package/dist/components/AiContextButton.js +67 -291
  7. package/dist/components/AiImageButton.d.ts +5 -1
  8. package/dist/components/AiImageButton.d.ts.map +1 -1
  9. package/dist/components/AiImageButton.js +6 -142
  10. package/dist/components/AiInput.d.ts +5 -3
  11. package/dist/components/AiInput.d.ts.map +1 -1
  12. package/dist/components/AiInput.js +13 -25
  13. package/dist/components/AiPromptPanel.d.ts.map +1 -1
  14. package/dist/components/AiPromptPanel.js +58 -212
  15. package/dist/components/AiSelect.d.ts +5 -3
  16. package/dist/components/AiSelect.d.ts.map +1 -1
  17. package/dist/components/AiSelect.js +21 -30
  18. package/dist/components/AiStatusButton.d.ts +4 -1
  19. package/dist/components/AiStatusButton.d.ts.map +1 -1
  20. package/dist/components/AiStatusButton.js +198 -626
  21. package/dist/components/AiTextarea.d.ts +4 -2
  22. package/dist/components/AiTextarea.d.ts.map +1 -1
  23. package/dist/components/AiTextarea.js +14 -26
  24. package/dist/components/LBApiKeySelector.d.ts.map +1 -1
  25. package/dist/components/LBApiKeySelector.js +5 -166
  26. package/dist/components/LBConnectButton.d.ts +4 -7
  27. package/dist/components/LBConnectButton.d.ts.map +1 -1
  28. package/dist/components/LBConnectButton.js +17 -86
  29. package/dist/components/LBSigninModal.d.ts +1 -1
  30. package/dist/components/LBSigninModal.d.ts.map +1 -1
  31. package/dist/components/LBSigninModal.js +42 -320
  32. package/dist/examples/AiUiPremiumShowcase.d.ts +2 -0
  33. package/dist/examples/AiUiPremiumShowcase.d.ts.map +1 -0
  34. package/dist/examples/AiUiPremiumShowcase.js +15 -0
  35. package/dist/index.d.ts +2 -0
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +2 -0
  38. package/dist/styles/inline.d.ts +1 -0
  39. package/dist/styles/inline.d.ts.map +1 -1
  40. package/dist/styles/inline.js +25 -129
  41. package/dist/styles.css +1268 -369
  42. package/dist/types.d.ts +3 -0
  43. package/dist/types.d.ts.map +1 -1
  44. package/package.json +2 -2
  45. package/src/components/AiChipLabel.tsx +64 -101
  46. package/src/components/AiContextButton.tsx +138 -430
  47. package/src/components/AiImageButton.tsx +29 -190
  48. package/src/components/AiInput.tsx +49 -74
  49. package/src/components/AiPromptPanel.tsx +71 -254
  50. package/src/components/AiSelect.tsx +61 -69
  51. package/src/components/AiStatusButton.tsx +477 -1219
  52. package/src/components/AiTextarea.tsx +49 -64
  53. package/src/components/LBApiKeySelector.tsx +86 -274
  54. package/src/components/LBConnectButton.tsx +46 -334
  55. package/src/components/LBSigninModal.tsx +140 -481
  56. package/src/examples/AiUiPremiumShowcase.tsx +91 -0
  57. package/src/index.ts +3 -0
  58. package/src/styles/inline.ts +27 -148
  59. package/src/styles.css +1268 -369
  60. package/src/types.ts +3 -0
@@ -0,0 +1,91 @@
1
+ "use client";
2
+
3
+ import { Sparkles } from "lucide-react";
4
+ import { AiProvider } from "../context/AiProvider";
5
+ import { AiInput } from "../components/AiInput";
6
+ import { AiTextarea } from "../components/AiTextarea";
7
+ import { AiChipLabel } from "../components/AiChipLabel";
8
+
9
+ function ShowcasePanel({
10
+ title,
11
+ theme,
12
+ }: {
13
+ title: string;
14
+ theme: "light" | "dark";
15
+ }) {
16
+ return (
17
+ <section
18
+ data-theme={theme}
19
+ className={`rounded-2xl border p-6 ${
20
+ theme === "dark"
21
+ ? "bg-slate-950 border-slate-800 text-slate-100"
22
+ : "bg-white border-slate-200 text-slate-900"
23
+ }`}
24
+ >
25
+ <div className="mb-4 flex items-center justify-between">
26
+ <h3 className="text-base font-semibold">{title}</h3>
27
+ <span className="text-xs opacity-70">{theme}</span>
28
+ </div>
29
+
30
+ <AiProvider baseUrl="/api/ai" apiKeyId="demo-key">
31
+ <div className="space-y-4">
32
+ <AiInput
33
+ value=""
34
+ onChange={() => {}}
35
+ placeholder="Ask anything..."
36
+ data-testid={`showcase-input-${theme}`}
37
+ />
38
+
39
+ <AiTextarea
40
+ value=""
41
+ onChange={() => {}}
42
+ placeholder="Generate a concise product description..."
43
+ data-testid={`showcase-textarea-${theme}`}
44
+ />
45
+
46
+ <div className="flex flex-wrap gap-2">
47
+ <AiChipLabel>Default</AiChipLabel>
48
+ <AiChipLabel variant="selected">Selected</AiChipLabel>
49
+ <AiChipLabel variant="success">Success</AiChipLabel>
50
+ <AiChipLabel variant="danger">Danger</AiChipLabel>
51
+ </div>
52
+
53
+ <div className="ai-surface p-3">
54
+ <div className="flex items-center justify-between">
55
+ <span className="text-sm font-medium">Static control states</span>
56
+ <Sparkles size={14} className="text-[var(--ai-primary)]" />
57
+ </div>
58
+ <div className="mt-3 space-y-2">
59
+ <input className="ai-control ai-control-input" placeholder="Default state" />
60
+ <input
61
+ className="ai-control ai-control-input ai-control--focused"
62
+ placeholder="Focused style"
63
+ readOnly
64
+ />
65
+ <input
66
+ className="ai-control ai-control-input ai-control--error"
67
+ aria-invalid="true"
68
+ placeholder="Error style"
69
+ readOnly
70
+ />
71
+ <input
72
+ className="ai-control ai-control-input ai-control--disabled"
73
+ placeholder="Disabled style"
74
+ disabled
75
+ />
76
+ </div>
77
+ </div>
78
+ </div>
79
+ </AiProvider>
80
+ </section>
81
+ );
82
+ }
83
+
84
+ export function AiUiPremiumShowcase() {
85
+ return (
86
+ <div className="grid gap-6 md:grid-cols-2">
87
+ <ShowcasePanel title="Premium UI Showcase" theme="dark" />
88
+ <ShowcasePanel title="Premium UI Showcase" theme="light" />
89
+ </div>
90
+ );
91
+ }
package/src/index.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import "./styles.css";
2
+
1
3
  // Types
2
4
  export * from "./types";
3
5
 
@@ -45,3 +47,4 @@ export * from "./examples/AiPromptPanelAdvanced";
45
47
  export * from "./examples/AiChipInputExample";
46
48
  export * from "./examples/AiImageButtonExample";
47
49
  export * from "./examples/AiContextButtonExample";
50
+ export * from "./examples/AiUiPremiumShowcase";
@@ -3,6 +3,8 @@
3
3
  * Theme: Purple/Violet primary color with light/dark mode support
4
4
  */
5
5
 
6
+ import type React from "react";
7
+
6
8
  // Theme colors
7
9
  const colors = {
8
10
  // Purple/Violet theme
@@ -18,114 +20,23 @@ const colors = {
18
20
  warningLight: "#fbbf24",
19
21
  danger: "#ef4444",
20
22
  dangerLight: "#f87171",
21
-
22
- // Neutral colors - Light mode
23
- light: {
24
- bg: "#ffffff",
25
- bgSecondary: "#f9fafb",
26
- bgTertiary: "#f3f4f6",
27
- border: "#e2e8f0",
28
- borderLight: "#f1f5f9",
29
- text: "#111827",
30
- textSecondary: "#6b7280",
31
- textTertiary: "#9ca3af",
32
- shadow: "rgba(0, 0, 0, 0.1)",
33
- shadowMd:
34
- "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)",
35
- shadowLg:
36
- "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)",
37
- shadowXl:
38
- "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1)",
39
- },
40
-
41
- // Neutral colors - Dark mode
42
- dark: {
43
- bg: "#1f2937",
44
- bgSecondary: "#111827",
45
- bgTertiary: "#0f172a",
46
- border: "#374151",
47
- borderLight: "#4b5563",
48
- text: "#f9fafb",
49
- textSecondary: "#d1d5db",
50
- textTertiary: "#9ca3af",
51
- shadow: "rgba(0, 0, 0, 0.3)",
52
- shadowMd:
53
- "0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -2px rgba(0, 0, 0, 0.3)",
54
- shadowLg:
55
- "0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -4px rgba(0, 0, 0, 0.3)",
56
- shadowXl:
57
- "0 20px 25px -5px rgba(0, 0, 0, 0.3), 0 8px 10px -6px rgba(0, 0, 0, 0.3)",
58
- },
59
- };
60
-
61
- // Use light mode by default (can be made dynamic later)
62
- const getIsDark = () => {
63
- if (typeof document !== "undefined") {
64
- const root = document.documentElement;
65
- if (root.classList.contains("dark")) {
66
- return true;
67
- }
68
- if (root.classList.contains("light")) {
69
- return false;
70
- }
71
- }
72
-
73
- return (
74
- typeof window !== "undefined" &&
75
- window.matchMedia?.("(prefers-color-scheme: dark)").matches
76
- );
77
23
  };
78
24
 
79
25
  const themeVars = {
80
26
  bg: "var(--ai-bg)",
81
- bgSecondary: "var(--ai-bg-secondary)",
82
- bgTertiary: "var(--ai-bg-tertiary)",
27
+ bgSecondary: "var(--ai-bg2)",
28
+ bgTertiary: "var(--ai-bg3)",
83
29
  border: "var(--ai-border)",
84
- borderLight: "var(--ai-border-light)",
85
- text: "var(--ai-text)",
86
- textSecondary: "var(--ai-text-secondary)",
87
- textTertiary: "var(--ai-text-tertiary)",
88
- shadow: "var(--ai-shadow)",
89
- shadowMd: "var(--ai-shadow-md)",
30
+ borderLight: "color-mix(in srgb, var(--ai-border) 70%, transparent)",
31
+ text: "var(--ai-foreground)",
32
+ textSecondary: "var(--ai-secondary)",
33
+ textTertiary: "var(--ai-tertiary)",
34
+ shadow: "var(--ai-shadow-sm)",
35
+ shadowMd: "var(--ai-shadow-sm)",
90
36
  shadowLg: "var(--ai-shadow-lg)",
91
37
  shadowXl: "var(--ai-shadow-xl)",
92
38
  } as const;
93
39
 
94
- const applyThemeVariables = () => {
95
- if (typeof document === "undefined") {
96
- return;
97
- }
98
-
99
- const nextTheme = getIsDark() ? colors.dark : colors.light;
100
- const root = document.documentElement;
101
-
102
- root.style.setProperty("--ai-bg", nextTheme.bg);
103
- root.style.setProperty("--ai-bg-secondary", nextTheme.bgSecondary);
104
- root.style.setProperty("--ai-bg-tertiary", nextTheme.bgTertiary);
105
- root.style.setProperty("--ai-border", nextTheme.border);
106
- root.style.setProperty("--ai-border-light", nextTheme.borderLight);
107
- root.style.setProperty("--ai-text", nextTheme.text);
108
- root.style.setProperty("--ai-text-secondary", nextTheme.textSecondary);
109
- root.style.setProperty("--ai-text-tertiary", nextTheme.textTertiary);
110
- root.style.setProperty("--ai-shadow", nextTheme.shadow);
111
- root.style.setProperty("--ai-shadow-md", nextTheme.shadowMd);
112
- root.style.setProperty("--ai-shadow-lg", nextTheme.shadowLg);
113
- root.style.setProperty("--ai-shadow-xl", nextTheme.shadowXl);
114
- };
115
-
116
- if (typeof window !== "undefined") {
117
- applyThemeVariables();
118
-
119
- const media = window.matchMedia?.("(prefers-color-scheme: dark)");
120
- media?.addEventListener?.("change", applyThemeVariables);
121
-
122
- const observer = new MutationObserver(() => applyThemeVariables());
123
- observer.observe(document.documentElement, {
124
- attributes: true,
125
- attributeFilter: ["class"],
126
- });
127
- }
128
-
129
40
  export const aiStyles = {
130
41
  // Input field
131
42
  input: {
@@ -134,7 +45,7 @@ export const aiStyles = {
134
45
  fontSize: "14px",
135
46
  lineHeight: "1.5",
136
47
  color: themeVars.text,
137
- background: themeVars.bg,
48
+ background: "var(--ai-glass-strong)",
138
49
  border: `1px solid ${themeVars.border}`,
139
50
  borderColor: themeVars.border,
140
51
  borderRadius: "8px",
@@ -192,7 +103,7 @@ export const aiStyles = {
192
103
  fontSize: "14px",
193
104
  lineHeight: "1.5",
194
105
  color: themeVars.text,
195
- background: themeVars.bg,
106
+ background: "var(--ai-glass-strong)",
196
107
  border: `1px solid ${themeVars.border}`,
197
108
  borderColor: themeVars.border,
198
109
  borderRadius: "8px",
@@ -277,7 +188,7 @@ export const aiStyles = {
277
188
  fontSize: "14px",
278
189
  lineHeight: "1.5",
279
190
  color: themeVars.text,
280
- background: themeVars.bg,
191
+ background: "var(--ai-glass-strong)",
281
192
  borderWidth: "1px",
282
193
  borderStyle: "solid",
283
194
  borderColor: themeVars.border,
@@ -311,7 +222,7 @@ export const aiStyles = {
311
222
  height: "40px",
312
223
  border: `1px solid ${themeVars.border}`,
313
224
  borderRadius: "8px",
314
- background: themeVars.bg,
225
+ background: "var(--ai-glass, rgba(255,255,255,0.7))",
315
226
  color: themeVars.text,
316
227
  cursor: "pointer" as const,
317
228
  transition: "all 0.2s",
@@ -319,7 +230,7 @@ export const aiStyles = {
319
230
  } as React.CSSProperties,
320
231
 
321
232
  statusButtonHover: {
322
- background: themeVars.bgSecondary,
233
+ background: "var(--ai-glass-strong, rgba(255,255,255,0.82))",
323
234
  boxShadow: themeVars.shadowLg,
324
235
  transform: "scale(1.05)",
325
236
  } as React.CSSProperties,
@@ -336,7 +247,7 @@ export const aiStyles = {
336
247
  minWidth: "320px",
337
248
  maxWidth: "400px",
338
249
  padding: "16px",
339
- background: themeVars.bg,
250
+ background: "var(--ai-bg2)",
340
251
  border: `1px solid ${themeVars.border}`,
341
252
  borderRadius: "12px",
342
253
  boxShadow: themeVars.shadowXl,
@@ -428,13 +339,13 @@ export const aiStyles = {
428
339
  transition: "all 0.2s",
429
340
  fontSize: "11px",
430
341
  fontWeight: 500,
431
- background: `${colors.primary}10`,
432
- border: `1px solid ${colors.primary}30`,
342
+ background: "color-mix(in srgb, var(--ai-primary) 10%, transparent)",
343
+ border: "1px solid color-mix(in srgb, var(--ai-primary) 30%, transparent)",
433
344
  } as React.CSSProperties,
434
345
 
435
346
  tooltipLinkHover: {
436
- background: `${colors.primary}20`,
437
- borderColor: colors.primary,
347
+ background: "color-mix(in srgb, var(--ai-primary) 20%, transparent)",
348
+ borderColor: "var(--ai-primary)",
438
349
  } as React.CSSProperties,
439
350
 
440
351
  // Chip/Label
@@ -446,9 +357,9 @@ export const aiStyles = {
446
357
  fontSize: "12px",
447
358
  fontWeight: 500,
448
359
  borderRadius: "6px",
449
- background: `${colors.primary}10`,
450
- color: colors.primary,
451
- border: `1px solid ${colors.primary}30`,
360
+ background: "color-mix(in srgb, var(--ai-primary) 10%, transparent)",
361
+ color: "var(--ai-primary)",
362
+ border: "1px solid color-mix(in srgb, var(--ai-primary) 30%, transparent)",
452
363
  } as React.CSSProperties,
453
364
 
454
365
  // Modal (basic styles)
@@ -458,7 +369,7 @@ export const aiStyles = {
458
369
  left: 0,
459
370
  right: 0,
460
371
  bottom: 0,
461
- zIndex: 9999,
372
+ zIndex: 2147483645,
462
373
  display: "flex" as const,
463
374
  alignItems: "center" as const,
464
375
  justifyContent: "center" as const,
@@ -472,7 +383,7 @@ export const aiStyles = {
472
383
  left: 0,
473
384
  right: 0,
474
385
  bottom: 0,
475
- background: "rgba(0, 0, 0, 0.5)",
386
+ background: "var(--ai-overlay, rgba(0, 0, 0, 0.5))",
476
387
  backdropFilter: "blur(4px)",
477
388
  WebkitBackdropFilter: "blur(4px)",
478
389
  } as React.CSSProperties,
@@ -483,7 +394,8 @@ export const aiStyles = {
483
394
  maxWidth: "600px",
484
395
  maxHeight: "90vh",
485
396
  overflow: "auto" as const,
486
- background: themeVars.bg,
397
+ background: "var(--ai-bg2)",
398
+ border: "1px solid var(--ai-border)",
487
399
  borderRadius: "12px",
488
400
  boxShadow: themeVars.shadowXl,
489
401
  padding: "0",
@@ -578,39 +490,6 @@ export const aiStyles = {
578
490
  } as React.CSSProperties,
579
491
  };
580
492
 
581
- // Inject keyframes animation for spinner
582
- if (typeof document !== "undefined") {
583
- const styleSheet = document.createElement("style");
584
- styleSheet.textContent = `
585
- @keyframes ai-spin {
586
- from { transform: rotate(0deg); }
587
- to { transform: rotate(360deg); }
588
- }
589
-
590
- @keyframes ai-fadeIn {
591
- from { opacity: 0; }
592
- to { opacity: 1; }
593
- }
594
-
595
- @keyframes ai-slideUp {
596
- from {
597
- opacity: 0;
598
- transform: translateY(20px);
599
- }
600
- to {
601
- opacity: 1;
602
- transform: translateY(0);
603
- }
604
- }
605
-
606
- @keyframes pulse {
607
- 0%, 100% { opacity: 1; }
608
- 50% { opacity: 0.6; }
609
- }
610
- `;
611
- document.head.appendChild(styleSheet);
612
- }
613
-
614
493
  // Helper function to calculate tooltip position
615
494
  export function calculateTooltipPosition(
616
495
  buttonRect: DOMRect,