@gxp-dev/tools 2.0.63 → 2.0.64

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