feat: element customize component

This commit is contained in:
Ahmed Bouhuolia
2024-09-09 21:07:22 +02:00
parent dc18bde6be
commit f644ed6708
25 changed files with 319 additions and 292 deletions

View File

@@ -0,0 +1,15 @@
.field{
height: 28px;
line-height: 28px;
border-radius: 5px;
}
.colorPicker{
background-color: rgb(103, 114, 229);
border-radius: 3px;
height: 16px;
width: 16px;
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
cursor: pointer;
}

View File

@@ -0,0 +1,80 @@
import { useState } from 'react';
import clsx from 'classnames';
import {
IInputGroupProps,
InputGroup,
IPopoverProps,
Popover,
PopoverInteractionKind,
Position,
} from '@blueprintjs/core';
import { HexColorPicker } from 'react-colorful';
import { useUncontrolled } from '@/hooks/useUncontrolled';
import { Box, BoxProps } from '@/components';
import styles from './ColorInput.module.scss';
export interface ColorInputProps {
value?: string;
initialValue?: string;
onChange?: (value: string) => void;
popoverProps?: Partial<IPopoverProps>;
inputProps?: Partial<IInputGroupProps>;
pickerProps?: Partial<BoxProps>;
pickerWrapProps?: Partial<BoxProps>;
}
export function ColorInput({
value,
initialValue,
onChange,
popoverProps,
inputProps,
pickerWrapProps,
pickerProps,
}: ColorInputProps) {
const [_value, handleChange] = useUncontrolled({
value,
initialValue,
onChange,
finalValue: '',
});
const [isOpen, setIsOpen] = useState<boolean>(false);
const handleClose = () => {
setIsOpen(false);
};
return (
<Popover
content={<HexColorPicker color={_value} onChange={handleChange} />}
position={Position.BOTTOM}
interactionKind={PopoverInteractionKind.CLICK}
modifiers={{
offset: { offset: '0, 4' },
}}
onClose={handleClose}
isOpen={isOpen}
minimal
{...popoverProps}
>
<InputGroup
value={_value}
leftElement={
<Box
{...pickerWrapProps}
style={{ padding: 8, ...pickerWrapProps?.style }}
>
<Box
onClick={() => setIsOpen((oldValue) => !oldValue)}
style={{ backgroundColor: _value }}
className={clsx(styles.colorPicker, pickerProps?.className)}
{...pickerProps}
/>
</Box>
}
{...inputProps}
className={clsx(styles.field, inputProps?.className)}
/>
</Popover>
);
}

View File

@@ -0,0 +1,64 @@
import React from 'react';
import { getIn, FieldConfig, FieldProps } from 'formik';
import { Intent } from '@blueprintjs/core';
import { Field } from '@blueprintjs-formik/core';
import { ColorInput, ColorInputProps } from './ColorInput';
interface ColorInputInputGroupProps
extends Omit<FieldConfig, 'children' | 'component' | 'as' | 'value'>,
ColorInputProps {}
export interface ColorInputToInputProps
extends Omit<FieldProps, 'onChange'>,
ColorInputProps {}
/**
* Transforms field props to input group props for ColorInput.
* @param {ColorInputToInputProps}
* @returns {ColorInputProps}
*/
function fieldToColorInputInputGroup({
field: { onBlur: onFieldBlur, onChange: onFieldChange, value, ...field },
form: { touched, errors, setFieldValue },
onChange,
...props
}: ColorInputToInputProps): ColorInputProps {
const fieldError = getIn(errors, field.name);
const showError = getIn(touched, field.name) && !!fieldError;
return {
inputProps: {
intent: showError ? Intent.DANGER : Intent.NONE,
},
value,
onChange:
onChange ??
function (value: string) {
setFieldValue(field.name, value);
},
...field,
...props,
};
}
/**
* Transforms field props to input group props for ColorInput.
* @param {ColorInputToInputProps} props -
* @returns {JSX.Element}
*/
function ColorInputToInputGroup({
...props
}: ColorInputToInputProps): JSX.Element {
return <ColorInput {...fieldToColorInputInputGroup(props)} />;
}
/**
* Input group Blueprint component binded with Formik for ColorInput.
* @param {ColorInputInputGroupProps}
* @returns {JSX.Element}
*/
export function FColorInput({
...props
}: ColorInputInputGroupProps): JSX.Element {
return <Field {...props} component={ColorInputToInputGroup} />;
}