@devalok/shilp-sutra 0.57.0 → 0.59.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.
- package/MIGRATION.md +91 -0
- package/dist/_chunks/badge-group.js +75 -188
- package/dist/_chunks/badge-group.js.map +1 -1
- package/dist/_chunks/chat.js +244 -243
- package/dist/_chunks/chat.js.map +1 -1
- package/dist/_chunks/image-preview.js +71 -70
- package/dist/_chunks/image-preview.js.map +1 -1
- package/dist/_chunks/motion-preference.js +15 -0
- package/dist/_chunks/motion-preference.js.map +1 -0
- package/dist/_chunks/motion-provider.js +1 -1
- package/dist/_chunks/motion-provider.js.map +1 -1
- package/dist/_chunks/popover.js +50 -49
- package/dist/_chunks/popover.js.map +1 -1
- package/dist/_chunks/primitives-internal.js +29 -29
- package/dist/_chunks/primitives-internal.js.map +1 -1
- package/dist/_chunks/shared.js +48 -47
- package/dist/_chunks/shared.js.map +1 -1
- package/dist/_chunks/success.js +34 -34
- package/dist/_chunks/tree-view.js +1 -1
- package/dist/_chunks/tree-view.js.map +1 -1
- package/dist/ai/block-renderer.js +8 -8
- package/dist/ai/command-bar.js +65 -65
- package/dist/ai/command-bar.js.map +1 -1
- package/dist/ai/conversation.js +35 -35
- package/dist/ai/conversation.js.map +1 -1
- package/dist/ai/index.js +4 -4
- package/dist/composed/activity-feed.d.ts.map +1 -1
- package/dist/composed/activity-feed.js +108 -107
- package/dist/composed/activity-feed.js.map +1 -1
- package/dist/composed/command-palette.js +137 -137
- package/dist/composed/command-palette.js.map +1 -1
- package/dist/composed/content-card.js +1 -1
- package/dist/composed/content-card.js.map +1 -1
- package/dist/composed/date-picker/index.js +5 -5
- package/dist/composed/date-picker/index.js.map +1 -1
- package/dist/composed/empty-state.js +4 -4
- package/dist/composed/file-preview/image-preview.d.ts.map +1 -1
- package/dist/composed/file-preview/shared.d.ts.map +1 -1
- package/dist/composed/file-preview/video-preview.d.ts.map +1 -1
- package/dist/composed/file-preview.js +151 -150
- package/dist/composed/file-preview.js.map +1 -1
- package/dist/composed/filter-bar.d.ts.map +1 -1
- package/dist/composed/filter-bar.js +53 -52
- package/dist/composed/filter-bar.js.map +1 -1
- package/dist/composed/form-section.d.ts.map +1 -1
- package/dist/composed/form-section.js +38 -37
- package/dist/composed/form-section.js.map +1 -1
- package/dist/composed/master-detail.d.ts.map +1 -1
- package/dist/composed/master-detail.js +1 -1
- package/dist/composed/master-detail.js.map +1 -1
- package/dist/composed/multi-select-popover.d.ts.map +1 -1
- package/dist/composed/multi-select-popover.js +109 -108
- package/dist/composed/multi-select-popover.js.map +1 -1
- package/dist/composed/rich-chat-input/attachment-strip.d.ts.map +1 -1
- package/dist/composed/rich-chat-input/reply-banner.d.ts.map +1 -1
- package/dist/composed/rich-chat-input/schedule-send.d.ts.map +1 -1
- package/dist/composed/rich-chat-input.d.ts.map +1 -1
- package/dist/composed/rich-chat-input.js +467 -466
- package/dist/composed/rich-chat-input.js.map +1 -1
- package/dist/composed/rich-text-editor.js +3 -3
- package/dist/composed/rich-text-editor.js.map +1 -1
- package/dist/composed/schedule-view.js +2 -2
- package/dist/composed/schedule-view.js.map +1 -1
- package/dist/composed/status-badge.d.ts.map +1 -1
- package/dist/composed/status-badge.js +29 -28
- package/dist/composed/status-badge.js.map +1 -1
- package/dist/motion/index.d.ts +1 -0
- package/dist/motion/index.d.ts.map +1 -1
- package/dist/motion/index.js +2 -15
- package/dist/motion/motion-preference.d.ts +36 -0
- package/dist/motion/motion-preference.d.ts.map +1 -0
- package/dist/motion/motion-provider.d.ts +2 -1
- package/dist/motion/motion-provider.d.ts.map +1 -1
- package/dist/motion/primitives-index.js +103 -102
- package/dist/motion/primitives-index.js.map +1 -1
- package/dist/motion/primitives.d.ts.map +1 -1
- package/dist/shell/bottom-navbar.js +19 -19
- package/dist/shell/bottom-navbar.js.map +1 -1
- package/dist/shell/index.d.ts +1 -1
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/shell/notification-center.d.ts +17 -0
- package/dist/shell/notification-center.d.ts.map +1 -1
- package/dist/shell/notification-center.js +109 -104
- package/dist/shell/notification-center.js.map +1 -1
- package/dist/shell/notification-preferences.js +1 -1
- package/dist/shell/notification-preferences.js.map +1 -1
- package/dist/shell/top-bar.js +1 -1
- package/dist/shell/top-bar.js.map +1 -1
- package/dist/tokens/index.css +1 -0
- package/dist/tokens/palettes.css +292 -0
- package/dist/tokens/semantic.css +72 -8
- package/dist/tokens/shilp-sutra.css +1 -0
- package/dist/tokens/utilities.css +10 -7
- package/dist/ui/accordion.d.ts.map +1 -1
- package/dist/ui/accordion.js +27 -26
- package/dist/ui/accordion.js.map +1 -1
- package/dist/ui/alert-dialog.d.ts.map +1 -1
- package/dist/ui/alert-dialog.js +60 -59
- package/dist/ui/alert-dialog.js.map +1 -1
- package/dist/ui/alert.d.ts.map +1 -1
- package/dist/ui/alert.js +55 -113
- package/dist/ui/alert.js.map +1 -1
- package/dist/ui/autocomplete.js +80 -80
- package/dist/ui/autocomplete.js.map +1 -1
- package/dist/ui/avatar.d.ts.map +1 -1
- package/dist/ui/avatar.js +69 -68
- package/dist/ui/avatar.js.map +1 -1
- package/dist/ui/badge-indicator.d.ts +4 -8
- package/dist/ui/badge-indicator.d.ts.map +1 -1
- package/dist/ui/badge-indicator.js +3 -8
- package/dist/ui/badge-indicator.js.map +1 -1
- package/dist/ui/badge.d.ts +8 -1
- package/dist/ui/badge.d.ts.map +1 -1
- package/dist/ui/banner.d.ts.map +1 -1
- package/dist/ui/banner.js +42 -40
- package/dist/ui/banner.js.map +1 -1
- package/dist/ui/button-group.d.ts.map +1 -1
- package/dist/ui/button-group.js +3 -23
- package/dist/ui/button-group.js.map +1 -1
- package/dist/ui/button.d.ts +10 -1
- package/dist/ui/button.d.ts.map +1 -1
- package/dist/ui/button.js +79 -212
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/card.d.ts.map +1 -1
- package/dist/ui/card.js +75 -72
- package/dist/ui/card.js.map +1 -1
- package/dist/ui/charts/radar-chart.d.ts.map +1 -1
- package/dist/ui/charts/radar-chart.js +1 -1
- package/dist/ui/charts/radar-chart.js.map +1 -1
- package/dist/ui/chat/message-list.d.ts.map +1 -1
- package/dist/ui/chat/message.d.ts.map +1 -1
- package/dist/ui/chat/typing-indicator.d.ts.map +1 -1
- package/dist/ui/code.js +1 -1
- package/dist/ui/code.js.map +1 -1
- package/dist/ui/color-input.d.ts.map +1 -1
- package/dist/ui/color-input.js +151 -150
- package/dist/ui/color-input.js.map +1 -1
- package/dist/ui/combobox.d.ts +14 -0
- package/dist/ui/combobox.d.ts.map +1 -1
- package/dist/ui/combobox.js +152 -148
- package/dist/ui/combobox.js.map +1 -1
- package/dist/ui/context-menu.d.ts.map +1 -1
- package/dist/ui/context-menu.js +70 -69
- package/dist/ui/context-menu.js.map +1 -1
- package/dist/ui/data-table-body.js +2 -2
- package/dist/ui/data-table-body.js.map +1 -1
- package/dist/ui/data-table-context.js +2 -2
- package/dist/ui/data-table-context.js.map +1 -1
- package/dist/ui/data-table-header.d.ts.map +1 -1
- package/dist/ui/data-table-header.js +41 -40
- package/dist/ui/data-table-header.js.map +1 -1
- package/dist/ui/data-table-pagination.js +2 -2
- package/dist/ui/data-table-pagination.js.map +1 -1
- package/dist/ui/dialog.d.ts.map +1 -1
- package/dist/ui/dialog.js +61 -60
- package/dist/ui/dialog.js.map +1 -1
- package/dist/ui/dot.d.ts.map +1 -1
- package/dist/ui/dot.js +10 -41
- package/dist/ui/dot.js.map +1 -1
- package/dist/ui/dropdown-menu.d.ts.map +1 -1
- package/dist/ui/dropdown-menu.js +79 -78
- package/dist/ui/dropdown-menu.js.map +1 -1
- package/dist/ui/file-upload.d.ts.map +1 -1
- package/dist/ui/file-upload.js +116 -115
- package/dist/ui/file-upload.js.map +1 -1
- package/dist/ui/form.d.ts.map +1 -1
- package/dist/ui/form.js +27 -26
- package/dist/ui/form.js.map +1 -1
- package/dist/ui/hover-card.d.ts.map +1 -1
- package/dist/ui/hover-card.js +26 -25
- package/dist/ui/hover-card.js.map +1 -1
- package/dist/ui/icon.js +7 -7
- package/dist/ui/index.d.ts +2 -2
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +3 -3
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/input.js +1 -1
- package/dist/ui/input.js.map +1 -1
- package/dist/ui/menubar.d.ts.map +1 -1
- package/dist/ui/menubar.js +73 -72
- package/dist/ui/menubar.js.map +1 -1
- package/dist/ui/navigation-menu.d.ts.map +1 -1
- package/dist/ui/navigation-menu.js +80 -79
- package/dist/ui/navigation-menu.js.map +1 -1
- package/dist/ui/popover.d.ts.map +1 -1
- package/dist/ui/progress.d.ts.map +1 -1
- package/dist/ui/progress.js +72 -68
- package/dist/ui/progress.js.map +1 -1
- package/dist/ui/radio.d.ts.map +1 -1
- package/dist/ui/radio.js +32 -31
- package/dist/ui/radio.js.map +1 -1
- package/dist/ui/search-input.d.ts.map +1 -1
- package/dist/ui/search-input.js +28 -27
- package/dist/ui/search-input.js.map +1 -1
- package/dist/ui/select.d.ts.map +1 -1
- package/dist/ui/select.js +64 -63
- package/dist/ui/select.js.map +1 -1
- package/dist/ui/sidebar.d.ts.map +1 -1
- package/dist/ui/sidebar.js +4 -4
- package/dist/ui/sidebar.js.map +1 -1
- package/dist/ui/slider.d.ts +63 -9
- package/dist/ui/slider.d.ts.map +1 -1
- package/dist/ui/slider.js +74 -32
- package/dist/ui/slider.js.map +1 -1
- package/dist/ui/split-button.d.ts +8 -2
- package/dist/ui/split-button.d.ts.map +1 -1
- package/dist/ui/split-button.js +49 -95
- package/dist/ui/split-button.js.map +1 -1
- package/dist/ui/stat-card.d.ts.map +1 -1
- package/dist/ui/stat-card.js +89 -88
- package/dist/ui/stat-card.js.map +1 -1
- package/dist/ui/stat-flash.js +16 -16
- package/dist/ui/stepper.d.ts.map +1 -1
- package/dist/ui/stepper.js +63 -62
- package/dist/ui/stepper.js.map +1 -1
- package/dist/ui/table.js +3 -3
- package/dist/ui/table.js.map +1 -1
- package/dist/ui/tabs.d.ts.map +1 -1
- package/dist/ui/tabs.js +67 -66
- package/dist/ui/tabs.js.map +1 -1
- package/dist/ui/textarea.js +1 -1
- package/dist/ui/textarea.js.map +1 -1
- package/dist/ui/toast.d.ts.map +1 -1
- package/dist/ui/toast.js +195 -194
- package/dist/ui/toast.js.map +1 -1
- package/dist/ui/toggle.d.ts.map +1 -1
- package/dist/ui/toggle.js +24 -22
- package/dist/ui/toggle.js.map +1 -1
- package/dist/ui/tooltip.d.ts.map +1 -1
- package/dist/ui/tooltip.js +37 -36
- package/dist/ui/tooltip.js.map +1 -1
- package/dist/ui/tree-view/tree-item.d.ts.map +1 -1
- package/docs/recipes/customize-brand.md +58 -0
- package/docs/recipes/install-astro.md +1 -1
- package/docs/recipes/install-next-app-router.md +1 -1
- package/docs/recipes/install-next-pages.md +22 -1
- package/docs/recipes/install-remix.md +1 -1
- package/docs/recipes/install-tanstack-start.md +1 -1
- package/docs/recipes/install-vite.md +2 -1
- package/docs/recipes/server-components.md +7 -4
- package/docs/recipes/troubleshoot.md +1 -0
- package/llms.txt +1 -1
- package/mcp-manifest.json +9 -4
- package/package.json +3 -2
- package/skill/SKILL.md +1 -1
- package/skill/references/components.md +1 -1
- package/skill/references/customize-brand.md +58 -0
- package/skill/references/server-components.md +7 -4
- package/skill/references/setup-astro.md +1 -1
- package/skill/references/setup-next-app-router.md +1 -1
- package/skill/references/setup-next-pages.md +22 -1
- package/skill/references/setup-remix.md +1 -1
- package/skill/references/setup-tanstack-start.md +1 -1
- package/skill/references/setup-vite.md +2 -1
- package/skill/references/troubleshoot.md +1 -0
- package/dist/motion/check-motion-provider.d.ts +0 -2
- package/dist/motion/check-motion-provider.d.ts.map +0 -1
- package/dist/motion/index.js.map +0 -1
package/dist/ai/conversation.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
2
|
+
import { durations as e, springs as t } from "../ui/lib/motion.js";
|
|
3
|
+
import { useMotion as n } from "../_chunks/motion-provider.js";
|
|
4
|
+
import { IconProvider as r } from "../ui/icon-context.js";
|
|
5
|
+
import { cn as i } from "../ui/lib/utils.js";
|
|
6
|
+
import { Icon as a } from "../ui/icon.js";
|
|
7
7
|
import { normalizeIcon as o } from "../_chunks/normalize-icon.js";
|
|
8
8
|
import { useAICommand as s } from "./ai-command-provider.js";
|
|
9
9
|
import { BlockRenderer as c } from "./block-renderer.js";
|
|
@@ -14,7 +14,7 @@ import { AnimatePresence as g, motion as _ } from "framer-motion";
|
|
|
14
14
|
//#region src/ai/conversation.tsx
|
|
15
15
|
function v({ status: e }) {
|
|
16
16
|
switch (e) {
|
|
17
|
-
case "done": return /* @__PURE__ */ u(
|
|
17
|
+
case "done": return /* @__PURE__ */ u(a, {
|
|
18
18
|
icon: p,
|
|
19
19
|
size: "sm",
|
|
20
20
|
className: "text-success-11"
|
|
@@ -28,53 +28,53 @@ function v({ status: e }) {
|
|
|
28
28
|
ease: "linear"
|
|
29
29
|
},
|
|
30
30
|
"aria-hidden": "true",
|
|
31
|
-
children: /* @__PURE__ */ u(
|
|
31
|
+
children: /* @__PURE__ */ u(a, {
|
|
32
32
|
icon: h,
|
|
33
33
|
size: "sm"
|
|
34
34
|
})
|
|
35
35
|
});
|
|
36
|
-
case "error": return /* @__PURE__ */ u(
|
|
36
|
+
case "error": return /* @__PURE__ */ u(a, {
|
|
37
37
|
icon: m,
|
|
38
38
|
size: "sm",
|
|
39
39
|
className: "text-error-11"
|
|
40
40
|
});
|
|
41
|
-
default: return /* @__PURE__ */ u(
|
|
41
|
+
default: return /* @__PURE__ */ u(a, {
|
|
42
42
|
icon: f,
|
|
43
43
|
size: "sm",
|
|
44
44
|
className: "text-surface-fg-subtle opacity-50"
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
-
function y({ name:
|
|
48
|
+
function y({ name: e, icon: t }) {
|
|
49
49
|
return /* @__PURE__ */ d("div", {
|
|
50
50
|
className: "flex items-center gap-ds-02b mb-ds-03",
|
|
51
|
-
children: [
|
|
51
|
+
children: [t && /* @__PURE__ */ u("span", {
|
|
52
52
|
className: "h-4 w-4 flex items-center justify-center",
|
|
53
|
-
children: /* @__PURE__ */ u(
|
|
53
|
+
children: /* @__PURE__ */ u(r, {
|
|
54
54
|
size: "sm",
|
|
55
|
-
children: o(
|
|
55
|
+
children: o(t)
|
|
56
56
|
})
|
|
57
57
|
}), /* @__PURE__ */ u("span", {
|
|
58
58
|
className: "text-label-xs font-semibold uppercase tracking-wider text-surface-fg-subtle",
|
|
59
|
-
children:
|
|
59
|
+
children: e
|
|
60
60
|
})]
|
|
61
61
|
});
|
|
62
62
|
}
|
|
63
|
-
function b({ message: e, reducedMotion:
|
|
64
|
-
return
|
|
65
|
-
className: "bg-surface-panel rounded-surface px-ds-05 py-ds-04",
|
|
63
|
+
function b({ message: e, reducedMotion: n }) {
|
|
64
|
+
return n ? /* @__PURE__ */ u("div", {
|
|
65
|
+
className: "bg-surface-panel-hover rounded-surface px-ds-05 py-ds-04",
|
|
66
66
|
children: /* @__PURE__ */ u("p", {
|
|
67
67
|
className: "text-body-sm text-surface-fg",
|
|
68
68
|
children: e.content
|
|
69
69
|
})
|
|
70
70
|
}) : /* @__PURE__ */ u(_.div, {
|
|
71
|
-
className: "bg-surface-panel rounded-surface px-ds-05 py-ds-04",
|
|
71
|
+
className: "bg-surface-panel-hover rounded-surface px-ds-05 py-ds-04",
|
|
72
72
|
initial: { y: 8 },
|
|
73
73
|
animate: {
|
|
74
74
|
opacity: 1,
|
|
75
75
|
y: 0
|
|
76
76
|
},
|
|
77
|
-
transition:
|
|
77
|
+
transition: t.snappy,
|
|
78
78
|
children: /* @__PURE__ */ u("p", {
|
|
79
79
|
className: "text-body-sm text-surface-fg",
|
|
80
80
|
children: e.content
|
|
@@ -91,8 +91,8 @@ function x({ message: e, agent: t, onAction: n, customBlocks: r }) {
|
|
|
91
91
|
customBlocks: r
|
|
92
92
|
})] });
|
|
93
93
|
}
|
|
94
|
-
function S({ steps:
|
|
95
|
-
return
|
|
94
|
+
function S({ steps: t, agent: n, reducedMotion: r }) {
|
|
95
|
+
return t && t.length > 0 ? /* @__PURE__ */ d("div", {
|
|
96
96
|
role: "status",
|
|
97
97
|
"aria-busy": "true",
|
|
98
98
|
"aria-label": "Processing",
|
|
@@ -101,9 +101,9 @@ function S({ steps: e, agent: n, reducedMotion: i }) {
|
|
|
101
101
|
icon: n.icon
|
|
102
102
|
}), /* @__PURE__ */ u("div", {
|
|
103
103
|
className: "flex flex-col gap-ds-02b",
|
|
104
|
-
children:
|
|
104
|
+
children: t.map((t, n) => /* @__PURE__ */ d(_.div, {
|
|
105
105
|
className: "flex items-center gap-ds-02b",
|
|
106
|
-
initial:
|
|
106
|
+
initial: r ? void 0 : {
|
|
107
107
|
opacity: 0,
|
|
108
108
|
x: -8
|
|
109
109
|
},
|
|
@@ -111,15 +111,15 @@ function S({ steps: e, agent: n, reducedMotion: i }) {
|
|
|
111
111
|
opacity: 1,
|
|
112
112
|
x: 0
|
|
113
113
|
},
|
|
114
|
-
transition:
|
|
115
|
-
duration:
|
|
114
|
+
transition: r ? { duration: 0 } : {
|
|
115
|
+
duration: e.moderate01b,
|
|
116
116
|
delay: n * .05
|
|
117
117
|
},
|
|
118
|
-
children: [/* @__PURE__ */ u(v, { status:
|
|
119
|
-
className:
|
|
120
|
-
children:
|
|
118
|
+
children: [/* @__PURE__ */ u(v, { status: t.status }), /* @__PURE__ */ u("span", {
|
|
119
|
+
className: i("text-body-sm", t.status === "pending" ? "text-surface-fg-subtle" : "text-surface-fg"),
|
|
120
|
+
children: t.label
|
|
121
121
|
})]
|
|
122
|
-
},
|
|
122
|
+
}, t.id))
|
|
123
123
|
})]
|
|
124
124
|
}) : /* @__PURE__ */ d("div", {
|
|
125
125
|
role: "status",
|
|
@@ -130,7 +130,7 @@ function S({ steps: e, agent: n, reducedMotion: i }) {
|
|
|
130
130
|
icon: n.icon
|
|
131
131
|
}), /* @__PURE__ */ d("div", {
|
|
132
132
|
className: "flex items-center gap-ds-02",
|
|
133
|
-
children: [!
|
|
133
|
+
children: [!r && [
|
|
134
134
|
0,
|
|
135
135
|
1,
|
|
136
136
|
2
|
|
@@ -175,13 +175,13 @@ function C({ onClick: e }) {
|
|
|
175
175
|
opacity: 0,
|
|
176
176
|
y: 8
|
|
177
177
|
},
|
|
178
|
-
transition:
|
|
178
|
+
transition: t.snappy,
|
|
179
179
|
onClick: e,
|
|
180
180
|
children: ["↓", " New response"]
|
|
181
181
|
});
|
|
182
182
|
}
|
|
183
|
-
var w = { name: "Assistant" }, T = l.forwardRef(({ messages: e, isProcessing: t = !1, processingSteps:
|
|
184
|
-
let _ = s(), { reducedMotion: v } =
|
|
183
|
+
var w = { name: "Assistant" }, T = l.forwardRef(({ messages: e, isProcessing: t = !1, processingSteps: r, agent: a, onAction: o, customBlocks: c, maxHeight: f, autoScroll: p = !0, className: m }, h) => {
|
|
184
|
+
let _ = s(), { reducedMotion: v } = n(), y = a ?? _?.agent ?? w, T = o ?? _?.onAction, E = l.useMemo(() => ({
|
|
185
185
|
..._?.customBlocks ?? {},
|
|
186
186
|
...c
|
|
187
187
|
}), [_?.customBlocks, c]), D = l.useRef(null), O = l.useRef(null), [k, A] = l.useState(!0), [j, M] = l.useState(!1), N = l.useRef(e.length), P = l.useRef(t);
|
|
@@ -214,7 +214,7 @@ var w = { name: "Assistant" }, T = l.forwardRef(({ messages: e, isProcessing: t
|
|
|
214
214
|
}, []);
|
|
215
215
|
return /* @__PURE__ */ d("div", {
|
|
216
216
|
ref: h,
|
|
217
|
-
className:
|
|
217
|
+
className: i("relative", m),
|
|
218
218
|
children: [/* @__PURE__ */ d("div", {
|
|
219
219
|
ref: D,
|
|
220
220
|
className: "flex flex-col gap-ds-05 overflow-y-auto",
|
|
@@ -231,7 +231,7 @@ var w = { name: "Assistant" }, T = l.forwardRef(({ messages: e, isProcessing: t
|
|
|
231
231
|
customBlocks: E
|
|
232
232
|
}, e.id)),
|
|
233
233
|
t && /* @__PURE__ */ u(S, {
|
|
234
|
-
steps:
|
|
234
|
+
steps: r,
|
|
235
235
|
agent: y,
|
|
236
236
|
reducedMotion: v
|
|
237
237
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.js","names":[],"sources":["../../src/ai/conversation.tsx"],"sourcesContent":["'use client'\n\nimport {\n IconCircle,\n IconCircleCheck,\n IconCircleX,\n IconLoader2,\n} from '@tabler/icons-react'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { useMotion } from '../motion/motion-provider'\nimport { Icon } from '../ui/icon'\nimport { IconProvider } from '../ui/icon-context'\nimport type { IconInput } from '../ui/lib/icon-input'\nimport { durations,springs } from '../ui/lib/motion'\nimport { normalizeIcon } from '../ui/lib/normalize-icon'\nimport { cn } from '../ui/lib/utils'\nimport { useAICommand } from './ai-command-provider'\nimport { BlockRenderer } from './block-renderer'\nimport type {\n BlockComponentProps,\n ConversationMessage,\n ProcessingStep,\n} from './types'\n\n// ── Props ────────────────────────────────────────────────────────────────────\n\n/**\n * Renders a scrollable AI conversation thread with support for streaming\n * processing steps, custom content blocks, and action confirmations.\n */\nexport interface AIConversationProps {\n /** Ordered conversation messages (user + assistant turns). */\n messages: ConversationMessage[]\n /** When true, shows a live processing indicator below the last message. */\n isProcessing?: boolean\n /** Granular processing steps shown during the processing state. */\n processingSteps?: ProcessingStep[]\n /** Agent identity displayed as a header on assistant messages. */\n agent?: { name: string; icon?: IconInput }\n /** Called when user interacts with an action block (confirm/cancel/undo). */\n onAction?: (actionId: string, type: 'confirm' | 'cancel' | 'undo') => void\n /** Map of custom block type names to React components for extensible rendering. */\n customBlocks?: Record<string, React.ComponentType<BlockComponentProps<any>>>\n /** Max height of the conversation container (CSS value). Enables scrolling. */\n maxHeight?: string | number\n /** Auto-scroll to bottom on new messages. @default true */\n autoScroll?: boolean\n className?: string\n}\n\n// ── Step status icon ─────────────────────────────────────────────────────────\n\nfunction StepStatusIcon({ status }: { status: ProcessingStep['status'] }) {\n switch (status) {\n case 'done':\n return (\n <Icon icon={IconCircleCheck} size=\"sm\" className=\"text-success-11\" />\n )\n case 'active':\n return (\n <motion.span\n className=\"inline-flex items-center justify-center text-accent-9\"\n animate={{ rotate: 360 }}\n transition={{ repeat: Infinity, duration: 1, ease: 'linear' }}\n aria-hidden=\"true\"\n >\n <Icon icon={IconLoader2} size=\"sm\" />\n </motion.span>\n )\n case 'error':\n return (\n <Icon icon={IconCircleX} size=\"sm\" className=\"text-error-11\" />\n )\n case 'pending':\n default:\n return (\n <Icon icon={IconCircle} size=\"sm\" className=\"text-surface-fg-subtle opacity-50\" />\n )\n }\n}\n\n// ── Agent header ─────────────────────────────────────────────────────────────\n\nfunction AgentHeader({\n name,\n icon,\n}: {\n name: string\n icon?: IconInput\n}) {\n return (\n <div className=\"flex items-center gap-ds-02b mb-ds-03\">\n {icon && <span className=\"h-4 w-4 flex items-center justify-center\"><IconProvider size=\"sm\">{normalizeIcon(icon)}</IconProvider></span>}\n <span className=\"text-label-xs font-semibold uppercase tracking-wider text-surface-fg-subtle\">\n {name}\n </span>\n </div>\n )\n}\n\n// ── User message ─────────────────────────────────────────────────────────────\n\nfunction UserMessage({\n message,\n reducedMotion,\n}: {\n message: ConversationMessage\n reducedMotion: boolean\n}) {\n if (reducedMotion) {\n return (\n <div className=\"bg-surface-panel rounded-surface px-ds-05 py-ds-04\">\n <p className=\"text-body-sm text-surface-fg\">{message.content}</p>\n </div>\n )\n }\n\n return (\n <motion.div\n className=\"bg-surface-panel rounded-surface px-ds-05 py-ds-04\"\n initial={{ y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={springs.snappy}\n >\n <p className=\"text-body-sm text-surface-fg\">{message.content}</p>\n </motion.div>\n )\n}\n\n// ── Assistant message ────────────────────────────────────────────────────────\n\nfunction AssistantMessage({\n message,\n agent,\n onAction,\n customBlocks,\n}: {\n message: ConversationMessage\n agent: { name: string; icon?: IconInput }\n onAction?: (actionId: string, type: 'confirm' | 'cancel' | 'undo') => void\n customBlocks?: Record<string, React.ComponentType<BlockComponentProps<any>>>\n}) {\n return (\n <div>\n <AgentHeader name={agent.name} icon={agent.icon} />\n {message.blocks && (\n <BlockRenderer\n blocks={message.blocks}\n onAction={onAction}\n customBlocks={customBlocks}\n />\n )}\n </div>\n )\n}\n\n// ── Processing indicator ─────────────────────────────────────────────────────\n\nfunction ProcessingIndicator({\n steps,\n agent,\n reducedMotion,\n}: {\n steps?: ProcessingStep[]\n agent: { name: string; icon?: IconInput }\n reducedMotion: boolean\n}) {\n // Step visualization\n if (steps && steps.length > 0) {\n return (\n <div role=\"status\" aria-busy=\"true\" aria-label=\"Processing\">\n <AgentHeader name={agent.name} icon={agent.icon} />\n <div className=\"flex flex-col gap-ds-02b\">\n {steps.map((step, i) => (\n <motion.div\n key={step.id}\n className=\"flex items-center gap-ds-02b\"\n initial={reducedMotion ? undefined : { opacity: 0, x: -8 }}\n animate={{ opacity: 1, x: 0 }}\n transition={\n reducedMotion\n ? { duration: 0 }\n : { duration: durations.moderate01b, delay: i * 0.05 }\n }\n >\n <StepStatusIcon status={step.status} />\n <span\n className={cn(\n 'text-body-sm',\n step.status === 'pending'\n ? 'text-surface-fg-subtle'\n : 'text-surface-fg',\n )}\n >\n {step.label}\n </span>\n </motion.div>\n ))}\n </div>\n </div>\n )\n }\n\n // Breathing dots\n return (\n <div\n role=\"status\"\n aria-busy=\"true\"\n aria-label={`${agent.name} is processing`}\n >\n <AgentHeader name={agent.name} icon={agent.icon} />\n <div className=\"flex items-center gap-ds-02\">\n {!reducedMotion &&\n [0, 1, 2].map((i) => (\n <motion.span\n key={i}\n className=\"h-1.5 w-1.5 rounded-pill bg-accent-9\"\n animate={{ scale: [1, 1.4, 1], opacity: [0.4, 1, 0.4] }}\n transition={{\n duration: 1.4,\n repeat: Infinity,\n ease: 'easeInOut',\n delay: i * 0.16,\n }}\n />\n ))}\n <span className=\"ml-ds-02b text-body-sm text-surface-fg-subtle\">\n {agent.name} is thinking...\n </span>\n </div>\n </div>\n )\n}\n\n// ── Scroll-to-bottom pill ────────────────────────────────────────────────────\n\nfunction ScrollToBottomPill({ onClick }: { onClick: () => void }) {\n return (\n <motion.button\n role=\"button\"\n aria-label=\"Scroll to latest response\"\n className=\"absolute bottom-ds-04 left-1/2 -translate-x-1/2 z-10 flex items-center gap-ds-02 bg-accent-9 text-accent-fg text-body-xs font-medium rounded-pill px-ds-04 py-ds-02 shadow-floating\"\n initial={{ y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 8 }}\n transition={springs.snappy}\n onClick={onClick}\n >\n {'\\u2193'} New response\n </motion.button>\n )\n}\n\n// ── Default agent ────────────────────────────────────────────────────────────\n\nconst DEFAULT_AGENT = { name: 'Assistant' }\n\n// ── AIConversation ───────────────────────────────────────────────────────────\n\nconst AIConversation = React.forwardRef<HTMLDivElement, AIConversationProps>(({\n messages,\n isProcessing = false,\n processingSteps,\n agent: agentProp,\n onAction,\n customBlocks,\n maxHeight,\n autoScroll = true,\n className,\n}, ref) => {\n const ctx = useAICommand()\n const { reducedMotion } = useMotion()\n\n // Resolve agent: prop > context > default\n const agent = agentProp ?? ctx?.agent ?? DEFAULT_AGENT\n\n // Resolve onAction: prop > context\n const resolvedOnAction = onAction ?? ctx?.onAction\n\n // Resolve customBlocks: prop wins over context\n const resolvedCustomBlocks = React.useMemo(() => {\n const contextBlocks = ctx?.customBlocks ?? {}\n return { ...contextBlocks, ...customBlocks }\n }, [ctx?.customBlocks, customBlocks])\n\n // ── Auto-scroll ──────────────────────────────────────────────────────────\n\n const scrollRef = React.useRef<HTMLDivElement>(null)\n const sentinelRef = React.useRef<HTMLDivElement>(null)\n const [isAtBottom, setIsAtBottom] = React.useState(true)\n const [hasNewContent, setHasNewContent] = React.useState(false)\n const prevMessageCount = React.useRef(messages.length)\n const prevProcessing = React.useRef(isProcessing)\n\n // Track if user is scrolled to bottom via IntersectionObserver\n React.useEffect(() => {\n if (!autoScroll || !sentinelRef.current) return\n\n const observer = new IntersectionObserver(\n ([entry]) => {\n setIsAtBottom(entry.isIntersecting)\n if (entry.isIntersecting) {\n setHasNewContent(false)\n }\n },\n {\n root: scrollRef.current,\n threshold: 0.1,\n },\n )\n\n observer.observe(sentinelRef.current)\n return () => observer.disconnect()\n }, [autoScroll])\n\n // Auto-scroll or show pill on new content\n React.useEffect(() => {\n const contentChanged =\n messages.length !== prevMessageCount.current ||\n isProcessing !== prevProcessing.current\n\n prevMessageCount.current = messages.length\n prevProcessing.current = isProcessing\n\n if (!contentChanged || !autoScroll) return\n\n if (isAtBottom) {\n sentinelRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' })\n } else {\n setHasNewContent(true)\n }\n }, [messages, isProcessing, isAtBottom, autoScroll])\n\n const scrollToBottom = React.useCallback(() => {\n sentinelRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' })\n setIsAtBottom(true)\n setHasNewContent(false)\n }, [])\n\n // ── Render ───────────────────────────────────────────────────────────────\n\n return (\n <div ref={ref} className={cn('relative', className)}>\n <div\n ref={scrollRef}\n className=\"flex flex-col gap-ds-05 overflow-y-auto\"\n aria-live=\"polite\"\n style={\n maxHeight\n ? {\n maxHeight:\n typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight,\n }\n : undefined\n }\n >\n {messages.map((msg) =>\n msg.role === 'user' ? (\n <UserMessage\n key={msg.id}\n message={msg}\n reducedMotion={reducedMotion}\n />\n ) : (\n <AssistantMessage\n key={msg.id}\n message={msg}\n agent={agent}\n onAction={resolvedOnAction}\n customBlocks={resolvedCustomBlocks}\n />\n ),\n )}\n {isProcessing && (\n <ProcessingIndicator\n steps={processingSteps}\n agent={agent}\n reducedMotion={reducedMotion}\n />\n )}\n <div ref={sentinelRef} className=\"h-px\" />\n </div>\n <AnimatePresence>\n {!isAtBottom && hasNewContent && (\n <ScrollToBottomPill onClick={scrollToBottom} />\n )}\n </AnimatePresence>\n </div>\n )\n})\nAIConversation.displayName = 'AIConversation'\n\nexport { AIConversation }\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"conversation.js","names":[],"sources":["../../src/ai/conversation.tsx"],"sourcesContent":["'use client'\n\nimport {\n IconCircle,\n IconCircleCheck,\n IconCircleX,\n IconLoader2,\n} from '@tabler/icons-react'\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { useMotion } from '../motion/motion-provider'\nimport { Icon } from '../ui/icon'\nimport { IconProvider } from '../ui/icon-context'\nimport type { IconInput } from '../ui/lib/icon-input'\nimport { durations,springs } from '../ui/lib/motion'\nimport { normalizeIcon } from '../ui/lib/normalize-icon'\nimport { cn } from '../ui/lib/utils'\nimport { useAICommand } from './ai-command-provider'\nimport { BlockRenderer } from './block-renderer'\nimport type {\n BlockComponentProps,\n ConversationMessage,\n ProcessingStep,\n} from './types'\n\n// ── Props ────────────────────────────────────────────────────────────────────\n\n/**\n * Renders a scrollable AI conversation thread with support for streaming\n * processing steps, custom content blocks, and action confirmations.\n */\nexport interface AIConversationProps {\n /** Ordered conversation messages (user + assistant turns). */\n messages: ConversationMessage[]\n /** When true, shows a live processing indicator below the last message. */\n isProcessing?: boolean\n /** Granular processing steps shown during the processing state. */\n processingSteps?: ProcessingStep[]\n /** Agent identity displayed as a header on assistant messages. */\n agent?: { name: string; icon?: IconInput }\n /** Called when user interacts with an action block (confirm/cancel/undo). */\n onAction?: (actionId: string, type: 'confirm' | 'cancel' | 'undo') => void\n /** Map of custom block type names to React components for extensible rendering. */\n customBlocks?: Record<string, React.ComponentType<BlockComponentProps<any>>>\n /** Max height of the conversation container (CSS value). Enables scrolling. */\n maxHeight?: string | number\n /** Auto-scroll to bottom on new messages. @default true */\n autoScroll?: boolean\n className?: string\n}\n\n// ── Step status icon ─────────────────────────────────────────────────────────\n\nfunction StepStatusIcon({ status }: { status: ProcessingStep['status'] }) {\n switch (status) {\n case 'done':\n return (\n <Icon icon={IconCircleCheck} size=\"sm\" className=\"text-success-11\" />\n )\n case 'active':\n return (\n <motion.span\n className=\"inline-flex items-center justify-center text-accent-9\"\n animate={{ rotate: 360 }}\n transition={{ repeat: Infinity, duration: 1, ease: 'linear' }}\n aria-hidden=\"true\"\n >\n <Icon icon={IconLoader2} size=\"sm\" />\n </motion.span>\n )\n case 'error':\n return (\n <Icon icon={IconCircleX} size=\"sm\" className=\"text-error-11\" />\n )\n case 'pending':\n default:\n return (\n <Icon icon={IconCircle} size=\"sm\" className=\"text-surface-fg-subtle opacity-50\" />\n )\n }\n}\n\n// ── Agent header ─────────────────────────────────────────────────────────────\n\nfunction AgentHeader({\n name,\n icon,\n}: {\n name: string\n icon?: IconInput\n}) {\n return (\n <div className=\"flex items-center gap-ds-02b mb-ds-03\">\n {icon && <span className=\"h-4 w-4 flex items-center justify-center\"><IconProvider size=\"sm\">{normalizeIcon(icon)}</IconProvider></span>}\n <span className=\"text-label-xs font-semibold uppercase tracking-wider text-surface-fg-subtle\">\n {name}\n </span>\n </div>\n )\n}\n\n// ── User message ─────────────────────────────────────────────────────────────\n\nfunction UserMessage({\n message,\n reducedMotion,\n}: {\n message: ConversationMessage\n reducedMotion: boolean\n}) {\n if (reducedMotion) {\n return (\n <div className=\"bg-surface-panel-hover rounded-surface px-ds-05 py-ds-04\">\n <p className=\"text-body-sm text-surface-fg\">{message.content}</p>\n </div>\n )\n }\n\n return (\n <motion.div\n className=\"bg-surface-panel-hover rounded-surface px-ds-05 py-ds-04\"\n initial={{ y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={springs.snappy}\n >\n <p className=\"text-body-sm text-surface-fg\">{message.content}</p>\n </motion.div>\n )\n}\n\n// ── Assistant message ────────────────────────────────────────────────────────\n\nfunction AssistantMessage({\n message,\n agent,\n onAction,\n customBlocks,\n}: {\n message: ConversationMessage\n agent: { name: string; icon?: IconInput }\n onAction?: (actionId: string, type: 'confirm' | 'cancel' | 'undo') => void\n customBlocks?: Record<string, React.ComponentType<BlockComponentProps<any>>>\n}) {\n return (\n <div>\n <AgentHeader name={agent.name} icon={agent.icon} />\n {message.blocks && (\n <BlockRenderer\n blocks={message.blocks}\n onAction={onAction}\n customBlocks={customBlocks}\n />\n )}\n </div>\n )\n}\n\n// ── Processing indicator ─────────────────────────────────────────────────────\n\nfunction ProcessingIndicator({\n steps,\n agent,\n reducedMotion,\n}: {\n steps?: ProcessingStep[]\n agent: { name: string; icon?: IconInput }\n reducedMotion: boolean\n}) {\n // Step visualization\n if (steps && steps.length > 0) {\n return (\n <div role=\"status\" aria-busy=\"true\" aria-label=\"Processing\">\n <AgentHeader name={agent.name} icon={agent.icon} />\n <div className=\"flex flex-col gap-ds-02b\">\n {steps.map((step, i) => (\n <motion.div\n key={step.id}\n className=\"flex items-center gap-ds-02b\"\n initial={reducedMotion ? undefined : { opacity: 0, x: -8 }}\n animate={{ opacity: 1, x: 0 }}\n transition={\n reducedMotion\n ? { duration: 0 }\n : { duration: durations.moderate01b, delay: i * 0.05 }\n }\n >\n <StepStatusIcon status={step.status} />\n <span\n className={cn(\n 'text-body-sm',\n step.status === 'pending'\n ? 'text-surface-fg-subtle'\n : 'text-surface-fg',\n )}\n >\n {step.label}\n </span>\n </motion.div>\n ))}\n </div>\n </div>\n )\n }\n\n // Breathing dots\n return (\n <div\n role=\"status\"\n aria-busy=\"true\"\n aria-label={`${agent.name} is processing`}\n >\n <AgentHeader name={agent.name} icon={agent.icon} />\n <div className=\"flex items-center gap-ds-02\">\n {!reducedMotion &&\n [0, 1, 2].map((i) => (\n <motion.span\n key={i}\n className=\"h-1.5 w-1.5 rounded-pill bg-accent-9\"\n animate={{ scale: [1, 1.4, 1], opacity: [0.4, 1, 0.4] }}\n transition={{\n duration: 1.4,\n repeat: Infinity,\n ease: 'easeInOut',\n delay: i * 0.16,\n }}\n />\n ))}\n <span className=\"ml-ds-02b text-body-sm text-surface-fg-subtle\">\n {agent.name} is thinking...\n </span>\n </div>\n </div>\n )\n}\n\n// ── Scroll-to-bottom pill ────────────────────────────────────────────────────\n\nfunction ScrollToBottomPill({ onClick }: { onClick: () => void }) {\n return (\n <motion.button\n role=\"button\"\n aria-label=\"Scroll to latest response\"\n className=\"absolute bottom-ds-04 left-1/2 -translate-x-1/2 z-10 flex items-center gap-ds-02 bg-accent-9 text-accent-fg text-body-xs font-medium rounded-pill px-ds-04 py-ds-02 shadow-floating\"\n initial={{ y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 8 }}\n transition={springs.snappy}\n onClick={onClick}\n >\n {'\\u2193'} New response\n </motion.button>\n )\n}\n\n// ── Default agent ────────────────────────────────────────────────────────────\n\nconst DEFAULT_AGENT = { name: 'Assistant' }\n\n// ── AIConversation ───────────────────────────────────────────────────────────\n\nconst AIConversation = React.forwardRef<HTMLDivElement, AIConversationProps>(({\n messages,\n isProcessing = false,\n processingSteps,\n agent: agentProp,\n onAction,\n customBlocks,\n maxHeight,\n autoScroll = true,\n className,\n}, ref) => {\n const ctx = useAICommand()\n const { reducedMotion } = useMotion()\n\n // Resolve agent: prop > context > default\n const agent = agentProp ?? ctx?.agent ?? DEFAULT_AGENT\n\n // Resolve onAction: prop > context\n const resolvedOnAction = onAction ?? ctx?.onAction\n\n // Resolve customBlocks: prop wins over context\n const resolvedCustomBlocks = React.useMemo(() => {\n const contextBlocks = ctx?.customBlocks ?? {}\n return { ...contextBlocks, ...customBlocks }\n }, [ctx?.customBlocks, customBlocks])\n\n // ── Auto-scroll ──────────────────────────────────────────────────────────\n\n const scrollRef = React.useRef<HTMLDivElement>(null)\n const sentinelRef = React.useRef<HTMLDivElement>(null)\n const [isAtBottom, setIsAtBottom] = React.useState(true)\n const [hasNewContent, setHasNewContent] = React.useState(false)\n const prevMessageCount = React.useRef(messages.length)\n const prevProcessing = React.useRef(isProcessing)\n\n // Track if user is scrolled to bottom via IntersectionObserver\n React.useEffect(() => {\n if (!autoScroll || !sentinelRef.current) return\n\n const observer = new IntersectionObserver(\n ([entry]) => {\n setIsAtBottom(entry.isIntersecting)\n if (entry.isIntersecting) {\n setHasNewContent(false)\n }\n },\n {\n root: scrollRef.current,\n threshold: 0.1,\n },\n )\n\n observer.observe(sentinelRef.current)\n return () => observer.disconnect()\n }, [autoScroll])\n\n // Auto-scroll or show pill on new content\n React.useEffect(() => {\n const contentChanged =\n messages.length !== prevMessageCount.current ||\n isProcessing !== prevProcessing.current\n\n prevMessageCount.current = messages.length\n prevProcessing.current = isProcessing\n\n if (!contentChanged || !autoScroll) return\n\n if (isAtBottom) {\n sentinelRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' })\n } else {\n setHasNewContent(true)\n }\n }, [messages, isProcessing, isAtBottom, autoScroll])\n\n const scrollToBottom = React.useCallback(() => {\n sentinelRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' })\n setIsAtBottom(true)\n setHasNewContent(false)\n }, [])\n\n // ── Render ───────────────────────────────────────────────────────────────\n\n return (\n <div ref={ref} className={cn('relative', className)}>\n <div\n ref={scrollRef}\n className=\"flex flex-col gap-ds-05 overflow-y-auto\"\n aria-live=\"polite\"\n style={\n maxHeight\n ? {\n maxHeight:\n typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight,\n }\n : undefined\n }\n >\n {messages.map((msg) =>\n msg.role === 'user' ? (\n <UserMessage\n key={msg.id}\n message={msg}\n reducedMotion={reducedMotion}\n />\n ) : (\n <AssistantMessage\n key={msg.id}\n message={msg}\n agent={agent}\n onAction={resolvedOnAction}\n customBlocks={resolvedCustomBlocks}\n />\n ),\n )}\n {isProcessing && (\n <ProcessingIndicator\n steps={processingSteps}\n agent={agent}\n reducedMotion={reducedMotion}\n />\n )}\n <div ref={sentinelRef} className=\"h-px\" />\n </div>\n <AnimatePresence>\n {!isAtBottom && hasNewContent && (\n <ScrollToBottomPill onClick={scrollToBottom} />\n )}\n </AnimatePresence>\n </div>\n )\n})\nAIConversation.displayName = 'AIConversation'\n\nexport { AIConversation }\n"],"mappings":";;;;;;;;;;;;;;AAsDA,SAAS,EAAe,EAAE,aAAgD;CACxE,QAAQ,GAAR;EACE,KAAK,QACH,OACE,kBAAC,GAAD;GAAM,MAAM;GAAiB,MAAK;GAAK,WAAU;EAAmB,CAAA;EAExE,KAAK,UACH,OACE,kBAAC,EAAO,MAAR;GACE,WAAU;GACV,SAAS,EAAE,QAAQ,IAAI;GACvB,YAAY;IAAE,QAAQ;IAAU,UAAU;IAAG,MAAM;GAAS;GAC5D,eAAY;aAEZ,kBAAC,GAAD;IAAM,MAAM;IAAa,MAAK;GAAM,CAAA;EACzB,CAAA;EAEjB,KAAK,SACH,OACE,kBAAC,GAAD;GAAM,MAAM;GAAa,MAAK;GAAK,WAAU;EAAiB,CAAA;EAGlE,SACE,OACE,kBAAC,GAAD;GAAM,MAAM;GAAY,MAAK;GAAK,WAAU;EAAqC,CAAA;CAEvF;AACF;AAIA,SAAS,EAAY,EACnB,SACA,WAIC;CACD,OACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACG,KAAQ,kBAAC,QAAD;GAAM,WAAU;aAA2C,kBAAC,GAAD;IAAc,MAAK;cAAM,EAAc,CAAI;GAAgB,CAAA;EAAO,CAAA,GACtI,kBAAC,QAAD;GAAM,WAAU;aACb;EACG,CAAA,CACH;;AAET;AAIA,SAAS,EAAY,EACnB,YACA,oBAIC;CASD,OARI,IAEA,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,KAAD;GAAG,WAAU;aAAgC,EAAQ;EAAW,CAAA;CAC7D,CAAA,IAKP,kBAAC,EAAO,KAAR;EACE,WAAU;EACV,SAAS,EAAE,GAAG,EAAE;EAChB,SAAS;GAAE,SAAS;GAAG,GAAG;EAAE;EAC5B,YAAY,EAAQ;YAEpB,kBAAC,KAAD;GAAG,WAAU;aAAgC,EAAQ;EAAW,CAAA;CACtD,CAAA;AAEhB;AAIA,SAAS,EAAiB,EACxB,YACA,UACA,aACA,mBAMC;CACD,OACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,GAAD;EAAa,MAAM,EAAM;EAAM,MAAM,EAAM;CAAO,CAAA,GACjD,EAAQ,UACP,kBAAC,GAAD;EACE,QAAQ,EAAQ;EACN;EACI;CACf,CAAA,CAEA,EAAA,CAAA;AAET;AAIA,SAAS,EAAoB,EAC3B,UACA,UACA,oBAKC;CAsCD,OApCI,KAAS,EAAM,SAAS,IAExB,kBAAC,OAAD;EAAK,MAAK;EAAS,aAAU;EAAO,cAAW;YAA/C,CACE,kBAAC,GAAD;GAAa,MAAM,EAAM;GAAM,MAAM,EAAM;EAAO,CAAA,GAClD,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAM,KAAK,GAAM,MAChB,kBAAC,EAAO,KAAR;IAEE,WAAU;IACV,SAAS,IAAgB,KAAA,IAAY;KAAE,SAAS;KAAG,GAAG;IAAG;IACzD,SAAS;KAAE,SAAS;KAAG,GAAG;IAAE;IAC5B,YACE,IACI,EAAE,UAAU,EAAE,IACd;KAAE,UAAU,EAAU;KAAa,OAAO,IAAI;IAAK;cAR3D,CAWE,kBAAC,GAAD,EAAgB,QAAQ,EAAK,OAAS,CAAA,GACtC,kBAAC,QAAD;KACE,WAAW,EACT,gBACA,EAAK,WAAW,YACZ,2BACA,iBACN;eAEC,EAAK;IACF,CAAA,CACI;MArBL,EAAK,EAqBA,CACb;EACE,CAAA,CACF;MAMP,kBAAC,OAAD;EACE,MAAK;EACL,aAAU;EACV,cAAY,GAAG,EAAM,KAAK;YAH5B,CAKE,kBAAC,GAAD;GAAa,MAAM,EAAM;GAAM,MAAM,EAAM;EAAO,CAAA,GAClD,kBAAC,OAAD;GAAK,WAAU;aAAf,CACG,CAAC,KACA;IAAC;IAAG;IAAG;GAAC,CAAC,CAAC,KAAK,MACb,kBAAC,EAAO,MAAR;IAEE,WAAU;IACV,SAAS;KAAE,OAAO;MAAC;MAAG;MAAK;KAAC;KAAG,SAAS;MAAC;MAAK;MAAG;KAAG;IAAE;IACtD,YAAY;KACV,UAAU;KACV,QAAQ;KACR,MAAM;KACN,OAAO,IAAI;IACb;GACD,GATM,CASN,CACF,GACH,kBAAC,QAAD;IAAM,WAAU;cAAhB,CACG,EAAM,MAAK,iBACR;KACH;IACF;;AAET;AAIA,SAAS,EAAmB,EAAE,cAAoC;CAChE,OACE,kBAAC,EAAO,QAAR;EACE,MAAK;EACL,cAAW;EACX,WAAU;EACV,SAAS,EAAE,GAAG,EAAE;EAChB,SAAS;GAAE,SAAS;GAAG,GAAG;EAAE;EAC5B,MAAM;GAAE,SAAS;GAAG,GAAG;EAAE;EACzB,YAAY,EAAQ;EACX;YARX,CAUG,KAAS,eACG;;AAEnB;AAIA,IAAM,IAAgB,EAAE,MAAM,YAAY,GAIpC,IAAiB,EAAM,YAAiD,EAC5E,aACA,kBAAe,IACf,oBACA,OAAO,GACP,aACA,iBACA,cACA,gBAAa,IACb,gBACC,MAAQ;CACT,IAAM,IAAM,EAAa,GACnB,EAAE,qBAAkB,EAAU,GAG9B,IAAQ,KAAa,GAAK,SAAS,GAGnC,IAAmB,KAAY,GAAK,UAGpC,IAAuB,EAAM,eAE1B;EAAE,GADa,GAAK,gBAAgB,CAAC;EACjB,GAAG;CAAa,IAC1C,CAAC,GAAK,cAAc,CAAY,CAAC,GAI9B,IAAY,EAAM,OAAuB,IAAI,GAC7C,IAAc,EAAM,OAAuB,IAAI,GAC/C,CAAC,GAAY,KAAiB,EAAM,SAAS,EAAI,GACjD,CAAC,GAAe,KAAoB,EAAM,SAAS,EAAK,GACxD,IAAmB,EAAM,OAAO,EAAS,MAAM,GAC/C,IAAiB,EAAM,OAAO,CAAY;CAwBhD,AArBA,EAAM,gBAAgB;EACpB,IAAI,CAAC,KAAc,CAAC,EAAY,SAAS;EAEzC,IAAM,IAAW,IAAI,sBAClB,CAAC,OAAW;GAEX,AADA,EAAc,EAAM,cAAc,GAC9B,EAAM,kBACR,EAAiB,EAAK;EAE1B,GACA;GACE,MAAM,EAAU;GAChB,WAAW;EACb,CACF;EAGA,OADA,EAAS,QAAQ,EAAY,OAAO,SACvB,EAAS,WAAW;CACnC,GAAG,CAAC,CAAU,CAAC,GAGf,EAAM,gBAAgB;EACpB,IAAM,IACJ,EAAS,WAAW,EAAiB,WACrC,MAAiB,EAAe;EAElC,EAAiB,UAAU,EAAS,QACpC,EAAe,UAAU,GAErB,GAAC,KAAkB,CAAC,OAEpB,IACF,EAAY,SAAS,eAAe;GAAE,UAAU;GAAU,OAAO;EAAM,CAAC,IAExE,EAAiB,EAAI;CAEzB,GAAG;EAAC;EAAU;EAAc;EAAY;CAAU,CAAC;CAEnD,IAAM,IAAiB,EAAM,kBAAkB;EAG7C,AAFA,EAAY,SAAS,eAAe;GAAE,UAAU;GAAU,OAAO;EAAM,CAAC,GACxE,EAAc,EAAI,GAClB,EAAiB,EAAK;CACxB,GAAG,CAAC,CAAC;CAIL,OACE,kBAAC,OAAD;EAAU;EAAK,WAAW,EAAG,YAAY,CAAS;YAAlD,CACE,kBAAC,OAAD;GACE,KAAK;GACL,WAAU;GACV,aAAU;GACV,OACE,IACI,EACE,WACE,OAAO,KAAc,WAAW,GAAG,EAAU,MAAM,EACvD,IACA,KAAA;aAVR;IAaG,EAAS,KAAK,MACb,EAAI,SAAS,SACX,kBAAC,GAAD;KAEE,SAAS;KACM;IAChB,GAHM,EAAI,EAGV,IAED,kBAAC,GAAD;KAEE,SAAS;KACF;KACP,UAAU;KACV,cAAc;IACf,GALM,EAAI,EAKV,CAEL;IACC,KACC,kBAAC,GAAD;KACE,OAAO;KACA;KACQ;IAChB,CAAA;IAEH,kBAAC,OAAD;KAAK,KAAK;KAAa,WAAU;IAAQ,CAAA;GACtC;MACL,kBAAC,GAAD,EAAA,UACG,CAAC,KAAc,KACd,kBAAC,GAAD,EAAoB,SAAS,EAAiB,CAAA,EAEjC,CAAA,CACd;;AAET,CAAC;AACD,EAAe,cAAc"}
|
package/dist/ai/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { useMotion as e } from "../_chunks/motion-provider.js";
|
|
3
|
+
import { cn as t } from "../ui/lib/utils.js";
|
|
4
4
|
import { AICommandProvider as n, useAICommand as r } from "./ai-command-provider.js";
|
|
5
5
|
import { CommandBar as i } from "./command-bar.js";
|
|
6
6
|
import { BlockTable as a, ConfirmBlock as o, DividerBlock as s, InfoBlock as c, LoadingBlock as l, StatRowBlock as u, SuccessBlock as d } from "../_chunks/success.js";
|
|
@@ -22,7 +22,7 @@ function O(e) {
|
|
|
22
22
|
}, [t, e]), b(t, (e) => `rotate(${e}, 16, 16)`);
|
|
23
23
|
}
|
|
24
24
|
var k = p.memo(function({ state: n = "idle", size: r = 20, className: i }) {
|
|
25
|
-
let { reducedMotion: a } =
|
|
25
|
+
let { reducedMotion: a } = e(), o = O(n), s = p.useId();
|
|
26
26
|
if (a) return /* @__PURE__ */ m("svg", {
|
|
27
27
|
viewBox: "0 0 32 32",
|
|
28
28
|
width: r,
|
|
@@ -52,7 +52,7 @@ var k = p.memo(function({ state: n = "idle", size: r = 20, className: i }) {
|
|
|
52
52
|
s3: S
|
|
53
53
|
};
|
|
54
54
|
return /* @__PURE__ */ m("span", {
|
|
55
|
-
className:
|
|
55
|
+
className: t("relative inline-flex items-center justify-center", i),
|
|
56
56
|
style: {
|
|
57
57
|
width: r,
|
|
58
58
|
height: r
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity-feed.d.ts","sourceRoot":"","sources":["../../src/composed/activity-feed.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"activity-feed.d.ts","sourceRoot":"","sources":["../../src/composed/activity-feed.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAO9B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAMrD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACxC,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC,SAAS,CAAA;IAChC,SAAS,EAAE,IAAI,GAAG,MAAM,CAAA;IACxB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,KAAK,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAA;IAC5D,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,iBAAkB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAC7E,KAAK,EAAE,YAAY,EAAE,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAA;IACvB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACzB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,+GAA+G;IAC/G,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,GAAG,SAAS,CAAA;CAChF;AAiBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,YAAY,EAAE,EACrB,MAAM,CAAC,EAAE,WAAW,GACnB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,YAAY,EAAE,CAAA;CAAE,EAAE,CA6C5C;AAsKD,QAAA,MAAM,YAAY,0FAmHjB,CAAA;AAGD,OAAO,EAAE,YAAY,EAAE,CAAA"}
|