kemet-ui 0.2.0 → 1.0.0

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 (66) hide show
  1. package/custom-elements.json +5546 -855
  2. package/dist/components/kemet-accordion-panel.js +178 -0
  3. package/dist/components/kemet-accordion.js +105 -72
  4. package/dist/components/kemet-badge.js +102 -0
  5. package/dist/components/kemet-button.js +230 -0
  6. package/dist/components/kemet-checkbox.js +298 -0
  7. package/dist/components/kemet-combo.js +207 -0
  8. package/dist/components/kemet-count.js +112 -0
  9. package/dist/components/kemet-draggable.js +19 -6
  10. package/dist/components/kemet-drawer.js +38 -15
  11. package/dist/components/kemet-drawer.styles.js +6 -0
  12. package/dist/components/kemet-field.js +233 -0
  13. package/dist/components/kemet-flipcard-trigger.js +4 -5
  14. package/dist/components/kemet-flipcard.js +26 -3
  15. package/dist/components/kemet-icon.js +19 -3
  16. package/dist/components/kemet-input.js +650 -0
  17. package/dist/components/kemet-modal-close.js +23 -4
  18. package/dist/components/kemet-modal.js +78 -13
  19. package/dist/components/kemet-modal.styles.js +14 -2
  20. package/dist/components/kemet-option.js +45 -0
  21. package/dist/components/kemet-popover-close.js +1 -1
  22. package/dist/components/kemet-popover.js +75 -12
  23. package/dist/components/kemet-radio.js +214 -0
  24. package/dist/components/kemet-radios.js +218 -0
  25. package/dist/components/kemet-rotator.js +23 -4
  26. package/dist/components/kemet-scroll-link.js +21 -2
  27. package/dist/components/kemet-scroll-nav.js +25 -2
  28. package/dist/components/kemet-scroll-snap-paginator.js +68 -26
  29. package/dist/components/kemet-scroll-snap-slide.js +23 -13
  30. package/dist/components/kemet-scroll-snap.js +31 -16
  31. package/dist/components/kemet-select.js +365 -0
  32. package/dist/components/kemet-svg.js +18 -2
  33. package/dist/components/kemet-svgs.js +7 -3
  34. package/dist/components/kemet-tab-panel.js +15 -1
  35. package/dist/components/kemet-tab.js +48 -1
  36. package/dist/components/kemet-tabs.js +289 -83
  37. package/dist/components/kemet-tabs.styles.js +200 -0
  38. package/dist/components/kemet-textarea.js +395 -0
  39. package/dist/components/kemet-toggle.js +225 -0
  40. package/dist/kemet-components.cjs +5128 -1200
  41. package/dist/kemet-components.js +5117 -1173
  42. package/dist/kemet-components.min.js +1536 -421
  43. package/dist/styles/kemet.components.css +12 -260
  44. package/dist/styles/kemet.components.css.map +1 -1
  45. package/dist/styles/kemet.core.css +2371 -503
  46. package/dist/styles/kemet.core.css.map +1 -1
  47. package/dist/styles/scss/components/_config.scss +0 -25
  48. package/dist/styles/scss/components/accordion.scss +4 -53
  49. package/dist/styles/scss/components/modal.scss +5 -9
  50. package/dist/styles/scss/components/scrollsnap.scss +0 -57
  51. package/dist/styles/scss/core/_config.scss +160 -3
  52. package/dist/styles/scss/core/_helpers.scss +109 -2
  53. package/dist/styles/scss/core/attributes.scss +16 -0
  54. package/dist/styles/scss/core/base.scss +38 -0
  55. package/dist/styles/scss/core/layout.scss +6 -5
  56. package/dist/styles/scss/kemet.components.scss +0 -2
  57. package/dist/styles/scss/kemet.core.scss +1 -2
  58. package/package.json +34 -56
  59. package/dist/components/kemet-carousel-link.js +0 -54
  60. package/dist/components/kemet-carousel-next.js +0 -46
  61. package/dist/components/kemet-carousel-prev.js +0 -46
  62. package/dist/components/kemet-carousel-slide.js +0 -83
  63. package/dist/components/kemet-carousel.js +0 -236
  64. package/dist/components/kemet-ratio.js +0 -61
  65. package/dist/styles/scss/components/flipcard.scss +0 -14
  66. package/dist/styles/scss/components/tabs.scss +0 -73
