@goodie-forms/core 1.0.0-alpha → 1.1.1-alpha

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 (52) hide show
  1. package/dist/index.js +757 -646
  2. package/dist/index.js.map +1 -1
  3. package/dist/src/form/CustomValidation.d.ts +10 -0
  4. package/dist/src/form/CustomValidation.d.ts.map +1 -0
  5. package/dist/src/form/Field.d.ts +31 -0
  6. package/dist/src/form/Field.d.ts.map +1 -0
  7. package/dist/src/form/FormController.d.ts +68 -0
  8. package/dist/src/form/FormController.d.ts.map +1 -0
  9. package/dist/{form → src/form}/FormField.d.ts +6 -3
  10. package/dist/src/form/FormField.d.ts.map +1 -0
  11. package/dist/src/form/NonullFormField.d.ts +10 -0
  12. package/dist/src/form/NonullFormField.d.ts.map +1 -0
  13. package/dist/src/index.d.ts +6 -0
  14. package/dist/src/index.d.ts.map +1 -0
  15. package/dist/src/types/DeepPartial.d.ts +6 -0
  16. package/dist/src/types/DeepPartial.d.ts.map +1 -0
  17. package/dist/src/types/Mixin.d.ts +2 -0
  18. package/dist/src/types/Mixin.d.ts.map +1 -0
  19. package/dist/src/utils/ensureImmerability.d.ts +2 -0
  20. package/dist/src/utils/ensureImmerability.d.ts.map +1 -0
  21. package/dist/src/utils/getId.d.ts.map +1 -0
  22. package/dist/src/utils/removeBy.d.ts.map +1 -0
  23. package/dist/test/test1.d.ts +2 -0
  24. package/dist/test/test1.d.ts.map +1 -0
  25. package/package.json +27 -27
  26. package/src/form/CustomValidation.ts +52 -0
  27. package/src/form/Field.ts +334 -194
  28. package/src/form/FormController.ts +310 -290
  29. package/src/form/FormField.ts +202 -199
  30. package/src/form/NonullFormField.ts +21 -0
  31. package/src/index.ts +5 -3
  32. package/src/types/DeepPartial.ts +7 -3
  33. package/src/types/Mixin.ts +2 -0
  34. package/src/utils/ensureImmerability.ts +30 -0
  35. package/src/utils/getId.ts +5 -5
  36. package/src/utils/removeBy.ts +11 -11
  37. package/test/test1.ts +52 -0
  38. package/tsconfig.json +7 -7
  39. package/vite.config.ts +18 -18
  40. package/dist/form/Field.d.ts +0 -17
  41. package/dist/form/Field.d.ts.map +0 -1
  42. package/dist/form/FormController.d.ts +0 -62
  43. package/dist/form/FormController.d.ts.map +0 -1
  44. package/dist/form/FormField.d.ts.map +0 -1
  45. package/dist/index.d.ts +0 -4
  46. package/dist/index.d.ts.map +0 -1
  47. package/dist/types/DeepPartial.d.ts +0 -4
  48. package/dist/types/DeepPartial.d.ts.map +0 -1
  49. package/dist/utils/getId.d.ts.map +0 -1
  50. package/dist/utils/removeBy.d.ts.map +0 -1
  51. /package/dist/{utils → src/utils}/getId.d.ts +0 -0
  52. /package/dist/{utils → src/utils}/removeBy.d.ts +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormController.d.ts","sourceRoot":"","sources":["../../../src/form/FormController.ts"],"names":[],"mappings":"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"}
@@ -7,8 +7,12 @@ export declare class FormField<TShape extends object, TPath extends Field.Paths<
7
7
  protected target?: HTMLElement;
8
8
  protected _isTouched: boolean;
9
9
  protected _isDirty: boolean;
10
- constructor(controller: FormController<TShape>, path: TPath);
10
+ constructor(controller: FormController<TShape>, path: TPath, initialState?: {
11
+ isTouched?: boolean;
12
+ isDirty?: boolean;
13
+ });
11
14
  get value(): Field.GetValue<TShape, TPath> | undefined;
15
+ get initialValue(): Field.GetValue<TShape, TPath> | undefined;
12
16
  get boundElement(): HTMLElement | undefined;
13
17
  get issues(): import("@standard-schema/spec").StandardSchemaV1.Issue[];
14
18
  get isTouched(): boolean;
@@ -17,9 +21,8 @@ export declare class FormField<TShape extends object, TPath extends Field.Paths<
17
21
  protected _setTouched(isTouched: boolean): void;
