@descope/web-components-ui 1.0.321 → 1.0.323

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.
Files changed (56) hide show
  1. package/dist/cjs/index.cjs.js +555 -25
  2. package/dist/cjs/index.cjs.js.map +1 -1
  3. package/dist/index.esm.js +634 -86
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/umd/4392.js +1 -1
  6. package/dist/umd/DescopeDev.js +1 -1
  7. package/dist/umd/boolean-fields-descope-checkbox-index-js.js +1 -1
  8. package/dist/umd/boolean-fields-descope-switch-toggle-index-js.js +1 -1
  9. package/dist/umd/button-selection-group-fields-descope-button-multi-selection-group-index-js.js +1 -1
  10. package/dist/umd/button-selection-group-fields-descope-button-selection-group-index-js.js +1 -1
  11. package/dist/umd/descope-combo-box-index-js.js +7 -7
  12. package/dist/umd/descope-email-field-index-js.js +4 -4
  13. package/dist/umd/descope-grid-descope-grid-selection-column-index-js.js +1 -1
  14. package/dist/umd/descope-grid-index-js.js +1 -1
  15. package/dist/umd/descope-multi-select-combo-box-index-js.js +1 -1
  16. package/dist/umd/descope-new-password-descope-new-password-internal-index-js.js +1 -1
  17. package/dist/umd/descope-new-password-index-js.js +1 -1
  18. package/dist/umd/descope-number-field-index-js.js +1 -1
  19. package/dist/umd/descope-passcode-index-js.js +1 -1
  20. package/dist/umd/descope-password-index-js.js +1 -1
  21. package/dist/umd/descope-radio-group-index-js.js +1 -1
  22. package/dist/umd/descope-text-area-index-js.js +1 -1
  23. package/dist/umd/descope-text-field-index-js.js +2 -2
  24. package/dist/umd/index.js +1 -1
  25. package/dist/umd/mapping-fields-descope-mappings-field-index-js.js +1 -1
  26. package/dist/umd/mapping-fields-descope-saml-group-mappings-index-js.js +1 -1
  27. package/dist/umd/phone-fields-descope-phone-field-descope-phone-field-internal-index-js.js +1 -1
  28. package/dist/umd/phone-fields-descope-phone-field-index-js.js +1 -1
  29. package/dist/umd/phone-fields-descope-phone-input-box-field-descope-phone-input-box-internal-index-js.js +1 -1
  30. package/dist/umd/phone-fields-descope-phone-input-box-field-index-js.js +1 -1
  31. package/package.json +1 -1
  32. package/src/components/descope-combo-box/ComboBoxClass.js +57 -0
  33. package/src/components/descope-email-field/EmailFieldClass.js +74 -1
  34. package/src/components/descope-multi-select-combo-box/MultiSelectComboBoxClass.js +31 -0
  35. package/src/components/descope-new-password/NewPasswordClass.js +7 -0
  36. package/src/components/descope-new-password/descope-new-password-internal/NewPasswordInternal.js +1 -0
  37. package/src/components/descope-number-field/NumberFieldClass.js +9 -0
  38. package/src/components/descope-password/PasswordClass.js +43 -3
  39. package/src/components/descope-text-field/TextFieldClass.js +24 -1
  40. package/src/components/descope-text-field/textFieldMappings.js +40 -6
  41. package/src/components/phone-fields/descope-phone-field/PhoneFieldClass.js +36 -4
  42. package/src/components/phone-fields/descope-phone-field/descope-phone-field-internal/PhoneFieldInternal.js +19 -3
  43. package/src/components/phone-fields/descope-phone-input-box-field/PhoneFieldInputBoxClass.js +45 -1
  44. package/src/components/phone-fields/descope-phone-input-box-field/descope-phone-input-box-internal/PhoneFieldInternalInputBox.js +1 -0
  45. package/src/{components/descope-password/helpers.js → helpers/externalInputs.js} +5 -5
  46. package/src/helpers/themeHelpers/resetHelpers.js +15 -0
  47. package/src/theme/components/comboBox.js +17 -0
  48. package/src/theme/components/emailField.js +17 -0
  49. package/src/theme/components/inputWrapper.js +35 -0
  50. package/src/theme/components/multiSelectComboBox.js +22 -0
  51. package/src/theme/components/newPassword.js +10 -0
  52. package/src/theme/components/numberField.js +17 -0
  53. package/src/theme/components/password.js +17 -0
  54. package/src/theme/components/phoneField.js +8 -0
  55. package/src/theme/components/phoneInputBoxField.js +17 -0
  56. package/src/theme/components/textField.js +17 -0
