stimulus_plumbers 0.2.9 → 0.3.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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +38 -0
  3. data/README.md +5 -4
  4. data/app/assets/javascripts/stimulus-plumbers/stimulus-plumbers-controllers.es.js +246 -269
  5. data/app/assets/javascripts/stimulus-plumbers/stimulus-plumbers-controllers.umd.js +1 -1
  6. data/lib/stimulus_plumbers/components/action_list/section.rb +6 -5
  7. data/lib/stimulus_plumbers/components/action_list.rb +3 -3
  8. data/lib/stimulus_plumbers/components/avatar.rb +4 -3
  9. data/lib/stimulus_plumbers/components/calendar/month/turbo/days_of_month.rb +62 -41
  10. data/lib/stimulus_plumbers/components/calendar/month/turbo/days_of_week.rb +13 -10
  11. data/lib/stimulus_plumbers/components/calendar.rb +36 -13
  12. data/lib/stimulus_plumbers/components/card/section.rb +3 -3
  13. data/lib/stimulus_plumbers/components/card.rb +3 -3
  14. data/lib/stimulus_plumbers/components/combobox/autocomplete.rb +8 -14
  15. data/lib/stimulus_plumbers/components/combobox/date.rb +6 -2
  16. data/lib/stimulus_plumbers/components/combobox/dropdown.rb +6 -2
  17. data/lib/stimulus_plumbers/components/combobox/popover.rb +9 -5
  18. data/lib/stimulus_plumbers/components/combobox/time.rb +1 -1
  19. data/lib/stimulus_plumbers/components/combobox/trigger.rb +19 -10
  20. data/lib/stimulus_plumbers/components/combobox.rb +33 -23
  21. data/lib/stimulus_plumbers/components/date_picker/navigation.rb +14 -22
  22. data/lib/stimulus_plumbers/components/divider.rb +16 -0
  23. data/lib/stimulus_plumbers/components/icon.rb +14 -20
  24. data/lib/stimulus_plumbers/components/popover/builder.rb +2 -2
  25. data/lib/stimulus_plumbers/components/popover.rb +11 -6
  26. data/lib/stimulus_plumbers/configuration.rb +3 -18
  27. data/lib/stimulus_plumbers/engine.rb +2 -2
  28. data/lib/stimulus_plumbers/form/builder.rb +40 -44
  29. data/lib/stimulus_plumbers/form/field.rb +96 -45
  30. data/lib/stimulus_plumbers/form/fields/error.rb +2 -2
  31. data/lib/stimulus_plumbers/form/fields/fieldset.rb +54 -0
  32. data/lib/stimulus_plumbers/form/fields/group.rb +2 -2
  33. data/lib/stimulus_plumbers/form/fields/hint.rb +2 -2
  34. data/lib/stimulus_plumbers/form/fields/input_group.rb +25 -0
  35. data/lib/stimulus_plumbers/form/fields/inputs/choice.rb +69 -0
  36. data/lib/stimulus_plumbers/form/fields/inputs/datetime.rb +81 -0
  37. data/lib/stimulus_plumbers/form/fields/inputs/file.rb +22 -0
  38. data/lib/stimulus_plumbers/form/fields/inputs/password.rb +59 -0
  39. data/lib/stimulus_plumbers/form/fields/inputs/search.rb +102 -0
  40. data/lib/stimulus_plumbers/form/fields/inputs/select/grouped.rb +56 -0
  41. data/lib/stimulus_plumbers/form/fields/inputs/select/timezone.rb +59 -0
  42. data/lib/stimulus_plumbers/form/fields/inputs/select/weekday.rb +45 -0
  43. data/lib/stimulus_plumbers/form/fields/inputs/select.rb +91 -0
  44. data/lib/stimulus_plumbers/form/fields/inputs/submit.rb +25 -0
  45. data/lib/stimulus_plumbers/form/fields/inputs/text.rb +37 -0
  46. data/lib/stimulus_plumbers/form/fields/inputs/text_area.rb +22 -0
  47. data/lib/stimulus_plumbers/form/fields/label.rb +13 -9
  48. data/lib/stimulus_plumbers/helpers/calendar_helper.rb +1 -1
  49. data/lib/stimulus_plumbers/helpers/combobox_helper.rb +29 -36
  50. data/lib/stimulus_plumbers/helpers/divider_helper.rb +11 -0
  51. data/lib/stimulus_plumbers/helpers.rb +2 -0
  52. data/lib/stimulus_plumbers/plumber/base.rb +1 -1
  53. data/lib/stimulus_plumbers/plumber/dispatcher/callable_inspector.rb +19 -0
  54. data/lib/stimulus_plumbers/plumber/dispatcher/instance_exec.rb +35 -0
  55. data/lib/stimulus_plumbers/plumber/dispatcher/klass_proxy.rb +34 -0
  56. data/lib/stimulus_plumbers/plumber/dispatcher/method_call.rb +36 -0
  57. data/lib/stimulus_plumbers/plumber/dispatcher.rb +4 -87
  58. data/lib/stimulus_plumbers/plumber/html_options.rb +6 -5
  59. data/lib/stimulus_plumbers/plumber/renderer.rb +2 -2
  60. data/lib/stimulus_plumbers/themes/base.rb +26 -5
  61. data/lib/stimulus_plumbers/themes/configuration.rb +38 -0
  62. data/lib/stimulus_plumbers/themes/schema/form/ranges.rb +14 -0
  63. data/lib/stimulus_plumbers/themes/schema/icon.rb +32 -0
  64. data/lib/stimulus_plumbers/themes/schema/ranges.rb +1 -1
  65. data/lib/stimulus_plumbers/themes/schema.rb +17 -5
  66. data/lib/stimulus_plumbers/version.rb +1 -1
  67. data/lib/stimulus_plumbers.rb +4 -2
  68. metadata +25 -21
  69. data/lib/stimulus_plumbers/form/fields/choice.rb +0 -25
  70. data/lib/stimulus_plumbers/form/fields/combobox.rb +0 -41
  71. data/lib/stimulus_plumbers/form/fields/file.rb +0 -16
  72. data/lib/stimulus_plumbers/form/fields/password.rb +0 -55
  73. data/lib/stimulus_plumbers/form/fields/renderer.rb +0 -52
  74. data/lib/stimulus_plumbers/form/fields/search.rb +0 -54
  75. data/lib/stimulus_plumbers/form/fields/select.rb +0 -33
  76. data/lib/stimulus_plumbers/form/fields/submit.rb +0 -23
  77. data/lib/stimulus_plumbers/form/fields/text.rb +0 -33
  78. data/lib/stimulus_plumbers/form/fields/text_area.rb +0 -16
  79. data/lib/stimulus_plumbers/themes/tailwind/action_list.rb +0 -33
  80. data/lib/stimulus_plumbers/themes/tailwind/avatar.rb +0 -52
  81. data/lib/stimulus_plumbers/themes/tailwind/button.rb +0 -89
  82. data/lib/stimulus_plumbers/themes/tailwind/calendar.rb +0 -80
  83. data/lib/stimulus_plumbers/themes/tailwind/card.rb +0 -24
  84. data/lib/stimulus_plumbers/themes/tailwind/combobox.rb +0 -75
  85. data/lib/stimulus_plumbers/themes/tailwind/form.rb +0 -108
  86. data/lib/stimulus_plumbers/themes/tailwind/layout.rb +0 -25
  87. data/lib/stimulus_plumbers/themes/tailwind_theme.rb +0 -31
