@unabridged/midwest 0.10.2 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/app/assets/javascript/midwest/index.ts +6 -0
  2. package/app/assets/javascript/midwest.js +123 -2
  3. package/app/assets/javascript/midwest.js.map +1 -1
  4. package/app/assets/stylesheets/midwest.css +1 -1
  5. package/app/assets/stylesheets/midwest.tailwind.css +6 -1
  6. package/dist/css/midwest.css +1 -1
  7. package/dist/javascript/collection/app/assets/javascript/midwest/index.js +6 -0
  8. package/dist/javascript/collection/app/assets/javascript/midwest/index.js.map +1 -1
  9. package/dist/javascript/collection/app/components/midwest/accordion_component/accordion_component_controller.js +30 -0
  10. package/dist/javascript/collection/app/components/midwest/accordion_component/accordion_component_controller.js.map +1 -0
  11. package/dist/javascript/collection/app/components/midwest/avatar_group_component/avatar_group_component_controller.js +20 -0
  12. package/dist/javascript/collection/app/components/midwest/avatar_group_component/avatar_group_component_controller.js.map +1 -0
  13. package/dist/javascript/collection/app/components/midwest/badge_component/badge_component_controller.js +10 -0
  14. package/dist/javascript/collection/app/components/midwest/badge_component/badge_component_controller.js.map +1 -0
  15. package/dist/javascript/collection/app/components/midwest/banner_component/banner_component_controller.js +5 -0
  16. package/dist/javascript/collection/app/components/midwest/banner_component/banner_component_controller.js.map +1 -1
  17. package/dist/javascript/collection/app/components/midwest/carousel_component/carousel_component_controller.js +58 -1
  18. package/dist/javascript/collection/app/components/midwest/carousel_component/carousel_component_controller.js.map +1 -1
  19. package/dist/javascript/collection/app/components/midwest/confirmation_component/confirmation_component_controller.js +22 -0
  20. package/dist/javascript/collection/app/components/midwest/confirmation_component/confirmation_component_controller.js.map +1 -0
  21. package/dist/javascript/collection/app/components/midwest/tooltip_component/tooltip_component_controller.js +17 -1
  22. package/dist/javascript/collection/app/components/midwest/tooltip_component/tooltip_component_controller.js.map +1 -1
  23. package/dist/javascript/midwest.js +123 -2
  24. package/dist/javascript/midwest.js.map +1 -1
  25. package/package.json +1 -1
@@ -11,6 +11,9 @@ import Carousel from '../../../components/midwest/carousel_component/carousel_co
11
11
  import FormLiveSummary from '../../../components/midwest/form/live_summary_component/live_summary_component_controller'
12
12
  import Form from '../../../components/midwest/form/form_controller'
13
13
  import CountdownTimer from '../../../components/midwest/countdown_timer_component/countdown_timer_component_controller'
14
+ import Badge from '../../../components/midwest/badge_component/badge_component_controller'
15
+ import Confirmation from '../../../components/midwest/confirmation_component/confirmation_component_controller'
16
+ import AvatarGroup from '../../../components/midwest/avatar_group_component/avatar_group_component_controller'
14
17
  /* IMPORTS */
15
18
 
16
19
  export { Card, Banner, CountdownTimer }
@@ -29,5 +32,8 @@ export function registerMidwestControllers (application: any) {
29
32
  application.register('midwest-carousel', Carousel)
30
33
  application.register('midwest-form-live-summary', FormLiveSummary)
31
34
  application.register('midwest-form', Form)
35
+ application.register('midwest-badge', Badge)
36
+ application.register('midwest-confirmation', Confirmation)
37
+ application.register('midwest-avatar-group', AvatarGroup)
32
38
  /* EXPORTS */
33
39
  }
@@ -536,6 +536,11 @@ class Banner extends Controller {
536
536
  this.element.classList.add("visible");
537
537
  }
