@fgv/ts-res-ui-components 5.0.0-21 → 5.0.0-23
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/README.md +401 -155
- package/config/jest.setup.js +10 -0
- package/dist/ts-res-ui-components.d.ts +1657 -76
- package/lib/components/common/QualifierContextControl.js +4 -1
- package/lib/components/common/ResourceTreeView.js +4 -1
- package/lib/components/forms/GenericQualifierTypeEditForm.d.ts +26 -0
- package/lib/components/forms/GenericQualifierTypeEditForm.js +166 -0
- package/lib/components/forms/QualifierEditForm.d.ts +1 -1
- package/lib/components/forms/index.d.ts +2 -0
- package/lib/components/forms/index.js +1 -0
- package/lib/components/orchestrator/ResourceOrchestrator.d.ts +3 -0
- package/lib/components/orchestrator/ResourceOrchestrator.js +118 -51
- package/lib/components/pickers/ResourcePicker/ResourcePickerTree.js +32 -10
- package/lib/components/pickers/ResourcePicker/index.js +4 -2
- package/lib/components/views/CompiledView/index.js +75 -16
- package/lib/components/views/ConfigurationView/index.js +94 -35
- package/lib/components/views/FilterView/index.js +7 -4
- package/lib/components/views/GridView/EditableGridCell.d.ts +76 -0
- package/lib/components/views/GridView/EditableGridCell.js +224 -0
- package/lib/components/views/GridView/GridSelector.d.ts +43 -0
- package/lib/components/views/GridView/GridSelector.js +89 -0
- package/lib/components/views/GridView/MultiGridView.d.ts +85 -0
- package/lib/components/views/GridView/MultiGridView.js +196 -0
- package/lib/components/views/GridView/ResourceGrid.d.ts +38 -0
- package/lib/components/views/GridView/ResourceGrid.js +232 -0
- package/lib/components/views/GridView/SharedContextControls.d.ts +47 -0
- package/lib/components/views/GridView/SharedContextControls.js +95 -0
- package/lib/components/views/GridView/cells/BooleanCell.d.ts +44 -0
- package/lib/components/views/GridView/cells/BooleanCell.js +49 -0
- package/lib/components/views/GridView/cells/DropdownCell.d.ts +58 -0
- package/lib/components/views/GridView/cells/DropdownCell.js +182 -0
- package/lib/components/views/GridView/cells/StringCell.d.ts +57 -0
- package/lib/components/views/GridView/cells/StringCell.js +106 -0
- package/lib/components/views/GridView/cells/TriStateCell.d.ts +54 -0
- package/lib/components/views/GridView/cells/TriStateCell.js +112 -0
- package/lib/components/views/GridView/cells/index.d.ts +15 -0
- package/lib/components/views/GridView/cells/index.js +11 -0
- package/lib/components/views/GridView/index.d.ts +53 -0
- package/lib/components/views/GridView/index.js +212 -0
- package/lib/components/views/ImportView/index.js +22 -19
- package/lib/components/views/MessagesWindow/index.js +4 -1
- package/lib/components/views/ResolutionView/index.js +8 -5
- package/lib/contexts/ObservabilityContext.d.ts +85 -0
- package/lib/contexts/ObservabilityContext.js +98 -0
- package/lib/contexts/index.d.ts +2 -0
- package/lib/contexts/index.js +24 -0
- package/lib/hooks/useConfigurationState.d.ts +3 -3
- package/lib/hooks/useResolutionState.js +850 -246
- package/lib/hooks/useResourceData.d.ts +7 -4
- package/lib/hooks/useResourceData.js +185 -184
- package/lib/index.d.ts +5 -1
- package/lib/index.js +8 -1
- package/lib/namespaces/GridTools.d.ts +136 -0
- package/lib/namespaces/GridTools.js +138 -0
- package/lib/namespaces/ObservabilityTools.d.ts +3 -0
- package/lib/namespaces/ObservabilityTools.js +23 -0
- package/lib/namespaces/ResolutionTools.d.ts +2 -1
- package/lib/namespaces/ResolutionTools.js +2 -0
- package/lib/namespaces/index.d.ts +2 -0
- package/lib/namespaces/index.js +2 -0
- package/lib/test/integration/observability.integration.test.d.ts +2 -0
- package/lib/test/unit/hooks/useResourceData.test.d.ts +2 -0
- package/lib/test/unit/utils/downloadHelper.test.d.ts +2 -0
- package/lib/test/unit/workflows/resolutionWorkflows.test.d.ts +2 -0
- package/lib/test/unit/workflows/resourceCreation.test.d.ts +2 -0
- package/lib/test/unit/workflows/resultPatternExtensions.test.d.ts +2 -0
- package/lib/test/unit/workflows/validation.test.d.ts +2 -0
- package/lib/types/index.d.ts +387 -20
- package/lib/types/index.js +2 -1
- package/lib/utils/cellValidation.d.ts +113 -0
- package/lib/utils/cellValidation.js +248 -0
- package/lib/utils/downloadHelper.d.ts +66 -0
- package/lib/utils/downloadHelper.js +195 -0
- package/lib/utils/observability/factories.d.ts +29 -0
- package/lib/utils/observability/factories.js +58 -0
- package/lib/utils/observability/implementations.d.ts +61 -0
- package/lib/utils/observability/implementations.js +103 -0
- package/lib/utils/observability/index.d.ts +4 -0
- package/lib/utils/observability/index.js +26 -0
- package/lib/utils/observability/interfaces.d.ts +30 -0
- package/lib/utils/observability/interfaces.js +23 -0
- package/lib/utils/resolutionEditing.js +2 -1
- package/lib/utils/resourceSelector.d.ts +97 -0
- package/lib/utils/resourceSelector.js +195 -0
- package/lib/utils/resourceSelectors.d.ts +146 -0
- package/lib/utils/resourceSelectors.js +233 -0
- package/lib/utils/tsResIntegration.d.ts +6 -41
- package/lib/utils/tsResIntegration.js +20 -16
- package/lib/utils/zipLoader/zipProcessingHelpers.d.ts +3 -2
- package/lib/utils/zipLoader/zipProcessingHelpers.js +6 -5
- package/lib-commonjs/components/common/QualifierContextControl.js +4 -1
- package/lib-commonjs/components/common/ResourceTreeView.js +4 -1
- package/lib-commonjs/components/forms/GenericQualifierTypeEditForm.js +171 -0
- package/lib-commonjs/components/forms/index.js +3 -1
- package/lib-commonjs/components/orchestrator/ResourceOrchestrator.js +118 -51
- package/lib-commonjs/components/pickers/ResourcePicker/ResourcePickerTree.js +32 -10
- package/lib-commonjs/components/pickers/ResourcePicker/index.js +4 -2
- package/lib-commonjs/components/views/CompiledView/index.js +75 -16
- package/lib-commonjs/components/views/ConfigurationView/index.js +93 -34
- package/lib-commonjs/components/views/FilterView/index.js +7 -4
- package/lib-commonjs/components/views/GridView/EditableGridCell.js +232 -0
- package/lib-commonjs/components/views/GridView/GridSelector.js +94 -0
- package/lib-commonjs/components/views/GridView/MultiGridView.js +201 -0
- package/lib-commonjs/components/views/GridView/ResourceGrid.js +237 -0
- package/lib-commonjs/components/views/GridView/SharedContextControls.js +100 -0
- package/lib-commonjs/components/views/GridView/cells/BooleanCell.js +54 -0
- package/lib-commonjs/components/views/GridView/cells/DropdownCell.js +187 -0
- package/lib-commonjs/components/views/GridView/cells/StringCell.js +111 -0
- package/lib-commonjs/components/views/GridView/cells/TriStateCell.js +117 -0
- package/lib-commonjs/components/views/GridView/cells/index.js +18 -0
- package/lib-commonjs/components/views/GridView/index.js +217 -0
- package/lib-commonjs/components/views/ImportView/index.js +22 -19
- package/lib-commonjs/components/views/MessagesWindow/index.js +4 -1
- package/lib-commonjs/components/views/ResolutionView/index.js +8 -5
- package/lib-commonjs/contexts/ObservabilityContext.js +104 -0
- package/lib-commonjs/contexts/index.js +30 -0
- package/lib-commonjs/hooks/useResolutionState.js +849 -245
- package/lib-commonjs/hooks/useResourceData.js +184 -215
- package/lib-commonjs/index.js +15 -1
- package/lib-commonjs/namespaces/GridTools.js +161 -0
- package/lib-commonjs/namespaces/ObservabilityTools.js +33 -0
- package/lib-commonjs/namespaces/ResolutionTools.js +10 -1
- package/lib-commonjs/namespaces/index.js +3 -1
- package/lib-commonjs/types/index.js +10 -0
- package/lib-commonjs/utils/cellValidation.js +253 -0
- package/lib-commonjs/utils/downloadHelper.js +198 -0
- package/lib-commonjs/utils/observability/factories.js +63 -0
- package/lib-commonjs/utils/observability/implementations.js +109 -0
- package/lib-commonjs/utils/observability/index.js +36 -0
- package/lib-commonjs/utils/observability/interfaces.js +24 -0
- package/lib-commonjs/utils/resolutionEditing.js +2 -1
- package/lib-commonjs/utils/resourceSelector.js +200 -0
- package/lib-commonjs/utils/resourceSelectors.js +242 -0
- package/lib-commonjs/utils/tsResIntegration.js +21 -16
- package/lib-commonjs/utils/zipLoader/zipProcessingHelpers.js +7 -5
- package/package.json +7 -7
- package/src/components/common/QualifierContextControl.tsx +0 -338
- package/src/components/common/ResolutionContextOptionsControl.tsx +0 -450
- package/src/components/common/ResolutionResults/index.tsx +0 -481
- package/src/components/common/ResourceListView.tsx +0 -167
- package/src/components/common/ResourcePickerOptionsControl.tsx +0 -351
- package/src/components/common/ResourceTreeView.tsx +0 -417
- package/src/components/common/SourceResourceDetail/index.tsx +0 -493
- package/src/components/forms/HierarchyEditor.tsx +0 -285
- package/src/components/forms/QualifierEditForm.tsx +0 -487
- package/src/components/forms/QualifierTypeEditForm.tsx +0 -458
- package/src/components/forms/ResourceTypeEditForm.tsx +0 -437
- package/src/components/forms/index.ts +0 -11
- package/src/components/orchestrator/ResourceOrchestrator.tsx +0 -444
- package/src/components/pickers/ResourcePicker/README.md +0 -570
- package/src/components/pickers/ResourcePicker/ResourceItem.tsx +0 -127
- package/src/components/pickers/ResourcePicker/ResourcePickerList.tsx +0 -114
- package/src/components/pickers/ResourcePicker/ResourcePickerTree.tsx +0 -461
- package/src/components/pickers/ResourcePicker/index.tsx +0 -234
- package/src/components/pickers/ResourcePicker/types.ts +0 -301
- package/src/components/pickers/ResourcePicker/utils/treeNavigation.ts +0 -210
- package/src/components/views/CompiledView/index.tsx +0 -1342
- package/src/components/views/ConfigurationView/index.tsx +0 -848
- package/src/components/views/FilterView/index.tsx +0 -681
- package/src/components/views/ImportView/index.tsx +0 -789
- package/src/components/views/MessagesWindow/index.tsx +0 -325
- package/src/components/views/ResolutionView/EditableJsonView.tsx +0 -386
- package/src/components/views/ResolutionView/NewResourceModal.tsx +0 -158
- package/src/components/views/ResolutionView/UnifiedChangeControls.tsx +0 -163
- package/src/components/views/ResolutionView/index.tsx +0 -751
- package/src/components/views/SourceView/index.tsx +0 -291
- package/src/hooks/useConfigurationState.ts +0 -436
- package/src/hooks/useFilterState.ts +0 -150
- package/src/hooks/useResolutionState.ts +0 -893
- package/src/hooks/useResourceData.ts +0 -596
- package/src/hooks/useViewState.ts +0 -97
- package/src/index.ts +0 -68
- package/src/namespaces/ConfigurationTools.ts +0 -59
- package/src/namespaces/FilterTools.ts +0 -47
- package/src/namespaces/ImportTools.ts +0 -42
- package/src/namespaces/PickerTools.ts +0 -104
- package/src/namespaces/ResolutionTools.ts +0 -68
- package/src/namespaces/ResourceTools.ts +0 -106
- package/src/namespaces/TsResTools.ts +0 -49
- package/src/namespaces/ViewStateTools.ts +0 -91
- package/src/namespaces/ZipTools.ts +0 -49
- package/src/namespaces/index.ts +0 -49
- package/src/types/index.ts +0 -1273
- package/src/utils/configurationUtils.ts +0 -339
- package/src/utils/fileProcessing.ts +0 -164
- package/src/utils/filterResources.ts +0 -356
- package/src/utils/resolutionEditing.ts +0 -346
- package/src/utils/resolutionUtils.ts +0 -740
- package/src/utils/tsResIntegration.ts +0 -475
- package/src/utils/zipLoader/index.ts +0 -5
- package/src/utils/zipLoader/zipProcessingHelpers.ts +0 -46
- package/src/utils/zipLoader/zipUtils.ts +0 -7
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
import React, { useState, useMemo, useCallback } from 'react';
|
|
2
|
-
import { MagnifyingGlassIcon, ListBulletIcon, FolderIcon } from '@heroicons/react/24/outline';
|
|
3
|
-
import { ResourcePickerProps, ResourceSelection, ResourcePickerOptions } from './types';
|
|
4
|
-
import { ResourcePickerList } from './ResourcePickerList';
|
|
5
|
-
import { ResourcePickerTree } from './ResourcePickerTree';
|
|
6
|
-
import { searchResources, filterTreeBranch } from './utils/treeNavigation';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Comprehensive resource picker component with search, view modes, and annotation support.
|
|
10
|
-
*
|
|
11
|
-
* The ResourcePicker provides a flexible interface for browsing and selecting resources
|
|
12
|
-
* from processed resource collections. It supports both list and tree view modes,
|
|
13
|
-
* search functionality, visual annotations, and pending resource management.
|
|
14
|
-
*
|
|
15
|
-
* Key features:
|
|
16
|
-
* - **Multiple view modes**: List view for simple browsing, tree view for hierarchical navigation
|
|
17
|
-
* - **Search functionality**: Search across all resources or within a specific branch
|
|
18
|
-
* - **Visual annotations**: Display badges, indicators, and suffixes for enhanced UX
|
|
19
|
-
* - **Pending resources**: Show unsaved changes alongside persisted resources
|
|
20
|
-
* - **Branch isolation**: Focus on a specific branch node of the resource tree
|
|
21
|
-
* - **Type safety**: Full TypeScript support with generic resource data types
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* ```tsx
|
|
25
|
-
* function MyResourceEditor() {
|
|
26
|
-
* const [selectedId, setSelectedId] = useState<string | null>(null);
|
|
27
|
-
* const [selectedData, setSelectedData] = useState<MyResourceType | null>(null);
|
|
28
|
-
*
|
|
29
|
-
* return (
|
|
30
|
-
* <ResourcePicker<MyResourceType>
|
|
31
|
-
* resources={processedResources}
|
|
32
|
-
* selectedResourceId={selectedId}
|
|
33
|
-
* onResourceSelect={(selection) => {
|
|
34
|
-
* setSelectedId(selection.resourceId);
|
|
35
|
-
* setSelectedData(selection.resourceData || null);
|
|
36
|
-
*
|
|
37
|
-
* if (selection.isPending) {
|
|
38
|
-
* console.log(`Pending ${selection.pendingType} operation`);
|
|
39
|
-
* }
|
|
40
|
-
* }}
|
|
41
|
-
* defaultView="tree"
|
|
42
|
-
* enableSearch={true}
|
|
43
|
-
* searchPlaceholder="Search resources..."
|
|
44
|
-
* resourceAnnotations={{
|
|
45
|
-
* 'user.welcome': {
|
|
46
|
-
* badge: { text: '3', variant: 'info' },
|
|
47
|
-
* suffix: '(3 candidates)'
|
|
48
|
-
* }
|
|
49
|
-
* }}
|
|
50
|
-
* pendingResources={[{
|
|
51
|
-
* id: 'user.new-item',
|
|
52
|
-
* type: 'new',
|
|
53
|
-
* displayName: 'New Welcome Message',
|
|
54
|
-
* resourceData: { text: 'Hello World!' }
|
|
55
|
-
* }]}
|
|
56
|
-
* height="500px"
|
|
57
|
-
* />
|
|
58
|
-
* );
|
|
59
|
-
* }
|
|
60
|
-
* ```
|
|
61
|
-
*
|
|
62
|
-
* @public
|
|
63
|
-
*/
|
|
64
|
-
export const ResourcePicker = <T = unknown,>({
|
|
65
|
-
resources,
|
|
66
|
-
selectedResourceId,
|
|
67
|
-
onResourceSelect,
|
|
68
|
-
resourceAnnotations,
|
|
69
|
-
pendingResources,
|
|
70
|
-
options,
|
|
71
|
-
className = '',
|
|
72
|
-
onMessage
|
|
73
|
-
}: ResourcePickerProps<T>) => {
|
|
74
|
-
// Extract options with defaults
|
|
75
|
-
const {
|
|
76
|
-
defaultView = 'list',
|
|
77
|
-
showViewToggle = true,
|
|
78
|
-
rootPath,
|
|
79
|
-
hideRootNode = false,
|
|
80
|
-
enableSearch = true,
|
|
81
|
-
searchPlaceholder,
|
|
82
|
-
searchScope = 'current-branch',
|
|
83
|
-
emptyMessage,
|
|
84
|
-
height = '600px'
|
|
85
|
-
} = options || {};
|
|
86
|
-
const [viewMode, setViewMode] = useState<'list' | 'tree'>(defaultView);
|
|
87
|
-
const [searchTerm, setSearchTerm] = useState('');
|
|
88
|
-
|
|
89
|
-
// Get resource IDs based on current filters
|
|
90
|
-
const resourceIds = useMemo(() => {
|
|
91
|
-
if (!resources?.summary.resourceIds) {
|
|
92
|
-
return [];
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
let ids = resources.summary.resourceIds;
|
|
96
|
-
|
|
97
|
-
// Apply branch filtering if specified
|
|
98
|
-
if (rootPath) {
|
|
99
|
-
ids = filterTreeBranch(ids, rootPath, hideRootNode);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Apply search filtering
|
|
103
|
-
if (searchTerm) {
|
|
104
|
-
ids = searchResources(ids, searchTerm, searchScope, rootPath);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return ids;
|
|
108
|
-
}, [resources?.summary.resourceIds, rootPath, hideRootNode, searchTerm, searchScope]);
|
|
109
|
-
|
|
110
|
-
// Handle resource selection
|
|
111
|
-
const handleResourceSelect = useCallback(
|
|
112
|
-
(selection: ResourceSelection<T>) => {
|
|
113
|
-
onResourceSelect(selection);
|
|
114
|
-
if (selection.resourceId) {
|
|
115
|
-
onMessage?.('info', `Selected resource: ${selection.resourceId}`);
|
|
116
|
-
}
|
|
117
|
-
},
|
|
118
|
-
[onResourceSelect, onMessage]
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
// Calculate dynamic search placeholder
|
|
122
|
-
const getSearchPlaceholder = () => {
|
|
123
|
-
if (searchPlaceholder) {
|
|
124
|
-
return searchPlaceholder;
|
|
125
|
-
}
|
|
126
|
-
if (rootPath && hideRootNode) {
|
|
127
|
-
const segments = rootPath.split('/');
|
|
128
|
-
const branchName = segments[segments.length - 1];
|
|
129
|
-
return `Search ${branchName}...`;
|
|
130
|
-
}
|
|
131
|
-
return 'Search resources...';
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
// Handle empty state
|
|
135
|
-
if (!resources) {
|
|
136
|
-
return (
|
|
137
|
-
<div className={`${className} p-4 text-center text-gray-500`}>
|
|
138
|
-
<p>{emptyMessage || 'No resources loaded'}</p>
|
|
139
|
-
</div>
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const containerHeight = typeof height === 'number' ? `${height}px` : height;
|
|
144
|
-
|
|
145
|
-
return (
|
|
146
|
-
<div className={`flex flex-col ${className}`} style={{ height: containerHeight }}>
|
|
147
|
-
{/* Header with search and view toggle */}
|
|
148
|
-
{(enableSearch || showViewToggle) && (
|
|
149
|
-
<div className="flex flex-col gap-3 mb-4">
|
|
150
|
-
{/* Search Box */}
|
|
151
|
-
{enableSearch && (
|
|
152
|
-
<div className="relative">
|
|
153
|
-
<MagnifyingGlassIcon className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
|
|
154
|
-
<input
|
|
155
|
-
type="text"
|
|
156
|
-
placeholder={getSearchPlaceholder()}
|
|
157
|
-
value={searchTerm}
|
|
158
|
-
onChange={(e) => setSearchTerm(e.target.value)}
|
|
159
|
-
className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent text-sm"
|
|
160
|
-
/>
|
|
161
|
-
</div>
|
|
162
|
-
)}
|
|
163
|
-
|
|
164
|
-
{/* View Mode Toggle */}
|
|
165
|
-
{showViewToggle && (
|
|
166
|
-
<div className="flex items-center justify-between">
|
|
167
|
-
<span className="text-sm text-gray-600">
|
|
168
|
-
{resourceIds.length} resource{resourceIds.length !== 1 ? 's' : ''}
|
|
169
|
-
{searchTerm && ` matching "${searchTerm}"`}
|
|
170
|
-
</span>
|
|
171
|
-
<div className="flex items-center space-x-1 bg-gray-100 rounded-lg p-1">
|
|
172
|
-
<button
|
|
173
|
-
onClick={() => setViewMode('list')}
|
|
174
|
-
className={`flex items-center px-2 py-1 text-xs font-medium rounded transition-colors ${
|
|
175
|
-
viewMode === 'list'
|
|
176
|
-
? 'bg-white text-gray-900 shadow-sm'
|
|
177
|
-
: 'text-gray-600 hover:text-gray-900'
|
|
178
|
-
}`}
|
|
179
|
-
title="List View"
|
|
180
|
-
>
|
|
181
|
-
<ListBulletIcon className="h-4 w-4" />
|
|
182
|
-
<span className="ml-1">List</span>
|
|
183
|
-
</button>
|
|
184
|
-
<button
|
|
185
|
-
onClick={() => setViewMode('tree')}
|
|
186
|
-
className={`flex items-center px-2 py-1 text-xs font-medium rounded transition-colors ${
|
|
187
|
-
viewMode === 'tree'
|
|
188
|
-
? 'bg-white text-gray-900 shadow-sm'
|
|
189
|
-
: 'text-gray-600 hover:text-gray-900'
|
|
190
|
-
}`}
|
|
191
|
-
title="Tree View"
|
|
192
|
-
>
|
|
193
|
-
<FolderIcon className="h-4 w-4" />
|
|
194
|
-
<span className="ml-1">Tree</span>
|
|
195
|
-
</button>
|
|
196
|
-
</div>
|
|
197
|
-
</div>
|
|
198
|
-
)}
|
|
199
|
-
</div>
|
|
200
|
-
)}
|
|
201
|
-
|
|
202
|
-
{/* Resource List or Tree */}
|
|
203
|
-
<div className="flex-1 overflow-y-auto border border-gray-200 rounded-lg bg-gray-50">
|
|
204
|
-
{viewMode === 'tree' ? (
|
|
205
|
-
<ResourcePickerTree<T>
|
|
206
|
-
resources={resources}
|
|
207
|
-
pendingResources={pendingResources}
|
|
208
|
-
selectedResourceId={selectedResourceId}
|
|
209
|
-
onResourceSelect={handleResourceSelect}
|
|
210
|
-
resourceAnnotations={resourceAnnotations}
|
|
211
|
-
searchTerm={searchTerm}
|
|
212
|
-
rootPath={rootPath}
|
|
213
|
-
hideRootNode={hideRootNode}
|
|
214
|
-
emptyMessage={emptyMessage}
|
|
215
|
-
/>
|
|
216
|
-
) : (
|
|
217
|
-
<ResourcePickerList<T>
|
|
218
|
-
resourceIds={resources.summary.resourceIds || []}
|
|
219
|
-
pendingResources={pendingResources}
|
|
220
|
-
selectedResourceId={selectedResourceId}
|
|
221
|
-
onResourceSelect={handleResourceSelect}
|
|
222
|
-
resourceAnnotations={resourceAnnotations}
|
|
223
|
-
searchTerm={searchTerm}
|
|
224
|
-
rootPath={rootPath}
|
|
225
|
-
hideRootNode={hideRootNode}
|
|
226
|
-
emptyMessage={emptyMessage}
|
|
227
|
-
/>
|
|
228
|
-
)}
|
|
229
|
-
</div>
|
|
230
|
-
</div>
|
|
231
|
-
);
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
export default ResourcePicker;
|
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { ProcessedResources, ExtendedProcessedResources, ViewBaseProps } from '../../../types';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Resource selection data returned by the onResourceSelect callback.
|
|
6
|
-
*
|
|
7
|
-
* This interface provides comprehensive information about the selected resource,
|
|
8
|
-
* eliminating the need for consumers to perform additional lookups.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```tsx
|
|
12
|
-
* const handleResourceSelect = (selection: ResourceSelection<MyResourceType>) => {
|
|
13
|
-
* if (selection.resourceId) {
|
|
14
|
-
* console.log('Selected:', selection.resourceId);
|
|
15
|
-
* if (selection.resourceData) {
|
|
16
|
-
* console.log('Data:', selection.resourceData);
|
|
17
|
-
* }
|
|
18
|
-
* if (selection.isPending) {
|
|
19
|
-
* console.log('Pending operation:', selection.pendingType);
|
|
20
|
-
* }
|
|
21
|
-
* }
|
|
22
|
-
* };
|
|
23
|
-
* ```
|
|
24
|
-
*
|
|
25
|
-
* @public
|
|
26
|
-
*/
|
|
27
|
-
export interface ResourceSelection<T = unknown> {
|
|
28
|
-
/** The ID of the selected resource, or null if no selection */
|
|
29
|
-
resourceId: string | null;
|
|
30
|
-
/** The actual resource data if available and typed */
|
|
31
|
-
resourceData?: T;
|
|
32
|
-
/** Whether this is a pending (unsaved) resource */
|
|
33
|
-
isPending?: boolean;
|
|
34
|
-
/** Type of pending operation for unsaved resources */
|
|
35
|
-
pendingType?: 'new' | 'modified' | 'deleted';
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* UI behavior configuration options for ResourcePicker.
|
|
40
|
-
*
|
|
41
|
-
* This interface groups all UI-related options that control how the ResourcePicker
|
|
42
|
-
* behaves and appears, separate from functional data like annotations and pending resources.
|
|
43
|
-
*
|
|
44
|
-
* @example
|
|
45
|
-
* ```tsx
|
|
46
|
-
* const pickerOptions: ResourcePickerOptions = {
|
|
47
|
-
* defaultView: 'tree',
|
|
48
|
-
* enableSearch: true,
|
|
49
|
-
* searchPlaceholder: 'Find resources...',
|
|
50
|
-
* rootPath: 'user.messages',
|
|
51
|
-
* hideRootNode: true,
|
|
52
|
-
* height: '400px'
|
|
53
|
-
* };
|
|
54
|
-
* ```
|
|
55
|
-
*
|
|
56
|
-
* @public
|
|
57
|
-
*/
|
|
58
|
-
export interface ResourcePickerOptions {
|
|
59
|
-
/** View and navigation options */
|
|
60
|
-
/** Default view mode to use on initial render */
|
|
61
|
-
defaultView?: 'list' | 'tree';
|
|
62
|
-
/** Whether to show the list/tree view toggle buttons */
|
|
63
|
-
showViewToggle?: boolean;
|
|
64
|
-
|
|
65
|
-
/** Branch isolation options */
|
|
66
|
-
/** Path to treat as root for tree branch isolation (e.g., "platform/territories") */
|
|
67
|
-
rootPath?: string;
|
|
68
|
-
/** Hide the root node itself, showing only its children */
|
|
69
|
-
hideRootNode?: boolean;
|
|
70
|
-
|
|
71
|
-
/** Search options */
|
|
72
|
-
/** Whether to enable the search input */
|
|
73
|
-
enableSearch?: boolean;
|
|
74
|
-
/** Placeholder text for the search input */
|
|
75
|
-
searchPlaceholder?: string;
|
|
76
|
-
/** Scope of search - entire tree or just the currently visible branch */
|
|
77
|
-
searchScope?: 'all' | 'current-branch';
|
|
78
|
-
|
|
79
|
-
/** Appearance options */
|
|
80
|
-
/** Message to display when no resources are available */
|
|
81
|
-
emptyMessage?: string;
|
|
82
|
-
/** Height of the picker component */
|
|
83
|
-
height?: string | number;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Props for the ResourcePicker component.
|
|
88
|
-
*
|
|
89
|
-
* The ResourcePicker is a comprehensive component for browsing and selecting resources
|
|
90
|
-
* with support for multiple view modes, search, annotations, and pending resources.
|
|
91
|
-
* UI behavior is controlled through the options object, while functional data is
|
|
92
|
-
* passed as separate props.
|
|
93
|
-
*
|
|
94
|
-
* @example
|
|
95
|
-
* ```tsx
|
|
96
|
-
* <ResourcePicker
|
|
97
|
-
* resources={processedResources}
|
|
98
|
-
* selectedResourceId={currentId}
|
|
99
|
-
* onResourceSelect={(selection) => {
|
|
100
|
-
* setCurrentId(selection.resourceId);
|
|
101
|
-
* if (selection.resourceData) {
|
|
102
|
-
* // Use the resource data directly
|
|
103
|
-
* handleResourceData(selection.resourceData);
|
|
104
|
-
* }
|
|
105
|
-
* }}
|
|
106
|
-
* resourceAnnotations={{
|
|
107
|
-
* 'res1': { badge: { text: '3', variant: 'info' } }
|
|
108
|
-
* }}
|
|
109
|
-
* options={{
|
|
110
|
-
* defaultView: 'tree',
|
|
111
|
-
* enableSearch: true,
|
|
112
|
-
* searchPlaceholder: 'Find resources...',
|
|
113
|
-
* height: '400px'
|
|
114
|
-
* }}
|
|
115
|
-
* />
|
|
116
|
-
* ```
|
|
117
|
-
*
|
|
118
|
-
* @public
|
|
119
|
-
*/
|
|
120
|
-
export interface ResourcePickerProps<T = unknown> extends ViewBaseProps {
|
|
121
|
-
/** Core functionality */
|
|
122
|
-
/** Processed resources to display in the picker */
|
|
123
|
-
resources: ProcessedResources | ExtendedProcessedResources | null;
|
|
124
|
-
/** Currently selected resource ID */
|
|
125
|
-
selectedResourceId: string | null;
|
|
126
|
-
/** Callback fired when a resource is selected, providing comprehensive selection data */
|
|
127
|
-
onResourceSelect: (selection: ResourceSelection<T>) => void;
|
|
128
|
-
|
|
129
|
-
/** Functional data */
|
|
130
|
-
/** Annotations to display next to resource names (badges, indicators, etc.) */
|
|
131
|
-
resourceAnnotations?: ResourceAnnotations;
|
|
132
|
-
/** Pending (unsaved) resources to display alongside persisted resources */
|
|
133
|
-
pendingResources?: PendingResource<T>[];
|
|
134
|
-
|
|
135
|
-
/** UI behavior configuration */
|
|
136
|
-
/** Options controlling picker appearance and behavior */
|
|
137
|
-
options?: ResourcePickerOptions;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Annotations that can be displayed next to resource names in the picker.
|
|
142
|
-
*
|
|
143
|
-
* This allows the host application to provide visual indicators for resources,
|
|
144
|
-
* such as candidate counts, editing status, or validation states.
|
|
145
|
-
*
|
|
146
|
-
* @example
|
|
147
|
-
* ```tsx
|
|
148
|
-
* const annotations: ResourceAnnotations = {
|
|
149
|
-
* 'user.welcome': {
|
|
150
|
-
* badge: { text: '3', variant: 'info' },
|
|
151
|
-
* suffix: '(3 candidates)'
|
|
152
|
-
* },
|
|
153
|
-
* 'user.modified': {
|
|
154
|
-
* badge: { text: 'M', variant: 'edited' },
|
|
155
|
-
* indicator: { type: 'dot', value: 'orange', tooltip: 'Modified' }
|
|
156
|
-
* }
|
|
157
|
-
* };
|
|
158
|
-
* ```
|
|
159
|
-
*
|
|
160
|
-
* @public
|
|
161
|
-
*/
|
|
162
|
-
export interface ResourceAnnotations {
|
|
163
|
-
/** Map of resource IDs to their annotation configurations */
|
|
164
|
-
[resourceId: string]: ResourceAnnotation;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Individual resource annotation configuration.
|
|
169
|
-
*
|
|
170
|
-
* Supports multiple types of visual indicators that can be combined:
|
|
171
|
-
* - Badge: Small colored badge with text
|
|
172
|
-
* - Indicator: Dot, icon, or text indicator with optional tooltip
|
|
173
|
-
* - Suffix: Additional content displayed after the resource name
|
|
174
|
-
*
|
|
175
|
-
* @example
|
|
176
|
-
* ```tsx
|
|
177
|
-
* const annotation: ResourceAnnotation = {
|
|
178
|
-
* badge: { text: 'NEW', variant: 'new' },
|
|
179
|
-
* indicator: {
|
|
180
|
-
* type: 'icon',
|
|
181
|
-
* value: <CheckIcon />,
|
|
182
|
-
* tooltip: 'Validated'
|
|
183
|
-
* },
|
|
184
|
-
* suffix: <span className="text-gray-500">(5 candidates)</span>,
|
|
185
|
-
* className: 'resource-highlighted'
|
|
186
|
-
* };
|
|
187
|
-
* ```
|
|
188
|
-
*
|
|
189
|
-
* @public
|
|
190
|
-
*/
|
|
191
|
-
export interface ResourceAnnotation {
|
|
192
|
-
/** Small colored badge displayed next to the resource name */
|
|
193
|
-
badge?: {
|
|
194
|
-
/** Text content of the badge */
|
|
195
|
-
text: string;
|
|
196
|
-
/** Visual style variant for the badge */
|
|
197
|
-
variant: 'info' | 'warning' | 'success' | 'error' | 'edited' | 'new';
|
|
198
|
-
};
|
|
199
|
-
/** Visual indicator (dot, icon, or text) with optional tooltip */
|
|
200
|
-
indicator?: {
|
|
201
|
-
/** Type of indicator to display */
|
|
202
|
-
type: 'dot' | 'icon' | 'text';
|
|
203
|
-
/** Content of the indicator (color for dot, React element for icon, string for text) */
|
|
204
|
-
value: string | React.ReactNode;
|
|
205
|
-
/** Optional tooltip text shown on hover */
|
|
206
|
-
tooltip?: string;
|
|
207
|
-
};
|
|
208
|
-
/** Additional content displayed after the resource name (e.g., candidate counts) */
|
|
209
|
-
suffix?: React.ReactNode;
|
|
210
|
-
/** Additional CSS class names to apply to the resource item */
|
|
211
|
-
className?: string;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Represents a resource that hasn't been persisted yet.
|
|
216
|
-
*
|
|
217
|
-
* Pending resources are displayed alongside persisted resources in the picker,
|
|
218
|
-
* allowing users to interact with unsaved changes. They are visually distinguished
|
|
219
|
-
* with appropriate styling and annotations.
|
|
220
|
-
*
|
|
221
|
-
* @example
|
|
222
|
-
* ```tsx
|
|
223
|
-
* const pendingResources: PendingResource<MyResourceType>[] = [
|
|
224
|
-
* {
|
|
225
|
-
* id: 'user.new-welcome',
|
|
226
|
-
* type: 'new',
|
|
227
|
-
* resourceType: 'string',
|
|
228
|
-
* displayName: 'Welcome Message (New)',
|
|
229
|
-
* resourceData: { text: 'Welcome!', locale: 'en' }
|
|
230
|
-
* },
|
|
231
|
-
* {
|
|
232
|
-
* id: 'user.existing-modified',
|
|
233
|
-
* type: 'modified',
|
|
234
|
-
* displayName: 'User Profile (Modified)',
|
|
235
|
-
* resourceData: { name: 'Updated Name' }
|
|
236
|
-
* }
|
|
237
|
-
* ];
|
|
238
|
-
* ```
|
|
239
|
-
*
|
|
240
|
-
* @public
|
|
241
|
-
*/
|
|
242
|
-
export interface PendingResource<T = unknown> {
|
|
243
|
-
/** Unique identifier for the pending resource */
|
|
244
|
-
id: string;
|
|
245
|
-
/** Type of pending operation */
|
|
246
|
-
type: 'new' | 'modified' | 'deleted';
|
|
247
|
-
/** Optional resource type identifier */
|
|
248
|
-
resourceType?: string;
|
|
249
|
-
/** Display name for the resource in the picker */
|
|
250
|
-
displayName?: string;
|
|
251
|
-
/** The actual resource data with type safety */
|
|
252
|
-
resourceData?: T;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Props for individual resource items
|
|
257
|
-
*/
|
|
258
|
-
export interface ResourceItemProps<T = unknown> {
|
|
259
|
-
resourceId: string;
|
|
260
|
-
displayName?: string;
|
|
261
|
-
isSelected: boolean;
|
|
262
|
-
isPending?: boolean;
|
|
263
|
-
annotation?: ResourceAnnotation;
|
|
264
|
-
onClick: (selection: ResourceSelection<T>) => void;
|
|
265
|
-
searchTerm?: string;
|
|
266
|
-
className?: string;
|
|
267
|
-
resourceData?: T; // The actual resource data if available
|
|
268
|
-
pendingType?: 'new' | 'modified' | 'deleted'; // Type of pending operation
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Props for the list view component
|
|
273
|
-
*/
|
|
274
|
-
export interface ResourcePickerListProps<T = unknown> {
|
|
275
|
-
resourceIds: string[];
|
|
276
|
-
pendingResources?: PendingResource<T>[];
|
|
277
|
-
selectedResourceId: string | null;
|
|
278
|
-
onResourceSelect: (selection: ResourceSelection<T>) => void;
|
|
279
|
-
resourceAnnotations?: ResourceAnnotations;
|
|
280
|
-
searchTerm?: string;
|
|
281
|
-
rootPath?: string;
|
|
282
|
-
hideRootNode?: boolean;
|
|
283
|
-
className?: string;
|
|
284
|
-
emptyMessage?: string;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
/**
|
|
288
|
-
* Props for the tree view component
|
|
289
|
-
*/
|
|
290
|
-
export interface ResourcePickerTreeProps<T = unknown> {
|
|
291
|
-
resources: ProcessedResources | ExtendedProcessedResources;
|
|
292
|
-
pendingResources?: PendingResource<T>[];
|
|
293
|
-
selectedResourceId: string | null;
|
|
294
|
-
onResourceSelect: (selection: ResourceSelection<T>) => void;
|
|
295
|
-
resourceAnnotations?: ResourceAnnotations;
|
|
296
|
-
searchTerm?: string;
|
|
297
|
-
rootPath?: string;
|
|
298
|
-
hideRootNode?: boolean;
|
|
299
|
-
className?: string;
|
|
300
|
-
emptyMessage?: string;
|
|
301
|
-
}
|