@@ -1 +1 @@
1
- (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`@hotwired/stimulus`)):typeof define==`function`&&define.amd?define([`exports`,`@hotwired/stimulus`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.StimulusPlumbersControllers={},e.Stimulus))})(this,function(e,t){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var n=[`a[href]`,`area[href]`,`button:not([disabled])`,`input:not([disabled])`,`select:not([disabled])`,`textarea:not([disabled])`,`[tabindex]:not([tabindex="-1"])`,`audio[controls]`,`video[controls]`,`[contenteditable]:not([contenteditable="false"])`].join(`,`);function r(e){return Array.from(e.querySelectorAll(n)).filter(e=>i(e))}function i(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)}function a(e){let t=r(e);return t.length>0?(t[0].focus(),!0):!1}var o=class{constructor(e,t={}){this.container=e,this.previouslyFocused=null,this.options=t,this.isActive=!1}activate(){this.isActive||(this.previouslyFocused=document.activeElement,this.isActive=!0,this.options.initialFocus?this.options.initialFocus.focus():a(this.container),this.container.addEventListener(`keydown`,this.handleKeyDown))}deactivate(){if(!this.isActive)return;this.isActive=!1,this.container.removeEventListener(`keydown`,this.handleKeyDown);let e=this.options.returnFocus||this.previouslyFocused;e&&i(e)&&e.focus()}handleKeyDown=e=>{if(e.key===`Escape`&&this.options.escapeDeactivates){e.preventDefault(),this.deactivate();return}if(e.key!==`Tab`)return;let t=r(this.container);if(t.length===0)return;let n=t[0],i=t[t.length-1];e.shiftKey&&document.activeElement===n?(e.preventDefault(),i.focus()):!e.shiftKey&&document.activeElement===i&&(e.preventDefault(),n.focus())}},s=class{constructor(){this.savedElement=null}save(){this.savedElement=document.activeElement}restore(){this.savedElement&&i(this.savedElement)&&(this.savedElement.focus(),this.savedElement=null)}};function c(e,t){return e.key===t}function l(e){return e.key===`Enter`||e.key===` `}function u(e){return[`ArrowUp`,`ArrowDown`,`ArrowLeft`,`ArrowRight`].includes(e.key)}function d(e){e.preventDefault(),e.stopPropagation()}var f=class{constructor(e,t=0){this.items=e,this.currentIndex=t,this.updateTabIndex()}handleKeyDown(e){let t;switch(e.key){case`ArrowDown`:case`ArrowRight`:e.preventDefault(),t=(this.currentIndex+1)%this.items.length;break;case`ArrowUp`:case`ArrowLeft`:e.preventDefault(),t=this.currentIndex===0?this.items.length-1:this.currentIndex-1;break;case`Home`:e.preventDefault(),t=0;break;case`End`:e.preventDefault(),t=this.items.length-1;break;default:return}this.setCurrentIndex(t)}setCurrentIndex(e){e>=0&&e<this.items.length&&(this.currentIndex=e,this.updateTabIndex(),this.items[e].focus())}updateTabIndex(){this.items.forEach((e,t)=>{e.tabIndex=t===this.currentIndex?0:-1})}updateItems(e){this.items=e,this.currentIndex=Math.min(this.currentIndex,e.length-1),this.updateTabIndex()}},p=(e,t,n)=>{let r=document.querySelector(`[data-live-region="${e}"]`);return r||(r=document.createElement(`div`),r.className=`sr-only`,r.dataset.liveRegion=e,r.setAttribute(`aria-live`,e),r.setAttribute(`aria-atomic`,t.toString()),r.setAttribute(`aria-relevant`,n),document.body.appendChild(r)),r};function m(e,t={}){let{politeness:n=`polite`,atomic:r=!0,relevant:i=`additions text`}=t,a=p(n,r,i);a.textContent=``,setTimeout(()=>{a.textContent=e},100)}var h=(e=`a11y`)=>`${e}-${Math.random().toString(36).substr(2,9)}`,ee=(e,t=`element`)=>e.id||=h(t),g=(e,t,n)=>{e.setAttribute(t,n.toString())},te=(e,t)=>g(e,`aria-expanded`,t),_=(e,t)=>g(e,`aria-pressed`,t),ne=(e,t)=>g(e,`aria-checked`,t);function re(e,t){g(e,`aria-disabled`,t),t?e.setAttribute(`tabindex`,`-1`):e.removeAttribute(`tabindex`)}var v={menu:`menu`,listbox:`listbox`,tree:`tree`,grid:`grid`,dialog:`dialog`},y=(e,t,n)=>{Object.entries(t).forEach(([t,r])=>{e.setAttribute(t,r),n[t]=r})},b=(e,t,n)=>n||!e.hasAttribute(t);function x({trigger:e,target:t,role:n=null,override:r=!1}){let i={trigger:{},target:{}};if(!e||!t)return i;let a={},o={};if(n&&b(t,`role`,r)&&(o.role=n),t.id&&(b(e,`aria-controls`,r)&&(a[`aria-controls`]=t.id),n===`tooltip`&&b(e,`aria-describedby`,r)&&(a[`aria-describedby`]=t.id)),n&&b(e,`aria-haspopup`,r)){let e=v[n]||`true`;e&&(a[`aria-haspopup`]=e)}return y(t,o,i.target),y(e,a,i.trigger),i}var S=(e,t)=>{t.forEach(t=>{e.hasAttribute(t)&&e.removeAttribute(t)})};function C({trigger:e,target:t,attributes:n=null}){!e||!t||(S(e,n||[`aria-controls`,`aria-haspopup`,`aria-describedby`]),(!n||n.includes(`role`))&&S(t,[`role`]))}var w={get visibleOnly(){return!0},hiddenClass:null},T={get top(){return`bottom`},get bottom(){return`top`},get left(){return`right`},get right(){return`left`}};function E({x:e,y:t,width:n,height:r}){return{x:e,y:t,width:n,height:r,left:e,right:e+n,top:t,bottom:t+r}}function D(){return E({x:0,y:0,width:window.innerWidth||document.documentElement.clientWidth,height:window.innerHeight||document.documentElement.clientHeight})}function O(e){if(!(e instanceof HTMLElement))return!1;let t=D(),n=e.getBoundingClientRect(),r=n.top<=t.height&&n.top+n.height>0,i=n.left<=t.width&&n.left+n.width>0;return r&&i}function k(e){return e instanceof Date&&!isNaN(e)}function A(...e){if(e.length===0)throw`Missing values to parse as date`;if(e.length===1){let t=new Date(e[0]);if(e[0]&&k(t))return t}else{let t=new Date(...e);if(k(t))return t}}var ie={element:null,visible:null,dispatch:!0,prefix:``},j=class{constructor(e,t={}){this.controller=e;let{element:n,visible:r,dispatch:i,prefix:a}=Object.assign({},ie,t);this.element=n||e.element,this.visibleOnly=typeof r==`boolean`?r:w.visibleOnly,this.visibleCallback=typeof r==`string`?r:null,this.notify=!!i,this.prefix=typeof a==`string`&&a?a:e.identifier}get visible(){return this.element instanceof HTMLElement?this.visibleOnly?O(this.element)&&this.isVisible(this.element):!0:!1}isVisible(e){if(this.visibleCallback){let t=this.findCallback(this.visibleCallback);if(typeof t==`function`)return t(e)}return e instanceof HTMLElement?!e.hasAttribute(`hidden`):!1}dispatch(e,{target:t=null,prefix:n=null,detail:r=null}={}){if(this.notify)return this.controller.dispatch(e,{target:t||this.element,prefix:n||this.prefix,detail:r})}findCallback(e){if(typeof e!=`string`)return;let t=this,n=e.split(`.`).reduce((e,t)=>e&&e[t],t.controller);if(typeof n==`function`)return n.bind(t.controller);let r=e.split(`.`).reduce((e,t)=>e&&e[t],t);if(typeof r==`function`)return r.bind(t)}async awaitCallback(e,...t){if(typeof e==`string`&&(e=this.findCallback(e)),typeof e==`function`){let n=e(...t);return n instanceof Promise?await n:n}}},ae={normalize(e){return typeof e==`string`?e:``},validate(){return!0}};function oe(e){let t=0,n=!1;for(let r=e.length-1;r>=0;r--){let i=parseInt(e[r],10);n&&(i*=2,i>9&&(i-=9)),t+=i,n=!n}return t%10==0}var se=/\D/g,ce=/^\d{13,19}$/,le=/(.{4})(?=.)/g,ue={normalize(e){return typeof e==`string`?e.replace(se,``):``},validate(e){return typeof e!=`string`||!ce.test(e)?!1:oe(e)},format(e){return typeof e==`string`?e.replace(le,`$1 `):``}},M={1:10},N=/\D/g,de=/^\+\d{7,15}$/,fe={normalize(e){if(typeof e!=`string`)return``;let t=e.trimStart().startsWith(`+`),n=e.replace(N,``);return t?`+${n}`:n},validate(e){if(typeof e!=`string`)return!1;if(de.test(e))return!0;let t=e.replace(N,``);return Object.values(M).includes(t.length)},format(e){if(typeof e!=`string`)return``;let t=e.replace(N,``);for(let[e,n]of Object.entries(M)){if(t.length===n)return`(${t.slice(0,3)}) ${t.slice(3,6)}-${t.slice(6)}`;let r=n+e.length;if(t.length===r&&t.startsWith(e)){let n=t.slice(e.length);return`+${e} (${n.slice(0,3)}) ${n.slice(3,6)}-${n.slice(6)}`}}return e}},pe=/[^\d.,-]/g,P=/^-?\d+(\.\d+)?$/,F={normalize(e){if(typeof e!=`string`)return``;let t=e.replace(pe,``);if(!t)return``;let n=t.lastIndexOf(`,`),r=t.lastIndexOf(`.`);return n>-1&&r>-1?n>r?t.replace(/\./g,``).replace(`,`,`.`):t.replace(/,/g,``):n>-1?t.slice(n+1).length<=2?t.replace(`,`,`.`):t.replace(/,/g,``):t},validate(e){return typeof e==`string`?P.test(e):!1},format(e,t={}){if(typeof e!=`string`)return``;let n=parseFloat(e);if(isNaN(n))return e;let r=t.locale||`en-US`,i=t.currency||`USD`,a=t.fractionDigits===void 0?{}:{minimumFractionDigits:t.fractionDigits,maximumFractionDigits:t.fractionDigits};try{return new Intl.NumberFormat(r,{style:`currency`,currency:i,...a}).format(n)}catch{return e}}},I=/^\d{4}-\d{2}-\d{2}$/,L=/^(\d{1,4})[/\-.](\d{1,2})[/\-.](\d{1,4})$/,R=/\D/g,z={normalize(e){if(typeof e!=`string`)return``;let t=e.trim();if(I.test(t))return t;let n=t.match(L);if(n){let[,e,t,r]=n;if(e.length===4)return`${e}-${t.padStart(2,`0`)}-${r.padStart(2,`0`)}`;if(r.length===4)return`${r}-${e.padStart(2,`0`)}-${t.padStart(2,`0`)}`}let r=t.replace(R,``);if(r.length===8){let e=parseInt(r.slice(0,4),10);return e>=1e3&&e<=9999?`${r.slice(0,4)}-${r.slice(4,6)}-${r.slice(6,8)}`:`${r.slice(4,8)}-${r.slice(0,2)}-${r.slice(2,4)}`}return t},validate(e){if(typeof e!=`string`)return!1;let t=z.normalize(e);if(!I.test(t))return!1;let n=new Date(`${t}T00:00:00Z`);return!isNaN(n.getTime())&&n.toISOString().startsWith(t)},format(e,t={}){if(typeof e!=`string`)return``;let n=new Date(`${e}T00:00:00Z`);if(isNaN(n.getTime()))return e;let r=t.locale||`en-US`;try{return new Intl.DateTimeFormat(r,{year:t.year||`numeric`,month:t.month||`2-digit`,day:t.day||`2-digit`,timeZone:t.timeZone||`UTC`}).format(n)}catch{return e}}},B=/^([01]?\d|2[0-3]):([0-5]\d)$/,V={normalize(e){if(typeof e!=`string`)return``;let t=e.trim();if(B.test(t)){let[e,n]=t.split(`:`);return`${String(parseInt(e,10)).padStart(2,`0`)}:${n}`}let n=t.match(/^(\d{1,2}):(\d{2})\s*(AM|PM)$/i);if(n){let e=parseInt(n[1],10),t=n[2];return e=n[3].toUpperCase()===`AM`?e===12?0:e:e===12?12:e+12,e>23||parseInt(t,10)>59?``:`${String(e).padStart(2,`0`)}:${t}`}return``},validate(e){return V.normalize(e)!==``},format(e,t={}){if(typeof e!=`string`)return``;let n=e.match(/^(\d{2}):(\d{2})$/);if(!n)return e;let r=parseInt(n[1],10),i=n[2];if(t.format===`h24`)return`${String(r).padStart(2,`0`)}:${i}`;let a=r<12?`AM`:`PM`;return`${r%12||12}:${i} ${a}`}},H={PLAIN:`plain`,CREDIT_CARD:`creditCard`,PHONE:`phone`,CURRENCY:`currency`,DATE:`date`,TIME:`time`},U=new Map([[H.PLAIN,ae],[H.CREDIT_CARD,ue],[H.PHONE,fe],[H.CURRENCY,F],[H.DATE,z],[H.TIME,V]]),W={type:H.PLAIN,options:{}},G=class extends j{static register(e,t){U.set(e,t)}constructor(e,t={}){super(e,t),this.type=t.type??W.type,this.options=t.options??W.options,this.enhance()}enhance(){let e=this,t=U.get(e.type)??U.get(H.PLAIN),n={normalize:n=>t.normalize?.(n,e.options)??(typeof n==`string`?n:``),validate:n=>t.validate?.(n,e.options)??!0,format:n=>t.format?.(n,e.options)??(typeof n==`string`?n:``),mask:n=>t.mask?.(n,e.options)??null,maskable:()=>typeof t.mask==`function`};Object.defineProperty(this.controller,`formatter`,{get(){return n},configurable:!0})}},K=(e,t)=>new G(e,t),q=7,J={locales:[`default`],today:``,day:null,month:null,year:null,since:null,till:null,disabledDates:[],disabledWeekdays:[],disabledDays:[],disabledMonths:[],disabledYears:[],firstDayOfWeek:0,onNavigated:`navigated`},me=class extends j{constructor(e,t={}){super(e,t);let n=Object.assign({},J,t),{onNavigated:r,since:i,till:a,firstDayOfWeek:o}=n;this.onNavigated=r,this.since=A(i),this.till=A(a),this.firstDayOfWeek=0<=o&&o<7?o:J.firstDayOfWeek;let{disabledDates:s,disabledWeekdays:c,disabledDays:l,disabledMonths:u,disabledYears:d}=n;this.disabledDates=Array.isArray(s)?s:[],this.disabledWeekdays=Array.isArray(c)?c:[],this.disabledDays=Array.isArray(l)?l:[],this.disabledMonths=Array.isArray(u)?u:[],this.disabledYears=Array.isArray(d)?d:[];let{today:f,day:p,month:m,year:h}=n;this.now=A(f)||new Date,typeof h==`number`&&typeof m==`number`&&typeof p==`number`?this.current=A(h,m,p):this.current=this.now,this.build(),this.enhance()}build(){this.daysOfWeek=this.buildDaysOfWeek(),this.daysOfMonth=this.buildDaysOfMonth(),this.monthsOfYear=this.buildMonthsOfYear()}buildDaysOfWeek(){let e=new Intl.DateTimeFormat(this.localesValue,{weekday:`long`}),t=new Intl.DateTimeFormat(this.localesValue,{weekday:`short`}),n=new Date(`2024-10-06`),r=[];for(let i=this.firstDayOfWeek,a=i+7;i<a;i++){let a=new Date(n);a.setDate(n.getDate()+i),r.push({date:a,value:a.getDay(),long:e.format(a),short:t.format(a)})}return r}buildDaysOfMonth(){let e=this.month,t=this.year,n=[],r=e=>({current:this.month===e.getMonth()&&this.year===e.getFullYear(),date:e,value:e.getDate(),month:e.getMonth(),year:e.getFullYear(),iso:e.toISOString()}),i=new Date(t,e).getDay(),a=this.firstDayOfWeek-i;for(let i=a>0?a-7:a;i<0;i++){let a=new Date(t,e,i+1);n.push(r(a))}let o=new Date(t,e+1,0).getDate();for(let i=1;i<=o;i++){let a=new Date(t,e,i);n.push(r(a))}let s=n.length%q,c=s===0?0:q-s;for(let i=1;i<=c;i++){let a=new Date(t,e+1,i);n.push(r(a))}return n}buildMonthsOfYear(){let e=new Intl.DateTimeFormat(this.localesValue,{month:`long`}),t=new Intl.DateTimeFormat(this.localesValue,{month:`short`}),n=new Intl.DateTimeFormat(this.localesValue,{month:`numeric`}),r=[];for(let i=0;i<12;i++){let a=new Date(this.year,i);r.push({date:a,value:a.getMonth(),long:e.format(a),short:t.format(a),numeric:n.format(a)})}return r}get today(){return this.now}set today(e){if(!k(e))return;let t=this.month?this.month:e.getMonth(),n=this.year?this.year:e.getFullYear(),r=t==e.getMonth()&&n==e.getFullYear(),i=this.hasDayValue?this.day:r?e.getDate():1;this.now=new Date(n,t,i).toISOString()}get current(){return typeof this.year==`number`&&typeof this.month==`number`&&typeof this.day==`number`?A(this.year,this.month,this.day):null}set current(e){k(e)&&(this.day=e.getDate(),this.month=e.getMonth(),this.year=e.getFullYear())}navigate=async e=>{if(!k(e))return;let t=this.current,n=e.toISOString(),r=t.toISOString();this.dispatch(`navigate`,{detail:{from:r,to:n}}),this.current=e,this.build(),await this.awaitCallback(this.onNavigated,{from:r,to:n}),this.dispatch(`navigated`,{detail:{from:r,to:n}})};step=async(e,t)=>{if(t===0)return;let n=this.current;switch(e){case`year`:n.setFullYear(n.getFullYear()+t);break;case`month`:n.setMonth(n.getMonth()+t);break;case`day`:n.setDate(n.getDate()+t);break;default:return}await this.navigate(n)};isDisabled=e=>{if(!k(e))return!1;if(this.disabledDates.length){let t=e.getTime();for(let e of this.disabledDates)if(t===new Date(e).getTime())return!0}if(this.disabledWeekdays.length){let t=e.getDay(),n=this.daysOfWeek,r=n.findIndex(e=>e.value===t);if(r>=0){let e=n[r];for(let t of this.disabledWeekdays)if(e.value==t||e.short===t||e.long===t)return!0}}if(this.disabledDays.length){let t=e.getDate();for(let e of this.disabledDays)if(t==e)return!0}if(this.disabledMonths.length){let t=e.getMonth(),n=this.monthsOfYear,r=n.findIndex(e=>e.value===t);if(r>=0){let e=n[r];for(let t of this.disabledMonths)if(e.value==t||e.short===t||e.long===t)return!0}}if(this.disabledYears.length){let t=e.getFullYear();for(let e of this.disabledYears)if(t==e)return!0}return!1};isWithinRange=e=>{if(!k(e))return!1;let t=!0;return this.since&&(t&&=e>=this.since),this.till&&(t&&=e<=this.till),t};enhance(){let e=this;Object.assign(this.controller,{get calendar(){return{get today(){return e.today},get current(){return e.current},get day(){return e.day},get month(){return e.month},get year(){return e.year},get since(){return e.since},get till(){return e.till},get firstDayOfWeek(){return e.firstDayOfWeek},get disabledDates(){return e.disabledDates},get disabledWeekdays(){return e.disabledWeekdays},get disabledDays(){return e.disabledDays},get disabledMonths(){return e.disabledMonths},get disabledYears(){return e.disabledYears},get daysOfWeek(){return e.daysOfWeek},get daysOfMonth(){return e.daysOfMonth},get monthsOfYear(){return e.monthsOfYear},navigate:async t=>await e.navigate(t),step:async(t,n)=>await e.step(t,n),isDisabled:t=>e.isDisabled(t),isWithinRange:t=>e.isWithinRange(t)}}})}},he=(e,t)=>new me(e,t),ge=class extends j{constructor(e,t={}){super(e,t),this.debounceTimer=null,this.abortController=null}fuzzyFilter(e,t){let n=t.toLowerCase(),r=0;return e.querySelectorAll(`[role="option"]`).forEach(e=>{let t=this.fuzzyMatch(n,e.textContent.trim().toLowerCase());e.hidden=!t,t&&r++}),r}fuzzyMatch(e,t){let n=0;for(let r=0;r<t.length&&n<e.length;r++)t[r]===e[n]&&n++;return n===e.length}scheduleFetch(e,t,n){clearTimeout(this.debounceTimer),this.debounceTimer=setTimeout(()=>this.fetch(e,n),t)}async fetch(e,{url:t,field:n,onLoading:r,onLoaded:i,onError:a}){this.abortController?.abort(),this.abortController=new AbortController,r?.(!0);let o=new URL(t,window.location.href);o.searchParams.set(n,e);try{let e=await fetch(o,{signal:this.abortController.signal,headers:{Accept:`text/html`,"X-Requested-With":`XMLHttpRequest`}});if(!e.ok)throw Error(`${e.status}`);i?.(await e.text())}catch(e){e.name!==`AbortError`&&a?.(e)}finally{r?.(!1)}}cancel(){clearTimeout(this.debounceTimer),this.abortController?.abort()}},_e=(e,t)=>new ge(e,t),Y={content:null,url:``,reload:`never`,stale:3600,onLoad:`canLoad`,onLoading:`contentLoading`,onLoaded:`contentLoaded`},ve=class extends j{constructor(e,t={}){super(e,t);let n=Object.assign({},Y,t),{content:r,url:i,reload:a,stale:o}=n;this.content=r,this.url=i,this.reload=typeof a==`string`?a:Y.reload,this.stale=typeof o==`number`?o:Y.stale;let{onLoad:s,onLoading:c,onLoaded:l}=n;this.onLoad=s,this.onLoading=c,this.onLoaded=l,this.enhance()}get reloadable(){switch(this.reload){case`never`:return!1;case`always`:return!0;default:{let e=A(this.loadedAt);return e&&new Date-e>this.stale*1e3}}}contentLoadable=({url:e})=>!!e;contentLoading=async({url:e})=>e?await this.remoteContentLoader(e):await this.contentLoader();contentLoader=async()=>``;remoteContentLoader=async e=>(await fetch(e)).text();load=async()=>{if(this.loadedAt&&!this.reloadable)return;let e=this.findCallback(this.onLoad),t=await this.awaitCallback(e||this.contentLoadable,{url:this.url});if(this.dispatch(`load`,{detail:{url:this.url}}),!t)return;let n=this.url?await this.remoteContentLoader(this.url):await this.contentLoader();this.dispatch(`loading`,{detail:{url:this.url}}),n&&(await this.awaitCallback(this.onLoaded,{url:this.url,content:n}),this.loadedAt=new Date().getTime(),this.dispatch(`loaded`,{detail:{url:this.url,content:n}}))};enhance(){let e=this;Object.assign(this.controller,{load:e.load.bind(e)})}},ye=(e,t)=>new ve(e,t),be={trigger:null,events:[`click`],onDismissed:`dismissed`},xe=class extends j{constructor(e,t={}){super(e,t);let{trigger:n,events:r,onDismissed:i}=Object.assign({},be,t);this.onDismissed=i,this.trigger=n||this.element,this.events=r,this.enhance(),this.observe()}dismiss=async e=>{let{target:t}=e;t instanceof HTMLElement&&(this.element.contains(t)||this.visible&&(this.dispatch(`dismiss`),await this.awaitCallback(this.onDismissed,{target:this.trigger}),this.dispatch(`dismissed`)))};observe(){this.events.forEach(e=>{window.addEventListener(e,this.dismiss,!0)})}unobserve(){this.events.forEach(e=>{window.removeEventListener(e,this.dismiss,!0)})}enhance(){let e=this,t=e.controller.disconnect.bind(e.controller);Object.assign(this.controller,{disconnect:()=>{e.unobserve(),t()}})}},X=(e,t)=>new xe(e,t),Se={anchor:null,events:[`click`],placement:`bottom`,alignment:`start`,onFlipped:`flipped`,ariaRole:null,respectMotion:!0},Ce=class extends j{constructor(e,t={}){super(e,t);let{anchor:n,events:r,placement:i,alignment:a,onFlipped:o,ariaRole:s,respectMotion:c}=Object.assign({},Se,t);this.anchor=n,this.events=r,this.placement=i,this.alignment=a,this.onFlipped=o,this.ariaRole=s,this.respectMotion=c,this.prefersReducedMotion=window.matchMedia(`(prefers-reduced-motion: reduce)`).matches,this.anchor&&this.element&&x({trigger:this.anchor,target:this.element,role:this.ariaRole}),this.enhance(),this.observe()}flip=async()=>{if(!this.visible)return;this.dispatch(`flip`),window.getComputedStyle(this.element).position!=`absolute`&&(this.element.style.position=`absolute`);let e=this.flippedRect(this.anchor.getBoundingClientRect(),this.element.getBoundingClientRect());this.element.style.transition=this.respectMotion&&this.prefersReducedMotion?`none`:``;for(let[t,n]of Object.entries(e))this.element.style[t]=n;await this.awaitCallback(this.onFlipped,{target:this.element,placement:e}),this.dispatch(`flipped`,{detail:{placement:e}})};flippedRect(e,t){let n=this.quadrumRect(e,D()),r=[this.placement,T[this.placement]],i={};for(;!Object.keys(i).length&&r.length>0;){let a=r.shift();if(!this.biggerRectThan(n[a],t))continue;let o=this.quadrumPlacement(e,a,t),s=this.quadrumAlignment(e,a,o);i.top=`${s.top+window.scrollY}px`,i.left=`${s.left+window.scrollX}px`}return Object.keys(i).length||(i.top=``,i.left=``),i}quadrumRect(e,t){return{left:E({x:t.x,y:t.y,width:e.x-t.x,height:t.height}),right:E({x:e.x+e.width,y:t.y,width:t.width-(e.x+e.width),height:t.height}),top:E({x:t.x,y:t.y,width:t.width,height:e.y-t.y}),bottom:E({x:t.x,y:e.y+e.height,width:t.width,height:t.height-(e.y+e.height)})}}quadrumPlacement(e,t,n){switch(t){case`top`:return E({x:n.x,y:e.y-n.height,width:n.width,height:n.height});case`bottom`:return E({x:n.x,y:e.y+e.height,width:n.width,height:n.height});case`left`:return E({x:e.x-n.width,y:n.y,width:n.width,height:n.height});case`right`:return E({x:e.x+e.width,y:n.y,width:n.width,height:n.height});default:throw`Unable place at the quadrum, ${t}`}}quadrumAlignment(e,t,n){switch(t){case`top`:case`bottom`:{let t=e.x;return this.alignment===`center`?t=e.x+e.width/2-n.width/2:this.alignment===`end`&&(t=e.x+e.width-n.width),E({x:t,y:n.y,width:n.width,height:n.height})}case`left`:case`right`:{let t=e.y;return this.alignment===`center`?t=e.y+e.height/2-n.height/2:this.alignment===`end`&&(t=e.y+e.height-n.height),E({x:n.x,y:t,width:n.width,height:n.height})}default:throw`Unable align at the quadrum, ${t}`}}biggerRectThan(e,t){return e.height>=t.height&&e.width>=t.width}observe(){this.events.forEach(e=>{window.addEventListener(e,this.flip,!0)})}unobserve(){this.events.forEach(e=>{window.removeEventListener(e,this.flip,!0)})}enhance(){let e=this,t=e.controller.disconnect.bind(e.controller);Object.assign(this.controller,{disconnect:()=>{e.unobserve(),t()},flip:e.flip.bind(e)})}},we=(e,t)=>new Ce(e,t),Te={events:[`resize`],boundaries:[`top`,`left`,`right`],onShifted:`shifted`,respectMotion:!0},Ee=class extends j{constructor(e,t={}){super(e,t);let{onShifted:n,events:r,boundaries:i,respectMotion:a}=Object.assign({},Te,t);this.onShifted=n,this.events=r,this.boundaries=i,this.respectMotion=a,this.prefersReducedMotion=window.matchMedia(`(prefers-reduced-motion: reduce)`).matches,this.enhance(),this.observe()}shift=async()=>{if(!this.visible)return;this.dispatch(`shift`);let e=this.overflowRect(this.element.getBoundingClientRect(),this.elementTranslations(this.element)),t=e.left||e.right||0,n=e.top||e.bottom||0;this.element.style.transition=this.respectMotion&&this.prefersReducedMotion?`none`:``,this.element.style.transform=`translate(${t}px, ${n}px)`,await this.awaitCallback(this.onShifted,e),this.dispatch(`shifted`,{detail:e})};overflowRect(e,t){let n={},r=D(),i=E({x:e.x-t.x,y:e.y-t.y,width:e.width,height:e.height});for(let e of this.boundaries){let t=this.directionDistance(i,e,r),a=T[e];t<0?i[a]+t>=r[a]&&!n[a]&&(n[e]=t):n[e]=``}return n}directionDistance(e,t,n){switch(t){case`top`:case`left`:return e[t]-n[t];case`bottom`:case`right`:return n[t]-e[t];default:throw`Invalid direction to calcuate distance, ${t}`}}elementTranslations(e){let t=window.getComputedStyle(e),n=t.transform||t.webkitTransform||t.mozTransform;if(n===`none`||n===void 0)return{x:0,y:0};let r=n.includes(`3d`)?`3d`:`2d`,i=n.match(/matrix.*\((.+)\)/)[1].split(`, `);return r===`2d`?{x:Number(i[4]),y:Number(i[5])}:{x:0,y:0}}observe(){this.events.forEach(e=>{window.addEventListener(e,this.shift,!0)})}unobserve(){this.events.forEach(e=>{window.removeEventListener(e,this.shift,!0)})}enhance(){let e=this,t=e.controller.disconnect.bind(e.controller);Object.assign(this.controller,{disconnect:()=>{e.unobserve(),t()},shift:e.shift.bind(e)})}},De=(e,t)=>new Ee(e,t),Z={visibility:`visibility`,onShown:`shown`,onHidden:`hidden`},Oe=class extends j{constructor(e,t={}){let{visibility:n,onShown:r,onHidden:i,activator:a}=Object.assign({},Z,t),o=typeof n==`string`?n:Z.namespace,s=typeof t.visible==`string`?t.visible:`isVisible`;(typeof t.visible!=`boolean`||t.visible)&&(t.visible=`${o}.${s}`),super(e,t),this.visibility=o,this.visibilityResolver=s,this.onShown=r,this.onHidden=i,this.activator=a instanceof HTMLElement?a:null,this.enhance(),this.element instanceof HTMLElement&&this.activate(this.isVisible(this.element))}isVisible(e){if(!(e instanceof HTMLElement))return!1;let t=w.hiddenClass;return t?!e.classList.contains(t):!e.hasAttribute(`hidden`)}toggle(e,t){if(!(e instanceof HTMLElement))return;let n=w.hiddenClass;n?t?e.classList.remove(n):e.classList.add(n):t?e.removeAttribute(`hidden`):e.setAttribute(`hidden`,!0)}activate(e){this.activator&&this.activator.setAttribute(`aria-expanded`,e?`true`:`false`)}async show(){!(this.element instanceof HTMLElement)||this.isVisible(this.element)||(this.dispatch(`show`),this.toggle(this.element,!0),this.activate(!0),await this.awaitCallback(this.onShown,{target:this.element}),this.dispatch(`shown`))}async hide(){!(this.element instanceof HTMLElement)||!this.isVisible(this.element)||(this.dispatch(`hide`),this.toggle(this.element,!1),this.activate(!1),await this.awaitCallback(this.onHidden,{target:this.element}),this.dispatch(`hidden`))}enhance(){let e=this,t={show:e.show.bind(e),hide:e.hide.bind(e)};Object.defineProperty(t,`visible`,{get(){return e.isVisible(e.element)}}),Object.defineProperty(t,this.visibilityResolver,{value:e.isVisible.bind(e)}),Object.defineProperty(this.controller,this.visibility,{get(){return t}})}},Q=(e,t)=>new Oe(e,t),ke=class extends t.Controller{static targets=[`daysOfWeek`,`daysOfMonth`];static classes=[`dayOfWeek`,`dayOfMonth`];static values={locales:{type:Array,default:[`default`]},weekdayFormat:{type:String,default:`short`},dayFormat:{type:String,default:`numeric`},daysOfOtherMonth:{type:Boolean,default:!1}};initialize(){he(this)}connect(){this.draw()}navigated(){this.draw()}draw(){this.drawDaysOfWeek(),this.drawDaysOfMonth()}createDayElement(e,{selectable:t=!1,disabled:n=!1}={}){let r=document.createElement(t?`button`:`div`);return r.tabIndex=-1,e?r.textContent=e:r.setAttribute(`aria-hidden`,`true`),n&&(r instanceof HTMLButtonElement?r.disabled=!0:r.setAttribute(`aria-disabled`,`true`)),r}drawDaysOfWeek(){if(!this.hasDaysOfWeekTarget)return;let e=new Intl.DateTimeFormat(this.localesValue,{weekday:this.weekdayFormatValue}),t=[];for(let n of this.calendar.daysOfWeek){let r=this.createDayElement(e.format(n.date));r.setAttribute(`role`,`columnheader`),r.title=n.long,this.hasDayOfWeekClass&&r.classList.add(...this.dayOfWeekClasses),t.push(r)}let n=document.createElement(`div`);n.setAttribute(`role`,`row`),n.replaceChildren(...t),this.daysOfWeekTarget.replaceChildren(n)}drawDaysOfMonth(){if(!this.hasDaysOfMonthTarget)return;let e=this.calendar.today,t=new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime(),n=[];for(let e of this.calendar.daysOfMonth){let r=!e.current||this.calendar.isDisabled(e.date)||!this.calendar.isWithinRange(e.date),i=e.current||this.daysOfOtherMonthValue?e.value:``,a=this.createDayElement(i,{selectable:e.current,disabled:r});t===e.date.getTime()&&a.setAttribute(`aria-current`,`date`),this.hasDayOfMonthClass&&a.classList.add(...this.dayOfMonthClasses);let o=document.createElement(`time`);o.dateTime=e.iso,a.appendChild(o),n.push(a)}let r=[];for(let e=0;e<n.length;e+=7){let t=document.createElement(`div`);t.setAttribute(`role`,`row`);for(let r of n.slice(e,e+7))r.setAttribute(`role`,`gridcell`),t.appendChild(r);r.push(t)}this.daysOfMonthTarget.replaceChildren(...r)}},Ae=class extends t.Controller{onSelect(e){if(!(e.target instanceof HTMLElement))return;e.preventDefault();let t=e.target instanceof HTMLTimeElement?e.target.parentElement:e.target;if(t.disabled||t.getAttribute(`aria-disabled`)===`true`)return;this.dispatch(`selecting`,{target:t});let n=e.target instanceof HTMLTimeElement?e.target:e.target.querySelector(`time`);if(!n)return console.error(`unable to locate time element within ${t}`);let r=A(n.dateTime);if(!r)return console.error(`unable to parse ${n.dateTime} found within the time element`);this.select(r.toISOString())}select(e){let t=A(e);t&&this.dispatch(`selected`,{detail:{epoch:t.getTime(),iso:e}})}},je=class extends t.Controller{static targets=[`source`];static values={type:{type:String,default:`text/plain`}};onPaste(e){let t=e.clipboardData?.getData(this.typeValue)??``,n=Array.from(e.clipboardData?.types??[]);e.preventDefault(),this.dispatch(`pasted`,{detail:{text:t,types:n},bubbles:!0})}async copy(e){let t=e.params?.text??(this.hasSourceTarget?this.sourceTarget.value??this.sourceTarget.textContent??``:``);try{await navigator.clipboard.writeText(t),this.dispatch(`copied`,{detail:{text:t},bubbles:!0})}catch(e){this.dispatch(`copy-failed`,{detail:{error:e},bubbles:!0})}}},Me=class extends t.Controller{static targets=[`previous`,`next`,`day`,`month`,`year`];static outlets=[`calendar-month`];static values={date:String,locales:{type:Array,default:[`default`]},dayFormat:{type:String,default:`numeric`},monthFormat:{type:String,default:`long`},yearFormat:{type:String,default:`numeric`}};initialize(){this.previous=this.previous.bind(this),this.next=this.next.bind(this)}async calendarMonthOutletConnected(){if(this.dateValue){let e=A(this.dateValue);e&&await this.calendarMonthOutlet.calendar.navigate(e)}this.draw()}onSelect(e){this.dateValue=e.detail.iso,this.draw(),this.dispatch(`selected`,{detail:{value:e.detail.iso},bubbles:!0})}previousTargetConnected(e){e.addEventListener(`click`,this.previous)}previousTargetDisconnected(e){e.removeEventListener(`click`,this.previous)}async previous(){await this.calendarMonthOutlet.calendar.step(`month`,-1),this.draw()}nextTargetConnected(e){e.addEventListener(`click`,this.next)}nextTargetDisconnected(e){e.removeEventListener(`click`,this.next)}async next(){await this.calendarMonthOutlet.calendar.step(`month`,1),this.draw()}draw(){this.drawDay(),this.drawMonth(),this.drawYear()}drawDay(){if(!this.hasDayTarget||!this.hasCalendarMonthOutlet)return;let{year:e,month:t,day:n}=this.calendarMonthOutlet.calendar;this.dayTarget.textContent=new Intl.DateTimeFormat(this.localesValue,{day:this.dayFormatValue}).format(new Date(e,t,n))}drawMonth(){if(!this.hasMonthTarget||!this.hasCalendarMonthOutlet)return;let{year:e,month:t}=this.calendarMonthOutlet.calendar;this.monthTarget.textContent=new Intl.DateTimeFormat(this.localesValue,{month:this.monthFormatValue}).format(new Date(e,t))}drawYear(){if(!this.hasYearTarget||!this.hasCalendarMonthOutlet)return;let{year:e}=this.calendarMonthOutlet.calendar;this.yearTarget.textContent=new Intl.DateTimeFormat(this.localesValue,{year:this.yearFormatValue}).format(new Date(e,0))}},Ne=class extends t.Controller{static targets=[`listbox`,`loading`,`empty`];static values={url:{type:String,default:``},field:{type:String,default:`q`},delay:{type:Number,default:300}};initialize(){this.comboboxDropdown=_e(this)}onSelect(e){let t=e.target.closest(`[role="option"]`);!t||t.getAttribute(`aria-disabled`)===`true`||this.select(t.dataset.value??``)}select(e){let t=this.listboxTarget.querySelectorAll(`[role="option"]`);t.forEach(e=>e.setAttribute(`aria-selected`,`false`));let n=[...t].find(t=>t.dataset.value===e);n&&n.setAttribute(`aria-selected`,`true`),this.dispatch(`selected`,{detail:{value:e},bubbles:!0})}onNavigate(e){if([`ArrowUp`,`ArrowDown`,`Enter`,` `].includes(e.key)){if(e.preventDefault(),e.key===`Enter`||e.key===` `){this.listboxTarget.querySelector(`[aria-selected="true"]`)?.click();return}this.step(e.key===`ArrowDown`?1:-1)}}step(e){let t=[...this.listboxTarget.querySelectorAll(`[role="option"]:not([aria-disabled="true"]):not([hidden])`)];if(!t.length)return;let n=this.listboxTarget.querySelector(`[aria-selected="true"]`),r=t.indexOf(n),i=e>0?t[Math.min(r+1,t.length-1)]:t[Math.max(r-1,0)];!i||i===n||(t.forEach(e=>e.setAttribute(`aria-selected`,`false`)),i.setAttribute(`aria-selected`,`true`),i.scrollIntoView({block:`nearest`}))}filter(e){if(this.urlValue)this.comboboxDropdown.scheduleFetch(e,this.delayValue,{url:this.urlValue,field:this.fieldValue,onLoading:e=>this.setLoading(e),onLoaded:e=>{this.listboxTarget.innerHTML=e,this.setEmpty(this.listboxTarget.querySelectorAll(`[role="option"]`).length===0)},onError:e=>console.error(`[combobox-dropdown] fetch failed`,e)});else{let t=this.comboboxDropdown.fuzzyFilter(this.listboxTarget,e);this.setEmpty(t===0)}}showAll(){this.listboxTarget.querySelectorAll(`[role="option"]`).forEach(e=>e.hidden=!1),this.setEmpty(!1)}setLoading(e){this.hasLoadingTarget&&(this.loadingTarget.hidden=!e)}setEmpty(e){this.hasEmptyTarget&&(this.emptyTarget.hidden=!e)}disconnect(){this.comboboxDropdown.cancel()}},Pe=class extends t.Controller{static targets=[`hour`,`minute`,`period`];connect(){this.select(this.toH24())}onSelect(e){let t=e.target.closest(`[role="option"]`);t&&(t.closest(`[role="listbox"]`).querySelectorAll(`[role="option"]`).forEach(e=>e.setAttribute(`aria-selected`,`false`)),t.setAttribute(`aria-selected`,`true`),this.select(this.toH24()))}select(e){e&&this.dispatch(`selected`,{detail:{value:e},bubbles:!0})}onNavigate(e){[`ArrowUp`,`ArrowDown`].includes(e.key)&&(e.preventDefault(),this.step(e.currentTarget,e.key===`ArrowDown`?1:-1))}step(e,t){let n=[...e.querySelectorAll(`[role="option"]`)],r=e.querySelector(`[aria-selected="true"]`),i=n.indexOf(r),a=t>0?n[Math.min(i+1,n.length-1)]:n[Math.max(i-1,0)];!a||a===r||(n.forEach(e=>e.setAttribute(`aria-selected`,`false`)),a.setAttribute(`aria-selected`,`true`),a.scrollIntoView({block:`nearest`}),this.select(this.toH24()))}toH24(){let e=this.selectedValue(this.hourTarget),t=this.selectedValue(this.minuteTarget);if(!e||!t)return null;if(!this.hasPeriodTarget)return`${e}:${t}`;let n=this.selectedValue(this.periodTarget),r=parseInt(e,10);return r=n===`AM`?r===12?0:r:r===12?12:r+12,`${String(r).padStart(2,`0`)}:${t}`}selectedValue(e){return e?.querySelector(`[aria-selected="true"]`)?.dataset.value??null}},$=class extends t.Controller{static targets=[`trigger`];connect(){X(this,{trigger:this.hasTriggerTarget?this.triggerTarget:null})}},Fe=class extends t.Controller{static targets=[`anchor`,`reference`];static values={placement:{type:String,default:`bottom`},alignment:{type:String,default:`start`},role:{type:String,default:`tooltip`}};connect(){if(!this.hasReferenceTarget){console.error(`FlipperController requires a reference target. Add data-flipper-target="reference" to your element.`);return}if(!this.hasAnchorTarget){console.error(`FlipperController requires an anchor target. Add data-flipper-target="anchor" to your element.`);return}we(this,{element:this.referenceTarget,anchor:this.anchorTarget,placement:this.placementValue,alignment:this.alignmentValue,ariaRole:this.roleValue})}},Ie=class extends t.Controller{static targets=[`trigger`,`popover`,`value`];static values={value:String,minLength:{type:Number,default:1}};static outlets=[`combobox-dropdown`];connect(){X(this),this.hasPopoverTarget&&Q(this,{element:this.popoverTarget,activator:this.hasTriggerTarget?this.triggerTarget:null})}async dismissed(){await this.close()}async open(){this.hasPopoverTarget&&await this.visibility.show()}async close(){this.hasPopoverTarget&&await this.visibility.hide()}async toggle(){this.visibility?.visible?await this.close():await this.open()}async shown(){this.hasPopoverTarget&&a(this.popoverTarget)}async hidden(){this.hasTriggerTarget&&this.triggerTarget.focus()}async onSelect(e){e.detail?.value!==void 0&&(this.valueValue=e.detail.value),await this.close()}onInput(e){if(e.target!==this.triggerTarget)return;let t=e.target.value.trim();if(t.length<this.minLengthValue){this.hasComboboxDropdownOutlet&&this.comboboxDropdownOutlet.showAll();return}this.hasComboboxDropdownOutlet&&this.comboboxDropdownOutlet.filter(t)}valueValueChanged(e){this.hasValueTarget&&(this.valueTarget.value=e),this.dispatch(`changed`,{detail:{value:e}})}},Le=class extends t.Controller{static targets=[`input`,`toggle`];static values={type:{type:String,default:`plain`},options:{type:Object,default:{}},revealed:{type:Boolean,default:!1}};connect(){K(this,{type:this.typeValue,options:this.optionsValue}),this.format(this.readValue()),this.drawToggle()}typeValueChanged(){this.formatter&&(K(this,{type:this.typeValue,options:this.optionsValue}),this.format(this.readValue()),this.drawToggle())}optionsValueChanged(){this.formatter&&(K(this,{type:this.typeValue,options:this.optionsValue}),this.format(this.readValue()))}revealedValueChanged(){this.formatter&&(this.format(this.readValue()),this.drawToggle())}onChange(e){this.format(e?.detail?.value??``)}format(e){this.formatter&&this.onFormatting(e)}toggle(){!this.formatter.maskable()&&this.typeValue!==`password`||(this.revealedValue=!this.revealedValue)}onPaste(e){let t=e.detail?.text??``;if(!this.formatter||!t)return;let n=this.formatter.normalize(t);this.formatter.validate(n)&&this.format(n)}drawToggle(){if(!this.hasToggleTarget)return;let e=this.formatter?.maskable()||this.typeValue===`password`;this.toggleTarget.hidden=!e,e&&_(this.toggleTarget,this.revealedValue)}readValue(){return this.hasInputTarget?this.inputTarget instanceof HTMLInputElement?this.inputTarget.value:this.inputTarget.textContent:``}onFormatting(e){if(!this.formatter)return;if(this.typeValue===`password`){this.hasInputTarget&&(this.inputTarget.type=this.revealedValue?`text`:`password`);return}let t=this.formatter.normalize(e),n=this.revealedValue||!this.formatter.maskable()?this.formatter.format(t):this.formatter.mask(t);this.hasInputTarget&&(this.inputTarget instanceof HTMLInputElement?this.inputTarget.value=n:this.inputTarget.textContent=n),this.dispatch(`formatted`,{detail:{value:n}})}},Re=class extends t.Controller{static targets=[`input`,`clear`];initialize(){this.onInput=this.draw.bind(this),this.onEscape=this.handleEscape.bind(this)}connect(){this.draw()}inputTargetConnected(e){e.addEventListener(`input`,this.onInput),e.addEventListener(`keydown`,this.onEscape)}inputTargetDisconnected(e){e.removeEventListener(`input`,this.onInput),e.removeEventListener(`keydown`,this.onEscape)}clear(){this.hasInputTarget&&(this.inputTarget.value=``,this.draw(),this.inputTarget.focus(),this.inputTarget.dispatchEvent(new Event(`input`,{bubbles:!0})))}draw(){!this.hasInputTarget||!this.hasClearTarget||(this.clearTarget.hidden=this.inputTarget.value.length===0)}handleEscape(e){e.key===`Escape`&&this.inputTarget.value!==``&&(e.preventDefault(),this.clear())}},ze=class extends t.Controller{static targets=[`modal`,`overlay`];initialize(){this.onCancel=this.close.bind(this)}connect(){this.hasModalTarget||console.error(`ModalController requires a modal target. Add data-modal-target="modal" to your element.`)}modalTargetConnected(e){this.isNativeDialog=e instanceof HTMLDialogElement,this.isNativeDialog?(e.addEventListener(`cancel`,this.onCancel),e.addEventListener(`click`,this.onBackdropClick)):(this.focusTrap=new o(e,{escapeDeactivates:!0}),X(this,{element:e}))}modalTargetDisconnected(e){this.isNativeDialog&&(e.removeEventListener(`cancel`,this.onCancel),e.removeEventListener(`click`,this.onBackdropClick))}dismissed=()=>{this.close()};open(e){if(e&&e.preventDefault(),this.hasModalTarget){if(this.isNativeDialog)this.previouslyFocused=document.activeElement,this.modalTarget.showModal();else{let e=this.hasOverlayTarget?this.overlayTarget:this.modalTarget;e.hidden=!1,document.body.style.overflow=`hidden`,this.focusTrap&&this.focusTrap.activate()}m(`Modal opened`)}}close(e){if(e&&e.preventDefault(),this.hasModalTarget){if(this.isNativeDialog)this.modalTarget.close(),this.previouslyFocused&&this.previouslyFocused.isConnected&&setTimeout(()=>{this.previouslyFocused.focus()},0);else{let e=this.hasOverlayTarget?this.overlayTarget:this.modalTarget;e.hidden=!0,document.body.style.overflow=``,this.focusTrap&&this.focusTrap.deactivate()}m(`Modal closed`)}}onBackdropClick=e=>{let t=this.modalTarget.getBoundingClientRect();(e.clientY<t.top||e.clientY>t.bottom||e.clientX<t.left||e.clientX>t.right)&&this.close()}},Be=class extends t.Controller{static targets=[`content`];connect(){De(this,{element:this.hasContentTarget?this.contentTarget:null})}},Ve=class extends t.Controller{static targets=[`content`,`template`,`loader`,`activator`];static classes=[`hidden`];static values={url:String,loadedAt:String,reload:{type:String,default:`never`},staleAfter:{type:Number,default:3600}};connect(){ye(this,{element:this.hasContentTarget?this.contentTarget:null,url:this.hasUrlValue?this.urlValue:null}),this.hasContentTarget&&Q(this,{element:this.contentTarget,activator:this.hasActivatorTarget?this.activatorTarget:null}),this.hasLoaderTarget&&Q(this,{element:this.loaderTarget,visibility:`contentLoaderVisibility`})}async show(){await this.visibility.show()}async hide(){await this.visibility.hide()}async shown(){await this.load()}canLoad(){return this.hasContentTarget&&this.contentTarget.tagName.toLowerCase()===`turbo-frame`?(this.hasUrlValue&&this.contentTarget.setAttribute(`src`,this.urlValue),!1):!0}async contentLoading(){this.hasLoaderTarget&&await this.contentLoaderVisibility.show()}async contentLoaded({content:e}){this.hasContentTarget&&this.contentTarget.replaceChildren(this.getContentNode(e)),this.hasLoaderTarget&&await this.contentLoaderVisibility.hide()}getContentNode(e){if(typeof e==`string`){let t=document.createElement(`template`);return t.innerHTML=e,document.importNode(t.content,!0)}return document.importNode(e,!0)}contentLoader(){if(this.hasTemplateTarget)return this.templateTarget instanceof HTMLTemplateElement?this.templateTarget.content:this.templateTarget.innerHTML}};e.ARIA_HASPOPUP_VALUES=v,e.CalendarMonthController=ke,e.CalendarMonthObserverController=Ae,e.ClipboardController=je,e.ComboboxDateController=Me,e.ComboboxDropdownController=Ne,e.ComboboxTimeController=Pe,e.DismisserController=$,e.FOCUSABLE_SELECTOR=n,e.FORMATTER_TYPES=H,e.FlipperController=Fe,e.FocusRestoration=s,e.FocusTrap=o,e.Formatter=G,e.InputComboboxController=Ie,e.InputFormatController=Le,e.InputSearchController=Re,e.ModalController=ze,e.PannerController=Be,e.PopoverController=Ve,e.RovingTabIndex=f,e.announce=m,e.connectTriggerToTarget=x,e.disconnectTriggerFromTarget=C,e.ensureId=ee,e.focusFirst=a,e.generateId=h,e.getFocusableElements=r,e.isActivationKey=l,e.isArrowKey=u,e.isKey=c,e.isVisible=i,e.preventDefault=d,e.setAriaState=g,e.setChecked=ne,e.setDisabled=re,e.setExpanded=te,e.setPressed=_});
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`@hotwired/stimulus`)):typeof define==`function`&&define.amd?define([`exports`,`@hotwired/stimulus`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.StimulusPlumbersControllers={},e.Stimulus))})(this,function(e,t){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var n=[`a[href]`,`area[href]`,`button:not([disabled])`,`input:not([disabled])`,`select:not([disabled])`,`textarea:not([disabled])`,`[tabindex]:not([tabindex="-1"])`,`audio[controls]`,`video[controls]`,`[contenteditable]:not([contenteditable="false"])`].join(`,`);function r(e){return Array.from(e.querySelectorAll(n)).filter(e=>i(e))}function i(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)}function a(e){let t=r(e);return t.length>0?(t[0].focus(),!0):!1}var o=class{constructor(e,t={}){this.container=e,this.previouslyFocused=null,this.options=t,this.isActive=!1}activate(){this.isActive||(this.previouslyFocused=document.activeElement,this.isActive=!0,this.options.initialFocus?this.options.initialFocus.focus():a(this.container),this.container.addEventListener(`keydown`,this.handleKeyDown))}deactivate(){if(!this.isActive)return;this.isActive=!1,this.container.removeEventListener(`keydown`,this.handleKeyDown);let e=this.options.returnFocus||this.previouslyFocused;e&&i(e)&&e.focus()}handleKeyDown=e=>{if(e.key===`Escape`&&this.options.escapeDeactivates){e.preventDefault(),this.deactivate();return}if(e.key!==`Tab`)return;let t=r(this.container);if(t.length===0)return;let n=t[0],i=t[t.length-1];e.shiftKey&&document.activeElement===n?(e.preventDefault(),i.focus()):!e.shiftKey&&document.activeElement===i&&(e.preventDefault(),n.focus())}},s=class{constructor(){this.savedElement=null}save(){this.savedElement=document.activeElement}restore(){this.savedElement&&i(this.savedElement)&&(this.savedElement.focus(),this.savedElement=null)}};function c(e,t){return e.key===t}function l(e){return e.key===`Enter`||e.key===` `}function u(e){return[`ArrowUp`,`ArrowDown`,`ArrowLeft`,`ArrowRight`].includes(e.key)}function d(e){e.preventDefault(),e.stopPropagation()}var f=class{constructor(e,t=0){this.items=e,this.currentIndex=t,this.updateTabIndex()}handleKeyDown(e){let t;switch(e.key){case`ArrowDown`:case`ArrowRight`:e.preventDefault(),t=(this.currentIndex+1)%this.items.length;break;case`ArrowUp`:case`ArrowLeft`:e.preventDefault(),t=this.currentIndex===0?this.items.length-1:this.currentIndex-1;break;case`Home`:e.preventDefault(),t=0;break;case`End`:e.preventDefault(),t=this.items.length-1;break;default:return}this.setCurrentIndex(t)}setCurrentIndex(e){e>=0&&e<this.items.length&&(this.currentIndex=e,this.updateTabIndex(),this.items[e].focus())}updateTabIndex(){this.items.forEach((e,t)=>{e.tabIndex=t===this.currentIndex?0:-1})}updateItems(e){this.items=e,this.currentIndex=Math.min(this.currentIndex,e.length-1),this.updateTabIndex()}},p=(e,t,n)=>{let r=document.querySelector(`[data-live-region="${e}"]`);return r||(r=document.createElement(`div`),r.className=`sr-only`,r.dataset.liveRegion=e,r.setAttribute(`aria-live`,e),r.setAttribute(`aria-atomic`,t.toString()),r.setAttribute(`aria-relevant`,n),document.body.appendChild(r)),r};function m(e,t={}){let{politeness:n=`polite`,atomic:r=!0,relevant:i=`additions text`}=t,a=p(n,r,i);a.textContent=``,setTimeout(()=>{a.textContent=e},100)}var h=(e=`a11y`)=>`${e}-${Math.random().toString(36).substr(2,9)}`,ee=(e,t=`element`)=>e.id||=h(t),g=(e,t,n)=>{e.setAttribute(t,n.toString())},te=(e,t)=>g(e,`aria-expanded`,t),_=(e,t)=>g(e,`aria-pressed`,t),ne=(e,t)=>g(e,`aria-checked`,t);function re(e,t){g(e,`aria-disabled`,t),t?e.setAttribute(`tabindex`,`-1`):e.removeAttribute(`tabindex`)}var v={menu:`menu`,listbox:`listbox`,tree:`tree`,grid:`grid`,dialog:`dialog`},y=(e,t,n)=>{Object.entries(t).forEach(([t,r])=>{e.setAttribute(t,r),n[t]=r})},b=(e,t,n)=>n||!e.hasAttribute(t);function x({trigger:e,target:t,role:n=null,override:r=!1}){let i={trigger:{},target:{}};if(!e||!t)return i;let a={},o={};if(n&&b(t,`role`,r)&&(o.role=n),t.id&&(b(e,`aria-controls`,r)&&(a[`aria-controls`]=t.id),n===`tooltip`&&b(e,`aria-describedby`,r)&&(a[`aria-describedby`]=t.id)),n&&b(e,`aria-haspopup`,r)){let e=v[n]||`true`;e&&(a[`aria-haspopup`]=e)}return y(t,o,i.target),y(e,a,i.trigger),i}var S=(e,t)=>{t.forEach(t=>{e.hasAttribute(t)&&e.removeAttribute(t)})};function ie({trigger:e,target:t,attributes:n=null}){!e||!t||(S(e,n||[`aria-controls`,`aria-haspopup`,`aria-describedby`]),(!n||n.includes(`role`))&&S(t,[`role`]))}var C=class{constructor(){this._abortController=null,this._timer=null}schedule(e,t){clearTimeout(this._timer),this._timer=setTimeout(e,t)}async request(e,t={}){this._abortController?.abort(),this._abortController=new AbortController;let n=await fetch(e,{...t,signal:this._abortController.signal});if(!n.ok)throw Error(`${n.status}`);return n}cancel(){clearTimeout(this._timer),this._abortController?.abort()}};function w(e,t){let n=0;for(let r=0;r<t.length&&n<e.length;r++)t[r]===e[n]&&n++;return n===e.length}function ae(e,t){return t.includes(e)}function oe(e,t){return t.startsWith(e)}function se(e){return e===`contains`?ae:e===`prefix`?oe:w}function ce(e,t){return t===`textContent`?e.textContent?.trim().toLowerCase()??``:(e.getAttribute(t)??``).toLowerCase()}function T(e,t,n={}){let{strategy:r=`fuzzy`,matcher:i,fields:a=[`textContent`]}=n,o=typeof i==`function`?i:se(r),s=t.toLowerCase(),c=0;return e.querySelectorAll(`[role="option"]`).forEach(e=>{let t=a.some(t=>o(s,ce(e,t)));e.hidden=!t,t&&c++}),c}var E={get top(){return`bottom`},get bottom(){return`top`},get left(){return`right`},get right(){return`left`}};function D({x:e,y:t,width:n,height:r}){return{x:e,y:t,width:n,height:r,left:e,right:e+n,top:t,bottom:t+r}}function O(){return D({x:0,y:0,width:window.innerWidth||document.documentElement.clientWidth,height:window.innerHeight||document.documentElement.clientHeight})}function le(e){if(!(e instanceof HTMLElement))return!1;let t=O(),n=e.getBoundingClientRect(),r=n.top<=t.height&&n.top+n.height>0,i=n.left<=t.width&&n.left+n.width>0;return r&&i}var k={get visibleOnly(){return!0},hiddenClass:null},ue={element:null,visible:null,dispatch:!0,prefix:``},A=class{constructor(e,t={}){this.controller=e;let{element:n,visible:r,dispatch:i,prefix:a}=Object.assign({},ue,t);this.element=n||e.element,this.visibleOnly=typeof r==`boolean`?r:k.visibleOnly,this.visibleCallback=typeof r==`string`?r:null,this.notify=!!i,this.prefix=typeof a==`string`&&a?a:e.identifier}get visible(){return this.element instanceof HTMLElement?this.visibleOnly?le(this.element)&&this.isVisible(this.element):!0:!1}isVisible(e){if(this.visibleCallback){let t=this.findCallback(this.visibleCallback);if(typeof t==`function`)return t(e)}return e instanceof HTMLElement?!e.hasAttribute(`hidden`):!1}dispatch(e,{target:t=null,prefix:n=null,detail:r=null}={}){if(this.notify)return this.controller.dispatch(e,{target:t||this.element,prefix:n||this.prefix,detail:r})}findCallback(e){if(typeof e!=`string`)return;let t=this,n=e.split(`.`).reduce((e,t)=>e&&e[t],t.controller);if(typeof n==`function`)return n.bind(t.controller);let r=e.split(`.`).reduce((e,t)=>e&&e[t],t);if(typeof r==`function`)return r.bind(t)}async awaitCallback(e,...t){if(typeof e==`string`&&(e=this.findCallback(e)),typeof e==`function`){let n=e(...t);return n instanceof Promise?await n:n}}},de={normalize(e){return typeof e==`string`?e:``},validate(){return!0}};function fe(e){let t=0,n=!1;for(let r=e.length-1;r>=0;r--){let i=parseInt(e[r],10);n&&(i*=2,i>9&&(i-=9)),t+=i,n=!n}return t%10==0}var pe=/\D/g,me=/^\d{13,19}$/,he=/(.{4})(?=.)/g,ge={normalize(e){return typeof e==`string`?e.replace(pe,``):``},validate(e){return typeof e!=`string`||!me.test(e)?!1:fe(e)},format(e){return typeof e==`string`?e.replace(he,`$1 `):``}},j={1:10},M=/\D/g,_e=/^\+\d{7,15}$/,ve={normalize(e){if(typeof e!=`string`)return``;let t=e.trimStart().startsWith(`+`),n=e.replace(M,``);return t?`+${n}`:n},validate(e){if(typeof e!=`string`)return!1;if(_e.test(e))return!0;let t=e.replace(M,``);return Object.values(j).includes(t.length)},format(e){if(typeof e!=`string`)return``;let t=e.replace(M,``);for(let[e,n]of Object.entries(j)){if(t.length===n)return`(${t.slice(0,3)}) ${t.slice(3,6)}-${t.slice(6)}`;let r=n+e.length;if(t.length===r&&t.startsWith(e)){let n=t.slice(e.length);return`+${e} (${n.slice(0,3)}) ${n.slice(3,6)}-${n.slice(6)}`}}return e}},N=/[^\d.,-]/g,P=/^-?\d+(\.\d+)?$/,F={normalize(e){if(typeof e!=`string`)return``;let t=e.replace(N,``);if(!t)return``;let n=t.lastIndexOf(`,`),r=t.lastIndexOf(`.`);return n>-1&&r>-1?n>r?t.replace(/\./g,``).replace(`,`,`.`):t.replace(/,/g,``):n>-1?t.slice(n+1).length<=2?t.replace(`,`,`.`):t.replace(/,/g,``):t},validate(e){return typeof e==`string`?P.test(e):!1},format(e,t={}){if(typeof e!=`string`)return``;let n=parseFloat(e);if(isNaN(n))return e;let r=t.locale||`en-US`,i=t.currency||`USD`,a=t.fractionDigits===void 0?{}:{minimumFractionDigits:t.fractionDigits,maximumFractionDigits:t.fractionDigits};try{return new Intl.NumberFormat(r,{style:`currency`,currency:i,...a}).format(n)}catch{return e}}},I=/^\d{4}-\d{2}-\d{2}$/,ye=/^(\d{1,4})[/\-.](\d{1,2})[/\-.](\d{1,4})$/,be=/\D/g,L={normalize(e){if(typeof e!=`string`)return``;let t=e.trim();if(I.test(t))return t;let n=t.match(ye);if(n){let[,e,t,r]=n;if(e.length===4)return`${e}-${t.padStart(2,`0`)}-${r.padStart(2,`0`)}`;if(r.length===4)return`${r}-${e.padStart(2,`0`)}-${t.padStart(2,`0`)}`}let r=t.replace(be,``);if(r.length===8){let e=parseInt(r.slice(0,4),10);return e>=1e3&&e<=9999?`${r.slice(0,4)}-${r.slice(4,6)}-${r.slice(6,8)}`:`${r.slice(4,8)}-${r.slice(0,2)}-${r.slice(2,4)}`}return t},validate(e){if(typeof e!=`string`)return!1;let t=L.normalize(e);if(!I.test(t))return!1;let n=new Date(`${t}T00:00:00Z`);return!isNaN(n.getTime())&&n.toISOString().startsWith(t)},format(e,t={}){if(typeof e!=`string`)return``;let n=new Date(`${e}T00:00:00Z`);if(isNaN(n.getTime()))return e;let r=t.locale||`en-US`;try{return new Intl.DateTimeFormat(r,{year:t.year||`numeric`,month:t.month||`2-digit`,day:t.day||`2-digit`,timeZone:t.timeZone||`UTC`}).format(n)}catch{return e}}},xe=/^([01]?\d|2[0-3]):([0-5]\d)$/,R={normalize(e){if(typeof e!=`string`)return``;let t=e.trim();if(xe.test(t)){let[e,n]=t.split(`:`);return`${String(parseInt(e,10)).padStart(2,`0`)}:${n}`}let n=t.match(/^(\d{1,2}):(\d{2})\s*(AM|PM)$/i);if(n){let e=parseInt(n[1],10),t=n[2];return e=n[3].toUpperCase()===`AM`?e===12?0:e:e===12?12:e+12,e>23||parseInt(t,10)>59?``:`${String(e).padStart(2,`0`)}:${t}`}return``},validate(e){return R.normalize(e)!==``},format(e,t={}){if(typeof e!=`string`)return``;let n=e.match(/^(\d{2}):(\d{2})$/);if(!n)return e;let r=parseInt(n[1],10),i=n[2];if(t.format===`h24`)return`${String(r).padStart(2,`0`)}:${i}`;let a=r<12?`AM`:`PM`;return`${r%12||12}:${i} ${a}`}},z={PLAIN:`plain`,CREDIT_CARD:`creditCard`,PHONE:`phone`,CURRENCY:`currency`,DATE:`date`,TIME:`time`},B=new Map([[z.PLAIN,de],[z.CREDIT_CARD,ge],[z.PHONE,ve],[z.CURRENCY,F],[z.DATE,L],[z.TIME,R]]),V={type:z.PLAIN,options:{}},H=class extends A{static register(e,t){B.set(e,t)}constructor(e,t={}){super(e,t),this.type=t.type??V.type,this.options=t.options??V.options,this.enhance()}enhance(){let e=this,t=B.get(e.type)??B.get(z.PLAIN),n={normalize:n=>t.normalize?.(n,e.options)??(typeof n==`string`?n:``),validate:n=>t.validate?.(n,e.options)??!0,format:n=>t.format?.(n,e.options)??(typeof n==`string`?n:``),mask:n=>t.mask?.(n,e.options)??null,maskable:()=>typeof t.mask==`function`};Object.defineProperty(this.controller,`formatter`,{get(){return n},configurable:!0})}},U=(e,t)=>new H(e,t);function W(e){return e instanceof Date&&!isNaN(e)}function G(...e){if(e.length===0)throw`Missing values to parse as date`;if(e.length===1){let t=new Date(e[0]);if(e[0]&&W(t))return t}else{let t=new Date(...e);if(W(t))return t}}var K=7,q={locales:[`default`],today:``,day:null,month:null,year:null,since:null,till:null,disabledDates:[],disabledWeekdays:[],disabledDays:[],disabledMonths:[],disabledYears:[],firstDayOfWeek:0,onNavigated:`navigated`},Se=class extends A{constructor(e,t={}){super(e,t);let n=Object.assign({},q,t),{onNavigated:r,since:i,till:a,firstDayOfWeek:o}=n;this.onNavigated=r,this.since=G(i),this.till=G(a),this.firstDayOfWeek=0<=o&&o<7?o:q.firstDayOfWeek;let{disabledDates:s,disabledWeekdays:c,disabledDays:l,disabledMonths:u,disabledYears:d}=n;this.disabledDates=Array.isArray(s)?s:[],this.disabledWeekdays=Array.isArray(c)?c:[],this.disabledDays=Array.isArray(l)?l:[],this.disabledMonths=Array.isArray(u)?u:[],this.disabledYears=Array.isArray(d)?d:[];let{today:f,day:p,month:m,year:h}=n;this.now=G(f)||new Date,typeof h==`number`&&typeof m==`number`&&typeof p==`number`?this.current=G(h,m,p):this.current=this.now,this.build(),this.enhance()}build(){this.daysOfWeek=this.buildDaysOfWeek(),this.daysOfMonth=this.buildDaysOfMonth(),this.monthsOfYear=this.buildMonthsOfYear()}buildDaysOfWeek(){let e=new Intl.DateTimeFormat(this.localesValue,{weekday:`long`}),t=new Intl.DateTimeFormat(this.localesValue,{weekday:`short`}),n=new Date(`2024-10-06`),r=[];for(let i=this.firstDayOfWeek,a=i+7;i<a;i++){let a=new Date(n);a.setDate(n.getDate()+i),r.push({date:a,value:a.getDay(),long:e.format(a),short:t.format(a)})}return r}buildDaysOfMonth(){let e=this.month,t=this.year,n=[],r=e=>({current:this.month===e.getMonth()&&this.year===e.getFullYear(),date:e,value:e.getDate(),month:e.getMonth(),year:e.getFullYear(),iso:e.toISOString()}),i=new Date(t,e).getDay(),a=this.firstDayOfWeek-i;for(let i=a>0?a-7:a;i<0;i++){let a=new Date(t,e,i+1);n.push(r(a))}let o=new Date(t,e+1,0).getDate();for(let i=1;i<=o;i++){let a=new Date(t,e,i);n.push(r(a))}let s=n.length%K,c=s===0?0:K-s;for(let i=1;i<=c;i++){let a=new Date(t,e+1,i);n.push(r(a))}return n}buildMonthsOfYear(){let e=new Intl.DateTimeFormat(this.localesValue,{month:`long`}),t=new Intl.DateTimeFormat(this.localesValue,{month:`short`}),n=new Intl.DateTimeFormat(this.localesValue,{month:`numeric`}),r=[];for(let i=0;i<12;i++){let a=new Date(this.year,i);r.push({date:a,value:a.getMonth(),long:e.format(a),short:t.format(a),numeric:n.format(a)})}return r}get today(){return this.now}set today(e){if(!W(e))return;let t=this.month?this.month:e.getMonth(),n=this.year?this.year:e.getFullYear(),r=t==e.getMonth()&&n==e.getFullYear(),i=this.hasDayValue?this.day:r?e.getDate():1;this.now=new Date(n,t,i).toISOString()}get current(){return typeof this.year==`number`&&typeof this.month==`number`&&typeof this.day==`number`?G(this.year,this.month,this.day):null}set current(e){W(e)&&(this.day=e.getDate(),this.month=e.getMonth(),this.year=e.getFullYear())}navigate=async e=>{if(!W(e))return;let t=this.current,n=e.toISOString(),r=t.toISOString();this.dispatch(`navigate`,{detail:{from:r,to:n}}),this.current=e,this.build(),await this.awaitCallback(this.onNavigated,{from:r,to:n}),this.dispatch(`navigated`,{detail:{from:r,to:n}})};step=async(e,t)=>{if(t===0)return;let n=this.current;switch(e){case`year`:n.setFullYear(n.getFullYear()+t);break;case`month`:n.setMonth(n.getMonth()+t);break;case`day`:n.setDate(n.getDate()+t);break;default:return}await this.navigate(n)};isDisabled=e=>{if(!W(e))return!1;if(this.disabledDates.length){let t=e.getTime();for(let e of this.disabledDates)if(t===new Date(e).getTime())return!0}if(this.disabledWeekdays.length){let t=e.getDay(),n=this.daysOfWeek,r=n.findIndex(e=>e.value===t);if(r>=0){let e=n[r];for(let t of this.disabledWeekdays)if(e.value==t||e.short===t||e.long===t)return!0}}if(this.disabledDays.length){let t=e.getDate();for(let e of this.disabledDays)if(t==e)return!0}if(this.disabledMonths.length){let t=e.getMonth(),n=this.monthsOfYear,r=n.findIndex(e=>e.value===t);if(r>=0){let e=n[r];for(let t of this.disabledMonths)if(e.value==t||e.short===t||e.long===t)return!0}}if(this.disabledYears.length){let t=e.getFullYear();for(let e of this.disabledYears)if(t==e)return!0}return!1};isWithinRange=e=>{if(!W(e))return!1;let t=!0;return this.since&&(t&&=e>=this.since),this.till&&(t&&=e<=this.till),t};enhance(){let e=this;Object.assign(this.controller,{get calendar(){return{get today(){return e.today},get current(){return e.current},get day(){return e.day},get month(){return e.month},get year(){return e.year},get since(){return e.since},get till(){return e.till},get firstDayOfWeek(){return e.firstDayOfWeek},get disabledDates(){return e.disabledDates},get disabledWeekdays(){return e.disabledWeekdays},get disabledDays(){return e.disabledDays},get disabledMonths(){return e.disabledMonths},get disabledYears(){return e.disabledYears},get daysOfWeek(){return e.daysOfWeek},get daysOfMonth(){return e.daysOfMonth},get monthsOfYear(){return e.monthsOfYear},navigate:async t=>await e.navigate(t),step:async(t,n)=>await e.step(t,n),isDisabled:t=>e.isDisabled(t),isWithinRange:t=>e.isWithinRange(t)}}})}},Ce=(e,t)=>new Se(e,t),J={content:null,url:``,reload:`never`,stale:3600,onLoad:`canLoad`,onLoaded:`contentLoaded`},we=class extends A{constructor(e,t={}){super(e,t);let n=Object.assign({},J,t),{content:r,url:i,reload:a,stale:o}=n;this.content=r,this.url=i,this.reload=typeof a==`string`?a:J.reload,this.stale=typeof o==`number`?o:J.stale;let{onLoad:s,onLoaded:c}=n;this.onLoad=s,this.onLoaded=c,this._requestor=new C,this.enhance()}get reloadable(){switch(this.reload){case`never`:return!1;case`always`:return!0;default:{let e=G(this.loadedAt);return e&&new Date-e>this.stale*1e3}}}contentLoadable=({url:e})=>!!e;contentLoader=async()=>``;remoteContentLoader=async e=>(await this._requestor.request(e)).text();load=async()=>{if(this.loadedAt&&!this.reloadable)return;let e=this.findCallback(this.onLoad),t=await this.awaitCallback(e||this.contentLoadable,{url:this.url});if(this.dispatch(`load`,{detail:{url:this.url}}),!t)return;this.dispatch(`loading`,{detail:{url:this.url}});let n=this.url?await this.remoteContentLoader(this.url):await this.contentLoader();n&&(await this.awaitCallback(this.onLoaded,{url:this.url,content:n}),this.loadedAt=new Date().getTime(),this.dispatch(`loaded`,{detail:{url:this.url,content:n}}))};enhance(){let e=this;Object.assign(this.controller,{load:e.load.bind(e)})}},Te=(e,t)=>new we(e,t),Y=class extends A{observe(e){this._handler=e,this.events.forEach(t=>window.addEventListener(t,e,!0))}unobserve(){this._handler&&this.events.forEach(e=>window.removeEventListener(e,this._handler,!0))}enhance(){let e=this,t=this.controller.disconnect?.bind(this.controller)||(()=>{});this.controller.disconnect=()=>{e.unobserve(),t()}}},Ee={trigger:null,events:[`click`],onDismissed:`dismissed`},De=class extends Y{constructor(e,t={}){super(e,t);let{trigger:n,events:r,onDismissed:i}=Object.assign({},Ee,t);this.onDismissed=i,this.trigger=n||this.element,this.events=r,this.enhance(),this.observe(this.dismiss)}dismiss=async e=>{let{target:t}=e;t instanceof HTMLElement&&(this.element.contains(t)||this.visible&&(this.dispatch(`dismiss`),await this.awaitCallback(this.onDismissed,{target:this.trigger}),this.dispatch(`dismissed`)))}},X=(e,t)=>new De(e,t),Oe={anchor:null,events:[`click`],placement:`bottom`,alignment:`start`,onFlipped:`flipped`,ariaRole:null,respectMotion:!0},ke=class extends Y{constructor(e,t={}){super(e,t);let{anchor:n,events:r,placement:i,alignment:a,onFlipped:o,ariaRole:s,respectMotion:c}=Object.assign({},Oe,t);this.anchor=n,this.events=r,this.placement=i,this.alignment=a,this.onFlipped=o,this.ariaRole=s,this.respectMotion=c,this.prefersReducedMotion=window.matchMedia(`(prefers-reduced-motion: reduce)`).matches,this.anchor&&this.element&&x({trigger:this.anchor,target:this.element,role:this.ariaRole}),this.enhance(),this.observe(this.flip)}flip=async()=>{if(!this.visible)return;this.dispatch(`flip`),window.getComputedStyle(this.element).position!=`absolute`&&(this.element.style.position=`absolute`);let e=this.flippedRect(this.anchor.getBoundingClientRect(),this.element.getBoundingClientRect());this.element.style.transition=this.respectMotion&&this.prefersReducedMotion?`none`:``;for(let[t,n]of Object.entries(e))this.element.style[t]=n;await this.awaitCallback(this.onFlipped,{target:this.element,placement:e}),this.dispatch(`flipped`,{detail:{placement:e}})};flippedRect(e,t){let n=this.quadrumRect(e,O()),r=[this.placement,E[this.placement]],i={};for(;!Object.keys(i).length&&r.length>0;){let a=r.shift();if(!this.biggerRectThan(n[a],t))continue;let o=this.quadrumPlacement(e,a,t),s=this.quadrumAlignment(e,a,o);i.top=`${s.top+window.scrollY}px`,i.left=`${s.left+window.scrollX}px`}return Object.keys(i).length||(i.top=``,i.left=``),i}quadrumRect(e,t){return{left:D({x:t.x,y:t.y,width:e.x-t.x,height:t.height}),right:D({x:e.x+e.width,y:t.y,width:t.width-(e.x+e.width),height:t.height}),top:D({x:t.x,y:t.y,width:t.width,height:e.y-t.y}),bottom:D({x:t.x,y:e.y+e.height,width:t.width,height:t.height-(e.y+e.height)})}}quadrumPlacement(e,t,n){switch(t){case`top`:return D({x:n.x,y:e.y-n.height,width:n.width,height:n.height});case`bottom`:return D({x:n.x,y:e.y+e.height,width:n.width,height:n.height});case`left`:return D({x:e.x-n.width,y:n.y,width:n.width,height:n.height});case`right`:return D({x:e.x+e.width,y:n.y,width:n.width,height:n.height});default:throw`Unable place at the quadrum, ${t}`}}quadrumAlignment(e,t,n){switch(t){case`top`:case`bottom`:{let t=e.x;return this.alignment===`center`?t=e.x+e.width/2-n.width/2:this.alignment===`end`&&(t=e.x+e.width-n.width),D({x:t,y:n.y,width:n.width,height:n.height})}case`left`:case`right`:{let t=e.y;return this.alignment===`center`?t=e.y+e.height/2-n.height/2:this.alignment===`end`&&(t=e.y+e.height-n.height),D({x:n.x,y:t,width:n.width,height:n.height})}default:throw`Unable align at the quadrum, ${t}`}}biggerRectThan(e,t){return e.height>=t.height&&e.width>=t.width}enhance(){super.enhance(),this.controller.flip=this.flip}},Ae=(e,t)=>new ke(e,t),je={events:[`resize`],boundaries:[`top`,`left`,`right`],onShifted:`shifted`,respectMotion:!0},Me=class extends Y{constructor(e,t={}){super(e,t);let{onShifted:n,events:r,boundaries:i,respectMotion:a}=Object.assign({},je,t);this.onShifted=n,this.events=r,this.boundaries=i,this.respectMotion=a,this.prefersReducedMotion=window.matchMedia(`(prefers-reduced-motion: reduce)`).matches,this.enhance(),this.observe(this.shift)}shift=async()=>{if(!this.visible)return;this.dispatch(`shift`);let e=this.overflowRect(this.element.getBoundingClientRect(),this.elementTranslations(this.element)),t=e.left||e.right||0,n=e.top||e.bottom||0;this.element.style.transition=this.respectMotion&&this.prefersReducedMotion?`none`:``,this.element.style.transform=`translate(${t}px, ${n}px)`,await this.awaitCallback(this.onShifted,e),this.dispatch(`shifted`,{detail:e})};overflowRect(e,t){let n={},r=O(),i=D({x:e.x-t.x,y:e.y-t.y,width:e.width,height:e.height});for(let e of this.boundaries){let t=this.directionDistance(i,e,r),a=E[e];t<0?i[a]+t>=r[a]&&!n[a]&&(n[e]=t):n[e]=``}return n}directionDistance(e,t,n){switch(t){case`top`:case`left`:return e[t]-n[t];case`bottom`:case`right`:return n[t]-e[t];default:throw`Invalid direction to calcuate distance, ${t}`}}elementTranslations(e){let t=window.getComputedStyle(e),n=t.transform||t.webkitTransform||t.mozTransform;if(n===`none`||n===void 0)return{x:0,y:0};let r=n.includes(`3d`)?`3d`:`2d`,i=n.match(/matrix.*\((.+)\)/)[1].split(`, `);return r===`2d`?{x:Number(i[4]),y:Number(i[5])}:{x:0,y:0}}enhance(){super.enhance(),this.controller.shift=this.shift}},Ne=(e,t)=>new Me(e,t),Z={visibility:`visibility`,onShown:`shown`,onHidden:`hidden`},Pe=class extends A{constructor(e,t={}){let{visibility:n,onShown:r,onHidden:i,activator:a}=Object.assign({},Z,t),o=typeof n==`string`?n:Z.namespace,s=typeof t.visible==`string`?t.visible:`isVisible`;(typeof t.visible!=`boolean`||t.visible)&&(t.visible=`${o}.${s}`),super(e,t),this.visibility=o,this.visibilityResolver=s,this.onShown=r,this.onHidden=i,this.activator=a instanceof HTMLElement?a:null,this.enhance(),this.element instanceof HTMLElement&&this.activate(this.isVisible(this.element))}isVisible(e){if(!(e instanceof HTMLElement))return!1;let t=k.hiddenClass;return t?!e.classList.contains(t):!e.hasAttribute(`hidden`)}toggle(e,t){if(!(e instanceof HTMLElement))return;let n=k.hiddenClass;n?t?e.classList.remove(n):e.classList.add(n):t?e.removeAttribute(`hidden`):e.setAttribute(`hidden`,!0)}activate(e){this.activator&&this.activator.setAttribute(`aria-expanded`,e?`true`:`false`)}async show(){!(this.element instanceof HTMLElement)||this.isVisible(this.element)||(this.dispatch(`show`),this.toggle(this.element,!0),this.activate(!0),await this.awaitCallback(this.onShown,{target:this.element}),this.dispatch(`shown`))}async hide(){!(this.element instanceof HTMLElement)||!this.isVisible(this.element)||(this.dispatch(`hide`),this.toggle(this.element,!1),this.activate(!1),await this.awaitCallback(this.onHidden,{target:this.element}),this.dispatch(`hidden`))}enhance(){let e=this,t={show:e.show.bind(e),hide:e.hide.bind(e)};Object.defineProperty(t,`visible`,{get(){return e.isVisible(e.element)}}),Object.defineProperty(t,this.visibilityResolver,{value:e.isVisible.bind(e)}),Object.defineProperty(this.controller,this.visibility,{get(){return t}})}},Q=(e,t)=>new Pe(e,t),Fe=class extends t.Controller{static targets=[`daysOfWeek`,`daysOfMonth`];static classes=[`dayOfWeek`,`dayOfMonth`,`week`];static values={locales:{type:Array,default:[`default`]},weekdayFormat:{type:String,default:`short`},dayFormat:{type:String,default:`numeric`},daysOfOtherMonth:{type:Boolean,default:!1}};initialize(){Ce(this)}connect(){this.draw()}navigated(){this.draw()}draw(){this.drawDaysOfWeek(),this.drawDaysOfMonth()}createDayElement(e,{selectable:t=!1,disabled:n=!1}={}){let r=document.createElement(t?`button`:`div`);return r.tabIndex=-1,e?r.textContent=e:r.setAttribute(`aria-hidden`,`true`),n&&(r instanceof HTMLButtonElement?r.disabled=!0:r.setAttribute(`aria-disabled`,`true`)),r}drawDaysOfWeek(){if(!this.hasDaysOfWeekTarget)return;let e=new Intl.DateTimeFormat(this.localesValue,{weekday:this.weekdayFormatValue}),t=[];for(let n of this.calendar.daysOfWeek){let r=this.createDayElement(e.format(n.date));r.setAttribute(`role`,`columnheader`),r.title=n.long,this.hasDayOfWeekClass&&r.classList.add(...this.dayOfWeekClasses),t.push(r)}let n=document.createElement(`div`);n.setAttribute(`role`,`row`),this.hasWeekClass&&n.classList.add(...this.weekClasses),n.replaceChildren(...t),this.daysOfWeekTarget.replaceChildren(n)}drawDaysOfMonth(){if(!this.hasDaysOfMonthTarget)return;let e=this.calendar.today,t=new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime(),n=[];for(let e of this.calendar.daysOfMonth){let r=!e.current||this.calendar.isDisabled(e.date)||!this.calendar.isWithinRange(e.date),i=e.current||this.daysOfOtherMonthValue?e.value:``,a=this.createDayElement(i,{selectable:e.current,disabled:r});t===e.date.getTime()&&a.setAttribute(`aria-current`,`date`),this.hasDayOfMonthClass&&a.classList.add(...this.dayOfMonthClasses);let o=document.createElement(`time`);o.dateTime=e.iso,a.appendChild(o),n.push(a)}let r=[];for(let e=0;e<n.length;e+=7){let t=document.createElement(`div`);t.setAttribute(`role`,`row`),this.hasWeekClass&&t.classList.add(...this.weekClasses);for(let r of n.slice(e,e+7))r.setAttribute(`role`,`gridcell`),t.appendChild(r);r.push(t)}this.daysOfMonthTarget.replaceChildren(...r)}},Ie=class extends t.Controller{onSelect(e){if(!(e.target instanceof HTMLElement))return;e.preventDefault();let t=e.target instanceof HTMLTimeElement?e.target.parentElement:e.target;if(t.disabled||t.getAttribute(`aria-disabled`)===`true`)return;this.dispatch(`selecting`,{target:t});let n=e.target instanceof HTMLTimeElement?e.target:e.target.querySelector(`time`);if(!n)return console.error(`unable to locate time element within ${t}`);let r=G(n.dateTime);if(!r)return console.error(`unable to parse ${n.dateTime} found within the time element`);this.select(r.toISOString())}select(e){let t=G(e);t&&this.dispatch(`selected`,{detail:{epoch:t.getTime(),iso:e}})}},Le=class extends t.Controller{static targets=[`source`];static values={type:{type:String,default:`text/plain`}};onPaste(e){let t=e.clipboardData?.getData(this.typeValue)??``,n=Array.from(e.clipboardData?.types??[]);e.preventDefault(),this.dispatch(`pasted`,{detail:{text:t,types:n},bubbles:!0})}async copy(e){let t=e.params?.text??(this.hasSourceTarget?this.sourceTarget.value??this.sourceTarget.textContent??``:``);try{await navigator.clipboard.writeText(t),this.dispatch(`copied`,{detail:{text:t},bubbles:!0})}catch(e){this.dispatch(`copy-failed`,{detail:{error:e},bubbles:!0})}}},Re=class extends t.Controller{static targets=[`previous`,`next`,`day`,`month`,`year`];static outlets=[`calendar-month`];static values={date:String,locales:{type:Array,default:[`default`]},dayFormat:{type:String,default:`numeric`},monthFormat:{type:String,default:`long`},yearFormat:{type:String,default:`numeric`}};initialize(){this.previous=this.previous.bind(this),this.next=this.next.bind(this)}async calendarMonthOutletConnected(){if(this.dateValue){let e=G(this.dateValue);e&&await this.calendarMonthOutlet.calendar.navigate(e)}this.draw()}onSelect(e){this.dateValue=e.detail.iso,this.draw(),this.dispatch(`selected`,{detail:{value:e.detail.iso},bubbles:!0})}previousTargetConnected(e){e.addEventListener(`click`,this.previous)}previousTargetDisconnected(e){e.removeEventListener(`click`,this.previous)}async previous(){await this.calendarMonthOutlet.calendar.step(`month`,-1),this.draw()}nextTargetConnected(e){e.addEventListener(`click`,this.next)}nextTargetDisconnected(e){e.removeEventListener(`click`,this.next)}async next(){await this.calendarMonthOutlet.calendar.step(`month`,1),this.draw()}draw(){this.drawDay(),this.drawMonth(),this.drawYear()}drawDay(){if(!this.hasDayTarget||!this.hasCalendarMonthOutlet)return;let{year:e,month:t,day:n}=this.calendarMonthOutlet.calendar;this.dayTarget.textContent=new Intl.DateTimeFormat(this.localesValue,{day:this.dayFormatValue}).format(new Date(e,t,n))}drawMonth(){if(!this.hasMonthTarget||!this.hasCalendarMonthOutlet)return;let{year:e,month:t}=this.calendarMonthOutlet.calendar;this.monthTarget.textContent=new Intl.DateTimeFormat(this.localesValue,{month:this.monthFormatValue}).format(new Date(e,t))}drawYear(){if(!this.hasYearTarget||!this.hasCalendarMonthOutlet)return;let{year:e}=this.calendarMonthOutlet.calendar;this.yearTarget.textContent=new Intl.DateTimeFormat(this.localesValue,{year:this.yearFormatValue}).format(new Date(e,0))}},ze=class extends t.Controller{static targets=[`listbox`,`loading`,`empty`];static values={url:{type:String,default:``},field:{type:String,default:`q`},delay:{type:Number,default:300}};initialize(){this._requestor=new C}onSelect(e){let t=e.target.closest(`[role="option"]`);!t||t.getAttribute(`aria-disabled`)===`true`||this.select(t.dataset.value??``)}select(e){let t=this.listboxTarget.querySelectorAll(`[role="option"]`);t.forEach(e=>e.setAttribute(`aria-selected`,`false`));let n=[...t].find(t=>t.dataset.value===e);n&&n.setAttribute(`aria-selected`,`true`),this.dispatch(`selected`,{detail:{value:e},bubbles:!0})}onNavigate(e){if([`ArrowUp`,`ArrowDown`,`Enter`,` `].includes(e.key)){if(e.preventDefault(),e.key===`Enter`||e.key===` `){this.listboxTarget.querySelector(`[aria-selected="true"]`)?.click();return}this.step(e.key===`ArrowDown`?1:-1)}}step(e){let t=[...this.listboxTarget.querySelectorAll(`[role="option"]:not([aria-disabled="true"]):not([hidden])`)];if(!t.length)return;let n=this.listboxTarget.querySelector(`[aria-selected="true"]`),r=t.indexOf(n),i=e>0?t[Math.min(r+1,t.length-1)]:t[Math.max(r-1,0)];!i||i===n||(t.forEach(e=>e.setAttribute(`aria-selected`,`false`)),i.setAttribute(`aria-selected`,`true`),i.scrollIntoView({block:`nearest`}))}filter(e){if(this.urlValue){let t=new URL(this.urlValue,window.location.href);t.searchParams.set(this.fieldValue,e),this.setLoading(!0),this._requestor.schedule(()=>this._requestor.request(t).then(e=>e.text()).then(e=>{this.listboxTarget.innerHTML=e,this.setEmpty(this.listboxTarget.querySelectorAll(`[role="option"]`).length===0)}).catch(e=>{e.name!==`AbortError`&&console.error(`[combobox-dropdown] fetch failed`,e)}).finally(()=>this.setLoading(!1)),this.delayValue)}else{let t=T(this.listboxTarget,e);this.setEmpty(t===0)}}showAll(){this.listboxTarget.querySelectorAll(`[role="option"]`).forEach(e=>e.hidden=!1),this.setEmpty(!1)}setLoading(e){this.hasLoadingTarget&&(this.loadingTarget.hidden=!e)}setEmpty(e){this.hasEmptyTarget&&(this.emptyTarget.hidden=!e)}disconnect(){this._requestor.cancel()}},$=class extends t.Controller{static targets=[`hour`,`minute`,`period`];connect(){this.select(this.toH24())}onSelect(e){let t=e.target.closest(`[role="option"]`);t&&(t.closest(`[role="listbox"]`).querySelectorAll(`[role="option"]`).forEach(e=>e.setAttribute(`aria-selected`,`false`)),t.setAttribute(`aria-selected`,`true`),this.select(this.toH24()))}select(e){e&&this.dispatch(`selected`,{detail:{value:e},bubbles:!0})}onNavigate(e){[`ArrowUp`,`ArrowDown`].includes(e.key)&&(e.preventDefault(),this.step(e.currentTarget,e.key===`ArrowDown`?1:-1))}step(e,t){let n=[...e.querySelectorAll(`[role="option"]`)],r=e.querySelector(`[aria-selected="true"]`),i=n.indexOf(r),a=t>0?n[Math.min(i+1,n.length-1)]:n[Math.max(i-1,0)];!a||a===r||(n.forEach(e=>e.setAttribute(`aria-selected`,`false`)),a.setAttribute(`aria-selected`,`true`),a.scrollIntoView({block:`nearest`}),this.select(this.toH24()))}toH24(){let e=this.selectedValue(this.hourTarget),t=this.selectedValue(this.minuteTarget);if(!e||!t)return null;if(!this.hasPeriodTarget)return`${e}:${t}`;let n=this.selectedValue(this.periodTarget),r=parseInt(e,10);return r=n===`AM`?r===12?0:r:r===12?12:r+12,`${String(r).padStart(2,`0`)}:${t}`}selectedValue(e){return e?.querySelector(`[aria-selected="true"]`)?.dataset.value??null}},Be=class extends t.Controller{static targets=[`trigger`];connect(){X(this,{trigger:this.hasTriggerTarget?this.triggerTarget:null})}},Ve=class extends t.Controller{static targets=[`anchor`,`reference`];static values={placement:{type:String,default:`bottom`},alignment:{type:String,default:`start`},role:{type:String,default:`tooltip`}};connect(){if(!this.hasReferenceTarget){console.error(`FlipperController requires a reference target. Add data-flipper-target="reference" to your element.`);return}if(!this.hasAnchorTarget){console.error(`FlipperController requires an anchor target. Add data-flipper-target="anchor" to your element.`);return}Ae(this,{element:this.referenceTarget,anchor:this.anchorTarget,placement:this.placementValue,alignment:this.alignmentValue,ariaRole:this.roleValue})}},He=class extends t.Controller{static targets=[`trigger`,`popover`,`value`];static values={value:String,minLength:{type:Number,default:1}};static outlets=[`combobox-dropdown`];connect(){X(this),this.hasPopoverTarget&&Q(this,{element:this.popoverTarget,activator:this.hasTriggerTarget?this.triggerTarget:null})}async dismissed(){await this.close()}async open(){this.hasPopoverTarget&&await this.visibility.show()}async close(){this.hasPopoverTarget&&await this.visibility.hide()}async toggle(){this.visibility?.visible?await this.close():await this.open()}async shown(){this.hasPopoverTarget&&a(this.popoverTarget)}async hidden(){this.hasTriggerTarget&&this.triggerTarget.focus()}async onSelect(e){e.detail?.value!==void 0&&(this.valueValue=e.detail.value),await this.close()}onInput(e){if(e.target!==this.triggerTarget)return;let t=e.target.value.trim();if(t.length<this.minLengthValue){this.hasComboboxDropdownOutlet&&this.comboboxDropdownOutlet.showAll();return}this.hasComboboxDropdownOutlet&&this.comboboxDropdownOutlet.filter(t)}valueValueChanged(e){this.hasValueTarget&&(this.valueTarget.value=e),this.dispatch(`changed`,{detail:{value:e}})}},Ue=class extends t.Controller{static targets=[`input`,`toggle`];static values={type:{type:String,default:`plain`},options:{type:Object,default:{}},revealed:{type:Boolean,default:!1}};connect(){U(this,{type:this.typeValue,options:this.optionsValue}),this.format(this.readValue()),this.drawToggle()}typeValueChanged(){this.formatter&&(U(this,{type:this.typeValue,options:this.optionsValue}),this.format(this.readValue()),this.drawToggle())}optionsValueChanged(){this.formatter&&(U(this,{type:this.typeValue,options:this.optionsValue}),this.format(this.readValue()))}revealedValueChanged(){this.formatter&&(this.format(this.readValue()),this.drawToggle())}onChange(e){this.format(e?.detail?.value??``)}format(e){this.formatter&&this.onFormatting(e)}toggle(){!this.formatter.maskable()&&this.typeValue!==`password`||(this.revealedValue=!this.revealedValue)}onPaste(e){let t=e.detail?.text??``;if(!this.formatter||!t)return;let n=this.formatter.normalize(t);this.formatter.validate(n)&&this.format(n)}drawToggle(){if(!this.hasToggleTarget)return;let e=this.formatter?.maskable()||this.typeValue===`password`;this.toggleTarget.hidden=!e,e&&_(this.toggleTarget,this.revealedValue)}readValue(){return this.hasInputTarget?this.inputTarget instanceof HTMLInputElement?this.inputTarget.value:this.inputTarget.textContent:``}onFormatting(e){if(!this.formatter)return;if(this.typeValue===`password`){this.hasInputTarget&&(this.inputTarget.type=this.revealedValue?`text`:`password`);return}let t=this.formatter.normalize(e),n=this.revealedValue||!this.formatter.maskable()?this.formatter.format(t):this.formatter.mask(t);this.hasInputTarget&&(this.inputTarget instanceof HTMLInputElement?this.inputTarget.value=n:this.inputTarget.textContent=n),this.dispatch(`formatted`,{detail:{value:n}})}},We=class extends t.Controller{static targets=[`input`,`clear`];initialize(){this.onInput=this.draw.bind(this),this.onEscape=this.handleEscape.bind(this)}connect(){this.draw()}inputTargetConnected(e){e.addEventListener(`input`,this.onInput),e.addEventListener(`keydown`,this.onEscape)}inputTargetDisconnected(e){e.removeEventListener(`input`,this.onInput),e.removeEventListener(`keydown`,this.onEscape)}clear(){this.hasInputTarget&&(this.inputTarget.value=``,this.draw(),this.inputTarget.focus(),this.inputTarget.dispatchEvent(new Event(`input`,{bubbles:!0})))}draw(){!this.hasInputTarget||!this.hasClearTarget||(this.clearTarget.hidden=this.inputTarget.value.length===0)}handleEscape(e){e.key===`Escape`&&this.inputTarget.value!==``&&(e.preventDefault(),this.clear())}},Ge=class extends t.Controller{static targets=[`modal`,`overlay`];initialize(){this.onCancel=this.close.bind(this)}connect(){this.hasModalTarget||console.error(`ModalController requires a modal target. Add data-modal-target="modal" to your element.`)}modalTargetConnected(e){this.isNativeDialog=e instanceof HTMLDialogElement,this.isNativeDialog?(e.addEventListener(`cancel`,this.onCancel),e.addEventListener(`click`,this.onBackdropClick)):(this.focusTrap=new o(e,{escapeDeactivates:!0}),X(this,{element:e}))}modalTargetDisconnected(e){this.isNativeDialog&&(e.removeEventListener(`cancel`,this.onCancel),e.removeEventListener(`click`,this.onBackdropClick))}dismissed=()=>{this.close()};open(e){if(e&&e.preventDefault(),this.hasModalTarget){if(this.isNativeDialog)this.previouslyFocused=document.activeElement,this.modalTarget.showModal();else{let e=this.hasOverlayTarget?this.overlayTarget:this.modalTarget;e.hidden=!1,document.body.style.overflow=`hidden`,this.focusTrap&&this.focusTrap.activate()}m(`Modal opened`)}}close(e){if(e&&e.preventDefault(),this.hasModalTarget){if(this.isNativeDialog)this.modalTarget.close(),this.previouslyFocused&&this.previouslyFocused.isConnected&&setTimeout(()=>{this.previouslyFocused.focus()},0);else{let e=this.hasOverlayTarget?this.overlayTarget:this.modalTarget;e.hidden=!0,document.body.style.overflow=``,this.focusTrap&&this.focusTrap.deactivate()}m(`Modal closed`)}}onBackdropClick=e=>{let t=this.modalTarget.getBoundingClientRect();(e.clientY<t.top||e.clientY>t.bottom||e.clientX<t.left||e.clientX>t.right)&&this.close()}},Ke=class extends t.Controller{static targets=[`content`];connect(){Ne(this,{element:this.hasContentTarget?this.contentTarget:null})}},qe=class extends t.Controller{static targets=[`content`,`template`,`loader`,`activator`];static classes=[`hidden`];static values={url:String,loadedAt:String,reload:{type:String,default:`never`},staleAfter:{type:Number,default:3600}};connect(){Te(this,{element:this.hasContentTarget?this.contentTarget:null,url:this.hasUrlValue?this.urlValue:null}),this.hasContentTarget&&Q(this,{element:this.contentTarget,activator:this.hasActivatorTarget?this.activatorTarget:null}),this.hasLoaderTarget&&Q(this,{element:this.loaderTarget,visibility:`contentLoaderVisibility`})}async show(){await this.visibility.show()}async hide(){await this.visibility.hide()}async shown(){await this.load()}canLoad(){return this.hasContentTarget&&this.contentTarget.tagName.toLowerCase()===`turbo-frame`?(this.hasUrlValue&&this.contentTarget.setAttribute(`src`,this.urlValue),!1):!0}async contentLoading(){this.hasLoaderTarget&&await this.contentLoaderVisibility.show()}async contentLoaded({content:e}){this.hasContentTarget&&this.contentTarget.replaceChildren(this.getContentNode(e)),this.hasLoaderTarget&&await this.contentLoaderVisibility.hide()}getContentNode(e){if(typeof e==`string`){let t=document.createElement(`template`);return t.innerHTML=e,document.importNode(t.content,!0)}return document.importNode(e,!0)}contentLoader(){if(this.hasTemplateTarget)return this.templateTarget instanceof HTMLTemplateElement?this.templateTarget.content:this.templateTarget.innerHTML}};e.ARIA_HASPOPUP_VALUES=v,e.CalendarMonthController=Fe,e.CalendarMonthObserverController=Ie,e.ClipboardController=Le,e.ComboboxDateController=Re,e.ComboboxDropdownController=ze,e.ComboboxTimeController=$,e.DismisserController=Be,e.FOCUSABLE_SELECTOR=n,e.FORMATTER_TYPES=z,e.FlipperController=Ve,e.FocusRestoration=s,e.FocusTrap=o,e.Formatter=H,e.InputComboboxController=He,e.InputFormatController=Ue,e.InputSearchController=We,e.ModalController=Ge,e.PannerController=Ke,e.PopoverController=qe,e.Requestor=C,e.RovingTabIndex=f,e.announce=m,e.connectTriggerToTarget=x,e.disconnectTriggerFromTarget=ie,e.ensureId=ee,e.filterOptions=T,e.focusFirst=a,e.fuzzyMatcher=w,e.generateId=h,e.getFocusableElements=r,e.isActivationKey=l,e.isArrowKey=u,e.isKey=c,e.isVisible=i,e.preventDefault=d,e.setAriaState=g,e.setChecked=ne,e.setDisabled=re,e.setExpanded=te,e.setPressed=_});
@@ -5,13 +5,14 @@ module StimulusPlumbers
5
5
  class ActionList