@@ -1,12 +1,23 @@
1
1
  import { html, css, LitElement } from 'lit';
2
2
 
3
- export class KemetScrollSnap extends LitElement {
3
+ export default class KemetScrollSnap extends LitElement {
4
4
  static get styles() {
5
5
  return css`
6
+ *,
7
+ *::after,
8
+ *::before {
9
+ box-sizing: border-box;
10
+ }
11
+
6
12
  :host {
7
13
  display: flex;
8
- width: 100%;
9
14
  flex-direction: column;
15
+ width: 100%;
16
+ }
17
+
18
+ :host([axis='horizontal']) {
19
+ margin: auto;
20
+ max-width: var(--kemet-scroll-snap-horizontal-max-width, 1024px);
10
21
  }
11
22
 
12
23
  :host([pagination="left"]),
@@ -26,9 +37,8 @@ export class KemetScrollSnap extends LitElement {
26
37
 
27
38
  ::slotted([slot="slides"]) {
28
39
  display: flex;
29
- gap: var(--kemet-scroll-snap-gap, 0);
40
+ gap: var(--kemet-scroll-snap-gap, 1.5rem);
30
41
  scroll-snap-type: x mandatory;
31
-
32
42
  overflow-x: scroll;
33
43
  }
34
44
 
@@ -41,38 +51,36 @@ export class KemetScrollSnap extends LitElement {
41
51
  flex-direction: column;
42
52
  overflow-x: hidden;
43
53
  scroll-snap-type: y mandatory;
54
+ padding: var(--kemet-scroll-snap-slides-vertical-padding, 0 2rem);
44
55
  }
45
56
  `;
46
57
  }
47
58
 
48
59
  static get properties() {
49
60
  return {
61
+ /**
62
+ * Determines the direction the component flows. Values include: (horizontal|vertical)
63
+ */
50
64
  axis: {
51
65
  type: String,
52
66
  reflect: true,
53
67
  },
68
+ /**
69
+ * Determines where to display the paginator. Values include: (top | right | bottom | left)
70
+ */
54
71
  pagination: {
55
72
  type: String,
56
73
  reflect: true,
57
74
  },
58
- isTouchDevice: {
59
- type: Boolean,
60
- reflect: true,
61
- attribute: 'is-touch-device',
62
- },
63
- slides: {
64
- type: Array,
65
- },
66
75
  };
67
76
  }
68
77
 
69
78
  constructor() {
70
79
  super();
71
80
 
81
+ // managed properties
72
82
  this.axis = 'horizontal';
73
83
  this.pagination = 'bottom';
74
- this.isTouchDevice = 'ontouchstart' in document.documentElement;
75
- this.slides = [];
76
84
 
77
85
  this.addEventListener('kemet-scroll-snap-focus', (event) => {
78
86
  this.focusSlide(event.detail);
@@ -80,6 +88,10 @@ export class KemetScrollSnap extends LitElement {
80
88
  }
81
89
 
82
90
  firstUpdated() {
91
+ // standard properties
92
+ this.isTouchDevice = 'ontouchstart' in document.documentElement;
93
+ this.slides = [];
94
+
83
95
  this.setFocusedSlides();
84
96
  }
85
97
 
@@ -134,7 +146,6 @@ export class KemetScrollSnap extends LitElement {
134
146
  const slide = element;
135
147
 
136
148
  slide.index = index;
137
-
138
149
  slides.push({
139
150
  id: index,
140
151
  focused: slide.focused,
@@ -144,6 +155,9 @@ export class KemetScrollSnap extends LitElement {
144
155
 
145
156
  this.slides = slides;
146
157
 
158
+ /**
159
+ * Fires when slide data has been created.
160
+ */
147
161
  this.dispatchEvent(new CustomEvent('kemet-scroll-snap-make-slides', {
148
162
  bubbles: true,
149
163
  composed: true,
@@ -163,4 +177,5 @@ export class KemetScrollSnap extends LitElement {
163
177
  }
164
178
  }
165
179
 
166
- window.customElements.define('kemet-scroll-snap', KemetScrollSnap);
180
+ // eslint-disable-next-line no-unused-expressions
181
+ customElements.get('kemet-scroll-snap') || customElements.define('kemet-scroll-snap', KemetScrollSnap);
@@ -0,0 +1,365 @@
1
+ import { html, css, LitElement } from 'lit';
2
+ import { FormSubmitController } from '../../utilities/controllers/forms.js';
3
+
4
+ export default class KemetSelect extends LitElement {
5
+ static get styles() {
6
+ return [
7
+ css`
8
+ :host {
9
+ position: relative;
10
+ display: block;
11
+ }
12
+
13
+ select {
14
+ display: block;
15
+ font-size: 1rem;
16
+ width: 100%;
17
+ padding: var(--kemet-select-padding, 1rem);
18
+ border: var(--kemet-select-border, 1px solid var(--kemet-color-primary));
19
+ appearance: none;
20
+ box-sizing: border-box;
21
+ background-color: transparent;
22
+ }
23
+
24
+ :host([status='error']) select {
25
+ border: var(--kemet-select-border-color-error, 1px solid var(--kemet-color-error));
26
+ }
27
+
28
+ :host([status='success']) select {
29
+ border: var(--kemet-select-border-color-success, 1px solid var(--kemet-color-success));
30
+ }
31
+
32
+ :host([status='warning']) select {
33
+ border: var(--kemet-select-border-color-warning, 1px solid var(--kemet-color-warning));
34
+ }
35
+
36
+ :host([disabled]) select {
37
+ opacity: 0.5;
38
+ }
39
+
40
+ :host([rounded]) select {
41
+ border-radius: var(--kemet-select-border-radius-rounded, var(--kemet-border-radius));
42
+ }
43
+
44
+ :host([filled]) select {
45
+ border: var(--kemet-select-border-filled, none);
46
+ color: var(--kemet-select-color-filled, var(--kemet-color-white));
47
+ background-color: var(--kemet-select-background-color-filled, var(--kemet-color-primary));
48
+ }
49
+
50
+ :host([filled]) kemet-icon {
51
+ color: var(--kemet-select-color-filled, var(--kemet-color-white));
52
+ }
53
+
54
+ :host([status='error'][filled]) select {
55
+ background-color: var(--kemet-select-background-color-error, var(--kemet-color-error));
56
+ }
57
+
58
+ :host([status='success'][filled]) select {
59
+ background-color: var(--kemet-select-background-color-success, var(--kemet-color-success));
60
+ }
61
+
62
+ :host([status='warning'][filled]) select {
63
+ background-color: var(--kemet-select-background-color-warning, var(--kemet-color-warning));
64
+ }
65
+
66
+ kemet-icon {
67
+ position: absolute;
68
+ right: var(--kemet-select-icon-right, 1rem);
69
+ top: 50%;
70
+ transform: translateY(-50%);
71
+ }
72
+ `,
73
+ ];
74
+ }
75
+
76
+ static get properties() {
77
+ return {
78
+ /**
79
+ * A string the uniquely identifies the select
80
+ */
81
+ slug: {
82
+ type: String,
83
+ },
84
+ /**
85
+ * The name of the select
86
+ */
87
+ name: {
88
+ type: String,
89
+ },
90
+ /**
91
+ * The value of the select
92
+ */
93
+ value: {
94
+ type: String,
95
+ },
96
+ /**
97
+ * The options the select contains
98
+ */
99
+ options: {
100
+ type: Array,
101
+ },
102
+ /**
103
+ * The status of the select
104
+ */
105
+ status: {
106
+ type: String,
107
+ reflect: true,
108
+ },
109
+ /**
110
+ * Determines whether or not the field is required
111
+ */
112
+ required: {
113
+ type: Boolean,
114
+ reflect: true,
115
+ },
116
+ /**
117
+ * Determines whether or not the field is disabled
118
+ */
119
+ disabled: {
120
+ type: Boolean,
121
+ reflect: true,
122
+ },
123
+ /**
124
+ * Support of multiple choice selections
125
+ */
126
+ multiple: {
127
+ type: Boolean,
128
+ },
129
+ /**
130
+ * The dropdown icon
131
+ */
132
+ icon: {
133
+ type: String,
134
+ },
135
+ /**
136
+ * The dropdown icon size
137
+ */
138
+ iconSize: {
139
+ type: Number,
140
+ attribute: 'icon-size',
141
+ },
142
+ /**
143
+ * Displays a filled select
144
+ */
145
+ filled: {
146
+ type: Boolean,
147
+ reflect: true,
148
+ },
149
+ /**
150
+ * Displays rounded corners
151
+ */
152
+ rounded: {
153
+ type: Boolean,
154
+ reflect: true,
155
+ },
156
+ };
157
+ }
158
+
159
+ constructor() {
160
+ super();
161
+
162
+ // managed properties
163
+ this.name = 'select';
164
+ this.icon = 'chevron-down';
165
+ this.iconSize = 16;
166
+
167
+ /**
168
+ * Used only for form reactive controller
169
+ */
170
+ this.formSubmitController = new FormSubmitController(this);
171
+
172
+ // elements
173
+ this.control = this.closest('kemet-field');
174
+ }
175
+
176
+ firstUpdated() {
177
+ // elements
178
+ this.select = this.shadowRoot.querySelector('select');
179
+ this.selectedOption = this.querySelector('[selected]');
180
+
181
+ this.value = this.selecltedOption ? this.selectedOption.value : '';
182
+ }
183
+
184
+ render() {
185
+ return html`
186
+ <select
187
+ part="select"
188
+ id=${this.slug}
189
+ name=${this.name}
190
+ ?required=${this.required}
191
+ ?disabled=${this.disabled}
192
+ ?multiple=${this.multiple}
193
+ @change=${this.handleChange}
194
+ @focus=${this.handleFocus}
195
+ @blur=${this.handleBlur}
196
+ @invalid=${this.handleInvalid}
197
+ >
198
+ ${this.makeOptions()}
199
+ </select>
200
+ ${this.makeIcon()}
201
+ <slot @slotchange=${() => this.makeOptions()}></slot>
202
+ `;
203
+ }
204
+
205
+ /**
206
+ * Generates the option elements
207
+ * @private
208
+ * @returns {TemplateResult} An option element
209
+ */
210
+ makeOptions() {
211
+ this.options = [];
212
+ this.optionElements = this.querySelectorAll('kemet-option');
213
+
214
+ this.optionElements.forEach((option) => {
215
+ // if (index === 0) this.value = option.value;
216
+ // this.value = option.selected ? option.value : this.value;
217
+ this.options = this.options.concat({
218
+ label: option.label,
219
+ value: option.value,
220
+ disabled: option.disabled,
221
+ selected: option.selected,
222
+ });
223
+ });
224
+
225
+ return this.options.map(
226
+ option => html`<option value=${option.value} ?disabled=${option.disabled} ?selected=${option.selected}>
227
+ ${option.label}
228
+ </option>`,
229
+ );
230
+ }
231
+
232
+ /**
233
+ * Generates an dropdown icon
234
+ * @private
235
+ */
236
+ makeIcon() {
237
+ if (this.icon || this.icon !== '') {
238
+ return html`<kemet-icon icon=${this.icon} size=${this.iconSize}></kemet-icon>`;
239
+ }
240
+
241
+ return null;
242
+ }
243
+
244
+ /**
245
+ * Handles when the input receives focus
246
+ * @private
247
+ */
248
+ handleFocus() {
249
+ this.hasFocus = true;
250
+
251
+ /**
252
+ * Fires when the input receives and loses focus
253
+ */
254
+ this.dispatchEvent(
255
+ new CustomEvent('kemet-input-focused', {
256
+ bubbles: true,
257
+ composed: true,
258
+ detail: true,
259
+ }),
260
+ );
261
+ }
262
+
263
+ /**
264
+ * Handles when the input loses focus
265
+ * @private
266
+ */
267
+ handleBlur() {
268
+ this.hasFocus = false;
269
+
270
+ /**
271
+ * Fires when the input receives and loses focus
272
+ */
273
+ this.dispatchEvent(
274
+ new CustomEvent('kemet-input-focused', {
275
+ bubbles: true,
276
+ composed: true,
277
+ detail: false,
278
+ }),
279
+ );
280
+
281
+ this.select.checkValidity();
282
+
283
+ if (!this.select.checkValidity()) {
284
+ this.invalid = true;
285
+ this.status = 'error';
286
+ this.control.status = 'error';
287
+
288
+ this.dispatchEvent(
289
+ new CustomEvent('kemet-input-status', {
290
+ bubbles: true,
291
+ composed: true,
292
+ detail: {
293
+ status: 'error',
294
+ validity: this.select.validity,
295
+ element: this,
296
+ },
297
+ }),
298
+ );
299
+ }
300
+ }
301
+
302
+ /**
303
+ * Handles when the input changes value
304
+ * @private
305
+ */
306
+ handleChange() {
307
+ this.value = this.select.value;
308
+
309
+ if (this.select.checkValidity()) {
310
+ this.invalid = false;
311
+ this.status = 'standard';
312
+
313
+ /**
314
+ * Fires when there's a change in status
315
+ */
316
+ this.dispatchEvent(
317
+ new CustomEvent('kemet-input-status', {
318
+ bubbles: true,
319
+ composed: true,
320
+ detail: {
321
+ status: 'standard',
322
+ validity: this.select.validity,
323
+ element: this,
324
+ },
325
+ }),
326
+ );
327
+ }
328
+ }
329
+
330
+ /**
331
+ * Handles when the input has an error
332
+ * @private
333
+ */
334
+ handleInvalid() {
335
+ this.invalid = true;
336
+ this.status = 'error';
337
+
338
+ /**
339
+ * Fires when there's a change in status
340
+ */
341
+ this.dispatchEvent(
342
+ new CustomEvent('kemet-input-status', {
343
+ bubbles: true,
344
+ composed: true,
345
+ detail: {
346
+ status: 'error',
347
+ validity: this.select.validity,
348
+ element: this,
349
+ },
350
+ }),
351
+ );
352
+ }
353
+
354
+ /**
355
+ * Checks the validity of the standard select
356
+ * @public
357
+ * @returns {boolean}
358
+ */
359
+ checkValidity() {
360
+ this.select.checkValidity();
361
+ }
362
+ }
363
+
364
+ // eslint-disable-next-line no-unused-expressions
365
+ customElements.get('kemet-select') || customElements.define('kemet-select', KemetSelect);
@@ -1,6 +1,6 @@
1
1
  import { html, css, LitElement } from 'lit';
2
2
 
3
- export class KemetSVG extends LitElement {
3
+ export default class KemetSVG extends LitElement {
4
4
  static get styles() {
5
5
  return css`
6
6
  :host {
@@ -16,18 +16,33 @@ export class KemetSVG extends LitElement {
16
16
 
17
17
  static get properties() {
18
18
  return {
19
+ /**
20
+ * Defines which set of svgs is referenced.
21
+ */
19
22
  set: {
20
23
  type: String,
21
24
  },
25
+ /**
26
+ * The name (id) of the svg to be displayed.
27
+ */
22
28
  svg: {
23
29
  type: String,
24
30
  },
31
+ /**
32
+ * Sets the width and height of a the svg to the given value in pixels.
33
+ */
25
34
  size: {
26
35
  type: Number,
27
36
  },
37
+ /**
38
+ * The value for the preserveAspectRatio attribute of the svg.
39
+ */
28
40
  ratio: {
29
41
  type: String,
30
42
  },
43
+ /**
44
+ * The value for the viewBox attribute of the svg.
45
+ */
31
46
  viewBox: {
32
47
  type: String,
33
48
  },
@@ -90,4 +105,5 @@ export class KemetSVG extends LitElement {
90
105
  }
91
106
  }
92
107
 
93
- window.customElements.define('kemet-svg', KemetSVG);
108
+ // eslint-disable-next-line no-unused-expressions
109
+ customElements.get('kemet-svg') || customElements.define('kemet-svg', KemetSVG);
@@ -1,6 +1,6 @@
1
1
  import { LitElement, html, css } from 'lit';
2
2
 
3
- export class KemetSVGs extends LitElement {
3
+ export default class KemetSVGs extends LitElement {
4
4
  static get styles() {
5
5
  return css`
6
6
  :host {
@@ -11,6 +11,9 @@ export class KemetSVGs extends LitElement {
11
11
 
12
12
  static get properties() {
13
13
  return {
14
+ /**
15
+ * Defines the name for the set of svgs.
16
+ */
14
17
  set: {
15
18
  type: String,
16
19
  },
@@ -21,11 +24,11 @@ export class KemetSVGs extends LitElement {
21
24
  super();
22
25
 
23
26
  this.set = 'svgs';
24
- document.kemetSVGs = document.kemetSVGs || {};
25
27
  }
26
28
 
27
29
  firstUpdated() {
28
30
  this.slotElement = this.shadowRoot.querySelector('slot');
31
+ document.kemetSVGs = document.kemetSVGs || {};
29
32
 
30
33
  this.populateIcons();
31
34
  this.slotElement.addEventListener('slotchange', this.populateIcons());
@@ -45,4 +48,5 @@ export class KemetSVGs extends LitElement {
45
48
  }
46
49
  }
47
50
 
48
- window.customElements.define('kemet-svgs', KemetSVGs);
51
+ // eslint-disable-next-line no-unused-expressions
52
+ customElements.get('kemet-svgs') || customElements.define('kemet-svgs', KemetSVGs);
@@ -1,6 +1,6 @@
1
1
  import { LitElement, html, css } from 'lit';
2
2
 
3
- export class KemetTabPanel extends LitElement {
3
+ export default class KemetTabPanel extends LitElement {
4
4
  static get styles() {
5
5
  return css`
6
6
  :host {
@@ -26,15 +26,29 @@ export class KemetTabPanel extends LitElement {
26
26
  :host(.fade.push) {
27
27
  margin-left: -100%;
28
28
  }
29
+
30
+ :host(.vertical) {
31
+ display: none;
32
+ }
33
+
34
+ :host(.vertical[selected]) {
35
+ display: block;
36
+ }
29
37
  `;
30
38
  }
31
39
 
32
40
  static get properties() {
33
41
  return {
42
+ /**
43
+ * Is true when a panel is selected
44
+ */
34
45
  selected: {
35
46
  type: Boolean,
36
47
  reflect: true,
37
48
  },
49
+ /**
50
+ * Identifies the panel to be linked by a tab
51
+ */
38
52
  panel: {
39
53
  type: String,
40
54
  },
@@ -1,27 +1,51 @@
1
1
  import { LitElement, html, css } from 'lit';
2
2
 
3
- export class KemetTab extends LitElement {
3
+ export default class KemetTab extends LitElement {
4
4
  static get styles() {
5
5
  return css`
6
6
  :host {
7
7
  cursor: pointer;
8
+ display: inline-flex;
9
+ flex: 0 0 auto;
10
+ align-items: center;
11
+ justify-content: center;
12
+ white-space: nowrap;
13
+ padding: var(--kemet-tab-padding, 1rem);
8
14
  }
9
15
 
10
16
  :host([selected]) {
11
17
  cursor: auto;
18
+ color: var(--kemet-tab-color, var(--kemet-color-primary));
19
+ }
20
+
21
+ kemet-icon {
22
+ cursor: pointer;
23
+ margin-left: 0.5rem;
12
24
  }
13
25
  `;
14
26
  }
15
27
 
16
28
  static get properties() {
17
29
  return {
30
+ /**
31
+ * Is true when the tab is selected
32
+ */
18
33
  selected: {
19
34
  type: Boolean,
20
35
  reflect: true,
21
36
  },
37
+ /**
38
+ * Links to a panel name
39
+ */
22
40
  link: {
23
41
  type: String,
24
42
  },
43
+ /**
44
+ * Determines if the tab can be closed
45
+ */
46
+ closable: {
47
+ type: Boolean,
48
+ },
25
49
  };
26
50
  }
27
51
 
@@ -43,10 +67,14 @@ export class KemetTab extends LitElement {
43
67
  render() {
44
68
  return html`
45
69
  <slot></slot>
70
+ ${this.makeCloseable()}
46
71
  `;
47
72
  }
48
73
 
49
74
  select() {
75
+ /**
76
+ * Fires when a tab is selected
77
+ */
50
78
  this.dispatchEvent(new CustomEvent('kemet-tab-selected', {
51
79
  bubbles: true,
52
80
  composed: true,
@@ -65,6 +93,25 @@ export class KemetTab extends LitElement {
65
93
  this.setAttribute('tabindex', '-1');
66
94
  }
67
95
  }
96
+
97
+ makeCloseable() {
98
+ if (this.closable) {
99
+ return html`<kemet-icon icon="x-lg" @click=${() => this.handleClosable()}></kemet-icon>`;
100
+ }
101
+
102
+ return null;
103
+ }
104
+
105
+ handleClosable() {
106
+ /**
107
+ * Fires when the tab should close
108
+ */
109
+ this.dispatchEvent(new CustomEvent('kemet-tab-close', {
110
+ bubbles: true,
111
+ composed: true,
112
+ detail: this,
113
+ }));
114
+ }
68
115
  }
69
116
 
70
117
  customElements.define('kemet-tab', KemetTab);