@fgv/ts-res-browser 1.0.0

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 (95) hide show
  1. package/.rush/temp/5fc90bc7c2ccf812114ea099111568e5429be2a2.tar.log +15 -0
  2. package/.rush/temp/chunked-rush-logs/ts-res-browser.build.chunks.jsonl +35 -0
  3. package/.rush/temp/operation/build/all.log +35 -0
  4. package/.rush/temp/operation/build/log-chunks.jsonl +35 -0
  5. package/.rush/temp/operation/build/state.json +3 -0
  6. package/.rush/temp/shrinkwrap-deps.json +1217 -0
  7. package/README.md +95 -0
  8. package/TS_RES_BROWSER_PLAN.md +689 -0
  9. package/babel.config.js +17 -0
  10. package/config/jest.config.json +13 -0
  11. package/config/rig.json +16 -0
  12. package/dist/bundle.js +2 -0
  13. package/dist/bundle.js.LICENSE.txt +62 -0
  14. package/dist/index.html +1 -0
  15. package/package.json +78 -0
  16. package/postcss.config.js +3 -0
  17. package/public/index.html +15 -0
  18. package/rush-logs/ts-res-browser.build.cache.log +3 -0
  19. package/rush-logs/ts-res-browser.build.log +35 -0
  20. package/src/App.tsx +153 -0
  21. package/src/cli.ts +44 -0
  22. package/src/components/common/FileImporter.tsx +138 -0
  23. package/src/components/common/NavigationWarningModal.tsx +62 -0
  24. package/src/components/layout/AppLayout.tsx +46 -0
  25. package/src/components/layout/Header.tsx +22 -0
  26. package/src/components/layout/MessagesWindow.tsx +108 -0
  27. package/src/components/layout/Sidebar.tsx +92 -0
  28. package/src/components/tools/CompiledBrowser.tsx +949 -0
  29. package/src/components/tools/ConfigurationTool.tsx +1402 -0
  30. package/src/components/tools/FilterTool.tsx +1027 -0
  31. package/src/components/tools/ImportTool.tsx +246 -0
  32. package/src/components/tools/ResolutionViewer.tsx +1672 -0
  33. package/src/components/tools/SourceBrowser.tsx +496 -0
  34. package/src/hooks/useAppState.ts +107 -0
  35. package/src/hooks/useFileImport.ts +86 -0
  36. package/src/hooks/useNavigationWarning.ts +67 -0
  37. package/src/hooks/useResourceManager.ts +244 -0
  38. package/src/index.css +38 -0
  39. package/src/main.tsx +16 -0
  40. package/src/types/app.ts +62 -0
  41. package/src/types/fileSystemAccess.d.ts +94 -0
  42. package/src/utils/browserFileTreeAccessors.ts +245 -0
  43. package/src/utils/fileImport.ts +334 -0
  44. package/src/utils/filterResources.ts +677 -0
  45. package/src/utils/tsResIntegration.ts +467 -0
  46. package/tailwind.config.js +21 -0
  47. package/test-data/README.md +184 -0
  48. package/test-data/config-variations/README.md +64 -0
  49. package/test-data/config-variations/composition-terminology.json +112 -0
  50. package/test-data/config-variations/enterprise-complex.json +129 -0
  51. package/test-data/config-variations/gaming-app.json +87 -0
  52. package/test-data/config-variations/high-priority-language.json +65 -0
  53. package/test-data/config-variations/minimal-basic.json +37 -0
  54. package/test-data/config-variations/qualifier-default-values.json +71 -0
  55. package/test-data/config-variations/territory-first.json +68 -0
  56. package/test-data/config-variations/territory-hierarchy-test.json +31 -0
  57. package/test-data/config-variations/territory-hierarchy-unconstrained.json +32 -0
  58. package/test-data/default-matching-test/greeting.res.json +83 -0
  59. package/test-data/default-matching-test/only-defaults.res.json +48 -0
  60. package/test-data/sample-project/package.json +27 -0
  61. package/test-data/sample-project/src/resources/app-config.json +27 -0
  62. package/test-data/sample-project/src/resources/app.json +177 -0
  63. package/test-data/sample-project/src/resources/config/app.env=development.json +21 -0
  64. package/test-data/sample-project/src/resources/config/app.json +21 -0
  65. package/test-data/sample-project/src/resources/config/app.platform=mobile.json +23 -0
  66. package/test-data/sample-project/src/resources/feature-flags.json +23 -0
  67. package/test-data/sample-project/src/resources/home=CA/common.json +16 -0
  68. package/test-data/sample-project/src/resources/images/density=hdpi.json +29 -0
  69. package/test-data/sample-project/src/resources/images/home.json +29 -0
  70. package/test-data/sample-project/src/resources/images/logout.json +14 -0
  71. package/test-data/sample-project/src/resources/images/settings.json +14 -0
  72. package/test-data/sample-project/src/resources/images/ui-icons.json +29 -0
  73. package/test-data/sample-project/src/resources/images/user.density=hdpi.json +14 -0
  74. package/test-data/sample-project/src/resources/images/user.json +14 -0
  75. package/test-data/sample-project/src/resources/lang=en-US/common.json +15 -0
  76. package/test-data/sample-project/src/resources/language=en-CA/ui-terms.json +19 -0
  77. package/test-data/sample-project/src/resources/language=en-GB/ui-terms.json +30 -0
  78. package/test-data/sample-project/src/resources/language=fr-CA/ui-terms.json +25 -0
  79. package/test-data/sample-project/src/resources/language=nl-BE/ui-terms.json +17 -0
  80. package/test-data/sample-project/src/resources/region=europe/feature-flags.json +17 -0
  81. package/test-data/sample-project/src/resources/region=north-america/feature-flags.json +18 -0
  82. package/test-data/sample-project/src/resources/strings/dashboard.home=CA,language=fr.json +20 -0
  83. package/test-data/sample-project/src/resources/strings/dashboard.json +18 -0
  84. package/test-data/sample-project/src/resources/strings/dashboard.role=admin.json +23 -0
  85. package/test-data/sample-project/src/resources/strings/dashboard.role=user.json +21 -0
  86. package/test-data/sample-project/src/resources/strings/language=en-US.json +16 -0
  87. package/test-data/sample-project/src/resources/strings.json +78 -0
  88. package/test-data/sample-project/src/resources/territory=BE/app-config.json +19 -0
  89. package/test-data/sample-project/src/resources/territory=CA/app-config.json +21 -0
  90. package/test-data/sample-project/src/resources/territory=GB/app-config.json +25 -0
  91. package/test-data/sample-project/src/resources/territory=NL/app-config.json +25 -0
  92. package/test-data/sample-project/src/resources/ui-terms.json +96 -0
  93. package/test-data/sample-project/src/resources-config.json +111 -0
  94. package/tsconfig.json +27 -0
  95. package/webpack.config.js +54 -0
