diff --git a/.github/workflows/bench.yaml b/.github/workflows/bench.yaml index 2c0ec0e..92811a9 100644 --- a/.github/workflows/bench.yaml +++ b/.github/workflows/bench.yaml @@ -55,10 +55,8 @@ jobs: npm install ./build.sh - - name: Install B2 CLI - run: | - sudo pip install setuptools - sudo pip install --upgrade b2 + - name: Set up Backblaze B2 CLI + uses: wilsonzlin/setup-b2@v3 - name: Run bench and upload results working-directory: ./bench diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml index 4a378f8..756515b 100644 --- a/.github/workflows/cli.yml +++ b/.github/workflows/cli.yml @@ -55,15 +55,8 @@ jobs: - name: Build CLI working-directory: ./cli run: cargo build --release -vvv - - name: Install B2 CLI (macOS, Linux) - if: runner.os != 'Windows' - run: | - sudo pip install setuptools - sudo pip install --upgrade b2 - - name: Install B2 CLI (Windows) - if: runner.os == 'Windows' - run: | - pip install --upgrade b2 + - name: Set up Backblaze B2 CLI + uses: wilsonzlin/setup-b2@v3 - name: Upload to B2 run: | b2 authorize-account ${{ secrets.CICD_CLI_B2_KEY_ID }} ${{ secrets.CICD_CLI_B2_APPLICATION_KEY }} diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 49aa25a..e18ca7a 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -61,16 +61,8 @@ jobs: npm run build node compress.js - - name: Install B2 CLI (macOS, Linux) - if: runner.os != 'Windows' - run: | - sudo pip install setuptools - sudo pip install --upgrade b2 - - - name: Install B2 CLI (Windows) - if: runner.os == 'Windows' - run: | - pip install --upgrade b2 + - name: Set up Backblaze B2 CLI + uses: wilsonzlin/setup-b2@v3 - name: Upload to B2 shell: bash diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 4997bc6..63701cd 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -86,16 +86,8 @@ jobs: cargo build -vvv --release working-directory: ./ruby - - name: Install B2 CLI (macOS, Linux) - if: runner.os != 'Windows' - run: | - sudo pip install setuptools - sudo pip install --upgrade b2 - - - name: Install B2 CLI (Windows) - if: runner.os == 'Windows' - run: | - pip install --upgrade b2 + - name: Set up Backblaze B2 CLI + uses: wilsonzlin/setup-b2@v3 - name: Upload to B2 run: | @@ -115,10 +107,8 @@ jobs: uses: actions/setup-ruby@v1 with: ruby-version: '2.5' - - name: Install B2 CLI - run: | - sudo pip install setuptools - sudo pip install --upgrade b2 + - name: Set up Backblaze B2 CLI + uses: wilsonzlin/setup-b2@v3 - name: Pack and publish gem working-directory: ./ruby run: | diff --git a/gen/attrs.ts b/gen/attrs.ts index 25d443f..4d09f2a 100644 --- a/gen/attrs.ts +++ b/gen/attrs.ts @@ -1,127 +1,23 @@ -import {readFileSync, writeFileSync} from 'fs'; -import ts, {Node, SourceFile, SyntaxKind, Type} from 'typescript'; +import htmlData from '@wzlin/html-data'; +import {writeFileSync} from 'fs'; import {join} from 'path'; -import {DATA_DIR, prettyJson, RUST_OUT_DIR} from './_common'; - -const reactDeclarations = readFileSync(join(__dirname, 'data', 'react.d.ts'), 'utf8'); - -// TODO Consider and check behaviour when value matches case insensitively, after trimming whitespace, numerically (for number values), etc. -// TODO This file is currently manually sourced and written. Try to get machine-readable spec and automate. -const defaultAttributeValues: { - [attr: string]: { - tags: string[]; - defaultValue: string; - isPositiveInteger?: boolean; - }[]; -} = JSON.parse(readFileSync(join(DATA_DIR, 'attrs.json'), 'utf8')); - -const tagNameNormalised = { - 'anchor': 'a', -}; - -const attrNameNormalised = { - 'classname': 'class', -}; - -const reactSpecificAttributes = [ - 'defaultChecked', 'defaultValue', 'suppressContentEditableWarning', 'suppressHydrationWarning', -]; - -const collapsibleAndTrimmable = { - 'class': ['html:*'], - 'd': ['svg:*'], -}; - -// TODO Is escapedText the API for getting name? -const getNameOfNode = (n: any) => n.name.escapedText; -const normaliseName = (name: string, norms: { [name: string]: string }) => [name.toLowerCase()].map(n => norms[n] || n)[0]; - -type AttrConfig = { - boolean: boolean; - redundantIfEmpty: boolean; - collapseAndTrim: boolean; - defaultValue?: string; -}; +import {RUST_OUT_DIR} from './_common'; const rsTagAttr = ({ redundantIfEmpty, defaultValue, collapseAndTrim, boolean, -}: AttrConfig) => `AttributeMinification { boolean: ${boolean}, redundant_if_empty: ${redundantIfEmpty}, collapse_and_trim: ${collapseAndTrim}, default_value: ${defaultValue == undefined ? 'None' : `Some(b"${defaultValue}")`} }`; +}: { + boolean: boolean; + redundantIfEmpty: boolean; + collapseAndTrim: boolean; + defaultValue?: string; +}) => `AttributeMinification { boolean: ${boolean}, redundant_if_empty: ${redundantIfEmpty}, collapse_and_trim: ${collapseAndTrim}, default_value: ${defaultValue +== undefined ? 'None' : `Some(b"${defaultValue}")`} }`; -const processReactTypeDeclarations = (source: SourceFile) => { - const nodes: Node[] = [source]; - // Use index-based loop to keep iterating as nodes array grows. - for (let i = 0; i < nodes.length; i++) { - // forEachChild doesn't work if return value is number (e.g. return value of Array.prototype.push). - nodes[i].forEachChild(c => void nodes.push(c)); - } - const attributeNodes = nodes - .filter(n => n.kind === ts.SyntaxKind.InterfaceDeclaration) - .map(n => [/^([A-Za-z]*)(HTML|SVG)Attributes/.exec(getNameOfNode(n)), n]) - .filter(([matches]) => !!matches) - .map(([matches, node]) => [matches![2].toLowerCase(), normaliseName(matches![1], tagNameNormalised), node]) - .filter(([namespace, tagName]) => namespace !== 'html' || !['all', 'webview'].includes(tagName)) - .map(([namespace, tag, node]) => ({namespace, tag, node})) - .sort((a, b) => a.namespace.localeCompare(b.namespace) || a.tag.localeCompare(b.tag)); - // Process global HTML attributes first as they also appear on some specific HTML tags but we don't want to keep the specific ones if they're global. - if (attributeNodes[0].namespace !== 'html' || attributeNodes[0].tag !== '') { - throw new Error(`Global HTML attributes is not first to be processed`); - } - - // Map structure: attr => namespace => tag => config. - const attributes = new Map>>(); - - for (const {namespace, tag, node} of attributeNodes) { - const fullyQualifiedTagName = [namespace, tag || '*'].join(':'); - for (const n of node.members.filter((n: Node) => n.kind === ts.SyntaxKind.PropertySignature)) { - const attrName = normaliseName(getNameOfNode(n), attrNameNormalised); - if (reactSpecificAttributes.includes(attrName)) continue; - - const types: SyntaxKind[] = n.type.kind === ts.SyntaxKind.UnionType - ? n.type.types.map((t: Node) => t.kind) - : [n.type.kind]; - - const boolean = types.includes(ts.SyntaxKind.BooleanKeyword); - // If types includes boolean and string, make it a boolean attr to prevent it from being removed if empty value. - const redundantIfEmpty = !boolean && types.some(t => t === ts.SyntaxKind.StringKeyword || t === ts.SyntaxKind.NumberKeyword); - const defaultValues = (defaultAttributeValues[attrName] || []) - .filter(a => a.tags.includes(fullyQualifiedTagName)) - .map(a => a.defaultValue); - const collapseAndTrim = (collapsibleAndTrimmable[attrName] || []).includes(fullyQualifiedTagName); - if (defaultValues.length > 1) { - throw new Error(`Tag-attribute combination <${fullyQualifiedTagName} ${attrName}> has multiple default values: ${defaultValues}`); - } - const attr: AttrConfig = { - boolean, - redundantIfEmpty, - collapseAndTrim, - defaultValue: defaultValues[0], - }; - - if (!attributes.has(attrName)) attributes.set(attrName, new Map()); - const namespacesForAttribute = attributes.get(attrName)!; - if (!namespacesForAttribute.has(namespace)) namespacesForAttribute.set(namespace, new Map()); - const tagsForNsAttribute = namespacesForAttribute.get(namespace)!; - if (tagsForNsAttribute.has(tag)) throw new Error(`Duplicate tag-attribute combination: <${fullyQualifiedTagName} ${attrName}>`); - - const globalAttr = tagsForNsAttribute.get('*'); - if (globalAttr) { - if (globalAttr.boolean !== attr.boolean - || globalAttr.redundantIfEmpty !== attr.redundantIfEmpty - || globalAttr.collapseAndTrim !== attr.collapseAndTrim - || globalAttr.defaultValue !== attr.defaultValue) { - throw new Error(`Global and tag-specific attributes conflict: ${prettyJson(globalAttr)} ${prettyJson(attr)}`); - } - } else { - tagsForNsAttribute.set(tag || '*', attr); - } - } - } - - let code = ` +let code = ` use lazy_static::lazy_static; use std::collections::HashMap; use crate::spec::tag::ns::Namespace; @@ -173,34 +69,31 @@ impl AttrMap { `; - code += ` +code += ` lazy_static! { pub static ref ATTRS: AttrMap = { let mut m = HashMap::<&'static [u8], ByNamespace>::new(); -${[...attributes].map(([attr_name, namespaces]) => ` m.insert(b\"${attr_name}\", ByNamespace { +${[...Object.entries(htmlData.attributes)].map(([attr_name, namespaces]) => ` m.insert(b\"${attr_name}\", ByNamespace { ${(['html', 'svg'] as const).map(ns => ` ${ns}: ` + (() => { - const tagsMap = namespaces.get(ns); - if (!tagsMap) { - return 'None'; - } - const globalAttr = tagsMap.get('*'); - if (globalAttr) { - return `Some(AttrMapEntry::AllNamespaceElements(${rsTagAttr(globalAttr)}))`; - } - return `Some({ + const tagsMap = namespaces[ns]; + if (!tagsMap) { + return 'None'; + } + const globalAttr = tagsMap['*']; + if (globalAttr) { + return `Some(AttrMapEntry::AllNamespaceElements(${rsTagAttr(globalAttr)}))`; + } + return `Some({ let mut m = HashMap::<&'static [u8], AttributeMinification>::new(); -${[...tagsMap].map(([tagName, tagAttr]) => ` m.insert(b\"${tagName}\", ${rsTagAttr(tagAttr)});`).join('\n')} +${Object.entries(tagsMap).map(([tagName, tagAttr]) => ` m.insert(b\"${tagName}\", ${rsTagAttr(tagAttr)});`).join('\n')} AttrMapEntry::SpecificNamespaceElements(m) })`; - })() + ',').join('\n')} +})() + ',').join('\n')} }); `).join('')} AttrMap::new(m) }; }`; - return code; -}; -const source = ts.createSourceFile(`react.d.ts`, reactDeclarations, ts.ScriptTarget.ES2020); -writeFileSync(join(RUST_OUT_DIR, 'attrs.rs'), processReactTypeDeclarations(source)); +writeFileSync(join(RUST_OUT_DIR, 'attrs.rs'), code); diff --git a/gen/data/attrs.json b/gen/data/attrs.json deleted file mode 100644 index 2bb3548..0000000 --- a/gen/data/attrs.json +++ /dev/null @@ -1,160 +0,0 @@ -{ - "align": [ - { - "tags": [ - "html:img" - ], - "defaultValue": "bottom" - } - ], - "decoding": [ - { - "tags": [ - "html:img" - ], - "defaultValue": "auto" - } - ], - "enctype": [ - { - "tags": [ - "html:form" - ], - "defaultValue": "application/x-www-form-urlencoded" - } - ], - "frameborder": [ - { - "tags": [ - "html:iframe" - ], - "defaultValue": "1", - "isPositiveInteger": true - } - ], - "formenctype": [ - { - "tags": [ - "html:button", - "html:input" - ], - "defaultValue": "application/x-www-form-urlencoded" - } - ], - "height": [ - { - "tags": [ - "html:iframe" - ], - "defaultValue": "150", - "isPositiveInteger": true - } - ], - "importance": [ - { - "tags": [ - "html:iframe" - ], - "defaultValue": "auto" - } - ], - "loading": [ - { - "tags": [ - "html:iframe", - "html:img" - ], - "defaultValue": "eager" - } - ], - "media": [ - { - "tags": [ - "html:style" - ], - "defaultValue": "all" - } - ], - "method": [ - { - "tags": [ - "html:form" - ], - "defaultValue": "get" - } - ], - "referrerpolicy": [ - { - "tags": [ - "html:iframe", - "html:img" - ], - "defaultValue": "no-referrer-when-downgrade" - } - ], - "rules": [ - { - "tags": [ - "html:table" - ], - "defaultValue": "none" - } - ], - "shape": [ - { - "tags": [ - "html:area" - ], - "defaultValue": "rect" - } - ], - "span": [ - { - "tags": [ - "html:col", - "html:colgroup" - ], - "defaultValue": "1", - "isPositiveInteger": true - } - ], - "target": [ - { - "tags": [ - "html:a", - "html:form" - ], - "defaultValue": "_self" - } - ], - "type": [ - { - "tags": [ - "html:button" - ], - "defaultValue": "submit" - }, - { - "tags": [ - "html:input" - ], - "defaultValue": "text" - }, - { - "tags": [ - "html:link", - "html:style" - ], - "defaultValue": "text/css" - } - ], - "width": [ - { - "tags": [ - "html:iframe" - ], - "defaultValue": "300", - "isPositiveInteger": true - } - ] -} diff --git a/gen/data/react.d.ts b/gen/data/react.d.ts deleted file mode 100644 index 6865159..0000000 --- a/gen/data/react.d.ts +++ /dev/null @@ -1,3150 +0,0 @@ -// This file was fetched from https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/master/types/react/index.d.ts and is used to build attribute data. - -// Type definitions for React 16.9 -// Project: http://facebook.github.io/react/ -// Definitions by: Asana -// AssureSign -// Microsoft -// John Reilly -// Benoit Benezech -// Patricio Zavolinsky -// Digiguru -// Eric Anderson -// Dovydas Navickas -// Josh Rutherford -// Guilherme Hübner -// Ferdy Budhidharma -// Johann Rakotoharisoa -// Olivier Pascal -// Martin Hochel -// Frank Li -// Jessica Franco -// Saransh Kataria -// Kanitkorn Sujautra -// Sebastian Silbermann -// Kyle Scully -// Cong Zhang -// Dimitri Mitropoulos -// JongChan Choi -// Victor Magalhães -// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -// TypeScript Version: 2.8 - -// NOTE: Users of the `experimental` builds of React should add a reference -// to 'react/experimental' in their project. See experimental.d.ts's top comment -// for reference and documentation on how exactly to do it. - -/// - -import * as CSS from 'csstype'; -import * as PropTypes from 'prop-types'; - -type NativeAnimationEvent = AnimationEvent; -type NativeClipboardEvent = ClipboardEvent; -type NativeCompositionEvent = CompositionEvent; -type NativeDragEvent = DragEvent; -type NativeFocusEvent = FocusEvent; -type NativeKeyboardEvent = KeyboardEvent; -type NativeMouseEvent = MouseEvent; -type NativeTouchEvent = TouchEvent; -type NativePointerEvent = PointerEvent; -type NativeTransitionEvent = TransitionEvent; -type NativeUIEvent = UIEvent; -type NativeWheelEvent = WheelEvent; -type Booleanish = boolean | 'true' | 'false'; - -/** - * defined in scheduler/tracing - */ -interface SchedulerInteraction { - id: number; - name: string; - timestamp: number; -} - -// tslint:disable-next-line:export-just-namespace -export = React; -export as namespace React; - -declare namespace React { - // - // React Elements - // ---------------------------------------------------------------------- - - type ElementType

