kemet-ui 1.0.0 → 1.2.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 (77) hide show
  1. package/custom-elements.json +1605 -225
  2. package/dist/components/{kemet-accordion-panel.js → kemet-accordion/kemet-accordion-panel.js} +0 -0
  3. package/dist/components/{kemet-accordion.js → kemet-accordion/kemet-accordion.js} +0 -0
  4. package/dist/components/{kemet-badge.js → kemet-badge/kemet-badge.js} +0 -0
  5. package/dist/components/{kemet-button.js → kemet-button/kemet-button.js} +0 -0
  6. package/dist/components/kemet-carousel/kemet-carousel-current.js +36 -0
  7. package/dist/components/kemet-carousel/kemet-carousel-first.js +47 -0
  8. package/dist/components/kemet-carousel/kemet-carousel-last.js +47 -0
  9. package/dist/components/kemet-carousel/kemet-carousel-link.js +59 -0
  10. package/dist/components/kemet-carousel/kemet-carousel-next.js +47 -0
  11. package/dist/components/kemet-carousel/kemet-carousel-prev.js +47 -0
  12. package/dist/components/kemet-carousel/kemet-carousel-slide.js +51 -0
  13. package/dist/components/kemet-carousel/kemet-carousel-total.js +36 -0
  14. package/dist/components/kemet-carousel/kemet-carousel.js +492 -0
  15. package/dist/components/{kemet-checkbox.js → kemet-checkbox/kemet-checkbox.js} +0 -0
  16. package/dist/components/{kemet-combo.js → kemet-combo/kemet-combo.js} +0 -0
  17. package/dist/components/{kemet-count.js → kemet-count/kemet-count.js} +0 -0
  18. package/dist/components/{kemet-draggable.js → kemet-draggable/kemet-draggable.js} +0 -0
  19. package/dist/components/{kemet-drawer.js → kemet-drawer/kemet-drawer.js} +0 -0
  20. package/dist/components/{kemet-drawer.styles.js → kemet-drawer/kemet-drawer.styles.js} +0 -0
  21. package/dist/components/kemet-fab/kemet-fab.js +209 -0
  22. package/dist/components/{kemet-field.js → kemet-field/kemet-field.js} +0 -0
  23. package/dist/components/{kemet-flipcard-trigger.js → kemet-flipcard/kemet-flipcard-trigger.js} +0 -0
  24. package/dist/components/{kemet-flipcard.js → kemet-flipcard/kemet-flipcard.js} +0 -0
  25. package/dist/components/{kemet-icon.js → kemet-icon/kemet-icon.js} +0 -0
  26. package/dist/components/{kemet-input.js → kemet-input/kemet-input.js} +15 -4
  27. package/dist/components/{kemet-modal-close.js → kemet-modal/kemet-modal-close.js} +0 -0
  28. package/dist/components/{kemet-modal.js → kemet-modal/kemet-modal.js} +0 -0
  29. package/dist/components/{kemet-modal.styles.js → kemet-modal/kemet-modal.styles.js} +0 -0
  30. package/dist/components/kemet-password/kemet-password.js +278 -0
  31. package/dist/components/{kemet-popover-close.js → kemet-popover/kemet-popover-close.js} +0 -0
  32. package/dist/components/{kemet-popover.effects.styles.js → kemet-popover/kemet-popover.effects.styles.js} +0 -0
  33. package/dist/components/{kemet-popover.js → kemet-popover/kemet-popover.js} +0 -0
  34. package/dist/components/{kemet-popover.tooltip.styles.js → kemet-popover/kemet-popover.tooltip.styles.js} +0 -0
  35. package/dist/components/{kemet-radio.js → kemet-radio/kemet-radio.js} +0 -0
  36. package/dist/components/{kemet-radios.js → kemet-radio/kemet-radios.js} +0 -0
  37. package/dist/components/{kemet-rotator.js → kemet-rotator/kemet-rotator.js} +0 -0
  38. package/dist/components/{kemet-scroll-link.js → kemet-scroll-link/kemet-scroll-link.js} +0 -0
  39. package/dist/components/{kemet-scroll-nav.js → kemet-scroll-nav/kemet-scroll-nav.js} +0 -0
  40. package/dist/components/{kemet-scroll-snap-paginator.js → kemet-scroll-snap/kemet-scroll-snap-paginator.js} +0 -0
  41. package/dist/components/{kemet-scroll-snap-slide.js → kemet-scroll-snap/kemet-scroll-snap-slide.js} +0 -0
  42. package/dist/components/{kemet-scroll-snap.js → kemet-scroll-snap/kemet-scroll-snap.js} +0 -0
  43. package/dist/components/{kemet-option.js → kemet-select/kemet-option.js} +0 -0
  44. package/dist/components/{kemet-select.js → kemet-select/kemet-select.js} +0 -0
  45. package/dist/components/{kemet-svg.js → kemet-svgs/kemet-svg.js} +0 -0
  46. package/dist/components/{kemet-svgs.js → kemet-svgs/kemet-svgs.js} +0 -0
  47. package/dist/components/{kemet-tab-panel.js → kemet-tabs/kemet-tab-panel.js} +0 -0
  48. package/dist/components/{kemet-tab.js → kemet-tabs/kemet-tab.js} +0 -0
  49. package/dist/components/{kemet-tabs.js → kemet-tabs/kemet-tabs.js} +0 -0
  50. package/dist/components/{kemet-tabs.styles.js → kemet-tabs/kemet-tabs.styles.js} +0 -0
  51. package/dist/components/{kemet-textarea.js → kemet-textarea/kemet-textarea.js} +0 -0
  52. package/dist/components/{kemet-toggle.js → kemet-toggle/kemet-toggle.js} +0 -0
  53. package/dist/components/kemet-tracker/kemet-tracker-step.js +239 -0
  54. package/dist/components/kemet-tracker/kemet-tracker.js +76 -0
  55. package/dist/kemet-components.cjs +1809 -140
  56. package/dist/kemet-components.js +1805 -141
  57. package/dist/kemet-components.min.js +574 -87
  58. package/dist/styles/components/_config.scss +4 -0
  59. package/dist/styles/{scss/components → components}/accordion.scss +0 -0
  60. package/dist/styles/{scss/components → components}/drawer.scss +2 -2
  61. package/dist/styles/{scss/components → components}/modal.scss +0 -0
  62. package/dist/styles/{scss/components → components}/scrollsnap.scss +0 -0
  63. package/dist/styles/{scss/core → core}/_config.scss +22 -22
  64. package/dist/styles/{scss/core → core}/_helpers.scss +7 -3
  65. package/dist/styles/{scss/core → core}/attributes.scss +0 -0
  66. package/dist/styles/{scss/core → core}/base.scss +0 -0
  67. package/dist/styles/{scss/core → core}/layout.scss +0 -0
  68. package/dist/styles/kemet.components.css +1 -80
  69. package/dist/styles/kemet.components.css.map +1 -1
  70. package/dist/styles/{scss/kemet.components.scss → kemet.components.scss} +0 -1
  71. package/dist/styles/kemet.core.css +1 -1
  72. package/dist/styles/kemet.core.css.map +1 -1
  73. package/dist/styles/{scss/kemet.core.scss → kemet.core.scss} +0 -0
  74. package/dist/utilities/controllers/forms.js +123 -0
  75. package/package.json +5 -3
  76. package/dist/styles/scss/components/_config.scss +0 -4
  77. package/dist/styles/scss/components/carousel.scss +0 -64
