@vaadin/field-base 25.2.7 → 25.3.0-alpha10

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.
@@ -227,6 +227,16 @@
227
227
  "description": "A mixin to provide common field logic: label, error message and helper text.",
228
228
  "name": "FieldMixin",
229
229
  "members": [
230
+ {
231
+ "kind": "field",
232
+ "name": "accessibleDescriptionRef",
233
+ "privacy": "public",
234
+ "type": {
235
+ "text": "string"
236
+ },
237
+ "description": "A space-separated list of IDs referencing the elements that\ndescribe the component for screen reader users. The referenced\nelements are announced in addition to the helper text and\nthe error message.",
238
+ "attribute": "accessible-description-ref"
239
+ },
230
240
  {
231
241
  "kind": "field",
232
242
  "name": "accessibleName",
@@ -234,7 +244,7 @@
234
244
  "type": {
235
245
  "text": "string"
236
246
  },
237
- "description": "String used to label the component to screen reader users.",
247
+ "description": "String used to label the component for screen reader users.",
238
248
  "attribute": "accessible-name"
239
249
  },
240
250
  {
@@ -244,7 +254,7 @@
244
254
  "type": {
245
255
  "text": "string"
246
256
  },
247
- "description": "Id of the element used as label of the component to screen reader users.",
257
+ "description": "A space-separated list of IDs referencing the elements that\nlabel the component for screen reader users.",
248
258
  "attribute": "accessible-name-ref"
249
259
  },
250
260
  {
@@ -353,12 +363,20 @@
353
363
  }
354
364
  ],
