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
@@ -0,0 +1,178 @@
1
+ import { html, css, LitElement } from 'lit';
2
+ import '../kemet-icon/kemet-icon.js';
3
+
4
+ export default class KemetAccordionPanel extends LitElement {
5
+ static get styles() {
6
+ return [
7
+ css`
8
+ *,
9
+ *::before,
10
+ *::after {
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ :host {
15
+ display: block;
16
+ padding: 1.5rem 1rem;
17
+ border-bottom: 1px solid var(--kemet-color-primary);
18
+ }
19
+
20
+ .trigger {
21
+ cursor: pointer;
22
+ display: grid;
23
+ gap: 1rem;
24
+ grid-template-columns: 1fr auto;
25
+ width: 100%;
26
+ text-align: left;
27
+ padding: 0;
28
+ border: none;
29
+ background: none;
30
+ }
31
+
32
+ .body {
33
+ overflow: hidden;
34
+ transition: all var(--kemet-accordion-panel-transition-speed, 300ms) ease;
35
+ }
36
+
37
+ ::slotted([slot='body']) {
38
+ padding: 1rem 0;
39
+ }
40
+ `,
41
+ ];
42
+ }
43
+
44
+ static get properties() {
45
+ return {
46
+ /**
47
+ * Determines the opened state of the panel
48
+ */
49
+ opened: {
50
+ type: Boolean,
51
+ reflect: true,
52
+ },
53
+ /**
54
+ * Sets the max height of the panel's body
55
+ */
56
+ maxHeight: {
57
+ type: String,
58
+ attribute: 'max-height',
59
+ },
60
+ /**
61
+ * Uniquely identifies a panel for accessibility purposes
62
+ */
63
+ slug: {
64
+ type: String,
65
+ },
66
+ };
67
+ }
68
+
69
+ constructor() {
70
+ super();
71
+
72
+ // managed properties
73
+ this.opened = undefined;
74
+ this.maxHeight = '0px';
75
+ this.slug = 'panel';
76
+ }
77
+
78
+ firstUpdated() {
79
+ this.focusableSelector = 'body, a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]';
80
+ this.bodyElement = this.querySelector('[slot="body"]');
81
+ this.bodyElementFirst = this.bodyElement.querySelector(':first-child');
82
+ this.bodyElementLast = this.bodyElement.querySelector(':last-child');
83
+
84
+ if (this.bodyElementFirst) this.bodyElementFirst.style.marginTop = 0;
85
+ if (this.bodyELementLast) this.bodyElementLast.style.marginBottom = 0;
86
+ }
87
+
88
+ updated(prevProps) {
89
+ if (!prevProps.get('opened') && this.opened === true) {
90
+ this.maxHeight = `${this.bodyElement.offsetHeight}px`;
91
+
92
+ /**
93
+ * Fires when a panel is opened
94
+ */
95
+ this.dispatchEvent(
96
+ new CustomEvent('kemet-accordion-panel-opened', {
97
+ bubbles: true,
98
+ composed: true,
99
+ detail: this,
100
+ }),
101
+ );
102
+ }
103
+
104
+ if (prevProps.get('opened') && this.opened === false) {
105
+ this.maxHeight = '0px';
106
+
107
+ /**
108
+ * Fires when a panel is closed
109
+ */
110
+ this.dispatchEvent(
111
+ new CustomEvent('kemet-accordion-panel-closed', {
112
+ bubbles: true,
113
+ composed: true,
114
+ detail: this,
115
+ }),
116
+ );
117
+ }
118
+
119
+ this.a11y();
120
+ this.focusableBodyElements();
121
+ }
122
+
123
+ render() {
124
+ return html`
125
+ <button
126
+ class="trigger"
127
+ part="trigger"
128
+ @click=${() => this.toggle()}
129
+ @keydown=${event => this.handleKeyDown(event)}
130
+ >
131
+ <slot name="trigger"></slot>
132
+ <slot name="icon"></slot>
133
+ </button>
134
+ <section class="body" part="body" style="max-height:${this.maxHeight};">
135
+ <slot name="body"></slot>
136
+ </section>
137
+ `;
138
+ }
139
+
140
+ toggle() {
141
+ this.opened = !this.opened;
142
+ }
143
+
144
+ focusableBodyElements() {
145
+ const focusableElements = this.bodyElement.querySelectorAll(this.focusableSelector);
146
+
147
+ if (this.opened) {
148
+ focusableElements.forEach((element) => {
149
+ element.removeAttribute('tabindex');
150
+ });
151
+ } else {
152
+ focusableElements.forEach((element) => {
153
+ element.setAttribute('tabindex', '-1');
154
+ });
155
+ }
156
+ }
157
+
158
+ a11y() {
159
+ const trigger = this.shadowRoot.querySelector('.trigger');
160
+ const body = this.shadowRoot.querySelector('.body');
161
+
162
+ trigger.setAttribute('id', `${this.slug}-button`);
163
+ trigger.setAttribute('aria-controls', `${this.slug}-content`);
164
+
165
+ body.setAttribute('id', `${this.slug}-content`);
166
+ body.setAttribute('aria-labelledby', `${this.slug}-button`);
167
+ body.setAttribute('aria-hidden', `${!this.opened}`);
168
+ }
169
+
170
+ handleKeyDown(event) {
171
+ if (event.key === 'Space' || event.key === 'Enter') {
172
+ this.toggle();
173
+ }
174
+ }
175
+ }
176
+
177
+ // eslint-disable-next-line no-unused-expressions
178
+ customElements.get('kemet-accordion-panel') || customElements.define('kemet-accordion-panel', KemetAccordionPanel);
@@ -1,36 +1,30 @@
1
- import { LitElement, html, css } from 'lit';
1
+ import { html, css, LitElement } from 'lit';
2
2
 
