@descope/web-components-ui 1.0.67 → 1.0.69

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. package/dist/cjs/index.cjs.js.map +1 -1
  2. package/dist/index.esm.js +510 -395
  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-combo-box/ComboBox.js +18 -4
  29. package/src/components/descope-container/Container.js +17 -25
  30. package/src/components/descope-divider/Divider.js +32 -40
  31. package/src/components/descope-link/Link.js +8 -17
  32. package/src/components/descope-loader-linear/LoaderLinear.js +24 -29
  33. package/src/components/descope-loader-radial/LoaderRadial.js +18 -26
  34. package/src/components/descope-logo/Logo.js +4 -12
  35. package/src/components/descope-passcode/Passcode.js +4 -11
  36. package/src/components/descope-passcode/descope-passcode-internal/PasscodeInternal.js +41 -53
  37. package/src/components/descope-text/Text.js +4 -12
  38. package/src/helpers/index.js +2 -0
  39. package/src/helpers/mixinsHelpers.js +18 -0
  40. package/src/mixins/changeMixin.js +47 -0
  41. package/src/mixins/componentNameValidationMixin.js +1 -1
  42. package/src/mixins/createProxy.js +26 -28
  43. package/src/mixins/createStyleMixin/helpers.js +3 -3
  44. package/src/mixins/createStyleMixin/index.js +10 -9
  45. package/src/mixins/draggableMixin.js +1 -1
  46. package/src/mixins/focusMixin.js +130 -0
  47. package/src/mixins/hoverableMixin.js +14 -13
  48. package/src/mixins/index.js +3 -1
  49. package/src/mixins/{inputMixin.js → inputValidationMixin.js} +17 -58
  50. package/src/mixins/portalMixin.js +11 -7
  51. package/src/mixins/proxyInputMixin.js +50 -45
  52. package/src/theme/components/comboBox.js +2 -9
  53. package/dist/umd/860.js +0 -1
  54. package/src/baseClasses/DescopeBaseClass.js +0 -1
@@ -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
 
@@ -11,7 +11,7 @@ export const draggableMixin = (superclass) =>
11
11
  super();
12
12
 
13
13
  this.#styleEle = document.createElement('style');
14
- this.#styleEle.innerText = `${this.baseSelector} { cursor: inherit }`;
14
+ this.#styleEle.innerText = `* { cursor: inherit!important }`;
15
15
  }
16
16
 
17
17
  #handleDraggableStyle(isDraggable) {