6
6
  class Section < Plumber::Base
7
7
  def render(title: nil, **kwargs, &block)
8
- html_options = merge_html_options(kwargs)
9
- template.content_tag(:div, **html_options) do
8
+ template.content_tag(:li, **kwargs) do
9
+ ul_opts = {}
10
+ ul_opts[:aria] = { label: title } if title.present?
10
11
  template.safe_join(
11
12
  [
12
- (template.content_tag(:p, title) if title.present?),
13
- template.content_tag(:ul, template.capture(&block))
14
- ].compact
13
+ (template.content_tag(:span, title, aria: { hidden: "true" }) if title.present?),
14
+ template.content_tag(:ul, template.capture(&block), **ul_opts)
15
+ ]
15
16
  )
16
17
  end
17
18
  end
@@ -3,12 +3,12 @@
3
3
  module StimulusPlumbers
4
4
  module Components
5
5
  class ActionList < Plumber::Base
6
- def render(**kwargs, &block)
6
+ def render(role: "list", **kwargs, &block)
7
7
  html_options = merge_html_options(
8
- { classes: theme.resolve(:action_list).fetch(:classes, "") },
8
+ { role: role, classes: theme.resolve(:action_list).fetch(:classes, "") },
9
9
  kwargs
10
10
  )
11
- template.content_tag(:div, template.capture(&block), **html_options)
11
+ template.content_tag(:ul, template.capture(&block), **html_options)
12
12
  end
