@codeswayam/ui 1.1.1 → 1.3.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 (73) hide show
  1. package/README.md +727 -173
  2. package/dist/components/base/badge.d.ts +1 -1
  3. package/dist/components/base/button.d.ts +2 -2
  4. package/dist/components/base/button.d.ts.map +1 -1
  5. package/dist/components/base/button.js +2 -2
  6. package/dist/components/brand/BrandFooterSection.d.ts +8 -0
  7. package/dist/components/brand/BrandFooterSection.d.ts.map +1 -0
  8. package/dist/components/brand/BrandFooterSection.js +97 -0
  9. package/dist/components/brand/BrandNav.d.ts +17 -0
  10. package/dist/components/brand/BrandNav.d.ts.map +1 -0
  11. package/dist/components/brand/BrandNav.js +64 -0
  12. package/dist/components/data/DataTable.d.ts +18 -0
  13. package/dist/components/data/DataTable.d.ts.map +1 -0
  14. package/dist/components/data/DataTable.js +36 -0
  15. package/dist/components/data/EmptyState.d.ts +23 -0
  16. package/dist/components/data/EmptyState.d.ts.map +1 -0
  17. package/dist/components/data/EmptyState.js +9 -0
  18. package/dist/components/data/TableToolbar.d.ts +17 -0
  19. package/dist/components/data/TableToolbar.d.ts.map +1 -0
  20. package/dist/components/data/TableToolbar.js +21 -0
  21. package/dist/components/display/CopyButton.d.ts +14 -0
  22. package/dist/components/display/CopyButton.d.ts.map +1 -0
  23. package/dist/components/display/CopyButton.js +37 -0
  24. package/dist/components/display/PageHeader.d.ts +11 -0
  25. package/dist/components/display/PageHeader.d.ts.map +1 -0
  26. package/dist/components/display/PageHeader.js +5 -0
  27. package/dist/components/display/StatCard.d.ts +23 -0
  28. package/dist/components/display/StatCard.d.ts.map +1 -0
  29. package/dist/components/display/StatCard.js +6 -0
  30. package/dist/components/feedback/ConfirmDialog.d.ts +18 -0
  31. package/dist/components/feedback/ConfirmDialog.d.ts.map +1 -0
  32. package/dist/components/feedback/ConfirmDialog.js +10 -0
  33. package/dist/components/feedback/ErrorState.d.ts +10 -0
  34. package/dist/components/feedback/ErrorState.d.ts.map +1 -0
  35. package/dist/components/feedback/ErrorState.js +7 -0
  36. package/dist/components/feedback/Skeleton.d.ts +26 -0
  37. package/dist/components/feedback/Skeleton.d.ts.map +1 -0
  38. package/dist/components/feedback/Skeleton.js +31 -0
  39. package/dist/components/neural/AICreditBadge.d.ts +9 -0
  40. package/dist/components/neural/AICreditBadge.d.ts.map +1 -0
  41. package/dist/components/neural/AICreditBadge.js +31 -0
  42. package/dist/components/neural/AIImageGeneratorModal.d.ts +9 -0
  43. package/dist/components/neural/AIImageGeneratorModal.d.ts.map +1 -0
  44. package/dist/components/neural/AIImageGeneratorModal.js +66 -0
  45. package/dist/components/neural/AIPromptPlayground.d.ts +10 -0
  46. package/dist/components/neural/AIPromptPlayground.d.ts.map +1 -0
  47. package/dist/components/neural/AIPromptPlayground.js +66 -0
  48. package/dist/components/neural/KnowledgeBasePicker.d.ts +18 -0
  49. package/dist/components/neural/KnowledgeBasePicker.d.ts.map +1 -0
  50. package/dist/components/neural/KnowledgeBasePicker.js +42 -0
  51. package/dist/components/neural/WorkflowPicker.d.ts +18 -0
  52. package/dist/components/neural/WorkflowPicker.d.ts.map +1 -0
  53. package/dist/components/neural/WorkflowPicker.js +46 -0
  54. package/dist/components/neural/index.d.ts +11 -0
  55. package/dist/components/neural/index.d.ts.map +1 -0
  56. package/dist/components/neural/index.js +5 -0
  57. package/dist/components/saas/NotificationBell.d.ts +12 -0
  58. package/dist/components/saas/NotificationBell.d.ts.map +1 -0
  59. package/dist/components/saas/NotificationBell.js +52 -0
  60. package/dist/components/saas/status-badge.d.ts +15 -8
  61. package/dist/components/saas/status-badge.d.ts.map +1 -1
  62. package/dist/components/saas/status-badge.js +46 -25
  63. package/dist/index.d.ts +15 -0
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +34 -4
  66. package/dist/tsconfig.tsbuildinfo +1 -1
  67. package/dist/utils/useNotifications.d.ts +24 -0
  68. package/dist/utils/useNotifications.d.ts.map +1 -0
  69. package/dist/utils/useNotifications.js +71 -0
  70. package/dist/utils/useWebPush.d.ts +14 -0
  71. package/dist/utils/useWebPush.d.ts.map +1 -0
  72. package/dist/utils/useWebPush.js +110 -0
  73. package/package.json +4 -3
