tyrell-components 1.0.0-TC57 → 1.0.0-TC58
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/tyrell.js +1 -1
- package/dist/tyrell.js.map +1 -0
- package/lib/base/ty-component.d.ts +12 -3
- package/lib/base/ty-component.js +21 -17
- package/lib/components/button.d.ts +4 -0
- package/lib/components/button.js +33 -6
- package/lib/components/calendar-month.js +3 -10
- package/lib/components/calendar.d.ts +3 -1
- package/lib/components/calendar.js +19 -34
- package/lib/components/checkbox.d.ts +1 -1
- package/lib/components/checkbox.js +2 -1
- package/lib/components/date-picker.d.ts +60 -8
- package/lib/components/date-picker.js +268 -134
- package/lib/components/file-upload.d.ts +2 -1
- package/lib/components/file-upload.js +2 -1
- package/lib/components/input.d.ts +13 -6
- package/lib/components/input.js +58 -60
- package/lib/components/modal.js +37 -1
- package/lib/components/option.js +2 -5
- package/lib/components/popup.js +43 -6
- package/lib/components/radio.d.ts +2 -1
- package/lib/components/radio.js +2 -1
- package/lib/components/resize-observer.js +2 -0
- package/lib/components/scroll-container.js +2 -0
- package/lib/components/select.d.ts +32 -3
- package/lib/components/select.js +123 -11
- package/lib/components/switch.d.ts +3 -1
- package/lib/components/switch.js +2 -1
- package/lib/components/textarea.d.ts +44 -4
- package/lib/components/textarea.js +54 -10
- package/lib/styles/button.js +20 -19
- package/lib/styles/date-picker.js +17 -0
- package/lib/styles/select-base.js +26 -0
- package/lib/styles/textarea.d.ts +1 -1
- package/lib/styles/textarea.js +7 -0
- package/lib/utils/error-flavor.d.ts +8 -0
- package/lib/utils/error-flavor.js +1 -0
- package/lib/utils/upgrade-properties.d.ts +21 -0
- package/lib/utils/upgrade-properties.js +47 -0
- package/lib/utils/validity.d.ts +63 -5
- package/lib/utils/validity.js +145 -24
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +2 -1
- package/lib/base/ty-component.d.ts.map +0 -1
- package/lib/base/ty-component.js.map +0 -1
- package/lib/components/button.d.ts.map +0 -1
- package/lib/components/button.js.map +0 -1
- package/lib/components/calendar-month.d.ts.map +0 -1
- package/lib/components/calendar-month.js.map +0 -1
- package/lib/components/calendar-navigation.d.ts.map +0 -1
- package/lib/components/calendar-navigation.js.map +0 -1
- package/lib/components/calendar.d.ts.map +0 -1
- package/lib/components/calendar.js.map +0 -1
- package/lib/components/checkbox.d.ts.map +0 -1
- package/lib/components/checkbox.js.map +0 -1
- package/lib/components/copy.d.ts.map +0 -1
- package/lib/components/copy.js.map +0 -1
- package/lib/components/date-picker.d.ts.map +0 -1
- package/lib/components/date-picker.js.map +0 -1
- package/lib/components/dropdown.d.ts +0 -403
- package/lib/components/dropdown.d.ts.map +0 -1
- package/lib/components/dropdown.js +0 -1315
- package/lib/components/dropdown.js.map +0 -1
- package/lib/components/icon.d.ts.map +0 -1
- package/lib/components/icon.js.map +0 -1
- package/lib/components/input.d.ts.map +0 -1
- package/lib/components/input.js.map +0 -1
- package/lib/components/modal.d.ts.map +0 -1
- package/lib/components/modal.js.map +0 -1
- package/lib/components/multiselect.d.ts +0 -389
- package/lib/components/multiselect.d.ts.map +0 -1
- package/lib/components/multiselect.js +0 -1301
- package/lib/components/multiselect.js.map +0 -1
- package/lib/components/option.d.ts.map +0 -1
- package/lib/components/option.js.map +0 -1
- package/lib/components/popup.d.ts.map +0 -1
- package/lib/components/popup.js.map +0 -1
- package/lib/components/resize-observer.d.ts.map +0 -1
- package/lib/components/resize-observer.js.map +0 -1
- package/lib/components/scroll-container.d.ts.map +0 -1
- package/lib/components/scroll-container.js.map +0 -1
- package/lib/components/step.d.ts.map +0 -1
- package/lib/components/step.js.map +0 -1
- package/lib/components/tab.d.ts.map +0 -1
- package/lib/components/tab.js.map +0 -1
- package/lib/components/tabs.d.ts.map +0 -1
- package/lib/components/tabs.js.map +0 -1
- package/lib/components/tag.d.ts.map +0 -1
- package/lib/components/tag.js.map +0 -1
- package/lib/components/textarea.d.ts.map +0 -1
- package/lib/components/textarea.js.map +0 -1
- package/lib/components/tooltip.d.ts.map +0 -1
- package/lib/components/tooltip.js.map +0 -1
- package/lib/components/wizard.d.ts.map +0 -1
- package/lib/components/wizard.js.map +0 -1
- package/lib/icons/fontawesome/brands.d.ts.map +0 -1
- package/lib/icons/fontawesome/brands.js.map +0 -1
- package/lib/icons/fontawesome/regular.d.ts.map +0 -1
- package/lib/icons/fontawesome/regular.js.map +0 -1
- package/lib/icons/fontawesome/solid.d.ts.map +0 -1
- package/lib/icons/fontawesome/solid.js.map +0 -1
- package/lib/icons/heroicons/micro.d.ts.map +0 -1
- package/lib/icons/heroicons/micro.js.map +0 -1
- package/lib/icons/heroicons/mini.d.ts.map +0 -1
- package/lib/icons/heroicons/mini.js.map +0 -1
- package/lib/icons/heroicons/outline.d.ts.map +0 -1
- package/lib/icons/heroicons/outline.js.map +0 -1
- package/lib/icons/heroicons/solid.d.ts.map +0 -1
- package/lib/icons/heroicons/solid.js.map +0 -1
- package/lib/icons/lucide.d.ts.map +0 -1
- package/lib/icons/lucide.js.map +0 -1
- package/lib/icons/material/filled.d.ts.map +0 -1
- package/lib/icons/material/filled.js.map +0 -1
- package/lib/icons/material/outlined.d.ts.map +0 -1
- package/lib/icons/material/outlined.js.map +0 -1
- package/lib/icons/material/round.d.ts.map +0 -1
- package/lib/icons/material/round.js.map +0 -1
- package/lib/icons/material/sharp.d.ts.map +0 -1
- package/lib/icons/material/sharp.js.map +0 -1
- package/lib/icons/material/two-tone.d.ts.map +0 -1
- package/lib/icons/material/two-tone.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/styles/button.d.ts.map +0 -1
- package/lib/styles/button.js.map +0 -1
- package/lib/styles/calendar-month.d.ts.map +0 -1
- package/lib/styles/calendar-month.js.map +0 -1
- package/lib/styles/calendar-navigation.d.ts.map +0 -1
- package/lib/styles/calendar-navigation.js.map +0 -1
- package/lib/styles/calendar.d.ts.map +0 -1
- package/lib/styles/calendar.js.map +0 -1
- package/lib/styles/copy.d.ts.map +0 -1
- package/lib/styles/copy.js.map +0 -1
- package/lib/styles/date-picker.d.ts.map +0 -1
- package/lib/styles/date-picker.js.map +0 -1
- package/lib/styles/dropdown.d.ts +0 -12
- package/lib/styles/dropdown.d.ts.map +0 -1
- package/lib/styles/dropdown.js +0 -725
- package/lib/styles/dropdown.js.map +0 -1
- package/lib/styles/icon.d.ts.map +0 -1
- package/lib/styles/icon.js.map +0 -1
- package/lib/styles/input.d.ts.map +0 -1
- package/lib/styles/input.js.map +0 -1
- package/lib/styles/modal.d.ts.map +0 -1
- package/lib/styles/modal.js.map +0 -1
- package/lib/styles/multiselect.d.ts +0 -6
- package/lib/styles/multiselect.d.ts.map +0 -1
- package/lib/styles/multiselect.js +0 -568
- package/lib/styles/multiselect.js.map +0 -1
- package/lib/styles/option.d.ts.map +0 -1
- package/lib/styles/option.js.map +0 -1
- package/lib/styles/popup.d.ts.map +0 -1
- package/lib/styles/popup.js.map +0 -1
- package/lib/styles/resize-observer.d.ts.map +0 -1
- package/lib/styles/resize-observer.js.map +0 -1
- package/lib/styles/scroll-container.d.ts.map +0 -1
- package/lib/styles/scroll-container.js.map +0 -1
- package/lib/styles/step.d.ts.map +0 -1
- package/lib/styles/step.js.map +0 -1
- package/lib/styles/tab.d.ts.map +0 -1
- package/lib/styles/tab.js.map +0 -1
- package/lib/styles/tabs.d.ts.map +0 -1
- package/lib/styles/tabs.js.map +0 -1
- package/lib/styles/tag.d.ts.map +0 -1
- package/lib/styles/tag.js.map +0 -1
- package/lib/styles/textarea.d.ts.map +0 -1
- package/lib/styles/textarea.js.map +0 -1
- package/lib/styles/tooltip.d.ts.map +0 -1
- package/lib/styles/tooltip.js.map +0 -1
- package/lib/styles/wizard.d.ts.map +0 -1
- package/lib/styles/wizard.js.map +0 -1
- package/lib/types/common.d.ts.map +0 -1
- package/lib/types/common.js.map +0 -1
- package/lib/utils/calendar-utils.d.ts.map +0 -1
- package/lib/utils/calendar-utils.js.map +0 -1
- package/lib/utils/icon-registry.d.ts.map +0 -1
- package/lib/utils/icon-registry.js.map +0 -1
- package/lib/utils/locale.d.ts.map +0 -1
- package/lib/utils/locale.js.map +0 -1
- package/lib/utils/number-format.d.ts.map +0 -1
- package/lib/utils/number-format.js.map +0 -1
- package/lib/utils/parse-boolean.d.ts +0 -39
- package/lib/utils/parse-boolean.d.ts.map +0 -1
- package/lib/utils/parse-boolean.js +0 -23
- package/lib/utils/parse-boolean.js.map +0 -1
- package/lib/utils/positioning.d.ts.map +0 -1
- package/lib/utils/positioning.js.map +0 -1
- package/lib/utils/property-capture.d.ts.map +0 -1
- package/lib/utils/property-capture.js.map +0 -1
- package/lib/utils/property-manager.d.ts.map +0 -1
- package/lib/utils/property-manager.js.map +0 -1
- package/lib/utils/resize-observer.d.ts.map +0 -1
- package/lib/utils/resize-observer.js.map +0 -1
- package/lib/utils/scroll-lock.d.ts.map +0 -1
- package/lib/utils/scroll-lock.js.map +0 -1
- package/lib/utils/styles.d.ts.map +0 -1
- package/lib/utils/styles.js.map +0 -1
- package/lib/version.d.ts.map +0 -1
- package/lib/version.js.map +0 -1
package/lib/components/select.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DEFAULT_SIZE } from "../types/common.js";
|
|
2
2
|
import { ensureStyles } from "../utils/styles.js";
|
|
3
3
|
import { syncCustomFlavorSheet } from "../utils/flavor-sheet.js";
|
|
4
|
+
import { ERROR_FLAVOR } from "../utils/error-flavor.js";
|
|
4
5
|
import { selectBaseStyles, selectCustomFlavorCss } from "../styles/select-base.js";
|
|
5
6
|
import { selectStyles } from "../styles/select.js";
|
|
6
7
|
import { getLoaderSvg } from "../utils/loader-registry.js";
|
|
@@ -20,6 +21,7 @@ elementIds.set(element, id);
|
|
|
20
21
|
return id;
|
|
21
22
|
}
|
|
22
23
|
import { REQUIRED_ICON_SVG } from "../utils/icons.js";
|
|
24
|
+
import { nativeMessage } from "../utils/validity.js";
|
|
23
25
|
const SEARCH_AUTO_THRESHOLD = 7;
|
|
24
26
|
const CHEVRON_DOWN_SVG = `<svg viewBox="0 0 20 20" fill="currentColor">
|
|
25
27
|
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
|
|
@@ -81,6 +83,7 @@ this._optionsScrollbar = null;
|
|
|
81
83
|
this._childObserver = null;
|
|
82
84
|
this._selectedClone = null;
|
|
83
85
|
this._customFlavorSheet = null;
|
|
86
|
+
this._ariaTrigger = null;
|
|
84
87
|
const shadow = this.shadowRoot;
|
|
85
88
|
ensureStyles(shadow, { css: selectBaseStyles, id: "ty-select-base" });
|
|
86
89
|
ensureStyles(shadow, { css: selectStyles, id: "ty-select" });
|
|
@@ -109,11 +112,43 @@ this.updateMobileSelectedState();
|
|
|
109
112
|
this._childObserver.observe(this, { childList: true });
|
|
110
113
|
this.ensureOptionRoles();
|
|
111
114
|
this._syncCustomFlavor();
|
|
115
|
+
this.syncErrorFlavor();
|
|
116
|
+
if (!this._keyboardHandler) {
|
|
117
|
+
this._keyboardHandler = this.handleKeyboard.bind(this);
|
|
118
|
+
document.addEventListener("keydown", this._keyboardHandler, true);
|
|
119
|
+
}
|
|
112
120
|
}
|
|
113
121
|
_syncCustomFlavor() {
|
|
114
122
|
this._customFlavorSheet = syncCustomFlavorSheet(this.shadowRoot, this._customFlavorSheet, this.getProperty("flavor"), ({ base }) => selectCustomFlavorCss(base));
|
|
115
123
|
}
|
|
124
|
+
syncErrorFlavor() {
|
|
125
|
+
if (!this._connected)
|
|
126
|
+
return;
|
|
127
|
+
const flavor = this.getProperty("flavor");
|
|
128
|
+
const replaced = this.getAttribute(ERROR_FLAVOR);
|
|
129
|
+
if (this.getProperty("error")) {
|
|
130
|
+
if (replaced === null && flavor === "neutral") {
|
|
131
|
+
this.setAttribute(ERROR_FLAVOR, this.getAttribute("flavor") ?? "");
|
|
132
|
+
this.setProperty("flavor", "danger");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else if (replaced !== null) {
|
|
136
|
+
this.removeAttribute(ERROR_FLAVOR);
|
|
137
|
+
if (flavor !== "danger")
|
|
138
|
+
return;
|
|
139
|
+
if (!replaced)
|
|
140
|
+
this.removeAttribute("flavor");
|
|
141
|
+
else
|
|
142
|
+
this.setProperty("flavor", replaced);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
116
145
|
onDisconnect() {
|
|
146
|
+
if (this._state.open) {
|
|
147
|
+
if (this._state.mode === "mobile")
|
|
148
|
+
this.closeMobileModal();
|
|
149
|
+
else
|
|
150
|
+
this.closeDropdown();
|
|
151
|
+
}
|
|
117
152
|
const shadow = this.shadowRoot;
|
|
118
153
|
const dialogs = shadow.querySelectorAll("dialog");
|
|
119
154
|
dialogs.forEach((dialog) => {
|
|
@@ -122,7 +157,7 @@ dialog.close();
|
|
|
122
157
|
}
|
|
123
158
|
});
|
|
124
159
|
if (this._keyboardHandler) {
|
|
125
|
-
document.removeEventListener("keydown", this._keyboardHandler);
|
|
160
|
+
document.removeEventListener("keydown", this._keyboardHandler, true);
|
|
126
161
|
this._keyboardHandler = null;
|
|
127
162
|
}
|
|
128
163
|
if (this._searchDebounceTimer !== null) {
|
|
@@ -151,8 +186,15 @@ case "name":
|
|
|
151
186
|
this._name = newValue || "";
|
|
152
187
|
break;
|
|
153
188
|
case "flavor":
|
|
189
|
+
if (newValue !== "danger") {
|
|
190
|
+
this.removeAttribute(ERROR_FLAVOR);
|
|
191
|
+
this.syncErrorFlavor();
|
|
192
|
+
}
|
|
154
193
|
this._syncCustomFlavor();
|
|
155
194
|
break;
|
|
195
|
+
case "error":
|
|
196
|
+
this.syncErrorFlavor();
|
|
197
|
+
break;
|
|
156
198
|
case "multiple":
|
|
157
199
|
this._multiple = newValue;
|
|
158
200
|
if (!newValue && this._state.selectedValues.length > 1) {
|
|
@@ -256,6 +298,8 @@ return "";
|
|
|
256
298
|
return null;
|
|
257
299
|
}
|
|
258
300
|
focus(options) {
|
|
301
|
+
if (this._disabled)
|
|
302
|
+
return;
|
|
259
303
|
const trigger = this.querySelector(':scope > [slot="trigger"]');
|
|
260
304
|
const stub = this.shadowRoot?.querySelector(".select-stub");
|
|
261
305
|
const target = trigger ?? stub;
|
|
@@ -345,7 +389,7 @@ if (!tag.hasAttribute("aria-selected"))
|
|
|
345
389
|
tag.setAttribute("aria-selected", "false");
|
|
346
390
|
});
|
|
347
391
|
}
|
|
348
|
-
updateComponentValue(newValues, dispatchChange = false, action = "set", item = null) {
|
|
392
|
+
updateComponentValue(newValues, dispatchChange = false, action = "set", item = null, reveal = dispatchChange) {
|
|
349
393
|
const oldValues = this.getSelectedValues();
|
|
350
394
|
const valueStr = newValues.join(",");
|
|
351
395
|
if (JSON.stringify(newValues.sort()) !== JSON.stringify(oldValues.sort())) {
|
|
@@ -359,6 +403,8 @@ items: this.getSelectedItems(newValues),
|
|
|
359
403
|
action,
|
|
360
404
|
item,
|
|
361
405
|
});
|
|
406
|
+
if (reveal)
|
|
407
|
+
this.revealValidity();
|
|
362
408
|
}
|
|
363
409
|
}
|
|
364
410
|
}
|
|
@@ -602,6 +648,7 @@ if (this._disabled || this._readonly) {
|
|
|
602
648
|
return;
|
|
603
649
|
}
|
|
604
650
|
this.clear();
|
|
651
|
+
this.revealValidity();
|
|
605
652
|
}
|
|
606
653
|
handleStubKeydown(e) {
|
|
607
654
|
if (this._disabled || this._readonly || this._state.open)
|
|
@@ -754,6 +801,7 @@ this.closeMobileModal();
|
|
|
754
801
|
else {
|
|
755
802
|
this.closeDropdown();
|
|
756
803
|
}
|
|
804
|
+
this.focus();
|
|
757
805
|
break;
|
|
758
806
|
case "Enter":
|
|
759
807
|
e.preventDefault();
|
|
@@ -915,10 +963,26 @@ label.innerHTML = `${this._label}${this._required ? `<span class="required-icon"
|
|
|
915
963
|
else {
|
|
916
964
|
label?.remove();
|
|
917
965
|
}
|
|
966
|
+
const error = this.getProperty("error") || "";
|
|
967
|
+
const errorId = `select-error-${getElementHash(this)}`;
|
|
968
|
+
let errorLine = container.querySelector(":scope > .error-message");
|
|
969
|
+
if (error) {
|
|
970
|
+
if (!errorLine) {
|
|
971
|
+
errorLine = document.createElement("div");
|
|
972
|
+
errorLine.className = "error-message";
|
|
973
|
+
errorLine.id = errorId;
|
|
974
|
+
container.append(errorLine);
|
|
975
|
+
}
|
|
976
|
+
errorLine.textContent = error;
|
|
977
|
+
}
|
|
978
|
+
else {
|
|
979
|
+
errorLine?.remove();
|
|
980
|
+
}
|
|
918
981
|
const stub = shadow.querySelector(".select-stub");
|
|
919
982
|
if (stub) {
|
|
920
983
|
stub.classList.toggle("disabled", this._disabled);
|
|
921
984
|
stub.classList.toggle("compact", this._compact);
|
|
985
|
+
stub.classList.toggle("error", !!error);
|
|
922
986
|
stub.tabIndex = this._disabled ? -1 : 0;
|
|
923
987
|
stub.toggleAttribute("disabled", this._disabled);
|
|
924
988
|
if (this._disabled)
|
|
@@ -929,7 +993,27 @@ if (this._label)
|
|
|
929
993
|
stub.setAttribute("aria-labelledby", labelId);
|
|
930
994
|
else
|
|
931
995
|
stub.removeAttribute("aria-labelledby");
|
|
996
|
+
if (error) {
|
|
997
|
+
stub.setAttribute("aria-invalid", "true");
|
|
998
|
+
stub.setAttribute("aria-describedby", errorId);
|
|
932
999
|
}
|
|
1000
|
+
else {
|
|
1001
|
+
stub.removeAttribute("aria-invalid");
|
|
1002
|
+
stub.removeAttribute("aria-describedby");
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
const trigger = error
|
|
1006
|
+
? this.querySelector(':scope > [slot="trigger"]')
|
|
1007
|
+
: null;
|
|
1008
|
+
if (this._ariaTrigger && this._ariaTrigger !== trigger) {
|
|
1009
|
+
this._ariaTrigger.removeAttribute("aria-invalid");
|
|
1010
|
+
this._ariaTrigger.removeAttribute("aria-description");
|
|
1011
|
+
}
|
|
1012
|
+
if (trigger) {
|
|
1013
|
+
trigger.setAttribute("aria-invalid", "true");
|
|
1014
|
+
trigger.setAttribute("aria-description", error);
|
|
1015
|
+
}
|
|
1016
|
+
this._ariaTrigger = trigger;
|
|
933
1017
|
shadow
|
|
934
1018
|
.querySelectorAll(".dropdown-search-input, .mobile-search-input")
|
|
935
1019
|
.forEach((input) => (input.disabled = this._disabled));
|
|
@@ -941,7 +1025,7 @@ return;
|
|
|
941
1025
|
}
|
|
942
1026
|
if (this.required && this.getSelectedValues().length === 0) {
|
|
943
1027
|
const stub = this.shadowRoot?.querySelector(".select-stub");
|
|
944
|
-
this.applyValidity({ valueMissing: true }, "
|
|
1028
|
+
this.applyValidity({ valueMissing: true }, nativeMessage("select", { required: true, multiple: this._multiple }), stub ?? undefined);
|
|
945
1029
|
}
|
|
946
1030
|
else {
|
|
947
1031
|
this.applyValidity({});
|
|
@@ -958,7 +1042,10 @@ const hasTrigger = slot.assignedElements().length > 0;
|
|
|
958
1042
|
stub.classList.toggle("custom-trigger", hasTrigger);
|
|
959
1043
|
this.toggleAttribute("has-trigger", hasTrigger);
|
|
960
1044
|
};
|
|
961
|
-
slot.addEventListener("slotchange",
|
|
1045
|
+
slot.addEventListener("slotchange", () => {
|
|
1046
|
+
sync();
|
|
1047
|
+
this.syncFieldChrome();
|
|
1048
|
+
});
|
|
962
1049
|
sync();
|
|
963
1050
|
}
|
|
964
1051
|
setupEventListeners() {
|
|
@@ -991,9 +1078,13 @@ if (e.target === dialog) {
|
|
|
991
1078
|
this.closeDropdown();
|
|
992
1079
|
}
|
|
993
1080
|
});
|
|
1081
|
+
dialog.addEventListener("cancel", (e) => {
|
|
1082
|
+
e.preventDefault();
|
|
1083
|
+
this.closeDropdown();
|
|
1084
|
+
this.focus();
|
|
1085
|
+
});
|
|
1086
|
+
this.syncOnOutsideClose(dialog, () => this.closeDropdown());
|
|
994
1087
|
}
|
|
995
|
-
this._keyboardHandler = this.handleKeyboard.bind(this);
|
|
996
|
-
document.addEventListener("keydown", this._keyboardHandler);
|
|
997
1088
|
}
|
|
998
1089
|
buildStubClasses() {
|
|
999
1090
|
const classes = [];
|
|
@@ -1187,10 +1278,6 @@ this.setupMobileEventListeners();
|
|
|
1187
1278
|
this.updateSelectionDisplay();
|
|
1188
1279
|
}
|
|
1189
1280
|
setupMobileEventListeners() {
|
|
1190
|
-
if (!this._keyboardHandler) {
|
|
1191
|
-
this._keyboardHandler = this.handleKeyboard.bind(this);
|
|
1192
|
-
document.addEventListener("keydown", this._keyboardHandler);
|
|
1193
|
-
}
|
|
1194
1281
|
const shadow = this.shadowRoot;
|
|
1195
1282
|
const stub = shadow.querySelector(".select-stub");
|
|
1196
1283
|
const optionsSlot = shadow.querySelector("#options-slot");
|
|
@@ -1225,9 +1312,17 @@ this.closeMobileModal();
|
|
|
1225
1312
|
dialog.addEventListener("cancel", (e) => {
|
|
1226
1313
|
e.preventDefault();
|
|
1227
1314
|
this.closeMobileModal();
|
|
1315
|
+
this.focus();
|
|
1228
1316
|
});
|
|
1317
|
+
this.syncOnOutsideClose(dialog, () => this.closeMobileModal());
|
|
1229
1318
|
}
|
|
1230
1319
|
}
|
|
1320
|
+
syncOnOutsideClose(dialog, close) {
|
|
1321
|
+
new MutationObserver(() => {
|
|
1322
|
+
if (this._state.open && !dialog.open)
|
|
1323
|
+
close();
|
|
1324
|
+
}).observe(dialog, { attributes: true, attributeFilter: ["open"] });
|
|
1325
|
+
}
|
|
1231
1326
|
handleMobileStubClick(e) {
|
|
1232
1327
|
e.preventDefault();
|
|
1233
1328
|
e.stopPropagation();
|
|
@@ -1421,7 +1516,7 @@ return;
|
|
|
1421
1516
|
this.updateComponentValue(current.filter((v) => v !== value), true, "remove", value);
|
|
1422
1517
|
}
|
|
1423
1518
|
clear() {
|
|
1424
|
-
this.updateComponentValue([], true, "clear", null);
|
|
1519
|
+
this.updateComponentValue([], true, "clear", null, false);
|
|
1425
1520
|
}
|
|
1426
1521
|
get value() {
|
|
1427
1522
|
return this.getSelectedValues().join(",");
|
|
@@ -1489,6 +1584,12 @@ return this.getProperty("required");
|
|
|
1489
1584
|
set required(value) {
|
|
1490
1585
|
this.setProperty("required", value);
|
|
1491
1586
|
}
|
|
1587
|
+
get error() {
|
|
1588
|
+
return this.getProperty("error");
|
|
1589
|
+
}
|
|
1590
|
+
set error(value) {
|
|
1591
|
+
this.setProperty("error", value);
|
|
1592
|
+
}
|
|
1492
1593
|
get notSearchable() {
|
|
1493
1594
|
return this.getProperty("notSearchable");
|
|
1494
1595
|
}
|
|
@@ -1530,8 +1631,14 @@ get flavor() {
|
|
|
1530
1631
|
return this.getProperty("flavor");
|
|
1531
1632
|
}
|
|
1532
1633
|
set flavor(value) {
|
|
1634
|
+
this.removeAttribute(ERROR_FLAVOR);
|
|
1533
1635
|
this.setProperty("flavor", value);
|
|
1534
1636
|
}
|
|
1637
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
1638
|
+
if (name === "flavor" && newValue === "danger" && oldValue === newValue)
|
|
1639
|
+
this.removeAttribute(ERROR_FLAVOR);
|
|
1640
|
+
super.attributeChangedCallback(name, oldValue, newValue);
|
|
1641
|
+
}
|
|
1535
1642
|
get form() {
|
|
1536
1643
|
return this._internals.form;
|
|
1537
1644
|
}
|
|
@@ -1592,6 +1699,11 @@ type: "boolean",
|
|
|
1592
1699
|
visual: true,
|
|
1593
1700
|
default: false,
|
|
1594
1701
|
},
|
|
1702
|
+
error: {
|
|
1703
|
+
type: "string",
|
|
1704
|
+
visual: true,
|
|
1705
|
+
default: "",
|
|
1706
|
+
},
|
|
1595
1707
|
noClear: {
|
|
1596
1708
|
type: "boolean",
|
|
1597
1709
|
visual: true,
|
|
@@ -84,7 +84,9 @@ export declare class TySwitch extends TyComponent<SwitchState> implements TySwit
|
|
|
84
84
|
protected render(): void;
|
|
85
85
|
/** Focus the switch itself (the host is not focusable; its role element is). */
|
|
86
86
|
focus(options?: FocusOptions): void;
|
|
87
|
-
/** required + unchecked => valueMissing; otherwise valid.
|
|
87
|
+
/** required + unchecked => valueMissing; otherwise valid. The message is a
|
|
88
|
+
* native checkbox's, as a switch where the browser has one (Safari's
|
|
89
|
+
* `switch` attribute). */
|
|
88
90
|
private updateValidity;
|
|
89
91
|
get checked(): boolean;
|
|
90
92
|
set checked(value: boolean);
|
package/lib/components/switch.js
CHANGED
|
@@ -3,6 +3,7 @@ import { TyComponent } from "../base/ty-component.js";
|
|
|
3
3
|
import { ensureStyles } from "../utils/styles.js";
|
|
4
4
|
import { syncCustomFlavorSheet } from "../utils/flavor-sheet.js";
|
|
5
5
|
import { switchStyles, switchCustomFlavorCss } from "../styles/switch.js";
|
|
6
|
+
import { nativeMessage } from "../utils/validity.js";
|
|
6
7
|
export class TySwitch extends TyComponent {
|
|
7
8
|
constructor() {
|
|
8
9
|
super();
|
|
@@ -159,7 +160,7 @@ this.applyValidity({});
|
|
|
159
160
|
return;
|
|
160
161
|
}
|
|
161
162
|
if (this.required && !this.checked) {
|
|
162
|
-
this.applyValidity({ valueMissing: true }, "
|
|
163
|
+
this.applyValidity({ valueMissing: true }, nativeMessage("input", { type: "checkbox", switch: true, required: true }), anchor ?? undefined);
|
|
163
164
|
}
|
|
164
165
|
else {
|
|
165
166
|
this.applyValidity({});
|
|
@@ -21,6 +21,10 @@ export interface TyTextareaElement extends HTMLElement {
|
|
|
21
21
|
label?: string;
|
|
22
22
|
disabled?: boolean;
|
|
23
23
|
required?: boolean;
|
|
24
|
+
minLength?: number;
|
|
25
|
+
maxLength?: number;
|
|
26
|
+
tooShortMessage?: string;
|
|
27
|
+
tooLongMessage?: string;
|
|
24
28
|
error?: string;
|
|
25
29
|
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
26
30
|
rows?: string | number;
|
|
@@ -63,6 +67,26 @@ export declare class TyTextarea extends TyComponent<TextareaState> implements Ty
|
|
|
63
67
|
visual: boolean;
|
|
64
68
|
default: boolean;
|
|
65
69
|
};
|
|
70
|
+
minlength: {
|
|
71
|
+
type: "string";
|
|
72
|
+
visual: boolean;
|
|
73
|
+
default: string;
|
|
74
|
+
};
|
|
75
|
+
maxlength: {
|
|
76
|
+
type: "string";
|
|
77
|
+
visual: boolean;
|
|
78
|
+
default: string;
|
|
79
|
+
};
|
|
80
|
+
tooShortMessage: {
|
|
81
|
+
type: "string";
|
|
82
|
+
visual: boolean;
|
|
83
|
+
default: string;
|
|
84
|
+
};
|
|
85
|
+
tooLongMessage: {
|
|
86
|
+
type: "string";
|
|
87
|
+
visual: boolean;
|
|
88
|
+
default: string;
|
|
89
|
+
};
|
|
66
90
|
error: {
|
|
67
91
|
type: "string";
|
|
68
92
|
visual: boolean;
|
|
@@ -129,6 +153,14 @@ export declare class TyTextarea extends TyComponent<TextareaState> implements Ty
|
|
|
129
153
|
focus(options?: FocusOptions): void;
|
|
130
154
|
get required(): boolean;
|
|
131
155
|
set required(v: boolean);
|
|
156
|
+
get minLength(): number;
|
|
157
|
+
set minLength(v: number);
|
|
158
|
+
get maxLength(): number;
|
|
159
|
+
set maxLength(v: number);
|
|
160
|
+
get tooShortMessage(): string;
|
|
161
|
+
set tooShortMessage(v: string);
|
|
162
|
+
get tooLongMessage(): string;
|
|
163
|
+
set tooLongMessage(v: string);
|
|
132
164
|
get error(): string;
|
|
133
165
|
set error(v: string);
|
|
134
166
|
get size(): 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
@@ -153,8 +185,6 @@ export declare class TyTextarea extends TyComponent<TextareaState> implements Ty
|
|
|
153
185
|
private _destroyScrollbar;
|
|
154
186
|
private emitValueEvent;
|
|
155
187
|
private handleInputEvent;
|
|
156
|
-
/** The user typed since the field was created: blur then shows its validation message. */
|
|
157
|
-
private _userEdited;
|
|
158
188
|
private _valueAtFocus;
|
|
159
189
|
private handleFocusEvent;
|
|
160
190
|
private handleBlurEvent;
|
|
@@ -162,8 +192,18 @@ export declare class TyTextarea extends TyComponent<TextareaState> implements Ty
|
|
|
162
192
|
private applyHeightConstraints;
|
|
163
193
|
private setupTextareaEvents;
|
|
164
194
|
protected render(): void;
|
|
165
|
-
/**
|
|
166
|
-
*
|
|
195
|
+
/**
|
|
196
|
+
* minlength goes on the inner <textarea> for the browser's own too-short
|
|
197
|
+
* message after the user types, maxlength so typing stops at the limit
|
|
198
|
+
* (like ty-input).
|
|
199
|
+
*/
|
|
200
|
+
private syncConstraintAttributes;
|
|
201
|
+
/**
|
|
202
|
+
* required + empty => valueMissing (the browser's own message); otherwise
|
|
203
|
+
* minlength / maxlength, worded like ty-input's (lengthValidity). Empty
|
|
204
|
+
* values only fail `required`, like native. Disabled fields are barred
|
|
205
|
+
* from constraint validation.
|
|
206
|
+
*/
|
|
167
207
|
private updateValidity;
|
|
168
208
|
}
|
|
169
209
|
export {};
|
|
@@ -4,7 +4,8 @@ import { ensureStyles } from '../utils/styles.js';
|
|
|
4
4
|
import { textareaStyles } from '../styles/textarea.js';
|
|
5
5
|
import { CustomScrollbar, isCustomScrollbarEnabled } from '../utils/custom-scrollbar.js';
|
|
6
6
|
import { customScrollbarStyles } from '../styles/custom-scrollbar.js';
|
|
7
|
-
|
|
7
|
+
import { nativeMessage, lengthValidity, toLimit } from '../utils/validity.js';
|
|
8
|
+
import { REQUIRED_ICON_SVG } from '../utils/icons.js';
|
|
8
9
|
export class TyTextarea extends TyComponent {
|
|
9
10
|
constructor() {
|
|
10
11
|
super();
|
|
@@ -24,7 +25,6 @@ this._internals.setFormValue(this.value || '');
|
|
|
24
25
|
this.updateValidity();
|
|
25
26
|
this.emitValueEvent('input', e);
|
|
26
27
|
};
|
|
27
|
-
this._userEdited = false;
|
|
28
28
|
this._valueAtFocus = null;
|
|
29
29
|
this.handleFocusEvent = () => {
|
|
30
30
|
this._isFocused = true;
|
|
@@ -76,6 +76,14 @@ this.shadowRoot?.querySelector('textarea')?.focus(options);
|
|
|
76
76
|
}
|
|
77
77
|
get required() { return this.getProperty('required'); }
|
|
78
78
|
set required(v) { this.setProperty('required', v); }
|
|
79
|
+
get minLength() { return toLimit(this.getProperty('minlength')) ?? -1; }
|
|
80
|
+
set minLength(v) { this.setProperty('minlength', v == null || v < 0 ? '' : String(v)); }
|
|
81
|
+
get maxLength() { return toLimit(this.getProperty('maxlength')) ?? -1; }
|
|
82
|
+
set maxLength(v) { this.setProperty('maxlength', v == null || v < 0 ? '' : String(v)); }
|
|
83
|
+
get tooShortMessage() { return this.getProperty('tooShortMessage'); }
|
|
84
|
+
set tooShortMessage(v) { this.setProperty('tooShortMessage', v ?? ''); }
|
|
85
|
+
get tooLongMessage() { return this.getProperty('tooLongMessage'); }
|
|
86
|
+
set tooLongMessage(v) { this.setProperty('tooLongMessage', v ?? ''); }
|
|
79
87
|
get error() { return this.getProperty('error'); }
|
|
80
88
|
set error(v) { this.setProperty('error', v); }
|
|
81
89
|
get size() {
|
|
@@ -257,18 +265,19 @@ const existingError = root.querySelector('.error-message');
|
|
|
257
265
|
if (existingContainer && existingTextarea) {
|
|
258
266
|
if (this.label) {
|
|
259
267
|
if (existingLabel) {
|
|
260
|
-
existingLabel.innerHTML = this.label
|
|
261
|
-
|
|
262
|
-
existingLabel.style.display = 'block';
|
|
268
|
+
existingLabel.innerHTML = `${this.label}${this.required ? `<span class="required-icon">${REQUIRED_ICON_SVG}</span>` : ''}`;
|
|
269
|
+
existingLabel.style.display = 'flex';
|
|
263
270
|
}
|
|
264
271
|
}
|
|
265
272
|
else if (existingLabel) {
|
|
266
273
|
existingLabel.style.display = 'none';
|
|
267
274
|
}
|
|
275
|
+
if (existingTextarea.value !== (this.value || ''))
|
|
268
276
|
existingTextarea.value = this.value || '';
|
|
269
277
|
existingTextarea.placeholder = this.placeholder || '';
|
|
270
278
|
existingTextarea.disabled = this.disabled;
|
|
271
279
|
existingTextarea.required = this.required;
|
|
280
|
+
this.syncConstraintAttributes(existingTextarea);
|
|
272
281
|
existingTextarea.className = this.buildClassList();
|
|
273
282
|
if (this.label)
|
|
274
283
|
existingTextarea.setAttribute('aria-label', this.label);
|
|
@@ -308,9 +317,8 @@ container.className = 'textarea-container';
|
|
|
308
317
|
const labelEl = document.createElement('label');
|
|
309
318
|
labelEl.className = 'ty-field-label';
|
|
310
319
|
if (this.label) {
|
|
311
|
-
labelEl.innerHTML = this.label
|
|
312
|
-
|
|
313
|
-
labelEl.style.display = 'block';
|
|
320
|
+
labelEl.innerHTML = `${this.label}${this.required ? `<span class="required-icon">${REQUIRED_ICON_SVG}</span>` : ''}`;
|
|
321
|
+
labelEl.style.display = 'flex';
|
|
314
322
|
}
|
|
315
323
|
else {
|
|
316
324
|
labelEl.style.display = 'none';
|
|
@@ -320,6 +328,7 @@ textareaEl.value = this.value || '';
|
|
|
320
328
|
textareaEl.placeholder = this.placeholder || '';
|
|
321
329
|
textareaEl.disabled = this.disabled;
|
|
322
330
|
textareaEl.required = this.required;
|
|
331
|
+
this.syncConstraintAttributes(textareaEl);
|
|
323
332
|
textareaEl.className = this.buildClassList();
|
|
324
333
|
if (this.label)
|
|
325
334
|
textareaEl.setAttribute('aria-label', this.label);
|
|
@@ -371,6 +380,11 @@ this._textareaEl = textareaEl;
|
|
|
371
380
|
}
|
|
372
381
|
this.updateValidity();
|
|
373
382
|
}
|
|
383
|
+
syncConstraintAttributes(ta) {
|
|
384
|
+
const set = (name, limit) => limit !== null ? ta.setAttribute(name, String(limit)) : ta.removeAttribute(name);
|
|
385
|
+
set('minlength', toLimit(this.getProperty('minlength')));
|
|
386
|
+
set('maxlength', toLimit(this.getProperty('maxlength')));
|
|
387
|
+
}
|
|
374
388
|
updateValidity() {
|
|
375
389
|
const ta = this.shadowRoot?.querySelector('textarea');
|
|
376
390
|
if (this.disabled) {
|
|
@@ -378,12 +392,22 @@ this.applyValidity({});
|
|
|
378
392
|
return;
|
|
379
393
|
}
|
|
380
394
|
const current = ta ? ta.value : String(this.value ?? '');
|
|
381
|
-
if (
|
|
382
|
-
this.
|
|
395
|
+
if (current.trim() === '') {
|
|
396
|
+
if (this.required) {
|
|
397
|
+
this.applyValidity({ valueMissing: true }, nativeMessage('textarea', { required: true }), ta ?? undefined);
|
|
383
398
|
}
|
|
384
399
|
else {
|
|
385
400
|
this.applyValidity({});
|
|
386
401
|
}
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
const { tooShort, tooLong } = lengthValidity(current, {
|
|
405
|
+
minlength: this.getProperty('minlength'),
|
|
406
|
+
maxlength: this.getProperty('maxlength'),
|
|
407
|
+
tooShortMessage: this.tooShortMessage,
|
|
408
|
+
tooLongMessage: this.tooLongMessage,
|
|
409
|
+
}, ta);
|
|
410
|
+
this.applyValidity({ tooShort: !!tooShort, tooLong: !!tooLong }, tooShort ?? tooLong, ta ?? undefined);
|
|
387
411
|
}
|
|
388
412
|
}
|
|
389
413
|
TyTextarea.formAssociated = true;
|
|
@@ -419,6 +443,26 @@ type: 'boolean',
|
|
|
419
443
|
visual: true,
|
|
420
444
|
default: false
|
|
421
445
|
},
|
|
446
|
+
minlength: {
|
|
447
|
+
type: 'string',
|
|
448
|
+
visual: true,
|
|
449
|
+
default: ''
|
|
450
|
+
},
|
|
451
|
+
maxlength: {
|
|
452
|
+
type: 'string',
|
|
453
|
+
visual: true,
|
|
454
|
+
default: ''
|
|
455
|
+
},
|
|
456
|
+
tooShortMessage: {
|
|
457
|
+
type: 'string',
|
|
458
|
+
visual: true,
|
|
459
|
+
default: ''
|
|
460
|
+
},
|
|
461
|
+
tooLongMessage: {
|
|
462
|
+
type: 'string',
|
|
463
|
+
visual: true,
|
|
464
|
+
default: ''
|
|
465
|
+
},
|
|
422
466
|
error: {
|
|
423
467
|
type: 'string',
|
|
424
468
|
visual: true,
|
package/lib/styles/button.js
CHANGED
|
@@ -69,11 +69,25 @@ color: var(--ty-button-color, ${ink('-strong')});
|
|
|
69
69
|
export const buttonCustomFlavorCss = (base) => solidFlavor(base, 'neutral') + outlinedFlavor(base, 'neutral') + ghostFlavor(base, 'neutral');
|
|
70
70
|
export const buttonStyles = `
|
|
71
71
|
:host {
|
|
72
|
-
|
|
72
|
+
--_rung: var(--ty-button-height);
|
|
73
|
+
display: inline-grid;
|
|
74
|
+
grid-template: minmax(var(--_rung), 1fr) / minmax(min-content, 1fr);
|
|
75
|
+
height: fit-content;
|
|
73
76
|
font-family: inherit;
|
|
74
77
|
}
|
|
78
|
+
:host([action]) {
|
|
79
|
+
--_rung: var(--ty-button-action-size);
|
|
80
|
+
}
|
|
81
|
+
:host([action]:not([wide])) {
|
|
82
|
+
width: fit-content;
|
|
83
|
+
aspect-ratio: 1;
|
|
84
|
+
}
|
|
75
85
|
:host([wide]) {
|
|
76
|
-
display:
|
|
86
|
+
display: grid;
|
|
87
|
+
flex-grow: 1;
|
|
88
|
+
grid-template-rows: minmax(var(--_rung), max-content);
|
|
89
|
+
}
|
|
90
|
+
:host([wide]) button {
|
|
77
91
|
flex-grow: 1;
|
|
78
92
|
}
|
|
79
93
|
:host {
|
|
@@ -140,6 +154,7 @@ align-items: center;
|
|
|
140
154
|
justify-content: center;
|
|
141
155
|
gap: var(--ty-button-gap);
|
|
142
156
|
height: var(--ty-button-height);
|
|
157
|
+
min-height: 100%;
|
|
143
158
|
padding: var(--ty-button-pad-y) var(--ty-button-pad-x);
|
|
144
159
|
font-size: var(--ty-button-font);
|
|
145
160
|
line-height: var(--ty-button-leading);
|
|
@@ -214,13 +229,11 @@ justify-content: center;
|
|
|
214
229
|
::slotted(ty-icon) {
|
|
215
230
|
flex-shrink: 0;
|
|
216
231
|
}
|
|
217
|
-
:host([wide]) button {
|
|
218
|
-
flex-grow: 1;
|
|
219
|
-
}
|
|
220
232
|
button.action {
|
|
221
233
|
gap: 0px !important;
|
|
222
|
-
height:
|
|
223
|
-
width: var(--ty-button-action-size);
|
|
234
|
+
height: auto;
|
|
235
|
+
min-width: var(--ty-button-action-size);
|
|
236
|
+
min-height: var(--ty-button-action-size);
|
|
224
237
|
padding: 0px !important;
|
|
225
238
|
}
|
|
226
239
|
button.action ::slotted(ty-icon) {
|
|
@@ -272,18 +285,6 @@ button.pill.xs { padding-left: 1em; padding-right: 1em; }
|
|
|
272
285
|
button.pill.sm { padding-left: 1.125em; padding-right: 1.125em; }
|
|
273
286
|
button.pill.lg { padding-left: 1.5em; padding-right: 1.5em; }
|
|
274
287
|
button.pill.xl { padding-left: 1.75em; padding-right: 1.75em; }
|
|
275
|
-
button.pill:has(ty-icon:only-child),
|
|
276
|
-
button.pill:has(slot[name="start"]:only-child),
|
|
277
|
-
button.pill:has(slot[name="end"]:only-child) {
|
|
278
|
-
padding: 0;
|
|
279
|
-
aspect-ratio: 1;
|
|
280
|
-
min-width: var(--ty-size-md);
|
|
281
|
-
}
|
|
282
|
-
button.pill.xs:has(ty-icon:only-child) { min-width: 1.375rem; min-height: 1.375rem; }
|
|
283
|
-
button.pill.sm:has(ty-icon:only-child) { min-width: 1.5rem; min-height: 1.5rem; }
|
|
284
|
-
button.pill.md:has(ty-icon:only-child) { min-width: 2rem; min-height: 2rem; }
|
|
285
|
-
button.pill.lg:has(ty-icon:only-child) { min-width: 2.25rem; min-height: 2.25rem; }
|
|
286
|
-
button.pill.xl:has(ty-icon:only-child) { min-width: 2.5rem; min-height: 2.5rem; }
|
|
287
288
|
button.solid {
|
|
288
289
|
--_ring: var(--ty-color-neutral);
|
|
289
290
|
--_solid-bg: var(--ty-button-bg, var(--ty-solid-neutral));
|
|
@@ -134,6 +134,23 @@ border-color: var(--date-picker-accent-bold, var(--ty-date-picker-border-focus))
|
|
|
134
134
|
box-shadow: 0 0 0 3px var(--date-picker-ring, var(--ty-date-picker-shadow-focus));
|
|
135
135
|
}
|
|
136
136
|
${FLAVORS.filter((f) => f !== "neutral").map((f) => datePickerFlavor(f)).join("")}
|
|
137
|
+
.error-message {
|
|
138
|
+
font-size: var(--ty-font-xs);
|
|
139
|
+
line-height: var(--ty-leading-xs);
|
|
140
|
+
letter-spacing: var(--ty-tracking-xs);
|
|
141
|
+
color: var(--ty-color-danger);
|
|
142
|
+
margin-top: 4px;
|
|
143
|
+
padding-left: var(--ty-field-outer-pad-x);
|
|
144
|
+
}
|
|
145
|
+
.date-picker-stub.error {
|
|
146
|
+
border-color: var(--ty-color-danger);
|
|
147
|
+
background: var(--ty-bg-danger-soft);
|
|
148
|
+
}
|
|
149
|
+
.date-picker-stub.error:focus,
|
|
150
|
+
.date-picker-stub.error.open {
|
|
151
|
+
border-color: var(--ty-color-danger-bold);
|
|
152
|
+
box-shadow: 0 0 0 3px var(--ty-date-picker-shadow-focus);
|
|
153
|
+
}
|
|
137
154
|
.stub-text {
|
|
138
155
|
flex: 1;
|
|
139
156
|
white-space: nowrap;
|
|
@@ -239,6 +239,32 @@ background: transparent;
|
|
|
239
239
|
border-color: transparent;
|
|
240
240
|
box-shadow: none;
|
|
241
241
|
}
|
|
242
|
+
.error-message {
|
|
243
|
+
font-size: var(--ty-font-xs);
|
|
244
|
+
line-height: var(--ty-leading-xs);
|
|
245
|
+
letter-spacing: var(--ty-tracking-xs);
|
|
246
|
+
color: var(--ty-color-danger);
|
|
247
|
+
margin-top: 4px;
|
|
248
|
+
padding-left: var(--ty-field-outer-pad-x);
|
|
249
|
+
contain: inline-size;
|
|
250
|
+
}
|
|
251
|
+
:host([compact]) .error-message,
|
|
252
|
+
:host([has-trigger]) .error-message {
|
|
253
|
+
box-sizing: border-box;
|
|
254
|
+
width: max(100%, 20em);
|
|
255
|
+
}
|
|
256
|
+
:host([has-trigger]) .error-message {
|
|
257
|
+
padding-left: 0;
|
|
258
|
+
}
|
|
259
|
+
.select-stub.error:not(.custom-trigger) {
|
|
260
|
+
border-color: var(--ty-color-danger);
|
|
261
|
+
background: var(--ty-bg-danger-soft);
|
|
262
|
+
}
|
|
263
|
+
.select-stub.error:not(.custom-trigger):focus,
|
|
264
|
+
.select-stub.error:not(.custom-trigger):focus-visible {
|
|
265
|
+
border-color: var(--ty-color-danger-bold);
|
|
266
|
+
box-shadow: 0 0 0 3px var(--input-shadow-focus, var(--ty-input-shadow-focus));
|
|
267
|
+
}
|
|
242
268
|
.dropdown-mode-mobile .dropdown-wrapper:has(.mobile-dialog[open]) .select-chips {
|
|
243
269
|
display: none;
|
|
244
270
|
}
|