-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* updated types and updateSketchParams to handle vectors * addNode as shared func * imports fix * vector value passed to sketch * organise * ParamVector3 component * tweak * loosen lint rules * comments * rgb param type * type shuffling, better checking * types cleanup * project json update * color picker with story * better handling of body click * floating color picker position * ParamColor implemented * update content security policy to allow for data: URLs * picker styling * behaviour fix for color picker * example project update * color picker hue slider fix
- Loading branch information
1 parent
2df3b1e
commit b0ff160
Showing
16 changed files
with
713 additions
and
276 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
packages/desktop/src/renderer/components/ParamColor/ParamColor.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { NodeParamRGB } from '@hedron/engine' | ||
import { useInterval } from 'usehooks-ts' | ||
import { useRef } from 'react' | ||
import { ColorPicker, ColorPickerHandle } from '@components/core/ColorPicker/ColorPicker' | ||
import { useOnNodeVec3ValueChange } from '@components/hooks/useOnNodeVec3ValueChange' | ||
import { engineStore, useEngineStore } from '@renderer/engine' | ||
|
||
interface ParamRGBProps { | ||
id: string | ||
} | ||
|
||
export const ParamColor = ({ id }: ParamRGBProps) => { | ||
const ref = useRef<ColorPickerHandle>(null) | ||
const node = useEngineStore((state) => state.nodes[id] as NodeParamRGB) | ||
const { childNodeIds } = node | ||
|
||
useInterval(() => { | ||
const state = engineStore.getState() | ||
const nodeValues = node.childNodeIds.map((id) => state.nodeValues[id]) | ||
|
||
ref.current?.updateColor(nodeValues as [number, number, number]) | ||
}, 100) | ||
|
||
const onVec3ValueChange = useOnNodeVec3ValueChange( | ||
childNodeIds[0], | ||
childNodeIds[1], | ||
childNodeIds[2], | ||
) | ||
|
||
return <ColorPicker ref={ref} onValueChange={onVec3ValueChange} /> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
packages/desktop/src/renderer/components/core/ColorPicker/ColorPicker.module.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
.container { | ||
position: relative; | ||
width: 100%; | ||
height: 100%; | ||
} | ||
|
||
.colorBox { | ||
width: 100%; | ||
height: 100%; | ||
cursor: pointer; | ||
border-radius: 0.5rem; | ||
border: 1px solid var(--lineColor1); | ||
} | ||
|
||
.pickerContainer { | ||
z-index: 10; | ||
position: relative; | ||
} | ||
|
||
.picker { | ||
border-radius: 8px; | ||
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.3); | ||
} | ||
|
||
.picker::before { | ||
content: ''; | ||
position: absolute; | ||
top: -1px; | ||
left: -1px; | ||
right: -1px; | ||
bottom: -1px; | ||
border: 2px solid var(--lineColor1); | ||
border-radius: 8px; | ||
pointer-events: none; | ||
z-index: 1; | ||
} |
107 changes: 107 additions & 0 deletions
107
packages/desktop/src/renderer/components/core/ColorPicker/ColorPicker.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import { | ||
forwardRef, | ||
useCallback, | ||
useEffect, | ||
useImperativeHandle, | ||
useMemo, | ||
useRef, | ||
useState, | ||
} from 'react' | ||
import { | ||
Colorful, | ||
ColorResult, | ||
hexToHsva, | ||
HsvaColor, | ||
hsvaToHex, | ||
rgbaToHex, | ||
rgbaToHsva, | ||
} from '@uiw/react-color' | ||
import { useFloating, shift, offset } from '@floating-ui/react-dom' | ||
import css from './ColorPicker.module.css' | ||
|
||
type RGBColor = [number, number, number] | ||
|
||
export type ColorPickerHandle = { | ||
updateColor: (value: RGBColor) => void | ||
} | ||
|
||
interface ColorPickerProps { | ||
onValueChange: (value: RGBColor) => void | ||
} | ||
|
||
const defaultColor: HsvaColor = hexToHsva('#FFFFFF') | ||
|
||
export const ColorPicker = forwardRef<ColorPickerHandle, ColorPickerProps>(function ColorPicker( | ||
{ onValueChange }, | ||
ref, | ||
) { | ||
const colorBoxRef = useRef<HTMLDivElement>(null) | ||
const [color, setColor] = useState<HsvaColor>(defaultColor) | ||
const colorRef = useRef<HsvaColor>(defaultColor) | ||
const [isOpen, setIsOpen] = useState(false) | ||
const { refs, floatingStyles } = useFloating({ | ||
middleware: [shift({ padding: 10 }), offset({ mainAxis: 10 })], | ||
}) | ||
|
||
const onBoxClick = useCallback(() => { | ||
setColor(colorRef.current) | ||
setIsOpen((isOpen) => !isOpen) | ||
}, []) | ||
|
||
const onPickerClick = useCallback((e: React.MouseEvent) => { | ||
e.stopPropagation() | ||
}, []) | ||
|
||
const onChange = useCallback( | ||
({ rgb: { r, g, b }, hsva }: ColorResult) => { | ||
setColor(hsva) | ||
onValueChange([r / 255, g / 255, b / 255]) | ||
}, | ||
[onValueChange], | ||
) | ||
|
||
useEffect(() => { | ||
const handleClick = (e: MouseEvent) => { | ||
// do not close the picker if the color box is clicked | ||
if (colorBoxRef.current?.contains(e.target as Node)) return | ||
setIsOpen(false) | ||
} | ||
document.body.addEventListener('click', handleClick) | ||
return () => { | ||
document.body.removeEventListener('click', handleClick) | ||
} | ||
}, []) | ||
|
||
// Avoiding using state to keep external frequent updates performant | ||
const updateColor = useCallback(([r, g, b]: RGBColor) => { | ||
const rgba = { r: r * 255, g: g * 255, b: b * 255, a: 1 } | ||
const hsva = rgbaToHsva(rgba) | ||
colorBoxRef.current?.style.setProperty('background-color', rgbaToHex(rgba)) | ||
colorRef.current = hsva | ||
}, []) | ||
|
||
useImperativeHandle(ref, () => ({ updateColor }), [updateColor]) | ||
|
||
const backgroundColor = useMemo(() => hsvaToHex(color), [color]) | ||
|
||
return ( | ||
<div className={css.container} ref={refs.setReference}> | ||
<div | ||
className={css.colorBox} | ||
style={{ backgroundColor }} | ||
onClick={onBoxClick} | ||
ref={colorBoxRef} | ||
/> | ||
{isOpen && ( | ||
<div | ||
className={css.pickerContainer} | ||
ref={refs.setFloating} | ||
style={{ ...floatingStyles }} | ||
onClick={onPickerClick} | ||
> | ||
<Colorful className={css.picker} color={color} onChange={onChange} disableAlpha /> | ||
</div> | ||
)} | ||
</div> | ||
) | ||
}) |
19 changes: 19 additions & 0 deletions
19
packages/desktop/src/renderer/components/hooks/useOnNodeVec3ValueChange.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { useCallback } from 'react' | ||
import { useOnNodeValueChange } from './useOnNodeValueChange' | ||
|
||
export const useOnNodeVec3ValueChange = (id1: string, id2: string, id3: string) => { | ||
const onValueChange1 = useOnNodeValueChange(id1) | ||
const onValueChange2 = useOnNodeValueChange(id2) | ||
const onValueChange3 = useOnNodeValueChange(id3) | ||
|
||
const onVec3ValueChange = useCallback( | ||
(value: [number, number, number]) => { | ||
onValueChange1(value[0]) | ||
onValueChange2(value[1]) | ||
onValueChange3(value[2]) | ||
}, | ||
[onValueChange1, onValueChange2, onValueChange3], | ||
) | ||
|
||
return onVec3ValueChange | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.