@aerogel/core 0.0.0-next.7f6ed5a1f91688a86bf5ede2adc465e4fd6cfdea → 0.0.0-next.b85327579d32f21c6a9fa21142f0165cdd320d7e

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 (62) hide show
  1. package/dist/aerogel-core.cjs.js +1 -1
  2. package/dist/aerogel-core.d.ts +426 -82
  3. package/dist/aerogel-core.esm.js +1 -1
  4. package/package.json +6 -8
  5. package/src/bootstrap/bootstrap.test.ts +0 -56
  6. package/src/bootstrap/index.ts +9 -25
  7. package/src/bootstrap/options.ts +5 -1
  8. package/src/components/basic/AGMarkdown.vue +20 -5
  9. package/src/components/forms/AGButton.vue +26 -3
  10. package/src/components/forms/AGCheckbox.vue +35 -0
  11. package/src/components/forms/AGInput.vue +8 -4
  12. package/src/components/forms/index.ts +2 -1
  13. package/src/components/headless/forms/AGHeadlessButton.vue +3 -4
  14. package/src/components/headless/forms/AGHeadlessInput.ts +2 -2
  15. package/src/components/headless/forms/AGHeadlessInput.vue +5 -5
  16. package/src/components/headless/forms/AGHeadlessInputError.vue +9 -5
  17. package/src/components/headless/forms/AGHeadlessInputInput.vue +20 -4
  18. package/src/components/headless/forms/AGHeadlessInputLabel.vue +16 -0
  19. package/src/components/headless/forms/index.ts +6 -4
  20. package/src/components/headless/modals/AGHeadlessModal.vue +5 -1
  21. package/src/components/headless/modals/AGHeadlessModalPanel.vue +10 -2
  22. package/src/components/index.ts +2 -1
  23. package/src/components/modals/AGAlertModal.vue +13 -2
  24. package/src/components/modals/AGConfirmModal.vue +30 -0
  25. package/src/components/modals/AGLoadingModal.vue +19 -0
  26. package/src/components/modals/AGModal.ts +4 -0
  27. package/src/components/modals/AGModal.vue +20 -2
  28. package/src/components/modals/index.ts +4 -1
  29. package/src/directives/index.ts +5 -3
  30. package/src/errors/Errors.state.ts +31 -0
  31. package/src/errors/Errors.ts +132 -0
  32. package/src/errors/index.ts +21 -0
  33. package/src/forms/Form.test.ts +21 -0
  34. package/src/forms/Form.ts +38 -16
  35. package/src/forms/utils.ts +17 -0
  36. package/src/globals.ts +6 -0
  37. package/src/lang/Lang.ts +47 -8
  38. package/src/lang/index.ts +17 -76
  39. package/src/lang/utils.ts +4 -0
  40. package/src/main.ts +4 -0
  41. package/src/plugins/Plugin.ts +7 -0
  42. package/src/plugins/index.ts +7 -0
  43. package/src/services/App.state.ts +13 -0
  44. package/src/services/App.ts +17 -0
  45. package/src/services/Service.ts +151 -28
  46. package/src/services/index.ts +29 -7
  47. package/src/services/store.ts +27 -0
  48. package/src/types/vite.d.ts +0 -2
  49. package/src/ui/UI.state.ts +3 -6
  50. package/src/ui/UI.ts +35 -2
  51. package/src/ui/index.ts +20 -14
  52. package/src/utils/composition/forms.ts +11 -0
  53. package/src/utils/composition/hooks.ts +9 -0
  54. package/src/utils/index.ts +3 -0
  55. package/tsconfig.json +1 -10
  56. package/vite.config.ts +2 -6
  57. package/src/bootstrap/hooks.ts +0 -19
  58. package/src/lang/helpers.ts +0 -5
  59. package/src/models/index.ts +0 -18
  60. package/src/routing/index.ts +0 -33
  61. package/src/testing/stubs/lang/en.yaml +0 -1
  62. package/src/testing/stubs/models/User.ts +0 -3
