@promakeai/inspector 1.0.0 → 1.0.3

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 (204) hide show
  1. package/README.md +111 -0
  2. package/dist/App.d.ts.map +1 -0
  3. package/dist/__tests__/App.test.d.ts.map +1 -0
  4. package/dist/components/Badge.d.ts.map +1 -0
  5. package/dist/components/ControlBox/ContentArea.d.ts.map +1 -0
  6. package/dist/components/ControlBox/PromptInput.d.ts.map +1 -0
  7. package/dist/components/ControlBox/index.d.ts.map +1 -0
  8. package/dist/components/ImageEditor/UploadBox.d.ts.map +1 -0
  9. package/dist/components/ImageEditor/index.d.ts.map +1 -0
  10. package/dist/components/Overlay.d.ts.map +1 -0
  11. package/dist/components/StyleEditor/BorderSection.d.ts.map +1 -0
  12. package/dist/components/StyleEditor/ColorPicker.d.ts.map +1 -0
  13. package/dist/components/StyleEditor/DisplaySection.d.ts.map +1 -0
  14. package/dist/components/StyleEditor/ImageSection.d.ts.map +1 -0
  15. package/dist/components/StyleEditor/LayoutSection.d.ts.map +1 -0
  16. package/dist/components/StyleEditor/NumberInput.d.ts.map +1 -0
  17. package/dist/components/StyleEditor/SliderInput.d.ts.map +1 -0
  18. package/dist/components/StyleEditor/SpacingSection.d.ts.map +1 -0
  19. package/dist/components/StyleEditor/TextSection.d.ts.map +1 -0
  20. package/dist/components/StyleEditor/index.d.ts.map +1 -0
  21. package/dist/components/TextEditor/index.d.ts.map +1 -0
  22. package/dist/components/ui/CustomCollapsible.d.ts.map +1 -0
  23. package/dist/components/ui/button.d.ts.map +1 -0
  24. package/dist/components/ui/color-picker.d.ts.map +1 -0
  25. package/dist/components/ui/input.d.ts.map +1 -0
  26. package/dist/components/ui/popover.d.ts.map +1 -0
  27. package/dist/components/ui/select.d.ts.map +1 -0
  28. package/dist/components/ui/slider.d.ts.map +1 -0
  29. package/dist/components/ui/textarea.d.ts.map +1 -0
  30. package/dist/components/ui/tooltip.d.ts.map +1 -0
  31. package/dist/core/highlighter.d.ts.map +1 -0
  32. package/dist/hooks/useMessageBridge.d.ts.map +1 -0
  33. package/dist/hooks/useStylePreview.d.ts.map +1 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/lib/utils.d.ts.map +1 -0
  36. package/dist/plugin.d.ts.map +1 -0
  37. package/dist/store/useInspectorStore.d.ts.map +1 -0
  38. package/dist/styles.d.ts.map +1 -0
  39. package/dist/utils/colorUtils.d.ts.map +1 -0
  40. package/dist/utils/elementNames.d.ts.map +1 -0
  41. package/dist/utils/elementUtils.d.ts.map +1 -0
  42. package/dist/utils/errorTracker.d.ts.map +1 -0
  43. package/dist/utils/inputStyles.d.ts.map +1 -0
  44. package/dist/utils/styleUtils.d.ts.map +1 -0
  45. package/dist/utils/tailwindMapper.d.ts.map +1 -0
  46. package/dist/utils/urlTracker.d.ts.map +1 -0
  47. package/package.json +15 -10
  48. package/dist/packages/inspector/src/App.d.ts.map +0 -1
  49. package/dist/packages/inspector/src/__tests__/App.test.d.ts.map +0 -1
  50. package/dist/packages/inspector/src/components/Badge.d.ts.map +0 -1
  51. package/dist/packages/inspector/src/components/ControlBox/ContentArea.d.ts.map +0 -1
  52. package/dist/packages/inspector/src/components/ControlBox/PromptInput.d.ts.map +0 -1
  53. package/dist/packages/inspector/src/components/ControlBox/index.d.ts.map +0 -1
  54. package/dist/packages/inspector/src/components/ImageEditor/UploadBox.d.ts.map +0 -1
  55. package/dist/packages/inspector/src/components/ImageEditor/index.d.ts.map +0 -1
  56. package/dist/packages/inspector/src/components/Overlay.d.ts.map +0 -1
  57. package/dist/packages/inspector/src/components/StyleEditor/BorderSection.d.ts.map +0 -1
  58. package/dist/packages/inspector/src/components/StyleEditor/ColorPicker.d.ts.map +0 -1
  59. package/dist/packages/inspector/src/components/StyleEditor/DisplaySection.d.ts.map +0 -1
  60. package/dist/packages/inspector/src/components/StyleEditor/ImageSection.d.ts.map +0 -1
  61. package/dist/packages/inspector/src/components/StyleEditor/LayoutSection.d.ts.map +0 -1
  62. package/dist/packages/inspector/src/components/StyleEditor/NumberInput.d.ts.map +0 -1
  63. package/dist/packages/inspector/src/components/StyleEditor/SliderInput.d.ts.map +0 -1
  64. package/dist/packages/inspector/src/components/StyleEditor/SpacingSection.d.ts.map +0 -1
  65. package/dist/packages/inspector/src/components/StyleEditor/TextSection.d.ts.map +0 -1
  66. package/dist/packages/inspector/src/components/StyleEditor/index.d.ts.map +0 -1
  67. package/dist/packages/inspector/src/components/TextEditor/index.d.ts.map +0 -1
  68. package/dist/packages/inspector/src/components/ui/CustomCollapsible.d.ts.map +0 -1
  69. package/dist/packages/inspector/src/components/ui/button.d.ts.map +0 -1
  70. package/dist/packages/inspector/src/components/ui/color-picker.d.ts.map +0 -1
  71. package/dist/packages/inspector/src/components/ui/input.d.ts.map +0 -1
  72. package/dist/packages/inspector/src/components/ui/popover.d.ts.map +0 -1
  73. package/dist/packages/inspector/src/components/ui/select.d.ts.map +0 -1
  74. package/dist/packages/inspector/src/components/ui/slider.d.ts.map +0 -1
  75. package/dist/packages/inspector/src/components/ui/textarea.d.ts.map +0 -1
  76. package/dist/packages/inspector/src/components/ui/tooltip.d.ts.map +0 -1
  77. package/dist/packages/inspector/src/core/highlighter.d.ts.map +0 -1
  78. package/dist/packages/inspector/src/hooks/useMessageBridge.d.ts.map +0 -1
  79. package/dist/packages/inspector/src/hooks/useStylePreview.d.ts.map +0 -1
  80. package/dist/packages/inspector/src/index.d.ts.map +0 -1
  81. package/dist/packages/inspector/src/lib/utils.d.ts.map +0 -1
  82. package/dist/packages/inspector/src/plugin.d.ts.map +0 -1
  83. package/dist/packages/inspector/src/store/useInspectorStore.d.ts.map +0 -1
  84. package/dist/packages/inspector/src/styles.d.ts.map +0 -1
  85. package/dist/packages/inspector/src/utils/colorUtils.d.ts.map +0 -1
  86. package/dist/packages/inspector/src/utils/elementNames.d.ts.map +0 -1
  87. package/dist/packages/inspector/src/utils/elementUtils.d.ts.map +0 -1
  88. package/dist/packages/inspector/src/utils/errorTracker.d.ts.map +0 -1
  89. package/dist/packages/inspector/src/utils/inputStyles.d.ts.map +0 -1
  90. package/dist/packages/inspector/src/utils/styleUtils.d.ts.map +0 -1
  91. package/dist/packages/inspector/src/utils/tailwindMapper.d.ts.map +0 -1
  92. package/dist/packages/inspector/src/utils/urlTracker.d.ts.map +0 -1
  93. package/dist/packages/inspector/tsconfig.tsbuildinfo +0 -1
  94. package/src/App.tsx +0 -912
  95. package/src/__tests__/App.test.tsx +0 -373
  96. package/src/assets/fonts/Satoshi-Variable.woff +0 -0
  97. package/src/assets/fonts/Satoshi-Variable.woff2 +0 -0
  98. package/src/components/Badge.tsx +0 -118
  99. package/src/components/ControlBox/ContentArea.tsx +0 -13
  100. package/src/components/ControlBox/PromptInput.module.css +0 -66
  101. package/src/components/ControlBox/PromptInput.tsx +0 -104
  102. package/src/components/ControlBox/index.module.css +0 -81
  103. package/src/components/ControlBox/index.tsx +0 -409
  104. package/src/components/ImageEditor/UploadBox.module.css +0 -69
  105. package/src/components/ImageEditor/UploadBox.tsx +0 -113
  106. package/src/components/ImageEditor/index.module.css +0 -11
  107. package/src/components/ImageEditor/index.tsx +0 -84
  108. package/src/components/Overlay.tsx +0 -157
  109. package/src/components/StyleEditor/BorderSection.tsx +0 -147
  110. package/src/components/StyleEditor/ColorPicker.tsx +0 -182
  111. package/src/components/StyleEditor/DisplaySection.tsx +0 -349
  112. package/src/components/StyleEditor/ImageSection.tsx +0 -105
  113. package/src/components/StyleEditor/LayoutSection.tsx +0 -63
  114. package/src/components/StyleEditor/NumberInput.tsx +0 -138
  115. package/src/components/StyleEditor/SliderInput.tsx +0 -121
  116. package/src/components/StyleEditor/SpacingSection.tsx +0 -365
  117. package/src/components/StyleEditor/TextSection.tsx +0 -381
  118. package/src/components/StyleEditor/index.module.css +0 -133
  119. package/src/components/StyleEditor/index.tsx +0 -612
  120. package/src/components/StyleEditor/shared.module.css +0 -193
  121. package/src/components/TextEditor/index.module.css +0 -31
  122. package/src/components/TextEditor/index.tsx +0 -166
  123. package/src/components/ui/CustomCollapsible.tsx +0 -159
  124. package/src/components/ui/button.module.css +0 -141
  125. package/src/components/ui/button.tsx +0 -73
  126. package/src/components/ui/color-picker.module.css +0 -112
  127. package/src/components/ui/color-picker.tsx +0 -146
  128. package/src/components/ui/input.module.css +0 -49
  129. package/src/components/ui/input.tsx +0 -34
  130. package/src/components/ui/popover.module.css +0 -42
  131. package/src/components/ui/popover.tsx +0 -59
  132. package/src/components/ui/select.module.css +0 -160
  133. package/src/components/ui/select.tsx +0 -216
  134. package/src/components/ui/slider.module.css +0 -75
  135. package/src/components/ui/slider.tsx +0 -60
  136. package/src/components/ui/textarea.module.css +0 -30
  137. package/src/components/ui/textarea.tsx +0 -23
  138. package/src/components/ui/tooltip.module.css +0 -11
  139. package/src/components/ui/tooltip.tsx +0 -37
  140. package/src/core/highlighter.ts +0 -197
  141. package/src/hooks/useMessageBridge.ts +0 -49
  142. package/src/hooks/useStylePreview.ts +0 -332
  143. package/src/index.ts +0 -20
  144. package/src/lib/utils.ts +0 -5
  145. package/src/plugin.ts +0 -11
  146. package/src/store/useInspectorStore.ts +0 -235
  147. package/src/styles/fonts.css +0 -15
  148. package/src/styles/global.css +0 -138
  149. package/src/styles/variables.css +0 -151
  150. package/src/styles.ts +0 -5
  151. package/src/utils/colorUtils.ts +0 -133
  152. package/src/utils/elementNames.ts +0 -103
  153. package/src/utils/elementUtils.ts +0 -90
  154. package/src/utils/errorTracker.ts +0 -186
  155. package/src/utils/inputStyles.ts +0 -30
  156. package/src/utils/styleUtils.ts +0 -226
  157. package/src/utils/tailwindMapper.ts +0 -554
  158. package/src/utils/urlTracker.ts +0 -75
  159. package/src/vite-env.d.ts +0 -7
  160. /package/dist/{packages/inspector/src/App.d.ts → App.d.ts} +0 -0
  161. /package/dist/{packages/inspector/src/__tests__ → __tests__}/App.test.d.ts +0 -0
  162. /package/dist/{packages/inspector/src/components → components}/Badge.d.ts +0 -0
  163. /package/dist/{packages/inspector/src/components → components}/ControlBox/ContentArea.d.ts +0 -0
  164. /package/dist/{packages/inspector/src/components → components}/ControlBox/PromptInput.d.ts +0 -0
  165. /package/dist/{packages/inspector/src/components → components}/ControlBox/index.d.ts +0 -0
  166. /package/dist/{packages/inspector/src/components → components}/ImageEditor/UploadBox.d.ts +0 -0
  167. /package/dist/{packages/inspector/src/components → components}/ImageEditor/index.d.ts +0 -0
  168. /package/dist/{packages/inspector/src/components → components}/Overlay.d.ts +0 -0
  169. /package/dist/{packages/inspector/src/components → components}/StyleEditor/BorderSection.d.ts +0 -0
  170. /package/dist/{packages/inspector/src/components → components}/StyleEditor/ColorPicker.d.ts +0 -0
  171. /package/dist/{packages/inspector/src/components → components}/StyleEditor/DisplaySection.d.ts +0 -0
  172. /package/dist/{packages/inspector/src/components → components}/StyleEditor/ImageSection.d.ts +0 -0
  173. /package/dist/{packages/inspector/src/components → components}/StyleEditor/LayoutSection.d.ts +0 -0
  174. /package/dist/{packages/inspector/src/components → components}/StyleEditor/NumberInput.d.ts +0 -0
  175. /package/dist/{packages/inspector/src/components → components}/StyleEditor/SliderInput.d.ts +0 -0
  176. /package/dist/{packages/inspector/src/components → components}/StyleEditor/SpacingSection.d.ts +0 -0
  177. /package/dist/{packages/inspector/src/components → components}/StyleEditor/TextSection.d.ts +0 -0
  178. /package/dist/{packages/inspector/src/components → components}/StyleEditor/index.d.ts +0 -0
  179. /package/dist/{packages/inspector/src/components → components}/TextEditor/index.d.ts +0 -0
  180. /package/dist/{packages/inspector/src/components → components}/ui/CustomCollapsible.d.ts +0 -0
  181. /package/dist/{packages/inspector/src/components → components}/ui/button.d.ts +0 -0
  182. /package/dist/{packages/inspector/src/components → components}/ui/color-picker.d.ts +0 -0
  183. /package/dist/{packages/inspector/src/components → components}/ui/input.d.ts +0 -0
  184. /package/dist/{packages/inspector/src/components → components}/ui/popover.d.ts +0 -0
  185. /package/dist/{packages/inspector/src/components → components}/ui/select.d.ts +0 -0
  186. /package/dist/{packages/inspector/src/components → components}/ui/slider.d.ts +0 -0
  187. /package/dist/{packages/inspector/src/components → components}/ui/textarea.d.ts +0 -0
  188. /package/dist/{packages/inspector/src/components → components}/ui/tooltip.d.ts +0 -0
  189. /package/dist/{packages/inspector/src/core → core}/highlighter.d.ts +0 -0
  190. /package/dist/{packages/inspector/src/hooks → hooks}/useMessageBridge.d.ts +0 -0
  191. /package/dist/{packages/inspector/src/hooks → hooks}/useStylePreview.d.ts +0 -0
  192. /package/dist/{packages/inspector/src/index.d.ts → index.d.ts} +0 -0
  193. /package/dist/{packages/inspector/src/lib → lib}/utils.d.ts +0 -0
  194. /package/dist/{packages/inspector/src/plugin.d.ts → plugin.d.ts} +0 -0
  195. /package/dist/{packages/inspector/src/store → store}/useInspectorStore.d.ts +0 -0
  196. /package/dist/{packages/inspector/src/styles.d.ts → styles.d.ts} +0 -0
  197. /package/dist/{packages/inspector/src/utils → utils}/colorUtils.d.ts +0 -0
  198. /package/dist/{packages/inspector/src/utils → utils}/elementNames.d.ts +0 -0
  199. /package/dist/{packages/inspector/src/utils → utils}/elementUtils.d.ts +0 -0
  200. /package/dist/{packages/inspector/src/utils → utils}/errorTracker.d.ts +0 -0
  201. /package/dist/{packages/inspector/src/utils → utils}/inputStyles.d.ts +0 -0
  202. /package/dist/{packages/inspector/src/utils → utils}/styleUtils.d.ts +0 -0
  203. /package/dist/{packages/inspector/src/utils → utils}/tailwindMapper.d.ts +0 -0
  204. /package/dist/{packages/inspector/src/utils → utils}/urlTracker.d.ts +0 -0
