@descope/web-components-ui 1.0.66 → 1.0.68
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.map +1 -1
- package/dist/index.esm.js +481 -377
- package/dist/index.esm.js.map +1 -1
- package/dist/umd/135.js +1 -0
- package/dist/umd/descope-button-index-js.js +1 -1
- package/dist/umd/descope-checkbox-index-js.js +1 -1
- package/dist/umd/descope-combo-box-index-js.js +1 -1
- package/dist/umd/descope-container-index-js.js +1 -1
- package/dist/umd/descope-date-picker-index-js.js +1 -1
- package/dist/umd/descope-divider-index-js.js +1 -1
- package/dist/umd/descope-email-field-index-js.js +1 -1
- package/dist/umd/descope-link-index-js.js +1 -1
- package/dist/umd/descope-loader-linear-index-js.js +1 -1
- package/dist/umd/descope-loader-radial-index-js.js +1 -1
- package/dist/umd/descope-logo-index-js.js +1 -1
- package/dist/umd/descope-number-field-index-js.js +1 -1
- package/dist/umd/descope-passcode-descope-passcode-internal-index-js.js +1 -1
- package/dist/umd/descope-passcode-index-js.js +1 -1
- package/dist/umd/descope-password-field-index-js.js +1 -1
- package/dist/umd/descope-switch-toggle-index-js.js +1 -1
- package/dist/umd/descope-text-area-index-js.js +1 -1
- package/dist/umd/descope-text-field-index-js.js +1 -1
- package/dist/umd/descope-text-index-js.js +1 -1
- package/dist/umd/index.js +1 -1
- package/package.json +1 -1
- package/src/baseClasses/BaseInputClass.js +3 -2
- package/src/baseClasses/createBaseClass.js +29 -0
- package/src/components/descope-container/Container.js +17 -25
- package/src/components/descope-divider/Divider.js +32 -40
- package/src/components/descope-link/Link.js +8 -17
- package/src/components/descope-loader-linear/LoaderLinear.js +24 -29
- package/src/components/descope-loader-radial/LoaderRadial.js +18 -26
- package/src/components/descope-logo/Logo.js +4 -12
- package/src/components/descope-passcode/Passcode.js +4 -11
- package/src/components/descope-passcode/descope-passcode-internal/PasscodeInternal.js +41 -53
- package/src/components/descope-text/Text.js +4 -12
- package/src/helpers/index.js +2 -0
- package/src/helpers/mixinsHelpers.js +18 -0
- package/src/mixins/changeMixin.js +47 -0
- package/src/mixins/componentNameValidationMixin.js +1 -1
- package/src/mixins/createProxy.js +26 -28
- package/src/mixins/createStyleMixin/helpers.js +3 -3
- package/src/mixins/createStyleMixin/index.js +10 -9
- package/src/mixins/draggableMixin.js +1 -1
- package/src/mixins/focusMixin.js +130 -0
- package/src/mixins/hoverableMixin.js +14 -13
- package/src/mixins/index.js +3 -1
- package/src/mixins/{inputMixin.js → inputValidationMixin.js} +17 -58
- package/src/mixins/proxyInputMixin.js +50 -45
- package/dist/umd/860.js +0 -1
- package/src/baseClasses/DescopeBaseClass.js +0 -1
@@ -3,47 +3,42 @@ import {
|
|
3
3
|
draggableMixin,
|
4
4
|
componentNameValidationMixin
|
5
5
|
} from '../../mixins';
|
6
|
-
import {
|
6
|
+
import { createBaseClass } from '../../baseClasses/createBaseClass';
|
7
7
|
import { compose } from '../../helpers';
|
8
8
|
import { getComponentName } from '../../helpers/componentHelpers';
|
9
9
|
|
10
10
|
export const componentName = getComponentName('loader-linear');
|
11
11
|
|
12
|
-
class RawLoaderLinear extends
|
12
|
+
class RawLoaderLinear extends createBaseClass({ componentName, baseSelector: ':host > div' }) {
|
13
13
|
static get componentName() {
|
14
14
|
return componentName;
|
15
15
|
}
|
16
16
|
constructor() {
|
17
17
|
super();
|
18
|
-
const template = document.createElement('template');
|
19
|
-
template.innerHTML = `
|
20
|
-
<style>
|
21
|
-
@keyframes tilt {
|
22
|
-
0% { transform: translateX(0); }
|
23
|
-
50% { transform: translateX(400%); }
|
24
|
-
}
|
25
|
-
:host {
|
26
|
-
position: relative;
|
27
|
-
display: inline-block
|
28
|
-
}
|
29
|
-
div::after {
|
30
|
-
content: '';
|
31
|
-
animation-name: tilt;
|
32
|
-
position: absolute;
|
33
|
-
left: 0;
|
34
|
-
}
|
35
18
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
19
|
+
this.attachShadow({ mode: 'open' }).innerHTML = `
|
20
|
+
<style>
|
21
|
+
@keyframes tilt {
|
22
|
+
0% { transform: translateX(0); }
|
23
|
+
50% { transform: translateX(400%); }
|
24
|
+
}
|
25
|
+
:host {
|
26
|
+
position: relative;
|
27
|
+
display: inline-block
|
28
|
+
}
|
29
|
+
div::after {
|
30
|
+
content: '';
|
31
|
+
animation-name: tilt;
|
32
|
+
position: absolute;
|
33
|
+
left: 0;
|
34
|
+
}
|
42
35
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
36
|
+
:host > div {
|
37
|
+
width: 100%;
|
38
|
+
}
|
39
|
+
</style>
|
40
|
+
<div></div>
|
41
|
+
`;
|
47
42
|
}
|
48
43
|
}
|
49
44
|
|
@@ -3,40 +3,32 @@ import {
|
|
3
3
|
draggableMixin,
|
4
4
|
componentNameValidationMixin
|
5
5
|
} from '../../mixins';
|
6
|
-
import {
|
6
|
+
import { createBaseClass } from '../../baseClasses/createBaseClass';
|
7
7
|
import { compose } from '../../helpers';
|
8
8
|
import { getComponentName } from '../../helpers/componentHelpers';
|
9
9
|
|
10
10
|
export const componentName = getComponentName('loader-radial');
|
11
11
|
|
12
|
-
class RawLoaderRadial extends
|
13
|
-
static get componentName() {
|
14
|
-
return componentName;
|
15
|
-
}
|
12
|
+
class RawLoaderRadial extends createBaseClass({ componentName, baseSelector: ':host > div' }) {
|
16
13
|
constructor() {
|
17
14
|
super();
|
18
|
-
const template = document.createElement('template');
|
19
|
-
template.innerHTML = `
|
20
|
-
<style>
|
21
|
-
@keyframes spin {
|
22
|
-
0% { transform: rotate(0deg); }
|
23
|
-
100% { transform: rotate(360deg); }
|
24
|
-
}
|
25
|
-
:host {
|
26
|
-
position: relative;
|
27
|
-
display: inline-flex;
|
28
|
-
}
|
29
|
-
:host > div {
|
30
|
-
animation-name: spin;
|
31
|
-
}
|
32
|
-
</style>
|
33
|
-
<div></div>
|
34
|
-
`;
|
35
|
-
|
36
|
-
this.attachShadow({ mode: 'open' });
|
37
|
-
this.shadowRoot.appendChild(template.content.cloneNode(true));
|
38
15
|
|
39
|
-
this.
|
16
|
+
this.attachShadow({ mode: 'open' }).innerHTML = `
|
17
|
+
<style>
|
18
|
+
@keyframes spin {
|
19
|
+
0% { transform: rotate(0deg); }
|
20
|
+
100% { transform: rotate(360deg); }
|
21
|
+
}
|
22
|
+
:host {
|
23
|
+
position: relative;
|
24
|
+
display: inline-flex;
|
25
|
+
}
|
26
|
+
:host > div {
|
27
|
+
animation-name: spin;
|
28
|
+
}
|
29
|
+
</style>
|
30
|
+
<div></div>
|
31
|
+
`;
|
40
32
|
}
|
41
33
|
}
|
42
34
|
|
@@ -3,7 +3,7 @@ import {
|
|
3
3
|
draggableMixin,
|
4
4
|
componentNameValidationMixin
|
5
5
|
} from '../../mixins';
|
6
|
-
import {
|
6
|
+
import { createBaseClass } from '../../baseClasses/createBaseClass';
|
7
7
|
import { compose } from '../../helpers';
|
8
8
|
import { getComponentName } from '../../helpers/componentHelpers';
|
9
9
|
|
@@ -12,23 +12,15 @@ export const componentName = getComponentName('logo');
|
|
12
12
|
let style;
|
13
13
|
const getStyle = () => style;
|
14
14
|
|
15
|
-
class RawLogo extends
|
16
|
-
static get componentName() {
|
17
|
-
return componentName;
|
18
|
-
}
|
15
|
+
class RawLogo extends createBaseClass({ componentName, baseSelector: ':host > div' }) {
|
19
16
|
constructor() {
|
20
17
|
super();
|
21
|
-
|
22
|
-
|
18
|
+
|
19
|
+
this.attachShadow({ mode: 'open' }).innerHTML = `
|
23
20
|
<style>
|
24
21
|
${getStyle()}
|
25
22
|
</style>
|
26
23
|
<div></div>`;
|
27
|
-
|
28
|
-
this.attachShadow({ mode: 'open' });
|
29
|
-
this.shadowRoot.appendChild(template.content.cloneNode(true));
|
30
|
-
|
31
|
-
this.baseSelector = ':host > div';
|
32
24
|
}
|
33
25
|
}
|
34
26
|
|
@@ -38,21 +38,10 @@ const customMixin = (superclass) =>
|
|
38
38
|
|
39
39
|
this.proxyElement.appendChild(template.content.cloneNode(true));
|
40
40
|
|
41
|
-
// we want to control when the element is out of focus
|
42
|
-
// so the validations will be triggered blur event is dispatched from descope-passcode internal (and not every time focusing a digit)
|
43
|
-
this.proxyElement._setFocused = () => { };
|
44
|
-
|
45
41
|
this.inputElement = this.shadowRoot.querySelector(descopeInternalComponentName);
|
46
42
|
|
47
43
|
forwardAttrs(this.shadowRoot.host, this.inputElement, { includeAttrs: ['required', 'pattern'] })
|
48
44
|
|
49
|
-
// we want to trigger validation only when dispatching a blur event from the descope-passcode-internal
|
50
|
-
this.inputElement.addEventListener('blur', (e) => {
|
51
|
-
// we do not want native blur events, only the ones that we are sending
|
52
|
-
if (!e.isTrusted){
|
53
|
-
this.proxyElement.validate();
|
54
|
-
}
|
55
|
-
});
|
56
45
|
}
|
57
46
|
};
|
58
47
|
|
@@ -89,6 +78,10 @@ const Passcode = compose(
|
|
89
78
|
display: inline-block;
|
90
79
|
}
|
91
80
|
|
81
|
+
:host([readonly]) descope-passcode-internal > div {
|
82
|
+
pointer-events: none;
|
83
|
+
}
|
84
|
+
|
92
85
|
descope-passcode-internal {
|
93
86
|
-webkit-mask-image: none;
|
94
87
|
display: flex;
|
@@ -7,11 +7,10 @@ export const componentName = getComponentName('passcode-internal');
|
|
7
7
|
class PasscodeInternal extends BaseInputClass {
|
8
8
|
static get observedAttributes() {
|
9
9
|
return [
|
10
|
-
...BaseInputClass.observedAttributes,
|
10
|
+
...(BaseInputClass.observedAttributes || []),
|
11
11
|
'disabled',
|
12
12
|
'bordered',
|
13
13
|
'size',
|
14
|
-
'readonly'
|
15
14
|
];
|
16
15
|
}
|
17
16
|
|
@@ -19,10 +18,12 @@ class PasscodeInternal extends BaseInputClass {
|
|
19
18
|
return componentName;
|
20
19
|
}
|
21
20
|
|
21
|
+
#boundHandleInvalid = this.#handleInvalid.bind(this)
|
22
|
+
#boundHandleValid = this.#handleValid.bind(this)
|
23
|
+
#boundHandleBlur = this.#handleBlur.bind(this)
|
24
|
+
|
22
25
|
constructor() {
|
23
26
|
super();
|
24
|
-
const template = document.createElement('template');
|
25
|
-
|
26
27
|
const inputs = [...Array(this.digits).keys()].map((idx) => `
|
27
28
|
<descope-text-field
|
28
29
|
st-width="35px"
|
@@ -32,14 +33,12 @@ class PasscodeInternal extends BaseInputClass {
|
|
32
33
|
></descope-text-field>
|
33
34
|
`)
|
34
35
|
|
35
|
-
|
36
|
+
this.innerHTML = `
|
36
37
|
<div>
|
37
38
|
${inputs.join('')}
|
38
39
|
</div>
|
39
40
|
`;
|
40
41
|
|
41
|
-
this.appendChild(template.content.cloneNode(true));
|
42
|
-
|
43
42
|
this.baseSelector = ':host > div';
|
44
43
|
|
45
44
|
this.inputs = Array.from(this.querySelectorAll('descope-text-field'))
|
@@ -67,15 +66,13 @@ class PasscodeInternal extends BaseInputClass {
|
|
67
66
|
return `^$|^\\d{${this.digits},}$`
|
68
67
|
}
|
69
68
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
}
|
75
|
-
})
|
69
|
+
#handleInvalid() {
|
70
|
+
if (this.hasAttribute('invalid')) {
|
71
|
+
this.inputs.forEach(input => input.setAttribute('invalid', 'true'))
|
72
|
+
}
|
76
73
|
}
|
77
74
|
|
78
|
-
|
75
|
+
#handleValid() {
|
79
76
|
this.inputs.forEach(input => input.removeAttribute('invalid'))
|
80
77
|
}
|
81
78
|
|
@@ -91,17 +88,25 @@ class PasscodeInternal extends BaseInputClass {
|
|
91
88
|
}
|
92
89
|
};
|
93
90
|
|
94
|
-
|
95
|
-
this.inputs[0].focus()
|
91
|
+
onFocus(){
|
92
|
+
this.inputs[0].focus()
|
96
93
|
}
|
97
94
|
|
98
|
-
|
99
|
-
super.connectedCallback();
|
95
|
+
connectedCallback() {
|
96
|
+
super.connectedCallback?.();
|
100
97
|
|
101
98
|
this.initInputs()
|
102
99
|
|
103
|
-
this.addEventListener('invalid', this
|
104
|
-
this.addEventListener('valid', this
|
100
|
+
this.addEventListener('invalid', this.#boundHandleInvalid)
|
101
|
+
this.addEventListener('valid', this.#boundHandleValid)
|
102
|
+
this.addEventListener('blur', this.#boundHandleBlur)
|
103
|
+
}
|
104
|
+
|
105
|
+
disconnectedCallback() {
|
106
|
+
super.connectedCallback?.();
|
107
|
+
this.removeEventListener('invalid', this.#boundHandleInvalid)
|
108
|
+
this.removeEventListener('valid', this.#boundHandleValid)
|
109
|
+
this.removeEventListener('blur', this.#boundHandleBlur)
|
105
110
|
}
|
106
111
|
|
107
112
|
getInputIdx(inputEle) {
|
@@ -125,66 +130,49 @@ class PasscodeInternal extends BaseInputClass {
|
|
125
130
|
currentInput.value = charArr[i] ?? '';
|
126
131
|
|
127
132
|
const nextInput = this.getNextInput(currentInput);
|
133
|
+
|
128
134
|
if (nextInput === currentInput) break;
|
129
135
|
currentInput = nextInput;
|
130
136
|
}
|
131
137
|
|
132
|
-
|
138
|
+
focusElement(currentInput);
|
133
139
|
};
|
134
140
|
|
135
|
-
handleBlur() {
|
136
|
-
this
|
141
|
+
#handleBlur() {
|
142
|
+
this.#handleInvalid()
|
137
143
|
}
|
138
144
|
|
139
145
|
initInputs() {
|
140
146
|
this.inputs.forEach((input) => {
|
141
|
-
|
142
|
-
// in order to simulate blur on the input
|
143
|
-
// we are checking if focus on one of the digits happened immediately after blur on another digit
|
144
|
-
// if not, the component is no longer focused and we should simulate blur
|
145
|
-
input.addEventListener('blur', (e) => {
|
146
|
-
e.stopPropagation()
|
147
|
-
const timerId = setTimeout(() => {
|
148
|
-
this.dispatchBlur()
|
149
|
-
});
|
150
|
-
|
151
|
-
this.inputs.forEach((ele) =>
|
152
|
-
ele.addEventListener('focus', () => clearTimeout(timerId), { once: true })
|
153
|
-
);
|
154
|
-
})
|
155
|
-
|
156
147
|
input.oninput = (e) => {
|
157
|
-
e.stopPropagation()
|
158
148
|
const charArr = getSanitizedCharacters(input.value);
|
159
149
|
|
160
|
-
if (!charArr.length)
|
150
|
+
if (!charArr.length) {
|
151
|
+
// if we got an invalid value we want to clear the input
|
152
|
+
input.value = '';
|
153
|
+
if (e.data === null) {
|
154
|
+
// if the user deleted the char, we want to focus the prev digit
|
155
|
+
focusElement(this.getPrevInput(input));
|
156
|
+
}
|
157
|
+
}
|
161
158
|
else this.fillDigits(charArr, input);
|
162
|
-
|
163
|
-
this.dispatchInput()
|
164
159
|
};
|
165
160
|
|
166
161
|
input.onkeydown = ({ key }) => {
|
162
|
+
// when user deletes a digit, we want to focus the previous digit
|
167
163
|
if (key === 'Backspace') {
|
168
|
-
|
169
|
-
|
170
|
-
// if the user deleted the digit we want to focus the previous digit
|
171
|
-
const prevInput = this.getPrevInput(input)
|
172
|
-
|
173
|
-
!prevInput.hasAttribute('focused') && setTimeout(() => {
|
174
|
-
focusElement(prevInput);
|
164
|
+
setTimeout(() => {
|
165
|
+
focusElement(this.getPrevInput(input));
|
175
166
|
});
|
176
|
-
|
177
|
-
this.dispatchInput()
|
178
167
|
} else if (key.match(/^(\d)$/g)) { // if input is a digit
|
179
168
|
input.value = ''; // we are clearing the previous value so we can override it with the new value
|
180
169
|
}
|
181
|
-
|
182
170
|
};
|
183
171
|
})
|
184
172
|
}
|
185
173
|
|
186
174
|
attributeChangedCallback(attrName, oldValue, newValue) {
|
187
|
-
super.attributeChangedCallback(attrName, oldValue, newValue)
|
175
|
+
super.attributeChangedCallback?.(attrName, oldValue, newValue)
|
188
176
|
|
189
177
|
if (oldValue !== newValue) {
|
190
178
|
if (PasscodeInternal.observedAttributes.includes(attrName) && !BaseInputClass.observedAttributes.includes(attrName)) {
|
@@ -3,20 +3,17 @@ import {
|
|
3
3
|
draggableMixin,
|
4
4
|
componentNameValidationMixin
|
5
5
|
} from '../../mixins';
|
6
|
-
import {
|
6
|
+
import { createBaseClass } from '../../baseClasses/createBaseClass';
|
7
7
|
import { compose } from '../../helpers';
|
8
8
|
import { getComponentName } from '../../helpers/componentHelpers';
|
9
9
|
|
10
10
|
export const componentName = getComponentName('text');
|
11
11
|
|
12
|
-
class RawText extends
|
13
|
-
static get componentName() {
|
14
|
-
return componentName;
|
15
|
-
}
|
12
|
+
class RawText extends createBaseClass({ componentName, baseSelector: ':host > slot' }) {
|
16
13
|
constructor() {
|
17
14
|
super();
|
18
|
-
|
19
|
-
|
15
|
+
|
16
|
+
this.attachShadow({ mode: 'open' }).innerHTML = `
|
20
17
|
<style>
|
21
18
|
:host {
|
22
19
|
display: inline-block;
|
@@ -28,11 +25,6 @@ class RawText extends DescopeBaseClass {
|
|
28
25
|
</style>
|
29
26
|
<slot></slot>
|
30
27
|
`;
|
31
|
-
|
32
|
-
this.attachShadow({ mode: 'open' });
|
33
|
-
this.shadowRoot.appendChild(template.content.cloneNode(true));
|
34
|
-
|
35
|
-
this.baseSelector = ':host > slot';
|
36
28
|
}
|
37
29
|
}
|
38
30
|
|
package/src/helpers/index.js
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
// move create event to here
|
2
|
+
|
3
|
+
// usage example:
|
4
|
+
// #dispatchSomething = createDispatchEvent.bind(this, 'something')
|
5
|
+
export function createDispatchEvent(eventName) {
|
6
|
+
this[`on${eventName}`]?.(); // in case we got an event callback as property
|
7
|
+
this.dispatchEvent(new Event(eventName));
|
8
|
+
}
|
9
|
+
|
10
|
+
// usage example:
|
11
|
+
// #removeChangeListener = createEventListener.call(this,'change', this.onChange)
|
12
|
+
export function createEventListener(event, callback) {
|
13
|
+
const boundCallback = callback.bind(this);
|
14
|
+
|
15
|
+
this.addEventListener(event, boundCallback);
|
16
|
+
|
17
|
+
return () => this.removeEventListener(event, boundCallback)
|
18
|
+
}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
import { createDispatchEvent } from "../helpers/mixinsHelpers";
|
2
|
+
|
3
|
+
export const changeMixin = (superclass) => class ChangeMixinClass extends superclass {
|
4
|
+
|
5
|
+
#boundedHandleChange
|
6
|
+
#boundedHandleBlur
|
7
|
+
|
8
|
+
#removeChangeListener
|
9
|
+
#removeBlurListener
|
10
|
+
|
11
|
+
#dispatchChange = createDispatchEvent.bind(this, 'change')
|
12
|
+
|
13
|
+
constructor() {
|
14
|
+
super();
|
15
|
+
|
16
|
+
this.#boundedHandleChange = this.#handleChange.bind(this);
|
17
|
+
this.#boundedHandleBlur = this.#handleBlur.bind(this);
|
18
|
+
}
|
19
|
+
|
20
|
+
#handleChange(e) {
|
21
|
+
// we want to listen only to browser events
|
22
|
+
// and not to events we are dispatching
|
23
|
+
if (e.isTrusted) {
|
24
|
+
// we want to control the change events that dispatched by the component
|
25
|
+
// so we are stopping propagation and handling it in handleBlur
|
26
|
+
e.stopPropagation()
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
#handleBlur() {
|
31
|
+
// on blur, we want to dispatch a change event
|
32
|
+
this.#dispatchChange()
|
33
|
+
}
|
34
|
+
|
35
|
+
connectedCallback() {
|
36
|
+
super.connectedCallback?.();
|
37
|
+
|
38
|
+
this.#removeChangeListener = addEventListener.bind()
|
39
|
+
this.addEventListener('change', this.#boundedHandleChange, true)
|
40
|
+
this.addEventListener('blur', this.#boundedHandleBlur)
|
41
|
+
}
|
42
|
+
|
43
|
+
disconnectedCallback() {
|
44
|
+
this.removeEventListener('change', this.#boundedHandleChange)
|
45
|
+
this.removeEventListener('blur', this.#boundedHandleBlur)
|
46
|
+
}
|
47
|
+
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
export const componentNameValidationMixin = (superclass) =>
|
2
|
-
class
|
2
|
+
class ComponentNameValidationMixinClass extends superclass {
|
3
3
|
#checkComponentName() {
|
4
4
|
const currentComponentName = this.shadowRoot.host.tagName.toLowerCase();
|
5
5
|
|
@@ -1,7 +1,6 @@
|
|
1
|
-
import {
|
2
|
-
import {
|
1
|
+
import { createBaseClass } from '../baseClasses/createBaseClass';
|
2
|
+
import { isFunction } from '../helpers';
|
3
3
|
import { forwardProps, syncAttrs } from '../helpers/componentHelpers';
|
4
|
-
import { hoverableMixin } from './hoverableMixin';
|
5
4
|
|
6
5
|
export const createProxy = ({
|
7
6
|
componentName,
|
@@ -20,38 +19,39 @@ export const createProxy = ({
|
|
20
19
|
</${wrappedEleName}>
|
21
20
|
`;
|
22
21
|
|
23
|
-
class
|
24
|
-
static get componentName() {
|
25
|
-
return componentName;
|
26
|
-
}
|
27
|
-
|
22
|
+
class ProxyClass extends createBaseClass({ componentName, baseSelector: wrappedEleName }) {
|
28
23
|
constructor() {
|
29
24
|
super().attachShadow({ mode: 'open' }).innerHTML = template;
|
30
25
|
this.hostElement = this.shadowRoot.host;
|
31
|
-
this.baseSelector = wrappedEleName;
|
32
26
|
this.shadowRoot.getElementById('create-proxy').innerHTML =
|
33
|
-
|
27
|
+
isFunction(style) ? style() : style;
|
28
|
+
}
|
29
|
+
|
30
|
+
#boundOnFocus = this.#onFocus.bind(this);
|
31
|
+
|
32
|
+
// we want to focus on the proxy element when focusing our WCP
|
33
|
+
#onFocus() {
|
34
|
+
this.proxyElement.focus();
|
34
35
|
}
|
35
36
|
|
37
|
+
focus = this.#onFocus
|
38
|
+
|
36
39
|
connectedCallback() {
|
37
40
|
if (this.shadowRoot.isConnected) {
|
38
41
|
this.proxyElement = this.shadowRoot.querySelector(wrappedEleName);
|
39
42
|
|
43
|
+
this.addEventListener('focus', this.#boundOnFocus);
|
44
|
+
|
40
45
|
// this is needed for components that uses props, such as combo box
|
41
46
|
forwardProps(this.hostElement, this.proxyElement, includeForwardProps)
|
42
47
|
|
43
|
-
this.setAttribute('tabindex', '0');
|
44
|
-
|
45
|
-
// we want to focus on the proxy element when focusing our WC
|
46
|
-
this.addEventListener('focus', () => {
|
47
|
-
this.proxyElement.focus();
|
48
|
-
});
|
49
|
-
|
50
48
|
// `onkeydown` is set on `proxyElement` support proper tab-index navigation
|
51
49
|
// this support is needed since both proxy host and element catch `focus`/`blur` event
|
52
|
-
// which causes faulty
|
50
|
+
// which causes faulty behavior.
|
51
|
+
// we need this to happen only when the proxy component is in the light DOM,
|
52
|
+
// otherwise it will focus the nested proxy element
|
53
53
|
this.proxyElement.onkeydown = (e) => {
|
54
|
-
if (e.shiftKey && e.keyCode === 9) {
|
54
|
+
if (e.shiftKey && e.keyCode === 9 && this.getRootNode() === document) {
|
55
55
|
this.removeAttribute('tabindex');
|
56
56
|
// We want to defer the action of setting the tab index back
|
57
57
|
// so it will happen after focusing the previous element
|
@@ -59,10 +59,6 @@ export const createProxy = ({
|
|
59
59
|
}
|
60
60
|
};
|
61
61
|
|
62
|
-
// sync events
|
63
|
-
this.addEventListener = (...args) =>
|
64
|
-
this.proxyElement.addEventListener(...args);
|
65
|
-
|
66
62
|
syncAttrs(this.proxyElement, this.hostElement, {
|
67
63
|
excludeAttrs: excludeAttrsSync,
|
68
64
|
includeAttrs: includeAttrsSync
|
@@ -70,16 +66,18 @@ export const createProxy = ({
|
|
70
66
|
}
|
71
67
|
}
|
72
68
|
|
73
|
-
disconnectedCallback() {
|
74
|
-
this.proxyElement.removeEventListener('mouseover', this.mouseoverCbRef);
|
75
|
-
}
|
76
|
-
|
77
69
|
attributeChangedCallback() {
|
78
70
|
if (!this.proxyElement) {
|
79
71
|
return;
|
80
72
|
}
|
81
73
|
}
|
74
|
+
|
75
|
+
disconnectedCallback() {
|
76
|
+
super.disconnectedCallback?.()
|
77
|
+
|
78
|
+
this.removeEventListener('focus', this.#boundOnFocus);
|
79
|
+
}
|
82
80
|
}
|
83
81
|
|
84
|
-
return
|
82
|
+
return ProxyClass;
|
85
83
|
};
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { kebabCase } from '../../helpers';
|
1
|
+
import { isFunction, kebabCase } from '../../helpers';
|
2
2
|
import { getCssVarName } from '../../helpers/componentHelpers';
|
3
3
|
|
4
4
|
const createCssVarFallback = (first, ...rest) =>
|
@@ -8,7 +8,7 @@ const createCssSelector = (
|
|
8
8
|
baseSelector = '',
|
9
9
|
relativeSelectorOrSelectorFn = ''
|
10
10
|
) =>
|
11
|
-
|
11
|
+
isFunction(relativeSelectorOrSelectorFn)
|
12
12
|
? relativeSelectorOrSelectorFn(baseSelector)
|
13
13
|
: `${baseSelector}${/^[A-Za-z]/.test(relativeSelectorOrSelectorFn)
|
14
14
|
? ` ${relativeSelectorOrSelectorFn}`
|
@@ -65,7 +65,7 @@ export const createStyle = (componentName, baseSelector, mappings) => {
|
|
65
65
|
({ selector: relativeSelectorOrSelectorFn, property }) => {
|
66
66
|
style.add(
|
67
67
|
createCssSelector(baseSelector, relativeSelectorOrSelectorFn),
|
68
|
-
property,
|
68
|
+
isFunction(property) ? property() : property,
|
69
69
|
createCssVarFallback(cssVarName)
|
70
70
|
);
|
71
71
|
}
|
@@ -64,7 +64,7 @@ export const createStyleMixin =
|
|
64
64
|
this.#onComponentThemeChange()
|
65
65
|
}
|
66
66
|
|
67
|
-
#
|
67
|
+
#createOverridesStyle() {
|
68
68
|
this.#overrideStyleEle = document.createElement('style');
|
69
69
|
this.#overrideStyleEle.id = 'style-mixin-overrides';
|
70
70
|
|
@@ -74,7 +74,7 @@ export const createStyleMixin =
|
|
74
74
|
this.#rootElement.append(this.#overrideStyleEle);
|
75
75
|
}
|
76
76
|
|
77
|
-
#
|
77
|
+
#setAttrOverride(attrName, value) {
|
78
78
|
const style = this.#overrideStyleEle?.sheet?.cssRules[0].style;
|
79
79
|
if (!style) return;
|
80
80
|
|
@@ -87,10 +87,10 @@ export const createStyleMixin =
|
|
87
87
|
else style?.removeProperty(varName);
|
88
88
|
}
|
89
89
|
|
90
|
-
#
|
90
|
+
#updateOverridesStyle(attrs = []) {
|
91
91
|
for (const attr of attrs) {
|
92
92
|
if (this.#styleAttributes.includes(attr)) {
|
93
|
-
this.#
|
93
|
+
this.#setAttrOverride(attr, this.getAttribute(attr));
|
94
94
|
}
|
95
95
|
}
|
96
96
|
|
@@ -98,7 +98,7 @@ export const createStyleMixin =
|
|
98
98
|
this.#overrideStyleEle.innerHTML = this.#overrideStyleEle?.sheet?.cssRules[0].cssText
|
99
99
|
}
|
100
100
|
|
101
|
-
#
|
101
|
+
#createMappingStyle() {
|
102
102
|
const themeStyle = document.createElement('style');
|
103
103
|
themeStyle.id = 'style-mixin-mappings'
|
104
104
|
themeStyle.innerHTML = createStyle(
|
@@ -119,13 +119,14 @@ export const createStyleMixin =
|
|
119
119
|
|
120
120
|
this.#addClassName(superclass.componentName)
|
121
121
|
|
122
|
-
|
122
|
+
// TODO: we should do everything we can on the constructor
|
123
|
+
// when dragging & dropping these styles are created over & over
|
124
|
+
this.#createMappingStyle();
|
123
125
|
this.#createComponentTheme();
|
124
|
-
this.#
|
126
|
+
this.#createOverridesStyle();
|
125
127
|
|
126
128
|
// this is instead attributeChangedCallback because we cannot use static methods in this case
|
127
|
-
observeAttributes(this, this.#
|
128
|
-
|
129
|
+
observeAttributes(this, this.#updateOverridesStyle.bind(this), {})
|
129
130
|
}
|
130
131
|
}
|
131
132
|
|