355
365
  "attributes": [
366
+ {
367
+ "name": "accessible-description-ref",
368
+ "type": {
369
+ "text": "string"
370
+ },
371
+ "description": "A space-separated list of IDs referencing the elements that\ndescribe the component for screen reader users. The referenced\nelements are announced in addition to the helper text and\nthe error message.",
372
+ "fieldName": "accessibleDescriptionRef"
373
+ },
356
374
  {
357
375
  "name": "accessible-name",
358
376
  "type": {
359
377
  "text": "string"
360
378
  },
361
- "description": "String used to label the component to screen reader users.",
379
+ "description": "String used to label the component for screen reader users.",
362
380
  "fieldName": "accessibleName"
363
381
  },
364
382
  {
@@ -366,7 +384,7 @@
366
384
  "type": {
367
385
  "text": "string"
368
386
  },
369
- "description": "Id of the element used as label of the component to screen reader users.",
387
+ "description": "A space-separated list of IDs referencing the elements that\nlabel the component for screen reader users.",
370
388
  "fieldName": "accessibleNameRef"
371
389
  },
372
390
  {
@@ -690,6 +708,20 @@
690
708
  "description": "A mixin to provide shared logic for the editable form input controls.",
691
709
  "name": "InputControlMixin",
692
710
  "members": [
711
+ {
712
+ "kind": "field",
713
+ "name": "accessibleDescriptionRef",
714
+ "privacy": "public",
715
+ "type": {
716
+ "text": "string"
717
+ },
718
+ "description": "A space-separated list of IDs referencing the elements that\ndescribe the component for screen reader users. The referenced\nelements are announced in addition to the helper text and\nthe error message.",
719
+ "attribute": "accessible-description-ref",
720
+ "inheritedFrom": {
721
+ "name": "FieldMixin",
722
+ "module": "src/field-mixin.js"
723
+ }
724
+ },
693
725
  {
694
726
  "kind": "field",
695
727
  "name": "accessibleName",
@@ -697,7 +729,7 @@
697
729
  "type": {
698
730
  "text": "string"
699
731
  },
700
- "description": "String used to label the component to screen reader users.",
732
+ "description": "String used to label the component for screen reader users.",
701
733
  "attribute": "accessible-name",
702
734
  "inheritedFrom": {
703
735
  "name": "FieldMixin",
@@ -711,7 +743,7 @@
711
743
  "type": {
712
744
  "text": "string"
713
745
  },
714
- "description": "Id of the element used as label of the component to screen reader users.",
746
+ "description": "A space-separated list of IDs referencing the elements that\nlabel the component for screen reader users.",
715
747
  "attribute": "accessible-name-ref",
716
748
  "inheritedFrom": {
717
749
  "name": "FieldMixin",
@@ -957,12 +989,24 @@
957
989
  }
958
990
  ],
959
991
  "attributes": [
992
+ {
993
+ "name": "accessible-description-ref",
994
+ "type": {
995
+ "text": "string"
996
+ },
997
+ "description": "A space-separated list of IDs referencing the elements that\ndescribe the component for screen reader users. The referenced\nelements are announced in addition to the helper text and\nthe error message.",
998
+ "fieldName": "accessibleDescriptionRef",
999
+ "inheritedFrom": {
1000
+ "name": "FieldMixin",
1001
+ "module": "src/field-mixin.js"
1002
+ }
1003
+ },
960
1004
  {
961
1005
  "name": "accessible-name",
962
1006
  "type": {
963
1007
  "text": "string"
964
1008
  },
965
- "description": "String used to label the component to screen reader users.",
1009
+ "description": "String used to label the component for screen reader users.",
966
1010
  "fieldName": "accessibleName",
967
1011
  "inheritedFrom": {
968
1012
  "name": "FieldMixin",
@@ -974,7 +1018,7 @@
974
1018
  "type": {
975
1019
  "text": "string"
976
1020
  },
977
- "description": "Id of the element used as label of the component to screen reader users.",
1021
+ "description": "A space-separated list of IDs referencing the elements that\nlabel the component for screen reader users.",
978
1022
  "fieldName": "accessibleNameRef",
979
1023
  "inheritedFrom": {
980
1024
  "name": "FieldMixin",
@@ -1225,6 +1269,20 @@
1225
1269
  "description": "A mixin to provide logic for vaadin-text-field and related components.",
1226
1270
  "name": "InputFieldMixin",
1227
1271
  "members": [
1272
+ {
1273
+ "kind": "field",
1274
+ "name": "accessibleDescriptionRef",
1275
+ "privacy": "public",
1276
+ "type": {
1277
+ "text": "string"
1278
+ },
1279
+ "description": "A space-separated list of IDs referencing the elements that\ndescribe the component for screen reader users. The referenced\nelements are announced in addition to the helper text and\nthe error message.",
1280
+ "attribute": "accessible-description-ref",
1281
+ "inheritedFrom": {
1282
+ "name": "FieldMixin",
1283
+ "module": "src/field-mixin.js"
1284
+ }
1285
+ },
1228
1286
  {
1229
1287
  "kind": "field",
1230
1288
  "name": "accessibleName",
@@ -1232,7 +1290,7 @@
1232
1290
  "type": {
1233
1291
  "text": "string"
1234
1292
  },
1235
- "description": "String used to label the component to screen reader users.",
1293
+ "description": "String used to label the component for screen reader users.",
1236
1294
  "attribute": "accessible-name",
1237
1295
  "inheritedFrom": {
1238
1296
  "name": "FieldMixin",
@@ -1246,7 +1304,7 @@
1246
1304
  "type": {
1247
1305
  "text": "string"
1248
1306
  },
1249
- "description": "Id of the element used as label of the component to screen reader users.",
1307
+ "description": "A space-separated list of IDs referencing the elements that\nlabel the component for screen reader users.",
1250
1308
  "attribute": "accessible-name-ref",
1251
1309
  "inheritedFrom": {
1252
1310
  "name": "FieldMixin",
@@ -1546,12 +1604,24 @@
1546
1604
  }
1547
1605
  ],
1548
1606
  "attributes": [
1607
+ {
1608
+ "name": "accessible-description-ref",
1609
+ "type": {
1610
+ "text": "string"
1611
+ },
1612
+ "description": "A space-separated list of IDs referencing the elements that\ndescribe the component for screen reader users. The referenced\nelements are announced in addition to the helper text and\nthe error message.",
1613
+ "fieldName": "accessibleDescriptionRef",
1614
+ "inheritedFrom": {
1615
+ "name": "FieldMixin",
1616
+ "module": "src/field-mixin.js"
1617
+ }
1618
+ },
1549
1619
  {
1550
1620
  "name": "accessible-name",
1551
1621
  "type": {
1552
1622
  "text": "string"
1553
1623
  },
1554
- "description": "String used to label the component to screen reader users.",
1624
+ "description": "String used to label the component for screen reader users.",
1555
1625
  "fieldName": "accessibleName",
1556
1626
  "inheritedFrom": {
1557
1627
  "name": "FieldMixin",
@@ -1563,7 +1633,7 @@
1563
1633
  "type": {
1564
1634
  "text": "string"
1565
1635
  },
1566
- "description": "Id of the element used as label of the component to screen reader users.",
1636
+ "description": "A space-separated list of IDs referencing the elements that\nlabel the component for screen reader users.",
1567
1637
  "fieldName": "accessibleNameRef",
1568
1638
  "inheritedFrom": {
1569
1639
  "name": "FieldMixin",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/field-base",
3
- "version": "25.2.7",
3
+ "version": "25.3.0-alpha10",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -32,17 +32,17 @@
32
32
  ],
33
33
  "dependencies": {
34
34
  "@open-wc/dedupe-mixin": "^1.3.0",
35
- "@vaadin/a11y-base": "~25.2.7",
36
- "@vaadin/component-base": "~25.2.7",
35
+ "@vaadin/a11y-base": "25.3.0-alpha10",
36
+ "@vaadin/component-base": "25.3.0-alpha10",
37
37
  "lit": "^3.0.0"
38
38
  },
39
39
  "devDependencies": {
40
- "@vaadin/chai-plugins": "~25.2.7",
41
- "@vaadin/input-container": "~25.2.7",
42
- "@vaadin/test-runner-commands": "~25.2.7",
40
+ "@vaadin/chai-plugins": "25.3.0-alpha10",
41
+ "@vaadin/input-container": "25.3.0-alpha10",
42
+ "@vaadin/test-runner-commands": "25.3.0-alpha10",
43
43
  "@vaadin/testing-helpers": "^2.0.0",
44
44
  "sinon": "^22.0.0"
45
45
  },
46
46
  "customElements": "custom-elements.json",
47
- "gitHead": "14be1af674f3968cce68c6eb4742340694c4a949"
47
+ "gitHead": "f2833abdf9b613fa0d0ed216830e3f4de87b7dac"
48
48
  }
@@ -30,17 +30,30 @@ export declare class FieldMixinClass {
30
30
  errorMessage: string | null | undefined;
31
31
 
32
32
  /**
33
- * String used to label the component to screen reader users.
33
+ * String used to label the component for screen reader users.
34
+ *
34
35
  * @attr {string} accessible-name
35
36
  */
36
37
  accessibleName: string | null | undefined;
37
38
 
38
39
  /**
39
- * Id of the element used as label of the component to screen reader users.
40
+ * A space-separated list of IDs referencing the elements that
41
+ * label the component for screen reader users.
42
+ *
40
43
  * @attr {string} accessible-name-ref
41
44
  */
42
45
  accessibleNameRef: string | null | undefined;
43
46
 
47
+ /**
48
+ * A space-separated list of IDs referencing the elements that
49
+ * describe the component for screen reader users. The referenced
50
+ * elements are announced in addition to the helper text and
51
+ * the error message.
52
+ *
53
+ * @attr {string} accessible-description-ref
54
+ */
55
+ accessibleDescriptionRef: string | null | undefined;
56
+
44
57
  /**
45
58
  * A target element to which ARIA attributes are set.
46
59
  */
@@ -49,12 +62,4 @@ export declare class FieldMixinClass {
49
62
  protected readonly _errorNode: HTMLElement;
50
63
 
51
64
  protected readonly _helperNode?: HTMLElement;
52
-
53
- protected _helperTextChanged(helperText: string | null | undefined): void;
54
-
55
- protected _ariaTargetChanged(target: HTMLElement): void;
56
-
57
- protected _requiredChanged(required: boolean): void;
58
-
59
- protected _invalidChanged(invalid: boolean): void;
60
65
  }
@@ -22,7 +22,6 @@ export const FieldMixin = (superclass) =>
22
22
  */
23
23
  ariaTarget: {
24
24
  type: Object,
25
- observer: '_ariaTargetChanged',
26
25
  },
27
26
 
28
27
  /**
@@ -32,7 +31,6 @@ export const FieldMixin = (superclass) =>
32
31
  */
33
32
  errorMessage: {
34
33
  type: String,
35
- observer: '_errorMessageChanged',
36
34
  },
37
35
 
38
36
  /**
@@ -41,54 +39,59 @@ export const FieldMixin = (superclass) =>
41
39
  */
42
40
  helperText: {
43
41
  type: String,
44
- observer: '_helperTextChanged',
45
42
  },
46
43
 
47
44
  /**
48
- * String used to label the component to screen reader users.
45
+ * String used to label the component for screen reader users.
46
+ *
49
47
  * @attr {string} accessible-name
50
48
  */
51
49
  accessibleName: {
52
50
  type: String,
53
- observer: '_accessibleNameChanged',
54
51
  },
55
52
 
56
53
  /**
57
- * Id of the element used as label of the component to screen reader users.
54
+ * A space-separated list of IDs referencing the elements that
55
+ * label the component for screen reader users.
56
+ *
58
57
  * @attr {string} accessible-name-ref
59
58
  */
60
59
  accessibleNameRef: {
61
60
  type: String,
62
- observer: '_accessibleNameRefChanged',
63
61
  },
64
- };
65
- }
66
62
 
67
- static get observers() {
68
- return ['_invalidChanged(invalid)', '_requiredChanged(required)'];
63
+ /**
64
+ * A space-separated list of IDs referencing the elements that
65
+ * describe the component for screen reader users. The referenced
66
+ * elements are announced in addition to the helper text and
67
+ * the error message.
68
+ *
69
+ * @attr {string} accessible-description-ref
70
+ */
71
+ accessibleDescriptionRef: {
72
+ type: String,
73
+ },
74
+ };
69
75
  }
70
76
 
71
77
  constructor() {
72
78
  super();
73
79
 
74
- this._fieldAriaController = new FieldAriaController(this);
75
- this._helperController = new HelperController(this);
76
- this._errorController = new ErrorController(this);
77
-
78
- this._errorController.addEventListener('slot-content-changed', (event) => {
79
- this.toggleAttribute('has-error-message', event.detail.hasContent);
80
- });
81
-
82
80
  this._labelController.addEventListener('slot-content-changed', (event) => {
83
- const { hasContent, node } = event.detail;
84
- this.__labelChanged(hasContent, node);
81
+ this.#onLabelSlotContentChange(event);
85
82
  });
86
83
 
84
+ this._helperController = new HelperController(this);
87
85
  this._helperController.addEventListener('slot-content-changed', (event) => {
88
- const { hasContent, node } = event.detail;
89
- this.toggleAttribute('has-helper', hasContent);
90
- this.__helperChanged(hasContent, node);
86
+ this.#onHelperSlotContentChange(event);
91
87
  });
88
+
89
+ this._errorController = new ErrorController(this);
90
+ this._errorController.addEventListener('slot-content-changed', (event) => {
91
+ this.#onErrorSlotContentChange(event);
92
+ });
93
+
94
+ this._fieldAriaController = new FieldAriaController(this);
92
95
  }
93
96
 
94
97
  /**
@@ -116,76 +119,86 @@ export const FieldMixin = (superclass) =>
116
119
  this.addController(this._errorController);
117
120
  }
118
121
 
119
- /** @private */
120
- __helperChanged(hasHelper, helperNode) {
121
- if (hasHelper) {
122
- this._fieldAriaController.setHelperId(helperNode.id);
123
- } else {
124
- this._fieldAriaController.setHelperId(null);
122
+ /** @protected */
123
+ updated(props) {
124
+ super.updated(props);
125
+
126
+ if (props.has('invalid')) {
127
+ this._errorController.setInvalid(this.invalid);
125
128
  }
126
- }
127
129
 
128
- /** @protected */
129
- _accessibleNameChanged(accessibleName) {
130
- this._fieldAriaController.setAriaLabel(accessibleName);
130
+ if (props.has('errorMessage')) {
131
+ this._errorController.setErrorMessage(this.errorMessage);
132
+ }
133
+
134
+ if (props.has('helperText')) {
135
+ this._helperController.setHelperText(this.helperText);
136
+ }
137
+
138
+ if (props.has('ariaTarget')) {
139
+ this._fieldAriaController.setTarget(this.ariaTarget);
140
+ }
141
+
142
+ if (props.has('required')) {
143
+ this._fieldAriaController.setRequired(this.required);
144
+ }
145
+
146
+ if (props.has('accessibleName')) {
147
+ this.__updateFieldAriaControllerLabel();
148
+ }
149
+
150
+ if (props.has('accessibleName') || props.has('accessibleNameRef')) {
151
+ this.__updateFieldAriaControllerLabelledBy();
152
+ }
153
+
154
+ if (props.has('accessibleDescriptionRef')) {
155
+ this.__updateFieldAriaControllerDescribedBy();
156
+ }
131
157
  }
132
158
 
133
- /** @protected */
134
- _accessibleNameRefChanged(accessibleNameRef) {
135
- this._fieldAriaController.setLabelId(accessibleNameRef, true);
159
+ /** @private */
160
+ __updateFieldAriaControllerLabel() {
161
+ this._fieldAriaController.setLabel(this.accessibleName);
136
162
  }
137
163
 
138
164
  /** @private */
139
- __labelChanged(hasLabel, labelNode) {
140
- // Label ID should be only added when the label content is present.
141
- // Otherwise, it may conflict with an `aria-label` attribute possibly added by the user.
142
- if (hasLabel) {
143
- this._fieldAriaController.setLabelId(labelNode.id);
144
- } else {
145
- this._fieldAriaController.setLabelId(null);
165
+ __updateFieldAriaControllerLabelledBy() {
166
+ let id = null;
167
+
168
+ if (this.accessibleNameRef) {
169
+ id = this.accessibleNameRef;
170
+ } else if (this.hasAttribute('has-label') && !this.accessibleName) {
171
+ // Label ID should be only added when the label content is present
172
+ // and not overridden by `accessible-name` which sets `aria-label`.
173
+ id = this._labelNode?.id;
146
174
  }
147
- }
148
175
 
149
- /**
150
- * @param {string | null | undefined} errorMessage
151
- * @protected
152
- */
153
- _errorMessageChanged(errorMessage) {
154
- this._errorController.setErrorMessage(errorMessage);
176
+ this._fieldAriaController.setLabelledBy(id);
155
177
  }
156
178
 
157
- /**
158
- * @param {string} helperText
159
- * @protected
160
- */
161
- _helperTextChanged(helperText) {
162
- this._helperController.setHelperText(helperText);
179
+ /** @private */
180
+ __updateFieldAriaControllerDescribedBy() {
181
+ this._fieldAriaController.setDescribedBy(this.accessibleDescriptionRef);
163
182
  }
164
183
 
165
- /**
166
- * @param {HTMLElement | null | undefined} target
167
- * @protected
168
- */
169
- _ariaTargetChanged(target) {
170
- if (target) {
171
- this._fieldAriaController.setTarget(target);
172
- }
184
+ #onLabelSlotContentChange(_event) {
185
+ this.__updateFieldAriaControllerLabelledBy();
173
186
  }
174
187
 
175
- /**
176
- * @param {boolean} required
177
- * @protected
178
- */
179
- _requiredChanged(required) {
180
- this._fieldAriaController.setRequired(required);
188
+ #onHelperSlotContentChange(event) {
189
+ const { hasContent } = event.detail;
190
+
191
+ this.toggleAttribute('has-helper', hasContent);
192
+
193
+ if (hasContent) {
194
+ this._fieldAriaController.setHelperId(this._helperNode?.id);
195
+ } else {
196
+ this._fieldAriaController.setHelperId(null);
197
+ }
181
198
  }
182
199
 
183
- /**
184
- * @param {boolean} invalid
185
- * @protected
186
- */
187
- _invalidChanged(invalid) {
188
- this._errorController.setInvalid(invalid);
200
+ #onErrorSlotContentChange(event) {
201
+ this.toggleAttribute('has-error-message', event.detail.hasContent);
189
202
 
190
203
  // This timeout is needed to prevent NVDA from announcing the error message twice:
191
204
  // 1. Once adding the `[role=alert]` attribute when updating `has-error-message` (OK).
@@ -194,9 +207,8 @@ export const FieldMixin = (superclass) =>
194
207
  setTimeout(() => {
195
208
  // Error message ID needs to be dynamically added / removed based on the validity
196
209
  // Otherwise assistive technologies would announce the error, even if we hide it.
197
- if (invalid) {
198
- const node = this._errorNode;
199
- this._fieldAriaController.setErrorId(node?.id);
210
+ if (this.invalid) {
211
+ this._fieldAriaController.setErrorId(this._errorNode?.id);
200
212
  } else {
201
213
  this._fieldAriaController.setErrorId(null);
202
214
  }
@@ -10,23 +10,21 @@
10
10
  export class LabelledInputController {
11
11
  constructor(input, labelController) {
12
12
  this.input = input;
13
- this.__preventDuplicateLabelClick = this.__preventDuplicateLabelClick.bind(this);
14
13
 
15
14
  labelController.addEventListener('slot-content-changed', (event) => {
16
- this.__initLabel(event.detail.node);
15
+ this.#initLabel(event.detail.node);
17
16
  });
18
17
 
19
18
  // Initialize the default label element
20
- this.__initLabel(labelController.node);
19
+ this.#initLabel(labelController.node);
21
20
  }
22
21
 
23
22
  /**
24
23
  * @param {HTMLElement} label
25
- * @private
26
24
  */
27
- __initLabel(label) {
25
+ #initLabel(label) {
28
26
  if (label) {
29
- label.addEventListener('click', this.__preventDuplicateLabelClick);
27
+ label.addEventListener('click', this.#preventDuplicateLabelClick);
30
28
 
31
29
  if (this.input) {
32
30
  label.setAttribute('for', this.input.id);
@@ -40,13 +38,12 @@ export class LabelledInputController {
40
38
  * This results in two click events arriving at the host, but we only want one.
41
39
  * This method prevents the duplicate click and ensures the correct isTrusted event
42
40
  * with the correct event.target arrives at the host.
43
- * @private
44
41
  */
45
- __preventDuplicateLabelClick() {
42
+ #preventDuplicateLabelClick = () => {
46
43
  const inputClickHandler = (e) => {
47
44
  e.stopImmediatePropagation();
48
45
  this.input.removeEventListener('click', inputClickHandler);
49
46
  };
50
47
  this.input.addEventListener('click', inputClickHandler);
51
- }
48
+ };
52
49
  }
@@ -18,10 +18,6 @@ export const checkable = (part, propName = part) => css`
18
18
  --_cursor: var(--vaadin-clickable-cursor);
19
19
  }
20
20
 
21
- :host([disabled]) {
22
- --_cursor: var(--vaadin-disabled-cursor);
23
- }
24
-
25
21
  :host(:not([has-label])) {
26
22
  column-gap: 0;
27
23
  }
@@ -94,8 +90,8 @@ export const checkable = (part, propName = part) => css`
94
90
  box-sizing: border-box;
95
91
  --_color: var(--vaadin-${unsafeCSS(propName)}-marker-color, var(--vaadin-${unsafeCSS(propName)}-background, var(--vaadin-background-color)));
96
92
  color: var(--_color);
97
- height: var(--vaadin-${unsafeCSS(propName)}-size, 1lh);
98
- width: var(--vaadin-${unsafeCSS(propName)}-size, 1lh);
93
+ height: var(--vaadin-${unsafeCSS(propName)}-size, round(1.125em, 2px));
94
+ width: var(--vaadin-${unsafeCSS(propName)}-size, round(1.125em, 2px));
99
95
  position: relative;
100
96
  cursor: var(--_cursor);
101
97
  display: flex;
@@ -108,10 +104,24 @@ export const checkable = (part, propName = part) => css`
108
104
  --vaadin-${unsafeCSS(propName)}-border-color: transparent;
109
105
  }
110
106
 
107
+ :host([readonly]) {
108
+ --vaadin-${unsafeCSS(part)}-background: transparent;
109
+ --vaadin-${unsafeCSS(part)}-border-color: var(--vaadin-border-color);
110
+ --vaadin-${unsafeCSS(part)}-marker-color: var(--vaadin-text-color);
111
+ --_border-style: dashed;
112
+ --_cursor: var(--vaadin-disabled-cursor);
113
+
114
+ [part='label'],
115
+ ::slotted(label) {
116
+ cursor: default;
117
+ }
118
+ }
119
+
111
120
  :host([disabled]) {
112
121
  --vaadin-${unsafeCSS(propName)}-background: var(--vaadin-input-field-disabled-background, var(--vaadin-background-container-strong));
113
122
  --vaadin-${unsafeCSS(propName)}-border-color: transparent;
114
123
  --vaadin-${unsafeCSS(propName)}-marker-color: var(--vaadin-text-color-disabled);
124
+ --_cursor: var(--vaadin-disabled-cursor);
115
125
  }
116
126
 
117
127
  /* Focus ring */
@@ -145,6 +155,30 @@ export const checkable = (part, propName = part) => css`
145
155
  opacity: 0;
146
156
  }
147
157
 
158
+ /* Reverse variant */
159
+ :host([theme~='reverse']) {
160
+ grid-template-columns: 1fr auto;
161
+
162
+ &::before {
163
+ display: none;
164
+ }
165
+
166
+ [part='label'],
167
+ [part='helper-text'],
168
+ [part='error-message'] {
169
+ grid-column: 1;
170
+ }
171
+
172
+ [part='${unsafeCSS(part)}'],
173
+ ::slotted(input) {
174
+ grid-column: 2;
175
+ }
176
+
177
+ ::slotted(input) {
178
+ margin-inline: calc(min(0px, (24px - 100%) / -2) - var(--vaadin-${unsafeCSS(propName)}-gap, var(--vaadin-gap-s))) 0 !important;
179
+ }
180
+ }
181
+
148
182
  @media (forced-colors: active) {
149
183
  :host(:is([checked], [indeterminate])) {
150
184
  --vaadin-${unsafeCSS(propName)}-border-color: CanvasText !important;
@@ -18,19 +18,18 @@ export class VirtualKeyboardController {
18
18
  host.addEventListener('opened-changed', () => {
19
19
  if (!host.opened) {
20
20
  // Prevent opening the virtual keyboard when the input gets re-focused on dropdown close
21
- this.__setVirtualKeyboardEnabled(false);
21
+ this.#setVirtualKeyboardEnabled(false);
22
22
  }
23
23
  });
24
24
 
25
25
  // Re-enable virtual keyboard on blur, so it gets opened when the field is focused again
26
- host.addEventListener('blur', () => this.__setVirtualKeyboardEnabled(true));
26
+ host.addEventListener('blur', () => this.#setVirtualKeyboardEnabled(true));
27
27
 
28
28
  // Re-enable the virtual keyboard whenever the field is touched
29
- host.addEventListener('touchstart', () => this.__setVirtualKeyboardEnabled(true));
29
+ host.addEventListener('touchstart', () => this.#setVirtualKeyboardEnabled(true));
30
30
  }
31
31
 
32
- /** @private */
33
- __setVirtualKeyboardEnabled(value) {
32
+ #setVirtualKeyboardEnabled(value) {
34
33
  if (this.host.inputElement) {
35
34
  this.host.inputElement.inputMode = value ? '' : 'none';
36
35
  }