@fgv/ts-res-ui-components 5.0.0-21 → 5.0.0-23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/README.md +401 -155
  2. package/config/jest.setup.js +10 -0
  3. package/dist/ts-res-ui-components.d.ts +1657 -76
  4. package/lib/components/common/QualifierContextControl.js +4 -1
  5. package/lib/components/common/ResourceTreeView.js +4 -1
  6. package/lib/components/forms/GenericQualifierTypeEditForm.d.ts +26 -0
  7. package/lib/components/forms/GenericQualifierTypeEditForm.js +166 -0
  8. package/lib/components/forms/QualifierEditForm.d.ts +1 -1
  9. package/lib/components/forms/index.d.ts +2 -0
  10. package/lib/components/forms/index.js +1 -0
  11. package/lib/components/orchestrator/ResourceOrchestrator.d.ts +3 -0
  12. package/lib/components/orchestrator/ResourceOrchestrator.js +118 -51
  13. package/lib/components/pickers/ResourcePicker/ResourcePickerTree.js +32 -10
  14. package/lib/components/pickers/ResourcePicker/index.js +4 -2
  15. package/lib/components/views/CompiledView/index.js +75 -16
  16. package/lib/components/views/ConfigurationView/index.js +94 -35
  17. package/lib/components/views/FilterView/index.js +7 -4
  18. package/lib/components/views/GridView/EditableGridCell.d.ts +76 -0
  19. package/lib/components/views/GridView/EditableGridCell.js +224 -0
  20. package/lib/components/views/GridView/GridSelector.d.ts +43 -0
  21. package/lib/components/views/GridView/GridSelector.js +89 -0
  22. package/lib/components/views/GridView/MultiGridView.d.ts +85 -0
  23. package/lib/components/views/GridView/MultiGridView.js +196 -0
  24. package/lib/components/views/GridView/ResourceGrid.d.ts +38 -0
  25. package/lib/components/views/GridView/ResourceGrid.js +232 -0
  26. package/lib/components/views/GridView/SharedContextControls.d.ts +47 -0
  27. package/lib/components/views/GridView/SharedContextControls.js +95 -0
  28. package/lib/components/views/GridView/cells/BooleanCell.d.ts +44 -0
  29. package/lib/components/views/GridView/cells/BooleanCell.js +49 -0
  30. package/lib/components/views/GridView/cells/DropdownCell.d.ts +58 -0
  31. package/lib/components/views/GridView/cells/DropdownCell.js +182 -0
  32. package/lib/components/views/GridView/cells/StringCell.d.ts +57 -0
  33. package/lib/components/views/GridView/cells/StringCell.js +106 -0
  34. package/lib/components/views/GridView/cells/TriStateCell.d.ts +54 -0
  35. package/lib/components/views/GridView/cells/TriStateCell.js +112 -0
  36. package/lib/components/views/GridView/cells/index.d.ts +15 -0
  37. package/lib/components/views/GridView/cells/index.js +11 -0
  38. package/lib/components/views/GridView/index.d.ts +53 -0
  39. package/lib/components/views/GridView/index.js +212 -0
  40. package/lib/components/views/ImportView/index.js +22 -19
  41. package/lib/components/views/MessagesWindow/index.js +4 -1
  42. package/lib/components/views/ResolutionView/index.js +8 -5
  43. package/lib/contexts/ObservabilityContext.d.ts +85 -0
  44. package/lib/contexts/ObservabilityContext.js +98 -0
  45. package/lib/contexts/index.d.ts +2 -0
  46. package/lib/contexts/index.js +24 -0
  47. package/lib/hooks/useConfigurationState.d.ts +3 -3
  48. package/lib/hooks/useResolutionState.js +850 -246
  49. package/lib/hooks/useResourceData.d.ts +7 -4
  50. package/lib/hooks/useResourceData.js +185 -184
  51. package/lib/index.d.ts +5 -1
  52. package/lib/index.js +8 -1
  53. package/lib/namespaces/GridTools.d.ts +136 -0
  54. package/lib/namespaces/GridTools.js +138 -0
  55. package/lib/namespaces/ObservabilityTools.d.ts +3 -0
  56. package/lib/namespaces/ObservabilityTools.js +23 -0
  57. package/lib/namespaces/ResolutionTools.d.ts +2 -1
  58. package/lib/namespaces/ResolutionTools.js +2 -0
  59. package/lib/namespaces/index.d.ts +2 -0
  60. package/lib/namespaces/index.js +2 -0
  61. package/lib/test/integration/observability.integration.test.d.ts +2 -0
  62. package/lib/test/unit/hooks/useResourceData.test.d.ts +2 -0
  63. package/lib/test/unit/utils/downloadHelper.test.d.ts +2 -0
  64. package/lib/test/unit/workflows/resolutionWorkflows.test.d.ts +2 -0
  65. package/lib/test/unit/workflows/resourceCreation.test.d.ts +2 -0
  66. package/lib/test/unit/workflows/resultPatternExtensions.test.d.ts +2 -0
  67. package/lib/test/unit/workflows/validation.test.d.ts +2 -0
  68. package/lib/types/index.d.ts +387 -20
  69. package/lib/types/index.js +2 -1
  70. package/lib/utils/cellValidation.d.ts +113 -0
  71. package/lib/utils/cellValidation.js +248 -0
  72. package/lib/utils/downloadHelper.d.ts +66 -0
  73. package/lib/utils/downloadHelper.js +195 -0
  74. package/lib/utils/observability/factories.d.ts +29 -0
  75. package/lib/utils/observability/factories.js +58 -0
  76. package/lib/utils/observability/implementations.d.ts +61 -0
  77. package/lib/utils/observability/implementations.js +103 -0
  78. package/lib/utils/observability/index.d.ts +4 -0
  79. package/lib/utils/observability/index.js +26 -0
  80. package/lib/utils/observability/interfaces.d.ts +30 -0
  81. package/lib/utils/observability/interfaces.js +23 -0
  82. package/lib/utils/resolutionEditing.js +2 -1
  83. package/lib/utils/resourceSelector.d.ts +97 -0
  84. package/lib/utils/resourceSelector.js +195 -0
  85. package/lib/utils/resourceSelectors.d.ts +146 -0
  86. package/lib/utils/resourceSelectors.js +233 -0
  87. package/lib/utils/tsResIntegration.d.ts +6 -41
  88. package/lib/utils/tsResIntegration.js +20 -16
  89. package/lib/utils/zipLoader/zipProcessingHelpers.d.ts +3 -2
  90. package/lib/utils/zipLoader/zipProcessingHelpers.js +6 -5
  91. package/lib-commonjs/components/common/QualifierContextControl.js +4 -1
  92. package/lib-commonjs/components/common/ResourceTreeView.js +4 -1
  93. package/lib-commonjs/components/forms/GenericQualifierTypeEditForm.js +171 -0
  94. package/lib-commonjs/components/forms/index.js +3 -1
  95. package/lib-commonjs/components/orchestrator/ResourceOrchestrator.js +118 -51
  96. package/lib-commonjs/components/pickers/ResourcePicker/ResourcePickerTree.js +32 -10
  97. package/lib-commonjs/components/pickers/ResourcePicker/index.js +4 -2
  98. package/lib-commonjs/components/views/CompiledView/index.js +75 -16
  99. package/lib-commonjs/components/views/ConfigurationView/index.js +93 -34
  100. package/lib-commonjs/components/views/FilterView/index.js +7 -4
  101. package/lib-commonjs/components/views/GridView/EditableGridCell.js +232 -0
  102. package/lib-commonjs/components/views/GridView/GridSelector.js +94 -0
  103. package/lib-commonjs/components/views/GridView/MultiGridView.js +201 -0
  104. package/lib-commonjs/components/views/GridView/ResourceGrid.js +237 -0
  105. package/lib-commonjs/components/views/GridView/SharedContextControls.js +100 -0
  106. package/lib-commonjs/components/views/GridView/cells/BooleanCell.js +54 -0
  107. package/lib-commonjs/components/views/GridView/cells/DropdownCell.js +187 -0
  108. package/lib-commonjs/components/views/GridView/cells/StringCell.js +111 -0
  109. package/lib-commonjs/components/views/GridView/cells/TriStateCell.js +117 -0
  110. package/lib-commonjs/components/views/GridView/cells/index.js +18 -0
  111. package/lib-commonjs/components/views/GridView/index.js +217 -0
  112. package/lib-commonjs/components/views/ImportView/index.js +22 -19
  113. package/lib-commonjs/components/views/MessagesWindow/index.js +4 -1
  114. package/lib-commonjs/components/views/ResolutionView/index.js +8 -5
  115. package/lib-commonjs/contexts/ObservabilityContext.js +104 -0
  116. package/lib-commonjs/contexts/index.js +30 -0
  117. package/lib-commonjs/hooks/useResolutionState.js +849 -245
  118. package/lib-commonjs/hooks/useResourceData.js +184 -215
  119. package/lib-commonjs/index.js +15 -1
  120. package/lib-commonjs/namespaces/GridTools.js +161 -0
  121. package/lib-commonjs/namespaces/ObservabilityTools.js +33 -0
  122. package/lib-commonjs/namespaces/ResolutionTools.js +10 -1
  123. package/lib-commonjs/namespaces/index.js +3 -1
  124. package/lib-commonjs/types/index.js +10 -0
  125. package/lib-commonjs/utils/cellValidation.js +253 -0
  126. package/lib-commonjs/utils/downloadHelper.js +198 -0
  127. package/lib-commonjs/utils/observability/factories.js +63 -0
  128. package/lib-commonjs/utils/observability/implementations.js +109 -0
  129. package/lib-commonjs/utils/observability/index.js +36 -0
  130. package/lib-commonjs/utils/observability/interfaces.js +24 -0
  131. package/lib-commonjs/utils/resolutionEditing.js +2 -1
  132. package/lib-commonjs/utils/resourceSelector.js +200 -0
  133. package/lib-commonjs/utils/resourceSelectors.js +242 -0
  134. package/lib-commonjs/utils/tsResIntegration.js +21 -16
  135. package/lib-commonjs/utils/zipLoader/zipProcessingHelpers.js +7 -5
  136. package/package.json +7 -7
  137. package/src/components/common/QualifierContextControl.tsx +0 -338
  138. package/src/components/common/ResolutionContextOptionsControl.tsx +0 -450
  139. package/src/components/common/ResolutionResults/index.tsx +0 -481
  140. package/src/components/common/ResourceListView.tsx +0 -167
  141. package/src/components/common/ResourcePickerOptionsControl.tsx +0 -351
  142. package/src/components/common/ResourceTreeView.tsx +0 -417
  143. package/src/components/common/SourceResourceDetail/index.tsx +0 -493
  144. package/src/components/forms/HierarchyEditor.tsx +0 -285
  145. package/src/components/forms/QualifierEditForm.tsx +0 -487
  146. package/src/components/forms/QualifierTypeEditForm.tsx +0 -458
  147. package/src/components/forms/ResourceTypeEditForm.tsx +0 -437
  148. package/src/components/forms/index.ts +0 -11
  149. package/src/components/orchestrator/ResourceOrchestrator.tsx +0 -444
  150. package/src/components/pickers/ResourcePicker/README.md +0 -570
  151. package/src/components/pickers/ResourcePicker/ResourceItem.tsx +0 -127
  152. package/src/components/pickers/ResourcePicker/ResourcePickerList.tsx +0 -114
  153. package/src/components/pickers/ResourcePicker/ResourcePickerTree.tsx +0 -461
  154. package/src/components/pickers/ResourcePicker/index.tsx +0 -234
  155. package/src/components/pickers/ResourcePicker/types.ts +0 -301
  156. package/src/components/pickers/ResourcePicker/utils/treeNavigation.ts +0 -210
  157. package/src/components/views/CompiledView/index.tsx +0 -1342
  158. package/src/components/views/ConfigurationView/index.tsx +0 -848
  159. package/src/components/views/FilterView/index.tsx +0 -681
  160. package/src/components/views/ImportView/index.tsx +0 -789
  161. package/src/components/views/MessagesWindow/index.tsx +0 -325
  162. package/src/components/views/ResolutionView/EditableJsonView.tsx +0 -386
  163. package/src/components/views/ResolutionView/NewResourceModal.tsx +0 -158
  164. package/src/components/views/ResolutionView/UnifiedChangeControls.tsx +0 -163
  165. package/src/components/views/ResolutionView/index.tsx +0 -751
  166. package/src/components/views/SourceView/index.tsx +0 -291
  167. package/src/hooks/useConfigurationState.ts +0 -436
  168. package/src/hooks/useFilterState.ts +0 -150
  169. package/src/hooks/useResolutionState.ts +0 -893
  170. package/src/hooks/useResourceData.ts +0 -596
  171. package/src/hooks/useViewState.ts +0 -97
  172. package/src/index.ts +0 -68
  173. package/src/namespaces/ConfigurationTools.ts +0 -59
  174. package/src/namespaces/FilterTools.ts +0 -47
  175. package/src/namespaces/ImportTools.ts +0 -42
  176. package/src/namespaces/PickerTools.ts +0 -104
  177. package/src/namespaces/ResolutionTools.ts +0 -68
  178. package/src/namespaces/ResourceTools.ts +0 -106
  179. package/src/namespaces/TsResTools.ts +0 -49
  180. package/src/namespaces/ViewStateTools.ts +0 -91
  181. package/src/namespaces/ZipTools.ts +0 -49
  182. package/src/namespaces/index.ts +0 -49
  183. package/src/types/index.ts +0 -1273
  184. package/src/utils/configurationUtils.ts +0 -339
  185. package/src/utils/fileProcessing.ts +0 -164
  186. package/src/utils/filterResources.ts +0 -356
  187. package/src/utils/resolutionEditing.ts +0 -346
  188. package/src/utils/resolutionUtils.ts +0 -740
  189. package/src/utils/tsResIntegration.ts +0 -475
  190. package/src/utils/zipLoader/index.ts +0 -5
  191. package/src/utils/zipLoader/zipProcessingHelpers.ts +0 -46
  192. package/src/utils/zipLoader/zipUtils.ts +0 -7
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GenericQualifierTypeEditForm = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const react_1 = tslib_1.__importStar(require("react"));
6
+ const outline_1 = require("@heroicons/react/24/outline");
7
+ /**
8
+ * Form component for editing custom qualifier types with JSON configuration.
9
+ * Provides a generic editor for qualifier types that don't use the built-in system types.
10
+ *
11
+ * @public
12
+ */
13
+ const GenericQualifierTypeEditForm = ({ qualifierType, onSave, onCancel, existingNames = [] }) => {
14
+ const [formData, setFormData] = (0, react_1.useState)(() => {
15
+ if (qualifierType) {
16
+ return {
17
+ name: qualifierType.name,
18
+ systemType: qualifierType.systemType,
19
+ configuration: JSON.stringify(qualifierType.configuration || {}, null, 2)
20
+ };
21
+ }
22
+ return {
23
+ name: '',
24
+ systemType: '',
25
+ configuration: JSON.stringify({}, null, 2)
26
+ };
27
+ });
28
+ const [errors, setErrors] = (0, react_1.useState)({});
29
+ const [isJsonValid, setIsJsonValid] = (0, react_1.useState)(true);
30
+ const [configValidation, setConfigValidation] = (0, react_1.useState)(null);
31
+ // Validate JSON configuration on every change
32
+ (0, react_1.useEffect)(() => {
33
+ try {
34
+ const parsed = JSON.parse(formData.configuration);
35
+ setIsJsonValid(true);
36
+ // Attempt to validate the configuration structure if we have both name and systemType
37
+ if (formData.name && formData.systemType) {
38
+ try {
39
+ const testConfig = {
40
+ name: formData.name,
41
+ systemType: formData.systemType,
42
+ configuration: parsed
43
+ };
44
+ // For now, we'll just check basic structure
45
+ // In the future, this could call validateConfigurationJson if we had a qualifier type instance
46
+ setConfigValidation(null); // Could be enhanced with actual validation
47
+ setErrors((prev) => ({ ...prev, configuration: undefined }));
48
+ }
49
+ catch (validationError) {
50
+ setConfigValidation(null); // Could store validation result
51
+ setErrors((prev) => ({ ...prev, configuration: undefined }));
52
+ }
53
+ }
54
+ else {
55
+ setConfigValidation(null);
56
+ setErrors((prev) => ({ ...prev, configuration: undefined }));
57
+ }
58
+ }
59
+ catch (error) {
60
+ setIsJsonValid(false);
61
+ setConfigValidation(null);
62
+ setErrors((prev) => ({
63
+ ...prev,
64
+ configuration: error instanceof Error ? `JSON Error: ${error.message}` : 'Invalid JSON'
65
+ }));
66
+ }
67
+ }, [formData.configuration, formData.name, formData.systemType]);
68
+ const validateForm = (0, react_1.useCallback)(() => {
69
+ const newErrors = {};
70
+ // Validate name
71
+ if (!formData.name.trim()) {
72
+ newErrors.name = 'Name is required';
73
+ }
74
+ else if (existingNames.includes(formData.name.trim()) &&
75
+ (!qualifierType || qualifierType.name !== formData.name.trim())) {
76
+ newErrors.name = 'Name already exists';
77
+ }
78
+ // Validate system type
79
+ if (!formData.systemType.trim()) {
80
+ newErrors.systemType = 'System type is required';
81
+ }
82
+ // Validate JSON
83
+ if (!isJsonValid) {
84
+ newErrors.configuration = 'Valid JSON is required';
85
+ }
86
+ setErrors(newErrors);
87
+ return Object.keys(newErrors).length === 0;
88
+ }, [formData, qualifierType, existingNames, isJsonValid]);
89
+ const handleSave = (0, react_1.useCallback)(() => {
90
+ if (!validateForm()) {
91
+ return;
92
+ }
93
+ try {
94
+ const configuration = JSON.parse(formData.configuration);
95
+ const newQualifierType = {
96
+ name: formData.name.trim(),
97
+ systemType: formData.systemType.trim(),
98
+ configuration
99
+ };
100
+ onSave(newQualifierType);
101
+ }
102
+ catch (error) {
103
+ setErrors((prev) => ({
104
+ ...prev,
105
+ configuration: 'Failed to parse JSON configuration'
106
+ }));
107
+ }
108
+ }, [formData, validateForm, onSave]);
109
+ const handleInputChange = (0, react_1.useCallback)((field, value) => {
110
+ setFormData((prev) => ({ ...prev, [field]: value }));
111
+ // Clear error when user starts typing
112
+ if (errors[field]) {
113
+ setErrors((prev) => ({ ...prev, [field]: undefined }));
114
+ }
115
+ }, [errors]);
116
+ const formatJson = (0, react_1.useCallback)(() => {
117
+ try {
118
+ const parsed = JSON.parse(formData.configuration);
119
+ const formatted = JSON.stringify(parsed, null, 2);
120
+ setFormData((prev) => ({ ...prev, configuration: formatted }));
121
+ }
122
+ catch (error) {
123
+ // If JSON is invalid, don't format
124
+ }
125
+ }, [formData.configuration]);
126
+ return (react_1.default.createElement("div", { className: "fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50" },
127
+ react_1.default.createElement("div", { className: "bg-white rounded-lg shadow-xl max-w-2xl w-full max-h-[90vh] overflow-y-auto" },
128
+ react_1.default.createElement("div", { className: "flex items-center justify-between p-6 border-b border-gray-200" },
129
+ react_1.default.createElement("div", null,
130
+ react_1.default.createElement("h3", { className: "text-lg font-semibold text-gray-900" }, qualifierType ? 'Edit Custom Qualifier Type' : 'Add Custom Qualifier Type'),
131
+ react_1.default.createElement("p", { className: "text-sm text-gray-600 mt-1" }, "Configure a custom qualifier type with JSON configuration")),
132
+ react_1.default.createElement("button", { onClick: onCancel, className: "p-2 text-gray-400 hover:text-gray-600 rounded-lg hover:bg-gray-100" },
133
+ react_1.default.createElement(outline_1.XMarkIcon, { className: "w-6 h-6" }))),
134
+ react_1.default.createElement("div", { className: "p-6 space-y-6" },
135
+ react_1.default.createElement("div", null,
136
+ react_1.default.createElement("label", { htmlFor: "qualifierTypeName", className: "block text-sm font-medium text-gray-700 mb-2" }, "Name"),
137
+ react_1.default.createElement("input", { id: "qualifierTypeName", type: "text", value: formData.name, onChange: (e) => handleInputChange('name', e.target.value), className: `w-full px-3 py-2 border rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 ${errors.name ? 'border-red-300 bg-red-50' : 'border-gray-300'}`, placeholder: "Enter qualifier type name (e.g., 'custom-dimension')" }),
138
+ errors.name && (react_1.default.createElement("div", { className: "mt-1 flex items-center text-sm text-red-600" },
139
+ react_1.default.createElement(outline_1.ExclamationTriangleIcon, { className: "w-4 h-4 mr-1 flex-shrink-0" }),
140
+ errors.name))),
141
+ react_1.default.createElement("div", null,
142
+ react_1.default.createElement("label", { htmlFor: "systemType", className: "block text-sm font-medium text-gray-700 mb-2" }, "System Type"),
143
+ react_1.default.createElement("input", { id: "systemType", type: "text", value: formData.systemType, onChange: (e) => handleInputChange('systemType', e.target.value), className: `w-full px-3 py-2 border rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 ${errors.systemType ? 'border-red-300 bg-red-50' : 'border-gray-300'}`, placeholder: "Enter system type (e.g., 'custom', 'dimension')" }),
144
+ errors.systemType && (react_1.default.createElement("div", { className: "mt-1 flex items-center text-sm text-red-600" },
145
+ react_1.default.createElement(outline_1.ExclamationTriangleIcon, { className: "w-4 h-4 mr-1 flex-shrink-0" }),
146
+ errors.systemType))),
147
+ react_1.default.createElement("div", null,
148
+ react_1.default.createElement("div", { className: "flex items-center justify-between mb-2" },
149
+ react_1.default.createElement("label", { htmlFor: "configuration", className: "block text-sm font-medium text-gray-700" }, "Configuration (JSON)"),
150
+ react_1.default.createElement("button", { type: "button", onClick: formatJson, disabled: !isJsonValid, className: "text-xs text-blue-600 hover:text-blue-800 disabled:text-gray-400" }, "Format JSON")),
151
+ react_1.default.createElement("textarea", { id: "configuration", rows: 12, value: formData.configuration, onChange: (e) => handleInputChange('configuration', e.target.value), className: `w-full px-3 py-2 border rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 font-mono text-sm ${errors.configuration ? 'border-red-300 bg-red-50' : 'border-gray-300'}`, placeholder: '{"property": "value"}' }),
152
+ errors.configuration && (react_1.default.createElement("div", { className: "mt-1 flex items-center text-sm text-red-600" },
153
+ react_1.default.createElement(outline_1.ExclamationTriangleIcon, { className: "w-4 h-4 mr-1 flex-shrink-0" }),
154
+ errors.configuration)),
155
+ isJsonValid && (react_1.default.createElement("div", { className: "mt-1 flex items-center text-sm text-green-600" },
156
+ react_1.default.createElement(outline_1.InformationCircleIcon, { className: "w-4 h-4 mr-1 flex-shrink-0" }),
157
+ "Valid JSON configuration"))),
158
+ react_1.default.createElement("div", { className: "bg-blue-50 border border-blue-200 rounded-lg p-4" },
159
+ react_1.default.createElement("div", { className: "flex items-start" },
160
+ react_1.default.createElement(outline_1.InformationCircleIcon, { className: "w-5 h-5 text-blue-500 mr-2 mt-0.5 flex-shrink-0" }),
161
+ react_1.default.createElement("div", { className: "text-sm text-blue-700" },
162
+ react_1.default.createElement("p", { className: "font-medium mb-1" }, "Custom Qualifier Types"),
163
+ react_1.default.createElement("p", null, "Custom qualifier types allow you to extend the system with your own validation logic. The configuration object can contain any valid JSON and will be passed to your custom qualifier type implementation."))))),
164
+ react_1.default.createElement("div", { className: "flex items-center justify-end gap-3 p-6 border-t border-gray-200" },
165
+ react_1.default.createElement("button", { onClick: onCancel, className: "px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2" }, "Cancel"),
166
+ react_1.default.createElement("button", { onClick: handleSave, disabled: !isJsonValid || Object.keys(errors).length > 0, className: "px-4 py-2 text-sm font-medium text-white bg-blue-600 border border-transparent rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed" },
167
+ qualifierType ? 'Update' : 'Create',
168
+ " Qualifier Type")))));
169
+ };
170
+ exports.GenericQualifierTypeEditForm = GenericQualifierTypeEditForm;
171
+ //# sourceMappingURL=GenericQualifierTypeEditForm.js.map
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HierarchyEditor = exports.ResourceTypeEditForm = exports.QualifierEditForm = exports.QualifierTypeEditForm = void 0;
3
+ exports.HierarchyEditor = exports.ResourceTypeEditForm = exports.QualifierEditForm = exports.GenericQualifierTypeEditForm = exports.QualifierTypeEditForm = void 0;
4
4
  var QualifierTypeEditForm_1 = require("./QualifierTypeEditForm");
