@fgv/ts-res-ui-components 5.0.0-17 → 5.0.0-18
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 +56 -12
- package/dist/ts-res-ui-components.d.ts +114 -22
- package/lib/components/common/ResourcePickerOptionsControl.d.ts +43 -0
- package/lib/components/common/ResourcePickerOptionsControl.js +142 -0
- package/lib/components/pickers/ResourcePicker/index.d.ts +1 -1
- package/lib/components/pickers/ResourcePicker/index.js +3 -1
- package/lib/components/pickers/ResourcePicker/types.d.ts +57 -20
- package/lib/components/views/CompiledView/index.js +20 -2
- package/lib/components/views/FilterView/index.js +28 -2
- package/lib/components/views/ResolutionView/index.js +21 -3
- package/lib/components/views/SourceView/index.js +21 -3
- package/lib/namespaces/PickerTools.d.ts +16 -3
- package/lib/namespaces/PickerTools.js +15 -2
- package/lib/types/index.d.ts +10 -0
- package/lib-commonjs/components/common/ResourcePickerOptionsControl.js +147 -0
- package/lib-commonjs/components/pickers/ResourcePicker/index.js +3 -1
- package/lib-commonjs/components/views/CompiledView/index.js +20 -2
- package/lib-commonjs/components/views/FilterView/index.js +28 -2
- package/lib-commonjs/components/views/ResolutionView/index.js +20 -2
- package/lib-commonjs/components/views/SourceView/index.js +20 -2
- package/lib-commonjs/namespaces/PickerTools.js +17 -3
- package/package.json +7 -7
- package/src/components/common/ResourcePickerOptionsControl.tsx +351 -0
- package/src/components/pickers/ResourcePicker/README.md +93 -0
- package/src/components/pickers/ResourcePicker/index.tsx +14 -10
- package/src/components/pickers/ResourcePicker/types.ts +61 -25
- package/src/components/views/CompiledView/index.tsx +41 -8
- package/src/components/views/FilterView/index.tsx +49 -10
- package/src/components/views/ResolutionView/index.tsx +41 -8
- package/src/components/views/SourceView/index.tsx +43 -9
- package/src/namespaces/PickerTools.ts +20 -2
- package/src/types/index.ts +10 -0
package/README.md
CHANGED
|
@@ -247,9 +247,12 @@ is a generic component used by all of the views, which can also be used to power
|
|
|
247
247
|
console.log(`Pending ${selection.pendingType} operation`);
|
|
248
248
|
}
|
|
249
249
|
}}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
250
|
+
options={{
|
|
251
|
+
defaultView: "tree",
|
|
252
|
+
enableSearch: true,
|
|
253
|
+
searchPlaceholder: "Search resources...",
|
|
254
|
+
height: "500px"
|
|
255
|
+
}}
|
|
253
256
|
resourceAnnotations={{
|
|
254
257
|
'user.welcome': {
|
|
255
258
|
badge: { text: '3', variant: 'info' },
|
|
@@ -257,7 +260,6 @@ is a generic component used by all of the views, which can also be used to power
|
|
|
257
260
|
}
|
|
258
261
|
}}
|
|
259
262
|
pendingResources={pendingChanges}
|
|
260
|
-
height="500px"
|
|
261
263
|
/>
|
|
262
264
|
```
|
|
263
265
|
|
|
@@ -268,6 +270,36 @@ is a generic component used by all of the views, which can also be used to power
|
|
|
268
270
|
- **Pending resources**: Show unsaved changes with visual distinction
|
|
269
271
|
- **Branch isolation**: Focus on specific parts of large resource trees
|
|
270
272
|
- **Type safety**: Full TypeScript support with generic resource types
|
|
273
|
+
- **Debug controls**: Optional ResourcePickerOptionsControl for development and debugging
|
|
274
|
+
|
|
275
|
+
#### ResourcePickerOptionsControl
|
|
276
|
+
|
|
277
|
+
A debugging/design tool for interactively configuring ResourcePicker behavior. Hidden by default for production use, but can be enabled in development:
|
|
278
|
+
|
|
279
|
+
```tsx
|
|
280
|
+
// All view components support pickerOptionsPresentation
|
|
281
|
+
<SourceView
|
|
282
|
+
resources={state.processedResources}
|
|
283
|
+
pickerOptionsPresentation="collapsible" // Enable picker options UI
|
|
284
|
+
onMessage={(type, message) => console.log(`${type}: ${message}`)}
|
|
285
|
+
/>
|
|
286
|
+
|
|
287
|
+
// Direct usage in custom components
|
|
288
|
+
<PickerTools.ResourcePickerOptionsControl
|
|
289
|
+
options={pickerOptions}
|
|
290
|
+
onOptionsChange={setPickerOptions}
|
|
291
|
+
presentation="popup" // 'hidden' | 'inline' | 'collapsible' | 'popup' | 'popover'
|
|
292
|
+
title="Picker Configuration"
|
|
293
|
+
showAdvanced={true}
|
|
294
|
+
/>
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
**Presentation modes:**
|
|
298
|
+
- `'hidden'`: Not displayed (default for production)
|
|
299
|
+
- `'inline'`: Always visible with expanded controls
|
|
300
|
+
- `'collapsible'`: Expandable/collapsible section
|
|
301
|
+
- `'popup'`: Full modal dialog overlay
|
|
302
|
+
- `'popover'`: Small dropdown overlay
|
|
271
303
|
|
|
272
304
|
### SourceView
|
|
273
305
|
|
|
@@ -278,9 +310,13 @@ Displays the source resource collection with search and navigation capabilities
|
|
|
278
310
|
```tsx
|
|
279
311
|
<SourceView
|
|
280
312
|
resources={state.processedResources}
|
|
281
|
-
selectedResourceId={selectedId}
|
|
282
|
-
onResourceSelect={(selection) => setSelectedId(selection.resourceId)}
|
|
283
313
|
onExport={actions.exportData}
|
|
314
|
+
onMessage={(type, message) => console.log(`${type}: ${message}`)}
|
|
315
|
+
pickerOptions={{
|
|
316
|
+
defaultView: "list",
|
|
317
|
+
enableSearch: true,
|
|
318
|
+
searchPlaceholder: "Search resources..."
|
|
319
|
+
}}
|
|
284
320
|
/>
|
|
285
321
|
```
|
|
286
322
|
|
|
@@ -297,9 +333,10 @@ Provides filtering capabilities with context value specification and dual-resour
|
|
|
297
333
|
filterActions={filterActions}
|
|
298
334
|
filterResult={filterResult}
|
|
299
335
|
onFilterResult={setFilterResult}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
336
|
+
onMessage={(type, message) => console.log(`${type}: ${message}`)}
|
|
337
|
+
pickerOptions={{
|
|
338
|
+
enableSearch: true,
|
|
339
|
+
searchPlaceholder: "Search resources..."
|
|
303
340
|
}}
|
|
304
341
|
/>
|
|
305
342
|
```
|
|
@@ -316,9 +353,10 @@ Shows the compiled resource structure with detailed candidate information using
|
|
|
316
353
|
filterResult={filterResult}
|
|
317
354
|
useNormalization={true}
|
|
318
355
|
onExport={(data, type) => exportData(data, type)}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
356
|
+
onMessage={(type, message) => console.log(`${type}: ${message}`)}
|
|
357
|
+
pickerOptions={{
|
|
358
|
+
defaultView: "tree",
|
|
359
|
+
enableSearch: true
|
|
322
360
|
}}
|
|
323
361
|
/>
|
|
324
362
|
```
|
|
@@ -336,6 +374,12 @@ Interactive resource resolution testing with context management and support for
|
|
|
336
374
|
resolutionActions={resolutionActions}
|
|
337
375
|
availableQualifiers={availableQualifiers}
|
|
338
376
|
resourceEditorFactory={myResourceEditorFactory}
|
|
377
|
+
onMessage={(type, message) => console.log(`${type}: ${message}`)}
|
|
378
|
+
pickerOptions={{
|
|
379
|
+
defaultView: "list",
|
|
380
|
+
enableSearch: true,
|
|
381
|
+
searchPlaceholder: "Search resources for resolution testing..."
|
|
382
|
+
}}
|
|
339
383
|
/>
|
|
340
384
|
```
|
|
341
385
|
|
|
@@ -183,6 +183,8 @@ declare interface CompiledViewProps extends ViewBaseProps {
|
|
|
183
183
|
useNormalization?: boolean;
|
|
184
184
|
/** Callback for exporting compiled data or bundles */
|
|
185
185
|
onExport?: (data: ResourceJson.Compiled.ICompiledResourceCollection | Bundle.IBundle, type: 'json' | 'bundle') => void;
|
|
186
|
+
/** Optional configuration for the ResourcePicker behavior */
|
|
187
|
+
pickerOptions?: ResourcePickerOptions;
|
|
186
188
|
}
|
|
187
189
|
|
|
188
190
|
/**
|
|
@@ -1332,6 +1334,8 @@ declare interface FilterViewProps extends ViewBaseProps {
|
|
|
1332
1334
|
filterResult?: FilterResult | null;
|
|
1333
1335
|
/** Callback when filter results change */
|
|
1334
1336
|
onFilterResult?: (result: FilterResult | null) => void;
|
|
1337
|
+
/** Optional configuration for the ResourcePicker behavior */
|
|
1338
|
+
pickerOptions?: ResourcePickerOptions;
|
|
1335
1339
|
}
|
|
1336
1340
|
|
|
1337
1341
|
/**
|
|
@@ -2253,11 +2257,14 @@ declare interface PendingResource<T = unknown> {
|
|
|
2253
2257
|
export declare namespace PickerTools {
|
|
2254
2258
|
export {
|
|
2255
2259
|
ResourcePicker,
|
|
2260
|
+
ResourcePickerOptionsControl,
|
|
2256
2261
|
ResourcePickerProps,
|
|
2262
|
+
ResourcePickerOptions,
|
|
2257
2263
|
ResourceSelection,
|
|
2258
2264
|
ResourceAnnotations,
|
|
2259
2265
|
ResourceAnnotation,
|
|
2260
|
-
PendingResource
|
|
2266
|
+
PendingResource,
|
|
2267
|
+
ResourcePickerOptionsControlProps
|
|
2261
2268
|
}
|
|
2262
2269
|
}
|
|
2263
2270
|
|
|
@@ -3205,6 +3212,8 @@ declare interface ResolutionViewProps extends ViewBaseProps {
|
|
|
3205
3212
|
availableQualifiers?: string[];
|
|
3206
3213
|
/** Optional factory for creating type-specific resource editors */
|
|
3207
3214
|
resourceEditorFactory?: ResourceEditorFactory;
|
|
3215
|
+
/** Optional configuration for the ResourcePicker behavior */
|
|
3216
|
+
pickerOptions?: ResourcePickerOptions;
|
|
3208
3217
|
}
|
|
3209
3218
|
|
|
3210
3219
|
/**
|
|
@@ -3730,13 +3739,101 @@ declare interface ResourceOrchestratorProps {
|
|
|
3730
3739
|
*
|
|
3731
3740
|
* @public
|
|
3732
3741
|
*/
|
|
3733
|
-
declare const ResourcePicker: <T = unknown>({ resources, selectedResourceId, onResourceSelect,
|
|
3742
|
+
declare const ResourcePicker: <T = unknown>({ resources, selectedResourceId, onResourceSelect, resourceAnnotations, pendingResources, options, className, onMessage }: ResourcePickerProps<T>) => React_2.JSX.Element;
|
|
3743
|
+
|
|
3744
|
+
/**
|
|
3745
|
+
* UI behavior configuration options for ResourcePicker.
|
|
3746
|
+
*
|
|
3747
|
+
* This interface groups all UI-related options that control how the ResourcePicker
|
|
3748
|
+
* behaves and appears, separate from functional data like annotations and pending resources.
|
|
3749
|
+
*
|
|
3750
|
+
* @example
|
|
3751
|
+
* ```tsx
|
|
3752
|
+
* const pickerOptions: ResourcePickerOptions = {
|
|
3753
|
+
* defaultView: 'tree',
|
|
3754
|
+
* enableSearch: true,
|
|
3755
|
+
* searchPlaceholder: 'Find resources...',
|
|
3756
|
+
* rootPath: 'user.messages',
|
|
3757
|
+
* hideRootNode: true,
|
|
3758
|
+
* height: '400px'
|
|
3759
|
+
* };
|
|
3760
|
+
* ```
|
|
3761
|
+
*
|
|
3762
|
+
* @public
|
|
3763
|
+
*/
|
|
3764
|
+
declare interface ResourcePickerOptions {
|
|
3765
|
+
/** View and navigation options */
|
|
3766
|
+
/** Default view mode to use on initial render */
|
|
3767
|
+
defaultView?: 'list' | 'tree';
|
|
3768
|
+
/** Whether to show the list/tree view toggle buttons */
|
|
3769
|
+
showViewToggle?: boolean;
|
|
3770
|
+
/** Branch isolation options */
|
|
3771
|
+
/** Path to treat as root for tree branch isolation (e.g., "platform/territories") */
|
|
3772
|
+
rootPath?: string;
|
|
3773
|
+
/** Hide the root node itself, showing only its children */
|
|
3774
|
+
hideRootNode?: boolean;
|
|
3775
|
+
/** Search options */
|
|
3776
|
+
/** Whether to enable the search input */
|
|
3777
|
+
enableSearch?: boolean;
|
|
3778
|
+
/** Placeholder text for the search input */
|
|
3779
|
+
searchPlaceholder?: string;
|
|
3780
|
+
/** Scope of search - entire tree or just the currently visible branch */
|
|
3781
|
+
searchScope?: 'all' | 'current-branch';
|
|
3782
|
+
/** Appearance options */
|
|
3783
|
+
/** Message to display when no resources are available */
|
|
3784
|
+
emptyMessage?: string;
|
|
3785
|
+
/** Height of the picker component */
|
|
3786
|
+
height?: string | number;
|
|
3787
|
+
}
|
|
3788
|
+
|
|
3789
|
+
/**
|
|
3790
|
+
* Reusable control for configuring ResourcePicker options.
|
|
3791
|
+
*
|
|
3792
|
+
* Provides a clean interface for adjusting picker behavior including:
|
|
3793
|
+
* - View mode selection (list/tree)
|
|
3794
|
+
* - Search and view toggle settings
|
|
3795
|
+
* - Branch isolation configuration
|
|
3796
|
+
* - Quick path selection buttons
|
|
3797
|
+
*
|
|
3798
|
+
* Can be rendered in multiple presentation modes:
|
|
3799
|
+
* - 'hidden': Not displayed (default for production)
|
|
3800
|
+
* - 'inline': Always expanded with full controls visible
|
|
3801
|
+
* - 'collapsible': Expandable/collapsible section
|
|
3802
|
+
* - 'popover': Small dropdown overlay
|
|
3803
|
+
* - 'popup': Full modal dialog
|
|
3804
|
+
*
|
|
3805
|
+
* @public
|
|
3806
|
+
*/
|
|
3807
|
+
declare const ResourcePickerOptionsControl: React_2.FC<ResourcePickerOptionsControlProps>;
|
|
3808
|
+
|
|
3809
|
+
/**
|
|
3810
|
+
* Props for the ResourcePickerOptionsControl component.
|
|
3811
|
+
* @public
|
|
3812
|
+
*/
|
|
3813
|
+
declare interface ResourcePickerOptionsControlProps {
|
|
3814
|
+
/** Current picker options */
|
|
3815
|
+
options: ResourcePickerOptions;
|
|
3816
|
+
/** Callback when options change */
|
|
3817
|
+
onOptionsChange: (options: ResourcePickerOptions) => void;
|
|
3818
|
+
/** How to present the options control (default: 'hidden' for production use) */
|
|
3819
|
+
presentation?: 'hidden' | 'inline' | 'collapsible' | 'popup' | 'popover';
|
|
3820
|
+
/** Custom class name */
|
|
3821
|
+
className?: string;
|
|
3822
|
+
/** Available quick branch paths for selection */
|
|
3823
|
+
quickBranchPaths?: string[];
|
|
3824
|
+
/** Whether to show advanced options like branch isolation */
|
|
3825
|
+
showAdvanced?: boolean;
|
|
3826
|
+
/** Title for the control section */
|
|
3827
|
+
title?: string;
|
|
3828
|
+
}
|
|
3734
3829
|
|
|
3735
3830
|
/**
|
|
3736
3831
|
* Props for the ResourcePicker component.
|
|
3737
3832
|
*
|
|
3738
3833
|
* The ResourcePicker is a comprehensive component for browsing and selecting resources
|
|
3739
3834
|
* with support for multiple view modes, search, annotations, and pending resources.
|
|
3835
|
+
* UI behavior is controlled through the options object, while functional data is
|
|
3836
|
+
* passed as separate props.
|
|
3740
3837
|
*
|
|
3741
3838
|
* @example
|
|
3742
3839
|
* ```tsx
|
|
@@ -3750,45 +3847,36 @@ declare const ResourcePicker: <T = unknown>({ resources, selectedResourceId, onR
|
|
|
3750
3847
|
* handleResourceData(selection.resourceData);
|
|
3751
3848
|
* }
|
|
3752
3849
|
* }}
|
|
3753
|
-
* defaultView="tree"
|
|
3754
|
-
* enableSearch={true}
|
|
3755
3850
|
* resourceAnnotations={{
|
|
3756
3851
|
* 'res1': { badge: { text: '3', variant: 'info' } }
|
|
3757
3852
|
* }}
|
|
3853
|
+
* options={{
|
|
3854
|
+
* defaultView: 'tree',
|
|
3855
|
+
* enableSearch: true,
|
|
3856
|
+
* searchPlaceholder: 'Find resources...',
|
|
3857
|
+
* height: '400px'
|
|
3858
|
+
* }}
|
|
3758
3859
|
* />
|
|
3759
3860
|
* ```
|
|
3760
3861
|
*
|
|
3761
3862
|
* @public
|
|
3762
3863
|
*/
|
|
3763
3864
|
declare interface ResourcePickerProps<T = unknown> extends ViewBaseProps {
|
|
3865
|
+
/** Core functionality */
|
|
3764
3866
|
/** Processed resources to display in the picker */
|
|
3765
3867
|
resources: ProcessedResources | ExtendedProcessedResources | null;
|
|
3766
3868
|
/** Currently selected resource ID */
|
|
3767
3869
|
selectedResourceId: string | null;
|
|
3768
3870
|
/** Callback fired when a resource is selected, providing comprehensive selection data */
|
|
3769
3871
|
onResourceSelect: (selection: ResourceSelection<T>) => void;
|
|
3770
|
-
/**
|
|
3771
|
-
defaultView?: 'list' | 'tree';
|
|
3772
|
-
/** Whether to show the list/tree view toggle buttons */
|
|
3773
|
-
showViewToggle?: boolean;
|
|
3774
|
-
/** Path to treat as root for tree branch isolation (e.g., "platform/territories") */
|
|
3775
|
-
rootPath?: string;
|
|
3776
|
-
/** Hide the root node itself, showing only its children */
|
|
3777
|
-
hideRootNode?: boolean;
|
|
3778
|
-
/** Whether to enable the search input */
|
|
3779
|
-
enableSearch?: boolean;
|
|
3780
|
-
/** Placeholder text for the search input */
|
|
3781
|
-
searchPlaceholder?: string;
|
|
3782
|
-
/** Scope of search - entire tree or just the currently visible branch */
|
|
3783
|
-
searchScope?: 'all' | 'current-branch';
|
|
3872
|
+
/** Functional data */
|
|
3784
3873
|
/** Annotations to display next to resource names (badges, indicators, etc.) */
|
|
3785
3874
|
resourceAnnotations?: ResourceAnnotations;
|
|
3786
3875
|
/** Pending (unsaved) resources to display alongside persisted resources */
|
|
3787
3876
|
pendingResources?: PendingResource<T>[];
|
|
3788
|
-
/**
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
height?: string | number;
|
|
3877
|
+
/** UI behavior configuration */
|
|
3878
|
+
/** Options controlling picker appearance and behavior */
|
|
3879
|
+
options?: ResourcePickerOptions;
|
|
3792
3880
|
}
|
|
3793
3881
|
|
|
3794
3882
|
/**
|
|
@@ -4283,6 +4371,8 @@ declare interface SourceViewProps extends ViewBaseProps {
|
|
|
4283
4371
|
onResourceSelect?: (resourceId: string) => void;
|
|
4284
4372
|
/** Callback when exporting resource collection data */
|
|
4285
4373
|
onExport?: (data: unknown, type: 'json') => void;
|
|
4374
|
+
/** Optional configuration for the ResourcePicker behavior */
|
|
4375
|
+
pickerOptions?: ResourcePickerOptions;
|
|
4286
4376
|
}
|
|
4287
4377
|
|
|
4288
4378
|
export declare namespace TsResTools {
|
|
@@ -4688,6 +4778,8 @@ declare interface ViewBaseProps {
|
|
|
4688
4778
|
onMessage?: (type: Message['type'], message: string) => void;
|
|
4689
4779
|
/** Additional CSS class names for styling */
|
|
4690
4780
|
className?: string;
|
|
4781
|
+
/** How to present the ResourcePicker options control (default: 'hidden' for production use) */
|
|
4782
|
+
pickerOptionsPresentation?: 'hidden' | 'inline' | 'collapsible' | 'popup' | 'popover';
|
|
4691
4783
|
}
|
|
4692
4784
|
|
|
4693
4785
|
export declare namespace ViewStateTools {
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ResourcePickerOptions } from '../pickers/ResourcePicker/types';
|
|
3
|
+
/**
|
|
4
|
+
* Props for the ResourcePickerOptionsControl component.
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export interface ResourcePickerOptionsControlProps {
|
|
8
|
+
/** Current picker options */
|
|
9
|
+
options: ResourcePickerOptions;
|
|
10
|
+
/** Callback when options change */
|
|
11
|
+
onOptionsChange: (options: ResourcePickerOptions) => void;
|
|
12
|
+
/** How to present the options control (default: 'hidden' for production use) */
|
|
13
|
+
presentation?: 'hidden' | 'inline' | 'collapsible' | 'popup' | 'popover';
|
|
14
|
+
/** Custom class name */
|
|
15
|
+
className?: string;
|
|
16
|
+
/** Available quick branch paths for selection */
|
|
17
|
+
quickBranchPaths?: string[];
|
|
18
|
+
/** Whether to show advanced options like branch isolation */
|
|
19
|
+
showAdvanced?: boolean;
|
|
20
|
+
/** Title for the control section */
|
|
21
|
+
title?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Reusable control for configuring ResourcePicker options.
|
|
25
|
+
*
|
|
26
|
+
* Provides a clean interface for adjusting picker behavior including:
|
|
27
|
+
* - View mode selection (list/tree)
|
|
28
|
+
* - Search and view toggle settings
|
|
29
|
+
* - Branch isolation configuration
|
|
30
|
+
* - Quick path selection buttons
|
|
31
|
+
*
|
|
32
|
+
* Can be rendered in multiple presentation modes:
|
|
33
|
+
* - 'hidden': Not displayed (default for production)
|
|
34
|
+
* - 'inline': Always expanded with full controls visible
|
|
35
|
+
* - 'collapsible': Expandable/collapsible section
|
|
36
|
+
* - 'popover': Small dropdown overlay
|
|
37
|
+
* - 'popup': Full modal dialog
|
|
38
|
+
*
|
|
39
|
+
* @public
|
|
40
|
+
*/
|
|
41
|
+
export declare const ResourcePickerOptionsControl: React.FC<ResourcePickerOptionsControlProps>;
|
|
42
|
+
export default ResourcePickerOptionsControl;
|
|
43
|
+
//# sourceMappingURL=ResourcePickerOptionsControl.d.ts.map
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import React, { useState, useCallback } from 'react';
|
|
2
|
+
import { CogIcon, ChevronDownIcon, ChevronUpIcon, XMarkIcon } from '@heroicons/react/24/outline';
|
|
3
|
+
/**
|
|
4
|
+
* Reusable control for configuring ResourcePicker options.
|
|
5
|
+
*
|
|
6
|
+
* Provides a clean interface for adjusting picker behavior including:
|
|
7
|
+
* - View mode selection (list/tree)
|
|
8
|
+
* - Search and view toggle settings
|
|
9
|
+
* - Branch isolation configuration
|
|
10
|
+
* - Quick path selection buttons
|
|
11
|
+
*
|
|
12
|
+
* Can be rendered in multiple presentation modes:
|
|
13
|
+
* - 'hidden': Not displayed (default for production)
|
|
14
|
+
* - 'inline': Always expanded with full controls visible
|
|
15
|
+
* - 'collapsible': Expandable/collapsible section
|
|
16
|
+
* - 'popover': Small dropdown overlay
|
|
17
|
+
* - 'popup': Full modal dialog
|
|
18
|
+
*
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
export const ResourcePickerOptionsControl = ({ options, onOptionsChange, presentation = 'hidden', className = '', quickBranchPaths = ['strings', 'app', 'images', 'app.ui'], showAdvanced = true, title = 'Picker Options' }) => {
|
|
22
|
+
// Early return for hidden presentation
|
|
23
|
+
if (presentation === 'hidden') {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
const [isExpanded, setIsExpanded] = useState(presentation === 'inline');
|
|
27
|
+
const [showPopover, setShowPopover] = useState(false);
|
|
28
|
+
const handleOptionChange = useCallback((key, value) => {
|
|
29
|
+
onOptionsChange({
|
|
30
|
+
...options,
|
|
31
|
+
[key]: value
|
|
32
|
+
});
|
|
33
|
+
}, [options, onOptionsChange]);
|
|
34
|
+
const handleQuickPathSelect = useCallback((path) => {
|
|
35
|
+
handleOptionChange('rootPath', path);
|
|
36
|
+
}, [handleOptionChange]);
|
|
37
|
+
const clearRootPath = useCallback(() => {
|
|
38
|
+
handleOptionChange('rootPath', undefined);
|
|
39
|
+
handleOptionChange('hideRootNode', false);
|
|
40
|
+
}, [handleOptionChange]);
|
|
41
|
+
const renderControls = () => (React.createElement("div", { className: "space-y-4" },
|
|
42
|
+
React.createElement("div", { className: "space-y-3" },
|
|
43
|
+
React.createElement("h4", { className: "text-sm font-medium text-gray-700" }, "View Settings"),
|
|
44
|
+
React.createElement("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3" },
|
|
45
|
+
React.createElement("div", null,
|
|
46
|
+
React.createElement("label", { className: "block text-xs font-medium text-gray-600 mb-1" }, "Default View"),
|
|
47
|
+
React.createElement("select", { value: options.defaultView || 'list', onChange: (e) => handleOptionChange('defaultView', e.target.value), className: "w-full px-2 py-1 text-xs border border-gray-300 rounded focus:outline-none focus:ring-1 focus:ring-blue-500" },
|
|
48
|
+
React.createElement("option", { value: "list" }, "List"),
|
|
49
|
+
React.createElement("option", { value: "tree" }, "Tree"))),
|
|
50
|
+
React.createElement("div", null,
|
|
51
|
+
React.createElement("label", { className: "block text-xs font-medium text-gray-600 mb-1" }, "Search Scope"),
|
|
52
|
+
React.createElement("select", { value: options.searchScope || 'all', onChange: (e) => handleOptionChange('searchScope', e.target.value), className: "w-full px-2 py-1 text-xs border border-gray-300 rounded focus:outline-none focus:ring-1 focus:ring-blue-500", disabled: !options.enableSearch },
|
|
53
|
+
React.createElement("option", { value: "all" }, "All Resources"),
|
|
54
|
+
React.createElement("option", { value: "current-branch" }, "Current Branch")))),
|
|
55
|
+
React.createElement("div", { className: "space-y-2" },
|
|
56
|
+
React.createElement("label", { className: "flex items-center text-xs" },
|
|
57
|
+
React.createElement("input", { type: "checkbox", checked: options.enableSearch ?? true, onChange: (e) => handleOptionChange('enableSearch', e.target.checked), className: "mr-2 rounded" }),
|
|
58
|
+
"Enable Search"),
|
|
59
|
+
React.createElement("label", { className: "flex items-center text-xs" },
|
|
60
|
+
React.createElement("input", { type: "checkbox", checked: options.showViewToggle ?? true, onChange: (e) => handleOptionChange('showViewToggle', e.target.checked), className: "mr-2 rounded" }),
|
|
61
|
+
"Show View Toggle")),
|
|
62
|
+
options.enableSearch && (React.createElement("div", null,
|
|
63
|
+
React.createElement("label", { className: "block text-xs font-medium text-gray-600 mb-1" }, "Search Placeholder"),
|
|
64
|
+
React.createElement("input", { type: "text", value: options.searchPlaceholder || '', onChange: (e) => handleOptionChange('searchPlaceholder', e.target.value || undefined), placeholder: "Search resources...", className: "w-full px-2 py-1 text-xs border border-gray-300 rounded focus:outline-none focus:ring-1 focus:ring-blue-500" })))),
|
|
65
|
+
showAdvanced && (React.createElement("div", { className: "space-y-3 pt-3 border-t border-gray-200" },
|
|
66
|
+
React.createElement("h4", { className: "text-sm font-medium text-gray-700" }, "Branch Isolation"),
|
|
67
|
+
React.createElement("div", null,
|
|
68
|
+
React.createElement("label", { className: "block text-xs font-medium text-gray-600 mb-1" }, "Root Path"),
|
|
69
|
+
React.createElement("input", { type: "text", value: options.rootPath || '', onChange: (e) => handleOptionChange('rootPath', e.target.value || undefined), placeholder: "e.g., strings or app.ui", className: "w-full px-2 py-1 text-xs border border-gray-300 rounded focus:outline-none focus:ring-1 focus:ring-blue-500" }),
|
|
70
|
+
React.createElement("p", { className: "text-xs text-gray-500 mt-1" }, "Show only resources under this path")),
|
|
71
|
+
React.createElement("div", null,
|
|
72
|
+
React.createElement("label", { className: "flex items-center text-xs" },
|
|
73
|
+
React.createElement("input", { type: "checkbox", checked: options.hideRootNode ?? false, onChange: (e) => handleOptionChange('hideRootNode', e.target.checked), className: "mr-2 rounded", disabled: !options.rootPath }),
|
|
74
|
+
"Hide Root Node"),
|
|
75
|
+
React.createElement("p", { className: "text-xs text-gray-500 mt-1 ml-5" }, "Show only children of root path (requires Root Path)")),
|
|
76
|
+
React.createElement("div", null,
|
|
77
|
+
React.createElement("label", { className: "block text-xs font-medium text-gray-600 mb-2" }, "Quick Paths"),
|
|
78
|
+
React.createElement("div", { className: "flex flex-wrap gap-1" },
|
|
79
|
+
quickBranchPaths.map((path) => (React.createElement("button", { key: path, onClick: () => handleQuickPathSelect(path), className: `px-2 py-1 text-xs rounded border ${options.rootPath === path
|
|
80
|
+
? 'bg-blue-100 border-blue-300 text-blue-700'
|
|
81
|
+
: 'bg-gray-50 border-gray-300 text-gray-600 hover:bg-gray-100'}` }, path))),
|
|
82
|
+
React.createElement("button", { onClick: clearRootPath, className: `px-2 py-1 text-xs rounded border ${!options.rootPath
|
|
83
|
+
? 'bg-blue-100 border-blue-300 text-blue-700'
|
|
84
|
+
: 'bg-gray-50 border-gray-300 text-gray-600 hover:bg-gray-100'}` }, "Clear"))))),
|
|
85
|
+
React.createElement("div", { className: "space-y-3 pt-3 border-t border-gray-200" },
|
|
86
|
+
React.createElement("h4", { className: "text-sm font-medium text-gray-700" }, "Display"),
|
|
87
|
+
React.createElement("div", null,
|
|
88
|
+
React.createElement("label", { className: "block text-xs font-medium text-gray-600 mb-1" }, "Empty Message"),
|
|
89
|
+
React.createElement("input", { type: "text", value: options.emptyMessage || '', onChange: (e) => handleOptionChange('emptyMessage', e.target.value || undefined), placeholder: "No resources available", className: "w-full px-2 py-1 text-xs border border-gray-300 rounded focus:outline-none focus:ring-1 focus:ring-blue-500" })),
|
|
90
|
+
React.createElement("div", null,
|
|
91
|
+
React.createElement("label", { className: "block text-xs font-medium text-gray-600 mb-1" }, "Height"),
|
|
92
|
+
React.createElement("input", { type: "text", value: options.height || '', onChange: (e) => handleOptionChange('height', e.target.value || undefined), placeholder: "600px", className: "w-full px-2 py-1 text-xs border border-gray-300 rounded focus:outline-none focus:ring-1 focus:ring-blue-500" }),
|
|
93
|
+
React.createElement("p", { className: "text-xs text-gray-500 mt-1" }, "CSS height value (px, rem, %, etc.)")))));
|
|
94
|
+
if (presentation === 'popover') {
|
|
95
|
+
return (React.createElement("div", { className: `relative ${className}` },
|
|
96
|
+
React.createElement("button", { onClick: () => setShowPopover(!showPopover), className: "flex items-center px-3 py-1.5 text-xs font-medium text-gray-700 bg-white border border-gray-300 rounded hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500" },
|
|
97
|
+
React.createElement(CogIcon, { className: "w-3 h-3 mr-1" }),
|
|
98
|
+
title,
|
|
99
|
+
React.createElement(ChevronDownIcon, { className: "w-3 h-3 ml-1" })),
|
|
100
|
+
showPopover && (React.createElement(React.Fragment, null,
|
|
101
|
+
React.createElement("div", { className: "fixed inset-0 z-10", onClick: () => setShowPopover(false) }),
|
|
102
|
+
React.createElement("div", { className: "absolute top-full left-0 mt-1 w-80 bg-white border border-gray-200 rounded-lg shadow-lg z-20 p-4" },
|
|
103
|
+
React.createElement("div", { className: "flex items-center justify-between mb-3" },
|
|
104
|
+
React.createElement("h3", { className: "text-sm font-medium text-gray-900" }, title),
|
|
105
|
+
React.createElement("button", { onClick: () => setShowPopover(false), className: "p-1 text-gray-400 hover:text-gray-600" },
|
|
106
|
+
React.createElement(XMarkIcon, { className: "w-4 h-4" }))),
|
|
107
|
+
renderControls())))));
|
|
108
|
+
}
|
|
109
|
+
if (presentation === 'collapsible') {
|
|
110
|
+
return (React.createElement("div", { className: `border border-gray-200 rounded-lg ${className}` },
|
|
111
|
+
React.createElement("button", { onClick: () => setIsExpanded(!isExpanded), className: "w-full flex items-center justify-between px-4 py-2 text-sm font-medium text-gray-700 bg-gray-50 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 rounded-t-lg" },
|
|
112
|
+
React.createElement("span", { className: "flex items-center" },
|
|
113
|
+
React.createElement(CogIcon, { className: "w-4 h-4 mr-2" }),
|
|
114
|
+
title),
|
|
115
|
+
isExpanded ? React.createElement(ChevronUpIcon, { className: "w-4 h-4" }) : React.createElement(ChevronDownIcon, { className: "w-4 h-4" })),
|
|
116
|
+
isExpanded && React.createElement("div", { className: "p-4 border-t border-gray-200" }, renderControls())));
|
|
117
|
+
}
|
|
118
|
+
if (presentation === 'popup') {
|
|
119
|
+
return (React.createElement("div", { className: `relative ${className}` },
|
|
120
|
+
React.createElement("button", { onClick: () => setShowPopover(!showPopover), className: "flex items-center px-3 py-1.5 text-xs font-medium text-gray-700 bg-white border border-gray-300 rounded hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500" },
|
|
121
|
+
React.createElement(CogIcon, { className: "w-3 h-3 mr-1" }),
|
|
122
|
+
title,
|
|
123
|
+
React.createElement(ChevronDownIcon, { className: "w-3 h-3 ml-1" })),
|
|
124
|
+
showPopover && (React.createElement(React.Fragment, null,
|
|
125
|
+
React.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setShowPopover(false) }),
|
|
126
|
+
React.createElement("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4" },
|
|
127
|
+
React.createElement("div", { className: "bg-white border border-gray-200 rounded-lg shadow-xl max-w-md w-full max-h-96 overflow-y-auto" },
|
|
128
|
+
React.createElement("div", { className: "flex items-center justify-between p-4 border-b border-gray-200" },
|
|
129
|
+
React.createElement("h3", { className: "text-lg font-medium text-gray-900" }, title),
|
|
130
|
+
React.createElement("button", { onClick: () => setShowPopover(false), className: "p-1 text-gray-400 hover:text-gray-600" },
|
|
131
|
+
React.createElement(XMarkIcon, { className: "w-5 h-5" }))),
|
|
132
|
+
React.createElement("div", { className: "p-4" }, renderControls())))))));
|
|
133
|
+
}
|
|
134
|
+
// presentation === 'inline'
|
|
135
|
+
return (React.createElement("div", { className: `border border-gray-200 rounded-lg p-4 ${className}` },
|
|
136
|
+
React.createElement("h3", { className: "text-sm font-medium text-gray-900 mb-3 flex items-center" },
|
|
137
|
+
React.createElement(CogIcon, { className: "w-4 h-4 mr-2" }),
|
|
138
|
+
title),
|
|
139
|
+
renderControls()));
|
|
140
|
+
};
|
|
141
|
+
export default ResourcePickerOptionsControl;
|
|
142
|
+
//# sourceMappingURL=ResourcePickerOptionsControl.js.map
|
|
@@ -56,6 +56,6 @@ import { ResourcePickerProps } from './types';
|
|
|
56
56
|
*
|
|
57
57
|
* @public
|
|
58
58
|
*/
|
|
59
|
-
export declare const ResourcePicker: <T = unknown>({ resources, selectedResourceId, onResourceSelect,
|
|
59
|
+
export declare const ResourcePicker: <T = unknown>({ resources, selectedResourceId, onResourceSelect, resourceAnnotations, pendingResources, options, className, onMessage }: ResourcePickerProps<T>) => React.JSX.Element;
|
|
60
60
|
export default ResourcePicker;
|
|
61
61
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -59,7 +59,9 @@ import { searchResources, filterTreeBranch } from './utils/treeNavigation';
|
|
|
59
59
|
*
|
|
60
60
|
* @public
|
|
61
61
|
*/
|
|
62
|
-
export const ResourcePicker = ({ resources, selectedResourceId, onResourceSelect,
|
|
62
|
+
export const ResourcePicker = ({ resources, selectedResourceId, onResourceSelect, resourceAnnotations, pendingResources, options, className = '', onMessage }) => {
|
|
63
|
+
// Extract options with defaults
|
|
64
|
+
const { defaultView = 'list', showViewToggle = true, rootPath, hideRootNode = false, enableSearch = true, searchPlaceholder, searchScope = 'current-branch', emptyMessage, height = '600px' } = options || {};
|
|
63
65
|
const [viewMode, setViewMode] = useState(defaultView);
|
|
64
66
|
const [searchTerm, setSearchTerm] = useState('');
|
|
65
67
|
// Get resource IDs based on current filters
|
|
@@ -33,11 +33,57 @@ export interface ResourceSelection<T = unknown> {
|
|
|
33
33
|
/** Type of pending operation for unsaved resources */
|
|
34
34
|
pendingType?: 'new' | 'modified' | 'deleted';
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* UI behavior configuration options for ResourcePicker.
|
|
38
|
+
*
|
|
39
|
+
* This interface groups all UI-related options that control how the ResourcePicker
|
|
40
|
+
* behaves and appears, separate from functional data like annotations and pending resources.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```tsx
|
|
44
|
+
* const pickerOptions: ResourcePickerOptions = {
|
|
45
|
+
* defaultView: 'tree',
|
|
46
|
+
* enableSearch: true,
|
|
47
|
+
* searchPlaceholder: 'Find resources...',
|
|
48
|
+
* rootPath: 'user.messages',
|
|
49
|
+
* hideRootNode: true,
|
|
50
|
+
* height: '400px'
|
|
51
|
+
* };
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* @public
|
|
55
|
+
*/
|
|
56
|
+
export interface ResourcePickerOptions {
|
|
57
|
+
/** View and navigation options */
|
|
58
|
+
/** Default view mode to use on initial render */
|
|
59
|
+
defaultView?: 'list' | 'tree';
|
|
60
|
+
/** Whether to show the list/tree view toggle buttons */
|
|
61
|
+
showViewToggle?: boolean;
|
|
62
|
+
/** Branch isolation options */
|
|
63
|
+
/** Path to treat as root for tree branch isolation (e.g., "platform/territories") */
|
|
64
|
+
rootPath?: string;
|
|
65
|
+
/** Hide the root node itself, showing only its children */
|
|
66
|
+
hideRootNode?: boolean;
|
|
67
|
+
/** Search options */
|
|
68
|
+
/** Whether to enable the search input */
|
|
69
|
+
enableSearch?: boolean;
|
|
70
|
+
/** Placeholder text for the search input */
|
|
71
|
+
searchPlaceholder?: string;
|
|
72
|
+
/** Scope of search - entire tree or just the currently visible branch */
|
|
73
|
+
searchScope?: 'all' | 'current-branch';
|
|
74
|
+
/** Appearance options */
|
|
75
|
+
/** Message to display when no resources are available */
|
|
76
|
+
emptyMessage?: string;
|
|
77
|
+
/** Height of the picker component */
|
|
78
|
+
height?: string | number;
|
|
79
|
+
}
|
|
36
80
|
/**
|
|
37
81
|
* Props for the ResourcePicker component.
|
|
38
82
|
*
|
|
39
83
|
* The ResourcePicker is a comprehensive component for browsing and selecting resources
|
|
40
84
|
* with support for multiple view modes, search, annotations, and pending resources.
|
|
85
|
+
* UI behavior is controlled through the options object, while functional data is
|
|
86
|
+
* passed as separate props.
|
|
41
87
|
*
|
|
42
88
|
* @example
|
|
43
89
|
* ```tsx
|
|
@@ -51,45 +97,36 @@ export interface ResourceSelection<T = unknown> {
|
|
|
51
97
|
* handleResourceData(selection.resourceData);
|
|
52
98
|
* }
|
|
53
99
|
* }}
|
|
54
|
-
* defaultView="tree"
|
|
55
|
-
* enableSearch={true}
|
|
56
100
|
* resourceAnnotations={{
|
|
57
101
|
* 'res1': { badge: { text: '3', variant: 'info' } }
|
|
58
102
|
* }}
|
|
103
|
+
* options={{
|
|
104
|
+
* defaultView: 'tree',
|
|
105
|
+
* enableSearch: true,
|
|
106
|
+
* searchPlaceholder: 'Find resources...',
|
|
107
|
+
* height: '400px'
|
|
108
|
+
* }}
|
|
59
109
|
* />
|
|
60
110
|
* ```
|
|
61
111
|
*
|
|
62
112
|
* @public
|
|
63
113
|
*/
|
|
64
114
|
export interface ResourcePickerProps<T = unknown> extends ViewBaseProps {
|
|
115
|
+
/** Core functionality */
|
|
65
116
|
/** Processed resources to display in the picker */
|
|
66
117
|
resources: ProcessedResources | ExtendedProcessedResources | null;
|
|
67
118
|
/** Currently selected resource ID */
|
|
68
119
|
selectedResourceId: string | null;
|
|
69
120
|
/** Callback fired when a resource is selected, providing comprehensive selection data */
|
|
70
121
|
onResourceSelect: (selection: ResourceSelection<T>) => void;
|
|
71
|
-
/**
|
|
72
|
-
defaultView?: 'list' | 'tree';
|
|
73
|
-
/** Whether to show the list/tree view toggle buttons */
|
|
74
|
-
showViewToggle?: boolean;
|
|
75
|
-
/** Path to treat as root for tree branch isolation (e.g., "platform/territories") */
|
|
76
|
-
rootPath?: string;
|
|
77
|
-
/** Hide the root node itself, showing only its children */
|
|
78
|
-
hideRootNode?: boolean;
|
|
79
|
-
/** Whether to enable the search input */
|
|
80
|
-
enableSearch?: boolean;
|
|
81
|
-
/** Placeholder text for the search input */
|
|
82
|
-
searchPlaceholder?: string;
|
|
83
|
-
/** Scope of search - entire tree or just the currently visible branch */
|
|
84
|
-
searchScope?: 'all' | 'current-branch';
|
|
122
|
+
/** Functional data */
|
|
85
123
|
/** Annotations to display next to resource names (badges, indicators, etc.) */
|
|
86
124
|
resourceAnnotations?: ResourceAnnotations;
|
|
87
125
|
/** Pending (unsaved) resources to display alongside persisted resources */
|
|
88
126
|
pendingResources?: PendingResource<T>[];
|
|
89
|
-
/**
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
height?: string | number;
|
|
127
|
+
/** UI behavior configuration */
|
|
128
|
+
/** Options controlling picker appearance and behavior */
|
|
129
|
+
options?: ResourcePickerOptions;
|
|
93
130
|
}
|
|
94
131
|
/**
|
|
95
132
|
* Annotations that can be displayed next to resource names in the picker.
|