flowcloudai-ui 0.1.0 → 0.1.1
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/index.cjs +1095 -560
- package/dist/index.css +1155 -312
- package/dist/index.d.cts +281 -69
- package/dist/index.d.ts +281 -69
- package/dist/index.js +1035 -505
- package/package.json +6 -5
package/dist/index.js
CHANGED
|
@@ -49,10 +49,39 @@ function Button({
|
|
|
49
49
|
iconOnly = false,
|
|
50
50
|
iconLeft,
|
|
51
51
|
iconRight,
|
|
52
|
+
background,
|
|
53
|
+
hoverBackground,
|
|
54
|
+
activeBackground,
|
|
55
|
+
color,
|
|
56
|
+
hoverColor,
|
|
57
|
+
activeColor,
|
|
58
|
+
borderColor,
|
|
59
|
+
hoverBorderColor,
|
|
52
60
|
className,
|
|
61
|
+
style,
|
|
53
62
|
children,
|
|
54
63
|
...props
|
|
55
64
|
}) {
|
|
65
|
+
const colorVars = {
|
|
66
|
+
"--btn-bg": background,
|
|
67
|
+
"--btn-bg-hover": hoverBackground,
|
|
68
|
+
"--btn-bg-active": activeBackground,
|
|
69
|
+
"--btn-color": color,
|
|
70
|
+
"--btn-color-hover": hoverColor,
|
|
71
|
+
"--btn-color-active": activeColor,
|
|
72
|
+
"--btn-border": borderColor,
|
|
73
|
+
"--btn-border-hover": hoverBorderColor
|
|
74
|
+
};
|
|
75
|
+
const overrideStyle = {};
|
|
76
|
+
for (const [key, value] of Object.entries(colorVars)) {
|
|
77
|
+
if (value !== void 0) {
|
|
78
|
+
overrideStyle[key] = value;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const mergedStyle = {
|
|
82
|
+
...overrideStyle,
|
|
83
|
+
...style
|
|
84
|
+
};
|
|
56
85
|
const classNames = [
|
|
57
86
|
"fc-btn",
|
|
58
87
|
`fc-btn--${variant}`,
|
|
@@ -69,6 +98,7 @@ function Button({
|
|
|
69
98
|
{
|
|
70
99
|
className: classNames,
|
|
71
100
|
disabled: disabled || loading,
|
|
101
|
+
style: mergedStyle,
|
|
72
102
|
...props,
|
|
73
103
|
children: [
|
|
74
104
|
iconLeft && !loading && /* @__PURE__ */ jsx2("span", { className: "fc-btn__icon fc-btn__icon--left", children: iconLeft }),
|
|
@@ -107,6 +137,11 @@ function CheckButton({
|
|
|
107
137
|
size = "md",
|
|
108
138
|
labelLeft,
|
|
109
139
|
labelRight,
|
|
140
|
+
trackBackground,
|
|
141
|
+
checkedTrackBackground,
|
|
142
|
+
thumbBackground,
|
|
143
|
+
thumbDotColor,
|
|
144
|
+
labelColor,
|
|
110
145
|
className = "",
|
|
111
146
|
style
|
|
112
147
|
}) {
|
|
@@ -125,6 +160,23 @@ function CheckButton({
|
|
|
125
160
|
toggle();
|
|
126
161
|
}
|
|
127
162
|
};
|
|
163
|
+
const colorVars = {
|
|
164
|
+
"--check-track-bg": trackBackground,
|
|
165
|
+
"--check-track-bg-checked": checkedTrackBackground,
|
|
166
|
+
"--check-thumb-bg": thumbBackground,
|
|
167
|
+
"--check-thumb-dot-color": thumbDotColor,
|
|
168
|
+
"--check-label-color": labelColor
|
|
169
|
+
};
|
|
170
|
+
const overrideStyle = {};
|
|
171
|
+
for (const [key, value] of Object.entries(colorVars)) {
|
|
172
|
+
if (value !== void 0) {
|
|
173
|
+
overrideStyle[key] = value;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const mergedStyle = {
|
|
177
|
+
...overrideStyle,
|
|
178
|
+
...style
|
|
179
|
+
};
|
|
128
180
|
const cls = [
|
|
129
181
|
"fc-check",
|
|
130
182
|
`fc-check--${size}`,
|
|
@@ -136,7 +188,7 @@ function CheckButton({
|
|
|
136
188
|
"div",
|
|
137
189
|
{
|
|
138
190
|
className: cls,
|
|
139
|
-
style,
|
|
191
|
+
style: mergedStyle,
|
|
140
192
|
role: "switch",
|
|
141
193
|
"aria-checked": checked,
|
|
142
194
|
tabIndex: disabled ? -1 : 0,
|
|
@@ -162,8 +214,26 @@ function RollingBox({
|
|
|
162
214
|
showTrack = false,
|
|
163
215
|
children,
|
|
164
216
|
className,
|
|
217
|
+
thumbColor,
|
|
218
|
+
thumbHoverColor,
|
|
219
|
+
thumbActiveColor,
|
|
220
|
+
trackColor,
|
|
221
|
+
style,
|
|
165
222
|
...props
|
|
166
223
|
}) {
|
|
224
|
+
const colorVars = {
|
|
225
|
+
"--roll-thumb": thumbColor,
|
|
226
|
+
"--roll-thumb-hover": thumbHoverColor,
|
|
227
|
+
"--roll-thumb-active": thumbActiveColor,
|
|
228
|
+
"--roll-track": trackColor
|
|
229
|
+
};
|
|
230
|
+
const overrideStyle = {};
|
|
231
|
+
for (const [key, value] of Object.entries(colorVars)) {
|
|
232
|
+
if (value !== void 0) {
|
|
233
|
+
overrideStyle[key] = value;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
const mergedStyle = { ...overrideStyle, ...style };
|
|
167
237
|
const containerRef = React2.useRef(null);
|
|
168
238
|
const [isScrolling, setIsScrolling] = React2.useState(false);
|
|
169
239
|
const scrollTimeoutRef = React2.useRef(null);
|
|
@@ -199,6 +269,7 @@ function RollingBox({
|
|
|
199
269
|
{
|
|
200
270
|
ref: containerRef,
|
|
201
271
|
className: classNames,
|
|
272
|
+
style: mergedStyle,
|
|
202
273
|
onScroll: handleScroll,
|
|
203
274
|
...props,
|
|
204
275
|
children: /* @__PURE__ */ jsx4("div", { className: "fc-roll__content", children })
|
|
@@ -207,134 +278,100 @@ function RollingBox({
|
|
|
207
278
|
}
|
|
208
279
|
|
|
209
280
|
// src/components/Bar/SideBar.tsx
|
|
210
|
-
import
|
|
281
|
+
import { memo, useCallback as useCallback2 } from "react";
|
|
211
282
|
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
collapsed: controlledCollapsed,
|
|
221
|
-
defaultCollapsed = false,
|
|
222
|
-
onCollapse,
|
|
223
|
-
className,
|
|
224
|
-
width = 240,
|
|
225
|
-
collapsedWidth = 64
|
|
226
|
-
}) {
|
|
227
|
-
const [internalSelected, setInternalSelected] = React3.useState(defaultSelectedKeys);
|
|
228
|
-
const [internalOpen, setInternalOpen] = React3.useState(defaultOpenKeys);
|
|
229
|
-
const [internalCollapsed, setInternalCollapsed] = React3.useState(defaultCollapsed);
|
|
230
|
-
const currentSelected = controlledSelected ?? internalSelected;
|
|
231
|
-
const currentOpen = controlledOpen ?? internalOpen;
|
|
232
|
-
const currentCollapsed = controlledCollapsed ?? internalCollapsed;
|
|
233
|
-
const updateOpen = React3.useCallback((next) => {
|
|
234
|
-
if (controlledOpen === void 0) setInternalOpen(next);
|
|
235
|
-
onOpenChange?.(next);
|
|
236
|
-
}, [controlledOpen, onOpenChange]);
|
|
237
|
-
const toggleOpen = React3.useCallback((key) => {
|
|
238
|
-
const next = currentOpen.includes(key) ? currentOpen.filter((k) => k !== key) : [...currentOpen, key];
|
|
239
|
-
updateOpen(next);
|
|
240
|
-
}, [currentOpen, updateOpen]);
|
|
241
|
-
const handleSelect = React3.useCallback((key, item) => {
|
|
242
|
-
if (item.disabled) return;
|
|
243
|
-
const next = [key];
|
|
244
|
-
if (controlledSelected === void 0) setInternalSelected(next);
|
|
245
|
-
onSelect?.(next);
|
|
246
|
-
}, [controlledSelected, onSelect]);
|
|
247
|
-
const toggleCollapse = React3.useCallback(() => {
|
|
248
|
-
const next = !currentCollapsed;
|
|
249
|
-
if (controlledCollapsed === void 0) setInternalCollapsed(next);
|
|
250
|
-
onCollapse?.(next);
|
|
251
|
-
}, [currentCollapsed, controlledCollapsed, onCollapse]);
|
|
252
|
-
const handleItemClick = React3.useCallback((item) => {
|
|
253
|
-
if (item.children?.length) {
|
|
254
|
-
toggleOpen(item.key);
|
|
255
|
-
} else {
|
|
256
|
-
handleSelect(item.key, item);
|
|
257
|
-
}
|
|
258
|
-
}, [toggleOpen, handleSelect]);
|
|
259
|
-
const handleItemKeyDown = React3.useCallback((e, item) => {
|
|
260
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
261
|
-
e.preventDefault();
|
|
262
|
-
handleItemClick(item);
|
|
263
|
-
}
|
|
264
|
-
}, [handleItemClick]);
|
|
265
|
-
const renderMenuItem = (item, level = 0) => {
|
|
266
|
-
const hasChildren = (item.children?.length ?? 0) > 0;
|
|
267
|
-
const isOpen = currentOpen.includes(item.key);
|
|
268
|
-
const isSelected = currentSelected.includes(item.key);
|
|
269
|
-
const itemClassName = [
|
|
270
|
-
"fc-sidebar__item",
|
|
271
|
-
`fc-sidebar__item--level-${level}`,
|
|
272
|
-
hasChildren && "fc-sidebar__item--parent",
|
|
273
|
-
isOpen && "fc-sidebar__item--open",
|
|
274
|
-
isSelected && "fc-sidebar__item--selected",
|
|
275
|
-
item.disabled && "fc-sidebar__item--disabled"
|
|
276
|
-
].filter(Boolean).join(" ");
|
|
277
|
-
const Tag = item.href ? "a" : "div";
|
|
278
|
-
const interactiveProps = {
|
|
279
|
-
role: hasChildren ? "treeitem" : "menuitem",
|
|
280
|
-
tabIndex: item.disabled ? -1 : 0,
|
|
281
|
-
"aria-selected": isSelected || void 0,
|
|
282
|
-
"aria-expanded": hasChildren ? isOpen : void 0,
|
|
283
|
-
"aria-disabled": item.disabled || void 0,
|
|
284
|
-
onClick: () => handleItemClick(item),
|
|
285
|
-
onKeyDown: (e) => handleItemKeyDown(e, item),
|
|
286
|
-
...item.href ? { href: item.href } : {}
|
|
287
|
-
};
|
|
288
|
-
return /* @__PURE__ */ jsxs3("div", { className: "fc-sidebar__item-wrapper", children: [
|
|
289
|
-
/* @__PURE__ */ jsxs3(Tag, { className: itemClassName, ...interactiveProps, children: [
|
|
290
|
-
item.icon && /* @__PURE__ */ jsx5("span", { className: "fc-sidebar__icon", "aria-hidden": "true", children: item.icon }),
|
|
291
|
-
/* @__PURE__ */ jsx5("span", { className: "fc-sidebar__label", children: item.label }),
|
|
292
|
-
hasChildren && /* @__PURE__ */ jsx5("span", { className: "fc-sidebar__arrow", "aria-hidden": "true", children: "\u25B6" })
|
|
293
|
-
] }),
|
|
294
|
-
hasChildren && /* @__PURE__ */ jsx5(
|
|
295
|
-
"div",
|
|
296
|
-
{
|
|
297
|
-
className: [
|
|
298
|
-
"fc-sidebar__submenu",
|
|
299
|
-
isOpen && "fc-sidebar__submenu--open"
|
|
300
|
-
].filter(Boolean).join(" "),
|
|
301
|
-
role: "group",
|
|
302
|
-
children: /* @__PURE__ */ jsx5("div", { className: "fc-sidebar__submenu-inner", children: item.children.map((child) => renderMenuItem(child, level + 1)) })
|
|
303
|
-
}
|
|
304
|
-
)
|
|
305
|
-
] }, item.key);
|
|
306
|
-
};
|
|
307
|
-
const sidebarStyle = {
|
|
308
|
-
"--sidebar-width": `${currentCollapsed ? collapsedWidth : width}px`,
|
|
309
|
-
"--sidebar-collapsed-width": `${collapsedWidth}px`
|
|
310
|
-
};
|
|
283
|
+
var SideBarItemView = memo(({ item, isSelected, onClick }) => {
|
|
284
|
+
const classes = [
|
|
285
|
+
"fc-sidebar__item",
|
|
286
|
+
isSelected && "fc-sidebar__item--selected",
|
|
287
|
+
item.disabled && "fc-sidebar__item--disabled"
|
|
288
|
+
].filter(Boolean).join(" ");
|
|
289
|
+
const Tag = item.href ? "a" : "div";
|
|
290
|
+
const linkProps = item.href ? { href: item.href } : {};
|
|
311
291
|
return /* @__PURE__ */ jsxs3(
|
|
312
|
-
|
|
292
|
+
Tag,
|
|
313
293
|
{
|
|
314
|
-
className:
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
className
|
|
318
|
-
].filter(Boolean).join(" "),
|
|
319
|
-
style: sidebarStyle,
|
|
320
|
-
role: "navigation",
|
|
321
|
-
"aria-label": "Sidebar",
|
|
294
|
+
className: classes,
|
|
295
|
+
onClick: () => !item.disabled && onClick(item.key),
|
|
296
|
+
...linkProps,
|
|
322
297
|
children: [
|
|
323
|
-
/* @__PURE__ */ jsx5("
|
|
324
|
-
|
|
325
|
-
{
|
|
326
|
-
className: "fc-sidebar__collapse-btn",
|
|
327
|
-
onClick: toggleCollapse,
|
|
328
|
-
"aria-label": currentCollapsed ? "\u5C55\u5F00\u4FA7\u680F" : "\u6536\u8D77\u4FA7\u680F",
|
|
329
|
-
"aria-expanded": !currentCollapsed,
|
|
330
|
-
children: currentCollapsed ? "\u2192" : "\u2190"
|
|
331
|
-
}
|
|
332
|
-
) }),
|
|
333
|
-
/* @__PURE__ */ jsx5("nav", { className: "fc-sidebar__menu", role: "tree", children: items.map((item) => renderMenuItem(item)) })
|
|
298
|
+
item.icon && /* @__PURE__ */ jsx5("span", { className: "fc-sidebar__icon", children: item.icon }),
|
|
299
|
+
/* @__PURE__ */ jsx5("span", { className: "fc-sidebar__label", children: item.label })
|
|
334
300
|
]
|
|
335
301
|
}
|
|
336
302
|
);
|
|
337
|
-
}
|
|
303
|
+
});
|
|
304
|
+
SideBarItemView.displayName = "SideBarItemView";
|
|
305
|
+
var SideBar = memo(({
|
|
306
|
+
items,
|
|
307
|
+
selectedKey,
|
|
308
|
+
collapsed,
|
|
309
|
+
width = 240,
|
|
310
|
+
collapsedWidth = 64,
|
|
311
|
+
onSelect,
|
|
312
|
+
onCollapse,
|
|
313
|
+
className = "",
|
|
314
|
+
style
|
|
315
|
+
}) => {
|
|
316
|
+
const handleClick = useCallback2(
|
|
317
|
+
(key) => onSelect(key),
|
|
318
|
+
[onSelect]
|
|
319
|
+
);
|
|
320
|
+
const toggleCollapse = useCallback2(
|
|
321
|
+
() => onCollapse(!collapsed),
|
|
322
|
+
[collapsed, onCollapse]
|
|
323
|
+
);
|
|
324
|
+
const rootClasses = [
|
|
325
|
+
"fc-sidebar",
|
|
326
|
+
collapsed && "fc-sidebar--collapsed",
|
|
327
|
+
className
|
|
328
|
+
].filter(Boolean).join(" ");
|
|
329
|
+
const rootStyle = {
|
|
330
|
+
"--sidebar-width": `${collapsed ? collapsedWidth : width}px`,
|
|
331
|
+
"--sidebar-collapsed-width": `${collapsedWidth}px`,
|
|
332
|
+
...style
|
|
333
|
+
};
|
|
334
|
+
return /* @__PURE__ */ jsxs3("aside", { className: rootClasses, style: rootStyle, children: [
|
|
335
|
+
/* @__PURE__ */ jsx5("div", { className: "fc-sidebar__header", children: /* @__PURE__ */ jsx5(
|
|
336
|
+
"button",
|
|
337
|
+
{
|
|
338
|
+
className: "fc-sidebar__collapse-btn",
|
|
339
|
+
onClick: toggleCollapse,
|
|
340
|
+
children: /* @__PURE__ */ jsx5(
|
|
341
|
+
"svg",
|
|
342
|
+
{
|
|
343
|
+
className: "fc-sidebar__collapse-icon",
|
|
344
|
+
width: "16",
|
|
345
|
+
height: "16",
|
|
346
|
+
viewBox: "0 0 16 16",
|
|
347
|
+
fill: "none",
|
|
348
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
349
|
+
children: /* @__PURE__ */ jsx5(
|
|
350
|
+
"path",
|
|
351
|
+
{
|
|
352
|
+
d: collapsed ? "M6 3L11 8L6 13" : "M10 3L5 8L10 13",
|
|
353
|
+
stroke: "currentColor",
|
|
354
|
+
strokeWidth: "1.5",
|
|
355
|
+
strokeLinecap: "round",
|
|
356
|
+
strokeLinejoin: "round"
|
|
357
|
+
}
|
|
358
|
+
)
|
|
359
|
+
}
|
|
360
|
+
)
|
|
361
|
+
}
|
|
362
|
+
) }),
|
|
363
|
+
/* @__PURE__ */ jsx5("nav", { className: "fc-sidebar__menu", children: items.map((item) => /* @__PURE__ */ jsx5(
|
|
364
|
+
SideBarItemView,
|
|
365
|
+
{
|
|
366
|
+
item,
|
|
367
|
+
isSelected: selectedKey === item.key,
|
|
368
|
+
onClick: handleClick
|
|
369
|
+
},
|
|
370
|
+
item.key
|
|
371
|
+
)) })
|
|
372
|
+
] });
|
|
373
|
+
});
|
|
374
|
+
SideBar.displayName = "SideBar";
|
|
338
375
|
|
|
339
376
|
// src/components/Input/Input.tsx
|
|
340
377
|
import * as React4 from "react";
|
|
@@ -402,8 +439,8 @@ var Input = React4.forwardRef(({
|
|
|
402
439
|
);
|
|
403
440
|
return /* @__PURE__ */ jsxs4("div", { className: classNames, children: [
|
|
404
441
|
addonBefore && /* @__PURE__ */ jsx6("span", { className: "fc-input__addon fc-input__addon--before", children: addonBefore }),
|
|
405
|
-
prefix && /* @__PURE__ */ jsx6("span", { className: "fc-input__prefix", children: prefix }),
|
|
406
442
|
/* @__PURE__ */ jsxs4("div", { className: "fc-input__wrapper", children: [
|
|
443
|
+
prefix && /* @__PURE__ */ jsx6("span", { className: "fc-input__prefix", children: prefix }),
|
|
407
444
|
input,
|
|
408
445
|
/* @__PURE__ */ jsxs4("span", { className: "fc-input__actions", children: [
|
|
409
446
|
showClear && /* @__PURE__ */ jsx6(
|
|
@@ -450,7 +487,16 @@ function Slider({
|
|
|
450
487
|
disabled = false,
|
|
451
488
|
marks,
|
|
452
489
|
tooltip = false,
|
|
453
|
-
className = ""
|
|
490
|
+
className = "",
|
|
491
|
+
style,
|
|
492
|
+
trackBackground,
|
|
493
|
+
fillBackground,
|
|
494
|
+
thumbBackground,
|
|
495
|
+
thumbBorderColor,
|
|
496
|
+
markDotColor,
|
|
497
|
+
markLabelColor,
|
|
498
|
+
tooltipBackground,
|
|
499
|
+
tooltipColor
|
|
454
500
|
}) {
|
|
455
501
|
const trackRef = React5.useRef(null);
|
|
456
502
|
const draggingRef = React5.useRef(null);
|
|
@@ -459,6 +505,23 @@ function Slider({
|
|
|
459
505
|
const [internalValue, setInternalValue] = React5.useState(initialValue);
|
|
460
506
|
const isControlled = controlledValue !== void 0;
|
|
461
507
|
const currentValue = isControlled ? controlledValue : internalValue;
|
|
508
|
+
const colorVars = {
|
|
509
|
+
"--slider-track-bg": trackBackground,
|
|
510
|
+
"--slider-fill-bg": fillBackground,
|
|
511
|
+
"--slider-thumb-bg": thumbBackground,
|
|
512
|
+
"--slider-thumb-border": thumbBorderColor,
|
|
513
|
+
"--slider-mark-dot-bg": markDotColor,
|
|
514
|
+
"--slider-mark-label-color": markLabelColor,
|
|
515
|
+
"--slider-tooltip-bg": tooltipBackground,
|
|
516
|
+
"--slider-tooltip-color": tooltipColor
|
|
517
|
+
};
|
|
518
|
+
const overrideStyle = {};
|
|
519
|
+
for (const [key, value] of Object.entries(colorVars)) {
|
|
520
|
+
if (value !== void 0) {
|
|
521
|
+
overrideStyle[key] = value;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
const mergedStyle = { ...overrideStyle, ...style };
|
|
462
525
|
const getPercent = (val) => Math.max(0, Math.min(100, (val - min) / (max - min) * 100));
|
|
463
526
|
const getValueFromPercent = (percent) => {
|
|
464
527
|
const raw = min + percent / 100 * (max - min);
|
|
@@ -512,7 +575,7 @@ function Slider({
|
|
|
512
575
|
dragging !== null && "fc-slider--dragging",
|
|
513
576
|
className
|
|
514
577
|
].filter(Boolean).join(" ");
|
|
515
|
-
return /* @__PURE__ */ jsx7("div", { className: cls, children: /* @__PURE__ */ jsxs5(
|
|
578
|
+
return /* @__PURE__ */ jsx7("div", { className: cls, style: mergedStyle, children: /* @__PURE__ */ jsxs5(
|
|
516
579
|
"div",
|
|
517
580
|
{
|
|
518
581
|
ref: trackRef,
|
|
@@ -574,10 +637,30 @@ function Select({
|
|
|
574
637
|
multiple = false,
|
|
575
638
|
disabled = false,
|
|
576
639
|
className = "",
|
|
640
|
+
style,
|
|
577
641
|
virtualScroll = false,
|
|
578
642
|
virtualItemHeight = 32,
|
|
579
|
-
maxHeight = 256
|
|
643
|
+
maxHeight = 256,
|
|
644
|
+
triggerBackground,
|
|
645
|
+
triggerBorderColor,
|
|
646
|
+
selectedColor,
|
|
647
|
+
selectedBackground,
|
|
648
|
+
hoverBackground
|
|
580
649
|
}) {
|
|
650
|
+
const colorVars = {
|
|
651
|
+
"--select-trigger-bg": triggerBackground,
|
|
652
|
+
"--select-trigger-border": triggerBorderColor,
|
|
653
|
+
"--select-option-selected-color": selectedColor,
|
|
654
|
+
"--select-option-selected-bg": selectedBackground,
|
|
655
|
+
"--select-option-hover-bg": hoverBackground
|
|
656
|
+
};
|
|
657
|
+
const overrideStyle = {};
|
|
658
|
+
for (const [key, value] of Object.entries(colorVars)) {
|
|
659
|
+
if (value !== void 0) {
|
|
660
|
+
overrideStyle[key] = value;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
const mergedStyle = { ...overrideStyle, ...style };
|
|
581
664
|
const [isOpen, setIsOpen] = React6.useState(false);
|
|
582
665
|
const [searchValue, setSearchValue] = React6.useState("");
|
|
583
666
|
const [highlightedIndex, setHighlightedIndex] = React6.useState(0);
|
|
@@ -651,14 +734,14 @@ function Select({
|
|
|
651
734
|
disabled && "fc-select--disabled",
|
|
652
735
|
className
|
|
653
736
|
].filter(Boolean).join(" ");
|
|
654
|
-
return /* @__PURE__ */ jsxs6("div", { ref: containerRef, className: classNames, children: [
|
|
737
|
+
return /* @__PURE__ */ jsxs6("div", { ref: containerRef, className: classNames, style: mergedStyle, children: [
|
|
655
738
|
/* @__PURE__ */ jsxs6(
|
|
656
739
|
"div",
|
|
657
740
|
{
|
|
658
741
|
className: "fc-select__trigger",
|
|
659
742
|
onClick: () => !disabled && setIsOpen(!isOpen),
|
|
660
743
|
children: [
|
|
661
|
-
/* @__PURE__ */ jsx8("span", { className: `fc-select__value ${!currentValue && "fc-select__value--placeholder"}`, children: displayLabel() }),
|
|
744
|
+
/* @__PURE__ */ jsx8("span", { className: `fc-select__value ${(currentValue === void 0 || currentValue === null || multiple && !currentValue.length) && "fc-select__value--placeholder"}`, children: displayLabel() }),
|
|
662
745
|
/* @__PURE__ */ jsx8("span", { className: "fc-select__arrow", children: "\u25BC" })
|
|
663
746
|
]
|
|
664
747
|
}
|
|
@@ -725,7 +808,8 @@ function Select({
|
|
|
725
808
|
}
|
|
726
809
|
function highlightText(text, highlight) {
|
|
727
810
|
if (!highlight) return text;
|
|
728
|
-
const
|
|
811
|
+
const escaped = highlight.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
812
|
+
const parts = text.split(new RegExp(`(${escaped})`, "gi"));
|
|
729
813
|
return parts.map(
|
|
730
814
|
(part, i) => part.toLowerCase() === highlight.toLowerCase() ? /* @__PURE__ */ jsx8("mark", { className: "fc-select__highlight", children: part }, i) : part
|
|
731
815
|
);
|
|
@@ -735,13 +819,13 @@ function Select({
|
|
|
735
819
|
// src/components/Tree/Tree.tsx
|
|
736
820
|
import {
|
|
737
821
|
createContext as createContext2,
|
|
738
|
-
memo,
|
|
822
|
+
memo as memo2,
|
|
739
823
|
useCallback as useCallback4,
|
|
740
824
|
useContext as useContext2,
|
|
741
825
|
useEffect as useEffect4,
|
|
742
826
|
useMemo as useMemo2,
|
|
743
827
|
useRef as useRef4,
|
|
744
|
-
useState as
|
|
828
|
+
useState as useState8
|
|
745
829
|
} from "react";
|
|
746
830
|
import {
|
|
747
831
|
DndContext,
|
|
@@ -753,11 +837,11 @@ import {
|
|
|
753
837
|
} from "@dnd-kit/core";
|
|
754
838
|
|
|
755
839
|
// src/components/Tree/DeleteDialog.tsx
|
|
756
|
-
import { useState as
|
|
840
|
+
import { useState as useState7 } from "react";
|
|
757
841
|
import { Fragment, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
758
842
|
function DeleteDialog({ node, onClose, onDelete }) {
|
|
759
|
-
const [phase, setPhase] =
|
|
760
|
-
const [loading, setLoading] =
|
|
843
|
+
const [phase, setPhase] = useState7("choose");
|
|
844
|
+
const [loading, setLoading] = useState7(false);
|
|
761
845
|
if (!node) return null;
|
|
762
846
|
const reset = () => {
|
|
763
847
|
setPhase("choose");
|
|
@@ -919,10 +1003,10 @@ import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-ru
|
|
|
919
1003
|
var TreeActionsCtx = createContext2(null);
|
|
920
1004
|
var TreeStateCtx = createContext2(null);
|
|
921
1005
|
var DndStateCtx = createContext2(null);
|
|
922
|
-
var CollapsePanel =
|
|
1006
|
+
var CollapsePanel = memo2(function CollapsePanel2({ open, children }) {
|
|
923
1007
|
const innerRef = useRef4(null);
|
|
924
|
-
const [height, setHeight] =
|
|
925
|
-
const [ready, setReady] =
|
|
1008
|
+
const [height, setHeight] = useState8(0);
|
|
1009
|
+
const [ready, setReady] = useState8(false);
|
|
926
1010
|
useEffect4(() => {
|
|
927
1011
|
const el = innerRef.current;
|
|
928
1012
|
if (!el) return;
|
|
@@ -938,7 +1022,7 @@ var CollapsePanel = memo(function CollapsePanel2({ open, children }) {
|
|
|
938
1022
|
transition: ready ? "height 0.12s ease-out" : "none"
|
|
939
1023
|
}, children: /* @__PURE__ */ jsx10("div", { ref: innerRef, children }) });
|
|
940
1024
|
});
|
|
941
|
-
var DndSlot =
|
|
1025
|
+
var DndSlot = memo2(function DndSlot2({
|
|
942
1026
|
nodeKey,
|
|
943
1027
|
disabled,
|
|
944
1028
|
children
|
|
@@ -959,14 +1043,14 @@ var DndSlot = memo(function DndSlot2({
|
|
|
959
1043
|
);
|
|
960
1044
|
return /* @__PURE__ */ jsx10(Fragment2, { children: children({ setRef, handleProps, isDragging, isDragSource, dropPosition }) });
|
|
961
1045
|
});
|
|
962
|
-
var TreeNodeItem =
|
|
1046
|
+
var TreeNodeItem = memo2(function TreeNodeItem2({ node, level, hidden = false }) {
|
|
963
1047
|
const actions = useContext2(TreeActionsCtx);
|
|
964
1048
|
const state = useContext2(TreeStateCtx);
|
|
965
1049
|
const isExpanded = state.expandedKeys.has(node.key);
|
|
966
1050
|
const isEditing = state.editingKey === node.key;
|
|
967
1051
|
const hasChildren = node.children.length > 0;
|
|
968
1052
|
const indent = level * 20 + 12;
|
|
969
|
-
const [localEdit, setLocalEdit] =
|
|
1053
|
+
const [localEdit, setLocalEdit] = useState8("");
|
|
970
1054
|
useEffect4(() => {
|
|
971
1055
|
if (isEditing) setLocalEdit(node.title);
|
|
972
1056
|
}, [isEditing, node.title]);
|
|
@@ -1093,11 +1177,11 @@ function Tree({
|
|
|
1093
1177
|
scrollHeight = "400px",
|
|
1094
1178
|
className = ""
|
|
1095
1179
|
}) {
|
|
1096
|
-
const [expandedKeys, setExpandedKeys] =
|
|
1097
|
-
const [editingKey, setEditingKey] =
|
|
1098
|
-
const [deleteTarget, setDeleteTarget] =
|
|
1099
|
-
const [searchValue, setSearchValue] =
|
|
1100
|
-
const [dndState, setDndState] =
|
|
1180
|
+
const [expandedKeys, setExpandedKeys] = useState8(/* @__PURE__ */ new Set());
|
|
1181
|
+
const [editingKey, setEditingKey] = useState8(null);
|
|
1182
|
+
const [deleteTarget, setDeleteTarget] = useState8(null);
|
|
1183
|
+
const [searchValue, setSearchValue] = useState8("");
|
|
1184
|
+
const [dndState, setDndState] = useState8({
|
|
1101
1185
|
dropTargetKey: null,
|
|
1102
1186
|
dropPosition: null,
|
|
1103
1187
|
dragKey: null
|
|
@@ -1263,10 +1347,10 @@ function Tree({
|
|
|
1263
1347
|
}
|
|
1264
1348
|
|
|
1265
1349
|
// src/components/Tree/OrphanDialog.tsx
|
|
1266
|
-
import { useState as
|
|
1350
|
+
import { useState as useState9 } from "react";
|
|
1267
1351
|
import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1268
1352
|
function OrphanDialog({ orphans, onResolve, onClose }) {
|
|
1269
|
-
const [resolutions, setResolutions] =
|
|
1353
|
+
const [resolutions, setResolutions] = useState9(
|
|
1270
1354
|
() => Object.fromEntries(orphans.map((o) => [o.key, "lift"]))
|
|
1271
1355
|
);
|
|
1272
1356
|
if (orphans.length === 0) return null;
|
|
@@ -1330,7 +1414,7 @@ function OrphanDialog({ orphans, onResolve, onClose }) {
|
|
|
1330
1414
|
}
|
|
1331
1415
|
|
|
1332
1416
|
// src/components/Avatar/Avatar.tsx
|
|
1333
|
-
import { useState as
|
|
1417
|
+
import { useState as useState10, useMemo as useMemo3, useCallback as useCallback5, forwardRef as forwardRef2, useEffect as useEffect5 } from "react";
|
|
1334
1418
|
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
1335
1419
|
var SIZE_MAP = {
|
|
1336
1420
|
xs: 20,
|
|
@@ -1365,8 +1449,8 @@ var useAvatarStyles = (size, shape, bordered, onClick, loadState, src, children,
|
|
|
1365
1449
|
return { classes, style };
|
|
1366
1450
|
};
|
|
1367
1451
|
var useImageLoader = (src, fallbackSrc, onImageLoad, onImageError, onStateChange) => {
|
|
1368
|
-
const [loadState, setLoadState] =
|
|
1369
|
-
const [currentSrc, setCurrentSrc] =
|
|
1452
|
+
const [loadState, setLoadState] = useState10("idle");
|
|
1453
|
+
const [currentSrc, setCurrentSrc] = useState10(src);
|
|
1370
1454
|
useEffect5(() => {
|
|
1371
1455
|
setCurrentSrc(src);
|
|
1372
1456
|
setLoadState(src ? "loading" : "idle");
|
|
@@ -1579,8 +1663,10 @@ var ListGroup = forwardRef3(
|
|
|
1579
1663
|
ListGroup.displayName = "ListGroup";
|
|
1580
1664
|
|
|
1581
1665
|
// src/components/VirtualList/VirtualList.tsx
|
|
1582
|
-
import { useState as
|
|
1666
|
+
import { useState as useState11, useRef as useRef5, useCallback as useCallback7, useMemo as useMemo5, memo as memo3 } from "react";
|
|
1583
1667
|
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
1668
|
+
var VirtualItem = memo3(({ children, height }) => /* @__PURE__ */ jsx14("div", { className: "fc-virtual-list__item", style: { height: `${height}px` }, children }));
|
|
1669
|
+
VirtualItem.displayName = "VirtualItem";
|
|
1584
1670
|
function VirtualList({
|
|
1585
1671
|
data,
|
|
1586
1672
|
height,
|
|
@@ -1593,7 +1679,7 @@ function VirtualList({
|
|
|
1593
1679
|
style
|
|
1594
1680
|
}) {
|
|
1595
1681
|
const containerRef = useRef5(null);
|
|
1596
|
-
const [scrollTop, setScrollTop] =
|
|
1682
|
+
const [scrollTop, setScrollTop] = useState11(0);
|
|
1597
1683
|
const totalHeight = data.length * itemHeight;
|
|
1598
1684
|
const handleScroll = useCallback7((e) => {
|
|
1599
1685
|
const newScrollTop = e.currentTarget.scrollTop;
|
|
@@ -1618,11 +1704,6 @@ function VirtualList({
|
|
|
1618
1704
|
return data.slice(visibleRange.startIndex, visibleRange.endIndex);
|
|
1619
1705
|
}, [data, visibleRange]);
|
|
1620
1706
|
const offsetY = visibleRange.startIndex * itemHeight;
|
|
1621
|
-
useEffect6(() => {
|
|
1622
|
-
if (!showScrollbar && containerRef.current) {
|
|
1623
|
-
containerRef.current.style.scrollbarWidth = "none";
|
|
1624
|
-
}
|
|
1625
|
-
}, [showScrollbar]);
|
|
1626
1707
|
const classNames = [
|
|
1627
1708
|
"fc-virtual-list",
|
|
1628
1709
|
!showScrollbar && "fc-virtual-list--hide-scrollbar",
|
|
@@ -1647,15 +1728,7 @@ function VirtualList({
|
|
|
1647
1728
|
style: { transform: `translateY(${offsetY}px)` },
|
|
1648
1729
|
children: visibleData.map((item, idx) => {
|
|
1649
1730
|
const actualIndex = visibleRange.startIndex + idx;
|
|
1650
|
-
return /* @__PURE__ */ jsx14(
|
|
1651
|
-
"div",
|
|
1652
|
-
{
|
|
1653
|
-
className: "fc-virtual-list__item",
|
|
1654
|
-
style: { height: `${itemHeight}px` },
|
|
1655
|
-
children: renderItem(item, actualIndex)
|
|
1656
|
-
},
|
|
1657
|
-
actualIndex
|
|
1658
|
-
);
|
|
1731
|
+
return /* @__PURE__ */ jsx14(VirtualItem, { height: itemHeight, children: renderItem(item, actualIndex) }, actualIndex);
|
|
1659
1732
|
})
|
|
1660
1733
|
}
|
|
1661
1734
|
)
|
|
@@ -1666,7 +1739,7 @@ function VirtualList({
|
|
|
1666
1739
|
}
|
|
1667
1740
|
|
|
1668
1741
|
// src/components/Alert/AlertContext.tsx
|
|
1669
|
-
import { createContext as createContext3, useContext as useContext3, useState as
|
|
1742
|
+
import { createContext as createContext3, useContext as useContext3, useEffect as useEffect6, useState as useState12 } from "react";
|
|
1670
1743
|
import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1671
1744
|
var AlertContext = createContext3(null);
|
|
1672
1745
|
var ICONS = {
|
|
@@ -1742,55 +1815,72 @@ var ICONS = {
|
|
|
1742
1815
|
}
|
|
1743
1816
|
)
|
|
1744
1817
|
};
|
|
1745
|
-
function AlertProvider({ children }) {
|
|
1746
|
-
const [
|
|
1818
|
+
function AlertProvider({ children, background, borderColor }) {
|
|
1819
|
+
const [alert, setAlert] = useState12({
|
|
1747
1820
|
msg: "",
|
|
1748
1821
|
type: "info",
|
|
1822
|
+
mode: "alert",
|
|
1749
1823
|
visible: false,
|
|
1750
1824
|
choice: () => {
|
|
1751
1825
|
}
|
|
1752
1826
|
});
|
|
1753
|
-
const showAlert = (msg, type,
|
|
1754
|
-
|
|
1827
|
+
const showAlert = (msg, type, mode = "alert", duration) => new Promise((resolve) => {
|
|
1828
|
+
setAlert({
|
|
1755
1829
|
msg,
|
|
1756
1830
|
type,
|
|
1831
|
+
mode,
|
|
1757
1832
|
visible: true,
|
|
1758
|
-
|
|
1833
|
+
duration,
|
|
1759
1834
|
choice: (res) => {
|
|
1760
|
-
|
|
1835
|
+
setAlert((p) => ({ ...p, visible: false }));
|
|
1761
1836
|
resolve(res);
|
|
1762
1837
|
}
|
|
1763
1838
|
});
|
|
1764
1839
|
});
|
|
1840
|
+
useEffect6(() => {
|
|
1841
|
+
if (!alert.visible || !alert.duration) return;
|
|
1842
|
+
const timer = setTimeout(() => alert.choice("auto"), alert.duration);
|
|
1843
|
+
return () => clearTimeout(timer);
|
|
1844
|
+
}, [alert.visible, alert.duration]);
|
|
1845
|
+
const overrideStyle = {};
|
|
1846
|
+
if (background !== void 0) overrideStyle["--alert-bg"] = background;
|
|
1847
|
+
if (borderColor !== void 0) overrideStyle["--alert-border"] = borderColor;
|
|
1765
1848
|
return /* @__PURE__ */ jsxs10(AlertContext.Provider, { value: { showAlert }, children: [
|
|
1766
1849
|
children,
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1850
|
+
alert.visible && /* @__PURE__ */ jsx15("div", { className: "fc-alert-overlay", children: /* @__PURE__ */ jsxs10(
|
|
1851
|
+
"div",
|
|
1852
|
+
{
|
|
1853
|
+
className: `fc-alert fc-alert--${alert.type} fc-alert--${alert.mode}`,
|
|
1854
|
+
style: overrideStyle,
|
|
1855
|
+
children: [
|
|
1856
|
+
/* @__PURE__ */ jsxs10("div", { className: "fc-alert__header", children: [
|
|
1857
|
+
ICONS[alert.type],
|
|
1858
|
+
/* @__PURE__ */ jsx15("span", { className: "fc-alert__title", children: "\u63D0\u793A" })
|
|
1859
|
+
] }),
|
|
1860
|
+
/* @__PURE__ */ jsx15(RollingBox, { className: "fc-alert__msg", children: alert.msg }),
|
|
1861
|
+
alert.mode !== "toast" && /* @__PURE__ */ jsxs10("div", { className: "fc-alert__footer", children: [
|
|
1862
|
+
alert.mode === "confirm" && /* @__PURE__ */ jsx15(
|
|
1863
|
+
Button,
|
|
1864
|
+
{
|
|
1865
|
+
variant: "secondary",
|
|
1866
|
+
size: "sm",
|
|
1867
|
+
onClick: () => alert.choice("no"),
|
|
1868
|
+
children: "\u53D6\u6D88"
|
|
1869
|
+
}
|
|
1870
|
+
),
|
|
1871
|
+
/* @__PURE__ */ jsx15(
|
|
1872
|
+
Button,
|
|
1873
|
+
{
|
|
1874
|
+
variant: "primary",
|
|
1875
|
+
size: "sm",
|
|
1876
|
+
onClick: () => alert.choice("yes"),
|
|
1877
|
+
children: "\u786E\u5B9A"
|
|
1878
|
+
}
|
|
1879
|
+
)
|
|
1880
|
+
] })
|
|
1881
|
+
]
|
|
1882
|
+
}
|
|
1883
|
+
) })
|
|
1794
1884
|
] });
|
|
1795
1885
|
}
|
|
1796
1886
|
var useAlert = () => useContext3(AlertContext);
|
|
@@ -1882,344 +1972,779 @@ var Card = ({
|
|
|
1882
1972
|
] });
|
|
1883
1973
|
};
|
|
1884
1974
|
|
|
1885
|
-
// src/components/
|
|
1886
|
-
import {
|
|
1975
|
+
// src/components/Bar/TabBar.tsx
|
|
1976
|
+
import { useRef as useRef6, useCallback as useCallback8, memo as memo4 } from "react";
|
|
1887
1977
|
import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1888
|
-
var
|
|
1978
|
+
var TabItemView = memo4(({
|
|
1979
|
+
item,
|
|
1980
|
+
isActive,
|
|
1981
|
+
closable,
|
|
1982
|
+
draggable,
|
|
1983
|
+
tabClassName,
|
|
1984
|
+
activeTabClassName,
|
|
1985
|
+
tabStyle,
|
|
1986
|
+
activeTabStyle,
|
|
1987
|
+
renderCloseIcon,
|
|
1988
|
+
onClick,
|
|
1989
|
+
onClose,
|
|
1990
|
+
onDragStart,
|
|
1991
|
+
onDragOver,
|
|
1992
|
+
onDrop,
|
|
1993
|
+
onDragEnd
|
|
1994
|
+
}) => {
|
|
1995
|
+
const showClose = item.closable !== void 0 ? item.closable : closable;
|
|
1996
|
+
const classes = [
|
|
1997
|
+
"fc-tab-bar__tab",
|
|
1998
|
+
isActive && "fc-tab-bar__tab--active",
|
|
1999
|
+
item.disabled && "fc-tab-bar__tab--disabled",
|
|
2000
|
+
draggable && !item.disabled && "fc-tab-bar__tab--draggable",
|
|
2001
|
+
tabClassName,
|
|
2002
|
+
isActive && activeTabClassName
|
|
2003
|
+
].filter(Boolean).join(" ");
|
|
2004
|
+
const mergedStyle = {
|
|
2005
|
+
...tabStyle,
|
|
2006
|
+
...isActive ? activeTabStyle : void 0
|
|
2007
|
+
};
|
|
2008
|
+
return /* @__PURE__ */ jsxs13(
|
|
2009
|
+
"div",
|
|
2010
|
+
{
|
|
2011
|
+
className: classes,
|
|
2012
|
+
style: mergedStyle,
|
|
2013
|
+
onClick: () => !item.disabled && onClick(item.key),
|
|
2014
|
+
draggable: draggable && !item.disabled,
|
|
2015
|
+
onDragStart: (e) => onDragStart(e, item.key),
|
|
2016
|
+
onDragOver,
|
|
2017
|
+
onDrop: (e) => onDrop(e, item.key),
|
|
2018
|
+
onDragEnd,
|
|
2019
|
+
role: "tab",
|
|
2020
|
+
"aria-selected": isActive,
|
|
2021
|
+
"aria-disabled": item.disabled,
|
|
2022
|
+
tabIndex: item.disabled ? -1 : 0,
|
|
2023
|
+
children: [
|
|
2024
|
+
/* @__PURE__ */ jsx18("span", { className: "fc-tab-bar__tab-label", children: item.label }),
|
|
2025
|
+
showClose && !item.disabled && /* @__PURE__ */ jsx18(
|
|
2026
|
+
"span",
|
|
2027
|
+
{
|
|
2028
|
+
className: "fc-tab-bar__tab-close",
|
|
2029
|
+
onClick: (e) => onClose(e, item.key),
|
|
2030
|
+
role: "button",
|
|
2031
|
+
"aria-label": `\u5173\u95ED ${typeof item.label === "string" ? item.label : ""}`,
|
|
2032
|
+
children: renderCloseIcon ? renderCloseIcon(item.key) : "\xD7"
|
|
2033
|
+
}
|
|
2034
|
+
)
|
|
2035
|
+
]
|
|
2036
|
+
}
|
|
2037
|
+
);
|
|
2038
|
+
});
|
|
2039
|
+
TabItemView.displayName = "TabItemView";
|
|
2040
|
+
var TabBar = memo4(({
|
|
1889
2041
|
items,
|
|
1890
|
-
activeKey
|
|
1891
|
-
|
|
2042
|
+
activeKey,
|
|
2043
|
+
variant = "attached",
|
|
1892
2044
|
radius = "md",
|
|
2045
|
+
tabRadius,
|
|
1893
2046
|
closable = false,
|
|
1894
2047
|
addable = false,
|
|
2048
|
+
draggable = false,
|
|
1895
2049
|
onChange,
|
|
1896
2050
|
onClose,
|
|
1897
2051
|
onAdd,
|
|
2052
|
+
onReorder,
|
|
2053
|
+
tabClassName,
|
|
2054
|
+
activeTabClassName,
|
|
2055
|
+
tabStyle,
|
|
2056
|
+
activeTabStyle,
|
|
2057
|
+
renderCloseIcon,
|
|
2058
|
+
renderAddButton,
|
|
1898
2059
|
className = "",
|
|
1899
|
-
style
|
|
2060
|
+
style,
|
|
2061
|
+
background,
|
|
2062
|
+
tabColor,
|
|
2063
|
+
tabHoverColor,
|
|
2064
|
+
tabHoverBackground,
|
|
2065
|
+
tabActiveColor,
|
|
2066
|
+
tabActiveBackground,
|
|
2067
|
+
activeIndicatorColor
|
|
1900
2068
|
}) => {
|
|
1901
|
-
const
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
}
|
|
1910
|
-
onChange?.(key);
|
|
2069
|
+
const colorVars = {
|
|
2070
|
+
"--tab-bar-bg": background,
|
|
2071
|
+
"--tab-color": tabColor,
|
|
2072
|
+
"--tab-hover-color": tabHoverColor,
|
|
2073
|
+
"--tab-hover-bg": tabHoverBackground,
|
|
2074
|
+
"--tab-active-color": tabActiveColor,
|
|
2075
|
+
"--tab-active-bg": tabActiveBackground,
|
|
2076
|
+
"--tab-active-indicator": activeIndicatorColor
|
|
1911
2077
|
};
|
|
1912
|
-
const
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
const currentIndex = items.findIndex((item) => item.key === key);
|
|
1917
|
-
const nextItem = items[currentIndex + 1] || items[currentIndex - 1];
|
|
1918
|
-
if (nextItem && !nextItem.disabled) {
|
|
1919
|
-
handleTabClick(nextItem.key);
|
|
1920
|
-
}
|
|
2078
|
+
const overrideStyle = {};
|
|
2079
|
+
for (const [key, value] of Object.entries(colorVars)) {
|
|
2080
|
+
if (value !== void 0) {
|
|
2081
|
+
overrideStyle[key] = value;
|
|
1921
2082
|
}
|
|
1922
|
-
}
|
|
1923
|
-
const
|
|
1924
|
-
|
|
1925
|
-
|
|
2083
|
+
}
|
|
2084
|
+
const mergedStyle = { ...overrideStyle, ...style };
|
|
2085
|
+
const dragKeyRef = useRef6(null);
|
|
2086
|
+
const handleClick = useCallback8(
|
|
2087
|
+
(key) => onChange(key),
|
|
2088
|
+
[onChange]
|
|
2089
|
+
);
|
|
2090
|
+
const handleClose = useCallback8(
|
|
2091
|
+
(e, key) => {
|
|
2092
|
+
e.stopPropagation();
|
|
2093
|
+
onClose?.(key);
|
|
2094
|
+
},
|
|
2095
|
+
[onClose]
|
|
2096
|
+
);
|
|
2097
|
+
const handleDragStart = useCallback8(
|
|
2098
|
+
(e, key) => {
|
|
2099
|
+
dragKeyRef.current = key;
|
|
2100
|
+
e.dataTransfer.effectAllowed = "move";
|
|
2101
|
+
const target = e.currentTarget;
|
|
2102
|
+
requestAnimationFrame(() => target.classList.add("fc-tab-bar__tab--dragging"));
|
|
2103
|
+
},
|
|
2104
|
+
[]
|
|
2105
|
+
);
|
|
2106
|
+
const handleDragOver = useCallback8((e) => {
|
|
2107
|
+
e.preventDefault();
|
|
2108
|
+
e.dataTransfer.dropEffect = "move";
|
|
2109
|
+
}, []);
|
|
2110
|
+
const handleDrop = useCallback8(
|
|
2111
|
+
(e, targetKey) => {
|
|
2112
|
+
e.preventDefault();
|
|
2113
|
+
const dragKey = dragKeyRef.current;
|
|
2114
|
+
if (!dragKey || dragKey === targetKey || !onReorder) return;
|
|
2115
|
+
const fromIndex = items.findIndex((i) => i.key === dragKey);
|
|
2116
|
+
const toIndex = items.findIndex((i) => i.key === targetKey);
|
|
2117
|
+
if (fromIndex === -1 || toIndex === -1) return;
|
|
2118
|
+
const reordered = [...items];
|
|
2119
|
+
const [moved] = reordered.splice(fromIndex, 1);
|
|
2120
|
+
reordered.splice(toIndex, 0, moved);
|
|
2121
|
+
onReorder(reordered);
|
|
2122
|
+
},
|
|
2123
|
+
[items, onReorder]
|
|
2124
|
+
);
|
|
2125
|
+
const handleDragEnd = useCallback8((e) => {
|
|
2126
|
+
dragKeyRef.current = null;
|
|
2127
|
+
e.currentTarget.classList.remove("fc-tab-bar__tab--dragging");
|
|
2128
|
+
}, []);
|
|
2129
|
+
const rootClasses = [
|
|
2130
|
+
"fc-tab-bar",
|
|
2131
|
+
`fc-tab-bar--${variant}`,
|
|
2132
|
+
`fc-tab-bar--radius-${radius}`,
|
|
2133
|
+
tabRadius && `fc-tab-bar--tab-radius-${tabRadius}`,
|
|
1926
2134
|
className
|
|
1927
2135
|
].filter(Boolean).join(" ");
|
|
1928
|
-
return /* @__PURE__ */
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
2136
|
+
return /* @__PURE__ */ jsx18("div", { className: rootClasses, style: mergedStyle, role: "tablist", children: /* @__PURE__ */ jsx18("div", { className: "fc-tab-bar__nav", children: /* @__PURE__ */ jsxs13("div", { className: "fc-tab-bar__nav-wrap", children: [
|
|
2137
|
+
items.map((item) => /* @__PURE__ */ jsx18(
|
|
2138
|
+
TabItemView,
|
|
2139
|
+
{
|
|
2140
|
+
item,
|
|
2141
|
+
isActive: activeKey === item.key,
|
|
2142
|
+
closable,
|
|
2143
|
+
draggable,
|
|
2144
|
+
tabClassName,
|
|
2145
|
+
activeTabClassName,
|
|
2146
|
+
tabStyle,
|
|
2147
|
+
activeTabStyle,
|
|
2148
|
+
renderCloseIcon,
|
|
2149
|
+
onClick: handleClick,
|
|
2150
|
+
onClose: handleClose,
|
|
2151
|
+
onDragStart: handleDragStart,
|
|
2152
|
+
onDragOver: handleDragOver,
|
|
2153
|
+
onDrop: handleDrop,
|
|
2154
|
+
onDragEnd: handleDragEnd
|
|
2155
|
+
},
|
|
2156
|
+
item.key
|
|
2157
|
+
)),
|
|
2158
|
+
addable && /* @__PURE__ */ jsx18(
|
|
2159
|
+
"div",
|
|
2160
|
+
{
|
|
2161
|
+
className: "fc-tab-bar__add-btn",
|
|
2162
|
+
onClick: onAdd,
|
|
2163
|
+
role: "button",
|
|
2164
|
+
"aria-label": "\u6DFB\u52A0\u6807\u7B7E",
|
|
2165
|
+
children: renderAddButton ? renderAddButton() : "+"
|
|
2166
|
+
}
|
|
2167
|
+
)
|
|
2168
|
+
] }) }) });
|
|
2169
|
+
});
|
|
2170
|
+
TabBar.displayName = "TabBar";
|
|
1957
2171
|
|
|
1958
|
-
// src/components/
|
|
1959
|
-
import {
|
|
2172
|
+
// src/components/Tag/TagItem.tsx
|
|
2173
|
+
import { useEffect as useEffect7, useRef as useRef7, useState as useState13 } from "react";
|
|
1960
2174
|
import { Fragment as Fragment3, jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
assistantName = "AI\u52A9\u624B",
|
|
1974
|
-
onTyping,
|
|
1975
|
-
maxInputLength = 2e3,
|
|
1976
|
-
autoFocus = true,
|
|
1977
|
-
enableCopy = true
|
|
1978
|
-
}) => {
|
|
1979
|
-
const [inputValue, setInputValue] = useState15("");
|
|
1980
|
-
const [isTyping, setIsTyping] = useState15(false);
|
|
1981
|
-
const [isSending, setIsSending] = useState15(false);
|
|
1982
|
-
const [currentTheme, setCurrentTheme] = useState15("light");
|
|
1983
|
-
const [copiedMessageId, setCopiedMessageId] = useState15(null);
|
|
1984
|
-
const [copyError, setCopyError] = useState15(null);
|
|
1985
|
-
const messagesEndRef = useRef6(null);
|
|
1986
|
-
const inputRef = useRef6(null);
|
|
2175
|
+
function TagItem({
|
|
2176
|
+
schema,
|
|
2177
|
+
value,
|
|
2178
|
+
onChange,
|
|
2179
|
+
mode = "show",
|
|
2180
|
+
background,
|
|
2181
|
+
color,
|
|
2182
|
+
borderColor
|
|
2183
|
+
}) {
|
|
2184
|
+
const [editing, setEditing] = useState13(false);
|
|
2185
|
+
const [draft, setDraft] = useState13(() => value !== void 0 ? String(value) : "");
|
|
2186
|
+
const inputRef = useRef7(null);
|
|
1987
2187
|
useEffect7(() => {
|
|
1988
|
-
if (
|
|
1989
|
-
|
|
2188
|
+
if (!editing) setDraft(value !== void 0 ? String(value) : "");
|
|
2189
|
+
}, [value, editing]);
|
|
2190
|
+
const colorVars = {
|
|
2191
|
+
"--tag-bg": background,
|
|
2192
|
+
"--tag-color": color,
|
|
2193
|
+
"--tag-border": borderColor
|
|
2194
|
+
};
|
|
2195
|
+
const overrideStyle = {};
|
|
2196
|
+
for (const [k, v] of Object.entries(colorVars)) {
|
|
2197
|
+
if (v !== void 0) overrideStyle[k] = v;
|
|
2198
|
+
}
|
|
2199
|
+
if (schema.type === "boolean") {
|
|
2200
|
+
const boolVal = value === true || value === "true";
|
|
2201
|
+
return /* @__PURE__ */ jsxs14(
|
|
2202
|
+
"span",
|
|
2203
|
+
{
|
|
2204
|
+
className: "fc-tag-item fc-tag-item--boolean",
|
|
2205
|
+
style: overrideStyle,
|
|
2206
|
+
onClick: () => onChange?.(!boolVal),
|
|
2207
|
+
title: "\u70B9\u51FB\u5207\u6362",
|
|
2208
|
+
children: [
|
|
2209
|
+
/* @__PURE__ */ jsx19("span", { className: "fc-tag-item__name", children: schema.name }),
|
|
2210
|
+
/* @__PURE__ */ jsx19("span", { className: "fc-tag-item__sep", children: "\xB7" }),
|
|
2211
|
+
/* @__PURE__ */ jsx19("span", { className: boolVal ? "fc-tag-item__bool-true" : "fc-tag-item__bool-false", children: boolVal ? "\u2713" : "\u2717" })
|
|
2212
|
+
]
|
|
2213
|
+
}
|
|
2214
|
+
);
|
|
2215
|
+
}
|
|
2216
|
+
const commit = () => {
|
|
2217
|
+
if (schema.type === "number") {
|
|
2218
|
+
const n = parseFloat(draft);
|
|
2219
|
+
if (!isNaN(n)) {
|
|
2220
|
+
const clamped = schema.range_min != null && n < schema.range_min ? schema.range_min : schema.range_max != null && n > schema.range_max ? schema.range_max : n;
|
|
2221
|
+
onChange?.(clamped);
|
|
2222
|
+
}
|
|
1990
2223
|
} else {
|
|
1991
|
-
|
|
1992
|
-
const dataTheme = document.documentElement.getAttribute("data-theme");
|
|
1993
|
-
if (dataTheme === "dark") {
|
|
1994
|
-
setCurrentTheme("dark");
|
|
1995
|
-
} else if (dataTheme === "light") {
|
|
1996
|
-
setCurrentTheme("light");
|
|
1997
|
-
} else {
|
|
1998
|
-
const hasDarkClass = document.documentElement.classList.contains("dark") || document.body.classList.contains("dark") || document.documentElement.classList.contains("theme-dark") || document.body.classList.contains("theme-dark");
|
|
1999
|
-
setCurrentTheme(hasDarkClass ? "dark" : "light");
|
|
2000
|
-
}
|
|
2001
|
-
};
|
|
2002
|
-
checkTheme();
|
|
2003
|
-
const observer = new MutationObserver(checkTheme);
|
|
2004
|
-
observer.observe(document.documentElement, {
|
|
2005
|
-
attributes: true,
|
|
2006
|
-
attributeFilter: ["data-theme", "class"]
|
|
2007
|
-
});
|
|
2008
|
-
observer.observe(document.body, {
|
|
2009
|
-
attributes: true,
|
|
2010
|
-
attributeFilter: ["class"]
|
|
2011
|
-
});
|
|
2012
|
-
return () => observer.disconnect();
|
|
2013
|
-
}
|
|
2014
|
-
}, [propTheme]);
|
|
2015
|
-
useEffect7(() => {
|
|
2016
|
-
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
2017
|
-
}, [messages, loading]);
|
|
2018
|
-
useEffect7(() => {
|
|
2019
|
-
if (autoFocus && !disabled && inputRef.current) {
|
|
2020
|
-
inputRef.current.focus();
|
|
2224
|
+
onChange?.(draft);
|
|
2021
2225
|
}
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2226
|
+
if (mode === "show") setEditing(false);
|
|
2227
|
+
};
|
|
2228
|
+
const cancel = () => {
|
|
2229
|
+
setDraft(value !== void 0 ? String(value) : "");
|
|
2230
|
+
if (mode === "show") setEditing(false);
|
|
2231
|
+
};
|
|
2232
|
+
const isEditing = mode === "edit" || editing;
|
|
2233
|
+
if (isEditing) {
|
|
2234
|
+
return /* @__PURE__ */ jsxs14("span", { className: "fc-tag-item fc-tag-item--editing", style: overrideStyle, children: [
|
|
2235
|
+
/* @__PURE__ */ jsx19("span", { className: "fc-tag-item__name", children: schema.name }),
|
|
2236
|
+
/* @__PURE__ */ jsx19("span", { className: "fc-tag-item__sep", children: "\xB7" }),
|
|
2237
|
+
/* @__PURE__ */ jsx19(
|
|
2238
|
+
"input",
|
|
2239
|
+
{
|
|
2240
|
+
ref: inputRef,
|
|
2241
|
+
className: "fc-tag-item__input",
|
|
2242
|
+
type: schema.type === "number" ? "number" : "text",
|
|
2243
|
+
value: draft,
|
|
2244
|
+
min: schema.range_min ?? void 0,
|
|
2245
|
+
max: schema.range_max ?? void 0,
|
|
2246
|
+
autoFocus: true,
|
|
2247
|
+
onChange: (e) => setDraft(e.target.value),
|
|
2248
|
+
onBlur: commit,
|
|
2249
|
+
onKeyDown: (e) => {
|
|
2250
|
+
if (e.key === "Enter") {
|
|
2251
|
+
e.preventDefault();
|
|
2252
|
+
commit();
|
|
2253
|
+
}
|
|
2254
|
+
if (e.key === "Escape") {
|
|
2255
|
+
e.preventDefault();
|
|
2256
|
+
cancel();
|
|
2257
|
+
}
|
|
2258
|
+
}
|
|
2259
|
+
}
|
|
2260
|
+
)
|
|
2261
|
+
] });
|
|
2262
|
+
}
|
|
2263
|
+
return /* @__PURE__ */ jsxs14(
|
|
2264
|
+
"span",
|
|
2265
|
+
{
|
|
2266
|
+
className: "fc-tag-item fc-tag-item--show",
|
|
2267
|
+
style: overrideStyle,
|
|
2268
|
+
onDoubleClick: () => {
|
|
2269
|
+
setDraft(value !== void 0 ? String(value) : "");
|
|
2270
|
+
setEditing(true);
|
|
2271
|
+
setTimeout(() => inputRef.current?.select(), 0);
|
|
2272
|
+
},
|
|
2273
|
+
title: "\u53CC\u51FB\u7F16\u8F91",
|
|
2274
|
+
children: [
|
|
2275
|
+
/* @__PURE__ */ jsx19("span", { className: "fc-tag-item__name", children: schema.name }),
|
|
2276
|
+
value !== void 0 && /* @__PURE__ */ jsxs14(Fragment3, { children: [
|
|
2277
|
+
/* @__PURE__ */ jsx19("span", { className: "fc-tag-item__sep", children: "\xB7" }),
|
|
2278
|
+
/* @__PURE__ */ jsx19("span", { className: "fc-tag-item__value", children: String(value) })
|
|
2279
|
+
] })
|
|
2280
|
+
]
|
|
2029
2281
|
}
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2282
|
+
);
|
|
2283
|
+
}
|
|
2284
|
+
|
|
2285
|
+
// src/components/MarkdownEditor/MarkdownEditor.tsx
|
|
2286
|
+
import MDEditor, { commands } from "@uiw/react-md-editor";
|
|
2287
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
2288
|
+
var TOOLBAR_COMMANDS = [
|
|
2289
|
+
commands.bold,
|
|
2290
|
+
commands.italic,
|
|
2291
|
+
commands.strikethrough,
|
|
2292
|
+
commands.divider,
|
|
2293
|
+
commands.title1,
|
|
2294
|
+
commands.title2,
|
|
2295
|
+
commands.title3,
|
|
2296
|
+
commands.divider,
|
|
2297
|
+
commands.quote,
|
|
2298
|
+
commands.code,
|
|
2299
|
+
commands.codeBlock,
|
|
2300
|
+
commands.divider,
|
|
2301
|
+
commands.link,
|
|
2302
|
+
commands.unorderedListCommand,
|
|
2303
|
+
commands.orderedListCommand,
|
|
2304
|
+
commands.hr
|
|
2305
|
+
];
|
|
2306
|
+
function MarkdownEditor({
|
|
2307
|
+
value,
|
|
2308
|
+
onChange,
|
|
2309
|
+
onAiComplete,
|
|
2310
|
+
minHeight = 200,
|
|
2311
|
+
placeholder = "\u5728\u6B64\u8F93\u5165\u5185\u5BB9...",
|
|
2312
|
+
background,
|
|
2313
|
+
toolbarBackground,
|
|
2314
|
+
borderColor
|
|
2315
|
+
}) {
|
|
2316
|
+
const { resolvedTheme } = useTheme();
|
|
2317
|
+
const colorVars = {
|
|
2318
|
+
"--md-bg": background,
|
|
2319
|
+
"--md-toolbar-bg": toolbarBackground,
|
|
2320
|
+
"--md-border": borderColor
|
|
2321
|
+
};
|
|
2322
|
+
const overrideStyle = {};
|
|
2323
|
+
for (const [k, v] of Object.entries(colorVars)) {
|
|
2324
|
+
if (v !== void 0) overrideStyle[k] = v;
|
|
2325
|
+
}
|
|
2326
|
+
const aiCommand = {
|
|
2327
|
+
name: "ai-complete",
|
|
2328
|
+
keyCommand: "ai-complete",
|
|
2329
|
+
buttonProps: { "aria-label": "AI \u8865\u5168", className: "fc-md-ai-btn" },
|
|
2330
|
+
icon: /* @__PURE__ */ jsx20("span", { children: "AI \u8865\u5168" }),
|
|
2331
|
+
execute: () => onAiComplete?.()
|
|
2332
|
+
};
|
|
2333
|
+
const extraCommands = onAiComplete ? [commands.divider, aiCommand, commands.fullscreen] : [commands.fullscreen];
|
|
2334
|
+
return /* @__PURE__ */ jsx20(
|
|
2335
|
+
"div",
|
|
2336
|
+
{
|
|
2337
|
+
className: "fc-md-wrap",
|
|
2338
|
+
style: overrideStyle,
|
|
2339
|
+
"data-color-mode": resolvedTheme,
|
|
2340
|
+
children: /* @__PURE__ */ jsx20(
|
|
2341
|
+
MDEditor,
|
|
2342
|
+
{
|
|
2343
|
+
value,
|
|
2344
|
+
onChange: (v) => onChange(v ?? ""),
|
|
2345
|
+
commands: TOOLBAR_COMMANDS,
|
|
2346
|
+
extraCommands,
|
|
2347
|
+
height: minHeight,
|
|
2348
|
+
preview: "edit",
|
|
2349
|
+
visibleDragbar: false,
|
|
2350
|
+
textareaProps: { placeholder }
|
|
2351
|
+
}
|
|
2352
|
+
)
|
|
2035
2353
|
}
|
|
2354
|
+
);
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2357
|
+
// src/components/ContextMenu/ContextMenuContext.tsx
|
|
2358
|
+
import { createContext as createContext4, useContext as useContext4, useEffect as useEffect8, useRef as useRef8, useState as useState14 } from "react";
|
|
2359
|
+
import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2360
|
+
var ContextMenuContext = createContext4(null);
|
|
2361
|
+
function ContextMenuProvider({
|
|
2362
|
+
children,
|
|
2363
|
+
background,
|
|
2364
|
+
borderColor,
|
|
2365
|
+
hoverBackground
|
|
2366
|
+
}) {
|
|
2367
|
+
const [menu, setMenu] = useState14({
|
|
2368
|
+
visible: false,
|
|
2369
|
+
x: 0,
|
|
2370
|
+
y: 0,
|
|
2371
|
+
items: []
|
|
2372
|
+
});
|
|
2373
|
+
const menuRef = useRef8(null);
|
|
2374
|
+
const showContextMenu = (e, items) => {
|
|
2375
|
+
e.preventDefault();
|
|
2376
|
+
e.stopPropagation();
|
|
2377
|
+
setMenu({ visible: true, x: e.clientX, y: e.clientY, items });
|
|
2378
|
+
};
|
|
2379
|
+
const hide = () => setMenu((s) => ({ ...s, visible: false }));
|
|
2380
|
+
useEffect8(() => {
|
|
2381
|
+
if (!menu.visible) return;
|
|
2382
|
+
const onPointerDown = (e) => {
|
|
2383
|
+
if (menuRef.current && !menuRef.current.contains(e.target)) hide();
|
|
2384
|
+
};
|
|
2385
|
+
const onKeyDown = (e) => {
|
|
2386
|
+
if (e.key === "Escape") hide();
|
|
2387
|
+
};
|
|
2388
|
+
window.addEventListener("pointerdown", onPointerDown);
|
|
2389
|
+
window.addEventListener("keydown", onKeyDown);
|
|
2390
|
+
return () => {
|
|
2391
|
+
window.removeEventListener("pointerdown", onPointerDown);
|
|
2392
|
+
window.removeEventListener("keydown", onKeyDown);
|
|
2393
|
+
};
|
|
2394
|
+
}, [menu.visible]);
|
|
2395
|
+
const getPosition = () => {
|
|
2396
|
+
const W = window.innerWidth;
|
|
2397
|
+
const H = window.innerHeight;
|
|
2398
|
+
const menuW = 180;
|
|
2399
|
+
const menuH = menu.items.length * 32 + 12;
|
|
2400
|
+
return {
|
|
2401
|
+
left: menu.x + menuW > W ? menu.x - menuW : menu.x,
|
|
2402
|
+
top: menu.y + menuH > H ? menu.y - menuH : menu.y
|
|
2403
|
+
};
|
|
2404
|
+
};
|
|
2405
|
+
const colorVars = {
|
|
2406
|
+
"--ctx-bg": background,
|
|
2407
|
+
"--ctx-border": borderColor,
|
|
2408
|
+
"--ctx-item-hover-bg": hoverBackground
|
|
2409
|
+
};
|
|
2410
|
+
const overrideStyle = { ...getPosition() };
|
|
2411
|
+
for (const [k, v] of Object.entries(colorVars)) {
|
|
2412
|
+
if (v !== void 0) overrideStyle[k] = v;
|
|
2413
|
+
}
|
|
2414
|
+
return /* @__PURE__ */ jsxs15(ContextMenuContext.Provider, { value: { showContextMenu }, children: [
|
|
2415
|
+
children,
|
|
2416
|
+
menu.visible && /* @__PURE__ */ jsx21(
|
|
2417
|
+
"ul",
|
|
2418
|
+
{
|
|
2419
|
+
ref: menuRef,
|
|
2420
|
+
className: "fc-context-menu",
|
|
2421
|
+
style: overrideStyle,
|
|
2422
|
+
children: menu.items.map((item, i) => {
|
|
2423
|
+
if ("type" in item && item.type === "divider") {
|
|
2424
|
+
return /* @__PURE__ */ jsx21("li", { className: "fc-context-menu__divider" }, i);
|
|
2425
|
+
}
|
|
2426
|
+
const action = item;
|
|
2427
|
+
return /* @__PURE__ */ jsxs15(
|
|
2428
|
+
"li",
|
|
2429
|
+
{
|
|
2430
|
+
className: [
|
|
2431
|
+
"fc-context-menu__item",
|
|
2432
|
+
action.danger ? "fc-context-menu__item--danger" : "",
|
|
2433
|
+
action.disabled ? "fc-context-menu__item--disabled" : ""
|
|
2434
|
+
].filter(Boolean).join(" "),
|
|
2435
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
2436
|
+
onClick: () => {
|
|
2437
|
+
if (action.disabled) return;
|
|
2438
|
+
action.onClick();
|
|
2439
|
+
hide();
|
|
2440
|
+
},
|
|
2441
|
+
children: [
|
|
2442
|
+
action.icon && /* @__PURE__ */ jsx21("span", { className: "fc-context-menu__icon", children: action.icon }),
|
|
2443
|
+
/* @__PURE__ */ jsx21("span", { className: "fc-context-menu__label", children: action.label })
|
|
2444
|
+
]
|
|
2445
|
+
},
|
|
2446
|
+
i
|
|
2447
|
+
);
|
|
2448
|
+
})
|
|
2449
|
+
}
|
|
2450
|
+
)
|
|
2451
|
+
] });
|
|
2452
|
+
}
|
|
2453
|
+
var useContextMenu = () => useContext4(ContextMenuContext);
|
|
2454
|
+
|
|
2455
|
+
// src/components/Chat/Chat.tsx
|
|
2456
|
+
import { useState as useState16, useRef as useRef9, useEffect as useEffect9, useCallback as useCallback9, useMemo as useMemo6 } from "react";
|
|
2457
|
+
|
|
2458
|
+
// src/components/SmartMessage/SmartMessage.tsx
|
|
2459
|
+
import { useState as useState15, memo as memo5 } from "react";
|
|
2460
|
+
import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2461
|
+
var SmartMessage = memo5(({
|
|
2462
|
+
id,
|
|
2463
|
+
content,
|
|
2464
|
+
role,
|
|
2465
|
+
timestamp,
|
|
2466
|
+
status,
|
|
2467
|
+
toolName,
|
|
2468
|
+
toolResult,
|
|
2469
|
+
onCopy,
|
|
2470
|
+
className = "",
|
|
2471
|
+
style = {}
|
|
2472
|
+
}) => {
|
|
2473
|
+
const [copied, setCopied] = useState15(false);
|
|
2474
|
+
const formattedTime = timestamp ? new Date(timestamp).toLocaleTimeString("zh-CN", { hour: "2-digit", minute: "2-digit" }) : "";
|
|
2475
|
+
const handleCopy = async () => {
|
|
2036
2476
|
try {
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
}
|
|
2477
|
+
let copyContent = content;
|
|
2478
|
+
if (role === "tool" && toolResult) {
|
|
2479
|
+
copyContent = `\u5DE5\u5177: ${toolName || "\u5DE5\u5177\u8C03\u7528"}
|
|
2480
|
+
\u7ED3\u679C: ${JSON.stringify(toolResult, null, 2)}`;
|
|
2481
|
+
}
|
|
2482
|
+
await navigator.clipboard.writeText(copyContent);
|
|
2483
|
+
setCopied(true);
|
|
2484
|
+
onCopy?.(content, role);
|
|
2485
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
2042
2486
|
} catch (err) {
|
|
2043
2487
|
console.error("\u590D\u5236\u5931\u8D25:", err);
|
|
2044
|
-
if (err instanceof Error) {
|
|
2045
|
-
if (err.name === "NotAllowedError") {
|
|
2046
|
-
setCopyError("\u9700\u8981\u526A\u8D34\u677F\u6743\u9650\uFF0C\u8BF7\u5141\u8BB8\u540E\u91CD\u8BD5");
|
|
2047
|
-
} else if (err.name === "SecurityError") {
|
|
2048
|
-
setCopyError("\u51FA\u4E8E\u5B89\u5168\u539F\u56E0\uFF0C\u65E0\u6CD5\u590D\u5236\u5185\u5BB9");
|
|
2049
|
-
} else {
|
|
2050
|
-
setCopyError("\u590D\u5236\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5");
|
|
2051
|
-
}
|
|
2052
|
-
} else {
|
|
2053
|
-
setCopyError("\u590D\u5236\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5");
|
|
2054
|
-
}
|
|
2055
|
-
setTimeout(() => {
|
|
2056
|
-
setCopyError(null);
|
|
2057
|
-
}, 3e3);
|
|
2058
2488
|
}
|
|
2059
|
-
}
|
|
2060
|
-
const
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
}
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2489
|
+
};
|
|
2490
|
+
const shouldShowCopyButton = () => {
|
|
2491
|
+
return role === "user" || role === "assistant";
|
|
2492
|
+
};
|
|
2493
|
+
const getContainerClassName = () => {
|
|
2494
|
+
const baseClass = "smart-message";
|
|
2495
|
+
const roleClass = `smart-message-${role}`;
|
|
2496
|
+
const statusClass = status ? `smart-message-${status}` : "";
|
|
2497
|
+
return `${baseClass} ${roleClass} ${statusClass} ${className}`.trim();
|
|
2498
|
+
};
|
|
2499
|
+
const getContentClassName = () => {
|
|
2500
|
+
const baseClass = "smart-message-content";
|
|
2501
|
+
const roleContentClass = `smart-message-content-${role}`;
|
|
2502
|
+
return `${baseClass} ${roleContentClass}`;
|
|
2503
|
+
};
|
|
2504
|
+
const renderSystemMessage = () => /* @__PURE__ */ jsxs16("div", { className: "system-message-wrapper", children: [
|
|
2505
|
+
/* @__PURE__ */ jsx22("div", { className: "system-message-icon", children: /* @__PURE__ */ jsxs16("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [
|
|
2506
|
+
/* @__PURE__ */ jsx22("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "2" }),
|
|
2507
|
+
/* @__PURE__ */ jsx22("path", { d: "M12 8V12M12 16H12.01", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
|
|
2508
|
+
] }) }),
|
|
2509
|
+
/* @__PURE__ */ jsx22("div", { className: "system-message-text", children: content }),
|
|
2510
|
+
formattedTime && /* @__PURE__ */ jsx22("div", { className: "system-message-time", children: formattedTime })
|
|
2511
|
+
] });
|
|
2512
|
+
const renderToolMessage = () => /* @__PURE__ */ jsxs16("div", { className: "tool-message-wrapper", children: [
|
|
2513
|
+
/* @__PURE__ */ jsxs16("div", { className: "tool-message-header", children: [
|
|
2514
|
+
/* @__PURE__ */ jsx22("div", { className: "tool-message-icon", children: /* @__PURE__ */ jsxs16("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [
|
|
2515
|
+
/* @__PURE__ */ jsx22("path", { d: "M14.7 6.3L19 2L22 5L17.7 9.3L14.7 6.3Z", stroke: "currentColor", strokeWidth: "2" }),
|
|
2516
|
+
/* @__PURE__ */ jsx22("path", { d: "M9.3 17.7L5 22L2 19L6.3 14.7L9.3 17.7Z", stroke: "currentColor", strokeWidth: "2" }),
|
|
2517
|
+
/* @__PURE__ */ jsx22("path", { d: "M12 12L14.7 9.3M12 12L9.3 14.7M12 12L8 8M12 12L16 16", stroke: "currentColor", strokeWidth: "2" })
|
|
2518
|
+
] }) }),
|
|
2519
|
+
/* @__PURE__ */ jsx22("span", { className: "tool-message-name", children: toolName || "\u5DE5\u5177\u8C03\u7528" })
|
|
2520
|
+
] }),
|
|
2521
|
+
/* @__PURE__ */ jsxs16("div", { className: "tool-message-content", children: [
|
|
2522
|
+
/* @__PURE__ */ jsxs16("div", { className: "tool-message-params", children: [
|
|
2523
|
+
/* @__PURE__ */ jsx22("strong", { children: "\u53C2\u6570:" }),
|
|
2524
|
+
/* @__PURE__ */ jsx22("pre", { children: content })
|
|
2525
|
+
] }),
|
|
2526
|
+
toolResult && /* @__PURE__ */ jsxs16("div", { className: "tool-message-result", children: [
|
|
2527
|
+
/* @__PURE__ */ jsx22("strong", { children: "\u7ED3\u679C:" }),
|
|
2528
|
+
/* @__PURE__ */ jsx22("pre", { children: typeof toolResult === "object" ? JSON.stringify(toolResult, null, 2) : toolResult })
|
|
2529
|
+
] })
|
|
2530
|
+
] }),
|
|
2531
|
+
formattedTime && /* @__PURE__ */ jsx22("div", { className: "tool-message-time", children: formattedTime })
|
|
2532
|
+
] });
|
|
2533
|
+
const renderUserAssistantMessage = () => /* @__PURE__ */ jsxs16(Fragment4, { children: [
|
|
2534
|
+
/* @__PURE__ */ jsxs16("div", { className: "message-header", children: [
|
|
2535
|
+
/* @__PURE__ */ jsx22("span", { className: "message-sender", children: role === "user" ? "\u6211" : "AI\u52A9\u624B" }),
|
|
2536
|
+
formattedTime && /* @__PURE__ */ jsx22("span", { className: "message-time", children: formattedTime })
|
|
2537
|
+
] }),
|
|
2538
|
+
/* @__PURE__ */ jsxs16("div", { className: getContentClassName(), children: [
|
|
2539
|
+
/* @__PURE__ */ jsx22("div", { className: "message-text", children: content }),
|
|
2540
|
+
shouldShowCopyButton() && /* @__PURE__ */ jsx22(
|
|
2541
|
+
"button",
|
|
2542
|
+
{
|
|
2543
|
+
className: `copy-btn ${copied ? "copied" : ""}`,
|
|
2544
|
+
onClick: handleCopy,
|
|
2545
|
+
title: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236\u5185\u5BB9",
|
|
2546
|
+
children: copied ? /* @__PURE__ */ jsxs16(Fragment4, { children: [
|
|
2547
|
+
/* @__PURE__ */ jsx22("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx22("path", { d: "M20 6L9 17L4 12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }),
|
|
2548
|
+
/* @__PURE__ */ jsx22("span", { children: "\u5DF2\u590D\u5236" })
|
|
2549
|
+
] }) : /* @__PURE__ */ jsxs16(Fragment4, { children: [
|
|
2550
|
+
/* @__PURE__ */ jsxs16("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", children: [
|
|
2551
|
+
/* @__PURE__ */ jsx22("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", stroke: "currentColor", strokeWidth: "2" }),
|
|
2552
|
+
/* @__PURE__ */ jsx22("path", { d: "M5 15H4C2.9 15 2 14.1 2 13V4C2 2.9 2.9 2 4 2H13C14.1 2 15 2.9 15 4V5", stroke: "currentColor", strokeWidth: "2" })
|
|
2553
|
+
] }),
|
|
2554
|
+
/* @__PURE__ */ jsx22("span", { children: "\u590D\u5236" })
|
|
2555
|
+
] })
|
|
2078
2556
|
}
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2557
|
+
),
|
|
2558
|
+
status === "sending" && /* @__PURE__ */ jsx22("span", { className: "message-status sending", children: "\u53D1\u9001\u4E2D..." }),
|
|
2559
|
+
status === "error" && /* @__PURE__ */ jsx22("span", { className: "message-status error", children: "\u53D1\u9001\u5931\u8D25" })
|
|
2560
|
+
] })
|
|
2561
|
+
] });
|
|
2562
|
+
const renderMessage = () => {
|
|
2563
|
+
switch (role) {
|
|
2564
|
+
case "system":
|
|
2565
|
+
return renderSystemMessage();
|
|
2566
|
+
case "tool":
|
|
2567
|
+
return renderToolMessage();
|
|
2568
|
+
case "user":
|
|
2569
|
+
case "assistant":
|
|
2570
|
+
default:
|
|
2571
|
+
return renderUserAssistantMessage();
|
|
2094
2572
|
}
|
|
2095
|
-
}
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2573
|
+
};
|
|
2574
|
+
return /* @__PURE__ */ jsx22("div", { className: getContainerClassName(), style, "data-message-id": id, children: renderMessage() });
|
|
2575
|
+
});
|
|
2576
|
+
SmartMessage.displayName = "SmartMessage";
|
|
2577
|
+
var SmartMessage_default = SmartMessage;
|
|
2578
|
+
|
|
2579
|
+
// src/components/Chat/Chat.tsx
|
|
2580
|
+
import { jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2581
|
+
var Chat = ({
|
|
2582
|
+
messages = [],
|
|
2583
|
+
title = "AI \u52A9\u624B",
|
|
2584
|
+
loading = false,
|
|
2585
|
+
conversations = [],
|
|
2586
|
+
currentConversationId,
|
|
2587
|
+
emptyText = "\u6682\u65E0\u5386\u53F2\u5BF9\u8BDD",
|
|
2588
|
+
newConversationText = "\u65B0\u5EFA\u5BF9\u8BDD",
|
|
2589
|
+
historyTitle = "\u5386\u53F2\u5BF9\u8BDD",
|
|
2590
|
+
showHistoryButton = true,
|
|
2591
|
+
showMinimizeButton = true,
|
|
2592
|
+
showHeader = true,
|
|
2593
|
+
showFooter = false,
|
|
2594
|
+
autoScroll = true,
|
|
2595
|
+
onSwitchConversation,
|
|
2596
|
+
onNewConversation,
|
|
2597
|
+
onDeleteConversation,
|
|
2598
|
+
onMinimize,
|
|
2599
|
+
onRestore,
|
|
2600
|
+
onMessageCopy,
|
|
2601
|
+
className = "",
|
|
2602
|
+
style = {},
|
|
2603
|
+
headerClassName = "",
|
|
2604
|
+
headerStyle = {},
|
|
2605
|
+
messagesClassName = "",
|
|
2606
|
+
messagesStyle = {},
|
|
2607
|
+
bubbleClassName = "",
|
|
2608
|
+
height = "600px",
|
|
2609
|
+
width
|
|
2610
|
+
}) => {
|
|
2611
|
+
const [showHistory, setShowHistory] = useState16(false);
|
|
2612
|
+
const [isMinimized, setIsMinimized] = useState16(false);
|
|
2613
|
+
const messagesContainerRef = useRef9(null);
|
|
2614
|
+
const messagesEndRef = useRef9(null);
|
|
2615
|
+
const historyPanelRef = useRef9(null);
|
|
2616
|
+
const currentConversation = useMemo6(
|
|
2617
|
+
() => conversations.find((c) => c.id === currentConversationId),
|
|
2618
|
+
[conversations, currentConversationId]
|
|
2619
|
+
);
|
|
2620
|
+
const currentTitle = currentConversation?.title || title;
|
|
2621
|
+
useEffect9(() => {
|
|
2622
|
+
if (autoScroll && messagesContainerRef.current && !showHistory && !isMinimized) {
|
|
2623
|
+
messagesContainerRef.current.scrollTop = messagesContainerRef.current.scrollHeight;
|
|
2100
2624
|
}
|
|
2101
|
-
}, [
|
|
2102
|
-
|
|
2103
|
-
const
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
e.target.style.height = "auto";
|
|
2107
|
-
e.target.style.height = `${Math.min(e.target.scrollHeight, 100)}px`;
|
|
2108
|
-
const hasContent = value.length > 0;
|
|
2109
|
-
if (hasContent !== isTyping) {
|
|
2110
|
-
setIsTyping(hasContent);
|
|
2111
|
-
onTyping?.(hasContent);
|
|
2625
|
+
}, [messages, loading, showHistory, isMinimized, autoScroll]);
|
|
2626
|
+
useEffect9(() => {
|
|
2627
|
+
const handleClickOutside = (event) => {
|
|
2628
|
+
if (showHistory && historyPanelRef.current && !historyPanelRef.current.contains(event.target)) {
|
|
2629
|
+
setShowHistory(false);
|
|
2112
2630
|
}
|
|
2631
|
+
};
|
|
2632
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
2633
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
2634
|
+
}, [showHistory]);
|
|
2635
|
+
const handleDeleteConversation = useCallback9((conversationId) => {
|
|
2636
|
+
onDeleteConversation?.(conversationId);
|
|
2637
|
+
}, [onDeleteConversation]);
|
|
2638
|
+
const handleMinimize = useCallback9(() => {
|
|
2639
|
+
setIsMinimized(true);
|
|
2640
|
+
onMinimize?.();
|
|
2641
|
+
}, [onMinimize]);
|
|
2642
|
+
const handleRestore = useCallback9(() => {
|
|
2643
|
+
setIsMinimized(false);
|
|
2644
|
+
onRestore?.();
|
|
2645
|
+
}, [onRestore]);
|
|
2646
|
+
const handleCopy = useCallback9((content) => {
|
|
2647
|
+
const message = messages.find((m) => m.content === content);
|
|
2648
|
+
if (message) {
|
|
2649
|
+
onMessageCopy?.(message);
|
|
2113
2650
|
}
|
|
2114
|
-
}, [
|
|
2115
|
-
const
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
/* @__PURE__ */
|
|
2132
|
-
/* @__PURE__ */ jsx19("span", { className: "message-sender", children: isUser ? userName : assistantName }),
|
|
2133
|
-
/* @__PURE__ */ jsx19("span", { className: "message-time", children: formatTime(message.timestamp) })
|
|
2134
|
-
] }),
|
|
2135
|
-
/* @__PURE__ */ jsxs14("div", { className: "message-bubble", children: [
|
|
2136
|
-
/* @__PURE__ */ jsx19("div", { className: "message-text", children: message.content }),
|
|
2137
|
-
message.status === "sending" && /* @__PURE__ */ jsx19("span", { className: "message-status sending", children: "\u53D1\u9001\u4E2D..." }),
|
|
2138
|
-
message.status === "error" && /* @__PURE__ */ jsx19("span", { className: "message-status error", children: "\u53D1\u9001\u5931\u8D25" })
|
|
2139
|
-
] }),
|
|
2140
|
-
enableCopy && /* @__PURE__ */ jsx19(
|
|
2141
|
-
"button",
|
|
2142
|
-
{
|
|
2143
|
-
className: `copy-btn ${isCopied ? "copied" : ""}`,
|
|
2144
|
-
onClick: () => handleCopyMessage(message.id, message.content),
|
|
2145
|
-
title: isCopied ? "\u5DF2\u590D\u5236" : "\u590D\u5236\u5185\u5BB9",
|
|
2146
|
-
"aria-label": isCopied ? "\u5DF2\u590D\u5236" : "\u590D\u5236\u5185\u5BB9",
|
|
2147
|
-
children: isCopied ? /* @__PURE__ */ jsxs14(Fragment3, { children: [
|
|
2148
|
-
/* @__PURE__ */ jsx19("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx19("path", { d: "M20 6L9 17L4 12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
|
|
2149
|
-
/* @__PURE__ */ jsx19("span", { children: "\u5DF2\u590D\u5236" })
|
|
2150
|
-
] }) : /* @__PURE__ */ jsxs14(Fragment3, { children: [
|
|
2151
|
-
/* @__PURE__ */ jsxs14("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
2152
|
-
/* @__PURE__ */ jsx19("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", stroke: "currentColor", strokeWidth: "2" }),
|
|
2153
|
-
/* @__PURE__ */ jsx19("path", { d: "M5 15H4C2.9 15 2 14.1 2 13V4C2 2.9 2.9 2 4 2H13C14.1 2 15 2.9 15 4V5", stroke: "currentColor", strokeWidth: "2" })
|
|
2154
|
-
] }),
|
|
2155
|
-
/* @__PURE__ */ jsx19("span", { children: "\u590D\u5236" })
|
|
2156
|
-
] })
|
|
2157
|
-
}
|
|
2158
|
-
)
|
|
2159
|
-
] })
|
|
2160
|
-
] }, message.id);
|
|
2161
|
-
};
|
|
2162
|
-
return /* @__PURE__ */ jsxs14("div", { className: `chat-container ${currentTheme}`, style: { height }, children: [
|
|
2163
|
-
showHeader && /* @__PURE__ */ jsxs14("div", { className: "chat-header", children: [
|
|
2164
|
-
/* @__PURE__ */ jsx19("div", { className: "chat-title", children: title }),
|
|
2165
|
-
/* @__PURE__ */ jsxs14("div", { className: "chat-status", children: [
|
|
2166
|
-
(loading || isSending) && /* @__PURE__ */ jsx19("span", { className: "status-dot" }),
|
|
2167
|
-
/* @__PURE__ */ jsx19("span", { children: loading || isSending ? "AI \u6B63\u5728\u601D\u8003..." : "\u5728\u7EBF" })
|
|
2651
|
+
}, [messages, onMessageCopy]);
|
|
2652
|
+
const containerStyle = useMemo6(() => ({
|
|
2653
|
+
height,
|
|
2654
|
+
width,
|
|
2655
|
+
...style
|
|
2656
|
+
}), [height, width, style]);
|
|
2657
|
+
if (isMinimized) {
|
|
2658
|
+
return /* @__PURE__ */ jsx23("div", { className: `chat-container-minimized ${className}`, style: containerStyle, children: /* @__PURE__ */ jsx23("button", { className: "restore-btn-only", onClick: handleRestore, title: "\u5C55\u5F00", children: /* @__PURE__ */ jsx23("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx23("path", { d: "M12 5V19M5 12H19", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) }) });
|
|
2659
|
+
}
|
|
2660
|
+
return /* @__PURE__ */ jsxs17("div", { className: `chat-container ${className}`, style: containerStyle, children: [
|
|
2661
|
+
showHeader && /* @__PURE__ */ jsxs17("div", { className: `chat-header ${headerClassName}`, style: headerStyle, children: [
|
|
2662
|
+
/* @__PURE__ */ jsx23("div", { className: "chat-title", children: currentTitle }),
|
|
2663
|
+
/* @__PURE__ */ jsxs17("div", { className: "chat-header-actions", children: [
|
|
2664
|
+
showHistoryButton && /* @__PURE__ */ jsx23("button", { className: "history-btn", onClick: () => setShowHistory(!showHistory), title: "\u5386\u53F2\u5BF9\u8BDD", children: /* @__PURE__ */ jsxs17("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: [
|
|
2665
|
+
/* @__PURE__ */ jsx23("path", { d: "M12 8V12L15 15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
|
|
2666
|
+
/* @__PURE__ */ jsx23("circle", { cx: "12", cy: "12", r: "9", stroke: "currentColor", strokeWidth: "2" })
|
|
2667
|
+
] }) }),
|
|
2668
|
+
showMinimizeButton && /* @__PURE__ */ jsx23("button", { className: "minimize-btn", onClick: handleMinimize, title: "\u6700\u5C0F\u5316", children: /* @__PURE__ */ jsx23("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx23("path", { d: "M5 12H19", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
|
|
2168
2669
|
] })
|
|
2169
2670
|
] }),
|
|
2170
|
-
/* @__PURE__ */
|
|
2171
|
-
messages.map(
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2671
|
+
/* @__PURE__ */ jsxs17("div", { className: `chat-messages ${messagesClassName}`, ref: messagesContainerRef, style: messagesStyle, children: [
|
|
2672
|
+
messages.map((message) => /* @__PURE__ */ jsx23(
|
|
2673
|
+
SmartMessage_default,
|
|
2674
|
+
{
|
|
2675
|
+
id: message.id,
|
|
2676
|
+
content: message.content,
|
|
2677
|
+
role: message.type,
|
|
2678
|
+
timestamp: message.timestamp,
|
|
2679
|
+
status: message.status,
|
|
2680
|
+
toolName: message.toolName,
|
|
2681
|
+
toolResult: message.toolResult,
|
|
2682
|
+
onCopy: handleCopy,
|
|
2683
|
+
className: bubbleClassName
|
|
2684
|
+
},
|
|
2685
|
+
message.id
|
|
2686
|
+
)),
|
|
2687
|
+
loading && /* @__PURE__ */ jsx23("div", { className: "typing-wrapper", children: /* @__PURE__ */ jsxs17("div", { className: "typing-indicator", children: [
|
|
2688
|
+
/* @__PURE__ */ jsx23("span", {}),
|
|
2689
|
+
/* @__PURE__ */ jsx23("span", {}),
|
|
2690
|
+
/* @__PURE__ */ jsx23("span", {})
|
|
2691
|
+
] }) }),
|
|
2692
|
+
/* @__PURE__ */ jsx23("div", { ref: messagesEndRef })
|
|
2184
2693
|
] }),
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
/* @__PURE__ */
|
|
2188
|
-
/* @__PURE__ */
|
|
2189
|
-
|
|
2190
|
-
{
|
|
2191
|
-
ref: inputRef,
|
|
2192
|
-
className: "chat-input",
|
|
2193
|
-
value: inputValue,
|
|
2194
|
-
onChange: handleInputChange,
|
|
2195
|
-
onKeyDown: handleKeyDown,
|
|
2196
|
-
placeholder,
|
|
2197
|
-
disabled: disabled || loading || isSending,
|
|
2198
|
-
rows: 1,
|
|
2199
|
-
maxLength: maxInputLength,
|
|
2200
|
-
spellCheck: false,
|
|
2201
|
-
autoCorrect: "off",
|
|
2202
|
-
autoCapitalize: "off",
|
|
2203
|
-
autoComplete: "off"
|
|
2204
|
-
}
|
|
2205
|
-
),
|
|
2206
|
-
/* @__PURE__ */ jsx19(
|
|
2207
|
-
"button",
|
|
2208
|
-
{
|
|
2209
|
-
className: `chat-send-btn ${!inputValue.trim() || disabled || loading || isSending ? "disabled" : ""}`,
|
|
2210
|
-
onClick: handleSend,
|
|
2211
|
-
disabled: !inputValue.trim() || disabled || loading || isSending,
|
|
2212
|
-
children: "\u53D1\u9001"
|
|
2213
|
-
}
|
|
2214
|
-
)
|
|
2694
|
+
showFooter && /* @__PURE__ */ jsx23("div", { className: "chat-footer" }),
|
|
2695
|
+
showHistory && /* @__PURE__ */ jsxs17("div", { className: "history-panel", ref: historyPanelRef, children: [
|
|
2696
|
+
/* @__PURE__ */ jsxs17("div", { className: "history-header", children: [
|
|
2697
|
+
/* @__PURE__ */ jsx23("h3", { children: historyTitle }),
|
|
2698
|
+
/* @__PURE__ */ jsx23("button", { className: "close-history-btn", onClick: () => setShowHistory(false), children: "\u2715" })
|
|
2215
2699
|
] }),
|
|
2216
|
-
/* @__PURE__ */
|
|
2217
|
-
/* @__PURE__ */
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2700
|
+
/* @__PURE__ */ jsxs17("div", { className: "history-list", children: [
|
|
2701
|
+
/* @__PURE__ */ jsxs17("button", { className: "new-conversation-btn-large", onClick: () => {
|
|
2702
|
+
onNewConversation?.();
|
|
2703
|
+
setShowHistory(false);
|
|
2704
|
+
}, children: [
|
|
2705
|
+
/* @__PURE__ */ jsx23("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx23("path", { d: "M12 5V19M5 12H19", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }),
|
|
2706
|
+
/* @__PURE__ */ jsx23("span", { children: newConversationText })
|
|
2707
|
+
] }),
|
|
2708
|
+
conversations.length === 0 ? /* @__PURE__ */ jsx23("div", { className: "empty-history", children: /* @__PURE__ */ jsx23("p", { children: emptyText }) }) : conversations.map((conv) => /* @__PURE__ */ jsxs17(
|
|
2709
|
+
"div",
|
|
2710
|
+
{
|
|
2711
|
+
className: `history-item ${currentConversationId === conv.id ? "active" : ""}`,
|
|
2712
|
+
onClick: () => {
|
|
2713
|
+
onSwitchConversation?.(conv.id);
|
|
2714
|
+
setShowHistory(false);
|
|
2715
|
+
},
|
|
2716
|
+
children: [
|
|
2717
|
+
/* @__PURE__ */ jsxs17("div", { className: "history-item-content", children: [
|
|
2718
|
+
/* @__PURE__ */ jsx23("div", { className: "history-item-title", children: /* @__PURE__ */ jsx23("span", { children: conv.title }) }),
|
|
2719
|
+
/* @__PURE__ */ jsx23("div", { className: "history-item-preview", children: conv.lastMessage }),
|
|
2720
|
+
/* @__PURE__ */ jsxs17("div", { className: "history-item-meta", children: [
|
|
2721
|
+
/* @__PURE__ */ jsx23("span", { children: new Date(conv.timestamp).toLocaleDateString() }),
|
|
2722
|
+
/* @__PURE__ */ jsxs17("span", { children: [
|
|
2723
|
+
conv.messages.length,
|
|
2724
|
+
"\u6761\u6D88\u606F"
|
|
2725
|
+
] })
|
|
2726
|
+
] })
|
|
2727
|
+
] }),
|
|
2728
|
+
/* @__PURE__ */ jsx23("div", { className: "history-item-actions", children: /* @__PURE__ */ jsx23(
|
|
2729
|
+
"button",
|
|
2730
|
+
{
|
|
2731
|
+
className: "delete-conversation-btn",
|
|
2732
|
+
onClick: (e) => {
|
|
2733
|
+
e.stopPropagation();
|
|
2734
|
+
handleDeleteConversation(conv.id);
|
|
2735
|
+
},
|
|
2736
|
+
title: "\u5220\u9664\u5BF9\u8BDD",
|
|
2737
|
+
children: /* @__PURE__ */ jsxs17("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", children: [
|
|
2738
|
+
/* @__PURE__ */ jsx23("path", { d: "M3 6H21", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
|
|
2739
|
+
/* @__PURE__ */ jsx23("path", { d: "M19 6V20C19 21.1 18.1 22 17 22H7C5.9 22 5 21.1 5 20V6", stroke: "currentColor", strokeWidth: "2" }),
|
|
2740
|
+
/* @__PURE__ */ jsx23("path", { d: "M8 6V4C8 2.9 8.9 2 10 2H14C15.1 2 16 2.9 16 4V6", stroke: "currentColor", strokeWidth: "2" })
|
|
2741
|
+
] })
|
|
2742
|
+
}
|
|
2743
|
+
) })
|
|
2744
|
+
]
|
|
2745
|
+
},
|
|
2746
|
+
conv.id
|
|
2747
|
+
))
|
|
2223
2748
|
] })
|
|
2224
2749
|
] })
|
|
2225
2750
|
] });
|
|
@@ -2233,16 +2758,20 @@ export {
|
|
|
2233
2758
|
Card,
|
|
2234
2759
|
Chat,
|
|
2235
2760
|
CheckButton,
|
|
2761
|
+
ContextMenuProvider,
|
|
2236
2762
|
DeleteDialog,
|
|
2237
2763
|
Input,
|
|
2238
2764
|
ListGroup,
|
|
2239
2765
|
ListGroupItem,
|
|
2766
|
+
MarkdownEditor,
|
|
2240
2767
|
OrphanDialog,
|
|
2241
2768
|
RollingBox,
|
|
2242
2769
|
Select,
|
|
2243
2770
|
SideBar,
|
|
2244
2771
|
Slider,
|
|
2245
|
-
|
|
2772
|
+
SmartMessage,
|
|
2773
|
+
TabBar,
|
|
2774
|
+
TagItem,
|
|
2246
2775
|
ThemeProvider,
|
|
2247
2776
|
Tree,
|
|
2248
2777
|
VirtualList,
|
|
@@ -2251,5 +2780,6 @@ export {
|
|
|
2251
2780
|
isDescendantOf,
|
|
2252
2781
|
lazyLoad,
|
|
2253
2782
|
useAlert,
|
|
2783
|
+
useContextMenu,
|
|
2254
2784
|
useTheme
|
|
2255
2785
|
};
|