5
5
  Object.defineProperty(exports, "QualifierTypeEditForm", { enumerable: true, get: function () { return QualifierTypeEditForm_1.QualifierTypeEditForm; } });
6
+ var GenericQualifierTypeEditForm_1 = require("./GenericQualifierTypeEditForm");
7
+ Object.defineProperty(exports, "GenericQualifierTypeEditForm", { enumerable: true, get: function () { return GenericQualifierTypeEditForm_1.GenericQualifierTypeEditForm; } });
6
8
  var QualifierEditForm_1 = require("./QualifierEditForm");
7
9
  Object.defineProperty(exports, "QualifierEditForm", { enumerable: true, get: function () { return QualifierEditForm_1.QualifierEditForm; } });
8
10
  var ResourceTypeEditForm_1 = require("./ResourceTypeEditForm");
@@ -3,55 +3,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ResourceOrchestrator = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importStar(require("react"));
6
+ const contexts_1 = require("../../contexts");
7
+ const ts_res_1 = require("@fgv/ts-res");
8
+ const ObservabilityTools = tslib_1.__importStar(require("../../utils/observability"));
6
9
  const useResourceData_1 = require("../../hooks/useResourceData");
7
10
  const useFilterState_1 = require("../../hooks/useFilterState");
8
11
  const useViewState_1 = require("../../hooks/useViewState");
