@unabridged/midwest 0.16.1 → 0.18.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 (34) hide show
  1. package/app/assets/javascript/midwest/index.ts +6 -0
  2. package/app/assets/javascript/midwest.js +970 -39
  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/carousel_component/carousel_component_controller.js +17 -5
  10. package/dist/javascript/collection/app/components/midwest/carousel_component/carousel_component_controller.js.map +1 -1
  11. package/dist/javascript/collection/app/components/midwest/color_picker_component/color_picker_component_controller.js +135 -0
  12. package/dist/javascript/collection/app/components/midwest/color_picker_component/color_picker_component_controller.js.map +1 -0
  13. package/dist/javascript/collection/app/components/midwest/countdown_timer_component/countdown_timer_component_controller.js +27 -6
  14. package/dist/javascript/collection/app/components/midwest/countdown_timer_component/countdown_timer_component_controller.js.map +1 -1
  15. package/dist/javascript/collection/app/components/midwest/form/autocomplete_component/autocomplete_component_controller.js +109 -21
  16. package/dist/javascript/collection/app/components/midwest/form/autocomplete_component/autocomplete_component_controller.js.map +1 -1
  17. package/dist/javascript/collection/app/components/midwest/form/color_picker_component/color_picker_component_controller.js +129 -0
  18. package/dist/javascript/collection/app/components/midwest/form/color_picker_component/color_picker_component_controller.js.map +1 -0
  19. package/dist/javascript/collection/app/components/midwest/form/input_component/input_component_controller.js +50 -1
  20. package/dist/javascript/collection/app/components/midwest/form/input_component/input_component_controller.js.map +1 -1
  21. package/dist/javascript/collection/app/components/midwest/form/live_summary_component/live_summary_component_controller.js +38 -5
  22. package/dist/javascript/collection/app/components/midwest/form/live_summary_component/live_summary_component_controller.js.map +1 -1
  23. package/dist/javascript/collection/app/components/midwest/image_component/color_thief.js +490 -0
  24. package/dist/javascript/collection/app/components/midwest/image_component/color_thief.js.map +1 -0
  25. package/dist/javascript/collection/app/components/midwest/image_component/image_component_controller.js +47 -0
  26. package/dist/javascript/collection/app/components/midwest/image_component/image_component_controller.js.map +1 -0
  27. package/dist/javascript/collection/app/components/midwest/notification_component/notification_component_controller.js +60 -0
  28. package/dist/javascript/collection/app/components/midwest/notification_component/notification_component_controller.js.map +1 -0
  29. package/dist/javascript/collection/app/components/midwest/tabs_component/tabs_component_controller.js +15 -1
  30. package/dist/javascript/collection/app/components/midwest/tabs_component/tabs_component_controller.js.map +1 -1
  31. package/dist/javascript/midwest.d.ts +5 -0
  32. package/dist/javascript/midwest.js +970 -39
  33. package/dist/javascript/midwest.js.map +1 -1
  34. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"input_component_controller.js","sources":["../../../../../../../../app/components/midwest/form/input_component/input_component_controller.ts"],"sourcesContent":["\nimport { Controller } from '@hotwired/stimulus'\n\nexport default class Input extends Controller<HTMLFormElement> {\n static targets = ['input', 'counter']\n\n declare readonly hasInputTarget: boolean\n declare readonly inputTarget: HTMLInputElement\n declare readonly inputTargets: HTMLInputElement[]\n declare readonly hasCounterTarget: boolean\n declare readonly counterTarget: HTMLElement\n\n private updateClearButton: (() => void) | null = null\n private updateCounter: (() => void) | null = null\n\n connect () {\n this.applyColor()\n this.applySearchClear()\n this.applyCounter()\n }\n\n disconnect () {\n if (this.updateClearButton) {\n this.inputTarget.removeEventListener('input', this.updateClearButton)\n this.updateClearButton = null\n }\n if (this.updateCounter) {\n this.inputTarget.removeEventListener('input', this.updateCounter)\n this.updateCounter = null\n }\n }\n\n applyColor () {\n if (this.inputTarget.type !== 'color') {\n return\n }\n\n this.inputTarget.addEventListener('input', () => {\n this.inputTarget.setAttribute('value', this.inputTarget.value)\n })\n }\n\n private applyCounter () {\n if (!this.hasCounterTarget) return\n\n this.counterTarget.textContent = String(this.inputTarget.value.length)\n\n this.updateCounter = () => {\n this.counterTarget.textContent = String(this.inputTarget.value.length)\n }\n\n this.inputTarget.addEventListener('input', this.updateCounter)\n }\n\n private applySearchClear () {\n if (this.inputTarget.type !== 'search') return\n // Browsers that natively render a cancel button (Chrome, Safari, Edge)\n // already handle clearing. Only inject for browsers that don't (Firefox).\n if (CSS.supports('selector(::-webkit-search-cancel-button)')) return\n\n const button = document.createElement('button')\n button.type = 'button'\n button.setAttribute('aria-label', 'Clear search')\n button.classList.add('midwest-input-search-clear')\n button.hidden = this.inputTarget.value.length === 0\n\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n svg.setAttribute('viewBox', '0 0 24 24')\n svg.setAttribute('fill', 'none')\n svg.setAttribute('stroke', 'currentColor')\n svg.setAttribute('stroke-width', '2')\n svg.setAttribute('aria-hidden', 'true')\n svg.setAttribute('width', '16')\n svg.setAttribute('height', '16')\n\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')\n path.setAttribute('stroke-linecap', 'round')\n path.setAttribute('stroke-linejoin', 'round')\n path.setAttribute('d', 'M6 18L18 6M6 6l12 12')\n svg.appendChild(path)\n button.appendChild(svg)\n\n const wrapper = document.createElement('div')\n wrapper.classList.add('midwest-input-search-wrapper')\n this.inputTarget.parentElement?.insertBefore(wrapper, this.inputTarget)\n wrapper.appendChild(this.inputTarget)\n wrapper.appendChild(button)\n\n this.updateClearButton = () => {\n button.hidden = this.inputTarget.value.length === 0\n }\n\n this.inputTarget.addEventListener('input', this.updateClearButton)\n\n button.addEventListener('click', () => {\n this.inputTarget.value = ''\n button.hidden = true\n this.inputTarget.dispatchEvent(new Event('input', { bubbles: true }))\n this.inputTarget.focus()\n })\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"input_component_controller.js","sources":["../../../../../../../../app/components/midwest/form/input_component/input_component_controller.ts"],"sourcesContent":["\nimport { Controller } from '@hotwired/stimulus'\n\nexport default class Input extends Controller<HTMLFormElement> {\n static targets = ['input', 'counter', 'capsLockWarning']\n\n declare readonly hasInputTarget: boolean\n declare readonly inputTarget: HTMLInputElement\n declare readonly inputTargets: HTMLInputElement[]\n declare readonly hasCounterTarget: boolean\n declare readonly counterTarget: HTMLElement\n declare readonly hasCapsLockWarningTarget: boolean\n declare readonly capsLockWarningTarget: HTMLElement\n\n private updateClearButton: (() => void) | null = null\n private updateCounter: (() => void) | null = null\n private updateCapsLock: ((e: KeyboardEvent | MouseEvent) => void) | null = null\n private hideCapsLock: (() => void) | null = null\n\n connect () {\n this.applyColor()\n this.applySearchClear()\n this.applyCounter()\n this.applyPassword()\n }\n\n disconnect () {\n if (this.updateClearButton) {\n this.inputTarget.removeEventListener('input', this.updateClearButton)\n this.updateClearButton = null\n }\n if (this.updateCounter) {\n this.inputTarget.removeEventListener('input', this.updateCounter)\n this.updateCounter = null\n }\n if (this.updateCapsLock) {\n this.inputTarget.removeEventListener('keydown', this.updateCapsLock)\n this.inputTarget.removeEventListener('keyup', this.updateCapsLock)\n this.inputTarget.removeEventListener('mousedown', this.updateCapsLock)\n this.updateCapsLock = null\n }\n if (this.hideCapsLock) {\n this.inputTarget.removeEventListener('blur', this.hideCapsLock)\n this.hideCapsLock = null\n }\n }\n\n increment () {\n const input = this.inputTarget\n const step = parseFloat(input.step) || 1\n const max = input.max !== '' ? parseFloat(input.max) : Infinity\n const newValue = (parseFloat(input.value) || 0) + step\n if (newValue <= max) {\n input.value = String(newValue)\n input.dispatchEvent(new Event('input', { bubbles: true }))\n input.dispatchEvent(new Event('change', { bubbles: true }))\n }\n }\n\n decrement () {\n const input = this.inputTarget\n const step = parseFloat(input.step) || 1\n const min = input.min !== '' ? parseFloat(input.min) : -Infinity\n const newValue = (parseFloat(input.value) || 0) - step\n if (newValue >= min) {\n input.value = String(newValue)\n input.dispatchEvent(new Event('input', { bubbles: true }))\n input.dispatchEvent(new Event('change', { bubbles: true }))\n }\n }\n\n applyColor () {\n if (this.inputTarget.type !== 'color') {\n return\n }\n\n this.inputTarget.addEventListener('input', () => {\n this.inputTarget.setAttribute('value', this.inputTarget.value)\n })\n }\n\n private applyCounter () {\n if (!this.hasCounterTarget) return\n\n this.counterTarget.textContent = String(this.inputTarget.value.length)\n\n this.updateCounter = () => {\n this.counterTarget.textContent = String(this.inputTarget.value.length)\n }\n\n this.inputTarget.addEventListener('input', this.updateCounter)\n }\n\n private applyPassword () {\n if (!this.hasCapsLockWarningTarget) return\n\n this.updateCapsLock = (e: KeyboardEvent | MouseEvent) => {\n this.capsLockWarningTarget.hidden = !e.getModifierState('CapsLock')\n }\n\n this.hideCapsLock = () => {\n this.capsLockWarningTarget.hidden = true\n }\n\n this.inputTarget.addEventListener('keydown', this.updateCapsLock)\n this.inputTarget.addEventListener('keyup', this.updateCapsLock)\n this.inputTarget.addEventListener('mousedown', this.updateCapsLock)\n this.inputTarget.addEventListener('blur', this.hideCapsLock)\n }\n\n private applySearchClear () {\n if (this.inputTarget.type !== 'search') return\n // Browsers that natively render a cancel button (Chrome, Safari, Edge)\n // already handle clearing. Only inject for browsers that don't (Firefox).\n if (CSS.supports('selector(::-webkit-search-cancel-button)')) return\n\n const button = document.createElement('button')\n button.type = 'button'\n button.setAttribute('aria-label', 'Clear search')\n button.classList.add('midwest-input-search-clear')\n button.hidden = this.inputTarget.value.length === 0\n\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n svg.setAttribute('viewBox', '0 0 24 24')\n svg.setAttribute('fill', 'none')\n svg.setAttribute('stroke', 'currentColor')\n svg.setAttribute('stroke-width', '2')\n svg.setAttribute('aria-hidden', 'true')\n svg.setAttribute('width', '16')\n svg.setAttribute('height', '16')\n\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')\n path.setAttribute('stroke-linecap', 'round')\n path.setAttribute('stroke-linejoin', 'round')\n path.setAttribute('d', 'M6 18L18 6M6 6l12 12')\n svg.appendChild(path)\n button.appendChild(svg)\n\n const wrapper = document.createElement('div')\n wrapper.classList.add('midwest-input-search-wrapper')\n this.inputTarget.parentElement?.insertBefore(wrapper, this.inputTarget)\n wrapper.appendChild(this.inputTarget)\n wrapper.appendChild(button)\n\n this.updateClearButton = () => {\n button.hidden = this.inputTarget.value.length === 0\n }\n\n this.inputTarget.addEventListener('input', this.updateClearButton)\n\n button.addEventListener('click', () => {\n this.inputTarget.value = ''\n button.hidden = true\n this.inputTarget.dispatchEvent(new Event('input', { bubbles: true }))\n this.inputTarget.focus()\n })\n }\n}\n"],"names":[],"mappings":"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"}
@@ -14,11 +14,13 @@ class FormLiveSummary extends Controller {
14
14
  this.form?.addEventListener("input", this.render);
15
15
  this.form?.addEventListener("change", this.render);
16
16
  this.form?.addEventListener("midwest-autocomplete:change", this.render);
17
+ this.form?.addEventListener("midwest-color-picker:update", this.render);
17
18
  }
18
19
  disconnect() {
19
20
  this.form?.removeEventListener("input", this.render);
20
21
  this.form?.removeEventListener("change", this.render);
21
22
  this.form?.removeEventListener("midwest-autocomplete:change", this.render);
23
+ this.form?.removeEventListener("midwest-color-picker:update", this.render);
22
24
  }
23
25
  get form() {
24
26
  return this.element.closest("form");
@@ -36,15 +38,18 @@ class FormLiveSummary extends Controller {
36
38
  }
37
39
  const dl = document.createElement("dl");
38
40
  dl.className = "midwest-form-live-summary-list";
39
- fields.forEach(({ label, value }) => {
41
+ fields.forEach(({ label, value, swatchColor }) => {
40
42
  const dt = Object.assign(document.createElement("dt"), {
41
43
  className: "midwest-form-live-summary-term",
42
44
  textContent: label
43
45
  });
44
- const dd = Object.assign(document.createElement("dd"), {
45
- className: "midwest-form-live-summary-definition",
46
- textContent: value || "\u2014"
47
- });
46
+ const dd = document.createElement("dd");
47
+ dd.className = "midwest-form-live-summary-definition";
48
+ if (swatchColor !== void 0) {
49
+ dd.append(this.buildSwatch(swatchColor), value || "\u2014");
50
+ } else {
51
+ dd.textContent = value || "\u2014";
52
+ }
48
53
  dl.append(dt, dd);
49
54
  });
50
55
  this.listTarget.replaceChildren(dl);
@@ -101,6 +106,18 @@ class FormLiveSummary extends Controller {
101
106
  value: element.value
102
107
  });
103
108
  });
109
+ form.querySelectorAll('[data-midwest-color-picker-target="input"]').forEach((input) => {
110
+ if (this.element.contains(input))
111
+ return;
112
+ if (!input.name)
113
+ return;
114
+ const picker = input.closest(".midwest-color-picker");
115
+ const labelEl = picker?.querySelector(".midwest-form-group__top label") ?? this.form?.querySelector(`label[for="${CSS.escape(input.id)}"]`);
116
+ const label = labelEl?.textContent?.trim() || this.prettifyName(input.name.replace(/\[.*\]$/, ""));
117
+ const value = input.value;
118
+ const display = value.startsWith("#") ? value : value ? value.charAt(0).toUpperCase() + value.slice(1) : "\u2014";
119
+ fields.push({ label, value: display, swatchColor: value || void 0 });
120
+ });
104
121
  form.querySelectorAll(".midwest-autocomplete").forEach((ac) => {
105
122
  if (this.element.contains(ac))
106
123
  return;
@@ -113,6 +130,22 @@ class FormLiveSummary extends Controller {
113
130
  });
114
131
  return fields;
115
132
  }
133
+ // Builds a small inline colour swatch to display alongside a colour value.
134
+ // Hex values are applied as an inline background-color; named theme colours
135
+ // use a scoped theme-{color} class so the CSS variable cascade does the work.
136
+ // An empty/transparent value renders a diagonal-stripe placeholder.
137
+ buildSwatch(color) {
138
+ const swatch = document.createElement("span");
139
+ swatch.className = "midwest-form-live-summary-swatch";
140
+ if (color.startsWith("#")) {
141
+ swatch.style.backgroundColor = color;
142
+ } else if (color && color !== "transparent") {
143
+ swatch.classList.add(`theme-${color}`, "bg-theme-6");
144
+ } else {
145
+ swatch.classList.add("is-transparent");
146
+ }
147
+ return swatch;
148
+ }
116
149
  // Finds the label associated with a specific element via `for` attribute,
117
150
  // wrapping label, or falls back to a prettified version of the element name.
118
151
  labelFor(el) {
@@ -1 +1 @@
1
- {"version":3,"file":"live_summary_component_controller.js","sources":["../../../../../../../../app/components/midwest/form/live_summary_component/live_summary_component_controller.ts"],"sourcesContent":["import { Controller } from '@hotwired/stimulus'\n\n// Input types that should never appear in a form live summary.\nconst SKIPPED_INPUT_TYPES = new Set([\n 'hidden', 'submit', 'reset', 'button', 'image'\n])\n\ninterface FieldSummary {\n label: string\n value: string\n}\n\nexport default class FormLiveSummary extends Controller<HTMLElement> {\n static targets = ['list']\n\n declare readonly listTarget: HTMLElement\n\n connect () {\n this.render()\n this.form?.addEventListener('input', this.render)\n this.form?.addEventListener('change', this.render)\n this.form?.addEventListener('midwest-autocomplete:change', this.render)\n }\n\n disconnect () {\n this.form?.removeEventListener('input', this.render)\n this.form?.removeEventListener('change', this.render)\n this.form?.removeEventListener('midwest-autocomplete:change', this.render)\n }\n\n private get form (): HTMLFormElement | null {\n return this.element.closest('form')\n }\n\n private render = () => {\n const fields = this.collectFields()\n\n if (fields.length === 0) {\n this.listTarget.replaceChildren(\n Object.assign(document.createElement('p'), {\n className: 'midwest-form-live-summary-empty',\n textContent: 'No values to display.'\n })\n )\n return\n }\n\n const dl = document.createElement('dl')\n dl.className = 'midwest-form-live-summary-list'\n\n fields.forEach(({ label, value }) => {\n const dt = Object.assign(document.createElement('dt'), {\n className: 'midwest-form-live-summary-term',\n textContent: label\n })\n const dd = Object.assign(document.createElement('dd'), {\n className: 'midwest-form-live-summary-definition',\n textContent: value || '—'\n })\n dl.append(dt, dd)\n })\n\n this.listTarget.replaceChildren(dl)\n }\n\n private collectFields (): FieldSummary[] {\n const form = this.form\n if (!form) return []\n\n const fields: FieldSummary[] = []\n const seenRadioNames = new Set<string>()\n\n Array.from(form.elements).forEach(el => {\n const element = el as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | HTMLButtonElement\n\n if (!element.name) return\n\n // Skip elements that live inside the summary itself.\n if (this.element.contains(element)) return\n\n // Skip all button elements regardless of how they are declared.\n if (element instanceof HTMLButtonElement) return\n\n if (element instanceof HTMLInputElement) {\n if (SKIPPED_INPUT_TYPES.has(element.type)) return\n\n if (element.type === 'radio') {\n if (seenRadioNames.has(element.name)) return\n seenRadioNames.add(element.name)\n\n const checked = form.querySelector<HTMLInputElement>(\n `input[type=\"radio\"][name=\"${CSS.escape(element.name)}\"]:checked`\n )\n if (!checked) return\n\n fields.push({\n label: this.groupLabelFor(element),\n value: this.labelFor(checked) || checked.value\n })\n return\n }\n\n if (element.type === 'checkbox') {\n fields.push({\n label: this.labelFor(element),\n value: element.checked ? 'Yes' : 'No'\n })\n return\n }\n }\n\n if (element instanceof HTMLSelectElement) {\n fields.push({\n label: this.labelFor(element),\n value: Array.from(element.selectedOptions).map(o => o.text).join(', ') || '—'\n })\n return\n }\n\n // Text-like inputs and textareas only reach this point.\n fields.push({\n label: this.labelFor(element),\n value: element.value\n })\n })\n\n // Autocomplete components use a nameless combobox input + hidden inputs —\n // neither surfaces through the standard form.elements loop. Query them\n // separately so their selected badge labels appear in the summary.\n // Note: labelFor(input) doesn't work here because InputComponent assigns\n // its own id to the <input>, which won't match the <label>'s for attribute.\n form.querySelectorAll<HTMLElement>('.midwest-autocomplete').forEach(ac => {\n if (this.element.contains(ac)) return\n if (!ac.querySelector('[role=\"combobox\"]')) return\n\n const labelEl = ac.querySelector<HTMLElement>('label')\n const label = labelEl?.textContent?.trim() ||\n this.prettifyName((ac.dataset.name ?? '').replace(/\\[.*\\]$/, ''))\n\n const selected = Array.from(ac.querySelectorAll<HTMLElement>('.midwest-autocomplete-tokens .value'))\n .map(el => el.textContent?.trim())\n .filter(Boolean)\n .join(', ')\n fields.push({ label, value: selected || '—' })\n })\n\n return fields\n }\n\n // Finds the label associated with a specific element via `for` attribute,\n // wrapping label, or falls back to a prettified version of the element name.\n private labelFor (el: Element): string {\n const id = (el as HTMLElement).id\n if (id) {\n const label = this.form?.querySelector(`label[for=\"${CSS.escape(id)}\"]`)\n if (label) return label.textContent?.trim() ?? ''\n }\n const wrapper = el.closest('label')\n if (wrapper) return wrapper.textContent?.trim() ?? ''\n return this.prettifyName((el as HTMLInputElement).name ?? '')\n }\n\n // For radio groups, prefer the containing fieldset legend over the\n // individual radio's label, then fall back to prettifying the name.\n private groupLabelFor (el: Element): string {\n const legend = el.closest('fieldset')?.querySelector('legend')\n if (legend) return legend.textContent?.trim() ?? ''\n return this.prettifyName((el as HTMLInputElement).name ?? '')\n }\n\n // Converts \"user[first_name]\" or \"first_name\" into \"First name\".\n private prettifyName (name: string): string {\n return name\n .replace(/\\[.*?\\]/g, '')\n .replace(/_/g, ' ')\n .replace(/^\\w/, c => c.toUpperCase())\n .trim()\n }\n}\n"],"names":[],"mappings":";;AAGA,MAAM,mBAAA,uBAA0B,GAAI,CAAA;AAAA,EAClC,QAAA;AAAA,EAAU,QAAA;AAAA,EAAU,OAAA;AAAA,EAAS,QAAA;AAAA,EAAU,OAAA;AACzC,CAAC,CAAA,CAAA;AAOD,MAAqB,wBAAwB,UAAwB,CAAA;AAAA,EACnE,OAAO,OAAU,GAAA,CAAC,MAAM,CAAA,CAAA;AAAA,EAIxB,OAAW,GAAA;AACT,IAAA,IAAA,CAAK,MAAO,EAAA,CAAA;AACZ,IAAA,IAAA,CAAK,IAAM,EAAA,gBAAA,CAAiB,OAAS,EAAA,IAAA,CAAK,MAAM,CAAA,CAAA;AAChD,IAAA,IAAA,CAAK,IAAM,EAAA,gBAAA,CAAiB,QAAU,EAAA,IAAA,CAAK,MAAM,CAAA,CAAA;AACjD,IAAA,IAAA,CAAK,IAAM,EAAA,gBAAA,CAAiB,6BAA+B,EAAA,IAAA,CAAK,MAAM,CAAA,CAAA;AAAA,GACxE;AAAA,EAEA,UAAc,GAAA;AACZ,IAAA,IAAA,CAAK,IAAM,EAAA,mBAAA,CAAoB,OAAS,EAAA,IAAA,CAAK,MAAM,CAAA,CAAA;AACnD,IAAA,IAAA,CAAK,IAAM,EAAA,mBAAA,CAAoB,QAAU,EAAA,IAAA,CAAK,MAAM,CAAA,CAAA;AACpD,IAAA,IAAA,CAAK,IAAM,EAAA,mBAAA,CAAoB,6BAA+B,EAAA,IAAA,CAAK,MAAM,CAAA,CAAA;AAAA,GAC3E;AAAA,EAEA,IAAY,IAAgC,GAAA;AAC1C,IAAO,OAAA,IAAA,CAAK,OAAQ,CAAA,OAAA,CAAQ,MAAM,CAAA,CAAA;AAAA,GACpC;AAAA,EAEQ,SAAS,MAAM;AACrB,IAAM,MAAA,MAAA,GAAS,KAAK,aAAc,EAAA,CAAA;AAElC,IAAI,IAAA,MAAA,CAAO,WAAW,CAAG,EAAA;AACvB,MAAA,IAAA,CAAK,UAAW,CAAA,eAAA;AAAA,QACd,MAAO,CAAA,MAAA,CAAO,QAAS,CAAA,aAAA,CAAc,GAAG,CAAG,EAAA;AAAA,UACzC,SAAW,EAAA,iCAAA;AAAA,UACX,WAAa,EAAA,uBAAA;AAAA,SACd,CAAA;AAAA,OACH,CAAA;AACA,MAAA,OAAA;AAAA,KACF;AAEA,IAAM,MAAA,EAAA,GAAK,QAAS,CAAA,aAAA,CAAc,IAAI,CAAA,CAAA;AACtC,IAAA,EAAA,CAAG,SAAY,GAAA,gCAAA,CAAA;AAEf,IAAA,MAAA,CAAO,OAAQ,CAAA,CAAC,EAAE,KAAA,EAAO,OAAY,KAAA;AACnC,MAAA,MAAM,KAAK,MAAO,CAAA,MAAA,CAAO,QAAS,CAAA,aAAA,CAAc,IAAI,CAAG,EAAA;AAAA,QACrD,SAAW,EAAA,gCAAA;AAAA,QACX,WAAa,EAAA,KAAA;AAAA,OACd,CAAA,CAAA;AACD,MAAA,MAAM,KAAK,MAAO,CAAA,MAAA,CAAO,QAAS,CAAA,aAAA,CAAc,IAAI,CAAG,EAAA;AAAA,QACrD,SAAW,EAAA,sCAAA;AAAA,QACX,aAAa,KAAS,IAAA,QAAA;AAAA,OACvB,CAAA,CAAA;AACD,MAAG,EAAA,CAAA,MAAA,CAAO,IAAI,EAAE,CAAA,CAAA;AAAA,KACjB,CAAA,CAAA;AAED,IAAK,IAAA,CAAA,UAAA,CAAW,gBAAgB,EAAE,CAAA,CAAA;AAAA,GACpC,CAAA;AAAA,EAEQ,aAAiC,GAAA;AACvC,IAAA,MAAM,OAAO,IAAK,CAAA,IAAA,CAAA;AAClB,IAAA,IAAI,CAAC,IAAA;AAAM,MAAA,OAAO,EAAC,CAAA;AAEnB,IAAA,MAAM,SAAyB,EAAC,CAAA;AAChC,IAAM,MAAA,cAAA,uBAAqB,GAAY,EAAA,CAAA;AAEvC,IAAA,KAAA,CAAM,IAAK,CAAA,IAAA,CAAK,QAAQ,CAAA,CAAE,QAAQ,CAAM,EAAA,KAAA;AACtC,MAAA,MAAM,OAAU,GAAA,EAAA,CAAA;AAEhB,MAAA,IAAI,CAAC,OAAQ,CAAA,IAAA;AAAM,QAAA,OAAA;AAGnB,MAAI,IAAA,IAAA,CAAK,OAAQ,CAAA,QAAA,CAAS,OAAO,CAAA;AAAG,QAAA,OAAA;AAGpC,MAAA,IAAI,OAAmB,YAAA,iBAAA;AAAmB,QAAA,OAAA;AAE1C,MAAA,IAAI,mBAAmB,gBAAkB,EAAA;AACvC,QAAI,IAAA,mBAAA,CAAoB,GAAI,CAAA,OAAA,CAAQ,IAAI,CAAA;AAAG,UAAA,OAAA;AAE3C,QAAI,IAAA,OAAA,CAAQ,SAAS,OAAS,EAAA;AAC5B,UAAI,IAAA,cAAA,CAAe,GAAI,CAAA,OAAA,CAAQ,IAAI,CAAA;AAAG,YAAA,OAAA;AACtC,UAAe,cAAA,CAAA,GAAA,CAAI,QAAQ,IAAI,CAAA,CAAA;AAE/B,UAAA,MAAM,UAAU,IAAK,CAAA,aAAA;AAAA,YACnB,CAA6B,0BAAA,EAAA,GAAA,CAAI,MAAO,CAAA,OAAA,CAAQ,IAAI,CAAA,CAAA,UAAA,CAAA;AAAA,WACtD,CAAA;AACA,UAAA,IAAI,CAAC,OAAA;AAAS,YAAA,OAAA;AAEd,UAAA,MAAA,CAAO,IAAK,CAAA;AAAA,YACV,KAAA,EAAO,IAAK,CAAA,aAAA,CAAc,OAAO,CAAA;AAAA,YACjC,KAAO,EAAA,IAAA,CAAK,QAAS,CAAA,OAAO,KAAK,OAAQ,CAAA,KAAA;AAAA,WAC1C,CAAA,CAAA;AACD,UAAA,OAAA;AAAA,SACF;AAEA,QAAI,IAAA,OAAA,CAAQ,SAAS,UAAY,EAAA;AAC/B,UAAA,MAAA,CAAO,IAAK,CAAA;AAAA,YACV,KAAA,EAAO,IAAK,CAAA,QAAA,CAAS,OAAO,CAAA;AAAA,YAC5B,KAAA,EAAO,OAAQ,CAAA,OAAA,GAAU,KAAQ,GAAA,IAAA;AAAA,WAClC,CAAA,CAAA;AACD,UAAA,OAAA;AAAA,SACF;AAAA,OACF;AAEA,MAAA,IAAI,mBAAmB,iBAAmB,EAAA;AACxC,QAAA,MAAA,CAAO,IAAK,CAAA;AAAA,UACV,KAAA,EAAO,IAAK,CAAA,QAAA,CAAS,OAAO,CAAA;AAAA,UAC5B,KAAO,EAAA,KAAA,CAAM,IAAK,CAAA,OAAA,CAAQ,eAAe,CAAA,CAAE,GAAI,CAAA,CAAA,CAAA,KAAK,CAAE,CAAA,IAAI,CAAE,CAAA,IAAA,CAAK,IAAI,CAAK,IAAA,QAAA;AAAA,SAC3E,CAAA,CAAA;AACD,QAAA,OAAA;AAAA,OACF;AAGA,MAAA,MAAA,CAAO,IAAK,CAAA;AAAA,QACV,KAAA,EAAO,IAAK,CAAA,QAAA,CAAS,OAAO,CAAA;AAAA,QAC5B,OAAO,OAAQ,CAAA,KAAA;AAAA,OAChB,CAAA,CAAA;AAAA,KACF,CAAA,CAAA;AAOD,IAAA,IAAA,CAAK,gBAA8B,CAAA,uBAAuB,CAAE,CAAA,OAAA,CAAQ,CAAM,EAAA,KAAA;AACxE,MAAI,IAAA,IAAA,CAAK,OAAQ,CAAA,QAAA,CAAS,EAAE,CAAA;AAAG,QAAA,OAAA;AAC/B,MAAI,IAAA,CAAC,EAAG,CAAA,aAAA,CAAc,mBAAmB,CAAA;AAAG,QAAA,OAAA;AAE5C,MAAM,MAAA,OAAA,GAAU,EAAG,CAAA,aAAA,CAA2B,OAAO,CAAA,CAAA;AACrD,MAAA,MAAM,KAAQ,GAAA,OAAA,EAAS,WAAa,EAAA,IAAA,MAClC,IAAK,CAAA,YAAA,CAAA,CAAc,EAAG,CAAA,OAAA,CAAQ,IAAQ,IAAA,EAAA,EAAI,OAAQ,CAAA,SAAA,EAAW,EAAE,CAAC,CAAA,CAAA;AAElE,MAAA,MAAM,WAAW,KAAM,CAAA,IAAA,CAAK,GAAG,gBAA8B,CAAA,qCAAqC,CAAC,CAChG,CAAA,GAAA,CAAI,QAAM,EAAG,CAAA,WAAA,EAAa,MAAM,CAAA,CAChC,OAAO,OAAO,CAAA,CACd,KAAK,IAAI,CAAA,CAAA;AACZ,MAAA,MAAA,CAAO,KAAK,EAAE,KAAA,EAAO,KAAO,EAAA,QAAA,IAAY,UAAK,CAAA,CAAA;AAAA,KAC9C,CAAA,CAAA;AAED,IAAO,OAAA,MAAA,CAAA;AAAA,GACT;AAAA;AAAA;AAAA,EAIQ,SAAU,EAAqB,EAAA;AACrC,IAAA,MAAM,KAAM,EAAmB,CAAA,EAAA,CAAA;AAC/B,IAAA,IAAI,EAAI,EAAA;AACN,MAAM,MAAA,KAAA,GAAQ,KAAK,IAAM,EAAA,aAAA,CAAc,cAAc,GAAI,CAAA,MAAA,CAAO,EAAE,CAAK,CAAA,EAAA,CAAA,CAAA,CAAA;AACvE,MAAI,IAAA,KAAA;AAAO,QAAO,OAAA,KAAA,CAAM,WAAa,EAAA,IAAA,EAAU,IAAA,EAAA,CAAA;AAAA,KACjD;AACA,IAAM,MAAA,OAAA,GAAU,EAAG,CAAA,OAAA,CAAQ,OAAO,CAAA,CAAA;AAClC,IAAI,IAAA,OAAA;AAAS,MAAO,OAAA,OAAA,CAAQ,WAAa,EAAA,IAAA,EAAU,IAAA,EAAA,CAAA;AACnD,IAAA,OAAO,IAAK,CAAA,YAAA,CAAc,EAAwB,CAAA,IAAA,IAAQ,EAAE,CAAA,CAAA;AAAA,GAC9D;AAAA;AAAA;AAAA,EAIQ,cAAe,EAAqB,EAAA;AAC1C,IAAA,MAAM,SAAS,EAAG,CAAA,OAAA,CAAQ,UAAU,CAAA,EAAG,cAAc,QAAQ,CAAA,CAAA;AAC7D,IAAI,IAAA,MAAA;AAAQ,MAAO,OAAA,MAAA,CAAO,WAAa,EAAA,IAAA,EAAU,IAAA,EAAA,CAAA;AACjD,IAAA,OAAO,IAAK,CAAA,YAAA,CAAc,EAAwB,CAAA,IAAA,IAAQ,EAAE,CAAA,CAAA;AAAA,GAC9D;AAAA;AAAA,EAGQ,aAAc,IAAsB,EAAA;AAC1C,IAAA,OAAO,KACJ,OAAQ,CAAA,UAAA,EAAY,EAAE,CAAA,CACtB,QAAQ,IAAM,EAAA,GAAG,CACjB,CAAA,OAAA,CAAQ,OAAO,CAAK,CAAA,KAAA,CAAA,CAAE,WAAY,EAAC,EACnC,IAAK,EAAA,CAAA;AAAA,GACV;AACF;;;;"}
1
+ {"version":3,"file":"live_summary_component_controller.js","sources":["../../../../../../../../app/components/midwest/form/live_summary_component/live_summary_component_controller.ts"],"sourcesContent":["import { Controller } from '@hotwired/stimulus'\n\n// Input types that should never appear in a form live summary.\nconst SKIPPED_INPUT_TYPES = new Set([\n 'hidden', 'submit', 'reset', 'button', 'image'\n])\n\ninterface FieldSummary {\n label: string\n value: string\n /** When set, a colour swatch is prepended to the value cell. */\n swatchColor?: string\n}\n\nexport default class FormLiveSummary extends Controller<HTMLElement> {\n static targets = ['list']\n\n declare readonly listTarget: HTMLElement\n\n connect () {\n this.render()\n this.form?.addEventListener('input', this.render)\n this.form?.addEventListener('change', this.render)\n this.form?.addEventListener('midwest-autocomplete:change', this.render)\n this.form?.addEventListener('midwest-color-picker:update', this.render)\n }\n\n disconnect () {\n this.form?.removeEventListener('input', this.render)\n this.form?.removeEventListener('change', this.render)\n this.form?.removeEventListener('midwest-autocomplete:change', this.render)\n this.form?.removeEventListener('midwest-color-picker:update', this.render)\n }\n\n private get form (): HTMLFormElement | null {\n return this.element.closest('form')\n }\n\n private render = () => {\n const fields = this.collectFields()\n\n if (fields.length === 0) {\n this.listTarget.replaceChildren(\n Object.assign(document.createElement('p'), {\n className: 'midwest-form-live-summary-empty',\n textContent: 'No values to display.'\n })\n )\n return\n }\n\n const dl = document.createElement('dl')\n dl.className = 'midwest-form-live-summary-list'\n\n fields.forEach(({ label, value, swatchColor }) => {\n const dt = Object.assign(document.createElement('dt'), {\n className: 'midwest-form-live-summary-term',\n textContent: label\n })\n const dd = document.createElement('dd')\n dd.className = 'midwest-form-live-summary-definition'\n\n if (swatchColor !== undefined) {\n dd.append(this.buildSwatch(swatchColor), value || '—')\n } else {\n dd.textContent = value || '—'\n }\n\n dl.append(dt, dd)\n })\n\n this.listTarget.replaceChildren(dl)\n }\n\n private collectFields (): FieldSummary[] {\n const form = this.form\n if (!form) return []\n\n const fields: FieldSummary[] = []\n const seenRadioNames = new Set<string>()\n\n Array.from(form.elements).forEach(el => {\n const element = el as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | HTMLButtonElement\n\n if (!element.name) return\n\n // Skip elements that live inside the summary itself.\n if (this.element.contains(element)) return\n\n // Skip all button elements regardless of how they are declared.\n if (element instanceof HTMLButtonElement) return\n\n if (element instanceof HTMLInputElement) {\n if (SKIPPED_INPUT_TYPES.has(element.type)) return\n\n if (element.type === 'radio') {\n if (seenRadioNames.has(element.name)) return\n seenRadioNames.add(element.name)\n\n const checked = form.querySelector<HTMLInputElement>(\n `input[type=\"radio\"][name=\"${CSS.escape(element.name)}\"]:checked`\n )\n if (!checked) return\n\n fields.push({\n label: this.groupLabelFor(element),\n value: this.labelFor(checked) || checked.value\n })\n return\n }\n\n if (element.type === 'checkbox') {\n fields.push({\n label: this.labelFor(element),\n value: element.checked ? 'Yes' : 'No'\n })\n return\n }\n }\n\n if (element instanceof HTMLSelectElement) {\n fields.push({\n label: this.labelFor(element),\n value: Array.from(element.selectedOptions).map(o => o.text).join(', ') || '—'\n })\n return\n }\n\n // Text-like inputs and textareas only reach this point.\n fields.push({\n label: this.labelFor(element),\n value: element.value\n })\n })\n\n // Color picker components store their value in a hidden input tagged with\n // data-midwest-color-picker-target=\"input\". The standard loop skips hidden\n // inputs, so query them separately and render with an inline colour swatch.\n form.querySelectorAll<HTMLInputElement>('[data-midwest-color-picker-target=\"input\"]').forEach(input => {\n if (this.element.contains(input)) return\n if (!input.name) return\n\n // Prefer the label inside the picker's own form-group header; fall back\n // to a label[for] match or a prettified version of the input name.\n const picker = input.closest<HTMLElement>('.midwest-color-picker')\n const labelEl = picker?.querySelector<HTMLElement>('.midwest-form-group__top label') ??\n this.form?.querySelector<HTMLElement>(`label[for=\"${CSS.escape(input.id)}\"]`)\n const label = labelEl?.textContent?.trim() ||\n this.prettifyName(input.name.replace(/\\[.*\\]$/, ''))\n\n const value = input.value\n const display = value.startsWith('#') ? value : (value ? value.charAt(0).toUpperCase() + value.slice(1) : '—')\n\n fields.push({ label, value: display, swatchColor: value || undefined })\n })\n\n // Autocomplete components use a nameless combobox input + hidden inputs —\n // neither surfaces through the standard form.elements loop. Query them\n // separately so their selected badge labels appear in the summary.\n // Note: labelFor(input) doesn't work here because InputComponent assigns\n // its own id to the <input>, which won't match the <label>'s for attribute.\n form.querySelectorAll<HTMLElement>('.midwest-autocomplete').forEach(ac => {\n if (this.element.contains(ac)) return\n if (!ac.querySelector('[role=\"combobox\"]')) return\n\n const labelEl = ac.querySelector<HTMLElement>('label')\n const label = labelEl?.textContent?.trim() ||\n this.prettifyName((ac.dataset.name ?? '').replace(/\\[.*\\]$/, ''))\n\n const selected = Array.from(ac.querySelectorAll<HTMLElement>('.midwest-autocomplete-tokens .value'))\n .map(el => el.textContent?.trim())\n .filter(Boolean)\n .join(', ')\n fields.push({ label, value: selected || '—' })\n })\n\n return fields\n }\n\n // Builds a small inline colour swatch to display alongside a colour value.\n // Hex values are applied as an inline background-color; named theme colours\n // use a scoped theme-{color} class so the CSS variable cascade does the work.\n // An empty/transparent value renders a diagonal-stripe placeholder.\n private buildSwatch (color: string): HTMLElement {\n const swatch = document.createElement('span')\n swatch.className = 'midwest-form-live-summary-swatch'\n\n if (color.startsWith('#')) {\n swatch.style.backgroundColor = color\n } else if (color && color !== 'transparent') {\n swatch.classList.add(`theme-${color}`, 'bg-theme-6')\n } else {\n swatch.classList.add('is-transparent')\n }\n\n return swatch\n }\n\n // Finds the label associated with a specific element via `for` attribute,\n // wrapping label, or falls back to a prettified version of the element name.\n private labelFor (el: Element): string {\n const id = (el as HTMLElement).id\n if (id) {\n const label = this.form?.querySelector(`label[for=\"${CSS.escape(id)}\"]`)\n if (label) return label.textContent?.trim() ?? ''\n }\n const wrapper = el.closest('label')\n if (wrapper) return wrapper.textContent?.trim() ?? ''\n return this.prettifyName((el as HTMLInputElement).name ?? '')\n }\n\n // For radio groups, prefer the containing fieldset legend over the\n // individual radio's label, then fall back to prettifying the name.\n private groupLabelFor (el: Element): string {\n const legend = el.closest('fieldset')?.querySelector('legend')\n if (legend) return legend.textContent?.trim() ?? ''\n return this.prettifyName((el as HTMLInputElement).name ?? '')\n }\n\n // Converts \"user[first_name]\" or \"first_name\" into \"First name\".\n private prettifyName (name: string): string {\n return name\n .replace(/\\[.*?\\]/g, '')\n .replace(/_/g, ' ')\n .replace(/^\\w/, c => c.toUpperCase())\n .trim()\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,490 @@
1
+ /*
2
+ * Color Thief v2.0
3
+ * by Lokesh Dhakar - http://www.lokeshdhakar.com
4
+ *
5
+ * Thanks
6
+ * ------
7
+ * Nick Rabinowitz - For creating quantize.js.
8
+ * John Schulz - For clean up and optimization. @JFSIII
9
+ * Nathan Spady - For adding drag and drop support to the demo page.
10
+ *
11
+ * License
12
+ * -------
13
+ * Copyright 2011, 2015 Lokesh Dhakar
14
+ * Released under the MIT license
15
+ * https://raw.githubusercontent.com/lokesh/color-thief/master/LICENSE
16
+ *
17
+ * @license
18
+ */
19
+ const CanvasImage = function(image) {
20
+ this.canvas = document.createElement("canvas");
21
+ this.context = this.canvas.getContext("2d");
22
+ document.body.appendChild(this.canvas);
23
+ this.width = this.canvas.width = image.width;
24
+ this.height = this.canvas.height = image.height;
25
+ this.context.drawImage(image, 0, 0, this.width, this.height);
26
+ };
27
+ CanvasImage.prototype.clear = function() {
28
+ this.context.clearRect(0, 0, this.width, this.height);
29
+ };
30
+ CanvasImage.prototype.update = function(imageData) {
31
+ this.context.putImageData(imageData, 0, 0);
32
+ };
33
+ CanvasImage.prototype.getPixelCount = function() {
34
+ return this.width * this.height;
35
+ };
36
+ CanvasImage.prototype.getImageData = function() {
37
+ return this.context.getImageData(0, 0, this.width, this.height);
38
+ };
39
+ CanvasImage.prototype.removeCanvas = function() {
40
+ this.canvas.parentNode.removeChild(this.canvas);
41
+ };
42
+ const ColorThief = function() {
43
+ };
44
+ ColorThief.prototype.getColor = function(sourceImage2, quality) {
45
+ const palette = this.getPalette(sourceImage2, 5, quality);
46
+ const dominantColor = palette[0];
47
+ return dominantColor;
48
+ };
49
+ ColorThief.prototype.getPalette = function(sourceImage2, colorCount, quality) {
50
+ if (typeof colorCount === "undefined" || colorCount < 2 || colorCount > 256) {
51
+ colorCount = 10;
52
+ }
53
+ if (typeof quality === "undefined" || quality < 1) {
54
+ quality = 10;
55
+ }
56
+ const image = new CanvasImage(sourceImage2);
57
+ const imageData = image.getImageData();
58
+ const pixels = imageData.data;
59
+ const pixelCount = image.getPixelCount();
60
+ const pixelArray = [];
61
+ for (var i = 0, offset, r, g, b, a; i < pixelCount; i = i + quality) {
62
+ offset = i * 4;
63
+ r = pixels[offset + 0];
64
+ g = pixels[offset + 1];
65
+ b = pixels[offset + 2];
66
+ a = pixels[offset + 3];
67
+ if (a >= 125) {
68
+ if (!(r > 250 && g > 250 && b > 250)) {
69
+ pixelArray.push([r, g, b]);
70
+ }
71
+ }
72
+ }
73
+ const cmap = MMCQ.quantize(pixelArray, colorCount);
74
+ const palette = cmap ? cmap.palette() : null;
75
+ image.removeCanvas();
76
+ return palette;
77
+ };
78
+ ColorThief.prototype.getColorFromUrl = function(imageUrl, callback, quality) {
79
+ sourceImage = document.createElement("img");
80
+ const thief = this;
81
+ sourceImage.addEventListener("load", function() {
82
+ const palette = thief.getPalette(sourceImage, 5, quality);
83
+ const dominantColor = palette[0];
84
+ callback(dominantColor, imageUrl);
85
+ });
86
+ sourceImage.src = imageUrl;
87
+ };
88
+ ColorThief.prototype.getImageData = function(imageUrl, callback) {
89
+ xhr = new XMLHttpRequest();
90
+ xhr.open("GET", imageUrl, true);
91
+ xhr.responseType = "arraybuffer";
92
+ xhr.onload = function(e) {
93
+ if (this.status == 200) {
94
+ uInt8Array = new Uint8Array(this.response);
95
+ i = uInt8Array.length;
96
+ binaryString = new Array(i);
97
+ for (var i = 0; i < uInt8Array.length; i++) {
98
+ binaryString[i] = String.fromCharCode(uInt8Array[i]);
99
+ }
100
+ data = binaryString.join("");
101
+ base64 = window.btoa(data);
102
+ callback("data:image/png;base64," + base64);
103
+ }
104
+ };
105
+ xhr.send();
106
+ };
107
+ ColorThief.prototype.getColorAsync = function(imageUrl, callback, quality) {
108
+ const thief = this;
109
+ this.getImageData(imageUrl, function(imageData) {
110
+ sourceImage = document.createElement("img");
111
+ sourceImage.addEventListener("load", function() {
112
+ const palette = thief.getPalette(sourceImage, 5, quality);
113
+ const dominantColor = palette[0];
114
+ callback(dominantColor, this);
115
+ });
116
+ sourceImage.src = imageData;
117
+ });
118
+ };
119
+ /*!
120
+ * quantize.js Copyright 2008 Nick Rabinowitz.
121
+ * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
122
+ * @license
123
+ */
124
+ /*!
125
+ * Block below copied from Protovis: http://mbostock.github.com/protovis/
126
+ * Copyright 2010 Stanford Visualization Group
127
+ * Licensed under the BSD License: http://www.opensource.org/licenses/bsd-license.php
128
+ * @license
129
+ */
130
+ if (!pv) {
131
+ var pv = {
132
+ map: function(array, f) {
133
+ const o = {};
134
+ return f ? array.map(function(d, i) {
135
+ o.index = i;
136
+ return f.call(o, d);
137
+ }) : array.slice();
138
+ },
139
+ naturalOrder: function(a, b) {
140
+ return a < b ? -1 : a > b ? 1 : 0;
141
+ },
142
+ sum: function(array, f) {
143
+ const o = {};
144
+ return array.reduce(f ? function(p, d, i) {
145
+ o.index = i;
146
+ return p + f.call(o, d);
147
+ } : function(p, d) {
148
+ return p + d;
149
+ }, 0);
150
+ },
151
+ max: function(array, f) {
152
+ return Math.max.apply(null, f ? pv.map(array, f) : array);
153
+ }
154
+ };
155
+ }
156
+ var MMCQ = function() {
157
+ const sigbits = 5, rshift = 8 - sigbits, maxIterations = 1e3, fractByPopulations = 0.75;
158
+ function getColorIndex(r, g, b) {
159
+ return (r << 2 * sigbits) + (g << sigbits) + b;
160
+ }
161
+ function PQueue(comparator) {
162
+ let contents = [], sorted = false;
163
+ function sort() {
164
+ contents.sort(comparator);
165
+ sorted = true;
166
+ }
167
+ return {
168
+ push: function(o) {
169
+ contents.push(o);
170
+ sorted = false;
171
+ },
172
+ peek: function(index) {
173
+ if (!sorted)
174
+ sort();
175
+ if (index === void 0)
176
+ index = contents.length - 1;
177
+ return contents[index];
178
+ },
179
+ pop: function() {
180
+ if (!sorted)
181
+ sort();
182
+ return contents.pop();
183
+ },
184
+ size: function() {
185
+ return contents.length;
186
+ },
187
+ map: function(f) {
188
+ return contents.map(f);
189
+ },
190
+ debug: function() {
191
+ if (!sorted)
192
+ sort();
193
+ return contents;
194
+ }
195
+ };
196
+ }
197
+ function VBox(r1, r2, g1, g2, b1, b2, histo) {
198
+ const vbox = this;
199
+ vbox.r1 = r1;
200
+ vbox.r2 = r2;
201
+ vbox.g1 = g1;
202
+ vbox.g2 = g2;
203
+ vbox.b1 = b1;
204
+ vbox.b2 = b2;
205
+ vbox.histo = histo;
206
+ }
207
+ VBox.prototype = {
208
+ volume: function(force) {
209
+ const vbox = this;
210
+ if (!vbox._volume || force) {
211
+ vbox._volume = (vbox.r2 - vbox.r1 + 1) * (vbox.g2 - vbox.g1 + 1) * (vbox.b2 - vbox.b1 + 1);
212
+ }
213
+ return vbox._volume;
214
+ },
215
+ count: function(force) {
216
+ const vbox = this, histo = vbox.histo;
217
+ if (!vbox._count_set || force) {
218
+ let npix = 0, index, i, j, k;
219
+ for (i = vbox.r1; i <= vbox.r2; i++) {
220
+ for (j = vbox.g1; j <= vbox.g2; j++) {
221
+ for (k = vbox.b1; k <= vbox.b2; k++) {
222
+ index = getColorIndex(i, j, k);
223
+ npix += histo[index] || 0;
224
+ }
225
+ }
226
+ }
227
+ vbox._count = npix;
228
+ vbox._count_set = true;
229
+ }
230
+ return vbox._count;
231
+ },
232
+ copy: function() {
233
+ const vbox = this;
234
+ return new VBox(vbox.r1, vbox.r2, vbox.g1, vbox.g2, vbox.b1, vbox.b2, vbox.histo);
235
+ },
236
+ avg: function(force) {
237
+ const vbox = this, histo = vbox.histo;
238
+ if (!vbox._avg || force) {
239
+ let ntot = 0, mult = 1 << 8 - sigbits, rsum = 0, gsum = 0, bsum = 0, hval, i, j, k, histoindex;
240
+ for (i = vbox.r1; i <= vbox.r2; i++) {
241
+ for (j = vbox.g1; j <= vbox.g2; j++) {
242
+ for (k = vbox.b1; k <= vbox.b2; k++) {
243
+ histoindex = getColorIndex(i, j, k);
244
+ hval = histo[histoindex] || 0;
245
+ ntot += hval;
246
+ rsum += hval * (i + 0.5) * mult;
247
+ gsum += hval * (j + 0.5) * mult;
248
+ bsum += hval * (k + 0.5) * mult;
249
+ }
250
+ }
251
+ }
252
+ if (ntot) {
253
+ vbox._avg = [~~(rsum / ntot), ~~(gsum / ntot), ~~(bsum / ntot)];
254
+ } else {
255
+ vbox._avg = [
256
+ ~~(mult * (vbox.r1 + vbox.r2 + 1) / 2),
257
+ ~~(mult * (vbox.g1 + vbox.g2 + 1) / 2),
258
+ ~~(mult * (vbox.b1 + vbox.b2 + 1) / 2)
259
+ ];
260
+ }
261
+ }
262
+ return vbox._avg;
263
+ },
264
+ contains: function(pixel) {
265
+ const vbox = this, rval = pixel[0] >> rshift;
266
+ gval = pixel[1] >> rshift;
267
+ bval = pixel[2] >> rshift;
268
+ return rval >= vbox.r1 && rval <= vbox.r2 && gval >= vbox.g1 && gval <= vbox.g2 && bval >= vbox.b1 && bval <= vbox.b2;
269
+ }
270
+ };
271
+ function CMap() {
272
+ this.vboxes = new PQueue(function(a, b) {
273
+ return pv.naturalOrder(
274
+ a.vbox.count() * a.vbox.volume(),
275
+ b.vbox.count() * b.vbox.volume()
276
+ );
277
+ });
278
+ }
279
+ CMap.prototype = {
280
+ push: function(vbox) {
281
+ this.vboxes.push({
282
+ vbox,
283
+ color: vbox.avg()
284
+ });
285
+ },
286
+ palette: function() {
287
+ return this.vboxes.map(function(vb) {
288
+ return vb.color;
289
+ });
290
+ },
291
+ size: function() {
292
+ return this.vboxes.size();
293
+ },
294
+ map: function(color) {
295
+ const vboxes = this.vboxes;
296
+ for (let i = 0; i < vboxes.size(); i++) {
297
+ if (vboxes.peek(i).vbox.contains(color)) {
298
+ return vboxes.peek(i).color;
299
+ }
300
+ }
301
+ return this.nearest(color);
302
+ },
303
+ nearest: function(color) {
304
+ let vboxes = this.vboxes, d1, d2, pColor;
305
+ for (let i = 0; i < vboxes.size(); i++) {
306
+ d2 = Math.sqrt(
307
+ 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)
308
+ );
309
+ if (d2 < d1 || d1 === void 0) {
310
+ d1 = d2;
311
+ pColor = vboxes.peek(i).color;
312
+ }
313
+ }
314
+ return pColor;
315
+ },
316
+ forcebw: function() {
317
+ const vboxes = this.vboxes;
318
+ vboxes.sort(function(a, b) {
319
+ return pv.naturalOrder(pv.sum(a.color), pv.sum(b.color));
320
+ });
321
+ const lowest = vboxes[0].color;
322
+ if (lowest[0] < 5 && lowest[1] < 5 && lowest[2] < 5)
323
+ vboxes[0].color = [0, 0, 0];
324
+ const idx = vboxes.length - 1, highest = vboxes[idx].color;
325
+ if (highest[0] > 251 && highest[1] > 251 && highest[2] > 251)
326
+ vboxes[idx].color = [255, 255, 255];
327
+ }
328
+ };
329
+ function getHisto(pixels) {
330
+ let histosize = 1 << 3 * sigbits, histo = new Array(histosize), index, rval, gval2, bval2;
331
+ pixels.forEach(function(pixel) {
332
+ rval = pixel[0] >> rshift;
333
+ gval2 = pixel[1] >> rshift;
334
+ bval2 = pixel[2] >> rshift;
335
+ index = getColorIndex(rval, gval2, bval2);
336
+ histo[index] = (histo[index] || 0) + 1;
337
+ });
338
+ return histo;
339
+ }
340
+ function vboxFromPixels(pixels, histo) {
341
+ let rmin = 1e6, rmax = 0, gmin = 1e6, gmax = 0, bmin = 1e6, bmax = 0, rval, gval2, bval2;
342
+ pixels.forEach(function(pixel) {
343
+ rval = pixel[0] >> rshift;
344
+ gval2 = pixel[1] >> rshift;
345
+ bval2 = pixel[2] >> rshift;
346
+ if (rval < rmin)
347
+ rmin = rval;
348
+ else if (rval > rmax)
349
+ rmax = rval;
350
+ if (gval2 < gmin)
351
+ gmin = gval2;
352
+ else if (gval2 > gmax)
353
+ gmax = gval2;
354
+ if (bval2 < bmin)
355
+ bmin = bval2;
356
+ else if (bval2 > bmax)
357
+ bmax = bval2;
358
+ });
359
+ return new VBox(rmin, rmax, gmin, gmax, bmin, bmax, histo);
360
+ }
361
+ function medianCutApply(histo, vbox) {
362
+ if (!vbox.count())
363
+ return;
364
+ 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]);
365
+ if (vbox.count() == 1) {
366
+ return [vbox.copy()];
367
+ }
368
+ let total = 0, partialsum = [], lookaheadsum = [], i, j, k, sum, index;
369
+ if (maxw == rw) {
370
+ for (i = vbox.r1; i <= vbox.r2; i++) {
371
+ sum = 0;
372
+ for (j = vbox.g1; j <= vbox.g2; j++) {
373
+ for (k = vbox.b1; k <= vbox.b2; k++) {
374
+ index = getColorIndex(i, j, k);
375
+ sum += histo[index] || 0;
376
+ }
377
+ }
378
+ total += sum;
379
+ partialsum[i] = total;
380
+ }
381
+ } else if (maxw == gw) {
382
+ for (i = vbox.g1; i <= vbox.g2; i++) {
383
+ sum = 0;
384
+ for (j = vbox.r1; j <= vbox.r2; j++) {
385
+ for (k = vbox.b1; k <= vbox.b2; k++) {
386
+ index = getColorIndex(j, i, k);
387
+ sum += histo[index] || 0;
388
+ }
389
+ }
390
+ total += sum;
391
+ partialsum[i] = total;
392
+ }
393
+ } else {
394
+ for (i = vbox.b1; i <= vbox.b2; i++) {
395
+ sum = 0;
396
+ for (j = vbox.r1; j <= vbox.r2; j++) {
397
+ for (k = vbox.g1; k <= vbox.g2; k++) {
398
+ index = getColorIndex(j, k, i);
399
+ sum += histo[index] || 0;
400
+ }
401
+ }
402
+ total += sum;
403
+ partialsum[i] = total;
404
+ }
405
+ }
406
+ partialsum.forEach(function(d, i2) {
407
+ lookaheadsum[i2] = total - d;
408
+ });
409
+ function doCut(color) {
410
+ let dim1 = color + "1", dim2 = color + "2", left, right, vbox1, vbox2, d2, count2 = 0;
411
+ for (i = vbox[dim1]; i <= vbox[dim2]; i++) {
412
+ if (partialsum[i] > total / 2) {
413
+ vbox1 = vbox.copy();
414
+ vbox2 = vbox.copy();
415
+ left = i - vbox[dim1];
416
+ right = vbox[dim2] - i;
417
+ if (left <= right)
418
+ d2 = Math.min(vbox[dim2] - 1, ~~(i + right / 2));
419
+ else
420
+ d2 = Math.max(vbox[dim1], ~~(i - 1 - left / 2));
421
+ while (!partialsum[d2])
422
+ d2++;
423
+ count2 = lookaheadsum[d2];
424
+ while (!count2 && partialsum[d2 - 1])
425
+ count2 = lookaheadsum[--d2];
426
+ vbox1[dim2] = d2;
427
+ vbox2[dim1] = vbox1[dim2] + 1;
428
+ return [vbox1, vbox2];
429
+ }
430
+ }
431
+ }
432
+ return maxw == rw ? doCut("r") : maxw == gw ? doCut("g") : doCut("b");
433
+ }
434
+ function quantize(pixels, maxcolors) {
435
+ if (!pixels.length || maxcolors < 2 || maxcolors > 256) {
436
+ return false;
437
+ }
438
+ const histo = getHisto(pixels);
439
+ histo.forEach(function() {
440
+ });
441
+ const vbox = vboxFromPixels(pixels, histo), pq = new PQueue(function(a, b) {
442
+ return pv.naturalOrder(a.count(), b.count());
443
+ });
444
+ pq.push(vbox);
445
+ function iter(lh, target) {
446
+ let ncolors = 1, niters = 0, vbox2;
447
+ while (niters < maxIterations) {
448
+ vbox2 = lh.pop();
449
+ if (!vbox2.count()) {
450
+ lh.push(vbox2);
451
+ niters++;
452
+ continue;
453
+ }
454
+ const vboxes = medianCutApply(histo, vbox2), vbox1 = vboxes[0], vbox22 = vboxes[1];
455
+ if (!vbox1) {
456
+ return;
457
+ }
458
+ lh.push(vbox1);
459
+ if (vbox22) {
460
+ lh.push(vbox22);
461
+ ncolors++;
462
+ }
463
+ if (ncolors >= target)
464
+ return;
465
+ if (niters++ > maxIterations) {
466
+ return;
467
+ }
468
+ }
469
+ }
470
+ iter(pq, fractByPopulations * maxcolors);
471
+ const pq2 = new PQueue(function(a, b) {
472
+ return pv.naturalOrder(a.count() * a.volume(), b.count() * b.volume());
473
+ });
474
+ while (pq.size()) {
475
+ pq2.push(pq.pop());
476
+ }
477
+ iter(pq2, maxcolors - pq2.size());
478
+ const cmap = new CMap();
479
+ while (pq2.size()) {
480
+ cmap.push(pq2.pop());
481
+ }
482
+ return cmap;
483
+ }
484
+ return {
485
+ quantize
486
+ };
487
+ }();
488
+
489
+ export { CanvasImage, ColorThief };
490
+ //# sourceMappingURL=color_thief.js.map