import { useRender } from 'src/components/IdeWrapper/useRender' import { useIdeContext } from 'src/helpers/hooks/useIdeContext' import { Switch } from '@headlessui/react' import Svg from 'src/components/Svg/Svg' import { CadhubStringParam, CadhubBooleanParam, CadhubNumberParam, } from './customizerConverter' import { debounce } from 'lodash' const Customizer = () => { const [open, setOpen] = React.useState(false) const [shouldLiveUpdate, setShouldLiveUpdate] = React.useState(false) const { state, thunkDispatch } = useIdeContext() const customizerParams = state?.customizerParams const currentParameters = state?.currentParameters || {} const handleRender = useRender() const updateCustomizerParam = (paramName: string, paramValue: any) => { const payload = { ...currentParameters, [paramName]: paramValue, } thunkDispatch({ type: 'setCurrentCustomizerParams', payload }) shouldLiveUpdate && setTimeout(() => handleRender()) } if (!customizerParams?.length) return null return (
Parameters
{open && ( <>
Auto Update
{ if (newValue) handleRender() setShouldLiveUpdate(newValue) }} className={`${ shouldLiveUpdate ? 'bg-ch-purple-600' : 'bg-ch-gray-300' } relative inline-flex items-center h-6 rounded-full w-11 mr-6`} >
)}
{customizerParams.map((param, index) => { const otherProps = { value: currentParameters[param.name], onChange: (value) => updateCustomizerParam(param.name, value), } if (param.type === 'string') { return } else if (param.type === 'number') { return } else if (param.type === 'boolean') { return } return
{JSON.stringify(param)}
})}
) } export default Customizer function CustomizerParamBase({ name, caption, children, }: { name: string caption: string children: React.ReactNode }) { return (
  • {name}
    {caption}
    {children}
  • ) } function BooleanParam({ param, value, onChange, }: { param: CadhubBooleanParam value: any onChange: Function }) { return ( { onChange(newValue) }} className={`${ value ? 'bg-ch-gray-300' : 'bg-ch-gray-600' } relative inline-flex items-center h-6 rounded-full w-11 mr-6 border border-ch-gray-300`} > ) } function StringParam({ param, value, onChange, }: { param: CadhubStringParam value: any onChange: Function }) { return ( onChange(target?.value)} /> ) } function NumberParam({ param, value, onChange, }: { param: CadhubNumberParam value: any onChange: Function }) { const [isFocused, isFocusedSetter] = React.useState(false) const [localValue, localValueSetter] = React.useState(0) const [isLocked, isLockedSetter] = React.useState(false) const [pixelsDragged, pixelsDraggedSetter] = React.useState(0) const handleRender = useRender() const liveRenderHandler = debounce((a) => handleRender(a), 250) const step = param.step || 1 const commitChange = () => { let num = localValue if (typeof param.step === 'number') { num = Math.round(num / step) * step } if (typeof param.min === 'number') { num = Math.max(param.min, num) } if (typeof param.max === 'number') { num = Math.min(param.max, num) } num = Number(num.toFixed(2)) localValueSetter(num) onChange(num) } React.useEffect(() => { if (!isFocused) commitChange() }, [isFocused]) React.useEffect(() => localValueSetter(value), [value]) return (
    localValue) ? 'text-red-500' : '' }`} type="number" value={localValue} onFocus={() => isFocusedSetter(true)} onBlur={() => isFocusedSetter(false)} onKeyDown={({ key }) => key === 'Enter' && commitChange()} onChange={({ target }) => { const num = Number(target?.value) localValueSetter(num) }} max={param.max} min={param.min} step={step} />
    { isLockedSetter(true) target?.requestPointerLock?.() pixelsDraggedSetter(localValue) }} onMouseUp={() => { isLockedSetter(false) document?.exitPointerLock?.() commitChange() }} onMouseMove={({ movementX }) => { if (isLocked && movementX) { pixelsDraggedSetter(pixelsDragged + (movementX * step) / 8) // one step per 8 pixels localValueSetter(Number(pixelsDragged.toFixed(2))) liveRenderHandler({[param.name]: Number(pixelsDragged.toFixed(2))}) } }} >
    ) }