@unabridged/midwest 0.16.1 → 0.17.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.
@@ -3111,16 +3111,23 @@ class Dialog extends Controller {
3111
3111
  }
3112
3112
 
3113
3113
  class Tabs extends Controller {
3114
- static targets = ["tab", "panel"];
3114
+ static targets = ["tab", "panel", "list"];
3115
3115
  connect() {
3116
3116
  const activeIndex = this.tabTargets.findIndex(
3117
3117
  (tab) => tab.getAttribute("aria-selected") === "true"
3118
3118
  );
3119
3119
  this.activateTab(activeIndex >= 0 ? activeIndex : 0);
3120
3120
  this.element.addEventListener("keydown", this.handleKeydown);
3121
+ if (this.hasListTarget) {
3122
+ this.updateOverflow();
3123
+ this.listTarget.addEventListener("scroll", this.updateOverflow);
3124
+ }
3121
3125
  }
3122
3126
  disconnect() {
3123
3127
  this.element.removeEventListener("keydown", this.handleKeydown);
3128
+ if (this.hasListTarget) {
3129
+ this.listTarget.removeEventListener("scroll", this.updateOverflow);
3130
+ }
3124
3131
  }
3125
3132
  select(event) {
3126
3133
  const tab = event.currentTarget;
@@ -3128,6 +3135,13 @@ class Tabs extends Controller {
3128
3135
  if (index >= 0)
3129
3136
  this.activateTab(index);
3130
3137
  }
3138
+ updateOverflow = () => {
3139
+ if (!this.hasListTarget)
3140
+ return;
3141
+ const list = this.listTarget;
3142
+ list.classList.toggle("can-scroll-left", list.scrollLeft > 0);
3143
+ list.classList.toggle("can-scroll-right", list.scrollLeft < list.scrollWidth - list.clientWidth - 1);
3144
+ };
3131
3145
  handleKeydown = (event) => {
3132
3146
  const tabs = this.tabTargets;
3133
3147
  if (tabs.length === 0)
@@ -3230,7 +3244,8 @@ class Carousel extends Controller {
3230
3244
  static targets = ["track", "prev", "next", "dot"];
3231
3245
  static values = {
3232
3246
  wizard: { type: Boolean, default: false },
3233
- autoplay: { type: Number, default: 0 }
3247
+ autoplay: { type: Number, default: 0 },
3248
+ loop: { type: Boolean, default: false }
3234
3249
  };
3235
3250
  observer = null;
3236
3251
  _currentIndex = 0;
@@ -3266,10 +3281,21 @@ class Carousel extends Controller {
3266
3281
  this.stopAutoplay();
3267
3282
  }
3268
3283
  next() {
3269
- this.trackTarget.scrollBy({ left: this.trackTarget.clientWidth, behavior: "smooth" });
3284
+ const atEnd = this._currentIndex >= this.slides.length - 1;
3285
+ if (this.loopValue && atEnd) {
3286
+ this.slides[0]?.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" });
3287
+ } else {
3288
+ this.trackTarget.scrollBy({ left: this.trackTarget.clientWidth, behavior: "smooth" });
3289
+ }
3270
3290
  }
3271
3291
  previous() {
3272
- this.trackTarget.scrollBy({ left: -this.trackTarget.clientWidth, behavior: "smooth" });
3292
+ const atStart = this._currentIndex <= 0;
3293
+ if (this.loopValue && atStart) {
3294
+ const last = this.slides[this.slides.length - 1];
3295
+ last?.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" });
3296
+ } else {
3297
+ this.trackTarget.scrollBy({ left: -this.trackTarget.clientWidth, behavior: "smooth" });
3298
+ }
3273
3299
  }
3274
3300
  goto(event) {
3275
3301
  const button = event.currentTarget;
@@ -3436,11 +3462,11 @@ class Carousel extends Controller {
3436
3462
  const atStart = track.scrollLeft <= 0;
3437
3463
  const atEnd = track.scrollLeft >= track.scrollWidth - track.clientWidth - 1;
3438
3464
  if (this.hasPrevTarget)
3439
- this.prevTarget.classList.toggle("hide", atStart);
3465
+ this.prevTarget.classList.toggle("hide", atStart && !this.loopValue);
3440
3466
  if (this.hasNextTarget) {
3441
3467
  const atLastSlide = this._currentIndex >= this.slides.length - 1;
3442
3468
  const frontierReached = this.wizardValue && this._currentIndex >= this._maxUnlocked;
3443
- this.nextTarget.classList.toggle("hide", atEnd || atLastSlide || frontierReached);
3469
+ this.nextTarget.classList.toggle("hide", (atEnd || atLastSlide || frontierReached) && !this.loopValue);
3444
3470
  }
3445
3471
  if (this.wizardValue && this.hasDotTarget) {
3446
3472
  this.dotTargets.forEach((dot, i) => {
@@ -4177,6 +4203,536 @@ class Autocomplete extends Controller {
4177
4203
  }
4178
4204
  }
4179
4205
 
4206
+ /*
4207
+ * Color Thief v2.0
4208
+ * by Lokesh Dhakar - http://www.lokeshdhakar.com
4209
+ *
4210
+ * Thanks
4211
+ * ------
4212
+ * Nick Rabinowitz - For creating quantize.js.
4213
+ * John Schulz - For clean up and optimization. @JFSIII
4214
+ * Nathan Spady - For adding drag and drop support to the demo page.
4215
+ *
4216
+ * License
4217
+ * -------
4218
+ * Copyright 2011, 2015 Lokesh Dhakar
4219
+ * Released under the MIT license
4220
+ * https://raw.githubusercontent.com/lokesh/color-thief/master/LICENSE
4221
+ *
4222
+ * @license
4223
+ */
4224
+ const CanvasImage = function(image) {
4225
+ this.canvas = document.createElement("canvas");
4226
+ this.context = this.canvas.getContext("2d");
4227
+ document.body.appendChild(this.canvas);
4228
+ this.width = this.canvas.width = image.width;
4229
+ this.height = this.canvas.height = image.height;
4230
+ this.context.drawImage(image, 0, 0, this.width, this.height);
4231
+ };
4232
+ CanvasImage.prototype.clear = function() {
4233
+ this.context.clearRect(0, 0, this.width, this.height);
4234
+ };
4235
+ CanvasImage.prototype.update = function(imageData) {
4236
+ this.context.putImageData(imageData, 0, 0);
4237
+ };
4238
+ CanvasImage.prototype.getPixelCount = function() {
4239
+ return this.width * this.height;
4240
+ };
4241
+ CanvasImage.prototype.getImageData = function() {
4242
+ return this.context.getImageData(0, 0, this.width, this.height);
4243
+ };
4244
+ CanvasImage.prototype.removeCanvas = function() {
4245
+ this.canvas.parentNode.removeChild(this.canvas);
4246
+ };
4247
+ const ColorThief = function() {
4248
+ };
4249
+ ColorThief.prototype.getColor = function(sourceImage2, quality) {
4250
+ const palette = this.getPalette(sourceImage2, 5, quality);
4251
+ const dominantColor = palette[0];
4252
+ return dominantColor;
4253
+ };
4254
+ ColorThief.prototype.getPalette = function(sourceImage2, colorCount, quality) {
4255
+ if (typeof colorCount === "undefined" || colorCount < 2 || colorCount > 256) {
4256
+ colorCount = 10;
4257
+ }
4258
+ if (typeof quality === "undefined" || quality < 1) {
4259
+ quality = 10;
4260
+ }
4261
+ const image = new CanvasImage(sourceImage2);
4262
+ const imageData = image.getImageData();
4263
+ const pixels = imageData.data;
4264
+ const pixelCount = image.getPixelCount();
4265
+ const pixelArray = [];
4266
+ for (var i = 0, offset, r, g, b, a; i < pixelCount; i = i + quality) {
4267
+ offset = i * 4;
4268
+ r = pixels[offset + 0];
4269
+ g = pixels[offset + 1];
4270
+ b = pixels[offset + 2];
4271
+ a = pixels[offset + 3];
4272
+ if (a >= 125) {
4273
+ if (!(r > 250 && g > 250 && b > 250)) {
4274
+ pixelArray.push([r, g, b]);
4275
+ }
4276
+ }
4277
+ }
4278
+ const cmap = MMCQ.quantize(pixelArray, colorCount);
4279
+ const palette = cmap ? cmap.palette() : null;
4280
+ image.removeCanvas();
4281
+ return palette;
4282
+ };
4283
+ ColorThief.prototype.getColorFromUrl = function(imageUrl, callback, quality) {
4284
+ sourceImage = document.createElement("img");
4285
+ const thief = this;
4286
+ sourceImage.addEventListener("load", function() {
4287
+ const palette = thief.getPalette(sourceImage, 5, quality);
4288
+ const dominantColor = palette[0];
4289
+ callback(dominantColor, imageUrl);
4290
+ });
4291
+ sourceImage.src = imageUrl;
4292
+ };
4293
+ ColorThief.prototype.getImageData = function(imageUrl, callback) {
4294
+ xhr = new XMLHttpRequest();
4295
+ xhr.open("GET", imageUrl, true);
4296
+ xhr.responseType = "arraybuffer";
4297
+ xhr.onload = function(e) {
4298
+ if (this.status == 200) {
4299
+ uInt8Array = new Uint8Array(this.response);
4300
+ i = uInt8Array.length;
4301
+ binaryString = new Array(i);
4302
+ for (var i = 0; i < uInt8Array.length; i++) {
4303
+ binaryString[i] = String.fromCharCode(uInt8Array[i]);
4304
+ }
4305
+ data = binaryString.join("");
4306
+ base64 = window.btoa(data);
4307
+ callback("data:image/png;base64," + base64);
4308
+ }
4309
+ };
4310
+ xhr.send();
4311
+ };
4312
+ ColorThief.prototype.getColorAsync = function(imageUrl, callback, quality) {
4313
+ const thief = this;
4314
+ this.getImageData(imageUrl, function(imageData) {
4315
+ sourceImage = document.createElement("img");
4316
+ sourceImage.addEventListener("load", function() {
4317
+ const palette = thief.getPalette(sourceImage, 5, quality);
4318
+ const dominantColor = palette[0];
4319
+ callback(dominantColor, this);
4320
+ });
4321
+ sourceImage.src = imageData;
4322
+ });
4323
+ };
4324
+ /*!
4325
+ * quantize.js Copyright 2008 Nick Rabinowitz.
4326
+ * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
4327
+ * @license
4328
+ */
4329
+ /*!
4330
+ * Block below copied from Protovis: http://mbostock.github.com/protovis/
4331
+ * Copyright 2010 Stanford Visualization Group
4332
+ * Licensed under the BSD License: http://www.opensource.org/licenses/bsd-license.php
4333
+ * @license
4334
+ */
4335
+ if (!pv) {
4336
+ var pv = {
4337
+ map: function(array, f) {
4338
+ const o = {};
4339
+ return f ? array.map(function(d, i) {
4340
+ o.index = i;
4341
+ return f.call(o, d);
4342
+ }) : array.slice();
4343
+ },
4344
+ naturalOrder: function(a, b) {
4345
+ return a < b ? -1 : a > b ? 1 : 0;
4346
+ },
4347
+ sum: function(array, f) {
4348
+ const o = {};
4349
+ return array.reduce(f ? function(p, d, i) {
4350
+ o.index = i;
4351
+ return p + f.call(o, d);
4352
+ } : function(p, d) {
4353
+ return p + d;
4354
+ }, 0);
4355
+ },
4356
+ max: function(array, f) {
4357
+ return Math.max.apply(null, f ? pv.map(array, f) : array);
4358
+ }
4359
+ };
4360
+ }
4361
+ var MMCQ = function() {
4362
+ const sigbits = 5, rshift = 8 - sigbits, maxIterations = 1e3, fractByPopulations = 0.75;
4363
+ function getColorIndex(r, g, b) {
4364
+ return (r << 2 * sigbits) + (g << sigbits) + b;
4365
+ }
4366
+ function PQueue(comparator) {
4367
+ let contents = [], sorted = false;
4368
+ function sort() {
4369
+ contents.sort(comparator);
4370
+ sorted = true;
4371
+ }
4372
+ return {
4373
+ push: function(o) {
4374
+ contents.push(o);
4375
+ sorted = false;
4376
+ },
4377
+ peek: function(index) {
4378
+ if (!sorted)
4379
+ sort();
4380
+ if (index === void 0)
4381
+ index = contents.length - 1;
4382
+ return contents[index];
4383
+ },
4384
+ pop: function() {
4385
+ if (!sorted)
4386
+ sort();
4387
+ return contents.pop();
4388
+ },
4389
+ size: function() {
4390
+ return contents.length;
4391
+ },
4392
+ map: function(f) {
4393
+ return contents.map(f);
4394
+ },
4395
+ debug: function() {
4396
+ if (!sorted)
4397
+ sort();
4398
+ return contents;
4399
+ }
4400
+ };
4401
+ }
4402
+ function VBox(r1, r2, g1, g2, b1, b2, histo) {
4403
+ const vbox = this;
4404
+ vbox.r1 = r1;
4405
+ vbox.r2 = r2;
4406
+ vbox.g1 = g1;
4407
+ vbox.g2 = g2;
4408
+ vbox.b1 = b1;
4409
+ vbox.b2 = b2;
4410
+ vbox.histo = histo;
4411
+ }
4412
+ VBox.prototype = {
4413
+ volume: function(force) {
4414
+ const vbox = this;
4415
+ if (!vbox._volume || force) {
4416
+ vbox._volume = (vbox.r2 - vbox.r1 + 1) * (vbox.g2 - vbox.g1 + 1) * (vbox.b2 - vbox.b1 + 1);
4417
+ }
4418
+ return vbox._volume;
4419
+ },
4420
+ count: function(force) {
4421
+ const vbox = this, histo = vbox.histo;
4422
+ if (!vbox._count_set || force) {
4423
+ let npix = 0, index, i, j, k;
4424
+ for (i = vbox.r1; i <= vbox.r2; i++) {
4425
+ for (j = vbox.g1; j <= vbox.g2; j++) {
4426
+ for (k = vbox.b1; k <= vbox.b2; k++) {
4427
+ index = getColorIndex(i, j, k);
4428
+ npix += histo[index] || 0;
4429
+ }
4430
+ }
4431
+ }
4432
+ vbox._count = npix;
4433
+ vbox._count_set = true;
4434
+ }
4435
+ return vbox._count;
4436
+ },
4437
+ copy: function() {
4438
+ const vbox = this;
4439
+ return new VBox(vbox.r1, vbox.r2, vbox.g1, vbox.g2, vbox.b1, vbox.b2, vbox.histo);
4440
+ },
4441
+ avg: function(force) {
4442
+ const vbox = this, histo = vbox.histo;
4443
+ if (!vbox._avg || force) {
4444
+ let ntot = 0, mult = 1 << 8 - sigbits, rsum = 0, gsum = 0, bsum = 0, hval, i, j, k, histoindex;
4445
+ for (i = vbox.r1; i <= vbox.r2; i++) {
4446
+ for (j = vbox.g1; j <= vbox.g2; j++) {
4447
+ for (k = vbox.b1; k <= vbox.b2; k++) {
4448
+ histoindex = getColorIndex(i, j, k);
4449
+ hval = histo[histoindex] || 0;
4450
+ ntot += hval;
4451
+ rsum += hval * (i + 0.5) * mult;
4452
+ gsum += hval * (j + 0.5) * mult;
4453
+ bsum += hval * (k + 0.5) * mult;
4454
+ }
4455
+ }
4456
+ }
4457
+ if (ntot) {
4458
+ vbox._avg = [~~(rsum / ntot), ~~(gsum / ntot), ~~(bsum / ntot)];
4459
+ } else {
4460
+ vbox._avg = [
4461
+ ~~(mult * (vbox.r1 + vbox.r2 + 1) / 2),
4462
+ ~~(mult * (vbox.g1 + vbox.g2 + 1) / 2),
4463
+ ~~(mult * (vbox.b1 + vbox.b2 + 1) / 2)
4464
+ ];
4465
+ }
4466
+ }
4467
+ return vbox._avg;
4468
+ },
4469
+ contains: function(pixel) {
4470
+ const vbox = this, rval = pixel[0] >> rshift;
4471
+ gval = pixel[1] >> rshift;
4472
+ bval = pixel[2] >> rshift;
4473
+ return rval >= vbox.r1 && rval <= vbox.r2 && gval >= vbox.g1 && gval <= vbox.g2 && bval >= vbox.b1 && bval <= vbox.b2;
4474
+ }
4475
+ };
4476
+ function CMap() {
4477
+ this.vboxes = new PQueue(function(a, b) {
4478
+ return pv.naturalOrder(
4479
+ a.vbox.count() * a.vbox.volume(),
4480
+ b.vbox.count() * b.vbox.volume()
4481
+ );
4482
+ });
4483
+ }
4484
+ CMap.prototype = {
4485
+ push: function(vbox) {
4486
+ this.vboxes.push({
4487
+ vbox,
4488
+ color: vbox.avg()
4489
+ });
4490
+ },
4491
+ palette: function() {
4492
+ return this.vboxes.map(function(vb) {
4493
+ return vb.color;
4494
+ });
4495
+ },
4496
+ size: function() {
4497
+ return this.vboxes.size();
4498
+ },
4499
+ map: function(color) {
4500
+ const vboxes = this.vboxes;
4501
+ for (let i = 0; i < vboxes.size(); i++) {
4502
+ if (vboxes.peek(i).vbox.contains(color)) {
4503
+ return vboxes.peek(i).color;
4504
+ }
4505
+ }
4506
+ return this.nearest(color);
4507
+ },
4508
+ nearest: function(color) {
4509
+ let vboxes = this.vboxes, d1, d2, pColor;
4510
+ for (let i = 0; i < vboxes.size(); i++) {
4511
+ d2 = Math.sqrt(
4512
+ Math.pow(color[0] - vboxes.peek(i).color[0], 2) + Math.pow(color[1] - vboxes.peek(i).color[1], 2) + Math.pow(color[2] - vboxes.peek(i).color[2], 2)
4513
+ );
4514
+ if (d2 < d1 || d1 === void 0) {
4515
+ d1 = d2;
4516
+ pColor = vboxes.peek(i).color;
4517
+ }
4518
+ }
4519
+ return pColor;
4520
+ },
4521
+ forcebw: function() {
4522
+ const vboxes = this.vboxes;
4523
+ vboxes.sort(function(a, b) {
4524
+ return pv.naturalOrder(pv.sum(a.color), pv.sum(b.color));
4525
+ });
4526
+ const lowest = vboxes[0].color;
4527
+ if (lowest[0] < 5 && lowest[1] < 5 && lowest[2] < 5)
4528
+ vboxes[0].color = [0, 0, 0];
4529
+ const idx = vboxes.length - 1, highest = vboxes[idx].color;
4530
+ if (highest[0] > 251 && highest[1] > 251 && highest[2] > 251)
4531
+ vboxes[idx].color = [255, 255, 255];
4532
+ }
4533
+ };
4534
+ function getHisto(pixels) {
4535
+ let histosize = 1 << 3 * sigbits, histo = new Array(histosize), index, rval, gval2, bval2;
4536
+ pixels.forEach(function(pixel) {
4537
+ rval = pixel[0] >> rshift;
4538
+ gval2 = pixel[1] >> rshift;
4539
+ bval2 = pixel[2] >> rshift;
4540
+ index = getColorIndex(rval, gval2, bval2);
4541
+ histo[index] = (histo[index] || 0) + 1;
4542
+ });
4543
+ return histo;
4544
+ }
4545
+ function vboxFromPixels(pixels, histo) {
4546
+ let rmin = 1e6, rmax = 0, gmin = 1e6, gmax = 0, bmin = 1e6, bmax = 0, rval, gval2, bval2;
4547
+ pixels.forEach(function(pixel) {
4548
+ rval = pixel[0] >> rshift;
4549
+ gval2 = pixel[1] >> rshift;
4550
+ bval2 = pixel[2] >> rshift;
4551
+ if (rval < rmin)
4552
+ rmin = rval;
4553
+ else if (rval > rmax)
4554
+ rmax = rval;
4555
+ if (gval2 < gmin)
4556
+ gmin = gval2;
4557
+ else if (gval2 > gmax)
4558
+ gmax = gval2;
4559
+ if (bval2 < bmin)
4560
+ bmin = bval2;
4561
+ else if (bval2 > bmax)
4562
+ bmax = bval2;
4563
+ });
4564
+ return new VBox(rmin, rmax, gmin, gmax, bmin, bmax, histo);
4565
+ }
4566
+ function medianCutApply(histo, vbox) {
4567
+ if (!vbox.count())
4568
+ return;
4569
+ const rw = vbox.r2 - vbox.r1 + 1, gw = vbox.g2 - vbox.g1 + 1, bw = vbox.b2 - vbox.b1 + 1, maxw = pv.max([rw, gw, bw]);
4570
+ if (vbox.count() == 1) {
4571
+ return [vbox.copy()];
4572
+ }
4573
+ let total = 0, partialsum = [], lookaheadsum = [], i, j, k, sum, index;
4574
+ if (maxw == rw) {
4575
+ for (i = vbox.r1; i <= vbox.r2; i++) {
4576
+ sum = 0;
4577
+ for (j = vbox.g1; j <= vbox.g2; j++) {
4578
+ for (k = vbox.b1; k <= vbox.b2; k++) {
4579
+ index = getColorIndex(i, j, k);
4580
+ sum += histo[index] || 0;
4581
+ }
4582
+ }
4583
+ total += sum;
4584
+ partialsum[i] = total;
4585
+ }
4586
+ } else if (maxw == gw) {
4587
+ for (i = vbox.g1; i <= vbox.g2; i++) {
4588
+ sum = 0;
4589
+ for (j = vbox.r1; j <= vbox.r2; j++) {
4590
+ for (k = vbox.b1; k <= vbox.b2; k++) {
4591
+ index = getColorIndex(j, i, k);
4592
+ sum += histo[index] || 0;
4593
+ }
4594
+ }
4595
+ total += sum;
4596
+ partialsum[i] = total;
4597
+ }
4598
+ } else {
4599
+ for (i = vbox.b1; i <= vbox.b2; i++) {
4600
+ sum = 0;
4601
+ for (j = vbox.r1; j <= vbox.r2; j++) {
4602
+ for (k = vbox.g1; k <= vbox.g2; k++) {
4603
+ index = getColorIndex(j, k, i);
4604
+ sum += histo[index] || 0;
4605
+ }
4606
+ }
4607
+ total += sum;
4608
+ partialsum[i] = total;
4609
+ }
4610
+ }
4611
+ partialsum.forEach(function(d, i2) {
4612
+ lookaheadsum[i2] = total - d;
4613
+ });
4614
+ function doCut(color) {
4615
+ let dim1 = color + "1", dim2 = color + "2", left, right, vbox1, vbox2, d2, count2 = 0;
4616
+ for (i = vbox[dim1]; i <= vbox[dim2]; i++) {
4617
+ if (partialsum[i] > total / 2) {
4618
+ vbox1 = vbox.copy();
4619
+ vbox2 = vbox.copy();
4620
+ left = i - vbox[dim1];
4621
+ right = vbox[dim2] - i;
4622
+ if (left <= right)
4623
+ d2 = Math.min(vbox[dim2] - 1, ~~(i + right / 2));
4624
+ else
4625
+ d2 = Math.max(vbox[dim1], ~~(i - 1 - left / 2));
4626
+ while (!partialsum[d2])
4627
+ d2++;
4628
+ count2 = lookaheadsum[d2];
4629
+ while (!count2 && partialsum[d2 - 1])
4630
+ count2 = lookaheadsum[--d2];
4631
+ vbox1[dim2] = d2;
4632
+ vbox2[dim1] = vbox1[dim2] + 1;
4633
+ return [vbox1, vbox2];
4634
+ }
4635
+ }
4636
+ }
4637
+ return maxw == rw ? doCut("r") : maxw == gw ? doCut("g") : doCut("b");
4638
+ }
4639
+ function quantize(pixels, maxcolors) {
4640
+ if (!pixels.length || maxcolors < 2 || maxcolors > 256) {
4641
+ return false;
4642
+ }
4643
+ const histo = getHisto(pixels);
4644
+ histo.forEach(function() {
4645
+ });
4646
+ const vbox = vboxFromPixels(pixels, histo), pq = new PQueue(function(a, b) {
4647
+ return pv.naturalOrder(a.count(), b.count());
4648
+ });
4649
+ pq.push(vbox);
4650
+ function iter(lh, target) {
4651
+ let ncolors = 1, niters = 0, vbox2;
4652
+ while (niters < maxIterations) {
4653
+ vbox2 = lh.pop();
4654
+ if (!vbox2.count()) {
4655
+ lh.push(vbox2);
4656
+ niters++;
4657
+ continue;
4658
+ }
4659
+ const vboxes = medianCutApply(histo, vbox2), vbox1 = vboxes[0], vbox22 = vboxes[1];
4660
+ if (!vbox1) {
4661
+ return;
4662
+ }
4663
+ lh.push(vbox1);
4664
+ if (vbox22) {
4665
+ lh.push(vbox22);
4666
+ ncolors++;
4667
+ }
4668
+ if (ncolors >= target)
4669
+ return;
4670
+ if (niters++ > maxIterations) {
4671
+ return;
4672
+ }
4673
+ }
4674
+ }
4675
+ iter(pq, fractByPopulations * maxcolors);
4676
+ const pq2 = new PQueue(function(a, b) {
4677
+ return pv.naturalOrder(a.count() * a.volume(), b.count() * b.volume());
4678
+ });
4679
+ while (pq.size()) {
4680
+ pq2.push(pq.pop());
4681
+ }
4682
+ iter(pq2, maxcolors - pq2.size());
4683
+ const cmap = new CMap();
4684
+ while (pq2.size()) {
4685
+ cmap.push(pq2.pop());
4686
+ }
4687
+ return cmap;
4688
+ }
4689
+ return {
4690
+ quantize
4691
+ };
4692
+ }();
4693
+
4694
+ class Image extends Controller {
4695
+ static targets = ["dialog"];
4696
+ static values = { poster: String };
4697
+ connect() {
4698
+ this.extractColor();
4699
+ }
4700
+ extractColor() {
4701
+ if (!this.hasDialogTarget)
4702
+ return;
4703
+ const mainImg = this.element.querySelector("img.midwest-image-main");
4704
+ const colorSource = this.posterValue || mainImg?.src;
4705
+ if (!colorSource)
4706
+ return;
4707
+ const sample = new window.Image(80, 80);
4708
+ sample.crossOrigin = "Anonymous";
4709
+ sample.addEventListener("load", () => {
4710
+ try {
4711
+ const [r, g, b] = new ColorThief().getColor(sample);
4712
+ this.dialogTarget.style.setProperty("--image-dominant-color", `${r} ${g} ${b}`);
4713
+ } catch {
4714
+ }
4715
+ });
4716
+ sample.src = colorSource;
4717
+ }
4718
+ zoom() {
4719
+ if (this.hasDialogTarget) {
4720
+ this.dialogTarget.showModal();
4721
+ }
4722
+ }
4723
+ close() {
4724
+ if (this.hasDialogTarget) {
4725
+ this.dialogTarget.close();
4726
+ }
4727
+ }
4728
+ // Close when clicking the backdrop (outside the dialog content).
4729
+ backdropClose(event) {
4730
+ if (event.target === this.dialogTarget) {
4731
+ this.dialogTarget.close();
4732
+ }
4733
+ }
4734
+ }
4735
+
4180
4736
  function registerMidwestControllers(application) {
4181
4737
  application.register("midwest-card", Card);
4182
4738
  application.register("midwest-banner", Banner);
@@ -4198,6 +4754,7 @@ function registerMidwestControllers(application) {
4198
4754
  application.register("midwest-range", Range);
4199
4755
  application.register("midwest-rating", Rating);
4200
4756
  application.register("midwest-autocomplete", Autocomplete);
4757
+ application.register("midwest-image", Image);
4201
4758
  }
4202
4759
 
4203
4760
  export { Banner, Card, Chart, CountdownTimer, registerMidwestControllers };