@vaadin/field-base 22.0.0-alpha5 → 22.0.0-alpha9

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 (77) hide show
  1. package/index.d.ts +7 -15
  2. package/index.js +7 -15
  3. package/package.json +24 -18
  4. package/src/aria-label-controller.d.ts +11 -0
  5. package/src/aria-label-controller.js +53 -0
  6. package/src/checked-mixin.d.ts +21 -0
  7. package/src/checked-mixin.js +54 -0
  8. package/src/delegate-focus-mixin.d.ts +2 -2
  9. package/src/delegate-focus-mixin.js +150 -133
  10. package/src/delegate-state-mixin.d.ts +1 -1
  11. package/src/delegate-state-mixin.js +100 -88
  12. package/src/field-mixin.d.ts +39 -0
  13. package/src/field-mixin.js +317 -0
  14. package/src/input-constraints-mixin.d.ts +4 -2
  15. package/src/input-constraints-mixin.js +107 -64
  16. package/src/input-control-mixin.d.ts +52 -0
  17. package/src/input-control-mixin.js +170 -0
  18. package/src/input-controller.d.ts +11 -0
  19. package/src/input-controller.js +35 -0
  20. package/src/input-field-mixin.d.ts +2 -16
  21. package/src/input-field-mixin.js +125 -80
  22. package/src/input-mixin.d.ts +1 -1
  23. package/src/input-mixin.js +156 -145
  24. package/src/label-mixin.d.ts +2 -2
  25. package/src/label-mixin.js +73 -60
  26. package/src/pattern-mixin.js +9 -9
  27. package/src/shadow-focus-mixin.d.ts +21 -0
  28. package/src/shadow-focus-mixin.js +87 -0
  29. package/src/slot-controller.d.ts +8 -0
  30. package/src/slot-controller.js +36 -0
  31. package/src/slot-label-mixin.d.ts +20 -0
  32. package/src/slot-label-mixin.js +38 -0
  33. package/src/slot-styles-mixin.js +38 -31
  34. package/src/slot-target-mixin.d.ts +32 -0
  35. package/src/slot-target-mixin.js +110 -0
  36. package/src/styles/clear-button-styles.d.ts +8 -0
  37. package/src/styles/clear-button-styles.js +21 -0
  38. package/src/styles/field-shared-styles.d.ts +8 -0
  39. package/src/styles/field-shared-styles.js +29 -0
  40. package/src/styles/input-field-container-styles.d.ts +8 -0
  41. package/src/styles/input-field-container-styles.js +16 -0
  42. package/src/styles/input-field-shared-styles.d.ts +8 -0
  43. package/src/styles/input-field-shared-styles.js +10 -0
  44. package/src/text-area-controller.d.ts +11 -0
  45. package/src/text-area-controller.js +38 -0
  46. package/src/validate-mixin.d.ts +1 -9
  47. package/src/validate-mixin.js +43 -118
  48. package/src/active-mixin.d.ts +0 -26
  49. package/src/active-mixin.js +0 -106
  50. package/src/aria-label-mixin.d.ts +0 -20
  51. package/src/aria-label-mixin.js +0 -71
  52. package/src/char-length-mixin.d.ts +0 -30
  53. package/src/char-length-mixin.js +0 -42
  54. package/src/clear-button-mixin.d.ts +0 -28
  55. package/src/clear-button-mixin.js +0 -82
  56. package/src/delegate-input-state-mixin.d.ts +0 -43
  57. package/src/delegate-input-state-mixin.js +0 -63
  58. package/src/disabled-mixin.d.ts +0 -23
  59. package/src/disabled-mixin.js +0 -60
  60. package/src/field-aria-mixin.d.ts +0 -24
  61. package/src/field-aria-mixin.js +0 -61
  62. package/src/focus-mixin.d.ts +0 -33
  63. package/src/focus-mixin.js +0 -104
  64. package/src/helper-text-mixin.d.ts +0 -24
  65. package/src/helper-text-mixin.js +0 -144
  66. package/src/input-slot-mixin.d.ts +0 -26
  67. package/src/input-slot-mixin.js +0 -71
  68. package/src/keyboard-mixin.d.ts +0 -32
  69. package/src/keyboard-mixin.js +0 -51
  70. package/src/slot-mixin.d.ts +0 -23
  71. package/src/slot-mixin.js +0 -49
  72. package/src/tabindex-mixin.d.ts +0 -29
  73. package/src/tabindex-mixin.js +0 -78
  74. package/src/text-area-slot-mixin.d.ts +0 -21
  75. package/src/text-area-slot-mixin.js +0 -56
  76. package/src/text-field-mixin.d.ts +0 -21
  77. package/src/text-field-mixin.js +0 -17
