@openviking/react 0.1.2 → 0.1.4

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 (249) hide show
  1. package/LICENSE.arco-design +21 -0
  2. package/README.md +25 -15
  3. package/dist/0~0.js +19 -0
  4. package/dist/2~0.js +2360 -0
  5. package/dist/2~0.js.LICENSE.txt +23 -0
  6. package/dist/3c~0.js +2206 -0
  7. package/dist/3~0.js +1205 -1982
  8. package/dist/4~0.js +18 -0
  9. package/dist/9~0.js +43 -0
  10. package/dist/ae~0.js +487 -0
  11. package/dist/ark-message-list-view~0.js +530 -119
  12. package/dist/a~0.js +1289 -10
  13. package/dist/c7~0.js +38 -2
  14. package/dist/ck~0.js +23 -0
  15. package/dist/client/index.d.ts +2 -1
  16. package/dist/client/paths.d.ts +64 -0
  17. package/dist/client/provider.d.ts +5 -3
  18. package/dist/client/response.d.ts +31 -0
  19. package/dist/client/sse.d.ts +39 -0
  20. package/dist/client/stream.d.ts +26 -0
  21. package/dist/client/types.d.ts +109 -5
  22. package/dist/client.js +2 -239
  23. package/dist/components/agent-connect/agent-connect-copy.d.ts +19 -33
  24. package/dist/components/agent-connect/agent-connect-design.d.ts +1935 -167
  25. package/dist/components/agent-connect/agent-connect-instructions.d.ts +135 -0
  26. package/dist/components/agent-connect/locales/en-US.d.ts +20 -0
  27. package/dist/components/agent-connect/locales/zh-CN.d.ts +3 -0
  28. package/dist/components/agent-connect/style.css +14 -2
  29. package/dist/components/agent-connect/types.d.ts +2 -1
  30. package/dist/components/directory-tour/directory-tour.d.ts +3 -0
  31. package/dist/components/directory-tour/index.d.ts +3 -0
  32. package/dist/components/directory-tour/locales/en-US.d.ts +3 -0
  33. package/dist/components/directory-tour/locales/zh-CN.d.ts +3 -0
  34. package/dist/components/directory-tour/steps.d.ts +5 -0
  35. package/dist/components/directory-tour/style.css +237 -0
  36. package/dist/components/directory-tour/style.js +0 -0
  37. package/dist/components/directory-tour/types.d.ts +42 -0
  38. package/dist/components/directory-tour/use-tour-anchor.d.ts +5 -0
  39. package/dist/components/directory-tour/use-tour-position.d.ts +12 -0
  40. package/dist/components/directory-tour.js +40 -0
  41. package/dist/components/file-browser-entries/file-browser-entries-icons.d.ts +18 -0
  42. package/dist/components/file-browser-entries/file-browser-entries.d.ts +14 -0
  43. package/dist/components/file-browser-entries/index.d.ts +1 -0
  44. package/dist/components/file-browser-entries/labels.d.ts +3 -0
  45. package/dist/components/file-browser-entries/locales/en-US.d.ts +6 -0
  46. package/dist/components/file-browser-entries/locales/zh-CN.d.ts +6 -0
  47. package/dist/components/file-browser-entries/style.css +905 -0
  48. package/dist/components/file-browser-entries/style.js +0 -0
  49. package/dist/components/file-browser-entries/types.d.ts +63 -0
  50. package/dist/components/file-browser-entries.js +1 -0
  51. package/dist/components/file-preview/file-preview-adapters.d.ts +2 -1
  52. package/dist/components/file-preview/file-preview-body.d.ts +2 -1
  53. package/dist/components/file-preview/file-preview-breadcrumb-menu.d.ts +2 -1
  54. package/dist/components/file-preview/file-preview-breadcrumb.d.ts +2 -1
  55. package/dist/components/file-preview/file-preview-directory.d.ts +33 -0
  56. package/dist/components/file-preview/file-preview-handle-adapters.d.ts +2 -1
  57. package/dist/components/file-preview/file-preview-header.d.ts +25 -3
  58. package/dist/components/file-preview/file-preview-image-frame.d.ts +5 -0
  59. package/dist/components/file-preview/file-preview-labels.d.ts +2 -14
  60. package/dist/components/file-preview/file-preview-level-tabs.d.ts +7 -0
  61. package/dist/components/file-preview/file-preview-markdown-images.d.ts +13 -0
  62. package/dist/components/file-preview/file-preview-panels.d.ts +44 -0
  63. package/dist/components/file-preview/file-preview-state.d.ts +10 -3
  64. package/dist/components/file-preview/file-preview-viewer.d.ts +2 -1
  65. package/dist/components/file-preview/file-preview.d.ts +1 -1
  66. package/dist/components/file-preview/index.d.ts +2 -1
  67. package/dist/components/file-preview/level-selection.d.ts +25 -0
  68. package/dist/components/file-preview/locales/en-US.d.ts +16 -0
  69. package/dist/components/file-preview/locales/zh-CN.d.ts +16 -0
  70. package/dist/components/file-preview/style.css +234 -3
  71. package/dist/components/file-preview/types.d.ts +134 -11
  72. package/dist/components/file-preview/use-directory-level.d.ts +30 -0
  73. package/dist/components/file-preview/use-file-preview-actions-context.d.ts +6 -2
  74. package/dist/components/file-preview/use-file-preview-actions.d.ts +1 -1
  75. package/dist/components/file-preview/use-file-preview-levels.d.ts +7 -0
  76. package/dist/components/file-preview/use-file-preview-view-state.d.ts +15 -0
  77. package/dist/components/file-preview.js +1 -1
  78. package/dist/components/file-tree/file-tree-info-labels.d.ts +0 -15
  79. package/dist/components/file-tree/file-tree-info-tooltip.d.ts +7 -7
  80. package/dist/components/file-tree/file-tree-labels.d.ts +4 -0
  81. package/dist/components/file-tree/file-tree-row-context.d.ts +0 -5
  82. package/dist/components/file-tree/file-tree-row-shared.d.ts +1 -4
  83. package/dist/components/file-tree/file-tree-toolbar.d.ts +11 -0
  84. package/dist/components/file-tree/file-tree-tooltip-surface.d.ts +8 -8
  85. package/dist/components/file-tree/locales/en-US.d.ts +69 -0
  86. package/dist/components/file-tree/locales/zh-CN.d.ts +69 -0
  87. package/dist/components/file-tree/style.css +207 -42
  88. package/dist/components/file-tree/types.d.ts +58 -10
  89. package/dist/components/file-tree/use-file-tree-actions.d.ts +4 -1
  90. package/dist/components/scope-switcher/labels.d.ts +3 -0
  91. package/dist/components/scope-switcher/locales/en-US.d.ts +8 -0
  92. package/dist/components/scope-switcher/locales/zh-CN.d.ts +8 -0
  93. package/dist/components/scope-switcher/scope-panel.d.ts +1 -1
  94. package/dist/components/scope-switcher/scope-switcher.d.ts +1 -1
  95. package/dist/components/scope-switcher/style.css +14 -2
  96. package/dist/components/scope-switcher/types.d.ts +11 -5
  97. package/dist/components/style.css +10144 -6840
  98. package/dist/components/tui/locales/en-US.d.ts +35 -0
  99. package/dist/components/tui/locales/zh-CN.d.ts +35 -0
  100. package/dist/components/tui/style.css +310 -18
  101. package/dist/components/tui/tui-copy-button.d.ts +1 -1
  102. package/dist/components/tui/tui-empty.d.ts +25 -0
  103. package/dist/components/tui/tui-labels.d.ts +2 -2
  104. package/dist/components/tui/tui.d.ts +1 -1
  105. package/dist/components/tui/types.d.ts +35 -12
  106. package/dist/components/tui.js +1 -1
  107. package/dist/components/viking-bot/ark-adapter.d.ts +2 -0
  108. package/dist/components/viking-bot/ark-message-body.d.ts +1 -7
  109. package/dist/components/viking-bot/ark-message-list-view.d.ts +1 -1
  110. package/dist/components/viking-bot/ark-message-row.d.ts +3 -1
  111. package/dist/components/viking-bot/bot-popover.d.ts +9 -0
  112. package/dist/components/viking-bot/capabilities.d.ts +49 -0
  113. package/dist/components/viking-bot/composer-attachments.d.ts +13 -0
  114. package/dist/components/viking-bot/composer-controls.d.ts +10 -0
  115. package/dist/components/viking-bot/composer-footer.d.ts +17 -0
  116. package/dist/components/viking-bot/composer-references.d.ts +20 -0
  117. package/dist/components/viking-bot/composer-text.d.ts +10 -0
  118. package/dist/components/viking-bot/index.d.ts +3 -1
  119. package/dist/components/viking-bot/interaction/ask-human-fields.d.ts +1 -1
  120. package/dist/components/viking-bot/interaction/labels.d.ts +2 -1
  121. package/dist/components/viking-bot/interaction/locales/en-US.d.ts +17 -0
  122. package/dist/components/viking-bot/interaction/locales/zh-CN.d.ts +17 -0
  123. package/dist/components/viking-bot/interaction/types.d.ts +8 -3
  124. package/dist/components/viking-bot/interaction/viking-bot-interaction.d.ts +1 -1
  125. package/dist/components/viking-bot/labels.d.ts +2 -0
  126. package/dist/components/viking-bot/locales/en-US.d.ts +40 -0
  127. package/dist/components/viking-bot/locales/zh-CN.d.ts +40 -0
  128. package/dist/components/viking-bot/markdown-links.d.ts +27 -0
  129. package/dist/components/viking-bot/message-activity.d.ts +7 -0
  130. package/dist/components/viking-bot/message-code-block.d.ts +8 -0
  131. package/dist/components/viking-bot/message-footer.d.ts +8 -0
  132. package/dist/components/viking-bot/message-markdown.d.ts +9 -0
  133. package/dist/components/viking-bot/model.d.ts +37 -3
  134. package/dist/components/viking-bot/quick-input-tracker.d.ts +16 -0
  135. package/dist/components/viking-bot/quick-inputs.d.ts +6 -0
  136. package/dist/components/viking-bot/reference-picker.d.ts +16 -0
  137. package/dist/components/viking-bot/session-actions.d.ts +11 -0
  138. package/dist/components/viking-bot/style.css +1486 -48
  139. package/dist/components/viking-bot/tool-activity.d.ts +9 -0
  140. package/dist/components/viking-bot/tool-result-links.d.ts +6 -0
  141. package/dist/components/viking-bot/types.d.ts +21 -9
  142. package/dist/components/viking-bot/use-quick-input.d.ts +17 -0
  143. package/dist/components/viking-bot/viking-bot.d.ts +1 -6
  144. package/dist/components/viking-bot/welcome.d.ts +8 -0
  145. package/dist/components/viking-bot.js +1 -1
  146. package/dist/c~0.js +533 -66
  147. package/dist/e~0.js +333 -0
  148. package/dist/file-preview-viewer~0.js +90 -8
  149. package/dist/f~0.js +39 -47
  150. package/dist/h~0.js +5 -1
  151. package/dist/icons/console-icons.d.ts +12 -0
  152. package/dist/icons/index.d.ts +2 -0
  153. package/dist/icons/viking-bot-icons.d.ts +6 -0
  154. package/dist/icons.js +1 -0
  155. package/dist/index.d.ts +4 -0
  156. package/dist/index.js +3 -1
  157. package/dist/k~0.js +1 -0
  158. package/dist/lg~0.js +155 -0
  159. package/dist/lk~0.js +37 -8
  160. package/dist/l~0.js +1447 -25
  161. package/dist/modules/console/command-messages.d.ts +19 -0
  162. package/dist/modules/console/command-parser.d.ts +15 -0
  163. package/dist/modules/console/command-specs.d.ts +15 -0
  164. package/dist/modules/console/commands.d.ts +6 -0
  165. package/dist/modules/console/console-history.d.ts +10 -0
  166. package/dist/modules/console/console-toolbar.d.ts +18 -0
  167. package/dist/modules/console/console.d.ts +1 -3
  168. package/dist/modules/console/controller.d.ts +17 -0
  169. package/dist/modules/console/index.d.ts +2 -0
  170. package/dist/modules/console/labels.d.ts +61 -0
  171. package/dist/modules/console/locales/en-US.d.ts +49 -0
  172. package/dist/modules/console/locales/zh-CN.d.ts +3 -0
  173. package/dist/modules/console/localize-records.d.ts +11 -0
  174. package/dist/modules/console/results.d.ts +2 -0
  175. package/dist/modules/console/style.css +10905 -15
  176. package/dist/modules/console/types.d.ts +59 -80
  177. package/dist/modules/console/use-console.d.ts +3 -0
  178. package/dist/modules/console.js +1 -1
  179. package/dist/modules/file-browser/file-browser-detail-icons.d.ts +10 -0
  180. package/dist/modules/file-browser/file-browser-detail.d.ts +34 -0
  181. package/dist/modules/file-browser/file-browser-empty.d.ts +3 -0
  182. package/dist/modules/file-browser/file-browser-failure.d.ts +22 -0
  183. package/dist/modules/file-browser/file-browser-icons.d.ts +18 -0
  184. package/dist/modules/file-browser/file-browser-labels.d.ts +27 -0
  185. package/dist/modules/file-browser/file-browser-layout.d.ts +27 -0
  186. package/dist/modules/file-browser/file-browser-toolbar.d.ts +17 -0
  187. package/dist/modules/file-browser/file-browser-tree-pane.d.ts +32 -0
  188. package/dist/modules/file-browser/file-browser.d.ts +14 -5
  189. package/dist/modules/file-browser/find-result.d.ts +24 -0
  190. package/dist/modules/file-browser/fs-directories.d.ts +33 -0
  191. package/dist/modules/file-browser/fs-file-kind.d.ts +19 -0
  192. package/dist/modules/file-browser/fs-icon.d.ts +17 -0
  193. package/dist/modules/file-browser/fs-model.d.ts +106 -0
  194. package/dist/modules/file-browser/fs-page.d.ts +16 -0
  195. package/dist/modules/file-browser/fs-path.d.ts +16 -0
  196. package/dist/modules/file-browser/fs-read-directory.d.ts +16 -0
  197. package/dist/modules/file-browser/fs-scope.d.ts +22 -0
  198. package/dist/modules/file-browser/fs-stat.d.ts +25 -0
  199. package/dist/modules/file-browser/index.d.ts +3 -1
  200. package/dist/modules/file-browser/locales/en-US.d.ts +25 -0
  201. package/dist/modules/file-browser/locales/zh-CN.d.ts +25 -0
  202. package/dist/modules/file-browser/style.css +6388 -41
  203. package/dist/modules/file-browser/types.d.ts +206 -52
  204. package/dist/modules/file-browser/use-container-width.d.ts +17 -0
  205. package/dist/modules/file-browser/use-file-browser.d.ts +54 -0
  206. package/dist/modules/file-browser/use-fs-preview.d.ts +65 -0
  207. package/dist/modules/file-browser/use-fs-search.d.ts +35 -0
  208. package/dist/modules/file-browser/use-fs-tree.d.ts +43 -0
  209. package/dist/modules/file-browser/use-request-scope.d.ts +39 -0
  210. package/dist/modules/file-browser.js +1 -1
  211. package/dist/modules/scope-cascade/labels.d.ts +6 -0
  212. package/dist/modules/scope-cascade/locales/en-US.d.ts +6 -0
  213. package/dist/modules/scope-cascade/locales/zh-CN.d.ts +3 -0
  214. package/dist/modules/scope-cascade/scope-cascade.d.ts +1 -1
  215. package/dist/modules/scope-cascade/style.css +14 -2
  216. package/dist/modules/scope-cascade/types.d.ts +3 -0
  217. package/dist/modules/style.css +17338 -77
  218. package/dist/nx~0.js +15 -0
  219. package/dist/n~0.js +403 -144
  220. package/dist/o~0.js +106 -0
  221. package/dist/p~0.js +27 -0
  222. package/dist/rslib-runtime~0.js +42 -0
  223. package/dist/r~0.js +152 -0
  224. package/dist/shared/components/divider/divider.d.ts +18 -0
  225. package/dist/shared/components/divider/index.d.ts +1 -0
  226. package/dist/shared/components/divider/types.d.ts +35 -0
  227. package/dist/shared/components/drawer/drawer.d.ts +13 -0
  228. package/dist/shared/components/drawer/index.d.ts +1 -0
  229. package/dist/shared/components/overlay/types.d.ts +7 -0
  230. package/dist/shared/components/{tooltip/use-tooltip-position.d.ts → overlay/use-overlay-position.d.ts} +6 -6
  231. package/dist/shared/components/popover/index.d.ts +1 -0
  232. package/dist/shared/components/popover/popover.d.ts +23 -0
  233. package/dist/shared/components/popover/types.d.ts +50 -0
  234. package/dist/shared/components/resizable/clamp.d.ts +13 -0
  235. package/dist/shared/components/resizable/index.d.ts +2 -0
  236. package/dist/shared/components/resizable/resizable-handle.d.ts +25 -0
  237. package/dist/shared/components/resizable/types.d.ts +48 -0
  238. package/dist/shared/components/tooltip/types.d.ts +5 -5
  239. package/dist/shared/components/tooltip/use-portal-theme.d.ts +3 -0
  240. package/dist/shared/locale.d.ts +6 -0
  241. package/dist/style.css +27753 -7176
  242. package/dist/u~0.js +75 -58
  243. package/dist/viking-bot-composer~0.js +434 -77
  244. package/dist/viking-bot-interaction~0.js +11 -11
  245. package/package.json +18 -4
  246. package/dist/components/file-tree/file-tree-tooltip.d.ts +0 -17
  247. package/dist/components/tui/tui-labels-zh.d.ts +0 -2
  248. package/dist/g~0.js +0 -1207
  249. package/dist/modules/file-browser/file-browser-toolbar-button.d.ts +0 -10
