@teamnovu/kit-vue-forms 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/PLAN.md +209 -0
  2. package/dist/composables/useField.d.ts +12 -0
  3. package/dist/composables/useFieldRegistry.d.ts +15 -0
  4. package/dist/composables/useForm.d.ts +10 -0
  5. package/dist/composables/useFormState.d.ts +7 -0
  6. package/dist/composables/useSubform.d.ts +5 -0
  7. package/dist/composables/useValidation.d.ts +30 -0
  8. package/dist/index.d.ts +6 -0
  9. package/dist/index.mjs +414 -0
  10. package/dist/types/form.d.ts +41 -0
  11. package/dist/types/util.d.ts +26 -0
  12. package/dist/types/validation.d.ts +16 -0
  13. package/dist/utils/general.d.ts +2 -0
  14. package/dist/utils/path.d.ts +11 -0
  15. package/dist/utils/type-helpers.d.ts +3 -0
  16. package/dist/utils/validation.d.ts +3 -0
  17. package/dist/utils/zod.d.ts +3 -0
  18. package/package.json +41 -0
  19. package/src/composables/useField.ts +74 -0
  20. package/src/composables/useFieldRegistry.ts +53 -0
  21. package/src/composables/useForm.ts +54 -0
  22. package/src/composables/useFormData.ts +16 -0
  23. package/src/composables/useFormState.ts +21 -0
  24. package/src/composables/useSubform.ts +173 -0
  25. package/src/composables/useValidation.ts +227 -0
  26. package/src/index.ts +11 -0
  27. package/src/types/form.ts +58 -0
  28. package/src/types/util.ts +73 -0
  29. package/src/types/validation.ts +22 -0
  30. package/src/utils/general.ts +7 -0
  31. package/src/utils/path.ts +87 -0
  32. package/src/utils/type-helpers.ts +3 -0
  33. package/src/utils/validation.ts +66 -0
  34. package/src/utils/zod.ts +24 -0
  35. package/tests/formState.test.ts +138 -0
  36. package/tests/integration.test.ts +200 -0
  37. package/tests/nestedPath.test.ts +651 -0
  38. package/tests/path-utils.test.ts +159 -0
  39. package/tests/subform.test.ts +1348 -0
  40. package/tests/useField.test.ts +147 -0
  41. package/tests/useForm.test.ts +178 -0
  42. package/tests/useValidation.test.ts +216 -0
  43. package/tsconfig.json +18 -0
  44. package/vite.config.js +39 -0
  45. package/vitest.config.ts +14 -0
