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() { constructor() {
super(EMOJI_REGEX); super(EMOJI_REGEX);
this.matcher = new QueryMatcher(EMOJI_SHORTNAMES, { this.matcher = new QueryMatcher<IEmojiShort>(EMOJI_SHORTNAMES, {
keys: ['emoji.emoticon', 'shortname'], keys: ['emoji.emoticon', 'shortname'],
funcs: [ funcs: [
(o) => o.emoji.shortcodes.length > 1 ? o.emoji.shortcodes.slice(1).map(s => `:${s}:`).join(" ") : "", // aliases (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 * @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 * 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 _options: IOptions<T>;
private _keys: IOptions<T>["keys"]; private _keys: IOptions<T>["keys"];
private _funcs: Required<IOptions<T>["funcs"]>; private _funcs: Required<IOptions<T>["funcs"]>;
@ -75,7 +75,10 @@ export default class QueryMatcher<T> {
this._items = new Map(); this._items = new Map();
for (const object of objects) { 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) { for (const f of this._funcs) {
keyValues.push(f(object)); keyValues.push(f(object));

View file

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

View file

@ -17,7 +17,8 @@ limitations under the License.
import React from 'react'; import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import * as sdk from '../../../index'; 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. // Invoke validation from user input (when typing, etc.) at most once every N ms.
const VALIDATION_THROTTLE_MS = 200; const VALIDATION_THROTTLE_MS = 200;
@ -28,7 +29,7 @@ function getId() {
return `${BASE_ID}_${count++}`; 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. // The field's ID, which binds the input and label together. Immutable.
id?: string, id?: string,
// The element to create. Defaults to "input". // 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 // 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?: (input: IFieldState) => Promise<IValidationResult>,
args: {value: string, focused: boolean, allowEmpty: boolean}
) => {valid: boolean, feedback: React.ReactNode},
// If specified, overrides the value returned by onValidate. // If specified, overrides the value returned by onValidate.
flagInvalid?: boolean, flagInvalid?: boolean,
// If specified, contents will appear as a tooltip on the element and // 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 id: string;
private input: HTMLInputElement; private input: HTMLInputElement;
static defaultProps = {
element: "input",
type: "text",
}
/* /*
* This was changed from throttle to debounce: this is more traditional for * 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 * 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, element, prefixComponent, postfixComponent, className, onValidate, children,
tooltipContent, flagInvalid, tooltipClassName, list, ...inputProps} = this.props; tooltipContent, flagInvalid, tooltipClassName, list, ...inputProps} = this.props;
const inputElement = element || "input";
// Set some defaults for the <input> element // Set some defaults for the <input> element
inputProps.type = inputProps.type || "text";
const 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
@ -203,7 +204,7 @@ export default class Field extends React.PureComponent<IProps, IState> {
// Appease typescript's inference // Appease typescript's inference
const inputProps_ = {...inputProps, ref, list}; const inputProps_ = {...inputProps, ref, list};
const fieldInput = React.createElement(inputElement, inputProps_, children); const fieldInput = React.createElement(this.props.element, inputProps_, children);
let prefixContainer = null; let prefixContainer = null;
if (prefixComponent) { if (prefixComponent) {
@ -215,7 +216,7 @@ export default class Field extends React.PureComponent<IProps, IState> {
} }
const hasValidationFlag = flagInvalid !== null && flagInvalid !== undefined; 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 // 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.

840
yarn.lock

File diff suppressed because it is too large Load diff