@openviking/react 0.1.1 → 0.1.3

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 (229) hide show
  1. package/README.md +18 -15
  2. package/dist/1~0.js +506 -0
  3. package/dist/2~0.js +122 -0
  4. package/dist/30~0.js +1332 -0
  5. package/dist/3~0.js +2113 -4
  6. package/dist/ark-message-list-view~0.js +310 -0
  7. package/dist/c7~0.js +24 -0
  8. package/dist/client/index.d.ts +2 -1
  9. package/dist/client/paths.d.ts +64 -0
  10. package/dist/client/response.d.ts +31 -0
  11. package/dist/client/sse.d.ts +39 -0
  12. package/dist/client/stream.d.ts +26 -0
  13. package/dist/client/types.d.ts +104 -0
  14. package/dist/client.js +1 -239
  15. package/dist/components/agent-connect/agent-connect-copy.d.ts +34 -0
  16. package/dist/components/agent-connect/agent-connect-design.d.ts +1781 -0
  17. package/dist/components/agent-connect/agent-connect-detail.d.ts +13 -0
  18. package/dist/components/agent-connect/agent-connect-installer.d.ts +3 -0
  19. package/dist/components/agent-connect/agent-connect-instructions-view.d.ts +14 -0
  20. package/dist/components/agent-connect/agent-connect-instructions.d.ts +145 -0
  21. package/dist/components/agent-connect/agent-connect-markdown.d.ts +3 -0
  22. package/dist/components/agent-connect/agent-connect.d.ts +3 -3
  23. package/dist/components/agent-connect/content-en.d.ts +137 -0
  24. package/dist/components/agent-connect/content-zh.d.ts +137 -0
  25. package/dist/components/agent-connect/style.css +495 -6
  26. package/dist/components/agent-connect/types.d.ts +20 -166
  27. package/dist/components/file-browser-entries/file-browser-entries-icons.d.ts +18 -0
  28. package/dist/components/file-browser-entries/file-browser-entries.d.ts +14 -0
  29. package/dist/components/file-browser-entries/index.d.ts +1 -0
  30. package/dist/components/file-browser-entries/style.css +155 -0
  31. package/dist/components/file-browser-entries/types.d.ts +45 -0
  32. package/dist/components/file-browser-entries.js +1 -0
  33. package/dist/components/file-preview/file-preview-adapters.d.ts +33 -0
  34. package/dist/components/file-preview/file-preview-body.d.ts +24 -12
  35. package/dist/components/file-preview/file-preview-breadcrumb-menu.d.ts +16 -0
  36. package/dist/components/file-preview/file-preview-breadcrumb.d.ts +21 -0
  37. package/dist/components/file-preview/file-preview-copy-path.d.ts +12 -0
  38. package/dist/components/file-preview/file-preview-directory.d.ts +32 -0
  39. package/dist/components/file-preview/file-preview-editor.d.ts +22 -0
  40. package/dist/components/file-preview/file-preview-handle-adapters.d.ts +26 -0
  41. package/dist/components/file-preview/file-preview-header.d.ts +41 -14
  42. package/dist/components/file-preview/file-preview-labels.d.ts +15 -4
  43. package/dist/components/file-preview/file-preview-lazy-viewer.d.ts +3 -0
  44. package/dist/components/file-preview/file-preview-panels.d.ts +41 -0
  45. package/dist/components/file-preview/file-preview-path.d.ts +30 -0
  46. package/dist/components/file-preview/file-preview-source.d.ts +24 -0
  47. package/dist/components/file-preview/file-preview-state.d.ts +35 -0
  48. package/dist/components/file-preview/file-preview-tab-row.d.ts +16 -0
  49. package/dist/components/file-preview/file-preview-viewer.d.ts +31 -0
  50. package/dist/components/file-preview/file-preview.d.ts +9 -11
  51. package/dist/components/file-preview/level-selection.d.ts +25 -0
  52. package/dist/components/file-preview/style.css +4055 -126
  53. package/dist/components/file-preview/types.d.ts +350 -170
  54. package/dist/components/file-preview/use-directory-level.d.ts +30 -0
  55. package/dist/components/file-preview/use-file-preview-actions-context.d.ts +27 -0
  56. package/dist/components/file-preview/use-file-preview-actions.d.ts +19 -0
  57. package/dist/components/file-preview/use-file-preview-editing.d.ts +21 -2
  58. package/dist/components/file-preview/use-file-preview-ids.d.ts +24 -0
  59. package/dist/components/file-preview.js +1 -442
  60. package/dist/components/file-tree/file-tree-body.d.ts +8 -4
  61. package/dist/components/file-tree/file-tree-entry-row.d.ts +9 -3
  62. package/dist/components/file-tree/file-tree-icons.d.ts +12 -5
  63. package/dist/components/file-tree/file-tree-info-labels.d.ts +21 -0
  64. package/dist/components/file-tree/file-tree-info-tooltip.d.ts +43 -0
  65. package/dist/components/file-tree/file-tree-info.d.ts +29 -0
  66. package/dist/components/file-tree/file-tree-keyboard.d.ts +8 -4
  67. package/dist/components/file-tree/file-tree-row-context.d.ts +29 -12
  68. package/dist/components/file-tree/file-tree-row-shared.d.ts +18 -0
  69. package/dist/components/file-tree/file-tree-spinner.d.ts +10 -0
  70. package/dist/components/file-tree/file-tree-state-row.d.ts +7 -0
  71. package/dist/components/file-tree/file-tree-tooltip-surface.d.ts +22 -0
  72. package/dist/components/file-tree/file-tree.d.ts +12 -1
  73. package/dist/components/file-tree/style.css +280 -75
  74. package/dist/components/file-tree/types.d.ts +203 -0
  75. package/dist/components/file-tree/use-file-tree-actions.d.ts +7 -0
  76. package/dist/components/file-tree.js +1 -1
  77. package/dist/components/scope-switcher/scope-panel.d.ts +9 -3
  78. package/dist/components/scope-switcher/scope-selector.d.ts +1 -1
  79. package/dist/components/scope-switcher/scope-switcher.d.ts +1 -1
  80. package/dist/components/scope-switcher/style.css +282 -76
  81. package/dist/components/scope-switcher/types.d.ts +230 -108
  82. package/dist/components/style.css +14128 -390
  83. package/dist/components/tui/command-catalog.d.ts +58 -0
  84. package/dist/components/tui/command-completion.d.ts +19 -0
  85. package/dist/components/tui/command-definitions.d.ts +10 -0
  86. package/dist/components/tui/command-input.d.ts +16 -0
  87. package/dist/components/tui/style.css +1543 -5
  88. package/dist/components/tui/tui-assist.d.ts +15 -0
  89. package/dist/components/tui/tui-code-block.d.ts +8 -0
  90. package/dist/components/tui/tui-command-help.d.ts +9 -0
  91. package/dist/components/tui/tui-command-text.d.ts +6 -0
  92. package/dist/components/tui/tui-composer.d.ts +24 -0
  93. package/dist/components/tui/tui-copy-button.d.ts +9 -0
  94. package/dist/components/tui/tui-input-mirror.d.ts +14 -0
  95. package/dist/components/tui/tui-labels-zh.d.ts +2 -0
  96. package/dist/components/tui/tui-labels.d.ts +5 -0
  97. package/dist/components/tui/tui-markdown-renderers.d.ts +10 -0
  98. package/dist/components/tui/tui-markdown.d.ts +6 -0
  99. package/dist/components/tui/tui-param-hint.d.ts +7 -0
  100. package/dist/components/tui/tui-record-time.d.ts +11 -0
  101. package/dist/components/tui/tui-record.d.ts +13 -0
  102. package/dist/components/tui/tui-resource-preview.d.ts +10 -0
  103. package/dist/components/tui/tui-resource-tree.d.ts +10 -0
  104. package/dist/components/tui/tui-result-header.d.ts +7 -0
  105. package/dist/components/tui/tui-result-text.d.ts +5 -0
  106. package/dist/components/tui/tui-search-list.d.ts +8 -0
  107. package/dist/components/tui/tui-skeleton.d.ts +6 -0
  108. package/dist/components/tui/tui-status-card.d.ts +7 -0
  109. package/dist/components/tui/tui-text.d.ts +10 -0
  110. package/dist/components/tui/tui-uri-text.d.ts +19 -0
  111. package/dist/components/tui/tui-write-result.d.ts +7 -0
  112. package/dist/components/tui/tui.d.ts +10 -2
  113. package/dist/components/tui/types.d.ts +57 -15
  114. package/dist/components/tui/use-tui-assist-position.d.ts +3 -0
  115. package/dist/components/tui/use-tui-completion.d.ts +14 -0
  116. package/dist/components/tui/use-tui-composer-keyboard.d.ts +25 -0
  117. package/dist/components/viking-bot/ark-adapter.d.ts +45 -0
  118. package/dist/components/viking-bot/ark-message-body.d.ts +16 -0
  119. package/dist/components/viking-bot/ark-message-list-view.d.ts +7 -0
  120. package/dist/components/viking-bot/ark-message-row.d.ts +19 -0
  121. package/dist/components/viking-bot/index.d.ts +10 -0
  122. package/dist/components/viking-bot/interaction/ask-human-fields.d.ts +10 -0
  123. package/dist/components/viking-bot/interaction/index.d.ts +4 -0
  124. package/dist/components/viking-bot/interaction/labels.d.ts +7 -0
  125. package/dist/components/viking-bot/interaction/lazy-interaction.d.ts +3 -0
  126. package/dist/components/viking-bot/interaction/schedule-input.d.ts +13 -0
  127. package/dist/components/viking-bot/interaction/style.css +189 -0
  128. package/dist/components/viking-bot/interaction/style.js +0 -0
  129. package/dist/components/viking-bot/interaction/types.d.ts +188 -0
  130. package/dist/components/viking-bot/interaction/viking-bot-interaction.d.ts +9 -0
  131. package/dist/components/viking-bot/interaction.js +2 -0
  132. package/dist/components/viking-bot/labels.d.ts +2 -0
  133. package/dist/components/viking-bot/lazy-composer.d.ts +3 -0
  134. package/dist/components/viking-bot/message-groups.d.ts +12 -0
  135. package/dist/components/viking-bot/model.d.ts +252 -0
  136. package/dist/components/viking-bot/render-part.d.ts +12 -0
  137. package/dist/components/viking-bot/style.css +7135 -0
  138. package/dist/components/viking-bot/style.js +0 -0
  139. package/dist/components/viking-bot/types.d.ts +140 -0
  140. package/dist/components/viking-bot/viking-bot-composer.d.ts +6 -0
  141. package/dist/components/viking-bot/viking-bot-message-list.d.ts +3 -0
  142. package/dist/components/viking-bot/viking-bot.d.ts +16 -0
  143. package/dist/components/viking-bot.js +4 -0
  144. package/dist/c~0.js +201 -0
  145. package/dist/file-preview-viewer~0.js +191 -0
  146. package/dist/f~0.js +149 -77
  147. package/dist/h~0.js +58 -0
  148. package/dist/icons/file-type-icon.d.ts +31 -0
  149. package/dist/icons/index.d.ts +33 -23
  150. package/dist/icons/nextjs-icon.d.ts +19 -0
  151. package/dist/icons.js +1 -25
  152. package/dist/index.d.ts +4 -2
  153. package/dist/index.js +2 -1
  154. package/dist/k~0.js +1440 -0
  155. package/dist/lk~0.js +25 -12
  156. package/dist/l~0.js +1464 -25
  157. package/dist/modules/console/style.css +83 -1
  158. package/dist/modules/file-browser/file-browser-detail-icons.d.ts +10 -0
  159. package/dist/modules/file-browser/file-browser-detail.d.ts +33 -0
  160. package/dist/modules/file-browser/file-browser-empty.d.ts +3 -0
  161. package/dist/modules/file-browser/file-browser-failure.d.ts +22 -0
  162. package/dist/modules/file-browser/file-browser-icons.d.ts +18 -0
  163. package/dist/modules/file-browser/file-browser-labels.d.ts +28 -0
  164. package/dist/modules/file-browser/file-browser-layout.d.ts +27 -0
  165. package/dist/modules/file-browser/file-browser-toolbar.d.ts +18 -0
  166. package/dist/modules/file-browser/file-browser-tree-pane.d.ts +30 -0
  167. package/dist/modules/file-browser/file-browser.d.ts +14 -5
  168. package/dist/modules/file-browser/find-result.d.ts +24 -0
  169. package/dist/modules/file-browser/fs-directories.d.ts +33 -0
  170. package/dist/modules/file-browser/fs-file-kind.d.ts +19 -0
  171. package/dist/modules/file-browser/fs-icon.d.ts +17 -0
  172. package/dist/modules/file-browser/fs-model.d.ts +106 -0
  173. package/dist/modules/file-browser/fs-page.d.ts +16 -0
  174. package/dist/modules/file-browser/fs-path.d.ts +16 -0
  175. package/dist/modules/file-browser/fs-read-directory.d.ts +20 -0
  176. package/dist/modules/file-browser/fs-scope.d.ts +22 -0
  177. package/dist/modules/file-browser/fs-stat.d.ts +25 -0
  178. package/dist/modules/file-browser/index.d.ts +3 -1
  179. package/dist/modules/file-browser/style.css +5009 -34
  180. package/dist/modules/file-browser/tree-info-copy.d.ts +15 -0
  181. package/dist/modules/file-browser/tree-info-copy.zh-CN.d.ts +15 -0
  182. package/dist/modules/file-browser/types.d.ts +189 -44
  183. package/dist/modules/file-browser/use-container-width.d.ts +17 -0
  184. package/dist/modules/file-browser/use-file-browser.d.ts +49 -0
  185. package/dist/modules/file-browser/use-fs-preview.d.ts +51 -0
  186. package/dist/modules/file-browser/use-fs-search.d.ts +35 -0
  187. package/dist/modules/file-browser/use-fs-tree.d.ts +43 -0
  188. package/dist/modules/file-browser/use-request-scope.d.ts +39 -0
  189. package/dist/modules/file-browser.js +1 -1
  190. package/dist/modules/scope-cascade/style.css +282 -76
  191. package/dist/modules/style.css +5445 -130
  192. package/dist/n~0.js +568 -236
  193. package/dist/o~0.js +103 -0
  194. package/dist/shared/components/divider/divider.d.ts +18 -0
  195. package/dist/shared/components/divider/index.d.ts +1 -0
  196. package/dist/shared/components/divider/types.d.ts +35 -0
  197. package/dist/shared/components/overlay/types.d.ts +7 -0
  198. package/dist/shared/components/overlay/use-overlay-position.d.ts +38 -0
  199. package/dist/shared/components/popover/index.d.ts +1 -0
  200. package/dist/shared/components/popover/popover.d.ts +23 -0
  201. package/dist/shared/components/popover/types.d.ts +50 -0
  202. package/dist/shared/components/resizable/clamp.d.ts +13 -0
  203. package/dist/shared/components/resizable/index.d.ts +2 -0
  204. package/dist/shared/components/resizable/resizable-handle.d.ts +25 -0
  205. package/dist/shared/components/resizable/types.d.ts +48 -0
  206. package/dist/shared/components/tooltip/index.d.ts +1 -0
  207. package/dist/shared/components/tooltip/tooltip.d.ts +25 -0
  208. package/dist/shared/components/tooltip/types.d.ts +42 -0
  209. package/dist/style.css +19664 -530
  210. package/dist/u~0.js +1597 -4
  211. package/dist/viking-bot-composer~0.js +164 -0
  212. package/dist/viking-bot-interaction~0.js +284 -0
  213. package/dist/w~0.js +19 -0
  214. package/package.json +23 -10
  215. package/dist/components/file-preview/file-preview-icons.d.ts +0 -2
  216. package/dist/components/file-preview/file-preview-operations.d.ts +0 -1
  217. package/dist/components/file-tree/file-tree-dom.d.ts +0 -4
  218. package/dist/components/file-tree/file-tree-labels.d.ts +0 -5
  219. package/dist/components/file-tree/file-tree-rows.d.ts +0 -12
  220. package/dist/components/file-tree/file-tree-tooltip.d.ts +0 -11
  221. package/dist/i~0.js +0 -21
  222. package/dist/modules/file-browser/file-browser-toolbar-button.d.ts +0 -10
  223. package/dist/modules/task-center/columns.d.ts +0 -129
  224. package/dist/modules/task-center/index.d.ts +0 -1
  225. package/dist/modules/task-center/style.css +0 -29
  226. package/dist/modules/task-center/task-center.d.ts +0 -4
  227. package/dist/modules/task-center/types.d.ts +0 -168
  228. package/dist/modules/task-center.js +0 -1
  229. /package/dist/{modules/task-center → components/file-browser-entries}/style.js +0 -0