package/index.d.ts CHANGED
@@ -1,23 +1,15 @@
1
- export { ActiveMixin } from './src/active-mixin.js';
2
- export { AriaLabelMixin } from './src/aria-label-mixin.js';
3
- export { CharLengthMixin } from './src/char-length-mixin.js';
4
- export { ClearButtonMixin } from './src/clear-button-mixin.js';
1
+ export { AriaLabelController } from './src/aria-label-controller.js';
2
+ export { CheckedMixin } from './src/checked-mixin.js';
5
3
  export { DelegateFocusMixin } from './src/delegate-focus-mixin.js';
6
- export { DelegateInputStateMixin } from './src/delegate-input-state-mixin.js';
7
4
  export { DelegateStateMixin } from './src/delegate-state-mixin.js';
8
- export { DisabledMixin } from './src/disabled-mixin.js';
9
- export { FieldAriaMixin } from './src/field-aria-mixin.js';
10
- export { FocusMixin } from './src/focus-mixin.js';
11
- export { HelperTextMixin } from './src/helper-text-mixin.js';
5
+ export { FieldMixin } from './src/field-mixin.js';
6
+ export { InputController } from './src/input-controller.js';
7
+ export { InputControlMixin } from './src/input-control-mixin.js';
12
8
  export { InputFieldMixin } from './src/input-field-mixin.js';
13
9
  export { InputMixin } from './src/input-mixin.js';
14
- export { InputSlotMixin } from './src/input-slot-mixin.js';
15
- export { KeyboardMixin } from './src/keyboard-mixin.js';
16
10
  export { LabelMixin } from './src/label-mixin.js';
17
11
  export { PatternMixin } from './src/pattern-mixin.js';
18
- export { SlotMixin } from './src/slot-mixin.js';
12
+ export { ShadowFocusMixin } from './src/shadow-focus-mixin.js';
19
13
  export { SlotStylesMixin } from './src/slot-styles-mixin.js';
20
- export { TabindexMixin } from './src/tabindex-mixin.js';
21
- export { TextAreaSlotMixin } from './src/text-area-slot-mixin.js';
22
- export { TextFieldMixin } from './src/text-field-mixin.js';
14
+ export { TextAreaController } from './src/text-area-controller.js';
23
15
  export { ValidateMixin } from './src/validate-mixin.js';
package/index.js CHANGED
@@ -1,23 +1,15 @@
1
- export { ActiveMixin } from './src/active-mixin.js';
2
- export { AriaLabelMixin } from './src/aria-label-mixin.js';
3
- export { CharLengthMixin } from './src/char-length-mixin.js';
4
- export { ClearButtonMixin } from './src/clear-button-mixin.js';
1
+ export { AriaLabelController } from './src/aria-label-controller.js';
2
+ export { CheckedMixin } from './src/checked-mixin.js';
5
3
  export { DelegateFocusMixin } from './src/delegate-focus-mixin.js';
6
- export { DelegateInputStateMixin } from './src/delegate-input-state-mixin.js';
7
4
  export { DelegateStateMixin } from './src/delegate-state-mixin.js';
8
- export { DisabledMixin } from './src/disabled-mixin.js';
9
- export { FieldAriaMixin } from './src/field-aria-mixin.js';
10
- export { FocusMixin } from './src/focus-mixin.js';
11
- export { HelperTextMixin } from './src/helper-text-mixin.js';
5
+ export { FieldMixin } from './src/field-mixin.js';
6
+ export { InputController } from './src/input-controller.js';
7
+ export { InputControlMixin } from './src/input-control-mixin.js';
12
8
  export { InputFieldMixin } from './src/input-field-mixin.js';
13
9
  export { InputMixin } from './src/input-mixin.js';
14
- export { InputSlotMixin } from './src/input-slot-mixin.js';
15
- export { KeyboardMixin } from './src/keyboard-mixin.js';
16
10
  export { LabelMixin } from './src/label-mixin.js';
