@openviking/react 0.1.5 → 0.1.7

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 (145) hide show
  1. package/README.md +15 -11
  2. package/dist/2~0.js +6 -5
  3. package/dist/37~0.js +27 -0
  4. package/dist/3c~0.js +24 -12
  5. package/dist/3~0.js +19 -9
  6. package/dist/ae~0.js +8 -1
  7. package/dist/ark-message-list-view~0.js +9 -4
  8. package/dist/a~0.js +13 -7
  9. package/dist/c7r~0.js +50 -0
  10. package/dist/ck~0.js +7 -0
  11. package/dist/client/paths.d.ts +10 -0
  12. package/dist/client/provider.d.ts +6 -1
  13. package/dist/components/agent-connect/style.css +268 -37
  14. package/dist/components/directory-tour/style.css +265 -21
  15. package/dist/components/directory-tour.js +1 -1
  16. package/dist/components/experience-dashboard/dashboard-tabs.d.ts +11 -0
  17. package/dist/components/experience-dashboard/experience-dashboard.d.ts +2 -0
  18. package/dist/components/experience-dashboard/experience-impact.d.ts +11 -0
  19. package/dist/components/experience-dashboard/experience-list.d.ts +9 -0
  20. package/dist/components/experience-dashboard/experience-pagination.d.ts +8 -0
  21. package/dist/components/experience-dashboard/experience-tests.d.ts +6 -0
  22. package/dist/components/experience-dashboard/experience-trajectories.d.ts +6 -0
  23. package/dist/components/experience-dashboard/index.d.ts +2 -0
  24. package/dist/components/experience-dashboard/labels.d.ts +2 -0
  25. package/dist/components/experience-dashboard/style.css +914 -0
  26. package/dist/components/experience-dashboard/style.js +0 -0
  27. package/dist/components/experience-dashboard/types.d.ts +106 -0
  28. package/dist/components/experience-dashboard.js +1 -0
  29. package/dist/components/file-browser-entries/style.css +463 -86
  30. package/dist/components/file-preview/style.css +267 -78
  31. package/dist/components/file-tree/file-tree-toolbar.d.ts +3 -3
  32. package/dist/components/file-tree/locales/en-US.d.ts +3 -0
  33. package/dist/components/file-tree/locales/zh-CN.d.ts +3 -0
  34. package/dist/components/file-tree/style.css +372 -88
  35. package/dist/components/file-tree/types.d.ts +13 -4
  36. package/dist/components/scope-switcher/style.css +412 -39
  37. package/dist/components/style.css +9326 -4553
  38. package/dist/components/tui/style.css +385 -67
  39. package/dist/components/viking-bot/interaction/style.css +143 -22
  40. package/dist/components/viking-bot/style.css +1075 -278
  41. package/dist/components/wiki-dashboard/index.d.ts +2 -0
  42. package/dist/components/wiki-dashboard/labels.d.ts +2 -0
  43. package/dist/components/wiki-dashboard/style.css +956 -0
  44. package/dist/components/wiki-dashboard/style.js +0 -0
  45. package/dist/components/wiki-dashboard/types.d.ts +92 -0
  46. package/dist/components/wiki-dashboard/wiki-action-button.d.ts +9 -0
  47. package/dist/components/wiki-dashboard/wiki-conflict-card.d.ts +15 -0
  48. package/dist/components/wiki-dashboard/wiki-dashboard.d.ts +2 -0
  49. package/dist/components/wiki-dashboard/wiki-file-icon.d.ts +3 -0
  50. package/dist/components/wiki-dashboard/wiki-severity-filter.d.ts +8 -0
  51. package/dist/components/wiki-dashboard.js +1 -0
  52. package/dist/c~0.js +16 -8
  53. package/dist/ep~0.js +345 -0
  54. package/dist/e~0.js +33 -328
  55. package/dist/fj~0.js +507 -0
  56. package/dist/fl~0.js +709 -0
  57. package/dist/f~0.js +12 -27
  58. package/dist/icons/index.d.ts +28 -0
  59. package/dist/icons.js +1 -1
  60. package/dist/index.d.ts +4 -0
  61. package/dist/index.js +3 -1
  62. package/dist/k~0.js +277 -1
  63. package/dist/lk~0.js +56 -14
  64. package/dist/l~0.js +2786 -446
  65. package/dist/modules/console/index.d.ts +1 -2
  66. package/dist/modules/console/style.css +1787 -346
  67. package/dist/modules/console.js +1 -1
  68. package/dist/modules/file-browser/acl/acl-add-principal.d.ts +12 -0
  69. package/dist/modules/file-browser/acl/acl-candidate.d.ts +8 -0
  70. package/dist/modules/file-browser/acl/acl-client.d.ts +13 -0
  71. package/dist/modules/file-browser/acl/acl-confirmation.d.ts +6 -0
  72. package/dist/modules/file-browser/acl/acl-entry.d.ts +13 -0
  73. package/dist/modules/file-browser/acl/acl-labels.d.ts +47 -0
  74. package/dist/modules/file-browser/acl/acl-menu.d.ts +10 -0
  75. package/dist/modules/file-browser/acl/acl-modal.d.ts +17 -0
  76. package/dist/modules/file-browser/acl/acl-model.d.ts +17 -0
  77. package/dist/modules/file-browser/acl/acl-principal-tabs.d.ts +6 -0
  78. package/dist/modules/file-browser/acl/acl-tag.d.ts +7 -0
  79. package/dist/modules/file-browser/acl/locales/en-US.d.ts +44 -0
  80. package/dist/modules/file-browser/acl/locales/zh-CN.d.ts +44 -0
  81. package/dist/modules/file-browser/acl/use-acl-principals.d.ts +17 -0
  82. package/dist/modules/file-browser/acl/use-acl-report.d.ts +27 -0
  83. package/dist/modules/file-browser/acl-types.d.ts +86 -0
  84. package/dist/modules/file-browser/dashboard-data.d.ts +9 -0
  85. package/dist/modules/file-browser/dashboard-indicator.d.ts +8 -0
  86. package/dist/modules/file-browser/dashboard-labels.d.ts +9 -0
  87. package/dist/modules/file-browser/dashboard-model.d.ts +17 -0
  88. package/dist/modules/file-browser/dashboard-resource.d.ts +12 -0
  89. package/dist/modules/file-browser/experience-dashboard-pane.d.ts +8 -0
  90. package/dist/modules/file-browser/experience-data.d.ts +31 -0
  91. package/dist/modules/file-browser/file-browser-detail.d.ts +4 -1
  92. package/dist/modules/file-browser/file-browser-labels.d.ts +1 -1
  93. package/dist/modules/file-browser/file-browser-search.d.ts +20 -0
  94. package/dist/modules/file-browser/file-browser-toolbar.d.ts +3 -10
  95. package/dist/modules/file-browser/file-browser-tree-pane.d.ts +4 -7
  96. package/dist/modules/file-browser/file-browser.d.ts +1 -1
  97. package/dist/modules/file-browser/fs-directories.d.ts +9 -0
  98. package/dist/modules/file-browser/fs-lines.d.ts +36 -0
  99. package/dist/modules/file-browser/fs-memory-fields.d.ts +65 -0
  100. package/dist/modules/file-browser/fs-model.d.ts +15 -3
  101. package/dist/modules/file-browser/fs-read-file.d.ts +14 -0
  102. package/dist/modules/file-browser/index.d.ts +3 -2
  103. package/dist/modules/file-browser/locales/en-US.d.ts +5 -0
  104. package/dist/modules/file-browser/locales/zh-CN.d.ts +5 -0
  105. package/dist/modules/file-browser/style.css +4033 -483
  106. package/dist/modules/file-browser/types.d.ts +82 -20
  107. package/dist/modules/file-browser/use-browser-dashboards.d.ts +31 -0
  108. package/dist/modules/file-browser/use-dashboard-query.d.ts +9 -0
  109. package/dist/modules/file-browser/use-experience-dashboard.d.ts +27 -0
  110. package/dist/modules/file-browser/use-file-browser-acl.d.ts +15 -0
  111. package/dist/modules/file-browser/use-file-browser.d.ts +6 -51
  112. package/dist/modules/file-browser/use-fs-tree.d.ts +3 -0
  113. package/dist/modules/file-browser/use-wiki-dashboard.d.ts +17 -0
  114. package/dist/modules/file-browser/wiki-conflicts.d.ts +12 -0
  115. package/dist/modules/file-browser/wiki-dashboard-pane.d.ts +14 -0
  116. package/dist/modules/file-browser.js +1 -1
  117. package/dist/modules/scope-cascade/controller.d.ts +2 -2
  118. package/dist/modules/scope-cascade/index.d.ts +1 -2
  119. package/dist/modules/scope-cascade/scope-cascade.d.ts +1 -1
  120. package/dist/modules/scope-cascade/style.css +581 -39
  121. package/dist/modules/scope-cascade/types.d.ts +8 -3
  122. package/dist/modules/scope-cascade/use-scope-cascade.d.ts +2 -2
  123. package/dist/modules/scope-cascade.js +1 -1
  124. package/dist/modules/style.css +13589 -7966
  125. package/dist/n~0.js +73 -165
  126. package/dist/rt~0.js +255 -0
  127. package/dist/r~0.js +18 -39
  128. package/dist/shared/components/button/button.d.ts +20 -0
  129. package/dist/shared/components/input/input.d.ts +17 -0
  130. package/dist/shared/components/modal/locales/en-US.d.ts +4 -0
  131. package/dist/shared/components/modal/locales/zh-CN.d.ts +4 -0
  132. package/dist/shared/components/modal/modal.d.ts +2 -0
  133. package/dist/shared/components/modal/types.d.ts +18 -0
  134. package/dist/shared/components/overlay/lock-body-scroll.d.ts +1 -0
  135. package/dist/shared/components/popover/popover.d.ts +1 -1
  136. package/dist/shared/components/popover/types.d.ts +7 -1
  137. package/dist/shared/dashboard/dashboard-state.d.ts +12 -0
  138. package/dist/static/image/dashboard-background.png +0 -0
  139. package/dist/style.css +16088 -5602
  140. package/dist/s~0.js +16 -0
  141. package/dist/u~0.js +15 -6
  142. package/dist/viking-bot-composer~0.js +30 -12
  143. package/dist/viking-bot-interaction~0.js +2 -1
  144. package/package.json +14 -3
  145. package/dist/o~0.js +0 -106