13
13
 
14
14
  def section(title: nil, **kwargs, &block)
@@ -33,12 +33,13 @@ module StimulusPlumbers
33
33
  end
34
34
 
35
35
  def resolve_color(color, name, initials)
36
+ range = theme.avatar_color_range
36
37
  if color
37
38
  theme.avatar_colors.fetch(color, nil)
38
- elsif (seed = name || initials)
39
- theme.avatar_color_range[seed.bytes.reduce(:^) % theme.avatar_color_range.length]
39
+ elsif (seed = name || initials) && range.any?
40
+ range[seed.bytes.reduce(:^) % range.length]
40
41
  else
41
- theme.avatar_color_range.first
42
+ range.first
42
43
  end
43
44
  end
44
45
 
@@ -31,48 +31,63 @@ module StimulusPlumbers
31
31
  { classes: theme.resolve(:calendar_days_of_month).fetch(:classes, "") },
32
32
  kwargs
33
33
  )
34
-
35
- template.content_tag(:div, **html_options, role: "rowgroup") do
36
- template.safe_join(
37
- build_days.each_slice(DAYS_IN_WEEK).map do |week|
38
- template.content_tag(:div, role: "row") do
39
- days_in_week(week)
40
- end
41
- end
42
- )
43
- end
34
+ template.content_tag(:div, **html_options, role: "rowgroup") { weeks_of_month }
44
35
  end
