@je-es/client 0.1.4 → 0.1.6
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/README.md +1 -1
- package/dist/main.cjs +35 -15
- package/dist/main.cjs.map +1 -1
- package/dist/main.d.cts +5 -0
- package/dist/main.d.ts +5 -0
- package/dist/main.js +35 -15
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
package/dist/main.d.cts
CHANGED
|
@@ -105,6 +105,7 @@ interface FormFieldOption {
|
|
|
105
105
|
interface FormFieldConfig {
|
|
106
106
|
name: string;
|
|
107
107
|
label?: string;
|
|
108
|
+
icon?: string;
|
|
108
109
|
type?: string;
|
|
109
110
|
placeholder?: string;
|
|
110
111
|
value?: unknown;
|
|
@@ -562,6 +563,10 @@ declare class SmartFormComponent extends Component<FormConfig> {
|
|
|
562
563
|
* Handle form submission
|
|
563
564
|
*/
|
|
564
565
|
handleSubmit(event: Event): Promise<void>;
|
|
566
|
+
/**
|
|
567
|
+
* Render label with optional icon
|
|
568
|
+
*/
|
|
569
|
+
renderLabel(field: FormField): VNode | string;
|
|
565
570
|
/**
|
|
566
571
|
* Render form field
|
|
567
572
|
*/
|
package/dist/main.d.ts
CHANGED
|
@@ -105,6 +105,7 @@ interface FormFieldOption {
|
|
|
105
105
|
interface FormFieldConfig {
|
|
106
106
|
name: string;
|
|
107
107
|
label?: string;
|
|
108
|
+
icon?: string;
|
|
108
109
|
type?: string;
|
|
109
110
|
placeholder?: string;
|
|
110
111
|
value?: unknown;
|
|
@@ -562,6 +563,10 @@ declare class SmartFormComponent extends Component<FormConfig> {
|
|
|
562
563
|
* Handle form submission
|
|
563
564
|
*/
|
|
564
565
|
handleSubmit(event: Event): Promise<void>;
|
|
566
|
+
/**
|
|
567
|
+
* Render label with optional icon
|
|
568
|
+
*/
|
|
569
|
+
renderLabel(field: FormField): VNode | string;
|
|
565
570
|
/**
|
|
566
571
|
* Render form field
|
|
567
572
|
*/
|
package/dist/main.js
CHANGED
|
@@ -7,9 +7,14 @@ import {setConfig,patch,createElement,html}from'@je-es/vdom';export{createDOMEle
|
|
|
7
7
|
<p><strong>Route:</strong> ${t}</p>
|
|
8
8
|
<p><strong>Error:</strong> ${r}</p>
|
|
9
9
|
</div>
|
|
10
|
-
`;}}_handleScrollBehavior(t,e){if(t.hash){let r=document.getElementById(t.hash);if(r){r.scrollIntoView({behavior:this.scrollBehavior});return}}t.path!==e.path&&window.scrollTo({top:0,behavior:this.scrollBehavior});}_getCurrentPath(){if(this._internalPath!==null)return this._internalPath;if(this.mode==="hash")return window.location.hash.substring(1).split("?")[0]||"/";let t=window.location.pathname;return (!t||t==="blank"||t==="about:blank")&&(t="/"),this.base&&t.startsWith(this.base)&&(t=t.substring(this.base.length)),t||"/"}_buildFullPath(t){if(t.startsWith("http"))return t;let e=t.startsWith("/")?t:"/"+t;return this.base+e}_matchRoute(t){let e=t.split("?")[0].split("#")[0];for(let r of this.routes){let n=this._matchPath(r.path,e);if(n!==null)return {route:r,params:n}}return null}_matchPath(t,e){if(t==="*")return {};if(t===e)return {};let r=[],n=t.replace(/\*/g,".*").replace(/:([^/]+)/g,(i,u)=>(r.push(u),"([^/]+)")),s=new RegExp(`^${n}$`),a=e.match(s);return a?r.reduce((i,u,c)=>(i[u]=decodeURIComponent(a[c+1]),i),{}):null}_parseQuery(t){let e=t?t.includes("?")?t.split("?")[1].split("#")[0]:"":window.location.search.substring(1);return e?e.split("&").reduce((r,n)=>{let[s,a]=n.split("=").map(decodeURIComponent);return s&&(r[s]=a||""),r},{}):{}}},S=new R;function mt(o){let t=o;return {async build(){if(!t.build){console.warn("No build configuration provided");return}console.log("\u{1F528} Building @je-es/client application...");try{await this._buildJS(),await this._buildStyles(),console.log("\u2705 Build completed successfully!");}catch(e){throw console.error("\u274C Build error:",e),e}},async _buildJS(){if(!t.build)return;let e=await Bun.build({entrypoints:[t.build.entry],outdir:t.build.output.substring(0,t.build.output.lastIndexOf("/")),target:"browser",minify:t.build.minify??false,sourcemap:t.build.sourcemap?"external":"none",splitting:t.build.optimization?.splitChunks??false,naming:{entry:t.build.output.substring(t.build.output.lastIndexOf("/")+1)},external:["sass","fs","path","url","util","stream","buffer","events","crypto","os","child_process"]});if(!e.success)throw console.error("\u274C JS Build failed:",e.logs),new Error("JS Build failed")},async _buildStyles(){let e=t.build?.styles?.input||"./app/gui/style",r=t.build?.styles?.output||"./static/client.css",n=await import('sass'),{writeFileSync:s,existsSync:a,mkdirSync:i}=await import('fs'),{join:u,dirname:c}=await import('path'),d=c(r),l=r.split("/").pop()||"client.css",h=u(e,"index.scss");if(!a(h)){console.log("\u26A0\uFE0F No index.scss found, skipping CSS build");return}try{a(d)||i(d,{recursive:!0});let _=n.compile(h,{style:t.build?.minify?"compressed":"expanded",sourceMap:!!t.build?.sourcemap,loadPaths:[e]}),K=u(d,l);s(K,_.css,"utf-8"),t.build?.sourcemap&&_.sourceMap&&s(`${K}.map`,JSON.stringify(_.sourceMap),"utf-8");}catch(_){throw console.error("\u274C CSS Build failed:",_),_}},async _collectScssFiles(e){let{readdirSync:r,statSync:n,existsSync:s}=await import('fs'),{join:a,extname:i}=await import('path'),u=[];if(!s(e))return u;let c=r(e);for(let d of c){let l=a(e,d),h=n(l);h.isDirectory()?u.push(...await this._collectScssFiles(l)):h.isFile()&&i(d)===".scss"&&!d.startsWith("_")&&u.push(l);}return u.sort()},async watch(){console.log("\u{1F440} Watching for changes..."),await this.build();let{watch:e}=await import('fs'),{dirname:r}=await import('path'),{existsSync:n}=await import('fs');if(t.build?.entry){let a=r(t.build.entry);e(a,{recursive:true},async(i,u)=>{if(u&&(u.endsWith(".ts")||u.endsWith(".tsx"))){console.log(`\u{1F504} ${u} changed, rebuilding JS...`);try{await this._buildJS(),console.log("\u2705 JS rebuild complete");}catch(c){console.error("\u274C JS rebuild failed:",c);}}});}let s="./app/style";n(s)&&e(s,{recursive:true},async(a,i)=>{if(i&&i.endsWith(".scss")){console.log(`\u{1F504} ${i} changed, rebuilding CSS...`);try{await this._buildStyles(),console.log("\u2705 CSS rebuild complete");}catch(u){console.error("\u274C CSS rebuild failed:",u);}}});},init(){if(t.api){let e={baseURL:t.api.baseURL,timeout:t.api.timeout,headers:t.api.headers};t.api.interceptors&&(e.interceptors={request:t.api.interceptors.request||null,response:t.api.interceptors.response||null,error:t.api.interceptors.error||null}),configureApi(e);}t.router&&t.app?.routes&&(S.init(t.app.routes,t.router.mode,t.router.base),t.router.beforeEach&&S.beforeEach(t.router.beforeEach),t.router.afterEach&&S.afterEach(t.router.afterEach)),t.app?.root&&(document.querySelector(t.app.root)||console.error(`\u274C Root element "${t.app.root}" not found`)),t.devTools?.enabled&&this._enableDevTools();},_enableDevTools(){window.__JEES_DEV__={router:S,config:t,version:"0.0.1"};},getConfig(){return t}}}var P=class{constructor(t){this._subscribers=new Set;this._storage=null;this._middleware=[];this._isHydrating=false;if(this._persist=t.persist??false,this._storageKey=t.storageKey||`store_${Date.now()}`,this._persist&&typeof window<"u"&&(this._storage=t.storage==="sessionStorage"?sessionStorage:localStorage),this._persist&&this._storage){let e=this._loadFromStorage();this._state=e!==null?e:t.state;}else this._state=t.state;t.middleware&&(this._middleware=t.middleware);}get state(){return {...this._state}}set state(t){this.setState(t);}setState(t,e){let r={...this._state},n=typeof t=="function"?t(r):t;this._state={...r,...n};for(let s of this._middleware)try{s(this._state,e);}catch(a){console.error("Store middleware error:",a);}this._persist&&!this._isHydrating&&this._saveToStorage(),this._notify();}get(t){return this._state[t]}set(t,e,r){this.setState({[t]:e},r);}subscribe(t){return this._subscribers.add(t),t(this._state),()=>{this._subscribers.delete(t);}}subscribeToKey(t,e){let r=this._state[t],n=s=>{let a=s[t];r!==a&&(r=a,e(a));};return this.subscribe(n)}use(t){this._middleware.push(t);}clear(){if(this._state={},this._persist&&this._storage)try{this._storage.removeItem(this._storageKey);}catch(t){console.error("Failed to clear storage:",t);}this._notify();}reset(t){this._state={...t},this._persist&&this._saveToStorage(),this._notify();}hydrate(){if(!this._persist||!this._storage){console.warn("Cannot hydrate: persistence not enabled");return}this._isHydrating=true;let t=this._loadFromStorage();t!==null&&(this._state=t,this._notify()),this._isHydrating=false;}getSnapshot(){return {state:{...this._state},subscribers:this._subscribers.size,storageKey:this._storageKey}}batch(t){let e=this._notify.bind(this),r=false;this._notify=()=>{r=true;};try{t();}finally{this._notify=e,r&&this._notify();}}_notify(){let t={...this._state};for(let e of this._subscribers)try{e(t);}catch(r){console.error("Store subscriber error:",r);}}_loadFromStorage(){if(!this._storage)return null;try{let t=this._storage.getItem(this._storageKey);return t?JSON.parse(t):null}catch(t){return console.error("Failed to load from storage:",t),null}}_saveToStorage(){if(this._storage)try{this._storage.setItem(this._storageKey,JSON.stringify(this._state));}catch(t){console.error("Failed to save to storage:",t),t instanceof DOMException&&t.name==="QuotaExceededError"&&console.warn("Storage quota exceeded");}}destroy(){this._subscribers.clear(),this._middleware=[],this._state={};}};function B(o){return new P(o)}function gt(o,t){let e=B({state:{value:t(...o.map(r=>r.state))}});for(let r of o)r.subscribe(()=>{e.setState({value:t(...o.map(n=>n.state))});});return e}function vt(o,t,e){return o.subscribe(n=>{let s=e(n);Object.assign(t,s),typeof t.update=="function"&&t.update();})}function y(o,t){if(t&&typeof t=="object"&&"kind"in t){let a=t.name;return t.addInitializer(function(){let i=this;i.constructor.__reactiveProps__||(i.constructor.__reactiveProps__=[]),i.constructor.__reactiveProps__.includes(a)||i.constructor.__reactiveProps__.push(a);}),function(i){let u=this,c=`_state_${a}`;return u[c]=i,Object.defineProperty(this,a,{get(){return this[c]},set(d){let l=this,h=l[c];h!==d&&(l[c]=d,typeof l._invalidateAllComputed=="function"&&l._invalidateAllComputed(),typeof l._triggerWatchers=="function"&&l._triggerWatchers(a,d,h),l._isMounted&&typeof l.update=="function"&&l.update());},enumerable:true,configurable:true}),i}}let e=t,r=o.constructor;r.__reactiveProps__||(r.__reactiveProps__=[]),r.__reactiveProps__.includes(e)||r.__reactiveProps__.push(e);let n=`_state_${e}`,s=`_state_init_${e}`;Object.defineProperty(o,e,{get(){let a=this;if(a[s])return a[n]},set(a){let i=this;if(!i[s]){i[n]=a,i[s]=true;return}let u=i[n];u!==a&&(i[n]=a,typeof i._invalidateAllComputed=="function"&&i._invalidateAllComputed(),typeof i._triggerWatchers=="function"&&i._triggerWatchers(e,a,u),i._isMounted&&typeof i.update=="function"&&i.update());},enumerable:true,configurable:true});}function bt(o,t,e){if(t&&typeof t=="object"&&"kind"in t){let i=t;if(i.kind!=="getter")throw new Error("@computed can only be used on getters");let u=o,c=i.name,d=`_computed_cache_${c}`,l=`_computed_dirty_${c}`;return function(){let h=this;return h[l]===void 0&&(h[l]=true),h[l]===true&&(h[d]=u.call(this),h[l]=false),h[d]}}let r=t;if(!e)throw new Error("@computed requires a property descriptor");let n=e.get;if(!n)throw new Error("@computed can only be used on getters");let s=`_computed_cache_${r}`,a=`_computed_dirty_${r}`;return {get(){let i=this;return i[a]===void 0&&(i[a]=true),i[a]===true&&(i[s]=n.call(this),i[a]=false),i[s]},enumerable:e.enumerable,configurable:e.configurable}}function _t(o){function t(e,r,n){if(r&&typeof r=="object"&&"kind"in r){if(r.kind!=="method")throw new Error("@watch can only be used on methods");let u=r.name;r.addInitializer(function(){let c=this;c.constructor.__watchers__||(c.constructor.__watchers__={}),c.constructor.__watchers__[o]||(c.constructor.__watchers__[o]=[]),c.constructor.__watchers__[o].includes(u)||c.constructor.__watchers__[o].push(u);});return}let s=r;if(!n)throw new Error("@watch requires a property descriptor");let i=e.constructor;return i.__watchers__||(i.__watchers__={}),i.__watchers__[o]||(i.__watchers__[o]=[]),i.__watchers__[o].includes(s)||i.__watchers__[o].push(s),n}return t}var g=class extends m{constructor(e){super(e);this.fields=[];this.formData={};this.isSubmitting=false;this.submitError="";this.submitSuccess=false;this.fields=this.props.fields.map(r=>({...r,error:void 0,touched:false}));for(let r of this.fields)this.formData[r.name]=r.value||"";}onMount(){}handleChange(e,r){this.formData[e]=r;let n=this.fields.find(s=>s.name===e);n&&this.props.autoValidate&&(n.error=this.validateField(n,r),n.touched=true),this.update();}handleBlur(e){let r=this.fields.find(n=>n.name===e);r&&(r.touched=true,r.error=this.validateField(r,this.formData[e]),this.update());}validateField(e,r){let n=e.validation;if(!n)return;if(n.required&&!r)return n.message||`${e.label||e.name} is required`;if(!r)return;let s=String(r);if(n.minLength&&s.length<n.minLength)return n.message||`Minimum ${n.minLength} characters required`;if(n.maxLength&&s.length>n.maxLength)return n.message||`Maximum ${n.maxLength} characters allowed`;if(n.min!==void 0&&Number(r)<n.min)return n.message||`Minimum value is ${n.min}`;if(n.max!==void 0&&Number(r)>n.max)return n.message||`Maximum value is ${n.max}`;if(n.pattern&&!n.pattern.test(s))return n.message||"Invalid format";if(n.email&&!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(s))return n.message||"Invalid email address";if(n.url&&!/^https?:\/\/.+/.test(s))return n.message||"Invalid URL";if(n.custom){let a=n.custom(r);if(a!==true)return typeof a=="string"?a:"Validation failed"}}validateForm(){let e=true,r={};for(let n of this.fields){let s=this.validateField(n,this.formData[n.name]);n.error=s,n.touched=true,s&&(e=false,r[n.name]=s);}return this.update(),!e&&this.props.onValidationError&&this.props.onValidationError(r),e}async handleSubmit(e){if(e.preventDefault(),!this.validateForm()){let r=this.fields.find(n=>n.error);r&&document.querySelector(`[name="${r.name}"]`)?.focus();return}this.isSubmitting=true,this.submitError="",this.submitSuccess=false,this.update();try{if(this.props.onSubmit)await this.props.onSubmit(this.formData,e);else if(this.props.endpoint){let r=await api({method:this.props.method||"POST",url:this.props.endpoint,data:this.formData});this.submitSuccess=!0,this.props.onSuccess&&this.props.onSuccess(r.data);}}catch(r){let n=r instanceof Error?r.message:"Submission failed";this.submitError=n,this.props.onError&&this.props.onError(r);}finally{this.isSubmitting=false,this.update();}}renderField(e){let r=this.formData[e.name]||"",n=e.touched&&e.error;switch(e.type){case "textarea":return html`
|
|
10
|
+
`;}}_handleScrollBehavior(t,e){if(t.hash){let r=document.getElementById(t.hash);if(r){r.scrollIntoView({behavior:this.scrollBehavior});return}}t.path!==e.path&&window.scrollTo({top:0,behavior:this.scrollBehavior});}_getCurrentPath(){if(this._internalPath!==null)return this._internalPath;if(this.mode==="hash")return window.location.hash.substring(1).split("?")[0]||"/";let t=window.location.pathname;return (!t||t==="blank"||t==="about:blank")&&(t="/"),this.base&&t.startsWith(this.base)&&(t=t.substring(this.base.length)),t||"/"}_buildFullPath(t){if(t.startsWith("http"))return t;let e=t.startsWith("/")?t:"/"+t;return this.base+e}_matchRoute(t){let e=t.split("?")[0].split("#")[0];for(let r of this.routes){let n=this._matchPath(r.path,e);if(n!==null)return {route:r,params:n}}return null}_matchPath(t,e){if(t==="*")return {};if(t===e)return {};let r=[],n=t.replace(/\*/g,".*").replace(/:([^/]+)/g,(i,u)=>(r.push(u),"([^/]+)")),s=new RegExp(`^${n}$`),a=e.match(s);return a?r.reduce((i,u,c)=>(i[u]=decodeURIComponent(a[c+1]),i),{}):null}_parseQuery(t){let e=t?t.includes("?")?t.split("?")[1].split("#")[0]:"":window.location.search.substring(1);return e?e.split("&").reduce((r,n)=>{let[s,a]=n.split("=").map(decodeURIComponent);return s&&(r[s]=a||""),r},{}):{}}},S=new R;function mt(o){let t=o;return {async build(){if(!t.build){console.warn("No build configuration provided");return}console.log("\u{1F528} Building @je-es/client application...");try{await this._buildJS(),await this._buildStyles(),console.log("\u2705 Build completed successfully!");}catch(e){throw console.error("\u274C Build error:",e),e}},async _buildJS(){if(!t.build)return;let e=await Bun.build({entrypoints:[t.build.entry],outdir:t.build.output.substring(0,t.build.output.lastIndexOf("/")),target:"browser",minify:t.build.minify??false,sourcemap:t.build.sourcemap?"external":"none",splitting:t.build.optimization?.splitChunks??false,naming:{entry:t.build.output.substring(t.build.output.lastIndexOf("/")+1)},external:["sass","fs","path","url","util","stream","buffer","events","crypto","os","child_process"]});if(!e.success)throw console.error("\u274C JS Build failed:",e.logs),new Error("JS Build failed")},async _buildStyles(){let e=t.build?.styles?.input||"./app/gui/style",r=t.build?.styles?.output||"./static/client.css",n=await import('sass'),{writeFileSync:s,existsSync:a,mkdirSync:i}=await import('fs'),{join:u,dirname:c}=await import('path'),d=c(r),l=r.split("/").pop()||"client.css",p=u(e,"index.scss");if(!a(p)){console.log("\u26A0\uFE0F No index.scss found, skipping CSS build");return}try{a(d)||i(d,{recursive:!0});let _=n.compile(p,{style:t.build?.minify?"compressed":"expanded",sourceMap:!!t.build?.sourcemap,loadPaths:[e]}),K=u(d,l);s(K,_.css,"utf-8"),t.build?.sourcemap&&_.sourceMap&&s(`${K}.map`,JSON.stringify(_.sourceMap),"utf-8");}catch(_){throw console.error("\u274C CSS Build failed:",_),_}},async _collectScssFiles(e){let{readdirSync:r,statSync:n,existsSync:s}=await import('fs'),{join:a,extname:i}=await import('path'),u=[];if(!s(e))return u;let c=r(e);for(let d of c){let l=a(e,d),p=n(l);p.isDirectory()?u.push(...await this._collectScssFiles(l)):p.isFile()&&i(d)===".scss"&&!d.startsWith("_")&&u.push(l);}return u.sort()},async watch(){console.log("\u{1F440} Watching for changes..."),await this.build();let{watch:e}=await import('fs'),{dirname:r}=await import('path'),{existsSync:n}=await import('fs');if(t.build?.entry){let a=r(t.build.entry);e(a,{recursive:true},async(i,u)=>{if(u&&(u.endsWith(".ts")||u.endsWith(".tsx"))){console.log(`\u{1F504} ${u} changed, rebuilding JS...`);try{await this._buildJS(),console.log("\u2705 JS rebuild complete");}catch(c){console.error("\u274C JS rebuild failed:",c);}}});}let s="./app/style";n(s)&&e(s,{recursive:true},async(a,i)=>{if(i&&i.endsWith(".scss")){console.log(`\u{1F504} ${i} changed, rebuilding CSS...`);try{await this._buildStyles(),console.log("\u2705 CSS rebuild complete");}catch(u){console.error("\u274C CSS rebuild failed:",u);}}});},init(){if(t.api){let e={baseURL:t.api.baseURL,timeout:t.api.timeout,headers:t.api.headers};t.api.interceptors&&(e.interceptors={request:t.api.interceptors.request||null,response:t.api.interceptors.response||null,error:t.api.interceptors.error||null}),configureApi(e);}t.router&&t.app?.routes&&(S.init(t.app.routes,t.router.mode,t.router.base),t.router.beforeEach&&S.beforeEach(t.router.beforeEach),t.router.afterEach&&S.afterEach(t.router.afterEach)),t.app?.root&&(document.querySelector(t.app.root)||console.error(`\u274C Root element "${t.app.root}" not found`)),t.devTools?.enabled&&this._enableDevTools();},_enableDevTools(){window.__JEES_DEV__={router:S,config:t,version:"0.0.1"};},getConfig(){return t}}}var P=class{constructor(t){this._subscribers=new Set;this._storage=null;this._middleware=[];this._isHydrating=false;if(this._persist=t.persist??false,this._storageKey=t.storageKey||`store_${Date.now()}`,this._persist&&typeof window<"u"&&(this._storage=t.storage==="sessionStorage"?sessionStorage:localStorage),this._persist&&this._storage){let e=this._loadFromStorage();this._state=e!==null?e:t.state;}else this._state=t.state;t.middleware&&(this._middleware=t.middleware);}get state(){return {...this._state}}set state(t){this.setState(t);}setState(t,e){let r={...this._state},n=typeof t=="function"?t(r):t;this._state={...r,...n};for(let s of this._middleware)try{s(this._state,e);}catch(a){console.error("Store middleware error:",a);}this._persist&&!this._isHydrating&&this._saveToStorage(),this._notify();}get(t){return this._state[t]}set(t,e,r){this.setState({[t]:e},r);}subscribe(t){return this._subscribers.add(t),t(this._state),()=>{this._subscribers.delete(t);}}subscribeToKey(t,e){let r=this._state[t],n=s=>{let a=s[t];r!==a&&(r=a,e(a));};return this.subscribe(n)}use(t){this._middleware.push(t);}clear(){if(this._state={},this._persist&&this._storage)try{this._storage.removeItem(this._storageKey);}catch(t){console.error("Failed to clear storage:",t);}this._notify();}reset(t){this._state={...t},this._persist&&this._saveToStorage(),this._notify();}hydrate(){if(!this._persist||!this._storage){console.warn("Cannot hydrate: persistence not enabled");return}this._isHydrating=true;let t=this._loadFromStorage();t!==null&&(this._state=t,this._notify()),this._isHydrating=false;}getSnapshot(){return {state:{...this._state},subscribers:this._subscribers.size,storageKey:this._storageKey}}batch(t){let e=this._notify.bind(this),r=false;this._notify=()=>{r=true;};try{t();}finally{this._notify=e,r&&this._notify();}}_notify(){let t={...this._state};for(let e of this._subscribers)try{e(t);}catch(r){console.error("Store subscriber error:",r);}}_loadFromStorage(){if(!this._storage)return null;try{let t=this._storage.getItem(this._storageKey);return t?JSON.parse(t):null}catch(t){return console.error("Failed to load from storage:",t),null}}_saveToStorage(){if(this._storage)try{this._storage.setItem(this._storageKey,JSON.stringify(this._state));}catch(t){console.error("Failed to save to storage:",t),t instanceof DOMException&&t.name==="QuotaExceededError"&&console.warn("Storage quota exceeded");}}destroy(){this._subscribers.clear(),this._middleware=[],this._state={};}};function B(o){return new P(o)}function gt(o,t){let e=B({state:{value:t(...o.map(r=>r.state))}});for(let r of o)r.subscribe(()=>{e.setState({value:t(...o.map(n=>n.state))});});return e}function vt(o,t,e){return o.subscribe(n=>{let s=e(n);Object.assign(t,s),typeof t.update=="function"&&t.update();})}function y(o,t){if(t&&typeof t=="object"&&"kind"in t){let a=t.name;return t.addInitializer(function(){let i=this;i.constructor.__reactiveProps__||(i.constructor.__reactiveProps__=[]),i.constructor.__reactiveProps__.includes(a)||i.constructor.__reactiveProps__.push(a);}),function(i){let u=this,c=`_state_${a}`;return u[c]=i,Object.defineProperty(this,a,{get(){return this[c]},set(d){let l=this,p=l[c];p!==d&&(l[c]=d,typeof l._invalidateAllComputed=="function"&&l._invalidateAllComputed(),typeof l._triggerWatchers=="function"&&l._triggerWatchers(a,d,p),l._isMounted&&typeof l.update=="function"&&l.update());},enumerable:true,configurable:true}),i}}let e=t,r=o.constructor;r.__reactiveProps__||(r.__reactiveProps__=[]),r.__reactiveProps__.includes(e)||r.__reactiveProps__.push(e);let n=`_state_${e}`,s=`_state_init_${e}`;Object.defineProperty(o,e,{get(){let a=this;if(a[s])return a[n]},set(a){let i=this;if(!i[s]){i[n]=a,i[s]=true;return}let u=i[n];u!==a&&(i[n]=a,typeof i._invalidateAllComputed=="function"&&i._invalidateAllComputed(),typeof i._triggerWatchers=="function"&&i._triggerWatchers(e,a,u),i._isMounted&&typeof i.update=="function"&&i.update());},enumerable:true,configurable:true});}function bt(o,t,e){if(t&&typeof t=="object"&&"kind"in t){let i=t;if(i.kind!=="getter")throw new Error("@computed can only be used on getters");let u=o,c=i.name,d=`_computed_cache_${c}`,l=`_computed_dirty_${c}`;return function(){let p=this;return p[l]===void 0&&(p[l]=true),p[l]===true&&(p[d]=u.call(this),p[l]=false),p[d]}}let r=t;if(!e)throw new Error("@computed requires a property descriptor");let n=e.get;if(!n)throw new Error("@computed can only be used on getters");let s=`_computed_cache_${r}`,a=`_computed_dirty_${r}`;return {get(){let i=this;return i[a]===void 0&&(i[a]=true),i[a]===true&&(i[s]=n.call(this),i[a]=false),i[s]},enumerable:e.enumerable,configurable:e.configurable}}function _t(o){function t(e,r,n){if(r&&typeof r=="object"&&"kind"in r){if(r.kind!=="method")throw new Error("@watch can only be used on methods");let u=r.name;r.addInitializer(function(){let c=this;c.constructor.__watchers__||(c.constructor.__watchers__={}),c.constructor.__watchers__[o]||(c.constructor.__watchers__[o]=[]),c.constructor.__watchers__[o].includes(u)||c.constructor.__watchers__[o].push(u);});return}let s=r;if(!n)throw new Error("@watch requires a property descriptor");let i=e.constructor;return i.__watchers__||(i.__watchers__={}),i.__watchers__[o]||(i.__watchers__[o]=[]),i.__watchers__[o].includes(s)||i.__watchers__[o].push(s),n}return t}var g=class extends m{constructor(e){super(e);this.fields=[];this.formData={};this.isSubmitting=false;this.submitError="";this.submitSuccess=false;this.fields=this.props.fields.map(r=>({...r,error:void 0,touched:false}));for(let r of this.fields)this.formData[r.name]=r.value||"";}onMount(){}handleChange(e,r){this.formData[e]=r;let n=this.fields.find(s=>s.name===e);n&&this.props.autoValidate&&(n.error=this.validateField(n,r),n.touched=true),this.update();}handleBlur(e){let r=this.fields.find(n=>n.name===e);r&&(r.touched=true,r.error=this.validateField(r,this.formData[e]),this.update());}validateField(e,r){let n=e.validation;if(!n)return;if(n.required&&!r)return n.message||`${e.label||e.name} is required`;if(!r)return;let s=String(r);if(n.minLength&&s.length<n.minLength)return n.message||`Minimum ${n.minLength} characters required`;if(n.maxLength&&s.length>n.maxLength)return n.message||`Maximum ${n.maxLength} characters allowed`;if(n.min!==void 0&&Number(r)<n.min)return n.message||`Minimum value is ${n.min}`;if(n.max!==void 0&&Number(r)>n.max)return n.message||`Maximum value is ${n.max}`;if(n.pattern&&!n.pattern.test(s))return n.message||"Invalid format";if(n.email&&!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(s))return n.message||"Invalid email address";if(n.url&&!/^https?:\/\/.+/.test(s))return n.message||"Invalid URL";if(n.custom){let a=n.custom(r);if(a!==true)return typeof a=="string"?a:"Validation failed"}}validateForm(){let e=true,r={};for(let n of this.fields){let s=this.validateField(n,this.formData[n.name]);n.error=s,n.touched=true,s&&(e=false,r[n.name]=s);}return this.update(),!e&&this.props.onValidationError&&this.props.onValidationError(r),e}async handleSubmit(e){if(e.preventDefault(),!this.validateForm()){let r=this.fields.find(n=>n.error);r&&document.querySelector(`[name="${r.name}"]`)?.focus();return}this.isSubmitting=true,this.submitError="",this.submitSuccess=false,this.update();try{if(this.props.onSubmit)await this.props.onSubmit(this.formData,e);else if(this.props.endpoint){let r=await api({method:this.props.method||"POST",url:this.props.endpoint,data:this.formData});this.submitSuccess=!0,this.props.onSuccess&&this.props.onSuccess(r.data);}}catch(r){let n=r instanceof Error?r.message:"Submission failed";this.submitError=n,this.props.onError&&this.props.onError(r);}finally{this.isSubmitting=false,this.update();}}renderLabel(e){return !e.label&&!e.icon?"":e.icon?html`
|
|
11
|
+
<label for=${e.name}>
|
|
12
|
+
<i class="fa ${e.icon}"></i>
|
|
13
|
+
${e.label?html`<span>${e.label}</span>`:""}
|
|
14
|
+
</label>
|
|
15
|
+
`:html`<label for=${e.name}>${e.label}</label>`}renderField(e){let r=this.formData[e.name]||"",n=this.renderLabel(e);switch(e.type){case "textarea":return html`
|
|
11
16
|
<div class="form-field ${e.className||""}">
|
|
12
|
-
${
|
|
17
|
+
${n}
|
|
13
18
|
<textarea
|
|
14
19
|
id=${e.name}
|
|
15
20
|
name=${e.name}
|
|
@@ -19,13 +24,15 @@ import {setConfig,patch,createElement,html}from'@je-es/vdom';export{createDOMEle
|
|
|
19
24
|
oninput=${s=>{let a=s.target;this.handleChange(e.name,a.value);}}
|
|
20
25
|
onblur=${()=>this.handleBlur(e.name)}
|
|
21
26
|
></textarea>
|
|
22
|
-
${
|
|
27
|
+
${e.error&&e.touched?html`
|
|
28
|
+
<span class="field-error">${e.error}</span>
|
|
29
|
+
`:""}
|
|
23
30
|
</div>
|
|
24
31
|
`;case "select":{let a=(e.options||[]).map(i=>html`
|
|
25
32
|
<option value=${String(i.value)}>${i.label}</option>
|
|
26
33
|
`);return html`
|
|
27
34
|
<div class="form-field ${e.className||""}">
|
|
28
|
-
${
|
|
35
|
+
${n}
|
|
29
36
|
<select
|
|
30
37
|
id=${e.name}
|
|
31
38
|
name=${e.name}
|
|
@@ -37,7 +44,9 @@ import {setConfig,patch,createElement,html}from'@je-es/vdom';export{createDOMEle
|
|
|
37
44
|
<option value="">Select...</option>
|
|
38
45
|
${a}
|
|
39
46
|
</select>
|
|
40
|
-
${
|
|
47
|
+
${e.error&&e.touched?html`
|
|
48
|
+
<span class="field-error">${e.error}</span>
|
|
49
|
+
`:""}
|
|
41
50
|
</div>
|
|
42
51
|
`}case "checkbox":return html`
|
|
43
52
|
<div class="form-field form-field-checkbox ${e.className||""}">
|
|
@@ -50,23 +59,29 @@ import {setConfig,patch,createElement,html}from'@je-es/vdom';export{createDOMEle
|
|
|
50
59
|
disabled=${String(e.disabled||this.isSubmitting)}
|
|
51
60
|
onchange=${s=>{let a=s.target;this.handleChange(e.name,a.checked);}}
|
|
52
61
|
/>
|
|
62
|
+
${e.icon?html`<i class="fa ${e.icon}"></i>`:""}
|
|
53
63
|
${e.label||""}
|
|
54
64
|
</label>
|
|
55
|
-
${
|
|
65
|
+
${e.error&&e.touched?html`
|
|
66
|
+
<span class="field-error">${e.error}</span>
|
|
67
|
+
`:""}
|
|
56
68
|
</div>
|
|
57
69
|
`;default:return html`
|
|
58
70
|
<div class="form-field ${e.className||""}">
|
|
59
|
-
${
|
|
71
|
+
${n}
|
|
60
72
|
<input
|
|
61
73
|
type="${e.type||"text"}"
|
|
62
74
|
id="${e.name}"
|
|
63
75
|
name="${e.name}"
|
|
64
76
|
placeholder="${e.placeholder||""}"
|
|
65
77
|
value="${String(r)}"
|
|
78
|
+
disabled="${e.disabled||this.isSubmitting}"
|
|
66
79
|
oninput=${s=>{let a=s.target;this.handleChange(e.name,a.value);}}
|
|
67
80
|
onblur=${()=>this.handleBlur(e.name)}
|
|
68
81
|
/>
|
|
69
|
-
${
|
|
82
|
+
${e.error&&e.touched?html`
|
|
83
|
+
<span class="field-error">${e.error}</span>
|
|
84
|
+
`:""}
|
|
70
85
|
</div>
|
|
71
86
|
`}}render(){let e=this.props.submitButton||{},r=this.fields.map(n=>this.renderField(n));return html`
|
|
72
87
|
<form
|
|
@@ -99,10 +114,15 @@ import {setConfig,patch,createElement,html}from'@je-es/vdom';export{createDOMEle
|
|
|
99
114
|
margin-bottom: 1rem;
|
|
100
115
|
}
|
|
101
116
|
.form-field label {
|
|
102
|
-
display:
|
|
117
|
+
display: flex;
|
|
118
|
+
align-items: center;
|
|
119
|
+
gap: 0.5rem;
|
|
103
120
|
margin-bottom: 0.5rem;
|
|
104
121
|
font-weight: 500;
|
|
105
122
|
}
|
|
123
|
+
.form-field label i {
|
|
124
|
+
color: #6b7280;
|
|
125
|
+
}
|
|
106
126
|
.form-field input,
|
|
107
127
|
.form-field textarea,
|
|
108
128
|
.form-field select {
|
|
@@ -119,12 +139,6 @@ import {setConfig,patch,createElement,html}from'@je-es/vdom';export{createDOMEle
|
|
|
119
139
|
border-color: #3b82f6;
|
|
120
140
|
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
|
121
141
|
}
|
|
122
|
-
.form-field .error {
|
|
123
|
-
display: block;
|
|
124
|
-
margin-top: 0.25rem;
|
|
125
|
-
color: #ef4444;
|
|
126
|
-
font-size: 0.875rem;
|
|
127
|
-
}
|
|
128
142
|
.form-field-checkbox label {
|
|
129
143
|
display: flex;
|
|
130
144
|
align-items: center;
|
|
@@ -133,6 +147,12 @@ import {setConfig,patch,createElement,html}from'@je-es/vdom';export{createDOMEle
|
|
|
133
147
|
.form-field-checkbox input[type="checkbox"] {
|
|
134
148
|
width: auto;
|
|
135
149
|
}
|
|
150
|
+
.field-error {
|
|
151
|
+
display: block;
|
|
152
|
+
color: #dc2626;
|
|
153
|
+
font-size: 0.875rem;
|
|
154
|
+
margin-top: 0.25rem;
|
|
155
|
+
}
|
|
136
156
|
.submit-button {
|
|
137
157
|
width: 100%;
|
|
138
158
|
padding: 0.75rem 1rem;
|