@vaadin/details 24.0.0-alpha7 → 24.0.0-alpha8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/details",
3
- "version": "24.0.0-alpha7",
3
+ "version": "24.0.0-alpha8",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -37,12 +37,11 @@
37
37
  "dependencies": {
38
38
  "@open-wc/dedupe-mixin": "^1.3.0",
39
39
  "@polymer/polymer": "^3.0.0",
40
- "@vaadin/button": "24.0.0-alpha7",
41
- "@vaadin/component-base": "24.0.0-alpha7",
42
- "@vaadin/field-base": "24.0.0-alpha7",
43
- "@vaadin/vaadin-lumo-styles": "24.0.0-alpha7",
44
- "@vaadin/vaadin-material-styles": "24.0.0-alpha7",
45
- "@vaadin/vaadin-themable-mixin": "24.0.0-alpha7"
40
+ "@vaadin/button": "24.0.0-alpha8",
41
+ "@vaadin/component-base": "24.0.0-alpha8",
42
+ "@vaadin/vaadin-lumo-styles": "24.0.0-alpha8",
43
+ "@vaadin/vaadin-material-styles": "24.0.0-alpha8",
44
+ "@vaadin/vaadin-themable-mixin": "24.0.0-alpha8"
46
45
  },
47
46
  "devDependencies": {
48
47
  "@esm-bundle/chai": "^4.3.4",
@@ -53,5 +52,5 @@
53
52
  "web-types.json",
54
53
  "web-types.lit.json"
55
54
  ],
56
- "gitHead": "aeb4535336813636736759e0a5de148b26bfc3b6"
55
+ "gitHead": "476752249bb12295c500980d98a3256ad3b22b73"
57
56
  }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2019 - 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { SlotChildObserveController } from '@vaadin/component-base/src/slot-child-observe-controller.js';