45
36
 
46
37
  private
47
38
 
48
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
39
+ def weeks_of_month
40
+ week_options = merge_html_options(
41
+ { classes: theme.resolve(:calendar_week).fetch(:classes, "") },
42
+ { role: "row" }
43
+ )
44
+ template.safe_join(
45
+ build_days.each_slice(DAYS_IN_WEEK).map do |days|
46
+ template.content_tag(:div, **week_options) { days_in_week(days) }
47
+ end
48
+ )
49
+ end
50
+
49
51
  def focus_day
50
- @focus_day ||= if selected_date&.month == date.month && selected_date&.year == date.year
52
+ @focus_day ||= if selected_date_in_current_month?
51
53
  selected_date
52
- elsif today.month == date.month && today.year == date.year
54
+ elsif today_in_current_month?
53
55
  today
54
56
  else
55
57
  date.beginning_of_month
56
58
  end
57
59
  end
58
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
59
60
 
60
61
  def build_days
61
- first = date.beginning_of_month
62
- last = date.end_of_month
63
-
64
- prev_days = (first - first.wday).upto(first - 1).to_a
62
+ first = date.beginning_of_month
63
+ last = date.end_of_month
65
64
  current_days = first.upto(last).to_a
66
- total = prev_days.length + current_days.length
67
- next_count = (DAYS_IN_WEEK - (total % DAYS_IN_WEEK)) % DAYS_IN_WEEK
68
- next_days = next_count.positive? ? (last + 1).upto(last + next_count).to_a : []
65
+ prev_filler_days(first) + current_days + next_filler_days(last, current_days.length)
66
+ end
69
67
 