= - { - [K in keyof JSX.IntrinsicElements]: P extends JSX.IntrinsicElements[K] ? K : never - }[keyof JSX.IntrinsicElements] | - ComponentType

; - /** - * @deprecated Please use `ElementType` - */ - type ReactType

= ElementType

; - type ComponentType

= ComponentClass

| FunctionComponent

; - - type JSXElementConstructor

= - | ((props: P) => ReactElement | null) - | (new (props: P) => Component); - - interface RefObject { - readonly current: T | null; - } - type RefCallback = { bivarianceHack(instance: T | null): void }["bivarianceHack"]; - type Ref = RefCallback | RefObject | null; - type LegacyRef = string | Ref; - /** - * Gets the instance type for a React element. The instance will be different for various component types: - * - * - React class components will be the class instance. So if you had `class Foo extends React.Component<{}> {}` - * and used `React.ElementRef` then the type would be the instance of `Foo`. - * - React stateless functional components do not have a backing instance and so `React.ElementRef` - * (when `Bar` is `function Bar() {}`) will give you the `undefined` type. - * - JSX intrinsics like `div` will give you their DOM instance. For `React.ElementRef<'div'>` that would be - * `HTMLDivElement`. For `React.ElementRef<'input'>` that would be `HTMLInputElement`. - * - React stateless functional components that forward a `ref` will give you the `ElementRef` of the forwarded - * to component. - * - * `C` must be the type _of_ a React component so you need to use typeof as in React.ElementRef. - * - * @todo In Flow, this works a little different with forwarded refs and the `AbstractComponent` that - * `React.forwardRef()` returns. - */ - type ElementRef< - C extends - | ForwardRefExoticComponent - | { new (props: any): Component } - | ((props: any, context?: any) => ReactElement | null) - | keyof JSX.IntrinsicElements - > = C extends ForwardRefExoticComponent - ? FP extends RefAttributes - ? FC - : never - : C extends { new (props: any): Component } - ? InstanceType - : C extends ((props: any, context?: any) => ReactElement | null) - ? undefined - : C extends keyof JSX.IntrinsicElements - ? JSX.IntrinsicElements[C] extends DOMAttributes - ? E - : never - : never; - - type ComponentState = any; - - type Key = string | number; - - /** - * @internal You shouldn't need to use this type since you never see these attributes - * inside your component or have to validate them. - */ - interface Attributes { - key?: Key; - } - interface RefAttributes extends Attributes { - ref?: Ref; - } - interface ClassAttributes extends Attributes { - ref?: LegacyRef; - } - - interface ReactElement

