Skip to content

Commit

Permalink
feat: add experimental useStaticStyling internal
Browse files Browse the repository at this point in the history
  • Loading branch information
kripod committed Apr 19, 2020
1 parent c363cf3 commit 4f095f6
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 9 deletions.
17 changes: 8 additions & 9 deletions packages/glaze/src/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@ import { ThemeOrAny } from 'treat/theme';

import { modularScale, symmetricScale } from './scales';

export type Tokens<T extends keyof ThemeOrAny> = Extract<
keyof ThemeOrAny[T],
string | number
>;

export interface ScaleTokens<T extends keyof CSSProperties> {
[key: string]: NonNullable<CSSProperties[T]>;
}

export interface CommonTheme {
breakpoints: readonly number[];
shorthands: { [key: string]: ReadonlyArray<keyof CSSProperties> };
aliases: {
[key: string]:
| keyof CSSProperties
| Extract<keyof ThemeOrAny['shorthands'], string>;
};
aliases: { [key: string]: keyof CSSProperties | Tokens<'shorthands'> };
}

export interface RuntimeTheme extends CommonTheme {
Expand All @@ -41,9 +42,7 @@ export interface StaticTheme extends CommonTheme {
duration: ScaleTokens<'animationDuration'>;
};
matchers: {
[property in keyof CSSProperties]:
| keyof this['scales']
| keyof ThemeOrAny['scales'];
[property in keyof CSSProperties]: keyof this['scales'] | Tokens<'scales'>;
};
}

Expand Down Expand Up @@ -213,7 +212,7 @@ export const defaultTokens = {
paddingTop: 'spacing',
paddingRight: 'spacing',
paddingBottom: 'spacing',
paddingLeft: 'spacing',
// paddingLeft: 'spacing',

margin: 'spacing',
// TODO: marginInline: 'spacing',
Expand Down
14 changes: 14 additions & 0 deletions packages/glaze/src/useStaticStyling.treat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ClassRef, Style, styleMap } from 'treat';

export default styleMap((theme) => {
const styles: { [className in ClassRef]: Style } = {};

Object.entries(theme.matchers).forEach(([property, scale]) => {
const tokens = Object.entries(theme.scales[scale]);
tokens.forEach(([key, value]) => {
styles[`${property}-${key}`] = { [property]: value };
});
});

return styles;
});
63 changes: 63 additions & 0 deletions packages/glaze/src/useStaticStyling.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/* Prefer performance over elegance, as this code is critical for the runtime */

import { CSSProperties } from 'react';
import { useStyles } from 'react-treat';
import { ThemeOrAny } from 'treat/theme';
import { ValueOf } from 'type-fest';

import { Tokens } from './theme';
import { useTheme } from './ThemeContext';
import styleRefs from './useStaticStyling.treat';

type ResolveShorthand<T extends Tokens<'shorthands'>> = ValueOf<
ThemeOrAny['shorthands'][T],
number
>;

type ResolveAlias<
T extends Tokens<'aliases'>
> = ThemeOrAny['aliases'][T] extends Tokens<'shorthands'>
? ResolveShorthand<ThemeOrAny['aliases'][T]>
: ThemeOrAny['aliases'][T];

type ScaleKeys<Property> = Extract<
keyof ThemeOrAny['scales'][ThemeOrAny['matchers'][Extract<
Property,
Tokens<'matchers'>
>]],
ValueOf<CSSProperties>
>;

export type ThemedStyle = { [key in Tokens<'matchers'>]?: ScaleKeys<key> } &
{ [key in Tokens<'shorthands'>]?: ScaleKeys<ResolveShorthand<key>> } &
{ [key in Tokens<'aliases'>]?: ScaleKeys<ResolveAlias<key>> };

export function useStaticStyling(): (themedStyle: ThemedStyle) => string {
const styles = useStyles(styleRefs);
const theme = useTheme();

return function sx(themedStyle: ThemedStyle): string {
let className = '';

// eslint-disable-next-line guard-for-in, no-restricted-syntax
for (const alias in themedStyle) {
// TODO: Remove type assertion if possible
const value = themedStyle[alias as keyof ThemedStyle];
const shorthand = theme.aliases[alias] || alias;

// eslint-disable-next-line no-loop-func
(theme.shorthands[shorthand] || [shorthand]).forEach((key) => {
// TODO: Support selectors and media queries
if (typeof value !== 'object') {
const identName = `${key}-${value}`;
const appendedClassName = styles[identName];

className += ` ${appendedClassName}`;
}
});
}

// Remove prepended whitespace
return className.slice(1);
};
}

0 comments on commit 4f095f6

Please sign in to comment.