70
- prev_days + current_days + next_days
68
+ def prev_filler_days(first_day_of_month)
69
+ week_start = first_day_of_month - first_day_of_month.wday
70
+ week_start.upto(first_day_of_month - 1).to_a
71
71
  end
72
72
 
73
- def days_in_week(week)
73
+ def next_filler_days(last_day_of_month, days_in_month)
74
+ week_start_offset = last_day_of_month.beginning_of_month.wday
75
+ total = week_start_offset + days_in_month
76
+ next_count = (DAYS_IN_WEEK - (total % DAYS_IN_WEEK)) % DAYS_IN_WEEK
77
+ next_count.positive? ? (last_day_of_month + 1).upto(last_day_of_month + next_count).to_a : []
78
+ end
79
+
80
+ def selected_date_in_current_month?
81
+ selected_date&.month == date.month && selected_date&.year == date.year
82
+ end
83
+
84
+ def today_in_current_month?
85
+ today.month == date.month && today.year == date.year
86
+ end
87
+
88
+ def days_in_week(days)
74
89
  template.safe_join(
75
- week.map do |day|
90
+ days.map do |day|
76
91
  if day.month == date.month
77
92
  current_month_day_cell(day)
78
93
  elsif show_other_months
@@ -91,28 +106,34 @@ module StimulusPlumbers
91
106
  end
92
107
 
93
108
  def current_month_day_cell(date)
94
- tag = selectable ? :button : :span
95
- selected = selected_date && date == selected_date ? "true" : "false"
96
- template.content_tag(
97
- tag,
98
- role: "gridcell",
99
- tabindex: date == focus_day ? 0 : -1,
100
- aria: {
101
- current: date == today ? "date" : nil,
102
- selected: selectable ? selected : nil
103
- }
104
- ) do
109
+ tag = selectable ? :button : :span
110
+ template.content_tag(tag, **day_cell_html_options(date, today)) do
105
111
  template.content_tag(:time, date.day.to_s, datetime: date.iso8601)
106
112
  end
107
113
  end
108
114
 
115
+ def day_cell_html_options(date, today)
116
+ is_today = date == today
117
+ selected = selected_date && date == selected_date
118
+ merge_html_options(
119
+ { classes: theme.resolve(:calendar_day, today: is_today, selected: selected).fetch(:classes, "") },
120
+ {
121
+ role: "gridcell",
122
+ tabindex: date == focus_day ? 0 : -1,
123
+ aria: {
124
+ current: is_today ? "date" : nil,
125
+ selected: if selectable then selected ? "true" : "false" end
126
+ }
127
+ }
128
+ )
129
+ end
130
+
109
131
  def other_month_day_cell(date)
110
- template.content_tag(
111
- :span,
112
- role: "gridcell",
113
- tabindex: -1,
114
- aria: { disabled: "true", selected: "false" }
115
- ) do
132
+ options = merge_html_options(
133
+ { classes: theme.resolve(:calendar_day, outside: true).fetch(:classes, "") },
134
+ { role: "gridcell", tabindex: -1, aria: { disabled: "true", selected: "false" } }
135
+ )
136
+ template.content_tag(:span, **options) do
116
137
  template.content_tag(:time, date.day.to_s, datetime: date.iso8601)
117
138
  end
118
139
  end
@@ -11,20 +11,23 @@ module StimulusPlumbers
11
11
  { classes: theme.resolve(:calendar_days_of_week).fetch(:classes, "") },
12
12
  kwargs
13
13
  )