@@ -0,0 +1,159 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { joinPath, filterErrorsForPath } from '../src/utils/path'
3
+ import type { ErrorBag } from '../src/types/validation'
4
+
5
+ describe('Path Utilities', () => {
6
+ describe('joinPath', () => {
7
+ it('should join simple paths', () => {
8
+ const result = joinPath('user', 'name')
9
+ expect(result).toBe('user.name')
10
+ })
11
+
12
+ it('should handle empty base path', () => {
13
+ const result = joinPath('', 'name')
14
+ expect(result).toBe('name')
15
+ })
16
+
17
+ it('should handle empty sub path', () => {
18
+ const result = joinPath('user', '')
19
+ expect(result).toBe('user')
20
+ })
21
+
22
+ it('should handle both empty paths', () => {
23
+ const result = joinPath('', '')
24
+ expect(result).toBe('')
25
+ })
26
+
27
+ it('should join nested paths', () => {
28
+ const result = joinPath('user.profile', 'preferences.theme')
29
+ expect(result).toBe('user.profile.preferences.theme')
30
+ })
31
+
32
+ it('should handle paths with array indices', () => {
33
+ const result = joinPath('users.0', 'addresses.1.street')
34
+ expect(result).toBe('users.0.addresses.1.street')
35
+ })
36
+
37
+ it('should handle null or undefined paths', () => {
38
+ expect(joinPath(null as any, 'name')).toBe('name')
39
+ expect(joinPath('user', null as any)).toBe('user')
40
+ expect(joinPath(undefined as any, 'name')).toBe('name')
41
+ expect(joinPath('user', undefined as any)).toBe('user')
42
+ })
43
+ })
44
+
45
+ describe('filterErrorsForPath', () => {
46
+ it('should filter errors for specific path', () => {
47
+ const errors: ErrorBag = {
48
+ general: ['General error'],
49
+ propertyErrors: {
50
+ 'user.name': ['Name required'],
51
+ 'user.email': ['Invalid email'],
52
+ 'company.name': ['Company name required'],
53
+ },
54
+ }
55
+
56
+ const filtered = filterErrorsForPath(errors, 'user')
57
+ expect(filtered.general).toEqual(['General error'])
58
+ expect(filtered.propertyErrors).toEqual({
59
+ name: ['Name required'],
60
+ email: ['Invalid email'],
61
+ })
62
+ })
63
+
64
+ it('should handle nested path filtering', () => {
65
+ const errors: ErrorBag = {
66
+ general: [],
67
+ propertyErrors: {
68
+ 'user.profile.name': ['Name required'],
69
+ 'user.profile.bio': ['Bio too short'],
70
+ 'user.settings.theme': ['Invalid theme'],
71
+ },
72
+ }
73
+
74
+ const filtered = filterErrorsForPath(errors, 'user.profile')
75
+ expect(filtered.propertyErrors).toEqual({
76
+ name: ['Name required'],
77
+ bio: ['Bio too short'],
78
+ })
79
+ })
80
+
81
+ it('should handle paths with no matching errors', () => {
82
+ const errors: ErrorBag = {
83
+ general: ['General error'],
84
+ propertyErrors: {
85
+ 'user.name': ['Name required'],
86
+ 'company.name': ['Company name required'],
87
+ },
88
+ }
89
+
90
+ const filtered = filterErrorsForPath(errors, 'profile')
91
+ expect(filtered.general).toEqual(['General error'])
92
+ expect(filtered.propertyErrors).toEqual({})
93
+ })
94
+
95
+ it('should handle empty error object', () => {
96
+ const errors: ErrorBag = {
97
+ general: [],
98
+ propertyErrors: {},
99
+ }
100
+
101
+ const filtered = filterErrorsForPath(errors, 'user')
102
+ expect(filtered.general).toEqual([])
103
+ expect(filtered.propertyErrors).toEqual({})
104
+ })
105
+
106
+ it('should handle array path filtering', () => {
107
+ const errors: ErrorBag = {
108
+ general: [],
109
+ propertyErrors: {
110
+ 'contacts.0.name': ['Name required'],
111
+ 'contacts.0.email': ['Invalid email'],
112
+ 'contacts.1.name': ['Name required'],
113
+ },
114
+ }
115
+
116
+ const filtered = filterErrorsForPath(errors, 'contacts.0')
117
+ expect(filtered.propertyErrors).toEqual({
118
+ name: ['Name required'],
119
+ email: ['Invalid email'],
120
+ })
121
+ })
122
+
123
+ it('should handle exact path matches', () => {
124
+ const errors: ErrorBag = {
125
+ general: [],
126
+ propertyErrors: {
127
+ 'user': ['User error'],
128
+ 'user.name': ['Name required'],
129
+ 'username': ['Username taken'],
130
+ },
131
+ }
132
+
133
+ const filtered = filterErrorsForPath(errors, 'user')
134
+ expect(filtered.propertyErrors).toEqual({
135
+ name: ['Name required'],
136
+ })
137
+ })
138
+
139
+ it('should handle root path filtering', () => {
140
+ const errors: ErrorBag = {
141
+ general: ['General error'],
142
+ propertyErrors: {
143
+ 'name': ['Name required'],
144
+ 'email': ['Invalid email'],
145
+ 'user.name': ['User name required'],
146
+ },
147
+ }
148
+
149
+ const filtered = filterErrorsForPath(errors, '')
150
+ expect(filtered.general).toEqual(['General error'])
151
+ expect(filtered.propertyErrors).toEqual({
152
+ 'name': ['Name required'],
153
+ 'email': ['Invalid email'],
154
+ 'user.name': ['User name required'],
155
+ })
156
+ })
157
+ })
158
+ })
159
+