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() {
|
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
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Reference in a new issue