basecoat-css 0.2.5 → 0.2.8

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
@@ -516,7 +516,7 @@
516
516
  @apply aria-hidden:hidden [&_svg]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none [&_svg]:shrink-0 [&_svg]:size-4 aria-disabled:opacity-50 aria-disabled:pointer-events-none disabled:opacity-50 disabled:pointer-events-none w-full truncate;
517
517
 
518
518
  &:not([aria-disabled='true']) {
519
- @apply focus-visible:bg-accent focus-visible:text-accent-foreground hover:bg-accent hover:text-accent-foreground;
519
+ @apply focus-visible:bg-accent focus-visible:text-accent-foreground;
520
520
  }
521
521
 
522
522
  &.active {
@@ -530,6 +530,13 @@
530
530
  @apply border-border -mx-1 my-1;
531
531
  }
532
532
  }
533
+ &:not([data-dropdown-menu-initialized]) [data-popover] {
534
+ [role='menuitem'],
535
+ [role='menuitemcheckbox'],
536
+ [role='menuitemradio'] {
537
+ @apply hover:bg-accent hover:text-accent-foreground;
538
+ }
539
+ }
533
540
  }
534
541
  }
535
542
 
@@ -737,6 +744,10 @@
737
744
  &[aria-selected='true'] {
738
745
  @apply bg-[image:var(--check-icon)] bg-no-repeat bg-position-[center_right_0.5rem] bg-size-[0.875rem];
739
746
  }
747
+ &.active,
748
+ &:focus-visible {
749
+ @apply bg-accent text-accent-foreground;
750
+ }
740
751
  }
741
752
  [role='listbox'] [role='heading'] {
742
753
  @apply flex text-muted-foreground px-2 py-1.5 text-xs;
@@ -767,11 +778,8 @@
767
778
  @apply content-['No_results_found'];
768
779
  }
769
780
  }
770
-
771
- [role='option']:hover,
772
- &[data-select-initialized] [role='option'].active,
773
- &[data-select-initialized] [role='option']:focus-visible {
774
- @apply bg-accent text-accent-foreground;
781
+ &:not([data-select-initialized]) [data-popover] [role='option'] {
782
+ @apply hover:bg-accent hover:text-accent-foreground;
775
783
  }
776
784
  }
777
785
  }
package/dist/js/all.js CHANGED
@@ -29,7 +29,7 @@
29
29
  setActiveItem(-1);
30
30
  };
31
31
 
32
- const openPopover = () => {
32
+ const openPopover = (initialSelection = false) => {
33
33
  document.dispatchEvent(new CustomEvent('basecoat:popover', {
34
34
  detail: { source: dropdownMenuComponent }
35
35
  }));
@@ -40,8 +40,13 @@
40
40
  !item.hasAttribute('disabled') &&
41
41
  item.getAttribute('aria-disabled') !== 'true'
42
42
  );
43
- if (menuItems.length > 0) {
44
- setActiveItem(0);
43
+
44
+ if (menuItems.length > 0 && initialSelection) {
45
+ if (initialSelection === 'first') {
46
+ setActiveItem(0);
47
+ } else if (initialSelection === 'last') {
48
+ setActiveItem(menuItems.length - 1);
49
+ }
45
50
  }
46
51
  };
47
52
 
@@ -64,7 +69,7 @@
64
69
  if (isExpanded) {
65
70
  closePopover();
66
71
  } else {
67
- openPopover();
72
+ openPopover(false);
68
73
  }
69
74
  });
70
75
 
@@ -77,9 +82,15 @@
77
82
  }
78
83
 
79
84
  if (!isExpanded) {
80
- if (['ArrowDown', 'ArrowUp', 'Enter', ' '].includes(event.key)) {
85
+ if (['Enter', ' '].includes(event.key)) {
81
86
  event.preventDefault();
82
- openPopover();
87
+ openPopover(false);
88
+ } else if (event.key === 'ArrowDown') {
89
+ event.preventDefault();
90
+ openPopover('first');
91
+ } else if (event.key === 'ArrowUp') {
92
+ event.preventDefault();
93
+ openPopover('last');
83
94
  }
84
95
  return;
85
96
  }
@@ -91,11 +102,11 @@
91
102
  switch (event.key) {
92
103
  case 'ArrowDown':
93
104
  event.preventDefault();
94
- nextIndex = Math.min(activeIndex + 1, menuItems.length - 1);
105
+ nextIndex = activeIndex === -1 ? 0 : Math.min(activeIndex + 1, menuItems.length - 1);
95
106
  break;
96
107
  case 'ArrowUp':
97
108
  event.preventDefault();
98
- nextIndex = Math.max(activeIndex - 1, 0);
109
+ nextIndex = activeIndex === -1 ? menuItems.length - 1 : Math.max(activeIndex - 1, 0);
99
110
  break;
100
111
  case 'Home':
101
112
  event.preventDefault();
@@ -118,6 +129,20 @@
118
129
  }
119
130
  });
120
131
 
