UNPKG

css-vars-hook

Version:

css-vars-hook contains React hooks to set and manipulate CSS custom properties from React component.

1 lines 17.4 kB
{"version":3,"file":"index.umd.cjs","sources":["../src/lib/RootTheme/RootContext.ts","../src/lib/RootTheme/useRootThemePublic.ts","../src/lib/utils.ts","../src/lib/RootTheme/useRootTheme.ts","../src/lib/RootTheme/RootThemeProvider.tsx","../src/lib/LocalTheme/LocalRoot.tsx","../src/lib/LocalTheme/useLocalTheme.tsx"],"sourcesContent":["import type {Context} from 'react';\nimport {useContext, createContext} from 'react';\n\nimport type {Theme} from '@/lib/ThemeType.ts';\n\nimport type {HookInterface} from './HookInterfaceType';\n\nexport const RootContext = createContext({\n setTheme: () => {},\n getTheme: () => ({}),\n setVariable: () => {},\n getVariable: () => '',\n removeVariable: () => {},\n} as HookInterface<Theme>);\n\nexport const useRootContext = <TTheme extends Theme>() =>\n useContext<HookInterface<TTheme>>(\n RootContext as unknown as Context<HookInterface<TTheme>>\n );\n","import type {Theme} from '@/lib/ThemeType.ts';\n\nimport {useRootContext} from './RootContext';\n\n/**\n * @public\n * React hook to apply multiple CSS variables to theme root and manipulate them.\n * `ThemeType` is defined on project level.\n * @see ThemeType\n * @see https://github.com/morewings/css-vars-hook#type-safety\n */\nexport const useRootThemePublic = <TTheme extends Theme>() => {\n const {setTheme, getTheme, setVariable, getVariable, removeVariable} =\n useRootContext<TTheme>();\n return {\n /** Effect to apply new theme to the application */\n setTheme,\n /** Get current theme */\n getTheme,\n /** Effect to set new variable value within active theme */\n setVariable,\n /** Get variable value within active theme */\n getVariable,\n /** Effect to remove variable within active theme */\n removeVariable,\n };\n};\n","import type {MutableRefObject, CSSProperties} from 'react';\n\nimport type {UnitType, Theme} from '@/lib/ThemeType.ts';\n\nconst normalizeUnit = (unit: UnitType) => {\n if (typeof unit === 'string') {\n return unit;\n }\n return `${unit}`;\n};\n\n/**\n * Add `--` prefix to property names in theme object in order to make it applicable to DOM node\n */\nexport const createStyleObject = (theme: Theme): CSSProperties => {\n const keys = Object.keys(theme);\n const result: Record<string, UnitType> = {};\n keys.forEach(key => {\n result[`--${key}`] = theme[key];\n });\n return result;\n};\n\n/**\n * Add `--` prefix to property names in theme object in order to make it applicable to DOM node\n */\nexport const createStyleString = (theme: Theme) => {\n const keys = Object.keys(theme);\n let result = '';\n keys.forEach(key => {\n result = `${result}--${key}:${theme[key]};`;\n });\n return result;\n};\n\n/**\n * Set CSS theme at the provided DOM node\n */\nexport const setCSSTheme = (element: HTMLElement) => (theme: Theme) => {\n const style = createStyleString(theme);\n element?.setAttribute('style', style);\n};\n\n/**\n * Set CSS variable at the provided DOM node\n */\nexport const setCSSVariable =\n (element: HTMLElement) => (variableName: string, value: UnitType) => {\n element.style.setProperty(`--${variableName}`, normalizeUnit(value));\n };\n\n/**\n * Remove CSS variable from the provided DOM node\n */\nexport const removeCSSVariable =\n (ref: MutableRefObject<HTMLElement>) => (variableName: string) => {\n const element = ref.current;\n element?.style?.removeProperty?.(`--${variableName}`);\n };\n\n/**\n * Get CSS variable value at the provided DOM node\n */\nexport const getCSSVariable =\n (ref: MutableRefObject<HTMLElement>) => (variableName: string) => {\n const element = ref.current;\n return element?.style?.getPropertyValue?.(`--${variableName}`);\n };\n\n/**\n * Set new theme be replacing `style` attribute content\n */\nexport const setRootTheme = (id: string) => (theme: Theme) => {\n const root = document.getElementById(id)!;\n const style = createStyleString(theme);\n root?.setAttribute('style', style);\n};\n\n/**\n * Set CSS variable on theme root element\n */\nexport const setRootVariable =\n (id: string) => (variableName: string, value: UnitType) => {\n const root = document.getElementById(id)!;\n root?.style?.setProperty?.(`--${variableName}`, normalizeUnit(value));\n };\n\n/**\n * Get CSS variable on theme root element\n */\nexport const getRootVariable =\n (id: string) =>\n (variableName: string): string => {\n const root = document.getElementById(id)!;\n return root?.style?.getPropertyValue?.(`--${variableName}`);\n };\n\n/**\n * Remove CSS variable from theme root element\n */\nexport const removeRootVariable = (id: string) => (variableName: string) => {\n const root = document.getElementById(id)!;\n root?.style?.removeProperty?.(`--${variableName}`);\n};\n","import {useCallback, useMemo, useRef} from 'react';\nimport type {CSSProperties} from 'react';\n\nimport type {UnitType, Theme} from '@/lib/ThemeType.ts';\n\nimport {\n createStyleObject,\n getRootVariable,\n removeRootVariable,\n setRootVariable,\n setRootTheme,\n} from '../utils';\nimport type {HookInterface} from './HookInterfaceType';\n\n/**\n * @private\n * Logic for root theme handling such as updates and CSS style creation\n */\nexport const useRootTheme = <TTheme extends Theme>(\n theme: TTheme,\n id: string\n): HookInterface<TTheme> & {style: CSSProperties} => {\n const themeRef = useRef(theme);\n\n const setTheme = useCallback(\n (nextTheme: TTheme) => {\n setRootTheme(id)(nextTheme);\n themeRef.current = nextTheme;\n },\n [id]\n );\n\n const getTheme = useCallback(() => themeRef.current, []);\n\n const getVariable = useCallback(\n (variableName: string) => getRootVariable(id)(variableName),\n [id]\n );\n const setVariable = useCallback(\n (variableName: string, value: UnitType) => {\n setRootVariable(id)(variableName, value);\n themeRef.current = {\n ...themeRef.current,\n [variableName]: value,\n };\n },\n [id]\n );\n\n const removeVariable = useCallback(\n (variableName: string) => {\n removeRootVariable(id)(variableName);\n const nextTheme = {...themeRef.current};\n delete nextTheme[variableName];\n themeRef.current = nextTheme;\n },\n [id]\n );\n\n const style = useMemo(() => createStyleObject(themeRef.current), []);\n\n return {\n /** Effect to apply new theme to the application */\n setTheme,\n /** CSSProperties object to apply to container div */\n style,\n /** Get current theme */\n getTheme,\n /** Get variable value within active theme */\n getVariable,\n /** Effect to set new variable value within active theme */\n setVariable,\n /** Effect to remove variable within active theme */\n removeVariable,\n };\n};\n","import type {FC, ReactNode} from 'react';\nimport {useMemo, useEffect, useId} from 'react';\n\nimport type {Theme} from '@/lib/ThemeType.ts';\n\nimport type {DataAttributes, LibraryProps} from '../NativeProps';\nimport {RootContext} from './RootContext';\nimport {useRootTheme} from './useRootTheme';\n\n/**\n * @public\n */\nexport type RootThemeProviderProps = DataAttributes &\n LibraryProps & {children: ReactNode; theme: Theme};\n\n/**\n * @public\n * Root theme context provider also creates div to contain CSS properties.\n * `ThemeType` is declared globally.\n * @see ThemeType\n * @see https://github.com/morewings/css-vars-hook#type-safety\n */\nexport const RootThemeProvider: FC<RootThemeProviderProps> = ({\n children,\n theme,\n className,\n id,\n ...nativeProps\n}) => {\n const backupId = useId();\n const rootId = id ? id : backupId;\n const {setTheme, style, getTheme, getVariable, setVariable, removeVariable} =\n useRootTheme(theme, rootId);\n\n const {Provider} = RootContext;\n\n const actions = useMemo(\n () => ({setTheme, getTheme, getVariable, setVariable, removeVariable}),\n [setTheme, getTheme, getVariable, setVariable, removeVariable]\n );\n\n useEffect(() => {\n setTheme(theme);\n }, [theme, setTheme]);\n\n return (\n <Provider value={actions}>\n <div {...nativeProps} id={rootId} className={className} style={style}>\n {children}\n </div>\n </Provider>\n );\n};\n","import type {HTMLAttributes, ReactNode} from 'react';\nimport {createElement, forwardRef, useEffect, useMemo} from 'react';\n\nimport {createStyleObject} from '@/lib/utils';\nimport type {DataAttributes, LibraryProps} from '@/lib/NativeProps';\nimport type {Theme} from '@/lib/ThemeType.ts';\n\n/**\n * @public\n */\nexport type LocalRootProps = DataAttributes &\n LibraryProps &\n HTMLAttributes<HTMLElement> & {\n children?: ReactNode;\n /** Choose which HTMLElement to render as a root. div is default. */\n as?: string;\n /** Apply initial theme. */\n theme?: Theme;\n /** Provide theme setter function. */\n setTheme?: (arg0: Theme) => void;\n };\n\nexport const LocalRoot = forwardRef<HTMLElement, LocalRootProps>((props, ref) => {\n // This is needed to fix an error introduced in version 0.6.14.\n // Props were not transported to returned HTMLElement.\n const {children, as = 'div', theme = {}, setTheme = () => {}, ...restProps} = props;\n\n const initialStyle = useMemo(() => createStyleObject(theme), [theme]);\n\n useEffect(() => {\n setTheme(theme);\n }, [theme, setTheme]);\n\n return createElement(as, {...restProps, style: initialStyle, ref}, children);\n});\n\nLocalRoot.displayName = 'LocalRoot';\n","import {useCallback, useRef, useMemo} from 'react';\n\nimport {setCSSVariable, setCSSTheme} from '@/lib/utils';\nimport type {UnitType, Theme} from '@/lib/ThemeType.ts';\n\nimport type {LocalRootProps} from './LocalRoot';\nimport {LocalRoot} from './LocalRoot';\n\n/**\n * @public\n * React hook to apply multiple CSS variables to generated local root element (LocalRoot) and manipulate them.\n * Theme type is inferred from provided theme parameter.\n * @example\n * const {setTheme, getTheme, LocalRoot, getVariable, setVariable} = useLocalTheme();\n * const setThemeIvory = () => {\n * setTheme({foo: 'ivory'});\n * console.log('full theme', getTheme()) // => {foo: 'ivory'};\n * console.log('foo value', getVariable('foo')) // => 'ivory';\n *};\n * return <LocalRoot theme={{foo: 'bar'}} className=\"demo-local\">//...\n */\nexport const useLocalTheme = <TElement extends HTMLElement>() => {\n const themeRef = useRef<Theme>();\n const elementRef = useRef<TElement>(null);\n\n const setTheme = useCallback((nextTheme: Theme) => {\n setCSSTheme(elementRef.current!)(nextTheme);\n\n themeRef.current = nextTheme;\n }, []);\n\n const getTheme = useCallback(() => themeRef.current, []);\n\n const getVariable = useCallback(\n (variableName: string) => themeRef.current?.[variableName],\n []\n );\n\n const setVariable = useCallback((variableName: string, variableValue: UnitType) => {\n setCSSVariable(elementRef.current!)(variableName, variableValue);\n themeRef.current = {...themeRef.current, [variableName]: variableValue};\n }, []);\n\n const MemoRoot = useMemo(\n () =>\n // eslint-disable-next-line react/display-name\n ({children, ...restProps}: Omit<LocalRootProps, 'setTheme'>) => (\n <LocalRoot {...restProps} setTheme={setTheme} ref={elementRef}>\n {children}\n </LocalRoot>\n ),\n [setTheme]\n );\n\n return {\n /** Effect to apply new theme to LocalRoot */\n setTheme,\n /** Get current theme set for LocalRoot */\n getTheme,\n /** Wrapper component which creates DOM node to store theme data */\n LocalRoot: MemoRoot,\n /** React Mutable Ref object attached to LocalRoot */\n ref: elementRef,\n /** Get variable value within LocalRoot theme */\n getVariable,\n /** Effect to set new variable value within LocalRoot theme */\n setVariable,\n };\n};\n"],"names":["RootContext","createContext","useRootContext","useContext","useRootThemePublic","setTheme","getTheme","setVariable","getVariable","removeVariable","normalizeUnit","unit","createStyleObject","theme","keys","result","key","createStyleString","setCSSTheme","element","style","setCSSVariable","variableName","value","setRootTheme","id","root","setRootVariable","_b","_a","getRootVariable","removeRootVariable","useRootTheme","themeRef","useRef","useCallback","nextTheme","useMemo","RootThemeProvider","children","className","nativeProps","backupId","useId","rootId","Provider","actions","useEffect","jsx","LocalRoot","forwardRef","props","ref","as","restProps","initialStyle","createElement","useLocalTheme","elementRef","variableValue","MemoRoot"],"mappings":"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"}