Types exiliary files

This commit is contained in:
Jorik Schellekens 2020-05-25 16:47:57 +01:00
parent 63f78b0808
commit 5c9398a6b1
5 changed files with 449 additions and 423 deletions

View file

@ -69,7 +69,7 @@ export default class EmojiProvider extends AutocompleteProvider {
constructor() {
super(EMOJI_REGEX);
this.matcher = new QueryMatcher(EMOJI_SHORTNAMES, {
this.matcher = new QueryMatcher<IEmojiShort>(EMOJI_SHORTNAMES, {
keys: ['emoji.emoticon', 'shortname'],
funcs: [
(o) => o.emoji.shortcodes.length > 1 ? o.emoji.shortcodes.slice(1).map(s => `:${s}:`).join(" ") : "", // aliases

View file

@ -45,7 +45,7 @@ interface IOptions<T extends {}> {
* @param {function[]} options.funcs List of functions that when called with the
* object as an arg will return a string to use as an index
*/
export default class QueryMatcher<T> {
export default class QueryMatcher<T extends Object> {
private _options: IOptions<T>;
private _keys: IOptions<T>["keys"];
private _funcs: Required<IOptions<T>["funcs"]>;
@ -75,7 +75,10 @@ export default class QueryMatcher<T> {
this._items = new Map();
for (const object of objects) {
const keyValues = _at(object, this._keys);
// Need to use unsafe coerce here because the objects can have any
// type for their values. We assume that those values who's keys have
// been specified will be string.
const keyValues: (string)[] = _at<T>(object as any, this._keys) as any;
for (const f of this._funcs) {
keyValues.push(f(object));

View file

@ -36,7 +36,7 @@ interface IProps {
labelStrongPassword?: string;
labelAllowedButUnsafe?: string;
onChange(ev: KeyboardEvent);
onChange(ev: React.FormEvent<HTMLElement>);
onValidate(result: IValidationResult);
}

View file

@ -17,7 +17,8 @@ limitations under the License.
import React from 'react';
import classNames from 'classnames';
import * as sdk from '../../../index';
import { debounce, Cancelable } from 'lodash';
import { debounce } from 'lodash';
import {IFieldState, IValidationResult} from "../elements/Validation";
// Invoke validation from user input (when typing, etc.) at most once every N ms.
const VALIDATION_THROTTLE_MS = 200;
@ -28,7 +29,7 @@ function getId() {
return `${BASE_ID}_${count++}`;
}
interface IProps extends React.HTMLAttributes<HTMLElement> {
interface IProps extends React.InputHTMLAttributes<HTMLSelectElement | HTMLInputElement> {
// The field's ID, which binds the input and label together. Immutable.
id?: string,
// The element to create. Defaults to "input".
@ -53,9 +54,7 @@ interface IProps extends React.HTMLAttributes<HTMLElement> {
// changes. Returns an object with `valid` boolean field
// and a `feedback` react component field to provide feedback
// to the user.
onValidate?: (
args: {value: string, focused: boolean, allowEmpty: boolean}
) => {valid: boolean, feedback: React.ReactNode},
onValidate?: (input: IFieldState) => Promise<IValidationResult>,
// If specified, overrides the value returned by onValidate.
flagInvalid?: boolean,
// If specified, contents will appear as a tooltip on the element and
@ -86,6 +85,11 @@ export default class Field extends React.PureComponent<IProps, IState> {
private id: string;
private input: HTMLInputElement;
static defaultProps = {
element: "input",
type: "text",
}
/*
* 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
@ -188,10 +192,7 @@ export default class Field extends React.PureComponent<IProps, IState> {
element, prefixComponent, postfixComponent, className, onValidate, children,
tooltipContent, flagInvalid, tooltipClassName, list, ...inputProps} = this.props;
const inputElement = element || "input";
// Set some defaults for the <input> element
inputProps.type = inputProps.type || "text";
const ref = input => this.input = input;
inputProps.placeholder = inputProps.placeholder || inputProps.label;
inputProps.id = this.id; // this overwrites the id from props
@ -203,7 +204,7 @@ export default class Field extends React.PureComponent<IProps, IState> {
// Appease typescript's inference
const inputProps_ = {...inputProps, ref, list};
const fieldInput = React.createElement(inputElement, inputProps_, children);
const fieldInput = React.createElement(this.props.element, inputProps_, children);
let prefixContainer = null;
if (prefixComponent) {
@ -215,7 +216,7 @@ export default class Field extends React.PureComponent<IProps, IState> {
}
const hasValidationFlag = flagInvalid !== null && flagInvalid !== undefined;
const fieldClasses = classNames("mx_Field", `mx_Field_${inputElement}`, className, {
const fieldClasses = classNames("mx_Field", `mx_Field_${this.props.element}`, className, {
// 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
// properly.

840
yarn.lock

File diff suppressed because it is too large Load diff