@@ -1,2 +1,2 @@
1
- import"core-js/modules/esnext.async-iterator.map.js";import"core-js/modules/esnext.iterator.map.js";import{ref as e,inject as t,reactive as s,markRaw as a,nextTick as r,onUnmounted as o,defineComponent as n,toRef as l,openBlock as i,createBlock as u,unref as d,withCtx as c,renderSlot as m,provide as p,resolveDynamicComponent as f,normalizeProps as h,guardReactiveProps as v,computed as _,createCommentVNode as g,createElementVNode as y,createVNode as b,h as A,createApp as x,createElementBlock as w,Fragment as j,withModifiers as G,readonly as k,toDisplayString as M,mergeProps as $}from"vue";import"core-js/modules/esnext.async-iterator.for-each.js";import"core-js/modules/esnext.iterator.constructor.js";import"core-js/modules/esnext.iterator.for-each.js";import{fail as I,JSError as S,MagicObject as C,PromisedValue as H,facade as O,arr as P,tap as E,stringMatch as q,uuid as B,objectWithoutEmpty as F}from"@noeldemartin/utils";import"core-js/modules/esnext.async-iterator.reduce.js";import"core-js/modules/esnext.iterator.reduce.js";import{useI18n as L,createI18n as V}from"vue-i18n";import T from"@babel/runtime/helpers/esm/defineProperty";import{setEngine as N,IndexedDBEngine as D,bootModelsFromViteGlob as z}from"soukai";import{createRouter as K,createWebHistory as Q}from"vue-router";import"core-js/modules/esnext.string.at.js";import"core-js/modules/esnext.async-iterator.filter.js";import"core-js/modules/esnext.iterator.filter.js";import{Dialog as R,DialogPanel as U,DialogTitle as J}from"@headlessui/vue";import W from"dompurify";import{marked as X}from"marked";import"core-js/modules/esnext.async-iterator.some.js";import"core-js/modules/esnext.iterator.some.js";const Y=[];function Z(e){return{type:Array,default:e??(()=>[])}}function ee(){return{type:Boolean,default:arguments.length>0&&void 0!==arguments[0]&&arguments[0]}}function te(){return e()}function se(e){return e}function ae(e,t){const s=Object.values(e);return{type:String,default:t??s[0]??null,validator:e=>s.includes(e)}}function re(e){const a=t(e);return a?s(a):void 0}function oe(e,t){return re(e)??I(t??`Could not resolve '${e}' injection key`)}function ne(e,s){return t(e)??I(s??`Could not resolve '${e}' injection key`)}function le(e){return{type:e,default:null}}function ie(){return{type:Number,default:arguments.length>0&&void 0!==arguments[0]?arguments[0]:null}}function ue(){return{type:Object,default:arguments.length>0&&void 0!==arguments[0]?arguments[0]:null}}function de(){return{type:Array,required:!0}}function ce(e){const t=Object.values(e);return{type:String,required:!0,validator:e=>t.includes(e)}}function me(e){return{type:e,required:!0}}function pe(){return{type:Number,required:!0}}function fe(){return{type:Object,required:!0}}function he(){return{type:String,required:!0}}function ve(){return{type:String,default:arguments.length>0&&void 0!==arguments[0]?arguments[0]:null}}const _e={"initial-focus":{mounted(e,t){let{value:s}=t;!1!==s&&e.focus()}}};var ge=async e=>{Object.entries(_e).forEach((t=>{let[s,a]=t;return e.directive(s,a)}))};class ServiceBootError extends S{constructor(e,t){super(`Service '${e}' failed booting`,{cause:t})}}function ye(e){return class extends be{getInitialState(){return e.initialState}}}class be extends C{constructor(){super(),T(this,"_namespace",void 0),T(this,"_booted",void 0),T(this,"_state",void 0),this._namespace=new.target.name,this._booted=new H,this._state=s(this.getInitialState())}get booted(){return this._booted}launch(e){const handleError=e=>this._booted.reject(new ServiceBootError(this._namespace,e));this._namespace=e??this._namespace;try{this.boot().then((()=>this._booted.resolve())).catch(handleError)}catch(e){handleError(e)}return this._booted}__get(e){return this.hasState(e)?this.getState(e):super.__get(e)}__set(e,t){this.setState({[e]:t})}hasState(e){return e in this._state}getState(e){return e?this._state[e]:this._state}setState(e){Object.assign(this._state,e)}getInitialState(){return{}}async boot(){}}class Ae extends be{constructor(){super(...arguments),T(this,"listeners",{})}async emit(e,t){const s=[...this.listeners[e]??[]];await Promise.all(s.map((e=>e(t)))??[])}on(e,t){return(this.listeners[e]??=P([])).push(t),()=>this.off(e,t)}once(e,t){let s=null;return E((()=>s&&this.off(e,s)),(a=>{(this.listeners[e]??=P([])).push(s=function(){return a(),t(...arguments)})}))}off(e,t){const s=this.listeners[e];s&&(s.remove(t),s.isEmpty()&&delete this.listeners[e])}}var xe=O(new Ae);const we={$events:xe};async function je(e,t){await Promise.all(Object.entries(t).map((async e=>{let[t,s]=e;await s.launch(t.slice(1)).catch((e=>console.error(e)))}))),Object.assign(e.config.globalProperties,t)}var Ge=e=>je(e,we);var ke=O(new class extends be{constructor(){super(...arguments),T(this,"i18n",void 0)}setup(){this.i18n=L()}translate(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return this.i18n?.t(e,t)??e}});function Me(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return ke.translate(e,t)}const $e={$lang:ke};async function Ie(e){const t=e.defaultLocale??"en",s=e.fallbackLocale??"en",a=function(e){return Object.entries(e).reduce(((e,t)=>{let[s,a]=t;const r=q(s,/.*\/lang\/(.+)\.yaml/)?.[1];return r&&(e[r]=()=>a().then((e=>{let{default:t}=e;return t}))),e}),{})}(e.messages),r=a[t]??I(`Missing messages for '${t}' locale`),o={[t]:await r()};return V({locale:t,fallbackLocale:s,messages:o})}var Se=async(e,t)=>{const s=function(e){return e.lang?e.lang:e.langMessages?{messages:e.langMessages}:null}(t);if(!s)return;var a;a=()=>ke.setup(),Y.push(a);const r=await Ie(s);e.use(r),await je(e,$e)},Ce=async(e,t)=>{t.models&&(N(new D),z(t.models))};var He=async(e,t)=>{if(!t.routes)return;const s=function(e){return K({history:Q(e.basePath),routes:e.routes})}({routes:t.routes,basePath:t.basePath??__AG_BASE_PATH});e.use(s)},Oe=ye({initialState:{modals:[]}});const Pe={AlertModal:"alert-modal"};var Ee=O(new class extends Oe{constructor(){super(...arguments),T(this,"modalCallbacks",{}),T(this,"components",{})}alert(e){this.openModal(this.requireComponent(Pe.AlertModal),{message:e})}registerComponent(e,t){this.components[e]=t}async openModal(e,t){const s=B(),o={},n={id:s,properties:t??{},component:a(e),beforeClose:new Promise((e=>o.willClose=e)),afterClose:new Promise((e=>o.closed=e))},l=this.modals.at(-1),i=this.modals.concat(n);return this.modalCallbacks[n.id]=o,this.setState({modals:i}),await r(),await(l&&xe.emit("hide-modal",{id:l.id})),await Promise.all([l||xe.emit("show-overlays-backdrop"),xe.emit("show-modal",{id:n.id})]),n}async closeModal(e,t){await xe.emit("close-modal",{id:e,result:t})}async boot(){await super.boot(),this.watchModalEvents()}requireComponent(e){return this.components[e]??I(`UI Component '${e}' is not defined!`)}watchModalEvents(){xe.on("modal-will-close",(e=>{let{modal:t,result:s}=e;this.modalCallbacks[t.id]?.willClose?.(s),1===this.modals.length&&xe.emit("hide-overlays-backdrop")})),xe.on("modal-closed",(async e=>{let{modal:t,result:s}=e;this.setState({modals:this.modals.filter((e=>e.id!==t.id))}),this.modalCallbacks[t.id]?.closed?.(s),delete this.modalCallbacks[t.id];const a=this.modals.at(-1);await(a&&xe.emit("show-modal",{id:a.id}))}))}});function qe(e,t){const s=xe.on(e,t);o((()=>s()))}var Be=n({__name:"AGHeadlessModal",props:{cancellable:ee(!0)},setup(t,{expose:s}){const a=t,r=e(null),o=e(!0),n=e(!1),{modal:p}=oe("modal");async function f(){r.value?.$el&&(o.value=!0)}async function h(e){n.value||(xe.emit("modal-will-close",{modal:p,result:e}),await f(),n.value=!0,xe.emit("modal-closed",{modal:p,result:e}))}return qe("close-modal",(async({id:e,result:t})=>{e===p.id&&await h(t)})),qe("hide-modal",(async({id:e})=>{e===p.id&&await f()})),qe("show-modal",(async({id:e})=>{e===p.id&&await async function(){r.value?.$el&&(o.value=!1)}()})),s({close:h,cancellable:l(a,"cancellable")}),(e,s)=>(i(),u(d(R),{ref_key:"$root",ref:r,open:!0,onClose:s[0]||(s[0]=e=>t.cancellable&&h())},{default:c((()=>[m(e.$slots,"default",{close:h})])),_:3},512))}});Be.__file="src/components/headless/modals/AGHeadlessModal.vue";var Fe=n({__name:"AGModalContext",props:{modal:fe(),childIndex:pe()},setup(e){const t=e;return p("modal",{modal:l(t,"modal"),childIndex:l(t,"childIndex")}),(t,s)=>(i(),u(f(e.modal.component),h(v(e.modal.properties)),null,16))}});Fe.__file="src/components/modals/AGModalContext.vue";var Le=n({__name:"AGHeadlessModalPanel",setup(e){const t=oe("modal"),s=_((()=>Ee.modals[t.childIndex]??null));return(e,a)=>(i(),u(d(U),null,{default:c((()=>[m(e.$slots,"default"),s.value?(i(),u(Fe,{key:0,"child-index":d(t).childIndex+1,modal:s.value},null,8,["child-index","modal"])):g("v-if",!0)])),_:3}))}});Le.__file="src/components/headless/modals/AGHeadlessModalPanel.vue";const Ve={class:"fixed inset-0 flex items-center justify-center"},Te={class:"flex max-h-full flex-col overflow-auto p-4"};var Ne=n({__name:"AGModal",setup:e=>(e,t)=>(i(),u(Be,{class:"relative z-50"},{default:c((({close:t})=>[y("div",Ve,[b(Le,{class:"flex max-h-full max-w-full flex-col overflow-hidden bg-white"},{default:c((()=>[y("div",Te,[m(e.$slots,"default",{close:t})])])),_:2},1024)])])),_:3}))});function De(e){return t=X(e,{mangle:!1,headerIds:!1}),W.sanitize(t,{ADD_ATTR:["target"]});var t}Ne.__file="src/components/modals/AGModal.vue";var ze=n({__name:"AGMarkdown",props:{langKey:ve(),text:ve()},setup(e){const t=e,s=_((()=>t.text??(t.langKey&&Me(t.langKey)))),a=_((()=>s.value&&De(s.value))),r=()=>A("div",{class:"prose",innerHTML:a.value});return(e,t)=>(i(),u(r))}});ze.__file="src/components/basic/AGMarkdown.vue";var Ke=n({__name:"AGAlertModal",props:{message:he()},setup:e=>(t,s)=>(i(),u(Ne,null,{default:c((()=>[b(ze,{text:e.message},null,8,["text"])])),_:1}))});Ke.__file="src/components/modals/AGAlertModal.vue";const Qe={$ui:Ee};var Re=async(e,t)=>{const s={[Pe.AlertModal]:Ke};Object.entries({...s,...t.components}).forEach((e=>{let[t,s]=e;return Ee.registerComponent(t,s)})),await je(e,Qe)};async function Ue(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const s=[ge,Se,Ce,He,Ge,Re],a=x({data:()=>({ready:!1}),mounted(){Y.forEach((e=>e())),this.ready=!0},render(){return this.ready?A(e):null}});await Promise.all(s.map((e=>e(a,t)))),a.mount("#app")}const Je={key:0};var We=n({__name:"AGAppOverlays",setup(t){const s=e(null),a=e(!0),r=_((()=>Ee.modals[0]??null));return qe("show-overlays-backdrop",(async()=>{s.value&&a.value&&(a.value=!1,s.value.classList.remove("opacity-0"))})),qe("hide-overlays-backdrop",(async()=>{s.value&&!a.value&&(a.value=!0,s.value.classList.add("opacity-0"))})),(e,t)=>(i(),w(j,null,[y("div",{ref_key:"$backdrop",ref:s,class:"pointer-events-none fixed inset-0 z-50 bg-black/30 opacity-0"},null,512),r.value?(i(),w("aside",Je,[b(Fe,{"child-index":1,modal:r.value},null,8,["modal"])])):g("v-if",!0)],64))}});We.__file="src/components/AGAppOverlays.vue";const Xe={class:"flex h-full flex-col text-base font-normal leading-tight text-gray-900 antialiased"};var Ye=n({__name:"AGAppLayout",setup:e=>(e,t)=>(i(),w("div",Xe,[m(e.$slots,"default"),b(We)]))});Ye.__file="src/components/AGAppLayout.vue";var Ze=n({__name:"AGHeadlessButton",props:{url:ve(),route:ve(),routeParams:ue((()=>({}))),routeQuery:ue((()=>({}))),submit:ee()},setup(e){const{url:t,route:s,routeParams:a,routeQuery:r,submit:o}=e,n=_((()=>s?{tag:"router-link",props:{to:F({name:s,params:a,query:r})}}:t?{tag:"a",props:{target:"_blank",href:t}}:{tag:"button",props:{type:o?"submit":"button"}}));return(e,t)=>(i(),u(f(n.value.tag),h(v(n.value.props)),{default:c((()=>[m(e.$slots,"default")])),_:3},16))}});Ze.__file="src/components/headless/forms/AGHeadlessButton.vue";var et=n({__name:"AGButton",setup:e=>(e,t)=>(i(),u(Ze,{class:"bg-indigo-600 px-2.5 py-1.5 text-white hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"},{default:c((()=>[m(e.$slots,"default")])),_:3}))});et.__file="src/components/forms/AGButton.vue";const tt=["onSubmit"];var st=n({__name:"AGForm",props:{form:ue()},emits:["submit"],setup(e,{emit:t}){const s=e;function a(){s.form&&!s.form.submit()||t("submit")}return p("form",s.form),(e,t)=>(i(),w("form",{onSubmit:G(a,["prevent"])},[m(e.$slots,"default")],40,tt))}});st.__file="src/components/forms/AGForm.vue";var at=n({__name:"AGHeadlessInput",props:{as:ve(),name:ve(),modelValue:ve()},emits:["update:modelValue"],setup(e,{expose:s,emit:a}){const r=e,o=_((()=>n&&r.name?n.errors[r.name]??null:null)),n=t("form"),l={id:B(),value:_((()=>n&&r.name?n.getFieldValue(r.name):r.modelValue)),errors:k(o),update(e){n&&r.name?n.setFieldValue(r.name,e):a("update:modelValue",e)}};return p("input",l),s(l),(t,s)=>e.as?(i(),u(f(e.as),{key:0},{default:c((()=>[m(t.$slots,"default")])),_:3})):m(t.$slots,"default",{key:1})}});at.__file="src/components/headless/forms/AGHeadlessInput.vue";const rt=["value","aria-invalid","aria-describedby"];var ot=n({__name:"AGHeadlessInputInput",setup(t){const s=e(),a=oe("input"),r=_((()=>a.value));function o(){s.value&&a.update(s.value.value)}return(e,t)=>(i(),w("input",{ref_key:"$input",ref:s,type:"text",value:r.value,"aria-invalid":d(a).errors?"true":"false","aria-describedby":d(a).errors?`${d(a).id}-error`:void 0,onInput:o},null,40,rt))}});ot.__file="src/components/headless/forms/AGHeadlessInputInput.vue";const nt=["id"];var lt=n({__name:"AGHeadlessInputError",setup(e){const t=oe("input"),s=_((()=>t.errors?Me(`errors.${t.errors[0]}`):null));return(e,a)=>s.value?(i(),w("p",{key:0,id:`${d(t).id}-error`},M(s.value),9,nt)):g("v-if",!0)}});lt.__file="src/components/headless/forms/AGHeadlessInputError.vue";var it=n({inheritAttrs:!1,__name:"AGInput",props:{name:ve()},setup(e){const t=te();return(s,a)=>(i(),u(at,{ref_key:"$input",ref:t,as:"div",class:"flex flex-col items-center",name:e.name},{default:c((()=>[b(ot,$(s.$attrs,{class:["block w-full border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600",{"ring-1 ring-red-500":d(t)?.errors}]}),null,16,["class"]),b(lt,{class:"mt-1 text-sm text-red-500"})])),_:1},8,["name"]))}});it.__file="src/components/forms/AGInput.vue";var ut=n({__name:"AGHeadlessModalTitle",props:{as:ve("h2")},setup:e=>(t,s)=>(i(),u(d(J),{as:e.as},{default:c((()=>[m(t.$slots,"default")])),_:3},8,["as"]))});ut.__file="src/components/headless/modals/AGHeadlessModalTitle.vue";const dt={String:"string",Number:"number"};class ct extends C{constructor(t){super(),T(this,"errors",void 0),T(this,"_fields",void 0),T(this,"_data",void 0),T(this,"_valid",void 0),T(this,"_submitted",void 0),T(this,"_errors",void 0),this._fields=t,this._submitted=e(!1),this._valid=e(!0),this._data=this.getInitialData(t),this._errors=this.getInitialErrors(t),this.errors=k(this._errors)}get valid(){return this._valid.value}get submitted(){return this._submitted.value}setFieldValue(e,t){this._data[e]=t,this._submitted.value&&this.validate()}getFieldValue(e){return this._data[e]}validate(){const e=Object.entries(this._fields).reduce(((e,t)=>{let[s,a]=t;return e[s]=this.getFieldErrors(s,a),e}),{});return Object.assign(this._errors,e),this._valid.value=!Object.values(e).some((e=>null!==e))}submit(){return this._submitted.value=!0,this.validate()}__get(e){return e in this._fields?this._data[e]:super.__get(e)}__set(e,t){e in this._fields?Object.assign(this._data,{[e]:t}):super.__set(e,t)}getFieldErrors(e,t){const s=[];return t.rules?.includes("required")&&!this._data[e]&&s.push("required"),s.length>0?s:null}getInitialData(e){if(this.static().isConjuring())return{};const t=Object.entries(e).reduce(((e,t)=>{let[s,a]=t;return e[s]=a.default??null,e}),{});return s(t)}getInitialErrors(e){if(this.static().isConjuring())return{};const t=Object.keys(e).reduce(((e,t)=>(e[t]=null,e)),{});return s(t)}}function mt(e){return new ct(e)}function pt(e){return{default:e,type:dt.Number,rules:"required"}}function ft(e){return{default:e,type:dt.String,rules:"required"}}function ht(e){return{default:e,type:dt.Number}}function vt(e){return{default:e,type:dt.String}}export{Ye as AGAppLayout,et as AGButton,st as AGForm,Ze as AGHeadlessButton,at as AGHeadlessInput,Be as AGHeadlessModal,Le as AGHeadlessModalPanel,ut as AGHeadlessModalTitle,it as AGInput,ze as AGMarkdown,Ne as AGModal,Fe as AGModalContext,xe as Events,Ae as EventsService,dt as FormFieldTypes,ke as Lang,be as Service,Ee as UI,Pe as UIComponents,Z as arrayProp,ee as booleanProp,je as bootServices,Ue as bootstrapApplication,te as componentRef,se as defineDirective,ye as defineServiceState,ae as enumProp,ne as injectOrFail,re as injectReactive,oe as injectReactiveOrFail,Me as lang,le as mixedProp,ht as numberInput,ie as numberProp,ue as objectProp,de as requiredArrayProp,ce as requiredEnumProp,me as requiredMixedProp,pt as requiredNumberInput,pe as requiredNumberProp,fe as requiredObjectProp,ft as requiredStringInput,he as requiredStringProp,vt as stringInput,ve as stringProp,mt as useForm};
1
+ import"core-js/modules/esnext.async-iterator.map.js";import"core-js/modules/esnext.iterator.map.js";import{ref as e,inject as t,reactive as s,markRaw as r,nextTick as o,onUnmounted as a,useAttrs as n,computed as l,onMounted as i,defineComponent as u,toRef as d,openBlock as c,createBlock as m,unref as p,withCtx as f,renderSlot as h,provide as v,resolveDynamicComponent as _,normalizeProps as g,guardReactiveProps as b,createElementBlock as y,Fragment as x,createVNode as A,createCommentVNode as j,createElementVNode as w,h as G,normalizeClass as S,createTextVNode as k,toDisplayString as M,createApp as E,readonly as $,mergeProps as C,withModifiers as I}from"vue";import"core-js/modules/esnext.async-iterator.for-each.js";import"core-js/modules/esnext.iterator.constructor.js";import"core-js/modules/esnext.iterator.for-each.js";import{fail as H,JSError as O,MagicObject as P,PromisedValue as q,objectOnly as L,isEmpty as B,Storage as D,objectDeepClone as R,facade as F,arr as N,tap as V,uuid as z,toString as T,isObject as K,objectWithout as U,noop as Q,objectWithoutEmpty as W}from"@noeldemartin/utils";import J from"@babel/runtime/helpers/esm/defineProperty";import"core-js/modules/esnext.set.add-all.js";import"core-js/modules/esnext.set.delete-all.js";import"core-js/modules/esnext.set.difference.js";import"core-js/modules/esnext.set.every.js";import"core-js/modules/esnext.set.filter.js";import"core-js/modules/esnext.set.find.js";import"core-js/modules/esnext.set.intersection.js";import"core-js/modules/esnext.set.is-disjoint-from.js";import"core-js/modules/esnext.set.is-subset-of.js";import"core-js/modules/esnext.set.is-superset-of.js";import"core-js/modules/esnext.set.join.js";import"core-js/modules/esnext.set.map.js";import"core-js/modules/esnext.set.reduce.js";import"core-js/modules/esnext.set.some.js";import"core-js/modules/esnext.set.symmetric-difference.js";import"core-js/modules/esnext.set.union.js";import{defineStore as X,createPinia as Y,setActivePinia as Z}from"pinia";import"core-js/modules/esnext.string.at.js";import"core-js/modules/esnext.async-iterator.filter.js";import"core-js/modules/esnext.iterator.filter.js";import"core-js/modules/esnext.async-iterator.reduce.js";import"core-js/modules/esnext.iterator.reduce.js";import"core-js/modules/esnext.async-iterator.some.js";import"core-js/modules/esnext.iterator.some.js";import{Dialog as ee,DialogPanel as te,DialogTitle as se}from"@headlessui/vue";import re from"dompurify";import{marked as oe}from"marked";function ae(e){return e}function ne(e){return{type:Array,default:e??(()=>[])}}function le(){return{type:Boolean,default:arguments.length>0&&void 0!==arguments[0]&&arguments[0]}}function ie(){return e()}function ue(e){return e}function de(e,t){const s=Object.values(e);return{type:String,default:t??s[0]??null,validator:e=>s.includes(e)}}function ce(e){const r=t(e);return r?s(r):void 0}function me(e,t){return ce(e)??H(t??`Could not resolve '${e}' injection key`)}function pe(e,s){return t(e)??H(s??`Could not resolve '${e}' injection key`)}function fe(e){return{type:e,default:null}}function he(){return{type:Number,default:arguments.length>0&&void 0!==arguments[0]?arguments[0]:null}}function ve(){return{type:Object,default:arguments.length>0&&void 0!==arguments[0]?arguments[0]:null}}function _e(){return{type:Array,required:!0}}function ge(e){const t=Object.values(e);return{type:String,required:!0,validator:e=>t.includes(e)}}function be(e){return{type:e,required:!0}}function ye(){return{type:Number,required:!0}}function xe(){return{type:Object,required:!0}}function Ae(){return{type:String,required:!0}}function je(){return{type:String,default:arguments.length>0&&void 0!==arguments[0]?arguments[0]:null}}const we={"initial-focus":{mounted(e,t){let{value:s}=t;!1!==s&&e.focus()}}};var Ge={install(e){Object.entries(we).forEach((t=>{let[s,r]=t;return e.directive(s,r)}))}};class ServiceBootError extends O{constructor(e,t){super(`Service '${e}' failed booting`,{cause:t})}}let Se=null;function ke(){return Se||(Se=Y(),Z(Se)),Se}function Me(e){var t;return J(t=class extends Ee{usesStore(){return!0}getName(){return e.name??null}getInitialState(){return e.initialState}getComputedStateDefinition(){return e.computed??{}}serializePersistedState(t){return e.serialize?.(t)??t}},"persist",e.persist??[]),t}class Ee extends P{constructor(){super(),J(this,"_name",void 0),J(this,"_booted",void 0),J(this,"_computedStateKeys",void 0),J(this,"_store",void 0);const e=this.getComputedStateDefinition();var t,s;this._name=this.getName()??new.target.name,this._booted=new q,this._computedStateKeys=new Set(Object.keys(e)),this._store=this.usesStore()&&(t=this._name,s={state:()=>this.getInitialState(),getters:e},ke(),X(t,s)())}get booted(){return this._booted}launch(){const handleError=e=>this._booted.reject(new ServiceBootError(this._name,e));try{this.boot().then((()=>this._booted.resolve())).catch(handleError)}catch(e){handleError(e)}return this._booted}hasState(e){return!!this._store&&(e in this._store.$state||this._computedStateKeys.has(e))}getState(e){const t=this._store;return e?t?t[e]:void 0:t||{}}setState(e,t){if(!this._store)return;const s="string"==typeof e?{[e]:t}:e;Object.assign(this._store.$state,s),this.onStateUpdated(s)}__get(e){return this.hasState(e)?this.getState(e):super.__get(e)}__set(e,t){this.setState({[e]:t})}onStateUpdated(e){const t=this.constructor.persist,s=L(e,t);if(B(s))return;const r=D.require(this._name);D.set(this._name,{...r,...this.serializePersistedState(R(s))})}usesStore(){return!1}getName(){return null}getInitialState(){return{}}getComputedStateDefinition(){return{}}serializePersistedState(e){return e}async boot(){this.restorePersistedState()}restorePersistedState(){const e=this.constructor.persist;if(this.usesStore()&&!B(e))if(D.has(this._name)){const e=D.require(this._name);this.setState(e)}else D.set(this._name,L(this.getState(),e))}}J(Ee,"persist",[]);class $e extends Ee{constructor(){super(...arguments),J(this,"listeners",{})}async emit(e,t){const s=[...this.listeners[e]??[]];await Promise.all(s.map((e=>e(t)))??[])}on(e,t){return(this.listeners[e]??=N([])).push(t),()=>this.off(e,t)}once(e,t){let s=null;return V((()=>s&&this.off(e,s)),(r=>{(this.listeners[e]??=N([])).push(s=function(){return r(),t(...arguments)})}))}off(e,t){const s=this.listeners[e];s&&(s.remove(t),s.isEmpty()&&delete this.listeners[e])}}var Ce=F(new $e),Ie=Me({name:"app",initialState:{environment:__AG_ENV,isMounted:!1},computed:{isDevelopment:e=>"development"===e.environment,isTesting:e=>"testing"===e.environment}});class He extends Ie{async boot(){await super.boot(),Ce.once("application-mounted",(()=>this.setState({isMounted:!0})))}}var Oe=F(new He);const Pe={$app:Oe,$events:Ce};async function qe(e,t){await Promise.all(Object.entries(t).map((async e=>{let[t,s]=e;await s.launch().catch((e=>console.error(e)))}))),Object.assign(e.config.globalProperties,t)}var Le={async install(e,t){const s={...Pe,...t.services};e.use(Se??ke()),await qe(e,s)}},Be=Me({name:"ui",initialState:{modals:[]}});const De={AlertModal:"alert-modal",ConfirmModal:"confirm-modal",LoadingModal:"loading-modal"};var Re=F(new class extends Be{constructor(){super(...arguments),J(this,"modalCallbacks",{}),J(this,"components",{})}alert(e,t){const s="string"==typeof t?{title:e,message:t}:{message:e};this.openModal(this.requireComponent(De.AlertModal),s)}async confirm(e,t){const s="string"==typeof t?{title:e,message:t}:{message:e},r=await this.openModal(this.requireComponent(De.ConfirmModal),s);return await r.beforeClose??!1}async loading(e,t){t="string"==typeof e?t:e;const s="string"==typeof e?e:void 0,r=await this.openModal(this.requireComponent(De.LoadingModal),{message:s}),o=await t;return await this.closeModal(r.id),o}registerComponent(e,t){this.components[e]=t}async openModal(e,t){const s=z(),a={},n={id:s,properties:t??{},component:r(e),beforeClose:new Promise((e=>a.willClose=e)),afterClose:new Promise((e=>a.closed=e))},l=this.modals.at(-1),i=this.modals.concat(n);return this.modalCallbacks[n.id]=a,this.setState({modals:i}),await o(),await(l&&Ce.emit("hide-modal",{id:l.id})),await Promise.all([l||Ce.emit("show-overlays-backdrop"),Ce.emit("show-modal",{id:n.id})]),n}async closeModal(e,t){await Ce.emit("close-modal",{id:e,result:t})}async boot(){await super.boot(),this.watchModalEvents()}requireComponent(e){return this.components[e]??H(`UI Component '${e}' is not defined!`)}watchModalEvents(){Ce.on("modal-will-close",(e=>{let{modal:t,result:s}=e;this.modalCallbacks[t.id]?.willClose?.(s),1===this.modals.length&&Ce.emit("hide-overlays-backdrop")})),Ce.on("modal-closed",(async e=>{let{modal:t,result:s}=e;this.setState({modals:this.modals.filter((e=>e.id!==t.id))}),this.modalCallbacks[t.id]?.closed?.(s),delete this.modalCallbacks[t.id];const r=this.modals.at(-1);await(r&&Ce.emit("show-modal",{id:r.id}))}))}});var Fe=F(new class extends Ee{constructor(){super(),J(this,"provider",void 0),this.provider={translate:e=>(Oe.isDevelopment&&console.warn("Lang provider is missing"),e)}}setProvider(e){this.provider=e}translate(e,t){return this.provider.translate(e,t)??e}translateWithDefault(e,t,s){s??=t;const r="string"==typeof t?{}:t??{},o=this.provider.translate(e,r)??e;return o===e?Object.entries(r).reduce(((e,t)=>{let[s,r]=t;return e.replace(new RegExp(`\\{\\s*${s}\\s*\\}`,"g"),T(r))}),s):o}});const Ne=Fe.translate.bind(Fe),Ve=Fe.translateWithDefault.bind(Fe);var ze=Me({name:"errors",initialState:{logs:[],startupErrors:[]},computed:{hasErrors:e=>{let{logs:t}=e;return t.length>0},hasNewErrors:e=>{let{logs:t}=e;return t.some((e=>!e.seen))},hasStartupErrors:e=>{let{startupErrors:t}=e;return t.length>0}}});var Te=F(new class extends ze{constructor(){super(...arguments),J(this,"forceReporting",!1),J(this,"enabled",!0)}enable(){this.enabled=!0}disable(){this.enabled=!1}async inspect(e){Array.isArray(e)||await this.createErrorReport(e)}async report(e,t){if((Oe.isDevelopment||Oe.isTesting)&&this.logError(e),!this.enabled)throw e;if(!Oe.isMounted){const t=await this.createStartupErrorReport(e);return void(t&&this.setState({startupErrors:this.startupErrors.concat(t)}))}const s={report:await this.createErrorReport(e),seen:!1,date:new Date};Re.alert(t??"Something went wrong, but it's not your fault! (look at the console for details)"),this.setState({logs:[s].concat(this.logs)})}see(e){this.setState({logs:this.logs.map((t=>t.report!==e?t:{...t,seen:!0}))})}seeAll(){this.setState({logs:this.logs.map((e=>({...e,seen:!0})))})}logError(e){console.error(e),K(e)&&e.cause&&this.logError(e.cause)}async createErrorReport(e){return"string"==typeof e?{title:e}:e instanceof Error||e instanceof O?this.createErrorReportFromError(e):{title:Ne("errors.unknown"),error:e}}async createStartupErrorReport(e){return e instanceof ServiceBootError?e.cause instanceof ServiceBootError?null:this.createErrorReport(e.cause):this.createErrorReport(e)}createErrorReportFromError(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return{title:e.name,description:e.message,details:e.stack,error:e,...t}}});const Ke={$errors:Te};var Ue={async install(e){await qe(e,Ke)}};const Qe={$lang:Fe};var We={async install(e){e.config.globalProperties.$t??=Ne,e.config.globalProperties.$td=Ve,await qe(e,Qe)}};function Je(e,t){const s=Ce.on(e,t);a((()=>s()))}function Xe(){const e=n(),t=l((()=>e.class));return[l((()=>U(e,"class"))),t]}function Ye(e){let t=Q;i((()=>t=e())),a((()=>t()))}var Ze=u({__name:"AGHeadlessModal",props:{cancellable:le(!0)},setup(t,{expose:s}){const r=t,o=e(null),a=e(!0),n=e(!1),{modal:l}=me("modal","could not obtain modal reference from <AGHeadlessModal>, did you render this component manually? Show it using $ui.openModal() instead");async function i(){o.value?.$el&&(a.value=!0)}async function u(e){n.value||(Ce.emit("modal-will-close",{modal:l,result:e}),await i(),n.value=!0,Ce.emit("modal-closed",{modal:l,result:e}))}return Je("close-modal",(async({id:e,result:t})=>{e===l.id&&await u(t)})),Je("hide-modal",(async({id:e})=>{e===l.id&&await i()})),Je("show-modal",(async({id:e})=>{e===l.id&&await async function(){o.value?.$el&&(a.value=!1)}()})),s({close:u,cancellable:d(r,"cancellable")}),(e,s)=>(c(),m(p(ee),{ref_key:"$root",ref:o,open:!0,onClose:s[0]||(s[0]=e=>t.cancellable&&u())},{default:f((()=>[h(e.$slots,"default",{close:u})])),_:3},512))}});Ze.__file="src/components/headless/modals/AGHeadlessModal.vue";var et=u({__name:"AGModalContext",props:{modal:xe(),childIndex:ye()},setup(e){const t=e;return v("modal",{modal:d(t,"modal"),childIndex:d(t,"childIndex")}),(t,s)=>(c(),m(_(e.modal.component),g(b(e.modal.properties)),null,16))}});et.__file="src/components/modals/AGModalContext.vue";const tt=w("div",{class:"pointer-events-none fixed inset-0 z-50 bg-black/30"},null,-1);var st=u({__name:"AGHeadlessModalPanel",setup(e){const t=me("modal","could not obtain modal reference from <AGHeadlessModalPanel>, did you render this component manually? Show it using $ui.openModal() instead"),s=l((()=>Re.modals[t.childIndex]??null));return(e,r)=>(c(),m(p(te),null,{default:f((()=>[h(e.$slots,"default"),s.value?(c(),y(x,{key:0},[tt,A(et,{"child-index":p(t).childIndex+1,modal:s.value},null,8,["child-index","modal"])],64)):j("v-if",!0)])),_:3}))}});st.__file="src/components/headless/modals/AGHeadlessModalPanel.vue";const rt={class:"fixed inset-0 flex items-center justify-center"},ot={class:"flex max-h-full flex-col overflow-auto p-4"};var at=u({__name:"AGModal",props:{cancellable:le(!0)},setup(t,{expose:s}){const r=e();return s({close:async()=>r.value?.close(),cancellable:l((()=>!!r.value?.cancellable))}),(e,s)=>(c(),m(Ze,{ref_key:"$headlessModal",ref:r,cancellable:t.cancellable,class:"relative z-50"},{default:f((({close:t})=>[w("div",rt,[A(st,{class:"flex max-h-full max-w-full flex-col overflow-hidden bg-white"},{default:f((()=>[w("div",ot,[h(e.$slots,"default",{close:t})])])),_:2},1024)])])),_:3},8,["cancellable"]))}});function nt(e){return t=oe(e,{mangle:!1,headerIds:!1}),re.sanitize(t,{ADD_ATTR:["target"]});var t}at.__file="src/components/modals/AGModal.vue";var lt=u({__name:"AGMarkdown",props:{as:je("div"),langKey:je(),text:je(),inline:le(),raw:le()},setup(e){const t=e,s=l((()=>t.text??(t.langKey&&Ne(t.langKey)))),r=l((()=>{if(!s.value)return null;let e=nt(s.value);return t.inline&&(e=e.replace("<p>","<span>").replace("</p>","</span>")),e})),o=()=>G(t.as,{class:t.raw?"":"prose",innerHTML:r.value});return(e,t)=>(c(),m(o))}});lt.__file="src/components/basic/AGMarkdown.vue";var it=u({__name:"AGAlertModal",props:{title:je(),message:Ae()},setup:e=>(t,s)=>(c(),m(at,null,{default:f((()=>[e.title?(c(),m(lt,{key:0,text:e.title,as:"h2",class:"font-semibold",raw:"",inline:""},null,8,["text"])):j("v-if",!0),A(lt,{text:e.message},null,8,["text"])])),_:1}))});it.__file="src/components/modals/AGAlertModal.vue";var ut=u({__name:"AGHeadlessButton",props:{url:je(),route:je(),routeParams:ve((()=>({}))),routeQuery:ve((()=>({}))),submit:le()},setup(e){const{url:t,route:s,routeParams:r,routeQuery:o,submit:a}=e,n=l((()=>s?{tag:"router-link",props:{to:W({name:s,params:r,query:o})}}:t?{tag:"a",props:{target:"_blank",href:t}}:{tag:"button",props:{type:a?"submit":"button"}}));return(e,t)=>(c(),m(_(n.value.tag),g(b(n.value.props)),{default:f((()=>[h(e.$slots,"default")])),_:3},16))}});ut.__file="src/components/headless/forms/AGHeadlessButton.vue";var dt=u({__name:"AGButton",props:{clear:le(),secondary:le()},setup(e){const t=e,s=l((()=>t.secondary?"text-white bg-gray-600 hover:bg-gray-500 focus-visible:outline-offset-2 focus-visible:outline-gray-600":t.clear?"hover:bg-gray-500/20 focus-visible:outline-gray-500/60":["text-white bg-indigo-600","hover:bg-indigo-500","focus-visible:outline-offset-2 focus-visible:outline-indigo-600"].join(" ")));return(e,t)=>(c(),m(ut,{class:S(["px-2.5 py-1.5 focus-visible:outline focus-visible:outline-2",s.value])},{default:f((()=>[h(e.$slots,"default")])),_:3},8,["class"]))}});dt.__file="src/components/forms/AGButton.vue";const ct={class:"mt-2 flex flex-row-reverse gap-2"};var mt=u({__name:"AGConfirmModal",props:{title:je(),message:Ae()},setup:e=>(t,s)=>(c(),m(at,{cancellable:!1},{default:f((({close:s})=>[e.title?(c(),m(lt,{key:0,text:e.title,as:"h1"},null,8,["text"])):j("v-if",!0),A(lt,{text:e.message},null,8,["text"]),w("div",ct,[A(dt,{onClick:e=>s(!0)},{default:f((()=>[k(M(t.$td("ui.ok","OK")),1)])),_:2},1032,["onClick"]),A(dt,{secondary:"",onClick:e=>s()},{default:f((()=>[k(M(t.$td("ui.cancel","Cancel")),1)])),_:2},1032,["onClick"])])])),_:1}))});mt.__file="src/components/modals/AGConfirmModal.vue";var pt=u({__name:"AGLoadingModal",props:{message:je()},setup(e){const t=e,s=l((()=>t.message??Ve("ui.loading","Loading...")));return(e,t)=>(c(),m(at,{cancellable:!1},{default:f((()=>[A(lt,{text:s.value},null,8,["text"])])),_:1}))}});pt.__file="src/components/modals/AGLoadingModal.vue";const ft={$ui:Re};var ht={async install(e,t){const s={[De.AlertModal]:it,[De.ConfirmModal]:mt,[De.LoadingModal]:pt};Object.entries({...s,...t.components}).forEach((e=>{let[t,s]=e;return Re.registerComponent(t,s)})),await qe(e,ft)}};async function vt(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const s=[Ge,Ue,We,Le,ht,...t.plugins??[]],r=E(e);await Promise.all(s.map((e=>e.install(r,t)))??[]),r.mount("#app"),Ce.emit("application-mounted")}const _t={key:0};var gt=u({__name:"AGAppOverlays",setup(t){const s=e(null),r=e(!0),o=l((()=>Re.modals[0]??null));return Je("show-overlays-backdrop",(async()=>{s.value&&r.value&&(r.value=!1,s.value.classList.remove("opacity-0"))})),Je("hide-overlays-backdrop",(async()=>{s.value&&!r.value&&(r.value=!0,s.value.classList.add("opacity-0"))})),(e,t)=>(c(),y(x,null,[w("div",{ref_key:"$backdrop",ref:s,class:"pointer-events-none fixed inset-0 z-50 bg-black/30 opacity-0"},null,512),o.value?(c(),y("aside",_t,[A(et,{"child-index":1,modal:o.value},null,8,["modal"])])):j("v-if",!0)],64))}});gt.__file="src/components/AGAppOverlays.vue";const bt={class:"flex h-full flex-col text-base font-normal leading-tight text-gray-900 antialiased"};var yt=u({__name:"AGAppLayout",setup:e=>(e,t)=>(c(),y("div",bt,[h(e.$slots,"default"),A(gt)]))});yt.__file="src/components/AGAppLayout.vue";var xt=u({__name:"AGHeadlessInput",props:{as:je("div"),name:je(),modelValue:fe([String,Number,Boolean])},emits:["update:modelValue"],setup(e,{expose:s,emit:r}){const o=e,a=l((()=>n&&o.name?n.errors[o.name]??null:null)),n=t("form",null),i={id:`input-${z()}`,value:l((()=>n&&o.name?n.getFieldValue(o.name):o.modelValue)),errors:$(a),update(e){n&&o.name?n.setFieldValue(o.name,e):r("update:modelValue",e)}};return v("input",i),s(i),(t,s)=>e.as?(c(),m(_(e.as),{key:0},{default:f((()=>[h(t.$slots,"default")])),_:3})):h(t.$slots,"default",{key:1})}});xt.__file="src/components/headless/forms/AGHeadlessInput.vue";const At=["id"];var jt=u({__name:"AGHeadlessInputError",setup(e){const t=me("input","<AGHeadlessInputError> must be a child of a <AGHeadlessInput>"),s=l((()=>t.errors?Ve(`errors.${t.errors[0]}`,`Error: ${t.errors[0]}`):null));return(e,r)=>s.value?(c(),y("p",{key:0,id:`${p(t).id}-error`},M(s.value),9,At)):j("v-if",!0)}});jt.__file="src/components/headless/forms/AGHeadlessInputError.vue";const wt=["id","type","value","aria-invalid","aria-describedby","checked"];var Gt=u({__name:"AGHeadlessInputInput",props:{type:je("text")},setup(t){const s=t,r=e(),o=me("input","<AGHeadlessInputInput> must be a child of a <AGHeadlessInput>"),a=l((()=>o.value)),n=l((()=>{if("checkbox"===s.type)return!!a.value}));function i(){r.value&&o.update("checkbox"===s.type?r.value.checked:r.value.value)}return(e,s)=>(c(),y("input",{id:p(o).id,ref_key:"$input",ref:r,type:t.type,value:a.value,"aria-invalid":p(o).errors?"true":"false","aria-describedby":p(o).errors?`${p(o).id}-error`:void 0,checked:n.value,onInput:i},null,40,wt))}});Gt.__file="src/components/headless/forms/AGHeadlessInputInput.vue";const St=["for"];var kt=u({__name:"AGHeadlessInputLabel",setup(e){const t=me("input","<AGHeadlessInputLabel> must be a child of a <AGHeadlessInput>");return(e,s)=>(c(),y("label",{for:p(t).id},[h(e.$slots,"default")],8,St))}});kt.__file="src/components/headless/forms/AGHeadlessInputLabel.vue";const Mt={class:"ml-2"};var Et=u({inheritAttrs:!1,__name:"AGCheckbox",props:{name:je()},setup(e){const t=ie();return(s,r)=>(c(),m(xt,{ref_key:"$input",ref:t,name:e.name,class:"flex"},{default:f((()=>[A(Gt,C(s.$attrs,{type:"checkbox",class:{"text-indigo-600 focus:ring-indigo-600":!p(t)?.errors,"border-red-200 text-red-600 focus:ring-red-600":p(t)?.errors}}),null,16,["class"]),w("div",Mt,[s.$slots.default?(c(),m(kt,{key:0},{default:f((()=>[h(s.$slots,"default")])),_:3})):j("v-if",!0),A(jt,{class:"text-sm text-red-600"})])])),_:3},8,["name"]))}});Et.__file="src/components/forms/AGCheckbox.vue";const $t=["onSubmit"];var Ct=u({__name:"AGForm",props:{form:ve()},emits:["submit"],setup(e,{emit:t}){const s=e;function r(){s.form&&!s.form.submit()||t("submit")}return v("form",s.form),(e,t)=>(c(),y("form",{onSubmit:I(r,["prevent"])},[h(e.$slots,"default")],40,$t))}});Ct.__file="src/components/forms/AGForm.vue";const It={class:"absolute bottom-0 left-0 translate-y-full"};var Ht=u({inheritAttrs:!1,__name:"AGInput",props:{name:je()},setup(e){const t=ie(),[s,r]=Xe();return(o,a)=>(c(),m(xt,{ref_key:"$input",ref:t,class:S(["relative flex flex-col items-center",p(r)]),name:e.name},{default:f((()=>[A(Gt,C(p(s),{class:["block w-full border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600",{"ring-1 ring-red-500":p(t)?.errors}]}),null,16,["class"]),w("div",It,[A(jt,{class:"mt-1 text-sm text-red-500"})])])),_:1},8,["class","name"]))}});Ht.__file="src/components/forms/AGInput.vue";var Ot=u({__name:"AGHeadlessModalTitle",props:{as:je("h2")},setup:e=>(t,s)=>(c(),m(p(se),{as:e.as},{default:f((()=>[h(t.$slots,"default")])),_:3},8,["as"]))});Ot.__file="src/components/headless/modals/AGHeadlessModalTitle.vue";const Pt={String:"string",Number:"number",Boolean:"boolean"};class qt extends P{constructor(t){super(),J(this,"errors",void 0),J(this,"_fields",void 0),J(this,"_data",void 0),J(this,"_valid",void 0),J(this,"_submitted",void 0),J(this,"_errors",void 0),this._fields=t,this._submitted=e(!1),this._data=this.getInitialData(t),this._errors=this.getInitialErrors(t),this._valid=l((()=>!Object.values(this._errors).some((e=>null!==e)))),this.errors=$(this._errors)}get valid(){return this._valid.value}get submitted(){return this._submitted.value}setFieldValue(e,t){this._data[e]=t,this._submitted.value&&this.validate()}getFieldValue(e){return this._data[e]}validate(){const e=Object.entries(this._fields).reduce(((e,t)=>{let[s,r]=t;return e[s]=this.getFieldErrors(s,r),e}),{});return this.resetErrors(e),this.valid}reset(){this._submitted.value=!1,this.resetData(),this.resetErrors()}submit(){return this._submitted.value=!0,this.validate()}__get(e){return e in this._fields?this._data[e]:super.__get(e)}__set(e,t){e in this._fields?Object.assign(this._data,{[e]:t}):super.__set(e,t)}getFieldErrors(e,t){const s=[];return t.rules?.includes("required")&&!this._data[e]&&s.push("required"),s.length>0?s:null}getInitialData(e){if(this.static().isConjuring())return{};const t=Object.entries(e).reduce(((e,t)=>{let[s,r]=t;return e[s]=r.default??null,e}),{});return s(t)}getInitialErrors(e){if(this.static().isConjuring())return{};const t=Object.keys(e).reduce(((e,t)=>(e[t]=null,e)),{});return s(t)}resetData(){for(const[e,t]of Object.entries(this._fields))this._data[e]=t.default??null}resetErrors(e){Object.keys(this._errors).forEach((e=>delete this._errors[e])),e&&Object.assign(this._errors,e)}}function Lt(e){return new qt(e)}function Bt(e){return{default:e,type:Pt.Boolean}}function Dt(e){return{default:e,type:Pt.Boolean,rules:"required"}}function Rt(e){return{default:e,type:Pt.Number,rules:"required"}}function Ft(e){return{default:e,type:Pt.String,rules:"required"}}function Nt(e){return{default:e,type:Pt.Number}}function Vt(e){return{default:e,type:Pt.String}}export{it as AGAlertModal,yt as AGAppLayout,gt as AGAppOverlays,dt as AGButton,Et as AGCheckbox,mt as AGConfirmModal,Ct as AGForm,ut as AGHeadlessButton,xt as AGHeadlessInput,jt as AGHeadlessInputError,Gt as AGHeadlessInputInput,kt as AGHeadlessInputLabel,Ze as AGHeadlessModal,st as AGHeadlessModalPanel,Ot as AGHeadlessModalTitle,Ht as AGInput,pt as AGLoadingModal,lt as AGMarkdown,at as AGModal,et as AGModalContext,Oe as App,He as AppService,Te as Errors,Ce as Events,$e as EventsService,Pt as FormFieldTypes,Fe as Lang,Ee as Service,Re as UI,De as UIComponents,ne as arrayProp,Bt as booleanInput,le as booleanProp,qe as bootServices,vt as bootstrapApplication,ie as componentRef,ue as defineDirective,ae as definePlugin,Me as defineServiceState,de as enumProp,pe as injectOrFail,ce as injectReactive,me as injectReactiveOrFail,fe as mixedProp,Nt as numberInput,he as numberProp,ve as objectProp,Ye as onCleanMounted,_e as requiredArrayProp,Dt as requiredBooleanInput,ge as requiredEnumProp,be as requiredMixedProp,Rt as requiredNumberInput,ye as requiredNumberProp,xe as requiredObjectProp,Ft as requiredStringInput,Ae as requiredStringProp,Vt as stringInput,je as stringProp,Ne as translate,Ve as translateWithDefault,Je as useEvent,Lt as useForm,Xe as useInputAttrs};
2
2
  //# sourceMappingURL=aerogel-core.esm.js.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@aerogel/core",
