@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.
Files changed (98) hide show
  1. package/dist/1~0.js +506 -0
  2. package/dist/2~0.js +122 -0
  3. package/dist/{g~0.js → 30~0.js} +292 -167
  4. package/dist/client/index.d.ts +2 -1
  5. package/dist/client/paths.d.ts +64 -0
  6. package/dist/client/response.d.ts +31 -0
  7. package/dist/client/sse.d.ts +39 -0
  8. package/dist/client/stream.d.ts +26 -0
  9. package/dist/client/types.d.ts +104 -0
  10. package/dist/client.js +1 -239
  11. package/dist/components/agent-connect/style.css +2 -2
  12. package/dist/components/file-browser-entries/file-browser-entries-icons.d.ts +18 -0
  13. package/dist/components/file-browser-entries/file-browser-entries.d.ts +14 -0
  14. package/dist/components/file-browser-entries/index.d.ts +1 -0
  15. package/dist/components/file-browser-entries/style.css +155 -0
  16. package/dist/components/file-browser-entries/style.js +0 -0
  17. package/dist/components/file-browser-entries/types.d.ts +45 -0
  18. package/dist/components/file-browser-entries.js +1 -0
  19. package/dist/components/file-preview/file-preview-directory.d.ts +32 -0
  20. package/dist/components/file-preview/file-preview-header.d.ts +21 -3
  21. package/dist/components/file-preview/file-preview-panels.d.ts +41 -0
  22. package/dist/components/file-preview/file-preview-state.d.ts +10 -3
  23. package/dist/components/file-preview/file-preview.d.ts +2 -1
  24. package/dist/components/file-preview/level-selection.d.ts +25 -0
  25. package/dist/components/file-preview/style.css +76 -3
  26. package/dist/components/file-preview/types.d.ts +100 -1
  27. package/dist/components/file-preview/use-directory-level.d.ts +30 -0
  28. package/dist/components/file-preview/use-file-preview-actions-context.d.ts +6 -2
  29. package/dist/components/file-preview/use-file-preview-actions.d.ts +1 -1
  30. package/dist/components/file-preview.js +1 -1
  31. package/dist/components/file-tree/file-tree-info-tooltip.d.ts +7 -7
  32. package/dist/components/file-tree/file-tree-row-context.d.ts +0 -5
  33. package/dist/components/file-tree/file-tree-row-shared.d.ts +9 -2
  34. package/dist/components/file-tree/file-tree-tooltip-surface.d.ts +8 -8
  35. package/dist/components/file-tree/style.css +71 -34
  36. package/dist/components/file-tree/types.d.ts +20 -0
  37. package/dist/components/scope-switcher/style.css +2 -2
  38. package/dist/components/style.css +312 -47
  39. package/dist/components/tui/style.css +2 -2
  40. package/dist/components/viking-bot/style.css +2 -2
  41. package/dist/file-preview-viewer~0.js +1 -1
  42. package/dist/index.d.ts +2 -0
  43. package/dist/index.js +1 -0
  44. package/dist/l~0.js +1464 -25
  45. package/dist/modules/console/style.css +2 -2
  46. package/dist/modules/file-browser/file-browser-detail-icons.d.ts +10 -0
  47. package/dist/modules/file-browser/file-browser-detail.d.ts +33 -0
  48. package/dist/modules/file-browser/file-browser-empty.d.ts +3 -0
  49. package/dist/modules/file-browser/file-browser-failure.d.ts +22 -0
  50. package/dist/modules/file-browser/file-browser-icons.d.ts +18 -0
  51. package/dist/modules/file-browser/file-browser-labels.d.ts +28 -0
  52. package/dist/modules/file-browser/file-browser-layout.d.ts +27 -0
  53. package/dist/modules/file-browser/file-browser-toolbar.d.ts +18 -0
  54. package/dist/modules/file-browser/file-browser-tree-pane.d.ts +30 -0
  55. package/dist/modules/file-browser/file-browser.d.ts +14 -5
  56. package/dist/modules/file-browser/find-result.d.ts +24 -0
  57. package/dist/modules/file-browser/fs-directories.d.ts +33 -0
  58. package/dist/modules/file-browser/fs-file-kind.d.ts +19 -0
  59. package/dist/modules/file-browser/fs-icon.d.ts +17 -0
  60. package/dist/modules/file-browser/fs-model.d.ts +106 -0
  61. package/dist/modules/file-browser/fs-page.d.ts +16 -0
  62. package/dist/modules/file-browser/fs-path.d.ts +16 -0
  63. package/dist/modules/file-browser/fs-read-directory.d.ts +20 -0
  64. package/dist/modules/file-browser/fs-scope.d.ts +22 -0
  65. package/dist/modules/file-browser/fs-stat.d.ts +25 -0
  66. package/dist/modules/file-browser/index.d.ts +3 -1
  67. package/dist/modules/file-browser/style.css +4927 -35
  68. package/dist/modules/file-browser/tree-info-copy.d.ts +15 -0
  69. package/dist/modules/file-browser/tree-info-copy.zh-CN.d.ts +15 -0
  70. package/dist/modules/file-browser/types.d.ts +189 -44
  71. package/dist/modules/file-browser/use-container-width.d.ts +17 -0
  72. package/dist/modules/file-browser/use-file-browser.d.ts +49 -0
  73. package/dist/modules/file-browser/use-fs-preview.d.ts +51 -0
  74. package/dist/modules/file-browser/use-fs-search.d.ts +35 -0
  75. package/dist/modules/file-browser/use-fs-tree.d.ts +43 -0
  76. package/dist/modules/file-browser/use-request-scope.d.ts +39 -0
  77. package/dist/modules/file-browser.js +1 -1
  78. package/dist/modules/scope-cascade/style.css +2 -2
  79. package/dist/modules/style.css +4933 -41
  80. package/dist/n~0.js +178 -74
  81. package/dist/o~0.js +103 -0
  82. package/dist/shared/components/divider/divider.d.ts +18 -0
  83. package/dist/shared/components/divider/index.d.ts +1 -0
  84. package/dist/shared/components/divider/types.d.ts +35 -0
  85. package/dist/shared/components/overlay/types.d.ts +7 -0
  86. package/dist/shared/components/{tooltip/use-tooltip-position.d.ts → overlay/use-overlay-position.d.ts} +6 -6
  87. package/dist/shared/components/popover/index.d.ts +1 -0
  88. package/dist/shared/components/popover/popover.d.ts +23 -0
  89. package/dist/shared/components/popover/types.d.ts +50 -0
  90. package/dist/shared/components/resizable/clamp.d.ts +13 -0
  91. package/dist/shared/components/resizable/index.d.ts +2 -0
  92. package/dist/shared/components/resizable/resizable-handle.d.ts +25 -0
  93. package/dist/shared/components/resizable/types.d.ts +48 -0
  94. package/dist/shared/components/tooltip/types.d.ts +5 -5
  95. package/dist/style.css +5345 -188
  96. package/package.json +6 -1
  97. package/dist/components/file-tree/file-tree-tooltip.d.ts +0 -17
  98. 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
