@unabridged/midwest 0.19.1 → 0.20.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 (28) hide show
  1. package/README.md +1 -1
  2. package/app/assets/javascript/midwest/index.ts +8 -0
  3. package/app/assets/javascript/midwest/template_helpers.ts +27 -0
  4. package/app/assets/javascript/midwest.js +724 -0
  5. package/app/assets/javascript/midwest.js.map +1 -1
  6. package/app/assets/stylesheets/midwest.css +1 -1
  7. package/app/assets/stylesheets/midwest.tailwind.css +5 -1
  8. package/dist/css/midwest.css +1 -1
  9. package/dist/javascript/collection/app/assets/javascript/midwest/index.js +8 -0
  10. package/dist/javascript/collection/app/assets/javascript/midwest/index.js.map +1 -1
  11. package/dist/javascript/collection/app/assets/javascript/midwest/template_helpers.js +10 -0
  12. package/dist/javascript/collection/app/assets/javascript/midwest/template_helpers.js.map +1 -0
  13. package/dist/javascript/collection/app/components/midwest/card_component/card_component_controller.js.map +1 -1
  14. package/dist/javascript/collection/app/components/midwest/command_palette_component/command_palette_component_controller.js +350 -0
  15. package/dist/javascript/collection/app/components/midwest/command_palette_component/command_palette_component_controller.js.map +1 -0
  16. package/dist/javascript/collection/app/components/midwest/form/live_summary_component/live_summary_component_controller.js +24 -0
  17. package/dist/javascript/collection/app/components/midwest/form/live_summary_component/live_summary_component_controller.js.map +1 -1
  18. package/dist/javascript/collection/app/components/midwest/pagination_component/pagination_component_controller.js +52 -0
  19. package/dist/javascript/collection/app/components/midwest/pagination_component/pagination_component_controller.js.map +1 -0
  20. package/dist/javascript/collection/app/components/midwest/show_if_component/show_if_component_controller.js +80 -0
  21. package/dist/javascript/collection/app/components/midwest/show_if_component/show_if_component_controller.js.map +1 -0
  22. package/dist/javascript/collection/app/components/midwest/table_component/table_component_controller.js +19 -0
  23. package/dist/javascript/collection/app/components/midwest/table_component/table_component_controller.js.map +1 -1
  24. package/dist/javascript/collection/app/components/midwest/tree_view_component/tree_view_component_controller.js +204 -0
  25. package/dist/javascript/collection/app/components/midwest/tree_view_component/tree_view_component_controller.js.map +1 -0
  26. package/dist/javascript/midwest.js +724 -0
  27. package/dist/javascript/midwest.js.map +1 -1
  28. package/package.json +1 -1