3
- export class KemetAccordion extends LitElement {
3
+ export default class KemetAccordion extends LitElement {
4
4
  static get styles() {
5
- return css`
6
- :host {
7
- display: block;
8
- }
9
-
10
- [name="trigger"] {
11
- cursor: pointer
12
- }
13
-
14
- #panel {
15
- overflow: hidden;
16
- transition: all var(--kemet-accordion-transition-speed, 300ms) ease;
17
- }
18
- `;
5
+ return [
6
+ css`
7
+ :host {
8
+ display: block;
9
+ }
10
+ `,
11
+ ];
19
12
  }
20
13
 
21
14
  static get properties() {
22
15
  return {
23
- opened: {
24
- type: Boolean,
25
- reflect: true,
26
- },
27
- maxHeight: {
28
- type: String,
29
- attribute: 'max-height',
16
+ /**
17
+ * The index value for the most recently opened panel
18
+ */
19
+ currentPanel: {
20
+ type: Number,
30
21
  },
31
- closeOthers: {
22
+ /**
23
+ * Support for closing all inactive panels when one is opened
24
+ */
25
+ togglePanels: {
32
26
  type: Boolean,
33
- attribute: 'close-others',
27
+ attribute: 'toggle-panels',
34
28
  },
35
29
  };
36
30
  }
@@ -38,69 +32,108 @@ export class KemetAccordion extends LitElement {
38
32
  constructor() {
39
33
  super();
40
34
 
41
- this.opened = undefined;
42
- this.maxHeight = '0px';
43
- this.closeOthers = false;
35
+ // managed properties
36
+ this.togglePanels = false;
37
+ this.currentPanel = undefined;
38
+
39
+ // bindings
40
+ this.addEventListener('kemet-accordion-panel-opened', this.handlePanelOpened.bind(this));
44
41
  }
45
42
 
46
43
  firstUpdated() {
47
- // eslint-disable-next-line prefer-destructuring
48
- this.panelElement = this.shadowRoot
49
- .querySelector('slot[name="panel"]')
50
- .assignedNodes({ flatten: true })[0];
44
+ this.onKeyDown = event => this.handleKeyDown(event);
51
45
  }
52
46
 
53
- updated(prevProps) {
54
- if (!prevProps.get('opened') && this.opened === true) {
55
- this.makeEvent('opened');
56
- }
47
+ render() {
48
+ return html`<slot @slotchange=${event => this.handleSlotChange(event)}></slot>`;
49
+ }
57
50
 
58
- if (prevProps.get('opened') && this.opened === false) {
59
- this.makeEvent('closed');
60
- }
51
+ handleSlotChange() {
52
+ this.panels = this.querySelectorAll('kemet-accordion-panel');
53
+
54
+ this.panels.forEach((panel) => {
55
+ panel.removeEventListener('keydown', this.onKeyDown);
56
+ panel.addEventListener('keydown', this.onKeyDown);
57
+ });
61
58
  }
62
59
 
63
- render() {
64
- return html`
65
- <div id="trigger" tabindex="0" @keyup=${() => this.toggle()} @click="${() => this.toggle()}">
66
- <slot name="trigger"></slot>
67
- </div>
68
- <div id="panel" style="max-height:${this.maxHeight};">
69
- <slot name="panel"></slot>
70
- </div>
71
- `;
60
+ handlePanelOpened(event) {
61
+ if (this.togglePanels) {
62
+ this.panels.forEach((panel) => {
63
+ if (panel !== event.detail) {
64
+ panel.opened = false;
65
+ }
66
+ });
67
+ }
72
68
  }
73
69
 
74
- toggle() {
75
- this.opened = !this.opened;
70
+ navigatePanels(direction) {
71
+ switch (direction) {
72
+ case 'home':
73
+ this.currentPanel = 0;
74
+ break;
75
+ case 'end':
76
+ this.currentPanel = this.panels.length - 1;
77
+ break;
78
+ case 'next':
79
+ this.currentPanel += 1;
80
+ break;
81
+ case 'prev':
82
+ this.currentPanel -= 1;
83
+ break;
84
+ default:
85
+ this.currentPanelFocus = 0;
86
+ break;
87
+ }
88
+
89
+ if (this.currentPanel > this.panels.length - 1) this.currentPanel = 0;
90
+ if (this.currentPanel < 0) this.currentPanel = this.panels.length - 1;
76
91
 
77
- if (this.opened) {
78
- this.closeAll();
79
- this.opened = true;
80
- this.maxHeight = `${this.panelElement.offsetHeight}px`;
81
- } else {
82
- this.maxHeight = '0px';
92
+ this.panels[this.currentPanel].shadowRoot.querySelector('button').focus();
93
+ }
94
+
95
+ handleKeyDown(event) {
96
+ switch (event.key) {
97
+ case 'Enter':
98
+ case 'Space':
99
+ event.preventDefault();
100
+ event.target.click();
101
+ break;
102
+ case 'ArrowLeft':
103
+ case 'ArrowUp':
104
+ event.preventDefault();
105
+ this.navigatePanels('prev');
106
+ break;
107
+ case 'ArrowRight':
108
+ case 'ArrowDown':
109
+ event.preventDefault();
110
+ this.navigatePanels('next');
111
+ break;
112
+ case 'End':
113
+ event.preventDefault();
114
+ this.navigatePanels('end');
115
+ break;
116
+ case 'Home':
117
+ event.preventDefault();
118
+ this.navigatePanels('home');
119
+ break;
120
+ default:
121
+ break;
83
122
  }
84
123
  }
85
124
 
86
- makeEvent(type) {
87
- this.dispatchEvent(
88
- new CustomEvent(`kemet-accordion-${type}`, {
89
- bubbles: true,
90
- composed: true,
91
- detail: this,
92
- }),
93
- );
125
+ expandAll() {
126
+ this.panels.forEach((panel) => {
127
+ panel.opened = true;
128
+ });
94
129
  }
95
130
 
96
- closeAll() {
97
- if (this.closeOthers) {
98
- document.querySelectorAll('kemet-accordion').forEach((accordion) => {
99
- accordion.opened = false;
100
- accordion.maxHeight = '0px';
101
- });
102
- }
131
+ collapseAll() {
132
+ this.panels.forEach((panel) => {
133
+ panel.opened = false;
134
+ });
103
135
  }
104
136
  }
105
137
 
106
- window.customElements.define('kemet-accordion', KemetAccordion);
138
+ // eslint-disable-next-line no-unused-expressions
139
+ customElements.get('kemet-accordion') || customElements.define('kemet-accordion', KemetAccordion);
@@ -0,0 +1,102 @@
1
+ import { html, css, LitElement } from 'lit';
2
+
3
+ export default class KemetBadge extends LitElement {
4
+ static get styles() {
5
+ return [
6
+ css`
7
+ :host {
8
+ display: inline-flex;
9
+ align-items: center;
10
+ justify-content: center;
11
+ padding: var(--kemet-badge-padding, 10px);
12
+ line-height: 1;
13
+ color: var(--kemet-color-white);
14
+ }
15
+
16
+ :host([status='primary']) {
17
+ background-color: var(--kemet-color-primary);
18
+ }
19
+
20
+ :host([status='success']) {
21
+ background-color: var(--kemet-color-success);
22
+ }
23
+
24
+ :host([status='standard']) {
25
+ background-color: var(--kemet-color-gray6);
26
+ }
27
+
28
+ :host([status='warning']) {
29
+ background-color: var(--kemet-color-warning);
30
+ }
31
+
32
+ :host([status='error']) {
33
+ background-color: var(--kemet-color-error);
34
+ }
35
+
36
+ :host([circle]) {
37
+ border-radius: 50%;
38
+ }
39
+
40
+ :host([pill]) {
41
+ border-radius: 99rem;
42
+ }
43
+ `,
44
+ ];
45
+ }
46
+
47
+ static get properties() {
48
+ return {
49
+ /**
50
+ * The status of the badge
51
+ */
52
+ status: {
53
+ type: String,
54
+ reflect: true,
55
+ },
56
+ /**
57
+ * Displays the badge in a circle
58
+ */
59
+ circle: {
60
+ type: Boolean,
61
+ reflect: true,
62
+ },
63
+ /**
64
+ * Rounds the corners on the badge
65
+ */
66
+ pill: {
67
+ type: Boolean,
68
+ reflect: true,
69
+ },
70
+ /**
71
+ * Padding on the badge as a circle
72
+ */
73
+ circlePadding: {
74
+ type: Number,
75
+ attribute: 'circle-padding',
76
+ },
77
+ };
78
+ }
79
+
80
+ constructor() {
81
+ super();
82
+
83
+ this.status = 'primary';
84
+ this.pill = false;
85
+ this.circle = false;
86
+ this.circlePadding = 0;
87
+ }
88
+
89
+ render() {
90
+ return html`<slot @slotchange=${() => this.handleSlotChange()}></slot>`;
91
+ }
92
+
93
+ handleSlotChange() {
94
+ if (this.circle) {
95
+ this.style.height = `${this.offsetWidth + this.circlePadding}px`;
96
+ this.style.width = `${this.offsetWidth + this.circlePadding}px`;
97
+ }
98
+ }
99
+ }
100
+
101
+ // eslint-disable-next-line no-unused-expressions
102
+ customElements.get('kemet-badge') || customElements.define('kemet-badge', KemetBadge);