@3mo/segmented-input 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/InputSegment.d.ts +34 -0
- package/dist/InputSegment.d.ts.map +1 -0
- package/dist/InputSegment.js +3 -0
- package/dist/SegmentedDisplayController.d.ts +105 -0
- package/dist/SegmentedDisplayController.d.ts.map +1 -0
- package/dist/SegmentedDisplayController.js +208 -0
- package/dist/SegmentedInputController.d.ts +148 -0
- package/dist/SegmentedInputController.d.ts.map +1 -0
- package/dist/SegmentedInputController.js +450 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/setOrRemove.d.ts +3 -0
- package/dist/setOrRemove.d.ts.map +1 -0
- package/dist/setOrRemove.js +4 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +36 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One unit of a value as an input renders it — a year, a digit of a code, a group of a card number —
|
|
3
|
+
* or a literal separator between two of them.
|
|
4
|
+
*
|
|
5
|
+
* A segment is a *description*, not state: a host derives the whole array from its own value on every
|
|
6
|
+
* render, and a controller stamps it onto the elements. A host with more to say about its units
|
|
7
|
+
* extends the type and gets its own segments back from every callback.
|
|
8
|
+
*/
|
|
9
|
+
export type InputSegment = LiteralSegment | EditableSegment;
|
|
10
|
+
/** A separator between two units: shown, never focused, hidden from assistive technology. */
|
|
11
|
+
export interface LiteralSegment {
|
|
12
|
+
readonly key: string;
|
|
13
|
+
readonly editable: false;
|
|
14
|
+
readonly text: string;
|
|
15
|
+
}
|
|
16
|
+
export interface EditableSegment {
|
|
17
|
+
/** Identifies the segment within its group, e.g. "day" or "cell-3". */
|
|
18
|
+
readonly key: string;
|
|
19
|
+
readonly editable: true;
|
|
20
|
+
/** What the element shows: the entered text, or the placeholder while unfilled. */
|
|
21
|
+
readonly text: string;
|
|
22
|
+
/** Whether the unit has been entered. */
|
|
23
|
+
readonly filled: boolean;
|
|
24
|
+
/** The most characters the segment holds. Decides when typing moves on. Defaults to one. */
|
|
25
|
+
readonly capacity?: number;
|
|
26
|
+
/** The unit's own accessible name, e.g. "Monat" or "Digit 3 of 6". */
|
|
27
|
+
readonly label?: string;
|
|
28
|
+
/** The `inputmode` of the segment's element, e.g. "numeric". Left off for units which take letters. */
|
|
29
|
+
readonly inputMode?: string;
|
|
30
|
+
}
|
|
31
|
+
export declare function isEditableSegment<TSegment extends InputSegment>(segment: TSegment): segment is TSegment & EditableSegment;
|
|
32
|
+
/** What a step key asks of a segment. */
|
|
33
|
+
export type SegmentedInputStep = 'increment' | 'decrement' | 'incrementPage' | 'decrementPage' | 'min' | 'max';
|
|
34
|
+
//# sourceMappingURL=InputSegment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InputSegment.d.ts","sourceRoot":"","sources":["../InputSegment.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG,eAAe,CAAA;AAE3D,6FAA6F;AAC7F,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,eAAe;IAC/B,uEAAuE;IACvE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAA;IACvB,mFAAmF;IACnF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,yCAAyC;IACzC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,4FAA4F;IAC5F,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,uGAAuG;IACvG,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,SAAS,YAAY,EAAE,OAAO,EAAE,QAAQ,GAAG,OAAO,IAAI,QAAQ,GAAG,eAAe,CAEzH;AAED,yCAAyC;AACzC,MAAM,MAAM,kBAAkB,GAC3B,WAAW,GACX,WAAW,GACX,eAAe,GACf,eAAe,GACf,KAAK,GACL,KAAK,CAAA"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { Controller, ElementRef, ElementRefs, type ReactiveControllerHost } from '@a11d/lit';
|
|
2
|
+
import { type EditableSegment, type LiteralSegment } from './InputSegment.js';
|
|
3
|
+
export type SegmentedDisplayControllerOptions = {
|
|
4
|
+
/** The whole value, as one string without the separators. */
|
|
5
|
+
readonly value: string;
|
|
6
|
+
/** How many characters the value holds. */
|
|
7
|
+
readonly length: number;
|
|
8
|
+
/** The input's accessible name. */
|
|
9
|
+
readonly label?: string;
|
|
10
|
+
/** Shown by a cell which holds no character yet. */
|
|
11
|
+
readonly placeholder?: string;
|
|
12
|
+
/** Shown by a filled cell in place of its character, for a value which should not be read over a shoulder. */
|
|
13
|
+
readonly mask?: string;
|
|
14
|
+
/** The character positions a separator follows, e.g. `[3]` for "123 456". */
|
|
15
|
+
readonly separators?: ReadonlyArray<number>;
|
|
16
|
+
/** The separator itself. Defaults to a non-breaking hyphen. */
|
|
17
|
+
readonly separator?: string;
|
|
18
|
+
/** Defaults to "one-time-code", which is what lets a phone offer a code it has just received. */
|
|
19
|
+
readonly autocomplete?: string;
|
|
20
|
+
/** Defaults to "numeric". */
|
|
21
|
+
readonly inputMode?: string;
|
|
22
|
+
readonly name?: string;
|
|
23
|
+
readonly disabled?: boolean;
|
|
24
|
+
readonly readonly?: boolean;
|
|
25
|
+
readonly required?: boolean;
|
|
26
|
+
readonly invalid?: boolean;
|
|
27
|
+
/** Filters and normalizes one character of a typed or pasted value; `undefined` drops it. */
|
|
28
|
+
accept?(character: string): string | undefined;
|
|
29
|
+
/** The value as it is typed. */
|
|
30
|
+
handleInput(value: string): void;
|
|
31
|
+
/** The value once the input is left, as the input's own `change` reports it. */
|
|
32
|
+
handleChange?(value: string): void;
|
|
33
|
+
/** The value has just become as long as it can be. Fired once per completion. */
|
|
34
|
+
handleComplete?(value: string): void;
|
|
35
|
+
handleFocusChange?(focused: boolean): void;
|
|
36
|
+
};
|
|
37
|
+
type OptionsOrFactory<THost> = SegmentedDisplayControllerOptions | ((host: THost) => SegmentedDisplayControllerOptions);
|
|
38
|
+
/** A cell knows its position in the value, which is where the caret stands when it is the active one. */
|
|
39
|
+
export type SegmentedDisplaySegment = LiteralSegment | EditableSegment & {
|
|
40
|
+
readonly index: number;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Draws one value as a row of cells while a single real input holds it.
|
|
44
|
+
*
|
|
45
|
+
* ```html
|
|
46
|
+
* <div ${this.display.group.ref()}>
|
|
47
|
+
* <input ${this.display.input.ref()}>
|
|
48
|
+
* ${this.display.segments.map(segment => html`<span ${this.display.segment.ref(segment)}></span>`)}
|
|
49
|
+
* </div>
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* A code is one value, not several: the cells are a drawing of it, and everything which makes a value
|
|
53
|
+
* arrive — a phone offering the code it just received through `autocomplete="one-time-code"`, a
|
|
54
|
+
* password manager filling an authenticator code, a paste into the middle, select-all, undo, the
|
|
55
|
+
* long-press menu — happens on the input, where the platform already implements it. Splitting the
|
|
56
|
+
* value over one input per cell would take all of that away and hand a screen reader six controls
|
|
57
|
+
* where the user has one thing to enter.
|
|
58
|
+
*
|
|
59
|
+
* The cells are hidden from assistive technology for the same reason: the input carries the name, the
|
|
60
|
+
* value and the caret. The host places the input over the cells and paints it transparent — its
|
|
61
|
+
* `::selection` as well, since a selection repaints the text it covers and the value would show
|
|
62
|
+
* through the drawing. The cells mark the selected range themselves, through `data-active`.
|
|
63
|
+
*
|
|
64
|
+
* @ssr false
|
|
65
|
+
*/
|
|
66
|
+
export declare class SegmentedDisplayController<THost extends ReactiveControllerHost = ReactiveControllerHost> extends Controller implements EventListenerObject {
|
|
67
|
+
protected readonly host: THost;
|
|
68
|
+
private static readonly inputEventTypes;
|
|
69
|
+
protected readonly options: SegmentedDisplayControllerOptions;
|
|
70
|
+
/** The element wrapping the input and the cells. */
|
|
71
|
+
readonly group: ElementRef<HTMLElement, void>;
|
|
72
|
+
/** The one real input holding the value. */
|
|
73
|
+
readonly input: ElementRef<HTMLInputElement, void>;
|
|
74
|
+
/** The element drawing one cell, declared with the cell. The controller writes the cell's text into it. */
|
|
75
|
+
readonly segment: ElementRefs<HTMLElement, SegmentedDisplaySegment>;
|
|
76
|
+
private focused;
|
|
77
|
+
private completed;
|
|
78
|
+
constructor(host: THost, options: OptionsOrFactory<THost>);
|
|
79
|
+
/** The cells and the separators between them. */
|
|
80
|
+
get segments(): ReadonlyArray<SegmentedDisplaySegment>;
|
|
81
|
+
/** Whether the caret stands on the cell, or a selection spans it. */
|
|
82
|
+
private isActive;
|
|
83
|
+
get isComplete(): boolean;
|
|
84
|
+
private get editable();
|
|
85
|
+
hostUpdated(): void;
|
|
86
|
+
private listen;
|
|
87
|
+
handleEvent(event: Event): void;
|
|
88
|
+
private stampInput;
|
|
89
|
+
private stampSegment;
|
|
90
|
+
/** Re-reads the value and writes it onto the input and the cells, without waiting for the host to render. */
|
|
91
|
+
refresh(): void;
|
|
92
|
+
focus(): void;
|
|
93
|
+
/** Puts the caret on a cell. */
|
|
94
|
+
select(index: number): void;
|
|
95
|
+
private handleInput;
|
|
96
|
+
private filter;
|
|
97
|
+
private handleFocusChange;
|
|
98
|
+
/**
|
|
99
|
+
* The input covers the cells, so the browser places the caret by the position of a text which is
|
|
100
|
+
* painted transparent. The cell actually pressed is the one under the pointer.
|
|
101
|
+
*/
|
|
102
|
+
private handleClick;
|
|
103
|
+
}
|
|
104
|
+
export {};
|
|
105
|
+
//# sourceMappingURL=SegmentedDisplayController.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SegmentedDisplayController.d.ts","sourceRoot":"","sources":["../SegmentedDisplayController.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { Controller, ElementRef, ElementRefs } from '@a11d/lit';
|
|
2
|
+
import { setOrRemove } from './setOrRemove.js';
|
|
3
|
+
/**
|
|
4
|
+
* Draws one value as a row of cells while a single real input holds it.
|
|
5
|
+
*
|
|
6
|
+
* ```html
|
|
7
|
+
* <div ${this.display.group.ref()}>
|
|
8
|
+
* <input ${this.display.input.ref()}>
|
|
9
|
+
* ${this.display.segments.map(segment => html`<span ${this.display.segment.ref(segment)}></span>`)}
|
|
10
|
+
* </div>
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* A code is one value, not several: the cells are a drawing of it, and everything which makes a value
|
|
14
|
+
* arrive — a phone offering the code it just received through `autocomplete="one-time-code"`, a
|
|
15
|
+
* password manager filling an authenticator code, a paste into the middle, select-all, undo, the
|
|
16
|
+
* long-press menu — happens on the input, where the platform already implements it. Splitting the
|
|
17
|
+
* value over one input per cell would take all of that away and hand a screen reader six controls
|
|
18
|
+
* where the user has one thing to enter.
|
|
19
|
+
*
|
|
20
|
+
* The cells are hidden from assistive technology for the same reason: the input carries the name, the
|
|
21
|
+
* value and the caret. The host places the input over the cells and paints it transparent — its
|
|
22
|
+
* `::selection` as well, since a selection repaints the text it covers and the value would show
|
|
23
|
+
* through the drawing. The cells mark the selected range themselves, through `data-active`.
|
|
24
|
+
*
|
|
25
|
+
* @ssr false
|
|
26
|
+
*/
|
|
27
|
+
export class SegmentedDisplayController extends Controller {
|
|
28
|
+
static { this.inputEventTypes = ['input', 'change', 'focus', 'blur', 'select', 'keyup', 'pointerup']; }
|
|
29
|
+
constructor(host, options) {
|
|
30
|
+
super(host);
|
|
31
|
+
this.host = host;
|
|
32
|
+
/** The element wrapping the input and the cells. */
|
|
33
|
+
this.group = new ElementRef({
|
|
34
|
+
updated: element => this.listen(element, ['click'], 'addEventListener'),
|
|
35
|
+
disconnected: element => this.listen(element, ['click'], 'removeEventListener'),
|
|
36
|
+
});
|
|
37
|
+
/** The one real input holding the value. */
|
|
38
|
+
this.input = new ElementRef({
|
|
39
|
+
updated: element => {
|
|
40
|
+
this.listen(element, SegmentedDisplayController.inputEventTypes, 'addEventListener');
|
|
41
|
+
this.stampInput();
|
|
42
|
+
},
|
|
43
|
+
disconnected: element => this.listen(element, SegmentedDisplayController.inputEventTypes, 'removeEventListener'),
|
|
44
|
+
});
|
|
45
|
+
/** The element drawing one cell, declared with the cell. The controller writes the cell's text into it. */
|
|
46
|
+
this.segment = new ElementRefs({
|
|
47
|
+
updated: (element, segment) => this.stampSegment(element, segment),
|
|
48
|
+
});
|
|
49
|
+
this.focused = false;
|
|
50
|
+
this.completed = false;
|
|
51
|
+
this.options = typeof options === 'function' ? options(host) : options;
|
|
52
|
+
}
|
|
53
|
+
/** The cells and the separators between them. */
|
|
54
|
+
get segments() {
|
|
55
|
+
const { value, length, placeholder, mask, separators = [], separator = '‑' } = this.options;
|
|
56
|
+
const segments = new Array();
|
|
57
|
+
for (let index = 0; index < length; index++) {
|
|
58
|
+
const character = value[index];
|
|
59
|
+
segments.push({
|
|
60
|
+
key: `cell-${index}`,
|
|
61
|
+
editable: true,
|
|
62
|
+
index,
|
|
63
|
+
filled: character !== undefined,
|
|
64
|
+
text: character === undefined ? placeholder ?? '' : mask ?? character,
|
|
65
|
+
});
|
|
66
|
+
if (separators.includes(index) && index < length - 1) {
|
|
67
|
+
segments.push({ key: `separator-${index}`, editable: false, text: separator });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return segments;
|
|
71
|
+
}
|
|
72
|
+
/** Whether the caret stands on the cell, or a selection spans it. */
|
|
73
|
+
isActive(index) {
|
|
74
|
+
const element = this.input.value;
|
|
75
|
+
const start = element?.selectionStart ?? this.options.value.length;
|
|
76
|
+
const end = element?.selectionEnd ?? start;
|
|
77
|
+
return start === end
|
|
78
|
+
? index === Math.min(start, this.options.length - 1)
|
|
79
|
+
: index >= start && index < end;
|
|
80
|
+
}
|
|
81
|
+
get isComplete() {
|
|
82
|
+
return this.options.value.length >= this.options.length;
|
|
83
|
+
}
|
|
84
|
+
get editable() {
|
|
85
|
+
return !this.options.disabled && !this.options.readonly;
|
|
86
|
+
}
|
|
87
|
+
hostUpdated() {
|
|
88
|
+
this.refresh();
|
|
89
|
+
}
|
|
90
|
+
listen(element, types, method) {
|
|
91
|
+
for (const type of types) {
|
|
92
|
+
element[method](type, this);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
handleEvent(event) {
|
|
96
|
+
switch (event.type) {
|
|
97
|
+
case 'click': return this.handleClick(event);
|
|
98
|
+
case 'input': return this.handleInput();
|
|
99
|
+
case 'change': return this.options.handleChange?.(this.input.value.value);
|
|
100
|
+
case 'focus': return this.handleFocusChange(true);
|
|
101
|
+
case 'blur': return this.handleFocusChange(false);
|
|
102
|
+
// The caret moved: select, keyup, pointerup.
|
|
103
|
+
default: return this.refresh();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// #region Stamping
|
|
107
|
+
stampInput() {
|
|
108
|
+
const element = this.input.value;
|
|
109
|
+
if (!element) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const { options } = this;
|
|
113
|
+
element.type = 'text';
|
|
114
|
+
element.maxLength = options.length;
|
|
115
|
+
element.inputMode = options.inputMode ?? 'numeric';
|
|
116
|
+
element.setAttribute('autocomplete', options.autocomplete ?? 'one-time-code');
|
|
117
|
+
element.setAttribute('autocapitalize', 'off');
|
|
118
|
+
element.spellcheck = false;
|
|
119
|
+
element.disabled = options.disabled ?? false;
|
|
120
|
+
element.readOnly = options.readonly ?? false;
|
|
121
|
+
element.required = options.required ?? false;
|
|
122
|
+
setOrRemove(element, 'autocorrect', 'off');
|
|
123
|
+
setOrRemove(element, 'aria-label', options.label);
|
|
124
|
+
setOrRemove(element, 'aria-invalid', options.invalid ? 'true' : undefined);
|
|
125
|
+
setOrRemove(element, 'name', options.name);
|
|
126
|
+
if (element.value !== options.value) {
|
|
127
|
+
element.value = options.value;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
stampSegment(element, segment) {
|
|
131
|
+
if (element.textContent !== segment.text) {
|
|
132
|
+
element.textContent = segment.text;
|
|
133
|
+
}
|
|
134
|
+
element.setAttribute('data-segment', segment.key);
|
|
135
|
+
// The input carries the name, the value and the caret; the cells are the drawing of it.
|
|
136
|
+
element.setAttribute('aria-hidden', 'true');
|
|
137
|
+
element.toggleAttribute('data-placeholder', segment.editable && !segment.filled);
|
|
138
|
+
element.toggleAttribute('data-active', segment.editable && this.focused && this.isActive(segment.index));
|
|
139
|
+
}
|
|
140
|
+
/** Re-reads the value and writes it onto the input and the cells, without waiting for the host to render. */
|
|
141
|
+
refresh() {
|
|
142
|
+
this.stampInput();
|
|
143
|
+
const segmentsByKey = new Map(this.segments.map(segment => [segment.key, segment]));
|
|
144
|
+
for (const element of this.segment) {
|
|
145
|
+
const segment = segmentsByKey.get(this.segment.get(element).key);
|
|
146
|
+
if (segment) {
|
|
147
|
+
this.segment.set(element, segment);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// #endregion
|
|
152
|
+
// #region Editing
|
|
153
|
+
focus() {
|
|
154
|
+
this.input.value?.focus();
|
|
155
|
+
}
|
|
156
|
+
/** Puts the caret on a cell. */
|
|
157
|
+
select(index) {
|
|
158
|
+
const position = Math.max(0, Math.min(index, this.options.value.length));
|
|
159
|
+
this.input.value?.setSelectionRange(position, position);
|
|
160
|
+
this.refresh();
|
|
161
|
+
}
|
|
162
|
+
handleInput() {
|
|
163
|
+
const element = this.input.value;
|
|
164
|
+
if (!element) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const value = this.filter(element.value);
|
|
168
|
+
if (element.value !== value) {
|
|
169
|
+
element.value = value;
|
|
170
|
+
}
|
|
171
|
+
this.options.handleInput(value);
|
|
172
|
+
const complete = value.length >= this.options.length;
|
|
173
|
+
if (complete && !this.completed) {
|
|
174
|
+
this.options.handleComplete?.(value);
|
|
175
|
+
}
|
|
176
|
+
this.completed = complete;
|
|
177
|
+
this.refresh();
|
|
178
|
+
this.host.requestUpdate();
|
|
179
|
+
}
|
|
180
|
+
filter(value) {
|
|
181
|
+
const accept = this.options.accept;
|
|
182
|
+
const characters = [...value]
|
|
183
|
+
.map(character => accept ? accept(character) : character)
|
|
184
|
+
.filter((character) => character !== undefined);
|
|
185
|
+
return characters.join('').slice(0, this.options.length);
|
|
186
|
+
}
|
|
187
|
+
handleFocusChange(focused) {
|
|
188
|
+
this.focused = focused;
|
|
189
|
+
this.options.handleFocusChange?.(focused);
|
|
190
|
+
this.refresh();
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* The input covers the cells, so the browser places the caret by the position of a text which is
|
|
194
|
+
* painted transparent. The cell actually pressed is the one under the pointer.
|
|
195
|
+
*/
|
|
196
|
+
handleClick(event) {
|
|
197
|
+
if (!this.editable) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const cells = [...this.segment].filter(element => this.segment.get(element)?.editable);
|
|
201
|
+
const index = cells.findIndex(element => {
|
|
202
|
+
const rect = element.getBoundingClientRect();
|
|
203
|
+
return event.clientX >= rect.left && event.clientX <= rect.right;
|
|
204
|
+
});
|
|
205
|
+
this.focus();
|
|
206
|
+
this.select(index < 0 ? this.options.value.length : index);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { Controller, ElementRef, ElementRefs, type ReactiveControllerHost } from '@a11d/lit';
|
|
2
|
+
import { type EditableSegment, type InputSegment, type SegmentedInputStep } from './InputSegment.js';
|
|
3
|
+
export type SegmentedInputControllerOptions<TSegment extends InputSegment = InputSegment> = {
|
|
4
|
+
/** The segments as the host's value currently reads. Re-read after every interaction. */
|
|
5
|
+
readonly segments: ReadonlyArray<TSegment>;
|
|
6
|
+
/** The field's name, appended to every segment's own name for screen readers which do not announce groups. */
|
|
7
|
+
readonly label?: string;
|
|
8
|
+
/** The whole value in words, announced when the group is entered. */
|
|
9
|
+
readonly description?: string;
|
|
10
|
+
readonly direction?: 'ltr' | 'rtl';
|
|
11
|
+
readonly disabled?: boolean;
|
|
12
|
+
readonly readonly?: boolean;
|
|
13
|
+
readonly required?: boolean;
|
|
14
|
+
readonly invalid?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* The text the segment should hold once `character` is typed into what is already `typed`, or
|
|
17
|
+
* `undefined` to refuse the character. Defaults to appending it. A text longer than the segment's
|
|
18
|
+
* capacity restarts the segment with the character alone.
|
|
19
|
+
*
|
|
20
|
+
* Returning a *shorter* text is how a unit restarts before that: a month holding "1" which is typed
|
|
21
|
+
* "3" answers "3", because "13" is no month.
|
|
22
|
+
*/
|
|
23
|
+
accept?(segment: TSegment & EditableSegment, typed: string, character: string): string | undefined;
|
|
24
|
+
/** Whether no further character could follow `text`, so that the focus moves on. Defaults to the capacity being reached. */
|
|
25
|
+
isComplete?(segment: TSegment & EditableSegment, text: string): boolean;
|
|
26
|
+
/** Everything typed into the segment so far — nothing, once it is emptied. The host decides what, if anything, that means for its value. */
|
|
27
|
+
handleSegmentInput(segment: TSegment & EditableSegment, text: string): void;
|
|
28
|
+
/** Arrow, page, home and end keys. Left out, those keys do nothing and the segments are textboxes rather than spinbuttons. */
|
|
29
|
+
handleStep?(segment: TSegment & EditableSegment, step: SegmentedInputStep): void;
|
|
30
|
+
/** Enter, or the group being left: the moment for the host to complete and hand on its value. */
|
|
31
|
+
handleCommit?(): void;
|
|
32
|
+
/** The whole clipboard text. Return `true` when it was taken. */
|
|
33
|
+
handlePaste?(text: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Letters, and a leading plus or minus, are buffered instead of typed and handed over on Enter, on
|
|
36
|
+
* leaving, or after a pause — the "cheat code" a field may resolve to a whole value. Return `true`
|
|
37
|
+
* when the text was taken. Left out, such characters are ignored.
|
|
38
|
+
*/
|
|
39
|
+
handleShortcut?(text: string): boolean;
|
|
40
|
+
/** The focus would move past the first or last segment — into a neighbouring group, if there is one. */
|
|
41
|
+
handleMoveBeyond?(direction: -1 | 1): void;
|
|
42
|
+
handleFocusChange?(focused: boolean): void;
|
|
43
|
+
/** Stamps whatever the specialization adds to a segment, e.g. the value of a spinbutton. */
|
|
44
|
+
stamp?(element: HTMLElement, segment: TSegment & EditableSegment): void;
|
|
45
|
+
};
|
|
46
|
+
type OptionsOrFactory<TSegment extends InputSegment, THost> = SegmentedInputControllerOptions<TSegment> | ((host: THost) => SegmentedInputControllerOptions<TSegment>);
|
|
47
|
+
/**
|
|
48
|
+
* Turns a group of elements into one input made of several: each segment is focused and typed into on
|
|
49
|
+
* its own, a filled one hands the focus to the next, and the separators between them stay inert.
|
|
50
|
+
*
|
|
51
|
+
* ```html
|
|
52
|
+
* <div ${this.segments.group.ref()}>
|
|
53
|
+
* ${this.segments.segments.map(segment => html`<span ${this.segments.segment.ref(segment)}></span>`)}
|
|
54
|
+
* </div>
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* The controller owns everything on those elements except their styling: ARIA, `tabindex`,
|
|
58
|
+
* `contenteditable`, `data-*` and the rendered text — the template renders empty elements. What the
|
|
59
|
+
* segments *mean* stays with the host: it hands over the segments, is told what was typed into which,
|
|
60
|
+
* and decides what that makes of its value.
|
|
61
|
+
*
|
|
62
|
+
* Unmodified keys are the controller's; a key pressed with Ctrl, Meta or Alt is left to the host.
|
|
63
|
+
*
|
|
64
|
+
* The segments are `contenteditable` rather than inputs so that they size to their content, so that a
|
|
65
|
+
* right-to-left group keeps the order the language reads them in — inputs are atomic to the
|
|
66
|
+
* bidirectional algorithm and come out reversed — and so that the group is one line of text rather
|
|
67
|
+
* than a row of boxes. A value which must be autofilled needs a real input instead: see
|
|
68
|
+
* {@link SegmentedDisplayController}.
|
|
69
|
+
*
|
|
70
|
+
* @ssr false
|
|
71
|
+
*/
|
|
72
|
+
export declare class SegmentedInputController<TSegment extends InputSegment = InputSegment, THost extends ReactiveControllerHost = ReactiveControllerHost> extends Controller implements EventListenerObject {
|
|
73
|
+
protected readonly host: THost;
|
|
74
|
+
/** How long typing may pause before a buffered shortcut is handed over. */
|
|
75
|
+
static readonly shortcutTimeout = 700;
|
|
76
|
+
private static readonly groupEventTypes;
|
|
77
|
+
private static readonly segmentEventTypes;
|
|
78
|
+
protected readonly options: SegmentedInputControllerOptions<TSegment>;
|
|
79
|
+
/** The element wrapping the segments. */
|
|
80
|
+
readonly group: ElementRef<HTMLElement, void>;
|
|
81
|
+
/** The element rendering one segment, declared with the segment. The controller writes the segment's text into it. */
|
|
82
|
+
readonly segment: ElementRefs<HTMLElement, TSegment>;
|
|
83
|
+
private typed;
|
|
84
|
+
private shortcut;
|
|
85
|
+
private shortcutTimer?;
|
|
86
|
+
private focusedKey?;
|
|
87
|
+
private focusedWithin;
|
|
88
|
+
constructor(host: THost, options: OptionsOrFactory<TSegment, THost>);
|
|
89
|
+
get segments(): readonly TSegment[];
|
|
90
|
+
/** The segments which can be focused and typed into, in rendering order. */
|
|
91
|
+
get editableSegments(): (TSegment & EditableSegment)[];
|
|
92
|
+
get isEmpty(): boolean;
|
|
93
|
+
get isComplete(): boolean;
|
|
94
|
+
/** What has been typed into the focused segment but does not yet fill it. */
|
|
95
|
+
get typedText(): string;
|
|
96
|
+
private get editable();
|
|
97
|
+
private get direction();
|
|
98
|
+
/** The punctuation of the group's own literals: typing the separator which is shown moves on to the next segment. */
|
|
99
|
+
private get separators();
|
|
100
|
+
/** The segment the focus rests on when the group is tabbed into: the one it was on, otherwise the first. */
|
|
101
|
+
private get tabStopKey();
|
|
102
|
+
private segmentOf;
|
|
103
|
+
private elementOf;
|
|
104
|
+
hostUpdated(): void;
|
|
105
|
+
hostDisconnected(): void;
|
|
106
|
+
private listen;
|
|
107
|
+
handleEvent(event: Event): void;
|
|
108
|
+
private editableSegmentOn;
|
|
109
|
+
private stampGroup;
|
|
110
|
+
private stampSegment;
|
|
111
|
+
/**
|
|
112
|
+
* Re-reads the segments and writes them onto the elements, without waiting for the host to render,
|
|
113
|
+
* so that a keystroke shows at once.
|
|
114
|
+
*/
|
|
115
|
+
refresh(): void;
|
|
116
|
+
/** What follows every edit: the elements show it at once, the host on its next render. */
|
|
117
|
+
private update;
|
|
118
|
+
focus(key?: string | undefined): void;
|
|
119
|
+
focusFirst(): void;
|
|
120
|
+
focusLast(): void;
|
|
121
|
+
private move;
|
|
122
|
+
private handleFocus;
|
|
123
|
+
private handleFocusIn;
|
|
124
|
+
private handleFocusOut;
|
|
125
|
+
/**
|
|
126
|
+
* An empty field shows nothing until it is entered, so a press cannot have been aimed at the unit it
|
|
127
|
+
* happens to land on: entry starts at the first unit instead. A field already showing a value is a
|
|
128
|
+
* different matter, there the unit under the pointer was chosen. Handled on pointerdown, before the
|
|
129
|
+
* browser begins its own focus change — Blink ignores a `focus()` issued from inside a focus event.
|
|
130
|
+
*/
|
|
131
|
+
private handlePointerDown;
|
|
132
|
+
private handleKeyDown;
|
|
133
|
+
private handleBeforeInput;
|
|
134
|
+
/** Composition cannot be canceled; the segment's own text is put back. */
|
|
135
|
+
private handleInput;
|
|
136
|
+
private handlePaste;
|
|
137
|
+
/** Types text into a segment, character by character, as though it had been keyed in. */
|
|
138
|
+
type(segment: TSegment & EditableSegment, text: string): void;
|
|
139
|
+
private typeCharacter;
|
|
140
|
+
private accept;
|
|
141
|
+
private backspace;
|
|
142
|
+
private extendShortcut;
|
|
143
|
+
private cancelShortcut;
|
|
144
|
+
/** Applies a pending shortcut and lets the host complete and hand on its value. */
|
|
145
|
+
commit(): void;
|
|
146
|
+
}
|
|
147
|
+
export {};
|
|
148
|
+
//# sourceMappingURL=SegmentedInputController.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SegmentedInputController.d.ts","sourceRoot":"","sources":["../SegmentedInputController.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
import { Controller, ElementRef, ElementRefs } from '@a11d/lit';
|
|
2
|
+
import { isEditableSegment } from './InputSegment.js';
|
|
3
|
+
import { setOrRemove } from './setOrRemove.js';
|
|
4
|
+
const stepsByKey = new Map([
|
|
5
|
+
['ArrowUp', 'increment'],
|
|
6
|
+
['ArrowDown', 'decrement'],
|
|
7
|
+
['PageUp', 'incrementPage'],
|
|
8
|
+
['PageDown', 'decrementPage'],
|
|
9
|
+
['Home', 'min'],
|
|
10
|
+
['End', 'max'],
|
|
11
|
+
]);
|
|
12
|
+
/**
|
|
13
|
+
* Turns a group of elements into one input made of several: each segment is focused and typed into on
|
|
14
|
+
* its own, a filled one hands the focus to the next, and the separators between them stay inert.
|
|
15
|
+
*
|
|
16
|
+
* ```html
|
|
17
|
+
* <div ${this.segments.group.ref()}>
|
|
18
|
+
* ${this.segments.segments.map(segment => html`<span ${this.segments.segment.ref(segment)}></span>`)}
|
|
19
|
+
* </div>
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* The controller owns everything on those elements except their styling: ARIA, `tabindex`,
|
|
23
|
+
* `contenteditable`, `data-*` and the rendered text — the template renders empty elements. What the
|
|
24
|
+
* segments *mean* stays with the host: it hands over the segments, is told what was typed into which,
|
|
25
|
+
* and decides what that makes of its value.
|
|
26
|
+
*
|
|
27
|
+
* Unmodified keys are the controller's; a key pressed with Ctrl, Meta or Alt is left to the host.
|
|
28
|
+
*
|
|
29
|
+
* The segments are `contenteditable` rather than inputs so that they size to their content, so that a
|
|
30
|
+
* right-to-left group keeps the order the language reads them in — inputs are atomic to the
|
|
31
|
+
* bidirectional algorithm and come out reversed — and so that the group is one line of text rather
|
|
32
|
+
* than a row of boxes. A value which must be autofilled needs a real input instead: see
|
|
33
|
+
* {@link SegmentedDisplayController}.
|
|
34
|
+
*
|
|
35
|
+
* @ssr false
|
|
36
|
+
*/
|
|
37
|
+
export class SegmentedInputController extends Controller {
|
|
38
|
+
/** How long typing may pause before a buffered shortcut is handed over. */
|
|
39
|
+
static { this.shortcutTimeout = 700; }
|
|
40
|
+
static { this.groupEventTypes = ['focusin', 'focusout', 'pointerdown', 'paste']; }
|
|
41
|
+
static { this.segmentEventTypes = ['focus', 'keydown', 'beforeinput', 'input']; }
|
|
42
|
+
constructor(host, options) {
|
|
43
|
+
super(host);
|
|
44
|
+
this.host = host;
|
|
45
|
+
/** The element wrapping the segments. */
|
|
46
|
+
this.group = new ElementRef({
|
|
47
|
+
updated: element => {
|
|
48
|
+
this.listen(element, SegmentedInputController.groupEventTypes, 'addEventListener');
|
|
49
|
+
this.stampGroup();
|
|
50
|
+
},
|
|
51
|
+
disconnected: element => this.listen(element, SegmentedInputController.groupEventTypes, 'removeEventListener'),
|
|
52
|
+
});
|
|
53
|
+
/** The element rendering one segment, declared with the segment. The controller writes the segment's text into it. */
|
|
54
|
+
this.segment = new ElementRefs({
|
|
55
|
+
updated: (element, segment) => {
|
|
56
|
+
this.listen(element, SegmentedInputController.segmentEventTypes, 'addEventListener');
|
|
57
|
+
this.stampSegment(element, segment);
|
|
58
|
+
},
|
|
59
|
+
disconnected: element => this.listen(element, SegmentedInputController.segmentEventTypes, 'removeEventListener'),
|
|
60
|
+
});
|
|
61
|
+
this.typed = '';
|
|
62
|
+
this.shortcut = '';
|
|
63
|
+
this.focusedWithin = false;
|
|
64
|
+
this.options = typeof options === 'function' ? options(host) : options;
|
|
65
|
+
}
|
|
66
|
+
get segments() {
|
|
67
|
+
return this.options.segments;
|
|
68
|
+
}
|
|
69
|
+
/** The segments which can be focused and typed into, in rendering order. */
|
|
70
|
+
get editableSegments() {
|
|
71
|
+
return this.segments.filter(isEditableSegment);
|
|
72
|
+
}
|
|
73
|
+
get isEmpty() {
|
|
74
|
+
return this.editableSegments.every(segment => !segment.filled);
|
|
75
|
+
}
|
|
76
|
+
get isComplete() {
|
|
77
|
+
return this.editableSegments.every(segment => segment.filled);
|
|
78
|
+
}
|
|
79
|
+
/** What has been typed into the focused segment but does not yet fill it. */
|
|
80
|
+
get typedText() {
|
|
81
|
+
return this.typed;
|
|
82
|
+
}
|
|
83
|
+
get editable() {
|
|
84
|
+
return !this.options.disabled && !this.options.readonly;
|
|
85
|
+
}
|
|
86
|
+
get direction() {
|
|
87
|
+
return this.options.direction ?? 'ltr';
|
|
88
|
+
}
|
|
89
|
+
/** The punctuation of the group's own literals: typing the separator which is shown moves on to the next segment. */
|
|
90
|
+
get separators() {
|
|
91
|
+
return new Set(this.segments
|
|
92
|
+
.filter(segment => !segment.editable)
|
|
93
|
+
.flatMap(segment => [...segment.text])
|
|
94
|
+
.filter(character => !/[\p{L}\p{N}]/u.test(character)));
|
|
95
|
+
}
|
|
96
|
+
/** The segment the focus rests on when the group is tabbed into: the one it was on, otherwise the first. */
|
|
97
|
+
get tabStopKey() {
|
|
98
|
+
return this.segmentOf(this.focusedKey)?.key ?? this.editableSegments[0]?.key;
|
|
99
|
+
}
|
|
100
|
+
segmentOf(key) {
|
|
101
|
+
return key === undefined ? undefined : this.editableSegments.find(segment => segment.key === key);
|
|
102
|
+
}
|
|
103
|
+
elementOf(key) {
|
|
104
|
+
return key === undefined ? undefined : [...this.segment].find(element => this.segment.get(element)?.key === key);
|
|
105
|
+
}
|
|
106
|
+
hostUpdated() {
|
|
107
|
+
this.refresh();
|
|
108
|
+
}
|
|
109
|
+
hostDisconnected() {
|
|
110
|
+
this.cancelShortcut();
|
|
111
|
+
}
|
|
112
|
+
listen(element, types, method) {
|
|
113
|
+
for (const type of types) {
|
|
114
|
+
element[method](type, this);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
handleEvent(event) {
|
|
118
|
+
switch (event.type) {
|
|
119
|
+
case 'focus': return this.handleFocus(event);
|
|
120
|
+
case 'focusin': return this.handleFocusIn();
|
|
121
|
+
case 'focusout': return this.handleFocusOut(event);
|
|
122
|
+
case 'pointerdown': return this.handlePointerDown(event);
|
|
123
|
+
case 'paste': return this.handlePaste(event);
|
|
124
|
+
case 'keydown': return this.handleKeyDown(event);
|
|
125
|
+
case 'beforeinput': return this.handleBeforeInput(event);
|
|
126
|
+
case 'input': return this.handleInput(event);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
editableSegmentOn(event) {
|
|
130
|
+
const segment = this.segment.get(event.currentTarget);
|
|
131
|
+
return segment && isEditableSegment(segment) ? segment : undefined;
|
|
132
|
+
}
|
|
133
|
+
// #region Stamping
|
|
134
|
+
stampGroup() {
|
|
135
|
+
const element = this.group.value;
|
|
136
|
+
if (!element) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const { options } = this;
|
|
140
|
+
element.setAttribute('role', 'group');
|
|
141
|
+
element.setAttribute('dir', this.direction);
|
|
142
|
+
setOrRemove(element, 'aria-label', options.label);
|
|
143
|
+
setOrRemove(element, 'aria-description', options.description);
|
|
144
|
+
setOrRemove(element, 'aria-disabled', options.disabled ? 'true' : undefined);
|
|
145
|
+
setOrRemove(element, 'aria-invalid', options.invalid ? 'true' : undefined);
|
|
146
|
+
setOrRemove(element, 'data-shortcut', this.shortcut || undefined);
|
|
147
|
+
}
|
|
148
|
+
stampSegment(element, segment) {
|
|
149
|
+
const { options } = this;
|
|
150
|
+
if (element.textContent !== segment.text) {
|
|
151
|
+
element.textContent = segment.text;
|
|
152
|
+
}
|
|
153
|
+
element.setAttribute('data-segment', segment.key);
|
|
154
|
+
if (!isEditableSegment(segment)) {
|
|
155
|
+
element.setAttribute('aria-hidden', 'true');
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const editable = this.editable;
|
|
159
|
+
element.setAttribute('role', options.handleStep ? 'spinbutton' : 'textbox');
|
|
160
|
+
element.setAttribute('aria-label', [segment.label, options.label].filter(Boolean).join(', '));
|
|
161
|
+
setOrRemove(element, 'aria-readonly', options.readonly ? 'true' : undefined);
|
|
162
|
+
setOrRemove(element, 'aria-disabled', options.disabled ? 'true' : undefined);
|
|
163
|
+
setOrRemove(element, 'aria-invalid', options.invalid ? 'true' : undefined);
|
|
164
|
+
setOrRemove(element, 'aria-required', options.required ? 'true' : undefined);
|
|
165
|
+
element.toggleAttribute('data-placeholder', !segment.filled);
|
|
166
|
+
setOrRemove(element, 'contenteditable', editable ? 'plaintext-only' : undefined);
|
|
167
|
+
setOrRemove(element, 'inputmode', editable ? segment.inputMode : undefined);
|
|
168
|
+
setOrRemove(element, 'enterkeyhint', editable ? 'next' : undefined);
|
|
169
|
+
setOrRemove(element, 'spellcheck', editable ? 'false' : undefined);
|
|
170
|
+
setOrRemove(element, 'autocorrect', editable ? 'off' : undefined);
|
|
171
|
+
element.tabIndex = options.disabled ? -1 : segment.key === this.tabStopKey ? 0 : -1;
|
|
172
|
+
// Digits are a left-to-right run even in right-to-left text, but a placeholder word is not: the
|
|
173
|
+
// isolation keeps every numeric segment from jumping around as it fills — and, unlike an embedding,
|
|
174
|
+
// keeps the separators between them from fusing the whole group into one left-to-right number.
|
|
175
|
+
const isolate = this.direction === 'rtl' && segment.inputMode === 'numeric';
|
|
176
|
+
element.style.direction = isolate ? 'ltr' : '';
|
|
177
|
+
element.style.unicodeBidi = isolate ? 'isolate' : '';
|
|
178
|
+
options.stamp?.(element, segment);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Re-reads the segments and writes them onto the elements, without waiting for the host to render,
|
|
182
|
+
* so that a keystroke shows at once.
|
|
183
|
+
*/
|
|
184
|
+
refresh() {
|
|
185
|
+
const segmentsByKey = new Map(this.segments.map(segment => [segment.key, segment]));
|
|
186
|
+
for (const element of this.segment) {
|
|
187
|
+
const segment = segmentsByKey.get(this.segment.get(element).key);
|
|
188
|
+
if (segment) {
|
|
189
|
+
this.segment.set(element, segment);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
this.stampGroup();
|
|
193
|
+
}
|
|
194
|
+
/** What follows every edit: the elements show it at once, the host on its next render. */
|
|
195
|
+
update() {
|
|
196
|
+
this.refresh();
|
|
197
|
+
this.host.requestUpdate();
|
|
198
|
+
}
|
|
199
|
+
// #endregion
|
|
200
|
+
// #region Focus
|
|
201
|
+
focus(key = this.tabStopKey) {
|
|
202
|
+
const element = this.elementOf(key);
|
|
203
|
+
if (!element) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
// Recorded before focusing: a programmatic focus raises no focus event in every engine.
|
|
207
|
+
this.focusedKey = key;
|
|
208
|
+
this.typed = '';
|
|
209
|
+
element.focus();
|
|
210
|
+
this.refresh();
|
|
211
|
+
}
|
|
212
|
+
focusFirst() {
|
|
213
|
+
this.focus(this.editableSegments[0]?.key);
|
|
214
|
+
}
|
|
215
|
+
focusLast() {
|
|
216
|
+
this.focus(this.editableSegments.at(-1)?.key);
|
|
217
|
+
}
|
|
218
|
+
move(direction) {
|
|
219
|
+
const segments = this.editableSegments;
|
|
220
|
+
const index = segments.findIndex(segment => segment.key === this.focusedKey);
|
|
221
|
+
const next = segments[index + direction];
|
|
222
|
+
if (index >= 0 && !next) {
|
|
223
|
+
this.typed = '';
|
|
224
|
+
this.options.handleMoveBeyond?.(direction);
|
|
225
|
+
}
|
|
226
|
+
else if (next) {
|
|
227
|
+
this.focus(next.key);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
handleFocus(event) {
|
|
231
|
+
const segment = this.editableSegmentOn(event);
|
|
232
|
+
if (!segment) {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
this.focusedKey = segment.key;
|
|
236
|
+
this.typed = '';
|
|
237
|
+
// A collapsed selection is what keeps Android from composing across the segment's text.
|
|
238
|
+
window.getSelection()?.collapse(event.currentTarget, 0);
|
|
239
|
+
this.refresh();
|
|
240
|
+
}
|
|
241
|
+
handleFocusIn() {
|
|
242
|
+
if (!this.focusedWithin) {
|
|
243
|
+
this.focusedWithin = true;
|
|
244
|
+
this.options.handleFocusChange?.(true);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
handleFocusOut(event) {
|
|
248
|
+
if (event.relatedTarget instanceof Node && this.group.value?.contains(event.relatedTarget)) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
this.focusedWithin = false;
|
|
252
|
+
this.commit();
|
|
253
|
+
// A field left empty forgets where it was, so that the next entry starts at the first unit again.
|
|
254
|
+
if (this.isEmpty) {
|
|
255
|
+
this.focusedKey = undefined;
|
|
256
|
+
this.refresh();
|
|
257
|
+
}
|
|
258
|
+
this.options.handleFocusChange?.(false);
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* An empty field shows nothing until it is entered, so a press cannot have been aimed at the unit it
|
|
262
|
+
* happens to land on: entry starts at the first unit instead. A field already showing a value is a
|
|
263
|
+
* different matter, there the unit under the pointer was chosen. Handled on pointerdown, before the
|
|
264
|
+
* browser begins its own focus change — Blink ignores a `focus()` issued from inside a focus event.
|
|
265
|
+
*/
|
|
266
|
+
handlePointerDown(event) {
|
|
267
|
+
if (this.focusedWithin || !this.isEmpty || !this.editable) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
const first = this.editableSegments[0];
|
|
271
|
+
const pressed = event.composedPath().map(target => this.segment.get(target)).find(Boolean);
|
|
272
|
+
if (!first || pressed?.key === first.key) {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
event.preventDefault();
|
|
276
|
+
this.focusFirst();
|
|
277
|
+
}
|
|
278
|
+
// #endregion
|
|
279
|
+
// #region Editing
|
|
280
|
+
handleKeyDown(event) {
|
|
281
|
+
const segment = this.editableSegmentOn(event);
|
|
282
|
+
if (!segment) {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
if (event.ctrlKey || event.metaKey || event.altKey) {
|
|
286
|
+
if (event.key === 'a') {
|
|
287
|
+
event.preventDefault();
|
|
288
|
+
}
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
const rtl = this.direction === 'rtl';
|
|
292
|
+
const step = stepsByKey.get(event.key);
|
|
293
|
+
if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {
|
|
294
|
+
this.move((event.key === 'ArrowLeft') !== rtl ? -1 : 1);
|
|
295
|
+
}
|
|
296
|
+
else if (step) {
|
|
297
|
+
if (!this.options.handleStep || !this.editable) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
this.typed = '';
|
|
301
|
+
this.options.handleStep(segment, step);
|
|
302
|
+
this.refresh();
|
|
303
|
+
}
|
|
304
|
+
else if (event.key === 'Backspace' || event.key === 'Delete') {
|
|
305
|
+
this.backspace(segment);
|
|
306
|
+
}
|
|
307
|
+
else if (event.key === 'Enter') {
|
|
308
|
+
this.commit();
|
|
309
|
+
}
|
|
310
|
+
else if (event.key === 'Escape' && this.shortcut) {
|
|
311
|
+
this.cancelShortcut();
|
|
312
|
+
this.refresh();
|
|
313
|
+
}
|
|
314
|
+
else if (event.key.length === 1) {
|
|
315
|
+
this.type(segment, event.key);
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
event.preventDefault();
|
|
321
|
+
}
|
|
322
|
+
handleBeforeInput(event) {
|
|
323
|
+
const segment = this.editableSegmentOn(event);
|
|
324
|
+
if (!segment || event.inputType === 'insertCompositionText') {
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
event.preventDefault();
|
|
328
|
+
if (event.inputType === 'deleteContentBackward' || event.inputType === 'deleteContentForward') {
|
|
329
|
+
this.backspace(segment);
|
|
330
|
+
}
|
|
331
|
+
else if (event.inputType.startsWith('insert') && event.data) {
|
|
332
|
+
this.type(segment, event.data);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/** Composition cannot be canceled; the segment's own text is put back. */
|
|
336
|
+
handleInput(event) {
|
|
337
|
+
const element = event.currentTarget;
|
|
338
|
+
const segment = this.segment.get(element);
|
|
339
|
+
if (segment && element.textContent !== segment.text) {
|
|
340
|
+
element.textContent = segment.text;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
handlePaste(event) {
|
|
344
|
+
const text = event.clipboardData?.getData('text')?.trim();
|
|
345
|
+
if (!text || !this.editable) {
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
event.preventDefault();
|
|
349
|
+
if (this.options.handlePaste?.(text)) {
|
|
350
|
+
this.typed = '';
|
|
351
|
+
this.update();
|
|
352
|
+
}
|
|
353
|
+
else if (this.options.handleShortcut) {
|
|
354
|
+
this.shortcut = text;
|
|
355
|
+
this.commit();
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
/** Types text into a segment, character by character, as though it had been keyed in. */
|
|
359
|
+
type(segment, text) {
|
|
360
|
+
if (!this.editable) {
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
// Several characters at once (a paste, an IME commit) flow on into the segment a filled one advanced to.
|
|
364
|
+
let key = segment.key;
|
|
365
|
+
for (const character of text) {
|
|
366
|
+
const current = this.segmentOf(key);
|
|
367
|
+
if (!current) {
|
|
368
|
+
break;
|
|
369
|
+
}
|
|
370
|
+
const focusedBefore = this.focusedKey;
|
|
371
|
+
this.typeCharacter(current, character);
|
|
372
|
+
key = this.focusedKey === focusedBefore ? key : this.focusedKey;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
typeCharacter(segment, character) {
|
|
376
|
+
if (this.shortcut) {
|
|
377
|
+
this.extendShortcut(character);
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
const accepted = this.accept(segment, character);
|
|
381
|
+
if (accepted !== undefined) {
|
|
382
|
+
const complete = this.options.isComplete?.(segment, accepted) ?? accepted.length >= (segment.capacity ?? 1);
|
|
383
|
+
this.typed = complete ? '' : accepted;
|
|
384
|
+
this.options.handleSegmentInput(segment, accepted);
|
|
385
|
+
this.update();
|
|
386
|
+
if (complete) {
|
|
387
|
+
this.move(1);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
else if (this.typed && this.separators.has(character)) {
|
|
391
|
+
this.typed = '';
|
|
392
|
+
this.move(1);
|
|
393
|
+
}
|
|
394
|
+
else if (character === '+' || character === '-' || /\p{L}/u.test(character)) {
|
|
395
|
+
this.extendShortcut(character);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
accept(segment, character) {
|
|
399
|
+
const text = this.options.accept ? this.options.accept(segment, this.typed, character) : this.typed + character;
|
|
400
|
+
return text !== undefined && text.length > (segment.capacity ?? 1) ? character : text;
|
|
401
|
+
}
|
|
402
|
+
backspace(segment) {
|
|
403
|
+
if (!this.editable) {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
if (this.typed.length > 1) {
|
|
407
|
+
this.typed = this.typed.slice(0, -1);
|
|
408
|
+
this.options.handleSegmentInput(segment, this.typed);
|
|
409
|
+
this.update();
|
|
410
|
+
}
|
|
411
|
+
else if (segment.filled || this.typed) {
|
|
412
|
+
this.typed = '';
|
|
413
|
+
this.options.handleSegmentInput(segment, '');
|
|
414
|
+
this.update();
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
this.move(-1);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
// #endregion
|
|
421
|
+
// #region Shortcuts
|
|
422
|
+
extendShortcut(character) {
|
|
423
|
+
if (!this.options.handleShortcut) {
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
this.shortcut += character;
|
|
427
|
+
clearTimeout(this.shortcutTimer);
|
|
428
|
+
this.shortcutTimer = setTimeout(() => this.commit(), SegmentedInputController.shortcutTimeout);
|
|
429
|
+
this.stampGroup();
|
|
430
|
+
}
|
|
431
|
+
cancelShortcut() {
|
|
432
|
+
clearTimeout(this.shortcutTimer);
|
|
433
|
+
this.shortcutTimer = undefined;
|
|
434
|
+
this.shortcut = '';
|
|
435
|
+
}
|
|
436
|
+
// #endregion
|
|
437
|
+
/** Applies a pending shortcut and lets the host complete and hand on its value. */
|
|
438
|
+
commit() {
|
|
439
|
+
const shortcut = this.shortcut;
|
|
440
|
+
this.cancelShortcut();
|
|
441
|
+
if (shortcut) {
|
|
442
|
+
this.options.handleShortcut?.(shortcut);
|
|
443
|
+
}
|
|
444
|
+
this.typed = '';
|
|
445
|
+
if (this.editable) {
|
|
446
|
+
this.options.handleCommit?.();
|
|
447
|
+
}
|
|
448
|
+
this.update();
|
|
449
|
+
}
|
|
450
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,iCAAiC,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setOrRemove.d.ts","sourceRoot":"","sources":["../setOrRemove.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,QAEpF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"fileNames":["../../../node_modules/typescript/lib/lib.es5.d.ts","../../../node_modules/typescript/lib/lib.es2015.d.ts","../../../node_modules/typescript/lib/lib.es2016.d.ts","../../../node_modules/typescript/lib/lib.es2017.d.ts","../../../node_modules/typescript/lib/lib.es2018.d.ts","../../../node_modules/typescript/lib/lib.es2019.d.ts","../../../node_modules/typescript/lib/lib.es2020.d.ts","../../../node_modules/typescript/lib/lib.es2021.d.ts","../../../node_modules/typescript/lib/lib.es2022.d.ts","../../../node_modules/typescript/lib/lib.dom.d.ts","../../../node_modules/typescript/lib/lib.dom.iterable.d.ts","../../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../node_modules/typescript/lib/lib.es2016.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../../node_modules/typescript/lib/lib.es2017.date.d.ts","../../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../../node_modules/typescript/lib/lib.es2021.promise.d.ts","../../../node_modules/typescript/lib/lib.es2021.string.d.ts","../../../node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../../node_modules/typescript/lib/lib.es2021.intl.d.ts","../../../node_modules/typescript/lib/lib.es2022.array.d.ts","../../../node_modules/typescript/lib/lib.es2022.error.d.ts","../../../node_modules/typescript/lib/lib.es2022.intl.d.ts","../../../node_modules/typescript/lib/lib.es2022.object.d.ts","../../../node_modules/typescript/lib/lib.es2022.string.d.ts","../../../node_modules/typescript/lib/lib.es2022.regexp.d.ts","../../../node_modules/typescript/lib/lib.decorators.d.ts","../../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../../node_modules/tslib/tslib.d.ts","../../../node_modules/tslib/modules/index.d.ts","../inputsegment.ts","../../../node_modules/@a11d/constructor/dist/constructor.d.ts","../../../node_modules/@a11d/constructor/dist/index.d.ts","../../../node_modules/@lit/reactive-element/development/css-tag.d.ts","../../../node_modules/@lit/reactive-element/development/reactive-controller.d.ts","../../../node_modules/@lit/reactive-element/development/reactive-element.d.ts","../../../node_modules/lit-html/development/directive.d.ts","../../../node_modules/@types/trusted-types/lib/index.d.ts","../../../node_modules/lit-html/development/lit-html.d.ts","../../../node_modules/lit-element/development/lit-element.d.ts","../../../node_modules/lit-html/development/is-server.d.ts","../../../node_modules/lit/development/index.d.ts","../../../node_modules/@lit/reactive-element/development/decorators/base.d.ts","../../../node_modules/@lit/reactive-element/development/decorators/custom-element.d.ts","../../../node_modules/@lit/reactive-element/development/decorators/property.d.ts","../../../node_modules/@lit/reactive-element/development/decorators/state.d.ts","../../../node_modules/@lit/reactive-element/development/decorators/event-options.d.ts","../../../node_modules/@lit/reactive-element/development/decorators/query.d.ts","../../../node_modules/@lit/reactive-element/development/decorators/query-all.d.ts","../../../node_modules/@lit/reactive-element/development/decorators/query-async.d.ts","../../../node_modules/@lit/reactive-element/development/decorators/query-assigned-nodes.d.ts","../../../node_modules/@lit/reactive-element/development/decorators/query-assigned-elements.d.ts","../../../node_modules/lit/development/decorators.d.ts","../../../node_modules/lit-html/development/static.d.ts","../../../node_modules/lit/development/static-html.d.ts","../../../node_modules/lit-html/development/directive-helpers.d.ts","../../../node_modules/lit-html/development/async-directive.d.ts","../../../node_modules/lit-html/development/directives/async-replace.d.ts","../../../node_modules/lit-html/development/directives/async-append.d.ts","../../../node_modules/lit-html/development/directives/cache.d.ts","../../../node_modules/lit-html/development/directives/choose.d.ts","../../../node_modules/lit-html/development/directives/class-map.d.ts","../../../node_modules/lit-html/development/directives/guard.d.ts","../../../node_modules/lit-html/development/directives/if-defined.d.ts","../../../node_modules/lit-html/development/directives/join.d.ts","../../../node_modules/lit-html/development/directives/keyed.d.ts","../../../node_modules/lit-html/development/directives/live.d.ts","../../../node_modules/lit-html/development/directives/map.d.ts","../../../node_modules/lit-html/development/directives/range.d.ts","../../../node_modules/lit-html/development/directives/ref.d.ts","../../../node_modules/lit-html/development/directives/repeat.d.ts","../../../node_modules/lit-html/development/directives/style-map.d.ts","../../../node_modules/lit-html/development/directives/template-content.d.ts","../../../node_modules/lit-html/development/directives/unsafe-html.d.ts","../../../node_modules/lit-html/development/directives/unsafe-svg.d.ts","../../../node_modules/lit-html/development/directives/until.d.ts","../../../node_modules/lit-html/development/directives/when.d.ts","../../../node_modules/@a11d/lit/dist/component/html.d.ts","../../../node_modules/@a11d/lit/dist/component/component.d.ts","../../../node_modules/@a11d/lit/dist/component/index.d.ts","../../../node_modules/@a11d/lit/dist/host.d.ts","../../../node_modules/@a11d/lit/dist/controller/controller.d.ts","../../../node_modules/@a11d/lit/dist/controller/index.d.ts","../../../node_modules/@a11d/lit/dist/componentpart/componentpart.d.ts","../../../node_modules/@a11d/lit/dist/componentpart/index.d.ts","../../../node_modules/@a11d/lit/dist/elementref/elementreflifecycle.d.ts","../../../node_modules/@a11d/lit/dist/elementref/elementref.d.ts","../../../node_modules/@a11d/lit/dist/elementref/elementrefs.d.ts","../../../node_modules/@a11d/lit/dist/elementref/index.d.ts","../../../node_modules/@a11d/lit/dist/query/query.d.ts","../../../node_modules/@a11d/lit/dist/query/queryall.d.ts","../../../node_modules/@a11d/lit/dist/query/queryallasnodelist.d.ts","../../../node_modules/@a11d/lit/dist/query/queryconnectedinstances.d.ts","../../../node_modules/@a11d/lit/dist/query/index.d.ts","../../../node_modules/csstype/index.d.ts","../../../node_modules/@a11d/lit/dist/style/style.d.ts","../../../node_modules/@a11d/lit/dist/style/index.d.ts","../../../node_modules/@a11d/lit/dist/updated/updatedcontroller.d.ts","../../../node_modules/@a11d/lit/dist/updated/updated.d.ts","../../../node_modules/@a11d/lit/dist/updated/index.d.ts","../../../node_modules/@a11d/lit/dist/eventlistener/extracteventtargets.d.ts","../../../node_modules/@a11d/lit/dist/eventlistener/eventlistener.d.ts","../../../node_modules/@a11d/lit/dist/eventlistener/extracteventhandler.d.ts","../../../node_modules/@a11d/lit/dist/eventlistener/eventlistenercontroller.d.ts","../../../node_modules/@a11d/lit/dist/eventlistener/index.d.ts","../../../node_modules/@a11d/lit/dist/event/eventdispatcher.d.ts","../../../node_modules/@a11d/lit/dist/event/pureeventdispatcher.d.ts","../../../node_modules/@a11d/lit/dist/event/htmlelementeventdispatcher.d.ts","../../../node_modules/@a11d/lit/dist/event/event.d.ts","../../../node_modules/@a11d/lit/dist/event/index.d.ts","../../../node_modules/@a11d/lit/dist/bind/bindingdefaultproperty.d.ts","../../../node_modules/@a11d/lit/dist/bind/associatedevent/associatedevent.d.ts","../../../node_modules/@a11d/is-writable/dist/iswritable.d.ts","../../../node_modules/@a11d/is-writable/dist/index.d.ts","../../../node_modules/@a11d/key-path/dist/keypath.d.ts","../../../node_modules/@a11d/key-path/dist/index.d.ts","../../../node_modules/@a11d/lit/dist/bind/binddirective.d.ts","../../../node_modules/@a11d/lit/dist/bind/valuebinder.d.ts","../../../node_modules/@a11d/lit/dist/bind/binder.d.ts","../../../node_modules/@a11d/lit/dist/bind/bindingintegration.d.ts","../../../node_modules/@a11d/lit/dist/bind/nativeelementsupport.d.ts","../../../node_modules/@a11d/lit/dist/bind/index.d.ts","../../../node_modules/@a11d/lit/dist/property.d.ts","../../../node_modules/@a11d/lit/dist/state.d.ts","../../../node_modules/@a11d/lit/dist/index.d.ts","../setorremove.ts","../segmenteddisplaycontroller.ts","../segmentedinputcontroller.ts","../index.ts"],"fileIdsList":[[63],[144],[146],[145],[73],[147,156],[68,70,148,149],[156],[149],[142,143,148,150,151,152],[73,148],[70,73,84],[109,110],[73,114],[115],[73,112],[113],[117,156],[117,118,119],[137,138,139,140],[73,113,132],[132,133,134,135],[67,73],[64,68,70,73,84,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,111,112,114,116,120,125,128,131,136,141,153,154,155],[73,129],[121,122,123,124],[73,113],[84],[73,84,113,129],[127],[68,126,156],[129,130],[73,113,129],[112,114],[74],[67,74,112],[67,74,82,112],[76],[65,66],[67,70,112],[68,70],[70],[68,70,89],[68,70,88],[68],[68,70,105],[70,88],[68,69],[75,76,77,78,79,80,81,82,83],[67,70,71,72,112],[85],[60],[61,62,158,159],[61],[61,62,156,157]],"fileInfos":[{"version":"bcd24271a113971ba9eb71ff8cb01bc6b0f872a85c23fdbe5d93065b375933cd","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f88bedbeb09c6f5a6645cb24c7c55f1aa22d19ae96c8e6959cbd8b85a707bc6","impliedFormat":1},{"version":"7fe93b39b810eadd916be8db880dd7f0f7012a5cc6ffb62de8f62a2117fa6f1f","impliedFormat":1},{"version":"bb0074cc08b84a2374af33d8bf044b80851ccc9e719a5e202eacf40db2c31600","impliedFormat":1},{"version":"1a7daebe4f45fb03d9ec53d60008fbf9ac45a697fdc89e4ce218bc94b94f94d6","impliedFormat":1},{"version":"f94b133a3cb14a288803be545ac2683e0d0ff6661bcd37e31aaaec54fc382aed","impliedFormat":1},{"version":"f59d0650799f8782fd74cf73c19223730c6d1b9198671b1c5b3a38e1188b5953","impliedFormat":1},{"version":"8a15b4607d9a499e2dbeed9ec0d3c0d7372c850b2d5f1fb259e8f6d41d468a84","impliedFormat":1},{"version":"26e0fe14baee4e127f4365d1ae0b276f400562e45e19e35fd2d4c296684715e6","impliedFormat":1},{"version":"d6b1eba8496bdd0eed6fc8a685768fe01b2da4a0388b5fe7df558290bffcf32f","affectsGlobalScope":true,"impliedFormat":1},{"version":"7f57fc4404ff020bc45b9c620aff2b40f700b95fe31164024c453a5e3c163c54","impliedFormat":1},{"version":"eadcffda2aa84802c73938e589b9e58248d74c59cb7fcbca6474e3435ac15504","affectsGlobalScope":true,"impliedFormat":1},{"version":"105ba8ff7ba746404fe1a2e189d1d3d2e0eb29a08c18dded791af02f29fb4711","affectsGlobalScope":true,"impliedFormat":1},{"version":"00343ca5b2e3d48fa5df1db6e32ea2a59afab09590274a6cccb1dbae82e60c7c","affectsGlobalScope":true,"impliedFormat":1},{"version":"ebd9f816d4002697cb2864bea1f0b70a103124e18a8cd9645eeccc09bdf80ab4","affectsGlobalScope":true,"impliedFormat":1},{"version":"2c1afac30a01772cd2a9a298a7ce7706b5892e447bb46bdbeef720f7b5da77ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"7b0225f483e4fa685625ebe43dd584bb7973bbd84e66a6ba7bbe175ee1048b4f","affectsGlobalScope":true,"impliedFormat":1},{"version":"c0a4b8ac6ce74679c1da2b3795296f5896e31c38e888469a8e0f99dc3305de60","affectsGlobalScope":true,"impliedFormat":1},{"version":"3084a7b5f569088e0146533a00830e206565de65cae2239509168b11434cd84f","affectsGlobalScope":true,"impliedFormat":1},{"version":"c5079c53f0f141a0698faa903e76cb41cd664e3efb01cc17a5c46ec2eb0bef42","affectsGlobalScope":true,"impliedFormat":1},{"version":"32cafbc484dea6b0ab62cf8473182bbcb23020d70845b406f80b7526f38ae862","affectsGlobalScope":true,"impliedFormat":1},{"version":"fca4cdcb6d6c5ef18a869003d02c9f0fd95df8cfaf6eb431cd3376bc034cad36","affectsGlobalScope":true,"impliedFormat":1},{"version":"b93ec88115de9a9dc1b602291b85baf825c85666bf25985cc5f698073892b467","affectsGlobalScope":true,"impliedFormat":1},{"version":"f5c06dcc3fe849fcb297c247865a161f995cc29de7aa823afdd75aaaddc1419b","affectsGlobalScope":true,"impliedFormat":1},{"version":"b77e16112127a4b169ef0b8c3a4d730edf459c5f25fe52d5e436a6919206c4d7","affectsGlobalScope":true,"impliedFormat":1},{"version":"fbffd9337146eff822c7c00acbb78b01ea7ea23987f6c961eba689349e744f8c","affectsGlobalScope":true,"impliedFormat":1},{"version":"a995c0e49b721312f74fdfb89e4ba29bd9824c770bbb4021d74d2bf560e4c6bd","affectsGlobalScope":true,"impliedFormat":1},{"version":"c7b3542146734342e440a84b213384bfa188835537ddbda50d30766f0593aff9","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce6180fa19b1cccd07ee7f7dbb9a367ac19c0ed160573e4686425060b6df7f57","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f02e2476bccb9dbe21280d6090f0df17d2f66b74711489415a8aa4df73c9675","affectsGlobalScope":true,"impliedFormat":1},{"version":"45e3ab34c1c013c8ab2dc1ba4c80c780744b13b5676800ae2e3be27ae862c40c","affectsGlobalScope":true,"impliedFormat":1},{"version":"805c86f6cca8d7702a62a844856dbaa2a3fd2abef0536e65d48732441dde5b5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"e42e397f1a5a77994f0185fd1466520691456c772d06bf843e5084ceb879a0ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"f4c2b41f90c95b1c532ecc874bd3c111865793b23aebcc1c3cbbabcd5d76ffb0","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab26191cfad5b66afa11b8bf935ef1cd88fabfcb28d30b2dfa6fad877d050332","affectsGlobalScope":true,"impliedFormat":1},{"version":"2088bc26531e38fb05eedac2951480db5309f6be3fa4a08d2221abb0f5b4200d","affectsGlobalScope":true,"impliedFormat":1},{"version":"cb9d366c425fea79716a8fb3af0d78e6b22ebbab3bd64d25063b42dc9f531c1e","affectsGlobalScope":true,"impliedFormat":1},{"version":"500934a8089c26d57ebdb688fc9757389bb6207a3c8f0674d68efa900d2abb34","affectsGlobalScope":true,"impliedFormat":1},{"version":"689da16f46e647cef0d64b0def88910e818a5877ca5379ede156ca3afb780ac3","affectsGlobalScope":true,"impliedFormat":1},{"version":"bc21cc8b6fee4f4c2440d08035b7ea3c06b3511314c8bab6bef7a92de58a2593","affectsGlobalScope":true,"impliedFormat":1},{"version":"7ca53d13d2957003abb47922a71866ba7cb2068f8d154877c596d63c359fed25","affectsGlobalScope":true,"impliedFormat":1},{"version":"54725f8c4df3d900cb4dac84b64689ce29548da0b4e9b7c2de61d41c79293611","affectsGlobalScope":true,"impliedFormat":1},{"version":"e5594bc3076ac29e6c1ebda77939bc4c8833de72f654b6e376862c0473199323","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f3eb332c2d73e729f3364fcc0c2b375e72a121e8157d25a82d67a138c83a95c","affectsGlobalScope":true,"impliedFormat":1},{"version":"6f4427f9642ce8d500970e4e69d1397f64072ab73b97e476b4002a646ac743b1","affectsGlobalScope":true,"impliedFormat":1},{"version":"48915f327cd1dea4d7bd358d9dc7732f58f9e1626a29cc0c05c8c692419d9bb7","affectsGlobalScope":true,"impliedFormat":1},{"version":"b7bf9377723203b5a6a4b920164df22d56a43f593269ba6ae1fdc97774b68855","affectsGlobalScope":true,"impliedFormat":1},{"version":"db9709688f82c9e5f65a119c64d835f906efe5f559d08b11642d56eb85b79357","affectsGlobalScope":true,"impliedFormat":1},{"version":"4b25b8c874acd1a4cf8444c3617e037d444d19080ac9f634b405583fd10ce1f7","affectsGlobalScope":true,"impliedFormat":1},{"version":"37be57d7c90cf1f8112ee2636a068d8fd181289f82b744160ec56a7dc158a9f5","affectsGlobalScope":true,"impliedFormat":1},{"version":"a917a49ac94cd26b754ab84e113369a75d1a47a710661d7cd25e961cc797065f","affectsGlobalScope":true,"impliedFormat":1},{"version":"6d3261badeb7843d157ef3e6f5d1427d0eeb0af0cf9df84a62cfd29fd47ac86e","affectsGlobalScope":true,"impliedFormat":1},{"version":"195daca651dde22f2167ac0d0a05e215308119a3100f5e6268e8317d05a92526","affectsGlobalScope":true,"impliedFormat":1},{"version":"8b11e4285cd2bb164a4dc09248bdec69e9842517db4ca47c1ba913011e44ff2f","affectsGlobalScope":true,"impliedFormat":1},{"version":"0508571a52475e245b02bc50fa1394065a0a3d05277fbf5120c3784b85651799","affectsGlobalScope":true,"impliedFormat":1},{"version":"8f9af488f510c3015af3cc8c267a9e9d96c4dd38a1fdff0e11dc5a544711415b","affectsGlobalScope":true,"impliedFormat":1},{"version":"fc611fea8d30ea72c6bbfb599c9b4d393ce22e2f5bfef2172534781e7d138104","affectsGlobalScope":true,"impliedFormat":1},{"version":"1ce14b81c5cc821994aa8ec1d42b220dd41b27fcc06373bce3958af7421b77d4","affectsGlobalScope":true,"impliedFormat":1},{"version":"b3a048b3e9302ef9a34ef4ebb9aecfb28b66abb3bce577206a79fee559c230da","affectsGlobalScope":true,"impliedFormat":1},{"version":"a6a5253138c5432c68a1510c70fe78a644fe2e632111ba778e1978010d6edfec","impliedFormat":1},{"version":"b8f34dd1757f68e03262b1ca3ddfa668a855b872f8bdd5224d6f993a7b37dc2c","impliedFormat":99},{"version":"254b376821f2b7debb644762088b00856f85e069bd7c8f98b442f5317c645b69","signature":"3a096d0bf11218875715ef0a882062689571f724572f3b5b6f2b51e78b2395a5","impliedFormat":99},{"version":"eaf71303faefce7c63f3da861d339223be2e958279aaa97368310b9751dad0bc","affectsGlobalScope":true,"impliedFormat":99},{"version":"104f2db43e0d3ce214e6fef01e5ea6e1b834094a27ad84381846c1a7a9b3d36f","impliedFormat":99},{"version":"74012d464fbc5354ca3a7d5e71bee43b17da01a853c8ff10971bbe3680c76f40","impliedFormat":99},{"version":"5e30131b6a5587fe666926ad1d9807e733c0a597ed12d682669fcaa331aea576","impliedFormat":99},{"version":"a0f82d2f9450bd147a8c137798d9501bd49b7c9e118f75b07b76709ff39b6b55","affectsGlobalScope":true,"impliedFormat":99},{"version":"00cb63103f9670f8094c238a4a7e252c8b4c06ba371fea5c44add7e41b7247e4","impliedFormat":99},{"version":"15fe687c59d62741b4494d5e623d497d55eb38966ecf5bea7f36e48fc3fbe15e","impliedFormat":1},{"version":"e09db3291e6b440f7debed2227d8357e80c95987a0d0d67ac17521d8f7b11bdb","impliedFormat":99},{"version":"9a318e3a8900672b85cd3c8c3a5acf51b88049557a3ae897ccdcf2b85a8f61f9","impliedFormat":99},{"version":"1bcd560deed90a43c51b08aa18f7f55229f2e30974ab5ed1b7bb5721be379013","impliedFormat":99},{"version":"dc08fe04e50bc24d1baded4f33e942222bbdd5d77d6341a93cfe6e4e4586a3be","impliedFormat":99},{"version":"cdeae34aca6700620ebf3f27cf7d439c3af97595dd6e2729fa4780483add5680","impliedFormat":99},{"version":"3ff87ea3471b51beaf4aa8fd8f4422862b11d343fdbb55bf383e0f8cc195a445","impliedFormat":99},{"version":"99bdf729529cdbf12e2bf76ea751b662011133dcf9e35abcb3def47bb02f7b0a","impliedFormat":99},{"version":"732fb71ecb695d6f36ddcbb72ebfe4ff6b6491d45101a00fa2b75a26b80d640f","impliedFormat":99},{"version":"039cb05125d7621f8143616c495b8e6b54249c4e64d2754b80ff93867f7f4b01","impliedFormat":99},{"version":"1b81f1fa82ad30af01ab1cae91ccaddc10c48f5916bbd6d282155e44a65d858d","impliedFormat":99},{"version":"a0fc7a02a75802678a67000607f20266cf1a49dc0e787967efe514e31b9ed0c3","impliedFormat":99},{"version":"5ebf098a1d81d400b8af82807cf19893700335cf91a7b9dbd83a5d737af34b11","impliedFormat":99},{"version":"101cf83ac3f9c5e1a7355a02e4fbe988877ef83c4ebec0ff0f02b2af022254a3","impliedFormat":99},{"version":"d017e2fcd44b46ca80cd2b592a6314e75f5caab5bda230f0f4a45e964049a43a","impliedFormat":99},{"version":"a8992b852521a66f63e0cedc6e1f054b28f972232b6fa5ca59771db6a1c8bbea","impliedFormat":99},{"version":"fa8ef3fb228e258f9508386e2056c95c959d1c1168301181313a5c978754ba70","impliedFormat":99},{"version":"15c9478a8a3d630ac5e738aca25fca15d0842aaeb97fb1a9c1e80eddc5a0e14c","impliedFormat":99},{"version":"18b503f13b418f532ffdf558cf58f70f3cdc4dafa5dd45f882e881745a0af67d","impliedFormat":99},{"version":"c42f9b18f5f559b133cf9b409f678afb30df9c6498865aae9a1abad0f1e727a8","impliedFormat":99},{"version":"feaf207fddc69de2a8826438be06f5f954964cddc8e95bf980c9fe02cb22616a","impliedFormat":99},{"version":"22a1db6ed8bebd4969610da4ac82e6b821123f20862abe04992aed979f990c56","impliedFormat":99},{"version":"89069f48799198a4faeddffd2324ddd831fc8e099b5b1917bfeee379c2013773","impliedFormat":99},{"version":"430575191b1f9413196a64d611ff48edcd8d038a558e087143e287638a87c4c6","impliedFormat":99},{"version":"9e77270468dc77ee3f0182f377a6022b37cce590cab79205c497cfb964ee2d20","impliedFormat":99},{"version":"65925d46dcd2c666c08b1c2c18031cfef6e46e43adbe0eee06c66fa00f9ef4eb","impliedFormat":99},{"version":"74fe889b1d2bba4b2893d518ba94e2b20dabe6d19d0c2f9554d9a5d3755710f4","impliedFormat":99},{"version":"f599ef6a8f8678be036ae5ac26b00657664ed26d9e0ebaf9244739b267410646","impliedFormat":99},{"version":"e752c35aa2c473cb8c9c0a7d1330063c0a98ed5d421a6c25afefebdca805b876","impliedFormat":99},{"version":"81f64e790559d21c168e85c0f8e1ceb745b1906863a220c2b3c03aa4a636fad8","impliedFormat":99},{"version":"f0d4da8c4cc589095f0c2dc87ba5cd73394c382b54793357b6cf821dbd26c8e4","impliedFormat":99},{"version":"8eda58842fed4ca236afe50dd183d569d2cf0cb99be517e955c1c033d8b6bd58","impliedFormat":99},{"version":"5ba86f64dbaa08c0c799710953b7277e198c06e36efa9c1103774e7119c6ef7c","impliedFormat":99},{"version":"a4bbe05f59182f4ce279bf92b2fcf9ce52fe1a9feba61867aa97e11eaa1912aa","impliedFormat":99},{"version":"fb605fccb30512c9291061c381cba041e06b51d10479d1589441e9468a32363e","impliedFormat":99},{"version":"c50cdef58c53c1f6ccddb43b206fb327857af2bac581192d325ee8df817638d5","impliedFormat":99},{"version":"33b3c0269bf9dd055b94fe52c0e7e26b8a764274f2270a4a3d4a3ee2872165ba","impliedFormat":99},{"version":"ccf24cd06f3a6ed653dbfcfd162241399c727bfedd91ce5e6fabfa1e1796c37e","impliedFormat":99},{"version":"f4b26b8107218c67993b23418c9f07888651ef7106a611fa2ec30a2f8b61efd9","impliedFormat":99},{"version":"fe7cba26a13d8bb7d59328df2d4fa91a762cb92de62f163ff698829ce8fef4b3","impliedFormat":99},{"version":"463faba982eb24996db72bb4899e99101fccdb4d1e434fa083d3146eab8dbd32","impliedFormat":99},{"version":"3a3741a6cf7f8ca06277e50b08def1673a1cdf438dd3d8a6dfb196c7aa2de655","impliedFormat":99},{"version":"aef0f46ff1d6f3961e63b341fea232b5f4519895c56e7807362725bd26e7e04c","impliedFormat":99},{"version":"7c09943890cda5522989ef21807fb99486db66f53d693f6c3a81fec879a901fd","impliedFormat":99},{"version":"142b48dd12b9eca45ebbff239e6fded2def675ff0bc6f5ea9d93612ffdc6d83a","impliedFormat":99},{"version":"927f5e39c8cae873fb3cdbb93b4cc5d302decbfb8f5d9b2113988dcf8a150371","impliedFormat":99},{"version":"ec94a50e817108482f5ddd4fce1d5ab52074fd89dfdea50f2742479f5adc0ed8","impliedFormat":99},{"version":"f37df6ceb53c4c79e0a70d9bca6ea746a19d1ecd90cbb3c3ac5b28eadb4efe1f","impliedFormat":99},{"version":"ea8e9b396327865bea37657f064323973955230e5f16eb160f24342ac71af4fb","impliedFormat":99},{"version":"b0290b4354f2164c2f43de9d3a8481801f7f6bc84150bd5d53dcdd91ff77f96d","impliedFormat":99},{"version":"aa4d9388ee8674acd8fb5d995b9d3022f2e2e81c4d981dd153c50692c5c44e1a","impliedFormat":99},{"version":"32d52dbf16d4e4a1daed88ab9165fed74156b7c781eba9cf8642b0ba3fbdb035","impliedFormat":99},{"version":"efffd49dfa12fd5c6f24cbe265f4049b14595f86cb10476ea8bc225645e3fd7f","impliedFormat":99},{"version":"4274ddc03a8fac2badee8ce0ec80aaf875528d666a65767268d4bada0e23e7de","impliedFormat":99},{"version":"dba12ebd03d0b06be80194e5ef9e83f87405ebfbffe263bd1c612174a7b72520","impliedFormat":99},{"version":"0a01f0e57f3277e4e13dd32918829f1db7c88339741752b15cb4e120dbf3a28b","impliedFormat":99},{"version":"077579a47c807da116d314be5a8e24fdbb453d139c16343dff93f1a50bd57728","impliedFormat":99},{"version":"ac51dd7d31333793807a6abaa5ae168512b6131bd41d9c5b98477fc3b7800f9f","impliedFormat":1},{"version":"f06781c32d2a93598d926cdd1ae54b29e1b1c8d0bdfa5d95339cbd8ed15f8b6c","impliedFormat":99},{"version":"86ee3d380037ab37ffa8910edec153967b3b1a6c63d6e39a6d5d77c5559a2404","impliedFormat":99},{"version":"1957cb806ea15d65c96346a3372493bd0f86ab3cce9c8c9fe6b042278a391239","impliedFormat":99},{"version":"d842c91613e134202281bed1f6a26a08bfd7608037770c5d9cd5c4a44fa86ae6","impliedFormat":99},{"version":"a2aef0e5c2af0088cc43ff756c4ae1282d1d88f85c6ec7e1472dbe48b1226911","impliedFormat":99},{"version":"b6774952752576e2b90ab3a9e0e6122f1b086648a8d1266aba4ce19f22b7ac8b","impliedFormat":99},{"version":"36f13ff5166642b1597397ee27892fd0e6bb0dd652cb3904f1d43c9ebc4b38ad","impliedFormat":99},{"version":"019a7d171d48aec3d22b042b4f4a1699af13f34f26e3177ef5fdae9f6af072ee","impliedFormat":99},{"version":"869a30bb3d1996964cd1f6bda791d93732bdaa156e46da98ca748207c1d708fa","impliedFormat":99},{"version":"93cfb10a4b87c84d8c823bc624b3cd3a313d5c16a7c17e50273c4dca99b91340","impliedFormat":99},{"version":"9a3edeb212dd00a8a24c582d780f831bb779ea9ae4fa34b4279561887d4bd066","affectsGlobalScope":true,"impliedFormat":99},{"version":"72d30486d50c5624b446418a54c93ef2cdfb781ee5801fec3ef642094498c640","impliedFormat":99},{"version":"091729c3d769cc65f63d535d4998222f16da87311f5f6fc49e407b1dbd39d274","impliedFormat":99},{"version":"6fcdc851702e0f11209d63a1415d9148351e6738e38faee6eb67b7effc53f1c4","impliedFormat":99},{"version":"673a6be5d1871dc1c26385ffb6bee5cee8c914195502e67c7a830c8058ea3a22","impliedFormat":99},{"version":"de3ed1b1858b41b404e8d6cfa8f00f2a848287046dbeaa95729b712176b43d56","impliedFormat":99},{"version":"478459149b5c95a3edf38882f327b6f6ce19f6dc9cf3ec644a67d4cb242dca5c","impliedFormat":99},{"version":"3e168ef532d11e93595146147fb6a0730806a1938d68245539bdbce909ed2d78","affectsGlobalScope":true,"impliedFormat":99},{"version":"094bec6b9d9ca9ade55d6f2b70cc4f76cf86c440f9a25032b1b058371b0a3fde","impliedFormat":99},{"version":"ce6357775e7888f3b1bca4ec32e8a307156f928046020fbe4b287e4746bec67c","affectsGlobalScope":true,"impliedFormat":99},{"version":"8ae128871458811d834db25fdba2a24a2474c3cfab5d1216ff5b5ada7e53ff18","impliedFormat":99},{"version":"f1076d144f14f4c798e95e51042c5e6afb5fd6204bbae0f50c03ce5a033b8732","impliedFormat":99},{"version":"cba05a2b2ebb721119c7bad09a031f72398cd5d8c360fbceb8bd912cadc65ae0","impliedFormat":99},{"version":"cac6f5c23d791fbd0ee50604cfd67576dba60951a80b1e6089ebf84fc2277150","impliedFormat":99},{"version":"1bb2635795eb6e46cb3fe362e0af3826c726fa46307adab03d6b1c9238d3484b","impliedFormat":99},{"version":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881","impliedFormat":99},{"version":"b80e73eabc5b7d90a924ea3f9168e061ff7163cff8c14d8bb522546e4caea6a6","impliedFormat":99},{"version":"2ab8f58931d7b26a7c5dae44566e0a7b7ed57452df618f28be7b6c7b587da1ed","impliedFormat":99},{"version":"4f372c6fb68c1150ff6604d2654e7fdc067856ecf5122efeacef69d80b12d38c","impliedFormat":99},{"version":"3656cc88c522e09b756ce086ec3db0ab554af003a90fe0ede85f3eb11d315d6c","impliedFormat":99},{"version":"d0fcc33f0229c71f2c847c2706bef12df04da887a9c0781a88e9e94319e7a2ec","signature":"4ad27e003ba9f05be6279dfb9b94d8d449e64fa038b4721df80bc51bf0c5b951","impliedFormat":99},{"version":"8beec184db4bcb2878aa845e94dd09bfdaf1f5cbfe07f59841055d3ad29da9a0","signature":"8ab72e0f032ba7b181f5ae2089ec3106fe7024072a54e6666d5b070753588e3c","impliedFormat":99},{"version":"a995c4951d2901d49a39f5dd87828ca2fb987135ef5f6766a2e7ecf50e80cf2a","signature":"16409f7617285659309a84b768d1b12c89b302efb0da636d5e232547fc465248","impliedFormat":99},{"version":"e1d21cb3d3455996c1bcb12ddafb551ba936013dd46d5475d8bc29921915502b","signature":"c9c40aa88ef09cb2290c97840acaea0ba3223f65684edc00736f707518b04223","impliedFormat":99}],"root":[62,[157,160]],"options":{"allowSyntheticDefaultImports":true,"declaration":true,"declarationMap":true,"esModuleInterop":true,"experimentalDecorators":true,"importHelpers":true,"module":199,"noEmitOnError":true,"noFallthroughCasesInSwitch":true,"noImplicitOverride":true,"noImplicitReturns":true,"noUncheckedIndexedAccess":true,"noUnusedLocals":true,"noUnusedParameters":true,"outDir":"./","skipLibCheck":true,"strict":true,"target":9,"useDefineForClassFields":false},"referencedMap":[[64,1],[145,2],[147,3],[146,4],[143,5],[148,6],[150,7],[142,8],[151,9],[153,10],[149,11],[110,12],[109,5],[111,13],[115,14],[116,15],[113,16],[114,17],[118,18],[119,18],[120,19],[141,20],[133,21],[135,21],[136,22],[112,23],[156,24],[154,25],[125,26],[121,27],[122,27],[123,28],[124,5],[155,29],[128,30],[127,31],[131,32],[130,33],[129,34],[75,35],[78,36],[76,36],[80,36],[83,37],[82,36],[81,36],[79,36],[77,38],[67,39],[71,40],[88,41],[87,41],[68,42],[90,43],[89,44],[91,41],[93,41],[94,41],[95,42],[97,45],[98,41],[101,44],[102,41],[103,41],[104,41],[105,41],[106,46],[107,47],[70,48],[85,42],[84,49],[73,50],[86,51],[61,52],[160,53],[62,54],[158,55],[159,55],[157,54]],"version":"6.0.3"}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@3mo/segmented-input",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Controllers for inputs made of several sub-inputs — date units, code cells, templated groups.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/3mo-esolutions/web-components"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"lit",
|
|
11
|
+
"web-component",
|
|
12
|
+
"controller",
|
|
13
|
+
"segment",
|
|
14
|
+
"input",
|
|
15
|
+
"otp",
|
|
16
|
+
"pin",
|
|
17
|
+
"mask"
|
|
18
|
+
],
|
|
19
|
+
"author": "3MO GmbH",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"homepage": "https://www.3mo.de",
|
|
22
|
+
"type": "module",
|
|
23
|
+
"main": "dist/index.js",
|
|
24
|
+
"types": "dist/index.d.ts",
|
|
25
|
+
"customElements": "dist/custom-elements.json",
|
|
26
|
+
"files": [
|
|
27
|
+
"dist"
|
|
28
|
+
],
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@a11d/lit": "x",
|
|
31
|
+
"tslib": "x"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@a11d/lit-testing": "x"
|
|
35
|
+
}
|
|
36
|
+
}
|