@@ -12,12 +12,13 @@ import {
12
12
  resetInputLabelPosition,
13
13
  resetInputCursor,
14
14
  useHostExternalPadding,
15
+ inputFloatingLabelStyle,
15
16
  } from '../../helpers/themeHelpers/resetHelpers';
16
17
  import {
17
18
  applyExternalInputStyles,
18
19
  createExternalInputEle,
19
20
  createExternalInputSlot,
20
- } from './helpers';
21
+ } from '../../helpers/externalInputs';
21
22
 
22
23
  export const componentName = getComponentName('password');
23
24
 
@@ -40,13 +41,23 @@ const customMixin = (superclass) =>
40
41
  this.baseElement.appendChild(externalInputSlot);
41
42
 
42
43
  // create external input
43
- const externalInput = createExternalInputEle('external-input', this.getAutocompleteType());
44
+ const externalInput = createExternalInputEle(
45
+ 'external-input',
46
+ 'password',
47
+ this.getAutocompleteType()
48
+ );
44
49
 
45
50
  this.handlePasswordVisibility(externalInput);
46
51
 
47
52
  // apply original input's styles to external input
48
53
  setTimeout(() => {
49
- applyExternalInputStyles(origInput, externalInput);
54
+ applyExternalInputStyles(
55
+ origInput,
56
+ externalInput,
57
+ `
58
+ width: calc(100% - 3em) !important;
59
+ `
60
+ );
50
61
  });
51
62
 
52
63
  // set external input events
@@ -191,6 +202,8 @@ export const PasswordClass = compose(
191
202
  inputOutlineOffset: { ...inputField, property: 'outline-offset' },
192
203
  inputOutlineWidth: { ...inputField, property: 'outline-width' },
193
204
 
205
+ labelFontSize: { ...label, property: 'font-size' },
206
+ labelFontWeight: { ...label, property: 'font-weight' },
194
207
  labelTextColor: [
195
208
  { ...label, property: 'color' },
196
209
  { ...requiredIndicator, property: 'color' },
@@ -213,6 +226,22 @@ export const PasswordClass = compose(
213
226
  ],
214
227
  revealButtonSize: { ...revealButtonContainer, property: 'font-size' },
215
228
  revealButtonColor: { ...revealButtonIcon, property: 'color' },
229
+
230
+ labelPosition: { ...label, property: 'position' },
231
+ labelTopPosition: { ...label, property: 'top' },
232
+ labelHorizontalPosition: [
233
+ { ...label, property: 'left' },
234
+ { ...label, property: 'right' },
235
+ ],
236
+ inputTransformY: { ...label, property: 'transform' },
237
+ inputTransition: { ...label, property: 'transition' },
238
+ marginInlineStart: { ...label, property: 'margin-inline-start' },
239
+ placeholderOpacity: [
240
+ { selector: '> input:placeholder-shown', property: 'opacity' },
241
+ { ...inputElement, property: 'opacity' },
242
+ ],
243
+ inputVerticalAlignment: { ...inputField, property: 'align-items' },
244
+ valueInputHeight: { ...inputElement, property: 'height' },
216
245
  },
217
246
  }),
218
247
  draggableMixin,