@@ -0,0 +1,130 @@
1
+ import { upperFirst } from "../helpers";
2
+
3
+ const events = [
4
+ 'blur',
5
+ 'focus',
6
+ 'focusin',
7
+ 'focusout',
8
+ ]
9
+
10
+ export const focusMixin = (superclass) => class FocusMixinClass extends superclass {
11
+ #isFocused = false
12
+ #setFocusTimer
13
+
14
+ #boundedHandleFocus
15
+ #boundedHandleBlur
16
+ #boundedHandleFocusIn
17
+ #boundedHandleFocusOut
18
+
19
+ constructor() {
20
+ super();
21
+
22
+ for (const event of events) {
23
+ this[`dispatch${upperFirst(event)}`] = function () {
24
+ this.dispatchInputEvent(event)
25
+ }
26
+ }
27
+
28
+ this.#boundedHandleFocus = this.#handleFocus.bind(this);
29
+ this.#boundedHandleBlur = this.#handleBlur.bind(this);
30
+ this.#boundedHandleFocusIn = this.#handleFocusIn.bind(this);
31
+ this.#boundedHandleFocusOut = this.#handleFocusOut.bind(this);
32
+ }
33
+
34
+ #handleFocus(e) {
35
+ if (this.isReadOnly) {
36
+ e.stopPropagation()
37
+ return
38
+ }
39
+ // we want to listen only to browser events
40
+ // and not to events we are dispatching
41
+ if (e.isTrusted) { // TODO: check if this is needed, because Vaadin is also dispatching events
42
+ // we want to control the focus events that dispatched by the component
43
+ // so we are stopping propagation and handling it in setFocus
44
+ e.stopPropagation()
45
+ this.setFocus(true)
46
+
47
+ // if the focus event is on the root component (and not on the inner components)
48
+ // we want to notify the component and let it decide what to do with it
49
+ if (e.target === this) {
50
+ this.onFocus(e)
51
+ }
52
+ }
53
+ }
54
+
55
+ #handleFocusOut(e) {
56
+ // we want to listen only to browser events
57
+ // and not to events we are dispatching
58
+ if (e.isTrusted) {
59
+ // we want to control the focus events that dispatched by the component
60
+ // so we are stopping propagation and handling it in setFocus
61
+ e.stopPropagation()
62
+ }
63
+ }
64
+
65
+ #handleFocusIn(e) {
66
+ // we want to listen only to browser events
67
+ // and not to events we are dispatching
68
+ if (e.isTrusted) {
69
+ // we want to control the focus events that dispatched by the component
70
+ // so we are stopping propagation and handling it in setFocus
71
+ e.stopPropagation()
72
+ }
73
+ }
74
+
75
+ #handleBlur(e) {
76
+ if (e.isTrusted) {
77
+ e.stopPropagation()
78
+ this.setFocus(false)
79
+ }
80
+ }
81
+
82
+ get isReadOnly() {
83
+ return this.hasAttribute('readonly') && this.getAttribute('readonly') !== 'false'
84
+ }
85
+
86
+ // we want to debounce the calls to this fn
87
+ // so we can support input like components with multiple inputs inside
88
+ setFocus(isFocused) {
89
+ clearTimeout(this.#setFocusTimer)
90
+
91
+ this.#setFocusTimer = setTimeout(() => {
92
+ if (this.#isFocused !== isFocused) {
93
+ this.#isFocused = isFocused
94
+ if (isFocused) {
95
+ this.dispatchFocus();
96
+ this.dispatchFocusin();
97
+ }
98
+ else {
99
+ this.dispatchBlur()
100
+ this.dispatchFocusout();
101
+ }
102
+ }
103
+ })
104
+ }
105
+
106
+ onFocus() {
107
+ console.warn('onFocus', 'is not implemented')
108
+ }
109
+
110
+ dispatchInputEvent(eventName) {
111
+ this[`on${eventName}`]?.(); // in case we got an event callback as property
112
+ this.dispatchEvent(new InputEvent(eventName));
113
+ }
114
+
115
+ connectedCallback() {
116
+ super.connectedCallback?.();
117
+
118
+ this.addEventListener('focus', this.#boundedHandleFocus, true)
119
+ this.addEventListener('blur', this.#boundedHandleBlur, true)
120
+ this.addEventListener('focusin', this.#boundedHandleFocusIn)
121
+ this.addEventListener('focusout', this.#boundedHandleFocusOut)
122
+ }
123
+
124
+ disconnectedCallback() {
125
+ this.removeEventListener('focus', this.#boundedHandleFocus)
126
+ this.removeEventListener('blur', this.#boundedHandleBlur)
127
+ this.removeEventListener('focusin', this.#boundedHandleFocusIn)
128
+ this.removeEventListener('focusout', this.#boundedHandleFocusOut)
129
+ }
130
+ }
@@ -1,23 +1,24 @@
1
1
  export const hoverableMixin =
2
- (relativeSelector = '') =>
3
2
  (superclass) =>
4
- class HovrerableMixinClass extends superclass {
3
+ class HoverableMixinClass extends superclass {
4
+ #boundOnMouseOver = this.#onMouseOver.bind(this)
5
+
6
+ #onMouseOver(e) {
7
+ this.setAttribute('hover', 'true');
8
+ e.target.addEventListener(
9
+ 'mouseleave',
10
+ () => this.shadowRoot.host.removeAttribute('hover'),
11
+ { once: true }
12
+ );
13
+ }
14
+
5
15
  connectedCallback() {
6
16
  super.connectedCallback?.();
7
17
 
8
- const onMouseOver = (e) => {
9
- this.shadowRoot.host.setAttribute('hover', 'true');
10
- e.target.addEventListener(
11
- 'mouseleave',
12
- () => this.shadowRoot.host.removeAttribute('hover'),
13
- { once: true }
14
- );
15
- };
16
-
17
18
  const baseElement = this.shadowRoot.querySelector(
18
- this.baseSelector + relativeSelector
19
+ this.baseSelector
19
20
  );
20
21
 
21
- baseElement.addEventListener('mouseover', onMouseOver);
22
+ baseElement.addEventListener('mouseover', this.#boundOnMouseOver);
22
23
  }
23
24
  };
@@ -4,5 +4,7 @@ export { createProxy } from './createProxy';
4
4
  export { proxyInputMixin } from './proxyInputMixin';
5
5
  export { componentNameValidationMixin } from './componentNameValidationMixin';
6
6
  export { hoverableMixin } from './hoverableMixin';
7
- export { inputMixin } from './inputMixin'
7
+ export { focusMixin } from './focusMixin'
8
+ export { inputValidationMixin } from './inputValidationMixin'
8
9
  export { portalMixin } from './portalMixin'
10
+ export { changeMixin } from './changeMixin'
@@ -1,13 +1,4 @@
1
- import { upperFirst } from "../helpers";
2
-
3
- const events = [
4
- 'change',
5
- 'input',
6
- 'blur',
7
- 'focus',
8
- 'invalid',
9
- 'valid',
10
- ]
1
+ import { createDispatchEvent } from "../helpers/mixinsHelpers";
11
2
 
12
3
  const observedAttributes = [
13
4
  'required',
@@ -18,7 +9,7 @@ const errorAttributes = {
18
9
  valueMissing: 'data-errormessage-value-missing',
19
10
  patternMismatch: 'data-errormessage-pattern-mismatch'
20
11
  }
21
- export const inputMixin = (superclass) => class InputMixinClass extends superclass {
12
+ export const inputValidationMixin = (superclass) => class InputValidationMixinClass extends superclass {
22
13
  static get observedAttributes() {
23
14
  return [
24
15
  ...superclass.observedAttributes || [],
@@ -30,18 +21,19 @@ export const inputMixin = (superclass) => class InputMixinClass extends supercla
30
21
  return true;
31
22
  }
32
23
 
24
+ #dispatchValid = createDispatchEvent.bind(this, 'valid')
25
+ #dispatchInvalid = createDispatchEvent.bind(this, 'invalid')
26
+
33
27
  #internals
34
28
 
29
+ #boundedHandleInput
30
+
35
31
  constructor() {
36
32
  super();
37
33
 
38
34
  this.#internals = this.attachInternals();
39
35
 
40
- for (const event of events) {
41
- this[`dispatch${upperFirst(event)}`] = function () {
42
- this.dispatchInputEvent(event)
43
- }
44
- }
36
+ this.#boundedHandleInput = this.#handleInput.bind(this);
45
37
  }
46
38
 
47
39
  get defaultErrorMsgValueMissing() {
@@ -67,13 +59,7 @@ export const inputMixin = (superclass) => class InputMixinClass extends supercla
67
59
  }
68
60
  }
69
61
 
70
- get isReadOnly() {
71
- return this.hasAttribute('readonly') && this.getAttribute('readonly') !== 'false'
72
- }
73
-
74
62
  setValidity() {
75
- if (this.isReadOnly) return;
76
-
77
63
  const validity = this.getValidity()
78
64
  this.#internals.setValidity(validity, this.getErrorMessage(validity))
79
65
  }
@@ -83,7 +69,7 @@ export const inputMixin = (superclass) => class InputMixinClass extends supercla
83
69
  }
84
70
 
85
71
  getValidity() {
86
- throw Error('getValidity', 'is not implemented')
72
+ console.warn('getValidity', 'is not implemented')
87
73
  }
88
74
 
89
75
  checkValidity() {
@@ -115,36 +101,11 @@ export const inputMixin = (superclass) => class InputMixinClass extends supercla
115
101
  return this.getAttribute('pattern')
116
102
  }
117
103
 
118
- get value() {
119
- throw Error('get value', 'is not implemented')
120
- }
121
-
122
- set value(value) {
123
- throw Error('set value', 'is not implemented')
124
- }
125
-
126
- handleFocus() {
127
- throw Error('handleFocus', 'is not implemented')
128
- }
129
-
130
- handleInput() {
104
+ #handleInput() {
131
105
  this.setValidity()
132
106
  this.handleDispatchValidationEvents()
133
107
  }
134
108
 
135
- handleBlur() {
136
- throw Error('handleBlur', 'is not implemented')
137
- }
138
-
139
- handleChange() {
140
- throw Error('handleChange', 'is not implemented')
141
- }
142
-
143
- dispatchInputEvent(eventName) {
144
- this[`on${eventName}`]?.(); // in case we got an event callback as property
145
- this.dispatchEvent(new InputEvent(eventName));
146
- }
147
-
148
109
  attributeChangedCallback(attrName, oldValue, newValue) {
149
110
  super.attributeChangedCallback?.(attrName, oldValue, newValue);
150
111
 
@@ -155,24 +116,22 @@ export const inputMixin = (superclass) => class InputMixinClass extends supercla
155
116
 
156
117
  handleDispatchValidationEvents() {
157
118
  if (this.checkValidity()) {
158
- this.dispatchValid()
119
+ this.#dispatchValid()
159
120
  } else {
160
- this.dispatchInvalid()
121
+ this.#dispatchInvalid()
161
122
  }
162
123
  }
163
124
 
164
125
  connectedCallback() {
165
126
  super.connectedCallback?.();
166
127
 
128
+ this.addEventListener('input', this.#boundedHandleInput)
129
+
167
130
  this.setValidity();
168
131
  this.handleDispatchValidationEvents();
132
+ }
169
133
 
170
- // create proxy replace the addEventListener fn
171
- // and we want to be able to access the focus events
172
- // of this element and not the nested element's events
173
- this.onfocus = this.handleFocus.bind(this);
174
- this.addEventListener('input', this.handleInput.bind(this))
175
- this.addEventListener('blur', this.handleBlur.bind(this))
176
- this.addEventListener('change', this.handleBlur.bind(this))
134
+ disconnectedCallback() {
135
+ this.removeEventListener('input', this.#boundedHandleInput)
177
136
  }
178
137
  }
@@ -1,13 +1,17 @@
1
1
  import { PORTAL_THEME_PREFIX } from "../constants";
2
- import { upperFirst } from "../helpers";
2
+ import { kebabCaseJoin, upperFirst } from "../helpers";
3
3
  import { forwardAttrs } from "../helpers/componentHelpers";
4
4
  import { createStyleMixin } from "./createStyleMixin";
5
5
  import { createCssVarsList } from "./createStyleMixin/helpers";
6
6
 
7
- const sanitizeSelector = (selector) => selector.replace(/[^\w\s]/gi, '');
7
+ // this is needed because we might generate the same css vars names
8
+ // e.g. "overlayColor" attribute in style mixin's mapping,
9
+ // will generate the same var as "color" attribute in portals's mapping
10
+ // when the portal name is "overlay".
11
+ // because of that, we are adding this separator that is also used as a differentiator
12
+ const DISPLAY_NAME_SEPARATOR = '_'
8
13
 
9
- const appendSuffixToKeys = (obj, suffix) => Object.keys(obj).reduce((acc, key) =>
10
- Object.assign(acc, { [suffix + upperFirst(key)]: obj[key] }), {})
14
+ const sanitizeSelector = (selector) => selector.replace(/[^\w\s]/gi, '');
11
15
 
12
16
  const getDomNode = (maybeDomNode) => maybeDomNode.host || maybeDomNode;
13
17
 
@@ -22,7 +26,7 @@ export const portalMixin = ({ name, selector, mappings = {} }) => (superclass) =
22
26
  static get cssVarList() {
23
27
  return {
24
28
  ...BaseClass.cssVarList,
25
- ...createCssVarsList(superclass.componentName, appendSuffixToKeys(mappings, eleDisplayName))
29
+ [eleDisplayName]: createCssVarsList(kebabCaseJoin(superclass.componentName, DISPLAY_NAME_SEPARATOR + eleDisplayName), mappings)
26
30
  };
27
31
  }
28
32
 
@@ -32,14 +36,14 @@ export const portalMixin = ({ name, selector, mappings = {} }) => (superclass) =
32
36
  // we cannot use "this" before calling "super"
33
37
  const getRootElement = (that) => {
34
38
  const baseEle = that.shadowRoot.querySelector(that.baseSelector)
35
- const portal = baseEle.shadowRoot.querySelector(selector)
39
+ const portal = selector ? baseEle.shadowRoot.querySelector(selector) : baseEle
36
40
 
37
41
  return portal.shadowRoot || portal
38
42
  };
39
43
 
40
44
  super({
41
45
  getRootElement,
42
- componentNameSuffix: eleDisplayName,
46
+ componentNameSuffix: DISPLAY_NAME_SEPARATOR + eleDisplayName,
43
47
  themeSection: PORTAL_THEME_PREFIX + eleDisplayName,
44
48
  baseSelector: ':host'
45
49
  })
@@ -1,4 +1,4 @@
1
- import { inputMixin } from "./inputMixin";
1
+ import { inputValidationMixin } from "./inputValidationMixin";
2
2
 
3
3
  const errorAttrs = ['invalid', 'has-error-message'];
4
4
 
@@ -29,18 +29,28 @@ const getNestedInput = (ele) => {
29
29
  }
30
30
 
31
31
  export const proxyInputMixin = (superclass) =>
32
- class proxyInputMixinClass extends inputMixin(superclass) {
32
+ class proxyInputMixinClass extends inputValidationMixin(superclass) {
33
33
  static get observedAttributes() {
34
34
  return [...superclass.observedAttributes || [], ...errorAttrs];
35
35
  }
36
36
 
37
37
  #inputElement
38
38
 
39
+ #boundHandleFocus
40
+ #boundHandleInvalid
41
+ #boundHandleValid
42
+
39
43
  constructor() {
40
44
  super();
41
45
 
42
46
  this.#inputElement = super.inputElement
43
47
 
48
+ this.#boundHandleFocus = this.#handleFocus.bind(this);
49
+ this.#boundHandleInvalid = this.#handleInvalid.bind(this);
50
+ this.#boundHandleValid = this.#handleValid.bind(this);
51
+
52
+ this.baseEle = this.shadowRoot.querySelector(this.baseSelector);
53
+
44
54
  }
45
55
 
46
56
  get inputElement() {
@@ -48,7 +58,7 @@ export const proxyInputMixin = (superclass) =>
48
58
  const textAreaSlot = this.baseEle.shadowRoot.querySelector('slot[name="textarea"]')
49
59
 
50
60
  this.#inputElement ??= getNestedInput(inputSlot) || getNestedInput(textAreaSlot)
51
-
61
+
52
62
  if (!this.#inputElement) throw Error('no input was found');
53
63
 
54
64
  return this.#inputElement
@@ -64,27 +74,17 @@ export const proxyInputMixin = (superclass) =>
64
74
 
65
75
  reportValidityOnInternalInput() {
66
76
  setTimeout(() => {
77
+ this.baseEle.focus() //TODO: check if this is needed
67
78
  this.inputElement.reportValidity()
68
- }, 0)
69
- }
70
-
71
- handleBlur() { }
72
-
73
- handleFocus() {
74
- this.inputElement.focus();
75
- if (this.hasAttribute('invalid')) {
76
- this.reportValidityOnInternalInput()
77
- }
79
+ })
78
80
  }
79
81
 
80
82
  // we want reportValidity to behave like form submission
81
83
  reportValidity() {
82
- const isValid = super.reportValidity()
83
84
  if (!isValid) {
84
85
  this.setAttribute('invalid', 'true');
85
- this.inputElement.focus()
86
+ this.reportValidityOnInternalInput()
86
87
  }
87
- this.reportValidityOnInternalInput()
88
88
  }
89
89
 
90
90
  setInternalInputErrorMessage() {
@@ -93,48 +93,47 @@ export const proxyInputMixin = (superclass) =>
93
93
  }
94
94
  }
95
95
 
96
- connectedCallback() {
97
- this.baseEle = this.shadowRoot.querySelector(this.baseSelector);
96
+ // when clicking on the form submit button and the input is invalid
97
+ // we want it to appear as invalid
98
+ #handleFocus(e) {
99
+ if (e.relatedTarget?.form) {
100
+ if (!this.checkValidity()) {
101
+ this.setAttribute('invalid', 'true');
102
+ }
98
103
 
99
- // this is our way to identify that the form was submitted
100
- // in this case, we want the input to be in error state if it's not valid
101
- this.addEventListener('focus', (e) => {
102
- if (e.relatedTarget?.form) {
103
- if (!this.checkValidity()) {
104
- this.setAttribute('invalid', 'true');
105
- }
106
-
107
- if (this.hasAttribute('invalid')) {
108
- this.reportValidityOnInternalInput()
109
- }
104
+ if (this.hasAttribute('invalid')) {
105
+ this.reportValidityOnInternalInput()
110
106
  }
111
- })
107
+ }
108
+ }
112
109
 
113
- this.addEventListener('invalid', () => {
114
- this.setInternalInputErrorMessage()
115
- this.setAttribute('error-message', this.validationMessage)
116
- })
110
+ #handleInvalid() {
111
+ this.setInternalInputErrorMessage()
112
+ this.setAttribute('error-message', this.validationMessage)
113
+ }
117
114
 
118
- this.addEventListener('valid', () => {
119
- this.removeAttribute('invalid')
120
- })
115
+ #handleValid() {
116
+ this.removeAttribute('invalid')
117
+ }
121
118
 
119
+ connectedCallback() {
122
120
  super.connectedCallback?.();
123
121
 
124
- this.inputElement.addEventListener('input', () => {
122
+ // this is our way to identify that the form was submitted
123
+ // in this case, we want the input to be in error state if it's not valid
124
+ this.addEventListener('focus', this.#boundHandleFocus)
125
+
126
+ this.addEventListener('invalid', this.#boundHandleInvalid)
127
+ this.addEventListener('valid', this.#boundHandleValid)
128
+
129
+ this.addEventListener('input', () => {
125
130
  this.inputElement.setCustomValidity('')
126
131
  if (!this.inputElement.checkValidity())
127
132
  this.setInternalInputErrorMessage()
128
133
  })
129
134
 
130
- this.inputElement.addEventListener('invalid', () => {
131
- this.setValidity()
132
- this.setInternalInputErrorMessage()
133
- this.setAttribute('error-message', this.validationMessage)
134
- })
135
-
136
135
  // this is needed in order to make sure the form input validation is working
137
- if (!this.hasAttribute('tabindex')) {
136
+ if (!this.hasAttribute('tabindex') && this.getRootNode() === document) {
138
137
  this.setAttribute('tabindex', 0);
139
138
  }
140
139
 
@@ -143,6 +142,12 @@ export const proxyInputMixin = (superclass) =>
143
142
  this.setSelectionRange = this.inputElement.setSelectionRange?.bind(this.inputElement);
144
143
  }
145
144
 
145
+ disconnectedCallback() {
146
+ this.removeEventListener('focus', this.#boundHandleFocus)
147
+ this.removeEventListener('invalid', this.#boundHandleInvalid)
148
+ this.removeEventListener('valid', this.#boundHandleValid)
149
+ }
150
+
146
151
  attributeChangedCallback(attrName, oldValue, newValue) {
147
152
  super.attributeChangedCallback?.(attrName, oldValue, newValue);
148
153
 
@@ -18,15 +18,8 @@ export const comboBox = {
18
18
  [vars.borderWidth]: '0',
19
19
  [vars.cursor]: 'pointer',
20
20
  [vars.padding]: '0',
21
-
22
- '@overlay': {
23
- [vars.overlayBackgroundColor] : 'red',
24
- [vars.overlayBorder]: '3px solid blue',
25
-
26
- _hover: {
27
- [vars.overlayBackgroundColor] : 'blue',
28
- }
29
- }
21
+ // [vars.overlayBackground]: 'blue',
22
+ // [vars.overlayBorder]: '3px solid red',
30
23
  };
31
24
 
32
25
  export default comboBox;
package/dist/umd/860.js DELETED
@@ -1 +0,0 @@
1
- "use strict";(self.webpackChunkDescopeUI=self.webpackChunkDescopeUI||[]).push([[860],{9989:(t,e,s)=>{s.d(e,{V:()=>i});class i extends HTMLElement{}},5279:(t,e,s)=>{s.d(e,{gh:()=>i,k4:()=>n,qM:()=>a,qg:()=>r});const i="descope",n=3,r="host",a="@"},4567:(t,e,s)=>{s.d(e,{Db:()=>u,FX:()=>r,P$:()=>a,Tk:()=>c,iY:()=>h,oP:()=>d,tg:()=>l});var i=s(2061),n=s(5279);const r=(t,e,{excludeAttrs:s=[],includeAttrs:i=[]})=>{const n=Array.from(t.attributes).filter((t=>!s.includes(t.name)&&(!i.length||i.includes(t.name)))).map((t=>t.name));e(n),new MutationObserver((t=>{for(const n of t)"attributes"!==n.type||s.includes(n.attributeName)||i.length&&!i.includes(n.attributeName)||e([n.attributeName])})).observe(t,{attributes:!0})},a=(t,e)=>{e({addedNodes:Array.from(t.children),removedNodes:[]}),new MutationObserver((t=>{for(const s of t)"childList"===s.type&&e(s)})).observe(t,{childList:!0})},o=(t,e,s={})=>i=>{i.forEach((i=>{const n=s[i]||i,r=t.getAttribute(i);null!==r?e.getAttribute(n)!==r&&e.setAttribute(n,r):e.removeAttribute(n)}))},l=(t,e,s)=>{r(t,o(t,e),s),r(e,o(e,t),s)},h=t=>(0,i.E3)(n.gh,t),c=(...t)=>`--${(0,i.E3)(...t)}`,d=(t,e,s={})=>{r(t,o(t,e,s.mapAttrs),s)},u=(t,e,s=[])=>{if(!s.length)return;const i=s.reduce(((t,s)=>Object.assign(t,{[s]:{get:()=>e[s],set(t){e[s]=t}}})),{});Object.defineProperties(t,i)}},2061:(t,e,s)=>{s.d(e,{E3:()=>n,GL:()=>i,jC:()=>a,qC:()=>r});const i=t=>t.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[\s_.]+/g,"-").toLowerCase(),n=(...t)=>i(t.filter((t=>!!t)).join("-")),r=(...t)=>e=>t.reduceRight(((t,e)=>e(t)),e),a=t=>t.charAt(0).toUpperCase()+t.slice(1)},6860:(t,e,s)=>{s.d(e,{Ae:()=>C,DM:()=>p,yk:()=>c,e4:()=>d,_A:()=>m,y7:()=>g,Iw:()=>A,dj:()=>f});var i=s(5279),n=s(2061),r=s(4567),a=s(5561);const o=(t,...e)=>`var(${t}${e.length?` , ${o(...e)}`:""})`;class l{constructor(){this.styleMap=new Map}add(t,e,s){this.styleMap.has(t)||this.styleMap.set(t,[]),this.styleMap.set(t,[...this.styleMap.get(t),{property:e,value:s}])}toString(){return Array.from(this.styleMap.entries()).reduce(((t,[e,s])=>t+`${e} { \n${s.map((({property:t,value:e})=>`${t}: ${e}`)).join(";\n")} \n}\n\n`),"")}}const h=(t,e)=>Object.keys(e).reduce(((e,s)=>Object.assign(e,{[s]:(0,r.Tk)(t,s)})),{}),c=({mappings:t={}})=>e=>class extends e{static get cssVarList(){return{...e.cssVarList,...h(e.componentName,{...t})}}#t;#e;#s;#i;#n;#r;#a;#o;constructor({getRootElement:e,componentNameSuffix:s="",themeSection:r=i.qg,baseSelector:a}={}){super(),this.#i=s,this.#n=r,this.#r=e?.(this)||this.shadowRoot,this.#a=a??this.baseSelector,this.#o=Object.keys(t).map((t=>(0,n.E3)("st",s,t)))}get componentTheme(){return a.componentsThemeManager.currentTheme?.[e.componentName]||""}#l(){this.#e.innerHTML=this.componentTheme[this.#n]}#h(){this.#e=document.createElement("style"),this.#e.id="style-mixin-theme",this.#r.prepend(this.#e),this.#s=a.componentsThemeManager.onCurrentThemeChange(this.#l.bind(this)),this.#l()}#c(){this.#t=document.createElement("style"),this.#t.id="style-mixin-overrides";const t=(s=e.componentName,n=i.k4,Array(n).fill(`.${s}`).join(""));var s,n;this.#t.innerText=`:host(${t}) {}`,this.#r.append(this.#t)}#d(t,s){const i=this.#t?.sheet?.cssRules[0].style;if(!i)return;const n=(0,r.Tk)(e.componentName,t.replace(new RegExp("^st-"),""));s?i?.setProperty(n,s):i?.removeProperty(n)}#u(t=[]){for(const e of t)this.#o.includes(e)&&this.#d(e,this.getAttribute(e));this.#t.innerHTML=this.#t?.sheet?.cssRules[0].cssText}#m(){const s=document.createElement("style");s.id="style-mixin-mappings",s.innerHTML=((t,e,s)=>{const i=new l;return Object.keys(s).forEach((a=>{const l=((t,e)=>{const s={selector:"",property:(0,n.GL)(t)};return e&&Object.keys(e).length?Array.isArray(e)?e.map((t=>Object.assign({},s,t))):[Object.assign({},s,e)]:[s]})(a,s[a]),h=(0,r.Tk)(t,a);l.forEach((({selector:t,property:s})=>{i.add(((t="",e="")=>"function"==typeof e?e(t):`${t}${/^[A-Za-z]/.test(e)?` ${e}`:e}`)(e,t),s,o(h))}))})),i.toString()})((0,n.E3)(e.componentName,this.#i),this.#a,t),this.#r.prepend(s)}#p(t){(this.#r.classList||this.#r.host.classList).add(t)}connectedCallback(){super.connectedCallback?.(),this.shadowRoot.isConnected&&(this.#p(e.componentName),this.#m(),this.#h(),this.#c(),(0,r.FX)(this,this.#u.bind(this),{}))}disconnectedCallback(){this.#s?.()}},d=t=>class extends t{#b=null;static get observedAttributes(){return[...t.observedAttributes||[],"draggable"]}constructor(){super(),this.#b=document.createElement("style"),this.#b.innerText=`${this.baseSelector} { cursor: inherit }`}#y(t){t?this.shadowRoot.appendChild(this.#b):this.#b.remove()}attributeChangedCallback(t,e,s){super.attributeChangedCallback?.(t,e,s),"draggable"===t&&this.#y("true"===s)}};var u=s(9989);const m=(t="")=>e=>class extends e{connectedCallback(){super.connectedCallback?.(),this.shadowRoot.querySelector(this.baseSelector+t).addEventListener("mouseover",(t=>{this.shadowRoot.host.setAttribute("hover","true"),t.target.addEventListener("mouseleave",(()=>this.shadowRoot.host.removeAttribute("hover")),{once:!0})}))}},p=({componentName:t,wrappedEleName:e,slots:s=[],style:i,excludeAttrsSync:a=[],includeAttrsSync:o=[],includeForwardProps:l=[]})=>{const h=`\n\t\t<style id="create-proxy"></style>\n\t\t<${e}>\n\t\t<slot></slot>\n\t\t${s.map((t=>`<slot name="${t}" slot="${t}"></slot>`)).join("")}\n\t\t</${e}>\n\t`;class c extends u.V{static get componentName(){return t}constructor(){super().attachShadow({mode:"open"}).innerHTML=h,this.hostElement=this.shadowRoot.host,this.baseSelector=e,this.shadowRoot.getElementById("create-proxy").innerHTML="function"==typeof i?i():i}connectedCallback(){this.shadowRoot.isConnected&&(this.proxyElement=this.shadowRoot.querySelector(e),(0,r.Db)(this.hostElement,this.proxyElement,l),this.setAttribute("tabindex","0"),this.addEventListener("focus",(()=>{this.proxyElement.focus()})),this.proxyElement.onkeydown=t=>{t.shiftKey&&9===t.keyCode&&(this.removeAttribute("tabindex"),setTimeout((()=>this.setAttribute("tabindex","0")),0))},this.addEventListener=(...t)=>this.proxyElement.addEventListener(...t),(0,r.tg)(this.proxyElement,this.hostElement,{excludeAttrs:a,includeAttrs:o}))}disconnectedCallback(){this.proxyElement.removeEventListener("mouseover",this.mouseoverCbRef)}attributeChangedCallback(){this.proxyElement}}return(0,n.qC)(m())(c)},b=["change","input","blur","focus","invalid","valid"],y=["required","pattern"],g=t=>class extends t{static get observedAttributes(){return[...t.observedAttributes||[],...y]}static get formAssociated(){return!0}#g;constructor(){super(),this.#g=this.attachInternals();for(const t of b)this[`dispatch${(0,n.jC)(t)}`]=function(){this.dispatchInputEvent(t)}}get defaultErrorMsgValueMissing(){return"Please fill out this field."}get defaultErrorMsgPatternMismatch(){return"Please match the requested format."}getErrorMessage(t){switch(!0){case t.valueMissing:return this.getAttribute("data-errormessage-value-missing")||this.defaultErrorMsgValueMissing;case t.patternMismatch||t.typeMismatch:return this.getAttribute("data-errormessage-pattern-mismatch")||this.defaultErrorMsgPatternMismatch;case t.customError:return this.validationMessage;default:return""}}get isReadOnly(){return this.hasAttribute("readonly")&&"false"!==this.getAttribute("readonly")}setValidity(){if(this.isReadOnly)return;const t=this.getValidity();this.#g.setValidity(t,this.getErrorMessage(t))}get validationMessage(){return this.#g.validationMessage}getValidity(){throw Error("getValidity","is not implemented")}checkValidity(){return this.#g.validity.valid}reportValidity(){return this.#g.reportValidity()}get validity(){return this.#g.validity}setCustomValidity(t){t?this.#g.setValidity({customError:!0},t):(this.#g.setValidity({}),this.setValidity())}get isRequired(){return this.hasAttribute("required")&&"false"!==this.getAttribute("required")}get pattern(){return this.getAttribute("pattern")}get value(){throw Error("get value","is not implemented")}set value(t){throw Error("set value","is not implemented")}handleFocus(){throw Error("handleFocus","is not implemented")}handleInput(){this.setValidity(),this.handleDispatchValidationEvents()}handleBlur(){throw Error("handleBlur","is not implemented")}handleChange(){throw Error("handleChange","is not implemented")}dispatchInputEvent(t){this[`on${t}`]?.(),this.dispatchEvent(new InputEvent(t))}attributeChangedCallback(t,e,s){super.attributeChangedCallback?.(t,e,s),y.includes(t)&&this.setValidity()}handleDispatchValidationEvents(){this.checkValidity()?this.dispatchValid():this.dispatchInvalid()}connectedCallback(){super.connectedCallback?.(),this.setValidity(),this.handleDispatchValidationEvents(),this.onfocus=this.handleFocus.bind(this),this.addEventListener("input",this.handleInput.bind(this)),this.addEventListener("blur",this.handleBlur.bind(this)),this.addEventListener("change",this.handleBlur.bind(this))}},E=["invalid","has-error-message"],v=t=>{if(!t)return;let e=t;for(let t=0;t<10;t++)if(e=e.assignedElements()[0],"slot"!==e.localName)return e},f=t=>class extends(g(t)){static get observedAttributes(){return[...t.observedAttributes||[],...E]}#E;constructor(){super(),this.#E=super.inputElement}get inputElement(){const t=this.baseEle.shadowRoot.querySelector('slot[name="input"]'),e=this.baseEle.shadowRoot.querySelector('slot[name="textarea"]');if(this.#E??=v(t)||v(e),!this.#E)throw Error("no input was found");return this.#E}set inputElement(t){this.#E=t}getValidity(){return this.inputElement.validity}reportValidityOnInternalInput(){setTimeout((()=>{this.inputElement.reportValidity()}),0)}handleBlur(){}handleFocus(){this.inputElement.focus(),this.hasAttribute("invalid")&&this.reportValidityOnInternalInput()}reportValidity(){super.reportValidity()||(this.setAttribute("invalid","true"),this.inputElement.focus()),this.reportValidityOnInternalInput()}setInternalInputErrorMessage(){this.checkValidity()||this.inputElement.setCustomValidity(this.validationMessage)}connectedCallback(){var t,e;this.baseEle=this.shadowRoot.querySelector(this.baseSelector),this.addEventListener("focus",(t=>{t.relatedTarget?.form&&(this.checkValidity()||this.setAttribute("invalid","true"),this.hasAttribute("invalid")&&this.reportValidityOnInternalInput())})),this.addEventListener("invalid",(()=>{this.setInternalInputErrorMessage(),this.setAttribute("error-message",this.validationMessage)})),this.addEventListener("valid",(()=>{this.removeAttribute("invalid")})),super.connectedCallback?.(),this.inputElement.addEventListener("input",(()=>{this.inputElement.setCustomValidity(""),this.inputElement.checkValidity()||this.setInternalInputErrorMessage()})),this.inputElement.addEventListener("invalid",(()=>{this.setValidity(),this.setInternalInputErrorMessage(),this.setAttribute("error-message",this.validationMessage)})),this.hasAttribute("tabindex")||this.setAttribute("tabindex",0),t=this.inputElement,e="value",Object.defineProperty(this,e,{set:function(s){return t[e]=s},get:function(){return t[e]},configurable:!0}),this.setSelectionRange=this.inputElement.setSelectionRange?.bind(this.inputElement)}attributeChangedCallback(t,e,s){super.attributeChangedCallback?.(t,e,s),"invalid"===t&&""===s&&this.setAttribute("invalid","true")}},C=t=>class extends t{#v(){const e=this.shadowRoot.host.tagName.toLowerCase();if(!t.componentName)throw Error('component name is not defined on super class, make sure you have a static get for "componentName"');if(e!==t.componentName)throw Error(`component name mismatch, expected "${t.componentName}", current "${e}"`)}connectedCallback(){super.connectedCallback?.(),this.shadowRoot.isConnected&&this.#v()}},A=({name:t,selector:e,mappings:s={}})=>a=>{const o=t||(t=>t.replace(/[^\w\s]/gi,""))(e),l=c({mappings:s})(a);return class extends l{static get cssVarList(){return{...l.cssVarList,...h(a.componentName,(t=s,e=o,Object.keys(t).reduce(((s,i)=>Object.assign(s,{[e+(0,n.jC)(i)]:t[i]})),{})))};var t,e}#f;constructor(){const t=t=>{const s=t.shadowRoot.querySelector(t.baseSelector).shadowRoot.querySelector(e);return s.shadowRoot||s};var s;super({getRootElement:t,componentNameSuffix:o,themeSection:i.qM+o,baseSelector:":host"}),this.#f=(s=t(this)).host||s}#C(){this.#f.onmouseenter=t=>{t.target.setAttribute("hover","true")},this.#f.onmouseleave=t=>{t.target.removeAttribute("hover")}}connectedCallback(){super.connectedCallback?.(),(0,r.oP)(this,this.#f,{excludeAttrs:["hover"]}),this.#C()}}}}}]);
@@ -1 +0,0 @@
1
- export class DescopeBaseClass extends HTMLElement {}