= string | JSXElementConstructor> { - type: T; - props: P; - key: Key | null; - } - - interface ReactComponentElement< - T extends keyof JSX.IntrinsicElements | JSXElementConstructor, - P = Pick, Exclude, 'key' | 'ref'>> - > extends ReactElement> { } - - /** - * @deprecated Please use `FunctionComponentElement` - */ - type SFCElement

= FunctionComponentElement

; - - interface FunctionComponentElement

extends ReactElement> { - ref?: 'ref' extends keyof P ? P extends { ref?: infer R } ? R : never : never; - } - - type CElement> = ComponentElement; - interface ComponentElement> extends ReactElement> { - ref?: LegacyRef; - } - - type ClassicElement

= CElement>; - - // string fallback for custom web-components - interface DOMElement

| SVGAttributes, T extends Element> extends ReactElement { - ref: LegacyRef; - } - - // ReactHTML for ReactHTMLElement - // tslint:disable-next-line:no-empty-interface - interface ReactHTMLElement extends DetailedReactHTMLElement, T> { } - - interface DetailedReactHTMLElement

, T extends HTMLElement> extends DOMElement { - type: keyof ReactHTML; - } - - // ReactSVG for ReactSVGElement - interface ReactSVGElement extends DOMElement, SVGElement> { - type: keyof ReactSVG; - } - - interface ReactPortal extends ReactElement { - key: Key | null; - children: ReactNode; - } - - // - // Factories - // ---------------------------------------------------------------------- - - type Factory

= (props?: Attributes & P, ...children: ReactNode[]) => ReactElement

; - - /** - * @deprecated Please use `FunctionComponentFactory` - */ - type SFCFactory

= FunctionComponentFactory

; - - type FunctionComponentFactory

= (props?: Attributes & P, ...children: ReactNode[]) => FunctionComponentElement

; - - type ComponentFactory> = - (props?: ClassAttributes & P, ...children: ReactNode[]) => CElement; - - type CFactory> = ComponentFactory; - type ClassicFactory

= CFactory>; - - type DOMFactory

, T extends Element> = - (props?: ClassAttributes & P | null, ...children: ReactNode[]) => DOMElement; - - // tslint:disable-next-line:no-empty-interface - interface HTMLFactory extends DetailedHTMLFactory, T> {} - - interface DetailedHTMLFactory