@@ -274,6 +303,17 @@ export const PasswordClass = compose(
274
303
  vaadin-password-field-button[focus-ring] {
275
304
  box-shadow: 0 0 0 2px var(${PasswordClass.cssVarList.inputOutlineColor});
276
305
  }
306
+
307
+ ${inputFloatingLabelStyle()}
308
+
309
+ :host ::slotted(input) {
310
+ display: none !important;
311
+ }
312
+
313
+ ::part(reveal-button) {
314
+ align-self: center;
315
+ }
316
+
277
317
  `,
278
318
  excludeAttrsSync: ['tabindex'],
279
319
  componentName,
@@ -9,6 +9,7 @@ import textFieldMappings from './textFieldMappings';
9
9
  import { compose } from '../../helpers';
10
10
  import { getComponentName } from '../../helpers/componentHelpers';
11
11
  import {
12
+ inputFloatingLabelStyle,
12
13
  resetInputLabelPosition,
13
14
  resetInputOverrides,
14
15
  useHostExternalPadding,
@@ -16,7 +17,7 @@ import {
16
17
 
17
18
  export const componentName = getComponentName('text-field');
18
19
 
19
- const observedAttrs = ['type'];
20
+ const observedAttrs = ['type', 'label-type'];
20
21
 
21
22
  const customMixin = (superclass) =>
22
23
  class TextFieldClass extends superclass {
@@ -24,6 +25,10 @@ const customMixin = (superclass) =>
24
25
  return observedAttrs.concat(superclass.observedAttributes || []);
25
26
  }
26
27
 
28
+ onLabelClick() {
29
+ this.focus();
30
+ }
31
+
27
32
  attributeChangedCallback(attrName, oldVal, newVal) {
28
33
  super.attributeChangeCallback?.(attrName, oldVal, newVal);
29
34
 
@@ -35,6 +40,16 @@ const customMixin = (superclass) =>
35
40
  if (attrName === 'type') {
36
41
  this.baseElement._setType(newVal);
37
42
  }
43
+
44
+ if (oldVal !== newVal) {
45
+ if (attrName === 'label-type') {
46
+ if (newVal === 'floating') {
47
+ this.addEventListener('click', this.onLabelClick);
48
+ } else {
49
+ this.removeEventListener('click', this.onLabelClick);
50
+ }
51
+ }
52
+ }
38
53
  }
39
54
 
40
55
  // webauthn is not working when the native input element is nested inside multiple shadow roots
@@ -87,9 +102,17 @@ export const TextFieldClass = compose(
87
102
  :host(:is([readonly], [disabled])) ::slotted(:is(input, textarea):placeholder-shown) {
88
103
  opacity: 1;
89
104
  }
105
+
106
+ vaadin-text-field[label-type="floating"]:not([focused])[readonly] > input:placeholder-shown {
107
+ opacity: 0;
108
+ }
109
+ vaadin-text-field[label-type="floating"]:not([focused])[disabled] > input:placeholder-shown {
110
+ opacity: 0;
111
+ }
90
112
  ${resetInputLabelPosition('vaadin-text-field')}
91
113
  ${useHostExternalPadding(TextFieldClass.cssVarList)}
92
114
  ${resetInputOverrides('vaadin-text-field', TextFieldClass.cssVarList)}
115
+ ${inputFloatingLabelStyle()}
93
116
  `,
94
117
  excludeAttrsSync: ['tabindex'],
95
118
  componentName,
@@ -17,7 +17,10 @@ const {
17
17
  host: { selector: () => ':host' },
18
18
  label: { selector: '::part(label)' },
19
19
  requiredIndicator: { selector: '[required]::part(required-indicator)::after' },
20
- placeholder: { selector: '> input:placeholder-shown' },
20
+ placeholder: [
21
+ { selector: '> input:placeholder-shown' },
22
+ { selector: () => ':host::slotted(input:placeholder-shown)' },
23
+ ],
21
24
  disabledPlaceholder: { selector: '> input:disabled::placeholder' },
22
25
  inputField: { selector: '::part(input-field)' },
23
26
  input: { selector: 'input' },
@@ -35,11 +38,8 @@ export default {
35
38
  fontSize: [{}, host],
36
39
  fontFamily: [label, inputField, helperText, errorMessage],
37
40
 
38
- hostWidth: { ...host, property: 'width' },
39
- hostMinWidth: { ...host, property: 'min-width' },
40
- hostDirection: { ...host, property: 'direction' },
41
-
42
- inputBackgroundColor: { ...inputField, property: 'background-color' },
41
+ labelFontSize: { ...label, property: 'font-size' },
42
+ labelFontWeight: { ...label, property: 'font-weight' },
43
43
 
44
44
  labelTextColor: [
45
45
  { ...label, property: 'color' },
@@ -47,6 +47,13 @@ export default {
47
47
  { ...label, property: '-webkit-text-fill-color' },
48
48
  { ...requiredIndicator, property: '-webkit-text-fill-color' },
49
49
  ],
50
+
51
+ hostWidth: { ...host, property: 'width' },
52
+ hostMinWidth: { ...host, property: 'min-width' },
53
+ hostDirection: { ...host, property: 'direction' },
54
+
55
+ inputBackgroundColor: { ...inputField, property: 'background-color' },
56
+
50
57
  errorMessageTextColor: { ...errorMessage, property: 'color' },
51
58
  helperTextColor: { ...helperText, property: '-webkit-text-fill-color' },
52
59
 
@@ -86,9 +93,36 @@ export default {
86
93
  ],
87
94
 
88
95
  inputPlaceholderColor: [
96
+ { selector: () => ':host input:placeholder-shown', property: 'color' },
89
97
  { ...placeholder, property: 'color' },
90
98
  { ...externalPlaceholder, property: 'color' },
91
99
  { ...disabledPlaceholder, property: '-webkit-text-fill-color' },
92
100
  { ...externalDisabledPlaceholder, property: '-webkit-text-fill-color' },
93
101
  ],
102
+
103
+ labelPosition: { ...label, property: 'position' },
104
+ labelTopPosition: { ...label, property: 'top' },
105
+ labelHorizontalPosition: [
106
+ { ...label, property: 'left' },
107
+ { ...label, property: 'right' },
108
+ ],
109
+ inputTransformY: { ...label, property: 'transform' },
110
+ inputTransition: { ...label, property: 'transition' },
111
+ marginInlineStart: { ...label, property: 'margin-inline-start' },
112
+ placeholderOpacity: [
113
+ { selector: '> input:placeholder-shown', property: 'opacity' },
114
+ { ...externalPlaceholder, property: 'opacity' },
115
+ ],
116
+ inputVerticalAlignment: [
117
+ { ...inputField, property: 'align-items' },
118
+ { ...externalInput, property: 'align-items' },
119
+ ],
120
+ valueInputHeight: [
121
+ { ...input, property: 'height' },
122
+ { ...externalInput, property: 'height' },
123
+ ],
124
+ valueInputMarginBottom: [
125
+ { ...input, property: 'margin-bottom' },
126
+ { ...externalInput, property: 'margin-bottom' },
127
+ ],
94
128
  };
@@ -52,6 +52,10 @@ const customMixin = (superclass) =>
52
52
  'phone-input-placeholder',
53
53
  'disabled',
54
54
  'restrict-countries',
55
+ 'label-type',
56
+ 'country-input-label',
57
+ 'phone-input-label',
58
+ 'readonly',
55
59
  ],
56
60
  });
