From 033c6aa59aed9c7b3ef0435620ff7d63d7303aa6 Mon Sep 17 00:00:00 2001 From: Vu Tran Date: Fri, 18 Aug 2017 09:15:24 -0700 Subject: [PATCH] feat: add TS definitions (#56) * add TS definitions * Rename to Downshift * update with new API changes * update ts defintiions * fix pkg.json * import more typings * move ts test to validate --- other/TYPESCRIPT_USAGE.md | 5 ++ package-scripts.js | 3 +- package.json | 8 ++- test/basic.test.tsx | 75 +++++++++++++++++++++++++++ tsconfig.json | 5 ++ typings/index.d.ts | 103 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 other/TYPESCRIPT_USAGE.md create mode 100644 test/basic.test.tsx create mode 100644 tsconfig.json create mode 100644 typings/index.d.ts diff --git a/other/TYPESCRIPT_USAGE.md b/other/TYPESCRIPT_USAGE.md new file mode 100644 index 000000000..bf7f98270 --- /dev/null +++ b/other/TYPESCRIPT_USAGE.md @@ -0,0 +1,5 @@ +# Typescript Usage + +The current bundled Typescript definitions are incomplete and based around the needs of the developers who contributed them. + +Pull requests to improve them are welcome and appreciated. If you've never contributed to open source before, then you may find [this free video course](https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github) helpful. diff --git a/package-scripts.js b/package-scripts.js index b23e83d74..3b15bfced 100644 --- a/package-scripts.js +++ b/package-scripts.js @@ -22,6 +22,7 @@ module.exports = { test: { default: crossEnv('NODE_ENV=test jest --coverage'), update: crossEnv('NODE_ENV=test jest --coverage --updateSnapshot'), + ts: 'tsc --noEmit -p ./tsconfig.json', watch: crossEnv('NODE_ENV=test jest --watch'), build: { description: 'validates the built files', @@ -56,7 +57,7 @@ module.exports = { This runs several scripts to make sure things look good before committing or on clean install `, - script: concurrent.nps('lint', 'build.andTest', 'test'), + script: concurrent.nps('lint', 'build.andTest', 'test', 'test.ts'), }, }, options: { diff --git a/package.json b/package.json index ccd6304cf..5e2d6c398 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "main": "dist/downshift.cjs.js", "jsnext:main": "dist/downshift.es.js", "module": "dist/downshift.es.js", + "typings": "typings/index.d.ts", "scripts": { "start": "nps", "test": "nps test", @@ -12,7 +13,9 @@ "release": "npm publish && npm dist-tag add downshift@$npm_package_version rc", "precommit": "lint-staged && opt --in pre-commit --exec \"npm start validate\"" }, - "files": ["dist"], + "files": [ + "dist" + ], "keywords": [ "enhanced input", "react", @@ -72,7 +75,8 @@ "rollup-plugin-json": "^2.3.0", "rollup-plugin-node-resolve": "^3.0.0", "rollup-plugin-uglify": "^2.0.1", - "rollup-watch": "^4.3.1" + "rollup-watch": "^4.3.1", + "typescript": "^2.4.2" }, "lint-staged": { "*.js": [ diff --git a/test/basic.test.tsx b/test/basic.test.tsx new file mode 100644 index 000000000..05d6f1bb9 --- /dev/null +++ b/test/basic.test.tsx @@ -0,0 +1,75 @@ +import * as React from 'react'; +import Downshift, { ChangeOptions, ControllerStateAndHelpers } from '../'; + +interface Props {} + +interface State { + items: Array; +} + +export default class App extends React.Component { + state: State = { + items: ['apple', 'orange', 'carrot'], + }; + + onChange = ({ selectedItem, previousItem }: ChangeOptions) => { + console.log('selectedItem', selectedItem); + console.log('previousItem', previousItem); + }; + + render() { + const items = this.state.items; + + return ( + + {({ + getInputProps, + getItemProps, + isOpen, + inputValue, + selectedItem, + highlightedIndex, + }: ControllerStateAndHelpers) => +
+ + {isOpen + ?
+ {items + .filter( + (i: any) => + !inputValue || + i + .toLowerCase() + .includes( + inputValue.toLowerCase() + ) + ) + .map((item: any, index: number) => +
+ {item} +
+ )} +
+ : null} +
} +
+ ); + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..f06b6ff42 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "jsx": "react" + } +} \ No newline at end of file diff --git a/typings/index.d.ts b/typings/index.d.ts new file mode 100644 index 000000000..8a5437818 --- /dev/null +++ b/typings/index.d.ts @@ -0,0 +1,103 @@ +import * as React from 'react'; + +export interface DownshiftProps { + children: ChildrenFunction; + defaultHighlightedIndex?: number; + defaultSelectedItem?: any; + defaultInputValue?: string; + defaultIsOpen?: boolean; + getA11yStatusMessage?: (options: A11StatusMessageOptions) => any; + itemToString?: (item: any) => string; + onChange?: (options: ChangeOptions) => void; + onStateChange?: (options: StateChangeOptions) => void; + onClick?: Function; + selectedItem?: any; + isOpen?: boolean; + inputValue?: string; + highlightedIndex?: number; +} + +export interface A11StatusMessageOptions { + highlightedIndex: number; + highlightedValue: any; + inputValue: string; + isOpen: boolean; + itemToString: (item: any) => string; + previousResultCount: number; + resultCount: number; + selectedItem: any; +} + +export interface ChangeOptions { + selectedItem: any; + previousItem: any; +} + +export interface StateChangeOptions { + highlightedIndex: number; + inputValue: string; + isOpen: boolean; + selectedItem: any; +} + +export interface GetRootPropsOptions { + refKey: string; +} + +export interface GetInputPropsOptions extends React.HTMLProps { } + +export interface GetLabelPropsOptions extends React.HTMLProps { } + +export interface GetButtonPropsOptions extends React.HTMLProps { + // actions + clearSelection: () => void; + closeMenu: () => void; + openMenu: () => void; + selectHighlightedItem: () => void; + selectItem: (item: any) => void; + selectItemAtIndex: (index: number) => void; + setHighlightedIndex: (index: number) => void; + toggleMenu: (state: boolean) => void; + + // state + highlightedIndex: number; + inputValue: string; + isOpen: boolean; + selectedItem: any; +} + +export interface GetItemPropsOptions { + index: number; + item: any; +} + +export interface ControllerStateAndHelpers { + // prop getters + getRootProps: (options: GetRootPropsOptions) => any; + getButtonProps: (options: GetButtonPropsOptions) => any; + getLabelProps: (options: GetLabelPropsOptions) => any; + getInputProps: (options: GetInputPropsOptions) => any; + getItemProps: (options: GetItemPropsOptions) => any; + + // actions + openMenu: () => void; + closeMenu: () => void; + toggleMenu: () => void; + selectItem: (item: any) => void; + selectItemAtIndex: (index: number) => void; + selectHighlightedItem: (index: number) => void; + setHighlightedItem: (index: number) => void; + clearSelection: () => void; + + // state + highlightedIndex: number; + inputValue: string; + isOpen: boolean; + selectedItem: any; +} + +export type ChildrenFunction = (options: ControllerStateAndHelpers) => React.ReactNode; +export type DownshiftInterface = React.ComponentClass; + +declare const Downshift: DownshiftInterface; +export default Downshift; \ No newline at end of file