@lssm/module.ai-chat 0.0.0-canary-20251217062139 → 0.0.0-canary-20251217072406
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-chat.feature.js +93 -1
- package/dist/context/context-builder.js +147 -2
- package/dist/context/file-operations.js +174 -1
- package/dist/context/index.js +5 -1
- package/dist/context/workspace-context.js +123 -2
- package/dist/core/chat-service.js +211 -2
- package/dist/core/conversation-store.js +108 -1
- package/dist/core/index.js +4 -1
- package/dist/index.js +22 -1
- package/dist/libs/ai-providers/dist/factory.js +225 -1
- package/dist/libs/ai-providers/dist/index.js +4 -1
- package/dist/libs/ai-providers/dist/legacy.js +2 -1
- package/dist/libs/ai-providers/dist/models.js +299 -1
- package/dist/libs/ai-providers/dist/validation.js +60 -1
- package/dist/libs/design-system/dist/_virtual/rolldown_runtime.js +5 -1
- package/dist/libs/design-system/dist/components/atoms/Button.js +33 -1
- package/dist/libs/design-system/dist/components/atoms/Textarea.js +35 -1
- package/dist/libs/design-system/dist/lib/keyboard.js +193 -1
- package/dist/libs/design-system/dist/ui-kit-web/dist/ui/button.js +55 -1
- package/dist/libs/design-system/dist/ui-kit-web/dist/ui/textarea.js +16 -1
- package/dist/libs/design-system/dist/ui-kit-web/dist/ui-kit-core/dist/utils.js +13 -1
- package/dist/libs/ui-kit-web/dist/ui/avatar.js +25 -1
- package/dist/libs/ui-kit-web/dist/ui/badge.js +26 -1
- package/dist/libs/ui-kit-web/dist/ui/scroll-area.js +39 -1
- package/dist/libs/ui-kit-web/dist/ui/select.js +79 -1
- package/dist/libs/ui-kit-web/dist/ui/skeleton.js +14 -1
- package/dist/libs/ui-kit-web/dist/ui/tooltip.js +39 -1
- package/dist/libs/ui-kit-web/dist/ui/utils.js +10 -1
- package/dist/libs/ui-kit-web/dist/ui-kit-core/dist/utils.js +10 -1
- package/dist/presentation/components/ChatContainer.js +62 -1
- package/dist/presentation/components/ChatInput.d.ts +2 -2
- package/dist/presentation/components/ChatInput.js +149 -1
- package/dist/presentation/components/ChatMessage.d.ts +2 -2
- package/dist/presentation/components/ChatMessage.js +135 -1
- package/dist/presentation/components/CodePreview.d.ts +2 -2
- package/dist/presentation/components/CodePreview.js +126 -2
- package/dist/presentation/components/ContextIndicator.d.ts +2 -2
- package/dist/presentation/components/ContextIndicator.js +96 -1
- package/dist/presentation/components/ModelPicker.d.ts +2 -2
- package/dist/presentation/components/ModelPicker.js +197 -1
- package/dist/presentation/components/index.js +8 -1
- package/dist/presentation/hooks/index.js +4 -1
- package/dist/presentation/hooks/useChat.js +171 -1
- package/dist/presentation/hooks/useProviders.js +42 -1
- package/dist/presentation/index.js +12 -1
- package/dist/providers/chat-utilities.js +16 -1
- package/dist/providers/index.js +7 -1
- package/package.json +10 -10
|
@@ -1 +1,55 @@
|
|
|
1
|
-
import{cn
|
|
1
|
+
import { cn, init_utils } from "../ui-kit-core/dist/utils.js";
|
|
2
|
+
import * as React$1 from "react";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
import { cva } from "class-variance-authority";
|
|
5
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
6
|
+
|
|
7
|
+
//#region ../../libs/design-system/dist/ui-kit-web/dist/ui/button.js
|
|
8
|
+
init_utils();
|
|
9
|
+
const buttonVariants = cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-hidden focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", {
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
13
|
+
destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
14
|
+
outline: "border bg-background shadow-2xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
|
|
15
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
16
|
+
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
17
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
18
|
+
},
|
|
19
|
+
size: {
|
|
20
|
+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
21
|
+
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
22
|
+
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
23
|
+
icon: "size-9"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
defaultVariants: {
|
|
27
|
+
variant: "default",
|
|
28
|
+
size: "default"
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
const Button = React$1.forwardRef(({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
32
|
+
if (asChild) return /* @__PURE__ */ jsx(Slot, {
|
|
33
|
+
"data-slot": "button",
|
|
34
|
+
className: cn(buttonVariants({
|
|
35
|
+
variant,
|
|
36
|
+
size,
|
|
37
|
+
className
|
|
38
|
+
})),
|
|
39
|
+
...props
|
|
40
|
+
});
|
|
41
|
+
return /* @__PURE__ */ jsx("button", {
|
|
42
|
+
ref,
|
|
43
|
+
"data-slot": "button",
|
|
44
|
+
className: cn(buttonVariants({
|
|
45
|
+
variant,
|
|
46
|
+
size,
|
|
47
|
+
className
|
|
48
|
+
})),
|
|
49
|
+
...props
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
Button.displayName = "Button";
|
|
53
|
+
|
|
54
|
+
//#endregion
|
|
55
|
+
export { Button };
|
|
@@ -1 +1,16 @@
|
|
|
1
|
-
import{cn
|
|
1
|
+
import { cn, init_utils } from "../ui-kit-core/dist/utils.js";
|
|
2
|
+
import "react";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
|
|
5
|
+
//#region ../../libs/design-system/dist/ui-kit-web/dist/ui/textarea.js
|
|
6
|
+
init_utils();
|
|
7
|
+
function Textarea({ className, ...props }) {
|
|
8
|
+
return /* @__PURE__ */ jsx("textarea", {
|
|
9
|
+
"data-slot": "textarea",
|
|
10
|
+
className: cn("aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-2xs outline-hidden transition-[color,box-shadow] focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", className),
|
|
11
|
+
...props
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
export { Textarea };
|
|
@@ -1 +1,13 @@
|
|
|
1
|
-
import{__esmMin
|
|
1
|
+
import { __esmMin } from "../../../../_virtual/rolldown_runtime.js";
|
|
2
|
+
import { clsx } from "clsx";
|
|
3
|
+
import { twMerge } from "tailwind-merge";
|
|
4
|
+
|
|
5
|
+
//#region ../../libs/design-system/dist/ui-kit-web/dist/ui-kit-core/dist/utils.js
|
|
6
|
+
function cn(...inputs) {
|
|
7
|
+
return twMerge(clsx(inputs));
|
|
8
|
+
}
|
|
9
|
+
var init_utils = __esmMin((() => {}));
|
|
10
|
+
init_utils();
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
export { cn, init_utils };
|
|
@@ -1 +1,25 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { cn } from "./utils.js";
|
|
4
|
+
import "react";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
7
|
+
|
|
8
|
+
//#region ../../libs/ui-kit-web/dist/ui/avatar.js
|
|
9
|
+
function Avatar({ className, ...props }) {
|
|
10
|
+
return /* @__PURE__ */ jsx(AvatarPrimitive.Root, {
|
|
11
|
+
"data-slot": "avatar",
|
|
12
|
+
className: cn("relative flex size-8 shrink-0 overflow-hidden rounded-full", className),
|
|
13
|
+
...props
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
function AvatarFallback({ className, ...props }) {
|
|
17
|
+
return /* @__PURE__ */ jsx(AvatarPrimitive.Fallback, {
|
|
18
|
+
"data-slot": "avatar-fallback",
|
|
19
|
+
className: cn("bg-muted flex size-full items-center justify-center rounded-full", className),
|
|
20
|
+
...props
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
export { Avatar, AvatarFallback };
|
|
@@ -1 +1,26 @@
|
|
|
1
|
-
import{cn
|
|
1
|
+
import { cn } from "../ui-kit-core/dist/utils.js";
|
|
2
|
+
import "react";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
import { cva } from "class-variance-authority";
|
|
5
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
6
|
+
|
|
7
|
+
//#region ../../libs/ui-kit-web/dist/ui/badge.js
|
|
8
|
+
const badgeVariants = cva("inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", {
|
|
9
|
+
variants: { variant: {
|
|
10
|
+
default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
|
|
11
|
+
secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
|
|
12
|
+
destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
13
|
+
outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
|
|
14
|
+
} },
|
|
15
|
+
defaultVariants: { variant: "default" }
|
|
16
|
+
});
|
|
17
|
+
function Badge({ className, variant, asChild = false, ...props }) {
|
|
18
|
+
return /* @__PURE__ */ jsx(asChild ? Slot : "span", {
|
|
19
|
+
"data-slot": "badge",
|
|
20
|
+
className: cn(badgeVariants({ variant }), className),
|
|
21
|
+
...props
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
export { Badge };
|
|
@@ -1 +1,39 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { cn } from "../ui-kit-core/dist/utils.js";
|
|
4
|
+
import "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
|
|
7
|
+
|
|
8
|
+
//#region ../../libs/ui-kit-web/dist/ui/scroll-area.js
|
|
9
|
+
function ScrollArea({ className, children, ...props }) {
|
|
10
|
+
return /* @__PURE__ */ jsxs(ScrollAreaPrimitive.Root, {
|
|
11
|
+
"data-slot": "scroll-area",
|
|
12
|
+
className: cn("relative", className),
|
|
13
|
+
...props,
|
|
14
|
+
children: [
|
|
15
|
+
/* @__PURE__ */ jsx(ScrollAreaPrimitive.Viewport, {
|
|
16
|
+
"data-slot": "scroll-area-viewport",
|
|
17
|
+
className: "focus-visible:ring-ring/50 size-full rounded-[inherit] outline-hidden transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1",
|
|
18
|
+
children
|
|
19
|
+
}),
|
|
20
|
+
/* @__PURE__ */ jsx(ScrollBar, {}),
|
|
21
|
+
/* @__PURE__ */ jsx(ScrollAreaPrimitive.Corner, {})
|
|
22
|
+
]
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function ScrollBar({ className, orientation = "vertical", ...props }) {
|
|
26
|
+
return /* @__PURE__ */ jsx(ScrollAreaPrimitive.ScrollAreaScrollbar, {
|
|
27
|
+
"data-slot": "scroll-area-scrollbar",
|
|
28
|
+
orientation,
|
|
29
|
+
className: cn("flex touch-none p-px transition-colors select-none", orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent", orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent", className),
|
|
30
|
+
...props,
|
|
31
|
+
children: /* @__PURE__ */ jsx(ScrollAreaPrimitive.ScrollAreaThumb, {
|
|
32
|
+
"data-slot": "scroll-area-thumb",
|
|
33
|
+
className: "bg-border relative flex-1 rounded-full"
|
|
34
|
+
})
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
//#endregion
|
|
39
|
+
export { ScrollArea };
|
|
@@ -1 +1,79 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { cn } from "../ui-kit-core/dist/utils.js";
|
|
4
|
+
import "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
|
|
7
|
+
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
8
|
+
|
|
9
|
+
//#region ../../libs/ui-kit-web/dist/ui/select.js
|
|
10
|
+
function Select({ ...props }) {
|
|
11
|
+
return /* @__PURE__ */ jsx(SelectPrimitive.Root, {
|
|
12
|
+
"data-slot": "select",
|
|
13
|
+
...props
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
function SelectValue({ ...props }) {
|
|
17
|
+
return /* @__PURE__ */ jsx(SelectPrimitive.Value, {
|
|
18
|
+
"data-slot": "select-value",
|
|
19
|
+
...props
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function SelectTrigger({ className, size = "default", children, ...props }) {
|
|
23
|
+
return /* @__PURE__ */ jsxs(SelectPrimitive.Trigger, {
|
|
24
|
+
"data-slot": "select-trigger",
|
|
25
|
+
"data-size": size,
|
|
26
|
+
className: cn("aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive border-input focus-visible:border-ring focus-visible:ring-ring/50 data-placeholder:text-muted-foreground dark:bg-input/30 dark:hover:bg-input/50 [&_svg:not([class*='text-'])]:text-muted-foreground flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-2xs outline-hidden transition-[color,box-shadow] focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
|
|
27
|
+
...props,
|
|
28
|
+
children: [children, /* @__PURE__ */ jsx(SelectPrimitive.Icon, {
|
|
29
|
+
asChild: true,
|
|
30
|
+
children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4 opacity-50" })
|
|
31
|
+
})]
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function SelectContent({ className, children, position = "popper", ...props }) {
|
|
35
|
+
return /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(SelectPrimitive.Content, {
|
|
36
|
+
"data-slot": "select-content",
|
|
37
|
+
className: cn("bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-32 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md", position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", className),
|
|
38
|
+
position,
|
|
39
|
+
...props,
|
|
40
|
+
children: [
|
|
41
|
+
/* @__PURE__ */ jsx(SelectScrollUpButton, {}),
|
|
42
|
+
/* @__PURE__ */ jsx(SelectPrimitive.Viewport, {
|
|
43
|
+
className: cn("p-1", position === "popper" && "h-(--radix-select-trigger-height) w-full min-w-(--radix-select-trigger-width) scroll-my-1"),
|
|
44
|
+
children
|
|
45
|
+
}),
|
|
46
|
+
/* @__PURE__ */ jsx(SelectScrollDownButton, {})
|
|
47
|
+
]
|
|
48
|
+
}) });
|
|
49
|
+
}
|
|
50
|
+
function SelectItem({ className, children, ...props }) {
|
|
51
|
+
return /* @__PURE__ */ jsxs(SelectPrimitive.Item, {
|
|
52
|
+
"data-slot": "select-item",
|
|
53
|
+
className: cn("focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-xs py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2", className),
|
|
54
|
+
...props,
|
|
55
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
56
|
+
className: "absolute right-2 flex size-3.5 items-center justify-center",
|
|
57
|
+
children: /* @__PURE__ */ jsx(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" }) })
|
|
58
|
+
}), /* @__PURE__ */ jsx(SelectPrimitive.ItemText, { children })]
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function SelectScrollUpButton({ className, ...props }) {
|
|
62
|
+
return /* @__PURE__ */ jsx(SelectPrimitive.ScrollUpButton, {
|
|
63
|
+
"data-slot": "select-scroll-up-button",
|
|
64
|
+
className: cn("flex cursor-default items-center justify-center py-1", className),
|
|
65
|
+
...props,
|
|
66
|
+
children: /* @__PURE__ */ jsx(ChevronUpIcon, { className: "size-4" })
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
function SelectScrollDownButton({ className, ...props }) {
|
|
70
|
+
return /* @__PURE__ */ jsx(SelectPrimitive.ScrollDownButton, {
|
|
71
|
+
"data-slot": "select-scroll-down-button",
|
|
72
|
+
className: cn("flex cursor-default items-center justify-center py-1", className),
|
|
73
|
+
...props,
|
|
74
|
+
children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4" })
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
//#endregion
|
|
79
|
+
export { Select, SelectContent, SelectItem, SelectTrigger, SelectValue };
|
|
@@ -1 +1,14 @@
|
|
|
1
|
-
import{cn
|
|
1
|
+
import { cn } from "./utils.js";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
|
|
4
|
+
//#region ../../libs/ui-kit-web/dist/ui/skeleton.js
|
|
5
|
+
function Skeleton({ className, ...props }) {
|
|
6
|
+
return /* @__PURE__ */ jsx("div", {
|
|
7
|
+
"data-slot": "skeleton",
|
|
8
|
+
className: cn("bg-accent animate-pulse rounded-md", className),
|
|
9
|
+
...props
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
export { Skeleton };
|
|
@@ -1 +1,39 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { cn } from "../ui-kit-core/dist/utils.js";
|
|
4
|
+
import "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
7
|
+
|
|
8
|
+
//#region ../../libs/ui-kit-web/dist/ui/tooltip.js
|
|
9
|
+
function TooltipProvider({ delayDuration = 0, ...props }) {
|
|
10
|
+
return /* @__PURE__ */ jsx(TooltipPrimitive.Provider, {
|
|
11
|
+
"data-slot": "tooltip-provider",
|
|
12
|
+
delayDuration,
|
|
13
|
+
...props
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
function Tooltip({ ...props }) {
|
|
17
|
+
return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsx(TooltipPrimitive.Root, {
|
|
18
|
+
"data-slot": "tooltip",
|
|
19
|
+
...props
|
|
20
|
+
}) });
|
|
21
|
+
}
|
|
22
|
+
function TooltipTrigger({ ...props }) {
|
|
23
|
+
return /* @__PURE__ */ jsx(TooltipPrimitive.Trigger, {
|
|
24
|
+
"data-slot": "tooltip-trigger",
|
|
25
|
+
...props
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function TooltipContent({ className, sideOffset = 0, children, ...props }) {
|
|
29
|
+
return /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs(TooltipPrimitive.Content, {
|
|
30
|
+
"data-slot": "tooltip-content",
|
|
31
|
+
sideOffset,
|
|
32
|
+
className: cn("bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance", className),
|
|
33
|
+
...props,
|
|
34
|
+
children: [children, /* @__PURE__ */ jsx(TooltipPrimitive.Arrow, { className: "bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px]" })]
|
|
35
|
+
}) });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
//#endregion
|
|
39
|
+
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
|
|
@@ -1 +1,10 @@
|
|
|
1
|
-
import{clsx
|
|
1
|
+
import { clsx } from "clsx";
|
|
2
|
+
import { twMerge } from "tailwind-merge";
|
|
3
|
+
|
|
4
|
+
//#region ../../libs/ui-kit-web/dist/ui/utils.js
|
|
5
|
+
function cn(...inputs) {
|
|
6
|
+
return twMerge(clsx(inputs));
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
//#endregion
|
|
10
|
+
export { cn };
|
|
@@ -1 +1,10 @@
|
|
|
1
|
-
import{clsx
|
|
1
|
+
import { clsx } from "clsx";
|
|
2
|
+
import { twMerge } from "tailwind-merge";
|
|
3
|
+
|
|
4
|
+
//#region ../../libs/ui-kit-web/dist/ui-kit-core/dist/utils.js
|
|
5
|
+
function cn(...inputs) {
|
|
6
|
+
return twMerge(clsx(inputs));
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
//#endregion
|
|
10
|
+
export { cn };
|
|
@@ -1 +1,62 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { ScrollArea } from "../../libs/ui-kit-web/dist/ui/scroll-area.js";
|
|
4
|
+
import { cn } from "../../libs/ui-kit-web/dist/ui/utils.js";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
|
|
8
|
+
//#region src/presentation/components/ChatContainer.tsx
|
|
9
|
+
/**
|
|
10
|
+
* Container component for chat messages with scrolling
|
|
11
|
+
*/
|
|
12
|
+
function ChatContainer({ children, className, showScrollButton = true }) {
|
|
13
|
+
const scrollRef = React.useRef(null);
|
|
14
|
+
const [showScrollDown, setShowScrollDown] = React.useState(false);
|
|
15
|
+
React.useEffect(() => {
|
|
16
|
+
const container = scrollRef.current;
|
|
17
|
+
if (!container) return;
|
|
18
|
+
if (container.scrollHeight - container.scrollTop <= container.clientHeight + 100) container.scrollTop = container.scrollHeight;
|
|
19
|
+
}, [children]);
|
|
20
|
+
const handleScroll = React.useCallback((event) => {
|
|
21
|
+
const container = event.currentTarget;
|
|
22
|
+
setShowScrollDown(!(container.scrollHeight - container.scrollTop <= container.clientHeight + 100));
|
|
23
|
+
}, []);
|
|
24
|
+
const scrollToBottom = React.useCallback(() => {
|
|
25
|
+
const container = scrollRef.current;
|
|
26
|
+
if (container) container.scrollTo({
|
|
27
|
+
top: container.scrollHeight,
|
|
28
|
+
behavior: "smooth"
|
|
29
|
+
});
|
|
30
|
+
}, []);
|
|
31
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
32
|
+
className: cn("relative flex flex-1 flex-col", className),
|
|
33
|
+
children: [/* @__PURE__ */ jsx(ScrollArea, {
|
|
34
|
+
ref: scrollRef,
|
|
35
|
+
className: "flex-1",
|
|
36
|
+
onScroll: handleScroll,
|
|
37
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
38
|
+
className: "flex flex-col gap-4 p-4",
|
|
39
|
+
children
|
|
40
|
+
})
|
|
41
|
+
}), showScrollButton && showScrollDown && /* @__PURE__ */ jsxs("button", {
|
|
42
|
+
onClick: scrollToBottom,
|
|
43
|
+
className: cn("absolute bottom-4 left-1/2 -translate-x-1/2", "bg-primary text-primary-foreground", "rounded-full px-3 py-1.5 text-sm font-medium shadow-lg", "hover:bg-primary/90 transition-colors", "flex items-center gap-1.5"),
|
|
44
|
+
"aria-label": "Scroll to bottom",
|
|
45
|
+
children: [/* @__PURE__ */ jsx("svg", {
|
|
46
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
47
|
+
width: "16",
|
|
48
|
+
height: "16",
|
|
49
|
+
viewBox: "0 0 24 24",
|
|
50
|
+
fill: "none",
|
|
51
|
+
stroke: "currentColor",
|
|
52
|
+
strokeWidth: "2",
|
|
53
|
+
strokeLinecap: "round",
|
|
54
|
+
strokeLinejoin: "round",
|
|
55
|
+
children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
|
|
56
|
+
}), "New messages"]
|
|
57
|
+
})]
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
//#endregion
|
|
62
|
+
export { ChatContainer };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ChatAttachment } from "../../core/message-types.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react_jsx_runtime2 from "react/jsx-runtime";
|
|
3
3
|
|
|
4
4
|
//#region src/presentation/components/ChatInput.d.ts
|
|
5
5
|
interface ChatInputProps {
|
|
@@ -29,6 +29,6 @@ declare function ChatInput({
|
|
|
29
29
|
className,
|
|
30
30
|
showAttachments,
|
|
31
31
|
maxAttachments
|
|
32
|
-
}: ChatInputProps):
|
|
32
|
+
}: ChatInputProps): react_jsx_runtime2.JSX.Element;
|
|
33
33
|
//#endregion
|
|
34
34
|
export { ChatInput };
|
|
@@ -1 +1,149 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { cn } from "../../libs/ui-kit-web/dist/ui/utils.js";
|
|
4
|
+
import { Button$1 } from "../../libs/design-system/dist/components/atoms/Button.js";
|
|
5
|
+
import { Textarea$1 } from "../../libs/design-system/dist/components/atoms/Textarea.js";
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { Code, FileText, Loader2, Paperclip, Send, X } from "lucide-react";
|
|
9
|
+
|
|
10
|
+
//#region src/presentation/components/ChatInput.tsx
|
|
11
|
+
/**
|
|
12
|
+
* Chat input component with attachment support
|
|
13
|
+
*/
|
|
14
|
+
function ChatInput({ onSend, disabled = false, isLoading = false, placeholder = "Type a message...", className, showAttachments = true, maxAttachments = 5 }) {
|
|
15
|
+
const [content, setContent] = React.useState("");
|
|
16
|
+
const [attachments, setAttachments] = React.useState([]);
|
|
17
|
+
const textareaRef = React.useRef(null);
|
|
18
|
+
const fileInputRef = React.useRef(null);
|
|
19
|
+
const canSend = content.trim().length > 0 || attachments.length > 0;
|
|
20
|
+
const handleSubmit = React.useCallback((e) => {
|
|
21
|
+
e?.preventDefault();
|
|
22
|
+
if (!canSend || disabled || isLoading) return;
|
|
23
|
+
onSend(content.trim(), attachments.length > 0 ? attachments : void 0);
|
|
24
|
+
setContent("");
|
|
25
|
+
setAttachments([]);
|
|
26
|
+
textareaRef.current?.focus();
|
|
27
|
+
}, [
|
|
28
|
+
canSend,
|
|
29
|
+
content,
|
|
30
|
+
attachments,
|
|
31
|
+
disabled,
|
|
32
|
+
isLoading,
|
|
33
|
+
onSend
|
|
34
|
+
]);
|
|
35
|
+
const handleKeyDown = React.useCallback((e) => {
|
|
36
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
37
|
+
e.preventDefault();
|
|
38
|
+
handleSubmit();
|
|
39
|
+
}
|
|
40
|
+
}, [handleSubmit]);
|
|
41
|
+
const handleFileSelect = React.useCallback(async (e) => {
|
|
42
|
+
const files = e.target.files;
|
|
43
|
+
if (!files) return;
|
|
44
|
+
const newAttachments = [];
|
|
45
|
+
for (const file of Array.from(files)) {
|
|
46
|
+
if (attachments.length + newAttachments.length >= maxAttachments) break;
|
|
47
|
+
const content$1 = await file.text();
|
|
48
|
+
const extension = file.name.split(".").pop()?.toLowerCase() ?? "";
|
|
49
|
+
const isCode = [
|
|
50
|
+
"ts",
|
|
51
|
+
"tsx",
|
|
52
|
+
"js",
|
|
53
|
+
"jsx",
|
|
54
|
+
"py",
|
|
55
|
+
"go",
|
|
56
|
+
"rs",
|
|
57
|
+
"java"
|
|
58
|
+
].includes(extension);
|
|
59
|
+
newAttachments.push({
|
|
60
|
+
id: `att_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
|
|
61
|
+
type: isCode ? "code" : "file",
|
|
62
|
+
name: file.name,
|
|
63
|
+
content: content$1,
|
|
64
|
+
mimeType: file.type,
|
|
65
|
+
size: file.size
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
setAttachments((prev) => [...prev, ...newAttachments]);
|
|
69
|
+
e.target.value = "";
|
|
70
|
+
}, [attachments.length, maxAttachments]);
|
|
71
|
+
const removeAttachment = React.useCallback((id) => {
|
|
72
|
+
setAttachments((prev) => prev.filter((a) => a.id !== id));
|
|
73
|
+
}, []);
|
|
74
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
75
|
+
className: cn("flex flex-col gap-2", className),
|
|
76
|
+
children: [
|
|
77
|
+
attachments.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
78
|
+
className: "flex flex-wrap gap-2",
|
|
79
|
+
children: attachments.map((attachment) => /* @__PURE__ */ jsxs("div", {
|
|
80
|
+
className: cn("flex items-center gap-1.5 rounded-md px-2 py-1", "bg-muted text-muted-foreground text-sm"),
|
|
81
|
+
children: [
|
|
82
|
+
attachment.type === "code" ? /* @__PURE__ */ jsx(Code, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(FileText, { className: "h-3.5 w-3.5" }),
|
|
83
|
+
/* @__PURE__ */ jsx("span", {
|
|
84
|
+
className: "max-w-[150px] truncate",
|
|
85
|
+
children: attachment.name
|
|
86
|
+
}),
|
|
87
|
+
/* @__PURE__ */ jsx("button", {
|
|
88
|
+
type: "button",
|
|
89
|
+
onClick: () => removeAttachment(attachment.id),
|
|
90
|
+
className: "hover:text-foreground",
|
|
91
|
+
"aria-label": `Remove ${attachment.name}`,
|
|
92
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" })
|
|
93
|
+
})
|
|
94
|
+
]
|
|
95
|
+
}, attachment.id))
|
|
96
|
+
}),
|
|
97
|
+
/* @__PURE__ */ jsxs("form", {
|
|
98
|
+
onSubmit: handleSubmit,
|
|
99
|
+
className: "flex items-end gap-2",
|
|
100
|
+
children: [
|
|
101
|
+
showAttachments && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("input", {
|
|
102
|
+
ref: fileInputRef,
|
|
103
|
+
type: "file",
|
|
104
|
+
multiple: true,
|
|
105
|
+
accept: ".ts,.tsx,.js,.jsx,.json,.md,.txt,.py,.go,.rs,.java,.yaml,.yml",
|
|
106
|
+
onChange: handleFileSelect,
|
|
107
|
+
className: "hidden",
|
|
108
|
+
"aria-label": "Attach files"
|
|
109
|
+
}), /* @__PURE__ */ jsx(Button$1, {
|
|
110
|
+
type: "button",
|
|
111
|
+
variant: "ghost",
|
|
112
|
+
size: "sm",
|
|
113
|
+
onPress: () => fileInputRef.current?.click(),
|
|
114
|
+
disabled: disabled || attachments.length >= maxAttachments,
|
|
115
|
+
"aria-label": "Attach files",
|
|
116
|
+
children: /* @__PURE__ */ jsx(Paperclip, { className: "h-4 w-4" })
|
|
117
|
+
})] }),
|
|
118
|
+
/* @__PURE__ */ jsx("div", {
|
|
119
|
+
className: "relative flex-1",
|
|
120
|
+
children: /* @__PURE__ */ jsx(Textarea$1, {
|
|
121
|
+
value: content,
|
|
122
|
+
onChange: (e) => setContent(e.target.value),
|
|
123
|
+
onKeyDown: handleKeyDown,
|
|
124
|
+
placeholder,
|
|
125
|
+
disabled,
|
|
126
|
+
className: cn("min-h-[44px] max-h-[200px] resize-none pr-12", "focus-visible:ring-1"),
|
|
127
|
+
rows: 1,
|
|
128
|
+
"aria-label": "Chat message"
|
|
129
|
+
})
|
|
130
|
+
}),
|
|
131
|
+
/* @__PURE__ */ jsx(Button$1, {
|
|
132
|
+
type: "submit",
|
|
133
|
+
disabled: !canSend || disabled || isLoading,
|
|
134
|
+
size: "sm",
|
|
135
|
+
"aria-label": isLoading ? "Sending..." : "Send message",
|
|
136
|
+
children: isLoading ? /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx(Send, { className: "h-4 w-4" })
|
|
137
|
+
})
|
|
138
|
+
]
|
|
139
|
+
}),
|
|
140
|
+
/* @__PURE__ */ jsx("p", {
|
|
141
|
+
className: "text-muted-foreground text-xs",
|
|
142
|
+
children: "Press Enter to send, Shift+Enter for new line"
|
|
143
|
+
})
|
|
144
|
+
]
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
//#endregion
|
|
149
|
+
export { ChatInput };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ChatMessage } from "../../core/message-types.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react_jsx_runtime1 from "react/jsx-runtime";
|
|
3
3
|
|
|
4
4
|
//#region src/presentation/components/ChatMessage.d.ts
|
|
5
5
|
interface ChatMessageProps {
|
|
@@ -18,6 +18,6 @@ declare function ChatMessage$1({
|
|
|
18
18
|
className,
|
|
19
19
|
showCopy,
|
|
20
20
|
showAvatar
|
|
21
|
-
}: ChatMessageProps):
|
|
21
|
+
}: ChatMessageProps): react_jsx_runtime1.JSX.Element;
|
|
22
22
|
//#endregion
|
|
23
23
|
export { ChatMessage$1 as ChatMessage };
|