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