web-ui-pack
Version:
Web package with UI elements
156 lines (155 loc) • 6.72 kB
TypeScript
import WUPPopupElement from "../popup/popupElement";
import { MenuOpenCases } from "./baseCombo";
import { SetValueReasons } from "./baseControl";
import WUPSelectControl from "./select";
declare const tagName = "wup-selectmany";
declare global {
namespace WUP.SelectMany {
interface EventMap extends WUP.BaseCombo.EventMap {
}
interface ValidityMap extends WUP.BaseCombo.ValidityMap {
}
interface NewOptions {
/** Hide items in menu that selected
* @defaultValue false */
hideSelected: boolean;
/** Allow user to change ordering of items; Use drag&drop or keyboard Shift/Ctrl/Meta + arrows to change item position
* @defaultValue false */
sortable: boolean;
}
interface Options<T = any, VM = ValidityMap> extends WUP.Select.Options<T, VM>, NewOptions {
/** @readonly Constant value that impossible to change */
multiple: true;
}
interface JSXProps<C = WUPSelectManyControl> extends WUP.Select.JSXProps<C>, WUP.Base.OnlyNames<NewOptions> {
"w-hideSelected"?: boolean | "";
"w-sortable"?: boolean | "";
}
}
interface HTMLElementTagNameMap {
[tagName]: WUPSelectManyControl;
}
}
declare module "react" {
namespace JSX {
interface IntrinsicElements {
/** Form-control with dropdown/combobox behavior
* @see {@link WUPSelectManyControl} */
[tagName]: WUP.Base.ReactHTML<WUPSelectManyControl> & WUP.SelectMany.JSXProps;
}
}
}
declare module "preact/jsx-runtime" {
namespace JSX {
interface HTMLAttributes<RefType> {
}
interface IntrinsicElements {
/** Form-control with dropdown/combobox behavior
* @see {@link WUPSelectManyControl} */
[tagName]: HTMLAttributes<WUPSelectManyControl> & WUP.SelectMany.JSXProps;
}
}
}
/** Form-control with dropdown/combobox behavior
* @see demo {@link https://yegorich555.github.io/web-ui-pack/control/selectMany}
* @example
const el = document.createElement("wup-selectmany");
el.$options.name = "gender";
el.$options.items = [
{ value: 1, text: "Male" },
{ value: 2, text: "Female" },
{ value: 3, text: "Other/Skip" },
];
el.$initValue = [3];
el.$options.validations = { required: true };
const form = document.body.appendChild(document.createElement("wup-form"));
form.appendChild(el);
// or HTML
<wup-form>
<wup-selectmany w-name="gender" w-initvalue="window.myInitValue" w-validations="myValidations" w-items="window.myDropdownItems" />
</wup-form>;
@tutorial Troubleshooting
* * Accessibility. Screen readers announce 'blank' when focus on not-empty control.
Solution not found (using contenteditable fixes this but provides more other bugs)
* @tutorial innerHTML @example
* <label>
* <span> // extra span requires to use with icons via label:before, label:after without adjustments
* <span [item]>Item 1</span>
* <span [item]>Item 2</span>
* // etc/
* <input/>
* <strong>{$options.label}</strong>
* </span>
* <button clear/>
* <wup-popup menu>
* <ul>
* <li>Item 1</li>
* <li>Item 2</li>
* // etc/
* </ul>
* </wup-popup>
* </label>
*/
export default class WUPSelectManyControl<ValueType = any, TOptions extends WUP.SelectMany.Options = WUP.SelectMany.Options, EventMap extends WUP.SelectMany.EventMap = WUP.SelectMany.EventMap> extends WUPSelectControl<ValueType[], ValueType, TOptions, EventMap> {
#private;
static get $styleRoot(): string;
static get $style(): string;
static $isEmpty(v: unknown[] | undefined): boolean;
static $filterMenuItem(this: WUPSelectManyControl, menuItemText: string, menuItemValue: any, inputValue: string, inputRawValue: string): boolean;
static $defaults: WUP.SelectMany.Options;
/** Items selected & rendered on control */
$refItems?: Array<HTMLElement & {
_wupValue: ValueType;
}>;
protected renderControl(): void;
protected canHandleUndo(): boolean;
canParseInput(_text: string): boolean;
parseInput(text: string): ValueType[] | undefined;
protected gotChanges(propsChanged: Array<keyof WUP.Select.Options> | null): void;
/** It prevents menu opening if user tries sorting and focus got after mouseUp */
_wasSortAfterClick?: boolean;
/** Call it to remove dragdrop logic */
_disposeDragdrop?: () => void;
/** Called to apply dragdrop logic */
protected applyDragdrop(): void;
canOpenMenu(openCase: MenuOpenCases, e?: MouseEvent | FocusEvent | KeyboardEvent | null): boolean;
protected renderMenu(popup: WUPPopupElement, menuId: string): HTMLElement;
/** Called to update/remove selected items on control */
protected renderItems(v: ValueType[], all: WUP.Select.MenuItem<any>[]): void;
/** Announce items as single value on change if element is focused */
protected ariaSpeakValue(): void;
protected resetInputValue(): void;
protected valueToInput(v: ValueType[] | undefined, isReset?: boolean): string;
protected selectValue(v: ValueType, canCloseMenu?: boolean): void;
/** Index of focused value-item */
_focusIndex?: number;
/** Focus value-item by index (related to this.$refItems) */
protected focusItemByIndex(i: number | null): void;
protected focusMenuItem(next: HTMLElement | null): void;
protected selectMenuItemByValue(v: ValueType[] | undefined): void;
protected selectMenuItem(next: HTMLElement | null): void;
protected clearFilterMenuItems(): void;
/** Called to remove item with animation */
protected removeValue(index: number): void;
protected setValue(v: ValueType[] | undefined, reason: SetValueReasons, skipInput?: boolean): boolean | null;
protected gotFocus(ev: FocusEvent): Array<() => void>;
protected gotFocusLost(): void;
protected gotKeyDown(e: KeyboardEvent): void;
}
export {};
/**
* known issues when 'contenteditable':
*
* <span contenteditalbe='true'>
* <span></span>
* <span contenteditalbe='false'>Item 1</span>
* <span></span>
* <span contenteditalbe='false'>Item 2</span>
* <span>Input text here</span>
* </span>
* 01. NVDA. Reads only first line (the same issue for textarea)
* 02. NVDA. Reads only first item in Firefox (when :after exists)
* 1. Firefox. Caret position is wrong/missed between Items is use try to use ArrowKeys
* 2. Firefox. Caret position is missed if no empty spans between items
* 3. Without contenteditalbe='false' browser moves cursor into item, but it should be outside
*/