14
-
15
- template.content_tag(:div, **html_options) do
16
- template.content_tag(:div, role: "row") do
17
- template.safe_join(
18
- day_names.map do |abbr, full|
19
- template.content_tag(:span, abbr, role: "columnheader", abbr: full)
20
- end
21
- )
22
- end
23
- end
14
+ template.content_tag(:div, **html_options) { days_of_week }
24
15
  end
25
16
 
26
17
  private
27
18
 
19
+ def days_of_week
20
+ week_options = merge_html_options(
21
+ { classes: theme.resolve(:calendar_week).fetch(:classes, "") },
22
+ { role: "row" }
23
+ )
24
+ template.content_tag(:div, **week_options) do
25
+ template.safe_join(
26
+ day_names.map { |abbr, full| template.content_tag(:span, abbr, role: "columnheader", abbr: full) }
27
+ )
28
+ end
29
+ end
30
+
28
31
  def day_names
29
32
  I18n.t("date.abbr_day_names").zip(I18n.t("date.day_names"))
30
33
  end
@@ -11,22 +11,45 @@ module StimulusPlumbers
11
11
  }.freeze
12
12
 
13
13
  def month(**kwargs)
14
- html_options = merge_html_options(
15
- { classes: theme.resolve(:calendar).fetch(:classes, ""), data: STIMULUS_DATA },
14
+ template.content_tag(:div, role: "grid", **month_html_options(kwargs)) do
15
+ template.safe_join([template.tag.div(**dow_options), template.tag.div(**dom_options)])
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def month_html_options(kwargs)
22
+ merge_html_options(
23
+ {
24
+ classes: theme.resolve(:calendar).fetch(:classes, ""),
25
+ data: month_stimulus_data
26
+ },
16
27
  kwargs
17
28
  )
29
+ end
18
30
 
19
- template.content_tag(:div, role: "grid", **html_options) do
20
- template.safe_join(
21
- [
22
- template.tag.div(data: { "#{STIMULUS_CONTROLLER}-target" => "daysOfWeek" }),
23
- template.tag.div(
24
- role: "rowgroup",
25
- data: { "#{STIMULUS_CONTROLLER}-target" => "daysOfMonth" }
26
- )
27
- ]
28
- )
29
- end
31
+ def month_stimulus_data
32
+ STIMULUS_DATA.merge(
33
+ calendar_month_week_class: theme.resolve(:calendar_week).fetch(:classes, ""),
34
+ calendar_month_day_of_month_class: theme.resolve(:calendar_day).fetch(:classes, "")
35
+ ).compact_blank
36
+ end
37
+
38
+ def dow_options
39
+ merge_html_options(
40
+ { classes: theme.resolve(:calendar_days_of_week).fetch(:classes, "") },
41
+ { data: { "#{STIMULUS_CONTROLLER}-target": "daysOfWeek" } }
42
+ )
43
+ end
44
+
45
+ def dom_options
46
+ merge_html_options(
47
+ { classes: theme.resolve(:calendar_days_of_month).fetch(:classes, "") },
48
+ {
49
+ role: "rowgroup",
50
+ data: { "#{STIMULUS_CONTROLLER}-target": "daysOfMonth" }
51
+ }
52
+ )
30
53
  end
31
54
  end
32
55
  end
@@ -4,7 +4,7 @@ module StimulusPlumbers
4
4
  module Components
5
5
  class Card
6
6
  class Section < Plumber::Base
7
- def render(title: nil, **kwargs, &block)
7
+ def render(title: nil, title_tag: :h3, **kwargs, &block)
8
8
  html_options = merge_html_options(
9
9
  { classes: theme.resolve(:card_section).fetch(:classes, "") },
10
10
  kwargs
@@ -13,9 +13,9 @@ module StimulusPlumbers
13
13
  template.content_tag(:div, **html_options) do
14
14
  template.safe_join(
15
15
  [
16
- (template.content_tag(:h3, title) if title.present?),
16
+ (template.content_tag(title_tag, title) if title.present?),
17
17
  template.capture(&block)
18
- ].compact
18
+ ]
19
19
  )
20
20
  end
21
21
  end
@@ -3,7 +3,7 @@
3
3
  module StimulusPlumbers
4
4
  module Components
5
5
  class Card < Plumber::Base
6
- def render(title: nil, **kwargs, &block)
6
+ def render(title: nil, title_tag: :h2, **kwargs, &block)
7
7
  html_options = merge_html_options(
8
8
  { classes: theme.resolve(:card).fetch(:classes, "") },
9
9
  kwargs
@@ -12,9 +12,9 @@ module StimulusPlumbers
12
12
  template.content_tag(:div, **html_options) do
13
13
  template.safe_join(
14
14
  [
15
- (template.content_tag(:h2, title) if title.present?),
15
+ (template.content_tag(title_tag, title) if title.present?),
16
16
  template.capture(&block)
17
- ].compact
17
+ ]
18
18
  )
19
19
  end
20
20
  end
@@ -10,24 +10,18 @@ module StimulusPlumbers
10
10
  )