18
22
  protected _setDirty(isDirty: boolean): void;
19
23
  bindElement(el: HTMLElement | undefined): void;
20
- protected static ensureImmerability(value: any): void;
21
24
  setValue(value: Field.GetValue<TShape, TPath>, opts?: Parameters<typeof this.modifyValue>[1]): void;
22
- modifyValue(modifier: (currentValue: Field.GetValue<TShape, TPath>, field: this) => Field.GetValue<TShape, TPath> | void, opts?: {
25
+ modifyValue(modifier: (currentValue: Field.GetValue<TShape, TPath> | undefined) => Field.GetValue<TShape, TPath> | void, opts?: {
23
26
  shouldTouch?: boolean;
24
27
  shouldMarkDirty?: boolean;
25
28
  }): void;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormField.d.ts","sourceRoot":"","sources":["../../../src/form/FormField.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,qBAAa,SAAS,CACpB,MAAM,SAAS,MAAM,EACrB,KAAK,SAAS,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;aAUf,UAAU,EAAE,cAAc,CAAC,MAAM,CAAC;aAClC,IAAI,EAAE,KAAK;IAT7B,SAAgB,EAAE,SAAW;IAE7B,SAAS,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAE/B,SAAS,CAAC,UAAU,UAAS;IAC7B,SAAS,CAAC,QAAQ,UAAS;gBAGT,UAAU,EAAE,cAAc,CAAC,MAAM,CAAC,EAClC,IAAI,EAAE,KAAK,EAC3B,YAAY,CAAC,EAAE;QACb,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB;IAMH,IAAI,KAAK,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,SAAS,CAKrD;IAED,IAAI,YAAY,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,SAAS,CAK5D;IAED,IAAI,YAAY,4BAEf;IAED,IAAI,MAAM,6DAIT;IAED,IAAI,SAAS,YAEZ;IAED,IAAI,OAAO,YAEV;IAED,IAAI,OAAO,YAEV;IAED,SAAS,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO;IAcxC,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO;IAcpC,WAAW,CAAC,EAAE,EAAE,WAAW,GAAG,SAAS;IAMvC,QAAQ,CACN,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,EACpC,IAAI,CAAC,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAK/C,WAAW,CACT,QAAQ,EAAE,CACR,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,SAAS,KACpD,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,IAAI,EACzC,IAAI,CAAC,EAAE;QACL,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,eAAe,CAAC,EAAE,OAAO,CAAC;KAC3B,GACA,IAAI;IA2DP,KAAK;IAKL,KAAK;IAIL,SAAS;IAKT,iBAAiB;IAIjB,KAAK,CAAC,IAAI,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE;CAUvC"}
@@ -0,0 +1,10 @@
1
+ import { Field } from '../form/Field';
2
+ import { FormField } from '../form/FormField';
3
+ import { Mixin } from '../types/Mixin';
4
+ export type NonnullFormField<TShape extends object, TPath extends Field.Paths<TShape>> = Mixin<FormField<TShape, TPath>, {
5
+ modifyValue: (modifier: (currentValue: Field.GetValue<TShape, TPath>) => Field.GetValue<TShape, TPath> | void, opts?: {
6
+ shouldTouch?: boolean;
7
+ shouldMarkDirty?: boolean;
8
+ }) => void;
9
+ }>;
10
+ //# sourceMappingURL=NonullFormField.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NonullFormField.d.ts","sourceRoot":"","sources":["../../../src/form/NonullFormField.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvC,MAAM,MAAM,gBAAgB,CAC1B,MAAM,SAAS,MAAM,EACrB,KAAK,SAAS,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,IAC/B,KAAK,CACP,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,EACxB;IACE,WAAW,EAAE,CACX,QAAQ,EAAE,CACR,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,KACxC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,IAAI,EACzC,IAAI,CAAC,EAAE;QACL,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,eAAe,CAAC,EAAE,OAAO,CAAC;KAC3B,KACE,IAAI,CAAC;CACX,CACF,CAAC"}
@@ -0,0 +1,6 @@
1
+ export * from './form/Field';
2
+ export * from './form/FormField';
3
+ export * from './form/NonullFormField';
4
+ export * from './form/FormController';
5
+ export * from './form/CustomValidation';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export type DeepPartial<T> = {
2
+ [K in keyof T as T[K] extends (...args: any[]) => any ? K : never]: T[K];
3
+ } & {
4
+ [K in keyof T as T[K] extends (...args: any[]) => any ? never : K]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
5
+ };
6
+ //# sourceMappingURL=DeepPartial.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeepPartial.d.ts","sourceRoot":"","sources":["../../../src/types/DeepPartial.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;KAC1B,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;CACzE,GAAG;KACD,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GACjD,KAAK,GACL,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CACxD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export type Mixin<T extends object, U extends Partial<T>> = Omit<T, keyof U> & U;
2
+ //# sourceMappingURL=Mixin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Mixin.d.ts","sourceRoot":"","sources":["../../../src/types/Mixin.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAC1E,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function ensureImmerability(value: any): void;
2
+ //# sourceMappingURL=ensureImmerability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ensureImmerability.d.ts","sourceRoot":"","sources":["../../../src/utils/ensureImmerability.ts"],"names":[],"mappings":"AAEA,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,GAAG,QA2B5C"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getId.d.ts","sourceRoot":"","sources":["../../../src/utils/getId.ts"],"names":[],"mappings":"AAEA,wBAAgB,KAAK,WAEpB"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"removeBy.d.ts","sourceRoot":"","sources":["../../../src/utils/removeBy.ts"],"names":[],"mappings":"AAAA,wBAAgB,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,QAUpE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=test1.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test1.d.ts","sourceRoot":"","sources":["../../test/test1.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,27 +1,27 @@
1
- {
2
- "name": "@goodie-forms/core",
3
- "version": "1.0.0-alpha",
4
- "type": "module",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "exports": {
8
- ".": {
9
- "types": "./dist/index.d.ts",
10
- "default": "./dist/index.js"
11
- }
12
- },
13
- "scripts": {
14
- "build": "vite build",
15
- "prepublish": "npm run build"
16
- },
17
- "devDependencies": {
18
- "typescript": "^5.9.3",
19
- "vite": "^7.3.1",
20
- "vite-plugin-dts": "^4.5.4"
21
- },
22
- "dependencies": {
23
- "@standard-schema/spec": "^1.1.0",
24
- "immer": "^11.1.3",
25
- "nanoevents": "^9.1.0"
26
- }
27
- }
1
+ {
2
+ "name": "@goodie-forms/core",
3
+ "version": "1.1.1-alpha",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ }
12
+ },
13
+ "scripts": {
14
+ "build": "vite build",
15
+ "prepack": "npm run build"
16
+ },
17
+ "devDependencies": {
18
+ "typescript": "^5.9.3",
19
+ "vite": "^7.3.1",
20
+ "vite-plugin-dts": "^4.5.4"
21
+ },
22
+ "dependencies": {
23
+ "@standard-schema/spec": "^1.1.0",
24
+ "immer": "^11.1.3",
25
+ "nanoevents": "^9.1.0"
26
+ }
27
+ }
@@ -0,0 +1,52 @@
1
+ import { StandardSchemaV1 } from "@standard-schema/spec";
2
+ import { Field } from "../form/Field";
3
+ import { DeepPartial } from "../types/DeepPartial";
4
+
5
+ export type CustomValidationIssue<TShape extends object> = {
6
+ path: Field.Paths<TShape>;
7
+ message: string;
8
+ };
9
+
10
+ export type CustomValidationStrategy<TShape extends object> = (
11
+ data: DeepPartial<TShape>,
12
+ ) =>
13
+ | void
14
+ | CustomValidationIssue<TShape>[]
15
+ | Promise<CustomValidationIssue<TShape>[] | void>;
16
+
17
+ export function customValidation<TShape extends object>(
18
+ strategy: CustomValidationStrategy<TShape>,
19
+ ): StandardSchemaV1<TShape, TShape> {
20
+ return {
21
+ "~standard": {
22
+ version: 1 as const,
23
+
24
+ vendor: "goodie-forms/custom" as const,
25
+
26
+ validate: async (input: unknown) => {
27
+ try {
28
+ const customIssues = await strategy(input as DeepPartial<TShape>);
29
+
30
+ if (customIssues == null) {
31
+ return { value: input as TShape };
32
+ }
33
+
34
+ return {
35
+ issues: customIssues.map((i) => ({
36
+ path: Field.parsePathFragments(i.path),
37
+ message: i.message,
38
+ })),
39
+ };
40
+ } catch (err) {
41
+ return {
42
+ issues: [
43
+ {
44
+ message: err instanceof Error ? err.message : "Unknown error",
45
+ },
46
+ ],
47
+ };
48
+ }
49
+ },
50
+ },
51
+ };
52
+ }