codekingpro/portable-devtools
114k
1/////////////////////////////////////////////////////////////2//3// pgAdmin 4 - PostgreSQL Tools4//5// Copyright (C) 2013 - 2024, The pgAdmin Development Team6// This software is released under the PostgreSQL Licence7//8//////////////////////////////////////////////////////////////9 10/* React HOC on color pickr */11import Pickr from '@simonwep/pickr';12import React, { useEffect, useRef } from 'react';13import gettext from 'sources/gettext';14import PropTypes from 'prop-types';15import { fullHexColor } from '../utils';16 17export function withColorPicker(Component) {18 // eslint-disable-next-line react/display-name19 const HOCComponent = ({value, currObj, onChange, onSave, options, ...props})=>{20 const pickrOptions = {21 showPalette: true,22 allowEmpty: true,23 allowSave: false,24 colorFormat: 'HEX',25 defaultColor: null,26 position: 'right-middle',27 clearText: gettext('Clear'),28 ...options,29 };30 const eleRef = useRef();31 const pickrObj = useRef();32 const onChangeRef = useRef();33 const onSaveRef = useRef();34 35 onChangeRef.current = onChange;36 onSaveRef.current = onSave;37 38 const setColor = (newVal, silent) => {39 pickrObj.current?.setColor((_.isUndefined(newVal) || newVal == '') ? pickrOptions.defaultColor : newVal, silent);40 };41 42 const destroyPickr = () => {43 if (pickrObj.current) {44 pickrObj.current.destroy();45 pickrObj.current = null;46 }47 };48 49 const initPickr = () => {50 /* pickr does not have way to update options, need to51 destroy and recreate pickr to reflect options */52 destroyPickr();53 54 pickrObj.current = new Pickr({55 el: eleRef.current,56 useAsButton: true,57 theme: 'monolith',58 swatches: [59 '#000', '#666', '#ccc', '#fff', '#f90', '#ff0', '#0f0',60 '#f0f', '#f4cccc', '#fce5cd', '#d0e0e3', '#cfe2f3', '#ead1dc', '#ea9999',61 '#b6d7a8', '#a2c4c9', '#d5a6bd', '#e06666', '#93c47d', '#76a5af', '#c27ba0',62 '#f1c232', '#6aa84f', '#45818e', '#a64d79', '#bf9000', '#0c343d', '#4c1130',63 ],64 position: pickrOptions.position,65 strings: {66 clear: pickrOptions.clearText,67 },68 components: {69 palette: pickrOptions.showPalette,70 preview: true,71 hue: pickrOptions.showPalette,72 interaction: {73 clear: pickrOptions.allowEmpty,74 defaultRepresentation: pickrOptions.colorFormat,75 disabled: pickrOptions.disabled,76 save: pickrOptions.allowSave,77 },78 },79 }).on('init', instance => {80 setColor(value);81 pickrOptions.disabled && instance.disable();82 83 const { lastColor } = instance.getRoot().preview;84 const { clear } = instance.getRoot().interaction;85 86 /* Cycle the keyboard navigation within the color picker */87 clear.addEventListener('keydown', (e) => {88 if (e.keyCode === 9) {89 e.preventDefault();90 e.stopPropagation();91 lastColor.focus();92 }93 });94 95 lastColor.addEventListener('keydown', (e) => {96 if (e.keyCode === 9 && e.shiftKey) {97 e.preventDefault();98 e.stopPropagation();99 clear.focus();100 }101 });102 }).on('clear', () => {103 onChangeRef.current?.('');104 }).on('change', (color) => {105 onChangeRef.current?.(color.toHEXA().toString());106 }).on('show', (color, instance) => {107 const { palette } = instance.getRoot().palette;108 palette.focus();109 }).on('hide', (instance) => {110 const button = instance.getRoot().button;111 button.focus();112 }).on('save', (color, instance) => {113 if(color) {114 color.toHEXA().toString() != fullHexColor(value) && onSaveRef.current?.(color.toHEXA().toString());115 instance?.hide();116 } else {117 onSaveRef.current?.('');118 }119 });120 121 if (currObj) {122 currObj(pickrObj.current);123 }124 };125 126 useEffect(() => {127 initPickr();128 return () => {129 destroyPickr();130 };131 }, [...Object.values(pickrOptions)]);132 133 useEffect(() => {134 if (pickrObj.current) {135 setColor(value, true);136 }137 }, [value]);138 139 return <Component ref={eleRef} {...props}/>;140 };141 142 HOCComponent.propTypes = {143 value: PropTypes.string,144 currObj: PropTypes.func,145 onChange: PropTypes.func,146 onSave: PropTypes.func,147 options: PropTypes.object,148 };149 150 return HOCComponent;151}152 