@miethe/ui 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +77 -0
- package/README.md +1536 -0
- package/dist/bulk-actions/Button.d.ts +28 -0
- package/dist/bulk-actions/Button.d.ts.map +1 -0
- package/dist/bulk-actions/Button.js +45 -0
- package/dist/bulk-actions/Button.js.map +1 -0
- package/dist/bulk-actions/bulk-action-bar.d.ts +91 -0
- package/dist/bulk-actions/bulk-action-bar.d.ts.map +1 -0
- package/dist/bulk-actions/bulk-action-bar.js +94 -0
- package/dist/bulk-actions/bulk-action-bar.js.map +1 -0
- package/dist/bulk-actions/index.d.ts +5 -0
- package/dist/bulk-actions/index.d.ts.map +1 -0
- package/dist/bulk-actions/index.js +7 -0
- package/dist/bulk-actions/index.js.map +1 -0
- package/dist/bulk-actions/utils.d.ts +6 -0
- package/dist/bulk-actions/utils.d.ts.map +1 -0
- package/dist/bulk-actions/utils.js +9 -0
- package/dist/bulk-actions/utils.js.map +1 -0
- package/dist/components/ui/alert.d.ts +9 -0
- package/dist/components/ui/alert.d.ts.map +1 -0
- package/dist/components/ui/alert.js +23 -0
- package/dist/components/ui/alert.js.map +1 -0
- package/dist/components/ui/button.d.ts +12 -0
- package/dist/components/ui/button.d.ts.map +1 -0
- package/dist/components/ui/button.js +34 -0
- package/dist/components/ui/button.js.map +1 -0
- package/dist/components/ui/collapsible.d.ts +6 -0
- package/dist/components/ui/collapsible.d.ts.map +1 -0
- package/dist/components/ui/collapsible.js +7 -0
- package/dist/components/ui/collapsible.js.map +1 -0
- package/dist/components/ui/skeleton.d.ts +4 -0
- package/dist/components/ui/skeleton.d.ts.map +1 -0
- package/dist/components/ui/skeleton.js +7 -0
- package/dist/components/ui/skeleton.js.map +1 -0
- package/dist/content-viewer/ContentPane.d.ts +107 -0
- package/dist/content-viewer/ContentPane.d.ts.map +1 -0
- package/dist/content-viewer/ContentPane.js +247 -0
- package/dist/content-viewer/ContentPane.js.map +1 -0
- package/dist/content-viewer/ContentViewerProvider.d.ts +83 -0
- package/dist/content-viewer/ContentViewerProvider.d.ts.map +1 -0
- package/dist/content-viewer/ContentViewerProvider.js +92 -0
- package/dist/content-viewer/ContentViewerProvider.js.map +1 -0
- package/dist/content-viewer/FileTree.d.ts +71 -0
- package/dist/content-viewer/FileTree.d.ts.map +1 -0
- package/dist/content-viewer/FileTree.js +294 -0
- package/dist/content-viewer/FileTree.js.map +1 -0
- package/dist/content-viewer/adapters.d.ts +101 -0
- package/dist/content-viewer/adapters.d.ts.map +1 -0
- package/dist/content-viewer/adapters.js +32 -0
- package/dist/content-viewer/adapters.js.map +1 -0
- package/dist/content-viewer/index.d.ts +8 -0
- package/dist/content-viewer/index.d.ts.map +1 -0
- package/dist/content-viewer/index.js +5 -0
- package/dist/content-viewer/index.js.map +1 -0
- package/dist/diff/DiffViewer.d.ts +112 -0
- package/dist/diff/DiffViewer.d.ts.map +1 -0
- package/dist/diff/DiffViewer.js +414 -0
- package/dist/diff/DiffViewer.js.map +1 -0
- package/dist/diff/diff.d.ts +32 -0
- package/dist/diff/diff.d.ts.map +1 -0
- package/dist/diff/diff.js +8 -0
- package/dist/diff/diff.js.map +1 -0
- package/dist/diff/index.d.ts +4 -0
- package/dist/diff/index.d.ts.map +1 -0
- package/dist/diff/index.js +3 -0
- package/dist/diff/index.js.map +1 -0
- package/dist/display/FilePreviewPane.d.ts +31 -0
- package/dist/display/FilePreviewPane.d.ts.map +1 -0
- package/dist/display/FilePreviewPane.js +144 -0
- package/dist/display/FilePreviewPane.js.map +1 -0
- package/dist/display/FrontmatterDisplay.d.ts +33 -0
- package/dist/display/FrontmatterDisplay.d.ts.map +1 -0
- package/dist/display/FrontmatterDisplay.js +79 -0
- package/dist/display/FrontmatterDisplay.js.map +1 -0
- package/dist/display/index.d.ts +5 -0
- package/dist/display/index.d.ts.map +1 -0
- package/dist/display/index.js +4 -0
- package/dist/display/index.js.map +1 -0
- package/dist/editor/MarkdownEditor.d.ts +28 -0
- package/dist/editor/MarkdownEditor.d.ts.map +1 -0
- package/dist/editor/MarkdownEditor.js +160 -0
- package/dist/editor/MarkdownEditor.js.map +1 -0
- package/dist/editor/SplitPreview.d.ts +28 -0
- package/dist/editor/SplitPreview.d.ts.map +1 -0
- package/dist/editor/SplitPreview.js +34 -0
- package/dist/editor/SplitPreview.js.map +1 -0
- package/dist/editor/index.d.ts +5 -0
- package/dist/editor/index.d.ts.map +1 -0
- package/dist/editor/index.js +4 -0
- package/dist/editor/index.js.map +1 -0
- package/dist/filters/filters-dropdown.d.ts +24 -0
- package/dist/filters/filters-dropdown.d.ts.map +1 -0
- package/dist/filters/filters-dropdown.js +36 -0
- package/dist/filters/filters-dropdown.js.map +1 -0
- package/dist/filters/index.d.ts +9 -0
- package/dist/filters/index.d.ts.map +1 -0
- package/dist/filters/index.js +5 -0
- package/dist/filters/index.js.map +1 -0
- package/dist/filters/sort-dropdown.d.ts +13 -0
- package/dist/filters/sort-dropdown.d.ts.map +1 -0
- package/dist/filters/sort-dropdown.js +20 -0
- package/dist/filters/sort-dropdown.js.map +1 -0
- package/dist/filters/tag-filter-popover.d.ts +39 -0
- package/dist/filters/tag-filter-popover.d.ts.map +1 -0
- package/dist/filters/tag-filter-popover.js +72 -0
- package/dist/filters/tag-filter-popover.js.map +1 -0
- package/dist/filters/tool-filter-popover.d.ts +42 -0
- package/dist/filters/tool-filter-popover.d.ts.map +1 -0
- package/dist/filters/tool-filter-popover.js +67 -0
- package/dist/filters/tool-filter-popover.js.map +1 -0
- package/dist/hooks/use-debounce.d.ts +9 -0
- package/dist/hooks/use-debounce.d.ts.map +1 -0
- package/dist/hooks/use-debounce.js +21 -0
- package/dist/hooks/use-debounce.js.map +1 -0
- package/dist/hooks/use-intersection-observer.d.ts +11 -0
- package/dist/hooks/use-intersection-observer.d.ts.map +1 -0
- package/dist/hooks/use-intersection-observer.js +25 -0
- package/dist/hooks/use-intersection-observer.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/pickers/EntityPickerDialog.d.ts +233 -0
- package/dist/pickers/EntityPickerDialog.d.ts.map +1 -0
- package/dist/pickers/EntityPickerDialog.js +355 -0
- package/dist/pickers/EntityPickerDialog.js.map +1 -0
- package/dist/pickers/EntityPickerViewToggle.d.ts +8 -0
- package/dist/pickers/EntityPickerViewToggle.d.ts.map +1 -0
- package/dist/pickers/EntityPickerViewToggle.js +17 -0
- package/dist/pickers/EntityPickerViewToggle.js.map +1 -0
- package/dist/pickers/index.d.ts +5 -0
- package/dist/pickers/index.d.ts.map +1 -0
- package/dist/pickers/index.js +3 -0
- package/dist/pickers/index.js.map +1 -0
- package/dist/primitives/Badge.d.ts +16 -0
- package/dist/primitives/Badge.d.ts.map +1 -0
- package/dist/primitives/Badge.js +43 -0
- package/dist/primitives/Badge.js.map +1 -0
- package/dist/primitives/BaseArtifactModal.d.ts +114 -0
- package/dist/primitives/BaseArtifactModal.d.ts.map +1 -0
- package/dist/primitives/BaseArtifactModal.js +76 -0
- package/dist/primitives/BaseArtifactModal.js.map +1 -0
- package/dist/primitives/Dialog.d.ts +20 -0
- package/dist/primitives/Dialog.d.ts.map +1 -0
- package/dist/primitives/Dialog.js +24 -0
- package/dist/primitives/Dialog.js.map +1 -0
- package/dist/primitives/DropdownMenu.d.ts +28 -0
- package/dist/primitives/DropdownMenu.d.ts.map +1 -0
- package/dist/primitives/DropdownMenu.js +34 -0
- package/dist/primitives/DropdownMenu.js.map +1 -0
- package/dist/primitives/EnterpriseOwnerBadge.d.ts +9 -0
- package/dist/primitives/EnterpriseOwnerBadge.d.ts.map +1 -0
- package/dist/primitives/EnterpriseOwnerBadge.js +12 -0
- package/dist/primitives/EnterpriseOwnerBadge.js.map +1 -0
- package/dist/primitives/GroupedSelect.d.ts +30 -0
- package/dist/primitives/GroupedSelect.d.ts.map +1 -0
- package/dist/primitives/GroupedSelect.js +47 -0
- package/dist/primitives/GroupedSelect.js.map +1 -0
- package/dist/primitives/Input.d.ts +6 -0
- package/dist/primitives/Input.d.ts.map +1 -0
- package/dist/primitives/Input.js +9 -0
- package/dist/primitives/Input.js.map +1 -0
- package/dist/primitives/LockIcon.d.ts +11 -0
- package/dist/primitives/LockIcon.d.ts.map +1 -0
- package/dist/primitives/LockIcon.js +15 -0
- package/dist/primitives/LockIcon.js.map +1 -0
- package/dist/primitives/MaskedSecretInput.d.ts +16 -0
- package/dist/primitives/MaskedSecretInput.d.ts.map +1 -0
- package/dist/primitives/MaskedSecretInput.js +42 -0
- package/dist/primitives/MaskedSecretInput.js.map +1 -0
- package/dist/primitives/ModalHeader.d.ts +66 -0
- package/dist/primitives/ModalHeader.d.ts.map +1 -0
- package/dist/primitives/ModalHeader.js +58 -0
- package/dist/primitives/ModalHeader.js.map +1 -0
- package/dist/primitives/Popover.d.ts +9 -0
- package/dist/primitives/Popover.d.ts.map +1 -0
- package/dist/primitives/Popover.js +13 -0
- package/dist/primitives/Popover.js.map +1 -0
- package/dist/primitives/ScrollArea.d.ts +6 -0
- package/dist/primitives/ScrollArea.d.ts.map +1 -0
- package/dist/primitives/ScrollArea.js +11 -0
- package/dist/primitives/ScrollArea.js.map +1 -0
- package/dist/primitives/SearchableCombobox.d.ts +30 -0
- package/dist/primitives/SearchableCombobox.d.ts.map +1 -0
- package/dist/primitives/SearchableCombobox.js +124 -0
- package/dist/primitives/SearchableCombobox.js.map +1 -0
- package/dist/primitives/SearchablePickerDialog.d.ts +20 -0
- package/dist/primitives/SearchablePickerDialog.d.ts.map +1 -0
- package/dist/primitives/SearchablePickerDialog.js +78 -0
- package/dist/primitives/SearchablePickerDialog.js.map +1 -0
- package/dist/primitives/StatusBadge.d.ts +21 -0
- package/dist/primitives/StatusBadge.d.ts.map +1 -0
- package/dist/primitives/StatusBadge.js +25 -0
- package/dist/primitives/StatusBadge.js.map +1 -0
- package/dist/primitives/TabNavigation.d.ts +68 -0
- package/dist/primitives/TabNavigation.d.ts.map +1 -0
- package/dist/primitives/TabNavigation.js +74 -0
- package/dist/primitives/TabNavigation.js.map +1 -0
- package/dist/primitives/Tabs.d.ts +8 -0
- package/dist/primitives/Tabs.d.ts.map +1 -0
- package/dist/primitives/Tabs.js +14 -0
- package/dist/primitives/Tabs.js.map +1 -0
- package/dist/primitives/Tooltip.d.ts +8 -0
- package/dist/primitives/Tooltip.d.ts.map +1 -0
- package/dist/primitives/Tooltip.js +12 -0
- package/dist/primitives/Tooltip.js.map +1 -0
- package/dist/primitives/VerticalTabNavigation.d.ts +75 -0
- package/dist/primitives/VerticalTabNavigation.d.ts.map +1 -0
- package/dist/primitives/VerticalTabNavigation.js +166 -0
- package/dist/primitives/VerticalTabNavigation.js.map +1 -0
- package/dist/primitives/ViewModeToggle.d.ts +12 -0
- package/dist/primitives/ViewModeToggle.d.ts.map +1 -0
- package/dist/primitives/ViewModeToggle.js +56 -0
- package/dist/primitives/ViewModeToggle.js.map +1 -0
- package/dist/primitives/WizardShell.d.ts +81 -0
- package/dist/primitives/WizardShell.d.ts.map +1 -0
- package/dist/primitives/WizardShell.js +73 -0
- package/dist/primitives/WizardShell.js.map +1 -0
- package/dist/primitives/index.d.ts +38 -0
- package/dist/primitives/index.d.ts.map +1 -0
- package/dist/primitives/index.js +24 -0
- package/dist/primitives/index.js.map +1 -0
- package/dist/primitives/utils.d.ts +6 -0
- package/dist/primitives/utils.d.ts.map +1 -0
- package/dist/primitives/utils.js +9 -0
- package/dist/primitives/utils.js.map +1 -0
- package/dist/types/index.d.ts +63 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +9 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/frontmatter.d.ts +63 -0
- package/dist/utils/frontmatter.d.ts.map +1 -0
- package/dist/utils/frontmatter.js +345 -0
- package/dist/utils/frontmatter.js.map +1 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/perf-marks.d.ts +28 -0
- package/dist/utils/perf-marks.d.ts.map +1 -0
- package/dist/utils/perf-marks.js +45 -0
- package/dist/utils/perf-marks.js.map +1 -0
- package/dist/utils/readme-utils.d.ts +67 -0
- package/dist/utils/readme-utils.d.ts.map +1 -0
- package/dist/utils/readme-utils.js +164 -0
- package/dist/utils/readme-utils.js.map +1 -0
- package/dist/utils/type-colors.d.ts +70 -0
- package/dist/utils/type-colors.d.ts.map +1 -0
- package/dist/utils/type-colors.js +118 -0
- package/dist/utils/type-colors.js.map +1 -0
- package/package.json +131 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState, useCallback, useRef, useEffect } from 'react';
|
|
4
|
+
import { ChevronRight, ChevronDown, Folder, FolderOpen, FileText, FileCode, File, Braces, Trash2, Plus, } from 'lucide-react';
|
|
5
|
+
import { cn } from '../primitives/utils';
|
|
6
|
+
import { Button } from '../components/ui/button';
|
|
7
|
+
import { Skeleton } from '../components/ui/skeleton';
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Helper Functions
|
|
10
|
+
// ============================================================================
|
|
11
|
+
/**
|
|
12
|
+
* Get the appropriate icon for a file based on its extension
|
|
13
|
+
*/
|
|
14
|
+
function getFileIcon(fileName) {
|
|
15
|
+
const extension = fileName.split('.').pop()?.toLowerCase();
|
|
16
|
+
switch (extension) {
|
|
17
|
+
case 'md':
|
|
18
|
+
case 'txt':
|
|
19
|
+
return FileText;
|
|
20
|
+
case 'ts':
|
|
21
|
+
case 'tsx':
|
|
22
|
+
case 'js':
|
|
23
|
+
case 'jsx':
|
|
24
|
+
case 'py':
|
|
25
|
+
case 'java':
|
|
26
|
+
case 'cpp':
|
|
27
|
+
case 'c':
|
|
28
|
+
case 'go':
|
|
29
|
+
case 'rs':
|
|
30
|
+
return FileCode;
|
|
31
|
+
case 'json':
|
|
32
|
+
return Braces;
|
|
33
|
+
default:
|
|
34
|
+
return File;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// ============================================================================
|
|
38
|
+
// Helper: Flatten tree to ordered list for keyboard navigation
|
|
39
|
+
// ============================================================================
|
|
40
|
+
/**
|
|
41
|
+
* Flatten tree nodes into a linear list for keyboard navigation.
|
|
42
|
+
* Only includes visible nodes (respects expanded state).
|
|
43
|
+
*/
|
|
44
|
+
function flattenVisibleNodes(nodes, expandedPaths) {
|
|
45
|
+
const result = [];
|
|
46
|
+
function traverse(nodeList) {
|
|
47
|
+
for (const node of nodeList) {
|
|
48
|
+
result.push(node);
|
|
49
|
+
if (node.type === 'directory' && expandedPaths.has(node.path) && node.children) {
|
|
50
|
+
traverse(node.children);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
traverse(nodes);
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
function TreeNode({ node, level, selectedPath, focusedPath, expandedPaths, onSelect, onToggle, onDelete, onFocus, onKeyNavigation, treeSize, positionInSet, }) {
|
|
58
|
+
const nodeRef = useRef(null);
|
|
59
|
+
const isExpanded = expandedPaths.has(node.path);
|
|
60
|
+
const isSelected = selectedPath === node.path;
|
|
61
|
+
const isFocused = focusedPath === node.path;
|
|
62
|
+
const isDirectory = node.type === 'directory';
|
|
63
|
+
// Focus the element when it becomes the focused item (roving tabindex)
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
if (isFocused && nodeRef.current) {
|
|
66
|
+
nodeRef.current.focus();
|
|
67
|
+
}
|
|
68
|
+
}, [isFocused]);
|
|
69
|
+
const handleClick = useCallback(() => {
|
|
70
|
+
onFocus(node.path);
|
|
71
|
+
if (isDirectory) {
|
|
72
|
+
onToggle(node.path);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
onSelect(node.path);
|
|
76
|
+
}
|
|
77
|
+
}, [isDirectory, node.path, onSelect, onToggle, onFocus]);
|
|
78
|
+
const handleKeyDown = useCallback((e) => {
|
|
79
|
+
// Handle Enter and Space for activation
|
|
80
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
81
|
+
e.preventDefault();
|
|
82
|
+
if (isDirectory) {
|
|
83
|
+
onToggle(node.path);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
onSelect(node.path);
|
|
87
|
+
}
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
// Handle ArrowRight to expand directory
|
|
91
|
+
if (e.key === 'ArrowRight' && isDirectory) {
|
|
92
|
+
e.preventDefault();
|
|
93
|
+
if (!isExpanded) {
|
|
94
|
+
onToggle(node.path);
|
|
95
|
+
}
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
// Handle ArrowLeft to collapse directory
|
|
99
|
+
if (e.key === 'ArrowLeft' && isDirectory && isExpanded) {
|
|
100
|
+
e.preventDefault();
|
|
101
|
+
onToggle(node.path);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
// Delegate Up/Down/Home/End navigation to parent
|
|
105
|
+
onKeyNavigation(e, node);
|
|
106
|
+
}, [isDirectory, isExpanded, node, onSelect, onToggle, onKeyNavigation]);
|
|
107
|
+
const handleDelete = useCallback((e) => {
|
|
108
|
+
e.stopPropagation();
|
|
109
|
+
if (onDelete) {
|
|
110
|
+
onDelete(node.path);
|
|
111
|
+
}
|
|
112
|
+
}, [node.path, onDelete]);
|
|
113
|
+
const IconComponent = isDirectory ? (isExpanded ? FolderOpen : Folder) : getFileIcon(node.name);
|
|
114
|
+
return (_jsxs("div", { role: "none", children: [_jsxs("div", { ref: nodeRef, role: "treeitem", tabIndex: isFocused ? 0 : -1, "aria-selected": isSelected, "aria-expanded": isDirectory ? isExpanded : undefined, "aria-level": level + 1, "aria-setsize": treeSize, "aria-posinset": positionInSet, "data-testid": `tree-item-${node.path}`, className: cn('group flex cursor-pointer items-center gap-1 rounded px-2 py-1 transition-colors hover:bg-accent', isSelected && 'bg-accent text-accent-foreground', 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1'), style: { paddingLeft: `${level * 12 + 8}px` }, onClick: handleClick, onKeyDown: handleKeyDown, onFocus: () => onFocus(node.path), children: [isDirectory ? (_jsx("span", { className: "flex-shrink-0", "aria-hidden": "true", children: isExpanded ? (_jsx(ChevronDown, { className: "h-4 w-4 text-muted-foreground" })) : (_jsx(ChevronRight, { className: "h-4 w-4 text-muted-foreground" })) })) : (_jsx("span", { className: "w-4 flex-shrink-0", "aria-hidden": "true" })), _jsx(IconComponent, { className: cn('h-4 w-4 flex-shrink-0', isDirectory ? 'text-blue-500' : 'text-muted-foreground'), "aria-hidden": "true" }), _jsx("span", { className: "min-w-0 flex-1 truncate text-sm", children: node.name }), onDelete && !isDirectory && (_jsx(Button, { variant: "ghost", size: "icon", className: "h-6 w-6 opacity-0 transition-opacity focus:opacity-100 group-hover:opacity-100", onClick: handleDelete, "aria-label": `Delete ${node.name}`, tabIndex: -1, children: _jsx(Trash2, { className: "h-3 w-3", "aria-hidden": "true" }) }))] }), isDirectory && isExpanded && node.children && (_jsx("div", { role: "group", "aria-label": `Contents of ${node.name}`, children: node.children.map((child, index) => {
|
|
115
|
+
// Calculate position in the flattened visible list
|
|
116
|
+
// This is a simplified version - the parent handles the full calculation
|
|
117
|
+
return (_jsx(TreeNode, { node: child, level: level + 1, selectedPath: selectedPath, focusedPath: focusedPath, expandedPaths: expandedPaths, onSelect: onSelect, onToggle: onToggle, onDelete: onDelete, onFocus: onFocus, onKeyNavigation: onKeyNavigation, treeSize: treeSize, positionInSet: index + 1 }, child.path));
|
|
118
|
+
}) }))] }));
|
|
119
|
+
}
|
|
120
|
+
// ============================================================================
|
|
121
|
+
// Loading Skeleton
|
|
122
|
+
// ============================================================================
|
|
123
|
+
function FileTreeSkeleton() {
|
|
124
|
+
return (_jsx("div", { className: "space-y-2 p-2", children: [...Array(8)].map((_, i) => (_jsxs("div", { className: "flex items-center gap-2", style: { paddingLeft: `${(i % 3) * 12 + 8}px` }, children: [_jsx(Skeleton, { className: "h-4 w-4" }), _jsx(Skeleton, { className: "h-4 flex-1" })] }, i))) }));
|
|
125
|
+
}
|
|
126
|
+
// ============================================================================
|
|
127
|
+
// Main Component
|
|
128
|
+
// ============================================================================
|
|
129
|
+
/**
|
|
130
|
+
* FileTree - Recursive file browser component
|
|
131
|
+
*
|
|
132
|
+
* Displays a hierarchical tree of files and directories with expand/collapse functionality.
|
|
133
|
+
* Supports keyboard navigation, file selection, and optional delete actions.
|
|
134
|
+
*
|
|
135
|
+
* Features:
|
|
136
|
+
* - Recursive rendering of nested directories
|
|
137
|
+
* - Expandable/collapsible folders with chevron icons
|
|
138
|
+
* - File type icons (markdown, code, JSON, etc.)
|
|
139
|
+
* - Selected file highlighting
|
|
140
|
+
* - Full keyboard navigation (Arrow keys, Enter, Space, Home, End)
|
|
141
|
+
* - ARIA tree pattern for screen reader accessibility
|
|
142
|
+
* - Roving tabindex for efficient keyboard focus management
|
|
143
|
+
* - Optional context actions (delete)
|
|
144
|
+
* - Loading skeleton state
|
|
145
|
+
* - Read-only mode (hides create/delete buttons)
|
|
146
|
+
*
|
|
147
|
+
* Keyboard Controls:
|
|
148
|
+
* - ArrowUp/ArrowDown: Move focus between visible items
|
|
149
|
+
* - ArrowRight: Expand folder (if collapsed) or move to first child
|
|
150
|
+
* - ArrowLeft: Collapse folder (if expanded) or move to parent
|
|
151
|
+
* - Enter/Space: Select file or toggle folder
|
|
152
|
+
* - Home: Move to first item
|
|
153
|
+
* - End: Move to last visible item
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```tsx
|
|
157
|
+
* // Editable mode (default)
|
|
158
|
+
* <FileTree
|
|
159
|
+
* entityId="skill-123"
|
|
160
|
+
* files={fileStructure}
|
|
161
|
+
* selectedPath={selectedPath}
|
|
162
|
+
* onSelect={(path) => setSelectedPath(path)}
|
|
163
|
+
* onDeleteFile={(path) => handleDelete(path)}
|
|
164
|
+
* />
|
|
165
|
+
*
|
|
166
|
+
* // Read-only mode (no create/delete buttons)
|
|
167
|
+
* <FileTree
|
|
168
|
+
* entityId="skill-123"
|
|
169
|
+
* files={fileStructure}
|
|
170
|
+
* selectedPath={selectedPath}
|
|
171
|
+
* onSelect={(path) => setSelectedPath(path)}
|
|
172
|
+
* readOnly
|
|
173
|
+
* ariaLabel="Artifact file browser"
|
|
174
|
+
* />
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
export function FileTree({ entityId: _entityId, files, selectedPath, onSelect, onAddFile, onDeleteFile, isLoading = false, readOnly = false, ariaLabel = 'File browser', }) {
|
|
178
|
+
const [expandedPaths, setExpandedPaths] = useState(new Set());
|
|
179
|
+
const [focusedPath, setFocusedPath] = useState(null);
|
|
180
|
+
const treeRef = useRef(null);
|
|
181
|
+
// Get flat list of all visible nodes for keyboard navigation
|
|
182
|
+
const visibleNodes = flattenVisibleNodes(files, expandedPaths);
|
|
183
|
+
// Initialize focus to first item or selected item
|
|
184
|
+
useEffect(() => {
|
|
185
|
+
if (focusedPath === null && visibleNodes.length > 0) {
|
|
186
|
+
// If there's a selected path, focus it; otherwise focus first item
|
|
187
|
+
const firstNode = visibleNodes[0];
|
|
188
|
+
if (selectedPath && visibleNodes.some((n) => n.path === selectedPath)) {
|
|
189
|
+
setFocusedPath(selectedPath);
|
|
190
|
+
}
|
|
191
|
+
else if (firstNode) {
|
|
192
|
+
setFocusedPath(firstNode.path);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}, [focusedPath, visibleNodes, selectedPath]);
|
|
196
|
+
const handleToggle = useCallback((path) => {
|
|
197
|
+
setExpandedPaths((prev) => {
|
|
198
|
+
const next = new Set(prev);
|
|
199
|
+
if (next.has(path)) {
|
|
200
|
+
next.delete(path);
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
next.add(path);
|
|
204
|
+
}
|
|
205
|
+
return next;
|
|
206
|
+
});
|
|
207
|
+
}, []);
|
|
208
|
+
const handleFocus = useCallback((path) => {
|
|
209
|
+
setFocusedPath(path);
|
|
210
|
+
}, []);
|
|
211
|
+
// Handle keyboard navigation for the tree
|
|
212
|
+
const handleKeyNavigation = useCallback((e, currentNode) => {
|
|
213
|
+
const currentIndex = visibleNodes.findIndex((n) => n.path === currentNode.path);
|
|
214
|
+
if (currentIndex === -1)
|
|
215
|
+
return;
|
|
216
|
+
switch (e.key) {
|
|
217
|
+
case 'ArrowDown': {
|
|
218
|
+
e.preventDefault();
|
|
219
|
+
const nextNode = visibleNodes[currentIndex + 1];
|
|
220
|
+
if (nextNode) {
|
|
221
|
+
setFocusedPath(nextNode.path);
|
|
222
|
+
}
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
case 'ArrowUp': {
|
|
226
|
+
e.preventDefault();
|
|
227
|
+
const prevNode = visibleNodes[currentIndex - 1];
|
|
228
|
+
if (prevNode) {
|
|
229
|
+
setFocusedPath(prevNode.path);
|
|
230
|
+
}
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
case 'Home': {
|
|
234
|
+
e.preventDefault();
|
|
235
|
+
const firstNode = visibleNodes[0];
|
|
236
|
+
if (firstNode) {
|
|
237
|
+
setFocusedPath(firstNode.path);
|
|
238
|
+
}
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
case 'End': {
|
|
242
|
+
e.preventDefault();
|
|
243
|
+
const lastNode = visibleNodes[visibleNodes.length - 1];
|
|
244
|
+
if (lastNode) {
|
|
245
|
+
setFocusedPath(lastNode.path);
|
|
246
|
+
}
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
case 'ArrowLeft': {
|
|
250
|
+
// If not a directory or not expanded, try to move to parent
|
|
251
|
+
e.preventDefault();
|
|
252
|
+
const isDirectory = currentNode.type === 'directory';
|
|
253
|
+
const isExpanded = expandedPaths.has(currentNode.path);
|
|
254
|
+
if (isDirectory && isExpanded) {
|
|
255
|
+
// Let TreeNode handle collapsing
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
// Find parent directory
|
|
259
|
+
const pathParts = currentNode.path.split('/');
|
|
260
|
+
if (pathParts.length > 1) {
|
|
261
|
+
pathParts.pop();
|
|
262
|
+
const parentPath = pathParts.join('/');
|
|
263
|
+
const parentNode = visibleNodes.find((n) => n.path === parentPath);
|
|
264
|
+
if (parentNode) {
|
|
265
|
+
setFocusedPath(parentPath);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
case 'ArrowRight': {
|
|
271
|
+
// If directory is expanded, move to first child
|
|
272
|
+
const isDirectory = currentNode.type === 'directory';
|
|
273
|
+
const isExpanded = expandedPaths.has(currentNode.path);
|
|
274
|
+
if (isDirectory && isExpanded && currentNode.children?.length) {
|
|
275
|
+
e.preventDefault();
|
|
276
|
+
const firstChild = currentNode.children[0];
|
|
277
|
+
if (firstChild) {
|
|
278
|
+
setFocusedPath(firstChild.path);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
// If not expanded, TreeNode will handle expanding
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}, [visibleNodes, expandedPaths]);
|
|
286
|
+
if (isLoading) {
|
|
287
|
+
return _jsx(FileTreeSkeleton, {});
|
|
288
|
+
}
|
|
289
|
+
if (files.length === 0) {
|
|
290
|
+
return (_jsxs("div", { className: "flex h-full flex-col items-center justify-center py-12 text-center", children: [_jsx(Folder, { className: "mb-4 h-12 w-12 text-muted-foreground opacity-50", "aria-hidden": "true" }), _jsx("h3", { className: "mb-1 text-sm font-medium text-muted-foreground", children: "No files found" }), _jsx("p", { className: "text-xs text-muted-foreground", children: "This entity does not contain any files yet." })] }));
|
|
291
|
+
}
|
|
292
|
+
return (_jsxs("div", { className: "flex h-full flex-col", children: [onAddFile && !readOnly && (_jsxs("div", { className: "flex items-center justify-between border-b p-2", children: [_jsx("span", { className: "whitespace-nowrap text-xs font-medium text-muted-foreground", children: "FILES" }), _jsx(Button, { variant: "ghost", size: "icon", className: "h-6 w-6 flex-shrink-0", onClick: onAddFile, "aria-label": "Add new file", children: _jsx(Plus, { className: "h-3 w-3", "aria-hidden": "true" }) })] })), _jsx("div", { ref: treeRef, role: "tree", "aria-label": ariaLabel, className: "flex-1 overflow-auto p-2", "data-testid": "file-tree", children: files.map((node, index) => (_jsx(TreeNode, { node: node, level: 0, selectedPath: selectedPath, focusedPath: focusedPath, expandedPaths: expandedPaths, onSelect: onSelect, onToggle: handleToggle, onDelete: readOnly ? undefined : onDeleteFile, onFocus: handleFocus, onKeyNavigation: handleKeyNavigation, treeSize: visibleNodes.length, positionInSet: index + 1 }, node.path))) })] }));
|
|
293
|
+
}
|
|
294
|
+
//# sourceMappingURL=FileTree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileTree.js","sourceRoot":"","sources":["../../src/content-viewer/FileTree.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @skillmeat/content-viewer — Adapter Interface Definitions
|
|
3
|
+
*
|
|
4
|
+
* Adapter abstractions allow consumers to inject their own data-fetching
|
|
5
|
+
* hooks without coupling content-viewer components to any specific API layer
|
|
6
|
+
* (SkillMeat backend, REST, GraphQL, static JSON, etc.).
|
|
7
|
+
*
|
|
8
|
+
* Consumers implement these interfaces and pass them to ContentViewerProvider.
|
|
9
|
+
* Components then call useContentViewerAdapter() to access the injected hooks.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* // In your app, create an adapter that wraps your fetching hooks:
|
|
14
|
+
* const myAdapter: ContentViewerAdapter = {
|
|
15
|
+
* useFileTree: (artifactId, options) => {
|
|
16
|
+
* const result = useCatalogFileTree(sourceId, artifactId, options);
|
|
17
|
+
* return { data: result.data, isLoading: result.isLoading, error: result.error };
|
|
18
|
+
* },
|
|
19
|
+
* useFileContent: (artifactId, filePath, options) => {
|
|
20
|
+
* const result = useCatalogFileContent(sourceId, artifactId, filePath, options);
|
|
21
|
+
* return { data: result.data, isLoading: result.isLoading, error: result.error };
|
|
22
|
+
* },
|
|
23
|
+
* };
|
|
24
|
+
*
|
|
25
|
+
* // Wrap your component tree:
|
|
26
|
+
* <ContentViewerProvider adapter={myAdapter}>
|
|
27
|
+
* <FileTree artifactId={id} />
|
|
28
|
+
* </ContentViewerProvider>
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
import type { FileTreeResponse, FileContentResponse } from '../types';
|
|
32
|
+
/**
|
|
33
|
+
* Common options accepted by all adapter hooks.
|
|
34
|
+
*/
|
|
35
|
+
export interface AdapterHookOptions {
|
|
36
|
+
/**
|
|
37
|
+
* When false, the hook skips fetching entirely.
|
|
38
|
+
* Useful for conditional/deferred data loading.
|
|
39
|
+
* @default true
|
|
40
|
+
*/
|
|
41
|
+
enabled?: boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Normalized return shape for any data-fetching adapter hook.
|
|
45
|
+
* Mirrors the TanStack Query subset that content-viewer components need.
|
|
46
|
+
*/
|
|
47
|
+
export interface AdapterQueryResult<TData> {
|
|
48
|
+
/** The fetched data, or undefined while loading or on error. */
|
|
49
|
+
data: TData | undefined;
|
|
50
|
+
/** True while the initial fetch is in flight. */
|
|
51
|
+
isLoading: boolean;
|
|
52
|
+
/** Non-null when the most recent fetch failed. */
|
|
53
|
+
error: Error | null;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Adapter interface for fetching the directory/file tree of an artifact.
|
|
57
|
+
*
|
|
58
|
+
* Implementors must provide a `useFileTree` hook that accepts an artifact
|
|
59
|
+
* identifier and returns loading/error/data state conforming to
|
|
60
|
+
* AdapterQueryResult<FileTreeResponse>.
|
|
61
|
+
*/
|
|
62
|
+
export interface FileTreeAdapter {
|
|
63
|
+
/**
|
|
64
|
+
* React hook that fetches the file tree for the given artifact.
|
|
65
|
+
*
|
|
66
|
+
* @param artifactId - Opaque identifier for the artifact. The consumer
|
|
67
|
+
* decides how to map this to their API (e.g. sourceId + path tuple,
|
|
68
|
+
* UUID, slug, etc.).
|
|
69
|
+
* @param options - Optional control flags (enabled).
|
|
70
|
+
*/
|
|
71
|
+
useFileTree: (artifactId: string, options?: AdapterHookOptions) => AdapterQueryResult<FileTreeResponse>;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Adapter interface for fetching the content of a single file within
|
|
75
|
+
* an artifact.
|
|
76
|
+
*
|
|
77
|
+
* Implementors must provide a `useFileContent` hook that accepts an
|
|
78
|
+
* artifact identifier plus a file path and returns normalized query state.
|
|
79
|
+
*/
|
|
80
|
+
export interface FileContentAdapter {
|
|
81
|
+
/**
|
|
82
|
+
* React hook that fetches the content of a specific file.
|
|
83
|
+
*
|
|
84
|
+
* @param artifactId - Opaque identifier for the artifact (same semantics
|
|
85
|
+
* as FileTreeAdapter.useFileTree).
|
|
86
|
+
* @param filePath - Path of the file relative to the artifact root
|
|
87
|
+
* (e.g. "src/index.md").
|
|
88
|
+
* @param options - Optional control flags (enabled).
|
|
89
|
+
*/
|
|
90
|
+
useFileContent: (artifactId: string, filePath: string, options?: AdapterHookOptions) => AdapterQueryResult<FileContentResponse>;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Full content-viewer adapter — combines file tree and file content fetching.
|
|
94
|
+
*
|
|
95
|
+
* Pass an object implementing this interface to ContentViewerProvider.
|
|
96
|
+
* All content-viewer components that need data fetching will access it
|
|
97
|
+
* through useContentViewerAdapter().
|
|
98
|
+
*/
|
|
99
|
+
export interface ContentViewerAdapter extends FileTreeAdapter, FileContentAdapter {
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=adapters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapters.d.ts","sourceRoot":"","sources":["../../src/content-viewer/adapters.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAMtE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAMD;;;GAGG;AACH,MAAM,WAAW,kBAAkB,CAAC,KAAK;IACvC,gEAAgE;IAChE,IAAI,EAAE,KAAK,GAAG,SAAS,CAAC;IACxB,iDAAiD;IACjD,SAAS,EAAE,OAAO,CAAC;IACnB,kDAAkD;IAClD,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAMD;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;;;OAOG;IACH,WAAW,EAAE,CACX,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,kBAAkB,KACzB,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;CAC3C;AAMD;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;OAQG;IACH,cAAc,EAAE,CACd,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,kBAAkB,KACzB,kBAAkB,CAAC,mBAAmB,CAAC,CAAC;CAC9C;AAMD;;;;;;GAMG;AACH,MAAM,WAAW,oBAAqB,SAAQ,eAAe,EAAE,kBAAkB;CAAG"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @skillmeat/content-viewer — Adapter Interface Definitions
|
|
3
|
+
*
|
|
4
|
+
* Adapter abstractions allow consumers to inject their own data-fetching
|
|
5
|
+
* hooks without coupling content-viewer components to any specific API layer
|
|
6
|
+
* (SkillMeat backend, REST, GraphQL, static JSON, etc.).
|
|
7
|
+
*
|
|
8
|
+
* Consumers implement these interfaces and pass them to ContentViewerProvider.
|
|
9
|
+
* Components then call useContentViewerAdapter() to access the injected hooks.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* // In your app, create an adapter that wraps your fetching hooks:
|
|
14
|
+
* const myAdapter: ContentViewerAdapter = {
|
|
15
|
+
* useFileTree: (artifactId, options) => {
|
|
16
|
+
* const result = useCatalogFileTree(sourceId, artifactId, options);
|
|
17
|
+
* return { data: result.data, isLoading: result.isLoading, error: result.error };
|
|
18
|
+
* },
|
|
19
|
+
* useFileContent: (artifactId, filePath, options) => {
|
|
20
|
+
* const result = useCatalogFileContent(sourceId, artifactId, filePath, options);
|
|
21
|
+
* return { data: result.data, isLoading: result.isLoading, error: result.error };
|
|
22
|
+
* },
|
|
23
|
+
* };
|
|
24
|
+
*
|
|
25
|
+
* // Wrap your component tree:
|
|
26
|
+
* <ContentViewerProvider adapter={myAdapter}>
|
|
27
|
+
* <FileTree artifactId={id} />
|
|
28
|
+
* </ContentViewerProvider>
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=adapters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapters.js","sourceRoot":"","sources":["../../src/content-viewer/adapters.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { FileTree } from './FileTree';
|
|
2
|
+
export type { FileTreeProps } from './FileTree';
|
|
3
|
+
export { ContentPane } from './ContentPane';
|
|
4
|
+
export type { ContentPaneProps, TruncationInfo } from './ContentPane';
|
|
5
|
+
export { ContentViewerProvider, useContentViewerAdapter, } from './ContentViewerProvider';
|
|
6
|
+
export type { ContentViewerProviderProps } from './ContentViewerProvider';
|
|
7
|
+
export type { AdapterHookOptions, AdapterQueryResult, FileTreeAdapter, FileContentAdapter, ContentViewerAdapter, } from './adapters';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/content-viewer/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,EACL,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAC1E,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/content-viewer/index.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EACL,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { FileDiff } from './diff';
|
|
2
|
+
/**
|
|
3
|
+
* Resolution type for sync conflict resolution
|
|
4
|
+
*/
|
|
5
|
+
export type ResolutionType = 'keep_local' | 'keep_remote' | 'merge';
|
|
6
|
+
/**
|
|
7
|
+
* Tier context for enterprise tier comparison diffs.
|
|
8
|
+
*
|
|
9
|
+
* When provided, the diff panel headers display tier badges (e.g. "Tier 1 · Team")
|
|
10
|
+
* instead of the plain leftLabel/rightLabel text. The ownerType string is used to
|
|
11
|
+
* derive a human-readable tier name alongside the numeric tier level.
|
|
12
|
+
*/
|
|
13
|
+
export interface TierContext {
|
|
14
|
+
/** Owner type for the left (before) panel — e.g. "user", "team", "enterprise" */
|
|
15
|
+
leftOwnerType: string;
|
|
16
|
+
/** Owner type for the right (after) panel */
|
|
17
|
+
rightOwnerType: string;
|
|
18
|
+
/** Numeric tier level for the left panel (0 = Developer, 1 = Team, 2 = Enterprise, …) */
|
|
19
|
+
leftTier: number;
|
|
20
|
+
/** Numeric tier level for the right panel */
|
|
21
|
+
rightTier: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Props for DiffViewer component
|
|
25
|
+
*
|
|
26
|
+
* Configuration for displaying unified diffs with side-by-side view.
|
|
27
|
+
*/
|
|
28
|
+
export interface DiffViewerProps {
|
|
29
|
+
/** Array of file diffs to display */
|
|
30
|
+
files: FileDiff[];
|
|
31
|
+
/** Label for left (before) panel */
|
|
32
|
+
leftLabel?: string;
|
|
33
|
+
/** Label for right (after) panel */
|
|
34
|
+
rightLabel?: string;
|
|
35
|
+
/** Callback when user closes the diff viewer */
|
|
36
|
+
onClose?: () => void;
|
|
37
|
+
/** Show resolution action buttons (for sync conflict resolution) */
|
|
38
|
+
showResolutionActions?: boolean;
|
|
39
|
+
/** Callback when user selects a resolution */
|
|
40
|
+
onResolve?: (resolution: ResolutionType) => void;
|
|
41
|
+
/** Custom label for local version button (default: "Local (Project)") */
|
|
42
|
+
localLabel?: string;
|
|
43
|
+
/** Custom label for remote version button (default: "Remote (Collection)") */
|
|
44
|
+
remoteLabel?: string;
|
|
45
|
+
/** Show preview mode UI before applying resolution */
|
|
46
|
+
previewMode?: boolean;
|
|
47
|
+
/** Show loading state during resolution */
|
|
48
|
+
isResolving?: boolean;
|
|
49
|
+
/** Show skeleton loading state while data is being fetched */
|
|
50
|
+
isLoading?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Optional tier context for enterprise tier comparison diffs.
|
|
53
|
+
*
|
|
54
|
+
* When provided, the diff panel headers render tier badges instead of the
|
|
55
|
+
* default plain-text leftLabel/rightLabel. Existing label props still apply
|
|
56
|
+
* to other parts of the UI (e.g. "file added in {rightLabel}" messages);
|
|
57
|
+
* only the side-by-side panel column headers change.
|
|
58
|
+
*/
|
|
59
|
+
tierContext?: TierContext;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* DiffViewerSkeleton - Loading skeleton matching the DiffViewer layout
|
|
63
|
+
*
|
|
64
|
+
* Mimics the side-by-side diff viewer structure:
|
|
65
|
+
* - Summary header bar with skeleton badges
|
|
66
|
+
* - File list sidebar with skeleton entries
|
|
67
|
+
* - Main diff area with side-by-side skeleton code lines
|
|
68
|
+
*/
|
|
69
|
+
export declare function DiffViewerSkeleton(): import("react/jsx-runtime").JSX.Element;
|
|
70
|
+
/**
|
|
71
|
+
* DiffViewer - Side-by-side diff viewer with file browser
|
|
72
|
+
*
|
|
73
|
+
* Displays unified diffs in a professional side-by-side format. Features include:
|
|
74
|
+
* - File list sidebar with expandable items showing change statistics
|
|
75
|
+
* - Side-by-side diff panels with independent scrollbars
|
|
76
|
+
* - Color-coded additions (green), deletions (red), and context lines
|
|
77
|
+
* - File status badges (added, modified, deleted, unchanged)
|
|
78
|
+
* - Change summary (total files added, modified, deleted)
|
|
79
|
+
* - Optional sync conflict resolution actions (keep local/remote/merge)
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* Basic diff viewer:
|
|
83
|
+
* ```tsx
|
|
84
|
+
* <DiffViewer
|
|
85
|
+
* files={diffData.files}
|
|
86
|
+
* leftLabel="Collection"
|
|
87
|
+
* rightLabel="Project"
|
|
88
|
+
* onClose={() => closeDiff()}
|
|
89
|
+
* />
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* With sync resolution actions:
|
|
94
|
+
* ```tsx
|
|
95
|
+
* <DiffViewer
|
|
96
|
+
* files={diffData.files}
|
|
97
|
+
* leftLabel="Collection"
|
|
98
|
+
* rightLabel="Project"
|
|
99
|
+
* showResolutionActions={true}
|
|
100
|
+
* onResolve={(resolution) => handleResolve(resolution)}
|
|
101
|
+
* localLabel="Project"
|
|
102
|
+
* remoteLabel="Collection"
|
|
103
|
+
* isResolving={isResolving}
|
|
104
|
+
* previewMode={true}
|
|
105
|
+
* />
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* @param props - DiffViewerProps configuration
|
|
109
|
+
* @returns Full-height diff viewer component
|
|
110
|
+
*/
|
|
111
|
+
export declare function DiffViewer({ files, leftLabel, rightLabel, onClose, showResolutionActions, onResolve, localLabel, remoteLabel, previewMode, isResolving, isLoading, tierContext, }: DiffViewerProps): import("react/jsx-runtime").JSX.Element;
|
|
112
|
+
//# sourceMappingURL=DiffViewer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiffViewer.d.ts","sourceRoot":"","sources":["../../src/diff/DiffViewer.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAOlC;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,aAAa,GAAG,OAAO,CAAC;AAEpE;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,iFAAiF;IACjF,aAAa,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,yFAAyF;IACzF,QAAQ,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;CACnB;AAqCD;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,qCAAqC;IACrC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,oEAAoE;IACpE,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,8CAA8C;IAC9C,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,cAAc,KAAK,IAAI,CAAC;IACjD,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAiDD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,4CAyFjC;AAyID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,SAAoB,EACpB,UAAoB,EACpB,OAAO,EACP,qBAA6B,EAC7B,SAAS,EACT,UAAU,EACV,WAAW,EACX,WAAmB,EACnB,WAAmB,EACnB,SAAiB,EACjB,WAAW,GACZ,EAAE,eAAe,2CAgdjB"}
|