Move tooltip to ts
This commit is contained in:
parent
7533a8f80b
commit
63f78b0808
7 changed files with 170 additions and 113 deletions
|
@ -118,9 +118,11 @@
|
||||||
"@peculiar/webcrypto": "^1.0.22",
|
"@peculiar/webcrypto": "^1.0.22",
|
||||||
"@types/classnames": "^2.2.10",
|
"@types/classnames": "^2.2.10",
|
||||||
"@types/flux": "^3.1.9",
|
"@types/flux": "^3.1.9",
|
||||||
|
"@types/lodash": "^4.14.152",
|
||||||
"@types/modernizr": "^3.5.3",
|
"@types/modernizr": "^3.5.3",
|
||||||
"@types/qrcode": "^1.3.4",
|
"@types/qrcode": "^1.3.4",
|
||||||
"@types/react": "16.9",
|
"@types/react": "16.9",
|
||||||
|
"@types/react-dom": "^16.9.8",
|
||||||
"@types/zxcvbn": "^4.4.0",
|
"@types/zxcvbn": "^4.4.0",
|
||||||
"babel-eslint": "^10.0.3",
|
"babel-eslint": "^10.0.3",
|
||||||
"babel-jest": "^24.9.0",
|
"babel-jest": "^24.9.0",
|
||||||
|
|
|
@ -15,10 +15,9 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import * as sdk from '../../../index';
|
import * as sdk from '../../../index';
|
||||||
import { debounce } from 'lodash';
|
import { debounce, Cancelable } from 'lodash';
|
||||||
|
|
||||||
// Invoke validation from user input (when typing, etc.) at most once every N ms.
|
// Invoke validation from user input (when typing, etc.) at most once every N ms.
|
||||||
const VALIDATION_THROTTLE_MS = 200;
|
const VALIDATION_THROTTLE_MS = 200;
|
||||||
|
@ -29,51 +28,88 @@ function getId() {
|
||||||
return `${BASE_ID}_${count++}`;
|
return `${BASE_ID}_${count++}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Field extends React.PureComponent {
|
interface IProps extends React.HTMLAttributes<HTMLElement> {
|
||||||
static propTypes = {
|
// The field's ID, which binds the input and label together. Immutable.
|
||||||
// The field's ID, which binds the input and label together. Immutable.
|
id?: string,
|
||||||
id: PropTypes.string,
|
// The element to create. Defaults to "input".
|
||||||
// The element to create. Defaults to "input".
|
// To define options for a select, use <Field><option ... /></Field>
|
||||||
// To define options for a select, use <Field><option ... /></Field>
|
element?: InputType,
|
||||||
element: PropTypes.oneOf(["input", "select", "textarea"]),
|
// The field's type (when used as an <input>). Defaults to "text".
|
||||||
// The field's type (when used as an <input>). Defaults to "text".
|
type?: string,
|
||||||
type: PropTypes.string,
|
// id of a <datalist> element for suggestions
|
||||||
// id of a <datalist> element for suggestions
|
list?: string,
|
||||||
list: PropTypes.string,
|
// The field's label string.
|
||||||
// The field's label string.
|
label?: string,
|
||||||
label: PropTypes.string,
|
// The field's placeholder string. Defaults to the label.
|
||||||
// The field's placeholder string. Defaults to the label.
|
placeholder?: string,
|
||||||
placeholder: PropTypes.string,
|
// The field's value.
|
||||||
// The field's value.
|
// This is a controlled component, so the value is required.
|
||||||
// This is a controlled component, so the value is required.
|
value: string,
|
||||||
value: PropTypes.string.isRequired,
|
// Optional component to include inside the field before the input.
|
||||||
// Optional component to include inside the field before the input.
|
prefixComponent?: React.ReactNode,
|
||||||
prefix: PropTypes.node,
|
// Optional component to include inside the field after the input.
|
||||||
// Optional component to include inside the field after the input.
|
postfixComponent?: React.ReactNode,
|
||||||
postfix: PropTypes.node,
|
// The callback called whenever the contents of the field
|
||||||
// The callback called whenever the contents of the field
|
// changes. Returns an object with `valid` boolean field
|
||||||
// changes. Returns an object with `valid` boolean field
|
// and a `feedback` react component field to provide feedback
|
||||||
// and a `feedback` react component field to provide feedback
|
// to the user.
|
||||||
// to the user.
|
onValidate?: (
|
||||||
onValidate: PropTypes.func,
|
args: {value: string, focused: boolean, allowEmpty: boolean}
|
||||||
// If specified, overrides the value returned by onValidate.
|
) => {valid: boolean, feedback: React.ReactNode},
|
||||||
flagInvalid: PropTypes.bool,
|
// If specified, overrides the value returned by onValidate.
|
||||||
// If specified, contents will appear as a tooltip on the element and
|
flagInvalid?: boolean,
|
||||||
// validation feedback tooltips will be suppressed.
|
// If specified, contents will appear as a tooltip on the element and
|
||||||
tooltipContent: PropTypes.node,
|
// validation feedback tooltips will be suppressed.
|
||||||
// If specified alongside tooltipContent, the class name to apply to the
|
tooltipContent?: React.ReactNode,
|
||||||
// tooltip itself.
|
// If specified alongside tooltipContent, the class name to apply to the
|
||||||
tooltipClassName: PropTypes.string,
|
// tooltip itself.
|
||||||
// If specified, an additional class name to apply to the field container
|
tooltipClassName?: string,
|
||||||
className: PropTypes.string,
|
// If specified, an additional class name to apply to the field container
|
||||||
// All other props pass through to the <input>.
|
className?: string,
|
||||||
};
|
// All other props pass through to the <input>.
|
||||||
|
}
|
||||||
|
|
||||||
|
enum InputType {
|
||||||
|
INPUT = "input",
|
||||||
|
SELECT = "select",
|
||||||
|
TEXTAREA = "textarea",
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IState {
|
||||||
|
valid: boolean,
|
||||||
|
feedback: React.ReactNode,
|
||||||
|
feedbackVisible: boolean,
|
||||||
|
focused: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Field extends React.PureComponent<IProps, IState> {
|
||||||
|
private id: string;
|
||||||
|
private input: HTMLInputElement;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This was changed from throttle to debounce: this is more traditional for
|
||||||
|
* form validation since it means that the validation doesn't happen at all
|
||||||
|
* until the user stops typing for a bit (debounce defaults to not running on
|
||||||
|
* the leading edge). If we're doing an HTTP hit on each validation, we have more
|
||||||
|
* incentive to prevent validating input that's very unlikely to be valid.
|
||||||
|
* We may find that we actually want different behaviour for registration
|
||||||
|
* fields, in which case we can add some options to control it.
|
||||||
|
*/
|
||||||
|
validateOnChange = debounce(() => {
|
||||||
|
this.validate({
|
||||||
|
focused: true,
|
||||||
|
});
|
||||||
|
}, VALIDATION_THROTTLE_MS);
|
||||||
|
|
||||||
|
focus() {
|
||||||
|
this.input.focus();
|
||||||
|
}
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
valid: undefined,
|
valid: undefined,
|
||||||
feedback: undefined,
|
feedback: undefined,
|
||||||
|
feedbackVisible: false,
|
||||||
focused: false,
|
focused: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -114,11 +150,7 @@ export default class Field extends React.PureComponent {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
focus() {
|
async validate({ focused, allowEmpty = true }: {focused: boolean, allowEmpty?: boolean}) {
|
||||||
this.input.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
async validate({ focused, allowEmpty = true }) {
|
|
||||||
if (!this.props.onValidate) {
|
if (!this.props.onValidate) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -149,48 +181,37 @@ export default class Field extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* This was changed from throttle to debounce: this is more traditional for
|
|
||||||
* form validation since it means that the validation doesn't happen at all
|
|
||||||
* until the user stops typing for a bit (debounce defaults to not running on
|
|
||||||
* the leading edge). If we're doing an HTTP hit on each validation, we have more
|
|
||||||
* incentive to prevent validating input that's very unlikely to be valid.
|
|
||||||
* We may find that we actually want different behaviour for registration
|
|
||||||
* fields, in which case we can add some options to control it.
|
|
||||||
*/
|
|
||||||
validateOnChange = debounce(() => {
|
|
||||||
this.validate({
|
|
||||||
focused: true,
|
|
||||||
});
|
|
||||||
}, VALIDATION_THROTTLE_MS);
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
element, prefix, postfix, className, onValidate, children,
|
element, prefixComponent, postfixComponent, className, onValidate, children,
|
||||||
tooltipContent, flagInvalid, tooltipClassName, list, ...inputProps} = this.props;
|
tooltipContent, flagInvalid, tooltipClassName, list, ...inputProps} = this.props;
|
||||||
|
|
||||||
const inputElement = element || "input";
|
const inputElement = element || "input";
|
||||||
|
|
||||||
// Set some defaults for the <input> element
|
// Set some defaults for the <input> element
|
||||||
inputProps.type = inputProps.type || "text";
|
inputProps.type = inputProps.type || "text";
|
||||||
inputProps.ref = input => this.input = input;
|
const ref = input => this.input = input;
|
||||||
inputProps.placeholder = inputProps.placeholder || inputProps.label;
|
inputProps.placeholder = inputProps.placeholder || inputProps.label;
|
||||||
inputProps.id = this.id; // this overwrites the id from props
|
inputProps.id = this.id; // this overwrites the id from props
|
||||||
|
|
||||||
inputProps.onFocus = this.onFocus;
|
inputProps.onFocus = this.onFocus;
|
||||||
inputProps.onChange = this.onChange;
|
inputProps.onChange = this.onChange;
|
||||||
inputProps.onBlur = this.onBlur;
|
inputProps.onBlur = this.onBlur;
|
||||||
inputProps.list = list;
|
|
||||||
|
|
||||||
const fieldInput = React.createElement(inputElement, inputProps, children);
|
// Appease typescript's inference
|
||||||
|
const inputProps_ = {...inputProps, ref, list};
|
||||||
|
|
||||||
|
const fieldInput = React.createElement(inputElement, inputProps_, children);
|
||||||
|
|
||||||
let prefixContainer = null;
|
let prefixContainer = null;
|
||||||
if (prefix) {
|
if (prefixComponent) {
|
||||||
prefixContainer = <span className="mx_Field_prefix">{prefix}</span>;
|
prefixContainer = <span className="mx_Field_prefix">{prefixComponent}</span>;
|
||||||
}
|
}
|
||||||
let postfixContainer = null;
|
let postfixContainer = null;
|
||||||
if (postfix) {
|
if (postfixComponent) {
|
||||||
postfixContainer = <span className="mx_Field_postfix">{postfix}</span>;
|
postfixContainer = <span className="mx_Field_postfix">{postfixComponent}</span>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasValidationFlag = flagInvalid !== null && flagInvalid !== undefined;
|
const hasValidationFlag = flagInvalid !== null && flagInvalid !== undefined;
|
||||||
|
@ -198,7 +219,7 @@ export default class Field extends React.PureComponent {
|
||||||
// If we have a prefix element, leave the label always at the top left and
|
// If we have a prefix element, leave the label always at the top left and
|
||||||
// don't animate it, as it looks a bit clunky and would add complexity to do
|
// don't animate it, as it looks a bit clunky and would add complexity to do
|
||||||
// properly.
|
// properly.
|
||||||
mx_Field_labelAlwaysTopLeft: prefix,
|
mx_Field_labelAlwaysTopLeft: prefixComponent,
|
||||||
mx_Field_valid: onValidate && this.state.valid === true,
|
mx_Field_valid: onValidate && this.state.valid === true,
|
||||||
mx_Field_invalid: hasValidationFlag
|
mx_Field_invalid: hasValidationFlag
|
||||||
? flagInvalid
|
? flagInvalid
|
|
@ -18,67 +18,68 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
import React from 'react';
|
import React, { Component } from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import createReactClass from 'create-react-class';
|
|
||||||
import dis from '../../../dispatcher/dispatcher';
|
import dis from '../../../dispatcher/dispatcher';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { ViewTooltipPayload } from '../../../dispatcher/payloads/ViewUserPayload';
|
||||||
|
import { Action } from '../../../dispatcher/actions';
|
||||||
|
|
||||||
const MIN_TOOLTIP_HEIGHT = 25;
|
const MIN_TOOLTIP_HEIGHT = 25;
|
||||||
|
|
||||||
export default createReactClass({
|
interface IProps {
|
||||||
displayName: 'Tooltip',
|
|
||||||
|
|
||||||
propTypes: {
|
|
||||||
// Class applied to the element used to position the tooltip
|
// Class applied to the element used to position the tooltip
|
||||||
className: PropTypes.string,
|
className: string,
|
||||||
// Class applied to the tooltip itself
|
// Class applied to the tooltip itself
|
||||||
tooltipClassName: PropTypes.string,
|
tooltipClassName: string,
|
||||||
// Whether the tooltip is visible or hidden.
|
// Whether the tooltip is visible or hidden.
|
||||||
// The hidden state allows animating the tooltip away via CSS.
|
// The hidden state allows animating the tooltip away via CSS.
|
||||||
// Defaults to visible if unset.
|
// Defaults to visible if unset.
|
||||||
visible: PropTypes.bool,
|
visible: boolean,
|
||||||
// the react element to put into the tooltip
|
// the react element to put into the tooltip
|
||||||
label: PropTypes.node,
|
label: React.ReactNode,
|
||||||
},
|
}
|
||||||
|
|
||||||
getDefaultProps() {
|
class Tooltip extends React.Component<IProps> {
|
||||||
return {
|
private tooltipContainer: HTMLElement;
|
||||||
visible: true,
|
private tooltip: void | Element | Component<Element, any, any>;
|
||||||
};
|
private parent: Element;
|
||||||
},
|
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
visible: true,
|
||||||
|
};
|
||||||
|
|
||||||
// Create a wrapper for the tooltip outside the parent and attach it to the body element
|
// Create a wrapper for the tooltip outside the parent and attach it to the body element
|
||||||
componentDidMount: function() {
|
componentDidMount() {
|
||||||
this.tooltipContainer = document.createElement("div");
|
this.tooltipContainer = document.createElement("div");
|
||||||
this.tooltipContainer.className = "mx_Tooltip_wrapper";
|
this.tooltipContainer.className = "mx_Tooltip_wrapper";
|
||||||
document.body.appendChild(this.tooltipContainer);
|
document.body.appendChild(this.tooltipContainer);
|
||||||
window.addEventListener('scroll', this._renderTooltip, true);
|
window.addEventListener('scroll', this.renderTooltip, true);
|
||||||
|
|
||||||
this.parent = ReactDOM.findDOMNode(this).parentNode;
|
this.parent = ReactDOM.findDOMNode(this).parentNode as Element;
|
||||||
|
|
||||||
this._renderTooltip();
|
this.renderTooltip();
|
||||||
},
|
}
|
||||||
|
|
||||||
componentDidUpdate: function() {
|
componentDidUpdate() {
|
||||||
this._renderTooltip();
|
this.renderTooltip();
|
||||||
},
|
}
|
||||||
|
|
||||||
// Remove the wrapper element, as the tooltip has finished using it
|
// Remove the wrapper element, as the tooltip has finished using it
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount() {
|
||||||
dis.dispatch({
|
dis.dispatch<ViewTooltipPayload>({
|
||||||
action: 'view_tooltip',
|
action: Action.ViewTooltip,
|
||||||
tooltip: null,
|
tooltip: null,
|
||||||
parent: null,
|
parent: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
ReactDOM.unmountComponentAtNode(this.tooltipContainer);
|
ReactDOM.unmountComponentAtNode(this.tooltipContainer);
|
||||||
document.body.removeChild(this.tooltipContainer);
|
document.body.removeChild(this.tooltipContainer);
|
||||||
window.removeEventListener('scroll', this._renderTooltip, true);
|
window.removeEventListener('scroll', this.renderTooltip, true);
|
||||||
},
|
}
|
||||||
|
|
||||||
_updatePosition(style) {
|
private updatePosition(style: {[key: string]: any}) {
|
||||||
const parentBox = this.parent.getBoundingClientRect();
|
const parentBox = this.parent.getBoundingClientRect();
|
||||||
let offset = 0;
|
let offset = 0;
|
||||||
if (parentBox.height > MIN_TOOLTIP_HEIGHT) {
|
if (parentBox.height > MIN_TOOLTIP_HEIGHT) {
|
||||||
|
@ -91,16 +92,15 @@ export default createReactClass({
|
||||||
style.top = (parentBox.top - 2) + window.pageYOffset + offset;
|
style.top = (parentBox.top - 2) + window.pageYOffset + offset;
|
||||||
style.left = 6 + parentBox.right + window.pageXOffset;
|
style.left = 6 + parentBox.right + window.pageXOffset;
|
||||||
return style;
|
return style;
|
||||||
},
|
}
|
||||||
|
|
||||||
_renderTooltip: function() {
|
private renderTooltip() {
|
||||||
// Add the parent's position to the tooltips, so it's correctly
|
// Add the parent's position to the tooltips, so it's correctly
|
||||||
// positioned, also taking into account any window zoom
|
// positioned, also taking into account any window zoom
|
||||||
// NOTE: The additional 6 pixels for the left position, is to take account of the
|
// NOTE: The additional 6 pixels for the left position, is to take account of the
|
||||||
// tooltips chevron
|
// tooltips chevron
|
||||||
const parent = ReactDOM.findDOMNode(this).parentNode;
|
const parent = ReactDOM.findDOMNode(this).parentNode as Element;
|
||||||
let style = {};
|
const style = this.updatePosition({});
|
||||||
style = this._updatePosition(style);
|
|
||||||
// Hide the entire container when not visible. This prevents flashing of the tooltip
|
// Hide the entire container when not visible. This prevents flashing of the tooltip
|
||||||
// if it is not meant to be visible on first mount.
|
// if it is not meant to be visible on first mount.
|
||||||
style.display = this.props.visible ? "block" : "none";
|
style.display = this.props.visible ? "block" : "none";
|
||||||
|
@ -118,21 +118,21 @@ export default createReactClass({
|
||||||
);
|
);
|
||||||
|
|
||||||
// Render the tooltip manually, as we wish it not to be rendered within the parent
|
// Render the tooltip manually, as we wish it not to be rendered within the parent
|
||||||
this.tooltip = ReactDOM.render(tooltip, this.tooltipContainer);
|
this.tooltip = ReactDOM.render<Element>(tooltip, this.tooltipContainer);
|
||||||
|
|
||||||
// Tell the roomlist about us so it can manipulate us if it wishes
|
// Tell the roomlist about us so it can manipulate us if it wishes
|
||||||
dis.dispatch({
|
dis.dispatch<ViewTooltipPayload>({
|
||||||
action: 'view_tooltip',
|
action: Action.ViewTooltip,
|
||||||
tooltip: this.tooltip,
|
tooltip: this.tooltip,
|
||||||
parent: parent,
|
parent: parent,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
|
|
||||||
render: function() {
|
render() {
|
||||||
// Render a placeholder
|
// Render a placeholder
|
||||||
return (
|
return (
|
||||||
<div className={this.props.className} >
|
<div className={this.props.className} >
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
});
|
}
|
|
@ -267,7 +267,7 @@ export default class PhoneNumbers extends React.Component {
|
||||||
label={_t("Phone Number")}
|
label={_t("Phone Number")}
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
disabled={this.state.verifying}
|
disabled={this.state.verifying}
|
||||||
prefix={phoneCountry}
|
prefixComponent={phoneCountry}
|
||||||
value={this.state.newPhoneNumber}
|
value={this.state.newPhoneNumber}
|
||||||
onChange={this._onChangeNewPhoneNumber}
|
onChange={this._onChangeNewPhoneNumber}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -38,5 +38,10 @@ export enum Action {
|
||||||
* Open the user settings. No additional payload information required.
|
* Open the user settings. No additional payload information required.
|
||||||
*/
|
*/
|
||||||
ViewUserSettings = "view_user_settings",
|
ViewUserSettings = "view_user_settings",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current tooltip
|
||||||
|
*/
|
||||||
|
ViewTooltip = "view_tooltip",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||||
import { ActionPayload } from "../payloads";
|
import { ActionPayload } from "../payloads";
|
||||||
import { Action } from "../actions";
|
import { Action } from "../actions";
|
||||||
|
import { Component } from "react";
|
||||||
|
|
||||||
export interface ViewUserPayload extends ActionPayload {
|
export interface ViewUserPayload extends ActionPayload {
|
||||||
action: Action.ViewUser,
|
action: Action.ViewUser,
|
||||||
|
@ -27,3 +28,19 @@ export interface ViewUserPayload extends ActionPayload {
|
||||||
*/
|
*/
|
||||||
member?: RoomMember;
|
member?: RoomMember;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ViewTooltipPayload extends ActionPayload {
|
||||||
|
action: Action.ViewTooltip,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The tooltip to render. If it's null the tooltip will not be rendered
|
||||||
|
* We need the void type because of typescript headaches.
|
||||||
|
*/
|
||||||
|
tooltip: null | void | Element | Component<Element, any, any>;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The parent under which to render the tooltip. Can be null to remove
|
||||||
|
* the parent type.
|
||||||
|
*/
|
||||||
|
parent: null | Element
|
||||||
|
}
|
||||||
|
|
12
yarn.lock
12
yarn.lock
|
@ -1265,6 +1265,11 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339"
|
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339"
|
||||||
integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==
|
integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==
|
||||||
|
|
||||||
|
"@types/lodash@^4.14.152":
|
||||||
|
version "4.14.152"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.152.tgz#7e7679250adce14e749304cdb570969f77ec997c"
|
||||||
|
integrity sha512-Vwf9YF2x1GE3WNeUMjT5bTHa2DqgUo87ocdgTScupY2JclZ5Nn7W2RLM/N0+oreexUk8uaVugR81NnTY/jNNXg==
|
||||||
|
|
||||||
"@types/minimatch@*":
|
"@types/minimatch@*":
|
||||||
version "3.0.3"
|
version "3.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
|
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
|
||||||
|
@ -1292,6 +1297,13 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/react-dom@^16.9.8":
|
||||||
|
version "16.9.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.8.tgz#fe4c1e11dfc67155733dfa6aa65108b4971cb423"
|
||||||
|
integrity sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA==
|
||||||
|
dependencies:
|
||||||
|
"@types/react" "*"
|
||||||
|
|
||||||
"@types/react@*":
|
"@types/react@*":
|
||||||
version "16.9.35"
|
version "16.9.35"
|
||||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.35.tgz#a0830d172e8aadd9bd41709ba2281a3124bbd368"
|
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.35.tgz#a0830d172e8aadd9bd41709ba2281a3124bbd368"
|
||||||
|
|
Loading…
Reference in a new issue