Skip to content

Commit

Permalink
Migrate @emotion/css to TypeScript (#2558)
Browse files Browse the repository at this point in the history
  • Loading branch information
emmatown authored Nov 23, 2021
1 parent da3f244 commit 85772c3
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 139 deletions.
5 changes: 5 additions & 0 deletions .changeset/eighty-spies-beam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@emotion/css': minor
---

Source code has been migrated to TypeScript. From now on type declarations will be emitted based on that, instead of being hand-written.
5 changes: 5 additions & 0 deletions .changeset/modern-tomatoes-work.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@emotion/css': patch
---

Fixed `options` parameter to `createEmotion` from `@emotion/css/create-instance` incorrectly being marked as optional when it's required.
2 changes: 1 addition & 1 deletion packages/css/create-instance/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"main": "dist/emotion-css-create-instance.cjs.js",
"module": "dist/emotion-css-create-instance.esm.js",
"umd:main": "dist/emotion-css-create-instance.umd.min.js",
"types": "../types/create-instance",
"types": "dist/emotion-css-create-instance.cjs.d.ts",
"preconstruct": {
"umdName": "createEmotion"
}
Expand Down
6 changes: 3 additions & 3 deletions packages/css/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "The Next Generation of CSS-in-JS.",
"main": "dist/emotion-css.cjs.js",
"module": "dist/emotion-css.esm.js",
"types": "types/index.d.ts",
"types": "dist/emotion-css.cjs.d.ts",
"files": [
"src",
"dist",
Expand Down Expand Up @@ -53,8 +53,8 @@
"preconstruct": {
"umdName": "emotion",
"entrypoints": [
"./index.js",
"./create-instance.js"
"./index.ts",
"./create-instance.ts"
]
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,80 @@
import createCache from '@emotion/cache'
import { serializeStyles } from '@emotion/serialize'
import {
serializeStyles,
CSSInterpolation,
Interpolation
} from '@emotion/serialize'
import {
insertStyles,
getRegisteredStyles
/* type EmotionCache, */
/* type SerializedStyles */
getRegisteredStyles,
SerializedStyles,
RegisteredCache
} from '@emotion/utils'
import { EmotionCache, Options } from '@emotion/cache'
import { StyleSheet } from '@emotion/sheet'

export type {
CSSInterpolation,
ArrayCSSInterpolation,
ComponentSelector,
CSSObject
} from '@emotion/serialize'

function insertWithoutScoping(cache, serialized /*: SerializedStyles */) {
function insertWithoutScoping(
cache: EmotionCache,
serialized: SerializedStyles
) {
if (cache.inserted[serialized.name] === undefined) {
return cache.insert('', serialized, cache.sheet, true)
}
}

export type { EmotionCache, Options }

export interface ArrayClassNamesArg extends Array<ClassNamesArg> {}
export type ClassNamesArg =
| undefined
| null
| string
| boolean
| { [className: string]: boolean | null | undefined }
| ArrayClassNamesArg

export interface CSSStyleSheet extends StyleSheet {
speedy(value: boolean): void
}

export interface Emotion {
css(template: TemplateStringsArray, ...args: Array<CSSInterpolation>): string
css(...args: Array<CSSInterpolation>): string
cx(...classNames: Array<ClassNamesArg>): string
flush(): void
hydrate(ids: Array<string>): void
injectGlobal(
template: TemplateStringsArray,
...args: Array<CSSInterpolation>
): void
injectGlobal(...args: Array<CSSInterpolation>): void
keyframes(
template: TemplateStringsArray,
...args: Array<CSSInterpolation>
): string
keyframes(...args: Array<CSSInterpolation>): string
sheet: CSSStyleSheet
cache: EmotionCache
merge(className: string): string
getRegisteredStyles(
registeredStyles: Array<string>,
className: string
): string
}

function merge(
registered /*: Object */,
css /*: (*) => string */,
className /*: string */
registered: RegisteredCache,
css: Emotion['css'],
className: string
) {
const registeredStyles = []
const registeredStyles: string[] = []
const rawClassName = getRegisteredStyles(
registered,
registeredStyles,
Expand All @@ -31,61 +87,29 @@ function merge(
return rawClassName + css(registeredStyles)
}

/*
export type Interpolation = any
export type Interpolations = Array<Interpolation>
type CreateStyles<ReturnValue> = (...args: Interpolations) => ReturnValue
type ClassNameArg =
| string
| boolean
| { [key: string]: boolean | void | null }
| Array<ClassNameArg>
| void
| null
declare class StyleSheet {
insert(rule: string): void;
flush(): void;
speedy(newVal: boolean): void;
tags: Array<HTMLStyleElement>;
isSpeedy: number;
ctr: number;
}
export type Emotion = {
css: CreateStyles<string>,
cx: (...classNames: Array<ClassNameArg>) => string,
flush: () => void,
hydrate: (ids: Array<string>) => void,
injectGlobal: CreateStyles<void>,
keyframes: CreateStyles<string>,
sheet: StyleSheet,
cache: EmotionCache,
merge,
getRegisteredStyles
}
*/

let createEmotion = (options) /*: Emotion */ => {
let createEmotion = (options: Options): Emotion => {
let cache = createCache(options)

cache.sheet.speedy = function (value /*: boolean */) {
;(cache.sheet as CSSStyleSheet).speedy = function (value: boolean) {
if (process.env.NODE_ENV !== 'production' && this.ctr !== 0) {
throw new Error('speedy must be changed before any rules are inserted')
}
this.isSpeedy = value
}

cache.compat = true

let css = (...args) => {
let css: Emotion['css'] = (
...args: (TemplateStringsArray | Interpolation<unknown>)[]
) => {
let serialized = serializeStyles(args, cache.registered, undefined)
insertStyles(cache, serialized, false)
return `${cache.key}-${serialized.name}`
}

let keyframes = (...args) => {
let keyframes: Emotion['keyframes'] = (
...args: (TemplateStringsArray | Interpolation<unknown>)[]
) => {
let serialized = serializeStyles(args, cache.registered)
let animation = `animation-${serialized.name}`
insertWithoutScoping(cache, {
Expand All @@ -95,20 +119,22 @@ let createEmotion = (options) /*: Emotion */ => {

return animation
}
let injectGlobal = (...args) => {
let injectGlobal: Emotion['injectGlobal'] = (
...args: (TemplateStringsArray | Interpolation<unknown>)[]
) => {
let serialized = serializeStyles(args, cache.registered)
insertWithoutScoping(cache, serialized)
}

let cx = (...args) => {
let cx: Emotion['cx'] = (...args) => {
return merge(cache.registered, css, classnames(args))
}
return {
css,
cx,
injectGlobal,
keyframes,
hydrate(ids /*: Array<string> */) {
hydrate(ids) {
ids.forEach(key => {
cache.inserted[key] = true
})
Expand All @@ -118,14 +144,14 @@ let createEmotion = (options) /*: Emotion */ => {
cache.inserted = {}
cache.sheet.flush()
},
sheet: cache.sheet,
sheet: cache.sheet as CSSStyleSheet,
cache,
getRegisteredStyles: getRegisteredStyles.bind(null, cache.registered),
merge: merge.bind(null, cache.registered, css)
}
}

let classnames = args => {
let classnames = (args: ClassNamesArg[]) => {
let cls = ''
for (let i = 0; i < args.length; i++) {
let arg = args[i]
Expand Down
File renamed without changes.
55 changes: 2 additions & 53 deletions packages/css/types/create-instance.d.ts
Original file line number Diff line number Diff line change
@@ -1,55 +1,4 @@
// Definitions by: Junyoung Clare Jang <https://github.com/Ailrun>
// TypeScript Version: 2.8

import { EmotionCache, Options } from '@emotion/cache'
import { CSSInterpolation } from '@emotion/serialize'
import { StyleSheet } from '@emotion/sheet'

export {
CSSInterpolation,
ArrayCSSInterpolation,
ComponentSelector,
CSSObject
} from '@emotion/serialize'

export { EmotionCache, Options }

export interface ArrayClassNamesArg extends Array<ClassNamesArg> {}
export type ClassNamesArg =
| undefined
| null
| string
| boolean
| { [className: string]: boolean | null | undefined }
| ArrayClassNamesArg

export interface CSSStyleSheet extends StyleSheet {
speedy(value: boolean): void
}

export interface Emotion {
css(template: TemplateStringsArray, ...args: Array<CSSInterpolation>): string
css(...args: Array<CSSInterpolation>): string
cx(...classNames: Array<ClassNamesArg>): string
flush(): void
hydrate(ids: Array<string>): void
injectGlobal(
template: TemplateStringsArray,
...args: Array<CSSInterpolation>
): void
injectGlobal(...args: Array<CSSInterpolation>): void
keyframes(
template: TemplateStringsArray,
...args: Array<CSSInterpolation>
): string
keyframes(...args: Array<CSSInterpolation>): string
sheet: CSSStyleSheet
cache: EmotionCache
merge(className: string): string
getRegisteredStyles(
registeredStyles: Array<string>,
className: string
): string
}

export default function createEmotion(options?: Options): Emotion
export * from '../create-instance'
export { default } from '../create-instance'
27 changes: 1 addition & 26 deletions packages/css/types/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1 @@
// Definitions by: Junyoung Clare Jang <https://github.com/Ailrun>
// TypeScript Version: 2.8

import { Emotion } from './create-instance'

export {
ArrayClassNamesArg,
ArrayCSSInterpolation,
ClassNamesArg,
ComponentSelector,
EmotionCache,
CSSInterpolation,
CSSObject,
CSSStyleSheet
} from './create-instance'

export const flush: Emotion['flush']
export const hydrate: Emotion['hydrate']
export const cx: Emotion['cx']
export const merge: Emotion['merge']
export const getRegisteredStyles: Emotion['getRegisteredStyles']
export const css: Emotion['css']
export const injectGlobal: Emotion['injectGlobal']
export const keyframes: Emotion['keyframes']
export const sheet: Emotion['sheet']
export const cache: Emotion['cache']
export * from '..'
2 changes: 1 addition & 1 deletion packages/css/types/tests-create-instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const emotion0 = createEmotion({ key: 'bar' })
// $ExpectType Emotion
const emotion1 = createEmotion({
key: 'foo',
container: document.head,
container: document.head!,
nonce: 'fasefw'
})

Expand Down

0 comments on commit 85772c3

Please sign in to comment.