@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.
Files changed (32) hide show
  1. package/README.md +56 -12
  2. package/dist/ts-res-ui-components.d.ts +114 -22
  3. package/lib/components/common/ResourcePickerOptionsControl.d.ts +43 -0
  4. package/lib/components/common/ResourcePickerOptionsControl.js +142 -0
  5. package/lib/components/pickers/ResourcePicker/index.d.ts +1 -1
  6. package/lib/components/pickers/ResourcePicker/index.js +3 -1
  7. package/lib/components/pickers/ResourcePicker/types.d.ts +57 -20
  8. package/lib/components/views/CompiledView/index.js +20 -2
  9. package/lib/components/views/FilterView/index.js +28 -2
  10. package/lib/components/views/ResolutionView/index.js +21 -3
  11. package/lib/components/views/SourceView/index.js +21 -3
  12. package/lib/namespaces/PickerTools.d.ts +16 -3
  13. package/lib/namespaces/PickerTools.js +15 -2
  14. package/lib/types/index.d.ts +10 -0
  15. package/lib-commonjs/components/common/ResourcePickerOptionsControl.js +147 -0
  16. package/lib-commonjs/components/pickers/ResourcePicker/index.js +3 -1
  17. package/lib-commonjs/components/views/CompiledView/index.js +20 -2
  18. package/lib-commonjs/components/views/FilterView/index.js +28 -2
  19. package/lib-commonjs/components/views/ResolutionView/index.js +20 -2
  20. package/lib-commonjs/components/views/SourceView/index.js +20 -2
  21. package/lib-commonjs/namespaces/PickerTools.js +17 -3
  22. package/package.json +7 -7
  23. package/src/components/common/ResourcePickerOptionsControl.tsx +351 -0
  24. package/src/components/pickers/ResourcePicker/README.md +93 -0
  25. package/src/components/pickers/ResourcePicker/index.tsx +14 -10
  26. package/src/components/pickers/ResourcePicker/types.ts +61 -25
  27. package/src/components/views/CompiledView/index.tsx +41 -8
  28. package/src/components/views/FilterView/index.tsx +49 -10
  29. package/src/components/views/ResolutionView/index.tsx +41 -8
  30. package/src/components/views/SourceView/index.tsx +43 -9
  31. package/src/namespaces/PickerTools.ts +20 -2
  32. 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
- defaultView="tree"
251
- enableSearch={true}
252
- searchPlaceholder="Search resources..."
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
- onResourceSelect={(selection) => {
301
- setSelectedId(selection.resourceId);
302
- // Enhanced callback provides comprehensive selection data
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
- onResourceSelect={(selection) => {
320
- // Enhanced callback with comprehensive resource data
321
- setSelectedId(selection.resourceId);
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, defaultView, showViewToggle, rootPath, hideRootNode, enableSearch, searchPlaceholder, searchScope, resourceAnnotations, pendingResources, emptyMessage, height, className, onMessage }: ResourcePickerProps<T>) => React_2.JSX.Element;
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
- /** Default view mode to use on initial render */
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
- /** Message to display when no resources are available */
3789
- emptyMessage?: string;
3790
- /** Height of the picker component */
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, defaultView, showViewToggle, rootPath, hideRootNode, enableSearch, searchPlaceholder, searchScope, resourceAnnotations, pendingResources, emptyMessage, height, className, onMessage }: ResourcePickerProps<T>) => React.JSX.Element;
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, defaultView = 'list', showViewToggle = true, rootPath, hideRootNode = false, enableSearch = true, searchPlaceholder, searchScope = 'current-branch', resourceAnnotations, pendingResources, emptyMessage, height = '600px', className = '', onMessage }) => {
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
- /** Default view mode to use on initial render */
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
- /** Message to display when no resources are available */
90
- emptyMessage?: string;
91
- /** Height of the picker component */
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.