@@ -1,373 +0,0 @@
1
- /**
2
- * Unit tests for element stack feature
3
- */
4
-
5
- import { describe, it, expect, beforeEach, vi } from 'vitest';
6
- import { render, screen, fireEvent } from '@testing-library/react';
7
- import '@testing-library/jest-dom';
8
-
9
- describe('Element Stack Feature', () => {
10
- describe('getElementsAtPoint', () => {
11
- beforeEach(() => {
12
- document.body.innerHTML = '';
13
- });
14
-
15
- it('should return clicked element as first item', () => {
16
- // Create test DOM structure
17
- const container = document.createElement('div');
18
- container.setAttribute('data-testid', 'container');
19
- container.style.width = '200px';
20
- container.style.height = '200px';
21
- document.body.appendChild(container);
22
-
23
- // Test that we can get the element
24
- const result = document.body.querySelector('[data-testid="container"]');
25
-
26
- expect(result).toBe(container);
27
- expect(result?.getAttribute('data-testid')).toBe('container');
28
- });
29
-
30
- it('should collect meaningful children with data-dev-id', () => {
31
- // Create nested structure with data-dev-id
32
- const parent = document.createElement('div');
33
- parent.setAttribute('data-testid', 'parent');
34
-
35
- const childWithDevId = document.createElement('div');
36
- childWithDevId.setAttribute('data-dev-id', 'src/Component.tsx:10:5');
37
- childWithDevId.setAttribute('data-testid', 'child-with-id');
38
- childWithDevId.textContent = 'Component';
39
-
40
- const childWithoutDevId = document.createElement('div');
41
- childWithoutDevId.setAttribute('data-testid', 'child-without-id');
42
- childWithoutDevId.textContent = 'Regular div';
43
-
44
- parent.appendChild(childWithDevId);
45
- parent.appendChild(childWithoutDevId);
46
- document.body.appendChild(parent);
47
-
48
- // Verify structure
49
- expect(parent.children.length).toBe(2);
50
- expect(childWithDevId.hasAttribute('data-dev-id')).toBe(true);
51
- expect(childWithoutDevId.hasAttribute('data-dev-id')).toBe(false);
52
- });
53
-
54
- it('should filter out SVG elements', () => {
55
- const container = document.createElement('div');
56
-
57
- const svgElement = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
58
- svgElement.setAttribute('data-testid', 'svg-element');
59
-
60
- const pathElement = document.createElementNS('http://www.w3.org/2000/svg', 'path');
61
- pathElement.setAttribute('data-testid', 'path-element');
62
-
63
- svgElement.appendChild(pathElement);
64
- container.appendChild(svgElement);
65
- document.body.appendChild(container);
66
-
67
- // Verify SVG elements are identified correctly
68
- expect(svgElement instanceof SVGElement).toBe(true);
69
- expect(pathElement instanceof SVGElement).toBe(true);
70
- expect(container instanceof HTMLElement).toBe(true);
71
- });
72
-
73
- it('should collect interactive elements (button, input, img)', () => {
74
- const container = document.createElement('div');
75
-
76
- const button = document.createElement('button');
77
- button.setAttribute('data-testid', 'button');
78
- button.textContent = 'Click me';
79
-
80
- const input = document.createElement('input');
81
- input.setAttribute('data-testid', 'input');
82
-
83
- const img = document.createElement('img');
84
- img.setAttribute('data-testid', 'image');
85
- img.src = 'test.jpg';
86
-
87
- container.appendChild(button);
88
- container.appendChild(input);
89
- container.appendChild(img);
90
- document.body.appendChild(container);
91
-
92
- // Verify interactive elements
93
- expect(button.tagName).toBe('BUTTON');
94
- expect(input.tagName).toBe('INPUT');
95
- expect(img.tagName).toBe('IMG');
96
- });
97
-
98
- it('should go 3 levels deep recursively', () => {
99
- // Create 4-level deep structure
100
- const level1 = document.createElement('div');
101
- level1.setAttribute('data-testid', 'level-1');
102
- level1.textContent = 'Level 1';
103
-
104
- const level2 = document.createElement('div');
105
- level2.setAttribute('data-testid', 'level-2');
106
- level2.textContent = 'Level 2';
107
-
108
- const level3 = document.createElement('div');
109
- level3.setAttribute('data-testid', 'level-3');
110
- level3.textContent = 'Level 3';
111
-
112
- const level4 = document.createElement('div');
113
- level4.setAttribute('data-testid', 'level-4');
114
- level4.textContent = 'Level 4';
115
-
116
- level3.appendChild(level4);
117
- level2.appendChild(level3);
118
- level1.appendChild(level2);
119
- document.body.appendChild(level1);
120
-
121
- // Verify nesting
122
- expect(level1.querySelector('[data-testid="level-2"]')).toBe(level2);
123
- expect(level1.querySelector('[data-testid="level-3"]')).toBe(level3);
124
- expect(level1.querySelector('[data-testid="level-4"]')).toBe(level4);
125
- });
126
-
127
- it('should prioritize elements with data-dev-id', () => {
128
- const container = document.createElement('div');
129
-
130
- const regularDiv = document.createElement('div');
131
- regularDiv.setAttribute('data-testid', 'regular');
132
- regularDiv.textContent = 'Regular';
133
-
134
- const componentDiv = document.createElement('div');
135
- componentDiv.setAttribute('data-testid', 'component');
136
- componentDiv.setAttribute('data-dev-id', 'src/Component.tsx:5:10');
137
- componentDiv.textContent = 'Component';
138
-
139
- container.appendChild(regularDiv);
140
- container.appendChild(componentDiv);
141
- document.body.appendChild(container);
142
-
143
- // Get all children with data-dev-id
144
- const childrenWithDevId = Array.from(container.children).filter(
145
- (c) => c.hasAttribute('data-dev-id')
146
- );
147
- const childrenWithoutDevId = Array.from(container.children).filter(
148
- (c) => !c.hasAttribute('data-dev-id')
149
- );
150
-
151
- // Verify prioritization logic
152
- expect(childrenWithDevId.length).toBe(1);
153
- expect(childrenWithoutDevId.length).toBe(1);
154
- expect(childrenWithDevId[0]).toBe(componentDiv);
155
- });
156
- });
157
-
158
- describe('Element Stack Button Rendering', () => {
159
- it('should show buttons only when stack length > 1', () => {
160
- const singleElementStack: HTMLElement[] = [document.createElement('div')];
161
- const multiElementStack: HTMLElement[] = [
162
- document.createElement('div'),
163
- document.createElement('span'),
164
- ];
165
-
166
- expect(singleElementStack.length).toBe(1);
167
- expect(singleElementStack.length > 1).toBe(false);
168
-
169
- expect(multiElementStack.length).toBe(2);
170
- expect(multiElementStack.length > 1).toBe(true);
171
- });
172
-
173
- it('should identify selected element correctly', () => {
174
- const element1 = document.createElement('div');
175
- const element2 = document.createElement('span');
176
- const selectedElement = element1;
177
-
178
- expect(element1 === selectedElement).toBe(true);
179
- expect(element2 === selectedElement).toBe(false);
180
- });
181
-
182
- it('should apply correct styles based on selection', () => {
183
- const selectedColor = 'rgb(58, 18, 189)';
184
- const unselectedColor = '#ffffff';
185
-
186
- const isSelected = true;
187
- const isNotSelected = false;
188
-
189
- expect(isSelected ? selectedColor : unselectedColor).toBe(selectedColor);
190
- expect(isNotSelected ? selectedColor : unselectedColor).toBe(unselectedColor);
191
- });
192
- });
193
-
194
- describe('Element Name Utilities', () => {
195
- it('should map common HTML tags to user-friendly names', () => {
196
- const tagToName: Record<string, string> = {
197
- div: 'Container',
198
- span: 'Text',
199
- img: 'Image',
200
- button: 'Button',
201
- a: 'Link',
202
- input: 'Input',
203
- textarea: 'TextArea',
204
- h1: 'Heading',
205
- p: 'Paragraph',
206
- section: 'Section',
207
- };
208
-
209
- Object.entries(tagToName).forEach(([tag, name]) => {
210
- expect(tagToName[tag]).toBe(name);
211
- });
212
- });
213
-
214
- it('should format element labels correctly', () => {
215
- const formatLabel = (displayName: string, tagName: string) => {
216
- return `${displayName} (${tagName.toLowerCase()})`;
217
- };
218
-
219
- expect(formatLabel('Container', 'DIV')).toBe('Container (div)');
220
- expect(formatLabel('Button', 'BUTTON')).toBe('Button (button)');
221
- expect(formatLabel('Image', 'IMG')).toBe('Image (img)');
222
- });
223
-
224
- it('should handle missing labels gracefully', () => {
225
- const getLabel = (key: string, labels?: Record<string, string>, defaultValue?: string) => {
226
- return labels?.[key] || defaultValue || 'Element';
227
- };
228
-
229
- expect(getLabel('elementContainer', undefined, 'Container')).toBe('Container');
230
- expect(getLabel('elementContainer', {}, 'Container')).toBe('Container');
231
- expect(getLabel('elementContainer', { elementContainer: 'Custom' }, 'Container')).toBe('Custom');
232
- });
233
- });
234
-
235
- describe('Element Selection from Stack', () => {
236
- it('should update selected element when button is clicked', () => {
237
- const element1 = document.createElement('div');
238
- const element2 = document.createElement('span');
239
-
240
- let selectedElement: HTMLElement | null = element1;
241
-
242
- const selectElement = (el: HTMLElement) => {
243
- selectedElement = el;
244
- };
245
-
246
- selectElement(element2);
247
- expect(selectedElement).toBe(element2);
248
- });
249
-
250
- it('should generate element data for selected element', () => {
251
- const element = document.createElement('div');
252
- element.setAttribute('data-dev-id', 'src/Component.tsx:10:5');
253
- element.textContent = 'Test content';
254
- element.className = 'test-class';
255
-
256
- const elementData = {
257
- id: element.getAttribute('data-dev-id'),
258
- tagName: element.tagName,
259
- className: element.className,
260
- textContent: element.textContent?.trim(),
261
- };
262
-
263
- expect(elementData.id).toBe('src/Component.tsx:10:5');
264
- expect(elementData.tagName).toBe('DIV');
265
- expect(elementData.className).toBe('test-class');
266
- expect(elementData.textContent).toBe('Test content');
267
- });
268
-
269
- it('should handle element selection message', () => {
270
- const mockSendMessage = vi.fn();
271
-
272
- const element = document.createElement('div');
273
- const elementData = {
274
- id: 'test-id',
275
- tagName: 'DIV',
276
- };
277
-
278
- mockSendMessage('INSPECTOR_ELEMENT_SELECTED', elementData);
279
-
280
- expect(mockSendMessage).toHaveBeenCalledWith('INSPECTOR_ELEMENT_SELECTED', elementData);
281
- expect(mockSendMessage).toHaveBeenCalledTimes(1);
282
- });
283
- });
284
-
285
- describe('SVG Element Handling', () => {
286
- it('should find HTML parent when SVG is clicked', () => {
287
- const button = document.createElement('button');
288
- const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
289
- const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
290
-
291
- svg.appendChild(path);
292
- button.appendChild(svg);
293
- document.body.appendChild(button);
294
-
295
- // Simulate finding parent
296
- let target: Element | null = path;
297
- while (target && target instanceof SVGElement) {
298
- target = target.parentElement;
299
- }
300
-
301
- expect(target).toBe(button);
302
- expect(target instanceof HTMLElement).toBe(true);
303
- });
304
-
305
- it('should skip SVG elements in child collection', () => {
306
- const container = document.createElement('div');
307
- const div = document.createElement('div');
308
- const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
309
-
310
- container.appendChild(div);
311
- container.appendChild(svg);
312
-
313
- const htmlChildren = Array.from(container.children).filter(
314
- (child) => child instanceof HTMLElement && !(child instanceof SVGElement)
315
- );
316
-
317
- expect(htmlChildren.length).toBe(1);
318
- expect(htmlChildren[0]).toBe(div);
319
- });
320
- });
321
-
322
- describe('Meaningful Element Detection', () => {
323
- it('should detect elements with data-dev-id as meaningful', () => {
324
- const element = document.createElement('div');
325
- element.setAttribute('data-dev-id', 'src/Component.tsx:5:10');
326
-
327
- expect(element.hasAttribute('data-dev-id')).toBe(true);
328
- });
329
-
330
- it('should detect elements with dimensions as meaningful', () => {
331
- const element = document.createElement('div');
332
- element.style.width = '100px';
333
- element.style.height = '100px';
334
- element.style.position = 'absolute';
335
- element.style.top = '0';
336
- element.style.left = '0';
337
- document.body.appendChild(element);
338
-
339
- const rect = element.getBoundingClientRect();
340
- const hasDimensions = rect.width > 0 && rect.height > 0;
341
-
342
- // In happy-dom, getBoundingClientRect may not work perfectly, so we check the style
343
- const hasStyleDimensions = element.style.width === '100px' && element.style.height === '100px';
344
-
345
- expect(hasDimensions || hasStyleDimensions).toBe(true);
346
- document.body.removeChild(element);
347
- });
348
-
349
- it('should detect elements with children as meaningful', () => {
350
- const parent = document.createElement('div');
351
- const child = document.createElement('span');
352
- parent.appendChild(child);
353
-
354
- expect(parent.children.length > 0).toBe(true);
355
- });
356
-
357
- it('should detect elements with text as meaningful', () => {
358
- const element = document.createElement('div');
359
- element.textContent = 'Some text content';
360
-
361
- expect(element.textContent && element.textContent.trim().length > 0).toBe(true);
362
- });
363
-
364
- it('should detect interactive elements as meaningful', () => {
365
- const interactiveTags = ['BUTTON', 'A', 'INPUT', 'IMG', 'VIDEO', 'SELECT', 'TEXTAREA'];
366
-
367
- interactiveTags.forEach((tag) => {
368
- expect(interactiveTags.includes(tag)).toBe(true);
369
- });
370
- });
371
- });
372
- });
373
-
@@ -1,118 +0,0 @@
1
- /**
2
- * Badge component - "Built by Promake" badge
3
- */
4
-
5
- import { useState } from "react";
6
- import { useInspectorStore } from "../store/useInspectorStore";
7
-
8
- interface BadgeProps {
9
- visible: boolean;
10
- }
11
-
12
- export function Badge({ visible }: BadgeProps) {
13
- const { theme, labels } = useInspectorStore();
14
- const [isHovered, setIsHovered] = useState(false);
15
- const [isClosed, setIsClosed] = useState(false);
16
-
17
- if (!visible || isClosed) return null;
18
-
19
- const hasUrl = !!labels.badgeUrl;
20
-
21
- return (
22
- <div
23
- data-inspector-ignore
24
- style={{
25
- position: "fixed",
26
- bottom: "16px",
27
- right: "16px",
28
- pointerEvents: "all",
29
- }}
30
- onMouseEnter={() => setIsHovered(true)}
31
- onMouseLeave={() => setIsHovered(false)}
32
- >
33
- <div
34
- data-inspector-ignore
35
- style={{
36
- position: "relative",
37
- background: `linear-gradient(135deg, ${theme.badgeGradientStart} 0%, ${theme.badgeGradientEnd} 100%)`,
38
- color: theme.badgeTextColor,
39
- padding: "8px 16px",
40
- borderRadius: "24px",
41
- fontSize: "13px",
42
- fontWeight: 600,
43
- boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
44
- cursor: hasUrl ? "pointer" : "default",
45
- transition: "all 0.3s ease",
46
- fontFamily: "'Satoshi', system-ui, -apple-system, sans-serif",
47
- userSelect: "none",
48
- transform: isHovered ? "scale(1.02)" : "scale(1)",
49
- }}
50
- onClick={(e) => {
51
- // Prevent opening URL if clicking on close button
52
- if ((e.target as HTMLElement).dataset.badgeClose) return;
53
- if (hasUrl) {
54
- window.open(labels.badgeUrl, "_blank");
55
- }
56
- }}
57
- >
58
- {labels.badgeText}
59
- </div>
60
- {isHovered && (
61
- <button
62
- data-badge-close
63
- data-inspector-ignore
64
- onClick={(e) => {
65
- e.stopPropagation();
66
- setIsClosed(true);
67
- }}
68
- style={{
69
- position: "absolute",
70
- top: "-6px",
71
- right: "-6px",
72
- width: "20px",
73
- height: "20px",
74
- border: "none",
75
- background:
76
- theme.badgeTextColor === "#ffffff"
77
- ? "rgba(0, 0, 0, 0.7)"
78
- : "rgba(255, 255, 255, 0.9)",
79
- color: theme.badgeTextColor === "#ffffff" ? "#ffffff" : "#000000",
80
- borderRadius: "50%",
81
- cursor: "pointer",
82
- display: "flex",
83
- alignItems: "center",
84
- justifyContent: "center",
85
- fontSize: "14px",
86
- fontWeight: 700,
87
- lineHeight: 1,
88
- transition: "all 0.2s ease",
89
- padding: 0,
90
- boxShadow: "0 2px 8px rgba(0, 0, 0, 0.2)",
91
- zIndex: 1,
92
- }}
93
- onMouseEnter={(e) => {
94
- const isDark = theme.badgeTextColor === "#ffffff";
95
- (e.currentTarget as HTMLElement).style.background = isDark
96
- ? "rgba(0, 0, 0, 0.9)"
97
- : "rgba(255, 255, 255, 1)";
98
- (e.currentTarget as HTMLElement).style.transform = "scale(1.08)";
99
- (e.currentTarget as HTMLElement).style.boxShadow =
100
- "0 3px 12px rgba(0, 0, 0, 0.3)";
101
- }}
102
- onMouseLeave={(e) => {
103
- const isDark = theme.badgeTextColor === "#ffffff";
104
- (e.currentTarget as HTMLElement).style.background = isDark
105
- ? "rgba(0, 0, 0, 0.7)"
106
- : "rgba(255, 255, 255, 0.9)";
107
- (e.currentTarget as HTMLElement).style.transform = "scale(1)";
108
- (e.currentTarget as HTMLElement).style.boxShadow =
109
- "0 2px 8px rgba(0, 0, 0, 0.2)";
110
- }}
111
- aria-label="Close badge"
112
- >
113
- ×
114
- </button>
115
- )}
116
- </div>
117
- );
118
- }
@@ -1,13 +0,0 @@
1
- /**
2
- * ContentArea component - Container for tab content
3
- */
4
-
5
- import { ReactNode } from "react";
6
-
7
- interface ContentAreaProps {
8
- children: ReactNode;
9
- }
10
-
11
- export function ContentArea({ children }: ContentAreaProps) {
12
- return <div className="control-box-content">{children}</div>;
13
- }
@@ -1,66 +0,0 @@
1
- .container {
2
- position: relative;
3
- display: flex;
4
- align-items: center;
5
- justify-content: space-between;
6
- gap: var(--spacing-1);
7
- }
8
-
9
- .inputContainer {
10
- display: flex;
11
- align-items: center;
12
- gap: var(--spacing-2);
13
- flex: 1;
14
- border-radius: var(--radius-md);
15
- padding-right: var(--spacing-1);
16
- padding-left: var(--spacing-1);
17
- box-shadow: none;
18
- height: var(--spacing-9) !important;
19
- border: 1px solid;
20
- }
21
-
22
- .input {
23
- font-family: "Satoshi", var(--font-family-sans);
24
- font-size: var(--text-xs);
25
- border: none;
26
- box-shadow: none;
27
- height: var(--spacing-7) !important;
28
- padding-left: var(--spacing-1-5);
29
- padding-right: var(--spacing-1-5);
30
- flex: 1;
31
- min-width: 0;
32
- }
33
-
34
- .input:focus-visible {
35
- outline: none;
36
- box-shadow: none;
37
- }
38
-
39
- .buttons {
40
- display: flex;
41
- align-items: center;
42
- gap: var(--spacing-1);
43
- }
44
-
45
- .submitButton {
46
- height: var(--spacing-7);
47
- width: var(--spacing-7);
48
- flex-shrink: 0;
49
- }
50
-
51
- .submitIcon {
52
- height: var(--spacing-3-5);
53
- width: var(--spacing-3-5);
54
- }
55
-
56
- .closeButton {
57
- height: var(--spacing-9);
58
- width: var(--spacing-9);
59
- border-radius: var(--radius-md);
60
- flex-shrink: 0;
61
- }
62
-
63
- .closeIcon {
64
- height: var(--spacing-4);
65
- width: var(--spacing-4);
66
- }
@@ -1,104 +0,0 @@
1
- /**
2
- * PromptInput component - Always-visible prompt input at bottom
3
- */
4
-
5
- import { useState, useRef, useEffect } from "react";
6
- import { Input } from "../ui/input";
7
- import { Button } from "../ui/button";
8
- import { ArrowUpRight, X } from "lucide-react";
9
- import { useInspectorStore } from "../../store/useInspectorStore";
10
- import styles from "./PromptInput.module.css";
11
-
12
- interface PromptInputProps {
13
- placeholder: string;
14
- onSubmit: (prompt: string) => void;
15
- onClose: () => void;
16
- autoFocus?: boolean;
17
- }
18
-
19
- export function PromptInput({
20
- placeholder,
21
- onSubmit,
22
- onClose,
23
- autoFocus = false,
24
- }: PromptInputProps) {
25
- const { theme } = useInspectorStore();
26
- const [value, setValue] = useState("");
27
- const inputRef = useRef<HTMLInputElement>(null);
28
-
29
- useEffect(() => {
30
- if (autoFocus && inputRef.current) {
31
- inputRef.current.focus();
32
- }
33
- }, [autoFocus]);
34
-
35
- const handleSubmit = () => {
36
- if (value.trim()) {
37
- onSubmit(value.trim());
38
- setValue("");
39
- }
40
- };
41
-
42
- const handleKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => {
43
- if (e.key === "Enter") {
44
- e.preventDefault();
45
- handleSubmit();
46
- }
47
- };
48
-
49
- return (
50
- <div className={styles.container}>
51
- <div
52
- className={styles.inputContainer}
53
- style={{
54
- backgroundColor: theme.inputBackgroundColor,
55
- borderColor: theme.inputBorderColor,
56
- }}
57
- >
58
- <Input
59
- ref={inputRef}
60
- type="text"
61
- value={value}
62
- onChange={(e) => setValue(e.target.value)}
63
- onKeyDown={handleKeyPress}
64
- placeholder={placeholder}
65
- className={styles.input}
66
- style={{
67
- backgroundColor: "transparent",
68
- color: theme.inputTextColor,
69
- }}
70
- autoFocus={autoFocus}
71
- />
72
- <div className={styles.buttons}>
73
- <Button
74
- onClick={handleSubmit}
75
- disabled={!value.trim()}
76
- size="icon"
77
- className={styles.submitButton}
78
- title="Send"
79
- style={{
80
- backgroundColor: theme.buttonColor,
81
- color: theme.buttonTextColor,
82
- }}
83
- >
84
- <ArrowUpRight className={styles.submitIcon} />
85
- </Button>
86
- </div>
87
- </div>
88
- <Button
89
- onClick={onClose}
90
- variant="outline"
91
- title="Close"
92
- size="icon"
93
- className={styles.closeButton}
94
- style={{
95
- backgroundColor: theme.inputBackgroundColor,
96
- borderColor: theme.inputBorderColor,
97
- color: theme.textColor,
98
- }}
99
- >
100
- <X className={styles.closeIcon} />
101
- </Button>
102
- </div>
103
- );
104
- }