@gxp-dev/tools 2.0.5

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 (145) hide show
  1. package/.github/workflows/npm-publish.yml +48 -0
  2. package/CLAUDE.md +400 -0
  3. package/README.md +247 -0
  4. package/REFACTOR_PLAN.md +194 -0
  5. package/bin/gx-devtools.js +87 -0
  6. package/bin/lib/cli.js +251 -0
  7. package/bin/lib/commands/assets.js +337 -0
  8. package/bin/lib/commands/build.js +259 -0
  9. package/bin/lib/commands/datastore.js +433 -0
  10. package/bin/lib/commands/dev.js +328 -0
  11. package/bin/lib/commands/extensions.js +298 -0
  12. package/bin/lib/commands/index.js +35 -0
  13. package/bin/lib/commands/init.js +307 -0
  14. package/bin/lib/commands/publish.js +189 -0
  15. package/bin/lib/commands/socket.js +158 -0
  16. package/bin/lib/commands/ssl.js +47 -0
  17. package/bin/lib/constants.js +120 -0
  18. package/bin/lib/tui/App.tsx +600 -0
  19. package/bin/lib/tui/components/CommandInput.tsx +278 -0
  20. package/bin/lib/tui/components/GeminiPanel.tsx +161 -0
  21. package/bin/lib/tui/components/Header.tsx +27 -0
  22. package/bin/lib/tui/components/LogPanel.tsx +122 -0
  23. package/bin/lib/tui/components/TabBar.tsx +56 -0
  24. package/bin/lib/tui/components/WelcomeScreen.tsx +80 -0
  25. package/bin/lib/tui/index.tsx +63 -0
  26. package/bin/lib/tui/services/ExtensionService.ts +122 -0
  27. package/bin/lib/tui/services/GeminiService.ts +395 -0
  28. package/bin/lib/tui/services/ServiceManager.ts +336 -0
  29. package/bin/lib/tui/services/SocketService.ts +204 -0
  30. package/bin/lib/tui/services/ViteService.ts +107 -0
  31. package/bin/lib/tui/services/index.ts +13 -0
  32. package/bin/lib/utils/files.js +180 -0
  33. package/bin/lib/utils/index.js +17 -0
  34. package/bin/lib/utils/paths.js +138 -0
  35. package/bin/lib/utils/prompts.js +71 -0
  36. package/bin/lib/utils/ssl.js +233 -0
  37. package/browser-extensions/README.md +1 -0
  38. package/browser-extensions/chrome/background.js +857 -0
  39. package/browser-extensions/chrome/content.js +51 -0
  40. package/browser-extensions/chrome/devtools.html +9 -0
  41. package/browser-extensions/chrome/devtools.js +23 -0
  42. package/browser-extensions/chrome/icons/gx_off_128.png +0 -0
  43. package/browser-extensions/chrome/icons/gx_off_16.png +0 -0
  44. package/browser-extensions/chrome/icons/gx_off_32.png +0 -0
  45. package/browser-extensions/chrome/icons/gx_off_64.png +0 -0
  46. package/browser-extensions/chrome/icons/gx_on_128.png +0 -0
  47. package/browser-extensions/chrome/icons/gx_on_16.png +0 -0
  48. package/browser-extensions/chrome/icons/gx_on_32.png +0 -0
  49. package/browser-extensions/chrome/icons/gx_on_64.png +0 -0
  50. package/browser-extensions/chrome/inspector.js +1087 -0
  51. package/browser-extensions/chrome/manifest.json +70 -0
  52. package/browser-extensions/chrome/panel.html +638 -0
  53. package/browser-extensions/chrome/panel.js +862 -0
  54. package/browser-extensions/chrome/popup.html +399 -0
  55. package/browser-extensions/chrome/popup.js +515 -0
  56. package/browser-extensions/chrome/rules.json +1 -0
  57. package/browser-extensions/chrome/test-chrome.html +145 -0
  58. package/browser-extensions/chrome/test-mixed-content.html +190 -0
  59. package/browser-extensions/chrome/test-uri-pattern.html +199 -0
  60. package/browser-extensions/firefox/README.md +134 -0
  61. package/browser-extensions/firefox/background.js +804 -0
  62. package/browser-extensions/firefox/content.js +120 -0
  63. package/browser-extensions/firefox/debug-errors.html +229 -0
  64. package/browser-extensions/firefox/debug-https.html +113 -0
  65. package/browser-extensions/firefox/devtools.html +9 -0
  66. package/browser-extensions/firefox/devtools.js +24 -0
  67. package/browser-extensions/firefox/icons/gx_off_128.png +0 -0
  68. package/browser-extensions/firefox/icons/gx_off_16.png +0 -0
  69. package/browser-extensions/firefox/icons/gx_off_32.png +0 -0
  70. package/browser-extensions/firefox/icons/gx_off_64.png +0 -0
  71. package/browser-extensions/firefox/icons/gx_on_128.png +0 -0
  72. package/browser-extensions/firefox/icons/gx_on_16.png +0 -0
  73. package/browser-extensions/firefox/icons/gx_on_32.png +0 -0
  74. package/browser-extensions/firefox/icons/gx_on_64.png +0 -0
  75. package/browser-extensions/firefox/inspector.js +1087 -0
  76. package/browser-extensions/firefox/manifest.json +67 -0
  77. package/browser-extensions/firefox/panel.html +638 -0
  78. package/browser-extensions/firefox/panel.js +862 -0
  79. package/browser-extensions/firefox/popup.html +525 -0
  80. package/browser-extensions/firefox/popup.js +536 -0
  81. package/browser-extensions/firefox/test-gramercy.html +126 -0
  82. package/browser-extensions/firefox/test-imports.html +58 -0
  83. package/browser-extensions/firefox/test-masking.html +147 -0
  84. package/browser-extensions/firefox/test-uri-pattern.html +199 -0
  85. package/docs/DOCUSAURUS_IMPORT.md +378 -0
  86. package/docs/_category_.json +8 -0
  87. package/docs/app-manifest.md +272 -0
  88. package/docs/building-for-platform.md +315 -0
  89. package/docs/dev-tools.md +291 -0
  90. package/docs/getting-started.md +180 -0
  91. package/docs/gxp-store.md +305 -0
  92. package/docs/index.md +44 -0
  93. package/package.json +77 -0
  94. package/runtime/PortalContainer.vue +326 -0
  95. package/runtime/dev-tools/DevToolsModal.vue +217 -0
  96. package/runtime/dev-tools/LayoutSwitcher.vue +221 -0
  97. package/runtime/dev-tools/MockDataEditor.vue +621 -0
  98. package/runtime/dev-tools/SocketSimulator.vue +562 -0
  99. package/runtime/dev-tools/StoreInspector.vue +644 -0
  100. package/runtime/dev-tools/index.js +6 -0
  101. package/runtime/gxpStringsPlugin.js +428 -0
  102. package/runtime/index.html +22 -0
  103. package/runtime/main.js +32 -0
  104. package/runtime/mock-api/auth-middleware.js +97 -0
  105. package/runtime/mock-api/image-generator.js +221 -0
  106. package/runtime/mock-api/index.js +197 -0
  107. package/runtime/mock-api/response-generator.js +394 -0
  108. package/runtime/mock-api/route-generator.js +323 -0
  109. package/runtime/mock-api/socket-triggers.js +371 -0
  110. package/runtime/mock-api/spec-loader.js +300 -0
  111. package/runtime/server.js +180 -0
  112. package/runtime/stores/gxpPortalConfigStore.js +554 -0
  113. package/runtime/stores/index.js +6 -0
  114. package/runtime/vite-inspector-plugin.js +749 -0
  115. package/runtime/vite-source-tracker-plugin.js +232 -0
  116. package/runtime/vite.config.js +402 -0
  117. package/scripts/launch-chrome.js +90 -0
  118. package/scripts/pack-chrome.js +91 -0
  119. package/socket-events/AiSessionMessageCreated.json +18 -0
  120. package/socket-events/SocialStreamPostCreated.json +24 -0
  121. package/socket-events/SocialStreamPostVariantCompleted.json +23 -0
  122. package/template/README.md +332 -0
  123. package/template/app-manifest.json +32 -0
  124. package/template/dev-assets/images/avatar-placeholder.png +0 -0
  125. package/template/dev-assets/images/background-placeholder.jpg +0 -0
  126. package/template/dev-assets/images/banner-placeholder.jpg +0 -0
  127. package/template/dev-assets/images/icon-placeholder.png +0 -0
  128. package/template/dev-assets/images/logo-placeholder.png +0 -0
  129. package/template/dev-assets/images/product-placeholder.jpg +0 -0
  130. package/template/dev-assets/images/thumbnail-placeholder.jpg +0 -0
  131. package/template/env.example +51 -0
  132. package/template/gitignore +53 -0
  133. package/template/index.html +22 -0
  134. package/template/main.js +28 -0
  135. package/template/src/DemoPage.vue +459 -0
  136. package/template/src/Plugin.vue +38 -0
  137. package/template/src/stores/index.js +9 -0
  138. package/template/src/stores/test-data.json +173 -0
  139. package/template/theme-layouts/AdditionalStyling.css +0 -0
  140. package/template/theme-layouts/PrivateLayout.vue +39 -0
  141. package/template/theme-layouts/PublicLayout.vue +39 -0
  142. package/template/theme-layouts/SystemLayout.vue +39 -0
  143. package/template/vite.config.js +333 -0
  144. package/tsconfig.tui.json +21 -0
  145. package/vite.config.js +164 -0
