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.
Files changed (156) hide show
  1. package/dist/.release-verified.json +6 -0
  2. package/dist/ai.js +24 -0
  3. package/dist/components/Card/Metric2.js +11 -11
  4. package/dist/components/Card/Metric2.js.map +1 -1
  5. package/dist/components/Card/Ticket.d.ts +52 -0
  6. package/dist/components/Card/Ticket2.js +218 -0
  7. package/dist/components/Card/Ticket2.js.map +1 -0
  8. package/dist/components/Card/index.d.ts +32 -0
  9. package/dist/components/Card/index.js +211 -203
  10. package/dist/components/Card/index.js.map +1 -1
  11. package/dist/components/GroupButton/index.js +4 -4
  12. package/dist/components/GroupButton/index.js.map +1 -1
  13. package/dist/components/GroupedTable/index.js +10 -10
  14. package/dist/components/GroupedTable/index.js.map +1 -1
  15. package/dist/components/NavigationList/index.js +9 -9
  16. package/dist/components/NavigationList/index.js.map +1 -1
  17. package/dist/components/Section/index.js +11 -11
  18. package/dist/components/Section/index.js.map +1 -1
  19. package/dist/components/Skeleton/index.js +1 -1
  20. package/dist/components/Skeleton/index.js.map +1 -1
  21. package/dist/components/Table/index.js +6 -6
  22. package/dist/components/Table/index.js.map +1 -1
  23. package/dist/components/ai/AgentChat/index.d.ts +54 -0
  24. package/dist/components/ai/AgentChat/index.js +176 -0
  25. package/dist/components/ai/AgentChat/index.js.map +1 -0
  26. package/dist/components/ai/AgentRunCard/index.d.ts +38 -0
  27. package/dist/components/ai/AgentRunCard/index.js +100 -0
  28. package/dist/components/ai/AgentRunCard/index.js.map +1 -0
  29. package/dist/components/ai/AgentScreen/index.d.ts +50 -0
  30. package/dist/components/ai/AgentScreen/index.js +233 -0
  31. package/dist/components/ai/AgentScreen/index.js.map +1 -0
  32. package/dist/components/ai/ApprovalCard/index.d.ts +26 -0
  33. package/dist/components/ai/ApprovalCard/index.js +89 -0
  34. package/dist/components/ai/ApprovalCard/index.js.map +1 -0
  35. package/dist/components/ai/CodeView/index.d.ts +30 -0
  36. package/dist/components/ai/CodeView/index.js +149 -0
  37. package/dist/components/ai/CodeView/index.js.map +1 -0
  38. package/dist/components/ai/CommandSearch/index.d.ts +39 -0
  39. package/dist/components/ai/CommandSearch/index.js +217 -0
  40. package/dist/components/ai/CommandSearch/index.js.map +1 -0
  41. package/dist/components/ai/ContextCards/index.d.ts +42 -0
  42. package/dist/components/ai/ContextCards/index.js +106 -0
  43. package/dist/components/ai/ContextCards/index.js.map +1 -0
  44. package/dist/components/ai/DiffTable/index.d.ts +70 -0
  45. package/dist/components/ai/DiffTable/index.js +235 -0
  46. package/dist/components/ai/DiffTable/index.js.map +1 -0
  47. package/dist/components/ai/FilterTable/index.d.ts +35 -0
  48. package/dist/components/ai/FilterTable/index.js +86 -0
  49. package/dist/components/ai/FilterTable/index.js.map +1 -0
  50. package/dist/components/ai/FineTuneCard/index.d.ts +24 -0
  51. package/dist/components/ai/FineTuneCard/index.js +75 -0
  52. package/dist/components/ai/FineTuneCard/index.js.map +1 -0
  53. package/dist/components/ai/InsightCards/index.d.ts +23 -0
  54. package/dist/components/ai/InsightCards/index.js +64 -0
  55. package/dist/components/ai/InsightCards/index.js.map +1 -0
  56. package/dist/components/ai/IssueCard/index.d.ts +39 -0
  57. package/dist/components/ai/IssueCard/index.js +78 -0
  58. package/dist/components/ai/IssueCard/index.js.map +1 -0
  59. package/dist/components/ai/LoadingState/index.d.ts +22 -0
  60. package/dist/components/ai/LoadingState/index.js +80 -0
  61. package/dist/components/ai/LoadingState/index.js.map +1 -0
  62. package/dist/components/ai/PromptBar/index.d.ts +26 -0
  63. package/dist/components/ai/PromptBar/index.js +117 -0
  64. package/dist/components/ai/PromptBar/index.js.map +1 -0
  65. package/dist/components/ai/RecommendationCard/index.d.ts +44 -0
  66. package/dist/components/ai/RecommendationCard/index.js +142 -0
  67. package/dist/components/ai/RecommendationCard/index.js.map +1 -0
  68. package/dist/components/ai/RecordsTable/index.d.ts +65 -0
  69. package/dist/components/ai/RecordsTable/index.js +334 -0
  70. package/dist/components/ai/RecordsTable/index.js.map +1 -0
  71. package/dist/components/ai/SelectionActions/index.d.ts +19 -0
  72. package/dist/components/ai/SelectionActions/index.js +40 -0
  73. package/dist/components/ai/SelectionActions/index.js.map +1 -0
  74. package/dist/components/ai/StateFlow/index.d.ts +24 -0
  75. package/dist/components/ai/StateFlow/index.js +50 -0
  76. package/dist/components/ai/StateFlow/index.js.map +1 -0
  77. package/dist/components/ai/StreamingText/index.d.ts +44 -0
  78. package/dist/components/ai/StreamingText/index.js +211 -0
  79. package/dist/components/ai/StreamingText/index.js.map +1 -0
  80. package/dist/components/ai/TaskRows/index.d.ts +53 -0
  81. package/dist/components/ai/TaskRows/index.js +186 -0
  82. package/dist/components/ai/TaskRows/index.js.map +1 -0
  83. package/dist/components/ai/Thinking/index.d.ts +47 -0
  84. package/dist/components/ai/Thinking/index.js +197 -0
  85. package/dist/components/ai/Thinking/index.js.map +1 -0
  86. package/dist/components/ai/ToolChips/index.d.ts +21 -0
  87. package/dist/components/ai/ToolChips/index.js +63 -0
  88. package/dist/components/ai/ToolChips/index.js.map +1 -0
  89. package/dist/components/ai/index.d.ts +54 -0
  90. package/dist/components/ai/shared.d.ts +13 -0
  91. package/dist/components/ai/shared.js +25 -0
  92. package/dist/components/ai/shared.js.map +1 -0
  93. package/dist/components/pro/DataTable/rowDetailExtension.js +1 -1
  94. package/dist/components/pro/DataTable/rowDetailExtension.js.map +1 -1
  95. package/dist/components/pro/Flow/constants.js +3 -3
  96. package/dist/components/pro/Flow/constants.js.map +1 -1
  97. package/dist/components/pro/Flow/nodes/shapes.js +3 -3
  98. package/dist/components/pro/Flow/nodes/shapes.js.map +1 -1
  99. package/dist/components/pro/Flow/utils/themeColor.d.ts +2 -2
  100. package/dist/components/pro/Flow/utils/themeColor.js +2 -2
  101. package/dist/components/pro/Flow/utils/themeColor.js.map +1 -1
  102. package/dist/components/pro/Kanban/Kanban.d.ts +3 -0
  103. package/dist/components/pro/Kanban/Kanban.js +339 -0
  104. package/dist/components/pro/Kanban/Kanban.js.map +1 -0
  105. package/dist/components/pro/Kanban/Swimlanes.d.ts +3 -0
  106. package/dist/components/pro/Kanban/Swimlanes.js +60 -0
  107. package/dist/components/pro/Kanban/Swimlanes.js.map +1 -0
  108. package/dist/components/pro/Kanban/index.d.ts +5 -0
  109. package/dist/components/pro/Kanban/types.d.ts +103 -0
  110. package/dist/components/pro/Kanban/useKanbanDrag.d.ts +17 -0
  111. package/dist/components/pro/Kanban/useKanbanDrag.js +69 -0
  112. package/dist/components/pro/Kanban/useKanbanDrag.js.map +1 -0
  113. package/dist/components/pro/Kanban/utils.d.ts +13 -0
  114. package/dist/components/pro/Kanban/utils.js +48 -0
  115. package/dist/components/pro/Kanban/utils.js.map +1 -0
  116. package/dist/components/pro/RichTextEditor/AIRewrite.js +158 -127
  117. package/dist/components/pro/RichTextEditor/AIRewrite.js.map +1 -1
  118. package/dist/components/pro/RichTextEditor/BlockHandle.d.ts +2 -0
  119. package/dist/components/pro/RichTextEditor/BlockHandle.js +156 -115
  120. package/dist/components/pro/RichTextEditor/BlockHandle.js.map +1 -1
  121. package/dist/components/pro/RichTextEditor/RichTextEditor.js +136 -159
  122. package/dist/components/pro/RichTextEditor/RichTextEditor.js.map +1 -1
  123. package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js +44 -41
  124. package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
  125. package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js +59 -53
  126. package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js.map +1 -1
  127. package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js +48 -44
  128. package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js.map +1 -1
  129. package/dist/components/pro/RichTextEditor/Toolbar/TableOpsMenu.js +67 -63
  130. package/dist/components/pro/RichTextEditor/Toolbar/TableOpsMenu.js.map +1 -1
  131. package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.d.ts +1 -0
  132. package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js +182 -129
  133. package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
  134. package/dist/components/pro/RichTextEditor/Toolbar/ToolbarButton.d.ts +1 -0
  135. package/dist/components/pro/RichTextEditor/Toolbar/ToolbarButton.js +3 -3
  136. package/dist/components/pro/RichTextEditor/Toolbar/ToolbarButton.js.map +1 -1
  137. package/dist/components/pro/RichTextEditor/Toolbar/useAnchoredDropdown.d.ts +3 -0
  138. package/dist/components/pro/RichTextEditor/Toolbar/useAnchoredDropdown.js +31 -0
  139. package/dist/components/pro/RichTextEditor/Toolbar/useAnchoredDropdown.js.map +1 -0
  140. package/dist/components/pro/RichTextEditor/index.d.ts +1 -1
  141. package/dist/components/pro/RichTextEditor/types.d.ts +78 -11
  142. package/dist/components/pro/RichTextEditor/types.js +11 -0
  143. package/dist/components/pro/RichTextEditor/types.js.map +1 -1
  144. package/dist/dishui.css +1 -1
  145. package/dist/index-nostyled.d.ts +1 -1
  146. package/dist/index.d.ts +6 -3
  147. package/dist/index.js +134 -107
  148. package/dist/kanban.js +5 -0
  149. package/dist/layouts/Sidebar.d.ts +16 -0
  150. package/dist/layouts/Sidebar.js +85 -52
  151. package/dist/layouts/Sidebar.js.map +1 -1
  152. package/dist/utils/i18n.js +20 -0
  153. package/dist/utils/i18n.js.map +1 -1
  154. package/dist/utils/menu.js +1 -1
  155. package/dist/utils/menu.js.map +1 -1
  156. package/package.json +14 -3
