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.cjs
CHANGED
|
@@ -38,16 +38,20 @@ __export(index_exports, {
|
|
|
38
38
|
Card: () => Card,
|
|
39
39
|
Chat: () => Chat,
|
|
40
40
|
CheckButton: () => CheckButton,
|
|
41
|
+
ContextMenuProvider: () => ContextMenuProvider,
|
|
41
42
|
DeleteDialog: () => DeleteDialog,
|
|
42
43
|
Input: () => Input,
|
|
43
44
|
ListGroup: () => ListGroup,
|
|
44
45
|
ListGroupItem: () => ListGroupItem,
|
|
46
|
+
MarkdownEditor: () => MarkdownEditor,
|
|
45
47
|
OrphanDialog: () => OrphanDialog,
|
|
46
48
|
RollingBox: () => RollingBox,
|
|
47
49
|
Select: () => Select,
|
|
48
50
|
SideBar: () => SideBar,
|
|
49
51
|
Slider: () => Slider,
|
|
50
|
-
|
|
52
|
+
SmartMessage: () => SmartMessage,
|
|
53
|
+
TabBar: () => TabBar,
|
|
54
|
+
TagItem: () => TagItem,
|
|
51
55
|
ThemeProvider: () => ThemeProvider,
|
|
52
56
|
Tree: () => Tree,
|
|
53
57
|
VirtualList: () => VirtualList,
|
|
@@ -56,6 +60,7 @@ __export(index_exports, {
|
|
|
56
60
|
isDescendantOf: () => isDescendantOf,
|
|
57
61
|
lazyLoad: () => lazyLoad,
|
|
58
62
|
useAlert: () => useAlert,
|
|
63
|
+
useContextMenu: () => useContextMenu,
|
|
59
64
|
useTheme: () => useTheme
|
|
60
65
|
});
|
|
61
66
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -111,10 +116,39 @@ function Button({
|
|
|
111
116
|
iconOnly = false,
|
|
112
117
|
iconLeft,
|
|
113
118
|
iconRight,
|
|
119
|
+
background,
|
|
120
|
+
hoverBackground,
|
|
121
|
+
activeBackground,
|
|
122
|
+
color,
|
|
123
|
+
hoverColor,
|
|
124
|
+
activeColor,
|
|
125
|
+
borderColor,
|
|
126
|
+
hoverBorderColor,
|
|
114
127
|
className,
|
|
128
|
+
style,
|
|
115
129
|
children,
|
|
116
130
|
...props
|
|
117
131
|
}) {
|
|
132
|
+
const colorVars = {
|
|
133
|
+
"--btn-bg": background,
|
|
134
|
+
"--btn-bg-hover": hoverBackground,
|
|
135
|
+
"--btn-bg-active": activeBackground,
|
|
136
|
+
"--btn-color": color,
|
|
137
|
+
"--btn-color-hover": hoverColor,
|
|
138
|
+
"--btn-color-active": activeColor,
|
|
139
|
+
"--btn-border": borderColor,
|
|
140
|
+
"--btn-border-hover": hoverBorderColor
|
|
141
|
+
};
|
|
142
|
+
const overrideStyle = {};
|
|
143
|
+
for (const [key, value] of Object.entries(colorVars)) {
|
|
144
|
+
if (value !== void 0) {
|
|
145
|
+
overrideStyle[key] = value;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const mergedStyle = {
|
|
149
|
+
...overrideStyle,
|
|
150
|
+
...style
|
|
151
|
+
};
|
|
118
152
|
const classNames = [
|
|
119
153
|
"fc-btn",
|
|
120
154
|
`fc-btn--${variant}`,
|
|
@@ -131,6 +165,7 @@ function Button({
|
|
|
131
165
|
{
|
|
132
166
|
className: classNames,
|
|
133
167
|
disabled: disabled || loading,
|
|
168
|
+
style: mergedStyle,
|
|
134
169
|
...props,
|
|
135
170
|
children: [
|
|
136
171
|
iconLeft && !loading && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "fc-btn__icon fc-btn__icon--left", children: iconLeft }),
|
|
@@ -169,6 +204,11 @@ function CheckButton({
|
|
|
169
204
|
size = "md",
|
|
170
205
|
labelLeft,
|
|
171
206
|
labelRight,
|
|
207
|
+
trackBackground,
|
|
208
|
+
checkedTrackBackground,
|
|
209
|
+
thumbBackground,
|
|
210
|
+
thumbDotColor,
|
|
211
|
+
labelColor,
|
|
172
212
|
className = "",
|
|
173
213
|
style
|
|
174
214
|
}) {
|
|
@@ -187,6 +227,23 @@ function CheckButton({
|
|
|
187
227
|
toggle();
|
|
188
228
|
}
|
|
189
229
|
};
|
|
230
|
+
const colorVars = {
|
|
231
|
+
"--check-track-bg": trackBackground,
|
|
232
|
+
"--check-track-bg-checked": checkedTrackBackground,
|
|
233
|
+
"--check-thumb-bg": thumbBackground,
|
|
234
|
+
"--check-thumb-dot-color": thumbDotColor,
|
|
235
|
+
"--check-label-color": labelColor
|
|
236
|
+
};
|
|
237
|
+
const overrideStyle = {};
|
|
238
|
+
for (const [key, value] of Object.entries(colorVars)) {
|
|
239
|
+
if (value !== void 0) {
|
|
240
|
+
overrideStyle[key] = value;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
const mergedStyle = {
|
|
244
|
+
...overrideStyle,
|
|
245
|
+
...style
|
|
246
|
+
};
|
|
190
247
|
const cls = [
|
|
191
248
|
"fc-check",
|
|
192
249
|
`fc-check--${size}`,
|
|
@@ -198,7 +255,7 @@ function CheckButton({
|
|
|
198
255
|
"div",
|
|
199
256
|
{
|
|
200
257
|
className: cls,
|
|
201
|
-
style,
|
|
258
|
+
style: mergedStyle,
|
|
202
259
|
role: "switch",
|
|
203
260
|
"aria-checked": checked,
|
|
204
261
|
tabIndex: disabled ? -1 : 0,
|
|
@@ -224,8 +281,26 @@ function RollingBox({
|
|
|
224
281
|
showTrack = false,
|
|
225
282
|
children,
|
|
226
283
|
className,
|
|
284
|
+
thumbColor,
|
|
285
|
+
thumbHoverColor,
|
|
286
|
+
thumbActiveColor,
|
|
287
|
+
trackColor,
|
|
288
|
+
style,
|
|
227
289
|
...props
|
|
228
290
|
}) {
|
|
291
|
+
const colorVars = {
|
|
292
|
+
"--roll-thumb": thumbColor,
|
|
293
|
+
"--roll-thumb-hover": thumbHoverColor,
|
|
294
|
+
"--roll-thumb-active": thumbActiveColor,
|
|
295
|
+
"--roll-track": trackColor
|
|
296
|
+
};
|
|
297
|
+
const overrideStyle = {};
|
|
298
|
+
for (const [key, value] of Object.entries(colorVars)) {
|
|
299
|
+
if (value !== void 0) {
|
|
300
|
+
overrideStyle[key] = value;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
const mergedStyle = { ...overrideStyle, ...style };
|
|
229
304
|
const containerRef = React2.useRef(null);
|
|
230
305
|
const [isScrolling, setIsScrolling] = React2.useState(false);
|
|
231
306
|
const scrollTimeoutRef = React2.useRef(null);
|
|
@@ -261,6 +336,7 @@ function RollingBox({
|
|
|
261
336
|
{
|
|
262
337
|
ref: containerRef,
|
|
263
338
|
className: classNames,
|
|
339
|
+
style: mergedStyle,
|
|
264
340
|
onScroll: handleScroll,
|
|
265
341
|
...props,
|
|
266
342
|
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "fc-roll__content", children })
|
|
@@ -269,134 +345,100 @@ function RollingBox({
|
|
|
269
345
|
}
|
|
270
346
|
|
|
271
347
|
// src/components/Bar/SideBar.tsx
|
|
272
|
-
var
|
|
348
|
+
var import_react2 = require("react");
|
|
273
349
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
collapsed: controlledCollapsed,
|
|
283
|
-
defaultCollapsed = false,
|
|
284
|
-
onCollapse,
|
|
285
|
-
className,
|
|
286
|
-
width = 240,
|
|
287
|
-
collapsedWidth = 64
|
|
288
|
-
}) {
|
|
289
|
-
const [internalSelected, setInternalSelected] = React3.useState(defaultSelectedKeys);
|
|
290
|
-
const [internalOpen, setInternalOpen] = React3.useState(defaultOpenKeys);
|
|
291
|
-
const [internalCollapsed, setInternalCollapsed] = React3.useState(defaultCollapsed);
|
|
292
|
-
const currentSelected = controlledSelected ?? internalSelected;
|
|
293
|
-
const currentOpen = controlledOpen ?? internalOpen;
|
|
294
|
-
const currentCollapsed = controlledCollapsed ?? internalCollapsed;
|
|
295
|
-
const updateOpen = React3.useCallback((next) => {
|
|
296
|
-
if (controlledOpen === void 0) setInternalOpen(next);
|
|
297
|
-
onOpenChange?.(next);
|
|
298
|
-
}, [controlledOpen, onOpenChange]);
|
|
299
|
-
const toggleOpen = React3.useCallback((key) => {
|
|
300
|
-
const next = currentOpen.includes(key) ? currentOpen.filter((k) => k !== key) : [...currentOpen, key];
|
|
301
|
-
updateOpen(next);
|
|
302
|
-
}, [currentOpen, updateOpen]);
|
|
303
|
-
const handleSelect = React3.useCallback((key, item) => {
|
|
304
|
-
if (item.disabled) return;
|
|
305
|
-
const next = [key];
|
|
306
|
-
if (controlledSelected === void 0) setInternalSelected(next);
|
|
307
|
-
onSelect?.(next);
|
|
308
|
-
}, [controlledSelected, onSelect]);
|
|
309
|
-
const toggleCollapse = React3.useCallback(() => {
|
|
310
|
-
const next = !currentCollapsed;
|
|
311
|
-
if (controlledCollapsed === void 0) setInternalCollapsed(next);
|
|
312
|
-
onCollapse?.(next);
|
|
313
|
-
}, [currentCollapsed, controlledCollapsed, onCollapse]);
|
|
314
|
-
const handleItemClick = React3.useCallback((item) => {
|
|
315
|
-
if (item.children?.length) {
|
|
316
|
-
toggleOpen(item.key);
|
|
317
|
-
} else {
|
|
318
|
-
handleSelect(item.key, item);
|
|
319
|
-
}
|
|
320
|
-
}, [toggleOpen, handleSelect]);
|
|
321
|
-
const handleItemKeyDown = React3.useCallback((e, item) => {
|
|
322
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
323
|
-
e.preventDefault();
|
|
324
|
-
handleItemClick(item);
|
|
325
|
-
}
|
|
326
|
-
}, [handleItemClick]);
|
|
327
|
-
const renderMenuItem = (item, level = 0) => {
|
|
328
|
-
const hasChildren = (item.children?.length ?? 0) > 0;
|
|
329
|
-
const isOpen = currentOpen.includes(item.key);
|
|
330
|
-
const isSelected = currentSelected.includes(item.key);
|
|
331
|
-
const itemClassName = [
|
|
332
|
-
"fc-sidebar__item",
|
|
333
|
-
`fc-sidebar__item--level-${level}`,
|
|
334
|
-
hasChildren && "fc-sidebar__item--parent",
|
|
335
|
-
isOpen && "fc-sidebar__item--open",
|
|
336
|
-
isSelected && "fc-sidebar__item--selected",
|
|
337
|
-
item.disabled && "fc-sidebar__item--disabled"
|
|
338
|
-
].filter(Boolean).join(" ");
|
|
339
|
-
const Tag = item.href ? "a" : "div";
|
|
340
|
-
const interactiveProps = {
|
|
341
|
-
role: hasChildren ? "treeitem" : "menuitem",
|
|
342
|
-
tabIndex: item.disabled ? -1 : 0,
|
|
343
|
-
"aria-selected": isSelected || void 0,
|
|
344
|
-
"aria-expanded": hasChildren ? isOpen : void 0,
|
|
345
|
-
"aria-disabled": item.disabled || void 0,
|
|
346
|
-
onClick: () => handleItemClick(item),
|
|
347
|
-
onKeyDown: (e) => handleItemKeyDown(e, item),
|
|
348
|
-
...item.href ? { href: item.href } : {}
|
|
349
|
-
};
|
|
350
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "fc-sidebar__item-wrapper", children: [
|
|
351
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Tag, { className: itemClassName, ...interactiveProps, children: [
|
|
352
|
-
item.icon && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "fc-sidebar__icon", "aria-hidden": "true", children: item.icon }),
|
|
353
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "fc-sidebar__label", children: item.label }),
|
|
354
|
-
hasChildren && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "fc-sidebar__arrow", "aria-hidden": "true", children: "\u25B6" })
|
|
355
|
-
] }),
|
|
356
|
-
hasChildren && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
357
|
-
"div",
|
|
358
|
-
{
|
|
359
|
-
className: [
|
|
360
|
-
"fc-sidebar__submenu",
|
|
361
|
-
isOpen && "fc-sidebar__submenu--open"
|
|
362
|
-
].filter(Boolean).join(" "),
|
|
363
|
-
role: "group",
|
|
364
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "fc-sidebar__submenu-inner", children: item.children.map((child) => renderMenuItem(child, level + 1)) })
|
|
365
|
-
}
|
|
366
|
-
)
|
|
367
|
-
] }, item.key);
|
|
368
|
-
};
|
|
369
|
-
const sidebarStyle = {
|
|
370
|
-
"--sidebar-width": `${currentCollapsed ? collapsedWidth : width}px`,
|
|
371
|
-
"--sidebar-collapsed-width": `${collapsedWidth}px`
|
|
372
|
-
};
|
|
350
|
+
var SideBarItemView = (0, import_react2.memo)(({ item, isSelected, onClick }) => {
|
|
351
|
+
const classes = [
|
|
352
|
+
"fc-sidebar__item",
|
|
353
|
+
isSelected && "fc-sidebar__item--selected",
|
|
354
|
+
item.disabled && "fc-sidebar__item--disabled"
|
|
355
|
+
].filter(Boolean).join(" ");
|
|
356
|
+
const Tag = item.href ? "a" : "div";
|
|
357
|
+
const linkProps = item.href ? { href: item.href } : {};
|
|
373
358
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
374
|
-
|
|
359
|
+
Tag,
|
|
375
360
|
{
|
|
376
|
-
className:
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
className
|
|
380
|
-
].filter(Boolean).join(" "),
|
|
381
|
-
style: sidebarStyle,
|
|
382
|
-
role: "navigation",
|
|
383
|
-
"aria-label": "Sidebar",
|
|
361
|
+
className: classes,
|
|
362
|
+
onClick: () => !item.disabled && onClick(item.key),
|
|
363
|
+
...linkProps,
|
|
384
364
|
children: [
|
|
385
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("
|
|
386
|
-
|
|
387
|
-
{
|
|
388
|
-
className: "fc-sidebar__collapse-btn",
|
|
389
|
-
onClick: toggleCollapse,
|
|
390
|
-
"aria-label": currentCollapsed ? "\u5C55\u5F00\u4FA7\u680F" : "\u6536\u8D77\u4FA7\u680F",
|
|
391
|
-
"aria-expanded": !currentCollapsed,
|
|
392
|
-
children: currentCollapsed ? "\u2192" : "\u2190"
|
|
393
|
-
}
|
|
394
|
-
) }),
|
|
395
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("nav", { className: "fc-sidebar__menu", role: "tree", children: items.map((item) => renderMenuItem(item)) })
|
|
365
|
+
item.icon && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "fc-sidebar__icon", children: item.icon }),
|
|
366
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "fc-sidebar__label", children: item.label })
|
|
396
367
|
]
|
|
397
368
|
}
|
|
398
369
|
);
|
|
399
|
-
}
|
|
370
|
+
});
|
|
371
|
+
SideBarItemView.displayName = "SideBarItemView";
|
|
372
|
+
var SideBar = (0, import_react2.memo)(({
|
|
373
|
+
items,
|
|
374
|
+
selectedKey,
|
|
375
|
+
collapsed,
|
|
376
|
+
width = 240,
|
|
377
|
+
collapsedWidth = 64,
|
|
378
|
+
onSelect,
|
|
379
|
+
onCollapse,
|
|
380
|
+
className = "",
|
|
381
|
+
style
|
|
382
|
+
}) => {
|
|
383
|
+
const handleClick = (0, import_react2.useCallback)(
|
|
384
|
+
(key) => onSelect(key),
|
|
385
|
+
[onSelect]
|
|
386
|
+
);
|
|
387
|
+
const toggleCollapse = (0, import_react2.useCallback)(
|
|
388
|
+
() => onCollapse(!collapsed),
|
|
389
|
+
[collapsed, onCollapse]
|
|
390
|
+
);
|
|
391
|
+
const rootClasses = [
|
|
392
|
+
"fc-sidebar",
|
|
393
|
+
collapsed && "fc-sidebar--collapsed",
|
|
394
|
+
className
|
|
395
|
+
].filter(Boolean).join(" ");
|
|
396
|
+
const rootStyle = {
|
|
397
|
+
"--sidebar-width": `${collapsed ? collapsedWidth : width}px`,
|
|
398
|
+
"--sidebar-collapsed-width": `${collapsedWidth}px`,
|
|
399
|
+
...style
|
|
400
|
+
};
|
|
401
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("aside", { className: rootClasses, style: rootStyle, children: [
|
|
402
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "fc-sidebar__header", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
403
|
+
"button",
|
|
404
|
+
{
|
|
405
|
+
className: "fc-sidebar__collapse-btn",
|
|
406
|
+
onClick: toggleCollapse,
|
|
407
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
408
|
+
"svg",
|
|
409
|
+
{
|
|
410
|
+
className: "fc-sidebar__collapse-icon",
|
|
411
|
+
width: "16",
|
|
412
|
+
height: "16",
|
|
413
|
+
viewBox: "0 0 16 16",
|
|
414
|
+
fill: "none",
|
|
415
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
416
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
417
|
+
"path",
|
|
418
|
+
{
|
|
419
|
+
d: collapsed ? "M6 3L11 8L6 13" : "M10 3L5 8L10 13",
|
|
420
|
+
stroke: "currentColor",
|
|
421
|
+
strokeWidth: "1.5",
|
|
422
|
+
strokeLinecap: "round",
|
|
423
|
+
strokeLinejoin: "round"
|
|
424
|
+
}
|
|
425
|
+
)
|
|
426
|
+
}
|
|
427
|
+
)
|
|
428
|
+
}
|
|
429
|
+
) }),
|
|
430
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("nav", { className: "fc-sidebar__menu", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
431
|
+
SideBarItemView,
|
|
432
|
+
{
|
|
433
|
+
item,
|
|
434
|
+
isSelected: selectedKey === item.key,
|
|
435
|
+
onClick: handleClick
|
|
436
|
+
},
|
|
437
|
+
item.key
|
|
438
|
+
)) })
|
|
439
|
+
] });
|
|
440
|
+
});
|
|
441
|
+
SideBar.displayName = "SideBar";
|
|
400
442
|
|
|
401
443
|
// src/components/Input/Input.tsx
|
|
402
444
|
var React4 = __toESM(require("react"), 1);
|
|
@@ -464,8 +506,8 @@ var Input = React4.forwardRef(({
|
|
|
464
506
|
);
|
|
465
507
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: classNames, children: [
|
|
466
508
|
addonBefore && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "fc-input__addon fc-input__addon--before", children: addonBefore }),
|
|
467
|
-
prefix && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "fc-input__prefix", children: prefix }),
|
|
468
509
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "fc-input__wrapper", children: [
|
|
510
|
+
prefix && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "fc-input__prefix", children: prefix }),
|
|
469
511
|
input,
|
|
470
512
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "fc-input__actions", children: [
|
|
471
513
|
showClear && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
@@ -512,7 +554,16 @@ function Slider({
|
|
|
512
554
|
disabled = false,
|
|
513
555
|
marks,
|
|
514
556
|
tooltip = false,
|
|
515
|
-
className = ""
|
|
557
|
+
className = "",
|
|
558
|
+
style,
|
|
559
|
+
trackBackground,
|
|
560
|
+
fillBackground,
|
|
561
|
+
thumbBackground,
|
|
562
|
+
thumbBorderColor,
|
|
563
|
+
markDotColor,
|
|
564
|
+
markLabelColor,
|
|
565
|
+
tooltipBackground,
|
|
566
|
+
tooltipColor
|
|
516
567
|
}) {
|
|
517
568
|
const trackRef = React5.useRef(null);
|
|
518
569
|
const draggingRef = React5.useRef(null);
|
|
@@ -521,6 +572,23 @@ function Slider({
|
|
|
521
572
|
const [internalValue, setInternalValue] = React5.useState(initialValue);
|
|
522
573
|
const isControlled = controlledValue !== void 0;
|
|
523
574
|
const currentValue = isControlled ? controlledValue : internalValue;
|
|
575
|
+
const colorVars = {
|
|
576
|
+
"--slider-track-bg": trackBackground,
|
|
577
|
+
"--slider-fill-bg": fillBackground,
|
|
578
|
+
"--slider-thumb-bg": thumbBackground,
|
|
579
|
+
"--slider-thumb-border": thumbBorderColor,
|
|
580
|
+
"--slider-mark-dot-bg": markDotColor,
|
|
581
|
+
"--slider-mark-label-color": markLabelColor,
|
|
582
|
+
"--slider-tooltip-bg": tooltipBackground,
|
|
583
|
+
"--slider-tooltip-color": tooltipColor
|
|
584
|
+
};
|
|
585
|
+
const overrideStyle = {};
|
|
586
|
+
for (const [key, value] of Object.entries(colorVars)) {
|
|
587
|
+
if (value !== void 0) {
|
|
588
|
+
overrideStyle[key] = value;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
const mergedStyle = { ...overrideStyle, ...style };
|
|
524
592
|
const getPercent = (val) => Math.max(0, Math.min(100, (val - min) / (max - min) * 100));
|
|
525
593
|
const getValueFromPercent = (percent) => {
|
|
526
594
|
const raw = min + percent / 100 * (max - min);
|
|
@@ -574,7 +642,7 @@ function Slider({
|
|
|
574
642
|
dragging !== null && "fc-slider--dragging",
|
|
575
643
|
className
|
|
576
644
|
].filter(Boolean).join(" ");
|
|
577
|
-
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: cls, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
645
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: cls, style: mergedStyle, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
578
646
|
"div",
|
|
579
647
|
{
|
|
580
648
|
ref: trackRef,
|
|
@@ -636,10 +704,30 @@ function Select({
|
|
|
636
704
|
multiple = false,
|
|
637
705
|
disabled = false,
|
|
638
706
|
className = "",
|
|
707
|
+
style,
|
|
639
708
|
virtualScroll = false,
|
|
640
709
|
virtualItemHeight = 32,
|
|
641
|
-
maxHeight = 256
|
|
710
|
+
maxHeight = 256,
|
|
711
|
+
triggerBackground,
|
|
712
|
+
triggerBorderColor,
|
|
713
|
+
selectedColor,
|
|
714
|
+
selectedBackground,
|
|
715
|
+
hoverBackground
|
|
642
716
|
}) {
|
|
717
|
+
const colorVars = {
|
|
718
|
+
"--select-trigger-bg": triggerBackground,
|
|
719
|
+
"--select-trigger-border": triggerBorderColor,
|
|
720
|
+
"--select-option-selected-color": selectedColor,
|
|
721
|
+
"--select-option-selected-bg": selectedBackground,
|
|
722
|
+
"--select-option-hover-bg": hoverBackground
|
|
723
|
+
};
|
|
724
|
+
const overrideStyle = {};
|
|
725
|
+
for (const [key, value] of Object.entries(colorVars)) {
|
|
726
|
+
if (value !== void 0) {
|
|
727
|
+
overrideStyle[key] = value;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
const mergedStyle = { ...overrideStyle, ...style };
|
|
643
731
|
const [isOpen, setIsOpen] = React6.useState(false);
|
|
644
732
|
const [searchValue, setSearchValue] = React6.useState("");
|
|
645
733
|
const [highlightedIndex, setHighlightedIndex] = React6.useState(0);
|
|
@@ -713,14 +801,14 @@ function Select({
|
|
|
713
801
|
disabled && "fc-select--disabled",
|
|
714
802
|
className
|
|
715
803
|
].filter(Boolean).join(" ");
|
|
716
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { ref: containerRef, className: classNames, children: [
|
|
804
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { ref: containerRef, className: classNames, style: mergedStyle, children: [
|
|
717
805
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
718
806
|
"div",
|
|
719
807
|
{
|
|
720
808
|
className: "fc-select__trigger",
|
|
721
809
|
onClick: () => !disabled && setIsOpen(!isOpen),
|
|
722
810
|
children: [
|
|
723
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: `fc-select__value ${!currentValue && "fc-select__value--placeholder"}`, children: displayLabel() }),
|
|
811
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: `fc-select__value ${(currentValue === void 0 || currentValue === null || multiple && !currentValue.length) && "fc-select__value--placeholder"}`, children: displayLabel() }),
|
|
724
812
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "fc-select__arrow", children: "\u25BC" })
|
|
725
813
|
]
|
|
726
814
|
}
|
|
@@ -787,7 +875,8 @@ function Select({
|
|
|
787
875
|
}
|
|
788
876
|
function highlightText(text, highlight) {
|
|
789
877
|
if (!highlight) return text;
|
|
790
|
-
const
|
|
878
|
+
const escaped = highlight.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
879
|
+
const parts = text.split(new RegExp(`(${escaped})`, "gi"));
|
|
791
880
|
return parts.map(
|
|
792
881
|
(part, i) => part.toLowerCase() === highlight.toLowerCase() ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("mark", { className: "fc-select__highlight", children: part }, i) : part
|
|
793
882
|
);
|
|
@@ -795,15 +884,15 @@ function Select({
|
|
|
795
884
|
}
|
|
796
885
|
|
|
797
886
|
// src/components/Tree/Tree.tsx
|
|
798
|
-
var
|
|
887
|
+
var import_react4 = require("react");
|
|
799
888
|
var import_core = require("@dnd-kit/core");
|
|
800
889
|
|
|
801
890
|
// src/components/Tree/DeleteDialog.tsx
|
|
802
|
-
var
|
|
891
|
+
var import_react3 = require("react");
|
|
803
892
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
804
893
|
function DeleteDialog({ node, onClose, onDelete }) {
|
|
805
|
-
const [phase, setPhase] = (0,
|
|
806
|
-
const [loading, setLoading] = (0,
|
|
894
|
+
const [phase, setPhase] = (0, import_react3.useState)("choose");
|
|
895
|
+
const [loading, setLoading] = (0, import_react3.useState)(false);
|
|
807
896
|
if (!node) return null;
|
|
808
897
|
const reset = () => {
|
|
809
898
|
setPhase("choose");
|
|
@@ -962,14 +1051,14 @@ function isDescendantOf(roots, ancestorKey, targetKey) {
|
|
|
962
1051
|
|
|
963
1052
|
// src/components/Tree/Tree.tsx
|
|
964
1053
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
965
|
-
var TreeActionsCtx = (0,
|
|
966
|
-
var TreeStateCtx = (0,
|
|
967
|
-
var DndStateCtx = (0,
|
|
968
|
-
var CollapsePanel = (0,
|
|
969
|
-
const innerRef = (0,
|
|
970
|
-
const [height, setHeight] = (0,
|
|
971
|
-
const [ready, setReady] = (0,
|
|
972
|
-
(0,
|
|
1054
|
+
var TreeActionsCtx = (0, import_react4.createContext)(null);
|
|
1055
|
+
var TreeStateCtx = (0, import_react4.createContext)(null);
|
|
1056
|
+
var DndStateCtx = (0, import_react4.createContext)(null);
|
|
1057
|
+
var CollapsePanel = (0, import_react4.memo)(function CollapsePanel2({ open, children }) {
|
|
1058
|
+
const innerRef = (0, import_react4.useRef)(null);
|
|
1059
|
+
const [height, setHeight] = (0, import_react4.useState)(0);
|
|
1060
|
+
const [ready, setReady] = (0, import_react4.useState)(false);
|
|
1061
|
+
(0, import_react4.useEffect)(() => {
|
|
973
1062
|
const el = innerRef.current;
|
|
974
1063
|
if (!el) return;
|
|
975
1064
|
const ro = new ResizeObserver(() => setHeight(el.offsetHeight));
|
|
@@ -984,39 +1073,39 @@ var CollapsePanel = (0, import_react3.memo)(function CollapsePanel2({ open, chil
|
|
|
984
1073
|
transition: ready ? "height 0.12s ease-out" : "none"
|
|
985
1074
|
}, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { ref: innerRef, children }) });
|
|
986
1075
|
});
|
|
987
|
-
var DndSlot = (0,
|
|
1076
|
+
var DndSlot = (0, import_react4.memo)(function DndSlot2({
|
|
988
1077
|
nodeKey,
|
|
989
1078
|
disabled,
|
|
990
1079
|
children
|
|
991
1080
|
}) {
|
|
992
|
-
const dndState = (0,
|
|
1081
|
+
const dndState = (0, import_react4.useContext)(DndStateCtx);
|
|
993
1082
|
const isDropTarget = dndState.dropTargetKey === nodeKey;
|
|
994
1083
|
const dropPosition = isDropTarget ? dndState.dropPosition : null;
|
|
995
1084
|
const isDragSource = dndState.dragKey === nodeKey;
|
|
996
1085
|
const { attributes, listeners, setNodeRef: setDragRef, isDragging } = (0, import_core.useDraggable)({ id: nodeKey, disabled });
|
|
997
1086
|
const { setNodeRef: setDropRef } = (0, import_core.useDroppable)({ id: nodeKey, disabled });
|
|
998
|
-
const setRef = (0,
|
|
1087
|
+
const setRef = (0, import_react4.useCallback)((el) => {
|
|
999
1088
|
setDragRef(el);
|
|
1000
1089
|
setDropRef(el);
|
|
1001
1090
|
}, [setDragRef, setDropRef]);
|
|
1002
|
-
const handleProps = (0,
|
|
1091
|
+
const handleProps = (0, import_react4.useMemo)(
|
|
1003
1092
|
() => ({ ...attributes, ...listeners }),
|
|
1004
1093
|
[attributes, listeners]
|
|
1005
1094
|
);
|
|
1006
1095
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, { children: children({ setRef, handleProps, isDragging, isDragSource, dropPosition }) });
|
|
1007
1096
|
});
|
|
1008
|
-
var TreeNodeItem = (0,
|
|
1009
|
-
const actions = (0,
|
|
1010
|
-
const state = (0,
|
|
1097
|
+
var TreeNodeItem = (0, import_react4.memo)(function TreeNodeItem2({ node, level, hidden = false }) {
|
|
1098
|
+
const actions = (0, import_react4.useContext)(TreeActionsCtx);
|
|
1099
|
+
const state = (0, import_react4.useContext)(TreeStateCtx);
|
|
1011
1100
|
const isExpanded = state.expandedKeys.has(node.key);
|
|
1012
1101
|
const isEditing = state.editingKey === node.key;
|
|
1013
1102
|
const hasChildren = node.children.length > 0;
|
|
1014
1103
|
const indent = level * 20 + 12;
|
|
1015
|
-
const [localEdit, setLocalEdit] = (0,
|
|
1016
|
-
(0,
|
|
1104
|
+
const [localEdit, setLocalEdit] = (0, import_react4.useState)("");
|
|
1105
|
+
(0, import_react4.useEffect)(() => {
|
|
1017
1106
|
if (isEditing) setLocalEdit(node.title);
|
|
1018
1107
|
}, [isEditing, node.title]);
|
|
1019
|
-
const handleEditKeyDown = (0,
|
|
1108
|
+
const handleEditKeyDown = (0, import_react4.useCallback)((e) => {
|
|
1020
1109
|
e.stopPropagation();
|
|
1021
1110
|
if (e.key === "Enter") actions.commitEdit(node.key, localEdit).then();
|
|
1022
1111
|
if (e.key === "Escape") actions.cancelEdit();
|
|
@@ -1139,18 +1228,18 @@ function Tree({
|
|
|
1139
1228
|
scrollHeight = "400px",
|
|
1140
1229
|
className = ""
|
|
1141
1230
|
}) {
|
|
1142
|
-
const [expandedKeys, setExpandedKeys] = (0,
|
|
1143
|
-
const [editingKey, setEditingKey] = (0,
|
|
1144
|
-
const [deleteTarget, setDeleteTarget] = (0,
|
|
1145
|
-
const [searchValue, setSearchValue] = (0,
|
|
1146
|
-
const [dndState, setDndState] = (0,
|
|
1231
|
+
const [expandedKeys, setExpandedKeys] = (0, import_react4.useState)(/* @__PURE__ */ new Set());
|
|
1232
|
+
const [editingKey, setEditingKey] = (0, import_react4.useState)(null);
|
|
1233
|
+
const [deleteTarget, setDeleteTarget] = (0, import_react4.useState)(null);
|
|
1234
|
+
const [searchValue, setSearchValue] = (0, import_react4.useState)("");
|
|
1235
|
+
const [dndState, setDndState] = (0, import_react4.useState)({
|
|
1147
1236
|
dropTargetKey: null,
|
|
1148
1237
|
dropPosition: null,
|
|
1149
1238
|
dragKey: null
|
|
1150
1239
|
});
|
|
1151
|
-
const dropRef = (0,
|
|
1152
|
-
const pointerYRef = (0,
|
|
1153
|
-
(0,
|
|
1240
|
+
const dropRef = (0, import_react4.useRef)({ key: null, pos: null });
|
|
1241
|
+
const pointerYRef = (0, import_react4.useRef)(0);
|
|
1242
|
+
(0, import_react4.useEffect)(() => {
|
|
1154
1243
|
const handler = (e) => {
|
|
1155
1244
|
pointerYRef.current = e.clientY;
|
|
1156
1245
|
};
|
|
@@ -1160,39 +1249,39 @@ function Tree({
|
|
|
1160
1249
|
const sensors = (0, import_core.useSensors)(
|
|
1161
1250
|
(0, import_core.useSensor)(import_core.PointerSensor, { activationConstraint: { distance: 8 } })
|
|
1162
1251
|
);
|
|
1163
|
-
const toggleExpand = (0,
|
|
1252
|
+
const toggleExpand = (0, import_react4.useCallback)((key) => {
|
|
1164
1253
|
setExpandedKeys((prev) => {
|
|
1165
1254
|
const next = new Set(prev);
|
|
1166
1255
|
next.has(key) ? next.delete(key) : next.add(key);
|
|
1167
1256
|
return next;
|
|
1168
1257
|
});
|
|
1169
1258
|
}, []);
|
|
1170
|
-
const select = (0,
|
|
1171
|
-
const startEdit = (0,
|
|
1172
|
-
const cancelEdit = (0,
|
|
1173
|
-
const commitEdit = (0,
|
|
1259
|
+
const select = (0, import_react4.useCallback)((key) => onSelect?.(key), [onSelect]);
|
|
1260
|
+
const startEdit = (0, import_react4.useCallback)((key) => setEditingKey(key), []);
|
|
1261
|
+
const cancelEdit = (0, import_react4.useCallback)(() => setEditingKey(null), []);
|
|
1262
|
+
const commitEdit = (0, import_react4.useCallback)(async (key, newTitle) => {
|
|
1174
1263
|
setEditingKey(null);
|
|
1175
1264
|
const trimmed = newTitle.trim();
|
|
1176
1265
|
if (trimmed && onRename) await onRename(key, trimmed);
|
|
1177
1266
|
}, [onRename]);
|
|
1178
|
-
const requestCreate = (0,
|
|
1267
|
+
const requestCreate = (0, import_react4.useCallback)(async (parentKey) => {
|
|
1179
1268
|
if (!onCreate) return;
|
|
1180
1269
|
const newKey = await onCreate(parentKey);
|
|
1181
1270
|
if (parentKey) setExpandedKeys((prev) => /* @__PURE__ */ new Set([...prev, parentKey]));
|
|
1182
1271
|
setEditingKey(newKey);
|
|
1183
1272
|
}, [onCreate]);
|
|
1184
|
-
const requestDelete = (0,
|
|
1273
|
+
const requestDelete = (0, import_react4.useCallback)((node) => {
|
|
1185
1274
|
setDeleteTarget(node);
|
|
1186
1275
|
}, []);
|
|
1187
|
-
const treeDataRef = (0,
|
|
1188
|
-
const expandedRef = (0,
|
|
1276
|
+
const treeDataRef = (0, import_react4.useRef)(treeData);
|
|
1277
|
+
const expandedRef = (0, import_react4.useRef)(expandedKeys);
|
|
1189
1278
|
treeDataRef.current = treeData;
|
|
1190
1279
|
expandedRef.current = expandedKeys;
|
|
1191
|
-
const handleDragStart = (0,
|
|
1280
|
+
const handleDragStart = (0, import_react4.useCallback)(({ active }) => {
|
|
1192
1281
|
dropRef.current = { key: null, pos: null };
|
|
1193
1282
|
setDndState({ dropTargetKey: null, dropPosition: null, dragKey: active.id });
|
|
1194
1283
|
}, []);
|
|
1195
|
-
const handleDragMove = (0,
|
|
1284
|
+
const handleDragMove = (0, import_react4.useCallback)(({ over, active }) => {
|
|
1196
1285
|
if (!over || over.id === active.id) {
|
|
1197
1286
|
if (dropRef.current.key !== null) {
|
|
1198
1287
|
dropRef.current = { key: null, pos: null };
|
|
@@ -1219,18 +1308,18 @@ function Tree({
|
|
|
1219
1308
|
dropRef.current = { key: targetKey, pos: position };
|
|
1220
1309
|
setDndState((prev) => ({ ...prev, dropTargetKey: targetKey, dropPosition: position }));
|
|
1221
1310
|
}, []);
|
|
1222
|
-
const handleDragEnd = (0,
|
|
1311
|
+
const handleDragEnd = (0, import_react4.useCallback)(({ active }) => {
|
|
1223
1312
|
const { key: target, pos: position } = dropRef.current;
|
|
1224
1313
|
dropRef.current = { key: null, pos: null };
|
|
1225
1314
|
setDndState({ dropTargetKey: null, dropPosition: null, dragKey: null });
|
|
1226
1315
|
if (!target || !position || active.id === target) return;
|
|
1227
1316
|
onMove?.(active.id, target, position);
|
|
1228
1317
|
}, [onMove]);
|
|
1229
|
-
const handleDragCancel = (0,
|
|
1318
|
+
const handleDragCancel = (0, import_react4.useCallback)(() => {
|
|
1230
1319
|
dropRef.current = { key: null, pos: null };
|
|
1231
1320
|
setDndState({ dropTargetKey: null, dropPosition: null, dragKey: null });
|
|
1232
1321
|
}, []);
|
|
1233
|
-
const displayData = (0,
|
|
1322
|
+
const displayData = (0, import_react4.useMemo)(() => {
|
|
1234
1323
|
if (!searchValue) return treeData;
|
|
1235
1324
|
const kw = searchValue.toLowerCase();
|
|
1236
1325
|
const filter = (nodes) => nodes.reduce((acc, node) => {
|
|
@@ -1242,7 +1331,7 @@ function Tree({
|
|
|
1242
1331
|
}, []);
|
|
1243
1332
|
return filter(treeData);
|
|
1244
1333
|
}, [treeData, searchValue]);
|
|
1245
|
-
const actionsValue = (0,
|
|
1334
|
+
const actionsValue = (0, import_react4.useMemo)(() => ({
|
|
1246
1335
|
toggleExpand,
|
|
1247
1336
|
select,
|
|
1248
1337
|
startEdit,
|
|
@@ -1251,7 +1340,7 @@ function Tree({
|
|
|
1251
1340
|
requestCreate,
|
|
1252
1341
|
requestDelete
|
|
1253
1342
|
}), [toggleExpand, select, startEdit, commitEdit, cancelEdit, requestCreate, requestDelete]);
|
|
1254
|
-
const stateValue = (0,
|
|
1343
|
+
const stateValue = (0, import_react4.useMemo)(() => ({
|
|
1255
1344
|
expandedKeys,
|
|
1256
1345
|
selectedKey: selectedKey ?? null,
|
|
1257
1346
|
editingKey
|
|
@@ -1309,10 +1398,10 @@ function Tree({
|
|
|
1309
1398
|
}
|
|
1310
1399
|
|
|
1311
1400
|
// src/components/Tree/OrphanDialog.tsx
|
|
1312
|
-
var
|
|
1401
|
+
var import_react5 = require("react");
|
|
1313
1402
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1314
1403
|
function OrphanDialog({ orphans, onResolve, onClose }) {
|
|
1315
|
-
const [resolutions, setResolutions] = (0,
|
|
1404
|
+
const [resolutions, setResolutions] = (0, import_react5.useState)(
|
|
1316
1405
|
() => Object.fromEntries(orphans.map((o) => [o.key, "lift"]))
|
|
1317
1406
|
);
|
|
1318
1407
|
if (orphans.length === 0) return null;
|
|
@@ -1376,7 +1465,7 @@ function OrphanDialog({ orphans, onResolve, onClose }) {
|
|
|
1376
1465
|
}
|
|
1377
1466
|
|
|
1378
1467
|
// src/components/Avatar/Avatar.tsx
|
|
1379
|
-
var
|
|
1468
|
+
var import_react6 = require("react");
|
|
1380
1469
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1381
1470
|
var SIZE_MAP = {
|
|
1382
1471
|
xs: 20,
|
|
@@ -1387,7 +1476,7 @@ var SIZE_MAP = {
|
|
|
1387
1476
|
};
|
|
1388
1477
|
var DEFAULT_ICON = "M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z";
|
|
1389
1478
|
var useAvatarStyles = (size, shape, bordered, onClick, loadState, src, children, colorVariant, className, color, customStyle) => {
|
|
1390
|
-
const classes = (0,
|
|
1479
|
+
const classes = (0, import_react6.useMemo)(() => {
|
|
1391
1480
|
const classNames = [
|
|
1392
1481
|
"ui-avatar",
|
|
1393
1482
|
`ui-avatar-${size}`,
|
|
@@ -1401,7 +1490,7 @@ var useAvatarStyles = (size, shape, bordered, onClick, loadState, src, children,
|
|
|
1401
1490
|
];
|
|
1402
1491
|
return classNames.filter(Boolean).join(" ");
|
|
1403
1492
|
}, [size, shape, bordered, onClick, loadState, src, children, colorVariant, className]);
|
|
1404
|
-
const style = (0,
|
|
1493
|
+
const style = (0, import_react6.useMemo)(() => ({
|
|
1405
1494
|
width: SIZE_MAP[size],
|
|
1406
1495
|
height: SIZE_MAP[size],
|
|
1407
1496
|
fontSize: `${SIZE_MAP[size] * 0.4}px`,
|
|
@@ -1411,20 +1500,20 @@ var useAvatarStyles = (size, shape, bordered, onClick, loadState, src, children,
|
|
|
1411
1500
|
return { classes, style };
|
|
1412
1501
|
};
|
|
1413
1502
|
var useImageLoader = (src, fallbackSrc, onImageLoad, onImageError, onStateChange) => {
|
|
1414
|
-
const [loadState, setLoadState] = (0,
|
|
1415
|
-
const [currentSrc, setCurrentSrc] = (0,
|
|
1416
|
-
(0,
|
|
1503
|
+
const [loadState, setLoadState] = (0, import_react6.useState)("idle");
|
|
1504
|
+
const [currentSrc, setCurrentSrc] = (0, import_react6.useState)(src);
|
|
1505
|
+
(0, import_react6.useEffect)(() => {
|
|
1417
1506
|
setCurrentSrc(src);
|
|
1418
1507
|
setLoadState(src ? "loading" : "idle");
|
|
1419
1508
|
}, [src]);
|
|
1420
|
-
(0,
|
|
1509
|
+
(0, import_react6.useEffect)(() => {
|
|
1421
1510
|
onStateChange?.(loadState);
|
|
1422
1511
|
}, [loadState, onStateChange]);
|
|
1423
|
-
const handleLoad = (0,
|
|
1512
|
+
const handleLoad = (0, import_react6.useCallback)(() => {
|
|
1424
1513
|
setLoadState("loaded");
|
|
1425
1514
|
onImageLoad?.();
|
|
1426
1515
|
}, [onImageLoad]);
|
|
1427
|
-
const handleError = (0,
|
|
1516
|
+
const handleError = (0, import_react6.useCallback)((e) => {
|
|
1428
1517
|
if (fallbackSrc && currentSrc !== fallbackSrc) {
|
|
1429
1518
|
setCurrentSrc(fallbackSrc);
|
|
1430
1519
|
setLoadState("loading");
|
|
@@ -1441,7 +1530,7 @@ var useImageLoader = (src, fallbackSrc, onImageLoad, onImageError, onStateChange
|
|
|
1441
1530
|
};
|
|
1442
1531
|
};
|
|
1443
1532
|
var useKeyboardInteraction = (onClick) => {
|
|
1444
|
-
const handleKeyDown = (0,
|
|
1533
|
+
const handleKeyDown = (0, import_react6.useCallback)((e) => {
|
|
1445
1534
|
if (onClick && (e.key === "Enter" || e.key === " ")) {
|
|
1446
1535
|
e.preventDefault();
|
|
1447
1536
|
onClick(e);
|
|
@@ -1481,7 +1570,7 @@ var useAriaAttributes = (onClick, loadState, alt) => {
|
|
|
1481
1570
|
"data-load-state": loadState
|
|
1482
1571
|
};
|
|
1483
1572
|
};
|
|
1484
|
-
var Avatar = (0,
|
|
1573
|
+
var Avatar = (0, import_react6.forwardRef)(
|
|
1485
1574
|
({
|
|
1486
1575
|
children,
|
|
1487
1576
|
src,
|
|
@@ -1551,12 +1640,12 @@ var Avatar = (0, import_react5.forwardRef)(
|
|
|
1551
1640
|
Avatar.displayName = "Avatar";
|
|
1552
1641
|
|
|
1553
1642
|
// src/components/ListGroup/ListGroup.tsx
|
|
1554
|
-
var
|
|
1643
|
+
var import_react7 = require("react");
|
|
1555
1644
|
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1556
1645
|
var combineClassNames = (...classNames) => {
|
|
1557
1646
|
return classNames.filter(Boolean).join(" ");
|
|
1558
1647
|
};
|
|
1559
|
-
var ListGroupItem = (0,
|
|
1648
|
+
var ListGroupItem = (0, import_react7.forwardRef)(
|
|
1560
1649
|
({
|
|
1561
1650
|
active = false,
|
|
1562
1651
|
disabled = false,
|
|
@@ -1565,11 +1654,11 @@ var ListGroupItem = (0, import_react6.forwardRef)(
|
|
|
1565
1654
|
children,
|
|
1566
1655
|
...props
|
|
1567
1656
|
}, ref) => {
|
|
1568
|
-
const handleClick = (0,
|
|
1657
|
+
const handleClick = (0, import_react7.useCallback)((e) => {
|
|
1569
1658
|
if (disabled) return;
|
|
1570
1659
|
onClick?.(e);
|
|
1571
1660
|
}, [disabled, onClick]);
|
|
1572
|
-
const classNames = (0,
|
|
1661
|
+
const classNames = (0, import_react7.useMemo)(() => {
|
|
1573
1662
|
return combineClassNames(
|
|
1574
1663
|
"fc-list-group-item",
|
|
1575
1664
|
active && "fc-list-group-item--active",
|
|
@@ -1594,7 +1683,7 @@ var ListGroupItem = (0, import_react6.forwardRef)(
|
|
|
1594
1683
|
}
|
|
1595
1684
|
);
|
|
1596
1685
|
ListGroupItem.displayName = "ListGroupItem";
|
|
1597
|
-
var ListGroup = (0,
|
|
1686
|
+
var ListGroup = (0, import_react7.forwardRef)(
|
|
1598
1687
|
({
|
|
1599
1688
|
bordered = true,
|
|
1600
1689
|
flush = false,
|
|
@@ -1602,7 +1691,7 @@ var ListGroup = (0, import_react6.forwardRef)(
|
|
|
1602
1691
|
children,
|
|
1603
1692
|
...props
|
|
1604
1693
|
}, ref) => {
|
|
1605
|
-
const classNames = (0,
|
|
1694
|
+
const classNames = (0, import_react7.useMemo)(() => {
|
|
1606
1695
|
return combineClassNames(
|
|
1607
1696
|
"fc-list-group",
|
|
1608
1697
|
bordered && "fc-list-group--bordered",
|
|
@@ -1625,8 +1714,10 @@ var ListGroup = (0, import_react6.forwardRef)(
|
|
|
1625
1714
|
ListGroup.displayName = "ListGroup";
|
|
1626
1715
|
|
|
1627
1716
|
// src/components/VirtualList/VirtualList.tsx
|
|
1628
|
-
var
|
|
1717
|
+
var import_react8 = require("react");
|
|
1629
1718
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1719
|
+
var VirtualItem = (0, import_react8.memo)(({ children, height }) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "fc-virtual-list__item", style: { height: `${height}px` }, children }));
|
|
1720
|
+
VirtualItem.displayName = "VirtualItem";
|
|
1630
1721
|
function VirtualList({
|
|
1631
1722
|
data,
|
|
1632
1723
|
height,
|
|
@@ -1638,10 +1729,10 @@ function VirtualList({
|
|
|
1638
1729
|
onScrollEnd,
|
|
1639
1730
|
style
|
|
1640
1731
|
}) {
|
|
1641
|
-
const containerRef = (0,
|
|
1642
|
-
const [scrollTop, setScrollTop] = (0,
|
|
1732
|
+
const containerRef = (0, import_react8.useRef)(null);
|
|
1733
|
+
const [scrollTop, setScrollTop] = (0, import_react8.useState)(0);
|
|
1643
1734
|
const totalHeight = data.length * itemHeight;
|
|
1644
|
-
const handleScroll = (0,
|
|
1735
|
+
const handleScroll = (0, import_react8.useCallback)((e) => {
|
|
1645
1736
|
const newScrollTop = e.currentTarget.scrollTop;
|
|
1646
1737
|
setScrollTop(newScrollTop);
|
|
1647
1738
|
if (onScrollEnd) {
|
|
@@ -1652,7 +1743,7 @@ function VirtualList({
|
|
|
1652
1743
|
}
|
|
1653
1744
|
}
|
|
1654
1745
|
}, [onScrollEnd]);
|
|
1655
|
-
const visibleRange = (0,
|
|
1746
|
+
const visibleRange = (0, import_react8.useMemo)(() => {
|
|
1656
1747
|
const startIndex = Math.max(0, Math.floor(scrollTop / itemHeight) - overscan);
|
|
1657
1748
|
const endIndex = Math.min(
|
|
1658
1749
|
data.length,
|
|
@@ -1660,15 +1751,10 @@ function VirtualList({
|
|
|
1660
1751
|
);
|
|
1661
1752
|
return { startIndex, endIndex };
|
|
1662
1753
|
}, [scrollTop, height, itemHeight, data.length, overscan]);
|
|
1663
|
-
const visibleData = (0,
|
|
1754
|
+
const visibleData = (0, import_react8.useMemo)(() => {
|
|
1664
1755
|
return data.slice(visibleRange.startIndex, visibleRange.endIndex);
|
|
1665
1756
|
}, [data, visibleRange]);
|
|
1666
1757
|
const offsetY = visibleRange.startIndex * itemHeight;
|
|
1667
|
-
(0, import_react7.useEffect)(() => {
|
|
1668
|
-
if (!showScrollbar && containerRef.current) {
|
|
1669
|
-
containerRef.current.style.scrollbarWidth = "none";
|
|
1670
|
-
}
|
|
1671
|
-
}, [showScrollbar]);
|
|
1672
1758
|
const classNames = [
|
|
1673
1759
|
"fc-virtual-list",
|
|
1674
1760
|
!showScrollbar && "fc-virtual-list--hide-scrollbar",
|
|
@@ -1693,15 +1779,7 @@ function VirtualList({
|
|
|
1693
1779
|
style: { transform: `translateY(${offsetY}px)` },
|
|
1694
1780
|
children: visibleData.map((item, idx) => {
|
|
1695
1781
|
const actualIndex = visibleRange.startIndex + idx;
|
|
1696
|
-
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1697
|
-
"div",
|
|
1698
|
-
{
|
|
1699
|
-
className: "fc-virtual-list__item",
|
|
1700
|
-
style: { height: `${itemHeight}px` },
|
|
1701
|
-
children: renderItem(item, actualIndex)
|
|
1702
|
-
},
|
|
1703
|
-
actualIndex
|
|
1704
|
-
);
|
|
1782
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(VirtualItem, { height: itemHeight, children: renderItem(item, actualIndex) }, actualIndex);
|
|
1705
1783
|
})
|
|
1706
1784
|
}
|
|
1707
1785
|
)
|
|
@@ -1712,9 +1790,9 @@ function VirtualList({
|
|
|
1712
1790
|
}
|
|
1713
1791
|
|
|
1714
1792
|
// src/components/Alert/AlertContext.tsx
|
|
1715
|
-
var
|
|
1793
|
+
var import_react9 = require("react");
|
|
1716
1794
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1717
|
-
var AlertContext = (0,
|
|
1795
|
+
var AlertContext = (0, import_react9.createContext)(null);
|
|
1718
1796
|
var ICONS = {
|
|
1719
1797
|
success: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
1720
1798
|
"svg",
|
|
@@ -1788,65 +1866,82 @@ var ICONS = {
|
|
|
1788
1866
|
}
|
|
1789
1867
|
)
|
|
1790
1868
|
};
|
|
1791
|
-
function AlertProvider({ children }) {
|
|
1792
|
-
const [
|
|
1869
|
+
function AlertProvider({ children, background, borderColor }) {
|
|
1870
|
+
const [alert, setAlert] = (0, import_react9.useState)({
|
|
1793
1871
|
msg: "",
|
|
1794
1872
|
type: "info",
|
|
1873
|
+
mode: "alert",
|
|
1795
1874
|
visible: false,
|
|
1796
1875
|
choice: () => {
|
|
1797
1876
|
}
|
|
1798
1877
|
});
|
|
1799
|
-
const showAlert = (msg, type,
|
|
1800
|
-
|
|
1878
|
+
const showAlert = (msg, type, mode = "alert", duration) => new Promise((resolve) => {
|
|
1879
|
+
setAlert({
|
|
1801
1880
|
msg,
|
|
1802
1881
|
type,
|
|
1882
|
+
mode,
|
|
1803
1883
|
visible: true,
|
|
1804
|
-
|
|
1884
|
+
duration,
|
|
1805
1885
|
choice: (res) => {
|
|
1806
|
-
|
|
1886
|
+
setAlert((p) => ({ ...p, visible: false }));
|
|
1807
1887
|
resolve(res);
|
|
1808
1888
|
}
|
|
1809
1889
|
});
|
|
1810
1890
|
});
|
|
1891
|
+
(0, import_react9.useEffect)(() => {
|
|
1892
|
+
if (!alert.visible || !alert.duration) return;
|
|
1893
|
+
const timer = setTimeout(() => alert.choice("auto"), alert.duration);
|
|
1894
|
+
return () => clearTimeout(timer);
|
|
1895
|
+
}, [alert.visible, alert.duration]);
|
|
1896
|
+
const overrideStyle = {};
|
|
1897
|
+
if (background !== void 0) overrideStyle["--alert-bg"] = background;
|
|
1898
|
+
if (borderColor !== void 0) overrideStyle["--alert-border"] = borderColor;
|
|
1811
1899
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(AlertContext.Provider, { value: { showAlert }, children: [
|
|
1812
1900
|
children,
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1901
|
+
alert.visible && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "fc-alert-overlay", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
1902
|
+
"div",
|
|
1903
|
+
{
|
|
1904
|
+
className: `fc-alert fc-alert--${alert.type} fc-alert--${alert.mode}`,
|
|
1905
|
+
style: overrideStyle,
|
|
1906
|
+
children: [
|
|
1907
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "fc-alert__header", children: [
|
|
1908
|
+
ICONS[alert.type],
|
|
1909
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "fc-alert__title", children: "\u63D0\u793A" })
|
|
1910
|
+
] }),
|
|
1911
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(RollingBox, { className: "fc-alert__msg", children: alert.msg }),
|
|
1912
|
+
alert.mode !== "toast" && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "fc-alert__footer", children: [
|
|
1913
|
+
alert.mode === "confirm" && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1914
|
+
Button,
|
|
1915
|
+
{
|
|
1916
|
+
variant: "secondary",
|
|
1917
|
+
size: "sm",
|
|
1918
|
+
onClick: () => alert.choice("no"),
|
|
1919
|
+
children: "\u53D6\u6D88"
|
|
1920
|
+
}
|
|
1921
|
+
),
|
|
1922
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1923
|
+
Button,
|
|
1924
|
+
{
|
|
1925
|
+
variant: "primary",
|
|
1926
|
+
size: "sm",
|
|
1927
|
+
onClick: () => alert.choice("yes"),
|
|
1928
|
+
children: "\u786E\u5B9A"
|
|
1929
|
+
}
|
|
1930
|
+
)
|
|
1931
|
+
] })
|
|
1932
|
+
]
|
|
1933
|
+
}
|
|
1934
|
+
) })
|
|
1840
1935
|
] });
|
|
1841
1936
|
}
|
|
1842
|
-
var useAlert = () => (0,
|
|
1937
|
+
var useAlert = () => (0, import_react9.useContext)(AlertContext);
|
|
1843
1938
|
|
|
1844
1939
|
// src/components/LazyLoad/LazyLoad.tsx
|
|
1845
|
-
var
|
|
1940
|
+
var import_react10 = require("react");
|
|
1846
1941
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1847
1942
|
function lazyLoad(importFn, options = {}) {
|
|
1848
1943
|
const { fallback = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(LazySpinner, {}), timeout = 1e4 } = options;
|
|
1849
|
-
const LazyComponent = (0,
|
|
1944
|
+
const LazyComponent = (0, import_react10.lazy)(() => {
|
|
1850
1945
|
let timeoutId;
|
|
1851
1946
|
const loadPromise = Promise.race([
|
|
1852
1947
|
importFn(),
|
|
@@ -1856,7 +1951,7 @@ function lazyLoad(importFn, options = {}) {
|
|
|
1856
1951
|
]).finally(() => clearTimeout(timeoutId));
|
|
1857
1952
|
return loadPromise;
|
|
1858
1953
|
});
|
|
1859
|
-
return (props) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1954
|
+
return (props) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react10.Suspense, { fallback, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(LazyComponent, { ...props }) });
|
|
1860
1955
|
}
|
|
1861
1956
|
function LazySpinner() {
|
|
1862
1957
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "fc-lazy-spinner", children: [
|
|
@@ -1928,344 +2023,779 @@ var Card = ({
|
|
|
1928
2023
|
] });
|
|
1929
2024
|
};
|
|
1930
2025
|
|
|
1931
|
-
// src/components/
|
|
1932
|
-
var
|
|
2026
|
+
// src/components/Bar/TabBar.tsx
|
|
2027
|
+
var import_react11 = require("react");
|
|
1933
2028
|
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1934
|
-
var
|
|
2029
|
+
var TabItemView = (0, import_react11.memo)(({
|
|
2030
|
+
item,
|
|
2031
|
+
isActive,
|
|
2032
|
+
closable,
|
|
2033
|
+
draggable,
|
|
2034
|
+
tabClassName,
|
|
2035
|
+
activeTabClassName,
|
|
2036
|
+
tabStyle,
|
|
2037
|
+
activeTabStyle,
|
|
2038
|
+
renderCloseIcon,
|
|
2039
|
+
onClick,
|
|
2040
|
+
onClose,
|
|
2041
|
+
onDragStart,
|
|
2042
|
+
onDragOver,
|
|
2043
|
+
onDrop,
|
|
2044
|
+
onDragEnd
|
|
2045
|
+
}) => {
|
|
2046
|
+
const showClose = item.closable !== void 0 ? item.closable : closable;
|
|
2047
|
+
const classes = [
|
|
2048
|
+
"fc-tab-bar__tab",
|
|
2049
|
+
isActive && "fc-tab-bar__tab--active",
|
|
2050
|
+
item.disabled && "fc-tab-bar__tab--disabled",
|
|
2051
|
+
draggable && !item.disabled && "fc-tab-bar__tab--draggable",
|
|
2052
|
+
tabClassName,
|
|
2053
|
+
isActive && activeTabClassName
|
|
2054
|
+
].filter(Boolean).join(" ");
|
|
2055
|
+
const mergedStyle = {
|
|
2056
|
+
...tabStyle,
|
|
2057
|
+
...isActive ? activeTabStyle : void 0
|
|
2058
|
+
};
|
|
2059
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
2060
|
+
"div",
|
|
2061
|
+
{
|
|
2062
|
+
className: classes,
|
|
2063
|
+
style: mergedStyle,
|
|
2064
|
+
onClick: () => !item.disabled && onClick(item.key),
|
|
2065
|
+
draggable: draggable && !item.disabled,
|
|
2066
|
+
onDragStart: (e) => onDragStart(e, item.key),
|
|
2067
|
+
onDragOver,
|
|
2068
|
+
onDrop: (e) => onDrop(e, item.key),
|
|
2069
|
+
onDragEnd,
|
|
2070
|
+
role: "tab",
|
|
2071
|
+
"aria-selected": isActive,
|
|
2072
|
+
"aria-disabled": item.disabled,
|
|
2073
|
+
tabIndex: item.disabled ? -1 : 0,
|
|
2074
|
+
children: [
|
|
2075
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "fc-tab-bar__tab-label", children: item.label }),
|
|
2076
|
+
showClose && !item.disabled && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2077
|
+
"span",
|
|
2078
|
+
{
|
|
2079
|
+
className: "fc-tab-bar__tab-close",
|
|
2080
|
+
onClick: (e) => onClose(e, item.key),
|
|
2081
|
+
role: "button",
|
|
2082
|
+
"aria-label": `\u5173\u95ED ${typeof item.label === "string" ? item.label : ""}`,
|
|
2083
|
+
children: renderCloseIcon ? renderCloseIcon(item.key) : "\xD7"
|
|
2084
|
+
}
|
|
2085
|
+
)
|
|
2086
|
+
]
|
|
2087
|
+
}
|
|
2088
|
+
);
|
|
2089
|
+
});
|
|
2090
|
+
TabItemView.displayName = "TabItemView";
|
|
2091
|
+
var TabBar = (0, import_react11.memo)(({
|
|
1935
2092
|
items,
|
|
1936
|
-
activeKey
|
|
1937
|
-
|
|
2093
|
+
activeKey,
|
|
2094
|
+
variant = "attached",
|
|
1938
2095
|
radius = "md",
|
|
2096
|
+
tabRadius,
|
|
1939
2097
|
closable = false,
|
|
1940
2098
|
addable = false,
|
|
2099
|
+
draggable = false,
|
|
1941
2100
|
onChange,
|
|
1942
2101
|
onClose,
|
|
1943
2102
|
onAdd,
|
|
2103
|
+
onReorder,
|
|
2104
|
+
tabClassName,
|
|
2105
|
+
activeTabClassName,
|
|
2106
|
+
tabStyle,
|
|
2107
|
+
activeTabStyle,
|
|
2108
|
+
renderCloseIcon,
|
|
2109
|
+
renderAddButton,
|
|
1944
2110
|
className = "",
|
|
1945
|
-
style
|
|
2111
|
+
style,
|
|
2112
|
+
background,
|
|
2113
|
+
tabColor,
|
|
2114
|
+
tabHoverColor,
|
|
2115
|
+
tabHoverBackground,
|
|
2116
|
+
tabActiveColor,
|
|
2117
|
+
tabActiveBackground,
|
|
2118
|
+
activeIndicatorColor
|
|
1946
2119
|
}) => {
|
|
1947
|
-
const
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
}
|
|
1956
|
-
onChange?.(key);
|
|
2120
|
+
const colorVars = {
|
|
2121
|
+
"--tab-bar-bg": background,
|
|
2122
|
+
"--tab-color": tabColor,
|
|
2123
|
+
"--tab-hover-color": tabHoverColor,
|
|
2124
|
+
"--tab-hover-bg": tabHoverBackground,
|
|
2125
|
+
"--tab-active-color": tabActiveColor,
|
|
2126
|
+
"--tab-active-bg": tabActiveBackground,
|
|
2127
|
+
"--tab-active-indicator": activeIndicatorColor
|
|
1957
2128
|
};
|
|
1958
|
-
const
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
const currentIndex = items.findIndex((item) => item.key === key);
|
|
1963
|
-
const nextItem = items[currentIndex + 1] || items[currentIndex - 1];
|
|
1964
|
-
if (nextItem && !nextItem.disabled) {
|
|
1965
|
-
handleTabClick(nextItem.key);
|
|
1966
|
-
}
|
|
2129
|
+
const overrideStyle = {};
|
|
2130
|
+
for (const [key, value] of Object.entries(colorVars)) {
|
|
2131
|
+
if (value !== void 0) {
|
|
2132
|
+
overrideStyle[key] = value;
|
|
1967
2133
|
}
|
|
1968
|
-
}
|
|
1969
|
-
const
|
|
1970
|
-
|
|
1971
|
-
|
|
2134
|
+
}
|
|
2135
|
+
const mergedStyle = { ...overrideStyle, ...style };
|
|
2136
|
+
const dragKeyRef = (0, import_react11.useRef)(null);
|
|
2137
|
+
const handleClick = (0, import_react11.useCallback)(
|
|
2138
|
+
(key) => onChange(key),
|
|
2139
|
+
[onChange]
|
|
2140
|
+
);
|
|
2141
|
+
const handleClose = (0, import_react11.useCallback)(
|
|
2142
|
+
(e, key) => {
|
|
2143
|
+
e.stopPropagation();
|
|
2144
|
+
onClose?.(key);
|
|
2145
|
+
},
|
|
2146
|
+
[onClose]
|
|
2147
|
+
);
|
|
2148
|
+
const handleDragStart = (0, import_react11.useCallback)(
|
|
2149
|
+
(e, key) => {
|
|
2150
|
+
dragKeyRef.current = key;
|
|
2151
|
+
e.dataTransfer.effectAllowed = "move";
|
|
2152
|
+
const target = e.currentTarget;
|
|
2153
|
+
requestAnimationFrame(() => target.classList.add("fc-tab-bar__tab--dragging"));
|
|
2154
|
+
},
|
|
2155
|
+
[]
|
|
2156
|
+
);
|
|
2157
|
+
const handleDragOver = (0, import_react11.useCallback)((e) => {
|
|
2158
|
+
e.preventDefault();
|
|
2159
|
+
e.dataTransfer.dropEffect = "move";
|
|
2160
|
+
}, []);
|
|
2161
|
+
const handleDrop = (0, import_react11.useCallback)(
|
|
2162
|
+
(e, targetKey) => {
|
|
2163
|
+
e.preventDefault();
|
|
2164
|
+
const dragKey = dragKeyRef.current;
|
|
2165
|
+
if (!dragKey || dragKey === targetKey || !onReorder) return;
|
|
2166
|
+
const fromIndex = items.findIndex((i) => i.key === dragKey);
|
|
2167
|
+
const toIndex = items.findIndex((i) => i.key === targetKey);
|
|
2168
|
+
if (fromIndex === -1 || toIndex === -1) return;
|
|
2169
|
+
const reordered = [...items];
|
|
2170
|
+
const [moved] = reordered.splice(fromIndex, 1);
|
|
2171
|
+
reordered.splice(toIndex, 0, moved);
|
|
2172
|
+
onReorder(reordered);
|
|
2173
|
+
},
|
|
2174
|
+
[items, onReorder]
|
|
2175
|
+
);
|
|
2176
|
+
const handleDragEnd = (0, import_react11.useCallback)((e) => {
|
|
2177
|
+
dragKeyRef.current = null;
|
|
2178
|
+
e.currentTarget.classList.remove("fc-tab-bar__tab--dragging");
|
|
2179
|
+
}, []);
|
|
2180
|
+
const rootClasses = [
|
|
2181
|
+
"fc-tab-bar",
|
|
2182
|
+
`fc-tab-bar--${variant}`,
|
|
2183
|
+
`fc-tab-bar--radius-${radius}`,
|
|
2184
|
+
tabRadius && `fc-tab-bar--tab-radius-${tabRadius}`,
|
|
1972
2185
|
className
|
|
1973
2186
|
].filter(Boolean).join(" ");
|
|
1974
|
-
return /* @__PURE__ */ (0, import_jsx_runtime18.
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2187
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: rootClasses, style: mergedStyle, role: "tablist", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "fc-tab-bar__nav", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "fc-tab-bar__nav-wrap", children: [
|
|
2188
|
+
items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2189
|
+
TabItemView,
|
|
2190
|
+
{
|
|
2191
|
+
item,
|
|
2192
|
+
isActive: activeKey === item.key,
|
|
2193
|
+
closable,
|
|
2194
|
+
draggable,
|
|
2195
|
+
tabClassName,
|
|
2196
|
+
activeTabClassName,
|
|
2197
|
+
tabStyle,
|
|
2198
|
+
activeTabStyle,
|
|
2199
|
+
renderCloseIcon,
|
|
2200
|
+
onClick: handleClick,
|
|
2201
|
+
onClose: handleClose,
|
|
2202
|
+
onDragStart: handleDragStart,
|
|
2203
|
+
onDragOver: handleDragOver,
|
|
2204
|
+
onDrop: handleDrop,
|
|
2205
|
+
onDragEnd: handleDragEnd
|
|
2206
|
+
},
|
|
2207
|
+
item.key
|
|
2208
|
+
)),
|
|
2209
|
+
addable && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2210
|
+
"div",
|
|
2211
|
+
{
|
|
2212
|
+
className: "fc-tab-bar__add-btn",
|
|
2213
|
+
onClick: onAdd,
|
|
2214
|
+
role: "button",
|
|
2215
|
+
"aria-label": "\u6DFB\u52A0\u6807\u7B7E",
|
|
2216
|
+
children: renderAddButton ? renderAddButton() : "+"
|
|
2217
|
+
}
|
|
2218
|
+
)
|
|
2219
|
+
] }) }) });
|
|
2220
|
+
});
|
|
2221
|
+
TabBar.displayName = "TabBar";
|
|
2003
2222
|
|
|
2004
|
-
// src/components/
|
|
2005
|
-
var
|
|
2223
|
+
// src/components/Tag/TagItem.tsx
|
|
2224
|
+
var import_react12 = require("react");
|
|
2006
2225
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
const
|
|
2028
|
-
const [
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2226
|
+
function TagItem({
|
|
2227
|
+
schema,
|
|
2228
|
+
value,
|
|
2229
|
+
onChange,
|
|
2230
|
+
mode = "show",
|
|
2231
|
+
background,
|
|
2232
|
+
color,
|
|
2233
|
+
borderColor
|
|
2234
|
+
}) {
|
|
2235
|
+
const [editing, setEditing] = (0, import_react12.useState)(false);
|
|
2236
|
+
const [draft, setDraft] = (0, import_react12.useState)(() => value !== void 0 ? String(value) : "");
|
|
2237
|
+
const inputRef = (0, import_react12.useRef)(null);
|
|
2238
|
+
(0, import_react12.useEffect)(() => {
|
|
2239
|
+
if (!editing) setDraft(value !== void 0 ? String(value) : "");
|
|
2240
|
+
}, [value, editing]);
|
|
2241
|
+
const colorVars = {
|
|
2242
|
+
"--tag-bg": background,
|
|
2243
|
+
"--tag-color": color,
|
|
2244
|
+
"--tag-border": borderColor
|
|
2245
|
+
};
|
|
2246
|
+
const overrideStyle = {};
|
|
2247
|
+
for (const [k, v] of Object.entries(colorVars)) {
|
|
2248
|
+
if (v !== void 0) overrideStyle[k] = v;
|
|
2249
|
+
}
|
|
2250
|
+
if (schema.type === "boolean") {
|
|
2251
|
+
const boolVal = value === true || value === "true";
|
|
2252
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
2253
|
+
"span",
|
|
2254
|
+
{
|
|
2255
|
+
className: "fc-tag-item fc-tag-item--boolean",
|
|
2256
|
+
style: overrideStyle,
|
|
2257
|
+
onClick: () => onChange?.(!boolVal),
|
|
2258
|
+
title: "\u70B9\u51FB\u5207\u6362",
|
|
2259
|
+
children: [
|
|
2260
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "fc-tag-item__name", children: schema.name }),
|
|
2261
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "fc-tag-item__sep", children: "\xB7" }),
|
|
2262
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: boolVal ? "fc-tag-item__bool-true" : "fc-tag-item__bool-false", children: boolVal ? "\u2713" : "\u2717" })
|
|
2263
|
+
]
|
|
2264
|
+
}
|
|
2265
|
+
);
|
|
2266
|
+
}
|
|
2267
|
+
const commit = () => {
|
|
2268
|
+
if (schema.type === "number") {
|
|
2269
|
+
const n = parseFloat(draft);
|
|
2270
|
+
if (!isNaN(n)) {
|
|
2271
|
+
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;
|
|
2272
|
+
onChange?.(clamped);
|
|
2273
|
+
}
|
|
2036
2274
|
} else {
|
|
2037
|
-
|
|
2038
|
-
const dataTheme = document.documentElement.getAttribute("data-theme");
|
|
2039
|
-
if (dataTheme === "dark") {
|
|
2040
|
-
setCurrentTheme("dark");
|
|
2041
|
-
} else if (dataTheme === "light") {
|
|
2042
|
-
setCurrentTheme("light");
|
|
2043
|
-
} else {
|
|
2044
|
-
const hasDarkClass = document.documentElement.classList.contains("dark") || document.body.classList.contains("dark") || document.documentElement.classList.contains("theme-dark") || document.body.classList.contains("theme-dark");
|
|
2045
|
-
setCurrentTheme(hasDarkClass ? "dark" : "light");
|
|
2046
|
-
}
|
|
2047
|
-
};
|
|
2048
|
-
checkTheme();
|
|
2049
|
-
const observer = new MutationObserver(checkTheme);
|
|
2050
|
-
observer.observe(document.documentElement, {
|
|
2051
|
-
attributes: true,
|
|
2052
|
-
attributeFilter: ["data-theme", "class"]
|
|
2053
|
-
});
|
|
2054
|
-
observer.observe(document.body, {
|
|
2055
|
-
attributes: true,
|
|
2056
|
-
attributeFilter: ["class"]
|
|
2057
|
-
});
|
|
2058
|
-
return () => observer.disconnect();
|
|
2275
|
+
onChange?.(draft);
|
|
2059
2276
|
}
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2277
|
+
if (mode === "show") setEditing(false);
|
|
2278
|
+
};
|
|
2279
|
+
const cancel = () => {
|
|
2280
|
+
setDraft(value !== void 0 ? String(value) : "");
|
|
2281
|
+
if (mode === "show") setEditing(false);
|
|
2282
|
+
};
|
|
2283
|
+
const isEditing = mode === "edit" || editing;
|
|
2284
|
+
if (isEditing) {
|
|
2285
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "fc-tag-item fc-tag-item--editing", style: overrideStyle, children: [
|
|
2286
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "fc-tag-item__name", children: schema.name }),
|
|
2287
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "fc-tag-item__sep", children: "\xB7" }),
|
|
2288
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2289
|
+
"input",
|
|
2290
|
+
{
|
|
2291
|
+
ref: inputRef,
|
|
2292
|
+
className: "fc-tag-item__input",
|
|
2293
|
+
type: schema.type === "number" ? "number" : "text",
|
|
2294
|
+
value: draft,
|
|
2295
|
+
min: schema.range_min ?? void 0,
|
|
2296
|
+
max: schema.range_max ?? void 0,
|
|
2297
|
+
autoFocus: true,
|
|
2298
|
+
onChange: (e) => setDraft(e.target.value),
|
|
2299
|
+
onBlur: commit,
|
|
2300
|
+
onKeyDown: (e) => {
|
|
2301
|
+
if (e.key === "Enter") {
|
|
2302
|
+
e.preventDefault();
|
|
2303
|
+
commit();
|
|
2304
|
+
}
|
|
2305
|
+
if (e.key === "Escape") {
|
|
2306
|
+
e.preventDefault();
|
|
2307
|
+
cancel();
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
)
|
|
2312
|
+
] });
|
|
2313
|
+
}
|
|
2314
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
2315
|
+
"span",
|
|
2316
|
+
{
|
|
2317
|
+
className: "fc-tag-item fc-tag-item--show",
|
|
2318
|
+
style: overrideStyle,
|
|
2319
|
+
onDoubleClick: () => {
|
|
2320
|
+
setDraft(value !== void 0 ? String(value) : "");
|
|
2321
|
+
setEditing(true);
|
|
2322
|
+
setTimeout(() => inputRef.current?.select(), 0);
|
|
2323
|
+
},
|
|
2324
|
+
title: "\u53CC\u51FB\u7F16\u8F91",
|
|
2325
|
+
children: [
|
|
2326
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "fc-tag-item__name", children: schema.name }),
|
|
2327
|
+
value !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
2328
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "fc-tag-item__sep", children: "\xB7" }),
|
|
2329
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "fc-tag-item__value", children: String(value) })
|
|
2330
|
+
] })
|
|
2331
|
+
]
|
|
2075
2332
|
}
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2333
|
+
);
|
|
2334
|
+
}
|
|
2335
|
+
|
|
2336
|
+
// src/components/MarkdownEditor/MarkdownEditor.tsx
|
|
2337
|
+
var import_react_md_editor = __toESM(require("@uiw/react-md-editor"), 1);
|
|
2338
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2339
|
+
var TOOLBAR_COMMANDS = [
|
|
2340
|
+
import_react_md_editor.commands.bold,
|
|
2341
|
+
import_react_md_editor.commands.italic,
|
|
2342
|
+
import_react_md_editor.commands.strikethrough,
|
|
2343
|
+
import_react_md_editor.commands.divider,
|
|
2344
|
+
import_react_md_editor.commands.title1,
|
|
2345
|
+
import_react_md_editor.commands.title2,
|
|
2346
|
+
import_react_md_editor.commands.title3,
|
|
2347
|
+
import_react_md_editor.commands.divider,
|
|
2348
|
+
import_react_md_editor.commands.quote,
|
|
2349
|
+
import_react_md_editor.commands.code,
|
|
2350
|
+
import_react_md_editor.commands.codeBlock,
|
|
2351
|
+
import_react_md_editor.commands.divider,
|
|
2352
|
+
import_react_md_editor.commands.link,
|
|
2353
|
+
import_react_md_editor.commands.unorderedListCommand,
|
|
2354
|
+
import_react_md_editor.commands.orderedListCommand,
|
|
2355
|
+
import_react_md_editor.commands.hr
|
|
2356
|
+
];
|
|
2357
|
+
function MarkdownEditor({
|
|
2358
|
+
value,
|
|
2359
|
+
onChange,
|
|
2360
|
+
onAiComplete,
|
|
2361
|
+
minHeight = 200,
|
|
2362
|
+
placeholder = "\u5728\u6B64\u8F93\u5165\u5185\u5BB9...",
|
|
2363
|
+
background,
|
|
2364
|
+
toolbarBackground,
|
|
2365
|
+
borderColor
|
|
2366
|
+
}) {
|
|
2367
|
+
const { resolvedTheme } = useTheme();
|
|
2368
|
+
const colorVars = {
|
|
2369
|
+
"--md-bg": background,
|
|
2370
|
+
"--md-toolbar-bg": toolbarBackground,
|
|
2371
|
+
"--md-border": borderColor
|
|
2372
|
+
};
|
|
2373
|
+
const overrideStyle = {};
|
|
2374
|
+
for (const [k, v] of Object.entries(colorVars)) {
|
|
2375
|
+
if (v !== void 0) overrideStyle[k] = v;
|
|
2376
|
+
}
|
|
2377
|
+
const aiCommand = {
|
|
2378
|
+
name: "ai-complete",
|
|
2379
|
+
keyCommand: "ai-complete",
|
|
2380
|
+
buttonProps: { "aria-label": "AI \u8865\u5168", className: "fc-md-ai-btn" },
|
|
2381
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { children: "AI \u8865\u5168" }),
|
|
2382
|
+
execute: () => onAiComplete?.()
|
|
2383
|
+
};
|
|
2384
|
+
const extraCommands = onAiComplete ? [import_react_md_editor.commands.divider, aiCommand, import_react_md_editor.commands.fullscreen] : [import_react_md_editor.commands.fullscreen];
|
|
2385
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2386
|
+
"div",
|
|
2387
|
+
{
|
|
2388
|
+
className: "fc-md-wrap",
|
|
2389
|
+
style: overrideStyle,
|
|
2390
|
+
"data-color-mode": resolvedTheme,
|
|
2391
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2392
|
+
import_react_md_editor.default,
|
|
2393
|
+
{
|
|
2394
|
+
value,
|
|
2395
|
+
onChange: (v) => onChange(v ?? ""),
|
|
2396
|
+
commands: TOOLBAR_COMMANDS,
|
|
2397
|
+
extraCommands,
|
|
2398
|
+
height: minHeight,
|
|
2399
|
+
preview: "edit",
|
|
2400
|
+
visibleDragbar: false,
|
|
2401
|
+
textareaProps: { placeholder }
|
|
2402
|
+
}
|
|
2403
|
+
)
|
|
2081
2404
|
}
|
|
2405
|
+
);
|
|
2406
|
+
}
|
|
2407
|
+
|
|
2408
|
+
// src/components/ContextMenu/ContextMenuContext.tsx
|
|
2409
|
+
var import_react13 = require("react");
|
|
2410
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2411
|
+
var ContextMenuContext = (0, import_react13.createContext)(null);
|
|
2412
|
+
function ContextMenuProvider({
|
|
2413
|
+
children,
|
|
2414
|
+
background,
|
|
2415
|
+
borderColor,
|
|
2416
|
+
hoverBackground
|
|
2417
|
+
}) {
|
|
2418
|
+
const [menu, setMenu] = (0, import_react13.useState)({
|
|
2419
|
+
visible: false,
|
|
2420
|
+
x: 0,
|
|
2421
|
+
y: 0,
|
|
2422
|
+
items: []
|
|
2423
|
+
});
|
|
2424
|
+
const menuRef = (0, import_react13.useRef)(null);
|
|
2425
|
+
const showContextMenu = (e, items) => {
|
|
2426
|
+
e.preventDefault();
|
|
2427
|
+
e.stopPropagation();
|
|
2428
|
+
setMenu({ visible: true, x: e.clientX, y: e.clientY, items });
|
|
2429
|
+
};
|
|
2430
|
+
const hide = () => setMenu((s) => ({ ...s, visible: false }));
|
|
2431
|
+
(0, import_react13.useEffect)(() => {
|
|
2432
|
+
if (!menu.visible) return;
|
|
2433
|
+
const onPointerDown = (e) => {
|
|
2434
|
+
if (menuRef.current && !menuRef.current.contains(e.target)) hide();
|
|
2435
|
+
};
|
|
2436
|
+
const onKeyDown = (e) => {
|
|
2437
|
+
if (e.key === "Escape") hide();
|
|
2438
|
+
};
|
|
2439
|
+
window.addEventListener("pointerdown", onPointerDown);
|
|
2440
|
+
window.addEventListener("keydown", onKeyDown);
|
|
2441
|
+
return () => {
|
|
2442
|
+
window.removeEventListener("pointerdown", onPointerDown);
|
|
2443
|
+
window.removeEventListener("keydown", onKeyDown);
|
|
2444
|
+
};
|
|
2445
|
+
}, [menu.visible]);
|
|
2446
|
+
const getPosition = () => {
|
|
2447
|
+
const W = window.innerWidth;
|
|
2448
|
+
const H = window.innerHeight;
|
|
2449
|
+
const menuW = 180;
|
|
2450
|
+
const menuH = menu.items.length * 32 + 12;
|
|
2451
|
+
return {
|
|
2452
|
+
left: menu.x + menuW > W ? menu.x - menuW : menu.x,
|
|
2453
|
+
top: menu.y + menuH > H ? menu.y - menuH : menu.y
|
|
2454
|
+
};
|
|
2455
|
+
};
|
|
2456
|
+
const colorVars = {
|
|
2457
|
+
"--ctx-bg": background,
|
|
2458
|
+
"--ctx-border": borderColor,
|
|
2459
|
+
"--ctx-item-hover-bg": hoverBackground
|
|
2460
|
+
};
|
|
2461
|
+
const overrideStyle = { ...getPosition() };
|
|
2462
|
+
for (const [k, v] of Object.entries(colorVars)) {
|
|
2463
|
+
if (v !== void 0) overrideStyle[k] = v;
|
|
2464
|
+
}
|
|
2465
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(ContextMenuContext.Provider, { value: { showContextMenu }, children: [
|
|
2466
|
+
children,
|
|
2467
|
+
menu.visible && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2468
|
+
"ul",
|
|
2469
|
+
{
|
|
2470
|
+
ref: menuRef,
|
|
2471
|
+
className: "fc-context-menu",
|
|
2472
|
+
style: overrideStyle,
|
|
2473
|
+
children: menu.items.map((item, i) => {
|
|
2474
|
+
if ("type" in item && item.type === "divider") {
|
|
2475
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("li", { className: "fc-context-menu__divider" }, i);
|
|
2476
|
+
}
|
|
2477
|
+
const action = item;
|
|
2478
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2479
|
+
"li",
|
|
2480
|
+
{
|
|
2481
|
+
className: [
|
|
2482
|
+
"fc-context-menu__item",
|
|
2483
|
+
action.danger ? "fc-context-menu__item--danger" : "",
|
|
2484
|
+
action.disabled ? "fc-context-menu__item--disabled" : ""
|
|
2485
|
+
].filter(Boolean).join(" "),
|
|
2486
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
2487
|
+
onClick: () => {
|
|
2488
|
+
if (action.disabled) return;
|
|
2489
|
+
action.onClick();
|
|
2490
|
+
hide();
|
|
2491
|
+
},
|
|
2492
|
+
children: [
|
|
2493
|
+
action.icon && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "fc-context-menu__icon", children: action.icon }),
|
|
2494
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "fc-context-menu__label", children: action.label })
|
|
2495
|
+
]
|
|
2496
|
+
},
|
|
2497
|
+
i
|
|
2498
|
+
);
|
|
2499
|
+
})
|
|
2500
|
+
}
|
|
2501
|
+
)
|
|
2502
|
+
] });
|
|
2503
|
+
}
|
|
2504
|
+
var useContextMenu = () => (0, import_react13.useContext)(ContextMenuContext);
|
|
2505
|
+
|
|
2506
|
+
// src/components/Chat/Chat.tsx
|
|
2507
|
+
var import_react15 = require("react");
|
|
2508
|
+
|
|
2509
|
+
// src/components/SmartMessage/SmartMessage.tsx
|
|
2510
|
+
var import_react14 = require("react");
|
|
2511
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
2512
|
+
var SmartMessage = (0, import_react14.memo)(({
|
|
2513
|
+
id,
|
|
2514
|
+
content,
|
|
2515
|
+
role,
|
|
2516
|
+
timestamp,
|
|
2517
|
+
status,
|
|
2518
|
+
toolName,
|
|
2519
|
+
toolResult,
|
|
2520
|
+
onCopy,
|
|
2521
|
+
className = "",
|
|
2522
|
+
style = {}
|
|
2523
|
+
}) => {
|
|
2524
|
+
const [copied, setCopied] = (0, import_react14.useState)(false);
|
|
2525
|
+
const formattedTime = timestamp ? new Date(timestamp).toLocaleTimeString("zh-CN", { hour: "2-digit", minute: "2-digit" }) : "";
|
|
2526
|
+
const handleCopy = async () => {
|
|
2082
2527
|
try {
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
}
|
|
2528
|
+
let copyContent = content;
|
|
2529
|
+
if (role === "tool" && toolResult) {
|
|
2530
|
+
copyContent = `\u5DE5\u5177: ${toolName || "\u5DE5\u5177\u8C03\u7528"}
|
|
2531
|
+
\u7ED3\u679C: ${JSON.stringify(toolResult, null, 2)}`;
|
|
2532
|
+
}
|
|
2533
|
+
await navigator.clipboard.writeText(copyContent);
|
|
2534
|
+
setCopied(true);
|
|
2535
|
+
onCopy?.(content, role);
|
|
2536
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
2088
2537
|
} catch (err) {
|
|
2089
2538
|
console.error("\u590D\u5236\u5931\u8D25:", err);
|
|
2090
|
-
if (err instanceof Error) {
|
|
2091
|
-
if (err.name === "NotAllowedError") {
|
|
2092
|
-
setCopyError("\u9700\u8981\u526A\u8D34\u677F\u6743\u9650\uFF0C\u8BF7\u5141\u8BB8\u540E\u91CD\u8BD5");
|
|
2093
|
-
} else if (err.name === "SecurityError") {
|
|
2094
|
-
setCopyError("\u51FA\u4E8E\u5B89\u5168\u539F\u56E0\uFF0C\u65E0\u6CD5\u590D\u5236\u5185\u5BB9");
|
|
2095
|
-
} else {
|
|
2096
|
-
setCopyError("\u590D\u5236\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5");
|
|
2097
|
-
}
|
|
2098
|
-
} else {
|
|
2099
|
-
setCopyError("\u590D\u5236\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5");
|
|
2100
|
-
}
|
|
2101
|
-
setTimeout(() => {
|
|
2102
|
-
setCopyError(null);
|
|
2103
|
-
}, 3e3);
|
|
2104
|
-
}
|
|
2105
|
-
}, []);
|
|
2106
|
-
const handleSend = (0, import_react11.useCallback)(() => {
|
|
2107
|
-
const trimmedMessage = inputValue.trim();
|
|
2108
|
-
if (!trimmedMessage || disabled || loading || isSending) return;
|
|
2109
|
-
if (trimmedMessage.length > maxInputLength) {
|
|
2110
|
-
console.warn(`\u6D88\u606F\u8D85\u8FC7\u6700\u5927\u957F\u5EA6\u9650\u5236: ${maxInputLength}`);
|
|
2111
|
-
return;
|
|
2112
2539
|
}
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2540
|
+
};
|
|
2541
|
+
const shouldShowCopyButton = () => {
|
|
2542
|
+
return role === "user" || role === "assistant";
|
|
2543
|
+
};
|
|
2544
|
+
const getContainerClassName = () => {
|
|
2545
|
+
const baseClass = "smart-message";
|
|
2546
|
+
const roleClass = `smart-message-${role}`;
|
|
2547
|
+
const statusClass = status ? `smart-message-${status}` : "";
|
|
2548
|
+
return `${baseClass} ${roleClass} ${statusClass} ${className}`.trim();
|
|
2549
|
+
};
|
|
2550
|
+
const getContentClassName = () => {
|
|
2551
|
+
const baseClass = "smart-message-content";
|
|
2552
|
+
const roleContentClass = `smart-message-content-${role}`;
|
|
2553
|
+
return `${baseClass} ${roleContentClass}`;
|
|
2554
|
+
};
|
|
2555
|
+
const renderSystemMessage = () => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "system-message-wrapper", children: [
|
|
2556
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "system-message-icon", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [
|
|
2557
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "2" }),
|
|
2558
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M12 8V12M12 16H12.01", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
|
|
2559
|
+
] }) }),
|
|
2560
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "system-message-text", children: content }),
|
|
2561
|
+
formattedTime && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "system-message-time", children: formattedTime })
|
|
2562
|
+
] });
|
|
2563
|
+
const renderToolMessage = () => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "tool-message-wrapper", children: [
|
|
2564
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "tool-message-header", children: [
|
|
2565
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "tool-message-icon", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: [
|
|
2566
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M14.7 6.3L19 2L22 5L17.7 9.3L14.7 6.3Z", stroke: "currentColor", strokeWidth: "2" }),
|
|
2567
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M9.3 17.7L5 22L2 19L6.3 14.7L9.3 17.7Z", stroke: "currentColor", strokeWidth: "2" }),
|
|
2568
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M12 12L14.7 9.3M12 12L9.3 14.7M12 12L8 8M12 12L16 16", stroke: "currentColor", strokeWidth: "2" })
|
|
2569
|
+
] }) }),
|
|
2570
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "tool-message-name", children: toolName || "\u5DE5\u5177\u8C03\u7528" })
|
|
2571
|
+
] }),
|
|
2572
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "tool-message-content", children: [
|
|
2573
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "tool-message-params", children: [
|
|
2574
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("strong", { children: "\u53C2\u6570:" }),
|
|
2575
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("pre", { children: content })
|
|
2576
|
+
] }),
|
|
2577
|
+
toolResult && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "tool-message-result", children: [
|
|
2578
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("strong", { children: "\u7ED3\u679C:" }),
|
|
2579
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("pre", { children: typeof toolResult === "object" ? JSON.stringify(toolResult, null, 2) : toolResult })
|
|
2580
|
+
] })
|
|
2581
|
+
] }),
|
|
2582
|
+
formattedTime && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "tool-message-time", children: formattedTime })
|
|
2583
|
+
] });
|
|
2584
|
+
const renderUserAssistantMessage = () => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
2585
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "message-header", children: [
|
|
2586
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "message-sender", children: role === "user" ? "\u6211" : "AI\u52A9\u624B" }),
|
|
2587
|
+
formattedTime && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "message-time", children: formattedTime })
|
|
2588
|
+
] }),
|
|
2589
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: getContentClassName(), children: [
|
|
2590
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "message-text", children: content }),
|
|
2591
|
+
shouldShowCopyButton() && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2592
|
+
"button",
|
|
2593
|
+
{
|
|
2594
|
+
className: `copy-btn ${copied ? "copied" : ""}`,
|
|
2595
|
+
onClick: handleCopy,
|
|
2596
|
+
title: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236\u5185\u5BB9",
|
|
2597
|
+
children: copied ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
2598
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M20 6L9 17L4 12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }),
|
|
2599
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { children: "\u5DF2\u590D\u5236" })
|
|
2600
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
2601
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", children: [
|
|
2602
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", stroke: "currentColor", strokeWidth: "2" }),
|
|
2603
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("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" })
|
|
2604
|
+
] }),
|
|
2605
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { children: "\u590D\u5236" })
|
|
2606
|
+
] })
|
|
2124
2607
|
}
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2608
|
+
),
|
|
2609
|
+
status === "sending" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "message-status sending", children: "\u53D1\u9001\u4E2D..." }),
|
|
2610
|
+
status === "error" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "message-status error", children: "\u53D1\u9001\u5931\u8D25" })
|
|
2611
|
+
] })
|
|
2612
|
+
] });
|
|
2613
|
+
const renderMessage = () => {
|
|
2614
|
+
switch (role) {
|
|
2615
|
+
case "system":
|
|
2616
|
+
return renderSystemMessage();
|
|
2617
|
+
case "tool":
|
|
2618
|
+
return renderToolMessage();
|
|
2619
|
+
case "user":
|
|
2620
|
+
case "assistant":
|
|
2621
|
+
default:
|
|
2622
|
+
return renderUserAssistantMessage();
|
|
2140
2623
|
}
|
|
2141
|
-
}
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2624
|
+
};
|
|
2625
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: getContainerClassName(), style, "data-message-id": id, children: renderMessage() });
|
|
2626
|
+
});
|
|
2627
|
+
SmartMessage.displayName = "SmartMessage";
|
|
2628
|
+
var SmartMessage_default = SmartMessage;
|
|
2629
|
+
|
|
2630
|
+
// src/components/Chat/Chat.tsx
|
|
2631
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
2632
|
+
var Chat = ({
|
|
2633
|
+
messages = [],
|
|
2634
|
+
title = "AI \u52A9\u624B",
|
|
2635
|
+
loading = false,
|
|
2636
|
+
conversations = [],
|
|
2637
|
+
currentConversationId,
|
|
2638
|
+
emptyText = "\u6682\u65E0\u5386\u53F2\u5BF9\u8BDD",
|
|
2639
|
+
newConversationText = "\u65B0\u5EFA\u5BF9\u8BDD",
|
|
2640
|
+
historyTitle = "\u5386\u53F2\u5BF9\u8BDD",
|
|
2641
|
+
showHistoryButton = true,
|
|
2642
|
+
showMinimizeButton = true,
|
|
2643
|
+
showHeader = true,
|
|
2644
|
+
showFooter = false,
|
|
2645
|
+
autoScroll = true,
|
|
2646
|
+
onSwitchConversation,
|
|
2647
|
+
onNewConversation,
|
|
2648
|
+
onDeleteConversation,
|
|
2649
|
+
onMinimize,
|
|
2650
|
+
onRestore,
|
|
2651
|
+
onMessageCopy,
|
|
2652
|
+
className = "",
|
|
2653
|
+
style = {},
|
|
2654
|
+
headerClassName = "",
|
|
2655
|
+
headerStyle = {},
|
|
2656
|
+
messagesClassName = "",
|
|
2657
|
+
messagesStyle = {},
|
|
2658
|
+
bubbleClassName = "",
|
|
2659
|
+
height = "600px",
|
|
2660
|
+
width
|
|
2661
|
+
}) => {
|
|
2662
|
+
const [showHistory, setShowHistory] = (0, import_react15.useState)(false);
|
|
2663
|
+
const [isMinimized, setIsMinimized] = (0, import_react15.useState)(false);
|
|
2664
|
+
const messagesContainerRef = (0, import_react15.useRef)(null);
|
|
2665
|
+
const messagesEndRef = (0, import_react15.useRef)(null);
|
|
2666
|
+
const historyPanelRef = (0, import_react15.useRef)(null);
|
|
2667
|
+
const currentConversation = (0, import_react15.useMemo)(
|
|
2668
|
+
() => conversations.find((c) => c.id === currentConversationId),
|
|
2669
|
+
[conversations, currentConversationId]
|
|
2670
|
+
);
|
|
2671
|
+
const currentTitle = currentConversation?.title || title;
|
|
2672
|
+
(0, import_react15.useEffect)(() => {
|
|
2673
|
+
if (autoScroll && messagesContainerRef.current && !showHistory && !isMinimized) {
|
|
2674
|
+
messagesContainerRef.current.scrollTop = messagesContainerRef.current.scrollHeight;
|
|
2146
2675
|
}
|
|
2147
|
-
}, [
|
|
2148
|
-
|
|
2149
|
-
const
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
e.target.style.height = "auto";
|
|
2153
|
-
e.target.style.height = `${Math.min(e.target.scrollHeight, 100)}px`;
|
|
2154
|
-
const hasContent = value.length > 0;
|
|
2155
|
-
if (hasContent !== isTyping) {
|
|
2156
|
-
setIsTyping(hasContent);
|
|
2157
|
-
onTyping?.(hasContent);
|
|
2676
|
+
}, [messages, loading, showHistory, isMinimized, autoScroll]);
|
|
2677
|
+
(0, import_react15.useEffect)(() => {
|
|
2678
|
+
const handleClickOutside = (event) => {
|
|
2679
|
+
if (showHistory && historyPanelRef.current && !historyPanelRef.current.contains(event.target)) {
|
|
2680
|
+
setShowHistory(false);
|
|
2158
2681
|
}
|
|
2682
|
+
};
|
|
2683
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
2684
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
2685
|
+
}, [showHistory]);
|
|
2686
|
+
const handleDeleteConversation = (0, import_react15.useCallback)((conversationId) => {
|
|
2687
|
+
onDeleteConversation?.(conversationId);
|
|
2688
|
+
}, [onDeleteConversation]);
|
|
2689
|
+
const handleMinimize = (0, import_react15.useCallback)(() => {
|
|
2690
|
+
setIsMinimized(true);
|
|
2691
|
+
onMinimize?.();
|
|
2692
|
+
}, [onMinimize]);
|
|
2693
|
+
const handleRestore = (0, import_react15.useCallback)(() => {
|
|
2694
|
+
setIsMinimized(false);
|
|
2695
|
+
onRestore?.();
|
|
2696
|
+
}, [onRestore]);
|
|
2697
|
+
const handleCopy = (0, import_react15.useCallback)((content) => {
|
|
2698
|
+
const message = messages.find((m) => m.content === content);
|
|
2699
|
+
if (message) {
|
|
2700
|
+
onMessageCopy?.(message);
|
|
2159
2701
|
}
|
|
2160
|
-
}, [
|
|
2161
|
-
const
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
/* @__PURE__ */ (0,
|
|
2178
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "message-sender", children: isUser ? userName : assistantName }),
|
|
2179
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "message-time", children: formatTime(message.timestamp) })
|
|
2180
|
-
] }),
|
|
2181
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "message-bubble", children: [
|
|
2182
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "message-text", children: message.content }),
|
|
2183
|
-
message.status === "sending" && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "message-status sending", children: "\u53D1\u9001\u4E2D..." }),
|
|
2184
|
-
message.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "message-status error", children: "\u53D1\u9001\u5931\u8D25" })
|
|
2185
|
-
] }),
|
|
2186
|
-
enableCopy && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2187
|
-
"button",
|
|
2188
|
-
{
|
|
2189
|
-
className: `copy-btn ${isCopied ? "copied" : ""}`,
|
|
2190
|
-
onClick: () => handleCopyMessage(message.id, message.content),
|
|
2191
|
-
title: isCopied ? "\u5DF2\u590D\u5236" : "\u590D\u5236\u5185\u5BB9",
|
|
2192
|
-
"aria-label": isCopied ? "\u5DF2\u590D\u5236" : "\u590D\u5236\u5185\u5BB9",
|
|
2193
|
-
children: isCopied ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
2194
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("path", { d: "M20 6L9 17L4 12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
|
|
2195
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: "\u5DF2\u590D\u5236" })
|
|
2196
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
2197
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
2198
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", stroke: "currentColor", strokeWidth: "2" }),
|
|
2199
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("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" })
|
|
2200
|
-
] }),
|
|
2201
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: "\u590D\u5236" })
|
|
2202
|
-
] })
|
|
2203
|
-
}
|
|
2204
|
-
)
|
|
2205
|
-
] })
|
|
2206
|
-
] }, message.id);
|
|
2207
|
-
};
|
|
2208
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: `chat-container ${currentTheme}`, style: { height }, children: [
|
|
2209
|
-
showHeader && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "chat-header", children: [
|
|
2210
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "chat-title", children: title }),
|
|
2211
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "chat-status", children: [
|
|
2212
|
-
(loading || isSending) && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "status-dot" }),
|
|
2213
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: loading || isSending ? "AI \u6B63\u5728\u601D\u8003..." : "\u5728\u7EBF" })
|
|
2702
|
+
}, [messages, onMessageCopy]);
|
|
2703
|
+
const containerStyle = (0, import_react15.useMemo)(() => ({
|
|
2704
|
+
height,
|
|
2705
|
+
width,
|
|
2706
|
+
...style
|
|
2707
|
+
}), [height, width, style]);
|
|
2708
|
+
if (isMinimized) {
|
|
2709
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: `chat-container-minimized ${className}`, style: containerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { className: "restore-btn-only", onClick: handleRestore, title: "\u5C55\u5F00", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("path", { d: "M12 5V19M5 12H19", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) }) });
|
|
2710
|
+
}
|
|
2711
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: `chat-container ${className}`, style: containerStyle, children: [
|
|
2712
|
+
showHeader && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: `chat-header ${headerClassName}`, style: headerStyle, children: [
|
|
2713
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "chat-title", children: currentTitle }),
|
|
2714
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "chat-header-actions", children: [
|
|
2715
|
+
showHistoryButton && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { className: "history-btn", onClick: () => setShowHistory(!showHistory), title: "\u5386\u53F2\u5BF9\u8BDD", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: [
|
|
2716
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("path", { d: "M12 8V12L15 15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
|
|
2717
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("circle", { cx: "12", cy: "12", r: "9", stroke: "currentColor", strokeWidth: "2" })
|
|
2718
|
+
] }) }),
|
|
2719
|
+
showMinimizeButton && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { className: "minimize-btn", onClick: handleMinimize, title: "\u6700\u5C0F\u5316", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("path", { d: "M5 12H19", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
|
|
2214
2720
|
] })
|
|
2215
2721
|
] }),
|
|
2216
|
-
/* @__PURE__ */ (0,
|
|
2217
|
-
messages.map(
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2722
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: `chat-messages ${messagesClassName}`, ref: messagesContainerRef, style: messagesStyle, children: [
|
|
2723
|
+
messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2724
|
+
SmartMessage_default,
|
|
2725
|
+
{
|
|
2726
|
+
id: message.id,
|
|
2727
|
+
content: message.content,
|
|
2728
|
+
role: message.type,
|
|
2729
|
+
timestamp: message.timestamp,
|
|
2730
|
+
status: message.status,
|
|
2731
|
+
toolName: message.toolName,
|
|
2732
|
+
toolResult: message.toolResult,
|
|
2733
|
+
onCopy: handleCopy,
|
|
2734
|
+
className: bubbleClassName
|
|
2735
|
+
},
|
|
2736
|
+
message.id
|
|
2737
|
+
)),
|
|
2738
|
+
loading && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "typing-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "typing-indicator", children: [
|
|
2739
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", {}),
|
|
2740
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", {}),
|
|
2741
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", {})
|
|
2742
|
+
] }) }),
|
|
2743
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { ref: messagesEndRef })
|
|
2230
2744
|
] }),
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
/* @__PURE__ */ (0,
|
|
2234
|
-
/* @__PURE__ */ (0,
|
|
2235
|
-
|
|
2236
|
-
{
|
|
2237
|
-
ref: inputRef,
|
|
2238
|
-
className: "chat-input",
|
|
2239
|
-
value: inputValue,
|
|
2240
|
-
onChange: handleInputChange,
|
|
2241
|
-
onKeyDown: handleKeyDown,
|
|
2242
|
-
placeholder,
|
|
2243
|
-
disabled: disabled || loading || isSending,
|
|
2244
|
-
rows: 1,
|
|
2245
|
-
maxLength: maxInputLength,
|
|
2246
|
-
spellCheck: false,
|
|
2247
|
-
autoCorrect: "off",
|
|
2248
|
-
autoCapitalize: "off",
|
|
2249
|
-
autoComplete: "off"
|
|
2250
|
-
}
|
|
2251
|
-
),
|
|
2252
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2253
|
-
"button",
|
|
2254
|
-
{
|
|
2255
|
-
className: `chat-send-btn ${!inputValue.trim() || disabled || loading || isSending ? "disabled" : ""}`,
|
|
2256
|
-
onClick: handleSend,
|
|
2257
|
-
disabled: !inputValue.trim() || disabled || loading || isSending,
|
|
2258
|
-
children: "\u53D1\u9001"
|
|
2259
|
-
}
|
|
2260
|
-
)
|
|
2745
|
+
showFooter && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "chat-footer" }),
|
|
2746
|
+
showHistory && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "history-panel", ref: historyPanelRef, children: [
|
|
2747
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "history-header", children: [
|
|
2748
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h3", { children: historyTitle }),
|
|
2749
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { className: "close-history-btn", onClick: () => setShowHistory(false), children: "\u2715" })
|
|
2261
2750
|
] }),
|
|
2262
|
-
/* @__PURE__ */ (0,
|
|
2263
|
-
/* @__PURE__ */ (0,
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2751
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "history-list", children: [
|
|
2752
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("button", { className: "new-conversation-btn-large", onClick: () => {
|
|
2753
|
+
onNewConversation?.();
|
|
2754
|
+
setShowHistory(false);
|
|
2755
|
+
}, children: [
|
|
2756
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("path", { d: "M12 5V19M5 12H19", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }),
|
|
2757
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: newConversationText })
|
|
2758
|
+
] }),
|
|
2759
|
+
conversations.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "empty-history", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { children: emptyText }) }) : conversations.map((conv) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
2760
|
+
"div",
|
|
2761
|
+
{
|
|
2762
|
+
className: `history-item ${currentConversationId === conv.id ? "active" : ""}`,
|
|
2763
|
+
onClick: () => {
|
|
2764
|
+
onSwitchConversation?.(conv.id);
|
|
2765
|
+
setShowHistory(false);
|
|
2766
|
+
},
|
|
2767
|
+
children: [
|
|
2768
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "history-item-content", children: [
|
|
2769
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "history-item-title", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: conv.title }) }),
|
|
2770
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "history-item-preview", children: conv.lastMessage }),
|
|
2771
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "history-item-meta", children: [
|
|
2772
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: new Date(conv.timestamp).toLocaleDateString() }),
|
|
2773
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("span", { children: [
|
|
2774
|
+
conv.messages.length,
|
|
2775
|
+
"\u6761\u6D88\u606F"
|
|
2776
|
+
] })
|
|
2777
|
+
] })
|
|
2778
|
+
] }),
|
|
2779
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "history-item-actions", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2780
|
+
"button",
|
|
2781
|
+
{
|
|
2782
|
+
className: "delete-conversation-btn",
|
|
2783
|
+
onClick: (e) => {
|
|
2784
|
+
e.stopPropagation();
|
|
2785
|
+
handleDeleteConversation(conv.id);
|
|
2786
|
+
},
|
|
2787
|
+
title: "\u5220\u9664\u5BF9\u8BDD",
|
|
2788
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", children: [
|
|
2789
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("path", { d: "M3 6H21", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
|
|
2790
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("path", { d: "M19 6V20C19 21.1 18.1 22 17 22H7C5.9 22 5 21.1 5 20V6", stroke: "currentColor", strokeWidth: "2" }),
|
|
2791
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("path", { d: "M8 6V4C8 2.9 8.9 2 10 2H14C15.1 2 16 2.9 16 4V6", stroke: "currentColor", strokeWidth: "2" })
|
|
2792
|
+
] })
|
|
2793
|
+
}
|
|
2794
|
+
) })
|
|
2795
|
+
]
|
|
2796
|
+
},
|
|
2797
|
+
conv.id
|
|
2798
|
+
))
|
|
2269
2799
|
] })
|
|
2270
2800
|
] })
|
|
2271
2801
|
] });
|
|
@@ -2280,16 +2810,20 @@ var Chat = ({
|
|
|
2280
2810
|
Card,
|
|
2281
2811
|
Chat,
|
|
2282
2812
|
CheckButton,
|
|
2813
|
+
ContextMenuProvider,
|
|
2283
2814
|
DeleteDialog,
|
|
2284
2815
|
Input,
|
|
2285
2816
|
ListGroup,
|
|
2286
2817
|
ListGroupItem,
|
|
2818
|
+
MarkdownEditor,
|
|
2287
2819
|
OrphanDialog,
|
|
2288
2820
|
RollingBox,
|
|
2289
2821
|
Select,
|
|
2290
2822
|
SideBar,
|
|
2291
2823
|
Slider,
|
|
2292
|
-
|
|
2824
|
+
SmartMessage,
|
|
2825
|
+
TabBar,
|
|
2826
|
+
TagItem,
|
|
2293
2827
|
ThemeProvider,
|
|
2294
2828
|
Tree,
|
|
2295
2829
|
VirtualList,
|
|
@@ -2298,5 +2832,6 @@ var Chat = ({
|
|
|
2298
2832
|
isDescendantOf,
|
|
2299
2833
|
lazyLoad,
|
|
2300
2834
|
useAlert,
|
|
2835
|
+
useContextMenu,
|
|
2301
2836
|
useTheme
|
|
2302
2837
|
});
|