@descope/web-components-ui 1.0.66 → 1.0.68

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. package/dist/cjs/index.cjs.js.map +1 -1
  2. package/dist/index.esm.js +481 -377
  3. package/dist/index.esm.js.map +1 -1
  4. package/dist/umd/135.js +1 -0
  5. package/dist/umd/descope-button-index-js.js +1 -1
  6. package/dist/umd/descope-checkbox-index-js.js +1 -1
  7. package/dist/umd/descope-combo-box-index-js.js +1 -1
  8. package/dist/umd/descope-container-index-js.js +1 -1
  9. package/dist/umd/descope-date-picker-index-js.js +1 -1
  10. package/dist/umd/descope-divider-index-js.js +1 -1
  11. package/dist/umd/descope-email-field-index-js.js +1 -1
  12. package/dist/umd/descope-link-index-js.js +1 -1
  13. package/dist/umd/descope-loader-linear-index-js.js +1 -1
  14. package/dist/umd/descope-loader-radial-index-js.js +1 -1
  15. package/dist/umd/descope-logo-index-js.js +1 -1
  16. package/dist/umd/descope-number-field-index-js.js +1 -1
  17. package/dist/umd/descope-passcode-descope-passcode-internal-index-js.js +1 -1
  18. package/dist/umd/descope-passcode-index-js.js +1 -1
  19. package/dist/umd/descope-password-field-index-js.js +1 -1
  20. package/dist/umd/descope-switch-toggle-index-js.js +1 -1
  21. package/dist/umd/descope-text-area-index-js.js +1 -1
  22. package/dist/umd/descope-text-field-index-js.js +1 -1
  23. package/dist/umd/descope-text-index-js.js +1 -1
  24. package/dist/umd/index.js +1 -1
  25. package/package.json +1 -1
  26. package/src/baseClasses/BaseInputClass.js +3 -2
  27. package/src/baseClasses/createBaseClass.js +29 -0
  28. package/src/components/descope-container/Container.js +17 -25
  29. package/src/components/descope-divider/Divider.js +32 -40
  30. package/src/components/descope-link/Link.js +8 -17
  31. package/src/components/descope-loader-linear/LoaderLinear.js +24 -29
  32. package/src/components/descope-loader-radial/LoaderRadial.js +18 -26
  33. package/src/components/descope-logo/Logo.js +4 -12
  34. package/src/components/descope-passcode/Passcode.js +4 -11
  35. package/src/components/descope-passcode/descope-passcode-internal/PasscodeInternal.js +41 -53
  36. package/src/components/descope-text/Text.js +4 -12
  37. package/src/helpers/index.js +2 -0
  38. package/src/helpers/mixinsHelpers.js +18 -0
  39. package/src/mixins/changeMixin.js +47 -0
  40. package/src/mixins/componentNameValidationMixin.js +1 -1
  41. package/src/mixins/createProxy.js +26 -28
  42. package/src/mixins/createStyleMixin/helpers.js +3 -3
  43. package/src/mixins/createStyleMixin/index.js +10 -9
  44. package/src/mixins/draggableMixin.js +1 -1
  45. package/src/mixins/focusMixin.js +130 -0
  46. package/src/mixins/hoverableMixin.js +14 -13
  47. package/src/mixins/index.js +3 -1
  48. package/src/mixins/{inputMixin.js → inputValidationMixin.js} +17 -58
  49. package/src/mixins/proxyInputMixin.js +50 -45
  50. package/dist/umd/860.js +0 -1
  51. package/src/baseClasses/DescopeBaseClass.js +0 -1
@@ -3,47 +3,42 @@ import {
3
3
  draggableMixin,
4
4
  componentNameValidationMixin
5
5
  } from '../../mixins';