, T extends HTMLElement> extends DOMFactory { - (props?: ClassAttributes & P | null, ...children: ReactNode[]): DetailedReactHTMLElement; - } - - interface SVGFactory extends DOMFactory, SVGElement> { - (props?: ClassAttributes & SVGAttributes | null, ...children: ReactNode[]): ReactSVGElement; - } - - // - // React Nodes - // http://facebook.github.io/react/docs/glossary.html - // ---------------------------------------------------------------------- - - type ReactText = string | number; - type ReactChild = ReactElement | ReactText; - - interface ReactNodeArray extends Array {} - type ReactFragment = {} | ReactNodeArray; - type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined; - - // - // Top Level API - // ---------------------------------------------------------------------- - - // DOM Elements - function createFactory( - type: keyof ReactHTML): HTMLFactory; - function createFactory( - type: keyof ReactSVG): SVGFactory; - function createFactory

, T extends Element>( - type: string): DOMFactory; - - // Custom components - function createFactory

(type: FunctionComponent

): FunctionComponentFactory

; - function createFactory

( - type: ClassType, ClassicComponentClass

>): CFactory>; - function createFactory, C extends ComponentClass

>( - type: ClassType): CFactory; - function createFactory

(type: ComponentClass

): Factory

; - - // DOM Elements - // TODO: generalize this to everything in `keyof ReactHTML`, not just "input" - function createElement( - type: "input", - props?: InputHTMLAttributes & ClassAttributes | null, - ...children: ReactNode[]): DetailedReactHTMLElement, HTMLInputElement>; - function createElement

, T extends HTMLElement>( - type: keyof ReactHTML, - props?: ClassAttributes & P | null, - ...children: ReactNode[]): DetailedReactHTMLElement; - function createElement

, T extends SVGElement>( - type: keyof ReactSVG, - props?: ClassAttributes & P | null, - ...children: ReactNode[]): ReactSVGElement; - function createElement

, T extends Element>( - type: string, - props?: ClassAttributes & P | null, - ...children: ReactNode[]): DOMElement; - - // Custom components - - function createElement

( - type: FunctionComponent

, - props?: Attributes & P | null, - ...children: ReactNode[]): FunctionComponentElement

; - function createElement

( - type: ClassType, ClassicComponentClass

>, - props?: ClassAttributes> & P | null, - ...children: ReactNode[]): CElement>; - function createElement

, C extends ComponentClass

>( - type: ClassType, - props?: ClassAttributes & P | null, - ...children: ReactNode[]): CElement; - function createElement

( - type: FunctionComponent

| ComponentClass

| string, - props?: Attributes & P | null, - ...children: ReactNode[]): ReactElement

; - - // DOM Elements - // ReactHTMLElement - function cloneElement

, T extends HTMLElement>( - element: DetailedReactHTMLElement, - props?: P, - ...children: ReactNode[]): DetailedReactHTMLElement; - // ReactHTMLElement, less specific - function cloneElement

, T extends HTMLElement>( - element: ReactHTMLElement, - props?: P, - ...children: ReactNode[]): ReactHTMLElement; - // SVGElement - function cloneElement

, T extends SVGElement>( - element: ReactSVGElement, - props?: P, - ...children: ReactNode[]): ReactSVGElement; - // DOM Element (has to be the last, because type checking stops at first overload that fits) - function cloneElement

, T extends Element>( - element: DOMElement, - props?: DOMAttributes & P, - ...children: ReactNode[]): DOMElement; - - // Custom components - function cloneElement

( - element: FunctionComponentElement

, - props?: Partial

& Attributes, - ...children: ReactNode[]): FunctionComponentElement

; - function cloneElement>( - element: CElement, - props?: Partial

& ClassAttributes, - ...children: ReactNode[]): CElement; - function cloneElement

( - element: ReactElement

, - props?: Partial

& Attributes, - ...children: ReactNode[]): ReactElement

; - - // Context via RenderProps - interface ProviderProps { - value: T; - children?: ReactNode; - } - - interface ConsumerProps { - children: (value: T) => ReactNode; - unstable_observedBits?: number; - } - - // TODO: similar to how Fragment is actually a symbol, the values returned from createContext, - // forwardRef and memo are actually objects that are treated specially by the renderer; see: - // https://github.com/facebook/react/blob/v16.6.0/packages/react/src/ReactContext.js#L35-L48 - // https://github.com/facebook/react/blob/v16.6.0/packages/react/src/forwardRef.js#L42-L45 - // https://github.com/facebook/react/blob/v16.6.0/packages/react/src/memo.js#L27-L31 - // However, we have no way of telling the JSX parser that it's a JSX element type or its props other than - // by pretending to be a normal component. - // - // We don't just use ComponentType or SFC types because you are not supposed to attach statics to this - // object, but rather to the original function. - interface ExoticComponent

{ - /** - * **NOTE**: Exotic components are not callable. - */ - (props: P): (ReactElement|null); - readonly $$typeof: symbol; - } - - interface NamedExoticComponent

extends ExoticComponent

{ - displayName?: string; - } - - interface ProviderExoticComponent

extends ExoticComponent

{ - propTypes?: WeakValidationMap

; - } - - type ContextType> = C extends Context ? T : never; - - // NOTE: only the Context object itself can get a displayName - // https://github.com/facebook/react-devtools/blob/e0b854e4c/backend/attachRendererFiber.js#L310-L325 - type Provider = ProviderExoticComponent>; - type Consumer = ExoticComponent>; - interface Context { - Provider: Provider; - Consumer: Consumer; - displayName?: string; - } - function createContext( - // If you thought this should be optional, see - // https://github.com/DefinitelyTyped/DefinitelyTyped/pull/24509#issuecomment-382213106 - defaultValue: T, - calculateChangedBits?: (prev: T, next: T) => number - ): Context; - - function isValidElement

(object: {} | null | undefined): object is ReactElement

; - - const Children: ReactChildren; - const Fragment: ExoticComponent<{ children?: ReactNode }>; - const StrictMode: ExoticComponent<{ children?: ReactNode }>; - - interface SuspenseProps { - children?: ReactNode; - - /** A fallback react tree to show when a Suspense child (like React.lazy) suspends */ - fallback: NonNullable|null; - /** - * Tells React whether to “skip” revealing this boundary during the initial load. - * This API will likely be removed in a future release. - */ - // NOTE: this is unflagged and is respected even in stable builds - unstable_avoidThisFallback?: boolean; - } - /** - * This feature is not yet available for server-side rendering. - * Suspense support will be added in a later release. - */ - const Suspense: ExoticComponent; - const version: string; - - /** - * {@link https://github.com/bvaughn/rfcs/blob/profiler/text/0000-profiler.md#detailed-design | API} - */ - type ProfilerOnRenderCallback = ( - id: string, - phase: "mount" | "update", - actualDuration: number, - baseDuration: number, - startTime: number, - commitTime: number, - interactions: Set, - ) => void; - interface ProfilerProps { - children?: ReactNode; - id: string; - onRender: ProfilerOnRenderCallback; - } - - const Profiler: ExoticComponent; - - // - // Component API - // ---------------------------------------------------------------------- - - type ReactInstance = Component | Element; - - // Base component for plain JS classes - // tslint:disable-next-line:no-empty-interface - interface Component

extends ComponentLifecycle { } - class Component { - // tslint won't let me format the sample code in a way that vscode likes it :( - /** - * If set, `this.context` will be set at runtime to the current value of the given Context. - * - * Usage: - * - * ```ts - * type MyContext = number - * const Ctx = React.createContext(0) - * - * class Foo extends React.Component { - * static contextType = Ctx - * context!: React.ContextType - * render () { - * return <>My context's value: {this.context}; - * } - * } - * ``` - * - * @see https://reactjs.org/docs/context.html#classcontexttype - */ - static contextType?: Context; - - /** - * If using the new style context, re-declare this in your class to be the - * `React.ContextType` of your `static contextType`. - * Should be used with type annotation or static contextType. - * - * ```ts - * static contextType = MyContext - * // For TS pre-3.7: - * context!: React.ContextType - * // For TS 3.7 and above: - * declare context: React.ContextType - * ``` - * - * @see https://reactjs.org/docs/context.html - */ - // TODO (TypeScript 3.0): unknown - context: any; - - constructor(props: Readonly

); - /** - * @deprecated - * @see https://reactjs.org/docs/legacy-context.html - */ - constructor(props: P, context?: any); - - // We MUST keep setState() as a unified signature because it allows proper checking of the method return type. - // See: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18365#issuecomment-351013257 - // Also, the ` | S` allows intellisense to not be dumbisense - setState( - state: ((prevState: Readonly, props: Readonly

) => (Pick | S | null)) | (Pick | S | null), - callback?: () => void - ): void; - - forceUpdate(callback?: () => void): void; - render(): ReactNode; - - // React.Props is now deprecated, which means that the `children` - // property is not available on `P` by default, even though you can - // always pass children as variadic arguments to `createElement`. - // In the future, if we can define its call signature conditionally - // on the existence of `children` in `P`, then we should remove this. - readonly props: Readonly

