@gxp-dev/tools 2.0.5 → 2.0.6

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 (169) hide show
  1. package/dist/tui/App.d.ts +13 -0
  2. package/dist/tui/App.d.ts.map +1 -0
  3. package/dist/tui/App.js +480 -0
  4. package/dist/tui/App.js.map +1 -0
  5. package/dist/tui/components/CommandInput.d.ts +13 -0
  6. package/dist/tui/components/CommandInput.d.ts.map +1 -0
  7. package/dist/tui/components/CommandInput.js +180 -0
  8. package/dist/tui/components/CommandInput.js.map +1 -0
  9. package/dist/tui/components/GeminiPanel.d.ts +7 -0
  10. package/dist/tui/components/GeminiPanel.d.ts.map +1 -0
  11. package/dist/tui/components/GeminiPanel.js +99 -0
  12. package/dist/tui/components/GeminiPanel.js.map +1 -0
  13. package/dist/tui/components/Header.d.ts +6 -0
  14. package/dist/tui/components/Header.d.ts.map +1 -0
  15. package/dist/tui/components/Header.js +6 -0
  16. package/dist/tui/components/Header.js.map +1 -0
  17. package/dist/tui/components/LogPanel.d.ts +8 -0
  18. package/dist/tui/components/LogPanel.d.ts.map +1 -0
  19. package/dist/tui/components/LogPanel.js +89 -0
  20. package/dist/tui/components/LogPanel.js.map +1 -0
  21. package/dist/tui/components/TabBar.d.ts +9 -0
  22. package/dist/tui/components/TabBar.d.ts.map +1 -0
  23. package/dist/tui/components/TabBar.js +23 -0
  24. package/dist/tui/components/TabBar.js.map +1 -0
  25. package/dist/tui/components/WelcomeScreen.d.ts +2 -0
  26. package/dist/tui/components/WelcomeScreen.d.ts.map +1 -0
  27. package/dist/tui/components/WelcomeScreen.js +14 -0
  28. package/dist/tui/components/WelcomeScreen.js.map +1 -0
  29. package/dist/tui/index.d.ts +8 -0
  30. package/dist/tui/index.d.ts.map +1 -0
  31. package/dist/tui/index.js +47 -0
  32. package/dist/tui/index.js.map +1 -0
  33. package/dist/tui/package.json +1 -0
  34. package/dist/tui/services/ExtensionService.d.ts +11 -0
  35. package/dist/tui/services/ExtensionService.d.ts.map +1 -0
  36. package/dist/tui/services/ExtensionService.js +101 -0
  37. package/dist/tui/services/ExtensionService.js.map +1 -0
  38. package/dist/tui/services/GeminiService.d.ts +40 -0
  39. package/dist/tui/services/GeminiService.d.ts.map +1 -0
  40. package/dist/tui/services/GeminiService.js +327 -0
  41. package/dist/tui/services/GeminiService.js.map +1 -0
  42. package/dist/tui/services/ServiceManager.d.ts +40 -0
  43. package/dist/tui/services/ServiceManager.d.ts.map +1 -0
  44. package/dist/tui/services/ServiceManager.js +283 -0
  45. package/dist/tui/services/ServiceManager.js.map +1 -0
  46. package/dist/tui/services/SocketService.d.ts +19 -0
  47. package/dist/tui/services/SocketService.d.ts.map +1 -0
  48. package/dist/tui/services/SocketService.js +163 -0
  49. package/dist/tui/services/SocketService.js.map +1 -0
  50. package/dist/tui/services/ViteService.d.ts +8 -0
  51. package/dist/tui/services/ViteService.d.ts.map +1 -0
  52. package/dist/tui/services/ViteService.js +89 -0
  53. package/dist/tui/services/ViteService.js.map +1 -0
  54. package/dist/tui/services/index.d.ts +6 -0
  55. package/dist/tui/services/index.d.ts.map +1 -0
  56. package/dist/tui/services/index.js +6 -0
  57. package/dist/tui/services/index.js.map +1 -0
  58. package/package.json +6 -1
  59. package/.github/workflows/npm-publish.yml +0 -48
  60. package/CLAUDE.md +0 -400
  61. package/REFACTOR_PLAN.md +0 -194
  62. package/browser-extensions/README.md +0 -1
  63. package/browser-extensions/chrome/background.js +0 -857
  64. package/browser-extensions/chrome/content.js +0 -51
  65. package/browser-extensions/chrome/devtools.html +0 -9
  66. package/browser-extensions/chrome/devtools.js +0 -23
  67. package/browser-extensions/chrome/icons/gx_off_128.png +0 -0
  68. package/browser-extensions/chrome/icons/gx_off_16.png +0 -0
  69. package/browser-extensions/chrome/icons/gx_off_32.png +0 -0
  70. package/browser-extensions/chrome/icons/gx_off_64.png +0 -0
  71. package/browser-extensions/chrome/icons/gx_on_128.png +0 -0
  72. package/browser-extensions/chrome/icons/gx_on_16.png +0 -0
  73. package/browser-extensions/chrome/icons/gx_on_32.png +0 -0
  74. package/browser-extensions/chrome/icons/gx_on_64.png +0 -0
  75. package/browser-extensions/chrome/inspector.js +0 -1087
  76. package/browser-extensions/chrome/manifest.json +0 -70
  77. package/browser-extensions/chrome/panel.html +0 -638
  78. package/browser-extensions/chrome/panel.js +0 -862
  79. package/browser-extensions/chrome/popup.html +0 -399
  80. package/browser-extensions/chrome/popup.js +0 -515
  81. package/browser-extensions/chrome/rules.json +0 -1
  82. package/browser-extensions/chrome/test-chrome.html +0 -145
  83. package/browser-extensions/chrome/test-mixed-content.html +0 -190
  84. package/browser-extensions/chrome/test-uri-pattern.html +0 -199
  85. package/browser-extensions/firefox/README.md +0 -134
  86. package/browser-extensions/firefox/background.js +0 -804
  87. package/browser-extensions/firefox/content.js +0 -120
  88. package/browser-extensions/firefox/debug-errors.html +0 -229
  89. package/browser-extensions/firefox/debug-https.html +0 -113
  90. package/browser-extensions/firefox/devtools.html +0 -9
  91. package/browser-extensions/firefox/devtools.js +0 -24
  92. package/browser-extensions/firefox/icons/gx_off_128.png +0 -0
  93. package/browser-extensions/firefox/icons/gx_off_16.png +0 -0
  94. package/browser-extensions/firefox/icons/gx_off_32.png +0 -0
  95. package/browser-extensions/firefox/icons/gx_off_64.png +0 -0
  96. package/browser-extensions/firefox/icons/gx_on_128.png +0 -0
  97. package/browser-extensions/firefox/icons/gx_on_16.png +0 -0
  98. package/browser-extensions/firefox/icons/gx_on_32.png +0 -0
  99. package/browser-extensions/firefox/icons/gx_on_64.png +0 -0
  100. package/browser-extensions/firefox/inspector.js +0 -1087
  101. package/browser-extensions/firefox/manifest.json +0 -67
  102. package/browser-extensions/firefox/panel.html +0 -638
  103. package/browser-extensions/firefox/panel.js +0 -862
  104. package/browser-extensions/firefox/popup.html +0 -525
  105. package/browser-extensions/firefox/popup.js +0 -536
  106. package/browser-extensions/firefox/test-gramercy.html +0 -126
  107. package/browser-extensions/firefox/test-imports.html +0 -58
  108. package/browser-extensions/firefox/test-masking.html +0 -147
  109. package/browser-extensions/firefox/test-uri-pattern.html +0 -199
  110. package/docs/DOCUSAURUS_IMPORT.md +0 -378
  111. package/docs/_category_.json +0 -8
  112. package/docs/app-manifest.md +0 -272
  113. package/docs/building-for-platform.md +0 -315
  114. package/docs/dev-tools.md +0 -291
  115. package/docs/getting-started.md +0 -180
  116. package/docs/gxp-store.md +0 -305
  117. package/docs/index.md +0 -44
  118. package/runtime/PortalContainer.vue +0 -326
  119. package/runtime/dev-tools/DevToolsModal.vue +0 -217
  120. package/runtime/dev-tools/LayoutSwitcher.vue +0 -221
  121. package/runtime/dev-tools/MockDataEditor.vue +0 -621
  122. package/runtime/dev-tools/SocketSimulator.vue +0 -562
  123. package/runtime/dev-tools/StoreInspector.vue +0 -644
  124. package/runtime/dev-tools/index.js +0 -6
  125. package/runtime/gxpStringsPlugin.js +0 -428
  126. package/runtime/index.html +0 -22
  127. package/runtime/main.js +0 -32
  128. package/runtime/mock-api/auth-middleware.js +0 -97
  129. package/runtime/mock-api/image-generator.js +0 -221
  130. package/runtime/mock-api/index.js +0 -197
  131. package/runtime/mock-api/response-generator.js +0 -394
  132. package/runtime/mock-api/route-generator.js +0 -323
  133. package/runtime/mock-api/socket-triggers.js +0 -371
  134. package/runtime/mock-api/spec-loader.js +0 -300
  135. package/runtime/server.js +0 -180
  136. package/runtime/stores/gxpPortalConfigStore.js +0 -554
  137. package/runtime/stores/index.js +0 -6
  138. package/runtime/vite-inspector-plugin.js +0 -749
  139. package/runtime/vite-source-tracker-plugin.js +0 -232
  140. package/runtime/vite.config.js +0 -402
  141. package/scripts/launch-chrome.js +0 -90
  142. package/scripts/pack-chrome.js +0 -91
  143. package/socket-events/AiSessionMessageCreated.json +0 -18
  144. package/socket-events/SocialStreamPostCreated.json +0 -24
  145. package/socket-events/SocialStreamPostVariantCompleted.json +0 -23
  146. package/template/README.md +0 -332
  147. package/template/app-manifest.json +0 -32
  148. package/template/dev-assets/images/avatar-placeholder.png +0 -0
  149. package/template/dev-assets/images/background-placeholder.jpg +0 -0
  150. package/template/dev-assets/images/banner-placeholder.jpg +0 -0
  151. package/template/dev-assets/images/icon-placeholder.png +0 -0
  152. package/template/dev-assets/images/logo-placeholder.png +0 -0
  153. package/template/dev-assets/images/product-placeholder.jpg +0 -0
  154. package/template/dev-assets/images/thumbnail-placeholder.jpg +0 -0
  155. package/template/env.example +0 -51
  156. package/template/gitignore +0 -53
  157. package/template/index.html +0 -22
  158. package/template/main.js +0 -28
  159. package/template/src/DemoPage.vue +0 -459
  160. package/template/src/Plugin.vue +0 -38
  161. package/template/src/stores/index.js +0 -9
  162. package/template/src/stores/test-data.json +0 -173
  163. package/template/theme-layouts/AdditionalStyling.css +0 -0
  164. package/template/theme-layouts/PrivateLayout.vue +0 -39
  165. package/template/theme-layouts/PublicLayout.vue +0 -39
  166. package/template/theme-layouts/SystemLayout.vue +0 -39
  167. package/template/vite.config.js +0 -333
  168. package/tsconfig.tui.json +0 -21
  169. package/vite.config.js +0 -164
