dishui 0.0.91 → 0.0.101
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/.release-verified.json +6 -0
- package/dist/ai.js +24 -0
- package/dist/components/Card/Metric2.js +11 -11
- package/dist/components/Card/Metric2.js.map +1 -1
- package/dist/components/Card/Ticket.d.ts +52 -0
- package/dist/components/Card/Ticket2.js +218 -0
- package/dist/components/Card/Ticket2.js.map +1 -0
- package/dist/components/Card/index.d.ts +32 -0
- package/dist/components/Card/index.js +211 -203
- package/dist/components/Card/index.js.map +1 -1
- package/dist/components/GroupButton/index.js +4 -4
- package/dist/components/GroupButton/index.js.map +1 -1
- package/dist/components/GroupedTable/index.js +10 -10
- package/dist/components/GroupedTable/index.js.map +1 -1
- package/dist/components/NavigationList/index.js +9 -9
- package/dist/components/NavigationList/index.js.map +1 -1
- package/dist/components/Section/index.js +11 -11
- package/dist/components/Section/index.js.map +1 -1
- package/dist/components/Skeleton/index.js +1 -1
- package/dist/components/Skeleton/index.js.map +1 -1
- package/dist/components/Table/index.js +6 -6
- package/dist/components/Table/index.js.map +1 -1
- package/dist/components/ai/AgentChat/index.d.ts +54 -0
- package/dist/components/ai/AgentChat/index.js +176 -0
- package/dist/components/ai/AgentChat/index.js.map +1 -0
- package/dist/components/ai/AgentRunCard/index.d.ts +38 -0
- package/dist/components/ai/AgentRunCard/index.js +100 -0
- package/dist/components/ai/AgentRunCard/index.js.map +1 -0
- package/dist/components/ai/AgentScreen/index.d.ts +50 -0
- package/dist/components/ai/AgentScreen/index.js +233 -0
- package/dist/components/ai/AgentScreen/index.js.map +1 -0
- package/dist/components/ai/ApprovalCard/index.d.ts +26 -0
- package/dist/components/ai/ApprovalCard/index.js +89 -0
- package/dist/components/ai/ApprovalCard/index.js.map +1 -0
- package/dist/components/ai/CodeView/index.d.ts +30 -0
- package/dist/components/ai/CodeView/index.js +149 -0
- package/dist/components/ai/CodeView/index.js.map +1 -0
- package/dist/components/ai/CommandSearch/index.d.ts +39 -0
- package/dist/components/ai/CommandSearch/index.js +217 -0
- package/dist/components/ai/CommandSearch/index.js.map +1 -0
- package/dist/components/ai/ContextCards/index.d.ts +42 -0
- package/dist/components/ai/ContextCards/index.js +106 -0
- package/dist/components/ai/ContextCards/index.js.map +1 -0
- package/dist/components/ai/DiffTable/index.d.ts +70 -0
- package/dist/components/ai/DiffTable/index.js +235 -0
- package/dist/components/ai/DiffTable/index.js.map +1 -0
- package/dist/components/ai/FilterTable/index.d.ts +35 -0
- package/dist/components/ai/FilterTable/index.js +86 -0
- package/dist/components/ai/FilterTable/index.js.map +1 -0
- package/dist/components/ai/FineTuneCard/index.d.ts +24 -0
- package/dist/components/ai/FineTuneCard/index.js +75 -0
- package/dist/components/ai/FineTuneCard/index.js.map +1 -0
- package/dist/components/ai/InsightCards/index.d.ts +23 -0
- package/dist/components/ai/InsightCards/index.js +64 -0
- package/dist/components/ai/InsightCards/index.js.map +1 -0
- package/dist/components/ai/IssueCard/index.d.ts +39 -0
- package/dist/components/ai/IssueCard/index.js +78 -0
- package/dist/components/ai/IssueCard/index.js.map +1 -0
- package/dist/components/ai/LoadingState/index.d.ts +22 -0
- package/dist/components/ai/LoadingState/index.js +80 -0
- package/dist/components/ai/LoadingState/index.js.map +1 -0
- package/dist/components/ai/PromptBar/index.d.ts +26 -0
- package/dist/components/ai/PromptBar/index.js +117 -0
- package/dist/components/ai/PromptBar/index.js.map +1 -0
- package/dist/components/ai/RecommendationCard/index.d.ts +44 -0
- package/dist/components/ai/RecommendationCard/index.js +142 -0
- package/dist/components/ai/RecommendationCard/index.js.map +1 -0
- package/dist/components/ai/RecordsTable/index.d.ts +65 -0
- package/dist/components/ai/RecordsTable/index.js +334 -0
- package/dist/components/ai/RecordsTable/index.js.map +1 -0
- package/dist/components/ai/SelectionActions/index.d.ts +19 -0
- package/dist/components/ai/SelectionActions/index.js +40 -0
- package/dist/components/ai/SelectionActions/index.js.map +1 -0
- package/dist/components/ai/StateFlow/index.d.ts +24 -0
- package/dist/components/ai/StateFlow/index.js +50 -0
- package/dist/components/ai/StateFlow/index.js.map +1 -0
- package/dist/components/ai/StreamingText/index.d.ts +44 -0
- package/dist/components/ai/StreamingText/index.js +211 -0
- package/dist/components/ai/StreamingText/index.js.map +1 -0
- package/dist/components/ai/TaskRows/index.d.ts +53 -0
- package/dist/components/ai/TaskRows/index.js +186 -0
- package/dist/components/ai/TaskRows/index.js.map +1 -0
- package/dist/components/ai/Thinking/index.d.ts +47 -0
- package/dist/components/ai/Thinking/index.js +197 -0
- package/dist/components/ai/Thinking/index.js.map +1 -0
- package/dist/components/ai/ToolChips/index.d.ts +21 -0
- package/dist/components/ai/ToolChips/index.js +63 -0
- package/dist/components/ai/ToolChips/index.js.map +1 -0
- package/dist/components/ai/index.d.ts +54 -0
- package/dist/components/ai/shared.d.ts +13 -0
- package/dist/components/ai/shared.js +25 -0
- package/dist/components/ai/shared.js.map +1 -0
- package/dist/components/pro/DataTable/rowDetailExtension.js +1 -1
- package/dist/components/pro/DataTable/rowDetailExtension.js.map +1 -1
- package/dist/components/pro/Flow/constants.js +3 -3
- package/dist/components/pro/Flow/constants.js.map +1 -1
- package/dist/components/pro/Flow/nodes/shapes.js +3 -3
- package/dist/components/pro/Flow/nodes/shapes.js.map +1 -1
- package/dist/components/pro/Flow/utils/themeColor.d.ts +2 -2
- package/dist/components/pro/Flow/utils/themeColor.js +2 -2
- package/dist/components/pro/Flow/utils/themeColor.js.map +1 -1
- package/dist/components/pro/Kanban/Kanban.d.ts +3 -0
- package/dist/components/pro/Kanban/Kanban.js +339 -0
- package/dist/components/pro/Kanban/Kanban.js.map +1 -0
- package/dist/components/pro/Kanban/Swimlanes.d.ts +3 -0
- package/dist/components/pro/Kanban/Swimlanes.js +60 -0
- package/dist/components/pro/Kanban/Swimlanes.js.map +1 -0
- package/dist/components/pro/Kanban/index.d.ts +5 -0
- package/dist/components/pro/Kanban/types.d.ts +103 -0
- package/dist/components/pro/Kanban/useKanbanDrag.d.ts +17 -0
- package/dist/components/pro/Kanban/useKanbanDrag.js +69 -0
- package/dist/components/pro/Kanban/useKanbanDrag.js.map +1 -0
- package/dist/components/pro/Kanban/utils.d.ts +13 -0
- package/dist/components/pro/Kanban/utils.js +48 -0
- package/dist/components/pro/Kanban/utils.js.map +1 -0
- package/dist/components/pro/RichTextEditor/AIRewrite.js +158 -127
- package/dist/components/pro/RichTextEditor/AIRewrite.js.map +1 -1
- package/dist/components/pro/RichTextEditor/BlockHandle.d.ts +2 -0
- package/dist/components/pro/RichTextEditor/BlockHandle.js +156 -115
- package/dist/components/pro/RichTextEditor/BlockHandle.js.map +1 -1
- package/dist/components/pro/RichTextEditor/RichTextEditor.js +136 -159
- package/dist/components/pro/RichTextEditor/RichTextEditor.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js +44 -41
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js +59 -53
- package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js +48 -44
- package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/TableOpsMenu.js +67 -63
- package/dist/components/pro/RichTextEditor/Toolbar/TableOpsMenu.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.d.ts +1 -0
- package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js +182 -129
- package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/ToolbarButton.d.ts +1 -0
- package/dist/components/pro/RichTextEditor/Toolbar/ToolbarButton.js +3 -3
- package/dist/components/pro/RichTextEditor/Toolbar/ToolbarButton.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/useAnchoredDropdown.d.ts +3 -0
- package/dist/components/pro/RichTextEditor/Toolbar/useAnchoredDropdown.js +31 -0
- package/dist/components/pro/RichTextEditor/Toolbar/useAnchoredDropdown.js.map +1 -0
- package/dist/components/pro/RichTextEditor/index.d.ts +1 -1
- package/dist/components/pro/RichTextEditor/types.d.ts +78 -11
- package/dist/components/pro/RichTextEditor/types.js +11 -0
- package/dist/components/pro/RichTextEditor/types.js.map +1 -1
- package/dist/dishui.css +1 -1
- package/dist/index-nostyled.d.ts +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.js +134 -107
- package/dist/kanban.js +5 -0
- package/dist/layouts/Sidebar.d.ts +16 -0
- package/dist/layouts/Sidebar.js +85 -52
- package/dist/layouts/Sidebar.js.map +1 -1
- package/dist/utils/i18n.js +20 -0
- package/dist/utils/i18n.js.map +1 -1
- package/dist/utils/menu.js +1 -1
- package/dist/utils/menu.js.map +1 -1
- package/package.json +14 -3
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { cn as e } from "../../../utils/cn.js";
|
|
2
|
+
import t from "../../Button/index.js";
|
|
3
|
+
/* empty css */
|
|
4
|
+
import { useEffect as n, useMemo as r, useState as i, useSyncExternalStore as a } from "react";
|
|
5
|
+
import { jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
6
|
+
//#region src/components/ai/DiffTable/index.tsx
|
|
7
|
+
var c = {
|
|
8
|
+
added: "Added",
|
|
9
|
+
removed: "Removed",
|
|
10
|
+
modified: "Changed",
|
|
11
|
+
unchanged: "—",
|
|
12
|
+
acceptAll: "Accept all",
|
|
13
|
+
rejectAll: "Reject all",
|
|
14
|
+
accept: "Accept",
|
|
15
|
+
reject: "Reject",
|
|
16
|
+
accepted: "Accepted",
|
|
17
|
+
rejected: "Rejected",
|
|
18
|
+
status: "Status",
|
|
19
|
+
actions: "Actions",
|
|
20
|
+
empty: "∅"
|
|
21
|
+
};
|
|
22
|
+
function l(e) {
|
|
23
|
+
return typeof e == "object" && !!e;
|
|
24
|
+
}
|
|
25
|
+
function u(e) {
|
|
26
|
+
return e.change ? e.change : Object.values(e.cells).some(l) ? "modified" : void 0;
|
|
27
|
+
}
|
|
28
|
+
function d(e) {
|
|
29
|
+
let t = e.change;
|
|
30
|
+
return t === "added" || t === "removed" ? 1 : Object.values(e.cells).filter(l).length;
|
|
31
|
+
}
|
|
32
|
+
var f = (e, t) => `${e} ${t}${e === 1 ? "" : "s"}`, p = "(prefers-reduced-motion: reduce)", m = (e) => {
|
|
33
|
+
if (typeof window > "u" || !window.matchMedia) return () => {};
|
|
34
|
+
let t = window.matchMedia(p);
|
|
35
|
+
return t.addEventListener("change", e), () => t.removeEventListener("change", e);
|
|
36
|
+
}, h = () => typeof window < "u" && !!window.matchMedia && window.matchMedia(p).matches, g = () => a(m, h, () => !1), _ = () => /* @__PURE__ */ o("svg", {
|
|
37
|
+
width: "14",
|
|
38
|
+
height: "14",
|
|
39
|
+
viewBox: "0 0 24 24",
|
|
40
|
+
fill: "none",
|
|
41
|
+
stroke: "currentColor",
|
|
42
|
+
strokeWidth: "2",
|
|
43
|
+
strokeLinecap: "round",
|
|
44
|
+
strokeLinejoin: "round",
|
|
45
|
+
"aria-hidden": "true",
|
|
46
|
+
children: /* @__PURE__ */ o("path", { d: "M20 6 9 17l-5-5" })
|
|
47
|
+
}), v = () => /* @__PURE__ */ o("svg", {
|
|
48
|
+
width: "14",
|
|
49
|
+
height: "14",
|
|
50
|
+
viewBox: "0 0 24 24",
|
|
51
|
+
fill: "none",
|
|
52
|
+
stroke: "currentColor",
|
|
53
|
+
strokeWidth: "2",
|
|
54
|
+
strokeLinecap: "round",
|
|
55
|
+
strokeLinejoin: "round",
|
|
56
|
+
"aria-hidden": "true",
|
|
57
|
+
children: /* @__PURE__ */ o("path", { d: "M18 6 6 18M6 6l12 12" })
|
|
58
|
+
}), y = (e, t) => e == null || e === "" ? /* @__PURE__ */ o("span", {
|
|
59
|
+
className: "dishui-ai-diff-table__empty",
|
|
60
|
+
children: t
|
|
61
|
+
}) : String(e);
|
|
62
|
+
function b({ columns: a, rows: p, title: m, summary: h, sweeping: b = !1, sweepIntervalMs: x = 220, onAcceptAll: S, onRejectAll: C, onAcceptRow: w, onRejectRow: T, decisions: E, dense: D = !1, labels: O, className: k, ...A }) {
|
|
63
|
+
let j = {
|
|
64
|
+
...c,
|
|
65
|
+
...O
|
|
66
|
+
}, M = r(() => p.filter((e) => u(e)).map((e) => e.id), [p]), N = r(() => p.reduce((e, t) => e + d(t), 0), [p]), P = g(), F = b && !P, [I, L] = i(0);
|
|
67
|
+
n(() => {
|
|
68
|
+
if (!F) return;
|
|
69
|
+
let e = M.length, t = window.setInterval(() => {
|
|
70
|
+
L((n) => (n + 1 >= e && window.clearInterval(t), Math.min(n + 1, e)));
|
|
71
|
+
}, Math.max(16, x));
|
|
72
|
+
return () => {
|
|
73
|
+
window.clearInterval(t), L(0);
|
|
74
|
+
};
|
|
75
|
+
}, [
|
|
76
|
+
F,
|
|
77
|
+
x,
|
|
78
|
+
M.length
|
|
79
|
+
]);
|
|
80
|
+
let R = r(() => F ? new Set(M.slice(0, I)) : null, [
|
|
81
|
+
F,
|
|
82
|
+
M,
|
|
83
|
+
I
|
|
84
|
+
]), z = !F || I >= M.length, B = !!(w || T), V = !!(S || C), H = `${f(N, "change")} across ${f(M.length, "row")}`;
|
|
85
|
+
return /* @__PURE__ */ s("div", {
|
|
86
|
+
...A,
|
|
87
|
+
className: e("dishui-ai-diff-table", D && "dishui-ai-diff-table--dense", F && !z && "dishui-ai-diff-table--sweeping", k),
|
|
88
|
+
children: [
|
|
89
|
+
(m || h !== null) && /* @__PURE__ */ s("div", {
|
|
90
|
+
className: "dishui-ai-diff-table__header",
|
|
91
|
+
children: [m && /* @__PURE__ */ o("div", {
|
|
92
|
+
className: "dishui-ai-diff-table__title",
|
|
93
|
+
children: m
|
|
94
|
+
}), /* @__PURE__ */ o("div", {
|
|
95
|
+
className: "dishui-ai-diff-table__summary",
|
|
96
|
+
"aria-live": "polite",
|
|
97
|
+
children: h ?? H
|
|
98
|
+
})]
|
|
99
|
+
}),
|
|
100
|
+
/* @__PURE__ */ o("div", {
|
|
101
|
+
className: "dishui-ai-diff-table__scroll",
|
|
102
|
+
children: /* @__PURE__ */ s("table", {
|
|
103
|
+
className: "dishui-ai-diff-table__table",
|
|
104
|
+
children: [/* @__PURE__ */ o("thead", { children: /* @__PURE__ */ s("tr", { children: [
|
|
105
|
+
/* @__PURE__ */ o("th", {
|
|
106
|
+
scope: "col",
|
|
107
|
+
className: "dishui-ai-diff-table__th dishui-ai-diff-table__th--status",
|
|
108
|
+
children: j.status
|
|
109
|
+
}),
|
|
110
|
+
a.map((t) => /* @__PURE__ */ o("th", {
|
|
111
|
+
scope: "col",
|
|
112
|
+
className: e("dishui-ai-diff-table__th", t.align === "right" && "dishui-ai-diff-table__th--right"),
|
|
113
|
+
children: t.label
|
|
114
|
+
}, t.key)),
|
|
115
|
+
B && /* @__PURE__ */ o("th", {
|
|
116
|
+
scope: "col",
|
|
117
|
+
className: "dishui-ai-diff-table__th dishui-ai-diff-table__th--actions",
|
|
118
|
+
children: /* @__PURE__ */ o("span", {
|
|
119
|
+
className: "dishui-ai-diff-table__sr",
|
|
120
|
+
children: j.actions
|
|
121
|
+
})
|
|
122
|
+
})
|
|
123
|
+
] }) }), /* @__PURE__ */ o("tbody", { children: p.map((t) => {
|
|
124
|
+
let n = u(t), r = !n || !R || R.has(t.id), i = E?.[t.id];
|
|
125
|
+
return /* @__PURE__ */ s("tr", {
|
|
126
|
+
className: e("dishui-ai-diff-table__row", n && `dishui-ai-diff-table__row--${n}`, n && r && "dishui-ai-diff-table__row--revealed", i && `dishui-ai-diff-table__row--${i}`),
|
|
127
|
+
"data-change": n,
|
|
128
|
+
children: [
|
|
129
|
+
/* @__PURE__ */ o("td", {
|
|
130
|
+
className: "dishui-ai-diff-table__td dishui-ai-diff-table__td--status",
|
|
131
|
+
children: n && r ? /* @__PURE__ */ o("span", {
|
|
132
|
+
className: e("dishui-ai-diff-table__badge", `dishui-ai-diff-table__badge--${n}`),
|
|
133
|
+
children: j[n]
|
|
134
|
+
}) : /* @__PURE__ */ o("span", {
|
|
135
|
+
className: "dishui-ai-diff-table__badge dishui-ai-diff-table__badge--none",
|
|
136
|
+
"aria-hidden": "true",
|
|
137
|
+
children: j.unchanged
|
|
138
|
+
})
|
|
139
|
+
}),
|
|
140
|
+
a.map((i) => {
|
|
141
|
+
let a = t.cells[i.key], c = r && l(a), u = e("dishui-ai-diff-table__td", i.align === "right" && "dishui-ai-diff-table__td--right", i.mono && "dishui-ai-diff-table__td--mono", c && "dishui-ai-diff-table__td--changed");
|
|
142
|
+
return l(a) ? r ? /* @__PURE__ */ o("td", {
|
|
143
|
+
className: u,
|
|
144
|
+
children: /* @__PURE__ */ s("span", {
|
|
145
|
+
className: "dishui-ai-diff-table__change",
|
|
146
|
+
children: [
|
|
147
|
+
/* @__PURE__ */ o("del", {
|
|
148
|
+
className: "dishui-ai-diff-table__before",
|
|
149
|
+
children: y(a.before, j.empty)
|
|
150
|
+
}),
|
|
151
|
+
/* @__PURE__ */ o("span", {
|
|
152
|
+
className: "dishui-ai-diff-table__arrow",
|
|
153
|
+
"aria-hidden": "true",
|
|
154
|
+
children: "→"
|
|
155
|
+
}),
|
|
156
|
+
/* @__PURE__ */ o("ins", {
|
|
157
|
+
className: "dishui-ai-diff-table__after",
|
|
158
|
+
children: y(a.after, j.empty)
|
|
159
|
+
})
|
|
160
|
+
]
|
|
161
|
+
})
|
|
162
|
+
}, i.key) : /* @__PURE__ */ o("td", {
|
|
163
|
+
className: u,
|
|
164
|
+
children: y(a.before, j.empty)
|
|
165
|
+
}, i.key) : /* @__PURE__ */ o("td", {
|
|
166
|
+
className: u,
|
|
167
|
+
children: n === "removed" && r ? /* @__PURE__ */ o("del", {
|
|
168
|
+
className: "dishui-ai-diff-table__before",
|
|
169
|
+
children: y(a, j.empty)
|
|
170
|
+
}) : n === "added" && r ? /* @__PURE__ */ o("ins", {
|
|
171
|
+
className: "dishui-ai-diff-table__after",
|
|
172
|
+
children: y(a, j.empty)
|
|
173
|
+
}) : y(a, j.empty)
|
|
174
|
+
}, i.key);
|
|
175
|
+
}),
|
|
176
|
+
B && /* @__PURE__ */ o("td", {
|
|
177
|
+
className: "dishui-ai-diff-table__td dishui-ai-diff-table__td--actions",
|
|
178
|
+
children: n && r && (i ? /* @__PURE__ */ s("span", {
|
|
179
|
+
className: e("dishui-ai-diff-table__decision", `dishui-ai-diff-table__decision--${i}`),
|
|
180
|
+
children: [o(i === "accepted" ? _ : v, {}), j[i]]
|
|
181
|
+
}) : /* @__PURE__ */ s("span", {
|
|
182
|
+
className: "dishui-ai-diff-table__row-actions",
|
|
183
|
+
children: [w && /* @__PURE__ */ o("button", {
|
|
184
|
+
type: "button",
|
|
185
|
+
className: "dishui-ai-diff-table__icon-btn",
|
|
186
|
+
"aria-label": j.accept,
|
|
187
|
+
title: j.accept,
|
|
188
|
+
onClick: () => w(t),
|
|
189
|
+
children: /* @__PURE__ */ o(_, {})
|
|
190
|
+
}), T && /* @__PURE__ */ o("button", {
|
|
191
|
+
type: "button",
|
|
192
|
+
className: "dishui-ai-diff-table__icon-btn",
|
|
193
|
+
"aria-label": j.reject,
|
|
194
|
+
title: j.reject,
|
|
195
|
+
onClick: () => T(t),
|
|
196
|
+
children: /* @__PURE__ */ o(v, {})
|
|
197
|
+
})]
|
|
198
|
+
}))
|
|
199
|
+
})
|
|
200
|
+
]
|
|
201
|
+
}, t.id);
|
|
202
|
+
}) })]
|
|
203
|
+
})
|
|
204
|
+
}),
|
|
205
|
+
V && /* @__PURE__ */ s("div", {
|
|
206
|
+
className: "dishui-ai-diff-table__footer",
|
|
207
|
+
children: [/* @__PURE__ */ o("span", {
|
|
208
|
+
className: "dishui-ai-diff-table__footer-meta",
|
|
209
|
+
children: z ? H : "Reviewing…"
|
|
210
|
+
}), /* @__PURE__ */ s("span", {
|
|
211
|
+
className: "dishui-ai-diff-table__footer-actions",
|
|
212
|
+
children: [C && /* @__PURE__ */ o(t, {
|
|
213
|
+
type: "button",
|
|
214
|
+
variant: "secondary",
|
|
215
|
+
size: "sm",
|
|
216
|
+
onClick: C,
|
|
217
|
+
disabled: !z,
|
|
218
|
+
children: j.rejectAll
|
|
219
|
+
}), S && /* @__PURE__ */ o(t, {
|
|
220
|
+
type: "button",
|
|
221
|
+
variant: "primary",
|
|
222
|
+
size: "sm",
|
|
223
|
+
onClick: S,
|
|
224
|
+
disabled: !z,
|
|
225
|
+
children: j.acceptAll
|
|
226
|
+
})]
|
|
227
|
+
})]
|
|
228
|
+
})
|
|
229
|
+
]
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
//#endregion
|
|
233
|
+
export { b as default, u as diffRowChange, l as isDiffCellChange };
|
|
234
|
+
|
|
235
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/ai/DiffTable/index.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useState, useSyncExternalStore } from 'react';\nimport { cn } from '../../../utils/cn';\nimport Button from '../../Button';\nimport './DiffTable.css';\n\nexport type DiffTableColumn = {\n key: string;\n label: React.ReactNode;\n align?: 'left' | 'right';\n /** Render the cell in the mono font (IDs, SKUs). */\n mono?: boolean;\n};\n\nexport type DiffCellValue = string | number | null;\n\n/** A plain value is unchanged; an object describes a `before → after` edit. */\nexport type DiffCell = DiffCellValue | { before?: DiffCellValue; after?: DiffCellValue };\n\nexport type DiffRowChange = 'added' | 'removed' | 'modified';\n\nexport type DiffRow = {\n id: string;\n cells: Record<string, DiffCell>;\n /** Row-level change. Omitted rows are inferred as `modified` when any cell is an edit. */\n change?: DiffRowChange;\n};\n\nexport type DiffDecision = 'accepted' | 'rejected';\n\nexport type DiffTableProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'children' | 'title' | 'summary'> & {\n columns: DiffTableColumn[];\n rows: DiffRow[];\n title?: React.ReactNode;\n /** Summary line under the title. Auto-computed (`3 changes across 2 rows`) when omitted. */\n summary?: React.ReactNode;\n /** Reveal changed rows one by one, top to bottom. */\n sweeping?: boolean;\n /** Milliseconds between each revealed row while sweeping. */\n sweepIntervalMs?: number;\n onAcceptAll?: () => void;\n onRejectAll?: () => void;\n onAcceptRow?: (row: DiffRow) => void;\n onRejectRow?: (row: DiffRow) => void;\n /** Controlled per-row decisions, keyed by row id. */\n decisions?: Record<string, DiffDecision>;\n dense?: boolean;\n /** Text overrides. */\n labels?: Partial<typeof DEFAULT_LABELS>;\n};\n\nconst DEFAULT_LABELS = {\n added: 'Added',\n removed: 'Removed',\n modified: 'Changed',\n unchanged: '—',\n acceptAll: 'Accept all',\n rejectAll: 'Reject all',\n accept: 'Accept',\n reject: 'Reject',\n accepted: 'Accepted',\n rejected: 'Rejected',\n status: 'Status',\n actions: 'Actions',\n empty: '∅',\n};\n\nexport function isDiffCellChange(cell: DiffCell): cell is { before?: DiffCellValue; after?: DiffCellValue } {\n return typeof cell === 'object' && cell !== null;\n}\n\n/** Infer the row's change kind from its explicit flag or its cells. */\nexport function diffRowChange(row: DiffRow): DiffRowChange | undefined {\n if (row.change) return row.change;\n return Object.values(row.cells).some(isDiffCellChange) ? 'modified' : undefined;\n}\n\n/** Number of changed cells in a row (whole row counts as one for added/removed). */\nfunction countRowChanges(row: DiffRow): number {\n const change = row.change;\n if (change === 'added' || change === 'removed') return 1;\n return Object.values(row.cells).filter(isDiffCellChange).length;\n}\n\nconst plural = (n: number, word: string) => `${n} ${word}${n === 1 ? '' : 's'}`;\n\nconst REDUCED_MOTION = '(prefers-reduced-motion: reduce)';\nconst subscribeReducedMotion = (onChange: () => void) => {\n if (typeof window === 'undefined' || !window.matchMedia) return () => {};\n const mq = window.matchMedia(REDUCED_MOTION);\n mq.addEventListener('change', onChange);\n return () => mq.removeEventListener('change', onChange);\n};\nconst getReducedMotion = () => typeof window !== 'undefined' && !!window.matchMedia && window.matchMedia(REDUCED_MOTION).matches;\nconst usePrefersReducedMotion = () => useSyncExternalStore(subscribeReducedMotion, getReducedMotion, () => false);\n\nconst CheckIcon = () => (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n);\nconst XIcon = () => (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n);\n\nconst renderValue = (value: DiffCellValue | undefined, empty: string) =>\n value === null || value === undefined || value === '' ? <span className=\"dishui-ai-diff-table__empty\">{empty}</span> : String(value);\n\n/**\n * AI-proposed edits sweeping through tabular data. Changed cells show the\n * old value struck through next to the new one; added/removed rows are\n * tinted and always labelled in the leading status column.\n */\nexport default function DiffTable({\n columns,\n rows,\n title,\n summary,\n sweeping: sweepingProp = false,\n sweepIntervalMs = 220,\n onAcceptAll,\n onRejectAll,\n onAcceptRow,\n onRejectRow,\n decisions,\n dense = false,\n labels: labelOverrides,\n className,\n ...rest\n}: DiffTableProps) {\n const labels = { ...DEFAULT_LABELS, ...labelOverrides };\n\n const changedIds = useMemo(() => rows.filter(r => diffRowChange(r)).map(r => r.id), [rows]);\n const changeCount = useMemo(() => rows.reduce((n, r) => n + countRowChanges(r), 0), [rows]);\n\n // Reduced motion: skip the sweep and show every change at once.\n const reducedMotion = usePrefersReducedMotion();\n const sweeping = sweepingProp && !reducedMotion;\n\n // Sweep: reveal one changed row per interval. `revealed` counts changed rows (top to bottom).\n const [revealed, setRevealed] = useState(0);\n useEffect(() => {\n if (!sweeping) return;\n const total = changedIds.length;\n const id = window.setInterval(() => {\n setRevealed(n => {\n if (n + 1 >= total) window.clearInterval(id);\n return Math.min(n + 1, total);\n });\n }, Math.max(16, sweepIntervalMs));\n return () => {\n window.clearInterval(id);\n // Restart from the top the next time a sweep begins.\n setRevealed(0);\n };\n }, [sweeping, sweepIntervalMs, changedIds.length]);\n\n const revealedIds = useMemo(() => {\n if (!sweeping) return null;\n return new Set(changedIds.slice(0, revealed));\n }, [sweeping, changedIds, revealed]);\n\n const done = !sweeping || revealed >= changedIds.length;\n const hasRowActions = Boolean(onAcceptRow || onRejectRow);\n const hasFooter = Boolean(onAcceptAll || onRejectAll);\n\n const autoSummary = `${plural(changeCount, 'change')} across ${plural(changedIds.length, 'row')}`;\n\n return (\n <div\n {...rest}\n className={cn('dishui-ai-diff-table', dense && 'dishui-ai-diff-table--dense', sweeping && !done && 'dishui-ai-diff-table--sweeping', className)}\n >\n {(title || summary !== null) && (\n <div className=\"dishui-ai-diff-table__header\">\n {title && <div className=\"dishui-ai-diff-table__title\">{title}</div>}\n <div className=\"dishui-ai-diff-table__summary\" aria-live=\"polite\">\n {summary ?? autoSummary}\n </div>\n </div>\n )}\n\n <div className=\"dishui-ai-diff-table__scroll\">\n <table className=\"dishui-ai-diff-table__table\">\n <thead>\n <tr>\n <th scope=\"col\" className=\"dishui-ai-diff-table__th dishui-ai-diff-table__th--status\">{labels.status}</th>\n {columns.map(col => (\n <th\n key={col.key}\n scope=\"col\"\n className={cn('dishui-ai-diff-table__th', col.align === 'right' && 'dishui-ai-diff-table__th--right')}\n >\n {col.label}\n </th>\n ))}\n {hasRowActions && (\n <th scope=\"col\" className=\"dishui-ai-diff-table__th dishui-ai-diff-table__th--actions\">\n <span className=\"dishui-ai-diff-table__sr\">{labels.actions}</span>\n </th>\n )}\n </tr>\n </thead>\n <tbody>\n {rows.map(row => {\n const change = diffRowChange(row);\n const visible = !change || !revealedIds || revealedIds.has(row.id);\n const decision = decisions?.[row.id];\n return (\n <tr\n key={row.id}\n className={cn(\n 'dishui-ai-diff-table__row',\n change && `dishui-ai-diff-table__row--${change}`,\n change && visible && 'dishui-ai-diff-table__row--revealed',\n decision && `dishui-ai-diff-table__row--${decision}`,\n )}\n data-change={change}\n >\n <td className=\"dishui-ai-diff-table__td dishui-ai-diff-table__td--status\">\n {change && visible ? (\n <span className={cn('dishui-ai-diff-table__badge', `dishui-ai-diff-table__badge--${change}`)}>\n {labels[change]}\n </span>\n ) : (\n <span className=\"dishui-ai-diff-table__badge dishui-ai-diff-table__badge--none\" aria-hidden=\"true\">\n {labels.unchanged}\n </span>\n )}\n </td>\n {columns.map(col => {\n const cell = row.cells[col.key];\n const changed = visible && isDiffCellChange(cell);\n const tdClass = cn(\n 'dishui-ai-diff-table__td',\n col.align === 'right' && 'dishui-ai-diff-table__td--right',\n col.mono && 'dishui-ai-diff-table__td--mono',\n changed && 'dishui-ai-diff-table__td--changed',\n );\n if (isDiffCellChange(cell)) {\n if (!visible) {\n return <td key={col.key} className={tdClass}>{renderValue(cell.before, labels.empty)}</td>;\n }\n return (\n <td key={col.key} className={tdClass}>\n <span className=\"dishui-ai-diff-table__change\">\n <del className=\"dishui-ai-diff-table__before\">{renderValue(cell.before, labels.empty)}</del>\n <span className=\"dishui-ai-diff-table__arrow\" aria-hidden=\"true\">→</span>\n <ins className=\"dishui-ai-diff-table__after\">{renderValue(cell.after, labels.empty)}</ins>\n </span>\n </td>\n );\n }\n return (\n <td key={col.key} className={tdClass}>\n {change === 'removed' && visible ? (\n <del className=\"dishui-ai-diff-table__before\">{renderValue(cell, labels.empty)}</del>\n ) : change === 'added' && visible ? (\n <ins className=\"dishui-ai-diff-table__after\">{renderValue(cell, labels.empty)}</ins>\n ) : (\n renderValue(cell, labels.empty)\n )}\n </td>\n );\n })}\n {hasRowActions && (\n <td className=\"dishui-ai-diff-table__td dishui-ai-diff-table__td--actions\">\n {change && visible && (\n decision ? (\n <span className={cn('dishui-ai-diff-table__decision', `dishui-ai-diff-table__decision--${decision}`)}>\n {decision === 'accepted' ? <CheckIcon /> : <XIcon />}\n {labels[decision]}\n </span>\n ) : (\n <span className=\"dishui-ai-diff-table__row-actions\">\n {onAcceptRow && (\n <button type=\"button\" className=\"dishui-ai-diff-table__icon-btn\" aria-label={labels.accept} title={labels.accept} onClick={() => onAcceptRow(row)}>\n <CheckIcon />\n </button>\n )}\n {onRejectRow && (\n <button type=\"button\" className=\"dishui-ai-diff-table__icon-btn\" aria-label={labels.reject} title={labels.reject} onClick={() => onRejectRow(row)}>\n <XIcon />\n </button>\n )}\n </span>\n )\n )}\n </td>\n )}\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n\n {hasFooter && (\n <div className=\"dishui-ai-diff-table__footer\">\n <span className=\"dishui-ai-diff-table__footer-meta\">{done ? autoSummary : 'Reviewing…'}</span>\n <span className=\"dishui-ai-diff-table__footer-actions\">\n {onRejectAll && (\n <Button type=\"button\" variant=\"secondary\" size=\"sm\" onClick={onRejectAll} disabled={!done}>\n {labels.rejectAll}\n </Button>\n )}\n {onAcceptAll && (\n <Button type=\"button\" variant=\"primary\" size=\"sm\" onClick={onAcceptAll} disabled={!done}>\n {labels.acceptAll}\n </Button>\n )}\n </span>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type FilterTableColumn<Row> = {
|
|
3
|
+
key: string;
|
|
4
|
+
label: React.ReactNode;
|
|
5
|
+
render?: (row: Row) => React.ReactNode;
|
|
6
|
+
value?: (row: Row) => string | number;
|
|
7
|
+
align?: 'left' | 'right';
|
|
8
|
+
mono?: boolean;
|
|
9
|
+
};
|
|
10
|
+
export type FilterTableFilter<Row> = {
|
|
11
|
+
id: string;
|
|
12
|
+
label: string;
|
|
13
|
+
predicate: (row: Row) => boolean;
|
|
14
|
+
};
|
|
15
|
+
export type FilterTableProps<Row extends {
|
|
16
|
+
id: string;
|
|
17
|
+
}> = Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> & {
|
|
18
|
+
rows: Row[];
|
|
19
|
+
columns: FilterTableColumn<Row>[];
|
|
20
|
+
filters?: FilterTableFilter<Row>[];
|
|
21
|
+
value?: string;
|
|
22
|
+
defaultValue?: string;
|
|
23
|
+
onChange?: (id: string) => void;
|
|
24
|
+
search?: string;
|
|
25
|
+
defaultSearch?: string;
|
|
26
|
+
onSearchChange?: (query: string) => void;
|
|
27
|
+
searchPlaceholder?: string;
|
|
28
|
+
emptyText?: React.ReactNode;
|
|
29
|
+
noResultsText?: React.ReactNode;
|
|
30
|
+
caption?: React.ReactNode;
|
|
31
|
+
loading?: boolean;
|
|
32
|
+
};
|
|
33
|
+
export default function FilterTable<Row extends {
|
|
34
|
+
id: string;
|
|
35
|
+
}>({ rows, columns, filters, value, defaultValue, onChange, search, defaultSearch, onSearchChange, searchPlaceholder, emptyText, noResultsText, caption, loading, className, ...rest }: FilterTableProps<Row>): React.JSX.Element;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { cn as e } from "../../../utils/cn.js";
|
|
2
|
+
import t from "../../Table/index.js";
|
|
3
|
+
import n from "../../Skeleton/index.js";
|
|
4
|
+
/* empty css */
|
|
5
|
+
import { useMemo as r, useState as i } from "react";
|
|
6
|
+
import { jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
7
|
+
//#region src/components/ai/FilterTable/index.tsx
|
|
8
|
+
var s = [];
|
|
9
|
+
function c({ rows: c, columns: l, filters: u = s, value: d, defaultValue: f = "all", onChange: p, search: m, defaultSearch: h = "", onSearchChange: g, searchPlaceholder: _ = "Filter records…", emptyText: v = "No records yet", noResultsText: y = "No matching records", caption: b, loading: x = !1, className: S, ...C }) {
|
|
10
|
+
let [w, T] = i(f), [E, D] = i(h), O = d ?? w, k = m ?? E, A = r(() => c.filter((e) => {
|
|
11
|
+
let t = u.find((e) => e.id === O);
|
|
12
|
+
return t && !t.predicate(e) ? !1 : !k.trim() || l.some((t) => String(t.value?.(e) ?? e[t.key] ?? "").toLowerCase().includes(k.trim().toLowerCase()));
|
|
13
|
+
}), [
|
|
14
|
+
c,
|
|
15
|
+
l,
|
|
16
|
+
u,
|
|
17
|
+
O,
|
|
18
|
+
k
|
|
19
|
+
]), j = (e) => {
|
|
20
|
+
d === void 0 && T(e), p?.(e);
|
|
21
|
+
}, M = (e) => {
|
|
22
|
+
m === void 0 && D(e), g?.(e);
|
|
23
|
+
};
|
|
24
|
+
return /* @__PURE__ */ o("div", {
|
|
25
|
+
...C,
|
|
26
|
+
className: e("dishui-ai-filter-table", S),
|
|
27
|
+
"aria-busy": x || void 0,
|
|
28
|
+
children: [/* @__PURE__ */ o("div", {
|
|
29
|
+
className: "dishui-ai-filter-table__toolbar",
|
|
30
|
+
children: [/* @__PURE__ */ o("div", {
|
|
31
|
+
className: "dishui-ai-filter-table__filters",
|
|
32
|
+
role: "group",
|
|
33
|
+
"aria-label": "Table filters",
|
|
34
|
+
children: [/* @__PURE__ */ o("button", {
|
|
35
|
+
type: "button",
|
|
36
|
+
"aria-pressed": O === "all",
|
|
37
|
+
onClick: () => j("all"),
|
|
38
|
+
children: ["All ", /* @__PURE__ */ a("span", { children: c.length })]
|
|
39
|
+
}), u.map((e) => /* @__PURE__ */ o("button", {
|
|
40
|
+
type: "button",
|
|
41
|
+
"aria-pressed": O === e.id,
|
|
42
|
+
onClick: () => j(e.id),
|
|
43
|
+
children: [
|
|
44
|
+
e.label,
|
|
45
|
+
" ",
|
|
46
|
+
/* @__PURE__ */ a("span", { children: c.filter(e.predicate).length })
|
|
47
|
+
]
|
|
48
|
+
}, e.id))]
|
|
49
|
+
}), /* @__PURE__ */ a("input", {
|
|
50
|
+
type: "search",
|
|
51
|
+
"aria-label": _,
|
|
52
|
+
placeholder: _,
|
|
53
|
+
value: k,
|
|
54
|
+
onChange: (e) => M(e.target.value)
|
|
55
|
+
})]
|
|
56
|
+
}), /* @__PURE__ */ a("div", {
|
|
57
|
+
className: "dishui-ai-filter-table__scroll",
|
|
58
|
+
children: /* @__PURE__ */ o(t, { children: [
|
|
59
|
+
b && /* @__PURE__ */ a("caption", { children: b }),
|
|
60
|
+
/* @__PURE__ */ a(t.Head, { children: /* @__PURE__ */ a(t.Row, { children: l.map((e) => /* @__PURE__ */ a(t.HeaderCell, {
|
|
61
|
+
className: e.align === "right" ? "dishui-ai-filter-table__right" : void 0,
|
|
62
|
+
children: e.label
|
|
63
|
+
}, e.key)) }) }),
|
|
64
|
+
/* @__PURE__ */ o(t.Body, { children: [x ? [
|
|
65
|
+
"one",
|
|
66
|
+
"two",
|
|
67
|
+
"three"
|
|
68
|
+
].map((e) => /* @__PURE__ */ a(t.Row, {
|
|
69
|
+
"aria-hidden": "true",
|
|
70
|
+
children: l.map((e) => /* @__PURE__ */ a(t.Cell, { children: /* @__PURE__ */ a(n, { className: "dishui-ai-filter-table__skeleton" }) }, e.key))
|
|
71
|
+
}, e)) : A.map((n) => /* @__PURE__ */ a(t.Row, { children: l.map((r) => /* @__PURE__ */ a(t.Cell, {
|
|
72
|
+
className: e(r.align === "right" && "dishui-ai-filter-table__right", r.mono && "dishui-ai-filter-table__mono"),
|
|
73
|
+
children: r.render ? r.render(n) : String(r.value?.(n) ?? n[r.key] ?? "—")
|
|
74
|
+
}, r.key)) }, n.id)), !x && A.length === 0 && /* @__PURE__ */ a(t.Row, { children: /* @__PURE__ */ a(t.Cell, {
|
|
75
|
+
className: "dishui-ai-filter-table__empty",
|
|
76
|
+
colSpan: l.length,
|
|
77
|
+
children: c.length ? y : v
|
|
78
|
+
}) })] })
|
|
79
|
+
] })
|
|
80
|
+
})]
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
//#endregion
|
|
84
|
+
export { c as default };
|
|
85
|
+
|
|
86
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/ai/FilterTable/index.tsx"],"sourcesContent":["import React, { useMemo, useState } from 'react';\nimport { cn } from '../../../utils/cn';\nimport Table from '../../Table';\nimport Skeleton from '../../Skeleton';\nimport './FilterTable.css';\n\nconst EMPTY_FILTERS: FilterTableFilter<never>[] = [];\n\nexport type FilterTableColumn<Row> = { key: string; label: React.ReactNode; render?: (row: Row) => React.ReactNode; value?: (row: Row) => string | number; align?: 'left' | 'right'; mono?: boolean };\nexport type FilterTableFilter<Row> = { id: string; label: string; predicate: (row: Row) => boolean };\nexport type FilterTableProps<Row extends { id: string }> = Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> & { rows: Row[]; columns: FilterTableColumn<Row>[]; filters?: FilterTableFilter<Row>[]; value?: string; defaultValue?: string; onChange?: (id: string) => void; search?: string; defaultSearch?: string; onSearchChange?: (query: string) => void; searchPlaceholder?: string; emptyText?: React.ReactNode; noResultsText?: React.ReactNode; caption?: React.ReactNode; loading?: boolean };\n\nexport default function FilterTable<Row extends { id: string }>({ rows, columns, filters = EMPTY_FILTERS as FilterTableFilter<Row>[], value, defaultValue = 'all', onChange, search, defaultSearch = '', onSearchChange, searchPlaceholder = 'Filter records…', emptyText = 'No records yet', noResultsText = 'No matching records', caption, loading = false, className, ...rest }: FilterTableProps<Row>) {\n const [internalFilter, setInternalFilter] = useState(defaultValue); const [internalSearch, setInternalSearch] = useState(defaultSearch); const active = value ?? internalFilter; const query = search ?? internalSearch;\n const shown = useMemo(() => rows.filter(row => { const filter = filters.find(x => x.id === active); if (filter && !filter.predicate(row)) return false; if (!query.trim()) return true; return columns.some(col => String(col.value?.(row) ?? (row as Record<string, unknown>)[col.key] ?? '').toLowerCase().includes(query.trim().toLowerCase())); }), [rows, columns, filters, active, query]);\n const setFilter = (id: string) => { if (value === undefined) setInternalFilter(id); onChange?.(id); };\n const setSearch = (next: string) => { if (search === undefined) setInternalSearch(next); onSearchChange?.(next); };\n return <div {...rest} className={cn('dishui-ai-filter-table', className)} aria-busy={loading || undefined}><div className=\"dishui-ai-filter-table__toolbar\"><div className=\"dishui-ai-filter-table__filters\" role=\"group\" aria-label=\"Table filters\"><button type=\"button\" aria-pressed={active === 'all'} onClick={() => setFilter('all')}>All <span>{rows.length}</span></button>{filters.map(filter => <button key={filter.id} type=\"button\" aria-pressed={active === filter.id} onClick={() => setFilter(filter.id)}>{filter.label} <span>{rows.filter(filter.predicate).length}</span></button>)}</div><input type=\"search\" aria-label={searchPlaceholder} placeholder={searchPlaceholder} value={query} onChange={e => setSearch(e.target.value)}/></div><div className=\"dishui-ai-filter-table__scroll\"><Table>{caption && <caption>{caption}</caption>}<Table.Head><Table.Row>{columns.map(col => <Table.HeaderCell key={col.key} className={col.align === 'right' ? 'dishui-ai-filter-table__right' : undefined}>{col.label}</Table.HeaderCell>)}</Table.Row></Table.Head><Table.Body>{loading ? ['one', 'two', 'three'].map(rowKey => <Table.Row key={rowKey} aria-hidden=\"true\">{columns.map(col => <Table.Cell key={col.key}><Skeleton className=\"dishui-ai-filter-table__skeleton\" /></Table.Cell>)}</Table.Row>) : shown.map(row => <Table.Row key={row.id}>{columns.map(col => <Table.Cell key={col.key} className={cn(col.align === 'right' && 'dishui-ai-filter-table__right', col.mono && 'dishui-ai-filter-table__mono')}>{col.render ? col.render(row) : String(col.value?.(row) ?? (row as Record<string, unknown>)[col.key] ?? '—')}</Table.Cell>)}</Table.Row>)}{!loading && shown.length === 0 && <Table.Row><Table.Cell className=\"dishui-ai-filter-table__empty\" colSpan={columns.length}>{rows.length ? noResultsText : emptyText}</Table.Cell></Table.Row>}</Table.Body></Table></div></div>;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type FineTuneMetric = {
|
|
3
|
+
label: React.ReactNode;
|
|
4
|
+
value: React.ReactNode;
|
|
5
|
+
};
|
|
6
|
+
export type FineTuneCardProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> & {
|
|
7
|
+
title: React.ReactNode;
|
|
8
|
+
model?: string;
|
|
9
|
+
description?: React.ReactNode;
|
|
10
|
+
status?: 'draft' | 'queued' | 'training' | 'ready' | 'failed';
|
|
11
|
+
progress?: number;
|
|
12
|
+
metrics?: FineTuneMetric[];
|
|
13
|
+
error?: React.ReactNode;
|
|
14
|
+
onStart?: () => void;
|
|
15
|
+
onCancel?: () => void;
|
|
16
|
+
onRetry?: () => void;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
labels?: {
|
|
19
|
+
start?: string;
|
|
20
|
+
cancel?: string;
|
|
21
|
+
retry?: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export default function FineTuneCard({ title, model, description, status, progress, metrics, error, onStart, onCancel, onRetry, disabled, labels, className, ...rest }: FineTuneCardProps): React.JSX.Element;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { cn as e } from "../../../utils/cn.js";
|
|
2
|
+
import t from "../../Button/index.js";
|
|
3
|
+
import { clamp as n } from "../shared.js";
|
|
4
|
+
/* empty css */
|
|
5
|
+
import "react";
|
|
6
|
+
import { jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
7
|
+
//#region src/components/ai/FineTuneCard/index.tsx
|
|
8
|
+
var a = {
|
|
9
|
+
draft: "Draft",
|
|
10
|
+
queued: "Queued",
|
|
11
|
+
training: "Training",
|
|
12
|
+
ready: "Ready",
|
|
13
|
+
failed: "Failed"
|
|
14
|
+
}, o = [];
|
|
15
|
+
function s({ title: s, model: c, description: l, status: u = "draft", progress: d = 0, metrics: f = o, error: p, onStart: m, onCancel: h, onRetry: g, disabled: _ = !1, labels: v, className: y, ...b }) {
|
|
16
|
+
let x = Math.round(n(d, 0, 1) * 100), S = u === "queued" || u === "training";
|
|
17
|
+
return /* @__PURE__ */ i("article", {
|
|
18
|
+
...b,
|
|
19
|
+
className: e("dishui-ai-fine-tune-card", `dishui-ai-fine-tune-card--${u}`, y),
|
|
20
|
+
children: [
|
|
21
|
+
/* @__PURE__ */ i("header", { children: [/* @__PURE__ */ i("div", { children: [/* @__PURE__ */ r("h3", { children: s }), c && /* @__PURE__ */ r("code", { children: c })] }), /* @__PURE__ */ r("span", {
|
|
22
|
+
className: "dishui-ai-fine-tune-card__status",
|
|
23
|
+
children: a[u]
|
|
24
|
+
})] }),
|
|
25
|
+
l && /* @__PURE__ */ r("div", {
|
|
26
|
+
className: "dishui-ai-fine-tune-card__description",
|
|
27
|
+
children: l
|
|
28
|
+
}),
|
|
29
|
+
S && /* @__PURE__ */ i("div", {
|
|
30
|
+
className: "dishui-ai-fine-tune-card__progress",
|
|
31
|
+
children: [/* @__PURE__ */ i("div", { children: [/* @__PURE__ */ r("span", { children: "Training progress" }), /* @__PURE__ */ i("strong", { children: [x, "%"] })] }), /* @__PURE__ */ i("progress", {
|
|
32
|
+
max: 100,
|
|
33
|
+
value: x,
|
|
34
|
+
children: [x, "%"]
|
|
35
|
+
})]
|
|
36
|
+
}),
|
|
37
|
+
f.length > 0 && /* @__PURE__ */ r("dl", { children: f.map((e) => /* @__PURE__ */ i("div", { children: [/* @__PURE__ */ r("dt", { children: e.label }), /* @__PURE__ */ r("dd", { children: e.value })] }, `${String(e.label)}-${String(e.value)}`)) }),
|
|
38
|
+
u === "failed" && p && /* @__PURE__ */ r("div", {
|
|
39
|
+
role: "alert",
|
|
40
|
+
className: "dishui-ai-fine-tune-card__error",
|
|
41
|
+
children: p
|
|
42
|
+
}),
|
|
43
|
+
/* @__PURE__ */ i("footer", { children: [
|
|
44
|
+
u === "draft" && m && /* @__PURE__ */ r(t, {
|
|
45
|
+
type: "button",
|
|
46
|
+
variant: "primary",
|
|
47
|
+
size: "sm",
|
|
48
|
+
disabled: _,
|
|
49
|
+
onClick: m,
|
|
50
|
+
children: v?.start ?? "Start training"
|
|
51
|
+
}),
|
|
52
|
+
S && h && /* @__PURE__ */ r(t, {
|
|
53
|
+
type: "button",
|
|
54
|
+
variant: "secondary",
|
|
55
|
+
size: "sm",
|
|
56
|
+
disabled: _,
|
|
57
|
+
onClick: h,
|
|
58
|
+
children: v?.cancel ?? "Cancel"
|
|
59
|
+
}),
|
|
60
|
+
u === "failed" && g && /* @__PURE__ */ r(t, {
|
|
61
|
+
type: "button",
|
|
62
|
+
variant: "primary",
|
|
63
|
+
size: "sm",
|
|
64
|
+
disabled: _,
|
|
65
|
+
onClick: g,
|
|
66
|
+
children: v?.retry ?? "Retry"
|
|
67
|
+
})
|
|
68
|
+
] })
|
|
69
|
+
]
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
//#endregion
|
|
73
|
+
export { s as default };
|
|
74
|
+
|
|
75
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/ai/FineTuneCard/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../../utils/cn';\nimport Button from '../../Button';\nimport { clamp } from '../shared';\nimport './FineTuneCard.css';\n\nexport type FineTuneMetric = {\n label: React.ReactNode;\n value: React.ReactNode;\n};\n\nexport type FineTuneCardProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> & {\n title: React.ReactNode;\n model?: string;\n description?: React.ReactNode;\n status?: 'draft' | 'queued' | 'training' | 'ready' | 'failed';\n progress?: number;\n metrics?: FineTuneMetric[];\n error?: React.ReactNode;\n onStart?: () => void;\n onCancel?: () => void;\n onRetry?: () => void;\n disabled?: boolean;\n labels?: { start?: string; cancel?: string; retry?: string };\n};\n\nconst STATUS = {\n draft: 'Draft',\n queued: 'Queued',\n training: 'Training',\n ready: 'Ready',\n failed: 'Failed',\n} as const;\nconst EMPTY_METRICS: FineTuneMetric[] = [];\n\nexport default function FineTuneCard({\n title,\n model,\n description,\n status = 'draft',\n progress = 0,\n metrics = EMPTY_METRICS,\n error,\n onStart,\n onCancel,\n onRetry,\n disabled = false,\n labels,\n className,\n ...rest\n}: FineTuneCardProps) {\n const pct = Math.round(clamp(progress, 0, 1) * 100);\n const active = status === 'queued' || status === 'training';\n\n return (\n <article {...rest} className={cn('dishui-ai-fine-tune-card', `dishui-ai-fine-tune-card--${status}`, className)}>\n <header>\n <div>\n <h3>{title}</h3>\n {model && <code>{model}</code>}\n </div>\n <span className=\"dishui-ai-fine-tune-card__status\">{STATUS[status]}</span>\n </header>\n\n {description && <div className=\"dishui-ai-fine-tune-card__description\">{description}</div>}\n\n {active && (\n <div className=\"dishui-ai-fine-tune-card__progress\">\n <div><span>Training progress</span><strong>{pct}%</strong></div>\n <progress max={100} value={pct}>{pct}%</progress>\n </div>\n )}\n\n {metrics.length > 0 && (\n <dl>\n {metrics.map(metric => (\n <div key={`${String(metric.label)}-${String(metric.value)}`}>\n <dt>{metric.label}</dt>\n <dd>{metric.value}</dd>\n </div>\n ))}\n </dl>\n )}\n\n {status === 'failed' && error && (\n <div role=\"alert\" className=\"dishui-ai-fine-tune-card__error\">{error}</div>\n )}\n\n <footer>\n {status === 'draft' && onStart && (\n <Button type=\"button\" variant=\"primary\" size=\"sm\" disabled={disabled} onClick={onStart}>\n {labels?.start ?? 'Start training'}\n </Button>\n )}\n {active && onCancel && (\n <Button type=\"button\" variant=\"secondary\" size=\"sm\" disabled={disabled} onClick={onCancel}>\n {labels?.cancel ?? 'Cancel'}\n </Button>\n )}\n {status === 'failed' && onRetry && (\n <Button type=\"button\" variant=\"primary\" size=\"sm\" disabled={disabled} onClick={onRetry}>\n {labels?.retry ?? 'Retry'}\n </Button>\n )}\n </footer>\n </article>\n );\n}\n"],"mappings":";;;;;;;AA0BA,IAAM,IAAS;CACb,OAAO;CACP,QAAQ;CACR,UAAU;CACV,OAAO;CACP,QAAQ;AACV,GACM,IAAkC,CAAC;AAEzC,SAAwB,EAAa,EACnC,UACA,UACA,gBACA,YAAS,SACT,cAAW,GACX,aAAU,GACV,UACA,YACA,aACA,YACA,cAAW,IACX,WACA,cACA,GAAG,KACiB;CACpB,IAAM,IAAM,KAAK,MAAM,EAAM,GAAU,GAAG,CAAC,IAAI,GAAG,GAC5C,IAAS,MAAW,YAAY,MAAW;CAEjD,OACE,kBAAC,WAAD;EAAS,GAAI;EAAM,WAAW,EAAG,4BAA4B,6BAA6B,KAAU,CAAS;EAA7G,UAAA;GACE,kBAAC,UAAD,EAAA,UAAA,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD,EAAA,UAAK,EAAU,CAAA,GACd,KAAS,kBAAC,QAAD,EAAA,UAAO,EAAY,CAAA,CAC1B,EAAA,CAAA,GACL,kBAAC,QAAD;IAAM,WAAU;IAAoC,UAAA,EAAO;GAAc,CAAA,CACnE,EAAA,CAAA;GAEP,KAAe,kBAAC,OAAD;IAAK,WAAU;IAAyC,UAAA;GAAiB,CAAA;GAExF,KACC,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,kBAAC,OAAD,EAAA,UAAA,CAAK,kBAAC,QAAD,EAAA,UAAM,oBAAuB,CAAA,GAAC,kBAAC,UAAD,EAAA,UAAA,CAAS,GAAI,GAAS,EAAA,CAAA,CAAM,EAAA,CAAA,GAC/D,kBAAC,YAAD;KAAU,KAAK;KAAK,OAAO;KAA3B,UAAA,CAAiC,GAAI,GAAW;IAC7C,CAAA,CAAA;;GAGN,EAAQ,SAAS,KAChB,kBAAC,MAAD,EAAA,UACG,EAAQ,KAAI,MACX,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD,EAAA,UAAK,EAAO,MAAU,CAAA,GACtB,kBAAC,MAAD,EAAA,UAAK,EAAO,MAAU,CAAA,CACnB,EAAA,GAHK,GAAG,OAAO,EAAO,KAAK,EAAE,GAAG,OAAO,EAAO,KAAK,GAGnD,CACN,EACC,CAAA;GAGL,MAAW,YAAY,KACtB,kBAAC,OAAD;IAAK,MAAK;IAAQ,WAAU;IAAmC,UAAA;GAAW,CAAA;GAG5E,kBAAC,UAAD,EAAA,UAAA;IACG,MAAW,WAAW,KACrB,kBAAC,GAAD;KAAQ,MAAK;KAAS,SAAQ;KAAU,MAAK;KAAe;KAAU,SAAS;KAC5E,UAAA,GAAQ,SAAS;IACZ,CAAA;IAET,KAAU,KACT,kBAAC,GAAD;KAAQ,MAAK;KAAS,SAAQ;KAAY,MAAK;KAAe;KAAU,SAAS;KAC9E,UAAA,GAAQ,UAAU;IACb,CAAA;IAET,MAAW,YAAY,KACtB,kBAAC,GAAD;KAAQ,MAAK;KAAS,SAAQ;KAAU,MAAK;KAAe;KAAU,SAAS;KAC5E,UAAA,GAAQ,SAAS;IACZ,CAAA;GAEJ,EAAA,CAAA;EACD;;AAEb"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type InsightCardItem = {
|
|
3
|
+
id: string;
|
|
4
|
+
label: React.ReactNode;
|
|
5
|
+
value: React.ReactNode;
|
|
6
|
+
detail?: React.ReactNode;
|
|
7
|
+
trend?: {
|
|
8
|
+
value: string;
|
|
9
|
+
direction: 'up' | 'down' | 'flat';
|
|
10
|
+
label?: string;
|
|
11
|
+
};
|
|
12
|
+
status?: 'neutral' | 'success' | 'warning' | 'danger' | 'info';
|
|
13
|
+
};
|
|
14
|
+
export type InsightCardsProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'children' | 'onSelect'> & {
|
|
15
|
+
items: InsightCardItem[];
|
|
16
|
+
columns?: 2 | 3 | 4;
|
|
17
|
+
selectedId?: string;
|
|
18
|
+
defaultSelectedId?: string;
|
|
19
|
+
onSelect?: (item: InsightCardItem) => void;
|
|
20
|
+
loading?: boolean;
|
|
21
|
+
emptyText?: React.ReactNode;
|
|
22
|
+
};
|
|
23
|
+
export default function InsightCards({ items, columns, selectedId, defaultSelectedId, onSelect, loading, emptyText, className, ...rest }: InsightCardsProps): React.JSX.Element;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { cn as e } from "../../../utils/cn.js";
|
|
2
|
+
/* empty css */
|
|
3
|
+
import { useState as t } from "react";
|
|
4
|
+
import { Fragment as n, jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
5
|
+
//#region src/components/ai/InsightCards/index.tsx
|
|
6
|
+
function a({ items: a, columns: o = 3, selectedId: s, defaultSelectedId: c, onSelect: l, loading: u = !1, emptyText: d = "No insights available", className: f, ...p }) {
|
|
7
|
+
let [m, h] = t(c), g = s ?? m, _ = (e) => {
|
|
8
|
+
s === void 0 && h(e.id), l?.(e);
|
|
9
|
+
};
|
|
10
|
+
if (!u && !a.length) return /* @__PURE__ */ r("div", {
|
|
11
|
+
...p,
|
|
12
|
+
className: e("dishui-ai-insight-cards dishui-ai-insight-cards--empty", f),
|
|
13
|
+
children: d
|
|
14
|
+
});
|
|
15
|
+
let v = u ? Array.from({ length: o }, (e, t) => ({
|
|
16
|
+
id: `loading-${t}`,
|
|
17
|
+
label: "",
|
|
18
|
+
value: ""
|
|
19
|
+
})) : a;
|
|
20
|
+
return /* @__PURE__ */ r("div", {
|
|
21
|
+
...p,
|
|
22
|
+
className: e("dishui-ai-insight-cards", `dishui-ai-insight-cards--${o}`, f),
|
|
23
|
+
children: v.map((t) => {
|
|
24
|
+
let a = /* @__PURE__ */ i(n, { children: [
|
|
25
|
+
/* @__PURE__ */ r("span", {
|
|
26
|
+
className: "dishui-ai-insight-cards__label",
|
|
27
|
+
children: t.label
|
|
28
|
+
}),
|
|
29
|
+
/* @__PURE__ */ r("strong", {
|
|
30
|
+
className: "dishui-ai-insight-cards__value",
|
|
31
|
+
children: t.value
|
|
32
|
+
}),
|
|
33
|
+
t.trend && /* @__PURE__ */ i("span", {
|
|
34
|
+
className: e("dishui-ai-insight-cards__trend", `dishui-ai-insight-cards__trend--${t.trend.direction}`),
|
|
35
|
+
children: [
|
|
36
|
+
t.trend.direction === "up" ? "↑" : t.trend.direction === "down" ? "↓" : "→",
|
|
37
|
+
" ",
|
|
38
|
+
t.trend.value,
|
|
39
|
+
t.trend.label && /* @__PURE__ */ i("span", { children: [" ", t.trend.label] })
|
|
40
|
+
]
|
|
41
|
+
}),
|
|
42
|
+
t.detail && /* @__PURE__ */ r("span", {
|
|
43
|
+
className: "dishui-ai-insight-cards__detail",
|
|
44
|
+
children: t.detail
|
|
45
|
+
}),
|
|
46
|
+
u && /* @__PURE__ */ i(n, { children: [/* @__PURE__ */ r("span", { className: "dishui-ai-insight-cards__skeleton" }), /* @__PURE__ */ r("span", { className: "dishui-ai-insight-cards__skeleton dishui-ai-insight-cards__skeleton--short" })] })
|
|
47
|
+
] });
|
|
48
|
+
return l ? /* @__PURE__ */ r("button", {
|
|
49
|
+
type: "button",
|
|
50
|
+
className: e("dishui-ai-insight-cards__card", t.status && `dishui-ai-insight-cards__card--${t.status}`, g === t.id && "dishui-ai-insight-cards__card--selected"),
|
|
51
|
+
"aria-pressed": g === t.id,
|
|
52
|
+
onClick: () => _(t),
|
|
53
|
+
children: a
|
|
54
|
+
}, t.id) : /* @__PURE__ */ r("article", {
|
|
55
|
+
className: e("dishui-ai-insight-cards__card", t.status && `dishui-ai-insight-cards__card--${t.status}`),
|
|
56
|
+
children: a
|
|
57
|
+
}, t.id);
|
|
58
|
+
})
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
export { a as default };
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/ai/InsightCards/index.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { cn } from '../../../utils/cn';\nimport './InsightCards.css';\n\nexport type InsightCardItem = { id: string; label: React.ReactNode; value: React.ReactNode; detail?: React.ReactNode; trend?: { value: string; direction: 'up' | 'down' | 'flat'; label?: string }; status?: 'neutral' | 'success' | 'warning' | 'danger' | 'info' };\nexport type InsightCardsProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'children' | 'onSelect'> & { items: InsightCardItem[]; columns?: 2 | 3 | 4; selectedId?: string; defaultSelectedId?: string; onSelect?: (item: InsightCardItem) => void; loading?: boolean; emptyText?: React.ReactNode };\n\nexport default function InsightCards({ items, columns = 3, selectedId, defaultSelectedId, onSelect, loading = false, emptyText = 'No insights available', className, ...rest }: InsightCardsProps) {\n const [internal, setInternal] = useState(defaultSelectedId); const selected = selectedId ?? internal;\n const select = (item: InsightCardItem) => { if (selectedId === undefined) setInternal(item.id); onSelect?.(item); };\n if (!loading && !items.length) return <div {...rest} className={cn('dishui-ai-insight-cards dishui-ai-insight-cards--empty', className)}>{emptyText}</div>;\n const content = loading ? Array.from({ length: columns }, (_, i) => ({ id: `loading-${i}`, label: '', value: '' } as InsightCardItem)) : items;\n return <div {...rest} className={cn('dishui-ai-insight-cards', `dishui-ai-insight-cards--${columns}`, className)}>{content.map(item => { const body = <><span className=\"dishui-ai-insight-cards__label\">{item.label}</span><strong className=\"dishui-ai-insight-cards__value\">{item.value}</strong>{item.trend && <span className={cn('dishui-ai-insight-cards__trend', `dishui-ai-insight-cards__trend--${item.trend.direction}`)}>{item.trend.direction === 'up' ? '↑' : item.trend.direction === 'down' ? '↓' : '→'} {item.trend.value}{item.trend.label && <span> {item.trend.label}</span>}</span>}{item.detail && <span className=\"dishui-ai-insight-cards__detail\">{item.detail}</span>}{loading && <><span className=\"dishui-ai-insight-cards__skeleton\"/><span className=\"dishui-ai-insight-cards__skeleton dishui-ai-insight-cards__skeleton--short\"/></>}</>; return onSelect ? <button type=\"button\" key={item.id} className={cn('dishui-ai-insight-cards__card', item.status && `dishui-ai-insight-cards__card--${item.status}`, selected === item.id && 'dishui-ai-insight-cards__card--selected')} aria-pressed={selected === item.id} onClick={() => select(item)}>{body}</button> : <article key={item.id} className={cn('dishui-ai-insight-cards__card', item.status && `dishui-ai-insight-cards__card--${item.status}`)}>{body}</article>; })}</div>;\n}\n"],"mappings":";;;;;AAOA,SAAwB,EAAa,EAAE,UAAO,aAAU,GAAG,eAAY,sBAAmB,aAAU,aAAU,IAAO,eAAY,yBAAyB,cAAW,GAAG,KAA2B;CACjM,IAAM,CAAC,GAAU,KAAe,EAAS,CAAiB,GAAS,IAAW,KAAc,GACtF,KAAU,MAA0B;EAAsD,AAAhD,MAAe,KAAA,KAAW,EAAY,EAAK,EAAE,GAAG,IAAW,CAAI;CAAG;CAClH,IAAI,CAAC,KAAW,CAAC,EAAM,QAAQ,OAAO,kBAAC,OAAD;EAAK,GAAI;EAAM,WAAW,EAAG,0DAA0D,CAAS;EAAI,UAAA;CAAe,CAAA;CACzJ,IAAM,IAAU,IAAU,MAAM,KAAK,EAAE,QAAQ,EAAQ,IAAI,GAAG,OAAO;EAAE,IAAI,WAAW;EAAK,OAAO;EAAI,OAAO;CAAG,EAAqB,IAAI;CACzI,OAAO,kBAAC,OAAD;EAAK,GAAI;EAAM,WAAW,EAAG,2BAA2B,4BAA4B,KAAW,CAAS;EAAI,UAAA,EAAQ,KAAI,MAAQ;GAAE,IAAM,IAAO,kBAAA,GAAA,EAAA,UAAA;IAAE,kBAAC,QAAD;KAAM,WAAU;KAAkC,UAAA,EAAK;IAAY,CAAA;IAAC,kBAAC,UAAD;KAAQ,WAAU;KAAkC,UAAA,EAAK;IAAc,CAAA;IAAE,EAAK,SAAS,kBAAC,QAAD;KAAM,WAAW,EAAG,kCAAkC,mCAAmC,EAAK,MAAM,WAAW;KAA/G,UAAA;MAAmH,EAAK,MAAM,cAAc,OAAO,MAAM,EAAK,MAAM,cAAc,SAAS,MAAM;MAAI;MAAE,EAAK,MAAM;MAAO,EAAK,MAAM,SAAS,kBAAC,QAAD,EAAA,UAAA,CAAM,KAAE,EAAK,MAAM,KAAY,EAAA,CAAA;KAAQ;;IAAG,EAAK,UAAU,kBAAC,QAAD;KAAM,WAAU;KAAmC,UAAA,EAAK;IAAa,CAAA;IAAG,KAAW,kBAAA,GAAA,EAAA,UAAA,CAAE,kBAAC,QAAD,EAAM,WAAU,oCAAoC,CAAA,GAAC,kBAAC,QAAD,EAAM,WAAU,6EAA6E,CAAA,CAAG,EAAA,CAAA;GAAI,EAAA,CAAA;GAAG,OAAO,IAAW,kBAAC,UAAD;IAAQ,MAAK;IAAuB,WAAW,EAAG,iCAAiC,EAAK,UAAU,kCAAkC,EAAK,UAAU,MAAa,EAAK,MAAM,yCAAyC;IAAG,gBAAc,MAAa,EAAK;IAAI,eAAe,EAAO,CAAI;IAAI,UAAA;GAAa,GAA3Q,EAAK,EAAsQ,IAAI,kBAAC,WAAD;IAAuB,WAAW,EAAG,iCAAiC,EAAK,UAAU,kCAAkC,EAAK,QAAQ;IAAI,UAAA;GAAc,GAAxI,EAAK,EAAmI;EAAG,CAAC;CAAO,CAAA;AACzyC"}
|