11
11
  end
12
12
 
13
- def render(options: [], value: nil, label: nil, **_kwargs)
14
- template.safe_join([listbox(options, value, label), loading, empty])
13
+ def render(options: [], value: nil, label: nil, labelledby: nil)
14
+ template.safe_join(
15
+ [
16
+ Dropdown.new(template).render(options: options, value: value, label: label, labelledby: labelledby),
17
+ loading,
18
+ empty
19
+ ]
20
+ )
15
21
  end
16
22
 
17
23
  private
18
24
 
19
- def listbox(options, value, label)
20
- attrs = merge_html_options(
21
- { classes: theme.resolve(:combobox_listbox).fetch(:classes, "") },
22
- { role: "listbox", data: { "#{Dropdown::STIMULUS_CONTROLLER}_target": "listbox" } }
23
- )
24
- attrs[:aria] = { label: label } if label
25
-
26
- template.content_tag(:ul, **attrs) do
27
- Options.new(template).render(options, value: value)
28
- end
29
- end
30
-
31
25
  def loading
32
26
  template.content_tag(
33
27
  :div,
@@ -14,8 +14,12 @@ module StimulusPlumbers
14
14
  }
15
15
  end
16
16
 
17
- def render(value: nil, **_kwargs)
18
- calendar_id = "combobox_date_#{SecureRandom.hex(8)}_calendar"
17
+ def self.calendar_id_for(popover_id)
18
+ [popover_id, "calendar"].compact.join("_")
19
+ end
20
+
21
+ def render(value: nil, popover_id: nil)
22
+ calendar_id = self.class.calendar_id_for(popover_id)
19
23
 
20
24
  data = {
21
25
  controller: STIMULUS_CONTROLLER,
@@ -21,12 +21,16 @@ module StimulusPlumbers
21
21
  }
22
22
  end
23
23
 
24
- def render(options: [], value: nil, label: nil, **_kwargs)
24
+ def render(options: [], value: nil, label: nil, labelledby: nil)
25
25
  listbox_attrs = merge_html_options(
26
26
  { classes: theme.resolve(:combobox_listbox).fetch(:classes, "") },
27
27
  { role: "listbox", data: { "#{STIMULUS_CONTROLLER}_target": "listbox" } }
28
28
  )
29
- listbox_attrs[:aria] = { label: label } if label
29
+ if labelledby
30
+ listbox_attrs[:aria] = { labelledby: labelledby }
31
+ elsif label
32
+ listbox_attrs[:aria] = { label: label }
33
+ end
30
34
 
31
35
  template.content_tag(:ul, **listbox_attrs) do
32
36
  Options.new(template).render(options, value: value)
@@ -4,14 +4,18 @@ module StimulusPlumbers
4
4
  module Components
5
5
  class Combobox
6
6
  class Popover < Plumber::Base
7
- def render(stimulus_controller:, id:, tag: :div, role: nil, label: nil, content: nil, data: {}, **_rest, &block)
8
- base_data = { "#{stimulus_controller}_target": "popover" }
7
+ def render(stimulus_controller:, id:, tag: :div, role: nil, label: nil, labelledby: nil, content: nil, data: {}, &block)
8
+ stimulus_data = { "#{stimulus_controller}_target": "popover" }
9
9
 
10
- attrs = { id: id, hidden: "", data: merge_data_options(base_data, data.symbolize_keys) }
10
+ attrs = { id: id, hidden: "", data: merge_data_options(stimulus_data, data) }
11
11
  attrs[:role] = role if role
12
- attrs[:aria] = { label: label } if label
12
+ if labelledby
13
+ attrs[:aria] = { labelledby: labelledby }
14
+ elsif label
15
+ attrs[:aria] = { label: label }
16
+ end
13
17
 
14
- html_content = block_given? ? template.capture(&block) : content
18
+ html_content = block_given? ? template.capture(id, &block) : content
15
19
  template.content_tag(tag, **attrs) { html_content }
16
20
  end
17
21
  end