9
12
  const useResolutionState_1 = require("../../hooks/useResolutionState");
10
13
  const filterResources_1 = require("../../utils/filterResources");
14
+ const downloadHelper_1 = require("../../utils/downloadHelper");
11
15
  /**
12
- * Main orchestrator component for ts-res resource management UI.
13
- *
14
- * This component provides a centralized state management and action coordination
15
- * for all ts-res UI functionality. It uses the render props pattern to provide
16
- * state and actions to child components.
17
- *
18
- * Features:
19
- * - Resource processing (files, directories, bundles)
20
- * - Filtering and context management
21
- * - Resource resolution testing
22
- * - Configuration management
23
- * - View state coordination
24
- *
25
- * @param props - ResourceOrchestrator configuration
26
- * @returns JSX element using render props pattern
27
- *
28
- * @example
29
- * ```typescript
30
- * <ResourceOrchestrator>
31
- * {({ state, actions }) => (
32
- * <div>
33
- * <ImportView
34
- * onImport={actions.importDirectory}
35
- * onBundleImport={actions.importBundle}
36
- * />
37
- * {state.processedResources && (
38
- * <SourceView
39
- * resources={state.processedResources}
40
- * onExport={actions.exportData}
41
- * />
42
- * )}
43
- * </div>
44
- * )}
45
- * </ResourceOrchestrator>
46
- * ```
47
- *
48
- * @public
16
+ * Internal orchestrator component that has access to observability context via hook.
49
17
  */