@@ -0,0 +1,108 @@
1
+ import React, { useState } from 'react';
2
+ import {
3
+ XMarkIcon,
4
+ InformationCircleIcon,
5
+ ExclamationTriangleIcon,
6
+ XCircleIcon,
7
+ CheckCircleIcon,
8
+ ChevronUpIcon,
9
+ ChevronDownIcon
10
+ } from '@heroicons/react/24/outline';
11
+
12
+ interface Message {
13
+ id: string;
14
+ type: 'info' | 'warning' | 'error' | 'success';
15
+ message: string;
16
+ timestamp: Date;
17
+ }
18
+
19
+ interface MessagesWindowProps {
20
+ messages: Message[];
21
+ onClearMessages: () => void;
22
+ }
23
+
24
+ const MessagesWindow: React.FC<MessagesWindowProps> = ({ messages, onClearMessages }) => {
25
+ const [isCollapsed, setIsCollapsed] = useState(false);
26
+
27
+ if (messages.length === 0) {
28
+ return null;
29
+ }
30
+
31
+ const getMessageIcon = (type: Message['type']) => {
32
+ switch (type) {
33
+ case 'info':
34
+ return <InformationCircleIcon className="h-5 w-5 text-blue-500" />;
35
+ case 'warning':
36
+ return <ExclamationTriangleIcon className="h-5 w-5 text-yellow-500" />;
37
+ case 'error':
38
+ return <XCircleIcon className="h-5 w-5 text-red-500" />;
39
+ case 'success':
40
+ return <CheckCircleIcon className="h-5 w-5 text-green-500" />;
41
+ default:
42
+ return <InformationCircleIcon className="h-5 w-5 text-gray-500" />;
43
+ }
44
+ };
45
+
46
+ const getMessageBgColor = (type: Message['type']) => {
47
+ switch (type) {
48
+ case 'info':
49
+ return 'bg-blue-50 border-blue-200';
50
+ case 'warning':
51
+ return 'bg-yellow-50 border-yellow-200';
52
+ case 'error':
53
+ return 'bg-red-50 border-red-200';
54
+ case 'success':
55
+ return 'bg-green-50 border-green-200';
56
+ default:
57
+ return 'bg-gray-50 border-gray-200';
58
+ }
59
+ };
60
+
61
+ const formatTime = (date: Date) => {
62
+ return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });
63
+ };
64
+
65
+ return (
66
+ <div className="border-t border-gray-200 bg-white">
67
+ {/* Header */}
68
+ <div className="flex items-center justify-between px-4 py-2 bg-gray-50 border-b border-gray-200">
69
+ <div className="flex items-center space-x-2">
70
+ <button onClick={() => setIsCollapsed(!isCollapsed)} className="p-1 hover:bg-gray-200 rounded">
71
+ {isCollapsed ? (
72
+ <ChevronUpIcon className="h-4 w-4 text-gray-500" />
73
+ ) : (
74
+ <ChevronDownIcon className="h-4 w-4 text-gray-500" />
75
+ )}
76
+ </button>
77
+ <h3 className="text-sm font-medium text-gray-900">Messages ({messages.length})</h3>
78
+ </div>
79
+ <button
80
+ onClick={onClearMessages}
81
+ className="text-xs text-gray-500 hover:text-gray-700 px-2 py-1 rounded hover:bg-gray-200"
82
+ >
83
+ Clear All
84
+ </button>
85
+ </div>
86
+
87
+ {/* Messages */}
88
+ {!isCollapsed && (
89
+ <div className="max-h-48 overflow-y-auto">
90
+ {messages.map((message) => (
91
+ <div
92
+ key={message.id}
93
+ className={`flex items-start space-x-3 p-3 border-l-4 ${getMessageBgColor(message.type)}`}
94
+ >
95
+ {getMessageIcon(message.type)}
96
+ <div className="flex-1 min-w-0">
97
+ <p className="text-sm text-gray-900">{message.message}</p>
98
+ <p className="text-xs text-gray-500 mt-1">{formatTime(message.timestamp)}</p>
99
+ </div>
100
+ </div>
101
+ ))}
102
+ </div>
103
+ )}
104
+ </div>
105
+ );
106
+ };
107
+
108
+ export default MessagesWindow;
@@ -0,0 +1,92 @@
1
+ import React from 'react';
2
+ import {
3
+ DocumentArrowUpIcon,
4
+ DocumentTextIcon,
5
+ FunnelIcon,
6
+ CubeIcon,
7
+ MagnifyingGlassIcon,
8
+ CogIcon
9
+ } from '@heroicons/react/24/outline';
10
+ import { Tool } from '../../types/app';
11
+
12
+ interface SidebarProps {
13
+ selectedTool: Tool;
14
+ onToolSelect: (tool: Tool) => void;
15
+ }
16
+
17
+ const tools = [
18
+ {
19
+ id: 'import',
20
+ name: 'Import Resources',
21
+ icon: DocumentArrowUpIcon,
22
+ description: 'Import ts-res resource files and directories'
23
+ },
24
+ {
25
+ id: 'source',
26
+ name: 'Source Browser',
27
+ icon: DocumentTextIcon,
28
+ description: 'Browse built resources in alphabetical order'
29
+ },
30
+ {
31
+ id: 'filter',
32
+ name: 'Filter Tool',
33
+ icon: FunnelIcon,
34
+ description: 'Filter resources by context for focused analysis'
35
+ },
36
+ {
37
+ id: 'compiled',
38
+ name: 'Compiled Browser',
39
+ icon: CubeIcon,
40
+ description: 'Navigate compiled resources in tree view'
41
+ },
42
+ {
43
+ id: 'resolution',
44
+ name: 'Resolution Viewer',
45
+ icon: MagnifyingGlassIcon,
46
+ description: 'View resource resolution with qualifiers'
47
+ },
48
+ {
49
+ id: 'configuration',
50
+ name: 'Configuration',
51
+ icon: CogIcon,
52
+ description: 'Manage qualifier types, qualifiers, and resource types'
53
+ }
54
+ ];
55
+
56
+ const Sidebar: React.FC<SidebarProps> = ({ selectedTool, onToolSelect }) => {
57
+ return (
58
+ <aside className="w-64 bg-white shadow-sm border-r border-gray-200 h-screen overflow-y-auto">
59
+ <div className="p-4">
60
+ <h2 className="text-lg font-semibold text-gray-900 mb-4">Tools</h2>
61
+ <nav className="space-y-2">
62
+ {tools.map((tool) => {
63
+ const Icon = tool.icon;
64
+ const isSelected = selectedTool === tool.id;
65
+
66
+ return (
67
+ <button
68
+ key={tool.id}
69
+ onClick={() => onToolSelect(tool.id as Tool)}
70
+ className={`w-full text-left p-3 rounded-lg transition-colors ${
71
+ isSelected
72
+ ? 'bg-blue-50 text-blue-700 border border-blue-200'
73
+ : 'hover:bg-gray-50 text-gray-700 border border-transparent'
74
+ }`}
75
+ >
76
+ <div className="flex items-center space-x-3">
77
+ <Icon className="h-5 w-5 flex-shrink-0" />
78
+ <div className="min-w-0 flex-1">
79
+ <div className="font-medium text-sm">{tool.name}</div>
80
+ <div className="text-xs text-gray-500 mt-1">{tool.description}</div>
81
+ </div>
82
+ </div>
83
+ </button>
84
+ );
85
+ })}
86
+ </nav>
87
+ </div>
88
+ </aside>
89
+ );
90
+ };
91
+
92
+ export default Sidebar;