basecoat-css 0.3.8 → 0.3.10-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/basecoat.css CHANGED
@@ -797,7 +797,7 @@
797
797
  /* Popover */
798
798
  @layer components {
799
799
  [data-popover] {
800
- @apply absolute bg-popover text-popover-foreground overflow-x-hidden overflow-y-auto rounded-md border shadow-md z-50 visible opacity-100 scale-100 min-w-full w-fit transition-all;
800
+ @apply absolute bg-popover text-popover-foreground overflow-x-hidden overflow-y-auto rounded-md border shadow-md z-50 visible opacity-100 scale-100 min-w-full w-max transition-all;
801
801
 
802
802
  &[aria-hidden='true'] {
803
803
  @apply invisible opacity-0 scale-95;
@@ -941,6 +941,14 @@
941
941
  }
942
942
  *:not(select).select {
943
943
  @apply relative inline-flex;
944
+
945
+ & > button {
946
+ @apply justify-between font-normal;
947
+
948
+ &[aria-invalid='true'] {
949
+ @apply ring-destructive/20 dark:ring-destructive/40 border-destructive;
950
+ }
951
+ }
944
952
 
945
953
  [data-popover] {
946
954
  @apply p-1;
@@ -1250,7 +1258,7 @@
1250
1258
  @apply relative;
1251
1259
 
1252
1260
  &:before {
1253
- @apply absolute content-[attr(data-tooltip)] bg-primary text-primary-foreground z-[60] truncate max-w-xs w-fit rounded-md px-3 py-1.5 text-xs invisible opacity-0 scale-95 transition-all pointer-events-none;
1261
+ @apply absolute content-[attr(data-tooltip)] bg-foreground text-background z-[60] truncate max-w-xs w-fit rounded-md px-3 py-1.5 text-xs invisible opacity-0 scale-95 transition-all pointer-events-none;
1254
1262
  }
1255
1263
  &:hover:before {
1256
1264
  @apply visible opacity-100 scale-100;
package/dist/js/all.js CHANGED
@@ -508,23 +508,31 @@
508
508
  const trigger = selectComponent.querySelector(':scope > button');
509
509
  const selectedLabel = trigger.querySelector(':scope > span');
510
510
  const popover = selectComponent.querySelector(':scope > [data-popover]');
511
- const listbox = popover.querySelector('[role="listbox"]');
511
+ const listbox = popover ? popover.querySelector('[role="listbox"]') : null;
512
512
  const input = selectComponent.querySelector(':scope > input[type="hidden"]');
513
513
  const filter = selectComponent.querySelector('header input[type="text"]');
514
+
514
515
  if (!trigger || !popover || !listbox || !input) {
515
516
  const missing = [];
516
517
  if (!trigger) missing.push('trigger');
517
518
  if (!popover) missing.push('popover');
518
519
  if (!listbox) missing.push('listbox');
519
- if (!input) missing.push('input');
520
+ if (!input) missing.push('input');
520
521
  console.error(`Select component initialisation failed. Missing element(s): ${missing.join(', ')}`, selectComponent);
521
522
  return;
522
523
  }
523
-
524
+
524
525
  const allOptions = Array.from(listbox.querySelectorAll('[role="option"]'));
525
526
  const options = allOptions.filter(opt => opt.getAttribute('aria-disabled') !== 'true');
526
527
  let visibleOptions = [...options];
527
528
  let activeIndex = -1;
529
+ const isMultiple = listbox.getAttribute('aria-multiselectable') === 'true';
530
+ let selectedValues = isMultiple ? new Set() : null;
531
+ let placeholder = null;
532
+
533
+ if (isMultiple) {
534
+ placeholder = selectComponent.dataset.placeholder || '';
535
+ }
528
536
 
529
537
  const setActiveOption = (index) => {
530
538
  if (activeIndex > -1 && options[activeIndex]) {
@@ -551,21 +559,90 @@
551
559
  return parseFloat(style.transitionDuration) > 0 || parseFloat(style.transitionDelay) > 0;
552
560
  };
553
561
 
554
- const updateValue = (option, triggerEvent = true) => {
555
- if (option) {
562
+ const syncMultipleInputs = () => {
563
+ if (!isMultiple) return;
564
+ const values = Array.from(selectedValues);
565
+ const inputs = Array.from(selectComponent.querySelectorAll(':scope > input[type="hidden"]'));
566
+ inputs.slice(1).forEach(inp => inp.remove());
567
+
568
+ if (values.length === 0) {
569
+ input.value = '';
570
+ } else {
571
+ input.value = values[0];
572
+ let insertAfter = input;
573
+ for (let i = 1; i < values.length; i++) {
574
+ const clone = input.cloneNode(true);
575
+ clone.removeAttribute('id');
576
+ clone.value = values[i];
577
+ insertAfter.after(clone);
578
+ insertAfter = clone;
579
+ }
580
+ }
581
+ };
582
+
583
+ const updateMultipleLabel = () => {
584
+ if (!isMultiple) return;
585
+ const selected = options.filter(opt => selectedValues.has(opt.dataset.value));
586
+ if (selected.length === 0) {
587
+ selectedLabel.textContent = placeholder;
588
+ selectedLabel.classList.add('text-muted-foreground');
589
+ } else {
590
+ selectedLabel.textContent = selected.map(opt => opt.dataset.label || opt.textContent.trim()).join(', ');
591
+ selectedLabel.classList.remove('text-muted-foreground');
592
+ }
593
+ };
594
+
595
+ const updateValue = (optionOrOptions, triggerEvent = true) => {
596
+ let value;
597
+
598
+ if (isMultiple) {
599
+ const opts = Array.isArray(optionOrOptions) ? optionOrOptions : [];
600
+ selectedValues = new Set(opts.map(opt => opt.dataset.value));
601
+ options.forEach(opt => {
602
+ if (selectedValues.has(opt.dataset.value)) {
603
+ opt.setAttribute('aria-selected', 'true');
604
+ } else {
605
+ opt.removeAttribute('aria-selected');
606
+ }
607
+ });
608
+ updateMultipleLabel();
609
+ syncMultipleInputs();
610
+ value = Array.from(selectedValues);
611
+ } else {
612
+ const option = optionOrOptions;
613
+ if (!option) return;
556
614
  selectedLabel.innerHTML = option.innerHTML;
557
615
  input.value = option.dataset.value;
558
- listbox.querySelector('[role="option"][aria-selected="true"]')?.removeAttribute('aria-selected');
559
- option.setAttribute('aria-selected', 'true');
560
-
561
- if (triggerEvent) {
562
- const event = new CustomEvent('change', {
563
- detail: { value: option.dataset.value },
564
- bubbles: true
565
- });
566
- selectComponent.dispatchEvent(event);
567
- }
616
+ options.forEach(opt => {
617
+ if (opt === option) {
618
+ opt.setAttribute('aria-selected', 'true');
619
+ } else {
620
+ opt.removeAttribute('aria-selected');
621
+ }
622
+ });
623
+ value = option.dataset.value;
624
+ }
625
+
626
+ if (triggerEvent) {
627
+ selectComponent.dispatchEvent(new CustomEvent('change', {
628
+ detail: { value },
629
+ bubbles: true
630
+ }));
631
+ }
632
+ };
633
+
634
+ const toggleMultipleValue = (value, triggerEvent = true) => {
635
+ if (!isMultiple || value == null) return;
636
+
637
+ const newValues = new Set(selectedValues);
638
+ if (newValues.has(value)) {
639
+ newValues.delete(value);
640
+ } else {
641
+ newValues.add(value);
568
642
  }
643
+
644
+ const selectedOptions = options.filter(opt => newValues.has(opt.dataset.value));
645
+ updateValue(selectedOptions, triggerEvent);
569
646
  };
570
647
 
571
648
  const closePopover = (focusOnTrigger = true) => {
@@ -606,7 +683,27 @@
606
683
 
607
684
  const selectByValue = (value) => {
608
685
  const option = options.find(opt => opt.dataset.value === value);
609
- selectOption(option);
686
+ if (isMultiple) {
687
+ if (value != null && selectedValues.has(value)) return;
688
+ if (option && value != null) {
689
+ const newValues = new Set(selectedValues);
690
+ newValues.add(value);
691
+ const selectedOptions = options.filter(opt => newValues.has(opt.dataset.value));
692
+ updateValue(selectedOptions);
693
+ }
694
+ } else {
695
+ selectOption(option);
696
+ }
697
+ };
698
+
699
+ const selectAll = () => {
700
+ if (!isMultiple) return;
701
+ updateValue(options.filter(opt => opt.dataset.value != null));
702
+ };
703
+
704
+ const selectNone = () => {
705
+ if (!isMultiple) return;
706
+ updateValue([]);
610
707
  };
611
708
 
612
709
  if (filter) {
@@ -642,13 +739,32 @@
642
739
  filter.addEventListener('input', filterOptions);
643
740
  }
644
741
 
645
- let initialOption = options.find(opt => opt.dataset.value === input.value);
646
-
647
- if (!initialOption) {
648
- initialOption = options.find(opt => opt.dataset.value !== undefined) ?? options[0];
649
- }
742
+ if (isMultiple) {
743
+ const validValues = new Set(options.map(opt => opt.dataset.value).filter(v => v != null));
744
+ const inputs = Array.from(selectComponent.querySelectorAll(':scope > input[type="hidden"]'));
745
+ const initialValues = inputs
746
+ .map(inp => inp.value)
747
+ .filter(v => v != null && validValues.has(v));
748
+
749
+ let initialOptions;
750
+ if (initialValues.length > 0) {
751
+ initialOptions = options.filter(opt => initialValues.includes(opt.dataset.value));
752
+ } else {
753
+ initialOptions = options.filter(opt => opt.getAttribute('aria-selected') === 'true');
754
+ }
755
+
756
+ updateValue(initialOptions, false);
757
+ } else {
758
+ let initialOption = options.find(opt => opt.dataset.value === input.value);
650
759
 
651
- updateValue(initialOption, false);
760
+ if (!initialOption) {
761
+ initialOption = options.find(opt => opt.dataset.value !== undefined) ?? options[0];
762
+ }
763
+
764
+ if (initialOption) {
765
+ updateValue(initialOption, false);
766
+ }
767
+ }
652
768
 
653
769
  const handleKeyNavigation = (event) => {
654
770
  const isPopoverOpen = popover.getAttribute('aria-hidden') === 'false';
@@ -674,7 +790,11 @@
674
790
 
675
791
  if (event.key === 'Enter') {
676
792
  if (activeIndex > -1) {
677
- selectOption(options[activeIndex]);
793
+ if (isMultiple) {
794
+ toggleMultipleValue(options[activeIndex].dataset.value);
795
+ } else {
796
+ selectOption(options[activeIndex]);
797
+ }
678
798
  }
679
799
  return;
680
800
  }
@@ -773,7 +893,17 @@
773
893
  listbox.addEventListener('click', (event) => {
774
894
  const clickedOption = event.target.closest('[role="option"]');
775
895
  if (clickedOption) {
776
- selectOption(clickedOption);
896
+ if (isMultiple) {
897
+ toggleMultipleValue(clickedOption.dataset.value);
898
+ setActiveOption(options.indexOf(clickedOption));
899
+ if (filter) {
900
+ filter.focus();
901
+ } else {
902
+ trigger.focus();
903
+ }
904
+ } else {
905
+ selectOption(clickedOption);
906
+ }
777
907
  }
778
908
  });
779
909
 
@@ -790,8 +920,12 @@
790
920
  });
791
921
 
792
922
  popover.setAttribute('aria-hidden', 'true');
793
-
923
+
794
924
  selectComponent.selectByValue = selectByValue;
925
+ if (isMultiple) {
926
+ selectComponent.selectAll = selectAll;
927
+ selectComponent.selectNone = selectNone;
928
+ }
795
929
  selectComponent.dataset.selectInitialized = true;
796
930
  selectComponent.dispatchEvent(new CustomEvent('basecoat:initialized'));
797
931
  };
@@ -1 +1 @@
1
- (()=>{const e={};let t=null;const n=()=>{Object.entries(e).forEach((([e,{selector:t,init:n}])=>{document.querySelectorAll(t).forEach(n)}))},i=t=>{t.nodeType===Node.ELEMENT_NODE&&Object.entries(e).forEach((([e,{selector:n,init:i}])=>{t.matches(n)&&i(t),t.querySelectorAll(n).forEach(i)}))},a=()=>{t||(t=new MutationObserver((e=>{e.forEach((e=>{e.addedNodes.forEach(i)}))})),t.observe(document.body,{childList:!0,subtree:!0}))};window.basecoat={register:(t,n,i)=>{e[t]={selector:n,init:i}},init:t=>{const n=e[t];if(!n)return void console.warn(`Component '${t}' not found in registry`);const i=`data-${t}-initialized`;document.querySelectorAll(`[${i}]`).forEach((e=>{e.removeAttribute(i)})),document.querySelectorAll(n.selector).forEach(n.init)},initAll:()=>{Object.entries(e).forEach((([e,{selector:t}])=>{const n=`data-${e}-initialized`;document.querySelectorAll(`[${n}]`).forEach((e=>{e.removeAttribute(n)}))})),n()},start:a,stop:()=>{t&&(t.disconnect(),t=null)}},document.addEventListener("DOMContentLoaded",(()=>{n(),a()}))})(),(()=>{const e=e=>{const t=e.querySelector("header input"),n=e.querySelector('[role="menu"]');if(!t||!n){const i=[];return t||i.push("input"),n||i.push("menu"),void console.error(`Command component initialization failed. Missing element(s): ${i.join(", ")}`,e)}const i=Array.from(n.querySelectorAll('[role="menuitem"]')),a=i.filter((e=>!e.hasAttribute("disabled")&&"true"!==e.getAttribute("aria-disabled")));let o=[...a],r=-1;const s=e=>{if(r>-1&&a[r]&&a[r].classList.remove("active"),r=e,r>-1){const e=a[r];e.classList.add("active"),e.id?t.setAttribute("aria-activedescendant",e.id):t.removeAttribute("aria-activedescendant")}else t.removeAttribute("aria-activedescendant")};t.addEventListener("input",(()=>{const e=t.value.trim().toLowerCase();s(-1),o=[],i.forEach((t=>{if(t.hasAttribute("data-force"))return t.setAttribute("aria-hidden","false"),void(a.includes(t)&&o.push(t));const n=(t.dataset.filter||t.textContent).trim().toLowerCase(),i=(t.dataset.keywords||"").toLowerCase().split(/[\s,]+/).filter(Boolean).some((t=>t.includes(e))),r=n.includes(e)||i;t.setAttribute("aria-hidden",String(!r)),r&&a.includes(t)&&o.push(t)})),o.length>0&&(s(a.indexOf(o[0])),o[0].scrollIntoView({block:"nearest"}))}));n.addEventListener("mousemove",(e=>{const t=e.target.closest('[role="menuitem"]');if(t&&o.includes(t)){const e=a.indexOf(t);e!==r&&s(e)}})),n.addEventListener("click",(t=>{const n=t.target.closest('[role="menuitem"]');if(n&&o.includes(n)){const t=e.closest("dialog.command-dialog");t&&!n.hasAttribute("data-keep-command-open")&&t.close()}})),t.addEventListener("keydown",(e=>{if(!["ArrowDown","ArrowUp","Enter","Home","End"].includes(e.key))return;if("Enter"===e.key)return e.preventDefault(),void(r>-1&&a[r]?.click());if(0===o.length)return;e.preventDefault();const t=r>-1?o.indexOf(a[r]):-1;let n=t;switch(e.key){case"ArrowDown":t<o.length-1&&(n=t+1);break;case"ArrowUp":t>0?n=t-1:-1===t&&(n=0);break;case"Home":n=0;break;case"End":n=o.length-1}if(n!==t){const e=o[n];s(a.indexOf(e)),e.scrollIntoView({block:"nearest",behavior:"smooth"})}})),o.length>0&&(s(a.indexOf(o[0])),o[0].scrollIntoView({block:"nearest"})),e.dataset.commandInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("command",".command:not([data-command-initialized])",e)})(),(()=>{const e=e=>{const t=e.querySelector(":scope > button"),n=e.querySelector(":scope > [data-popover]"),i=n.querySelector('[role="menu"]');if(!t||!i||!n){const a=[];return t||a.push("trigger"),i||a.push("menu"),n||a.push("popover"),void console.error(`Dropdown menu initialisation failed. Missing element(s): ${a.join(", ")}`,e)}let a=[],o=-1;const r=(e=!0)=>{"false"!==t.getAttribute("aria-expanded")&&(t.setAttribute("aria-expanded","false"),t.removeAttribute("aria-activedescendant"),n.setAttribute("aria-hidden","true"),e&&t.focus(),d(-1))},s=(o=!1)=>{document.dispatchEvent(new CustomEvent("basecoat:popover",{detail:{source:e}})),t.setAttribute("aria-expanded","true"),n.setAttribute("aria-hidden","false"),a=Array.from(i.querySelectorAll('[role^="menuitem"]')).filter((e=>!e.hasAttribute("disabled")&&"true"!==e.getAttribute("aria-disabled"))),a.length>0&&o&&("first"===o?d(0):"last"===o&&d(a.length-1))},d=e=>{if(o>-1&&a[o]&&a[o].classList.remove("active"),o=e,o>-1&&a[o]){const e=a[o];e.classList.add("active"),t.setAttribute("aria-activedescendant",e.id)}else t.removeAttribute("aria-activedescendant")};t.addEventListener("click",(()=>{"true"===t.getAttribute("aria-expanded")?r():s(!1)})),e.addEventListener("keydown",(e=>{const n="true"===t.getAttribute("aria-expanded");if("Escape"===e.key)return void(n&&r());if(!n)return void(["Enter"," "].includes(e.key)?(e.preventDefault(),s(!1)):"ArrowDown"===e.key?(e.preventDefault(),s("first")):"ArrowUp"===e.key&&(e.preventDefault(),s("last")));if(0===a.length)return;let i=o;switch(e.key){case"ArrowDown":e.preventDefault(),i=-1===o?0:Math.min(o+1,a.length-1);break;case"ArrowUp":e.preventDefault(),i=-1===o?a.length-1:Math.max(o-1,0);break;case"Home":e.preventDefault(),i=0;break;case"End":e.preventDefault(),i=a.length-1;break;case"Enter":case" ":return e.preventDefault(),a[o]?.click(),void r()}i!==o&&d(i)})),i.addEventListener("mousemove",(e=>{const t=e.target.closest('[role^="menuitem"]');if(t&&a.includes(t)){const e=a.indexOf(t);e!==o&&d(e)}})),i.addEventListener("mouseleave",(()=>{d(-1)})),i.addEventListener("click",(e=>{e.target.closest('[role^="menuitem"]')&&r()})),document.addEventListener("click",(t=>{e.contains(t.target)||r()})),document.addEventListener("basecoat:popover",(t=>{t.detail.source!==e&&r(!1)})),e.dataset.dropdownMenuInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("dropdown-menu",".dropdown-menu:not([data-dropdown-menu-initialized])",e)})(),(()=>{const e=e=>{const t=e.querySelector(":scope > button"),n=e.querySelector(":scope > [data-popover]");if(!t||!n){const i=[];return t||i.push("trigger"),n||i.push("content"),void console.error(`Popover initialisation failed. Missing element(s): ${i.join(", ")}`,e)}const i=(e=!0)=>{"false"!==t.getAttribute("aria-expanded")&&(t.setAttribute("aria-expanded","false"),n.setAttribute("aria-hidden","true"),e&&t.focus())};t.addEventListener("click",(()=>{"true"===t.getAttribute("aria-expanded")?i():(()=>{document.dispatchEvent(new CustomEvent("basecoat:popover",{detail:{source:e}}));const i=n.querySelector("[autofocus]");i&&n.addEventListener("transitionend",(()=>{i.focus()}),{once:!0}),t.setAttribute("aria-expanded","true"),n.setAttribute("aria-hidden","false")})()})),e.addEventListener("keydown",(e=>{"Escape"===e.key&&i()})),document.addEventListener("click",(t=>{e.contains(t.target)||i()})),document.addEventListener("basecoat:popover",(t=>{t.detail.source!==e&&i(!1)})),e.dataset.popoverInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("popover",".popover:not([data-popover-initialized])",e)})(),(()=>{const e=e=>{const t=e.querySelector(":scope > button"),n=t.querySelector(":scope > span"),i=e.querySelector(":scope > [data-popover]"),a=i.querySelector('[role="listbox"]'),o=e.querySelector(':scope > input[type="hidden"]'),r=e.querySelector('header input[type="text"]');if(!(t&&i&&a&&o)){const n=[];return t||n.push("trigger"),i||n.push("popover"),a||n.push("listbox"),o||n.push("input"),void console.error(`Select component initialisation failed. Missing element(s): ${n.join(", ")}`,e)}const s=Array.from(a.querySelectorAll('[role="option"]')),d=s.filter((e=>"true"!==e.getAttribute("aria-disabled")));let c=[...d],l=-1;const u=e=>{if(l>-1&&d[l]&&d[l].classList.remove("active"),l=e,l>-1){const e=d[l];e.classList.add("active"),e.id?t.setAttribute("aria-activedescendant",e.id):t.removeAttribute("aria-activedescendant")}else t.removeAttribute("aria-activedescendant")},v=()=>{const e=getComputedStyle(i);return parseFloat(e.transitionDuration)>0||parseFloat(e.transitionDelay)>0},p=(t,i=!0)=>{if(t&&(n.innerHTML=t.innerHTML,o.value=t.dataset.value,a.querySelector('[role="option"][aria-selected="true"]')?.removeAttribute("aria-selected"),t.setAttribute("aria-selected","true"),i)){const n=new CustomEvent("change",{detail:{value:t.dataset.value},bubbles:!0});e.dispatchEvent(n)}},m=(e=!0)=>{if("true"!==i.getAttribute("aria-hidden")){if(r){const e=()=>{r.value="",c=[...d],s.forEach((e=>e.setAttribute("aria-hidden","false")))};v()?i.addEventListener("transitionend",e,{once:!0}):e()}e&&t.focus(),i.setAttribute("aria-hidden","true"),t.setAttribute("aria-expanded","false"),u(-1)}},b=e=>{if(!e)return;const t=o.value,n=e.dataset.value;null!=n&&n!==t&&p(e),m()};if(r){const e=()=>{const e=r.value.trim().toLowerCase();u(-1),c=[],s.forEach((t=>{if(t.hasAttribute("data-force"))return t.setAttribute("aria-hidden","false"),void(d.includes(t)&&c.push(t));const n=(t.dataset.filter||t.textContent).trim().toLowerCase(),i=(t.dataset.keywords||"").toLowerCase().split(/[\s,]+/).filter(Boolean).some((t=>t.includes(e))),a=n.includes(e)||i;t.setAttribute("aria-hidden",String(!a)),a&&d.includes(t)&&c.push(t)}))};r.addEventListener("input",e)}let h=d.find((e=>e.dataset.value===o.value));h||(h=d.find((e=>void 0!==e.dataset.value))??d[0]),p(h,!1);const f=e=>{const n="false"===i.getAttribute("aria-hidden");if(!["ArrowDown","ArrowUp","Enter","Home","End","Escape"].includes(e.key))return;if(!n)return void("Enter"!==e.key&&"Escape"!==e.key&&(e.preventDefault(),t.click()));if(e.preventDefault(),"Escape"===e.key)return void m();if("Enter"===e.key)return void(l>-1&&b(d[l]));if(0===c.length)return;const a=l>-1?c.indexOf(d[l]):-1;let o=a;switch(e.key){case"ArrowDown":a<c.length-1&&(o=a+1);break;case"ArrowUp":a>0?o=a-1:-1===a&&(o=0);break;case"Home":o=0;break;case"End":o=c.length-1}if(o!==a){const e=c[o];u(d.indexOf(e)),e.scrollIntoView({block:"nearest",behavior:"smooth"})}};a.addEventListener("mousemove",(e=>{const t=e.target.closest('[role="option"]');if(t&&c.includes(t)){const e=d.indexOf(t);e!==l&&u(e)}})),a.addEventListener("mouseleave",(()=>{const e=a.querySelector('[role="option"][aria-selected="true"]');u(e?d.indexOf(e):-1)})),t.addEventListener("keydown",f),r&&r.addEventListener("keydown",f);t.addEventListener("click",(()=>{"true"===t.getAttribute("aria-expanded")?m():(()=>{document.dispatchEvent(new CustomEvent("basecoat:popover",{detail:{source:e}})),r&&(v()?i.addEventListener("transitionend",(()=>{r.focus()}),{once:!0}):r.focus()),i.setAttribute("aria-hidden","false"),t.setAttribute("aria-expanded","true");const n=a.querySelector('[role="option"][aria-selected="true"]');n&&(u(d.indexOf(n)),n.scrollIntoView({block:"nearest"}))})()})),a.addEventListener("click",(e=>{const t=e.target.closest('[role="option"]');t&&b(t)})),document.addEventListener("click",(t=>{e.contains(t.target)||m(!1)})),document.addEventListener("basecoat:popover",(t=>{t.detail.source!==e&&m(!1)})),i.setAttribute("aria-hidden","true"),e.selectByValue=e=>{const t=d.find((t=>t.dataset.value===e));b(t)},e.dataset.selectInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("select","div.select:not([data-select-initialized])",e)})(),(()=>{if(!window.history.__basecoatPatched){const e=window.history.pushState;window.history.pushState=function(...t){e.apply(this,t),window.dispatchEvent(new Event("basecoat:locationchange"))};const t=window.history.replaceState;window.history.replaceState=function(...e){t.apply(this,e),window.dispatchEvent(new Event("basecoat:locationchange"))},window.history.__basecoatPatched=!0}const e=e=>{const t="false"!==e.dataset.initialOpen,n="true"===e.dataset.initialMobileOpen,i=parseInt(e.dataset.breakpoint)||768;let a=i>0?window.innerWidth>=i?t:n:t;const o=()=>{const t=window.location.pathname.replace(/\/$/,"");e.querySelectorAll("a").forEach((e=>{if(e.hasAttribute("data-ignore-current"))return;new URL(e.href).pathname.replace(/\/$/,"")===t?e.setAttribute("aria-current","page"):e.removeAttribute("aria-current")}))},r=()=>{e.setAttribute("aria-hidden",!a),a?e.removeAttribute("inert"):e.setAttribute("inert","")},s=e=>{a=e,r()},d=e.id;document.addEventListener("basecoat:sidebar",(e=>{if(!e.detail?.id||e.detail.id===d)switch(e.detail?.action){case"open":s(!0);break;case"close":s(!1);break;default:s(!a)}})),e.addEventListener("click",(t=>{const n=t.target,a=e.querySelector("nav");if(window.innerWidth<i&&n.closest("a, button")&&!n.closest("[data-keep-mobile-sidebar-open]"))return document.activeElement&&document.activeElement.blur(),void s(!1);(n===e||a&&!a.contains(n))&&(document.activeElement&&document.activeElement.blur(),s(!1))})),window.addEventListener("popstate",o),window.addEventListener("basecoat:locationchange",o),r(),o(),e.dataset.sidebarInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("sidebar",".sidebar:not([data-sidebar-initialized])",e)})(),(()=>{const e=e=>{const t=e.querySelector('[role="tablist"]');if(!t)return;const n=Array.from(t.querySelectorAll('[role="tab"]')),i=n.map((e=>document.getElementById(e.getAttribute("aria-controls")))).filter(Boolean),a=e=>{n.forEach(((e,t)=>{e.setAttribute("aria-selected","false"),e.setAttribute("tabindex","-1"),i[t]&&(i[t].hidden=!0)})),e.setAttribute("aria-selected","true"),e.setAttribute("tabindex","0");const t=document.getElementById(e.getAttribute("aria-controls"));t&&(t.hidden=!1)};t.addEventListener("click",(e=>{const t=e.target.closest('[role="tab"]');t&&a(t)})),t.addEventListener("keydown",(e=>{const t=e.target;if(!n.includes(t))return;let i;const o=n.indexOf(t);switch(e.key){case"ArrowRight":i=n[(o+1)%n.length];break;case"ArrowLeft":i=n[(o-1+n.length)%n.length];break;case"Home":i=n[0];break;case"End":i=n[n.length-1];break;default:return}e.preventDefault(),a(i),i.focus()})),e.dataset.tabsInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("tabs",".tabs:not([data-tabs-initialized])",e)})(),(()=>{let e;const t=new WeakMap;let n=!1;const i={success:'<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg>',error:'<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/></svg>',info:'<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>',warning:'<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>'};function a(e){if(e.dataset.toastInitialized)return;const i=parseInt(e.dataset.duration),a=-1!==i?i||("error"===e.dataset.category?5e3:3e3):-1,o={remainingTime:a,timeoutId:null,startTime:null};-1!==a&&(n?o.timeoutId=null:(o.startTime=Date.now(),o.timeoutId=setTimeout((()=>s(e)),a))),t.set(e,o),e.dataset.toastInitialized="true"}function o(){n||(n=!0,e.querySelectorAll('.toast:not([aria-hidden="true"])').forEach((e=>{if(!t.has(e))return;const n=t.get(e);n.timeoutId&&(clearTimeout(n.timeoutId),n.timeoutId=null,n.remainingTime-=Date.now()-n.startTime)})))}function r(){n&&(n=!1,e.querySelectorAll('.toast:not([aria-hidden="true"])').forEach((e=>{if(!t.has(e))return;const n=t.get(e);-1===n.remainingTime||n.timeoutId||(n.remainingTime>0?(n.startTime=Date.now(),n.timeoutId=setTimeout((()=>s(e)),n.remainingTime)):s(e))})))}function s(e){if(!t.has(e))return;const n=t.get(e);clearTimeout(n.timeoutId),t.delete(e),e.contains(document.activeElement)&&document.activeElement.blur(),e.setAttribute("aria-hidden","true"),e.addEventListener("transitionend",(()=>e.remove()),{once:!0})}document.addEventListener("basecoat:toast",(t=>{if(!e)return void console.error("Cannot create toast: toaster container not found on page.");const n=function(e){const{category:t="info",title:n,description:a,action:o,cancel:r,duration:s,icon:d}=e,c=d||t&&i[t]||"",l=n?`<h2>${n}</h2>`:"",u=a?`<p>${a}</p>`:"",v=o?.href?`<a href="${o.href}" class="btn" data-toast-action>${o.label}</a>`:o?.onclick?`<button type="button" class="btn" data-toast-action onclick="${o.onclick}">${o.label}</button>`:"",p=r?`<button type="button" class="btn-outline h-6 text-xs px-2.5 rounded-sm" data-toast-cancel onclick="${r?.onclick}">${r.label}</button>`:"",m=`\n <div\n class="toast"\n role="${"error"===t?"alert":"status"}"\n aria-atomic="true"\n ${t?`data-category="${t}"`:""}\n ${void 0!==s?`data-duration="${s}"`:""}\n >\n <div class="toast-content">\n ${c}\n <section>\n ${l}\n ${u}\n </section>\n ${v||p?`<footer>${v}${p}</footer>`:""}\n </div>\n </div>\n </div>\n `,b=document.createElement("template");return b.innerHTML=m.trim(),b.content.firstChild}(t.detail?.config||{});e.appendChild(n)})),window.basecoat&&(window.basecoat.register("toaster","#toaster:not([data-toaster-initialized])",(function(t){t.dataset.toasterInitialized||(e=t,e.addEventListener("mouseenter",o),e.addEventListener("mouseleave",r),e.addEventListener("click",(e=>{const t=e.target.closest(".toast footer a"),n=e.target.closest(".toast footer button");(t||n)&&s(e.target.closest(".toast"))})),e.querySelectorAll(".toast:not([data-toast-initialized])").forEach(a),e.dataset.toasterInitialized="true",e.dispatchEvent(new CustomEvent("basecoat:initialized")))})),window.basecoat.register("toast",".toast:not([data-toast-initialized])",a))})();
1
+ (()=>{const e={};let t=null;const n=()=>{Object.entries(e).forEach((([e,{selector:t,init:n}])=>{document.querySelectorAll(t).forEach(n)}))},a=t=>{t.nodeType===Node.ELEMENT_NODE&&Object.entries(e).forEach((([e,{selector:n,init:a}])=>{t.matches(n)&&a(t),t.querySelectorAll(n).forEach(a)}))},i=()=>{t||(t=new MutationObserver((e=>{e.forEach((e=>{e.addedNodes.forEach(a)}))})),t.observe(document.body,{childList:!0,subtree:!0}))};window.basecoat={register:(t,n,a)=>{e[t]={selector:n,init:a}},init:t=>{const n=e[t];if(!n)return void console.warn(`Component '${t}' not found in registry`);const a=`data-${t}-initialized`;document.querySelectorAll(`[${a}]`).forEach((e=>{e.removeAttribute(a)})),document.querySelectorAll(n.selector).forEach(n.init)},initAll:()=>{Object.entries(e).forEach((([e,{selector:t}])=>{const n=`data-${e}-initialized`;document.querySelectorAll(`[${n}]`).forEach((e=>{e.removeAttribute(n)}))})),n()},start:i,stop:()=>{t&&(t.disconnect(),t=null)}},document.addEventListener("DOMContentLoaded",(()=>{n(),i()}))})(),(()=>{const e=e=>{const t=e.querySelector("header input"),n=e.querySelector('[role="menu"]');if(!t||!n){const a=[];return t||a.push("input"),n||a.push("menu"),void console.error(`Command component initialization failed. Missing element(s): ${a.join(", ")}`,e)}const a=Array.from(n.querySelectorAll('[role="menuitem"]')),i=a.filter((e=>!e.hasAttribute("disabled")&&"true"!==e.getAttribute("aria-disabled")));let r=[...i],o=-1;const s=e=>{if(o>-1&&i[o]&&i[o].classList.remove("active"),o=e,o>-1){const e=i[o];e.classList.add("active"),e.id?t.setAttribute("aria-activedescendant",e.id):t.removeAttribute("aria-activedescendant")}else t.removeAttribute("aria-activedescendant")};t.addEventListener("input",(()=>{const e=t.value.trim().toLowerCase();s(-1),r=[],a.forEach((t=>{if(t.hasAttribute("data-force"))return t.setAttribute("aria-hidden","false"),void(i.includes(t)&&r.push(t));const n=(t.dataset.filter||t.textContent).trim().toLowerCase(),a=(t.dataset.keywords||"").toLowerCase().split(/[\s,]+/).filter(Boolean).some((t=>t.includes(e))),o=n.includes(e)||a;t.setAttribute("aria-hidden",String(!o)),o&&i.includes(t)&&r.push(t)})),r.length>0&&(s(i.indexOf(r[0])),r[0].scrollIntoView({block:"nearest"}))}));n.addEventListener("mousemove",(e=>{const t=e.target.closest('[role="menuitem"]');if(t&&r.includes(t)){const e=i.indexOf(t);e!==o&&s(e)}})),n.addEventListener("click",(t=>{const n=t.target.closest('[role="menuitem"]');if(n&&r.includes(n)){const t=e.closest("dialog.command-dialog");t&&!n.hasAttribute("data-keep-command-open")&&t.close()}})),t.addEventListener("keydown",(e=>{if(!["ArrowDown","ArrowUp","Enter","Home","End"].includes(e.key))return;if("Enter"===e.key)return e.preventDefault(),void(o>-1&&i[o]?.click());if(0===r.length)return;e.preventDefault();const t=o>-1?r.indexOf(i[o]):-1;let n=t;switch(e.key){case"ArrowDown":t<r.length-1&&(n=t+1);break;case"ArrowUp":t>0?n=t-1:-1===t&&(n=0);break;case"Home":n=0;break;case"End":n=r.length-1}if(n!==t){const e=r[n];s(i.indexOf(e)),e.scrollIntoView({block:"nearest",behavior:"smooth"})}})),r.length>0&&(s(i.indexOf(r[0])),r[0].scrollIntoView({block:"nearest"})),e.dataset.commandInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("command",".command:not([data-command-initialized])",e)})(),(()=>{const e=e=>{const t=e.querySelector(":scope > button"),n=e.querySelector(":scope > [data-popover]"),a=n.querySelector('[role="menu"]');if(!t||!a||!n){const i=[];return t||i.push("trigger"),a||i.push("menu"),n||i.push("popover"),void console.error(`Dropdown menu initialisation failed. Missing element(s): ${i.join(", ")}`,e)}let i=[],r=-1;const o=(e=!0)=>{"false"!==t.getAttribute("aria-expanded")&&(t.setAttribute("aria-expanded","false"),t.removeAttribute("aria-activedescendant"),n.setAttribute("aria-hidden","true"),e&&t.focus(),d(-1))},s=(r=!1)=>{document.dispatchEvent(new CustomEvent("basecoat:popover",{detail:{source:e}})),t.setAttribute("aria-expanded","true"),n.setAttribute("aria-hidden","false"),i=Array.from(a.querySelectorAll('[role^="menuitem"]')).filter((e=>!e.hasAttribute("disabled")&&"true"!==e.getAttribute("aria-disabled"))),i.length>0&&r&&("first"===r?d(0):"last"===r&&d(i.length-1))},d=e=>{if(r>-1&&i[r]&&i[r].classList.remove("active"),r=e,r>-1&&i[r]){const e=i[r];e.classList.add("active"),t.setAttribute("aria-activedescendant",e.id)}else t.removeAttribute("aria-activedescendant")};t.addEventListener("click",(()=>{"true"===t.getAttribute("aria-expanded")?o():s(!1)})),e.addEventListener("keydown",(e=>{const n="true"===t.getAttribute("aria-expanded");if("Escape"===e.key)return void(n&&o());if(!n)return void(["Enter"," "].includes(e.key)?(e.preventDefault(),s(!1)):"ArrowDown"===e.key?(e.preventDefault(),s("first")):"ArrowUp"===e.key&&(e.preventDefault(),s("last")));if(0===i.length)return;let a=r;switch(e.key){case"ArrowDown":e.preventDefault(),a=-1===r?0:Math.min(r+1,i.length-1);break;case"ArrowUp":e.preventDefault(),a=-1===r?i.length-1:Math.max(r-1,0);break;case"Home":e.preventDefault(),a=0;break;case"End":e.preventDefault(),a=i.length-1;break;case"Enter":case" ":return e.preventDefault(),i[r]?.click(),void o()}a!==r&&d(a)})),a.addEventListener("mousemove",(e=>{const t=e.target.closest('[role^="menuitem"]');if(t&&i.includes(t)){const e=i.indexOf(t);e!==r&&d(e)}})),a.addEventListener("mouseleave",(()=>{d(-1)})),a.addEventListener("click",(e=>{e.target.closest('[role^="menuitem"]')&&o()})),document.addEventListener("click",(t=>{e.contains(t.target)||o()})),document.addEventListener("basecoat:popover",(t=>{t.detail.source!==e&&o(!1)})),e.dataset.dropdownMenuInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("dropdown-menu",".dropdown-menu:not([data-dropdown-menu-initialized])",e)})(),(()=>{const e=e=>{const t=e.querySelector(":scope > button"),n=e.querySelector(":scope > [data-popover]");if(!t||!n){const a=[];return t||a.push("trigger"),n||a.push("content"),void console.error(`Popover initialisation failed. Missing element(s): ${a.join(", ")}`,e)}const a=(e=!0)=>{"false"!==t.getAttribute("aria-expanded")&&(t.setAttribute("aria-expanded","false"),n.setAttribute("aria-hidden","true"),e&&t.focus())};t.addEventListener("click",(()=>{"true"===t.getAttribute("aria-expanded")?a():(()=>{document.dispatchEvent(new CustomEvent("basecoat:popover",{detail:{source:e}}));const a=n.querySelector("[autofocus]");a&&n.addEventListener("transitionend",(()=>{a.focus()}),{once:!0}),t.setAttribute("aria-expanded","true"),n.setAttribute("aria-hidden","false")})()})),e.addEventListener("keydown",(e=>{"Escape"===e.key&&a()})),document.addEventListener("click",(t=>{e.contains(t.target)||a()})),document.addEventListener("basecoat:popover",(t=>{t.detail.source!==e&&a(!1)})),e.dataset.popoverInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("popover",".popover:not([data-popover-initialized])",e)})(),(()=>{const e=e=>{const t=e.querySelector(":scope > button"),n=t.querySelector(":scope > span"),a=e.querySelector(":scope > [data-popover]"),i=a?a.querySelector('[role="listbox"]'):null,r=e.querySelector(':scope > input[type="hidden"]'),o=e.querySelector('header input[type="text"]');if(!(t&&a&&i&&r)){const n=[];return t||n.push("trigger"),a||n.push("popover"),i||n.push("listbox"),r||n.push("input"),void console.error(`Select component initialisation failed. Missing element(s): ${n.join(", ")}`,e)}const s=Array.from(i.querySelectorAll('[role="option"]')),d=s.filter((e=>"true"!==e.getAttribute("aria-disabled")));let c=[...d],l=-1;const u="true"===i.getAttribute("aria-multiselectable");let v=u?new Set:null,p=null;u&&(p=e.dataset.placeholder||"");const m=e=>{if(l>-1&&d[l]&&d[l].classList.remove("active"),l=e,l>-1){const e=d[l];e.classList.add("active"),e.id?t.setAttribute("aria-activedescendant",e.id):t.removeAttribute("aria-activedescendant")}else t.removeAttribute("aria-activedescendant")},f=()=>{const e=getComputedStyle(a);return parseFloat(e.transitionDuration)>0||parseFloat(e.transitionDelay)>0},h=(t,a=!0)=>{let i;if(u){const a=Array.isArray(t)?t:[];v=new Set(a.map((e=>e.dataset.value))),d.forEach((e=>{v.has(e.dataset.value)?e.setAttribute("aria-selected","true"):e.removeAttribute("aria-selected")})),(()=>{if(!u)return;const e=d.filter((e=>v.has(e.dataset.value)));0===e.length?(n.textContent=p,n.classList.add("text-muted-foreground")):(n.textContent=e.map((e=>e.dataset.label||e.textContent.trim())).join(", "),n.classList.remove("text-muted-foreground"))})(),(()=>{if(!u)return;const t=Array.from(v);if(Array.from(e.querySelectorAll(':scope > input[type="hidden"]')).slice(1).forEach((e=>e.remove())),0===t.length)r.value="";else{r.value=t[0];let e=r;for(let n=1;n<t.length;n++){const a=r.cloneNode(!0);a.removeAttribute("id"),a.value=t[n],e.after(a),e=a}}})(),i=Array.from(v)}else{const e=t;if(!e)return;n.innerHTML=e.innerHTML,r.value=e.dataset.value,d.forEach((t=>{t===e?t.setAttribute("aria-selected","true"):t.removeAttribute("aria-selected")})),i=e.dataset.value}a&&e.dispatchEvent(new CustomEvent("change",{detail:{value:i},bubbles:!0}))},b=(e,t=!0)=>{if(!u||null==e)return;const n=new Set(v);n.has(e)?n.delete(e):n.add(e);const a=d.filter((e=>n.has(e.dataset.value)));h(a,t)},w=(e=!0)=>{if("true"!==a.getAttribute("aria-hidden")){if(o){const e=()=>{o.value="",c=[...d],s.forEach((e=>e.setAttribute("aria-hidden","false")))};f()?a.addEventListener("transitionend",e,{once:!0}):e()}e&&t.focus(),a.setAttribute("aria-hidden","true"),t.setAttribute("aria-expanded","false"),m(-1)}},g=e=>{if(!e)return;const t=r.value,n=e.dataset.value;null!=n&&n!==t&&h(e),w()},E=()=>{u&&h(d.filter((e=>null!=e.dataset.value)))},A=()=>{u&&h([])};if(o){const e=()=>{const e=o.value.trim().toLowerCase();m(-1),c=[],s.forEach((t=>{if(t.hasAttribute("data-force"))return t.setAttribute("aria-hidden","false"),void(d.includes(t)&&c.push(t));const n=(t.dataset.filter||t.textContent).trim().toLowerCase(),a=(t.dataset.keywords||"").toLowerCase().split(/[\s,]+/).filter(Boolean).some((t=>t.includes(e))),i=n.includes(e)||a;t.setAttribute("aria-hidden",String(!i)),i&&d.includes(t)&&c.push(t)}))};o.addEventListener("input",e)}if(u){const t=new Set(d.map((e=>e.dataset.value)).filter((e=>null!=e))),n=Array.from(e.querySelectorAll(':scope > input[type="hidden"]')).map((e=>e.value)).filter((e=>null!=e&&t.has(e)));let a;a=n.length>0?d.filter((e=>n.includes(e.dataset.value))):d.filter((e=>"true"===e.getAttribute("aria-selected"))),h(a,!1)}else{let e=d.find((e=>e.dataset.value===r.value));e||(e=d.find((e=>void 0!==e.dataset.value))??d[0]),e&&h(e,!1)}const y=e=>{const n="false"===a.getAttribute("aria-hidden");if(!["ArrowDown","ArrowUp","Enter","Home","End","Escape"].includes(e.key))return;if(!n)return void("Enter"!==e.key&&"Escape"!==e.key&&(e.preventDefault(),t.click()));if(e.preventDefault(),"Escape"===e.key)return void w();if("Enter"===e.key)return void(l>-1&&(u?b(d[l].dataset.value):g(d[l])));if(0===c.length)return;const i=l>-1?c.indexOf(d[l]):-1;let r=i;switch(e.key){case"ArrowDown":i<c.length-1&&(r=i+1);break;case"ArrowUp":i>0?r=i-1:-1===i&&(r=0);break;case"Home":r=0;break;case"End":r=c.length-1}if(r!==i){const e=c[r];m(d.indexOf(e)),e.scrollIntoView({block:"nearest",behavior:"smooth"})}};i.addEventListener("mousemove",(e=>{const t=e.target.closest('[role="option"]');if(t&&c.includes(t)){const e=d.indexOf(t);e!==l&&m(e)}})),i.addEventListener("mouseleave",(()=>{const e=i.querySelector('[role="option"][aria-selected="true"]');m(e?d.indexOf(e):-1)})),t.addEventListener("keydown",y),o&&o.addEventListener("keydown",y);t.addEventListener("click",(()=>{"true"===t.getAttribute("aria-expanded")?w():(()=>{document.dispatchEvent(new CustomEvent("basecoat:popover",{detail:{source:e}})),o&&(f()?a.addEventListener("transitionend",(()=>{o.focus()}),{once:!0}):o.focus()),a.setAttribute("aria-hidden","false"),t.setAttribute("aria-expanded","true");const n=i.querySelector('[role="option"][aria-selected="true"]');n&&(m(d.indexOf(n)),n.scrollIntoView({block:"nearest"}))})()})),i.addEventListener("click",(e=>{const n=e.target.closest('[role="option"]');n&&(u?(b(n.dataset.value),m(d.indexOf(n)),o?o.focus():t.focus()):g(n))})),document.addEventListener("click",(t=>{e.contains(t.target)||w(!1)})),document.addEventListener("basecoat:popover",(t=>{t.detail.source!==e&&w(!1)})),a.setAttribute("aria-hidden","true"),e.selectByValue=e=>{const t=d.find((t=>t.dataset.value===e));if(u){if(null!=e&&v.has(e))return;if(t&&null!=e){const t=new Set(v);t.add(e);const n=d.filter((e=>t.has(e.dataset.value)));h(n)}}else g(t)},u&&(e.selectAll=E,e.selectNone=A),e.dataset.selectInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("select","div.select:not([data-select-initialized])",e)})(),(()=>{if(!window.history.__basecoatPatched){const e=window.history.pushState;window.history.pushState=function(...t){e.apply(this,t),window.dispatchEvent(new Event("basecoat:locationchange"))};const t=window.history.replaceState;window.history.replaceState=function(...e){t.apply(this,e),window.dispatchEvent(new Event("basecoat:locationchange"))},window.history.__basecoatPatched=!0}const e=e=>{const t="false"!==e.dataset.initialOpen,n="true"===e.dataset.initialMobileOpen,a=parseInt(e.dataset.breakpoint)||768;let i=a>0?window.innerWidth>=a?t:n:t;const r=()=>{const t=window.location.pathname.replace(/\/$/,"");e.querySelectorAll("a").forEach((e=>{if(e.hasAttribute("data-ignore-current"))return;new URL(e.href).pathname.replace(/\/$/,"")===t?e.setAttribute("aria-current","page"):e.removeAttribute("aria-current")}))},o=()=>{e.setAttribute("aria-hidden",!i),i?e.removeAttribute("inert"):e.setAttribute("inert","")},s=e=>{i=e,o()},d=e.id;document.addEventListener("basecoat:sidebar",(e=>{if(!e.detail?.id||e.detail.id===d)switch(e.detail?.action){case"open":s(!0);break;case"close":s(!1);break;default:s(!i)}})),e.addEventListener("click",(t=>{const n=t.target,i=e.querySelector("nav");if(window.innerWidth<a&&n.closest("a, button")&&!n.closest("[data-keep-mobile-sidebar-open]"))return document.activeElement&&document.activeElement.blur(),void s(!1);(n===e||i&&!i.contains(n))&&(document.activeElement&&document.activeElement.blur(),s(!1))})),window.addEventListener("popstate",r),window.addEventListener("basecoat:locationchange",r),o(),r(),e.dataset.sidebarInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("sidebar",".sidebar:not([data-sidebar-initialized])",e)})(),(()=>{const e=e=>{const t=e.querySelector('[role="tablist"]');if(!t)return;const n=Array.from(t.querySelectorAll('[role="tab"]')),a=n.map((e=>document.getElementById(e.getAttribute("aria-controls")))).filter(Boolean),i=e=>{n.forEach(((e,t)=>{e.setAttribute("aria-selected","false"),e.setAttribute("tabindex","-1"),a[t]&&(a[t].hidden=!0)})),e.setAttribute("aria-selected","true"),e.setAttribute("tabindex","0");const t=document.getElementById(e.getAttribute("aria-controls"));t&&(t.hidden=!1)};t.addEventListener("click",(e=>{const t=e.target.closest('[role="tab"]');t&&i(t)})),t.addEventListener("keydown",(e=>{const t=e.target;if(!n.includes(t))return;let a;const r=n.indexOf(t);switch(e.key){case"ArrowRight":a=n[(r+1)%n.length];break;case"ArrowLeft":a=n[(r-1+n.length)%n.length];break;case"Home":a=n[0];break;case"End":a=n[n.length-1];break;default:return}e.preventDefault(),i(a),a.focus()})),e.dataset.tabsInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("tabs",".tabs:not([data-tabs-initialized])",e)})(),(()=>{let e;const t=new WeakMap;let n=!1;const a={success:'<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg>',error:'<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/></svg>',info:'<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>',warning:'<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>'};function i(e){if(e.dataset.toastInitialized)return;const a=parseInt(e.dataset.duration),i=-1!==a?a||("error"===e.dataset.category?5e3:3e3):-1,r={remainingTime:i,timeoutId:null,startTime:null};-1!==i&&(n?r.timeoutId=null:(r.startTime=Date.now(),r.timeoutId=setTimeout((()=>s(e)),i))),t.set(e,r),e.dataset.toastInitialized="true"}function r(){n||(n=!0,e.querySelectorAll('.toast:not([aria-hidden="true"])').forEach((e=>{if(!t.has(e))return;const n=t.get(e);n.timeoutId&&(clearTimeout(n.timeoutId),n.timeoutId=null,n.remainingTime-=Date.now()-n.startTime)})))}function o(){n&&(n=!1,e.querySelectorAll('.toast:not([aria-hidden="true"])').forEach((e=>{if(!t.has(e))return;const n=t.get(e);-1===n.remainingTime||n.timeoutId||(n.remainingTime>0?(n.startTime=Date.now(),n.timeoutId=setTimeout((()=>s(e)),n.remainingTime)):s(e))})))}function s(e){if(!t.has(e))return;const n=t.get(e);clearTimeout(n.timeoutId),t.delete(e),e.contains(document.activeElement)&&document.activeElement.blur(),e.setAttribute("aria-hidden","true"),e.addEventListener("transitionend",(()=>e.remove()),{once:!0})}document.addEventListener("basecoat:toast",(t=>{if(!e)return void console.error("Cannot create toast: toaster container not found on page.");const n=function(e){const{category:t="info",title:n,description:i,action:r,cancel:o,duration:s,icon:d}=e,c=d||t&&a[t]||"",l=n?`<h2>${n}</h2>`:"",u=i?`<p>${i}</p>`:"",v=r?.href?`<a href="${r.href}" class="btn" data-toast-action>${r.label}</a>`:r?.onclick?`<button type="button" class="btn" data-toast-action onclick="${r.onclick}">${r.label}</button>`:"",p=o?`<button type="button" class="btn-outline h-6 text-xs px-2.5 rounded-sm" data-toast-cancel onclick="${o?.onclick}">${o.label}</button>`:"",m=`\n <div\n class="toast"\n role="${"error"===t?"alert":"status"}"\n aria-atomic="true"\n ${t?`data-category="${t}"`:""}\n ${void 0!==s?`data-duration="${s}"`:""}\n >\n <div class="toast-content">\n ${c}\n <section>\n ${l}\n ${u}\n </section>\n ${v||p?`<footer>${v}${p}</footer>`:""}\n </div>\n </div>\n </div>\n `,f=document.createElement("template");return f.innerHTML=m.trim(),f.content.firstChild}(t.detail?.config||{});e.appendChild(n)})),window.basecoat&&(window.basecoat.register("toaster","#toaster:not([data-toaster-initialized])",(function(t){t.dataset.toasterInitialized||(e=t,e.addEventListener("mouseenter",r),e.addEventListener("mouseleave",o),e.addEventListener("click",(e=>{const t=e.target.closest(".toast footer a"),n=e.target.closest(".toast footer button");(t||n)&&s(e.target.closest(".toast"))})),e.querySelectorAll(".toast:not([data-toast-initialized])").forEach(i),e.dataset.toasterInitialized="true",e.dispatchEvent(new CustomEvent("basecoat:initialized")))})),window.basecoat.register("toast",".toast:not([data-toast-initialized])",i))})();
@@ -0,0 +1,192 @@
1
+ (() => {
2
+ const initCarousel = (carouselComponent) => {
3
+ const slidesContainer = carouselComponent.querySelector('.carousel-slides');
4
+ if (!slidesContainer) return;
5
+
6
+ const slides = Array.from(carouselComponent.querySelectorAll('.carousel-item'));
7
+ const prevButton = carouselComponent.querySelector('.carousel-prev');
8
+ const nextButton = carouselComponent.querySelector('.carousel-next');
9
+ const indicators = Array.from(carouselComponent.querySelectorAll('.carousel-indicators button'));
10
+
11
+ const loop = carouselComponent.dataset.carouselLoop === 'true';
12
+ const autoplayDelay = parseInt(carouselComponent.dataset.carouselAutoplay, 10);
13
+ const orientation = carouselComponent.dataset.orientation || 'horizontal';
14
+
15
+ let currentIndex = 0;
16
+ let autoplayInterval = null;
17
+
18
+ const getScrollAmount = () => {
19
+ if (slides.length === 0) return 0;
20
+ const firstSlide = slides[0];
21
+ return orientation === 'vertical'
22
+ ? firstSlide.offsetHeight + parseInt(getComputedStyle(slidesContainer).gap || 0)
23
+ : firstSlide.offsetWidth + parseInt(getComputedStyle(slidesContainer).gap || 0);
24
+ };
25
+
26
+ const scrollToIndex = (index) => {
27
+ const scrollAmount = getScrollAmount();
28
+ if (orientation === 'vertical') {
29
+ slidesContainer.scrollTo({ top: scrollAmount * index, behavior: 'smooth' });
30
+ } else {
31
+ slidesContainer.scrollTo({ left: scrollAmount * index, behavior: 'smooth' });
32
+ }
33
+ currentIndex = index;
34
+ updateIndicators();
35
+ updateButtonStates();
36
+ };
37
+
38
+ const updateIndicators = () => {
39
+ indicators.forEach((indicator, index) => {
40
+ const isActive = index === currentIndex;
41
+ indicator.setAttribute('aria-current', isActive ? 'true' : 'false');
42
+ indicator.setAttribute('aria-label', `Slide ${index + 1}${isActive ? ' (current)' : ''}`);
43
+ });
44
+
45
+ slides.forEach((slide, index) => {
46
+ slide.setAttribute('aria-hidden', index === currentIndex ? 'false' : 'true');
47
+ });
48
+ };
49
+
50
+ const updateButtonStates = () => {
51
+ if (!prevButton || !nextButton) return;
52
+
53
+ if (loop) {
54
+ prevButton.disabled = false;
55
+ nextButton.disabled = false;
56
+ } else {
57
+ prevButton.disabled = currentIndex === 0;
58
+ nextButton.disabled = currentIndex === slides.length - 1;
59
+ }
60
+ };
61
+
62
+ const goToPrevious = () => {
63
+ if (currentIndex > 0) {
64
+ scrollToIndex(currentIndex - 1);
65
+ } else if (loop) {
66
+ scrollToIndex(slides.length - 1);
67
+ }
68
+ };
69
+
70
+ const goToNext = () => {
71
+ if (currentIndex < slides.length - 1) {
72
+ scrollToIndex(currentIndex + 1);
73
+ } else if (loop) {
74
+ scrollToIndex(0);
75
+ }
76
+ };
77
+
78
+ const startAutoplay = () => {
79
+ if (!autoplayDelay || autoplayDelay <= 0) return;
80
+
81
+ autoplayInterval = setInterval(() => {
82
+ goToNext();
83
+ }, autoplayDelay);
84
+ };
85
+
86
+ const stopAutoplay = () => {
87
+ if (autoplayInterval) {
88
+ clearInterval(autoplayInterval);
89
+ autoplayInterval = null;
90
+ }
91
+ };
92
+
93
+ const detectCurrentSlide = () => {
94
+ const scrollPosition = orientation === 'vertical'
95
+ ? slidesContainer.scrollTop
96
+ : slidesContainer.scrollLeft;
97
+ const scrollAmount = getScrollAmount();
98
+ const newIndex = Math.round(scrollPosition / scrollAmount);
99
+
100
+ if (newIndex !== currentIndex && newIndex >= 0 && newIndex < slides.length) {
101
+ currentIndex = newIndex;
102
+ updateIndicators();
103
+ updateButtonStates();
104
+ }
105
+ };
106
+
107
+ // Previous/Next button handlers
108
+ if (prevButton) {
109
+ prevButton.addEventListener('click', () => {
110
+ stopAutoplay();
111
+ goToPrevious();
112
+ });
113
+ }
114
+
115
+ if (nextButton) {
116
+ nextButton.addEventListener('click', () => {
117
+ stopAutoplay();
118
+ goToNext();
119
+ });
120
+ }
121
+
122
+ // Indicator click handlers
123
+ indicators.forEach((indicator, index) => {
124
+ indicator.addEventListener('click', () => {
125
+ stopAutoplay();
126
+ scrollToIndex(index);
127
+ });
128
+ });
129
+
130
+ // Keyboard navigation
131
+ carouselComponent.addEventListener('keydown', (event) => {
132
+ const isVertical = orientation === 'vertical';
133
+ const prevKey = isVertical ? 'ArrowUp' : 'ArrowLeft';
134
+ const nextKey = isVertical ? 'ArrowDown' : 'ArrowRight';
135
+
136
+ switch (event.key) {
137
+ case prevKey:
138
+ event.preventDefault();
139
+ stopAutoplay();
140
+ goToPrevious();
141
+ break;
142
+ case nextKey:
143
+ event.preventDefault();
144
+ stopAutoplay();
145
+ goToNext();
146
+ break;
147
+ case 'Home':
148
+ event.preventDefault();
149
+ stopAutoplay();
150
+ scrollToIndex(0);
151
+ break;
152
+ case 'End':
153
+ event.preventDefault();
154
+ stopAutoplay();
155
+ scrollToIndex(slides.length - 1);
156
+ break;
157
+ }
158
+ });
159
+
160
+ // Detect scroll position changes (for touch/manual scrolling)
161
+ let scrollTimeout;
162
+ slidesContainer.addEventListener('scroll', () => {
163
+ clearTimeout(scrollTimeout);
164
+ scrollTimeout = setTimeout(() => {
165
+ detectCurrentSlide();
166
+ }, 100);
167
+ });
168
+
169
+ // Pause autoplay on hover or focus
170
+ if (autoplayDelay) {
171
+ carouselComponent.addEventListener('mouseenter', stopAutoplay);
172
+ carouselComponent.addEventListener('mouseleave', startAutoplay);
173
+ carouselComponent.addEventListener('focusin', stopAutoplay);
174
+ carouselComponent.addEventListener('focusout', startAutoplay);
175
+ }
176
+
177
+ // Initialize
178
+ updateIndicators();
179
+ updateButtonStates();
180
+
181
+ if (autoplayDelay) {
182
+ startAutoplay();
183
+ }
184
+
185
+ carouselComponent.dataset.carouselInitialized = true;
186
+ carouselComponent.dispatchEvent(new CustomEvent('basecoat:initialized'));
187
+ };
188
+
189
+ if (window.basecoat) {
190
+ window.basecoat.register('carousel', '.carousel:not([data-carousel-initialized])', initCarousel);
191
+ }
192
+ })();
@@ -0,0 +1 @@
1
+ (()=>{const e=e=>{const t=e.querySelector(".carousel-slides");if(!t)return;const r=Array.from(e.querySelectorAll(".carousel-item")),a=e.querySelector(".carousel-prev"),o=e.querySelector(".carousel-next"),l=Array.from(e.querySelectorAll(".carousel-indicators button")),s="true"===e.dataset.carouselLoop,n=parseInt(e.dataset.carouselAutoplay,10),i=e.dataset.orientation||"horizontal";let c=0,d=null;const u=()=>{if(0===r.length)return 0;const e=r[0];return"vertical"===i?e.offsetHeight+parseInt(getComputedStyle(t).gap||0):e.offsetWidth+parseInt(getComputedStyle(t).gap||0)},v=e=>{const r=u();"vertical"===i?t.scrollTo({top:r*e,behavior:"smooth"}):t.scrollTo({left:r*e,behavior:"smooth"}),c=e,f(),h()},f=()=>{l.forEach(((e,t)=>{const r=t===c;e.setAttribute("aria-current",r?"true":"false"),e.setAttribute("aria-label",`Slide ${t+1}${r?" (current)":""}`)})),r.forEach(((e,t)=>{e.setAttribute("aria-hidden",t===c?"false":"true")}))},h=()=>{a&&o&&(s?(a.disabled=!1,o.disabled=!1):(a.disabled=0===c,o.disabled=c===r.length-1))},p=()=>{c>0?v(c-1):s&&v(r.length-1)},b=()=>{c<r.length-1?v(c+1):s&&v(0)},E=()=>{!n||n<=0||(d=setInterval((()=>{b()}),n))},g=()=>{d&&(clearInterval(d),d=null)};let m;a&&a.addEventListener("click",(()=>{g(),p()})),o&&o.addEventListener("click",(()=>{g(),b()})),l.forEach(((e,t)=>{e.addEventListener("click",(()=>{g(),v(t)}))})),e.addEventListener("keydown",(e=>{const t="vertical"===i,a=t?"ArrowUp":"ArrowLeft",o=t?"ArrowDown":"ArrowRight";switch(e.key){case a:e.preventDefault(),g(),p();break;case o:e.preventDefault(),g(),b();break;case"Home":e.preventDefault(),g(),v(0);break;case"End":e.preventDefault(),g(),v(r.length-1)}})),t.addEventListener("scroll",(()=>{clearTimeout(m),m=setTimeout((()=>{(()=>{const e="vertical"===i?t.scrollTop:t.scrollLeft,a=u(),o=Math.round(e/a);o!==c&&o>=0&&o<r.length&&(c=o,f(),h())})()}),100)})),n&&(e.addEventListener("mouseenter",g),e.addEventListener("mouseleave",E),e.addEventListener("focusin",g),e.addEventListener("focusout",E)),f(),h(),n&&E(),e.dataset.carouselInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("carousel",".carousel:not([data-carousel-initialized])",e)})();