& Readonly<{ children?: ReactNode }>; - state: Readonly; - /** - * @deprecated - * https://reactjs.org/docs/refs-and-the-dom.html#legacy-api-string-refs - */ - refs: { - [key: string]: ReactInstance - }; - } - - class PureComponent

extends Component { } - - interface ClassicComponent

extends Component { - replaceState(nextState: S, callback?: () => void): void; - isMounted(): boolean; - getInitialState?(): S; - } - - interface ChildContextProvider { - getChildContext(): CC; - } - - // - // Class Interfaces - // ---------------------------------------------------------------------- - - /** - * @deprecated as of recent React versions, function components can no - * longer be considered 'stateless'. Please use `FunctionComponent` instead. - * - * @see [React Hooks](https://reactjs.org/docs/hooks-intro.html) - */ - type SFC

= FunctionComponent

; - - /** - * @deprecated as of recent React versions, function components can no - * longer be considered 'stateless'. Please use `FunctionComponent` instead. - * - * @see [React Hooks](https://reactjs.org/docs/hooks-intro.html) - */ - type StatelessComponent

= FunctionComponent

; - - type FC

= FunctionComponent

; - - interface FunctionComponent

{ - (props: PropsWithChildren

, context?: any): ReactElement | null; - propTypes?: WeakValidationMap

; - contextTypes?: ValidationMap; - defaultProps?: Partial

; - displayName?: string; - } - - interface ForwardRefRenderFunction { - (props: PropsWithChildren

, ref: ((instance: T | null) => void) | MutableRefObject | null): ReactElement | null; - displayName?: string; - // explicit rejected with `never` required due to - // https://github.com/microsoft/TypeScript/issues/36826 - /** - * defaultProps are not supported on render functions - */ - defaultProps?: never; - /** - * propTypes are not supported on render functions - */ - propTypes?: never; - } - - /** - * @deprecated Use ForwardRefRenderFunction. forwardRef doesn't accept a - * "real" component. - */ - interface RefForwardingComponent extends ForwardRefRenderFunction {} - - interface ComponentClass

extends StaticLifecycle { - new (props: P, context?: any): Component; - propTypes?: WeakValidationMap

; - contextType?: Context; - contextTypes?: ValidationMap; - childContextTypes?: ValidationMap; - defaultProps?: Partial

; - displayName?: string; - } - - interface ClassicComponentClass

extends ComponentClass

{ - new (props: P, context?: any): ClassicComponent; - getDefaultProps?(): P; - } - - /** - * We use an intersection type to infer multiple type parameters from - * a single argument, which is useful for many top-level API defs. - * See https://github.com/Microsoft/TypeScript/issues/7234 for more info. - */ - type ClassType, C extends ComponentClass

> = - C & - (new (props: P, context?: any) => T); - - // - // Component Specs and Lifecycle - // ---------------------------------------------------------------------- - - // This should actually be something like `Lifecycle | DeprecatedLifecycle`, - // as React will _not_ call the deprecated lifecycle methods if any of the new lifecycle - // methods are present. - interface ComponentLifecycle extends NewLifecycle, DeprecatedLifecycle { - /** - * Called immediately after a component is mounted. Setting state here will trigger re-rendering. - */ - componentDidMount?(): void; - /** - * Called to determine whether the change in props and state should trigger a re-render. - * - * `Component` always returns true. - * `PureComponent` implements a shallow comparison on props and state and returns true if any - * props or states have changed. - * - * If false is returned, `Component#render`, `componentWillUpdate` - * and `componentDidUpdate` will not be called. - */ - shouldComponentUpdate?(nextProps: Readonly

, nextState: Readonly, nextContext: any): boolean; - /** - * Called immediately before a component is destroyed. Perform any necessary cleanup in this method, such as - * cancelled network requests, or cleaning up any DOM elements created in `componentDidMount`. - */ - componentWillUnmount?(): void; - /** - * Catches exceptions generated in descendant components. Unhandled exceptions will cause - * the entire component tree to unmount. - */ - componentDidCatch?(error: Error, errorInfo: ErrorInfo): void; - } - - // Unfortunately, we have no way of declaring that the component constructor must implement this - interface StaticLifecycle { - getDerivedStateFromProps?: GetDerivedStateFromProps; - getDerivedStateFromError?: GetDerivedStateFromError; - } - - type GetDerivedStateFromProps = - /** - * Returns an update to a component's state based on its new props and old state. - * - * Note: its presence prevents any of the deprecated lifecycle methods from being invoked - */ - (nextProps: Readonly

, prevState: S) => Partial | null; - - type GetDerivedStateFromError = - /** - * This lifecycle is invoked after an error has been thrown by a descendant component. - * It receives the error that was thrown as a parameter and should return a value to update state. - * - * Note: its presence prevents any of the deprecated lifecycle methods from being invoked - */ - (error: any) => Partial | null; - - // This should be "infer SS" but can't use it yet - interface NewLifecycle { - /** - * Runs before React applies the result of `render` to the document, and - * returns an object to be given to componentDidUpdate. Useful for saving - * things such as scroll position before `render` causes changes to it. - * - * Note: the presence of getSnapshotBeforeUpdate prevents any of the deprecated - * lifecycle events from running. - */ - getSnapshotBeforeUpdate?(prevProps: Readonly