@@ -0,0 +1,211 @@
1
+ import { cn as e } from "../../../utils/cn.js";
2
+ /* empty css */
3
+ import t, { useEffect as n, useState as r } from "react";
4
+ import { Fragment as i, jsx as a, jsxs as o } from "react/jsx-runtime";
5
+ //#region src/components/ai/StreamingText/index.tsx
6
+ var s = 30, c = {
7
+ width: 16,
8
+ height: 16,
9
+ viewBox: "0 0 24 24",
10
+ fill: "none",
11
+ stroke: "currentColor",
12
+ strokeWidth: 2,
13
+ strokeLinecap: "round",
14
+ strokeLinejoin: "round",
15
+ "aria-hidden": !0
16
+ }, l = () => /* @__PURE__ */ o("svg", {
17
+ ...c,
18
+ children: [/* @__PURE__ */ a("rect", {
19
+ width: "14",
20
+ height: "14",
21
+ x: "8",
22
+ y: "8",
23
+ rx: "2"
24
+ }), /* @__PURE__ */ a("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })]
25
+ }), u = () => /* @__PURE__ */ o("svg", {
26
+ ...c,
27
+ children: [
28
+ /* @__PURE__ */ a("path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8" }),
29
+ /* @__PURE__ */ a("path", { d: "M21 3v5h-5" }),
30
+ /* @__PURE__ */ a("path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16" }),
31
+ /* @__PURE__ */ a("path", { d: "M8 16H3v5" })
32
+ ]
33
+ }), d = () => /* @__PURE__ */ o("svg", {
34
+ ...c,
35
+ children: [/* @__PURE__ */ a("path", { d: "M7 10v12" }), /* @__PURE__ */ a("path", { d: "M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z" })]
36
+ }), f = () => /* @__PURE__ */ o("svg", {
37
+ ...c,
38
+ children: [/* @__PURE__ */ a("path", { d: "M17 14V2" }), /* @__PURE__ */ a("path", { d: "M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22a3.13 3.13 0 0 1-3-3.88Z" })]
39
+ }), p = () => /* @__PURE__ */ o("svg", {
40
+ ...c,
41
+ children: [/* @__PURE__ */ a("path", { d: "M7 17 17 7" }), /* @__PURE__ */ a("path", { d: "M7 7h10v10" })]
42
+ }), m = /\[(\d+)\]/g, h = (e) => (e.domain ?? e.title).trim().charAt(0).toUpperCase();
43
+ function g(e, t, n, r) {
44
+ if (!n) return [e];
45
+ let i = [], o = 0, s;
46
+ for (m.lastIndex = 0; (s = m.exec(e)) !== null;) {
47
+ s.index > o && i.push(e.slice(o, s.index));
48
+ let n = Number(s[1]), c = t?.[n - 1], l = c ? c.title : `Source ${n}`;
49
+ i.push(c?.url ? /* @__PURE__ */ a("a", {
50
+ className: "dishui-ai-streaming__cite",
51
+ href: c.url,
52
+ target: "_blank",
53
+ rel: "noreferrer",
54
+ title: l,
55
+ "aria-label": l,
56
+ children: n
57
+ }, `${r}-${s.index}`) : /* @__PURE__ */ a("span", {
58
+ className: "dishui-ai-streaming__cite",
59
+ title: l,
60
+ "aria-label": l,
61
+ role: "note",
62
+ children: n
63
+ }, `${r}-${s.index}`)), o = s.index + s[0].length;
64
+ }
65
+ return o < e.length && i.push(e.slice(o)), i;
66
+ }
67
+ function _({ text: c, streaming: m = !1, typewriter: _ = !1, typewriterSpeed: v = 3, sources: y, citations: b = !1, maxVisibleSources: x = 3, actions: S, onCopy: C, onRegenerate: w, onFeedback: T, followUps: E, onFollowUp: D, followUpsLabel: O = "Follow-ups", className: k, ...A }) {
68
+ let [j, M] = r(0), [N, P] = r(!1), F = _ && j < c.length;
69
+ n(() => {
70
+ if (!F) return;
71
+ let e = window.setTimeout(() => {
72
+ M((e) => Math.min(c.length, e + Math.max(1, v)));
73
+ }, s);
74
+ return () => window.clearTimeout(e);
75
+ }, [
76
+ F,
77
+ c.length,
78
+ v
79
+ ]);
80
+ let I = _ ? c.slice(0, j) : c, L = m || F, R = I.split(/\n{2,}/).filter((e, t, n) => e.length > 0 || L && t === n.length - 1), z = [];
81
+ C && z.push({
82
+ id: "copy",
83
+ label: "Copy",
84
+ icon: /* @__PURE__ */ a(l, {}),
85
+ onClick: () => C(c)
86
+ }), w && z.push({
87
+ id: "regenerate",
88
+ label: "Regenerate",
89
+ icon: /* @__PURE__ */ a(u, {}),
90
+ onClick: w
91
+ }), T && (z.push({
92
+ id: "up",
93
+ label: "Good response",
94
+ icon: /* @__PURE__ */ a(d, {}),
95
+ onClick: () => T("up")
96
+ }), z.push({
97
+ id: "down",
98
+ label: "Bad response",
99
+ icon: /* @__PURE__ */ a(f, {}),
100
+ onClick: () => T("down")
101
+ }));
102
+ let B = [...z, ...S ?? []], V = y ?? [], H = N ? V : V.slice(0, x), U = V.length - H.length;
103
+ return /* @__PURE__ */ o("div", {
104
+ ...A,
105
+ className: e("dishui-ai-streaming", L && "dishui-ai-streaming--live", k),
106
+ children: [
107
+ /* @__PURE__ */ a("div", {
108
+ className: "dishui-ai-streaming__body",
109
+ "aria-live": L ? "polite" : void 0,
110
+ "aria-busy": L || void 0,
111
+ children: R.map((e, n) => {
112
+ let r = e.split("\n"), i = n === R.length - 1;
113
+ return /* @__PURE__ */ o("p", {
114
+ className: "dishui-ai-streaming__paragraph",
115
+ children: [r.map((e, r) => /* @__PURE__ */ o(t.Fragment, { children: [r > 0 && /* @__PURE__ */ a("br", {}), g(e, y, b, `${n}-${r}`)] }, e)), i && L && /* @__PURE__ */ a("span", {
116
+ className: "dishui-ai-streaming__caret",
117
+ "aria-hidden": "true"
118
+ })]
119
+ }, e);
120
+ })
121
+ }),
122
+ V.length > 0 && /* @__PURE__ */ o("div", {
123
+ className: "dishui-ai-streaming__sources",
124
+ children: [/* @__PURE__ */ o("span", {
125
+ className: "dishui-ai-streaming__sources-count",
126
+ children: [
127
+ V.length,
128
+ " ",
129
+ V.length === 1 ? "source" : "sources"
130
+ ]
131
+ }), /* @__PURE__ */ o("ul", {
132
+ className: "dishui-ai-streaming__source-list",
133
+ children: [H.map((e, t) => {
134
+ let n = /* @__PURE__ */ o(i, { children: [
135
+ /* @__PURE__ */ a("span", {
136
+ className: "dishui-ai-streaming__source-icon",
137
+ "aria-hidden": "true",
138
+ children: e.favicon ?? h(e)
139
+ }),
140
+ /* @__PURE__ */ a("span", {
141
+ className: "dishui-ai-streaming__source-title",
142
+ children: e.title
143
+ }),
144
+ e.domain && /* @__PURE__ */ a("span", {
145
+ className: "dishui-ai-streaming__source-domain",
146
+ children: e.domain
147
+ })
148
+ ] });
149
+ return /* @__PURE__ */ a("li", { children: e.url ? /* @__PURE__ */ a("a", {
150
+ className: "dishui-ai-streaming__source",
151
+ href: e.url,
152
+ target: "_blank",
153
+ rel: "noreferrer",
154
+ title: `[${t + 1}] ${e.title}`,
155
+ children: n
156
+ }) : /* @__PURE__ */ a("span", {
157
+ className: "dishui-ai-streaming__source",
158
+ title: `[${t + 1}] ${e.title}`,
159
+ children: n
160
+ }) }, e.id);
161
+ }), (U > 0 || N) && V.length > x && /* @__PURE__ */ a("li", { children: /* @__PURE__ */ a("button", {
162
+ type: "button",
163
+ className: "dishui-ai-streaming__source dishui-ai-streaming__source--more",
164
+ "aria-expanded": N,
165
+ onClick: () => P((e) => !e),
166
+ children: N ? "Show less" : `+${U}`
167
+ }) })]
168
+ })]
169
+ }),
170
+ !L && B.length > 0 && /* @__PURE__ */ a("div", {
171
+ className: "dishui-ai-streaming__actions",
172
+ role: "toolbar",
173
+ "aria-label": "Answer actions",
174
+ children: B.map((t) => /* @__PURE__ */ a("button", {
175
+ type: "button",
176
+ className: e("dishui-ai-streaming__action", !t.icon && "dishui-ai-streaming__action--text"),
177
+ "aria-label": t.label,
178
+ title: t.label,
179
+ onClick: t.onClick,
180
+ children: t.icon ?? t.label
181
+ }, t.id))
182
+ }),
183
+ !L && E && E.length > 0 && /* @__PURE__ */ o("div", {
184
+ className: "dishui-ai-streaming__follow-ups",
185
+ children: [/* @__PURE__ */ a("div", {
186
+ className: "dishui-ai-streaming__follow-ups-label",
187
+ children: O
188
+ }), /* @__PURE__ */ a("ul", {
189
+ className: "dishui-ai-streaming__follow-up-list",
190
+ children: E.map((e) => /* @__PURE__ */ a("li", { children: /* @__PURE__ */ o("button", {
191
+ type: "button",
192
+ className: "dishui-ai-streaming__follow-up",
193
+ onClick: () => D?.(e),
194
+ children: [/* @__PURE__ */ a("span", {
195
+ className: "dishui-ai-streaming__follow-up-text",
196
+ children: e
197
+ }), /* @__PURE__ */ a("span", {
198
+ className: "dishui-ai-streaming__follow-up-icon",
199
+ "aria-hidden": "true",
200
+ children: /* @__PURE__ */ a(p, {})
201
+ })]
202
+ }) }, e))
203
+ })]
204
+ })
205
+ ]
206
+ });
207
+ }
208
+ //#endregion
209
+ export { _ as default };
210
+
211
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/ai/StreamingText/index.tsx"],"sourcesContent":["import React, { useEffect, useState } from 'react';\nimport { cn } from '../../../utils/cn';\nimport './StreamingText.css';\n\nexport type StreamingSource = {\n id: string;\n title: string;\n domain?: string;\n url?: string;\n favicon?: React.ReactNode;\n};\n\nexport type StreamingAction = {\n id: string;\n label: string;\n icon?: React.ReactNode;\n onClick?: () => void;\n};\n\nexport type StreamingFeedback = 'up' | 'down';\n\nexport type StreamingTextProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> & {\n /** Full or partial answer text. `\\n\\n` starts a new paragraph. */\n text: string;\n /** Shows the caret and hides actions / follow-ups until the answer is complete. */\n streaming?: boolean;\n /** Reveal `text` progressively on the client. Remount (key) to replay. */\n typewriter?: boolean;\n /** Characters revealed per tick in typewriter mode. */\n typewriterSpeed?: number;\n sources?: StreamingSource[];\n /** Render `[n]` markers in `text` as inline chips pointing at `sources[n - 1]`. */\n citations?: boolean;\n /** Source chips shown before the “+k” overflow toggle. */\n maxVisibleSources?: number;\n /** Extra actions appended after the built-in copy / regenerate / feedback buttons. */\n actions?: StreamingAction[];\n onCopy?: (text: string) => void;\n onRegenerate?: () => void;\n onFeedback?: (kind: StreamingFeedback) => void;\n followUps?: string[];\n onFollowUp?: (question: string) => void;\n followUpsLabel?: React.ReactNode;\n};\n\nconst TYPEWRITER_TICK_MS = 30;\n\nconst svgProps = { width: 16, height: 16, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2, strokeLinecap: 'round', strokeLinejoin: 'round', 'aria-hidden': true } as const;\nconst CopyIcon = () => (\n <svg {...svgProps}><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" /><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" /></svg>\n);\nconst RefreshIcon = () => (\n <svg {...svgProps}><path d=\"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\" /><path d=\"M21 3v5h-5\" /><path d=\"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16\" /><path d=\"M8 16H3v5\" /></svg>\n);\nconst ThumbsUpIcon = () => (\n <svg {...svgProps}><path d=\"M7 10v12\" /><path d=\"M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z\" /></svg>\n);\nconst ThumbsDownIcon = () => (\n <svg {...svgProps}><path d=\"M17 14V2\" /><path d=\"M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22a3.13 3.13 0 0 1-3-3.88Z\" /></svg>\n);\nconst ArrowIcon = () => (\n <svg {...svgProps}><path d=\"M7 17 17 7\" /><path d=\"M7 7h10v10\" /></svg>\n);\n\nconst CITATION_RE = /\\[(\\d+)\\]/g;\n\nconst initialOf = (source: StreamingSource) => (source.domain ?? source.title).trim().charAt(0).toUpperCase();\n\nfunction renderLine(line: string, sources: StreamingSource[] | undefined, citations: boolean, keyBase: string): React.ReactNode[] {\n if (!citations) return [line];\n const nodes: React.ReactNode[] = [];\n let last = 0;\n let match: RegExpExecArray | null;\n CITATION_RE.lastIndex = 0;\n while ((match = CITATION_RE.exec(line)) !== null) {\n if (match.index > last) nodes.push(line.slice(last, match.index));\n const n = Number(match[1]);\n const source = sources?.[n - 1];\n const label = source ? source.title : `Source ${n}`;\n nodes.push(\n source?.url ? (\n <a key={`${keyBase}-${match.index}`} className=\"dishui-ai-streaming__cite\" href={source.url} target=\"_blank\" rel=\"noreferrer\" title={label} aria-label={label}>{n}</a>\n ) : (\n <span key={`${keyBase}-${match.index}`} className=\"dishui-ai-streaming__cite\" title={label} aria-label={label} role=\"note\">{n}</span>\n ),\n );\n last = match.index + match[0].length;\n }\n if (last < line.length) nodes.push(line.slice(last));\n return nodes;\n}\n\n/**\n * Streamed answer: paragraphs with optional inline citations, a source bar,\n * an action row and follow-up questions. Fully controlled — it renders the\n * `text` it is given; `typewriter` only adds a client-side reveal.\n */\nexport default function StreamingText({\n text,\n streaming = false,\n typewriter = false,\n typewriterSpeed = 3,\n sources,\n citations = false,\n maxVisibleSources = 3,\n actions,\n onCopy,\n onRegenerate,\n onFeedback,\n followUps,\n onFollowUp,\n followUpsLabel = 'Follow-ups',\n className,\n ...rest\n}: StreamingTextProps) {\n const [revealed, setRevealed] = useState(0);\n const [showAllSources, setShowAllSources] = useState(false);\n\n const revealing = typewriter && revealed < text.length;\n useEffect(() => {\n if (!revealing) return;\n const id = window.setTimeout(() => {\n setRevealed(count => Math.min(text.length, count + Math.max(1, typewriterSpeed)));\n }, TYPEWRITER_TICK_MS);\n return () => window.clearTimeout(id);\n }, [revealing, text.length, typewriterSpeed]);\n\n const visibleText = typewriter ? text.slice(0, revealed) : text;\n const live = streaming || revealing;\n // Keep a trailing empty paragraph only while live so the caret has a home.\n const paragraphs = visibleText.split(/\\n{2,}/).filter((p, i, all) => p.length > 0 || (live && i === all.length - 1));\n\n const builtIns: StreamingAction[] = [];\n if (onCopy) builtIns.push({ id: 'copy', label: 'Copy', icon: <CopyIcon />, onClick: () => onCopy(text) });\n if (onRegenerate) builtIns.push({ id: 'regenerate', label: 'Regenerate', icon: <RefreshIcon />, onClick: onRegenerate });\n if (onFeedback) {\n builtIns.push({ id: 'up', label: 'Good response', icon: <ThumbsUpIcon />, onClick: () => onFeedback('up') });\n builtIns.push({ id: 'down', label: 'Bad response', icon: <ThumbsDownIcon />, onClick: () => onFeedback('down') });\n }\n const allActions = [...builtIns, ...(actions ?? [])];\n\n const sourceList = sources ?? [];\n const visibleSources = showAllSources ? sourceList : sourceList.slice(0, maxVisibleSources);\n const overflow = sourceList.length - visibleSources.length;\n\n return (\n <div {...rest} className={cn('dishui-ai-streaming', live && 'dishui-ai-streaming--live', className)}>\n <div className=\"dishui-ai-streaming__body\" aria-live={live ? 'polite' : undefined} aria-busy={live || undefined}>\n {paragraphs.map((paragraph, pi) => {\n const lines = paragraph.split('\\n');\n const isLast = pi === paragraphs.length - 1;\n return (\n <p key={paragraph} className=\"dishui-ai-streaming__paragraph\">\n {lines.map((line, li) => (\n <React.Fragment key={line}>\n {li > 0 && <br />}\n {renderLine(line, sources, citations, `${pi}-${li}`)}\n </React.Fragment>\n ))}\n {isLast && live && <span className=\"dishui-ai-streaming__caret\" aria-hidden=\"true\" />}\n </p>\n );\n })}\n </div>\n\n {sourceList.length > 0 && (\n <div className=\"dishui-ai-streaming__sources\">\n <span className=\"dishui-ai-streaming__sources-count\">\n {sourceList.length} {sourceList.length === 1 ? 'source' : 'sources'}\n </span>\n <ul className=\"dishui-ai-streaming__source-list\">\n {visibleSources.map((source, i) => {\n const inner = (\n <>\n <span className=\"dishui-ai-streaming__source-icon\" aria-hidden=\"true\">{source.favicon ?? initialOf(source)}</span>\n <span className=\"dishui-ai-streaming__source-title\">{source.title}</span>\n {source.domain && <span className=\"dishui-ai-streaming__source-domain\">{source.domain}</span>}\n </>\n );\n return (\n <li key={source.id}>\n {source.url ? (\n <a className=\"dishui-ai-streaming__source\" href={source.url} target=\"_blank\" rel=\"noreferrer\" title={`[${i + 1}] ${source.title}`}>{inner}</a>\n ) : (\n <span className=\"dishui-ai-streaming__source\" title={`[${i + 1}] ${source.title}`}>{inner}</span>\n )}\n </li>\n );\n })}\n {(overflow > 0 || showAllSources) && sourceList.length > maxVisibleSources && (\n <li>\n <button\n type=\"button\"\n className=\"dishui-ai-streaming__source dishui-ai-streaming__source--more\"\n aria-expanded={showAllSources}\n onClick={() => setShowAllSources(v => !v)}\n >\n {showAllSources ? 'Show less' : `+${overflow}`}\n </button>\n </li>\n )}\n </ul>\n </div>\n )}\n\n {!live && allActions.length > 0 && (\n <div className=\"dishui-ai-streaming__actions\" role=\"toolbar\" aria-label=\"Answer actions\">\n {allActions.map(action => (\n <button\n key={action.id}\n type=\"button\"\n className={cn('dishui-ai-streaming__action', !action.icon && 'dishui-ai-streaming__action--text')}\n aria-label={action.label}\n title={action.label}\n onClick={action.onClick}\n >\n {action.icon ?? action.label}\n </button>\n ))}\n </div>\n )}\n\n {!live && followUps && followUps.length > 0 && (\n <div className=\"dishui-ai-streaming__follow-ups\">\n <div className=\"dishui-ai-streaming__follow-ups-label\">{followUpsLabel}</div>\n <ul className=\"dishui-ai-streaming__follow-up-list\">\n {followUps.map(question => (\n <li key={question}>\n <button type=\"button\" className=\"dishui-ai-streaming__follow-up\" onClick={() => onFollowUp?.(question)}>\n <span className=\"dishui-ai-streaming__follow-up-text\">{question}</span>\n <span className=\"dishui-ai-streaming__follow-up-icon\" aria-hidden=\"true\"><ArrowIcon /></span>\n </button>\n </li>\n ))}\n </ul>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import React from 'react';
2
+ import type { AgentStatus } from '../shared';
3
+ export type AgentSubtask = {
4
+ id: string;
5
+ title: React.ReactNode;
6
+ /** Right-aligned value, e.g. `12/12`, `68%`, `draft`. */
7
+ value?: React.ReactNode;
8
+ status?: AgentStatus;
9
+ };
10
+ export type AgentTask = {
11
+ id: string;
12
+ title: React.ReactNode;
13
+ /** Short qualifier shown after the title, e.g. `12 suppliers`. */
14
+ meta?: React.ReactNode;
15
+ status: AgentStatus;
16
+ /** Determinate progress 0–100. Running tasks without it show an indeterminate bar. */
17
+ progress?: number;
18
+ subtasks?: AgentSubtask[];
19
+ /** Shown under a failed task, next to the retry action. */
20
+ error?: React.ReactNode;
21
+ };
22
+ export type TaskRowsView = 'capsules' | 'list';
23
+ export type TaskRowsLabels = {
24
+ capsules?: string;
25
+ list?: string;
26
+ retry?: string;
27
+ view?: string;
28
+ status?: Partial<Record<AgentStatus, string>>;
29
+ };
30
+ export type TaskRowsProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> & {
31
+ tasks: AgentTask[];
32
+ /** Controlled view mode. */
33
+ view?: TaskRowsView;
34
+ defaultView?: TaskRowsView;
35
+ onViewChange?: (view: TaskRowsView) => void;
36
+ /** Render the Capsules / List toggle above the tasks. */
37
+ showViewToggle?: boolean;
38
+ /** Controlled list of task ids whose subtasks are visible. */
39
+ expanded?: string[];
40
+ /** Defaults to every running or failed task. */
41
+ defaultExpanded?: string[];
42
+ onExpandedChange?: (expanded: string[]) => void;
43
+ /** Enables the retry action on failed tasks. */
44
+ onRetry?: (task: AgentTask) => void;
45
+ emptyText?: React.ReactNode;
46
+ labels?: TaskRowsLabels;
47
+ };
48
+ /**
49
+ * Live agent task status. Each task is a row (or capsule) with a text +
50
+ * colour status pill, optional progress and expandable subtasks with
51
+ * right-aligned tabular values.
52
+ */
53
+ export default function TaskRows({ tasks, view: viewProp, defaultView, onViewChange, showViewToggle, expanded: expandedProp, defaultExpanded, onExpandedChange, onRetry, emptyText, labels, className, ...rest }: TaskRowsProps): React.JSX.Element;
@@ -0,0 +1,186 @@
1
+ import { cn as e } from "../../../utils/cn.js";
2
+ import { AGENT_STATUS_LABEL as t, clamp as n } from "../shared.js";
3
+ /* empty css */
4
+ import { useCallback as r, useId as i, useState as a } from "react";
5
+ import { jsx as o, jsxs as s } from "react/jsx-runtime";
6
+ //#region src/components/ai/TaskRows/index.tsx
7
+ var c = {
8
+ capsules: "Capsules",
9
+ list: "List",
10
+ retry: "Retry",
11
+ view: "View"
12
+ }, l = {
13
+ pending: "neutral",
14
+ running: "info",
15
+ completed: "success",
16
+ failed: "danger",
17
+ skipped: "neutral"
18
+ }, u = () => /* @__PURE__ */ o("svg", {
19
+ width: "16",
20
+ height: "16",
21
+ viewBox: "0 0 24 24",
22
+ fill: "none",
23
+ stroke: "currentColor",
24
+ strokeWidth: "2",
25
+ strokeLinecap: "round",
26
+ strokeLinejoin: "round",
27
+ "aria-hidden": "true",
28
+ children: /* @__PURE__ */ o("path", { d: "m9 18 6-6-6-6" })
29
+ }), d = () => /* @__PURE__ */ s("svg", {
30
+ width: "16",
31
+ height: "16",
32
+ viewBox: "0 0 24 24",
33
+ fill: "none",
34
+ stroke: "currentColor",
35
+ strokeWidth: "2",
36
+ strokeLinecap: "round",
37
+ strokeLinejoin: "round",
38
+ "aria-hidden": "true",
39
+ children: [/* @__PURE__ */ o("path", { d: "M3 12a9 9 0 1 0 3-6.7" }), /* @__PURE__ */ o("path", { d: "M3 4v5h5" })]
40
+ }), f = ({ status: t, label: n }) => /* @__PURE__ */ s("span", {
41
+ className: e("dishui-ai-task-rows__status", `dishui-ai-task-rows__status--${l[t]}`),
42
+ children: [t === "running" && /* @__PURE__ */ o("span", {
43
+ className: "dishui-ai-task-rows__pulse",
44
+ "aria-hidden": "true"
45
+ }), n]
46
+ }), p = (e) => e.filter((e) => e.status === "running" || e.status === "failed").map((e) => e.id);
47
+ function m({ tasks: l, view: m, defaultView: h = "capsules", onViewChange: g, showViewToggle: _ = !1, expanded: v, defaultExpanded: y, onExpandedChange: b, onRetry: x, emptyText: S = "No tasks yet", labels: C, className: w, ...T }) {
48
+ let E = i(), D = {
49
+ ...c,
50
+ ...C
51
+ }, [O, k] = a(h), A = m ?? O, j = r((e) => {
52
+ k(e), g?.(e);
53
+ }, [g]), [M, N] = a(() => y ?? p(l)), P = v ?? M, F = r((e) => {
54
+ let t = P.includes(e) ? P.filter((t) => t !== e) : [...P, e];
55
+ N(t), b?.(t);
56
+ }, [P, b]), I = (e) => C?.status?.[e] ?? t[e];
57
+ return /* @__PURE__ */ s("div", {
58
+ ...T,
59
+ className: e("dishui-ai-task-rows", `dishui-ai-task-rows--${A}`, w),
60
+ children: [_ && /* @__PURE__ */ o("div", {
61
+ className: "dishui-ai-task-rows__toolbar",
62
+ children: /* @__PURE__ */ o("div", {
63
+ className: "dishui-ai-task-rows__segmented",
64
+ role: "group",
65
+ "aria-label": D.view,
66
+ children: ["capsules", "list"].map((t) => /* @__PURE__ */ o("button", {
67
+ type: "button",
68
+ className: e("dishui-ai-task-rows__segment", t === A && "dishui-ai-task-rows__segment--active"),
69
+ "aria-pressed": t === A,
70
+ onClick: () => j(t),
71
+ children: D[t]
72
+ }, t))
73
+ })
74
+ }), l.length === 0 ? /* @__PURE__ */ o("div", {
75
+ className: "dishui-ai-task-rows__empty",
76
+ children: S
77
+ }) : /* @__PURE__ */ o("ul", {
78
+ className: "dishui-ai-task-rows__list",
79
+ children: l.map((t) => {
80
+ let r = !!t.subtasks?.length, i = r && P.includes(t.id), a = `${E}-${t.id}`, c = t.progress === void 0 ? void 0 : n(t.progress, 0, 100), l = A === "capsules" && (c !== void 0 || t.status === "running");
81
+ return /* @__PURE__ */ s("li", {
82
+ className: e("dishui-ai-task-rows__task", `dishui-ai-task-rows__task--${t.status}`, i && "dishui-ai-task-rows__task--open"),
83
+ children: [
84
+ /* @__PURE__ */ s("div", {
85
+ className: "dishui-ai-task-rows__row",
86
+ children: [
87
+ r ? /* @__PURE__ */ s("button", {
88
+ type: "button",
89
+ className: "dishui-ai-task-rows__toggle",
90
+ "aria-expanded": i,
91
+ "aria-controls": a,
92
+ onClick: () => F(t.id),
93
+ children: [
94
+ /* @__PURE__ */ o("span", {
95
+ className: "dishui-ai-task-rows__chevron",
96
+ children: /* @__PURE__ */ o(u, {})
97
+ }),
98
+ /* @__PURE__ */ o("span", {
99
+ className: "dishui-ai-task-rows__title",
100
+ children: t.title
101
+ }),
102
+ t.meta !== void 0 && /* @__PURE__ */ o("span", {
103
+ className: "dishui-ai-task-rows__meta",
104
+ children: t.meta
105
+ })
106
+ ]
107
+ }) : /* @__PURE__ */ s("div", {
108
+ className: "dishui-ai-task-rows__toggle dishui-ai-task-rows__toggle--static",
109
+ children: [
110
+ /* @__PURE__ */ o("span", { className: "dishui-ai-task-rows__chevron dishui-ai-task-rows__chevron--blank" }),
111
+ /* @__PURE__ */ o("span", {
112
+ className: "dishui-ai-task-rows__title",
113
+ children: t.title
114
+ }),
115
+ t.meta !== void 0 && /* @__PURE__ */ o("span", {
116
+ className: "dishui-ai-task-rows__meta",
117
+ children: t.meta
118
+ })
119
+ ]
120
+ }),
121
+ c !== void 0 && t.status === "running" && /* @__PURE__ */ s("span", {
122
+ className: "dishui-ai-task-rows__percent",
123
+ children: [Math.round(c), "%"]
124
+ }),
125
+ /* @__PURE__ */ o(f, {
126
+ status: t.status,
127
+ label: I(t.status)
128
+ })
129
+ ]
130
+ }),
131
+ l && /* @__PURE__ */ o("div", {
132
+ className: e("dishui-ai-task-rows__bar", c === void 0 && "dishui-ai-task-rows__bar--indeterminate"),
133
+ role: "progressbar",
134
+ "aria-valuemin": 0,
135
+ "aria-valuemax": 100,
136
+ "aria-valuenow": c,
137
+ children: /* @__PURE__ */ o("span", {
138
+ className: "dishui-ai-task-rows__fill",
139
+ style: c === void 0 ? void 0 : { width: `${c}%` }
140
+ })
141
+ }),
142
+ t.status === "failed" && (t.error !== void 0 || x) && /* @__PURE__ */ s("div", {
143
+ className: "dishui-ai-task-rows__error",
144
+ role: "alert",
145
+ children: [/* @__PURE__ */ o("span", {
146
+ className: "dishui-ai-task-rows__error-text",
147
+ children: t.error
148
+ }), x && /* @__PURE__ */ s("button", {
149
+ type: "button",
150
+ className: "dishui-ai-task-rows__retry",
151
+ onClick: () => x(t),
152
+ children: [/* @__PURE__ */ o(d, {}), D.retry]
153
+ })]
154
+ }),
155
+ r && /* @__PURE__ */ o("ul", {
156
+ id: a,
157
+ className: "dishui-ai-task-rows__subtasks",
158
+ hidden: !i,
159
+ children: t.subtasks.map((n) => /* @__PURE__ */ s("li", {
160
+ className: e("dishui-ai-task-rows__subtask", n.status && `dishui-ai-task-rows__subtask--${n.status}`),
161
+ children: [
162
+ /* @__PURE__ */ o("span", {
163
+ className: "dishui-ai-task-rows__subtitle",
164
+ children: n.title
165
+ }),
166
+ n.value !== void 0 && /* @__PURE__ */ o("span", {
167
+ className: "dishui-ai-task-rows__value",
168
+ children: n.value
169
+ }),
170
+ n.status && n.status !== t.status && /* @__PURE__ */ o("span", {
171
+ className: "dishui-ai-task-rows__substatus",
172
+ children: I(n.status)
173
+ })
174
+ ]
175
+ }, n.id))
176
+ })
177
+ ]
178
+ }, t.id);
179
+ })
180
+ })]
181
+ });
182
+ }
183
+ //#endregion
184
+ export { m as default };
185
+
186
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/ai/TaskRows/index.tsx"],"sourcesContent":["import React, { useCallback, useId, useState } from 'react';\nimport { cn } from '../../../utils/cn';\nimport { AGENT_STATUS_LABEL, clamp } from '../shared';\nimport type { AgentStatus } from '../shared';\nimport './TaskRows.css';\n\nexport type AgentSubtask = {\n id: string;\n title: React.ReactNode;\n /** Right-aligned value, e.g. `12/12`, `68%`, `draft`. */\n value?: React.ReactNode;\n status?: AgentStatus;\n};\n\nexport type AgentTask = {\n id: string;\n title: React.ReactNode;\n /** Short qualifier shown after the title, e.g. `12 suppliers`. */\n meta?: React.ReactNode;\n status: AgentStatus;\n /** Determinate progress 0–100. Running tasks without it show an indeterminate bar. */\n progress?: number;\n subtasks?: AgentSubtask[];\n /** Shown under a failed task, next to the retry action. */\n error?: React.ReactNode;\n};\n\nexport type TaskRowsView = 'capsules' | 'list';\n\nexport type TaskRowsLabels = {\n capsules?: string;\n list?: string;\n retry?: string;\n view?: string;\n status?: Partial<Record<AgentStatus, string>>;\n};\n\nexport type TaskRowsProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> & {\n tasks: AgentTask[];\n /** Controlled view mode. */\n view?: TaskRowsView;\n defaultView?: TaskRowsView;\n onViewChange?: (view: TaskRowsView) => void;\n /** Render the Capsules / List toggle above the tasks. */\n showViewToggle?: boolean;\n /** Controlled list of task ids whose subtasks are visible. */\n expanded?: string[];\n /** Defaults to every running or failed task. */\n defaultExpanded?: string[];\n onExpandedChange?: (expanded: string[]) => void;\n /** Enables the retry action on failed tasks. */\n onRetry?: (task: AgentTask) => void;\n emptyText?: React.ReactNode;\n labels?: TaskRowsLabels;\n};\n\nconst DEFAULT_LABELS = { capsules: 'Capsules', list: 'List', retry: 'Retry', view: 'View' };\n\nconst STATUS_TONE: Record<AgentStatus, string> = {\n pending: 'neutral',\n running: 'info',\n completed: 'success',\n failed: 'danger',\n skipped: 'neutral',\n};\n\nconst ChevronIcon: React.FC = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n);\n\nconst RetryIcon: React.FC = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M3 12a9 9 0 1 0 3-6.7\" />\n <path d=\"M3 4v5h5\" />\n </svg>\n);\n\nconst StatusPill: React.FC<{ status: AgentStatus; label: string }> = ({ status, label }) => (\n <span className={cn('dishui-ai-task-rows__status', `dishui-ai-task-rows__status--${STATUS_TONE[status]}`)}>\n {status === 'running' && <span className=\"dishui-ai-task-rows__pulse\" aria-hidden=\"true\" />}\n {label}\n </span>\n);\n\nconst defaultExpandedFor = (tasks: AgentTask[]) =>\n tasks.filter(t => t.status === 'running' || t.status === 'failed').map(t => t.id);\n\n/**\n * Live agent task status. Each task is a row (or capsule) with a text +\n * colour status pill, optional progress and expandable subtasks with\n * right-aligned tabular values.\n */\nexport default function TaskRows({\n tasks,\n view: viewProp,\n defaultView = 'capsules',\n onViewChange,\n showViewToggle = false,\n expanded: expandedProp,\n defaultExpanded,\n onExpandedChange,\n onRetry,\n emptyText = 'No tasks yet',\n labels,\n className,\n ...rest\n}: TaskRowsProps) {\n const baseId = useId();\n const text = { ...DEFAULT_LABELS, ...labels };\n\n const [internalView, setInternalView] = useState<TaskRowsView>(defaultView);\n const view = viewProp ?? internalView;\n const changeView = useCallback((next: TaskRowsView) => {\n setInternalView(next);\n onViewChange?.(next);\n }, [onViewChange]);\n\n const [internalExpanded, setInternalExpanded] = useState<string[]>(\n () => defaultExpanded ?? defaultExpandedFor(tasks),\n );\n const expanded = expandedProp ?? internalExpanded;\n const toggle = useCallback((id: string) => {\n const next = expanded.includes(id) ? expanded.filter(x => x !== id) : [...expanded, id];\n setInternalExpanded(next);\n onExpandedChange?.(next);\n }, [expanded, onExpandedChange]);\n\n const statusLabel = (status: AgentStatus) => labels?.status?.[status] ?? AGENT_STATUS_LABEL[status];\n\n return (\n <div {...rest} className={cn('dishui-ai-task-rows', `dishui-ai-task-rows--${view}`, className)}>\n {showViewToggle && (\n <div className=\"dishui-ai-task-rows__toolbar\">\n <div className=\"dishui-ai-task-rows__segmented\" role=\"group\" aria-label={text.view}>\n {(['capsules', 'list'] as TaskRowsView[]).map(v => (\n <button\n key={v}\n type=\"button\"\n className={cn('dishui-ai-task-rows__segment', v === view && 'dishui-ai-task-rows__segment--active')}\n aria-pressed={v === view}\n onClick={() => changeView(v)}\n >\n {text[v]}\n </button>\n ))}\n </div>\n </div>\n )}\n\n {tasks.length === 0 ? (\n <div className=\"dishui-ai-task-rows__empty\">{emptyText}</div>\n ) : (\n <ul className=\"dishui-ai-task-rows__list\">\n {tasks.map(task => {\n const hasSubtasks = !!task.subtasks?.length;\n const isOpen = hasSubtasks && expanded.includes(task.id);\n const panelId = `${baseId}-${task.id}`;\n const progress = task.progress === undefined ? undefined : clamp(task.progress, 0, 100);\n const showBar = view === 'capsules' && (progress !== undefined || task.status === 'running');\n return (\n <li\n key={task.id}\n className={cn(\n 'dishui-ai-task-rows__task',\n `dishui-ai-task-rows__task--${task.status}`,\n isOpen && 'dishui-ai-task-rows__task--open',\n )}\n >\n <div className=\"dishui-ai-task-rows__row\">\n {hasSubtasks ? (\n <button\n type=\"button\"\n className=\"dishui-ai-task-rows__toggle\"\n aria-expanded={isOpen}\n aria-controls={panelId}\n onClick={() => toggle(task.id)}\n >\n <span className=\"dishui-ai-task-rows__chevron\"><ChevronIcon /></span>\n <span className=\"dishui-ai-task-rows__title\">{task.title}</span>\n {task.meta !== undefined && <span className=\"dishui-ai-task-rows__meta\">{task.meta}</span>}\n </button>\n ) : (\n <div className=\"dishui-ai-task-rows__toggle dishui-ai-task-rows__toggle--static\">\n <span className=\"dishui-ai-task-rows__chevron dishui-ai-task-rows__chevron--blank\" />\n <span className=\"dishui-ai-task-rows__title\">{task.title}</span>\n {task.meta !== undefined && <span className=\"dishui-ai-task-rows__meta\">{task.meta}</span>}\n </div>\n )}\n {progress !== undefined && task.status === 'running' && (\n <span className=\"dishui-ai-task-rows__percent\">{Math.round(progress)}%</span>\n )}\n <StatusPill status={task.status} label={statusLabel(task.status)} />\n </div>\n\n {showBar && (\n <div\n className={cn('dishui-ai-task-rows__bar', progress === undefined && 'dishui-ai-task-rows__bar--indeterminate')}\n role=\"progressbar\"\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={progress}\n >\n <span className=\"dishui-ai-task-rows__fill\" style={progress === undefined ? undefined : { width: `${progress}%` }} />\n </div>\n )}\n\n {task.status === 'failed' && (task.error !== undefined || onRetry) && (\n <div className=\"dishui-ai-task-rows__error\" role=\"alert\">\n <span className=\"dishui-ai-task-rows__error-text\">{task.error}</span>\n {onRetry && (\n <button type=\"button\" className=\"dishui-ai-task-rows__retry\" onClick={() => onRetry(task)}>\n <RetryIcon />\n {text.retry}\n </button>\n )}\n </div>\n )}\n\n {hasSubtasks && (\n <ul id={panelId} className=\"dishui-ai-task-rows__subtasks\" hidden={!isOpen}>\n {task.subtasks!.map(sub => (\n <li\n key={sub.id}\n className={cn('dishui-ai-task-rows__subtask', sub.status && `dishui-ai-task-rows__subtask--${sub.status}`)}\n >\n <span className=\"dishui-ai-task-rows__subtitle\">{sub.title}</span>\n {sub.value !== undefined && <span className=\"dishui-ai-task-rows__value\">{sub.value}</span>}\n {sub.status && sub.status !== task.status && (\n <span className=\"dishui-ai-task-rows__substatus\">{statusLabel(sub.status)}</span>\n )}\n </li>\n ))}\n </ul>\n )}\n </li>\n );\n })}\n </ul>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import React from 'react';
2
+ import type { AgentStatus } from '../shared';
3
+ export type ThinkingStepKind = 'step' | 'reasoning' | 'search' | 'coding';
4
+ export type ThinkingMode = 'steps' | 'reasoning' | 'search' | 'coding' | 'auto';
5
+ export type ThinkingStatus = 'thinking' | 'done';
6
+ export type ThinkingSearchResult = {
7
+ title: string;
8
+ url?: string;
9
+ domain?: string;
10
+ };
11
+ export type ThinkingCode = {
12
+ language?: string;
13
+ content: string;
14
+ file?: string;
15
+ };
16
+ export type ThinkingStep = {
17
+ id: string;
18
+ kind: ThinkingStepKind;
19
+ title: React.ReactNode;
20
+ detail?: React.ReactNode;
21
+ /** Defaults to `completed`. */
22
+ status?: AgentStatus;
23
+ durationMs?: number;
24
+ /** Result chips rendered by `search` steps. */
25
+ results?: ThinkingSearchResult[];
26
+ /** Code block rendered by `coding` steps. */
27
+ code?: ThinkingCode;
28
+ };
29
+ export type ThinkingProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'children' | 'title'> & {
30
+ steps: ThinkingStep[];
31
+ /** Derived from the steps when omitted: any running step → `thinking`. */
32
+ status?: ThinkingStatus;
33
+ /** Total time; rendered as “Thought for 4s” once done. Falls back to the sum of step durations. */
34
+ durationMs?: number;
35
+ /** Overrides the default “Thinking” / “Thought for …” header text. */
36
+ title?: React.ReactNode;
37
+ expanded?: boolean;
38
+ defaultExpanded?: boolean;
39
+ onExpandedChange?: (expanded: boolean) => void;
40
+ /** Rendering emphasis. `auto` renders each step by its own `kind`. */
41
+ mode?: ThinkingMode;
42
+ };
43
+ /**
44
+ * Expandable reasoning trace. Collapsed by default; the header summarises the
45
+ * currently running step while collapsed and reads “Thought for …” once done.
46
+ */
47
+ export default function Thinking({ steps, status: statusProp, durationMs, title, expanded: expandedProp, defaultExpanded, onExpandedChange, mode, className, ...rest }: ThinkingProps): React.JSX.Element;