react-email-builder
Version:
A simple React drag and drop email builder.
126 lines (125 loc) • 4.48 kB
JavaScript
import clsx from 'clsx';
import React, { useEffect, useState } from 'react';
import { HexColorPicker } from 'react-colorful';
import { getPresetColors } from './preset';
import { getCss } from '../../utils';
export function ColorPalette({ color: propColor, onChange, onSelect }) {
const css = useCss();
const color = (propColor || '#000000').toUpperCase();
return (React.createElement("div", { className: css.root },
React.createElement("div", { className: css.colors }, getPresetColors().map((val) => (React.createElement("div", { key: val, className: clsx(css.color, {
[css.active]: val === color
}), onClick: () => {
onChange(val);
onSelect?.();
} },
React.createElement("div", { style: { backgroundColor: val } }))))),
React.createElement(Input, { color: color, onChange: onChange }),
React.createElement(HexColorPicker, { color: color, onChange: onChange, style: { width: '100%', height: 150 } })));
}
function useCss() {
return getCss('ColorPalette', (ns) => ({
root: ns(),
colors: ns('colors'),
color: ns('color'),
active: ns('active'),
form: ns('form'),
mode: ns('mode'),
input: ns('input'),
selected: ns('selected'),
preview: ns('preview')
}));
}
function Input({ color, onChange }) {
const [mode, setMode] = useState('hex');
const [focused, setFocused] = useState(false);
const [input, setInput] = useState('');
const css = useCss();
useEffect(() => {
if (!focused) {
if (color) {
setInput(mode === 'hex' ? color.toUpperCase() : hex2rgb(color));
}
else {
setInput('');
}
}
}, [mode, focused, color]);
return (React.createElement("div", { className: css.form },
React.createElement("div", { className: css.mode },
React.createElement("div", { className: mode === 'hex' ? css.selected : '', onClick: () => {
setMode('hex');
} }, "HEX"),
React.createElement("div", { className: mode === 'rgb' ? css.selected : '', onClick: () => {
setMode('rgb');
} }, "RGB")),
React.createElement("div", { className: css.input },
React.createElement("input", { placeholder: "\u8BF7\u8F93\u5165", value: input, onFocus: () => {
setFocused(true);
}, onBlur: () => {
setFocused(false);
}, onChange: (e) => {
const value = e.target.value;
const newColor = parseColor(value);
setInput(value);
if (newColor) {
onChange(newColor);
}
} })),
React.createElement("div", { className: css.preview },
React.createElement("div", { style: { backgroundColor: color } }))));
}
function parseColor(color) {
const val = color
.trim()
.replace(/rgba?/i, '')
.replace(/[^0-9a-fA-F,.\s%]/g, '');
const arr = val.split(/[\s,]+/);
let result;
if (arr.length > 1 || val.includes('%')) {
const hex = (s) => {
let n = 0;
if (s) {
if (s.endsWith('%')) {
n = Math.round(((+s.slice(0, -1) || 0) * 255) / 100);
}
else {
n = Math.round(+s || 0);
}
}
if (n < 0) {
n = 0;
}
if (n > 255) {
n = 255;
}
const h = n.toString(16);
return h.length < 2 ? '0' + h : h;
};
result = '#' + hex(arr[0]) + hex(arr[1]) + hex(arr[2]);
}
else {
if (val.length === 3) {
const [r, g, b] = val.split('');
result = '#' + r + r + g + g + b + b;
}
else if (val.length === 6) {
result = '#' + val;
}
}
return result?.toUpperCase();
}
function hex2rgb(color) {
const hex = parseColor(color);
if (hex) {
const num = (s) => parseInt(s, 16) || 0;
return ('rgb(' +
num(hex.slice(1, 3)) +
', ' +
num(hex.slice(3, 5)) +
', ' +
num(hex.slice(5)) +
')');
}
return 'rgb(0, 0, 0)';
}