cleanup and better naming

This commit is contained in:
Eric Bailey
2023-09-14 19:34:50 -05:00
parent 9a2fc9d9bd
commit 737e1d6453
3 changed files with 52 additions and 51 deletions
+40 -40
View File
@@ -12,15 +12,19 @@ import merge from 'lodash.merge'
import {Theme, light} from './themes' import {Theme, light} from './themes'
type ComponentProps = Partial<ViewProps & TextProps & ImageProps> type NativeProps = Partial<ViewProps & TextProps & ImageProps>
export type Props<T = ComponentProps> = Parameters<typeof light.pick<T>>[0] & { export type StyleProps = Parameters<typeof light.style>[0] &
Record<string, unknown>
export type ComponentProps<T = NativeProps> = Parameters<
typeof light.pick<T>
>[0] & {
/** /**
* Debug mode will log the styles and props to the console * Debug mode will log the styles and props to the console
*/ */
debug?: boolean debug?: boolean
} }
type HeadingElements = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' type HeadingElements = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
type TypeProps = Props<TextProps> & { type TypeProps = ComponentProps<TextProps> & {
as?: HeadingElements as?: HeadingElements
} }
@@ -53,44 +57,35 @@ export function useBreakpoints() {
return breakpoints return breakpoints
} }
export function useStyles<T = ComponentProps>(props: Props<T> & T) { export function usePick<T = NativeProps>(props: ComponentProps<T>) {
const {theme} = React.useContext(Context)
return React.useMemo(() => theme.pick(props), [props, theme])
}
export function useStyle(props: StyleProps) {
const {theme} = React.useContext(Context) const {theme} = React.useContext(Context)
const breakpoints = useBreakpoints() const breakpoints = useBreakpoints()
const { const {styles: responsiveStyles} = usePick(props)
styles: responsiveStyles, return React.useMemo(() => {
props: {debug, ...rest},
} = React.useMemo(
() => theme.pick<T & Pick<Props, 'debug'>>(props),
[props, theme],
)
const styles = React.useMemo(() => {
return theme.style( return theme.style(
theme.applyBreakpoints(responsiveStyles, breakpoints.active), theme.applyBreakpoints(responsiveStyles, breakpoints.active),
) )
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [responsiveStyles, breakpoints.current, theme]) }, [responsiveStyles, breakpoints.current, theme])
if (debug) {
console.debug({styles, props: rest, breakpoints})
}
return {styles, props: rest}
} }
export function useMultiStyle< export function useStyles<O extends Record<string, StyleProps>>(
O extends Record<string, Parameters<typeof light.pick<{}>>[0]>,
>(
styles: O, styles: O,
): { ): {
[Name in keyof O]: ReturnType<typeof light.style> [Name in keyof O]: ReturnType<typeof light.style>
} { } {
const {theme} = React.useContext(Context) const {theme} = React.useContext(Context)
const breakpoints = useBreakpoints() const breakpoints = useBreakpoints()
return React.useMemo(() => { return React.useMemo(() => {
return Object.entries(styles).reduce((acc, [key, style]) => { return Object.entries(styles).reduce((acc, [key, style]) => {
const responsiveStyles = theme.pick(style).styles
acc[key as keyof O] = theme.style( acc[key as keyof O] = theme.style(
theme.applyBreakpoints(style, breakpoints.active), theme.applyBreakpoints(responsiveStyles, breakpoints.active),
) )
return acc return acc
}, {} as {[Name in keyof O]: ReturnType<typeof light.style>}) }, {} as {[Name in keyof O]: ReturnType<typeof light.style>})
@@ -98,24 +93,27 @@ export function useMultiStyle<
}, [styles, breakpoints.current, theme]) }, [styles, breakpoints.current, theme])
} }
export const Box = React.forwardRef<View, Props<ViewProps>>(function BoxThemed( export const Box = React.forwardRef<View, ComponentProps<ViewProps>>(
{children, style, ...props}, function BoxThemed({children, style, ...props}, ref) {
ref, const {styles: pickedStyles, props: rest} = usePick<ViewProps>(props)
) { const styles = useStyle(pickedStyles)
const {styles, props: rest} = useStyles<ViewProps>(props) if (props.debug) console.log({styles: pickedStyles, props: rest})
return ( return (
<View {...rest} style={[styles, style]} ref={ref}> <View {...rest} style={[styles, style]} ref={ref}>
{children} {children}
</View> </View>
) )
}) },
)
export const Text = React.forwardRef<RNText, Props<TextProps>>( export const Text = React.forwardRef<RNText, ComponentProps<TextProps>>(
function TextThemed({children, style, ...props}, ref) { function TextThemed({children, style, ...props}, ref) {
const {styles, props: rest} = useStyles<TextProps>({ const {styles: pickedStyles, props: rest} = usePick<TextProps>(props)
const styles = useStyle({
color: 'text', color: 'text',
...props, ...pickedStyles,
}) })
if (props.debug) console.log({styles, props: rest})
return ( return (
<RNText {...rest} style={[styles, style]} ref={ref}> <RNText {...rest} style={[styles, style]} ref={ref}>
{children} {children}
@@ -134,7 +132,7 @@ const asToAriaLevel = {
} }
const asToTypeStyles: { const asToTypeStyles: {
[key in HeadingElements]: Props [key in HeadingElements]: ComponentProps
} = { } = {
h1: { h1: {
fontSize: 'l', fontSize: 'l',
@@ -190,10 +188,12 @@ function createHeadingComponent(element: HeadingElements) {
}, },
default: {}, default: {},
}) })
const {styles, props: rest} = useStyles({ const {styles: pickedStyles, props: rest} = usePick<TextProps>(props)
const styles = useStyle({
color: 'text', color: 'text',
...merge(asToTypeStyles[asEl], props), ...merge(asToTypeStyles[asEl], pickedStyles),
}) })
if (props.debug) console.debug({styles, props: rest})
return ( return (
<RNText <RNText
+10 -9
View File
@@ -81,7 +81,7 @@ type Styles<T extends Tokens, P extends Properties, C extends Macros<T>> = {
type ResponsiveStyles< type ResponsiveStyles<
B extends Breakpoints, B extends Breakpoints,
S extends Styles<any, any, any>, S extends Styles<any, any, any>,
> = { > = S & {
[Breakpoint in keyof B]?: S [Breakpoint in keyof B]?: S
} }
@@ -279,10 +279,10 @@ export const create = <
type InnerResponsiveStyles = ResponsiveStyles<typeof breakpoints, InnerStyles> type InnerResponsiveStyles = ResponsiveStyles<typeof breakpoints, InnerStyles>
function pick<Props = Partial<ViewProps & TextProps & ImageProps>>( function pick<Props = Partial<ViewProps & TextProps & ImageProps>>(
props: InnerStyles & InnerResponsiveStyles & Props, props: InnerResponsiveStyles & Props,
) { ) {
const res = {styles: {default: {}}, props: {}} as { const res = {styles: {}, props: {}} as {
styles: InnerResponsiveStyles & {default: InnerStyles} styles: InnerResponsiveStyles
props: Props props: Props
} }
@@ -291,7 +291,7 @@ export const create = <
if (value === undefined) continue if (value === undefined) continue
if (allPropertyKeys.includes(prop)) { if (allPropertyKeys.includes(prop)) {
// @ts-ignore no index sig, it's fine // @ts-ignore no index sig, it's fine
res.styles.default[prop] = value res.styles[prop] = value
} else if (keyofBreakpoints.includes(prop)) { } else if (keyofBreakpoints.includes(prop)) {
// @ts-ignore no index sig, it's fine // @ts-ignore no index sig, it's fine
res.styles[prop] = value res.styles[prop] = value
@@ -342,19 +342,20 @@ export const create = <
function applyBreakpoints( function applyBreakpoints(
styles: InnerResponsiveStyles, styles: InnerResponsiveStyles,
bp: (keyof typeof breakpoints | 'default')[], bp: (keyof typeof breakpoints)[],
) { ) {
let s = styles.default as InnerStyles let s = styles
for (const breakpoint of bp) { for (const breakpoint of bp) {
s = {...s, ...styles[breakpoint]} const o = styles[breakpoint] || {}
s = {...s, ...o}
} }
return s return s
} }
function getActiveBreakpoints({width}: {width: number}) { function getActiveBreakpoints({width}: {width: number}) {
const active: (keyof typeof breakpoints | 'default')[] = ['default'] const active: (keyof typeof breakpoints)[] = []
for (const breakpoint in breakpoints) { for (const breakpoint in breakpoints) {
if (width >= breakpoints[breakpoint]) { if (width >= breakpoints[breakpoint]) {
+2 -2
View File
@@ -12,8 +12,8 @@ export const DesignSystemScreen = withAuthRequired(
observer(function DesignSystem({}: Props) { observer(function DesignSystem({}: Props) {
return ( return (
<ThemeProvider theme={themes.dark}> <ThemeProvider theme={themes.dark}>
<Box pa="m" gtPhone={{padding: 'l'}}> <Box pa="m" gtPhone={{padding: 'l'}} debug>
<H2 as="h1" c="theme" gtPhone={{mb: 'm', marginTop: 'l'}} debug> <H2 as="h1" c="theme" gtPhone={{mb: 'm', marginTop: 'l'}}>
Heading 1 Heading 1
</H2> </H2>
<H1 as="h2" c="theme" style={{color: 'tomato'}}> <H1 as="h2" c="theme" style={{color: 'tomato'}}>