@flikk/ui 1.0.0-beta.21 → 1.0.0-beta.22
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/components/ai/CodeBlock/CodeBlock.theme.js +2 -2
- package/dist/components/ai/PromptInput/PromptInput.theme.js +3 -3
- package/dist/components/ai/PromptSuggestions/PromptSuggestion.theme.js +1 -1
- package/dist/components/ai/StreamingResponse/StreamingResponse.theme.js +4 -4
- package/dist/components/ai/TokenCounter/TokenCounter.theme.js +6 -6
- package/dist/components/charts/ActivityRings/ActivityRings.theme.js +2 -2
- package/dist/components/charts/DonutChart/DonutChart.theme.js +2 -2
- package/dist/components/charts/DonutChart/MultiSegmentDonutChart.theme.js +1 -1
- package/dist/components/charts/Heatmap/Heatmap.theme.js +1 -1
- package/dist/components/charts/RadarChart/RadarChart.theme.js +2 -2
- package/dist/components/charts/ScatterPlot/ScatterPlot.theme.js +2 -2
- package/dist/components/charts/shared/ChartText/ChartText.theme.js +1 -1
- package/dist/components/charts/shared/ChartTooltip/ChartTooltip.theme.js +4 -4
- package/dist/components/core/Alert/Alert.theme.js +1 -1
- package/dist/components/core/Avatar/Avatar.theme.js +10 -10
- package/dist/components/core/AvatarGroup/AvatarGroup.theme.js +1 -1
- package/dist/components/core/Badge/Badge.js +2 -12
- package/dist/components/core/Badge/Badge.theme.js +2 -2
- package/dist/components/core/Button/Button.theme.js +6 -6
- package/dist/components/core/ButtonGroup/ButtonGroup.theme.js +1 -1
- package/dist/components/core/Calendar/Calendar.theme.js +5 -5
- package/dist/components/core/Card/Card.theme.js +2 -2
- package/dist/components/core/CommandPalette/CommandPalette.theme.js +4 -4
- package/dist/components/core/Drawer/Drawer.animations.js +5 -4
- package/dist/components/core/Drawer/Drawer.theme.js +2 -2
- package/dist/components/core/Dropdown/Dropdown.theme.js +1 -1
- package/dist/components/core/Empty/Empty.theme.js +2 -2
- package/dist/components/core/Icon/Icon.d.ts +3 -0
- package/dist/components/core/Icon/Icon.js +70 -0
- package/dist/components/core/Icon/Icon.theme.d.ts +2 -0
- package/dist/components/core/Icon/Icon.theme.js +19 -0
- package/dist/components/core/Icon/Icon.types.d.ts +32 -0
- package/dist/components/core/{FileTypeIcon → Icon/data}/fileTypes.d.ts +1 -1
- package/dist/components/core/Icon/data/paymentMethods.d.ts +27 -0
- package/dist/components/core/Icon/data/paymentMethods.js +169 -0
- package/dist/components/core/Icon/index.d.ts +4 -0
- package/dist/components/core/Kbd/Kbd.theme.js +2 -2
- package/dist/components/core/MenuItem/MenuItem.theme.js +2 -2
- package/dist/components/core/Message/Message.theme.js +6 -6
- package/dist/components/core/Modal/Modal.animations.js +3 -1
- package/dist/components/core/Modal/Modal.theme.js +2 -2
- package/dist/components/core/Modal/ModalBody.js +7 -8
- package/dist/components/core/NavItem/NavItem.theme.js +1 -1
- package/dist/components/core/OfflineIndicator/OfflineIndicator.theme.js +2 -2
- package/dist/components/core/PageHeading/PageHeading.theme.js +2 -2
- package/dist/components/core/Pagination/Pagination.theme.js +2 -2
- package/dist/components/core/Pill/Pill.theme.js +3 -3
- package/dist/components/core/Progress/Progress.theme.js +2 -2
- package/dist/components/core/Segmented/Segmented.theme.js +3 -3
- package/dist/components/core/Tabs/Tabs.theme.js +2 -2
- package/dist/components/core/Tag/Tag.theme.js +2 -2
- package/dist/components/core/Toast/Toast.theme.js +2 -2
- package/dist/components/core/Tooltip/Tooltip.theme.js +1 -1
- package/dist/components/core/Tree/Tree.theme.js +1 -1
- package/dist/components/core/index.d.ts +1 -2
- package/dist/components/core/index.js +2 -2
- package/dist/components/data-display/DescriptionList/DescriptionList.theme.js +2 -2
- package/dist/components/data-display/Feed/Feed.theme.js +1 -1
- package/dist/components/data-display/GanttChart/GanttChart.theme.js +2 -2
- package/dist/components/data-display/KPI/KPI.theme.js +9 -9
- package/dist/components/data-display/Metric/Metric.theme.js +9 -9
- package/dist/components/data-display/Table/Table.animations.js +16 -10
- package/dist/components/data-display/Table/Table.filterUtils.js +8 -1
- package/dist/components/data-display/Table/Table.js +10 -14
- package/dist/components/data-display/Table/Table.theme.js +3 -3
- package/dist/components/data-display/Table/Table.types.d.ts +2 -0
- package/dist/components/data-display/Table/TableActions.js +3 -3
- package/dist/components/data-display/Table/TableActionsMenu.js +2 -3
- package/dist/components/data-display/Table/TableCell.js +6 -3
- package/dist/components/data-display/Table/TableDeclarative.js +5 -7
- package/dist/components/data-display/Table/TableHeader.js +5 -2
- package/dist/components/data-display/Table/TablePagination.js +2 -6
- package/dist/components/data-display/Table/TableRow.js +2 -6
- package/dist/components/data-display/Table/index.js +1 -0
- package/dist/components/effects/CustomCursor/CustomCursor.theme.js +1 -1
- package/dist/components/effects/Overlay/Overlay.js +50 -21
- package/dist/components/forms/Checkbox/Checkbox.theme.js +3 -3
- package/dist/components/forms/ColorPicker/ColorPicker.d.ts +5 -9
- package/dist/components/forms/ColorPicker/ColorPicker.js +126 -22
- package/dist/components/forms/ColorPicker/ColorPicker.theme.js +9 -6
- package/dist/components/forms/ColorPicker/ColorPicker.types.d.ts +99 -0
- package/dist/components/forms/ColorPicker/ColorPicker2DCanvas.js +43 -6
- package/dist/components/forms/ColorPicker/ColorPickerBody.js +1 -1
- package/dist/components/forms/ColorPicker/ColorPickerContext.d.ts +4 -0
- package/dist/components/forms/ColorPicker/ColorPickerContext.js +12 -0
- package/dist/components/forms/ColorPicker/ColorPickerEyeDropper.js +1 -1
- package/dist/components/forms/ColorPicker/ColorPickerFormatSelector.js +1 -1
- package/dist/components/forms/ColorPicker/ColorPickerGradient.d.ts +7 -0
- package/dist/components/forms/ColorPicker/ColorPickerGradient.js +186 -0
- package/dist/components/forms/ColorPicker/ColorPickerHeader.d.ts +14 -0
- package/dist/components/forms/ColorPicker/ColorPickerHeader.js +31 -0
- package/dist/components/forms/ColorPicker/ColorPickerImage.d.ts +6 -0
- package/dist/components/forms/ColorPicker/ColorPickerImage.js +154 -0
- package/dist/components/forms/ColorPicker/ColorPickerInput.d.ts +0 -4
- package/dist/components/forms/ColorPicker/ColorPickerInput.js +53 -61
- package/dist/components/forms/ColorPicker/ColorPickerPresets.js +13 -12
- package/dist/components/forms/ColorPicker/ColorPickerSavedColors.d.ts +3 -0
- package/dist/components/forms/ColorPicker/ColorPickerSavedColors.js +69 -0
- package/dist/components/forms/ColorPicker/ColorPickerSliders.d.ts +1 -2
- package/dist/components/forms/ColorPicker/ColorPickerSliders.js +84 -23
- package/dist/components/forms/ColorPicker/ColorPickerSwatch.d.ts +1 -1
- package/dist/components/forms/ColorPicker/ColorPickerSwatch.js +10 -9
- package/dist/components/forms/ColorPicker/ColorPickerTrigger.js +7 -3
- package/dist/components/forms/ColorPicker/index.d.ts +8 -2
- package/dist/components/forms/CronInput/CronInput.theme.js +8 -8
- package/dist/components/forms/DatePicker/DatePicker.theme.js +1 -1
- package/dist/components/forms/DateRangePicker/DateRangePicker.theme.js +3 -3
- package/dist/components/forms/FileUpload/FileUpload.theme.js +4 -4
- package/dist/components/forms/FileUpload/FileUploadProgress.js +3 -3
- package/dist/components/forms/FileUpload/FileUploadProgress.theme.js +2 -2
- package/dist/components/forms/FormLabel/FormLabel.theme.js +1 -1
- package/dist/components/forms/Input/Input.js +3 -3
- package/dist/components/forms/Input/Input.theme.js +1 -1
- package/dist/components/forms/Input/Input.types.d.ts +2 -0
- package/dist/components/forms/InputCounter/InputCounter.theme.js +1 -1
- package/dist/components/forms/InputOTP/InputOTP.theme.js +1 -1
- package/dist/components/forms/Mention/Mention.theme.js +3 -3
- package/dist/components/forms/Radio/Radio.theme.js +3 -3
- package/dist/components/forms/RichTextEditor/RichTextEditor.theme.js +1 -1
- package/dist/components/forms/Select/Select.theme.js +1 -1
- package/dist/components/forms/SelectableCard/SelectableCard.js +42 -27
- package/dist/components/forms/SelectableCard/SelectableCard.theme.js +15 -25
- package/dist/components/forms/SelectableCard/SelectableCard.types.d.ts +16 -3
- package/dist/components/forms/SelectableCard/SelectableCardContext.d.ts +1 -0
- package/dist/components/forms/SelectableCard/SelectableCardContext.js +4 -7
- package/dist/components/forms/SelectableCard/SelectableCardGroup.js +31 -10
- package/dist/components/forms/SelectableCard/index.d.ts +1 -1
- package/dist/components/forms/Signature/Signature.theme.js +1 -1
- package/dist/components/forms/Slider/Slider.theme.js +3 -3
- package/dist/components/forms/Switch/Switch.theme.js +1 -1
- package/dist/components/forms/TimePicker/TimePicker.theme.js +2 -2
- package/dist/components/forms/forms.theme.js +6 -6
- package/dist/components/forms/index.js +6 -1
- package/dist/components/layout/FormLayout/FormLayout.theme.js +2 -2
- package/dist/hooks/useOverlay.d.ts +2 -0
- package/dist/hooks/useOverlay.js +34 -4
- package/dist/index.js +8 -3
- package/dist/styles.css +1 -1
- package/package.json +2 -1
- package/src/global.scss +1 -1
- package/dist/bg/bg/1.jpg +0 -0
- package/dist/bg/bg/10.jpg +0 -0
- package/dist/bg/bg/11.jpg +0 -0
- package/dist/bg/bg/14.jpg +0 -0
- package/dist/bg/bg/15.jpg +0 -0
- package/dist/bg/bg/16.jpg +0 -0
- package/dist/bg/bg/17.jpg +0 -0
- package/dist/bg/bg/18.jpg +0 -0
- package/dist/bg/bg/19.jpg +0 -0
- package/dist/bg/bg/2.jpg +0 -0
- package/dist/bg/bg/20.jpg +0 -0
- package/dist/bg/bg/21.jpg +0 -0
- package/dist/bg/bg/22.jpg +0 -0
- package/dist/bg/bg/23.jpg +0 -0
- package/dist/bg/bg/24.jpg +0 -0
- package/dist/bg/bg/3.jpg +0 -0
- package/dist/bg/bg/4.jpg +0 -0
- package/dist/bg/bg/5.jpg +0 -0
- package/dist/bg/bg/6.jpg +0 -0
- package/dist/bg/bg/7.jpg +0 -0
- package/dist/bg/bg/8.jpg +0 -0
- package/dist/bg/bg/9.jpg +0 -0
- package/dist/components/core/FileTypeIcon/FileTypeIcon.d.ts +0 -3
- package/dist/components/core/FileTypeIcon/FileTypeIcon.js +0 -33
- package/dist/components/core/FileTypeIcon/FileTypeIcon.theme.d.ts +0 -2
- package/dist/components/core/FileTypeIcon/FileTypeIcon.theme.js +0 -12
- package/dist/components/core/FileTypeIcon/FileTypeIcon.types.d.ts +0 -19
- package/dist/components/core/FileTypeIcon/index.d.ts +0 -2
- package/dist/components/core/SocialIcon/SocialIcon.d.ts +0 -3
- package/dist/components/core/SocialIcon/SocialIcon.js +0 -30
- package/dist/components/core/SocialIcon/SocialIcon.theme.d.ts +0 -2
- package/dist/components/core/SocialIcon/SocialIcon.theme.js +0 -12
- package/dist/components/core/SocialIcon/SocialIcon.types.d.ts +0 -18
- package/dist/components/core/SocialIcon/index.d.ts +0 -2
- /package/dist/components/core/{FileTypeIcon → Icon/data}/fileTypes.js +0 -0
- /package/dist/components/core/{SocialIcon → Icon/data}/platforms.d.ts +0 -0
- /package/dist/components/core/{SocialIcon → Icon/data}/platforms.js +0 -0
|
@@ -1,38 +1,37 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import React__default, {
|
|
2
|
+
import React__default, { useMemo, useState, useCallback, useRef, useEffect } from 'react';
|
|
3
3
|
import { cn } from '../../../utils/cn.js';
|
|
4
4
|
import { FormLabel } from '../FormLabel/FormLabel.js';
|
|
5
5
|
import { colorPickerTheme } from './ColorPicker.theme.js';
|
|
6
|
+
import { ColorPickerContext } from './ColorPickerContext.js';
|
|
6
7
|
import { ColorPicker2DCanvas } from './ColorPicker2DCanvas.js';
|
|
7
8
|
import { ColorPickerBody } from './ColorPickerBody.js';
|
|
8
9
|
import { ColorPickerEyeDropper } from './ColorPickerEyeDropper.js';
|
|
9
10
|
import { ColorPickerFormatSelector } from './ColorPickerFormatSelector.js';
|
|
11
|
+
import { ColorPickerGradient } from './ColorPickerGradient.js';
|
|
12
|
+
import { ColorPickerHeader } from './ColorPickerHeader.js';
|
|
13
|
+
import { ColorPickerImage } from './ColorPickerImage.js';
|
|
10
14
|
import { ColorPickerInput } from './ColorPickerInput.js';
|
|
11
15
|
import { ColorPickerPresets } from './ColorPickerPresets.js';
|
|
16
|
+
import { ColorPickerSavedColors } from './ColorPickerSavedColors.js';
|
|
12
17
|
import { ColorPickerSliders } from './ColorPickerSliders.js';
|
|
13
18
|
import { ColorPickerSwatch } from './ColorPickerSwatch.js';
|
|
14
19
|
import { ColorPickerTrigger } from './ColorPickerTrigger.js';
|
|
15
20
|
import { parseColor, formatHex, formatRgb, formatHsl } from './colorUtils.js';
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const useColorPicker = () => {
|
|
25
|
-
const context = React__default.useContext(ColorPickerContext);
|
|
26
|
-
if (!context) {
|
|
27
|
-
throw new Error('useColorPicker must be used within a ColorPicker component');
|
|
28
|
-
}
|
|
29
|
-
return context;
|
|
22
|
+
const DEFAULT_GRADIENT = {
|
|
23
|
+
type: 'linear',
|
|
24
|
+
angle: 90,
|
|
25
|
+
stops: [
|
|
26
|
+
{ id: 'stop-1', color: '#000000', position: 0 },
|
|
27
|
+
{ id: 'stop-2', color: '#FFFFFF', position: 100 },
|
|
28
|
+
],
|
|
30
29
|
};
|
|
31
30
|
/**
|
|
32
31
|
* ColorPicker Root Component
|
|
33
32
|
* Follows Flikkui compound component pattern (similar to Accordion, Tabs, Popover)
|
|
34
33
|
*/
|
|
35
|
-
const ColorPickerRoot = React__default.forwardRef(({ value, defaultValue = '#000000', onChange, format: initialFormat = 'hex', showAlpha = true, showEyeDropper = true, presetColors, size = 'md', state = 'default', disabled = false, label, helperText, required = false, theme, className, children, ...props }, ref) => {
|
|
34
|
+
const ColorPickerRoot = React__default.forwardRef(({ value, defaultValue = '#000000', onChange, format: initialFormat = 'hex', showAlpha = true, showEyeDropper = true, presetColors, savedColors: savedColorsProp, onSavedColorsChange, defaultMode = 'solid', mode: modeProp, onModeChange, gradientValue: gradientProp, onGradientChange, size = 'md', state = 'default', disabled = false, label, helperText, required = false, theme, className, children, ...props }, ref) => {
|
|
36
35
|
// Parse initial color value
|
|
37
36
|
const initialColor = useMemo(() => {
|
|
38
37
|
const parsed = parseColor(value || defaultValue);
|
|
@@ -41,8 +40,75 @@ const ColorPickerRoot = React__default.forwardRef(({ value, defaultValue = '#000
|
|
|
41
40
|
const [color, setColor] = useState(initialColor);
|
|
42
41
|
const [format, setFormat] = useState(initialFormat);
|
|
43
42
|
const [isOpen, setIsOpen] = useState(false);
|
|
43
|
+
// Mode state (controlled/uncontrolled)
|
|
44
|
+
const [internalMode, setInternalMode] = useState(defaultMode);
|
|
45
|
+
const mode = modeProp !== null && modeProp !== void 0 ? modeProp : internalMode;
|
|
46
|
+
const setMode = useCallback((m) => {
|
|
47
|
+
if (onModeChange) {
|
|
48
|
+
onModeChange(m);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
setInternalMode(m);
|
|
52
|
+
}
|
|
53
|
+
}, [onModeChange]);
|
|
54
|
+
// Gradient state (controlled/uncontrolled)
|
|
55
|
+
const [internalGradient, setInternalGradient] = useState(gradientProp || DEFAULT_GRADIENT);
|
|
56
|
+
const gradient = gradientProp !== null && gradientProp !== void 0 ? gradientProp : internalGradient;
|
|
57
|
+
const setGradient = useCallback((g) => {
|
|
58
|
+
if (onGradientChange) {
|
|
59
|
+
onGradientChange(g);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
setInternalGradient(g);
|
|
63
|
+
}
|
|
64
|
+
}, [onGradientChange]);
|
|
65
|
+
const updateGradientStop = useCallback((id, updates) => {
|
|
66
|
+
const newGradient = {
|
|
67
|
+
...gradient,
|
|
68
|
+
stops: gradient.stops.map(s => s.id === id ? { ...s, ...updates } : s),
|
|
69
|
+
};
|
|
70
|
+
setGradient(newGradient);
|
|
71
|
+
}, [gradient, setGradient]);
|
|
72
|
+
const addGradientStop = useCallback((position) => {
|
|
73
|
+
const newStop = {
|
|
74
|
+
id: `stop-${Date.now()}`,
|
|
75
|
+
color: formatHex(color.h, color.s, color.l),
|
|
76
|
+
position: Math.round(position),
|
|
77
|
+
};
|
|
78
|
+
setGradient({
|
|
79
|
+
...gradient,
|
|
80
|
+
stops: [...gradient.stops, newStop].sort((a, b) => a.position - b.position),
|
|
81
|
+
});
|
|
82
|
+
}, [gradient, setGradient, color]);
|
|
83
|
+
const removeGradientStop = useCallback((id) => {
|
|
84
|
+
if (gradient.stops.length <= 2)
|
|
85
|
+
return;
|
|
86
|
+
setGradient({
|
|
87
|
+
...gradient,
|
|
88
|
+
stops: gradient.stops.filter(s => s.id !== id),
|
|
89
|
+
});
|
|
90
|
+
}, [gradient, setGradient]);
|
|
44
91
|
// Refs for positioning (like Dropdown)
|
|
45
92
|
const triggerRef = useRef(null);
|
|
93
|
+
// Saved colors (controlled/uncontrolled)
|
|
94
|
+
const [internalSavedColors, setInternalSavedColors] = useState([]);
|
|
95
|
+
const savedColors = savedColorsProp !== null && savedColorsProp !== void 0 ? savedColorsProp : internalSavedColors;
|
|
96
|
+
const setSavedColors = useCallback((colors) => {
|
|
97
|
+
if (onSavedColorsChange) {
|
|
98
|
+
onSavedColorsChange(colors);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
setInternalSavedColors(colors);
|
|
102
|
+
}
|
|
103
|
+
}, [onSavedColorsChange]);
|
|
104
|
+
const addSavedColor = useCallback((colorValue) => {
|
|
105
|
+
if (!savedColors.includes(colorValue)) {
|
|
106
|
+
setSavedColors([...savedColors, colorValue]);
|
|
107
|
+
}
|
|
108
|
+
}, [savedColors, setSavedColors]);
|
|
109
|
+
const removeSavedColor = useCallback((index) => {
|
|
110
|
+
setSavedColors(savedColors.filter((_, i) => i !== index));
|
|
111
|
+
}, [savedColors, setSavedColors]);
|
|
46
112
|
// Update color when controlled value changes
|
|
47
113
|
useEffect(() => {
|
|
48
114
|
if (value !== undefined) {
|
|
@@ -87,15 +153,27 @@ const ColorPickerRoot = React__default.forwardRef(({ value, defaultValue = '#000
|
|
|
87
153
|
return getHexValue();
|
|
88
154
|
}
|
|
89
155
|
}, [format, getHexValue, getRgbValue, getHslValue]);
|
|
156
|
+
// Get output value (accounts for mode)
|
|
157
|
+
const getOutputValue = useCallback(() => {
|
|
158
|
+
if (mode === 'gradient') {
|
|
159
|
+
const sortedStops = [...gradient.stops].sort((a, b) => a.position - b.position);
|
|
160
|
+
const stopStrings = sortedStops.map(s => `${s.color} ${s.position}%`).join(', ');
|
|
161
|
+
if (gradient.type === 'linear') {
|
|
162
|
+
return `linear-gradient(${gradient.angle}deg, ${stopStrings})`;
|
|
163
|
+
}
|
|
164
|
+
return `radial-gradient(circle, ${stopStrings})`;
|
|
165
|
+
}
|
|
166
|
+
return getFormattedValue();
|
|
167
|
+
}, [mode, gradient, getFormattedValue]);
|
|
90
168
|
// Notify parent of color changes
|
|
91
|
-
const
|
|
169
|
+
const prevOutputRef = useRef(undefined);
|
|
92
170
|
useEffect(() => {
|
|
93
|
-
const
|
|
94
|
-
if (onChange && !disabled &&
|
|
95
|
-
|
|
96
|
-
onChange(
|
|
171
|
+
const output = getOutputValue();
|
|
172
|
+
if (onChange && !disabled && output !== prevOutputRef.current) {
|
|
173
|
+
prevOutputRef.current = output;
|
|
174
|
+
onChange(output);
|
|
97
175
|
}
|
|
98
|
-
}, [color, format, onChange, disabled,
|
|
176
|
+
}, [color, format, mode, gradient, onChange, disabled, getOutputValue]);
|
|
99
177
|
// Merge theme
|
|
100
178
|
const mergedTheme = useMemo(() => ({
|
|
101
179
|
...colorPickerTheme,
|
|
@@ -111,6 +189,13 @@ const ColorPickerRoot = React__default.forwardRef(({ value, defaultValue = '#000
|
|
|
111
189
|
setAlpha,
|
|
112
190
|
format,
|
|
113
191
|
setFormat,
|
|
192
|
+
mode,
|
|
193
|
+
setMode,
|
|
194
|
+
gradient,
|
|
195
|
+
setGradient,
|
|
196
|
+
updateGradientStop,
|
|
197
|
+
addGradientStop,
|
|
198
|
+
removeGradientStop,
|
|
114
199
|
isOpen,
|
|
115
200
|
setIsOpen,
|
|
116
201
|
triggerRef,
|
|
@@ -127,7 +212,11 @@ const ColorPickerRoot = React__default.forwardRef(({ value, defaultValue = '#000
|
|
|
127
212
|
getRgbValue,
|
|
128
213
|
getHslValue,
|
|
129
214
|
getFormattedValue,
|
|
215
|
+
getOutputValue,
|
|
130
216
|
onChange,
|
|
217
|
+
savedColors,
|
|
218
|
+
addSavedColor,
|
|
219
|
+
removeSavedColor,
|
|
131
220
|
}), [
|
|
132
221
|
color,
|
|
133
222
|
setColor,
|
|
@@ -137,6 +226,13 @@ const ColorPickerRoot = React__default.forwardRef(({ value, defaultValue = '#000
|
|
|
137
226
|
setAlpha,
|
|
138
227
|
format,
|
|
139
228
|
setFormat,
|
|
229
|
+
mode,
|
|
230
|
+
setMode,
|
|
231
|
+
gradient,
|
|
232
|
+
setGradient,
|
|
233
|
+
updateGradientStop,
|
|
234
|
+
addGradientStop,
|
|
235
|
+
removeGradientStop,
|
|
140
236
|
isOpen,
|
|
141
237
|
setIsOpen,
|
|
142
238
|
showAlpha,
|
|
@@ -150,7 +246,11 @@ const ColorPickerRoot = React__default.forwardRef(({ value, defaultValue = '#000
|
|
|
150
246
|
getRgbValue,
|
|
151
247
|
getHslValue,
|
|
152
248
|
getFormattedValue,
|
|
249
|
+
getOutputValue,
|
|
153
250
|
onChange,
|
|
251
|
+
savedColors,
|
|
252
|
+
addSavedColor,
|
|
253
|
+
removeSavedColor,
|
|
154
254
|
]);
|
|
155
255
|
return (jsx(ColorPickerContext.Provider, { value: contextValue, children: jsxs("div", { ref: ref, className: cn(mergedTheme.baseStyle, className), ...props, children: [label && (jsx(FormLabel, { htmlFor: "color-picker", required: required, state: state, children: label })), children, helperText && (jsx("div", { className: cn('mt-1.5 text-sm text-[var(--color-text-secondary)]', state === 'invalid' && 'text-[var(--color-danger)]'), children: helperText }))] }) }));
|
|
156
256
|
});
|
|
@@ -161,6 +261,7 @@ ColorPickerRoot.displayName = 'ColorPicker';
|
|
|
161
261
|
*/
|
|
162
262
|
const ColorPicker = Object.assign(ColorPickerRoot, {
|
|
163
263
|
Trigger: ColorPickerTrigger,
|
|
264
|
+
Header: ColorPickerHeader,
|
|
164
265
|
Body: ColorPickerBody,
|
|
165
266
|
Canvas: ColorPicker2DCanvas,
|
|
166
267
|
Swatch: ColorPickerSwatch,
|
|
@@ -169,6 +270,9 @@ const ColorPicker = Object.assign(ColorPickerRoot, {
|
|
|
169
270
|
FormatSelector: ColorPickerFormatSelector,
|
|
170
271
|
EyeDropper: ColorPickerEyeDropper,
|
|
171
272
|
Presets: ColorPickerPresets,
|
|
273
|
+
SavedColors: ColorPickerSavedColors,
|
|
274
|
+
Gradient: ColorPickerGradient,
|
|
275
|
+
ImagePicker: ColorPickerImage,
|
|
172
276
|
});
|
|
173
277
|
|
|
174
|
-
export { ColorPicker
|
|
278
|
+
export { ColorPicker };
|
|
@@ -6,15 +6,18 @@ const colorPickerTheme = {
|
|
|
6
6
|
baseStyle: 'relative inline-block w-full',
|
|
7
7
|
triggerStyle: 'cursor-pointer',
|
|
8
8
|
swatchStyle: 'relative size-5 flex-shrink-0 rounded border border-[var(--color-border)] overflow-hidden',
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
sliderLabelStyle: 'flex items-center justify-between text-sm font-medium text-[var(--color-text-secondary)]',
|
|
9
|
+
contentStyle: 'min-w-[min(300px,calc(100vw-2rem))] max-w-[340px] rounded-xl border border-[var(--color-border)] bg-[var(--color-surface)] shadow-real-xl p-4 space-y-3 focus:outline-none',
|
|
10
|
+
sliderContainerStyle: 'space-y-2.5',
|
|
11
|
+
sliderLabelStyle: 'flex items-center justify-between text-xs font-medium text-[var(--color-text-secondary)]',
|
|
13
12
|
inputContainerStyle: 'flex items-center gap-2',
|
|
14
13
|
formatSelectorStyle: 'flex-shrink-0',
|
|
15
|
-
presetGridStyle: '
|
|
16
|
-
presetSwatchStyle: 'relative size-
|
|
14
|
+
presetGridStyle: 'grid grid-cols-8 gap-2',
|
|
15
|
+
presetSwatchStyle: 'relative size-6 cursor-pointer rounded-md border-2 border-transparent transition-all hover:border-[var(--color-primary)] hover:scale-110 focus:border-[var(--color-primary)] focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] focus:ring-opacity-20 data-[selected]:border-[var(--color-primary)] data-[selected]:ring-2 data-[selected]:ring-[var(--color-primary)] data-[selected]:ring-opacity-20',
|
|
17
16
|
eyedropperButtonStyle: 'flex-shrink-0',
|
|
17
|
+
sectionLabelStyle: 'text-xs font-medium text-[var(--color-text-muted)] mb-2',
|
|
18
|
+
savedColorsGridStyle: 'grid grid-cols-8 gap-2',
|
|
19
|
+
savedColorsAddButtonStyle: 'size-6 rounded-md border-2 border-dashed border-[var(--color-border)] flex items-center justify-center hover:border-[var(--color-primary)] cursor-pointer transition-colors text-[var(--color-text-muted)] hover:text-[var(--color-primary)]',
|
|
20
|
+
colorPreviewStyle: 'relative size-8 flex-shrink-0 rounded-lg border border-[var(--color-border)] overflow-hidden',
|
|
18
21
|
};
|
|
19
22
|
|
|
20
23
|
export { colorPickerTheme };
|
|
@@ -3,6 +3,24 @@ import type { HSLA } from './colorUtils';
|
|
|
3
3
|
export type ColorFormat = 'hex' | 'rgb' | 'hsl' | 'hsv';
|
|
4
4
|
export type ColorPickerSize = 'sm' | 'md' | 'lg';
|
|
5
5
|
export type ColorPickerState = 'default' | 'invalid' | 'disabled';
|
|
6
|
+
export type ColorPickerMode = 'solid' | 'gradient' | 'image';
|
|
7
|
+
export type GradientType = 'linear' | 'radial';
|
|
8
|
+
/**
|
|
9
|
+
* A single gradient color stop
|
|
10
|
+
*/
|
|
11
|
+
export interface GradientStop {
|
|
12
|
+
id: string;
|
|
13
|
+
color: string;
|
|
14
|
+
position: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Full gradient state
|
|
18
|
+
*/
|
|
19
|
+
export interface GradientState {
|
|
20
|
+
type: GradientType;
|
|
21
|
+
angle: number;
|
|
22
|
+
stops: GradientStop[];
|
|
23
|
+
}
|
|
6
24
|
/**
|
|
7
25
|
* Root ColorPicker component props
|
|
8
26
|
*/
|
|
@@ -39,6 +57,14 @@ export interface ColorPickerProps extends Omit<React.HTMLAttributes<HTMLDivEleme
|
|
|
39
57
|
* Array of preset colors to display
|
|
40
58
|
*/
|
|
41
59
|
presetColors?: string[];
|
|
60
|
+
/**
|
|
61
|
+
* Controlled saved colors array
|
|
62
|
+
*/
|
|
63
|
+
savedColors?: string[];
|
|
64
|
+
/**
|
|
65
|
+
* Callback when saved colors change
|
|
66
|
+
*/
|
|
67
|
+
onSavedColorsChange?: (colors: string[]) => void;
|
|
42
68
|
/**
|
|
43
69
|
* Size of the color picker
|
|
44
70
|
* @default 'md'
|
|
@@ -67,6 +93,27 @@ export interface ColorPickerProps extends Omit<React.HTMLAttributes<HTMLDivEleme
|
|
|
67
93
|
* @default false
|
|
68
94
|
*/
|
|
69
95
|
required?: boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Default mode
|
|
98
|
+
* @default 'solid'
|
|
99
|
+
*/
|
|
100
|
+
defaultMode?: ColorPickerMode;
|
|
101
|
+
/**
|
|
102
|
+
* Controlled mode
|
|
103
|
+
*/
|
|
104
|
+
mode?: ColorPickerMode;
|
|
105
|
+
/**
|
|
106
|
+
* Callback when mode changes
|
|
107
|
+
*/
|
|
108
|
+
onModeChange?: (mode: ColorPickerMode) => void;
|
|
109
|
+
/**
|
|
110
|
+
* Controlled gradient value
|
|
111
|
+
*/
|
|
112
|
+
gradientValue?: GradientState;
|
|
113
|
+
/**
|
|
114
|
+
* Callback when gradient changes
|
|
115
|
+
*/
|
|
116
|
+
onGradientChange?: (gradient: GradientState) => void;
|
|
70
117
|
/**
|
|
71
118
|
* Theme overrides
|
|
72
119
|
*/
|
|
@@ -92,6 +139,13 @@ export interface ColorPickerContextValue {
|
|
|
92
139
|
setAlpha: (a: number) => void;
|
|
93
140
|
format: ColorFormat;
|
|
94
141
|
setFormat: (format: ColorFormat) => void;
|
|
142
|
+
mode: ColorPickerMode;
|
|
143
|
+
setMode: (mode: ColorPickerMode) => void;
|
|
144
|
+
gradient: GradientState;
|
|
145
|
+
setGradient: (gradient: GradientState) => void;
|
|
146
|
+
updateGradientStop: (id: string, updates: Partial<GradientStop>) => void;
|
|
147
|
+
addGradientStop: (position: number) => void;
|
|
148
|
+
removeGradientStop: (id: string) => void;
|
|
95
149
|
isOpen: boolean;
|
|
96
150
|
setIsOpen: (open: boolean) => void;
|
|
97
151
|
triggerRef: React.RefObject<HTMLElement>;
|
|
@@ -108,7 +162,11 @@ export interface ColorPickerContextValue {
|
|
|
108
162
|
getRgbValue: () => string;
|
|
109
163
|
getHslValue: () => string;
|
|
110
164
|
getFormattedValue: () => string;
|
|
165
|
+
getOutputValue: () => string;
|
|
111
166
|
onChange?: (value: string) => void;
|
|
167
|
+
savedColors: string[];
|
|
168
|
+
addSavedColor: (color: string) => void;
|
|
169
|
+
removeSavedColor: (index: number) => void;
|
|
112
170
|
}
|
|
113
171
|
/**
|
|
114
172
|
* ColorPicker theme overrides
|
|
@@ -125,6 +183,10 @@ export interface ColorPickerThemeOverrides {
|
|
|
125
183
|
presetGridStyle?: string;
|
|
126
184
|
presetSwatchStyle?: string;
|
|
127
185
|
eyedropperButtonStyle?: string;
|
|
186
|
+
sectionLabelStyle?: string;
|
|
187
|
+
savedColorsGridStyle?: string;
|
|
188
|
+
savedColorsAddButtonStyle?: string;
|
|
189
|
+
colorPreviewStyle?: string;
|
|
128
190
|
}
|
|
129
191
|
/**
|
|
130
192
|
* ColorPicker theme
|
|
@@ -141,6 +203,10 @@ export interface ColorPickerTheme {
|
|
|
141
203
|
presetGridStyle: string;
|
|
142
204
|
presetSwatchStyle: string;
|
|
143
205
|
eyedropperButtonStyle: string;
|
|
206
|
+
sectionLabelStyle: string;
|
|
207
|
+
savedColorsGridStyle: string;
|
|
208
|
+
savedColorsAddButtonStyle: string;
|
|
209
|
+
colorPreviewStyle: string;
|
|
144
210
|
}
|
|
145
211
|
/**
|
|
146
212
|
* ColorPickerTrigger props
|
|
@@ -215,5 +281,38 @@ export interface ColorPickerPresetsProps extends React.HTMLAttributes<HTMLDivEle
|
|
|
215
281
|
* Custom preset colors (overrides context presetColors)
|
|
216
282
|
*/
|
|
217
283
|
colors?: string[];
|
|
284
|
+
/**
|
|
285
|
+
* Section label text. Set to false to hide.
|
|
286
|
+
* @default "Preset colors"
|
|
287
|
+
*/
|
|
288
|
+
label?: string | false;
|
|
289
|
+
className?: string;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* ColorPickerSavedColors props
|
|
293
|
+
*/
|
|
294
|
+
export interface ColorPickerSavedColorsProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
295
|
+
/**
|
|
296
|
+
* Section label text. Set to false to hide.
|
|
297
|
+
* @default "Saved colors"
|
|
298
|
+
*/
|
|
299
|
+
label?: string | false;
|
|
300
|
+
/**
|
|
301
|
+
* Maximum number of saved colors
|
|
302
|
+
* @default 16
|
|
303
|
+
*/
|
|
304
|
+
maxColors?: number;
|
|
305
|
+
className?: string;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* ColorPickerGradient props
|
|
309
|
+
*/
|
|
310
|
+
export interface ColorPickerGradientProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
311
|
+
className?: string;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* ColorPickerImage props
|
|
315
|
+
*/
|
|
316
|
+
export interface ColorPickerImageProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
218
317
|
className?: string;
|
|
219
318
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { useContext, useRef, useState, useCallback, useEffect } from 'react';
|
|
3
3
|
import { cn } from '../../../utils/cn.js';
|
|
4
|
-
import { ColorPickerContext } from './
|
|
5
|
-
import { hslToRgb, rgbToHsv } from './colorUtils.js';
|
|
4
|
+
import { ColorPickerContext } from './ColorPickerContext.js';
|
|
5
|
+
import { hslToRgb, formatRgb, rgbToHsv } from './colorUtils.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* ColorPicker2DCanvas - Main 2D draggable color picker
|
|
@@ -72,19 +72,56 @@ const ColorPicker2DCanvas = ({ className }) => {
|
|
|
72
72
|
};
|
|
73
73
|
}
|
|
74
74
|
}, [isDragging, handlePointerMove, handlePointerUp]);
|
|
75
|
+
// Keyboard navigation handler
|
|
76
|
+
const handleKeyDown = useCallback((e) => {
|
|
77
|
+
const arrowKeys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'];
|
|
78
|
+
if (!arrowKeys.includes(e.key))
|
|
79
|
+
return;
|
|
80
|
+
e.preventDefault();
|
|
81
|
+
const step = e.shiftKey ? 10 : 1;
|
|
82
|
+
let newS = hsv.s;
|
|
83
|
+
let newV = hsv.v;
|
|
84
|
+
switch (e.key) {
|
|
85
|
+
case 'ArrowRight':
|
|
86
|
+
newS = Math.min(100, newS + step);
|
|
87
|
+
break;
|
|
88
|
+
case 'ArrowLeft':
|
|
89
|
+
newS = Math.max(0, newS - step);
|
|
90
|
+
break;
|
|
91
|
+
case 'ArrowUp':
|
|
92
|
+
newV = Math.min(100, newV + step);
|
|
93
|
+
break;
|
|
94
|
+
case 'ArrowDown':
|
|
95
|
+
newV = Math.max(0, newV - step);
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
// Convert HSV back to HSL (same conversion as updateColorFromPosition)
|
|
99
|
+
color.h;
|
|
100
|
+
const l = ((2 - newS / 100) * newV) / 2;
|
|
101
|
+
const sl = l !== 0 && l !== 100
|
|
102
|
+
? ((newV - l) / Math.min(l, 100 - l)) * 100
|
|
103
|
+
: 0;
|
|
104
|
+
setColor({
|
|
105
|
+
...color,
|
|
106
|
+
s: Math.round(sl),
|
|
107
|
+
l: Math.round(l),
|
|
108
|
+
});
|
|
109
|
+
}, [color, setColor, hsv.s, hsv.v]);
|
|
75
110
|
// Background gradient based on current hue
|
|
76
111
|
const hueColor = `hsl(${color.h}, 100%, 50%)`;
|
|
77
|
-
|
|
112
|
+
// Current picked color for the inner circle
|
|
113
|
+
const rgbaColor = formatRgb(color.h, color.s, color.l, color.a);
|
|
114
|
+
return (jsx("div", { ref: canvasRef, onPointerDown: handlePointerDown, onKeyDown: handleKeyDown, className: cn('relative w-full h-[200px] cursor-crosshair rounded-xl ring-1 ring-inset ring-black/5 overflow-hidden touch-none select-none', className), style: {
|
|
78
115
|
background: `
|
|
79
116
|
linear-gradient(to top, #000, transparent),
|
|
80
117
|
linear-gradient(to right, #fff, ${hueColor})
|
|
81
118
|
`,
|
|
82
|
-
}, role: "slider", "aria-label": "Color saturation and brightness", "aria-valuemin": 0, "aria-valuemax": 100, tabIndex: 0, children: jsx("div", { className: "absolute w-
|
|
119
|
+
}, role: "slider", "aria-label": "Color saturation and brightness", "aria-valuemin": 0, "aria-valuemax": 100, tabIndex: 0, children: jsx("div", { className: "absolute w-5 h-5 border-2 border-white rounded-full pointer-events-none", style: {
|
|
83
120
|
left: `${positionX * 100}%`,
|
|
84
121
|
top: `${positionY * 100}%`,
|
|
85
122
|
transform: 'translate(-50%, -50%)',
|
|
86
|
-
boxShadow: '0 0 0
|
|
87
|
-
} }) }));
|
|
123
|
+
boxShadow: '0 0 0 1.5px rgba(0,0,0,0.15), 0 2px 6px rgba(0,0,0,0.15)',
|
|
124
|
+
}, children: jsx("div", { className: "absolute inset-1 rounded-full", style: { backgroundColor: rgbaColor } }) }) }));
|
|
88
125
|
};
|
|
89
126
|
ColorPicker2DCanvas.displayName = 'ColorPicker2DCanvas';
|
|
90
127
|
|
|
@@ -6,7 +6,7 @@ import { useSelectPortal } from '../../../hooks/useSelectPortal.js';
|
|
|
6
6
|
import { cn } from '../../../utils/cn.js';
|
|
7
7
|
import { useClickOutside } from '../../../hooks/useClickOutside.js';
|
|
8
8
|
import { contentVariants } from './ColorPicker.animations.js';
|
|
9
|
-
import { ColorPickerContext } from './
|
|
9
|
+
import { ColorPickerContext } from './ColorPickerContext.js';
|
|
10
10
|
import { useIsClient } from '../../../hooks/useIsClient.js';
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React__default, { createContext } from 'react';
|
|
2
|
+
|
|
3
|
+
const ColorPickerContext = createContext(undefined);
|
|
4
|
+
const useColorPicker = () => {
|
|
5
|
+
const context = React__default.useContext(ColorPickerContext);
|
|
6
|
+
if (!context) {
|
|
7
|
+
throw new Error('useColorPicker must be used within a ColorPicker component');
|
|
8
|
+
}
|
|
9
|
+
return context;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export { ColorPickerContext, useColorPicker };
|
|
@@ -3,7 +3,7 @@ import { EyeDropperIcon } from '@heroicons/react/20/solid';
|
|
|
3
3
|
import { useContext } from 'react';
|
|
4
4
|
import { cn } from '../../../utils/cn.js';
|
|
5
5
|
import { Button } from '../../core/Button/Button.js';
|
|
6
|
-
import { ColorPickerContext } from './
|
|
6
|
+
import { ColorPickerContext } from './ColorPickerContext.js';
|
|
7
7
|
import { parseColor } from './colorUtils.js';
|
|
8
8
|
|
|
9
9
|
// Check if browser supports EyeDropper API
|
|
@@ -3,7 +3,7 @@ import { useContext } from 'react';
|
|
|
3
3
|
import { cn } from '../../../utils/cn.js';
|
|
4
4
|
import { Select } from '../Select/Select.js';
|
|
5
5
|
import '../Select/Select.theme.js';
|
|
6
|
-
import { ColorPickerContext } from './
|
|
6
|
+
import { ColorPickerContext } from './ColorPickerContext.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* ColorPickerFormatSelector - Dropdown to select color format (HEX/RGB/HSL)
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ColorPickerGradientProps } from './ColorPicker.types';
|
|
3
|
+
/**
|
|
4
|
+
* ColorPickerGradient - Gradient editor with canvas, sliders, stop bar, type toggle, angle control.
|
|
5
|
+
* The 2D canvas and hue slider pick the color for the currently selected gradient stop.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ColorPickerGradient: React.FC<ColorPickerGradientProps>;
|