diff --git a/playground/src/App.tsx b/playground/src/App.tsx index d4f8bf3..4ee580f 100644 --- a/playground/src/App.tsx +++ b/playground/src/App.tsx @@ -204,17 +204,17 @@ export default function App() {
-

Color Wheel Mode

+

Flower Color Wheel Mode

- Starts in Wheel Mode: + Color Picker:

{color4()}

diff --git a/src/components/colorpicker/ColorPicker.tsx b/src/components/colorpicker/ColorPicker.tsx index 0179419..b6fc73a 100644 --- a/src/components/colorpicker/ColorPicker.tsx +++ b/src/components/colorpicker/ColorPicker.tsx @@ -14,6 +14,7 @@ import SaturationBrightness from "./SaturationBrightness"; import HueSlider from "./HueSlider"; import AlphaSlider from "./AlphaSlider"; import ColorWheel from "./ColorWheel"; +import ColorWheelFlower from "./ColorWheelFlower"; import LightnessSlider from "./LightnessSlider"; import ColorSwatches from "./ColorSwatches"; import ColorInput from "./ColorInput"; @@ -22,7 +23,7 @@ import { IComponentBaseProps } from "../types"; import { MotionDiv, motionPresets } from "../../motion"; export type { ColorFormat } from "./ColorUtils"; -export type ColorPickerMode = "picker" | "wheel"; +export type ColorPickerMode = "picker" | "wheel" | "flower"; export interface ColorPickerProps extends IComponentBaseProps { value?: string; @@ -189,6 +190,19 @@ const ColorPicker = (props: ColorPickerProps): JSX.Element => { > Wheel +
); @@ -213,6 +227,11 @@ const ColorPicker = (props: ColorPickerProps): JSX.Element => { + + + + + diff --git a/src/components/colorpicker/ColorWheelFlower.tsx b/src/components/colorpicker/ColorWheelFlower.tsx new file mode 100644 index 0000000..f9a82a8 --- /dev/null +++ b/src/components/colorpicker/ColorWheelFlower.tsx @@ -0,0 +1,204 @@ +import { type JSX, createSignal, For } from "solid-js"; +import { clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; +import { useColorPickerContext } from "./colorpickerContext"; +import { rgbToHsl, createColorFromHsl } from "./ColorUtils"; + +export interface ColorWheelFlowerProps { + class?: string; + className?: string; +} + +type ColorItem = { + rgb: string; + transform: string; + hue: number; + saturation: number; + lightness: number; +}; + + +const parseRgbToHsl = (rgbString: string) => { + const match = rgbString.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/); + if (!match) return { hue: 0, saturation: 0, lightness: 100 }; + + const r = parseInt(match[1]); + const g = parseInt(match[2]); + const b = parseInt(match[3]); + + const hsl = rgbToHsl(r, g, b); + return { hue: hsl.h, saturation: hsl.s, lightness: hsl.l }; +}; + + +const COLORS: ColorItem[] = [ + { rgb: "rgb(245,245,61)", transform: "translateX(34.641px) translateY(-20px)", ...parseRgbToHsl("rgb(245,245,61)") }, + { rgb: "rgb(245,153,61)", transform: "translateX(20px) translateY(-34.641px)", ...parseRgbToHsl("rgb(245,153,61)") }, + { rgb: "rgb(245,61,61)", transform: "translateY(-40px)", ...parseRgbToHsl("rgb(245,61,61)") }, + { rgb: "rgb(245,61,153)", transform: "translateX(-20px) translateY(-34.641px)", ...parseRgbToHsl("rgb(245,61,153)") }, + { rgb: "rgb(245,61,245)", transform: "translateX(-34.641px) translateY(-20px)", ...parseRgbToHsl("rgb(245,61,245)") }, + { rgb: "rgb(153,61,245)", transform: "translateX(-40px)", ...parseRgbToHsl("rgb(153,61,245)") }, + { rgb: "rgb(61,61,245)", transform: "translateX(-34.641px) translateY(20px)", ...parseRgbToHsl("rgb(61,61,245)") }, + { rgb: "rgb(61,153,245)", transform: "translateX(-20px) translateY(34.641px)", ...parseRgbToHsl("rgb(61,153,245)") }, + { rgb: "rgb(61,245,245)", transform: "translateY(40px)", ...parseRgbToHsl("rgb(61,245,245)") }, + { rgb: "rgb(61,245,153)", transform: "translateX(20px) translateY(34.641px)", ...parseRgbToHsl("rgb(61,245,153)") }, + { rgb: "rgb(61,245,61)", transform: "translateX(34.641px) translateY(20px)", ...parseRgbToHsl("rgb(61,245,61)") }, + { rgb: "rgb(153,245,61)", transform: "translateX(40px)", ...parseRgbToHsl("rgb(153,245,61)") }, + { rgb: "rgb(240,217,194)", transform: "translateX(10px) translateY(-17.3205px)", ...parseRgbToHsl("rgb(240,217,194)") }, + { rgb: "rgb(240,194,217)", transform: "translateX(-10px) translateY(-17.3205px)", ...parseRgbToHsl("rgb(240,194,217)") }, + { rgb: "rgb(217,194,240)", transform: "translateX(-20px)", ...parseRgbToHsl("rgb(217,194,240)") }, + { rgb: "rgb(194,217,240)", transform: "translateX(-10px) translateY(17.3205px)", ...parseRgbToHsl("rgb(194,217,240)") }, + { rgb: "rgb(194,240,217)", transform: "translateX(10px) translateY(17.3205px)", ...parseRgbToHsl("rgb(194,240,217)") }, + { rgb: "rgb(217,240,194)", transform: "translateX(20px)", ...parseRgbToHsl("rgb(217,240,194)") }, + { rgb: "rgb(255,255,255)", transform: "none", ...parseRgbToHsl("rgb(255,255,255)") }, +]; + + +const RAINBOW_GRADIENT = `conic-gradient( + from 0deg, + rgb(245,61,61) 0deg, + rgb(245,153,61) 30deg, + rgb(245,245,61) 60deg, + rgb(61,245,61) 120deg, + rgb(61,245,245) 180deg, + rgb(61,61,245) 240deg, + rgb(245,61,245) 300deg, + rgb(245,61,61) 360deg +)`; + +const ColorWheelFlower = (props: ColorWheelFlowerProps): JSX.Element => { + const context = useColorPickerContext(); + const [selectedIndex, setSelectedIndex] = createSignal(null); + const [hoveredIndex, setHoveredIndex] = createSignal(null); + + + const handleDotClick = (index: number) => { + if (context.disabled()) return; + + if (selectedIndex() === index) { + setSelectedIndex(null); + const whiteColor = createColorFromHsl(0, 0, 100, context.color().hsl.a); + context.onChange(whiteColor); + } else { + setSelectedIndex(index); + const color = COLORS[index]; + + const newColor = createColorFromHsl( + color.hue, + color.saturation, + color.lightness, + context.color().hsl.a + ); + context.onChange(newColor); + } + }; + + + const handleDotHover = (el: HTMLElement, isEntering: boolean) => { + + }; + + const containerClasses = () => + twMerge( + "relative w-[140px] h-[140px] flex items-center justify-center", + clsx({ + "opacity-50 cursor-not-allowed": context.disabled(), + }), + props.class, + props.className + ); + + + const outerRingBackground = () => { + const idx = selectedIndex(); + return idx === null + ? RAINBOW_GRADIENT + : `conic-gradient(${COLORS[idx].rgb}, ${COLORS[idx].rgb})`; + }; + + return ( +
+
+
+
+
+ +
+ + {(item, index) => { + let buttonRef: HTMLButtonElement | undefined; + + return ( + + ); + }} + +
+
+ ); +}; + +export default ColorWheelFlower;