import type { Meta, StoryObj } from '@storybook/react-vite'; import { useState } from 'react'; import { type ComponentMatrixCellProps, Story } from './_internal/Story'; import { Button } from './Button'; import { ColorPicker } from './ColorPicker'; const meta = { component: ColorPicker, parameters: { layout: 'fullscreen', }, title: 'components/ColorPicker', } satisfies Meta; export default meta; type StoryDefinition = StoryObj; const FORMAT_COLUMNS = [ { key: 'hex', label: 'HEX' }, { key: 'rgb', label: 'RGB' }, { key: 'hsl', label: 'HSL' }, { key: 'hsb', label: 'HSB' }, ]; const MODE_ROWS = [ { key: 'popover', label: 'Popover' }, { key: 'inline', label: 'Inline' }, { key: 'disabled', label: 'Disabled' }, ]; type ColorFormat = 'hex' | 'hsb' | 'hsl' | 'rgb'; function ColorPickerMatrixCell({ column, row }: ComponentMatrixCellProps) { return ; } function formatColor(hex: string, format: ColorFormat) { const [r, g, b] = hex .replace('#', '') .match(/.{2}/g) ?.map((channel) => Number.parseInt(channel, 16)) ?? []; if (r === undefined || g === undefined || b === undefined) { return hex; } if (format === 'rgb') { return `rgb(${r}, ${g}, ${b})`; } const max = Math.max(r, g, b) / 255; const min = Math.min(r, g, b) / 255; const diff = max - min; const lightness = (max + min) / 2; const saturation = diff === 0 ? 0 : diff / (format === 'hsl' ? 1 - Math.abs(2 * lightness - 1) : max); const hue = diff === 0 ? 0 : max === r / 255 ? ((g / 255 - b / 255) / diff) % 6 : max === g / 255 ? (b / 255 - r / 255) / diff + 2 : (r / 255 - g / 255) / diff + 4; const degrees = Math.round((hue < 0 ? hue + 6 : hue) * 60); if (format === 'hsl') { return `hsl(${degrees}, ${Math.round(saturation * 100)}%, ${Math.round(lightness * 100)}%)`; } if (format === 'hsb') { return `hsb(${degrees}, ${Math.round(saturation * 100)}%, ${Math.round(max * 100)}%)`; } return hex; } function PickerControls() { return ( <>
); } function PickerPreview({ format, mode }: { format: string; mode: string }) { const initialColor = mode === 'disabled' ? '#94a3b8' : '#3b82f6'; const colorFormat = format as ColorFormat; const [color, setColor] = useState(() => formatColor(initialColor, colorFormat), ); if (mode === 'inline') { return (
); } return ( ); } export const All: StoryDefinition = { render: () => ( ), };