diff --git a/web/package-lock.json b/web/package-lock.json index f655c5d54..afde0355e 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -73,6 +73,7 @@ "prettier-plugin-tailwindcss": "^0.6.11", "react": "^18", "react-color": "^2.19.3", + "react-colorful": "^5.6.1", "react-data-grid": "7.0.0-beta.47", "react-day-picker": "8.10.1", "react-dom": "^18", @@ -18523,6 +18524,16 @@ "react": "*" } }, + "node_modules/react-colorful": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", + "integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "node_modules/react-confetti": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/react-confetti/-/react-confetti-6.4.0.tgz", diff --git a/web/package.json b/web/package.json index 20306b772..27ce9d05d 100644 --- a/web/package.json +++ b/web/package.json @@ -82,6 +82,7 @@ "prettier-plugin-tailwindcss": "^0.6.11", "react": "^18", "react-color": "^2.19.3", + "react-colorful": "^5.6.1", "react-data-grid": "7.0.0-beta.47", "react-day-picker": "8.10.1", "react-dom": "^18", diff --git a/web/src/components/ui/color-picker/ColorPicker.stories.tsx b/web/src/components/ui/color-picker/ColorPicker.stories.tsx index 13a760fd1..7e22c8fed 100644 --- a/web/src/components/ui/color-picker/ColorPicker.stories.tsx +++ b/web/src/components/ui/color-picker/ColorPicker.stories.tsx @@ -7,8 +7,7 @@ const meta: Meta = { tags: ['autodocs'], args: { value: '#000000', - size: 'default', - variant: 'default' + size: 'default' }, argTypes: { value: { @@ -26,11 +25,7 @@ const meta: Meta = { options: ['small', 'default', 'tall'], description: 'The size of the color picker button' }, - variant: { - control: 'select', - options: ['default', 'outline', 'secondary', 'ghost', 'link'], - description: 'The variant style of the color picker button' - }, + className: { control: 'text', description: 'Additional CSS classes to apply' @@ -60,31 +55,3 @@ export const Tall: Story = { size: 'tall' } }; - -export const OutlineVariant: Story = { - args: { - value: '#800080', - variant: 'outline' - } -}; - -export const SecondaryVariant: Story = { - args: { - value: '#FFA500', - variant: 'secondary' - } -}; - -export const GhostVariant: Story = { - args: { - value: '#008080', - variant: 'ghost' - } -}; - -export const LinkVariant: Story = { - args: { - value: '#4B0082', - variant: 'link' - } -}; diff --git a/web/src/components/ui/color-picker/ColorPicker.tsx b/web/src/components/ui/color-picker/ColorPicker.tsx index f83a6ca38..3410c057b 100644 --- a/web/src/components/ui/color-picker/ColorPicker.tsx +++ b/web/src/components/ui/color-picker/ColorPicker.tsx @@ -1,100 +1,104 @@ -import React from 'react'; -import { PopoverRoot, PopoverContent, PopoverTrigger } from '@/components/ui/popover/PopoverBase'; -import { cva } from 'class-variance-authority'; +'use client'; + +import { forwardRef, useCallback, useMemo, useState } from 'react'; +import { HexColorPicker } from 'react-colorful'; import { cn } from '@/lib/utils'; -import { Button } from '@/components/ui/buttons'; -import { ChromePicker, ColorResult } from 'react-color'; -import { useMemoizedFn } from '@/hooks'; +import { Button, ButtonProps } from '@/components/ui/buttons'; +import { Popover, PopoverRoot, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; +import { Input } from '@/components/ui/inputs'; +import { useDebounceFn } from '@/hooks'; +import { cva } from 'class-variance-authority'; -const colorPickerVariants = cva( - 'rounded border bg-background transition-colors hover:bg-item-hover hover:text-text-default', - { - variants: { - variant: { - default: 'border-input', - outline: 'border-input', - secondary: 'border-secondary bg-secondary text-secondary-foreground hover:bg-secondary/80', - ghost: 'hover:bg-accent hover:text-accent-foreground', - link: 'text-primary underline-offset-4 hover:underline' - }, - size: { - default: 'h-6 min-h-6 max-h-6 px-1', - tall: 'h-7 min-h-7 max-h-7 px-0.5', - small: 'h-5 min-h-5 max-h-5 px-0.5 text-xs' - } - }, - defaultVariants: { - variant: 'default', - size: 'default' - } - } -); - -export interface ColorPickerProps { - value?: string | null; - onChange?: (color: string) => void; - onChangeComplete?: (color: string) => void; - size?: 'small' | 'default' | 'tall'; - variant?: 'default' | 'outline' | 'secondary' | 'ghost' | 'link'; +interface ColorPickerProps { + value: string | null | undefined; + onChange?: (value: string) => void; + onChangeComplete?: (value: string) => void; + onBlur?: () => void; + disabled?: boolean; + size?: 'default' | 'small' | 'tall'; + name?: string; className?: string; } -const ColorPicker = React.forwardRef( +const colorPickerWrapperVariants = cva('border p-1 rounded cursor-pointer shadow', { + variants: { + size: { + default: 'w-6 min-w-6 max-w-6 h-6 min-h-6 max-h-6', + small: 'w-5 min-w-5 max-w-5 h-5 min-h-5 max-h-5', + tall: 'w-7 min-w-7 max-w-7 h-7 min-h-7 max-h-7' + }, + disabled: { + true: 'cursor-not-allowed opacity-60', + false: 'cursor-pointer' + } + } +}); + +const ColorPicker = forwardRef( ( { - className, - value = '#000000', - onChange, + disabled, onChangeComplete, size = 'default', - variant = 'default' + value: valueProp = '#000000', + onChange, + name, + className = '', + ...props }, - ref + forwardedRef ) => { - const handleChange = useMemoizedFn( - (color: ColorResult, event: React.ChangeEvent) => { - onChange?.(color.hex); - } + const [open, setOpen] = useState(false); + const [value, setValue] = useState(valueProp); + + const parsedValue = useMemo(() => { + return value || '#000000'; + }, [value]); + + const { run: debouncedOnChangeComplete } = useDebounceFn( + (value: string) => { + onChangeComplete?.(value); + }, + { wait: 150 } ); - const handleChangeComplete = useMemoizedFn( - (color: ColorResult, event: React.ChangeEvent) => { - onChangeComplete?.(color.hex); - } + const handleInputChange = useCallback( + (e: React.ChangeEvent) => { + setValue(e?.currentTarget?.value); + onChange?.(e?.currentTarget?.value); + debouncedOnChangeComplete?.(e?.currentTarget?.value); + }, + [onChange, debouncedOnChangeComplete] ); + const handleHexColorPickerChange = useCallback( + (color: string) => { + setValue(color); + onChange?.(color); + debouncedOnChangeComplete?.(color); + }, + [onChange, debouncedOnChangeComplete] + ); return ( - - - + + +
+
+
- - + + ); } ); - ColorPicker.displayName = 'ColorPicker'; export { ColorPicker }; diff --git a/web/src/controllers/MetricController/MetricViewChart/MetricEditController/MetricStylingApp/StylingAppStyling/EditShowGoalLine.tsx b/web/src/controllers/MetricController/MetricViewChart/MetricEditController/MetricStylingApp/StylingAppStyling/EditShowGoalLine.tsx index 635a402d8..e88ec72e0 100644 --- a/web/src/controllers/MetricController/MetricViewChart/MetricEditController/MetricStylingApp/StylingAppStyling/EditShowGoalLine.tsx +++ b/web/src/controllers/MetricController/MetricViewChart/MetricEditController/MetricStylingApp/StylingAppStyling/EditShowGoalLine.tsx @@ -185,7 +185,6 @@ const GoalLineItemContent: React.FC<{
{ const hexColor = color; diff --git a/web/src/controllers/ReasoningController/ReasoningMessages/ReasoningMessage_Text/ReasoningMessage_Text.tsx b/web/src/controllers/ReasoningController/ReasoningMessages/ReasoningMessage_Text/ReasoningMessage_Text.tsx index f20aca510..5fe9fade5 100644 --- a/web/src/controllers/ReasoningController/ReasoningMessages/ReasoningMessage_Text/ReasoningMessage_Text.tsx +++ b/web/src/controllers/ReasoningController/ReasoningMessages/ReasoningMessage_Text/ReasoningMessage_Text.tsx @@ -11,8 +11,6 @@ export const ReasoningMessage_Text: React.FC = React.memo (x) => (x?.reasoning_messages[reasoningMessageId] as BusterChatMessageReasoning_text)?.message )!; - console.log('message', message); - if (!message) return null; return (