132
+ menu.addEventListener('mousemove', (event) => {
133
+ const menuItem = event.target.closest('[role^="menuitem"]');
134
+ if (menuItem && menuItems.includes(menuItem)) {
135
+ const index = menuItems.indexOf(menuItem);
136
+ if (index !== activeIndex) {
137
+ setActiveItem(index);
138
+ }
139
+ }
140
+ });
141
+
142
+ menu.addEventListener('mouseleave', () => {
143
+ setActiveItem(-1);
144
+ });
145
+
121
146
  menu.addEventListener('click', (event) => {
122
147
  if (event.target.closest('[role^="menuitem"]')) {
123
148
  closePopover();
@@ -245,7 +270,7 @@
245
270
  (() => {
246
271
  const initSelect = (selectComponent) => {
247
272
  const trigger = selectComponent.querySelector(':scope > button');
248
- const selectedValue = trigger.querySelector(':scope > span');
273
+ const selectedLabel = trigger.querySelector(':scope > span');
249
274
  const popover = selectComponent.querySelector(':scope > [data-popover]');
250
275
  const listbox = popover.querySelector('[role="listbox"]');
251
276
  const input = selectComponent.querySelector(':scope > input[type="hidden"]');
@@ -264,6 +289,26 @@
264
289
  let visibleOptions = [...options];
265
290
  let activeIndex = -1;
266
291
 
292
+ const setActiveOption = (index) => {
293
+ if (activeIndex > -1 && options[activeIndex]) {
294
+ options[activeIndex].classList.remove('active');
295
+ }
296
+
297
+ activeIndex = index;
298
+
299
+ if (activeIndex > -1) {
300
+ const activeOption = options[activeIndex];
301
+ activeOption.classList.add('active');
302
+ if (activeOption.id) {
303
+ trigger.setAttribute('aria-activedescendant', activeOption.id);
304
+ } else {
305
+ trigger.removeAttribute('aria-activedescendant');
306
+ }
307
+ } else {
308
+ trigger.removeAttribute('aria-activedescendant');
309
+ }
310
+ };
311
+
267
312
  const hasTransition = () => {
268
313
  const style = getComputedStyle(popover);
269
314
  return parseFloat(style.transitionDuration) > 0 || parseFloat(style.transitionDelay) > 0;
@@ -271,7 +316,7 @@
271
316
 
272
317
  const updateValue = (option) => {
273
318
  if (option) {
274
- selectedValue.innerHTML = option.dataset.label || option.innerHTML;
319
+ selectedLabel.innerHTML = option.dataset.label || option.innerHTML;
275
320
  input.value = option.dataset.value;
276
321
  listbox.querySelector('[role="option"][aria-selected="true"]')?.removeAttribute('aria-selected');
277
322
  option.setAttribute('aria-selected', 'true');
@@ -298,49 +343,40 @@
298
343
  if (focusOnTrigger) trigger.focus();
299
344
  popover.setAttribute('aria-hidden', 'true');
300
345
  trigger.setAttribute('aria-expanded', 'false');
301
- trigger.removeAttribute('aria-activedescendant');
302
- if (activeIndex > -1) options[activeIndex]?.classList.remove('active');
303
- activeIndex = -1;
346
+ setActiveOption(-1);
304
347
  }
305
348
 
306
349
  const selectOption = (option) => {
307
350
  if (!option) return;
308
351
 
309
- if (option.dataset.value != null) {
352
+ const oldValue = input.value;
353
+ const newValue = option.dataset.value;
354
+
355
+ if (newValue != null && newValue !== oldValue) {
310
356
  updateValue(option);
311
357
  }
312
358
 
313
359
  closePopover();
314
360
 
315
- const event = new CustomEvent('change', {
316
- detail: { value: option.dataset.value },
317
- bubbles: true
318
- });
319
- selectComponent.dispatchEvent(event);
320
- };
321
-
322
- const selectByValue = (value) => {
323
- const option = options.find(opt => opt.dataset.value === value);
324
- if (option) {
325
- updateValue(option);
326
-
361
+ if (newValue !== oldValue) {
327
362
  const event = new CustomEvent('change', {
328
- detail: { value: option.dataset.value },
363
+ detail: { value: newValue },
329
364
  bubbles: true
330
365
  });
331
366
  selectComponent.dispatchEvent(event);
332
367
  }
333
368
  };
334
369
 
370
+ const selectByValue = (value) => {
371
+ const option = options.find(opt => opt.dataset.value === value);
372
+ selectOption(option);
373
+ };
374
+
335
375
  if (filter) {
336
376
  const filterOptions = () => {
337
377
  const searchTerm = filter.value.trim().toLowerCase();
338
378
 
339
- if (activeIndex > -1) {
340
- options[activeIndex].classList.remove('active');
341
- trigger.removeAttribute('aria-activedescendant');
342
- activeIndex = -1;
343
- }
379
+ setActiveOption(-1);
344
380
 
345
381
  visibleOptions = [];
346
382
  options.forEach(option => {
@@ -417,21 +453,31 @@
417
453
  }
418
454
 
419
455
  if (nextVisibleIndex !== currentVisibleIndex) {
420
- if (currentVisibleIndex > -1) {
421
- visibleOptions[currentVisibleIndex].classList.remove('active');
422
- }
423
-
424
456
  const newActiveOption = visibleOptions[nextVisibleIndex];
425
- newActiveOption.classList.add('active');
426
- activeIndex = options.indexOf(newActiveOption);
427
-
428
- if (newActiveOption.id) {
429
- trigger.setAttribute('aria-activedescendant', newActiveOption.id);
430
- }
457
+ setActiveOption(options.indexOf(newActiveOption));
431
458
  newActiveOption.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
432
459
  }
433
460
  };
434
461
 
462
+ listbox.addEventListener('mousemove', (event) => {
463
+ const option = event.target.closest('[role="option"]');
464
+ if (option && visibleOptions.includes(option)) {
465
+ const index = options.indexOf(option);
466
+ if (index !== activeIndex) {
467
+ setActiveOption(index);
468
+ }
469
+ }
470
+ });
471
+
472
+ listbox.addEventListener('mouseleave', () => {
473
+ const selectedOption = listbox.querySelector('[role="option"][aria-selected="true"]');
474
+ if (selectedOption) {
475
+ setActiveOption(options.indexOf(selectedOption));
476
+ } else {
477
+ setActiveOption(-1);
478
+ }
479
+ });
480
+
435
481
  trigger.addEventListener('keydown', handleKeyNavigation);
436
482
  if (filter) {
437
483
  filter.addEventListener('keydown', handleKeyNavigation);
@@ -457,14 +503,7 @@
457
503
 
458
504
  const selectedOption = listbox.querySelector('[role="option"][aria-selected="true"]');
459
505
  if (selectedOption) {
460
- if (activeIndex > -1) {
461
- options[activeIndex]?.classList.remove('active');
462
- }
463
- activeIndex = options.indexOf(selectedOption);
464
- selectedOption.classList.add('active');
465
- if (selectedOption.id) {
466
- trigger.setAttribute('aria-activedescendant', selectedOption.id);
467
- }
506
+ setActiveOption(options.indexOf(selectedOption));
468
507
  selectedOption.scrollIntoView({ block: 'nearest' });
469
508
  }
470
509
  };
@@ -1 +1 @@
1
- (()=>{const e=e=>{const t=e.querySelector(":scope > button"),a=e.querySelector(":scope > [data-popover]"),n=a.querySelector('[role="menu"]');if(!t||!n||!a){const i=[];return t||i.push("trigger"),n||i.push("menu"),a||i.push("popover"),void console.error(`Dropdown menu initialisation failed. Missing element(s): ${i.join(", ")}`,e)}let i=[],o=-1;const r=(e=!0)=>{"false"!==t.getAttribute("aria-expanded")&&(t.setAttribute("aria-expanded","false"),t.removeAttribute("aria-activedescendant"),a.setAttribute("aria-hidden","true"),e&&t.focus(),d(-1))},s=()=>{document.dispatchEvent(new CustomEvent("basecoat:popover",{detail:{source:e}})),t.setAttribute("aria-expanded","true"),a.setAttribute("aria-hidden","false"),i=Array.from(n.querySelectorAll('[role^="menuitem"]')).filter((e=>!e.hasAttribute("disabled")&&"true"!==e.getAttribute("aria-disabled"))),i.length>0&&d(0)},d=e=>{if(o>-1&&i[o]&&i[o].classList.remove("active"),o=e,o>-1&&i[o]){const e=i[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()})),e.addEventListener("keydown",(e=>{const a="true"===t.getAttribute("aria-expanded");if("Escape"===e.key)return void(a&&r());if(!a)return void(["ArrowDown","ArrowUp","Enter"," "].includes(e.key)&&(e.preventDefault(),s()));if(0===i.length)return;let n=o;switch(e.key){case"ArrowDown":e.preventDefault(),n=Math.min(o+1,i.length-1);break;case"ArrowUp":e.preventDefault(),n=Math.max(o-1,0);break;case"Home":e.preventDefault(),n=0;break;case"End":e.preventDefault(),n=i.length-1;break;case"Enter":case" ":return e.preventDefault(),i[o]?.click(),void r()}n!==o&&d(n)})),n.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"))};document.querySelectorAll(".dropdown-menu:not([data-dropdown-menu-initialized])").forEach(e);new MutationObserver((t=>{t.forEach((t=>{t.addedNodes.forEach((t=>{t.nodeType===Node.ELEMENT_NODE&&(t.matches(".dropdown-menu:not([data-dropdown-menu-initialized])")&&e(t),t.querySelectorAll(".dropdown-menu:not([data-dropdown-menu-initialized])").forEach(e))}))}))})).observe(document.body,{childList:!0,subtree:!0})})(),(()=>{const e=e=>{const t=e.querySelector(":scope > button"),a=e.querySelector(":scope > [data-popover]");if(!t||!a){const n=[];return t||n.push("trigger"),a||n.push("content"),void console.error(`Popover initialisation failed. Missing element(s): ${n.join(", ")}`,e)}const n=(e=!0)=>{"false"!==t.getAttribute("aria-expanded")&&(t.setAttribute("aria-expanded","false"),a.setAttribute("aria-hidden","true"),e&&t.focus())};t.addEventListener("click",(()=>{"true"===t.getAttribute("aria-expanded")?n():(()=>{document.dispatchEvent(new CustomEvent("basecoat:popover",{detail:{source:e}}));const n=a.querySelector("[autofocus]");n&&a.addEventListener("transitionend",(()=>{n.focus()}),{once:!0}),t.setAttribute("aria-expanded","true"),a.setAttribute("aria-hidden","false")})()})),e.addEventListener("keydown",(e=>{"Escape"===e.key&&n()})),document.addEventListener("click",(t=>{e.contains(t.target)||n()})),document.addEventListener("basecoat:popover",(t=>{t.detail.source!==e&&n(!1)})),e.dataset.popoverInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};document.querySelectorAll(".popover:not([data-popover-initialized])").forEach(e);new MutationObserver((t=>{t.forEach((t=>{t.addedNodes.forEach((t=>{t.nodeType===Node.ELEMENT_NODE&&(t.matches(".popover:not([data-popover-initialized])")&&e(t),t.querySelectorAll(".popover:not([data-popover-initialized])").forEach(e))}))}))})).observe(document.body,{childList:!0,subtree:!0})})(),(()=>{const e=e=>{const t=e.querySelector(":scope > button"),a=t.querySelector(":scope > span"),n=e.querySelector(":scope > [data-popover]"),i=n.querySelector('[role="listbox"]'),o=e.querySelector(':scope > input[type="hidden"]'),r=e.querySelector('header input[type="text"]');if(!(t&&n&&i&&o)){const a=[];return t||a.push("trigger"),n||a.push("popover"),i||a.push("listbox"),o||a.push("input"),void console.error(`Select component initialisation failed. Missing element(s): ${a.join(", ")}`,e)}const s=Array.from(i.querySelectorAll('[role="option"]'));let d=[...s],c=-1;const l=()=>{const e=getComputedStyle(n);return parseFloat(e.transitionDuration)>0||parseFloat(e.transitionDelay)>0},u=e=>{e&&(a.innerHTML=e.dataset.label||e.innerHTML,o.value=e.dataset.value,i.querySelector('[role="option"][aria-selected="true"]')?.removeAttribute("aria-selected"),e.setAttribute("aria-selected","true"))},v=(e=!0)=>{if("true"!==n.getAttribute("aria-hidden")){if(r){const e=()=>{r.value="",d=[...s],s.forEach((e=>e.setAttribute("aria-hidden","false")))};l()?n.addEventListener("transitionend",e,{once:!0}):e()}e&&t.focus(),n.setAttribute("aria-hidden","true"),t.setAttribute("aria-expanded","false"),t.removeAttribute("aria-activedescendant"),c>-1&&s[c]?.classList.remove("active"),c=-1}},p=t=>{if(!t)return;null!=t.dataset.value&&u(t),v();const a=new CustomEvent("change",{detail:{value:t.dataset.value},bubbles:!0});e.dispatchEvent(a)};if(r){const e=()=>{const e=r.value.trim().toLowerCase();c>-1&&(s[c].classList.remove("active"),t.removeAttribute("aria-activedescendant"),c=-1),d=[],s.forEach((t=>{const a=(t.dataset.label||t.textContent).trim().toLowerCase().includes(e);t.setAttribute("aria-hidden",String(!a)),a&&d.push(t)}))};r.addEventListener("input",e)}let h=s.find((e=>e.dataset.value===o.value));!h&&s.length>0&&(h=s[0]),u(h);const b=e=>{const a="false"===n.getAttribute("aria-hidden");if(!["ArrowDown","ArrowUp","Enter","Home","End","Escape"].includes(e.key))return;if(!a)return void("Enter"!==e.key&&"Escape"!==e.key&&(e.preventDefault(),t.click()));if(e.preventDefault(),"Escape"===e.key)return void v();if("Enter"===e.key)return void(c>-1&&p(s[c]));if(0===d.length)return;const i=c>-1?d.indexOf(s[c]):-1;let o=i;switch(e.key){case"ArrowDown":i<d.length-1&&(o=i+1);break;case"ArrowUp":i>0?o=i-1:-1===i&&(o=0);break;case"Home":o=0;break;case"End":o=d.length-1}if(o!==i){i>-1&&d[i].classList.remove("active");const e=d[o];e.classList.add("active"),c=s.indexOf(e),e.id&&t.setAttribute("aria-activedescendant",e.id),e.scrollIntoView({block:"nearest",behavior:"smooth"})}};t.addEventListener("keydown",b),r&&r.addEventListener("keydown",b);t.addEventListener("click",(()=>{"true"===t.getAttribute("aria-expanded")?v():(()=>{document.dispatchEvent(new CustomEvent("basecoat:popover",{detail:{source:e}})),r&&(l()?n.addEventListener("transitionend",(()=>{r.focus()}),{once:!0}):r.focus()),n.setAttribute("aria-hidden","false"),t.setAttribute("aria-expanded","true");const a=i.querySelector('[role="option"][aria-selected="true"]');a&&(c>-1&&s[c]?.classList.remove("active"),c=s.indexOf(a),a.classList.add("active"),a.id&&t.setAttribute("aria-activedescendant",a.id),a.scrollIntoView({block:"nearest"}))})()})),i.addEventListener("click",(e=>{const t=e.target.closest('[role="option"]');t&&p(t)})),document.addEventListener("click",(t=>{e.contains(t.target)||v(!1)})),document.addEventListener("basecoat:popover",(t=>{t.detail.source!==e&&v(!1)})),n.setAttribute("aria-hidden","true"),e.selectByValue=t=>{const a=s.find((e=>e.dataset.value===t));if(a){u(a);const t=new CustomEvent("change",{detail:{value:a.dataset.value},bubbles:!0});e.dispatchEvent(t)}},e.dataset.selectInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};document.querySelectorAll("div.select:not([data-select-initialized])").forEach(e);new MutationObserver((t=>{t.forEach((t=>{t.addedNodes.forEach((t=>{t.nodeType===Node.ELEMENT_NODE&&(t.matches("div.select:not([data-select-initialized])")&&e(t),t.querySelectorAll("div.select:not([data-select-initialized])").forEach(e))}))}))})).observe(document.body,{childList:!0,subtree:!0})})(),(()=>{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,a="true"===e.dataset.initialMobileOpen,n=parseInt(e.dataset.breakpoint)||768;let i=n>0?window.innerWidth>=n?t:a: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",!i),i?e.removeAttribute("inert"):e.setAttribute("inert","")},s=e=>{i=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(!i)}})),e.addEventListener("click",(t=>{const a=t.target,i=e.querySelector("nav");if(window.innerWidth<n&&a.closest("a, button")&&!a.closest("[data-keep-mobile-sidebar-open]"))return document.activeElement&&document.activeElement.blur(),void s(!1);(a===e||i&&!i.contains(a))&&(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"))};document.querySelectorAll(".sidebar:not([data-sidebar-initialized])").forEach(e);new MutationObserver((t=>{t.forEach((t=>{t.addedNodes.forEach((t=>{t.nodeType===Node.ELEMENT_NODE&&(t.matches(".sidebar:not([data-sidebar-initialized])")&&e(t),t.querySelectorAll(".sidebar:not([data-sidebar-initialized])").forEach(e))}))}))})).observe(document.body,{childList:!0,subtree:!0})})(),(()=>{const e=e=>{const t=e.querySelector('[role="tablist"]');if(!t)return;const a=Array.from(t.querySelectorAll('[role="tab"]')),n=a.map((e=>document.getElementById(e.getAttribute("aria-controls")))).filter(Boolean),i=e=>{a.forEach(((e,t)=>{e.setAttribute("aria-selected","false"),e.setAttribute("tabindex","-1"),n[t]&&(n[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(!a.includes(t))return;let n;const o=a.indexOf(t);switch(e.key){case"ArrowRight":n=a[(o+1)%a.length];break;case"ArrowLeft":n=a[(o-1+a.length)%a.length];break;case"Home":n=a[0];break;case"End":n=a[a.length-1];break;default:return}e.preventDefault(),i(n),n.focus()})),e.dataset.tabsInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};document.querySelectorAll(".tabs:not([data-tabs-initialized])").forEach(e);new MutationObserver((t=>{t.forEach((t=>{t.addedNodes.forEach((t=>{t.nodeType===Node.ELEMENT_NODE&&(t.matches(".tabs:not([data-tabs-initialized])")&&e(t),t.querySelectorAll(".tabs:not([data-tabs-initialized])").forEach(e))}))}))})).observe(document.body,{childList:!0,subtree:!0})})(),(()=>{let e;const t=new WeakMap;let a=!1;const n={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(t){t.dataset.toasterInitialized||(e=t,e.addEventListener("mouseenter",r),e.addEventListener("mouseleave",s),e.addEventListener("click",(e=>{const t=e.target.closest(".toast footer a"),a=e.target.closest(".toast footer button");(t||a)&&d(e.target.closest(".toast"))})),e.querySelectorAll(".toast:not([data-toast-initialized])").forEach(o),e.dataset.toasterInitialized="true",e.dispatchEvent(new CustomEvent("basecoat:initialized")))}function o(e){if(e.dataset.toastInitialized)return;const n=parseInt(e.dataset.duration),i=-1!==n?n||("error"===e.dataset.category?5e3:3e3):-1,o={remainingTime:i,timeoutId:null,startTime:null};-1!==i&&(a?o.timeoutId=null:(o.startTime=Date.now(),o.timeoutId=setTimeout((()=>d(e)),i))),t.set(e,o),e.dataset.toastInitialized="true"}function r(){a||(a=!0,e.querySelectorAll('.toast:not([aria-hidden="true"])').forEach((e=>{if(!t.has(e))return;const a=t.get(e);a.timeoutId&&(clearTimeout(a.timeoutId),a.timeoutId=null,a.remainingTime-=Date.now()-a.startTime)})))}function s(){a&&(a=!1,e.querySelectorAll('.toast:not([aria-hidden="true"])').forEach((e=>{if(!t.has(e))return;const a=t.get(e);-1===a.remainingTime||a.timeoutId||(a.remainingTime>0?(a.startTime=Date.now(),a.timeoutId=setTimeout((()=>d(e)),a.remainingTime)):d(e))})))}function d(e){if(!t.has(e))return;const a=t.get(e);clearTimeout(a.timeoutId),t.delete(e),document.activeElement&&document.activeElement.blur(),e.setAttribute("aria-hidden","true"),e.addEventListener("transitionend",(()=>e.remove()),{once:!0})}const c=document.getElementById("toaster");c&&i(c),document.addEventListener("basecoat:toast",(t=>{if(!e)return void console.error("Cannot create toast: toaster container not found on page.");const a=function(e){const{category:t="info",title:a,description:i,action:o,cancel:r,duration:s,icon:d}=e,c=d||t&&n[t]||"",l=a?`<h2>${a}</h2>`:"",u=i?`<p>${i}</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>`:"",h=`\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=h.trim(),b.content.firstChild}(t.detail?.config||{});e.appendChild(a)}));new MutationObserver((t=>{t.forEach((t=>{t.addedNodes.forEach((t=>{t.nodeType===Node.ELEMENT_NODE&&(t.matches("#toaster")&&i(t),e&&t.matches(".toast:not([data-toast-initialized])")&&o(t))}))}))})).observe(document.body,{childList:!0,subtree:!0})})();
1
+ (()=>{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=[],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"),i=Array.from(a.querySelectorAll('[role^="menuitem"]')).filter((e=>!e.hasAttribute("disabled")&&"true"!==e.getAttribute("aria-disabled"))),i.length>0&&o&&("first"===o?d(0):"last"===o&&d(i.length-1))},d=e=>{if(o>-1&&i[o]&&i[o].classList.remove("active"),o=e,o>-1&&i[o]){const e=i[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===i.length)return;let a=o;switch(e.key){case"ArrowDown":e.preventDefault(),a=-1===o?0:Math.min(o+1,i.length-1);break;case"ArrowUp":e.preventDefault(),a=-1===o?i.length-1:Math.max(o-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[o]?.click(),void r()}a!==o&&d(a)})),a.addEventListener("mousemove",(e=>{const t=e.target.closest('[role^="menuitem"]');if(t&&i.includes(t)){const e=i.indexOf(t);e!==o&&d(e)}})),a.addEventListener("mouseleave",(()=>{d(-1)})),a.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"))};document.querySelectorAll(".dropdown-menu:not([data-dropdown-menu-initialized])").forEach(e);new MutationObserver((t=>{t.forEach((t=>{t.addedNodes.forEach((t=>{t.nodeType===Node.ELEMENT_NODE&&(t.matches(".dropdown-menu:not([data-dropdown-menu-initialized])")&&e(t),t.querySelectorAll(".dropdown-menu:not([data-dropdown-menu-initialized])").forEach(e))}))}))})).observe(document.body,{childList:!0,subtree:!0})})(),(()=>{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"))};document.querySelectorAll(".popover:not([data-popover-initialized])").forEach(e);new MutationObserver((t=>{t.forEach((t=>{t.addedNodes.forEach((t=>{t.nodeType===Node.ELEMENT_NODE&&(t.matches(".popover:not([data-popover-initialized])")&&e(t),t.querySelectorAll(".popover:not([data-popover-initialized])").forEach(e))}))}))})).observe(document.body,{childList:!0,subtree:!0})})(),(()=>{const e=e=>{const t=e.querySelector(":scope > button"),n=t.querySelector(":scope > span"),a=e.querySelector(":scope > [data-popover]"),i=a.querySelector('[role="listbox"]'),o=e.querySelector(':scope > input[type="hidden"]'),r=e.querySelector('header input[type="text"]');if(!(t&&a&&i&&o)){const n=[];return t||n.push("trigger"),a||n.push("popover"),i||n.push("listbox"),o||n.push("input"),void console.error(`Select component initialisation failed. Missing element(s): ${n.join(", ")}`,e)}const s=Array.from(i.querySelectorAll('[role="option"]'));let d=[...s],c=-1;const l=e=>{if(c>-1&&s[c]&&s[c].classList.remove("active"),c=e,c>-1){const e=s[c];e.classList.add("active"),e.id?t.setAttribute("aria-activedescendant",e.id):t.removeAttribute("aria-activedescendant")}else t.removeAttribute("aria-activedescendant")},u=()=>{const e=getComputedStyle(a);return parseFloat(e.transitionDuration)>0||parseFloat(e.transitionDelay)>0},p=e=>{e&&(n.innerHTML=e.dataset.label||e.innerHTML,o.value=e.dataset.value,i.querySelector('[role="option"][aria-selected="true"]')?.removeAttribute("aria-selected"),e.setAttribute("aria-selected","true"))},v=(e=!0)=>{if("true"!==a.getAttribute("aria-hidden")){if(r){const e=()=>{r.value="",d=[...s],s.forEach((e=>e.setAttribute("aria-hidden","false")))};u()?a.addEventListener("transitionend",e,{once:!0}):e()}e&&t.focus(),a.setAttribute("aria-hidden","true"),t.setAttribute("aria-expanded","false"),l(-1)}},h=t=>{if(!t)return;const n=o.value,a=t.dataset.value;if(null!=a&&a!==n&&p(t),v(),a!==n){const t=new CustomEvent("change",{detail:{value:a},bubbles:!0});e.dispatchEvent(t)}};if(r){const e=()=>{const e=r.value.trim().toLowerCase();l(-1),d=[],s.forEach((t=>{const n=(t.dataset.label||t.textContent).trim().toLowerCase().includes(e);t.setAttribute("aria-hidden",String(!n)),n&&d.push(t)}))};r.addEventListener("input",e)}let b=s.find((e=>e.dataset.value===o.value));!b&&s.length>0&&(b=s[0]),p(b);const m=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 v();if("Enter"===e.key)return void(c>-1&&h(s[c]));if(0===d.length)return;const i=c>-1?d.indexOf(s[c]):-1;let o=i;switch(e.key){case"ArrowDown":i<d.length-1&&(o=i+1);break;case"ArrowUp":i>0?o=i-1:-1===i&&(o=0);break;case"Home":o=0;break;case"End":o=d.length-1}if(o!==i){const e=d[o];l(s.indexOf(e)),e.scrollIntoView({block:"nearest",behavior:"smooth"})}};i.addEventListener("mousemove",(e=>{const t=e.target.closest('[role="option"]');if(t&&d.includes(t)){const e=s.indexOf(t);e!==c&&l(e)}})),i.addEventListener("mouseleave",(()=>{const e=i.querySelector('[role="option"][aria-selected="true"]');l(e?s.indexOf(e):-1)})),t.addEventListener("keydown",m),r&&r.addEventListener("keydown",m);t.addEventListener("click",(()=>{"true"===t.getAttribute("aria-expanded")?v():(()=>{document.dispatchEvent(new CustomEvent("basecoat:popover",{detail:{source:e}})),r&&(u()?a.addEventListener("transitionend",(()=>{r.focus()}),{once:!0}):r.focus()),a.setAttribute("aria-hidden","false"),t.setAttribute("aria-expanded","true");const n=i.querySelector('[role="option"][aria-selected="true"]');n&&(l(s.indexOf(n)),n.scrollIntoView({block:"nearest"}))})()})),i.addEventListener("click",(e=>{const t=e.target.closest('[role="option"]');t&&h(t)})),document.addEventListener("click",(t=>{e.contains(t.target)||v(!1)})),document.addEventListener("basecoat:popover",(t=>{t.detail.source!==e&&v(!1)})),a.setAttribute("aria-hidden","true"),e.selectByValue=e=>{const t=s.find((t=>t.dataset.value===e));h(t)},e.dataset.selectInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};document.querySelectorAll("div.select:not([data-select-initialized])").forEach(e);new MutationObserver((t=>{t.forEach((t=>{t.addedNodes.forEach((t=>{t.nodeType===Node.ELEMENT_NODE&&(t.matches("div.select:not([data-select-initialized])")&&e(t),t.querySelectorAll("div.select:not([data-select-initialized])").forEach(e))}))}))})).observe(document.body,{childList:!0,subtree:!0})})(),(()=>{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 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",!i),i?e.removeAttribute("inert"):e.setAttribute("inert","")},s=e=>{i=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(!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",o),window.addEventListener("basecoat:locationchange",o),r(),o(),e.dataset.sidebarInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};document.querySelectorAll(".sidebar:not([data-sidebar-initialized])").forEach(e);new MutationObserver((t=>{t.forEach((t=>{t.addedNodes.forEach((t=>{t.nodeType===Node.ELEMENT_NODE&&(t.matches(".sidebar:not([data-sidebar-initialized])")&&e(t),t.querySelectorAll(".sidebar:not([data-sidebar-initialized])").forEach(e))}))}))})).observe(document.body,{childList:!0,subtree:!0})})(),(()=>{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 o=n.indexOf(t);switch(e.key){case"ArrowRight":a=n[(o+1)%n.length];break;case"ArrowLeft":a=n[(o-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"))};document.querySelectorAll(".tabs:not([data-tabs-initialized])").forEach(e);new MutationObserver((t=>{t.forEach((t=>{t.addedNodes.forEach((t=>{t.nodeType===Node.ELEMENT_NODE&&(t.matches(".tabs:not([data-tabs-initialized])")&&e(t),t.querySelectorAll(".tabs:not([data-tabs-initialized])").forEach(e))}))}))})).observe(document.body,{childList:!0,subtree:!0})})(),(()=>{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(t){t.dataset.toasterInitialized||(e=t,e.addEventListener("mouseenter",r),e.addEventListener("mouseleave",s),e.addEventListener("click",(e=>{const t=e.target.closest(".toast footer a"),n=e.target.closest(".toast footer button");(t||n)&&d(e.target.closest(".toast"))})),e.querySelectorAll(".toast:not([data-toast-initialized])").forEach(o),e.dataset.toasterInitialized="true",e.dispatchEvent(new CustomEvent("basecoat:initialized")))}function o(e){if(e.dataset.toastInitialized)return;const a=parseInt(e.dataset.duration),i=-1!==a?a||("error"===e.dataset.category?5e3:3e3):-1,o={remainingTime:i,timeoutId:null,startTime:null};-1!==i&&(n?o.timeoutId=null:(o.startTime=Date.now(),o.timeoutId=setTimeout((()=>d(e)),i))),t.set(e,o),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 s(){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((()=>d(e)),n.remainingTime)):d(e))})))}function d(e){if(!t.has(e))return;const n=t.get(e);clearTimeout(n.timeoutId),t.delete(e),document.activeElement&&document.activeElement.blur(),e.setAttribute("aria-hidden","true"),e.addEventListener("transitionend",(()=>e.remove()),{once:!0})}const c=document.getElementById("toaster");c&&i(c),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:o,cancel:r,duration:s,icon:d}=e,c=d||t&&a[t]||"",l=n?`<h2>${n}</h2>`:"",u=i?`<p>${i}</p>`:"",p=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>`:"",v=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>`:"",h=`\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 ${p||v?`<footer>${p}${v}</footer>`:""}\n </div>\n </div>\n </div>\n `,b=document.createElement("template");return b.innerHTML=h.trim(),b.content.firstChild}(t.detail?.config||{});e.appendChild(n)}));new MutationObserver((t=>{t.forEach((t=>{t.addedNodes.forEach((t=>{t.nodeType===Node.ELEMENT_NODE&&(t.matches("#toaster")&&i(t),e&&t.matches(".toast:not([data-toast-initialized])")&&o(t))}))}))})).observe(document.body,{childList:!0,subtree:!0})})();
@@ -29,7 +29,7 @@
29
29
  setActiveItem(-1);
