@descope/web-components-ui 1.0.279 → 1.0.280
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/cjs/index.cjs.js +1123 -890
- package/dist/cjs/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.esm.js +1581 -964
- package/dist/index.esm.js.map +1 -1
- package/dist/umd/1000.js +1 -1
- package/dist/umd/1438.js +2 -2
- package/dist/umd/{9558.js → 1621.js} +117 -117
- package/dist/umd/2066.js +1 -1
- package/dist/umd/3280.js +197 -0
- package/dist/umd/3280.js.LICENSE.txt +29 -0
- package/dist/umd/{6542.js → 3951.js} +6 -6
- package/dist/umd/{6542.js.LICENSE.txt → 3951.js.LICENSE.txt} +0 -6
- package/dist/umd/422.js +1 -1
- package/dist/umd/5806.js +1 -1
- package/dist/umd/6770.js +1 -1
- package/dist/umd/6977.js +2 -0
- package/dist/umd/6977.js.LICENSE.txt +5 -0
- package/dist/umd/7056.js +1 -1
- package/dist/umd/7531.js +2 -2
- package/dist/umd/7583.js +2 -2
- package/dist/umd/8725.js +1 -1
- package/dist/umd/9092.js +2 -2
- package/dist/umd/9437.js +1 -1
- package/dist/umd/descope-combo-box-index-js.js +1 -1
- package/dist/umd/descope-notification-descope-notification-card-index-js.js +1 -1
- package/dist/umd/descope-notification-index-js.js +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/mapping-fields-descope-mappings-field-descope-mapping-item-index-js.js +1 -0
- package/dist/umd/mapping-fields-descope-mappings-field-descope-mappings-field-internal-index-js.js +1 -0
- package/dist/umd/mapping-fields-descope-mappings-field-index-js.js +1 -0
- package/package.json +4 -1
- package/src/components/descope-combo-box/ComboBoxClass.js +4 -0
- package/src/components/mapping-fields/descope-mappings-field/MappingsFieldClass.js +159 -0
- package/src/components/mapping-fields/descope-mappings-field/descope-mapping-item/MappingItem.js +158 -0
- package/src/components/mapping-fields/descope-mappings-field/descope-mapping-item/index.js +3 -0
- package/src/components/mapping-fields/descope-mappings-field/descope-mappings-field-internal/MappingsFieldInternal.js +232 -0
- package/src/components/mapping-fields/descope-mappings-field/descope-mappings-field-internal/index.js +3 -0
- package/src/components/mapping-fields/descope-mappings-field/index.js +14 -0
- package/src/index.cjs.js +1 -0
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/mixins/inputValidationMixin.js +8 -0
- package/src/mixins/proxyInputMixin.js +48 -6
- package/src/theme/components/index.js +2 -0
- package/src/theme/components/mappingsField.js +25 -0
- /package/dist/umd/{9558.js.LICENSE.txt → 1621.js.LICENSE.txt} +0 -0
@@ -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,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,
|
@@ -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
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
this.
|
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 };
|
File without changes
|