@nectary/components 5.6.7 → 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 +71 -16
- package/field/index.js +8 -0
- package/input/index.js +64 -17
- 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
|
};
|
|
@@ -5299,10 +5324,14 @@ class Input extends NectaryElement {
|
|
|
5299
5324
|
"value",
|
|
5300
5325
|
"placeholder",
|
|
5301
5326
|
"mask",
|
|
5327
|
+
"max",
|
|
5328
|
+
"min",
|
|
5302
5329
|
"invalid",
|
|
5303
5330
|
"disabled",
|
|
5304
5331
|
"size",
|
|
5332
|
+
"step",
|
|
5305
5333
|
"autocomplete",
|
|
5334
|
+
"readonly",
|
|
5306
5335
|
"autofocus",
|
|
5307
5336
|
"data-size",
|
|
5308
5337
|
"aria-label",
|
|
@@ -5322,6 +5351,11 @@ class Input extends NectaryElement {
|
|
|
5322
5351
|
case "type": {
|
|
5323
5352
|
updateLiteralAttribute(this.#$input, inputTypes, "type", newVal);
|
|
5324
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
|
+
}
|
|
5325
5359
|
break;
|
|
5326
5360
|
}
|
|
5327
5361
|
case "value": {
|
|
@@ -5399,7 +5433,11 @@ class Input extends NectaryElement {
|
|
|
5399
5433
|
}
|
|
5400
5434
|
case "autocomplete":
|
|
5401
5435
|
case "maxlength":
|
|
5402
|
-
case "required":
|
|
5436
|
+
case "required":
|
|
5437
|
+
case "readonly":
|
|
5438
|
+
case "max":
|
|
5439
|
+
case "min":
|
|
5440
|
+
case "step": {
|
|
5403
5441
|
updateAttribute(this.#$input, name, newVal);
|
|
5404
5442
|
break;
|
|
5405
5443
|
}
|
|
@@ -5801,14 +5839,19 @@ class Input extends NectaryElement {
|
|
|
5801
5839
|
if (this.#maskSymbols === null) {
|
|
5802
5840
|
const value = this.placeholder;
|
|
5803
5841
|
this.#$input.placeholder = value ?? "";
|
|
5804
|
-
this
|
|
5805
|
-
|
|
5842
|
+
if (this.type !== "number") {
|
|
5843
|
+
this.#internals.ariaPlaceholder = value ?? "";
|
|
5844
|
+
updateAttribute(this, "aria-placeholder", value);
|
|
5845
|
+
}
|
|
5806
5846
|
} else {
|
|
5807
|
-
updateAttribute(this, "aria-placeholder", null);
|
|
5808
5847
|
this.#$input.placeholder = "";
|
|
5809
|
-
this.#
|
|
5848
|
+
this.#resetAriaPlaceholder();
|
|
5810
5849
|
}
|
|
5811
5850
|
}
|
|
5851
|
+
#resetAriaPlaceholder() {
|
|
5852
|
+
updateAttribute(this, "aria-placeholder", null);
|
|
5853
|
+
this.#internals.ariaPlaceholder = "";
|
|
5854
|
+
}
|
|
5812
5855
|
#onIconSlotChange = () => {
|
|
5813
5856
|
const isEmpty = this.#$iconSlot.assignedElements().length === 0;
|
|
5814
5857
|
setClass(this.#$iconWrapper, "empty", isEmpty);
|
|
@@ -5856,6 +5899,10 @@ class Input extends NectaryElement {
|
|
|
5856
5899
|
#onWheelReactHandler = (e) => {
|
|
5857
5900
|
getReactEventHandler(this, "on-wheel")?.(e);
|
|
5858
5901
|
};
|
|
5902
|
+
#setRole = (role) => {
|
|
5903
|
+
this.setAttribute("role", role);
|
|
5904
|
+
this.#internals.role = role;
|
|
5905
|
+
};
|
|
5859
5906
|
}
|
|
5860
5907
|
defineCustomElement("sinch-input", Input);
|
|
5861
5908
|
const orientationValues = [
|
|
@@ -6591,6 +6638,7 @@ class Field extends NectaryElement {
|
|
|
6591
6638
|
this.shouldShowTopSection();
|
|
6592
6639
|
this.#$label.addEventListener("click", this.#onLabelClick, options);
|
|
6593
6640
|
this.#$tooltipSlot.addEventListener("slotchange", this.#onTooltipSlotChange, options);
|
|
6641
|
+
this.#$inputSlot.addEventListener("slotchange", this.#onInputSlotChange, options);
|
|
6594
6642
|
}
|
|
6595
6643
|
disconnectedCallback() {
|
|
6596
6644
|
this.#controller.abort();
|
|
@@ -6674,6 +6722,13 @@ class Field extends NectaryElement {
|
|
|
6674
6722
|
#onTooltipSlotChange = () => {
|
|
6675
6723
|
setClass(this.#$tooltipWrapper, "empty", this.#$tooltipSlot.assignedElements().length === 0);
|
|
6676
6724
|
};
|
|
6725
|
+
#onInputSlotChange = () => {
|
|
6726
|
+
const inputElement = getFirstSlotElement(this.#$inputSlot);
|
|
6727
|
+
const labelText = this.#$label.textContent;
|
|
6728
|
+
if (inputElement !== null && labelText != null && labelText.length > 0) {
|
|
6729
|
+
inputElement.setAttribute("aria-label", "label");
|
|
6730
|
+
}
|
|
6731
|
+
};
|
|
6677
6732
|
}
|
|
6678
6733
|
defineCustomElement("sinch-field", Field);
|
|
6679
6734
|
const doFilesSatisfySize$1 = (files, size) => {
|
package/field/index.js
CHANGED
|
@@ -34,6 +34,7 @@ class Field extends NectaryElement {
|
|
|
34
34
|
this.shouldShowTopSection();
|
|
35
35
|
this.#$label.addEventListener("click", this.#onLabelClick, options);
|
|
36
36
|
this.#$tooltipSlot.addEventListener("slotchange", this.#onTooltipSlotChange, options);
|
|
37
|
+
this.#$inputSlot.addEventListener("slotchange", this.#onInputSlotChange, options);
|
|
37
38
|
}
|
|
38
39
|
disconnectedCallback() {
|
|
39
40
|
this.#controller.abort();
|
|
@@ -117,6 +118,13 @@ class Field extends NectaryElement {
|
|
|
117
118
|
#onTooltipSlotChange = () => {
|
|
118
119
|
setClass(this.#$tooltipWrapper, "empty", this.#$tooltipSlot.assignedElements().length === 0);
|
|
119
120
|
};
|
|
121
|
+
#onInputSlotChange = () => {
|
|
122
|
+
const inputElement = getFirstSlotElement(this.#$inputSlot);
|
|
123
|
+
const labelText = this.#$label.textContent;
|
|
124
|
+
if (inputElement !== null && labelText != null && labelText.length > 0) {
|
|
125
|
+
inputElement.setAttribute("aria-label", "label");
|
|
126
|
+
}
|
|
127
|
+
};
|
|
120
128
|
}
|
|
121
129
|
defineCustomElement("sinch-field", Field);
|
|
122
130
|
export {
|
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
|
};
|
|
@@ -133,10 +158,14 @@ class Input extends NectaryElement {
|
|
|
133
158
|
"value",
|
|
134
159
|
"placeholder",
|
|
135
160
|
"mask",
|
|
161
|
+
"max",
|
|
162
|
+
"min",
|
|
136
163
|
"invalid",
|
|
137
164
|
"disabled",
|
|
138
165
|
"size",
|
|
166
|
+
"step",
|
|
139
167
|
"autocomplete",
|
|
168
|
+
"readonly",
|
|
140
169
|
"autofocus",
|
|
141
170
|
"data-size",
|
|
142
171
|
"aria-label",
|
|
@@ -156,6 +185,11 @@ class Input extends NectaryElement {
|
|
|
156
185
|
case "type": {
|
|
157
186
|
updateLiteralAttribute(this.#$input, inputTypes, "type", newVal);
|
|
158
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
|
+
}
|
|
159
193
|
break;
|
|
160
194
|
}
|
|
161
195
|
case "value": {
|
|
@@ -233,7 +267,11 @@ class Input extends NectaryElement {
|
|
|
233
267
|
}
|
|
234
268
|
case "autocomplete":
|
|
235
269
|
case "maxlength":
|
|
236
|
-
case "required":
|
|
270
|
+
case "required":
|
|
271
|
+
case "readonly":
|
|
272
|
+
case "max":
|
|
273
|
+
case "min":
|
|
274
|
+
case "step": {
|
|
237
275
|
updateAttribute(this.#$input, name, newVal);
|
|
238
276
|
break;
|
|
239
277
|
}
|
|
@@ -635,14 +673,19 @@ class Input extends NectaryElement {
|
|
|
635
673
|
if (this.#maskSymbols === null) {
|
|
636
674
|
const value = this.placeholder;
|
|
637
675
|
this.#$input.placeholder = value ?? "";
|
|
638
|
-
this
|
|
639
|
-
|
|
676
|
+
if (this.type !== "number") {
|
|
677
|
+
this.#internals.ariaPlaceholder = value ?? "";
|
|
678
|
+
updateAttribute(this, "aria-placeholder", value);
|
|
679
|
+
}
|
|
640
680
|
} else {
|
|
641
|
-
updateAttribute(this, "aria-placeholder", null);
|
|
642
681
|
this.#$input.placeholder = "";
|
|
643
|
-
this.#
|
|
682
|
+
this.#resetAriaPlaceholder();
|
|
644
683
|
}
|
|
645
684
|
}
|
|
685
|
+
#resetAriaPlaceholder() {
|
|
686
|
+
updateAttribute(this, "aria-placeholder", null);
|
|
687
|
+
this.#internals.ariaPlaceholder = "";
|
|
688
|
+
}
|
|
646
689
|
#onIconSlotChange = () => {
|
|
647
690
|
const isEmpty = this.#$iconSlot.assignedElements().length === 0;
|
|
648
691
|
setClass(this.#$iconWrapper, "empty", isEmpty);
|
|
@@ -690,6 +733,10 @@ class Input extends NectaryElement {
|
|
|
690
733
|
#onWheelReactHandler = (e) => {
|
|
691
734
|
getReactEventHandler(this, "on-wheel")?.(e);
|
|
692
735
|
};
|
|
736
|
+
#setRole = (role) => {
|
|
737
|
+
this.setAttribute("role", role);
|
|
738
|
+
this.#internals.role = role;
|
|
739
|
+
};
|
|
693
740
|
}
|
|
694
741
|
defineCustomElement("sinch-input", Input);
|
|
695
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;
|