7
+
8
+ /**
9
+ * A controller to manage the default content slot.
10
+ */
11
+ export class ContentController extends SlotChildObserveController {}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2019 - 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { SlotChildObserveController } from '@vaadin/component-base/src/slot-child-observe-controller.js';
7
+
8
+ /**
9
+ * A controller to manage the default content slot.
10
+ */
11
+ export class ContentController extends SlotChildObserveController {
12
+ /**
13
+ * Override method from `SlotController` to change
14
+ * the ID prefix for the default slot content.
15
+ *
16
+ * @param {HTMLElement} host
17
+ * @return {string}
18
+ * @protected
19
+ * @override
20
+ */
21
+ static generateId(host) {
22
+ return super.generateId(host, 'content');
23
+ }
24
+
25
+ constructor(host) {
26
+ super(host, '', null, { multiple: true });
27
+ }
28
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2019 - 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { SlotChildObserveController } from '@vaadin/component-base/src/slot-child-observe-controller.js';
7
+
8
+ /**
9
+ * A controller to manage the summary element.
10
+ */
11
+ export class SummaryController extends SlotChildObserveController {
12
+ /**
13
+ * String used for the summary.
14
+ */
15
+ protected summary: string | null | undefined;
16
+
17
+ /**
18
+ * Set summary based on corresponding host property.
19
+ */
20
+ setSummary(label: string | null | undefined): void;
21
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2019 - 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { SlotChildObserveController } from '@vaadin/component-base/src/slot-child-observe-controller.js';
7
+
8
+ /**
9
+ * A controller to manage the summary element.
10
+ */
11
+ export class SummaryController extends SlotChildObserveController {
12
+ constructor(host, tagName) {
13
+ super(host, 'summary', tagName);
14
+ }
15
+
16
+ /**
17
+ * Set summary based on corresponding host property.
18
+ *
19
+ * @param {string} summary
20
+ */
21
+ setSummary(summary) {
22
+ this.summary = summary;
23
+
24
+ // Restore the default summary, if needed.
25
+ const summaryNode = this.getSlotChild();
26
+ if (!summaryNode) {
27
+ this.restoreDefaultNode();
28
+ }
29
+
30
+ // When default summary is used, update it.
31
+ if (this.node === this.defaultNode) {
32
+ this.updateDefaultNode(this.node);
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Override method inherited from `SlotChildObserveController`
38
+ * to restore and observe the default summary element.
39
+ *
40
+ * @protected
41
+ * @override
42
+ */
43
+ restoreDefaultNode() {
44
+ const { summary } = this;
45
+
46
+ // Restore the default summary.
47
+ if (summary && summary.trim() !== '') {
48
+ this.attachDefaultNode();
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Override method inherited from `SlotChildObserveController`
54
+ * to update the default summary element text content.
55
+ *
56
+ * @param {Node | undefined} node
57
+ * @protected
58
+ * @override
59
+ */
60
+ updateDefaultNode(node) {
61
+ if (node) {
62
+ node.textContent = this.summary;
63
+ }
64
+
65
+ // Notify the host after update.
66
+ super.updateDefaultNode(node);
67
+ }
68
+ }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import type { Constructor } from '@open-wc/dedupe-mixin';
@@ -20,9 +20,4 @@ export declare class DetailsMixinClass {
20
20
  * List of elements passed to the details default slot.
21
21
  */
22
22
  protected _contentElements: HTMLElement[];
23
-
24
- /**
25
- * An element used to toggle the content visibility.
26
- */
27
- protected _toggleElement: HTMLElement;
28
23
  }
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2019 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2019 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+ import { ContentController } from './content-controller.js';
6
7
 
7
8
  /**
8
9
  * A mixin providing common details functionality.
@@ -32,53 +33,47 @@ export const DetailsMixin = (superClass) =>
32
33
  _contentElements: {
33
34
  type: Array,
34
35
  },
35
-
36
- /**
37
- * An element used to toggle the content visibility.
38
- *
39
- * @type {!HTMLElement | undefined}
40
- * @protected
41
- */
42
- _toggleElement: {
43
- type: Object,
44
- observer: '_toggleElementChanged',
45
- },
46
36
  };
47
37
  }
48
38
 
49
39
  static get observers() {
50
- return ['_openedOrToggleChanged(opened, _toggleElement)', '_openedOrContentChanged(opened, _contentElements)'];
40
+ return ['_openedOrContentChanged(opened, _contentElements)'];
51
41
  }
52
42
 
53
- /** @private */
54
- _openedOrContentChanged(opened, elements) {
55
- if (elements) {
56
- elements.forEach((el) => {
57
- el.setAttribute('aria-hidden', opened ? 'false' : 'true');
58
- });
59
- }
43
+ constructor() {
44
+ super();
45
+
46
+ this._contentController = new ContentController(this);
47
+
48
+ this._contentController.addEventListener('slot-content-changed', (event) => {
49
+ const content = event.target.nodes || [];
50
+
51
+ // Exclude nodes that are no longer connected
52
+ this._contentElements = content.filter((node) => node.parentNode === this);
53
+ });
60
54
  }
61
55
 
62
- /** @private */
63
- _openedOrToggleChanged(opened, toggleElement) {
64
- if (toggleElement) {
65
- toggleElement.setAttribute('aria-expanded', opened ? 'true' : 'false');
66
- }
56
+ /** @protected */
57
+ ready() {
58
+ super.ready();
59
+
60
+ this.addController(this._contentController);
61
+
62
+ // Only handle click and not keydown, because `vaadin-details-summary` uses `ButtonMixin`
63
+ // that already covers this logic, and `vaadin-accordion-heading` uses native `<button>`.
64
+ this.addEventListener('click', (event) => {
65
+ if (event.target === this.focusElement) {
66
+ this.opened = !this.opened;
67
+ }
68
+ });
67
69
  }
68
70
 
69
71
  /** @private */
70
- _toggleElementChanged(toggleElement) {
71
- if (toggleElement) {
72
- // Only handle click and not keydown, because `vaadin-details-summary` uses `ButtonMixin`
73
- // that already covers this logic, and `vaadin-accordion-heading` uses native `<button>`.
74
- toggleElement.addEventListener('click', () => {
75
- this._toggle();
72
+ _openedOrContentChanged(opened, elements) {
73
+ if (elements) {
74
+ elements.forEach((el) => {
75
+ el.setAttribute('aria-hidden', opened ? 'false' : 'true');
76
76
  });
77
77
  }
78
78
  }
79
-
80
- /** @private */
81
- _toggle() {
82
- this.opened = !this.opened;
83
- }
84
79
  };
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2017 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2017 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2019 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2019 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
7
+ import { DelegateFocusMixin } from '@vaadin/component-base/src/delegate-focus-mixin.js';
8
+ import { DelegateStateMixin } from '@vaadin/component-base/src/delegate-state-mixin.js';
7
9
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
8
- import { DelegateFocusMixin } from '@vaadin/field-base/src/delegate-focus-mixin.js';
9
- import { DelegateStateMixin } from '@vaadin/field-base/src/delegate-state-mixin.js';
10
10
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
11
11
  import { DetailsMixin } from './vaadin-details-mixin.js';
12
12
 
@@ -61,6 +61,12 @@ export type DetailsEventMap = DetailsCustomEventMap & HTMLElementEventMap;
61
61
  declare class Details extends DetailsMixin(
62
62
  DelegateStateMixin(DelegateFocusMixin(ElementMixin(ThemableMixin(ControllerMixin(HTMLElement))))),
63
63
  ) {
64
+ /**
65
+ * A text that is displayed in the summary, if no
66
+ * element is assigned to the `summary` slot.
67
+ */
68
+ summary: string | null | undefined;
69
+
64
70
  addEventListener<K extends keyof DetailsEventMap>(
65
71
  type: K,
66
72
  listener: (this: Details, ev: DetailsEventMap[K]) => void,
@@ -1,52 +1,19 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2019 - 2022 Vaadin Ltd.
3
+ * Copyright (c) 2019 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import './vaadin-details-summary.js';
7
7
  import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
8
8
  import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
9
+ import { DelegateFocusMixin } from '@vaadin/component-base/src/delegate-focus-mixin.js';
10
+ import { DelegateStateMixin } from '@vaadin/component-base/src/delegate-state-mixin.js';
9
11
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
10
- import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
11
- import { SlotObserveController } from '@vaadin/component-base/src/slot-observe-controller.js';
12
12
  import { TooltipController } from '@vaadin/component-base/src/tooltip-controller.js';
13
- import { DelegateFocusMixin } from '@vaadin/field-base/src/delegate-focus-mixin.js';
14
- import { DelegateStateMixin } from '@vaadin/field-base/src/delegate-state-mixin.js';
15
13
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
14
+ import { SummaryController } from './summary-controller.js';
16
15
  import { DetailsMixin } from './vaadin-details-mixin.js';
17
16
 
18
- class SummaryController extends SlotController {
19
- constructor(host) {
20
- super(host, 'summary', 'vaadin-details-summary', {
21
- useUniqueId: true,
22
- initializer: (node, host) => {
23
- host._toggleElement = node;
24
- host._setFocusElement(node);
25
- host.stateTarget = node;
26
- },
27
- });
28
- }
29
- }
30
-
31
- class ContentController extends SlotObserveController {
32
- /**
33
- * Override method from `SlotController` to change
34
- * the ID prefix for the default slot content.
35
- *
36
- * @param {HTMLElement} host
37
- * @return {string}
38
- * @protected
39
- * @override
40
- */
41
- static generateId(host) {
42
- return super.generateId(host, 'content');
43
- }
44
-
45
- constructor(host) {
46
- super(host, '', null, { multiple: true });
47
- }
48
- }
49
-
50
17
  /**
51
18
  * `<vaadin-details>` is a Web Component which the creates an
52
19
  * expandable panel similar to `<details>` HTML element.
@@ -86,6 +53,7 @@ class ContentController extends SlotObserveController {
86
53
  *
87
54
  * @extends HTMLElement
88
55
  * @mixes ControllerMixin
56
+ * @mixes DetailsMixin
89
57
  * @mixes DelegateFocusMixin
90
58
  * @mixes DelegateStateMixin
91
59
  * @mixes ElementMixin
@@ -128,6 +96,23 @@ class Details extends DetailsMixin(
128
96
  return 'vaadin-details';
129
97
  }
130
98
 
99
+ static get properties() {
100
+ return {
101
+ /**
102
+ * A text that is displayed in the summary, if no
103
+ * element is assigned to the `summary` slot.
104
+ */
105
+ summary: {
106
+ type: String,
107
+ observer: '_summaryChanged',
108
+ },
109
+ };
110
+ }
111
+
112
+ static get observers() {
113
+ return ['__updateAriaControls(focusElement, _contentElements)', '__updateAriaExpanded(focusElement, opened)'];
114
+ }
115
+
131
116
  static get delegateAttrs() {
132
117
  return ['theme'];
133
118
  }
@@ -136,13 +121,29 @@ class Details extends DetailsMixin(
136
121
  return ['disabled', 'opened'];
137
122
  }
138
123
 
124
+ constructor() {
125
+ super();
126
+
127
+ this._summaryController = new SummaryController(this, 'vaadin-details-summary');
128
+ this._summaryController.addEventListener('slot-content-changed', (event) => {
129
+ const { node } = event.target;
130
+
131
+ this._setFocusElement(node);
132
+ this.stateTarget = node;
133
+
134
+ this._tooltipController.setTarget(node);
135
+ });
136
+
137
+ this._tooltipController = new TooltipController(this);
138
+ this._tooltipController.setPosition('bottom-start');
139
+ }
140
+
139
141
  /** @protected */
140
142
  ready() {
141
143
  super.ready();
142
144
 
143
- this._initSummary();
144
- this._initContent();
145
- this._initTooltip();
145
+ this.addController(this._summaryController);
146
+ this.addController(this._tooltipController);
146
147
  }
147
148
 
148
149
  /**
@@ -157,35 +158,28 @@ class Details extends DetailsMixin(
157
158
  }
158
159
 
159
160
  /** @private */
160
- _initSummary() {
161
- this._summaryController = new SummaryController(this);
162
- this.addController(this._summaryController);
161
+ _summaryChanged(summary) {
162
+ this._summaryController.setSummary(summary);
163
163
  }
164
164
 
165
165
  /** @private */
166
- _initContent() {
167
- this._contentController = new ContentController(this);
168
- this._contentController.addEventListener('slot-content-changed', (event) => {
169
- // Store nodes to toggle `aria-hidden` attribute
170
- const { nodes } = event.target;
171
- this._contentElements = nodes;
172
-
173
- if (nodes[0] && nodes[0].id) {
174
- this._toggleElement.setAttribute('aria-controls', nodes[0].id);
166
+ __updateAriaControls(summary, contentElements) {
167
+ if (summary && contentElements) {
168
+ const node = contentElements[0];
169
+
170
+ if (node && node.id) {
171
+ summary.setAttribute('aria-controls', node.id);
175
172
  } else {
176
- this._toggleElement.removeAttribute('aria-controls');
173
+ summary.removeAttribute('aria-controls');
177
174
  }
178
- });
179
- this.addController(this._contentController);
175
+ }
180
176
  }
181
177
 
182
178
  /** @private */
183
- _initTooltip() {
184
- this._tooltipController = new TooltipController(this);
185
- this.addController(this._tooltipController);
186
-
187
- this._tooltipController.setTarget(this._toggleElement);
188
- this._tooltipController.setPosition('bottom-start');
179
+ __updateAriaExpanded(focusElement, opened) {
180
+ if (focusElement) {
181
+ focusElement.setAttribute('aria-expanded', opened ? 'true' : 'false');
182
+ }
189
183
  }
190
184
  }
191
185
 
package/web-types.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/details",
4
- "version": "24.0.0-alpha7",
4
+ "version": "24.0.0-alpha8",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
@@ -76,6 +76,15 @@
76
76
  "name": "vaadin-details",
77
77
  "description": "`<vaadin-details>` is a Web Component which the creates an\nexpandable panel similar to `<details>` HTML element.\n\n```\n<vaadin-details>\n <vaadin-details-summary slot=\"summary\">Expandable Details</vaadin-details-summary>\n <div>\n Toggle using mouse, Enter and Space keys.\n </div>\n</vaadin-details>\n```\n\n### Styling\n\nThe following shadow DOM parts are exposed for styling:\n\nPart name | Description\n-----------------|----------------\n`summary` | The element used to open and close collapsible content.\n`toggle` | The element used as indicator, can represent an icon.\n`summary-content`| The wrapper for the slotted summary content.\n`content` | The wrapper for the collapsible details content.\n\nThe following attributes are exposed for styling:\n\nAttribute | Description\n-------------| -----------\n`opened` | Set when the collapsible content is expanded and visible.\n`disabled` | Set when the element is disabled.\n`focus-ring` | Set when the element is focused using the keyboard.\n`focused` | Set when the element is focused.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.",
78
78
  "attributes": [
79
+ {
80
+ "name": "opened",
81
+ "description": "If true, the collapsible content is visible.",
82
+ "value": {
83
+ "type": [
84
+ "boolean"
85
+ ]
86
+ }
87
+ },
79
88
  {
80
89
  "name": "disabled",
81
90
  "description": "If true, the user cannot interact with this element.",
@@ -98,6 +107,17 @@
98
107
  ]
99
108
  }
100
109
  },
110
+ {
111
+ "name": "summary",
112
+ "description": "A text that is displayed in the summary, if no\nelement is assigned to the `summary` slot.",
113
+ "value": {
114
+ "type": [
115
+ "string",
116
+ "null",
117
+ "undefined"
118
+ ]
119
+ }
120
+ },
101
121
  {
102
122
  "name": "theme",
103
123
  "description": "The theme variants to apply to the component.",
@@ -112,6 +132,15 @@
112
132
  ],
113
133
  "js": {
114
134
  "properties": [
135
+ {
136
+ "name": "opened",
137
+ "description": "If true, the collapsible content is visible.",
138
+ "value": {
139
+ "type": [
140
+ "boolean"
141
+ ]
142
+ }
143
+ },
115
144
  {
116
145
  "name": "disabled",
117
146
  "description": "If true, the user cannot interact with this element.",
@@ -135,45 +164,23 @@
135
164
  }
136
165
  },
137
166
  {
138
- "name": "rootPath",
139
- "description": "",
167
+ "name": "summary",
168
+ "description": "A text that is displayed in the summary, if no\nelement is assigned to the `summary` slot.",
140
169
  "value": {
141
170
  "type": [
142
- "string"
143
- ]
144
- }
145
- },
146
- {
147
- "name": "importPath",
148
- "description": "",
149
- "value": {
150
- "type": [
151
- "string"
152
- ]
153
- }
154
- },
155
- {
156
- "name": "root",
157
- "description": "",
158
- "value": {
159
- "type": [
160
- "StampedTemplate",
161
- "HTMLElement",
162
- "ShadowRoot"
163
- ]
164
- }
165
- },
166
- {
167
- "name": "$",
168
- "description": "",
169
- "value": {
170
- "type": [
171
- "Object.<string, Element>"
171
+ "string",
172
+ "null",
173
+ "undefined"
172
174
  ]
173
175
  }
174
176
  }
175
177
  ],
176
- "events": []
178
+ "events": [
179
+ {
180
+ "name": "opened-changed",
181
+ "description": "Fired when the `opened` property changes."
182
+ }
183
+ ]
177
184
  }
178
185
  }
179
186
  ]
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/details",
4
- "version": "24.0.0-alpha7",
4
+ "version": "24.0.0-alpha8",
5
5
  "description-markup": "markdown",
6
6
  "framework": "lit",
7
7
  "framework-config": {
@@ -41,43 +41,36 @@
41
41
  "extension": true,
42
42
  "attributes": [
43
43
  {
44
- "name": "?disabled",
45
- "description": "If true, the user cannot interact with this element.",
46
- "value": {
47
- "kind": "expression"
48
- }
49
- },
50
- {
51
- "name": "?autofocus",
52
- "description": "Specify that this control should have input focus when the page loads.",
44
+ "name": "?opened",
45
+ "description": "If true, the collapsible content is visible.",
53
46
  "value": {
54
47
  "kind": "expression"
55
48
  }
56
49
  },
57
50
  {
58
- "name": ".rootPath",
59
- "description": "",
51
+ "name": "?disabled",
52
+ "description": "If true, the user cannot interact with this element.",
60
53
  "value": {
61
54
  "kind": "expression"
62
55
  }
63
56
  },
64
57
  {
65
- "name": ".importPath",
66
- "description": "",
58
+ "name": "?autofocus",
59
+ "description": "Specify that this control should have input focus when the page loads.",
67
60
  "value": {
68
61
  "kind": "expression"
69
62
  }
70
63
  },
71
64
  {
72
- "name": ".root",
73
- "description": "",
65
+ "name": ".summary",
66
+ "description": "A text that is displayed in the summary, if no\nelement is assigned to the `summary` slot.",
74
67
  "value": {
75
68
  "kind": "expression"
76
69
  }
77
70
  },
78
71
  {
79
- "name": ".$",
80
- "description": "",
72
+ "name": "@opened-changed",
73
+ "description": "Fired when the `opened` property changes.",
81
74
  "value": {
82
75
  "kind": "expression"
83
76
  }