Skip to content
Open
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
15 changes: 0 additions & 15 deletions src/styleSheet.ts

This file was deleted.

3 changes: 3 additions & 0 deletions src/styleSheet/EnhancedCSSProperties/CSSProperties.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import * as CSS from 'csstype';

export type CSSProperties = CSS.PropertiesFallback<number | string>;
31 changes: 31 additions & 0 deletions src/styleSheet/EnhancedCSSProperties/EnhancedCSSObject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as CSS from 'csstype';
import { CSSProperties } from './CSSProperties';
import { toCSSProperty, EnhancedCSSProperties } from './EnhancedCSSProperties';

type CSSPseudos<P> = { [K in CSS.Pseudos]?: CSSObject<P> };

interface CSSOthersObject<P> {
[propertiesName: string]: CSSObject<P>;
}

export type CSSObject<P> = (P & CSSPseudos<P>) | CSSOthersObject<P>;

export type EnhancedCSSObject = CSSObject<EnhancedCSSProperties>;

export function toCSSObject(
cssObject: EnhancedCSSObject,
): CSSObject<CSSProperties> {
const result: any = {};

Object.entries(cssObject).forEach(([key, value]) => {
let cleanValue = toCSSProperty(key, value);

if (typeof cleanValue === 'object') {
cleanValue = toCSSObject(cleanValue);
}

result[key] = cleanValue;
});

return result;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { CSSProperties } from '../CSSProperties';
import { enhancers, Enhancers } from './enhancers';

export type EnhancedCSSProperties = {
[K in keyof CSSProperties]: K extends keyof Enhancers
? Parameters<Enhancers[K]>[0]
: CSSProperties[K];
};

export function toCSSProperty(property: string, value: any) {
if (property in enhancers) {
return enhancers[property as keyof Enhancers](value);
}

return value;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
type AreaValue = number | string | 'auto';

type AreaOptions =
| { vertical: AreaValue; horizontal: AreaValue }
| { top: AreaValue; horizontal: AreaValue; bottom: AreaValue }
| { top: AreaValue; right: AreaValue; bottom: AreaValue; left: AreaValue }
| [top: AreaValue, right: AreaValue, bottom: AreaValue, left: AreaValue]
| [top: AreaValue, horizontal: AreaValue, bottom: AreaValue]
| [vertical: AreaValue, horizontal: AreaValue]
| AreaValue;

function getAreaFromValue(value: AreaOptions): AreaValue[] {
if (Array.isArray(value)) {
return value;
}

if (typeof value === 'number' || typeof value === 'string') {
return [value];
}

if ('left' in value) {
return [value.top, value.right, value.bottom, value.left];
}

if ('bottom' in value) {
return [value.top, value.horizontal, value.bottom];
}

return [value.vertical, value.horizontal];
}

export function area(value: AreaOptions): string {
return getAreaFromValue(value)
.map((area) => {
if (typeof area === 'number') {
return `${area}px`;
}

return area;
})
.join(' ');
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { GlobalValues } from '../../../../types';

type BackgroundRepeatValues =
| 'repeat-x'
| 'repeat-y'
| 'repeat'
| 'space'
| 'round'
| 'no-repeat';

type BackgroundAttachment = 'scroll' | 'fixed' | 'local' | GlobalValues;
type BackgroundClip =
| 'border-box'
| 'padding-box'
| 'content-box'
| 'text'
| GlobalValues;
type BackgroundColor = string | GlobalValues;
type BackgroundImage = string;
type BackgroundOrigin =
| 'border-box'
| 'padding-box'
| 'content-box'
| GlobalValues;
type BackgroundPosition = string | GlobalValues;
type BackgroundRepeat =
| BackgroundRepeatValues
| [BackgroundRepeatValues, BackgroundRepeatValues]
| GlobalValues;
type BackgroundSize = string | GlobalValues;

interface BackgroundWithoutSize {
attachment?: BackgroundAttachment;
clip?: BackgroundClip;
color?: BackgroundColor;
image?: BackgroundImage;
origin?: BackgroundOrigin;
position?: BackgroundSize;
repeat?: BackgroundRepeat;
}

type BackgroundWithSize = Omit<BackgroundWithoutSize, 'position'> & {
position: BackgroundPosition;
size?: BackgroundSize;
};

type BackgroundOptions = BackgroundWithoutSize | BackgroundWithSize;

function isBackgroundWithSize(
background: BackgroundOptions,
): background is BackgroundWithSize {
return 'size' in background;
}

function backgroundOptionsToString(options: BackgroundOptions): string {
let position;
if (isBackgroundWithSize(options) && options.size) {
position = `${options.position}/${options.size}`;
} else {
position = options.position;
}

return [
options.image,
position,
options.repeat,
options.origin,
options.clip,
options.attachment,
options.color,
]
.filter(Boolean)
.join(' ');
}

/**
* Note: Color can only be defined on the last background,
* https://developer.mozilla.org/en-US/docs/Web/CSS/background
* TODO: Implement this check by types in Typescript 4.2 (by [...options, lastOptions])
*/
export function background(
value: 'none' | BackgroundOptions | BackgroundOptions[],
): string {
if (value === 'none') {
return value;
}

if (Array.isArray(value)) {
return value.map(backgroundOptionsToString).join(', ');
}

return backgroundOptionsToString(value);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
type BorderOptions = {
width: number;
type?: string;
color: string;
};

export function border(value: 'none' | BorderOptions): string {
if (value === 'none') {
return value;
}

const { width, type = 'solid', color } = value;

return `${width}px ${type} ${color}`;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
interface BoxShadow {
inset?: boolean;
x: number;
y: number;
color: string;
blur?: never;
spread?: never;
}
interface BoxShadowWithBlur {
inset?: boolean;
x: number;
y: number;
color: string;
blur: number;
spread?: never;
}
interface BoxShadowWithSpread {
inset?: boolean;
x: number;
y: number;
color: string;
blur: number;
spread: number;
}

type BoxShadowOptions = BoxShadow | BoxShadowWithBlur | BoxShadowWithSpread;

function isBoxShadowWithBlur(shadowOption: BoxShadowOptions): shadowOption is BoxShadowWithSpread {
return 'blur' in shadowOption;
}

function isBoxShadowWithSpread(
shadowOption: BoxShadowOptions,
): shadowOption is BoxShadowWithSpread {
return 'blur' in shadowOption && 'spread' in shadowOption;
}

function boxShadowOptionsToString(options: BoxShadowOptions): string {
const { inset, x, y, color } = options;

let blur: number | undefined;
let spread: number | undefined;

if (isBoxShadowWithSpread(options)) {
({ blur, spread } = options);
} else if (isBoxShadowWithBlur(options)) {
({ blur } = options);
}

return [inset && 'inset', `${x}px`, `${y}px`, blur && `${blur}px`, spread && `${spread}px`, color]
.filter(Boolean)
.join(' ');
}

export function boxShadow(value: 'none' | BoxShadowOptions | BoxShadowOptions[]): string {
if (value === 'none') {
return value;
}


if (Array.isArray(value)) {
return value.map(boxShadowOptionsToString).join(', ');
}

return boxShadowOptionsToString(value);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { area } from './area';
import { background } from './background';
import { border } from './border';
import { boxShadow } from './boxShadow';
import { transition } from './transition';

export const enhancers = {
background,
border,
boxShadow,
margin: area,
padding: area,
transition,
};

export type Enhancers = typeof enhancers;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './enhancers';
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
interface TransitionOptions {
property: string;
duration: string;
timingFunction?: string;
delay?: string;
}

function transitionOptionsToString(options: TransitionOptions) {
const { property, duration, timingFunction, delay } = options;

return [property, duration, timingFunction, delay].filter(Boolean).join(' ');
}

export function transition(
value: 'none' | TransitionOptions | TransitionOptions[],
): string {
if (value === 'none') {
return value;
}

if (Array.isArray(value)) {
return value.map(options => transitionOptionsToString(options)).join(', ');
}

return transitionOptionsToString(value);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './EnhancedCSSProperties';
1 change: 1 addition & 0 deletions src/styleSheet/EnhancedCSSProperties/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './EnhancedCSSObject';
1 change: 1 addition & 0 deletions src/styleSheet/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './styleSheet';
22 changes: 22 additions & 0 deletions src/styleSheet/styleSheet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { SerializedStyles, css } from '@emotion/react';
import {
CSSObject,
toCSSObject,
EnhancedCSSObject,
} from './EnhancedCSSProperties';

type Styles = Record<string, CSSObject<EnhancedCSSObject>>;

type Result<S> = { [K in keyof S]: SerializedStyles };

export function styleSheet<S extends Styles>(styles: S): Result<S> {
const result = {} as Result<S>;

Object.entries(styles).forEach(([key, value]) => {
const cssObject: any = toCSSObject(value);

result[key as keyof Result<S>] = css(cssObject);
});

return result;
}