@@ -0,0 +1,26 @@
1
+ import * as React from 'react';
2
+ interface SkeletonProps {
3
+ className?: string;
4
+ style?: React.CSSProperties;
5
+ }
6
+ /** Generic skeleton block — use className to set size */
7
+ export declare function Skeleton({ className }: SkeletonProps): import("react/jsx-runtime").JSX.Element;
8
+ /** Skeleton shaped like a single line of text */
9
+ export declare function SkeletonText({ className }: SkeletonProps): import("react/jsx-runtime").JSX.Element;
10
+ /** Skeleton shaped like a circular avatar */
11
+ export declare function SkeletonAvatar({ className }: SkeletonProps): import("react/jsx-runtime").JSX.Element;
12
+ /** Skeleton for a StatCard */
13
+ export declare function SkeletonStatCard({ className }: SkeletonProps): import("react/jsx-runtime").JSX.Element;
14
+ /** Skeleton for a table row */
15
+ export declare function SkeletonTableRow({ cols }: {
16
+ cols?: number;
17
+ }): import("react/jsx-runtime").JSX.Element;
18
+ /** Full skeleton table (header + N rows) */
19
+ export declare function SkeletonTable({ rows, cols }: {
20
+ rows?: number;
21
+ cols?: number;
22
+ }): import("react/jsx-runtime").JSX.Element;
23
+ /** Skeleton for a user list item (avatar + two lines) */
24
+ export declare function SkeletonUserRow({ className }: SkeletonProps): import("react/jsx-runtime").JSX.Element;
25
+ export {};
26
+ //# sourceMappingURL=Skeleton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Skeleton.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/Skeleton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,UAAU,aAAa;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAED,yDAAyD;AACzD,wBAAgB,QAAQ,CAAC,EAAE,SAAS,EAAE,EAAE,aAAa,2CAOpD;AAED,iDAAiD;AACjD,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,EAAE,aAAa,2CAExD;AAED,6CAA6C;AAC7C,wBAAgB,cAAc,CAAC,EAAE,SAAS,EAAE,EAAE,aAAa,2CAE1D;AAID,8BAA8B;AAC9B,wBAAgB,gBAAgB,CAAC,EAAE,SAAS,EAAE,EAAE,aAAa,2CAQ5D;AAED,+BAA+B;AAC/B,wBAAgB,gBAAgB,CAAC,EAAE,IAAQ,EAAE,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,2CAU/D;AAED,4CAA4C;AAC5C,wBAAgB,aAAa,CAAC,EAAE,IAAQ,EAAE,IAAQ,EAAE,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,2CAiBrF;AAED,yDAAyD;AACzD,wBAAgB,eAAe,CAAC,EAAE,SAAS,EAAE,EAAE,aAAa,2CAU3D"}
@@ -0,0 +1,31 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from '../../utils/cn';
3
+ /** Generic skeleton block — use className to set size */
4
+ export function Skeleton({ className }) {
5
+ return (_jsx("div", { className: cn('animate-pulse rounded-md bg-muted', className), "aria-hidden": true }));
6
+ }
7
+ /** Skeleton shaped like a single line of text */
8
+ export function SkeletonText({ className }) {
9
+ return _jsx(Skeleton, { className: cn('h-4 w-3/4', className) });
10
+ }
11
+ /** Skeleton shaped like a circular avatar */
12
+ export function SkeletonAvatar({ className }) {
13
+ return _jsx(Skeleton, { className: cn('h-9 w-9 rounded-full', className) });
14
+ }
15
+ // ─── Composed skeleton cards ──────────────────────────────────────────────────
16
+ /** Skeleton for a StatCard */
17
+ export function SkeletonStatCard({ className }) {
18
+ return (_jsxs("div", { className: cn('rounded-2xl border border-border bg-card p-5 space-y-3', className), children: [_jsx(Skeleton, { className: "h-3.5 w-20" }), _jsx(Skeleton, { className: "h-8 w-28" }), _jsx(Skeleton, { className: "h-3 w-16" })] }));
19
+ }
20
+ /** Skeleton for a table row */
21
+ export function SkeletonTableRow({ cols = 4 }) {
22
+ return (_jsx("tr", { className: "border-b border-border/50", children: Array.from({ length: cols }).map((_, i) => (_jsx("td", { className: "px-4 py-3", children: _jsx(Skeleton, { className: "h-4", style: { width: `${60 + Math.random() * 30}%` } }) }, i))) }));
23
+ }
24
+ /** Full skeleton table (header + N rows) */
25
+ export function SkeletonTable({ rows = 5, cols = 4 }) {
26
+ return (_jsxs("div", { className: "rounded-xl border border-border overflow-hidden", children: [_jsx("div", { className: "px-4 py-3 border-b border-border bg-muted/40 flex gap-4", children: Array.from({ length: cols }).map((_, i) => (_jsx(Skeleton, { className: "h-3.5 w-20" }, i))) }), _jsx("table", { className: "w-full", children: _jsx("tbody", { children: Array.from({ length: rows }).map((_, i) => (_jsx(SkeletonTableRow, { cols: cols }, i))) }) })] }));
27
+ }
28
+ /** Skeleton for a user list item (avatar + two lines) */
29
+ export function SkeletonUserRow({ className }) {
30
+ return (_jsxs("div", { className: cn('flex items-center gap-3 p-3', className), children: [_jsx(SkeletonAvatar, {}), _jsxs("div", { className: "flex-1 space-y-2", children: [_jsx(Skeleton, { className: "h-3.5 w-32" }), _jsx(Skeleton, { className: "h-3 w-48" })] })] }));
31
+ }
@@ -0,0 +1,9 @@
1
+ export interface AICreditBadgeProps {
2
+ apiUrl?: string;
3
+ costPreview?: number;
4
+ showAddButton?: boolean;
5
+ onUpgradeClick?: () => void;
6
+ className?: string;
7
+ }
8
+ export declare function AICreditBadge({ apiUrl, costPreview, showAddButton, onUpgradeClick, className, }: AICreditBadgeProps): import("react/jsx-runtime").JSX.Element;
9
+ //# sourceMappingURL=AICreditBadge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AICreditBadge.d.ts","sourceRoot":"","sources":["../../../src/components/neural/AICreditBadge.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,aAAa,CAAC,EAC5B,MAAgC,EAChC,WAAW,EACX,aAAqB,EACrB,cAAc,EACd,SAAc,GACf,EAAE,kBAAkB,2CAuDpB"}
@@ -0,0 +1,31 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useState } from "react";
4
+ import { Zap, Loader2, Plus } from "lucide-react";
5
+ export function AICreditBadge({ apiUrl = "http://localhost:3000", costPreview, showAddButton = false, onUpgradeClick, className = "", }) {
6
+ const [balance, setBalance] = useState(null);
7
+ const [loading, setLoading] = useState(true);
8
+ useEffect(() => {
9
+ let mounted = true;
10
+ async function fetchCredits() {
11
+ try {
12
+ const res = await fetch(`${apiUrl}/credits/balance`, { credentials: "include" });
13
+ if (res.ok) {
14
+ const data = await res.json();
15
+ if (mounted)
16
+ setBalance(data.balance ?? data.credits ?? 0);
17
+ }
18
+ }
19
+ catch (err) {
20
+ console.error("[AICreditBadge] Failed to fetch credits:", err);
21
+ }
22
+ finally {
23
+ if (mounted)
24
+ setLoading(false);
25
+ }
26
+ }
27
+ fetchCredits();
28
+ return () => { mounted = false; };
29
+ }, [apiUrl]);
30
+ return (_jsxs("div", { className: `inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full bg-amber-500/10 border border-amber-500/20 text-amber-300 text-xs font-medium ${className}`, children: [_jsx(Zap, { className: "w-3.5 h-3.5 text-amber-400 fill-amber-400/30" }), loading ? (_jsx(Loader2, { className: "w-3 h-3 animate-spin text-amber-400" })) : (_jsxs("span", { children: [balance !== null ? balance.toLocaleString() : "0", " ", _jsx("span", { className: "text-[10px] text-amber-400/80 font-normal", children: "Credits" })] })), costPreview !== undefined && costPreview > 0 && (_jsxs("span", { className: "text-[10px] text-amber-400/70 border-l border-amber-500/30 pl-1.5", children: ["-", costPreview] })), showAddButton && (_jsx("button", { type: "button", onClick: onUpgradeClick, className: "ml-1 p-0.5 rounded-full hover:bg-amber-500/20 text-amber-300 transition", title: "Get more credits", children: _jsx(Plus, { className: "w-3 h-3" }) }))] }));
31
+ }
@@ -0,0 +1,9 @@
1
+ export interface AIImageGeneratorModalProps {
2
+ isOpen: boolean;
3
+ onClose: () => void;
4
+ onSelectImage: (base64OrUrl: string) => void;
5
+ apiUrl?: string;
6
+ defaultAspectRatio?: "1:1" | "16:9" | "9:16" | "4:3";
7
+ }
8
+ export declare function AIImageGeneratorModal({ isOpen, onClose, onSelectImage, apiUrl, defaultAspectRatio, }: AIImageGeneratorModalProps): import("react/jsx-runtime").JSX.Element | null;
9
+ //# sourceMappingURL=AIImageGeneratorModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AIImageGeneratorModal.d.ts","sourceRoot":"","sources":["../../../src/components/neural/AIImageGeneratorModal.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,aAAa,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;CACtD;AAED,wBAAgB,qBAAqB,CAAC,EACpC,MAAM,EACN,OAAO,EACP,aAAa,EACb,MAAgC,EAChC,kBAA0B,GAC3B,EAAE,0BAA0B,kDA6N5B"}
@@ -0,0 +1,66 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { Image as ImageIcon, Sparkles, Loader2, X, Download, Check, RefreshCw } from "lucide-react";
5
+ export function AIImageGeneratorModal({ isOpen, onClose, onSelectImage, apiUrl = "http://localhost:3000", defaultAspectRatio = "1:1", }) {
6
+ const [prompt, setPrompt] = useState("");
7
+ const [negativePrompt, setNegativePrompt] = useState("");
8
+ const [aspectRatio, setAspectRatio] = useState(defaultAspectRatio);
9
+ const [loading, setLoading] = useState(false);
10
+ const [generatedImage, setGeneratedImage] = useState(null);
11
+ const [error, setError] = useState(null);
12
+ if (!isOpen)
13
+ return null;
14
+ const handleGenerate = async (e) => {
15
+ if (e)
16
+ e.preventDefault();
17
+ if (!prompt.trim() || loading)
18
+ return;
19
+ setLoading(true);
20
+ setError(null);
21
+ try {
22
+ const res = await fetch(`${apiUrl}/v1/generate-image`, {
23
+ method: "POST",
24
+ headers: { "Content-Type": "application/json" },
25
+ credentials: "include",
26
+ body: JSON.stringify({
27
+ prompt: prompt.trim(),
28
+ negativePrompt: negativePrompt.trim() || undefined,
29
+ aspectRatio,
30
+ }),
31
+ });
32
+ if (res.ok) {
33
+ const data = await res.json();
34
+ if (data.imageBase64) {
35
+ const imgSrc = `data:${data.mimeType || "image/png"};base64,${data.imageBase64}`;
36
+ setGeneratedImage(imgSrc);
37
+ }
38
+ else if (data.imageUrl) {
39
+ setGeneratedImage(data.imageUrl);
40
+ }
41
+ else {
42
+ setError("No image data returned from generation model.");
43
+ }
44
+ }
45
+ else {
46
+ const errData = await res.json().catch(() => ({}));
47
+ setError(errData.message || "Failed to generate image. Please check your credit balance.");
48
+ }
49
+ }
50
+ catch {
51
+ setError("Network error occurred during image generation.");
52
+ }
53
+ finally {
54
+ setLoading(false);
55
+ }
56
+ };
57
+ const handleUse = () => {
58
+ if (generatedImage) {
59
+ onSelectImage(generatedImage);
60
+ onClose();
61
+ }
62
+ };
63
+ return (_jsx("div", { className: "fixed inset-0 z-50 bg-black/80 flex items-center justify-center p-4 backdrop-blur-sm animate-in fade-in-0 duration-200", children: _jsxs("div", { className: "bg-neutral-900 border border-neutral-800 w-full max-w-2xl rounded-2xl shadow-2xl flex flex-col max-h-[90vh] overflow-hidden", children: [_jsxs("div", { className: "flex items-center justify-between px-6 py-4 border-b border-neutral-800 bg-neutral-900/60", children: [_jsxs("div", { className: "flex items-center gap-2.5", children: [_jsx("div", { className: "p-2 bg-primary/10 rounded-xl text-primary", children: _jsx(Sparkles, { className: "w-4 h-4" }) }), _jsxs("div", { children: [_jsx("h3", { className: "font-semibold text-neutral-100 text-sm", children: "AI Image Studio" }), _jsx("p", { className: "text-xs text-neutral-400", children: "Generate custom high-resolution images" })] })] }), _jsx("button", { type: "button", onClick: onClose, className: "p-1.5 text-neutral-400 hover:text-neutral-200 hover:bg-neutral-800 rounded-lg transition", children: _jsx(X, { className: "w-4 h-4" }) })] }), _jsxs("div", { className: "flex-1 overflow-y-auto p-6 space-y-5", children: [_jsxs("div", { children: [_jsx("label", { className: "block text-xs font-medium text-neutral-300 mb-1.5", children: "Describe what you want to generate" }), _jsx("textarea", { rows: 3, value: prompt, onChange: (e) => setPrompt(e.target.value), placeholder: "e.g. A sleek modern workspace with soft neon lighting and minimalist aesthetics...", className: "w-full px-3.5 py-2.5 text-sm bg-neutral-800/80 border border-neutral-700/70 rounded-xl text-neutral-200 placeholder-neutral-500 focus:outline-none focus:border-primary resize-none" })] }), _jsxs("div", { children: [_jsx("label", { className: "block text-xs font-medium text-neutral-300 mb-1.5", children: "Aspect Ratio" }), _jsx("div", { className: "grid grid-cols-4 gap-2", children: ["1:1", "16:9", "9:16", "4:3"].map((ratio) => (_jsxs("button", { type: "button", onClick: () => setAspectRatio(ratio), className: `py-2 px-3 text-xs rounded-xl border text-center transition font-medium ${aspectRatio === ratio
64
+ ? "bg-primary/20 border-primary text-primary"
65
+ : "bg-neutral-800/60 border-neutral-700/60 text-neutral-300 hover:bg-neutral-800"}`, children: [ratio === "1:1" && "1:1 (Square)", ratio === "16:9" && "16:9 (Landscape)", ratio === "9:16" && "9:16 (Story/Reel)", ratio === "4:3" && "4:3 (Standard)"] }, ratio))) })] }), _jsxs("div", { children: [_jsx("label", { className: "block text-xs font-medium text-neutral-400 mb-1", children: "Negative Prompt (Optional)" }), _jsx("input", { type: "text", value: negativePrompt, onChange: (e) => setNegativePrompt(e.target.value), placeholder: "e.g. blurry, low quality, distorted text, watermark", className: "w-full px-3.5 py-2 text-xs bg-neutral-800/60 border border-neutral-700/50 rounded-lg text-neutral-200 placeholder-neutral-500 focus:outline-none focus:border-primary" })] }), _jsxs("div", { className: "rounded-2xl border border-neutral-800 bg-neutral-950/50 p-4 flex flex-col items-center justify-center min-h-[220px]", children: [loading ? (_jsxs("div", { className: "flex flex-col items-center justify-center text-center py-8", children: [_jsx(Loader2, { className: "w-8 h-8 text-primary animate-spin mb-3" }), _jsx("p", { className: "text-sm font-medium text-neutral-300", children: "Generating your image..." }), _jsx("p", { className: "text-xs text-neutral-500 mt-1", children: "Rendering details, please wait" })] })) : generatedImage ? (_jsxs("div", { className: "flex flex-col items-center gap-4 w-full", children: [_jsx("div", { className: "relative max-h-72 rounded-xl overflow-hidden border border-neutral-800 shadow-lg", children: _jsx("img", { src: generatedImage, alt: "AI Generated", className: "max-h-72 object-contain rounded-xl" }) }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("button", { type: "button", onClick: handleGenerate, className: "px-3 py-1.5 text-xs bg-neutral-800 hover:bg-neutral-700 text-neutral-200 rounded-lg transition flex items-center gap-1.5", children: [_jsx(RefreshCw, { className: "w-3.5 h-3.5" }), " Regenerate"] }), _jsxs("a", { href: generatedImage, download: "ai-image.png", className: "px-3 py-1.5 text-xs bg-neutral-800 hover:bg-neutral-700 text-neutral-200 rounded-lg transition flex items-center gap-1.5", children: [_jsx(Download, { className: "w-3.5 h-3.5" }), " Download"] })] })] })) : (_jsxs("div", { className: "flex flex-col items-center justify-center text-center text-neutral-500 py-6", children: [_jsx(ImageIcon, { className: "w-10 h-10 mb-2 opacity-30 text-neutral-400" }), _jsx("p", { className: "text-xs text-neutral-400 font-medium", children: "No image generated yet" }), _jsx("p", { className: "text-[11px] text-neutral-500 max-w-xs mt-0.5", children: "Enter a prompt above and click generate to create a new image." })] })), error && (_jsx("div", { className: "mt-3 p-2.5 bg-red-500/10 border border-red-500/20 rounded-xl text-xs text-red-400 text-center w-full", children: error }))] })] }), _jsxs("div", { className: "px-6 py-4 border-t border-neutral-800 bg-neutral-900/60 flex items-center justify-between", children: [_jsx("span", { className: "text-xs text-neutral-400", children: "\u26A1 Estimated cost: 10 credits" }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { type: "button", onClick: onClose, className: "px-4 py-2 text-xs text-neutral-400 hover:text-neutral-200 font-medium transition", children: "Cancel" }), generatedImage ? (_jsxs("button", { type: "button", onClick: handleUse, className: "px-4 py-2 bg-primary text-primary-foreground text-xs font-semibold rounded-xl hover:bg-primary/90 transition flex items-center gap-1.5 shadow-lg shadow-primary/20", children: [_jsx(Check, { className: "w-3.5 h-3.5" }), " Use This Image"] })) : (_jsxs("button", { type: "button", disabled: !prompt.trim() || loading, onClick: handleGenerate, className: "px-5 py-2 bg-primary text-primary-foreground text-xs font-semibold rounded-xl hover:bg-primary/90 disabled:opacity-50 transition flex items-center gap-1.5 shadow-lg shadow-primary/20", children: [loading ? _jsx(Loader2, { className: "w-3.5 h-3.5 animate-spin" }) : _jsx(Sparkles, { className: "w-3.5 h-3.5" }), "Generate Image"] }))] })] })] }) }));
66
+ }
@@ -0,0 +1,10 @@
1
+ export interface AIPromptPlaygroundProps {
2
+ systemPrompt: string;
3
+ knowledgeBaseId?: number | null;
4
+ appName?: string;
5
+ isOpen: boolean;
6
+ onClose: () => void;
7
+ apiUrl?: string;
8
+ }
9
+ export declare function AIPromptPlayground({ systemPrompt, knowledgeBaseId, appName, isOpen, onClose, apiUrl, }: AIPromptPlaygroundProps): import("react/jsx-runtime").JSX.Element | null;
10
+ //# sourceMappingURL=AIPromptPlayground.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AIPromptPlayground.d.ts","sourceRoot":"","sources":["../../../src/components/neural/AIPromptPlayground.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAQD,wBAAgB,kBAAkB,CAAC,EACjC,YAAY,EACZ,eAAe,EACf,OAAsB,EACtB,MAAM,EACN,OAAO,EACP,MAAgC,GACjC,EAAE,uBAAuB,kDA0KzB"}
@@ -0,0 +1,66 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { Send, Bot, User, Sparkles, Loader2, X, RefreshCw } from "lucide-react";
5
+ export function AIPromptPlayground({ systemPrompt, knowledgeBaseId, appName = "playground", isOpen, onClose, apiUrl = "http://localhost:3000", }) {
6
+ const [messages, setMessages] = useState([]);
7
+ const [input, setInput] = useState("");
8
+ const [loading, setLoading] = useState(false);
9
+ const [sessionId] = useState(() => `play_${Math.random().toString(36).substring(2, 9)}`);
10
+ if (!isOpen)
11
+ return null;
12
+ const handleSend = async (e) => {
13
+ if (e)
14
+ e.preventDefault();
15
+ if (!input.trim() || loading)
16
+ return;
17
+ const userText = input.trim();
18
+ setInput("");
19
+ setMessages((prev) => [...prev, { role: "user", content: userText }]);
20
+ setLoading(true);
21
+ try {
22
+ const res = await fetch(`${apiUrl}/agents/entity/chat`, {
23
+ method: "POST",
24
+ headers: { "Content-Type": "application/json" },
25
+ credentials: "include",
26
+ body: JSON.stringify({
27
+ appName,
28
+ entityId: `test_${sessionId}`,
29
+ systemPrompt,
30
+ knowledgeBaseId: knowledgeBaseId ?? undefined,
31
+ message: userText,
32
+ sessionId,
33
+ }),
34
+ });
35
+ if (res.ok) {
36
+ const data = await res.json();
37
+ setMessages((prev) => [
38
+ ...prev,
39
+ {
40
+ role: "assistant",
41
+ content: data.text || "No response received",
42
+ latencyMs: data.latencyMs,
43
+ },
44
+ ]);
45
+ }
46
+ else {
47
+ setMessages((prev) => [
48
+ ...prev,
49
+ { role: "assistant", content: "Error: Failed to generate response from AI agent." },
50
+ ]);
51
+ }
52
+ }
53
+ catch {
54
+ setMessages((prev) => [
55
+ ...prev,
56
+ { role: "assistant", content: "Error: Network request failed." },
57
+ ]);
58
+ }
59
+ finally {
60
+ setLoading(false);
61
+ }
62
+ };
63
+ return (_jsx("div", { className: "fixed inset-0 z-50 bg-black/80 flex items-center justify-center p-4 backdrop-blur-sm animate-in fade-in-0 duration-200", children: _jsxs("div", { className: "bg-neutral-900 border border-neutral-800 w-full max-w-xl rounded-2xl shadow-2xl flex flex-col h-[600px] overflow-hidden", children: [_jsxs("div", { className: "flex items-center justify-between px-5 py-4 border-b border-neutral-800 bg-neutral-900/60", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "p-2 bg-primary/10 rounded-lg text-primary", children: _jsx(Sparkles, { className: "w-4 h-4" }) }), _jsxs("div", { children: [_jsx("h3", { className: "font-semibold text-neutral-100 text-sm", children: "AI Agent Live Playground" }), _jsx("p", { className: "text-xs text-neutral-400", children: knowledgeBaseId ? `Testing with KB #${knowledgeBaseId}` : "Testing prompt without KB" })] })] }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { type: "button", onClick: () => setMessages([]), title: "Clear chat", className: "p-1.5 text-neutral-400 hover:text-neutral-200 hover:bg-neutral-800 rounded-lg transition", children: _jsx(RefreshCw, { className: "w-4 h-4" }) }), _jsx("button", { type: "button", onClick: onClose, className: "p-1.5 text-neutral-400 hover:text-neutral-200 hover:bg-neutral-800 rounded-lg transition", children: _jsx(X, { className: "w-4 h-4" }) })] })] }), _jsxs("div", { className: "flex-1 overflow-y-auto p-4 space-y-4 text-sm", children: [messages.length === 0 && (_jsxs("div", { className: "flex flex-col items-center justify-center h-full text-center text-neutral-500 py-12", children: [_jsx(Bot, { className: "w-10 h-10 mb-2 opacity-40 text-primary" }), _jsx("p", { className: "font-medium text-neutral-400 text-sm", children: "Ready to test your prompt" }), _jsx("p", { className: "text-xs text-neutral-500 max-w-xs mt-1", children: "Type a message below to see how your AI agent will respond before publishing." })] })), messages.map((m, idx) => (_jsxs("div", { className: `flex gap-3 ${m.role === "user" ? "justify-end" : "justify-start"}`, children: [m.role === "assistant" && (_jsx("div", { className: "w-7 h-7 rounded-full bg-primary/20 text-primary flex items-center justify-center shrink-0 mt-0.5", children: _jsx(Bot, { className: "w-4 h-4" }) })), _jsxs("div", { className: `max-w-[80%] rounded-2xl px-4 py-2.5 text-sm ${m.role === "user"
64
+ ? "bg-primary text-primary-foreground font-medium rounded-br-none"
65
+ : "bg-neutral-800/90 text-neutral-200 border border-neutral-700/60 rounded-bl-none"}`, children: [_jsx("div", { className: "whitespace-pre-wrap", children: m.content }), m.latencyMs !== undefined && (_jsxs("div", { className: "text-[10px] text-neutral-400 mt-1 text-right", children: [m.latencyMs, "ms"] }))] }), m.role === "user" && (_jsx("div", { className: "w-7 h-7 rounded-full bg-neutral-800 text-neutral-300 flex items-center justify-center shrink-0 mt-0.5", children: _jsx(User, { className: "w-4 h-4" }) }))] }, idx))), loading && (_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "w-7 h-7 rounded-full bg-primary/20 text-primary flex items-center justify-center shrink-0", children: _jsx(Loader2, { className: "w-4 h-4 animate-spin" }) }), _jsx("div", { className: "bg-neutral-800/70 border border-neutral-700/40 rounded-2xl rounded-bl-none px-4 py-2 text-xs text-neutral-400", children: "Thinking..." })] }))] }), _jsxs("form", { onSubmit: handleSend, className: "p-3 border-t border-neutral-800 bg-neutral-900/60 flex gap-2", children: [_jsx("input", { type: "text", placeholder: "Send a test message...", value: input, onChange: (e) => setInput(e.target.value), disabled: loading, className: "flex-1 px-3.5 py-2 text-sm bg-neutral-800/80 border border-neutral-700/70 rounded-xl text-neutral-200 placeholder-neutral-500 focus:outline-none focus:border-primary" }), _jsx("button", { type: "submit", disabled: !input.trim() || loading, className: "px-4 py-2 bg-primary text-primary-foreground rounded-xl text-sm font-medium hover:bg-primary/90 disabled:opacity-50 transition flex items-center gap-1.5", children: _jsx(Send, { className: "w-3.5 h-3.5" }) })] })] }) }));
66
+ }
@@ -0,0 +1,18 @@
1
+ export interface KnowledgeBaseItem {
2
+ id: number;
3
+ name: string;
4
+ description?: string;
5
+ docCount: number;
6
+ status: "active" | "indexing" | "error";
7
+ createdAt?: string;
8
+ }
9
+ export interface KnowledgeBasePickerProps {
10
+ value?: number | null;
11
+ onChange: (kbId: number | null) => void;
12
+ apiUrl?: string;
13
+ neuralWebUrl?: string;
14
+ className?: string;
15
+ disabled?: boolean;
16
+ }
17
+ export declare function KnowledgeBasePicker({ value, onChange, apiUrl, neuralWebUrl, className, disabled, }: KnowledgeBasePickerProps): import("react/jsx-runtime").JSX.Element;
18
+ //# sourceMappingURL=KnowledgeBasePicker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"KnowledgeBasePicker.d.ts","sourceRoot":"","sources":["../../../src/components/neural/KnowledgeBasePicker.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,mBAAmB,CAAC,EAClC,KAAK,EACL,QAAQ,EACR,MAAgC,EAChC,YAAsC,EACtC,SAAc,EACd,QAAgB,GACjB,EAAE,wBAAwB,2CAyI1B"}
@@ -0,0 +1,42 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useState } from "react";
4
+ import { Database, Search, ExternalLink, Check, Loader2, Sparkles } from "lucide-react";
5
+ export function KnowledgeBasePicker({ value, onChange, apiUrl = "http://localhost:3000", neuralWebUrl = "http://localhost:3007", className = "", disabled = false, }) {
6
+ const [items, setItems] = useState([]);
7
+ const [loading, setLoading] = useState(true);
8
+ const [search, setSearch] = useState("");
9
+ const [isOpen, setIsOpen] = useState(false);
10
+ useEffect(() => {
11
+ let mounted = true;
12
+ async function fetchKBs() {
13
+ try {
14
+ const res = await fetch(`${apiUrl}/knowledge-base`, { credentials: "include" });
15
+ if (res.ok) {
16
+ const data = await res.json();
17
+ if (mounted)
18
+ setItems(Array.isArray(data) ? data : data.items || []);
19
+ }
20
+ }
21
+ catch (err) {
22
+ console.error("[KnowledgeBasePicker] Failed to load KBs:", err);
23
+ }
24
+ finally {
25
+ if (mounted)
26
+ setLoading(false);
27
+ }
28
+ }
29
+ fetchKBs();
30
+ return () => { mounted = false; };
31
+ }, [apiUrl]);
32
+ const filtered = items.filter((kb) => kb.name.toLowerCase().includes(search.toLowerCase()) ||
33
+ (kb.description && kb.description.toLowerCase().includes(search.toLowerCase())));
34
+ const selectedItem = items.find((k) => k.id === value);
35
+ return (_jsxs("div", { className: `relative ${className}`, children: [_jsxs("button", { type: "button", disabled: disabled, onClick: () => setIsOpen((prev) => !prev), className: "w-full flex items-center justify-between px-3 py-2 text-sm bg-neutral-900 border border-neutral-800 rounded-lg text-neutral-200 hover:border-neutral-700 focus:outline-none focus:ring-1 focus:ring-primary disabled:opacity-50 transition", children: [_jsxs("div", { className: "flex items-center gap-2 truncate", children: [_jsx(Database, { className: "w-4 h-4 text-primary shrink-0" }), loading ? (_jsxs("span", { className: "text-neutral-500 flex items-center gap-1", children: [_jsx(Loader2, { className: "w-3 h-3 animate-spin" }), " Loading knowledge bases..."] })) : selectedItem ? (_jsxs("span", { className: "truncate font-medium text-neutral-100", children: [selectedItem.name, " ", _jsxs("span", { className: "text-xs text-neutral-400 font-normal", children: ["(", selectedItem.docCount, " docs)"] })] })) : (_jsx("span", { className: "text-neutral-500", children: "None (General Knowledge)" }))] }), _jsx("span", { className: "text-xs text-neutral-500 ml-2", children: "\u25BC" })] }), isOpen && (_jsxs("div", { className: "absolute z-50 mt-1 w-full bg-neutral-900 border border-neutral-800 rounded-xl shadow-2xl p-2 text-sm max-h-72 flex flex-col", children: [_jsxs("div", { className: "relative mb-2", children: [_jsx(Search, { className: "w-3.5 h-3.5 text-neutral-400 absolute left-2.5 top-2.5" }), _jsx("input", { type: "text", placeholder: "Search knowledge bases...", value: search, onChange: (e) => setSearch(e.target.value), className: "w-full pl-8 pr-2 py-1.5 text-xs bg-neutral-800/80 border border-neutral-700/60 rounded-md text-neutral-200 placeholder-neutral-500 focus:outline-none focus:border-primary" })] }), _jsxs("div", { className: "overflow-y-auto flex-1 space-y-1", children: [_jsxs("button", { type: "button", onClick: () => {
36
+ onChange(null);
37
+ setIsOpen(false);
38
+ }, className: `w-full flex items-center justify-between px-2.5 py-1.5 rounded-lg text-left text-xs transition ${!value ? "bg-primary/20 text-primary font-medium" : "text-neutral-300 hover:bg-neutral-800/60"}`, children: [_jsx("span", { children: "None (No RAG attached)" }), !value && _jsx(Check, { className: "w-3.5 h-3.5" })] }), filtered.map((kb) => (_jsxs("button", { type: "button", onClick: () => {
39
+ onChange(kb.id);
40
+ setIsOpen(false);
41
+ }, className: `w-full flex items-center justify-between px-2.5 py-2 rounded-lg text-left text-xs transition ${value === kb.id ? "bg-primary/20 text-primary font-medium" : "text-neutral-200 hover:bg-neutral-800/60"}`, children: [_jsxs("div", { className: "truncate pr-2", children: [_jsx("div", { className: "font-medium truncate", children: kb.name }), kb.description && (_jsx("div", { className: "text-[10px] text-neutral-400 truncate", children: kb.description }))] }), _jsxs("div", { className: "flex items-center gap-1.5 shrink-0", children: [_jsxs("span", { className: "text-[10px] bg-neutral-800 text-neutral-400 px-1.5 py-0.5 rounded", children: [kb.docCount, " docs"] }), value === kb.id && _jsx(Check, { className: "w-3.5 h-3.5 text-primary" })] })] }, kb.id))), filtered.length === 0 && !loading && (_jsx("div", { className: "text-center py-4 text-xs text-neutral-500", children: "No knowledge bases found" }))] }), _jsx("div", { className: "pt-2 mt-1 border-t border-neutral-800/80", children: _jsxs("a", { href: `${neuralWebUrl}/knowledge-base`, target: "_blank", rel: "noopener noreferrer", className: "flex items-center justify-center gap-1.5 text-xs text-primary hover:underline font-medium py-1", children: [_jsx(Sparkles, { className: "w-3 h-3" }), " Create / Manage in Neural Hub", _jsx(ExternalLink, { className: "w-2.5 h-2.5" })] }) })] }))] }));
42
+ }
@@ -0,0 +1,18 @@
1
+ export interface WorkflowItem {
2
+ id: number;
3
+ name: string;
4
+ slug?: string;
5
+ description?: string;
6
+ status: string;
7
+ nodeCount?: number;
8
+ }
9
+ export interface WorkflowPickerProps {
10
+ value?: string | number | null;
11
+ onChange: (workflowIdentifier: string | number | null) => void;
12
+ apiUrl?: string;
13
+ neuralWebUrl?: string;
14
+ className?: string;
15
+ disabled?: boolean;
16
+ }
17
+ export declare function WorkflowPicker({ value, onChange, apiUrl, neuralWebUrl, className, disabled, }: WorkflowPickerProps): import("react/jsx-runtime").JSX.Element;
18
+ //# sourceMappingURL=WorkflowPicker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkflowPicker.d.ts","sourceRoot":"","sources":["../../../src/components/neural/WorkflowPicker.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,EAAE,CAAC,kBAAkB,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,QAAQ,EACR,MAAgC,EAChC,YAAsC,EACtC,SAAc,EACd,QAAgB,GACjB,EAAE,mBAAmB,2CAoJrB"}
@@ -0,0 +1,46 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useState } from "react";
4
+ import { GitBranch, Search, Check, Loader2, ExternalLink, Play } from "lucide-react";
5
+ export function WorkflowPicker({ value, onChange, apiUrl = "http://localhost:3000", neuralWebUrl = "http://localhost:3007", className = "", disabled = false, }) {
6
+ const [workflows, setWorkflows] = useState([]);
7
+ const [loading, setLoading] = useState(true);
8
+ const [search, setSearch] = useState("");
9
+ const [isOpen, setIsOpen] = useState(false);
10
+ useEffect(() => {
11
+ let mounted = true;
12
+ async function fetchWorkflows() {
13
+ try {
14
+ const res = await fetch(`${apiUrl}/workflows`, { credentials: "include" });
15
+ if (res.ok) {
16
+ const data = await res.json();
17
+ if (mounted)
18
+ setWorkflows(Array.isArray(data) ? data : data.items || []);
19
+ }
20
+ }
21
+ catch (err) {
22
+ console.error("[WorkflowPicker] Failed to load workflows:", err);
23
+ }
24
+ finally {
25
+ if (mounted)
26
+ setLoading(false);
27
+ }
28
+ }
29
+ fetchWorkflows();
30
+ return () => { mounted = false; };
31
+ }, [apiUrl]);
32
+ const filtered = workflows.filter((w) => w.name.toLowerCase().includes(search.toLowerCase()) ||
33
+ (w.slug && w.slug.toLowerCase().includes(search.toLowerCase())) ||
34
+ (w.description && w.description.toLowerCase().includes(search.toLowerCase())));
35
+ const selectedItem = workflows.find((w) => w.id === value || w.slug === value);
36
+ return (_jsxs("div", { className: `relative ${className}`, children: [_jsxs("button", { type: "button", disabled: disabled, onClick: () => setIsOpen((prev) => !prev), className: "w-full flex items-center justify-between px-3 py-2 text-sm bg-neutral-900 border border-neutral-800 rounded-lg text-neutral-200 hover:border-neutral-700 focus:outline-none focus:ring-1 focus:ring-primary disabled:opacity-50 transition", children: [_jsxs("div", { className: "flex items-center gap-2 truncate", children: [_jsx(GitBranch, { className: "w-4 h-4 text-emerald-400 shrink-0" }), loading ? (_jsxs("span", { className: "text-neutral-500 flex items-center gap-1", children: [_jsx(Loader2, { className: "w-3 h-3 animate-spin" }), " Loading workflows..."] })) : selectedItem ? (_jsxs("span", { className: "truncate font-medium text-neutral-100", children: [selectedItem.name, " ", selectedItem.slug && (_jsxs("span", { className: "text-xs text-neutral-400 font-mono font-normal", children: ["(", selectedItem.slug, ")"] }))] })) : (_jsx("span", { className: "text-neutral-500", children: "None (No workflow attached)" }))] }), _jsx("span", { className: "text-xs text-neutral-500 ml-2", children: "\u25BC" })] }), isOpen && (_jsxs("div", { className: "absolute z-50 mt-1 w-full bg-neutral-900 border border-neutral-800 rounded-xl shadow-2xl p-2 text-sm max-h-72 flex flex-col", children: [_jsxs("div", { className: "relative mb-2", children: [_jsx(Search, { className: "w-3.5 h-3.5 text-neutral-400 absolute left-2.5 top-2.5" }), _jsx("input", { type: "text", placeholder: "Search workflows by name or slug...", value: search, onChange: (e) => setSearch(e.target.value), className: "w-full pl-8 pr-2 py-1.5 text-xs bg-neutral-800/80 border border-neutral-700/60 rounded-md text-neutral-200 placeholder-neutral-500 focus:outline-none focus:border-primary" })] }), _jsxs("div", { className: "overflow-y-auto flex-1 space-y-1", children: [_jsxs("button", { type: "button", onClick: () => {
37
+ onChange(null);
38
+ setIsOpen(false);
39
+ }, className: `w-full flex items-center justify-between px-2.5 py-1.5 rounded-lg text-left text-xs transition ${!value ? "bg-primary/20 text-primary font-medium" : "text-neutral-300 hover:bg-neutral-800/60"}`, children: [_jsx("span", { children: "None (Do not run workflow)" }), !value && _jsx(Check, { className: "w-3.5 h-3.5" })] }), filtered.map((wf) => {
40
+ const isSelected = value === wf.id || value === wf.slug;
41
+ return (_jsxs("button", { type: "button", onClick: () => {
42
+ onChange(wf.slug || wf.id);
43
+ setIsOpen(false);
44
+ }, className: `w-full flex items-center justify-between px-2.5 py-2 rounded-lg text-left text-xs transition ${isSelected ? "bg-primary/20 text-primary font-medium" : "text-neutral-200 hover:bg-neutral-800/60"}`, children: [_jsxs("div", { className: "truncate pr-2", children: [_jsxs("div", { className: "font-medium truncate flex items-center gap-1.5", children: [_jsx(Play, { className: "w-2.5 h-2.5 text-emerald-400" }), wf.name] }), wf.description && (_jsx("div", { className: "text-[10px] text-neutral-400 truncate", children: wf.description }))] }), _jsxs("div", { className: "flex items-center gap-1.5 shrink-0", children: [wf.nodeCount !== undefined && (_jsxs("span", { className: "text-[10px] bg-neutral-800 text-neutral-400 px-1.5 py-0.5 rounded", children: [wf.nodeCount, " steps"] })), isSelected && _jsx(Check, { className: "w-3.5 h-3.5 text-primary" })] })] }, wf.id));
45
+ }), filtered.length === 0 && !loading && (_jsx("div", { className: "text-center py-4 text-xs text-neutral-500", children: "No workflows found" }))] }), _jsx("div", { className: "pt-2 mt-1 border-t border-neutral-800/80", children: _jsxs("a", { href: `${neuralWebUrl}/workflows`, target: "_blank", rel: "noopener noreferrer", className: "flex items-center justify-center gap-1.5 text-xs text-primary hover:underline font-medium py-1", children: [_jsx(GitBranch, { className: "w-3 h-3" }), " Build New Workflow in Neural Hub", _jsx(ExternalLink, { className: "w-2.5 h-2.5" })] }) })] }))] }));
46
+ }
@@ -0,0 +1,11 @@
1
+ export { KnowledgeBasePicker } from "./KnowledgeBasePicker";
2
+ export type { KnowledgeBasePickerProps, KnowledgeBaseItem } from "./KnowledgeBasePicker";
3
+ export { AIPromptPlayground } from "./AIPromptPlayground";
4
+ export type { AIPromptPlaygroundProps } from "./AIPromptPlayground";
5
+ export { WorkflowPicker } from "./WorkflowPicker";
6
+ export type { WorkflowPickerProps, WorkflowItem } from "./WorkflowPicker";
7
+ export { AIImageGeneratorModal } from "./AIImageGeneratorModal";
8
+ export type { AIImageGeneratorModalProps } from "./AIImageGeneratorModal";
9
+ export { AICreditBadge } from "./AICreditBadge";
10
+ export type { AICreditBadgeProps } from "./AICreditBadge";
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/neural/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAEzF,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,YAAY,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAEpE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,YAAY,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAE1E,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { KnowledgeBasePicker } from "./KnowledgeBasePicker";
2
+ export { AIPromptPlayground } from "./AIPromptPlayground";
3
+ export { WorkflowPicker } from "./WorkflowPicker";
4
+ export { AIImageGeneratorModal } from "./AIImageGeneratorModal";
5
+ export { AICreditBadge } from "./AICreditBadge";
@@ -0,0 +1,12 @@
1
+ export interface NotificationBellProps {
2
+ apiUrl?: string;
3
+ onNavigate?: (url: string) => void;
4
+ onOpenSettings?: () => void;
5
+ className?: string;
6
+ }
7
+ /**
8
+ * Universal Notification Bell Component for SaaS applications.
9
+ * Renders an unread badge counter and a notification feed dropdown.
10
+ */
11
+ export declare function NotificationBell({ apiUrl, onNavigate, onOpenSettings, className, }: NotificationBellProps): import("react/jsx-runtime").JSX.Element;
12
+ //# sourceMappingURL=NotificationBell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NotificationBell.d.ts","sourceRoot":"","sources":["../../../src/components/saas/NotificationBell.tsx"],"names":[],"mappings":"AAqBA,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA6BD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,UAAU,EACV,cAAc,EACd,SAAS,GACV,EAAE,qBAAqB,2CAoIvB"}
@@ -0,0 +1,52 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Bell, CheckCheck, CreditCard, ShieldAlert, Sparkles, Tag, Settings, Info, } from "lucide-react";
4
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger, } from "../base/dropdown-menu";
5
+ import { useNotifications } from "../../utils/useNotifications";
6
+ import { cn } from "../../utils/cn";
7
+ function getCategoryIcon(category) {
8
+ switch (category) {
9
+ case "billing":
10
+ return _jsx(CreditCard, { size: 14, className: "text-violet-600" });
11
+ case "security":
12
+ return _jsx(ShieldAlert, { size: 14, className: "text-red-600" });
13
+ case "updates":
14
+ return _jsx(Sparkles, { size: 14, className: "text-blue-600" });
15
+ case "marketing":
16
+ return _jsx(Tag, { size: 14, className: "text-amber-600" });
17
+ default:
18
+ return _jsx(Info, { size: 14, className: "text-gray-600" });
19
+ }
20
+ }
21
+ function formatTimeAgo(dateStr) {
22
+ const diff = Date.now() - new Date(dateStr).getTime();
23
+ const mins = Math.floor(diff / (1000 * 60));
24
+ if (mins < 1)
25
+ return "Just now";
26
+ if (mins < 60)
27
+ return `${mins}m ago`;
28
+ const hours = Math.floor(mins / 60);
29
+ if (hours < 24)
30
+ return `${hours}h ago`;
31
+ const days = Math.floor(hours / 24);
32
+ if (days < 7)
33
+ return `${days}d ago`;
34
+ return new Date(dateStr).toLocaleDateString();
35
+ }
36
+ /**
37
+ * Universal Notification Bell Component for SaaS applications.
38
+ * Renders an unread badge counter and a notification feed dropdown.
39
+ */
40
+ export function NotificationBell({ apiUrl, onNavigate, onOpenSettings, className, }) {
41
+ const { notifications, unreadCount, markAsRead, markAllAsRead } = useNotifications({ apiUrl });
42
+ return (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs("button", { "aria-label": "Open notifications", className: cn("relative p-2 rounded-xl text-gray-600 hover:text-gray-900 hover:bg-gray-100 transition-colors cursor-pointer outline-none", className), children: [_jsx(Bell, { size: 18 }), unreadCount > 0 && (_jsx("span", { className: "absolute top-1 right-1 flex h-4 min-w-[16px] px-1 items-center justify-center rounded-full bg-violet-600 text-[10px] font-bold text-white shadow-sm ring-2 ring-background animate-in zoom-in-50", children: unreadCount > 99 ? "99+" : unreadCount }))] }) }), _jsxs(DropdownMenuContent, { align: "end", className: "w-80 sm:w-96 max-h-[480px] p-0 rounded-2xl shadow-2xl border border-gray-100 overflow-hidden z-50 bg-white", children: [_jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-b border-gray-100 bg-gray-50/70", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-sm font-bold text-gray-900", children: "Notifications" }), unreadCount > 0 && (_jsxs("span", { className: "bg-violet-100 text-violet-700 text-[10px] font-bold px-1.5 py-0.5 rounded-full", children: [unreadCount, " new"] }))] }), _jsxs("div", { className: "flex items-center gap-1", children: [unreadCount > 0 && (_jsxs("button", { type: "button", onClick: markAllAsRead, title: "Mark all as read", className: "flex items-center gap-1 text-[11px] font-semibold text-violet-700 hover:text-violet-900 px-2 py-1 rounded-md hover:bg-violet-50 transition-colors cursor-pointer", children: [_jsx(CheckCheck, { size: 13 }), "Mark all read"] })), onOpenSettings && (_jsx("button", { type: "button", onClick: onOpenSettings, title: "Notification Settings", className: "p-1 rounded-md text-gray-400 hover:text-gray-600 hover:bg-gray-100 transition-colors cursor-pointer", children: _jsx(Settings, { size: 14 }) }))] })] }), _jsx("div", { className: "overflow-y-auto max-h-[360px] divide-y divide-gray-50", children: notifications.length === 0 ? (_jsxs("div", { className: "py-12 text-center text-gray-400 space-y-2", children: [_jsx(Bell, { size: 32, strokeWidth: 1.5, className: "mx-auto text-gray-300" }), _jsx("p", { className: "text-xs font-medium text-gray-500", children: "No notifications yet" }), _jsx("p", { className: "text-[11px] text-gray-400", children: "You're completely caught up! \u2728" })] })) : (notifications.map((item) => {
43
+ const isUnread = !item.isRead;
44
+ return (_jsxs("div", { onClick: () => {
45
+ if (isUnread)
46
+ markAsRead(item.id);
47
+ if (item.actionUrl && onNavigate) {
48
+ onNavigate(item.actionUrl);
49
+ }
50
+ }, className: cn("flex items-start gap-3 p-3.5 transition-colors cursor-pointer text-left", isUnread ? "bg-violet-50/40 hover:bg-violet-50/70" : "bg-white hover:bg-gray-50/80"), children: [_jsx("div", { className: "mt-0.5 shrink-0 p-1.5 rounded-lg bg-gray-100 border border-gray-200/60", children: getCategoryIcon(item.category) }), _jsxs("div", { className: "flex-1 min-w-0 space-y-0.5", children: [_jsxs("div", { className: "flex items-center justify-between gap-1", children: [_jsx("p", { className: cn("text-xs font-semibold truncate", isUnread ? "text-gray-900 font-bold" : "text-gray-700"), children: item.title }), _jsx("span", { className: "text-[10px] text-gray-400 shrink-0", children: formatTimeAgo(item.createdAt) })] }), _jsx("p", { className: "text-[11px] text-gray-600 line-clamp-2 leading-relaxed", children: item.message })] }), isUnread && (_jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-violet-600 shrink-0 mt-2" }))] }, item.id));
51
+ })) }), onOpenSettings && (_jsx("div", { className: "p-2 border-t border-gray-100 bg-gray-50/50 text-center", children: _jsx("button", { type: "button", onClick: onOpenSettings, className: "text-[11px] font-semibold text-gray-500 hover:text-violet-700 transition-colors cursor-pointer", children: "Configure Notification Preferences \u2192" }) }))] })] }));
52
+ }
@@ -1,10 +1,17 @@
1
- export type SubscriptionStatus = 'active' | 'past_due' | 'canceled' | 'pending_cancellation';
2
- export interface StatusBadgeProps {
3
- status: SubscriptionStatus | string;
1
+ type StatusType = 'todo' | 'in-progress' | 'in_progress' | 'done' | 'cancelled' | 'approved' | 'pending' | 'rejected' | 'submitted' | 'suspended' | 'active' | 'inactive' | 'past_due' | 'draft' | 'published';
2
+ type PriorityType = 'low' | 'medium' | 'high' | 'urgent';
3
+ type RoleType = 'admin' | 'manager' | 'employee' | 'ceo' | 'intern' | 'superadmin' | 'owner';
4
+ export declare function StatusBadge({ status, className }: {
5
+ status: StatusType;
4
6
  className?: string;
5
- }
6
- /**
7
- * Smart Status Badge for Subscription management.
8
- */
9
- export declare function StatusBadge({ status, className }: StatusBadgeProps): import("react/jsx-runtime").JSX.Element;
7
+ }): import("react/jsx-runtime").JSX.Element;
8
+ export declare function PriorityBadge({ priority, className }: {
9
+ priority: PriorityType;
10
+ className?: string;
11
+ }): import("react/jsx-runtime").JSX.Element;
12
+ export declare function RoleBadge({ role, className }: {
13
+ role: RoleType;
14
+ className?: string;
15
+ }): import("react/jsx-runtime").JSX.Element;
16
+ export type { StatusType, PriorityType, RoleType };
10
17
  //# sourceMappingURL=status-badge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"status-badge.d.ts","sourceRoot":"","sources":["../../../src/components/saas/status-badge.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU,GAAG,sBAAsB,CAAC;AAE7F,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,gBAAgB,2CAiClE"}
1
+ {"version":3,"file":"status-badge.d.ts","sourceRoot":"","sources":["../../../src/components/saas/status-badge.tsx"],"names":[],"mappings":"AAIA,KAAK,UAAU,GACX,MAAM,GAAG,aAAa,GAAG,aAAa,GAAG,MAAM,GAAG,WAAW,GAC7D,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,WAAW,GAC/D,QAAQ,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,GAAG,WAAW,CAAC;AAE/D,KAAK,YAAY,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEzD,KAAK,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,KAAK,GAAG,QAAQ,GAAG,YAAY,GAAG,OAAO,CAAC;AA4C7F,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,2CAG5F;AAED,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;IAAE,QAAQ,EAAE,YAAY,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,2CAGpG;AAED,wBAAgB,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,2CAGpF;AAGD,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC"}