@unabridged/midwest 0.11.0 → 0.12.1

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 (23) hide show
  1. package/app/assets/javascript/midwest/index.ts +6 -0
  2. package/app/assets/javascript/midwest.js +118 -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/carousel_component/carousel_component_controller.js +58 -1
  16. package/dist/javascript/collection/app/components/midwest/carousel_component/carousel_component_controller.js.map +1 -1
  17. package/dist/javascript/collection/app/components/midwest/confirmation_component/confirmation_component_controller.js +22 -0
  18. package/dist/javascript/collection/app/components/midwest/confirmation_component/confirmation_component_controller.js.map +1 -0
  19. package/dist/javascript/collection/app/components/midwest/tooltip_component/tooltip_component_controller.js +17 -1
  20. package/dist/javascript/collection/app/components/midwest/tooltip_component/tooltip_component_controller.js.map +1 -1
  21. package/dist/javascript/midwest.js +118 -2
  22. package/dist/javascript/midwest.js.map +1 -1
  23. 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
  }
@@ -3160,21 +3160,37 @@ class Tabs extends Controller {
3160
3160
 
3161
3161
  class Tooltip extends Controller {
3162
3162
  static targets = ["popover"];
3163
+ static values = {
3164
+ delay: { type: Number, default: 0 }
3165
+ };
3166
+ showTimer = null;
3163
3167
  connect() {
3164
3168
  document.addEventListener("keydown", this.handleKeydown);
3165
3169
  }
3166
3170
  disconnect() {
3167
3171
  document.removeEventListener("keydown", this.handleKeydown);
3172
+ this.cancelShow();
3168
3173
  }
3169
3174
  show() {
3170
- this.popoverTarget.showPopover();
3175
+ if (this.delayValue > 0) {
3176
+ this.showTimer = setTimeout(() => this.popoverTarget.showPopover(), this.delayValue);
3177
+ } else {
3178
+ this.popoverTarget.showPopover();
3179
+ }
3171
3180
  }
3172
3181
  hide() {
3182
+ this.cancelShow();
3173
3183
  try {
3174
3184
  this.popoverTarget.hidePopover();
3175
3185
  } catch {
3176
3186
  }
3177
3187
  }
3188
+ cancelShow() {
3189
+ if (this.showTimer !== null) {
3190
+ clearTimeout(this.showTimer);
3191
+ this.showTimer = null;
3192
+ }
3193
+ }
3178
3194
  handleKeydown = (event) => {
3179
3195
  if (event.key !== "Escape")
3180
3196
  return;
@@ -3194,18 +3210,22 @@ const NON_SUBMITTING_INPUT_TYPES = /* @__PURE__ */ new Set([
3194
3210
  "reset",
3195
3211
  "submit"
3196
3212
  ]);
3213
+ const FORM_ELEMENT_TAGS = /* @__PURE__ */ new Set(["INPUT", "TEXTAREA", "SELECT"]);
3197
3214
  class Carousel extends Controller {
3198
3215
  static targets = ["track", "prev", "next", "dot"];
3199
3216
  static values = {
3200
- wizard: { type: Boolean, default: false }
3217
+ wizard: { type: Boolean, default: false },
3218
+ autoplay: { type: Number, default: 0 }
3201
3219
  };
3202
3220
  observer = null;
3203
3221
  _currentIndex = 0;
3204
3222
  _maxUnlocked = 0;
3205
3223
  _lastTouchX = 0;
3224
+ _autoplayTimer = null;
3206
3225
  connect() {
3207
3226
  this.setupObserver();
3208
3227
  this.updateNavigation();
3228
+ this.element.addEventListener("keydown", this.handleArrowKeys);
3209
3229
  if (this.wizardValue) {
3210
3230
  this.element.addEventListener("keydown", this.handleKeydown);
3211
3231
  this.trackTarget.addEventListener("wheel", this.handleWheel, { passive: false });
@@ -3213,13 +3233,22 @@ class Carousel extends Controller {
3213
3233
  this.trackTarget.addEventListener("touchmove", this.handleTouchMove, { passive: false });
3214
3234
  this.updateSlideAccessibility();
3215
3235
  }
3236
+ if (this.autoplayValue > 0) {
3237
+ this.startAutoplay();
3238
+ this.element.addEventListener("mouseenter", this.pauseAutoplay);
3239
+ this.element.addEventListener("mouseleave", this.resumeAutoplay);
3240
+ }
3216
3241
  }
3217
3242
  disconnect() {
3218
3243
  this.observer?.disconnect();
3244
+ this.element.removeEventListener("keydown", this.handleArrowKeys);
3219
3245
  this.element.removeEventListener("keydown", this.handleKeydown);
3246
+ this.element.removeEventListener("mouseenter", this.pauseAutoplay);
3247
+ this.element.removeEventListener("mouseleave", this.resumeAutoplay);
3220
3248
  this.trackTarget.removeEventListener("wheel", this.handleWheel);
3221
3249
  this.trackTarget.removeEventListener("touchstart", this.handleTouchStart);
3222
3250
  this.trackTarget.removeEventListener("touchmove", this.handleTouchMove);
3251
+ this.stopAutoplay();
3223
3252
  }
3224
3253
  next() {
3225
3254
  this.trackTarget.scrollBy({ left: this.trackTarget.clientWidth, behavior: "smooth" });
@@ -3255,6 +3284,22 @@ class Carousel extends Controller {
3255
3284
  this.updateNavigation();
3256
3285
  }
3257
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.
3258
3303
  handleKeydown = (event) => {
3259
3304
  if (event.key !== "Enter")
3260
3305
  return;
@@ -3289,6 +3334,34 @@ class Carousel extends Controller {
3289
3334
  event.preventDefault();
3290
3335
  }
3291
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
+ }
3292
3365
  get slides() {
3293
3366
  return Array.from(this.trackTarget.children);
3294
3367
  }
@@ -3543,6 +3616,46 @@ class CountdownTimer extends Controller {
3543
3616
  }
3544
3617
  }
3545
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
+
3546
3659
  function registerMidwestControllers(application) {
3547
3660
  application.register("midwest-card", Card);
3548
3661
  application.register("midwest-banner", Banner);
@@ -3557,6 +3670,9 @@ function registerMidwestControllers(application) {
3557
3670
  application.register("midwest-carousel", Carousel);
3558
3671
  application.register("midwest-form-live-summary", FormLiveSummary);
3559
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);
3560
3676
  }
3561
3677
 
3562
3678
  export { Banner, Card, CountdownTimer, registerMidwestControllers };