@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.
- package/README.md +111 -0
- package/dist/App.d.ts.map +1 -0
- package/dist/__tests__/App.test.d.ts.map +1 -0
- package/dist/components/Badge.d.ts.map +1 -0
- package/dist/components/ControlBox/ContentArea.d.ts.map +1 -0
- package/dist/components/ControlBox/PromptInput.d.ts.map +1 -0
- package/dist/components/ControlBox/index.d.ts.map +1 -0
- package/dist/components/ImageEditor/UploadBox.d.ts.map +1 -0
- package/dist/components/ImageEditor/index.d.ts.map +1 -0
- package/dist/components/Overlay.d.ts.map +1 -0
- package/dist/components/StyleEditor/BorderSection.d.ts.map +1 -0
- package/dist/components/StyleEditor/ColorPicker.d.ts.map +1 -0
- package/dist/components/StyleEditor/DisplaySection.d.ts.map +1 -0
- package/dist/components/StyleEditor/ImageSection.d.ts.map +1 -0
- package/dist/components/StyleEditor/LayoutSection.d.ts.map +1 -0
- package/dist/components/StyleEditor/NumberInput.d.ts.map +1 -0
- package/dist/components/StyleEditor/SliderInput.d.ts.map +1 -0
- package/dist/components/StyleEditor/SpacingSection.d.ts.map +1 -0
- package/dist/components/StyleEditor/TextSection.d.ts.map +1 -0
- package/dist/components/StyleEditor/index.d.ts.map +1 -0
- package/dist/components/TextEditor/index.d.ts.map +1 -0
- package/dist/components/ui/CustomCollapsible.d.ts.map +1 -0
- package/dist/components/ui/button.d.ts.map +1 -0
- package/dist/components/ui/color-picker.d.ts.map +1 -0
- package/dist/components/ui/input.d.ts.map +1 -0
- package/dist/components/ui/popover.d.ts.map +1 -0
- package/dist/components/ui/select.d.ts.map +1 -0
- package/dist/components/ui/slider.d.ts.map +1 -0
- package/dist/components/ui/textarea.d.ts.map +1 -0
- package/dist/components/ui/tooltip.d.ts.map +1 -0
- package/dist/core/highlighter.d.ts.map +1 -0
- package/dist/hooks/useMessageBridge.d.ts.map +1 -0
- package/dist/hooks/useStylePreview.d.ts.map +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/store/useInspectorStore.d.ts.map +1 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/utils/colorUtils.d.ts.map +1 -0
- package/dist/utils/elementNames.d.ts.map +1 -0
- package/dist/utils/elementUtils.d.ts.map +1 -0
- package/dist/utils/errorTracker.d.ts.map +1 -0
- package/dist/utils/inputStyles.d.ts.map +1 -0
- package/dist/utils/styleUtils.d.ts.map +1 -0
- package/dist/utils/tailwindMapper.d.ts.map +1 -0
- package/dist/utils/urlTracker.d.ts.map +1 -0
- package/package.json +15 -10
- package/dist/packages/inspector/src/App.d.ts.map +0 -1
- package/dist/packages/inspector/src/__tests__/App.test.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/Badge.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/ControlBox/ContentArea.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/ControlBox/PromptInput.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/ControlBox/index.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/ImageEditor/UploadBox.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/ImageEditor/index.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/Overlay.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/StyleEditor/BorderSection.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/StyleEditor/ColorPicker.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/StyleEditor/DisplaySection.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/StyleEditor/ImageSection.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/StyleEditor/LayoutSection.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/StyleEditor/NumberInput.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/StyleEditor/SliderInput.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/StyleEditor/SpacingSection.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/StyleEditor/TextSection.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/StyleEditor/index.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/TextEditor/index.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/ui/CustomCollapsible.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/ui/button.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/ui/color-picker.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/ui/input.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/ui/popover.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/ui/select.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/ui/slider.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/ui/textarea.d.ts.map +0 -1
- package/dist/packages/inspector/src/components/ui/tooltip.d.ts.map +0 -1
- package/dist/packages/inspector/src/core/highlighter.d.ts.map +0 -1
- package/dist/packages/inspector/src/hooks/useMessageBridge.d.ts.map +0 -1
- package/dist/packages/inspector/src/hooks/useStylePreview.d.ts.map +0 -1
- package/dist/packages/inspector/src/index.d.ts.map +0 -1
- package/dist/packages/inspector/src/lib/utils.d.ts.map +0 -1
- package/dist/packages/inspector/src/plugin.d.ts.map +0 -1
- package/dist/packages/inspector/src/store/useInspectorStore.d.ts.map +0 -1
- package/dist/packages/inspector/src/styles.d.ts.map +0 -1
- package/dist/packages/inspector/src/utils/colorUtils.d.ts.map +0 -1
- package/dist/packages/inspector/src/utils/elementNames.d.ts.map +0 -1
- package/dist/packages/inspector/src/utils/elementUtils.d.ts.map +0 -1
- package/dist/packages/inspector/src/utils/errorTracker.d.ts.map +0 -1
- package/dist/packages/inspector/src/utils/inputStyles.d.ts.map +0 -1
- package/dist/packages/inspector/src/utils/styleUtils.d.ts.map +0 -1
- package/dist/packages/inspector/src/utils/tailwindMapper.d.ts.map +0 -1
- package/dist/packages/inspector/src/utils/urlTracker.d.ts.map +0 -1
- package/dist/packages/inspector/tsconfig.tsbuildinfo +0 -1
- package/src/App.tsx +0 -912
- package/src/__tests__/App.test.tsx +0 -373
- package/src/assets/fonts/Satoshi-Variable.woff +0 -0
- package/src/assets/fonts/Satoshi-Variable.woff2 +0 -0
- package/src/components/Badge.tsx +0 -118
- package/src/components/ControlBox/ContentArea.tsx +0 -13
- package/src/components/ControlBox/PromptInput.module.css +0 -66
- package/src/components/ControlBox/PromptInput.tsx +0 -104
- package/src/components/ControlBox/index.module.css +0 -81
- package/src/components/ControlBox/index.tsx +0 -409
- package/src/components/ImageEditor/UploadBox.module.css +0 -69
- package/src/components/ImageEditor/UploadBox.tsx +0 -113
- package/src/components/ImageEditor/index.module.css +0 -11
- package/src/components/ImageEditor/index.tsx +0 -84
- package/src/components/Overlay.tsx +0 -157
- package/src/components/StyleEditor/BorderSection.tsx +0 -147
- package/src/components/StyleEditor/ColorPicker.tsx +0 -182
- package/src/components/StyleEditor/DisplaySection.tsx +0 -349
- package/src/components/StyleEditor/ImageSection.tsx +0 -105
- package/src/components/StyleEditor/LayoutSection.tsx +0 -63
- package/src/components/StyleEditor/NumberInput.tsx +0 -138
- package/src/components/StyleEditor/SliderInput.tsx +0 -121
- package/src/components/StyleEditor/SpacingSection.tsx +0 -365
- package/src/components/StyleEditor/TextSection.tsx +0 -381
- package/src/components/StyleEditor/index.module.css +0 -133
- package/src/components/StyleEditor/index.tsx +0 -612
- package/src/components/StyleEditor/shared.module.css +0 -193
- package/src/components/TextEditor/index.module.css +0 -31
- package/src/components/TextEditor/index.tsx +0 -166
- package/src/components/ui/CustomCollapsible.tsx +0 -159
- package/src/components/ui/button.module.css +0 -141
- package/src/components/ui/button.tsx +0 -73
- package/src/components/ui/color-picker.module.css +0 -112
- package/src/components/ui/color-picker.tsx +0 -146
- package/src/components/ui/input.module.css +0 -49
- package/src/components/ui/input.tsx +0 -34
- package/src/components/ui/popover.module.css +0 -42
- package/src/components/ui/popover.tsx +0 -59
- package/src/components/ui/select.module.css +0 -160
- package/src/components/ui/select.tsx +0 -216
- package/src/components/ui/slider.module.css +0 -75
- package/src/components/ui/slider.tsx +0 -60
- package/src/components/ui/textarea.module.css +0 -30
- package/src/components/ui/textarea.tsx +0 -23
- package/src/components/ui/tooltip.module.css +0 -11
- package/src/components/ui/tooltip.tsx +0 -37
- package/src/core/highlighter.ts +0 -197
- package/src/hooks/useMessageBridge.ts +0 -49
- package/src/hooks/useStylePreview.ts +0 -332
- package/src/index.ts +0 -20
- package/src/lib/utils.ts +0 -5
- package/src/plugin.ts +0 -11
- package/src/store/useInspectorStore.ts +0 -235
- package/src/styles/fonts.css +0 -15
- package/src/styles/global.css +0 -138
- package/src/styles/variables.css +0 -151
- package/src/styles.ts +0 -5
- package/src/utils/colorUtils.ts +0 -133
- package/src/utils/elementNames.ts +0 -103
- package/src/utils/elementUtils.ts +0 -90
- package/src/utils/errorTracker.ts +0 -186
- package/src/utils/inputStyles.ts +0 -30
- package/src/utils/styleUtils.ts +0 -226
- package/src/utils/tailwindMapper.ts +0 -554
- package/src/utils/urlTracker.ts +0 -75
- package/src/vite-env.d.ts +0 -7
- /package/dist/{packages/inspector/src/App.d.ts → App.d.ts} +0 -0
- /package/dist/{packages/inspector/src/__tests__ → __tests__}/App.test.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/Badge.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/ControlBox/ContentArea.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/ControlBox/PromptInput.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/ControlBox/index.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/ImageEditor/UploadBox.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/ImageEditor/index.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/Overlay.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/StyleEditor/BorderSection.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/StyleEditor/ColorPicker.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/StyleEditor/DisplaySection.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/StyleEditor/ImageSection.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/StyleEditor/LayoutSection.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/StyleEditor/NumberInput.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/StyleEditor/SliderInput.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/StyleEditor/SpacingSection.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/StyleEditor/TextSection.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/StyleEditor/index.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/TextEditor/index.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/ui/CustomCollapsible.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/ui/button.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/ui/color-picker.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/ui/input.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/ui/popover.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/ui/select.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/ui/slider.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/ui/textarea.d.ts +0 -0
- /package/dist/{packages/inspector/src/components → components}/ui/tooltip.d.ts +0 -0
- /package/dist/{packages/inspector/src/core → core}/highlighter.d.ts +0 -0
- /package/dist/{packages/inspector/src/hooks → hooks}/useMessageBridge.d.ts +0 -0
- /package/dist/{packages/inspector/src/hooks → hooks}/useStylePreview.d.ts +0 -0
- /package/dist/{packages/inspector/src/index.d.ts → index.d.ts} +0 -0
- /package/dist/{packages/inspector/src/lib → lib}/utils.d.ts +0 -0
- /package/dist/{packages/inspector/src/plugin.d.ts → plugin.d.ts} +0 -0
- /package/dist/{packages/inspector/src/store → store}/useInspectorStore.d.ts +0 -0
- /package/dist/{packages/inspector/src/styles.d.ts → styles.d.ts} +0 -0
- /package/dist/{packages/inspector/src/utils → utils}/colorUtils.d.ts +0 -0
- /package/dist/{packages/inspector/src/utils → utils}/elementNames.d.ts +0 -0
- /package/dist/{packages/inspector/src/utils → utils}/elementUtils.d.ts +0 -0
- /package/dist/{packages/inspector/src/utils → utils}/errorTracker.d.ts +0 -0
- /package/dist/{packages/inspector/src/utils → utils}/inputStyles.d.ts +0 -0
- /package/dist/{packages/inspector/src/utils → utils}/styleUtils.d.ts +0 -0
- /package/dist/{packages/inspector/src/utils → utils}/tailwindMapper.d.ts +0 -0
- /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
|
-
}
|