diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts
index 2c4f002..623b3d9 100644
--- a/docs/.vitepress/config.ts
+++ b/docs/.vitepress/config.ts
@@ -46,7 +46,7 @@ const AdvancedUsage: (DefaultTheme.NavItemWithLink | DefaultTheme.NavItemChildre
{ text: 'Using metadata from rules', link: '/advanced-usage/rule-metadata' },
{ text: 'Rules operators', link: '/advanced-usage/rules-operators' },
{ text: 'Validation helpers', link: '/advanced-usage/validations-helpers' },
- { text: 'Usage with Zod', link: '/advanced-usage/usage-with-zod' },
+ { text: 'Async validation', link: '/advanced-usage/async-validation' },
];
const Typescript: (DefaultTheme.NavItemWithLink | DefaultTheme.NavItemChildren)[] = [
@@ -60,6 +60,17 @@ const Typescript: (DefaultTheme.NavItemWithLink | DefaultTheme.NavItemChildren)[
},
];
+const Integrations: (DefaultTheme.NavItemWithLink | DefaultTheme.NavItemChildren)[] = [
+ {
+ text: 'Nuxt',
+ link: '/integrations/nuxt',
+ },
+ {
+ text: 'Zod',
+ link: '/integrations/zod',
+ },
+];
+
const Examples: DefaultTheme.NavItemWithLink[] = [{ text: 'Simple form example', link: '/examples/simple' }];
const Troubleshooting: DefaultTheme.NavItemWithLink[] = [
@@ -95,7 +106,6 @@ export default defineConfig({
text: 'Introduction',
items: [
{ text: 'Getting Started', link: '/introduction/' },
- { text: 'Integrations', link: '/introduction/integrations' },
{ text: 'Comparisons', link: '/introduction/comparisons' },
],
collapsed: false,
@@ -113,17 +123,22 @@ export default defineConfig({
{
text: 'Advanced Usage',
items: AdvancedUsage,
- collapsed: false,
+ collapsed: true,
+ },
+ {
+ text: 'Integrations',
+ items: Integrations,
+ collapsed: true,
},
{
text: 'Examples',
items: Examples,
- collapsed: false,
+ collapsed: true,
},
{
text: 'Troubleshooting',
items: Troubleshooting,
- collapsed: false,
+ collapsed: true,
},
],
socialLinks: [{ icon: 'github', link: 'https://github.com/victorgarciaesgi/regle' }],
diff --git a/docs/.vitepress/theme/custom.scss b/docs/.vitepress/theme/custom.scss
index 63daaaa..140c457 100644
--- a/docs/.vitepress/theme/custom.scss
+++ b/docs/.vitepress/theme/custom.scss
@@ -112,6 +112,10 @@ iframe {
flex-flow: row wrap;
align-items: center;
gap: 8px;
+
+ .delete {
+ cursor: pointer;
+ }
}
}
}
@@ -182,7 +186,7 @@ iframe {
.password-strength {
margin: 8px 8px 0 8px;
- width: 150px;
+ width: 170px;
height: 4px;
border-radius: 4px;
border: 1px solid var(--vp-c-border);
diff --git a/docs/src/advanced-usage/async-validation.md b/docs/src/advanced-usage/async-validation.md
new file mode 100644
index 0000000..898c41d
--- /dev/null
+++ b/docs/src/advanced-usage/async-validation.md
@@ -0,0 +1,8 @@
+---
+title: Async validations
+---
+
+
+# Async validation
+
+TODO
\ No newline at end of file
diff --git a/docs/src/introduction/integrations.md b/docs/src/integrations/nuxt.md
similarity index 66%
rename from docs/src/introduction/integrations.md
rename to docs/src/integrations/nuxt.md
index a797ac4..5f1abca 100644
--- a/docs/src/introduction/integrations.md
+++ b/docs/src/integrations/nuxt.md
@@ -1,11 +1,9 @@
---
-title: Integrations
+title: Nuxt
---
-# Integrations
-
-## Nuxt
+# Nuxt
Adding the Nuxt module enables auto-imports for selected exports.
@@ -58,28 +56,3 @@ The following exports will become globally available in your Nuxt application:
- `@regle/zod` (if present)
- useZodRegle
-
-
-## Zod
-
-Regle offers an adapter for [Zod](https://zod.dev/). You can use any zod object schema to validate your state. It offers the same DX as using `@regle/rules`.
-
-Check [documentation for Zod](/advanced-usage/usage-with-zod)
-
-::: code-group
-```sh [pnpm]
-pnpm add @regle/zod
-```
-
-```sh [npm]
-npm install @regle/zod
-```
-
-```sh [yarn]
-yarn add @regle/zod
-```
-
-```sh [bun]
-bun add @regle/zod
-```
-:::
diff --git a/docs/src/advanced-usage/usage-with-zod.md b/docs/src/integrations/zod.md
similarity index 92%
rename from docs/src/advanced-usage/usage-with-zod.md
rename to docs/src/integrations/zod.md
index f1fb7cd..4ff9fe8 100644
--- a/docs/src/advanced-usage/usage-with-zod.md
+++ b/docs/src/integrations/zod.md
@@ -5,20 +5,17 @@ title: Zod
-# Usage with Zod
-
-## Prerequisites
+# Zod
-- `zod` version `3` or higher.
+Regle offers an adapter for [Zod](https://zod.dev/). You can use any zod object schema to validate your state. It offers the same DX as using `@regle/rules`.
+## Prerequisites
-## Installation
+- `zod` version `3.x`
::: code-group
-
```sh [pnpm]
pnpm add @regle/zod
```
@@ -37,6 +34,7 @@ bun add @regle/zod
:::
+
## Usage
@@ -125,3 +123,4 @@ async function submit() {
}
```
+
diff --git a/docs/src/parts/components/collections/AccessingCurrentItemState.vue b/docs/src/parts/components/collections/AccessingCurrentItemState.vue
index fc548c0..789a39b 100644
--- a/docs/src/parts/components/collections/AccessingCurrentItemState.vue
+++ b/docs/src/parts/components/collections/AccessingCurrentItemState.vue
@@ -14,7 +14,7 @@
-
❌
+ 🗑️
@@ -51,7 +51,9 @@ function shuffle(arr: any[], options?: any) {
var shuffleAll = options && options.shuffleAll;
var result = arr.slice();
- var i = arr.length, rand, temp;
+ var i = arr.length,
+ rand,
+ temp;
while (--i > 0) {
do {
@@ -63,7 +65,7 @@ function shuffle(arr: any[], options?: any) {
result[rand] = temp;
}
}
-
+
return result;
}
diff --git a/docs/src/parts/components/collections/DisplayingCollectionErrors.vue b/docs/src/parts/components/collections/DisplayingCollectionErrors.vue
index 1954c4b..5092e03 100644
--- a/docs/src/parts/components/collections/DisplayingCollectionErrors.vue
+++ b/docs/src/parts/components/collections/DisplayingCollectionErrors.vue
@@ -9,7 +9,7 @@
placeholder="Type an item value"
/>
- ❌
+ 🗑️
@@ -48,7 +48,9 @@ function shuffle(arr: any[], options?: any) {
var shuffleAll = options && options.shuffleAll;
var result = arr.slice();
- var i = arr.length, rand, temp;
+ var i = arr.length,
+ rand,
+ temp;
while (--i > 0) {
do {
@@ -61,7 +63,7 @@ function shuffle(arr: any[], options?: any) {
result[rand] = temp;
}
}
-
+
return result;
}
diff --git a/docs/src/parts/components/collections/ValidatingArray.vue b/docs/src/parts/components/collections/ValidatingArray.vue
index cbd51bc..c1fc24e 100644
--- a/docs/src/parts/components/collections/ValidatingArray.vue
+++ b/docs/src/parts/components/collections/ValidatingArray.vue
@@ -9,7 +9,7 @@
placeholder="Type an item value"
/>
- ❌
+ 🗑️
@@ -25,7 +25,7 @@
{{ error }}
-
+
diff --git a/docs/src/parts/components/modifiers/ExternalErrors.vue b/docs/src/parts/components/modifiers/ExternalErrors.vue
index 0218756..d1f1ebe 100644
--- a/docs/src/parts/components/modifiers/ExternalErrors.vue
+++ b/docs/src/parts/components/modifiers/ExternalErrors.vue
@@ -31,7 +31,7 @@
-
+
diff --git a/docs/src/troubleshooting/reactivity.md b/docs/src/troubleshooting/reactivity.md
index 0349dd8..d16ee07 100644
--- a/docs/src/troubleshooting/reactivity.md
+++ b/docs/src/troubleshooting/reactivity.md
@@ -11,46 +11,49 @@ When using `useRegle` with a getter function or a computed property, Regle autom
To illustrate the issue, consider the following example:
```ts twoslash
-// @noErrors
+const form = ref({
+ items: [] as {weight: number}[]
+})
+//---cut---
import { ref, computed } from 'vue';
import { withMessage } from '@regle/rules';
+import {type Maybe, type RegleComputedRules} from '@regle/core';
const condition = ref(false)
const weight = (greeting: string) => {
- return withMessage(value => {
- return value > 1 && condition.value === true
+ return withMessage((value: Maybe) => {
+ return !!value && value > 1 && condition.value === true
}, `Weight must be greater than 1, ${greeting}`)
}
const rules = computed(() => {
return {
items: {
- $each: item => ({
+ $each: (item) => ({
weight: {
weight: weight('Hello World')
}
})
}
- }
+ } satisfies RegleComputedRules
})
```
In the above example, the `weight` rule depends on the `condition` ref, which is not tracked by Regle because it is inside a function and Vue cannot collect the reference. To fix this, you can either use the `withParams` wrapper or use the `createRule` function which automatically tracks dependencies for you.
```ts twoslash
-// @noErrors
import { ref } from 'vue';
import { withParams, withMessage } from '@regle/rules';
-import { createRule } from '@regle/core';
+import { createRule, type Maybe } from '@regle/core';
const condition = ref(false)
// Usage with `withParams`
const weight1 = (greeting: string) => {
return withMessage(
- withParams(value => {
- return value > 1 && condition.value === true
+ withParams((value: Maybe) => {
+ return !!value && value > 1 && condition.value === true
}, [condition]),
`Weight must be greater than 1, ${greeting}`
)
@@ -58,8 +61,8 @@ const weight1 = (greeting: string) => {
// Usage with `createRule`
const weight2 = createRule({
- validator(value: Maybe, greeting: string, condition: boolean) {
- return value > 1 && condition === true
+ validator(value: Maybe, greeting: string, condition: boolean) {
+ return !!value && value > 1 && condition === true
},
message: ({ $params: [greeting] }) => {
diff --git a/packages/core/src/types/rules/rule.errors.types.ts b/packages/core/src/types/rules/rule.errors.types.ts
index 3bf56e0..1da58ac 100644
--- a/packages/core/src/types/rules/rule.errors.types.ts
+++ b/packages/core/src/types/rules/rule.errors.types.ts
@@ -3,23 +3,30 @@ import type { MaybeRef, UnwrapNestedRefs } from 'vue';
import type { ReglePartialRuleTree } from './rule.declaration.types';
import type { DeepSafeFormState, SafeFieldProperty } from '../core';
import type { ExtendOnlyRealRecord, Maybe, Prettify } from '../utils';
+import type { PartialObjectDeep } from 'type-fest/source/partial-deep';
export type RegleErrorTree | any[]>> = {
readonly [K in keyof UnwrapNestedRefs]: RegleValidationErrors[K]>;
};
-export type RegleExternalErrorTree | any[]> = PartialDeep<
- RegleErrorTree,
- { recurseIntoArrays: true }
->;
+export type RegleExternalErrorTree | any[]>> = {
+ readonly [K in keyof UnwrapNestedRefs]?: RegleValidationErrors[K], true>;
+};
-export type RegleValidationErrors | any[] | unknown = never> =
+export type RegleValidationErrors<
+ TState extends Record | any[] | unknown = never,
+ TExternal extends boolean = false,
+> =
NonNullable extends Array>
- ? RegleCollectionErrors
+ ? TExternal extends false
+ ? RegleCollectionErrors
+ : RegleExternalCollectionErrors
: NonNullable extends Date | File
? string[]
: NonNullable extends Record
- ? RegleErrorTree
+ ? TExternal extends false
+ ? RegleErrorTree
+ : RegleExternalErrorTree
: string[];
export type RegleCollectionErrors> = {
@@ -27,6 +34,11 @@ export type RegleCollectionErrors> = {
readonly $each: RegleValidationErrors[];
};
+export type RegleExternalCollectionErrors> = {
+ readonly $self?: string[];
+ readonly $each?: RegleValidationErrors[];
+};
+
/** @internal */
export type $InternalRegleCollectionErrors = {
readonly $self?: string[];
diff --git a/packages/nuxt/test/nuxt.spec.ts b/packages/nuxt/test/nuxt.spec.ts
index bba0ac7..2269017 100644
--- a/packages/nuxt/test/nuxt.spec.ts
+++ b/packages/nuxt/test/nuxt.spec.ts
@@ -1,7 +1,6 @@
import { describe, it, expect } from 'vitest';
import { fileURLToPath } from 'node:url';
import { setup, $fetch } from '@nuxt/test-utils/e2e';
-import { createResolver } from '@nuxt/kit';
describe('ssr', async () => {
await setup({
diff --git a/playground/vue3/src/App.vue b/playground/vue3/src/App.vue
index 1e39f4c..eb15660 100644
--- a/playground/vue3/src/App.vue
+++ b/playground/vue3/src/App.vue
@@ -6,15 +6,16 @@