diff --git a/.eslintrc.js b/.eslintrc.js index 17a1449e2..47cb5d00f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -57,7 +57,15 @@ module.exports = { parser: '@typescript-eslint/parser', rules: { 'prettier/prettier': [2, {...prettierConfig, parser: 'typescript'}], - '@typescript-eslint/no-unused-vars': [1, {argsIgnorePattern: '^_'}], + '@typescript-eslint/no-unused-vars': [ + 1, + { + ignoreRestSiblings: true, + varsIgnorePattern: '^_', + argsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', + }, + ], }, }, ], diff --git a/src/ui/components/Tab.js b/src/ui/components/Tab.tsx similarity index 71% rename from src/ui/components/Tab.js rename to src/ui/components/Tab.tsx index d374f16e1..e48685bad 100644 --- a/src/ui/components/Tab.js +++ b/src/ui/components/Tab.tsx @@ -5,34 +5,39 @@ * @format */ -export default function Tab(props: {| +import {WidthProperty} from 'csstype'; + +export type Props = { /** * Label of this tab to show in the tab list. */ - label: React$Node, + label: React.ReactNode; /** * Whether this tab is closable. */ - closable?: boolean, + closable?: boolean; /** * Whether this tab is hidden. Useful for when you want a tab to be * inaccessible via the user but you want to manually set the `active` props * yourself. */ - hidden?: boolean, + hidden?: boolean; /** * Whether this tab should always be included in the DOM and have its * visibility toggled. */ - persist?: boolean, + persist?: boolean; /** * Callback for when tab is closed. */ - onClose?: () => void, + onClose?: () => void; /** * Contents of this tab. */ - children?: React$Node, -|}) { + children?: React.ReactNode; + width?: WidthProperty; +}; + +export default function Tab(_props: Props) { throw new Error("don't render me"); } diff --git a/src/ui/components/Tabs.js b/src/ui/components/Tabs.tsx similarity index 76% rename from src/ui/components/Tabs.js rename to src/ui/components/Tabs.tsx index 00a13c263..44e2ea113 100644 --- a/src/ui/components/Tabs.js +++ b/src/ui/components/Tabs.tsx @@ -6,35 +6,39 @@ */ import FlexColumn from './FlexColumn.js'; -import styled from '../styled/index.js'; -import Orderable from './Orderable.tsx'; +import styled from 'react-emotion'; +import Orderable from './Orderable'; import FlexRow from './FlexRow.js'; -import {colors} from './colors.tsx'; -import Tab from './Tab.js'; +import {colors} from './colors'; +import Tab, {Props as TabProps} from './Tab'; +import {WidthProperty} from 'csstype'; +import React from 'react'; const TabList = styled(FlexRow)({ alignItems: 'stretch', }); -const TabListItem = styled('div')(props => ({ - backgroundColor: props.active ? colors.light15 : colors.light02, - borderBottom: '1px solid #dddfe2', - boxShadow: props.active ? 'inset 0px 0px 3px rgba(0,0,0,0.25)' : 'none', - color: colors.dark80, - flex: 1, - fontSize: 13, - lineHeight: '28px', - overflow: 'hidden', - padding: '0 10px', - position: 'relative', - textAlign: 'center', - textOverflow: 'ellipsis', - whiteSpace: 'nowrap', +const TabListItem = styled('div')( + (props: {active?: boolean; width?: WidthProperty}) => ({ + backgroundColor: props.active ? colors.light15 : colors.light02, + borderBottom: '1px solid #dddfe2', + boxShadow: props.active ? 'inset 0px 0px 3px rgba(0,0,0,0.25)' : 'none', + color: colors.dark80, + flex: 1, + fontSize: 13, + lineHeight: '28px', + overflow: 'hidden', + padding: '0 10px', + position: 'relative', + textAlign: 'center', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', - '&:hover': { - backgroundColor: props.active ? colors.light15 : colors.light05, - }, -})); + '&:hover': { + backgroundColor: props.active ? colors.light15 : colors.light05, + }, + }), +); const TabListAddItem = styled(TabListItem)({ borderRight: 'none', @@ -75,59 +79,59 @@ const TabContent = styled('div')({ /** * A Tabs component. */ -export default function Tabs(props: {| +export default function Tabs(props: { /** * Callback for when the active tab has changed. */ - onActive?: (key: ?string) => void, + onActive?: (key: string | null | undefined) => void; /** * The key of the default active tab. */ - defaultActive?: string, + defaultActive?: string; /** * The key of the currently active tab. */ - active?: ?string, + active?: string | null | undefined; /** * Tab elements. */ - children?: Array>, + children?: React.ReactElement[] | React.ReactElement; /** * Whether the tabs can be reordered by the user. */ - orderable?: boolean, + orderable?: boolean; /** * Callback when the tab order changes. */ - onOrder?: (order: Array) => void, + onOrder?: (order: Array) => void; /** * Order of tabs. */ - order?: Array, + order?: Array; /** * Whether to include the contents of every tab in the DOM and just toggle * its visibility. */ - persist?: boolean, + persist?: boolean; /** * Whether to include a button to create additional items. */ - newable?: boolean, + newable?: boolean; /** * Callback for when the new button is clicked. */ - onNew?: () => void, + onNew?: () => void; /** * Elements to insert before all tabs in the tab list. */ - before?: Array, + before?: Array; /** * Elements to insert after all tabs in the tab list. */ - after?: Array, -|}) { + after?: Array; +}) { const {onActive} = props; - const active: ?string = + const active: string | undefined = props.active == null ? props.defaultActive : props.active; // array of other components that aren't tabs @@ -143,8 +147,9 @@ export default function Tabs(props: {| const tabContents = []; const tabSiblings = []; - function add(comps) { - for (const comp of [].concat(comps || [])) { + function add(comps: React.ReactElement | React.ReactElement[]) { + const compsArray: React.ReactElement[] = [].concat(comps || []); + for (const comp of compsArray) { if (Array.isArray(comp)) { add(comp); continue; @@ -194,7 +199,7 @@ export default function Tabs(props: {| onMouseDown={ !isActive && onActive && - ((event: SyntheticMouseEvent<>) => { + ((event: React.MouseEvent) => { if (event.target !== closeButton) { onActive(key); } diff --git a/src/ui/index.js b/src/ui/index.js index 4991576a8..676025013 100644 --- a/src/ui/index.js +++ b/src/ui/index.js @@ -67,8 +67,8 @@ export { } from './components/data-inspector/DataDescription.js'; // tabs -export {default as Tabs} from './components/Tabs.js'; -export {default as Tab} from './components/Tab.js'; +export {default as Tabs} from './components/Tabs.tsx'; +export {default as Tab} from './components/Tab.tsx'; // inputs export {default as Input} from './components/Input.js';