@descope/web-components-ui 1.0.278 → 1.0.280

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. package/dist/cjs/index.cjs.js +1124 -890
  2. package/dist/cjs/index.cjs.js.map +1 -1
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.esm.js +1583 -965
  5. package/dist/index.esm.js.map +1 -1
  6. package/dist/umd/1000.js +1 -1
  7. package/dist/umd/1438.js +2 -2
  8. package/dist/umd/{9558.js → 1621.js} +117 -117
  9. package/dist/umd/2066.js +1 -1
  10. package/dist/umd/3280.js +197 -0
  11. package/dist/umd/3280.js.LICENSE.txt +29 -0
  12. package/dist/umd/{6542.js → 3951.js} +6 -6
  13. package/dist/umd/{6542.js.LICENSE.txt → 3951.js.LICENSE.txt} +0 -6
  14. package/dist/umd/422.js +1 -1
  15. package/dist/umd/5806.js +1 -1
  16. package/dist/umd/6770.js +1 -1
  17. package/dist/umd/6977.js +2 -0
  18. package/dist/umd/6977.js.LICENSE.txt +5 -0
  19. package/dist/umd/7056.js +1 -1
  20. package/dist/umd/7531.js +2 -2
  21. package/dist/umd/7583.js +2 -2
  22. package/dist/umd/8725.js +1 -1
  23. package/dist/umd/9092.js +2 -2
  24. package/dist/umd/9437.js +1 -1
  25. package/dist/umd/descope-combo-box-index-js.js +1 -1
  26. package/dist/umd/descope-grid-index-js.js +1 -1
  27. package/dist/umd/descope-notification-descope-notification-card-index-js.js +1 -1
  28. package/dist/umd/descope-notification-index-js.js +1 -1
  29. package/dist/umd/index.js +1 -1
  30. package/dist/umd/mapping-fields-descope-mappings-field-descope-mapping-item-index-js.js +1 -0
  31. package/dist/umd/mapping-fields-descope-mappings-field-descope-mappings-field-internal-index-js.js +1 -0
  32. package/dist/umd/mapping-fields-descope-mappings-field-index-js.js +1 -0
  33. package/package.json +4 -1
  34. package/src/components/descope-combo-box/ComboBoxClass.js +4 -0
  35. package/src/components/descope-grid/GridClass.js +1 -0
  36. package/src/components/mapping-fields/descope-mappings-field/MappingsFieldClass.js +159 -0
  37. package/src/components/mapping-fields/descope-mappings-field/descope-mapping-item/MappingItem.js +158 -0
  38. package/src/components/mapping-fields/descope-mappings-field/descope-mapping-item/index.js +3 -0
  39. package/src/components/mapping-fields/descope-mappings-field/descope-mappings-field-internal/MappingsFieldInternal.js +232 -0
  40. package/src/components/mapping-fields/descope-mappings-field/descope-mappings-field-internal/index.js +3 -0
  41. package/src/components/mapping-fields/descope-mappings-field/index.js +14 -0
  42. package/src/index.cjs.js +1 -0
  43. package/src/index.d.ts +1 -0
  44. package/src/index.js +1 -0
  45. package/src/mixins/inputValidationMixin.js +8 -0
  46. package/src/mixins/proxyInputMixin.js +48 -6
  47. package/src/theme/components/index.js +2 -0
  48. package/src/theme/components/mappingsField.js +25 -0
  49. /package/dist/umd/{9558.js.LICENSE.txt → 1621.js.LICENSE.txt} +0 -0
