@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,84 +0,0 @@
1
- /**
2
- * ImageEditor component - Edit/upload images
3
- */
4
-
5
- import { useState } from "react";
6
- import { useMessageBridge } from "../../hooks/useMessageBridge";
7
- import { UploadBox } from "./UploadBox";
8
- import { Button } from "../ui/button";
9
- import type { SelectedElementData } from "@promakeai/inspector-types";
10
- import { useInspectorStore } from "../../store/useInspectorStore";
11
- import styles from "./index.module.css";
12
-
13
- interface ImageEditorProps {
14
- element: HTMLElement;
15
- elementData: SelectedElementData;
16
- }
17
-
18
- export function ImageEditor({ element, elementData }: ImageEditorProps) {
19
- const [selectedFile, setSelectedFile] = useState<File | null>(null);
20
- const [imageData, setImageData] = useState<string | null>(null);
21
- const { sendToParent } = useMessageBridge();
22
- const { labels, theme } = useInspectorStore();
23
-
24
- const handleFileSelect = (file: File) => {
25
- setSelectedFile(file);
26
-
27
- // Read file as base64
28
- const reader = new FileReader();
29
- reader.onload = (evt) => {
30
- const data = evt.target?.result as string;
31
- setImageData(data);
32
- };
33
- reader.readAsDataURL(file);
34
- };
35
-
36
- const handleUpdate = () => {
37
- if (!selectedFile || !imageData) return;
38
-
39
- // Update DOM immediately
40
- if (element.tagName.toLowerCase() === "img") {
41
- (element as HTMLImageElement).src = imageData;
42
- } else if (window.getComputedStyle(element).backgroundImage !== "none") {
43
- element.style.backgroundImage = `url("${imageData}")`;
44
- } else {
45
- // Try to find img child
46
- const imgChild = element.querySelector("img");
47
- if (imgChild) {
48
- imgChild.src = imageData;
49
- }
50
- }
51
-
52
- // Send to parent
53
- sendToParent("INSPECTOR_IMAGE_UPDATED", {
54
- imageData,
55
- imageFile: {
56
- name: selectedFile.name,
57
- size: selectedFile.size,
58
- type: selectedFile.type,
59
- },
60
- originalImageUrl: elementData.imageUrl,
61
- element: elementData,
62
- });
63
- };
64
-
65
- return (
66
- <div className={styles.container}>
67
- <UploadBox onFileSelect={handleFileSelect} previewImage={imageData} />
68
- <div>
69
- <Button
70
- onClick={handleUpdate}
71
- disabled={!selectedFile}
72
- className={styles.button}
73
- style={{
74
- backgroundColor: theme.buttonColor,
75
- color: theme.buttonTextColor,
76
- opacity: selectedFile ? 1 : 0.5,
77
- }}
78
- >
79
- {labels.updateImage}
80
- </Button>
81
- </div>
82
- </div>
83
- );
84
- }
@@ -1,157 +0,0 @@
1
- /**
2
- * Overlay component for highlighting elements
3
- */
4
-
5
- import { useEffect, useState } from "react";
6
-
7
- interface OverlayProps {
8
- element: HTMLElement | null;
9
- selectedElement: HTMLElement | null;
10
- showChildBorders?: boolean;
11
- }
12
-
13
- export function Overlay({
14
- element,
15
- selectedElement,
16
- showChildBorders = true,
17
- }: OverlayProps) {
18
- const [rect, setRect] = useState<DOMRect | null>(null);
19
- const [childRects, setChildRects] = useState<DOMRect[]>([]);
20
- const [isPaused, setIsPaused] = useState(false);
21
-
22
- const activeElement = selectedElement || element;
23
-
24
- useEffect(() => {
25
- if (!activeElement) {
26
- setRect(null);
27
- return;
28
- }
29
-
30
- setIsPaused(!!selectedElement);
31
-
32
- // Throttle updates to avoid excessive re-renders
33
- let updateTimeout: number | null = null;
34
- let lastUpdate = 0;
35
- const throttleMs = 16; // ~60fps
36
-
37
- const updateRect = () => {
38
- const now = Date.now();
39
- const timeSinceLastUpdate = now - lastUpdate;
40
-
41
- if (timeSinceLastUpdate >= throttleMs) {
42
- const newRect = activeElement.getBoundingClientRect();
43
- setRect(newRect);
44
-
45
- // Collect direct children rectangles
46
- const children = Array.from(activeElement.children) as HTMLElement[];
47
- const newChildRects = children
48
- .filter(child => !child.closest("[data-inspector-ignore]"))
49
- .map(child => child.getBoundingClientRect());
50
- setChildRects(newChildRects);
51
-
52
- lastUpdate = now;
53
- } else if (!updateTimeout) {
54
- // Schedule update for later
55
- updateTimeout = window.setTimeout(() => {
56
- const newRect = activeElement.getBoundingClientRect();
57
- setRect(newRect);
58
-
59
- // Collect direct children rectangles
60
- const children = Array.from(activeElement.children) as HTMLElement[];
61
- const newChildRects = children
62
- .filter(child => !child.closest("[data-inspector-ignore]"))
63
- .map(child => child.getBoundingClientRect());
64
- setChildRects(newChildRects);
65
-
66
- lastUpdate = Date.now();
67
- updateTimeout = null;
68
- }, throttleMs - timeSinceLastUpdate);
69
- }
70
- };
71
-
72
- updateRect();
73
-
74
- // Update on scroll and resize
75
- const handleUpdate = () => {
76
- updateRect();
77
- };
78
-
79
- window.addEventListener("scroll", handleUpdate, true);
80
- window.addEventListener("resize", handleUpdate);
81
-
82
- // Use ResizeObserver to track element size changes (for style edits)
83
- let resizeObserver: ResizeObserver | null = null;
84
-
85
- if (typeof ResizeObserver !== "undefined") {
86
- resizeObserver = new ResizeObserver(() => {
87
- updateRect();
88
- });
89
- resizeObserver.observe(activeElement);
90
- }
91
-
92
- // Use MutationObserver to track attribute and style changes
93
- let mutationObserver: MutationObserver | null = null;
94
-
95
- if (typeof MutationObserver !== "undefined") {
96
- mutationObserver = new MutationObserver(() => {
97
- updateRect();
98
- });
99
- mutationObserver.observe(activeElement, {
100
- attributes: true,
101
- attributeFilter: ["style", "class"],
102
- childList: false,
103
- subtree: false,
104
- });
105
- }
106
-
107
- return () => {
108
- window.removeEventListener("scroll", handleUpdate, true);
109
- window.removeEventListener("resize", handleUpdate);
110
-
111
- if (resizeObserver) {
112
- resizeObserver.disconnect();
113
- }
114
-
115
- if (mutationObserver) {
116
- mutationObserver.disconnect();
117
- }
118
-
119
- if (updateTimeout) {
120
- clearTimeout(updateTimeout);
121
- }
122
- };
123
- }, [activeElement, selectedElement]);
124
-
125
- if (!rect) return null;
126
-
127
- return (
128
- <>
129
- {/* Main element overlay */}
130
- <div
131
- className={`inspector-overlay ${isPaused ? "paused" : ""} active`}
132
- style={{
133
- top: `${rect.top}px`,
134
- left: `${rect.left}px`,
135
- width: `${rect.width}px`,
136
- height: `${rect.height}px`,
137
- }}
138
- />
139
-
140
-
141
- {/* Child overlays */}
142
- {showChildBorders &&
143
- childRects.map((childRect, index) => (
144
- <div
145
- key={index}
146
- className="inspector-overlay-child active"
147
- style={{
148
- top: `${childRect.top}px`,
149
- left: `${childRect.left}px`,
150
- width: `${childRect.width}px`,
151
- height: `${childRect.height}px`,
152
- }}
153
- />
154
- ))}
155
- </>
156
- );
157
- }
@@ -1,147 +0,0 @@
1
- /**
2
- * BorderSection - Border Radius, Border Width, Border Color
3
- */
4
-
5
- import type { StyleChanges } from "@promakeai/inspector-types";
6
- import { ColorPicker } from "./ColorPicker";
7
- import { NumberInput } from "./NumberInput";
8
- import {
9
- Select,
10
- SelectContent,
11
- SelectItem,
12
- SelectTrigger,
13
- SelectValue,
14
- } from "../ui/select";
15
- import { RotateCcw } from "lucide-react";
16
- import { useInspectorStore } from "../../store/useInspectorStore";
17
- import styles from "./shared.module.css";
18
-
19
- interface BorderSectionProps {
20
- styles: StyleChanges;
21
- onChange: (property: keyof StyleChanges, value: string) => void;
22
- originalStyles: StyleChanges;
23
- onResetProperty: (property: keyof StyleChanges) => void;
24
- }
25
-
26
- export function BorderSection({
27
- styles: styleValues,
28
- onChange,
29
- originalStyles,
30
- onResetProperty
31
- }: BorderSectionProps) {
32
- const { labels, theme } = useInspectorStore();
33
-
34
- const BORDER_STYLES = [
35
- { label: labels.borderStyleSolid || "Solid", value: "solid" },
36
- { label: labels.borderStyleDashed || "Dashed", value: "dashed" },
37
- { label: labels.borderStyleDotted || "Dotted", value: "dotted" },
38
- { label: labels.borderStyleDouble || "Double", value: "double" },
39
- { label: labels.borderStyleGroove || "Groove", value: "groove" },
40
- { label: labels.borderStyleRidge || "Ridge", value: "ridge" },
41
- { label: labels.borderStyleInset || "Inset", value: "inset" },
42
- { label: labels.borderStyleOutset || "Outset", value: "outset" },
43
- { label: labels.borderStyleNone || "None", value: "none" },
44
- ];
45
-
46
- return (
47
- <div className={styles.section}>
48
- <div className={styles.grid2}>
49
- <NumberInput
50
- label={labels.borderRadiusLabel || "Border Radius"}
51
- value={styleValues.borderRadius}
52
- onChange={(value) => onChange("borderRadius", value)}
53
- min={0}
54
- max={400}
55
- step={1}
56
- unit="px"
57
- originalValue={originalStyles.borderRadius}
58
- onReset={() => onResetProperty("borderRadius")}
59
- />
60
-
61
- <NumberInput
62
- label={labels.borderWidthLabel || "Border Width"}
63
- value={styleValues.borderWidth}
64
- onChange={(value) => onChange("borderWidth", value)}
65
- min={0}
66
- max={100}
67
- step={1}
68
- unit="px"
69
- originalValue={originalStyles.borderWidth}
70
- onReset={() => onResetProperty("borderWidth")}
71
- />
72
- </div>
73
-
74
- {/* Border Color and Border Style - Side by side */}
75
- <div className={styles.grid2}>
76
- <ColorPicker
77
- label={labels.borderColorLabel || "Border Color"}
78
- value={styleValues.borderColor || "#000000"}
79
- onChange={(value) => onChange("borderColor", value)}
80
- originalValue={originalStyles.borderColor}
81
- onReset={() => onResetProperty("borderColor")}
82
- />
83
-
84
- {/* Border Style */}
85
- <div>
86
- <div className={styles.labelContainer}>
87
- <label className={styles.label} style={{ color: theme.textColor }}>
88
- {labels.borderStyleLabel || "Border Style"}
89
- </label>
90
- {styleValues.borderStyle !== originalStyles.borderStyle && (
91
- <button
92
- type="button"
93
- onClick={() => onResetProperty("borderStyle")}
94
- className={styles.resetIcon}
95
- style={{ color: theme.secondaryTextColor }}
96
- title="Reset to original"
97
- >
98
- <RotateCcw size={12} />
99
- </button>
100
- )}
101
- </div>
102
- <div
103
- className={styles.inputContainer}
104
- style={{
105
- backgroundColor: theme.inputBackgroundColor,
106
- borderColor: theme.inputBorderColor,
107
- }}
108
- >
109
- <Select
110
- value={styleValues.borderStyle || "solid"}
111
- onValueChange={(value) => onChange("borderStyle", value)}
112
- >
113
- <SelectTrigger
114
- className={styles.input}
115
- style={{
116
- backgroundColor: "transparent",
117
- color: theme.inputTextColor,
118
- }}
119
- size="sm"
120
- >
121
- <SelectValue />
122
- </SelectTrigger>
123
- <SelectContent
124
- style={{
125
- backgroundColor: theme.backgroundColor,
126
- borderColor: theme.borderColor,
127
- }}
128
- >
129
- {BORDER_STYLES.map((borderStyle) => (
130
- <SelectItem
131
- key={borderStyle.value}
132
- value={borderStyle.value}
133
- style={{
134
- color: theme.textColor,
135
- }}
136
- >
137
- {borderStyle.label}
138
- </SelectItem>
139
- ))}
140
- </SelectContent>
141
- </Select>
142
- </div>
143
- </div>
144
- </div>
145
- </div>
146
- );
147
- }
@@ -1,182 +0,0 @@
1
- /**
2
- * ColorPicker - Simple color picker with react-colorful
3
- */
4
-
5
- import { useMemo, useState } from "react";
6
- import { Input } from "../ui/input";
7
- import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
8
- import { RgbaColorPicker } from "react-colorful";
9
- import { hexToRgba } from "../../utils/colorUtils";
10
- import { useInspectorStore } from "../../store/useInspectorStore";
11
- import { RotateCcw } from "lucide-react";
12
- import styles from "./shared.module.css";
13
-
14
- interface ColorPickerProps {
15
- label: string;
16
- value: string;
17
- onChange: (value: string) => void;
18
- originalValue?: string;
19
- onReset?: () => void;
20
- }
21
-
22
- export function ColorPicker({ label, value, onChange, originalValue, onReset }: ColorPickerProps) {
23
- const { theme } = useInspectorStore();
24
- const hasChanged = originalValue !== undefined && value !== originalValue;
25
- const [hexInput, setHexInput] = useState("");
26
- const [isEditingHex, setIsEditingHex] = useState(false);
27
-
28
- // Convert current value to RGBA for react-colorful
29
- const rgbaValue = useMemo(() => {
30
- if (value === "transparent") return { r: 255, g: 255, b: 255, a: 0 };
31
- if (value.startsWith("#")) {
32
- const rgba = hexToRgba(value);
33
- return rgba || { r: 0, g: 0, b: 0, a: 1 };
34
- }
35
- if (value.startsWith("rgb")) {
36
- const match = value.match(
37
- /rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/
38
- );
39
- if (match) {
40
- return {
41
- r: parseInt(match[1]),
42
- g: parseInt(match[2]),
43
- b: parseInt(match[3]),
44
- a: match[4] ? parseFloat(match[4]) : 1,
45
- };
46
- }
47
- }
48
- return { r: 0, g: 0, b: 0, a: 1 };
49
- }, [value]);
50
-
51
- // Convert to hex for display
52
- const displayValue = useMemo(() => {
53
- if (value.startsWith("#")) return value;
54
- if (value.startsWith("rgb")) {
55
- const match = value.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
56
- if (match) {
57
- const r = parseInt(match[1]);
58
- const g = parseInt(match[2]);
59
- const b = parseInt(match[3]);
60
- return `#${((1 << 24) + (r << 16) + (g << 8) + b)
61
- .toString(16)
62
- .slice(1)}`;
63
- }
64
- }
65
- return value || "#000000";
66
- }, [value]);
67
-
68
- const handleRgbaChange = (newRgba: {
69
- r: number;
70
- g: number;
71
- b: number;
72
- a: number;
73
- }) => {
74
- if (newRgba.a < 1) {
75
- onChange(`rgba(${newRgba.r}, ${newRgba.g}, ${newRgba.b}, ${newRgba.a})`);
76
- } else {
77
- const hex = `#${(
78
- (1 << 24) +
79
- (newRgba.r << 16) +
80
- (newRgba.g << 8) +
81
- newRgba.b
82
- )
83
- .toString(16)
84
- .slice(1)}`;
85
- onChange(hex);
86
- }
87
- };
88
-
89
- const handleHexInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
90
- const input = e.target.value;
91
- setHexInput(input);
92
-
93
- // Validate and update if it's a valid hex color
94
- if (/^#[0-9A-Fa-f]{6}$/.test(input)) {
95
- onChange(input);
96
- }
97
- };
98
-
99
- const handleHexInputFocus = () => {
100
- setIsEditingHex(true);
101
- setHexInput(displayValue);
102
- };
103
-
104
- const handleHexInputBlur = () => {
105
- setIsEditingHex(false);
106
- // Ensure valid hex on blur
107
- if (hexInput && /^#[0-9A-Fa-f]{6}$/.test(hexInput)) {
108
- onChange(hexInput);
109
- }
110
- };
111
-
112
- return (
113
- <div className={styles.inputField}>
114
- <div className={styles.labelContainer}>
115
- <label className={styles.label} style={{ color: theme.textColor }}>
116
- {label}
117
- </label>
118
- {hasChanged && onReset && (
119
- <button
120
- type="button"
121
- onClick={onReset}
122
- className={styles.resetIcon}
123
- style={{ color: theme.secondaryTextColor }}
124
- title="Reset to original"
125
- >
126
- <RotateCcw size={12} />
127
- </button>
128
- )}
129
- </div>
130
-
131
- <div
132
- className={styles.inputContainer}
133
- style={{
134
- backgroundColor: theme.inputBackgroundColor,
135
- borderColor: theme.inputBorderColor,
136
- }}
137
- >
138
- {/* Color preview with picker */}
139
- <Popover>
140
- <PopoverTrigger asChild>
141
- <button
142
- type="button"
143
- className={styles.colorPreview}
144
- style={{
145
- backgroundColor: value,
146
- borderColor: theme.inputBorderColor,
147
- }}
148
- title="Pick color"
149
- />
150
- </PopoverTrigger>
151
- <PopoverContent
152
- side="top"
153
- align="center"
154
- sideOffset={8}
155
- style={{
156
- padding: 'var(--spacing-3)',
157
- width: 'auto',
158
- }}
159
- >
160
- <RgbaColorPicker color={rgbaValue} onChange={handleRgbaChange} />
161
- </PopoverContent>
162
- </Popover>
163
-
164
- {/* Hex input */}
165
- <Input
166
- type="text"
167
- value={isEditingHex ? hexInput : displayValue}
168
- onChange={handleHexInputChange}
169
- onFocus={handleHexInputFocus}
170
- onBlur={handleHexInputBlur}
171
- className={styles.input}
172
- style={{
173
- backgroundColor: "transparent",
174
- color: theme.inputTextColor,
175
- fontFamily: "monospace",
176
- }}
177
- placeholder="#000000"
178
- />
179
- </div>
180
- </div>
181
- );
182
- }