Types exiliary files
This commit is contained in:
parent
63f78b0808
commit
5c9398a6b1
5 changed files with 449 additions and 423 deletions
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -36,7 +36,7 @@ interface IProps {
|
|||
labelStrongPassword?: string;
|
||||
labelAllowedButUnsafe?: string;
|
||||
|
||||
onChange(ev: KeyboardEvent);
|
||||
onChange(ev: React.FormEvent<HTMLElement>);
|
||||
onValidate(result: IValidationResult);
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue