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,650 @@
1
+ import { html, css, LitElement } from 'lit';
2
+ import { ifDefined } from 'lit/directives/if-defined.js';
3
+ import { live } from 'lit/directives/live.js';
4
+ import { FormSubmitController } from '../../utilities/controllers/forms.js';
5
+
6
+ export default class KemetInput extends LitElement {
7
+ static get styles() {
8
+ return [
9
+ css`
10
+ :host {
11
+ position: relative;
12
+ display: block;
13
+ }
14
+
15
+ input {
16
+ display: block;
17
+ font-size: 1rem;
18
+ width: 100%;
19
+ height: var(--kemet-input-height, 50px);
20
+ padding: var(--kemet-input-padding, 0.5rem 1rem);
21
+ border: var(--kemet-input-border, 1px solid var(--kemet-color-primary));
22
+ appearance: none;
23
+ box-sizing: border-box;
24
+ }
25
+
26
+ input[type='color'] {
27
+ min-width: 10rem;
28
+ }
29
+
30
+ input[type='search']::-webkit-search-decoration,
31
+ input[type='search']::-webkit-search-cancel-button,
32
+ input[type='search']::-webkit-search-results-button,
33
+ input[type='search']::-webkit-search-results-decoration {
34
+ display: none;
35
+ }
36
+
37
+ :host([status='error']) input {
38
+ border: var(--kemet-input-border-color-error, 1px solid var(--kemet-color-error));
39
+ }
40
+
41
+ :host([status='success']) input {
42
+ border: var(--kemet-input-border-color-success, 1px solid var(--kemet-color-success));
43
+ }
44
+
45
+ :host([status='warning']) input {
46
+ border: var(--kemet-input-border-color-warning, 1px solid var(--kemet-color-warning));
47
+ }
48
+
49
+ :host([disabled]) input {
50
+ opacity: 0.5;
51
+ }
52
+
53
+ :host([icon-left]) input {
54
+ padding-left: var(--kemet-input-icon-left-padding, 3rem);
55
+ }
56
+
57
+ :host([icon-right]) input {
58
+ padding-right: var(--kemet-input-icon-right-padding, 3rem);
59
+ }
60
+
61
+ :host([rounded]) input {
62
+ border-radius: var(--kemet-input-border-radius-rounded, var(--kemet-border-radius));
63
+ }
64
+
65
+ :host([filled]) input {
66
+ border: var(--kemet-input-border-filled, none);
67
+ color: var(--kemet-input-color-filled, var(--kemet-color-white));
68
+ background-color: var(--kemet-input-background-color-filled, var(--kemet-color-primary));
69
+ }
70
+
71
+ :host([filled]) kemet-icon,
72
+ :host([filled]) input::placeholder {
73
+ color: var(--kemet-input-color-filled, var(--kemet-color-white));
74
+ }
75
+
76
+ :host([status='error'][filled]) input {
77
+ background-color: var(--kemet-input-background-color-error, var(--kemet-color-error));
78
+ }
79
+
80
+ :host([status='success'][filled]) input {
81
+ background-color: var(--kemet-input-background-color-success, var(--kemet-color-success));
82
+ }
83
+
84
+ :host([status='warning'][filled]) input {
85
+ background-color: var(--kemet-input-background-color-warning, var(--kemet-color-warning));
86
+ }
87
+
88
+ kemet-icon {
89
+ color: var(--kemet-color-primary);
90
+ position: absolute;
91
+ top: 50%;
92
+ transform: translateY(-50%);
93
+ }
94
+
95
+ kemet-icon.left {
96
+ left: 1rem;
97
+ }
98
+
99
+ kemet-icon.right {
100
+ right: 1rem;
101
+ }
102
+
103
+ kemet-icon.eye,
104
+ kemet-icon.search {
105
+ cursor: pointer;
106
+ }
107
+
108
+ :host([status='error']) kemet-icon {
109
+ color: var(--kemet-color-error);
110
+ }
111
+
112
+ :host([status='warning']) kemet-icon {
113
+ color: var(--kemet-color-error);
114
+ }
115
+
116
+ :host([status='success']) kemet-icon {
117
+ color: var(--kemet-color-success);
118
+ }
119
+ `,
120
+ ];
121
+ }
122
+
123
+ static get properties() {
124
+ return {
125
+ /**
126
+ * Used for the id of the input. Should match the slug used in a control if applicable.
127
+ */
128
+ slug: {
129
+ type: String,
130
+ },
131
+ /**
132
+ * The name of the input
133
+ */
134
+ name: {
135
+ type: String,
136
+ },
137
+ /**
138
+ * The placeholder attribute
139
+ */
140
+ placeholder: {
141
+ type: String,
142
+ },
143
+ /**
144
+ * The minlength attribute
145
+ */
146
+ minlength: {
147
+ type: String,
148
+ },
149
+ /**
150
+ * The maxlength attribute
151
+ */
152
+ maxlength: {
153
+ type: String,
154
+ },
155
+ /**
156
+ * The min attribute
157
+ */
158
+ min: {
159
+ type: String,
160
+ },
161
+ /**
162
+ * The max attribute
163
+ */
164
+ max: {
165
+ type: String,
166
+ },
167
+ /**
168
+ * The step attribute
169
+ */
170
+ step: {
171
+ type: String,
172
+ },
173
+ /**
174
+ * The autocomplete attribute
175
+ */
176
+ autocomplete: {
177
+ type: String,
178
+ },
179
+ /**
180
+ * The pattern attribute
181
+ */
182
+ pattern: {
183
+ type: String,
184
+ },
185
+ /**
186
+ * The input mode attribute
187
+ */
188
+ inputmode: {
189
+ type: String,
190
+ },
191
+ /**
192
+ * The autofocus attribute
193
+ */
194
+ autofocus: {
195
+ type: Boolean,
196
+ },
197
+ /**
198
+ * The disable attribute
199
+ */
200
+ disabled: {
201
+ type: Boolean,
202
+ reflect: true,
203
+ },
204
+ /**
205
+ * The readonly attribute
206
+ */
207
+ readonly: {
208
+ type: Boolean,
209
+ },
210
+ /**
211
+ * The required attribute
212
+ */
213
+ required: {
214
+ type: Boolean,
215
+ reflect: true,
216
+ },
217
+ /**
218
+ * The type of input
219
+ */
220
+ type: {
221
+ type: String,
222
+ },
223
+ /**
224
+ * The input's value
225
+ */
226
+ value: {
227
+ type: String,
228
+ },
229
+ /**
230
+ * States whether or not the input is invalid
231
+ */
232
+ invalid: {
233
+ type: Boolean,
234
+ reflect: true,
235
+ },
236
+ /**
237
+ * The status of the input
238
+ */
239
+ status: {
240
+ type: String,
241
+ reflect: true,
242
+ },
243
+ /**
244
+ * Activates validation on blur
245
+ */
246
+ validateOnBlur: {
247
+ type: Boolean,
248
+ attribute: 'validate-on-blur',
249
+ },
250
+ /**
251
+ * Aria Autocomplete
252
+ */
253
+ ariaAutoComplete: {
254
+ type: String,
255
+ attribute: 'aria-autocomplete',
256
+ },
257
+ /**
258
+ * Aria Controls
259
+ */
260
+ ariaControls: {
261
+ type: String,
262
+ attribute: 'aria-controls',
263
+ },
264
+ /**
265
+ * Aria Active Descendant
266
+ */
267
+ ariaActiveDescendant: {
268
+ type: String,
269
+ attribute: 'aria-activedescendant',
270
+ },
271
+ /**
272
+ * Displays rounded corners
273
+ */
274
+ rounded: {
275
+ type: Boolean,
276
+ reflect: true,
277
+ },
278
+ /**
279
+ * Displays a filled input box
280
+ */
281
+ filled: {
282
+ type: Boolean,
283
+ reflect: true,
284
+ },
285
+ /**
286
+ * Custom Icon to the right of the input
287
+ */
288
+ iconRight: {
289
+ type: String,
290
+ reflect: true,
291
+ attribute: 'icon-right',
292
+ },
293
+ /**
294
+ * Custom Icon to the left of the input
295
+ */
296
+ iconLeft: {
297
+ type: String,
298
+ reflect: true,
299
+ attribute: 'icon-left',
300
+ },
301
+ /**
302
+ * Size of the icons
303
+ */
304
+ iconSize: {
305
+ type: Number,
306
+ },
307
+ /**
308
+ * The HTML5 validity object.
309
+ */
310
+ validity: {
311
+ type: Object,
312
+ },
313
+ /**
314
+ * Manages password visibility
315
+ */
316
+ isPasswordVisible: {
317
+ type: Boolean,
318
+ },
319
+ /**
320
+ * Input Type of keypress handled through handleInput(e)
321
+ */
322
+ inputType: {
323
+ type: String,
324
+ },
325
+ };
326
+ }
327
+
328
+ constructor() {
329
+ super();
330
+
331
+ // managed properties
332
+ this.name = 'input';
333
+ this.type = 'text';
334
+ this.value = '';
335
+ this.status = 'standard';
336
+ this.iconSize = 20;
337
+ this.validateOnBlur = false;
338
+ this.isPasswordVisible = false;
339
+
340
+ /**
341
+ * Used only for form reactive controller
342
+ */
343
+ this.formSubmitController = new FormSubmitController(this);
344
+ }
345
+
346
+ firstUpdated() {
347
+ // elements
348
+ this.input = this.shadowRoot.querySelector('input');
349
+ this.field = this.closest('kemet-field');
350
+ this.form = this.closest('form');
351
+ this.slug = this.field ? this.field.slug : 'input';
352
+ }
353
+
354
+ render() {
355
+ return html`
356
+ <div>
357
+ ${this.makeIconLeft()}
358
+ <input
359
+ part="input"
360
+ id=${this.slug}
361
+ name=${this.name}
362
+ placeholder=${ifDefined(this.placeholder)}
363
+ minlength=${ifDefined(this.minlength)}
364
+ maxlength=${ifDefined(this.maxlength)}
365
+ min=${ifDefined(this.min)}
366
+ max=${ifDefined(this.max)}
367
+ step=${ifDefined(this.step)}
368
+ autocomplete=${ifDefined(this.autocomplete)}
369
+ aria-autocomplete=${ifDefined(this.ariaAutoComplete)}
370
+ aria-controls=${ifDefined(this.ariaControls)}
371
+ aria-activedescendant=${ifDefined(this.ariaActiveDescendant)}
372
+ pattern=${ifDefined(this.pattern)}
373
+ inputmode=${ifDefined(this.inputmode)}
374
+ aria-invalid=${this.invalid ? 'true' : 'false'}
375
+ ?autofocus=${this.autofocus}
376
+ ?disabled=${this.disabled}
377
+ ?readonly=${this.readonly}
378
+ ?required=${this.required}
379
+ .type="${this.type === 'password' && this.isPasswordVisible ? 'text' : this.type}"
380
+ .value=${live(this.value)}
381
+ @change=${this.handleChange}
382
+ @input=${this.handleInput}
383
+ @invalid=${this.handleInvalid}
384
+ @focus=${this.handleFocus}
385
+ @blur=${this.handleBlur}
386
+ />
387
+ ${this.makeIconRight()} ${this.makeIconClear()} ${this.makeVisibilityToggle()}
388
+ </div>
389
+ `;
390
+ }
391
+
392
+ /**
393
+ * Makes the right icon
394
+ * @private
395
+ * @returns {templateResult} A right icon
396
+ */
397
+ makeIconRight() {
398
+ if (this.iconRight) {
399
+ return html`
400
+ <kemet-icon class="right" icon="${this.iconRight}" size="${this.iconSize ? this.iconSize : 20}"></kemet-icon>
401
+ `;
402
+ }
403
+
404
+ return null;
405
+ }
406
+
407
+ /**
408
+ * Makes the left icon
409
+ * @private
410
+ * @returns {templateResult} A left icon
411
+ */
412
+ makeIconLeft() {
413
+ if (this.iconLeft) {
414
+ return html`
415
+ <kemet-icon class="left" icon="${this.iconLeft}" size="${this.iconSize ? this.iconSize : 16}"></kemet-icon>
416
+ `;
417
+ }
418
+
419
+ return null;
420
+ }
421
+
422
+ /**
423
+ * Makes a clear icon for search.
424
+ * @private
425
+ * @returns {templateResult} A search icon
426
+ */
427
+ makeIconClear() {
428
+ if (this.type === 'search' && this.value !== '') {
429
+ return html`
430
+ <kemet-icon class="search right" icon="x-lg" size="${this.iconSize}" @click=${() => this.handleClear()}></kemet-icon>
431
+ `;
432
+ }
433
+
434
+ return null;
435
+ }
436
+
437
+ /**
438
+ * Makes a password visibility toggle button
439
+ * @returns {templateResult} A mask or unmask icon
440
+ */
441
+ makeVisibilityToggle() {
442
+ if (this.type === 'password') {
443
+ return html`<kemet-icon
444
+ class="eye right"
445
+ icon="${this.setPasswordIcon()}"
446
+ @click=${() => this.togglePasswordVisibility()}
447
+ ></kemet-icon>`;
448
+ }
449
+
450
+ return null;
451
+ }
452
+
453
+ setPasswordIcon() {
454
+ if (this.isPasswordVisible) {
455
+ return 'eye';
456
+ }
457
+
458
+ return 'eye-slash';
459
+ }
460
+
461
+ /**
462
+ * Handles when the input receives focus
463
+ * @private
464
+ */
465
+ handleFocus() {
466
+ this.hasFocus = true;
467
+
468
+ /**
469
+ * Fires when the input receives and loses focus
470
+ */
471
+ this.dispatchEvent(
472
+ new CustomEvent('kemet-input-focused', {
473
+ bubbles: true,
474
+ composed: true,
475
+ detail: true,
476
+ }),
477
+ );
478
+ }
479
+
480
+ /**
481
+ * Handles when the input loses focus
482
+ * @private
483
+ */
484
+ handleBlur() {
485
+ if (this.validateOnBlur && this.form && !this.form.noValidate) {
486
+ this.input.checkValidity();
487
+ this.validity = this.input.validity;
488
+ }
489
+
490
+ this.hasFocus = false;
491
+
492
+ /**
493
+ * Fires when the input receives and loses focus
494
+ */
495
+ this.dispatchEvent(
496
+ new CustomEvent('kemet-input-focused', {
497
+ bubbles: true,
498
+ composed: true,
499
+ detail: false,
500
+ }),
501
+ );
502
+ }
503
+
504
+ /**
505
+ * Handles when the input changes value
506
+ * @private
507
+ */
508
+ handleChange() {
509
+ this.value = this.input.value;
510
+
511
+ if (this.input.checkValidity() && this.checkLimitValidity() && this.status !== 'success') {
512
+ this.invalid = false;
513
+ this.status = 'standard';
514
+ this.validity = this.input.validity;
515
+
516
+ /**
517
+ * Fires when there's a change in status.
518
+ * This event includes an object that reports:
519
+ * 1) the status. 2) HTML5 validity object. 3) the component element.
520
+ * Use the validity object to support custom validation messages.
521
+ */
522
+ this.dispatchEvent(
523
+ new CustomEvent('kemet-input-status', {
524
+ bubbles: true,
525
+ composed: true,
526
+ detail: {
527
+ status: 'standard',
528
+ validity: this.input.validity,
529
+ element: this,
530
+ },
531
+ }),
532
+ );
533
+ }
534
+ }
535
+
536
+ /**
537
+ * Handles when the input receives input
538
+ * @private
539
+ */
540
+ handleInput(e) {
541
+ this.inputType = e.inputType;
542
+ this.value = this.input.value;
543
+
544
+ /**
545
+ * Fires when the input receives input
546
+ */
547
+ this.dispatchEvent(
548
+ new CustomEvent('kemet-input-input', {
549
+ bubbles: true,
550
+ composed: true,
551
+ detail: this.value,
552
+ }),
553
+ );
554
+ }
555
+
556
+ /**
557
+ * Handles when the input has an error
558
+ * @private
559
+ */
560
+ handleInvalid() {
561
+ this.validity = this.input.validity;
562
+
563
+ if (this.validateOnBlur) {
564
+ this.invalid = true;
565
+ this.status = 'error';
566
+
567
+ /**
568
+ * Fires when there's a change in status
569
+ */
570
+ this.dispatchEvent(
571
+ new CustomEvent('kemet-input-status', {
572
+ bubbles: true,
573
+ composed: true,
574
+ detail: {
575
+ status: 'error',
576
+ validity: this.input.validity,
577
+ element: this,
578
+ },
579
+ }),
580
+ );
581
+ }
582
+ }
583
+
584
+ handleStatus(event) {
585
+ this.status = event.detail.status;
586
+ }
587
+
588
+ /**
589
+ * Toggles password visibility
590
+ * @private
591
+ */
592
+ togglePasswordVisibility() {
593
+ this.isPasswordVisible = !this.isPasswordVisible;
594
+ }
595
+
596
+ /**
597
+ * Handles the clear button for search
598
+ * @private
599
+ */
600
+ handleClear() {
601
+ this.value = '';
602
+
603
+ /**
604
+ * Fires when the input receives input
605
+ */
606
+ this.dispatchEvent(
607
+ new CustomEvent('kemet-input-input', {
608
+ bubbles: true,
609
+ composed: true,
610
+ detail: this.value,
611
+ }),
612
+ );
613
+ }
614
+
615
+ /**
616
+ * Checks the validity of the character limit for the count component
617
+ * @private
618
+ * @returns {boolean}
619
+ */
620
+ checkLimitValidity() {
621
+ if (this.field) {
622
+ const count = this.field.querySelector('kemet-count');
623
+ if (count) {
624
+ return this.value.length < count.limit;
625
+ }
626
+ }
627
+
628
+ return true;
629
+ }
630
+
631
+ /**
632
+ * Checks the validity of the standard input
633
+ * @public
634
+ * @returns {boolean}
635
+ */
636
+ checkValidity() {
637
+ return this.input.checkValidity();
638
+ }
639
+
640
+ /**
641
+ * Focuses the standard input
642
+ * @public
643
+ */
644
+ focus() {
645
+ this.input.focus();
646
+ }
647
+ }
648
+
649
+ // eslint-disable-next-line no-unused-expressions
650
+ customElements.get('kemet-input') || customElements.define('kemet-input', KemetInput);
@@ -1,6 +1,21 @@
1
- import { html, LitElement } from 'lit';
1
+ import { css, html, LitElement } from 'lit';
2
+
3
+ export default class KemetModalClose extends LitElement {
4
+ static get styles() {
5
+ return [
6
+ css`
7
+ :host {
8
+ position: absolute;
9
+ top: -0.5rem;
10
+ right: -0.5rem;
11
+ border: 2px solid white;
12
+ border-radius: 50%;
13
+ cursor: pointer;
14
+ }
15
+ `,
16
+ ];
17
+ }
2
18
 
3
- export class KemetModalClose extends LitElement {
4
19
  render() {
5
20
  return html`
6
21
  <slot @keyup=${() => this.close()} @click=${() => this.close()}></slot>
@@ -8,7 +23,10 @@ export class KemetModalClose extends LitElement {
8
23
  }
9
24
 
10
25
  close() {
11
- this.dispatchEvent(new CustomEvent('kemet-modal-close-btn', {
26
+ /**
27
+ * Fires when the close button is pressed
28
+ */
29
+ this.dispatchEvent(new CustomEvent('kemet-modal-close-pressed', {
12
30
  bubbles: true,
13
31
  composed: true,
14
32
  detail: this,
@@ -16,4 +34,5 @@ export class KemetModalClose extends LitElement {
16
34
  }
17
35
  }
18
36
 
19
- window.customElements.define('kemet-modal-close', KemetModalClose);
37
+ // eslint-disable-next-line no-unused-expressions
38
+ customElements.get('kemet-modal-close') || customElements.define('kemet-modal-close', KemetModalClose);