import { groupBy, startCase } from 'lodash'; import React, { useEffect, useMemo, useRef, useState } from 'react'; import { copyToClipboard } from '../../helpers/copy-to-clipboard'; import { SilkeColorTheme } from '../../silke-theme-provider'; import { SilkeBox } from '../silke-box'; import { SilkeButton } from '../silke-button'; import { SilkeColorPickerButton } from '../silke-color-picker'; import { SilkeText, SilkeTitle } from '../silke-text'; import { SilkeTextField } from '../silke-text-field'; type SilkeThemeEditorProps = { theme: SilkeColorTheme; search?: string; onChange: (theme: SilkeColorTheme) => void; }; export function SilkeThemeEditor({ theme, search, onChange }: SilkeThemeEditorProps) { const colors: string[] = useMemo( () => [ 'color-accent-60', 'color-accent-50', 'color-accent-40', 'color-accent-30', 'color-accent-20', 'color-accent-10', 'color-error-60', 'color-error-50', 'color-error-40', 'color-error-30', 'color-error-20', 'color-error-10', 'color-warning-60', 'color-warning-50', 'color-warning-40', 'color-warning-30', 'color-warning-20', 'color-warning-10', 'color-success-60', 'color-success-50', 'color-success-40', 'color-success-30', 'color-success-20', 'color-success-10', 'color-neutral-0', 'color-neutral-40', 'color-neutral-30', 'color-neutral-20', 'color-neutral-10', 'color-neutral-5', 'color-neutral-100', 'color-neutral-90', 'color-neutral-80', 'color-neutral-70', 'color-neutral-60', 'color-neutral-50', 'color-support-secondary-60', 'color-support-secondary-50', 'color-support-secondary-40', 'color-support-secondary-30', 'color-support-secondary-20', 'color-support-secondary-10', 'color-support-primary-60', 'color-support-primary-50', 'color-support-primary-40', 'color-support-primary-30', 'color-support-primary-20', 'color-support-primary-10', 'color-brand-primary-60', 'color-brand-primary-bright', 'color-brand-primary-30', 'color-brand-primary-10', 'color-brand-secondary-bright', 'color-brand-secondary-30', 'color-brand-secondary-10', 'color-brand-secondary-60', 'color-brand-tertiary-bright', 'color-brand-tertiary-60', 'color-brand-tertiary-30', 'color-brand-tertiary-10', 'color-brand-quaternary-60', 'color-brand-quaternary-30', 'color-brand-quaternary-10', ], [], ); const ref = useRef(null); const [currentColors, setCurrentColors] = useState({}); useEffect(() => { const el = ref.current; if (!el) return; const computed = getComputedStyle(el); const current: SilkeColorTheme = {}; for (const color of colors) { current[color as keyof SilkeColorTheme] = computed.getPropertyValue('--' + color); } setCurrentColors(current); }, [colors]); const group = useMemo(() => { const filteredColors = search ? colors.filter((c) => c.search(search) !== -1) : colors; return groupBy(filteredColors, (color) => color.replace('color-', '').split('-')[0]); }, [search, colors]); return ( { let s = ''; let group = ''; for (const color of colors) { const colorGroup = startCase(color).split(' ').slice(1, -1).join('/'); if (colorGroup !== group) { group = colorGroup; s += `\n//${colorGroup}\n`; } const value = theme?.[color as keyof SilkeColorTheme] || currentColors[color as keyof SilkeColorTheme]; s += `"${color}" ${value},\n`; } copyToClipboard(s.slice(0, -2) + ';'); }} /> {Object.entries(group).map(([groupName, colors]) => ( {startCase(groupName)} {colors.map((color) => ( { onChange({ ...theme, [color]: value }); }} /> { onChange({ ...theme, [color]: value }); }} /> ))} ))} ); }