, prevState: Readonly): SS | null; - /** - * Called immediately after updating occurs. Not called for the initial render. - * - * The snapshot is only present if getSnapshotBeforeUpdate is present and returns non-null. - */ - componentDidUpdate?(prevProps: Readonly

, prevState: Readonly, snapshot?: SS): void; - } - - interface DeprecatedLifecycle { - /** - * Called immediately before mounting occurs, and before `Component#render`. - * Avoid introducing any side-effects or subscriptions in this method. - * - * Note: the presence of getSnapshotBeforeUpdate or getDerivedStateFromProps - * prevents this from being invoked. - * - * @deprecated 16.3, use componentDidMount or the constructor instead; will stop working in React 17 - * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#initializing-state - * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path - */ - componentWillMount?(): void; - /** - * Called immediately before mounting occurs, and before `Component#render`. - * Avoid introducing any side-effects or subscriptions in this method. - * - * This method will not stop working in React 17. - * - * Note: the presence of getSnapshotBeforeUpdate or getDerivedStateFromProps - * prevents this from being invoked. - * - * @deprecated 16.3, use componentDidMount or the constructor instead - * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#initializing-state - * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path - */ - UNSAFE_componentWillMount?(): void; - /** - * Called when the component may be receiving new props. - * React may call this even if props have not changed, so be sure to compare new and existing - * props if you only want to handle changes. - * - * Calling `Component#setState` generally does not trigger this method. - * - * Note: the presence of getSnapshotBeforeUpdate or getDerivedStateFromProps - * prevents this from being invoked. - * - * @deprecated 16.3, use static getDerivedStateFromProps instead; will stop working in React 17 - * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#updating-state-based-on-props - * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path - */ - componentWillReceiveProps?(nextProps: Readonly

, nextContext: any): void; - /** - * Called when the component may be receiving new props. - * React may call this even if props have not changed, so be sure to compare new and existing - * props if you only want to handle changes. - * - * Calling `Component#setState` generally does not trigger this method. - * - * This method will not stop working in React 17. - * - * Note: the presence of getSnapshotBeforeUpdate or getDerivedStateFromProps - * prevents this from being invoked. - * - * @deprecated 16.3, use static getDerivedStateFromProps instead - * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#updating-state-based-on-props - * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path - */ - UNSAFE_componentWillReceiveProps?(nextProps: Readonly

, nextContext: any): void; - /** - * Called immediately before rendering when new props or state is received. Not called for the initial render. - * - * Note: You cannot call `Component#setState` here. - * - * Note: the presence of getSnapshotBeforeUpdate or getDerivedStateFromProps - * prevents this from being invoked. - * - * @deprecated 16.3, use getSnapshotBeforeUpdate instead; will stop working in React 17 - * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#reading-dom-properties-before-an-update - * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path - */ - componentWillUpdate?(nextProps: Readonly

, nextState: Readonly, nextContext: any): void; - /** - * Called immediately before rendering when new props or state is received. Not called for the initial render. - * - * Note: You cannot call `Component#setState` here. - * - * This method will not stop working in React 17. - * - * Note: the presence of getSnapshotBeforeUpdate or getDerivedStateFromProps - * prevents this from being invoked. - * - * @deprecated 16.3, use getSnapshotBeforeUpdate instead - * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#reading-dom-properties-before-an-update - * @see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#gradual-migration-path - */ - UNSAFE_componentWillUpdate?(nextProps: Readonly

, nextState: Readonly, nextContext: any): void; - } - - interface Mixin extends ComponentLifecycle { - mixins?: Array>; - statics?: { - [key: string]: any; - }; - - displayName?: string; - propTypes?: ValidationMap; - contextTypes?: ValidationMap; - childContextTypes?: ValidationMap; - - getDefaultProps?(): P; - getInitialState?(): S; - } - - interface ComponentSpec extends Mixin { - render(): ReactNode; - - [propertyName: string]: any; - } - - function createRef(): RefObject; - - // will show `ForwardRef(${Component.displayName || Component.name})` in devtools by default, - // but can be given its own specific name - interface ForwardRefExoticComponent

extends NamedExoticComponent

{ - defaultProps?: Partial

; - propTypes?: WeakValidationMap

; - } - - function forwardRef(render: ForwardRefRenderFunction): ForwardRefExoticComponent & RefAttributes>; - - /** Ensures that the props do not include ref at all */ - type PropsWithoutRef

= - // Just Pick would be sufficient for this, but I'm trying to avoid unnecessary mapping over union types - // https://github.com/Microsoft/TypeScript/issues/28339 - 'ref' extends keyof P - ? Pick> - : P; - /** Ensures that the props do not include string ref, which cannot be forwarded */ - type PropsWithRef

= - // Just "P extends { ref?: infer R }" looks sufficient, but R will infer as {} if P is {}. - 'ref' extends keyof P - ? P extends { ref?: infer R } - ? string extends R - ? PropsWithoutRef

& { ref?: Exclude } - : P - : P - : P; - - type PropsWithChildren

= P & { children?: ReactNode }; - - /** - * NOTE: prefer ComponentPropsWithRef, if the ref is forwarded, - * or ComponentPropsWithoutRef when refs are not supported. - */ - type ComponentProps> = - T extends JSXElementConstructor - ? P - : T extends keyof JSX.IntrinsicElements - ? JSX.IntrinsicElements[T] - : {}; - type ComponentPropsWithRef = - T extends ComponentClass - ? PropsWithoutRef

& RefAttributes> - : PropsWithRef>; - type ComponentPropsWithoutRef = - PropsWithoutRef>; - - // will show `Memo(${Component.displayName || Component.name})` in devtools by default, - // but can be given its own specific name - type MemoExoticComponent> = NamedExoticComponent> & { - readonly type: T; - }; - - function memo

( - Component: SFC

, - propsAreEqual?: (prevProps: Readonly>, nextProps: Readonly>) => boolean - ): NamedExoticComponent