package/dist/n~0.js CHANGED
@@ -1,13 +1,17 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
- import { cloneElement, forwardRef, useCallback, useEffect, useId, useImperativeHandle, useRef, useState } from "react";
3
- import { createPortal } from "react-dom";
2
+ import { forwardRef, useImperativeHandle, useRef, useState } from "react";
4
3
  import { resolveLocale, mergeLabels } from "./nx~0.js";
5
4
  import { FolderOpenIcon, FolderIcon, ChevronRightIcon, DocumentIcon } from "./k~0.js";
6
- import { useOverlayPosition } from "./o~0.js";
5
+ import { Popover } from "./r~0.js";
6
+ import { button_Button } from "./e~0.js";
7
7
  import { searchreact } from "./p~0.js";
8
+ import { Tooltip } from "./rt~0.js";
8
9
  import { useLocale } from "./28~0.js";
9
10
  const messages = {
10
- search: 'Search files…',
11
+ readOnly: 'Read-only',
12
+ noAccess: 'No access',
13
+ traverseOnly: 'Traverse only',
14
+ search: 'Search files ⌘+K...',
11
15
  refresh: 'Refresh file tree',
12
16
  empty: 'No files yet',
13
17
  error: 'Failed to load',
@@ -76,7 +80,10 @@ const messages = {
76
80
  };
77
81
  const en_US = messages;
78
82
  const zh_CN_messages = {
79
- search: '搜索文件…',
83
+ readOnly: '只读',
84
+ noAccess: '无权限',
85
+ traverseOnly: '仅可遍历',
86
+ search: '搜索文件 ⌘+K...',
80
87
  refresh: '刷新文件树',
81
88
  empty: '暂无文件',
82
89
  error: '加载失败',
@@ -278,131 +285,6 @@ function resolveInfoCopy(key, hostLabels) {
278
285
  triggerBehavior: triggerBehavior || void 0
279
286
  };
280
287
  }
281
- function useMergedRef(ref, target) {
282
- return useCallback((node)=>{
283
- target.current = node;
284
- if ('function' == typeof ref) ref(node);
285
- else if (ref) ref.current = node;
286
- }, [
287
- ref,
288
- target
289
- ]);
290
- }
291
- function Popover({ children, content, placement = 'right', trigger = 'hover', delay = 300, disabled = false, className, style, onOpenChange }) {
292
- const [open, setOpen] = useState(false);
293
- const triggerRef = useRef(null);
294
- const timerRef = useRef(void 0);
295
- const [surfaceNode, setSurfaceNode] = useState(null);
296
- const id = useId();
297
- const position = useOverlayPosition(open, triggerRef, surfaceNode, placement);
298
- const change = useCallback((next)=>{
299
- setOpen(next);
300
- onOpenChange?.(next);
301
- }, [
302
- onOpenChange
303
- ]);
304
- const clearTimer = useCallback(()=>{
305
- if (void 0 !== timerRef.current) {
306
- window.clearTimeout(timerRef.current);
307
- timerRef.current = void 0;
308
- }
309
- }, []);
310
- useEffect(()=>clearTimer, [
311
- clearTimer
312
- ]);
313
- useEffect(()=>{
314
- if (disabled) {
315
- clearTimer();
316
- setOpen(false);
317
- }
318
- }, [
319
- disabled,
320
- clearTimer
321
- ]);
322
- useEffect(()=>{
323
- if (!open || 'click' !== trigger) return;
324
- const onPointerDown = (event)=>{
325
- const target = event.target;
326
- if (surfaceNode?.contains(target) || triggerRef.current?.contains(target)) return;
327
- change(false);
328
- };
329
- const onKeyDown = (event)=>{
330
- if ('Escape' === event.key) change(false);
331
- };
332
- document.addEventListener('mousedown', onPointerDown);
333
- document.addEventListener('keydown', onKeyDown);
334
- return ()=>{
335
- document.removeEventListener('mousedown', onPointerDown);
336
- document.removeEventListener('keydown', onKeyDown);
337
- };
338
- }, [
339
- change,
340
- open,
341
- surfaceNode,
342
- trigger
343
- ]);
344
- const show = ()=>{
345
- if (disabled) return;
346
- if ('click' === trigger) return void change(!open);
347
- clearTimer();
348
- timerRef.current = window.setTimeout(()=>{
349
- change(true);
350
- timerRef.current = void 0;
351
- }, delay);
352
- };
353
- const hide = ()=>{
354
- if ('click' === trigger) return;
355
- clearTimer();
356
- change(false);
357
- };
358
- const child = children;
359
- const childProps = child.props;
360
- const childRef = child.ref;
361
- const mergedRef = useMergedRef(childRef, triggerRef);
362
- const declaresExpanded = 'aria-expanded' in childProps;
363
- const triggerElement = /*#__PURE__*/ cloneElement(child, {
364
- ref: mergedRef,
365
- ...declaresExpanded ? {} : {
366
- 'aria-expanded': open
367
- },
368
- onMouseEnter: (event)=>{
369
- childProps.onMouseEnter?.(event);
370
- if ('hover' === trigger) show();
371
- },
372
- onMouseLeave: (event)=>{
373
- childProps.onMouseLeave?.(event);
374
- if ('hover' === trigger) hide();
375
- },
376
- onClick: (event)=>{
377
- childProps.onClick?.(event);
378
- if ('click' === trigger) show();
379
- }
380
- });
381
- const surface = open ? /*#__PURE__*/ createPortal(/*#__PURE__*/ jsx("div", {
382
- ref: setSurfaceNode,
383
- id: id,
384
- role: 'click' === trigger ? 'dialog' : 'note',
385
- className: [
386
- 'ov-popover',
387
- className
388
- ].filter(Boolean).join(' '),
389
- "data-placement": position.placement,
390
- style: {
391
- top: position.top,
392
- left: position.left,
393
- ...style
394
- },
395
- onMouseEnter: 'hover' === trigger ? clearTimer : void 0,
396
- onMouseLeave: 'hover' === trigger ? hide : void 0,
397
- children: content
398
- }), document.body) : null;
399
- return /*#__PURE__*/ jsxs(Fragment, {
400
- children: [
401
- triggerElement,
402
- surface
403
- ]
404
- });
405
- }
406
288
  const DEFAULT_FIELDS = {
407
289
  description: "Description",
408
290
  triggerBehavior: 'Trigger',
@@ -509,6 +391,7 @@ function Guides({ depth }) {
509
391
  }
510
392
  const FILE_TREE_ROW_ATTRIBUTE = 'data-file-tree-row-id';
511
393
  function FileTreeRowView({ row, ctx }) {
394
+ const anchorRef = useRef(null);
512
395
  const { text, selectedId, getRowAttributes, renderDashboard, renderRowTooltip, renderRowIcon, onSelect, onToggleExpand, onOpenRetentionSettings, onRowKeyDown } = ctx;
513
396
  const isDirectory = 'directory' === row.type;
514
397
  const canExpand = isDirectory && false !== row.hasChildren;
@@ -521,7 +404,7 @@ function FileTreeRowView({ row, ctx }) {
521
404
  const description = row.description ?? (infoKey && showsInlineDescription(infoKey) ? resolveInfoCopy(infoKey, ctx.infoLabels).description : void 0);
522
405
  const handleClick = (event)=>{
523
406
  if (event.target.closest('[data-role="toggle"]')) return;
524
- if (row.disabled) return;
407
+ if (row.disabled || false === row.selectable) return;
525
408
  onSelect?.(row);
526
409
  };
527
410
  const handleToggle = (event)=>{
@@ -532,7 +415,7 @@ function FileTreeRowView({ row, ctx }) {
532
415
  role: "treeitem",
533
416
  tabIndex: 0,
534
417
  "aria-level": row.depth + 1,
535
- "aria-selected": isSelected,
418
+ "aria-selected": false === row.selectable ? void 0 : isSelected,
536
419
  "aria-expanded": canExpand ? isExpanded : void 0,
537
420
  "aria-disabled": row.disabled || void 0,
538
421
  ...extraAttributes,
@@ -611,10 +494,22 @@ function FileTreeRowView({ row, ctx }) {
611
494
  className: "ov-file-tree__level",
612
495
  children: row.levelLabel
613
496
  }) : null,
497
+ row.access ? /*#__PURE__*/ jsx("span", {
498
+ className: "ov-file-tree__level",
499
+ children: 'read-only' === row.access ? text.readOnly : 'denied' === row.access ? text.noAccess : text.traverseOnly
500
+ }) : null,
614
501
  dashboard ? /*#__PURE__*/ jsx("span", {
615
502
  className: "ov-file-tree__dashboard",
616
503
  children: dashboard
617
- }) : null
504
+ }) : null,
505
+ /*#__PURE__*/ jsx("span", {
506
+ className: "ov-file-tree__popover-anchor-container",
507
+ "aria-hidden": "true",
508
+ children: /*#__PURE__*/ jsx("span", {
509
+ ref: anchorRef,
510
+ className: "ov-file-tree__popover-anchor"
511
+ })
512
+ })
618
513
  ]
619
514
  });
