@varialkit/colorpicker 0.1.0
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/docs.md +124 -0
- package/examples.tsx +376 -0
- package/package.json +27 -0
- package/src/ColorPicker.scss +471 -0
- package/src/ColorPicker.tsx +905 -0
- package/src/ColorPicker.types.ts +270 -0
- package/src/ColorPreview.tsx +48 -0
- package/src/index.ts +12 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import type React from "react";
|
|
2
|
+
import type { MenuDropdownProps, MenuProps } from "@solara/menu";
|
|
3
|
+
|
|
4
|
+
export type ColorPickerSize = "sm" | "md" | "lg";
|
|
5
|
+
export type ColorPickerValueFormat = "hex" | "rgba" | "hsla";
|
|
6
|
+
|
|
7
|
+
export type ColorPickerPaletteEntry = string | ColorPickerPaletteOption;
|
|
8
|
+
|
|
9
|
+
export interface ColorPickerPaletteOption {
|
|
10
|
+
/**
|
|
11
|
+
* Color value (hex format)
|
|
12
|
+
*/
|
|
13
|
+
value: string;
|
|
14
|
+
/**
|
|
15
|
+
* Optional label for accessibility or overlays.
|
|
16
|
+
*/
|
|
17
|
+
label?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Optional overlay content rendered on top of the swatch.
|
|
20
|
+
*/
|
|
21
|
+
content?: React.ReactNode;
|
|
22
|
+
/**
|
|
23
|
+
* Whether this palette option is disabled.
|
|
24
|
+
*/
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface ColorPickerSwatchProps
|
|
29
|
+
extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "color"> {
|
|
30
|
+
/**
|
|
31
|
+
* Color value to render.
|
|
32
|
+
*/
|
|
33
|
+
color: string;
|
|
34
|
+
/**
|
|
35
|
+
* Size of the swatch.
|
|
36
|
+
*/
|
|
37
|
+
size?: ColorPickerSize;
|
|
38
|
+
/**
|
|
39
|
+
* Override the swatch radius (CSS value or token).
|
|
40
|
+
*/
|
|
41
|
+
radius?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Whether the swatch is selected.
|
|
44
|
+
*/
|
|
45
|
+
selected?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Disabled state.
|
|
48
|
+
*/
|
|
49
|
+
disabled?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Optional overlay content on top of the swatch.
|
|
52
|
+
*/
|
|
53
|
+
children?: React.ReactNode;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface ColorPickerPaletteProps {
|
|
57
|
+
/**
|
|
58
|
+
* Current selected color value (hex format)
|
|
59
|
+
*/
|
|
60
|
+
value?: string;
|
|
61
|
+
/**
|
|
62
|
+
* Palette entries rendered as swatches.
|
|
63
|
+
*/
|
|
64
|
+
colors?: ColorPickerPaletteEntry[];
|
|
65
|
+
/**
|
|
66
|
+
* Called when a swatch is selected.
|
|
67
|
+
*/
|
|
68
|
+
onSelectColor?: (color: string) => void;
|
|
69
|
+
/**
|
|
70
|
+
* Size of the palette swatches.
|
|
71
|
+
*/
|
|
72
|
+
size?: ColorPickerSize;
|
|
73
|
+
/**
|
|
74
|
+
* Disabled state for the entire palette.
|
|
75
|
+
*/
|
|
76
|
+
disabled?: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Additional className.
|
|
79
|
+
*/
|
|
80
|
+
className?: string;
|
|
81
|
+
/**
|
|
82
|
+
* Override the swatch radius (CSS value or token).
|
|
83
|
+
*/
|
|
84
|
+
swatchRadius?: string;
|
|
85
|
+
/**
|
|
86
|
+
* Optional overlay content for each swatch.
|
|
87
|
+
*/
|
|
88
|
+
swatchContent?: (color: string) => React.ReactNode;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface ColorPickerContentProps {
|
|
92
|
+
/**
|
|
93
|
+
* Current selected color value.
|
|
94
|
+
*/
|
|
95
|
+
value?: string;
|
|
96
|
+
/**
|
|
97
|
+
* Callback when color changes
|
|
98
|
+
*/
|
|
99
|
+
onChange?: (color: string) => void;
|
|
100
|
+
/**
|
|
101
|
+
* Presets rendered in the menu palette.
|
|
102
|
+
*/
|
|
103
|
+
presets?: ColorPickerPaletteEntry[];
|
|
104
|
+
/**
|
|
105
|
+
* Legacy alias for `presets`.
|
|
106
|
+
*/
|
|
107
|
+
colors?: ColorPickerPaletteEntry[];
|
|
108
|
+
/**
|
|
109
|
+
* Whether to show the value input row.
|
|
110
|
+
*/
|
|
111
|
+
showValueInput?: boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Legacy alias for `showValueInput`.
|
|
114
|
+
*/
|
|
115
|
+
showHexInput?: boolean;
|
|
116
|
+
/**
|
|
117
|
+
* Placeholder text for the value input.
|
|
118
|
+
*/
|
|
119
|
+
valueInputPlaceholder?: string;
|
|
120
|
+
/**
|
|
121
|
+
* Legacy alias for `valueInputPlaceholder`.
|
|
122
|
+
*/
|
|
123
|
+
hexInputPlaceholder?: string;
|
|
124
|
+
/**
|
|
125
|
+
* Format emitted through `onChange`.
|
|
126
|
+
*/
|
|
127
|
+
valueFormat?: ColorPickerValueFormat;
|
|
128
|
+
/**
|
|
129
|
+
* Initial format shown in the value editor row.
|
|
130
|
+
*/
|
|
131
|
+
defaultInputFormat?: ColorPickerValueFormat;
|
|
132
|
+
/**
|
|
133
|
+
* Formats available in the value type dropdown.
|
|
134
|
+
*/
|
|
135
|
+
inputFormats?: ColorPickerValueFormat[];
|
|
136
|
+
/**
|
|
137
|
+
* Show the saturation/value selection field.
|
|
138
|
+
*/
|
|
139
|
+
showSpectrum?: boolean;
|
|
140
|
+
/**
|
|
141
|
+
* Show the hue slider.
|
|
142
|
+
*/
|
|
143
|
+
showHueSlider?: boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Show the opacity slider.
|
|
146
|
+
*/
|
|
147
|
+
showOpacitySlider?: boolean;
|
|
148
|
+
/**
|
|
149
|
+
* Show the eyedropper trigger.
|
|
150
|
+
*/
|
|
151
|
+
showEyedropper?: boolean;
|
|
152
|
+
/**
|
|
153
|
+
* Show the value format selector.
|
|
154
|
+
*/
|
|
155
|
+
showFormatSelector?: boolean;
|
|
156
|
+
/**
|
|
157
|
+
* Show the alpha / opacity text input.
|
|
158
|
+
*/
|
|
159
|
+
showOpacityInput?: boolean;
|
|
160
|
+
/**
|
|
161
|
+
* Size of the color picker
|
|
162
|
+
*/
|
|
163
|
+
size?: ColorPickerSize;
|
|
164
|
+
/**
|
|
165
|
+
* Override the swatch radius (CSS value or token).
|
|
166
|
+
*/
|
|
167
|
+
swatchRadius?: string;
|
|
168
|
+
/**
|
|
169
|
+
* Optional overlay content for each swatch.
|
|
170
|
+
*/
|
|
171
|
+
swatchContent?: (color: string) => React.ReactNode;
|
|
172
|
+
/**
|
|
173
|
+
* Additional className
|
|
174
|
+
*/
|
|
175
|
+
className?: string;
|
|
176
|
+
/**
|
|
177
|
+
* Disabled state
|
|
178
|
+
*/
|
|
179
|
+
disabled?: boolean;
|
|
180
|
+
/**
|
|
181
|
+
* Called when a color is selected from the swatches.
|
|
182
|
+
*/
|
|
183
|
+
onSelectColor?: (color: string) => void;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export interface ColorPickerProps extends ColorPickerContentProps {
|
|
187
|
+
/**
|
|
188
|
+
* Custom trigger element (if not provided, uses ColorPreview)
|
|
189
|
+
*/
|
|
190
|
+
trigger?: MenuDropdownProps["trigger"];
|
|
191
|
+
/**
|
|
192
|
+
* Label used by the default trigger.
|
|
193
|
+
*/
|
|
194
|
+
triggerLabel?: string;
|
|
195
|
+
/**
|
|
196
|
+
* Controlled open state for the dropdown.
|
|
197
|
+
*/
|
|
198
|
+
isOpen?: MenuDropdownProps["isOpen"];
|
|
199
|
+
/**
|
|
200
|
+
* Default open state for the dropdown.
|
|
201
|
+
*/
|
|
202
|
+
defaultOpen?: MenuDropdownProps["defaultOpen"];
|
|
203
|
+
/**
|
|
204
|
+
* Callback when dropdown open state changes.
|
|
205
|
+
*/
|
|
206
|
+
onOpenChange?: MenuDropdownProps["onOpenChange"];
|
|
207
|
+
/**
|
|
208
|
+
* Menu placement (align) for the dropdown.
|
|
209
|
+
*/
|
|
210
|
+
align?: MenuDropdownProps["align"];
|
|
211
|
+
/**
|
|
212
|
+
* Menu placement (side) for the dropdown.
|
|
213
|
+
*/
|
|
214
|
+
side?: MenuDropdownProps["side"];
|
|
215
|
+
/**
|
|
216
|
+
* Close the dropdown when a swatch is selected.
|
|
217
|
+
*/
|
|
218
|
+
closeOnSelect?: boolean;
|
|
219
|
+
/**
|
|
220
|
+
* Override the dropdown menu width.
|
|
221
|
+
*/
|
|
222
|
+
menuWidth?: React.CSSProperties["width"];
|
|
223
|
+
/**
|
|
224
|
+
* Override the dropdown menu height.
|
|
225
|
+
*/
|
|
226
|
+
menuHeight?: React.CSSProperties["height"];
|
|
227
|
+
/**
|
|
228
|
+
* Props passed to the Menu surface wrapper.
|
|
229
|
+
*/
|
|
230
|
+
menuProps?: Omit<MenuProps, "children">;
|
|
231
|
+
/**
|
|
232
|
+
* Accessible label for the dropdown content.
|
|
233
|
+
*/
|
|
234
|
+
contentAriaLabel?: MenuDropdownProps["contentAriaLabel"];
|
|
235
|
+
/**
|
|
236
|
+
* Custom class name for the wrapper element.
|
|
237
|
+
*/
|
|
238
|
+
wrapperClassName?: string;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export interface ColorPreviewProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
242
|
+
/**
|
|
243
|
+
* Color value to display (hex format)
|
|
244
|
+
*/
|
|
245
|
+
color: string;
|
|
246
|
+
/**
|
|
247
|
+
* Size of the color preview
|
|
248
|
+
*/
|
|
249
|
+
size?: ColorPickerSize;
|
|
250
|
+
/**
|
|
251
|
+
* Shape of the color preview
|
|
252
|
+
*/
|
|
253
|
+
shape?: "square" | "circle";
|
|
254
|
+
/**
|
|
255
|
+
* Whether to show a border
|
|
256
|
+
*/
|
|
257
|
+
showBorder?: boolean;
|
|
258
|
+
/**
|
|
259
|
+
* Label text to display next to the color
|
|
260
|
+
*/
|
|
261
|
+
label?: string;
|
|
262
|
+
/**
|
|
263
|
+
* Position of the label relative to the color preview
|
|
264
|
+
*/
|
|
265
|
+
labelPosition?: "left" | "right" | "top" | "bottom";
|
|
266
|
+
/**
|
|
267
|
+
* Additional className
|
|
268
|
+
*/
|
|
269
|
+
className?: string;
|
|
270
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React, { forwardRef } from "react";
|
|
2
|
+
import type { ColorPreviewProps } from "./ColorPicker.types";
|
|
3
|
+
import "./ColorPicker.scss";
|
|
4
|
+
|
|
5
|
+
function cx(...values: Array<string | false | null | undefined>) {
|
|
6
|
+
return values.filter(Boolean).join(" ");
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const ColorPreview = forwardRef<HTMLButtonElement, ColorPreviewProps>(
|
|
10
|
+
(
|
|
11
|
+
{
|
|
12
|
+
color,
|
|
13
|
+
size = "md",
|
|
14
|
+
shape = "square",
|
|
15
|
+
showBorder = true,
|
|
16
|
+
label,
|
|
17
|
+
labelPosition = "right",
|
|
18
|
+
className,
|
|
19
|
+
disabled = false,
|
|
20
|
+
...props
|
|
21
|
+
},
|
|
22
|
+
ref
|
|
23
|
+
) => {
|
|
24
|
+
return (
|
|
25
|
+
<button
|
|
26
|
+
ref={ref}
|
|
27
|
+
type={props.type ?? "button"}
|
|
28
|
+
className={cx("solara-color-preview", className)}
|
|
29
|
+
data-size={size}
|
|
30
|
+
data-shape={shape}
|
|
31
|
+
data-border={showBorder ? "true" : "false"}
|
|
32
|
+
data-label-position={label ? labelPosition : undefined}
|
|
33
|
+
data-disabled={disabled ? "true" : undefined}
|
|
34
|
+
disabled={disabled}
|
|
35
|
+
aria-label={`Color: ${color}`}
|
|
36
|
+
{...props}>
|
|
37
|
+
<span
|
|
38
|
+
className="solara-color-preview__swatch"
|
|
39
|
+
style={{ backgroundColor: color }}
|
|
40
|
+
aria-hidden="true"
|
|
41
|
+
/>
|
|
42
|
+
{label ? <span className="solara-color-preview__label">{label}</span> : null}
|
|
43
|
+
</button>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
ColorPreview.displayName = "ColorPreview";
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { ColorPicker, ColorPickerContent, ColorPickerPalette, ColorPickerSwatch } from "./ColorPicker";
|
|
2
|
+
export { ColorPreview } from "./ColorPreview";
|
|
3
|
+
export type {
|
|
4
|
+
ColorPickerProps,
|
|
5
|
+
ColorPickerContentProps,
|
|
6
|
+
ColorPickerPaletteProps,
|
|
7
|
+
ColorPickerPaletteEntry,
|
|
8
|
+
ColorPickerPaletteOption,
|
|
9
|
+
ColorPickerSwatchProps,
|
|
10
|
+
ColorPickerSize,
|
|
11
|
+
ColorPreviewProps,
|
|
12
|
+
} from "./ColorPicker.types";
|