; - function memo>( - Component: T, - propsAreEqual?: (prevProps: Readonly>, nextProps: Readonly>) => boolean - ): MemoExoticComponent; - - type LazyExoticComponent> = ExoticComponent> & { - readonly _result: T; - }; - - function lazy>( - factory: () => Promise<{ default: T }> - ): LazyExoticComponent; - - // - // React Hooks - // ---------------------------------------------------------------------- - - // based on the code in https://github.com/facebook/react/pull/13968 - - // Unlike the class component setState, the updates are not allowed to be partial - type SetStateAction = S | ((prevState: S) => S); - // this technically does accept a second argument, but it's already under a deprecation warning - // and it's not even released so probably better to not define it. - type Dispatch = (value: A) => void; - // Since action _can_ be undefined, dispatch may be called without any parameters. - type DispatchWithoutAction = () => void; - // Unlike redux, the actions _can_ be anything - type Reducer = (prevState: S, action: A) => S; - // If useReducer accepts a reducer without action, dispatch may be called without any parameters. - type ReducerWithoutAction = (prevState: S) => S; - // types used to try and prevent the compiler from reducing S - // to a supertype common with the second argument to useReducer() - type ReducerState> = R extends Reducer ? S : never; - type ReducerAction> = R extends Reducer ? A : never; - // The identity check is done with the SameValue algorithm (Object.is), which is stricter than === - type ReducerStateWithoutAction> = - R extends ReducerWithoutAction ? S : never; - // TODO (TypeScript 3.0): ReadonlyArray - type DependencyList = ReadonlyArray; - - // NOTE: callbacks are _only_ allowed to return either void, or a destructor. - // The destructor is itself only allowed to return void. - type EffectCallback = () => (void | (() => void | undefined)); - - interface MutableRefObject { - current: T; - } - - // This will technically work if you give a Consumer or Provider but it's deprecated and warns - /** - * Accepts a context object (the value returned from `React.createContext`) and returns the current - * context value, as given by the nearest context provider for the given context. - * - * @version 16.8.0 - * @see https://reactjs.org/docs/hooks-reference.html#usecontext - */ - function useContext(context: Context/*, (not public API) observedBits?: number|boolean */): T; - /** - * Returns a stateful value, and a function to update it. - * - * @version 16.8.0 - * @see https://reactjs.org/docs/hooks-reference.html#usestate - */ - function useState(initialState: S | (() => S)): [S, Dispatch>]; - // convenience overload when first argument is ommitted - /** - * Returns a stateful value, and a function to update it. - * - * @version 16.8.0 - * @see https://reactjs.org/docs/hooks-reference.html#usestate - */ - function useState(): [S | undefined, Dispatch>]; - /** - * An alternative to `useState`. - * - * `useReducer` is usually preferable to `useState` when you have complex state logic that involves - * multiple sub-values. It also lets you optimize performance for components that trigger deep - * updates because you can pass `dispatch` down instead of callbacks. - * - * @version 16.8.0 - * @see https://reactjs.org/docs/hooks-reference.html#usereducer - */ - // overload where dispatch could accept 0 arguments. - function useReducer, I>( - reducer: R, - initializerArg: I, - initializer: (arg: I) => ReducerStateWithoutAction - ): [ReducerStateWithoutAction, DispatchWithoutAction]; - /** - * An alternative to `useState`. - * - * `useReducer` is usually preferable to `useState` when you have complex state logic that involves - * multiple sub-values. It also lets you optimize performance for components that trigger deep - * updates because you can pass `dispatch` down instead of callbacks. - * - * @version 16.8.0 - * @see https://reactjs.org/docs/hooks-reference.html#usereducer - */ - // overload where dispatch could accept 0 arguments. - function useReducer>( - reducer: R, - initializerArg: ReducerStateWithoutAction, - initializer?: undefined - ): [ReducerStateWithoutAction, DispatchWithoutAction]; - /** - * An alternative to `useState`. - * - * `useReducer` is usually preferable to `useState` when you have complex state logic that involves - * multiple sub-values. It also lets you optimize performance for components that trigger deep - * updates because you can pass `dispatch` down instead of callbacks. - * - * @version 16.8.0 - * @see https://reactjs.org/docs/hooks-reference.html#usereducer - */ - // overload where "I" may be a subset of ReducerState; used to provide autocompletion. - // If "I" matches ReducerState exactly then the last overload will allow initializer to be ommitted. - // the last overload effectively behaves as if the identity function (x => x) is the initializer. - function useReducer, I>( - reducer: R, - initializerArg: I & ReducerState, - initializer: (arg: I & ReducerState) => ReducerState - ): [ReducerState, Dispatch>]; - /** - * An alternative to `useState`. - * - * `useReducer` is usually preferable to `useState` when you have complex state logic that involves - * multiple sub-values. It also lets you optimize performance for components that trigger deep - * updates because you can pass `dispatch` down instead of callbacks. - * - * @version 16.8.0 - * @see https://reactjs.org/docs/hooks-reference.html#usereducer - */ - // overload for free "I"; all goes as long as initializer converts it into "ReducerState". - function useReducer, I>( - reducer: R, - initializerArg: I, - initializer: (arg: I) => ReducerState - ): [ReducerState, Dispatch>]; - /** - * An alternative to `useState`. - * - * `useReducer` is usually preferable to `useState` when you have complex state logic that involves - * multiple sub-values. It also lets you optimize performance for components that trigger deep - * updates because you can pass `dispatch` down instead of callbacks. - * - * @version 16.8.0 - * @see https://reactjs.org/docs/hooks-reference.html#usereducer - */ - - // I'm not sure if I keep this 2-ary or if I make it (2,3)-ary; it's currently (2,3)-ary. - // The Flow types do have an overload for 3-ary invocation with undefined initializer. - - // NOTE: without the ReducerState indirection, TypeScript would reduce S to be the most common - // supertype between the reducer's return type and the initialState (or the initializer's return type), - // which would prevent autocompletion from ever working. - - // TODO: double-check if this weird overload logic is necessary. It is possible it's either a bug - // in older versions, or a regression in newer versions of the typescript completion service. - function useReducer>( - reducer: R, - initialState: ReducerState, - initializer?: undefined - ): [ReducerState, Dispatch>]; - /** - * `useRef` returns a mutable ref object whose `.current` property is initialized to the passed argument - * (`initialValue`). The returned object will persist for the full lifetime of the component. - * - * Note that `useRef()` is useful for more than the `ref` attribute. It’s handy for keeping any mutable - * value around similar to how you’d use instance fields in classes. - * - * @version 16.8.0 - * @see https://reactjs.org/docs/hooks-reference.html#useref - */ - // TODO (TypeScript 3.0): - function useRef(initialValue: T): MutableRefObject; - // convenience overload for refs given as a ref prop as they typically start with a null value - /** - * `useRef` returns a mutable ref object whose `.current` property is initialized to the passed argument - * (`initialValue`). The returned object will persist for the full lifetime of the component. - * - * Note that `useRef()` is useful for more than the `ref` attribute. It’s handy for keeping any mutable - * value around similar to how you’d use instance fields in classes. - * - * Usage note: if you need the result of useRef to be directly mutable, include `| null` in the type - * of the generic argument. - * - * @version 16.8.0 - * @see https://reactjs.org/docs/hooks-reference.html#useref - */ - // TODO (TypeScript 3.0): - function useRef(initialValue: T|null): RefObject; - // convenience overload for potentially undefined initialValue / call with 0 arguments - // has a default to stop it from defaulting to {} instead - /** - * `useRef` returns a mutable ref object whose `.current` property is initialized to the passed argument - * (`initialValue`). The returned object will persist for the full lifetime of the component. - * - * Note that `useRef()` is useful for more than the `ref` attribute. It’s handy for keeping any mutable - * value around similar to how you’d use instance fields in classes. - * - * @version 16.8.0 - * @see https://reactjs.org/docs/hooks-reference.html#useref - */ - // TODO (TypeScript 3.0): - function useRef(): MutableRefObject; - /** - * The signature is identical to `useEffect`, but it fires synchronously after all DOM mutations. - * Use this to read layout from the DOM and synchronously re-render. Updates scheduled inside - * `useLayoutEffect` will be flushed synchronously, before the browser has a chance to paint. - * - * Prefer the standard `useEffect` when possible to avoid blocking visual updates. - * - * If you’re migrating code from a class component, `useLayoutEffect` fires in the same phase as - * `componentDidMount` and `componentDidUpdate`. - * - * @version 16.8.0 - * @see https://reactjs.org/docs/hooks-reference.html#uselayouteffect - */ - function useLayoutEffect(effect: EffectCallback, deps?: DependencyList): void; - /** - * Accepts a function that contains imperative, possibly effectful code. - * - * @param effect Imperative function that can return a cleanup function - * @param deps If present, effect will only activate if the values in the list change. - * - * @version 16.8.0 - * @see https://reactjs.org/docs/hooks-reference.html#useeffect - */ - function useEffect(effect: EffectCallback, deps?: DependencyList): void; - // NOTE: this does not accept strings, but this will have to be fixed by removing strings from type Ref - /** - * `useImperativeHandle` customizes the instance value that is exposed to parent components when using - * `ref`. As always, imperative code using refs should be avoided in most cases. - * - * `useImperativeHandle` should be used with `React.forwardRef`. - * - * @version 16.8.0 - * @see https://reactjs.org/docs/hooks-reference.html#useimperativehandle - */ - function useImperativeHandle(ref: Ref|undefined, init: () => R, deps?: DependencyList): void; - // I made 'inputs' required here and in useMemo as there's no point to memoizing without the memoization key - // useCallback(X) is identical to just using X, useMemo(() => Y) is identical to just using Y. - /** - * `useCallback` will return a memoized version of the callback that only changes if one of the `inputs` - * has changed. - * - * @version 16.8.0 - * @see https://reactjs.org/docs/hooks-reference.html#usecallback - */ - // TODO (TypeScript 3.0): unknown> - function useCallback any>(callback: T, deps: DependencyList): T; - /** - * `useMemo` will only recompute the memoized value when one of the `deps` has changed. - * - * Usage note: if calling `useMemo` with a referentially stable function, also give it as the input in - * the second argument. - * - * ```ts - * function expensive () { ... } - * - * function Component () { - * const expensiveResult = useMemo(expensive, [expensive]) - * return ... - * } - * ``` - * - * @version 16.8.0 - * @see https://reactjs.org/docs/hooks-reference.html#usememo - */ - // allow undefined, but don't make it optional as that is very likely a mistake - function useMemo(factory: () => T, deps: DependencyList | undefined): T; - /** - * `useDebugValue` can be used to display a label for custom hooks in React DevTools. - * - * NOTE: We don’t recommend adding debug values to every custom hook. - * It’s most valuable for custom hooks that are part of shared libraries. - * - * @version 16.8.0 - * @see https://reactjs.org/docs/hooks-reference.html#usedebugvalue - */ - // the name of the custom hook is itself derived from the function name at runtime: - // it's just the function name without the "use" prefix. - function useDebugValue(value: T, format?: (value: T) => any): void; - - // - // Event System - // ---------------------------------------------------------------------- - // TODO: change any to unknown when moving to TS v3 - interface BaseSyntheticEvent { - nativeEvent: E; - currentTarget: C; - target: T; - bubbles: boolean; - cancelable: boolean; - defaultPrevented: boolean; - eventPhase: number; - isTrusted: boolean; - preventDefault(): void; - isDefaultPrevented(): boolean; - stopPropagation(): void; - isPropagationStopped(): boolean; - persist(): void; - timeStamp: number; - type: string; - } - - /** - * currentTarget - a reference to the element on which the event listener is registered. - * - * target - a reference to the element from which the event was originally dispatched. - * This might be a child element to the element on which the event listener is registered. - * If you thought this should be `EventTarget & T`, see https://github.com/DefinitelyTyped/DefinitelyTyped/pull/12239 - */ - interface SyntheticEvent extends BaseSyntheticEvent {} - - interface ClipboardEvent extends SyntheticEvent { - clipboardData: DataTransfer; - } - - interface CompositionEvent extends SyntheticEvent { - data: string; - } - - interface DragEvent extends MouseEvent { - dataTransfer: DataTransfer; - } - - interface PointerEvent extends MouseEvent { - pointerId: number; - pressure: number; - tangentialPressure: number; - tiltX: number; - tiltY: number; - twist: number; - width: number; - height: number; - pointerType: 'mouse' | 'pen' | 'touch'; - isPrimary: boolean; - } - - interface FocusEvent extends SyntheticEvent { - relatedTarget: EventTarget | null; - target: EventTarget & T; - } - - // tslint:disable-next-line:no-empty-interface - interface FormEvent extends SyntheticEvent { - } - - interface InvalidEvent extends SyntheticEvent { - target: EventTarget & T; - } - - interface ChangeEvent extends SyntheticEvent { - target: EventTarget & T; - } - - interface KeyboardEvent extends SyntheticEvent { - altKey: boolean; - charCode: number; - ctrlKey: boolean; - /** - * See [DOM Level 3 Events spec](https://www.w3.org/TR/uievents-key/#keys-modifier). for a list of valid (case-sensitive) arguments to this method. - */ - getModifierState(key: string): boolean; - /** - * See the [DOM Level 3 Events spec](https://www.w3.org/TR/uievents-key/#named-key-attribute-values). for possible values - */ - key: string; - keyCode: number; - locale: string; - location: number; - metaKey: boolean; - repeat: boolean; - shiftKey: boolean; - which: number; - } - - interface MouseEvent extends UIEvent { - altKey: boolean; - button: number; - buttons: number; - clientX: number; - clientY: number; - ctrlKey: boolean; - /** - * See [DOM Level 3 Events spec](https://www.w3.org/TR/uievents-key/#keys-modifier). for a list of valid (case-sensitive) arguments to this method. - */ - getModifierState(key: string): boolean; - metaKey: boolean; - movementX: number; - movementY: number; - pageX: number; - pageY: number; - relatedTarget: EventTarget | null; - screenX: number; - screenY: number; - shiftKey: boolean; - } - - interface TouchEvent extends SyntheticEvent { - altKey: boolean; - changedTouches: TouchList; - ctrlKey: boolean; - /** - * See [DOM Level 3 Events spec](https://www.w3.org/TR/uievents-key/#keys-modifier). for a list of valid (case-sensitive) arguments to this method. - */ - getModifierState(key: string): boolean; - metaKey: boolean; - shiftKey: boolean; - targetTouches: TouchList; - touches: TouchList; - } - - interface UIEvent extends SyntheticEvent { - detail: number; - view: AbstractView; - } - - interface WheelEvent extends MouseEvent { - deltaMode: number; - deltaX: number; - deltaY: number; - deltaZ: number; - } - - interface AnimationEvent extends SyntheticEvent { - animationName: string; - elapsedTime: number; - pseudoElement: string; - } - - interface TransitionEvent extends SyntheticEvent { - elapsedTime: number; - propertyName: string; - pseudoElement: string; - } - - // - // Event Handler Types - // ---------------------------------------------------------------------- - - type EventHandler> = { bivarianceHack(event: E): void }["bivarianceHack"]; - - type ReactEventHandler = EventHandler>; - - type ClipboardEventHandler = EventHandler>; - type CompositionEventHandler = EventHandler>; - type DragEventHandler = EventHandler>; - type FocusEventHandler = EventHandler>; - type FormEventHandler = EventHandler>; - type ChangeEventHandler = EventHandler>; - type KeyboardEventHandler = EventHandler>; - type MouseEventHandler = EventHandler>; - type TouchEventHandler = EventHandler>; - type PointerEventHandler = EventHandler>; - type UIEventHandler = EventHandler>; - type WheelEventHandler = EventHandler>; - type AnimationEventHandler = EventHandler>; - type TransitionEventHandler = EventHandler>; - - // - // Props / DOM Attributes - // ---------------------------------------------------------------------- - - /** - * @deprecated. This was used to allow clients to pass `ref` and `key` - * to `createElement`, which is no longer necessary due to intersection - * types. If you need to declare a props object before passing it to - * `createElement` or a factory, use `ClassAttributes`: - * - * ```ts - * var b: Button | null; - * var props: ButtonProps & ClassAttributes