3
3
  "description": "The Lightest Solid",
4
- "version": "0.0.0-next.7f6ed5a1f91688a86bf5ede2adc465e4fd6cfdea",
4
+ "version": "0.0.0-next.b85327579d32f21c6a9fa21142f0165cdd320d7e",
5
5
  "main": "dist/aerogel-core.cjs.js",
6
6
  "module": "dist/aerogel-core.esm.js",
7
7
  "types": "dist/aerogel-core.d.ts",
@@ -33,17 +33,15 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@headlessui/vue": "^1.7.14",
36
- "@noeldemartin/utils": "0.4.0-next.65c07a35cd02a0aa1ed9e742f72036354eba5fa8",
36
+ "@noeldemartin/utils": "0.4.0-next.ac00beaecf32bb02ed8e335225d7948d946d73bd",
37
37
  "dompurify": "^3.0.3",
38
38
  "marked": "^5.0.4",
39
- "soukai": "^0.5.1",
40
- "vue": "^3.3.0",
41
- "vue-i18n": "9.3.0-beta.19",
42
- "vue-router": "^4.2.1"
39
+ "pinia": "^2.1.6",
40
+ "vue": "^3.3.0"
43
41
  },
44
42
  "devDependencies": {
43
+ "@aerogel/vite": "*",
45
44
  "@types/dompurify": "^3.0.2",
46
- "@types/marked": "^5.0.0",
47
- "@vitejs/plugin-vue": "^4.2.3"
45
+ "@types/marked": "^5.0.0"
48
46
  }