@@ -0,0 +1,52 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+
3
+ class Pagination extends Controller {
4
+ static targets = ["jumpInput"];
5
+ static values = { urlTemplate: String, turboFrameId: String };
6
+ debounceTimer = null;
7
+ // Intercepts the jump-to-page form submit and navigates to the resolved URL.
8
+ jump(event) {
9
+ event.preventDefault();
10
+ if (!this.hasJumpInputTarget)
11
+ return;
12
+ const page = parseInt(this.jumpInputTarget.value, 10);
13
+ if (!isNaN(page) && page >= 1) {
14
+ this.visitUrl(this.urlTemplateValue.replace("__PAGE__", String(page)));
15
+ }
16
+ }
17
+ // Debounced handler for the `incremental` input — navigates 400 ms after the
18
+ // user stops typing, and only when the value is within the valid page range.
19
+ jumpIncremental() {
20
+ if (this.debounceTimer)
21
+ clearTimeout(this.debounceTimer);
22
+ this.debounceTimer = setTimeout(() => {
23
+ if (!this.hasJumpInputTarget)
24
+ return;
25
+ const input = this.jumpInputTarget;
26
+ const page = parseInt(input.value, 10);
27
+ const max = parseInt(input.max, 10);
28
+ if (!isNaN(page) && page >= 1 && (!max || page <= max)) {
29
+ this.visitUrl(this.urlTemplateValue.replace("__PAGE__", String(page)));
30
+ }
31
+ }, 400);
32
+ }
33
+ // Navigates to the URL selected in the per-page <select> element.
34
+ navigate(event) {
35
+ const select = event.target;
36
+ const href = select.value;
37
+ if (href && href !== "#") {
38
+ this.visitUrl(href);
39
+ }
40
+ }
41
+ // Navigates to a URL via Turbo visit, updating the browser URL.
42
+ visitUrl(url) {
43
+ if (window.Turbo) {
44
+ window.Turbo.visit(url);
45
+ } else {
46
+ window.location.href = url;
47
+ }
48
+ }
49
+ }
50
+
51
+ export { Pagination as default };
52
+ //# sourceMappingURL=pagination_component_controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagination_component_controller.js","sources":["../../../../../../../app/components/midwest/pagination_component/pagination_component_controller.ts"],"sourcesContent":["import { Controller } from '@hotwired/stimulus'\n\nexport default class Pagination extends Controller {\n static targets = ['jumpInput']\n static values = { urlTemplate: String, turboFrameId: String }\n\n declare readonly jumpInputTarget: HTMLInputElement\n declare readonly hasJumpInputTarget: boolean\n declare urlTemplateValue: string\n declare turboFrameIdValue: string\n\n private debounceTimer: ReturnType<typeof setTimeout> | null = null\n\n // Intercepts the jump-to-page form submit and navigates to the resolved URL.\n jump (event: Event) {\n event.preventDefault()\n if (!this.hasJumpInputTarget) return\n const page = parseInt(this.jumpInputTarget.value, 10)\n if (!isNaN(page) && page >= 1) {\n this.visitUrl(this.urlTemplateValue.replace('__PAGE__', String(page)))\n }\n }\n\n // Debounced handler for the `incremental` input — navigates 400 ms after the\n // user stops typing, and only when the value is within the valid page range.\n jumpIncremental () {\n if (this.debounceTimer) clearTimeout(this.debounceTimer)\n this.debounceTimer = setTimeout(() => {\n if (!this.hasJumpInputTarget) return\n const input = this.jumpInputTarget\n const page = parseInt(input.value, 10)\n const max = parseInt(input.max, 10)\n if (!isNaN(page) && page >= 1 && (!max || page <= max)) {\n this.visitUrl(this.urlTemplateValue.replace('__PAGE__', String(page)))\n }\n }, 400)\n }\n\n // Navigates to the URL selected in the per-page <select> element.\n navigate (event: Event) {\n const select = event.target as HTMLSelectElement\n const href = select.value\n if (href && href !== '#') {\n this.visitUrl(href)\n }\n }\n\n // Navigates to a URL via Turbo visit, updating the browser URL.\n private visitUrl (url: string) {\n if ((window as any).Turbo) {\n (window as any).Turbo.visit(url)\n } else {\n window.location.href = url\n }\n }\n}\n"],"names":[],"mappings":";;AAEA,MAAqB,mBAAmB,UAAW,CAAA;AAAA,EACjD,OAAO,OAAU,GAAA,CAAC,WAAW,CAAA,CAAA;AAAA,EAC7B,OAAO,MAAS,GAAA,EAAE,WAAa,EAAA,MAAA,EAAQ,cAAc,MAAO,EAAA,CAAA;AAAA,EAOpD,aAAsD,GAAA,IAAA,CAAA;AAAA;AAAA,EAG9D,KAAM,KAAc,EAAA;AAClB,IAAA,KAAA,CAAM,cAAe,EAAA,CAAA;AACrB,IAAA,IAAI,CAAC,IAAK,CAAA,kBAAA;AAAoB,MAAA,OAAA;AAC9B,IAAA,MAAM,IAAO,GAAA,QAAA,CAAS,IAAK,CAAA,eAAA,CAAgB,OAAO,EAAE,CAAA,CAAA;AACpD,IAAA,IAAI,CAAC,KAAA,CAAM,IAAI,CAAA,IAAK,QAAQ,CAAG,EAAA;AAC7B,MAAK,IAAA,CAAA,QAAA,CAAS,KAAK,gBAAiB,CAAA,OAAA,CAAQ,YAAY,MAAO,CAAA,IAAI,CAAC,CAAC,CAAA,CAAA;AAAA,KACvE;AAAA,GACF;AAAA;AAAA;AAAA,EAIA,eAAmB,GAAA;AACjB,IAAA,IAAI,IAAK,CAAA,aAAA;AAAe,MAAA,YAAA,CAAa,KAAK,aAAa,CAAA,CAAA;AACvD,IAAK,IAAA,CAAA,aAAA,GAAgB,WAAW,MAAM;AACpC,MAAA,IAAI,CAAC,IAAK,CAAA,kBAAA;AAAoB,QAAA,OAAA;AAC9B,MAAA,MAAM,QAAQ,IAAK,CAAA,eAAA,CAAA;AACnB,MAAA,MAAM,IAAQ,GAAA,QAAA,CAAS,KAAM,CAAA,KAAA,EAAO,EAAE,CAAA,CAAA;AACtC,MAAA,MAAM,GAAQ,GAAA,QAAA,CAAS,KAAM,CAAA,GAAA,EAAK,EAAE,CAAA,CAAA;AACpC,MAAI,IAAA,CAAC,MAAM,IAAI,CAAA,IAAK,QAAQ,CAAM,KAAA,CAAC,GAAO,IAAA,IAAA,IAAQ,GAAM,CAAA,EAAA;AACtD,QAAK,IAAA,CAAA,QAAA,CAAS,KAAK,gBAAiB,CAAA,OAAA,CAAQ,YAAY,MAAO,CAAA,IAAI,CAAC,CAAC,CAAA,CAAA;AAAA,OACvE;AAAA,OACC,GAAG,CAAA,CAAA;AAAA,GACR;AAAA;AAAA,EAGA,SAAU,KAAc,EAAA;AACtB,IAAA,MAAM,SAAS,KAAM,CAAA,MAAA,CAAA;AACrB,IAAA,MAAM,OAAO,MAAO,CAAA,KAAA,CAAA;AACpB,IAAI,IAAA,IAAA,IAAQ,SAAS,GAAK,EAAA;AACxB,MAAA,IAAA,CAAK,SAAS,IAAI,CAAA,CAAA;AAAA,KACpB;AAAA,GACF;AAAA;AAAA,EAGQ,SAAU,GAAa,EAAA;AAC7B,IAAA,IAAK,OAAe,KAAO,EAAA;AACzB,MAAC,MAAA,CAAe,KAAM,CAAA,KAAA,CAAM,GAAG,CAAA,CAAA;AAAA,KAC1B,MAAA;AACL,MAAA,MAAA,CAAO,SAAS,IAAO,GAAA,GAAA,CAAA;AAAA,KACzB;AAAA,GACF;AACF;;;;"}
@@ -0,0 +1,80 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+
3
+ class ShowIf extends Controller {
4
+ static values = {
5
+ watch: { type: String, default: "" },
6
+ is: { type: String, default: "" },
7
+ negate: { type: Boolean, default: false }
8
+ };
9
+ sourceElement = null;
10
+ listenedElements = [];
11
+ changeListener = null;
12
+ connect() {
13
+ if (!this.watchValue)
14
+ return;
15
+ this.sourceElement = document.querySelector(this.watchValue);
16
+ if (!this.sourceElement)
17
+ return;
18
+ this.changeListener = () => this.evaluate();
19
+ if (this.sourceElement instanceof HTMLInputElement && this.sourceElement.type === "radio") {
20
+ const radios = document.querySelectorAll(
21
+ `input[type="radio"][name="${this.sourceElement.name}"]`
22
+ );
23
+ const listener = this.changeListener;
24
+ radios.forEach((radio) => {
25
+ radio.addEventListener("change", listener);
26
+ this.listenedElements.push(radio);
27
+ });
28
+ } else {
29
+ this.sourceElement.addEventListener("input", this.changeListener);
30
+ this.sourceElement.addEventListener("change", this.changeListener);
31
+ this.listenedElements.push(this.sourceElement);
32
+ }
33
+ this.evaluate();
34
+ }
35
+ disconnect() {
36
+ if (this.changeListener) {
37
+ for (const el of this.listenedElements) {
38
+ el.removeEventListener("input", this.changeListener);
39
+ el.removeEventListener("change", this.changeListener);
40
+ }
41
+ }
42
+ this.changeListener = null;
43
+ this.sourceElement = null;
44
+ this.listenedElements = [];
45
+ }
46
+ evaluate() {
47
+ const el = this.sourceElement;
48
+ if (!el)
49
+ return;
50
+ const currentValue = this.readValue(el);
51
+ const match = currentValue === this.isValue;
52
+ const visible = this.negateValue ? !match : match;
53
+ this.element.toggleAttribute("hidden", !visible);
54
+ this.element.toggleAttribute("disabled", !visible);
55
+ }
56
+ readValue(el) {
57
+ if (el instanceof HTMLInputElement) {
58
+ if (el.type === "radio") {
59
+ const checked = document.querySelector(
60
+ `input[name="${el.name}"]:checked`
61
+ );
62
+ return checked ? checked.value : "";
63
+ }
64
+ if (el.type === "checkbox") {
65
+ return el.checked ? el.value || "true" : "";
66
+ }
67
+ return el.value;
68
+ }
69
+ if (el instanceof HTMLSelectElement) {
70
+ return el.value;
71
+ }
72
+ if (el instanceof HTMLTextAreaElement) {
73
+ return el.value;
74
+ }
75
+ return el.getAttribute("value") ?? "";
76
+ }
77
+ }
78
+
79
+ export { ShowIf as default };
80
+ //# sourceMappingURL=show_if_component_controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"show_if_component_controller.js","sources":["../../../../../../../app/components/midwest/show_if_component/show_if_component_controller.ts"],"sourcesContent":["\nimport { Controller } from '@hotwired/stimulus'\n\nexport default class ShowIf extends Controller<HTMLElement> {\n static values = {\n watch: { type: String, default: '' },\n is: { type: String, default: '' },\n negate: { type: Boolean, default: false }\n }\n\n declare watchValue: string\n declare isValue: string\n declare negateValue: boolean\n\n private sourceElement: Element | null = null\n private listenedElements: Element[] = []\n private changeListener: (() => void) | null = null\n\n connect () {\n if (!this.watchValue) return\n\n this.sourceElement = document.querySelector(this.watchValue)\n if (!this.sourceElement) return\n\n this.changeListener = () => this.evaluate()\n\n // For radio buttons, listen on all radios in the group so that\n // selecting a *different* radio still triggers re-evaluation.\n if (this.sourceElement instanceof HTMLInputElement && this.sourceElement.type === 'radio') {\n const radios = document.querySelectorAll<HTMLInputElement>(\n `input[type=\"radio\"][name=\"${this.sourceElement.name}\"]`\n )\n const listener = this.changeListener\n radios.forEach((radio) => {\n radio.addEventListener('change', listener)\n this.listenedElements.push(radio)\n })\n } else {\n this.sourceElement.addEventListener('input', this.changeListener)\n this.sourceElement.addEventListener('change', this.changeListener)\n this.listenedElements.push(this.sourceElement)\n }\n\n this.evaluate()\n }\n\n disconnect () {\n if (this.changeListener) {\n for (const el of this.listenedElements) {\n el.removeEventListener('input', this.changeListener)\n el.removeEventListener('change', this.changeListener)\n }\n }\n this.changeListener = null\n this.sourceElement = null\n this.listenedElements = []\n }\n\n private evaluate () {\n const el = this.sourceElement\n if (!el) return\n\n const currentValue = this.readValue(el)\n const match = currentValue === this.isValue\n const visible = this.negateValue ? !match : match\n\n this.element.toggleAttribute('hidden', !visible)\n this.element.toggleAttribute('disabled', !visible)\n }\n\n private readValue (el: Element): string {\n if (el instanceof HTMLInputElement) {\n if (el.type === 'radio') {\n const checked = document.querySelector<HTMLInputElement>(\n `input[name=\"${el.name}\"]:checked`\n )\n return checked ? checked.value : ''\n }\n if (el.type === 'checkbox') {\n return el.checked ? (el.value || 'true') : ''\n }\n return el.value\n }\n\n if (el instanceof HTMLSelectElement) {\n return el.value\n }\n\n if (el instanceof HTMLTextAreaElement) {\n return el.value\n }\n\n return el.getAttribute('value') ?? ''\n }\n}\n"],"names":[],"mappings":"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"}
@@ -8,6 +8,25 @@ class Table extends Controller {
8
8
  cb.checked = checked;
9
9
  });
