Created
October 25, 2023 15:25
-
-
Save MarkAtOmniux/b630051f26d6759bd3a83387de97d15f to your computer and use it in GitHub Desktop.
PayloadCMS Color Picker Field
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
import React from 'react'; | |
import { Props } from 'payload/components/views/Cell'; | |
import './styles.scss'; | |
const Cell: React.FC<Props> = (props) => { | |
const { cellData } = props; | |
if (!cellData) return null; | |
return ( | |
<div | |
className={`chip`} | |
style={{ backgroundColor: cellData as string }} | |
> | |
</div> | |
) | |
} | |
export default Cell; |
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
import React, { useEffect, useState, useCallback, Fragment } from 'react'; | |
import { useFieldType } from 'payload/components/forms'; | |
import { usePreferences } from 'payload/components/preferences'; | |
import { Label } from 'payload/components/forms'; | |
import { Props } from 'payload/components/fields/Text'; | |
import './styles.scss'; | |
import { validateHexColor } from '.'; | |
import { HexColorInput, HexColorPicker } from 'react-colorful'; | |
const defaultColor = '#9A9A9A'; | |
const baseClass = 'custom-color-picker'; | |
const preferenceKey = 'color-picker-color'; | |
const InputField: React.FC<Props> = (props) => { | |
const { path, label, required, defaultValue } = props; | |
const { value = '', setValue } = useFieldType({ | |
path, | |
validate: validateHexColor, | |
}); | |
const { getPreference, setPreference } = usePreferences(); | |
const [color, setColor] = useState(value ?? defaultValue ?? defaultColor); | |
const [isAdding, setIsAdding] = useState(false); | |
const [colorToAdd, setColorToAdd] = useState(value ?? defaultValue ?? defaultColor); | |
useEffect(() => { | |
const mergeColorsFromPreferences = async () => { | |
const colorPreference = await getPreference<string>( | |
path + '-' + preferenceKey | |
); | |
if (colorPreference) { | |
setColor(colorPreference); | |
} | |
}; | |
mergeColorsFromPreferences(); | |
}, [getPreference, setColor]); | |
const handleAddColor = useCallback((val?: string) => { | |
console.log(val) | |
setIsAdding(false); | |
setValue(colorToAdd); | |
// update state with new colors | |
setColor(colorToAdd); | |
// store the user color preferences for future use | |
setPreference(path + '-' + preferenceKey, colorToAdd); | |
}, [color, setPreference, colorToAdd, setIsAdding, setValue]); | |
return ( | |
<div className={baseClass}> | |
<Label htmlFor={path} label={label} required={required} /> | |
{isAdding && ( | |
<div> | |
<HexColorPicker | |
onBlur={(e) => { | |
if ( | |
e.relatedTarget === null && | |
validateHexColor(colorToAdd) === true | |
) { | |
handleAddColor(); | |
} | |
}} | |
onChange={setColorToAdd} | |
color={colorToAdd} | |
/> | |
<HexColorInput | |
prefixed | |
alpha | |
onKeyDown={ ({ code }) => { | |
if (code === 'Enter') { | |
if (validateHexColor(colorToAdd) === true | |
) { | |
handleAddColor(); | |
} | |
} | |
}} | |
onBlur={(e) => { | |
if ( | |
e.relatedTarget === null && | |
validateHexColor(colorToAdd) === true | |
) { | |
handleAddColor(); | |
} | |
}} | |
className={`${baseClass}__input`} | |
color={colorToAdd} | |
onChange={setColorToAdd} | |
/> | |
</div> | |
)} | |
{!isAdding && ( | |
<Fragment> | |
<button | |
type='button' | |
className={`chip chip--clickable`} | |
style={{ backgroundColor: color }} | |
aria-label={color} | |
onClick={() => { | |
setValue(color); | |
setIsAdding(true); | |
}} | |
/> | |
</Fragment> | |
)} | |
</div> | |
); | |
}; | |
export default InputField; |
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
import { Field as FieldType, RichTextField } from 'payload/types'; | |
import Cell from './Cell'; | |
import Field from './Field'; | |
import { TextField } from 'payload/dist/fields/config/types'; | |
export const validateHexColor = (value: string = ''): true | string => { | |
return ( | |
value.match(/^#(?:[0-9a-fA-F]{3}){1,2}$/) !== null || | |
`Please give a valid hex color` | |
); | |
}; | |
type ColorPicker = (name: string, overrides?: Partial<TextField>) => FieldType; | |
export const colorField: ColorPicker = ( | |
name = 'colorField', | |
overrides = {} | |
) => { | |
return { | |
name: name, | |
type: 'text', | |
validate: validateHexColor, | |
admin: { | |
components: { | |
Field, | |
Cell, | |
}, | |
}, | |
...overrides, | |
}; | |
}; |
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
@import '~payload/scss'; | |
.add-color.btn { | |
margin: 0; | |
padding: 0; | |
border: $style-stroke-width-m solid #fff; | |
} | |
.custom-color-picker { | |
max-width: fit-content; | |
margin-right: 1rem; | |
&__btn.btn { | |
margin: base(0.5); | |
&:first-of-type { | |
margin-left: unset; | |
} | |
} | |
&__input { | |
// Payload exports a mixin from the vars file for quickly applying formInput rules to the class for our input | |
@include formInput; | |
} | |
&__colors { | |
display: flex; | |
flex-wrap: wrap; | |
list-style: none; | |
padding: 0; | |
margin: 0; | |
} | |
} | |
.chip { | |
border-radius: 50%; | |
border: $style-stroke-width-m solid #fff; | |
height: base(1.25); | |
width: base(1.25); | |
margin-right: base(0.5); | |
box-shadow: none; | |
&--selected { | |
box-shadow: 0 0 0 $style-stroke-width-m $color-dark-gray; | |
} | |
&--clickable { | |
cursor: pointer; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment