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,217 @@
1
+ import { cn as e } from "../../../utils/cn.js";
2
+ /* empty css */
3
+ import t, { useEffect as n, useId as r, useMemo as i, useRef as a, useState as o } from "react";
4
+ import { Fragment as s, jsx as c, jsxs as l } from "react/jsx-runtime";
5
+ //#region src/components/ai/CommandSearch/index.tsx
6
+ var u = () => /* @__PURE__ */ l("svg", {
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": "true",
16
+ children: [/* @__PURE__ */ c("circle", {
17
+ cx: "11",
18
+ cy: "11",
19
+ r: "8"
20
+ }), /* @__PURE__ */ c("path", { d: "m21 21-4.3-4.3" })]
21
+ }), d = () => /* @__PURE__ */ l("svg", {
22
+ width: "16",
23
+ height: "16",
24
+ viewBox: "0 0 24 24",
25
+ fill: "none",
26
+ stroke: "currentColor",
27
+ strokeWidth: "2",
28
+ strokeLinecap: "round",
29
+ strokeLinejoin: "round",
30
+ "aria-hidden": "true",
31
+ children: [/* @__PURE__ */ c("path", { d: "M5 12h14" }), /* @__PURE__ */ c("path", { d: "m12 5 7 7-7 7" })]
32
+ });
33
+ function f(e, t) {
34
+ let n = t.trim().toLowerCase();
35
+ return !n || [
36
+ e.label,
37
+ e.description ?? "",
38
+ ...e.keywords ?? []
39
+ ].join(" ").toLowerCase().includes(n);
40
+ }
41
+ function p(e, t) {
42
+ let n = t.trim();
43
+ if (!n) return e;
44
+ let r = e.toLowerCase().indexOf(n.toLowerCase());
45
+ return r < 0 ? e : /* @__PURE__ */ l(s, { children: [
46
+ e.slice(0, r),
47
+ /* @__PURE__ */ c("mark", {
48
+ className: "dishui-ai-command-search__mark",
49
+ children: e.slice(r, r + n.length)
50
+ }),
51
+ e.slice(r + n.length)
52
+ ] });
53
+ }
54
+ function m({ items: m, query: h, defaultQuery: g = "", onQueryChange: _, onSelect: v, onSubmit: y, placeholder: b = "Search or ask…", filter: x = f, highlightMatches: S = !0, emptyState: C, maxVisible: w, autoFocus: T, inline: E = !0, loading: D = !1, label: O = "Search", className: k, ...A }) {
55
+ let j = r(), M = `${j}-list`, N = a(null), [P, F] = o(g), I = h ?? P, [L, R] = o(-1), z = (e) => {
56
+ h === void 0 && F(e), _?.(e), R(-1);
57
+ }, B = i(() => {
58
+ let e = m.filter((e) => x(e, I));
59
+ return w === void 0 ? e : e.slice(0, w);
60
+ }, [
61
+ m,
62
+ x,
63
+ I,
64
+ w
65
+ ]), V = L < B.length ? L : -1;
66
+ n(() => {
67
+ V < 0 || document.getElementById(`${j}-opt-${V}`)?.scrollIntoView({ block: "nearest" });
68
+ }, [V, j]);
69
+ let H = (e) => {
70
+ e.onSelect?.(), v?.(e);
71
+ }, U = (e) => {
72
+ let t = B.length;
73
+ switch (e.key) {
74
+ case "ArrowDown":
75
+ e.preventDefault(), t && R((e) => (e + 1) % t);
76
+ break;
77
+ case "ArrowUp":
78
+ e.preventDefault(), t && R((e) => e <= 0 ? t - 1 : e - 1);
79
+ break;
80
+ case "Home":
81
+ t && (e.preventDefault(), R(0));
82
+ break;
83
+ case "End":
84
+ t && (e.preventDefault(), R(t - 1));
85
+ break;
86
+ case "Enter":
87
+ e.preventDefault(), V >= 0 && B[V] ? H(B[V]) : y?.(I);
88
+ break;
89
+ case "Escape": I && (e.preventDefault(), z("")), R(-1);
90
+ }
91
+ }, W = i(() => {
92
+ let e = [], t = /* @__PURE__ */ new Map();
93
+ return B.forEach((n, r) => {
94
+ let i = n.group ?? "";
95
+ t.has(i) || (t.set(i, []), e.push(i)), t.get(i).push({
96
+ item: n,
97
+ index: r
98
+ });
99
+ }), e.map((e) => ({
100
+ key: e,
101
+ entries: t.get(e)
102
+ }));
103
+ }, [B]), G = B.length === 0, K = V >= 0 ? `${j}-opt-${V}` : void 0;
104
+ return /* @__PURE__ */ l("div", {
105
+ ...A,
106
+ className: e("dishui-ai-command-search", E && "dishui-ai-command-search--inline", k),
107
+ children: [
108
+ /* @__PURE__ */ l("div", {
109
+ className: e("dishui-ai-command-search__field", D && "dishui-ai-command-search__field--loading"),
110
+ children: [
111
+ /* @__PURE__ */ c("span", {
112
+ className: "dishui-ai-command-search__glyph",
113
+ "aria-hidden": "true",
114
+ children: /* @__PURE__ */ c(u, {})
115
+ }),
116
+ /* @__PURE__ */ c("input", {
117
+ ref: N,
118
+ className: "dishui-ai-command-search__input",
119
+ type: "text",
120
+ role: "combobox",
121
+ "aria-label": O,
122
+ "aria-expanded": !G,
123
+ "aria-controls": M,
124
+ "aria-activedescendant": K,
125
+ "aria-autocomplete": "list",
126
+ "aria-busy": D || void 0,
127
+ autoComplete: "off",
128
+ spellCheck: !1,
129
+ autoFocus: T,
130
+ placeholder: b,
131
+ value: I,
132
+ onChange: (e) => z(e.target.value),
133
+ onKeyDown: U
134
+ }),
135
+ D && /* @__PURE__ */ c("span", {
136
+ className: "dishui-ai-command-search__spinner",
137
+ role: "status",
138
+ "aria-label": "Searching"
139
+ }),
140
+ I && !D && /* @__PURE__ */ c("button", {
141
+ type: "button",
142
+ className: "dishui-ai-command-search__clear",
143
+ "aria-label": "Clear search",
144
+ onClick: () => {
145
+ z(""), N.current?.focus();
146
+ },
147
+ children: "×"
148
+ })
149
+ ]
150
+ }),
151
+ /* @__PURE__ */ c("ul", {
152
+ id: M,
153
+ role: "listbox",
154
+ "aria-label": O,
155
+ className: "dishui-ai-command-search__list",
156
+ children: W.map((n) => /* @__PURE__ */ l(t.Fragment, { children: [n.key && /* @__PURE__ */ c("li", {
157
+ role: "presentation",
158
+ className: "dishui-ai-command-search__group",
159
+ children: n.key
160
+ }), n.entries.map(({ item: t, index: n }) => {
161
+ let r = n === V;
162
+ return /* @__PURE__ */ l("li", {
163
+ id: `${j}-opt-${n}`,
164
+ role: "option",
165
+ "aria-selected": r,
166
+ className: e("dishui-ai-command-search__option", r && "dishui-ai-command-search__option--active"),
167
+ onMouseMove: () => {
168
+ r || R(n);
169
+ },
170
+ onMouseDown: (e) => e.preventDefault(),
171
+ onClick: () => H(t),
172
+ children: [
173
+ /* @__PURE__ */ c("span", {
174
+ className: "dishui-ai-command-search__icon",
175
+ "aria-hidden": "true",
176
+ children: t.icon ?? /* @__PURE__ */ c(d, {})
177
+ }),
178
+ /* @__PURE__ */ l("span", {
179
+ className: "dishui-ai-command-search__text",
180
+ children: [/* @__PURE__ */ c("span", {
181
+ className: "dishui-ai-command-search__label",
182
+ children: S ? p(t.label, I) : t.label
183
+ }), t.description && /* @__PURE__ */ c("span", {
184
+ className: "dishui-ai-command-search__description",
185
+ children: S ? p(t.description, I) : t.description
186
+ })]
187
+ }),
188
+ t.shortcut && /* @__PURE__ */ c("kbd", {
189
+ className: "dishui-ai-command-search__shortcut",
190
+ children: t.shortcut
191
+ })
192
+ ]
193
+ }, t.id);
194
+ })] }, n.key || "__default"))
195
+ }),
196
+ G && /* @__PURE__ */ c("div", {
197
+ className: "dishui-ai-command-search__empty",
198
+ role: "status",
199
+ children: typeof C == "function" ? C(I) : C ?? /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ c("p", {
200
+ className: "dishui-ai-command-search__empty-title",
201
+ children: I.trim() ? /* @__PURE__ */ l(s, { children: [
202
+ "No results for “",
203
+ I.trim(),
204
+ "”"
205
+ ] }) : "Nothing to show"
206
+ }), /* @__PURE__ */ c("p", {
207
+ className: "dishui-ai-command-search__empty-hint",
208
+ children: y ? "Try a different phrase or press Enter to ask the agent" : "Try a different phrase"
209
+ })] })
210
+ })
211
+ ]
212
+ });
213
+ }
214
+ //#endregion
215
+ export { m as default };
216
+
217
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/ai/CommandSearch/index.tsx"],"sourcesContent":["import React, { useEffect, useId, useMemo, useRef, useState } from 'react';\nimport { cn } from '../../../utils/cn';\nimport './CommandSearch.css';\n\nexport type CommandSearchItem = {\n id: string;\n label: string;\n description?: string;\n icon?: React.ReactNode;\n group?: string;\n keywords?: string[];\n shortcut?: string;\n onSelect?: () => void;\n};\n\nexport type CommandSearchProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'onSelect' | 'onSubmit' | 'children'> & {\n items: CommandSearchItem[];\n query?: string;\n defaultQuery?: string;\n onQueryChange?: (query: string) => void;\n onSelect?: (item: CommandSearchItem) => void;\n /** Enter with nothing highlighted, or on an empty result set. */\n onSubmit?: (query: string) => void;\n placeholder?: string;\n /** Custom predicate; default is a case-insensitive match on label / description / keywords. */\n filter?: (item: CommandSearchItem, query: string) => boolean;\n /** Wrap matched substrings in `<mark>`. */\n highlightMatches?: boolean;\n emptyState?: React.ReactNode | ((query: string) => React.ReactNode);\n maxVisible?: number;\n autoFocus?: boolean;\n /** Renders as an in-page panel (not a modal). */\n inline?: boolean;\n /** Show a small indeterminate indicator in the input. */\n loading?: boolean;\n /** Accessible name for the input. */\n label?: string;\n};\n\nconst SearchIcon = () => (\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 <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.3-4.3\" />\n </svg>\n);\nconst ArrowRight = () => (\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=\"M5 12h14\" />\n <path d=\"m12 5 7 7-7 7\" />\n </svg>\n);\n\nfunction defaultFilter(item: CommandSearchItem, query: string): boolean {\n const q = query.trim().toLowerCase();\n if (!q) return true;\n const hay = [item.label, item.description ?? '', ...(item.keywords ?? [])].join(' ').toLowerCase();\n return hay.includes(q);\n}\n\nfunction highlight(text: string, query: string): React.ReactNode {\n const q = query.trim();\n if (!q) return text;\n const idx = text.toLowerCase().indexOf(q.toLowerCase());\n if (idx < 0) return text;\n return (\n <>\n {text.slice(0, idx)}\n <mark className=\"dishui-ai-command-search__mark\">{text.slice(idx, idx + q.length)}</mark>\n {text.slice(idx + q.length)}\n </>\n );\n}\n\n/**\n * Command search: an input over a filtered, grouped listbox with keyboard\n * navigation and an empty state that hands the query to the agent.\n */\nexport default function CommandSearch({\n items,\n query,\n defaultQuery = '',\n onQueryChange,\n onSelect,\n onSubmit,\n placeholder = 'Search or ask…',\n filter = defaultFilter,\n highlightMatches = true,\n emptyState,\n maxVisible,\n autoFocus,\n inline = true,\n loading = false,\n label = 'Search',\n className,\n ...rest\n}: CommandSearchProps) {\n const uid = useId();\n const listId = `${uid}-list`;\n const inputRef = useRef<HTMLInputElement>(null);\n\n const [internalQuery, setInternalQuery] = useState(defaultQuery);\n const q = query ?? internalQuery;\n const [highlighted, setHighlighted] = useState<number>(-1);\n const setQuery = (next: string) => {\n if (query === undefined) setInternalQuery(next);\n onQueryChange?.(next);\n setHighlighted(-1);\n };\n\n const visible = useMemo(() => {\n const matched = items.filter(item => filter(item, q));\n return maxVisible !== undefined ? matched.slice(0, maxVisible) : matched;\n }, [items, filter, q, maxVisible]);\n\n // -1 means \"nothing highlighted\"; clamp in case the result set shrank.\n const activeIndex = highlighted < visible.length ? highlighted : -1;\n\n // Keep the highlighted option in view.\n useEffect(() => {\n if (activeIndex < 0) return;\n const el = document.getElementById(`${uid}-opt-${activeIndex}`);\n el?.scrollIntoView({ block: 'nearest' });\n }, [activeIndex, uid]);\n\n const select = (item: CommandSearchItem) => {\n item.onSelect?.();\n onSelect?.(item);\n };\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n const n = visible.length;\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n if (n) setHighlighted(i => (i + 1) % n);\n break;\n case 'ArrowUp':\n e.preventDefault();\n if (n) setHighlighted(i => (i <= 0 ? n - 1 : i - 1));\n break;\n case 'Home':\n if (n) { e.preventDefault(); setHighlighted(0); }\n break;\n case 'End':\n if (n) { e.preventDefault(); setHighlighted(n - 1); }\n break;\n case 'Enter':\n e.preventDefault();\n if (activeIndex >= 0 && visible[activeIndex]) select(visible[activeIndex]);\n else onSubmit?.(q);\n break;\n case 'Escape':\n if (q) { e.preventDefault(); setQuery(''); }\n setHighlighted(-1);\n break;\n default:\n }\n };\n\n // Group while preserving first-seen order.\n const groups = useMemo(() => {\n const order: string[] = [];\n const map = new Map<string, { item: CommandSearchItem; index: number }[]>();\n visible.forEach((item, index) => {\n const key = item.group ?? '';\n if (!map.has(key)) { map.set(key, []); order.push(key); }\n map.get(key)!.push({ item, index });\n });\n return order.map(key => ({ key, entries: map.get(key)! }));\n }, [visible]);\n\n const empty = visible.length === 0;\n const activeId = activeIndex >= 0 ? `${uid}-opt-${activeIndex}` : undefined;\n\n return (\n <div {...rest} className={cn('dishui-ai-command-search', inline && 'dishui-ai-command-search--inline', className)}>\n <div className={cn('dishui-ai-command-search__field', loading && 'dishui-ai-command-search__field--loading')}>\n <span className=\"dishui-ai-command-search__glyph\" aria-hidden=\"true\"><SearchIcon /></span>\n <input\n ref={inputRef}\n className=\"dishui-ai-command-search__input\"\n type=\"text\"\n role=\"combobox\"\n aria-label={label}\n aria-expanded={!empty}\n aria-controls={listId}\n aria-activedescendant={activeId}\n aria-autocomplete=\"list\"\n aria-busy={loading || undefined}\n autoComplete=\"off\"\n spellCheck={false}\n autoFocus={autoFocus}\n placeholder={placeholder}\n value={q}\n onChange={e => setQuery(e.target.value)}\n onKeyDown={onKeyDown}\n />\n {loading && <span className=\"dishui-ai-command-search__spinner\" role=\"status\" aria-label=\"Searching\" />}\n {q && !loading && (\n <button\n type=\"button\"\n className=\"dishui-ai-command-search__clear\"\n aria-label=\"Clear search\"\n onClick={() => { setQuery(''); inputRef.current?.focus(); }}\n >\n ×\n </button>\n )}\n </div>\n\n <ul id={listId} role=\"listbox\" aria-label={label} className=\"dishui-ai-command-search__list\">\n {groups.map(group => (\n <React.Fragment key={group.key || '__default'}>\n {group.key && (\n <li role=\"presentation\" className=\"dishui-ai-command-search__group\">{group.key}</li>\n )}\n {group.entries.map(({ item, index }) => {\n const isActive = index === activeIndex;\n return (\n <li\n key={item.id}\n id={`${uid}-opt-${index}`}\n role=\"option\"\n aria-selected={isActive}\n className={cn('dishui-ai-command-search__option', isActive && 'dishui-ai-command-search__option--active')}\n onMouseMove={() => { if (!isActive) setHighlighted(index); }}\n onMouseDown={e => e.preventDefault()}\n onClick={() => select(item)}\n >\n <span className=\"dishui-ai-command-search__icon\" aria-hidden=\"true\">{item.icon ?? <ArrowRight />}</span>\n <span className=\"dishui-ai-command-search__text\">\n <span className=\"dishui-ai-command-search__label\">{highlightMatches ? highlight(item.label, q) : item.label}</span>\n {item.description && (\n <span className=\"dishui-ai-command-search__description\">\n {highlightMatches ? highlight(item.description, q) : item.description}\n </span>\n )}\n </span>\n {item.shortcut && <kbd className=\"dishui-ai-command-search__shortcut\">{item.shortcut}</kbd>}\n </li>\n );\n })}\n </React.Fragment>\n ))}\n </ul>\n\n {empty && (\n <div className=\"dishui-ai-command-search__empty\" role=\"status\">\n {typeof emptyState === 'function' ? emptyState(q) : emptyState ?? (\n <>\n <p className=\"dishui-ai-command-search__empty-title\">\n {q.trim() ? <>No results for “{q.trim()}”</> : 'Nothing to show'}\n </p>\n <p className=\"dishui-ai-command-search__empty-hint\">\n {onSubmit ? 'Try a different phrase or press Enter to ask the agent' : 'Try a different phrase'}\n </p>\n </>\n )}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ export type ContextSourceKind = 'pdf' | 'csv' | 'doc' | 'web' | 'db' | 'code' | (string & {});
3
+ export type ContextSource = {
4
+ kind: ContextSourceKind;
5
+ name: string;
6
+ url?: string;
7
+ page?: number;
8
+ };
9
+ export type ContextChunk = {
10
+ id: string;
11
+ title: React.ReactNode;
12
+ excerpt: string;
13
+ /** Defaults to `excerpt.length`. */
14
+ characters?: number;
15
+ /** Relevance 0–1, shown as a percentage. */
16
+ score?: number;
17
+ source: ContextSource;
18
+ };
19
+ export type ContextCardsLabels = {
20
+ characters?: string;
21
+ page?: string;
22
+ };
23
+ export type ContextCardsProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'children' | 'title' | 'onSelect'> & {
24
+ chunks: ContextChunk[];
25
+ /** Total count when only a subset is passed; defaults to `chunks.length`. */
26
+ total?: number;
27
+ title?: React.ReactNode;
28
+ /** Grid columns on wide containers; collapses to 1 below 560px. */
29
+ columns?: 1 | 2;
30
+ /** Makes each card a button. */
31
+ onSelect?: (chunk: ContextChunk) => void;
32
+ selectedId?: string;
33
+ /** Excerpt line clamp. */
34
+ maxExcerptLines?: number;
35
+ emptyText?: React.ReactNode;
36
+ labels?: ContextCardsLabels;
37
+ };
38
+ /**
39
+ * Retrieved knowledge chunks with their sources: a header count, then
40
+ * cards with title, character count, clamped excerpt and a source pill.
41
+ */
42
+ export default function ContextCards({ chunks, total, title, columns, onSelect, selectedId, maxExcerptLines, emptyText, labels, className, ...rest }: ContextCardsProps): React.JSX.Element;
@@ -0,0 +1,106 @@
1
+ import { cn as e } from "../../../utils/cn.js";
2
+ /* empty css */
3
+ import "react";
4
+ import { Fragment as t, jsx as n, jsxs as r } from "react/jsx-runtime";
5
+ //#region src/components/ai/ContextCards/index.tsx
6
+ var i = {
7
+ characters: "characters",
8
+ page: "p."
9
+ }, a = new Intl.NumberFormat("en-US");
10
+ function o({ chunks: o, total: s, title: c = "All chunks", columns: l = 2, onSelect: u, selectedId: d, maxExcerptLines: f = 3, emptyText: p = "No context retrieved", labels: m, className: h, ...g }) {
11
+ let _ = {
12
+ ...i,
13
+ ...m
14
+ }, v = s ?? o.length, y = {
15
+ WebkitLineClamp: f,
16
+ lineClamp: f
17
+ };
18
+ return /* @__PURE__ */ r("div", {
19
+ ...g,
20
+ className: e("dishui-ai-context-cards", `dishui-ai-context-cards--cols-${l}`, h),
21
+ children: [/* @__PURE__ */ r("div", {
22
+ className: "dishui-ai-context-cards__header",
23
+ children: [/* @__PURE__ */ n("span", {
24
+ className: "dishui-ai-context-cards__title",
25
+ children: c
26
+ }), /* @__PURE__ */ n("span", {
27
+ className: "dishui-ai-context-cards__count",
28
+ children: a.format(v)
29
+ })]
30
+ }), o.length === 0 ? /* @__PURE__ */ n("div", {
31
+ className: "dishui-ai-context-cards__empty",
32
+ children: p
33
+ }) : /* @__PURE__ */ n("ul", {
34
+ className: "dishui-ai-context-cards__grid",
35
+ children: o.map((i) => {
36
+ let o = i.characters ?? i.excerpt.length, s = i.id === d, c = /* @__PURE__ */ r(t, { children: [
37
+ /* @__PURE__ */ r("div", {
38
+ className: "dishui-ai-context-cards__card-header",
39
+ children: [
40
+ /* @__PURE__ */ n("span", {
41
+ className: "dishui-ai-context-cards__card-title",
42
+ children: i.title
43
+ }),
44
+ /* @__PURE__ */ r("span", {
45
+ className: "dishui-ai-context-cards__chars",
46
+ children: [
47
+ a.format(o),
48
+ " ",
49
+ _.characters
50
+ ]
51
+ }),
52
+ i.score !== void 0 && /* @__PURE__ */ r("span", {
53
+ className: "dishui-ai-context-cards__score",
54
+ children: [Math.round(i.score * 100), "%"]
55
+ })
56
+ ]
57
+ }),
58
+ /* @__PURE__ */ n("p", {
59
+ className: "dishui-ai-context-cards__excerpt",
60
+ style: y,
61
+ children: i.excerpt
62
+ }),
63
+ /* @__PURE__ */ r("span", {
64
+ className: "dishui-ai-context-cards__source",
65
+ children: [
66
+ /* @__PURE__ */ n("span", {
67
+ className: "dishui-ai-context-cards__kind",
68
+ children: i.source.kind
69
+ }),
70
+ /* @__PURE__ */ n("span", {
71
+ className: "dishui-ai-context-cards__source-name",
72
+ title: i.source.name,
73
+ children: i.source.name
74
+ }),
75
+ i.source.page !== void 0 && /* @__PURE__ */ r("span", {
76
+ className: "dishui-ai-context-cards__page",
77
+ children: [
78
+ _.page,
79
+ " ",
80
+ i.source.page
81
+ ]
82
+ })
83
+ ]
84
+ })
85
+ ] }), l = e("dishui-ai-context-cards__card", u && "dishui-ai-context-cards__card--interactive", s && "dishui-ai-context-cards__card--selected");
86
+ return /* @__PURE__ */ n("li", {
87
+ className: "dishui-ai-context-cards__item",
88
+ children: u ? /* @__PURE__ */ n("button", {
89
+ type: "button",
90
+ className: l,
91
+ "aria-pressed": s,
92
+ onClick: () => u(i),
93
+ children: c
94
+ }) : /* @__PURE__ */ n("div", {
95
+ className: l,
96
+ children: c
97
+ })
98
+ }, i.id);
99
+ })
100
+ })]
101
+ });
102
+ }
103
+ //#endregion
104
+ export { o as default };
105
+
106
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/ai/ContextCards/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../../utils/cn';\nimport './ContextCards.css';\n\nexport type ContextSourceKind = 'pdf' | 'csv' | 'doc' | 'web' | 'db' | 'code' | (string & {});\n\nexport type ContextSource = {\n kind: ContextSourceKind;\n name: string;\n url?: string;\n page?: number;\n};\n\nexport type ContextChunk = {\n id: string;\n title: React.ReactNode;\n excerpt: string;\n /** Defaults to `excerpt.length`. */\n characters?: number;\n /** Relevance 0–1, shown as a percentage. */\n score?: number;\n source: ContextSource;\n};\n\nexport type ContextCardsLabels = {\n characters?: string;\n page?: string;\n};\n\nexport type ContextCardsProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'children' | 'title' | 'onSelect'> & {\n chunks: ContextChunk[];\n /** Total count when only a subset is passed; defaults to `chunks.length`. */\n total?: number;\n title?: React.ReactNode;\n /** Grid columns on wide containers; collapses to 1 below 560px. */\n columns?: 1 | 2;\n /** Makes each card a button. */\n onSelect?: (chunk: ContextChunk) => void;\n selectedId?: string;\n /** Excerpt line clamp. */\n maxExcerptLines?: number;\n emptyText?: React.ReactNode;\n labels?: ContextCardsLabels;\n};\n\nconst DEFAULT_LABELS: Required<ContextCardsLabels> = { characters: 'characters', page: 'p.' };\n\nconst numberFormat = new Intl.NumberFormat('en-US');\n\n/**\n * Retrieved knowledge chunks with their sources: a header count, then\n * cards with title, character count, clamped excerpt and a source pill.\n */\nexport default function ContextCards({\n chunks,\n total,\n title = 'All chunks',\n columns = 2,\n onSelect,\n selectedId,\n maxExcerptLines = 3,\n emptyText = 'No context retrieved',\n labels,\n className,\n ...rest\n}: ContextCardsProps) {\n const text = { ...DEFAULT_LABELS, ...labels };\n const count = total ?? chunks.length;\n const excerptStyle: React.CSSProperties = { WebkitLineClamp: maxExcerptLines, lineClamp: maxExcerptLines };\n\n return (\n <div {...rest} className={cn('dishui-ai-context-cards', `dishui-ai-context-cards--cols-${columns}`, className)}>\n <div className=\"dishui-ai-context-cards__header\">\n <span className=\"dishui-ai-context-cards__title\">{title}</span>\n <span className=\"dishui-ai-context-cards__count\">{numberFormat.format(count)}</span>\n </div>\n\n {chunks.length === 0 ? (\n <div className=\"dishui-ai-context-cards__empty\">{emptyText}</div>\n ) : (\n <ul className=\"dishui-ai-context-cards__grid\">\n {chunks.map(chunk => {\n const characters = chunk.characters ?? chunk.excerpt.length;\n const selected = chunk.id === selectedId;\n const inner = (\n <>\n <div className=\"dishui-ai-context-cards__card-header\">\n <span className=\"dishui-ai-context-cards__card-title\">{chunk.title}</span>\n <span className=\"dishui-ai-context-cards__chars\">\n {numberFormat.format(characters)} {text.characters}\n </span>\n {chunk.score !== undefined && (\n <span className=\"dishui-ai-context-cards__score\">{Math.round(chunk.score * 100)}%</span>\n )}\n </div>\n <p className=\"dishui-ai-context-cards__excerpt\" style={excerptStyle}>{chunk.excerpt}</p>\n <span className=\"dishui-ai-context-cards__source\">\n <span className=\"dishui-ai-context-cards__kind\">{chunk.source.kind}</span>\n <span className=\"dishui-ai-context-cards__source-name\" title={chunk.source.name}>\n {chunk.source.name}\n </span>\n {chunk.source.page !== undefined && (\n <span className=\"dishui-ai-context-cards__page\">{text.page} {chunk.source.page}</span>\n )}\n </span>\n </>\n );\n const cardClass = cn(\n 'dishui-ai-context-cards__card',\n onSelect && 'dishui-ai-context-cards__card--interactive',\n selected && 'dishui-ai-context-cards__card--selected',\n );\n return (\n <li key={chunk.id} className=\"dishui-ai-context-cards__item\">\n {onSelect ? (\n <button type=\"button\" className={cardClass} aria-pressed={selected} onClick={() => onSelect(chunk)}>\n {inner}\n </button>\n ) : (\n <div className={cardClass}>{inner}</div>\n )}\n </li>\n );\n })}\n </ul>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;AA6CA,IAAM,IAA+C;CAAE,YAAY;CAAc,MAAM;AAAK,GAEtF,IAAe,IAAI,KAAK,aAAa,OAAO;AAMlD,SAAwB,EAAa,EACnC,WACA,UACA,WAAQ,cACR,aAAU,GACV,aACA,eACA,qBAAkB,GAClB,eAAY,wBACZ,WACA,cACA,GAAG,KACiB;CACpB,IAAM,IAAO;EAAE,GAAG;EAAgB,GAAG;CAAO,GACtC,IAAQ,KAAS,EAAO,QACxB,IAAoC;EAAE,iBAAiB;EAAiB,WAAW;CAAgB;CAEzG,OACE,kBAAC,OAAD;EAAK,GAAI;EAAM,WAAW,EAAG,2BAA2B,iCAAiC,KAAW,CAAS;EAA7G,UAAA,CACE,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACE,kBAAC,QAAD;IAAM,WAAU;IAAkC,UAAA;GAAY,CAAA,GAC9D,kBAAC,QAAD;IAAM,WAAU;IAAkC,UAAA,EAAa,OAAO,CAAK;GAAQ,CAAA,CAChF;EAEJ,CAAA,GAAA,EAAO,WAAW,IACjB,kBAAC,OAAD;GAAK,WAAU;GAAkC,UAAA;EAAe,CAAA,IAEhE,kBAAC,MAAD;GAAI,WAAU;GACX,UAAA,EAAO,KAAI,MAAS;IACnB,IAAM,IAAa,EAAM,cAAc,EAAM,QAAQ,QAC/C,IAAW,EAAM,OAAO,GACxB,IACJ,kBAAA,GAAA,EAAA,UAAA;KACE,kBAAC,OAAD;MAAK,WAAU;MAAf,UAAA;OACE,kBAAC,QAAD;QAAM,WAAU;QAAuC,UAAA,EAAM;OAAY,CAAA;OACzE,kBAAC,QAAD;QAAM,WAAU;QAAhB,UAAA;SACG,EAAa,OAAO,CAAU;SAAE;SAAE,EAAK;QACpC;;OACL,EAAM,UAAU,KAAA,KACf,kBAAC,QAAD;QAAM,WAAU;QAAhB,UAAA,CAAkD,KAAK,MAAM,EAAM,QAAQ,GAAG,GAAE,GAAO;;MAEtF;;KACL,kBAAC,KAAD;MAAG,WAAU;MAAmC,OAAO;MAAe,UAAA,EAAM;KAAW,CAAA;KACvF,kBAAC,QAAD;MAAM,WAAU;MAAhB,UAAA;OACE,kBAAC,QAAD;QAAM,WAAU;QAAiC,UAAA,EAAM,OAAO;OAAW,CAAA;OACzE,kBAAC,QAAD;QAAM,WAAU;QAAuC,OAAO,EAAM,OAAO;QACxE,UAAA,EAAM,OAAO;OACV,CAAA;OACL,EAAM,OAAO,SAAS,KAAA,KACrB,kBAAC,QAAD;QAAM,WAAU;QAAhB,UAAA;SAAiD,EAAK;SAAK;SAAE,EAAM,OAAO;QAAW;;MAEnF;;IACN,EAAA,CAAA,GAEE,IAAY,EAChB,iCACA,KAAY,8CACZ,KAAY,yCACd;IACA,OACE,kBAAC,MAAD;KAAmB,WAAU;KAC1B,UAAA,IACC,kBAAC,UAAD;MAAQ,MAAK;MAAS,WAAW;MAAW,gBAAc;MAAU,eAAe,EAAS,CAAK;MAC9F,UAAA;KACK,CAAA,IAER,kBAAC,OAAD;MAAK,WAAW;MAAY,UAAA;KAAW,CAAA;IAEvC,GARK,EAAM,EAQX;GAER,CAAC;EACC,CAAA,CAEH;;AAET"}
@@ -0,0 +1,70 @@
1
+ import React from 'react';
2
+ export type DiffTableColumn = {
3
+ key: string;
4
+ label: React.ReactNode;
5
+ align?: 'left' | 'right';
6
+ /** Render the cell in the mono font (IDs, SKUs). */
7
+ mono?: boolean;
8
+ };
9
+ export type DiffCellValue = string | number | null;
10
+ /** A plain value is unchanged; an object describes a `before → after` edit. */
11
+ export type DiffCell = DiffCellValue | {
12
+ before?: DiffCellValue;
13
+ after?: DiffCellValue;
14
+ };
15
+ export type DiffRowChange = 'added' | 'removed' | 'modified';
16
+ export type DiffRow = {
17
+ id: string;
18
+ cells: Record<string, DiffCell>;
19
+ /** Row-level change. Omitted rows are inferred as `modified` when any cell is an edit. */
20
+ change?: DiffRowChange;
21
+ };
22
+ export type DiffDecision = 'accepted' | 'rejected';
23
+ export type DiffTableProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'children' | 'title' | 'summary'> & {
24
+ columns: DiffTableColumn[];
25
+ rows: DiffRow[];
26
+ title?: React.ReactNode;
27
+ /** Summary line under the title. Auto-computed (`3 changes across 2 rows`) when omitted. */
28
+ summary?: React.ReactNode;
29
+ /** Reveal changed rows one by one, top to bottom. */
30
+ sweeping?: boolean;
31
+ /** Milliseconds between each revealed row while sweeping. */
32
+ sweepIntervalMs?: number;
33
+ onAcceptAll?: () => void;
34
+ onRejectAll?: () => void;
35
+ onAcceptRow?: (row: DiffRow) => void;
36
+ onRejectRow?: (row: DiffRow) => void;
37
+ /** Controlled per-row decisions, keyed by row id. */
38
+ decisions?: Record<string, DiffDecision>;
39
+ dense?: boolean;
40
+ /** Text overrides. */
41
+ labels?: Partial<typeof DEFAULT_LABELS>;
42
+ };
43
+ declare const DEFAULT_LABELS: {
44
+ added: string;
45
+ removed: string;
46
+ modified: string;
47
+ unchanged: string;
48
+ acceptAll: string;
49
+ rejectAll: string;
50
+ accept: string;
51
+ reject: string;
52
+ accepted: string;
53
+ rejected: string;
54
+ status: string;
55
+ actions: string;
56
+ empty: string;
57
+ };
58
+ export declare function isDiffCellChange(cell: DiffCell): cell is {
59
+ before?: DiffCellValue;
60
+ after?: DiffCellValue;
61
+ };
62
+ /** Infer the row's change kind from its explicit flag or its cells. */
63
+ export declare function diffRowChange(row: DiffRow): DiffRowChange | undefined;
64
+ /**
65
+ * AI-proposed edits sweeping through tabular data. Changed cells show the
66
+ * old value struck through next to the new one; added/removed rows are
67
+ * tinted and always labelled in the leading status column.
68
+ */
69
+ export default function DiffTable({ columns, rows, title, summary, sweeping: sweepingProp, sweepIntervalMs, onAcceptAll, onRejectAll, onAcceptRow, onRejectRow, decisions, dense, labels: labelOverrides, className, ...rest }: DiffTableProps): React.JSX.Element;
70
+ export {};