@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
@@ -1,6 +1,7 @@
1
- import { Fragment as jsx_runtime_Fragment, jsx, jsxs } from "react/jsx-runtime";
2
- import { Fragment, Suspense, cloneElement, forwardRef, lazy, useCallback, useEffect, useId, useImperativeHandle, useLayoutEffect, useRef, useState } from "react";
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { Fragment as external_react_Fragment, Suspense, cloneElement, forwardRef, lazy, useCallback, useEffect, useId, useImperativeHandle, useLayoutEffect, useRef, useState } from "react";
3
3
  import { createPortal } from "react-dom";
4
+ import { useOverlayPosition } from "./o~0.js";
4
5
  function FilePreviewEditor({ draft, text, loading, failed, saveFailed, saving, onChange, onCancel }) {
5
6
  if (loading) return /*#__PURE__*/ jsx("div", {
6
7
  className: "ov-file-preview__state",
@@ -84,11 +85,12 @@ function readCopyableText(source) {
84
85
  function isEmptyFile(source) {
85
86
  return '' === source.content;
86
87
  }
87
- function StatePanel({ title, description, action }) {
88
+ function StatePanel({ title, description, action, icon }) {
88
89
  return /*#__PURE__*/ jsxs("div", {
89
90
  className: "ov-file-preview__state",
90
91
  role: "status",
91
92
  children: [
93
+ icon,
92
94
  /*#__PURE__*/ jsx("p", {
93
95
  className: "ov-file-preview__state-title",
94
96
  children: title
@@ -108,7 +110,10 @@ function EmptyFileState({ text }) {
108
110
  }
109
111
  function LoadingState({ text }) {
110
112
  return /*#__PURE__*/ jsx(StatePanel, {
111
- title: text.loading
113
+ title: text.loading ?? 'Loading…',
114
+ icon: /*#__PURE__*/ jsx("span", {
115
+ className: "ov-file-preview__spinner"
116
+ })
112
117
  });
113
118
  }
114
119
  function LoadFailedState({ text, description, onRetry }) {
@@ -167,6 +172,9 @@ function FilePreviewBody({ fileTab, text, locale, viewMode, editing, onViewModeC
167
172
  onChange: editing.updateDraft,
168
173
  onCancel: onCancelEditing
169
174
  });
175
+ if (fileTab.loading) return /*#__PURE__*/ jsx(LoadingState, {
176
+ text: text
177
+ });
170
178
  if (isEmptyFile(fileTab.source)) return /*#__PURE__*/ jsx(EmptyFileState, {
171
179
  text: text
172
180
  });
@@ -182,107 +190,6 @@ function FilePreviewBody({ fileTab, text, locale, viewMode, editing, onViewModeC
182
190
  onLinkClick: onLinkClick
183
191
  });
184
192
  }
185
- const OFFSET = 6;
186
- const VIEWPORT_MARGIN = 8;
187
- const OPPOSITE = {
188
- top: 'bottom',
189
- bottom: 'top',
190
- left: 'right',
191
- right: 'left'
192
- };
193
- function resolvePosition(trigger, surface, placement) {
194
- const viewportWidth = window.innerWidth;
195
- const viewportHeight = window.innerHeight;
196
- const fits = (side)=>{
197
- if ('top' === side) return trigger.top - surface.height - OFFSET >= VIEWPORT_MARGIN;
198
- if ('bottom' === side) return trigger.bottom + surface.height + OFFSET <= viewportHeight - VIEWPORT_MARGIN;
199
- if ('left' === side) return trigger.left - surface.width - OFFSET >= VIEWPORT_MARGIN;
200
- return trigger.right + surface.width + OFFSET <= viewportWidth - VIEWPORT_MARGIN;
201
- };
202
- const side = fits(placement) || !fits(OPPOSITE[placement]) ? placement : OPPOSITE[placement];
203
- const clamp = (value, size, limit)=>Math.min(Math.max(value, VIEWPORT_MARGIN), limit - size - VIEWPORT_MARGIN);
204
- if ('top' === side || 'bottom' === side) {
205
- const top = 'top' === side ? trigger.top - surface.height - OFFSET : trigger.bottom + OFFSET;
206
- const left = trigger.left + trigger.width / 2 - surface.width / 2;
207
- return {
208
- top: clamp(top, surface.height, viewportHeight),
209
- left: clamp(left, surface.width, viewportWidth),
210
- placement: side
211
- };
212
- }
213
- const left = 'left' === side ? trigger.left - surface.width - OFFSET : trigger.right + OFFSET;
214
- const top = trigger.top + trigger.height / 2 - surface.height / 2;
215
- return {
216
- top: clamp(top, surface.height, viewportHeight),
217
- left: clamp(left, surface.width, viewportWidth),
218
- placement: side
219
- };
220
- }
221
- function useTooltipPosition(open, triggerRef, surface, placement) {
222
- const [position, setPosition] = useState({
223
- top: 0,
224
- left: 0,
225
- placement
226
- });
227
- useLayoutEffect(()=>{
228
- if (!open) return;
229
- const trigger = triggerRef.current;
230
- if (!trigger || !surface) return;
231
- const written = new Set();
232
- const syncTheme = ()=>{
233
- const triggerStyle = window.getComputedStyle(trigger);
234
- const seen = new Set();
235
- for (const name of Array.from(triggerStyle)){
236
- if (!name.startsWith('--ov-ui-color-')) continue;
237
- const value = triggerStyle.getPropertyValue(name).trim();
238
- if (value) {
239
- seen.add(name);
240
- surface.style.setProperty(name, value);
241
- }
242
- }
243
- for (const name of written)if (!seen.has(name)) surface.style.removeProperty(name);
244
- written.clear();
245
- seen.forEach((name)=>written.add(name));
246
- };
247
- syncTheme();
248
- const themeObserver = new MutationObserver(syncTheme);
249
- const observerOptions = {
250
- attributes: true,
251
- attributeFilter: [
252
- 'class',
253
- 'style',
254
- 'data-theme'
255
- ]
256
- };
257
- for(let node = trigger; node; node = node.parentElement)themeObserver.observe(node, observerOptions);
258
- const update = ()=>{
259
- const triggerRect = trigger.getBoundingClientRect();
260
- const surfaceRect = surface.getBoundingClientRect();
261
- const next = resolvePosition(triggerRect, {
262
- width: surfaceRect.width,
263
- height: surfaceRect.height
264
- }, placement);
265
- setPosition((previous)=>previous.top === next.top && previous.left === next.left && previous.placement === next.placement ? previous : next);
266
- };
267
- update();
268
- const observer = new ResizeObserver(update);
269
- observer.observe(surface);
270
- window.addEventListener('scroll', update, true);
271
- window.addEventListener('resize', update);
272
- return ()=>{
273
- observer.disconnect();
274
- themeObserver.disconnect();
275
- window.removeEventListener('scroll', update, true);
276
- window.removeEventListener('resize', update);
277
- };
278
- }, [
279
- open,
280
- placement,
281
- surface,
282
- triggerRef
283
- ]);
284
- return position;
285
- }
286
193
  const DEFAULT_LABELS = {
287
194
  close: 'Close'
288
195
  };
@@ -307,7 +214,7 @@ function Tooltip({ children, content, placement = 'top', trigger = 'hover', dela
307
214
  const timerRef = useRef(void 0);
308
215
  const [surfaceNode, setSurfaceNode] = useState(null);
309
216
  const id = useId();
310
- const position = useTooltipPosition(open, triggerRef, surfaceNode, placement);
217
+ const position = useOverlayPosition(open, triggerRef, surfaceNode, placement);
311
218
  const change = useCallback((next)=>{
312
219
  setOpen(next);
313
220
  onOpenChange?.(next);
@@ -416,7 +323,7 @@ function Tooltip({ children, content, placement = 'top', trigger = 'hover', dela
416
323
  onMouseLeave: 'hover' === trigger ? hide : void 0,
417
324
  children: content
418
325
  }), document.body) : null;
419
- return /*#__PURE__*/ jsxs(jsx_runtime_Fragment, {
326
+ return /*#__PURE__*/ jsxs(Fragment, {
420
327
  children: [
421
328
  triggerElement,
422
329
  surface
@@ -597,7 +504,7 @@ function FilePreviewBreadcrumb({ segments, title, canOpen, disabled, onOpen }) {
597
504
  }) : null,
598
505
  segments.map((segment, index)=>{
599
506
  if (hiddenSegments.includes(segment)) return null;
600
- return /*#__PURE__*/ jsxs(Fragment, {
507
+ return /*#__PURE__*/ jsxs(external_react_Fragment, {
601
508
  children: [
602
509
  /*#__PURE__*/ jsxs("span", {
603
510
  className: "ov-file-preview__breadcrumb-part",
@@ -693,11 +600,9 @@ function getPathFileName(path) {
693
600
  const parts = trimmed.split(SEPARATOR).filter(Boolean);
694
601
  return parts[parts.length - 1];
695
602
  }
696
- function FilePreviewHeader({ fileTab, actions, text, onOpenParent }) {
697
- const path = fileTab.source.path;
603
+ function FilePreviewHeader({ path, fileName, canOpenParent, titleExtra, slotActions, actions, text, onOpenParent }) {
698
604
  const segments = splitPathSegments(path);
699
- const title = getPathFileName(path) ?? fileTab.source.fileName;
700
- const slotActions = fileTab.slots?.actions;
605
+ const title = getPathFileName(path) ?? fileName;
701
606
  const actionNode = 'function' == typeof slotActions ? slotActions(actions) : slotActions;
702
607
  return /*#__PURE__*/ jsxs("div", {
703
608
  className: "ov-file-preview__header",
@@ -708,7 +613,7 @@ function FilePreviewHeader({ fileTab, actions, text, onOpenParent }) {
708
613
  /*#__PURE__*/ jsx(FilePreviewBreadcrumb, {
709
614
  segments: segments,
710
615
  title: title,
711
- canOpen: Boolean(fileTab.operations?.openParent),
616
+ canOpen: canOpenParent,
712
617
  disabled: actions.busy,
713
618
  onOpen: onOpenParent
714
619
  }),
@@ -717,7 +622,7 @@ function FilePreviewHeader({ fileTab, actions, text, onOpenParent }) {
717
622
  disabled: actions.busy,
718
623
  onClick: ()=>void actions.copyPath()
719
624
  }) : null,
720
- fileTab.slots?.titleExtra
625
+ titleExtra
721
626
  ]
722
627
  }),
723
628
  actionNode ? /*#__PURE__*/ jsx("div", {
@@ -727,6 +632,214 @@ function FilePreviewHeader({ fileTab, actions, text, onOpenParent }) {
727
632
  ]
728
633
  });
729
634
  }
635
+ function levelToFileTab(tab, key) {
636
+ const level = tab.levels.find((candidate)=>candidate.key === key);
637
+ if (!level) return;
638
+ return {
639
+ kind: 'file',
640
+ key: `${tab.key}::${level.key}`,
641
+ source: level.source,
642
+ operations: tab.operations,
643
+ slots: tab.slots
644
+ };
645
+ }
646
+ function FilePreviewDirectoryBody({ tab, text, locale, actions, editing, viewMode, onViewModeChange, onHandleChange, onViewModesChange, onDownload, onCancelEditing }) {
647
+ const [internalKey, setInternalKey] = useState(()=>tab.defaultLevelKey ?? tab.levels[0].key);
648
+ const activeKey = tab.activeLevelKey ?? internalKey;
649
+ const fileTab = levelToFileTab(tab, activeKey) ?? levelToFileTab(tab, tab.levels[0].key);
650
+ const tabsRef = useRef(null);
651
+ const [indicator, setIndicator] = useState({
652
+ left: 0,
653
+ width: 0
654
+ });
655
+ useLayoutEffect(()=>{
656
+ const root = tabsRef.current;
657
+ if (!root) return;
658
+ const measure = ()=>{
659
+ const active = root.querySelector('[aria-selected="true"]');
660
+ if (!active) return;
661
+ setIndicator({
662
+ left: active.offsetLeft,
663
+ width: active.offsetWidth
664
+ });
665
+ };
666
+ measure();
667
+ const observer = new ResizeObserver(measure);
668
+ observer.observe(root);
669
+ return ()=>observer.disconnect();
670
+ }, [
671
+ activeKey,
672
+ tab.levels
673
+ ]);
674
+ const changeLevel = (key)=>{
675
+ if (void 0 === tab.activeLevelKey) setInternalKey(key);
676
+ tab.onActiveLevelChange?.(key);
677
+ };
678
+ const onLevelKeyDown = (event)=>{
679
+ const keys = [
680
+ 'ArrowLeft',
681
+ 'ArrowRight',
682
+ 'Home',
683
+ 'End'
684
+ ];
685
+ if (!keys.includes(event.key)) return;
686
+ const buttons = Array.from(event.currentTarget.querySelectorAll('[role="tab"]:not(:disabled)'));
687
+ if (0 === buttons.length) return;
688
+ const current = buttons.indexOf(event.target);
689
+ const next = 'Home' === event.key ? 0 : 'End' === event.key ? buttons.length - 1 : (current + ('ArrowRight' === event.key ? 1 : -1) + buttons.length) % buttons.length;
690
+ const target = buttons[next];
691
+ if (!target) return;
692
+ event.preventDefault();
693
+ target.focus();
694
+ const key = tab.levels[next]?.key;
695
+ if (void 0 !== key) changeLevel(key);
696
+ };
697
+ if (!fileTab) return null;
698
+ if (tab.loading) return /*#__PURE__*/ jsxs(Fragment, {
699
+ children: [
700
+ /*#__PURE__*/ jsx(FilePreviewHeader, {
701
+ path: fileTab.source.path,
702
+ fileName: fileTab.source.fileName,
703
+ canOpenParent: Boolean(tab.operations?.openParent),
704
+ titleExtra: tab.slots?.titleExtra,
705
+ slotActions: tab.slots?.actions,
706
+ actions: actions,
707
+ text: text,
708
+ onOpenParent: (uri)=>void tab.operations?.openParent?.(uri)
709
+ }),
710
+ /*#__PURE__*/ jsx("div", {
711
+ className: "ov-file-preview__body",
712
+ children: /*#__PURE__*/ jsx(LoadingState, {
713
+ text: text
714
+ })
715
+ })
716
+ ]
717
+ });
718
+ return /*#__PURE__*/ jsxs(Fragment, {
719
+ children: [
720
+ /*#__PURE__*/ jsx(FilePreviewHeader, {
721
+ path: fileTab.source.path,
722
+ fileName: fileTab.source.fileName,
723
+ canOpenParent: Boolean(tab.operations?.openParent),
724
+ titleExtra: tab.slots?.titleExtra,
725
+ slotActions: tab.slots?.actions,
726
+ actions: actions,
727
+ text: text,
728
+ onOpenParent: (uri)=>void tab.operations?.openParent?.(uri)
729
+ }),
730
+ tab.levels.length > 1 ? /*#__PURE__*/ jsxs("div", {
731
+ className: "ov-file-preview__levels",
732
+ role: "tablist",
733
+ ref: tabsRef,
734
+ tabIndex: -1,
735
+ onKeyDown: onLevelKeyDown,
736
+ children: [
737
+ tab.levels.map((level)=>/*#__PURE__*/ jsx("button", {
738
+ type: "button",
739
+ role: "tab",
740
+ "aria-selected": level.key === activeKey,
741
+ tabIndex: level.key === activeKey ? 0 : -1,
742
+ className: "ov-file-preview__level",
743
+ "data-active": level.key === activeKey || void 0,
744
+ onClick: ()=>changeLevel(level.key),
745
+ children: level.label
746
+ }, level.key)),
747
+ /*#__PURE__*/ jsx("span", {
748
+ "aria-hidden": "true",
749
+ className: "ov-file-preview__level-indicator",
750
+ style: {
751
+ transform: `translateX(${indicator.left}px)`,
752
+ width: indicator.width
753
+ }
754
+ })
755
+ ]
756
+ }) : null,
757
+ /*#__PURE__*/ jsx("div", {
758
+ className: "ov-file-preview__body",
759
+ children: /*#__PURE__*/ jsx(FilePreviewBody, {
760
+ fileTab: fileTab,
761
+ text: text,
762
+ locale: locale,
763
+ viewMode: viewMode,
764
+ editing: editing,
765
+ onViewModeChange: onViewModeChange,
766
+ onHandleChange: onHandleChange,
767
+ onViewModesChange: onViewModesChange,
768
+ onDownload: onDownload,
769
+ onCancelEditing: onCancelEditing
770
+ })
771
+ }),
772
+ tab.slots?.footer ? /*#__PURE__*/ jsx("div", {
773
+ className: "ov-file-preview__footer",
774
+ children: tab.slots.footer
775
+ }) : null
776
+ ]
777
+ });
778
+ }
779
+ function FilePreviewPanels({ contentTab, directoryTab, fileTab, panelProps, panelClass, text, locale, actions, actionContext, editing, viewMode, setViewMode, onHandleChange, onViewModesChange, linkClickHandler, activeTab }) {
780
+ if (contentTab) return /*#__PURE__*/ jsx("div", {
781
+ ...panelProps,
782
+ className: `${panelClass} ${panelClass}--content`,
783
+ children: contentTab.content
784
+ });
785
+ if (directoryTab) return /*#__PURE__*/ jsx("div", {
786
+ ...panelProps,
787
+ className: panelClass,
788
+ children: /*#__PURE__*/ jsx(FilePreviewDirectoryBody, {
789
+ tab: directoryTab,
790
+ text: text,
791
+ locale: locale,
792
+ actions: actionContext,
793
+ editing: editing,
794
+ viewMode: viewMode,
795
+ onViewModeChange: setViewMode,
796
+ onHandleChange: onHandleChange,
797
+ onViewModesChange: onViewModesChange,
798
+ onDownload: ()=>{},
799
+ onCancelEditing: actionContext.cancelEditing
800
+ })
801
+ });
802
+ if (!fileTab) return null;
803
+ return /*#__PURE__*/ jsxs("div", {
804
+ ...panelProps,
805
+ className: panelClass,
806
+ children: [
807
+ /*#__PURE__*/ jsx(FilePreviewHeader, {
808
+ path: fileTab.source.path,
809
+ fileName: fileTab.source.fileName,
810
+ canOpenParent: Boolean(fileTab.operations?.openParent),
811
+ titleExtra: fileTab.slots?.titleExtra,
812
+ slotActions: fileTab.slots?.actions,
813
+ actions: actionContext,
814
+ text: text,
815
+ onOpenParent: (uri)=>void actions.openParent(activeTab, uri)
816
+ }),
817
+ /*#__PURE__*/ jsx("div", {
818
+ className: "ov-file-preview__body",
819
+ children: /*#__PURE__*/ jsx(FilePreviewBody, {
820
+ fileTab: fileTab,
821
+ text: text,
822
+ locale: locale,
823
+ viewMode: viewMode,
824
+ editing: editing,
825
+ onViewModeChange: setViewMode,
826
+ onHandleChange: onHandleChange,
827
+ onViewModesChange: onViewModesChange,
828
+ onDownload: ()=>void actions.download(fileTab),
829
+ onLinkClick: linkClickHandler,
830
+ onCancelEditing: actionContext.cancelEditing
831
+ })
832
+ }),
833
+ fileTab.source.truncated ? /*#__PURE__*/ jsx(TruncatedNotice, {
834
+ text: text
835
+ }) : null,
836
+ fileTab.slots?.footer ? /*#__PURE__*/ jsx("div", {
837
+ className: "ov-file-preview__footer",
838
+ children: fileTab.slots.footer
839
+ }) : null
840
+ ]
841
+ });
842
+ }
730
843
  const file_preview_labels_DEFAULT_LABELS = {
731
844
  copyPath: 'Copy path',
732
845
  editor: 'Edit content',
@@ -878,10 +991,10 @@ function useFilePreviewActions() {
878
991
  notify?.(value);
879
992
  }
880
993
  return {
881
- openParent: (tab, uri)=>'file' === tab.kind ? run(`openParent:${tab.key}`, {
994
+ openParent: (tab, uri)=>'content' === tab.kind ? Promise.resolve() : run(`openParent:${tab.key}`, {
882
995
  execute: tab.operations?.openParent,
883
996
  notify: tab.onOpenParent
884
- }, uri) : Promise.resolve(),
997
+ }, uri),
885
998
  download: (tab)=>run(`download:${tab.key}`, {
886
999
  execute: tab.operations?.download,
887
1000
  notify: tab.onDownload
@@ -891,10 +1004,10 @@ function useFilePreviewActions() {
891
1004
  notify: tab.onOpenUri
892
1005
  }, uri),
893
1006
  copyPath: (tab, path)=>copyText(path, tab.onCopyPath),
894
- copyContent: (tab, text)=>copyText(text, tab.onCopyContent)
1007
+ copyContent: (tab, text)=>copyText(text, 'onCopyContent' in tab ? tab.onCopyContent : void 0)
895
1008
  };
896
1009
  }
897
- function useFilePreviewActionsContext({ activeTab, fileTab, viewMode, canSwitchView, setViewMode, editing, operations }) {
1010
+ function useFilePreviewActionsContext({ activeTab, fileTab, currentPath, currentSource, viewMode, canSwitchView, setViewMode, editing, operations }) {
898
1011
  const startEditing = useCallback(()=>{
899
1012
  if (!fileTab) return;
900
1013
  setViewMode('source');
@@ -922,21 +1035,22 @@ function useFilePreviewActionsContext({ activeTab, fileTab, viewMode, canSwitchV
922
1035
  editing,
923
1036
  setViewMode
924
1037
  ]);
1038
+ const copyable = currentSource ? readCopyableText(currentSource) : void 0;
925
1039
  const copyContent = useCallback(async ()=>{
926
- const copyable = fileTab && readCopyableText(fileTab.source);
927
- if (!fileTab || !copyable) return false;
928
- return operations.copyContent(fileTab, copyable);
1040
+ if (!copyable) return false;
1041
+ return operations.copyContent(activeTab, copyable);
929
1042
  }, [
930
- fileTab,
1043
+ activeTab,
1044
+ copyable,
931
1045
  operations
932
1046
  ]);
933
1047
  const copyPath = useCallback(async ()=>{
934
- const path = fileTab?.source.path;
1048
+ const path = currentPath;
935
1049
  if (!path) return false;
936
1050
  return operations.copyPath(activeTab, path);
937
1051
  }, [
938
1052
  activeTab,
939
- fileTab,
1053
+ currentPath,
940
1054
  operations
941
1055
  ]);
942
1056
  const download = useCallback(()=>{
@@ -955,9 +1069,9 @@ function useFilePreviewActionsContext({ activeTab, fileTab, viewMode, canSwitchV
955
1069
  startEditing,
956
1070
  saveEditing,
957
1071
  cancelEditing,
958
- canCopyContent: Boolean(fileTab && readCopyableText(fileTab.source)),
1072
+ canCopyContent: Boolean(copyable),
959
1073
  copyContent,
960
- canCopyPath: Boolean(fileTab?.source.path),
1074
+ canCopyPath: Boolean(currentPath),
961
1075
  copyPath,
962
1076
  canDownload: Boolean(fileTab?.operations?.download),
963
1077
  download
@@ -977,6 +1091,32 @@ function useFilePreviewIds(activeKey) {
977
1091
  }
978
1092
  };
979
1093
  }
1094
+ function initialLevelKey(tab, remembered, tabKey) {
1095
+ const preferred = tab.activeLevelKey ?? remembered[tabKey] ?? tab.defaultLevelKey;
1096
+ const first = tab.levels[0]?.key ?? '';
1097
+ if (void 0 === preferred) return first;
1098
+ return tab.levels.some((level)=>level.key === preferred) ? preferred : first;
1099
+ }
1100
+ function useDirectoryLevel(tab) {
1101
+ const [levelKeys, setLevelKeys] = useState({});
1102
+ if (!tab) return {};
1103
+ const activeLevel = tab.levels.find((level)=>level.key === initialLevelKey(tab, levelKeys, tab.key)) ?? tab.levels[0];
1104
+ return {
1105
+ activeLevel,
1106
+ directoryTab: {
1107
+ ...tab,
1108
+ activeLevelKey: activeLevel.key,
1109
+ onActiveLevelChange: (key)=>{
1110
+ if (void 0 === tab.activeLevelKey) setLevelKeys((previous)=>({
1111
+ ...previous,
1112
+ [tab.key]: key
1113
+ }));
1114
+ tab.onActiveLevelChange?.(key);
1115
+ }
1116
+ },
1117
+ source: activeLevel.source
1118
+ };
1119
+ }
980
1120
  function useFilePreviewEditing(activeTabKey) {
981
1121
  const [editing, setEditing] = useState(false);
982
1122
  const [loadingEdit, setLoadingEdit] = useState(false);
@@ -1090,7 +1230,8 @@ const file_preview_FilePreview = /*#__PURE__*/ forwardRef(function({ tabs, activ
1090
1230
  ...activeTab.labels
1091
1231
  };
1092
1232
  const fileTab = isFileTab(activeTab) ? activeTab : void 0;
1093
- const contentTab = fileTab ? void 0 : activeTab;
1233
+ const directoryTab = 'directory' === activeTab.kind ? activeTab : void 0;
1234
+ const contentTab = fileTab || directoryTab ? void 0 : activeTab;
1094
1235
  const switchTab = useCallback((key)=>{
1095
1236
  if (editing.saving) return false;
1096
1237
  if (key === currentKey && key === activeTab.key) return false;
@@ -1138,9 +1279,14 @@ const file_preview_FilePreview = /*#__PURE__*/ forwardRef(function({ tabs, activ
1138
1279
  fileTab
1139
1280
  ]);
1140
1281
  const linkClickHandler = fileTab?.operations?.openUri ? onLinkClick : void 0;
1282
+ const level = useDirectoryLevel(directoryTab);
1283
+ const currentPath = level.source?.path ?? fileTab?.source.path;
1284
+ const currentSource = level.source ?? fileTab?.source;
1141
1285
  const actionContext = useFilePreviewActionsContext({
1142
1286
  activeTab,
1143
1287
  fileTab,
1288
+ currentPath,
1289
+ currentSource,
1144
1290
  viewMode,
1145
1291
  canSwitchView,
1146
1292
  setViewMode,
@@ -1162,46 +1308,25 @@ const file_preview_FilePreview = /*#__PURE__*/ forwardRef(function({ tabs, activ
1162
1308
  panelId: panelId,
1163
1309
  onSelect: (key)=>void switchTab(key)
1164
1310
  }),
1165
- contentTab ? /*#__PURE__*/ jsx("div", {
1166
- ...panelProps,
1167
- className: `${panelClass} ${panelClass}--content`,
1168
- children: contentTab.content
1169
- }) : fileTab ? /*#__PURE__*/ jsxs("div", {
1170
- ...panelProps,
1171
- className: panelClass,
1172
- children: [
1173
- /*#__PURE__*/ jsx(FilePreviewHeader, {
1174
- fileTab: fileTab,
1175
- actions: actionContext,
1176
- text: tabText,
1177
- onOpenParent: (uri)=>void actions.openParent(activeTab, uri)
1178
- }),
1179
- /*#__PURE__*/ jsx("div", {
1180
- className: "ov-file-preview__body",
1181
- children: /*#__PURE__*/ jsx(FilePreviewBody, {
1182
- fileTab: fileTab,
1183
- text: tabText,
1184
- locale: locale,
1185
- viewMode: viewMode,
1186
- editing: editing,
1187
- onViewModeChange: setViewMode,
1188
- onHandleChange: onHandleChange,
1189
- onViewModesChange: onViewModesChange,
1190
- onDownload: ()=>void actions.download(fileTab),
1191
- onLinkClick: linkClickHandler,
1192
- onCancelEditing: actionContext.cancelEditing
1193
- })
1194
- }),
1195
- fileTab.source.truncated ? /*#__PURE__*/ jsx(TruncatedNotice, {
1196
- text: tabText
1197
- }) : null,
1198
- fileTab.slots?.footer ? /*#__PURE__*/ jsx("div", {
1199
- className: "ov-file-preview__footer",
1200
- children: fileTab.slots.footer
1201
- }) : null
1202
- ]
1203
- }) : null
1311
+ /*#__PURE__*/ jsx(FilePreviewPanels, {
1312
+ contentTab: contentTab,
1313
+ directoryTab: level.directoryTab,
1314
+ fileTab: fileTab,
1315
+ panelProps: panelProps,
1316
+ panelClass: panelClass,
1317
+ text: tabText,
1318
+ locale: locale,
1319
+ actions: actions,
1320
+ actionContext: actionContext,
1321
+ editing: editing,
1322
+ viewMode: viewMode,
1323
+ setViewMode: setViewMode,
1324
+ onHandleChange: onHandleChange,
1325
+ onViewModesChange: onViewModesChange,
1326
+ linkClickHandler: linkClickHandler,
1327
+ activeTab: activeTab
1328
+ })
1204
1329
  ]
1205
1330
  });
1206
1331
  });
1207
- export { LoadFailedState, LoadingState, UnsupportedState, file_preview_FilePreview as FilePreview, toFileSource };
1332
+ export { LoadFailedState, LoadingState, Tooltip, UnsupportedState, file_preview_FilePreview as FilePreview, toFileSource };
@@ -1,4 +1,5 @@
1
1
  export { createOvClient } from './client.js';
2
2
  export { OvClientError, isOvClientError } from './errors.js';
3
+ export { OV_PATHS, OV_PATH_BUILDERS, type OvPath } from './paths.js';
3
4
  export { OpenVikingProvider, type OpenVikingProviderProps, } from './provider.js';
4
- export type { OvClient, OvClientOptions, OvErrorEnvelope, OvIdentityValue, OvQueryValue, OvRequestOptions, OvRequestSpec, OvResolvedOptions, OvSuccessEnvelope, } from './types.js';
5
+ export type { OvClient, OvClientOptions, OvErrorEnvelope, OvIdentityValue, OvQueryValue, OvRequestOptions, OvRequestSpec, OvResolvedOptions, OvResponseEnvelope, OvResponseType, OvStream, OvStreamEvent, OvStreamSpec, OvSuccessEnvelope, } from './types.js';