Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 0 additions & 36 deletions packages/uniwind/src/hooks/useCSSVariable.native.ts

This file was deleted.

56 changes: 0 additions & 56 deletions packages/uniwind/src/hooks/useCSSVariable.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { UniwindStore } from '../../core/native'

export const getVariableValue = (name: string) => UniwindStore.vars[name]
19 changes: 19 additions & 0 deletions packages/uniwind/src/hooks/useCSSVariable/getVariableValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { parseCSSValue } from '../../core/web'

const documentStyles = typeof document !== 'undefined'
? window.getComputedStyle(document.documentElement)
: null

export const getVariableValue = (name: string) => {
if (!documentStyles) {
return undefined
}

const value = documentStyles.getPropertyValue(name).trim()

if (value === '') {
return undefined
}

return parseCSSValue(value)
}
1 change: 1 addition & 0 deletions packages/uniwind/src/hooks/useCSSVariable/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './useCSSVariable'
87 changes: 87 additions & 0 deletions packages/uniwind/src/hooks/useCSSVariable/useCSSVariable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { useEffect, useRef, useState } from 'react'
import { UniwindListener } from '../../core/listener'
import { StyleDependency } from '../../types'
import { getVariableValue } from './getVariableValue'

const getValue = (name: string | Array<string>) =>
Array.isArray(name)
? name.map(getVariableValue)
: getVariableValue(name)

const arrayEquals = <T>(a: Array<T>, b: Array<T>) => {
if (a.length !== b.length) {
return false
}

return a.every((value, index) => value === b[index])
}

let warned = false

const logDevError = (name: string) => {
warned = true

// eslint-disable-next-line no-console
console.warn(
`We couldn't find your variable ${name}. Make sure it's used at least once in your className, or define it in a static theme as described in the docs: https://docs.uniwind.dev/api/use-css-variable`,
)
}

type IsGenericNumber<T> = T & 0 extends -1 ? false : true
type CreateArray<N extends number, Value, TAcc extends Array<Value> = []> = TAcc['length'] extends N ? TAcc : CreateArray<N, Value, [...TAcc, Value]>

type UseCSSVariable = {
(name: string): string | number | undefined
<const T extends Array<string>>(
names: T,
): IsGenericNumber<T['length']> extends true ? Array<string | number | undefined> : CreateArray<T['length'], string | number | undefined>
}

/**
* A hook that returns the value of a CSS variable.
* @param name Name / Array of names of the CSS variable.
* @returns Value / Values of the CSS variable. On web it is always a string (1rem, #ff0000, etc.), but on native it can be a string or a number (16px, #ff0000)
*/
export const useCSSVariable: UseCSSVariable = (name: string | Array<string>) => {
const [value, setValue] = useState(getValue(name))
const nameRef = useRef(name)

useEffect(() => {
if (Array.isArray(name) && Array.isArray(nameRef.current)) {
if (arrayEquals(name, nameRef.current)) {
return
}

setValue(getValue(name))
nameRef.current = name

return
}

if (name !== nameRef.current) {
setValue(getValue(name))
nameRef.current = name
}
}, [name])

useEffect(() => {
const updateValue = () => setValue(getValue(nameRef.current))
const dispose = UniwindListener.subscribe(updateValue, [StyleDependency.Theme])

return dispose
}, [])

if (Array.isArray(value)) {
value.forEach((val, index) => {
if (val === undefined && __DEV__ && !warned) {
logDevError(name[index] ?? '')
}
})
}

if (value === undefined && __DEV__ && !warned) {
logDevError(name as string)
}

return value as never
}