diff --git a/package.json b/package.json index 4124f9b8a..62a320b53 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "r3f-perf": "6.7.0", "react": "^18.2.0", "react-audio-player": "^0.17.0", + "react-color": "^2.19.3", "react-dom": "^18.2.0", "react-dropdown-select": "^4.9.3", "react-hook-form": "^7.39.5", @@ -185,6 +186,7 @@ "@types/lodash": "^4.14.182", "@types/node": "^16.7.13", "@types/react": "^18.2.15", + "@types/react-color": "^3.0.12", "@types/react-dom": "^18.2.7", "@types/react-input-mask": "3.0.2", "@types/react-lottie": "^1.2.10", diff --git a/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/ColorPickerPopoverView/ColorPicker/ColorUtils.ts b/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/ColorPickerPopoverView/ColorPicker/ColorUtils.ts new file mode 100644 index 000000000..6c49e25d1 --- /dev/null +++ b/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/ColorPickerPopoverView/ColorPicker/ColorUtils.ts @@ -0,0 +1,76 @@ +export const hexToHsl = (hex: string) => { + let r = 0 + let g = 0 + let b = 0 + + if (hex.length === 4) { + r = parseInt(hex[1] + hex[1], 16) + g = parseInt(hex[2] + hex[2], 16) + b = parseInt(hex[3] + hex[3], 16) + } else if (hex.length === 7) { + r = parseInt(hex[1] + hex[2], 16) + g = parseInt(hex[3] + hex[4], 16) + b = parseInt(hex[5] + hex[6], 16) + } + + r /= 255 + g /= 255 + b /= 255 + + const max = Math.max(r, g, b) + const min = Math.min(r, g, b) + + let h = 0 + let s = 0 + const l = (max + min) / 2 + + if (max !== min) { + const d = max - min + + s = l > 0.5 ? d / (2 - max - min) : d / (max + min) + + // eslint-disable-next-line default-case + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0) + break + case g: + h = (b - r) / d + 2 + break + case b: + h = (r - g) / d + 4 + break + } + + h /= 6 + } + + return { + h: Math.round(h * 360), + s: Math.round(s * 100), + l: Math.round(l * 100), + } +} + +export const hslToHex = (h: number, s: number, l: number) => { + const saturation = s / 100 + + const lightness = l / 100 + + const k = (n: number) => (n + h / 30) % 12 + const a = saturation * Math.min(lightness, 1 - lightness) + + const f = (n: number) => Math.round(255 * (lightness - a * Math.max(-1, Math.min(k(n) - 3, 9 - k(n), 1)))) + + const r = f(0) + const g = f(8) + const b = f(4) + + // Construct the hex value without bitwise operations + const hex = `#${[r, g, b] + .map((val) => val.toString(16).padStart(2, '0')) + .join('') + .toUpperCase()}` + + return hex +} diff --git a/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/ColorPickerPopoverView/ColorPicker/SaturationPicker.tsx b/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/ColorPickerPopoverView/ColorPicker/SaturationPicker.tsx new file mode 100644 index 000000000..394683ecb --- /dev/null +++ b/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/ColorPickerPopoverView/ColorPicker/SaturationPicker.tsx @@ -0,0 +1,118 @@ +import React, { useRef, useEffect, useState, useCallback } from 'react' +import styled from 'styled-components' +import { hslToHex } from './ColorUtils' + +interface SaturationPickerProps { + hue: number + onChange: (color: string) => void +} + +const Container = styled.div` + position: relative; +` + +const Pointer = styled.div<{ x: number; y: number }>` + position: absolute; + top: ${(props) => props.y - 7}px; + left: ${(props) => props.x - 7}px; + width: 8px; + height: 8px; + border-radius: 50%; + border: 2px solid white; + background-color: transparent; + box-shadow: inset 0 0 0 3px rgba(0, 0, 0, 0.3); + pointer-events: none; + transition: top 0.1s ease, left 0.1s ease; +` + +const SaturationPicker: React.FC = ({ hue, onChange }) => { + const canvasRef = useRef(null) + const [pointerPos, setPointerPos] = useState<{ x: number; y: number }>({ x: 80, y: 50 }) + const [isDragging, setIsDragging] = useState(false) + + useEffect(() => { + const canvas = canvasRef.current + + if (canvas) { + const ctx = canvas.getContext('2d') + + if (ctx) { + const { width, height } = canvas + + // eslint-disable-next-line no-plusplus + for (let x = 0; x < width; x++) { + // eslint-disable-next-line no-plusplus + for (let y = 0; y < height; y++) { + const saturation = x / width + const brightness = 1 - y / height + const color = `hsl(${hue}, ${saturation * 100}%, ${brightness * 100}%)` + + ctx.fillStyle = color + ctx.fillRect(x, y, 1, 1) + } + } + } + } + }, [hue]) + + const handleCanvasInteraction = useCallback( + (e: React.MouseEvent | MouseEvent) => { + const canvas = canvasRef.current + + if (canvas) { + const rect = canvas.getBoundingClientRect() + const x = e.clientX - rect.left + const y = e.clientY - rect.top + + const saturation = x / canvas.width + const brightness = 1 - y / canvas.height + + const hexColor = hslToHex(hue, saturation * 100, brightness * 100) + + setPointerPos({ x, y }) + onChange(hexColor) + } + }, + [hue, onChange], + ) + + const handleMouseDown = (e: React.MouseEvent) => { + setIsDragging(true) + handleCanvasInteraction(e) + } + + // eslint-disable-next-line react-hooks/exhaustive-deps + const handleMouseMove = (e: MouseEvent) => { + if (isDragging) { + handleCanvasInteraction(e) + } + } + + const handleMouseUp = () => { + setIsDragging(false) + } + + useEffect(() => { + if (isDragging) { + window.addEventListener('mousemove', handleMouseMove) + window.addEventListener('mouseup', handleMouseUp) + } else { + window.removeEventListener('mousemove', handleMouseMove) + window.removeEventListener('mouseup', handleMouseUp) + } + + return () => { + window.removeEventListener('mousemove', handleMouseMove) + window.removeEventListener('mouseup', handleMouseUp) + } + }, [isDragging, handleMouseMove]) + + return ( + + + + + ) +} + +export default SaturationPicker diff --git a/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/ColorPickerPopoverView/ColorPicker/index.tsx b/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/ColorPickerPopoverView/ColorPicker/index.tsx index a7dcafb90..9b2d24db8 100644 --- a/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/ColorPickerPopoverView/ColorPicker/index.tsx +++ b/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/ColorPickerPopoverView/ColorPicker/index.tsx @@ -1,16 +1,94 @@ /* eslint-disable no-nested-ternary */ import styled from 'styled-components' import { Flex } from '~/components/common/Flex' - +import { HuePicker } from 'react-color' import { colors } from '~/utils/colors' +import { useState } from 'react' +import SaturationPicker from './SaturationPicker' +import { hslToHex, hexToHsl } from './ColorUtils' +import { useAppStore } from '~/stores/useAppStore' +import { circleColors } from '../../Constants' + +export const ColorPicker = () => { + const { selectedColor, setSelectedColor } = useAppStore((s) => s) + const [hexValue, setHexValue] = useState(selectedColor) + const [hueValue, setHueValue] = useState(315) + const [saturation, setSaturation] = useState(74) + const [brightness, setBrightness] = useState(59) + + const handleColorChange = (hexColor: string) => { + setSelectedColor(hexColor) + setHexValue(hexColor) + + const { h, s, l } = hexToHsl(hexColor) + + setHueValue(h) + setSaturation(s) + setBrightness(l) + } + + const handleHueChange = (color: { hsl: { h: number }; hex: string }) => { + setHueValue(color.hsl.h) + + const newHex = hslToHex(color.hsl.h, saturation, brightness) + + handleColorChange(newHex) + } + + const handleSaturationChange = (hexColor: string) => { + setSelectedColor(hexColor) + setHexValue(hexColor) + + const { h, s, l } = hexToHsl(hexColor) + + setHueValue(h) + setSaturation(s) + setBrightness(l) + } + + const handleHexInputChange = (e: React.ChangeEvent) => { + const newHex = e.target.value + + setHexValue(newHex) + + const { h, s, l } = hexToHsl(newHex) + + setHueValue(h) + setSaturation(s) + setBrightness(l) + setSelectedColor(newHex) + } + + return ( + + + + + + {circleColors.map((circleColor) => ( + handleColorChange(circleColor)} /> + ))} + + + + + + + + + + + + + HEX -export const ColorPicker = () => ( - - -

this is color wrapper

-
-
-) + +
+
+
+
+ ) +} const Wrapper = styled(Flex)` flex: 1; @@ -50,3 +128,81 @@ const TableWrapper = styled(Flex)` flex: 1; width: 100%; ` + +const PickerContainer = styled.div` + padding: 0 20px; + width: 315px; +` + +const ColorPalette = styled.div` + display: flex; + flex-wrap: wrap; + justify-content: flex-start; + margin-bottom: 16px; +` + +const ColorPaletteWrapper = styled.div` + margin-left: 10px; + margin-bottom: 6px; +` + +const ColorCircle = styled.div<{ color: string }>` + width: 20px; + height: 20px; + border-radius: 50%; + margin: 4px; + background-color: ${(props) => props.color}; + cursor: pointer; + + &:hover { + box-shadow: 0 0 7px ${(props) => props.color}; + } +` + +const SaturationPickerWrapper = styled.div` + margin-bottom: 8px; + margin-left: 4px; + display: flex; + justify-content: center; + align-items: center; +` + +const HuePickerWrapper = styled.div` + margin-bottom: 15px; + width: 224px; + margin-left: 10px; + display: flex; + justify-content: center; + align-items: center; +` + +const StyledInput = styled.input` + font-family: 'Barlow'; + padding: 2px 5px 2px 10px; + font-size: 13px; + background-color: ${colors.black}; + color: ${colors.primaryText1}; + border-radius: 6px; + width: 84px; + height: 28px; + border: none; + + &:focus { + outline: none; + } +` + +const LabelText = styled.p` + font-family: 'Barlow'; + font-size: 13px; + font-weight: 400; + color: ${colors.primaryText1}; + letter-spacing: 1px; + margin: 0 10px; +` + +const HexaInputWrapper = styled.div` + display: flex; + align-items: center; + gap: 8px; +` diff --git a/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/ColorPickerPopoverView/IconPicker/index.tsx b/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/ColorPickerPopoverView/IconPicker/index.tsx new file mode 100644 index 000000000..2a198f0bb --- /dev/null +++ b/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/ColorPickerPopoverView/IconPicker/index.tsx @@ -0,0 +1,131 @@ +import React from 'react' +import styled, { css } from 'styled-components' +import { Icons } from '~/components/Icons' +import { Flex } from '~/components/common/Flex' +import { colors } from '~/utils' +import { useAppStore } from '~/stores/useAppStore' + +export const IconPicker: React.FC = () => { + const { selectedIcon, setSelectedIcon } = useAppStore((s) => s) + + const handleIconChange = (icon: string) => { + setSelectedIcon(icon) + } + + return ( + + + + + + {Object.keys(Icons).map((iconKey) => { + const IconComponent = Icons[iconKey as keyof typeof Icons] + + return ( + handleIconChange(iconKey)} + > + {IconComponent && } + + ) + })} + + + + + + ) +} + +const Wrapper = styled(Flex)` + flex: 1; + + .title { + font-size: 20px; + color: ${colors.white}; + font-family: Barlow; + font-size: 22px; + font-style: normal; + font-weight: 600; + line-height: normal; + } + + .subtitle { + color: ${colors.GRAY3}; + font-family: Barlow; + font-size: 13px; + font-style: normal; + font-weight: 400; + line-height: normal; + } + + & .filters { + overflow-x: auto; + } + + .load-more { + margin: 8px auto; + align-self: center; + } +` + +const TableWrapper = styled(Flex)` + min-height: 0; + overflow: auto; + flex: 1; + width: 100%; +` + +const PickerContainer = styled.div` + padding: 0 20px; + width: 300px; + height: 350px; + overflow: auto; +` + +const IconPaletteWrapper = styled.div` + margin-left: 18px; + margin-bottom: 6px; +` + +const IconGrid = styled.div` + display: flex; + flex-wrap: wrap; + justify-content: flex-start; + margin-bottom: 16px; +` + +const IconBox = styled.div<{ isSelected: boolean }>` + width: 50px; + height: 50px; + margin: 4px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + padding: 10px; + border: none; + border-radius: 8px; + + ${({ isSelected }) => + isSelected + ? css` + background: ${colors.black}; + border: 1px solid ${colors.primaryBlue}; + ` + : css` + &:hover { + background: ${colors.black}; + border: 1px solid ${colors.primaryBlue}; + } + `} + + svg { + width: 30px; + height: 30px; + object-fit: contain; + color: white; + } +` diff --git a/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/ColorPickerPopoverView/index.tsx b/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/ColorPickerPopoverView/index.tsx index f2abc7eca..542d4a186 100644 --- a/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/ColorPickerPopoverView/index.tsx +++ b/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/ColorPickerPopoverView/index.tsx @@ -5,6 +5,7 @@ import styled from 'styled-components' import { Flex } from '~/components/common/Flex' import { colors } from '~/utils/colors' import { ColorPicker } from './ColorPicker' +import { IconPicker } from './IconPicker' interface TabPanelProps { children?: React.ReactNode @@ -42,7 +43,10 @@ export const ColorPickerPopoverView = () => { setValue(newValue) } - const tabs = [{ label: 'Color', component: ColorPicker }] + const tabs = [ + { label: 'Color', component: ColorPicker }, + { label: 'Icon', component: IconPicker }, + ] return ( diff --git a/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/Constants/index.ts b/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/Constants/index.ts new file mode 100644 index 000000000..61b834809 --- /dev/null +++ b/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/Constants/index.ts @@ -0,0 +1,34 @@ +export const circleColors = [ + '#C62828', + '#D32F2F', + '#F57C00', + '#FF9800', + '#FFB74D', + '#FFEB3B', + '#CDDC39', + '#8BC34A', + '#388E3C', + '#4CAF50', + '#009688', + '#00796B', + '#00BCD4', + '#0097A7', + '#3F51B5', + '#283593', + '#5C6BC0', + '#7E57C2', + '#512DA8', + '#9C27B0', + '#E91E63', + '#F06292', + '#F48FB1', + '#795548', + '#6D4C41', + '#9E9E9E', + '#757575', + '#607D8B', + '#455A64', + '#2196F3', + '#1976D2', + '#64B5F6', +] diff --git a/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/index.tsx b/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/index.tsx index 29adc7c6c..0dd8da3d5 100644 --- a/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/index.tsx +++ b/src/components/ModalsContainer/BlueprintModal/Body/Editor/ColorPickerPopover/index.tsx @@ -24,12 +24,12 @@ const ModalBackground = styled.div<{ isOpen: boolean }>` const ModalContent = styled.div` position: fixed; - top: 38%; + top: 40%; left: 34%; transform: translate(-50%, -50%); background: ${colors.BG1}; width: 300px; - height: 443px; + height: 460px; z-index: 1001; border-radius: 8px; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); diff --git a/src/components/ModalsContainer/BlueprintModal/Body/Editor/index.tsx b/src/components/ModalsContainer/BlueprintModal/Body/Editor/index.tsx index 2b07fdf64..b77a7499f 100644 --- a/src/components/ModalsContainer/BlueprintModal/Body/Editor/index.tsx +++ b/src/components/ModalsContainer/BlueprintModal/Body/Editor/index.tsx @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { Button, Grid } from '@mui/material' -import { useEffect, useMemo, useState } from 'react' +import React, { useEffect, useMemo, useState } from 'react' import { FieldValues, FormProvider, useForm } from 'react-hook-form' import { ClipLoader } from 'react-spinners' import styled from 'styled-components' @@ -18,9 +18,10 @@ import { useModal } from '~/stores/useModalStore' import { colors } from '~/utils' import { CreateCustomNodeAttribute } from './CustomAttributesStep' import MediaOptions from './MediaOptions' +import { Icons } from '~/components/Icons' import { convertAttributes, parsedObjProps, parseJson } from './utils' -import ColorPickerIcon from '~/components/Icons/ColorPickerIcon' import { ColorPickerPopover } from './ColorPickerPopover' +import { useAppStore } from '~/stores/useAppStore' const defaultValues = { type: '', @@ -70,6 +71,8 @@ const handleSubmitForm = async ( data: FieldValues, isUpdate = false, deletedAttributes: string[], + selectedColor: string, + selectedIcon: string, mediaOptions: { videoAudio: boolean; image: boolean; sourceLink: boolean }, initialMediaOptions: { videoAudio: boolean; image: boolean; sourceLink: boolean }, ): Promise => { @@ -86,6 +89,8 @@ const handleSubmitForm = async ( attributes: { [key: string]: string } index?: string media_url?: string + color?: string + icon?: string image_url?: string source_link?: string } = { @@ -94,6 +99,14 @@ const handleSubmitForm = async ( index: selectedIndex, } + if (selectedColor) { + requestData.color = selectedColor + } + + if (selectedIcon) { + requestData.icon = selectedIcon + } + if (mediaOptions.videoAudio) { requestData.media_url = '' } else if (initialMediaOptions.videoAudio) { @@ -211,6 +224,7 @@ export const Editor = ({ sourceLink: false, }) + const { selectedColor, selectedIcon } = useAppStore((s) => s) const [isPopoverOpen, setPopoverOpen] = useState(!!selectedSchema) const handleColorPickerPopover = () => setPopoverOpen(!isPopoverOpen) @@ -354,6 +368,8 @@ export const Editor = ({ await editNodeSchemaUpdate(selectedSchema?.ref_id as string, { type: data.type, parent: newParent as string, + color: selectedColor, + icon: selectedIcon, attributes: { index: selectedIndex as string, }, @@ -366,6 +382,8 @@ export const Editor = ({ { ...data, ...(selectedSchema ? { ref_id: selectedSchema?.ref_id } : {}) }, !!selectedSchema, deletedAttributes, + selectedColor, + selectedIcon, mediaOptions, { videoAudio: !!selectedSchema?.media_url, @@ -462,6 +480,8 @@ export const Editor = ({ return undefined }, [selectedSchema, attributes]) + const IconComponent = Icons[selectedIcon as keyof typeof Icons] + return ( @@ -512,8 +532,8 @@ export const Editor = ({ value={parent} /> - - + + {IconComponent && } @@ -541,8 +561,8 @@ export const Editor = ({ value={parent} /> - - + + @@ -710,16 +730,22 @@ const HeaderText = styled(Text)` color: ${colors.white}; ` -const ColorPickerIconWrapper = styled.span` +const ColorPickerIconWrapper = styled.span<{ selectedColor?: string }>` width: 36px; height: 36px; border-radius: 6px; margin-left: 12px; - color: ${colors.colorPickerThing}; - background: ${colors.THING}; + background: ${(props) => props.selectedColor ?? colors.THING}; display: flex; justify-content: center; align-items: center; + + svg { + width: 22px; + height: 22px; + object-fit: contain; + color: white; + } ` const InputIconWrapper = styled(Flex)` diff --git a/src/network/fetchSourcesData/index.ts b/src/network/fetchSourcesData/index.ts index 78ad26076..7b0793de6 100644 --- a/src/network/fetchSourcesData/index.ts +++ b/src/network/fetchSourcesData/index.ts @@ -181,6 +181,8 @@ interface UpdateEdgeData { export interface UpdateSchemaParams { type: string parent: string + color?: string + icon?: string attributes: { index: string } diff --git a/src/stores/useAppStore/index.ts b/src/stores/useAppStore/index.ts index 132a7395a..7a68b8e15 100644 --- a/src/stores/useAppStore/index.ts +++ b/src/stores/useAppStore/index.ts @@ -29,6 +29,10 @@ export type AppStore = { setUniverseQuestionIsOpen: () => void setCurrentPlayingAudio: (_: React.MutableRefObject | null) => void setShowCollapseButton: (_: boolean) => void + selectedColor: string + setSelectedColor: (color: string) => void + selectedIcon: string + setSelectedIcon: (icon: string) => void } const defaultData = { @@ -45,6 +49,8 @@ const defaultData = { appMetaData: null, currentPlayingAudio: null, showCollapseButton: true, + selectedColor: '#962777', + selectedIcon: 'ConstructionIcon', } export const useAppStore = create((set, get) => ({ @@ -68,4 +74,6 @@ export const useAppStore = create((set, get) => ({ setUniverseQuestionIsOpen: () => set({ universeQuestionIsOpen: !get().universeQuestionIsOpen }), setAppMetaData: (appMetaData) => set({ appMetaData }), setShowCollapseButton: (showCollapseButton) => set({ showCollapseButton }), + setSelectedColor: (selectedColor) => set({ selectedColor }), + setSelectedIcon: (selectedIcon) => set({ selectedIcon }), })) diff --git a/yarn.lock b/yarn.lock index e8cdc4d5e..8ac08e9e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2376,6 +2376,15 @@ __metadata: languageName: node linkType: hard +"@icons/material@npm:^0.2.4": + version: 0.2.4 + resolution: "@icons/material@npm:0.2.4" + peerDependencies: + react: "*" + checksum: 24baa360cb83f7e1a9e6784ac11185d57eb895b0efd3070ec915693378330f35ff9feb248f650b9649fa3e1045601286585dc05795a4c734d4849b33900351ee + languageName: node + linkType: hard + "@isaacs/cliui@npm:^8.0.2": version: 8.0.2 resolution: "@isaacs/cliui@npm:8.0.2" @@ -4591,6 +4600,16 @@ __metadata: languageName: node linkType: hard +"@types/react-color@npm:^3.0.12": + version: 3.0.12 + resolution: "@types/react-color@npm:3.0.12" + dependencies: + "@types/react": "*" + "@types/reactcss": "*" + checksum: 2b3baffa6d293ee98a66ccb8c47d47700a7139c42589f8acc7713c7b5ae1dd61e7b4ceeebdb4f2d1b3c54466a1d3f351c3126929ebb9c6e1fe460b7400a857c2 + languageName: node + linkType: hard + "@types/react-dom@npm:^18.0.0, @types/react-dom@npm:^18.2.7": version: 18.2.18 resolution: "@types/react-dom@npm:18.2.18" @@ -4665,6 +4684,15 @@ __metadata: languageName: node linkType: hard +"@types/reactcss@npm:*": + version: 1.2.12 + resolution: "@types/reactcss@npm:1.2.12" + dependencies: + "@types/react": "*" + checksum: d04c087376daa503e187b390e416530904152046a7ac79a1c94e43cb4855fc8078ba8947792b88f3aff953defd9cae331c44fba717ebd650f40556e8f4bbb2a2 + languageName: node + linkType: hard + "@types/scheduler@npm:*": version: 0.16.8 resolution: "@types/scheduler@npm:0.16.8" @@ -11155,7 +11183,7 @@ __metadata: languageName: node linkType: hard -"lodash-es@npm:4": +"lodash-es@npm:4, lodash-es@npm:^4.17.15": version: 4.17.21 resolution: "lodash-es@npm:4.17.21" checksum: 05cbffad6e2adbb331a4e16fbd826e7faee403a1a04873b82b42c0f22090f280839f85b95393f487c1303c8a3d2a010048bf06151a6cbe03eee4d388fb0a12d2 @@ -11274,7 +11302,7 @@ __metadata: languageName: node linkType: hard -"lodash@npm:^4.17.11, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21": +"lodash@npm:^4.0.1, lodash@npm:^4.17.11, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21": version: 4.17.21 resolution: "lodash@npm:4.17.21" checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 @@ -11521,6 +11549,13 @@ __metadata: languageName: node linkType: hard +"material-colors@npm:^1.2.1": + version: 1.2.6 + resolution: "material-colors@npm:1.2.6" + checksum: 72d005ccccb82bab68eef3cd757e802668634fc86976dedb9fc564ce994f2d3258273766b7efecb7404a0031969e2d72201a1b74169763f0a53c0dd8d649209f + languageName: node + linkType: hard + "md5.js@npm:^1.3.4": version: 1.3.5 resolution: "md5.js@npm:1.3.5" @@ -13095,7 +13130,7 @@ __metadata: languageName: node linkType: hard -"prop-types@npm:^15.6.0, prop-types@npm:^15.6.2, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1": +"prop-types@npm:^15.5.10, prop-types@npm:^15.6.0, prop-types@npm:^15.6.2, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1": version: 15.8.1 resolution: "prop-types@npm:15.8.1" dependencies: @@ -13290,6 +13325,23 @@ __metadata: languageName: node linkType: hard +"react-color@npm:^2.19.3": + version: 2.19.3 + resolution: "react-color@npm:2.19.3" + dependencies: + "@icons/material": ^0.2.4 + lodash: ^4.17.15 + lodash-es: ^4.17.15 + material-colors: ^1.2.1 + prop-types: ^15.5.10 + reactcss: ^1.2.0 + tinycolor2: ^1.4.1 + peerDependencies: + react: "*" + checksum: 40b49e1aa2ab27a099cc37a3fa2d5bb906b8def4dbe2d922c0e42365e386d82b03f9b06a2b29a44a51f1e114cef72e61c0ba0740581a128d951936ea4617429b + languageName: node + linkType: hard + "react-colorful@npm:^5.5.1": version: 5.6.1 resolution: "react-colorful@npm:5.6.1" @@ -13617,6 +13669,15 @@ __metadata: languageName: node linkType: hard +"reactcss@npm:^1.2.0": + version: 1.2.3 + resolution: "reactcss@npm:1.2.3" + dependencies: + lodash: ^4.0.1 + checksum: c53e386a0881f1477e1cff661f6a6ad4c662230941f3827862193ac30f9b75cdf7bc7b4c7e5ca543d3e4e80fee1a3e9fa0056c206b1c0423726c41773ab3fe45 + languageName: node + linkType: hard + "reactflow@npm:^11.9.2": version: 11.10.1 resolution: "reactflow@npm:11.10.1" @@ -14650,6 +14711,7 @@ __metadata: "@types/lodash": ^4.14.182 "@types/node": ^16.7.13 "@types/react": ^18.2.15 + "@types/react-color": ^3.0.12 "@types/react-dom": ^18.2.7 "@types/react-input-mask": 3.0.2 "@types/react-lottie": ^1.2.10 @@ -14702,6 +14764,7 @@ __metadata: r3f-perf: 6.7.0 react: ^18.2.0 react-audio-player: ^0.17.0 + react-color: ^2.19.3 react-dom: ^18.2.0 react-dropdown-select: ^4.9.3 react-hook-form: ^7.39.5 @@ -15308,7 +15371,7 @@ __metadata: languageName: node linkType: hard -"tinycolor2@npm:1": +"tinycolor2@npm:1, tinycolor2@npm:^1.4.1": version: 1.6.0 resolution: "tinycolor2@npm:1.6.0" checksum: 6df4d07fceeedc0a878d7bac47e2cd47c1ceeb1078340a9eb8a295bc0651e17c750f73d47b3028d829f30b85c15e0572c0fd4142083e4c21a30a597e47f47230