@@ -0,0 +1,158 @@
1
+ import { createBaseInputClass } from '../../../../baseClasses/createBaseInputClass';
2
+ import { forwardAttrs, getComponentName } from '../../../../helpers/componentHelpers';
3
+
4
+ export const componentName = getComponentName('mapping-item');
5
+
6
+ const inputAttrs = ['size', 'bordered', 'readonly', 'full-width', 'disabled'];
7
+
8
+ const BaseInputClass = createBaseInputClass({ componentName, baseSelector: 'div' });
9
+
10
+ class MappingItem extends BaseInputClass {
11
+ static get observedAttributes() {
12
+ return [].concat(BaseInputClass.observedAttributes || [], inputAttrs, [
13
+ 'separator',
14
+ 'options',
15
+ 'invalid',
16
+ 'disabled',
17
+ ]);
18
+ }
19
+
20
+ get separator() {
21
+ return this.getAttribute('separator') || 'map to';
22
+ }
23
+
24
+ get value() {
25
+ const attributeValue = this.attributeInput.value;
26
+ const inputValue = this.valueInput.value;
27
+ if (attributeValue && inputValue) {
28
+ return { [attributeValue]: inputValue };
29
+ }
30
+ return null;
31
+ }
32
+
33
+ set value(mapping) {
34
+ if (Object.entries(mapping).length !== 1) {
35
+ // eslint-disable-next-line no-console
36
+ console.error(
37
+ 'descope-mapping item expected expects only one key-value pair in the value but received: ',
38
+ mapping
39
+ );
40
+ return;
41
+ }
42
+ const [attribute, value] = Object.entries(mapping)[0];
43
+ this.valueInput.value = value;
44
+ this.attributeInput.value = attribute;
45
+ // The event needs to be dispatched to trigger the validation if setting the value externally
46
+ this.dispatchEvent(new InputEvent('input', { bubbles: true, composed: true }));
47
+ }
48
+
49
+ constructor() {
50
+ super();
51
+
52
+ this.attachShadow({ mode: 'open' }).innerHTML = `
53
+ <style>
54
+ .wrapper {
55
+ display: flex;
56
+ }
57
+ .separator {
58
+ text-align: center;
59
+ flex-shrink: 0;
60
+ }
61
+ </style>
62
+ <div class="wrapper" part="wrapper">
63
+ <descope-text-field required="true"></descope-text-field>
64
+ <div class="separator" part="separator">${this.separator}</div>
65
+ <descope-combo-box
66
+ item-label-path="data-name"
67
+ item-value-path="data-id"
68
+ required="true"
69
+ >
70
+ </descope-combo-box>
71
+ <descope-button variant="link" mode="primary">
72
+ <vaadin-icon icon="vaadin:minus"></vaadin-icon>
73
+ </descope-button>
74
+ </div>
75
+ `;
76
+ this.valueInput = this.shadowRoot.querySelector('descope-text-field');
77
+ this.attributeInput = this.shadowRoot.querySelector('descope-combo-box');
78
+ this.inputs = [this.valueInput, this.attributeInput];
79
+ this.removeButton = this.shadowRoot.querySelector('descope-button');
80
+
81
+ forwardAttrs(this, this.valueInput, {
82
+ includeAttrs: inputAttrs,
83
+ });
84
+ forwardAttrs(this, this.attributeInput, {
85
+ includeAttrs: [...inputAttrs, 'options'],
86
+ mapAttrs: { options: 'data' },
87
+ });
88
+ forwardAttrs(this, this.removeButton, {
89
+ includeAttrs: ['disabled'],
90
+ });
91
+ }
92
+
93
+ initRemoveButton() {
94
+ this.removeButton.addEventListener('click', () =>
95
+ this.dispatchEvent(new CustomEvent('mapping-item-removed'))
96
+ );
97
+ }
98
+
99
+ init() {
100
+ super.init?.();
101
+ this.initRemoveButton();
102
+ }
103
+
104
+ getValidity() {
105
+ const attributeValue = this.attributeInput.value;
106
+ const inputValue = this.valueInput.value;
107
+ if (!attributeValue || !inputValue) {
108
+ return { badInput: true };
109
+ }
110
+ return {};
111
+ }
112
+
113
+ reportValidity() {
114
+ this.inputs.forEach((input) => input.reportValidity());
115
+ }
116
+
117
+ focus() {
118
+ const focusedElement =
119
+ this.checkValidity() || !this.valueInput.checkValidity()
120
+ ? this.valueInput
121
+ : this.attributeInput;
122
+ focusedElement.focus();
123
+ }
124
+
125
+ handleSeparatorChange() {
126
+ this.shadowRoot.querySelector('.separator').textContent = this.separator;
127
+ }
128
+
129
+ #handleInvalidMapping(invalid) {
130
+ if (invalid === 'true') {
131
+ const inputValue = this.valueInput.value;
132
+ if (!inputValue) {
133
+ this.valueInput.setAttribute('invalid', 'true');
134
+ this.valueInput.setAttribute('error-message', this.defaultErrorMsgValueMissing);
135
+ }
136
+
137
+ const attributeValue = this.attributeInput.value;
138
+ if (!attributeValue) {
139
+ this.attributeInput.setAttribute('invalid', 'true');
140
+ this.attributeInput.setAttribute('error-message', this.defaultErrorMsgValueMissing);
141
+ }
142
+ }
143
+ }
144
+
145
+ attributeChangedCallback(attrName, oldValue, newValue) {
146
+ super.attributeChangedCallback?.(attrName, oldValue, newValue);
147
+
148
+ if (attrName === 'separator') {
149
+ this.handleSeparatorChange();
150
+ }
151
+
152
+ if (attrName === 'invalid') {
153
+ this.#handleInvalidMapping(newValue);
154
+ }
155
+ }
156
+ }
157
+
158
+ export default MappingItem;
@@ -0,0 +1,3 @@
1
+ import MappingItem, { componentName } from './MappingItem';
2
+
3
+ customElements.define(componentName, MappingItem);
@@ -0,0 +1,232 @@
1
+ import { createBaseInputClass } from '../../../../baseClasses/createBaseInputClass';
2
+ import { getComponentName, forwardAttrs } from '../../../../helpers/componentHelpers';
3
+
4
+ export const componentName = getComponentName('mappings-field-internal');
5
+
6
+ const BaseInputClass = createBaseInputClass({ componentName, baseSelector: 'div' });
7
+
8
+ class MappingsFieldInternal extends BaseInputClass {
9
+ #errorItem;
10
+
11
+ static get observedAttributes() {
12
+ return [].concat(BaseInputClass.observedAttributes || [], [
13
+ 'label-value',
14
+ 'label-attr',
15
+ 'button-label',
16
+ 'invalid',
17
+ 'readonly',
18
+ 'disabled',
19
+ ]);
20
+ }
21
+
22
+ // eslint-disable-next-line class-methods-use-this
23
+ isValidDataType(data) {
24
+ try {
25
+ return data.every(
26
+ (obj) =>
27
+ typeof obj === 'object' &&
28
+ !Array.isArray(obj) &&
29
+ Object.getOwnPropertyNames(obj).length === 1 &&
30
+ typeof obj[Object.keys(obj)[0]] === 'string' &&
31
+ obj[Object.keys(obj)[0]].trim() !== ''
32
+ );
33
+ } catch (e) {
34
+ return false;
35
+ }
36
+ }
37
+
38
+ get labelValue() {
39
+ return this.getAttribute('label-value') || 'Value';
40
+ }
41
+
42
+ get labelAttr() {
43
+ return this.getAttribute('label-attr') || 'Attribute';
44
+ }
45
+
46
+ get buttonLabel() {
47
+ return this.getAttribute('button-label') || 'Add mapping';
48
+ }
49
+
50
+ get options() {
51
+ return this.getAttribute('options') || [];
52
+ }
53
+
54
+ addNewMappingItem() {
55
+ const newMappingItem = document.createElement('descope-mapping-item');
56
+ newMappingItem.setAttribute('bordered', 'true');
57
+ this.mappingsContainerEle.appendChild(newMappingItem);
58
+ forwardAttrs(this, newMappingItem, {
59
+ includeAttrs: ['size', 'full-width', 'separator', 'options', 'disabled'],
60
+ });
61
+ // This needs to be done with the timeout, otherwise the validation is performed
62
+ // before the new item is added and thus returns a wrong result
63
+ setTimeout(() => {
64
+ this.setCustomValidity('');
65
+ newMappingItem.addEventListener('mapping-item-removed', (e) => {
66
+ // If the removed item was the one that was invalid, we need to reset the invalid indication for the internal
67
+ if (newMappingItem === this.#errorItem) {
68
+ this.resetInvalidIndication();
69
+ this.#errorItem = undefined;
70
+ }
71
+ newMappingItem.remove();
72
+ this.setCustomValidity('');
73
+ e.stopPropagation();
74
+ });
75
+ }, 0);
76
+ return newMappingItem;
77
+ }
78
+
79
+ get items() {
80
+ return Array.from(this.mappingsContainerEle.querySelectorAll('descope-mapping-item'));
81
+ }
82
+
83
+ get value() {
84
+ return this.items.reduce((acc, item) => {
85
+ if (!item.value) {
86
+ return acc;
87
+ }
88
+
89
+ return [...acc, item.value];
90
+ }, []);
91
+ }
92
+
93
+ set value(mappings) {
94
+ if (!this.isValidDataType(mappings)) {
95
+ // eslint-disable-next-line no-console
96
+ console.error(
97
+ 'received invalid value to set - should be an array of objects with one key-value pair'
98
+ );
99
+ return;
100
+ }
101
+
102
+ const currentItems = this.items;
103
+
104
+ // Remove extra mapping items we don't need
105
+ if (currentItems.length > mappings.length) {
106
+ for (let i = mappings.length; i < currentItems.length; i++) {
107
+ this.mappingsContainerEle.removeChild(currentItems[i]);
108
+ }
109
+ }
110
+
111
+ // Add or update items
112
+ mappings.forEach((mapping, index) => {
113
+ const mappingItem = currentItems[index];
114
+ if (mappingItem) {
115
+ // Set existing item value
116
+ mappingItem.value = mapping;
117
+ } else {
118
+ // Add new item
119
+ const newMappingItem = this.addNewMappingItem();
120
+ // Setting the new item value needs to be done with the timeout,
121
+ // otherwise the value is not set correctly
122
+ setTimeout(() => {
123
+ newMappingItem.value = mapping;
124
+ }, 0);
125
+ }
126
+ });
127
+ }
128
+
129
+ constructor() {
130
+ super();
131
+
132
+ this.innerHTML = `
133
+ <div class="labels-container" part="labels"></div>
134
+ <div class="mappings-container"></div>
135
+ <div class="button-container"></div>
136
+ `;
137
+
138
+ this.labelsEle = this.querySelector('.labels-container');
139
+ this.mappingsContainerEle = this.querySelector('.mappings-container');
140
+ this.buttonContainer = this.querySelector('.button-container');
141
+ }
142
+
143
+ initLabels() {
144
+ this.labelsEle.innerHTML = `
145
+ <descope-text variant="body2" part="value-label">${this.labelValue}</descope-text>
146
+ <descope-text variant="body2" part="attr-label">${this.labelAttr}</descope-text>
147
+ `;
148
+ }
149
+
150
+ initAddButton() {
151
+ this.buttonContainer.innerHTML = `
152
+ <descope-button variant="link" mode="primary" disabled="${this.isDisabled}">
153
+ <vaadin-icon icon="vaadin:plus"></vaadin-icon>
154
+ ${this.buttonLabel}
155
+ </descope-button>
156
+ `;
157
+ const button = this.querySelector('descope-button');
158
+ button.onclick = () => {
159
+ this.addNewMappingItem();
160
+ };
161
+ forwardAttrs(this, button, {
162
+ includeAttrs: ['disabled'],
163
+ });
164
+ }
165
+
166
+ init() {
167
+ // This event listener needs to be placed before the super.init() call
168
+ this.addEventListener('focus', (e) => {
169
+ // we want to ignore focus events we are dispatching
170
+ if (e.isTrusted) {
171
+ const focusedElement =
172
+ this.#errorItem || this.items[0] || this.querySelector('descope-button');
173
+ focusedElement.focus();
174
+ }
175
+ });
176
+
177
+ super.init?.();
178
+ this.initLabels();
179
+ this.initAddButton();
180
+
181
+ // This event listener is responsible for removing the invalid attribute
182
+ // from the internal once the invalid item turns valid
183
+ this.addEventListener('input', () => {
184
+ const isErrorItemMounted = this.mappingsContainerEle.contains(this.#errorItem);
185
+ if (isErrorItemMounted && this.#errorItem?.checkValidity()) {
186
+ // Item has changed, it was invalid before and now it's valid
187
+ this.resetInvalidIndication();
188
+ this.#errorItem.removeAttribute('invalid');
189
+ this.#errorItem = undefined;
190
+ }
191
+ });
192
+ }
193
+
194
+ resetInvalidIndication() {
195
+ this.removeAttribute('invalid');
196
+ }
197
+
198
+ getValidity() {
199
+ const errorItem = this.items.find((item) => !item.checkValidity());
200
+ if (errorItem) {
201
+ return errorItem.validity;
202
+ }
203
+
204
+ return {};
205
+ }
206
+
207
+ #handleInvalidMappings(isInvalid) {
208
+ if (isInvalid) {
209
+ this.#errorItem = this.items.find((item) => !item.checkValidity());
210
+ this.#errorItem?.reportValidity();
211
+ this.#errorItem?.setAttribute('invalid', 'true');
212
+ }
213
+ }
214
+
215
+ attributeChangedCallback(attrName, oldValue, newValue) {
216
+ super.attributeChangedCallback?.(attrName, oldValue, newValue);
217
+ if (attrName === 'label-value' || attrName === 'label-attr') {
218
+ this.initLabels();
219
+ }
220
+ if (attrName === 'button-label') {
221
+ this.initAddButton();
222
+ }
223
+ if (attrName === 'invalid') {
224
+ this.#handleInvalidMappings(newValue === 'true');
225
+ }
226
+ if (attrName === 'readonly') {
227
+ this.toggleAttribute('inert', newValue === 'true');
228
+ }
229
+ }
230
+ }
231
+
232
+ export default MappingsFieldInternal;
@@ -0,0 +1,3 @@
1
+ import MappingsFieldInternal, { componentName } from './MappingsFieldInternal';
2
+
3
+ customElements.define(componentName, MappingsFieldInternal);
@@ -0,0 +1,14 @@
1
+ import '@vaadin/custom-field';
2
+ import '@vaadin/icon';
3
+ import '@vaadin/icons';
4
+ import { componentName, MappingsFieldClass } from './MappingsFieldClass';
5
+ import '../../descope-text';
6
+ import '../../descope-button';
7
+ import '../../descope-text-field';
8
+ import '../../descope-combo-box';
9
+ import './descope-mappings-field-internal';
10
+ import './descope-mapping-item';
11
+
12
+ customElements.define(componentName, MappingsFieldClass);
13
+
14
+ export { MappingsFieldClass };
package/src/index.cjs.js CHANGED
@@ -37,3 +37,4 @@ export { NotificationClass } from './components/descope-notification/Notificatio
37
37
  export { GridClass } from './components/descope-grid/GridClass';