57
61
  }
@@ -64,6 +68,7 @@ const {
64
68
  inputField,
65
69
  countryCodeInput,
66
70
  phoneInput,
71
+ phoneExternalInput,
67
72
  separator,
68
73
  errorMessage,
69
74
  helperText,
@@ -73,6 +78,7 @@ const {
73
78
  requiredIndicator: { selector: '[required]::part(required-indicator)::after' },
74
79
  inputField: { selector: '::part(input-field)' },
75
80
  phoneInput: { selector: () => 'descope-text-field' },
81
+ phoneExternalInput: { selector: () => '::slotted(input)' },
76
82
  countryCodeInput: { selector: () => 'descope-combo-box' },
77
83
  separator: { selector: 'descope-phone-field-internal .separator' },
78
84
  helperText: { selector: '::part(helper-text)' },
@@ -131,6 +137,13 @@ export const PhoneFieldClass = compose(
131
137
  },
132
138
  phoneInputWidth: { ...phoneInput, property: 'width' },
133
139
 
140
+ horizontalPadding: [
141
+ { ...phoneInput, property: 'padding-left' },
142
+ { ...phoneInput, property: 'padding-right' },
143
+ { ...countryCodeInput, property: 'padding-left' },
144
+ { ...countryCodeInput, property: 'padding-right' },
145
+ ],
146
+
134
147
  labelTextColor: [
135
148
  { ...label, property: 'color' },
136
149
  { ...requiredIndicator, property: 'color' },
@@ -154,6 +167,20 @@ export const PhoneFieldClass = compose(
154
167
  inputOutlineColor: { ...inputField, property: 'outline-color' },
155
168
  inputOutlineWidth: { ...inputField, property: 'outline-width' },
156
169
  inputOutlineOffset: { ...inputField, property: 'outline-offset' },
170
+
171
+ valueInputHeight: [
172
+ { ...phoneExternalInput, property: textVars.valueInputHeight },
173
+ { ...countryCodeInput, property: comboVars.valueInputHeight },
174
+ ],
175
+ valueInputMarginBottom: [
176
+ { ...phoneInput, property: textVars.valueInputMarginBottom },
177
+ { ...phoneExternalInput, property: 'margin-bottom' },
178
+ ],
179
+ marginInlineStart: [
180
+ { ...phoneInput, property: textVars.marginInlineStart },
181
+ { ...phoneExternalInput, property: 'margin-inline-start' },
182
+ { ...countryCodeInput, property: comboVars.marginInlineStart },
183
+ ],
157
184
  },
158
185
  }),
159
186
  draggableMixin,
@@ -224,10 +251,15 @@ export const PhoneFieldClass = compose(
224
251
  ${textVars.inputOutlineOffset}: 0;
225
252
  ${textVars.inputBorderWidth}: 0;
226
253
  ${textVars.inputBorderRadius}: 0;
227
- }
228
- vaadin-text-field[readonly] > input:placeholder-shown {
229
- opacity: 1;
230
- }
254
+ }
255
+
256
+ descope-text-field[label-type="floating"]:not([focused])[readonly] > input:placeholder-shown {
257
+ opacity: 0;
258
+ }
259
+ descope-text-field[label-type="floating"]:not([focused])[disabled] > input:placeholder-shown {
260
+ opacity: 0;
261
+ }
262
+
231
263
  vaadin-text-field::part(input-field)::after {
232
264
  border: none;
233
265
  }