@@ -0,0 +1,492 @@
1
+ import { html, css, LitElement } from 'lit';
2
+
3
+ export default class KemetCarousel extends LitElement {
4
+ static get styles() {
5
+ return css`
6
+ :host,
7
+ *,
8
+ *::before,
9
+ *::after {
10
+ box-sizing: border-box;
11
+ }
12
+
13
+ :host {
14
+ position: relative;
15
+ display: grid;
16
+ grid-template-columns: minmax(0, 1fr);
17
+ align-items: center;
18
+ width: var(--kemet-carousel-width, 100%);
19
+ height: var(--kemet-carousel-height, auto);
20
+ overflow: visible;
21
+ }
22
+
23
+ :host([arrows]) {
24
+ grid-template-columns: auto minmax(0, 1fr) auto;
25
+ }
26
+
27
+ .toolbar {
28
+ display: flex;
29
+ gap: var(--kemet-carousel-toolbar-gap, 1rem);
30
+ align-items: center;
31
+ justify-content: var(--kemet-carousel-toolbar-justify-content, center);
32
+ line-height: 1;
33
+ padding: var(--kemet-carousel-toolbar-padding, 1rem);
34
+ }
35
+
36
+ :host([inner]) .toolbar {
37
+ width: var(--kemet-carousel-toolbar-inner-width, 100%);
38
+ position: absolute;
39
+ bottom: var(--kemet-carousel-toolbar-inner-bottom, 0);
40
+ top: var(--kemet-carousel-toolbar-inner-top, auto);
41
+ color: var(--kemet-carousel-toolbar-inner-color, var(--kemet-color-white));
42
+ background-color: var(--kemet-carousel-toolbar-inner-background-color, rgba(0, 0, 0, 0.4));
43
+ }
44
+
45
+ .slides {
46
+ overflow: hidden;
47
+ position: relative;
48
+ padding: 1rem 0;
49
+ border: var(--kemet-carousel-slides-border, 1px solid var(--kemet-color-gray1));
50
+ }
51
+
52
+ .slider {
53
+ display: flex;
54
+ flex-wrap: nowrap;
55
+ transition: transform var(--kemet-carousel-transition-speed, 300ms) ease;
56
+ }
57
+
58
+ ::slotted([slot='next']),
59
+ ::slotted([slot='prev']) {
60
+ opacity: var(--kemet-carousel-arrows-opacity, 0.25);
61
+ transition: opacity var(--kemet-carousel-arrows-transition-speed, 300ms) ease-in-out;
62
+ }
63
+
64
+ :host(:hover) ::slotted([slot='next']),
65
+ :host(:hover) ::slotted([slot='prev']) {
66
+ opacity: var(--kemet-carousel-arrows-opacity-hover, 1);
67
+ }
68
+ `;
69
+ }
70
+
71
+ static get properties() {
72
+ return {
73
+ /**
74
+ * The current slide index.
75
+ */
76
+ index: {
77
+ type: Number,
78
+ reflect: true,
79
+ },
80
+ /**
81
+ * The total amount of slides
82
+ */
83
+ total: {
84
+ type: Number,
85
+ },
86
+ /**
87
+ * The width of the slider
88
+ */
89
+ sliderWidth: {
90
+ type: String,
91
+ },
92
+ /**
93
+ * The X position of the slider
94
+ */
95
+ sliderTranslateX: {
96
+ type: String,
97
+ },
98
+ /**
99
+ * Displays the toolbar inside the carousel container
100
+ */
101
+ inner: {
102
+ type: Boolean,
103
+ reflect: true,
104
+ },
105
+ /**
106
+ * Determines whether or not to display arrows
107
+ */
108
+ arrows: {
109
+ type: Boolean,
110
+ reflect: true,
111
+ },
112
+ /**
113
+ * Default options for the carousel
114
+ */
115
+ options: {
116
+ type: Object,
117
+ },
118
+ /**
119
+ * Options are different breakpoints for the carousel. Is mobile first.
120
+ */
121
+ breakpoints: {
122
+ type: Object,
123
+ },
124
+ };
125
+ }
126
+
127
+ constructor() {
128
+ super();
129
+
130
+ // managed properties
131
+ this.index = 0;
132
+ this.total = 0;
133
+ this.sliderWidth = 'auto';
134
+ this.sliderTranslateX = '0';
135
+ this.inner = false;
136
+ this.arrows = false;
137
+ this.options = {
138
+ perView: 1,
139
+ perMove: 1,
140
+ gap: 12,
141
+ slideshow: 0,
142
+ rewind: true,
143
+ center: false,
144
+ };
145
+ this.breakpoints = {
146
+ 768: {
147
+ perView: 2,
148
+ gap: 24,
149
+ rewind: false,
150
+ },
151
+ 1280: {
152
+ perView: 2.5,
153
+ center: true,
154
+ },
155
+ };
156
+
157
+ // bindings
158
+ this.addEventListener('kemet-carousel-first', this.handleFirst.bind(this));
159
+ this.addEventListener('kemet-carousel-last', this.handleLast.bind(this));
160
+ this.addEventListener('kemet-carousel-next', this.handleNext.bind(this));
161
+ this.addEventListener('kemet-carousel-prev', this.handlePrev.bind(this));
162
+ this.addEventListener('kemet-carousel-link', this.handleLink.bind(this));
163
+ }
164
+
165
+ firstUpdated() {
166
+ // standard properties
167
+ this.slides = [];
168
+ this.links = [];
169
+
170
+ // elements
171
+ this.containerElement = this.shadowRoot.querySelector('[part="container"]');
172
+ this.slidesElement = this.shadowRoot.querySelector('[part="slides"]');
173
+ this.sliderElement = this.shadowRoot.querySelector('[part="slider"]');
174
+ this.toolbarElement = this.shadowRoot.querySelector('[part="toolbar"]');
175
+ this.toolbarSlotElement = this.querySelector('[slot="toolbar"]');
176
+ this.informationElement = this.querySelector('kemet-carousel-information');
177
+
178
+ // events
179
+ window.addEventListener('resize', () => {
180
+ this.setSlideSize();
181
+ this.setToolbarSize();
182
+ this.updateIndex(this.index);
183
+ });
184
+
185
+ this.sliderElement.addEventListener('transitionend', this.handleTransitionEnd.bind(this));
186
+
187
+ // methods
188
+ this.swipeMove = (event) => {
189
+ event.preventDefault();
190
+
191
+ const pageX = event.touches ? event.touches[0].pageX : event.pageX;
192
+ const currentSlide = this.slides[this.index];
193
+
194
+ this.sliderTranslateX = `${pageX - this.startX - currentSlide.offsetLeft}px`;
195
+ };
196
+
197
+ this.handleSlideShow = () => {
198
+ if (this.getOption('slideshow') > 0) {
199
+ this.updateIndex(this.index + 1);
200
+ clearTimeout(this.handleSlideShow);
201
+ }
202
+ };
203
+
204
+ // setup
205
+ this.setSlideSize();
206
+ this.goToSlide(this.index);
207
+ }
208
+
209
+ updated(prevProps) {
210
+ this.setSlideSize();
211
+ this.setToolbarSize();
212
+
213
+ if (prevProps.has('index')) {
214
+ this.updateIndex(this.index);
215
+ setTimeout(this.handleSlideShow, this.getOption('slideshow') * 1000);
216
+ }
217
+ }
218
+
219
+ render() {
220
+ return html`
221
+ <slot name="prev" @slotchange=${this.handleArrows}></slot>
222
+ <div class="container" part="container">
223
+ <section
224
+ class="slides"
225
+ part="slides"
226
+ @mousedown=${this.swipeStart}
227
+ @mouseup=${this.swipeEnd}
228
+ @touchstart=${this.swipeStart}
229
+ @touchend=${this.swipeEnd}
230
+ @mouseleave=${this.swipeLeave}
231
+ >
232
+ <div class="slider" part="slider" style="width:${this.sliderWidth}; transform:translateX(${this.sliderTranslateX});">
233
+ <slot name="slides" @slotchange="${this.handleSlotChange}"></slot>
234
+ </div>
235
+ </section>
236
+ ${this.makeToolbar()}
237
+ </div>
238
+ <slot name="next" @slotchange=${this.handleArrows}></slot>
239
+ `;
240
+ }
241
+
242
+ swipeStart(event) {
243
+ this.startX = event.touches ? event.touches[0].pageX : event.pageX;
244
+
245
+ this.addEventListener('mousemove', this.swipeMove);
246
+ this.addEventListener('touchmove', this.swipeMove);
247
+ }
248
+
249
+ swipeEnd(event) {
250
+ this.updateIndex(this.swipeUpdate(event));
251
+ this.removeEventListener('mousemove', this.swipeMove, false);
252
+ this.removeEventListener('touchmove', this.swipeMove, false);
253
+ }
254
+
255
+ swipeUpdate(event) {
256
+ const pageX = event.changedTouches ? event.changedTouches[0].pageX : event.pageX;
257
+ const direction = this.startX > pageX ? 'right' : 'left';
258
+ const threshold = this.slidesElement.offsetWidth / 3;
259
+ const diff = this.startX - pageX;
260
+ const shouldUpdate = Math.abs(diff) > threshold;
261
+
262
+ let { index } = this;
263
+
264
+ if (shouldUpdate && direction === 'right') {
265
+ index = this.index >= this.slides.length - 1 ? this.index : this.index + 1;
266
+ }
267
+
268
+ if (shouldUpdate && direction === 'left') {
269
+ index = this.index < 1 ? 0 : this.index - 1;
270
+ }
271
+
272
+ return index;
273
+ }
274
+
275
+ swipeLeave() {
276
+ this.updateIndex(this.index);
277
+ this.removeEventListener('mousemove', this.swipeMove, false);
278
+ this.removeEventListener('touchmove', this.swipeMove, false);
279
+ }
280
+
281
+ setSlideSize() {
282
+ this.slideWidth = this.containerElement.offsetWidth / this.getOption('perView');
283
+
284
+ this.slides.forEach((slide) => {
285
+ slide.style.marginLeft = `${this.getOption('gap') / 2}px`;
286
+ slide.style.marginRight = `${this.getOption('gap') / 2}px`;
287
+ slide.style.width = `${this.slideWidth - this.getOption('gap')}px`;
288
+ });
289
+
290
+ this.sliderWidth = `${this.slideWidth * this.slides.length}px`;
291
+ }
292
+
293
+ setToolbarSize() {
294
+ if (this.inner && this.toolbarElement) {
295
+ const width = this.slidesElement.offsetWidth;
296
+ this.toolbarElement.style.width = `${width}px`;
297
+ }
298
+ }
299
+
300
+ makeToolbar() {
301
+ if (this.toolbarSlotElement) {
302
+ return html`
303
+ <section class="toolbar" part="toolbar">
304
+ <slot name="toolbar"></slot>
305
+ </section>
306
+ `;
307
+ }
308
+
309
+ return null;
310
+ }
311
+
312
+ handleSlotChange() {
313
+ const slides = this.querySelectorAll('kemet-carousel-slide');
314
+ const links = this.querySelectorAll('kemet-carousel-link');
315
+
316
+ // handle slides
317
+ slides.forEach((slide) => {
318
+ this.slides.push(slide);
319
+ });
320
+
321
+ this.updateInformation();
322
+ this.total = slides.length;
323
+ slides[this.index].selected = true;
324
+
325
+ // handle links
326
+ links.forEach((link) => {
327
+ this.links.push(link);
328
+ });
329
+ }
330
+
331
+ handleArrows() {
332
+ this.arrows = true;
333
+ }
334
+
335
+ handleFirst() {
336
+ this.updateIndex(0);
337
+ }
338
+
339
+ handleLast() {
340
+ this.updateIndex(this.slides.length - 1);
341
+ }
342
+
343
+ handleNext() {
344
+ let newIndex = this.index + this.getOption('perMove');
345
+
346
+ if (newIndex >= this.slides.length) {
347
+ if (this.getOption('rewind')) {
348
+ newIndex = 0;
349
+ } else {
350
+ newIndex = this.index;
351
+ }
352
+ }
353
+
354
+ this.updateIndex(newIndex);
355
+ }
356
+
357
+ handlePrev() {
358
+ let newIndex = this.index - this.getOption('perMove');
359
+
360
+ // send them to the last slide
361
+ if (newIndex < 0) {
362
+ if (this.getOption('rewind')) {
363
+ newIndex = this.slides.length - 1;
364
+ } else {
365
+ newIndex = this.index;
366
+ }
367
+ }
368
+
369
+ this.updateIndex(newIndex);
370
+ }
371
+
372
+ updateIndex(newIndex) {
373
+ let currentSlide = this.slides[this.index];
374
+ let currentLink = this.links[newIndex];
375
+
376
+ // remove selected from all links
377
+ this.links.forEach((link) => {
378
+ link.selected = false;
379
+ });
380
+
381
+ // if current link is invalid assume it's the first link
382
+ if (!currentLink) {
383
+ [currentLink] = this.links;
384
+ }
385
+
386
+ // add selected to current link
387
+ if (currentLink) {
388
+ currentLink.selected = true;
389
+ }
390
+
391
+ if (currentSlide) {
392
+ currentSlide.setAttribute('aria-hidden', 'true');
393
+
394
+ // correct for invalid indexes
395
+ if (newIndex > -1 && newIndex < this.slides.length) {
396
+ this.index = newIndex;
397
+ } else {
398
+ // eslint-disable-next-line no-console
399
+ console.warn('An invalid index number was entered. The kemet-carousel has been reset to the first slide.');
400
+ this.index = 0;
401
+ }
402
+
403
+ // move
404
+ this.goToSlide(this.index);
405
+
406
+ // update new slide
407
+ currentSlide = this.slides[this.index];
408
+ currentSlide.setAttribute('aria-hidden', 'false');
409
+
410
+ this.slides.forEach((slide) => {
411
+ slide.selected = false;
412
+ });
413
+
414
+ currentSlide.selected = true;
415
+
416
+ // notify consumers of slide change
417
+
418
+ /**
419
+ * Fires with the a slide has begun to change
420
+ */
421
+ this.dispatchEvent(new CustomEvent('kemet-carousel-change-start', {
422
+ bubbles: true,
423
+ composed: true,
424
+ detail: this,
425
+ }));
426
+
427
+ // update information element
428
+ this.updateInformation();
429
+ }
430
+ }
431
+
432
+ updateInformation() {
433
+ this.informationSlot = this.slides[this.index].querySelector('[slot="information"]');
434
+
435
+ if (this.informationElement) {
436
+ if (this.informationSlot) {
437
+ this.informationElement.innerHTML = this.informationSlot.outerHTML;
438
+ } else {
439
+ this.informationElement.innerHTML = '';
440
+ }
441
+ }
442
+ }
443
+
444
+ goToSlide(index) {
445
+ if (this.getOption('center') === true) {
446
+ const slidesCenter = this.slidesElement.offsetWidth / 2;
447
+ const slideX = this.slideWidth * index;
448
+ this.sliderTranslateX = `${slideX - (slideX - slidesCenter) - this.slideWidth / 2 - slideX}px`;
449
+ } else {
450
+ this.sliderTranslateX = `${(this.slideWidth * index) * -1}px`;
451
+ }
452
+ }
453
+
454
+ handleTransitionEnd() {
455
+ const currentElement = this.querySelector('kemet-carousel-current');
456
+
457
+ if (currentElement) {
458
+ currentElement.current = this.index + 1;
459
+ }
460
+
461
+ /**
462
+ * Fires when a slide has changed and finished animating
463
+ */
464
+ this.dispatchEvent(new CustomEvent('kemet-carousel-change-finished', {
465
+ bubbles: true,
466
+ composed: true,
467
+ detail: this,
468
+ }));
469
+ }
470
+
471
+ handleLink(event) {
472
+ this.updateIndex(event.detail.slide);
473
+ }
474
+
475
+ getOption(option) {
476
+ const breakpoints = Object.keys(this.breakpoints);
477
+ let value = this.options[option];
478
+
479
+ breakpoints.forEach((breakpoint) => {
480
+ if (window.matchMedia(`(min-width: ${breakpoint}px)`).matches && this.breakpoints[breakpoint][option] !== undefined) {
481
+ value = this.breakpoints[breakpoint][option];
482
+ }
483
+
484
+ return value;
485
+ });
486
+
487
+ return value;
488
+ }
489
+ }
490
+
491
+ // eslint-disable-next-line no-unused-expressions
492
+ customElements.get('kemet-carousel') || customElements.define('kemet-carousel', KemetCarousel);
@@ -0,0 +1,209 @@
1
+ import { html, css, LitElement } from 'lit';
2
+
3
+ export default class KemetFAB extends LitElement {
4
+ static get styles() {
5
+ return [
6
+ css`
7
+ :host {
8
+ --kemet-fab-size: 50px;
9
+
10
+ display: inline-block;
11
+ position: relative;
12
+ }
13
+
14
+ button {
15
+ color: var(--kemet-fab-color, var(--kemet-color-white));
16
+ font-size: inherit;
17
+ display: inline-flex;
18
+ padding: 0;
19
+ position: relative;
20
+ min-height: var(--kemet-fab-size);
21
+ min-width: var(--kemet-fab-size);
22
+ max-width: var(--kemet-fab-size);
23
+ align-items: center;
24
+ justify-content: flex-start;
25
+ transition: all 0.4s ease;
26
+ border: none;
27
+ background-color: var(--kemet-fab-background-color, var(--kemet-color-primary));
28
+ }
29
+
30
+ :host([outlined]) button {
31
+ color: var(--kemet-fab-outlined-color, var(--kemet-color-primary));
32
+ border: var(--kemet-fab-outlined-border, 1px solid var(--kemet-color-primary));
33
+ background-color: transparent;
34
+ }
35
+
36
+ :host([pill]) button {
37
+ border-radius: var(--kemet-fab-pill-radius, 10rem);
38
+ }
39
+
40
+ button::before {
41
+ content: '';
42
+ position: absolute;
43
+ top: 0;
44
+ left: 0;
45
+ right: 0;
46
+ bottom: 0;
47
+ z-index: -1;
48
+ width: 100%;
49
+ height: 100%;
50
+ transition: background-color 0.3s ease-in-out;
51
+ background-color: var(--kemet-fab-background-color, var(--kemet-color-primary));
52
+ }
53
+
54
+ :host([pill]) button::before {
55
+ border-radius: var(--kemet-fab-pill-radius, 10rem);
56
+ }
57
+
58
+ :host([outlined]) button::before {
59
+ border: var(--kemet-fab-outline-border, 1px solid var(--kemet-color-primary));
60
+ background-color: transparent;
61
+ }
62
+
63
+ :host([expanded]) button {
64
+ max-width: 99rem;
65
+ padding: 0 1.35rem 0 0.25rem;
66
+ }
67
+
68
+ :host([disabled]) button {
69
+ opacity: 0.5;
70
+ cursor: not-allowed;
71
+ }
72
+
73
+ .icon {
74
+ width: var(--kemet-fab-size);
75
+ height: var(--kemet-fab-size);
76
+ display: flex;
77
+ flex: 0 0 auto;
78
+ align-items: center;
79
+ justify-content: center;
80
+ }
81
+
82
+ .text {
83
+ color: var(--kemet-fab-color, var(--kemet-color-white));
84
+ z-index: 1;
85
+ white-space: nowrap;
86
+ pointer-events: none;
87
+ opacity: 0;
88
+ transition: opacity 0.2s ease-in-out;
89
+ }
90
+
91
+ :host([outlined]) .text {
92
+ color: var(--kemet-fab-outlined-color, var(--kemet-color-primary));
93
+ }
94
+
95
+ :host([expanded]) .text {
96
+ opacity: 1;
97
+ }
98
+ `,
99
+ ];
100
+ }
101
+
102
+ static get properties() {
103
+ return {
104
+ /**
105
+ * The expanded state of the button
106
+ */
107
+ expanded: {
108
+ type: Boolean,
109
+ reflect: true,
110
+ },
111
+ /**
112
+ * Outline style for a button
113
+ */
114
+ outlined: {
115
+ type: Boolean,
116
+ reflect: true,
117
+ },
118
+ /**
119
+ * Determines whether not a button is disabled
120
+ */
121
+ disabled: {
122
+ type: Boolean,
123
+ reflect: true,
124
+ },
125
+ /**
126
+ * Displays the fab with rounded corners
127
+ */
128
+ pill: {
129
+ type: Boolean,
130
+ reflect: true,
131
+ },
132
+ /**
133
+ * The distance, in pixels, where the fab should automatically expand
134
+ */
135
+ expandPoint: {
136
+ type: Number,
137
+ attribute: 'expand-point',
138
+ },
139
+ /**
140
+ * The distance, in pixels, where the fab should automatically collapse
141
+ */
142
+ collapsePoint: {
143
+ type: Number,
144
+ attribute: 'collapse-point',
145
+ },
146
+ };
147
+ }
148
+
149
+ constructor() {
150
+ super();
151
+
152
+ this.outlined = false;
153
+ this.disabled = false;
154
+ this.expanded = false;
155
+ }
156
+
157
+ firstUpdated() {
158
+ // events
159
+ window.addEventListener('scroll', this.handleScroll.bind(this));
160
+ this.addEventListener('mouseover', this.handleMouseOver.bind(this));
161
+ this.addEventListener('mouseout', this.handleMouseOut.bind(this));
162
+ }
163
+
164
+ render() {
165
+ return html`
166
+ <button class="button" part="button" ?disabled=${this.disabled} aria-disabled=${this.disabled ? 'true' : 'false'}>
167
+ <span class="icon" part="icon">
168
+ <slot name="icon"></slot>
169
+ </span>
170
+ <span class="text" part="text">
171
+ <slot></slot>
172
+ </span>
173
+ </button>
174
+ `;
175
+ }
176
+
177
+ handleMouseOver() {
178
+ if (!this.disabled) {
179
+ this.expanded = true;
180
+ }
181
+ }
182
+
183
+ handleMouseOut() {
184
+ if (!this.disabled) {
185
+ this.expanded = false;
186
+ }
187
+ }
188
+
189
+ handleScroll() {
190
+ if (window.scrollY > this.expandPoint) {
191
+ this.expanded = true;
192
+ }
193
+
194
+ if (window.scrollY < this.expandPoint) {
195
+ this.expanded = false;
196
+ }
197
+
198
+ if (window.scrollY > this.collapsePoint) {
199
+ this.expanded = false;
200
+ }
201
+
202
+ if (window.scrollY < this.collapsePoint) {
203
+ this.expanded = true;
204
+ }
205
+ }
206
+ }
207
+
208
+ // eslint-disable-next-line no-unused-expressions
209
+ customElements.get('kemet-fab') || customElements.define('kemet-fab', KemetFAB);