620
515
  const custom = renderRowTooltip?.(row);
@@ -628,6 +523,7 @@ function FileTreeRowView({ row, ctx }) {
628
523
  return /*#__PURE__*/ jsx(Popover, {
629
524
  content: tooltipContent,
630
525
  placement: "right",
526
+ anchorRef: anchorRef,
631
527
  trigger: "hover",
632
528
  children: rowNode
633
529
  });
@@ -682,8 +578,10 @@ function FileTreeStateRow({ row, ctx }) {
682
578
  className: "ov-file-tree__toggle-spacer"
683
579
  }),
684
580
  row.loading ? spinner : null,
685
- /*#__PURE__*/ jsx("button", {
686
- type: "button",
581
+ /*#__PURE__*/ jsx(button_Button, {
582
+ size: "mini",
583
+ type: "text",
584
+ htmlType: "button",
687
585
  className: "ov-file-tree__action",
688
586
  disabled: row.loading || !onLoadMore,
689
587
  onClick: ()=>onLoadMore?.(row),
@@ -701,8 +599,10 @@ function FileTreeStateRow({ row, ctx }) {
701
599
  className: "ov-file-tree__muted",
702
600
  children: row.message ?? text.error
703
601
  }),
704
- /*#__PURE__*/ jsx("button", {
705
- type: "button",
602
+ /*#__PURE__*/ jsx(button_Button, {
603
+ size: "mini",
604
+ type: "text",
605
+ htmlType: "button",
706
606
  className: "ov-file-tree__action",
707
607
  disabled: !onRetry,
708
608
  onClick: ()=>onRetry?.(row),
@@ -802,22 +702,27 @@ function handleRowKeyDown(event, { root, row, onSelect, onToggleExpand }) {
802
702
  case 'Enter':
803
703
  case ' ':
804
704
  event.preventDefault();
805
- if (!row.disabled) onSelect?.(row);
705
+ if (!row.disabled && false !== row.selectable) onSelect?.(row);
806
706
  return;
807
707
  default:
808
708
  return;
809
709
  }
810
710
  }
811
- function FileTreeToolbar({ search, refresh, text, refreshing, onSearch, onRefresh }) {
711
+ function FileTreeToolbar({ search, refresh, loading, text, refreshing, onSearch, onRefresh, className }) {
812
712
  if (!search && !refresh) return null;
813
713
  const searchDisabled = !onSearch || 'object' == typeof search && search.disabled;
814
714
  const refreshDisabled = !onRefresh || 'object' == typeof refresh && refresh.disabled;
815
- const busy = refreshing || 'object' == typeof refresh && refresh.loading;
715
+ const busy = loading || refreshing || 'object' == typeof refresh && refresh.loading;
816
716
  return /*#__PURE__*/ jsxs("div", {
817
- className: "ov-file-tree__controls",
717
+ className: [
718
+ 'ov-file-tree__controls',
719
+ className
720
+ ].filter(Boolean).join(' '),
818
721
  children: [
819
- search ? /*#__PURE__*/ jsxs("button", {
820
- type: "button",
722
+ search ? /*#__PURE__*/ jsxs(button_Button, {
723
+ size: "default",
724
+ type: "default",
725
+ htmlType: "button",
821
726
  className: "ov-file-tree__search",
822
727
  disabled: Boolean(searchDisabled),
823
728
  onClick: onSearch,
@@ -834,27 +739,29 @@ function FileTreeToolbar({ search, refresh, text, refreshing, onSearch, onRefres
834
739
  })
835
740
  ]
836
741
  }) : null,
837
- refresh ? /*#__PURE__*/ jsx("button", {
838
- type: "button",
839
- className: "ov-file-tree__refresh",
840
- "aria-label": text.refresh,
841
- title: text.refresh,
842
- "aria-busy": Boolean(busy),
742
+ refresh ? /*#__PURE__*/ jsx(Tooltip, {
743
+ content: text.refresh,
843
744
  disabled: Boolean(refreshDisabled || busy),
844
- onClick: onRefresh,
845
- children: /*#__PURE__*/ jsx("svg", {
846
- "aria-hidden": "true",
847
- width: 14,
848
- height: 14,
849
- viewBox: "0 0 16 16",
850
- fill: "none",
851
- className: busy ? 'ov-file-tree__refresh-spinning' : void 0,
852
- children: /*#__PURE__*/ jsx("path", {
853
- d: "M13 6a5.2 5.2 0 1 0 .15 3.5M13 2.5V6H9.5",
854
- stroke: "currentColor",
855
- strokeWidth: "1.5",
856
- strokeLinecap: "round",
857
- strokeLinejoin: "round"
745
+ children: /*#__PURE__*/ jsx(button_Button, {
746
+ className: "ov-file-tree__refresh",
747
+ "aria-label": text.refresh,
748
+ "aria-busy": Boolean(busy),
749
+ loading: Boolean(busy),
750
+ disabled: Boolean(refreshDisabled),
751
+ onClick: onRefresh,
752
+ icon: /*#__PURE__*/ jsx("svg", {
753
+ "aria-hidden": "true",
754
+ width: 14,
755
+ height: 14,
756
+ viewBox: "0 0 16 16",
757
+ fill: "none",
758
+ children: /*#__PURE__*/ jsx("path", {
759
+ d: "M13 6a5.2 5.2 0 1 0 .15 3.5M13 2.5V6H9.5",
760
+ stroke: "currentColor",
761
+ strokeWidth: "1.5",
762
+ strokeLinecap: "round",
763
+ strokeLinejoin: "round"
764
+ })
858
765
  })
859
766
  })
860
767
  }) : null
@@ -905,7 +812,7 @@ function FileTreeSpinner({ className, ...rest }) {
905
812
  function findRow(root, id) {
906
813
  return root?.querySelector(`[${FILE_TREE_ROW_ATTRIBUTE}="${CSS.escape(id)}"]`) ?? null;
907
814
  }
908
- const file_tree_FileTree = /*#__PURE__*/ forwardRef(function({ rows, locale: localeProp, operations, selectedId, search, refresh, isReady = true, loadingFallback, errorFallback, emptyFallback, slots, labels, getRowAttributes, renderDashboard, renderRowTooltip, renderRowIcon, onSelect, onToggleExpand, onLoadMore, onRetry, onOpenRetentionSettings, onSearch, onRefresh, className, ...rest }, ref) {
815
+ const file_tree_FileTree = /*#__PURE__*/ forwardRef(function({ rows, locale: localeProp, operations, selectedId, search = true, refresh = true, loading = false, isReady = true, loadingFallback, errorFallback, emptyFallback, slots, labels, getRowAttributes, renderDashboard, renderRowTooltip, renderRowIcon, onSelect, onToggleExpand, onLoadMore, onRetry, onOpenRetentionSettings, onSearch, onRefresh, className, ...rest }, ref) {
909
816
  const locale = useLocale(localeProp);
910
817
  const rootRef = useRef(null);
911
818
  const text = resolveFileTreeLabels(locale, labels);
@@ -963,6 +870,7 @@ const file_tree_FileTree = /*#__PURE__*/ forwardRef(function({ rows, locale: loc
963
870
  /*#__PURE__*/ jsx(FileTreeToolbar, {
964
871
  search: search,
965
872
  refresh: refresh,
873
+ loading: loading,
966
874
  text: text,
967
875
  refreshing: actions.refreshing,
968
876
  onSearch: actions.onSearch,
@@ -985,4 +893,4 @@ const file_tree_FileTree = /*#__PURE__*/ forwardRef(function({ rows, locale: loc
985
893
  ]
986
894
  });
987
895
  });
988
- export { DEFAULT_INFO_LABELS, FILE_TREE_ROW_ATTRIBUTE, FileTreeSpinner, file_tree_FileTree as FileTree, resolveFileTreeInfoKey, resolveInfoCopy, showsInlineDescription, splitVikingUri };
896
+ export { DEFAULT_INFO_LABELS, FILE_TREE_ROW_ATTRIBUTE, FileTreeSpinner, FileTreeToolbar, file_tree_FileTree as FileTree, resolveFileTreeInfoKey, resolveInfoCopy, showsInlineDescription, splitVikingUri };
package/dist/rt~0.js ADDED
@@ -0,0 +1,255 @@
1
+ import { cloneElement, useCallback, useEffect, useId, useLayoutEffect, useRef, useState } from "react";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { createPortal } from "react-dom";
4
+ const usePositionEffect = "u" < typeof window ? useEffect : useLayoutEffect;
5
+ const OVERLAY_OFFSET = 6;
6
+ const VIEWPORT_MARGIN = 8;
7
+ const OPPOSITE = {
8
+ top: 'bottom',
9
+ bottom: 'top',
10
+ left: 'right',
11
+ right: 'left'
12
+ };
13
+ function resolvePosition(trigger, surface, placement, alignment = 'center') {
14
+ const viewportWidth = window.innerWidth;
15
+ const viewportHeight = window.innerHeight;
16
+ const fits = (side)=>{
17
+ if ('top' === side) return trigger.top - surface.height - OVERLAY_OFFSET >= VIEWPORT_MARGIN;
18
+ if ('bottom' === side) return trigger.bottom + surface.height + OVERLAY_OFFSET <= viewportHeight - VIEWPORT_MARGIN;
19
+ if ('left' === side) return trigger.left - surface.width - OVERLAY_OFFSET >= VIEWPORT_MARGIN;
20
+ return trigger.right + surface.width + OVERLAY_OFFSET <= viewportWidth - VIEWPORT_MARGIN;
21
+ };
22
+ const side = fits(placement) || !fits(OPPOSITE[placement]) ? placement : OPPOSITE[placement];
23
+ const clamp = (value, size, limit)=>Math.min(Math.max(value, VIEWPORT_MARGIN), limit - size - VIEWPORT_MARGIN);
24
+ if ('top' === side || 'bottom' === side) {
25
+ const top = 'top' === side ? trigger.top - surface.height - OVERLAY_OFFSET : trigger.bottom + OVERLAY_OFFSET;
26
+ const left = 'end' === alignment ? trigger.right - surface.width : trigger.left + trigger.width / 2 - surface.width / 2;
27
+ return {
28
+ top: clamp(top, surface.height, viewportHeight),
29
+ left: clamp(left, surface.width, viewportWidth),
30
+ placement: side
31
+ };
32
+ }
33
+ const left = 'left' === side ? trigger.left - surface.width - OVERLAY_OFFSET : trigger.right + OVERLAY_OFFSET;
34
+ const top = trigger.top + trigger.height / 2 - surface.height / 2;
35
+ return {
36
+ top: clamp(top, surface.height, viewportHeight),
37
+ left: clamp(left, surface.width, viewportWidth),
38
+ placement: side
39
+ };
40
+ }
41
+ function useOverlayPosition(open, triggerRef, surface, placement, alignment = 'center') {
42
+ const [position, setPosition] = useState({
43
+ top: 0,
44
+ left: 0,
45
+ placement
46
+ });
47
+ usePositionEffect(()=>{
48
+ if (!open) return;
49
+ const trigger = triggerRef.current;
50
+ if (!trigger || !surface) return;
51
+ const written = new Set();
52
+ const syncTheme = ()=>{
53
+ const triggerStyle = window.getComputedStyle(trigger);
54
+ const seen = new Set();
55
+ for (const name of Array.from(triggerStyle)){
56
+ if (!name.startsWith('--ov-ui-color-')) continue;
57
+ const value = triggerStyle.getPropertyValue(name).trim();
58
+ if (value) {
59
+ seen.add(name);
60
+ surface.style.setProperty(name, value);
61
+ }
62
+ }
63
+ for (const name of written)if (!seen.has(name)) surface.style.removeProperty(name);
64
+ written.clear();
65
+ seen.forEach((name)=>written.add(name));
66
+ };
67
+ syncTheme();
68
+ const themeObserver = new MutationObserver(syncTheme);
69
+ const observerOptions = {
70
+ attributes: true,
71
+ attributeFilter: [
72
+ 'class',
73
+ 'style',
74
+ 'data-theme'
75
+ ]
76
+ };
77
+ for(let node = trigger; node; node = node.parentElement)themeObserver.observe(node, observerOptions);
78
+ const update = ()=>{
79
+ const triggerRect = trigger.getBoundingClientRect();
80
+ const surfaceRect = surface.getBoundingClientRect();
81
+ const next = resolvePosition(triggerRect, {
82
+ width: surfaceRect.width,
83
+ height: surfaceRect.height
84
+ }, placement, alignment);
85
+ setPosition((previous)=>previous.top === next.top && previous.left === next.left && previous.placement === next.placement ? previous : next);
86
+ };
87
+ update();
88
+ const observer = new ResizeObserver(update);
89
+ observer.observe(surface);
90
+ window.addEventListener('scroll', update, true);
91
+ window.addEventListener('resize', update);
92
+ return ()=>{
93
+ observer.disconnect();
94
+ themeObserver.disconnect();
95
+ written.forEach((name)=>surface.style.removeProperty(name));
96
+ window.removeEventListener('scroll', update, true);
97
+ window.removeEventListener('resize', update);
98
+ };
99
+ }, [
100
+ open,
101
+ placement,
102
+ surface,
103
+ triggerRef,
104
+ alignment
105
+ ]);
106
+ return position;
107
+ }
108
+ const DEFAULT_LABELS = {
109
+ close: 'Close'
110
+ };
111
+ function useMergedRef(ref, target) {
112
+ const merged = useCallback((node)=>{
113
+ target.current = node;
114
+ if ('function' == typeof ref) ref(node);
115
+ else if (ref) ref.current = node;
116
+ }, [
117
+ ref,
118
+ target
119
+ ]);
120
+ return merged;
121
+ }
122
+ function Tooltip({ children, content, placement = 'top', trigger = 'hover', delay = 300, disabled = false, className, style, onOpenChange, labels }) {
123
+ const text = {
124
+ ...DEFAULT_LABELS,
125
+ ...labels
126
+ };
127
+ const [open, setOpen] = useState(false);
128
+ const triggerRef = useRef(null);
129
+ const timerRef = useRef(void 0);
130
+ const [surfaceNode, setSurfaceNode] = useState(null);
131
+ const id = useId();
132
+ const position = useOverlayPosition(open, triggerRef, surfaceNode, placement);
133
+ const change = useCallback((next)=>{
134
+ setOpen(next);
135
+ onOpenChange?.(next);
136
+ }, [
137
+ onOpenChange
138
+ ]);
139
+ const clearTimer = useCallback(()=>{
140
+ if (void 0 !== timerRef.current) {
141
+ window.clearTimeout(timerRef.current);
142
+ timerRef.current = void 0;
143
+ }
144
+ }, []);
145
+ useEffect(()=>clearTimer, [
146
+ clearTimer
147
+ ]);
148
+ useEffect(()=>{
149
+ if (disabled) {
150
+ clearTimer();
151
+ setOpen(false);
152
+ }
153
+ }, [
154
+ disabled,
155
+ clearTimer
156
+ ]);
157
+ useEffect(()=>{
158
+ if (!open) return;
159
+ const onPointerDown = (event)=>{
160
+ const target = event.target;
161
+ if (surfaceNode?.contains(target) || triggerRef.current?.contains(target)) return;
162
+ change(false);
163
+ };
164
+ const onKeyDown = (event)=>{
165
+ if ('Escape' === event.key) {
166
+ clearTimer();
167
+ change(false);
168
+ }
169
+ };
170
+ if ('click' === trigger) document.addEventListener('mousedown', onPointerDown);
171
+ document.addEventListener('keydown', onKeyDown);
172
+ return ()=>{
173
+ if ('click' === trigger) document.removeEventListener('mousedown', onPointerDown);
174
+ document.removeEventListener('keydown', onKeyDown);
175
+ };
176
+ }, [
177
+ change,
178
+ clearTimer,
179
+ open,
180
+ surfaceNode,
181
+ trigger
182
+ ]);
183
+ const show = ()=>{
184
+ if (disabled) return;
185
+ if ('click' === trigger) return void change(!open);
186
+ clearTimer();
187
+ timerRef.current = window.setTimeout(()=>{
188
+ change(true);
189
+ timerRef.current = void 0;
190
+ }, delay);
191
+ };
192
+ const hide = ()=>{
193
+ if ('click' === trigger) return;
194
+ clearTimer();
195
+ timerRef.current = window.setTimeout(()=>{
196
+ change(false);
197
+ timerRef.current = void 0;
198
+ }, 120);
199
+ };
200
+ const child = children;
201
+ const childProps = child.props;
202
+ const childRef = child.ref;
203
+ const mergedRef = useMergedRef(childRef, triggerRef);
204
+ const triggerElement = /*#__PURE__*/ cloneElement(child, {
205
+ ref: mergedRef,
206
+ 'aria-describedby': childProps['aria-describedby'] ?? (open && 'hover' === trigger && content !== childProps['aria-label'] ? id : void 0),
207
+ 'aria-expanded': 'click' === trigger ? open : childProps['aria-expanded'],
208
+ onMouseEnter: (event)=>{
209
+ childProps.onMouseEnter?.(event);
210
+ if ('hover' === trigger) show();
211
+ },
212
+ onMouseLeave: (event)=>{
213
+ childProps.onMouseLeave?.(event);
214
+ if ('hover' === trigger) hide();
215
+ },
216
+ onFocus: (event)=>{
217
+ childProps.onFocus?.(event);
218
+ if ('hover' === trigger) show();
219
+ },
220
+ onBlur: (event)=>{
221
+ childProps.onBlur?.(event);
222
+ hide();
223
+ },
224
+ onClick: (event)=>{
225
+ childProps.onClick?.(event);
226
+ if ('click' === trigger) show();
227
+ }
228
+ });
229
+ const surface = open ? /*#__PURE__*/ createPortal(/*#__PURE__*/ jsx("div", {
230
+ ref: setSurfaceNode,
231
+ id: id,
232
+ role: 'hover' === trigger ? 'tooltip' : 'dialog',
233
+ "aria-label": 'click' === trigger ? text.close : void 0,
234
+ className: [
235
+ 'ov-tooltip',
236
+ className
237
+ ].filter(Boolean).join(' '),
238
+ "data-placement": position.placement,
239
+ style: {
240
+ top: position.top,
241
+ left: position.left,
242
+ ...style
243
+ },
244
+ onMouseEnter: 'hover' === trigger ? clearTimer : void 0,
245
+ onMouseLeave: 'hover' === trigger ? hide : void 0,
246
+ children: content
247
+ }), document.body) : null;
248
+ return /*#__PURE__*/ jsxs(Fragment, {
249
+ children: [
250
+ triggerElement,
251
+ surface
252
+ ]
253
+ });
254
+ }
255
+ export { Tooltip, useOverlayPosition };