50
- const ResourceOrchestrator = ({ children, initialConfiguration, qualifierTypeFactory, resourceTypeFactory, onStateChange }) => {
18
+ const ResourceOrchestratorInternal = ({ children, initialConfiguration, qualifierTypeFactory, resourceTypeFactory, onStateChange }) => {
19
+ // Get observability context from provider
20
+ const o11y = (0, contexts_1.useObservability)();
51
21
  // Core hooks
52
22
  const resourceData = (0, useResourceData_1.useResourceData)({
53
23
  qualifierTypeFactory,
54
- resourceTypeFactory
24
+ resourceTypeFactory,
25
+ o11y
55
26
  });
56
27
  const filterState = (0, useFilterState_1.useFilterState)();
57
28
  const viewState = (0, useViewState_1.useViewState)();
@@ -97,7 +68,7 @@ const ResourceOrchestrator = ({ children, initialConfiguration, qualifierTypeFac
97
68
  const performFiltering = (0, react_1.useCallback)(async (filterValues) => {
98
69
  // Prevent concurrent filtering operations
99
70
  if (isFilteringInProgress.current) {
100
- console.log('Filtering already in progress, skipping...');
71
+ o11y.diag.info('Filtering already in progress, skipping...');
101
72
  return null;
102
73
  }
103
74
  if (!resourceData.state.processedResources || !filterState.state.enabled) {
@@ -114,12 +85,12 @@ const ResourceOrchestrator = ({ children, initialConfiguration, qualifierTypeFac
114
85
  try {
115
86
  const { system } = resourceData.state.processedResources;
116
87
  viewState.addMessage('info', 'Starting filtering process...');
117
- console.log('Filtering with values:', filterValues);
118
- console.log('Filter state:', filterState.state);
88
+ o11y.diag.info('Filtering with values:', filterValues);
89
+ o11y.diag.info('Filter state:', filterState.state);
119
90
  // Try the simplified filtering approach using provided values
120
91
  let filteredResult = await (0, filterResources_1.createFilteredResourceManagerSimple)(system, filterValues, {
121
92
  partialContextMatch: true,
122
- enableDebugLogging: true, // Enable debug logging to see what's happening
93
+ enableDebugLogging: false, // Disable debug logging to reduce console output
123
94
  reduceQualifiers: filterState.state.reduceQualifiers
124
95
  });
125
96
  if (filteredResult.isFailure()) {
@@ -135,15 +106,15 @@ const ResourceOrchestrator = ({ children, initialConfiguration, qualifierTypeFac
135
106
  }
136
107
  // Analyze filtered resources compared to original
137
108
  const originalResources = resourceData.state.processedResources.summary.resourceIds || [];
138
- console.log('Original resources count:', originalResources.length);
109
+ o11y.diag.info('Original resources count:', originalResources.length);
139
110
  const analysis = (0, filterResources_1.analyzeFilteredResources)(originalResources, filteredResult.value, resourceData.state.processedResources);
140
- console.log('Analysis result:', {
111
+ o11y.diag.info('Analysis result:', {
141
112
  success: analysis.success,
142
113
  filteredResourcesCount: analysis.filteredResources.length,
143
114
  warningsCount: analysis.warnings.length,
144
115
  hasProcessedResources: !!analysis.processedResources
145
116
  });
146
- console.log('Filtered resources breakdown:', analysis.filteredResources.map((r) => ({
117
+ o11y.diag.info('Filtered resources breakdown:', analysis.filteredResources.map((r) => ({
147
118
  id: r.id,
148
119
  originalCandidates: r.originalCandidateCount,
149
120
  filteredCandidates: r.filteredCandidateCount,
@@ -156,7 +127,7 @@ const ResourceOrchestrator = ({ children, initialConfiguration, qualifierTypeFac
156
127
  filteredResources: analysis.filteredResources,
157
128
  warnings: analysis.warnings
158
129
  };
159
- console.log('Setting filter result:', result);
130
+ o11y.diag.info('Setting filter result:', result);
160
131
  setFilterResult(result);
161
132
  if (analysis.warnings.length > 0) {
162
133
  viewState.addMessage('warning', `Filtering completed with ${analysis.warnings.length} warning(s)`);
@@ -242,12 +213,12 @@ const ResourceOrchestrator = ({ children, initialConfiguration, qualifierTypeFac
242
213
  // Resource management
243
214
  importDirectory: async (directory) => {
244
215
  viewState.addMessage('info', 'Importing directory...');
245
- await resourceData.actions.processDirectory(directory);
246
- if (!resourceData.state.error) {
216
+ const result = await resourceData.actions.processDirectory(directory);
217
+ if (result.isSuccess()) {
247
218
  viewState.addMessage('success', 'Directory imported successfully');
248
219
  }
249
220
  else {
250
- viewState.addMessage('error', resourceData.state.error);
221
+ viewState.addMessage('error', result.message);
251
222
  }
252
223
  },
253
224
  importDirectoryWithConfig: async (directory, config) => {
@@ -315,10 +286,12 @@ const ResourceOrchestrator = ({ children, initialConfiguration, qualifierTypeFac
315
286
  clearResourceEdits: resolutionData.actions.clearEdits,
316
287
  // Edits applied through unified applyPendingResources
317
288
  discardResourceEdits: resolutionData.actions.discardEdits,
318
- // Resource creation actions
289
+ // Resource creation actions (enhanced with atomic API)
290
+ createPendingResource: resolutionData.actions.createPendingResource,
319
291
  startNewResource: resolutionData.actions.startNewResource,
320
292
  updateNewResourceId: resolutionData.actions.updateNewResourceId,
321
293
  selectResourceType: resolutionData.actions.selectResourceType,
294
+ updateNewResourceJson: resolutionData.actions.updateNewResourceJson,
322
295
  saveNewResourceAsPending: resolutionData.actions.saveNewResourceAsPending,
323
296
  cancelNewResource: resolutionData.actions.cancelNewResource,
324
297
  removePendingResource: resolutionData.actions.removePendingResource,
@@ -326,15 +299,109 @@ const ResourceOrchestrator = ({ children, initialConfiguration, qualifierTypeFac
326
299
  applyPendingResources: resolutionData.actions.applyPendingResources,
327
300
  discardPendingResources: resolutionData.actions.discardPendingResources,
328
301
  // Combined apply/discard removed; use applyPendingResources/discard* directly
302
+ // Export functionality
303
+ exportBundle: () => {
304
+ const resources = resourceData.state.processedResources;
305
+ if (!resources || !resources.activeConfiguration) {
306
+ viewState.addMessage('error', 'Export bundle failed: No resource manager or configuration available');
307
+ return;
308
+ }
309
+ // Use proper Result chaining with side effects
310
+ const result = ts_res_1.Config.SystemConfiguration.create(resources.activeConfiguration)
311
+ .onSuccess((systemConfig) => ts_res_1.Bundle.BundleBuilder.create(resources.system.resourceManager, systemConfig))
312
+ .onSuccess((bundle) => downloadHelper_1.DownloadUtils.downloadBundle(bundle, resources.resourceCount));
313
+ // Handle final result with side effects
314
+ if (result.isSuccess()) {
315
+ viewState.addMessage('success', 'Bundle exported successfully');
316
+ }
317
+ else {
318
+ viewState.addMessage('error', `Export bundle failed: ${result.message}`);
319
+ }
320
+ },
321
+ exportSource: () => {
322
+ const resources = resourceData.state.processedResources;
323
+ if (!resources) {
324
+ viewState.addMessage('error', 'Export source failed: No processed resources available');
325
+ return;
326
+ }
327
+ // Use proper Result chaining with side effects
328
+ const result = downloadHelper_1.DownloadUtils.downloadSourceResources(resources, resources.resourceCount);
329
+ // Handle result with side effects
330
+ if (result.isSuccess()) {
331
+ viewState.addMessage('success', 'Source resources exported successfully');
332
+ }
333
+ else {
334
+ viewState.addMessage('error', `Export source failed: ${result.message}`);
335
+ }
336
+ },
337
+ exportCompiled: () => {
338
+ const resources = resourceData.state.processedResources;
339
+ if (!resources || !resources.compiledCollection) {
340
+ viewState.addMessage('error', 'Export compiled failed: No compiled resources available');
341
+ return;
342
+ }
343
+ // Use proper Result chaining with side effects
344
+ const result = downloadHelper_1.DownloadUtils.downloadCompiledResources(resources.compiledCollection, resources.resourceCount);
345
+ // Handle result with side effects
346
+ if (result.isSuccess()) {
347
+ viewState.addMessage('success', 'Compiled resources exported successfully');
348
+ }
349
+ else {
350
+ viewState.addMessage('error', `Export compiled failed: ${result.message}`);
351
+ }
352
+ },
329
353
  // UI state management
330
354
  selectResource: viewState.selectResource,
331
355
  addMessage: viewState.addMessage,
332
356
  clearMessages: viewState.clearMessages,
357
+ // Observability context
358
+ o11y,
333
359
  // Resource resolution
334
360
  resolveResource: resourceData.actions.resolveResource
335
361
  }), [resourceData.actions, filterState.actions, resolutionData.actions, viewState, applyFilter, resetFilter]);
336
362
  return react_1.default.createElement(react_1.default.Fragment, null, children({ state, actions }));
337
363
  };
364
+ /**
365
+ * Main orchestrator component for ts-res resource management UI.
366
+ *
367
+ * This component provides a centralized state management and action coordination
368
+ * for all ts-res UI functionality. It uses the render props pattern to provide
369
+ * state and actions to child components.
370
+ *
371
+ * Features:
372
+ * - Resource processing (files, directories, bundles)
373
+ * - Filtering and context management
374
+ * - Resource resolution testing
375
+ * - Configuration management
376
+ * - View state coordination
377
+ *
378
+ * @param props - ResourceOrchestrator configuration
379
+ * @returns JSX element using render props pattern
380
+ *
381
+ * @example
382
+ * ```typescript
383
+ * <ResourceOrchestrator>
384
+ * {({ state, actions }) => (
385
+ * <div>
386
+ * <ImportView
387
+ * onImport={actions.importDirectory}
388
+ * onBundleImport={actions.importBundle}
389
+ * />
390
+ * {state.processedResources && (
391
+ * <SourceView
392
+ * resources={state.processedResources}
393
+ * onExport={actions.exportData}
394
+ * />
395
+ * )}
396
+ * </div>
397
+ * )}
398
+ * </ResourceOrchestrator>
399
+ * ```
400
+ *
401
+ * @public
402
+ */
403
+ const ResourceOrchestrator = ({ observabilityContext = ObservabilityTools.DefaultObservabilityContext, ...props }) => (react_1.default.createElement(contexts_1.ObservabilityProvider, { observabilityContext: observabilityContext },
404
+ react_1.default.createElement(ResourceOrchestratorInternal, { ...props })));
338
405
  exports.ResourceOrchestrator = ResourceOrchestrator;
339
406
  exports.default = exports.ResourceOrchestrator;
340
407
  //# sourceMappingURL=ResourceOrchestrator.js.map
@@ -4,12 +4,14 @@ exports.ResourcePickerTree = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importStar(require("react"));
6
6
  const outline_1 = require("@heroicons/react/24/outline");
7
+ const contexts_1 = require("../../../contexts");
7
8
  /**
8
9
  * Creates a virtual tree by merging real resource tree with pending resources
9
10
  */
10
11
  function createVirtualTree(realTree, pendingResources = []) {
11
- if (!realTree)
12
+ if (!realTree) {
12
13
  return null;
14
+ }
13
15
  // Helper to convert real node to virtual node
14
16
  const convertRealNode = (realNode) => {
15
17
  const virtualNode = {
@@ -84,28 +86,46 @@ function createVirtualTree(realTree, pendingResources = []) {
84
86
  * Enhanced version of ResourceTreeView with branch isolation and annotation support
85
87
  */
86
88
  const ResourcePickerTree = ({ resources, pendingResources, selectedResourceId, onResourceSelect, resourceAnnotations, searchTerm = '', rootPath, hideRootNode, className = '', emptyMessage = 'No resources available' }) => {
89
+ // Get observability context
90
+ const o11y = (0, contexts_1.useObservability)();
87
91
  const [expandedNodes, setExpandedNodes] = (0, react_1.useState)(new Set());
88
92
  // Build the virtual tree structure from resources and pending resources
89
93
  const virtualTree = (0, react_1.useMemo)(() => {
90
- if (!resources)
94
+ if (!resources) {
91
95
  return null;
96
+ }
92
97
  // Get the tree from the resource manager
93
98
  const resourceManager = resources.system.resourceManager;
94
99
  const treeResult = resourceManager.getBuiltResourceTree();
95
100
  if (treeResult.isFailure()) {
96
- console.error('Failed to build resource tree:', treeResult.message);
101
+ o11y.diag.error('ResourcePickerTree: Failed to build resource tree:', treeResult.message);
97
102
  return null;
98
103
  }
99
104
  // Create virtual tree that includes pending resources
100
- return createVirtualTree(treeResult.value, pendingResources);
105
+ try {
106
+ const virtualTree = createVirtualTree(treeResult.value, pendingResources);
107
+ return virtualTree;
108
+ }
109
+ catch (error) {
110
+ o11y.diag.error('ResourcePickerTree: Error in createVirtualTree:', error);
111
+ return null;
112
+ }
101
113
  }, [resources, pendingResources]);
102
114
  // Find the effective root node(s) to display
103
115
  const effectiveRootNodes = (0, react_1.useMemo)(() => {
104
- if (!virtualTree)
116
+ try {
117
+ if (!virtualTree) {
118
+ return [];
119
+ }
120
+ // If no rootPath, show all top-level nodes
121
+ if (!rootPath) {
122
+ const nodes = Array.from(virtualTree.children.values());
123
+ return nodes;
124
+ }
125
+ }
126
+ catch (error) {
127
+ o11y.diag.error('ResourcePickerTree: Error in effectiveRootNodes calculation:', error);
105
128
  return [];
106
- // If no rootPath, show all top-level nodes
107
- if (!rootPath) {
108
- return Array.from(virtualTree.children.values());
109
129
  }
110
130
  // Find the target node in the virtual tree
111
131
  const findVirtualNodeById = (node, targetId) => {
@@ -280,7 +300,7 @@ const ResourcePickerTree = ({ resources, pendingResources, selectedResourceId, o
280
300
  return (react_1.default.createElement("div", { className: `${className} p-4 text-center text-gray-500` },
281
301
  react_1.default.createElement("p", null, emptyMessage)));
282
302
  }
283
- return (react_1.default.createElement("div", { className: `${className} overflow-y-auto` }, effectiveRootNodes
303
+ return (react_1.default.createElement("div", { className: `${className} overflow-y-auto !relative !z-auto !min-h-[200px]` }, effectiveRootNodes
284
304
  .sort((a, b) => {
285
305
  // Sort folders first, then by name
286
306
  if (a.isLeaf !== b.isLeaf) {
@@ -288,7 +308,9 @@ const ResourcePickerTree = ({ resources, pendingResources, selectedResourceId, o
288
308
  }
289
309
  return a.name.localeCompare(b.name);
290
310
  })
291
- .map((child) => renderTreeNode(child))));
311
+ .map((child) => {
312
+ return renderTreeNode(child);
313
+ })));
292
314
  };
293
315
  exports.ResourcePickerTree = ResourcePickerTree;
294
316
  /**
@@ -109,7 +109,9 @@ const ResourcePicker = ({ resources, selectedResourceId, onResourceSelect, resou
109
109
  react_1.default.createElement("p", null, emptyMessage || 'No resources loaded')));
110
110
  }
111
111
  const containerHeight = typeof height === 'number' ? `${height}px` : height;
112
- return (react_1.default.createElement("div", { className: `flex flex-col ${className}`, style: { height: containerHeight } },
112
+ return (react_1.default.createElement("div", { className: `flex flex-col !relative !z-auto !min-h-[400px] ${className}`, style: {
113
+ height: containerHeight
114
+ } },
113
115
  (enableSearch || showViewToggle) && (react_1.default.createElement("div", { className: "flex flex-col gap-3 mb-4" },
114
116
  enableSearch && (react_1.default.createElement("div", { className: "relative" },
115
117
  react_1.default.createElement(outline_1.MagnifyingGlassIcon, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" }),
@@ -131,7 +133,7 @@ const ResourcePicker = ({ resources, selectedResourceId, onResourceSelect, resou
131
133
  : 'text-gray-600 hover:text-gray-900'}`, title: "Tree View" },
132
134
  react_1.default.createElement(outline_1.FolderIcon, { className: "h-4 w-4" }),
133
135
  react_1.default.createElement("span", { className: "ml-1" }, "Tree"))))))),
134
- react_1.default.createElement("div", { className: "flex-1 overflow-y-auto border border-gray-200 rounded-lg bg-gray-50" }, viewMode === 'tree' ? (react_1.default.createElement(ResourcePickerTree_1.ResourcePickerTree, { resources: resources, pendingResources: pendingResources, selectedResourceId: selectedResourceId, onResourceSelect: handleResourceSelect, resourceAnnotations: resourceAnnotations, searchTerm: searchTerm, rootPath: rootPath, hideRootNode: hideRootNode, emptyMessage: emptyMessage })) : (react_1.default.createElement(ResourcePickerList_1.ResourcePickerList, { resourceIds: resources.summary.resourceIds || [], pendingResources: pendingResources, selectedResourceId: selectedResourceId, onResourceSelect: handleResourceSelect, resourceAnnotations: resourceAnnotations, searchTerm: searchTerm, rootPath: rootPath, hideRootNode: hideRootNode, emptyMessage: emptyMessage })))));
136
+ react_1.default.createElement("div", { className: "flex-1 overflow-y-auto border border-gray-200 rounded-lg bg-gray-50 !relative !z-auto !min-h-[300px]" }, viewMode === 'tree' ? (react_1.default.createElement(ResourcePickerTree_1.ResourcePickerTree, { resources: resources, pendingResources: pendingResources, selectedResourceId: selectedResourceId, onResourceSelect: handleResourceSelect, resourceAnnotations: resourceAnnotations, searchTerm: searchTerm, rootPath: rootPath, hideRootNode: hideRootNode, emptyMessage: emptyMessage })) : (react_1.default.createElement(ResourcePickerList_1.ResourcePickerList, { resourceIds: resources.summary.resourceIds || [], pendingResources: pendingResources, selectedResourceId: selectedResourceId, onResourceSelect: handleResourceSelect, resourceAnnotations: resourceAnnotations, searchTerm: searchTerm, rootPath: rootPath, hideRootNode: hideRootNode, emptyMessage: emptyMessage })))));
135
137
  };
136
138
  exports.ResourcePicker = ResourcePicker;
137
139
  exports.default = exports.ResourcePicker;