6
- import { DescopeBaseClass } from '../../baseClasses/DescopeBaseClass';
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 DescopeBaseClass {
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
- :host > div {
37
- width: 100%;
38
- }
39
- </style>
40
- <div></div>
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
- this.attachShadow({ mode: 'open' });
44
- this.shadowRoot.appendChild(template.content.cloneNode(true));
45
-
46
- this.baseSelector = ':host > div';
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 { DescopeBaseClass } from '../../baseClasses/DescopeBaseClass';
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 DescopeBaseClass {
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.baseSelector = ':host > div';
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 { DescopeBaseClass } from '../../baseClasses/DescopeBaseClass';
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 DescopeBaseClass {
16
- static get componentName() {
17
- return componentName;
18
- }
15
+ class RawLogo extends createBaseClass({ componentName, baseSelector: ':host > div' }) {
19
16
  constructor() {
20
17
  super();
21
- const template = document.createElement('template');
22
- template.innerHTML = `
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
- template.innerHTML = `
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
- handleInputsInvalid() {
71
- setTimeout(() => {
72
- if (this.hasAttribute('invalid')) {
73
- this.inputs.forEach(input => input.setAttribute('invalid', 'true'))
74
- }
75
- })
69
+ #handleInvalid() {
70
+ if (this.hasAttribute('invalid')) {
71
+ this.inputs.forEach(input => input.setAttribute('invalid', 'true'))
72
+ }
76
73
  }
77
74
 
78
- handleInputsValid() {
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
- handleFocus() {
95
- this.inputs[0].focus();
91
+ onFocus(){
92
+ this.inputs[0].focus()
96
93
  }
97
94
 
98
- async connectedCallback() {
99
- super.connectedCallback();
95
+ connectedCallback() {
96
+ super.connectedCallback?.();
100
97
 
101
98
  this.initInputs()
102
99
 
103
- this.addEventListener('invalid', this.handleInputsInvalid)
104
- this.addEventListener('valid', this.handleInputsValid)
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
- !currentInput.hasAttribute('focused') && focusElement(currentInput);
138
+ focusElement(currentInput);
133
139
  };
134
140
 
135
- handleBlur() {
136
- this.handleInputsInvalid()
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) input.value = ''; // if we got an invalid value we want to clear the input
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
- input.value = '';
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 { DescopeBaseClass } from '../../baseClasses/DescopeBaseClass';
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 DescopeBaseClass {
13
- static get componentName() {
14
- return componentName;
15
- }
12
+ class RawText extends createBaseClass({ componentName, baseSelector: ':host > slot' }) {
16
13
  constructor() {
17
14
  super();
18
- const template = document.createElement('template');
19
- template.innerHTML = `
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
 
@@ -12,3 +12,5 @@ export const compose = (...fns) =>
12
12
  fns.reduceRight((res, fn) => fn(res), val);
13
13
 
14
14
  export const upperFirst = (str) => str.charAt(0).toUpperCase() + str.slice(1)
15
+
16
+ export const isFunction = (maybeFunc) => typeof maybeFunc === 'function'
@@ -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 DraggableMixinClass extends superclass {
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 { DescopeBaseClass } from '../baseClasses/DescopeBaseClass';
2
- import { compose } from '../helpers';
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 ProxyElement extends DescopeBaseClass {
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
- typeof style === 'function' ? style() : style;
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 behaviour.
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 compose(hoverableMixin())(ProxyElement);
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
- typeof relativeSelectorOrSelectorFn === 'function'
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
- #createAttrOverrideStyle() {
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
- #setAttrOverrideStyle(attrName, value) {
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
- #updateOverrideStyle(attrs = []) {
90
+ #updateOverridesStyle(attrs = []) {
91
91
  for (const attr of attrs) {
92
92
  if (this.#styleAttributes.includes(attr)) {
93
- this.#setAttrOverrideStyle(attr, this.getAttribute(attr));
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
- #createComponentStyle() {
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
- this.#createComponentStyle();
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.#createAttrOverrideStyle();
126
+ this.#createOverridesStyle();
125
127
 
126
128
  // this is instead attributeChangedCallback because we cannot use static methods in this case
127
- observeAttributes(this, this.#updateOverrideStyle.bind(this), {})
128
-
129
+ observeAttributes(this, this.#updateOverridesStyle.bind(this), {})
129
130
  }
130
131
  }
131
132