30
30
  };
31
31
 
32
- const openPopover = () => {
32
+ const openPopover = (initialSelection = false) => {
33
33
  document.dispatchEvent(new CustomEvent('basecoat:popover', {
34
34
  detail: { source: dropdownMenuComponent }
35
35
  }));
@@ -40,8 +40,13 @@
40
40
  !item.hasAttribute('disabled') &&
41
41
  item.getAttribute('aria-disabled') !== 'true'
42
42
  );
43
- if (menuItems.length > 0) {
44
- setActiveItem(0);
43
+
44
+ if (menuItems.length > 0 && initialSelection) {
45
+ if (initialSelection === 'first') {
46
+ setActiveItem(0);
47
+ } else if (initialSelection === 'last') {
48
+ setActiveItem(menuItems.length - 1);
49
+ }
45
50
  }
46
51
  };
47
52
 
@@ -64,7 +69,7 @@
64
69
  if (isExpanded) {
65
70
  closePopover();
66
71
  } else {
67
- openPopover();
72
+ openPopover(false);
68
73
  }
69
74
  });
70
75
 
@@ -77,9 +82,15 @@
77
82
  }
78
83
 
79
84
  if (!isExpanded) {
80
- if (['ArrowDown', 'ArrowUp', 'Enter', ' '].includes(event.key)) {
85
+ if (['Enter', ' '].includes(event.key)) {
86
+ event.preventDefault();
87
+ openPopover(false);
88
+ } else if (event.key === 'ArrowDown') {
81
89
  event.preventDefault();
82
- openPopover();
90
+ openPopover('first');
91
+ } else if (event.key === 'ArrowUp') {
92
+ event.preventDefault();
93
+ openPopover('last');
83
94
  }
84
95
  return;
85
96
  }
@@ -91,11 +102,11 @@
91
102
  switch (event.key) {
92
103
  case 'ArrowDown':
93
104
  event.preventDefault();
94
- nextIndex = Math.min(activeIndex + 1, menuItems.length - 1);
105
+ nextIndex = activeIndex === -1 ? 0 : Math.min(activeIndex + 1, menuItems.length - 1);
95
106
  break;
96
107
  case 'ArrowUp':
97
108
  event.preventDefault();
98
- nextIndex = Math.max(activeIndex - 1, 0);
109
+ nextIndex = activeIndex === -1 ? menuItems.length - 1 : Math.max(activeIndex - 1, 0);
99
110
  break;
100
111
  case 'Home':
101
112
  event.preventDefault();
@@ -118,6 +129,20 @@
118
129
  }
119
130
  });