49
47
  }
@@ -1,13 +1,10 @@
1
1
  import { beforeEach, describe, expect, it, vi } from 'vitest';
2
2
  import { createApp } from 'vue';
3
- import { createI18n } from 'vue-i18n';
4
- import { IndexedDBEngine, requireBootedModel, requireEngine } from 'soukai';
5
3
  import { mock } from '@noeldemartin/utils';
6
4
  import type { Component } from 'vue';
7
5
 
8
6
  import Events from '@/services/Events';
9
7
  import initialFocus from '@/directives/initial-focus';
10
- import User from '@/testing/stubs/models/User';
11
8
 
12
9
  import { bootstrapApplication } from './index';
13
10
 
@@ -29,59 +26,6 @@ describe('Aerogel', () => {
29
26
  });
30
27
  });
31
28
 
32
- it('Initializes Soukai', async () => {
33
- // Arrange
34
- const rootComponent = mock<Component>();
35
-
36
- // Act
37
- await bootstrapApplication(rootComponent, {
38
- models: import.meta.glob('@/testing/stubs/models/*', { eager: true }),
39
- });
40
-
41
- // Assert
42
- expect(requireBootedModel('User')).toEqual(User);
43
- expect(requireEngine()).toBeInstanceOf(IndexedDBEngine);
44
- });
45
-
46
- it('Initializes routes', async () => {
47
- // Arrange
48
- vi.mock('vue-router', () => ({
49
- createRouter: vi.fn(() => ({ routerMock: true })),
50
- createWebHistory: vi.fn(),
51
- }));
52
-
53
- const rootComponent = mock<Component>();
54
-
55
- // Act
56
- await bootstrapApplication(rootComponent, {
57
- routes: [],
58
- });
59
-
60
- // Assert
61
- expect(vi.mocked(createApp).mock.results[0]?.value.use).toHaveBeenCalledWith({ routerMock: true });
62
- });
63
-
64
- it('Initializes lang', async () => {
65
- // Arrange
66
- vi.mock('vue-i18n', () => ({ createI18n: vi.fn(() => ({ i18nMock: true })) }));
67
-
68
- const rootComponent = mock<Component>();
69
-
70
- // Act
71
- await bootstrapApplication(rootComponent, {
72
- langMessages: import.meta.glob('@/testing/stubs/lang/*'),
73
- });
74
-
75
- // Assert
76
- const mockedCreateI18n = vi.mocked(createI18n);
77
- const mockedCreateApp = vi.mocked(createApp);
78
-
79
- expect(mockedCreateI18n).toHaveBeenCalled();
80
- expect(mockedCreateI18n.mock.calls[0]?.[0].messages).key('en').to.exist;
81
- expect(mockedCreateI18n.mock.calls[0]?.[0].messages?.['en']).key('foo').to.exist;
82
- expect(mockedCreateApp.mock.results[0]?.value.use).toHaveBeenCalledWith({ i18nMock: true });
83
- });
84
-
85
29
  it('Boots services', async () => {
86
30
  // Arrange
87
31
  const rootComponent = mock<Component>();
@@ -1,36 +1,20 @@
1
- import { createApp, h } from 'vue';
1
+ import { createApp } from 'vue';
2
2
  import type { Component } from 'vue';
3
3
 
4
4
  import directives from '@/directives';
5
+ import errors from '@/errors';
6
+ import Events from '@/services/Events';
5
7
  import lang from '@/lang';
6
- import models from '@/models';
7
- import routing from '@/routing';
8
8
  import services from '@/services';
9
9
  import ui from '@/ui';
10
- import { runAppMountedHooks } from '@/bootstrap/hooks';
11
- import type { BootstrapOptions } from '@/bootstrap/options';
10
+ import type { AerogelOptions } from '@/bootstrap/options';
12
11
 
13
- export async function bootstrapApplication(rootComponent: Component, options: BootstrapOptions = {}): Promise<void> {
14
- const hooks = [directives, lang, models, routing, services, ui];
15
- const app = createApp({
16
- data: () => ({
17
- ready: false,
18
- }),
19
- mounted() {
20
- runAppMountedHooks();
12
+ export async function bootstrapApplication(rootComponent: Component, options: AerogelOptions = {}): Promise<void> {
13
+ const plugins = [directives, errors, lang, services, ui, ...(options.plugins ?? [])];
14
+ const app = createApp(rootComponent);
21
15
 
22
- this.ready = true;
23
- },
24
- render() {
25
- if (!this.ready) {
26
- return null;
27
- }
28
-
29
- return h(rootComponent);
30
- },
31
- });
32
-
33
- await Promise.all(hooks.map((hook) => hook(app, options)));
16
+ await Promise.all(plugins.map((plugin) => plugin.install(app, options)) ?? []);
34
17
 
35
18
  app.mount('#app');
19
+ Events.emit('application-mounted');
36
20
  }
@@ -1 +1,5 @@
1
- export interface BootstrapOptions {}
1
+ import type { Plugin } from '@/plugins';
2
+
3
+ export interface AerogelOptions {
4
+ plugins?: Plugin[];
5
+ }
@@ -6,15 +6,30 @@
6
6
  import { computed, h } from 'vue';
7
7
 
8
8
  import { renderMarkdown } from '@/utils/markdown';
9
- import { stringProp } from '@/utils/vue';
10
- import { lang } from '@/lang/helpers';
9
+ import { booleanProp, stringProp } from '@/utils/vue';
10
+ import { translate } from '@/lang';
11
11
 
12
12
  const props = defineProps({
13
+ as: stringProp('div'),
13
14
  langKey: stringProp(),
14
15
  text: stringProp(),
16
+ inline: booleanProp(),
17
+ raw: booleanProp(),
15
18
  });
16
19
 
17
- const markdown = computed(() => props.text ?? (props.langKey && lang(props.langKey)));
18
- const html = computed(() => markdown.value && renderMarkdown(markdown.value));
19
- const root = () => h('div', { class: 'prose', innerHTML: html.value });
20
+ const markdown = computed(() => props.text ?? (props.langKey && translate(props.langKey)));
21
+ const html = computed(() => {
22
+ if (!markdown.value) {
23
+ return null;
24
+ }
25
+
26
+ let renderedHtml = renderMarkdown(markdown.value);
27
+
28
+ if (props.inline) {
29
+ renderedHtml = renderedHtml.replace('<p>', '<span>').replace('</p>', '</span>');
30
+ }
31
+
32
+ return renderedHtml;
33
+ });
34
+ const root = () => h(props.as, { class: props.raw ? '' : 'prose', innerHTML: html.value });
20
35
  </script>
@@ -1,11 +1,34 @@
1
1
  <template>
2
- <AGHeadlessButton
3
- class="bg-indigo-600 px-2.5 py-1.5 text-white hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
4
- >
2
+ <AGHeadlessButton class="px-2.5 py-1.5 focus-visible:outline focus-visible:outline-2" :class="colorClasses">
5
3
  <slot />
6
4
  </AGHeadlessButton>
7
5
  </template>
8
6
 
9
7
  <script setup lang="ts">
8
+ import { computed } from 'vue';
9
+
10
+ import { booleanProp } from '@/utils';
11
+
10
12
  import AGHeadlessButton from '../headless/forms/AGHeadlessButton.vue';
13
+
14
+ const props = defineProps({
15
+ clear: booleanProp(),
16
+ secondary: booleanProp(),
17
+ });
18
+
19
+ const colorClasses = computed(() => {
20
+ if (props.secondary) {
21
+ return 'text-white bg-gray-600 hover:bg-gray-500 focus-visible:outline-offset-2 focus-visible:outline-gray-600';
22
+ }
23
+
24
+ if (props.clear) {
25
+ return 'hover:bg-gray-500/20 focus-visible:outline-gray-500/60';
26
+ }
27
+
28
+ return [
29
+ 'text-white bg-indigo-600',
30
+ 'hover:bg-indigo-500',
31
+ 'focus-visible:outline-offset-2 focus-visible:outline-indigo-600',
32
+ ].join(' ');
33
+ });
11
34
  </script>
@@ -0,0 +1,35 @@
1
+ <template>
2
+ <AGHeadlessInput ref="$input" :name="name" class="flex">
3
+ <AGHeadlessInputInput
4
+ v-bind="$attrs"
5
+ type="checkbox"
6
+ :class="{
7
+ 'text-indigo-600 focus:ring-indigo-600': !$input?.errors,
8
+ 'border-red-200 text-red-600 focus:ring-red-600': $input?.errors,
9
+ }"
10
+ />
11
+
12
+ <div class="ml-2">
13
+ <AGHeadlessInputLabel v-if="$slots.default">
14
+ <slot />
15
+ </AGHeadlessInputLabel>
16
+ <AGHeadlessInputError class="text-sm text-red-600" />
17
+ </div>
18
+ </AGHeadlessInput>
19
+ </template>
20
+
21
+ <script setup lang="ts">
22
+ import { componentRef, stringProp } from '@/utils/vue';
23
+
24
+ import type { IAGHeadlessInput } from '@/components/headless/forms/AGHeadlessInput';
25
+
26
+ import AGHeadlessInput from '../headless/forms/AGHeadlessInput.vue';
27
+ import AGHeadlessInputError from '../headless/forms/AGHeadlessInputError.vue';
28
+ import AGHeadlessInputInput from '../headless/forms/AGHeadlessInputInput.vue';
29
+ import AGHeadlessInputLabel from '../headless/forms/AGHeadlessInputLabel.vue';
30
+
31
+ defineProps({ name: stringProp() });
32
+ defineOptions({ inheritAttrs: false });
33
+
34
+ const $input = componentRef<IAGHeadlessInput>();
35
+ </script>
@@ -1,24 +1,27 @@
1
1
  <template>
2
2
  <AGHeadlessInput
3
3
  ref="$input"
4
- as="div"
5
- class="flex flex-col items-center"
4
+ class="relative flex flex-col items-center"
5
+ :class="className"
6
6
  :name="name"
7
7
  >
8
8
  <AGHeadlessInputInput
9
- v-bind="$attrs"
9
+ v-bind="attrs"
10
10
  class="block w-full border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600"
11
11
  :class="{
12
12
  'ring-1 ring-red-500': $input?.errors,
13
13
  }"
14
14
  />
15
- <AGHeadlessInputError class="mt-1 text-sm text-red-500" />
15
+ <div class="absolute bottom-0 left-0 translate-y-full">
16
+ <AGHeadlessInputError class="mt-1 text-sm text-red-500" />
17
+ </div>
16
18
  </AGHeadlessInput>
17
19
  </template>
18
20
 
19
21
  <script setup lang="ts">
20
22
  import { componentRef, stringProp } from '@/utils/vue';
21
23
 
24
+ import { useInputAttrs } from '@/utils';
22
25
  import type { IAGHeadlessInput } from '@/components/headless/forms/AGHeadlessInput';
23
26
 
24
27
  import AGHeadlessInput from '../headless/forms/AGHeadlessInput.vue';
@@ -29,4 +32,5 @@ defineProps({ name: stringProp() });
29
32
  defineOptions({ inheritAttrs: false });
30
33
 
31
34
  const $input = componentRef<IAGHeadlessInput>();
35
+ const [attrs, className] = useInputAttrs();
32
36
  </script>
@@ -1,5 +1,6 @@
1
1
  import AGButton from './AGButton.vue';
2
+ import AGCheckbox from './AGCheckbox.vue';
2
3
  import AGForm from './AGForm.vue';
3
4
  import AGInput from './AGInput.vue';
4
5
 
5
- export { AGButton, AGForm, AGInput };
6
+ export { AGButton, AGCheckbox, AGForm, AGInput };
@@ -7,15 +7,14 @@
7
7
  <script setup lang="ts">
8
8
  import { computed } from 'vue';
9
9
  import { objectWithoutEmpty } from '@noeldemartin/utils';
10
- import type { LocationQuery, RouteLocation, RouteParams } from 'vue-router';
11
10
 
12
11
  import { booleanProp, objectProp, stringProp } from '@/utils/vue';
13
12
 
14
13
  const { url, route, routeParams, routeQuery, submit } = defineProps({
15
14
  url: stringProp(),
16
15
  route: stringProp(),
17
- routeParams: objectProp<RouteParams>(() => ({})),
18
- routeQuery: objectProp<LocationQuery>(() => ({})),
16
+ routeParams: objectProp(() => ({})),
17
+ routeQuery: objectProp(() => ({})),
19
18
  submit: booleanProp(),
20
19
  });
21
20
 
@@ -24,7 +23,7 @@ const component = computed(() => {
24
23
  return {
25
24
  tag: 'router-link',
26
25
  props: {
27
- to: objectWithoutEmpty<Partial<RouteLocation>>({
26
+ to: objectWithoutEmpty({
28
27
  name: route,
29
28
  params: routeParams,
30
29
  query: routeQuery,
@@ -2,7 +2,7 @@ import type { ComputedRef, DeepReadonly, Ref } from 'vue';
2
2
 
3
3
  export interface IAGHeadlessInput {
4
4
  id: string;
5
- value: ComputedRef<string | number | null>;
5
+ value: ComputedRef<string | number | boolean | null>;
6
6
  errors: DeepReadonly<Ref<string[] | null>>;
7
- update(value: string | number | null): void;
7
+ update(value: string | number | boolean | null): void;
8
8
  }
@@ -9,16 +9,16 @@
9
9
  import { computed, inject, provide, readonly } from 'vue';
10
10
  import { uuid } from '@noeldemartin/utils';
11
11
 
12
- import { stringProp } from '@/utils/vue';
12
+ import { mixedProp, stringProp } from '@/utils/vue';
13
13
  import type Form from '@/forms/Form';
14
14
 
15
15
  import type { IAGHeadlessInput } from './AGHeadlessInput';
16
16
 
17
17
  const emit = defineEmits(['update:modelValue']);
18
18
  const props = defineProps({
19
- as: stringProp(),
19
+ as: stringProp('div'),
20
20
  name: stringProp(),
21
- modelValue: stringProp(),
21
+ modelValue: mixedProp<string | number | boolean>([String, Number, Boolean]),
22
22
  });
23
23
  const errors = computed(() => {
24
24
  if (!form || !props.name) {
@@ -27,9 +27,9 @@ const errors = computed(() => {
27
27
 
28
28
  return form.errors[props.name] ?? null;
29
29
  });
30
- const form = inject<Form>('form');
30
+ const form = inject<Form | null>('form', null);
31
31
  const publicApi: IAGHeadlessInput = {
32
- id: uuid(),
32
+ id: `input-${uuid()}`,
33
33
  value: computed(() => {
34
34
  if (form && props.name) {
35
35
  return form.getFieldValue(props.name);
@@ -5,18 +5,22 @@
5
5
  </template>
6
6
 
7
7
  <script setup lang="ts">
8
- import { injectReactiveOrFail } from '@/utils';
8
+ import { computed } from 'vue';
9
+
10
+ import { injectReactiveOrFail } from '@/utils/vue';
11
+ import { translateWithDefault } from '@/lang/utils';
9
12
 
10
13
  import type { IAGHeadlessInput } from './AGHeadlessInput';
11
- import { computed } from 'vue';
12
- import { lang } from '@/lang';
13
14
 
14
- const input = injectReactiveOrFail<IAGHeadlessInput>('input');
15
+ const input = injectReactiveOrFail<IAGHeadlessInput>(
16
+ 'input',
17
+ '<AGHeadlessInputError> must be a child of a <AGHeadlessInput>',
18
+ );
15
19
  const errorMessage = computed(() => {
16
20
  if (!input.errors) {
17
21
  return null;
18
22
  }
19
23
 
20
- return lang(`errors.${input.errors[0]}`);
24
+ return translateWithDefault(`errors.${input.errors[0]}`, `Error: ${input.errors[0]}`);
21
25
  });
22
26
  </script>
@@ -1,10 +1,12 @@
1
1
  <template>
2
2
  <input
3
+ :id="input.id"
3
4
  ref="$input"
4
- type="text"
5
+ :type="type"
5
6
  :value="value"
6
7
  :aria-invalid="input.errors ? 'true' : 'false'"
7
8
  :aria-describedby="input.errors ? `${input.id}-error` : undefined"
9
+ :checked="checked"
8
10
  @input="update"
9
11
  >
10
12
  </template>
@@ -12,18 +14,32 @@
12
14
  <script setup lang="ts">
13
15
  import { computed, ref } from 'vue';
14
16
 
15
- import { injectReactiveOrFail } from '@/utils';
17
+ import { injectReactiveOrFail, stringProp } from '@/utils';
16
18
  import type { IAGHeadlessInput } from '@/components/headless/forms/AGHeadlessInput';
17
19
 
20
+ const props = defineProps({
21
+ type: stringProp('text'),
22
+ });
23
+
18
24
  const $input = ref<HTMLInputElement>();
19
- const input = injectReactiveOrFail<IAGHeadlessInput>('input');
25
+ const input = injectReactiveOrFail<IAGHeadlessInput>(
26
+ 'input',
27
+ '<AGHeadlessInputInput> must be a child of a <AGHeadlessInput>',
28
+ );
20
29
  const value = computed(() => input.value);
30
+ const checked = computed(() => {
31
+ if (props.type !== 'checkbox') {
32
+ return;
33
+ }
34
+
35
+ return !!value.value;
36
+ });
21
37
 
22
38
  function update() {
23
39
  if (!$input.value) {
24
40
  return;
25
41
  }
26
42
 
27
- input.update($input.value.value);
43
+ input.update(props.type === 'checkbox' ? $input.value.checked : $input.value.value);
28
44
  }
29
45
  </script>
@@ -0,0 +1,16 @@
1
+ <template>
2
+ <label :for="input.id">
3
+ <slot />
4
+ </label>
5
+ </template>
6
+
7
+ <script setup lang="ts">
8
+ import { injectReactiveOrFail } from '@/utils/vue';
9
+
10
+ import type { IAGHeadlessInput } from './AGHeadlessInput';
11
+
12
+ const input = injectReactiveOrFail<IAGHeadlessInput>(
13
+ 'input',
14
+ '<AGHeadlessInputLabel> must be a child of a <AGHeadlessInput>',
15
+ );
16
+ </script>
@@ -1,4 +1,6 @@
1
- import AGHeadlessButton from './AGHeadlessButton.vue';
2
- import AGHeadlessInput from './AGHeadlessInput.vue';
3
-
4
- export { AGHeadlessButton, AGHeadlessInput };
1
+ export { IAGHeadlessInput } from './AGHeadlessInput';
2
+ export { default as AGHeadlessButton } from './AGHeadlessButton.vue';
3
+ export { default as AGHeadlessInput } from './AGHeadlessInput.vue';
4
+ export { default as AGHeadlessInputError } from './AGHeadlessInputError.vue';
5
+ export { default as AGHeadlessInputInput } from './AGHeadlessInputInput.vue';
6
+ export { default as AGHeadlessInputLabel } from './AGHeadlessInputLabel.vue';
@@ -23,7 +23,11 @@ const props = defineProps({
23
23
  const $root = ref<{ $el?: HTMLElement } | null>(null);
24
24
  const hidden = ref(true);
25
25
  const closed = ref(false);
26
- const { modal } = injectReactiveOrFail<IAGModalContext>('modal');
26
+ const { modal } = injectReactiveOrFail<IAGModalContext>(
27
+ 'modal',
28
+ 'could not obtain modal reference from <AGHeadlessModal>, ' +
29
+ 'did you render this component manually? Show it using $ui.openModal() instead',
30
+ );
27
31
 
28
32
  async function hide(): Promise<void> {
29
33
  if (!$root.value?.$el) {