@fgv/ts-res-ui-components 5.0.0-10

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 (231) hide show
  1. package/.rush/temp/03c8b056281d9db0a97d8a6e25eea798a160d393.tar.log +271 -0
  2. package/.rush/temp/chunked-rush-logs/ts-res-ui-components.build.chunks.jsonl +9 -0
  3. package/.rush/temp/operation/build/all.log +9 -0
  4. package/.rush/temp/operation/build/log-chunks.jsonl +9 -0
  5. package/.rush/temp/operation/build/state.json +3 -0
  6. package/.rush/temp/shrinkwrap-deps.json +1111 -0
  7. package/README.md +18 -0
  8. package/REFACTORING_PLAN.md +171 -0
  9. package/config/jest.config.json +16 -0
  10. package/config/jest.setup.js +64 -0
  11. package/config/rig.json +16 -0
  12. package/lib/components/common/QualifierContextControl.d.ts +14 -0
  13. package/lib/components/common/QualifierContextControl.d.ts.map +1 -0
  14. package/lib/components/common/QualifierContextControl.js +78 -0
  15. package/lib/components/common/QualifierContextControl.js.map +1 -0
  16. package/lib/components/common/ResourceListView.d.ts +11 -0
  17. package/lib/components/common/ResourceListView.d.ts.map +1 -0
  18. package/lib/components/common/ResourceListView.js +20 -0
  19. package/lib/components/common/ResourceListView.js.map +1 -0
  20. package/lib/components/common/ResourceTreeView.d.ts +12 -0
  21. package/lib/components/common/ResourceTreeView.d.ts.map +1 -0
  22. package/lib/components/common/ResourceTreeView.js +162 -0
  23. package/lib/components/common/ResourceTreeView.js.map +1 -0
  24. package/lib/components/forms/HierarchyEditor.d.ts +10 -0
  25. package/lib/components/forms/HierarchyEditor.d.ts.map +1 -0
  26. package/lib/components/forms/HierarchyEditor.js +106 -0
  27. package/lib/components/forms/HierarchyEditor.js.map +1 -0
  28. package/lib/components/forms/QualifierEditForm.d.ts +11 -0
  29. package/lib/components/forms/QualifierEditForm.d.ts.map +1 -0
  30. package/lib/components/forms/QualifierEditForm.js +181 -0
  31. package/lib/components/forms/QualifierEditForm.js.map +1 -0
  32. package/lib/components/forms/QualifierTypeEditForm.d.ts +10 -0
  33. package/lib/components/forms/QualifierTypeEditForm.d.ts.map +1 -0
  34. package/lib/components/forms/QualifierTypeEditForm.js +172 -0
  35. package/lib/components/forms/QualifierTypeEditForm.js.map +1 -0
  36. package/lib/components/forms/ResourceTypeEditForm.d.ts +10 -0
  37. package/lib/components/forms/ResourceTypeEditForm.d.ts.map +1 -0
  38. package/lib/components/forms/ResourceTypeEditForm.js +188 -0
  39. package/lib/components/forms/ResourceTypeEditForm.js.map +1 -0
  40. package/lib/components/forms/index.d.ts +9 -0
  41. package/lib/components/forms/index.d.ts.map +1 -0
  42. package/lib/components/forms/index.js +5 -0
  43. package/lib/components/forms/index.js.map +1 -0
  44. package/lib/components/orchestrator/ResourceOrchestrator.d.ts +14 -0
  45. package/lib/components/orchestrator/ResourceOrchestrator.d.ts.map +1 -0
  46. package/lib/components/orchestrator/ResourceOrchestrator.js +278 -0
  47. package/lib/components/orchestrator/ResourceOrchestrator.js.map +1 -0
  48. package/lib/components/views/CompiledView/index.d.ts +5 -0
  49. package/lib/components/views/CompiledView/index.d.ts.map +1 -0
  50. package/lib/components/views/CompiledView/index.js +595 -0
  51. package/lib/components/views/CompiledView/index.js.map +1 -0
  52. package/lib/components/views/ConfigurationView/index.d.ts +5 -0
  53. package/lib/components/views/ConfigurationView/index.d.ts.map +1 -0
  54. package/lib/components/views/ConfigurationView/index.js +363 -0
  55. package/lib/components/views/ConfigurationView/index.js.map +1 -0
  56. package/lib/components/views/FilterView/index.d.ts +5 -0
  57. package/lib/components/views/FilterView/index.d.ts.map +1 -0
  58. package/lib/components/views/FilterView/index.js +463 -0
  59. package/lib/components/views/FilterView/index.js.map +1 -0
  60. package/lib/components/views/ImportView/index.d.ts +5 -0
  61. package/lib/components/views/ImportView/index.d.ts.map +1 -0
  62. package/lib/components/views/ImportView/index.js +514 -0
  63. package/lib/components/views/ImportView/index.js.map +1 -0
  64. package/lib/components/views/ResolutionView/EditableJsonView.d.ts +21 -0
  65. package/lib/components/views/ResolutionView/EditableJsonView.d.ts.map +1 -0
  66. package/lib/components/views/ResolutionView/EditableJsonView.js +109 -0
  67. package/lib/components/views/ResolutionView/EditableJsonView.js.map +1 -0
  68. package/lib/components/views/ResolutionView/ResolutionEditControls.d.ts +19 -0
  69. package/lib/components/views/ResolutionView/ResolutionEditControls.d.ts.map +1 -0
  70. package/lib/components/views/ResolutionView/ResolutionEditControls.js +82 -0
  71. package/lib/components/views/ResolutionView/ResolutionEditControls.js.map +1 -0
  72. package/lib/components/views/ResolutionView/index.d.ts +5 -0
  73. package/lib/components/views/ResolutionView/index.d.ts.map +1 -0
  74. package/lib/components/views/ResolutionView/index.js +255 -0
  75. package/lib/components/views/ResolutionView/index.js.map +1 -0
  76. package/lib/components/views/SourceView/index.d.ts +5 -0
  77. package/lib/components/views/SourceView/index.d.ts.map +1 -0
  78. package/lib/components/views/SourceView/index.js +316 -0
  79. package/lib/components/views/SourceView/index.js.map +1 -0
  80. package/lib/components/views/ZipLoaderView/index.d.ts +5 -0
  81. package/lib/components/views/ZipLoaderView/index.d.ts.map +1 -0
  82. package/lib/components/views/ZipLoaderView/index.js +313 -0
  83. package/lib/components/views/ZipLoaderView/index.js.map +1 -0
  84. package/lib/hooks/useConfigurationState.d.ts +46 -0
  85. package/lib/hooks/useConfigurationState.d.ts.map +1 -0
  86. package/lib/hooks/useConfigurationState.js +239 -0
  87. package/lib/hooks/useConfigurationState.js.map +1 -0
  88. package/lib/hooks/useFilterState.d.ts +7 -0
  89. package/lib/hooks/useFilterState.d.ts.map +1 -0
  90. package/lib/hooks/useFilterState.js +80 -0
  91. package/lib/hooks/useFilterState.js.map +1 -0
  92. package/lib/hooks/useResolutionState.d.ts +8 -0
  93. package/lib/hooks/useResolutionState.d.ts.map +1 -0
  94. package/lib/hooks/useResolutionState.js +253 -0
  95. package/lib/hooks/useResolutionState.js.map +1 -0
  96. package/lib/hooks/useResourceData.d.ts +19 -0
  97. package/lib/hooks/useResourceData.d.ts.map +1 -0
  98. package/lib/hooks/useResourceData.js +368 -0
  99. package/lib/hooks/useResourceData.js.map +1 -0
  100. package/lib/hooks/useViewState.d.ts +10 -0
  101. package/lib/hooks/useViewState.d.ts.map +1 -0
  102. package/lib/hooks/useViewState.js +29 -0
  103. package/lib/hooks/useViewState.js.map +1 -0
  104. package/lib/index.d.ts +27 -0
  105. package/lib/index.d.ts.map +1 -0
  106. package/lib/index.js +34 -0
  107. package/lib/index.js.map +1 -0
  108. package/lib/test/helpers/testDataLoader.d.ts +37 -0
  109. package/lib/test/helpers/testDataLoader.d.ts.map +1 -0
  110. package/lib/test/helpers/testDataLoader.js +171 -0
  111. package/lib/test/helpers/testDataLoader.js.map +1 -0
  112. package/lib/test/unit/utils/configurationUtils.test.d.ts +2 -0
  113. package/lib/test/unit/utils/configurationUtils.test.d.ts.map +1 -0
  114. package/lib/test/unit/utils/configurationUtils.test.js +497 -0
  115. package/lib/test/unit/utils/configurationUtils.test.js.map +1 -0
  116. package/lib/test/unit/utils/fileProcessing.test.d.ts +2 -0
  117. package/lib/test/unit/utils/fileProcessing.test.d.ts.map +1 -0
  118. package/lib/test/unit/utils/fileProcessing.test.js +321 -0
  119. package/lib/test/unit/utils/fileProcessing.test.js.map +1 -0
  120. package/lib/test/unit/utils/filterResources.test.d.ts +2 -0
  121. package/lib/test/unit/utils/filterResources.test.d.ts.map +1 -0
  122. package/lib/test/unit/utils/filterResources.test.js +403 -0
  123. package/lib/test/unit/utils/filterResources.test.js.map +1 -0
  124. package/lib/test/unit/utils/resolutionEditing.test.d.ts +2 -0
  125. package/lib/test/unit/utils/resolutionEditing.test.d.ts.map +1 -0
  126. package/lib/test/unit/utils/resolutionEditing.test.js +439 -0
  127. package/lib/test/unit/utils/resolutionEditing.test.js.map +1 -0
  128. package/lib/test/unit/utils/resolutionUtils.test.d.ts +2 -0
  129. package/lib/test/unit/utils/resolutionUtils.test.d.ts.map +1 -0
  130. package/lib/test/unit/utils/resolutionUtils.test.js +397 -0
  131. package/lib/test/unit/utils/resolutionUtils.test.js.map +1 -0
  132. package/lib/test/unit/utils/tsResIntegration.test.d.ts +2 -0
  133. package/lib/test/unit/utils/tsResIntegration.test.d.ts.map +1 -0
  134. package/lib/test/unit/utils/tsResIntegration.test.js +376 -0
  135. package/lib/test/unit/utils/tsResIntegration.test.js.map +1 -0
  136. package/lib/types/index.d.ts +251 -0
  137. package/lib/types/index.d.ts.map +1 -0
  138. package/lib/types/index.js +2 -0
  139. package/lib/types/index.js.map +1 -0
  140. package/lib/utils/configurationUtils.d.ts +74 -0
  141. package/lib/utils/configurationUtils.d.ts.map +1 -0
  142. package/lib/utils/configurationUtils.js +359 -0
  143. package/lib/utils/configurationUtils.js.map +1 -0
  144. package/lib/utils/fileProcessing.d.ts +18 -0
  145. package/lib/utils/fileProcessing.d.ts.map +1 -0
  146. package/lib/utils/fileProcessing.js +142 -0
  147. package/lib/utils/fileProcessing.js.map +1 -0
  148. package/lib/utils/filterResources.d.ts +38 -0
  149. package/lib/utils/filterResources.d.ts.map +1 -0
  150. package/lib/utils/filterResources.js +153 -0
  151. package/lib/utils/filterResources.js.map +1 -0
  152. package/lib/utils/resolutionEditing.d.ts +58 -0
  153. package/lib/utils/resolutionEditing.d.ts.map +1 -0
  154. package/lib/utils/resolutionEditing.js +246 -0
  155. package/lib/utils/resolutionEditing.js.map +1 -0
  156. package/lib/utils/resolutionUtils.d.ts +28 -0
  157. package/lib/utils/resolutionUtils.d.ts.map +1 -0
  158. package/lib/utils/resolutionUtils.js +216 -0
  159. package/lib/utils/resolutionUtils.js.map +1 -0
  160. package/lib/utils/tsResIntegration.d.ts +71 -0
  161. package/lib/utils/tsResIntegration.d.ts.map +1 -0
  162. package/lib/utils/tsResIntegration.js +294 -0
  163. package/lib/utils/tsResIntegration.js.map +1 -0
  164. package/lib/utils/zipLoader/browserZipLoader.d.ts +48 -0
  165. package/lib/utils/zipLoader/browserZipLoader.d.ts.map +1 -0
  166. package/lib/utils/zipLoader/browserZipLoader.js +247 -0
  167. package/lib/utils/zipLoader/browserZipLoader.js.map +1 -0
  168. package/lib/utils/zipLoader/index.d.ts +8 -0
  169. package/lib/utils/zipLoader/index.d.ts.map +1 -0
  170. package/lib/utils/zipLoader/index.js +13 -0
  171. package/lib/utils/zipLoader/index.js.map +1 -0
  172. package/lib/utils/zipLoader/nodeZipBuilder.d.ts +55 -0
  173. package/lib/utils/zipLoader/nodeZipBuilder.d.ts.map +1 -0
  174. package/lib/utils/zipLoader/nodeZipBuilder.js +98 -0
  175. package/lib/utils/zipLoader/nodeZipBuilder.js.map +1 -0
  176. package/lib/utils/zipLoader/types.d.ts +139 -0
  177. package/lib/utils/zipLoader/types.d.ts.map +1 -0
  178. package/lib/utils/zipLoader/types.js +2 -0
  179. package/lib/utils/zipLoader/types.js.map +1 -0
  180. package/lib/utils/zipLoader/zipUtils.d.ts +53 -0
  181. package/lib/utils/zipLoader/zipUtils.d.ts.map +1 -0
  182. package/lib/utils/zipLoader/zipUtils.js +229 -0
  183. package/lib/utils/zipLoader/zipUtils.js.map +1 -0
  184. package/package.json +69 -0
  185. package/rush-logs/ts-res-ui-components.build.cache.log +3 -0
  186. package/rush-logs/ts-res-ui-components.build.log +9 -0
  187. package/src/components/common/QualifierContextControl.tsx +151 -0
  188. package/src/components/common/ResourceListView.tsx +63 -0
  189. package/src/components/common/ResourceTreeView.tsx +271 -0
  190. package/src/components/forms/HierarchyEditor.tsx +204 -0
  191. package/src/components/forms/QualifierEditForm.tsx +355 -0
  192. package/src/components/forms/QualifierTypeEditForm.tsx +347 -0
  193. package/src/components/forms/ResourceTypeEditForm.tsx +331 -0
  194. package/src/components/forms/index.ts +11 -0
  195. package/src/components/orchestrator/ResourceOrchestrator.tsx +372 -0
  196. package/src/components/views/CompiledView/index.tsx +922 -0
  197. package/src/components/views/ConfigurationView/index.tsx +800 -0
  198. package/src/components/views/FilterView/index.tsx +825 -0
  199. package/src/components/views/ImportView/index.tsx +717 -0
  200. package/src/components/views/ResolutionView/EditableJsonView.tsx +214 -0
  201. package/src/components/views/ResolutionView/ResolutionEditControls.tsx +170 -0
  202. package/src/components/views/ResolutionView/index.tsx +591 -0
  203. package/src/components/views/SourceView/index.tsx +536 -0
  204. package/src/components/views/ZipLoaderView/index.tsx +485 -0
  205. package/src/hooks/useConfigurationState.ts +374 -0
  206. package/src/hooks/useFilterState.ts +97 -0
  207. package/src/hooks/useResolutionState.ts +355 -0
  208. package/src/hooks/useResourceData.ts +467 -0
  209. package/src/hooks/useViewState.ts +44 -0
  210. package/src/index.ts +45 -0
  211. package/src/test/helpers/testDataLoader.ts +195 -0
  212. package/src/test/unit/utils/configurationUtils.test.ts +630 -0
  213. package/src/test/unit/utils/fileProcessing.test.ts +391 -0
  214. package/src/test/unit/utils/filterResources.test.ts +574 -0
  215. package/src/test/unit/utils/resolutionEditing.test.ts +556 -0
  216. package/src/test/unit/utils/resolutionUtils.test.ts +521 -0
  217. package/src/test/unit/utils/tsResIntegration.test.ts +433 -0
  218. package/src/types/index.ts +322 -0
  219. package/src/utils/configurationUtils.ts +424 -0
  220. package/src/utils/fileProcessing.ts +160 -0
  221. package/src/utils/filterResources.ts +206 -0
  222. package/src/utils/resolutionEditing.ts +319 -0
  223. package/src/utils/resolutionUtils.ts +289 -0
  224. package/src/utils/tsResIntegration.ts +440 -0
  225. package/src/utils/zipLoader/browserZipLoader.ts +319 -0
  226. package/src/utils/zipLoader/index.ts +26 -0
  227. package/src/utils/zipLoader/nodeZipBuilder.ts +153 -0
  228. package/src/utils/zipLoader/types.ts +175 -0
  229. package/src/utils/zipLoader/zipUtils.ts +266 -0
  230. package/temp/build/typescript/ts_gZid87Hu.json +1 -0
  231. package/tsconfig.json +15 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResourceTreeView.js","sourceRoot":"","sources":["../../../src/components/common/ResourceTreeView.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState, useMemo, useCallback } from 'react';\nimport {\n ChevronRightIcon,\n ChevronDownIcon,\n DocumentTextIcon,\n FolderIcon,\n FolderOpenIcon\n} from '@heroicons/react/24/outline';\nimport { Resources, Runtime } from '@fgv/ts-res';\n\ninterface ResourceTreeViewProps {\n resources: Resources.ResourceManagerBuilder | Runtime.CompiledResourceCollection;\n selectedResourceId: string | null;\n onResourceSelect: (resourceId: string) => void;\n searchTerm?: string;\n className?: string;\n}\n\ninterface TreeNode {\n id: string;\n name: string;\n isLeaf: boolean;\n resource?: Resources.Resource | Runtime.IResource;\n children?: Map<string, TreeNode>;\n isExpanded?: boolean;\n isVisible?: boolean;\n matchesSearch?: boolean;\n}\n\nexport const ResourceTreeView: React.FC<ResourceTreeViewProps> = ({\n resources,\n selectedResourceId,\n onResourceSelect,\n searchTerm = '',\n className = ''\n}) => {\n const [expandedNodes, setExpandedNodes] = useState<Set<string>>(new Set());\n\n // Build the tree structure from resources\n const treeData = useMemo(() => {\n if (!resources) return null;\n\n // Get the tree from the resources\n const treeResult = resources.getBuiltResourceTree();\n if (treeResult.isFailure()) {\n console.error('Failed to build resource tree:', treeResult.message);\n return null;\n }\n\n return treeResult.value;\n }, [resources]);\n\n // Filter tree based on search term\n const filteredTree = useMemo(() => {\n if (!treeData || !searchTerm) return treeData;\n\n // Helper function to check if a node or its descendants match the search\n const markMatchingNodes = (\n node: Runtime.ResourceTree.IReadOnlyResourceTreeNode<any>,\n searchLower: string\n ): boolean => {\n const nodeIdLower = node.id.toLowerCase();\n let matches = nodeIdLower.includes(searchLower);\n\n if (!node.isLeaf && node.children) {\n // Check children recursively\n for (const child of node.children.values()) {\n if (markMatchingNodes(child, searchLower)) {\n matches = true;\n }\n }\n }\n\n return matches;\n };\n\n // Mark all matching nodes\n const searchLower = searchTerm.toLowerCase();\n for (const child of treeData.children.values()) {\n markMatchingNodes(child, searchLower);\n }\n\n return treeData;\n }, [treeData, searchTerm]);\n\n // Toggle node expansion\n const toggleNode = useCallback((nodeId: string) => {\n setExpandedNodes((prev) => {\n const newExpanded = new Set(prev);\n if (newExpanded.has(nodeId)) {\n newExpanded.delete(nodeId);\n } else {\n newExpanded.add(nodeId);\n }\n return newExpanded;\n });\n }, []);\n\n // Expand all nodes that contain search matches\n const expandMatchingNodes = useCallback(() => {\n if (!searchTerm || !filteredTree) return;\n\n const searchLower = searchTerm.toLowerCase();\n const nodesToExpand = new Set<string>();\n\n const checkNode = (node: Runtime.ResourceTree.IReadOnlyResourceTreeNode<any>) => {\n if (node.id.toLowerCase().includes(searchLower)) {\n // Expand all parent nodes\n const parts = node.id.split('.');\n for (let i = 1; i < parts.length; i++) {\n nodesToExpand.add(parts.slice(0, i).join('.'));\n }\n }\n\n if (!node.isLeaf && node.children) {\n for (const child of node.children.values()) {\n checkNode(child);\n }\n }\n };\n\n for (const child of filteredTree.children.values()) {\n checkNode(child);\n }\n\n setExpandedNodes(nodesToExpand);\n }, [searchTerm, filteredTree]);\n\n // Auto-expand when search term changes\n React.useEffect(() => {\n if (searchTerm) {\n expandMatchingNodes();\n }\n }, [searchTerm, expandMatchingNodes]);\n\n // Render a single tree node\n const renderTreeNode = (\n node: Runtime.ResourceTree.IReadOnlyResourceTreeNode<Resources.Resource | Runtime.IResource>,\n level: number = 0\n ): React.ReactElement | null => {\n const isExpanded = expandedNodes.has(node.id);\n const isSelected = selectedResourceId === node.id;\n const nodeIdLower = node.id.toLowerCase();\n const searchLower = searchTerm.toLowerCase();\n const matchesSearch = !searchTerm || nodeIdLower.includes(searchLower);\n\n // Check if any children match\n let hasMatchingChildren = false;\n if (!node.isLeaf && node.children && searchTerm) {\n const checkChildren = (n: Runtime.ResourceTree.IReadOnlyResourceTreeNode<any>): boolean => {\n if (n.id.toLowerCase().includes(searchLower)) return true;\n if (!n.isLeaf && n.children) {\n for (const child of n.children.values()) {\n if (checkChildren(child)) return true;\n }\n }\n return false;\n };\n\n for (const child of node.children.values()) {\n if (checkChildren(child)) {\n hasMatchingChildren = true;\n break;\n }\n }\n }\n\n // Hide nodes that don't match search and don't have matching children\n if (searchTerm && !matchesSearch && !hasMatchingChildren) {\n return null;\n }\n\n return (\n <div key={node.id}>\n <div\n className={`flex items-center px-2 py-1 cursor-pointer hover:bg-gray-100 ${\n isSelected ? 'bg-purple-50 border-l-2 border-purple-500' : ''\n } ${matchesSearch && searchTerm ? 'bg-yellow-50' : ''}`}\n style={{ paddingLeft: `${level * 20 + 8}px` }}\n onClick={() => {\n if (node.isLeaf) {\n onResourceSelect(node.id);\n } else {\n toggleNode(node.id);\n }\n }}\n >\n {/* Expand/Collapse icon for branches */}\n {!node.isLeaf && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n toggleNode(node.id);\n }}\n className=\"mr-1 p-0.5 hover:bg-gray-200 rounded\"\n >\n {isExpanded ? (\n <ChevronDownIcon className=\"w-3 h-3 text-gray-600\" />\n ) : (\n <ChevronRightIcon className=\"w-3 h-3 text-gray-600\" />\n )}\n </button>\n )}\n\n {/* Folder or document icon */}\n {node.isLeaf ? (\n <DocumentTextIcon className=\"w-4 h-4 text-green-500 mr-2 flex-shrink-0\" />\n ) : isExpanded ? (\n <FolderOpenIcon className=\"w-4 h-4 text-blue-500 mr-2 flex-shrink-0\" />\n ) : (\n <FolderIcon className=\"w-4 h-4 text-blue-500 mr-2 flex-shrink-0\" />\n )}\n\n {/* Node name */}\n <span\n className={`text-sm truncate ${isSelected ? 'font-medium text-purple-900' : 'text-gray-700'} ${\n matchesSearch && searchTerm ? 'font-medium' : ''\n }`}\n title={node.id}\n >\n {node.name}\n </span>\n\n {/* Show child count for branches */}\n {!node.isLeaf && node.children && (\n <span className=\"ml-2 text-xs text-gray-500\">({node.children.size})</span>\n )}\n </div>\n\n {/* Render children if expanded */}\n {!node.isLeaf && node.children && isExpanded && (\n <div>\n {Array.from(node.children.values())\n .sort((a, b) => {\n // Sort folders first, then by name\n if (a.isLeaf !== b.isLeaf) {\n return a.isLeaf ? 1 : -1;\n }\n return a.name.localeCompare(b.name);\n })\n .map((child) => renderTreeNode(child, level + 1))}\n </div>\n )}\n </div>\n );\n };\n\n if (!filteredTree) {\n return (\n <div className={`${className} p-4 text-center text-gray-500`}>\n <p>No resources available</p>\n </div>\n );\n }\n\n return (\n <div className={`${className} overflow-y-auto`}>\n {Array.from(filteredTree.children.values())\n .sort((a, b) => {\n // Sort folders first, then by name\n if (a.isLeaf !== b.isLeaf) {\n return a.isLeaf ? 1 : -1;\n }\n return a.name.localeCompare(b.name);\n })\n .map((child) => renderTreeNode(child))}\n </div>\n );\n};\n\nexport default ResourceTreeView;\n"]}
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ export interface HierarchyEditorProps {
3
+ hierarchy: Record<string, string>;
4
+ onChange: (hierarchy: Record<string, string>) => void;
5
+ availableValues: string[];
6
+ className?: string;
7
+ }
8
+ export declare const HierarchyEditor: React.FC<HierarchyEditorProps>;
9
+ export default HierarchyEditor;
10
+ //# sourceMappingURL=HierarchyEditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HierarchyEditor.d.ts","sourceRoot":"","sources":["../../../src/components/forms/HierarchyEditor.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IACtD,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAgM1D,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -0,0 +1,106 @@
1
+ import React, { useState } from 'react';
2
+ export const HierarchyEditor = ({ hierarchy, onChange, availableValues, className = '' }) => {
3
+ const [newChild, setNewChild] = useState('');
4
+ const [newParent, setNewParent] = useState('');
5
+ // Ensure hierarchy is a valid object with string values
6
+ const safeHierarchy = React.useMemo(() => {
7
+ if (!hierarchy || typeof hierarchy !== 'object') {
8
+ return {};
9
+ }
10
+ // Filter out any non-string values
11
+ const safe = {};
12
+ for (const [key, value] of Object.entries(hierarchy)) {
13
+ if (typeof value === 'string') {
14
+ safe[key] = value;
15
+ }
16
+ }
17
+ return safe;
18
+ }, [hierarchy]);
19
+ const handleAddRelationship = () => {
20
+ if (newChild && newParent && newChild !== newParent) {
21
+ const updatedHierarchy = { ...safeHierarchy, [newChild]: newParent };
22
+ onChange(updatedHierarchy);
23
+ setNewChild('');
24
+ setNewParent('');
25
+ }
26
+ };
27
+ const handleRemoveRelationship = (child) => {
28
+ const updatedHierarchy = { ...safeHierarchy };
29
+ delete updatedHierarchy[child];
30
+ onChange(updatedHierarchy);
31
+ };
32
+ const getHierarchyTree = () => {
33
+ const roots = new Set(availableValues);
34
+ const children = new Set(Object.keys(safeHierarchy));
35
+ const parents = new Set(Object.values(safeHierarchy));
36
+ // Remove children from roots (they have parents)
37
+ children.forEach((child) => roots.delete(child));
38
+ // Add parents that aren't in available values (for display purposes)
39
+ parents.forEach((parent) => {
40
+ if (!availableValues.includes(parent)) {
41
+ roots.add(parent);
42
+ }
43
+ });
44
+ const buildTree = (value, level = 0) => {
45
+ const childrenOfValue = Object.entries(safeHierarchy).filter(([, parent]) => parent === value);
46
+ return {
47
+ value,
48
+ level,
49
+ children: childrenOfValue.map(([child]) => buildTree(child, level + 1))
50
+ };
51
+ };
52
+ return Array.from(roots).map((root) => buildTree(root));
53
+ };
54
+ const renderTree = (nodes) => {
55
+ return nodes.map((node) => {
56
+ const parentValue = safeHierarchy[node.value];
57
+ return (React.createElement("div", { key: node.value, className: "ml-4" },
58
+ React.createElement("div", { className: "flex items-center space-x-2 py-1" },
59
+ React.createElement("span", { className: "text-sm text-gray-700", style: { marginLeft: `${node.level * 20}px` } },
60
+ node.level > 0 && '└─ ',
61
+ node.value),
62
+ parentValue && React.createElement("span", { className: "text-xs text-gray-500" },
63
+ "\u2192 ",
64
+ parentValue)),
65
+ node.children.length > 0 && renderTree(node.children)));
66
+ });
67
+ };
68
+ return (React.createElement("div", { className: className },
69
+ React.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-2" }, "Value Hierarchy"),
70
+ React.createElement("div", { className: "border border-gray-300 rounded-md p-3 bg-white" },
71
+ React.createElement("div", { className: "mb-4 p-3 bg-gray-50 rounded border" },
72
+ React.createElement("div", { className: "text-sm font-medium text-gray-700 mb-2" }, "Add Parent-Child Relationship"),
73
+ React.createElement("div", { className: "grid grid-cols-3 gap-2 items-end" },
74
+ React.createElement("div", null,
75
+ React.createElement("label", { className: "block text-xs text-gray-600" }, "Child Value"),
76
+ availableValues.length > 0 ? (React.createElement("select", { value: newChild, onChange: (e) => setNewChild(e.target.value), className: "w-full text-sm rounded border-gray-300 focus:border-blue-500 focus:ring-blue-500" },
77
+ React.createElement("option", { value: "" }, "Select child..."),
78
+ availableValues.map((value) => (React.createElement("option", { key: value, value: value }, value))))) : (React.createElement("input", { type: "text", value: newChild, onChange: (e) => setNewChild(e.target.value), placeholder: "Enter child value", className: "w-full text-sm rounded border-gray-300 focus:border-blue-500 focus:ring-blue-500" }))),
79
+ React.createElement("div", null,
80
+ React.createElement("label", { className: "block text-xs text-gray-600" }, "Parent Value"),
81
+ React.createElement("input", { type: "text", value: newParent, onChange: (e) => setNewParent(e.target.value), placeholder: "Enter parent value", className: "w-full text-sm rounded border-gray-300 focus:border-blue-500 focus:ring-blue-500" })),
82
+ React.createElement("div", null,
83
+ React.createElement("button", { onClick: handleAddRelationship, disabled: !newChild || !newParent || newChild === newParent, className: "w-full px-3 py-1 text-sm bg-blue-600 text-white rounded hover:bg-blue-700 disabled:bg-gray-300 disabled:cursor-not-allowed" }, "Add"))),
84
+ React.createElement("div", { className: "text-xs text-gray-500 mt-1" }, availableValues.length > 0
85
+ ? "Define which values are children of other values. The parent doesn't need to be in the enumerated values list."
86
+ : 'Define which values are children of other values. Enter any valid values for this qualifier type.')),
87
+ Object.keys(safeHierarchy).length > 0 && (React.createElement("div", { className: "mb-4" },
88
+ React.createElement("div", { className: "text-sm font-medium text-gray-700 mb-2" },
89
+ "Current Relationships (",
90
+ Object.keys(safeHierarchy).length,
91
+ ")"),
92
+ React.createElement("div", { className: "max-h-24 overflow-y-auto border border-gray-200 rounded bg-white p-2" },
93
+ React.createElement("div", { className: "space-y-1" }, Object.entries(safeHierarchy).map(([child, parent]) => (React.createElement("div", { key: child, className: "flex items-center justify-between bg-gray-50 px-2 py-1 rounded" },
94
+ React.createElement("span", { className: "text-sm" },
95
+ React.createElement("span", { className: "font-medium" }, child),
96
+ " \u2192",
97
+ ' ',
98
+ React.createElement("span", { className: "text-gray-600" }, parent)),
99
+ React.createElement("button", { onClick: () => handleRemoveRelationship(child), className: "text-red-600 hover:text-red-800 text-xs ml-2 flex-shrink-0" }, "Remove")))))))),
100
+ (availableValues.length > 0 || Object.keys(safeHierarchy).length > 0) && (React.createElement("div", null,
101
+ React.createElement("div", { className: "text-sm font-medium text-gray-700 mb-2" }, "Hierarchy Tree"),
102
+ React.createElement("div", { className: "bg-gray-50 border rounded max-h-32 overflow-y-auto" },
103
+ React.createElement("div", { className: "p-2 text-sm font-mono" }, getHierarchyTree().length > 0 ? (renderTree(getHierarchyTree())) : (React.createElement("div", { className: "text-gray-500 text-center py-2" }, "No hierarchy defined. Add relationships above to see the tree structure.")))))))));
104
+ };
105
+ export default HierarchyEditor;
106
+ //# sourceMappingURL=HierarchyEditor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HierarchyEditor.js","sourceRoot":"","sources":["../../../src/components/forms/HierarchyEditor.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState } from 'react';\n\nexport interface HierarchyEditorProps {\n hierarchy: Record<string, string>;\n onChange: (hierarchy: Record<string, string>) => void;\n availableValues: string[];\n className?: string;\n}\n\nexport const HierarchyEditor: React.FC<HierarchyEditorProps> = ({\n hierarchy,\n onChange,\n availableValues,\n className = ''\n}) => {\n const [newChild, setNewChild] = useState('');\n const [newParent, setNewParent] = useState('');\n\n // Ensure hierarchy is a valid object with string values\n const safeHierarchy = React.useMemo(() => {\n if (!hierarchy || typeof hierarchy !== 'object') {\n return {};\n }\n // Filter out any non-string values\n const safe: Record<string, string> = {};\n for (const [key, value] of Object.entries(hierarchy)) {\n if (typeof value === 'string') {\n safe[key] = value;\n }\n }\n return safe;\n }, [hierarchy]);\n\n const handleAddRelationship = () => {\n if (newChild && newParent && newChild !== newParent) {\n const updatedHierarchy = { ...safeHierarchy, [newChild]: newParent };\n onChange(updatedHierarchy);\n setNewChild('');\n setNewParent('');\n }\n };\n\n const handleRemoveRelationship = (child: string) => {\n const updatedHierarchy = { ...safeHierarchy };\n delete updatedHierarchy[child];\n onChange(updatedHierarchy);\n };\n\n const getHierarchyTree = () => {\n const roots = new Set(availableValues);\n const children = new Set(Object.keys(safeHierarchy));\n const parents = new Set(Object.values(safeHierarchy));\n\n // Remove children from roots (they have parents)\n children.forEach((child) => roots.delete(child));\n\n // Add parents that aren't in available values (for display purposes)\n parents.forEach((parent) => {\n if (!availableValues.includes(parent)) {\n roots.add(parent);\n }\n });\n\n const buildTree = (value: string, level = 0): any => {\n const childrenOfValue = Object.entries(safeHierarchy).filter(([, parent]) => parent === value);\n return {\n value,\n level,\n children: childrenOfValue.map(([child]) => buildTree(child, level + 1))\n };\n };\n\n return Array.from(roots).map((root) => buildTree(root));\n };\n\n const renderTree = (nodes: any[]): React.ReactNode => {\n return nodes.map((node) => {\n const parentValue = safeHierarchy[node.value];\n\n return (\n <div key={node.value} className=\"ml-4\">\n <div className=\"flex items-center space-x-2 py-1\">\n <span className=\"text-sm text-gray-700\" style={{ marginLeft: `${node.level * 20}px` }}>\n {node.level > 0 && '└─ '}\n {node.value}\n </span>\n {parentValue && <span className=\"text-xs text-gray-500\">→ {parentValue}</span>}\n </div>\n {node.children.length > 0 && renderTree(node.children)}\n </div>\n );\n });\n };\n\n return (\n <div className={className}>\n <label className=\"block text-sm font-medium text-gray-700 mb-2\">Value Hierarchy</label>\n <div className=\"border border-gray-300 rounded-md p-3 bg-white\">\n {/* Add new relationship form */}\n <div className=\"mb-4 p-3 bg-gray-50 rounded border\">\n <div className=\"text-sm font-medium text-gray-700 mb-2\">Add Parent-Child Relationship</div>\n <div className=\"grid grid-cols-3 gap-2 items-end\">\n <div>\n <label className=\"block text-xs text-gray-600\">Child Value</label>\n {availableValues.length > 0 ? (\n <select\n value={newChild}\n onChange={(e) => setNewChild(e.target.value)}\n className=\"w-full text-sm rounded border-gray-300 focus:border-blue-500 focus:ring-blue-500\"\n >\n <option value=\"\">Select child...</option>\n {availableValues.map((value) => (\n <option key={value} value={value}>\n {value}\n </option>\n ))}\n </select>\n ) : (\n <input\n type=\"text\"\n value={newChild}\n onChange={(e) => setNewChild(e.target.value)}\n placeholder=\"Enter child value\"\n className=\"w-full text-sm rounded border-gray-300 focus:border-blue-500 focus:ring-blue-500\"\n />\n )}\n </div>\n <div>\n <label className=\"block text-xs text-gray-600\">Parent Value</label>\n <input\n type=\"text\"\n value={newParent}\n onChange={(e) => setNewParent(e.target.value)}\n placeholder=\"Enter parent value\"\n className=\"w-full text-sm rounded border-gray-300 focus:border-blue-500 focus:ring-blue-500\"\n />\n </div>\n <div>\n <button\n onClick={handleAddRelationship}\n disabled={!newChild || !newParent || newChild === newParent}\n className=\"w-full px-3 py-1 text-sm bg-blue-600 text-white rounded hover:bg-blue-700 disabled:bg-gray-300 disabled:cursor-not-allowed\"\n >\n Add\n </button>\n </div>\n </div>\n <div className=\"text-xs text-gray-500 mt-1\">\n {availableValues.length > 0\n ? \"Define which values are children of other values. The parent doesn't need to be in the enumerated values list.\"\n : 'Define which values are children of other values. Enter any valid values for this qualifier type.'}\n </div>\n </div>\n\n {/* Current relationships */}\n {Object.keys(safeHierarchy).length > 0 && (\n <div className=\"mb-4\">\n <div className=\"text-sm font-medium text-gray-700 mb-2\">\n Current Relationships ({Object.keys(safeHierarchy).length})\n </div>\n <div className=\"max-h-24 overflow-y-auto border border-gray-200 rounded bg-white p-2\">\n <div className=\"space-y-1\">\n {Object.entries(safeHierarchy).map(([child, parent]) => (\n <div key={child} className=\"flex items-center justify-between bg-gray-50 px-2 py-1 rounded\">\n <span className=\"text-sm\">\n <span className=\"font-medium\">{child}</span> →{' '}\n <span className=\"text-gray-600\">{parent}</span>\n </span>\n <button\n onClick={() => handleRemoveRelationship(child)}\n className=\"text-red-600 hover:text-red-800 text-xs ml-2 flex-shrink-0\"\n >\n Remove\n </button>\n </div>\n ))}\n </div>\n </div>\n </div>\n )}\n\n {/* Hierarchy visualization */}\n {(availableValues.length > 0 || Object.keys(safeHierarchy).length > 0) && (\n <div>\n <div className=\"text-sm font-medium text-gray-700 mb-2\">Hierarchy Tree</div>\n <div className=\"bg-gray-50 border rounded max-h-32 overflow-y-auto\">\n <div className=\"p-2 text-sm font-mono\">\n {getHierarchyTree().length > 0 ? (\n renderTree(getHierarchyTree())\n ) : (\n <div className=\"text-gray-500 text-center py-2\">\n No hierarchy defined. Add relationships above to see the tree structure.\n </div>\n )}\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default HierarchyEditor;\n"]}
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { Qualifiers, QualifierTypes } from '@fgv/ts-res';
3
+ export interface QualifierEditFormProps {
4
+ qualifier?: Qualifiers.IQualifierDecl;
5
+ qualifierTypes: QualifierTypes.Config.ISystemQualifierTypeConfig[];
6
+ onSave: (qualifier: Qualifiers.IQualifierDecl) => void;
7
+ onCancel: () => void;
8
+ existingNames?: string[];
9
+ }
10
+ export declare const QualifierEditForm: React.FC<QualifierEditFormProps>;
11
+ //# sourceMappingURL=QualifierEditForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QualifierEditForm.d.ts","sourceRoot":"","sources":["../../../src/components/forms/QualifierEditForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AAErD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEzD,MAAM,WAAW,sBAAsB;IACrC,SAAS,CAAC,EAAE,UAAU,CAAC,cAAc,CAAC;IACtC,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC,0BAA0B,EAAE,CAAC;IACnE,MAAM,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC,cAAc,KAAK,IAAI,CAAC;IACvD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAWD,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CA6U9D,CAAC"}
@@ -0,0 +1,181 @@
1
+ import React, { useState, useCallback } from 'react';
2
+ import { XMarkIcon, InformationCircleIcon } from '@heroicons/react/24/outline';
3
+ export const QualifierEditForm = ({ qualifier, qualifierTypes, onSave, onCancel, existingNames = [] }) => {
4
+ const [formData, setFormData] = useState(() => {
5
+ if (qualifier) {
6
+ return {
7
+ name: qualifier.name,
8
+ typeName: qualifier.typeName,
9
+ defaultPriority: qualifier.defaultPriority,
10
+ token: qualifier.token || '',
11
+ tokenIsOptional: qualifier.tokenIsOptional || false,
12
+ defaultValue: qualifier.defaultValue || ''
13
+ };
14
+ }
15
+ return {
16
+ name: '',
17
+ typeName: qualifierTypes[0]?.name || '',
18
+ defaultPriority: 50,
19
+ token: '',
20
+ tokenIsOptional: false,
21
+ defaultValue: ''
22
+ };
23
+ });
24
+ const [errors, setErrors] = useState({});
25
+ // Get the selected qualifier type for context
26
+ const selectedQualifierType = qualifierTypes.find((qt) => qt.name === formData.typeName);
27
+ const allowsContextList = selectedQualifierType?.configuration && selectedQualifierType.configuration.allowContextList;
28
+ // Validation
29
+ const validateForm = useCallback(() => {
30
+ const newErrors = {};
31
+ if (!formData.name.trim()) {
32
+ newErrors.name = 'Name is required';
33
+ }
34
+ else if (existingNames.includes(formData.name) && formData.name !== qualifier?.name) {
35
+ newErrors.name = 'Name must be unique';
36
+ }
37
+ if (!formData.typeName) {
38
+ newErrors.typeName = 'Qualifier type is required';
39
+ }
40
+ if (formData.defaultPriority < 0 || formData.defaultPriority > 1000) {
41
+ newErrors.defaultPriority = 'Priority must be between 0 and 1000';
42
+ }
43
+ if (formData.token && !/^[a-zA-Z][a-zA-Z0-9_]*$/.test(formData.token)) {
44
+ newErrors.token = 'Token must start with a letter and contain only letters, numbers, and underscores';
45
+ }
46
+ setErrors(newErrors);
47
+ return Object.keys(newErrors).length === 0;
48
+ }, [formData, existingNames, qualifier?.name]);
49
+ const handleSave = useCallback(() => {
50
+ if (!validateForm())
51
+ return;
52
+ const result = {
53
+ name: formData.name,
54
+ typeName: formData.typeName,
55
+ defaultPriority: formData.defaultPriority,
56
+ ...(formData.token && { token: formData.token }),
57
+ ...(formData.token && formData.tokenIsOptional && { tokenIsOptional: true }),
58
+ ...(formData.defaultValue && { defaultValue: formData.defaultValue })
59
+ };
60
+ onSave(result);
61
+ }, [formData, validateForm, onSave]);
62
+ const updateField = useCallback((field, value) => {
63
+ setFormData((prev) => {
64
+ const updated = { ...prev, [field]: value };
65
+ // Auto-generate token from name if no custom token is set
66
+ if (field === 'name' && !prev.token) {
67
+ updated.token = value.toLowerCase().replace(/[^a-zA-Z0-9]/g, '');
68
+ }
69
+ // Clear tokenIsOptional if token is cleared
70
+ if (field === 'token' && !value) {
71
+ updated.tokenIsOptional = false;
72
+ }
73
+ return updated;
74
+ });
75
+ if (errors[field]) {
76
+ setErrors((prev) => ({ ...prev, [field]: '' }));
77
+ }
78
+ }, [errors]);
79
+ const getDefaultValuePlaceholder = () => {
80
+ if (!selectedQualifierType)
81
+ return 'Enter default value';
82
+ switch (selectedQualifierType.systemType) {
83
+ case 'language':
84
+ return allowsContextList ? 'e.g., en-US or en-US,en' : 'e.g., en-US';
85
+ case 'territory':
86
+ return allowsContextList ? 'e.g., US or US,CA' : 'e.g., US';
87
+ case 'literal':
88
+ const enumValues = selectedQualifierType.configuration?.enumeratedValues;
89
+ if (enumValues && enumValues.length > 0) {
90
+ return allowsContextList
91
+ ? `e.g., ${enumValues[0]} or ${enumValues.slice(0, 2).join(',')}`
92
+ : `e.g., ${enumValues[0]}`;
93
+ }
94
+ return allowsContextList ? 'e.g., value or value1,value2' : 'e.g., value';
95
+ default:
96
+ return 'Enter default value';
97
+ }
98
+ };
99
+ return (React.createElement("div", { className: "fixed inset-0 bg-gray-600 bg-opacity-50 flex items-center justify-center z-50 p-4" },
100
+ React.createElement("div", { className: "bg-white rounded-lg shadow-xl max-w-2xl w-full h-full max-h-[calc(100vh-2rem)] flex flex-col" },
101
+ React.createElement("div", { className: "flex items-center justify-between p-6 border-b flex-shrink-0" },
102
+ React.createElement("h3", { className: "text-lg font-medium text-gray-900" }, qualifier ? 'Edit Qualifier' : 'Add Qualifier'),
103
+ React.createElement("button", { onClick: onCancel, className: "text-gray-400 hover:text-gray-600" },
104
+ React.createElement(XMarkIcon, { className: "w-6 h-6" }))),
105
+ React.createElement("div", { className: "p-6 space-y-6 overflow-y-auto flex-1 min-h-0" },
106
+ React.createElement("div", { className: "grid grid-cols-2 gap-4" },
107
+ React.createElement("div", null,
108
+ React.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "Name *"),
109
+ React.createElement("input", { type: "text", value: formData.name, onChange: (e) => updateField('name', e.target.value), className: `w-full px-3 py-2 border rounded-md shadow-sm focus:outline-none focus:ring-1 focus:ring-blue-500 ${errors.name ? 'border-red-300' : 'border-gray-300'}`, placeholder: "Enter qualifier name" }),
110
+ errors.name && React.createElement("p", { className: "mt-1 text-sm text-red-600" }, errors.name)),
111
+ React.createElement("div", null,
112
+ React.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "Qualifier Type *"),
113
+ React.createElement("select", { value: formData.typeName, onChange: (e) => updateField('typeName', e.target.value), className: `w-full px-3 py-2 border rounded-md shadow-sm focus:outline-none focus:ring-1 focus:ring-blue-500 ${errors.typeName ? 'border-red-300' : 'border-gray-300'}` }, qualifierTypes.length === 0 ? (React.createElement("option", { value: "" }, "No qualifier types available")) : (qualifierTypes.map((type) => (React.createElement("option", { key: type.name, value: type.name },
114
+ type.name,
115
+ " (",
116
+ type.systemType,
117
+ ")"))))),
118
+ errors.typeName && React.createElement("p", { className: "mt-1 text-sm text-red-600" }, errors.typeName))),
119
+ React.createElement("div", { className: "grid grid-cols-2 gap-4" },
120
+ React.createElement("div", null,
121
+ React.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" }, "Default Priority *"),
122
+ React.createElement("input", { type: "number", min: "0", max: "1000", value: formData.defaultPriority, onChange: (e) => updateField('defaultPriority', parseInt(e.target.value) || 0), className: `w-full px-3 py-2 border rounded-md shadow-sm focus:outline-none focus:ring-1 focus:ring-blue-500 ${errors.defaultPriority ? 'border-red-300' : 'border-gray-300'}`, placeholder: "50" }),
123
+ errors.defaultPriority && (React.createElement("p", { className: "mt-1 text-sm text-red-600" }, errors.defaultPriority)),
124
+ React.createElement("p", { className: "mt-1 text-xs text-gray-500" }, "Higher numbers have higher priority (0-1000)")),
125
+ React.createElement("div", null,
126
+ React.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" },
127
+ "Token",
128
+ React.createElement("span", { className: "ml-1 text-gray-500" }, "(optional)")),
129
+ React.createElement("input", { type: "text", value: formData.token, onChange: (e) => updateField('token', e.target.value), className: `w-full px-3 py-2 border rounded-md shadow-sm focus:outline-none focus:ring-1 focus:ring-blue-500 ${errors.token ? 'border-red-300' : 'border-gray-300'}`, placeholder: "e.g., lang, locale" }),
130
+ errors.token && React.createElement("p", { className: "mt-1 text-sm text-red-600" }, errors.token),
131
+ React.createElement("p", { className: "mt-1 text-xs text-gray-500" }, "Used to identify this qualifier in resource names"))),
132
+ formData.token && (React.createElement("div", { className: "flex items-center" },
133
+ React.createElement("input", { type: "checkbox", id: "tokenIsOptional", checked: formData.tokenIsOptional, onChange: (e) => updateField('tokenIsOptional', e.target.checked), className: "h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" }),
134
+ React.createElement("label", { htmlFor: "tokenIsOptional", className: "ml-2 text-sm text-gray-700" }, "Token is optional in resource names"),
135
+ React.createElement("div", { className: "ml-2 group relative" },
136
+ React.createElement(InformationCircleIcon, { className: "w-4 h-4 text-gray-400" }),
137
+ React.createElement("div", { className: "absolute left-0 bottom-6 hidden group-hover:block bg-gray-800 text-white text-xs rounded py-1 px-2 whitespace-nowrap z-10" }, "Allow resources without this qualifier token")))),
138
+ React.createElement("div", null,
139
+ React.createElement("label", { className: "block text-sm font-medium text-gray-700 mb-1" },
140
+ "Default Value",
141
+ React.createElement("span", { className: "ml-1 text-gray-500" }, "(optional)")),
142
+ React.createElement("input", { type: "text", value: formData.defaultValue, onChange: (e) => updateField('defaultValue', e.target.value), className: "w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:ring-blue-500", placeholder: getDefaultValuePlaceholder() }),
143
+ React.createElement("div", { className: "mt-1 text-xs text-gray-500" }, selectedQualifierType && (React.createElement("div", null,
144
+ React.createElement("p", null,
145
+ "Qualifier type: ",
146
+ React.createElement("span", { className: "font-medium" }, selectedQualifierType.systemType)),
147
+ allowsContextList && (React.createElement("p", { className: "text-blue-600" }, "This qualifier type supports multiple values (comma-separated)")))))),
148
+ selectedQualifierType && (React.createElement("div", { className: "p-4 bg-gray-50 rounded-lg" },
149
+ React.createElement("h4", { className: "font-medium text-gray-900 mb-2" }, "Qualifier Type Information"),
150
+ React.createElement("div", { className: "text-sm text-gray-600 space-y-1" },
151
+ React.createElement("p", null,
152
+ React.createElement("span", { className: "font-medium" }, "System Type:"),
153
+ " ",
154
+ selectedQualifierType.systemType),
155
+ React.createElement("p", null,
156
+ React.createElement("span", { className: "font-medium" }, "Supports Context List:"),
157
+ ' ',
158
+ allowsContextList ? 'Yes' : 'No'),
159
+ selectedQualifierType.systemType === 'literal' && selectedQualifierType.configuration && (React.createElement(React.Fragment, null,
160
+ selectedQualifierType.configuration.caseSensitive !== undefined && (React.createElement("p", null,
161
+ React.createElement("span", { className: "font-medium" }, "Case Sensitive:"),
162
+ ' ',
163
+ selectedQualifierType.configuration.caseSensitive ? 'Yes' : 'No')),
164
+ selectedQualifierType.configuration.enumeratedValues && (React.createElement("p", null,
165
+ React.createElement("span", { className: "font-medium" }, "Allowed Values:"),
166
+ ' ',
167
+ selectedQualifierType.configuration.enumeratedValues.join(', '))))),
168
+ selectedQualifierType.systemType === 'territory' && selectedQualifierType.configuration && (React.createElement(React.Fragment, null,
169
+ selectedQualifierType.configuration.acceptLowercase !== undefined && (React.createElement("p", null,
170
+ React.createElement("span", { className: "font-medium" }, "Accept Lowercase:"),
171
+ ' ',
172
+ selectedQualifierType.configuration.acceptLowercase ? 'Yes' : 'No')),
173
+ selectedQualifierType.configuration.allowedTerritories && (React.createElement("p", null,
174
+ React.createElement("span", { className: "font-medium" }, "Allowed Territories:"),
175
+ ' ',
176
+ selectedQualifierType.configuration.allowedTerritories.join(', '))))))))),
177
+ React.createElement("div", { className: "flex justify-end space-x-3 px-6 py-4 border-t bg-gray-50 flex-shrink-0" },
178
+ React.createElement("button", { onClick: onCancel, className: "px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500" }, "Cancel"),
179
+ React.createElement("button", { onClick: handleSave, className: "px-4 py-2 text-sm font-medium text-white bg-blue-600 border border-transparent rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500" }, qualifier ? 'Save Changes' : 'Add Qualifier')))));
180
+ };
181
+ //# sourceMappingURL=QualifierEditForm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QualifierEditForm.js","sourceRoot":"","sources":["../../../src/components/forms/QualifierEditForm.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useState, useCallback } from 'react';\nimport { XMarkIcon, InformationCircleIcon } from '@heroicons/react/24/outline';\nimport { Qualifiers, QualifierTypes } from '@fgv/ts-res';\n\nexport interface QualifierEditFormProps {\n qualifier?: Qualifiers.IQualifierDecl;\n qualifierTypes: QualifierTypes.Config.ISystemQualifierTypeConfig[];\n onSave: (qualifier: Qualifiers.IQualifierDecl) => void;\n onCancel: () => void;\n existingNames?: string[];\n}\n\ninterface FormData {\n name: string;\n typeName: string;\n defaultPriority: number;\n token: string;\n tokenIsOptional: boolean;\n defaultValue: string;\n}\n\nexport const QualifierEditForm: React.FC<QualifierEditFormProps> = ({\n qualifier,\n qualifierTypes,\n onSave,\n onCancel,\n existingNames = []\n}) => {\n const [formData, setFormData] = useState<FormData>(() => {\n if (qualifier) {\n return {\n name: qualifier.name,\n typeName: qualifier.typeName,\n defaultPriority: qualifier.defaultPriority,\n token: qualifier.token || '',\n tokenIsOptional: qualifier.tokenIsOptional || false,\n defaultValue: qualifier.defaultValue || ''\n };\n }\n return {\n name: '',\n typeName: qualifierTypes[0]?.name || '',\n defaultPriority: 50,\n token: '',\n tokenIsOptional: false,\n defaultValue: ''\n };\n });\n\n const [errors, setErrors] = useState<Record<string, string>>({});\n\n // Get the selected qualifier type for context\n const selectedQualifierType = qualifierTypes.find((qt) => qt.name === formData.typeName);\n const allowsContextList =\n selectedQualifierType?.configuration && (selectedQualifierType.configuration as any).allowContextList;\n\n // Validation\n const validateForm = useCallback((): boolean => {\n const newErrors: Record<string, string> = {};\n\n if (!formData.name.trim()) {\n newErrors.name = 'Name is required';\n } else if (existingNames.includes(formData.name) && formData.name !== qualifier?.name) {\n newErrors.name = 'Name must be unique';\n }\n\n if (!formData.typeName) {\n newErrors.typeName = 'Qualifier type is required';\n }\n\n if (formData.defaultPriority < 0 || formData.defaultPriority > 1000) {\n newErrors.defaultPriority = 'Priority must be between 0 and 1000';\n }\n\n if (formData.token && !/^[a-zA-Z][a-zA-Z0-9_]*$/.test(formData.token)) {\n newErrors.token = 'Token must start with a letter and contain only letters, numbers, and underscores';\n }\n\n setErrors(newErrors);\n return Object.keys(newErrors).length === 0;\n }, [formData, existingNames, qualifier?.name]);\n\n const handleSave = useCallback(() => {\n if (!validateForm()) return;\n\n const result: Qualifiers.IQualifierDecl = {\n name: formData.name,\n typeName: formData.typeName,\n defaultPriority: formData.defaultPriority,\n ...(formData.token && { token: formData.token }),\n ...(formData.token && formData.tokenIsOptional && { tokenIsOptional: true }),\n ...(formData.defaultValue && { defaultValue: formData.defaultValue })\n };\n\n onSave(result);\n }, [formData, validateForm, onSave]);\n\n const updateField = useCallback(\n (field: keyof FormData, value: any) => {\n setFormData((prev) => {\n const updated = { ...prev, [field]: value };\n\n // Auto-generate token from name if no custom token is set\n if (field === 'name' && !prev.token) {\n updated.token = value.toLowerCase().replace(/[^a-zA-Z0-9]/g, '');\n }\n\n // Clear tokenIsOptional if token is cleared\n if (field === 'token' && !value) {\n updated.tokenIsOptional = false;\n }\n\n return updated;\n });\n\n if (errors[field]) {\n setErrors((prev) => ({ ...prev, [field]: '' }));\n }\n },\n [errors]\n );\n\n const getDefaultValuePlaceholder = (): string => {\n if (!selectedQualifierType) return 'Enter default value';\n\n switch (selectedQualifierType.systemType) {\n case 'language':\n return allowsContextList ? 'e.g., en-US or en-US,en' : 'e.g., en-US';\n case 'territory':\n return allowsContextList ? 'e.g., US or US,CA' : 'e.g., US';\n case 'literal':\n const enumValues = (selectedQualifierType.configuration as any)?.enumeratedValues;\n if (enumValues && enumValues.length > 0) {\n return allowsContextList\n ? `e.g., ${enumValues[0]} or ${enumValues.slice(0, 2).join(',')}`\n : `e.g., ${enumValues[0]}`;\n }\n return allowsContextList ? 'e.g., value or value1,value2' : 'e.g., value';\n default:\n return 'Enter default value';\n }\n };\n\n return (\n <div className=\"fixed inset-0 bg-gray-600 bg-opacity-50 flex items-center justify-center z-50 p-4\">\n <div className=\"bg-white rounded-lg shadow-xl max-w-2xl w-full h-full max-h-[calc(100vh-2rem)] flex flex-col\">\n {/* Fixed Header */}\n <div className=\"flex items-center justify-between p-6 border-b flex-shrink-0\">\n <h3 className=\"text-lg font-medium text-gray-900\">\n {qualifier ? 'Edit Qualifier' : 'Add Qualifier'}\n </h3>\n <button onClick={onCancel} className=\"text-gray-400 hover:text-gray-600\">\n <XMarkIcon className=\"w-6 h-6\" />\n </button>\n </div>\n\n {/* Scrollable Content */}\n <div className=\"p-6 space-y-6 overflow-y-auto flex-1 min-h-0\">\n {/* Basic Properties */}\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">Name *</label>\n <input\n type=\"text\"\n value={formData.name}\n onChange={(e) => updateField('name', e.target.value)}\n className={`w-full px-3 py-2 border rounded-md shadow-sm focus:outline-none focus:ring-1 focus:ring-blue-500 ${\n errors.name ? 'border-red-300' : 'border-gray-300'\n }`}\n placeholder=\"Enter qualifier name\"\n />\n {errors.name && <p className=\"mt-1 text-sm text-red-600\">{errors.name}</p>}\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">Qualifier Type *</label>\n <select\n value={formData.typeName}\n onChange={(e) => updateField('typeName', e.target.value)}\n className={`w-full px-3 py-2 border rounded-md shadow-sm focus:outline-none focus:ring-1 focus:ring-blue-500 ${\n errors.typeName ? 'border-red-300' : 'border-gray-300'\n }`}\n >\n {qualifierTypes.length === 0 ? (\n <option value=\"\">No qualifier types available</option>\n ) : (\n qualifierTypes.map((type) => (\n <option key={type.name} value={type.name}>\n {type.name} ({type.systemType})\n </option>\n ))\n )}\n </select>\n {errors.typeName && <p className=\"mt-1 text-sm text-red-600\">{errors.typeName}</p>}\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">Default Priority *</label>\n <input\n type=\"number\"\n min=\"0\"\n max=\"1000\"\n value={formData.defaultPriority}\n onChange={(e) => updateField('defaultPriority', parseInt(e.target.value) || 0)}\n className={`w-full px-3 py-2 border rounded-md shadow-sm focus:outline-none focus:ring-1 focus:ring-blue-500 ${\n errors.defaultPriority ? 'border-red-300' : 'border-gray-300'\n }`}\n placeholder=\"50\"\n />\n {errors.defaultPriority && (\n <p className=\"mt-1 text-sm text-red-600\">{errors.defaultPriority}</p>\n )}\n <p className=\"mt-1 text-xs text-gray-500\">Higher numbers have higher priority (0-1000)</p>\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n Token\n <span className=\"ml-1 text-gray-500\">(optional)</span>\n </label>\n <input\n type=\"text\"\n value={formData.token}\n onChange={(e) => updateField('token', e.target.value)}\n className={`w-full px-3 py-2 border rounded-md shadow-sm focus:outline-none focus:ring-1 focus:ring-blue-500 ${\n errors.token ? 'border-red-300' : 'border-gray-300'\n }`}\n placeholder=\"e.g., lang, locale\"\n />\n {errors.token && <p className=\"mt-1 text-sm text-red-600\">{errors.token}</p>}\n <p className=\"mt-1 text-xs text-gray-500\">Used to identify this qualifier in resource names</p>\n </div>\n </div>\n\n {/* Token Options */}\n {formData.token && (\n <div className=\"flex items-center\">\n <input\n type=\"checkbox\"\n id=\"tokenIsOptional\"\n checked={formData.tokenIsOptional}\n onChange={(e) => updateField('tokenIsOptional', e.target.checked)}\n className=\"h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded\"\n />\n <label htmlFor=\"tokenIsOptional\" className=\"ml-2 text-sm text-gray-700\">\n Token is optional in resource names\n </label>\n <div className=\"ml-2 group relative\">\n <InformationCircleIcon className=\"w-4 h-4 text-gray-400\" />\n <div className=\"absolute left-0 bottom-6 hidden group-hover:block bg-gray-800 text-white text-xs rounded py-1 px-2 whitespace-nowrap z-10\">\n Allow resources without this qualifier token\n </div>\n </div>\n </div>\n )}\n\n {/* Default Value */}\n <div>\n <label className=\"block text-sm font-medium text-gray-700 mb-1\">\n Default Value\n <span className=\"ml-1 text-gray-500\">(optional)</span>\n </label>\n <input\n type=\"text\"\n value={formData.defaultValue}\n onChange={(e) => updateField('defaultValue', e.target.value)}\n className=\"w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-1 focus:ring-blue-500\"\n placeholder={getDefaultValuePlaceholder()}\n />\n <div className=\"mt-1 text-xs text-gray-500\">\n {selectedQualifierType && (\n <div>\n <p>\n Qualifier type: <span className=\"font-medium\">{selectedQualifierType.systemType}</span>\n </p>\n {allowsContextList && (\n <p className=\"text-blue-600\">\n This qualifier type supports multiple values (comma-separated)\n </p>\n )}\n </div>\n )}\n </div>\n </div>\n\n {/* Qualifier Type Information */}\n {selectedQualifierType && (\n <div className=\"p-4 bg-gray-50 rounded-lg\">\n <h4 className=\"font-medium text-gray-900 mb-2\">Qualifier Type Information</h4>\n <div className=\"text-sm text-gray-600 space-y-1\">\n <p>\n <span className=\"font-medium\">System Type:</span> {selectedQualifierType.systemType}\n </p>\n <p>\n <span className=\"font-medium\">Supports Context List:</span>{' '}\n {allowsContextList ? 'Yes' : 'No'}\n </p>\n {selectedQualifierType.systemType === 'literal' && selectedQualifierType.configuration && (\n <>\n {(selectedQualifierType.configuration as any).caseSensitive !== undefined && (\n <p>\n <span className=\"font-medium\">Case Sensitive:</span>{' '}\n {(selectedQualifierType.configuration as any).caseSensitive ? 'Yes' : 'No'}\n </p>\n )}\n {(selectedQualifierType.configuration as any).enumeratedValues && (\n <p>\n <span className=\"font-medium\">Allowed Values:</span>{' '}\n {(selectedQualifierType.configuration as any).enumeratedValues.join(', ')}\n </p>\n )}\n </>\n )}\n {selectedQualifierType.systemType === 'territory' && selectedQualifierType.configuration && (\n <>\n {(selectedQualifierType.configuration as any).acceptLowercase !== undefined && (\n <p>\n <span className=\"font-medium\">Accept Lowercase:</span>{' '}\n {(selectedQualifierType.configuration as any).acceptLowercase ? 'Yes' : 'No'}\n </p>\n )}\n {(selectedQualifierType.configuration as any).allowedTerritories && (\n <p>\n <span className=\"font-medium\">Allowed Territories:</span>{' '}\n {(selectedQualifierType.configuration as any).allowedTerritories.join(', ')}\n </p>\n )}\n </>\n )}\n </div>\n </div>\n )}\n </div>\n\n {/* Fixed Footer */}\n <div className=\"flex justify-end space-x-3 px-6 py-4 border-t bg-gray-50 flex-shrink-0\">\n <button\n onClick={onCancel}\n className=\"px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500\"\n >\n Cancel\n </button>\n <button\n onClick={handleSave}\n className=\"px-4 py-2 text-sm font-medium text-white bg-blue-600 border border-transparent rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500\"\n >\n {qualifier ? 'Save Changes' : 'Add Qualifier'}\n </button>\n </div>\n </div>\n </div>\n );\n};\n"]}
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { QualifierTypes } from '@fgv/ts-res';
3
+ export interface QualifierTypeEditFormProps {
4
+ qualifierType?: QualifierTypes.Config.ISystemQualifierTypeConfig;
5
+ onSave: (qualifierType: QualifierTypes.Config.ISystemQualifierTypeConfig) => void;
6
+ onCancel: () => void;
7
+ existingNames?: string[];
8
+ }
9
+ export declare const QualifierTypeEditForm: React.FC<QualifierTypeEditFormProps>;
10
+ //# sourceMappingURL=QualifierTypeEditForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QualifierTypeEditForm.d.ts","sourceRoot":"","sources":["../../../src/components/forms/QualifierTypeEditForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAEhE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,MAAM,WAAW,0BAA0B;IACzC,aAAa,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,0BAA0B,CAAC;IACjE,MAAM,EAAE,CAAC,aAAa,EAAE,cAAc,CAAC,MAAM,CAAC,0BAA0B,KAAK,IAAI,CAAC;IAClF,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAgBD,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,0BAA0B,CAgUtE,CAAC"}