@k8o/arte-odyssey 10.6.4 → 10.8.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 (61) hide show
  1. package/dist/components/ai/_internal/collapsible.d.mts +14 -0
  2. package/dist/components/ai/_internal/collapsible.mjs +49 -0
  3. package/dist/components/ai/_internal/streaming-cursor.d.mts +6 -0
  4. package/dist/components/ai/_internal/streaming-cursor.mjs +8 -0
  5. package/dist/components/ai/conversation/conversation.d.mts +19 -0
  6. package/dist/components/ai/conversation/conversation.mjs +105 -0
  7. package/dist/components/ai/conversation/index.d.mts +2 -0
  8. package/dist/components/ai/conversation/index.mjs +2 -0
  9. package/dist/components/ai/index.d.mts +8 -0
  10. package/dist/components/ai/index.mjs +7 -0
  11. package/dist/components/ai/message/index.d.mts +2 -0
  12. package/dist/components/ai/message/index.mjs +2 -0
  13. package/dist/components/ai/message/message.d.mts +18 -0
  14. package/dist/components/ai/message/message.mjs +33 -0
  15. package/dist/components/ai/prompt-input/index.d.mts +2 -0
  16. package/dist/components/ai/prompt-input/index.mjs +2 -0
  17. package/dist/components/ai/prompt-input/prompt-input.d.mts +27 -0
  18. package/dist/components/ai/prompt-input/prompt-input.mjs +103 -0
  19. package/dist/components/ai/reasoning/index.d.mts +2 -0
  20. package/dist/components/ai/reasoning/index.mjs +2 -0
  21. package/dist/components/ai/reasoning/reasoning.d.mts +13 -0
  22. package/dist/components/ai/reasoning/reasoning.mjs +21 -0
  23. package/dist/components/ai/response/index.d.mts +2 -0
  24. package/dist/components/ai/response/index.mjs +2 -0
  25. package/dist/components/ai/response/response.d.mts +18 -0
  26. package/dist/components/ai/response/response.mjs +20 -0
  27. package/dist/components/ai/suggestion/index.d.mts +2 -0
  28. package/dist/components/ai/suggestion/index.mjs +2 -0
  29. package/dist/components/ai/suggestion/suggestion.d.mts +18 -0
  30. package/dist/components/ai/suggestion/suggestion.mjs +25 -0
  31. package/dist/components/ai/tool-invocation/index.d.mts +2 -0
  32. package/dist/components/ai/tool-invocation/index.mjs +2 -0
  33. package/dist/components/ai/tool-invocation/tool-invocation.d.mts +17 -0
  34. package/dist/components/ai/tool-invocation/tool-invocation.mjs +59 -0
  35. package/dist/components/ai/types.d.mts +5 -0
  36. package/dist/components/ai/types.mjs +1 -0
  37. package/dist/components/data-display/avatar/avatar.d.mts +3 -1
  38. package/dist/components/data-display/avatar/avatar.mjs +7 -3
  39. package/dist/components/form/checkbox-group/index.d.mts +3 -3
  40. package/dist/components/icons/color-scale.d.mts +7 -0
  41. package/dist/components/icons/color-scale.mjs +43 -0
  42. package/dist/components/icons/index.d.mts +3 -2
  43. package/dist/components/icons/index.mjs +3 -2
  44. package/dist/components/icons/lucide-imports.d.mts +2 -1
  45. package/dist/components/icons/lucide-imports.mjs +2 -1
  46. package/dist/components/icons/lucide.d.mts +2 -1
  47. package/dist/components/icons/lucide.mjs +6 -2
  48. package/dist/components/index.d.mts +3 -2
  49. package/dist/components/index.mjs +3 -2
  50. package/dist/index.d.mts +3 -2
  51. package/dist/index.mjs +3 -2
  52. package/dist/integrations/_shared/openui-defs.mjs +1 -1
  53. package/dist/integrations/_shared/schemas.d.mts +17 -17
  54. package/dist/integrations/ai-sdk/index.d.mts +3 -0
  55. package/dist/integrations/ai-sdk/index.mjs +2 -0
  56. package/dist/integrations/ai-sdk/map-parts.d.mts +28 -0
  57. package/dist/integrations/ai-sdk/map-parts.mjs +31 -0
  58. package/dist/integrations/json-render/catalog.d.mts +16 -16
  59. package/dist/integrations/json-render/registry.mjs +1 -1
  60. package/dist/integrations/openui/library.mjs +1 -1
  61. package/package.json +29 -1