38
38
  export { BadgeClass } from './components/descope-badge/BadgeClass';
39
39
  export { MultiSelectComboBoxClass } from './components/descope-multi-select-combo-box/MultiSelectComboBoxClass';
40
+ export { MappingsFieldClass } from './components/mapping-fields/descope-mappings-field/MappingsFieldClass';
package/src/index.d.ts CHANGED
@@ -42,6 +42,7 @@ export { ModalClass } from './components/descope-modal/ModalClass';
42
42
  export { NotificationClass } from './components/descope-notification/';
43
43
  export { BadgeClass } from './components/descope-badge/';
44
44
  export { MultiSelectComboBoxClass } from './components/descope-multi-select-combo-box/';
45
+ export { MappingsFieldClass } from './components/mapping-fields/descope-mappings-field/';
45
46
 
46
47
  export type Theme = {
47
48
  globals: {
package/src/index.js CHANGED
@@ -31,6 +31,7 @@ export * from './components/descope-multi-select-combo-box';
31
31
  export * from './components/descope-badge';
32
32
  export * from './components/descope-modal';
33
33
  export * from './components/descope-notification';
34
+ export * from './components/mapping-fields/descope-mappings-field';
34
35
 
35
36
  export {
36
37
  globalsThemeToStyle,
@@ -20,6 +20,14 @@ export const inputValidationMixin = (superclass) =>
20
20
 
21
21
  #internals;
22
22
 
23
+ get internals() {
24
+ return this.#internals;
25
+ }
26
+
27
+ set internals(value) {
28
+ this.#internals = value;
29
+ }
30
+
23
31
  constructor() {
24
32
  super();
25
33
 
@@ -38,7 +38,10 @@ const proxyInputMixin =
38
38
  ({
39
39
  proxyProps = [],
40
40
  // allows us to set the event that should trigger validation
41
+ // it can be either a string or an array of strings (for multiple events)
41
42
  inputEvent = 'input',
43
+ // Proxies all validations from the parent component to the input element
44
+ proxyParentValidation = false,
42
45
  }) =>
43
46
  (superclass) =>
44
47
  class ProxyInputMixinClass extends inputValidationMixin(superclass) {
@@ -128,12 +131,16 @@ const proxyInputMixin =
128
131
  // on some cases the base element is not ready so the inputElement is empty
129
132
  // we are deferring this section to make sure the base element is ready
130
133
  setTimeout(() => {
131
- this.baseElement?.addEventListener(inputEvent, () => {
132
- if (!this.baseElement.checkValidity()) {
133
- this.#handleErrorMessage();
134
- } else {
135
- this.removeAttribute('invalid');
136
- }
134
+ const validationEvents = Array.isArray(inputEvent) ? inputEvent : [inputEvent];
135
+
136
+ validationEvents.forEach((e) => {
137
+ this.baseElement?.addEventListener(e, () => {
138
+ if (!this.baseElement.checkValidity()) {
139
+ this.#handleErrorMessage();
140
+ } else {
141
+ this.removeAttribute('invalid');
142
+ }
143
+ });
137
144
  });
138
145
 
139
146
  this.baseElement.addEventListener('change', () => {
@@ -156,6 +163,41 @@ const proxyInputMixin =
156
163
 
157
164
  forwardAttrs(this, this.inputElement, { includeAttrs: ['inputmode'] });
158
165
  });
166
+
167
+ if (proxyParentValidation) {
168
+ // All functions called on the inputElement internals will be applied to the parent
169
+ // component internals as well. As a result, there's no need to add outer mechanisms
170
+ // to update the parent component's validity state based on the input elements validity.
171
+ const inputElementInternals = this.inputElement.internals;
172
+ const parentThis = this;
173
+ this.inputElement.internals = new Proxy(inputElementInternals, {
174
+ get: (target, prop) => {
175
+ if (typeof target[prop] === 'function' && prop === 'setValidity') {
176
+ return (...args) => {
177
+ // If we're calling setValidity with 3 args, then the validationTarget
178
+ // needs to be swapped to be the inputElement
179
+ if (args.length === 3) {
180
+ const newArgs = args.slice(0, args.length - 1);
181
+ newArgs.push(parentThis.inputElement);
182
+ parentThis.internals[prop](...newArgs);
183
+ } else {
184
+ parentThis.internals[prop](...args);
185
+ }
186
+ return target[prop](...args);
187
+ };
188
+ }
189
+
190
+ if (typeof target[prop] === 'function') {
191
+ return (...args) => {
192
+ parentThis.internals[prop](...args);
193
+ return target[prop](...args);
194
+ };
195
+ }
196
+
197
+ return target[prop];
198
+ },
199
+ });
200
+ }
159
201
  }
160
202
  };
161
203
 
@@ -30,6 +30,7 @@ import * as grid from './grid';
30
30
  import * as notificationCard from './notificationCard';
31
31
  import * as multiSelectComboBox from './multiSelectComboBox';
32
32
  import * as badge from './badge';
33
+ import * as mappingsField from './mappingsField';
33
34
 
34
35
  const components = {
35
36
  button,
@@ -65,6 +66,7 @@ const components = {
65
66
  notificationCard,
66
67
  multiSelectComboBox,
67
68
  badge,
69
+ mappingsField,
68
70
  };
69
71
 
70
72
  const theme = Object.keys(components).reduce(
@@ -0,0 +1,25 @@
1
+ import globals from '../globals';
2
+ import { MappingsFieldClass } from '../../components/mapping-fields/descope-mappings-field/MappingsFieldClass';
3
+ import { getThemeRefs } from '../../helpers/themeHelpers';
4
+ import { refs } from './inputWrapper';
5
+
6
+ const globalRefs = getThemeRefs(globals);
7
+
8
+ const vars = MappingsFieldClass.cssVarList;
9
+
10
+ export const mappingsField = {
11
+ [vars.hostWidth]: refs.width,
12
+ [vars.hostDirection]: refs.direction,
13
+ [vars.fontSize]: refs.fontSize,
14
+ [vars.fontFamily]: refs.fontFamily,
15
+ [vars.separatorFontSize]: '14px',
16
+ [vars.labelTextColor]: refs.labelTextColor,
17
+ [vars.itemMarginBottom]: '1em',
18
+ // To be positioned correctly, the min width has to match the text field min width
19
+ [vars.valueLabelMinWidth]: refs.minWidth,
20
+ // To be positioned correctly, the min width has to match the combo box field min width
21
+ [vars.attrLabelMinWidth]: `calc(12em + 2 * ${globalRefs.border.xs})`,
22
+ };
23
+
24
+ export default mappingsField;
25
+ export { vars };