cleanup and better naming
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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]) {
|
||||||
|
|||||||
@@ -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'}}>
|
||||||
|
|||||||
Reference in New Issue
Block a user