17
11
  export { PatternMixin } from './src/pattern-mixin.js';
18
- export { SlotMixin } from './src/slot-mixin.js';
12
+ export { ShadowFocusMixin } from './src/shadow-focus-mixin.js';
19
13
  export { SlotStylesMixin } from './src/slot-styles-mixin.js';
20
- export { TabindexMixin } from './src/tabindex-mixin.js';
21
- export { TextAreaSlotMixin } from './src/text-area-slot-mixin.js';
22
- export { TextFieldMixin } from './src/text-field-mixin.js';
14
+ export { TextAreaController } from './src/text-area-controller.js';
23
15
  export { ValidateMixin } from './src/validate-mixin.js';
package/package.json CHANGED
@@ -1,36 +1,42 @@
1
1
  {
2
2
  "name": "@vaadin/field-base",
3
- "version": "22.0.0-alpha5",
3
+ "version": "22.0.0-alpha9",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
4
7
  "description": "Vaadin field base mixins",
5
- "main": "index.js",
6
- "module": "index.js",
7
- "repository": "vaadin/web-components",
8
- "keywords": [
9
- "Vaadin",
10
- "web-components",
11
- "web-component"
12
- ],
13
- "author": "Vaadin Ltd",
14
8
  "license": "Apache-2.0",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/vaadin/web-components.git",
12
+ "directory": "packages/field-base"
13
+ },
14
+ "author": "Vaadin Ltd",
15
+ "homepage": "https://vaadin.com/components",
15
16
  "bugs": {
16
17
  "url": "https://github.com/vaadin/web-components"
17
18
  },
18
- "homepage": "https://vaadin.com/components",
19
+ "main": "index.js",
20
+ "module": "index.js",
19
21
  "files": [
20
- "index.js",
21
22
  "index.d.ts",
23
+ "index.js",
22
24
  "src"
23
25
  ],
26
+ "keywords": [
27
+ "Vaadin",
28
+ "web-components",
29
+ "web-component"
30
+ ],
24
31
  "dependencies": {
25
- "@polymer/polymer": "^3.0.0"
32
+ "@polymer/polymer": "^3.0.0",
33
+ "@vaadin/component-base": "22.0.0-alpha9",
34
+ "lit": "^2.0.0"
26
35
  },
27
36
  "devDependencies": {
28
37
  "@esm-bundle/chai": "^4.3.4",
29
- "@vaadin/testing-helpers": "^0.2.1",
38
+ "@vaadin/testing-helpers": "^0.3.0",
30
39
  "sinon": "^9.2.1"
31
40
  },
32
- "publishConfig": {
33
- "access": "public"
34
- },
35
- "gitHead": "012f658db6f81375be8889f63ee15e3f660fe9ec"
41
+ "gitHead": "6e8c899dc65918f97e3c0acb2076122c4b2ef274"
36
42
  }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2021 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { ReactiveController } from 'lit';
