@designtools/shadows 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +292 -193
- package/package.json +1 -1
- package/src/client/app.tsx +19 -3
- package/src/client/components/shadow-controls.tsx +9 -3
- package/src/client/components/shadow-editor-panel.tsx +31 -5
- package/src/client/components/shadow-list.tsx +95 -67
- package/src/client/components/shadow-overview.tsx +83 -78
- package/src/client/components/shadow-preview-settings.tsx +210 -0
- package/src/client/components/shadow-preview.tsx +5 -1
- package/src/client/dist/assets/index-CA2rtXvo.js +49 -0
- package/src/client/dist/index.html +1 -1
- package/src/client/dist/assets/index-DuqoHhIQ.js +0 -49
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { useState, useRef, useEffect } from "react";
|
|
2
|
+
import { Half2Icon } from "@radix-ui/react-icons";
|
|
3
|
+
|
|
4
|
+
export interface PreviewSettings {
|
|
5
|
+
previewBg: string;
|
|
6
|
+
showBorder: boolean;
|
|
7
|
+
borderColor: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const DEFAULT_PREVIEW_SETTINGS: PreviewSettings = {
|
|
11
|
+
previewBg: "rgb(240, 244, 250)",
|
|
12
|
+
showBorder: false,
|
|
13
|
+
borderColor: "#e8e8e8",
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const BG_SWATCHES = [
|
|
17
|
+
{ name: "Soft Blue", value: "rgb(240, 244, 250)" },
|
|
18
|
+
{ name: "White", value: "white" },
|
|
19
|
+
{ name: "Light Gray", value: "#f0f0f0" },
|
|
20
|
+
{ name: "Gray", value: "#e0e0e0" },
|
|
21
|
+
{ name: "Mid Gray", value: "#d0d0d0" },
|
|
22
|
+
{ name: "Dark Gray", value: "#bbb" },
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const BORDER_COLORS = [
|
|
26
|
+
{ name: "Lightest", value: "#eee" },
|
|
27
|
+
{ name: "Light", value: "#e0e0e0" },
|
|
28
|
+
{ name: "Medium", value: "#d0d0d0" },
|
|
29
|
+
{ name: "Dark", value: "#bbb" },
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
interface ShadowPreviewSettingsProps {
|
|
33
|
+
settings: PreviewSettings;
|
|
34
|
+
onChange: (settings: PreviewSettings) => void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function ShadowPreviewSettingsButton({
|
|
38
|
+
settings,
|
|
39
|
+
onChange,
|
|
40
|
+
}: ShadowPreviewSettingsProps) {
|
|
41
|
+
const [open, setOpen] = useState(false);
|
|
42
|
+
const popoverRef = useRef<HTMLDivElement>(null);
|
|
43
|
+
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
44
|
+
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
if (!open) return;
|
|
47
|
+
const handleClick = (e: MouseEvent) => {
|
|
48
|
+
if (
|
|
49
|
+
popoverRef.current &&
|
|
50
|
+
!popoverRef.current.contains(e.target as Node) &&
|
|
51
|
+
buttonRef.current &&
|
|
52
|
+
!buttonRef.current.contains(e.target as Node)
|
|
53
|
+
) {
|
|
54
|
+
setOpen(false);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
document.addEventListener("mousedown", handleClick);
|
|
58
|
+
return () => document.removeEventListener("mousedown", handleClick);
|
|
59
|
+
}, [open]);
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<div style={{ position: "relative" }}>
|
|
63
|
+
<button
|
|
64
|
+
ref={buttonRef}
|
|
65
|
+
onClick={() => setOpen(!open)}
|
|
66
|
+
className="cursor-pointer"
|
|
67
|
+
style={{
|
|
68
|
+
display: "flex",
|
|
69
|
+
alignItems: "center",
|
|
70
|
+
gap: 6,
|
|
71
|
+
padding: "3px 8px 3px 6px",
|
|
72
|
+
borderRadius: 6,
|
|
73
|
+
fontSize: 10,
|
|
74
|
+
fontWeight: 500,
|
|
75
|
+
color: open ? "var(--studio-accent)" : "var(--studio-text-dimmed)",
|
|
76
|
+
background: open ? "var(--studio-accent-muted)" : "var(--studio-input-bg)",
|
|
77
|
+
border: "1px solid",
|
|
78
|
+
borderColor: open ? "var(--studio-accent)" : "var(--studio-border)",
|
|
79
|
+
transition: "all 0.15s",
|
|
80
|
+
}}
|
|
81
|
+
>
|
|
82
|
+
<Half2Icon style={{ width: 12, height: 12 }} />
|
|
83
|
+
Settings
|
|
84
|
+
</button>
|
|
85
|
+
|
|
86
|
+
{open && (
|
|
87
|
+
<div
|
|
88
|
+
ref={popoverRef}
|
|
89
|
+
style={{
|
|
90
|
+
position: "absolute",
|
|
91
|
+
top: "100%",
|
|
92
|
+
right: 0,
|
|
93
|
+
marginTop: 4,
|
|
94
|
+
background: "var(--studio-surface)",
|
|
95
|
+
border: "1px solid var(--studio-border)",
|
|
96
|
+
borderRadius: 8,
|
|
97
|
+
padding: "12px 14px",
|
|
98
|
+
zIndex: 100,
|
|
99
|
+
width: 248,
|
|
100
|
+
boxShadow: "0 8px 24px rgb(0 0 0 / 0.15)",
|
|
101
|
+
}}
|
|
102
|
+
>
|
|
103
|
+
<div className="flex flex-col gap-3.5">
|
|
104
|
+
{/* Background */}
|
|
105
|
+
<div>
|
|
106
|
+
<div
|
|
107
|
+
className="text-[9px] font-semibold uppercase tracking-wide mb-2"
|
|
108
|
+
style={{ color: "var(--studio-text-dimmed)" }}
|
|
109
|
+
>
|
|
110
|
+
Preview Background
|
|
111
|
+
</div>
|
|
112
|
+
<div className="flex gap-1.5">
|
|
113
|
+
{BG_SWATCHES.map((bg) => (
|
|
114
|
+
<button
|
|
115
|
+
key={bg.value}
|
|
116
|
+
onClick={() =>
|
|
117
|
+
onChange({ ...settings, previewBg: bg.value })
|
|
118
|
+
}
|
|
119
|
+
className="shrink-0 cursor-pointer"
|
|
120
|
+
title={bg.name}
|
|
121
|
+
style={{
|
|
122
|
+
width: 24,
|
|
123
|
+
height: 24,
|
|
124
|
+
borderRadius: 5,
|
|
125
|
+
background: bg.value,
|
|
126
|
+
border:
|
|
127
|
+
settings.previewBg === bg.value
|
|
128
|
+
? "2px solid var(--studio-accent)"
|
|
129
|
+
: "1px solid var(--studio-border)",
|
|
130
|
+
}}
|
|
131
|
+
/>
|
|
132
|
+
))}
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
{/* Borders */}
|
|
137
|
+
<div>
|
|
138
|
+
<div className="flex items-center justify-between mb-2">
|
|
139
|
+
<div
|
|
140
|
+
className="text-[9px] font-semibold uppercase tracking-wide"
|
|
141
|
+
style={{ color: "var(--studio-text-dimmed)" }}
|
|
142
|
+
>
|
|
143
|
+
Show card borders
|
|
144
|
+
</div>
|
|
145
|
+
<button
|
|
146
|
+
onClick={() =>
|
|
147
|
+
onChange({
|
|
148
|
+
...settings,
|
|
149
|
+
showBorder: !settings.showBorder,
|
|
150
|
+
})
|
|
151
|
+
}
|
|
152
|
+
className="shrink-0 cursor-pointer"
|
|
153
|
+
style={{
|
|
154
|
+
width: 34,
|
|
155
|
+
height: 20,
|
|
156
|
+
borderRadius: 10,
|
|
157
|
+
border: "1px solid var(--studio-border)",
|
|
158
|
+
background: settings.showBorder
|
|
159
|
+
? "var(--studio-accent)"
|
|
160
|
+
: "var(--studio-input-bg)",
|
|
161
|
+
position: "relative",
|
|
162
|
+
transition: "background 0.15s",
|
|
163
|
+
}}
|
|
164
|
+
>
|
|
165
|
+
<div
|
|
166
|
+
style={{
|
|
167
|
+
width: 14,
|
|
168
|
+
height: 14,
|
|
169
|
+
borderRadius: "50%",
|
|
170
|
+
background: "white",
|
|
171
|
+
position: "absolute",
|
|
172
|
+
top: 2,
|
|
173
|
+
left: settings.showBorder ? 16 : 2,
|
|
174
|
+
transition: "left 0.15s",
|
|
175
|
+
boxShadow: "0 1px 2px rgb(0 0 0 / 0.15)",
|
|
176
|
+
}}
|
|
177
|
+
/>
|
|
178
|
+
</button>
|
|
179
|
+
</div>
|
|
180
|
+
{settings.showBorder && (
|
|
181
|
+
<div className="flex gap-1.5">
|
|
182
|
+
{BORDER_COLORS.map((bc) => (
|
|
183
|
+
<button
|
|
184
|
+
key={bc.value}
|
|
185
|
+
onClick={() =>
|
|
186
|
+
onChange({ ...settings, borderColor: bc.value })
|
|
187
|
+
}
|
|
188
|
+
className="shrink-0 cursor-pointer"
|
|
189
|
+
title={bc.name}
|
|
190
|
+
style={{
|
|
191
|
+
width: 24,
|
|
192
|
+
height: 24,
|
|
193
|
+
borderRadius: 5,
|
|
194
|
+
background: bc.value,
|
|
195
|
+
border:
|
|
196
|
+
settings.borderColor === bc.value
|
|
197
|
+
? "2px solid var(--studio-accent)"
|
|
198
|
+
: "1px solid var(--studio-border)",
|
|
199
|
+
}}
|
|
200
|
+
/>
|
|
201
|
+
))}
|
|
202
|
+
</div>
|
|
203
|
+
)}
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
</div>
|
|
207
|
+
)}
|
|
208
|
+
</div>
|
|
209
|
+
);
|
|
210
|
+
}
|
|
@@ -3,6 +3,8 @@ interface ShadowPreviewProps {
|
|
|
3
3
|
size?: number;
|
|
4
4
|
shape?: "square" | "rounded" | "circle";
|
|
5
5
|
background?: string;
|
|
6
|
+
showBorder?: boolean;
|
|
7
|
+
borderColor?: string;
|
|
6
8
|
}
|
|
7
9
|
|
|
8
10
|
export function ShadowPreview({
|
|
@@ -10,6 +12,8 @@ export function ShadowPreview({
|
|
|
10
12
|
size = 32,
|
|
11
13
|
shape = "rounded",
|
|
12
14
|
background = "white",
|
|
15
|
+
showBorder = false,
|
|
16
|
+
borderColor = "#e0e0e0",
|
|
13
17
|
}: ShadowPreviewProps) {
|
|
14
18
|
const borderRadius =
|
|
15
19
|
shape === "circle" ? "50%" : shape === "rounded" ? "4px" : "0";
|
|
@@ -23,7 +27,7 @@ export function ShadowPreview({
|
|
|
23
27
|
borderRadius,
|
|
24
28
|
background,
|
|
25
29
|
boxShadow: value,
|
|
26
|
-
border:
|
|
30
|
+
border: showBorder ? `1px solid ${borderColor}` : "none",
|
|
27
31
|
}}
|
|
28
32
|
/>
|
|
29
33
|
);
|