@pactor-app/ui 1.44.0 → 1.46.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/dist/{chunk-SD2XSQIP.js → chunk-FU4P7CAM.js} +4 -0
- package/dist/{chunk-A6WUHUJL.js → chunk-JV2V4HCI.js} +1 -1
- package/dist/{chunk-3PQOJRJD.js → chunk-QB2RZXDD.js} +35 -2450
- package/dist/{chunk-T3TGKYAB.js → chunk-XA7J5SGA.js} +16 -121
- package/dist/components/index.cjs +39 -2524
- package/dist/components/index.d.cts +16 -846
- package/dist/components/index.d.ts +16 -846
- package/dist/components/index.js +7 -43
- package/dist/index.cjs +375 -2860
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +16 -52
- package/dist/layout/index.cjs +2 -0
- package/dist/layout/index.js +2 -2
- package/dist/ui/index.cjs +1138 -560
- package/dist/ui/index.d.cts +219 -16
- package/dist/ui/index.d.ts +219 -16
- package/dist/ui/index.js +721 -44
- package/package.json +10 -8
- package/src/theme-bridge.css +54 -0
- package/styles.css +87 -183
package/dist/index.cjs
CHANGED
|
@@ -33,20 +33,16 @@ __export(index_exports, {
|
|
|
33
33
|
Accordion: () => Accordion2,
|
|
34
34
|
AdminLayout: () => AdminLayout,
|
|
35
35
|
Affix: () => Affix,
|
|
36
|
-
AgentStatus: () => AgentStatus,
|
|
37
36
|
Alert: () => Alert2,
|
|
38
37
|
AlertDialog: () => AlertDialog2,
|
|
39
38
|
Anchor: () => Anchor,
|
|
40
|
-
ArtifactPanel: () => ArtifactPanel,
|
|
41
39
|
AspectRatio: () => AspectRatio2,
|
|
42
|
-
Attachment: () => Attachment,
|
|
43
40
|
Audio: () => Audio,
|
|
44
41
|
Avatar: () => Avatar2,
|
|
45
42
|
BackTop: () => BackTop,
|
|
46
43
|
Badge: () => Badge2,
|
|
47
44
|
BlankLayout: () => BlankLayout,
|
|
48
45
|
Breadcrumb: () => Breadcrumb2,
|
|
49
|
-
Bubble: () => Bubble2,
|
|
50
46
|
Button: () => Button2,
|
|
51
47
|
ButtonGroup: () => ButtonGroup2,
|
|
52
48
|
CONTROL_SIZE_AREA: () => CONTROL_SIZE_AREA,
|
|
@@ -60,12 +56,9 @@ __export(index_exports, {
|
|
|
60
56
|
Cascader: () => Cascader,
|
|
61
57
|
ChatInput: () => ChatInput,
|
|
62
58
|
ChatLayout: () => ChatLayout,
|
|
63
|
-
ChatMessage: () => ChatMessage,
|
|
64
|
-
ChatPage: () => ChatPage,
|
|
65
59
|
Checkbox: () => Checkbox2,
|
|
66
60
|
ChipFilter: () => ChipFilter,
|
|
67
61
|
ChipNode: () => ChipNode,
|
|
68
|
-
Citation: () => Citation,
|
|
69
62
|
ClearHoverButton: () => ClearHoverButton,
|
|
70
63
|
CodeBlock: () => CodeBlock,
|
|
71
64
|
Col: () => Col,
|
|
@@ -73,11 +66,9 @@ __export(index_exports, {
|
|
|
73
66
|
ColorPicker: () => ColorPicker,
|
|
74
67
|
Combobox: () => Combobox2,
|
|
75
68
|
Command: () => Command2,
|
|
76
|
-
Composer: () => Composer,
|
|
77
69
|
Container: () => Container,
|
|
78
70
|
Content: () => Content,
|
|
79
71
|
ContextMenu: () => ContextMenu2,
|
|
80
|
-
ConversationList: () => ConversationList,
|
|
81
72
|
DataTable: () => DataTable,
|
|
82
73
|
DatePicker: () => DatePicker,
|
|
83
74
|
Descriptions: () => Descriptions,
|
|
@@ -121,7 +112,6 @@ __export(index_exports, {
|
|
|
121
112
|
Menu: () => Menu2,
|
|
122
113
|
Menubar: () => Menubar2,
|
|
123
114
|
Message: () => Message,
|
|
124
|
-
MessageList: () => MessageList,
|
|
125
115
|
NavigationMenu: () => NavigationMenu2,
|
|
126
116
|
Notification: () => Notification,
|
|
127
117
|
NumberInput: () => NumberInput,
|
|
@@ -133,7 +123,6 @@ __export(index_exports, {
|
|
|
133
123
|
Popconfirm: () => Popconfirm,
|
|
134
124
|
Popover: () => Popover2,
|
|
135
125
|
Progress: () => Progress2,
|
|
136
|
-
Prompt: () => Prompt,
|
|
137
126
|
QRCode: () => QRCode,
|
|
138
127
|
RadioGroup: () => RadioGroup2,
|
|
139
128
|
RailTooltip: () => RailTooltip,
|
|
@@ -145,7 +134,6 @@ __export(index_exports, {
|
|
|
145
134
|
ScrollArea: () => ScrollArea2,
|
|
146
135
|
Segmented: () => Segmented,
|
|
147
136
|
Select: () => Select2,
|
|
148
|
-
Sender: () => Sender,
|
|
149
137
|
Separator: () => Separator2,
|
|
150
138
|
Sheet: () => Sheet2,
|
|
151
139
|
Sidebar: () => Sidebar,
|
|
@@ -158,21 +146,16 @@ __export(index_exports, {
|
|
|
158
146
|
Statistic: () => Statistic,
|
|
159
147
|
Status: () => Status,
|
|
160
148
|
Steps: () => Steps,
|
|
161
|
-
StepsPanel: () => StepsPanel,
|
|
162
|
-
StreamingText: () => StreamingText,
|
|
163
|
-
Suggestion: () => Suggestion,
|
|
164
149
|
Switch: () => Switch2,
|
|
165
150
|
Table: () => Table3,
|
|
166
151
|
Tabs: () => Tabs2,
|
|
167
152
|
Tag: () => Tag2,
|
|
168
153
|
Text: () => Text,
|
|
169
154
|
Textarea: () => Textarea2,
|
|
170
|
-
Thinking: () => Thinking,
|
|
171
155
|
TimePicker: () => TimePicker,
|
|
172
156
|
Timeline: () => Timeline,
|
|
173
157
|
Toggle: () => Toggle2,
|
|
174
158
|
ToggleGroup: () => ToggleGroup2,
|
|
175
|
-
ToolCall: () => ToolCall,
|
|
176
159
|
Tooltip: () => Tooltip2,
|
|
177
160
|
Tour: () => Tour,
|
|
178
161
|
Transfer: () => Transfer,
|
|
@@ -182,8 +165,6 @@ __export(index_exports, {
|
|
|
182
165
|
Upload: () => Upload2,
|
|
183
166
|
Video: () => Video2,
|
|
184
167
|
Watermark: () => Watermark,
|
|
185
|
-
Welcome: () => Welcome,
|
|
186
|
-
buildArtifactTree: () => buildArtifactTree,
|
|
187
168
|
builtinComponents: () => builtinComponents,
|
|
188
169
|
collectDefaultOpenKeys: () => collectDefaultOpenKeys,
|
|
189
170
|
createComponentRegistry: () => createComponentRegistry,
|
|
@@ -198,12 +179,13 @@ __export(index_exports, {
|
|
|
198
179
|
registerInteractionActions: () => registerInteractionActions,
|
|
199
180
|
resolveLayout: () => resolveLayout,
|
|
200
181
|
useFormContext: () => useFormContext,
|
|
182
|
+
useOptionalRenderer: () => useOptionalRenderer,
|
|
201
183
|
useSidebarDrawer: () => useSidebarDrawer
|
|
202
184
|
});
|
|
203
185
|
module.exports = __toCommonJS(index_exports);
|
|
204
186
|
|
|
205
187
|
// src/components/register.ts
|
|
206
|
-
var
|
|
188
|
+
var import_core2 = require("@pactor-app/core");
|
|
207
189
|
|
|
208
190
|
// src/components/components/Accordion/index.tsx
|
|
209
191
|
var import_runtime = require("@pactor-app/runtime");
|
|
@@ -521,6 +503,8 @@ var ICONS = {
|
|
|
521
503
|
"chart-column": import_lucide_react2.ChartColumn,
|
|
522
504
|
"layout-grid": import_lucide_react2.LayoutGrid,
|
|
523
505
|
"layout-template": import_lucide_react2.LayoutTemplate,
|
|
506
|
+
"maximize-2": import_lucide_react2.Maximize2,
|
|
507
|
+
"minimize-2": import_lucide_react2.Minimize2,
|
|
524
508
|
palette: import_lucide_react2.Palette,
|
|
525
509
|
paintbrush: import_lucide_react2.Paintbrush,
|
|
526
510
|
funnel: import_lucide_react2.Funnel,
|
|
@@ -3294,12 +3278,21 @@ function Textarea({
|
|
|
3294
3278
|
|
|
3295
3279
|
// src/components/components/ChatInput/index.tsx
|
|
3296
3280
|
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
3281
|
+
function useOptionalRenderer() {
|
|
3282
|
+
try {
|
|
3283
|
+
return (0, import_runtime13.useRenderer)();
|
|
3284
|
+
} catch {
|
|
3285
|
+
return null;
|
|
3286
|
+
}
|
|
3287
|
+
}
|
|
3297
3288
|
function ChatInput({
|
|
3298
3289
|
value,
|
|
3299
3290
|
placeholder,
|
|
3300
3291
|
disabled,
|
|
3301
3292
|
rows = 3,
|
|
3302
3293
|
hideSend,
|
|
3294
|
+
streaming = false,
|
|
3295
|
+
onStop,
|
|
3303
3296
|
toolbarStart,
|
|
3304
3297
|
toolbarEnd,
|
|
3305
3298
|
header,
|
|
@@ -3310,14 +3303,14 @@ function ChatInput({
|
|
|
3310
3303
|
className,
|
|
3311
3304
|
style
|
|
3312
3305
|
}) {
|
|
3313
|
-
const
|
|
3306
|
+
const renderer = useOptionalRenderer();
|
|
3314
3307
|
const controlled = value !== void 0;
|
|
3315
3308
|
const [draft, setDraft] = (0, import_react14.useState)("");
|
|
3316
3309
|
const { t } = (0, import_runtime12.useI18n)();
|
|
3317
3310
|
const text = controlled ? value : draft;
|
|
3318
3311
|
const canSubmit = !disabled && text.trim() !== "";
|
|
3319
3312
|
const customField = field !== void 0 && field !== null;
|
|
3320
|
-
const renderSlot = (slot) => (0, import_react14.isValidElement)(slot) || typeof slot !== "object" || slot === null ? slot : renderChildren([slot]);
|
|
3313
|
+
const renderSlot = (slot) => (0, import_react14.isValidElement)(slot) || typeof slot !== "object" || slot === null ? slot : renderer?.renderChildren([slot]) ?? null;
|
|
3321
3314
|
const composingRef = (0, import_react14.useRef)(false);
|
|
3322
3315
|
const handleChange = (next) => {
|
|
3323
3316
|
if (!controlled) {
|
|
@@ -3377,11 +3370,11 @@ function ChatInput({
|
|
|
3377
3370
|
{
|
|
3378
3371
|
type: "button",
|
|
3379
3372
|
size: "icon",
|
|
3380
|
-
"aria-label": t("pactor.chatInput.send"),
|
|
3381
|
-
disabled: !canSubmit,
|
|
3382
|
-
onClick: submit,
|
|
3373
|
+
"aria-label": streaming ? t("pactor.chatInput.stop") : t("pactor.chatInput.send"),
|
|
3374
|
+
disabled: streaming ? false : !canSubmit,
|
|
3375
|
+
onClick: streaming ? () => onStop?.() : submit,
|
|
3383
3376
|
className: "size-8 rounded-full",
|
|
3384
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_lucide_react13.ArrowUp, {})
|
|
3377
|
+
children: streaming ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_lucide_react13.Square, {}) : /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_lucide_react13.ArrowUp, {})
|
|
3385
3378
|
}
|
|
3386
3379
|
)
|
|
3387
3380
|
] }) : null,
|
|
@@ -7519,7 +7512,7 @@ function useSidebarDrawer() {
|
|
|
7519
7512
|
return null;
|
|
7520
7513
|
}
|
|
7521
7514
|
}
|
|
7522
|
-
function
|
|
7515
|
+
function useOptionalRenderer2() {
|
|
7523
7516
|
try {
|
|
7524
7517
|
return (0, import_runtime31.useRenderer)();
|
|
7525
7518
|
} catch {
|
|
@@ -7527,7 +7520,7 @@ function useOptionalRenderer() {
|
|
|
7527
7520
|
}
|
|
7528
7521
|
}
|
|
7529
7522
|
function SidebarContentSlot({ content }) {
|
|
7530
|
-
const renderer =
|
|
7523
|
+
const renderer = useOptionalRenderer2();
|
|
7531
7524
|
if (renderer !== null && typeof content === "object" && content !== null && !("$$typeof" in content) && "type" in content) {
|
|
7532
7525
|
return /* @__PURE__ */ (0, import_jsx_runtime108.jsx)(import_jsx_runtime108.Fragment, { children: renderer.renderChildren([content]) });
|
|
7533
7526
|
}
|
|
@@ -11010,16 +11003,26 @@ var tabsListVariants = (0, import_class_variance_authority7.cva)(
|
|
|
11010
11003
|
default: "h-9 rounded-lg bg-muted p-[3px]",
|
|
11011
11004
|
// line:页签栏通栏(下划线轨道占满容器宽),触发器自然宽度靠左排列
|
|
11012
11005
|
line: "h-auto w-full justify-start gap-1 rounded-none border-b border-border bg-transparent p-0"
|
|
11006
|
+
},
|
|
11007
|
+
/** 尺寸(对齐 Button 的 size 语义):sm 经 compoundVariants 仅压缩胶囊变体 */
|
|
11008
|
+
size: {
|
|
11009
|
+
default: "",
|
|
11010
|
+
sm: ""
|
|
11013
11011
|
}
|
|
11014
11012
|
},
|
|
11013
|
+
compoundVariants: [
|
|
11014
|
+
{ variant: "default", size: "sm", class: "h-8" }
|
|
11015
|
+
],
|
|
11015
11016
|
defaultVariants: {
|
|
11016
|
-
variant: "default"
|
|
11017
|
+
variant: "default",
|
|
11018
|
+
size: "default"
|
|
11017
11019
|
}
|
|
11018
11020
|
}
|
|
11019
11021
|
);
|
|
11020
11022
|
function TabsList({
|
|
11021
11023
|
className,
|
|
11022
11024
|
variant,
|
|
11025
|
+
size,
|
|
11023
11026
|
...props
|
|
11024
11027
|
}) {
|
|
11025
11028
|
return /* @__PURE__ */ (0, import_jsx_runtime153.jsx)(
|
|
@@ -11027,7 +11030,8 @@ function TabsList({
|
|
|
11027
11030
|
{
|
|
11028
11031
|
"data-slot": "tabs-list",
|
|
11029
11032
|
"data-variant": variant ?? "default",
|
|
11030
|
-
|
|
11033
|
+
"data-size": size ?? "default",
|
|
11034
|
+
className: cn(tabsListVariants({ variant, size }), className),
|
|
11031
11035
|
...props
|
|
11032
11036
|
}
|
|
11033
11037
|
);
|
|
@@ -11048,6 +11052,8 @@ function TabsTrigger({
|
|
|
11048
11052
|
//(叠在 List 的底边轨道上),无底色/圆角/阴影;通栏 List 下取消
|
|
11049
11053
|
// flex-1 拉伸,触发器保持自然宽度
|
|
11050
11054
|
"group-data-[variant=line]/tabs-list:-mb-px group-data-[variant=line]/tabs-list:h-9 group-data-[variant=line]/tabs-list:flex-none group-data-[variant=line]/tabs-list:rounded-none group-data-[variant=line]/tabs-list:border-x-0 group-data-[variant=line]/tabs-list:border-t-0 group-data-[variant=line]/tabs-list:border-b-2 group-data-[variant=line]/tabs-list:py-1.5 group-data-[variant=line]/tabs-list:text-muted-foreground group-data-[variant=line]/tabs-list:data-active:border-b-primary group-data-[variant=line]/tabs-list:data-active:text-foreground",
|
|
11055
|
+
// size=sm:小字号 + 收紧纵向 padding(高度随 List h-8 自动收缩)
|
|
11056
|
+
"group-data-[size=sm]/tabs-list:py-0.5 group-data-[size=sm]/tabs-list:text-xs",
|
|
11051
11057
|
className
|
|
11052
11058
|
),
|
|
11053
11059
|
...props
|
|
@@ -12978,2687 +12984,214 @@ function Watermark({
|
|
|
12978
12984
|
);
|
|
12979
12985
|
}
|
|
12980
12986
|
|
|
12981
|
-
// src/components/
|
|
12982
|
-
var
|
|
12983
|
-
|
|
12984
|
-
|
|
12985
|
-
|
|
12986
|
-
|
|
12987
|
-
|
|
12987
|
+
// src/components/register.ts
|
|
12988
|
+
var builtinComponents = {
|
|
12989
|
+
Page,
|
|
12990
|
+
Grid,
|
|
12991
|
+
Row,
|
|
12992
|
+
Col,
|
|
12993
|
+
// 循环渲染:行模板(原始 DSL children)由 For 逐项渲染并注入 { row, rowIndex } 作用域
|
|
12994
|
+
For: { component: For, withScope: true },
|
|
12995
|
+
Flex,
|
|
12996
|
+
Card: Card2,
|
|
12997
|
+
Button: Button2,
|
|
12998
|
+
Alert: Alert2,
|
|
12999
|
+
Statistic,
|
|
13000
|
+
Tabs: Tabs2,
|
|
13001
|
+
Table: Table3,
|
|
13002
|
+
Form,
|
|
13003
|
+
Input: Input2,
|
|
13004
|
+
NumberInput,
|
|
13005
|
+
Select: Select2,
|
|
13006
|
+
// Layout 需要原始 DSL 子树做方向推导(含 Sider 判定),以 withScope 注册
|
|
13007
|
+
Layout: { component: Layout, withScope: true },
|
|
13008
|
+
Header,
|
|
13009
|
+
Sider,
|
|
13010
|
+
Content,
|
|
13011
|
+
Footer,
|
|
13012
|
+
Menu: Menu2,
|
|
13013
|
+
Link: Link2,
|
|
13014
|
+
Text,
|
|
13015
|
+
// 展示类扩展组件
|
|
13016
|
+
Badge: Badge2,
|
|
13017
|
+
Avatar: Avatar2,
|
|
13018
|
+
Skeleton: Skeleton2,
|
|
13019
|
+
Separator: Separator2,
|
|
13020
|
+
Kbd: Kbd2,
|
|
13021
|
+
Spinner: Spinner2,
|
|
13022
|
+
Empty: Empty2,
|
|
13023
|
+
AspectRatio: AspectRatio2,
|
|
13024
|
+
Progress: Progress2,
|
|
13025
|
+
// 表单类扩展组件
|
|
13026
|
+
Textarea: Textarea2,
|
|
13027
|
+
Checkbox: Checkbox2,
|
|
13028
|
+
ChipFilter,
|
|
13029
|
+
ChipNode,
|
|
13030
|
+
RadioGroup: RadioGroup2,
|
|
13031
|
+
Switch: Switch2,
|
|
13032
|
+
Slider: Slider2,
|
|
13033
|
+
Label: Label2,
|
|
13034
|
+
Field: Field2,
|
|
13035
|
+
ChatInput,
|
|
13036
|
+
// 导航类扩展组件
|
|
13037
|
+
Breadcrumb: Breadcrumb2,
|
|
13038
|
+
Pagination: Pagination2,
|
|
13039
|
+
Menubar: Menubar2,
|
|
13040
|
+
NavigationMenu: NavigationMenu2,
|
|
13041
|
+
DropdownMenu: DropdownMenu2,
|
|
13042
|
+
ContextMenu: ContextMenu2,
|
|
13043
|
+
// 反馈与弹层类扩展组件
|
|
13044
|
+
Dialog: Dialog2,
|
|
13045
|
+
AlertDialog: AlertDialog2,
|
|
13046
|
+
Drawer: Drawer2,
|
|
13047
|
+
Sheet: Sheet2,
|
|
13048
|
+
Popover: Popover2,
|
|
13049
|
+
Sonner,
|
|
13050
|
+
Accordion: Accordion2,
|
|
13051
|
+
Collapsible: Collapsible2,
|
|
13052
|
+
Tooltip: Tooltip2,
|
|
13053
|
+
HoverCard: HoverCard2,
|
|
13054
|
+
// 复合类扩展组件(第三批)
|
|
13055
|
+
Calendar: Calendar3,
|
|
13056
|
+
DatePicker,
|
|
13057
|
+
InputOTP: InputOTP2,
|
|
13058
|
+
Combobox: Combobox2,
|
|
13059
|
+
Carousel: Carousel2,
|
|
13060
|
+
Command: Command2,
|
|
13061
|
+
Resizable,
|
|
13062
|
+
ScrollArea: ScrollArea2,
|
|
13063
|
+
Toggle: Toggle2,
|
|
13064
|
+
ToggleGroup: ToggleGroup2,
|
|
13065
|
+
ButtonGroup: ButtonGroup2,
|
|
13066
|
+
InputGroup: InputGroup2,
|
|
13067
|
+
Item: Item2,
|
|
13068
|
+
Typography: Typography2,
|
|
13069
|
+
// 页面级组合类扩展组件(第四批)
|
|
13070
|
+
Sidebar,
|
|
13071
|
+
DataTable,
|
|
13072
|
+
// 图标(lucide 白名单)
|
|
13073
|
+
Icon,
|
|
13074
|
+
// 业务刚需类扩展组件(第五批:数据录入 / 数据展示 / 反馈)
|
|
13075
|
+
Rate,
|
|
13076
|
+
TimePicker,
|
|
13077
|
+
ColorPicker,
|
|
13078
|
+
Upload: Upload2,
|
|
13079
|
+
TreeSelect,
|
|
13080
|
+
Cascader,
|
|
13081
|
+
Transfer,
|
|
13082
|
+
Mentions,
|
|
13083
|
+
List: List2,
|
|
13084
|
+
Tree,
|
|
13085
|
+
Descriptions,
|
|
13086
|
+
Timeline,
|
|
13087
|
+
Image: Image2,
|
|
13088
|
+
QRCode,
|
|
13089
|
+
Segmented,
|
|
13090
|
+
Message,
|
|
13091
|
+
Notification,
|
|
13092
|
+
Popconfirm,
|
|
13093
|
+
Result,
|
|
13094
|
+
LoadingOverlay,
|
|
13095
|
+
Watermark,
|
|
13096
|
+
Tour,
|
|
13097
|
+
// 基础补齐类扩展组件(第六批:通用 / 布局 / 导航)
|
|
13098
|
+
Tag: Tag2,
|
|
13099
|
+
Status,
|
|
13100
|
+
Space,
|
|
13101
|
+
Container,
|
|
13102
|
+
Steps,
|
|
13103
|
+
Anchor,
|
|
13104
|
+
BackTop,
|
|
13105
|
+
Affix,
|
|
13106
|
+
// 媒体与内容类扩展组件(第七批)
|
|
13107
|
+
ImageViewer,
|
|
13108
|
+
Gallery,
|
|
13109
|
+
Video: Video2,
|
|
13110
|
+
Audio,
|
|
13111
|
+
FilePreview,
|
|
13112
|
+
DocumentPreview,
|
|
13113
|
+
RichText,
|
|
13114
|
+
Markdown: import_markdown2.MarkdownDslComponent,
|
|
13115
|
+
CodeBlock,
|
|
13116
|
+
DiffViewer,
|
|
13117
|
+
JSONViewer
|
|
12988
13118
|
};
|
|
12989
|
-
function
|
|
12990
|
-
const
|
|
12991
|
-
|
|
12992
|
-
|
|
12993
|
-
|
|
12994
|
-
|
|
12995
|
-
|
|
12996
|
-
|
|
12997
|
-
|
|
12998
|
-
children: [
|
|
12999
|
-
/* @__PURE__ */ (0, import_jsx_runtime174.jsx)("span", { className: cn(meta.className, meta.spin && "animate-spin motion-reduce:animate-none"), children: /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(Icon, { name: meta.icon, size: "sm" }) }),
|
|
13000
|
-
text ? /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("span", { "data-slot": "agent-status-text", children: text }) : null,
|
|
13001
|
-
elapsed !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("span", { "data-slot": "agent-status-elapsed", className: "text-xs text-muted-foreground", children: [
|
|
13002
|
-
"\u5DF2\u7528\u65F6 ",
|
|
13003
|
-
elapsed,
|
|
13004
|
-
"s"
|
|
13005
|
-
] }) : null
|
|
13006
|
-
]
|
|
13007
|
-
}
|
|
13008
|
-
);
|
|
13119
|
+
function registerBuiltinComponents(registry) {
|
|
13120
|
+
for (const [type, component] of Object.entries(builtinComponents)) {
|
|
13121
|
+
registry.register(type, component);
|
|
13122
|
+
}
|
|
13123
|
+
}
|
|
13124
|
+
function createComponentRegistry() {
|
|
13125
|
+
const registry = new import_core2.Registry("ComponentRegistry");
|
|
13126
|
+
registerBuiltinComponents(registry);
|
|
13127
|
+
return registry;
|
|
13009
13128
|
}
|
|
13010
13129
|
|
|
13011
|
-
// src/
|
|
13012
|
-
|
|
13013
|
-
|
|
13014
|
-
|
|
13015
|
-
|
|
13016
|
-
|
|
13017
|
-
|
|
13018
|
-
|
|
13019
|
-
|
|
13020
|
-
|
|
13021
|
-
|
|
13022
|
-
|
|
13023
|
-
|
|
13024
|
-
"ico"
|
|
13025
|
-
];
|
|
13026
|
-
function resolveArtifactFileType(artifact) {
|
|
13027
|
-
const declared = artifact.fileType?.trim().toLowerCase().replace(/^\./, "");
|
|
13028
|
-
if (declared) {
|
|
13029
|
-
return declared;
|
|
13030
|
-
}
|
|
13031
|
-
const match = /\.([A-Za-z0-9]+)$/.exec(artifact.title.trim());
|
|
13032
|
-
return match ? match[1].toLowerCase() : null;
|
|
13033
|
-
}
|
|
13034
|
-
function isImageArtifact(artifact) {
|
|
13035
|
-
const ext = resolveArtifactFileType(artifact);
|
|
13036
|
-
return ext !== null && ARTIFACT_IMAGE_EXTENSIONS.includes(ext);
|
|
13037
|
-
}
|
|
13038
|
-
var ARTIFACT_ICON_BY_EXTENSION = {
|
|
13039
|
-
// 表格数据
|
|
13040
|
-
csv: "table",
|
|
13041
|
-
tsv: "table",
|
|
13042
|
-
xls: "table",
|
|
13043
|
-
xlsx: "table",
|
|
13044
|
-
// 数据 / 数据库
|
|
13045
|
-
json: "database",
|
|
13046
|
-
sql: "database",
|
|
13047
|
-
// 脚本
|
|
13048
|
-
sh: "terminal",
|
|
13049
|
-
bash: "terminal",
|
|
13050
|
-
zsh: "terminal",
|
|
13051
|
-
// 代码 / 配置
|
|
13052
|
-
js: "code",
|
|
13053
|
-
mjs: "code",
|
|
13054
|
-
cjs: "code",
|
|
13055
|
-
jsx: "code",
|
|
13056
|
-
ts: "code",
|
|
13057
|
-
mts: "code",
|
|
13058
|
-
cts: "code",
|
|
13059
|
-
tsx: "code",
|
|
13060
|
-
py: "code",
|
|
13061
|
-
rb: "code",
|
|
13062
|
-
go: "code",
|
|
13063
|
-
rs: "code",
|
|
13064
|
-
java: "code",
|
|
13065
|
-
kt: "code",
|
|
13066
|
-
c: "code",
|
|
13067
|
-
h: "code",
|
|
13068
|
-
cc: "code",
|
|
13069
|
-
cpp: "code",
|
|
13070
|
-
cs: "code",
|
|
13071
|
-
swift: "code",
|
|
13072
|
-
php: "code",
|
|
13073
|
-
css: "code",
|
|
13074
|
-
scss: "code",
|
|
13075
|
-
less: "code",
|
|
13076
|
-
html: "code",
|
|
13077
|
-
vue: "code",
|
|
13078
|
-
svelte: "code",
|
|
13079
|
-
yaml: "code",
|
|
13080
|
-
yml: "code",
|
|
13081
|
-
toml: "code",
|
|
13082
|
-
xml: "code",
|
|
13083
|
-
// 文档 / 文本
|
|
13084
|
-
md: "file-text",
|
|
13085
|
-
markdown: "file-text",
|
|
13086
|
-
mdx: "file-text",
|
|
13087
|
-
txt: "file-text",
|
|
13088
|
-
text: "file-text",
|
|
13089
|
-
log: "file-text",
|
|
13090
|
-
rst: "file-text",
|
|
13091
|
-
pdf: "file-text",
|
|
13092
|
-
doc: "file-text",
|
|
13093
|
-
docx: "file-text"
|
|
13094
|
-
};
|
|
13095
|
-
function resolveArtifactIconName(artifact) {
|
|
13096
|
-
const ext = resolveArtifactFileType(artifact);
|
|
13097
|
-
if (ext !== null) {
|
|
13098
|
-
if (ARTIFACT_IMAGE_EXTENSIONS.includes(ext)) {
|
|
13099
|
-
return "image";
|
|
13100
|
-
}
|
|
13101
|
-
const name = ARTIFACT_ICON_BY_EXTENSION[ext];
|
|
13102
|
-
if (name !== void 0) {
|
|
13103
|
-
return name;
|
|
13104
|
-
}
|
|
13105
|
-
}
|
|
13106
|
-
if (artifact.kind === "code") {
|
|
13107
|
-
return "code";
|
|
13108
|
-
}
|
|
13109
|
-
if (artifact.kind === "dsl") {
|
|
13110
|
-
return "layout-grid";
|
|
13111
|
-
}
|
|
13112
|
-
return ext === null ? "file-text" : "file";
|
|
13113
|
-
}
|
|
13114
|
-
function buildArtifactTree(artifacts) {
|
|
13115
|
-
const root = { name: "", path: "", children: [] };
|
|
13116
|
-
for (const artifact of artifacts) {
|
|
13117
|
-
const segments = artifact.id.split("/").filter(Boolean);
|
|
13118
|
-
let node = root;
|
|
13119
|
-
for (let i = 0; i < segments.length - 1; i++) {
|
|
13120
|
-
const path = segments.slice(0, i + 1).join("/");
|
|
13121
|
-
let child = node.children.find(
|
|
13122
|
-
(item) => item.path === path && item.artifact === void 0
|
|
13123
|
-
);
|
|
13124
|
-
if (!child) {
|
|
13125
|
-
child = { name: segments[i], path, children: [] };
|
|
13126
|
-
node.children.push(child);
|
|
13130
|
+
// src/layout/admin/menu-chain.ts
|
|
13131
|
+
function findMenuChain(registry, menuId) {
|
|
13132
|
+
const walk = (menus, ancestors) => {
|
|
13133
|
+
for (const menu of menus) {
|
|
13134
|
+
const chain = [...ancestors, menu];
|
|
13135
|
+
if (menu.id === menuId) {
|
|
13136
|
+
return chain;
|
|
13137
|
+
}
|
|
13138
|
+
if (menu.children !== void 0) {
|
|
13139
|
+
const hit = walk(menu.children, chain);
|
|
13140
|
+
if (hit !== null) {
|
|
13141
|
+
return hit;
|
|
13142
|
+
}
|
|
13127
13143
|
}
|
|
13128
|
-
node = child;
|
|
13129
|
-
}
|
|
13130
|
-
node.children.push({
|
|
13131
|
-
name: artifact.title,
|
|
13132
|
-
path: artifact.id,
|
|
13133
|
-
artifact,
|
|
13134
|
-
children: []
|
|
13135
|
-
});
|
|
13136
|
-
}
|
|
13137
|
-
const sortLevel = (nodes) => {
|
|
13138
|
-
nodes.sort((a, b) => {
|
|
13139
|
-
const dirDelta = Number(b.artifact === void 0) - Number(a.artifact === void 0);
|
|
13140
|
-
return dirDelta !== 0 ? dirDelta : a.name.localeCompare(b.name);
|
|
13141
|
-
});
|
|
13142
|
-
for (const item of nodes) {
|
|
13143
|
-
sortLevel(item.children);
|
|
13144
13144
|
}
|
|
13145
|
+
return null;
|
|
13145
13146
|
};
|
|
13146
|
-
|
|
13147
|
-
return root.children;
|
|
13147
|
+
return walk(registry.tree(), []) ?? [];
|
|
13148
13148
|
}
|
|
13149
13149
|
|
|
13150
|
-
// src/
|
|
13151
|
-
|
|
13152
|
-
|
|
13153
|
-
|
|
13154
|
-
|
|
13155
|
-
|
|
13156
|
-
|
|
13157
|
-
|
|
13158
|
-
|
|
13159
|
-
|
|
13160
|
-
|
|
13161
|
-
}
|
|
13162
|
-
const ext = resolveArtifactFileType(artifact) ?? KIND_EXTENSIONS[artifact.kind];
|
|
13163
|
-
return `${title}.${ext}`;
|
|
13164
|
-
}
|
|
13165
|
-
function dataUrlToBlob(dataUrl) {
|
|
13166
|
-
const comma = dataUrl.indexOf(",");
|
|
13167
|
-
const meta = dataUrl.slice(0, comma);
|
|
13168
|
-
const payload = dataUrl.slice(comma + 1);
|
|
13169
|
-
const mime = /^data:([^;,]+)/.exec(meta)?.[1] ?? "application/octet-stream";
|
|
13170
|
-
if (meta.includes(";base64")) {
|
|
13171
|
-
const binary = atob(payload);
|
|
13172
|
-
const bytes = new Uint8Array(binary.length);
|
|
13173
|
-
for (let i = 0; i < binary.length; i++) {
|
|
13174
|
-
bytes[i] = binary.charCodeAt(i);
|
|
13175
|
-
}
|
|
13176
|
-
return new Blob([bytes], { type: mime });
|
|
13177
|
-
}
|
|
13178
|
-
return new Blob([decodeURIComponent(payload)], { type: mime });
|
|
13179
|
-
}
|
|
13180
|
-
function isRemoteUrl(raw) {
|
|
13181
|
-
return /^https?:\/\//.test(raw.trim());
|
|
13182
|
-
}
|
|
13183
|
-
function buildArtifactBlob(artifact) {
|
|
13184
|
-
if (artifact.kind === "dsl" && typeof artifact.content === "object") {
|
|
13185
|
-
return new Blob([JSON.stringify(artifact.content, null, 2)], {
|
|
13186
|
-
type: "application/json"
|
|
13187
|
-
});
|
|
13188
|
-
}
|
|
13189
|
-
const raw = String(artifact.content);
|
|
13190
|
-
if (isImageArtifact(artifact)) {
|
|
13191
|
-
const trimmed = raw.trim();
|
|
13192
|
-
if (trimmed.startsWith("data:")) {
|
|
13193
|
-
return dataUrlToBlob(trimmed);
|
|
13194
|
-
}
|
|
13195
|
-
if (trimmed.startsWith("<svg") || trimmed.startsWith("<?xml")) {
|
|
13196
|
-
return new Blob([raw], { type: "image/svg+xml" });
|
|
13197
|
-
}
|
|
13198
|
-
if (isRemoteUrl(trimmed)) {
|
|
13199
|
-
return null;
|
|
13150
|
+
// src/layout/admin/menu-items.ts
|
|
13151
|
+
function collectDefaultOpenKeys(registry, activeMenuId) {
|
|
13152
|
+
const keys = [];
|
|
13153
|
+
const walk = (menus) => {
|
|
13154
|
+
for (const menu of menus) {
|
|
13155
|
+
if (menu.type === "group" && menu.defaultOpen === true) {
|
|
13156
|
+
keys.push(menu.id);
|
|
13157
|
+
}
|
|
13158
|
+
if (menu.children !== void 0) {
|
|
13159
|
+
walk(menu.children);
|
|
13160
|
+
}
|
|
13200
13161
|
}
|
|
13201
|
-
}
|
|
13202
|
-
|
|
13203
|
-
|
|
13204
|
-
|
|
13205
|
-
|
|
13206
|
-
|
|
13207
|
-
const url = URL.createObjectURL(blob);
|
|
13208
|
-
const anchor = document.createElement("a");
|
|
13209
|
-
anchor.href = url;
|
|
13210
|
-
anchor.download = filename;
|
|
13211
|
-
document.body.appendChild(anchor);
|
|
13212
|
-
anchor.click();
|
|
13213
|
-
anchor.remove();
|
|
13214
|
-
setTimeout(() => URL.revokeObjectURL(url), 1e3);
|
|
13215
|
-
}
|
|
13216
|
-
async function downloadArtifact(artifact) {
|
|
13217
|
-
const filename = resolveArtifactFilename(artifact);
|
|
13218
|
-
const raw = String(artifact.content ?? "").trim();
|
|
13219
|
-
if (isImageArtifact(artifact) && isRemoteUrl(raw)) {
|
|
13220
|
-
try {
|
|
13221
|
-
const response = await fetch(raw);
|
|
13222
|
-
if (!response.ok) {
|
|
13223
|
-
throw new Error(`HTTP ${response.status}`);
|
|
13162
|
+
};
|
|
13163
|
+
walk(registry.tree());
|
|
13164
|
+
if (activeMenuId !== void 0) {
|
|
13165
|
+
for (const menu of findMenuChain(registry, activeMenuId)) {
|
|
13166
|
+
if (menu.type === "group" && !keys.includes(menu.id)) {
|
|
13167
|
+
keys.push(menu.id);
|
|
13224
13168
|
}
|
|
13225
|
-
saveBlob(await response.blob(), filename);
|
|
13226
|
-
return;
|
|
13227
|
-
} catch {
|
|
13228
|
-
window.open(raw, "_blank", "noopener");
|
|
13229
|
-
return;
|
|
13230
13169
|
}
|
|
13231
13170
|
}
|
|
13232
|
-
|
|
13233
|
-
if (blob) {
|
|
13234
|
-
saveBlob(blob, filename);
|
|
13235
|
-
}
|
|
13171
|
+
return keys;
|
|
13236
13172
|
}
|
|
13237
13173
|
|
|
13238
|
-
// src/
|
|
13239
|
-
var
|
|
13174
|
+
// src/layout/admin/AdminLayout.tsx
|
|
13175
|
+
var import_permission = require("@pactor-app/permission");
|
|
13176
|
+
var import_router = require("@pactor-app/router");
|
|
13240
13177
|
var import_runtime50 = require("@pactor-app/runtime");
|
|
13178
|
+
var import_react62 = require("react");
|
|
13179
|
+
|
|
13180
|
+
// src/layout/admin/use-media-query.ts
|
|
13241
13181
|
var import_react61 = require("react");
|
|
13242
|
-
var
|
|
13243
|
-
|
|
13244
|
-
|
|
13245
|
-
|
|
13246
|
-
|
|
13247
|
-
|
|
13248
|
-
|
|
13249
|
-
|
|
13250
|
-
|
|
13251
|
-
|
|
13252
|
-
|
|
13253
|
-
deniedType ? `\uFF1A${deniedType}` : ""
|
|
13254
|
-
]
|
|
13255
|
-
}
|
|
13182
|
+
var BREAKPOINT_PX = {
|
|
13183
|
+
xs: 480,
|
|
13184
|
+
sm: 576,
|
|
13185
|
+
md: 768,
|
|
13186
|
+
lg: 992,
|
|
13187
|
+
xl: 1200,
|
|
13188
|
+
xxl: 1600
|
|
13189
|
+
};
|
|
13190
|
+
function useMediaQuery(query) {
|
|
13191
|
+
const [matches, setMatches] = (0, import_react61.useState)(
|
|
13192
|
+
() => typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia(query).matches : false
|
|
13256
13193
|
);
|
|
13257
|
-
|
|
13258
|
-
function guardArtifactDsl(node, registry) {
|
|
13259
|
-
const type = node.type ?? "(reference)";
|
|
13260
|
-
if (type !== ARTIFACT_DENIED_TYPE && !registry.has(type)) {
|
|
13261
|
-
return {
|
|
13262
|
-
type: ARTIFACT_DENIED_TYPE,
|
|
13263
|
-
props: { deniedType: type }
|
|
13264
|
-
};
|
|
13265
|
-
}
|
|
13266
|
-
if (node.children === void 0) {
|
|
13267
|
-
return node;
|
|
13268
|
-
}
|
|
13269
|
-
if (!Array.isArray(node.children)) {
|
|
13270
|
-
return {
|
|
13271
|
-
type: ARTIFACT_DENIED_TYPE,
|
|
13272
|
-
props: { deniedType: `${type}(remote)` }
|
|
13273
|
-
};
|
|
13274
|
-
}
|
|
13275
|
-
if (node.children.length === 0) {
|
|
13276
|
-
return node;
|
|
13277
|
-
}
|
|
13278
|
-
return {
|
|
13279
|
-
...node,
|
|
13280
|
-
// 数组中混排的引用元素同样无法静态过白名单:替换为受控占位
|
|
13281
|
-
children: node.children.map(
|
|
13282
|
-
(child) => (0, import_core2.isDslSourceRef)(child) ? { type: ARTIFACT_DENIED_TYPE, props: { deniedType: "(remote)" } } : guardArtifactDsl(child, registry)
|
|
13283
|
-
)
|
|
13284
|
-
};
|
|
13285
|
-
}
|
|
13286
|
-
function useArtifactPreviewRuntime(safeRegistry, user) {
|
|
13287
|
-
return (0, import_react61.useMemo)(() => {
|
|
13288
|
-
if (!safeRegistry) {
|
|
13289
|
-
return void 0;
|
|
13290
|
-
}
|
|
13291
|
-
const components = new import_core2.Registry("ArtifactPreviewRegistry");
|
|
13292
|
-
components.register(ARTIFACT_DENIED_TYPE, ArtifactDenied);
|
|
13293
|
-
for (const name of safeRegistry.list()) {
|
|
13294
|
-
components.register(name, safeRegistry.get(name));
|
|
13295
|
-
}
|
|
13296
|
-
const context = (0, import_runtime50.createRuntimeContext)({ components, user });
|
|
13297
|
-
(0, import_runtime50.registerBuiltinActions)(context.actions);
|
|
13298
|
-
return { context, engine: new import_runtime50.ActionEngine(context) };
|
|
13299
|
-
}, [safeRegistry, user]);
|
|
13300
|
-
}
|
|
13301
|
-
var ArtifactDslGuard = class extends import_react61.Component {
|
|
13302
|
-
constructor() {
|
|
13303
|
-
super(...arguments);
|
|
13304
|
-
this.state = { failed: false };
|
|
13305
|
-
}
|
|
13306
|
-
static getDerivedStateFromError() {
|
|
13307
|
-
return { failed: true };
|
|
13308
|
-
}
|
|
13309
|
-
componentDidCatch(error) {
|
|
13310
|
-
console.warn("[@pactor-app/ui] DSL \u4EA7\u7269\u6E32\u67D3\u5931\u8D25\uFF0C\u5DF2\u964D\u7EA7\u5C55\u793A", error);
|
|
13311
|
-
}
|
|
13312
|
-
render() {
|
|
13313
|
-
return this.state.failed ? /* @__PURE__ */ (0, import_jsx_runtime175.jsx)(
|
|
13314
|
-
"div",
|
|
13315
|
-
{
|
|
13316
|
-
"data-slot": "artifact-denied",
|
|
13317
|
-
className: "rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground",
|
|
13318
|
-
children: "DSL \u4EA7\u7269\u6E32\u67D3\u5931\u8D25\uFF0C\u5DF2\u964D\u7EA7\u5C55\u793A"
|
|
13319
|
-
}
|
|
13320
|
-
) : this.props.children;
|
|
13321
|
-
}
|
|
13322
|
-
};
|
|
13323
|
-
function ArtifactDslNode({ node }) {
|
|
13324
|
-
const { renderChildren } = (0, import_runtime50.useRenderer)();
|
|
13325
|
-
return /* @__PURE__ */ (0, import_jsx_runtime175.jsx)(import_jsx_runtime175.Fragment, { children: renderChildren([node]) });
|
|
13326
|
-
}
|
|
13327
|
-
function ArtifactDslContent({
|
|
13328
|
-
content,
|
|
13329
|
-
runtime,
|
|
13330
|
-
style
|
|
13331
|
-
}) {
|
|
13332
|
-
const node = typeof content === "object" && content !== null && !Array.isArray(content) && typeof content.type === "string" ? content : void 0;
|
|
13333
|
-
if (!node || !runtime) {
|
|
13334
|
-
return /* @__PURE__ */ (0, import_jsx_runtime175.jsx)(
|
|
13335
|
-
"div",
|
|
13336
|
-
{
|
|
13337
|
-
"data-slot": "artifact-denied",
|
|
13338
|
-
className: "rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground",
|
|
13339
|
-
style,
|
|
13340
|
-
children: node ? "DSL \u9884\u89C8\u4E0D\u53EF\u7528\uFF08\u672A\u6CE8\u5165 Safe Registry\uFF09" : "DSL \u4EA7\u7269\u5185\u5BB9\u65E0\u6548"
|
|
13341
|
-
}
|
|
13342
|
-
);
|
|
13343
|
-
}
|
|
13344
|
-
const guarded = guardArtifactDsl(node, runtime.context.components);
|
|
13345
|
-
return /* @__PURE__ */ (0, import_jsx_runtime175.jsx)(import_runtime50.DslRenderer, { context: runtime.context, engine: runtime.engine, children: /* @__PURE__ */ (0, import_jsx_runtime175.jsx)(ArtifactDslGuard, { children: /* @__PURE__ */ (0, import_jsx_runtime175.jsx)(ArtifactDslNode, { node: guarded }) }) });
|
|
13346
|
-
}
|
|
13347
|
-
|
|
13348
|
-
// src/components/chat/ArtifactPanel/index.tsx
|
|
13349
|
-
var import_jsx_runtime176 = require("react/jsx-runtime");
|
|
13350
|
-
function ArtifactKindIcon({ artifact }) {
|
|
13351
|
-
return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(Icon, { name: resolveArtifactIconName(artifact), size: 13 });
|
|
13352
|
-
}
|
|
13353
|
-
function ArtifactListView({
|
|
13354
|
-
nodes,
|
|
13355
|
-
activeId,
|
|
13356
|
-
onSelect
|
|
13357
|
-
}) {
|
|
13358
|
-
return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("ul", { "data-slot": "artifact-panel-list", className: "flex flex-col gap-0.5", children: nodes.map((node) => /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
|
|
13359
|
-
ArtifactTreeRow,
|
|
13360
|
-
{
|
|
13361
|
-
node,
|
|
13362
|
-
activeId,
|
|
13363
|
-
onSelect
|
|
13364
|
-
},
|
|
13365
|
-
node.path
|
|
13366
|
-
)) });
|
|
13367
|
-
}
|
|
13368
|
-
function ArtifactTreeRow({
|
|
13369
|
-
node,
|
|
13370
|
-
activeId,
|
|
13371
|
-
onSelect
|
|
13372
|
-
}) {
|
|
13373
|
-
const [open, setOpen] = (0, import_react62.useState)(true);
|
|
13374
|
-
if (node.artifact) {
|
|
13375
|
-
return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime176.jsxs)(
|
|
13376
|
-
"button",
|
|
13377
|
-
{
|
|
13378
|
-
type: "button",
|
|
13379
|
-
"data-slot": "artifact-panel-list-item",
|
|
13380
|
-
"data-active": node.artifact.id === activeId,
|
|
13381
|
-
className: "flex w-full cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm hover:bg-accent data-[active=true]:bg-accent",
|
|
13382
|
-
onClick: () => onSelect?.(node.artifact.id),
|
|
13383
|
-
children: [
|
|
13384
|
-
/* @__PURE__ */ (0, import_jsx_runtime176.jsx)(ArtifactKindIcon, { artifact: node.artifact }),
|
|
13385
|
-
/* @__PURE__ */ (0, import_jsx_runtime176.jsx)("span", { className: "min-w-0 flex-1 truncate", children: node.artifact.title }),
|
|
13386
|
-
/* @__PURE__ */ (0, import_jsx_runtime176.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: node.artifact.kind })
|
|
13387
|
-
]
|
|
13388
|
-
}
|
|
13389
|
-
) });
|
|
13390
|
-
}
|
|
13391
|
-
return /* @__PURE__ */ (0, import_jsx_runtime176.jsxs)("li", { children: [
|
|
13392
|
-
/* @__PURE__ */ (0, import_jsx_runtime176.jsxs)(
|
|
13393
|
-
"button",
|
|
13394
|
-
{
|
|
13395
|
-
type: "button",
|
|
13396
|
-
"data-slot": "artifact-panel-list-folder",
|
|
13397
|
-
"aria-expanded": open,
|
|
13398
|
-
"data-open": open,
|
|
13399
|
-
className: "flex w-full cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm hover:bg-accent",
|
|
13400
|
-
onClick: () => setOpen((value) => !value),
|
|
13401
|
-
children: [
|
|
13402
|
-
/* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
|
|
13403
|
-
"span",
|
|
13404
|
-
{
|
|
13405
|
-
className: "inline-flex transition-transform data-[open=true]:rotate-90",
|
|
13406
|
-
"data-open": open,
|
|
13407
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(Icon, { name: "chevron-right", size: 12 })
|
|
13408
|
-
}
|
|
13409
|
-
),
|
|
13410
|
-
/* @__PURE__ */ (0, import_jsx_runtime176.jsx)(Icon, { name: "folder", size: 13 }),
|
|
13411
|
-
/* @__PURE__ */ (0, import_jsx_runtime176.jsx)("span", { className: "min-w-0 flex-1 truncate", children: node.name })
|
|
13412
|
-
]
|
|
13413
|
-
}
|
|
13414
|
-
),
|
|
13415
|
-
open && /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("div", { className: "pl-4", children: /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
|
|
13416
|
-
ArtifactListView,
|
|
13417
|
-
{
|
|
13418
|
-
nodes: node.children,
|
|
13419
|
-
activeId,
|
|
13420
|
-
onSelect
|
|
13421
|
-
}
|
|
13422
|
-
) })
|
|
13423
|
-
] });
|
|
13424
|
-
}
|
|
13425
|
-
function ArtifactImageContent({ artifact }) {
|
|
13426
|
-
const raw = String(artifact.content).trim();
|
|
13427
|
-
const src = raw.startsWith("<svg") || raw.startsWith("<?xml") ? `data:image/svg+xml;utf8,${encodeURIComponent(raw)}` : raw;
|
|
13428
|
-
return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("div", { "data-slot": "artifact-panel-image", className: "flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("img", { src, alt: artifact.title, className: "max-w-full rounded-md" }) });
|
|
13429
|
-
}
|
|
13430
|
-
function ArtifactContent({
|
|
13431
|
-
artifact,
|
|
13432
|
-
runtime,
|
|
13433
|
-
viewers
|
|
13434
|
-
}) {
|
|
13435
|
-
const ext = resolveArtifactFileType(artifact);
|
|
13436
|
-
const custom = (ext ? viewers?.[ext] : void 0) ?? viewers?.[artifact.kind];
|
|
13437
|
-
if (custom) {
|
|
13438
|
-
return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(import_jsx_runtime176.Fragment, { children: custom(artifact) });
|
|
13439
|
-
}
|
|
13440
|
-
if (isImageArtifact(artifact)) {
|
|
13441
|
-
return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(ArtifactImageContent, { artifact });
|
|
13442
|
-
}
|
|
13443
|
-
switch (artifact.kind) {
|
|
13444
|
-
case "markdown":
|
|
13445
|
-
return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(import_markdown2.MarkdownDslComponent, { content: String(artifact.content) });
|
|
13446
|
-
case "code":
|
|
13447
|
-
return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
|
|
13448
|
-
CodeBlock,
|
|
13449
|
-
{
|
|
13450
|
-
code: String(artifact.content),
|
|
13451
|
-
language: artifact.language
|
|
13452
|
-
}
|
|
13453
|
-
);
|
|
13454
|
-
case "text":
|
|
13455
|
-
return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
|
|
13456
|
-
"pre",
|
|
13457
|
-
{
|
|
13458
|
-
"data-slot": "artifact-panel-text",
|
|
13459
|
-
className: "text-sm break-words whitespace-pre-wrap",
|
|
13460
|
-
children: String(artifact.content)
|
|
13461
|
-
}
|
|
13462
|
-
);
|
|
13463
|
-
case "dsl":
|
|
13464
|
-
return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(ArtifactDslContent, { content: artifact.content, runtime });
|
|
13465
|
-
default:
|
|
13466
|
-
return null;
|
|
13467
|
-
}
|
|
13468
|
-
}
|
|
13469
|
-
function ArtifactPanel({
|
|
13470
|
-
artifact,
|
|
13471
|
-
artifacts,
|
|
13472
|
-
activeArtifactId,
|
|
13473
|
-
onSelectArtifact,
|
|
13474
|
-
title = "\u4EA7\u7269",
|
|
13475
|
-
emptyText = "\u6682\u65E0\u4EA7\u7269",
|
|
13476
|
-
onClose,
|
|
13477
|
-
onDownload,
|
|
13478
|
-
safeRegistry,
|
|
13479
|
-
user,
|
|
13480
|
-
artifactViewers,
|
|
13481
|
-
className,
|
|
13482
|
-
style
|
|
13483
|
-
}) {
|
|
13484
|
-
const runtime = useArtifactPreviewRuntime(safeRegistry, user);
|
|
13485
|
-
const [view, setView] = (0, import_react62.useState)("content");
|
|
13486
|
-
const activeId = activeArtifactId ?? artifact?.id;
|
|
13487
|
-
(0, import_react62.useEffect)(() => {
|
|
13488
|
-
setView("content");
|
|
13489
|
-
}, [activeId]);
|
|
13490
|
-
const hasArtifacts = artifacts !== void 0 && artifacts.length > 0;
|
|
13491
|
-
const headerTitle = view === "list" ? "\u4EA7\u7269\u76EE\u5F55" : artifact?.title ?? title;
|
|
13492
|
-
return /* @__PURE__ */ (0, import_jsx_runtime176.jsxs)(
|
|
13493
|
-
"aside",
|
|
13494
|
-
{
|
|
13495
|
-
"data-slot": "artifact-panel",
|
|
13496
|
-
"data-kind": artifact?.kind,
|
|
13497
|
-
className: cn("flex h-full min-w-0 flex-col", className),
|
|
13498
|
-
style,
|
|
13499
|
-
children: [
|
|
13500
|
-
/* @__PURE__ */ (0, import_jsx_runtime176.jsxs)("div", { className: "flex shrink-0 items-center gap-1 border-b border-border px-2 py-2.5", children: [
|
|
13501
|
-
hasArtifacts ? /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
|
|
13502
|
-
Button2,
|
|
13503
|
-
{
|
|
13504
|
-
icon: "list",
|
|
13505
|
-
variant: "text",
|
|
13506
|
-
tooltip: view === "list" ? "\u8FD4\u56DE\u5185\u5BB9" : "\u4EA7\u7269\u76EE\u5F55",
|
|
13507
|
-
onClick: () => setView((value) => value === "list" ? "content" : "list")
|
|
13508
|
-
}
|
|
13509
|
-
) : null,
|
|
13510
|
-
hasArtifacts ? /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
|
|
13511
|
-
DropdownMenu2,
|
|
13512
|
-
{
|
|
13513
|
-
items: artifacts.map((item) => ({
|
|
13514
|
-
label: item.title,
|
|
13515
|
-
value: item.id,
|
|
13516
|
-
icon: resolveArtifactIconName(item)
|
|
13517
|
-
})),
|
|
13518
|
-
onSelect: (id) => onSelectArtifact?.(id),
|
|
13519
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime176.jsxs)(
|
|
13520
|
-
"span",
|
|
13521
|
-
{
|
|
13522
|
-
"data-slot": "artifact-panel-menu-trigger",
|
|
13523
|
-
className: "flex min-w-0 cursor-pointer items-center gap-1 rounded-md px-1.5 py-1 text-sm font-medium hover:bg-accent",
|
|
13524
|
-
children: [
|
|
13525
|
-
view !== "list" && artifact ? /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(ArtifactKindIcon, { artifact }) : null,
|
|
13526
|
-
/* @__PURE__ */ (0, import_jsx_runtime176.jsx)("span", { className: "truncate", children: headerTitle }),
|
|
13527
|
-
/* @__PURE__ */ (0, import_jsx_runtime176.jsx)(Icon, { name: "chevron-down", size: 12 })
|
|
13528
|
-
]
|
|
13529
|
-
}
|
|
13530
|
-
)
|
|
13531
|
-
}
|
|
13532
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("span", { className: "min-w-0 flex-1 truncate px-1.5 text-sm font-medium", children: headerTitle }),
|
|
13533
|
-
view !== "list" && artifact ? /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("span", { className: "shrink-0 rounded-md bg-accent px-1.5 py-0.5 text-xs text-muted-foreground", children: artifact.kind }) : null,
|
|
13534
|
-
/* @__PURE__ */ (0, import_jsx_runtime176.jsx)("span", { className: "flex-1" }),
|
|
13535
|
-
artifact ? /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
|
|
13536
|
-
Button2,
|
|
13537
|
-
{
|
|
13538
|
-
icon: "download",
|
|
13539
|
-
variant: "text",
|
|
13540
|
-
tooltip: "\u4E0B\u8F7D\u4EA7\u7269",
|
|
13541
|
-
className: "px-2",
|
|
13542
|
-
onClick: () => onDownload ? onDownload(artifact) : void downloadArtifact(artifact)
|
|
13543
|
-
}
|
|
13544
|
-
) : null,
|
|
13545
|
-
/* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
|
|
13546
|
-
Button2,
|
|
13547
|
-
{
|
|
13548
|
-
icon: "x",
|
|
13549
|
-
variant: "text",
|
|
13550
|
-
tooltip: "\u6536\u8D77\u4EA7\u7269\u533A",
|
|
13551
|
-
className: "px-2",
|
|
13552
|
-
onClick: () => onClose?.()
|
|
13553
|
-
}
|
|
13554
|
-
)
|
|
13555
|
-
] }),
|
|
13556
|
-
/* @__PURE__ */ (0, import_jsx_runtime176.jsx)("div", { className: "scrollbar-subtle min-h-0 flex-1 overflow-auto p-4", children: view === "list" && artifacts !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
|
|
13557
|
-
ArtifactListView,
|
|
13558
|
-
{
|
|
13559
|
-
nodes: buildArtifactTree(artifacts),
|
|
13560
|
-
activeId,
|
|
13561
|
-
onSelect: onSelectArtifact
|
|
13562
|
-
}
|
|
13563
|
-
) : artifact ? /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
|
|
13564
|
-
ArtifactContent,
|
|
13565
|
-
{
|
|
13566
|
-
artifact,
|
|
13567
|
-
runtime,
|
|
13568
|
-
viewers: artifactViewers
|
|
13569
|
-
}
|
|
13570
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime176.jsx)("p", { className: "text-sm text-muted-foreground", children: emptyText }) })
|
|
13571
|
-
]
|
|
13572
|
-
}
|
|
13573
|
-
);
|
|
13574
|
-
}
|
|
13575
|
-
|
|
13576
|
-
// src/components/chat/Attachment/index.tsx
|
|
13577
|
-
var import_jsx_runtime177 = require("react/jsx-runtime");
|
|
13578
|
-
var kindIcon2 = { image: "image", text: "file-text", video: "video", audio: "music", other: "file" };
|
|
13579
|
-
function formatSize3(bytes) {
|
|
13580
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
13581
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
13582
|
-
return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
13583
|
-
}
|
|
13584
|
-
function Attachment({ items = [], onRemove, onRetry, className, style }) {
|
|
13585
|
-
return /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("div", { "data-slot": "attachment", className: cn("flex flex-wrap gap-2", className), style, children: items.map((item, index) => {
|
|
13586
|
-
const key = item.id ?? index;
|
|
13587
|
-
const kind = inferKind(item.name, item.fileType);
|
|
13588
|
-
const status = item.status ?? "done";
|
|
13589
|
-
return /* @__PURE__ */ (0, import_jsx_runtime177.jsxs)(
|
|
13590
|
-
"div",
|
|
13591
|
-
{
|
|
13592
|
-
"data-slot": "attachment-item",
|
|
13593
|
-
"data-status": status,
|
|
13594
|
-
className: "flex w-56 flex-col rounded-md border border-border px-2 py-1.5",
|
|
13595
|
-
children: [
|
|
13596
|
-
/* @__PURE__ */ (0, import_jsx_runtime177.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
13597
|
-
/* @__PURE__ */ (0, import_jsx_runtime177.jsx)("span", { className: "shrink-0 text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(Icon, { name: kindIcon2[kind], size: "sm" }) }),
|
|
13598
|
-
/* @__PURE__ */ (0, import_jsx_runtime177.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm", children: item.name }),
|
|
13599
|
-
status === "uploading" ? /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("span", { className: "shrink-0 animate-spin text-muted-foreground motion-reduce:animate-none", children: /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(Icon, { name: "loader-circle", size: "sm" }) }) : null,
|
|
13600
|
-
status === "error" && onRetry ? /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(
|
|
13601
|
-
"button",
|
|
13602
|
-
{
|
|
13603
|
-
type: "button",
|
|
13604
|
-
"data-slot": "attachment-retry",
|
|
13605
|
-
"aria-label": `\u91CD\u8BD5 ${item.name}`,
|
|
13606
|
-
className: "shrink-0 text-destructive hover:opacity-80",
|
|
13607
|
-
onClick: () => onRetry(key),
|
|
13608
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(Icon, { name: "refresh-ccw", size: "sm" })
|
|
13609
|
-
}
|
|
13610
|
-
) : null,
|
|
13611
|
-
onRemove ? /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(
|
|
13612
|
-
"button",
|
|
13613
|
-
{
|
|
13614
|
-
type: "button",
|
|
13615
|
-
"data-slot": "attachment-remove",
|
|
13616
|
-
"aria-label": `\u79FB\u9664 ${item.name}`,
|
|
13617
|
-
className: "shrink-0 text-muted-foreground hover:text-foreground",
|
|
13618
|
-
onClick: () => onRemove(key),
|
|
13619
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(Icon, { name: "x", size: "sm" })
|
|
13620
|
-
}
|
|
13621
|
-
) : null
|
|
13622
|
-
] }),
|
|
13623
|
-
/* @__PURE__ */ (0, import_jsx_runtime177.jsxs)("div", { className: "mt-0.5 flex items-center gap-1.5 pl-5 text-xs", children: [
|
|
13624
|
-
item.fileSize !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("span", { className: "text-muted-foreground", children: formatSize3(item.fileSize) }) : null,
|
|
13625
|
-
status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("span", { className: "text-destructive", children: "\u4E0A\u4F20\u5931\u8D25" }) : null
|
|
13626
|
-
] }),
|
|
13627
|
-
status === "uploading" && item.progress !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("div", { "data-slot": "attachment-progress", className: "mt-1 ml-5 h-1 overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("div", { className: "h-full bg-primary transition-[width]", style: { width: `${item.progress}%` } }) }) : null
|
|
13628
|
-
]
|
|
13629
|
-
},
|
|
13630
|
-
key
|
|
13631
|
-
);
|
|
13632
|
-
}) });
|
|
13633
|
-
}
|
|
13634
|
-
|
|
13635
|
-
// src/ui/bubble.tsx
|
|
13636
|
-
var React7 = __toESM(require("react"), 1);
|
|
13637
|
-
var import_class_variance_authority10 = require("class-variance-authority");
|
|
13638
|
-
var import_jsx_runtime178 = require("react/jsx-runtime");
|
|
13639
|
-
var bubbleVariants = (0, import_class_variance_authority10.cva)(
|
|
13640
|
-
"group/bubble relative flex w-fit max-w-[80%] min-w-0 flex-col gap-1 group-data-[align=end]/message:self-end data-[align=end]:self-end data-[variant=ghost]:max-w-full",
|
|
13641
|
-
{
|
|
13642
|
-
variants: {
|
|
13643
|
-
variant: {
|
|
13644
|
-
default: "*:data-[slot=bubble-content]:bg-primary *:data-[slot=bubble-content]:text-primary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-primary/80",
|
|
13645
|
-
secondary: "*:data-[slot=bubble-content]:bg-secondary *:data-[slot=bubble-content]:text-secondary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)]",
|
|
13646
|
-
muted: "*:data-[slot=bubble-content]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--muted),var(--foreground)_5%)]",
|
|
13647
|
-
tinted: "*:data-[slot=bubble-content]:bg-(--bubble-background) *:data-[slot=bubble-content]:text-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-(--bubble-hover-background)",
|
|
13648
|
-
outline: "*:data-[slot=bubble-content]:border-border *:data-[slot=bubble-content]:bg-card [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-input/30",
|
|
13649
|
-
ghost: "border-none *:data-[slot=bubble-content]:rounded-none *:data-[slot=bubble-content]:bg-transparent *:data-[slot=bubble-content]:p-0 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted/50",
|
|
13650
|
-
destructive: "*:data-[slot=bubble-content]:bg-destructive/10 *:data-[slot=bubble-content]:text-destructive dark:*:data-[slot=bubble-content]:bg-destructive/20 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/20 dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/30"
|
|
13651
|
-
}
|
|
13652
|
-
},
|
|
13653
|
-
defaultVariants: {
|
|
13654
|
-
variant: "default"
|
|
13655
|
-
}
|
|
13656
|
-
}
|
|
13657
|
-
);
|
|
13658
|
-
function Bubble({
|
|
13659
|
-
variant = "default",
|
|
13660
|
-
align = "start",
|
|
13661
|
-
className,
|
|
13662
|
-
...props
|
|
13663
|
-
}) {
|
|
13664
|
-
return /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(
|
|
13665
|
-
"div",
|
|
13666
|
-
{
|
|
13667
|
-
"data-slot": "bubble",
|
|
13668
|
-
"data-variant": variant,
|
|
13669
|
-
"data-align": align,
|
|
13670
|
-
className: cn(bubbleVariants({ variant }), className),
|
|
13671
|
-
...props
|
|
13672
|
-
}
|
|
13673
|
-
);
|
|
13674
|
-
}
|
|
13675
|
-
function BubbleContent({
|
|
13676
|
-
asChild = false,
|
|
13677
|
-
className,
|
|
13678
|
-
children,
|
|
13679
|
-
...props
|
|
13680
|
-
}) {
|
|
13681
|
-
const cls = cn(
|
|
13682
|
-
"w-fit max-w-full min-w-0 overflow-hidden rounded-xl border border-transparent px-3 py-2 text-sm leading-relaxed wrap-break-word group-data-[align=end]/bubble:self-end [button]:text-left [button,a]:transition-colors [button,a]:outline-none [button,a]:focus-visible:border-ring [button,a]:focus-visible:ring-3 [button,a]:focus-visible:ring-ring/50",
|
|
13683
|
-
className
|
|
13684
|
-
);
|
|
13685
|
-
if (asChild && React7.isValidElement(children)) {
|
|
13686
|
-
return React7.cloneElement(children, {
|
|
13687
|
-
"data-slot": "bubble-content",
|
|
13688
|
-
className: cn(cls, children.props.className),
|
|
13689
|
-
...props
|
|
13690
|
-
});
|
|
13691
|
-
}
|
|
13692
|
-
return /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(
|
|
13693
|
-
"div",
|
|
13694
|
-
{
|
|
13695
|
-
"data-slot": "bubble-content",
|
|
13696
|
-
className: cls,
|
|
13697
|
-
...props,
|
|
13698
|
-
children
|
|
13699
|
-
}
|
|
13700
|
-
);
|
|
13701
|
-
}
|
|
13702
|
-
var bubbleReactionsVariants = (0, import_class_variance_authority10.cva)(
|
|
13703
|
-
"absolute z-10 flex w-fit shrink-0 items-center justify-center gap-1 rounded-full bg-muted px-1.5 py-0.5 text-sm ring-3 ring-card has-[button]:p-0",
|
|
13704
|
-
{
|
|
13705
|
-
variants: {
|
|
13706
|
-
side: {
|
|
13707
|
-
top: "top-0 -translate-y-3/4",
|
|
13708
|
-
bottom: "bottom-0 translate-y-3/4"
|
|
13709
|
-
},
|
|
13710
|
-
align: {
|
|
13711
|
-
start: "left-3",
|
|
13712
|
-
end: "right-3"
|
|
13713
|
-
}
|
|
13714
|
-
},
|
|
13715
|
-
defaultVariants: {
|
|
13716
|
-
side: "bottom",
|
|
13717
|
-
align: "end"
|
|
13718
|
-
}
|
|
13719
|
-
}
|
|
13720
|
-
);
|
|
13721
|
-
|
|
13722
|
-
// src/components/chat/Bubble/index.tsx
|
|
13723
|
-
var import_jsx_runtime179 = require("react/jsx-runtime");
|
|
13724
|
-
function Bubble2({ align = "start", variant = "muted", className, style, children }) {
|
|
13725
|
-
return /* @__PURE__ */ (0, import_jsx_runtime179.jsx)(Bubble, { variant, align, className, style, children: /* @__PURE__ */ (0, import_jsx_runtime179.jsx)(BubbleContent, { children }) });
|
|
13726
|
-
}
|
|
13727
|
-
|
|
13728
|
-
// src/components/chat/Sender/index.tsx
|
|
13729
|
-
var import_jsx_runtime180 = require("react/jsx-runtime");
|
|
13730
|
-
function Sender({ name, avatar, avatarText, role, time, align = "start", className, style }) {
|
|
13731
|
-
return /* @__PURE__ */ (0, import_jsx_runtime180.jsxs)(
|
|
13732
|
-
"div",
|
|
13733
|
-
{
|
|
13734
|
-
"data-slot": "sender",
|
|
13735
|
-
className: cn("flex items-center gap-2", align === "end" && "flex-row-reverse", className),
|
|
13736
|
-
style,
|
|
13737
|
-
children: [
|
|
13738
|
-
/* @__PURE__ */ (0, import_jsx_runtime180.jsx)(Avatar2, { src: avatar, fallback: avatarText ?? name?.slice(0, 1) ?? "?", className: "size-7" }),
|
|
13739
|
-
/* @__PURE__ */ (0, import_jsx_runtime180.jsxs)("div", { className: cn("flex min-w-0 items-baseline gap-1.5", align === "end" && "flex-row-reverse"), children: [
|
|
13740
|
-
name ? /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("span", { "data-slot": "sender-name", className: "truncate text-sm font-medium", children: name }) : null,
|
|
13741
|
-
role ? /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("span", { "data-slot": "sender-role", className: "shrink-0 text-xs text-muted-foreground", children: role }) : null,
|
|
13742
|
-
time ? /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("span", { "data-slot": "sender-time", className: "shrink-0 text-xs text-muted-foreground", children: time }) : null
|
|
13743
|
-
] })
|
|
13744
|
-
]
|
|
13745
|
-
}
|
|
13746
|
-
);
|
|
13747
|
-
}
|
|
13748
|
-
|
|
13749
|
-
// src/components/chat/StreamingText/index.tsx
|
|
13750
|
-
var import_react63 = require("react");
|
|
13751
|
-
var import_jsx_runtime181 = require("react/jsx-runtime");
|
|
13752
|
-
function StreamingText({ content = "", streaming, typing, speed = 2, className, style }) {
|
|
13753
|
-
const [revealed, setRevealed] = (0, import_react63.useState)(typing ? 0 : content.length);
|
|
13754
|
-
(0, import_react63.useEffect)(() => {
|
|
13755
|
-
if (!typing) {
|
|
13756
|
-
setRevealed(content.length);
|
|
13757
|
-
return;
|
|
13758
|
-
}
|
|
13759
|
-
setRevealed(0);
|
|
13760
|
-
const timer = window.setInterval(() => {
|
|
13761
|
-
setRevealed((value) => {
|
|
13762
|
-
if (value >= content.length) {
|
|
13763
|
-
window.clearInterval(timer);
|
|
13764
|
-
return value;
|
|
13765
|
-
}
|
|
13766
|
-
return Math.min(content.length, value + speed);
|
|
13767
|
-
});
|
|
13768
|
-
}, 24);
|
|
13769
|
-
return () => window.clearInterval(timer);
|
|
13770
|
-
}, [content, typing, speed]);
|
|
13771
|
-
const typingDone = !typing || revealed >= content.length;
|
|
13772
|
-
const showCursor = streaming || typing && !typingDone;
|
|
13773
|
-
return /* @__PURE__ */ (0, import_jsx_runtime181.jsxs)("span", { "data-slot": "streaming-text", className: cn("whitespace-pre-wrap", className), style, children: [
|
|
13774
|
-
typing ? content.slice(0, revealed) : content,
|
|
13775
|
-
showCursor ? /* @__PURE__ */ (0, import_jsx_runtime181.jsx)(
|
|
13776
|
-
"span",
|
|
13777
|
-
{
|
|
13778
|
-
"data-slot": "streaming-text-cursor",
|
|
13779
|
-
"aria-hidden": "true",
|
|
13780
|
-
className: "ml-0.5 inline-block animate-pulse text-primary motion-reduce:animate-none",
|
|
13781
|
-
children: "\u258D"
|
|
13782
|
-
}
|
|
13783
|
-
) : null
|
|
13784
|
-
] });
|
|
13785
|
-
}
|
|
13786
|
-
|
|
13787
|
-
// src/components/chat/Thinking/index.tsx
|
|
13788
|
-
var import_react64 = require("react");
|
|
13789
|
-
var import_jsx_runtime182 = require("react/jsx-runtime");
|
|
13790
|
-
function Thinking({
|
|
13791
|
-
content,
|
|
13792
|
-
status = "thinking",
|
|
13793
|
-
title,
|
|
13794
|
-
expanded,
|
|
13795
|
-
defaultExpanded,
|
|
13796
|
-
onToggle,
|
|
13797
|
-
className,
|
|
13798
|
-
style
|
|
13799
|
-
}) {
|
|
13800
|
-
const [innerExpanded, setInnerExpanded] = (0, import_react64.useState)(defaultExpanded ?? status === "thinking");
|
|
13801
|
-
const isExpanded = expanded ?? innerExpanded;
|
|
13802
|
-
const resolvedTitle = title ?? (status === "thinking" ? "\u601D\u8003\u4E2D\u2026" : "\u601D\u8003\u5B8C\u6210");
|
|
13803
|
-
const toggle = () => {
|
|
13804
|
-
if (expanded === void 0) {
|
|
13805
|
-
setInnerExpanded(!isExpanded);
|
|
13806
|
-
}
|
|
13807
|
-
onToggle?.(!isExpanded);
|
|
13808
|
-
};
|
|
13809
|
-
return /* @__PURE__ */ (0, import_jsx_runtime182.jsxs)(
|
|
13810
|
-
"div",
|
|
13811
|
-
{
|
|
13812
|
-
"data-slot": "thinking",
|
|
13813
|
-
"data-status": status,
|
|
13814
|
-
className: cn("w-full", className),
|
|
13815
|
-
style,
|
|
13816
|
-
children: [
|
|
13817
|
-
/* @__PURE__ */ (0, import_jsx_runtime182.jsxs)(
|
|
13818
|
-
"button",
|
|
13819
|
-
{
|
|
13820
|
-
type: "button",
|
|
13821
|
-
"data-slot": "thinking-trigger",
|
|
13822
|
-
"aria-expanded": isExpanded,
|
|
13823
|
-
className: "flex w-full cursor-pointer items-center gap-2 py-1 text-left text-sm",
|
|
13824
|
-
onClick: toggle,
|
|
13825
|
-
children: [
|
|
13826
|
-
/* @__PURE__ */ (0, import_jsx_runtime182.jsx)("span", { className: cn("text-muted-foreground", status === "thinking" && "animate-pulse motion-reduce:animate-none"), children: /* @__PURE__ */ (0, import_jsx_runtime182.jsx)(Icon, { name: "brain", size: "sm" }) }),
|
|
13827
|
-
/* @__PURE__ */ (0, import_jsx_runtime182.jsx)("span", { "data-slot": "thinking-title", className: "text-muted-foreground", children: resolvedTitle }),
|
|
13828
|
-
/* @__PURE__ */ (0, import_jsx_runtime182.jsx)("span", { className: "text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime182.jsx)(Icon, { name: isExpanded ? "chevron-down" : "chevron-right", size: "sm" }) })
|
|
13829
|
-
]
|
|
13830
|
-
}
|
|
13831
|
-
),
|
|
13832
|
-
isExpanded && content ? /* @__PURE__ */ (0, import_jsx_runtime182.jsx)(
|
|
13833
|
-
"div",
|
|
13834
|
-
{
|
|
13835
|
-
"data-slot": "thinking-content",
|
|
13836
|
-
className: "py-1 pl-6 text-sm whitespace-pre-wrap text-muted-foreground",
|
|
13837
|
-
children: content
|
|
13838
|
-
}
|
|
13839
|
-
) : null
|
|
13840
|
-
]
|
|
13841
|
-
}
|
|
13842
|
-
);
|
|
13843
|
-
}
|
|
13844
|
-
|
|
13845
|
-
// src/components/chat/ToolCall/index.tsx
|
|
13846
|
-
var import_react65 = require("react");
|
|
13847
|
-
var import_jsx_runtime183 = require("react/jsx-runtime");
|
|
13848
|
-
var statusIcon3 = {
|
|
13849
|
-
running: { icon: "loader-circle", className: "text-info", spin: true },
|
|
13850
|
-
done: { icon: "circle-check", className: "text-success" },
|
|
13851
|
-
error: { icon: "circle-x", className: "text-destructive" }
|
|
13852
|
-
};
|
|
13853
|
-
function renderValue(value) {
|
|
13854
|
-
if (value === void 0 || value === null) return "";
|
|
13855
|
-
if (typeof value === "string") return value;
|
|
13856
|
-
try {
|
|
13857
|
-
return JSON.stringify(value, null, 2);
|
|
13858
|
-
} catch {
|
|
13859
|
-
return String(value);
|
|
13860
|
-
}
|
|
13861
|
-
}
|
|
13862
|
-
function ToolCall({ name, params, status = "done", result, durationMs, defaultExpanded, className, style }) {
|
|
13863
|
-
const [expanded, setExpanded] = (0, import_react65.useState)(defaultExpanded ?? status === "running");
|
|
13864
|
-
const meta = statusIcon3[status];
|
|
13865
|
-
const paramsText = renderValue(params);
|
|
13866
|
-
const hasDetail = Boolean(paramsText) || Boolean(result);
|
|
13867
|
-
const headerInner = /* @__PURE__ */ (0, import_jsx_runtime183.jsxs)(import_jsx_runtime183.Fragment, { children: [
|
|
13868
|
-
/* @__PURE__ */ (0, import_jsx_runtime183.jsx)("span", { className: "shrink-0 text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime183.jsx)(Icon, { name: "terminal", size: "sm" }) }),
|
|
13869
|
-
/* @__PURE__ */ (0, import_jsx_runtime183.jsx)("span", { "data-slot": "tool-call-name", className: "min-w-0 truncate font-medium", children: name ?? "\u5DE5\u5177\u8C03\u7528" }),
|
|
13870
|
-
/* @__PURE__ */ (0, import_jsx_runtime183.jsx)("span", { className: cn("shrink-0", meta.className, meta.spin && "animate-spin motion-reduce:animate-none"), children: /* @__PURE__ */ (0, import_jsx_runtime183.jsx)(Icon, { name: meta.icon, size: "sm" }) }),
|
|
13871
|
-
durationMs !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime183.jsxs)("span", { className: "shrink-0 text-xs text-muted-foreground", children: [
|
|
13872
|
-
(durationMs / 1e3).toFixed(1),
|
|
13873
|
-
"s"
|
|
13874
|
-
] }) : null,
|
|
13875
|
-
hasDetail ? /* @__PURE__ */ (0, import_jsx_runtime183.jsx)("span", { className: "shrink-0 text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime183.jsx)(Icon, { name: expanded ? "chevron-down" : "chevron-right", size: "sm" }) }) : null
|
|
13876
|
-
] });
|
|
13877
|
-
return /* @__PURE__ */ (0, import_jsx_runtime183.jsxs)(
|
|
13878
|
-
"div",
|
|
13879
|
-
{
|
|
13880
|
-
"data-slot": "tool-call",
|
|
13881
|
-
"data-status": status,
|
|
13882
|
-
className: cn("w-full", className),
|
|
13883
|
-
style,
|
|
13884
|
-
children: [
|
|
13885
|
-
hasDetail ? /* @__PURE__ */ (0, import_jsx_runtime183.jsx)(
|
|
13886
|
-
"button",
|
|
13887
|
-
{
|
|
13888
|
-
type: "button",
|
|
13889
|
-
"data-slot": "tool-call-trigger",
|
|
13890
|
-
"aria-expanded": expanded,
|
|
13891
|
-
className: "flex w-full cursor-pointer items-center gap-2 py-1 text-left text-sm",
|
|
13892
|
-
onClick: () => setExpanded((value) => !value),
|
|
13893
|
-
children: headerInner
|
|
13894
|
-
}
|
|
13895
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime183.jsx)(
|
|
13896
|
-
"div",
|
|
13897
|
-
{
|
|
13898
|
-
"data-slot": "tool-call-trigger",
|
|
13899
|
-
className: "flex w-full items-center gap-2 py-1 text-left text-sm",
|
|
13900
|
-
children: headerInner
|
|
13901
|
-
}
|
|
13902
|
-
),
|
|
13903
|
-
hasDetail && expanded ? /* @__PURE__ */ (0, import_jsx_runtime183.jsxs)("div", { "data-slot": "tool-call-body", className: "flex flex-col gap-2 py-1 pl-6", children: [
|
|
13904
|
-
paramsText ? /* @__PURE__ */ (0, import_jsx_runtime183.jsxs)("div", { children: [
|
|
13905
|
-
/* @__PURE__ */ (0, import_jsx_runtime183.jsx)("div", { className: "text-xs font-medium text-muted-foreground", children: "\u53C2\u6570" }),
|
|
13906
|
-
/* @__PURE__ */ (0, import_jsx_runtime183.jsx)("pre", { "data-slot": "tool-call-params", className: "mt-1 overflow-x-auto text-xs whitespace-pre-wrap text-muted-foreground", children: paramsText })
|
|
13907
|
-
] }) : null,
|
|
13908
|
-
result ? /* @__PURE__ */ (0, import_jsx_runtime183.jsxs)("div", { children: [
|
|
13909
|
-
/* @__PURE__ */ (0, import_jsx_runtime183.jsx)("div", { className: "text-xs font-medium text-muted-foreground", children: "\u7ED3\u679C" }),
|
|
13910
|
-
/* @__PURE__ */ (0, import_jsx_runtime183.jsx)("pre", { "data-slot": "tool-call-result", className: "mt-1 overflow-x-auto text-xs whitespace-pre-wrap text-muted-foreground", children: result })
|
|
13911
|
-
] }) : null
|
|
13912
|
-
] }) : null
|
|
13913
|
-
]
|
|
13914
|
-
}
|
|
13915
|
-
);
|
|
13916
|
-
}
|
|
13917
|
-
|
|
13918
|
-
// src/components/chat/ChatMessage/index.tsx
|
|
13919
|
-
var import_jsx_runtime184 = require("react/jsx-runtime");
|
|
13920
|
-
function PartView({
|
|
13921
|
-
part,
|
|
13922
|
-
role,
|
|
13923
|
-
onOpenArtifacts
|
|
13924
|
-
}) {
|
|
13925
|
-
if (role === "system" && (part.type === "text" || part.type === "markdown")) {
|
|
13926
|
-
return /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(
|
|
13927
|
-
"div",
|
|
13928
|
-
{
|
|
13929
|
-
"data-slot": "chat-message-system-part",
|
|
13930
|
-
className: "w-full text-center text-xs text-muted-foreground",
|
|
13931
|
-
children: part.type === "markdown" ? /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(import_markdown2.MarkdownDslComponent, { content: part.content }) : part.content
|
|
13932
|
-
}
|
|
13933
|
-
);
|
|
13934
|
-
}
|
|
13935
|
-
switch (part.type) {
|
|
13936
|
-
case "text":
|
|
13937
|
-
return /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Bubble2, { align: role === "user" ? "end" : "start", variant: role === "user" ? "default" : "muted", children: /* @__PURE__ */ (0, import_jsx_runtime184.jsx)("span", { className: "text-sm whitespace-pre-wrap", children: part.content }) });
|
|
13938
|
-
case "markdown":
|
|
13939
|
-
return /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Bubble2, { align: role === "user" ? "end" : "start", variant: role === "user" ? "default" : "ghost", children: /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(import_markdown2.MarkdownDslComponent, { content: part.content }) });
|
|
13940
|
-
case "thinking":
|
|
13941
|
-
return /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Thinking, { content: part.content, status: part.status ?? "done" });
|
|
13942
|
-
case "tool-call":
|
|
13943
|
-
return /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(ToolCall, { name: part.name, params: part.params, status: part.status ?? "done", result: part.result });
|
|
13944
|
-
case "tool-result":
|
|
13945
|
-
return /* @__PURE__ */ (0, import_jsx_runtime184.jsx)("pre", { "data-slot": "chat-message-tool-result", className: "overflow-x-auto rounded-md bg-muted p-2 text-xs whitespace-pre-wrap", children: part.content });
|
|
13946
|
-
case "status":
|
|
13947
|
-
return /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)("div", { "data-slot": "chat-message-status", className: "flex w-fit items-center gap-1.5 text-muted-foreground", children: [
|
|
13948
|
-
/* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Icon, { name: "clock", size: "sm" }),
|
|
13949
|
-
part.text
|
|
13950
|
-
] });
|
|
13951
|
-
case "artifacts": {
|
|
13952
|
-
const artifactsClass = "flex w-fit items-center gap-1.5 text-muted-foreground";
|
|
13953
|
-
const label = `\u5DF2\u751F\u6210 ${part.count} \u4E2A\u4EA7\u7269`;
|
|
13954
|
-
return onOpenArtifacts ? /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)(
|
|
13955
|
-
"button",
|
|
13956
|
-
{
|
|
13957
|
-
type: "button",
|
|
13958
|
-
"data-slot": "chat-message-artifacts",
|
|
13959
|
-
className: cn(artifactsClass, "cursor-pointer hover:text-foreground"),
|
|
13960
|
-
onClick: onOpenArtifacts,
|
|
13961
|
-
children: [
|
|
13962
|
-
/* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Icon, { name: "package", size: "sm" }),
|
|
13963
|
-
label,
|
|
13964
|
-
/* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Icon, { name: "chevron-right", size: 12 })
|
|
13965
|
-
]
|
|
13966
|
-
}
|
|
13967
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)("div", { "data-slot": "chat-message-artifacts", className: artifactsClass, children: [
|
|
13968
|
-
/* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Icon, { name: "package", size: "sm" }),
|
|
13969
|
-
label
|
|
13970
|
-
] });
|
|
13971
|
-
}
|
|
13972
|
-
case "error":
|
|
13973
|
-
return /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)("div", { "data-slot": "chat-message-error", className: "flex items-center gap-1.5 text-sm text-destructive", children: [
|
|
13974
|
-
/* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Icon, { name: "circle-alert", size: "sm" }),
|
|
13975
|
-
part.message
|
|
13976
|
-
] });
|
|
13977
|
-
default:
|
|
13978
|
-
return null;
|
|
13979
|
-
}
|
|
13980
|
-
}
|
|
13981
|
-
var ACTION_ICON_BY_NAME = {
|
|
13982
|
-
copy: "copy",
|
|
13983
|
-
retry: "rotate-ccw",
|
|
13984
|
-
regenerate: "refresh-ccw",
|
|
13985
|
-
edit: "pencil",
|
|
13986
|
-
like: "thumbs-up",
|
|
13987
|
-
dislike: "thumbs-down",
|
|
13988
|
-
share: "share",
|
|
13989
|
-
delete: "trash"
|
|
13990
|
-
};
|
|
13991
|
-
function ChatMessage({
|
|
13992
|
-
role = "assistant",
|
|
13993
|
-
parts = [],
|
|
13994
|
-
status = "completed",
|
|
13995
|
-
agent,
|
|
13996
|
-
time,
|
|
13997
|
-
showSender = false,
|
|
13998
|
-
actions = [],
|
|
13999
|
-
onAction,
|
|
14000
|
-
onOpenArtifacts,
|
|
14001
|
-
className,
|
|
14002
|
-
style
|
|
14003
|
-
}) {
|
|
14004
|
-
const isUser = role === "user";
|
|
14005
|
-
const isSystem = role === "system";
|
|
14006
|
-
const senderName = isUser ? "\u6211" : agent?.name ?? "\u52A9\u624B";
|
|
14007
|
-
return /* @__PURE__ */ (0, import_jsx_runtime184.jsxs)(
|
|
14008
|
-
"div",
|
|
14009
|
-
{
|
|
14010
|
-
"data-slot": "chat-message",
|
|
14011
|
-
"data-role": role,
|
|
14012
|
-
"data-status": status,
|
|
14013
|
-
className: cn(
|
|
14014
|
-
"flex w-full flex-col gap-1.5",
|
|
14015
|
-
isUser && "items-end",
|
|
14016
|
-
// system 居中弱提示(参考 @pactor-app/chat MessageBubble)
|
|
14017
|
-
isSystem && "items-center text-muted-foreground",
|
|
14018
|
-
className
|
|
14019
|
-
),
|
|
14020
|
-
style,
|
|
14021
|
-
children: [
|
|
14022
|
-
showSender ? /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(
|
|
14023
|
-
Sender,
|
|
14024
|
-
{
|
|
14025
|
-
name: senderName,
|
|
14026
|
-
avatarText: isUser ? void 0 : agent?.icon ? void 0 : senderName.slice(0, 1),
|
|
14027
|
-
time,
|
|
14028
|
-
align: isUser ? "end" : "start"
|
|
14029
|
-
}
|
|
14030
|
-
) : null,
|
|
14031
|
-
/* @__PURE__ */ (0, import_jsx_runtime184.jsxs)("div", { className: cn("flex min-w-0 w-full max-w-full flex-col gap-2", isUser && "items-end", isSystem && "items-center"), children: [
|
|
14032
|
-
parts.map((part, index) => /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(PartView, { part, role, onOpenArtifacts }, index)),
|
|
14033
|
-
status === "streaming" ? /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(StreamingText, { content: "", streaming: true }) : null
|
|
14034
|
-
] }),
|
|
14035
|
-
actions.length > 0 && (status === "completed" || status === "error") ? /* @__PURE__ */ (0, import_jsx_runtime184.jsx)("div", { "data-slot": "chat-message-actions", className: "flex items-center gap-1 mt-2", children: actions.map((action) => {
|
|
14036
|
-
const label = action.label ?? action.name;
|
|
14037
|
-
const iconName = action.icon ?? ACTION_ICON_BY_NAME[action.name];
|
|
14038
|
-
if (iconName) {
|
|
14039
|
-
return /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Tooltip2, { content: label, side: "top", children: /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(
|
|
14040
|
-
"button",
|
|
14041
|
-
{
|
|
14042
|
-
type: "button",
|
|
14043
|
-
"data-slot": "chat-message-action",
|
|
14044
|
-
"data-action": action.name,
|
|
14045
|
-
"aria-label": label,
|
|
14046
|
-
className: "flex cursor-pointer items-center rounded-sm p-1 text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
14047
|
-
onClick: () => onAction?.(action.name),
|
|
14048
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(Icon, { name: iconName, size: "sm" })
|
|
14049
|
-
}
|
|
14050
|
-
) }, action.name);
|
|
14051
|
-
}
|
|
14052
|
-
return /* @__PURE__ */ (0, import_jsx_runtime184.jsx)(
|
|
14053
|
-
"button",
|
|
14054
|
-
{
|
|
14055
|
-
type: "button",
|
|
14056
|
-
"data-slot": "chat-message-action",
|
|
14057
|
-
"data-action": action.name,
|
|
14058
|
-
className: "flex items-center cursor-pointer gap-1 rounded-sm px-1.5 py-0.5 text-xs text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
14059
|
-
onClick: () => onAction?.(action.name),
|
|
14060
|
-
children: label
|
|
14061
|
-
},
|
|
14062
|
-
action.name
|
|
14063
|
-
);
|
|
14064
|
-
}) }) : null
|
|
14065
|
-
]
|
|
14066
|
-
}
|
|
14067
|
-
);
|
|
14068
|
-
}
|
|
14069
|
-
|
|
14070
|
-
// src/components/chat/ChatPage/index.tsx
|
|
14071
|
-
var import_runtime51 = require("@pactor-app/runtime");
|
|
14072
|
-
var import_react70 = require("react");
|
|
14073
|
-
|
|
14074
|
-
// src/components/chat/Composer/index.tsx
|
|
14075
|
-
var import_react67 = require("react");
|
|
14076
|
-
|
|
14077
|
-
// src/components/chat/Composer/mention-input.tsx
|
|
14078
|
-
var import_react66 = require("react");
|
|
14079
|
-
var import_server = require("react-dom/server");
|
|
14080
|
-
var import_jsx_runtime185 = require("react/jsx-runtime");
|
|
14081
|
-
var NBSP = "\xA0";
|
|
14082
|
-
var CHIP_ATTR = "data-mention-chip";
|
|
14083
|
-
function escapeRegExp(text) {
|
|
14084
|
-
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
14085
|
-
}
|
|
14086
|
-
function isChipElement(node) {
|
|
14087
|
-
return node instanceof HTMLElement && node.hasAttribute(CHIP_ATTR);
|
|
14088
|
-
}
|
|
14089
|
-
function serializeNode(node) {
|
|
14090
|
-
let out = "";
|
|
14091
|
-
node.childNodes.forEach((child) => {
|
|
14092
|
-
if (child.nodeType === Node.TEXT_NODE) {
|
|
14093
|
-
out += (child.textContent ?? "").replace(/\u00A0/g, " ");
|
|
14094
|
-
} else if (isChipElement(child)) {
|
|
14095
|
-
out += `${child.dataset["trigger"] ?? ""}${child.dataset["label"] ?? ""}`;
|
|
14096
|
-
} else if (child instanceof HTMLBRElement) {
|
|
14097
|
-
out += "\n";
|
|
14098
|
-
} else if (child instanceof HTMLElement) {
|
|
14099
|
-
const inner = serializeNode(child).replace(/\n$/, "");
|
|
14100
|
-
out += (out === "" || out.endsWith("\n") ? "" : "\n") + inner + "\n";
|
|
14101
|
-
}
|
|
14102
|
-
});
|
|
14103
|
-
return out;
|
|
14104
|
-
}
|
|
14105
|
-
function collectChips(field) {
|
|
14106
|
-
return Array.from(field.querySelectorAll(`[${CHIP_ATTR}]`)).map((el) => ({
|
|
14107
|
-
id: el.dataset["id"] ?? "",
|
|
14108
|
-
label: el.dataset["label"] ?? "",
|
|
14109
|
-
trigger: el.dataset["trigger"] ?? ""
|
|
14110
|
-
}));
|
|
14111
|
-
}
|
|
14112
|
-
function detectActiveMention(field, sources) {
|
|
14113
|
-
const selection = window.getSelection();
|
|
14114
|
-
if (!selection || selection.rangeCount === 0 || !selection.isCollapsed) {
|
|
14115
|
-
return null;
|
|
14116
|
-
}
|
|
14117
|
-
const anchor = selection.anchorNode;
|
|
14118
|
-
if (!anchor || anchor.nodeType !== Node.TEXT_NODE || !field.contains(anchor)) {
|
|
14119
|
-
return null;
|
|
14120
|
-
}
|
|
14121
|
-
const caretOffset = selection.anchorOffset;
|
|
14122
|
-
const beforeCaret = (anchor.textContent ?? "").slice(0, caretOffset);
|
|
14123
|
-
for (const source of sources) {
|
|
14124
|
-
const trigger = source.trigger;
|
|
14125
|
-
const match = new RegExp(
|
|
14126
|
-
`(?:^|\\s)${escapeRegExp(trigger)}([^\\s${escapeRegExp(trigger)}]*)$`
|
|
14127
|
-
).exec(beforeCaret);
|
|
14128
|
-
if (match) {
|
|
14129
|
-
const query = match[1] ?? "";
|
|
14130
|
-
return {
|
|
14131
|
-
source,
|
|
14132
|
-
query,
|
|
14133
|
-
node: anchor,
|
|
14134
|
-
triggerStart: caretOffset - query.length - trigger.length,
|
|
14135
|
-
caretOffset
|
|
14136
|
-
};
|
|
14137
|
-
}
|
|
14138
|
-
}
|
|
14139
|
-
return null;
|
|
14140
|
-
}
|
|
14141
|
-
function chipIcon(item, source) {
|
|
14142
|
-
return item.icon ?? source.icon ?? (source.trigger === "@" ? "user" : "file-text");
|
|
14143
|
-
}
|
|
14144
|
-
var MentionInput = (0, import_react66.forwardRef)(
|
|
14145
|
-
function MentionInput2({
|
|
14146
|
-
value,
|
|
14147
|
-
placeholder,
|
|
14148
|
-
disabled,
|
|
14149
|
-
sources,
|
|
14150
|
-
chips,
|
|
14151
|
-
onChipsChange,
|
|
14152
|
-
onChange,
|
|
14153
|
-
onSubmit,
|
|
14154
|
-
className,
|
|
14155
|
-
style
|
|
14156
|
-
}, ref) {
|
|
14157
|
-
const fieldRef = (0, import_react66.useRef)(null);
|
|
14158
|
-
const [menu, setMenu] = (0, import_react66.useState)(null);
|
|
14159
|
-
const [empty, setEmpty] = (0, import_react66.useState)(true);
|
|
14160
|
-
const suppressSyncRef = (0, import_react66.useRef)(false);
|
|
14161
|
-
const composingRef = (0, import_react66.useRef)(false);
|
|
14162
|
-
const emitChips = () => {
|
|
14163
|
-
if (suppressSyncRef.current || !fieldRef.current) {
|
|
14164
|
-
return;
|
|
14165
|
-
}
|
|
14166
|
-
onChipsChange?.(collectChips(fieldRef.current));
|
|
14167
|
-
};
|
|
14168
|
-
const serialize = () => fieldRef.current ? serializeNode(fieldRef.current).replace(/\n$/, "") : "";
|
|
14169
|
-
const buildChipElement = (item, source) => {
|
|
14170
|
-
const chip = document.createElement("span");
|
|
14171
|
-
chip.setAttribute(CHIP_ATTR, "");
|
|
14172
|
-
chip.dataset["id"] = item.id;
|
|
14173
|
-
chip.dataset["label"] = item.label;
|
|
14174
|
-
chip.dataset["trigger"] = item.trigger ?? source.trigger;
|
|
14175
|
-
chip.contentEditable = "false";
|
|
14176
|
-
chip.className = "mx-0.5 inline-flex items-center gap-1 rounded-md bg-muted px-1.5 py-0.5 align-middle text-xs text-foreground";
|
|
14177
|
-
const iconMarkup = (0, import_server.renderToStaticMarkup)(
|
|
14178
|
-
/* @__PURE__ */ (0, import_jsx_runtime185.jsx)(Icon, { name: chipIcon(item, source), size: 12 })
|
|
14179
|
-
);
|
|
14180
|
-
const label = document.createElement("span");
|
|
14181
|
-
label.textContent = item.label;
|
|
14182
|
-
chip.innerHTML = iconMarkup;
|
|
14183
|
-
chip.appendChild(label);
|
|
14184
|
-
return chip;
|
|
14185
|
-
};
|
|
14186
|
-
const insertChipElement = (item, source, replace) => {
|
|
14187
|
-
const field = fieldRef.current;
|
|
14188
|
-
if (!field) {
|
|
14189
|
-
return;
|
|
14190
|
-
}
|
|
14191
|
-
const chip = buildChipElement(item, source);
|
|
14192
|
-
let caretNode;
|
|
14193
|
-
if (replace) {
|
|
14194
|
-
const { node, start, end } = replace;
|
|
14195
|
-
const text = node.textContent ?? "";
|
|
14196
|
-
node.textContent = text.slice(0, start);
|
|
14197
|
-
caretNode = document.createTextNode(`${NBSP}${text.slice(end)}`);
|
|
14198
|
-
node.after(chip, caretNode);
|
|
14199
|
-
} else {
|
|
14200
|
-
caretNode = document.createTextNode(NBSP);
|
|
14201
|
-
const selection2 = window.getSelection();
|
|
14202
|
-
if (selection2 && selection2.rangeCount > 0 && selection2.anchorNode !== null && field.contains(selection2.anchorNode)) {
|
|
14203
|
-
const range = selection2.getRangeAt(0);
|
|
14204
|
-
range.deleteContents();
|
|
14205
|
-
range.insertNode(caretNode);
|
|
14206
|
-
range.insertNode(chip);
|
|
14207
|
-
} else {
|
|
14208
|
-
field.append(chip, caretNode);
|
|
14209
|
-
}
|
|
14210
|
-
}
|
|
14211
|
-
const selection = window.getSelection();
|
|
14212
|
-
if (selection) {
|
|
14213
|
-
const range = document.createRange();
|
|
14214
|
-
range.setStart(caretNode, 1);
|
|
14215
|
-
range.collapse(true);
|
|
14216
|
-
selection.removeAllRanges();
|
|
14217
|
-
selection.addRange(range);
|
|
14218
|
-
}
|
|
14219
|
-
setEmpty(false);
|
|
14220
|
-
onChange?.(serialize());
|
|
14221
|
-
emitChips();
|
|
14222
|
-
};
|
|
14223
|
-
(0, import_react66.useImperativeHandle)(ref, () => ({
|
|
14224
|
-
insertChip: (item, source) => {
|
|
14225
|
-
fieldRef.current?.focus();
|
|
14226
|
-
insertChipElement(item, source);
|
|
14227
|
-
},
|
|
14228
|
-
focus: () => fieldRef.current?.focus()
|
|
14229
|
-
}));
|
|
14230
|
-
(0, import_react66.useEffect)(() => {
|
|
14231
|
-
const field = fieldRef.current;
|
|
14232
|
-
if (field && value === "" && serializeNode(field).trim() !== "") {
|
|
14233
|
-
suppressSyncRef.current = true;
|
|
14234
|
-
field.innerHTML = "";
|
|
14235
|
-
setEmpty(true);
|
|
14236
|
-
setMenu(null);
|
|
14237
|
-
suppressSyncRef.current = false;
|
|
14238
|
-
}
|
|
14239
|
-
}, [value]);
|
|
14240
|
-
(0, import_react66.useEffect)(() => {
|
|
14241
|
-
const field = fieldRef.current;
|
|
14242
|
-
if (!field) {
|
|
14243
|
-
return;
|
|
14244
|
-
}
|
|
14245
|
-
const keep = new Set(chips.map((chip) => `${chip.trigger}:${chip.id}`));
|
|
14246
|
-
const stale = Array.from(field.querySelectorAll(`[${CHIP_ATTR}]`)).filter(
|
|
14247
|
-
(el) => !keep.has(
|
|
14248
|
-
`${el.dataset["trigger"]}:${el.dataset["id"]}`
|
|
14249
|
-
)
|
|
14250
|
-
);
|
|
14251
|
-
if (stale.length > 0) {
|
|
14252
|
-
suppressSyncRef.current = true;
|
|
14253
|
-
stale.forEach((el) => el.remove());
|
|
14254
|
-
suppressSyncRef.current = false;
|
|
14255
|
-
setEmpty(serializeNode(field).trim() === "");
|
|
14256
|
-
}
|
|
14257
|
-
}, [chips]);
|
|
14258
|
-
const closeMenu = () => setMenu(null);
|
|
14259
|
-
const filteredItems = (state) => state.query ? state.source.items.filter((item) => item.label.includes(state.query)) : state.source.items;
|
|
14260
|
-
const refreshMenu = () => {
|
|
14261
|
-
const field = fieldRef.current;
|
|
14262
|
-
if (!field) {
|
|
14263
|
-
return;
|
|
14264
|
-
}
|
|
14265
|
-
const active = detectActiveMention(field, sources);
|
|
14266
|
-
if (!active) {
|
|
14267
|
-
setMenu(null);
|
|
14268
|
-
return;
|
|
14269
|
-
}
|
|
14270
|
-
const range = document.createRange();
|
|
14271
|
-
range.setStart(active.node, active.triggerStart);
|
|
14272
|
-
range.setEnd(active.node, active.caretOffset);
|
|
14273
|
-
const rect = typeof range.getBoundingClientRect === "function" ? range.getBoundingClientRect() : field.getBoundingClientRect();
|
|
14274
|
-
setMenu((prev) => ({
|
|
14275
|
-
source: active.source,
|
|
14276
|
-
query: active.query,
|
|
14277
|
-
left: rect.left,
|
|
14278
|
-
top: rect.top,
|
|
14279
|
-
// 过滤结果变化后候选下标钳制在有效范围内(DSL 每次渲染产出新
|
|
14280
|
-
// props 对象,source 按 trigger 比较而非引用)
|
|
14281
|
-
activeIndex: Math.min(
|
|
14282
|
-
prev?.source.trigger === active.source.trigger ? prev.activeIndex : 0,
|
|
14283
|
-
Math.max(filteredItems({ source: active.source, query: active.query, left: 0, top: 0, activeIndex: 0 }).length - 1, 0)
|
|
14284
|
-
)
|
|
14285
|
-
}));
|
|
14286
|
-
};
|
|
14287
|
-
const selectMenuItem = (item) => {
|
|
14288
|
-
const field = fieldRef.current;
|
|
14289
|
-
if (!field || !menu) {
|
|
14290
|
-
return;
|
|
14291
|
-
}
|
|
14292
|
-
const active = detectActiveMention(field, sources);
|
|
14293
|
-
insertChipElement(
|
|
14294
|
-
{ ...item, trigger: item.trigger ?? menu.source.trigger },
|
|
14295
|
-
menu.source,
|
|
14296
|
-
active && active.source.trigger === menu.source.trigger ? { node: active.node, start: active.triggerStart, end: active.caretOffset } : void 0
|
|
14297
|
-
);
|
|
14298
|
-
setMenu(null);
|
|
14299
|
-
};
|
|
14300
|
-
const handleInput = () => {
|
|
14301
|
-
const field = fieldRef.current;
|
|
14302
|
-
if (!field) {
|
|
14303
|
-
return;
|
|
14304
|
-
}
|
|
14305
|
-
if ((field.textContent ?? "") === "" && field.querySelector(`[${CHIP_ATTR}]`) === null) {
|
|
14306
|
-
field.innerHTML = "";
|
|
14307
|
-
}
|
|
14308
|
-
setEmpty(serializeNode(field).trim() === "");
|
|
14309
|
-
onChange?.(serialize());
|
|
14310
|
-
refreshMenu();
|
|
14311
|
-
};
|
|
14312
|
-
const handleKeyDown = (event) => {
|
|
14313
|
-
if (menu) {
|
|
14314
|
-
const items = filteredItems(menu);
|
|
14315
|
-
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
14316
|
-
event.preventDefault();
|
|
14317
|
-
if (items.length > 0) {
|
|
14318
|
-
const delta = event.key === "ArrowDown" ? 1 : -1;
|
|
14319
|
-
setMenu({
|
|
14320
|
-
...menu,
|
|
14321
|
-
activeIndex: (menu.activeIndex + delta + items.length) % items.length
|
|
14322
|
-
});
|
|
14323
|
-
}
|
|
14324
|
-
return;
|
|
14325
|
-
}
|
|
14326
|
-
if (event.key === "Enter" && !composingRef.current && !event.nativeEvent.isComposing) {
|
|
14327
|
-
event.preventDefault();
|
|
14328
|
-
const item = items[Math.min(menu.activeIndex, items.length - 1)];
|
|
14329
|
-
if (item) {
|
|
14330
|
-
selectMenuItem(item);
|
|
14331
|
-
} else {
|
|
14332
|
-
closeMenu();
|
|
14333
|
-
}
|
|
14334
|
-
return;
|
|
14335
|
-
}
|
|
14336
|
-
if (event.key === "Escape") {
|
|
14337
|
-
event.preventDefault();
|
|
14338
|
-
closeMenu();
|
|
14339
|
-
return;
|
|
14340
|
-
}
|
|
14341
|
-
}
|
|
14342
|
-
if (event.key === "Enter" && !event.shiftKey && !composingRef.current && !event.nativeEvent.isComposing) {
|
|
14343
|
-
event.preventDefault();
|
|
14344
|
-
const text = serialize();
|
|
14345
|
-
if (text.trim() !== "" && !disabled) {
|
|
14346
|
-
onSubmit?.(text);
|
|
14347
|
-
}
|
|
14348
|
-
return;
|
|
14349
|
-
}
|
|
14350
|
-
if (event.key === "Backspace") {
|
|
14351
|
-
const selection = window.getSelection();
|
|
14352
|
-
const field = fieldRef.current;
|
|
14353
|
-
if (!selection || !selection.isCollapsed || !field) {
|
|
14354
|
-
return;
|
|
14355
|
-
}
|
|
14356
|
-
let chip = null;
|
|
14357
|
-
const anchor = selection.anchorNode;
|
|
14358
|
-
if (anchor === field && selection.anchorOffset > 0) {
|
|
14359
|
-
const before = field.childNodes[selection.anchorOffset - 1];
|
|
14360
|
-
if (isChipElement(before)) {
|
|
14361
|
-
chip = before;
|
|
14362
|
-
}
|
|
14363
|
-
} else if (anchor?.nodeType === Node.TEXT_NODE && selection.anchorOffset === 0) {
|
|
14364
|
-
if (isChipElement(anchor.previousSibling)) {
|
|
14365
|
-
chip = anchor.previousSibling;
|
|
14366
|
-
}
|
|
14367
|
-
}
|
|
14368
|
-
if (chip) {
|
|
14369
|
-
event.preventDefault();
|
|
14370
|
-
chip.remove();
|
|
14371
|
-
onChange?.(serialize());
|
|
14372
|
-
emitChips();
|
|
14373
|
-
setEmpty(serializeNode(field).trim() === "");
|
|
14374
|
-
}
|
|
14375
|
-
}
|
|
14376
|
-
};
|
|
14377
|
-
const menuItems = menu ? filteredItems(menu) : [];
|
|
14378
|
-
const activeIndex = Math.min(menu?.activeIndex ?? 0, Math.max(menuItems.length - 1, 0));
|
|
14379
|
-
return /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)("div", { className: "relative", children: [
|
|
14380
|
-
/* @__PURE__ */ (0, import_jsx_runtime185.jsx)(
|
|
14381
|
-
"div",
|
|
14382
|
-
{
|
|
14383
|
-
ref: fieldRef,
|
|
14384
|
-
"data-slot": "mention-input",
|
|
14385
|
-
role: "textbox",
|
|
14386
|
-
"aria-multiline": "true",
|
|
14387
|
-
"aria-placeholder": placeholder,
|
|
14388
|
-
contentEditable: !disabled,
|
|
14389
|
-
suppressContentEditableWarning: true,
|
|
14390
|
-
className: cn(
|
|
14391
|
-
"min-h-[60px] w-full px-4 pt-3 pb-1 text-sm whitespace-pre-wrap break-words outline-none",
|
|
14392
|
-
className
|
|
14393
|
-
),
|
|
14394
|
-
style,
|
|
14395
|
-
onInput: handleInput,
|
|
14396
|
-
onKeyDown: handleKeyDown,
|
|
14397
|
-
onCompositionStart: () => {
|
|
14398
|
-
composingRef.current = true;
|
|
14399
|
-
},
|
|
14400
|
-
onCompositionEnd: () => {
|
|
14401
|
-
composingRef.current = false;
|
|
14402
|
-
},
|
|
14403
|
-
onPaste: (event) => {
|
|
14404
|
-
event.preventDefault();
|
|
14405
|
-
const text = event.clipboardData?.getData("text/plain") ?? "";
|
|
14406
|
-
if (text) {
|
|
14407
|
-
document.execCommand("insertText", false, text);
|
|
14408
|
-
}
|
|
14409
|
-
}
|
|
14410
|
-
}
|
|
14411
|
-
),
|
|
14412
|
-
empty && placeholder !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime185.jsx)("span", { className: "pointer-events-none absolute top-3 left-4 text-sm text-muted-foreground", children: placeholder }) : null,
|
|
14413
|
-
menu ? /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)(import_jsx_runtime185.Fragment, { children: [
|
|
14414
|
-
/* @__PURE__ */ (0, import_jsx_runtime185.jsx)(
|
|
14415
|
-
"div",
|
|
14416
|
-
{
|
|
14417
|
-
className: "fixed inset-0 z-40",
|
|
14418
|
-
onMouseDown: (event) => {
|
|
14419
|
-
event.preventDefault();
|
|
14420
|
-
closeMenu();
|
|
14421
|
-
}
|
|
14422
|
-
}
|
|
14423
|
-
),
|
|
14424
|
-
/* @__PURE__ */ (0, import_jsx_runtime185.jsxs)(
|
|
14425
|
-
"div",
|
|
14426
|
-
{
|
|
14427
|
-
"data-slot": "mention-menu",
|
|
14428
|
-
role: "listbox",
|
|
14429
|
-
className: "scrollbar-subtle fixed z-50 max-h-72 w-64 overflow-y-auto rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md",
|
|
14430
|
-
style: {
|
|
14431
|
-
left: menu.left,
|
|
14432
|
-
bottom: typeof window === "undefined" ? void 0 : window.innerHeight - menu.top + 6
|
|
14433
|
-
},
|
|
14434
|
-
children: [
|
|
14435
|
-
/* @__PURE__ */ (0, import_jsx_runtime185.jsx)("div", { className: "px-2 py-1 text-xs text-muted-foreground", children: menu.source.label }),
|
|
14436
|
-
menuItems.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime185.jsx)("div", { className: "px-2 py-2 text-xs text-muted-foreground", children: "\u65E0\u5339\u914D\u9879" }) : menuItems.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime185.jsxs)(
|
|
14437
|
-
"button",
|
|
14438
|
-
{
|
|
14439
|
-
type: "button",
|
|
14440
|
-
role: "option",
|
|
14441
|
-
"aria-selected": index === activeIndex,
|
|
14442
|
-
className: cn(
|
|
14443
|
-
"flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm",
|
|
14444
|
-
index === activeIndex ? "bg-accent" : "hover:bg-accent"
|
|
14445
|
-
),
|
|
14446
|
-
onMouseDown: (event) => {
|
|
14447
|
-
event.preventDefault();
|
|
14448
|
-
selectMenuItem(item);
|
|
14449
|
-
},
|
|
14450
|
-
children: [
|
|
14451
|
-
/* @__PURE__ */ (0, import_jsx_runtime185.jsx)(Icon, { name: chipIcon(item, menu.source), size: "sm" }),
|
|
14452
|
-
/* @__PURE__ */ (0, import_jsx_runtime185.jsx)("span", { className: "min-w-0 flex-1 truncate", children: item.label })
|
|
14453
|
-
]
|
|
14454
|
-
},
|
|
14455
|
-
item.id
|
|
14456
|
-
))
|
|
14457
|
-
]
|
|
14458
|
-
}
|
|
14459
|
-
)
|
|
14460
|
-
] }) : null
|
|
14461
|
-
] });
|
|
14462
|
-
}
|
|
14463
|
-
);
|
|
14464
|
-
|
|
14465
|
-
// src/components/chat/Composer/index.tsx
|
|
14466
|
-
var import_jsx_runtime186 = require("react/jsx-runtime");
|
|
14467
|
-
var toolButtonClass3 = "flex cursor-pointer items-center rounded-md p-1.5 text-muted-foreground hover:bg-accent hover:text-foreground";
|
|
14468
|
-
var popoverPanelClass = "absolute bottom-full left-0 z-50 mb-2 max-h-72 w-64 overflow-y-auto rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md";
|
|
14469
|
-
var popoverItemClass = "flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm hover:bg-accent";
|
|
14470
|
-
function Composer({
|
|
14471
|
-
value,
|
|
14472
|
-
placeholder,
|
|
14473
|
-
disabled,
|
|
14474
|
-
loading,
|
|
14475
|
-
rows,
|
|
14476
|
-
attachments = [],
|
|
14477
|
-
onRemoveAttachment,
|
|
14478
|
-
onRetryAttachment,
|
|
14479
|
-
onAttachFiles,
|
|
14480
|
-
onChange,
|
|
14481
|
-
onSubmit,
|
|
14482
|
-
models,
|
|
14483
|
-
model,
|
|
14484
|
-
onModelChange,
|
|
14485
|
-
contexts,
|
|
14486
|
-
contextItems,
|
|
14487
|
-
onContextItemsChange,
|
|
14488
|
-
footer,
|
|
14489
|
-
className,
|
|
14490
|
-
style
|
|
14491
|
-
}) {
|
|
14492
|
-
const textControlled = value !== void 0;
|
|
14493
|
-
const [innerText, setInnerText] = (0, import_react67.useState)("");
|
|
14494
|
-
const text = textControlled ? value : innerText;
|
|
14495
|
-
const [dragOver, setDragOver] = (0, import_react67.useState)(false);
|
|
14496
|
-
const [plusOpen, setPlusOpen] = (0, import_react67.useState)(false);
|
|
14497
|
-
const [modelOpen, setModelOpen] = (0, import_react67.useState)(false);
|
|
14498
|
-
const fileInputRef = (0, import_react67.useRef)(null);
|
|
14499
|
-
const mentionRef = (0, import_react67.useRef)(null);
|
|
14500
|
-
const sources = contexts ?? [];
|
|
14501
|
-
const rich = sources.length > 0;
|
|
14502
|
-
const plusSources = sources.filter((s) => s.trigger === "+");
|
|
14503
|
-
const plusEnabled = plusSources.length > 0;
|
|
14504
|
-
const modelEnabled = models !== void 0 && models.length > 0;
|
|
14505
|
-
const currentModel = models?.find((m) => m.value === model) ?? models?.[0];
|
|
14506
|
-
const [innerChips, setInnerChips] = (0, import_react67.useState)([]);
|
|
14507
|
-
const chipsControlled = contextItems !== void 0;
|
|
14508
|
-
const chips = chipsControlled ? contextItems : innerChips;
|
|
14509
|
-
const handleChipsChange = (next) => {
|
|
14510
|
-
if (!chipsControlled) {
|
|
14511
|
-
setInnerChips(next);
|
|
14512
|
-
}
|
|
14513
|
-
onContextItemsChange?.(next);
|
|
14514
|
-
};
|
|
14515
|
-
const closePopovers = () => {
|
|
14516
|
-
setPlusOpen(false);
|
|
14517
|
-
setModelOpen(false);
|
|
14518
|
-
};
|
|
14519
|
-
const handleChange = (next) => {
|
|
14520
|
-
if (!textControlled) {
|
|
14521
|
-
setInnerText(next);
|
|
14522
|
-
}
|
|
14523
|
-
onChange?.(next);
|
|
14524
|
-
};
|
|
14525
|
-
const handleSubmit = (submitted) => {
|
|
14526
|
-
onSubmit?.(submitted);
|
|
14527
|
-
if (!textControlled) {
|
|
14528
|
-
setInnerText("");
|
|
14529
|
-
}
|
|
14530
|
-
closePopovers();
|
|
14531
|
-
};
|
|
14532
|
-
const selectContext = (item, source) => {
|
|
14533
|
-
if (rich) {
|
|
14534
|
-
mentionRef.current?.insertChip(item, source);
|
|
14535
|
-
} else {
|
|
14536
|
-
const chip = { ...item, trigger: item.trigger ?? source.trigger };
|
|
14537
|
-
const duplicated = chips.some(
|
|
14538
|
-
(existing) => existing.id === chip.id && existing.trigger === chip.trigger
|
|
14539
|
-
);
|
|
14540
|
-
if (!duplicated) {
|
|
14541
|
-
handleChipsChange([...chips, chip]);
|
|
14542
|
-
}
|
|
14543
|
-
}
|
|
14544
|
-
closePopovers();
|
|
14545
|
-
};
|
|
14546
|
-
const emitFiles = (files) => {
|
|
14547
|
-
if (files.length > 0 && onAttachFiles) {
|
|
14548
|
-
onAttachFiles(files);
|
|
14549
|
-
}
|
|
14550
|
-
};
|
|
14551
|
-
const handleDrop = (event) => {
|
|
14552
|
-
if (!onAttachFiles) {
|
|
14553
|
-
return;
|
|
14554
|
-
}
|
|
14555
|
-
event.preventDefault();
|
|
14556
|
-
setDragOver(false);
|
|
14557
|
-
emitFiles(Array.from(event.dataTransfer?.files ?? []));
|
|
14558
|
-
};
|
|
14559
|
-
const toolbarStart = plusEnabled || onAttachFiles ? /* @__PURE__ */ (0, import_jsx_runtime186.jsxs)(import_jsx_runtime186.Fragment, { children: [
|
|
14560
|
-
plusEnabled ? /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(
|
|
14561
|
-
"button",
|
|
14562
|
-
{
|
|
14563
|
-
type: "button",
|
|
14564
|
-
"aria-label": "\u6DFB\u52A0\u4E0A\u4E0B\u6587",
|
|
14565
|
-
title: "\u6DFB\u52A0\u4E0A\u4E0B\u6587",
|
|
14566
|
-
className: toolButtonClass3,
|
|
14567
|
-
onClick: () => {
|
|
14568
|
-
setPlusOpen((prev) => !prev);
|
|
14569
|
-
setModelOpen(false);
|
|
14570
|
-
},
|
|
14571
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(Icon, { name: "plus", size: "sm" })
|
|
14572
|
-
}
|
|
14573
|
-
) : null,
|
|
14574
|
-
onAttachFiles ? /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(
|
|
14575
|
-
"button",
|
|
14576
|
-
{
|
|
14577
|
-
type: "button",
|
|
14578
|
-
"aria-label": "\u6DFB\u52A0\u9644\u4EF6",
|
|
14579
|
-
title: "\u6DFB\u52A0\u9644\u4EF6",
|
|
14580
|
-
className: toolButtonClass3,
|
|
14581
|
-
onClick: () => fileInputRef.current?.click(),
|
|
14582
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(Icon, { name: "paperclip", size: "sm" })
|
|
14583
|
-
}
|
|
14584
|
-
) : null
|
|
14585
|
-
] }) : void 0;
|
|
14586
|
-
const toolbarEnd = modelEnabled ? /* @__PURE__ */ (0, import_jsx_runtime186.jsxs)(
|
|
14587
|
-
"button",
|
|
14588
|
-
{
|
|
14589
|
-
type: "button",
|
|
14590
|
-
"aria-label": "\u9009\u62E9\u6A21\u578B",
|
|
14591
|
-
title: "\u9009\u62E9\u6A21\u578B",
|
|
14592
|
-
className: "flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
14593
|
-
onClick: () => {
|
|
14594
|
-
setModelOpen((prev) => !prev);
|
|
14595
|
-
setPlusOpen(false);
|
|
14596
|
-
},
|
|
14597
|
-
children: [
|
|
14598
|
-
currentModel?.label,
|
|
14599
|
-
/* @__PURE__ */ (0, import_jsx_runtime186.jsx)(Icon, { name: "chevrons-up-down", size: 12 })
|
|
14600
|
-
]
|
|
14601
|
-
}
|
|
14602
|
-
) : void 0;
|
|
14603
|
-
const activePopover = plusOpen ? "plus" : modelOpen ? "model" : null;
|
|
14604
|
-
return /* @__PURE__ */ (0, import_jsx_runtime186.jsxs)(
|
|
14605
|
-
"div",
|
|
14606
|
-
{
|
|
14607
|
-
"data-slot": "composer",
|
|
14608
|
-
className: cn("relative flex w-full flex-col gap-2", className),
|
|
14609
|
-
style,
|
|
14610
|
-
onDragOver: (event) => {
|
|
14611
|
-
if (onAttachFiles) {
|
|
14612
|
-
event.preventDefault();
|
|
14613
|
-
setDragOver(true);
|
|
14614
|
-
}
|
|
14615
|
-
},
|
|
14616
|
-
onDragLeave: () => setDragOver(false),
|
|
14617
|
-
onDrop: handleDrop,
|
|
14618
|
-
onPaste: (event) => {
|
|
14619
|
-
const files = Array.from(event.clipboardData?.files ?? []);
|
|
14620
|
-
if (files.length > 0 && onAttachFiles) {
|
|
14621
|
-
event.preventDefault();
|
|
14622
|
-
emitFiles(files);
|
|
14623
|
-
}
|
|
14624
|
-
},
|
|
14625
|
-
children: [
|
|
14626
|
-
attachments.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(Attachment, { items: attachments, onRemove: onRemoveAttachment, onRetry: onRetryAttachment }) : null,
|
|
14627
|
-
/* @__PURE__ */ (0, import_jsx_runtime186.jsx)("div", { className: cn(dragOver && "rounded-xl ring-2 ring-ring/50"), children: /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(
|
|
14628
|
-
ChatInput,
|
|
14629
|
-
{
|
|
14630
|
-
value: text,
|
|
14631
|
-
placeholder,
|
|
14632
|
-
disabled: disabled || loading,
|
|
14633
|
-
rows,
|
|
14634
|
-
toolbarStart,
|
|
14635
|
-
toolbarEnd,
|
|
14636
|
-
footer,
|
|
14637
|
-
field: rich ? /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(
|
|
14638
|
-
MentionInput,
|
|
14639
|
-
{
|
|
14640
|
-
ref: mentionRef,
|
|
14641
|
-
value: text,
|
|
14642
|
-
placeholder,
|
|
14643
|
-
disabled: disabled || loading,
|
|
14644
|
-
sources,
|
|
14645
|
-
chips,
|
|
14646
|
-
onChipsChange: handleChipsChange,
|
|
14647
|
-
onChange: handleChange,
|
|
14648
|
-
onSubmit: handleSubmit
|
|
14649
|
-
}
|
|
14650
|
-
) : void 0,
|
|
14651
|
-
onChange: handleChange,
|
|
14652
|
-
onSubmit: handleSubmit
|
|
14653
|
-
}
|
|
14654
|
-
) }),
|
|
14655
|
-
onAttachFiles ? /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(
|
|
14656
|
-
"input",
|
|
14657
|
-
{
|
|
14658
|
-
ref: fileInputRef,
|
|
14659
|
-
type: "file",
|
|
14660
|
-
multiple: true,
|
|
14661
|
-
hidden: true,
|
|
14662
|
-
onChange: (event) => {
|
|
14663
|
-
emitFiles(Array.from(event.target.files ?? []));
|
|
14664
|
-
event.target.value = "";
|
|
14665
|
-
}
|
|
14666
|
-
}
|
|
14667
|
-
) : null,
|
|
14668
|
-
activePopover !== null ? /* @__PURE__ */ (0, import_jsx_runtime186.jsxs)(import_jsx_runtime186.Fragment, { children: [
|
|
14669
|
-
/* @__PURE__ */ (0, import_jsx_runtime186.jsx)("div", { className: "fixed inset-0 z-40", onClick: closePopovers }),
|
|
14670
|
-
activePopover === "model" ? /* @__PURE__ */ (0, import_jsx_runtime186.jsx)("div", { "data-slot": "composer-model-popover", className: cn(popoverPanelClass, "right-0 left-auto w-48"), role: "listbox", children: models.map((option) => /* @__PURE__ */ (0, import_jsx_runtime186.jsxs)(
|
|
14671
|
-
"button",
|
|
14672
|
-
{
|
|
14673
|
-
type: "button",
|
|
14674
|
-
role: "option",
|
|
14675
|
-
"aria-selected": option.value === currentModel?.value,
|
|
14676
|
-
className: popoverItemClass,
|
|
14677
|
-
onClick: () => {
|
|
14678
|
-
onModelChange?.(option.value);
|
|
14679
|
-
closePopovers();
|
|
14680
|
-
},
|
|
14681
|
-
children: [
|
|
14682
|
-
/* @__PURE__ */ (0, import_jsx_runtime186.jsx)("span", { className: "min-w-0 flex-1 truncate", children: option.label }),
|
|
14683
|
-
option.value === currentModel?.value ? /* @__PURE__ */ (0, import_jsx_runtime186.jsx)(Icon, { name: "check", size: 14 }) : null
|
|
14684
|
-
]
|
|
14685
|
-
},
|
|
14686
|
-
option.value
|
|
14687
|
-
)) }) : /* @__PURE__ */ (0, import_jsx_runtime186.jsx)("div", { "data-slot": "composer-context-popover", className: popoverPanelClass, role: "listbox", children: plusSources.map(
|
|
14688
|
-
(source) => source.items.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime186.jsxs)("div", { children: [
|
|
14689
|
-
/* @__PURE__ */ (0, import_jsx_runtime186.jsx)("div", { className: "px-2 py-1 text-xs text-muted-foreground", children: source.label }),
|
|
14690
|
-
source.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime186.jsxs)(
|
|
14691
|
-
"button",
|
|
14692
|
-
{
|
|
14693
|
-
type: "button",
|
|
14694
|
-
className: popoverItemClass,
|
|
14695
|
-
onClick: () => selectContext(item, source),
|
|
14696
|
-
children: [
|
|
14697
|
-
/* @__PURE__ */ (0, import_jsx_runtime186.jsx)(Icon, { name: item.icon ?? source.icon ?? "file-text", size: "sm" }),
|
|
14698
|
-
/* @__PURE__ */ (0, import_jsx_runtime186.jsx)("span", { className: "min-w-0 flex-1 truncate", children: item.label })
|
|
14699
|
-
]
|
|
14700
|
-
},
|
|
14701
|
-
item.id
|
|
14702
|
-
))
|
|
14703
|
-
] }, source.trigger)
|
|
14704
|
-
) })
|
|
14705
|
-
] }) : null
|
|
14706
|
-
]
|
|
14707
|
-
}
|
|
14708
|
-
);
|
|
14709
|
-
}
|
|
14710
|
-
|
|
14711
|
-
// src/components/chat/ConversationList/index.tsx
|
|
14712
|
-
var import_react68 = require("react");
|
|
14713
|
-
var import_jsx_runtime187 = require("react/jsx-runtime");
|
|
14714
|
-
function ConversationList({ items = [], activeId, searchable, onSelect, onDelete, className, style }) {
|
|
14715
|
-
const [innerActive, setInnerActive] = (0, import_react68.useState)();
|
|
14716
|
-
const [keyword, setKeyword] = (0, import_react68.useState)("");
|
|
14717
|
-
const active = activeId ?? innerActive;
|
|
14718
|
-
const filtered = (0, import_react68.useMemo)(() => {
|
|
14719
|
-
const query = keyword.trim().toLowerCase();
|
|
14720
|
-
if (!query) return items;
|
|
14721
|
-
return items.filter(
|
|
14722
|
-
(item) => item.title.toLowerCase().includes(query) || (item.description ?? "").toLowerCase().includes(query)
|
|
14723
|
-
);
|
|
14724
|
-
}, [items, keyword]);
|
|
14725
|
-
const select = (id) => {
|
|
14726
|
-
if (activeId === void 0) {
|
|
14727
|
-
setInnerActive(id);
|
|
14728
|
-
}
|
|
14729
|
-
onSelect?.(id);
|
|
14730
|
-
};
|
|
14731
|
-
return /* @__PURE__ */ (0, import_jsx_runtime187.jsxs)("div", { "data-slot": "conversation-list", className: cn("flex w-full flex-col gap-1", className), style, children: [
|
|
14732
|
-
searchable ? /* @__PURE__ */ (0, import_jsx_runtime187.jsxs)("div", { className: "relative mb-1", children: [
|
|
14733
|
-
/* @__PURE__ */ (0, import_jsx_runtime187.jsx)("span", { className: "absolute top-1/2 left-2 -translate-y-1/2 text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime187.jsx)(Icon, { name: "search", size: "sm" }) }),
|
|
14734
|
-
/* @__PURE__ */ (0, import_jsx_runtime187.jsx)(
|
|
14735
|
-
"input",
|
|
14736
|
-
{
|
|
14737
|
-
"data-slot": "conversation-list-search",
|
|
14738
|
-
value: keyword,
|
|
14739
|
-
placeholder: "\u641C\u7D22\u4F1A\u8BDD",
|
|
14740
|
-
className: "h-8 w-full rounded-md border border-border bg-background pr-2 pl-7 text-sm outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50",
|
|
14741
|
-
onChange: (event) => setKeyword(event.target.value)
|
|
14742
|
-
}
|
|
14743
|
-
)
|
|
14744
|
-
] }) : null,
|
|
14745
|
-
filtered.map((item) => /* @__PURE__ */ (0, import_jsx_runtime187.jsxs)(
|
|
14746
|
-
"div",
|
|
14747
|
-
{
|
|
14748
|
-
"data-slot": "conversation-list-item",
|
|
14749
|
-
"data-active": item.id === active || void 0,
|
|
14750
|
-
className: cn(
|
|
14751
|
-
"group flex cursor-pointer items-center gap-2 rounded-md px-2 py-1.5 hover:bg-accent",
|
|
14752
|
-
item.id === active && "bg-accent"
|
|
14753
|
-
),
|
|
14754
|
-
onClick: () => select(item.id),
|
|
14755
|
-
children: [
|
|
14756
|
-
/* @__PURE__ */ (0, import_jsx_runtime187.jsxs)("div", { className: "min-w-0 flex-1", children: [
|
|
14757
|
-
/* @__PURE__ */ (0, import_jsx_runtime187.jsx)("div", { className: cn("truncate text-sm", item.id === active && "font-medium"), children: item.title }),
|
|
14758
|
-
item.description ? /* @__PURE__ */ (0, import_jsx_runtime187.jsx)("div", { className: "truncate text-xs text-muted-foreground", children: item.description }) : null
|
|
14759
|
-
] }),
|
|
14760
|
-
item.time ? /* @__PURE__ */ (0, import_jsx_runtime187.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: item.time }) : null,
|
|
14761
|
-
onDelete ? /* @__PURE__ */ (0, import_jsx_runtime187.jsx)(
|
|
14762
|
-
"button",
|
|
14763
|
-
{
|
|
14764
|
-
type: "button",
|
|
14765
|
-
"data-slot": "conversation-list-delete",
|
|
14766
|
-
"aria-label": `\u5220\u9664 ${item.title}`,
|
|
14767
|
-
className: "shrink-0 text-muted-foreground opacity-0 group-hover:opacity-100 hover:text-destructive",
|
|
14768
|
-
onClick: (event) => {
|
|
14769
|
-
event.stopPropagation();
|
|
14770
|
-
onDelete(item.id);
|
|
14771
|
-
},
|
|
14772
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime187.jsx)(Icon, { name: "trash-2", size: "sm" })
|
|
14773
|
-
}
|
|
14774
|
-
) : null
|
|
14775
|
-
]
|
|
14776
|
-
},
|
|
14777
|
-
item.id
|
|
14778
|
-
)),
|
|
14779
|
-
filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime187.jsx)("div", { className: "px-2 py-4 text-center text-sm text-muted-foreground", children: "\u65E0\u5339\u914D\u4F1A\u8BDD" }) : null
|
|
14780
|
-
] });
|
|
14781
|
-
}
|
|
14782
|
-
|
|
14783
|
-
// src/components/chat/MessageList/index.tsx
|
|
14784
|
-
var import_react69 = require("react");
|
|
14785
|
-
var import_jsx_runtime188 = require("react/jsx-runtime");
|
|
14786
|
-
function MessageList({ messages = [], autoScroll = true, onAction, onOpenArtifacts, className, style }) {
|
|
14787
|
-
const listRef = (0, import_react69.useRef)(null);
|
|
14788
|
-
(0, import_react69.useEffect)(() => {
|
|
14789
|
-
if (!autoScroll) return;
|
|
14790
|
-
const el = listRef.current;
|
|
14791
|
-
if (el) {
|
|
14792
|
-
el.scrollTop = el.scrollHeight;
|
|
14793
|
-
}
|
|
14794
|
-
}, [messages, autoScroll]);
|
|
14795
|
-
return /* @__PURE__ */ (0, import_jsx_runtime188.jsx)(
|
|
14796
|
-
"div",
|
|
14797
|
-
{
|
|
14798
|
-
ref: listRef,
|
|
14799
|
-
"data-slot": "message-list",
|
|
14800
|
-
className: cn("flex w-full flex-col gap-4 overflow-y-auto", className),
|
|
14801
|
-
style,
|
|
14802
|
-
children: messages.map((message, index) => /* @__PURE__ */ (0, import_jsx_runtime188.jsx)(
|
|
14803
|
-
ChatMessage,
|
|
14804
|
-
{
|
|
14805
|
-
...message,
|
|
14806
|
-
onAction: (action) => onAction?.({ id: message.id, action }),
|
|
14807
|
-
onOpenArtifacts: onOpenArtifacts ? () => onOpenArtifacts({ id: message.id }) : void 0
|
|
14808
|
-
},
|
|
14809
|
-
message.id ?? index
|
|
14810
|
-
))
|
|
14811
|
-
}
|
|
14812
|
-
);
|
|
14813
|
-
}
|
|
14814
|
-
|
|
14815
|
-
// src/components/chat/Prompt/index.tsx
|
|
14816
|
-
var import_jsx_runtime189 = require("react/jsx-runtime");
|
|
14817
|
-
function Prompt({ title, description, icon, value, disabled, onSelect, className, style }) {
|
|
14818
|
-
return /* @__PURE__ */ (0, import_jsx_runtime189.jsxs)(
|
|
14819
|
-
"button",
|
|
14820
|
-
{
|
|
14821
|
-
type: "button",
|
|
14822
|
-
"data-slot": "prompt",
|
|
14823
|
-
disabled,
|
|
14824
|
-
className: cn(
|
|
14825
|
-
"flex items-start gap-2.5 rounded-md border border-border p-3 text-left transition-colors hover:border-primary disabled:pointer-events-none disabled:opacity-50",
|
|
14826
|
-
className
|
|
14827
|
-
),
|
|
14828
|
-
style,
|
|
14829
|
-
onClick: () => onSelect?.(value ?? title ?? ""),
|
|
14830
|
-
children: [
|
|
14831
|
-
icon ? /* @__PURE__ */ (0, import_jsx_runtime189.jsx)("span", { className: "mt-0.5 shrink-0 text-primary", children: /* @__PURE__ */ (0, import_jsx_runtime189.jsx)(Icon, { name: icon, size: "sm" }) }) : null,
|
|
14832
|
-
/* @__PURE__ */ (0, import_jsx_runtime189.jsxs)("span", { className: "min-w-0", children: [
|
|
14833
|
-
/* @__PURE__ */ (0, import_jsx_runtime189.jsx)("span", { "data-slot": "prompt-title", className: "block text-sm font-medium", children: title }),
|
|
14834
|
-
description ? /* @__PURE__ */ (0, import_jsx_runtime189.jsx)("span", { "data-slot": "prompt-description", className: "mt-0.5 block text-xs text-muted-foreground", children: description }) : null
|
|
14835
|
-
] })
|
|
14836
|
-
]
|
|
14837
|
-
}
|
|
14838
|
-
);
|
|
14839
|
-
}
|
|
14840
|
-
|
|
14841
|
-
// src/components/chat/Welcome/index.tsx
|
|
14842
|
-
var import_jsx_runtime190 = require("react/jsx-runtime");
|
|
14843
|
-
function Welcome({
|
|
14844
|
-
title = "\u6709\u4EC0\u4E48\u53EF\u4EE5\u5E2E\u4F60\uFF1F",
|
|
14845
|
-
description,
|
|
14846
|
-
icon = "chat",
|
|
14847
|
-
prompts = [],
|
|
14848
|
-
onSelect,
|
|
14849
|
-
className,
|
|
14850
|
-
style
|
|
14851
|
-
}) {
|
|
14852
|
-
return /* @__PURE__ */ (0, import_jsx_runtime190.jsxs)(
|
|
14853
|
-
"div",
|
|
14854
|
-
{
|
|
14855
|
-
"data-slot": "welcome",
|
|
14856
|
-
className: cn("flex w-full flex-col items-center gap-4 py-10 text-center", className),
|
|
14857
|
-
style,
|
|
14858
|
-
children: [
|
|
14859
|
-
/* @__PURE__ */ (0, import_jsx_runtime190.jsx)("span", { "data-slot": "welcome-icon", className: "text-primary", children: /* @__PURE__ */ (0, import_jsx_runtime190.jsx)(Icon, { name: icon, size: "lg" }) }),
|
|
14860
|
-
/* @__PURE__ */ (0, import_jsx_runtime190.jsxs)("div", { children: [
|
|
14861
|
-
/* @__PURE__ */ (0, import_jsx_runtime190.jsx)("div", { "data-slot": "welcome-title", className: "text-xl font-semibold", children: title }),
|
|
14862
|
-
description ? /* @__PURE__ */ (0, import_jsx_runtime190.jsx)("div", { "data-slot": "welcome-description", className: "mt-1 text-sm text-muted-foreground", children: description }) : null
|
|
14863
|
-
] }),
|
|
14864
|
-
prompts.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime190.jsx)("div", { "data-slot": "welcome-prompts", className: "grid w-full max-w-xl grid-cols-1 gap-3 text-left sm:grid-cols-2", children: prompts.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime190.jsx)(
|
|
14865
|
-
Prompt,
|
|
14866
|
-
{
|
|
14867
|
-
title: item.title,
|
|
14868
|
-
description: item.description,
|
|
14869
|
-
icon: item.icon,
|
|
14870
|
-
value: item.value,
|
|
14871
|
-
onSelect
|
|
14872
|
-
},
|
|
14873
|
-
`${item.title}-${index}`
|
|
14874
|
-
)) }) : null
|
|
14875
|
-
]
|
|
14876
|
-
}
|
|
14877
|
-
);
|
|
14878
|
-
}
|
|
14879
|
-
|
|
14880
|
-
// src/components/chat/ChatPage/index.tsx
|
|
14881
|
-
var import_jsx_runtime191 = require("react/jsx-runtime");
|
|
14882
|
-
function ChatPage({
|
|
14883
|
-
brand,
|
|
14884
|
-
menuItems = [],
|
|
14885
|
-
activeMenuKey,
|
|
14886
|
-
railItems = [],
|
|
14887
|
-
railFooterItems = [],
|
|
14888
|
-
menuAction,
|
|
14889
|
-
onMenuSelect,
|
|
14890
|
-
onMenuAction,
|
|
14891
|
-
conversationSectionTitle,
|
|
14892
|
-
conversationSectionCollapsed,
|
|
14893
|
-
defaultConversationSectionCollapsed = false,
|
|
14894
|
-
onConversationSectionToggle,
|
|
14895
|
-
conversations = [],
|
|
14896
|
-
activeConversationId,
|
|
14897
|
-
onSelectConversation,
|
|
14898
|
-
onDeleteConversation,
|
|
14899
|
-
moreLabel,
|
|
14900
|
-
onMore,
|
|
14901
|
-
footerSectionTitle,
|
|
14902
|
-
footerItems = [],
|
|
14903
|
-
footerSectionCollapsed,
|
|
14904
|
-
defaultFooterSectionCollapsed = false,
|
|
14905
|
-
onFooterSectionToggle,
|
|
14906
|
-
conversationTitle,
|
|
14907
|
-
conversationHeaderAction,
|
|
14908
|
-
onConversationHeaderAction,
|
|
14909
|
-
conversationRailItems = [],
|
|
14910
|
-
hideArtifactRailItem = false,
|
|
14911
|
-
activeConversationRailKey,
|
|
14912
|
-
onConversationRailChange,
|
|
14913
|
-
messages = [],
|
|
14914
|
-
sending,
|
|
14915
|
-
composerPlaceholder,
|
|
14916
|
-
welcome,
|
|
14917
|
-
onSend,
|
|
14918
|
-
onMessageAction,
|
|
14919
|
-
models,
|
|
14920
|
-
model,
|
|
14921
|
-
onModelChange,
|
|
14922
|
-
contexts,
|
|
14923
|
-
contextItems,
|
|
14924
|
-
onContextItemsChange,
|
|
14925
|
-
attachments,
|
|
14926
|
-
onAttachFiles,
|
|
14927
|
-
onRemoveAttachment,
|
|
14928
|
-
onRetryAttachment,
|
|
14929
|
-
composerFooter,
|
|
14930
|
-
composerBottom,
|
|
14931
|
-
artifactTitle = "\u4EA7\u7269",
|
|
14932
|
-
artifacts = [],
|
|
14933
|
-
activeArtifactId,
|
|
14934
|
-
onSelectArtifact,
|
|
14935
|
-
artifactEmptyText = "\u6682\u65E0\u4EA7\u7269\uFF0C\u53D1\u9001\u6D88\u606F\u540E\u751F\u6210\u7684\u6587\u4EF6\u5C06\u5C55\u793A\u5728\u8FD9\u91CC",
|
|
14936
|
-
safeRegistry,
|
|
14937
|
-
user,
|
|
14938
|
-
artifactViewers,
|
|
14939
|
-
onDownloadArtifact,
|
|
14940
|
-
artifactOpen,
|
|
14941
|
-
defaultArtifactOpen = false,
|
|
14942
|
-
onArtifactOpenChange,
|
|
14943
|
-
content,
|
|
14944
|
-
className,
|
|
14945
|
-
style
|
|
14946
|
-
}) {
|
|
14947
|
-
const controlled = artifactOpen !== void 0;
|
|
14948
|
-
const [innerOpen, setInnerOpen] = (0, import_react70.useState)(defaultArtifactOpen);
|
|
14949
|
-
const open = controlled ? artifactOpen === true : innerOpen;
|
|
14950
|
-
const setOpen = (next) => {
|
|
14951
|
-
if (!controlled) setInnerOpen(next);
|
|
14952
|
-
onArtifactOpenChange?.(next);
|
|
14953
|
-
};
|
|
14954
|
-
const railControlled = activeConversationRailKey !== void 0;
|
|
14955
|
-
const [activeRailInner, setActiveRailInner] = (0, import_react70.useState)(null);
|
|
14956
|
-
const activeRailKey = railControlled ? activeConversationRailKey : activeRailInner;
|
|
14957
|
-
const setActiveRailKey = (next) => {
|
|
14958
|
-
if (!railControlled) setActiveRailInner(next);
|
|
14959
|
-
onConversationRailChange?.(next);
|
|
14960
|
-
};
|
|
14961
|
-
const visibleRailItems = conversationRailItems.filter((item) => item.hidden !== true);
|
|
14962
|
-
const activeRailItem = visibleRailItems.find(
|
|
14963
|
-
(item) => item.key === activeRailKey
|
|
14964
|
-
);
|
|
14965
|
-
const activePanelItem = activeRailItem?.display === "panel" && activeRailItem.content !== void 0 ? activeRailItem : void 0;
|
|
14966
|
-
const activePopoverItem = activeRailItem !== void 0 && activeRailItem.display !== "panel" && activeRailItem.content !== void 0 ? activeRailItem : void 0;
|
|
14967
|
-
const toggleRailItem = (item) => {
|
|
14968
|
-
const next = activeRailKey === item.key ? null : item.key;
|
|
14969
|
-
if (next !== null && item.display === "panel") {
|
|
14970
|
-
setOpen(false);
|
|
14971
|
-
}
|
|
14972
|
-
setActiveRailKey(next);
|
|
14973
|
-
};
|
|
14974
|
-
const toggleArtifact = () => {
|
|
14975
|
-
if (!open && activePanelItem) {
|
|
14976
|
-
setActiveRailKey(null);
|
|
14977
|
-
}
|
|
14978
|
-
setOpen(!open);
|
|
14979
|
-
};
|
|
14980
|
-
(0, import_react70.useEffect)(() => {
|
|
14981
|
-
if (!activePopoverItem) return;
|
|
14982
|
-
const onKeyDown = (event) => {
|
|
14983
|
-
if (event.key === "Escape") setActiveRailKey(null);
|
|
14984
|
-
};
|
|
14985
|
-
const onPointerDown = (event) => {
|
|
14986
|
-
const target = event.target;
|
|
14987
|
-
if (target.closest("[data-slot=chat-page-rail-popover]") || target.closest("[data-slot=chat-page-conv-rail]")) {
|
|
14988
|
-
return;
|
|
14989
|
-
}
|
|
14990
|
-
setActiveRailKey(null);
|
|
14991
|
-
};
|
|
14992
|
-
document.addEventListener("keydown", onKeyDown);
|
|
14993
|
-
document.addEventListener("mousedown", onPointerDown);
|
|
14994
|
-
return () => {
|
|
14995
|
-
document.removeEventListener("keydown", onKeyDown);
|
|
14996
|
-
document.removeEventListener("mousedown", onPointerDown);
|
|
14997
|
-
};
|
|
14998
|
-
});
|
|
14999
|
-
const { renderChildren } = (0, import_runtime51.useRenderer)();
|
|
15000
|
-
const renderSlot = (slot) => (0, import_react70.isValidElement)(slot) || typeof slot !== "object" || slot === null ? slot : renderChildren([slot]);
|
|
15001
|
-
const convCollControlled = conversationSectionCollapsed !== void 0;
|
|
15002
|
-
const [convCollapsedInner, setConvCollapsedInner] = (0, import_react70.useState)(
|
|
15003
|
-
defaultConversationSectionCollapsed
|
|
15004
|
-
);
|
|
15005
|
-
const convCollapsed = convCollControlled ? conversationSectionCollapsed === true : convCollapsedInner;
|
|
15006
|
-
const toggleConvSection = () => {
|
|
15007
|
-
const next = !convCollapsed;
|
|
15008
|
-
if (!convCollControlled) setConvCollapsedInner(next);
|
|
15009
|
-
onConversationSectionToggle?.(next);
|
|
15010
|
-
};
|
|
15011
|
-
const footerCollControlled = footerSectionCollapsed !== void 0;
|
|
15012
|
-
const [footerCollapsedInner, setFooterCollapsedInner] = (0, import_react70.useState)(
|
|
15013
|
-
defaultFooterSectionCollapsed
|
|
15014
|
-
);
|
|
15015
|
-
const footerCollapsed = footerCollControlled ? footerSectionCollapsed === true : footerCollapsedInner;
|
|
15016
|
-
const toggleFooterSection = () => {
|
|
15017
|
-
const next = !footerCollapsed;
|
|
15018
|
-
if (!footerCollControlled) setFooterCollapsedInner(next);
|
|
15019
|
-
onFooterSectionToggle?.(next);
|
|
15020
|
-
};
|
|
15021
|
-
const railVisible = railItems.length > 0 || railFooterItems.length > 0;
|
|
15022
|
-
const railButton = (item) => /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Tooltip2, { content: item.label, side: "right", children: /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
|
|
15023
|
-
Button2,
|
|
15024
|
-
{
|
|
15025
|
-
icon: item.icon,
|
|
15026
|
-
variant: "text",
|
|
15027
|
-
onClick: () => onMenuSelect?.(item.key)
|
|
15028
|
-
}
|
|
15029
|
-
) }, item.key);
|
|
15030
|
-
const convRailButton = (item, active, onClick) => {
|
|
15031
|
-
const button = /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
|
|
15032
|
-
Button2,
|
|
15033
|
-
{
|
|
15034
|
-
icon: item.icon,
|
|
15035
|
-
variant: "text",
|
|
15036
|
-
className: cn(active ? "bg-accent text-accent-foreground" : void 0, "px-2"),
|
|
15037
|
-
onClick
|
|
15038
|
-
}
|
|
15039
|
-
);
|
|
15040
|
-
return item.label !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Tooltip2, { content: item.label, side: "left", children: button }, item.key) : /* @__PURE__ */ (0, import_jsx_runtime191.jsx)("span", { children: button }, item.key);
|
|
15041
|
-
};
|
|
15042
|
-
const convRailVisible = !hideArtifactRailItem || visibleRailItems.length > 0;
|
|
15043
|
-
const convRail = convRailVisible ? /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)(
|
|
15044
|
-
"div",
|
|
15045
|
-
{
|
|
15046
|
-
"data-slot": "chat-page-conv-rail",
|
|
15047
|
-
className: "relative flex w-(--pactor-chat-rail-width) shrink-0 flex-col items-center gap-1 px-1 py-2",
|
|
15048
|
-
children: [
|
|
15049
|
-
!hideArtifactRailItem ? convRailButton(
|
|
15050
|
-
{
|
|
15051
|
-
key: "artifact",
|
|
15052
|
-
icon: open ? "panel-right-close" : "package",
|
|
15053
|
-
label: open ? "\u6536\u8D77\u4EA7\u7269\u533A" : artifactTitle
|
|
15054
|
-
},
|
|
15055
|
-
open,
|
|
15056
|
-
toggleArtifact
|
|
15057
|
-
) : null,
|
|
15058
|
-
visibleRailItems.map(
|
|
15059
|
-
(item) => convRailButton(item, activeRailKey === item.key, () => toggleRailItem(item))
|
|
15060
|
-
),
|
|
15061
|
-
activePopoverItem ? /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
|
|
15062
|
-
"div",
|
|
15063
|
-
{
|
|
15064
|
-
"data-slot": "chat-page-rail-popover",
|
|
15065
|
-
className: "absolute right-full top-0 z-10 mr-2 overflow-auto rounded-lg border border-border bg-popover shadow-md",
|
|
15066
|
-
style: {
|
|
15067
|
-
width: "var(--pactor-chat-rail-popover-width)",
|
|
15068
|
-
maxWidth: "calc(100cqw - 2rem)",
|
|
15069
|
-
maxHeight: "calc(100% - 1rem)"
|
|
15070
|
-
},
|
|
15071
|
-
children: renderSlot(activePopoverItem.content)
|
|
15072
|
-
}
|
|
15073
|
-
) : null
|
|
15074
|
-
]
|
|
15075
|
-
}
|
|
15076
|
-
) : null;
|
|
15077
|
-
const chatArea = /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)("div", { "data-slot": "chat-page-conversation", className: "flex h-full min-w-0 flex-1 flex-col", children: [
|
|
15078
|
-
/* @__PURE__ */ (0, import_jsx_runtime191.jsxs)(
|
|
15079
|
-
"div",
|
|
15080
|
-
{
|
|
15081
|
-
"data-slot": "chat-page-conversation-header",
|
|
15082
|
-
className: "flex shrink-0 items-center justify-between border-b border-border px-4 py-2.5",
|
|
15083
|
-
children: [
|
|
15084
|
-
/* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Text, { text: conversationTitle, strong: true }),
|
|
15085
|
-
conversationHeaderAction ? /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Tooltip2, { content: conversationHeaderAction.tooltip ?? conversationHeaderAction.label, side: "bottom", children: /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
|
|
15086
|
-
Button2,
|
|
15087
|
-
{
|
|
15088
|
-
text: conversationHeaderAction.label,
|
|
15089
|
-
icon: conversationHeaderAction.icon,
|
|
15090
|
-
variant: "text",
|
|
15091
|
-
onClick: () => onConversationHeaderAction?.()
|
|
15092
|
-
}
|
|
15093
|
-
) }) : null
|
|
15094
|
-
]
|
|
15095
|
-
}
|
|
15096
|
-
),
|
|
15097
|
-
/* @__PURE__ */ (0, import_jsx_runtime191.jsxs)("div", { className: "flex min-h-0 flex-1", children: [
|
|
15098
|
-
/* @__PURE__ */ (0, import_jsx_runtime191.jsxs)(
|
|
15099
|
-
"div",
|
|
15100
|
-
{
|
|
15101
|
-
"data-slot": "chat-page-conversation-body",
|
|
15102
|
-
className: "mx-auto flex min-h-0 w-[61.8cqw] max-w-full flex-col",
|
|
15103
|
-
children: [
|
|
15104
|
-
messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
|
|
15105
|
-
Welcome,
|
|
15106
|
-
{
|
|
15107
|
-
title: welcome?.title,
|
|
15108
|
-
description: welcome?.description,
|
|
15109
|
-
prompts: welcome?.prompts,
|
|
15110
|
-
style: { flex: 1 },
|
|
15111
|
-
onSelect: (value) => onSend?.(value)
|
|
15112
|
-
}
|
|
15113
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
|
|
15114
|
-
MessageList,
|
|
15115
|
-
{
|
|
15116
|
-
messages,
|
|
15117
|
-
className: "scrollbar-subtle",
|
|
15118
|
-
style: { flex: 1, minHeight: 0, padding: 16 },
|
|
15119
|
-
onAction: onMessageAction,
|
|
15120
|
-
onOpenArtifacts: () => setOpen(true)
|
|
15121
|
-
}
|
|
15122
|
-
),
|
|
15123
|
-
/* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
|
|
15124
|
-
Composer,
|
|
15125
|
-
{
|
|
15126
|
-
placeholder: composerPlaceholder,
|
|
15127
|
-
loading: sending,
|
|
15128
|
-
models,
|
|
15129
|
-
model,
|
|
15130
|
-
contexts,
|
|
15131
|
-
contextItems,
|
|
15132
|
-
attachments,
|
|
15133
|
-
footer: composerFooter,
|
|
15134
|
-
style: { padding: 16, paddingBottom: composerBottom ? 8 : 16, flexShrink: 0 },
|
|
15135
|
-
onModelChange,
|
|
15136
|
-
onContextItemsChange,
|
|
15137
|
-
onAttachFiles,
|
|
15138
|
-
onRemoveAttachment,
|
|
15139
|
-
onRetryAttachment,
|
|
15140
|
-
onSubmit: (text) => onSend?.(text)
|
|
15141
|
-
}
|
|
15142
|
-
),
|
|
15143
|
-
composerBottom ? /* @__PURE__ */ (0, import_jsx_runtime191.jsx)("div", { "data-slot": "chat-page-composer-bottom", className: "shrink-0 px-4 pb-2 text-center", children: renderSlot(composerBottom) }) : null
|
|
15144
|
-
]
|
|
15145
|
-
}
|
|
15146
|
-
),
|
|
15147
|
-
convRail
|
|
15148
|
-
] })
|
|
15149
|
-
] });
|
|
15150
|
-
const activeArtifact = artifacts.find((item) => item.id === activeArtifactId) ?? (activeArtifactId === void 0 || activeArtifactId === "" ? artifacts[artifacts.length - 1] : void 0);
|
|
15151
|
-
const artifactPanel = /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
|
|
15152
|
-
"div",
|
|
15153
|
-
{
|
|
15154
|
-
"data-slot": "chat-page-artifact",
|
|
15155
|
-
className: "flex h-full min-w-0 flex-col border-l border-border bg-muted",
|
|
15156
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
|
|
15157
|
-
ArtifactPanel,
|
|
15158
|
-
{
|
|
15159
|
-
artifact: activeArtifact,
|
|
15160
|
-
artifacts,
|
|
15161
|
-
activeArtifactId,
|
|
15162
|
-
title: artifactTitle,
|
|
15163
|
-
emptyText: artifactEmptyText,
|
|
15164
|
-
safeRegistry,
|
|
15165
|
-
user,
|
|
15166
|
-
artifactViewers,
|
|
15167
|
-
onSelectArtifact: (id) => onSelectArtifact?.(id),
|
|
15168
|
-
onDownload: onDownloadArtifact,
|
|
15169
|
-
onClose: () => setOpen(false)
|
|
15170
|
-
}
|
|
15171
|
-
)
|
|
15172
|
-
}
|
|
15173
|
-
);
|
|
15174
|
-
return /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)(
|
|
15175
|
-
"div",
|
|
15176
|
-
{
|
|
15177
|
-
"data-slot": "chat-page",
|
|
15178
|
-
className: cn("flex w-full overflow-hidden", className),
|
|
15179
|
-
style: { height: "100vh", ...style },
|
|
15180
|
-
children: [
|
|
15181
|
-
railVisible ? /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)(
|
|
15182
|
-
"div",
|
|
15183
|
-
{
|
|
15184
|
-
"data-slot": "chat-page-rail",
|
|
15185
|
-
className: "flex h-full w-[52px] shrink-0 flex-col items-center gap-1 border-r border-border py-2.5",
|
|
15186
|
-
children: [
|
|
15187
|
-
railItems.map(railButton),
|
|
15188
|
-
/* @__PURE__ */ (0, import_jsx_runtime191.jsx)("div", { className: "flex-1" }),
|
|
15189
|
-
railFooterItems.map(railButton)
|
|
15190
|
-
]
|
|
15191
|
-
}
|
|
15192
|
-
) : null,
|
|
15193
|
-
/* @__PURE__ */ (0, import_jsx_runtime191.jsxs)(
|
|
15194
|
-
"div",
|
|
15195
|
-
{
|
|
15196
|
-
"data-slot": "chat-page-menu",
|
|
15197
|
-
className: "flex h-full w-[250px] shrink-0 flex-col gap-2 overflow-hidden border-r border-border px-2 py-3",
|
|
15198
|
-
children: [
|
|
15199
|
-
brand ? /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)("div", { className: "flex shrink-0 items-center justify-between px-2", children: [
|
|
15200
|
-
/* @__PURE__ */ (0, import_jsx_runtime191.jsxs)("div", { className: "flex flex-col gap-0.5", children: [
|
|
15201
|
-
/* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Text, { text: brand.title, strong: true, size: "large" }),
|
|
15202
|
-
brand.version !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Text, { text: brand.version, type: "secondary", size: "small" }) : null
|
|
15203
|
-
] }),
|
|
15204
|
-
menuAction ? /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
|
|
15205
|
-
Button2,
|
|
15206
|
-
{
|
|
15207
|
-
text: menuAction.label,
|
|
15208
|
-
icon: menuAction.icon,
|
|
15209
|
-
size: "small",
|
|
15210
|
-
onClick: () => onMenuAction?.()
|
|
15211
|
-
}
|
|
15212
|
-
) : null
|
|
15213
|
-
] }) : null,
|
|
15214
|
-
/* @__PURE__ */ (0, import_jsx_runtime191.jsx)("div", { className: "scrollbar-subtle max-h-[40%] min-h-0 shrink-0 overflow-y-auto", children: /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
|
|
15215
|
-
Menu2,
|
|
15216
|
-
{
|
|
15217
|
-
items: menuItems,
|
|
15218
|
-
selectedKey: activeMenuKey,
|
|
15219
|
-
onSelect: (key) => onMenuSelect?.(key)
|
|
15220
|
-
}
|
|
15221
|
-
) }),
|
|
15222
|
-
conversationSectionTitle !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)(
|
|
15223
|
-
"button",
|
|
15224
|
-
{
|
|
15225
|
-
type: "button",
|
|
15226
|
-
"data-slot": "chat-page-section-toggle",
|
|
15227
|
-
"aria-expanded": !convCollapsed,
|
|
15228
|
-
className: "flex w-full shrink-0 cursor-pointer items-center justify-between px-2 pt-2",
|
|
15229
|
-
onClick: toggleConvSection,
|
|
15230
|
-
children: [
|
|
15231
|
-
/* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
|
|
15232
|
-
Text,
|
|
15233
|
-
{
|
|
15234
|
-
text: `${conversationSectionTitle} (${conversations.length})`,
|
|
15235
|
-
type: "secondary",
|
|
15236
|
-
className: "text-sm",
|
|
15237
|
-
strong: true
|
|
15238
|
-
}
|
|
15239
|
-
),
|
|
15240
|
-
/* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Icon, { name: convCollapsed ? "chevron-right" : "chevron-down", size: 14 })
|
|
15241
|
-
]
|
|
15242
|
-
}
|
|
15243
|
-
) : null,
|
|
15244
|
-
!convCollapsed ? /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)("div", { "data-slot": "chat-page-section-body", className: "scrollbar-subtle flex min-h-0 flex-1 flex-col overflow-y-auto", children: [
|
|
15245
|
-
/* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
|
|
15246
|
-
ConversationList,
|
|
15247
|
-
{
|
|
15248
|
-
items: conversations,
|
|
15249
|
-
activeId: activeConversationId,
|
|
15250
|
-
onSelect: (id) => onSelectConversation?.(id),
|
|
15251
|
-
onDelete: (id) => onDeleteConversation?.(id)
|
|
15252
|
-
}
|
|
15253
|
-
),
|
|
15254
|
-
moreLabel !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime191.jsx)("div", { className: "flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Button2, { text: `${moreLabel} >>`, variant: "link", size: "small", onClick: () => onMore?.() }) }) : null
|
|
15255
|
-
] }) : null,
|
|
15256
|
-
footerSectionTitle !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)(
|
|
15257
|
-
"button",
|
|
15258
|
-
{
|
|
15259
|
-
type: "button",
|
|
15260
|
-
"data-slot": "chat-page-section-toggle",
|
|
15261
|
-
"aria-expanded": !footerCollapsed,
|
|
15262
|
-
className: "flex w-full shrink-0 cursor-pointer items-center justify-between px-2 pt-2",
|
|
15263
|
-
onClick: toggleFooterSection,
|
|
15264
|
-
children: [
|
|
15265
|
-
/* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Text, { text: footerSectionTitle, type: "secondary", className: "text-sm", strong: true }),
|
|
15266
|
-
/* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Icon, { name: footerCollapsed ? "chevron-right" : "chevron-down", size: 14 })
|
|
15267
|
-
]
|
|
15268
|
-
}
|
|
15269
|
-
) : null,
|
|
15270
|
-
!footerCollapsed && footerItems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime191.jsx)("div", { "data-slot": "chat-page-section-body", className: "scrollbar-subtle min-h-0 flex-1 overflow-y-auto", children: /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
|
|
15271
|
-
Menu2,
|
|
15272
|
-
{
|
|
15273
|
-
items: footerItems,
|
|
15274
|
-
onSelect: (key) => onMenuSelect?.(key)
|
|
15275
|
-
}
|
|
15276
|
-
) }) : null
|
|
15277
|
-
]
|
|
15278
|
-
}
|
|
15279
|
-
),
|
|
15280
|
-
/* @__PURE__ */ (0, import_jsx_runtime191.jsx)("div", { className: "@container h-full min-w-0 flex-1", children: content !== void 0 ? renderSlot(content) : open || activePanelItem ? /* @__PURE__ */ (0, import_jsx_runtime191.jsxs)(PanelGroup, { orientation: "horizontal", style: { width: "100%", height: "100%" }, children: [
|
|
15281
|
-
/* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Panel, { defaultSize: "62%", children: chatArea }),
|
|
15282
|
-
/* @__PURE__ */ (0, import_jsx_runtime191.jsx)(ResizableHandle, { withHandle: true }),
|
|
15283
|
-
/* @__PURE__ */ (0, import_jsx_runtime191.jsx)(Panel, { defaultSize: "38%", minSize: "380px", maxSize: "760px", children: activePanelItem ? /* @__PURE__ */ (0, import_jsx_runtime191.jsx)(
|
|
15284
|
-
"div",
|
|
15285
|
-
{
|
|
15286
|
-
"data-slot": "chat-page-rail-panel",
|
|
15287
|
-
className: "flex h-full min-w-0 flex-col border-l border-border bg-muted",
|
|
15288
|
-
children: renderSlot(activePanelItem.content)
|
|
15289
|
-
}
|
|
15290
|
-
) : artifactPanel })
|
|
15291
|
-
] }) : chatArea })
|
|
15292
|
-
]
|
|
15293
|
-
}
|
|
15294
|
-
);
|
|
15295
|
-
}
|
|
15296
|
-
|
|
15297
|
-
// src/components/chat/Citation/index.tsx
|
|
15298
|
-
var import_jsx_runtime192 = require("react/jsx-runtime");
|
|
15299
|
-
function Citation({ items = [], start = 1, className, style }) {
|
|
15300
|
-
return /* @__PURE__ */ (0, import_jsx_runtime192.jsx)("span", { "data-slot": "citation", className: cn("inline-flex gap-1 align-super", className), style, children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime192.jsxs)(HoverCard, { children: [
|
|
15301
|
-
/* @__PURE__ */ (0, import_jsx_runtime192.jsxs)(
|
|
15302
|
-
HoverCardTrigger,
|
|
15303
|
-
{
|
|
15304
|
-
"data-slot": "citation-marker",
|
|
15305
|
-
className: "cursor-pointer rounded-sm border border-border px-1 text-xs leading-4 text-primary hover:bg-accent",
|
|
15306
|
-
children: [
|
|
15307
|
-
"[",
|
|
15308
|
-
start + index,
|
|
15309
|
-
"]"
|
|
15310
|
-
]
|
|
15311
|
-
}
|
|
15312
|
-
),
|
|
15313
|
-
/* @__PURE__ */ (0, import_jsx_runtime192.jsxs)(HoverCardContent, { "data-slot": "citation-card", className: "w-72", children: [
|
|
15314
|
-
/* @__PURE__ */ (0, import_jsx_runtime192.jsx)("div", { className: "text-sm font-medium", children: item.title }),
|
|
15315
|
-
item.snippet ? /* @__PURE__ */ (0, import_jsx_runtime192.jsx)("div", { className: "mt-1 line-clamp-3 text-xs text-muted-foreground", children: item.snippet }) : null,
|
|
15316
|
-
item.url ? /* @__PURE__ */ (0, import_jsx_runtime192.jsx)(
|
|
15317
|
-
"a",
|
|
15318
|
-
{
|
|
15319
|
-
href: item.url,
|
|
15320
|
-
target: "_blank",
|
|
15321
|
-
rel: "noreferrer",
|
|
15322
|
-
className: "mt-1 block truncate text-xs text-primary hover:underline",
|
|
15323
|
-
children: item.url
|
|
15324
|
-
}
|
|
15325
|
-
) : null
|
|
15326
|
-
] })
|
|
15327
|
-
] }, `${item.title}-${index}`)) });
|
|
15328
|
-
}
|
|
15329
|
-
|
|
15330
|
-
// src/components/chat/StepsPanel/index.tsx
|
|
15331
|
-
var import_jsx_runtime193 = require("react/jsx-runtime");
|
|
15332
|
-
function StepsPanel({
|
|
15333
|
-
title = "\u6267\u884C\u6B65\u9AA4",
|
|
15334
|
-
steps = [],
|
|
15335
|
-
emptyText = "\u5F53\u524D\u4F1A\u8BDD\u6682\u65E0\u6267\u884C\u6B65\u9AA4",
|
|
15336
|
-
className,
|
|
15337
|
-
style
|
|
15338
|
-
}) {
|
|
15339
|
-
return /* @__PURE__ */ (0, import_jsx_runtime193.jsxs)(
|
|
15340
|
-
"div",
|
|
15341
|
-
{
|
|
15342
|
-
"data-slot": "steps-panel",
|
|
15343
|
-
className: cn("px-3.5 py-3 text-foreground", className),
|
|
15344
|
-
style,
|
|
15345
|
-
children: [
|
|
15346
|
-
/* @__PURE__ */ (0, import_jsx_runtime193.jsx)("div", { className: "mb-1 text-[13px] font-semibold", children: title }),
|
|
15347
|
-
steps.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime193.jsx)("div", { className: "py-4 text-center text-[13px] text-muted-foreground", children: emptyText }) : /* @__PURE__ */ (0, import_jsx_runtime193.jsx)("ol", { children: steps.map((step, index) => {
|
|
15348
|
-
const status = step.status ?? "pending";
|
|
15349
|
-
return /* @__PURE__ */ (0, import_jsx_runtime193.jsxs)(
|
|
15350
|
-
"li",
|
|
15351
|
-
{
|
|
15352
|
-
"data-status": status,
|
|
15353
|
-
className: cn(
|
|
15354
|
-
"relative flex gap-2 py-1.5",
|
|
15355
|
-
// 步骤之间的连接线(对齐 16px 图标中心)
|
|
15356
|
-
'not-last:before:absolute not-last:before:left-[7.5px] not-last:before:top-7 not-last:before:-bottom-1 not-last:before:w-px not-last:before:bg-border not-last:before:content-[""]'
|
|
15357
|
-
),
|
|
15358
|
-
children: [
|
|
15359
|
-
/* @__PURE__ */ (0, import_jsx_runtime193.jsx)(
|
|
15360
|
-
"span",
|
|
15361
|
-
{
|
|
15362
|
-
className: cn(
|
|
15363
|
-
"flex h-5 w-4 shrink-0 items-center justify-center",
|
|
15364
|
-
status !== "pending" && "text-primary"
|
|
15365
|
-
),
|
|
15366
|
-
children: status === "done" ? /* @__PURE__ */ (0, import_jsx_runtime193.jsx)(Icon, { name: "check-circle", size: 16 }) : status === "running" ? /* @__PURE__ */ (0, import_jsx_runtime193.jsx)(
|
|
15367
|
-
Icon,
|
|
15368
|
-
{
|
|
15369
|
-
name: "loading",
|
|
15370
|
-
size: 16,
|
|
15371
|
-
className: "animate-spin motion-reduce:animate-none"
|
|
15372
|
-
}
|
|
15373
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime193.jsx)("span", { className: "size-1.5 rounded-full bg-muted-foreground/50" })
|
|
15374
|
-
}
|
|
15375
|
-
),
|
|
15376
|
-
/* @__PURE__ */ (0, import_jsx_runtime193.jsxs)("div", { className: "min-w-0 flex-1", children: [
|
|
15377
|
-
/* @__PURE__ */ (0, import_jsx_runtime193.jsx)(
|
|
15378
|
-
"div",
|
|
15379
|
-
{
|
|
15380
|
-
className: cn(
|
|
15381
|
-
"text-[13px] leading-5",
|
|
15382
|
-
status === "pending" && "text-muted-foreground"
|
|
15383
|
-
),
|
|
15384
|
-
children: step.title
|
|
15385
|
-
}
|
|
15386
|
-
),
|
|
15387
|
-
step.description ? /* @__PURE__ */ (0, import_jsx_runtime193.jsx)("div", { className: "mt-0.5 text-xs leading-[18px] text-muted-foreground", children: step.description }) : null
|
|
15388
|
-
] }),
|
|
15389
|
-
step.duration ? /* @__PURE__ */ (0, import_jsx_runtime193.jsx)("span", { className: "shrink-0 text-xs leading-5 text-muted-foreground", children: step.duration }) : null
|
|
15390
|
-
]
|
|
15391
|
-
},
|
|
15392
|
-
`${step.title}-${index}`
|
|
15393
|
-
);
|
|
15394
|
-
}) })
|
|
15395
|
-
]
|
|
15396
|
-
}
|
|
15397
|
-
);
|
|
15398
|
-
}
|
|
15399
|
-
|
|
15400
|
-
// src/components/chat/Suggestion/index.tsx
|
|
15401
|
-
var import_jsx_runtime194 = require("react/jsx-runtime");
|
|
15402
|
-
function normalize(item) {
|
|
15403
|
-
if (typeof item === "string") return { label: item, value: item };
|
|
15404
|
-
return { label: item.label, value: item.value ?? item.label, icon: item.icon };
|
|
15405
|
-
}
|
|
15406
|
-
function Suggestion({ items = [], justify = "start", onSelect, className, style }) {
|
|
15407
|
-
return /* @__PURE__ */ (0, import_jsx_runtime194.jsx)(
|
|
15408
|
-
"div",
|
|
15409
|
-
{
|
|
15410
|
-
"data-slot": "suggestion",
|
|
15411
|
-
className: cn("flex flex-wrap gap-2", justify === "center" && "justify-center", className),
|
|
15412
|
-
style,
|
|
15413
|
-
children: items.map((item, index) => {
|
|
15414
|
-
const { label, value, icon } = normalize(item);
|
|
15415
|
-
return /* @__PURE__ */ (0, import_jsx_runtime194.jsxs)(
|
|
15416
|
-
"button",
|
|
15417
|
-
{
|
|
15418
|
-
type: "button",
|
|
15419
|
-
"data-slot": "suggestion-item",
|
|
15420
|
-
"data-value": value,
|
|
15421
|
-
className: "flex items-center gap-1.5 rounded-full border border-border px-3 py-1 text-sm transition-colors hover:bg-accent",
|
|
15422
|
-
onClick: () => onSelect?.(value),
|
|
15423
|
-
children: [
|
|
15424
|
-
icon ? /* @__PURE__ */ (0, import_jsx_runtime194.jsx)(Icon, { name: icon, size: "sm" }) : null,
|
|
15425
|
-
label
|
|
15426
|
-
]
|
|
15427
|
-
},
|
|
15428
|
-
`${value}-${index}`
|
|
15429
|
-
);
|
|
15430
|
-
})
|
|
15431
|
-
}
|
|
15432
|
-
);
|
|
15433
|
-
}
|
|
15434
|
-
|
|
15435
|
-
// src/components/register.ts
|
|
15436
|
-
var builtinComponents = {
|
|
15437
|
-
Page,
|
|
15438
|
-
Grid,
|
|
15439
|
-
Row,
|
|
15440
|
-
Col,
|
|
15441
|
-
// 循环渲染:行模板(原始 DSL children)由 For 逐项渲染并注入 { row, rowIndex } 作用域
|
|
15442
|
-
For: { component: For, withScope: true },
|
|
15443
|
-
Flex,
|
|
15444
|
-
Card: Card2,
|
|
15445
|
-
Button: Button2,
|
|
15446
|
-
Alert: Alert2,
|
|
15447
|
-
Statistic,
|
|
15448
|
-
Tabs: Tabs2,
|
|
15449
|
-
Table: Table3,
|
|
15450
|
-
Form,
|
|
15451
|
-
Input: Input2,
|
|
15452
|
-
NumberInput,
|
|
15453
|
-
Select: Select2,
|
|
15454
|
-
// Layout 需要原始 DSL 子树做方向推导(含 Sider 判定),以 withScope 注册
|
|
15455
|
-
Layout: { component: Layout, withScope: true },
|
|
15456
|
-
Header,
|
|
15457
|
-
Sider,
|
|
15458
|
-
Content,
|
|
15459
|
-
Footer,
|
|
15460
|
-
Menu: Menu2,
|
|
15461
|
-
Link: Link2,
|
|
15462
|
-
Text,
|
|
15463
|
-
// 展示类扩展组件
|
|
15464
|
-
Badge: Badge2,
|
|
15465
|
-
Avatar: Avatar2,
|
|
15466
|
-
Skeleton: Skeleton2,
|
|
15467
|
-
Separator: Separator2,
|
|
15468
|
-
Kbd: Kbd2,
|
|
15469
|
-
Spinner: Spinner2,
|
|
15470
|
-
Empty: Empty2,
|
|
15471
|
-
AspectRatio: AspectRatio2,
|
|
15472
|
-
Progress: Progress2,
|
|
15473
|
-
// 表单类扩展组件
|
|
15474
|
-
Textarea: Textarea2,
|
|
15475
|
-
Checkbox: Checkbox2,
|
|
15476
|
-
ChipFilter,
|
|
15477
|
-
ChipNode,
|
|
15478
|
-
RadioGroup: RadioGroup2,
|
|
15479
|
-
Switch: Switch2,
|
|
15480
|
-
Slider: Slider2,
|
|
15481
|
-
Label: Label2,
|
|
15482
|
-
Field: Field2,
|
|
15483
|
-
ChatInput,
|
|
15484
|
-
// 导航类扩展组件
|
|
15485
|
-
Breadcrumb: Breadcrumb2,
|
|
15486
|
-
Pagination: Pagination2,
|
|
15487
|
-
Menubar: Menubar2,
|
|
15488
|
-
NavigationMenu: NavigationMenu2,
|
|
15489
|
-
DropdownMenu: DropdownMenu2,
|
|
15490
|
-
ContextMenu: ContextMenu2,
|
|
15491
|
-
// 反馈与弹层类扩展组件
|
|
15492
|
-
Dialog: Dialog2,
|
|
15493
|
-
AlertDialog: AlertDialog2,
|
|
15494
|
-
Drawer: Drawer2,
|
|
15495
|
-
Sheet: Sheet2,
|
|
15496
|
-
Popover: Popover2,
|
|
15497
|
-
Sonner,
|
|
15498
|
-
Accordion: Accordion2,
|
|
15499
|
-
Collapsible: Collapsible2,
|
|
15500
|
-
Tooltip: Tooltip2,
|
|
15501
|
-
HoverCard: HoverCard2,
|
|
15502
|
-
// 复合类扩展组件(第三批)
|
|
15503
|
-
Calendar: Calendar3,
|
|
15504
|
-
DatePicker,
|
|
15505
|
-
InputOTP: InputOTP2,
|
|
15506
|
-
Combobox: Combobox2,
|
|
15507
|
-
Carousel: Carousel2,
|
|
15508
|
-
Command: Command2,
|
|
15509
|
-
Resizable,
|
|
15510
|
-
ScrollArea: ScrollArea2,
|
|
15511
|
-
Toggle: Toggle2,
|
|
15512
|
-
ToggleGroup: ToggleGroup2,
|
|
15513
|
-
ButtonGroup: ButtonGroup2,
|
|
15514
|
-
InputGroup: InputGroup2,
|
|
15515
|
-
Item: Item2,
|
|
15516
|
-
Typography: Typography2,
|
|
15517
|
-
// 页面级组合类扩展组件(第四批)
|
|
15518
|
-
Sidebar,
|
|
15519
|
-
DataTable,
|
|
15520
|
-
// 图标(lucide 白名单)
|
|
15521
|
-
Icon,
|
|
15522
|
-
// 业务刚需类扩展组件(第五批:数据录入 / 数据展示 / 反馈)
|
|
15523
|
-
Rate,
|
|
15524
|
-
TimePicker,
|
|
15525
|
-
ColorPicker,
|
|
15526
|
-
Upload: Upload2,
|
|
15527
|
-
TreeSelect,
|
|
15528
|
-
Cascader,
|
|
15529
|
-
Transfer,
|
|
15530
|
-
Mentions,
|
|
15531
|
-
List: List2,
|
|
15532
|
-
Tree,
|
|
15533
|
-
Descriptions,
|
|
15534
|
-
Timeline,
|
|
15535
|
-
Image: Image2,
|
|
15536
|
-
QRCode,
|
|
15537
|
-
Segmented,
|
|
15538
|
-
Message,
|
|
15539
|
-
Notification,
|
|
15540
|
-
Popconfirm,
|
|
15541
|
-
Result,
|
|
15542
|
-
LoadingOverlay,
|
|
15543
|
-
Watermark,
|
|
15544
|
-
Tour,
|
|
15545
|
-
// 基础补齐类扩展组件(第六批:通用 / 布局 / 导航)
|
|
15546
|
-
Tag: Tag2,
|
|
15547
|
-
Status,
|
|
15548
|
-
Space,
|
|
15549
|
-
Container,
|
|
15550
|
-
Steps,
|
|
15551
|
-
Anchor,
|
|
15552
|
-
BackTop,
|
|
15553
|
-
Affix,
|
|
15554
|
-
// 媒体与内容类扩展组件(第七批)
|
|
15555
|
-
ImageViewer,
|
|
15556
|
-
Gallery,
|
|
15557
|
-
Video: Video2,
|
|
15558
|
-
Audio,
|
|
15559
|
-
FilePreview,
|
|
15560
|
-
DocumentPreview,
|
|
15561
|
-
RichText,
|
|
15562
|
-
Markdown: import_markdown2.MarkdownDslComponent,
|
|
15563
|
-
CodeBlock,
|
|
15564
|
-
DiffViewer,
|
|
15565
|
-
JSONViewer,
|
|
15566
|
-
// AI 与会话类扩展组件(第八批:chat 子目录)
|
|
15567
|
-
Bubble: Bubble2,
|
|
15568
|
-
Sender,
|
|
15569
|
-
Thinking,
|
|
15570
|
-
AgentStatus,
|
|
15571
|
-
StreamingText,
|
|
15572
|
-
Suggestion,
|
|
15573
|
-
Prompt,
|
|
15574
|
-
Welcome,
|
|
15575
|
-
Citation,
|
|
15576
|
-
Attachment,
|
|
15577
|
-
ToolCall,
|
|
15578
|
-
ChatMessage,
|
|
15579
|
-
ChatPage,
|
|
15580
|
-
ArtifactPanel,
|
|
15581
|
-
MessageList,
|
|
15582
|
-
Composer,
|
|
15583
|
-
ConversationList,
|
|
15584
|
-
StepsPanel
|
|
15585
|
-
};
|
|
15586
|
-
function registerBuiltinComponents(registry) {
|
|
15587
|
-
for (const [type, component] of Object.entries(builtinComponents)) {
|
|
15588
|
-
registry.register(type, component);
|
|
15589
|
-
}
|
|
15590
|
-
}
|
|
15591
|
-
function createComponentRegistry() {
|
|
15592
|
-
const registry = new import_core3.Registry("ComponentRegistry");
|
|
15593
|
-
registerBuiltinComponents(registry);
|
|
15594
|
-
return registry;
|
|
15595
|
-
}
|
|
15596
|
-
|
|
15597
|
-
// src/layout/admin/menu-chain.ts
|
|
15598
|
-
function findMenuChain(registry, menuId) {
|
|
15599
|
-
const walk = (menus, ancestors) => {
|
|
15600
|
-
for (const menu of menus) {
|
|
15601
|
-
const chain = [...ancestors, menu];
|
|
15602
|
-
if (menu.id === menuId) {
|
|
15603
|
-
return chain;
|
|
15604
|
-
}
|
|
15605
|
-
if (menu.children !== void 0) {
|
|
15606
|
-
const hit = walk(menu.children, chain);
|
|
15607
|
-
if (hit !== null) {
|
|
15608
|
-
return hit;
|
|
15609
|
-
}
|
|
15610
|
-
}
|
|
15611
|
-
}
|
|
15612
|
-
return null;
|
|
15613
|
-
};
|
|
15614
|
-
return walk(registry.tree(), []) ?? [];
|
|
15615
|
-
}
|
|
15616
|
-
|
|
15617
|
-
// src/layout/admin/menu-items.ts
|
|
15618
|
-
function collectDefaultOpenKeys(registry, activeMenuId) {
|
|
15619
|
-
const keys = [];
|
|
15620
|
-
const walk = (menus) => {
|
|
15621
|
-
for (const menu of menus) {
|
|
15622
|
-
if (menu.type === "group" && menu.defaultOpen === true) {
|
|
15623
|
-
keys.push(menu.id);
|
|
15624
|
-
}
|
|
15625
|
-
if (menu.children !== void 0) {
|
|
15626
|
-
walk(menu.children);
|
|
15627
|
-
}
|
|
15628
|
-
}
|
|
15629
|
-
};
|
|
15630
|
-
walk(registry.tree());
|
|
15631
|
-
if (activeMenuId !== void 0) {
|
|
15632
|
-
for (const menu of findMenuChain(registry, activeMenuId)) {
|
|
15633
|
-
if (menu.type === "group" && !keys.includes(menu.id)) {
|
|
15634
|
-
keys.push(menu.id);
|
|
15635
|
-
}
|
|
15636
|
-
}
|
|
15637
|
-
}
|
|
15638
|
-
return keys;
|
|
15639
|
-
}
|
|
15640
|
-
|
|
15641
|
-
// src/layout/admin/AdminLayout.tsx
|
|
15642
|
-
var import_permission = require("@pactor-app/permission");
|
|
15643
|
-
var import_router = require("@pactor-app/router");
|
|
15644
|
-
var import_runtime52 = require("@pactor-app/runtime");
|
|
15645
|
-
var import_react72 = require("react");
|
|
15646
|
-
|
|
15647
|
-
// src/layout/admin/use-media-query.ts
|
|
15648
|
-
var import_react71 = require("react");
|
|
15649
|
-
var BREAKPOINT_PX = {
|
|
15650
|
-
xs: 480,
|
|
15651
|
-
sm: 576,
|
|
15652
|
-
md: 768,
|
|
15653
|
-
lg: 992,
|
|
15654
|
-
xl: 1200,
|
|
15655
|
-
xxl: 1600
|
|
15656
|
-
};
|
|
15657
|
-
function useMediaQuery(query) {
|
|
15658
|
-
const [matches, setMatches] = (0, import_react71.useState)(
|
|
15659
|
-
() => typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia(query).matches : false
|
|
15660
|
-
);
|
|
15661
|
-
(0, import_react71.useEffect)(() => {
|
|
13194
|
+
(0, import_react61.useEffect)(() => {
|
|
15662
13195
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
15663
13196
|
return;
|
|
15664
13197
|
}
|
|
@@ -15678,7 +13211,7 @@ function useBreakpointBelow(breakpoint) {
|
|
|
15678
13211
|
}
|
|
15679
13212
|
|
|
15680
13213
|
// src/layout/admin/AdminLayout.tsx
|
|
15681
|
-
var
|
|
13214
|
+
var import_jsx_runtime174 = require("react/jsx-runtime");
|
|
15682
13215
|
function buildVisibleMenuTree(registry, permissionChecker) {
|
|
15683
13216
|
const tree = registry.tree();
|
|
15684
13217
|
return permissionChecker === void 0 ? [...tree] : (0, import_permission.filterMenusByPermission)(tree, permissionChecker);
|
|
@@ -15701,8 +13234,8 @@ function CollapsedGroupFlyout({
|
|
|
15701
13234
|
activeMenuId,
|
|
15702
13235
|
defaultOpenKeys
|
|
15703
13236
|
}) {
|
|
15704
|
-
const [open, setOpen] = (0,
|
|
15705
|
-
const closeTimer = (0,
|
|
13237
|
+
const [open, setOpen] = (0, import_react62.useState)(false);
|
|
13238
|
+
const closeTimer = (0, import_react62.useRef)(void 0);
|
|
15706
13239
|
const openNow = () => {
|
|
15707
13240
|
window.clearTimeout(closeTimer.current);
|
|
15708
13241
|
setOpen(true);
|
|
@@ -15711,12 +13244,12 @@ function CollapsedGroupFlyout({
|
|
|
15711
13244
|
window.clearTimeout(closeTimer.current);
|
|
15712
13245
|
closeTimer.current = window.setTimeout(() => setOpen(false), 200);
|
|
15713
13246
|
};
|
|
15714
|
-
(0,
|
|
15715
|
-
return /* @__PURE__ */ (0,
|
|
15716
|
-
/* @__PURE__ */ (0,
|
|
13247
|
+
(0, import_react62.useEffect)(() => () => window.clearTimeout(closeTimer.current), []);
|
|
13248
|
+
return /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(Popover, { open, onOpenChange: setOpen, children: [
|
|
13249
|
+
/* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
|
|
15717
13250
|
PopoverTrigger,
|
|
15718
13251
|
{
|
|
15719
|
-
render: /* @__PURE__ */ (0,
|
|
13252
|
+
render: /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
|
|
15720
13253
|
"button",
|
|
15721
13254
|
{
|
|
15722
13255
|
type: "button",
|
|
@@ -15734,7 +13267,7 @@ function CollapsedGroupFlyout({
|
|
|
15734
13267
|
)
|
|
15735
13268
|
}
|
|
15736
13269
|
),
|
|
15737
|
-
/* @__PURE__ */ (0,
|
|
13270
|
+
/* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
|
|
15738
13271
|
PopoverContent,
|
|
15739
13272
|
{
|
|
15740
13273
|
"data-slot": "menu-flyout",
|
|
@@ -15751,8 +13284,8 @@ function CollapsedGroupFlyout({
|
|
|
15751
13284
|
}
|
|
15752
13285
|
},
|
|
15753
13286
|
children: [
|
|
15754
|
-
/* @__PURE__ */ (0,
|
|
15755
|
-
/* @__PURE__ */ (0,
|
|
13287
|
+
/* @__PURE__ */ (0, import_jsx_runtime174.jsx)("div", { className: "px-3 pt-2 pb-1 text-xs font-semibold text-muted-foreground", children: menu.title }),
|
|
13288
|
+
/* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
|
|
15756
13289
|
MenuTree,
|
|
15757
13290
|
{
|
|
15758
13291
|
menus: menu.children ?? [],
|
|
@@ -15776,9 +13309,9 @@ function MenuTree({
|
|
|
15776
13309
|
collapsed = false
|
|
15777
13310
|
}) {
|
|
15778
13311
|
if (collapsed) {
|
|
15779
|
-
return /* @__PURE__ */ (0,
|
|
13312
|
+
return /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("div", { "data-slot": "menu", "data-collapsed": "true", className: "flex flex-col gap-1", children: menus.map((menu) => {
|
|
15780
13313
|
if (menu.type === "group") {
|
|
15781
|
-
return /* @__PURE__ */ (0,
|
|
13314
|
+
return /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
|
|
15782
13315
|
CollapsedGroupFlyout,
|
|
15783
13316
|
{
|
|
15784
13317
|
menu,
|
|
@@ -15790,7 +13323,7 @@ function MenuTree({
|
|
|
15790
13323
|
menu.id
|
|
15791
13324
|
);
|
|
15792
13325
|
}
|
|
15793
|
-
return /* @__PURE__ */ (0,
|
|
13326
|
+
return /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
|
|
15794
13327
|
"button",
|
|
15795
13328
|
{
|
|
15796
13329
|
type: "button",
|
|
@@ -15810,7 +13343,7 @@ function MenuTree({
|
|
|
15810
13343
|
);
|
|
15811
13344
|
}) });
|
|
15812
13345
|
}
|
|
15813
|
-
return /* @__PURE__ */ (0,
|
|
13346
|
+
return /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
|
|
15814
13347
|
Accordion,
|
|
15815
13348
|
{
|
|
15816
13349
|
type: "multiple",
|
|
@@ -15819,27 +13352,27 @@ function MenuTree({
|
|
|
15819
13352
|
className: "flex flex-col gap-0.5 px-2",
|
|
15820
13353
|
children: menus.map((menu) => {
|
|
15821
13354
|
if (menu.type === "group") {
|
|
15822
|
-
return /* @__PURE__ */ (0,
|
|
13355
|
+
return /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
|
|
15823
13356
|
AccordionItem,
|
|
15824
13357
|
{
|
|
15825
13358
|
value: menu.id,
|
|
15826
13359
|
"data-slot": "menu-group",
|
|
15827
13360
|
className: "border-b-0",
|
|
15828
13361
|
children: [
|
|
15829
|
-
/* @__PURE__ */ (0,
|
|
13362
|
+
/* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
|
|
15830
13363
|
AccordionTrigger,
|
|
15831
13364
|
{
|
|
15832
13365
|
"data-slot": "menu-group-trigger",
|
|
15833
13366
|
className: cn(menuItemClass2, "py-2 font-medium"),
|
|
15834
13367
|
disabled: menu.disabled,
|
|
15835
13368
|
title: menu.title,
|
|
15836
|
-
children: /* @__PURE__ */ (0,
|
|
15837
|
-
menu.icon ? /* @__PURE__ */ (0,
|
|
13369
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("span", { className: "inline-flex items-center gap-2", children: [
|
|
13370
|
+
menu.icon ? /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(Icon, { name: menu.icon, size: "sm" }) : null,
|
|
15838
13371
|
menu.title
|
|
15839
13372
|
] })
|
|
15840
13373
|
}
|
|
15841
13374
|
),
|
|
15842
|
-
/* @__PURE__ */ (0,
|
|
13375
|
+
/* @__PURE__ */ (0, import_jsx_runtime174.jsx)(AccordionContent, { "data-slot": "menu-group-content", className: "pb-1", children: /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("div", { className: "flex flex-col gap-0.5 pl-3", children: /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
|
|
15843
13376
|
MenuTree,
|
|
15844
13377
|
{
|
|
15845
13378
|
menus: menu.children ?? [],
|
|
@@ -15854,7 +13387,7 @@ function MenuTree({
|
|
|
15854
13387
|
menu.id
|
|
15855
13388
|
);
|
|
15856
13389
|
}
|
|
15857
|
-
return /* @__PURE__ */ (0,
|
|
13390
|
+
return /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
|
|
15858
13391
|
"button",
|
|
15859
13392
|
{
|
|
15860
13393
|
type: "button",
|
|
@@ -15868,7 +13401,7 @@ function MenuTree({
|
|
|
15868
13401
|
title: menu.title,
|
|
15869
13402
|
onClick: () => navigateMenuItem(registry.findById(menu.id), bridge),
|
|
15870
13403
|
children: [
|
|
15871
|
-
menu.icon ? /* @__PURE__ */ (0,
|
|
13404
|
+
menu.icon ? /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(Icon, { name: menu.icon, size: "sm" }) : null,
|
|
15872
13405
|
menu.title
|
|
15873
13406
|
]
|
|
15874
13407
|
},
|
|
@@ -15888,23 +13421,23 @@ function AdminLayout({
|
|
|
15888
13421
|
headerExtra,
|
|
15889
13422
|
children
|
|
15890
13423
|
}) {
|
|
15891
|
-
const { t } = (0,
|
|
13424
|
+
const { t } = (0, import_runtime50.useI18n)();
|
|
15892
13425
|
const mode = config.mode ?? "top-side";
|
|
15893
13426
|
const showHeader = config.header ?? true;
|
|
15894
13427
|
const showSidebar = (config.sidebar ?? true) && mode !== "top-bottom";
|
|
15895
13428
|
const showTabs = config.tabs ?? false;
|
|
15896
13429
|
const showBreadcrumb = config.breadcrumb ?? false;
|
|
15897
13430
|
const showFooter = config.footer ?? false;
|
|
15898
|
-
const [collapsed, setCollapsed] = (0,
|
|
13431
|
+
const [collapsed, setCollapsed] = (0, import_react62.useState)(config.collapsed ?? false);
|
|
15899
13432
|
const broken = useBreakpointBelow(config.breakpoint);
|
|
15900
13433
|
const effectiveCollapsed = collapsed || broken;
|
|
15901
|
-
const [bridgeRoute, setBridgeRoute] = (0,
|
|
13434
|
+
const [bridgeRoute, setBridgeRoute] = (0, import_react62.useState)(
|
|
15902
13435
|
() => (0, import_router.resolveRoute)(registry, bridge.getLocation())
|
|
15903
13436
|
);
|
|
15904
|
-
const [tabs, setTabs] = (0,
|
|
15905
|
-
const tabsRef = (0,
|
|
13437
|
+
const [tabs, setTabs] = (0, import_react62.useState)([]);
|
|
13438
|
+
const tabsRef = (0, import_react62.useRef)(tabs);
|
|
15906
13439
|
tabsRef.current = tabs;
|
|
15907
|
-
(0,
|
|
13440
|
+
(0, import_react62.useEffect)(() => {
|
|
15908
13441
|
const handleLocation = (location) => {
|
|
15909
13442
|
const next = (0, import_router.resolveRoute)(registry, location);
|
|
15910
13443
|
setBridgeRoute(next);
|
|
@@ -15925,16 +13458,16 @@ function AdminLayout({
|
|
|
15925
13458
|
}, [registry, bridge]);
|
|
15926
13459
|
const route = routeProp ?? bridgeRoute;
|
|
15927
13460
|
const activeMenuId = route?.activeMenu;
|
|
15928
|
-
const visibleMenus = (0,
|
|
13461
|
+
const visibleMenus = (0, import_react62.useMemo)(
|
|
15929
13462
|
() => buildVisibleMenuTree(registry, permissionChecker),
|
|
15930
13463
|
[registry, permissionChecker]
|
|
15931
13464
|
);
|
|
15932
|
-
const defaultOpenKeysRef = (0,
|
|
13465
|
+
const defaultOpenKeysRef = (0, import_react62.useRef)(null);
|
|
15933
13466
|
if (defaultOpenKeysRef.current === null) {
|
|
15934
13467
|
defaultOpenKeysRef.current = collectDefaultOpenKeys(registry, activeMenuId);
|
|
15935
13468
|
}
|
|
15936
13469
|
const defaultOpenKeys = defaultOpenKeysRef.current;
|
|
15937
|
-
const activeTopId = (0,
|
|
13470
|
+
const activeTopId = (0, import_react62.useMemo)(() => {
|
|
15938
13471
|
if (activeMenuId !== void 0) {
|
|
15939
13472
|
const chain = findMenuChain(registry, activeMenuId);
|
|
15940
13473
|
if (chain.length > 0) {
|
|
@@ -15943,11 +13476,11 @@ function AdminLayout({
|
|
|
15943
13476
|
}
|
|
15944
13477
|
return void 0;
|
|
15945
13478
|
}, [registry, activeMenuId]);
|
|
15946
|
-
const [selectedTopId, setSelectedTopId] = (0,
|
|
13479
|
+
const [selectedTopId, setSelectedTopId] = (0, import_react62.useState)();
|
|
15947
13480
|
const secondaryTopId = selectedTopId ?? activeTopId ?? visibleMenus.find((m) => m.type === "group")?.id ?? visibleMenus[0]?.id;
|
|
15948
13481
|
const secondaryTop = visibleMenus.find((m) => m.id === secondaryTopId);
|
|
15949
13482
|
const hasSecondary = (secondaryTop?.children?.length ?? 0) > 0;
|
|
15950
|
-
const breadcrumbItems = (0,
|
|
13483
|
+
const breadcrumbItems = (0, import_react62.useMemo)(() => {
|
|
15951
13484
|
if (!showBreadcrumb || activeMenuId === void 0) {
|
|
15952
13485
|
return [];
|
|
15953
13486
|
}
|
|
@@ -15963,7 +13496,7 @@ function AdminLayout({
|
|
|
15963
13496
|
};
|
|
15964
13497
|
const fixedHeader = config.fixedHeader ?? true;
|
|
15965
13498
|
const fixedSider = config.fixedSider ?? true;
|
|
15966
|
-
const header = showHeader ? /* @__PURE__ */ (0,
|
|
13499
|
+
const header = showHeader ? /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
|
|
15967
13500
|
"header",
|
|
15968
13501
|
{
|
|
15969
13502
|
"data-slot": "admin-header",
|
|
@@ -15972,21 +13505,21 @@ function AdminLayout({
|
|
|
15972
13505
|
fixedHeader && "sticky top-0 z-20"
|
|
15973
13506
|
),
|
|
15974
13507
|
children: [
|
|
15975
|
-
mode !== "side-full" && /* @__PURE__ */ (0,
|
|
13508
|
+
mode !== "side-full" && /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(import_jsx_runtime174.Fragment, { children: [
|
|
15976
13509
|
brand.logo,
|
|
15977
|
-
/* @__PURE__ */ (0,
|
|
13510
|
+
/* @__PURE__ */ (0, import_jsx_runtime174.jsx)("span", { "data-slot": "admin-brand", className: "text-lg font-semibold", children: brand.title })
|
|
15978
13511
|
] }),
|
|
15979
|
-
/* @__PURE__ */ (0,
|
|
13512
|
+
/* @__PURE__ */ (0, import_jsx_runtime174.jsx)("div", { className: "flex-1" }),
|
|
15980
13513
|
headerExtra
|
|
15981
13514
|
]
|
|
15982
13515
|
}
|
|
15983
13516
|
) : null;
|
|
15984
|
-
const primaryColumn = /* @__PURE__ */ (0,
|
|
13517
|
+
const primaryColumn = /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
|
|
15985
13518
|
"div",
|
|
15986
13519
|
{
|
|
15987
13520
|
"data-slot": "admin-primary-col",
|
|
15988
13521
|
className: "flex w-12 shrink-0 flex-col items-center gap-1 border-r border-border py-2",
|
|
15989
|
-
children: visibleMenus.map((menu) => /* @__PURE__ */ (0,
|
|
13522
|
+
children: visibleMenus.map((menu) => /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
|
|
15990
13523
|
"button",
|
|
15991
13524
|
{
|
|
15992
13525
|
type: "button",
|
|
@@ -16013,7 +13546,7 @@ function AdminLayout({
|
|
|
16013
13546
|
}
|
|
16014
13547
|
);
|
|
16015
13548
|
const showTrigger = config.collapsible && mode !== "two-column";
|
|
16016
|
-
const sidebar = showSidebar ? /* @__PURE__ */ (0,
|
|
13549
|
+
const sidebar = showSidebar ? /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
|
|
16017
13550
|
"aside",
|
|
16018
13551
|
{
|
|
16019
13552
|
"data-slot": "admin-sidebar",
|
|
@@ -16025,20 +13558,20 @@ function AdminLayout({
|
|
|
16025
13558
|
),
|
|
16026
13559
|
style: mode === "two-column" && !hasSecondary ? { width: 56 } : void 0,
|
|
16027
13560
|
children: [
|
|
16028
|
-
mode === "side-full" && /* @__PURE__ */ (0,
|
|
13561
|
+
mode === "side-full" && /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
|
|
16029
13562
|
"div",
|
|
16030
13563
|
{
|
|
16031
13564
|
"data-slot": "admin-sidebar-brand",
|
|
16032
13565
|
className: "flex items-center gap-2 border-b border-border px-4 py-4 font-semibold",
|
|
16033
13566
|
children: [
|
|
16034
13567
|
brand.logo,
|
|
16035
|
-
/* @__PURE__ */ (0,
|
|
13568
|
+
/* @__PURE__ */ (0, import_jsx_runtime174.jsx)("span", { children: brand.title })
|
|
16036
13569
|
]
|
|
16037
13570
|
}
|
|
16038
13571
|
),
|
|
16039
|
-
mode === "two-column" ? /* @__PURE__ */ (0,
|
|
13572
|
+
mode === "two-column" ? /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("div", { "data-slot": "admin-two-col", className: "flex h-full", children: [
|
|
16040
13573
|
primaryColumn,
|
|
16041
|
-
hasSecondary && /* @__PURE__ */ (0,
|
|
13574
|
+
hasSecondary && /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("div", { "data-slot": "admin-secondary-col", className: "min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
|
|
16042
13575
|
MenuTree,
|
|
16043
13576
|
{
|
|
16044
13577
|
menus: secondaryTop?.children ?? [],
|
|
@@ -16048,7 +13581,7 @@ function AdminLayout({
|
|
|
16048
13581
|
defaultOpenKeys
|
|
16049
13582
|
}
|
|
16050
13583
|
) })
|
|
16051
|
-
] }) : /* @__PURE__ */ (0,
|
|
13584
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
|
|
16052
13585
|
MenuTree,
|
|
16053
13586
|
{
|
|
16054
13587
|
menus: visibleMenus,
|
|
@@ -16059,7 +13592,7 @@ function AdminLayout({
|
|
|
16059
13592
|
collapsed: effectiveCollapsed
|
|
16060
13593
|
}
|
|
16061
13594
|
),
|
|
16062
|
-
showTrigger && /* @__PURE__ */ (0,
|
|
13595
|
+
showTrigger && /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
|
|
16063
13596
|
"button",
|
|
16064
13597
|
{
|
|
16065
13598
|
type: "button",
|
|
@@ -16074,14 +13607,14 @@ function AdminLayout({
|
|
|
16074
13607
|
]
|
|
16075
13608
|
}
|
|
16076
13609
|
) : null;
|
|
16077
|
-
const body = /* @__PURE__ */ (0,
|
|
16078
|
-
showTabs && /* @__PURE__ */ (0,
|
|
13610
|
+
const body = /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("div", { "data-slot": "admin-body", className: "flex min-w-0 flex-1 flex-col", children: [
|
|
13611
|
+
showTabs && /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
|
|
16079
13612
|
"div",
|
|
16080
13613
|
{
|
|
16081
13614
|
"data-slot": "admin-tabs",
|
|
16082
13615
|
role: "tablist",
|
|
16083
13616
|
className: "flex items-center gap-1 border-b border-border bg-card px-4 pt-2",
|
|
16084
|
-
children: tabs.map((tab, index) => /* @__PURE__ */ (0,
|
|
13617
|
+
children: tabs.map((tab, index) => /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
|
|
16085
13618
|
"div",
|
|
16086
13619
|
{
|
|
16087
13620
|
"data-slot": "admin-tab",
|
|
@@ -16092,7 +13625,7 @@ function AdminLayout({
|
|
|
16092
13625
|
tab.key === currentPath ? "bg-card font-medium text-foreground" : "bg-muted text-muted-foreground"
|
|
16093
13626
|
),
|
|
16094
13627
|
children: [
|
|
16095
|
-
/* @__PURE__ */ (0,
|
|
13628
|
+
/* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
|
|
16096
13629
|
"button",
|
|
16097
13630
|
{
|
|
16098
13631
|
type: "button",
|
|
@@ -16103,7 +13636,7 @@ function AdminLayout({
|
|
|
16103
13636
|
children: tab.title
|
|
16104
13637
|
}
|
|
16105
13638
|
),
|
|
16106
|
-
index > 0 && /* @__PURE__ */ (0,
|
|
13639
|
+
index > 0 && /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
|
|
16107
13640
|
"button",
|
|
16108
13641
|
{
|
|
16109
13642
|
type: "button",
|
|
@@ -16120,21 +13653,21 @@ function AdminLayout({
|
|
|
16120
13653
|
))
|
|
16121
13654
|
}
|
|
16122
13655
|
),
|
|
16123
|
-
/* @__PURE__ */ (0,
|
|
13656
|
+
/* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
|
|
16124
13657
|
"main",
|
|
16125
13658
|
{
|
|
16126
13659
|
"data-slot": "admin-content",
|
|
16127
13660
|
className: "flex-1 bg-muted/40 p-6",
|
|
16128
13661
|
children: [
|
|
16129
|
-
showBreadcrumb && breadcrumbItems.length > 0 && /* @__PURE__ */ (0,
|
|
13662
|
+
showBreadcrumb && breadcrumbItems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
|
|
16130
13663
|
"nav",
|
|
16131
13664
|
{
|
|
16132
13665
|
"data-slot": "admin-breadcrumb",
|
|
16133
13666
|
"aria-label": t("pactor.layout.breadcrumb"),
|
|
16134
13667
|
className: "mb-4",
|
|
16135
|
-
children: /* @__PURE__ */ (0,
|
|
16136
|
-
index > 0 && /* @__PURE__ */ (0,
|
|
16137
|
-
/* @__PURE__ */ (0,
|
|
13668
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("ol", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: breadcrumbItems.map((title, index) => /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("li", { className: "flex items-center gap-2", children: [
|
|
13669
|
+
index > 0 && /* @__PURE__ */ (0, import_jsx_runtime174.jsx)("span", { "aria-hidden": true, children: "/" }),
|
|
13670
|
+
/* @__PURE__ */ (0, import_jsx_runtime174.jsx)("span", { "data-slot": "breadcrumb-link", children: title })
|
|
16138
13671
|
] }, index)) })
|
|
16139
13672
|
}
|
|
16140
13673
|
),
|
|
@@ -16143,7 +13676,7 @@ function AdminLayout({
|
|
|
16143
13676
|
}
|
|
16144
13677
|
)
|
|
16145
13678
|
] });
|
|
16146
|
-
const footer = showFooter ? /* @__PURE__ */ (0,
|
|
13679
|
+
const footer = showFooter ? /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
|
|
16147
13680
|
"footer",
|
|
16148
13681
|
{
|
|
16149
13682
|
"data-slot": "admin-footer",
|
|
@@ -16151,7 +13684,7 @@ function AdminLayout({
|
|
|
16151
13684
|
children: brand.title
|
|
16152
13685
|
}
|
|
16153
13686
|
) : null;
|
|
16154
|
-
return /* @__PURE__ */ (0,
|
|
13687
|
+
return /* @__PURE__ */ (0, import_jsx_runtime174.jsx)(
|
|
16155
13688
|
"div",
|
|
16156
13689
|
{
|
|
16157
13690
|
"data-slot": "admin-layout",
|
|
@@ -16159,9 +13692,9 @@ function AdminLayout({
|
|
|
16159
13692
|
"data-fixed-header": fixedHeader || void 0,
|
|
16160
13693
|
"data-fixed-sider": fixedSider || void 0,
|
|
16161
13694
|
className: "flex min-h-screen flex-col bg-background text-foreground",
|
|
16162
|
-
children: mode === "side-full" ? /* @__PURE__ */ (0,
|
|
13695
|
+
children: mode === "side-full" ? /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("div", { "data-slot": "admin-side-full", className: "flex min-h-screen flex-1", children: [
|
|
16163
13696
|
sidebar,
|
|
16164
|
-
/* @__PURE__ */ (0,
|
|
13697
|
+
/* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(
|
|
16165
13698
|
"div",
|
|
16166
13699
|
{
|
|
16167
13700
|
"data-slot": "admin-side-full-main",
|
|
@@ -16173,9 +13706,9 @@ function AdminLayout({
|
|
|
16173
13706
|
]
|
|
16174
13707
|
}
|
|
16175
13708
|
)
|
|
16176
|
-
] }) : /* @__PURE__ */ (0,
|
|
13709
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime174.jsxs)(import_jsx_runtime174.Fragment, { children: [
|
|
16177
13710
|
header,
|
|
16178
|
-
/* @__PURE__ */ (0,
|
|
13711
|
+
/* @__PURE__ */ (0, import_jsx_runtime174.jsxs)("div", { "data-slot": "admin-main", className: "flex min-h-0 flex-1", children: [
|
|
16179
13712
|
sidebar,
|
|
16180
13713
|
body
|
|
16181
13714
|
] }),
|
|
@@ -16186,9 +13719,9 @@ function AdminLayout({
|
|
|
16186
13719
|
}
|
|
16187
13720
|
|
|
16188
13721
|
// src/layout/basic/BlankLayout.tsx
|
|
16189
|
-
var
|
|
13722
|
+
var import_jsx_runtime175 = require("react/jsx-runtime");
|
|
16190
13723
|
function BlankLayout({ children }) {
|
|
16191
|
-
return /* @__PURE__ */ (0,
|
|
13724
|
+
return /* @__PURE__ */ (0, import_jsx_runtime175.jsx)(
|
|
16192
13725
|
"div",
|
|
16193
13726
|
{
|
|
16194
13727
|
"data-slot": "blank-layout",
|
|
@@ -16200,8 +13733,8 @@ function BlankLayout({ children }) {
|
|
|
16200
13733
|
|
|
16201
13734
|
// src/layout/chat/ChatLayout.tsx
|
|
16202
13735
|
var import_permission2 = require("@pactor-app/permission");
|
|
16203
|
-
var
|
|
16204
|
-
var
|
|
13736
|
+
var import_react63 = require("react");
|
|
13737
|
+
var import_jsx_runtime176 = require("react/jsx-runtime");
|
|
16205
13738
|
function ChatLayout({
|
|
16206
13739
|
brand,
|
|
16207
13740
|
menu,
|
|
@@ -16216,7 +13749,7 @@ function ChatLayout({
|
|
|
16216
13749
|
sidebarFooter,
|
|
16217
13750
|
children
|
|
16218
13751
|
}) {
|
|
16219
|
-
const registryMenus = (0,
|
|
13752
|
+
const registryMenus = (0, import_react63.useMemo)(() => {
|
|
16220
13753
|
if (menu !== void 0 || registry === void 0) {
|
|
16221
13754
|
return [];
|
|
16222
13755
|
}
|
|
@@ -16225,10 +13758,10 @@ function ChatLayout({
|
|
|
16225
13758
|
return visible.flatMap((item) => menuItemToMenuData(item));
|
|
16226
13759
|
}, [menu, registry, permissionChecker]);
|
|
16227
13760
|
const menuItems = menu ?? registryMenus;
|
|
16228
|
-
const [bridgePath, setBridgePath] = (0,
|
|
13761
|
+
const [bridgePath, setBridgePath] = (0, import_react63.useState)(
|
|
16229
13762
|
() => bridge?.getLocation().pathname ?? "/"
|
|
16230
13763
|
);
|
|
16231
|
-
(0,
|
|
13764
|
+
(0, import_react63.useEffect)(() => {
|
|
16232
13765
|
if (bridge === void 0) {
|
|
16233
13766
|
return;
|
|
16234
13767
|
}
|
|
@@ -16236,7 +13769,7 @@ function ChatLayout({
|
|
|
16236
13769
|
setBridgePath(location.pathname);
|
|
16237
13770
|
});
|
|
16238
13771
|
}, [bridge]);
|
|
16239
|
-
const activeKey = (0,
|
|
13772
|
+
const activeKey = (0, import_react63.useMemo)(() => {
|
|
16240
13773
|
if (activeMenuKey !== void 0) {
|
|
16241
13774
|
return activeMenuKey;
|
|
16242
13775
|
}
|
|
@@ -16256,7 +13789,7 @@ function ChatLayout({
|
|
|
16256
13789
|
bridge.push(item.path);
|
|
16257
13790
|
}
|
|
16258
13791
|
};
|
|
16259
|
-
const sidebarContent = sidebar !== void 0 && sidebar !== null ? sidebar : menuItems.length > 0 ? /* @__PURE__ */ (0,
|
|
13792
|
+
const sidebarContent = sidebar !== void 0 && sidebar !== null ? sidebar : menuItems.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
|
|
16260
13793
|
Menu2,
|
|
16261
13794
|
{
|
|
16262
13795
|
items: menuItems.map((item) => chatMenuItemToUiMenuItem(item)),
|
|
@@ -16264,7 +13797,7 @@ function ChatLayout({
|
|
|
16264
13797
|
onSelect: handleSelect
|
|
16265
13798
|
}
|
|
16266
13799
|
) : void 0;
|
|
16267
|
-
return /* @__PURE__ */ (0,
|
|
13800
|
+
return /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
|
|
16268
13801
|
Sidebar,
|
|
16269
13802
|
{
|
|
16270
13803
|
brand,
|
|
@@ -16272,7 +13805,7 @@ function ChatLayout({
|
|
|
16272
13805
|
sidebarFooter,
|
|
16273
13806
|
collapsible,
|
|
16274
13807
|
locationKey: routeProp?.path ?? bridgePath,
|
|
16275
|
-
children: /* @__PURE__ */ (0,
|
|
13808
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(
|
|
16276
13809
|
"div",
|
|
16277
13810
|
{
|
|
16278
13811
|
"data-slot": "chat-layout-content",
|
|
@@ -16326,26 +13859,26 @@ function menuItemToMenuData(item) {
|
|
|
16326
13859
|
}
|
|
16327
13860
|
|
|
16328
13861
|
// src/layout/basic/LoginLayout.tsx
|
|
16329
|
-
var
|
|
13862
|
+
var import_jsx_runtime177 = require("react/jsx-runtime");
|
|
16330
13863
|
function LoginLayout({
|
|
16331
13864
|
variant = "center",
|
|
16332
13865
|
brand,
|
|
16333
13866
|
children
|
|
16334
13867
|
}) {
|
|
16335
|
-
const brandBlock = /* @__PURE__ */ (0,
|
|
13868
|
+
const brandBlock = /* @__PURE__ */ (0, import_jsx_runtime177.jsxs)("div", { "data-slot": "login-brand", className: "flex flex-col items-center gap-2", children: [
|
|
16336
13869
|
brand.logo,
|
|
16337
|
-
/* @__PURE__ */ (0,
|
|
16338
|
-
brand.description !== void 0 && /* @__PURE__ */ (0,
|
|
13870
|
+
/* @__PURE__ */ (0, import_jsx_runtime177.jsx)("h1", { className: "text-xl font-semibold", children: brand.title }),
|
|
13871
|
+
brand.description !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime177.jsx)("div", { className: "text-sm text-muted-foreground", children: brand.description })
|
|
16339
13872
|
] });
|
|
16340
13873
|
if (variant === "split") {
|
|
16341
|
-
return /* @__PURE__ */ (0,
|
|
13874
|
+
return /* @__PURE__ */ (0, import_jsx_runtime177.jsxs)(
|
|
16342
13875
|
"div",
|
|
16343
13876
|
{
|
|
16344
13877
|
"data-slot": "login-layout",
|
|
16345
13878
|
"data-variant": "split",
|
|
16346
13879
|
className: "grid min-h-screen grid-cols-2 bg-background text-foreground",
|
|
16347
13880
|
children: [
|
|
16348
|
-
/* @__PURE__ */ (0,
|
|
13881
|
+
/* @__PURE__ */ (0, import_jsx_runtime177.jsx)(
|
|
16349
13882
|
"div",
|
|
16350
13883
|
{
|
|
16351
13884
|
"data-slot": "login-brand-panel",
|
|
@@ -16353,7 +13886,7 @@ function LoginLayout({
|
|
|
16353
13886
|
children: brandBlock
|
|
16354
13887
|
}
|
|
16355
13888
|
),
|
|
16356
|
-
/* @__PURE__ */ (0,
|
|
13889
|
+
/* @__PURE__ */ (0, import_jsx_runtime177.jsx)(
|
|
16357
13890
|
"div",
|
|
16358
13891
|
{
|
|
16359
13892
|
"data-slot": "login-form-panel",
|
|
@@ -16365,37 +13898,37 @@ function LoginLayout({
|
|
|
16365
13898
|
}
|
|
16366
13899
|
);
|
|
16367
13900
|
}
|
|
16368
|
-
return /* @__PURE__ */ (0,
|
|
13901
|
+
return /* @__PURE__ */ (0, import_jsx_runtime177.jsx)(
|
|
16369
13902
|
"div",
|
|
16370
13903
|
{
|
|
16371
13904
|
"data-slot": "login-layout",
|
|
16372
13905
|
"data-variant": "center",
|
|
16373
13906
|
className: "flex min-h-screen items-center justify-center bg-muted/40 text-foreground",
|
|
16374
|
-
children: /* @__PURE__ */ (0,
|
|
16375
|
-
/* @__PURE__ */ (0,
|
|
16376
|
-
/* @__PURE__ */ (0,
|
|
13907
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime177.jsxs)(Card, { "data-slot": "login-card", className: "w-full max-w-sm gap-4 py-6", children: [
|
|
13908
|
+
/* @__PURE__ */ (0, import_jsx_runtime177.jsxs)(CardHeader, { className: "px-6", children: [
|
|
13909
|
+
/* @__PURE__ */ (0, import_jsx_runtime177.jsx)(CardTitle, { className: "sr-only", children: brand.title }),
|
|
16377
13910
|
brandBlock
|
|
16378
13911
|
] }),
|
|
16379
|
-
/* @__PURE__ */ (0,
|
|
13912
|
+
/* @__PURE__ */ (0, import_jsx_runtime177.jsx)(CardContent, { className: "flex flex-col gap-4 px-6", children })
|
|
16380
13913
|
] })
|
|
16381
13914
|
}
|
|
16382
13915
|
);
|
|
16383
13916
|
}
|
|
16384
13917
|
|
|
16385
13918
|
// src/layout/basic/LandingLayout.tsx
|
|
16386
|
-
var
|
|
13919
|
+
var import_jsx_runtime178 = require("react/jsx-runtime");
|
|
16387
13920
|
function LandingLayout({
|
|
16388
13921
|
navbar,
|
|
16389
13922
|
footer,
|
|
16390
13923
|
children
|
|
16391
13924
|
}) {
|
|
16392
|
-
return /* @__PURE__ */ (0,
|
|
13925
|
+
return /* @__PURE__ */ (0, import_jsx_runtime178.jsxs)(
|
|
16393
13926
|
"div",
|
|
16394
13927
|
{
|
|
16395
13928
|
"data-slot": "landing-layout",
|
|
16396
13929
|
className: "flex min-h-screen flex-col bg-background text-foreground",
|
|
16397
13930
|
children: [
|
|
16398
|
-
navbar !== void 0 && /* @__PURE__ */ (0,
|
|
13931
|
+
navbar !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(
|
|
16399
13932
|
"header",
|
|
16400
13933
|
{
|
|
16401
13934
|
"data-slot": "landing-navbar",
|
|
@@ -16403,8 +13936,8 @@ function LandingLayout({
|
|
|
16403
13936
|
children: navbar
|
|
16404
13937
|
}
|
|
16405
13938
|
),
|
|
16406
|
-
/* @__PURE__ */ (0,
|
|
16407
|
-
footer !== void 0 && /* @__PURE__ */ (0,
|
|
13939
|
+
/* @__PURE__ */ (0, import_jsx_runtime178.jsx)("main", { "data-slot": "landing-content", className: "flex-1", children }),
|
|
13940
|
+
footer !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime178.jsx)(
|
|
16408
13941
|
"footer",
|
|
16409
13942
|
{
|
|
16410
13943
|
"data-slot": "landing-footer",
|
|
@@ -16418,7 +13951,7 @@ function LandingLayout({
|
|
|
16418
13951
|
}
|
|
16419
13952
|
|
|
16420
13953
|
// src/layout/registry.ts
|
|
16421
|
-
var
|
|
13954
|
+
var import_core3 = require("@pactor-app/core");
|
|
16422
13955
|
function registerBuiltinLayouts(registry) {
|
|
16423
13956
|
registry.register("admin", AdminLayout);
|
|
16424
13957
|
registry.register("blank", BlankLayout);
|
|
@@ -16427,7 +13960,7 @@ function registerBuiltinLayouts(registry) {
|
|
|
16427
13960
|
registry.register("chat", ChatLayout);
|
|
16428
13961
|
}
|
|
16429
13962
|
function createLayoutRegistry() {
|
|
16430
|
-
const registry = new
|
|
13963
|
+
const registry = new import_core3.Registry("LayoutRegistry");
|
|
16431
13964
|
registerBuiltinLayouts(registry);
|
|
16432
13965
|
return registry;
|
|
16433
13966
|
}
|
|
@@ -16531,7 +14064,7 @@ var OverlayManager = class {
|
|
|
16531
14064
|
};
|
|
16532
14065
|
|
|
16533
14066
|
// src/interaction/actions.ts
|
|
16534
|
-
var
|
|
14067
|
+
var import_runtime51 = require("@pactor-app/runtime");
|
|
16535
14068
|
function createUiBridge() {
|
|
16536
14069
|
return {};
|
|
16537
14070
|
}
|
|
@@ -16547,7 +14080,7 @@ function registerInteractionActions(actions, manager, ui) {
|
|
|
16547
14080
|
return failure("[pactor-interaction] overlay.open \u7F3A\u5C11 overlay \u914D\u7F6E\u53C2\u6570");
|
|
16548
14081
|
}
|
|
16549
14082
|
const { content, ...rest } = overlay;
|
|
16550
|
-
const resolved = (0,
|
|
14083
|
+
const resolved = (0, import_runtime51.resolveDeep)(rest, ctx.scope);
|
|
16551
14084
|
const config = { ...resolved, content };
|
|
16552
14085
|
const data = await manager.open(config, {
|
|
16553
14086
|
parentScope: { ...ctx.scope }
|
|
@@ -16610,10 +14143,10 @@ function isRecord(value) {
|
|
|
16610
14143
|
}
|
|
16611
14144
|
|
|
16612
14145
|
// src/interaction/provider.tsx
|
|
16613
|
-
var
|
|
16614
|
-
var
|
|
14146
|
+
var import_runtime52 = require("@pactor-app/runtime");
|
|
14147
|
+
var import_react64 = require("react");
|
|
16615
14148
|
var import_react_dom2 = require("react-dom");
|
|
16616
|
-
var
|
|
14149
|
+
var import_jsx_runtime179 = require("react/jsx-runtime");
|
|
16617
14150
|
var TOAST_DURATION = 3e3;
|
|
16618
14151
|
var toastTypeClass = {
|
|
16619
14152
|
success: "border-l-4 border-l-success",
|
|
@@ -16625,11 +14158,11 @@ function InteractionProvider({
|
|
|
16625
14158
|
bridge,
|
|
16626
14159
|
children
|
|
16627
14160
|
}) {
|
|
16628
|
-
const [confirmState, setConfirmState] = (0,
|
|
16629
|
-
const [confirmOpen, setConfirmOpen] = (0,
|
|
16630
|
-
const [toasts, setToasts] = (0,
|
|
16631
|
-
const { t } = (0,
|
|
16632
|
-
const { modal, message } = (0,
|
|
14161
|
+
const [confirmState, setConfirmState] = (0, import_react64.useState)(null);
|
|
14162
|
+
const [confirmOpen, setConfirmOpen] = (0, import_react64.useState)(false);
|
|
14163
|
+
const [toasts, setToasts] = (0, import_react64.useState)([]);
|
|
14164
|
+
const { t } = (0, import_runtime52.useI18n)();
|
|
14165
|
+
const { modal, message } = (0, import_react64.useMemo)(() => {
|
|
16633
14166
|
const pushToast = (type, content) => {
|
|
16634
14167
|
const id = Date.now() + Math.random();
|
|
16635
14168
|
setToasts((prev) => [...prev, { id, type, content }]);
|
|
@@ -16651,7 +14184,7 @@ function InteractionProvider({
|
|
|
16651
14184
|
};
|
|
16652
14185
|
return { modal: modalImpl, message: messageImpl };
|
|
16653
14186
|
}, []);
|
|
16654
|
-
(0,
|
|
14187
|
+
(0, import_react64.useEffect)(() => {
|
|
16655
14188
|
bridge.modal = modal;
|
|
16656
14189
|
bridge.message = message;
|
|
16657
14190
|
return () => {
|
|
@@ -16669,11 +14202,11 @@ function InteractionProvider({
|
|
|
16669
14202
|
setConfirmOpen(false);
|
|
16670
14203
|
state?.onCancel?.();
|
|
16671
14204
|
};
|
|
16672
|
-
return /* @__PURE__ */ (0,
|
|
14205
|
+
return /* @__PURE__ */ (0, import_jsx_runtime179.jsxs)(import_jsx_runtime179.Fragment, { children: [
|
|
16673
14206
|
children,
|
|
16674
14207
|
typeof document !== "undefined" && (0, import_react_dom2.createPortal)(
|
|
16675
|
-
/* @__PURE__ */ (0,
|
|
16676
|
-
/* @__PURE__ */ (0,
|
|
14208
|
+
/* @__PURE__ */ (0, import_jsx_runtime179.jsxs)(import_jsx_runtime179.Fragment, { children: [
|
|
14209
|
+
/* @__PURE__ */ (0, import_jsx_runtime179.jsx)(
|
|
16677
14210
|
Dialog,
|
|
16678
14211
|
{
|
|
16679
14212
|
open: confirmOpen,
|
|
@@ -16687,29 +14220,29 @@ function InteractionProvider({
|
|
|
16687
14220
|
setConfirmState(null);
|
|
16688
14221
|
}
|
|
16689
14222
|
},
|
|
16690
|
-
children: /* @__PURE__ */ (0,
|
|
16691
|
-
/* @__PURE__ */ (0,
|
|
16692
|
-
/* @__PURE__ */ (0,
|
|
16693
|
-
confirmState?.content !== void 0 && /* @__PURE__ */ (0,
|
|
14223
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime179.jsxs)(DialogContent, { "data-slot": "confirm-dialog", className: "sm:max-w-sm", children: [
|
|
14224
|
+
/* @__PURE__ */ (0, import_jsx_runtime179.jsxs)(DialogHeader, { children: [
|
|
14225
|
+
/* @__PURE__ */ (0, import_jsx_runtime179.jsx)(DialogTitle, { children: confirmState?.title ?? "" }),
|
|
14226
|
+
confirmState?.content !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime179.jsx)(
|
|
16694
14227
|
DialogDescription,
|
|
16695
14228
|
{
|
|
16696
|
-
render: /* @__PURE__ */ (0,
|
|
14229
|
+
render: /* @__PURE__ */ (0, import_jsx_runtime179.jsx)("div", { children: confirmState.content })
|
|
16697
14230
|
}
|
|
16698
14231
|
)
|
|
16699
14232
|
] }),
|
|
16700
|
-
/* @__PURE__ */ (0,
|
|
16701
|
-
/* @__PURE__ */ (0,
|
|
16702
|
-
/* @__PURE__ */ (0,
|
|
14233
|
+
/* @__PURE__ */ (0, import_jsx_runtime179.jsxs)(DialogFooter, { children: [
|
|
14234
|
+
/* @__PURE__ */ (0, import_jsx_runtime179.jsx)(Button, { type: "button", variant: "outline", onClick: handleCancel, children: t("pactor.alertDialog.cancel") }),
|
|
14235
|
+
/* @__PURE__ */ (0, import_jsx_runtime179.jsx)(Button, { type: "button", onClick: handleOk, children: t("pactor.alertDialog.confirm") })
|
|
16703
14236
|
] })
|
|
16704
14237
|
] })
|
|
16705
14238
|
}
|
|
16706
14239
|
),
|
|
16707
|
-
toasts.length > 0 && /* @__PURE__ */ (0,
|
|
14240
|
+
toasts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime179.jsx)(
|
|
16708
14241
|
"div",
|
|
16709
14242
|
{
|
|
16710
14243
|
"data-slot": "toast-container",
|
|
16711
14244
|
className: "fixed top-4 right-4 z-[100] flex w-80 flex-col gap-2",
|
|
16712
|
-
children: toasts.map((toast2) => /* @__PURE__ */ (0,
|
|
14245
|
+
children: toasts.map((toast2) => /* @__PURE__ */ (0, import_jsx_runtime179.jsx)(
|
|
16713
14246
|
"div",
|
|
16714
14247
|
{
|
|
16715
14248
|
"data-slot": "toast",
|
|
@@ -16733,9 +14266,9 @@ function InteractionProvider({
|
|
|
16733
14266
|
|
|
16734
14267
|
// src/interaction/host.tsx
|
|
16735
14268
|
var import_lucide_react40 = require("lucide-react");
|
|
16736
|
-
var
|
|
16737
|
-
var
|
|
16738
|
-
var
|
|
14269
|
+
var import_runtime53 = require("@pactor-app/runtime");
|
|
14270
|
+
var import_react65 = require("react");
|
|
14271
|
+
var import_jsx_runtime180 = require("react/jsx-runtime");
|
|
16739
14272
|
function toCssWidth(width) {
|
|
16740
14273
|
if (width === void 0) {
|
|
16741
14274
|
return void 0;
|
|
@@ -16743,12 +14276,12 @@ function toCssWidth(width) {
|
|
|
16743
14276
|
return typeof width === "number" ? `${width}px` : width;
|
|
16744
14277
|
}
|
|
16745
14278
|
function OverlayHost({ manager, resolvePage }) {
|
|
16746
|
-
const renderer = (0,
|
|
16747
|
-
const stack = (0,
|
|
14279
|
+
const renderer = (0, import_runtime53.useRenderer)();
|
|
14280
|
+
const stack = (0, import_react65.useSyncExternalStore)(
|
|
16748
14281
|
(onChange) => manager.subscribe(onChange),
|
|
16749
14282
|
() => manager.stack()
|
|
16750
14283
|
);
|
|
16751
|
-
(0,
|
|
14284
|
+
(0, import_react65.useSyncExternalStore)(
|
|
16752
14285
|
(onChange) => {
|
|
16753
14286
|
const offState = renderer.context.state.subscribe(onChange);
|
|
16754
14287
|
const offData = renderer.context.data.subscribe(onChange);
|
|
@@ -16759,7 +14292,7 @@ function OverlayHost({ manager, resolvePage }) {
|
|
|
16759
14292
|
},
|
|
16760
14293
|
() => `${renderer.context.state.getVersion()}:${renderer.context.data.getVersion()}`
|
|
16761
14294
|
);
|
|
16762
|
-
return /* @__PURE__ */ (0,
|
|
14295
|
+
return /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(import_jsx_runtime180.Fragment, { children: stack.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
|
|
16763
14296
|
OverlayEntryView,
|
|
16764
14297
|
{
|
|
16765
14298
|
entry,
|
|
@@ -16776,7 +14309,7 @@ function OverlayEntryView({
|
|
|
16776
14309
|
renderer,
|
|
16777
14310
|
resolvePage
|
|
16778
14311
|
}) {
|
|
16779
|
-
const { t } = (0,
|
|
14312
|
+
const { t } = (0, import_runtime53.useI18n)();
|
|
16780
14313
|
const handleCancel = () => manager.close(entry.id);
|
|
16781
14314
|
let body = null;
|
|
16782
14315
|
if (entry.content) {
|
|
@@ -16785,7 +14318,7 @@ function OverlayEntryView({
|
|
|
16785
14318
|
parent: manager.parentScopeOf(entry.id)
|
|
16786
14319
|
});
|
|
16787
14320
|
} else if (entry.page) {
|
|
16788
|
-
body = /* @__PURE__ */ (0,
|
|
14321
|
+
body = /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
|
|
16789
14322
|
PageOverlayBody,
|
|
16790
14323
|
{
|
|
16791
14324
|
entry,
|
|
@@ -16795,9 +14328,9 @@ function OverlayEntryView({
|
|
|
16795
14328
|
);
|
|
16796
14329
|
}
|
|
16797
14330
|
if (entry.type === "drawer") {
|
|
16798
|
-
return /* @__PURE__ */ (0,
|
|
14331
|
+
return /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(ShadcnDrawerView, { entry, onCancel: handleCancel, children: body });
|
|
16799
14332
|
}
|
|
16800
|
-
return /* @__PURE__ */ (0,
|
|
14333
|
+
return /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
|
|
16801
14334
|
Dialog,
|
|
16802
14335
|
{
|
|
16803
14336
|
open: true,
|
|
@@ -16806,7 +14339,7 @@ function OverlayEntryView({
|
|
|
16806
14339
|
handleCancel();
|
|
16807
14340
|
}
|
|
16808
14341
|
},
|
|
16809
|
-
children: /* @__PURE__ */ (0,
|
|
14342
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime180.jsxs)(
|
|
16810
14343
|
DialogContent,
|
|
16811
14344
|
{
|
|
16812
14345
|
"data-slot": "overlay-modal",
|
|
@@ -16814,25 +14347,25 @@ function OverlayEntryView({
|
|
|
16814
14347
|
style: entry.width === void 0 ? void 0 : { width: toCssWidth(entry.width) },
|
|
16815
14348
|
showCloseButton: false,
|
|
16816
14349
|
children: [
|
|
16817
|
-
/* @__PURE__ */ (0,
|
|
16818
|
-
/* @__PURE__ */ (0,
|
|
16819
|
-
/* @__PURE__ */ (0,
|
|
14350
|
+
/* @__PURE__ */ (0, import_jsx_runtime180.jsxs)(DialogHeader, { children: [
|
|
14351
|
+
/* @__PURE__ */ (0, import_jsx_runtime180.jsx)(DialogTitle, { children: entry.title ?? "" }),
|
|
14352
|
+
/* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
|
|
16820
14353
|
DialogClose,
|
|
16821
14354
|
{
|
|
16822
|
-
render: /* @__PURE__ */ (0,
|
|
14355
|
+
render: /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
|
|
16823
14356
|
"button",
|
|
16824
14357
|
{
|
|
16825
14358
|
type: "button",
|
|
16826
14359
|
"data-slot": "overlay-modal-close",
|
|
16827
14360
|
"aria-label": t("pactor.overlay.close"),
|
|
16828
14361
|
className: "absolute top-4 right-4 cursor-pointer rounded-xs opacity-70 transition-opacity hover:opacity-100 focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-none",
|
|
16829
|
-
children: /* @__PURE__ */ (0,
|
|
14362
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(import_lucide_react40.XIcon, { className: "size-4" })
|
|
16830
14363
|
}
|
|
16831
14364
|
)
|
|
16832
14365
|
}
|
|
16833
14366
|
)
|
|
16834
14367
|
] }),
|
|
16835
|
-
/* @__PURE__ */ (0,
|
|
14368
|
+
/* @__PURE__ */ (0, import_jsx_runtime180.jsx)("div", { "data-slot": "overlay-modal-body", children: body })
|
|
16836
14369
|
]
|
|
16837
14370
|
}
|
|
16838
14371
|
)
|
|
@@ -16844,9 +14377,9 @@ function ShadcnDrawerView({
|
|
|
16844
14377
|
onCancel,
|
|
16845
14378
|
children
|
|
16846
14379
|
}) {
|
|
16847
|
-
const { t } = (0,
|
|
14380
|
+
const { t } = (0, import_runtime53.useI18n)();
|
|
16848
14381
|
const panelStyle = entry.width === void 0 ? void 0 : { width: toCssWidth(entry.width), maxWidth: toCssWidth(entry.width) };
|
|
16849
|
-
return /* @__PURE__ */ (0,
|
|
14382
|
+
return /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
|
|
16850
14383
|
Drawer,
|
|
16851
14384
|
{
|
|
16852
14385
|
direction: "right",
|
|
@@ -16857,7 +14390,7 @@ function ShadcnDrawerView({
|
|
|
16857
14390
|
onCancel();
|
|
16858
14391
|
}
|
|
16859
14392
|
},
|
|
16860
|
-
children: /* @__PURE__ */ (0,
|
|
14393
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime180.jsxs)(
|
|
16861
14394
|
DrawerContent,
|
|
16862
14395
|
{
|
|
16863
14396
|
"data-slot": "drawer-panel",
|
|
@@ -16865,27 +14398,27 @@ function ShadcnDrawerView({
|
|
|
16865
14398
|
style: panelStyle,
|
|
16866
14399
|
overlayProps: { onPointerDown: onCancel },
|
|
16867
14400
|
children: [
|
|
16868
|
-
/* @__PURE__ */ (0,
|
|
14401
|
+
/* @__PURE__ */ (0, import_jsx_runtime180.jsxs)(
|
|
16869
14402
|
DrawerHeader,
|
|
16870
14403
|
{
|
|
16871
14404
|
"data-slot": "drawer-header",
|
|
16872
14405
|
className: "flex flex-row items-center justify-between border-b border-border px-6 py-4",
|
|
16873
14406
|
children: [
|
|
16874
|
-
/* @__PURE__ */ (0,
|
|
16875
|
-
/* @__PURE__ */ (0,
|
|
14407
|
+
/* @__PURE__ */ (0, import_jsx_runtime180.jsx)(DrawerTitle, { className: "text-lg", children: entry.title ?? "" }),
|
|
14408
|
+
/* @__PURE__ */ (0, import_jsx_runtime180.jsx)(DrawerClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
|
|
16876
14409
|
"button",
|
|
16877
14410
|
{
|
|
16878
14411
|
type: "button",
|
|
16879
14412
|
"data-slot": "drawer-close",
|
|
16880
14413
|
"aria-label": t("pactor.overlay.close"),
|
|
16881
14414
|
className: "cursor-pointer rounded-xs opacity-70 transition-opacity hover:opacity-100 focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-none",
|
|
16882
|
-
children: /* @__PURE__ */ (0,
|
|
14415
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(import_lucide_react40.XIcon, { className: "size-4" })
|
|
16883
14416
|
}
|
|
16884
14417
|
) })
|
|
16885
14418
|
]
|
|
16886
14419
|
}
|
|
16887
14420
|
),
|
|
16888
|
-
/* @__PURE__ */ (0,
|
|
14421
|
+
/* @__PURE__ */ (0, import_jsx_runtime180.jsx)("div", { "data-slot": "drawer-body", className: "flex-1 overflow-auto p-6", children })
|
|
16889
14422
|
]
|
|
16890
14423
|
}
|
|
16891
14424
|
)
|
|
@@ -16897,9 +14430,9 @@ function PageOverlayBody({
|
|
|
16897
14430
|
renderer,
|
|
16898
14431
|
resolvePage
|
|
16899
14432
|
}) {
|
|
16900
|
-
const [child, setChild] = (0,
|
|
16901
|
-
const [error, setError] = (0,
|
|
16902
|
-
(0,
|
|
14433
|
+
const [child, setChild] = (0, import_react65.useState)(null);
|
|
14434
|
+
const [error, setError] = (0, import_react65.useState)(null);
|
|
14435
|
+
(0, import_react65.useEffect)(() => {
|
|
16903
14436
|
if (!resolvePage) {
|
|
16904
14437
|
setError(
|
|
16905
14438
|
new Error(
|
|
@@ -16917,7 +14450,7 @@ function PageOverlayBody({
|
|
|
16917
14450
|
return;
|
|
16918
14451
|
}
|
|
16919
14452
|
const host = renderer.context;
|
|
16920
|
-
created = (0,
|
|
14453
|
+
created = (0, import_runtime53.createPageRuntime)(pageDsl, {
|
|
16921
14454
|
app: host.app,
|
|
16922
14455
|
user: host.user,
|
|
16923
14456
|
components: host.components,
|
|
@@ -16941,32 +14474,28 @@ function PageOverlayBody({
|
|
|
16941
14474
|
};
|
|
16942
14475
|
}, [entry.id]);
|
|
16943
14476
|
if (error) {
|
|
16944
|
-
return /* @__PURE__ */ (0,
|
|
14477
|
+
return /* @__PURE__ */ (0, import_jsx_runtime180.jsx)("div", { role: "alert", children: error.message });
|
|
16945
14478
|
}
|
|
16946
14479
|
if (!child) {
|
|
16947
14480
|
return null;
|
|
16948
14481
|
}
|
|
16949
|
-
return /* @__PURE__ */ (0,
|
|
14482
|
+
return /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(import_runtime53.PageRuntimeView, { runtime: child });
|
|
16950
14483
|
}
|
|
16951
14484
|
// Annotate the CommonJS export names for ESM import in node:
|
|
16952
14485
|
0 && (module.exports = {
|
|
16953
14486
|
Accordion,
|
|
16954
14487
|
AdminLayout,
|
|
16955
14488
|
Affix,
|
|
16956
|
-
AgentStatus,
|
|
16957
14489
|
Alert,
|
|
16958
14490
|
AlertDialog,
|
|
16959
14491
|
Anchor,
|
|
16960
|
-
ArtifactPanel,
|
|
16961
14492
|
AspectRatio,
|
|
16962
|
-
Attachment,
|
|
16963
14493
|
Audio,
|
|
16964
14494
|
Avatar,
|
|
16965
14495
|
BackTop,
|
|
16966
14496
|
Badge,
|
|
16967
14497
|
BlankLayout,
|
|
16968
14498
|
Breadcrumb,
|
|
16969
|
-
Bubble,
|
|
16970
14499
|
Button,
|
|
16971
14500
|
ButtonGroup,
|
|
16972
14501
|
CONTROL_SIZE_AREA,
|
|
@@ -16980,12 +14509,9 @@ function PageOverlayBody({
|
|
|
16980
14509
|
Cascader,
|
|
16981
14510
|
ChatInput,
|
|
16982
14511
|
ChatLayout,
|
|
16983
|
-
ChatMessage,
|
|
16984
|
-
ChatPage,
|
|
16985
14512
|
Checkbox,
|
|
16986
14513
|
ChipFilter,
|
|
16987
14514
|
ChipNode,
|
|
16988
|
-
Citation,
|
|
16989
14515
|
ClearHoverButton,
|
|
16990
14516
|
CodeBlock,
|
|
16991
14517
|
Col,
|
|
@@ -16993,11 +14519,9 @@ function PageOverlayBody({
|
|
|
16993
14519
|
ColorPicker,
|
|
16994
14520
|
Combobox,
|
|
16995
14521
|
Command,
|
|
16996
|
-
Composer,
|
|
16997
14522
|
Container,
|
|
16998
14523
|
Content,
|
|
16999
14524
|
ContextMenu,
|
|
17000
|
-
ConversationList,
|
|
17001
14525
|
DataTable,
|
|
17002
14526
|
DatePicker,
|
|
17003
14527
|
Descriptions,
|
|
@@ -17041,7 +14565,6 @@ function PageOverlayBody({
|
|
|
17041
14565
|
Menu,
|
|
17042
14566
|
Menubar,
|
|
17043
14567
|
Message,
|
|
17044
|
-
MessageList,
|
|
17045
14568
|
NavigationMenu,
|
|
17046
14569
|
Notification,
|
|
17047
14570
|
NumberInput,
|
|
@@ -17053,7 +14576,6 @@ function PageOverlayBody({
|
|
|
17053
14576
|
Popconfirm,
|
|
17054
14577
|
Popover,
|
|
17055
14578
|
Progress,
|
|
17056
|
-
Prompt,
|
|
17057
14579
|
QRCode,
|
|
17058
14580
|
RadioGroup,
|
|
17059
14581
|
RailTooltip,
|
|
@@ -17065,7 +14587,6 @@ function PageOverlayBody({
|
|
|
17065
14587
|
ScrollArea,
|
|
17066
14588
|
Segmented,
|
|
17067
14589
|
Select,
|
|
17068
|
-
Sender,
|
|
17069
14590
|
Separator,
|
|
17070
14591
|
Sheet,
|
|
17071
14592
|
Sidebar,
|
|
@@ -17078,21 +14599,16 @@ function PageOverlayBody({
|
|
|
17078
14599
|
Statistic,
|
|
17079
14600
|
Status,
|
|
17080
14601
|
Steps,
|
|
17081
|
-
StepsPanel,
|
|
17082
|
-
StreamingText,
|
|
17083
|
-
Suggestion,
|
|
17084
14602
|
Switch,
|
|
17085
14603
|
Table,
|
|
17086
14604
|
Tabs,
|
|
17087
14605
|
Tag,
|
|
17088
14606
|
Text,
|
|
17089
14607
|
Textarea,
|
|
17090
|
-
Thinking,
|
|
17091
14608
|
TimePicker,
|
|
17092
14609
|
Timeline,
|
|
17093
14610
|
Toggle,
|
|
17094
14611
|
ToggleGroup,
|
|
17095
|
-
ToolCall,
|
|
17096
14612
|
Tooltip,
|
|
17097
14613
|
Tour,
|
|
17098
14614
|
Transfer,
|
|
@@ -17102,8 +14618,6 @@ function PageOverlayBody({
|
|
|
17102
14618
|
Upload,
|
|
17103
14619
|
Video,
|
|
17104
14620
|
Watermark,
|
|
17105
|
-
Welcome,
|
|
17106
|
-
buildArtifactTree,
|
|
17107
14621
|
builtinComponents,
|
|
17108
14622
|
collectDefaultOpenKeys,
|
|
17109
14623
|
createComponentRegistry,
|
|
@@ -17118,5 +14632,6 @@ function PageOverlayBody({
|
|
|
17118
14632
|
registerInteractionActions,
|
|
17119
14633
|
resolveLayout,
|
|
17120
14634
|
useFormContext,
|
|
14635
|
+
useOptionalRenderer,
|
|
17121
14636
|
useSidebarDrawer
|
|
17122
14637
|
});
|