import React, { useContext, useEffect, useRef } from 'react'; import tinycolor from 'tinycolor2'; import SilkePopoverProvider from './components/silke-popover/popover-context'; type SilkeColorGroup = | 'surface' | 'accent' | 'error' | 'warning' | 'success' | 'neutral' | 'support-primary' | 'support-secondary' | 'support-tertiary' | 'support-quaternary' | 'brand-primary' | 'brand-secondary' | 'brand-tertiary' | 'brand-quaternary'; export type SilkeColor = | `${SilkeColorGroup}-${'10' | '20' | '30' | '40' | '50' | '60'}` | `neutral-${'0' | '5' | '70' | '80' | '90' | '100'}` | `brand-${'primary' | 'secondary' | 'tertiary'}-bright` | `surface-${'0' | '1' | '2' | '3' | '4'}`; export type SilkeColorTheme = Partial>; type SilkeContextModel = { /** WHen a overflow menu is mounted this is set, call function to close */ mountedOverflowMenu?: () => void; colors?: SilkeColorTheme; onFileUpload: (file: File) => Promise; }; type SilkeThemeProviderProps = { children: React.ReactElement; } & Omit; const SilkeThemeContext = React.createContext({ onFileUpload: async () => '' }); export function useSilkeContext() { return useContext(SilkeThemeContext); } export function SilkeThemeProvider({ children, ...rest }: SilkeThemeProviderProps) { const ref = useRef(null); const { colors } = rest; useEffect(() => { // We use a non wrapping element so we don't need to care about layout and fill etc, can result in 2 theme providers using same parent element, but very unlikely const el = ref.current?.parentElement; if (!el || !colors) return; for (const key in colors) { const color = colors[key as keyof SilkeColorTheme]; if (color) { el?.style.setProperty('--' + key, color); const { r, g, b } = tinycolor(color).toRgb(); el?.style.setProperty(`--${key}-rgb`, `${r},${g},${b}`); } } return () => { for (const key in colors) { el?.style.removeProperty('--' + key); el?.style.removeProperty(`--${key}-rgb`); } }; }, [colors]); return (
{children} ); }