ctrovalidate-svelte 1.0.0
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/LICENSE +21 -0
- package/README.md +106 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +506 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ctrotech
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# ctrovalidate-svelte
|
|
2
|
+
|
|
3
|
+
**Reactive form validation for Svelte.**
|
|
4
|
+
|
|
5
|
+
`ctrovalidate-svelte` provides a `useCtrovalidate` function that wraps [`ctrovalidate-core`](https://www.npmjs.com/package/ctrovalidate-core)'s validation engine with Svelte stores. Returns `writable` and `derived` stores for values, errors, dirty state, and async validation status.
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/ctrovalidate-svelte)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install ctrovalidate-svelte ctrovalidate-core
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
**Requirements:** Svelte >=3.0.0
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```svelte
|
|
25
|
+
<script lang="ts">
|
|
26
|
+
import { useCtrovalidate } from 'ctrovalidate-svelte';
|
|
27
|
+
|
|
28
|
+
const { values, errors, handleChange, handleBlur, validateForm, isValidating } =
|
|
29
|
+
useCtrovalidate<{ email: string; password: string }>({
|
|
30
|
+
initialValues: { email: '', password: '' },
|
|
31
|
+
schema: { email: 'required|email', password: 'required|minLength:8' },
|
|
32
|
+
});
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<form on:submit|preventDefault={async () => { if (await validateForm()) { /* submit */ } }}>
|
|
36
|
+
<input value={$values.email} on:input={(e) => handleChange('email', e.target.value)} on:blur={() => handleBlur('email')} />
|
|
37
|
+
{#if $errors.email}<span>{$errors.email}</span>{/if}
|
|
38
|
+
|
|
39
|
+
<input type="password" value={$values.password} on:input={(e) => handleChange('password', e.target.value)} on:blur={() => handleBlur('password')} />
|
|
40
|
+
{#if $errors.password}<span>{$errors.password}</span>{/if}
|
|
41
|
+
|
|
42
|
+
<button disabled={$isValidating.email || $isValidating.password}>
|
|
43
|
+
{$isValidating.email || $isValidating.password ? 'Validating...' : 'Login'}
|
|
44
|
+
</button>
|
|
45
|
+
</form>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## API
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
const {
|
|
54
|
+
values, // Writable<T>
|
|
55
|
+
errors, // Writable<Partial<Record<keyof T, string>>>
|
|
56
|
+
isDirty, // Writable<Partial<Record<keyof T, boolean>>>
|
|
57
|
+
isValidating, // Writable<Partial<Record<keyof T, boolean>>>
|
|
58
|
+
isValid, // Readable<boolean> — derived from errors
|
|
59
|
+
handleChange, // (name, value) => void — updates value, marks dirty, validates
|
|
60
|
+
handleBlur, // (name) => void — marks dirty, validates
|
|
61
|
+
validateField, // (name, value?) => Promise<boolean>
|
|
62
|
+
validateForm, // () => Promise<boolean>
|
|
63
|
+
reset, // (newValues?) => void
|
|
64
|
+
} = useCtrovalidate<T>({
|
|
65
|
+
schema, // Required
|
|
66
|
+
initialValues, // Optional (default: {})
|
|
67
|
+
validateOnBlur, // Optional (default: true)
|
|
68
|
+
validateOnChange, // Optional (default: true)
|
|
69
|
+
customRules, // Optional
|
|
70
|
+
aliases, // Optional
|
|
71
|
+
messages, // Optional
|
|
72
|
+
locale, // Optional
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Behavior
|
|
79
|
+
|
|
80
|
+
| Call | Marks dirty | Validates |
|
|
81
|
+
|------|-------------|-----------|
|
|
82
|
+
| `handleChange(name, value)` | Yes | If `validateOnChange` |
|
|
83
|
+
| `handleBlur(name)` | Yes | If `validateOnBlur` |
|
|
84
|
+
|
|
85
|
+
- `validateField` aborts any in-flight async rule for the same field
|
|
86
|
+
- All `AbortController`s are aborted on `onDestroy`
|
|
87
|
+
- `isValid` is a `derived` store: `true` when no error string is truthy
|
|
88
|
+
- `reset()` re-initializes all stores and clears validation state
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Related Packages
|
|
93
|
+
|
|
94
|
+
- **[ctrovalidate-core](https://www.npmjs.com/package/ctrovalidate-core)** — Validation engine
|
|
95
|
+
- **[ctrovalidate-browser](https://www.npmjs.com/package/ctrovalidate-browser)** — Vanilla JS DOM integration
|
|
96
|
+
- **[ctrovalidate-react](https://www.npmjs.com/package/ctrovalidate-react)** — React hook
|
|
97
|
+
- **[ctrovalidate-vue](https://www.npmjs.com/package/ctrovalidate-vue)** — Vue composable
|
|
98
|
+
- **[ctrovalidate-next](https://www.npmjs.com/package/ctrovalidate-next)** — Next.js server actions
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## License
|
|
103
|
+
|
|
104
|
+
MIT © [Ctrotech](https://github.com/ctrotech-tutor)
|
|
105
|
+
|
|
106
|
+
Full documentation: https://ctrovalidate.vercel.app
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const H=require("svelte"),N=()=>{};function K(e){for(var r=0;r<e.length;r++)e[r]()}function Q(e,r){return e!=e?r==r:e!==r||e!==null&&typeof e=="object"||typeof e=="function"}function E(e,r,t){if(e==null)return r(void 0),t&&t(void 0),N;const i=ee(()=>e.subscribe(r,t));return i.unsubscribe?()=>i.unsubscribe():i}const w=[];function X(e,r){return{subscribe:$(e,r).subscribe}}function $(e,r=N){let t=null;const i=new Set;function n(c){if(Q(e,c)&&(e=c,t)){const d=!w.length;for(const o of i)o[1](),w.push(o,e);if(d){for(let o=0;o<w.length;o+=2)w[o][0](w[o+1]);w.length=0}}}function a(c){n(c(e))}function l(c,d=N){const o=[c,d];return i.add(o),i.size===1&&(t=r(n,a)||N),c(e),()=>{i.delete(o),i.size===0&&t&&(t(),t=null)}}return{set:n,update:a,subscribe:l}}function Y(e,r,t){const i=!Array.isArray(e),n=i?[e]:e;if(!n.every(Boolean))throw new Error("derived() expects stores as input, got a falsy value");const a=r.length<2;return X(t,(l,c)=>{let d=!1;const o=[];let g=0,h=N;const L=()=>{if(g)return;h();const m=r(i?o[0]:o,l,c);a?l(m):h=typeof m=="function"?m:N},v=n.map((m,_)=>E(m,F=>{o[_]=F,g&=~(1<<_),d&&L()},()=>{g|=1<<_}));return d=!0,L(),function(){K(v),h(),d=!1}})}function V(e){let r;return E(e,t=>r=t)(),r}let R=!1;function ee(e){var r=R;try{return R=!0,e()}finally{R=r}}var q=Object.defineProperty,D=e=>{throw TypeError(e)},re=(e,r,t)=>r in e?q(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t,te=(e,r)=>{for(var t in r)q(e,t,{get:r[t],enumerable:!0})},P=(e,r,t)=>re(e,typeof r!="symbol"?r+"":r,t),I=(e,r,t)=>r.has(e)||D("Cannot "+t),A=(e,r,t)=>(I(e,r,"read from private field"),t?t.call(e):r.get(e)),O=(e,r,t)=>r.has(e)?D("Cannot add the same private member more than once"):r instanceof WeakSet?r.add(e):r.set(e,t),z=(e,r,t,i)=>(I(e,r,"write to private field"),r.set(e,t),t);function k(e){if(!e||typeof e!="string")return[];const r=[],t=e.split("|");for(const i of t){const n=i.trim();if(n==="")continue;const a=n.indexOf(":");if(a===-1)r.push({name:n,params:[]});else{const l=n.substring(0,a).trim(),c=n.substring(a+1).trim();if(l){const d=c.split(",").map(o=>o.trim());r.push({name:l,params:d})}}}return r}function Z(e,r={},t=new Set){if(!e)return[];let i;if(typeof e=="string")i=k(e);else if(Array.isArray(e))i=e;else return[];return i.flatMap(n=>{const a=typeof n=="string"?n.split(":")[0]:n.name;if(r[a]&&!t.has(a)){const l=new Set(t);return l.add(a),Z(r[a],r,l)}return typeof n=="string"?k(n):[n]})}var M=class W{constructor(r=0){P(this,"level"),this.level=r}setLevel(r){this.level=r}static setLevel(r){this.globalLevel=r}format(r){return`${W.prefix} ${r}`}error(r,...t){this.level>=1&&console.error(this.format(r),...t)}warn(r,...t){this.level>=2&&console.warn(this.format(r),...t)}info(r,...t){this.level>=3&&console.info(this.format(r),...t)}debug(r,...t){this.level>=4&&console.debug(this.format(r),...t)}static error(r,...t){this.globalLevel>=1&&console.error(`${this.prefix} ${r}`,...t)}static warn(r,...t){this.globalLevel>=2&&console.warn(`${this.prefix} ${r}`,...t)}static info(r,...t){this.globalLevel>=3&&console.info(`${this.prefix} ${r}`,...t)}static debug(r,...t){this.globalLevel>=4&&console.debug(`${this.prefix} ${r}`,...t)}};P(M,"globalLevel",1);P(M,"prefix","[Ctrovalidate]");var ne=M,B={};te(B,{alpha:()=>fe,alphaDash:()=>me,alphaNum:()=>he,alphaSpaces:()=>ve,between:()=>ze,creditCard:()=>Me,decimal:()=>Se,email:()=>ae,exactLength:()=>Oe,integer:()=>xe,ipAddress:()=>Fe,json:()=>Ce,max:()=>le,maxLength:()=>de,min:()=>oe,minLength:()=>ue,numeric:()=>ye,phone:()=>Pe,required:()=>se,sameAs:()=>ke,strongPassword:()=>Ve,url:()=>Le});var se=e=>e==null?!1:typeof e=="boolean"?e:String(e).trim()!=="",ie=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,ae=e=>e?ie.test(String(e)):!0,oe=(e,r=[])=>{if(e==null||e==="")return!0;if(!r[0])return console.error("[Ctrovalidate] Missing parameter for 'min' rule."),!1;const t=Number(r[0]);return Number(e)>=t},le=(e,r=[])=>{if(e==null||e==="")return!0;if(!r[0])return console.error("[Ctrovalidate] Missing parameter for 'max' rule."),!1;const t=Number(r[0]);return Number(e)<=t},ue=(e,r=[])=>{if(e==null||e==="")return!0;if(!r[0])return console.error("[Ctrovalidate] Missing parameter for 'minLength' rule."),!1;const t=Number(r[0]);return String(e).length>=t},de=(e,r=[])=>{if(e==null||e==="")return!0;if(!r[0])return console.error("[Ctrovalidate] Missing parameter for 'maxLength' rule."),!1;const t=Number(r[0]);return String(e).length<=t},ce=/^[a-zA-Z]+$/,fe=e=>e?ce.test(String(e)):!0,ge=/^[a-zA-Z0-9]+$/,he=e=>e?ge.test(String(e)):!0,pe=/^[a-zA-Z0-9-_]+$/,me=e=>e?pe.test(String(e)):!0,be=/^[a-zA-Z\s]+$/,ve=e=>e?be.test(String(e)):!0,ye=e=>!e&&e!==0?!0:!isNaN(Number(e))&&!isNaN(parseFloat(String(e))),Ae=/^-?\d+$/,xe=e=>!e&&e!==0?!0:Ae.test(String(e)),we=/^-?\d+(\.\d+)?$/,Se=e=>!e&&e!==0?!0:we.test(String(e)),Ne=/^(https?:\/\/)([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/,Le=e=>e?Ne.test(String(e)):!0,_e=/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,$e=/^(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$/,Fe=e=>{if(!e)return!0;const r=String(e);return _e.test(r)||$e.test(r)},Ce=e=>{if(!e)return!0;try{const r=JSON.parse(String(e));return typeof r=="object"&&r!==null}catch{return!1}},Re=/^[+]?([(]?[0-9]{1,4}[)]?)[-\s.]?[0-9]{3,4}[-\s.]?[0-9]{4,6}$/,Pe=e=>e?Re.test(String(e)):!0,Me=e=>{if(!e)return!0;const r=String(e).replace(/[- ]/g,"");if(!/^\d+$/.test(r))return!1;let t=0;const i=r.length%2;for(let n=0;n<r.length;n++){let a=parseInt(r[n],10);n%2===i&&(a*=2,a>9&&(a-=9)),t+=a}return t%10===0},Te=/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/,Ve=e=>e?Te.test(String(e)):!0,Oe=(e,r=[])=>{if(e==null||e==="")return!0;if(!r[0])return console.error("[Ctrovalidate] Missing parameter for 'exactLength' rule."),!1;const t=Number(r[0]);return String(e).length===t},ze=(e,r=[])=>{if(e==null||e==="")return!0;if(r.length<2)return console.error("[Ctrovalidate] Missing parameters for 'between' rule."),!1;const t=Number(r[0]),i=Number(r[1]);if(isNaN(t)||isNaN(i))return!1;if(!isNaN(Number(e))&&typeof e!="string"){const l=Number(e);return l>=t&&l<=i}const n=String(e);if(!isNaN(Number(n))&&n!==""){const l=Number(n);return l>=t&&l<=i}const a=n.length;return a>=t&&a<=i},ke=(e,r=[])=>{if(r.length===0||r[0]===void 0)return console.error("[Ctrovalidate] Missing parameter for 'sameAs' rule."),!1;const t=r[0];return e===t},je={required:"This field is required.",email:"Please enter a valid email address.",min:"Minimum value is {0}.",max:"Maximum value is {0}.",minLength:"Minimum length is {0} characters.",maxLength:"Maximum length is {0} characters.",alpha:"This field may only contain alphabetic characters.",alphaNum:"This field may only contain alpha-numeric characters.",alphaDash:"This field may only contain alpha-numeric characters as well as dashes and underscores.",alphaSpaces:"This field may only contain alphabetic characters and spaces.",numeric:"This field must be a number.",integer:"This field must be an integer.",decimal:"This field must be a decimal number.",url:"Please enter a valid URL.",ipAddress:"Please enter a valid IP address.",json:"Please enter a valid JSON string.",phone:"Please enter a valid phone number.",creditCard:"Please enter a valid credit card number.",strongPassword:"Password must be at least 8 characters long and include an uppercase letter, a lowercase letter, a number, and a symbol.",exactLength:"This field must be exactly {0} characters long.",between:"This field must be between {0} and {1}.",sameAs:"This field must match {0}."},x,S,Ee=class{constructor(){O(this,x,{en:je}),O(this,S,"en")}setLocale(e){if(!A(this,x)[e]){console.warn(`[Ctrovalidate] Locale "${e}" not found. Falling back to "en".`),z(this,S,"en");return}z(this,S,e)}addMessages(e,r){A(this,x)[e]={...A(this,x)[e]||{},...r}}translate(e,r=[],t){const i=t||A(this,S),n=A(this,x)[i]||A(this,x).en;return(n[e]||n.default||"Invalid input.").replace(/{(\d+)}/g,(l,c)=>{const d=parseInt(c,10);return r[d]!==void 0?String(r[d]):l})}get currentLocale(){return A(this,S)}};x=new WeakMap;S=new WeakMap;var qe=new Ee;async function De(e,r,t={}){const{customRules:i={},aliases:n={},messages:a={},locale:l,signal:c}=t,d=Z(r,n),o={...B,...i};for(const g of d){const h=o[g.name];if(!h)continue;if(!await h(e,g.params,null,c))return{isValid:!1,error:a[g.name]||a["*"]||qe.translate(g.name,g.params,l),rule:g.name}}return{isValid:!0,error:null,rule:null}}async function j(e,r,t={}){const i={};for(const n in r)i[n]=await De(e[n],r[n],t);return i}function Ie({schema:e,initialValues:r={},validateOnBlur:t=!0,validateOnChange:i=!0,customRules:n={},aliases:a={},messages:l={},locale:c}){const d=$({...r}),o=$(Object.keys(e).reduce((s,f)=>(s[f]=void 0,s),{})),g=$(Object.keys(e).reduce((s,f)=>(s[f]=!1,s),{})),h=$(Object.keys(e).reduce((s,f)=>(s[f]=!1,s),{})),L=Y(o,s=>!Object.values(s).some(f=>!!f)),v={};H.onDestroy(()=>{Object.values(v).forEach(s=>s.abort())});async function m(s,f){var y;const p=e[s];if(!p)return!0;v[s]&&v[s].abort(),v[s]=new AbortController,h.update(u=>({...u,[s]:!0}));try{const u=V(d),b=f!==void 0?f:u[s],T=(y=(await j({[s]:b},{[s]:p},{customRules:n,aliases:a,messages:l,locale:c,signal:v[s].signal}))[s])==null?void 0:y.error;return o.update(U=>({...U,[s]:T||void 0})),!T}catch(u){return u instanceof Error&&u.name==="AbortError"||ne.error(`Validation failed for ${String(s)}:`,u),!1}finally{h.update(u=>({...u,[s]:!1}))}}async function _(){const s=V(d),f=await j(s,e,{customRules:n,aliases:a,messages:l,locale:c}),p={};let y=!0;return Object.keys(e).forEach(u=>{var C;const b=(C=f[u])==null?void 0:C.error;p[u]=b||void 0,b&&(y=!1)}),o.set(p),y}function F(s){d.set({...r,...s});const f=Object.keys(e).reduce((u,b)=>(u[b]=void 0,u),{}),p=Object.keys(e).reduce((u,b)=>(u[b]=!1,u),{}),y=Object.keys(e).reduce((u,b)=>(u[b]=!1,u),{});o.set(f),g.set(p),h.set(y)}function J(s,f){d.update(p=>({...p,[s]:f})),g.update(p=>({...p,[s]:!0})),i&&m(s)}function G(s){g.update(f=>({...f,[s]:!0})),t&&m(s)}return{values:d,errors:o,isDirty:g,isValidating:h,isValid:L,validateField:m,validateForm:_,reset:F,handleChange:J,handleBlur:G}}exports.useCtrovalidate=Ie;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { AsyncRuleLogic } from 'ctrovalidate-core';
|
|
2
|
+
import { Readable } from 'svelte/store';
|
|
3
|
+
import { RuleLogic } from 'ctrovalidate-core';
|
|
4
|
+
import { SchemaRule } from 'ctrovalidate-core';
|
|
5
|
+
import { ValidationSchema } from 'ctrovalidate-core';
|
|
6
|
+
import { Writable } from 'svelte/store';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* useCtrovalidate for Svelte.
|
|
10
|
+
* Provides reactive stores for form validation state.
|
|
11
|
+
*/
|
|
12
|
+
export declare function useCtrovalidate<T extends object>({ schema, initialValues, validateOnBlur, validateOnChange, customRules, aliases, messages, locale, }: UseCtrovalidateOptions<T>): {
|
|
13
|
+
values: Writable<T>;
|
|
14
|
+
errors: Writable<Partial<Record<keyof T, string>>>;
|
|
15
|
+
isDirty: Writable<Partial<Record<keyof T, boolean>>>;
|
|
16
|
+
isValidating: Writable<Partial<Record<keyof T, boolean>>>;
|
|
17
|
+
isValid: Readable<boolean>;
|
|
18
|
+
validateField: (name: keyof T, value?: T[keyof T]) => Promise<boolean>;
|
|
19
|
+
validateForm: () => Promise<boolean>;
|
|
20
|
+
reset: (newValues?: Partial<T>) => void;
|
|
21
|
+
handleChange: (name: keyof T, value: T[keyof T]) => void;
|
|
22
|
+
handleBlur: (name: keyof T) => void;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export declare interface UseCtrovalidateOptions<T extends object> {
|
|
26
|
+
schema: ValidationSchema;
|
|
27
|
+
initialValues?: T;
|
|
28
|
+
validateOnBlur?: boolean;
|
|
29
|
+
validateOnChange?: boolean;
|
|
30
|
+
customRules?: Record<string, RuleLogic | AsyncRuleLogic>;
|
|
31
|
+
aliases?: Record<string, SchemaRule>;
|
|
32
|
+
messages?: Record<string, string>;
|
|
33
|
+
locale?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { }
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
import { onDestroy as H } from "svelte";
|
|
2
|
+
const S = () => {
|
|
3
|
+
};
|
|
4
|
+
function K(e) {
|
|
5
|
+
for (var r = 0; r < e.length; r++)
|
|
6
|
+
e[r]();
|
|
7
|
+
}
|
|
8
|
+
function Q(e, r) {
|
|
9
|
+
return e != e ? r == r : e !== r || e !== null && typeof e == "object" || typeof e == "function";
|
|
10
|
+
}
|
|
11
|
+
function j(e, r, t) {
|
|
12
|
+
if (e == null)
|
|
13
|
+
return r(void 0), t && t(void 0), S;
|
|
14
|
+
const i = ee(
|
|
15
|
+
() => e.subscribe(
|
|
16
|
+
r,
|
|
17
|
+
// @ts-expect-error
|
|
18
|
+
t
|
|
19
|
+
)
|
|
20
|
+
);
|
|
21
|
+
return i.unsubscribe ? () => i.unsubscribe() : i;
|
|
22
|
+
}
|
|
23
|
+
const w = [];
|
|
24
|
+
function X(e, r) {
|
|
25
|
+
return {
|
|
26
|
+
subscribe: $(e, r).subscribe
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function $(e, r = S) {
|
|
30
|
+
let t = null;
|
|
31
|
+
const i = /* @__PURE__ */ new Set();
|
|
32
|
+
function n(c) {
|
|
33
|
+
if (Q(e, c) && (e = c, t)) {
|
|
34
|
+
const d = !w.length;
|
|
35
|
+
for (const o of i)
|
|
36
|
+
o[1](), w.push(o, e);
|
|
37
|
+
if (d) {
|
|
38
|
+
for (let o = 0; o < w.length; o += 2)
|
|
39
|
+
w[o][0](w[o + 1]);
|
|
40
|
+
w.length = 0;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function a(c) {
|
|
45
|
+
n(c(
|
|
46
|
+
/** @type {T} */
|
|
47
|
+
e
|
|
48
|
+
));
|
|
49
|
+
}
|
|
50
|
+
function l(c, d = S) {
|
|
51
|
+
const o = [c, d];
|
|
52
|
+
return i.add(o), i.size === 1 && (t = r(n, a) || S), c(
|
|
53
|
+
/** @type {T} */
|
|
54
|
+
e
|
|
55
|
+
), () => {
|
|
56
|
+
i.delete(o), i.size === 0 && t && (t(), t = null);
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return { set: n, update: a, subscribe: l };
|
|
60
|
+
}
|
|
61
|
+
function Y(e, r, t) {
|
|
62
|
+
const i = !Array.isArray(e), n = i ? [e] : e;
|
|
63
|
+
if (!n.every(Boolean))
|
|
64
|
+
throw new Error("derived() expects stores as input, got a falsy value");
|
|
65
|
+
const a = r.length < 2;
|
|
66
|
+
return X(t, (l, c) => {
|
|
67
|
+
let d = !1;
|
|
68
|
+
const o = [];
|
|
69
|
+
let g = 0, h = S;
|
|
70
|
+
const L = () => {
|
|
71
|
+
if (g)
|
|
72
|
+
return;
|
|
73
|
+
h();
|
|
74
|
+
const m = r(i ? o[0] : o, l, c);
|
|
75
|
+
a ? l(m) : h = typeof m == "function" ? m : S;
|
|
76
|
+
}, v = n.map(
|
|
77
|
+
(m, _) => j(
|
|
78
|
+
m,
|
|
79
|
+
(F) => {
|
|
80
|
+
o[_] = F, g &= ~(1 << _), d && L();
|
|
81
|
+
},
|
|
82
|
+
() => {
|
|
83
|
+
g |= 1 << _;
|
|
84
|
+
}
|
|
85
|
+
)
|
|
86
|
+
);
|
|
87
|
+
return d = !0, L(), function() {
|
|
88
|
+
K(v), h(), d = !1;
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
function T(e) {
|
|
93
|
+
let r;
|
|
94
|
+
return j(e, (t) => r = t)(), r;
|
|
95
|
+
}
|
|
96
|
+
let R = !1;
|
|
97
|
+
function ee(e) {
|
|
98
|
+
var r = R;
|
|
99
|
+
try {
|
|
100
|
+
return R = !0, e();
|
|
101
|
+
} finally {
|
|
102
|
+
R = r;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
var q = Object.defineProperty, D = (e) => {
|
|
106
|
+
throw TypeError(e);
|
|
107
|
+
}, re = (e, r, t) => r in e ? q(e, r, { enumerable: !0, configurable: !0, writable: !0, value: t }) : e[r] = t, te = (e, r) => {
|
|
108
|
+
for (var t in r)
|
|
109
|
+
q(e, t, { get: r[t], enumerable: !0 });
|
|
110
|
+
}, P = (e, r, t) => re(e, typeof r != "symbol" ? r + "" : r, t), I = (e, r, t) => r.has(e) || D("Cannot " + t), x = (e, r, t) => (I(e, r, "read from private field"), t ? t.call(e) : r.get(e)), z = (e, r, t) => r.has(e) ? D("Cannot add the same private member more than once") : r instanceof WeakSet ? r.add(e) : r.set(e, t), O = (e, r, t, i) => (I(e, r, "write to private field"), r.set(e, t), t);
|
|
111
|
+
function k(e) {
|
|
112
|
+
if (!e || typeof e != "string")
|
|
113
|
+
return [];
|
|
114
|
+
const r = [], t = e.split("|");
|
|
115
|
+
for (const i of t) {
|
|
116
|
+
const n = i.trim();
|
|
117
|
+
if (n === "")
|
|
118
|
+
continue;
|
|
119
|
+
const a = n.indexOf(":");
|
|
120
|
+
if (a === -1)
|
|
121
|
+
r.push({ name: n, params: [] });
|
|
122
|
+
else {
|
|
123
|
+
const l = n.substring(0, a).trim(), c = n.substring(a + 1).trim();
|
|
124
|
+
if (l) {
|
|
125
|
+
const d = c.split(",").map((o) => o.trim());
|
|
126
|
+
r.push({ name: l, params: d });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return r;
|
|
131
|
+
}
|
|
132
|
+
function Z(e, r = {}, t = /* @__PURE__ */ new Set()) {
|
|
133
|
+
if (!e) return [];
|
|
134
|
+
let i;
|
|
135
|
+
if (typeof e == "string")
|
|
136
|
+
i = k(e);
|
|
137
|
+
else if (Array.isArray(e))
|
|
138
|
+
i = e;
|
|
139
|
+
else
|
|
140
|
+
return [];
|
|
141
|
+
return i.flatMap((n) => {
|
|
142
|
+
const a = typeof n == "string" ? n.split(":")[0] : n.name;
|
|
143
|
+
if (r[a] && !t.has(a)) {
|
|
144
|
+
const l = new Set(t);
|
|
145
|
+
return l.add(a), Z(r[a], r, l);
|
|
146
|
+
}
|
|
147
|
+
return typeof n == "string" ? k(n) : [n];
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
var M = class W {
|
|
151
|
+
constructor(r = 0) {
|
|
152
|
+
P(this, "level"), this.level = r;
|
|
153
|
+
}
|
|
154
|
+
setLevel(r) {
|
|
155
|
+
this.level = r;
|
|
156
|
+
}
|
|
157
|
+
static setLevel(r) {
|
|
158
|
+
this.globalLevel = r;
|
|
159
|
+
}
|
|
160
|
+
format(r) {
|
|
161
|
+
return `${W.prefix} ${r}`;
|
|
162
|
+
}
|
|
163
|
+
// Instance methods
|
|
164
|
+
error(r, ...t) {
|
|
165
|
+
this.level >= 1 && console.error(this.format(r), ...t);
|
|
166
|
+
}
|
|
167
|
+
warn(r, ...t) {
|
|
168
|
+
this.level >= 2 && console.warn(this.format(r), ...t);
|
|
169
|
+
}
|
|
170
|
+
info(r, ...t) {
|
|
171
|
+
this.level >= 3 && console.info(this.format(r), ...t);
|
|
172
|
+
}
|
|
173
|
+
debug(r, ...t) {
|
|
174
|
+
this.level >= 4 && console.debug(this.format(r), ...t);
|
|
175
|
+
}
|
|
176
|
+
// Static methods (using global level)
|
|
177
|
+
static error(r, ...t) {
|
|
178
|
+
this.globalLevel >= 1 && console.error(`${this.prefix} ${r}`, ...t);
|
|
179
|
+
}
|
|
180
|
+
static warn(r, ...t) {
|
|
181
|
+
this.globalLevel >= 2 && console.warn(`${this.prefix} ${r}`, ...t);
|
|
182
|
+
}
|
|
183
|
+
static info(r, ...t) {
|
|
184
|
+
this.globalLevel >= 3 && console.info(`${this.prefix} ${r}`, ...t);
|
|
185
|
+
}
|
|
186
|
+
static debug(r, ...t) {
|
|
187
|
+
this.globalLevel >= 4 && console.debug(`${this.prefix} ${r}`, ...t);
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
P(
|
|
191
|
+
M,
|
|
192
|
+
"globalLevel",
|
|
193
|
+
1
|
|
194
|
+
/* ERROR */
|
|
195
|
+
);
|
|
196
|
+
P(M, "prefix", "[Ctrovalidate]");
|
|
197
|
+
var ne = M, B = {};
|
|
198
|
+
te(B, {
|
|
199
|
+
alpha: () => fe,
|
|
200
|
+
alphaDash: () => me,
|
|
201
|
+
alphaNum: () => he,
|
|
202
|
+
alphaSpaces: () => ve,
|
|
203
|
+
between: () => Oe,
|
|
204
|
+
creditCard: () => Me,
|
|
205
|
+
decimal: () => Ne,
|
|
206
|
+
email: () => ae,
|
|
207
|
+
exactLength: () => ze,
|
|
208
|
+
integer: () => Ae,
|
|
209
|
+
ipAddress: () => Fe,
|
|
210
|
+
json: () => Ce,
|
|
211
|
+
max: () => le,
|
|
212
|
+
maxLength: () => de,
|
|
213
|
+
min: () => oe,
|
|
214
|
+
minLength: () => ue,
|
|
215
|
+
numeric: () => ye,
|
|
216
|
+
phone: () => Pe,
|
|
217
|
+
required: () => se,
|
|
218
|
+
sameAs: () => ke,
|
|
219
|
+
strongPassword: () => Te,
|
|
220
|
+
url: () => Le
|
|
221
|
+
});
|
|
222
|
+
var se = (e) => e == null ? !1 : typeof e == "boolean" ? e : String(e).trim() !== "", ie = /^[^\s@]+@[^\s@]+\.[^\s@]+$/, ae = (e) => e ? ie.test(String(e)) : !0, oe = (e, r = []) => {
|
|
223
|
+
if (e == null || e === "") return !0;
|
|
224
|
+
if (!r[0])
|
|
225
|
+
return console.error("[Ctrovalidate] Missing parameter for 'min' rule."), !1;
|
|
226
|
+
const t = Number(r[0]);
|
|
227
|
+
return Number(e) >= t;
|
|
228
|
+
}, le = (e, r = []) => {
|
|
229
|
+
if (e == null || e === "") return !0;
|
|
230
|
+
if (!r[0])
|
|
231
|
+
return console.error("[Ctrovalidate] Missing parameter for 'max' rule."), !1;
|
|
232
|
+
const t = Number(r[0]);
|
|
233
|
+
return Number(e) <= t;
|
|
234
|
+
}, ue = (e, r = []) => {
|
|
235
|
+
if (e == null || e === "") return !0;
|
|
236
|
+
if (!r[0])
|
|
237
|
+
return console.error("[Ctrovalidate] Missing parameter for 'minLength' rule."), !1;
|
|
238
|
+
const t = Number(r[0]);
|
|
239
|
+
return String(e).length >= t;
|
|
240
|
+
}, de = (e, r = []) => {
|
|
241
|
+
if (e == null || e === "") return !0;
|
|
242
|
+
if (!r[0])
|
|
243
|
+
return console.error("[Ctrovalidate] Missing parameter for 'maxLength' rule."), !1;
|
|
244
|
+
const t = Number(r[0]);
|
|
245
|
+
return String(e).length <= t;
|
|
246
|
+
}, ce = /^[a-zA-Z]+$/, fe = (e) => e ? ce.test(String(e)) : !0, ge = /^[a-zA-Z0-9]+$/, he = (e) => e ? ge.test(String(e)) : !0, pe = /^[a-zA-Z0-9-_]+$/, me = (e) => e ? pe.test(String(e)) : !0, be = /^[a-zA-Z\s]+$/, ve = (e) => e ? be.test(String(e)) : !0, ye = (e) => !e && e !== 0 ? !0 : !isNaN(Number(e)) && !isNaN(parseFloat(String(e))), xe = /^-?\d+$/, Ae = (e) => !e && e !== 0 ? !0 : xe.test(String(e)), we = /^-?\d+(\.\d+)?$/, Ne = (e) => !e && e !== 0 ? !0 : we.test(String(e)), Se = /^(https?:\/\/)([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/, Le = (e) => e ? Se.test(String(e)) : !0, _e = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/, $e = /^(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$/, Fe = (e) => {
|
|
247
|
+
if (!e) return !0;
|
|
248
|
+
const r = String(e);
|
|
249
|
+
return _e.test(r) || $e.test(r);
|
|
250
|
+
}, Ce = (e) => {
|
|
251
|
+
if (!e) return !0;
|
|
252
|
+
try {
|
|
253
|
+
const r = JSON.parse(String(e));
|
|
254
|
+
return typeof r == "object" && r !== null;
|
|
255
|
+
} catch {
|
|
256
|
+
return !1;
|
|
257
|
+
}
|
|
258
|
+
}, Re = /^[+]?([(]?[0-9]{1,4}[)]?)[-\s.]?[0-9]{3,4}[-\s.]?[0-9]{4,6}$/, Pe = (e) => e ? Re.test(String(e)) : !0, Me = (e) => {
|
|
259
|
+
if (!e) return !0;
|
|
260
|
+
const r = String(e).replace(/[- ]/g, "");
|
|
261
|
+
if (!/^\d+$/.test(r)) return !1;
|
|
262
|
+
let t = 0;
|
|
263
|
+
const i = r.length % 2;
|
|
264
|
+
for (let n = 0; n < r.length; n++) {
|
|
265
|
+
let a = parseInt(r[n], 10);
|
|
266
|
+
n % 2 === i && (a *= 2, a > 9 && (a -= 9)), t += a;
|
|
267
|
+
}
|
|
268
|
+
return t % 10 === 0;
|
|
269
|
+
}, Ve = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/, Te = (e) => e ? Ve.test(String(e)) : !0, ze = (e, r = []) => {
|
|
270
|
+
if (e == null || e === "") return !0;
|
|
271
|
+
if (!r[0])
|
|
272
|
+
return console.error("[Ctrovalidate] Missing parameter for 'exactLength' rule."), !1;
|
|
273
|
+
const t = Number(r[0]);
|
|
274
|
+
return String(e).length === t;
|
|
275
|
+
}, Oe = (e, r = []) => {
|
|
276
|
+
if (e == null || e === "") return !0;
|
|
277
|
+
if (r.length < 2)
|
|
278
|
+
return console.error("[Ctrovalidate] Missing parameters for 'between' rule."), !1;
|
|
279
|
+
const t = Number(r[0]), i = Number(r[1]);
|
|
280
|
+
if (isNaN(t) || isNaN(i))
|
|
281
|
+
return !1;
|
|
282
|
+
if (!isNaN(Number(e)) && typeof e != "string") {
|
|
283
|
+
const l = Number(e);
|
|
284
|
+
return l >= t && l <= i;
|
|
285
|
+
}
|
|
286
|
+
const n = String(e);
|
|
287
|
+
if (!isNaN(Number(n)) && n !== "") {
|
|
288
|
+
const l = Number(n);
|
|
289
|
+
return l >= t && l <= i;
|
|
290
|
+
}
|
|
291
|
+
const a = n.length;
|
|
292
|
+
return a >= t && a <= i;
|
|
293
|
+
}, ke = (e, r = []) => {
|
|
294
|
+
if (r.length === 0 || r[0] === void 0)
|
|
295
|
+
return console.error("[Ctrovalidate] Missing parameter for 'sameAs' rule."), !1;
|
|
296
|
+
const t = r[0];
|
|
297
|
+
return e === t;
|
|
298
|
+
}, Ee = {
|
|
299
|
+
required: "This field is required.",
|
|
300
|
+
email: "Please enter a valid email address.",
|
|
301
|
+
min: "Minimum value is {0}.",
|
|
302
|
+
max: "Maximum value is {0}.",
|
|
303
|
+
minLength: "Minimum length is {0} characters.",
|
|
304
|
+
maxLength: "Maximum length is {0} characters.",
|
|
305
|
+
alpha: "This field may only contain alphabetic characters.",
|
|
306
|
+
alphaNum: "This field may only contain alpha-numeric characters.",
|
|
307
|
+
alphaDash: "This field may only contain alpha-numeric characters as well as dashes and underscores.",
|
|
308
|
+
alphaSpaces: "This field may only contain alphabetic characters and spaces.",
|
|
309
|
+
numeric: "This field must be a number.",
|
|
310
|
+
integer: "This field must be an integer.",
|
|
311
|
+
decimal: "This field must be a decimal number.",
|
|
312
|
+
url: "Please enter a valid URL.",
|
|
313
|
+
ipAddress: "Please enter a valid IP address.",
|
|
314
|
+
json: "Please enter a valid JSON string.",
|
|
315
|
+
phone: "Please enter a valid phone number.",
|
|
316
|
+
creditCard: "Please enter a valid credit card number.",
|
|
317
|
+
strongPassword: "Password must be at least 8 characters long and include an uppercase letter, a lowercase letter, a number, and a symbol.",
|
|
318
|
+
exactLength: "This field must be exactly {0} characters long.",
|
|
319
|
+
between: "This field must be between {0} and {1}.",
|
|
320
|
+
sameAs: "This field must match {0}."
|
|
321
|
+
}, A, N, je = class {
|
|
322
|
+
constructor() {
|
|
323
|
+
z(this, A, { en: Ee }), z(this, N, "en");
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Set the current locale.
|
|
327
|
+
*/
|
|
328
|
+
setLocale(e) {
|
|
329
|
+
if (!x(this, A)[e]) {
|
|
330
|
+
console.warn(
|
|
331
|
+
`[Ctrovalidate] Locale "${e}" not found. Falling back to "en".`
|
|
332
|
+
), O(this, N, "en");
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
O(this, N, e);
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Add or update messages for a specific locale.
|
|
339
|
+
*/
|
|
340
|
+
addMessages(e, r) {
|
|
341
|
+
x(this, A)[e] = {
|
|
342
|
+
...x(this, A)[e] || {},
|
|
343
|
+
...r
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Translates a rule name with optional parameters.
|
|
348
|
+
*/
|
|
349
|
+
translate(e, r = [], t) {
|
|
350
|
+
const i = t || x(this, N), n = x(this, A)[i] || x(this, A).en;
|
|
351
|
+
return (n[e] || n.default || "Invalid input.").replace(/{(\d+)}/g, (l, c) => {
|
|
352
|
+
const d = parseInt(c, 10);
|
|
353
|
+
return r[d] !== void 0 ? String(r[d]) : l;
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Get the current active locale.
|
|
358
|
+
*/
|
|
359
|
+
get currentLocale() {
|
|
360
|
+
return x(this, N);
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
A = /* @__PURE__ */ new WeakMap();
|
|
364
|
+
N = /* @__PURE__ */ new WeakMap();
|
|
365
|
+
var qe = new je();
|
|
366
|
+
async function De(e, r, t = {}) {
|
|
367
|
+
const {
|
|
368
|
+
customRules: i = {},
|
|
369
|
+
aliases: n = {},
|
|
370
|
+
messages: a = {},
|
|
371
|
+
locale: l,
|
|
372
|
+
signal: c
|
|
373
|
+
} = t, d = Z(r, n), o = {
|
|
374
|
+
...B,
|
|
375
|
+
...i
|
|
376
|
+
};
|
|
377
|
+
for (const g of d) {
|
|
378
|
+
const h = o[g.name];
|
|
379
|
+
if (!h)
|
|
380
|
+
continue;
|
|
381
|
+
if (!await h(e, g.params, null, c))
|
|
382
|
+
return {
|
|
383
|
+
isValid: !1,
|
|
384
|
+
error: a[g.name] || a["*"] || qe.translate(g.name, g.params, l),
|
|
385
|
+
rule: g.name
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
return {
|
|
389
|
+
isValid: !0,
|
|
390
|
+
error: null,
|
|
391
|
+
rule: null
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
async function E(e, r, t = {}) {
|
|
395
|
+
const i = {};
|
|
396
|
+
for (const n in r)
|
|
397
|
+
i[n] = await De(
|
|
398
|
+
e[n],
|
|
399
|
+
r[n],
|
|
400
|
+
t
|
|
401
|
+
);
|
|
402
|
+
return i;
|
|
403
|
+
}
|
|
404
|
+
function Ze({
|
|
405
|
+
schema: e,
|
|
406
|
+
initialValues: r = {},
|
|
407
|
+
validateOnBlur: t = !0,
|
|
408
|
+
validateOnChange: i = !0,
|
|
409
|
+
customRules: n = {},
|
|
410
|
+
aliases: a = {},
|
|
411
|
+
messages: l = {},
|
|
412
|
+
locale: c
|
|
413
|
+
}) {
|
|
414
|
+
const d = $({ ...r }), o = $(
|
|
415
|
+
Object.keys(e).reduce(
|
|
416
|
+
(s, f) => (s[f] = void 0, s),
|
|
417
|
+
{}
|
|
418
|
+
)
|
|
419
|
+
), g = $(
|
|
420
|
+
Object.keys(e).reduce(
|
|
421
|
+
(s, f) => (s[f] = !1, s),
|
|
422
|
+
{}
|
|
423
|
+
)
|
|
424
|
+
), h = $(
|
|
425
|
+
Object.keys(e).reduce(
|
|
426
|
+
(s, f) => (s[f] = !1, s),
|
|
427
|
+
{}
|
|
428
|
+
)
|
|
429
|
+
), L = Y(o, (s) => !Object.values(s).some((f) => !!f)), v = {};
|
|
430
|
+
H(() => {
|
|
431
|
+
Object.values(v).forEach((s) => s.abort());
|
|
432
|
+
});
|
|
433
|
+
async function m(s, f) {
|
|
434
|
+
var y;
|
|
435
|
+
const p = e[s];
|
|
436
|
+
if (!p) return !0;
|
|
437
|
+
v[s] && v[s].abort(), v[s] = new AbortController(), h.update((u) => ({ ...u, [s]: !0 }));
|
|
438
|
+
try {
|
|
439
|
+
const u = T(d), b = f !== void 0 ? f : u[s], V = (y = (await E(
|
|
440
|
+
{ [s]: b },
|
|
441
|
+
{ [s]: p },
|
|
442
|
+
{
|
|
443
|
+
customRules: n,
|
|
444
|
+
aliases: a,
|
|
445
|
+
messages: l,
|
|
446
|
+
locale: c,
|
|
447
|
+
signal: v[s].signal
|
|
448
|
+
}
|
|
449
|
+
))[s]) == null ? void 0 : y.error;
|
|
450
|
+
return o.update((U) => ({ ...U, [s]: V || void 0 })), !V;
|
|
451
|
+
} catch (u) {
|
|
452
|
+
return u instanceof Error && u.name === "AbortError" || ne.error(`Validation failed for ${String(s)}:`, u), !1;
|
|
453
|
+
} finally {
|
|
454
|
+
h.update((u) => ({ ...u, [s]: !1 }));
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
async function _() {
|
|
458
|
+
const s = T(d), f = await E(s, e, {
|
|
459
|
+
customRules: n,
|
|
460
|
+
aliases: a,
|
|
461
|
+
messages: l,
|
|
462
|
+
locale: c
|
|
463
|
+
}), p = {};
|
|
464
|
+
let y = !0;
|
|
465
|
+
return Object.keys(e).forEach((u) => {
|
|
466
|
+
var C;
|
|
467
|
+
const b = (C = f[u]) == null ? void 0 : C.error;
|
|
468
|
+
p[u] = b || void 0, b && (y = !1);
|
|
469
|
+
}), o.set(p), y;
|
|
470
|
+
}
|
|
471
|
+
function F(s) {
|
|
472
|
+
d.set({ ...r, ...s });
|
|
473
|
+
const f = Object.keys(e).reduce(
|
|
474
|
+
(u, b) => (u[b] = void 0, u),
|
|
475
|
+
{}
|
|
476
|
+
), p = Object.keys(e).reduce(
|
|
477
|
+
(u, b) => (u[b] = !1, u),
|
|
478
|
+
{}
|
|
479
|
+
), y = Object.keys(e).reduce(
|
|
480
|
+
(u, b) => (u[b] = !1, u),
|
|
481
|
+
{}
|
|
482
|
+
);
|
|
483
|
+
o.set(f), g.set(p), h.set(y);
|
|
484
|
+
}
|
|
485
|
+
function J(s, f) {
|
|
486
|
+
d.update((p) => ({ ...p, [s]: f })), g.update((p) => ({ ...p, [s]: !0 })), i && m(s);
|
|
487
|
+
}
|
|
488
|
+
function G(s) {
|
|
489
|
+
g.update((f) => ({ ...f, [s]: !0 })), t && m(s);
|
|
490
|
+
}
|
|
491
|
+
return {
|
|
492
|
+
values: d,
|
|
493
|
+
errors: o,
|
|
494
|
+
isDirty: g,
|
|
495
|
+
isValidating: h,
|
|
496
|
+
isValid: L,
|
|
497
|
+
validateField: m,
|
|
498
|
+
validateForm: _,
|
|
499
|
+
reset: F,
|
|
500
|
+
handleChange: J,
|
|
501
|
+
handleBlur: G
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
export {
|
|
505
|
+
Ze as useCtrovalidate
|
|
506
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ctrovalidate-svelte",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Svelte adapter for Ctrovalidate.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "vite build",
|
|
21
|
+
"test": "vitest run --passWithNoTests",
|
|
22
|
+
"lint": "eslint .",
|
|
23
|
+
"format": "prettier . --check"
|
|
24
|
+
},
|
|
25
|
+
"homepage": "https://ctrovalidate.vercel.app/api/svelte",
|
|
26
|
+
"keywords": [
|
|
27
|
+
"ctrovalidate",
|
|
28
|
+
"validation",
|
|
29
|
+
"form-validation",
|
|
30
|
+
"svelte",
|
|
31
|
+
"sveltekit"
|
|
32
|
+
],
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/ctrotech-tutor/ctrovalidate-svelte.git"
|
|
36
|
+
},
|
|
37
|
+
"bugs": {
|
|
38
|
+
"url": "https://github.com/ctrotech-tutor/ctrovalidate-svelte/issues"
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"svelte": ">=3.0.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@eslint/js": "^9.39.2",
|
|
48
|
+
"ctrovalidate-core": "^1.0.0",
|
|
49
|
+
"eslint": "^9.39.2",
|
|
50
|
+
"eslint-config-prettier": "^9.1.0",
|
|
51
|
+
"globals": "^17.2.0",
|
|
52
|
+
"prettier": "^3.1.1",
|
|
53
|
+
"vite": "^6.0.0",
|
|
54
|
+
"vite-plugin-dts": "^4.0.0",
|
|
55
|
+
"typescript": "^5.9.3",
|
|
56
|
+
"typescript-eslint": "^8.54.0",
|
|
57
|
+
"vitest": "^4.0.18"
|
|
58
|
+
},
|
|
59
|
+
"author": "Ctrotech (https://github.com/ctrotech-tutor)",
|
|
60
|
+
"license": "MIT"
|
|
61
|
+
}
|