@nectary/components 5.7.0 → 5.8.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/bundle.js +56 -15
- package/input/index.js +57 -16
- package/input/types.d.ts +12 -0
- package/package.json +1 -1
package/bundle.js
CHANGED
|
@@ -5214,8 +5214,8 @@ class Input extends NectaryElement {
|
|
|
5214
5214
|
}
|
|
5215
5215
|
connectedCallback() {
|
|
5216
5216
|
super.connectedCallback();
|
|
5217
|
-
this.
|
|
5218
|
-
this.#
|
|
5217
|
+
const role = this.type === "number" ? "spinbutton" : "textbox";
|
|
5218
|
+
this.#setRole(role);
|
|
5219
5219
|
if (this.#controller === null) {
|
|
5220
5220
|
this.#controller = new AbortController();
|
|
5221
5221
|
}
|
|
@@ -5273,7 +5273,7 @@ class Input extends NectaryElement {
|
|
|
5273
5273
|
}
|
|
5274
5274
|
// This handler mimicks the behavior (with some exceptions) of the implicit form submission logic from the HTML spec:
|
|
5275
5275
|
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#implicit-submission
|
|
5276
|
-
#
|
|
5276
|
+
#formSubmitHandler = () => {
|
|
5277
5277
|
const form = this.#internals.form;
|
|
5278
5278
|
if (form === null) {
|
|
5279
5279
|
return;
|
|
@@ -5281,14 +5281,39 @@ class Input extends NectaryElement {
|
|
|
5281
5281
|
if (form.disabled === true) {
|
|
5282
5282
|
return;
|
|
5283
5283
|
}
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5284
|
+
const submitSelectors = [
|
|
5285
|
+
'sinch-button[form-type="submit"]'
|
|
5286
|
+
];
|
|
5287
|
+
const formSubmitters = Array.from(form.querySelectorAll(submitSelectors.join(",")));
|
|
5288
|
+
const formSubmitter = formSubmitters.find((submitter) => !submitter.disabled) ?? null;
|
|
5289
|
+
if (formSubmitter !== null) {
|
|
5290
|
+
requestSubmitForm(form, formSubmitter);
|
|
5291
|
+
}
|
|
5292
|
+
};
|
|
5293
|
+
#onKeyDown = (e) => {
|
|
5294
|
+
switch (e.key) {
|
|
5295
|
+
case "Enter": {
|
|
5296
|
+
this.#formSubmitHandler();
|
|
5297
|
+
break;
|
|
5298
|
+
}
|
|
5299
|
+
case "Home": {
|
|
5300
|
+
if (this.type === "number") {
|
|
5301
|
+
const min = getAttribute(this, "min");
|
|
5302
|
+
if (min !== null && !isNaN(parseFloat(min))) {
|
|
5303
|
+
this.#$input.value = min;
|
|
5304
|
+
setFormValue(this.#internals, min);
|
|
5305
|
+
}
|
|
5306
|
+
}
|
|
5307
|
+
break;
|
|
5308
|
+
}
|
|
5309
|
+
case "End": {
|
|
5310
|
+
if (this.type === "number") {
|
|
5311
|
+
const max = getAttribute(this, "max");
|
|
5312
|
+
if (max !== null && !isNaN(parseFloat(max))) {
|
|
5313
|
+
this.#$input.value = max;
|
|
5314
|
+
setFormValue(this.#internals, max);
|
|
5315
|
+
}
|
|
5316
|
+
}
|
|
5292
5317
|
}
|
|
5293
5318
|
}
|
|
5294
5319
|
};
|
|
@@ -5306,6 +5331,7 @@ class Input extends NectaryElement {
|
|
|
5306
5331
|
"size",
|
|
5307
5332
|
"step",
|
|
5308
5333
|
"autocomplete",
|
|
5334
|
+
"readonly",
|
|
5309
5335
|
"autofocus",
|
|
5310
5336
|
"data-size",
|
|
5311
5337
|
"aria-label",
|
|
@@ -5325,6 +5351,11 @@ class Input extends NectaryElement {
|
|
|
5325
5351
|
case "type": {
|
|
5326
5352
|
updateLiteralAttribute(this.#$input, inputTypes, "type", newVal);
|
|
5327
5353
|
updateAttribute(this.#$input, "spellcheck", newVal === "password" ? "false" : null);
|
|
5354
|
+
const role = newVal === "number" ? "spinbutton" : "textbox";
|
|
5355
|
+
this.#setRole(role);
|
|
5356
|
+
if (newVal === "number") {
|
|
5357
|
+
this.#resetAriaPlaceholder();
|
|
5358
|
+
}
|
|
5328
5359
|
break;
|
|
5329
5360
|
}
|
|
5330
5361
|
case "value": {
|
|
@@ -5403,6 +5434,7 @@ class Input extends NectaryElement {
|
|
|
5403
5434
|
case "autocomplete":
|
|
5404
5435
|
case "maxlength":
|
|
5405
5436
|
case "required":
|
|
5437
|
+
case "readonly":
|
|
5406
5438
|
case "max":
|
|
5407
5439
|
case "min":
|
|
5408
5440
|
case "step": {
|
|
@@ -5807,14 +5839,19 @@ class Input extends NectaryElement {
|
|
|
5807
5839
|
if (this.#maskSymbols === null) {
|
|
5808
5840
|
const value = this.placeholder;
|
|
5809
5841
|
this.#$input.placeholder = value ?? "";
|
|
5810
|
-
this
|
|
5811
|
-
|
|
5842
|
+
if (this.type !== "number") {
|
|
5843
|
+
this.#internals.ariaPlaceholder = value ?? "";
|
|
5844
|
+
updateAttribute(this, "aria-placeholder", value);
|
|
5845
|
+
}
|
|
5812
5846
|
} else {
|
|
5813
|
-
updateAttribute(this, "aria-placeholder", null);
|
|
5814
5847
|
this.#$input.placeholder = "";
|
|
5815
|
-
this.#
|
|
5848
|
+
this.#resetAriaPlaceholder();
|
|
5816
5849
|
}
|
|
5817
5850
|
}
|
|
5851
|
+
#resetAriaPlaceholder() {
|
|
5852
|
+
updateAttribute(this, "aria-placeholder", null);
|
|
5853
|
+
this.#internals.ariaPlaceholder = "";
|
|
5854
|
+
}
|
|
5818
5855
|
#onIconSlotChange = () => {
|
|
5819
5856
|
const isEmpty = this.#$iconSlot.assignedElements().length === 0;
|
|
5820
5857
|
setClass(this.#$iconWrapper, "empty", isEmpty);
|
|
@@ -5862,6 +5899,10 @@ class Input extends NectaryElement {
|
|
|
5862
5899
|
#onWheelReactHandler = (e) => {
|
|
5863
5900
|
getReactEventHandler(this, "on-wheel")?.(e);
|
|
5864
5901
|
};
|
|
5902
|
+
#setRole = (role) => {
|
|
5903
|
+
this.setAttribute("role", role);
|
|
5904
|
+
this.#internals.role = role;
|
|
5905
|
+
};
|
|
5865
5906
|
}
|
|
5866
5907
|
defineCustomElement("sinch-input", Input);
|
|
5867
5908
|
const orientationValues = [
|
package/input/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Context, subscribeContext } from "../utils/context.js";
|
|
2
|
-
import { getBooleanAttribute, updateAttribute, isAttrEqual, isAttrTrue, updateBooleanAttribute, updateLiteralAttribute,
|
|
2
|
+
import { getBooleanAttribute, getAttribute, updateAttribute, isAttrEqual, isAttrTrue, updateBooleanAttribute, updateLiteralAttribute, getLiteralAttribute, setClass } from "../utils/dom.js";
|
|
3
3
|
import { defineCustomElement, NectaryElement } from "../utils/element.js";
|
|
4
4
|
import { isElementFocused } from "../utils/slot.js";
|
|
5
5
|
import { getReactEventHandler } from "../utils/get-react-event-handler.js";
|
|
@@ -48,8 +48,8 @@ class Input extends NectaryElement {
|
|
|
48
48
|
}
|
|
49
49
|
connectedCallback() {
|
|
50
50
|
super.connectedCallback();
|
|
51
|
-
this.
|
|
52
|
-
this.#
|
|
51
|
+
const role = this.type === "number" ? "spinbutton" : "textbox";
|
|
52
|
+
this.#setRole(role);
|
|
53
53
|
if (this.#controller === null) {
|
|
54
54
|
this.#controller = new AbortController();
|
|
55
55
|
}
|
|
@@ -107,7 +107,7 @@ class Input extends NectaryElement {
|
|
|
107
107
|
}
|
|
108
108
|
// This handler mimicks the behavior (with some exceptions) of the implicit form submission logic from the HTML spec:
|
|
109
109
|
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#implicit-submission
|
|
110
|
-
#
|
|
110
|
+
#formSubmitHandler = () => {
|
|
111
111
|
const form = this.#internals.form;
|
|
112
112
|
if (form === null) {
|
|
113
113
|
return;
|
|
@@ -115,14 +115,39 @@ class Input extends NectaryElement {
|
|
|
115
115
|
if (form.disabled === true) {
|
|
116
116
|
return;
|
|
117
117
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
118
|
+
const submitSelectors = [
|
|
119
|
+
'sinch-button[form-type="submit"]'
|
|
120
|
+
];
|
|
121
|
+
const formSubmitters = Array.from(form.querySelectorAll(submitSelectors.join(",")));
|
|
122
|
+
const formSubmitter = formSubmitters.find((submitter) => !submitter.disabled) ?? null;
|
|
123
|
+
if (formSubmitter !== null) {
|
|
124
|
+
requestSubmitForm(form, formSubmitter);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
#onKeyDown = (e) => {
|
|
128
|
+
switch (e.key) {
|
|
129
|
+
case "Enter": {
|
|
130
|
+
this.#formSubmitHandler();
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
case "Home": {
|
|
134
|
+
if (this.type === "number") {
|
|
135
|
+
const min = getAttribute(this, "min");
|
|
136
|
+
if (min !== null && !isNaN(parseFloat(min))) {
|
|
137
|
+
this.#$input.value = min;
|
|
138
|
+
setFormValue(this.#internals, min);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
case "End": {
|
|
144
|
+
if (this.type === "number") {
|
|
145
|
+
const max = getAttribute(this, "max");
|
|
146
|
+
if (max !== null && !isNaN(parseFloat(max))) {
|
|
147
|
+
this.#$input.value = max;
|
|
148
|
+
setFormValue(this.#internals, max);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
126
151
|
}
|
|
127
152
|
}
|
|
128
153
|
};
|
|
@@ -140,6 +165,7 @@ class Input extends NectaryElement {
|
|
|
140
165
|
"size",
|
|
141
166
|
"step",
|
|
142
167
|
"autocomplete",
|
|
168
|
+
"readonly",
|
|
143
169
|
"autofocus",
|
|
144
170
|
"data-size",
|
|
145
171
|
"aria-label",
|
|
@@ -159,6 +185,11 @@ class Input extends NectaryElement {
|
|
|
159
185
|
case "type": {
|
|
160
186
|
updateLiteralAttribute(this.#$input, inputTypes, "type", newVal);
|
|
161
187
|
updateAttribute(this.#$input, "spellcheck", newVal === "password" ? "false" : null);
|
|
188
|
+
const role = newVal === "number" ? "spinbutton" : "textbox";
|
|
189
|
+
this.#setRole(role);
|
|
190
|
+
if (newVal === "number") {
|
|
191
|
+
this.#resetAriaPlaceholder();
|
|
192
|
+
}
|
|
162
193
|
break;
|
|
163
194
|
}
|
|
164
195
|
case "value": {
|
|
@@ -237,6 +268,7 @@ class Input extends NectaryElement {
|
|
|
237
268
|
case "autocomplete":
|
|
238
269
|
case "maxlength":
|
|
239
270
|
case "required":
|
|
271
|
+
case "readonly":
|
|
240
272
|
case "max":
|
|
241
273
|
case "min":
|
|
242
274
|
case "step": {
|
|
@@ -641,14 +673,19 @@ class Input extends NectaryElement {
|
|
|
641
673
|
if (this.#maskSymbols === null) {
|
|
642
674
|
const value = this.placeholder;
|
|
643
675
|
this.#$input.placeholder = value ?? "";
|
|
644
|
-
this
|
|
645
|
-
|
|
676
|
+
if (this.type !== "number") {
|
|
677
|
+
this.#internals.ariaPlaceholder = value ?? "";
|
|
678
|
+
updateAttribute(this, "aria-placeholder", value);
|
|
679
|
+
}
|
|
646
680
|
} else {
|
|
647
|
-
updateAttribute(this, "aria-placeholder", null);
|
|
648
681
|
this.#$input.placeholder = "";
|
|
649
|
-
this.#
|
|
682
|
+
this.#resetAriaPlaceholder();
|
|
650
683
|
}
|
|
651
684
|
}
|
|
685
|
+
#resetAriaPlaceholder() {
|
|
686
|
+
updateAttribute(this, "aria-placeholder", null);
|
|
687
|
+
this.#internals.ariaPlaceholder = "";
|
|
688
|
+
}
|
|
652
689
|
#onIconSlotChange = () => {
|
|
653
690
|
const isEmpty = this.#$iconSlot.assignedElements().length === 0;
|
|
654
691
|
setClass(this.#$iconWrapper, "empty", isEmpty);
|
|
@@ -696,6 +733,10 @@ class Input extends NectaryElement {
|
|
|
696
733
|
#onWheelReactHandler = (e) => {
|
|
697
734
|
getReactEventHandler(this, "on-wheel")?.(e);
|
|
698
735
|
};
|
|
736
|
+
#setRole = (role) => {
|
|
737
|
+
this.setAttribute("role", role);
|
|
738
|
+
this.#internals.role = role;
|
|
739
|
+
};
|
|
699
740
|
}
|
|
700
741
|
defineCustomElement("sinch-input", Input);
|
|
701
742
|
export {
|
package/input/types.d.ts
CHANGED
|
@@ -28,6 +28,18 @@ export type TSinchInputProps = {
|
|
|
28
28
|
autofocus?: boolean;
|
|
29
29
|
/** Size, `m` by default */
|
|
30
30
|
size?: TSinchSize;
|
|
31
|
+
/** Whether or not the input is in readonly mode **/
|
|
32
|
+
readonly?: boolean;
|
|
33
|
+
/** Whether or not the input is required **/
|
|
34
|
+
required?: boolean;
|
|
35
|
+
/** Maximum length of the input value */
|
|
36
|
+
maxLength?: number | null;
|
|
37
|
+
/** Maximum numeric value for type 'number' */
|
|
38
|
+
max?: number | null;
|
|
39
|
+
/** Minimum numeric value for type 'number' */
|
|
40
|
+
min?: number | null;
|
|
41
|
+
/** Step value for type 'number' */
|
|
42
|
+
step?: number | null;
|
|
31
43
|
selectionStart?: number | null;
|
|
32
44
|
selectionEnd?: number | null;
|
|
33
45
|
selectionDirection?: 'forward' | 'backward' | 'none' | null;
|