@openviking/react 0.1.2 → 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.
- package/dist/1~0.js +506 -0
- package/dist/2~0.js +122 -0
- package/dist/{g~0.js → 30~0.js} +292 -167
- package/dist/client/index.d.ts +2 -1
- package/dist/client/paths.d.ts +64 -0
- package/dist/client/response.d.ts +31 -0
- package/dist/client/sse.d.ts +39 -0
- package/dist/client/stream.d.ts +26 -0
- package/dist/client/types.d.ts +104 -0
- package/dist/client.js +1 -239
- package/dist/components/agent-connect/style.css +2 -2
- package/dist/components/file-browser-entries/file-browser-entries-icons.d.ts +18 -0
- package/dist/components/file-browser-entries/file-browser-entries.d.ts +14 -0
- package/dist/components/file-browser-entries/index.d.ts +1 -0
- package/dist/components/file-browser-entries/style.css +155 -0
- package/dist/components/file-browser-entries/style.js +0 -0
- package/dist/components/file-browser-entries/types.d.ts +45 -0
- package/dist/components/file-browser-entries.js +1 -0
- package/dist/components/file-preview/file-preview-directory.d.ts +32 -0
- package/dist/components/file-preview/file-preview-header.d.ts +21 -3
- package/dist/components/file-preview/file-preview-panels.d.ts +41 -0
- package/dist/components/file-preview/file-preview-state.d.ts +10 -3
- package/dist/components/file-preview/file-preview.d.ts +2 -1
- package/dist/components/file-preview/level-selection.d.ts +25 -0
- package/dist/components/file-preview/style.css +76 -3
- package/dist/components/file-preview/types.d.ts +100 -1
- package/dist/components/file-preview/use-directory-level.d.ts +30 -0
- package/dist/components/file-preview/use-file-preview-actions-context.d.ts +6 -2
- package/dist/components/file-preview/use-file-preview-actions.d.ts +1 -1
- package/dist/components/file-preview.js +1 -1
- package/dist/components/file-tree/file-tree-info-tooltip.d.ts +7 -7
- package/dist/components/file-tree/file-tree-row-context.d.ts +0 -5
- package/dist/components/file-tree/file-tree-row-shared.d.ts +9 -2
- package/dist/components/file-tree/file-tree-tooltip-surface.d.ts +8 -8
- package/dist/components/file-tree/style.css +71 -34
- package/dist/components/file-tree/types.d.ts +20 -0
- package/dist/components/scope-switcher/style.css +2 -2
- package/dist/components/style.css +312 -47
- package/dist/components/tui/style.css +2 -2
- package/dist/components/viking-bot/style.css +2 -2
- package/dist/file-preview-viewer~0.js +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/l~0.js +1464 -25
- package/dist/modules/console/style.css +2 -2
- package/dist/modules/file-browser/file-browser-detail-icons.d.ts +10 -0
- package/dist/modules/file-browser/file-browser-detail.d.ts +33 -0
- package/dist/modules/file-browser/file-browser-empty.d.ts +3 -0
- package/dist/modules/file-browser/file-browser-failure.d.ts +22 -0
- package/dist/modules/file-browser/file-browser-icons.d.ts +18 -0
- package/dist/modules/file-browser/file-browser-labels.d.ts +28 -0
- package/dist/modules/file-browser/file-browser-layout.d.ts +27 -0
- package/dist/modules/file-browser/file-browser-toolbar.d.ts +18 -0
- package/dist/modules/file-browser/file-browser-tree-pane.d.ts +30 -0
- package/dist/modules/file-browser/file-browser.d.ts +14 -5
- package/dist/modules/file-browser/find-result.d.ts +24 -0
- package/dist/modules/file-browser/fs-directories.d.ts +33 -0
- package/dist/modules/file-browser/fs-file-kind.d.ts +19 -0
- package/dist/modules/file-browser/fs-icon.d.ts +17 -0
- package/dist/modules/file-browser/fs-model.d.ts +106 -0
- package/dist/modules/file-browser/fs-page.d.ts +16 -0
- package/dist/modules/file-browser/fs-path.d.ts +16 -0
- package/dist/modules/file-browser/fs-read-directory.d.ts +20 -0
- package/dist/modules/file-browser/fs-scope.d.ts +22 -0
- package/dist/modules/file-browser/fs-stat.d.ts +25 -0
- package/dist/modules/file-browser/index.d.ts +3 -1
- package/dist/modules/file-browser/style.css +4927 -35
- package/dist/modules/file-browser/tree-info-copy.d.ts +15 -0
- package/dist/modules/file-browser/tree-info-copy.zh-CN.d.ts +15 -0
- package/dist/modules/file-browser/types.d.ts +189 -44
- package/dist/modules/file-browser/use-container-width.d.ts +17 -0
- package/dist/modules/file-browser/use-file-browser.d.ts +49 -0
- package/dist/modules/file-browser/use-fs-preview.d.ts +51 -0
- package/dist/modules/file-browser/use-fs-search.d.ts +35 -0
- package/dist/modules/file-browser/use-fs-tree.d.ts +43 -0
- package/dist/modules/file-browser/use-request-scope.d.ts +39 -0
- package/dist/modules/file-browser.js +1 -1
- package/dist/modules/scope-cascade/style.css +2 -2
- package/dist/modules/style.css +4933 -41
- package/dist/n~0.js +178 -74
- package/dist/o~0.js +103 -0
- package/dist/shared/components/divider/divider.d.ts +18 -0
- package/dist/shared/components/divider/index.d.ts +1 -0
- package/dist/shared/components/divider/types.d.ts +35 -0
- package/dist/shared/components/overlay/types.d.ts +7 -0
- package/dist/shared/components/{tooltip/use-tooltip-position.d.ts → overlay/use-overlay-position.d.ts} +6 -6
- package/dist/shared/components/popover/index.d.ts +1 -0
- package/dist/shared/components/popover/popover.d.ts +23 -0
- package/dist/shared/components/popover/types.d.ts +50 -0
- package/dist/shared/components/resizable/clamp.d.ts +13 -0
- package/dist/shared/components/resizable/index.d.ts +2 -0
- package/dist/shared/components/resizable/resizable-handle.d.ts +25 -0
- package/dist/shared/components/resizable/types.d.ts +48 -0
- package/dist/shared/components/tooltip/types.d.ts +5 -5
- package/dist/style.css +5345 -188
- package/package.json +6 -1
- package/dist/components/file-tree/file-tree-tooltip.d.ts +0 -17
- package/dist/modules/file-browser/file-browser-toolbar-button.d.ts +0 -10
package/dist/n~0.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
|
|
2
|
+
import { cloneElement, forwardRef, useCallback, useEffect, useId, useImperativeHandle, useRef, useState } from "react";
|
|
3
|
+
import { createPortal } from "react-dom";
|
|
3
4
|
import { FolderOpenIcon, FolderIcon, ChevronRightIcon, DocumentIcon } from "./k~0.js";
|
|
5
|
+
import { useOverlayPosition } from "./o~0.js";
|
|
4
6
|
function FileTreeFolderIcon({ open }) {
|
|
5
7
|
return /*#__PURE__*/ jsxs("span", {
|
|
6
8
|
className: "ov-file-tree__folder",
|
|
@@ -59,6 +61,12 @@ const USER_SCOPE_KEY_BY_SEGMENT = {
|
|
|
59
61
|
sessions: 'sessions',
|
|
60
62
|
skills: 'skills'
|
|
61
63
|
};
|
|
64
|
+
const AGENT_KEY_BY_SEGMENT = {
|
|
65
|
+
endpoints: 'agentEndpoints',
|
|
66
|
+
payments: 'agentPayments',
|
|
67
|
+
skills: 'agentSkills',
|
|
68
|
+
tools: 'agentTools'
|
|
69
|
+
};
|
|
62
70
|
const MEMORY_KEY_BY_SEGMENT = {
|
|
63
71
|
'profile.md': 'profile',
|
|
64
72
|
preferences: 'preferences',
|
|
@@ -96,6 +104,10 @@ function resolveFileTreeInfoKey(uri) {
|
|
|
96
104
|
if ('resources' === first) return 'sharedResources';
|
|
97
105
|
return ROOT_KEY_BY_SEGMENT[first] ?? null;
|
|
98
106
|
}
|
|
107
|
+
if (('agent' === first || 'agents' === first) && 2 === segments.length) {
|
|
108
|
+
const second = segments[1];
|
|
109
|
+
return second ? AGENT_KEY_BY_SEGMENT[second] ?? null : null;
|
|
110
|
+
}
|
|
99
111
|
return null;
|
|
100
112
|
}
|
|
101
113
|
function showsInlineDescription(key) {
|
|
@@ -120,6 +132,10 @@ const DESCRIPTION = {
|
|
|
120
132
|
experiences: 'Execution experience distilled automatically',
|
|
121
133
|
sharedResources: 'External resources the agent can reference',
|
|
122
134
|
agentRoot: 'Agent capabilities, tools and experience',
|
|
135
|
+
agentEndpoints: 'Communication endpoints shared across the account',
|
|
136
|
+
agentPayments: 'Payment capabilities shared across the account',
|
|
137
|
+
agentSkills: 'Skill definitions callable across the account',
|
|
138
|
+
agentTools: 'Tool configuration shared across the account',
|
|
123
139
|
memoryRoot: 'Long-term memory and accumulated information',
|
|
124
140
|
resourceRoot: 'External knowledge the agent can reference',
|
|
125
141
|
sessionRoot: 'Raw session records of the user',
|
|
@@ -141,7 +157,11 @@ const TRIGGER_BEHAVIOR = {
|
|
|
141
157
|
cases: 'A session with a clear task and an evaluable execution result is committed',
|
|
142
158
|
trajectories: 'A task containing decisions, tool calls or multi-step execution is committed',
|
|
143
159
|
experiences: 'Distilled from task cases and execution trajectories',
|
|
144
|
-
sharedResources: 'Imported material, uploaded to a shared resource space'
|
|
160
|
+
sharedResources: 'Imported material, uploaded to a shared resource space',
|
|
161
|
+
agentEndpoints: 'Configured when an integration endpoint is registered for the account',
|
|
162
|
+
agentPayments: 'Configured when a payment capability is enabled for the account',
|
|
163
|
+
agentSkills: 'Installed or imported as a shared skill available to every agent',
|
|
164
|
+
agentTools: 'Configured when a tool is registered for the account'
|
|
145
165
|
};
|
|
146
166
|
const DEFAULT_INFO_LABELS = {
|
|
147
167
|
description: DESCRIPTION,
|
|
@@ -160,6 +180,131 @@ function resolveInfoCopy(key, hostLabels) {
|
|
|
160
180
|
triggerBehavior: triggerBehavior || void 0
|
|
161
181
|
};
|
|
162
182
|
}
|
|
183
|
+
function useMergedRef(ref, target) {
|
|
184
|
+
return useCallback((node)=>{
|
|
185
|
+
target.current = node;
|
|
186
|
+
if ('function' == typeof ref) ref(node);
|
|
187
|
+
else if (ref) ref.current = node;
|
|
188
|
+
}, [
|
|
189
|
+
ref,
|
|
190
|
+
target
|
|
191
|
+
]);
|
|
192
|
+
}
|
|
193
|
+
function Popover({ children, content, placement = 'right', trigger = 'hover', delay = 300, disabled = false, className, style, onOpenChange }) {
|
|
194
|
+
const [open, setOpen] = useState(false);
|
|
195
|
+
const triggerRef = useRef(null);
|
|
196
|
+
const timerRef = useRef(void 0);
|
|
197
|
+
const [surfaceNode, setSurfaceNode] = useState(null);
|
|
198
|
+
const id = useId();
|
|
199
|
+
const position = useOverlayPosition(open, triggerRef, surfaceNode, placement);
|
|
200
|
+
const change = useCallback((next)=>{
|
|
201
|
+
setOpen(next);
|
|
202
|
+
onOpenChange?.(next);
|
|
203
|
+
}, [
|
|
204
|
+
onOpenChange
|
|
205
|
+
]);
|
|
206
|
+
const clearTimer = useCallback(()=>{
|
|
207
|
+
if (void 0 !== timerRef.current) {
|
|
208
|
+
window.clearTimeout(timerRef.current);
|
|
209
|
+
timerRef.current = void 0;
|
|
210
|
+
}
|
|
211
|
+
}, []);
|
|
212
|
+
useEffect(()=>clearTimer, [
|
|
213
|
+
clearTimer
|
|
214
|
+
]);
|
|
215
|
+
useEffect(()=>{
|
|
216
|
+
if (disabled) {
|
|
217
|
+
clearTimer();
|
|
218
|
+
setOpen(false);
|
|
219
|
+
}
|
|
220
|
+
}, [
|
|
221
|
+
disabled,
|
|
222
|
+
clearTimer
|
|
223
|
+
]);
|
|
224
|
+
useEffect(()=>{
|
|
225
|
+
if (!open || 'click' !== trigger) return;
|
|
226
|
+
const onPointerDown = (event)=>{
|
|
227
|
+
const target = event.target;
|
|
228
|
+
if (surfaceNode?.contains(target) || triggerRef.current?.contains(target)) return;
|
|
229
|
+
change(false);
|
|
230
|
+
};
|
|
231
|
+
const onKeyDown = (event)=>{
|
|
232
|
+
if ('Escape' === event.key) change(false);
|
|
233
|
+
};
|
|
234
|
+
document.addEventListener('mousedown', onPointerDown);
|
|
235
|
+
document.addEventListener('keydown', onKeyDown);
|
|
236
|
+
return ()=>{
|
|
237
|
+
document.removeEventListener('mousedown', onPointerDown);
|
|
238
|
+
document.removeEventListener('keydown', onKeyDown);
|
|
239
|
+
};
|
|
240
|
+
}, [
|
|
241
|
+
change,
|
|
242
|
+
open,
|
|
243
|
+
surfaceNode,
|
|
244
|
+
trigger
|
|
245
|
+
]);
|
|
246
|
+
const show = ()=>{
|
|
247
|
+
if (disabled) return;
|
|
248
|
+
if ('click' === trigger) return void change(!open);
|
|
249
|
+
clearTimer();
|
|
250
|
+
timerRef.current = window.setTimeout(()=>{
|
|
251
|
+
change(true);
|
|
252
|
+
timerRef.current = void 0;
|
|
253
|
+
}, delay);
|
|
254
|
+
};
|
|
255
|
+
const hide = ()=>{
|
|
256
|
+
if ('click' === trigger) return;
|
|
257
|
+
clearTimer();
|
|
258
|
+
change(false);
|
|
259
|
+
};
|
|
260
|
+
const child = children;
|
|
261
|
+
const childProps = child.props;
|
|
262
|
+
const childRef = child.ref;
|
|
263
|
+
const mergedRef = useMergedRef(childRef, triggerRef);
|
|
264
|
+
const declaresExpanded = 'aria-expanded' in childProps;
|
|
265
|
+
const triggerElement = /*#__PURE__*/ cloneElement(child, {
|
|
266
|
+
ref: mergedRef,
|
|
267
|
+
...declaresExpanded ? {} : {
|
|
268
|
+
'aria-expanded': open
|
|
269
|
+
},
|
|
270
|
+
onMouseEnter: (event)=>{
|
|
271
|
+
childProps.onMouseEnter?.(event);
|
|
272
|
+
if ('hover' === trigger) show();
|
|
273
|
+
},
|
|
274
|
+
onMouseLeave: (event)=>{
|
|
275
|
+
childProps.onMouseLeave?.(event);
|
|
276
|
+
if ('hover' === trigger) hide();
|
|
277
|
+
},
|
|
278
|
+
onClick: (event)=>{
|
|
279
|
+
childProps.onClick?.(event);
|
|
280
|
+
if ('click' === trigger) show();
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
const surface = open ? /*#__PURE__*/ createPortal(/*#__PURE__*/ jsx("div", {
|
|
284
|
+
ref: setSurfaceNode,
|
|
285
|
+
id: id,
|
|
286
|
+
role: 'click' === trigger ? 'dialog' : 'note',
|
|
287
|
+
className: [
|
|
288
|
+
'ov-popover',
|
|
289
|
+
className
|
|
290
|
+
].filter(Boolean).join(' '),
|
|
291
|
+
"data-placement": position.placement,
|
|
292
|
+
style: {
|
|
293
|
+
top: position.top,
|
|
294
|
+
left: position.left,
|
|
295
|
+
...style
|
|
296
|
+
},
|
|
297
|
+
onMouseEnter: 'hover' === trigger ? clearTimer : void 0,
|
|
298
|
+
onMouseLeave: 'hover' === trigger ? hide : void 0,
|
|
299
|
+
children: content
|
|
300
|
+
}), document.body) : null;
|
|
301
|
+
return /*#__PURE__*/ jsxs(Fragment, {
|
|
302
|
+
children: [
|
|
303
|
+
triggerElement,
|
|
304
|
+
surface
|
|
305
|
+
]
|
|
306
|
+
});
|
|
307
|
+
}
|
|
163
308
|
const DEFAULT_FIELDS = {
|
|
164
309
|
description: "Description",
|
|
165
310
|
triggerBehavior: 'Trigger',
|
|
@@ -167,7 +312,8 @@ const DEFAULT_FIELDS = {
|
|
|
167
312
|
};
|
|
168
313
|
function resolveFileTreeInfoCopy(row, infoLabels) {
|
|
169
314
|
const key = resolveFileTreeInfoKey(row.uri);
|
|
170
|
-
|
|
315
|
+
if (!key) return null;
|
|
316
|
+
const builtIn = resolveInfoCopy(key, infoLabels);
|
|
171
317
|
const description = row.description ?? builtIn.description;
|
|
172
318
|
if (!description && !builtIn.triggerBehavior) return null;
|
|
173
319
|
return {
|
|
@@ -183,14 +329,14 @@ function resolveFileTreeInfoCopy(row, infoLabels) {
|
|
|
183
329
|
}
|
|
184
330
|
function FileTreeInfoTooltip({ copy }) {
|
|
185
331
|
const { description, fields, path, title, triggerBehavior } = copy;
|
|
186
|
-
return /*#__PURE__*/ jsxs("
|
|
332
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
187
333
|
className: "ov-file-tree__info",
|
|
188
334
|
children: [
|
|
189
|
-
/*#__PURE__*/ jsx("
|
|
335
|
+
/*#__PURE__*/ jsx("div", {
|
|
190
336
|
className: "ov-file-tree__info-title",
|
|
191
337
|
children: title
|
|
192
338
|
}),
|
|
193
|
-
description ? /*#__PURE__*/ jsxs("
|
|
339
|
+
description ? /*#__PURE__*/ jsxs("div", {
|
|
194
340
|
className: "ov-file-tree__info-row",
|
|
195
341
|
children: [
|
|
196
342
|
/*#__PURE__*/ jsx("span", {
|
|
@@ -203,7 +349,7 @@ function FileTreeInfoTooltip({ copy }) {
|
|
|
203
349
|
})
|
|
204
350
|
]
|
|
205
351
|
}) : null,
|
|
206
|
-
triggerBehavior ? /*#__PURE__*/ jsxs("
|
|
352
|
+
triggerBehavior ? /*#__PURE__*/ jsxs("div", {
|
|
207
353
|
className: "ov-file-tree__info-row",
|
|
208
354
|
children: [
|
|
209
355
|
/*#__PURE__*/ jsx("span", {
|
|
@@ -216,7 +362,7 @@ function FileTreeInfoTooltip({ copy }) {
|
|
|
216
362
|
})
|
|
217
363
|
]
|
|
218
364
|
}) : null,
|
|
219
|
-
/*#__PURE__*/ jsxs("
|
|
365
|
+
/*#__PURE__*/ jsxs("div", {
|
|
220
366
|
className: "ov-file-tree__info-row",
|
|
221
367
|
children: [
|
|
222
368
|
/*#__PURE__*/ jsx("span", {
|
|
@@ -232,31 +378,23 @@ function FileTreeInfoTooltip({ copy }) {
|
|
|
232
378
|
]
|
|
233
379
|
});
|
|
234
380
|
}
|
|
235
|
-
function
|
|
381
|
+
function FileTreeTooltipContent({ row, infoLabels, renderRowTooltip }) {
|
|
236
382
|
if (renderRowTooltip) {
|
|
237
383
|
const custom = renderRowTooltip(row);
|
|
238
384
|
if (null == custom || false === custom) return null;
|
|
239
|
-
return
|
|
240
|
-
role: "tooltip",
|
|
241
|
-
className: "ov-file-tree__tooltip",
|
|
242
|
-
children: custom
|
|
243
|
-
});
|
|
385
|
+
return custom;
|
|
244
386
|
}
|
|
245
387
|
const copy = resolveFileTreeInfoCopy(row, infoLabels);
|
|
246
388
|
if (!copy) return null;
|
|
247
|
-
return /*#__PURE__*/ jsx(
|
|
248
|
-
|
|
249
|
-
className: "ov-file-tree__tooltip",
|
|
250
|
-
children: /*#__PURE__*/ jsx(FileTreeInfoTooltip, {
|
|
251
|
-
copy: copy
|
|
252
|
-
})
|
|
389
|
+
return /*#__PURE__*/ jsx(FileTreeInfoTooltip, {
|
|
390
|
+
copy: copy
|
|
253
391
|
});
|
|
254
392
|
}
|
|
255
|
-
const INDENT =
|
|
393
|
+
const INDENT = 16;
|
|
256
394
|
const CHEVRON_SIZE = 16;
|
|
257
395
|
function rowStyle(depth) {
|
|
258
396
|
return {
|
|
259
|
-
paddingLeft:
|
|
397
|
+
paddingLeft: depth * INDENT
|
|
260
398
|
};
|
|
261
399
|
}
|
|
262
400
|
function Guides({ depth }) {
|
|
@@ -267,14 +405,14 @@ function Guides({ depth }) {
|
|
|
267
405
|
"aria-hidden": "true",
|
|
268
406
|
className: "ov-file-tree__guide",
|
|
269
407
|
style: {
|
|
270
|
-
left:
|
|
408
|
+
left: level * INDENT + CHEVRON_SIZE / 2
|
|
271
409
|
}
|
|
272
410
|
}, level))
|
|
273
411
|
});
|
|
274
412
|
}
|
|
275
413
|
const FILE_TREE_ROW_ATTRIBUTE = 'data-file-tree-row-id';
|
|
276
414
|
function FileTreeRowView({ row, ctx }) {
|
|
277
|
-
const { text, selectedId,
|
|
415
|
+
const { text, selectedId, getRowAttributes, renderDashboard, renderRowTooltip, renderRowIcon, onSelect, onToggleExpand, onOpenRetentionSettings, onRowKeyDown } = ctx;
|
|
278
416
|
const isDirectory = 'directory' === row.type;
|
|
279
417
|
const canExpand = isDirectory && false !== row.hasChildren;
|
|
280
418
|
const isExpanded = Boolean(row.expanded);
|
|
@@ -293,7 +431,7 @@ function FileTreeRowView({ row, ctx }) {
|
|
|
293
431
|
event.stopPropagation();
|
|
294
432
|
onToggleExpand?.(row);
|
|
295
433
|
};
|
|
296
|
-
|
|
434
|
+
const rowNode = /*#__PURE__*/ jsxs("div", {
|
|
297
435
|
role: "treeitem",
|
|
298
436
|
tabIndex: 0,
|
|
299
437
|
"aria-level": row.depth + 1,
|
|
@@ -315,10 +453,6 @@ function FileTreeRowView({ row, ctx }) {
|
|
|
315
453
|
},
|
|
316
454
|
onClick: handleClick,
|
|
317
455
|
onKeyDown: (event)=>onRowKeyDown(event, row),
|
|
318
|
-
onMouseEnter: ()=>onRowEnter(row.id),
|
|
319
|
-
onMouseLeave: onRowLeave,
|
|
320
|
-
onFocus: ()=>onRowEnter(row.id),
|
|
321
|
-
onBlur: onRowLeave,
|
|
322
456
|
children: [
|
|
323
457
|
/*#__PURE__*/ jsx(Guides, {
|
|
324
458
|
depth: row.depth
|
|
@@ -382,14 +516,23 @@ function FileTreeRowView({ row, ctx }) {
|
|
|
382
516
|
dashboard ? /*#__PURE__*/ jsx("span", {
|
|
383
517
|
className: "ov-file-tree__dashboard",
|
|
384
518
|
children: dashboard
|
|
385
|
-
}) : null,
|
|
386
|
-
tooltipRowId === row.id ? /*#__PURE__*/ jsx(FileTreeTooltipSurface, {
|
|
387
|
-
row: row,
|
|
388
|
-
infoLabels: ctx.infoLabels,
|
|
389
|
-
renderRowTooltip: renderRowTooltip
|
|
390
519
|
}) : null
|
|
391
520
|
]
|
|
392
521
|
});
|
|
522
|
+
const custom = renderRowTooltip?.(row);
|
|
523
|
+
const hasContent = renderRowTooltip ? null != custom && false !== custom : null !== resolveFileTreeInfoCopy(row, ctx.infoLabels);
|
|
524
|
+
if (!hasContent) return rowNode;
|
|
525
|
+
const tooltipContent = /*#__PURE__*/ jsx(FileTreeTooltipContent, {
|
|
526
|
+
row: row,
|
|
527
|
+
infoLabels: ctx.infoLabels,
|
|
528
|
+
renderRowTooltip: renderRowTooltip
|
|
529
|
+
});
|
|
530
|
+
return /*#__PURE__*/ jsx(Popover, {
|
|
531
|
+
content: tooltipContent,
|
|
532
|
+
placement: "right",
|
|
533
|
+
trigger: "hover",
|
|
534
|
+
children: rowNode
|
|
535
|
+
});
|
|
393
536
|
}
|
|
394
537
|
function FileTreeStateRow({ row, ctx }) {
|
|
395
538
|
const { text, onLoadMore, onRetry, getRowAttributes, renderSpinner } = ctx;
|
|
@@ -567,41 +710,6 @@ function handleRowKeyDown(event, { root, row, onSelect, onToggleExpand }) {
|
|
|
567
710
|
return;
|
|
568
711
|
}
|
|
569
712
|
}
|
|
570
|
-
const DEFAULT_DELAY = 400;
|
|
571
|
-
function useRowTooltip(delay = DEFAULT_DELAY) {
|
|
572
|
-
const [tooltipRowId, setTooltipRowId] = useState(null);
|
|
573
|
-
const timerRef = useRef(void 0);
|
|
574
|
-
const clear = useCallback(()=>{
|
|
575
|
-
if (void 0 !== timerRef.current) {
|
|
576
|
-
window.clearTimeout(timerRef.current);
|
|
577
|
-
timerRef.current = void 0;
|
|
578
|
-
}
|
|
579
|
-
}, []);
|
|
580
|
-
useEffect(()=>clear, [
|
|
581
|
-
clear
|
|
582
|
-
]);
|
|
583
|
-
const show = useCallback((rowId)=>{
|
|
584
|
-
clear();
|
|
585
|
-
timerRef.current = window.setTimeout(()=>{
|
|
586
|
-
setTooltipRowId(rowId);
|
|
587
|
-
timerRef.current = void 0;
|
|
588
|
-
}, delay);
|
|
589
|
-
}, [
|
|
590
|
-
clear,
|
|
591
|
-
delay
|
|
592
|
-
]);
|
|
593
|
-
const hide = useCallback(()=>{
|
|
594
|
-
clear();
|
|
595
|
-
setTooltipRowId(null);
|
|
596
|
-
}, [
|
|
597
|
-
clear
|
|
598
|
-
]);
|
|
599
|
-
return {
|
|
600
|
-
tooltipRowId,
|
|
601
|
-
show,
|
|
602
|
-
hide
|
|
603
|
-
};
|
|
604
|
-
}
|
|
605
713
|
function useFileTreeActions(props) {
|
|
606
714
|
const pending = useRef(new Set());
|
|
607
715
|
const { select, toggleExpand, loadMore, retry, openRetentionSettings } = props.operations ?? {};
|
|
@@ -654,7 +762,6 @@ const file_tree_FileTree = /*#__PURE__*/ forwardRef(function({ rows, operations,
|
|
|
654
762
|
...labels,
|
|
655
763
|
info: labels?.info ?? DEFAULT_LABELS.info
|
|
656
764
|
};
|
|
657
|
-
const tooltip = useRowTooltip();
|
|
658
765
|
const actions = useFileTreeActions({
|
|
659
766
|
operations,
|
|
660
767
|
onSelect,
|
|
@@ -679,7 +786,6 @@ const file_tree_FileTree = /*#__PURE__*/ forwardRef(function({ rows, operations,
|
|
|
679
786
|
text,
|
|
680
787
|
infoLabels: labels?.info,
|
|
681
788
|
selectedId,
|
|
682
|
-
tooltipRowId: tooltip.tooltipRowId,
|
|
683
789
|
getRowAttributes,
|
|
684
790
|
renderDashboard,
|
|
685
791
|
renderRowTooltip,
|
|
@@ -691,9 +797,7 @@ const file_tree_FileTree = /*#__PURE__*/ forwardRef(function({ rows, operations,
|
|
|
691
797
|
row,
|
|
692
798
|
onSelect: actions.onSelect,
|
|
693
799
|
onToggleExpand: actions.onToggleExpand
|
|
694
|
-
})
|
|
695
|
-
onRowEnter: tooltip.show,
|
|
696
|
-
onRowLeave: tooltip.hide
|
|
800
|
+
})
|
|
697
801
|
};
|
|
698
802
|
return /*#__PURE__*/ jsxs("div", {
|
|
699
803
|
...rest,
|
package/dist/o~0.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { useLayoutEffect, useState } from "react";
|
|
2
|
+
const OVERLAY_OFFSET = 6;
|
|
3
|
+
const VIEWPORT_MARGIN = 8;
|
|
4
|
+
const OPPOSITE = {
|
|
5
|
+
top: 'bottom',
|
|
6
|
+
bottom: 'top',
|
|
7
|
+
left: 'right',
|
|
8
|
+
right: 'left'
|
|
9
|
+
};
|
|
10
|
+
function resolvePosition(trigger, surface, placement) {
|
|
11
|
+
const viewportWidth = window.innerWidth;
|
|
12
|
+
const viewportHeight = window.innerHeight;
|
|
13
|
+
const fits = (side)=>{
|
|
14
|
+
if ('top' === side) return trigger.top - surface.height - OVERLAY_OFFSET >= VIEWPORT_MARGIN;
|
|
15
|
+
if ('bottom' === side) return trigger.bottom + surface.height + OVERLAY_OFFSET <= viewportHeight - VIEWPORT_MARGIN;
|
|
16
|
+
if ('left' === side) return trigger.left - surface.width - OVERLAY_OFFSET >= VIEWPORT_MARGIN;
|
|
17
|
+
return trigger.right + surface.width + OVERLAY_OFFSET <= viewportWidth - VIEWPORT_MARGIN;
|
|
18
|
+
};
|
|
19
|
+
const side = fits(placement) || !fits(OPPOSITE[placement]) ? placement : OPPOSITE[placement];
|
|
20
|
+
const clamp = (value, size, limit)=>Math.min(Math.max(value, VIEWPORT_MARGIN), limit - size - VIEWPORT_MARGIN);
|
|
21
|
+
if ('top' === side || 'bottom' === side) {
|
|
22
|
+
const top = 'top' === side ? trigger.top - surface.height - OVERLAY_OFFSET : trigger.bottom + OVERLAY_OFFSET;
|
|
23
|
+
const left = trigger.left + trigger.width / 2 - surface.width / 2;
|
|
24
|
+
return {
|
|
25
|
+
top: clamp(top, surface.height, viewportHeight),
|
|
26
|
+
left: clamp(left, surface.width, viewportWidth),
|
|
27
|
+
placement: side
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const left = 'left' === side ? trigger.left - surface.width - OVERLAY_OFFSET : trigger.right + OVERLAY_OFFSET;
|
|
31
|
+
const top = trigger.top + trigger.height / 2 - surface.height / 2;
|
|
32
|
+
return {
|
|
33
|
+
top: clamp(top, surface.height, viewportHeight),
|
|
34
|
+
left: clamp(left, surface.width, viewportWidth),
|
|
35
|
+
placement: side
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function useOverlayPosition(open, triggerRef, surface, placement) {
|
|
39
|
+
const [position, setPosition] = useState({
|
|
40
|
+
top: 0,
|
|
41
|
+
left: 0,
|
|
42
|
+
placement
|
|
43
|
+
});
|
|
44
|
+
useLayoutEffect(()=>{
|
|
45
|
+
if (!open) return;
|
|
46
|
+
const trigger = triggerRef.current;
|
|
47
|
+
if (!trigger || !surface) return;
|
|
48
|
+
const written = new Set();
|
|
49
|
+
const syncTheme = ()=>{
|
|
50
|
+
const triggerStyle = window.getComputedStyle(trigger);
|
|
51
|
+
const seen = new Set();
|
|
52
|
+
for (const name of Array.from(triggerStyle)){
|
|
53
|
+
if (!name.startsWith('--ov-ui-color-')) continue;
|
|
54
|
+
const value = triggerStyle.getPropertyValue(name).trim();
|
|
55
|
+
if (value) {
|
|
56
|
+
seen.add(name);
|
|
57
|
+
surface.style.setProperty(name, value);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
for (const name of written)if (!seen.has(name)) surface.style.removeProperty(name);
|
|
61
|
+
written.clear();
|
|
62
|
+
seen.forEach((name)=>written.add(name));
|
|
63
|
+
};
|
|
64
|
+
syncTheme();
|
|
65
|
+
const themeObserver = new MutationObserver(syncTheme);
|
|
66
|
+
const observerOptions = {
|
|
67
|
+
attributes: true,
|
|
68
|
+
attributeFilter: [
|
|
69
|
+
'class',
|
|
70
|
+
'style',
|
|
71
|
+
'data-theme'
|
|
72
|
+
]
|
|
73
|
+
};
|
|
74
|
+
for(let node = trigger; node; node = node.parentElement)themeObserver.observe(node, observerOptions);
|
|
75
|
+
const update = ()=>{
|
|
76
|
+
const triggerRect = trigger.getBoundingClientRect();
|
|
77
|
+
const surfaceRect = surface.getBoundingClientRect();
|
|
78
|
+
const next = resolvePosition(triggerRect, {
|
|
79
|
+
width: surfaceRect.width,
|
|
80
|
+
height: surfaceRect.height
|
|
81
|
+
}, placement);
|
|
82
|
+
setPosition((previous)=>previous.top === next.top && previous.left === next.left && previous.placement === next.placement ? previous : next);
|
|
83
|
+
};
|
|
84
|
+
update();
|
|
85
|
+
const observer = new ResizeObserver(update);
|
|
86
|
+
observer.observe(surface);
|
|
87
|
+
window.addEventListener('scroll', update, true);
|
|
88
|
+
window.addEventListener('resize', update);
|
|
89
|
+
return ()=>{
|
|
90
|
+
observer.disconnect();
|
|
91
|
+
themeObserver.disconnect();
|
|
92
|
+
window.removeEventListener('scroll', update, true);
|
|
93
|
+
window.removeEventListener('resize', update);
|
|
94
|
+
};
|
|
95
|
+
}, [
|
|
96
|
+
open,
|
|
97
|
+
placement,
|
|
98
|
+
surface,
|
|
99
|
+
triggerRef
|
|
100
|
+
]);
|
|
101
|
+
return position;
|
|
102
|
+
}
|
|
103
|
+
export { useOverlayPosition };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { DividerProps } from './types.js';
|
|
2
|
+
export type { DividerOrientation, DividerProps } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* 一条分隔线。并排的控件之间用竖线,堆叠的分组之间用横线。
|
|
5
|
+
*
|
|
6
|
+
* 尺寸用内联样式给:`length` 与 `thickness` 都是运行时值,写进类名只能固定成
|
|
7
|
+
* 几个预设,而调用方要的往往是「和旁边按钮一样高」这种随上下文变化的长度。
|
|
8
|
+
* 颜色默认取主题基线的边框色,宿主换主题时自动跟随。
|
|
9
|
+
*
|
|
10
|
+
* A single divider: vertical between side-by-side controls, horizontal between
|
|
11
|
+
* stacked groups.
|
|
12
|
+
*
|
|
13
|
+
* Sizing is inline because `length` and `thickness` are runtime values; baking them
|
|
14
|
+
* into class names would fix them to a few presets, while a caller usually wants a
|
|
15
|
+
* length that follows its context, such as "as tall as the button beside it". The
|
|
16
|
+
* colour defaults to the baseline border, so it follows a host theme change.
|
|
17
|
+
*/
|
|
18
|
+
export declare function Divider({ orientation, length, thickness, color, className, style, ...rest }: DividerProps): import("react").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './divider.js';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { CSSProperties, HTMLAttributes } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* 分隔线的方向。竖线用于并排的控件之间,横线用于堆叠的分组之间。
|
|
4
|
+
* Direction of the divider: vertical between side-by-side controls, horizontal
|
|
5
|
+
* between stacked groups.
|
|
6
|
+
*/
|
|
7
|
+
export type DividerOrientation = 'vertical' | 'horizontal';
|
|
8
|
+
/**
|
|
9
|
+
* 分隔线的属性。
|
|
10
|
+
*
|
|
11
|
+
* 它只是一个 `role="separator"` 的元素,不占交互焦点,也不读屏幕阅读器以外的
|
|
12
|
+
* 内容。长度由 `length` 决定,颜色默认取主题基线里的边框色。
|
|
13
|
+
*
|
|
14
|
+
* Props of the divider.
|
|
15
|
+
*
|
|
16
|
+
* It is just a `role="separator"` element: not focusable, and it carries no content
|
|
17
|
+
* for a screen reader. `length` sets its extent, and the colour defaults to the
|
|
18
|
+
* baseline border.
|
|
19
|
+
*/
|
|
20
|
+
export interface DividerProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
21
|
+
/** 方向,默认竖线。Orientation; vertical by default. */
|
|
22
|
+
orientation?: DividerOrientation;
|
|
23
|
+
/**
|
|
24
|
+
* 线的长度:竖线是高度,横线是宽度。省略时由父级布局决定,横线默认铺满。
|
|
25
|
+
* Extent of the line: height for a vertical one, width for a horizontal one.
|
|
26
|
+
* Omitted leaves it to the parent layout; a horizontal one fills by default.
|
|
27
|
+
*/
|
|
28
|
+
length?: number | string;
|
|
29
|
+
/** 线的粗细,缺省为 1px。Thickness, 1px by default. */
|
|
30
|
+
thickness?: number | string;
|
|
31
|
+
/** 线的颜色,缺省取主题基线的边框色。Colour; defaults to the baseline border. */
|
|
32
|
+
color?: string;
|
|
33
|
+
/** 内联样式,可覆盖上面的值。Inline styles, overriding the values above. */
|
|
34
|
+
style?: CSSProperties;
|
|
35
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { OverlayPlacement } from './types.js';
|
|
2
2
|
/** 浮层与触发元素之间的间隙。 Gap between the surface and its trigger. */
|
|
3
|
-
export declare const
|
|
4
|
-
export interface
|
|
3
|
+
export declare const OVERLAY_OFFSET = 6;
|
|
4
|
+
export interface OverlayPosition {
|
|
5
5
|
top: number;
|
|
6
6
|
left: number;
|
|
7
7
|
/** 实际采用的方位,可能与请求的不同。 The placement actually used. */
|
|
8
|
-
placement:
|
|
8
|
+
placement: OverlayPlacement;
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
11
|
* 按触发元素与浮层尺寸算出一个视口坐标。空间不足时翻到对侧,仍放不下就
|
|
@@ -18,7 +18,7 @@ export interface TooltipPosition {
|
|
|
18
18
|
export declare function resolvePosition(trigger: DOMRect, surface: {
|
|
19
19
|
width: number;
|
|
20
20
|
height: number;
|
|
21
|
-
}, placement:
|
|
21
|
+
}, placement: OverlayPlacement): OverlayPosition;
|
|
22
22
|
/**
|
|
23
23
|
* 跟踪浮层的视口坐标。
|
|
24
24
|
*
|
|
@@ -35,4 +35,4 @@ export declare function resolvePosition(trigger: DOMRect, surface: {
|
|
|
35
35
|
* that is derivable during render. Scroll is captured so inner scroll containers
|
|
36
36
|
* count too; listeners are removed on close or unmount.
|
|
37
37
|
*/
|
|
38
|
-
export declare function
|
|
38
|
+
export declare function useOverlayPosition(open: boolean, triggerRef: React.RefObject<HTMLElement | null>, surface: HTMLElement | null, placement: OverlayPlacement): OverlayPosition;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './popover.js';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { PopoverProps } from './types.js';
|
|
2
|
+
export type { PopoverPlacement, PopoverProps, PopoverTrigger, } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* 弹出层:挂一段结构化信息或一小块可交互内容。
|
|
5
|
+
*
|
|
6
|
+
* 渲染到 `document.body`,因此不会被祖先的 `overflow: hidden` 裁掉——文件树的
|
|
7
|
+
* 行就处在这样的容器里。定位用 fixed 视口坐标,空间不足时翻到对侧。
|
|
8
|
+
*
|
|
9
|
+
* 与 `Tooltip` 分开,是因为两者视觉与语义都不同:提示是深色的一句话,弹出层是
|
|
10
|
+
* 白底卡片。共用的部分(portal、定位、主题变量同步)留在 `overlay/`。
|
|
11
|
+
*
|
|
12
|
+
* A surface holding structured information or a small piece of interactive
|
|
13
|
+
* content.
|
|
14
|
+
*
|
|
15
|
+
* It renders into `document.body`, so an ancestor's `overflow: hidden` cannot clip
|
|
16
|
+
* it — the file tree's rows sit inside exactly such a container. Positioning uses
|
|
17
|
+
* fixed viewport coordinates and flips sides when space runs out.
|
|
18
|
+
*
|
|
19
|
+
* It is separate from `Tooltip` because the two differ in look and semantics: a
|
|
20
|
+
* tooltip is one dark line, a popover is a white card. What they share — the
|
|
21
|
+
* portal, positioning and theme-variable syncing — lives in `overlay/`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function Popover({ children, content, placement, trigger, delay, disabled, className, style, onOpenChange, }: PopoverProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { OverlayPlacement } from '../overlay/types.js';
|
|
2
|
+
import type { CSSProperties, ReactElement, ReactNode } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* 弹出层的方位,与提示共用一套取值。空间不足时自动翻到对侧。
|
|
5
|
+
* Where the popover sits relative to its trigger, sharing the tooltip's values.
|
|
6
|
+
* It flips to the opposite side when there is not enough room.
|
|
7
|
+
*/
|
|
8
|
+
export type PopoverPlacement = OverlayPlacement;
|
|
9
|
+
/**
|
|
10
|
+
* 触发方式。`hover` 悬停与聚焦都展示,适合展示型内容;`click` 点击切换,适合
|
|
11
|
+
* 放按钮、菜单这类可交互的内容。
|
|
12
|
+
*
|
|
13
|
+
* How the popover opens. `hover` shows it on hover and focus, for display
|
|
14
|
+
* content; `click` toggles it, for interactive content such as buttons or menus.
|
|
15
|
+
*/
|
|
16
|
+
export type PopoverTrigger = 'hover' | 'click';
|
|
17
|
+
/**
|
|
18
|
+
* 弹出层的属性。
|
|
19
|
+
*
|
|
20
|
+
* 与提示的区别是视觉与语义:提示是深色底的一句话,弹出层是白底卡片,用来放
|
|
21
|
+
* 结构化信息或可交互内容。两者共用同一套 portal 与定位,触发元素都必须是能
|
|
22
|
+
* 接受 `ref` 的单个元素。
|
|
23
|
+
*
|
|
24
|
+
* Props of the popover.
|
|
25
|
+
*
|
|
26
|
+
* It differs from the tooltip in look and semantics: a tooltip is one dark line,
|
|
27
|
+
* a popover is a white card for structured or interactive content. Both share the
|
|
28
|
+
* same portal and positioning, and the trigger must be a single element that
|
|
29
|
+
* accepts a `ref`.
|
|
30
|
+
*/
|
|
31
|
+
export interface PopoverProps {
|
|
32
|
+
/** 触发元素,必须是能接受 ref 的单个元素。 The trigger; a single element that accepts a ref. */
|
|
33
|
+
children: ReactElement;
|
|
34
|
+
/** 浮层内容。 Surface content. */
|
|
35
|
+
content: ReactNode;
|
|
36
|
+
/** 方位,默认 `right`——内容在行尾展开,不遮挡左侧。 Placement, `right` by default. */
|
|
37
|
+
placement?: PopoverPlacement;
|
|
38
|
+
/** 触发方式,默认 `hover`。 Trigger mode, `hover` by default. */
|
|
39
|
+
trigger?: PopoverTrigger;
|
|
40
|
+
/** 悬停后多久展示,单位毫秒。延迟只作用于 `hover`。 Hover delay in ms; `hover` only. */
|
|
41
|
+
delay?: number;
|
|
42
|
+
/** 为真时不展示浮层。 Suppresses the surface; the trigger still renders. */
|
|
43
|
+
disabled?: boolean;
|
|
44
|
+
/** 浮层容器的额外类名。 Extra class names for the surface. */
|
|
45
|
+
className?: string;
|
|
46
|
+
/** 浮层容器的内联样式,可覆盖定位以外的样式。 Inline styles for the surface. */
|
|
47
|
+
style?: CSSProperties;
|
|
48
|
+
/** 展示状态变化时触发。 Fires when the surface opens or closes. */
|
|
49
|
+
onOpenChange?: (open: boolean) => void;
|
|
50
|
+
}
|