diff --git a/package.json b/package.json index 9bf62b3..2f65a60 100644 --- a/package.json +++ b/package.json @@ -10,12 +10,14 @@ "main": "dist/vue-emotion.cjs.js", "cdn": "dist/vue-emotion.min.js", "unpkg": "dist/vue-emotion.min.js", + "types": "types/index.d.ts", "files": [ "dist" ], "scripts": { - "test": "npm run lint && echo 'no tests!'", + "test": "npm run lint && npm run dtslint && echo 'no tests!'", "lint": "xo", + "dtslint": "dtslint types", "prepublishOnly": "npm run build", "build": "bili --format umd,cjs,es,umd-min --module-name emotionVue", "example": "poi", @@ -27,6 +29,7 @@ "devDependencies": { "babel-plugin-emotion": "^9.1.0", "bili": "^3.0.13", + "dtslint": "^0.3.0", "emotion": "^9.1.0", "eslint-config-rem": "^3.0.0", "markdown-toc": "^1.1.0", @@ -48,6 +51,7 @@ }, "dependencies": { "emotion-utils": "^9.1.0", - "nano-assign": "^1.0.0" + "nano-assign": "^1.0.0", + "vue-tsx-support": "^1.2.0" } } diff --git a/src/index.js b/src/index.js index abfbd40..e880bf9 100644 --- a/src/index.js +++ b/src/index.js @@ -7,9 +7,8 @@ function stringifyClass(klass) { return klass.join(' ') } if (typeof klass === 'object') { - return Object.keys(klass) - .filter(key => Boolean(klass[key])) - .join(' ') + // prettier-ignore + return Object.keys(klass).filter(key => Boolean(klass[key])).join(' ') } return klass } diff --git a/types/index.d.ts b/types/index.d.ts new file mode 100644 index 0000000..d3025b3 --- /dev/null +++ b/types/index.d.ts @@ -0,0 +1,103 @@ +// TypeScript Version: 2.3 +// tslint:disable-next-line:no-implicit-dependencies +import Vue from 'vue' +import { TsxComponent } from 'vue-tsx-support/lib/api' +import { Interpolation as EmotionInterpolation } from 'emotion' + +export * from 'emotion' + +export type InterpolationFn = ( + props: Props +) => EmotionInterpolation | InterpolationFn + +export type InterpolationTypes = + | InterpolationFn + | EmotionInterpolation + +export type Interpolation = + | InterpolationTypes + | Array> + +export interface Options { + string?: string +} + +type ElementProps< + Tag extends keyof JSX.IntrinsicElements +> = JSX.IntrinsicElements[Tag] + +export interface StyledComponent + extends TsxComponent { + withComponent( + tag: Tag + ): StyledComponent> + + withComponent(component: any): StyledComponent + + displayName: string + __emotion_styles: string[] + __emotion_base: string | {} + __emotion_real: ThemedVueEmotionInterface +} + +export type ObjectStyleAttributes = + | object + | object[] + | { [key: string]: ObjectStyleAttributes } + +export interface CreateStyled { + // overload for template string as styles + ( + strings: TemplateStringsArray, + ...vars: Array> + ): StyledComponent + + // overload for object as styles + ( + ...styles: Array< + | ObjectStyleAttributes + | ((props: Props & IntrinsicProps) => ObjectStyleAttributes) + > + ): StyledComponent +} + +type ShorthandsFactories = { + [Tag in keyof JSX.IntrinsicElements]: { + // overload for template string as styles + ( + strings: TemplateStringsArray, + ...vars: Array> + ): StyledComponent> + + // overload for object as styles + ( + ...styles: Array< + | ObjectStyleAttributes + | ((props: Props & JSX.IntrinsicElements[Tag]) => ObjectStyleAttributes) + > + ): StyledComponent> + } +} + +export interface ThemedVueEmotionInterface extends ShorthandsFactories { + // overload for dom tag + ( + tag: Tag, + options?: Options + ): // tslint:disable-next-line:no-unnecessary-generics + CreateStyled> + + // overload for component + ( + component: any, + options?: Options + ): // tslint:disable-next-line:no-unnecessary-generics + CreateStyled +} + +export interface ThemedVueEmotionModule { + default: ThemedVueEmotionInterface +} + +declare const styled: ThemedVueEmotionInterface +export default styled diff --git a/types/test.tsx b/types/test.tsx new file mode 100644 index 0000000..875da0e --- /dev/null +++ b/types/test.tsx @@ -0,0 +1,83 @@ +import styled, { flush, ThemedVueEmotionInterface } from './' + +let Component +let mount + +/* + * Inference HTML Tag Props + */ +Component = styled.div({ color: 'red' }) +mount = event} /> + +Component = styled('div')({ color: 'red' }) +mount = event} /> + +Component = styled.div` + color: red; +` +mount = event} /> + +Component = styled('div')` + color: red; +` +mount = event} /> + +Component = styled.a({ color: 'red' }) +mount = + +Component = styled('a')({ color: 'red' }) +mount = + +/* + * Passing custom props + */ +interface CustomProps { + lookColor: string +} + +Component = styled.div( + { color: 'blue' }, + props => ({ + background: props.lookColor + }), + props => ({ + border: `1px solid ${props.lookColor}` + }) +) +mount = + +Component = styled('div')({ color: 'blue' }, props => ({ + background: props.lookColor +})) +mount = + +const anotherColor = 'blue' +Component = styled('div')` + background: ${props => props.lookColor}; + color: ${anotherColor}; +` +mount = + +/* + * withComponent + */ + +interface CustomProps3 { + bgColor: string +} + +Component = styled.div(props => ({ + bgColor: props.bgColor +})) + +const Link = Component.withComponent('a') +mount = + +const Button = Component.withComponent('button') +mount =