10
10
  }
11
+ navigateRow(event) {
12
+ const target = event.target;
13
+ if (target.closest('a, button, input, select, textarea, [role="button"]'))
14
+ return;
15
+ const row = event.currentTarget;
16
+ const href = row.dataset.href;
17
+ if (!href)
18
+ return;
19
+ if (event.metaKey || event.ctrlKey) {
20
+ window.open(href, "_blank");
21
+ } else {
22
+ const Turbo = window.Turbo;
23
+ if (Turbo?.visit) {
24
+ Turbo.visit(href);
25
+ } else {
26
+ window.location.href = href;
27
+ }
28
+ }
29
+ }
11
30
  updateSelectAll() {
12
31
  if (!this.hasSelectAllTarget)
13
32
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"table_component_controller.js","sources":["../../../../../../../app/components/midwest/table_component/table_component_controller.ts"],"sourcesContent":["import { Controller } from '@hotwired/stimulus'\n\nexport default class Table extends Controller<HTMLElement> {\n static targets = ['selectAll', 'rowCheckbox']\n\n declare readonly selectAllTarget: HTMLInputElement\n declare readonly rowCheckboxTargets: HTMLInputElement[]\n declare readonly hasSelectAllTarget: boolean\n\n toggleAll () {\n const checked = this.selectAllTarget.checked\n this.rowCheckboxTargets.forEach(cb => { cb.checked = checked })\n }\n\n updateSelectAll () {\n if (!this.hasSelectAllTarget) return\n\n const total = this.rowCheckboxTargets.length\n const checkedCount = this.rowCheckboxTargets.filter(cb => cb.checked).length\n\n if (checkedCount === 0) {\n this.selectAllTarget.checked = false\n this.selectAllTarget.indeterminate = false\n } else if (checkedCount === total) {\n this.selectAllTarget.checked = true\n this.selectAllTarget.indeterminate = false\n } else {\n this.selectAllTarget.checked = false\n this.selectAllTarget.indeterminate = true\n }\n }\n}\n"],"names":[],"mappings":";;AAEA,MAAqB,cAAc,UAAwB,CAAA;AAAA,EACzD,OAAO,OAAA,GAAU,CAAC,WAAA,EAAa,aAAa,CAAA,CAAA;AAAA,EAM5C,SAAa,GAAA;AACX,IAAM,MAAA,OAAA,GAAU,KAAK,eAAgB,CAAA,OAAA,CAAA;AACrC,IAAK,IAAA,CAAA,kBAAA,CAAmB,QAAQ,CAAM,EAAA,KAAA;AAAE,MAAA,EAAA,CAAG,OAAU,GAAA,OAAA,CAAA;AAAA,KAAS,CAAA,CAAA;AAAA,GAChE;AAAA,EAEA,eAAmB,GAAA;AACjB,IAAA,IAAI,CAAC,IAAK,CAAA,kBAAA;AAAoB,MAAA,OAAA;AAE9B,IAAM,MAAA,KAAA,GAAQ,KAAK,kBAAmB,CAAA,MAAA,CAAA;AACtC,IAAA,MAAM,eAAe,IAAK,CAAA,kBAAA,CAAmB,OAAO,CAAM,EAAA,KAAA,EAAA,CAAG,OAAO,CAAE,CAAA,MAAA,CAAA;AAEtE,IAAA,IAAI,iBAAiB,CAAG,EAAA;AACtB,MAAA,IAAA,CAAK,gBAAgB,OAAU,GAAA,KAAA,CAAA;AAC/B,MAAA,IAAA,CAAK,gBAAgB,aAAgB,GAAA,KAAA,CAAA;AAAA,KACvC,MAAA,IAAW,iBAAiB,KAAO,EAAA;AACjC,MAAA,IAAA,CAAK,gBAAgB,OAAU,GAAA,IAAA,CAAA;AAC/B,MAAA,IAAA,CAAK,gBAAgB,aAAgB,GAAA,KAAA,CAAA;AAAA,KAChC,MAAA;AACL,MAAA,IAAA,CAAK,gBAAgB,OAAU,GAAA,KAAA,CAAA;AAC/B,MAAA,IAAA,CAAK,gBAAgB,aAAgB,GAAA,IAAA,CAAA;AAAA,KACvC;AAAA,GACF;AACF;;;;"}
1
+ {"version":3,"file":"table_component_controller.js","sources":["../../../../../../../app/components/midwest/table_component/table_component_controller.ts"],"sourcesContent":["import { Controller } from '@hotwired/stimulus'\n\nexport default class Table extends Controller<HTMLElement> {\n static targets = ['selectAll', 'rowCheckbox']\n\n declare readonly selectAllTarget: HTMLInputElement\n declare readonly rowCheckboxTargets: HTMLInputElement[]\n declare readonly hasSelectAllTarget: boolean\n\n toggleAll () {\n const checked = this.selectAllTarget.checked\n this.rowCheckboxTargets.forEach(cb => { cb.checked = checked })\n }\n\n navigateRow (event: MouseEvent) {\n const target = event.target as HTMLElement\n if (target.closest('a, button, input, select, textarea, [role=\"button\"]')) return\n\n const row = event.currentTarget as HTMLElement\n const href = row.dataset.href\n if (!href) return\n\n if (event.metaKey || event.ctrlKey) {\n window.open(href, '_blank')\n } else {\n const Turbo = (window as any).Turbo\n if (Turbo?.visit) {\n Turbo.visit(href)\n } else {\n window.location.href = href\n }\n }\n }\n\n updateSelectAll () {\n if (!this.hasSelectAllTarget) return\n\n const total = this.rowCheckboxTargets.length\n const checkedCount = this.rowCheckboxTargets.filter(cb => cb.checked).length\n\n if (checkedCount === 0) {\n this.selectAllTarget.checked = false\n this.selectAllTarget.indeterminate = false\n } else if (checkedCount === total) {\n this.selectAllTarget.checked = true\n this.selectAllTarget.indeterminate = false\n } else {\n this.selectAllTarget.checked = false\n this.selectAllTarget.indeterminate = true\n }\n }\n}\n"],"names":[],"mappings":";;AAEA,MAAqB,cAAc,UAAwB,CAAA;AAAA,EACzD,OAAO,OAAA,GAAU,CAAC,WAAA,EAAa,aAAa,CAAA,CAAA;AAAA,EAM5C,SAAa,GAAA;AACX,IAAM,MAAA,OAAA,GAAU,KAAK,eAAgB,CAAA,OAAA,CAAA;AACrC,IAAK,IAAA,CAAA,kBAAA,CAAmB,QAAQ,CAAM,EAAA,KAAA;AAAE,MAAA,EAAA,CAAG,OAAU,GAAA,OAAA,CAAA;AAAA,KAAS,CAAA,CAAA;AAAA,GAChE;AAAA,EAEA,YAAa,KAAmB,EAAA;AAC9B,IAAA,MAAM,SAAS,KAAM,CAAA,MAAA,CAAA;AACrB,IAAI,IAAA,MAAA,CAAO,QAAQ,qDAAqD,CAAA;AAAG,MAAA,OAAA;AAE3E,IAAA,MAAM,MAAM,KAAM,CAAA,aAAA,CAAA;AAClB,IAAM,MAAA,IAAA,GAAO,IAAI,OAAQ,CAAA,IAAA,CAAA;AACzB,IAAA,IAAI,CAAC,IAAA;AAAM,MAAA,OAAA;AAEX,IAAI,IAAA,KAAA,CAAM,OAAW,IAAA,KAAA,CAAM,OAAS,EAAA;AAClC,MAAO,MAAA,CAAA,IAAA,CAAK,MAAM,QAAQ,CAAA,CAAA;AAAA,KACrB,MAAA;AACL,MAAA,MAAM,QAAS,MAAe,CAAA,KAAA,CAAA;AAC9B,MAAA,IAAI,OAAO,KAAO,EAAA;AAChB,QAAA,KAAA,CAAM,MAAM,IAAI,CAAA,CAAA;AAAA,OACX,MAAA;AACL,QAAA,MAAA,CAAO,SAAS,IAAO,GAAA,IAAA,CAAA;AAAA,OACzB;AAAA,KACF;AAAA,GACF;AAAA,EAEA,eAAmB,GAAA;AACjB,IAAA,IAAI,CAAC,IAAK,CAAA,kBAAA;AAAoB,MAAA,OAAA;AAE9B,IAAM,MAAA,KAAA,GAAQ,KAAK,kBAAmB,CAAA,MAAA,CAAA;AACtC,IAAA,MAAM,eAAe,IAAK,CAAA,kBAAA,CAAmB,OAAO,CAAM,EAAA,KAAA,EAAA,CAAG,OAAO,CAAE,CAAA,MAAA,CAAA;AAEtE,IAAA,IAAI,iBAAiB,CAAG,EAAA;AACtB,MAAA,IAAA,CAAK,gBAAgB,OAAU,GAAA,KAAA,CAAA;AAC/B,MAAA,IAAA,CAAK,gBAAgB,aAAgB,GAAA,KAAA,CAAA;AAAA,KACvC,MAAA,IAAW,iBAAiB,KAAO,EAAA;AACjC,MAAA,IAAA,CAAK,gBAAgB,OAAU,GAAA,IAAA,CAAA;AAC/B,MAAA,IAAA,CAAK,gBAAgB,aAAgB,GAAA,KAAA,CAAA;AAAA,KAChC,MAAA;AACL,MAAA,IAAA,CAAK,gBAAgB,OAAU,GAAA,KAAA,CAAA;AAC/B,MAAA,IAAA,CAAK,gBAAgB,aAAgB,GAAA,IAAA,CAAA;AAAA,KACvC;AAAA,GACF;AACF;;;;"}
@@ -0,0 +1,204 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+
3
+ class TreeView extends Controller {
4
+ // ── Expand / Collapse ───────────────────────────────────────────────
5
+ toggle(event) {
6
+ const chevron = event.currentTarget.closest(".tree-node-chevron");
7
+ if (!chevron)
8
+ return;
9
+ const node = chevron.closest(".midwest-tree-node");
10
+ if (!node)
11
+ return;
12
+ const expanded = node.getAttribute("aria-expanded") === "true";
13
+ node.setAttribute("aria-expanded", String(!expanded));
14
+ this.focusNode(node);
15
+ }
16
+ // ── Checkbox Cascading ──────────────────────────────────────────────
17
+ checkboxChanged(event) {
18
+ const checkbox = event.target;
19
+ const node = checkbox.closest(".midwest-tree-node");
20
+ if (!node)
21
+ return;
22
+ const descendants = node.querySelectorAll(
23
+ ".tree-node-children .tree-node-checkbox"
24
+ );
25
+ for (const desc of descendants) {
26
+ desc.checked = checkbox.checked;
27
+ desc.indeterminate = false;
28
+ }
29
+ this.updateAncestors(node);
30
+ }
31
+ updateAncestors(node) {
32
+ const parentGroup = node.parentElement;
33
+ if (!parentGroup || !parentGroup.classList.contains("tree-node-children"))
34
+ return;
35
+ const parentNode = parentGroup.closest(".midwest-tree-node");
36
+ if (!parentNode)
37
+ return;
38
+ const parentCheckbox = parentNode.querySelector(
39
+ ":scope > .tree-node-trigger > .tree-node-checkbox"
40
+ );
41
+ if (!parentCheckbox)
42
+ return;
43
+ const childCheckboxes = parentGroup.querySelectorAll(
44
+ ":scope > .midwest-tree-node > .tree-node-trigger > .tree-node-checkbox"
45
+ );
46
+ const total = childCheckboxes.length;
47
+ let checked = 0;
48
+ let indeterminate = 0;
49
+ for (const cb of childCheckboxes) {
50
+ if (cb.indeterminate)
51
+ indeterminate++;
52
+ else if (cb.checked)
53
+ checked++;
54
+ }
55
+ if (indeterminate > 0 || checked > 0 && checked < total) {
56
+ parentCheckbox.checked = false;
57
+ parentCheckbox.indeterminate = true;
58
+ } else if (checked === total) {
59
+ parentCheckbox.checked = true;
60
+ parentCheckbox.indeterminate = false;
61
+ } else {
62
+ parentCheckbox.checked = false;
63
+ parentCheckbox.indeterminate = false;
64
+ }
65
+ this.updateAncestors(parentNode);
66
+ }
67
+ // ── Keyboard Navigation (WAI-ARIA TreeView) ────────────────────────
68
+ connect() {
69
+ this.element.addEventListener("keydown", this.handleKeydown);
70
+ const firstNode = this.element.querySelector(".midwest-tree-node");
71
+ if (firstNode) {
72
+ firstNode.setAttribute("tabindex", "0");
73
+ }
74
+ }
75
+ disconnect() {
76
+ this.element.removeEventListener("keydown", this.handleKeydown);
77
+ }
78
+ handleKeydown = (event) => {
79
+ const target = event.target.closest(".midwest-tree-node");
80
+ if (!target)
81
+ return;
82
+ switch (event.key) {
83
+ case "ArrowDown":
84
+ event.preventDefault();
85
+ this.moveFocus(target, "next");
86
+ break;
87
+ case "ArrowUp":
88
+ event.preventDefault();
89
+ this.moveFocus(target, "previous");
90
+ break;
91
+ case "ArrowRight":
92
+ event.preventDefault();
93
+ this.handleArrowRight(target);
94
+ break;
95
+ case "ArrowLeft":
96
+ event.preventDefault();
97
+ this.handleArrowLeft(target);
98
+ break;
99
+ case "Home":
100
+ event.preventDefault();
101
+ this.focusFirst();
102
+ break;
103
+ case "End":
104
+ event.preventDefault();
105
+ this.focusLast();
106
+ break;
107
+ case "Enter":
108
+ case " ":
109
+ event.preventDefault();
110
+ this.handleActivate(target);
111
+ break;
112
+ }
113
+ };
114
+ getVisibleNodes() {
115
+ const nodes = [];
116
+ const walk = (container) => {
117
+ const children = container.querySelectorAll(
118
+ ":scope > .midwest-tree-node"
119
+ );
120
+ for (const child of children) {
121
+ nodes.push(child);
122
+ if (child.getAttribute("aria-expanded") === "true") {
123
+ const group = child.querySelector(":scope > .tree-node-children");
124
+ if (group)
125
+ walk(group);
126
+ }
127
+ }
128
+ };
129
+ walk(this.element);
130
+ return nodes;
131
+ }
132
+ moveFocus(current, direction) {
133
+ const visible = this.getVisibleNodes();
134
+ const index = visible.indexOf(current);
135
+ if (index === -1)
136
+ return;
137
+ const nextIndex = direction === "next" ? index + 1 : index - 1;
138
+ if (nextIndex >= 0 && nextIndex < visible.length) {
139
+ this.focusNode(visible[nextIndex]);
140
+ }
141
+ }
142
+ handleArrowRight(node) {
143
+ const isExpanded = node.getAttribute("aria-expanded");
144
+ if (isExpanded === "false") {
145
+ node.setAttribute("aria-expanded", "true");
146
+ } else if (isExpanded === "true") {
147
+ const firstChild = node.querySelector(
148
+ ":scope > .tree-node-children > .midwest-tree-node"
149
+ );
150
+ if (firstChild)
151
+ this.focusNode(firstChild);
152
+ }
153
+ }
154
+ handleArrowLeft(node) {
155
+ const isExpanded = node.getAttribute("aria-expanded");
156
+ if (isExpanded === "true") {
157
+ node.setAttribute("aria-expanded", "false");
158
+ } else {
159
+ const parentGroup = node.parentElement;
160
+ if (parentGroup && parentGroup.classList.contains("tree-node-children")) {
161
+ const parentNode = parentGroup.closest(".midwest-tree-node");
162
+ if (parentNode)
163
+ this.focusNode(parentNode);
164
+ }
165
+ }
166
+ }
167
+ handleActivate(node) {
168
+ const checkbox = node.querySelector(
169
+ ":scope > .tree-node-trigger > .tree-node-checkbox"
170
+ );
171
+ if (checkbox) {
172
+ checkbox.checked = !checkbox.checked;
173
+ checkbox.dispatchEvent(new Event("change", { bubbles: true }));
174
+ return;
175
+ }
176
+ const expanded = node.getAttribute("aria-expanded");
177
+ if (expanded !== null) {
178
+ node.setAttribute("aria-expanded", String(expanded !== "true"));
179
+ }
180
+ }
181
+ focusNode(node) {
182
+ const current = this.element.querySelector(
183
+ '.midwest-tree-node[tabindex="0"]'
184
+ );
185
+ if (current)
186
+ current.setAttribute("tabindex", "-1");
187
+ node.setAttribute("tabindex", "0");
188
+ node.focus();
189
+ }
190
+ focusFirst() {
191
+ const first = this.element.querySelector(".midwest-tree-node");
192
+ if (first)
193
+ this.focusNode(first);
194
+ }
195
+ focusLast() {
196
+ const visible = this.getVisibleNodes();
197
+ if (visible.length > 0) {
198
+ this.focusNode(visible[visible.length - 1]);
199
+ }
200
+ }
201
+ }
202
+
203
+ export { TreeView as default };
204
+ //# sourceMappingURL=tree_view_component_controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree_view_component_controller.js","sources":["../../../../../../../app/components/midwest/tree_view_component/tree_view_component_controller.ts"],"sourcesContent":["import { Controller } from '@hotwired/stimulus'\n\nexport default class TreeView extends Controller<HTMLElement> {\n // ── Expand / Collapse ───────────────────────────────────────────────\n\n toggle (event: Event) {\n const chevron = (event.currentTarget as HTMLElement).closest('.tree-node-chevron')\n if (!chevron) return\n\n const node = chevron.closest('.midwest-tree-node') as HTMLElement | null\n if (!node) return\n\n const expanded = node.getAttribute('aria-expanded') === 'true'\n node.setAttribute('aria-expanded', String(!expanded))\n\n this.focusNode(node)\n }\n\n // ── Checkbox Cascading ──────────────────────────────────────────────\n\n checkboxChanged (event: Event) {\n const checkbox = event.target as HTMLInputElement\n const node = checkbox.closest('.midwest-tree-node') as HTMLElement | null\n if (!node) return\n\n // Cascade down: set all descendant checkboxes to match\n const descendants = node.querySelectorAll<HTMLInputElement>(\n '.tree-node-children .tree-node-checkbox'\n )\n for (const desc of descendants) {\n desc.checked = checkbox.checked\n desc.indeterminate = false\n }\n\n // Cascade up: update ancestor checkboxes\n this.updateAncestors(node)\n }\n\n private updateAncestors (node: HTMLElement) {\n const parentGroup = node.parentElement\n if (!parentGroup || !parentGroup.classList.contains('tree-node-children')) return\n\n const parentNode = parentGroup.closest('.midwest-tree-node') as HTMLElement | null\n if (!parentNode) return\n\n const parentCheckbox = parentNode.querySelector<HTMLInputElement>(\n ':scope > .tree-node-trigger > .tree-node-checkbox'\n )\n if (!parentCheckbox) return\n\n const childCheckboxes = parentGroup.querySelectorAll<HTMLInputElement>(\n ':scope > .midwest-tree-node > .tree-node-trigger > .tree-node-checkbox'\n )\n\n const total = childCheckboxes.length\n let checked = 0\n let indeterminate = 0\n\n for (const cb of childCheckboxes) {\n if (cb.indeterminate) indeterminate++\n else if (cb.checked) checked++\n }\n\n if (indeterminate > 0 || (checked > 0 && checked < total)) {\n parentCheckbox.checked = false\n parentCheckbox.indeterminate = true\n } else if (checked === total) {\n parentCheckbox.checked = true\n parentCheckbox.indeterminate = false\n } else {\n parentCheckbox.checked = false\n parentCheckbox.indeterminate = false\n }\n\n this.updateAncestors(parentNode)\n }\n\n // ── Keyboard Navigation (WAI-ARIA TreeView) ────────────────────────\n\n connect () {\n this.element.addEventListener('keydown', this.handleKeydown)\n\n // Set the first node to tabindex 0 for initial focus\n const firstNode = this.element.querySelector<HTMLElement>('.midwest-tree-node')\n if (firstNode) {\n firstNode.setAttribute('tabindex', '0')\n }\n }\n\n disconnect () {\n this.element.removeEventListener('keydown', this.handleKeydown)\n }\n\n private handleKeydown = (event: KeyboardEvent) => {\n const target = (event.target as HTMLElement).closest('.midwest-tree-node') as HTMLElement | null\n if (!target) return\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault()\n this.moveFocus(target, 'next')\n break\n case 'ArrowUp':\n event.preventDefault()\n this.moveFocus(target, 'previous')\n break\n case 'ArrowRight':\n event.preventDefault()\n this.handleArrowRight(target)\n break\n case 'ArrowLeft':\n event.preventDefault()\n this.handleArrowLeft(target)\n break\n case 'Home':\n event.preventDefault()\n this.focusFirst()\n break\n case 'End':\n event.preventDefault()\n this.focusLast()\n break\n case 'Enter':\n case ' ':\n event.preventDefault()\n this.handleActivate(target)\n break\n }\n }\n\n private getVisibleNodes (): HTMLElement[] {\n const nodes: HTMLElement[] = []\n\n const walk = (container: Element) => {\n const children = container.querySelectorAll<HTMLElement>(\n ':scope > .midwest-tree-node'\n )\n for (const child of children) {\n nodes.push(child)\n if (child.getAttribute('aria-expanded') === 'true') {\n const group = child.querySelector(':scope > .tree-node-children')\n if (group) walk(group)\n }\n }\n }\n\n walk(this.element)\n return nodes\n }\n\n private moveFocus (current: HTMLElement, direction: 'next' | 'previous') {\n const visible = this.getVisibleNodes()\n const index = visible.indexOf(current)\n if (index === -1) return\n\n const nextIndex = direction === 'next' ? index + 1 : index - 1\n if (nextIndex >= 0 && nextIndex < visible.length) {\n this.focusNode(visible[nextIndex])\n }\n }\n\n private handleArrowRight (node: HTMLElement) {\n const isExpanded = node.getAttribute('aria-expanded')\n\n if (isExpanded === 'false') {\n // Expand the node\n node.setAttribute('aria-expanded', 'true')\n } else if (isExpanded === 'true') {\n // Move focus to first child\n const firstChild = node.querySelector<HTMLElement>(\n ':scope > .tree-node-children > .midwest-tree-node'\n )\n if (firstChild) this.focusNode(firstChild)\n }\n // Leaf nodes: do nothing\n }\n\n private handleArrowLeft (node: HTMLElement) {\n const isExpanded = node.getAttribute('aria-expanded')\n\n if (isExpanded === 'true') {\n // Collapse the node\n node.setAttribute('aria-expanded', 'false')\n } else {\n // Move focus to parent node\n const parentGroup = node.parentElement\n if (parentGroup && parentGroup.classList.contains('tree-node-children')) {\n const parentNode = parentGroup.closest('.midwest-tree-node') as HTMLElement | null\n if (parentNode) this.focusNode(parentNode)\n }\n }\n }\n\n private handleActivate (node: HTMLElement) {\n const checkbox = node.querySelector<HTMLInputElement>(\n ':scope > .tree-node-trigger > .tree-node-checkbox'\n )\n if (checkbox) {\n checkbox.checked = !checkbox.checked\n checkbox.dispatchEvent(new Event('change', { bubbles: true }))\n return\n }\n\n // Toggle expand/collapse for branch nodes\n const expanded = node.getAttribute('aria-expanded')\n if (expanded !== null) {\n node.setAttribute('aria-expanded', String(expanded !== 'true'))\n }\n }\n\n private focusNode (node: HTMLElement) {\n // Remove tabindex from currently focused node\n const current = this.element.querySelector<HTMLElement>(\n '.midwest-tree-node[tabindex=\"0\"]'\n )\n if (current) current.setAttribute('tabindex', '-1')\n\n node.setAttribute('tabindex', '0')\n node.focus()\n }\n\n private focusFirst () {\n const first = this.element.querySelector<HTMLElement>('.midwest-tree-node')\n if (first) this.focusNode(first)\n }\n\n private focusLast () {\n const visible = this.getVisibleNodes()\n if (visible.length > 0) {\n this.focusNode(visible[visible.length - 1])\n }\n }\n}\n"],"names":[],"mappings":"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"}