7
+
8
+ /**
9
+ * A controller to link an input element with a slotted `<label>` element.
10
+ */
11
+ export class AriaLabelController implements ReactiveController {}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2021 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+
7
+ /**
8
+ * A controller to link an input element with a slotted `<label>` element.
9
+ */
10
+ export class AriaLabelController {
11
+ constructor(input, label) {
12
+ this.input = input;
13
+ this.label = label;
14
+ this.__preventDuplicateLabelClick = this.__preventDuplicateLabelClick.bind(this);
15
+ }
16
+
17
+ hostConnected() {
18
+ const label = this.label;
19
+ const input = this.input;
20
+
21
+ if (label) {
22
+ label.addEventListener('click', this.__preventDuplicateLabelClick);
23
+
24
+ if (input) {
25
+ input.setAttribute('aria-labelledby', label.id);
26
+ label.setAttribute('for', input.id);
27
+ }
28
+ }
29
+ }
30
+
31
+ hostDisconnected() {
32
+ const label = this.label;
33
+ if (label) {
34
+ label.removeEventListener('click', this.__preventDuplicateLabelClick);
35
+ }
36
+ }
37
+
38
+ /**
39
+ * The native platform fires an event for both the click on the label, and also
40
+ * the subsequent click on the native input element caused by label click.
41
+ * This results in two click events arriving at the host, but we only want one.
42
+ * This method prevents the duplicate click and ensures the correct isTrusted event
43
+ * with the correct event.target arrives at the host.
44
+ * @private
45
+ */
46
+ __preventDuplicateLabelClick() {
47
+ const inputClickHandler = (e) => {
48
+ e.stopImmediatePropagation();
49
+ this.input.removeEventListener('click', inputClickHandler);
50
+ };
51
+ this.input.addEventListener('click', inputClickHandler);
52
+ }
53
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2021 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { DisabledMixin } from '@vaadin/component-base/src/disabled-mixin.js';
7
+ import { DelegateStateMixin } from './delegate-state-mixin.js';
8
+ import { InputMixin } from './input-mixin.js';
9
+
10
+ /**
11
+ * A mixin to manage the checked state.
12
+ */
13
+ declare function CheckedMixin<T extends new (...args: any[]) => {}>(base: T): T & CheckedMixinConstructor;
14
+
15
+ interface CheckedMixinConstructor {
16
+ new (...args: any[]): CheckedMixin;
17
+ }
18
+
19
+ interface CheckedMixin extends DelegateStateMixin, DisabledMixin, InputMixin {}
20
+
21
+ export { CheckedMixinConstructor, CheckedMixin };
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2021 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
7
+ import { DisabledMixin } from '@vaadin/component-base/src/disabled-mixin.js';
8
+ import { DelegateStateMixin } from './delegate-state-mixin.js';
9
+ import { InputMixin } from './input-mixin.js';
10
+
11
+ /**
12
+ * A mixin to manage the checked state.
13
+ *
14
+ * @polymerMixin
15
+ * @mixes DelegateStateMixin
16
+ * @mixes DisabledMixin
17
+ * @mixes InputMixin
18
+ */
19
+ export const CheckedMixin = dedupingMixin(
20
+ (superclass) =>
21
+ class CheckedMixinClass extends DelegateStateMixin(DisabledMixin(InputMixin(superclass))) {
22
+ static get properties() {
23
+ return {
24
+ /**
25
+ * True if the element is checked.
26
+ * @type {boolean}
27
+ */
28
+ checked: {
29
+ type: Boolean,
30
+ value: false,
31
+ notify: true,
32
+ reflectToAttribute: true
33
+ }
34
+ };
35
+ }
36
+
37
+ static get delegateProps() {
38
+ return [...super.delegateProps, 'checked'];
39
+ }
40
+
41
+ /**
42
+ * @protected
43
+ * @override
44
+ */
45
+ _onChange(event) {
46
+ this._toggleChecked(event.target.checked);
47
+ }
48
+
49
+ /** @protected */
50
+ _toggleChecked(checked) {
51
+ this.checked = checked;
52
+ }
53
+ }
54
+ );
@@ -3,8 +3,8 @@
3
3
  * Copyright (c) 2021 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { FocusMixin } from './focus-mixin.js';
7
- import { DisabledMixin } from './disabled-mixin.js';
6
+ import { DisabledMixin } from '@vaadin/component-base/src/disabled-mixin.js';
7
+ import { FocusMixin } from '@vaadin/component-base/src/focus-mixin.js';
8
8
 
9
9
  /**
10
10
  * A mixin to forward focus to an element in the light DOM.
@@ -4,159 +4,176 @@
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
7
- import { FocusMixin } from './focus-mixin.js';
8
- import { DisabledMixin } from './disabled-mixin.js';
9
-
10
- const DelegateFocusMixinImplementation = (superclass) =>
11
- class DelegateFocusMixinClass extends FocusMixin(DisabledMixin(superclass)) {
12
- static get properties() {
13
- return {
14
- /**
15
- * Specify that this control should have input focus when the page loads.
16
- */
17
- autofocus: {
18
- type: Boolean
19
- },
20
-
21
- /**
22
- * A reference to the focusable element controlled by the mixin.
23
- * It can be an input, textarea, button or any element with tabindex > -1.
24
- *
25
- * Any component implementing this mixin is expected to provide it
26
- * by using `this._setFocusElement(input)` Polymer API.
27
- *
28
- * @protected
29
- * @type {!HTMLElement}
30
- */
31
- focusElement: {
32
- type: Object,
33
- readOnly: true,
34
- observer: '_focusElementChanged'
35
- }
36
- };
37
- }
38
-
39
- constructor() {
40
- super();
7
+ import { DisabledMixin } from '@vaadin/component-base/src/disabled-mixin.js';
8
+ import { FocusMixin } from '@vaadin/component-base/src/focus-mixin.js';
41
9
 
42
- this._boundOnBlur = this._onBlur.bind(this);
43
- this._boundOnFocus = this._onFocus.bind(this);
44
- }
10
+ /**
11
+ * A mixin to forward focus to an element in the light DOM.
12
+ *
13
+ * @polymerMixin
14
+ * @mixes DisabledMixin
15
+ * @mixes FocusMixin
16
+ */
17
+ export const DelegateFocusMixin = dedupingMixin(
18
+ (superclass) =>
19
+ class DelegateFocusMixinClass extends FocusMixin(DisabledMixin(superclass)) {
20
+ static get properties() {
21
+ return {
22
+ /**
23
+ * Specify that this control should have input focus when the page loads.
24
+ */
25
+ autofocus: {
26
+ type: Boolean
27
+ },
28
+
29
+ /**
30
+ * A reference to the focusable element controlled by the mixin.
31
+ * It can be an input, textarea, button or any element with tabindex > -1.
32
+ *
33
+ * Any component implementing this mixin is expected to provide it
34
+ * by using `this._setFocusElement(input)` Polymer API.
35
+ *
36
+ * @protected
37
+ * @type {!HTMLElement}
38
+ */
39
+ focusElement: {
40
+ type: Object,
41
+ readOnly: true,
42
+ observer: '_focusElementChanged'
43
+ }
44
+ };
45
+ }
45
46
 
46
- /** @protected */
47
- ready() {
48
- super.ready();
47
+ constructor() {
48
+ super();
49
49
 
50
- if (this.autofocus && !this.disabled) {
51
- requestAnimationFrame(() => {
52
- this.focus();
53
- this.setAttribute('focus-ring', '');
54
- });
50
+ this._boundOnBlur = this._onBlur.bind(this);
51
+ this._boundOnFocus = this._onFocus.bind(this);
55
52
  }
56
- }
57
53
 
58
- focus() {
59
- if (!this.focusElement || this.disabled) {
60
- return;
54
+ /** @protected */
55
+ ready() {
56
+ super.ready();
57
+
58
+ if (this.autofocus && !this.disabled) {
59
+ requestAnimationFrame(() => {
60
+ this.focus();
61
+ this.setAttribute('focus-ring', '');
62
+ });
63
+ }
61
64
  }
62
65
 
63
- this.focusElement.focus();
64
- this._setFocused(true);
65
- }
66
+ /**
67
+ * @protected
68
+ * @override
69
+ */
70
+ focus() {
71
+ if (!this.focusElement || this.disabled) {
72
+ return;
73
+ }
66
74
 
67
- blur() {
68
- if (!this.focusElement) {
69
- return;
75
+ this.focusElement.focus();
76
+ this._setFocused(true);
70
77
  }
71
- this.focusElement.blur();
72
- this._setFocused(false);
73
- }
74
78
 
75
- click() {
76
- if (this.focusElement && !this.disabled) {
77
- this.focusElement.click();
79
+ /**
80
+ * @protected
81
+ * @override
82
+ */
83
+ blur() {
84
+ if (!this.focusElement) {
85
+ return;
86
+ }
87
+ this.focusElement.blur();
88
+ this._setFocused(false);
78
89
  }
79
- }
80
90
 
81
- /** @protected */
82
- _focusElementChanged(element, oldElement) {
83
- if (element) {
84
- this._addFocusListeners(element);
85
- } else if (oldElement) {
86
- this._removeFocusListeners(oldElement);
91
+ /**
92
+ * @protected
93
+ * @override
94
+ */
95
+ click() {
96
+ if (this.focusElement && !this.disabled) {
97
+ this.focusElement.click();
98
+ }
87
99
  }
88
- }
89
-
90
- /**
91
- * @param {HTMLElement} element
92
- * @protected
93
- */
94
- _addFocusListeners(element) {
95
- element.addEventListener('blur', this._boundOnBlur);
96
- element.addEventListener('focus', this._boundOnFocus);
97
- }
98
100
 
99
- /**
100
- * @param {HTMLElement} element
101
- * @protected
102
- */
103
- _removeFocusListeners(element) {
104
- element.removeEventListener('blur', this._boundOnBlur);
105
- element.removeEventListener('focus', this._boundOnFocus);
106
- }
101
+ /** @protected */
102
+ _focusElementChanged(element, oldElement) {
103
+ if (element) {
104
+ element.disabled = this.disabled;
105
+ this._addFocusListeners(element);
106
+ } else if (oldElement) {
107
+ this._removeFocusListeners(oldElement);
108
+ }
109
+ }
107
110
 
108
- /**
109
- * Focus event does not bubble, so we dispatch it manually
110
- * on the host element to support adding focus listeners
111
- * when the focusable element is placed in light DOM.
112
- * @param {FocusEvent} event
113
- * @protected
114
- */
115
- _onFocus(event) {
116
- event.stopPropagation();
117
- this.dispatchEvent(new Event('focus'));
118
- }
111
+ /**
112
+ * @param {HTMLElement} element
113
+ * @protected
114
+ */
115
+ _addFocusListeners(element) {
116
+ element.addEventListener('blur', this._boundOnBlur);
117
+ element.addEventListener('focus', this._boundOnFocus);
118
+ }
119
119
 
120
- /**
121
- * Blur event does not bubble, so we dispatch it manually
122
- * on the host element to support adding blur listeners
123
- * when the focusable element is placed in light DOM.
124
- * @param {FocusEvent} event
125
- * @protected
126
- */
127
- _onBlur(event) {
128
- event.stopPropagation();
129
- this.dispatchEvent(new Event('blur'));
130
- }
120
+ /**
121
+ * @param {HTMLElement} element
122
+ * @protected
123
+ */
124
+ _removeFocusListeners(element) {
125
+ element.removeEventListener('blur', this._boundOnBlur);
126
+ element.removeEventListener('focus', this._boundOnFocus);
127
+ }
131
128
 
132
- /**
133
- * @param {Event} event
134
- * @return {boolean}
135
- * @protected
136
- * @override
137
- */
138
- _shouldSetFocus(event) {
139
- return event.target === this.focusElement;
140
- }
129
+ /**
130
+ * Focus event does not bubble, so we dispatch it manually
131
+ * on the host element to support adding focus listeners
132
+ * when the focusable element is placed in light DOM.
133
+ * @param {FocusEvent} event
134
+ * @protected
135
+ */
136
+ _onFocus(event) {
137
+ event.stopPropagation();
138
+ this.dispatchEvent(new Event('focus'));
139
+ }
141
140
 
142
- /**
143
- * @param {boolean} disabled
144
- * @protected
145
- */
146
- _disabledChanged(disabled) {
147
- super._disabledChanged(disabled);
141
+ /**
142
+ * Blur event does not bubble, so we dispatch it manually
143
+ * on the host element to support adding blur listeners
144
+ * when the focusable element is placed in light DOM.
145
+ * @param {FocusEvent} event
146
+ * @protected
147
+ */
148
+ _onBlur(event) {
149
+ event.stopPropagation();
150
+ this.dispatchEvent(new Event('blur'));
151
+ }
148
152
 
149
- if (this.focusElement) {
150
- this.focusElement.disabled = disabled;
153
+ /**
154
+ * @param {Event} event
155
+ * @return {boolean}
156
+ * @protected
157
+ * @override
158
+ */
159
+ _shouldSetFocus(event) {
160
+ return event.target === this.focusElement;
151
161
  }
152
162
 
153
- if (disabled) {
154
- this.blur();
163
+ /**
164
+ * @param {boolean} disabled
165
+ * @protected
166
+ */
167
+ _disabledChanged(disabled) {
168
+ super._disabledChanged(disabled);
169
+
170
+ if (this.focusElement) {
171
+ this.focusElement.disabled = disabled;
172
+ }
173
+
174
+ if (disabled) {
175
+ this.blur();
176
+ }
155
177
  }
156
178
  }
157
- };
158
-
159
- /**
160
- * A mixin to forward focus to an element in the light DOM.
161
- */
162
- export const DelegateFocusMixin = dedupingMixin(DelegateFocusMixinImplementation);
179
+ );
@@ -17,7 +17,7 @@ interface DelegateStateMixin {
17
17
  /**
18
18
  * A target element to which attributes and properties are delegated.
19
19
  */
20
- _delegateStateTarget: HTMLElement | null;
20
+ stateTarget: HTMLElement | null;
21
21
  }
22
22
 
23
23
  export { DelegateStateMixinConstructor, DelegateStateMixin };