kemet-ui 1.2.0 → 1.3.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.
@@ -463,107 +463,6 @@ class KemetAccordion extends s$1 {
463
463
  // eslint-disable-next-line no-unused-expressions
464
464
  customElements.get('kemet-accordion') || customElements.define('kemet-accordion', KemetAccordion);
465
465
 
466
- class KemetBadge extends s$1 {
467
- static get styles() {
468
- return [
469
- r$3`
470
- :host {
471
- display: inline-flex;
472
- align-items: center;
473
- justify-content: center;
474
- padding: var(--kemet-badge-padding, 10px);
475
- line-height: 1;
476
- color: var(--kemet-color-white);
477
- }
478
-
479
- :host([status='primary']) {
480
- background-color: var(--kemet-color-primary);
481
- }
482
-
483
- :host([status='success']) {
484
- background-color: var(--kemet-color-success);
485
- }
486
-
487
- :host([status='standard']) {
488
- background-color: var(--kemet-color-gray6);
489
- }
490
-
491
- :host([status='warning']) {
492
- background-color: var(--kemet-color-warning);
493
- }
494
-
495
- :host([status='error']) {
496
- background-color: var(--kemet-color-error);
497
- }
498
-
499
- :host([circle]) {
500
- border-radius: 50%;
501
- }
502
-
503
- :host([pill]) {
504
- border-radius: 99rem;
505
- }
506
- `,
507
- ];
508
- }
509
-
510
- static get properties() {
511
- return {
512
- /**
513
- * The status of the badge
514
- */
515
- status: {
516
- type: String,
517
- reflect: true,
518
- },
519
- /**
520
- * Displays the badge in a circle
521
- */
522
- circle: {
523
- type: Boolean,
524
- reflect: true,
525
- },
526
- /**
527
- * Rounds the corners on the badge
528
- */
529
- pill: {
530
- type: Boolean,
531
- reflect: true,
532
- },
533
- /**
534
- * Padding on the badge as a circle
535
- */
536
- circlePadding: {
537
- type: Number,
538
- attribute: 'circle-padding',
539
- },
540
- };
541
- }
542
-
543
- constructor() {
544
- super();
545
-
546
- this.status = 'primary';
547
- this.pill = false;
548
- this.circle = false;
549
- this.circlePadding = 0;
550
- }
551
-
552
- render() {
553
- return $`<slot @slotchange=${() => this.handleSlotChange()}></slot>`;
554
- }
555
-
556
- handleSlotChange() {
557
- if (this.circle) {
558
- this.style.height = `${this.offsetWidth + this.circlePadding}px`;
559
- this.style.width = `${this.offsetWidth + this.circlePadding}px`;
560
- }
561
- }
562
- }
563
-
564
- // eslint-disable-next-line no-unused-expressions
565
- customElements.get('kemet-badge') || customElements.define('kemet-badge', KemetBadge);
566
-
567
466
  class FormSubmitController {
568
467
  host;
569
468
  form;
@@ -915,51 +814,45 @@ class KemetButton extends s$1 {
915
814
  // eslint-disable-next-line no-unused-expressions
916
815
  customElements.get('kemet-button') || customElements.define('kemet-button', KemetButton);
917
816
 
918
- class KemetCarouselCurrent extends s$1 {
817
+ class KemetBadge extends s$1 {
919
818
  static get styles() {
920
819
  return [
921
820
  r$3`
922
821
  :host {
923
- display: inline-block;
822
+ display: inline-flex;
823
+ align-items: center;
824
+ justify-content: center;
825
+ padding: var(--kemet-badge-padding, 10px);
826
+ line-height: 1;
827
+ color: var(--kemet-color-white);
924
828
  }
925
- `,
926
- ];
927
- }
928
829
 
929
- static get properties() {
930
- return {
931
- current: {
932
- type: Number,
933
- },
934
- };
935
- }
830
+ :host([status='primary']) {
831
+ background-color: var(--kemet-color-primary);
832
+ }
936
833
 
937
- firstUpdated() {
938
- this.carousel = this.closest('kemet-carousel');
939
- }
834
+ :host([status='success']) {
835
+ background-color: var(--kemet-color-success);
836
+ }
940
837
 
941
- updated() {
942
- this.current = this.carousel.index + 1;
943
- }
838
+ :host([status='standard']) {
839
+ background-color: var(--kemet-color-gray6);
840
+ }
944
841
 
945
- render() {
946
- return $`${this.current}`;
947
- }
948
- }
842
+ :host([status='warning']) {
843
+ background-color: var(--kemet-color-warning);
844
+ }
949
845
 
950
- // eslint-disable-next-line no-unused-expressions
951
- customElements.get('kemet-carousel-current') || customElements.define('kemet-carousel-current', KemetCarouselCurrent);
846
+ :host([status='error']) {
847
+ background-color: var(--kemet-color-error);
848
+ }
952
849
 
953
- class KemetCarouselFirst extends s$1 {
954
- static get styles() {
955
- return [
956
- r$3`
957
- :host {
958
- cursor: pointer;
850
+ :host([circle]) {
851
+ border-radius: 50%;
959
852
  }
960
853
 
961
- :host([disabled]) {
962
- cursor: not-allowed;
854
+ :host([pill]) {
855
+ border-radius: 99rem;
963
856
  }
964
857
  `,
965
858
  ];
@@ -967,195 +860,168 @@ class KemetCarouselFirst extends s$1 {
967
860
 
968
861
  static get properties() {
969
862
  return {
970
- disabled: {
863
+ /**
864
+ * The status of the badge
865
+ */
866
+ status: {
867
+ type: String,
868
+ reflect: true,
869
+ },
870
+ /**
871
+ * Displays the badge in a circle
872
+ */
873
+ circle: {
874
+ type: Boolean,
875
+ reflect: true,
876
+ },
877
+ /**
878
+ * Rounds the corners on the badge
879
+ */
880
+ pill: {
971
881
  type: Boolean,
972
882
  reflect: true,
973
883
  },
884
+ /**
885
+ * Padding on the badge as a circle
886
+ */
887
+ circlePadding: {
888
+ type: Number,
889
+ attribute: 'circle-padding',
890
+ },
974
891
  };
975
892
  }
976
893
 
894
+ constructor() {
895
+ super();
896
+
897
+ this.status = 'primary';
898
+ this.pill = false;
899
+ this.circle = false;
900
+ this.circlePadding = 0;
901
+ }
902
+
977
903
  render() {
978
- return $`
979
- <span tabindex="0" @keyup=${() => this.first()} @click=${() => this.first()}>
980
- <slot></slot>
981
- </span>
982
- `;
904
+ return $`<slot @slotchange=${() => this.handleSlotChange()}></slot>`;
983
905
  }
984
906
 
985
- first() {
986
- if (!this.disabled) {
987
- this.dispatchEvent(new CustomEvent('kemet-carousel-first', {
988
- bubbles: true,
989
- composed: true,
990
- detail: this,
991
- }));
907
+ handleSlotChange() {
908
+ if (this.circle) {
909
+ this.style.height = `${this.offsetWidth + this.circlePadding}px`;
910
+ this.style.width = `${this.offsetWidth + this.circlePadding}px`;
992
911
  }
993
912
  }
994
913
  }
995
914
 
996
915
  // eslint-disable-next-line no-unused-expressions
997
- customElements.get('kemet-carousel-first') || customElements.define('kemet-carousel-first', KemetCarouselFirst);
916
+ customElements.get('kemet-badge') || customElements.define('kemet-badge', KemetBadge);
998
917
 
999
- class KemetCarouselLast extends s$1 {
918
+ /**
919
+ * @license
920
+ * Copyright 2018 Google LLC
921
+ * SPDX-License-Identifier: BSD-3-Clause
922
+ */const l$1=l=>null!=l?l:w;
923
+
924
+ /**
925
+ * @license
926
+ * Copyright 2017 Google LLC
927
+ * SPDX-License-Identifier: BSD-3-Clause
928
+ */
929
+ const t={ATTRIBUTE:1,CHILD:2,PROPERTY:3,BOOLEAN_ATTRIBUTE:4,EVENT:5,ELEMENT:6},e$1=t=>(...e)=>({_$litDirective$:t,values:e});class i{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,i){this._$Ct=t,this._$AM=e,this._$Ci=i;}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}}
930
+
931
+ /**
932
+ * @license
933
+ * Copyright 2020 Google LLC
934
+ * SPDX-License-Identifier: BSD-3-Clause
935
+ */const r=o=>void 0===o.strings,f={},s=(o,i=f)=>o._$AH=i;
936
+
937
+ /**
938
+ * @license
939
+ * Copyright 2020 Google LLC
940
+ * SPDX-License-Identifier: BSD-3-Clause
941
+ */const l=e$1(class extends i{constructor(r$1){if(super(r$1),r$1.type!==t.PROPERTY&&r$1.type!==t.ATTRIBUTE&&r$1.type!==t.BOOLEAN_ATTRIBUTE)throw Error("The `live` directive is not allowed on child or event bindings");if(!r(r$1))throw Error("`live` bindings can only contain a single expression")}render(r){return r}update(i,[t$1]){if(t$1===b||t$1===w)return t$1;const o=i.element,l=i.name;if(i.type===t.PROPERTY){if(t$1===o[l])return b}else if(i.type===t.BOOLEAN_ATTRIBUTE){if(!!t$1===o.hasAttribute(l))return b}else if(i.type===t.ATTRIBUTE&&o.getAttribute(l)===t$1+"")return b;return s(i),t$1}});
942
+
943
+ class KemetCheckbox extends s$1 {
1000
944
  static get styles() {
1001
945
  return [
1002
946
  r$3`
947
+ *,
948
+ *::before,
949
+ *::after {
950
+ box-sizing: border-box;
951
+ }
952
+
1003
953
  :host {
1004
- cursor: pointer;
954
+ display: inline-block;
1005
955
  }
1006
956
 
1007
957
  :host([disabled]) {
1008
- cursor: not-allowed;
958
+ opacity: 0.5;
1009
959
  }
1010
- `,
1011
- ];
1012
- }
1013
960
 
1014
- static get properties() {
1015
- return {
1016
- disabled: {
1017
- type: Boolean,
1018
- reflect: true,
1019
- },
1020
- };
1021
- }
1022
-
1023
- render() {
1024
- return $`
1025
- <span tabindex="0" @keyup=${() => this.last()} @click=${() => this.last()}>
1026
- <slot></slot>
1027
- </span>
1028
- `;
1029
- }
1030
-
1031
- last() {
1032
- if (!this.disabled) {
1033
- this.dispatchEvent(new CustomEvent('kemet-carousel-last', {
1034
- bubbles: true,
1035
- composed: true,
1036
- detail: this,
1037
- }));
1038
- }
1039
- }
1040
- }
1041
-
1042
- // eslint-disable-next-line no-unused-expressions
1043
- customElements.get('kemet-carousel-last') || customElements.define('kemet-carousel-last', KemetCarouselLast);
1044
-
1045
- class KemetCarouselLink extends s$1 {
1046
- static get properties() {
1047
- return {
1048
- slide: {
1049
- type: Number,
1050
- reflect: true,
1051
- },
1052
- selected: {
1053
- type: Boolean,
1054
- reflect: true,
1055
- },
1056
- disabled: {
1057
- type: Boolean,
1058
- reflect: true,
1059
- },
1060
- };
1061
- }
1062
-
1063
- static get styles() {
1064
- return [
1065
- r$3`
1066
- :host([selected]) {
1067
- color: var(--kemet-carousel-link-selected-color, var(--kemet-color-primary));
961
+ label {
962
+ display: inline-flex;
963
+ gap: 0.5rem;
964
+ align-items: center;
1068
965
  }
1069
966
 
1070
- :host(:not([selected])) {
967
+ input {
1071
968
  cursor: pointer;
969
+ margin: 0;
970
+ padding: 0;
971
+ width: var(--kemet-checkbox-size, 18px);
972
+ height: var(--kemet-checkbox-size, 18px);
973
+ position: absolute;
974
+ opacity: 0;
1072
975
  }
1073
976
 
1074
- :host([disabled]) {
1075
- cursor: not-allowed;
977
+ button {
978
+ margin: 0;
979
+ border: none;
980
+ background: none;
1076
981
  }
1077
- `,
1078
- ];
1079
- }
1080
-
1081
- render() {
1082
- return $`
1083
- <span tabindex="0" @keyup=${() => this.changed()} @click=${() => this.changed()}>
1084
- <slot></slot>
1085
- </span>
1086
- `;
1087
- }
1088
982
 
1089
- changed() {
1090
- if (!this.disabled) {
1091
- this.dispatchEvent(new CustomEvent('kemet-carousel-link', {
1092
- bubbles: true,
1093
- composed: true,
1094
- detail: this,
1095
- }));
1096
- }
1097
- }
1098
- }
1099
-
1100
- // eslint-disable-next-line no-unused-expressions
1101
- customElements.get('kemet-carousel-link') || customElements.define('kemet-carousel-link', KemetCarouselLink);
1102
-
1103
- class KemetCarouselNext extends s$1 {
1104
- static get styles() {
1105
- return [
1106
- r$3`
1107
- :host {
1108
- cursor: pointer;
983
+ [part='checkbox'] {
984
+ color: var(--kemet-checkbox-color, var(--kemet-color-primary));
985
+ display: flex;
986
+ align-items: center;
987
+ justify-content: center;
988
+ width: var(--kemet-checkbox-size, 18px);
989
+ height: var(--kemet-checkbox-size, 18px);
990
+ border: var(--kemet-checkbox-border, 1px solid var(--kemet-color-primary));
1109
991
  }
1110
992
 
1111
- :host([disabled]) {
1112
- cursor: not-allowed;
993
+ :host([rounded]) [part='checkbox'] {
994
+ border-radius: var(--kemet-checkbox-border-radius, 4px);
1113
995
  }
1114
- `,
1115
- ];
1116
- }
1117
996
 
1118
- static get properties() {
1119
- return {
1120
- disabled: {
1121
- type: Boolean,
1122
- reflect: true,
1123
- },
1124
- };
1125
- }
997
+ :host([filled][checked]) [part='checkbox'],
998
+ :host([filled][indeterminate]) [part='checkbox'] {
999
+ border: none;
1000
+ background-color: var(--kemet-checkbox-filled-background-color, var(--kemet-color-primary));
1001
+ }
1126
1002
 
1127
- render() {
1128
- return $`
1129
- <span tabindex="0" @keyup=${() => this.next()} @click=${() => this.next()}>
1130
- <slot></slot>
1131
- </span>
1132
- `;
1133
- }
1003
+ [part='mark'] {
1004
+ display: flex;
1005
+ width: calc(var(--kemet-checkbox-size, 18px) - 4px);
1006
+ height: calc(var(--kemet-checkbox-size, 18px) - 4px);
1007
+ }
1134
1008
 
1135
- next() {
1136
- if (!this.disabled) {
1137
- this.dispatchEvent(new CustomEvent('kemet-carousel-next', {
1138
- bubbles: true,
1139
- composed: true,
1140
- detail: this,
1141
- }));
1142
- }
1143
- }
1144
- }
1009
+ :host([filled][checked]) [part='mark'],
1010
+ :host([filled][indeterminate]) [part='mark'] {
1011
+ color: var(--kemet-checkbox-filled-color, var(--kemet-color-white));
1012
+ }
1145
1013
 
1146
- // eslint-disable-next-line no-unused-expressions
1147
- customElements.get('kemet-carousel-next') || customElements.define('kemet-carousel-next', KemetCarouselNext);
1014
+ [part='message'] {
1015
+ display: block;
1016
+ margin-top: 0.5rem;
1017
+ }
1148
1018
 
1149
- class KemetCarouselPrev extends s$1 {
1150
- static get styles() {
1151
- return [
1152
- r$3`
1153
- :host {
1154
- cursor: pointer;
1019
+ :host([status='error']) [part='message'] {
1020
+ color: var(--kemet-color-error);
1155
1021
  }
1156
1022
 
1157
- :host([disabled]) {
1158
- cursor: not-allowed;
1023
+ :host([status='warning']) [part='message'] {
1024
+ color: var(--kemet-color-error);
1159
1025
  }
1160
1026
  `,
1161
1027
  ];
@@ -1163,86 +1029,212 @@ class KemetCarouselPrev extends s$1 {
1163
1029
 
1164
1030
  static get properties() {
1165
1031
  return {
1032
+ label: {
1033
+ type: String,
1034
+ },
1035
+ checked: {
1036
+ type: Boolean,
1037
+ reflect: true,
1038
+ },
1039
+ indeterminate: {
1040
+ type: Boolean,
1041
+ reflect: true,
1042
+ },
1043
+ name: {
1044
+ type: String,
1045
+ },
1046
+ value: {
1047
+ type: String,
1048
+ },
1166
1049
  disabled: {
1167
1050
  type: Boolean,
1168
1051
  reflect: true,
1169
1052
  },
1170
- };
1171
- }
1172
-
1173
- render() {
1174
- return $`
1175
- <span tabindex="0" @keyup=${() => this.prev()} @click=${() => this.prev()}>
1176
- <slot></slot>
1177
- </span>
1178
- `;
1179
- }
1180
-
1181
- prev() {
1182
- if (!this.disabled) {
1183
- this.dispatchEvent(new CustomEvent('kemet-carousel-prev', {
1184
- bubbles: true,
1185
- composed: true,
1186
- detail: this,
1187
- }));
1188
- }
1189
- }
1190
- }
1191
-
1192
- // eslint-disable-next-line no-unused-expressions
1193
- customElements.get('kemet-carousel-prev') || customElements.define('kemet-carousel-prev', KemetCarouselPrev);
1194
-
1195
- class KemetCarouselSlide extends s$1 {
1196
- static get styles() {
1197
- return [
1198
- r$3`
1199
- :host,
1200
- :host *,
1201
- :host *::before,
1202
- *::after {
1203
- box-sizing: border-box;
1204
- }
1205
-
1206
- :host {
1207
- flex: 0 0 auto;
1208
- }
1209
- `,
1210
- ];
1211
- }
1212
-
1213
- static get properties() {
1214
- return {
1215
- /**
1216
- * Determines if the slide is selected
1217
- */
1218
- selected: {
1053
+ required: {
1219
1054
  type: Boolean,
1220
1055
  reflect: true,
1221
1056
  },
1222
- 'aria-hidden': {
1057
+ focused: {
1058
+ type: Boolean,
1059
+ reflect: true,
1060
+ },
1061
+ rounded: {
1062
+ type: Boolean,
1063
+ reflect: true,
1064
+ },
1065
+ filled: {
1066
+ type: Boolean,
1067
+ reflect: true,
1068
+ },
1069
+ status: {
1223
1070
  type: String,
1224
1071
  reflect: true,
1225
1072
  },
1073
+ message: {
1074
+ type: String,
1075
+ },
1226
1076
  };
1227
1077
  }
1228
1078
 
1229
1079
  constructor() {
1230
1080
  super();
1231
- this.selected = false;
1232
- this['aria-hidden'] = 'true';
1081
+
1082
+ // managed properties
1083
+ this.label = '';
1084
+ this.name = 'checkbox';
1085
+ this.disabled = false;
1086
+ this.required = false;
1087
+ this.rounded = false;
1088
+ this.filled = false;
1089
+ this.status = 'standard';
1090
+
1091
+ /**
1092
+ * Used only for form reactive controller
1093
+ */
1094
+ this.formSubmitController = new FormSubmitController(this);
1095
+ }
1096
+
1097
+ firstUpdated() {
1098
+ this.input = this.shadowRoot.querySelector('input');
1233
1099
  }
1234
1100
 
1235
1101
  render() {
1236
1102
  return $`
1237
- <slot></slot>
1103
+ <label part="label">
1104
+ <input
1105
+ type="checkbox"
1106
+ name=${l$1(this.name)}
1107
+ .value=${this.value}
1108
+ .indeterminate=${l(this.indeterminate)}
1109
+ .checked=${l(this.checked)}
1110
+ .disabled=${this.disabled}
1111
+ .required=${this.required}
1112
+ aria-checked=${this.checked ? 'true' : 'false'}
1113
+ @click=${() => this.handleClick()}
1114
+ @blur=${() => this.handleBlur()}
1115
+ @focus=${() => this.handleFocus()}
1116
+ @change=${() => this.handleChange()}
1117
+ />
1118
+ <button part="checkbox" aria-label=${this.label}>
1119
+ ${this.makeCheckMark()}
1120
+ </button>
1121
+ <span part="text">${this.label}</span>
1122
+ </label>
1123
+ ${this.makeMessage()}
1238
1124
  `;
1239
1125
  }
1126
+
1127
+ click() {
1128
+ this.input.click();
1129
+ }
1130
+
1131
+ handleClick() {
1132
+ this.checked = !this.checked;
1133
+ this.indeterminate = false;
1134
+
1135
+ /**
1136
+ * Fires when the state of the checkbox changes
1137
+ */
1138
+ this.dispatchEvent(
1139
+ new CustomEvent('kemet-checkbox-change', {
1140
+ bubbles: true,
1141
+ composed: true,
1142
+ detail: this,
1143
+ }),
1144
+ );
1145
+ }
1146
+
1147
+ handleBlur() {
1148
+ this.focused = false;
1149
+
1150
+ /**
1151
+ * Fires when the checkbox loses or receives focus
1152
+ */
1153
+ this.dispatchEvent(
1154
+ new CustomEvent('kemet-checkbox-focused', {
1155
+ bubbles: true,
1156
+ composed: true,
1157
+ detail: false,
1158
+ }),
1159
+ );
1160
+ }
1161
+
1162
+ handleFocus() {
1163
+ this.focused = true;
1164
+ /**
1165
+ * Fires when the checkbox loses or receives focus
1166
+ */
1167
+ this.dispatchEvent(
1168
+ new CustomEvent('kemet-checkbox-focused', {
1169
+ bubbles: true,
1170
+ composed: true,
1171
+ detail: true,
1172
+ }),
1173
+ );
1174
+ }
1175
+
1176
+ handleChange() {
1177
+ this.value = this.checked;
1178
+
1179
+ if (this.input.checkValidity()) {
1180
+ this.status = 'standard';
1181
+ }
1182
+ }
1183
+
1184
+ makeMessage() {
1185
+ if (this.status === 'error' || this.status === 'warning') {
1186
+ return $`<span part="message">${this.message}</span>`;
1187
+ }
1188
+
1189
+ return null;
1190
+ }
1191
+
1192
+ makeCheckMark() {
1193
+ if (this.checked) {
1194
+ return $`
1195
+ <span part="mark">
1196
+ <svg viewBox="0 0 16 16">
1197
+ <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
1198
+ <g stroke="currentColor" stroke-width="2">
1199
+ <g transform="translate(3.428571, 3.428571)">
1200
+ <path d="M0,5.71428571 L3.42857143,9.14285714"></path>
1201
+ <path d="M9.14285714,0 L3.42857143,9.14285714"></path>
1202
+ </g>
1203
+ </g>
1204
+ </g>
1205
+ </svg>
1206
+ </span>
1207
+ `;
1208
+ }
1209
+
1210
+ if (!this.checked && this.indeterminate) {
1211
+ return $`
1212
+ <span part="mark">
1213
+ <svg viewBox="0 0 16 16">
1214
+ <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
1215
+ <g stroke="currentColor" stroke-width="2">
1216
+ <g transform="translate(2.285714, 6.857143)">
1217
+ <path d="M10.2857143,1.14285714 L1.14285714,1.14285714"></path>
1218
+ </g>
1219
+ </g>
1220
+ </g>
1221
+ </svg>
1222
+ </span>
1223
+ `;
1224
+ }
1225
+
1226
+ return null;
1227
+ }
1228
+
1229
+ checkValidity() {
1230
+ return this.input.checkValidity();
1231
+ }
1240
1232
  }
1241
1233
 
1242
1234
  // eslint-disable-next-line no-unused-expressions
1243
- customElements.get('kemet-carousel-slide') || customElements.define('kemet-carousel-slide', KemetCarouselSlide);
1235
+ customElements.get('kemet-checkbox') || customElements.define('kemet-checkbox', KemetCheckbox);
1244
1236
 
1245
- class KemetCarouselTotal extends s$1 {
1237
+ class KemetCarouselCurrent extends s$1 {
1246
1238
  static get styles() {
1247
1239
  return [
1248
1240
  r$3`
@@ -1255,7 +1247,7 @@ class KemetCarouselTotal extends s$1 {
1255
1247
 
1256
1248
  static get properties() {
1257
1249
  return {
1258
- total: {
1250
+ current: {
1259
1251
  type: Number,
1260
1252
  },
1261
1253
  };
@@ -1266,826 +1258,834 @@ class KemetCarouselTotal extends s$1 {
1266
1258
  }
1267
1259
 
1268
1260
  updated() {
1269
- this.total = this.carousel.total;
1261
+ this.current = this.carousel.index + 1;
1270
1262
  }
1271
1263
 
1272
1264
  render() {
1273
- return $`${this.total}`;
1265
+ return $`${this.current}`;
1274
1266
  }
1275
1267
  }
1276
1268
 
1277
1269
  // eslint-disable-next-line no-unused-expressions
1278
- customElements.get('kemet-carousel-total') || customElements.define('kemet-carousel-total', KemetCarouselTotal);
1270
+ customElements.get('kemet-carousel-current') || customElements.define('kemet-carousel-current', KemetCarouselCurrent);
1279
1271
 
1280
- class KemetCarousel extends s$1 {
1272
+ class KemetCarouselFirst extends s$1 {
1281
1273
  static get styles() {
1282
- return r$3`
1283
- :host,
1284
- *,
1285
- *::before,
1286
- *::after {
1287
- box-sizing: border-box;
1288
- }
1289
-
1290
- :host {
1291
- position: relative;
1292
- display: grid;
1293
- grid-template-columns: minmax(0, 1fr);
1294
- align-items: center;
1295
- width: var(--kemet-carousel-width, 100%);
1296
- height: var(--kemet-carousel-height, auto);
1297
- overflow: visible;
1298
- }
1299
-
1300
- :host([arrows]) {
1301
- grid-template-columns: auto minmax(0, 1fr) auto;
1302
- }
1303
-
1304
- .toolbar {
1305
- display: flex;
1306
- gap: var(--kemet-carousel-toolbar-gap, 1rem);
1307
- align-items: center;
1308
- justify-content: var(--kemet-carousel-toolbar-justify-content, center);
1309
- line-height: 1;
1310
- padding: var(--kemet-carousel-toolbar-padding, 1rem);
1311
- }
1312
-
1313
- :host([inner]) .toolbar {
1314
- width: var(--kemet-carousel-toolbar-inner-width, 100%);
1315
- position: absolute;
1316
- bottom: var(--kemet-carousel-toolbar-inner-bottom, 0);
1317
- top: var(--kemet-carousel-toolbar-inner-top, auto);
1318
- color: var(--kemet-carousel-toolbar-inner-color, var(--kemet-color-white));
1319
- background-color: var(--kemet-carousel-toolbar-inner-background-color, rgba(0, 0, 0, 0.4));
1320
- }
1321
-
1322
- .slides {
1323
- overflow: hidden;
1324
- position: relative;
1325
- padding: 1rem 0;
1326
- border: var(--kemet-carousel-slides-border, 1px solid var(--kemet-color-gray1));
1327
- }
1328
-
1329
- .slider {
1330
- display: flex;
1331
- flex-wrap: nowrap;
1332
- transition: transform var(--kemet-carousel-transition-speed, 300ms) ease;
1333
- }
1334
-
1335
- ::slotted([slot='next']),
1336
- ::slotted([slot='prev']) {
1337
- opacity: var(--kemet-carousel-arrows-opacity, 0.25);
1338
- transition: opacity var(--kemet-carousel-arrows-transition-speed, 300ms) ease-in-out;
1339
- }
1274
+ return [
1275
+ r$3`
1276
+ :host {
1277
+ cursor: pointer;
1278
+ }
1340
1279
 
1341
- :host(:hover) ::slotted([slot='next']),
1342
- :host(:hover) ::slotted([slot='prev']) {
1343
- opacity: var(--kemet-carousel-arrows-opacity-hover, 1);
1344
- }
1345
- `;
1280
+ :host([disabled]) {
1281
+ cursor: not-allowed;
1282
+ }
1283
+ `,
1284
+ ];
1346
1285
  }
1347
1286
 
1348
1287
  static get properties() {
1349
1288
  return {
1350
- /**
1351
- * The current slide index.
1352
- */
1353
- index: {
1354
- type: Number,
1289
+ disabled: {
1290
+ type: Boolean,
1355
1291
  reflect: true,
1356
1292
  },
1357
- /**
1358
- * The total amount of slides
1359
- */
1360
- total: {
1361
- type: Number,
1362
- },
1363
- /**
1364
- * The width of the slider
1365
- */
1366
- sliderWidth: {
1367
- type: String,
1368
- },
1369
- /**
1370
- * The X position of the slider
1371
- */
1372
- sliderTranslateX: {
1373
- type: String,
1374
- },
1375
- /**
1376
- * Displays the toolbar inside the carousel container
1377
- */
1378
- inner: {
1379
- type: Boolean,
1380
- reflect: true,
1381
- },
1382
- /**
1383
- * Determines whether or not to display arrows
1384
- */
1385
- arrows: {
1386
- type: Boolean,
1387
- reflect: true,
1388
- },
1389
- /**
1390
- * Default options for the carousel
1391
- */
1392
- options: {
1393
- type: Object,
1394
- },
1395
- /**
1396
- * Options are different breakpoints for the carousel. Is mobile first.
1397
- */
1398
- breakpoints: {
1399
- type: Object,
1400
- },
1401
1293
  };
1402
1294
  }
1403
1295
 
1404
- constructor() {
1405
- super();
1406
-
1407
- // managed properties
1408
- this.index = 0;
1409
- this.total = 0;
1410
- this.sliderWidth = 'auto';
1411
- this.sliderTranslateX = '0';
1412
- this.inner = false;
1413
- this.arrows = false;
1414
- this.options = {
1415
- perView: 1,
1416
- perMove: 1,
1417
- gap: 12,
1418
- slideshow: 0,
1419
- rewind: true,
1420
- center: false,
1421
- };
1422
- this.breakpoints = {
1423
- 768: {
1424
- perView: 2,
1425
- gap: 24,
1426
- rewind: false,
1427
- },
1428
- 1280: {
1429
- perView: 2.5,
1430
- center: true,
1431
- },
1432
- };
1296
+ render() {
1297
+ return $`
1298
+ <span tabindex="0" @keyup=${() => this.first()} @click=${() => this.first()}>
1299
+ <slot></slot>
1300
+ </span>
1301
+ `;
1302
+ }
1433
1303
 
1434
- // bindings
1435
- this.addEventListener('kemet-carousel-first', this.handleFirst.bind(this));
1436
- this.addEventListener('kemet-carousel-last', this.handleLast.bind(this));
1437
- this.addEventListener('kemet-carousel-next', this.handleNext.bind(this));
1438
- this.addEventListener('kemet-carousel-prev', this.handlePrev.bind(this));
1439
- this.addEventListener('kemet-carousel-link', this.handleLink.bind(this));
1304
+ first() {
1305
+ if (!this.disabled) {
1306
+ this.dispatchEvent(new CustomEvent('kemet-carousel-first', {
1307
+ bubbles: true,
1308
+ composed: true,
1309
+ detail: this,
1310
+ }));
1311
+ }
1440
1312
  }
1313
+ }
1441
1314
 
1442
- firstUpdated() {
1443
- // standard properties
1444
- this.slides = [];
1445
- this.links = [];
1315
+ // eslint-disable-next-line no-unused-expressions
1316
+ customElements.get('kemet-carousel-first') || customElements.define('kemet-carousel-first', KemetCarouselFirst);
1446
1317
 
1447
- // elements
1448
- this.containerElement = this.shadowRoot.querySelector('[part="container"]');
1449
- this.slidesElement = this.shadowRoot.querySelector('[part="slides"]');
1450
- this.sliderElement = this.shadowRoot.querySelector('[part="slider"]');
1451
- this.toolbarElement = this.shadowRoot.querySelector('[part="toolbar"]');
1452
- this.toolbarSlotElement = this.querySelector('[slot="toolbar"]');
1453
- this.informationElement = this.querySelector('kemet-carousel-information');
1318
+ class KemetCarouselLast extends s$1 {
1319
+ static get styles() {
1320
+ return [
1321
+ r$3`
1322
+ :host {
1323
+ cursor: pointer;
1324
+ }
1454
1325
 
1455
- // events
1456
- window.addEventListener('resize', () => {
1457
- this.setSlideSize();
1458
- this.setToolbarSize();
1459
- this.updateIndex(this.index);
1460
- });
1326
+ :host([disabled]) {
1327
+ cursor: not-allowed;
1328
+ }
1329
+ `,
1330
+ ];
1331
+ }
1461
1332
 
1462
- this.sliderElement.addEventListener('transitionend', this.handleTransitionEnd.bind(this));
1333
+ static get properties() {
1334
+ return {
1335
+ disabled: {
1336
+ type: Boolean,
1337
+ reflect: true,
1338
+ },
1339
+ };
1340
+ }
1463
1341
 
1464
- // methods
1465
- this.swipeMove = (event) => {
1466
- event.preventDefault();
1342
+ render() {
1343
+ return $`
1344
+ <span tabindex="0" @keyup=${() => this.last()} @click=${() => this.last()}>
1345
+ <slot></slot>
1346
+ </span>
1347
+ `;
1348
+ }
1467
1349
 
1468
- const pageX = event.touches ? event.touches[0].pageX : event.pageX;
1469
- const currentSlide = this.slides[this.index];
1350
+ last() {
1351
+ if (!this.disabled) {
1352
+ this.dispatchEvent(new CustomEvent('kemet-carousel-last', {
1353
+ bubbles: true,
1354
+ composed: true,
1355
+ detail: this,
1356
+ }));
1357
+ }
1358
+ }
1359
+ }
1470
1360
 
1471
- this.sliderTranslateX = `${pageX - this.startX - currentSlide.offsetLeft}px`;
1472
- };
1361
+ // eslint-disable-next-line no-unused-expressions
1362
+ customElements.get('kemet-carousel-last') || customElements.define('kemet-carousel-last', KemetCarouselLast);
1473
1363
 
1474
- this.handleSlideShow = () => {
1475
- if (this.getOption('slideshow') > 0) {
1476
- this.updateIndex(this.index + 1);
1477
- clearTimeout(this.handleSlideShow);
1478
- }
1364
+ class KemetCarouselLink extends s$1 {
1365
+ static get properties() {
1366
+ return {
1367
+ slide: {
1368
+ type: Number,
1369
+ reflect: true,
1370
+ },
1371
+ selected: {
1372
+ type: Boolean,
1373
+ reflect: true,
1374
+ },
1375
+ disabled: {
1376
+ type: Boolean,
1377
+ reflect: true,
1378
+ },
1479
1379
  };
1480
-
1481
- // setup
1482
- this.setSlideSize();
1483
- this.goToSlide(this.index);
1484
1380
  }
1485
1381
 
1486
- updated(prevProps) {
1487
- this.setSlideSize();
1488
- this.setToolbarSize();
1382
+ static get styles() {
1383
+ return [
1384
+ r$3`
1385
+ :host([selected]) {
1386
+ color: var(--kemet-carousel-link-selected-color, var(--kemet-color-primary));
1387
+ }
1489
1388
 
1490
- if (prevProps.has('index')) {
1491
- this.updateIndex(this.index);
1492
- setTimeout(this.handleSlideShow, this.getOption('slideshow') * 1000);
1493
- }
1389
+ :host(:not([selected])) {
1390
+ cursor: pointer;
1391
+ }
1392
+
1393
+ :host([disabled]) {
1394
+ cursor: not-allowed;
1395
+ }
1396
+ `,
1397
+ ];
1494
1398
  }
1495
1399
 
1496
1400
  render() {
1497
1401
  return $`
1498
- <slot name="prev" @slotchange=${this.handleArrows}></slot>
1499
- <div class="container" part="container">
1500
- <section
1501
- class="slides"
1502
- part="slides"
1503
- @mousedown=${this.swipeStart}
1504
- @mouseup=${this.swipeEnd}
1505
- @touchstart=${this.swipeStart}
1506
- @touchend=${this.swipeEnd}
1507
- @mouseleave=${this.swipeLeave}
1508
- >
1509
- <div class="slider" part="slider" style="width:${this.sliderWidth}; transform:translateX(${this.sliderTranslateX});">
1510
- <slot name="slides" @slotchange="${this.handleSlotChange}"></slot>
1511
- </div>
1512
- </section>
1513
- ${this.makeToolbar()}
1514
- </div>
1515
- <slot name="next" @slotchange=${this.handleArrows}></slot>
1402
+ <span tabindex="0" @keyup=${() => this.changed()} @click=${() => this.changed()}>
1403
+ <slot></slot>
1404
+ </span>
1516
1405
  `;
1517
1406
  }
1518
1407
 
1519
- swipeStart(event) {
1520
- this.startX = event.touches ? event.touches[0].pageX : event.pageX;
1521
-
1522
- this.addEventListener('mousemove', this.swipeMove);
1523
- this.addEventListener('touchmove', this.swipeMove);
1408
+ changed() {
1409
+ if (!this.disabled) {
1410
+ this.dispatchEvent(new CustomEvent('kemet-carousel-link', {
1411
+ bubbles: true,
1412
+ composed: true,
1413
+ detail: this,
1414
+ }));
1415
+ }
1524
1416
  }
1417
+ }
1525
1418
 
1526
- swipeEnd(event) {
1527
- this.updateIndex(this.swipeUpdate(event));
1528
- this.removeEventListener('mousemove', this.swipeMove, false);
1529
- this.removeEventListener('touchmove', this.swipeMove, false);
1530
- }
1419
+ // eslint-disable-next-line no-unused-expressions
1420
+ customElements.get('kemet-carousel-link') || customElements.define('kemet-carousel-link', KemetCarouselLink);
1531
1421
 
1532
- swipeUpdate(event) {
1533
- const pageX = event.changedTouches ? event.changedTouches[0].pageX : event.pageX;
1534
- const direction = this.startX > pageX ? 'right' : 'left';
1535
- const threshold = this.slidesElement.offsetWidth / 3;
1536
- const diff = this.startX - pageX;
1537
- const shouldUpdate = Math.abs(diff) > threshold;
1422
+ class KemetCarouselNext extends s$1 {
1423
+ static get styles() {
1424
+ return [
1425
+ r$3`
1426
+ :host {
1427
+ cursor: pointer;
1428
+ }
1538
1429
 
1539
- let { index } = this;
1430
+ :host([disabled]) {
1431
+ cursor: not-allowed;
1432
+ }
1433
+ `,
1434
+ ];
1435
+ }
1540
1436
 
1541
- if (shouldUpdate && direction === 'right') {
1542
- index = this.index >= this.slides.length - 1 ? this.index : this.index + 1;
1543
- }
1544
-
1545
- if (shouldUpdate && direction === 'left') {
1546
- index = this.index < 1 ? 0 : this.index - 1;
1547
- }
1437
+ static get properties() {
1438
+ return {
1439
+ disabled: {
1440
+ type: Boolean,
1441
+ reflect: true,
1442
+ },
1443
+ };
1444
+ }
1548
1445
 
1549
- return index;
1446
+ render() {
1447
+ return $`
1448
+ <span tabindex="0" @keyup=${() => this.next()} @click=${() => this.next()}>
1449
+ <slot></slot>
1450
+ </span>
1451
+ `;
1550
1452
  }
1551
1453
 
1552
- swipeLeave() {
1553
- this.updateIndex(this.index);
1554
- this.removeEventListener('mousemove', this.swipeMove, false);
1555
- this.removeEventListener('touchmove', this.swipeMove, false);
1454
+ next() {
1455
+ if (!this.disabled) {
1456
+ this.dispatchEvent(new CustomEvent('kemet-carousel-next', {
1457
+ bubbles: true,
1458
+ composed: true,
1459
+ detail: this,
1460
+ }));
1461
+ }
1556
1462
  }
1463
+ }
1557
1464
 
1558
- setSlideSize() {
1559
- this.slideWidth = this.containerElement.offsetWidth / this.getOption('perView');
1465
+ // eslint-disable-next-line no-unused-expressions
1466
+ customElements.get('kemet-carousel-next') || customElements.define('kemet-carousel-next', KemetCarouselNext);
1560
1467
 
1561
- this.slides.forEach((slide) => {
1562
- slide.style.marginLeft = `${this.getOption('gap') / 2}px`;
1563
- slide.style.marginRight = `${this.getOption('gap') / 2}px`;
1564
- slide.style.width = `${this.slideWidth - this.getOption('gap')}px`;
1565
- });
1468
+ class KemetCarouselPrev extends s$1 {
1469
+ static get styles() {
1470
+ return [
1471
+ r$3`
1472
+ :host {
1473
+ cursor: pointer;
1474
+ }
1566
1475
 
1567
- this.sliderWidth = `${this.slideWidth * this.slides.length}px`;
1476
+ :host([disabled]) {
1477
+ cursor: not-allowed;
1478
+ }
1479
+ `,
1480
+ ];
1568
1481
  }
1569
1482
 
1570
- setToolbarSize() {
1571
- if (this.inner && this.toolbarElement) {
1572
- const width = this.slidesElement.offsetWidth;
1573
- this.toolbarElement.style.width = `${width}px`;
1574
- }
1483
+ static get properties() {
1484
+ return {
1485
+ disabled: {
1486
+ type: Boolean,
1487
+ reflect: true,
1488
+ },
1489
+ };
1575
1490
  }
1576
1491
 
1577
- makeToolbar() {
1578
- if (this.toolbarSlotElement) {
1579
- return $`
1580
- <section class="toolbar" part="toolbar">
1581
- <slot name="toolbar"></slot>
1582
- </section>
1583
- `;
1584
- }
1585
-
1586
- return null;
1492
+ render() {
1493
+ return $`
1494
+ <span tabindex="0" @keyup=${() => this.prev()} @click=${() => this.prev()}>
1495
+ <slot></slot>
1496
+ </span>
1497
+ `;
1587
1498
  }
1588
1499
 
1589
- handleSlotChange() {
1590
- const slides = this.querySelectorAll('kemet-carousel-slide');
1591
- const links = this.querySelectorAll('kemet-carousel-link');
1500
+ prev() {
1501
+ if (!this.disabled) {
1502
+ this.dispatchEvent(new CustomEvent('kemet-carousel-prev', {
1503
+ bubbles: true,
1504
+ composed: true,
1505
+ detail: this,
1506
+ }));
1507
+ }
1508
+ }
1509
+ }
1592
1510
 
1593
- // handle slides
1594
- slides.forEach((slide) => {
1595
- this.slides.push(slide);
1596
- });
1511
+ // eslint-disable-next-line no-unused-expressions
1512
+ customElements.get('kemet-carousel-prev') || customElements.define('kemet-carousel-prev', KemetCarouselPrev);
1597
1513
 
1598
- this.updateInformation();
1599
- this.total = slides.length;
1600
- slides[this.index].selected = true;
1514
+ class KemetCarouselSlide extends s$1 {
1515
+ static get styles() {
1516
+ return [
1517
+ r$3`
1518
+ :host,
1519
+ :host *,
1520
+ :host *::before,
1521
+ *::after {
1522
+ box-sizing: border-box;
1523
+ }
1601
1524
 
1602
- // handle links
1603
- links.forEach((link) => {
1604
- this.links.push(link);
1605
- });
1525
+ :host {
1526
+ flex: 0 0 auto;
1527
+ }
1528
+ `,
1529
+ ];
1606
1530
  }
1607
1531
 
1608
- handleArrows() {
1609
- this.arrows = true;
1532
+ static get properties() {
1533
+ return {
1534
+ /**
1535
+ * Determines if the slide is selected
1536
+ */
1537
+ selected: {
1538
+ type: Boolean,
1539
+ reflect: true,
1540
+ },
1541
+ 'aria-hidden': {
1542
+ type: String,
1543
+ reflect: true,
1544
+ },
1545
+ };
1610
1546
  }
1611
1547
 
1612
- handleFirst() {
1613
- this.updateIndex(0);
1548
+ constructor() {
1549
+ super();
1550
+ this.selected = false;
1551
+ this['aria-hidden'] = 'true';
1614
1552
  }
1615
1553
 
1616
- handleLast() {
1617
- this.updateIndex(this.slides.length - 1);
1554
+ render() {
1555
+ return $`
1556
+ <slot></slot>
1557
+ `;
1618
1558
  }
1559
+ }
1619
1560
 
1620
- handleNext() {
1621
- let newIndex = this.index + this.getOption('perMove');
1622
-
1623
- if (newIndex >= this.slides.length) {
1624
- if (this.getOption('rewind')) {
1625
- newIndex = 0;
1626
- } else {
1627
- newIndex = this.index;
1628
- }
1629
- }
1561
+ // eslint-disable-next-line no-unused-expressions
1562
+ customElements.get('kemet-carousel-slide') || customElements.define('kemet-carousel-slide', KemetCarouselSlide);
1630
1563
 
1631
- this.updateIndex(newIndex);
1564
+ class KemetCarouselTotal extends s$1 {
1565
+ static get styles() {
1566
+ return [
1567
+ r$3`
1568
+ :host {
1569
+ display: inline-block;
1570
+ }
1571
+ `,
1572
+ ];
1632
1573
  }
1633
1574
 
1634
- handlePrev() {
1635
- let newIndex = this.index - this.getOption('perMove');
1636
-
1637
- // send them to the last slide
1638
- if (newIndex < 0) {
1639
- if (this.getOption('rewind')) {
1640
- newIndex = this.slides.length - 1;
1641
- } else {
1642
- newIndex = this.index;
1643
- }
1644
- }
1645
-
1646
- this.updateIndex(newIndex);
1575
+ static get properties() {
1576
+ return {
1577
+ total: {
1578
+ type: Number,
1579
+ },
1580
+ };
1647
1581
  }
1648
1582
 
1649
- updateIndex(newIndex) {
1650
- let currentSlide = this.slides[this.index];
1651
- let currentLink = this.links[newIndex];
1583
+ firstUpdated() {
1584
+ this.carousel = this.closest('kemet-carousel');
1585
+ }
1652
1586
 
1653
- // remove selected from all links
1654
- this.links.forEach((link) => {
1655
- link.selected = false;
1656
- });
1587
+ updated() {
1588
+ this.total = this.carousel.total;
1589
+ }
1657
1590
 
1658
- // if current link is invalid assume it's the first link
1659
- if (!currentLink) {
1660
- [currentLink] = this.links;
1661
- }
1591
+ render() {
1592
+ return $`${this.total}`;
1593
+ }
1594
+ }
1662
1595
 
1663
- // add selected to current link
1664
- if (currentLink) {
1665
- currentLink.selected = true;
1666
- }
1596
+ // eslint-disable-next-line no-unused-expressions
1597
+ customElements.get('kemet-carousel-total') || customElements.define('kemet-carousel-total', KemetCarouselTotal);
1667
1598
 
1668
- if (currentSlide) {
1669
- currentSlide.setAttribute('aria-hidden', 'true');
1599
+ class KemetCarousel extends s$1 {
1600
+ static get styles() {
1601
+ return r$3`
1602
+ :host,
1603
+ *,
1604
+ *::before,
1605
+ *::after {
1606
+ box-sizing: border-box;
1607
+ }
1670
1608
 
1671
- // correct for invalid indexes
1672
- if (newIndex > -1 && newIndex < this.slides.length) {
1673
- this.index = newIndex;
1674
- } else {
1675
- // eslint-disable-next-line no-console
1676
- console.warn('An invalid index number was entered. The kemet-carousel has been reset to the first slide.');
1677
- this.index = 0;
1609
+ :host {
1610
+ position: relative;
1611
+ display: grid;
1612
+ grid-template-columns: minmax(0, 1fr);
1613
+ align-items: center;
1614
+ width: var(--kemet-carousel-width, 100%);
1615
+ height: var(--kemet-carousel-height, auto);
1616
+ overflow: visible;
1678
1617
  }
1679
1618
 
1680
- // move
1681
- this.goToSlide(this.index);
1619
+ :host([arrows]) {
1620
+ grid-template-columns: auto minmax(0, 1fr) auto;
1621
+ }
1682
1622
 
1683
- // update new slide
1684
- currentSlide = this.slides[this.index];
1685
- currentSlide.setAttribute('aria-hidden', 'false');
1686
-
1687
- this.slides.forEach((slide) => {
1688
- slide.selected = false;
1689
- });
1690
-
1691
- currentSlide.selected = true;
1623
+ .toolbar {
1624
+ display: flex;
1625
+ gap: var(--kemet-carousel-toolbar-gap, 1rem);
1626
+ align-items: center;
1627
+ justify-content: var(--kemet-carousel-toolbar-justify-content, center);
1628
+ line-height: 1;
1629
+ padding: var(--kemet-carousel-toolbar-padding, 1rem);
1630
+ }
1692
1631
 
1693
- // notify consumers of slide change
1632
+ :host([inner]) .toolbar {
1633
+ width: var(--kemet-carousel-toolbar-inner-width, 100%);
1634
+ position: absolute;
1635
+ bottom: var(--kemet-carousel-toolbar-inner-bottom, 0);
1636
+ top: var(--kemet-carousel-toolbar-inner-top, auto);
1637
+ color: var(--kemet-carousel-toolbar-inner-color, var(--kemet-color-white));
1638
+ background-color: var(--kemet-carousel-toolbar-inner-background-color, rgba(0, 0, 0, 0.4));
1639
+ }
1694
1640
 
1695
- /**
1696
- * Fires with the a slide has begun to change
1697
- */
1698
- this.dispatchEvent(new CustomEvent('kemet-carousel-change-start', {
1699
- bubbles: true,
1700
- composed: true,
1701
- detail: this,
1702
- }));
1641
+ .slides {
1642
+ overflow: hidden;
1643
+ position: relative;
1644
+ padding: 1rem 0;
1645
+ border: var(--kemet-carousel-slides-border, 1px solid var(--kemet-color-gray1));
1646
+ }
1703
1647
 
1704
- // update information element
1705
- this.updateInformation();
1706
- }
1707
- }
1648
+ .slider {
1649
+ display: flex;
1650
+ flex-wrap: nowrap;
1651
+ transition: transform var(--kemet-carousel-transition-speed, 300ms) ease;
1652
+ }
1708
1653
 
1709
- updateInformation() {
1710
- this.informationSlot = this.slides[this.index].querySelector('[slot="information"]');
1654
+ ::slotted([slot='next']),
1655
+ ::slotted([slot='prev']) {
1656
+ opacity: var(--kemet-carousel-arrows-opacity, 0.25);
1657
+ transition: opacity var(--kemet-carousel-arrows-transition-speed, 300ms) ease-in-out;
1658
+ }
1711
1659
 
1712
- if (this.informationElement) {
1713
- if (this.informationSlot) {
1714
- this.informationElement.innerHTML = this.informationSlot.outerHTML;
1715
- } else {
1716
- this.informationElement.innerHTML = '';
1660
+ :host(:hover) ::slotted([slot='next']),
1661
+ :host(:hover) ::slotted([slot='prev']) {
1662
+ opacity: var(--kemet-carousel-arrows-opacity-hover, 1);
1717
1663
  }
1718
- }
1664
+ `;
1719
1665
  }
1720
1666
 
1721
- goToSlide(index) {
1722
- if (this.getOption('center') === true) {
1723
- const slidesCenter = this.slidesElement.offsetWidth / 2;
1724
- const slideX = this.slideWidth * index;
1725
- this.sliderTranslateX = `${slideX - (slideX - slidesCenter) - this.slideWidth / 2 - slideX}px`;
1726
- } else {
1727
- this.sliderTranslateX = `${(this.slideWidth * index) * -1}px`;
1728
- }
1667
+ static get properties() {
1668
+ return {
1669
+ /**
1670
+ * The current slide index.
1671
+ */
1672
+ index: {
1673
+ type: Number,
1674
+ reflect: true,
1675
+ },
1676
+ /**
1677
+ * The total amount of slides
1678
+ */
1679
+ total: {
1680
+ type: Number,
1681
+ },
1682
+ /**
1683
+ * The width of the slider
1684
+ */
1685
+ sliderWidth: {
1686
+ type: String,
1687
+ },
1688
+ /**
1689
+ * The X position of the slider
1690
+ */
1691
+ sliderTranslateX: {
1692
+ type: String,
1693
+ },
1694
+ /**
1695
+ * Displays the toolbar inside the carousel container
1696
+ */
1697
+ inner: {
1698
+ type: Boolean,
1699
+ reflect: true,
1700
+ },
1701
+ /**
1702
+ * Determines whether or not to display arrows
1703
+ */
1704
+ arrows: {
1705
+ type: Boolean,
1706
+ reflect: true,
1707
+ },
1708
+ /**
1709
+ * Default options for the carousel
1710
+ */
1711
+ options: {
1712
+ type: Object,
1713
+ },
1714
+ /**
1715
+ * Options are different breakpoints for the carousel. Is mobile first.
1716
+ */
1717
+ breakpoints: {
1718
+ type: Object,
1719
+ },
1720
+ };
1729
1721
  }
1730
1722
 
1731
- handleTransitionEnd() {
1732
- const currentElement = this.querySelector('kemet-carousel-current');
1733
-
1734
- if (currentElement) {
1735
- currentElement.current = this.index + 1;
1736
- }
1723
+ constructor() {
1724
+ super();
1737
1725
 
1738
- /**
1739
- * Fires when a slide has changed and finished animating
1740
- */
1741
- this.dispatchEvent(new CustomEvent('kemet-carousel-change-finished', {
1742
- bubbles: true,
1743
- composed: true,
1744
- detail: this,
1745
- }));
1746
- }
1726
+ // managed properties
1727
+ this.index = 0;
1728
+ this.total = 0;
1729
+ this.sliderWidth = 'auto';
1730
+ this.sliderTranslateX = '0';
1731
+ this.inner = false;
1732
+ this.arrows = false;
1733
+ this.options = {
1734
+ perView: 1,
1735
+ perMove: 1,
1736
+ gap: 12,
1737
+ slideshow: 0,
1738
+ rewind: true,
1739
+ center: false,
1740
+ };
1741
+ this.breakpoints = {
1742
+ 768: {
1743
+ perView: 2,
1744
+ gap: 24,
1745
+ rewind: false,
1746
+ },
1747
+ 1280: {
1748
+ perView: 2.5,
1749
+ center: true,
1750
+ },
1751
+ };
1747
1752
 
1748
- handleLink(event) {
1749
- this.updateIndex(event.detail.slide);
1753
+ // bindings
1754
+ this.addEventListener('kemet-carousel-first', this.handleFirst.bind(this));
1755
+ this.addEventListener('kemet-carousel-last', this.handleLast.bind(this));
1756
+ this.addEventListener('kemet-carousel-next', this.handleNext.bind(this));
1757
+ this.addEventListener('kemet-carousel-prev', this.handlePrev.bind(this));
1758
+ this.addEventListener('kemet-carousel-link', this.handleLink.bind(this));
1750
1759
  }
1751
1760
 
1752
- getOption(option) {
1753
- const breakpoints = Object.keys(this.breakpoints);
1754
- let value = this.options[option];
1761
+ firstUpdated() {
1762
+ // standard properties
1763
+ this.slides = [];
1764
+ this.links = [];
1755
1765
 
1756
- breakpoints.forEach((breakpoint) => {
1757
- if (window.matchMedia(`(min-width: ${breakpoint}px)`).matches && this.breakpoints[breakpoint][option] !== undefined) {
1758
- value = this.breakpoints[breakpoint][option];
1759
- }
1766
+ // elements
1767
+ this.containerElement = this.shadowRoot.querySelector('[part="container"]');
1768
+ this.slidesElement = this.shadowRoot.querySelector('[part="slides"]');
1769
+ this.sliderElement = this.shadowRoot.querySelector('[part="slider"]');
1770
+ this.toolbarElement = this.shadowRoot.querySelector('[part="toolbar"]');
1771
+ this.toolbarSlotElement = this.querySelector('[slot="toolbar"]');
1772
+ this.informationElement = this.querySelector('kemet-carousel-information');
1760
1773
 
1761
- return value;
1774
+ // events
1775
+ window.addEventListener('resize', () => {
1776
+ this.setSlideSize();
1777
+ this.setToolbarSize();
1778
+ this.updateIndex(this.index);
1762
1779
  });
1763
1780
 
1764
- return value;
1765
- }
1766
- }
1767
-
1768
- // eslint-disable-next-line no-unused-expressions
1769
- customElements.get('kemet-carousel') || customElements.define('kemet-carousel', KemetCarousel);
1781
+ this.sliderElement.addEventListener('transitionend', this.handleTransitionEnd.bind(this));
1770
1782
 
1771
- /**
1772
- * @license
1773
- * Copyright 2018 Google LLC
1774
- * SPDX-License-Identifier: BSD-3-Clause
1775
- */const l$1=l=>null!=l?l:w;
1783
+ // methods
1784
+ this.swipeMove = (event) => {
1785
+ event.preventDefault();
1776
1786
 
1777
- /**
1778
- * @license
1779
- * Copyright 2017 Google LLC
1780
- * SPDX-License-Identifier: BSD-3-Clause
1781
- */
1782
- const t={ATTRIBUTE:1,CHILD:2,PROPERTY:3,BOOLEAN_ATTRIBUTE:4,EVENT:5,ELEMENT:6},e$1=t=>(...e)=>({_$litDirective$:t,values:e});class i{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,i){this._$Ct=t,this._$AM=e,this._$Ci=i;}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}}
1787
+ const pageX = event.touches ? event.touches[0].pageX : event.pageX;
1788
+ const currentSlide = this.slides[this.index];
1783
1789
 
1784
- /**
1785
- * @license
1786
- * Copyright 2020 Google LLC
1787
- * SPDX-License-Identifier: BSD-3-Clause
1788
- */const r=o=>void 0===o.strings,f={},s=(o,i=f)=>o._$AH=i;
1790
+ this.sliderTranslateX = `${pageX - this.startX - currentSlide.offsetLeft}px`;
1791
+ };
1789
1792
 
1790
- /**
1791
- * @license
1792
- * Copyright 2020 Google LLC
1793
- * SPDX-License-Identifier: BSD-3-Clause
1794
- */const l=e$1(class extends i{constructor(r$1){if(super(r$1),r$1.type!==t.PROPERTY&&r$1.type!==t.ATTRIBUTE&&r$1.type!==t.BOOLEAN_ATTRIBUTE)throw Error("The `live` directive is not allowed on child or event bindings");if(!r(r$1))throw Error("`live` bindings can only contain a single expression")}render(r){return r}update(i,[t$1]){if(t$1===b||t$1===w)return t$1;const o=i.element,l=i.name;if(i.type===t.PROPERTY){if(t$1===o[l])return b}else if(i.type===t.BOOLEAN_ATTRIBUTE){if(!!t$1===o.hasAttribute(l))return b}else if(i.type===t.ATTRIBUTE&&o.getAttribute(l)===t$1+"")return b;return s(i),t$1}});
1793
+ this.handleSlideShow = () => {
1794
+ if (this.getOption('slideshow') > 0) {
1795
+ this.updateIndex(this.index + 1);
1796
+ clearTimeout(this.handleSlideShow);
1797
+ }
1798
+ };
1795
1799
 
1796
- class KemetCheckbox extends s$1 {
1797
- static get styles() {
1798
- return [
1799
- r$3`
1800
- *,
1801
- *::before,
1802
- *::after {
1803
- box-sizing: border-box;
1804
- }
1800
+ // setup
1801
+ this.setSlideSize();
1802
+ this.goToSlide(this.index);
1803
+ }
1805
1804
 
1806
- :host {
1807
- display: inline-block;
1808
- }
1805
+ updated(prevProps) {
1806
+ this.setSlideSize();
1807
+ this.setToolbarSize();
1809
1808
 
1810
- :host([disabled]) {
1811
- opacity: 0.5;
1812
- }
1809
+ if (prevProps.has('index')) {
1810
+ this.updateIndex(this.index);
1811
+ setTimeout(this.handleSlideShow, this.getOption('slideshow') * 1000);
1812
+ }
1813
+ }
1813
1814
 
1814
- label {
1815
- display: inline-flex;
1816
- gap: 0.5rem;
1817
- align-items: center;
1818
- }
1815
+ render() {
1816
+ return $`
1817
+ <slot name="prev" @slotchange=${this.handleArrows}></slot>
1818
+ <div class="container" part="container">
1819
+ <section
1820
+ class="slides"
1821
+ part="slides"
1822
+ @mousedown=${this.swipeStart}
1823
+ @mouseup=${this.swipeEnd}
1824
+ @touchstart=${this.swipeStart}
1825
+ @touchend=${this.swipeEnd}
1826
+ @mouseleave=${this.swipeLeave}
1827
+ >
1828
+ <div class="slider" part="slider" style="width:${this.sliderWidth}; transform:translateX(${this.sliderTranslateX});">
1829
+ <slot name="slides" @slotchange="${this.handleSlotChange}"></slot>
1830
+ </div>
1831
+ </section>
1832
+ ${this.makeToolbar()}
1833
+ </div>
1834
+ <slot name="next" @slotchange=${this.handleArrows}></slot>
1835
+ `;
1836
+ }
1819
1837
 
1820
- input {
1821
- cursor: pointer;
1822
- margin: 0;
1823
- padding: 0;
1824
- width: var(--kemet-checkbox-size, 18px);
1825
- height: var(--kemet-checkbox-size, 18px);
1826
- position: absolute;
1827
- opacity: 0;
1828
- }
1838
+ swipeStart(event) {
1839
+ this.startX = event.touches ? event.touches[0].pageX : event.pageX;
1829
1840
 
1830
- button {
1831
- margin: 0;
1832
- border: none;
1833
- background: none;
1834
- }
1841
+ this.addEventListener('mousemove', this.swipeMove);
1842
+ this.addEventListener('touchmove', this.swipeMove);
1843
+ }
1835
1844
 
1836
- [part='checkbox'] {
1837
- color: var(--kemet-checkbox-color, var(--kemet-color-primary));
1838
- display: flex;
1839
- align-items: center;
1840
- justify-content: center;
1841
- width: var(--kemet-checkbox-size, 18px);
1842
- height: var(--kemet-checkbox-size, 18px);
1843
- border: var(--kemet-checkbox-border, 1px solid var(--kemet-color-primary));
1844
- }
1845
+ swipeEnd(event) {
1846
+ this.updateIndex(this.swipeUpdate(event));
1847
+ this.removeEventListener('mousemove', this.swipeMove, false);
1848
+ this.removeEventListener('touchmove', this.swipeMove, false);
1849
+ }
1845
1850
 
1846
- :host([rounded]) [part='checkbox'] {
1847
- border-radius: var(--kemet-checkbox-border-radius, 4px);
1848
- }
1851
+ swipeUpdate(event) {
1852
+ const pageX = event.changedTouches ? event.changedTouches[0].pageX : event.pageX;
1853
+ const direction = this.startX > pageX ? 'right' : 'left';
1854
+ const threshold = this.slidesElement.offsetWidth / 3;
1855
+ const diff = this.startX - pageX;
1856
+ const shouldUpdate = Math.abs(diff) > threshold;
1849
1857
 
1850
- :host([filled][checked]) [part='checkbox'],
1851
- :host([filled][indeterminate]) [part='checkbox'] {
1852
- border: none;
1853
- background-color: var(--kemet-checkbox-filled-background-color, var(--kemet-color-primary));
1854
- }
1858
+ let { index } = this;
1855
1859
 
1856
- [part='mark'] {
1857
- display: flex;
1858
- width: calc(var(--kemet-checkbox-size, 18px) - 4px);
1859
- height: calc(var(--kemet-checkbox-size, 18px) - 4px);
1860
- }
1860
+ if (shouldUpdate && direction === 'right') {
1861
+ index = this.index >= this.slides.length - 1 ? this.index : this.index + 1;
1862
+ }
1861
1863
 
1862
- :host([filled][checked]) [part='mark'],
1863
- :host([filled][indeterminate]) [part='mark'] {
1864
- color: var(--kemet-checkbox-filled-color, var(--kemet-color-white));
1865
- }
1864
+ if (shouldUpdate && direction === 'left') {
1865
+ index = this.index < 1 ? 0 : this.index - 1;
1866
+ }
1866
1867
 
1867
- [part='message'] {
1868
- display: block;
1869
- margin-top: 0.5rem;
1870
- }
1868
+ return index;
1869
+ }
1871
1870
 
1872
- :host([status='error']) [part='message'] {
1873
- color: var(--kemet-color-error);
1874
- }
1871
+ swipeLeave() {
1872
+ this.updateIndex(this.index);
1873
+ this.removeEventListener('mousemove', this.swipeMove, false);
1874
+ this.removeEventListener('touchmove', this.swipeMove, false);
1875
+ }
1875
1876
 
1876
- :host([status='warning']) [part='message'] {
1877
- color: var(--kemet-color-error);
1878
- }
1879
- `,
1880
- ];
1877
+ setSlideSize() {
1878
+ this.slideWidth = this.containerElement.offsetWidth / this.getOption('perView');
1879
+
1880
+ this.slides.forEach((slide) => {
1881
+ slide.style.marginLeft = `${this.getOption('gap') / 2}px`;
1882
+ slide.style.marginRight = `${this.getOption('gap') / 2}px`;
1883
+ slide.style.width = `${this.slideWidth - this.getOption('gap')}px`;
1884
+ });
1885
+
1886
+ this.sliderWidth = `${this.slideWidth * this.slides.length}px`;
1881
1887
  }
1882
1888
 
1883
- static get properties() {
1884
- return {
1885
- label: {
1886
- type: String,
1887
- },
1888
- checked: {
1889
- type: Boolean,
1890
- reflect: true,
1891
- },
1892
- indeterminate: {
1893
- type: Boolean,
1894
- reflect: true,
1895
- },
1896
- name: {
1897
- type: String,
1898
- },
1899
- value: {
1900
- type: String,
1901
- },
1902
- disabled: {
1903
- type: Boolean,
1904
- reflect: true,
1905
- },
1906
- required: {
1907
- type: Boolean,
1908
- reflect: true,
1909
- },
1910
- focused: {
1911
- type: Boolean,
1912
- reflect: true,
1913
- },
1914
- rounded: {
1915
- type: Boolean,
1916
- reflect: true,
1917
- },
1918
- filled: {
1919
- type: Boolean,
1920
- reflect: true,
1921
- },
1922
- status: {
1923
- type: String,
1924
- reflect: true,
1925
- },
1926
- message: {
1927
- type: String,
1928
- },
1929
- };
1889
+ setToolbarSize() {
1890
+ if (this.inner && this.toolbarElement) {
1891
+ const width = this.slidesElement.offsetWidth;
1892
+ this.toolbarElement.style.width = `${width}px`;
1893
+ }
1930
1894
  }
1931
1895
 
1932
- constructor() {
1933
- super();
1896
+ makeToolbar() {
1897
+ if (this.toolbarSlotElement) {
1898
+ return $`
1899
+ <section class="toolbar" part="toolbar">
1900
+ <slot name="toolbar"></slot>
1901
+ </section>
1902
+ `;
1903
+ }
1934
1904
 
1935
- // managed properties
1936
- this.label = '';
1937
- this.name = 'checkbox';
1938
- this.disabled = false;
1939
- this.required = false;
1940
- this.rounded = false;
1941
- this.filled = false;
1942
- this.status = 'standard';
1905
+ return null;
1906
+ }
1943
1907
 
1944
- /**
1945
- * Used only for form reactive controller
1946
- */
1947
- this.formSubmitController = new FormSubmitController(this);
1908
+ handleSlotChange() {
1909
+ const slides = this.querySelectorAll('kemet-carousel-slide');
1910
+ const links = this.querySelectorAll('kemet-carousel-link');
1911
+
1912
+ // handle slides
1913
+ slides.forEach((slide) => {
1914
+ this.slides.push(slide);
1915
+ });
1916
+
1917
+ this.updateInformation();
1918
+ this.total = slides.length;
1919
+ slides[this.index].selected = true;
1920
+
1921
+ // handle links
1922
+ links.forEach((link) => {
1923
+ this.links.push(link);
1924
+ });
1948
1925
  }
1949
1926
 
1950
- firstUpdated() {
1951
- this.input = this.shadowRoot.querySelector('input');
1927
+ handleArrows() {
1928
+ this.arrows = true;
1952
1929
  }
1953
1930
 
1954
- render() {
1955
- return $`
1956
- <label part="label">
1957
- <input
1958
- type="checkbox"
1959
- name=${l$1(this.name)}
1960
- .value=${this.value}
1961
- .indeterminate=${l(this.indeterminate)}
1962
- .checked=${l(this.checked)}
1963
- .disabled=${this.disabled}
1964
- .required=${this.required}
1965
- aria-checked=${this.checked ? 'true' : 'false'}
1966
- @click=${() => this.handleClick()}
1967
- @blur=${() => this.handleBlur()}
1968
- @focus=${() => this.handleFocus()}
1969
- @change=${() => this.handleChange()}
1970
- />
1971
- <button part="checkbox" aria-label=${this.label}>
1972
- ${this.makeCheckMark()}
1973
- </button>
1974
- <span part="text">${this.label}</span>
1975
- </label>
1976
- ${this.makeMessage()}
1977
- `;
1931
+ handleFirst() {
1932
+ this.updateIndex(0);
1933
+ }
1934
+
1935
+ handleLast() {
1936
+ this.updateIndex(this.slides.length - 1);
1937
+ }
1938
+
1939
+ handleNext() {
1940
+ let newIndex = this.index + this.getOption('perMove');
1941
+
1942
+ if (newIndex >= this.slides.length) {
1943
+ if (this.getOption('rewind')) {
1944
+ newIndex = 0;
1945
+ } else {
1946
+ newIndex = this.index;
1947
+ }
1948
+ }
1949
+
1950
+ this.updateIndex(newIndex);
1978
1951
  }
1979
1952
 
1980
- click() {
1981
- this.input.click();
1982
- }
1953
+ handlePrev() {
1954
+ let newIndex = this.index - this.getOption('perMove');
1955
+
1956
+ // send them to the last slide
1957
+ if (newIndex < 0) {
1958
+ if (this.getOption('rewind')) {
1959
+ newIndex = this.slides.length - 1;
1960
+ } else {
1961
+ newIndex = this.index;
1962
+ }
1963
+ }
1964
+
1965
+ this.updateIndex(newIndex);
1966
+ }
1967
+
1968
+ updateIndex(newIndex) {
1969
+ let currentSlide = this.slides[this.index];
1970
+ let currentLink = this.links[newIndex];
1971
+
1972
+ // remove selected from all links
1973
+ this.links.forEach((link) => {
1974
+ link.selected = false;
1975
+ });
1976
+
1977
+ // if current link is invalid assume it's the first link
1978
+ if (!currentLink) {
1979
+ [currentLink] = this.links;
1980
+ }
1981
+
1982
+ // add selected to current link
1983
+ if (currentLink) {
1984
+ currentLink.selected = true;
1985
+ }
1986
+
1987
+ if (currentSlide) {
1988
+ currentSlide.setAttribute('aria-hidden', 'true');
1989
+
1990
+ // correct for invalid indexes
1991
+ if (newIndex > -1 && newIndex < this.slides.length) {
1992
+ this.index = newIndex;
1993
+ } else {
1994
+ // eslint-disable-next-line no-console
1995
+ console.warn('An invalid index number was entered. The kemet-carousel has been reset to the first slide.');
1996
+ this.index = 0;
1997
+ }
1998
+
1999
+ // move
2000
+ this.goToSlide(this.index);
1983
2001
 
1984
- handleClick() {
1985
- this.checked = !this.checked;
1986
- this.indeterminate = false;
2002
+ // update new slide
2003
+ currentSlide = this.slides[this.index];
2004
+ currentSlide.setAttribute('aria-hidden', 'false');
1987
2005
 
1988
- /**
1989
- * Fires when the state of the checkbox changes
1990
- */
1991
- this.dispatchEvent(
1992
- new CustomEvent('kemet-checkbox-change', {
1993
- bubbles: true,
1994
- composed: true,
1995
- detail: this,
1996
- }),
1997
- );
1998
- }
2006
+ this.slides.forEach((slide) => {
2007
+ slide.selected = false;
2008
+ });
1999
2009
 
2000
- handleBlur() {
2001
- this.focused = false;
2010
+ currentSlide.selected = true;
2002
2011
 
2003
- /**
2004
- * Fires when the checkbox loses or receives focus
2005
- */
2006
- this.dispatchEvent(
2007
- new CustomEvent('kemet-checkbox-focused', {
2008
- bubbles: true,
2009
- composed: true,
2010
- detail: false,
2011
- }),
2012
- );
2013
- }
2012
+ // notify consumers of slide change
2014
2013
 
2015
- handleFocus() {
2016
- this.focused = true;
2017
- /**
2018
- * Fires when the checkbox loses or receives focus
2019
- */
2020
- this.dispatchEvent(
2021
- new CustomEvent('kemet-checkbox-focused', {
2014
+ /**
2015
+ * Fires with the a slide has begun to change
2016
+ */
2017
+ this.dispatchEvent(new CustomEvent('kemet-carousel-change-start', {
2022
2018
  bubbles: true,
2023
2019
  composed: true,
2024
- detail: true,
2025
- }),
2026
- );
2020
+ detail: this,
2021
+ }));
2022
+
2023
+ // update information element
2024
+ this.updateInformation();
2025
+ }
2027
2026
  }
2028
2027
 
2029
- handleChange() {
2030
- this.value = this.checked;
2028
+ updateInformation() {
2029
+ this.informationSlot = this.slides[this.index].querySelector('[slot="information"]');
2031
2030
 
2032
- if (this.input.checkValidity()) {
2033
- this.status = 'standard';
2031
+ if (this.informationElement) {
2032
+ if (this.informationSlot) {
2033
+ this.informationElement.innerHTML = this.informationSlot.outerHTML;
2034
+ } else {
2035
+ this.informationElement.innerHTML = '';
2036
+ }
2034
2037
  }
2035
2038
  }
2036
2039
 
2037
- makeMessage() {
2038
- if (this.status === 'error' || this.status === 'warning') {
2039
- return $`<span part="message">${this.message}</span>`;
2040
+ goToSlide(index) {
2041
+ if (this.getOption('center') === true) {
2042
+ const slidesCenter = this.slidesElement.offsetWidth / 2;
2043
+ const slideX = this.slideWidth * index;
2044
+ this.sliderTranslateX = `${slideX - (slideX - slidesCenter) - this.slideWidth / 2 - slideX}px`;
2045
+ } else {
2046
+ this.sliderTranslateX = `${(this.slideWidth * index) * -1}px`;
2040
2047
  }
2041
-
2042
- return null;
2043
2048
  }
2044
2049
 
2045
- makeCheckMark() {
2046
- if (this.checked) {
2047
- return $`
2048
- <span part="mark">
2049
- <svg viewBox="0 0 16 16">
2050
- <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
2051
- <g stroke="currentColor" stroke-width="2">
2052
- <g transform="translate(3.428571, 3.428571)">
2053
- <path d="M0,5.71428571 L3.42857143,9.14285714"></path>
2054
- <path d="M9.14285714,0 L3.42857143,9.14285714"></path>
2055
- </g>
2056
- </g>
2057
- </g>
2058
- </svg>
2059
- </span>
2060
- `;
2061
- }
2050
+ handleTransitionEnd() {
2051
+ const currentElement = this.querySelector('kemet-carousel-current');
2062
2052
 
2063
- if (!this.checked && this.indeterminate) {
2064
- return $`
2065
- <span part="mark">
2066
- <svg viewBox="0 0 16 16">
2067
- <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
2068
- <g stroke="currentColor" stroke-width="2">
2069
- <g transform="translate(2.285714, 6.857143)">
2070
- <path d="M10.2857143,1.14285714 L1.14285714,1.14285714"></path>
2071
- </g>
2072
- </g>
2073
- </g>
2074
- </svg>
2075
- </span>
2076
- `;
2053
+ if (currentElement) {
2054
+ currentElement.current = this.index + 1;
2077
2055
  }
2078
2056
 
2079
- return null;
2057
+ /**
2058
+ * Fires when a slide has changed and finished animating
2059
+ */
2060
+ this.dispatchEvent(new CustomEvent('kemet-carousel-change-finished', {
2061
+ bubbles: true,
2062
+ composed: true,
2063
+ detail: this,
2064
+ }));
2080
2065
  }
2081
2066
 
2082
- checkValidity() {
2083
- return this.input.checkValidity();
2067
+ handleLink(event) {
2068
+ this.updateIndex(event.detail.slide);
2069
+ }
2070
+
2071
+ getOption(option) {
2072
+ const breakpoints = Object.keys(this.breakpoints);
2073
+ let value = this.options[option];
2074
+
2075
+ breakpoints.forEach((breakpoint) => {
2076
+ if (window.matchMedia(`(min-width: ${breakpoint}px)`).matches && this.breakpoints[breakpoint][option] !== undefined) {
2077
+ value = this.breakpoints[breakpoint][option];
2078
+ }
2079
+
2080
+ return value;
2081
+ });
2082
+
2083
+ return value;
2084
2084
  }
2085
2085
  }
2086
2086
 
2087
2087
  // eslint-disable-next-line no-unused-expressions
2088
- customElements.get('kemet-checkbox') || customElements.define('kemet-checkbox', KemetCheckbox);
2088
+ customElements.get('kemet-carousel') || customElements.define('kemet-carousel', KemetCarousel);
2089
2089
 
2090
2090
  class KemetCombo extends s$1 {
2091
2091
  static get styles() {
@@ -2171,7 +2171,7 @@ class KemetCombo extends s$1 {
2171
2171
  this.input = this.field.querySelector('[slot="input"]');
2172
2172
 
2173
2173
  // managed properties
2174
- this.slug = this.field.slug;
2174
+ this.slug = this.field.slug || 'slug';
2175
2175
 
2176
2176
  // events listeners
2177
2177
  this.input.addEventListener('kemet-input-input', this.handleInput.bind(this));
@@ -2186,7 +2186,7 @@ class KemetCombo extends s$1 {
2186
2186
  aria-controls="${this.slug}-listbox"
2187
2187
  aria-haspopup="listbox"
2188
2188
  id="${this.slug}-combobox"
2189
- aria-label="${this.field.label}"
2189
+ aria-label="${this.field?.label}"
2190
2190
  >
2191
2191
  <ul role="listbox" aria-labelledby="${this.slug}-label" id="${this.slug}-listbox">
2192
2192
  ${this.makeOptions()}
@@ -2241,7 +2241,11 @@ class KemetCombo extends s$1 {
2241
2241
  new CustomEvent('kemet-combo-selection', {
2242
2242
  bubbles: true,
2243
2243
  composed: true,
2244
- detail: event.target.getAttribute('id'),
2244
+ detail: {
2245
+ element: event.target,
2246
+ text: event.target.innerText,
2247
+ id: event.target.getAttribute('id'),
2248
+ },
2245
2249
  }),
2246
2250
  );
2247
2251
  }
@@ -4671,7 +4675,7 @@ class KemetModal extends s$1 {
4671
4675
  updated(prevProps) {
4672
4676
  if (!prevProps.get('opened') && this.opened === true) {
4673
4677
  setTimeout(() => {
4674
- this.focusableElements[0].focus();
4678
+ this.focusableElements[0]?.focus();
4675
4679
  }, 100);
4676
4680
 
4677
4681
  /**
@@ -7494,42 +7498,185 @@ class KemetSelect extends s$1 {
7494
7498
  }
7495
7499
  }
7496
7500
 
7497
- /**
7498
- * Handles when the input has an error
7499
- * @private
7500
- */
7501
- handleInvalid() {
7502
- this.invalid = true;
7503
- this.status = 'error';
7501
+ /**
7502
+ * Handles when the input has an error
7503
+ * @private
7504
+ */
7505
+ handleInvalid() {
7506
+ this.invalid = true;
7507
+ this.status = 'error';
7508
+
7509
+ /**
7510
+ * Fires when there's a change in status
7511
+ */
7512
+ this.dispatchEvent(
7513
+ new CustomEvent('kemet-input-status', {
7514
+ bubbles: true,
7515
+ composed: true,
7516
+ detail: {
7517
+ status: 'error',
7518
+ validity: this.select.validity,
7519
+ element: this,
7520
+ },
7521
+ }),
7522
+ );
7523
+ }
7524
+
7525
+ /**
7526
+ * Checks the validity of the standard select
7527
+ * @public
7528
+ * @returns {boolean}
7529
+ */
7530
+ checkValidity() {
7531
+ this.select.checkValidity();
7532
+ }
7533
+ }
7534
+
7535
+ // eslint-disable-next-line no-unused-expressions
7536
+ customElements.get('kemet-select') || customElements.define('kemet-select', KemetSelect);
7537
+
7538
+ class KemetSortableItem extends s$1 {
7539
+ static get styles() {
7540
+ return [
7541
+ r$3`
7542
+ :host {
7543
+ cursor: grab;
7544
+ display: block;
7545
+ padding: 1rem;
7546
+ border: 1px solid var(--kemet-color-primary);
7547
+ }
7548
+
7549
+ :host([ghost]) {
7550
+ opacity: 0.5;
7551
+ border-style: dashed;
7552
+ }
7553
+ `,
7554
+ ];
7555
+ }
7556
+
7557
+ static get properties() {
7558
+ return {
7559
+ /* Automatically set to true when an item is dragged to a new spot */
7560
+ ghost: {
7561
+ type: Boolean,
7562
+ reflect: true,
7563
+ },
7564
+ };
7565
+ }
7566
+
7567
+ firstUpdated() {
7568
+ this.draggable = true;
7569
+ }
7570
+
7571
+ render() {
7572
+ return $`<slot></slot>`;
7573
+ }
7574
+ }
7575
+
7576
+ // eslint-disable-next-line no-unused-expressions
7577
+ customElements.get('kemet-sortable-item') || customElements.define('kemet-sortable-item', KemetSortableItem);
7578
+
7579
+ var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
7580
+
7581
+ var index_min = {exports: {}};
7582
+
7583
+ /*! mobile-drag-drop 2.1.0 | Copyright (c) 2017 Tim Ruffles | MIT License */
7584
+
7585
+ (function (module, exports) {
7586
+ !function(a,b){b(exports);}(commonjsGlobal,function(a){function b(){var a={dragEvents:"ondragstart"in document.documentElement,draggable:"draggable"in document.documentElement,touchEvents:"ontouchstart"in document.documentElement,userAgentSupportingNativeDnD:void 0},b=!!window.chrome||/chrome/i.test(navigator.userAgent);return a.userAgentSupportingNativeDnD=!(/iPad|iPhone|iPod|Android/.test(navigator.userAgent)||b&&a.touchEvents),a}function c(){var a=!1;try{var b=Object.defineProperty({},"passive",{get:function(){a=!0;}});window.addEventListener("test",null,b);}catch(a){}return a}function d(a){if(a&&Object.keys(a).forEach(function(b){B[b]=a[b];}),!B.forceApply){var d=b();if(d.userAgentSupportingNativeDnD&&d.draggable&&d.dragEvents)return !1}return y=c(),B.holdToDrag?h("touchstart",w,!1):h("touchstart",e,!1),!0}function e(a){if(!z){var b=f(a);if(b)try{z=new J(a,B,b,g);}catch(b){throw g(B,a,3),b}}}function f(a){var b=a.target;do if(b.draggable!==!1&&b.getAttribute&&"true"===b.getAttribute("draggable"))return b;while((b=b.parentNode)&&b!==document.body)}function g(a,b,c){if(0===c&&a.defaultActionOverride)try{a.defaultActionOverride(b),b.defaultPrevented;}catch(a){}z=null;}function h(a,b,c){void 0===c&&(c=!0),document.addEventListener(a,b,!!y&&{passive:c});}function i(a,b){document.removeEventListener(a,b);}function j(a){return 0===a.length?0:a.reduce(function(a,b){return b+a},0)/a.length}function k(a){return a&&a.tagName}function l(a,b){for(var c=0;c<a.changedTouches.length;c++){var d=a.changedTouches[c];if(d.identifier===b)return !0}return !1}function m(a,b,c,d,e,f,g){void 0===g&&(g=null);var h=b.changedTouches[0],i=new Event(c,{bubbles:!0,cancelable:d});i.dataTransfer=f,i.relatedTarget=g,i.screenX=h.screenX,i.screenY=h.screenY,i.clientX=h.clientX,i.clientY=h.clientY,i.pageX=h.pageX,i.pageY=h.pageY;var j=a.getBoundingClientRect();return i.offsetX=i.clientX-j.left,i.offsetY=i.clientY-j.top,i}function n(a,b,c){for(var d=[],e=[],f=0;f<b.touches.length;f++){var g=b.touches[f];d.push(g[a+"X"]),e.push(g[a+"Y"]);}c.x=j(d),c.y=j(e);}function o(a,b){if(1===a.nodeType){for(var c=getComputedStyle(a),d=0;d<c.length;d++){var e=c[d];b.style.setProperty(e,c.getPropertyValue(e),c.getPropertyPriority(e));}b.style.pointerEvents="none",b.removeAttribute("id"),b.removeAttribute("class"),b.removeAttribute("draggable");}if(a.hasChildNodes())for(var d=0;d<a.childNodes.length;d++)o(a.childNodes[d],b.childNodes[d]);}function p(a){var b=a.cloneNode(!0);return o(a,b),b.style.position="absolute",b.style.left="0px",b.style.top="0px",b.style.zIndex="999999",b.classList.add(G),b.classList.add(I),b}function q(a){return E.map(function(b){var c=a.style[b+"transform"];return c&&"none"!==c?c.replace(/translate\(\D*\d+[^,]*,\D*\d+[^,]*\)\s*/g,""):""})}function r(a,b,c,d,e){void 0===e&&(e=!0);var f=b.x,g=b.y;d&&(f+=d.x,g+=d.y),e&&(f-=parseInt(a.offsetWidth,10)/2,g-=parseInt(a.offsetHeight,10)/2);for(var h="translate3d("+f+"px,"+g+"px, 0)",i=0;i<E.length;i++){var j=E[i]+"transform";a.style[j]=h+" "+c[i];}}function s(a,b,c,d){var e=getComputedStyle(a);if("hidden"===e.visibility||"none"===e.display)return void d();b.classList.add(H);var f=getComputedStyle(b),g=parseFloat(f.transitionDuration);if(isNaN(g)||0===g)return void d();var h=a.getBoundingClientRect(),i={x:h.left,y:h.top};i.x+=document.body.scrollLeft||document.documentElement.scrollLeft,i.y+=document.body.scrollTop||document.documentElement.scrollTop,i.x-=parseInt(e.marginLeft,10),i.y-=parseInt(e.marginTop,10);var j=parseFloat(f.transitionDelay),k=Math.round(1e3*(g+j));r(b,i,c,void 0,!1),setTimeout(d,k);}function t(a,b){return a?a===C[0]?D[0]:0===a.indexOf(C[1])||a===C[7]?D[1]:0===a.indexOf(C[4])?D[3]:a===C[6]?D[2]:D[1]:3===b.nodeType&&"A"===b.tagName?D[3]:D[1]}function u(a,b,c,d,e,f,g){if(void 0===f&&(f=!0),void 0===g&&(g=null),A);var k=m(b,c,a,f,document.defaultView,e,g),l=!b.dispatchEvent(k);return d.g=0,l}function v(a,b){if(!a||a===C[7])return b;if(b===D[1]){if(0===a.indexOf(D[1]))return D[1]}else if(b===D[3]){if(0===a.indexOf(D[3])||a.indexOf("Link")>-1)return D[3]}else if(b===D[2]&&(0===a.indexOf(D[2])||a.indexOf("Move")>-1))return D[2];return D[0]}function w(a){var b=a.target,c=function(){g.off(),h.off(),i.off(),e(a);},d=function(){g.off(),h.off(),i.off(),clearTimeout(f);},f=setTimeout(c,B.holdToDrag),g=x(b,"touchend",d,this),h=x(b,"touchcancel",d,this),i=x(window,"scroll",d,this);}function x(a,b,c,d){return d&&(c=c.bind(d)),a.addEventListener(b,c),{off:function(){return a.removeEventListener(b,c)}}}var y,z,A=!1,B={iterationInterval:150},C=["none","copy","copyLink","copyMove","link","linkMove","move","all"],D=["none","copy","move","link"],E=["","-webkit-"],F="dnd-poly-",G=F+"drag-image",H=F+"snapback",I=F+"icon",J=function(){function a(a,b,c,d){this.h=a,this.i=b,this.j=c,this.k=d,this.l=0,this.m=null,this.o=null,this.p=a,this.q=a.changedTouches[0],this.s=this.t.bind(this),this.u=this.v.bind(this),h("touchmove",this.s,!1),h("touchend",this.u,!1),h("touchcancel",this.u,!1);}return a.prototype.A=function(){var a=this;this.l=1,this.B=D[0],this.C={D:{},F:void 0,g:3,G:[]},this.H={x:null,y:null},this.I={x:null,y:null};var b=this.j;if(this.J=new K(this.C,function(c,d,e){b=c,"number"!=typeof d&&"number"!=typeof e||(a.K={x:d||0,y:e||0});}),this.C.g=2,this.J.dropEffect=D[0],u("dragstart",this.j,this.p,this.C,this.J))return this.l=3,this.L(),!1;if(n("page",this.p,this.I),this.M=p(b),this.N=q(this.M),!this.K)if(this.i.dragImageOffset)this.K={x:this.i.dragImageOffset.x,y:this.i.dragImageOffset.y};else if(this.i.dragImageCenterOnTouch){var c=getComputedStyle(b);this.K={x:0-parseInt(c.marginLeft,10),y:0-parseInt(c.marginTop,10)};}else {var d=b.getBoundingClientRect(),c=getComputedStyle(b);this.K={x:d.left-this.q.clientX-parseInt(c.marginLeft,10)+d.width/2,y:d.top-this.q.clientY-parseInt(c.marginTop,10)+d.height/2};}return r(this.M,this.I,this.N,this.K,this.i.dragImageCenterOnTouch),document.body.appendChild(this.M),this.O=setInterval(function(){a.P||(a.P=!0,a.R(),a.P=!1);},this.i.iterationInterval),!0},a.prototype.L=function(){this.O&&(clearInterval(this.O),this.O=null),i("touchmove",this.s),i("touchend",this.u),i("touchcancel",this.u),this.M&&(this.M.parentNode.removeChild(this.M),this.M=null),this.k(this.i,this.p,this.l);},a.prototype.t=function(a){var b=this;if(l(a,this.q.identifier)!==!1){if(this.p=a,0===this.l){var c=void 0;if(this.i.dragStartConditionOverride)try{c=this.i.dragStartConditionOverride(a);}catch(a){c=!1;}else c=1===a.touches.length;return c?void(this.A()===!0&&(this.h.preventDefault(),a.preventDefault())):void this.L()}if(a.preventDefault(),n("client",a,this.H),n("page",a,this.I),this.i.dragImageTranslateOverride)try{var d=!1;if(this.i.dragImageTranslateOverride(a,{x:this.H.x,y:this.H.y},this.m,function(a,c){b.M&&(d=!0,b.H.x+=a,b.H.y+=c,b.I.x+=a,b.I.y+=c,r(b.M,b.I,b.N,b.K,b.i.dragImageCenterOnTouch));}),d)return}catch(a){}r(this.M,this.I,this.N,this.K,this.i.dragImageCenterOnTouch);}},a.prototype.v=function(a){if(l(a,this.q.identifier)!==!1){if(this.i.dragImageTranslateOverride)try{this.i.dragImageTranslateOverride(void 0,void 0,void 0,function(){});}catch(a){}if(0===this.l)return void this.L();a.preventDefault(),this.l="touchcancel"===a.type?3:2;}},a.prototype.R=function(){var a=this;var e=this.B;this.C.g=3,this.J.dropEffect=D[0];var f=u("drag",this.j,this.p,this.C,this.J);if(f&&(this.B=D[0]),f||2===this.l||3===this.l){var g=this.S(this.l);return g?void s(this.j,this.M,this.N,function(){a.T();}):void this.T()}var h=document.elementFromPoint(this.H.x,this.H.y),i=this.o;h!==this.m&&h!==this.o&&(this.m=h,null!==this.o&&(this.C.g=3,this.J.dropEffect=D[0],u("dragexit",this.o,this.p,this.C,this.J,!1)),null===this.m?this.o=this.m:(this.C.g=3,this.J.dropEffect=t(this.C.F,this.j),u("dragenter",this.m,this.p,this.C,this.J)?(this.o=this.m,this.B=v(this.J.effectAllowed,this.J.dropEffect)):this.m!==document.body&&(this.o=document.body))),i!==this.o&&k(i)&&(this.C.g=3,this.J.dropEffect=D[0],u("dragleave",i,this.p,this.C,this.J,!1,this.o)),k(this.o)&&(this.C.g=3,this.J.dropEffect=t(this.C.F,this.j),u("dragover",this.o,this.p,this.C,this.J)===!1?this.B=D[0]:this.B=v(this.J.effectAllowed,this.J.dropEffect)),e!==this.B&&this.M.classList.remove(F+e);var j=F+this.B;this.M.classList.contains(j)===!1&&this.M.classList.add(j);},a.prototype.S=function(a){var d=this.B===D[0]||null===this.o||3===a;return d?k(this.o)&&(this.C.g=3,this.J.dropEffect=D[0],u("dragleave",this.o,this.p,this.C,this.J,!1)):k(this.o)&&(this.C.g=1,this.J.dropEffect=this.B,u("drop",this.o,this.p,this.C,this.J)===!0?this.B=this.J.dropEffect:this.B=D[0]),d},a.prototype.T=function(){this.C.g=3,this.J.dropEffect=this.B,u("dragend",this.j,this.p,this.C,this.J,!1),this.l=2,this.L();},a}(),K=function(){function a(a,b){this.U=a,this.V=b,this.W=D[0];}return Object.defineProperty(a.prototype,"types",{get:function(){if(0!==this.U.g)return Object.freeze(this.U.G)},enumerable:!0,configurable:!0}),a.prototype.setData=function(a,b){if(2===this.U.g){if(a.indexOf(" ")>-1)throw new Error("illegal arg: type contains space");this.U.D[a]=b,this.U.G.indexOf(a)===-1&&this.U.G.push(a);}},a.prototype.getData=function(a){if(1===this.U.g||2===this.U.g)return this.U.D[a]||""},a.prototype.clearData=function(a){if(2===this.U.g){if(a&&this.U.D[a]){delete this.U.D[a];var b=this.U.G.indexOf(a);return void(b>-1&&this.U.G.splice(b,1))}this.U.D={},this.U.G=[];}},a.prototype.setDragImage=function(a,b,c){2===this.U.g&&this.V(a,b,c);},Object.defineProperty(a.prototype,"effectAllowed",{get:function(){return this.U.F},set:function(a){2===this.U.g&&C.indexOf(a)>-1&&(this.U.F=a);},enumerable:!0,configurable:!0}),Object.defineProperty(a.prototype,"dropEffect",{get:function(){return this.W},set:function(a){0!==this.U.g&&C.indexOf(a)>-1&&(this.W=a);},enumerable:!0,configurable:!0}),a}();a.polyfill=d,Object.defineProperty(a,"__esModule",{value:!0});});
7587
+
7588
+ } (index_min, index_min.exports));
7589
+
7590
+ const getMouseOffset = (event) => {
7591
+ const targetRect = event.target.getBoundingClientRect();
7592
+ const offset = {
7593
+ x: event.pageX - targetRect.left,
7594
+ y: event.pageY - targetRect.top,
7595
+ };
7596
+
7597
+ return offset;
7598
+ };
7599
+
7600
+ const getElementVerticalCenter = (element) => {
7601
+ const rect = element.getBoundingClientRect();
7602
+ return (rect.bottom - rect.top) / 2;
7603
+ };
7604
+
7605
+ class KemetSortable extends s$1 {
7606
+ static get styles() {
7607
+ return [
7608
+ r$3`
7609
+ :host {
7610
+ display: flex;
7611
+ gap: 1rem;
7612
+ flex-direction: column;
7613
+ }
7614
+ `,
7615
+ ];
7616
+ }
7617
+
7618
+ firstUpdated() {
7619
+ index_min.exports.polyfill();
7620
+
7621
+ this.addEventListener('dragstart', event => this.handleDragStart(event), false);
7622
+ this.addEventListener('dragenter', (event) => { event.preventDefault(); });
7623
+ }
7624
+
7625
+ render() {
7626
+ return $`<slot></slot>`;
7627
+ }
7628
+
7629
+ handleDragStart(event) {
7630
+ this.sortableItem = event.target;
7631
+
7632
+ this.addEventListener('dragover', dragOverEvent => this.handleDragOver(dragOverEvent), false);
7633
+ this.addEventListener('dragend', dragEndEvent => this.handleDragEnd(dragEndEvent), false);
7634
+
7635
+ setTimeout(() => {
7636
+ this.sortableItem.ghost = true;
7637
+ }, 0);
7638
+ }
7639
+
7640
+ handleDragOver(event) {
7641
+ event.preventDefault();
7642
+
7643
+ const { target } = event;
7644
+
7645
+ if (target && target.tagName === 'KEMET-SORTABLE-ITEM') {
7646
+ const offset = getMouseOffset(event);
7647
+ const middleY = getElementVerticalCenter(event.target);
7648
+
7649
+ if (offset.y > middleY) {
7650
+ this.insertBefore(this.sortableItem, target.nextSibling);
7651
+ } else {
7652
+ this.insertBefore(this.sortableItem, target);
7653
+ }
7654
+ }
7655
+ }
7656
+
7657
+ handleDragEnd(event) {
7658
+ event.preventDefault();
7659
+ this.sortableItem.ghost = false;
7504
7660
 
7505
7661
  /**
7506
- * Fires when there's a change in status
7662
+ * Fires when an item has been moved to a new spot
7507
7663
  */
7508
7664
  this.dispatchEvent(
7509
- new CustomEvent('kemet-input-status', {
7665
+ new CustomEvent('kemet-sortable-drag-end', {
7510
7666
  bubbles: true,
7511
7667
  composed: true,
7512
7668
  detail: {
7513
- status: 'error',
7514
- validity: this.select.validity,
7515
- element: this,
7669
+ event,
7670
+ current: this.sortableItem,
7671
+ all: this.querySelectorAll('kemet-sortable-item'),
7516
7672
  },
7517
7673
  }),
7518
7674
  );
7519
7675
  }
7520
-
7521
- /**
7522
- * Checks the validity of the standard select
7523
- * @public
7524
- * @returns {boolean}
7525
- */
7526
- checkValidity() {
7527
- this.select.checkValidity();
7528
- }
7529
7676
  }
7530
7677
 
7531
7678
  // eslint-disable-next-line no-unused-expressions
7532
- customElements.get('kemet-select') || customElements.define('kemet-select', KemetSelect);
7679
+ customElements.get('kemet-sortable') || customElements.define('kemet-sortable', KemetSortable);
7533
7680
 
7534
7681
  class KemetSVG extends s$1 {
7535
7682
  static get styles() {
@@ -9019,101 +9166,487 @@ class KemetTextarea extends s$1 {
9019
9166
  return this.textarea.checkValidity();
9020
9167
  }
9021
9168
 
9022
- /**
9023
- * Focuses the standard input
9024
- * @public
9025
- */
9026
- focus() {
9027
- return this.textarea.focus();
9169
+ /**
9170
+ * Focuses the standard input
9171
+ * @public
9172
+ */
9173
+ focus() {
9174
+ return this.textarea.focus();
9175
+ }
9176
+ }
9177
+
9178
+ // eslint-disable-next-line no-unused-expressions
9179
+ customElements.get('kemet-textarea') || customElements.define('kemet-textarea', KemetTextarea);
9180
+
9181
+ class KemetToggle extends s$1 {
9182
+ static get styles() {
9183
+ return [
9184
+ r$3`
9185
+ :host {
9186
+ --kemet-toggle-width: 3.5rem;
9187
+ --kemet-toggle-height: 2rem;
9188
+ --kemet-toggle-handle-diameter: 1.6rem;
9189
+ --kemet-toggle-handle-margin: calc((var(--kemet-toggle-height) - var(--kemet-toggle-handle-diameter)) / 2);
9190
+
9191
+ display: flex;
9192
+ align-items: center;
9193
+ }
9194
+
9195
+ :host([disabled]) {
9196
+ opacity: 0.5;
9197
+ }
9198
+
9199
+ label {
9200
+ cursor: pointer;
9201
+ display: flex;
9202
+ align-items: center;
9203
+ gap: 1rem;
9204
+ font-size: inherit;
9205
+ color: inherit;
9206
+ }
9207
+
9208
+ :host([disabled]) label {
9209
+ cursor: not-allowed;
9210
+ }
9211
+
9212
+ input {
9213
+ display: none;
9214
+ }
9215
+
9216
+ [part='control'] {
9217
+ position: relative;
9218
+ display: inline-flex;
9219
+ margin: 0;
9220
+ width: var(--kemet-toggle-width);
9221
+ height: var(--kemet-toggle-height);
9222
+ }
9223
+
9224
+ [part='control'] > span {
9225
+ transition: 300ms ease-in-out;
9226
+ }
9227
+
9228
+ [part='track'] {
9229
+ width: var(--kemet-toggle-width);
9230
+ height: var(--kemet-toggle-height);
9231
+ border: var(--kemet-toggle-track-border, none);
9232
+ border-radius: var(--kemet-toggle-height);
9233
+ background-color: var(--kemet-toggle-track-color, var(--kemet-color-white));
9234
+ box-shadow: var(--kemet-toggle-track-shadow, inset 0 0.4rem 0.7rem 0 rgba(47, 47, 47, 0.35), inset 0 -0.2rem 0.4rem 0 var(--kemet-color-gray1));
9235
+ }
9236
+
9237
+ :host([squared]) [part='track'] {
9238
+ border-radius: 0;
9239
+ }
9240
+
9241
+ [part='handle'] {
9242
+ position: absolute;
9243
+ top: var(--kemet-toggle-handle-margin);
9244
+ left: var(--kemet-toggle-handle-margin);
9245
+ width: var(--kemet-toggle-handle-diameter);
9246
+ height: var(--kemet-toggle-handle-diameter);
9247
+ transform: translateX(0);
9248
+ border: var(--kemet-toggle-handle-border, none);
9249
+ border-radius: var(--kemet-toggle-handle-diameter);
9250
+ background-color: var(--kemet-toggle-handle-color, var(--kemet-color-primary));
9251
+ box-shadow: var(--kemet-toggle-handle-shadow, 0 0.5rem 0.5rem 0 rgba(0, 0, 0, 0.1), 0 0.5rem 0.5rem 0 rgba(0, 0, 0, 0.2));
9252
+ }
9253
+
9254
+ :host([squared]) [part='handle'] {
9255
+ border-radius: 0;
9256
+ }
9257
+
9258
+ :host([checked]) [part='handle'] {
9259
+ transform: translateX(calc(var(--kemet-toggle-width) - var(--kemet-toggle-handle-diameter) - var(--kemet-toggle-handle-margin) * 2));
9260
+ }
9261
+
9262
+ .option {
9263
+ font-size: 90%;
9264
+ }
9265
+ `,
9266
+ ];
9267
+ }
9268
+
9269
+ static get properties() {
9270
+ return {
9271
+ /**
9272
+ * The name on the input field
9273
+ */
9274
+ name: {
9275
+ type: String,
9276
+ },
9277
+ /**
9278
+ * Determines whether or not the toggle is checked
9279
+ */
9280
+ checked: {
9281
+ type: Boolean,
9282
+ reflect: true,
9283
+ },
9284
+ /**
9285
+ * Determines whether or not the toggle is disabled
9286
+ */
9287
+ disabled: {
9288
+ type: Boolean,
9289
+ },
9290
+ /**
9291
+ * A description of the toggle's purpose
9292
+ */
9293
+ label: {
9294
+ type: String,
9295
+ },
9296
+ /**
9297
+ * Determines whether or not to show text options
9298
+ */
9299
+ show: {
9300
+ type: Boolean,
9301
+ },
9302
+ /**
9303
+ * Displays the toggle as squared instead of rounded
9304
+ */
9305
+ squared: {
9306
+ type: Boolean,
9307
+ },
9308
+ /**
9309
+ * The checked option text
9310
+ */
9311
+ optionChecked: {
9312
+ type: String,
9313
+ attribute: 'option-checked',
9314
+ },
9315
+ /**
9316
+ * The unchecked option text
9317
+ */
9318
+ optionUnchecked: {
9319
+ type: String,
9320
+ attribute: 'option-unchecked',
9321
+ },
9322
+ };
9323
+ }
9324
+
9325
+ constructor() {
9326
+ super();
9327
+
9328
+ this.name = 'toggle-switch';
9329
+ this.disabled = false;
9330
+ this.checked = false;
9331
+ this.show = false;
9332
+ this.squared = false;
9333
+ this.label = '';
9334
+ this.optionChecked = 'on';
9335
+ this.optionUnchecked = 'off';
9336
+ this.value = this.checked ? this.optionChecked : this.optionUnchecked;
9337
+
9338
+ /**
9339
+ * Used only for form reactive controller
9340
+ */
9341
+ this.formSubmitController = new FormSubmitController(this);
9342
+ }
9343
+
9344
+ render() {
9345
+ return $`
9346
+ <label part="label">
9347
+ ${this.makeUncheckedOption()}
9348
+ <span part="control">
9349
+ <span part="track"></span>
9350
+ <span part="handle"></span>
9351
+ </span>
9352
+ <input
9353
+ role="switch"
9354
+ type="checkbox"
9355
+ name="${this.name}"
9356
+ aria-label="${this.label}"
9357
+ aria-checked=${this.checked ? 'true' : 'false'}
9358
+ ?disabled=${this.disabled}
9359
+ ?checked=${this.checked}
9360
+ @change=${this.handleChange}
9361
+ />
9362
+ ${this.makeCheckedOption()}
9363
+ <span part="text">${this.label}</span>
9364
+ </label>
9365
+ `;
9366
+ }
9367
+
9368
+ handleChange() {
9369
+ this.checked = !this.checked;
9370
+ this.value = this.checked ? this.optionChecked : this.optionUnchecked;
9371
+
9372
+ /**
9373
+ * Fires when the toggle changes state
9374
+ */
9375
+ this.dispatchEvent(
9376
+ new CustomEvent('kemet-toggle-change', {
9377
+ bubbles: true,
9378
+ composed: true,
9379
+ detail: true,
9380
+ }),
9381
+ );
9382
+ }
9383
+
9384
+ makeUncheckedOption() {
9385
+ if (this.show) {
9386
+ return $`<span class="option" part="unchecked">${this.optionUnchecked}</span>`;
9387
+ }
9388
+
9389
+ return null;
9390
+ }
9391
+
9392
+ makeCheckedOption() {
9393
+ if (this.show) {
9394
+ return $`<span class="option" part="checked">${this.optionChecked}</span>`;
9395
+ }
9396
+
9397
+ return null;
9028
9398
  }
9029
9399
  }
9030
9400
 
9031
9401
  // eslint-disable-next-line no-unused-expressions
9032
- customElements.get('kemet-textarea') || customElements.define('kemet-textarea', KemetTextarea);
9402
+ customElements.get('kemet-toggle') || customElements.define('kemet-toggle', KemetToggle);
9033
9403
 
9034
- class KemetToggle extends s$1 {
9404
+ class KemetTrackerStep extends s$1 {
9035
9405
  static get styles() {
9036
9406
  return [
9037
9407
  r$3`
9038
9408
  :host {
9039
- --kemet-toggle-width: 3.5rem;
9040
- --kemet-toggle-height: 2rem;
9041
- --kemet-toggle-handle-diameter: 1.6rem;
9042
- --kemet-toggle-handle-margin: calc((var(--kemet-toggle-height) - var(--kemet-toggle-handle-diameter)) / 2);
9409
+ --kemet-tracker-step-dot-size: 50px;
9410
+ --kemet-tracker-step-dot-size-mobile: 25px;
9411
+ --kemet-tracker-step-dot-gap: 4px;
9412
+ --kemet-tracker-step-standard-line-weight: 1px;
9413
+ --kemet-tracker-step-completed-line-weight: 3px;
9414
+ --kemet-tracker-step-dot-transition: all 300ms ease-in-out;
9415
+
9416
+ position: relative;
9417
+ width: 100%;
9418
+ text-align: center;
9419
+ }
9043
9420
 
9421
+ .dot {
9422
+ font-size: var(--kemet-tracker-step-dot-font-size, 90%);
9423
+ color: var(--kemet-tracker-step-dot-color, var(--kemet-color-primary));
9044
9424
  display: flex;
9045
9425
  align-items: center;
9426
+ justify-content: center;
9427
+ margin: 0 auto;
9428
+ position: relative;
9429
+ z-index: 1;
9430
+ width: var(--kemet-tracker-step-dot-size);
9431
+ height: var(--kemet-tracker-step-dot-size);
9432
+ border-radius: 100%;
9433
+ transition: var(--kemet-tracker-step-dot-transition);
9434
+ background-color: var(--kemet-tracker-step-dot-background-color, var(--kemet-color-white));
9046
9435
  }
9047
9436
 
9048
- :host([disabled]) {
9049
- opacity: 0.5;
9437
+ .dot::after {
9438
+ content: "";
9439
+ width: unset;
9440
+ height: unset;
9441
+ position: absolute;
9442
+ top: var(--kemet-tracker-step-dot-gap);
9443
+ left: var(--kemet-tracker-step-dot-gap);
9444
+ right: var(--kemet-tracker-step-dot-gap);
9445
+ bottom: var(--kemet-tracker-step-dot-gap);
9446
+ z-index: -1;
9447
+ border-radius: 100%;
9448
+ transition: var(--kemet-tracker-step-dot-transition);
9449
+ border: var(--kemet-tracker-step-dot-border, 1px solid var(--kemet-color-primary));
9450
+ background-color: var(--kemet-tracker-step-dot-fill-color, transparent);
9050
9451
  }
9051
9452
 
9052
- label {
9053
- cursor: pointer;
9054
- display: flex;
9055
- align-items: center;
9056
- gap: 1rem;
9057
- font-size: inherit;
9058
- color: inherit;
9453
+ :host([completed]) .dot {
9454
+ color: var(--kemet-tracker-step-completed-color, var(--kemet-color-white));
9059
9455
  }
9060
9456
 
9061
- :host([disabled]) label {
9062
- cursor: not-allowed;
9457
+ :host([completed]) .dot::after {
9458
+ border: 0;
9459
+ background-color: var(--kemet-tracker-step-completed-fill-color, var(--kemet-color-success));
9063
9460
  }
9064
9461
 
9065
- input {
9066
- display: none;
9462
+ :host([current]) .dot.animate {
9463
+ color: var(--kemet-tracker-step-current-color, var(--kemet-color-white));
9067
9464
  }
9068
9465
 
9069
- [part='control'] {
9070
- position: relative;
9071
- display: inline-flex;
9072
- margin: 0;
9073
- width: var(--kemet-toggle-width);
9074
- height: var(--kemet-toggle-height);
9466
+ :host([current]) .dot.animate::after {
9467
+ border: 0;
9468
+ background-color: var(--kemet-tracker-step-current-fill-color, var(--kemet-color-primary));
9075
9469
  }
9076
9470
 
9077
- [part='control'] > span {
9078
- transition: 300ms ease-in-out;
9471
+ :host([mobile]) .dot {
9472
+ width: var(--kemet-tracker-step-dot-size-mobile);
9473
+ height: var(--kemet-tracker-step-dot-size-mobile);
9079
9474
  }
9080
9475
 
9081
- [part='track'] {
9082
- width: var(--kemet-toggle-width);
9083
- height: var(--kemet-toggle-height);
9084
- border: var(--kemet-toggle-track-border, none);
9085
- border-radius: var(--kemet-toggle-height);
9086
- background-color: var(--kemet-toggle-track-color, var(--kemet-color-white));
9087
- box-shadow: var(--kemet-toggle-track-shadow, inset 0 0.4rem 0.7rem 0 rgba(47, 47, 47, 0.35), inset 0 -0.2rem 0.4rem 0 var(--kemet-color-gray1));
9476
+ .line {
9477
+ display: block;
9478
+ position: absolute;
9479
+ left: 50%;
9480
+ right: 0;
9481
+ bottom: 0;
9482
+ width: 100%;
9483
+
9484
+ /* standard */
9485
+ top: calc((var(--kemet-tracker-step-dot-size) - var(--kemet-tracker-step-standard-line-weight)) / 2);
9486
+ height: var(--kemet-tracker-step-standard-line-weight);
9487
+ background-color: var(--kemet-tracker-step-line-color, var(--kemet-color-primary));
9088
9488
  }
9089
9489
 
9090
- :host([squared]) [part='track'] {
9091
- border-radius: 0;
9490
+ .line.completed {
9491
+ width: 100%;
9492
+ transform: scaleX(0);
9493
+ transform-origin: left center;
9494
+ top: calc((var(--kemet-tracker-step-dot-size) - var(--kemet-tracker-step-completed-line-weight)) / 2);
9495
+ height: var(--kemet-tracker-step-completed-line-weight);
9496
+ background-color: var(--kemet-tracker-step-completed-line-color, var(--kemet-color-primary));
9497
+ animation-name: grow;
9498
+ animation-delay: 1s;
9499
+ animation-duration: 600ms;
9500
+ animation-fill-mode: forwards;
9092
9501
  }
9093
9502
 
9094
- [part='handle'] {
9095
- position: absolute;
9096
- top: var(--kemet-toggle-handle-margin);
9097
- left: var(--kemet-toggle-handle-margin);
9098
- width: var(--kemet-toggle-handle-diameter);
9099
- height: var(--kemet-toggle-handle-diameter);
9100
- transform: translateX(0);
9101
- border: var(--kemet-toggle-handle-border, none);
9102
- border-radius: var(--kemet-toggle-handle-diameter);
9103
- background-color: var(--kemet-toggle-handle-color, var(--kemet-color-primary));
9104
- box-shadow: var(--kemet-toggle-handle-shadow, 0 0.5rem 0.5rem 0 rgba(0, 0, 0, 0.1), 0 0.5rem 0.5rem 0 rgba(0, 0, 0, 0.2));
9503
+ :host([mobile]) .line {
9504
+ top: calc((var(--kemet-tracker-step-dot-size-mobile) - var(--kemet-tracker-step-standard-line-weight)) / 2);
9505
+ }
9506
+
9507
+ :host([mobile]) .line.completed {
9508
+ top: calc((var(--kemet-tracker-step-dot-size-mobile) - var(--kemet-tracker-step-completed-line-weight)) / 2);
9509
+ }
9510
+
9511
+ @keyframes grow {
9512
+ from { transform: scaleX(0); }
9513
+ to { transform: scaleX(1); }
9105
9514
  }
9515
+ `,
9516
+ ];
9517
+ }
9518
+
9519
+ static get properties() {
9520
+ return {
9521
+ /**
9522
+ * The current step number
9523
+ */
9524
+ step: {
9525
+ type: Number,
9526
+ },
9527
+ /**
9528
+ * Determines whether or not a step renders as complete
9529
+ */
9530
+ completed: {
9531
+ type: Boolean,
9532
+ reflect: true,
9533
+ },
9534
+ /**
9535
+ * Determines whether or not a step renders as the current step
9536
+ */
9537
+ current: {
9538
+ type: Boolean,
9539
+ reflect: true,
9540
+ },
9541
+ /**
9542
+ * Is automatically added to the last step
9543
+ */
9544
+ last: {
9545
+ type: Boolean,
9546
+ reflect: true,
9547
+ },
9548
+ /**
9549
+ * Determines if a step should render as mobile
9550
+ */
9551
+ mobile: {
9552
+ type: Boolean,
9553
+ reflect: true,
9554
+ },
9555
+ /**
9556
+ * Hides the label inside of a dot
9557
+ */
9558
+ hideDotContent: {
9559
+ type: Boolean,
9560
+ reflect: true,
9561
+ attribute: 'hide-dot-content',
9562
+ },
9563
+ /**
9564
+ * The icon size for the completed check mark
9565
+ */
9566
+ completedSize: {
9567
+ type: Number,
9568
+ },
9569
+ };
9570
+ }
9571
+
9572
+ constructor() {
9573
+ super();
9574
+ this.completedSize = 16;
9575
+ }
9576
+
9577
+ firstUpdated() {
9578
+ this.tracker = this.closest('kemet-tracker');
9579
+ }
9580
+
9581
+ render() {
9582
+ return $`
9583
+ ${this.makeLine()}
9584
+ ${this.makeCompletedLine()}
9585
+ <div class="dot" part="dot">${this.makeDotContent()}</div>
9586
+ ${this.makeSlotContent()}
9587
+ `;
9588
+ }
9589
+
9590
+ makeLine() {
9591
+ if (!this.last) {
9592
+ return $`<div class="line" part="line"></div>`;
9593
+ }
9594
+
9595
+ return null;
9596
+ }
9597
+
9598
+ makeCompletedLine() {
9599
+ if (this.completed && !this.last) {
9600
+ return $`<div class="line completed" part="completed-line" @animationend=${() => this.handleCompletedLineEnd()}></div>`;
9601
+ }
9602
+
9603
+ return null;
9604
+ }
9605
+
9606
+ makeDotContent() {
9607
+ if (this.completed && !this.mobile && !this.hideDotContent) {
9608
+ return $`
9609
+ <kemet-icon icon="check2" size=${this.completedSize}></kemet-icon>
9610
+ `;
9611
+ }
9612
+
9613
+ if (!this.mobile && !this.hideDotContent) {
9614
+ return $`
9615
+ <span>${this.step}/${this.tracker?.total}</span>
9616
+ `;
9617
+ }
9618
+
9619
+ return null;
9620
+ }
9621
+
9622
+ makeSlotContent() {
9623
+ if (!this.mobile) {
9624
+ return $`<slot></slot>`;
9625
+ }
9106
9626
 
9107
- :host([squared]) [part='handle'] {
9108
- border-radius: 0;
9109
- }
9627
+ return null;
9628
+ }
9110
9629
 
9111
- :host([checked]) [part='handle'] {
9112
- transform: translateX(calc(var(--kemet-toggle-width) - var(--kemet-toggle-handle-diameter) - var(--kemet-toggle-handle-margin) * 2));
9113
- }
9630
+ handleCompletedLineEnd() {
9631
+ const currentDot = this.tracker.querySelector('[current]').shadowRoot.querySelector('.dot');
9114
9632
 
9115
- .option {
9116
- font-size: 90%;
9633
+ if (currentDot) {
9634
+ currentDot.classList.add('animate');
9635
+ }
9636
+ }
9637
+ }
9638
+
9639
+ // eslint-disable-next-line no-unused-expressions
9640
+ customElements.get('kemet-tracker-step') || customElements.define('kemet-tracker-step', KemetTrackerStep);
9641
+
9642
+ class KemetTracker extends s$1 {
9643
+ static get styles() {
9644
+ return [
9645
+ r$3`
9646
+ :host {
9647
+ display: flex;
9648
+ justify-content: center;
9649
+ align-items: flex-start;
9117
9650
  }
9118
9651
  `,
9119
9652
  ];
@@ -9122,384 +9655,361 @@ class KemetToggle extends s$1 {
9122
9655
  static get properties() {
9123
9656
  return {
9124
9657
  /**
9125
- * The name on the input field
9126
- */
9127
- name: {
9128
- type: String,
9129
- },
9130
- /**
9131
- * Determines whether or not the toggle is checked
9132
- */
9133
- checked: {
9134
- type: Boolean,
9135
- reflect: true,
9136
- },
9137
- /**
9138
- * Determines whether or not the toggle is disabled
9139
- */
9140
- disabled: {
9141
- type: Boolean,
9142
- },
9143
- /**
9144
- * A description of the toggle's purpose
9145
- */
9146
- label: {
9147
- type: String,
9148
- },
9149
- /**
9150
- * Determines whether or not to show text options
9151
- */
9152
- show: {
9153
- type: Boolean,
9154
- },
9155
- /**
9156
- * Displays the toggle as squared instead of rounded
9157
- */
9158
- squared: {
9159
- type: Boolean,
9160
- },
9161
- /**
9162
- * The checked option text
9658
+ * The total number of steps
9163
9659
  */
9164
- optionChecked: {
9165
- type: String,
9166
- attribute: 'option-checked',
9660
+ total: {
9661
+ type: Number,
9167
9662
  },
9168
9663
  /**
9169
- * The unchecked option text
9664
+ * The point at which the tracker goes from mobile to standard
9170
9665
  */
9171
- optionUnchecked: {
9666
+ breakpoint: {
9172
9667
  type: String,
9173
- attribute: 'option-unchecked',
9174
9668
  },
9175
9669
  };
9176
9670
  }
9177
9671
 
9178
9672
  constructor() {
9179
9673
  super();
9674
+ this.breakpoint = '767px';
9675
+ }
9180
9676
 
9181
- this.name = 'toggle-switch';
9182
- this.disabled = false;
9183
- this.checked = false;
9184
- this.show = false;
9185
- this.squared = false;
9186
- this.label = '';
9187
- this.optionChecked = 'on';
9188
- this.optionUnchecked = 'off';
9189
- this.value = this.checked ? this.optionChecked : this.optionUnchecked;
9677
+ firstUpdated() {
9678
+ // elements
9679
+ this.steps = this.querySelectorAll('kemet-tracker-step');
9190
9680
 
9191
- /**
9192
- * Used only for form reactive controller
9193
- */
9194
- this.formSubmitController = new FormSubmitController(this);
9681
+ // methods exe
9682
+ this.isMobile();
9683
+
9684
+ // events
9685
+ window.addEventListener('resize', () => {
9686
+ this.isMobile();
9687
+ });
9195
9688
  }
9196
9689
 
9197
9690
  render() {
9198
- return $`
9199
- <label part="label">
9200
- ${this.makeUncheckedOption()}
9201
- <span part="control">
9202
- <span part="track"></span>
9203
- <span part="handle"></span>
9204
- </span>
9205
- <input
9206
- role="switch"
9207
- type="checkbox"
9208
- name="${this.name}"
9209
- aria-label="${this.label}"
9210
- aria-checked=${this.checked ? 'true' : 'false'}
9211
- ?disabled=${this.disabled}
9212
- ?checked=${this.checked}
9213
- @change=${this.handleChange}
9214
- />
9215
- ${this.makeCheckedOption()}
9216
- <span part="text">${this.label}</span>
9217
- </label>
9218
- `;
9691
+ return $`<slot @slotchange=${() => this.handleSlotChange()}></slot>`;
9219
9692
  }
9220
9693
 
9221
- handleChange() {
9222
- this.checked = !this.checked;
9223
- this.value = this.checked ? this.optionChecked : this.optionUnchecked;
9694
+ handleSlotChange() {
9695
+ this.total = this.steps.length;
9224
9696
 
9225
- /**
9226
- * Fires when the toggle changes state
9227
- */
9228
- this.dispatchEvent(
9229
- new CustomEvent('kemet-toggle-change', {
9230
- bubbles: true,
9231
- composed: true,
9232
- detail: true,
9233
- }),
9234
- );
9697
+ this.steps.forEach((step, index) => {
9698
+ step.step = index + 1;
9699
+ if (step.step === this.total) {
9700
+ step.last = true;
9701
+ }
9702
+ });
9235
9703
  }
9236
9704
 
9237
- makeUncheckedOption() {
9238
- if (this.show) {
9239
- return $`<span class="option" part="unchecked">${this.optionUnchecked}</span>`;
9240
- }
9705
+ isMobile() {
9706
+ const mediaQuery = window.matchMedia(`(max-width: ${this.breakpoint})`);
9241
9707
 
9242
- return null;
9708
+ this.steps.forEach((step) => {
9709
+ step.mobile = mediaQuery.matches;
9710
+ });
9243
9711
  }
9712
+ }
9244
9713
 
9245
- makeCheckedOption() {
9246
- if (this.show) {
9247
- return $`<span class="option" part="checked">${this.optionChecked}</span>`;
9248
- }
9714
+ // eslint-disable-next-line no-unused-expressions
9715
+ customElements.get('kemet-tracker') || customElements.define('kemet-tracker', KemetTracker);
9249
9716
 
9250
- return null;
9717
+ const stylesLoaders = r$3`
9718
+ .lds-ripple {
9719
+ display: inline-block;
9720
+ position: relative;
9721
+ width: 80px;
9722
+ height: 80px;
9251
9723
  }
9252
- }
9253
9724
 
9254
- // eslint-disable-next-line no-unused-expressions
9255
- customElements.get('kemet-toggle') || customElements.define('kemet-toggle', KemetToggle);
9725
+ .lds-ripple div {
9726
+ position: absolute;
9727
+ border: 4px solid var(--kemet-upload-file-ripple-color);
9728
+ opacity: 1;
9729
+ border-radius: 50%;
9730
+ animation: lds-ripple 1s cubic-bezier(0, 0.2, 0.8, 1) infinite;
9731
+ }
9732
+
9733
+ .lds-ripple div:nth-child(2) {
9734
+ animation-delay: -0.5s;
9735
+ }
9736
+
9737
+ @keyframes lds-ripple {
9738
+ 0% {
9739
+ top: 36px;
9740
+ left: 36px;
9741
+ width: 0;
9742
+ height: 0;
9743
+ opacity: 0;
9744
+ }
9745
+ 4.9% {
9746
+ top: 36px;
9747
+ left: 36px;
9748
+ width: 0;
9749
+ height: 0;
9750
+ opacity: 0;
9751
+ }
9752
+ 5% {
9753
+ top: 36px;
9754
+ left: 36px;
9755
+ width: 0;
9756
+ height: 0;
9757
+ opacity: 1;
9758
+ }
9759
+ 100% {
9760
+ top: 0px;
9761
+ left: 0px;
9762
+ width: 72px;
9763
+ height: 72px;
9764
+ opacity: 0;
9765
+ }
9766
+ }
9767
+ `;
9256
9768
 
9257
- class KemetTrackerStep extends s$1 {
9769
+ const formatBytes = (bytes, decimals = 2) => {
9770
+ if (bytes === 0) return '0 Bytes';
9771
+
9772
+ const k = 1024;
9773
+ const dm = decimals < 0 ? 0 : decimals;
9774
+ const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
9775
+
9776
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
9777
+
9778
+ // eslint-disable-next-line no-restricted-properties
9779
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
9780
+ };
9781
+
9782
+ class KemetUploadFile extends s$1 {
9258
9783
  static get styles() {
9259
9784
  return [
9260
9785
  r$3`
9261
9786
  :host {
9262
- --kemet-tracker-step-dot-size: 50px;
9263
- --kemet-tracker-step-dot-size-mobile: 25px;
9264
- --kemet-tracker-step-dot-gap: 4px;
9265
- --kemet-tracker-step-standard-line-weight: 1px;
9266
- --kemet-tracker-step-completed-line-weight: 3px;
9267
- --kemet-tracker-step-dot-transition: all 300ms ease-in-out;
9268
-
9269
- position: relative;
9270
- width: 100%;
9271
- text-align: center;
9272
- }
9787
+ --kemet-upload-file-ripple-color: var(--kemet-color-primary);
9273
9788
 
9274
- .dot {
9275
- font-size: var(--kemet-tracker-step-dot-font-size, 90%);
9276
- color: var(--kemet-tracker-step-dot-color, var(--kemet-color-primary));
9277
- display: flex;
9789
+ color: var(--kemet-upload-file-color, var(--kemet-color-gray7));
9790
+ display: grid;
9791
+ gap: 1rem;
9792
+ grid-template-columns: auto 1fr auto;
9278
9793
  align-items: center;
9279
- justify-content: center;
9280
- margin: 0 auto;
9281
- position: relative;
9282
- z-index: 1;
9283
- width: var(--kemet-tracker-step-dot-size);
9284
- height: var(--kemet-tracker-step-dot-size);
9285
- border-radius: 100%;
9286
- transition: var(--kemet-tracker-step-dot-transition);
9287
- background-color: var(--kemet-tracker-step-dot-background-color, var(--kemet-color-white));
9288
- }
9289
-
9290
- .dot::after {
9291
- content: "";
9292
- width: unset;
9293
- height: unset;
9294
- position: absolute;
9295
- top: var(--kemet-tracker-step-dot-gap);
9296
- left: var(--kemet-tracker-step-dot-gap);
9297
- right: var(--kemet-tracker-step-dot-gap);
9298
- bottom: var(--kemet-tracker-step-dot-gap);
9299
- z-index: -1;
9300
- border-radius: 100%;
9301
- transition: var(--kemet-tracker-step-dot-transition);
9302
- border: var(--kemet-tracker-step-dot-border, 1px solid var(--kemet-color-primary));
9303
- background-color: var(--kemet-tracker-step-dot-fill-color, transparent);
9794
+ padding: var(--kemet-upload-file-padding, 0.5rem 1rem);
9795
+ border: var(--kemet-upload-file-border, 1px solid var(--kemet-color-primary));
9304
9796
  }
9305
9797
 
9306
- :host([completed]) .dot {
9307
- color: var(--kemet-tracker-step-completed-color, var(--kemet-color-white));
9308
- }
9309
-
9310
- :host([completed]) .dot::after {
9311
- border: 0;
9312
- background-color: var(--kemet-tracker-step-completed-fill-color, var(--kemet-color-success));
9313
- }
9314
-
9315
- :host([current]) .dot.animate {
9316
- color: var(--kemet-tracker-step-current-color, var(--kemet-color-white));
9317
- }
9318
-
9319
- :host([current]) .dot.animate::after {
9320
- border: 0;
9321
- background-color: var(--kemet-tracker-step-current-fill-color, var(--kemet-color-primary));
9798
+ :host([status='error']) {
9799
+ border: 1px solid var(--kemet-color-error);
9322
9800
  }
9323
9801
 
9324
- :host([mobile]) .dot {
9325
- width: var(--kemet-tracker-step-dot-size-mobile);
9326
- height: var(--kemet-tracker-step-dot-size-mobile);
9802
+ :host([status='complete']) {
9803
+ border: 1px solid var(--kemet-color-success);
9327
9804
  }
9328
9805
 
9329
- .line {
9330
- display: block;
9331
- position: absolute;
9332
- left: 50%;
9333
- right: 0;
9334
- bottom: 0;
9335
- width: 100%;
9336
-
9337
- /* standard */
9338
- top: calc((var(--kemet-tracker-step-dot-size) - var(--kemet-tracker-step-standard-line-weight)) / 2);
9339
- height: var(--kemet-tracker-step-standard-line-weight);
9340
- background-color: var(--kemet-tracker-step-line-color, var(--kemet-color-primary));
9806
+ h3 {
9807
+ margin: 0;
9341
9808
  }
9342
9809
 
9343
- .line.completed {
9344
- width: 100%;
9345
- transform: scaleX(0);
9346
- transform-origin: left center;
9347
- top: calc((var(--kemet-tracker-step-dot-size) - var(--kemet-tracker-step-completed-line-weight)) / 2);
9348
- height: var(--kemet-tracker-step-completed-line-weight);
9349
- background-color: var(--kemet-tracker-step-completed-line-color, var(--kemet-color-primary));
9350
- animation-name: grow;
9351
- animation-delay: 1s;
9352
- animation-duration: 600ms;
9353
- animation-fill-mode: forwards;
9810
+ .percentage {
9811
+ font-size: clamp(2rem, 3vw, 2.5rem);
9812
+ align-self: center;
9813
+ justify-self: center;
9354
9814
  }
9355
9815
 
9356
- :host([mobile]) .line {
9357
- top: calc((var(--kemet-tracker-step-dot-size-mobile) - var(--kemet-tracker-step-standard-line-weight)) / 2);
9816
+ .indicator {
9817
+ transform: scale(0.8);
9358
9818
  }
9359
9819
 
9360
- :host([mobile]) .line.completed {
9361
- top: calc((var(--kemet-tracker-step-dot-size-mobile) - var(--kemet-tracker-step-completed-line-weight)) / 2);
9820
+ :host([status='complete']) .message,
9821
+ :host([status='complete']) .indicator {
9822
+ color: var(--kemet-color-success);
9362
9823
  }
9363
9824
 
9364
- @keyframes grow {
9365
- from { transform: scaleX(0); }
9366
- to { transform: scaleX(1); }
9825
+ :host([status='error']) .message,
9826
+ :host([status='error']) .indicator {
9827
+ color: var(--kemet-color-error);
9367
9828
  }
9368
9829
  `,
9830
+ stylesLoaders,
9369
9831
  ];
9370
9832
  }
9371
9833
 
9372
9834
  static get properties() {
9373
9835
  return {
9374
9836
  /**
9375
- * The current step number
9837
+ * The name of the file
9376
9838
  */
9377
- step: {
9378
- type: Number,
9839
+ name: {
9840
+ type: String,
9379
9841
  },
9380
9842
  /**
9381
- * Determines whether or not a step renders as complete
9843
+ * The number of bytes loaded
9382
9844
  */
9383
- completed: {
9384
- type: Boolean,
9385
- reflect: true,
9845
+ loaded: {
9846
+ type: Number,
9386
9847
  },
9387
9848
  /**
9388
- * Determines whether or not a step renders as the current step
9849
+ * The file size in bytes
9389
9850
  */
9390
- current: {
9391
- type: Boolean,
9392
- reflect: true,
9851
+ size: {
9852
+ type: Number,
9393
9853
  },
9394
9854
  /**
9395
- * Is automatically added to the last step
9855
+ * The file type
9396
9856
  */
9397
- last: {
9398
- type: Boolean,
9399
- reflect: true,
9857
+ type: {
9858
+ type: String,
9400
9859
  },
9401
9860
  /**
9402
- * Determines if a step should render as mobile
9861
+ * The status of the file. Values are complete | uploading | error.
9403
9862
  */
9404
- mobile: {
9405
- type: Boolean,
9863
+ status: {
9864
+ type: String,
9406
9865
  reflect: true,
9407
9866
  },
9408
9867
  /**
9409
- * Hides the label inside of a dot
9868
+ * A percentage of file completion that's calculated by the loaded property
9410
9869
  */
9411
- hideDotContent: {
9412
- type: Boolean,
9413
- reflect: true,
9414
- attribute: 'hide-dot-content',
9870
+ percent: {
9871
+ type: Number,
9415
9872
  },
9416
9873
  /**
9417
- * The icon size for the completed check mark
9874
+ * An error message to give to users
9418
9875
  */
9419
- completedSize: {
9420
- type: Number,
9876
+ message: {
9877
+ type: String,
9421
9878
  },
9422
9879
  };
9423
9880
  }
9424
9881
 
9425
9882
  constructor() {
9426
9883
  super();
9427
- this.completedSize = 16;
9884
+ this.loaded = 0;
9885
+ this.size = 0;
9886
+ this.percent = 0;
9428
9887
  }
9429
9888
 
9430
- firstUpdated() {
9431
- this.tracker = this.closest('kemet-tracker');
9889
+ updated() {
9890
+ this.percent = this.calculatePercent();
9432
9891
  }
9433
9892
 
9434
9893
  render() {
9435
9894
  return $`
9436
- ${this.makeLine()}
9437
- ${this.makeCompletedLine()}
9438
- <div class="dot" part="dot">${this.makeDotContent()}</div>
9439
- ${this.makeSlotContent()}
9895
+ <div class="percentage" part="percentage">
9896
+ <span>${this.percent}%</span>
9897
+ </div>
9898
+ <div>
9899
+ <h3 part="filename">${this.name}</h3>
9900
+ <span part="loaded">${formatBytes(this.loaded)} / ${formatBytes(this.size)}</span>
9901
+ ${this.message ? $`<div class="message" part="message">${this.message}</div>` : null}
9902
+ </div>
9903
+ <div class="indicator" part="indicator">
9904
+ ${this.getStatusIcon()}
9905
+ </div>
9440
9906
  `;
9441
9907
  }
9442
9908
 
9443
- makeLine() {
9444
- if (!this.last) {
9445
- return $`<div class="line" part="line"></div>`;
9446
- }
9447
-
9448
- return null;
9449
- }
9450
-
9451
- makeCompletedLine() {
9452
- if (this.completed && !this.last) {
9453
- return $`<div class="line completed" part="completed-line" @animationend=${() => this.handleCompletedLineEnd()}></div>`;
9454
- }
9455
-
9456
- return null;
9909
+ calculatePercent() {
9910
+ const percent = Math.round((this.loaded * 100.0) / this.size);
9911
+ return percent > 100 ? 100 : percent;
9457
9912
  }
9458
9913
 
9459
- makeDotContent() {
9460
- if (this.completed && !this.mobile && !this.hideDotContent) {
9461
- return $`
9462
- <kemet-icon icon="check2" size=${this.completedSize}></kemet-icon>
9463
- `;
9914
+ getStatusIcon() {
9915
+ if (this.status === 'uploading') {
9916
+ return $`<div class="lds-ripple"><div></div><div></div></div>`;
9464
9917
  }
9465
9918
 
9466
- if (!this.mobile && !this.hideDotContent) {
9467
- return $`
9468
- <span>${this.step}/${this.tracker?.total}</span>
9469
- `;
9919
+ if (this.status === 'complete') {
9920
+ return $`<kemet-icon icon="check-circle" size="48"></kemet-icon>`;
9470
9921
  }
9471
9922
 
9472
- return null;
9473
- }
9474
-
9475
- makeSlotContent() {
9476
- if (!this.mobile) {
9477
- return $`<slot></slot>`;
9923
+ if (this.status === 'error') {
9924
+ return $`<kemet-icon icon="exclamation-circle" size="48"></kemet-icon>`;
9478
9925
  }
9479
9926
 
9480
9927
  return null;
9481
9928
  }
9482
-
9483
- handleCompletedLineEnd() {
9484
- const currentDot = this.tracker.querySelector('[current]').shadowRoot.querySelector('.dot');
9485
-
9486
- if (currentDot) {
9487
- currentDot.classList.add('animate');
9488
- }
9489
- }
9490
9929
  }
9491
9930
 
9492
9931
  // eslint-disable-next-line no-unused-expressions
9493
- customElements.get('kemet-tracker-step') || customElements.define('kemet-tracker-step', KemetTrackerStep);
9932
+ customElements.get('kemet-upload-file') || customElements.define('kemet-upload-file', KemetUploadFile);
9494
9933
 
9495
- class KemetTracker extends s$1 {
9934
+ const preventDefaults = (event) => {
9935
+ event.preventDefault();
9936
+ event.stopPropagation();
9937
+ };
9938
+
9939
+ class KemetUpload extends s$1 {
9496
9940
  static get styles() {
9497
9941
  return [
9498
9942
  r$3`
9499
9943
  :host {
9944
+ color: var(--kemet-upload-color, var(--kemet-color-white));
9945
+ display: grid;
9946
+ grid-template-columns: 1fr 1fr;
9947
+ height: var(--kemet-upload-height, 364px);
9948
+ border: var(--kemet-upload-border, 1rem solid var(--kemet-color-white));
9949
+ background-color: var(--kemet-upload-background-color, var(--kemet-color-primary));
9950
+ }
9951
+
9952
+ :host([mobile]) {
9953
+ display: block;
9954
+ height: auto;
9955
+ }
9956
+
9957
+ input {
9958
+ display: none;
9959
+ }
9960
+
9961
+ .button {
9962
+ cursor: pointer;
9963
+ font-size: 1rem;
9964
+ display: block;
9965
+ color: var(--kemet-color-white);
9966
+ padding: 0.5rem 1rem;
9967
+ border: 1px solid var(--kemet-color-white);
9968
+ background-color: transparent;
9969
+ }
9970
+
9971
+ .upload {
9500
9972
  display: flex;
9973
+ align-items: center;
9501
9974
  justify-content: center;
9502
- align-items: flex-start;
9975
+ margin: 1rem;
9976
+ flex-direction: column;
9977
+ border: 2px dashed var(--kemet-color-white);
9978
+ }
9979
+
9980
+ :host([over]) .upload {
9981
+ background-color: green;
9982
+ }
9983
+
9984
+ :host([mobile]) .upload {
9985
+ height: 280px;
9986
+ }
9987
+
9988
+ .files {
9989
+ display: flex;
9990
+ gap: 1rem;
9991
+ flex-direction: column;
9992
+ padding: 0 1rem;
9993
+ overflow: auto;
9994
+ background-color: var(--kemet-color-white);
9995
+ }
9996
+
9997
+ :host([mobile]) .files {
9998
+ padding: 0;
9999
+ max-height: 280px;
10000
+ }
10001
+
10002
+ .heading {
10003
+ font-size: 1.25rem;
10004
+ margin: 0 0 2rem 0;
10005
+ }
10006
+
10007
+ :host([no-drag-drop]) .heading {
10008
+ display: none;
10009
+ }
10010
+
10011
+ ::slotted(:first-child) {
10012
+ margin-top: 1rem;
9503
10013
  }
9504
10014
  `,
9505
10015
  ];
@@ -9508,64 +10018,176 @@ class KemetTracker extends s$1 {
9508
10018
  static get properties() {
9509
10019
  return {
9510
10020
  /**
9511
- * The total number of steps
10021
+ * A unique identifier for the component
9512
10022
  */
9513
- total: {
9514
- type: Number,
10023
+ slug: {
10024
+ type: String,
9515
10025
  },
9516
10026
  /**
9517
- * The point at which the tracker goes from mobile to standard
10027
+ * Determines what file types are accepted
10028
+ */
10029
+ accept: {
10030
+ type: String,
10031
+ },
10032
+ /**
10033
+ * Allows for multiple files
10034
+ */
10035
+ multiple: {
10036
+ type: Boolean,
10037
+ },
10038
+ /**
10039
+ * Automatically is true when a file is being dragged over the upload area
10040
+ */
10041
+ over: {
10042
+ type: Boolean,
10043
+ reflect: true,
10044
+ },
10045
+ /**
10046
+ * Descriptive text for the upload area
10047
+ */
10048
+ heading: {
10049
+ type: String,
10050
+ },
10051
+ /**
10052
+ * Displays the component in a mobile context
10053
+ */
10054
+ mobile: {
10055
+ type: Boolean,
10056
+ reflect: true,
10057
+ },
10058
+ /**
10059
+ * Controls the point at which the component is considered mobile
9518
10060
  */
9519
10061
  breakpoint: {
9520
10062
  type: String,
10063
+ reflect: true,
10064
+ },
10065
+ /**
10066
+ * If true if drag and drop support is not detected
10067
+ */
10068
+ noDragDrop: {
10069
+ type: Boolean,
10070
+ reflect: true,
10071
+ attribute: 'no-drag-drop',
10072
+ },
10073
+ /**
10074
+ * The maximum file size for uploads
10075
+ */
10076
+ maxSize: {
10077
+ type: Number,
10078
+ attribute: 'max-size',
10079
+ },
10080
+ /**
10081
+ * The browse files button text
10082
+ */
10083
+ buttonLabel: {
10084
+ type: String,
10085
+ attribute: 'button-label',
9521
10086
  },
9522
10087
  };
9523
10088
  }
9524
10089
 
9525
10090
  constructor() {
9526
10091
  super();
9527
- this.breakpoint = '767px';
10092
+ this.slug = 'upload';
10093
+ this.breakpoint = '600px';
10094
+ this.buttonLabel = 'Browse Files';
10095
+ this.heading = 'Drag & Drop Files';
9528
10096
  }
9529
10097
 
9530
10098
  firstUpdated() {
9531
- // elements
9532
- this.steps = this.querySelectorAll('kemet-tracker-step');
10099
+ this.fileInputElement = this.shadowRoot.querySelector('[type="file"]');
10100
+ this.upload = this.shadowRoot.querySelector('.upload');
9533
10101
 
9534
- // methods exe
9535
- this.isMobile();
10102
+ ['dragenter', 'dragover', 'dragleave', 'drop'].forEach((eventName) => {
10103
+ this.upload.addEventListener(eventName, event => preventDefaults(event), false);
10104
+ });
9536
10105
 
9537
- // events
9538
- window.addEventListener('resize', () => {
9539
- this.isMobile();
10106
+ ['dragenter', 'dragover'].forEach((eventName) => {
10107
+ this.upload.addEventListener(eventName, () => { this.over = true; }, false);
10108
+ });
10109
+
10110
+ ['dragleave', 'drop'].forEach((eventName) => {
10111
+ this.upload.addEventListener(eventName, () => { this.over = false; }, false);
9540
10112
  });
10113
+
10114
+ this.isMobile();
10115
+ this.hasDragDrop();
10116
+
10117
+ window.addEventListener('resize', () => { this.isMobile(); });
10118
+ this.upload.addEventListener('drop', event => this.handleDrop(event), false);
9541
10119
  }
9542
10120
 
9543
10121
  render() {
9544
- return $`<slot @slotchange=${() => this.handleSlotChange()}></slot>`;
10122
+ return $`
10123
+ <div class="upload" part="upload">
10124
+ <kemet-icon icon="cloud-arrow-up" size="128"></kemet-icon>
10125
+ <input
10126
+ type="file"
10127
+ id=${this.slug}
10128
+ ?multiple=${this.multiple}
10129
+ accept=${l$1(this.accept) ? this.accept : null}
10130
+ @change=${event => this.handleChange(event)}
10131
+ />
10132
+ <h3 class="heading" part="heading">${this.heading}</h3>
10133
+ <label class="button" part="button" for=${this.slug}>${this.buttonLabel}</label>
10134
+ </div>
10135
+ <div class="files" part="files">
10136
+ <slot></slot>
10137
+ </div>
10138
+ `;
9545
10139
  }
9546
10140
 
9547
- handleSlotChange() {
9548
- this.total = this.steps.length;
10141
+ handleChange(event) {
10142
+ /**
10143
+ * Fires when files have been added
10144
+ */
10145
+ this.dispatchEvent(
10146
+ new CustomEvent('kemet-upload-change', {
10147
+ bubbles: true,
10148
+ composed: true,
10149
+ detail: {
10150
+ event,
10151
+ files: this.fileInputElement.files,
10152
+ fileElement: this.fileInputElement,
10153
+ },
10154
+ }),
10155
+ );
10156
+ }
9549
10157
 
9550
- this.steps.forEach((step, index) => {
9551
- step.step = index + 1;
9552
- if (step.step === this.total) {
9553
- step.last = true;
9554
- }
9555
- });
10158
+ handleDrop(event) {
10159
+ /**
10160
+ * Fires when files have been added
10161
+ */
10162
+ this.dispatchEvent(
10163
+ new CustomEvent('kemet-upload-change', {
10164
+ bubbles: true,
10165
+ composed: true,
10166
+ detail: {
10167
+ event,
10168
+ files: event?.dataTransfer.files || [],
10169
+ fileElement: this.fileInputElement,
10170
+ },
10171
+ }),
10172
+ );
9556
10173
  }
9557
10174
 
9558
10175
  isMobile() {
9559
10176
  const mediaQuery = window.matchMedia(`(max-width: ${this.breakpoint})`);
10177
+ this.mobile = mediaQuery.matches;
10178
+ }
9560
10179
 
9561
- this.steps.forEach((step) => {
9562
- step.mobile = mediaQuery.matches;
9563
- });
10180
+ hasDragDrop() {
10181
+ if ('draggable' in document.createElement('span')) {
10182
+ this.noDragDrop = false;
10183
+ } else {
10184
+ this.noDragDrop = true;
10185
+ }
9564
10186
  }
9565
10187
  }
9566
10188
 
9567
10189
  // eslint-disable-next-line no-unused-expressions
9568
- customElements.get('kemet-tracker') || customElements.define('kemet-tracker', KemetTracker);
10190
+ customElements.get('kemet-upload') || customElements.define('kemet-upload', KemetUpload);
9569
10191
 
9570
10192
  exports.KemetCarouselCurrent = KemetCarouselCurrent;
9571
10193
  exports.KemetCarouselFirst = KemetCarouselFirst;
@@ -9581,5 +10203,6 @@ exports.scale = scale;
9581
10203
  exports.sign = sign;
9582
10204
  exports.slide = slide;
9583
10205
  exports.stylesKemetTabs = stylesKemetTabs;
10206
+ exports.stylesLoaders = stylesLoaders;
9584
10207
  exports.superScaled = superScaled;
9585
10208
  exports.tooltip = tooltip;