- const builtIn = key ? resolveInfoCopy(key, infoLabels) : {};
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("span", {
332
+ return /*#__PURE__*/ jsxs("div", {
187
333
  className: "ov-file-tree__info",
188
334
  children: [
189
- /*#__PURE__*/ jsx("span", {
335
+ /*#__PURE__*/ jsx("div", {
190
336
  className: "ov-file-tree__info-title",
191
337
  children: title
192
338
  }),
193
- description ? /*#__PURE__*/ jsxs("span", {
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("span", {
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("span", {
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 FileTreeTooltipSurface({ row, infoLabels, renderRowTooltip }) {
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 /*#__PURE__*/ jsx("span", {
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("span", {
248
- role: "tooltip",
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 = 20;
393
+ const INDENT = 16;
256
394
  const CHEVRON_SIZE = 16;
257
395
  function rowStyle(depth) {
258
396
  return {
259
- paddingLeft: 8 + depth * INDENT
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: 8 + level * INDENT + CHEVRON_SIZE / 2
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, tooltipRowId, getRowAttributes, renderDashboard, renderRowTooltip, renderRowIcon, onSelect, onToggleExpand, onOpenRetentionSettings, onRowKeyDown, onRowEnter, onRowLeave } = ctx;
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
- return /*#__PURE__*/ jsxs("div", {
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
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * 浮层相对触发元素的方位。空间不足时会自动翻到对侧。
3
+ *
4
+ * Where the surface sits relative to its trigger. It flips to the opposite side
5
+ * when there is not enough room.
6
+ */
7
+ export type OverlayPlacement = 'top' | 'bottom' | 'left' | 'right';
@@ -1,11 +1,11 @@
1
- import type { TooltipPlacement } from './types.js';
1
+ import type { OverlayPlacement } from './types.js';
2
2
  /** 浮层与触发元素之间的间隙。 Gap between the surface and its trigger. */
3
- export declare const OFFSET = 6;
4
- export interface TooltipPosition {
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: TooltipPlacement;
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: TooltipPlacement): TooltipPosition;
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 useTooltipPosition(open: boolean, triggerRef: React.RefObject<HTMLElement | null>, surface: HTMLElement | null, placement: TooltipPlacement): TooltipPosition;
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
+ }