@fgv/ts-res-ui-components 5.0.0-16 → 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 +705 -68
- package/config/api-extractor.json +89 -0
- package/dist/ts-res-ui-components.d.ts +4805 -0
- package/lib/components/common/QualifierContextControl.d.ts +76 -0
- package/lib/components/common/QualifierContextControl.js +64 -0
- package/lib/components/common/ResolutionResults/index.d.ts +138 -0
- package/lib/components/common/ResolutionResults/index.js +293 -0
- package/lib/components/common/ResourceListView.d.ts +104 -0
- package/lib/components/common/ResourceListView.js +94 -0
- package/lib/components/common/ResourcePickerOptionsControl.d.ts +43 -0
- package/lib/components/common/ResourcePickerOptionsControl.js +142 -0
- package/lib/components/common/ResourceTreeView.d.ts +141 -0
- package/lib/components/common/ResourceTreeView.js +131 -0
- package/lib/components/common/SourceResourceDetail/index.d.ts +125 -0
- package/lib/components/common/SourceResourceDetail/index.js +339 -0
- package/lib/components/forms/HierarchyEditor.d.ts +81 -0
- package/lib/components/forms/HierarchyEditor.js +72 -0
- package/lib/components/forms/QualifierEditForm.d.ts +97 -0
- package/lib/components/forms/QualifierEditForm.js +87 -0
- package/lib/components/forms/QualifierTypeEditForm.d.ts +111 -0
- package/lib/components/forms/QualifierTypeEditForm.js +102 -0
- package/lib/components/forms/ResourceTypeEditForm.d.ts +106 -0
- package/lib/components/forms/ResourceTypeEditForm.js +97 -0
- package/lib/components/orchestrator/ResourceOrchestrator.js +6 -2
- package/lib/components/pickers/ResourcePicker/ResourceItem.d.ts +8 -0
- package/lib/components/pickers/ResourcePicker/ResourceItem.js +55 -0
- package/lib/components/pickers/ResourcePicker/ResourcePickerList.d.ts +9 -0
- package/lib/components/pickers/ResourcePicker/ResourcePickerList.js +71 -0
- package/lib/components/pickers/ResourcePicker/ResourcePickerTree.d.ts +9 -0
- package/lib/components/pickers/ResourcePicker/ResourcePickerTree.js +301 -0
- package/lib/components/pickers/ResourcePicker/index.d.ts +61 -0
- package/lib/components/pickers/ResourcePicker/index.js +133 -0
- package/lib/components/pickers/ResourcePicker/types.d.ts +288 -0
- package/lib/components/pickers/ResourcePicker/utils/treeNavigation.d.ts +44 -0
- package/lib/components/pickers/ResourcePicker/utils/treeNavigation.js +147 -0
- package/lib/components/views/CompiledView/index.d.ts +39 -0
- package/lib/components/views/CompiledView/index.js +251 -37
- package/lib/components/views/ConfigurationView/index.d.ts +46 -0
- package/lib/components/views/ConfigurationView/index.js +46 -0
- package/lib/components/views/FilterView/index.d.ts +48 -0
- package/lib/components/views/FilterView/index.js +136 -224
- package/lib/components/views/ImportView/index.d.ts +47 -0
- package/lib/components/views/ImportView/index.js +101 -37
- package/lib/components/views/MessagesWindow/index.d.ts +128 -0
- package/lib/components/views/MessagesWindow/index.js +189 -0
- package/lib/components/views/ResolutionView/EditableJsonView.d.ts +171 -0
- package/lib/components/views/ResolutionView/EditableJsonView.js +166 -0
- package/lib/components/views/ResolutionView/ResolutionEditControls.d.ts +133 -0
- package/lib/components/views/ResolutionView/ResolutionEditControls.js +128 -0
- package/lib/components/views/ResolutionView/index.d.ts +49 -0
- package/lib/components/views/ResolutionView/index.js +148 -169
- package/lib/components/views/SourceView/index.d.ts +36 -0
- package/lib/components/views/SourceView/index.js +69 -212
- package/lib/hooks/useConfigurationState.d.ts +63 -0
- package/lib/hooks/useConfigurationState.js +63 -0
- package/lib/hooks/useFilterState.d.ts +53 -0
- package/lib/hooks/useFilterState.js +46 -0
- package/lib/hooks/useResolutionState.d.ts +71 -0
- package/lib/hooks/useResolutionState.js +63 -0
- package/lib/hooks/useViewState.d.ts +53 -0
- package/lib/hooks/useViewState.js +43 -0
- package/lib/index.d.ts +7 -17
- package/lib/index.js +32 -22
- package/lib/namespaces/ConfigurationTools.d.ts +44 -0
- package/lib/namespaces/ConfigurationTools.js +47 -0
- package/lib/namespaces/FilterTools.d.ts +34 -0
- package/lib/namespaces/FilterTools.js +36 -0
- package/lib/namespaces/ImportTools.d.ts +32 -0
- package/lib/namespaces/ImportTools.js +33 -0
- package/lib/namespaces/PickerTools.d.ts +90 -0
- package/lib/namespaces/PickerTools.js +90 -0
- package/lib/namespaces/ResolutionTools.d.ts +38 -0
- package/lib/namespaces/ResolutionTools.js +40 -0
- package/lib/namespaces/ResourceTools.d.ts +95 -0
- package/lib/namespaces/ResourceTools.js +95 -0
- package/lib/namespaces/TsResTools.d.ts +37 -0
- package/lib/namespaces/TsResTools.js +38 -0
- package/lib/namespaces/ViewStateTools.d.ts +84 -0
- package/lib/namespaces/ViewStateTools.js +84 -0
- package/lib/namespaces/ZipTools.d.ts +42 -0
- package/lib/namespaces/ZipTools.js +44 -0
- package/lib/namespaces/index.d.ts +49 -0
- package/lib/namespaces/index.js +49 -0
- package/lib/test/unit/ResourcePicker.test.d.ts +9 -0
- package/lib/tsdoc-metadata.json +11 -0
- package/lib/types/index.d.ts +636 -10
- package/lib/utils/configurationUtils.d.ts +153 -0
- package/lib/utils/configurationUtils.js +149 -0
- package/lib/utils/fileProcessing.d.ts +4 -0
- package/lib/utils/fileProcessing.js +4 -0
- package/lib/utils/filterResources.d.ts +168 -16
- package/lib/utils/filterResources.js +159 -2
- package/lib/utils/resolutionUtils.d.ts +456 -5
- package/lib/utils/resolutionUtils.js +413 -5
- package/lib/utils/tsResIntegration.d.ts +6 -0
- package/lib/utils/tsResIntegration.js +6 -0
- package/lib/utils/zipLoader/index.d.ts +2 -7
- package/lib/utils/zipLoader/index.js +4 -12
- package/lib/utils/zipLoader/zipProcessingHelpers.d.ts +18 -0
- package/lib/utils/zipLoader/zipProcessingHelpers.js +43 -0
- package/lib/utils/zipLoader/zipUtils.d.ts +1 -48
- package/lib/utils/zipLoader/zipUtils.js +1 -222
- package/lib-commonjs/components/common/QualifierContextControl.js +64 -0
- package/lib-commonjs/components/common/ResolutionResults/index.js +298 -0
- package/lib-commonjs/components/common/ResourceListView.js +94 -0
- package/lib-commonjs/components/common/ResourcePickerOptionsControl.js +147 -0
- package/lib-commonjs/components/common/ResourceTreeView.js +131 -0
- package/lib-commonjs/components/common/SourceResourceDetail/index.js +344 -0
- package/lib-commonjs/components/forms/HierarchyEditor.js +72 -0
- package/lib-commonjs/components/forms/QualifierEditForm.js +87 -0
- package/lib-commonjs/components/forms/QualifierTypeEditForm.js +102 -0
- package/lib-commonjs/components/forms/ResourceTypeEditForm.js +97 -0
- package/lib-commonjs/components/orchestrator/ResourceOrchestrator.js +6 -2
- package/lib-commonjs/components/pickers/ResourcePicker/ResourceItem.js +60 -0
- package/lib-commonjs/components/pickers/ResourcePicker/ResourcePickerList.js +76 -0
- package/lib-commonjs/components/pickers/ResourcePicker/ResourcePickerTree.js +306 -0
- package/lib-commonjs/components/pickers/ResourcePicker/index.js +138 -0
- package/lib-commonjs/components/pickers/ResourcePicker/utils/treeNavigation.js +156 -0
- package/lib-commonjs/components/views/CompiledView/index.js +251 -37
- package/lib-commonjs/components/views/ConfigurationView/index.js +46 -0
- package/lib-commonjs/components/views/FilterView/index.js +135 -223
- package/lib-commonjs/components/views/ImportView/index.js +100 -36
- package/lib-commonjs/components/views/MessagesWindow/index.js +194 -0
- package/lib-commonjs/components/views/ResolutionView/EditableJsonView.js +166 -0
- package/lib-commonjs/components/views/ResolutionView/ResolutionEditControls.js +128 -0
- package/lib-commonjs/components/views/ResolutionView/index.js +147 -168
- package/lib-commonjs/components/views/SourceView/index.js +68 -211
- package/lib-commonjs/hooks/useConfigurationState.js +63 -0
- package/lib-commonjs/hooks/useFilterState.js +46 -0
- package/lib-commonjs/hooks/useResolutionState.js +63 -0
- package/lib-commonjs/hooks/useViewState.js +43 -0
- package/lib-commonjs/index.js +45 -38
- package/lib-commonjs/namespaces/ConfigurationTools.js +61 -0
- package/lib-commonjs/namespaces/FilterTools.js +45 -0
- package/lib-commonjs/namespaces/ImportTools.js +41 -0
- package/lib-commonjs/namespaces/PickerTools.js +95 -0
- package/lib-commonjs/namespaces/ResolutionTools.js +53 -0
- package/lib-commonjs/namespaces/ResourceTools.js +99 -0
- package/lib-commonjs/namespaces/TsResTools.js +49 -0
- package/lib-commonjs/namespaces/ViewStateTools.js +89 -0
- package/lib-commonjs/namespaces/ZipTools.js +51 -0
- package/lib-commonjs/namespaces/index.js +53 -0
- package/lib-commonjs/utils/configurationUtils.js +149 -0
- package/lib-commonjs/utils/fileProcessing.js +4 -0
- package/lib-commonjs/utils/filterResources.js +159 -2
- package/lib-commonjs/utils/resolutionUtils.js +413 -5
- package/lib-commonjs/utils/tsResIntegration.js +6 -0
- package/lib-commonjs/utils/zipLoader/index.js +6 -25
- package/lib-commonjs/utils/zipLoader/zipProcessingHelpers.js +47 -0
- package/lib-commonjs/utils/zipLoader/zipUtils.js +1 -233
- package/package.json +11 -7
- package/src/components/common/QualifierContextControl.tsx +76 -0
- package/src/components/common/ResolutionResults/index.tsx +481 -0
- package/src/components/common/ResourceListView.tsx +104 -0
- package/src/components/common/ResourcePickerOptionsControl.tsx +351 -0
- package/src/components/common/ResourceTreeView.tsx +146 -0
- package/src/components/common/SourceResourceDetail/index.tsx +493 -0
- package/src/components/forms/HierarchyEditor.tsx +81 -0
- package/src/components/forms/QualifierEditForm.tsx +97 -0
- package/src/components/forms/QualifierTypeEditForm.tsx +111 -0
- package/src/components/forms/ResourceTypeEditForm.tsx +106 -0
- package/src/components/orchestrator/ResourceOrchestrator.tsx +7 -4
- package/src/components/pickers/ResourcePicker/README.md +570 -0
- package/src/components/pickers/ResourcePicker/ResourceItem.tsx +127 -0
- package/src/components/pickers/ResourcePicker/ResourcePickerList.tsx +114 -0
- package/src/components/pickers/ResourcePicker/ResourcePickerTree.tsx +461 -0
- package/src/components/pickers/ResourcePicker/index.tsx +234 -0
- package/src/components/pickers/ResourcePicker/types.ts +301 -0
- package/src/components/pickers/ResourcePicker/utils/treeNavigation.ts +210 -0
- package/src/components/views/CompiledView/index.tsx +419 -42
- package/src/components/views/ConfigurationView/index.tsx +46 -0
- package/src/components/views/FilterView/index.tsx +182 -406
- package/src/components/views/ImportView/index.tsx +110 -38
- package/src/components/views/MessagesWindow/index.tsx +325 -0
- package/src/components/views/ResolutionView/EditableJsonView.tsx +171 -0
- package/src/components/views/ResolutionView/ResolutionEditControls.tsx +133 -0
- package/src/components/views/ResolutionView/index.tsx +191 -337
- package/src/components/views/SourceView/index.tsx +103 -350
- package/src/hooks/useConfigurationState.ts +63 -0
- package/src/hooks/useFilterState.ts +53 -0
- package/src/hooks/useResolutionState.ts +71 -0
- package/src/hooks/useViewState.ts +53 -0
- package/src/index.ts +53 -30
- package/src/namespaces/ConfigurationTools.ts +59 -0
- package/src/namespaces/FilterTools.ts +47 -0
- package/src/namespaces/ImportTools.ts +42 -0
- package/src/namespaces/PickerTools.ts +104 -0
- package/src/namespaces/ResolutionTools.ts +64 -0
- package/src/namespaces/ResourceTools.ts +106 -0
- package/src/namespaces/TsResTools.ts +49 -0
- package/src/namespaces/ViewStateTools.ts +91 -0
- package/src/namespaces/ZipTools.ts +49 -0
- package/src/namespaces/index.ts +49 -0
- package/src/types/index.ts +644 -14
- package/src/utils/configurationUtils.ts +153 -0
- package/src/utils/fileProcessing.ts +4 -0
- package/src/utils/filterResources.ts +168 -18
- package/src/utils/resolutionUtils.ts +456 -5
- package/src/utils/tsResIntegration.ts +6 -0
- package/src/utils/zipLoader/index.ts +4 -25
- package/src/utils/zipLoader/zipProcessingHelpers.ts +52 -0
- package/src/utils/zipLoader/zipUtils.ts +1 -260
- package/lib/components/views/ZipLoaderView/index.d.ts +0 -5
- package/lib/components/views/ZipLoaderView/index.js +0 -313
- package/lib/utils/zipLoader/browserZipLoader.d.ts +0 -52
- package/lib/utils/zipLoader/browserZipLoader.js +0 -224
- package/lib/utils/zipLoader/nodeZipBuilder.d.ts +0 -55
- package/lib/utils/zipLoader/nodeZipBuilder.js +0 -98
- package/lib/utils/zipLoader/types.d.ts +0 -139
- package/lib-commonjs/components/views/ZipLoaderView/index.js +0 -318
- package/lib-commonjs/utils/zipLoader/browserZipLoader.js +0 -231
- package/lib-commonjs/utils/zipLoader/nodeZipBuilder.js +0 -105
- package/src/components/views/ZipLoaderView/index.tsx +0 -485
- package/src/utils/zipLoader/browserZipLoader.ts +0 -324
- package/src/utils/zipLoader/nodeZipBuilder.ts +0 -153
- package/src/utils/zipLoader/types.ts +0 -175
- /package/lib/{utils/zipLoader → components/pickers/ResourcePicker}/types.js +0 -0
- /package/lib-commonjs/{utils/zipLoader → components/pickers/ResourcePicker}/types.js +0 -0
package/README.md
CHANGED
|
@@ -16,9 +16,20 @@ This packlet is largely AI written, and it shows.
|
|
|
16
16
|
- **🎯 Resource Resolution**: Test resource resolution with dynamic context values
|
|
17
17
|
- **📊 Visualization**: Multiple views for exploring resource structures and compiled output
|
|
18
18
|
- **⚙️ Configuration**: Visual configuration management for qualifier types, qualifiers, and resource types
|
|
19
|
-
- **📁 File Handling**: Support for directory imports, ZIP files, and bundle loading
|
|
19
|
+
- **📁 File Handling**: Support for directory imports, ZIP files via ts-res zip-archive packlet, and bundle loading
|
|
20
20
|
- **🎨 Modern UI**: Built with Tailwind CSS and Heroicons for a clean, responsive interface
|
|
21
21
|
|
|
22
|
+
### ZIP Archive Integration
|
|
23
|
+
|
|
24
|
+
This library now uses the **ts-res zip-archive packlet** as the single source of truth for all ZIP operations, providing:
|
|
25
|
+
|
|
26
|
+
- **Universal compatibility**: Works in both browser and Node.js environments using fflate
|
|
27
|
+
- **Standardized format**: Common ZIP bundle format across all ts-res tools
|
|
28
|
+
- **Simplified API**: Direct integration with ts-res ZIP archive functionality
|
|
29
|
+
- **Processing helpers**: Utilities to integrate ZIP data with ts-res-ui-components workflows
|
|
30
|
+
|
|
31
|
+
The `ImportView` component handles ZIP files automatically, and the `ZipTools` namespace provides processing helpers for custom ZIP workflows.
|
|
32
|
+
|
|
22
33
|
## Installation
|
|
23
34
|
|
|
24
35
|
```bash
|
|
@@ -116,24 +127,32 @@ function MyResourceViewer() {
|
|
|
116
127
|
|
|
117
128
|
```
|
|
118
129
|
ResourceOrchestrator (state management)
|
|
119
|
-
├── ImportView (file/bundle import)
|
|
130
|
+
├── ImportView (file/bundle/ZIP import)
|
|
120
131
|
├── SourceView (resource collection display)
|
|
121
132
|
├── FilterView (context filtering)
|
|
122
133
|
├── CompiledView (compiled resource structure)
|
|
123
134
|
├── ResolutionView (resource resolution testing)
|
|
124
|
-
|
|
125
|
-
└── ZipLoaderView (ZIP file handling)
|
|
135
|
+
└── ConfigurationView (system configuration)
|
|
126
136
|
```
|
|
127
137
|
|
|
128
138
|
### Data Flow
|
|
129
139
|
|
|
130
|
-
1. **
|
|
131
|
-
|
|
140
|
+
1. **Configuration Phase**: System configuration is created or managed via `ConfigurationView`
|
|
141
|
+
- Define qualifier types (language, territory, platform, etc.)
|
|
142
|
+
- Configure qualifiers and their default values
|
|
143
|
+
- Set up resource types and validation rules
|
|
144
|
+
2. **Import Phase**: Resources are imported via `ImportView` or programmatically
|
|
145
|
+
- Individual JSON files, directories, ZIP bundles, or pre-compiled collections
|
|
146
|
+
- Configuration can be imported alongside resources or applied separately
|
|
147
|
+
3. **Processing Phase**: Raw files are processed into a `ProcessedResources` object containing:
|
|
132
148
|
- `ResourceManagerBuilder` for build-time operations
|
|
133
149
|
- `CompiledResourceCollection` for runtime efficiency
|
|
134
150
|
- `ResourceResolver` for resource resolution
|
|
135
|
-
|
|
136
|
-
|
|
151
|
+
4. **Interaction Phase**: Users can filter, explore, and test resource resolution
|
|
152
|
+
- Filter resources with context values using `FilterView`
|
|
153
|
+
- Browse source and compiled structures with `SourceView` and `CompiledView`
|
|
154
|
+
- Test resolution with different contexts using `ResolutionView`
|
|
155
|
+
5. **Export Phase**: Processed resources can be exported as JSON or compiled bundles
|
|
137
156
|
|
|
138
157
|
### Key Concepts
|
|
139
158
|
|
|
@@ -149,6 +168,8 @@ ResourceOrchestrator (state management)
|
|
|
149
168
|
|
|
150
169
|
The main orchestration component that manages all state and provides actions via render props.
|
|
151
170
|
|
|
171
|
+
> 📚 **[See ResourceOrchestrator documentation →](./docs/ts-res-ui-components.resourceorchestrator.md)**
|
|
172
|
+
|
|
152
173
|
```tsx
|
|
153
174
|
<ResourceOrchestrator
|
|
154
175
|
initialConfiguration={myConfig}
|
|
@@ -160,36 +181,150 @@ The main orchestration component that manages all state and provides actions via
|
|
|
160
181
|
</ResourceOrchestrator>
|
|
161
182
|
```
|
|
162
183
|
|
|
184
|
+
### ConfigurationView
|
|
185
|
+
|
|
186
|
+
Visual configuration management for ts-res system settings including qualifier types, qualifiers, and resource types.
|
|
187
|
+
|
|
188
|
+
> 📚 **[See ConfigurationView documentation →](./docs/ts-res-ui-components.configurationview.md)**
|
|
189
|
+
|
|
190
|
+
```tsx
|
|
191
|
+
<ConfigurationView
|
|
192
|
+
configuration={state.activeConfiguration}
|
|
193
|
+
onConfigurationChange={actions.applyConfiguration}
|
|
194
|
+
onSave={actions.saveConfiguration}
|
|
195
|
+
hasUnsavedChanges={state.hasConfigurationChanges}
|
|
196
|
+
onMessage={(type, message) => console.log(type, message)}
|
|
197
|
+
/>
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**Key features:**
|
|
201
|
+
- **Qualifier type management**: Define language, territory, platform, and custom qualifier types
|
|
202
|
+
- **Qualifier configuration**: Set up specific qualifiers with default values and validation
|
|
203
|
+
- **Resource type management**: Configure resource types and their validation rules
|
|
204
|
+
- **Import/export**: Load configurations from files or export current settings
|
|
205
|
+
- **Real-time validation**: Validate configuration changes as you edit
|
|
206
|
+
- **Change tracking**: Visual indicators for unsaved changes
|
|
207
|
+
|
|
163
208
|
### ImportView
|
|
164
209
|
|
|
165
|
-
Handles importing resource files, directories, bundles, and ZIP files.
|
|
210
|
+
Handles importing resource files, directories, bundles, and ZIP files. Uses the ts-res zip-archive packlet for all ZIP operations.
|
|
211
|
+
|
|
212
|
+
> 📚 **[See ImportView documentation →](./docs/ts-res-ui-components.importview.md)**
|
|
166
213
|
|
|
167
214
|
```tsx
|
|
168
215
|
<ImportView
|
|
169
216
|
onImport={actions.importDirectory}
|
|
170
217
|
onBundleImport={actions.importBundle}
|
|
171
|
-
onZipImport={
|
|
218
|
+
onZipImport={(zipData, config) => {
|
|
219
|
+
// zipData contains files and directory structure from ZIP
|
|
220
|
+
// config contains any configuration found in the ZIP
|
|
221
|
+
actions.importDirectory(zipData, config);
|
|
222
|
+
}}
|
|
172
223
|
acceptedFileTypes={['.json', '.ts', '.js']}
|
|
173
224
|
onMessage={(type, message) => console.log(type, message)}
|
|
174
225
|
/>
|
|
175
226
|
```
|
|
176
227
|
|
|
228
|
+
### ResourcePicker
|
|
229
|
+
|
|
230
|
+
Core component for browsing and selecting resources with advanced features like search, annotations, and pending resource support. The resource picker
|
|
231
|
+
is a generic component used by all of the views, which can also be used to power other application-specific views.
|
|
232
|
+
|
|
233
|
+
> 📚 **[See complete ResourcePicker documentation →](./docs/ts-res-ui-components.resourcepicker.md)**
|
|
234
|
+
|
|
235
|
+
```tsx
|
|
236
|
+
<ResourcePicker
|
|
237
|
+
resources={state.processedResources}
|
|
238
|
+
selectedResourceId={selectedId}
|
|
239
|
+
onResourceSelect={(selection) => {
|
|
240
|
+
setSelectedId(selection.resourceId);
|
|
241
|
+
// Access resource data directly without additional lookups
|
|
242
|
+
if (selection.resourceData) {
|
|
243
|
+
handleResourceData(selection.resourceData);
|
|
244
|
+
}
|
|
245
|
+
// Handle pending resources
|
|
246
|
+
if (selection.isPending) {
|
|
247
|
+
console.log(`Pending ${selection.pendingType} operation`);
|
|
248
|
+
}
|
|
249
|
+
}}
|
|
250
|
+
options={{
|
|
251
|
+
defaultView: "tree",
|
|
252
|
+
enableSearch: true,
|
|
253
|
+
searchPlaceholder: "Search resources...",
|
|
254
|
+
height: "500px"
|
|
255
|
+
}}
|
|
256
|
+
resourceAnnotations={{
|
|
257
|
+
'user.welcome': {
|
|
258
|
+
badge: { text: '3', variant: 'info' },
|
|
259
|
+
suffix: '(3 candidates)'
|
|
260
|
+
}
|
|
261
|
+
}}
|
|
262
|
+
pendingResources={pendingChanges}
|
|
263
|
+
/>
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
**Key features:**
|
|
267
|
+
- **Enhanced callbacks**: Get resource data and metadata in selection callback
|
|
268
|
+
- **Multiple view modes**: List and tree views with search
|
|
269
|
+
- **Visual annotations**: Badges, indicators, and suffixes
|
|
270
|
+
- **Pending resources**: Show unsaved changes with visual distinction
|
|
271
|
+
- **Branch isolation**: Focus on specific parts of large resource trees
|
|
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
|
|
303
|
+
|
|
177
304
|
### SourceView
|
|
178
305
|
|
|
179
|
-
Displays the source resource collection with search and navigation capabilities.
|
|
306
|
+
Displays the source resource collection with search and navigation capabilities using the enhanced ResourcePicker.
|
|
307
|
+
|
|
308
|
+
> 📚 **[See SourceView documentation →](./docs/ts-res-ui-components.sourceview.md)**
|
|
180
309
|
|
|
181
310
|
```tsx
|
|
182
311
|
<SourceView
|
|
183
312
|
resources={state.processedResources}
|
|
184
|
-
selectedResourceId={selectedId}
|
|
185
|
-
onResourceSelect={setSelectedId}
|
|
186
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
|
+
}}
|
|
187
320
|
/>
|
|
188
321
|
```
|
|
189
322
|
|
|
190
323
|
### FilterView
|
|
191
324
|
|
|
192
|
-
Provides filtering capabilities with context value specification.
|
|
325
|
+
Provides filtering capabilities with context value specification and dual-resource comparison.
|
|
326
|
+
|
|
327
|
+
> 📚 **[See FilterView documentation →](./docs/ts-res-ui-components.filterview.md)**
|
|
193
328
|
|
|
194
329
|
```tsx
|
|
195
330
|
<FilterView
|
|
@@ -198,12 +333,19 @@ Provides filtering capabilities with context value specification.
|
|
|
198
333
|
filterActions={filterActions}
|
|
199
334
|
filterResult={filterResult}
|
|
200
335
|
onFilterResult={setFilterResult}
|
|
336
|
+
onMessage={(type, message) => console.log(`${type}: ${message}`)}
|
|
337
|
+
pickerOptions={{
|
|
338
|
+
enableSearch: true,
|
|
339
|
+
searchPlaceholder: "Search resources..."
|
|
340
|
+
}}
|
|
201
341
|
/>
|
|
202
342
|
```
|
|
203
343
|
|
|
204
344
|
### CompiledView
|
|
205
345
|
|
|
206
|
-
Shows the compiled resource structure with detailed candidate information.
|
|
346
|
+
Shows the compiled resource structure with detailed candidate information using the enhanced ResourcePicker.
|
|
347
|
+
|
|
348
|
+
> 📚 **[See CompiledView documentation →](./docs/ts-res-ui-components.compiledview.md)**
|
|
207
349
|
|
|
208
350
|
```tsx
|
|
209
351
|
<CompiledView
|
|
@@ -211,12 +353,19 @@ Shows the compiled resource structure with detailed candidate information.
|
|
|
211
353
|
filterResult={filterResult}
|
|
212
354
|
useNormalization={true}
|
|
213
355
|
onExport={(data, type) => exportData(data, type)}
|
|
356
|
+
onMessage={(type, message) => console.log(`${type}: ${message}`)}
|
|
357
|
+
pickerOptions={{
|
|
358
|
+
defaultView: "tree",
|
|
359
|
+
enableSearch: true
|
|
360
|
+
}}
|
|
214
361
|
/>
|
|
215
362
|
```
|
|
216
363
|
|
|
217
364
|
### ResolutionView
|
|
218
365
|
|
|
219
|
-
Interactive resource resolution testing with context management.
|
|
366
|
+
Interactive resource resolution testing with context management and support for custom resource editors via the ResourceEditorFactory pattern.
|
|
367
|
+
|
|
368
|
+
> 📚 **[See ResolutionView documentation →](./docs/ts-res-ui-components.resolutionview.md)**
|
|
220
369
|
|
|
221
370
|
```tsx
|
|
222
371
|
<ResolutionView
|
|
@@ -224,29 +373,235 @@ Interactive resource resolution testing with context management.
|
|
|
224
373
|
resolutionState={resolutionState}
|
|
225
374
|
resolutionActions={resolutionActions}
|
|
226
375
|
availableQualifiers={availableQualifiers}
|
|
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
|
+
}}
|
|
227
383
|
/>
|
|
228
384
|
```
|
|
229
385
|
|
|
230
|
-
|
|
386
|
+
#### Custom Resource Editors
|
|
231
387
|
|
|
232
|
-
|
|
388
|
+
The ResolutionView supports custom editors for specific resource types through the `ResourceEditorFactory` interface:
|
|
233
389
|
|
|
234
390
|
```tsx
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
391
|
+
import { ResourceEditorFactory, ResourceEditorResult, ResourceEditorProps } from '@fgv/ts-res-ui-components';
|
|
392
|
+
|
|
393
|
+
// Custom editor component
|
|
394
|
+
const MarketInfoEditor: React.FC<ResourceEditorProps> = ({
|
|
395
|
+
value,
|
|
396
|
+
resourceId,
|
|
397
|
+
isEdited,
|
|
398
|
+
editedValue,
|
|
399
|
+
onSave,
|
|
400
|
+
onCancel,
|
|
401
|
+
disabled,
|
|
402
|
+
className
|
|
403
|
+
}) => {
|
|
404
|
+
// Custom form-based editor implementation
|
|
405
|
+
return (
|
|
406
|
+
<div className={`market-info-editor ${className}`}>
|
|
407
|
+
{/* Custom editing interface for market information */}
|
|
408
|
+
</div>
|
|
409
|
+
);
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
// Resource editor factory
|
|
413
|
+
class MyResourceEditorFactory implements ResourceEditorFactory {
|
|
414
|
+
createEditor(resourceId: string, resourceType: string, value: any): ResourceEditorResult {
|
|
415
|
+
if (resourceType === 'marketInfo') {
|
|
416
|
+
return {
|
|
417
|
+
success: true,
|
|
418
|
+
editor: MarketInfoEditor
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
return {
|
|
423
|
+
success: false,
|
|
424
|
+
message: `No custom editor available for resource type '${resourceType}'`
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// Usage
|
|
430
|
+
const editorFactory = new MyResourceEditorFactory();
|
|
431
|
+
|
|
432
|
+
<ResolutionView
|
|
433
|
+
resources={resources}
|
|
434
|
+
resourceEditorFactory={editorFactory}
|
|
435
|
+
// ... other props
|
|
239
436
|
/>
|
|
240
437
|
```
|
|
241
438
|
|
|
439
|
+
**Benefits of Custom Editors:**
|
|
440
|
+
- **Type-Specific UX**: Provide structured editing interfaces for different resource types
|
|
441
|
+
- **Graceful Fallback**: Unknown resource types automatically fall back to JSON editor
|
|
442
|
+
- **Extensible**: Easy to add new editors for new resource types
|
|
443
|
+
- **Error Handling**: Factory failures are caught and reported to users
|
|
444
|
+
|
|
445
|
+
### MessagesWindow
|
|
446
|
+
|
|
447
|
+
Displays and manages application messages with filtering, search, and copy functionality. Perfect for debugging interfaces and development tools where message visibility is critical.
|
|
448
|
+
|
|
449
|
+
> 📚 **[See MessagesWindow documentation →](./docs/ts-res-ui-components.messageswindow.md)**
|
|
450
|
+
|
|
451
|
+
```tsx
|
|
452
|
+
import { MessagesWindow, ViewTools } from '@fgv/ts-res-ui-components';
|
|
453
|
+
|
|
454
|
+
function MyApplication() {
|
|
455
|
+
const [messages, setMessages] = useState<ViewTools.Message[]>([]);
|
|
456
|
+
|
|
457
|
+
const addMessage = (type: ViewTools.Message['type'], text: string) => {
|
|
458
|
+
const newMessage: ViewTools.Message = {
|
|
459
|
+
id: `msg-${Date.now()}-${Math.random()}`,
|
|
460
|
+
type,
|
|
461
|
+
message: text,
|
|
462
|
+
timestamp: new Date()
|
|
463
|
+
};
|
|
464
|
+
setMessages(prev => [...prev, newMessage]);
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
const clearMessages = () => {
|
|
468
|
+
setMessages([]);
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
return (
|
|
472
|
+
<div className="flex flex-col h-screen">
|
|
473
|
+
<div className="flex-1">
|
|
474
|
+
{/* Main application content */}
|
|
475
|
+
<button onClick={() => addMessage('info', 'Processing started')}>
|
|
476
|
+
Add Info Message
|
|
477
|
+
</button>
|
|
478
|
+
<button onClick={() => addMessage('success', 'Operation completed')}>
|
|
479
|
+
Add Success Message
|
|
480
|
+
</button>
|
|
481
|
+
<button onClick={() => addMessage('error', 'Something went wrong')}>
|
|
482
|
+
Add Error Message
|
|
483
|
+
</button>
|
|
484
|
+
</div>
|
|
485
|
+
|
|
486
|
+
{/* Messages window at bottom */}
|
|
487
|
+
<MessagesWindow
|
|
488
|
+
messages={messages}
|
|
489
|
+
onClearMessages={clearMessages}
|
|
490
|
+
/>
|
|
491
|
+
</div>
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
**Key features:**
|
|
497
|
+
- **Message filtering**: Filter by type (info, warning, error, success) with count indicators
|
|
498
|
+
- **Search functionality**: Full-text search across message content
|
|
499
|
+
- **Copy functionality**: Copy all filtered messages to clipboard with timestamps
|
|
500
|
+
- **Collapsible interface**: Minimize/maximize to save screen space
|
|
501
|
+
- **Auto-hide when empty**: Component automatically hides when no messages exist
|
|
502
|
+
- **Visual indicators**: Color-coded message types with appropriate icons
|
|
503
|
+
- **Timestamp formatting**: Human-readable timestamp display
|
|
504
|
+
|
|
505
|
+
#### Adding Messages to Your Application
|
|
506
|
+
|
|
507
|
+
To integrate MessagesWindow into your application and provide user feedback during operations:
|
|
508
|
+
|
|
509
|
+
```tsx
|
|
510
|
+
import { ViewTools } from '@fgv/ts-res-ui-components';
|
|
511
|
+
|
|
512
|
+
function useMessages() {
|
|
513
|
+
const [messages, setMessages] = useState<ViewTools.Message[]>([]);
|
|
514
|
+
|
|
515
|
+
const addMessage = useCallback((type: ViewTools.Message['type'], message: string) => {
|
|
516
|
+
const newMessage: ViewTools.Message = {
|
|
517
|
+
id: `msg-${Date.now()}-${Math.random()}`,
|
|
518
|
+
type,
|
|
519
|
+
message,
|
|
520
|
+
timestamp: new Date()
|
|
521
|
+
};
|
|
522
|
+
setMessages(prev => [...prev, newMessage]);
|
|
523
|
+
}, []);
|
|
524
|
+
|
|
525
|
+
const clearMessages = useCallback(() => {
|
|
526
|
+
setMessages([]);
|
|
527
|
+
}, []);
|
|
528
|
+
|
|
529
|
+
return { messages, addMessage, clearMessages };
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
function MyResourceTool() {
|
|
533
|
+
const { messages, addMessage, clearMessages } = useMessages();
|
|
534
|
+
const [resources, setResources] = useState(null);
|
|
535
|
+
|
|
536
|
+
const handleFileImport = async (files) => {
|
|
537
|
+
try {
|
|
538
|
+
addMessage('info', 'Starting file import...');
|
|
539
|
+
const processed = await processFiles(files);
|
|
540
|
+
setResources(processed);
|
|
541
|
+
addMessage('success', `Successfully imported ${files.length} files`);
|
|
542
|
+
} catch (error) {
|
|
543
|
+
addMessage('error', `Import failed: ${error.message}`);
|
|
544
|
+
}
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
const handleResourceFilter = (filterValues) => {
|
|
548
|
+
if (Object.keys(filterValues).length === 0) {
|
|
549
|
+
addMessage('warning', 'No filter values provided');
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
try {
|
|
554
|
+
const filtered = applyFilters(resources, filterValues);
|
|
555
|
+
addMessage('success', `Filtered to ${filtered.length} resources`);
|
|
556
|
+
} catch (error) {
|
|
557
|
+
addMessage('error', `Filter failed: ${error.message}`);
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
return (
|
|
562
|
+
<div className="flex flex-col h-screen">
|
|
563
|
+
<div className="flex-1">
|
|
564
|
+
<ImportView onImport={handleFileImport} onMessage={addMessage} />
|
|
565
|
+
<FilterView onFilter={handleResourceFilter} onMessage={addMessage} />
|
|
566
|
+
{/* Other components that use onMessage callback */}
|
|
567
|
+
</div>
|
|
568
|
+
|
|
569
|
+
<ViewTools.MessagesWindow
|
|
570
|
+
messages={messages}
|
|
571
|
+
onClearMessages={clearMessages}
|
|
572
|
+
/>
|
|
573
|
+
</div>
|
|
574
|
+
);
|
|
575
|
+
}
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
**Common patterns for adding messages:**
|
|
579
|
+
- **info**: Operation started, processing steps, configuration loaded
|
|
580
|
+
- **success**: Operations completed successfully, files imported, resources processed
|
|
581
|
+
- **warning**: Non-critical issues, fallback behaviors, deprecated features used
|
|
582
|
+
- **error**: Operation failures, validation errors, unexpected conditions
|
|
583
|
+
|
|
584
|
+
**Message callback integration:**
|
|
585
|
+
Most components in this library accept an `onMessage` callback prop that you can connect to your message system. This provides consistent feedback across all operations.
|
|
586
|
+
|
|
242
587
|
## Hooks API
|
|
243
588
|
|
|
244
|
-
|
|
589
|
+
> 📚 **[See complete hooks documentation →](./docs/ts-res-ui-components.md)** for detailed examples and patterns
|
|
590
|
+
|
|
591
|
+
All hooks are organized within their respective namespaces alongside their related components and utilities for better discoverability and logical grouping.
|
|
592
|
+
|
|
593
|
+
### Core Data Management
|
|
245
594
|
|
|
246
|
-
|
|
595
|
+
#### ResourceTools.useResourceData
|
|
596
|
+
|
|
597
|
+
Main orchestrator hook for resource processing, configuration, and resolution.
|
|
598
|
+
|
|
599
|
+
> 📚 **[useResourceData documentation →](./docs/ts-res-ui-components.resourcetools.useresourcedata.md)**
|
|
247
600
|
|
|
248
601
|
```tsx
|
|
249
|
-
|
|
602
|
+
import { ResourceTools } from '@fgv/ts-res-ui-components';
|
|
603
|
+
|
|
604
|
+
const { state, actions } = ResourceTools.useResourceData();
|
|
250
605
|
|
|
251
606
|
// Process files
|
|
252
607
|
await actions.processFiles(importedFiles);
|
|
@@ -259,58 +614,157 @@ const result = await actions.resolveResource('my.resource', {
|
|
|
259
614
|
|
|
260
615
|
// Apply configuration
|
|
261
616
|
actions.applyConfiguration(newConfig);
|
|
617
|
+
|
|
618
|
+
// Check processing state
|
|
619
|
+
if (state.isProcessing) {
|
|
620
|
+
console.log('Processing resources...');
|
|
621
|
+
} else if (state.error) {
|
|
622
|
+
console.error('Processing failed:', state.error);
|
|
623
|
+
} else if (state.processedResources) {
|
|
624
|
+
console.log('Resources ready!');
|
|
625
|
+
}
|
|
262
626
|
```
|
|
263
627
|
|
|
264
|
-
###
|
|
628
|
+
### View State Management
|
|
265
629
|
|
|
266
|
-
|
|
630
|
+
#### ViewTools.useViewState
|
|
631
|
+
|
|
632
|
+
Manages view state including messages and resource selection.
|
|
633
|
+
|
|
634
|
+
> 📚 **[useViewState documentation →](./docs/ts-res-ui-components.viewtools.useviewstate.md)**
|
|
267
635
|
|
|
268
636
|
```tsx
|
|
269
|
-
|
|
637
|
+
import { ViewTools } from '@fgv/ts-res-ui-components';
|
|
270
638
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
639
|
+
const { messages, selectedResourceId, addMessage, clearMessages, selectResource } = ViewTools.useViewState();
|
|
640
|
+
|
|
641
|
+
// Display operation feedback
|
|
642
|
+
const handleOperation = async () => {
|
|
643
|
+
try {
|
|
644
|
+
await someAsyncOperation();
|
|
645
|
+
addMessage('success', 'Operation completed successfully');
|
|
646
|
+
} catch (error) {
|
|
647
|
+
addMessage('error', `Operation failed: ${error.message}`);
|
|
648
|
+
}
|
|
649
|
+
};
|
|
650
|
+
|
|
651
|
+
// Use with MessagesWindow component
|
|
652
|
+
return (
|
|
653
|
+
<div>
|
|
654
|
+
<button onClick={handleOperation}>Run Operation</button>
|
|
655
|
+
<ViewTools.MessagesWindow
|
|
656
|
+
messages={messages}
|
|
657
|
+
onClearMessages={clearMessages}
|
|
658
|
+
/>
|
|
659
|
+
</div>
|
|
660
|
+
);
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
### Domain-Specific Hooks
|
|
664
|
+
|
|
665
|
+
#### FilterTools.useFilterState
|
|
666
|
+
|
|
667
|
+
Manages resource filtering state with change tracking and validation.
|
|
668
|
+
|
|
669
|
+
> 📚 **[useFilterState documentation →](./docs/ts-res-ui-components.filtertools.usefilterstate.md)**
|
|
670
|
+
|
|
671
|
+
```tsx
|
|
672
|
+
import { FilterTools } from '@fgv/ts-res-ui-components';
|
|
673
|
+
|
|
674
|
+
const { state, actions } = FilterTools.useFilterState({
|
|
675
|
+
enabled: true,
|
|
676
|
+
values: { platform: 'web', locale: 'en' }
|
|
275
677
|
});
|
|
276
678
|
|
|
277
|
-
//
|
|
278
|
-
|
|
679
|
+
// Update filter values with change tracking
|
|
680
|
+
actions.updateFilterValue('language', 'en-US');
|
|
681
|
+
actions.updateFilterValue('environment', 'prod');
|
|
279
682
|
|
|
280
|
-
//
|
|
281
|
-
if (
|
|
282
|
-
|
|
683
|
+
// Apply filters when ready
|
|
684
|
+
if (state.hasPendingChanges) {
|
|
685
|
+
actions.applyFilters();
|
|
283
686
|
}
|
|
284
687
|
```
|
|
285
688
|
|
|
286
|
-
|
|
689
|
+
#### ResolutionTools.useResolutionState
|
|
287
690
|
|
|
288
|
-
|
|
691
|
+
Comprehensive state management for resource resolution and editing.
|
|
692
|
+
|
|
693
|
+
> 📚 **[useResolutionState documentation →](./docs/ts-res-ui-components.resolutiontools.useresolutionstate.md)**
|
|
289
694
|
|
|
290
695
|
```tsx
|
|
291
|
-
|
|
696
|
+
import { ResolutionTools } from '@fgv/ts-res-ui-components';
|
|
697
|
+
|
|
698
|
+
const { state, actions, availableQualifiers } = ResolutionTools.useResolutionState(
|
|
699
|
+
processedResources,
|
|
700
|
+
(type, message) => addMessage(type, message),
|
|
701
|
+
(updatedResources) => setProcessedResources(updatedResources)
|
|
702
|
+
);
|
|
292
703
|
|
|
293
704
|
// Set context for resolution testing
|
|
294
|
-
actions.
|
|
705
|
+
actions.updateContext({ language: 'en-US', platform: 'web' });
|
|
706
|
+
|
|
707
|
+
// Start editing a resource
|
|
708
|
+
actions.selectResource('user.welcome');
|
|
709
|
+
actions.startEditing();
|
|
295
710
|
|
|
296
|
-
//
|
|
297
|
-
|
|
711
|
+
// Save edits with validation
|
|
712
|
+
actions.saveEdit(editedValue);
|
|
298
713
|
```
|
|
299
714
|
|
|
300
|
-
|
|
715
|
+
#### ConfigurationTools.useConfigurationState
|
|
301
716
|
|
|
302
|
-
Manages system configuration state.
|
|
717
|
+
Manages system configuration state with change tracking and import/export capabilities.
|
|
303
718
|
|
|
304
|
-
|
|
305
|
-
const { configuration, updateConfiguration, resetConfiguration } = useConfigurationState();
|
|
719
|
+
> 📚 **[useConfigurationState documentation →](./docs/ts-res-ui-components.configurationtools.useconfigurationstate.md)**
|
|
306
720
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
721
|
+
```tsx
|
|
722
|
+
import { ConfigurationTools } from '@fgv/ts-res-ui-components';
|
|
723
|
+
|
|
724
|
+
const { state, actions, templates } = ConfigurationTools.useConfigurationState(
|
|
725
|
+
undefined,
|
|
726
|
+
(config) => console.log('Configuration changed:', config),
|
|
727
|
+
(hasChanges) => setHasUnsavedChanges(hasChanges)
|
|
728
|
+
);
|
|
729
|
+
|
|
730
|
+
// Load a template
|
|
731
|
+
const loadResult = actions.loadTemplate('minimal');
|
|
732
|
+
|
|
733
|
+
// Add a new qualifier with validation
|
|
734
|
+
actions.addQualifier({
|
|
735
|
+
name: 'language',
|
|
736
|
+
typeName: 'language',
|
|
737
|
+
defaultPriority: 100
|
|
311
738
|
});
|
|
739
|
+
|
|
740
|
+
// Check for unsaved changes
|
|
741
|
+
if (state.hasUnsavedChanges) {
|
|
742
|
+
actions.applyConfiguration();
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
// Export configuration
|
|
746
|
+
const exportResult = actions.exportToJson({ pretty: true });
|
|
747
|
+
if (exportResult.isSuccess()) {
|
|
748
|
+
downloadFile(exportResult.value, 'configuration.json');
|
|
749
|
+
}
|
|
312
750
|
```
|
|
313
751
|
|
|
752
|
+
### Hook Organization
|
|
753
|
+
|
|
754
|
+
All hooks are organized within logical namespaces alongside their related components and utilities:
|
|
755
|
+
|
|
756
|
+
- **`ResourceTools.useResourceData`** - Core data orchestration (import, processing, configuration, resolution)
|
|
757
|
+
- **`ViewTools.useViewState`** - View state management (messages, resource selection)
|
|
758
|
+
- **`FilterTools.useFilterState`** - Resource filtering with change tracking
|
|
759
|
+
- **`ResolutionTools.useResolutionState`** - Resource resolution and editing
|
|
760
|
+
- **`ConfigurationTools.useConfigurationState`** - System configuration management
|
|
761
|
+
|
|
762
|
+
This organization provides:
|
|
763
|
+
- **Better discoverability** - Related functionality grouped together
|
|
764
|
+
- **Logical imports** - `FilterTools.useFilterState` is self-documenting
|
|
765
|
+
- **Namespace consistency** - Matches the existing component organization pattern
|
|
766
|
+
- **Clear separation of concerns** - Each namespace has a specific domain focus
|
|
767
|
+
|
|
314
768
|
## Styling
|
|
315
769
|
|
|
316
770
|
This library uses Tailwind CSS for styling. Make sure to include Tailwind CSS in your project:
|
|
@@ -353,7 +807,7 @@ All components accept a `className` prop for custom styling:
|
|
|
353
807
|
### Custom Resource Processing
|
|
354
808
|
|
|
355
809
|
```tsx
|
|
356
|
-
import {
|
|
810
|
+
import { TsResTools } from '@fgv/ts-res-ui-components';
|
|
357
811
|
|
|
358
812
|
// Custom processing pipeline
|
|
359
813
|
const customProcessor = async (files: ImportedFile[]) => {
|
|
@@ -364,7 +818,7 @@ const customProcessor = async (files: ImportedFile[]) => {
|
|
|
364
818
|
const config = await createConfigFromFiles(processedFiles);
|
|
365
819
|
|
|
366
820
|
// Create ts-res system
|
|
367
|
-
const system = await createTsResSystemFromConfig(config);
|
|
821
|
+
const system = await TsResTools.createTsResSystemFromConfig(config);
|
|
368
822
|
|
|
369
823
|
return system;
|
|
370
824
|
};
|
|
@@ -437,9 +891,54 @@ The library provides comprehensive error handling through the state management s
|
|
|
437
891
|
</ResourceOrchestrator>
|
|
438
892
|
```
|
|
439
893
|
|
|
894
|
+
## Organized Tool Namespaces
|
|
895
|
+
|
|
896
|
+
For better organization and discoverability, utility functions are organized into logical namespaces alongside their related view components:
|
|
897
|
+
|
|
898
|
+
```tsx
|
|
899
|
+
import {
|
|
900
|
+
FilterTools, // FilterView + filtering utilities
|
|
901
|
+
ResolutionTools, // ResolutionView + resolution utilities
|
|
902
|
+
ConfigurationTools, // ConfigurationView + configuration utilities
|
|
903
|
+
TsResTools, // SourceView, CompiledView + ts-res utilities
|
|
904
|
+
ViewTools, // MessagesWindow + view state utilities
|
|
905
|
+
ZipTools, // ImportView + ZIP processing helpers
|
|
906
|
+
FileTools // File processing utilities
|
|
907
|
+
} from '@fgv/ts-res-ui-components';
|
|
908
|
+
|
|
909
|
+
// Use view components from namespaces
|
|
910
|
+
<FilterTools.FilterView {...filterProps} />
|
|
911
|
+
<ResolutionTools.ResolutionView {...resolutionProps} />
|
|
912
|
+
<ViewTools.MessagesWindow {...messageProps} />
|
|
913
|
+
<TsResTools.SourceView {...sourceProps} />
|
|
914
|
+
<ZipTools.ImportView {...importProps} />
|
|
915
|
+
|
|
916
|
+
// Use utility functions from namespaces
|
|
917
|
+
const hasFilters = FilterTools.hasFilterValues(filterState.values);
|
|
918
|
+
const resolver = ResolutionTools.createResolverWithContext(resources, context);
|
|
919
|
+
const system = await TsResTools.createTsResSystemFromConfig(config);
|
|
920
|
+
|
|
921
|
+
// ZIP processing helpers for ts-res-ui-components integration
|
|
922
|
+
const processResult = await ZipTools.processZipLoadResult(zipData, config);
|
|
923
|
+
```
|
|
924
|
+
|
|
925
|
+
### Namespace Contents
|
|
926
|
+
|
|
927
|
+
- **[FilterTools](./docs/ts-res-ui-components.filtertools.md)**: FilterView, filter analysis, filtered resource creation
|
|
928
|
+
- **[ResolutionTools](./docs/ts-res-ui-components.resolutiontools.md)**: ResolutionView, resolution testing, context management
|
|
929
|
+
- **[ConfigurationTools](./docs/ts-res-ui-components.configurationtools.md)**: ConfigurationView, configuration validation, import/export
|
|
930
|
+
- **[TsResTools](./docs/ts-res-ui-components.tsrestools.md)**: SourceView, CompiledView, ts-res system integration
|
|
931
|
+
- **[ViewTools](./docs/ts-res-ui-components.viewtools.md)**: MessagesWindow, message management, view state utilities
|
|
932
|
+
- **[ZipTools](./docs/ts-res-ui-components.ziptools.md)**: ImportView, ZIP processing helpers, uses ts-res zip-archive packlet
|
|
933
|
+
- **[FileTools](./docs/ts-res-ui-components.filetools.md)**: File processing, import/export utilities
|
|
934
|
+
|
|
935
|
+
All components are also available at the top level for backward compatibility.
|
|
936
|
+
|
|
440
937
|
## TypeScript Support
|
|
441
938
|
|
|
442
|
-
This library is written in TypeScript and provides comprehensive type definitions
|
|
939
|
+
This library is written in TypeScript and provides comprehensive type definitions with enhanced support for resource selection and generic resource data.
|
|
940
|
+
|
|
941
|
+
> 📚 **[See complete type documentation →](./docs/ts-res-ui-components.md)**
|
|
443
942
|
|
|
444
943
|
```tsx
|
|
445
944
|
import type {
|
|
@@ -447,18 +946,66 @@ import type {
|
|
|
447
946
|
FilterState,
|
|
448
947
|
ResolutionResult,
|
|
449
948
|
Message,
|
|
450
|
-
ImportedFile
|
|
949
|
+
ImportedFile,
|
|
950
|
+
// Enhanced ResourcePicker types
|
|
951
|
+
ResourceSelection,
|
|
952
|
+
ResourcePickerProps,
|
|
953
|
+
ResourceAnnotation,
|
|
954
|
+
ResourceAnnotations,
|
|
955
|
+
PendingResource,
|
|
956
|
+
// Custom editor factory types
|
|
957
|
+
ResourceEditorFactory,
|
|
958
|
+
ResourceEditorResult,
|
|
959
|
+
ResourceEditorProps,
|
|
960
|
+
// Hook return types
|
|
961
|
+
UseViewStateReturn,
|
|
962
|
+
UseFilterStateReturn,
|
|
963
|
+
UseResolutionStateReturn
|
|
964
|
+
} from '@fgv/ts-res-ui-components';
|
|
965
|
+
|
|
966
|
+
// Import organized namespaces for components and utilities
|
|
967
|
+
import {
|
|
968
|
+
FilterTools,
|
|
969
|
+
ResolutionTools,
|
|
970
|
+
TsResTools,
|
|
971
|
+
ZipTools
|
|
451
972
|
} from '@fgv/ts-res-ui-components';
|
|
452
973
|
|
|
453
|
-
// Type-safe component
|
|
454
|
-
interface
|
|
974
|
+
// Type-safe component with enhanced resource selection
|
|
975
|
+
interface MyResourceViewProps<T = unknown> {
|
|
455
976
|
resources: ProcessedResources;
|
|
456
977
|
onMessage: (type: Message['type'], message: string) => void;
|
|
978
|
+
onResourceSelect: (selection: ResourceSelection<T>) => void;
|
|
457
979
|
}
|
|
458
980
|
|
|
459
|
-
const
|
|
460
|
-
|
|
981
|
+
const MyResourceView = <T = unknown>({ resources, onMessage, onResourceSelect }: MyResourceViewProps<T>) => {
|
|
982
|
+
return (
|
|
983
|
+
<ResourcePicker<T>
|
|
984
|
+
resources={resources}
|
|
985
|
+
onResourceSelect={(selection) => {
|
|
986
|
+
// TypeScript knows selection has resourceId, resourceData, isPending, etc.
|
|
987
|
+
onResourceSelect(selection);
|
|
988
|
+
}}
|
|
989
|
+
resourceAnnotations={{
|
|
990
|
+
'user.welcome': {
|
|
991
|
+
badge: { text: 'NEW', variant: 'new' },
|
|
992
|
+
suffix: '(3 candidates)'
|
|
993
|
+
}
|
|
994
|
+
}}
|
|
995
|
+
/>
|
|
996
|
+
);
|
|
461
997
|
};
|
|
998
|
+
|
|
999
|
+
// Type-safe custom editor factory
|
|
1000
|
+
class TypedResourceEditorFactory implements ResourceEditorFactory {
|
|
1001
|
+
createEditor(resourceId: string, resourceType: string, value: any): ResourceEditorResult {
|
|
1002
|
+
// Full type safety for factory pattern
|
|
1003
|
+
if (resourceType === 'marketInfo') {
|
|
1004
|
+
return { success: true, editor: MarketInfoEditor };
|
|
1005
|
+
}
|
|
1006
|
+
return { success: false, message: `No editor for ${resourceType}` };
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
462
1009
|
```
|
|
463
1010
|
|
|
464
1011
|
## Performance Considerations
|
|
@@ -477,24 +1024,101 @@ const MyComponent: React.FC<MyComponentProps> = ({ resources, onMessage }) => {
|
|
|
477
1024
|
|
|
478
1025
|
## Development
|
|
479
1026
|
|
|
480
|
-
|
|
1027
|
+
This library is part of a [Rush.js](https://rushjs.io/) monorepo. Rush is a build orchestrator for JavaScript monorepos that provides scalable build performance and consistent package management.
|
|
1028
|
+
|
|
1029
|
+
### Rush Monorepo Setup
|
|
1030
|
+
|
|
1031
|
+
If you're new to this monorepo, follow these steps to get started:
|
|
1032
|
+
|
|
1033
|
+
1. **Install Rush globally** (if not already installed):
|
|
1034
|
+
```bash
|
|
1035
|
+
npm install -g @microsoft/rush
|
|
1036
|
+
```
|
|
1037
|
+
|
|
1038
|
+
2. **Clone the repository and install dependencies**:
|
|
1039
|
+
```bash
|
|
1040
|
+
git clone https://github.com/ErikFortune/fgv.git
|
|
1041
|
+
cd fgv
|
|
1042
|
+
rush install
|
|
1043
|
+
```
|
|
1044
|
+
|
|
1045
|
+
3. **Build all projects** (including dependencies):
|
|
1046
|
+
```bash
|
|
1047
|
+
rush build
|
|
1048
|
+
```
|
|
1049
|
+
|
|
1050
|
+
> 📚 **Learn more about Rush**: [Official Rush Documentation](https://rushjs.io/pages/intro/get_started/)
|
|
1051
|
+
|
|
1052
|
+
### Development Commands
|
|
1053
|
+
|
|
1054
|
+
All development commands use Rush's `rushx` tool to run scripts within this specific project:
|
|
1055
|
+
|
|
1056
|
+
#### Building
|
|
1057
|
+
|
|
1058
|
+
```bash
|
|
1059
|
+
# Build this project only
|
|
1060
|
+
rushx build
|
|
1061
|
+
|
|
1062
|
+
# Build all projects in the monorepo (from root)
|
|
1063
|
+
rush build
|
|
1064
|
+
```
|
|
1065
|
+
|
|
1066
|
+
#### Testing
|
|
481
1067
|
|
|
482
1068
|
```bash
|
|
483
|
-
|
|
1069
|
+
# Test this project (includes coverage by default)
|
|
1070
|
+
rushx test
|
|
1071
|
+
|
|
1072
|
+
# Test all projects in the monorepo (from root)
|
|
1073
|
+
rush test
|
|
1074
|
+
|
|
1075
|
+
# Test specific projects with dependencies
|
|
1076
|
+
rush test --to ts-res-ui-components
|
|
1077
|
+
|
|
1078
|
+
# Test only this project without dependencies
|
|
1079
|
+
rush test --only ts-res-ui-components
|
|
484
1080
|
```
|
|
485
1081
|
|
|
486
|
-
|
|
1082
|
+
#### Linting
|
|
487
1083
|
|
|
488
1084
|
```bash
|
|
489
|
-
|
|
1085
|
+
# Lint this project
|
|
1086
|
+
rushx lint
|
|
1087
|
+
|
|
1088
|
+
# Fix lint issues automatically
|
|
1089
|
+
rushx fixlint
|
|
1090
|
+
|
|
1091
|
+
# Lint all projects in the monorepo (from root)
|
|
1092
|
+
rush prettier
|
|
490
1093
|
```
|
|
491
1094
|
|
|
492
|
-
|
|
1095
|
+
#### Other Useful Commands
|
|
493
1096
|
|
|
494
1097
|
```bash
|
|
495
|
-
|
|
1098
|
+
# Clean build artifacts
|
|
1099
|
+
rushx clean
|
|
1100
|
+
|
|
1101
|
+
# Update dependencies (from repository root)
|
|
1102
|
+
rush update
|
|
1103
|
+
|
|
1104
|
+
# Add a new dependency to this project (from repository root)
|
|
1105
|
+
rush add -p <package-name>
|
|
1106
|
+
|
|
1107
|
+
# Check for security vulnerabilities (from repository root)
|
|
1108
|
+
rush audit
|
|
496
1109
|
```
|
|
497
1110
|
|
|
1111
|
+
### Monorepo Structure
|
|
1112
|
+
|
|
1113
|
+
This library is located at `libraries/ts-res-ui-components/` within the monorepo and depends on several other libraries in the workspace:
|
|
1114
|
+
|
|
1115
|
+
- `@fgv/ts-res` - Core resource management library
|
|
1116
|
+
- `@fgv/ts-utils` - Utility functions and Result pattern
|
|
1117
|
+
- `@fgv/ts-json-base` - JSON validation and processing
|
|
1118
|
+
- `@fgv/ts-bcp47` - BCP47 language tag processing
|
|
1119
|
+
|
|
1120
|
+
All workspace dependencies use `workspace:*` version ranges for automatic version resolution.
|
|
1121
|
+
|
|
498
1122
|
## License
|
|
499
1123
|
|
|
500
1124
|
MIT License - see [LICENSE](./LICENSE) file for details.
|
|
@@ -503,10 +1127,23 @@ MIT License - see [LICENSE](./LICENSE) file for details.
|
|
|
503
1127
|
|
|
504
1128
|
Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.
|
|
505
1129
|
|
|
1130
|
+
## API Documentation
|
|
1131
|
+
|
|
1132
|
+
Comprehensive API documentation is available in the [docs](./docs) directory:
|
|
1133
|
+
|
|
1134
|
+
- **[API Overview](./docs/index.md)** - Complete API reference
|
|
1135
|
+
- **[Components](./docs/ts-res-ui-components.md)** - All available components and their props
|
|
1136
|
+
- **[Hooks](./docs/ts-res-ui-components.md)** - State management hooks (useViewState, useResolutionState, etc.)
|
|
1137
|
+
- **[Types](./docs/ts-res-ui-components.md)** - TypeScript interfaces and type definitions
|
|
1138
|
+
- **[Tool Namespaces](./docs/ts-res-ui-components.md)** - Organized tool namespaces with view components and utility functions
|
|
1139
|
+
|
|
1140
|
+
The API documentation includes detailed examples, usage patterns, and type information for all public APIs.
|
|
1141
|
+
|
|
506
1142
|
## Support
|
|
507
1143
|
|
|
508
1144
|
For questions and support, please:
|
|
509
1145
|
|
|
510
|
-
1. Check the [documentation](
|
|
511
|
-
2.
|
|
512
|
-
3.
|
|
1146
|
+
1. Check the [API documentation](./docs/index.md) for detailed component usage
|
|
1147
|
+
2. Review the [ts-res documentation](https://docs.ts-res.dev) for core concepts
|
|
1148
|
+
3. Search [existing issues](https://github.com/fgv/ts-res/issues)
|
|
1149
|
+
4. Create a [new issue](https://github.com/fgv/ts-res/issues/new)
|