@@ -0,0 +1,67 @@
1
+ {
2
+ "manifest_version": 2,
3
+ "name": "GxP Developer Toolkit",
4
+ "version": "1.2",
5
+ "description": "JavaScript proxy and component inspector for GxP plugin development",
6
+
7
+ "browser_specific_settings": {
8
+ "gecko": {
9
+ "id": "gxp-toolkit@gx-devtools.dev"
10
+ }
11
+ },
12
+
13
+ "permissions": [
14
+ "tabs",
15
+ "webRequest",
16
+ "webRequestBlocking",
17
+ "<all_urls>",
18
+ "storage",
19
+ "notifications",
20
+ "browsingData"
21
+ ],
22
+
23
+ "background": {
24
+ "scripts": ["background.js"],
25
+ "persistent": true
26
+ },
27
+
28
+ "devtools_page": "devtools.html",
29
+
30
+ "content_scripts": [
31
+ {
32
+ "matches": ["<all_urls>"],
33
+ "js": ["content.js"],
34
+ "run_at": "document_start"
35
+ },
36
+ {
37
+ "matches": ["<all_urls>"],
38
+ "js": ["inspector.js"],
39
+ "run_at": "document_idle"
40
+ }
41
+ ],
42
+
43
+ "browser_action": {
44
+ "default_popup": "popup.html",
45
+ "default_title": "GxP Developer Toolkit",
46
+ "default_icon": {
47
+ "16": "icons/gx_off_16.png",
48
+ "32": "icons/gx_off_32.png",
49
+ "48": "icons/gx_off_48.png",
50
+ "128": "icons/gx_off_128.png"
51
+ }
52
+ },
53
+
54
+ "icons": {
55
+ "16": "icons/gx_off_16.png",
56
+ "32": "icons/gx_off_32.png",
57
+ "48": "icons/gx_off_48.png",
58
+ "128": "icons/gx_off_128.png"
59
+ },
60
+
61
+ "web_accessible_resources": [
62
+ "content.js",
63
+ "inspector.js",
64
+ "panel.html",
65
+ "panel.js"
66
+ ]
67
+ }
@@ -0,0 +1,638 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <style>
6
+ * {
7
+ box-sizing: border-box;
8
+ }
9
+
10
+ body {
11
+ margin: 0;
12
+ padding: 0;
13
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
14
+ font-size: 12px;
15
+ background: #1e1e1e;
16
+ color: #e0e0e0;
17
+ height: 100vh;
18
+ overflow: hidden;
19
+ display: flex;
20
+ flex-direction: column;
21
+ }
22
+
23
+ /* Header / Toolbar */
24
+ .toolbar {
25
+ display: flex;
26
+ align-items: center;
27
+ gap: 8px;
28
+ padding: 8px 12px;
29
+ background: #2d2d2d;
30
+ border-bottom: 1px solid #3d3d3d;
31
+ flex-shrink: 0;
32
+ }
33
+
34
+ .toolbar-title {
35
+ font-weight: 600;
36
+ color: #61dafb;
37
+ margin-right: auto;
38
+ }
39
+
40
+ .toolbar-btn {
41
+ background: #3d3d3d;
42
+ border: none;
43
+ color: #e0e0e0;
44
+ padding: 6px 12px;
45
+ border-radius: 4px;
46
+ font-size: 11px;
47
+ cursor: pointer;
48
+ display: flex;
49
+ align-items: center;
50
+ gap: 4px;
51
+ }
52
+
53
+ .toolbar-btn:hover {
54
+ background: #4d4d4d;
55
+ }
56
+
57
+ .toolbar-btn.active {
58
+ background: #61dafb;
59
+ color: #1e1e1e;
60
+ }
61
+
62
+ .toolbar-btn.active:hover {
63
+ background: #4fc3f7;
64
+ }
65
+
66
+ .status-indicator {
67
+ width: 8px;
68
+ height: 8px;
69
+ border-radius: 50%;
70
+ background: #dc3545;
71
+ }
72
+
73
+ .status-indicator.connected {
74
+ background: #28a745;
75
+ }
76
+
77
+ /* Main content area */
78
+ .main-content {
79
+ flex: 1;
80
+ display: flex;
81
+ overflow: hidden;
82
+ }
83
+
84
+ /* Sidebar for component tree (future) */
85
+ .sidebar {
86
+ width: 250px;
87
+ background: #252525;
88
+ border-right: 1px solid #3d3d3d;
89
+ display: flex;
90
+ flex-direction: column;
91
+ flex-shrink: 0;
92
+ }
93
+
94
+ .sidebar-header {
95
+ padding: 8px 12px;
96
+ font-weight: 600;
97
+ font-size: 11px;
98
+ text-transform: uppercase;
99
+ color: #888;
100
+ border-bottom: 1px solid #3d3d3d;
101
+ }
102
+
103
+ .sidebar-content {
104
+ flex: 1;
105
+ overflow-y: auto;
106
+ padding: 8px;
107
+ }
108
+
109
+ /* Inspector panel */
110
+ .inspector {
111
+ flex: 1;
112
+ display: flex;
113
+ flex-direction: column;
114
+ overflow: hidden;
115
+ }
116
+
117
+ .inspector-header {
118
+ padding: 12px 16px;
119
+ border-bottom: 1px solid #3d3d3d;
120
+ background: #252525;
121
+ }
122
+
123
+ .component-name {
124
+ font-size: 15px;
125
+ font-weight: 600;
126
+ color: #61dafb;
127
+ margin-bottom: 4px;
128
+ }
129
+
130
+ .component-file {
131
+ font-size: 11px;
132
+ color: #888;
133
+ word-break: break-all;
134
+ }
135
+
136
+ .inspector-body {
137
+ flex: 1;
138
+ overflow-y: auto;
139
+ padding: 16px;
140
+ }
141
+
142
+ /* Sections */
143
+ .section {
144
+ margin-bottom: 20px;
145
+ }
146
+
147
+ .section-title {
148
+ font-size: 11px;
149
+ font-weight: 600;
150
+ text-transform: uppercase;
151
+ color: #888;
152
+ margin-bottom: 8px;
153
+ display: flex;
154
+ align-items: center;
155
+ gap: 6px;
156
+ }
157
+
158
+ .section-title .count {
159
+ background: #3d3d3d;
160
+ padding: 1px 6px;
161
+ border-radius: 10px;
162
+ font-size: 10px;
163
+ }
164
+
165
+ /* Strings list */
166
+ .strings-list {
167
+ display: flex;
168
+ flex-direction: column;
169
+ gap: 4px;
170
+ }
171
+
172
+ .string-item {
173
+ display: flex;
174
+ align-items: center;
175
+ padding: 8px 10px;
176
+ background: #2d2d2d;
177
+ border-radius: 4px;
178
+ border: 1px solid transparent;
179
+ cursor: pointer;
180
+ }
181
+
182
+ .string-item:hover {
183
+ border-color: #3d3d3d;
184
+ background: #333;
185
+ }
186
+
187
+ .string-item.selected {
188
+ border-color: #61dafb;
189
+ background: #2a3a4a;
190
+ }
191
+
192
+ .string-text {
193
+ flex: 1;
194
+ overflow: hidden;
195
+ text-overflow: ellipsis;
196
+ white-space: nowrap;
197
+ font-family: 'Monaco', 'Menlo', monospace;
198
+ font-size: 11px;
199
+ }
200
+
201
+ .string-actions {
202
+ display: flex;
203
+ gap: 4px;
204
+ opacity: 0;
205
+ transition: opacity 0.15s;
206
+ }
207
+
208
+ .string-item:hover .string-actions {
209
+ opacity: 1;
210
+ }
211
+
212
+ .action-btn {
213
+ background: #61dafb;
214
+ color: #1e1e1e;
215
+ border: none;
216
+ padding: 4px 8px;
217
+ border-radius: 3px;
218
+ font-size: 10px;
219
+ font-weight: 600;
220
+ cursor: pointer;
221
+ }
222
+
223
+ .action-btn:hover {
224
+ background: #4fc3f7;
225
+ }
226
+
227
+ .action-btn.secondary {
228
+ background: #4d4d4d;
229
+ color: #e0e0e0;
230
+ }
231
+
232
+ .action-btn.secondary:hover {
233
+ background: #5d5d5d;
234
+ }
235
+
236
+ /* Extract form */
237
+ .extract-form {
238
+ background: #252525;
239
+ border: 1px solid #3d3d3d;
240
+ border-radius: 6px;
241
+ padding: 16px;
242
+ margin-top: 12px;
243
+ }
244
+
245
+ .form-row {
246
+ display: flex;
247
+ flex-direction: column;
248
+ gap: 4px;
249
+ margin-bottom: 12px;
250
+ }
251
+
252
+ .form-row:last-child {
253
+ margin-bottom: 0;
254
+ }
255
+
256
+ .form-label {
257
+ font-size: 11px;
258
+ color: #888;
259
+ font-weight: 500;
260
+ }
261
+
262
+ .form-input {
263
+ background: #1e1e1e;
264
+ border: 1px solid #3d3d3d;
265
+ border-radius: 4px;
266
+ padding: 8px 10px;
267
+ color: #e0e0e0;
268
+ font-size: 12px;
269
+ font-family: 'Monaco', 'Menlo', monospace;
270
+ }
271
+
272
+ .form-input:focus {
273
+ outline: none;
274
+ border-color: #61dafb;
275
+ }
276
+
277
+ .form-input:disabled {
278
+ background: #2d2d2d;
279
+ color: #888;
280
+ }
281
+
282
+ .form-actions {
283
+ display: flex;
284
+ gap: 8px;
285
+ margin-top: 16px;
286
+ }
287
+
288
+ .btn-primary {
289
+ background: #28a745;
290
+ color: white;
291
+ border: none;
292
+ padding: 10px 16px;
293
+ border-radius: 4px;
294
+ font-size: 12px;
295
+ font-weight: 600;
296
+ cursor: pointer;
297
+ flex: 1;
298
+ }
299
+
300
+ .btn-primary:hover {
301
+ background: #218838;
302
+ }
303
+
304
+ .btn-primary:disabled {
305
+ background: #6c757d;
306
+ cursor: not-allowed;
307
+ }
308
+
309
+ .btn-cancel {
310
+ background: #4d4d4d;
311
+ color: #e0e0e0;
312
+ border: none;
313
+ padding: 10px 16px;
314
+ border-radius: 4px;
315
+ font-size: 12px;
316
+ cursor: pointer;
317
+ }
318
+
319
+ .btn-cancel:hover {
320
+ background: #5d5d5d;
321
+ }
322
+
323
+ /* Props tree */
324
+ .props-tree {
325
+ background: #2d2d2d;
326
+ border-radius: 4px;
327
+ padding: 10px;
328
+ font-family: 'Monaco', 'Menlo', monospace;
329
+ font-size: 11px;
330
+ overflow-x: auto;
331
+ max-height: 200px;
332
+ }
333
+
334
+ .prop-item {
335
+ padding: 2px 0;
336
+ }
337
+
338
+ .prop-key {
339
+ color: #9cdcfe;
340
+ }
341
+
342
+ .prop-value {
343
+ color: #ce9178;
344
+ }
345
+
346
+ .prop-value.number {
347
+ color: #b5cea8;
348
+ }
349
+
350
+ .prop-value.boolean {
351
+ color: #569cd6;
352
+ }
353
+
354
+ /* Status messages */
355
+ .status-message {
356
+ padding: 10px 12px;
357
+ border-radius: 4px;
358
+ font-size: 12px;
359
+ margin-top: 12px;
360
+ }
361
+
362
+ .status-message.success {
363
+ background: #28a74520;
364
+ border: 1px solid #28a745;
365
+ color: #28a745;
366
+ }
367
+
368
+ .status-message.error {
369
+ background: #dc354520;
370
+ border: 1px solid #dc3545;
371
+ color: #dc3545;
372
+ }
373
+
374
+ .status-message.info {
375
+ background: #17a2b820;
376
+ border: 1px solid #17a2b8;
377
+ color: #17a2b8;
378
+ }
379
+
380
+ /* Form header for edit form */
381
+ .form-header {
382
+ display: flex;
383
+ align-items: center;
384
+ gap: 8px;
385
+ margin-bottom: 16px;
386
+ padding-bottom: 12px;
387
+ border-bottom: 1px solid #3d3d3d;
388
+ }
389
+
390
+ .form-badge {
391
+ padding: 4px 8px;
392
+ border-radius: 4px;
393
+ font-size: 11px;
394
+ font-weight: 600;
395
+ font-family: 'Monaco', 'Menlo', monospace;
396
+ }
397
+
398
+ .form-badge.getString {
399
+ background: #61dafb20;
400
+ border: 1px solid #61dafb;
401
+ color: #61dafb;
402
+ }
403
+
404
+ .form-subtitle {
405
+ font-size: 12px;
406
+ color: #888;
407
+ }
408
+
409
+ /* String item badges */
410
+ .string-badge {
411
+ padding: 2px 6px;
412
+ border-radius: 3px;
413
+ font-size: 9px;
414
+ font-weight: 600;
415
+ margin-left: 8px;
416
+ }
417
+
418
+ .string-badge.extracted {
419
+ background: #61dafb30;
420
+ color: #61dafb;
421
+ }
422
+
423
+ .string-badge.raw {
424
+ background: #ffc10730;
425
+ color: #ffc107;
426
+ }
427
+
428
+ .string-badge.dynamic {
429
+ background: #9c27b030;
430
+ color: #ce93d8;
431
+ }
432
+
433
+ .string-item.extracted {
434
+ border-left: 3px solid #61dafb;
435
+ }
436
+
437
+ .string-item.dynamic {
438
+ border-left: 3px solid #9c27b0;
439
+ opacity: 0.85;
440
+ }
441
+
442
+ .string-item.dynamic:hover {
443
+ opacity: 1;
444
+ }
445
+
446
+ .string-content {
447
+ flex: 1;
448
+ display: flex;
449
+ flex-direction: column;
450
+ gap: 2px;
451
+ overflow: hidden;
452
+ }
453
+
454
+ .string-expression {
455
+ font-size: 10px;
456
+ color: #ce93d8;
457
+ font-family: 'Monaco', 'Menlo', monospace;
458
+ overflow: hidden;
459
+ text-overflow: ellipsis;
460
+ white-space: nowrap;
461
+ }
462
+
463
+ .string-item.extracted .string-actions .action-btn {
464
+ background: #4d4d4d;
465
+ color: #e0e0e0;
466
+ }
467
+
468
+ .string-item.extracted .string-actions .action-btn:hover {
469
+ background: #5d5d5d;
470
+ }
471
+
472
+ /* Empty state */
473
+ .empty-state {
474
+ display: flex;
475
+ flex-direction: column;
476
+ align-items: center;
477
+ justify-content: center;
478
+ height: 100%;
479
+ color: #888;
480
+ text-align: center;
481
+ padding: 40px;
482
+ }
483
+
484
+ .empty-state-icon {
485
+ font-size: 48px;
486
+ margin-bottom: 16px;
487
+ opacity: 0.5;
488
+ }
489
+
490
+ .empty-state-title {
491
+ font-size: 14px;
492
+ font-weight: 600;
493
+ margin-bottom: 8px;
494
+ color: #aaa;
495
+ }
496
+
497
+ .empty-state-text {
498
+ font-size: 12px;
499
+ line-height: 1.5;
500
+ }
501
+
502
+ .kbd {
503
+ background: #3d3d3d;
504
+ padding: 2px 6px;
505
+ border-radius: 3px;
506
+ font-family: 'Monaco', 'Menlo', monospace;
507
+ font-size: 10px;
508
+ }
509
+
510
+ /* Scrollbar styling */
511
+ ::-webkit-scrollbar {
512
+ width: 8px;
513
+ height: 8px;
514
+ }
515
+
516
+ ::-webkit-scrollbar-track {
517
+ background: #1e1e1e;
518
+ }
519
+
520
+ ::-webkit-scrollbar-thumb {
521
+ background: #4d4d4d;
522
+ border-radius: 4px;
523
+ }
524
+
525
+ ::-webkit-scrollbar-thumb:hover {
526
+ background: #5d5d5d;
527
+ }
528
+
529
+ /* Hidden class */
530
+ .hidden {
531
+ display: none !important;
532
+ }
533
+ </style>
534
+ </head>
535
+ <body>
536
+ <div class="toolbar">
537
+ <span class="toolbar-title">GxP Component Inspector</span>
538
+ <div class="status-indicator" id="statusIndicator" title="Disconnected"></div>
539
+ <button class="toolbar-btn" id="selectBtn">
540
+ <span>Select Element</span>
541
+ </button>
542
+ <button class="toolbar-btn" id="refreshBtn">Refresh</button>
543
+ </div>
544
+
545
+ <div class="main-content">
546
+ <div class="inspector">
547
+ <!-- Empty state shown when no component selected -->
548
+ <div class="empty-state" id="emptyState">
549
+ <div class="empty-state-icon">&#128269;</div>
550
+ <div class="empty-state-title">No Component Selected</div>
551
+ <div class="empty-state-text">
552
+ Click <strong>"Select Element"</strong> then click on any element in the page to inspect it.<br><br>
553
+ Or use the keyboard shortcut <span class="kbd">Ctrl+Shift+I</span> to toggle element selection.
554
+ </div>
555
+ </div>
556
+
557
+ <!-- Inspector content shown when component is selected -->
558
+ <div class="hidden" id="inspectorContent">
559
+ <div class="inspector-header">
560
+ <div class="component-name" id="componentName">&lt;Unknown&gt;</div>
561
+ <div class="component-file" id="componentFile">No file info</div>
562
+ </div>
563
+
564
+ <div class="inspector-body">
565
+ <!-- Text content section -->
566
+ <div class="section" id="stringsSection">
567
+ <div class="section-title">
568
+ Text Content
569
+ <span class="count" id="stringsCount">0</span>
570
+ </div>
571
+ <div class="strings-list" id="stringsList"></div>
572
+ </div>
573
+
574
+ <!-- Extract form (hidden by default) -->
575
+ <div class="extract-form hidden" id="extractForm">
576
+ <div class="form-row">
577
+ <label class="form-label">Original Text</label>
578
+ <input type="text" class="form-input" id="extractText" readonly>
579
+ </div>
580
+ <div class="form-row">
581
+ <label class="form-label">String Key</label>
582
+ <input type="text" class="form-input" id="extractKey" placeholder="e.g., welcome_title">
583
+ </div>
584
+ <div class="form-row">
585
+ <label class="form-label">Source File</label>
586
+ <input type="text" class="form-input" id="extractFile" readonly>
587
+ </div>
588
+ <div class="form-actions">
589
+ <button class="btn-cancel" id="cancelExtract">Cancel</button>
590
+ <button class="btn-primary" id="doExtract">Extract to gxp-string</button>
591
+ </div>
592
+ <div class="status-message hidden" id="extractStatus"></div>
593
+ </div>
594
+
595
+ <!-- Edit form for existing gxp-string attributes (hidden by default) -->
596
+ <div class="extract-form hidden" id="editForm">
597
+ <div class="form-header">
598
+ <span class="form-badge getString">gxp-string</span>
599
+ <span class="form-subtitle">This text is already extracted</span>
600
+ </div>
601
+ <div class="form-row">
602
+ <label class="form-label">String Key</label>
603
+ <input type="text" class="form-input" id="editKey" placeholder="e.g., welcome_title">
604
+ </div>
605
+ <div class="form-row">
606
+ <label class="form-label">Default Value</label>
607
+ <input type="text" class="form-input" id="editValue" placeholder="The displayed text">
608
+ </div>
609
+ <div class="form-row">
610
+ <label class="form-label">Source File</label>
611
+ <input type="text" class="form-input" id="editFile" readonly>
612
+ </div>
613
+ <div class="form-actions">
614
+ <button class="btn-cancel" id="cancelEdit">Cancel</button>
615
+ <button class="btn-primary" id="doEdit">Update gxp-string</button>
616
+ </div>
617
+ <div class="status-message hidden" id="editStatus"></div>
618
+ </div>
619
+
620
+ <!-- Props section -->
621
+ <div class="section" id="propsSection">
622
+ <div class="section-title">Props</div>
623
+ <div class="props-tree" id="propsTree"></div>
624
+ </div>
625
+
626
+ <!-- Data section -->
627
+ <div class="section hidden" id="dataSection">
628
+ <div class="section-title">Data</div>
629
+ <div class="props-tree" id="dataTree"></div>
630
+ </div>
631
+ </div>
632
+ </div>
633
+ </div>
634
+ </div>
635
+
636
+ <script src="panel.js"></script>
637
+ </body>
638
+ </html>