@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.
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