From fd0b348c15d34138bbd11209d74e12799a0042c5 Mon Sep 17 00:00:00 2001 From: Shingo Yamazaki Date: Sat, 18 May 2019 00:48:41 +0900 Subject: [PATCH 1/8] #289 AutoAlign: mv AutoAlign.js -> AutoAlign.tsx --- src/scripts/{AutoAlign.js => AutoAlign.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/scripts/{AutoAlign.js => AutoAlign.tsx} (100%) diff --git a/src/scripts/AutoAlign.js b/src/scripts/AutoAlign.tsx similarity index 100% rename from src/scripts/AutoAlign.js rename to src/scripts/AutoAlign.tsx From 7721e86cdf425d3088d06081ed2f6252b2399eae Mon Sep 17 00:00:00 2001 From: Shingo Yamazaki Date: Mon, 20 May 2019 23:29:47 +0900 Subject: [PATCH 2/8] #289 AutoAlign: Declare module for `react-relative-portal` --- tsconfig.json | 2 ++ types/react-relative-portal.d.ts | 1 + 2 files changed, 3 insertions(+) create mode 100644 types/react-relative-portal.d.ts diff --git a/tsconfig.json b/tsconfig.json index d91070509..5647e0991 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,7 @@ { "compilerOptions": { + "baseUrl": ".", + "paths": { "*": ["types/*"] }, /* Basic Options */ "target": "esnext", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ diff --git a/types/react-relative-portal.d.ts b/types/react-relative-portal.d.ts new file mode 100644 index 000000000..7423999ce --- /dev/null +++ b/types/react-relative-portal.d.ts @@ -0,0 +1 @@ +declare module 'react-relative-portal'; From 370c3901b5e4ee1e867675f49ebc54e7f5cff2f5 Mon Sep 17 00:00:00 2001 From: Shingo Yamazaki Date: Fri, 24 May 2019 01:24:58 +0900 Subject: [PATCH 3/8] #289 AutoAlign: Add types to arguments of functions --- src/scripts/AutoAlign.tsx | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/scripts/AutoAlign.tsx b/src/scripts/AutoAlign.tsx index 9885d26d4..e633854a9 100644 --- a/src/scripts/AutoAlign.tsx +++ b/src/scripts/AutoAlign.tsx @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import classnames from 'classnames'; import RelativePortal from 'react-relative-portal'; -function delay(ms) { +function delay(ms: number) { return new Promise((resolve) => { setTimeout(resolve, ms); }); @@ -15,14 +15,21 @@ function getViewportRect() { return { top: 0, left: 0, width, height }; } -function getCenterPoint(rect) { +type Rect = { + top: number; + left: number; + width: number; + height: number; +}; + +function getCenterPoint(rect: Rect) { return { x: rect.left + 0.5 * rect.width, y: rect.top + 0.5 * rect.height, }; } -function getPreferAlignment(rect) { +function getPreferAlignment(rect: Rect) { const { x: rx, y: ry } = getCenterPoint(rect); const { x: vx, y: vy } = getCenterPoint(getViewportRect()); return { @@ -31,7 +38,12 @@ function getPreferAlignment(rect) { }; } -function calcAlignmentRect(target, rect, vertAlign, horizAlign) { +function calcAlignmentRect( + target: Rect, + rect: Rect, + vertAlign: string, + horizAlign: string +) { return { ...rect, top: @@ -53,7 +65,7 @@ function calcAlignmentRect(target, rect, vertAlign, horizAlign) { }; } -function hasViewportIntersection({ top, left, width, height }) { +function hasViewportIntersection({ top, left, width, height }: Rect) { const { width: viewportWidth, height: viewportHeight } = getViewportRect(); return ( top < 0 || @@ -63,7 +75,7 @@ function hasViewportIntersection({ top, left, width, height }) { ); } -function isEqualRect(aRect, bRect) { +function isEqualRect(aRect: Rect, bRect: Rect) { return ( aRect.top === bRect.top && aRect.left === bRect.left && @@ -72,9 +84,9 @@ function isEqualRect(aRect, bRect) { ); } -function throttle(func, ms) { +function throttle(func: any, ms: number) { let last = 0; - return (...args) => { + return (...args: any) => { const now = Date.now(); if (last + ms < now) { func(...args); @@ -83,9 +95,9 @@ function throttle(func, ms) { }; } -function ignoreFirstCall(func) { +function ignoreFirstCall(func: any) { let called = false; - return (...args) => { + return (...args: any) => { if (called) { func(...args); } From 8068794ef24c5e41e8e2f3e41e544af2c6647265 Mon Sep 17 00:00:00 2001 From: Shingo Yamazaki Date: Fri, 24 May 2019 01:31:33 +0900 Subject: [PATCH 4/8] #289 AutoAlign: Declare private fields --- src/scripts/AutoAlign.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/scripts/AutoAlign.tsx b/src/scripts/AutoAlign.tsx index e633854a9..3739eb5c1 100644 --- a/src/scripts/AutoAlign.tsx +++ b/src/scripts/AutoAlign.tsx @@ -113,6 +113,14 @@ export default function autoAlign(options) { return (Cmp) => class extends React.Component { + /* eslint-disable react/sort-comp */ + private pid: number | null = null; + + private node: any; + + private content: any; + /* eslint-enable react/sort-comp */ + static propTypes = { portalClassName: PropTypes.string, portalStyle: PropTypes.object, // eslint-disable-line react/forbid-prop-types From f883f62412d8221204986a632e54ec133f36daf4 Mon Sep 17 00:00:00 2001 From: Shingo Yamazaki Date: Fri, 19 Jul 2019 06:56:26 +0900 Subject: [PATCH 5/8] #289 AutoAlign: Convert propTypes to TypeScript type --- src/scripts/AutoAlign.tsx | 71 ++++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 24 deletions(-) diff --git a/src/scripts/AutoAlign.tsx b/src/scripts/AutoAlign.tsx index 3739eb5c1..2336de3e8 100644 --- a/src/scripts/AutoAlign.tsx +++ b/src/scripts/AutoAlign.tsx @@ -1,7 +1,8 @@ -import React from 'react'; +import React, { ComponentType } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import RelativePortal from 'react-relative-portal'; +import { ComponentSettingsContext } from './ComponentSettings'; function delay(ms: number) { return new Promise((resolve) => { @@ -9,7 +10,7 @@ function delay(ms: number) { }); } -function getViewportRect() { +function getViewportRect(): Rect { const { innerHeight: height = Infinity, innerWidth: width = Infinity } = window || {}; return { top: 0, left: 0, width, height }; @@ -40,7 +41,7 @@ function getPreferAlignment(rect: Rect) { function calcAlignmentRect( target: Rect, - rect: Rect, + rect: { width: number; height: number }, vertAlign: string, horizAlign: string ) { @@ -84,7 +85,7 @@ function isEqualRect(aRect: Rect, bRect: Rect) { ); } -function throttle(func: any, ms: number) { +function throttle(func: Function, ms: number) { let last = 0; return (...args: any) => { const now = Date.now(); @@ -95,7 +96,7 @@ function throttle(func: any, ms: number) { }; } -function ignoreFirstCall(func: any) { +function ignoreFirstCall(func: Function) { let called = false; return (...args: any) => { if (called) { @@ -105,38 +106,59 @@ function ignoreFirstCall(func: any) { }; } +export type AutoAlignOptions = { + triggerSelector: string; +}; + +export type AutoAlignProps = { + portalClassName: string; + portalStyle: object; + size: 'small' | 'medium' | 'large'; + preventPortalize: boolean; +} & InjectedProps; + +export type InjectedProps = { + align: 'left' | 'right'; + vertAlign: 'top' | 'bottom'; +}; + +export type AutoAlignState = { + triggerRect: Rect; + horizAlign: string; + vertAlign: string; +}; + /** * */ -export default function autoAlign(options) { +export default function autoAlign(options: AutoAlignOptions) { const { triggerSelector } = options; - return (Cmp) => - class extends React.Component { - /* eslint-disable react/sort-comp */ + return ( + Cmp: ComponentType + ) => { + type ResultProps = TOriginalProps & AutoAlignProps; + + return class extends React.Component { private pid: number | null = null; + /* eslint-disable react/sort-comp */ private node: any; private content: any; /* eslint-enable react/sort-comp */ - static propTypes = { - portalClassName: PropTypes.string, - portalStyle: PropTypes.object, // eslint-disable-line react/forbid-prop-types - size: PropTypes.oneOf(['small', 'medium', 'large']), - align: PropTypes.oneOf(['left', 'right']), - vertAlign: PropTypes.oneOf(['top', 'bottom']), - preventPortalize: PropTypes.bool, - children: PropTypes.node, - }; + context!: Pick< + ComponentSettingsContext, + 'portalClassName' | 'portalStyle' + >; static contextTypes = { portalClassName: PropTypes.string, portalStyle: PropTypes.object, // eslint-disable-line react/forbid-prop-types }; - state = { + state: AutoAlignState = { triggerRect: { top: 0, left: 0, width: 0, height: 0 }, horizAlign: 'left', vertAlign: 'top', @@ -202,7 +224,7 @@ export default function autoAlign(options) { } }; - updateAlignment(triggerRect) { + updateAlignment(triggerRect: Rect) { if (this.content && this.content.node) { const { horizAlign: oldHorizAlign, @@ -293,10 +315,10 @@ export default function autoAlign(options) { : 0; const content = ( (this.content = cmp)} - {...pprops} + align={align.split('-')[0] as InjectedProps['align']} + vertAlign={vertAlign.split('-')[0] as InjectedProps['vertAlign']} + ref={(cmp: any) => (this.content = cmp)} + {...pprops as TOriginalProps} > {children} @@ -321,4 +343,5 @@ export default function autoAlign(options) { ); } }; + }; } From 8352e4ea418b345434e872cf592f765b86ff1771 Mon Sep 17 00:00:00 2001 From: Shingo Yamazaki Date: Wed, 24 Jul 2019 19:35:23 +0900 Subject: [PATCH 6/8] #289 AutoAlign: Quit default export --- src/scripts/AutoAlign.tsx | 2 +- src/scripts/DateInput.js | 2 +- src/scripts/DropdownMenu.js | 2 +- src/scripts/Lookup.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/scripts/AutoAlign.tsx b/src/scripts/AutoAlign.tsx index 2336de3e8..a9791d73a 100644 --- a/src/scripts/AutoAlign.tsx +++ b/src/scripts/AutoAlign.tsx @@ -131,7 +131,7 @@ export type AutoAlignState = { /** * */ -export default function autoAlign(options: AutoAlignOptions) { +export function autoAlign(options: AutoAlignOptions) { const { triggerSelector } = options; return ( diff --git a/src/scripts/DateInput.js b/src/scripts/DateInput.js index 2d0d5ec5d..9369e3306 100644 --- a/src/scripts/DateInput.js +++ b/src/scripts/DateInput.js @@ -2,7 +2,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import moment from 'moment'; -import autoAlign from './AutoAlign'; +import { autoAlign } from './AutoAlign'; import { FormElement } from './FormElement'; import Input from './Input'; import { Icon } from './Icon'; diff --git a/src/scripts/DropdownMenu.js b/src/scripts/DropdownMenu.js index 1bfb30268..0409cfc1f 100644 --- a/src/scripts/DropdownMenu.js +++ b/src/scripts/DropdownMenu.js @@ -2,7 +2,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import { Icon } from './Icon'; -import autoAlign from './AutoAlign'; +import { autoAlign } from './AutoAlign'; import { PicklistItem } from './Picklist'; export const DropdownMenuHeader = ({ divider, className, children }) => { diff --git a/src/scripts/Lookup.js b/src/scripts/Lookup.js index 32142134b..7aa376066 100644 --- a/src/scripts/Lookup.js +++ b/src/scripts/Lookup.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; -import autoAlign from './AutoAlign'; +import { autoAlign } from './AutoAlign'; import { FormElement } from './FormElement'; import Input from './Input'; import { Icon } from './Icon'; From e843de611b9ea3512b84d464c4b1037461675c0a Mon Sep 17 00:00:00 2001 From: Shingo Yamazaki Date: Mon, 5 Aug 2019 20:10:47 +0900 Subject: [PATCH 7/8] #289 AutoAlign: InjectedProps of AutoAlignProps should be optional --- src/scripts/AutoAlign.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/AutoAlign.tsx b/src/scripts/AutoAlign.tsx index a9791d73a..54c7b8c27 100644 --- a/src/scripts/AutoAlign.tsx +++ b/src/scripts/AutoAlign.tsx @@ -115,7 +115,7 @@ export type AutoAlignProps = { portalStyle: object; size: 'small' | 'medium' | 'large'; preventPortalize: boolean; -} & InjectedProps; +} & Partial; export type InjectedProps = { align: 'left' | 'right'; From 764166a76ce7777d877f3faa47a83830e956f0de Mon Sep 17 00:00:00 2001 From: Shingo Yamazaki Date: Mon, 5 Aug 2019 20:12:51 +0900 Subject: [PATCH 8/8] #289 AutoAlign: AutoAlignProps should be optional --- src/scripts/AutoAlign.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/scripts/AutoAlign.tsx b/src/scripts/AutoAlign.tsx index 54c7b8c27..3903cd587 100644 --- a/src/scripts/AutoAlign.tsx +++ b/src/scripts/AutoAlign.tsx @@ -111,10 +111,10 @@ export type AutoAlignOptions = { }; export type AutoAlignProps = { - portalClassName: string; - portalStyle: object; - size: 'small' | 'medium' | 'large'; - preventPortalize: boolean; + portalClassName?: string; + portalStyle?: object; + size?: 'small' | 'medium' | 'large'; + preventPortalize?: boolean; } & Partial; export type InjectedProps = {