@aerogel/core 0.0.0-next.7f6ed5a1f91688a86bf5ede2adc465e4fd6cfdea → 0.0.0-next.926bde19326fe7b6b24b277666936862b64d8295
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aerogel-core.cjs.js +1 -1
- package/dist/aerogel-core.d.ts +231 -47
- package/dist/aerogel-core.esm.js +1 -1
- package/package.json +5 -8
- package/src/bootstrap/bootstrap.test.ts +0 -56
- package/src/bootstrap/index.ts +6 -25
- package/src/bootstrap/options.ts +5 -1
- package/src/components/basic/AGMarkdown.vue +20 -5
- package/src/components/forms/AGButton.vue +11 -1
- package/src/components/headless/forms/AGHeadlessInput.vue +2 -2
- package/src/components/headless/forms/AGHeadlessInputError.vue +9 -5
- package/src/components/headless/forms/AGHeadlessInputInput.vue +5 -1
- package/src/components/headless/forms/AGHeadlessInputLabel.vue +16 -0
- package/src/components/headless/forms/index.ts +6 -4
- package/src/components/headless/modals/AGHeadlessModal.vue +5 -1
- package/src/components/headless/modals/AGHeadlessModalPanel.vue +5 -1
- package/src/components/index.ts +2 -1
- package/src/components/modals/AGAlertModal.vue +13 -2
- package/src/components/modals/AGConfirmModal.vue +30 -0
- package/src/components/modals/AGModal.ts +4 -0
- package/src/components/modals/index.ts +3 -1
- package/src/directives/index.ts +5 -3
- package/src/forms/Form.test.ts +21 -0
- package/src/forms/Form.ts +26 -7
- package/src/globals.ts +6 -0
- package/src/lang/Lang.ts +38 -7
- package/src/lang/index.ts +18 -75
- package/src/main.ts +3 -0
- package/src/plugins/Plugin.ts +7 -0
- package/src/plugins/index.ts +7 -0
- package/src/services/App.state.ts +10 -0
- package/src/services/App.ts +7 -0
- package/src/services/Service.ts +50 -9
- package/src/services/index.ts +13 -5
- package/src/types/vite.d.ts +0 -2
- package/src/ui/UI.state.ts +2 -6
- package/src/ui/UI.ts +20 -2
- package/src/ui/index.ts +15 -11
- package/src/utils/composition/hooks.ts +9 -0
- package/src/utils/index.ts +2 -0
- package/tsconfig.json +1 -10
- package/vite.config.ts +2 -6
- package/src/bootstrap/hooks.ts +0 -19
- package/src/lang/helpers.ts +0 -5
- package/src/models/index.ts +0 -18
- package/src/routing/index.ts +0 -33
- package/src/testing/stubs/lang/en.yaml +0 -1
- package/src/testing/stubs/models/User.ts +0 -3
package/dist/aerogel-core.esm.js
CHANGED
|
@@ -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,computed as a,markRaw as r,nextTick as o,onUnmounted as n,defineComponent as l,toRef as i,openBlock as u,createBlock as d,unref as c,withCtx as m,renderSlot as p,provide as f,resolveDynamicComponent as h,normalizeProps as v,guardReactiveProps as _,createCommentVNode as g,createElementVNode as b,createVNode as y,h as A,onMounted as x,normalizeClass as G,createTextVNode as w,toDisplayString as j,createApp as C,createElementBlock as M,Fragment as I,withModifiers as S,readonly as k,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 H,JSError as O,MagicObject as E,PromisedValue as P,facade as q,arr as D,tap as L,uuid as B,noop as F,objectWithoutEmpty as V}from"@noeldemartin/utils";import N from"@babel/runtime/helpers/esm/defineProperty";import"core-js/modules/esnext.async-iterator.reduce.js";import"core-js/modules/esnext.iterator.reduce.js";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 T,DialogPanel as K,DialogTitle as z}from"@headlessui/vue";import Q from"dompurify";import{marked as W}from"marked";import"core-js/modules/esnext.async-iterator.some.js";import"core-js/modules/esnext.iterator.some.js";function R(e){return e}function U(e){return{type:Array,default:e??(()=>[])}}function J(){return{type:Boolean,default:arguments.length>0&&void 0!==arguments[0]&&arguments[0]}}function X(){return e()}function Y(e){return e}function Z(e,t){const s=Object.values(e);return{type:String,default:t??s[0]??null,validator:e=>s.includes(e)}}function ee(e){const a=t(e);return a?s(a):void 0}function te(e,t){return ee(e)??H(t??`Could not resolve '${e}' injection key`)}function se(e,s){return t(e)??H(s??`Could not resolve '${e}' injection key`)}function ae(e){return{type:e,default:null}}function re(){return{type:Number,default:arguments.length>0&&void 0!==arguments[0]?arguments[0]:null}}function oe(){return{type:Object,default:arguments.length>0&&void 0!==arguments[0]?arguments[0]:null}}function ne(){return{type:Array,required:!0}}function le(e){const t=Object.values(e);return{type:String,required:!0,validator:e=>t.includes(e)}}function ie(e){return{type:e,required:!0}}function ue(){return{type:Number,required:!0}}function de(){return{type:Object,required:!0}}function ce(){return{type:String,required:!0}}function me(){return{type:String,default:arguments.length>0&&void 0!==arguments[0]?arguments[0]:null}}const pe={"initial-focus":{mounted(e,t){let{value:s}=t;!1!==s&&e.focus()}}};var fe={install(e){Object.entries(pe).forEach((t=>{let[s,a]=t;return e.directive(s,a)}))}};class ServiceBootError extends O{constructor(e,t){super(`Service '${e}' failed booting`,{cause:t})}}function he(e){return class extends ve{getInitialState(){return e.initialState}getComputedStateDefinition(){return e.computed??{}}}}class ve extends E{constructor(){super(),N(this,"_namespace",void 0),N(this,"_booted",void 0),N(this,"_state",void 0),N(this,"_computedState",void 0),this._namespace=new.target.name,this._booted=new P,this._state=s(this.getInitialState()),this._computedState=Object.entries(this.getComputedStateDefinition()).reduce(((e,t)=>{let[s,r]=t;return e[s]=a((()=>r(this._state))),e}),{})}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):this.hasComputedState(e)?this.getComputedState(e):super.__get(e)}__set(e,t){this.setState({[e]:t})}hasState(e){return e in this._state}hasComputedState(e){return e in this._computedState}getState(e){return e?this._state[e]:this._state}getComputedState(e){return this._computedState[e]?.value}setState(e){Object.assign(this._state,e)}getInitialState(){return{}}getComputedStateDefinition(){return{}}async boot(){}}var _e=he({initialState:{environment:__AG_ENV},computed:{isDevelopment:e=>"development"===e.environment}});class ge extends _e{}var be=q(new ge);class ye extends ve{constructor(){super(...arguments),N(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]??=D([])).push(t),()=>this.off(e,t)}once(e,t){let s=null;return L((()=>s&&this.off(e,s)),(a=>{(this.listeners[e]??=D([])).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 Ae=q(new ye);const xe={$app:be,$events:Ae};async function Ge(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 we={async install(e){await Ge(e,xe)}};var je=q(new class extends ve{constructor(){super(),N(this,"provider",void 0),this.provider={translate:e=>(be.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 a="string"==typeof t?{}:t,r=this.provider.translate(e,a)??e;return r===e?s:r}});const Ce={$lang:je},Me=je.translate.bind(je),Ie=je.translateWithDefault.bind(je);var Se={async install(e){e.config.globalProperties.$t??=Me,e.config.globalProperties.$td=Ie,await Ge(e,Ce)}},ke=he({initialState:{modals:[]}});const $e={AlertModal:"alert-modal",ConfirmModal:"confirm-modal"};var He=q(new class extends ke{constructor(){super(...arguments),N(this,"modalCallbacks",{}),N(this,"components",{})}alert(e,t){const s="string"==typeof t?{title:e,message:t}:{message:e};this.openModal(this.requireComponent($e.AlertModal),s)}async confirm(e,t){const s="string"==typeof t?{title:e,message:t}:{message:e},a=await this.openModal(this.requireComponent($e.ConfirmModal),s);return await a.beforeClose??!1}registerComponent(e,t){this.components[e]=t}async openModal(e,t){const s=B(),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&&Ae.emit("hide-modal",{id:l.id})),await Promise.all([l||Ae.emit("show-overlays-backdrop"),Ae.emit("show-modal",{id:n.id})]),n}async closeModal(e,t){await Ae.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(){Ae.on("modal-will-close",(e=>{let{modal:t,result:s}=e;this.modalCallbacks[t.id]?.willClose?.(s),1===this.modals.length&&Ae.emit("hide-overlays-backdrop")})),Ae.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&&Ae.emit("show-modal",{id:a.id}))}))}});function Oe(e,t){const s=Ae.on(e,t);n((()=>s()))}var Ee=l({__name:"AGHeadlessModal",props:{cancellable:J(!0)},setup(t,{expose:s}){const a=t,r=e(null),o=e(!0),n=e(!1),{modal:l}=te("modal","could not obtain modal reference from <AGHeadlessModal>, did you render this component manually? Show it using $ui.openModal() instead");async function f(){r.value?.$el&&(o.value=!0)}async function h(e){n.value||(Ae.emit("modal-will-close",{modal:l,result:e}),await f(),n.value=!0,Ae.emit("modal-closed",{modal:l,result:e}))}return Oe("close-modal",(async({id:e,result:t})=>{e===l.id&&await h(t)})),Oe("hide-modal",(async({id:e})=>{e===l.id&&await f()})),Oe("show-modal",(async({id:e})=>{e===l.id&&await async function(){r.value?.$el&&(o.value=!1)}()})),s({close:h,cancellable:i(a,"cancellable")}),(e,s)=>(u(),d(c(T),{ref_key:"$root",ref:r,open:!0,onClose:s[0]||(s[0]=e=>t.cancellable&&h())},{default:m((()=>[p(e.$slots,"default",{close:h})])),_:3},512))}});Ee.__file="src/components/headless/modals/AGHeadlessModal.vue";var Pe=l({__name:"AGModalContext",props:{modal:de(),childIndex:ue()},setup(e){const t=e;return f("modal",{modal:i(t,"modal"),childIndex:i(t,"childIndex")}),(t,s)=>(u(),d(h(e.modal.component),v(_(e.modal.properties)),null,16))}});Pe.__file="src/components/modals/AGModalContext.vue";var qe=l({__name:"AGHeadlessModalPanel",setup(e){const t=te("modal","could not obtain modal reference from <AGHeadlessModalPanel>, did you render this component manually? Show it using $ui.openModal() instead"),s=a((()=>He.modals[t.childIndex]??null));return(e,a)=>(u(),d(c(K),null,{default:m((()=>[p(e.$slots,"default"),s.value?(u(),d(Pe,{key:0,"child-index":c(t).childIndex+1,modal:s.value},null,8,["child-index","modal"])):g("v-if",!0)])),_:3}))}});qe.__file="src/components/headless/modals/AGHeadlessModalPanel.vue";const De={class:"fixed inset-0 flex items-center justify-center"},Le={class:"flex max-h-full flex-col overflow-auto p-4"};var Be=l({__name:"AGModal",setup:e=>(e,t)=>(u(),d(Ee,{class:"relative z-50"},{default:m((({close:t})=>[b("div",De,[y(qe,{class:"flex max-h-full max-w-full flex-col overflow-hidden bg-white"},{default:m((()=>[b("div",Le,[p(e.$slots,"default",{close:t})])])),_:2},1024)])])),_:3}))});function Fe(e){return t=W(e,{mangle:!1,headerIds:!1}),Q.sanitize(t,{ADD_ATTR:["target"]});var t}Be.__file="src/components/modals/AGModal.vue";var Ve=l({__name:"AGMarkdown",props:{as:me("div"),langKey:me(),text:me(),inline:J(),raw:J()},setup(e){const t=e,s=a((()=>t.text??(t.langKey&&Me(t.langKey)))),r=a((()=>{if(!s.value)return null;let e=Fe(s.value);return t.inline&&(e=e.replace("<p>","<span>").replace("</p>","</span>")),e})),o=()=>A(t.as,{class:t.raw?"":"prose",innerHTML:r.value});return(e,t)=>(u(),d(o))}});Ve.__file="src/components/basic/AGMarkdown.vue";var Ne=l({__name:"AGAlertModal",props:{title:me(),message:ce()},setup:e=>(t,s)=>(u(),d(Be,null,{default:m((()=>[e.title?(u(),d(Ve,{key:0,text:e.title,as:"h2",class:"font-semibold",raw:"",inline:""},null,8,["text"])):g("v-if",!0),y(Ve,{text:e.message},null,8,["text"])])),_:1}))});function Te(e){let t=F;x((()=>t=e())),n((()=>t()))}Ne.__file="src/components/modals/AGAlertModal.vue";var Ke=l({__name:"AGHeadlessButton",props:{url:me(),route:me(),routeParams:oe((()=>({}))),routeQuery:oe((()=>({}))),submit:J()},setup(e){const{url:t,route:s,routeParams:r,routeQuery:o,submit:n}=e,l=a((()=>s?{tag:"router-link",props:{to:V({name:s,params:r,query:o})}}:t?{tag:"a",props:{target:"_blank",href:t}}:{tag:"button",props:{type:n?"submit":"button"}}));return(e,t)=>(u(),d(h(l.value.tag),v(_(l.value.props)),{default:m((()=>[p(e.$slots,"default")])),_:3},16))}});Ke.__file="src/components/headless/forms/AGHeadlessButton.vue";var ze=l({__name:"AGButton",props:{secondary:J()},setup:e=>(t,s)=>(u(),d(Ke,{class:G(["px-2.5 py-1.5 text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2",{"bg-indigo-600 hover:bg-indigo-500 focus-visible:outline-indigo-600":!e.secondary,"bg-gray-600 hover:bg-gray-500 focus-visible:outline-gray-600":e.secondary}])},{default:m((()=>[p(t.$slots,"default")])),_:3},8,["class"]))});ze.__file="src/components/forms/AGButton.vue";const Qe={class:"mt-2 flex flex-row-reverse gap-2"};var We=l({__name:"AGConfirmModal",props:{title:me(),message:ce()},setup:e=>(t,s)=>(u(),d(Be,{cancellable:!1},{default:m((({close:s})=>[e.title?(u(),d(Ve,{key:0,text:e.title,as:"h1"},null,8,["text"])):g("v-if",!0),y(Ve,{text:e.message},null,8,["text"]),b("div",Qe,[y(ze,{onClick:e=>s(!0)},{default:m((()=>[w(j(t.$td("ui.ok","OK")),1)])),_:2},1032,["onClick"]),y(ze,{secondary:"",onClick:e=>s()},{default:m((()=>[w(j(t.$td("ui.cancel","Cancel")),1)])),_:2},1032,["onClick"])])])),_:1}))});We.__file="src/components/modals/AGConfirmModal.vue";const Re={$ui:He};var Ue={async install(e,t){const s={[$e.AlertModal]:Ne,[$e.ConfirmModal]:We};Object.entries({...s,...t.components}).forEach((e=>{let[t,s]=e;return He.registerComponent(t,s)})),await Ge(e,Re)}};async function Je(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const s=[fe,Se,we,Ue,...t.plugins??[]],a=C(e);await Promise.all(s.map((e=>e.install(a,t)))??[]),a.mount("#app")}const Xe={key:0};var Ye=l({__name:"AGAppOverlays",setup(t){const s=e(null),r=e(!0),o=a((()=>He.modals[0]??null));return Oe("show-overlays-backdrop",(async()=>{s.value&&r.value&&(r.value=!1,s.value.classList.remove("opacity-0"))})),Oe("hide-overlays-backdrop",(async()=>{s.value&&!r.value&&(r.value=!0,s.value.classList.add("opacity-0"))})),(e,t)=>(u(),M(I,null,[b("div",{ref_key:"$backdrop",ref:s,class:"pointer-events-none fixed inset-0 z-50 bg-black/30 opacity-0"},null,512),o.value?(u(),M("aside",Xe,[y(Pe,{"child-index":1,modal:o.value},null,8,["modal"])])):g("v-if",!0)],64))}});Ye.__file="src/components/AGAppOverlays.vue";const Ze={class:"flex h-full flex-col text-base font-normal leading-tight text-gray-900 antialiased"};var et=l({__name:"AGAppLayout",setup:e=>(e,t)=>(u(),M("div",Ze,[p(e.$slots,"default"),y(Ye)]))});et.__file="src/components/AGAppLayout.vue";const tt=["onSubmit"];var st=l({__name:"AGForm",props:{form:oe()},emits:["submit"],setup(e,{emit:t}){const s=e;function a(){s.form&&!s.form.submit()||t("submit")}return f("form",s.form),(e,t)=>(u(),M("form",{onSubmit:S(a,["prevent"])},[p(e.$slots,"default")],40,tt))}});st.__file="src/components/forms/AGForm.vue";var at=l({__name:"AGHeadlessInput",props:{as:me(),name:me(),modelValue:me()},emits:["update:modelValue"],setup(e,{expose:s,emit:r}){const o=e,n=a((()=>l&&o.name?l.errors[o.name]??null:null)),l=t("form",null),i={id:`input-${B()}`,value:a((()=>l&&o.name?l.getFieldValue(o.name):o.modelValue)),errors:k(n),update(e){l&&o.name?l.setFieldValue(o.name,e):r("update:modelValue",e)}};return f("input",i),s(i),(t,s)=>e.as?(u(),d(h(e.as),{key:0},{default:m((()=>[p(t.$slots,"default")])),_:3})):p(t.$slots,"default",{key:1})}});at.__file="src/components/headless/forms/AGHeadlessInput.vue";const rt=["id","value","aria-invalid","aria-describedby"];var ot=l({__name:"AGHeadlessInputInput",setup(t){const s=e(),r=te("input","<AGHeadlessInputInput> must be a child of a <AGHeadlessInput>"),o=a((()=>r.value));function n(){s.value&&r.update(s.value.value)}return(e,t)=>(u(),M("input",{id:c(r).id,ref_key:"$input",ref:s,type:"text",value:o.value,"aria-invalid":c(r).errors?"true":"false","aria-describedby":c(r).errors?`${c(r).id}-error`:void 0,onInput:n},null,40,rt))}});ot.__file="src/components/headless/forms/AGHeadlessInputInput.vue";const nt=["id"];var lt=l({__name:"AGHeadlessInputError",setup(e){const t=te("input","<AGHeadlessInputError> must be a child of a <AGHeadlessInput>"),s=a((()=>t.errors?Ie(`errors.${t.errors[0]}`,`Error: ${t.errors[0]}`):null));return(e,a)=>s.value?(u(),M("p",{key:0,id:`${c(t).id}-error`},j(s.value),9,nt)):g("v-if",!0)}});lt.__file="src/components/headless/forms/AGHeadlessInputError.vue";var it=l({inheritAttrs:!1,__name:"AGInput",props:{name:me()},setup(e){const t=X();return(s,a)=>(u(),d(at,{ref_key:"$input",ref:t,as:"div",class:"flex flex-col items-center",name:e.name},{default:m((()=>[y(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":c(t)?.errors}]}),null,16,["class"]),y(lt,{class:"mt-1 text-sm text-red-500"})])),_:1},8,["name"]))}});it.__file="src/components/forms/AGInput.vue";const ut=["for"];var dt=l({__name:"AGHeadlessInputLabel",setup(e){const t=te("input","<AGHeadlessInputLabel> must be a child of a <AGHeadlessInput>");return(e,s)=>(u(),M("label",{for:c(t).id},[p(e.$slots,"default")],8,ut))}});dt.__file="src/components/headless/forms/AGHeadlessInputLabel.vue";var ct=l({__name:"AGHeadlessModalTitle",props:{as:me("h2")},setup:e=>(t,s)=>(u(),d(c(z),{as:e.as},{default:m((()=>[p(t.$slots,"default")])),_:3},8,["as"]))});ct.__file="src/components/headless/modals/AGHeadlessModalTitle.vue";const mt={String:"string",Number:"number"};class pt extends E{constructor(t){super(),N(this,"errors",void 0),N(this,"_fields",void 0),N(this,"_data",void 0),N(this,"_valid",void 0),N(this,"_submitted",void 0),N(this,"_errors",void 0),this._fields=t,this._submitted=e(!1),this._data=this.getInitialData(t),this._errors=this.getInitialErrors(t),this._valid=a((()=>!Object.values(this._errors).some((e=>null!==e)))),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 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,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)}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 ft(e){return new pt(e)}function ht(e){return{default:e,type:mt.Number,rules:"required"}}function vt(e){return{default:e,type:mt.String,rules:"required"}}function _t(e){return{default:e,type:mt.Number}}function gt(e){return{default:e,type:mt.String}}export{Ne as AGAlertModal,et as AGAppLayout,Ye as AGAppOverlays,ze as AGButton,We as AGConfirmModal,st as AGForm,Ke as AGHeadlessButton,at as AGHeadlessInput,lt as AGHeadlessInputError,ot as AGHeadlessInputInput,dt as AGHeadlessInputLabel,Ee as AGHeadlessModal,qe as AGHeadlessModalPanel,ct as AGHeadlessModalTitle,it as AGInput,Ve as AGMarkdown,Be as AGModal,Pe as AGModalContext,be as App,ge as AppService,Ae as Events,ye as EventsService,mt as FormFieldTypes,je as Lang,ve as Service,He as UI,$e as UIComponents,U as arrayProp,J as booleanProp,Ge as bootServices,Je as bootstrapApplication,X as componentRef,Y as defineDirective,R as definePlugin,he as defineServiceState,Z as enumProp,se as injectOrFail,ee as injectReactive,te as injectReactiveOrFail,ae as mixedProp,_t as numberInput,re as numberProp,oe as objectProp,Te as onCleanMounted,ne as requiredArrayProp,le as requiredEnumProp,ie as requiredMixedProp,ht as requiredNumberInput,ue as requiredNumberProp,de as requiredObjectProp,vt as requiredStringInput,ce as requiredStringProp,gt as stringInput,me as stringProp,Me as translate,Ie as translateWithDefault,Oe as useEvent,ft as useForm};
|
|
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.
|
|
4
|
+
"version": "0.0.0-next.926bde19326fe7b6b24b277666936862b64d8295",
|
|
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,14 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@headlessui/vue": "^1.7.14",
|
|
36
|
-
"@noeldemartin/utils": "0.4.0-next.
|
|
36
|
+
"@noeldemartin/utils": "0.4.0-next.ac00beaecf32bb02ed8e335225d7948d946d73bd",
|
|
37
37
|
"dompurify": "^3.0.3",
|
|
38
38
|
"marked": "^5.0.4",
|
|
39
|
-
"
|
|
40
|
-
"vue": "^3.3.0",
|
|
41
|
-
"vue-i18n": "9.3.0-beta.19",
|
|
42
|
-
"vue-router": "^4.2.1"
|
|
39
|
+
"vue": "^3.3.0"
|
|
43
40
|
},
|
|
44
41
|
"devDependencies": {
|
|
42
|
+
"@aerogel/vite": "*",
|
|
45
43
|
"@types/dompurify": "^3.0.2",
|
|
46
|
-
"@types/marked": "^5.0.0"
|
|
47
|
-
"@vitejs/plugin-vue": "^4.2.3"
|
|
44
|
+
"@types/marked": "^5.0.0"
|
|
48
45
|
}
|
|
49
46
|
}
|
|
@@ -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>();
|
package/src/bootstrap/index.ts
CHANGED
|
@@ -1,36 +1,17 @@
|
|
|
1
|
-
import { createApp
|
|
1
|
+
import { createApp } from 'vue';
|
|
2
2
|
import type { Component } from 'vue';
|
|
3
3
|
|
|
4
4
|
import directives from '@/directives';
|
|
5
5
|
import lang from '@/lang';
|
|
6
|
-
import models from '@/models';
|
|
7
|
-
import routing from '@/routing';
|
|
8
6
|
import services from '@/services';
|
|
9
7
|
import ui from '@/ui';
|
|
10
|
-
import {
|
|
11
|
-
import type { BootstrapOptions } from '@/bootstrap/options';
|
|
8
|
+
import type { AerogelOptions } from '@/bootstrap/options';
|
|
12
9
|
|
|
13
|
-
export async function bootstrapApplication(rootComponent: Component, options:
|
|
14
|
-
const
|
|
15
|
-
const app = createApp(
|
|
16
|
-
data: () => ({
|
|
17
|
-
ready: false,
|
|
18
|
-
}),
|
|
19
|
-
mounted() {
|
|
20
|
-
runAppMountedHooks();
|
|
10
|
+
export async function bootstrapApplication(rootComponent: Component, options: AerogelOptions = {}): Promise<void> {
|
|
11
|
+
const plugins = [directives, lang, services, ui, ...(options.plugins ?? [])];
|
|
12
|
+
const app = createApp(rootComponent);
|
|
21
13
|
|
|
22
|
-
|
|
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)));
|
|
14
|
+
await Promise.all(plugins.map((plugin) => plugin.install(app, options)) ?? []);
|
|
34
15
|
|
|
35
16
|
app.mount('#app');
|
|
36
17
|
}
|
package/src/bootstrap/options.ts
CHANGED
|
@@ -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 {
|
|
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 &&
|
|
18
|
-
const html = computed(() =>
|
|
19
|
-
|
|
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 html = renderMarkdown(markdown.value);
|
|
27
|
+
|
|
28
|
+
if (props.inline) {
|
|
29
|
+
html = html.replace('<p>', '<span>').replace('</p>', '</span>');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return html;
|
|
33
|
+
});
|
|
34
|
+
const root = () => h(props.as, { class: props.raw ? '' : 'prose', innerHTML: html.value });
|
|
20
35
|
</script>
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<AGHeadlessButton
|
|
3
|
-
class="
|
|
3
|
+
class="px-2.5 py-1.5 text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2"
|
|
4
|
+
:class="{
|
|
5
|
+
'bg-indigo-600 hover:bg-indigo-500 focus-visible:outline-indigo-600': !secondary,
|
|
6
|
+
'bg-gray-600 hover:bg-gray-500 focus-visible:outline-gray-600': secondary,
|
|
7
|
+
}"
|
|
4
8
|
>
|
|
5
9
|
<slot />
|
|
6
10
|
</AGHeadlessButton>
|
|
7
11
|
</template>
|
|
8
12
|
|
|
9
13
|
<script setup lang="ts">
|
|
14
|
+
import { booleanProp } from '@/utils';
|
|
15
|
+
|
|
10
16
|
import AGHeadlessButton from '../headless/forms/AGHeadlessButton.vue';
|
|
17
|
+
|
|
18
|
+
defineProps({
|
|
19
|
+
secondary: booleanProp(),
|
|
20
|
+
});
|
|
11
21
|
</script>
|
|
@@ -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 {
|
|
8
|
+
import { computed } from 'vue';
|
|
9
|
+
|
|
10
|
+
import { injectReactiveOrFail } from '@/utils/vue';
|
|
11
|
+
import { translateWithDefault } from '@/lang';
|
|
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>(
|
|
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
|
|
24
|
+
return translateWithDefault(`errors.${input.errors[0]}`, `Error: ${input.errors[0]}`);
|
|
21
25
|
});
|
|
22
26
|
</script>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<input
|
|
3
|
+
:id="input.id"
|
|
3
4
|
ref="$input"
|
|
4
5
|
type="text"
|
|
5
6
|
:value="value"
|
|
@@ -16,7 +17,10 @@ import { injectReactiveOrFail } from '@/utils';
|
|
|
16
17
|
import type { IAGHeadlessInput } from '@/components/headless/forms/AGHeadlessInput';
|
|
17
18
|
|
|
18
19
|
const $input = ref<HTMLInputElement>();
|
|
19
|
-
const input = injectReactiveOrFail<IAGHeadlessInput>(
|
|
20
|
+
const input = injectReactiveOrFail<IAGHeadlessInput>(
|
|
21
|
+
'input',
|
|
22
|
+
'<AGHeadlessInputInput> must be a child of a <AGHeadlessInput>',
|
|
23
|
+
);
|
|
20
24
|
const value = computed(() => input.value);
|
|
21
25
|
|
|
22
26
|
function update() {
|
|
@@ -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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export {
|
|
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>(
|
|
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) {
|
|
@@ -15,6 +15,10 @@ import type { IAGModalContext } from '@/components/modals/AGModalContext';
|
|
|
15
15
|
|
|
16
16
|
import AGModalContext from '../../modals/AGModalContext.vue';
|
|
17
17
|
|
|
18
|
-
const modal = injectReactiveOrFail<IAGModalContext>(
|
|
18
|
+
const modal = injectReactiveOrFail<IAGModalContext>(
|
|
19
|
+
'modal',
|
|
20
|
+
'could not obtain modal reference from <AGHeadlessModalPanel>, ' +
|
|
21
|
+
'did you render this component manually? Show it using $ui.openModal() instead',
|
|
22
|
+
);
|
|
19
23
|
const childModal = computed(() => UI.modals[modal.childIndex] ?? null);
|
|
20
24
|
</script>
|
package/src/components/index.ts
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<AGModal>
|
|
3
|
+
<AGMarkdown
|
|
4
|
+
v-if="title"
|
|
5
|
+
:text="title"
|
|
6
|
+
as="h2"
|
|
7
|
+
class="font-semibold"
|
|
8
|
+
raw
|
|
9
|
+
inline
|
|
10
|
+
/>
|
|
3
11
|
<AGMarkdown :text="message" />
|
|
4
12
|
</AGModal>
|
|
5
13
|
</template>
|
|
6
14
|
|
|
7
15
|
<script setup lang="ts">
|
|
8
|
-
import { requiredStringProp } from '@/utils/vue';
|
|
16
|
+
import { requiredStringProp, stringProp } from '@/utils/vue';
|
|
9
17
|
|
|
10
18
|
import AGModal from './AGModal.vue';
|
|
11
19
|
|
|
12
20
|
import AGMarkdown from '../basic/AGMarkdown.vue';
|
|
13
21
|
|
|
14
|
-
defineProps({
|
|
22
|
+
defineProps({
|
|
23
|
+
title: stringProp(),
|
|
24
|
+
message: requiredStringProp(),
|
|
25
|
+
});
|
|
15
26
|
</script>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<AGModal v-slot="{ close }: IAGModalDefaultSlotProps" :cancellable="false">
|
|
3
|
+
<AGMarkdown v-if="title" :text="title" as="h1" />
|
|
4
|
+
<AGMarkdown :text="message" />
|
|
5
|
+
|
|
6
|
+
<div class="mt-2 flex flex-row-reverse gap-2">
|
|
7
|
+
<AGButton @click="close(true)">
|
|
8
|
+
{{ $td('ui.ok', 'OK') }}
|
|
9
|
+
</AGButton>
|
|
10
|
+
<AGButton secondary @click="close()">
|
|
11
|
+
{{ $td('ui.cancel', 'Cancel') }}
|
|
12
|
+
</AGButton>
|
|
13
|
+
</div>
|
|
14
|
+
</AGModal>
|
|
15
|
+
</template>
|
|
16
|
+
|
|
17
|
+
<script setup lang="ts">
|
|
18
|
+
import { requiredStringProp, stringProp } from '@/utils/vue';
|
|
19
|
+
|
|
20
|
+
import AGModal from './AGModal.vue';
|
|
21
|
+
import type { IAGModalDefaultSlotProps } from './AGModal';
|
|
22
|
+
|
|
23
|
+
import AGButton from '../forms/AGButton.vue';
|
|
24
|
+
import AGMarkdown from '../basic/AGMarkdown.vue';
|
|
25
|
+
|
|
26
|
+
defineProps({
|
|
27
|
+
title: stringProp(),
|
|
28
|
+
message: requiredStringProp(),
|
|
29
|
+
});
|
|
30
|
+
</script>
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import AGAlertModal from './AGAlertModal.vue';
|
|
2
|
+
import AGConfirmModal from './AGConfirmModal.vue';
|
|
1
3
|
import AGModal from './AGModal.vue';
|
|
2
4
|
import AGModalContext from './AGModalContext.vue';
|
|
3
5
|
import { IAGModal } from './AGModal';
|
|
4
6
|
|
|
5
|
-
export { AGModal, AGModalContext, IAGModal };
|
|
7
|
+
export { AGAlertModal, AGConfirmModal, AGModal, AGModalContext, IAGModal };
|
package/src/directives/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Directive } from 'vue';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { definePlugin } from '@/plugins';
|
|
4
4
|
|
|
5
5
|
import initialFocus from './initial-focus';
|
|
6
6
|
|
|
@@ -8,6 +8,8 @@ const directives: Record<string, Directive> = {
|
|
|
8
8
|
'initial-focus': initialFocus,
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
export default
|
|
12
|
-
|
|
11
|
+
export default definePlugin({
|
|
12
|
+
install(app) {
|
|
13
|
+
Object.entries(directives).forEach(([name, directive]) => app.directive(name, directive));
|
|
14
|
+
},
|
|
13
15
|
});
|
package/src/forms/Form.test.ts
CHANGED
|
@@ -34,4 +34,25 @@ describe('Form', () => {
|
|
|
34
34
|
expect(form.errors.name).toEqual(['required']);
|
|
35
35
|
});
|
|
36
36
|
|
|
37
|
+
it('resets form', () => {
|
|
38
|
+
// Arrange
|
|
39
|
+
const form = useForm({
|
|
40
|
+
name: {
|
|
41
|
+
type: FormFieldTypes.String,
|
|
42
|
+
rules: 'required',
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
form.name = 'Foo bar';
|
|
47
|
+
form.submit();
|
|
48
|
+
|
|
49
|
+
// Act
|
|
50
|
+
form.reset();
|
|
51
|
+
|
|
52
|
+
// Assert
|
|
53
|
+
expect(form.valid).toBe(true);
|
|
54
|
+
expect(form.submitted).toBe(false);
|
|
55
|
+
expect(form.name).toBeNull();
|
|
56
|
+
});
|
|
57
|
+
|
|
37
58
|
});
|
package/src/forms/Form.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { MagicObject } from '@noeldemartin/utils';
|
|
2
|
-
import { reactive, readonly, ref } from 'vue';
|
|
2
|
+
import { computed, reactive, readonly, ref } from 'vue';
|
|
3
3
|
import type { ObjectValues } from '@noeldemartin/utils';
|
|
4
|
-
import type { DeepReadonly, Ref, UnwrapNestedRefs } from 'vue';
|
|
4
|
+
import type { ComputedRef, DeepReadonly, Ref, UnwrapNestedRefs } from 'vue';
|
|
5
5
|
|
|
6
6
|
export const FormFieldTypes = {
|
|
7
7
|
String: 'string',
|
|
@@ -18,7 +18,7 @@ export type FormFieldDefinitions = Record<string, FormFieldDefinition>;
|
|
|
18
18
|
export type FormFieldType = ObjectValues<typeof FormFieldTypes>;
|
|
19
19
|
|
|
20
20
|
export type FormData<T> = {
|
|
21
|
-
[k in keyof T]: T[k] extends FormFieldDefinition<infer TType, infer TRules>
|
|
21
|
+
-readonly [k in keyof T]: T[k] extends FormFieldDefinition<infer TType, infer TRules>
|
|
22
22
|
? TRules extends 'required'
|
|
23
23
|
? GetFormFieldValue<TType>
|
|
24
24
|
: GetFormFieldValue<TType> | null
|
|
@@ -41,7 +41,7 @@ export default class Form<Fields extends FormFieldDefinitions = FormFieldDefinit
|
|
|
41
41
|
|
|
42
42
|
private _fields: Fields;
|
|
43
43
|
private _data: FormData<Fields>;
|
|
44
|
-
private _valid:
|
|
44
|
+
private _valid: ComputedRef<boolean>;
|
|
45
45
|
private _submitted: Ref<boolean>;
|
|
46
46
|
private _errors: FormErrors<Fields>;
|
|
47
47
|
|
|
@@ -50,9 +50,9 @@ export default class Form<Fields extends FormFieldDefinitions = FormFieldDefinit
|
|
|
50
50
|
|
|
51
51
|
this._fields = fields;
|
|
52
52
|
this._submitted = ref(false);
|
|
53
|
-
this._valid = ref(true);
|
|
54
53
|
this._data = this.getInitialData(fields);
|
|
55
54
|
this._errors = this.getInitialErrors(fields);
|
|
55
|
+
this._valid = computed(() => !Object.values(this._errors).some((error) => error !== null));
|
|
56
56
|
|
|
57
57
|
this.errors = readonly(this._errors);
|
|
58
58
|
}
|
|
@@ -84,9 +84,16 @@ export default class Form<Fields extends FormFieldDefinitions = FormFieldDefinit
|
|
|
84
84
|
return errors;
|
|
85
85
|
}, {} as Record<string, string[] | null>);
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
this.resetErrors(errors);
|
|
88
88
|
|
|
89
|
-
return
|
|
89
|
+
return this.valid;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
public reset(): void {
|
|
93
|
+
this._submitted.value = false;
|
|
94
|
+
|
|
95
|
+
this.resetData();
|
|
96
|
+
this.resetErrors();
|
|
90
97
|
}
|
|
91
98
|
|
|
92
99
|
public submit(): boolean {
|
|
@@ -151,4 +158,16 @@ export default class Form<Fields extends FormFieldDefinitions = FormFieldDefinit
|
|
|
151
158
|
return reactive(errors) as FormErrors<Fields>;
|
|
152
159
|
}
|
|
153
160
|
|
|
161
|
+
private resetData(): void {
|
|
162
|
+
for (const [name, field] of Object.entries(this._fields)) {
|
|
163
|
+
this._data[name as keyof Fields] = (field.default ?? null) as FormData<Fields>[keyof Fields];
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
private resetErrors(errors?: Record<string, string[] | null>): void {
|
|
168
|
+
Object.keys(this._errors).forEach((key) => delete this._errors[key as keyof Fields]);
|
|
169
|
+
|
|
170
|
+
errors && Object.assign(this._errors, errors);
|
|
171
|
+
}
|
|
172
|
+
|
|
154
173
|
}
|