120
131
 
132
+ menu.addEventListener('mousemove', (event) => {
133
+ const menuItem = event.target.closest('[role^="menuitem"]');
134
+ if (menuItem && menuItems.includes(menuItem)) {
135
+ const index = menuItems.indexOf(menuItem);
136
+ if (index !== activeIndex) {
137
+ setActiveItem(index);
138
+ }
139
+ }
140
+ });
141
+
142
+ menu.addEventListener('mouseleave', () => {
143
+ setActiveItem(-1);
144
+ });
145
+
121
146
  menu.addEventListener('click', (event) => {
122
147
  if (event.target.closest('[role^="menuitem"]')) {
123
148
  closePopover();
@@ -1 +1 @@
1
- (()=>{const e=e=>{const t=e.querySelector(":scope > button"),r=e.querySelector(":scope > [data-popover]"),a=r.querySelector('[role="menu"]');if(!t||!a||!r){const n=[];return t||n.push("trigger"),a||n.push("menu"),r||n.push("popover"),void console.error(`Dropdown menu initialisation failed. Missing element(s): ${n.join(", ")}`,e)}let n=[],i=-1;const o=(e=!0)=>{"false"!==t.getAttribute("aria-expanded")&&(t.setAttribute("aria-expanded","false"),t.removeAttribute("aria-activedescendant"),r.setAttribute("aria-hidden","true"),e&&t.focus(),s(-1))},d=()=>{document.dispatchEvent(new CustomEvent("basecoat:popover",{detail:{source:e}})),t.setAttribute("aria-expanded","true"),r.setAttribute("aria-hidden","false"),n=Array.from(a.querySelectorAll('[role^="menuitem"]')).filter((e=>!e.hasAttribute("disabled")&&"true"!==e.getAttribute("aria-disabled"))),n.length>0&&s(0)},s=e=>{if(i>-1&&n[i]&&n[i].classList.remove("active"),i=e,i>-1&&n[i]){const e=n[i];e.classList.add("active"),t.setAttribute("aria-activedescendant",e.id)}else t.removeAttribute("aria-activedescendant")};t.addEventListener("click",(()=>{"true"===t.getAttribute("aria-expanded")?o():d()})),e.addEventListener("keydown",(e=>{const r="true"===t.getAttribute("aria-expanded");if("Escape"===e.key)return void(r&&o());if(!r)return void(["ArrowDown","ArrowUp","Enter"," "].includes(e.key)&&(e.preventDefault(),d()));if(0===n.length)return;let a=i;switch(e.key){case"ArrowDown":e.preventDefault(),a=Math.min(i+1,n.length-1);break;case"ArrowUp":e.preventDefault(),a=Math.max(i-1,0);break;case"Home":e.preventDefault(),a=0;break;case"End":e.preventDefault(),a=n.length-1;break;case"Enter":case" ":return e.preventDefault(),n[i]?.click(),void o()}a!==i&&s(a)})),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"))};document.querySelectorAll(".dropdown-menu:not([data-dropdown-menu-initialized])").forEach(e);new MutationObserver((t=>{t.forEach((t=>{t.addedNodes.forEach((t=>{t.nodeType===Node.ELEMENT_NODE&&(t.matches(".dropdown-menu:not([data-dropdown-menu-initialized])")&&e(t),t.querySelectorAll(".dropdown-menu:not([data-dropdown-menu-initialized])").forEach(e))}))}))})).observe(document.body,{childList:!0,subtree:!0})})();
1
+ (()=>{const e=e=>{const t=e.querySelector(":scope > button"),r=e.querySelector(":scope > [data-popover]"),a=r.querySelector('[role="menu"]');if(!t||!a||!r){const n=[];return t||n.push("trigger"),a||n.push("menu"),r||n.push("popover"),void console.error(`Dropdown menu initialisation failed. Missing element(s): ${n.join(", ")}`,e)}let n=[],i=-1;const o=(e=!0)=>{"false"!==t.getAttribute("aria-expanded")&&(t.setAttribute("aria-expanded","false"),t.removeAttribute("aria-activedescendant"),r.setAttribute("aria-hidden","true"),e&&t.focus(),s(-1))},d=(i=!1)=>{document.dispatchEvent(new CustomEvent("basecoat:popover",{detail:{source:e}})),t.setAttribute("aria-expanded","true"),r.setAttribute("aria-hidden","false"),n=Array.from(a.querySelectorAll('[role^="menuitem"]')).filter((e=>!e.hasAttribute("disabled")&&"true"!==e.getAttribute("aria-disabled"))),n.length>0&&i&&("first"===i?s(0):"last"===i&&s(n.length-1))},s=e=>{if(i>-1&&n[i]&&n[i].classList.remove("active"),i=e,i>-1&&n[i]){const e=n[i];e.classList.add("active"),t.setAttribute("aria-activedescendant",e.id)}else t.removeAttribute("aria-activedescendant")};t.addEventListener("click",(()=>{"true"===t.getAttribute("aria-expanded")?o():d(!1)})),e.addEventListener("keydown",(e=>{const r="true"===t.getAttribute("aria-expanded");if("Escape"===e.key)return void(r&&o());if(!r)return void(["Enter"," "].includes(e.key)?(e.preventDefault(),d(!1)):"ArrowDown"===e.key?(e.preventDefault(),d("first")):"ArrowUp"===e.key&&(e.preventDefault(),d("last")));if(0===n.length)return;let a=i;switch(e.key){case"ArrowDown":e.preventDefault(),a=-1===i?0:Math.min(i+1,n.length-1);break;case"ArrowUp":e.preventDefault(),a=-1===i?n.length-1:Math.max(i-1,0);break;case"Home":e.preventDefault(),a=0;break;case"End":e.preventDefault(),a=n.length-1;break;case"Enter":case" ":return e.preventDefault(),n[i]?.click(),void o()}a!==i&&s(a)})),a.addEventListener("mousemove",(e=>{const t=e.target.closest('[role^="menuitem"]');if(t&&n.includes(t)){const e=n.indexOf(t);e!==i&&s(e)}})),a.addEventListener("mouseleave",(()=>{s(-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"))};document.querySelectorAll(".dropdown-menu:not([data-dropdown-menu-initialized])").forEach(e);new MutationObserver((t=>{t.forEach((t=>{t.addedNodes.forEach((t=>{t.nodeType===Node.ELEMENT_NODE&&(t.matches(".dropdown-menu:not([data-dropdown-menu-initialized])")&&e(t),t.querySelectorAll(".dropdown-menu:not([data-dropdown-menu-initialized])").forEach(e))}))}))})).observe(document.body,{childList:!0,subtree:!0})})();
package/dist/js/select.js CHANGED
@@ -1,7 +1,7 @@
1
1
  (() => {
2
2
  const initSelect = (selectComponent) => {
3
3
  const trigger = selectComponent.querySelector(':scope > button');
4
- const selectedValue = trigger.querySelector(':scope > span');
4
+ const selectedLabel = trigger.querySelector(':scope > span');
5
5
  const popover = selectComponent.querySelector(':scope > [data-popover]');
6
6
  const listbox = popover.querySelector('[role="listbox"]');
7
7
  const input = selectComponent.querySelector(':scope > input[type="hidden"]');
@@ -20,6 +20,26 @@
20
20
  let visibleOptions = [...options];
21
21
  let activeIndex = -1;
22
22
 
23
+ const setActiveOption = (index) => {
24
+ if (activeIndex > -1 && options[activeIndex]) {
25
+ options[activeIndex].classList.remove('active');
26
+ }
27
+
28
+ activeIndex = index;
29
+
30
+ if (activeIndex > -1) {
31
+ const activeOption = options[activeIndex];
32
+ activeOption.classList.add('active');
33
+ if (activeOption.id) {
34
+ trigger.setAttribute('aria-activedescendant', activeOption.id);
35
+ } else {
36
+ trigger.removeAttribute('aria-activedescendant');
37
+ }
38
+ } else {
39
+ trigger.removeAttribute('aria-activedescendant');
40
+ }
41
+ };
42
+
23
43
  const hasTransition = () => {
24
44
  const style = getComputedStyle(popover);
25
45
  return parseFloat(style.transitionDuration) > 0 || parseFloat(style.transitionDelay) > 0;
@@ -27,7 +47,7 @@
27
47
 
28
48
  const updateValue = (option) => {
29
49
  if (option) {
30
- selectedValue.innerHTML = option.dataset.label || option.innerHTML;
50
+ selectedLabel.innerHTML = option.dataset.label || option.innerHTML;
31
51
  input.value = option.dataset.value;
32
52
  listbox.querySelector('[role="option"][aria-selected="true"]')?.removeAttribute('aria-selected');
33
53
  option.setAttribute('aria-selected', 'true');
@@ -54,49 +74,40 @@
54
74
  if (focusOnTrigger) trigger.focus();
55
75
  popover.setAttribute('aria-hidden', 'true');
56
76
  trigger.setAttribute('aria-expanded', 'false');
57
- trigger.removeAttribute('aria-activedescendant');
58
- if (activeIndex > -1) options[activeIndex]?.classList.remove('active');
59
- activeIndex = -1;
77
+ setActiveOption(-1);
60
78
  }
61
79
 
62
80
  const selectOption = (option) => {
63
81
  if (!option) return;
64
82
 
65
- if (option.dataset.value != null) {
83
+ const oldValue = input.value;
84
+ const newValue = option.dataset.value;
85
+
86
+ if (newValue != null && newValue !== oldValue) {
66
87
  updateValue(option);
67
88
  }
68
89
 
69
90
  closePopover();
70
91
 
71
- const event = new CustomEvent('change', {
72
- detail: { value: option.dataset.value },
73
- bubbles: true
74
- });
75
- selectComponent.dispatchEvent(event);
76
- };
77
-
78
- const selectByValue = (value) => {
79
- const option = options.find(opt => opt.dataset.value === value);
80
- if (option) {
81
- updateValue(option);
82
-
92
+ if (newValue !== oldValue) {
83
93
  const event = new CustomEvent('change', {
84
- detail: { value: option.dataset.value },
94
+ detail: { value: newValue },
85
95
  bubbles: true
86
96
  });
87
97
  selectComponent.dispatchEvent(event);
88
98
  }
89
99
  };
90
100
 
101
+ const selectByValue = (value) => {
102
+ const option = options.find(opt => opt.dataset.value === value);
103
+ selectOption(option);
104
+ };
105
+
91
106
  if (filter) {
92
107
  const filterOptions = () => {
93
108
  const searchTerm = filter.value.trim().toLowerCase();
94
109
 
95
- if (activeIndex > -1) {
96
- options[activeIndex].classList.remove('active');
97
- trigger.removeAttribute('aria-activedescendant');
98
- activeIndex = -1;
99
- }
110
+ setActiveOption(-1);
100
111
 
101
112
  visibleOptions = [];
102
113
  options.forEach(option => {
@@ -173,21 +184,31 @@
173
184
  }
174
185
 
175
186
  if (nextVisibleIndex !== currentVisibleIndex) {
176
- if (currentVisibleIndex > -1) {
177
- visibleOptions[currentVisibleIndex].classList.remove('active');
178
- }
179
-
180
187
  const newActiveOption = visibleOptions[nextVisibleIndex];
181
- newActiveOption.classList.add('active');
182
- activeIndex = options.indexOf(newActiveOption);
183
-
184
- if (newActiveOption.id) {
185
- trigger.setAttribute('aria-activedescendant', newActiveOption.id);
186
- }
188
+ setActiveOption(options.indexOf(newActiveOption));
187
189
  newActiveOption.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
188
190
  }
189
191
  };
190
192
 
193
+ listbox.addEventListener('mousemove', (event) => {
194
+ const option = event.target.closest('[role="option"]');
195
+ if (option && visibleOptions.includes(option)) {
196
+ const index = options.indexOf(option);
197
+ if (index !== activeIndex) {
198
+ setActiveOption(index);
199
+ }
200
+ }
201
+ });
202
+
203
+ listbox.addEventListener('mouseleave', () => {
204
+ const selectedOption = listbox.querySelector('[role="option"][aria-selected="true"]');
205
+ if (selectedOption) {
206
+ setActiveOption(options.indexOf(selectedOption));
207
+ } else {
208
+ setActiveOption(-1);
209
+ }
210
+ });
211
+
191
212
  trigger.addEventListener('keydown', handleKeyNavigation);
192
213
  if (filter) {
193
214
  filter.addEventListener('keydown', handleKeyNavigation);
@@ -213,14 +234,7 @@
213
234
 
214
235
  const selectedOption = listbox.querySelector('[role="option"][aria-selected="true"]');
215
236
  if (selectedOption) {
216
- if (activeIndex > -1) {
217
- options[activeIndex]?.classList.remove('active');
218
- }
219
- activeIndex = options.indexOf(selectedOption);
220
- selectedOption.classList.add('active');
221
- if (selectedOption.id) {
222
- trigger.setAttribute('aria-activedescendant', selectedOption.id);
223
- }
237
+ setActiveOption(options.indexOf(selectedOption));
224
238
  selectedOption.scrollIntoView({ block: 'nearest' });
225
239
  }
226
240
  };