package/dist/g~0.js DELETED
@@ -1,1207 +0,0 @@
1
- import { Fragment as jsx_runtime_Fragment, jsx, jsxs } from "react/jsx-runtime";
2
- import { Fragment, Suspense, cloneElement, forwardRef, lazy, useCallback, useEffect, useId, useImperativeHandle, useLayoutEffect, useRef, useState } from "react";
3
- import { createPortal } from "react-dom";
4
- function FilePreviewEditor({ draft, text, loading, failed, saveFailed, saving, onChange, onCancel }) {
5
- if (loading) return /*#__PURE__*/ jsx("div", {
6
- className: "ov-file-preview__state",
7
- role: "status",
8
- children: /*#__PURE__*/ jsx("p", {
9
- className: "ov-file-preview__state-title",
10
- children: text.loading
11
- })
12
- });
13
- if (failed) return /*#__PURE__*/ jsxs("div", {
14
- className: "ov-file-preview__state",
15
- role: "alert",
16
- children: [
17
- /*#__PURE__*/ jsx("p", {
18
- className: "ov-file-preview__state-title",
19
- children: text.loadFailed
20
- }),
21
- /*#__PURE__*/ jsx("button", {
22
- type: "button",
23
- className: "ov-file-preview__button",
24
- onClick: onCancel,
25
- children: text.leaveEditing
26
- })
27
- ]
28
- });
29
- return /*#__PURE__*/ jsxs("div", {
30
- className: "ov-file-preview__editor",
31
- children: [
32
- /*#__PURE__*/ jsx("textarea", {
33
- className: "ov-file-preview__textarea",
34
- value: draft,
35
- readOnly: saving,
36
- "aria-label": text.editor,
37
- spellCheck: false,
38
- onChange: (event)=>onChange(event.target.value)
39
- }),
40
- saveFailed ? /*#__PURE__*/ jsx("p", {
41
- className: "ov-file-preview__notice",
42
- role: "alert",
43
- children: text.saveFailed
44
- }) : null
45
- ]
46
- });
47
- }
48
- function encodeText(content) {
49
- return new TextEncoder().encode(content);
50
- }
51
- function toFileSource(source) {
52
- const { content, file, url, fileName, fileType } = source;
53
- if ('string' == typeof content) return {
54
- kind: 'bytes',
55
- bytes: encodeText(content),
56
- name: fileName,
57
- ...fileType ? {
58
- fileType
59
- } : {}
60
- };
61
- if (file) return {
62
- kind: 'file',
63
- file: file instanceof File ? file : new File([
64
- file
65
- ], fileName),
66
- name: fileName,
67
- ...fileType ? {
68
- fileType
69
- } : {}
70
- };
71
- if (url) return {
72
- kind: 'url',
73
- url,
74
- name: fileName,
75
- ...fileType ? {
76
- fileType
77
- } : {}
78
- };
79
- }
80
- function readCopyableText(source) {
81
- const { content } = source;
82
- return 'string' == typeof content && content.length > 0 ? content : void 0;
83
- }
84
- function isEmptyFile(source) {
85
- return '' === source.content;
86
- }
87
- function StatePanel({ title, description, action }) {
88
- return /*#__PURE__*/ jsxs("div", {
89
- className: "ov-file-preview__state",
90
- role: "status",
91
- children: [
92
- /*#__PURE__*/ jsx("p", {
93
- className: "ov-file-preview__state-title",
94
- children: title
95
- }),
96
- description ? /*#__PURE__*/ jsx("p", {
97
- className: "ov-file-preview__state-description",
98
- children: description
99
- }) : null,
100
- action
101
- ]
102
- });
103
- }
104
- function EmptyFileState({ text }) {
105
- return /*#__PURE__*/ jsx(StatePanel, {
106
- title: text.fileEmpty
107
- });
108
- }
109
- function LoadingState({ text }) {
110
- return /*#__PURE__*/ jsx(StatePanel, {
111
- title: text.loading
112
- });
113
- }
114
- function LoadFailedState({ text, description, onRetry }) {
115
- return /*#__PURE__*/ jsx(StatePanel, {
116
- title: text.loadFailed,
117
- description: description,
118
- action: onRetry ? /*#__PURE__*/ jsx("button", {
119
- type: "button",
120
- className: "ov-file-preview__button",
121
- onClick: onRetry,
122
- children: text.retry
123
- }) : void 0
124
- });
125
- }
126
- function UnsupportedState({ text, onDownload }) {
127
- return /*#__PURE__*/ jsx(StatePanel, {
128
- title: text.unsupported,
129
- action: onDownload ? /*#__PURE__*/ jsx("button", {
130
- type: "button",
131
- className: "ov-file-preview__button",
132
- onClick: onDownload,
133
- children: text.download
134
- }) : void 0
135
- });
136
- }
137
- function TruncatedNotice({ text }) {
138
- return /*#__PURE__*/ jsx("p", {
139
- className: "ov-file-preview__notice",
140
- children: text.truncated
141
- });
142
- }
143
- const Viewer = /*#__PURE__*/ lazy(async ()=>{
144
- const { FilePreviewViewer } = await import("./file-preview-viewer~0.js");
145
- return {
146
- default: FilePreviewViewer
147
- };
148
- });
149
- function LazyFilePreviewViewer(props) {
150
- return /*#__PURE__*/ jsx(Suspense, {
151
- fallback: /*#__PURE__*/ jsx(LoadingState, {
152
- text: props.text
153
- }),
154
- children: /*#__PURE__*/ jsx(Viewer, {
155
- ...props
156
- })
157
- });
158
- }
159
- function FilePreviewBody({ fileTab, text, locale, viewMode, editing, onViewModeChange, onHandleChange, onViewModesChange, onDownload, onLinkClick, onCancelEditing }) {
160
- if (editing.editing || editing.loadingEdit || editing.editFailed) return /*#__PURE__*/ jsx(FilePreviewEditor, {
161
- draft: editing.draft,
162
- text: text,
163
- loading: editing.loadingEdit,
164
- failed: editing.editFailed,
165
- saveFailed: editing.saveFailed,
166
- saving: editing.saving,
167
- onChange: editing.updateDraft,
168
- onCancel: onCancelEditing
169
- });
170
- if (isEmptyFile(fileTab.source)) return /*#__PURE__*/ jsx(EmptyFileState, {
171
- text: text
172
- });
173
- return /*#__PURE__*/ jsx(LazyFilePreviewViewer, {
174
- tab: fileTab,
175
- text: text,
176
- locale: locale,
177
- viewMode: viewMode,
178
- onViewModeChange: onViewModeChange,
179
- onDownload: onDownload,
180
- onHandleChange: onHandleChange,
181
- onViewModesChange: onViewModesChange,
182
- onLinkClick: onLinkClick
183
- });
184
- }
185
- const OFFSET = 6;
186
- const VIEWPORT_MARGIN = 8;
187
- const OPPOSITE = {
188
- top: 'bottom',
189
- bottom: 'top',
190
- left: 'right',
191
- right: 'left'
192
- };
193
- function resolvePosition(trigger, surface, placement) {
194
- const viewportWidth = window.innerWidth;
195
- const viewportHeight = window.innerHeight;
196
- const fits = (side)=>{
197
- if ('top' === side) return trigger.top - surface.height - OFFSET >= VIEWPORT_MARGIN;
198
- if ('bottom' === side) return trigger.bottom + surface.height + OFFSET <= viewportHeight - VIEWPORT_MARGIN;
199
- if ('left' === side) return trigger.left - surface.width - OFFSET >= VIEWPORT_MARGIN;
200
- return trigger.right + surface.width + OFFSET <= viewportWidth - VIEWPORT_MARGIN;
201
- };
202
- const side = fits(placement) || !fits(OPPOSITE[placement]) ? placement : OPPOSITE[placement];
203
- const clamp = (value, size, limit)=>Math.min(Math.max(value, VIEWPORT_MARGIN), limit - size - VIEWPORT_MARGIN);
204
- if ('top' === side || 'bottom' === side) {
205
- const top = 'top' === side ? trigger.top - surface.height - OFFSET : trigger.bottom + OFFSET;
206
- const left = trigger.left + trigger.width / 2 - surface.width / 2;
207
- return {
208
- top: clamp(top, surface.height, viewportHeight),
209
- left: clamp(left, surface.width, viewportWidth),
210
- placement: side
211
- };
212
- }
213
- const left = 'left' === side ? trigger.left - surface.width - OFFSET : trigger.right + OFFSET;
214
- const top = trigger.top + trigger.height / 2 - surface.height / 2;
215
- return {
216
- top: clamp(top, surface.height, viewportHeight),
217
- left: clamp(left, surface.width, viewportWidth),
218
- placement: side
219
- };
220
- }
221
- function useTooltipPosition(open, triggerRef, surface, placement) {
222
- const [position, setPosition] = useState({
223
- top: 0,
224
- left: 0,
225
- placement
226
- });
227
- useLayoutEffect(()=>{
228
- if (!open) return;
229
- const trigger = triggerRef.current;
230
- if (!trigger || !surface) return;
231
- const written = new Set();
232
- const syncTheme = ()=>{
233
- const triggerStyle = window.getComputedStyle(trigger);
234
- const seen = new Set();
235
- for (const name of Array.from(triggerStyle)){
236
- if (!name.startsWith('--ov-ui-color-')) continue;
237
- const value = triggerStyle.getPropertyValue(name).trim();
238
- if (value) {
239
- seen.add(name);
240
- surface.style.setProperty(name, value);
241
- }
242
- }
243
- for (const name of written)if (!seen.has(name)) surface.style.removeProperty(name);
244
- written.clear();
245
- seen.forEach((name)=>written.add(name));
246
- };
247
- syncTheme();
248
- const themeObserver = new MutationObserver(syncTheme);
249
- const observerOptions = {
250
- attributes: true,
251
- attributeFilter: [
252
- 'class',
253
- 'style',
254
- 'data-theme'
255
- ]
256
- };
257
- for(let node = trigger; node; node = node.parentElement)themeObserver.observe(node, observerOptions);
258
- const update = ()=>{
259
- const triggerRect = trigger.getBoundingClientRect();
260
- const surfaceRect = surface.getBoundingClientRect();
261
- const next = resolvePosition(triggerRect, {
262
- width: surfaceRect.width,
263
- height: surfaceRect.height
264
- }, placement);
265
- setPosition((previous)=>previous.top === next.top && previous.left === next.left && previous.placement === next.placement ? previous : next);
266
- };
267
- update();
268
- const observer = new ResizeObserver(update);
269
- observer.observe(surface);
270
- window.addEventListener('scroll', update, true);
271
- window.addEventListener('resize', update);
272
- return ()=>{
273
- observer.disconnect();
274
- themeObserver.disconnect();
275
- window.removeEventListener('scroll', update, true);
276
- window.removeEventListener('resize', update);
277
- };
278
- }, [
279
- open,
280
- placement,
281
- surface,
282
- triggerRef
283
- ]);
284
- return position;
285
- }
286
- const DEFAULT_LABELS = {
287
- close: 'Close'
288
- };
289
- function useMergedRef(ref, target) {
290
- const merged = useCallback((node)=>{
291
- target.current = node;
292
- if ('function' == typeof ref) ref(node);
293
- else if (ref) ref.current = node;
294
- }, [
295
- ref,
296
- target
297
- ]);
298
- return merged;
299
- }
300
- function Tooltip({ children, content, placement = 'top', trigger = 'hover', delay = 300, disabled = false, className, style, onOpenChange, labels }) {
301
- const text = {
302
- ...DEFAULT_LABELS,
303
- ...labels
304
- };
305
- const [open, setOpen] = useState(false);
306
- const triggerRef = useRef(null);
307
- const timerRef = useRef(void 0);
308
- const [surfaceNode, setSurfaceNode] = useState(null);
309
- const id = useId();
310
- const position = useTooltipPosition(open, triggerRef, surfaceNode, placement);
311
- const change = useCallback((next)=>{
312
- setOpen(next);
313
- onOpenChange?.(next);
314
- }, [
315
- onOpenChange
316
- ]);
317
- const clearTimer = useCallback(()=>{
318
- if (void 0 !== timerRef.current) {
319
- window.clearTimeout(timerRef.current);
320
- timerRef.current = void 0;
321
- }
322
- }, []);
323
- useEffect(()=>clearTimer, [
324
- clearTimer
325
- ]);
326
- useEffect(()=>{
327
- if (disabled) {
328
- clearTimer();
329
- setOpen(false);
330
- }
331
- }, [
332
- disabled,
333
- clearTimer
334
- ]);
335
- useEffect(()=>{
336
- if (!open || 'click' !== trigger) return;
337
- const onPointerDown = (event)=>{
338
- const target = event.target;
339
- if (surfaceNode?.contains(target) || triggerRef.current?.contains(target)) return;
340
- change(false);
341
- };
342
- const onKeyDown = (event)=>{
343
- if ('Escape' === event.key) change(false);
344
- };
345
- document.addEventListener('mousedown', onPointerDown);
346
- document.addEventListener('keydown', onKeyDown);
347
- return ()=>{
348
- document.removeEventListener('mousedown', onPointerDown);
349
- document.removeEventListener('keydown', onKeyDown);
350
- };
351
- }, [
352
- change,
353
- open,
354
- surfaceNode,
355
- trigger
356
- ]);
357
- const show = ()=>{
358
- if (disabled) return;
359
- if ('click' === trigger) return void change(!open);
360
- clearTimer();
361
- timerRef.current = window.setTimeout(()=>{
362
- change(true);
363
- timerRef.current = void 0;
364
- }, delay);
365
- };
366
- const hide = ()=>{
367
- if ('click' === trigger) return;
368
- clearTimer();
369
- change(false);
370
- };
371
- const child = children;
372
- const childProps = child.props;
373
- const childRef = child.ref;
374
- const mergedRef = useMergedRef(childRef, triggerRef);
375
- const triggerElement = /*#__PURE__*/ cloneElement(child, {
376
- ref: mergedRef,
377
- 'aria-describedby': open && 'hover' === trigger ? id : void 0,
378
- 'aria-expanded': 'click' === trigger ? open : void 0,
379
- onMouseEnter: (event)=>{
380
- childProps.onMouseEnter?.(event);
381
- if ('hover' === trigger) show();
382
- },
383
- onMouseLeave: (event)=>{
384
- childProps.onMouseLeave?.(event);
385
- if ('hover' === trigger) hide();
386
- },
387
- onFocus: (event)=>{
388
- childProps.onFocus?.(event);
389
- if ('hover' === trigger) show();
390
- },
391
- onBlur: (event)=>{
392
- childProps.onBlur?.(event);
393
- hide();
394
- },
395
- onClick: (event)=>{
396
- childProps.onClick?.(event);
397
- if ('click' === trigger) show();
398
- }
399
- });
400
- const surface = open ? /*#__PURE__*/ createPortal(/*#__PURE__*/ jsx("div", {
401
- ref: setSurfaceNode,
402
- id: id,
403
- role: 'hover' === trigger ? 'tooltip' : 'dialog',
404
- "aria-label": 'click' === trigger ? text.close : void 0,
405
- className: [
406
- 'ov-tooltip',
407
- className
408
- ].filter(Boolean).join(' '),
409
- "data-placement": position.placement,
410
- style: {
411
- top: position.top,
412
- left: position.left,
413
- ...style
414
- },
415
- onMouseEnter: 'hover' === trigger ? clearTimer : void 0,
416
- onMouseLeave: 'hover' === trigger ? hide : void 0,
417
- children: content
418
- }), document.body) : null;
419
- return /*#__PURE__*/ jsxs(jsx_runtime_Fragment, {
420
- children: [
421
- triggerElement,
422
- surface
423
- ]
424
- });
425
- }
426
- function FilePreviewBreadcrumbMenu({ segments, canOpen, disabled, onOpen }) {
427
- return /*#__PURE__*/ jsx(Tooltip, {
428
- trigger: "click",
429
- placement: "bottom",
430
- className: "ov-file-preview__breadcrumb-menu-surface",
431
- content: /*#__PURE__*/ jsx("ul", {
432
- className: "ov-file-preview__breadcrumb-menu",
433
- role: "menu",
434
- children: segments.map((segment)=>/*#__PURE__*/ jsx("li", {
435
- role: "none",
436
- children: /*#__PURE__*/ jsxs("button", {
437
- type: "button",
438
- role: "menuitem",
439
- disabled: !canOpen || disabled,
440
- onClick: ()=>onOpen(segment.uri),
441
- children: [
442
- segment.label,
443
- "/"
444
- ]
445
- })
446
- }, segment.uri))
447
- }),
448
- children: /*#__PURE__*/ jsx("button", {
449
- type: "button",
450
- className: "ov-file-preview__breadcrumb-more",
451
- "aria-label": "Show hidden path levels",
452
- "aria-haspopup": "menu",
453
- children: "…"
454
- })
455
- });
456
- }
457
- const MAX_ANCESTOR_WIDTH = 160;
458
- const OVERFLOW_BUTTON_WIDTH = 36;
459
- const SHIFT_DURATION = 160;
460
- function prefersReducedMotion() {
461
- return "u" > typeof window && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
462
- }
463
- function measureAvailable(root) {
464
- const row = root.parentElement;
465
- if (!row) return root.clientWidth;
466
- const style = window.getComputedStyle(row);
467
- const gap = Number.parseFloat(style.columnGap) || 0;
468
- const siblings = Array.from(row.children).filter((child)=>child !== root && child instanceof HTMLElement);
469
- const siblingWidth = siblings.reduce((sum, child)=>sum + child.getBoundingClientRect().width, 0);
470
- const siblingGaps = gap * siblings.length;
471
- return Math.max(0, row.clientWidth - siblingWidth - siblingGaps);
472
- }
473
- function FilePreviewBreadcrumb({ segments, title, canOpen, disabled, onOpen }) {
474
- const rootRef = useRef(null);
475
- const measureRef = useRef(null);
476
- const currentRef = useRef(null);
477
- const previousRef = useRef(void 0);
478
- const [hiddenCount, setHiddenCount] = useState(0);
479
- const [rootHidden, setRootHidden] = useState(false);
480
- const [overflowing, setOverflowing] = useState(false);
481
- const signature = JSON.stringify([
482
- segments.map((s)=>s.uri),
483
- title
484
- ]);
485
- useLayoutEffect(()=>{
486
- const root = rootRef.current;
487
- const measure = measureRef.current;
488
- if (!root || !measure) return;
489
- const run = ()=>{
490
- const widths = Array.from(measure.children).map((child)=>child.getBoundingClientRect().width);
491
- const available = measureAvailable(root);
492
- const isOverflowing = widths.reduce((sum, width)=>sum + width, 0) > available;
493
- const capped = isOverflowing ? widths.map((width, index)=>index < widths.length - 1 ? Math.min(width, MAX_ANCESTOR_WIDTH) : width) : widths;
494
- const ancestors = capped.slice(0, -1);
495
- const trailing = capped[capped.length - 1] ?? 0;
496
- const total = capped.reduce((sum, width)=>sum + width, 0);
497
- setOverflowing(isOverflowing);
498
- let count = 0;
499
- let used = total;
500
- while(used > available && count < ancestors.length - 1){
501
- used -= ancestors[count + 1] ?? 0;
502
- if (0 === count) used += OVERFLOW_BUTTON_WIDTH;
503
- count += 1;
504
- }
505
- let hideRoot = false;
506
- if (used > available && ancestors.length > 0) {
507
- const rootCollapsed = OVERFLOW_BUTTON_WIDTH + trailing;
508
- hideRoot = rootCollapsed < used;
509
- }
510
- setHiddenCount(hideRoot ? ancestors.length : count);
511
- setRootHidden(hideRoot);
512
- };
513
- run();
514
- const observer = new ResizeObserver(run);
515
- observer.observe(root);
516
- observer.observe(measure);
517
- if (root.parentElement) observer.observe(root.parentElement);
518
- return ()=>observer.disconnect();
519
- }, [
520
- segments,
521
- title
522
- ]);
523
- useLayoutEffect(()=>{
524
- const current = currentRef.current;
525
- const previous = previousRef.current;
526
- if (!current) return;
527
- const left = current.offsetLeft;
528
- previousRef.current = {
529
- signature,
530
- left
531
- };
532
- if (!previous || previous.signature !== signature || previous.left === left || prefersReducedMotion()) return;
533
- const animation = current.animate([
534
- {
535
- transform: `translateX(${previous.left - left}px)`,
536
- opacity: 0.65
537
- },
538
- {
539
- transform: 'translateX(0)',
540
- opacity: 1
541
- }
542
- ], {
543
- duration: SHIFT_DURATION,
544
- easing: 'cubic-bezier(0.2, 0, 0, 1)'
545
- });
546
- return ()=>animation.cancel();
547
- }, [
548
- hiddenCount,
549
- rootHidden,
550
- signature
551
- ]);
552
- const hiddenSegments = segments.filter((_, index)=>rootHidden ? index < hiddenCount : index > 0 && index <= hiddenCount);
553
- const menu = hiddenSegments.length ? /*#__PURE__*/ jsx(FilePreviewBreadcrumbMenu, {
554
- segments: hiddenSegments,
555
- canOpen: canOpen,
556
- disabled: disabled,
557
- onOpen: onOpen
558
- }) : null;
559
- return /*#__PURE__*/ jsxs("div", {
560
- className: [
561
- 'ov-file-preview__breadcrumb',
562
- overflowing ? 'ov-file-preview__breadcrumb--overflowing' : ''
563
- ].filter(Boolean).join(' '),
564
- ref: rootRef,
565
- children: [
566
- /*#__PURE__*/ jsxs("div", {
567
- className: "ov-file-preview__breadcrumb-measure",
568
- ref: measureRef,
569
- "aria-hidden": "true",
570
- children: [
571
- segments.map((segment)=>/*#__PURE__*/ jsxs("span", {
572
- className: "ov-file-preview__breadcrumb-part",
573
- children: [
574
- /*#__PURE__*/ jsx("span", {
575
- children: segment.isFirst ? `${segment.uri}` : segment.label
576
- }),
577
- /*#__PURE__*/ jsx("span", {
578
- className: "ov-file-preview__breadcrumb-separator",
579
- children: "/"
580
- })
581
- ]
582
- }, segment.uri)),
583
- /*#__PURE__*/ jsx("span", {
584
- children: title
585
- })
586
- ]
587
- }),
588
- rootHidden && menu ? /*#__PURE__*/ jsxs("span", {
589
- className: "ov-file-preview__breadcrumb-part",
590
- children: [
591
- menu,
592
- /*#__PURE__*/ jsx("span", {
593
- className: "ov-file-preview__breadcrumb-separator",
594
- children: "/"
595
- })
596
- ]
597
- }) : null,
598
- segments.map((segment, index)=>{
599
- if (hiddenSegments.includes(segment)) return null;
600
- return /*#__PURE__*/ jsxs(Fragment, {
601
- children: [
602
- /*#__PURE__*/ jsxs("span", {
603
- className: "ov-file-preview__breadcrumb-part",
604
- children: [
605
- /*#__PURE__*/ jsx("button", {
606
- type: "button",
607
- className: "ov-file-preview__breadcrumb-link",
608
- disabled: !canOpen || disabled,
609
- title: segment.uri,
610
- onClick: ()=>onOpen(segment.uri),
611
- children: segment.isFirst ? `${segment.uri}` : segment.label
612
- }),
613
- /*#__PURE__*/ jsx("span", {
614
- className: "ov-file-preview__breadcrumb-separator",
615
- children: "/"
616
- })
617
- ]
618
- }),
619
- 0 === index && !rootHidden && menu ? /*#__PURE__*/ jsxs("span", {
620
- className: "ov-file-preview__breadcrumb-part",
621
- children: [
622
- menu,
623
- /*#__PURE__*/ jsx("span", {
624
- className: "ov-file-preview__breadcrumb-separator",
625
- children: "/"
626
- })
627
- ]
628
- }) : null
629
- ]
630
- }, segment.uri);
631
- }),
632
- /*#__PURE__*/ jsx("span", {
633
- ref: currentRef,
634
- className: "ov-file-preview__breadcrumb-current",
635
- "aria-current": "page",
636
- title: title,
637
- children: title
638
- })
639
- ]
640
- });
641
- }
642
- function FilePreviewCopyPath({ label, disabled, onClick }) {
643
- return /*#__PURE__*/ jsx(Tooltip, {
644
- content: label,
645
- children: /*#__PURE__*/ jsx("button", {
646
- type: "button",
647
- className: "ov-file-preview__action",
648
- "aria-label": label,
649
- disabled: disabled,
650
- onClick: onClick,
651
- children: /*#__PURE__*/ jsx("svg", {
652
- width: "14",
653
- height: "14",
654
- viewBox: "0 0 14 14",
655
- fill: "none",
656
- stroke: "currentColor",
657
- strokeWidth: "1.2",
658
- strokeLinecap: "round",
659
- strokeLinejoin: "round",
660
- "aria-hidden": "true",
661
- children: /*#__PURE__*/ jsx("path", {
662
- d: "M4.667 4.667V3.033c0-.653 0-.98.127-1.229a1.167 1.167 0 0 1 .51-.51c.25-.127.576-.127 1.23-.127h4.433c.653 0 .98 0 1.229.127.22.112.398.29.51.51.127.25.127.576.127 1.23v4.433c0 .653 0 .98-.127 1.229a1.167 1.167 0 0 1-.51.51c-.25.127-.576.127-1.23.127H9.333M3.033 12.833h4.434c.653 0 .98 0 1.229-.127.22-.112.398-.29.51-.51.127-.25.127-.576.127-1.229V6.533c0-.653 0-.98-.127-1.229a1.167 1.167 0 0 0-.51-.51c-.25-.127-.576-.127-1.23-.127H3.034c-.653 0-.98 0-1.23.127a1.167 1.167 0 0 0-.51.51c-.126.25-.126.576-.126 1.23v4.433c0 .653 0 .98.127 1.229.112.22.29.398.51.51.25.127.576.127 1.23.127Z"
663
- })
664
- })
665
- })
666
- });
667
- }
668
- const SEPARATOR = '/';
669
- function splitPathSegments(path) {
670
- const trimmed = path?.trim();
671
- if (!trimmed) return [];
672
- const schemeIndex = trimmed.indexOf('://');
673
- const scheme = schemeIndex >= 0 ? trimmed.slice(0, schemeIndex + 3) : '';
674
- const body = schemeIndex >= 0 ? trimmed.slice(schemeIndex + 3) : trimmed;
675
- const parts = body.split(SEPARATOR).filter(Boolean);
676
- if (parts.length <= 1) return [];
677
- const root = '' === scheme && body.startsWith(SEPARATOR) ? SEPARATOR : '';
678
- const segments = [];
679
- let uri = scheme;
680
- parts.slice(0, -1).forEach((part, index)=>{
681
- uri = 0 === index ? `${scheme}${root}${part}` : `${uri}${SEPARATOR}${part}`;
682
- segments.push({
683
- label: part,
684
- uri,
685
- isFirst: 0 === index
686
- });
687
- });
688
- return segments;
689
- }
690
- function getPathFileName(path) {
691
- const trimmed = path?.trim();
692
- if (!trimmed) return;
693
- const parts = trimmed.split(SEPARATOR).filter(Boolean);
694
- return parts[parts.length - 1];
695
- }
696
- function FilePreviewHeader({ fileTab, actions, text, onOpenParent }) {
697
- const path = fileTab.source.path;
698
- const segments = splitPathSegments(path);
699
- const title = getPathFileName(path) ?? fileTab.source.fileName;
700
- const slotActions = fileTab.slots?.actions;
701
- const actionNode = 'function' == typeof slotActions ? slotActions(actions) : slotActions;
702
- return /*#__PURE__*/ jsxs("div", {
703
- className: "ov-file-preview__header",
704
- children: [
705
- /*#__PURE__*/ jsxs("div", {
706
- className: "ov-file-preview__path-row",
707
- children: [
708
- /*#__PURE__*/ jsx(FilePreviewBreadcrumb, {
709
- segments: segments,
710
- title: title,
711
- canOpen: Boolean(fileTab.operations?.openParent),
712
- disabled: actions.busy,
713
- onOpen: onOpenParent
714
- }),
715
- actions.canCopyPath ? /*#__PURE__*/ jsx(FilePreviewCopyPath, {
716
- label: text.copyPath,
717
- disabled: actions.busy,
718
- onClick: ()=>void actions.copyPath()
719
- }) : null,
720
- fileTab.slots?.titleExtra
721
- ]
722
- }),
723
- actionNode ? /*#__PURE__*/ jsx("div", {
724
- className: "ov-file-preview__header-actions",
725
- children: actionNode
726
- }) : null
727
- ]
728
- });
729
- }
730
- const file_preview_labels_DEFAULT_LABELS = {
731
- copyPath: 'Copy path',
732
- editor: 'Edit content',
733
- leaveEditing: 'Cancel',
734
- retry: 'Retry',
735
- loadFailed: 'Failed to load the file',
736
- saveFailed: 'Failed to save',
737
- unsupported: 'Preview is not supported for this format',
738
- loading: 'Loading…',
739
- download: 'Download',
740
- fileEmpty: 'This file is empty',
741
- noContent: 'No content to show',
742
- truncated: 'Only part of the content is shown'
743
- };
744
- const OUTLINE_RADIUS = 7;
745
- const STROKE_INSET = 0.5;
746
- function buildOutline(width, top, bottom, left, right) {
747
- const radius = OUTLINE_RADIUS;
748
- if (right - left < 2 * radius + 1) return `M0 ${bottom} H${width}`;
749
- const lead = left > radius ? [
750
- `M0 ${bottom}`,
751
- `H${left - radius}`
752
- ] : [
753
- `M${left} ${bottom}`
754
- ];
755
- return [
756
- ...lead,
757
- `Q${left} ${bottom} ${left} ${bottom - radius}`,
758
- `V${top + radius}`,
759
- `Q${left} ${top} ${left + radius} ${top}`,
760
- `H${right - radius}`,
761
- `Q${right} ${top} ${right} ${top + radius}`,
762
- `V${bottom - radius}`,
763
- `Q${right} ${bottom} ${right + radius} ${bottom}`,
764
- `H${width}`
765
- ].join(' ');
766
- }
767
- function FilePreviewTabRow({ tabs, activeKey, disabled, tabId, panelId, onSelect }) {
768
- const trackRef = useRef(null);
769
- const [outline, setOutline] = useState('');
770
- useLayoutEffect(()=>{
771
- const track = trackRef.current;
772
- if (!track) return;
773
- const measure = ()=>{
774
- const trackRect = track.getBoundingClientRect();
775
- const bottom = trackRect.height - STROKE_INSET;
776
- const active = track.querySelector('[aria-selected="true"]');
777
- if (!active) return void setOutline(`M0 ${bottom} H${trackRect.width}`);
778
- const rect = active.getBoundingClientRect();
779
- setOutline(buildOutline(trackRect.width, rect.top - trackRect.top + STROKE_INSET, rect.bottom - trackRect.top - STROKE_INSET, rect.left - trackRect.left, rect.right - trackRect.left));
780
- };
781
- measure();
782
- const observer = new ResizeObserver(measure);
783
- observer.observe(track);
784
- return ()=>observer.disconnect();
785
- }, [
786
- activeKey,
787
- tabs
788
- ]);
789
- const onKeyDown = (event)=>{
790
- const keys = [
791
- 'ArrowLeft',
792
- 'ArrowRight',
793
- 'Home',
794
- 'End'
795
- ];
796
- if (!keys.includes(event.key)) return;
797
- const buttons = Array.from(event.currentTarget.querySelectorAll('[role="tab"]:not(:disabled)'));
798
- if (0 === buttons.length) return;
799
- const current = buttons.indexOf(event.target);
800
- const next = 'Home' === event.key ? 0 : 'End' === event.key ? buttons.length - 1 : (current + ('ArrowRight' === event.key ? 1 : -1) + buttons.length) % buttons.length;
801
- const target = buttons[next];
802
- if (!target) return;
803
- event.preventDefault();
804
- target.focus();
805
- onSelect(target.dataset.key ?? '');
806
- };
807
- return /*#__PURE__*/ jsx("div", {
808
- className: "ov-file-preview__tab-row",
809
- children: /*#__PURE__*/ jsxs("div", {
810
- role: "tablist",
811
- className: "ov-file-preview__tab-track",
812
- ref: trackRef,
813
- tabIndex: -1,
814
- onKeyDown: onKeyDown,
815
- children: [
816
- tabs.map((tab)=>{
817
- const selected = tab.key === activeKey;
818
- return /*#__PURE__*/ jsxs("button", {
819
- type: "button",
820
- role: "tab",
821
- "data-key": tab.key,
822
- id: tabId(tab.key),
823
- "aria-selected": selected,
824
- "aria-controls": panelId(tab.key),
825
- tabIndex: selected ? 0 : -1,
826
- disabled: tab.disabled || disabled,
827
- title: 'string' == typeof tab.title ? tab.title : void 0,
828
- className: [
829
- 'ov-file-preview__tab',
830
- selected ? 'ov-file-preview__tab--active' : ''
831
- ].filter(Boolean).join(' '),
832
- onClick: ()=>onSelect(tab.key),
833
- children: [
834
- tab.icon ? /*#__PURE__*/ jsx("span", {
835
- className: "ov-file-preview__tab-icon",
836
- "aria-hidden": "true",
837
- children: tab.icon
838
- }) : null,
839
- /*#__PURE__*/ jsx("span", {
840
- className: "ov-file-preview__tab-title",
841
- children: tab.title ?? ('file' === tab.kind ? tab.source.fileName : tab.key)
842
- })
843
- ]
844
- }, tab.key);
845
- }),
846
- /*#__PURE__*/ jsx("svg", {
847
- className: "ov-file-preview__tab-outline",
848
- "aria-hidden": "true",
849
- children: /*#__PURE__*/ jsx("path", {
850
- d: outline
851
- })
852
- })
853
- ]
854
- })
855
- });
856
- }
857
- async function copyText(value, notify) {
858
- try {
859
- await navigator.clipboard.writeText(value);
860
- } catch {
861
- return false;
862
- }
863
- notify?.(value);
864
- return true;
865
- }
866
- function useFilePreviewActions() {
867
- const pending = useRef(new Set());
868
- async function run(key, { execute, notify }, value) {
869
- if (!execute || pending.current.has(key)) return;
870
- pending.current.add(key);
871
- try {
872
- await execute(value);
873
- } catch {
874
- return;
875
- } finally{
876
- pending.current.delete(key);
877
- }
878
- notify?.(value);
879
- }
880
- return {
881
- openParent: (tab, uri)=>'file' === tab.kind ? run(`openParent:${tab.key}`, {
882
- execute: tab.operations?.openParent,
883
- notify: tab.onOpenParent
884
- }, uri) : Promise.resolve(),
885
- download: (tab)=>run(`download:${tab.key}`, {
886
- execute: tab.operations?.download,
887
- notify: tab.onDownload
888
- }, void 0),
889
- openUri: (tab, uri)=>run(`openUri:${tab.key}`, {
890
- execute: tab.operations?.openUri,
891
- notify: tab.onOpenUri
892
- }, uri),
893
- copyPath: (tab, path)=>copyText(path, tab.onCopyPath),
894
- copyContent: (tab, text)=>copyText(text, tab.onCopyContent)
895
- };
896
- }
897
- function useFilePreviewActionsContext({ activeTab, fileTab, viewMode, canSwitchView, setViewMode, editing, operations }) {
898
- const startEditing = useCallback(()=>{
899
- if (!fileTab) return;
900
- setViewMode('source');
901
- editing.start(fileTab);
902
- }, [
903
- editing,
904
- fileTab,
905
- setViewMode
906
- ]);
907
- const saveEditing = useCallback(async ()=>{
908
- if (!fileTab) return false;
909
- const saved = await editing.save(fileTab);
910
- if (saved) setViewMode('preview');
911
- return saved;
912
- }, [
913
- editing,
914
- fileTab,
915
- setViewMode
916
- ]);
917
- const cancelEditing = useCallback(()=>{
918
- editing.discard(activeTab);
919
- setViewMode('preview');
920
- }, [
921
- activeTab,
922
- editing,
923
- setViewMode
924
- ]);
925
- const copyContent = useCallback(async ()=>{
926
- const copyable = fileTab && readCopyableText(fileTab.source);
927
- if (!fileTab || !copyable) return false;
928
- return operations.copyContent(fileTab, copyable);
929
- }, [
930
- fileTab,
931
- operations
932
- ]);
933
- const copyPath = useCallback(async ()=>{
934
- const path = fileTab?.source.path;
935
- if (!path) return false;
936
- return operations.copyPath(activeTab, path);
937
- }, [
938
- activeTab,
939
- fileTab,
940
- operations
941
- ]);
942
- const download = useCallback(()=>{
943
- if (fileTab) operations.download(fileTab);
944
- }, [
945
- fileTab,
946
- operations
947
- ]);
948
- return {
949
- viewMode,
950
- setViewMode,
951
- canSwitchView,
952
- editing: editing.editing,
953
- busy: editing.saving || editing.loadingEdit,
954
- canEdit: Boolean(fileTab?.editing) && !editing.editing,
955
- startEditing,
956
- saveEditing,
957
- cancelEditing,
958
- canCopyContent: Boolean(fileTab && readCopyableText(fileTab.source)),
959
- copyContent,
960
- canCopyPath: Boolean(fileTab?.source.path),
961
- copyPath,
962
- canDownload: Boolean(fileTab?.operations?.download),
963
- download
964
- };
965
- }
966
- function useFilePreviewIds(activeKey) {
967
- const instanceId = useId();
968
- const tabId = (key)=>`${instanceId}-tab-${key}`;
969
- const panelId = (key)=>`${instanceId}-panel-${key}`;
970
- return {
971
- tabId,
972
- panelId,
973
- panelProps: {
974
- id: panelId(activeKey),
975
- role: 'tabpanel',
976
- 'aria-labelledby': tabId(activeKey)
977
- }
978
- };
979
- }
980
- function useFilePreviewEditing(activeTabKey) {
981
- const [editing, setEditing] = useState(false);
982
- const [loadingEdit, setLoadingEdit] = useState(false);
983
- const [editFailed, setEditFailed] = useState(false);
984
- const [saving, setSaving] = useState(false);
985
- const [saveFailed, setSaveFailed] = useState(false);
986
- const [draft, setDraft] = useState('');
987
- const requestId = useRef(0);
988
- const loading = useRef(false);
989
- const pendingSave = useRef(false);
990
- const lastKey = useRef(activeTabKey);
991
- if (lastKey.current !== activeTabKey) {
992
- lastKey.current = activeTabKey;
993
- requestId.current += 1;
994
- loading.current = false;
995
- if (editing) setEditing(false);
996
- if (loadingEdit) setLoadingEdit(false);
997
- if (editFailed) setEditFailed(false);
998
- if (saveFailed) setSaveFailed(false);
999
- if (draft) setDraft('');
1000
- }
1001
- function discard(tab) {
1002
- requestId.current += 1;
1003
- loading.current = false;
1004
- const wasEditing = editing;
1005
- const discarded = draft;
1006
- setEditing(false);
1007
- setLoadingEdit(false);
1008
- setEditFailed(false);
1009
- setSaveFailed(false);
1010
- setDraft('');
1011
- if (wasEditing && 'file' === tab.kind) tab.editing?.onCancel?.(discarded);
1012
- }
1013
- async function start(tab) {
1014
- if (loading.current || pendingSave.current) return;
1015
- const id = ++requestId.current;
1016
- loading.current = true;
1017
- setLoadingEdit(true);
1018
- setEditFailed(false);
1019
- setSaveFailed(false);
1020
- let content;
1021
- try {
1022
- content = tab.editing?.loadContent ? await tab.editing.loadContent(tab.source) : tab.source.content ?? await tab.source.file?.text();
1023
- } catch {
1024
- if (id === requestId.current) setEditFailed(true);
1025
- }
1026
- if (id !== requestId.current) return;
1027
- loading.current = false;
1028
- setLoadingEdit(false);
1029
- if (void 0 !== content) {
1030
- setDraft(content);
1031
- setEditing(true);
1032
- }
1033
- }
1034
- async function save(tab) {
1035
- if (!editing || !tab.editing || pendingSave.current) return false;
1036
- pendingSave.current = true;
1037
- setSaving(true);
1038
- setSaveFailed(false);
1039
- const value = draft;
1040
- try {
1041
- await tab.editing.save(value);
1042
- } catch {
1043
- setSaveFailed(true);
1044
- return false;
1045
- } finally{
1046
- pendingSave.current = false;
1047
- setSaving(false);
1048
- }
1049
- setEditing(false);
1050
- setDraft('');
1051
- tab.editing.onSave?.(value);
1052
- return true;
1053
- }
1054
- return {
1055
- editing,
1056
- loadingEdit,
1057
- editFailed,
1058
- saving,
1059
- saveFailed,
1060
- draft,
1061
- discard,
1062
- start,
1063
- save,
1064
- updateDraft: (value)=>{
1065
- setDraft(value);
1066
- setSaveFailed(false);
1067
- }
1068
- };
1069
- }
1070
- function isFileTab(tab) {
1071
- return 'file' === tab.kind;
1072
- }
1073
- const file_preview_FilePreview = /*#__PURE__*/ forwardRef(function({ tabs, activeKey, defaultActiveKey, locale, labels, onActiveKeyChange, className, ...rest }, ref) {
1074
- const text = {
1075
- ...file_preview_labels_DEFAULT_LABELS,
1076
- ...labels
1077
- };
1078
- const [internalKey, setInternalKey] = useState(()=>defaultActiveKey ?? tabs[0].key);
1079
- const [viewMode, setViewMode] = useState('preview');
1080
- const [viewModes, setViewModes] = useState([]);
1081
- const viewerHandle = useRef(null);
1082
- const panelClass = 'ov-file-preview__panel';
1083
- const currentKey = activeKey ?? internalKey;
1084
- const activeTab = tabs.find((tab)=>tab.key === currentKey) ?? tabs[0];
1085
- const { tabId, panelId, panelProps } = useFilePreviewIds(activeTab.key);
1086
- const editing = useFilePreviewEditing(activeTab.key);
1087
- const actions = useFilePreviewActions();
1088
- const tabText = {
1089
- ...text,
1090
- ...activeTab.labels
1091
- };
1092
- const fileTab = isFileTab(activeTab) ? activeTab : void 0;
1093
- const contentTab = fileTab ? void 0 : activeTab;
1094
- const switchTab = useCallback((key)=>{
1095
- if (editing.saving) return false;
1096
- if (key === currentKey && key === activeTab.key) return false;
1097
- const target = tabs.find((tab)=>tab.key === key);
1098
- if (!target || target.disabled) return false;
1099
- const syncingOnly = target.key === activeTab.key;
1100
- if (!syncingOnly) {
1101
- editing.discard(activeTab);
1102
- setViewMode('preview');
1103
- setViewModes([]);
1104
- viewerHandle.current = null;
1105
- }
1106
- if (void 0 === activeKey) setInternalKey(key);
1107
- onActiveKeyChange?.(key);
1108
- return true;
1109
- }, [
1110
- activeKey,
1111
- activeTab,
1112
- currentKey,
1113
- editing,
1114
- onActiveKeyChange,
1115
- tabs
1116
- ]);
1117
- const onHandleChange = useCallback((handle)=>{
1118
- viewerHandle.current = handle;
1119
- }, []);
1120
- const onViewModesChange = useCallback((modes)=>{
1121
- const next = modes.map((mode)=>mode.value);
1122
- setViewModes((previous)=>previous.join() === next.join() ? previous : next);
1123
- }, []);
1124
- useImperativeHandle(ref, ()=>({
1125
- setActiveTab: switchTab,
1126
- getActiveTab: ()=>activeTab.key,
1127
- getViewerHandle: ()=>fileTab ? viewerHandle.current : null
1128
- }), [
1129
- activeTab.key,
1130
- fileTab,
1131
- switchTab
1132
- ]);
1133
- const canSwitchView = Boolean(fileTab) && viewModes.includes('preview') && viewModes.includes('source');
1134
- const onLinkClick = useCallback((_event, link)=>{
1135
- if (fileTab) actions.openUri(fileTab, link.url);
1136
- }, [
1137
- actions,
1138
- fileTab
1139
- ]);
1140
- const linkClickHandler = fileTab?.operations?.openUri ? onLinkClick : void 0;
1141
- const actionContext = useFilePreviewActionsContext({
1142
- activeTab,
1143
- fileTab,
1144
- viewMode,
1145
- canSwitchView,
1146
- setViewMode,
1147
- editing,
1148
- operations: actions
1149
- });
1150
- return /*#__PURE__*/ jsxs("div", {
1151
- ...rest,
1152
- className: [
1153
- 'ov-file-preview',
1154
- className
1155
- ].filter(Boolean).join(' '),
1156
- children: [
1157
- /*#__PURE__*/ jsx(FilePreviewTabRow, {
1158
- tabs: tabs,
1159
- activeKey: activeTab.key,
1160
- disabled: editing.saving,
1161
- tabId: tabId,
1162
- panelId: panelId,
1163
- onSelect: (key)=>void switchTab(key)
1164
- }),
1165
- contentTab ? /*#__PURE__*/ jsx("div", {
1166
- ...panelProps,
1167
- className: `${panelClass} ${panelClass}--content`,
1168
- children: contentTab.content
1169
- }) : fileTab ? /*#__PURE__*/ jsxs("div", {
1170
- ...panelProps,
1171
- className: panelClass,
1172
- children: [
1173
- /*#__PURE__*/ jsx(FilePreviewHeader, {
1174
- fileTab: fileTab,
1175
- actions: actionContext,
1176
- text: tabText,
1177
- onOpenParent: (uri)=>void actions.openParent(activeTab, uri)
1178
- }),
1179
- /*#__PURE__*/ jsx("div", {
1180
- className: "ov-file-preview__body",
1181
- children: /*#__PURE__*/ jsx(FilePreviewBody, {
1182
- fileTab: fileTab,
1183
- text: tabText,
1184
- locale: locale,
1185
- viewMode: viewMode,
1186
- editing: editing,
1187
- onViewModeChange: setViewMode,
1188
- onHandleChange: onHandleChange,
1189
- onViewModesChange: onViewModesChange,
1190
- onDownload: ()=>void actions.download(fileTab),
1191
- onLinkClick: linkClickHandler,
1192
- onCancelEditing: actionContext.cancelEditing
1193
- })
1194
- }),
1195
- fileTab.source.truncated ? /*#__PURE__*/ jsx(TruncatedNotice, {
1196
- text: tabText
1197
- }) : null,
1198
- fileTab.slots?.footer ? /*#__PURE__*/ jsx("div", {
1199
- className: "ov-file-preview__footer",
1200
- children: fileTab.slots.footer
1201
- }) : null
1202
- ]
1203
- }) : null
1204
- ]
1205
- });
1206
- });
1207
- export { LoadFailedState, LoadingState, UnsupportedState, file_preview_FilePreview as FilePreview, toFileSource };