diff --git a/build/babel.config.js b/build/babel.config.js index 3ac1e0a17..9168543b3 100644 --- a/build/babel.config.js +++ b/build/babel.config.js @@ -24,7 +24,7 @@ module.exports = { [ "@babel/preset-react", { - // runtime: "automatic", + runtime: "automatic", useBuiltIns: true, development: !IS_PRODUCTION } @@ -49,7 +49,6 @@ module.exports = { } ], "babel-plugin-jsx-control-statements", - "babel-plugin-react-require", IS_PRODUCTION && "babel-plugin-jsx-remove-data-test-id", !IS_TEST && [ "babel-plugin-named-asset-import", diff --git a/jest/jest.config.js b/jest/jest.config.js index 520d70557..121e65ad4 100644 --- a/jest/jest.config.js +++ b/jest/jest.config.js @@ -4,7 +4,7 @@ module.exports = { rootDir: path.resolve(__dirname, ".."), roots: ["/packages/react-components"], transform: { - "^.+\\.(js|jsx)$": path.resolve("jest/babel-transform.js") + "^.+\\.(js|jsx|ts|tsx)$": path.resolve("jest/babel-transform.js") }, // https://github.com/facebook/jest/issues/6229#issuecomment-403539460 transformIgnorePatterns: [ diff --git a/package.json b/package.json index 8edc65073..bd3316f15 100644 --- a/package.json +++ b/package.json @@ -34,9 +34,9 @@ "delete-yarn-lock:root": "rimraf yarn.lock", "delete-yarn-lock:storybook": "cd storybook && rimraf yarn.lock", "eslint": "run-s \"eslint:* --max-warnings={1:--1}\"", - "eslint:pkg": "eslint --ext .js,.jsx packages", - "eslint:sb": "eslint --ext .js,.jsx storybook", - "eslint-fix": "eslint --ext .js,.jsx . --fix", + "eslint:pkg": "eslint --ext .js,.jsx,.ts,.tsx packages", + "eslint:sb": "eslint --ext .js,.jsx,.ts,.tsx storybook", + "eslint-fix": "eslint --ext .js,.jsx,.ts,.tsx . --fix", "install:pkg": "yarn install --ignore-scripts", "install:sb": "cd storybook && yarn install", "lint": "run-s eslint stylelint check-types", @@ -82,16 +82,19 @@ "@babel/preset-typescript": "7.12.7", "@sharegate/browserslist-config-recommended": "1.0.1", "@sharegate/eslint-config-lodash": "1.0.2", - "@sharegate/eslint-config-react": "2.0.0", + "@sharegate/eslint-config-react": "2.1.0", "@sharegate/eslint-config-recommended": "1.1.0", "@sharegate/eslint-config-sort-imports": "1.0.2", + "@sharegate/eslint-config-typescript": "1.3.0", "@sharegate/stylelint-config-recommended": "2.0.0", "@types/lodash": "4.14.168", "@types/react-with-styles": "4.0.5", "@types/react-dates": "21.8.1", "@types/react-dom": "17.0.0", "@types/react": "17.0.0", - "@sharegate/eslint-config-typescript": "1.0.0", + "@types/react-is": "17.0.0", + "@types/resize-observer-browser": "0.1.5", + "@typescript-eslint/parser": "4.15.0", "@storybook/addon-essentials": "6.1.8", "@storybook/react": "6.1.8", "@svgr/webpack": "5.5.0", @@ -104,7 +107,6 @@ "babel-plugin-jsx-control-statements": "4.1.0", "babel-plugin-jsx-remove-data-test-id": "2.1.3", "babel-plugin-named-asset-import": "0.3.7", - "babel-plugin-react-require": "3.1.3", "browserslist": "4.14.7", "chalk": "4.1.0", "chromatic": "5.4.0", diff --git a/packages/react-components/.eslintrc.js b/packages/react-components/.eslintrc.js index ec2bbf7a0..d11f87803 100644 --- a/packages/react-components/.eslintrc.js +++ b/packages/react-components/.eslintrc.js @@ -37,20 +37,22 @@ module.exports = { } }, { - files: ["*.tsx"], + files: ["*.ts?(x)"], extends:[ "@sharegate/eslint-config-typescript" ], rules: { - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-module-boundary-types": "off", - "@typescript-eslint/no-use-before-define": ["error", { "functions": false, "classes": true, "variables": false }] + "no-param-reassign": "off", + "@typescript-eslint/no-explicit-any": "off", + + "jsx-control-statements/jsx-jcs-no-undef": "off", + "@typescript-eslint/explicit-function-return-type": ["warn", { allowExpressions: true }] } } ], rules: { "no-param-reassign": "off", - "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx", ".mdx"] }], + "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx",".ts", ".tsx", ".mdx"] }], "react/destructuring-assignment": "off", "jsx-control-statements/jsx-use-if-tag": "off" } diff --git a/packages/react-components/src/shared/src/OLD_env.js b/packages/react-components/src/shared/src/OLD_env.ts similarity index 100% rename from packages/react-components/src/shared/src/OLD_env.js rename to packages/react-components/src/shared/src/OLD_env.ts diff --git a/packages/react-components/src/shared/src/OLD_resolvePopperPosition.js b/packages/react-components/src/shared/src/OLD_resolvePopperPosition.js deleted file mode 100644 index 846b09165..000000000 --- a/packages/react-components/src/shared/src/OLD_resolvePopperPosition.js +++ /dev/null @@ -1,3 +0,0 @@ -export function resolvePopperPosition(upward, direction) { - return `${upward ? "top" : "bottom"}-${direction === "left" ? "end" : "start"}`; -} diff --git a/packages/react-components/src/shared/src/OLD_resolvePopperPosition.ts b/packages/react-components/src/shared/src/OLD_resolvePopperPosition.ts new file mode 100644 index 000000000..9722c96d6 --- /dev/null +++ b/packages/react-components/src/shared/src/OLD_resolvePopperPosition.ts @@ -0,0 +1,3 @@ +export function resolvePopperPosition(upward: boolean, direction: "left" | "right"): string { + return `${upward ? "top" : "bottom"}-${direction === "left" ? "end" : "start"}`; +} diff --git a/packages/react-components/src/shared/src/arrayify.js b/packages/react-components/src/shared/src/arrayify.ts similarity index 50% rename from packages/react-components/src/shared/src/arrayify.js rename to packages/react-components/src/shared/src/arrayify.ts index e085424df..d6da591af 100644 --- a/packages/react-components/src/shared/src/arrayify.js +++ b/packages/react-components/src/shared/src/arrayify.ts @@ -1,3 +1,3 @@ -export function arrayify(value) { +export function arrayify(value: T | T[]): T[] { return Array.isArray(value) ? value : [value]; } diff --git a/packages/react-components/src/shared/src/assertion.js b/packages/react-components/src/shared/src/assertion.ts similarity index 79% rename from packages/react-components/src/shared/src/assertion.js rename to packages/react-components/src/shared/src/assertion.ts index 7a1917610..fe702731d 100644 --- a/packages/react-components/src/shared/src/assertion.js +++ b/packages/react-components/src/shared/src/assertion.ts @@ -3,6 +3,6 @@ import { isNil } from "lodash"; -export function isNilOrEmpty(value) { +export function isNilOrEmpty(value: any): value is null | undefined | "" { return isNil(value) || value === ""; } diff --git a/packages/react-components/src/shared/src/augmentElement.js b/packages/react-components/src/shared/src/augmentElement.js deleted file mode 100644 index 4f288f24f..000000000 --- a/packages/react-components/src/shared/src/augmentElement.js +++ /dev/null @@ -1,32 +0,0 @@ -import { cloneElement } from "react"; -import { isString } from "lodash"; -import { isValidElementType } from "react-is"; -import { mergeProps } from "./mergeProps"; -import { normalizeSize } from "./normalizeSize"; - -export function augmentElement(element, newProps) { - const augmentedProps = mergeProps({ ...element.props, ref: element.ref }, newProps); - - return cloneElement(element, augmentedProps); -} - -export function createOrAugmentElement(element, props = {}) { - if (isValidElementType(element) && !isString(element)) { - const Type = element; - - return ; - } - - return augmentElement(element, props); -} - -export function createEmbeddableAdapter(sizeAdapter) { - return (element, { size, ...props } = {}) => { - const newProps = { - ...props, - size: sizeAdapter[normalizeSize(size)] - }; - - return augmentElement(element, newProps); - }; -} diff --git a/packages/react-components/src/shared/src/augmentElement.tsx b/packages/react-components/src/shared/src/augmentElement.tsx new file mode 100644 index 000000000..87ef960f1 --- /dev/null +++ b/packages/react-components/src/shared/src/augmentElement.tsx @@ -0,0 +1,37 @@ +import { ElementType, HTMLAttributes, ReactElement, RefAttributes, cloneElement } from "react"; +import { isString } from "lodash"; +import { isValidElementType } from "react-is"; +import { mergeProps } from "./mergeProps"; +import { normalizeSize } from "./normalizeSize"; +import type { SizeAdapter } from "./createSizeAdapter"; + +export function augmentElement(element: ReactElement & RefAttributes, newProps: Record): ReactElement { + const augmentedProps = mergeProps({ ...element.props, ref: element.ref }, newProps); + + return cloneElement(element, augmentedProps); +} + +export function createOrAugmentElement>(element: ReactElement | ElementType, props: P): ReactElement { + if (isValidElementType(element) && !isString(element)) { + const Type = element; + + return ; + } + + // The isString in the previous condition assume it can be possible that element is a string. however, if its the case, cloneElement does not support string, so it does not make sense + // Therefore, since we are only typing the code and i don't want to introduce regression bugs, i will disable the ts compiler for that line + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + return augmentElement(element, props); +} + +export function createEmbeddableAdapter(sizeAdapter: SizeAdapter) { + return

>(element: ReactElement, { size, ...props }: P) => { + const newProps = { + ...props, + size: sizeAdapter[normalizeSize(size)] + }; + + return augmentElement(element, newProps); + }; +} diff --git a/packages/react-components/src/shared/src/checkable.js b/packages/react-components/src/shared/src/checkable.ts similarity index 63% rename from packages/react-components/src/shared/src/checkable.js rename to packages/react-components/src/shared/src/checkable.ts index 183ac3f7e..b74a6ea1a 100644 --- a/packages/react-components/src/shared/src/checkable.js +++ b/packages/react-components/src/shared/src/checkable.ts @@ -1,9 +1,14 @@ import { createContext, useContext } from "react"; import { isNil } from "lodash"; -export const CheckableContext = createContext(); +interface CheckableContextProps { + checkedValue?: boolean; + [x: string]: any; +} + +export const CheckableContext = createContext(undefined); -export function useCheckableContext() { +export function useCheckableContext(): [CheckableContextProps, boolean] { const context = useContext(CheckableContext); if (!isNil(context)) { @@ -13,7 +18,7 @@ export function useCheckableContext() { return [context, false]; } -export function useCheckableProps({ value }) { +export function useCheckableProps({ value }: { value: boolean }): [{ checked: boolean } & any, boolean] { const [context, isCheckable] = useCheckableContext(); if (isCheckable) { diff --git a/packages/react-components/src/shared/src/createSizeAdapter.js b/packages/react-components/src/shared/src/createSizeAdapter.js deleted file mode 100644 index 0f7172c78..000000000 --- a/packages/react-components/src/shared/src/createSizeAdapter.js +++ /dev/null @@ -1,9 +0,0 @@ -import { normalizeSize } from "./normalizeSize"; - -export function createSizeAdapter(adapter) { - return size => adapter[normalizeSize(size)]; -} - -export function adaptSize(size, adapter) { - return adapter[normalizeSize(size)]; -} diff --git a/packages/react-components/src/shared/src/createSizeAdapter.ts b/packages/react-components/src/shared/src/createSizeAdapter.ts new file mode 100644 index 000000000..e3e31f91a --- /dev/null +++ b/packages/react-components/src/shared/src/createSizeAdapter.ts @@ -0,0 +1,12 @@ +import { normalizeSize } from "./normalizeSize"; +import type { Size } from "./size"; + +export type SizeAdapter = Record; + +export function createSizeAdapter(adapter: SizeAdapter): (size: Size) => Size { + return (size: Size) => adapter[normalizeSize(size)]; +} + +export function adaptSize(size: Size, adapter: SizeAdapter): Size { + return adapter[normalizeSize(size)]; +} diff --git a/packages/react-components/src/shared/src/cssModule.js b/packages/react-components/src/shared/src/cssModule.ts similarity index 64% rename from packages/react-components/src/shared/src/cssModule.js rename to packages/react-components/src/shared/src/cssModule.ts index 65e2ee36b..addf72168 100644 --- a/packages/react-components/src/shared/src/cssModule.js +++ b/packages/react-components/src/shared/src/cssModule.ts @@ -1,4 +1,4 @@ -export function cssModule(moduleName, ...values) { +export function cssModule(moduleName: string, ...values: (false | string)[]): string { const classes = values .filter(Boolean) .map(x => `${moduleName}-${x}`); diff --git a/packages/react-components/src/shared/src/focusTarget.js b/packages/react-components/src/shared/src/focusTarget.js deleted file mode 100644 index 19a2581c8..000000000 --- a/packages/react-components/src/shared/src/focusTarget.js +++ /dev/null @@ -1,4 +0,0 @@ -export const FocusTarget = { - first: "first", - last: "last" -}; diff --git a/packages/react-components/src/shared/src/focusTarget.ts b/packages/react-components/src/shared/src/focusTarget.ts new file mode 100644 index 000000000..c52ce84ab --- /dev/null +++ b/packages/react-components/src/shared/src/focusTarget.ts @@ -0,0 +1,4 @@ +export enum FocusTarget { + first = "first", + last = "last" +} diff --git a/packages/react-components/src/shared/src/focusableTreeWalker.js b/packages/react-components/src/shared/src/focusableTreeWalker.ts similarity index 76% rename from packages/react-components/src/shared/src/focusableTreeWalker.js rename to packages/react-components/src/shared/src/focusableTreeWalker.ts index 56425dbf9..8e2b80b91 100644 --- a/packages/react-components/src/shared/src/focusableTreeWalker.js +++ b/packages/react-components/src/shared/src/focusableTreeWalker.ts @@ -20,7 +20,11 @@ export const FocusableElementSelector = [...FocusableElement, "[tabindex]"].join export const TabbableElementSelector = [...FocusableElement, "[tabindex]:not([tabindex=\"-1\"])"].join(":not([tabindex=\"-1\"]),"); -export function createFocusableTreeWalker(root, { tabbable } = {}) { +interface FocusableTreeWalkerOptions { + tabbable?: boolean; +} + +export function createFocusableTreeWalker(root: HTMLElement, { tabbable }: FocusableTreeWalkerOptions = {}): TreeWalker { const selector = tabbable ? TabbableElementSelector : FocusableElementSelector; const walker = document.createTreeWalker( @@ -28,7 +32,7 @@ export function createFocusableTreeWalker(root, { tabbable } = {}) { NodeFilter.SHOW_ELEMENT, { acceptNode(node) { - if (node.matches(selector)) { + if ((node as HTMLElement).matches(selector)) { return NodeFilter.FILTER_ACCEPT; } @@ -41,6 +45,6 @@ export function createFocusableTreeWalker(root, { tabbable } = {}) { return walker; } -export function walkFocusableElements(root, onElement) { +export function walkFocusableElements(root: HTMLElement, onElement: (element: Element, index?: number) => void): void { root.querySelectorAll(FocusableElementSelector).forEach((x, index) => onElement(x, index)); } diff --git a/packages/react-components/src/shared/src/index.js b/packages/react-components/src/shared/src/index.ts similarity index 100% rename from packages/react-components/src/shared/src/index.js rename to packages/react-components/src/shared/src/index.ts diff --git a/packages/react-components/src/shared/src/keys.js b/packages/react-components/src/shared/src/keys.js deleted file mode 100644 index 03eaf5369..000000000 --- a/packages/react-components/src/shared/src/keys.js +++ /dev/null @@ -1,14 +0,0 @@ -export const Keys = { - backspace: 8, - tab: 9, - enter: 13, - esc: 27, - space: 32, - end: 35, - home: 36, - left: 37, - up: 38, - right: 39, - down: 40, - delete: 46 -}; diff --git a/packages/react-components/src/shared/src/keys.ts b/packages/react-components/src/shared/src/keys.ts new file mode 100644 index 000000000..04d90ae9b --- /dev/null +++ b/packages/react-components/src/shared/src/keys.ts @@ -0,0 +1,14 @@ +export enum Keys { + backspace = 8, + tab = 9, + enter = 13, + esc = 27, + space = 32, + end = 35, + home = 36, + left = 37, + up = 38, + right = 39, + down = 40, + delete = 46 +} diff --git a/packages/react-components/src/shared/src/match.js b/packages/react-components/src/shared/src/match.ts similarity index 74% rename from packages/react-components/src/shared/src/match.js rename to packages/react-components/src/shared/src/match.ts index 1c4b10227..8a9ae63f0 100644 --- a/packages/react-components/src/shared/src/match.js +++ b/packages/react-components/src/shared/src/match.ts @@ -1,7 +1,7 @@ import { isFunction, isNil } from "lodash"; // Took from https://github.com/tailwindlabs/headlessui/blob/develop/packages/%40headlessui-react/src/utils/match.ts -export function match(value, lookup, ...args) { +export function match(value: TValue, lookup: Record TReturnValue)>, ...args: any[]): TReturnValue { const handler = lookup[value]; if (!isNil(handler)) { diff --git a/packages/react-components/src/shared/src/mergeClasses.js b/packages/react-components/src/shared/src/mergeClasses.js deleted file mode 100644 index 5c79273b3..000000000 --- a/packages/react-components/src/shared/src/mergeClasses.js +++ /dev/null @@ -1,13 +0,0 @@ -export function mergeClasses(...values) { - const deduped = values - .filter(Boolean) - .reduce((set, x) => { - x.split(" ").forEach(y => { - set.add(y); - }); - - return set; - }, new Set()); - - return [...deduped].join(" "); -} diff --git a/packages/react-components/src/shared/src/mergeClasses.ts b/packages/react-components/src/shared/src/mergeClasses.ts new file mode 100644 index 000000000..05beacc87 --- /dev/null +++ b/packages/react-components/src/shared/src/mergeClasses.ts @@ -0,0 +1,13 @@ +export function mergeClasses(...values: (string | false)[]): string { + const deduped = (values + .filter(Boolean) as string[]) + .reduce((set, x) => { + x.split(" ").forEach(y => { + set.add(y); + }); + + return set; + }, new Set()); + + return Array.from(deduped).join(" "); +} diff --git a/packages/react-components/src/shared/src/mergeProps.js b/packages/react-components/src/shared/src/mergeProps.ts similarity index 55% rename from packages/react-components/src/shared/src/mergeProps.js rename to packages/react-components/src/shared/src/mergeProps.ts index 4a801e464..5790f73b0 100644 --- a/packages/react-components/src/shared/src/mergeProps.js +++ b/packages/react-components/src/shared/src/mergeProps.ts @@ -3,19 +3,24 @@ import { isFunction, isNil, isUndefined } from "lodash"; import { mergeClasses } from "./mergeClasses"; import { mergeRefs } from "./useMergedRefs"; -// Usefull to compose a weak map key with multiple objects. -export class CompositeKeyWeakMap { - _root = new WeakMap(); +interface CompositeKeyWeakMapNode { + value?: T, + map: WeakMap +} + +// Useful to compose a weak map key with multiple objects. +export class CompositeKeyWeakMap { + _root = new WeakMap(); - set(keys, value) { - let node = this._root; + set(keys: any[], value: T): void { + let node: WeakMap | CompositeKeyWeakMapNode = this._root; for (let i = 0; i < keys.length; i += 1) { const key = keys[i]; - const map = node.map || node; + const map: WeakMap = (node as CompositeKeyWeakMapNode).map || node as WeakMap; if (!map.has(key)) { - const child = { + const child: CompositeKeyWeakMapNode = { value: undefined, map: new WeakMap() }; @@ -27,33 +32,34 @@ export class CompositeKeyWeakMap { } } - node.value = value; + (node as CompositeKeyWeakMapNode).value = value; } - get(keys) { - let node = this._root; + get(keys: any[]): T { + let node: WeakMap | CompositeKeyWeakMapNode = this._root; for (let i = 0; i < keys.length; i += 1) { - node = (node.map || node).get(keys[i]); + const map: WeakMap = (node as CompositeKeyWeakMapNode).map || node as WeakMap; + node = map.get(keys[i]); if (isUndefined(node)) { return node; } } - return node.value; + return (node as CompositeKeyWeakMapNode).value; } - has(keys) { + has(keys: any[]): boolean { return !isUndefined(this.get(keys)); } } //////// -const cache = new CompositeKeyWeakMap(); +const cache = new CompositeKeyWeakMap(); -function memoMerge(x, y, fct) { +function memoMerge(x: TFirst, y: TSecond, fct: (y: TSecond, x: TFirst) => TOutput): undefined | TFirst | TSecond | TOutput { if (isNil(x) && isNil(y)) { return undefined; } @@ -67,7 +73,7 @@ function memoMerge(x, y, fct) { } const key = [x, y]; - const value = cache.get(key); + const value = cache.get(key) as TOutput; if (!isUndefined(value)) { return value; @@ -80,7 +86,7 @@ function memoMerge(x, y, fct) { return mergeResult; } -function merge(props, newProps) { +function merge(props: any, newProps: any): any { Object .keys(newProps) .forEach(x => { @@ -107,12 +113,16 @@ function merge(props, newProps) { return props; } -export function mergeProps(...args) { +// taken from: https://stackoverflow.com/questions/51603250/typescript-3-parameter-list-intersection-type/51604379#51604379 +type TupleTypes = { [P in keyof T]: T[P] } extends { [key: number]: infer V } ? V : never; +type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never; + +export function mergeProps[]>(...args: T): UnionToIntersection> { let result = {}; args.forEach(x => { result = merge(result, x); }); - return result; + return result as UnionToIntersection>; } diff --git a/packages/react-components/src/shared/src/normalizeSize.js b/packages/react-components/src/shared/src/normalizeSize.js deleted file mode 100644 index a3040304c..000000000 --- a/packages/react-components/src/shared/src/normalizeSize.js +++ /dev/null @@ -1,3 +0,0 @@ -export function normalizeSize(size) { - return size || "md"; -} diff --git a/packages/react-components/src/shared/src/normalizeSize.ts b/packages/react-components/src/shared/src/normalizeSize.ts new file mode 100644 index 000000000..bfc889e23 --- /dev/null +++ b/packages/react-components/src/shared/src/normalizeSize.ts @@ -0,0 +1,5 @@ +import type { Size } from "./size"; + +export function normalizeSize(size?: Size): Size { + return size || "md"; +} diff --git a/packages/react-components/src/shared/src/omitProps.js b/packages/react-components/src/shared/src/omitProps.js deleted file mode 100644 index da42dc4b7..000000000 --- a/packages/react-components/src/shared/src/omitProps.js +++ /dev/null @@ -1,9 +0,0 @@ -export function omitProps(obj, props) { - return Object.keys(obj).reduce((acc, x) => { - if (!props.includes(x)) { - acc[x] = obj[x]; - } - - return acc; - }, {}); -} diff --git a/packages/react-components/src/shared/src/omitProps.ts b/packages/react-components/src/shared/src/omitProps.ts new file mode 100644 index 000000000..0bfbe3931 --- /dev/null +++ b/packages/react-components/src/shared/src/omitProps.ts @@ -0,0 +1,10 @@ +export function omitProps, TKey extends keyof TObject>(obj: TObject, props: TKey[]): Omit { + return Object.keys(obj) + .reduce((acc: Record, x: string) => { + if (!props.includes(x as TKey)) { + acc[x] = obj[x]; + } + + return acc; + }, {}) as Omit; +} diff --git a/packages/react-components/src/shared/src/resolveChildren.js b/packages/react-components/src/shared/src/resolveChildren.js deleted file mode 100644 index b514d1b59..000000000 --- a/packages/react-components/src/shared/src/resolveChildren.js +++ /dev/null @@ -1,19 +0,0 @@ -import { Fragment } from "react"; -import { isFunction, isNil } from "lodash"; - -// Support first level fragment: https://github.com/facebook/react/issues/11859. -export function resolveFragment(children) { - if (!isNil(children) && children.type === Fragment) { - return children.props.children; - } - - return children; -} - -export function resolveChildren(children, renderProps) { - if (isFunction(children)) { - return resolveFragment(children(renderProps)); - } - - return resolveFragment(children); -} diff --git a/packages/react-components/src/shared/src/resolveChildren.ts b/packages/react-components/src/shared/src/resolveChildren.ts new file mode 100644 index 000000000..1fa9d4096 --- /dev/null +++ b/packages/react-components/src/shared/src/resolveChildren.ts @@ -0,0 +1,19 @@ +import { Fragment, ReactElement, ReactNode } from "react"; +import { isFunction, isNil } from "lodash"; + +// Support first level fragment: https://github.com/facebook/react/issues/11859. +export function resolveFragment(children: ReactNode): ReactNode { + if (!isNil(children) && (children as ReactElement).type === Fragment) { + return (children as ReactElement).props.children; + } + + return children; +} + +export function resolveChildren(children: ReactNode | ((args: T[]) => ReactNode), renderProps?: T): ReactNode { + if (isFunction(children)) { + return resolveFragment(children(renderProps)); + } + + return resolveFragment(children); +} diff --git a/packages/react-components/src/shared/src/semantic-ui/SemanticRef.jsx b/packages/react-components/src/shared/src/semantic-ui/SemanticRef.jsx deleted file mode 100644 index b2d5f4f34..000000000 --- a/packages/react-components/src/shared/src/semantic-ui/SemanticRef.jsx +++ /dev/null @@ -1,14 +0,0 @@ -import { Ref } from "semantic-ui-react"; -import { isNil } from "lodash"; - -export function SemanticRef({ innerRef, children }) { - if (!isNil(innerRef)) { - return ( - - {children} - - ); - } - - return children; -} diff --git a/packages/react-components/src/shared/src/semantic-ui/SemanticRef.tsx b/packages/react-components/src/shared/src/semantic-ui/SemanticRef.tsx new file mode 100644 index 000000000..db894f5ee --- /dev/null +++ b/packages/react-components/src/shared/src/semantic-ui/SemanticRef.tsx @@ -0,0 +1,20 @@ +import { Ref } from "semantic-ui-react"; +import { isNil } from "lodash"; +import React, { Ref as InnerRef, ReactElement, ReactNode } from "react"; + +interface SemanticRefProps { + innerRef: InnerRef | null + children: ReactElement +} + +export function SemanticRef({ innerRef, children }: SemanticRefProps): ReactNode { + if (!isNil(innerRef)) { + return ( + + {children} + + ); + } + + return children; +} diff --git a/packages/react-components/src/shared/src/semantic-ui/index.js b/packages/react-components/src/shared/src/semantic-ui/index.ts similarity index 100% rename from packages/react-components/src/shared/src/semantic-ui/index.js rename to packages/react-components/src/shared/src/semantic-ui/index.ts diff --git a/packages/react-components/src/shared/src/semantic-ui/throwWhenUnsupportedPropIsProvided.js b/packages/react-components/src/shared/src/semantic-ui/throwWhenUnsupportedPropIsProvided.ts similarity index 72% rename from packages/react-components/src/shared/src/semantic-ui/throwWhenUnsupportedPropIsProvided.js rename to packages/react-components/src/shared/src/semantic-ui/throwWhenUnsupportedPropIsProvided.ts index f12b78a7c..0268ab5aa 100644 --- a/packages/react-components/src/shared/src/semantic-ui/throwWhenUnsupportedPropIsProvided.js +++ b/packages/react-components/src/shared/src/semantic-ui/throwWhenUnsupportedPropIsProvided.ts @@ -1,7 +1,7 @@ import { IS_PRODUCTION } from "../OLD_env"; import { isNil } from "lodash"; -export function throwWhenUnsupportedPropIsProvided(props, unsupportedProps, componentName) { +export function throwWhenUnsupportedPropIsProvided(props: Record, unsupportedProps: string[], componentName: string): void { if (!IS_PRODUCTION) { unsupportedProps.forEach(x => { if (!isNil(props[x])) { diff --git a/packages/react-components/src/shared/src/size.ts b/packages/react-components/src/shared/src/size.ts new file mode 100644 index 000000000..631ff0633 --- /dev/null +++ b/packages/react-components/src/shared/src/size.ts @@ -0,0 +1 @@ +export type Size = "2xs" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "4xl" | "5xl" | "inherit"; diff --git a/packages/react-components/src/shared/src/slots.js b/packages/react-components/src/shared/src/slots.tsx similarity index 61% rename from packages/react-components/src/shared/src/slots.js rename to packages/react-components/src/shared/src/slots.tsx index 0d8440666..118e9c11b 100644 --- a/packages/react-components/src/shared/src/slots.js +++ b/packages/react-components/src/shared/src/slots.tsx @@ -1,21 +1,35 @@ -import { Children, useMemo } from "react"; +import { Children, ComponentType, ReactElement, ReactNode, useMemo } from "react"; import { augmentElement, resolveChildren } from "../../shared"; import { isNil, isString, isUndefined } from "lodash"; const SLOT_KEY = "__slot__"; -function slotDecorator(slotName, ElementType) { - ElementType[SLOT_KEY] = slotName; +interface SlottedElement { + [SLOT_KEY]?: string; +} + +function slotDecorator

(slotName: string, ElementType: P): P { + (ElementType as Record)[SLOT_KEY] = slotName; return ElementType; } export { slotDecorator as slot }; -function findSlots(children, slots) { - return Children.toArray(children).reduce((acc, x) => { +interface Slots { + _: { + defaultWrapper?: ComponentType; + required?: string[]; + }, + [x: string]: any; +} + + +function findSlots(children: ReactNode, slots: string[]): Record { + return Children.toArray(children).reduce((acc: Record, x: ReactNode) => { if (!isNil(x)) { - const slotKey = (x.props && x.props["slot"]) ?? (x.type && x.type[SLOT_KEY]); + const reactElement = x as ReactElement; + const slotKey = (reactElement.props && reactElement.props["slot"]) ?? (reactElement.type && (reactElement.type as SlottedElement)[SLOT_KEY]); if (!isNil(slotKey) && slots.includes(slotKey)) { acc[slotKey] = x; @@ -23,10 +37,10 @@ function findSlots(children, slots) { } return acc; - }, {}); + }, {}) as Record; } -export function parseSlots(children, slots) { +export function parseSlots(children: ReactNode, slots: string[]): Record { if (isNil(children)) { return {}; } @@ -42,12 +56,12 @@ export function parseSlots(children, slots) { }; } -export function getSlots(children, { _ = {}, ...slots }) { +export function getSlots(children: ReactNode, { _ = {}, ...slots }: Slots): Record { if (isNil(children)) { return {}; } - let slotElements = {}; + let slotElements: Record = {}; children = resolveChildren(children); @@ -58,7 +72,7 @@ export function getSlots(children, { _ = {}, ...slots }) { const { required, defaultWrapper: Wrapper } = _; if (!isNil(required)) { - const unfulfilledSlots = []; + const unfulfilledSlots: string[] = []; required.forEach(x => { if (isUndefined(slotElements[x])) { @@ -73,7 +87,7 @@ export function getSlots(children, { _ = {}, ...slots }) { if (!isNil(Wrapper)) { if (Object.keys(slotElements).length === 0 && !isNil(children)) { - const wrapperSlot = Wrapper[SLOT_KEY]; + const wrapperSlot = (Wrapper as SlottedElement)[SLOT_KEY]; if (isNil(wrapperSlot)) { throw new Error("A default wrapper should have a slot key."); @@ -98,6 +112,6 @@ export function getSlots(children, { _ = {}, ...slots }) { return slotElements; } -export function useSlots(children, slots) { +export function useSlots(children: ReactElement, slots: Slots): Record { return useMemo(() => getSlots(children, slots), [children, slots]); } diff --git a/packages/react-components/src/shared/src/styles.js b/packages/react-components/src/shared/src/styles.ts similarity index 61% rename from packages/react-components/src/shared/src/styles.js rename to packages/react-components/src/shared/src/styles.ts index 061b349d7..b9a32b94a 100644 --- a/packages/react-components/src/shared/src/styles.js +++ b/packages/react-components/src/shared/src/styles.ts @@ -1,15 +1,17 @@ import { createContext, useContext } from "react"; import { isNil } from "lodash"; -export const StyleContext = createContext(); +type StyleContextProps = Record; + +export const StyleContext = createContext(undefined); export const StyleProvider = StyleContext.Provider; -export function useStyleContext() { +export function useStyleContext(): StyleContextProps { return useContext(StyleContext); } -export function useStyleProps(key) { +export function useStyleProps(key: string): [StyleContextProps, boolean] { const context = useStyleContext(); if (!isNil(context)) { diff --git a/packages/react-components/src/shared/src/useAutoFocus.js b/packages/react-components/src/shared/src/useAutoFocus.ts similarity index 66% rename from packages/react-components/src/shared/src/useAutoFocus.js rename to packages/react-components/src/shared/src/useAutoFocus.ts index 06e5f379c..14a79bf68 100644 --- a/packages/react-components/src/shared/src/useAutoFocus.js +++ b/packages/react-components/src/shared/src/useAutoFocus.ts @@ -1,11 +1,18 @@ +import { FocusManager, FocusOptions } from "./useFocusManager"; import { FocusTarget } from "./focusTarget"; +import { MutableRefObject, useEffect } from "react"; import { disposables } from "./useDisposables"; import { isNil } from "lodash"; import { useChainedEventCallback } from "./useChainedEventCallback"; -import { useEffect } from "react"; import { useEventCallback } from "./useEventCallback"; -function useAbstractAutoFocus({ isDisabled, delay, onFocus }) { +interface AutoFocusOptions extends FocusOptions { + target?: FocusTarget; + isDisabled?: boolean; + delay?: number; +} + +function useAbstractAutoFocus({ isDisabled, delay, onFocus }: AutoFocusOptions): void { useEffect(() => { const d = disposables(); @@ -23,7 +30,7 @@ function useAbstractAutoFocus({ isDisabled, delay, onFocus }) { }, [isDisabled, delay, onFocus]); } -export function useAutoFocus(targetRef, { isDisabled, delay, onFocus } = {}) { +export function useAutoFocus(targetRef: MutableRefObject, { isDisabled, delay, onFocus }: AutoFocusOptions = {}): void { useAbstractAutoFocus({ isDisabled, delay, @@ -35,7 +42,7 @@ export function useAutoFocus(targetRef, { isDisabled, delay, onFocus } = {}) { }); } -export function useAutoFocusChild(focusManager, { target = FocusTarget.first, isDisabled, delay, canFocus, onFocus, onNotFound } = {}) { +export function useAutoFocusChild(focusManager: FocusManager, { target = FocusTarget.first, isDisabled, delay, canFocus, onFocus, onNotFound }: AutoFocusOptions = {}): void { useAbstractAutoFocus({ isDisabled: isDisabled, delay, diff --git a/packages/react-components/src/shared/src/useChainedEventCallback.js b/packages/react-components/src/shared/src/useChainedEventCallback.js deleted file mode 100644 index eb24d1cf1..000000000 --- a/packages/react-components/src/shared/src/useChainedEventCallback.js +++ /dev/null @@ -1,17 +0,0 @@ -// Copied from https://github.com/react-bootstrap/react-bootstrap/blob/master/src/createChainedFunction.js. - -import { useEventCallback } from "./useEventCallback"; - -export function createChainedFunction(...funcs) { - return (...args) => { - funcs - .filter(Boolean) - .forEach(x => { - x(...args); - }); - }; -} - -export function useChainedEventCallback(...callbacks) { - return useEventCallback(createChainedFunction(...callbacks)); -} diff --git a/packages/react-components/src/shared/src/useChainedEventCallback.ts b/packages/react-components/src/shared/src/useChainedEventCallback.ts new file mode 100644 index 000000000..b035a8592 --- /dev/null +++ b/packages/react-components/src/shared/src/useChainedEventCallback.ts @@ -0,0 +1,18 @@ +// Copied from https://github.com/react-bootstrap/react-bootstrap/blob/master/src/createChainedFunction.js. + +import { useEventCallback } from "./useEventCallback"; + +type ChainableFunction = (...args: any[]) => void; + +export function createChainedFunction(...funcs: (T | false)[]) { + return (...args: any[]) => { + (funcs.filter(Boolean) as T[]) + .forEach(x => { + x(...args); + }); + }; +} + +export function useChainedEventCallback(...callbacks: (T | false)[]): ChainableFunction { + return useEventCallback(createChainedFunction(...callbacks)); +} diff --git a/packages/react-components/src/shared/src/useCommittedRef.js b/packages/react-components/src/shared/src/useCommittedRef.ts similarity index 62% rename from packages/react-components/src/shared/src/useCommittedRef.js rename to packages/react-components/src/shared/src/useCommittedRef.ts index e5fffe007..e95d493c5 100644 --- a/packages/react-components/src/shared/src/useCommittedRef.js +++ b/packages/react-components/src/shared/src/useCommittedRef.ts @@ -1,8 +1,8 @@ // Copied from https://github.com/react-restart/hooks/blob/master/src/useCommittedRef.ts. -import { useEffect, useRef } from "react"; +import { MutableRefObject, useEffect, useRef } from "react"; -export function useCommittedRef(value) { +export function useCommittedRef(value: T): MutableRefObject { const ref = useRef(value); useEffect(() => { diff --git a/packages/react-components/src/shared/src/useControllableState.js b/packages/react-components/src/shared/src/useControllableState.ts similarity index 81% rename from packages/react-components/src/shared/src/useControllableState.js rename to packages/react-components/src/shared/src/useControllableState.ts index da15bd0ad..28a6c3f2f 100644 --- a/packages/react-components/src/shared/src/useControllableState.js +++ b/packages/react-components/src/shared/src/useControllableState.ts @@ -2,7 +2,7 @@ import { isFunction, isUndefined } from "lodash"; import { useCallback, useRef } from "react"; import { useRefState } from "./useRefState"; -function validatePrerequisites(controlledValue, initialValue) { +function validatePrerequisites(controlledValue: any, initialValue: any): void { if (!isUndefined(controlledValue) && !isUndefined(initialValue)) { throw new Error( "useControllableState - A controllable state value can either have a controlled value or an initial value, but not both." @@ -10,14 +10,21 @@ function validatePrerequisites(controlledValue, initialValue) { } } -function ensureControlledStateHaveNotChanged(controlledValue, isControlled) { +function ensureControlledStateHaveNotChanged(controlledValue: any, isControlled: any): void { if ((isControlled && isUndefined(controlledValue)) || (!isControlled && !isUndefined(controlledValue))) { throw new Error("useControllableState - A controllable state value cannot switch between controlled and uncontrolled. Did you inadvertently set a default value (defaultProps) for your controlled prop?"); } } -function useComputeInitialState(controlledValue, initialValue, defaultValue) { - const result = (state, isControlled, isInitialState = false) => ({ state, isControlled, isInitialState }); + +interface useComputeInitialStateResult { + state: T; + isControlled: boolean; + isInitialState: boolean; +} + +function useComputeInitialState(controlledValue: T, initialValue: T, defaultValue: T): useComputeInitialStateResult { + const result = (state: T, isControlled: boolean, isInitialState = false): useComputeInitialStateResult => ({ state, isControlled, isInitialState }); const hasComputedRef = useRef(false); @@ -25,7 +32,7 @@ function useComputeInitialState(controlledValue, initialValue, defaultValue) { return result(null, null); } - let state; + let state: T; let isControlled = false; if (isUndefined(controlledValue)) { @@ -42,8 +49,8 @@ function useComputeInitialState(controlledValue, initialValue, defaultValue) { return result(state, isControlled, true); } -function computeSubsequentState(controlledValue, currentState, isControlled) { - let newState = null; +function computeSubsequentState(controlledValue: T, currentState: T, isControlled: boolean): { newState: T; hasChanged: boolean; } { + let newState: T | null = null; let hasChanged = false; ensureControlledStateHaveNotChanged(controlledValue, isControlled); @@ -61,6 +68,10 @@ function computeSubsequentState(controlledValue, currentState, isControlled) { }; } +interface ControllableStateOptions { + onChange?: (newState: T, options: { isControlled: boolean; isInitialState: boolean; }) => void +} + /** * This implementation is a port of Semantic UI React "AutoControlledComponent" base component to hooks: https://github.com/Semantic-Org/Semantic-UI-React/blob/master/src/lib/AutoControlledComponent.js. * The goal is to seemlessly support "controlled" and "uncontrolled" component behaviors by abstracting the complexity in this hook. @@ -85,7 +96,7 @@ function computeSubsequentState(controlledValue, currentState, isControlled) { * * setUncontrolledState("Neil Armstrong"); */ -export function useControllableState(controlledValue, initialValue, defaultValue, { onChange } = {}) { +export function useControllableState(controlledValue: T, initialValue: T, defaultValue: T, { onChange }: ControllableStateOptions = {}): [T, (maybeState: any) => void, boolean] { validatePrerequisites(controlledValue, initialValue); let { state: initialState, isControlled: isControlledProp, isInitialState } = useComputeInitialState(controlledValue, initialValue, defaultValue); diff --git a/packages/react-components/src/shared/src/useDisposables.js b/packages/react-components/src/shared/src/useDisposables.js deleted file mode 100644 index 06886883f..000000000 --- a/packages/react-components/src/shared/src/useDisposables.js +++ /dev/null @@ -1,44 +0,0 @@ -import { useEffect, useState } from "react"; - -// Took from https://github.com/tailwindlabs/headlessui/blob/develop/packages/%40headlessui-react/src/utils/disposables.ts -export function disposables() { - // eslint-disable-next-line no-shadow - const disposables = []; - - const api = { - requestAnimationFrame(...args) { - const id = requestAnimationFrame(...args); - api.add(() => cancelAnimationFrame(id)); - }, - - nextFrame(...args) { - api.requestAnimationFrame(...args); - }, - - setTimeout(...args) { - const timer = setTimeout(...args); - api.add(() => clearTimeout(timer)); - }, - - add(callback) { - disposables.push(callback); - }, - - dispose() { - disposables.splice(0).forEach(dispose => dispose()); - } - }; - - return api; -} - -export function useDisposables() { - // Using useState instead of useRef so that we can use the initializer function. - const [d] = useState(disposables); - - useEffect(() => { - return () => d.dispose(); - }, [d]); - - return d; -} diff --git a/packages/react-components/src/shared/src/useDisposables.ts b/packages/react-components/src/shared/src/useDisposables.ts new file mode 100644 index 000000000..50a60574d --- /dev/null +++ b/packages/react-components/src/shared/src/useDisposables.ts @@ -0,0 +1,57 @@ +import { useEffect, useState } from "react"; + +// we use Function here since we copied the method from another repo and they use this +// we rename it to DisposableFunction so we don't have to add the @typescript-eslint/ban-types every time we use this type. +// eslint-disable-next-line @typescript-eslint/ban-types +type DisposableFunction = Function; + +interface DisposableAPI { + requestAnimationFrame(callback: FrameRequestCallback): void; + nextFrame(callback: FrameRequestCallback): void; + setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): void; + add(callback: DisposableFunction): void; + dispose(): void; +} + +// Took from https://github.com/tailwindlabs/headlessui/blob/develop/packages/%40headlessui-react/src/utils/disposables.ts +export function disposables(): DisposableAPI { + // eslint-disable-next-line no-shadow + const _disposables: DisposableFunction[] = []; + + const api = { + requestAnimationFrame(...args: Parameters) { + const id = requestAnimationFrame(...args); + api.add(() => cancelAnimationFrame(id)); + }, + + nextFrame(...args: Parameters) { + api.requestAnimationFrame(...args); + }, + + setTimeout(...args: Parameters) { + const timer = setTimeout(...args); + api.add(() => clearTimeout(timer)); + }, + + add(callback: DisposableFunction) { + _disposables.push(callback); + }, + + dispose() { + _disposables.splice(0).forEach(dispose => dispose()); + } + }; + + return api; +} + +export function useDisposables(): DisposableAPI { + // Using useState instead of useRef so that we can use the initializer function. + const [d] = useState(disposables); + + useEffect(() => { + return () => d.dispose(); + }, [d]); + + return d; +} diff --git a/packages/react-components/src/shared/src/useEventCallback.js b/packages/react-components/src/shared/src/useEventCallback.ts similarity index 80% rename from packages/react-components/src/shared/src/useEventCallback.js rename to packages/react-components/src/shared/src/useEventCallback.ts index 19eccc9a7..8cf44c317 100644 --- a/packages/react-components/src/shared/src/useEventCallback.js +++ b/packages/react-components/src/shared/src/useEventCallback.ts @@ -4,7 +4,7 @@ import { isNil } from "lodash"; import { useCallback } from "react"; import { useCommittedRef } from "./useCommittedRef"; -export function useEventCallback(callback) { +export function useEventCallback(callback: (...args: any[]) => void): (...args: any[]) => void { const ref = useCommittedRef(callback); return useCallback((...args) => { diff --git a/packages/react-components/src/shared/src/useEventListener.js b/packages/react-components/src/shared/src/useEventListener.ts similarity index 63% rename from packages/react-components/src/shared/src/useEventListener.js rename to packages/react-components/src/shared/src/useEventListener.ts index f76f76639..c99f28641 100644 --- a/packages/react-components/src/shared/src/useEventListener.js +++ b/packages/react-components/src/shared/src/useEventListener.ts @@ -1,7 +1,7 @@ import { isFunction, isNil } from "lodash"; import { useCallback, useEffect } from "react"; -export function useEventListener(eventTarget, eventName, listener, active = true, capture = false) { +export function useEventListener(eventTarget: EventTarget | (() => EventTarget), eventName: string, listener: EventListenerOrEventListenerObject | null, active = true, capture = false): void { useEffect(() => { const target = isFunction(eventTarget) ? eventTarget() : eventTarget; @@ -19,13 +19,13 @@ export function useEventListener(eventTarget, eventName, listener, active = true }, [eventTarget, eventName, listener, active, capture]); } -export function useDocumentListener(eventName, listener, active, capture) { +export function useDocumentListener(eventName: string, listener: EventListenerOrEventListenerObject | null, active: boolean, capture: boolean): void { const documentTarget = useCallback(() => document, []); useEventListener(documentTarget, eventName, listener, active, capture); } -export function useWindowListener(eventName, listener, active, capture) { +export function useWindowListener(eventName: string, listener: EventListenerOrEventListenerObject | null, active: boolean, capture: boolean): void { const documentTarget = useCallback(() => window, []); useEventListener(documentTarget, eventName, listener, active, capture); diff --git a/packages/react-components/src/shared/src/useFocusManager.js b/packages/react-components/src/shared/src/useFocusManager.ts similarity index 73% rename from packages/react-components/src/shared/src/useFocusManager.js rename to packages/react-components/src/shared/src/useFocusManager.ts index 8b5713a8b..a33d63442 100644 --- a/packages/react-components/src/shared/src/useFocusManager.js +++ b/packages/react-components/src/shared/src/useFocusManager.ts @@ -1,17 +1,18 @@ +import { FocusScope } from "./useFocusScope"; import { FocusTarget } from "./focusTarget"; import { isFunction, isNil } from "lodash"; import { useMemo } from "react"; -class ElementIterator { +class ElementIterator { _elements; _index; - constructor(elements, { from = -1 } = {}) { + constructor(elements: T[], { from = -1 } = {}) { this._elements = elements; this._index = from; } - next() { + next(): T { if (this._index < this._elements.length - 1) { return this._elements[++this._index]; } @@ -19,7 +20,7 @@ class ElementIterator { return null; } - previous() { + previous(): T { if (this._index > 0) { return this._elements[--this._index]; } @@ -27,25 +28,35 @@ class ElementIterator { return null; } - reset({ from = -1 } = {}) { + reset({ from = -1 } = {}): void { this._index = from; } - get currentIndex() { + get currentIndex(): number { return this._index; } } +export interface FocusManagerOptions { + keyProp?: string; +} + +export interface FocusOptions { + onFocus?(element?: HTMLElement): void + onNotFound?(): void + canFocus?(element: HTMLElement): boolean; +} + export class FocusManager { _scope; _keyProp; - constructor(scope, { keyProp } = {}) { + constructor(scope: FocusScope, { keyProp }: FocusManagerOptions = {}) { this._scope = scope; this._keyProp = keyProp; } - _focusElement(element, { onFocus, onNotFound } = {}) { + _focusElement(element: HTMLElement, { onFocus, onNotFound }: FocusOptions = {}): HTMLElement { if (!isNil(element)) { if (isFunction(element.focus)) { element.focus(); @@ -63,7 +74,7 @@ export class FocusManager { return element; } - focusFirst({ canFocus, ...options } = {}) { + focusFirst({ canFocus, ...options }: FocusOptions = {}): HTMLElement { const { elements } = this._scope; let target; @@ -75,17 +86,17 @@ export class FocusManager { else { const iterator = new ElementIterator(elements); - do { target = iterator.next(); } while(!isNil(target) && !canFocus(target)); + do { target = iterator.next(); } while (!isNil(target) && !canFocus(target)); } } return this._focusElement(target, options); } - focusLast({ canFocus, ...options } = {}) { + focusLast({ canFocus, ...options }: FocusOptions = {}): HTMLElement { const { elements } = this._scope; - let target; + let target: HTMLElement; if (elements.length > 0) { if (isNil(canFocus)) { @@ -94,14 +105,14 @@ export class FocusManager { else { const iterator = new ElementIterator(elements, { from: elements.length }); - do { target = iterator.previous(); } while(!isNil(target) && !canFocus(target)); + do { target = iterator.previous(); } while (!isNil(target) && !canFocus(target)); } } return this._focusElement(target, options); } - focusNext({ canFocus, ...options } = {}) { + focusNext({ canFocus, ...options }: FocusOptions = {}): HTMLElement { const { elements } = this._scope; let target; @@ -111,7 +122,7 @@ export class FocusManager { canFocus = !isNil(canFocus) ? canFocus : () => true; - const index = elements.indexOf(document.activeElement); + const index = elements.indexOf(document.activeElement as HTMLElement); const iterator = new ElementIterator(elements, { from: index !== -1 ? index : undefined }); do { @@ -130,13 +141,13 @@ export class FocusManager { if (!isNil(target) && !canFocus(target)) { target = null; } - } while(isNil(target) && !hasLooped); + } while (isNil(target) && !hasLooped); } return this._focusElement(target, options); } - focusPrevious({ canFocus, ...options } = {}) { + focusPrevious({ canFocus, ...options }: FocusOptions = {}): HTMLElement { const { elements } = this._scope; let target; @@ -146,7 +157,7 @@ export class FocusManager { canFocus = !isNil(canFocus) ? canFocus : () => true; - const index = elements.indexOf(document.activeElement); + const index = elements.indexOf(document.activeElement as HTMLElement); const iterator = new ElementIterator(elements, { from: index !== -1 ? index : undefined }); do { @@ -165,13 +176,13 @@ export class FocusManager { if (!isNil(target) && !canFocus(target)) { target = null; } - } while(isNil(target) && !hasLooped); + } while (isNil(target) && !hasLooped); } return this._focusElement(target, options); } - focusKey(key, options) { + focusKey(key: FocusTarget, options: FocusOptions): HTMLElement { const { elements } = this._scope; if (isNil(this._keyProp)) { @@ -181,7 +192,7 @@ export class FocusManager { return this._focusElement(elements.find(x => x.getAttribute(this._keyProp) === key?.toString()), options); } - focusTarget(target, options) { + focusTarget(target: FocusTarget, options: FocusOptions): HTMLElement { switch (target) { case FocusTarget.first: return this.focusFirst(options); @@ -192,17 +203,17 @@ export class FocusManager { } } - search(query, options) { + search(query: string, options: FocusOptions): HTMLElement { const { elements } = this._scope; return this._focusElement(elements.find(x => x.textContent?.toLowerCase().startsWith(query)), options); } - hasFocus() { - return this._scope.isInScope(document.activeElement); + hasFocus(): boolean { + return this._scope.isInScope(document.activeElement as HTMLElement); } } -export function useFocusManager(scope, { keyProp } = {}) { +export function useFocusManager(scope: FocusScope, { keyProp }: FocusManagerOptions = {}): FocusManager { return useMemo(() => new FocusManager(scope, { keyProp }), [scope, keyProp]); } diff --git a/packages/react-components/src/shared/src/useFocusScope.js b/packages/react-components/src/shared/src/useFocusScope.js deleted file mode 100644 index 2833c6620..000000000 --- a/packages/react-components/src/shared/src/useFocusScope.js +++ /dev/null @@ -1,89 +0,0 @@ -import { createContext, useCallback, useContext, useMemo } from "react"; -import { isNil } from "lodash"; -import { useRefState } from "./useRefState"; -import { walkFocusableElements } from "./focusableTreeWalker"; - -class DomScope { - _scopeRef; - _handlersRef; - - constructor(scopeRef, handlersRef) { - this._scopeRef = scopeRef; - this._handlersRef = handlersRef; - } - - get elements() { - return this._scopeRef.current; - } - - registerChangeHandler(handler) { - this._handlersRef.current.push(handler); - } - - removeChangeHandler(handler) { - const handlers = this._handlersRef.current; - - handlers.splice(handlers.indexOf(handler), 1); - } - - isInScope(element) { - return this.elements.some(x => x.contains(element)); - } -} - -export function useFocusScope() { - const [scopeRef, setScope] = useRefState([]); - const [handlersRef] = useRefState([]); - - const setRef = useCallback(rootElement => { - const setElements = elements => { - handlersRef.current.forEach(x => { - x(elements, scopeRef.current); - }); - - setScope(elements); - }; - - const parseElements = () => { - const scope = []; - - walkFocusableElements(rootElement, x => { - scope.push(x); - }); - - setElements(scope); - }; - - // Watch for dynamic elements. - const mutationObserver = new MutationObserver(() => { - parseElements(); - }); - - if (rootElement) { - // Parse initial elements. - parseElements(); - - mutationObserver.observe(rootElement, { - subtree: true, - childList: true - }); - } else { - mutationObserver.disconnect(); - setElements([]); - } - }, [scopeRef, setScope, handlersRef]); - - const scope = useMemo(() => new DomScope(scopeRef, handlersRef), [scopeRef, handlersRef]); - - const { scope: contextScope } = useFocusContext(); - - return isNil(contextScope) - ? [scope, setRef] - : [contextScope, undefined]; -} - -export const FocusContext = createContext({}); - -export function useFocusContext() { - return useContext(FocusContext) ?? {}; -} diff --git a/packages/react-components/src/shared/src/useFocusScope.ts b/packages/react-components/src/shared/src/useFocusScope.ts new file mode 100644 index 000000000..a894952c2 --- /dev/null +++ b/packages/react-components/src/shared/src/useFocusScope.ts @@ -0,0 +1,103 @@ +import { RefObject, createContext, useCallback, useContext, useMemo } from "react"; +import { isNil } from "lodash"; +import { useRefState } from "./useRefState"; +import { walkFocusableElements } from "./focusableTreeWalker"; + +export type ChangeEventHandler = (elements: HTMLElement[], scope: HTMLElement[]) => void; + +export interface FocusScope { + elements: HTMLElement[]; + isInScope: (element: HTMLElement) => boolean; + registerChangeHandler: (onChangeHandler: ChangeEventHandler) => void; + removeChangeHandler: (onChangeHandler: ChangeEventHandler) => void; +} + + +class DomScope implements FocusScope { + _scopeRef: RefObject; + _handlersRef: RefObject; + + constructor(scopeRef: RefObject, handlersRef: RefObject) { + this._scopeRef = scopeRef; + this._handlersRef = handlersRef; + } + + get elements(): HTMLElement[] { + return this._scopeRef.current; + } + + registerChangeHandler(handler: ChangeEventHandler): void { + this._handlersRef.current.push(handler); + } + + removeChangeHandler(handler: ChangeEventHandler): void { + const handlers = this._handlersRef.current; + + handlers.splice(handlers.indexOf(handler), 1); + } + + isInScope(element: HTMLElement): boolean { + return this.elements.some(x => x.contains(element)); + } +} + +interface FocusContextProps { + scope?: FocusScope +} + +export const FocusContext = createContext({}); + +export function useFocusContext(): FocusContextProps { + return useContext(FocusContext) ?? {}; +} + +export function useFocusScope(): [FocusScope, (rootElement: HTMLElement) => void] { + const [scopeRef, setScope] = useRefState([]); + const [handlersRef] = useRefState([]); + + const setRef = useCallback((rootElement: HTMLElement) => { + const setElements = (elements: HTMLElement[]): void => { + handlersRef.current.forEach(x => { + x(elements, scopeRef.current); + }); + + setScope(elements); + }; + + const parseElements = (): void => { + const scope: HTMLElement[] = []; + + walkFocusableElements(rootElement, x => { + scope.push(x as HTMLElement); + }); + + setElements(scope); + }; + + // Watch for dynamic elements. + const mutationObserver = new MutationObserver(() => { + parseElements(); + }); + + if (rootElement) { + // Parse initial elements. + parseElements(); + + mutationObserver.observe(rootElement, { + subtree: true, + childList: true + }); + } else { + mutationObserver.disconnect(); + setElements([]); + } + }, [scopeRef, setScope, handlersRef]); + + const scope: FocusScope = useMemo(() => new DomScope(scopeRef, handlersRef), [scopeRef, handlersRef]); + + const { scope: contextScope } = useFocusContext(); + + return isNil(contextScope) + ? [scope, setRef] + : [contextScope, undefined]; +} diff --git a/packages/react-components/src/shared/src/useForceRender.js b/packages/react-components/src/shared/src/useForceRender.ts similarity index 76% rename from packages/react-components/src/shared/src/useForceRender.js rename to packages/react-components/src/shared/src/useForceRender.ts index 3751f9426..eef0fac89 100644 --- a/packages/react-components/src/shared/src/useForceRender.js +++ b/packages/react-components/src/shared/src/useForceRender.ts @@ -1,6 +1,6 @@ import { useCallback, useState } from "react"; -export function useForceRender() { +export function useForceRender(): () => void { const [, set] = useState(false); return useCallback(() => { diff --git a/packages/react-components/src/shared/src/useForwardInputApi.js b/packages/react-components/src/shared/src/useForwardInputApi.js deleted file mode 100644 index 05c338915..000000000 --- a/packages/react-components/src/shared/src/useForwardInputApi.js +++ /dev/null @@ -1,25 +0,0 @@ -const API_METHODS = [ - "blur", - "focus", - "click", - "select", - "setRangeText", - "setSelectionRange", - "checkValidity", - "reportValidity", - "setCustomValidity" -]; - -export function useForwardInputApi(inputRef) { - return targetRef => { - const element = targetRef.current; - - API_METHODS.forEach(x => { - element[x] = (...args) => { - inputRef.current[x](...args); - }; - }); - - return element; - }; -} diff --git a/packages/react-components/src/shared/src/useForwardInputApi.ts b/packages/react-components/src/shared/src/useForwardInputApi.ts new file mode 100644 index 000000000..f63c7555d --- /dev/null +++ b/packages/react-components/src/shared/src/useForwardInputApi.ts @@ -0,0 +1,30 @@ +import { MutableRefObject } from "react"; + +const API_METHODS = [ + "blur", + "focus", + "click", + "select", + "setRangeText", + "setSelectionRange", + "checkValidity", + "reportValidity", + "setCustomValidity" +] as const; + +export function useForwardInputApi(inputRef: MutableRefObject) { + return (targetRef: MutableRefObject): HTMLInputElement => { + const element = targetRef.current; + + API_METHODS.forEach(x => { + element[x] = ((...args: any[]) => { + // we know the args passed here will match the one needed. Disable TS check + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + inputRef.current[x](...args); + }) as any; + }); + + return element; + }; +} diff --git a/packages/react-components/src/shared/src/useHasChild.js b/packages/react-components/src/shared/src/useHasChild.ts similarity index 70% rename from packages/react-components/src/shared/src/useHasChild.js rename to packages/react-components/src/shared/src/useHasChild.ts index 67ee465be..247f7830b 100644 --- a/packages/react-components/src/shared/src/useHasChild.js +++ b/packages/react-components/src/shared/src/useHasChild.ts @@ -1,9 +1,9 @@ // These hooks are a "temporary" solution until CSS Selector 4 (and :has with complex combinators) is available. +import { RefObject, useLayoutEffect, useState } from "react"; import { isNil } from "lodash"; -import { useLayoutEffect, useState } from "react"; -export function useHasChild(querySelector, rootRef) { +export function useHasChild(querySelector: string, rootRef: RefObject): boolean { const [result, setResult] = useState(false); // No deps since it must be evaluated on every render to handled dynamically rendered elements. @@ -21,8 +21,8 @@ export function useHasChild(querySelector, rootRef) { * @example * const { hasIcon } = useHasChildren({ hasIcon: ".o-ui-lozenge-icon" }, ref); */ -export function useHasChildren(querySelectors, rootRef) { - const [queryResults, setResults] = useState({}); +export function useHasChildren(querySelectors: Record, rootRef: RefObject): Record { + const [queryResults, setResults] = useState>({}); // No deps since it must be evaluated on every render to handled dynamically rendered elements. // eslint-disable-next-line react-hooks/exhaustive-deps @@ -32,7 +32,7 @@ export function useHasChildren(querySelectors, rootRef) { if (!isNil(element)) { let isDirty = false; - const newResults = Object.keys(querySelectors).reduce((results, x) => { + const newResults = (Object.keys(querySelectors) as T[]).reduce((results: Record, x) => { const result = !isNil(element.querySelector(`:scope > ${querySelectors[x]}`)); isDirty = isDirty || queryResults[x] !== result; @@ -47,5 +47,6 @@ export function useHasChildren(querySelectors, rootRef) { } }); - return queryResults; + return queryResults as Record; } + diff --git a/packages/react-components/src/shared/src/useId.js b/packages/react-components/src/shared/src/useId.ts similarity index 75% rename from packages/react-components/src/shared/src/useId.js rename to packages/react-components/src/shared/src/useId.ts index 69ddac6df..4720556f8 100644 --- a/packages/react-components/src/shared/src/useId.js +++ b/packages/react-components/src/shared/src/useId.ts @@ -3,7 +3,7 @@ import { useId as useAutoId } from "@reach/auto-id"; /* This utility will initially trigger a re-render. */ -export function useId(userId, prefix) { +export function useId(userId: string, prefix?: string): string { const uuid = useAutoId(userId); return prefix ? `${prefix}-${uuid}` : uuid; diff --git a/packages/react-components/src/shared/src/useIsInitialRender.js b/packages/react-components/src/shared/src/useIsInitialRender.ts similarity index 84% rename from packages/react-components/src/shared/src/useIsInitialRender.js rename to packages/react-components/src/shared/src/useIsInitialRender.ts index 472b8f2bc..2d431dc08 100644 --- a/packages/react-components/src/shared/src/useIsInitialRender.js +++ b/packages/react-components/src/shared/src/useIsInitialRender.ts @@ -1,7 +1,7 @@ import { useEffect } from "react"; import { useRefState } from "./useRefState"; -export function useIsInitialRender() { +export function useIsInitialRender(): boolean { const [isInitialRef, setIsInitial] = useRefState(true); useEffect(() => { diff --git a/packages/react-components/src/shared/src/useKeyboardNavigation.js b/packages/react-components/src/shared/src/useKeyboardNavigation.ts similarity index 51% rename from packages/react-components/src/shared/src/useKeyboardNavigation.js rename to packages/react-components/src/shared/src/useKeyboardNavigation.ts index 1df7eeeec..ea0235e9c 100644 --- a/packages/react-components/src/shared/src/useKeyboardNavigation.js +++ b/packages/react-components/src/shared/src/useKeyboardNavigation.ts @@ -1,11 +1,29 @@ +import { KeyboardEvent, KeyboardEventHandler } from "react"; +import { Keys } from "./keys"; import { isNil } from "lodash"; import { useEventCallback } from "./useEventCallback"; +import type { FocusManager, FocusOptions } from "./useFocusManager"; -export function useKeyboardNavigation(focusManager, { previous = [], next = [], first = [], last = [] }, { onSelect } = {}) { - const handleKeyDown = useEventCallback(event => { +interface KeyboardNavigationOptions { + onSelect?(event: KeyboardEvent, element: Element): void; +} + +interface KeyboardNavigationBindings { + previous: Keys[]; + next: Keys[]; + first: Keys[]; + last: Keys[]; +} + +interface KeyboardNavigationAPI { + onKeyDown: (event: KeyboardEvent) => void; +} + +export function useKeyboardNavigation(focusManager: FocusManager, { previous = [], next = [], first = [], last = [] }: KeyboardNavigationBindings, { onSelect }: KeyboardNavigationOptions = {}): KeyboardNavigationAPI { + const handleKeyDown: KeyboardEventHandler = useEventCallback((event: KeyboardEvent) => { const keyCode = event.keyCode; - const handleFocus = element => { + const handleFocus: FocusOptions["onFocus"] = element => { if (!isNil(onSelect)) { onSelect(event, element); } diff --git a/packages/react-components/src/shared/src/useMediaQuery.js b/packages/react-components/src/shared/src/useMediaQuery.ts similarity index 83% rename from packages/react-components/src/shared/src/useMediaQuery.js rename to packages/react-components/src/shared/src/useMediaQuery.ts index 6a06db107..591f900b5 100644 --- a/packages/react-components/src/shared/src/useMediaQuery.js +++ b/packages/react-components/src/shared/src/useMediaQuery.ts @@ -2,7 +2,7 @@ import { isFunction } from "lodash"; import { useEffect, useState } from "react"; // Copied from https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/utils/src/useMediaQuery.ts -export function useMediaQuery(query) { +export function useMediaQuery(query: string): boolean { const supportsMatchMedia = isFunction(window?.matchMedia); const [matches, setMatches] = useState(() => @@ -18,13 +18,13 @@ export function useMediaQuery(query) { const mediaQueryList = window.matchMedia(query); - const onChange = event => { + const onChange = (event: MediaQueryListEvent): void => { setMatches(event.matches); }; mediaQueryList.addListener(onChange); - return () => { + return (): void => { mediaQueryList.removeListener(onChange); }; }, [supportsMatchMedia, query]); diff --git a/packages/react-components/src/shared/src/useMergedRefs.js b/packages/react-components/src/shared/src/useMergedRefs.ts similarity index 57% rename from packages/react-components/src/shared/src/useMergedRefs.js rename to packages/react-components/src/shared/src/useMergedRefs.ts index 87a0c23c1..14af2cd00 100644 --- a/packages/react-components/src/shared/src/useMergedRefs.js +++ b/packages/react-components/src/shared/src/useMergedRefs.ts @@ -1,7 +1,7 @@ +import { ForwardedRef, useCallback } from "react"; import { isFunction, isNil } from "lodash"; -import { useCallback } from "react"; -export function assignRef(ref, node) { +export function assignRef(ref: ForwardedRef, node: T): void { if (!isNil(ref)) { if (isFunction(ref)) { ref(node); @@ -11,9 +11,11 @@ export function assignRef(ref, node) { } } -export function mergeRefs(...refs) { - const mergedRef = current => { +export function mergeRefs(...refs: ForwardedRef[]): (current: T) => void { + const mergedRef = (current: T): void => { // Resulting callback function can be used has a ref. + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore mergedRef.current = current; refs @@ -26,7 +28,7 @@ export function mergeRefs(...refs) { return mergedRef; } -export function useMergedRefs(...refs) { +export function useMergedRefs(...refs: ForwardedRef[]): (current: T) => void { // eslint-disable-next-line react-hooks/exhaustive-deps return useCallback(mergeRefs(...refs), refs); } diff --git a/packages/react-components/src/shared/src/useRefState.js b/packages/react-components/src/shared/src/useRefState.js deleted file mode 100644 index 51e56a94e..000000000 --- a/packages/react-components/src/shared/src/useRefState.js +++ /dev/null @@ -1,18 +0,0 @@ -import { useCallback, useRef } from "react"; -import { useForceRender } from "./useForceRender"; - -export function useRefState(initialValue) { - const rerender = useForceRender(); - - const valueRef = useRef(initialValue); - - const setValue = useCallback((newValue, forceRender = false) => { - valueRef.current = newValue; - - if (forceRender) { - rerender(); - } - }, [valueRef, rerender]); - - return [valueRef, setValue]; -} diff --git a/packages/react-components/src/shared/src/useRefState.ts b/packages/react-components/src/shared/src/useRefState.ts new file mode 100644 index 000000000..064015104 --- /dev/null +++ b/packages/react-components/src/shared/src/useRefState.ts @@ -0,0 +1,18 @@ +import { MutableRefObject, useCallback, useRef } from "react"; +import { useForceRender } from "./useForceRender"; + +export function useRefState(initialValue: T): [MutableRefObject, (newValue: T, forceRender?: boolean) => void] { + const rerender = useForceRender(); + + const valueRef = useRef(initialValue); + + const setValue = useCallback((newValue: T, forceRender = false) => { + valueRef.current = newValue; + + if (forceRender) { + rerender(); + } + }, [valueRef, rerender]); + + return [valueRef, setValue]; +} diff --git a/packages/react-components/src/shared/src/useResizeObserver.js b/packages/react-components/src/shared/src/useResizeObserver.ts similarity index 69% rename from packages/react-components/src/shared/src/useResizeObserver.js rename to packages/react-components/src/shared/src/useResizeObserver.ts index 3e817898f..dae0af945 100644 --- a/packages/react-components/src/shared/src/useResizeObserver.js +++ b/packages/react-components/src/shared/src/useResizeObserver.ts @@ -3,11 +3,11 @@ import { isFunction, isNil } from "lodash"; import { useEffect } from "react"; -const handlersMap = new WeakMap(); +const handlersMap = new WeakMap void>(); -let observer; +let observer: ResizeObserver; -function getResizeObserver() { +function getResizeObserver(): ResizeObserver { return (observer = observer || new ResizeObserver(entries => { entries.forEach(entry => { @@ -21,7 +21,11 @@ function getResizeObserver() { ); } -export const useResizeObserver = (element, onResize, { isDisabled, box } = {}) => { +interface UseResizeObserverOptions extends ResizeObserverOptions { + isDisabled?: boolean; +} + +export const useResizeObserver = (element: Element, onResize: (entry: ResizeObserverEntry) => void, { isDisabled, box }: UseResizeObserverOptions = {}): void => { useEffect(() => { if (!isDisabled) { if (!isNil(element)) { @@ -30,8 +34,7 @@ export const useResizeObserver = (element, onResize, { isDisabled, box } = {}) = handlersMap.set(element, onResize); } - return () => { - + return (): void => { if (!isNil(element)) { handlersMap.delete(element); diff --git a/packages/react-components/src/shared/src/useRovingFocus.js b/packages/react-components/src/shared/src/useRovingFocus.ts similarity index 73% rename from packages/react-components/src/shared/src/useRovingFocus.js rename to packages/react-components/src/shared/src/useRovingFocus.ts index 03a53bf34..ae99199c4 100644 --- a/packages/react-components/src/shared/src/useRovingFocus.js +++ b/packages/react-components/src/shared/src/useRovingFocus.ts @@ -1,29 +1,30 @@ import { isNil } from "lodash"; import { useLayoutEffect } from "react"; +import type { ChangeEventHandler, FocusScope } from "./useFocusScope"; -export function useRovingFocus(scope) { +export function useRovingFocus(scope: FocusScope): void { useLayoutEffect(() => { - const handleFocus = event => { + const handleFocus = (event: FocusEvent): void => { scope.elements.forEach(x => { if (x.tabIndex === 0) { x.tabIndex = -1; } }); - event.target.tabIndex = 0; + (event.target as HTMLElement).tabIndex = 0; }; - const registerElement = (element, isTabbable) => { + const registerElement = (element: HTMLElement, isTabbable: boolean): void => { element.tabIndex = isTabbable ? 0 : -1; element.addEventListener("focusin", handleFocus, { capture: true }); }; - const disposeElement = element => { + const disposeElement = (element: HTMLElement): void => { element.removeEventListener("focusin", handleFocus, { capture: true }); }; - const initializeElements = () => { + const initializeElements = (): void => { scope.elements.forEach((x, index) => { registerElement(x, index === 0); }); @@ -31,7 +32,7 @@ export function useRovingFocus(scope) { initializeElements(); - const onChange = (newElements, oldElements) => { + const onChange: ChangeEventHandler = (newElements, oldElements) => { oldElements.forEach(disposeElement); const tabbableIndex = newElements.findIndex(x => x.tabIndex === 0); @@ -44,7 +45,7 @@ export function useRovingFocus(scope) { scope.registerChangeHandler(onChange); - return () => { + return (): void => { scope.elements.forEach(disposeElement); scope.removeChangeHandler(onChange); }; @@ -54,9 +55,9 @@ export function useRovingFocus(scope) { /* IMPORTANT: Keyed roving focus doesn't handle disabled elements. This is the responsability of the calling component to ensure that the `currentKey` doesn't match a disabled element. */ -export function useKeyedRovingFocus(scope, currentKey, { keyProp = "value" } = {}) { +export function useKeyedRovingFocus(scope: FocusScope, currentKey: string, { keyProp = "value" } = {}): void { useLayoutEffect(() => { - const setTabIndexes = elements => { + const setTabIndexes = (elements: HTMLElement[]): void => { if (!isNil(currentKey)) { const tabbableIndex = !isNil(currentKey) ? elements.findIndex(x => x.getAttribute(keyProp) === currentKey.toString()) @@ -73,19 +74,19 @@ export function useKeyedRovingFocus(scope, currentKey, { keyProp = "value" } = { } }; - const initializeElements = () => { + const initializeElements = (): void => { setTabIndexes(scope.elements); }; initializeElements(); - const onChange = newElements => { + const onChange = (newElements: HTMLElement[]): void => { setTabIndexes(newElements); }; scope.registerChangeHandler(onChange); - return () => { + return (): void => { scope.removeChangeHandler(onChange); }; }, [scope, currentKey, keyProp]); diff --git a/packages/react-components/src/tags-picker/src/monkey-patch-dropdown.tsx b/packages/react-components/src/tags-picker/src/monkey-patch-dropdown.tsx index 59daaf23f..d6b5bf5a9 100644 --- a/packages/react-components/src/tags-picker/src/monkey-patch-dropdown.tsx +++ b/packages/react-components/src/tags-picker/src/monkey-patch-dropdown.tsx @@ -8,7 +8,7 @@ import keyboardKey from "keyboard-key"; // Sadly, specifying "search" doesn't work for us since it renders the dropdown as a "combolist" instead of a "listbox" and it cause a // whole new set of problems. export class MonkeyPatchDropdown extends Dropdown { - selectItemOnEnter = (e: any) => { + selectItemOnEnter = (e: any): void => { const { search } = this.props; if (keyboardKey.getCode(e) !== keyboardKey.Enter) { diff --git a/tsconfig.json b/tsconfig.json index 8a647a3b6..77b179381 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,7 @@ { "compilerOptions": { + "target": "es6", + "moduleResolution": "node", "skipLibCheck": true, // Skip type checking of all declaration files "allowSyntheticDefaultImports": true, // Allow default imports from modules with no default export "noImplicitAny": true, @@ -9,7 +11,7 @@ // "strict": true, // Enabling --strict enables --noImplicitAny, --noImplicitThis, --alwaysStrict, --strictBindCallApply, --strictNullChecks, --strictFunctionTypes and --strictPropertyInitialization. // the bare minimum for our project - "jsx": "react", + "jsx": "react-jsx", "outDir": "./dist", "allowJs": true, "esModuleInterop": true, diff --git a/yarn.lock b/yarn.lock index 55021e241..bcfb44e86 100644 --- a/yarn.lock +++ b/yarn.lock @@ -135,9 +135,9 @@ semver "^6.3.0" "@babel/generator@^7.12.1", "@babel/generator@^7.12.13", "@babel/generator@^7.12.5": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.13.tgz#5f6ebe6c85db99886db2d7b044409196f872a503" - integrity sha512-9qQ8Fgo8HaSvHEt6A5+BATP7XktD/AdAnObUeTRz5/e2y3kbrxZgz32qUJJsdmwUvBJzF4AeV21nGTNwv05Mpw== + version "7.12.15" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.15.tgz#4617b5d0b25cc572474cc1aafee1edeaf9b5368f" + integrity sha512-6F2xHxBiFXWNSGb7vyCUTBF8RCLY66rS0zEPcP8t/nQyXjha5EuK4z7H5o7fWG8B4M7y6mqVWq1J+1PuwRhecQ== dependencies: "@babel/types" "^7.12.13" jsesc "^2.5.1" @@ -342,9 +342,9 @@ js-tokens "^4.0.0" "@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.12.3", "@babel/parser@^7.12.7": - version "7.12.14" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.14.tgz#4adb7c5eef1d437ef965ad1569cd826db8c11dc9" - integrity sha512-xcfxDq3OrBnDsA/Z8eK5/2iPcLD8qbOaSSfOw4RA6jp4i7e6dEQ7+wTwxItEwzcXPQcsry5nZk96gmVPKletjQ== + version "7.12.15" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.15.tgz#2b20de7f0b4b332d9b119dd9c33409c538b8aacf" + integrity sha512-AQBOU2Z9kWwSZMd6lNjCX0GUgFonL1wAM1db8L8PMk9UDaGsRCArBkU4Sc+UCM3AE4hjbXx+h58Lb3QT4oRmrA== "@babel/plugin-proposal-async-generator-functions@^7.12.1", "@babel/plugin-proposal-async-generator-functions@^7.12.13": version "7.12.13" @@ -2585,9 +2585,9 @@ yargs "^15.3.0" "@netlify/functions-utils@^1.3.2": - version "1.3.10" - resolved "https://registry.yarnpkg.com/@netlify/functions-utils/-/functions-utils-1.3.10.tgz#8a32f9134102fa957b8d599227da14d461dd206b" - integrity sha512-cakXwiNWNau80ZLU33nbmBxNfFmMwrwgy+P9U9ep3NXxocWJeMVjCPoXzpoE3VydnOoyVJNy6erTziNdOVykEA== + version "1.3.11" + resolved "https://registry.yarnpkg.com/@netlify/functions-utils/-/functions-utils-1.3.11.tgz#27dc85aae951f281a0a64294ee976724defbeb2d" + integrity sha512-cGVOQ2BubMHfUNAGpqAcFmpAm2gh1A1aDD0cIMvZ48bIve0153AYCSvQXVFBqxxdLQbcfN2VHUd9LkSdu9+Hyg== dependencies: "@netlify/zip-it-and-ship-it" "^2.1.3" cpy "^8.1.0" @@ -2699,16 +2699,17 @@ unixify "^1.0.0" yargs "^15.4.1" -"@netlify/zip-it-and-ship-it@^2.1.3": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@netlify/zip-it-and-ship-it/-/zip-it-and-ship-it-2.1.3.tgz#573fd7e0ff4f29a6023614a78972f83f138e995d" - integrity sha512-nYHM4dnlua/aCe74ZPZcIlWAN1QbyGDaWbJi+Qkb0VSe4yX6PYvPNeymABggDbA9xFhk+nEA98wSu2A/beHPfQ== +"@netlify/zip-it-and-ship-it@^2.1.3", "@netlify/zip-it-and-ship-it@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@netlify/zip-it-and-ship-it/-/zip-it-and-ship-it-2.2.0.tgz#c081370e0c2270d3db6e8814e5b4bdce68526a95" + integrity sha512-DRiZVqlD/fFOAARPjsTwxAIUCZ+tnRgvdQGQbBqhqqdIo9ARjgYbPQj3zdSgBgOEjLMgx8jDv60iu/BGK1LQqg== dependencies: archiver "^4.0.0" common-path-prefix "^2.0.0" cp-file "^7.0.0" elf-cam "^0.1.1" end-of-stream "^1.4.4" + esbuild "^0.8.36" find-up "^4.1.0" glob "^7.1.6" junk "^3.1.0" @@ -3161,6 +3162,11 @@ dependencies: any-observable "^0.3.0" +"@scarf/scarf@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@scarf/scarf/-/scarf-1.1.0.tgz#b84b4a91cd938a688d36245b7a7db6fbc476a499" + integrity sha512-b2iE8kjjzzUo2WZ0xuE2N77kfnTds7ClrDxcz3Atz7h2XrNVoAPUoT75i7CY0st5x++70V91Y+c6RpBX9MX7Jg== + "@semantic-ui-react/event-stack@^3.1.0": version "3.1.2" resolved "https://registry.yarnpkg.com/@semantic-ui-react/event-stack/-/event-stack-3.1.2.tgz#14fac9796695aa3967962d94ea9733a85325f9c4" @@ -3181,15 +3187,24 @@ dependencies: eslint-plugin-lodash "*" -"@sharegate/eslint-config-react@2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@sharegate/eslint-config-react/-/eslint-config-react-2.0.0.tgz#13385abcf82fe50c838742d917235bc9f3f08493" - integrity sha512-5KTQcB1cR0Am8bE4UNdLRHuE3uPjvo4Q0BkQyZYKIe0zwjtiO6vE2rNT+pwiR6z0tg2ACj+FLiiHzb+dYxflkQ== +"@sharegate/eslint-config-react@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@sharegate/eslint-config-react/-/eslint-config-react-2.1.0.tgz#c9e0ad1938f69ade705cfbe6d0a11dc7d80045b7" + integrity sha512-mG/9oRNeYvg+uLIeA5DNOF+Mr09r0VYnD6YKjFJu9P7Uk7bEzyvZ1Gl869jR58q7EWCzT1Sc30Vk4xjK5SKk3A== dependencies: + "@sharegate/eslint-config-recommended" "*" + "@sharegate/eslint-config-sort-imports" "*" eslint-plugin-jsx-a11y "*" eslint-plugin-react "*" eslint-plugin-react-hooks "*" +"@sharegate/eslint-config-recommended@*": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@sharegate/eslint-config-recommended/-/eslint-config-recommended-1.1.1.tgz#2d35f0efbf2b6ab7f45e128e11c98763445a9beb" + integrity sha512-/PmVHkmjVVoVf855ud4mWRXYBnuZ5ZSzOuxDgjj0HfOsF6Q//2JIHHohheqM9F5LBOOIjZ0TULfp1cSxgyzT8Q== + dependencies: + eslint-plugin-import "2.22.0" + "@sharegate/eslint-config-recommended@1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@sharegate/eslint-config-recommended/-/eslint-config-recommended-1.1.0.tgz#2bc40614b0c742090619f68c43df55b6cd749fe8" @@ -3197,6 +3212,13 @@ dependencies: eslint-plugin-import "*" +"@sharegate/eslint-config-sort-imports@*": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@sharegate/eslint-config-sort-imports/-/eslint-config-sort-imports-1.0.3.tgz#258d77dd92ede603a4ab543fc1ad490640ac83c0" + integrity sha512-wCIwKKDA4B8omudZinmSR/WonM5PJukcLugWtA44tzusj702Yu6FFJlSUzWevgdUwkRMhmiAgpPuZCAB/46z1Q== + dependencies: + eslint-plugin-sort-imports-es6-autofix "0.5.0" + "@sharegate/eslint-config-sort-imports@1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@sharegate/eslint-config-sort-imports/-/eslint-config-sort-imports-1.0.2.tgz#ffc9b1299ec957e020f4c70f12b931dc2e5c9f63" @@ -3204,13 +3226,14 @@ dependencies: eslint-plugin-sort-imports-es6-autofix "*" -"@sharegate/eslint-config-typescript@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@sharegate/eslint-config-typescript/-/eslint-config-typescript-1.0.0.tgz#712b602b5d4b8a38af4593a002cb79ff3e095051" - integrity sha512-7CaCnKwG0bXfi5FcTff7s1vuwP8nh76Ub8BB+84Ty3SCH+qE+qU69riRBAsiejoP7nAdpS4WeAQzUzeJdVTF7g== +"@sharegate/eslint-config-typescript@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@sharegate/eslint-config-typescript/-/eslint-config-typescript-1.3.0.tgz#cf9102588294dc680ff378b13def371a62f1c3f9" + integrity sha512-NX6FYDYnJwphSkoETwjfMCWJSA6K7atwUr3xnUbyUAtCZWgdKiDlp3xa4PZeqdmCvS7x8xX8iXolRxhIAectqg== dependencies: + "@sharegate/eslint-config-recommended" "*" + "@sharegate/eslint-config-sort-imports" "*" "@typescript-eslint/eslint-plugin" "*" - "@typescript-eslint/parser" "*" "@sharegate/stylelint-config-recommended@2.0.0": version "2.0.0" @@ -4327,9 +4350,9 @@ integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== "@types/prettier@^2.0.0": - version "2.1.6" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.1.6.tgz#f4b1efa784e8db479cdb8b14403e2144b1e9ff03" - integrity sha512-6gOkRe7OIioWAXfnO/2lFiv+SJichKVSys1mSsgyrYHSEjk8Ctv4tSR/Odvnu+HWlH2C8j53dahU03XmQdd5fA== + version "2.2.0" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.2.0.tgz#a4e8205a4955690eef712a6d0394a1d2e121e721" + integrity sha512-O3SQC6+6AySHwrspYn2UvC6tjo6jCTMMmylxZUFhE1CulVu5l3AxU6ca9lrJDTQDVllF62LIxVSx5fuYL6LiZg== "@types/prop-types@*": version "15.7.3" @@ -4377,6 +4400,13 @@ dependencies: "@types/react" "*" +"@types/react-is@17.0.0": + version "17.0.0" + resolved "https://registry.yarnpkg.com/@types/react-is/-/react-is-17.0.0.tgz#6b60190ae60591ae0c83d6f3854e61e08f5a7976" + integrity sha512-A0DQ1YWZ0RG2+PV7neAotNCIh8gZ3z7tQnDJyS2xRPDNtAtSPcJ9YyfMP8be36Ha0kQRzbZCrrTMznA4blqO5g== + dependencies: + "@types/react" "*" + "@types/react-outside-click-handler@*": version "1.3.0" resolved "https://registry.yarnpkg.com/@types/react-outside-click-handler/-/react-outside-click-handler-1.3.0.tgz#ccf0014032fc6ec286210f8a05d26a5c1f94cc96" @@ -4430,6 +4460,11 @@ dependencies: "@types/react" "*" +"@types/resize-observer-browser@0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@types/resize-observer-browser/-/resize-observer-browser-0.1.5.tgz#36d897708172ac2380cd486da7a3daf1161c1e23" + integrity sha512-8k/67Z95Goa6Lznuykxkfhq9YU3l1Qe6LNZmwde1u7802a3x8v44oq0j91DICclxatTr0rNnhXx7+VTIetSrSQ== + "@types/resolve@1.17.1": version "1.17.1" resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" @@ -4472,9 +4507,9 @@ "@types/react-test-renderer" "*" "@types/uglify-js@*": - version "3.11.1" - resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.11.1.tgz#97ff30e61a0aa6876c270b5f538737e2d6ab8ceb" - integrity sha512-7npvPKV+jINLu1SpSYVWG8KvyJBhBa8tmzMMdDoVc2pWUYHN8KIXlPJhjJ4LT97c4dXJA2SHL/q6ADbDriZN+Q== + version "3.12.0" + resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.12.0.tgz#2bb061c269441620d46b946350c8f16d52ef37c5" + integrity sha512-sYAF+CF9XZ5cvEBkI7RtrG9g2GtMBkviTnBxYYyq+8BWvO4QtXfwwR6a2LFwCi4evMKZfpv6U43ViYvv17Wz3Q== dependencies: source-map "^0.6.1" @@ -4534,12 +4569,12 @@ "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@*": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.14.2.tgz#47a15803cfab89580b96933d348c2721f3d2f6fe" - integrity sha512-uMGfG7GFYK/nYutK/iqYJv6K/Xuog/vrRRZX9aEP4Zv1jsYXuvFUMDFLhUnc8WFv3D2R5QhNQL3VYKmvLS5zsQ== + version "4.15.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.0.tgz#13a5a07cf30d0d5781e43480aa2a8d38d308b084" + integrity sha512-DJgdGZW+8CFUTz5C/dnn4ONcUm2h2T0itWD85Ob5/V27Ndie8hUoX5HKyGssvR8sUMkAIlUc/AMK67Lqa3kBIQ== dependencies: - "@typescript-eslint/experimental-utils" "4.14.2" - "@typescript-eslint/scope-manager" "4.14.2" + "@typescript-eslint/experimental-utils" "4.15.0" + "@typescript-eslint/scope-manager" "4.15.0" debug "^4.1.1" functional-red-black-tree "^1.0.1" lodash "^4.17.15" @@ -4547,52 +4582,51 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@4.14.2", "@typescript-eslint/experimental-utils@^4.0.1": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.14.2.tgz#9df35049d1d36b6cbaba534d703648b9e1f05cbb" - integrity sha512-mV9pmET4C2y2WlyHmD+Iun8SAEqkLahHGBkGqDVslHkmoj3VnxnGP4ANlwuxxfq1BsKdl/MPieDbohCEQgKrwA== +"@typescript-eslint/experimental-utils@4.15.0", "@typescript-eslint/experimental-utils@^4.0.1": + version "4.15.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.15.0.tgz#b87c36410a9b23f637689427be85007a2ec1a9c6" + integrity sha512-V4vaDWvxA2zgesg4KPgEGiomWEBpJXvY4ZX34Y3qxK8LUm5I87L+qGIOTd9tHZOARXNRt9pLbblSKiYBlGMawg== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.14.2" - "@typescript-eslint/types" "4.14.2" - "@typescript-eslint/typescript-estree" "4.14.2" + "@typescript-eslint/scope-manager" "4.15.0" + "@typescript-eslint/types" "4.15.0" + "@typescript-eslint/typescript-estree" "4.15.0" eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@*": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.14.2.tgz#31e216e4baab678a56e539f9db9862e2542c98d0" - integrity sha512-ipqSP6EuUsMu3E10EZIApOJgWSpcNXeKZaFeNKQyzqxnQl8eQCbV+TSNsl+s2GViX2d18m1rq3CWgnpOxDPgHg== +"@typescript-eslint/parser@4.15.0": + version "4.15.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.15.0.tgz#8df94365b4b7161f9e8514fe28aef19954810b6b" + integrity sha512-L6Dtbq8Bc7g2aZwnIBETpmUa9XDKCMzKVwAArnGp5Mn7PRNFjf3mUzq8UeBjL3K8t311hvevnyqXAMSmxO8Gpg== dependencies: - "@typescript-eslint/scope-manager" "4.14.2" - "@typescript-eslint/types" "4.14.2" - "@typescript-eslint/typescript-estree" "4.14.2" + "@typescript-eslint/scope-manager" "4.15.0" + "@typescript-eslint/types" "4.15.0" + "@typescript-eslint/typescript-estree" "4.15.0" debug "^4.1.1" -"@typescript-eslint/scope-manager@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.14.2.tgz#64cbc9ca64b60069aae0c060b2bf81163243b266" - integrity sha512-cuV9wMrzKm6yIuV48aTPfIeqErt5xceTheAgk70N1V4/2Ecj+fhl34iro/vIssJlb7XtzcaD07hWk7Jk0nKghg== +"@typescript-eslint/scope-manager@4.15.0": + version "4.15.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.15.0.tgz#c42703558ea6daaaba51a9c3a86f2902dbab9432" + integrity sha512-CSNBZnCC2jEA/a+pR9Ljh8Y+5TY5qgbPz7ICEk9WCpSEgT6Pi7H2RIjxfrrbUXvotd6ta+i27sssKEH8Azm75g== dependencies: - "@typescript-eslint/types" "4.14.2" - "@typescript-eslint/visitor-keys" "4.14.2" + "@typescript-eslint/types" "4.15.0" + "@typescript-eslint/visitor-keys" "4.15.0" -"@typescript-eslint/types@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.14.2.tgz#d96da62be22dc9dc6a06647f3633815350fb3174" - integrity sha512-LltxawRW6wXy4Gck6ZKlBD05tCHQUj4KLn4iR69IyRiDHX3d3NCAhO+ix5OR2Q+q9bjCrHE/HKt+riZkd1At8Q== +"@typescript-eslint/types@4.15.0": + version "4.15.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.15.0.tgz#3011ae1ac3299bb9a5ac56bdd297cccf679d3662" + integrity sha512-su4RHkJhS+iFwyqyXHcS8EGPlUVoC+XREfy5daivjLur9JP8GhvTmDipuRpcujtGC4M+GYhUOJCPDE3rC5NJrg== -"@typescript-eslint/typescript-estree@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.14.2.tgz#9c5ebd8cae4d7b014f890acd81e8e17f309c9df9" - integrity sha512-ESiFl8afXxt1dNj8ENEZT12p+jl9PqRur+Y19m0Z/SPikGL6rqq4e7Me60SU9a2M28uz48/8yct97VQYaGl0Vg== +"@typescript-eslint/typescript-estree@4.15.0": + version "4.15.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.0.tgz#402c86a7d2111c1f7a2513022f22a38a395b7f93" + integrity sha512-jG6xTmcNbi6xzZq0SdWh7wQ9cMb2pqXaUp6bUZOMsIlu5aOlxGxgE/t6L/gPybybQGvdguajXGkZKSndZJpksA== dependencies: - "@typescript-eslint/types" "4.14.2" - "@typescript-eslint/visitor-keys" "4.14.2" + "@typescript-eslint/types" "4.15.0" + "@typescript-eslint/visitor-keys" "4.15.0" debug "^4.1.1" globby "^11.0.1" is-glob "^4.0.1" - lodash "^4.17.15" semver "^7.3.2" tsutils "^3.17.1" @@ -4609,12 +4643,12 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/visitor-keys@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.14.2.tgz#997cbe2cb0690e1f384a833f64794e98727c70c6" - integrity sha512-KBB+xLBxnBdTENs/rUgeUKO0UkPBRs2vD09oMRRIkj5BEN8PX1ToXV532desXfpQnZsYTyLLviS7JrPhdL154w== +"@typescript-eslint/visitor-keys@4.15.0": + version "4.15.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.0.tgz#2a07768df30c8a5673f1bce406338a07fdec38ca" + integrity sha512-RnDtJwOwFucWFAMjG3ghCG/ikImFJFEg20DI7mn4pHEx3vC48lIAoyjhffvfHmErRDboUPC7p9Z2il4CLb7qxA== dependencies: - "@typescript-eslint/types" "4.14.2" + "@typescript-eslint/types" "4.15.0" eslint-visitor-keys "^2.0.0" "@ungap/from-entries@^0.2.1": @@ -5687,9 +5721,9 @@ autoprefixer@^9.5.1, autoprefixer@^9.7.2, autoprefixer@^9.8.6: postcss-value-parser "^4.1.0" aws-sdk@^2.689.0: - version "2.836.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.836.0.tgz#69a26db1beb3c139d67833bd3adc082f9e148777" - integrity sha512-lVOT5/yr9ONfbn6UXYYIdFlVIFmSoX0CnjAQzXkfcYg+k7CZklbqqVIdgdLoiQYwQGLceoWghSevPGe7fjFg9Q== + version "2.841.0" + resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.841.0.tgz#a29314f6696bdf02a4c952b6f7c791042fa61eaa" + integrity sha512-pMgFr0B4WFIZEKc6EPAcyrvafkqoE1JwU6DJuE4UmT2ntat87DnbWUzFRP2HB4HuJvP1F7KNmElMz8p8j8bkNg== dependencies: buffer "4.9.2" events "1.1.1" @@ -5712,9 +5746,9 @@ aws4@^1.8.0: integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== axe-core@^4.0.2: - version "4.1.1" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.1.1.tgz#70a7855888e287f7add66002211a423937063eaf" - integrity sha512-5Kgy8Cz6LPC9DJcNb3yjAXTu3XihQgEdnIg50c//zOC/MyLP0Clg+Y8Sh9ZjjnvBrDZU4DgXS9C3T9r4/scGZQ== + version "4.1.2" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.1.2.tgz#7cf783331320098bfbef620df3b3c770147bc224" + integrity sha512-V+Nq70NxKhYt89ArVcaNL9FDryB3vQOd+BFXZIfO3RP6rwtj+2yqqqdHEkacutglPaZLkJeuXKCjCJDMGPtPqg== axios@0.19.0: version "0.19.0" @@ -5983,11 +6017,6 @@ babel-plugin-react-docgen@^4.2.1: lodash "^4.17.15" react-docgen "^5.0.0" -babel-plugin-react-require@3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/babel-plugin-react-require/-/babel-plugin-react-require-3.1.3.tgz#ba3d7305b044a90c35c32c5a9ab943fd68e1638d" - integrity sha512-kDXhW2iPTL81x4Ye2aUMdEXQ56JP0sBJmRQRXJPH5FsNB7fOc/YCsHTqHv8IovPyw9Rk07gdd7MVUz8tUmRBCA== - babel-plugin-syntax-jsx@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" @@ -6235,9 +6264,9 @@ bl@^1.0.0: safe-buffer "^5.1.1" bl@^4.0.3: - version "4.0.4" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.4.tgz#f4fda39f81a811d0df6368c1ed91dae499d1c900" - integrity sha512-7tdr4EpSd7jJ6tuQ21vu2ke8w7pNEstzj1O8wwq6sNNzO3UDi5MA8Gny/gquCj7r2C6fHudg8tKRGyjRgmvNxQ== + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== dependencies: buffer "^5.5.0" inherits "^2.0.4" @@ -6803,14 +6832,14 @@ caniuse-api@^1.5.2: lodash.uniq "^4.5.0" caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: - version "1.0.30001183" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30001183.tgz#e3c39eeb1372c621af2e4ed29cebd0c93b31f029" - integrity sha512-Vh0OIg93dKq42DHBDqR0bXVlfX3grH6Lmfx2Wd2DnV3pIjXfLytURd4VHZfB8N1Zdp6Q1T2vun8ohYH5FUOMAw== + version "1.0.30001185" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30001185.tgz#7dd4979a73f60857f93dadd9a0fb8f72fca5aa64" + integrity sha512-U6cMo4IQCIOsYZSMKdOJqsw3bCI1e72NKdRKMET3D5ws03cmNL9FiBCvkH+QjF1ejiHb4b9qIgfLkoc6MmECjQ== caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000864, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001157, caniuse-lite@^1.0.30001181: - version "1.0.30001183" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001183.tgz#7a57ba9d6584119bb5f2bc76d3cc47ba9356b3e2" - integrity sha512-7JkwTEE1hlRKETbCFd8HDZeLiQIUcl8rC6JgNjvHCNaxOeNmQ9V4LvQXRUsKIV2CC73qKxljwVhToaA3kLRqTw== + version "1.0.30001185" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001185.tgz#3482a407d261da04393e2f0d61eefbc53be43b95" + integrity sha512-Fpi4kVNtNvJ15H0F6vwmXtb3tukv3Zg3qhKkOGUq7KJ1J6b9kf4dnNgtEAFXhRsJo0gNj9W60+wBvn0JcTvdTg== capture-exit@^2.0.0: version "2.0.0" @@ -9287,16 +9316,16 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= ejs@^3.1.2: - version "3.1.5" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.5.tgz#aed723844dc20acb4b170cd9ab1017e476a0d93b" - integrity sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w== + version "3.1.6" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.6.tgz#5bfd0a0689743bb5268b3550cceeebbc1702822a" + integrity sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw== dependencies: jake "^10.6.1" electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.47, electron-to-chromium@^1.3.591, electron-to-chromium@^1.3.649: - version "1.3.653" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.653.tgz#1d98400eba330538a7fe169808c6bf9d83c44450" - integrity sha512-LehOhcl74u9fkV9Un6WahJ+Xh+0FZLCCDnKYis1Olx1DX2ugRww5PJicE65OG8yznMj8EOQZRcz6FSV1xKxqsA== + version "1.3.660" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.660.tgz#bfa8ce23735391cbd1c75c38f483e3179d0e0370" + integrity sha512-UOSKNfUBY8FDOSo4mfaUsN3KftlNLcYOg9v5apqLvNcWj+Ogy/i9SEDMZpfSVOeDkOcpu9iusucX6jxTWzqGLA== elegant-spinner@^1.0.1: version "1.0.1" @@ -9613,6 +9642,11 @@ es6-weak-map@^2.0.1: es6-iterator "^2.0.3" es6-symbol "^3.1.1" +esbuild@^0.8.36: + version "0.8.43" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.8.43.tgz#19d79f8c6d1cc6dadd50942057a5aff906a1ecf2" + integrity sha512-ZVE2CpootS4jtnfV0bbtJdgRsHEXcMP0P7ZXGfTmNzzhBr2e5ag7Vp3ry0jmw8zduJz4iHzxg4m5jtPxWERz1w== + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -9655,7 +9689,7 @@ escodegen@^1.12.0, escodegen@^1.14.1, escodegen@^1.8.0: optionalDependencies: source-map "~0.6.1" -eslint-import-resolver-node@^0.3.4: +eslint-import-resolver-node@^0.3.3, eslint-import-resolver-node@^0.3.4: version "0.3.4" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA== @@ -9701,6 +9735,25 @@ eslint-plugin-import@*: resolve "^1.17.0" tsconfig-paths "^3.9.0" +eslint-plugin-import@2.22.0: + version "2.22.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.0.tgz#92f7736fe1fde3e2de77623c838dd992ff5ffb7e" + integrity sha512-66Fpf1Ln6aIS5Gr/55ts19eUuoDhAbZgnr6UxK5hbDx6l/QgQgx61AePq+BV4PP2uXQFClgMVzep5zZ94qqsxg== + dependencies: + array-includes "^3.1.1" + array.prototype.flat "^1.2.3" + contains-path "^0.1.0" + debug "^2.6.9" + doctrine "1.5.0" + eslint-import-resolver-node "^0.3.3" + eslint-module-utils "^2.6.0" + has "^1.0.3" + minimatch "^3.0.4" + object.values "^1.1.1" + read-pkg-up "^2.0.0" + resolve "^1.17.0" + tsconfig-paths "^3.9.0" + eslint-plugin-jest@24.1.3: version "24.1.3" resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-24.1.3.tgz#fa3db864f06c5623ff43485ca6c0e8fc5fe8ba0c" @@ -9774,7 +9827,7 @@ eslint-plugin-react@*, eslint-plugin-react@^7.20.6: resolve "^1.18.1" string.prototype.matchall "^4.0.2" -eslint-plugin-sort-imports-es6-autofix@*: +eslint-plugin-sort-imports-es6-autofix@*, eslint-plugin-sort-imports-es6-autofix@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/eslint-plugin-sort-imports-es6-autofix/-/eslint-plugin-sort-imports-es6-autofix-0.5.0.tgz#dabae09a457eac6e95c52d8edd7855f576d014b6" integrity sha512-KEX2Uz6bAs67jDYiH/OT1xz1E7AzIJJOIRg1F7OnFAfUVlpws3ldSZj5oZySRHfoVkWqDX9GGExYxckdLrWhwg== @@ -9949,9 +10002,9 @@ esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.0.1, esquery@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" - integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== dependencies: estraverse "^5.1.0" @@ -10604,9 +10657,9 @@ file-uri-to-path@1.0.0: integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== filelist@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.1.tgz#f10d1a3ae86c1694808e8f20906f43d4c9132dbb" - integrity sha512-8zSK6Nu0DQIC08mUC46sWGXi+q3GGpKydAG36k+JDba6VRpkevvOWUW5a/PhShij4+vHT9M+ghgG7eM+a9JDUQ== + version "1.0.2" + resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.2.tgz#80202f21462d4d1c2e214119b1807c1bc0380e5b" + integrity sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ== dependencies: minimatch "^3.0.4" @@ -11090,9 +11143,9 @@ fsevents@^1.2.7: nan "^2.12.1" fsevents@^2.1.2, fsevents@~2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.1.tgz#b209ab14c61012636c8863507edf7fb68cc54e9f" - integrity sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw== + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== function-bind@^1.1.1: version "1.1.1" @@ -11818,9 +11871,9 @@ graceful-fs@^3.0.0: natives "^1.1.3" graceful-fs@^4.0.0, graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.4: - version "4.2.4" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" - integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + version "4.2.6" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" + integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== graceful-fs@~1.2.0: version "1.2.3" @@ -12481,10 +12534,10 @@ hex-color-regex@^1.0.1: resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== -highlight.js@^10.1.1, highlight.js@~10.5.0: - version "10.5.0" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.5.0.tgz#3f09fede6a865757378f2d9ebdcbc15ba268f98f" - integrity sha512-xTmvd9HiIHR6L53TMC7TKolEj65zG1XU+Onr8oi86mYa+nLcIbxTTWkpW7CsEwv/vK7u1zb8alZIMLDqqN6KTw== +highlight.js@^10.1.1, highlight.js@~10.6.0: + version "10.6.0" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.6.0.tgz#0073aa71d566906965ba6e1b7be7b2682f5e18b6" + integrity sha512-8mlRcn5vk/r4+QcqerapwBYTe+iPL5ih6xrNylxrnBdHQiijDETfXX7VIxC3UiCRiINBJfANBAsPzAvRQj8RpQ== hmac-drbg@^1.0.1: version "1.0.1" @@ -15416,12 +15469,12 @@ lowercase-keys@^2.0.0: integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== lowlight@^1.14.0: - version "1.18.0" - resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.18.0.tgz#cfff11cfb125ca66f1c12cb43d27fff68cbeafa9" - integrity sha512-Zlc3GqclU71HRw5fTOy00zz5EOlqAdKMYhOFIO8ay4SQEDQgFuhR8JNwDIzAGMLoqTsWxe0elUNmq5o2USRAzw== + version "1.19.0" + resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.19.0.tgz#b8544199cafcf10c5731b21c7458c358f79a2a97" + integrity sha512-NIskvQ1d1ovKyUytkMpT8+8Bhq3Ub54os1Xp4RAC9uNbXH1YVRf5NERq7JNzapEe5BzUc1Cj4F0I+eLBBFj6hA== dependencies: fault "^1.0.0" - highlight.js "~10.5.0" + highlight.js "~10.6.0" lru-cache@2: version "2.7.3" @@ -15714,9 +15767,9 @@ mdast-util-to-hast@10.0.1: unist-util-visit "^2.0.0" mdast-util-to-markdown@^0.6.0: - version "0.6.4" - resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.4.tgz#1942cdf523942a6adf131ea09d6a915ae2eddbe5" - integrity sha512-iMH81C+5QUAjOsf4jj5XLSU9e+L1FAn427mliK1Z57FRMS5J2fyPJC0zZ2GYEXKp4IhrM9OF1i5mDu+W+Ey+Iw== + version "0.6.5" + resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz#b33f67ca820d69e6cc527a93d4039249b504bebe" + integrity sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ== dependencies: "@types/unist" "^2.0.0" longest-streak "^2.0.0" @@ -16562,12 +16615,12 @@ netlify@^4.1.7, netlify@^4.5.2: through2-map "^3.0.0" netlify@^6.0.0: - version "6.1.6" - resolved "https://registry.yarnpkg.com/netlify/-/netlify-6.1.6.tgz#c841438a802e04b5914b5d3af48d633ee2b0b0e8" - integrity sha512-hjXoiqKHetP+OD/DmOLHeTW/AZvsitFCz5d1mOAivrnQXVKrKRS6XHbsLELiUuXv8hW1PrWnImFF0VdLPKo0wA== + version "6.1.7" + resolved "https://registry.yarnpkg.com/netlify/-/netlify-6.1.7.tgz#4c7cac4efc979408966afa593c22a93721788b3a" + integrity sha512-6eSG7gtjOKNDUMjk/s35auWJJ4o03j+iy6eY4L3Fe2p0FoSm6x5wGk0ZCnD9o0QCleXubSJIPe6MCYa/fwdpqg== dependencies: "@netlify/open-api" "^1.3.0" - "@netlify/zip-it-and-ship-it" "^2.1.3" + "@netlify/zip-it-and-ship-it" "^2.2.0" backoff "^2.5.0" clean-deep "^3.4.0" flush-write-stream "^2.0.0" @@ -17962,11 +18015,12 @@ pnp-webpack-plugin@1.6.4: ts-pnp "^1.1.6" polished@^3.4.4: - version "3.6.7" - resolved "https://registry.yarnpkg.com/polished/-/polished-3.6.7.tgz#44cbd0047f3187d83db0c479ef0c7d5583af5fb6" - integrity sha512-b4OViUOihwV0icb9PHmWbR+vPqaSzSAEbgLskvb7ANPATVXGiYv/TQFHQo65S53WU9i5EQ1I03YDOJW7K0bmYg== + version "3.7.0" + resolved "https://registry.yarnpkg.com/polished/-/polished-3.7.0.tgz#ece3368df30d33082bc8a957aa212d3f98119278" + integrity sha512-1tnvQ2wsxfR/DyPE2Xu9sRbnLAwXAarCWiZJ8Hfirw59bTigqjbzEWSAmzYizT6ocQW995V8n7RP48jq50DjJA== dependencies: - "@babel/runtime" "^7.9.2" + "@babel/runtime" "^7.12.5" + "@scarf/scarf" "^1.1.0" popper.js@^1.14.4: version "1.16.1" @@ -18158,9 +18212,9 @@ postcss-load-config@^2.0.0: import-cwd "^2.0.0" postcss-load-config@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.0.0.tgz#850bb066edd65b734329eacf83af0c0764226c87" - integrity sha512-lErrN8imuEF1cSiHBV8MiR7HeuzlDpCGNtaMyYHlOBuJHHOGw6S4xOMZp8BbXPr7AGQp14L6PZDlIOpfFJ6f7w== + version "3.0.1" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.0.1.tgz#d214bf9cfec1608ffaf0f4161b3ba20664ab64b9" + integrity sha512-/pDHe30UYZUD11IeG8GWx9lNtu1ToyTsZHnyy45B4Mrwr/Kb6NgYl7k753+05CJNKnjbwh4975amoPJ+TEjHNQ== dependencies: cosmiconfig "^7.0.0" import-cwd "^3.0.0" @@ -18505,9 +18559,9 @@ postcss@^7.0.0, postcss@^7.0.14, postcss@^7.0.2, postcss@^7.0.21, postcss@^7.0.2 supports-color "^6.1.0" postcss@^8.1.0, postcss@^8.1.4: - version "8.2.4" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.4.tgz#20a98a39cf303d15129c2865a9ec37eda0031d04" - integrity sha512-kRFftRoExRVXZlwUuay9iC824qmXPcQQVzAjbCCgjpXnkdMCJYBu2gTwAaFBzv8ewND6O8xFb3aELmEkh9zTzg== + version "8.2.5" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.5.tgz#3c75149ada4e93db9521913654c0144517f77c9a" + integrity sha512-wMcb7BpDcm3gxQOQx46NDNT36Kk0Ao6PJLLI2ed5vehbbbxCEuslSQzbQ2sfSKy+gkYxhWcGWSeaK+gwm4KIZg== dependencies: colorette "^1.2.1" nanoid "^3.1.20" @@ -20293,9 +20347,9 @@ rollup-pluginutils@^2.8.1: estree-walker "^0.6.1" rollup@^2.23.1: - version "2.38.4" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.38.4.tgz#1b84ea8728c73b1a00a6a6e9c630ec8c3fe48cea" - integrity sha512-B0LcJhjiwKkTl79aGVF/u5KdzsH8IylVfV56Ut6c9ouWLJcUK17T83aZBetNYSnZtXf2OHD4+2PbmRW+Fp5ulg== + version "2.38.5" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.38.5.tgz#be41ad4fe0c103a8794377afceb5f22b8f603d6a" + integrity sha512-VoWt8DysFGDVRGWuHTqZzT02J0ASgjVq/hPs9QcBOGMd7B+jfTr/iqMVEyOi901rE3xq+Deq66GzIT1yt7sGwQ== optionalDependencies: fsevents "~2.3.1" @@ -22516,9 +22570,9 @@ typescript@4.1.3: integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg== typescript@^3.8.3, typescript@^3.9.7: - version "3.9.7" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa" - integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw== + version "3.9.8" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.8.tgz#7d937ba4e4044af7fa83d127b982f8f61ca816a4" + integrity sha512-nDbnFkUZZjkQ92qwKX+C+jtk4OGfU8H9toSEs3uAsl8cxLjG2sqQm6leF/pLWvm9FAEJ6KHkYMAbHYaY2ITeVg== uglify-js@^2.8.22: version "2.8.29" @@ -22531,9 +22585,9 @@ uglify-js@^2.8.22: uglify-to-browserify "~1.0.0" uglify-js@^3.0.5, uglify-js@^3.1.4: - version "3.12.6" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.12.6.tgz#f884584fcc42e10bca70db5cb32e8625c2c42535" - integrity sha512-aqWHe3DfQmZUDGWBbabZ2eQnJlQd1fKlMUu7gV+MiTuDzdgDw31bI3wA2jLLsV/hNcDP26IfyEgSVoft5+0SVw== + version "3.12.7" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.12.7.tgz#be4f06142a67bd91ef868b4e111dc241e151bff3" + integrity sha512-SIZhkoh+U/wjW+BHGhVwE9nt8tWJspncloBcFapkpGRwNPqcH8pzX36BXe3TPBjzHWPMUZotpCigak/udWNr1Q== uglify-to-browserify@~1.0.0: version "1.0.2"