@@ -1,644 +0,0 @@
1
- <template>
2
- <div class="store-inspector">
3
- <div class="inspector-section">
4
- <h3 class="section-title" @click="toggleSection('pluginVars')">
5
- <span class="toggle-icon">{{ expandedSections.pluginVars ? '▼' : '▶' }}</span>
6
- Plugin Variables
7
- <span class="item-count">{{ Object.keys(store.pluginVars || {}).length }}</span>
8
- </h3>
9
- <div v-if="expandedSections.pluginVars" class="section-content">
10
- <div v-if="Object.keys(store.pluginVars || {}).length === 0" class="empty-state">
11
- No plugin variables defined
12
- </div>
13
- <div v-else class="property-list">
14
- <div
15
- v-for="(value, key) in store.pluginVars"
16
- :key="key"
17
- class="property-item"
18
- @mouseenter="highlightElements('gxp-settings', key)"
19
- @mouseleave="clearHighlight()"
20
- >
21
- <span class="property-key">{{ key }}</span>
22
- <input
23
- v-if="editingKey === `pluginVars.${key}`"
24
- v-model="editValue"
25
- class="property-input"
26
- @blur="saveEdit('pluginVars', key)"
27
- @keydown.enter="saveEdit('pluginVars', key)"
28
- @keydown.escape="cancelEdit"
29
- ref="editInput"
30
- />
31
- <span
32
- v-else
33
- class="property-value"
34
- :class="getValueType(value)"
35
- @dblclick="startEdit('pluginVars', key, value)"
36
- :title="'Double-click to edit'"
37
- >
38
- {{ formatValue(value) }}
39
- </span>
40
- </div>
41
- </div>
42
- </div>
43
- </div>
44
-
45
- <div class="inspector-section">
46
- <h3 class="section-title" @click="toggleSection('stringsList')">
47
- <span class="toggle-icon">{{ expandedSections.stringsList ? '▼' : '▶' }}</span>
48
- Strings List
49
- <span class="item-count">{{ Object.keys(store.stringsList || {}).length }}</span>
50
- </h3>
51
- <div v-if="expandedSections.stringsList" class="section-content">
52
- <div v-if="Object.keys(store.stringsList || {}).length === 0" class="empty-state">
53
- No strings defined
54
- </div>
55
- <div v-else class="property-list">
56
- <div
57
- v-for="(value, key) in store.stringsList"
58
- :key="key"
59
- class="property-item"
60
- @mouseenter="highlightElements('gxp-string', key)"
61
- @mouseleave="clearHighlight()"
62
- >
63
- <span class="property-key">{{ key }}</span>
64
- <input
65
- v-if="editingKey === `stringsList.${key}`"
66
- v-model="editValue"
67
- class="property-input"
68
- @blur="saveEdit('stringsList', key)"
69
- @keydown.enter="saveEdit('stringsList', key)"
70
- @keydown.escape="cancelEdit"
71
- />
72
- <span
73
- v-else
74
- class="property-value string"
75
- @dblclick="startEdit('stringsList', key, value)"
76
- :title="'Double-click to edit'"
77
- >
78
- "{{ value }}"
79
- </span>
80
- </div>
81
- </div>
82
- </div>
83
- </div>
84
-
85
- <div class="inspector-section">
86
- <h3 class="section-title" @click="toggleSection('assetList')">
87
- <span class="toggle-icon">{{ expandedSections.assetList ? '▼' : '▶' }}</span>
88
- Asset List
89
- <span class="item-count">{{ Object.keys(store.assetList || {}).length }}</span>
90
- </h3>
91
- <div v-if="expandedSections.assetList" class="section-content">
92
- <div v-if="Object.keys(store.assetList || {}).length === 0" class="empty-state">
93
- No assets defined
94
- </div>
95
- <div v-else class="property-list">
96
- <div
97
- v-for="(value, key) in store.assetList"
98
- :key="key"
99
- class="property-item asset-item"
100
- @mouseenter="highlightElements('gxp-src', key)"
101
- @mouseleave="clearHighlight()"
102
- >
103
- <span class="property-key">{{ key }}</span>
104
- <div class="asset-preview">
105
- <img
106
- v-if="isImageUrl(value)"
107
- :src="value"
108
- class="asset-thumbnail"
109
- @error="(e) => e.target.style.display = 'none'"
110
- />
111
- <span class="property-value string" :title="value">
112
- {{ truncateUrl(value) }}
113
- </span>
114
- </div>
115
- </div>
116
- </div>
117
- </div>
118
- </div>
119
-
120
- <div class="inspector-section">
121
- <h3 class="section-title" @click="toggleSection('triggerState')">
122
- <span class="toggle-icon">{{ expandedSections.triggerState ? '▼' : '▶' }}</span>
123
- Trigger State
124
- <span class="item-count">{{ Object.keys(store.triggerState || {}).length }}</span>
125
- </h3>
126
- <div v-if="expandedSections.triggerState" class="section-content">
127
- <div v-if="Object.keys(store.triggerState || {}).length === 0" class="empty-state">
128
- No trigger state defined
129
- </div>
130
- <div v-else class="property-list">
131
- <div
132
- v-for="(value, key) in store.triggerState"
133
- :key="key"
134
- class="property-item"
135
- @mouseenter="highlightElements('gxp-state', key)"
136
- @mouseleave="clearHighlight()"
137
- >
138
- <span class="property-key">{{ key }}</span>
139
- <span class="property-value" :class="getValueType(value)">
140
- {{ formatValue(value) }}
141
- </span>
142
- </div>
143
- </div>
144
- </div>
145
- </div>
146
-
147
- <div class="inspector-section">
148
- <h3 class="section-title" @click="toggleSection('dependencyList')">
149
- <span class="toggle-icon">{{ expandedSections.dependencyList ? '▼' : '▶' }}</span>
150
- Dependencies
151
- <span class="item-count">{{ getDependencyCount() }}</span>
152
- </h3>
153
- <div v-if="expandedSections.dependencyList" class="section-content">
154
- <div v-if="getDependencyCount() === 0" class="empty-state">
155
- No dependencies defined
156
- </div>
157
- <div v-else class="property-list">
158
- <div
159
- v-for="(value, key) in store.dependencyList"
160
- :key="key"
161
- class="property-item"
162
- >
163
- <span class="property-key">{{ key }}</span>
164
- <input
165
- v-if="editingKey === `dependencyList.${key}`"
166
- v-model="editValue"
167
- class="property-input"
168
- @blur="saveEdit('dependencyList', key)"
169
- @keydown.enter="saveEdit('dependencyList', key)"
170
- @keydown.escape="cancelEdit"
171
- />
172
- <span
173
- v-else
174
- class="property-value string"
175
- @dblclick="startEdit('dependencyList', key, value)"
176
- :title="'Double-click to edit'"
177
- >
178
- "{{ value }}"
179
- </span>
180
- </div>
181
- </div>
182
- </div>
183
- </div>
184
-
185
- <div class="inspector-actions">
186
- <button class="action-btn" @click="refreshStore" title="Refresh store data">
187
- Refresh
188
- </button>
189
- <button class="action-btn" @click="copyStoreToClipboard" title="Copy store state to clipboard">
190
- Copy JSON
191
- </button>
192
- </div>
193
- </div>
194
- </template>
195
-
196
- <script setup>
197
- import { ref, reactive, nextTick, onUnmounted } from 'vue';
198
-
199
- const props = defineProps({
200
- store: {
201
- type: Object,
202
- required: true
203
- }
204
- });
205
-
206
- // Element highlighting
207
- const highlightedElements = ref([]);
208
- const highlightOverlays = ref([]);
209
-
210
- const expandedSections = reactive({
211
- pluginVars: true,
212
- stringsList: false,
213
- assetList: false,
214
- triggerState: false,
215
- dependencyList: false
216
- });
217
-
218
- const editingKey = ref(null);
219
- const editValue = ref('');
220
-
221
- function toggleSection(section) {
222
- expandedSections[section] = !expandedSections[section];
223
- }
224
-
225
- function getValueType(value) {
226
- if (value === null) return 'null';
227
- if (value === undefined) return 'undefined';
228
- if (typeof value === 'boolean') return 'boolean';
229
- if (typeof value === 'number') return 'number';
230
- if (typeof value === 'string') return 'string';
231
- if (Array.isArray(value)) return 'array';
232
- if (typeof value === 'object') return 'object';
233
- return 'unknown';
234
- }
235
-
236
- function formatValue(value) {
237
- if (value === null) return 'null';
238
- if (value === undefined) return 'undefined';
239
- if (typeof value === 'boolean') return value ? 'true' : 'false';
240
- if (typeof value === 'number') return value.toString();
241
- if (typeof value === 'string') return `"${value}"`;
242
- if (Array.isArray(value)) return `Array(${value.length})`;
243
- if (typeof value === 'object') return `Object(${Object.keys(value).length})`;
244
- return String(value);
245
- }
246
-
247
- function isImageUrl(url) {
248
- if (typeof url !== 'string') return false;
249
- return /\.(jpg|jpeg|png|gif|webp|svg)(\?.*)?$/i.test(url);
250
- }
251
-
252
- function truncateUrl(url, maxLength = 50) {
253
- if (typeof url !== 'string') return url;
254
- if (url.length <= maxLength) return url;
255
- return url.substring(0, maxLength) + '...';
256
- }
257
-
258
- function getDependencyCount() {
259
- const deps = props.store.dependencyList;
260
- if (!deps) return 0;
261
- if (Array.isArray(deps)) return deps.length;
262
- return Object.keys(deps).length;
263
- }
264
-
265
- function startEdit(section, key, value) {
266
- editingKey.value = `${section}.${key}`;
267
- editValue.value = typeof value === 'string' ? value : JSON.stringify(value);
268
- nextTick(() => {
269
- const input = document.querySelector('.property-input');
270
- if (input) input.focus();
271
- });
272
- }
273
-
274
- function saveEdit(section, key) {
275
- if (editingKey.value && props.store[section]) {
276
- let newValue = editValue.value;
277
- // Try to parse as JSON for non-string values
278
- try {
279
- const parsed = JSON.parse(newValue);
280
- newValue = parsed;
281
- } catch {
282
- // Keep as string if not valid JSON
283
- }
284
-
285
- // Use the store's update methods to ensure Vue reactivity triggers properly
286
- // This will update any gxp-string/gxp-src directives that depend on these values
287
- if (section === 'stringsList' && typeof props.store.updateString === 'function') {
288
- props.store.updateString(key, newValue);
289
- } else if (section === 'pluginVars' && typeof props.store.updateSetting === 'function') {
290
- props.store.updateSetting(key, newValue);
291
- } else if (section === 'assetList' && typeof props.store.updateAsset === 'function') {
292
- props.store.updateAsset(key, newValue);
293
- } else if (section === 'triggerState' && typeof props.store.updateState === 'function') {
294
- props.store.updateState(key, newValue);
295
- } else {
296
- // Fallback for older stores without update methods
297
- props.store[section][key] = newValue;
298
- }
299
- console.log(`[DevTools] Updated ${section}.${key}:`, newValue);
300
- }
301
- cancelEdit();
302
- }
303
-
304
- function cancelEdit() {
305
- editingKey.value = null;
306
- editValue.value = '';
307
- }
308
-
309
- function refreshStore() {
310
- // Force reactivity update
311
- console.log('[DevTools] Store refreshed');
312
- }
313
-
314
- async function copyStoreToClipboard() {
315
- const storeData = {
316
- pluginVars: props.store.pluginVars,
317
- stringsList: props.store.stringsList,
318
- assetList: props.store.assetList,
319
- triggerState: props.store.triggerState,
320
- dependencyList: props.store.dependencyList
321
- };
322
-
323
- try {
324
- await navigator.clipboard.writeText(JSON.stringify(storeData, null, 2));
325
- console.log('[DevTools] Store data copied to clipboard');
326
- } catch (err) {
327
- console.error('[DevTools] Failed to copy:', err);
328
- }
329
- }
330
-
331
- /**
332
- * Element highlighting functions
333
- * Creates overlay boxes that highlight elements using gxp-* attributes
334
- */
335
-
336
- // CSS class name for our highlight overlay
337
- const HIGHLIGHT_CLASS = 'gxp-devtools-highlight-overlay';
338
-
339
- // Inject highlight styles into the document if not already present
340
- function ensureHighlightStyles() {
341
- if (document.getElementById('gxp-devtools-highlight-styles')) return;
342
-
343
- const style = document.createElement('style');
344
- style.id = 'gxp-devtools-highlight-styles';
345
- style.textContent = `
346
- .${HIGHLIGHT_CLASS} {
347
- position: fixed;
348
- pointer-events: none;
349
- z-index: 99998;
350
- background: rgba(97, 218, 251, 0.15);
351
- border: 2px solid #61dafb;
352
- border-radius: 4px;
353
- box-shadow: 0 0 10px rgba(97, 218, 251, 0.5), inset 0 0 10px rgba(97, 218, 251, 0.1);
354
- animation: gxp-highlight-pulse 1.5s ease-in-out infinite;
355
- }
356
- .${HIGHLIGHT_CLASS}::before {
357
- content: attr(data-gxp-key);
358
- position: absolute;
359
- top: -22px;
360
- left: -2px;
361
- background: #61dafb;
362
- color: #1e1e1e;
363
- font-size: 10px;
364
- font-weight: 600;
365
- padding: 2px 6px;
366
- border-radius: 3px 3px 0 0;
367
- font-family: 'SF Mono', Monaco, 'Courier New', monospace;
368
- white-space: nowrap;
369
- }
370
- @keyframes gxp-highlight-pulse {
371
- 0%, 100% { box-shadow: 0 0 10px rgba(97, 218, 251, 0.5), inset 0 0 10px rgba(97, 218, 251, 0.1); }
372
- 50% { box-shadow: 0 0 20px rgba(97, 218, 251, 0.8), inset 0 0 15px rgba(97, 218, 251, 0.2); }
373
- }
374
- `;
375
- document.head.appendChild(style);
376
- }
377
-
378
- // Find elements that match a gxp attribute and key
379
- function findMatchingElements(attribute, key) {
380
- const elements = [];
381
-
382
- // For stringsList, look for gxp-string attribute (without gxp-settings, gxp-assets, gxp-state)
383
- // For pluginVars (gxp-settings), look for gxp-string with gxp-settings modifier
384
- // For assetList (gxp-src), look for gxp-src attribute
385
- // For triggerState (gxp-state), look for gxp-string or gxp-src with gxp-state modifier
386
-
387
- if (attribute === 'gxp-string') {
388
- // Find elements with gxp-string="key" that don't have modifiers
389
- document.querySelectorAll(`[gxp-string="${key}"]`).forEach(el => {
390
- if (!el.hasAttribute('gxp-settings') && !el.hasAttribute('gxp-assets') && !el.hasAttribute('gxp-state')) {
391
- elements.push(el);
392
- }
393
- });
394
- } else if (attribute === 'gxp-settings') {
395
- // Find elements with gxp-string="key" AND gxp-settings attribute
396
- document.querySelectorAll(`[gxp-string="${key}"][gxp-settings]`).forEach(el => {
397
- elements.push(el);
398
- });
399
- } else if (attribute === 'gxp-src') {
400
- // Find elements with gxp-src="key" that don't have gxp-state modifier
401
- document.querySelectorAll(`[gxp-src="${key}"]`).forEach(el => {
402
- if (!el.hasAttribute('gxp-state')) {
403
- elements.push(el);
404
- }
405
- });
406
- // Also check for gxp-string with gxp-assets modifier
407
- document.querySelectorAll(`[gxp-string="${key}"][gxp-assets]`).forEach(el => {
408
- elements.push(el);
409
- });
410
- } else if (attribute === 'gxp-state') {
411
- // Find elements with gxp-state modifier on either gxp-string or gxp-src
412
- document.querySelectorAll(`[gxp-string="${key}"][gxp-state]`).forEach(el => {
413
- elements.push(el);
414
- });
415
- document.querySelectorAll(`[gxp-src="${key}"][gxp-state]`).forEach(el => {
416
- elements.push(el);
417
- });
418
- }
419
-
420
- return elements;
421
- }
422
-
423
- // Create overlay for an element
424
- function createOverlay(element, key) {
425
- const rect = element.getBoundingClientRect();
426
- const overlay = document.createElement('div');
427
- overlay.className = HIGHLIGHT_CLASS;
428
- overlay.setAttribute('data-gxp-key', key);
429
- overlay.style.top = `${rect.top}px`;
430
- overlay.style.left = `${rect.left}px`;
431
- overlay.style.width = `${rect.width}px`;
432
- overlay.style.height = `${rect.height}px`;
433
- document.body.appendChild(overlay);
434
- return overlay;
435
- }
436
-
437
- // Highlight elements matching a key
438
- function highlightElements(attribute, key) {
439
- ensureHighlightStyles();
440
- clearHighlight();
441
-
442
- const elements = findMatchingElements(attribute, key);
443
- highlightedElements.value = elements;
444
-
445
- elements.forEach(el => {
446
- const overlay = createOverlay(el, key);
447
- highlightOverlays.value.push(overlay);
448
- });
449
-
450
- if (elements.length > 0) {
451
- console.log(`[DevTools] Highlighting ${elements.length} element(s) with ${attribute}="${key}"`);
452
- }
453
- }
454
-
455
- // Clear all highlight overlays
456
- function clearHighlight() {
457
- highlightOverlays.value.forEach(overlay => {
458
- if (overlay && overlay.parentNode) {
459
- overlay.parentNode.removeChild(overlay);
460
- }
461
- });
462
- highlightOverlays.value = [];
463
- highlightedElements.value = [];
464
- }
465
-
466
- // Clean up on unmount
467
- onUnmounted(() => {
468
- clearHighlight();
469
- });
470
- </script>
471
-
472
- <style scoped>
473
- .store-inspector {
474
- display: flex;
475
- flex-direction: column;
476
- gap: 8px;
477
- }
478
-
479
- .inspector-section {
480
- background: #2d2d2d;
481
- border-radius: 6px;
482
- overflow: hidden;
483
- }
484
-
485
- .section-title {
486
- display: flex;
487
- align-items: center;
488
- gap: 8px;
489
- margin: 0;
490
- padding: 10px 12px;
491
- font-size: 13px;
492
- font-weight: 500;
493
- cursor: pointer;
494
- user-select: none;
495
- transition: background 0.2s;
496
- }
497
-
498
- .section-title:hover {
499
- background: #3d3d3d;
500
- }
501
-
502
- .toggle-icon {
503
- font-size: 10px;
504
- color: #888;
505
- width: 12px;
506
- }
507
-
508
- .item-count {
509
- margin-left: auto;
510
- background: #3d3d3d;
511
- padding: 2px 8px;
512
- border-radius: 10px;
513
- font-size: 11px;
514
- color: #888;
515
- }
516
-
517
- .section-content {
518
- padding: 8px 12px 12px;
519
- border-top: 1px solid #3d3d3d;
520
- }
521
-
522
- .empty-state {
523
- color: #666;
524
- font-size: 12px;
525
- font-style: italic;
526
- padding: 8px 0;
527
- }
528
-
529
- .property-list {
530
- display: flex;
531
- flex-direction: column;
532
- gap: 6px;
533
- }
534
-
535
- .property-item {
536
- display: flex;
537
- align-items: flex-start;
538
- gap: 8px;
539
- font-size: 12px;
540
- font-family: 'SF Mono', Monaco, 'Courier New', monospace;
541
- }
542
-
543
- .property-key {
544
- color: #9cdcfe;
545
- min-width: 140px;
546
- flex-shrink: 0;
547
- }
548
-
549
- .property-key::after {
550
- content: ':';
551
- color: #888;
552
- }
553
-
554
- .property-value {
555
- word-break: break-all;
556
- cursor: pointer;
557
- padding: 2px 4px;
558
- border-radius: 3px;
559
- transition: background 0.2s;
560
- }
561
-
562
- .property-value:hover {
563
- background: #3d3d3d;
564
- }
565
-
566
- .property-value.string {
567
- color: #ce9178;
568
- }
569
-
570
- .property-value.number {
571
- color: #b5cea8;
572
- }
573
-
574
- .property-value.boolean {
575
- color: #569cd6;
576
- }
577
-
578
- .property-value.null,
579
- .property-value.undefined {
580
- color: #808080;
581
- font-style: italic;
582
- }
583
-
584
- .property-value.object,
585
- .property-value.array {
586
- color: #dcdcaa;
587
- }
588
-
589
- .property-input {
590
- flex: 1;
591
- background: #3d3d3d;
592
- border: 1px solid #61dafb;
593
- color: #e0e0e0;
594
- padding: 4px 8px;
595
- border-radius: 3px;
596
- font-family: inherit;
597
- font-size: 12px;
598
- outline: none;
599
- }
600
-
601
- .asset-item {
602
- flex-direction: column;
603
- gap: 4px;
604
- }
605
-
606
- .asset-preview {
607
- display: flex;
608
- align-items: center;
609
- gap: 8px;
610
- padding-left: 148px;
611
- }
612
-
613
- .asset-thumbnail {
614
- width: 32px;
615
- height: 32px;
616
- object-fit: cover;
617
- border-radius: 4px;
618
- background: #3d3d3d;
619
- }
620
-
621
- .inspector-actions {
622
- display: flex;
623
- gap: 8px;
624
- margin-top: 12px;
625
- padding-top: 12px;
626
- border-top: 1px solid #3d3d3d;
627
- }
628
-
629
- .action-btn {
630
- background: #3d3d3d;
631
- border: none;
632
- color: #e0e0e0;
633
- padding: 8px 16px;
634
- border-radius: 4px;
635
- cursor: pointer;
636
- font-size: 12px;
637
- transition: all 0.2s;
638
- }
639
-
640
- .action-btn:hover {
641
- background: #4d4d4d;
642
- color: #61dafb;
643
- }
644
- </style>
@@ -1,6 +0,0 @@
1
- // GxP Dev Tools Components
2
- export { default as DevToolsModal } from './DevToolsModal.vue';
3
- export { default as StoreInspector } from './StoreInspector.vue';
4
- export { default as LayoutSwitcher } from './LayoutSwitcher.vue';
5
- export { default as SocketSimulator } from './SocketSimulator.vue';
6
- export { default as MockDataEditor } from './MockDataEditor.vue';