@@ -1,19 +1,22 @@
1
1
  import { createBaseInputClass } from '../../../../baseClasses/createBaseInputClass';
2
- import { getComponentName } from '../../../../helpers/componentHelpers';
2
+ import { forwardAttrs, getComponentName, syncAttrs } from '../../../../helpers/componentHelpers';
3
3
  import CountryCodes from '../../CountryCodes';
4
4
  import { comboBoxItem } from '../helpers';
5
5
 
6
6
  export const componentName = getComponentName('phone-field-internal');
7
7
 
8
- const commonAttrs = ['disabled', 'size', 'bordered', 'invalid', 'readonly'];
8
+ const commonAttrs = ['disabled', 'size', 'bordered', 'invalid', 'readonly', 'label-type'];
9
9
  const countryAttrs = ['country-input-placeholder', 'default-code', 'restrict-countries'];
10
10
  const phoneAttrs = ['phone-input-placeholder', 'maxlength', 'autocomplete', 'name'];
11
+ const labelTypeAttrs = ['country-input-label', 'phone-input-label'];
11
12
  const mapAttrs = {
13
+ 'country-input-label': 'label',
14
+ 'phone-input-label': 'label',
12
15
  'country-input-placeholder': 'placeholder',
13
16
  'phone-input-placeholder': 'placeholder',
14
17
  };
15
18
 
16
- const inputRelatedAttrs = [].concat(commonAttrs, countryAttrs, phoneAttrs);
19
+ const inputRelatedAttrs = [].concat(commonAttrs, countryAttrs, phoneAttrs, labelTypeAttrs);
17
20
 
18
21
  const BaseInputClass = createBaseInputClass({ componentName, baseSelector: 'div' });
19
22
 
@@ -42,6 +45,12 @@ class PhoneFieldInternal extends BaseInputClass {
42
45
  this.phoneNumberInput = this.querySelector('descope-text-field');
43
46
  this.inputs = [this.countryCodeInput, this.phoneNumberInput];
44
47
 
48
+ forwardAttrs(this, this.countryCodeInput, { includeAttrs: ['label-type'] });
49
+ forwardAttrs(this, this.phoneNumberInput, { includeAttrs: ['label-type'] });
50
+
51
+ const externalInput = this.phoneNumberInput.querySelector('input');
52
+ syncAttrs(this.phoneNumberInput, externalInput, { includeAttrs: ['focused'] });
53
+
45
54
  // override combo box setter to display dialCode value in input
46
55
  this.countryCodeInput.customValueTransformFn = (val) => {
47
56
  const [, dialCode] = val?.split?.(' ') || [];
@@ -178,6 +187,13 @@ class PhoneFieldInternal extends BaseInputClass {
178
187
  this.countryCodeInput.setAttribute(attr, newValue);
179
188
  } else if (phoneAttrs.includes(attrName)) {
180
189
  this.phoneNumberInput.setAttribute(attr, newValue);
190
+ } else if (labelTypeAttrs.includes(attrName)) {
191
+ if (attrName === 'country-input-label') {
192
+ this.countryCodeInput.setAttribute(attr, newValue);
193
+ }
194
+ if (attrName === 'phone-input-label') {
195
+ this.phoneNumberInput.setAttribute(attr, newValue);
196
+ }
181
197
  }
182
198
  }
183
199
  if (attrName === 'restrict-countries') {
@@ -10,6 +10,7 @@ import {
10
10
  resetInputFieldDefaultWidth,
11
11
  resetInputFieldInvalidBackgroundColor,
12
12
  useHostExternalPadding,
13
+ inputFloatingLabelStyle,
13
14
  } from '../../../helpers/themeHelpers/resetHelpers';
14
15
 
15
16
  const textVars = TextFieldClass.cssVarList;
@@ -48,14 +49,26 @@ const customMixin = (superclass) =>
48
49
  'default-code',
49
50
  'disabled',
50
51
  'phone-input-placeholder',
52
+ 'label-type',
51
53
  ],
52
54
  });
53
55
  }
54
56
  };
55
57
 