package/dist/3~0.js CHANGED
@@ -1,8 +1,2117 @@
1
- import { jsx } from "react/jsx-runtime";
2
- function Tui() {
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { Children, createContext, isValidElement, useCallback, useContext, useEffect, useId, useRef, useState, useSyncExternalStore } from "react";
3
+ import react_markdown, { defaultUrlTransform } from "react-markdown";
4
+ import remark_gfm from "remark-gfm";
5
+ function getTuiCommandInputText(command) {
6
+ return command.inputText?.trim() || command.name;
7
+ }
8
+ function matchTuiCommandInput(value, commands) {
9
+ const content = value.trimStart();
10
+ const leadingWhitespace = value.slice(0, value.length - content.length);
11
+ const matches = commands.flatMap((command)=>{
12
+ const names = [
13
+ command.name,
14
+ ...command.aliases ?? []
15
+ ];
16
+ return [
17
+ getTuiCommandInputText(command),
18
+ ...names,
19
+ ...names.map((name)=>`/${name}`)
20
+ ].flatMap((prefix)=>{
21
+ const words = prefix.trim().split(/[ \t]+/);
22
+ const pattern = words.map((word)=>word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('[ \t]+');
23
+ const match = pattern && new RegExp(`^${pattern}(?=$|\\s)`, 'i').exec(content);
24
+ return match ? [
25
+ {
26
+ command,
27
+ leadingWhitespace,
28
+ prefix: match[0],
29
+ rest: content.slice(match[0].length)
30
+ }
31
+ ] : [];
32
+ });
33
+ });
34
+ return matches.sort((left, right)=>right.prefix.length - left.prefix.length)[0];
35
+ }
36
+ function formatTuiCommandInput(value, commands) {
37
+ const match = matchTuiCommandInput(value, commands);
38
+ return match ? `${match.leadingWhitespace}${getTuiCommandInputText(match.command)}${match.rest}` : value;
39
+ }
40
+ function getTuiArgumentHints(command) {
41
+ const params = command.params ?? [];
42
+ const positional = params.filter((param)=>!param.label.startsWith('-'));
43
+ if (positional.length) return positional;
44
+ return [
45
+ ...params.filter((param)=>param.required),
46
+ ...(command.options ?? []).filter((option)=>option.required).map((option)=>({
47
+ label: option.token,
48
+ description: option.description
49
+ }))
50
+ ];
51
+ }
52
+ function TuiParamHint({ command, labels, onPick }) {
53
+ const examples = command.examples?.map((example)=>'string' == typeof example ? {
54
+ value: example,
55
+ label: example
56
+ } : example);
57
+ const params = [
58
+ ...(command.params ?? []).map((param)=>({
59
+ name: param.label,
60
+ description: param.description,
61
+ required: param.required ?? false,
62
+ defaultValue: param.defaultValue
63
+ })),
64
+ ...(command.options ?? []).map((option)=>({
65
+ name: option.token,
66
+ description: option.description,
67
+ required: option.required ?? false,
68
+ defaultValue: option.defaultValue
69
+ }))
70
+ ];
71
+ return /*#__PURE__*/ jsxs("div", {
72
+ className: "ov-tui__hint",
73
+ children: [
74
+ /*#__PURE__*/ jsxs("div", {
75
+ className: "ov-tui__hint-head",
76
+ children: [
77
+ /*#__PURE__*/ jsxs("code", {
78
+ className: "ov-tui__hint-name",
79
+ children: [
80
+ "/",
81
+ command.name
82
+ ]
83
+ }),
84
+ /*#__PURE__*/ jsx("span", {
85
+ className: "ov-tui__hint-desc",
86
+ children: command.description
87
+ })
88
+ ]
89
+ }),
90
+ examples?.length ? /*#__PURE__*/ jsxs("div", {
91
+ className: "ov-tui__hint-group",
92
+ children: [
93
+ /*#__PURE__*/ jsx("div", {
94
+ className: "ov-tui__hint-label",
95
+ children: labels.examples
96
+ }),
97
+ examples.map((example, index)=>/*#__PURE__*/ jsxs("button", {
98
+ type: "button",
99
+ className: "ov-tui__hint-example",
100
+ onMouseDown: (event)=>event.preventDefault(),
101
+ onClick: ()=>onPick(example.value),
102
+ children: [
103
+ /*#__PURE__*/ jsx("span", {
104
+ className: "ov-tui__hint-example-index",
105
+ "aria-hidden": "true",
106
+ children: index + 1
107
+ }),
108
+ /*#__PURE__*/ jsx("span", {
109
+ children: example.label ?? example.value
110
+ })
111
+ ]
112
+ }, example.value))
113
+ ]
114
+ }) : null,
115
+ /*#__PURE__*/ jsxs("div", {
116
+ className: "ov-tui__hint-group",
117
+ children: [
118
+ /*#__PURE__*/ jsx("div", {
119
+ className: "ov-tui__hint-section-title",
120
+ children: labels.parameters
121
+ }),
122
+ /*#__PURE__*/ jsx("code", {
123
+ className: "ov-tui__hint-usage",
124
+ children: command.usage
125
+ }),
126
+ params.length ? /*#__PURE__*/ jsx("div", {
127
+ className: "ov-tui__hint-table-frame",
128
+ children: /*#__PURE__*/ jsxs("table", {
129
+ className: "ov-tui__hint-table",
130
+ children: [
131
+ /*#__PURE__*/ jsx("thead", {
132
+ children: /*#__PURE__*/ jsxs("tr", {
133
+ children: [
134
+ /*#__PURE__*/ jsx("th", {
135
+ children: labels.parameter
136
+ }),
137
+ /*#__PURE__*/ jsx("th", {
138
+ children: labels.required
139
+ }),
140
+ /*#__PURE__*/ jsx("th", {
141
+ children: labels.description
142
+ }),
143
+ /*#__PURE__*/ jsx("th", {
144
+ children: labels.defaultValue
145
+ })
146
+ ]
147
+ })
148
+ }),
149
+ /*#__PURE__*/ jsx("tbody", {
150
+ children: params.map((param)=>/*#__PURE__*/ jsxs("tr", {
151
+ children: [
152
+ /*#__PURE__*/ jsx("td", {
153
+ children: /*#__PURE__*/ jsx("code", {
154
+ children: param.name
155
+ })
156
+ }),
157
+ /*#__PURE__*/ jsx("td", {
158
+ children: param.required ? labels.yes : labels.no
159
+ }),
160
+ /*#__PURE__*/ jsx("td", {
161
+ children: param.description
162
+ }),
163
+ /*#__PURE__*/ jsx("td", {
164
+ children: param.defaultValue ?? '—'
165
+ })
166
+ ]
167
+ }, param.name))
168
+ })
169
+ ]
170
+ })
171
+ }) : /*#__PURE__*/ jsx("div", {
172
+ className: "ov-tui__hint-empty",
173
+ children: labels.noParameters
174
+ })
175
+ ]
176
+ })
177
+ ]
178
+ });
179
+ }
180
+ function useTuiAssistPosition(anchorRef, open, onDismiss) {
181
+ const panelRef = useRef(null);
182
+ const anchorName = `--ov-tui-${useId().replace(/[^a-zA-Z0-9_-]/g, '')}`;
183
+ useEffect(()=>{
184
+ const panel = panelRef.current;
185
+ const anchor = anchorRef.current;
186
+ if (!open || !panel || !anchor) return;
187
+ const dismiss = ()=>onDismiss(anchor.querySelector('textarea')?.value ?? '');
188
+ const outside = (event)=>{
189
+ if (event.target instanceof Node && !panel.contains(event.target) && !anchor.contains(event.target)) dismiss();
190
+ };
191
+ const escape = (event)=>{
192
+ if (event.isComposing || 229 === event.keyCode) return;
193
+ if ('Escape' === event.key && (anchor.contains(document.activeElement) || panel.contains(document.activeElement))) {
194
+ event.preventDefault();
195
+ dismiss();
196
+ }
197
+ };
198
+ document.addEventListener('pointerdown', outside);
199
+ document.addEventListener('keydown', escape);
200
+ if (!('popover' in HTMLElement.prototype)) {
201
+ panel.removeAttribute('popover');
202
+ panel.dataset.inline = '';
203
+ return ()=>{
204
+ document.removeEventListener('pointerdown', outside);
205
+ document.removeEventListener('keydown', escape);
206
+ };
207
+ }
208
+ const nativeAnchors = CSS.supports('position-area', 'block-start span-inline-end');
209
+ const previousAnchor = anchor.style.getPropertyValue('anchor-name');
210
+ anchor.style.setProperty('anchor-name', anchorName);
211
+ panel.style.setProperty('position-anchor', anchorName);
212
+ panel.dataset.floating = '';
213
+ const place = ()=>{
214
+ const rect = anchor.getBoundingClientRect();
215
+ const above = Math.max(0, rect.top - 20);
216
+ const below = Math.max(0, window.innerHeight - rect.bottom - 20);
217
+ const onTop = above >= 160 || above >= below;
218
+ const available = Math.max(80, onTop ? above : below);
219
+ const width = Math.min(rect.width, window.innerWidth - 24);
220
+ const left = Math.max(12, Math.min(rect.left, window.innerWidth - width - 12));
221
+ panel.style.width = `${width}px`;
222
+ panel.style.setProperty('--ov-ui-tui-assist-height', `${Math.min(420, available)}px`);
223
+ const right = window.innerWidth - left - width;
224
+ panel.dataset.side = left >= 334 ? 'left' : right >= 334 ? 'right' : 'stack';
225
+ panel.style.setProperty('--ov-ui-tui-assist-detail-width', `${Math.min(400, (left >= 334 ? left : right) - 14)}px`);
226
+ panel.dataset.placement = onTop ? 'above' : 'below';
227
+ if (nativeAnchors) panel.style.setProperty('position-area', `${onTop ? 'block-start' : 'block-end'} span-inline-end`);
228
+ else {
229
+ panel.style.left = `${left}px`;
230
+ panel.style.top = onTop ? 'auto' : `${rect.bottom + 8}px`;
231
+ panel.style.bottom = onTop ? `${window.innerHeight - rect.top + 8}px` : 'auto';
232
+ }
233
+ };
234
+ place();
235
+ panel.showPopover();
236
+ const observer = new ResizeObserver(place);
237
+ observer.observe(anchor);
238
+ observer.observe(panel);
239
+ window.addEventListener('resize', place);
240
+ window.addEventListener('scroll', place, true);
241
+ return ()=>{
242
+ observer.disconnect();
243
+ window.removeEventListener('resize', place);
244
+ window.removeEventListener('scroll', place, true);
245
+ document.removeEventListener('pointerdown', outside);
246
+ document.removeEventListener('keydown', escape);
247
+ anchor.style.setProperty('anchor-name', previousAnchor);
248
+ if (panel.matches(':popover-open')) panel.hidePopover();
249
+ };
250
+ }, [
251
+ anchorRef,
252
+ anchorName,
253
+ open,
254
+ onDismiss
255
+ ]);
256
+ return panelRef;
257
+ }
258
+ function Highlighted({ text, keyword }) {
259
+ const normalized = keyword.trim().toLowerCase();
260
+ const index = normalized ? text.toLowerCase().indexOf(normalized) : -1;
261
+ if (index < 0) return /*#__PURE__*/ jsx(Fragment, {
262
+ children: text
263
+ });
264
+ return /*#__PURE__*/ jsxs(Fragment, {
265
+ children: [
266
+ text.slice(0, index),
267
+ /*#__PURE__*/ jsx("mark", {
268
+ className: "ov-tui__mark",
269
+ children: text.slice(index, index + normalized.length)
270
+ }),
271
+ text.slice(index + normalized.length)
272
+ ]
273
+ });
274
+ }
275
+ function TuiAssist({ anchorRef, assistId, labels, completion, activeIndex, onActiveIndexChange, onPick, onDismiss }) {
276
+ const options = completion.options;
277
+ const keyword = completion.query.keyword;
278
+ const selected = options[activeIndex];
279
+ const command = selected;
280
+ const open = completion.showSuggestions;
281
+ const panelRef = useTuiAssistPosition(anchorRef, open, onDismiss);
282
+ const listRef = useRef(null);
283
+ useEffect(()=>{
284
+ const list = listRef.current;
285
+ const option = list?.querySelector('[aria-selected="true"]');
286
+ if (!list || !option) return;
287
+ const listBox = list.getBoundingClientRect();
288
+ const optionBox = option.getBoundingClientRect();
289
+ if (optionBox.top < listBox.top) list.scrollTop -= listBox.top - optionBox.top;
290
+ if (optionBox.bottom > listBox.bottom) list.scrollTop += optionBox.bottom - listBox.bottom;
291
+ }, [
292
+ activeIndex,
293
+ options
294
+ ]);
295
+ if (!open) return null;
296
+ return /*#__PURE__*/ jsxs("div", {
297
+ ref: panelRef,
298
+ className: "ov-tui__assist",
299
+ popover: "manual",
300
+ "data-details-only": !options.length || void 0,
301
+ children: [
302
+ command ? /*#__PURE__*/ jsx("div", {
303
+ className: "ov-tui__assist-detail",
304
+ children: /*#__PURE__*/ jsx(TuiParamHint, {
305
+ command: command,
306
+ labels: labels,
307
+ onPick: onPick
308
+ })
309
+ }) : null,
310
+ options.length ? /*#__PURE__*/ jsx("div", {
311
+ className: "ov-tui__suggestions",
312
+ ref: listRef,
313
+ role: "listbox",
314
+ id: assistId,
315
+ "aria-label": labels.suggestions,
316
+ children: completion.suggestions.map((section)=>/*#__PURE__*/ jsxs("div", {
317
+ className: "ov-tui__suggestion-group",
318
+ children: [
319
+ /*#__PURE__*/ jsx("div", {
320
+ className: "ov-tui__suggestion-label",
321
+ children: section.group.label
322
+ }),
323
+ section.commands.map((item)=>{
324
+ const index = options.indexOf(item);
325
+ return /*#__PURE__*/ jsxs("button", {
326
+ id: `${assistId}-${index}`,
327
+ type: "button",
328
+ role: "option",
329
+ "aria-selected": item === selected,
330
+ className: "ov-tui__suggestion",
331
+ onMouseEnter: ()=>onActiveIndexChange(index),
332
+ onFocus: ()=>onActiveIndexChange(index),
333
+ onMouseDown: (event)=>event.preventDefault(),
334
+ onClick: ()=>onPick(`${getTuiCommandInputText(item)} `),
335
+ children: [
336
+ /*#__PURE__*/ jsx("code", {
337
+ className: "ov-tui__suggestion-name",
338
+ children: /*#__PURE__*/ jsx(Highlighted, {
339
+ text: item.name,
340
+ keyword: keyword
341
+ })
342
+ }),
343
+ /*#__PURE__*/ jsx("span", {
344
+ className: "ov-tui__suggestion-desc",
345
+ title: item.summary ?? item.description,
346
+ children: /*#__PURE__*/ jsx(Highlighted, {
347
+ text: item.summary ?? item.description,
348
+ keyword: keyword
349
+ })
350
+ })
351
+ ]
352
+ }, item.name);
353
+ })
354
+ ]
355
+ }, section.group.key))
356
+ }) : command ? null : /*#__PURE__*/ jsx("div", {
357
+ className: "ov-tui__no-suggestions",
358
+ role: "status",
359
+ children: labels.noSuggestions
360
+ })
361
+ ]
362
+ });
363
+ }
364
+ const LEADING_SLASH = /^\s*\//;
365
+ const COMMAND_NAME = /^([^\s]*)([\s\S]*)$/;
366
+ function parseTuiCommandInput(value) {
367
+ if (!LEADING_SLASH.test(value)) return null;
368
+ const body = value.replace(LEADING_SLASH, '');
369
+ const matched = COMMAND_NAME.exec(body);
370
+ if (!matched) return null;
371
+ const name = matched[1] ?? '';
372
+ const rest = matched[2] ?? '';
373
+ return {
374
+ name,
375
+ rest,
376
+ hasTrailingSpace: /^\s/.test(rest)
377
+ };
378
+ }
379
+ function resolveTuiSkeleton(command) {
380
+ return command?.skeleton ?? 'generic';
381
+ }
382
+ function findTuiCommand(text, commands) {
383
+ return matchTuiCommandInput(text, commands)?.command;
384
+ }
385
+ function filterTuiCommands(keyword, commands) {
386
+ const normalized = keyword.trim().toLowerCase();
387
+ if (!normalized) return commands;
388
+ return commands.filter((command)=>command.name.toLowerCase().includes(normalized) || (command.summary ?? command.description).toLowerCase().includes(normalized) || command.aliases?.some((alias)=>alias.toLowerCase().includes(normalized)));
389
+ }
390
+ function groupTuiCommands(commands, groups = []) {
391
+ const known = new Map(groups.map((group)=>[
392
+ group.key,
393
+ group
394
+ ]));
395
+ for (const command of commands){
396
+ const key = command.group ?? '';
397
+ if (!known.has(key)) known.set(key, {
398
+ key,
399
+ label: key
400
+ });
401
+ }
402
+ return Array.from(known.values(), (group)=>({
403
+ group,
404
+ commands: commands.filter((command)=>(command.group ?? '') === group.key)
405
+ })).filter((section)=>section.commands.length > 0);
406
+ }
407
+ const EMPTY_QUERY = {
408
+ keyword: '',
409
+ scope: null,
410
+ matches: [],
411
+ automatic: false,
412
+ canOpenPalette: false,
413
+ colorInput: false
414
+ };
415
+ const normalize = (text)=>text.replace(/[ \t]+/g, ' ');
416
+ function getTuiCommandQuery(value, commands) {
417
+ if (!commands.length || /[\r\n]/.test(value)) return EMPTY_QUERY;
418
+ const slash = parseTuiCommandInput(value);
419
+ const content = normalize(value.trimStart().slice(slash ? 1 : 0));
420
+ if (!slash && !content) return EMPTY_QUERY;
421
+ const boundary = content.lastIndexOf(' ') + 1;
422
+ const head = content.slice(0, boundary);
423
+ const keyword = content.slice(boundary);
424
+ const entries = commands.flatMap((command)=>(slash ? [
425
+ command.name,
426
+ ...command.aliases ?? []
427
+ ] : [
428
+ getTuiCommandInputText(command)
429
+ ]).map((text)=>({
430
+ command,
431
+ text: normalize(text)
432
+ })));
433
+ const definitions = (items)=>[
434
+ ...new Set(items.map((entry)=>entry.command))
435
+ ];
436
+ const scoped = entries.filter((entry)=>entry.text.toLowerCase().startsWith(head.toLowerCase()));
437
+ if (!scoped.length) return EMPTY_QUERY;
438
+ const matching = scoped.filter((entry)=>entry.text.toLowerCase().startsWith(content.toLowerCase()));
439
+ const input = matchTuiCommandInput(value, commands);
440
+ if (input && (!slash || input.rest) && !matching.some((entry)=>entry.text.length > content.trimEnd().length)) return EMPTY_QUERY;
441
+ const base = {
442
+ ...EMPTY_QUERY,
443
+ keyword,
444
+ scope: slash ? '/' : head.trimEnd(),
445
+ automatic: Boolean(slash)
446
+ };
447
+ if (slash) return {
448
+ ...base,
449
+ matches: head ? matching.length ? definitions(matching) : filterTuiCommands(keyword, definitions(scoped)) : filterTuiCommands(keyword, commands)
450
+ };
451
+ if (!keyword) return {
452
+ ...base,
453
+ matches: matching.map((entry)=>entry.command),
454
+ canOpenPalette: matching.length > 0,
455
+ colorInput: matching.length > 0
456
+ };
457
+ const words = content.split(' ').length;
458
+ if (matching.length && matching.every((entry)=>entry.text.split(' ').length > words)) {
459
+ const targets = [
460
+ ...new Set(matching.map((entry)=>entry.text.split(' ').slice(0, words).join(' ')))
461
+ ];
462
+ const target = 1 === targets.length ? targets[0] : void 0;
463
+ return {
464
+ ...base,
465
+ matches: matching.map((entry)=>entry.command),
466
+ colorInput: true,
467
+ prefixTarget: target,
468
+ canOpenPalette: !target || target.toLowerCase() === content.toLowerCase()
469
+ };
470
+ }
471
+ return {
472
+ ...base,
473
+ matches: matching.length ? matching.map((entry)=>entry.command) : filterTuiCommands(keyword, scoped.map((entry)=>entry.command)),
474
+ colorInput: matching.length > 0
475
+ };
476
+ }
477
+ function getTuiInlineCompletion(value, query, selected, paletteOpen = false) {
478
+ const leading = value.slice(0, value.length - value.trimStart().length);
479
+ const content = normalize(value.trimStart());
480
+ if (query.prefixTarget) {
481
+ const suffix = query.prefixTarget.slice(content.length);
482
+ return suffix ? {
483
+ kind: 'prefix',
484
+ suffix,
485
+ value: `${leading}${query.prefixTarget}`
486
+ } : void 0;
487
+ }
488
+ if (!selected || !query.keyword && (!paletteOpen || '/' === query.scope)) return;
489
+ if ('/' === query.scope) {
490
+ const typed = content.slice(1);
491
+ const name = [
492
+ selected.name,
493
+ ...selected.aliases ?? []
494
+ ].map(normalize).find((name)=>name.toLowerCase().startsWith(typed.toLowerCase()));
495
+ const suffix = name?.slice(typed.length);
496
+ return suffix ? {
497
+ kind: 'command',
498
+ suffix,
499
+ value: `${leading}${getTuiCommandInputText(selected)} `
500
+ } : void 0;
501
+ }
502
+ const text = getTuiCommandInputText(selected);
503
+ const normalized = normalize(text);
504
+ if (!normalized.toLowerCase().startsWith(content.toLowerCase())) return;
505
+ const suffix = normalized.slice(content.length);
506
+ return suffix ? {
507
+ kind: 'command',
508
+ suffix,
509
+ value: `${leading}${text} `
510
+ } : void 0;
511
+ }
512
+ function useTuiComposerKeyboard({ inputRef, value, history, completion, inline, disabled, readOnly, canSubmit, activeIndex, onActiveIndexChange, onValueChange, onSubmit, onDismiss, onRequestPalette }) {
513
+ const historyRef = useRef({
514
+ offset: -1,
515
+ draft: '',
516
+ value: ''
517
+ });
518
+ const change = (next)=>{
519
+ historyRef.current.offset = -1;
520
+ onValueChange?.(next);
521
+ };
522
+ const accept = (next)=>{
523
+ change(next);
524
+ inputRef.current?.focus({
525
+ preventScroll: true
526
+ });
527
+ };
528
+ const handleKeyDown = (event)=>{
529
+ if (event.nativeEvent.isComposing || 229 === event.nativeEvent.keyCode) return;
530
+ const input = event.currentTarget;
531
+ const atEnd = input.selectionStart === input.selectionEnd && input.selectionEnd === value.length;
532
+ if ('Tab' === event.key) {
533
+ if (event.shiftKey || event.ctrlKey || event.altKey || event.metaKey) return;
534
+ event.preventDefault();
535
+ if (!atEnd) return;
536
+ }
537
+ const options = completion.options;
538
+ const listOpen = completion.showSuggestions;
539
+ if ('Escape' === event.key && (inline || listOpen)) {
540
+ event.preventDefault();
541
+ onDismiss(value);
542
+ return;
543
+ }
544
+ if (!disabled && !readOnly) {
545
+ if ('Tab' === event.key && inline?.kind === 'prefix') {
546
+ event.preventDefault();
547
+ accept(inline.value);
548
+ return;
549
+ }
550
+ if (' ' === event.key && atEnd && inline?.kind === 'prefix' && !event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey) {
551
+ event.preventDefault();
552
+ accept(`${inline.value} `);
553
+ return;
554
+ }
555
+ if ('Tab' === event.key && completion.query.canOpenPalette && !listOpen) {
556
+ event.preventDefault();
557
+ onRequestPalette();
558
+ return;
559
+ }
560
+ if (listOpen && options.length) {
561
+ if ('ArrowDown' === event.key || 'ArrowUp' === event.key) {
562
+ event.preventDefault();
563
+ const delta = 'ArrowDown' === event.key ? 1 : -1;
564
+ onActiveIndexChange((index)=>index < 0 ? delta > 0 ? 0 : options.length - 1 : (index + delta + options.length) % options.length);
565
+ return;
566
+ }
567
+ const spaceCommand = ' ' === event.key && atEnd ? matchTuiCommandInput(value, options)?.command : void 0;
568
+ if ('Tab' === event.key || 'Enter' === event.key && !event.shiftKey || spaceCommand) {
569
+ event.preventDefault();
570
+ const picked = spaceCommand ?? options[activeIndex];
571
+ if (picked) accept(`${getTuiCommandInputText(picked)} `);
572
+ else if ('Tab' === event.key && inline) accept(inline.value);
573
+ return;
574
+ }
575
+ }
576
+ if ('Tab' === event.key && inline) {
577
+ event.preventDefault();
578
+ accept(inline.value);
579
+ return;
580
+ }
581
+ }
582
+ const previous = historyRef.current;
583
+ const browsing = previous.offset >= 0 && previous.value === value;
584
+ if (!disabled && !readOnly && history.length > 0 && input.selectionStart === input.selectionEnd && !event.shiftKey && ('ArrowUp' === event.key && !value.slice(0, input.selectionStart).includes('\n') || 'ArrowDown' === event.key && browsing && !value.slice(input.selectionEnd).includes('\n'))) {
585
+ event.preventDefault();
586
+ const offset = Math.max(-1, Math.min(history.length - 1, (browsing ? previous.offset : -1) + ('ArrowUp' === event.key ? 1 : -1)));
587
+ const draft = browsing ? previous.draft : value;
588
+ const next = offset < 0 ? draft : history[history.length - 1 - offset];
589
+ historyRef.current = {
590
+ offset,
591
+ draft,
592
+ value: next
593
+ };
594
+ onValueChange?.(next);
595
+ onDismiss(next);
596
+ inputRef.current?.focus({
597
+ preventScroll: true
598
+ });
599
+ return;
600
+ }
601
+ if ('Enter' === event.key && !event.shiftKey) {
602
+ event.preventDefault();
603
+ if (value.trim() && !disabled && !readOnly && canSubmit) onSubmit?.(value.trim());
604
+ }
605
+ };
606
+ return {
607
+ change,
608
+ handleKeyDown
609
+ };
610
+ }
611
+ const TUI_URI_PATTERN = /viking:\/\/[^\s"'<>`]+/g;
612
+ const TUI_PROSE_URI_PATTERN = /viking:\/\/[^\s,,。;;、"'<>()[\]]+/g;
613
+ function getTuiSafeHref(uri) {
614
+ const href = uri?.trim();
615
+ return href && /^(?:viking|https?):\/\/[^\s]+$/i.test(href) ? href : void 0;
616
+ }
617
+ async function copyTuiText(text) {
618
+ if ("u" < typeof navigator) return false;
619
+ try {
620
+ if (navigator.clipboard?.writeText) {
621
+ await navigator.clipboard.writeText(text);
622
+ return true;
623
+ }
624
+ } catch {}
625
+ return false;
626
+ }
627
+ function formatTuiJson(text) {
628
+ const trimmed = text.trim();
629
+ if (!trimmed || !/^[[{]/.test(trimmed)) return text;
630
+ try {
631
+ JSON.parse(trimmed);
632
+ } catch {
633
+ return text;
634
+ }
635
+ const tokens = trimmed.match(/"(?:\\.|[^"\\])*"|[^\s]/g) ?? [];
636
+ let depth = 0;
637
+ let output = '';
638
+ const newline = ()=>`\n${' '.repeat(depth)}`;
639
+ for (const [index, token] of tokens.entries())if ('{' === token || '[' === token) {
640
+ output += token;
641
+ depth++;
642
+ if ('}' !== tokens[index + 1] && ']' !== tokens[index + 1]) output += newline();
643
+ } else if ('}' === token || ']' === token) {
644
+ depth--;
645
+ if ('{' !== tokens[index - 1] && '[' !== tokens[index - 1]) output += newline();
646
+ output += token;
647
+ } else if (',' === token) output += `,${newline()}`;
648
+ else if (':' === token) output += ': ';
649
+ else output += token;
650
+ return output;
651
+ }
652
+ function TuiUriLink({ uri, children, onOpenUri, editor = false, className = 'ov-tui__link' }) {
653
+ const href = getTuiSafeHref(uri);
654
+ if (!href) return /*#__PURE__*/ jsx(Fragment, {
655
+ children: children
656
+ });
657
+ return /*#__PURE__*/ jsx("a", {
658
+ href: href,
659
+ className: className,
660
+ onMouseDown: editor ? (event)=>event.preventDefault() : void 0,
661
+ onClick: onOpenUri ? (event)=>{
662
+ event.preventDefault();
663
+ onOpenUri(href);
664
+ } : void 0,
665
+ children: children
666
+ });
667
+ }
668
+ function TuiUriText({ text, onOpenUri, editor = false, mode }) {
669
+ const parts = [];
670
+ let cursor = 0;
671
+ const pattern = new RegExp(('prose' === mode ? TUI_PROSE_URI_PATTERN : TUI_URI_PATTERN).source, 'gi');
672
+ const plain = (value, key)=>editor ? /*#__PURE__*/ jsx("span", {
673
+ "aria-hidden": "true",
674
+ children: value
675
+ }, key) : value;
676
+ for (const matched of text.matchAll(pattern)){
677
+ const index = matched.index ?? 0;
678
+ const uri = 'prose' === mode ? matched[0].replace(/[.!?;;::!?]+$/u, '') : matched[0];
679
+ if (index > cursor) parts.push(plain(text.slice(cursor, index), cursor));
680
+ parts.push(/*#__PURE__*/ jsx(TuiUriLink, {
681
+ uri: uri,
682
+ onOpenUri: onOpenUri,
683
+ editor: editor,
684
+ children: uri
685
+ }, `${index}-${uri}`));
686
+ cursor = index + uri.length;
687
+ }
688
+ if (!parts.length) return /*#__PURE__*/ jsx(Fragment, {
689
+ children: plain(text, 0)
690
+ });
691
+ if (cursor < text.length) parts.push(plain(text.slice(cursor), cursor));
692
+ return /*#__PURE__*/ jsx(Fragment, {
693
+ children: parts
694
+ });
695
+ }
696
+ function TuiCommandText({ text, name, namespaceOnly = false }) {
697
+ const namedStart = name ? text.length - name.length : -1;
698
+ const matchesName = namedStart >= 0 && text.slice(namedStart).toLowerCase() === name?.toLowerCase() && (0 === namedStart || /\s/.test(text[namedStart - 1]));
699
+ const lastToken = text.search(/\S+$/);
700
+ const start = namespaceOnly ? text.length : matchesName ? namedStart : lastToken < 0 ? text.length : lastToken;
701
+ return /*#__PURE__*/ jsxs(Fragment, {
702
+ children: [
703
+ start > 0 ? /*#__PURE__*/ jsx("span", {
704
+ className: "ov-tui__command-prefix",
705
+ children: text.slice(0, start)
706
+ }) : null,
707
+ start < text.length ? /*#__PURE__*/ jsx("span", {
708
+ className: "ov-tui__command-name",
709
+ children: text.slice(start)
710
+ }) : null
711
+ ]
712
+ });
713
+ }
714
+ function TuiInputMirror({ value, input, inline, colorInput, onOpenUri, onScroll, mirrorRef, hintId }) {
715
+ const hints = input && !input.rest.trim() ? getTuiArgumentHints(input.command) : [];
716
+ return /*#__PURE__*/ jsxs(Fragment, {
717
+ children: [
718
+ /*#__PURE__*/ jsxs("span", {
719
+ className: "ov-tui__input-mirror",
720
+ ref: mirrorRef,
721
+ onScroll: onScroll,
722
+ children: [
723
+ input ? /*#__PURE__*/ jsxs(Fragment, {
724
+ children: [
725
+ input.leadingWhitespace,
726
+ /*#__PURE__*/ jsx("span", {
727
+ "aria-hidden": "true",
728
+ children: /*#__PURE__*/ jsx("span", {
729
+ className: "ov-tui__input-command",
730
+ children: /*#__PURE__*/ jsx(TuiCommandText, {
731
+ text: input.prefix,
732
+ name: input.command.name
733
+ })
734
+ })
735
+ }),
736
+ /*#__PURE__*/ jsx(TuiUriText, {
737
+ text: input.rest,
738
+ mode: "literal",
739
+ onOpenUri: onOpenUri,
740
+ editor: true
741
+ })
742
+ ]
743
+ }) : colorInput ? /*#__PURE__*/ jsx("span", {
744
+ className: "ov-tui__input-command",
745
+ "aria-hidden": "true",
746
+ children: /*#__PURE__*/ jsx(TuiCommandText, {
747
+ text: value,
748
+ namespaceOnly: inline?.kind !== 'command'
749
+ })
750
+ }) : /*#__PURE__*/ jsx(TuiUriText, {
751
+ text: value,
752
+ mode: "literal",
753
+ onOpenUri: onOpenUri,
754
+ editor: true
755
+ }),
756
+ /*#__PURE__*/ jsxs("span", {
757
+ "aria-hidden": "true",
758
+ children: [
759
+ inline ? /*#__PURE__*/ jsx("span", {
760
+ className: "ov-tui__input-completion",
761
+ children: inline.suffix
762
+ }) : null,
763
+ hints.length ? /*#__PURE__*/ jsxs("span", {
764
+ className: "ov-tui__input-arguments",
765
+ children: [
766
+ input?.rest.endsWith(' ') ? '' : ' ',
767
+ hints.map((hint)=>hint.label).join(' ')
768
+ ]
769
+ }) : null,
770
+ value.endsWith('\n') ? '\u200b' : null
771
+ ]
772
+ })
773
+ ]
774
+ }),
775
+ /*#__PURE__*/ jsxs("span", {
776
+ id: hintId,
777
+ className: "ov-tui__input-hint-description",
778
+ "aria-live": inline?.kind === 'prefix' ? 'polite' : void 0,
779
+ children: [
780
+ inline?.value,
781
+ hints.map((hint)=>`${hint.label}: ${hint.description}`).join('; ')
782
+ ]
783
+ })
784
+ ]
785
+ });
786
+ }
787
+ function TuiComposer({ anchorRef, assistId, onFocus, onDismiss, onRequestPalette, value, history, labels, completion, disabled, readOnly, canSubmit, activeIndex, onActiveIndexChange, onValueChange, onSubmit, onOpenUri }) {
788
+ const inputRef = useRef(null);
789
+ const inputId = useId();
790
+ const mirrorRef = useRef(null);
791
+ const showSuggestions = completion.showSuggestions && completion.options.length > 0;
792
+ const preview = completion.options[activeIndex] ?? (completion.query.keyword ? completion.options[0] : void 0);
793
+ const inline = completion.enabled ? getTuiInlineCompletion(value, completion.query, preview, completion.showSuggestions) : void 0;
794
+ const keyboard = useTuiComposerKeyboard({
795
+ inputRef,
796
+ value,
797
+ history,
798
+ completion,
799
+ inline,
800
+ disabled,
801
+ readOnly,
802
+ canSubmit,
803
+ activeIndex,
804
+ onActiveIndexChange,
805
+ onValueChange,
806
+ onSubmit,
807
+ onDismiss,
808
+ onRequestPalette
809
+ });
810
+ return /*#__PURE__*/ jsxs("div", {
811
+ ref: anchorRef,
812
+ className: "ov-tui__composer",
813
+ "data-disabled": disabled || void 0,
814
+ children: [
815
+ /*#__PURE__*/ jsxs("div", {
816
+ className: "ov-tui__input-row",
817
+ "data-value": `${value}\n`,
818
+ children: [
819
+ /*#__PURE__*/ jsx("label", {
820
+ className: "ov-tui__input-label",
821
+ htmlFor: inputId,
822
+ children: labels.placeholder
823
+ }),
824
+ /*#__PURE__*/ jsx(TuiInputMirror, {
825
+ value: value,
826
+ input: completion.activeInput,
827
+ inline: inline,
828
+ colorInput: completion.query.colorInput,
829
+ onOpenUri: onOpenUri,
830
+ onScroll: (event)=>{
831
+ if (inputRef.current) {
832
+ inputRef.current.scrollTop = event.currentTarget.scrollTop;
833
+ inputRef.current.scrollLeft = event.currentTarget.scrollLeft;
834
+ }
835
+ },
836
+ mirrorRef: mirrorRef,
837
+ hintId: `${inputId}-hint`
838
+ }),
839
+ /*#__PURE__*/ jsx("textarea", {
840
+ id: inputId,
841
+ name: "command",
842
+ ref: inputRef,
843
+ className: "ov-tui__input",
844
+ rows: 1,
845
+ value: value,
846
+ placeholder: labels.placeholder,
847
+ readOnly: readOnly,
848
+ disabled: disabled,
849
+ autoCapitalize: "off",
850
+ autoCorrect: "off",
851
+ spellCheck: false,
852
+ enterKeyHint: "send",
853
+ onFocus: onFocus,
854
+ "aria-describedby": `${inputId}-shortcuts ${inputId}-hint`,
855
+ "aria-autocomplete": inline ? 'both' : 'list',
856
+ "aria-haspopup": "listbox",
857
+ "aria-controls": showSuggestions ? assistId : void 0,
858
+ "aria-activedescendant": showSuggestions && activeIndex >= 0 ? `${assistId}-${activeIndex}` : void 0,
859
+ onChange: (event)=>keyboard.change(event.target.value),
860
+ onScroll: (event)=>{
861
+ if (mirrorRef.current) {
862
+ mirrorRef.current.scrollTop = event.currentTarget.scrollTop;
863
+ mirrorRef.current.scrollLeft = event.currentTarget.scrollLeft;
864
+ }
865
+ },
866
+ onKeyDown: keyboard.handleKeyDown
867
+ })
868
+ ]
869
+ }),
870
+ /*#__PURE__*/ jsxs("div", {
871
+ className: "ov-tui__shortcuts",
872
+ id: `${inputId}-shortcuts`,
873
+ children: [
874
+ /*#__PURE__*/ jsxs("span", {
875
+ className: "ov-tui__shortcut",
876
+ children: [
877
+ /*#__PURE__*/ jsx("kbd", {
878
+ children: "/"
879
+ }),
880
+ labels.allCommands
881
+ ]
882
+ }),
883
+ /*#__PURE__*/ jsxs("span", {
884
+ className: "ov-tui__shortcut",
885
+ children: [
886
+ /*#__PURE__*/ jsx("kbd", {
887
+ children: "↑"
888
+ }),
889
+ labels.historyCommands
890
+ ]
891
+ }),
892
+ /*#__PURE__*/ jsxs("span", {
893
+ className: "ov-tui__shortcut",
894
+ children: [
895
+ /*#__PURE__*/ jsx("kbd", {
896
+ children: "↵"
897
+ }),
898
+ labels.send
899
+ ]
900
+ })
901
+ ]
902
+ }),
903
+ disabled ? /*#__PURE__*/ jsx("div", {
904
+ className: "ov-tui__unavailable",
905
+ role: "status",
906
+ children: labels.unavailableMessage
907
+ }) : null
908
+ ]
909
+ });
910
+ }
911
+ const ZH_TUI_LABELS = {
912
+ placeholder: '>_ 输入 CLI 命令,如 ov find OpenViking',
913
+ unavailableMessage: '当前无法执行命令。',
914
+ send: '发送',
915
+ allCommands: '全部指令',
916
+ historyCommands: '历史指令',
917
+ suggestions: '命令建议',
918
+ noSuggestions: '没有匹配的命令',
919
+ pending: '执行中',
920
+ success: '执行成功',
921
+ error: '执行失败',
922
+ copy: '复制',
923
+ copied: '已复制',
924
+ empty: '运行命令后将在此显示结果。',
925
+ noResult: '暂无返回结果',
926
+ justNow: '刚刚',
927
+ formatMinutesAgo: (minutes)=>`${minutes} 分钟前`,
928
+ formatHoursAgo: (hours)=>`${hours} 小时前`,
929
+ availableCommands: '可用命令',
930
+ helpHint: '输入 / 可打开命令面板。',
931
+ parameters: '参数详情',
932
+ examples: '快速体验',
933
+ noParameters: '此命令不需要参数',
934
+ loadMore: '加载更多',
935
+ resource: '资源',
936
+ parameter: '参数',
937
+ required: '必填',
938
+ description: '说明',
939
+ defaultValue: '默认值',
940
+ yes: '是',
941
+ no: '否'
942
+ };
943
+ const DEFAULT_TUI_LABELS = {
944
+ placeholder: '>_ Enter CLI commands, e.g. ov find OpenViking',
945
+ unavailableMessage: 'Commands are unavailable right now.',
946
+ send: 'Send',
947
+ allCommands: 'All commands',
948
+ historyCommands: 'History',
949
+ suggestions: 'Command suggestions',
950
+ noSuggestions: 'No matching commands',
951
+ pending: 'Running',
952
+ success: 'Succeeded',
953
+ error: 'Failed',
954
+ copy: 'Copy',
955
+ copied: 'Copied',
956
+ empty: 'Run a command to see its result here.',
957
+ noResult: 'No result returned',
958
+ justNow: 'Just now',
959
+ formatMinutesAgo: (minutes)=>`${minutes} minute${1 === minutes ? '' : 's'} ago`,
960
+ formatHoursAgo: (hours)=>`${hours} hour${1 === hours ? '' : 's'} ago`,
961
+ availableCommands: 'Available commands',
962
+ helpHint: 'Type / to open the command palette.',
963
+ parameters: 'Parameters',
964
+ examples: 'Examples',
965
+ noParameters: 'No parameters',
966
+ loadMore: 'Load more',
967
+ resource: 'Resource',
968
+ parameter: 'Parameter',
969
+ required: 'Required',
970
+ description: "Description",
971
+ defaultValue: 'Default',
972
+ yes: 'Yes',
973
+ no: 'No'
974
+ };
975
+ function resolveTuiLabels(labels, locale = 'en') {
976
+ const defaults = 'zh' === locale ? ZH_TUI_LABELS : DEFAULT_TUI_LABELS;
977
+ if (!labels) return defaults;
978
+ return {
979
+ ...defaults,
980
+ placeholder: labels.placeholder ?? defaults.placeholder,
981
+ unavailableMessage: labels.unavailableMessage ?? defaults.unavailableMessage,
982
+ send: labels.send ?? defaults.send,
983
+ allCommands: labels.allCommands ?? defaults.allCommands,
984
+ historyCommands: labels.historyCommands ?? defaults.historyCommands,
985
+ suggestions: labels.suggestions ?? defaults.suggestions,
986
+ noSuggestions: labels.noSuggestions ?? defaults.noSuggestions,
987
+ pending: labels.pending ?? defaults.pending,
988
+ success: labels.success ?? defaults.success,
989
+ error: labels.error ?? defaults.error,
990
+ copy: labels.copy ?? defaults.copy,
991
+ copied: labels.copied ?? defaults.copied,
992
+ empty: labels.empty ?? defaults.empty,
993
+ noResult: labels.noResult ?? defaults.noResult,
994
+ justNow: labels.justNow ?? defaults.justNow,
995
+ formatMinutesAgo: labels.formatMinutesAgo ?? defaults.formatMinutesAgo,
996
+ formatHoursAgo: labels.formatHoursAgo ?? defaults.formatHoursAgo,
997
+ availableCommands: labels.availableCommands ?? defaults.availableCommands,
998
+ helpHint: labels.helpHint ?? defaults.helpHint,
999
+ parameters: labels.parameters ?? defaults.parameters,
1000
+ examples: labels.examples ?? defaults.examples,
1001
+ noParameters: labels.noParameters ?? defaults.noParameters,
1002
+ loadMore: labels.loadMore ?? defaults.loadMore,
1003
+ resource: labels.resource ?? defaults.resource,
1004
+ parameter: labels.parameter ?? defaults.parameter,
1005
+ required: labels.required ?? defaults.required,
1006
+ description: labels.description ?? defaults.description,
1007
+ defaultValue: labels.defaultValue ?? defaults.defaultValue,
1008
+ yes: labels.yes ?? defaults.yes,
1009
+ no: labels.no ?? defaults.no
1010
+ };
1011
+ }
1012
+ function TuiCommandHelp({ content, onPick, labels }) {
1013
+ return /*#__PURE__*/ jsxs("div", {
1014
+ className: "ov-tui__help",
1015
+ children: [
1016
+ /*#__PURE__*/ jsx("div", {
1017
+ className: "ov-tui__help-lead",
1018
+ children: labels.availableCommands
1019
+ }),
1020
+ content.sections.map((section)=>/*#__PURE__*/ jsxs("section", {
1021
+ className: "ov-tui__help-section",
1022
+ children: [
1023
+ /*#__PURE__*/ jsx("div", {
1024
+ className: "ov-tui__help-section-label",
1025
+ children: section.label
1026
+ }),
1027
+ /*#__PURE__*/ jsx("div", {
1028
+ className: "ov-tui__help-items",
1029
+ children: section.items.map((item)=>/*#__PURE__*/ jsxs("button", {
1030
+ type: "button",
1031
+ className: "ov-tui__help-item",
1032
+ disabled: !onPick,
1033
+ onClick: ()=>onPick?.(item.name),
1034
+ children: [
1035
+ /*#__PURE__*/ jsx("span", {
1036
+ className: "ov-tui__help-name",
1037
+ children: item.name
1038
+ }),
1039
+ item.description ? /*#__PURE__*/ jsx("span", {
1040
+ className: "ov-tui__help-desc",
1041
+ children: item.description
1042
+ }) : null
1043
+ ]
1044
+ }, item.key))
1045
+ })
1046
+ ]
1047
+ }, section.key)),
1048
+ /*#__PURE__*/ jsx("div", {
1049
+ className: "ov-tui__help-footer",
1050
+ children: labels.helpHint
1051
+ })
1052
+ ]
1053
+ });
1054
+ }
1055
+ function formatTuiRecordTime(record, labels, now = Date.now()) {
1056
+ const timestamp = record.createdAtMs;
1057
+ if ('number' != typeof timestamp || !Number.isFinite(timestamp)) return record.createdAt;
1058
+ const date = new Date(timestamp);
1059
+ if (!Number.isFinite(date.getTime())) return record.createdAt;
1060
+ const elapsed = Math.max(0, now - timestamp);
1061
+ if (elapsed < 60000) return labels.justNow;
1062
+ if (elapsed < 3600000) return labels.formatMinutesAgo(Math.floor(elapsed / 60000));
1063
+ if (elapsed < 86400000) return labels.formatHoursAgo(Math.floor(elapsed / 3600000));
1064
+ const pad = (value)=>String(value).padStart(2, '0');
1065
+ return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`;
1066
+ }
1067
+ const subscribe = ()=>()=>{};
1068
+ const clientSnapshot = ()=>true;
1069
+ const serverSnapshot = ()=>false;
1070
+ function TuiRecordTime({ record, labels }) {
1071
+ const client = useSyncExternalStore(subscribe, clientSnapshot, serverSnapshot);
1072
+ const text = client ? formatTuiRecordTime(record, labels) : record.createdAt;
1073
+ return text ? /*#__PURE__*/ jsx("span", {
1074
+ className: "ov-tui__bubble-time",
1075
+ children: text
1076
+ }) : null;
1077
+ }
1078
+ function TuiCopyButton({ text, label, copiedLabel, onCopy, className }) {
1079
+ const [copied, setCopied] = useState(false);
1080
+ const handleCopy = ()=>{
1081
+ copyTuiText(text).then((succeeded)=>{
1082
+ if (!succeeded) return;
1083
+ setCopied(true);
1084
+ onCopy?.(text);
1085
+ window.setTimeout(()=>setCopied(false), 1600);
1086
+ });
1087
+ };
1088
+ return /*#__PURE__*/ jsx("button", {
1089
+ type: "button",
1090
+ className: [
1091
+ 'ov-tui__copy',
1092
+ className
1093
+ ].filter(Boolean).join(' '),
1094
+ onClick: handleCopy,
1095
+ children: copied ? copiedLabel : label
1096
+ });
1097
+ }
1098
+ function TuiCodeBlock({ text, labels, onCopy, onOpenUri }) {
1099
+ return /*#__PURE__*/ jsxs("div", {
1100
+ className: "ov-tui__code-block",
1101
+ children: [
1102
+ /*#__PURE__*/ jsx(TuiCopyButton, {
1103
+ className: "ov-tui__copy--inline",
1104
+ text: text,
1105
+ label: labels.copy,
1106
+ copiedLabel: labels.copied,
1107
+ onCopy: onCopy
1108
+ }),
1109
+ /*#__PURE__*/ jsx("pre", {
1110
+ className: "ov-tui__code-content",
1111
+ children: /*#__PURE__*/ jsx(TuiUriText, {
1112
+ text: formatTuiJson(text),
1113
+ mode: "literal",
1114
+ onOpenUri: onOpenUri
1115
+ })
1116
+ })
1117
+ ]
1118
+ });
1119
+ }
1120
+ const TuiMarkdownContext = /*#__PURE__*/ createContext(null);
1121
+ const InsideLink = /*#__PURE__*/ createContext(false);
1122
+ function textOf(children) {
1123
+ if ('string' == typeof children || 'number' == typeof children) return String(children);
1124
+ if (Array.isArray(children)) return children.map(textOf).join('');
1125
+ if (/*#__PURE__*/ isValidElement(children)) return textOf(children.props.children);
1126
+ return '';
1127
+ }
1128
+ function LinkedText({ children }) {
1129
+ const options = useContext(TuiMarkdownContext);
1130
+ const insideLink = useContext(InsideLink);
1131
+ return /*#__PURE__*/ jsx(Fragment, {
1132
+ children: insideLink ? children : Children.map(children, (child)=>'string' == typeof child ? /*#__PURE__*/ jsx(TuiUriText, {
1133
+ text: child,
1134
+ mode: "prose",
1135
+ onOpenUri: options.onOpenUri
1136
+ }) : child)
1137
+ });
1138
+ }
1139
+ function MarkdownCode({ children }) {
1140
+ const options = useContext(TuiMarkdownContext);
1141
+ const insideLink = useContext(InsideLink);
1142
+ return /*#__PURE__*/ jsx("code", {
1143
+ children: insideLink ? children : /*#__PURE__*/ jsx(TuiUriText, {
1144
+ text: textOf(children),
1145
+ mode: "literal",
1146
+ onOpenUri: options.onOpenUri
1147
+ })
1148
+ });
1149
+ }
1150
+ function MarkdownPre({ children }) {
1151
+ const options = useContext(TuiMarkdownContext);
1152
+ return /*#__PURE__*/ jsx(TuiCodeBlock, {
1153
+ text: textOf(children).replace(/\n$/, ''),
1154
+ ...options
1155
+ });
1156
+ }
1157
+ function MarkdownLink({ children, href, title }) {
1158
+ const { onOpenUri } = useContext(TuiMarkdownContext);
1159
+ const isViking = /^viking:/i.test(href ?? '');
1160
+ const target = isViking ? getTuiSafeHref(href) : href;
1161
+ return /*#__PURE__*/ jsx(InsideLink.Provider, {
1162
+ value: true,
1163
+ children: target ? /*#__PURE__*/ jsx("a", {
1164
+ href: target,
1165
+ title: title,
1166
+ className: isViking ? 'ov-tui__link' : void 0,
1167
+ target: isViking ? void 0 : '_blank',
1168
+ rel: isViking ? void 0 : 'noreferrer',
1169
+ onClick: isViking && onOpenUri ? (event)=>{
1170
+ event.preventDefault();
1171
+ onOpenUri(target);
1172
+ } : void 0,
1173
+ children: children
1174
+ }) : children
1175
+ });
1176
+ }
1177
+ const TUI_MARKDOWN_COMPONENTS = {
1178
+ p: ({ children })=>/*#__PURE__*/ jsx("p", {
1179
+ children: /*#__PURE__*/ jsx(LinkedText, {
1180
+ children: children
1181
+ })
1182
+ }),
1183
+ li: ({ children })=>/*#__PURE__*/ jsx("li", {
1184
+ children: /*#__PURE__*/ jsx(LinkedText, {
1185
+ children: children
1186
+ })
1187
+ }),
1188
+ h1: ({ children })=>/*#__PURE__*/ jsx("h1", {
1189
+ children: /*#__PURE__*/ jsx(LinkedText, {
1190
+ children: children
1191
+ })
1192
+ }),
1193
+ h2: ({ children })=>/*#__PURE__*/ jsx("h2", {
1194
+ children: /*#__PURE__*/ jsx(LinkedText, {
1195
+ children: children
1196
+ })
1197
+ }),
1198
+ h3: ({ children })=>/*#__PURE__*/ jsx("h3", {
1199
+ children: /*#__PURE__*/ jsx(LinkedText, {
1200
+ children: children
1201
+ })
1202
+ }),
1203
+ h4: ({ children })=>/*#__PURE__*/ jsx("h4", {
1204
+ children: /*#__PURE__*/ jsx(LinkedText, {
1205
+ children: children
1206
+ })
1207
+ }),
1208
+ h5: ({ children })=>/*#__PURE__*/ jsx("h5", {
1209
+ children: /*#__PURE__*/ jsx(LinkedText, {
1210
+ children: children
1211
+ })
1212
+ }),
1213
+ h6: ({ children })=>/*#__PURE__*/ jsx("h6", {
1214
+ children: /*#__PURE__*/ jsx(LinkedText, {
1215
+ children: children
1216
+ })
1217
+ }),
1218
+ strong: ({ children })=>/*#__PURE__*/ jsx("strong", {
1219
+ children: /*#__PURE__*/ jsx(LinkedText, {
1220
+ children: children
1221
+ })
1222
+ }),
1223
+ em: ({ children })=>/*#__PURE__*/ jsx("em", {
1224
+ children: /*#__PURE__*/ jsx(LinkedText, {
1225
+ children: children
1226
+ })
1227
+ }),
1228
+ del: ({ children })=>/*#__PURE__*/ jsx("del", {
1229
+ children: /*#__PURE__*/ jsx(LinkedText, {
1230
+ children: children
1231
+ })
1232
+ }),
1233
+ td: ({ children, style })=>/*#__PURE__*/ jsx("td", {
1234
+ style: style,
1235
+ children: /*#__PURE__*/ jsx(LinkedText, {
1236
+ children: children
1237
+ })
1238
+ }),
1239
+ th: ({ children, style })=>/*#__PURE__*/ jsx("th", {
1240
+ style: style,
1241
+ children: /*#__PURE__*/ jsx(LinkedText, {
1242
+ children: children
1243
+ })
1244
+ }),
1245
+ code: MarkdownCode,
1246
+ pre: MarkdownPre,
1247
+ a: MarkdownLink,
1248
+ table: ({ children })=>/*#__PURE__*/ jsx("div", {
1249
+ className: "ov-tui__table-frame",
1250
+ children: /*#__PURE__*/ jsx("table", {
1251
+ children: children
1252
+ })
1253
+ })
1254
+ };
1255
+ function TuiMarkdown({ text, ...options }) {
1256
+ return /*#__PURE__*/ jsx(TuiMarkdownContext.Provider, {
1257
+ value: options,
1258
+ children: /*#__PURE__*/ jsx("div", {
1259
+ className: "ov-tui__markdown",
1260
+ children: /*#__PURE__*/ jsx(react_markdown, {
1261
+ remarkPlugins: [
1262
+ [
1263
+ remark_gfm,
1264
+ {
1265
+ singleTilde: false
1266
+ }
1267
+ ]
1268
+ ],
1269
+ urlTransform: (url)=>/^viking:/i.test(url) ? getTuiSafeHref(url) ?? '' : defaultUrlTransform(url),
1270
+ components: TUI_MARKDOWN_COMPONENTS,
1271
+ children: text
1272
+ })
1273
+ })
1274
+ });
1275
+ }
1276
+ function getVisibleTuiResultTitle(title, command) {
1277
+ if (!title || !command) return title;
1278
+ const candidate = title.trim().replace(/^\*\*([\s\S]*)\*\*$/, '$1').replace(/^\/+/, '').trim();
1279
+ const match = matchTuiCommandInput(candidate, [
1280
+ command
1281
+ ]);
1282
+ return match && !match.rest.trim() ? void 0 : title;
1283
+ }
1284
+ function getTuiResultText(text, command) {
1285
+ const heading = text.match(/^\s*(\*\*\/?[^\r\n]+\*\*|\/[^\r\n]+)\r?\n(?:[ \t]*\r?\n)?/);
1286
+ return heading && void 0 === getVisibleTuiResultTitle(heading[1], command) ? text.slice(heading[0].length) : text;
1287
+ }
1288
+ function isTuiJson(text) {
1289
+ const first = text.trimStart().charAt(0);
1290
+ if ('{' !== first && '[' !== first) return false;
1291
+ try {
1292
+ JSON.parse(text);
1293
+ return true;
1294
+ } catch {
1295
+ return false;
1296
+ }
1297
+ }
1298
+ function TuiResourcePreview({ content, onOpenUri, onCopy, labels }) {
1299
+ const metaLabel = content.meta?.filter(Boolean).join(' · ') || content.description;
1300
+ const target = content.navigationUri ?? content.uri;
1301
+ return /*#__PURE__*/ jsxs("div", {
1302
+ className: "ov-tui__preview",
1303
+ children: [
1304
+ metaLabel ? /*#__PURE__*/ jsx("div", {
1305
+ className: "ov-tui__result-meta",
1306
+ children: /*#__PURE__*/ jsx(TuiUriText, {
1307
+ text: metaLabel,
1308
+ mode: "prose",
1309
+ onOpenUri: onOpenUri
1310
+ })
1311
+ }) : null,
1312
+ content.title ? /*#__PURE__*/ jsx("div", {
1313
+ className: "ov-tui__card-title",
1314
+ children: /*#__PURE__*/ jsx(TuiUriText, {
1315
+ text: content.title,
1316
+ mode: "literal",
1317
+ onOpenUri: onOpenUri
1318
+ })
1319
+ }) : null,
1320
+ /*#__PURE__*/ jsxs("div", {
1321
+ className: "ov-tui__preview-body",
1322
+ children: [
1323
+ content.uri ? /*#__PURE__*/ jsx(TuiUriLink, {
1324
+ uri: target,
1325
+ onOpenUri: onOpenUri,
1326
+ className: "ov-tui__link ov-tui__preview-uri",
1327
+ children: content.uri
1328
+ }) : null,
1329
+ isTuiJson(content.content) ? /*#__PURE__*/ jsx(TuiCodeBlock, {
1330
+ text: content.content,
1331
+ labels: labels,
1332
+ onCopy: onCopy,
1333
+ onOpenUri: onOpenUri
1334
+ }) : /*#__PURE__*/ jsx("pre", {
1335
+ className: "ov-tui__preview-content",
1336
+ children: /*#__PURE__*/ jsx(TuiUriText, {
1337
+ text: content.content,
1338
+ mode: "literal",
1339
+ onOpenUri: onOpenUri
1340
+ })
1341
+ })
1342
+ ]
1343
+ })
1344
+ ]
1345
+ });
1346
+ }
1347
+ const PAGE_SIZE = 20;
1348
+ function TreeIdentity({ item, onOpenUri }) {
1349
+ return /*#__PURE__*/ jsxs(Fragment, {
1350
+ children: [
1351
+ /*#__PURE__*/ jsx("span", {
1352
+ className: "ov-tui__tree-title",
1353
+ children: item.uri ? /*#__PURE__*/ jsx(TuiUriLink, {
1354
+ uri: item.uri,
1355
+ onOpenUri: onOpenUri,
1356
+ children: item.title
1357
+ }) : /*#__PURE__*/ jsx(TuiUriText, {
1358
+ text: item.title,
1359
+ mode: "literal",
1360
+ onOpenUri: onOpenUri
1361
+ })
1362
+ }),
1363
+ item.metaLabel ? /*#__PURE__*/ jsx("span", {
1364
+ className: "ov-tui__tree-meta",
1365
+ children: /*#__PURE__*/ jsx(TuiUriText, {
1366
+ text: item.metaLabel,
1367
+ mode: "prose",
1368
+ onOpenUri: onOpenUri
1369
+ })
1370
+ }) : null
1371
+ ]
1372
+ });
1373
+ }
1374
+ function TuiResourceTree({ content, onOpenUri, loadMoreLabel, noResultLabel, resourceLabel }) {
1375
+ const [visibleCount, setVisibleCount] = useState(PAGE_SIZE);
1376
+ const columns = Array.from(new Set(content.items.flatMap((item)=>item.detailRows?.map((row)=>row.label) ?? [])));
1377
+ const visibleItems = content.items.slice(0, visibleCount);
1378
+ const hiddenCount = content.items.length - visibleItems.length;
1379
+ return /*#__PURE__*/ jsxs("div", {
1380
+ className: "ov-tui__tree",
1381
+ children: [
1382
+ content.title ? /*#__PURE__*/ jsx("div", {
1383
+ className: "ov-tui__card-title",
1384
+ children: /*#__PURE__*/ jsx(TuiUriText, {
1385
+ text: content.title,
1386
+ mode: "literal",
1387
+ onOpenUri: onOpenUri
1388
+ })
1389
+ }) : null,
1390
+ content.items.length ? null : /*#__PURE__*/ jsx("div", {
1391
+ className: "ov-tui__no-result",
1392
+ children: noResultLabel
1393
+ }),
1394
+ columns.length ? /*#__PURE__*/ jsx("div", {
1395
+ className: "ov-tui__table-frame",
1396
+ children: /*#__PURE__*/ jsxs("table", {
1397
+ className: "ov-tui__table",
1398
+ children: [
1399
+ /*#__PURE__*/ jsx("thead", {
1400
+ children: /*#__PURE__*/ jsxs("tr", {
1401
+ children: [
1402
+ /*#__PURE__*/ jsx("th", {
1403
+ scope: "col",
1404
+ children: resourceLabel
1405
+ }),
1406
+ columns.map((column)=>/*#__PURE__*/ jsx("th", {
1407
+ scope: "col",
1408
+ children: column
1409
+ }, column))
1410
+ ]
1411
+ })
1412
+ }),
1413
+ /*#__PURE__*/ jsx("tbody", {
1414
+ children: visibleItems.map((item)=>/*#__PURE__*/ jsxs("tr", {
1415
+ children: [
1416
+ /*#__PURE__*/ jsx("td", {
1417
+ children: /*#__PURE__*/ jsx(TreeIdentity, {
1418
+ item: item,
1419
+ onOpenUri: onOpenUri
1420
+ })
1421
+ }),
1422
+ columns.map((column)=>{
1423
+ const value = item.detailRows?.find((row)=>row.label === column)?.value ?? '';
1424
+ return /*#__PURE__*/ jsx("td", {
1425
+ children: /*#__PURE__*/ jsx(TuiUriText, {
1426
+ text: value,
1427
+ mode: "literal",
1428
+ onOpenUri: onOpenUri
1429
+ })
1430
+ }, column);
1431
+ })
1432
+ ]
1433
+ }, item.id))
1434
+ })
1435
+ ]
1436
+ })
1437
+ }) : /*#__PURE__*/ jsx("div", {
1438
+ className: "ov-tui__tree-items",
1439
+ children: visibleItems.map((item)=>/*#__PURE__*/ jsx("div", {
1440
+ className: "ov-tui__tree-item",
1441
+ children: /*#__PURE__*/ jsx(TreeIdentity, {
1442
+ item: item,
1443
+ onOpenUri: onOpenUri
1444
+ })
1445
+ }, item.id))
1446
+ }),
1447
+ hiddenCount > 0 ? /*#__PURE__*/ jsxs("button", {
1448
+ type: "button",
1449
+ className: "ov-tui__load-more",
1450
+ onClick: ()=>setVisibleCount((count)=>count + PAGE_SIZE),
1451
+ children: [
1452
+ loadMoreLabel,
1453
+ " (",
1454
+ hiddenCount,
1455
+ ")"
1456
+ ]
1457
+ }) : null
1458
+ ]
1459
+ });
1460
+ }
1461
+ function TuiResultHeader({ command, status, label }) {
1462
+ return /*#__PURE__*/ jsxs("header", {
1463
+ className: "ov-tui__result-head",
1464
+ children: [
1465
+ /*#__PURE__*/ jsx("span", {
1466
+ className: "ov-tui__result-state",
1467
+ "data-status": status,
1468
+ role: "img",
1469
+ "aria-label": label
1470
+ }),
1471
+ /*#__PURE__*/ jsx("span", {
1472
+ className: "ov-tui__result-command",
1473
+ children: command
1474
+ })
1475
+ ]
1476
+ });
1477
+ }
1478
+ function ScoreDetails({ item }) {
1479
+ const [hovered, setHovered] = useState(false);
1480
+ const [pinned, setPinned] = useState(false);
1481
+ if (!item.scoreDetails) return /*#__PURE__*/ jsx("span", {
1482
+ className: "ov-tui__search-score",
1483
+ children: item.scoreLabel
1484
+ });
1485
+ const open = hovered || pinned;
1486
+ return /*#__PURE__*/ jsxs("span", {
1487
+ className: "ov-tui__search-score-wrap",
1488
+ children: [
1489
+ /*#__PURE__*/ jsx("button", {
1490
+ type: "button",
1491
+ className: "ov-tui__search-score",
1492
+ "aria-expanded": open,
1493
+ onClick: ()=>setPinned((current)=>!current),
1494
+ onMouseEnter: ()=>setHovered(true),
1495
+ onMouseLeave: ()=>setHovered(false),
1496
+ onFocus: ()=>setHovered(true),
1497
+ onBlur: ()=>{
1498
+ setHovered(false);
1499
+ setPinned(false);
1500
+ },
1501
+ children: item.scoreLabel
1502
+ }),
1503
+ open ? /*#__PURE__*/ jsx("span", {
1504
+ role: "tooltip",
1505
+ className: "ov-tui__score-details",
1506
+ children: item.scoreDetails
1507
+ }) : null
1508
+ ]
1509
+ });
1510
+ }
1511
+ function ResourceUri({ text }) {
1512
+ const boundary = text.lastIndexOf('/');
1513
+ return boundary > 9 ? /*#__PURE__*/ jsxs("span", {
1514
+ className: "ov-tui__search-uri",
1515
+ children: [
1516
+ /*#__PURE__*/ jsx("span", {
1517
+ className: "ov-tui__search-uri-prefix",
1518
+ children: text.slice(0, boundary + 1)
1519
+ }),
1520
+ /*#__PURE__*/ jsx("span", {
1521
+ className: "ov-tui__search-uri-suffix",
1522
+ children: text.slice(boundary + 1)
1523
+ })
1524
+ ]
1525
+ }) : /*#__PURE__*/ jsx("span", {
1526
+ className: "ov-tui__search-uri-full",
1527
+ children: text
1528
+ });
1529
+ }
1530
+ function SearchRow({ item, onOpenUri }) {
1531
+ return /*#__PURE__*/ jsxs(Fragment, {
1532
+ children: [
1533
+ item.scoreLabel || item.typeLabel ? /*#__PURE__*/ jsxs("span", {
1534
+ className: "ov-tui__search-metrics",
1535
+ children: [
1536
+ item.scoreLabel ? /*#__PURE__*/ jsx(ScoreDetails, {
1537
+ item: item
1538
+ }) : null,
1539
+ item.typeLabel ? /*#__PURE__*/ jsx("span", {
1540
+ className: "ov-tui__search-type",
1541
+ children: item.typeLabel
1542
+ }) : null
1543
+ ]
1544
+ }) : null,
1545
+ /*#__PURE__*/ jsxs("span", {
1546
+ className: "ov-tui__search-body",
1547
+ children: [
1548
+ /*#__PURE__*/ jsxs("span", {
1549
+ className: "ov-tui__search-main",
1550
+ children: [
1551
+ /*#__PURE__*/ jsx("span", {
1552
+ className: "ov-tui__search-title",
1553
+ title: item.uri ?? item.title,
1554
+ children: item.uri ? /*#__PURE__*/ jsx(TuiUriLink, {
1555
+ uri: item.uri,
1556
+ onOpenUri: onOpenUri,
1557
+ className: "ov-tui__link ov-tui__search-open",
1558
+ children: /*#__PURE__*/ jsx(ResourceUri, {
1559
+ text: item.uri
1560
+ })
1561
+ }) : /*#__PURE__*/ jsx(TuiUriText, {
1562
+ text: item.title,
1563
+ mode: "literal",
1564
+ onOpenUri: onOpenUri
1565
+ })
1566
+ }),
1567
+ item.levelLabel ? /*#__PURE__*/ jsx("span", {
1568
+ className: "ov-tui__search-level",
1569
+ children: item.levelLabel
1570
+ }) : null
1571
+ ]
1572
+ }),
1573
+ item.preview ? /*#__PURE__*/ jsx("span", {
1574
+ className: "ov-tui__search-preview",
1575
+ children: /*#__PURE__*/ jsx(TuiUriText, {
1576
+ text: item.preview,
1577
+ mode: "prose",
1578
+ onOpenUri: onOpenUri
1579
+ })
1580
+ }) : null,
1581
+ item.metaLabel ? /*#__PURE__*/ jsx("span", {
1582
+ className: "ov-tui__search-meta",
1583
+ children: /*#__PURE__*/ jsx(TuiUriText, {
1584
+ text: item.metaLabel,
1585
+ mode: "prose",
1586
+ onOpenUri: onOpenUri
1587
+ })
1588
+ }) : null
1589
+ ]
1590
+ })
1591
+ ]
1592
+ });
1593
+ }
1594
+ function TuiSearchList({ content, onOpenUri, noResultLabel }) {
1595
+ return /*#__PURE__*/ jsxs("div", {
1596
+ className: "ov-tui__search",
1597
+ children: [
1598
+ content.summary ? /*#__PURE__*/ jsx("div", {
1599
+ className: "ov-tui__search-summary",
1600
+ children: 'string' == typeof content.summary ? /*#__PURE__*/ jsx(TuiUriText, {
1601
+ text: content.summary,
1602
+ mode: "prose",
1603
+ onOpenUri: onOpenUri
1604
+ }) : content.summary
1605
+ }) : null,
1606
+ content.items.length ? /*#__PURE__*/ jsx("div", {
1607
+ className: "ov-tui__search-items",
1608
+ children: content.items.map((item)=>/*#__PURE__*/ jsx("article", {
1609
+ className: "ov-tui__search-item",
1610
+ children: /*#__PURE__*/ jsx(SearchRow, {
1611
+ item: item,
1612
+ onOpenUri: onOpenUri
1613
+ })
1614
+ }, item.id))
1615
+ }) : /*#__PURE__*/ jsx("div", {
1616
+ className: "ov-tui__no-result",
1617
+ children: noResultLabel
1618
+ })
1619
+ ]
1620
+ });
1621
+ }
1622
+ function Line({ width }) {
1623
+ return /*#__PURE__*/ jsx("span", {
1624
+ className: "ov-tui__skeleton-line",
1625
+ style: {
1626
+ width
1627
+ }
1628
+ });
1629
+ }
1630
+ function TuiSkeleton({ kind }) {
1631
+ if ('search' === kind) return /*#__PURE__*/ jsxs("div", {
1632
+ className: "ov-tui__skeleton",
1633
+ "aria-hidden": "true",
1634
+ children: [
1635
+ /*#__PURE__*/ jsxs("div", {
1636
+ className: "ov-tui__skeleton-summary",
1637
+ children: [
1638
+ /*#__PURE__*/ jsx(Line, {
1639
+ width: "100%"
1640
+ }),
1641
+ /*#__PURE__*/ jsx(Line, {
1642
+ width: "56%"
1643
+ })
1644
+ ]
1645
+ }),
1646
+ [
1647
+ 0,
1648
+ 1,
1649
+ 2
1650
+ ].map((index)=>/*#__PURE__*/ jsxs("div", {
1651
+ className: "ov-tui__skeleton-item",
1652
+ children: [
1653
+ /*#__PURE__*/ jsx("span", {
1654
+ className: "ov-tui__skeleton-icon"
1655
+ }),
1656
+ /*#__PURE__*/ jsxs("span", {
1657
+ className: "ov-tui__skeleton-lines",
1658
+ children: [
1659
+ /*#__PURE__*/ jsx(Line, {
1660
+ width: "72%"
1661
+ }),
1662
+ /*#__PURE__*/ jsx(Line, {
1663
+ width: "44%"
1664
+ })
1665
+ ]
1666
+ })
1667
+ ]
1668
+ }, index))
1669
+ ]
1670
+ });
1671
+ if ('tree' === kind) return /*#__PURE__*/ jsx("div", {
1672
+ className: "ov-tui__skeleton",
1673
+ "aria-hidden": "true",
1674
+ children: [
1675
+ 0,
1676
+ 1,
1677
+ 2,
1678
+ 3
1679
+ ].map((index)=>/*#__PURE__*/ jsx("div", {
1680
+ className: "ov-tui__skeleton-row",
1681
+ children: /*#__PURE__*/ jsx(Line, {
1682
+ width: index % 2 ? '52%' : '68%'
1683
+ })
1684
+ }, index))
1685
+ });
1686
+ if ('status' === kind) return /*#__PURE__*/ jsx("div", {
1687
+ className: "ov-tui__skeleton",
1688
+ "aria-hidden": "true",
1689
+ children: [
1690
+ 0,
1691
+ 1,
1692
+ 2
1693
+ ].map((index)=>/*#__PURE__*/ jsxs("div", {
1694
+ className: "ov-tui__skeleton-row",
1695
+ children: [
1696
+ /*#__PURE__*/ jsx(Line, {
1697
+ width: "28%"
1698
+ }),
1699
+ /*#__PURE__*/ jsx(Line, {
1700
+ width: "46%"
1701
+ })
1702
+ ]
1703
+ }, index))
1704
+ });
1705
+ if ('resource' === kind) return /*#__PURE__*/ jsxs("div", {
1706
+ className: "ov-tui__skeleton",
1707
+ "aria-hidden": "true",
1708
+ children: [
1709
+ /*#__PURE__*/ jsx(Line, {
1710
+ width: "38%"
1711
+ }),
1712
+ /*#__PURE__*/ jsxs("div", {
1713
+ className: "ov-tui__skeleton-block",
1714
+ children: [
1715
+ /*#__PURE__*/ jsx(Line, {
1716
+ width: "100%"
1717
+ }),
1718
+ /*#__PURE__*/ jsx(Line, {
1719
+ width: "92%"
1720
+ }),
1721
+ /*#__PURE__*/ jsx(Line, {
1722
+ width: "76%"
1723
+ })
1724
+ ]
1725
+ })
1726
+ ]
1727
+ });
1728
+ if ('write' === kind) return /*#__PURE__*/ jsxs("div", {
1729
+ className: "ov-tui__skeleton",
1730
+ "aria-hidden": "true",
1731
+ children: [
1732
+ /*#__PURE__*/ jsx("div", {
1733
+ className: "ov-tui__skeleton-row",
1734
+ children: /*#__PURE__*/ jsx(Line, {
1735
+ width: "64%"
1736
+ })
1737
+ }),
1738
+ /*#__PURE__*/ jsx("div", {
1739
+ className: "ov-tui__skeleton-row",
1740
+ children: /*#__PURE__*/ jsx(Line, {
1741
+ width: "42%"
1742
+ })
1743
+ })
1744
+ ]
1745
+ });
3
1746
  return /*#__PURE__*/ jsx("div", {
4
- className: "ov-tui",
5
- children: "Tui"
1747
+ className: "ov-tui__skeleton",
1748
+ "aria-hidden": "true",
1749
+ children: /*#__PURE__*/ jsxs("div", {
1750
+ className: "ov-tui__skeleton-summary",
1751
+ children: [
1752
+ /*#__PURE__*/ jsx(Line, {
1753
+ width: "100%"
1754
+ }),
1755
+ /*#__PURE__*/ jsx(Line, {
1756
+ width: "64%"
1757
+ })
1758
+ ]
1759
+ })
1760
+ });
1761
+ }
1762
+ function TuiStatusCard({ content, onOpenUri }) {
1763
+ return /*#__PURE__*/ jsxs("div", {
1764
+ className: "ov-tui__status",
1765
+ children: [
1766
+ content.title ? /*#__PURE__*/ jsx("div", {
1767
+ className: "ov-tui__card-title",
1768
+ children: /*#__PURE__*/ jsx(TuiUriText, {
1769
+ text: content.title,
1770
+ mode: "prose",
1771
+ onOpenUri: onOpenUri
1772
+ })
1773
+ }) : null,
1774
+ /*#__PURE__*/ jsx("dl", {
1775
+ className: "ov-tui__status-rows",
1776
+ children: content.rows.map((row)=>/*#__PURE__*/ jsxs("div", {
1777
+ className: "ov-tui__status-row",
1778
+ "data-variant": row.variant ?? 'inline',
1779
+ children: [
1780
+ /*#__PURE__*/ jsx("dt", {
1781
+ className: "ov-tui__status-label",
1782
+ children: row.label
1783
+ }),
1784
+ /*#__PURE__*/ jsx("dd", {
1785
+ className: "ov-tui__status-value",
1786
+ children: 'string' == typeof row.value ? /*#__PURE__*/ jsx(TuiUriText, {
1787
+ text: row.value,
1788
+ mode: "literal",
1789
+ onOpenUri: onOpenUri
1790
+ }) : row.value
1791
+ })
1792
+ ]
1793
+ }, row.label))
1794
+ })
1795
+ ]
1796
+ });
1797
+ }
1798
+ function TuiWriteResult({ content, onOpenUri }) {
1799
+ return /*#__PURE__*/ jsxs("div", {
1800
+ className: "ov-tui__write",
1801
+ children: [
1802
+ content.title ? /*#__PURE__*/ jsx("div", {
1803
+ className: "ov-tui__card-title",
1804
+ children: /*#__PURE__*/ jsx(TuiUriText, {
1805
+ text: content.title,
1806
+ mode: "prose",
1807
+ onOpenUri: onOpenUri
1808
+ })
1809
+ }) : null,
1810
+ /*#__PURE__*/ jsx("div", {
1811
+ className: "ov-tui__write-lines",
1812
+ children: content.lines.map((line, index)=>/*#__PURE__*/ jsx("div", {
1813
+ className: "ov-tui__write-line",
1814
+ children: 'string' == typeof line ? /*#__PURE__*/ jsx(TuiUriText, {
1815
+ text: line,
1816
+ mode: "prose",
1817
+ onOpenUri: onOpenUri
1818
+ }) : line
1819
+ }, index))
1820
+ })
1821
+ ]
1822
+ });
1823
+ }
1824
+ function RecordBody({ record, command, labels, onOpenUri, onCopy, onPickCommand }) {
1825
+ const { content } = record;
1826
+ if ('pending' === record.status) return /*#__PURE__*/ jsx(TuiSkeleton, {
1827
+ kind: resolveTuiSkeleton(command)
1828
+ });
1829
+ if (!content) return /*#__PURE__*/ jsx("div", {
1830
+ className: "ov-tui__muted",
1831
+ children: 'error' === record.status ? labels.error : labels.noResult
1832
+ });
1833
+ switch(content.variant){
1834
+ case 'search-list':
1835
+ return /*#__PURE__*/ jsx(TuiSearchList, {
1836
+ content: content,
1837
+ onOpenUri: onOpenUri,
1838
+ noResultLabel: labels.noResult
1839
+ });
1840
+ case 'resource-preview':
1841
+ return /*#__PURE__*/ jsx(TuiResourcePreview, {
1842
+ content: {
1843
+ ...content,
1844
+ title: getVisibleTuiResultTitle(content.title, command) ?? ''
1845
+ },
1846
+ labels: labels,
1847
+ onCopy: onCopy,
1848
+ onOpenUri: onOpenUri
1849
+ });
1850
+ case 'resource-tree':
1851
+ return /*#__PURE__*/ jsx(TuiResourceTree, {
1852
+ content: {
1853
+ ...content,
1854
+ title: getVisibleTuiResultTitle(content.title, command)
1855
+ },
1856
+ onOpenUri: onOpenUri,
1857
+ resourceLabel: labels.resource,
1858
+ loadMoreLabel: labels.loadMore,
1859
+ noResultLabel: labels.noResult
1860
+ });
1861
+ case 'status':
1862
+ return /*#__PURE__*/ jsx(TuiStatusCard, {
1863
+ content: {
1864
+ ...content,
1865
+ title: getVisibleTuiResultTitle(content.title, command)
1866
+ },
1867
+ onOpenUri: onOpenUri
1868
+ });
1869
+ case 'write-result':
1870
+ return /*#__PURE__*/ jsx(TuiWriteResult, {
1871
+ content: {
1872
+ ...content,
1873
+ title: getVisibleTuiResultTitle(content.title, command)
1874
+ },
1875
+ onOpenUri: onOpenUri
1876
+ });
1877
+ case 'command-help':
1878
+ return /*#__PURE__*/ jsx(TuiCommandHelp, {
1879
+ content: content,
1880
+ onPick: onPickCommand,
1881
+ labels: labels
1882
+ });
1883
+ default:
1884
+ {
1885
+ const text = getTuiResultText(formatTuiJson(content.text), command);
1886
+ return /*#__PURE__*/ jsx("div", {
1887
+ className: "ov-tui__text",
1888
+ children: 'markdown' === content.format ? /*#__PURE__*/ jsx(TuiMarkdown, {
1889
+ text: text,
1890
+ labels: labels,
1891
+ onCopy: onCopy,
1892
+ onOpenUri: onOpenUri
1893
+ }) : isTuiJson(text) ? /*#__PURE__*/ jsx(TuiCodeBlock, {
1894
+ text: text,
1895
+ labels: labels,
1896
+ onCopy: onCopy,
1897
+ onOpenUri: onOpenUri
1898
+ }) : /*#__PURE__*/ jsx("pre", {
1899
+ className: "ov-tui__plain",
1900
+ children: /*#__PURE__*/ jsx(TuiUriText, {
1901
+ text: text,
1902
+ mode: "prose",
1903
+ onOpenUri: onOpenUri
1904
+ })
1905
+ })
1906
+ });
1907
+ }
1908
+ }
1909
+ }
1910
+ const STATUS_TEXT = {
1911
+ pending: 'pending',
1912
+ success: 'success',
1913
+ error: 'error'
1914
+ };
1915
+ function TuiRecordItem(props) {
1916
+ const { record, labels } = props;
1917
+ const statusLabel = labels[STATUS_TEXT[record.status]];
1918
+ const input = props.command ? matchTuiCommandInput(record.command, [
1919
+ props.command
1920
+ ]) : void 0;
1921
+ const prefix = input ? getTuiCommandInputText(input.command) : '';
1922
+ return /*#__PURE__*/ jsxs("div", {
1923
+ className: "ov-tui__record",
1924
+ "data-status": record.status,
1925
+ children: [
1926
+ /*#__PURE__*/ jsxs("div", {
1927
+ className: "ov-tui__bubble",
1928
+ children: [
1929
+ /*#__PURE__*/ jsx("code", {
1930
+ className: "ov-tui__bubble-text",
1931
+ children: input ? /*#__PURE__*/ jsxs(Fragment, {
1932
+ children: [
1933
+ input.leadingWhitespace,
1934
+ /*#__PURE__*/ jsx("span", {
1935
+ className: "ov-tui__bubble-command",
1936
+ children: /*#__PURE__*/ jsx(TuiCommandText, {
1937
+ text: prefix,
1938
+ name: input.command.name
1939
+ })
1940
+ }),
1941
+ /*#__PURE__*/ jsx(TuiUriText, {
1942
+ text: input.rest,
1943
+ mode: "literal",
1944
+ onOpenUri: props.onOpenUri
1945
+ })
1946
+ ]
1947
+ }) : /*#__PURE__*/ jsx(TuiUriText, {
1948
+ text: record.command,
1949
+ mode: "literal",
1950
+ onOpenUri: props.onOpenUri
1951
+ })
1952
+ }),
1953
+ record.createdAt || void 0 !== record.createdAtMs ? /*#__PURE__*/ jsx(TuiRecordTime, {
1954
+ record: record,
1955
+ labels: labels
1956
+ }) : null
1957
+ ]
1958
+ }),
1959
+ /*#__PURE__*/ jsxs("article", {
1960
+ className: "ov-tui__result",
1961
+ children: [
1962
+ /*#__PURE__*/ jsx(TuiResultHeader, {
1963
+ command: prefix || record.command,
1964
+ status: record.status,
1965
+ label: statusLabel
1966
+ }),
1967
+ /*#__PURE__*/ jsx("div", {
1968
+ className: "ov-tui__result-body",
1969
+ children: /*#__PURE__*/ jsx(RecordBody, {
1970
+ ...props
1971
+ })
1972
+ })
1973
+ ]
1974
+ })
1975
+ ]
1976
+ });
1977
+ }
1978
+ function useTuiCompletion(value, enabled, commands, groups = [], paletteScope = null) {
1979
+ const query = getTuiCommandQuery(value, commands);
1980
+ const suggestions = groupTuiCommands(enabled ? query.matches : [], groups);
1981
+ return {
1982
+ query,
1983
+ suggestions,
1984
+ options: suggestions.flatMap((section)=>section.commands),
1985
+ enabled,
1986
+ activeInput: '/' === query.scope ? void 0 : matchTuiCommandInput(value, commands),
1987
+ showSuggestions: enabled && (query.automatic || null !== query.scope && paletteScope === query.scope)
1988
+ };
1989
+ }
1990
+ function Tui({ records, value, disabled = false, emptyState, locale = 'en', commands = [], commandGroups = [], onValueChange, onSubmit, onOpenUri, onCopy, labels, className, ...rest }) {
1991
+ const text = resolveTuiLabels(labels, locale);
1992
+ const bodyRef = useRef(null);
1993
+ const followOutput = useRef(true);
1994
+ const composerRef = useRef(null);
1995
+ const assistId = useId();
1996
+ const [dismissedValue, setDismissedValue] = useState(null);
1997
+ const [paletteScope, setPaletteScope] = useState(null);
1998
+ const [selection, setSelection] = useState({
1999
+ queryKey: value,
2000
+ index: -1
2001
+ });
2002
+ const dismissCompletion = useCallback((next)=>{
2003
+ setDismissedValue(next);
2004
+ setPaletteScope(null);
2005
+ setSelection({
2006
+ queryKey: next,
2007
+ index: -1
2008
+ });
2009
+ }, []);
2010
+ const updateValue = (next)=>{
2011
+ setDismissedValue(null);
2012
+ setSelection({
2013
+ queryKey: next,
2014
+ index: -1
2015
+ });
2016
+ if (getTuiCommandQuery(next, commands).scope !== paletteScope) setPaletteScope(null);
2017
+ onValueChange?.(next);
2018
+ };
2019
+ const readOnly = !onValueChange;
2020
+ const fillCommand = (next)=>{
2021
+ if (disabled || readOnly) return;
2022
+ updateValue(formatTuiCommandInput(next, commands));
2023
+ composerRef.current?.querySelector('textarea')?.focus({
2024
+ preventScroll: true
2025
+ });
2026
+ };
2027
+ const completion = useTuiCompletion(value, !disabled && !readOnly && dismissedValue !== value, commands, commandGroups, paletteScope);
2028
+ const queryKey = value;
2029
+ const activeIndex = selection.queryKey === queryKey && selection.index < completion.options.length ? selection.index : -1;
2030
+ const setActiveIndexSafely = useCallback((next)=>{
2031
+ setSelection((current)=>{
2032
+ const index = current.queryKey === queryKey && current.index < completion.options.length ? current.index : -1;
2033
+ return {
2034
+ queryKey,
2035
+ index: 'function' == typeof next ? next(index) : next
2036
+ };
2037
+ });
2038
+ }, [
2039
+ queryKey,
2040
+ completion.options.length
2041
+ ]);
2042
+ useEffect(()=>{
2043
+ const body = bodyRef.current;
2044
+ if (body && followOutput.current) body.scrollTop = body.scrollHeight;
2045
+ }, [
2046
+ records
2047
+ ]);
2048
+ return /*#__PURE__*/ jsxs("div", {
2049
+ className: [
2050
+ 'ov-tui',
2051
+ className
2052
+ ].filter(Boolean).join(' '),
2053
+ ...rest,
2054
+ children: [
2055
+ /*#__PURE__*/ jsx("div", {
2056
+ ref: bodyRef,
2057
+ className: "ov-tui__body",
2058
+ onScroll: (event)=>{
2059
+ const body = event.currentTarget;
2060
+ followOutput.current = body.scrollHeight - body.scrollTop - body.clientHeight <= 24;
2061
+ },
2062
+ children: records.length ? records.map((record)=>/*#__PURE__*/ jsx(TuiRecordItem, {
2063
+ record: record,
2064
+ command: findTuiCommand(record.command, commands),
2065
+ labels: text,
2066
+ onOpenUri: onOpenUri,
2067
+ onCopy: onCopy,
2068
+ onPickCommand: disabled || readOnly ? void 0 : (command)=>fillCommand(`${command} `)
2069
+ }, record.id)) : /*#__PURE__*/ jsx("div", {
2070
+ className: "ov-tui__empty",
2071
+ children: void 0 === emptyState ? text.empty : emptyState
2072
+ })
2073
+ }),
2074
+ /*#__PURE__*/ jsx(TuiAssist, {
2075
+ assistId: assistId,
2076
+ anchorRef: composerRef,
2077
+ onDismiss: dismissCompletion,
2078
+ labels: text,
2079
+ completion: completion,
2080
+ activeIndex: activeIndex,
2081
+ onActiveIndexChange: setActiveIndexSafely,
2082
+ onPick: fillCommand
2083
+ }),
2084
+ /*#__PURE__*/ jsx(TuiComposer, {
2085
+ onDismiss: dismissCompletion,
2086
+ onRequestPalette: ()=>{
2087
+ setDismissedValue(null);
2088
+ setSelection({
2089
+ queryKey: value,
2090
+ index: -1
2091
+ });
2092
+ setPaletteScope(completion.query.scope);
2093
+ },
2094
+ assistId: assistId,
2095
+ anchorRef: composerRef,
2096
+ onFocus: ()=>setDismissedValue(null),
2097
+ value: value,
2098
+ history: records.map((record)=>formatTuiCommandInput(record.command, commands)),
2099
+ labels: text,
2100
+ completion: completion,
2101
+ disabled: disabled,
2102
+ readOnly: readOnly,
2103
+ canSubmit: Boolean(onSubmit) && !readOnly,
2104
+ activeIndex: activeIndex,
2105
+ onActiveIndexChange: setActiveIndexSafely,
2106
+ onValueChange: onValueChange ? updateValue : void 0,
2107
+ onSubmit: (command)=>{
2108
+ if (disabled || readOnly) return;
2109
+ followOutput.current = true;
2110
+ onSubmit?.(command);
2111
+ },
2112
+ onOpenUri: onOpenUri
2113
+ })
2114
+ ]
6
2115
  });
7
2116
  }
8
2117
  export { Tui };