@@ -0,0 +1,14 @@
1
+ import { FC, ReactNode } from "react";
2
+
3
+ //#region src/components/ai/_internal/collapsible.d.ts
4
+ type Props = {
5
+ icon?: ReactNode;
6
+ label: ReactNode;
7
+ isOpen?: boolean;
8
+ defaultOpen?: boolean;
9
+ onChange?: (isOpen: boolean) => void;
10
+ children: ReactNode;
11
+ };
12
+ declare const Collapsible: FC<Props>;
13
+ //#endregion
14
+ export { Collapsible };
@@ -0,0 +1,49 @@
1
+ "use client";
2
+ import { FOCUS_RING_NO_BORDER } from "../../_internal/focus-ring.mjs";
3
+ import { cn } from "../../../helpers/cn.mjs";
4
+ import { useControllableState } from "../../../hooks/controllable-state/index.mjs";
5
+ import { ChevronIcon } from "../../icons/lucide.mjs";
6
+ import { useId } from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ //#region src/components/ai/_internal/collapsible.tsx
9
+ const Collapsible = ({ icon, label, isOpen, defaultOpen = false, onChange, children }) => {
10
+ const [open, setOpen] = useControllableState({
11
+ value: isOpen,
12
+ defaultValue: defaultOpen,
13
+ onChange
14
+ });
15
+ const panelId = useId();
16
+ return /* @__PURE__ */ jsxs("div", {
17
+ className: "border-border-mute bg-bg-subtle overflow-hidden rounded-xl border text-sm",
18
+ children: [/* @__PURE__ */ jsxs("button", {
19
+ "aria-controls": panelId,
20
+ "aria-expanded": open,
21
+ className: cn("flex w-full items-center gap-2 px-3 py-2 text-left text-fg-mute transition-colors duration-150 ease-out hover:bg-bg-mute", FOCUS_RING_NO_BORDER),
22
+ onClick: () => {
23
+ setOpen(!open);
24
+ },
25
+ type: "button",
26
+ children: [
27
+ icon !== void 0 && /* @__PURE__ */ jsx("span", {
28
+ className: "flex shrink-0 items-center",
29
+ children: icon
30
+ }),
31
+ /* @__PURE__ */ jsx("span", {
32
+ className: "min-w-0 flex-1 truncate",
33
+ children: label
34
+ }),
35
+ /* @__PURE__ */ jsx(ChevronIcon, {
36
+ direction: open ? "up" : "down",
37
+ size: "sm"
38
+ })
39
+ ]
40
+ }), /* @__PURE__ */ jsx("div", {
41
+ className: "px-3 pt-2 pb-3",
42
+ hidden: !open,
43
+ id: panelId,
44
+ children
45
+ })]
46
+ });
47
+ };
48
+ //#endregion
49
+ export { Collapsible };
@@ -0,0 +1,6 @@
1
+ import { FC } from "react";
2
+
3
+ //#region src/components/ai/_internal/streaming-cursor.d.ts
4
+ declare const StreamingCursor: FC;
5
+ //#endregion
6
+ export { StreamingCursor };
@@ -0,0 +1,8 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ //#region src/components/ai/_internal/streaming-cursor.tsx
3
+ const StreamingCursor = () => /* @__PURE__ */ jsx("span", {
4
+ "aria-hidden": true,
5
+ className: "bg-fg-base ml-0.5 inline-block h-[1.1em] w-0.5 translate-y-[0.15em] rounded-xs motion-safe:animate-pulse"
6
+ });
7
+ //#endregion
8
+ export { StreamingCursor };
@@ -0,0 +1,19 @@
1
+ import { FC, ReactNode } from "react";
2
+
3
+ //#region src/components/ai/conversation/conversation.d.ts
4
+ type MessagesProps = {
5
+ label?: string;
6
+ isStreaming?: boolean;
7
+ children: ReactNode;
8
+ };
9
+ declare const Conversation: {
10
+ readonly Root: FC<{
11
+ children: ReactNode;
12
+ }>;
13
+ readonly Messages: FC<MessagesProps>;
14
+ readonly ScrollButton: FC<{
15
+ label?: string;
16
+ }>;
17
+ };
18
+ //#endregion
19
+ export { Conversation };
@@ -0,0 +1,105 @@
1
+ "use client";
2
+ import { FOCUS_RING, FOCUS_RING_NO_BORDER } from "../../_internal/focus-ring.mjs";
3
+ import { cn } from "../../../helpers/cn.mjs";
4
+ import { createSafeContext } from "../../../helpers/create-safe-context.mjs";
5
+ import { useIntersectionObserver } from "../../../hooks/intersection-observer/use-intersection-observer.mjs";
6
+ import { useResize } from "../../../hooks/resize/index.mjs";
7
+ import { ChevronIcon } from "../../icons/lucide.mjs";
8
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ //#region src/components/ai/conversation/conversation.tsx
11
+ const prefersReducedMotion = () => window.matchMedia("(prefers-reduced-motion: reduce)").matches;
12
+ const [ConversationProvider, useConversationContext] = createSafeContext("Conversation.* must be used within <Conversation.Root>");
13
+ const Root = ({ children }) => {
14
+ const [viewport, setViewport] = useState(null);
15
+ const sentinelRef = useRef(null);
16
+ const contentRef = useRef(null);
17
+ const [isAtBottom, setIsAtBottom] = useState(true);
18
+ const isAtBottomRef = useRef(true);
19
+ const updateAtBottom = useCallback((next) => {
20
+ isAtBottomRef.current = next;
21
+ setIsAtBottom(next);
22
+ }, []);
23
+ const scrollToBottom = useCallback((behavior = "smooth") => {
24
+ if (!viewport) return;
25
+ viewport.scrollTo({
26
+ top: viewport.scrollHeight,
27
+ behavior: prefersReducedMotion() ? "instant" : behavior
28
+ });
29
+ }, [viewport]);
30
+ useIntersectionObserver(sentinelRef, useCallback((entry) => {
31
+ updateAtBottom(entry.isIntersecting);
32
+ }, [updateAtBottom]), {
33
+ root: viewport,
34
+ rootMargin: "0px 0px 24px 0px"
35
+ });
36
+ useResize(contentRef, useCallback(() => {
37
+ if (isAtBottomRef.current && viewport) viewport.scrollTo({
38
+ top: viewport.scrollHeight,
39
+ behavior: "instant"
40
+ });
41
+ }, [viewport]));
42
+ useEffect(() => {
43
+ if (viewport) viewport.scrollTo({
44
+ top: viewport.scrollHeight,
45
+ behavior: "instant"
46
+ });
47
+ }, [viewport]);
48
+ return /* @__PURE__ */ jsx(ConversationProvider, {
49
+ value: useMemo(() => ({
50
+ isAtBottom,
51
+ scrollToBottom,
52
+ setViewport,
53
+ sentinelRef,
54
+ contentRef
55
+ }), [isAtBottom, scrollToBottom]),
56
+ children: /* @__PURE__ */ jsx("div", {
57
+ className: "relative flex h-full min-h-0 flex-col",
58
+ children
59
+ })
60
+ });
61
+ };
62
+ const Messages = ({ label = "チャット", isStreaming = false, children }) => {
63
+ const { setViewport, sentinelRef, contentRef } = useConversationContext();
64
+ return /* @__PURE__ */ jsx("div", {
65
+ "aria-busy": isStreaming,
66
+ "aria-label": label,
67
+ "aria-live": "polite",
68
+ className: cn("min-h-0 flex-1 overflow-y-auto overscroll-contain", FOCUS_RING_NO_BORDER),
69
+ ref: setViewport,
70
+ role: "log",
71
+ tabIndex: 0,
72
+ children: /* @__PURE__ */ jsxs("div", {
73
+ className: "flex flex-col gap-6 p-4",
74
+ ref: contentRef,
75
+ children: [children, /* @__PURE__ */ jsx("div", {
76
+ "aria-hidden": true,
77
+ className: "h-px w-full shrink-0",
78
+ ref: sentinelRef
79
+ })]
80
+ })
81
+ });
82
+ };
83
+ const ScrollButton = ({ label = "最新のメッセージへ移動" }) => {
84
+ const { isAtBottom, scrollToBottom } = useConversationContext();
85
+ if (isAtBottom) return null;
86
+ return /* @__PURE__ */ jsx("button", {
87
+ "aria-label": label,
88
+ className: cn("absolute bottom-4 left-1/2 flex size-9 -translate-x-1/2 items-center justify-center rounded-full border border-border-base bg-bg-base text-fg-mute shadow-md transition-colors duration-150 ease-out hover:bg-bg-subtle", FOCUS_RING),
89
+ onClick: () => {
90
+ scrollToBottom("smooth");
91
+ },
92
+ type: "button",
93
+ children: /* @__PURE__ */ jsx(ChevronIcon, {
94
+ direction: "down",
95
+ size: "sm"
96
+ })
97
+ });
98
+ };
99
+ const Conversation = {
100
+ Root,
101
+ Messages,
102
+ ScrollButton
103
+ };
104
+ //#endregion
105
+ export { Conversation };
@@ -0,0 +1,2 @@
1
+ import { Conversation } from "./conversation.mjs";
2
+ export { Conversation };
@@ -0,0 +1,2 @@
1
+ import { Conversation } from "./conversation.mjs";
2
+ export { Conversation };
@@ -0,0 +1,8 @@
1
+ import { Conversation } from "./conversation/conversation.mjs";
2
+ import { Message } from "./message/message.mjs";
3
+ import { ChatStatus, ToolState } from "./types.mjs";
4
+ import { PromptInput } from "./prompt-input/prompt-input.mjs";
5
+ import { Reasoning } from "./reasoning/reasoning.mjs";
6
+ import { Suggestion } from "./suggestion/suggestion.mjs";
7
+ import { ToolInvocation } from "./tool-invocation/tool-invocation.mjs";
8
+ export { type ChatStatus, Conversation, Message, PromptInput, Reasoning, Suggestion, ToolInvocation, type ToolState };
@@ -0,0 +1,7 @@
1
+ import { Conversation } from "./conversation/conversation.mjs";
2
+ import { Message } from "./message/message.mjs";
3
+ import { PromptInput } from "./prompt-input/prompt-input.mjs";
4
+ import { Reasoning } from "./reasoning/reasoning.mjs";
5
+ import { Suggestion } from "./suggestion/suggestion.mjs";
6
+ import { ToolInvocation } from "./tool-invocation/tool-invocation.mjs";
7
+ export { Conversation, Message, PromptInput, Reasoning, Suggestion, ToolInvocation };
@@ -0,0 +1,2 @@
1
+ import { Message } from "./message.mjs";
2
+ export { Message };
@@ -0,0 +1,2 @@
1
+ import { Message } from "./message.mjs";
2
+ export { Message };
@@ -0,0 +1,18 @@
1
+ import { FC, HTMLAttributes, ReactNode } from "react";
2
+
3
+ //#region src/components/ai/message/message.d.ts
4
+ type MessageRole = 'user' | 'assistant';
5
+ type RootProps = {
6
+ from: MessageRole;
7
+ children: ReactNode;
8
+ } & Omit<HTMLAttributes<HTMLDivElement>, 'className' | 'style'>;
9
+ type ContentProps = {
10
+ isStreaming?: boolean;
11
+ children: ReactNode;
12
+ } & Omit<HTMLAttributes<HTMLDivElement>, 'className' | 'style'>;
13
+ declare const Message: {
14
+ readonly Root: FC<RootProps>;
15
+ readonly Content: FC<ContentProps>;
16
+ };
17
+ //#endregion
18
+ export { Message };
@@ -0,0 +1,33 @@
1
+ "use client";
2
+ import { cn } from "../../../helpers/cn.mjs";
3
+ import { createSafeContext } from "../../../helpers/create-safe-context.mjs";
4
+ import { StreamingCursor } from "../_internal/streaming-cursor.mjs";
5
+ import { useMemo } from "react";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ //#region src/components/ai/message/message.tsx
8
+ const [MessageProvider, useMessageContext] = createSafeContext("Message.Content must be used within <Message.Root>");
9
+ const Root = ({ from, children, ...rest }) => {
10
+ return /* @__PURE__ */ jsx(MessageProvider, {
11
+ value: useMemo(() => ({ from }), [from]),
12
+ children: /* @__PURE__ */ jsx("div", {
13
+ ...rest,
14
+ className: cn("flex w-full items-start gap-3", from === "user" ? "flex-row-reverse" : "flex-row"),
15
+ "data-from": from,
16
+ children
17
+ })
18
+ });
19
+ };
20
+ const Content = ({ isStreaming = false, children, ...rest }) => {
21
+ const { from } = useMessageContext();
22
+ return /* @__PURE__ */ jsxs("div", {
23
+ ...rest,
24
+ className: cn("min-w-0 wrap-break-word whitespace-pre-wrap text-fg-base", from === "user" ? "w-fit max-w-[80%] rounded-2xl bg-bg-subtle px-4 py-2.5" : "flex-1 leading-relaxed"),
25
+ children: [children, isStreaming ? /* @__PURE__ */ jsx(StreamingCursor, {}) : null]
26
+ });
27
+ };
28
+ const Message = {
29
+ Root,
30
+ Content
31
+ };
32
+ //#endregion
33
+ export { Message };
@@ -0,0 +1,2 @@
1
+ import { PromptInput } from "./prompt-input.mjs";
2
+ export { PromptInput };
@@ -0,0 +1,2 @@
1
+ import { PromptInput } from "./prompt-input.mjs";
2
+ export { PromptInput };
@@ -0,0 +1,27 @@
1
+ import { ChatStatus } from "../types.mjs";
2
+ import { FC, ReactNode, TextareaHTMLAttributes } from "react";
3
+
4
+ //#region src/components/ai/prompt-input/prompt-input.d.ts
5
+ type RootProps = {
6
+ status?: ChatStatus;
7
+ value?: string;
8
+ defaultValue?: string;
9
+ onChange?: (value: string) => void;
10
+ onSubmit?: (message: string) => void;
11
+ onStop?: () => void;
12
+ children: ReactNode;
13
+ };
14
+ type TextareaProps = {
15
+ placeholder?: string;
16
+ } & Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'value' | 'defaultValue' | 'onChange' | 'className' | 'style' | 'rows'>;
17
+ type SubmitProps = {
18
+ sendLabel?: string;
19
+ stopLabel?: string;
20
+ };
21
+ declare const PromptInput: {
22
+ readonly Root: FC<RootProps>;
23
+ readonly Textarea: FC<TextareaProps>;
24
+ readonly Submit: FC<SubmitProps>;
25
+ };
26
+ //#endregion
27
+ export { PromptInput };
@@ -0,0 +1,103 @@
1
+ "use client";
2
+ import { FOCUS_RING, FOCUS_RING_WITHIN } from "../../_internal/focus-ring.mjs";
3
+ import { cn } from "../../../helpers/cn.mjs";
4
+ import { createSafeContext } from "../../../helpers/create-safe-context.mjs";
5
+ import { useControllableState } from "../../../hooks/controllable-state/index.mjs";
6
+ import { SendIcon } from "../../icons/lucide.mjs";
7
+ import { useEffect, useMemo, useRef } from "react";
8
+ import { jsx } from "react/jsx-runtime";
9
+ //#region src/components/ai/prompt-input/prompt-input.tsx
10
+ const [PromptInputProvider, usePromptInputContext] = createSafeContext("PromptInput.Textarea / PromptInput.Submit must be used within <PromptInput.Root>");
11
+ const resizeToContent = (el) => {
12
+ el.style.height = "auto";
13
+ el.style.height = `${el.scrollHeight.toString()}px`;
14
+ };
15
+ const Root = ({ status = "ready", value, defaultValue = "", onChange, onSubmit, onStop, children }) => {
16
+ const isControlled = value !== void 0;
17
+ const [text, setText] = useControllableState({
18
+ value,
19
+ defaultValue,
20
+ onChange
21
+ });
22
+ return /* @__PURE__ */ jsx(PromptInputProvider, {
23
+ value: useMemo(() => ({
24
+ value: text,
25
+ setValue: setText,
26
+ status,
27
+ stop: () => onStop?.()
28
+ }), [
29
+ text,
30
+ setText,
31
+ status,
32
+ onStop
33
+ ]),
34
+ children: /* @__PURE__ */ jsx("form", {
35
+ className: cn("flex items-end gap-2 rounded-2xl border border-border-base bg-bg-base p-2", FOCUS_RING_WITHIN),
36
+ onSubmit: (event) => {
37
+ event.preventDefault();
38
+ if (status === "submitted" || status === "streaming") return;
39
+ const trimmed = text.trim();
40
+ if (trimmed === "") return;
41
+ onSubmit?.(trimmed);
42
+ if (!isControlled) setText("");
43
+ },
44
+ children
45
+ })
46
+ });
47
+ };
48
+ const Textarea = ({ placeholder, onKeyDown, ...rest }) => {
49
+ const { value, setValue, status } = usePromptInputContext();
50
+ const ref = useRef(null);
51
+ useEffect(() => {
52
+ if (ref.current) resizeToContent(ref.current);
53
+ }, [value]);
54
+ const handleKeyDown = (event) => {
55
+ onKeyDown?.(event);
56
+ if (event.defaultPrevented) return;
57
+ if (event.key !== "Enter" || event.shiftKey) return;
58
+ if (event.nativeEvent.isComposing) return;
59
+ if (status !== "submitted" && status !== "streaming") {
60
+ event.preventDefault();
61
+ event.currentTarget.form?.requestSubmit();
62
+ }
63
+ };
64
+ return /* @__PURE__ */ jsx("textarea", {
65
+ ...rest,
66
+ className: cn("max-h-48 min-h-10 flex-1 resize-none bg-transparent text-fg-base outline-hidden p-2", "placeholder:text-fg-subtle"),
67
+ onChange: (event) => {
68
+ setValue(event.target.value);
69
+ },
70
+ onKeyDown: handleKeyDown,
71
+ placeholder,
72
+ ref,
73
+ rows: 1,
74
+ value
75
+ });
76
+ };
77
+ const Submit = ({ sendLabel = "送信", stopLabel = "停止" }) => {
78
+ const { value, status, stop } = usePromptInputContext();
79
+ if (status === "submitted" || status === "streaming") return /* @__PURE__ */ jsx("button", {
80
+ "aria-label": stopLabel,
81
+ className: cn("flex size-9 shrink-0 items-center justify-center rounded-full bg-primary-bg text-primary-fg transition-colors duration-150 ease-out", FOCUS_RING),
82
+ onClick: stop,
83
+ type: "button",
84
+ children: /* @__PURE__ */ jsx("span", {
85
+ "aria-hidden": true,
86
+ className: "size-3 rounded-xs bg-current"
87
+ })
88
+ });
89
+ return /* @__PURE__ */ jsx("button", {
90
+ "aria-label": sendLabel,
91
+ className: cn("flex size-9 shrink-0 items-center justify-center rounded-full bg-primary-bg text-primary-fg transition-colors duration-150 ease-out", "disabled:cursor-not-allowed disabled:opacity-50", FOCUS_RING),
92
+ disabled: value.trim() === "",
93
+ type: "submit",
94
+ children: /* @__PURE__ */ jsx(SendIcon, { size: "sm" })
95
+ });
96
+ };
97
+ const PromptInput = {
98
+ Root,
99
+ Textarea,
100
+ Submit
101
+ };
102
+ //#endregion
103
+ export { PromptInput };
@@ -0,0 +1,2 @@
1
+ import { Reasoning } from "./reasoning.mjs";
2
+ export { Reasoning };
@@ -0,0 +1,2 @@
1
+ import { Reasoning } from "./reasoning.mjs";
2
+ export { Reasoning };
@@ -0,0 +1,13 @@
1
+ import { FC, ReactNode } from "react";
2
+
3
+ //#region src/components/ai/reasoning/reasoning.d.ts
4
+ type Props = {
5
+ children: ReactNode;
6
+ isStreaming?: boolean;
7
+ isOpen?: boolean;
8
+ defaultOpen?: boolean;
9
+ onChange?: (isOpen: boolean) => void;
10
+ };
11
+ declare const Reasoning: FC<Props>;
12
+ //#endregion
13
+ export { Reasoning };
@@ -0,0 +1,21 @@
1
+ "use client";
2
+ import { SparklesIcon } from "../../icons/lucide.mjs";
3
+ import { Collapsible } from "../_internal/collapsible.mjs";
4
+ import { jsx } from "react/jsx-runtime";
5
+ //#region src/components/ai/reasoning/reasoning.tsx
6
+ const Reasoning = ({ children, isStreaming = false, isOpen, defaultOpen = false, onChange }) => /* @__PURE__ */ jsx(Collapsible, {
7
+ defaultOpen,
8
+ isOpen,
9
+ onChange,
10
+ icon: /* @__PURE__ */ jsx("span", {
11
+ className: "text-fg-subtle",
12
+ children: /* @__PURE__ */ jsx(SparklesIcon, { size: "sm" })
13
+ }),
14
+ label: isStreaming ? "思考中…" : "思考の過程",
15
+ children: /* @__PURE__ */ jsx("div", {
16
+ className: "text-fg-mute text-sm leading-relaxed whitespace-pre-wrap",
17
+ children
18
+ })
19
+ });
20
+ //#endregion
21
+ export { Reasoning };
@@ -0,0 +1,2 @@
1
+ import { Response } from "./response.mjs";
2
+ export { Response };
@@ -0,0 +1,2 @@
1
+ import { Response } from "./response.mjs";
2
+ export { Response };
@@ -0,0 +1,18 @@
1
+ import { FC } from "react";
2
+
3
+ //#region src/components/ai/response/response.d.ts
4
+ type Props = {
5
+ children: string;
6
+ isStreaming?: boolean;
7
+ };
8
+ /**
9
+ * ストリーミング対応の Markdown レンダラ。未クローズのコードブロックなど
10
+ * 途中の Markdown も streamdown が破綻なく描画する。
11
+ *
12
+ * このコンポーネントは streamdown(optional peer)に依存する。利用側は
13
+ * `pnpm add streamdown` に加え、`streamdown/styles.css` の読み込みと
14
+ * Tailwind の `@source` 設定が必要。詳細は docs を参照。
15
+ */
16
+ declare const Response: FC<Props>;
17
+ //#endregion
18
+ export { Response };
@@ -0,0 +1,20 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { Streamdown } from "streamdown";
4
+ //#region src/components/ai/response/response.tsx
5
+ /**
6
+ * ストリーミング対応の Markdown レンダラ。未クローズのコードブロックなど
7
+ * 途中の Markdown も streamdown が破綻なく描画する。
8
+ *
9
+ * このコンポーネントは streamdown(optional peer)に依存する。利用側は
10
+ * `pnpm add streamdown` に加え、`streamdown/styles.css` の読み込みと
11
+ * Tailwind の `@source` 設定が必要。詳細は docs を参照。
12
+ */
13
+ const Response = ({ children, isStreaming = false }) => /* @__PURE__ */ jsx(Streamdown, {
14
+ className: "text-fg-base",
15
+ mode: isStreaming ? "streaming" : "static",
16
+ parseIncompleteMarkdown: true,
17
+ children
18
+ });
19
+ //#endregion
20
+ export { Response };
@@ -0,0 +1,2 @@
1
+ import { Suggestion } from "./suggestion.mjs";
2
+ export { Suggestion };
@@ -0,0 +1,2 @@
1
+ import { Suggestion } from "./suggestion.mjs";
2
+ export { Suggestion };
@@ -0,0 +1,18 @@
1
+ import { FC, ReactNode } from "react";
2
+
3
+ //#region src/components/ai/suggestion/suggestion.d.ts
4
+ type ListProps = {
5
+ label?: string;
6
+ children: ReactNode;
7
+ };
8
+ type ItemProps = {
9
+ value: string;
10
+ onSelect?: (value: string) => void;
11
+ children?: ReactNode;
12
+ };
13
+ declare const Suggestion: {
14
+ readonly List: FC<ListProps>;
15
+ readonly Item: FC<ItemProps>;
16
+ };
17
+ //#endregion
18
+ export { Suggestion };
@@ -0,0 +1,25 @@
1
+ "use client";
2
+ import { FOCUS_RING } from "../../_internal/focus-ring.mjs";
3
+ import { cn } from "../../../helpers/cn.mjs";
4
+ import { jsx } from "react/jsx-runtime";
5
+ //#region src/components/ai/suggestion/suggestion.tsx
6
+ const List = ({ label = "候補", children }) => /* @__PURE__ */ jsx("div", {
7
+ "aria-label": label,
8
+ className: "flex flex-wrap gap-2",
9
+ role: "group",
10
+ children
11
+ });
12
+ const Item = ({ value, onSelect, children }) => /* @__PURE__ */ jsx("button", {
13
+ className: cn("rounded-full border border-border-base bg-bg-subtle px-3 py-1.5 text-sm text-fg-base transition-colors duration-150 ease-out hover:bg-bg-mute", FOCUS_RING),
14
+ onClick: () => {
15
+ onSelect?.(value);
16
+ },
17
+ type: "button",
18
+ children: children ?? value
19
+ });
20
+ const Suggestion = {
21
+ List,
22
+ Item
23
+ };
24
+ //#endregion
25
+ export { Suggestion };
@@ -0,0 +1,2 @@
1
+ import { ToolInvocation } from "./tool-invocation.mjs";
2
+ export { ToolInvocation };
@@ -0,0 +1,2 @@
1
+ import { ToolInvocation } from "./tool-invocation.mjs";
2
+ export { ToolInvocation };
@@ -0,0 +1,17 @@
1
+ import { ToolState } from "../types.mjs";
2
+ import { FC, ReactNode } from "react";
3
+
4
+ //#region src/components/ai/tool-invocation/tool-invocation.d.ts
5
+ type Props = {
6
+ name: string;
7
+ state: ToolState;
8
+ input?: unknown;
9
+ output?: ReactNode;
10
+ errorText?: string;
11
+ isOpen?: boolean;
12
+ defaultOpen?: boolean;
13
+ onChange?: (isOpen: boolean) => void;
14
+ };
15
+ declare const ToolInvocation: FC<Props>;
16
+ //#endregion
17
+ export { ToolInvocation };