@descope/web-components-ui 1.0.312 → 1.0.314
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 +209 -29
- package/dist/cjs/index.cjs.js.map +1 -1
- package/dist/index.esm.js +231 -63
- package/dist/index.esm.js.map +1 -1
- package/dist/umd/4978.js +1 -1
- package/dist/umd/DescopeDev.js +1 -1
- package/dist/umd/descope-divider-index-js.js +1 -1
- package/dist/umd/descope-enriched-text-index-js.js +1 -1
- package/dist/umd/descope-link-index-js.js +1 -1
- package/dist/umd/descope-new-password-descope-new-password-internal-index-js.js +1 -1
- package/dist/umd/descope-new-password-index-js.js +1 -1
- package/dist/umd/descope-password-index-js.js +1 -1
- package/dist/umd/descope-text-index-js.js +1 -1
- package/dist/umd/descope-user-attribute-index-js.js +1 -1
- package/dist/umd/descope-user-auth-method-index-js.js +1 -1
- package/dist/umd/mapping-fields-descope-mappings-field-index-js.js +1 -1
- package/dist/umd/mapping-fields-descope-saml-group-mappings-index-js.js +1 -1
- package/package.json +1 -1
- package/src/components/descope-enriched-text/EnrichedTextClass.js +1 -0
- package/src/components/descope-link/LinkClass.js +1 -0
- package/src/components/descope-new-password/NewPasswordClass.js +27 -1
- package/src/components/descope-new-password/descope-new-password-internal/NewPasswordInternal.js +18 -30
- package/src/components/descope-password/PasswordClass.js +92 -15
- package/src/components/descope-password/helpers.js +62 -0
- package/src/components/descope-password/passwordDraggableMixin.js +16 -11
- package/src/components/descope-text/TextClass.js +1 -0
- package/src/mixins/inputValidationMixin.js +12 -1
@@ -6,16 +6,86 @@ import {
|
|
6
6
|
componentNameValidationMixin,
|
7
7
|
} from '../../mixins';
|
8
8
|
import { compose } from '../../helpers';
|
9
|
-
import { getComponentName } from '../../helpers/componentHelpers';
|
9
|
+
import { getComponentName, syncAttrs } from '../../helpers/componentHelpers';
|
10
10
|
import passwordDraggableMixin from './passwordDraggableMixin';
|
11
11
|
import {
|
12
12
|
resetInputLabelPosition,
|
13
13
|
resetInputCursor,
|
14
14
|
useHostExternalPadding,
|
15
15
|
} from '../../helpers/themeHelpers/resetHelpers';
|
16
|
+
import {
|
17
|
+
applyExternalInputStyles,
|
18
|
+
createExternalInputEle,
|
19
|
+
createExternalInputSlot,
|
20
|
+
} from './helpers';
|
16
21
|
|
17
22
|
export const componentName = getComponentName('password');
|
18
23
|
|
24
|
+
const customMixin = (superclass) =>
|
25
|
+
class PasswordFieldMixinClass extends superclass {
|
26
|
+
init() {
|
27
|
+
super.init?.();
|
28
|
+
|
29
|
+
// reset vaadin's checkValidity
|
30
|
+
this.baseElement.checkValidity = () => {};
|
31
|
+
// set safety attribute `external-input`
|
32
|
+
this.setAttribute('external-input', 'true');
|
33
|
+
|
34
|
+
// use original input element as reference
|
35
|
+
const origInput = this.baseElement.querySelector('input');
|
36
|
+
|
37
|
+
// create external slot
|
38
|
+
const externalInputSlot = createExternalInputSlot('external-input', 'suffix');
|
39
|
+
// append external slot to base element
|
40
|
+
this.baseElement.appendChild(externalInputSlot);
|
41
|
+
|
42
|
+
// create external input
|
43
|
+
const externalInput = createExternalInputEle('external-input', this.getAutocompleteType());
|
44
|
+
|
45
|
+
// apply original input's styles to external input
|
46
|
+
setTimeout(() => {
|
47
|
+
applyExternalInputStyles(origInput, externalInput);
|
48
|
+
});
|
49
|
+
|
50
|
+
// set external input events
|
51
|
+
this.handleExternalInputEvents(externalInput);
|
52
|
+
|
53
|
+
// sync input stateful attributes: `type` (for visibility state change) and `readonly`
|
54
|
+
syncAttrs(origInput, externalInput, { includeAttrs: ['type', 'readonly'] });
|
55
|
+
|
56
|
+
origInput.addEventListener('focus', (e) => {
|
57
|
+
e.preventDefault();
|
58
|
+
if (e.isTrusted) {
|
59
|
+
externalInput.focus();
|
60
|
+
}
|
61
|
+
});
|
62
|
+
|
63
|
+
this.addEventListener('focus', (e) => {
|
64
|
+
e.preventDefault();
|
65
|
+
this.focus();
|
66
|
+
});
|
67
|
+
|
68
|
+
// append external input to component's DOM
|
69
|
+
this.appendChild(externalInput);
|
70
|
+
}
|
71
|
+
|
72
|
+
getAutocompleteType() {
|
73
|
+
return this.getAttribute('autocomplete') || 'current-password';
|
74
|
+
}
|
75
|
+
|
76
|
+
handleExternalInputEvents(inputEle) {
|
77
|
+
// sync value of insible input back to original input
|
78
|
+
inputEle.addEventListener('input', (e) => {
|
79
|
+
this.value = e.target.value;
|
80
|
+
});
|
81
|
+
|
82
|
+
// sync `focused` attribute on host when focusing on external input
|
83
|
+
inputEle.addEventListener('focus', () => {
|
84
|
+
this.setAttribute('focused', 'true');
|
85
|
+
});
|
86
|
+
}
|
87
|
+
};
|
88
|
+
|
19
89
|
const {
|
20
90
|
host,
|
21
91
|
inputField,
|
@@ -31,9 +101,9 @@ const {
|
|
31
101
|
host: { selector: () => ':host' },
|
32
102
|
inputField: { selector: '::part(input-field)' },
|
33
103
|
inputElement: { selector: '> input' },
|
34
|
-
inputElementPlaceholder: { selector: '
|
35
|
-
revealButtonContainer: { selector:
|
36
|
-
revealButtonIcon: { selector:
|
104
|
+
inputElementPlaceholder: { selector: () => ':host input:placeholder-shown' },
|
105
|
+
revealButtonContainer: { selector: '::part(reveal-button)' },
|
106
|
+
revealButtonIcon: { selector: '::part(reveal-button)::before' },
|
37
107
|
label: { selector: '::part(label)' },
|
38
108
|
requiredIndicator: { selector: '[required]::part(required-indicator)::after' },
|
39
109
|
helperText: { selector: '::part(helper-text)' },
|
@@ -72,8 +142,14 @@ export const PasswordClass = compose(
|
|
72
142
|
labelRequiredIndicator: { ...requiredIndicator, property: 'content' },
|
73
143
|
errorMessageTextColor: { ...errorMessage, property: 'color' },
|
74
144
|
|
75
|
-
|
76
|
-
|
145
|
+
inputPlaceholderTextColor: [
|
146
|
+
{ ...inputElementPlaceholder, property: 'color' },
|
147
|
+
{ selector: () => ':host ::slotted(input:placeholder-shown)', property: 'color' },
|
148
|
+
],
|
149
|
+
inputValueTextColor: [
|
150
|
+
{ ...inputElement, property: 'color' },
|
151
|
+
{ selector: () => ':host ::slotted(input)', property: 'color' },
|
152
|
+
],
|
77
153
|
|
78
154
|
revealButtonOffset: [
|
79
155
|
{ ...revealButtonContainer, property: 'margin-right' },
|
@@ -86,7 +162,8 @@ export const PasswordClass = compose(
|
|
86
162
|
draggableMixin,
|
87
163
|
proxyInputMixin({ proxyProps: ['value', 'selectionStart'] }),
|
88
164
|
componentNameValidationMixin,
|
89
|
-
passwordDraggableMixin
|
165
|
+
passwordDraggableMixin,
|
166
|
+
customMixin
|
90
167
|
)(
|
91
168
|
createProxy({
|
92
169
|
slots: ['', 'suffix'],
|
@@ -97,6 +174,7 @@ export const PasswordClass = compose(
|
|
97
174
|
max-width: 100%;
|
98
175
|
min-width: 10em;
|
99
176
|
box-sizing: border-box;
|
177
|
+
position: relative;
|
100
178
|
}
|
101
179
|
${useHostExternalPadding(PasswordClass.cssVarList)}
|
102
180
|
${resetInputCursor('vaadin-password-field')}
|
@@ -108,7 +186,9 @@ export const PasswordClass = compose(
|
|
108
186
|
padding: 0;
|
109
187
|
}
|
110
188
|
vaadin-password-field > input {
|
189
|
+
-webkit-mask-image: none;
|
111
190
|
box-sizing: border-box;
|
191
|
+
opacity: 1;
|
112
192
|
}
|
113
193
|
vaadin-password-field::part(input-field) {
|
114
194
|
box-sizing: border-box;
|
@@ -117,12 +197,11 @@ export const PasswordClass = compose(
|
|
117
197
|
vaadin-password-field[focus-ring]::part(input-field) {
|
118
198
|
box-shadow: none;
|
119
199
|
}
|
120
|
-
|
200
|
+
:host ::slotted(input) {
|
121
201
|
min-height: 0;
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
opacity: 1;
|
202
|
+
}
|
203
|
+
:host([readonly]) ::slotted(input:placeholder-shown) {
|
204
|
+
opacity: 0;
|
126
205
|
}
|
127
206
|
vaadin-password-field::before {
|
128
207
|
height: initial;
|
@@ -133,11 +212,9 @@ export const PasswordClass = compose(
|
|
133
212
|
vaadin-password-field-button {
|
134
213
|
cursor: pointer;
|
135
214
|
}
|
136
|
-
|
137
|
-
[readonly] vaadin-password-field-button {
|
215
|
+
:host([readonly]) vaadin-password-field-button {
|
138
216
|
pointer-events: none;
|
139
217
|
}
|
140
|
-
|
141
218
|
vaadin-password-field-button[focus-ring] {
|
142
219
|
box-shadow: 0 0 0 2px var(${PasswordClass.cssVarList.inputOutlineColor});
|
143
220
|
}
|
@@ -0,0 +1,62 @@
|
|
1
|
+
// since on load we can only sample the color of the placeholder,
|
2
|
+
// we need to temporarily populate the input in order to sample the value color
|
3
|
+
const getValueColor = (ele, computedStyle) => {
|
4
|
+
// eslint-disable-next-line no-param-reassign
|
5
|
+
ele.value = '_';
|
6
|
+
|
7
|
+
const valueColor = computedStyle.getPropertyValue('color');
|
8
|
+
|
9
|
+
// eslint-disable-next-line no-param-reassign
|
10
|
+
ele.value = '';
|
11
|
+
|
12
|
+
return valueColor;
|
13
|
+
};
|
14
|
+
|
15
|
+
export const createExternalInputSlot = (slotName, targetSlotName) => {
|
16
|
+
const slotEle = document.createElement('slot');
|
17
|
+
|
18
|
+
slotEle.setAttribute('name', slotName);
|
19
|
+
slotEle.setAttribute('slot', targetSlotName);
|
20
|
+
|
21
|
+
return slotEle;
|
22
|
+
};
|
23
|
+
|
24
|
+
export const createExternalInputEle = (targetSlotName, autocompleteType) => {
|
25
|
+
const inputEle = document.createElement('input');
|
26
|
+
|
27
|
+
inputEle.setAttribute('slot', targetSlotName);
|
28
|
+
inputEle.setAttribute('type', 'password');
|
29
|
+
inputEle.setAttribute('data-hidden-input', 'true');
|
30
|
+
inputEle.setAttribute('autocomplete', autocompleteType);
|
31
|
+
|
32
|
+
return inputEle;
|
33
|
+
};
|
34
|
+
|
35
|
+
export const applyExternalInputStyles = (sourceInputEle, targetInputEle) => {
|
36
|
+
const computedStyle = getComputedStyle(sourceInputEle);
|
37
|
+
const height = computedStyle.getPropertyValue('height');
|
38
|
+
const paddingLeft = computedStyle.getPropertyValue('padding-left');
|
39
|
+
const paddingRight = computedStyle.getPropertyValue('padding-right');
|
40
|
+
const fontSize = computedStyle.getPropertyValue('font-size');
|
41
|
+
const fontFamily = computedStyle.getPropertyValue('font-family');
|
42
|
+
const letterSpacing = computedStyle.getPropertyValue('letter-spacing');
|
43
|
+
const caretColor = computedStyle.getPropertyValue('caret-color');
|
44
|
+
const valueColor = getValueColor(sourceInputEle, computedStyle);
|
45
|
+
|
46
|
+
// set external input style (and lock it with `all: unset` and `!important` all around)
|
47
|
+
// eslint-disable-next-line no-param-reassign
|
48
|
+
targetInputEle.style = `
|
49
|
+
all: unset !important;
|
50
|
+
position: absolute !important;
|
51
|
+
width: calc(100% - 3em) !important;
|
52
|
+
background-color: transparent !important;
|
53
|
+
color: ${valueColor} !important;
|
54
|
+
height: ${height} !important;
|
55
|
+
left: ${paddingLeft} !important;
|
56
|
+
right: ${paddingRight} !important;
|
57
|
+
font-size: ${fontSize} !important;
|
58
|
+
font-family: ${fontFamily} !important;
|
59
|
+
letter-spacing: ${letterSpacing} !important;
|
60
|
+
caret-color: ${caretColor} !important;
|
61
|
+
`;
|
62
|
+
};
|
@@ -8,27 +8,32 @@ const passwordDraggableMixin = (superclass) =>
|
|
8
8
|
// there is an issue in Chrome that input field with type password cannot be D&D
|
9
9
|
// so in case the input is draggable & readonly, we are changing the input type to "text" before dragging
|
10
10
|
// and return the original type when done
|
11
|
-
|
11
|
+
super.init?.();
|
12
|
+
|
13
|
+
const ele = this.querySelector('input');
|
14
|
+
|
15
|
+
ele?.addEventListener('mousedown', (e) => {
|
12
16
|
if (this.isDraggable && this.isReadOnly) {
|
13
|
-
|
14
|
-
const prevType = inputEle.getAttribute('type');
|
17
|
+
ele.setAttribute('inert', 'true');
|
15
18
|
|
19
|
+
const inputEle = e.target;
|
20
|
+
const prevType = inputEle.getAttribute('type');
|
16
21
|
inputEle.setAttribute('type', 'text');
|
17
|
-
setTimeout(() =>
|
22
|
+
setTimeout(() => {
|
23
|
+
inputEle.focus();
|
24
|
+
});
|
18
25
|
|
19
26
|
const onComplete = (_) => {
|
20
27
|
inputEle.setAttribute('type', prevType);
|
21
|
-
|
22
|
-
|
23
|
-
|
28
|
+
ele.removeAttribute('inert');
|
29
|
+
this.removeEventListener('mouseup', onComplete);
|
30
|
+
this.removeEventListener('dragend', onComplete);
|
24
31
|
};
|
25
32
|
|
26
|
-
|
27
|
-
|
33
|
+
this.addEventListener('dragend', onComplete, { once: true });
|
34
|
+
this.addEventListener('mouseup', onComplete, { once: true });
|
28
35
|
}
|
29
36
|
});
|
30
|
-
|
31
|
-
super.init?.();
|
32
37
|
}
|
33
38
|
};
|
34
39
|
|
@@ -8,8 +8,13 @@ const errorAttributes = {
|
|
8
8
|
tooShort: 'data-errormessage-pattern-mismatch-too-short',
|
9
9
|
tooLong: 'data-errormessage-pattern-mismatch-too-long',
|
10
10
|
};
|
11
|
+
|
12
|
+
const validationTargetSymbol = Symbol('validationTarget');
|
13
|
+
|
11
14
|
export const inputValidationMixin = (superclass) =>
|
12
15
|
class InputValidationMixinClass extends superclass {
|
16
|
+
#validationTarget = validationTargetSymbol;
|
17
|
+
|
13
18
|
static get observedAttributes() {
|
14
19
|
return [...(superclass.observedAttributes || []), ...observedAttributes];
|
15
20
|
}
|
@@ -126,7 +131,13 @@ export const inputValidationMixin = (superclass) =>
|
|
126
131
|
}
|
127
132
|
|
128
133
|
get validationTarget() {
|
129
|
-
return this
|
134
|
+
return this.#validationTarget === validationTargetSymbol
|
135
|
+
? this.inputElement
|
136
|
+
: this.#validationTarget;
|
137
|
+
}
|
138
|
+
|
139
|
+
set validationTarget(val) {
|
140
|
+
this.#validationTarget = val;
|
130
141
|
}
|
131
142
|
|
132
143
|
setCustomValidity(errorMessage) {
|