538
538
  close() {
539
+ if (!this.element.classList.contains("animated")) {
540
+ this.element.style.display = "none";
541
+ return;
542
+ }
543
+ this.element.classList.remove("shown");
539
544
  this.element.classList.add("closing");
540
545
  setTimeout(() => {
541
546
  this.element.classList.add("closed");
@@ -3155,21 +3160,37 @@ class Tabs extends Controller {
3155
3160
 
3156
3161
  class Tooltip extends Controller {
3157
3162
  static targets = ["popover"];
3163
+ static values = {
3164
+ delay: { type: Number, default: 0 }
3165
+ };
3166
+ showTimer = null;
3158
3167
  connect() {
3159
3168
  document.addEventListener("keydown", this.handleKeydown);
3160
3169
  }
3161
3170
  disconnect() {
3162
3171
  document.removeEventListener("keydown", this.handleKeydown);
3172
+ this.cancelShow();
3163
3173
  }
3164
3174
  show() {
3165
- this.popoverTarget.showPopover();
3175
+ if (this.delayValue > 0) {
3176
+ this.showTimer = setTimeout(() => this.popoverTarget.showPopover(), this.delayValue);
3177
+ } else {
3178
+ this.popoverTarget.showPopover();
3179
+ }
3166
3180
  }
3167
3181
  hide() {
3182
+ this.cancelShow();
3168
3183
  try {
3169
3184
  this.popoverTarget.hidePopover();
3170
3185
  } catch {
3171
3186
  }
3172
3187
  }
3188
+ cancelShow() {
3189
+ if (this.showTimer !== null) {
3190
+ clearTimeout(this.showTimer);
3191
+ this.showTimer = null;
3192
+ }
3193
+ }
3173
3194
  handleKeydown = (event) => {
3174
3195
  if (event.key !== "Escape")
3175
3196
  return;
@@ -3189,18 +3210,22 @@ const NON_SUBMITTING_INPUT_TYPES = /* @__PURE__ */ new Set([
3189
3210
  "reset",
3190
3211
  "submit"
3191
3212
  ]);
3213
+ const FORM_ELEMENT_TAGS = /* @__PURE__ */ new Set(["INPUT", "TEXTAREA", "SELECT"]);
3192
3214
  class Carousel extends Controller {
3193
3215
  static targets = ["track", "prev", "next", "dot"];
3194
3216
  static values = {
3195
- wizard: { type: Boolean, default: false }
3217
+ wizard: { type: Boolean, default: false },
3218
+ autoplay: { type: Number, default: 0 }
3196
3219
  };
3197
3220
  observer = null;
3198
3221
  _currentIndex = 0;
3199
3222
  _maxUnlocked = 0;
3200
3223
  _lastTouchX = 0;
3224
+ _autoplayTimer = null;
3201
3225
  connect() {
3202
3226
  this.setupObserver();
3203
3227
  this.updateNavigation();
3228
+ this.element.addEventListener("keydown", this.handleArrowKeys);
3204
3229
  if (this.wizardValue) {
3205
3230
  this.element.addEventListener("keydown", this.handleKeydown);
3206
3231
  this.trackTarget.addEventListener("wheel", this.handleWheel, { passive: false });
@@ -3208,13 +3233,22 @@ class Carousel extends Controller {
3208
3233
  this.trackTarget.addEventListener("touchmove", this.handleTouchMove, { passive: false });
3209
3234
  this.updateSlideAccessibility();
3210
3235
  }
3236
+ if (this.autoplayValue > 0) {
3237
+ this.startAutoplay();
3238
+ this.element.addEventListener("mouseenter", this.pauseAutoplay);
3239
+ this.element.addEventListener("mouseleave", this.resumeAutoplay);
3240
+ }
3211
3241
  }
3212
3242
  disconnect() {
3213
3243
  this.observer?.disconnect();
3244
+ this.element.removeEventListener("keydown", this.handleArrowKeys);
3214
3245
  this.element.removeEventListener("keydown", this.handleKeydown);
3246
+ this.element.removeEventListener("mouseenter", this.pauseAutoplay);
3247
+ this.element.removeEventListener("mouseleave", this.resumeAutoplay);
3215
3248
  this.trackTarget.removeEventListener("wheel", this.handleWheel);
3216
3249
  this.trackTarget.removeEventListener("touchstart", this.handleTouchStart);
3217
3250
  this.trackTarget.removeEventListener("touchmove", this.handleTouchMove);
3251
+ this.stopAutoplay();
3218
3252
  }
3219
3253
  next() {
3220
3254
  this.trackTarget.scrollBy({ left: this.trackTarget.clientWidth, behavior: "smooth" });
@@ -3250,6 +3284,22 @@ class Carousel extends Controller {
3250
3284
  this.updateNavigation();
3251
3285
  }
3252
3286
  // Arrow function so `this` is stable for add/removeEventListener pairing.
3287
+ // Handles ArrowLeft/ArrowRight for keyboard slide navigation. Skips form
3288
+ // elements so arrow keys continue to work normally inside inputs and selects.
3289
+ handleArrowKeys = (event) => {
3290
+ if (event.key !== "ArrowLeft" && event.key !== "ArrowRight")
3291
+ return;
3292
+ const target = event.target;
3293
+ if (FORM_ELEMENT_TAGS.has(target.tagName) || target.isContentEditable)
3294
+ return;
3295
+ event.preventDefault();
3296
+ if (event.key === "ArrowLeft") {
3297
+ this.previous();
3298
+ } else {
3299
+ this.next();
3300
+ }
3301
+ };
3302
+ // Arrow function so `this` is stable for add/removeEventListener pairing.
3253
3303
  handleKeydown = (event) => {
3254
3304
  if (event.key !== "Enter")
3255
3305
  return;
@@ -3284,6 +3334,34 @@ class Carousel extends Controller {
3284
3334
  event.preventDefault();
3285
3335
  }
3286
3336
  };
3337
+ pauseAutoplay = () => {
3338
+ this.stopAutoplay();
3339
+ };
3340
+ resumeAutoplay = () => {
3341
+ this.startAutoplay();
3342
+ };
3343
+ startAutoplay() {
3344
+ if (this.autoplayValue <= 0 || this._autoplayTimer !== null)
3345
+ return;
3346
+ this._autoplayTimer = setInterval(() => {
3347
+ this.autoplayAdvance();
3348
+ }, this.autoplayValue);
3349
+ }
3350
+ stopAutoplay() {
3351
+ if (this._autoplayTimer === null)
3352
+ return;
3353
+ clearInterval(this._autoplayTimer);
3354
+ this._autoplayTimer = null;
3355
+ }
3356
+ autoplayAdvance() {
3357
+ const atEnd = this._currentIndex >= this.slides.length - 1;
3358
+ if (atEnd) {
3359
+ const firstSlide = this.slides[0];
3360
+ firstSlide?.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" });
3361
+ } else {
3362
+ this.next();
3363
+ }
3364
+ }
3287
3365
  get slides() {
3288
3366
  return Array.from(this.trackTarget.children);
3289
3367
  }
@@ -3538,6 +3616,46 @@ class CountdownTimer extends Controller {
3538
3616
  }
3539
3617
  }
3540
3618
 
3619
+ class Badge extends Controller {
3620
+ remove() {
3621
+ this.element.remove();
3622
+ }
3623
+ }
3624
+
3625
+ class ConfirmationController extends Controller {
3626
+ static targets = ["input", "submitButton"];
3627
+ static values = { confirmText: String };
3628
+ connect() {
3629
+ this.validate();
3630
+ }
3631
+ validate() {
3632
+ const matches = this.inputTarget.value === this.confirmTextValue;
3633
+ this.submitButtonTarget.classList.toggle("disabled", !matches);
3634
+ this.submitButtonTarget.setAttribute("aria-disabled", String(!matches));
3635
+ if (matches) {
3636
+ this.submitButtonTarget.removeAttribute("tabindex");
3637
+ } else {
3638
+ this.submitButtonTarget.setAttribute("tabindex", "-1");
3639
+ }
3640
+ }
3641
+ }
3642
+
3643
+ class AvatarGroup extends Controller {
3644
+ static targets = ["overflow", "hidden"];
3645
+ expand() {
3646
+ this.element.classList.add("is-expanding");
3647
+ this.hiddenTargets.forEach((wrapper) => {
3648
+ wrapper.classList.add("is-visible");
3649
+ });
3650
+ if (this.hasOverflowTarget) {
3651
+ this.overflowTarget.classList.add("avatar-overflow-hiding");
3652
+ this.overflowTarget.addEventListener("transitionend", () => {
3653
+ this.overflowTarget.remove();
3654
+ }, { once: true });
3655
+ }
3656
+ }
3657
+ }
3658
+
3541
3659
  function registerMidwestControllers(application) {
3542
3660
  application.register("midwest-card", Card);
3543
3661
  application.register("midwest-banner", Banner);
@@ -3552,6 +3670,9 @@ function registerMidwestControllers(application) {
3552
3670
  application.register("midwest-carousel", Carousel);
3553
3671
  application.register("midwest-form-live-summary", FormLiveSummary);
3554
3672
  application.register("midwest-form", Form);
3673
+ application.register("midwest-badge", Badge);
3674
+ application.register("midwest-confirmation", ConfirmationController);
3675
+ application.register("midwest-avatar-group", AvatarGroup);
3555
3676
  }
3556
3677
 
3557
3678
  export { Banner, Card, CountdownTimer, registerMidwestControllers };