56
- const { host, label, requiredIndicator, inputField, phoneInput, errorMessage, helperText } = {
58
+ const {
59
+ host,
60
+ label,
61
+ inputElement,
62
+ requiredIndicator,
63
+ inputField,
64
+ phoneInput,
65
+ errorMessage,
66
+ helperText,
67
+ } = {
57
68
  host: { selector: () => ':host' },
58
69
  label: { selector: '::part(label)' },
70
+ placeholder: { selector: '> input:placeholder-shown' },
71
+ inputElement: { selector: 'input' },
59
72
  requiredIndicator: { selector: '[required]::part(required-indicator)::after' },
60
73
  inputField: { selector: '::part(input-field)' },
61
74
  phoneInput: { selector: () => 'descope-text-field' },
@@ -84,6 +97,13 @@ export const PhoneFieldInputBoxClass = compose(
84
97
  inputBorderColor: { ...inputField, property: 'border-color' },
85
98
  inputBorderRadius: { ...inputField, property: 'border-radius' },
86
99
 
100
+ inputHorizontalPadding: [
101
+ { ...phoneInput, property: 'padding-left' },
102
+ { ...phoneInput, property: 'padding-right' },
103
+ ],
104
+
105
+ labelFontSize: { ...label, property: 'font-size' },
106
+ labelFontWeight: { ...label, property: 'font-weight' },
87
107
  labelTextColor: [
88
108
  { ...label, property: 'color' },
89
109
  { ...requiredIndicator, property: 'color' },
@@ -99,6 +119,21 @@ export const PhoneFieldInputBoxClass = compose(
99
119
  inputOutlineColor: { ...inputField, property: 'outline-color' },
100
120
  inputOutlineWidth: { ...inputField, property: 'outline-width' },
101
121
  inputOutlineOffset: { ...inputField, property: 'outline-offset' },
122
+
123
+ labelPosition: { ...label, property: 'position' },
124
+ labelTopPosition: { ...label, property: 'top' },
125
+ labelHorizontalPosition: [
126
+ { ...label, property: 'left' },
127
+ { ...label, property: 'right' },
128
+ ],
129
+ inputTransformY: { ...label, property: 'transform' },
130
+ inputTransition: { ...label, property: 'transition' },
131
+ marginInlineStart: { ...label, property: 'margin-inline-start' },
132
+ valueInputHeight: { ...inputElement, property: 'height' },
133
+ valueInputMarginBottom: {
134
+ selector: TextFieldClass.componentName,
135
+ property: textVars.valueInputMarginBottom,
136
+ },
102
137
  },
103
138
  }),
104
139
  draggableMixin,
@@ -166,7 +201,16 @@ export const PhoneFieldInputBoxClass = compose(
166
201
  vaadin-text-field::part(input-field)::after {
167
202
  border: none;
168
203
  }
204
+
205
+ vaadin-text-field[label-type="floating"]:not([focused])[readonly] input:placeholder-shown {
206
+ opacity: 0;
207
+ }
208
+ vaadin-text-field[label-type="floating"]:not([focused])[disabled] input:placeholder-shown {
209
+ opacity: 0;
210
+ }
211
+
169
212
  ${resetInputLabelPosition('vaadin-text-field')}
213
+ ${inputFloatingLabelStyle()}
170
214
  `,
171
215
  excludeAttrsSync: ['tabindex'],
172
216
  componentName,
@@ -13,6 +13,7 @@ const observedAttributes = [
13
13
  'phone-input-placeholder',
14
14
  'name',
15
15
  'autocomplete',
16
+ 'label-type',
16
17
  ];
17
18
  const mapAttrs = {
18
19
  'phone-input-placeholder': 'placeholder',
@@ -1,6 +1,6 @@
1
1
  // since on load we can only sample the color of the placeholder,
2
2
  // we need to temporarily populate the input in order to sample the value color
3
- const getValueColor = (ele, computedStyle) => {
3
+ export const getValueColor = (ele, computedStyle) => {
4
4
  // eslint-disable-next-line no-param-reassign
5
5
  ele.value = '_';
6
6
 
@@ -21,18 +21,18 @@ export const createExternalInputSlot = (slotName, targetSlotName) => {
21
21
  return slotEle;
22
22
  };
23
23
 
24
- export const createExternalInputEle = (targetSlotName, autocompleteType) => {
24
+ export const createExternalInputEle = (targetSlotName, type, autocompleteType) => {
25
25
  const inputEle = document.createElement('input');
26
26
 
27
27
  inputEle.setAttribute('slot', targetSlotName);
28
- inputEle.setAttribute('type', 'password');
28
+ inputEle.setAttribute('type', type);
29
29
  inputEle.setAttribute('data-hidden-input', 'true');
30
30
  inputEle.setAttribute('autocomplete', autocompleteType);
31
31
 
32
32
  return inputEle;
33
33
  };
34
34
 
35
- export const applyExternalInputStyles = (sourceInputEle, targetInputEle) => {
35
+ export const applyExternalInputStyles = (sourceInputEle, targetInputEle, customStyle) => {
36
36
  const computedStyle = getComputedStyle(sourceInputEle);
37
37
  const height = computedStyle.getPropertyValue('height');
38
38
  const paddingLeft = computedStyle.getPropertyValue('padding-left');
@@ -48,7 +48,6 @@ export const applyExternalInputStyles = (sourceInputEle, targetInputEle) => {
48
48
  targetInputEle.style = `
49
49
  all: unset !important;
50
50
  position: absolute !important;
51
- width: calc(100% - 3em) !important;
52
51
  background-color: transparent !important;
53
52
  color: ${valueColor} !important;
54
53
  height: ${height} !important;
@@ -58,5 +57,6 @@ export const applyExternalInputStyles = (sourceInputEle, targetInputEle) => {
58
57
  font-family: ${fontFamily} !important;
59
58
  letter-spacing: ${letterSpacing} !important;
60
59
  caret-color: ${caretColor} !important;
60
+ ${customStyle || ''}
61
61
  `;
62
62
  };
@@ -126,3 +126,18 @@ export const resetInputLabelPosition = (name) => `
126
126
  padding-bottom: 0.5em;
127
127
  }
128
128
  `;
129
+
130
+ export const inputFloatingLabelStyle = () => {
131
+ return `
132
+ :host([label-type="floating"]) {
133
+ position: relative;
134
+ }
135
+ :host([label-type="floating"][has-label]) [slot="label"] {
136
+ padding: 0;
137
+ }
138
+ :host([label-type="floating"][has-label]) > ::part(label) {
139
+ z-index: 1;
140
+ padding: 0;
141
+ }
142
+ `;
143
+ };
@@ -11,6 +11,8 @@ export const comboBox = {
11
11
  [vars.hostDirection]: refs.direction,
12
12
  [vars.fontSize]: refs.fontSize,
13
13
  [vars.fontFamily]: refs.fontFamily,
14
+ [vars.labelFontSize]: refs.labelFontSize,
15
+ [vars.labelFontWeight]: refs.labelFontWeight,
14
16
  [vars.labelTextColor]: refs.labelTextColor,
15
17
  [vars.errorMessageTextColor]: refs.errorMessageTextColor,
16
18
  [vars.inputBorderColor]: refs.borderColor,
@@ -34,6 +36,21 @@ export const comboBox = {
34
36
  [vars.overlayItemPaddingInlineStart]: globalRefs.spacing.xs,
35
37
  [vars.overlayItemPaddingInlineEnd]: globalRefs.spacing.lg,
36
38
 
39
+ labelType: {
40
+ floating: {
41
+ [vars.labelPosition]: refs.labelPosition,
42
+ [vars.labelTopPosition]: refs.labelTopPosition,
43
+ [vars.labelHorizontalPosition]: refs.labelHorizontalPosition,
44
+ [vars.inputTransformY]: refs.inputTransformY,
45
+ [vars.inputTransition]: refs.inputTransition,
46
+ [vars.marginInlineStart]: refs.marginInlineStart,
47
+ [vars.placeholderOpacity]: refs.placeholderOpacity,
48
+ [vars.inputVerticalAlignment]: refs.inputVerticalAlignment,
49
+ [vars.valueInputHeight]: refs.valueInputHeight,
50
+ [vars.valueInputMarginBottom]: refs.valueInputMarginBottom,
51
+ },
52
+ },
53
+
37
54
  _readonly: {
38
55
  [vars.inputDropdownButtonCursor]: 'default',
39
56
  },
@@ -9,6 +9,8 @@ const emailField = {
9
9
  [vars.hostDirection]: refs.direction,
10
10
  [vars.fontSize]: refs.fontSize,
11
11
  [vars.fontFamily]: refs.fontFamily,
12
+ [vars.labelFontSize]: refs.labelFontSize,
13
+ [vars.labelFontWeight]: refs.labelFontWeight,
12
14
  [vars.labelTextColor]: refs.labelTextColor,
13
15
  [vars.errorMessageTextColor]: refs.errorMessageTextColor,
14
16
  [vars.inputValueTextColor]: refs.valueTextColor,
@@ -25,6 +27,21 @@ const emailField = {
25
27
  [vars.inputBackgroundColor]: refs.backgroundColor,
26
28
  [vars.inputHorizontalPadding]: refs.horizontalPadding,
27
29
  [vars.inputHeight]: refs.inputHeight,
30
+
31
+ labelType: {
32
+ floating: {
33
+ [vars.labelPosition]: refs.labelPosition,
34
+ [vars.labelTopPosition]: refs.labelTopPosition,
35
+ [vars.labelHorizontalPosition]: refs.labelHorizontalPosition,
36
+ [vars.inputTransformY]: refs.inputTransformY,
37
+ [vars.inputTransition]: refs.inputTransition,
38
+ [vars.marginInlineStart]: refs.marginInlineStart,
39
+ [vars.placeholderOpacity]: refs.placeholderOpacity,
40
+ [vars.inputVerticalAlignment]: refs.inputVerticalAlignment,
41
+ [vars.valueInputHeight]: refs.valueInputHeight,
42
+ [vars.valueInputMarginBottom]: refs.valueInputMarginBottom,
43
+ },
44
+ },
28
45
  };
29
46
 
30
47
  export default emailField;
@@ -9,6 +9,7 @@ const [theme, refs, vars] = createHelperVars(
9
9
  {
10
10
  labelTextColor: globalRefs.colors.surface.dark,
11
11
  labelFontSize: '14px', // not taken from globals as it is fixed in all inputs
12
+ labelFontWeight: '500', // not taken from globals as it is fixed in all inputs
12
13
  valueTextColor: globalRefs.colors.surface.contrast,
13
14
  placeholderTextColor: globalRefs.colors.surface.dark,
14
15
  requiredIndicator: "'*'",
@@ -46,6 +47,40 @@ const [theme, refs, vars] = createHelperVars(
46
47
  lg: { fontSize: '18px', chipFontSize: '16px' },
47
48
  },
48
49
 
50
+ labelType: {
51
+ floating: {
52
+ labelPosition: 'absolute',
53
+ labelTopPosition: '0',
54
+ labelHorizontalPosition: '0.9em',
55
+ labelFontSize: '1em',
56
+ placeholderOpacity: 0,
57
+ inputHeight: '3.5em',
58
+ inputVerticalAlignment: 'flex-end',
59
+ inputTransformY: 'translateY(1.55em)',
60
+ inputTransition: 'all 75ms ease-in-out',
61
+ marginInlineStart: '0', // `calc(0.25em + ${globalRefs.border.sm})`,
62
+ valueInputHeight: '1.5702em',
63
+ valueInputMarginBottom: '0.5em',
64
+
65
+ _focused: {
66
+ labelFontSize: '0.75em',
67
+ inputTransformY: 'translateY(1.05em)',
68
+ labelFontWeight: '400',
69
+ placeholderOpacity: 1,
70
+ },
71
+
72
+ _readOnly: {
73
+ placeholderOpacity: 0,
74
+ },
75
+
76
+ _hasValue: {
77
+ inputTransformY: 'translateY(1.05em)',
78
+ labelFontSize: '0.75em',
79
+ labelFontWeight: '400',
80
+ },
81
+ },
82
+ },
83
+
49
84
  _fullWidth: {
50
85
  width: '100%',
51
86
  },
@@ -11,6 +11,8 @@ export const multiSelectComboBox = {
11
11
  [vars.hostDirection]: refs.direction,
12
12
  [vars.fontSize]: refs.fontSize,
13
13
  [vars.fontFamily]: refs.fontFamily,
14
+ [vars.labelFontSize]: refs.labelFontSize,
15
+ [vars.labelFontWeight]: refs.labelFontWeight,
14
16
  [vars.labelTextColor]: refs.labelTextColor,
15
17
  [vars.errorMessageTextColor]: refs.errorMessageTextColor,
16
18
  [vars.inputBorderColor]: refs.borderColor,
@@ -38,6 +40,26 @@ export const multiSelectComboBox = {
38
40
  [vars.chipTextColor]: globalRefs.colors.surface.contrast,
39
41
  [vars.chipBackgroundColor]: globalRefs.colors.surface.light,
40
42
 
43
+ labelType: {
44
+ floating: {
45
+ [vars.labelPosition]: refs.labelPosition,
46
+ [vars.labelTopPosition]: refs.labelTopPosition,
47
+ [vars.labelLeftPosition]: refs.labelLeftPosition,
48
+ [vars.labelHorizontalPosition]: refs.labelHorizontalPosition,
49
+ [vars.inputTransformY]: refs.inputTransformY,
50
+ [vars.inputTransition]: refs.inputTransition,
51
+ [vars.marginInlineStart]: refs.marginInlineStart,
52
+ [vars.placeholderOpacity]: refs.placeholderOpacity,
53
+ [vars.inputVerticalAlignment]: refs.inputVerticalAlignment,
54
+ [vars.valueInputHeight]: refs.valueInputHeight,
55
+ [vars.inputHorizontalPadding]: '0.25em',
56
+
57
+ _hasValue: {
58
+ [vars.inputHorizontalPadding]: '0.45em',
59
+ },
60
+ },
61
+ },
62
+
41
63
  _readonly: {
42
64
  [vars.inputDropdownButtonCursor]: 'default',
43
65
  },