@kirill.konshin/react 0.0.1 → 0.0.2
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/.ctirc +19 -10
- package/.turbo/turbo-build.log +12 -31
- package/CHANGELOG.md +8 -0
- package/dist/form/form.d.ts +10 -10
- package/dist/form/form.d.ts.map +1 -1
- package/dist/form/form.js +6 -6
- package/dist/form/form.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/keyboard.d.ts +4 -1
- package/dist/keyboard.d.ts.map +1 -1
- package/dist/keyboard.js +3 -3
- package/dist/keyboard.js.map +1 -1
- package/package.json +2 -2
- package/src/form/form.tsx +22 -22
- package/src/index.ts +1 -1
- package/src/keyboard.tsx +18 -3
package/.ctirc
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
"options": [
|
|
3
|
+
{
|
|
4
|
+
"mode": "create",
|
|
5
|
+
"project": "tsconfig.json",
|
|
6
|
+
"include": "src/**/*.{ts,tsx}",
|
|
7
|
+
"exclude": [
|
|
8
|
+
"**/*.stories.*",
|
|
9
|
+
"**/*.test.*",
|
|
10
|
+
"**/*.fixture.*"
|
|
11
|
+
],
|
|
12
|
+
"startFrom": "src",
|
|
13
|
+
"backup": false,
|
|
14
|
+
"overwrite": true,
|
|
15
|
+
"generationStyle": "default-alias-named-star",
|
|
16
|
+
"output": "src",
|
|
17
|
+
"verbose": true
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,44 +1,25 @@
|
|
|
1
1
|
[36mvite v7.0.6 [32mbuilding SSR bundle for production...[36m[39m
|
|
2
|
-
create
|
|
2
|
+
- ctix 'create' mode start, ...
|
|
3
|
+
✔ /home/runner/work/utils/utils/packages/react/tsconfig.json loading complete!
|
|
4
|
+
✔ analysis export statements completed!
|
|
5
|
+
- build "index.ts" file start
|
|
6
|
+
- output file exists check, ...
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
✔ ctix 'create' mode complete!
|
|
3
10
|
transforming...
|
|
4
11
|
[32m✓[39m 8 modules transformed.
|
|
5
12
|
rendering chunks...
|
|
6
13
|
|
|
7
14
|
[vite:dts] Start generate declaration files...
|
|
8
|
-
[96msrc/form/form.tsx[0m:[93m1[0m:[93m10[0m - [91merror[0m[90m TS2724: [0m'"zod"' has no exported member named 'typeToFlattenedError'. Did you mean 'ZodFlattenedError'?
|
|
9
|
-
|
|
10
|
-
[7m1[0m import { typeToFlattenedError, z, SafeParseReturnType, TypeOf } from 'zod';
|
|
11
|
-
[7m [0m [91m ~~~~~~~~~~~~~~~~~~~~[0m
|
|
12
|
-
[96msrc/form/form.tsx[0m:[93m1[0m:[93m35[0m - [91merror[0m[90m TS2614: [0mModule '"zod"' has no exported member 'SafeParseReturnType'. Did you mean to use 'import SafeParseReturnType from "zod"' instead?
|
|
13
|
-
|
|
14
|
-
[7m1[0m import { typeToFlattenedError, z, SafeParseReturnType, TypeOf } from 'zod';
|
|
15
|
-
[7m [0m [91m ~~~~~~~~~~~~~~~~~~~[0m
|
|
16
|
-
[96msrc/form/form.tsx[0m:[93m7[0m:[93m61[0m - [91merror[0m[90m TS2769: [0mNo overload matches this call.
|
|
17
|
-
Overload 1 of 2, '(params?: string | { error?: string | $ZodErrorMap<$ZodIssueInvalidType<unknown>> | undefined; message?: string | undefined; } | undefined): ZodString', gave the following error.
|
|
18
|
-
Object literal may only specify known properties, and 'required_error' does not exist in type '{ error?: string | $ZodErrorMap<$ZodIssueInvalidType<unknown>> | undefined; message?: string | undefined; }'.
|
|
19
|
-
Overload 2 of 2, '(params?: string | { error?: string | $ZodErrorMap<$ZodIssueInvalidType<unknown>> | undefined; message?: string | undefined; } | undefined): $ZodType<...>', gave the following error.
|
|
20
|
-
Object literal may only specify known properties, and 'required_error' does not exist in type '{ error?: string | $ZodErrorMap<$ZodIssueInvalidType<unknown>> | undefined; message?: string | undefined; }'.
|
|
21
|
-
|
|
22
|
-
[7m7[0m export const stringRequired = (): z.ZodString => z.string({ required_error: nonEmpty }).min(1, nonEmpty);
|
|
23
|
-
[7m [0m [91m ~~~~~~~~~~~~~~[0m
|
|
24
|
-
|
|
25
|
-
[96msrc/form/form.tsx[0m:[93m12[0m:[93m46[0m - [91merror[0m[90m TS2694: [0mNamespace '"/home/runner/work/utils/utils/node_modules/zod/v4/classic/external"' has no exported member 'ZodEffects'.
|
|
26
|
-
|
|
27
|
-
[7m12[0m export type ZodObject = z.ZodObject<any> | z.ZodEffects<z.ZodObject<any>>; // z.ZodType<any, any, any>
|
|
28
|
-
[7m [0m [91m ~~~~~~~~~~[0m
|
|
29
|
-
[96msrc/form/form.tsx[0m:[93m43[0m:[93m56[0m - [91merror[0m[90m TS2694: [0mNamespace '"/home/runner/work/utils/utils/node_modules/zod/v4/classic/external"' has no exported member 'ZodEffects'.
|
|
30
|
-
|
|
31
|
-
[7m43[0m (schema as z.ZodObject<any>).shape || (schema as z.ZodEffects<z.ZodObject<any>>).sourceType().shape;
|
|
32
|
-
[7m [0m [91m ~~~~~~~~~~[0m
|
|
33
|
-
|
|
34
15
|
[2mdist/[22m[36museFetch.js [39m[1m[2m0.57 kB[22m[1m[22m[2m │ map: 1.69 kB[22m
|
|
35
16
|
[2mdist/[22m[36mindex.js [39m[1m[2m0.67 kB[22m[1m[22m[2m │ map: 0.10 kB[22m
|
|
36
17
|
[2mdist/[22m[36mapiCall.js [39m[1m[2m0.69 kB[22m[1m[22m[2m │ map: 1.45 kB[22m
|
|
37
18
|
[2mdist/[22m[36museFetcher.js [39m[1m[2m1.18 kB[22m[1m[22m[2m │ map: 2.62 kB[22m
|
|
38
|
-
[2mdist/[22m[36mkeyboard.js [39m[1m[2m1.
|
|
19
|
+
[2mdist/[22m[36mkeyboard.js [39m[1m[2m1.27 kB[22m[1m[22m[2m │ map: 2.81 kB[22m
|
|
39
20
|
[2mdist/[22m[36mform/client.js [39m[1m[2m1.58 kB[22m[1m[22m[2m │ map: 3.88 kB[22m
|
|
40
|
-
[2mdist/[22m[36mform/form.js [39m[1m[2m2.
|
|
41
|
-
[vite:dts] Declaration files built in
|
|
21
|
+
[2mdist/[22m[36mform/form.js [39m[1m[2m2.89 kB[22m[1m[22m[2m │ map: 7.94 kB[22m
|
|
22
|
+
[vite:dts] Declaration files built in 1853ms.
|
|
42
23
|
|
|
43
|
-
[32m✓ built in
|
|
24
|
+
[32m✓ built in 5.02s[39m
|
|
44
25
|
Updated package.json with exports
|
package/CHANGELOG.md
ADDED
package/dist/form/form.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { z } from 'zod';
|
|
2
2
|
import { Context, FC } from 'react';
|
|
3
3
|
export declare const stringRequired: () => z.ZodString;
|
|
4
4
|
export declare const maxLength: (schema: z.ZodString) => number;
|
|
5
5
|
export declare const minLength: (schema: z.ZodString) => number;
|
|
6
6
|
export declare const isRequired: (schema: z.ZodString) => boolean;
|
|
7
|
-
export type ZodObject = z.ZodObject<any> | z.
|
|
8
|
-
export type MaybeTypeOf<S extends ZodObject> = Partial<
|
|
9
|
-
export type SafeTypeOf<S extends ZodObject> =
|
|
10
|
-
export type Errors<S extends ZodObject> =
|
|
7
|
+
export type ZodObject = z.ZodObject<any> | z.ZodPipe<any, any>;
|
|
8
|
+
export type MaybeTypeOf<S extends ZodObject> = Partial<z.output<S>>;
|
|
9
|
+
export type SafeTypeOf<S extends ZodObject> = z.core.util.SafeParseResult<z.output<S>>['data'];
|
|
10
|
+
export type Errors<S extends ZodObject> = z.core.$ZodFlattenedError<z.output<S>>['fieldErrors'];
|
|
11
11
|
export type Validation<S extends ZodObject> = {
|
|
12
12
|
success: true;
|
|
13
13
|
data: SafeTypeOf<S>;
|
|
@@ -26,23 +26,23 @@ export interface FormProps<S extends ZodObject> {
|
|
|
26
26
|
}
|
|
27
27
|
export declare const Form: FC<FormProps<any>>;
|
|
28
28
|
export declare function create<S extends ZodObject>(schema: S): {
|
|
29
|
-
register: (name: keyof
|
|
29
|
+
register: (name: keyof z.output<S>, data?: MaybeTypeOf<S>, errors?: Errors<S>, mui?: boolean) => {
|
|
30
30
|
label?: any;
|
|
31
31
|
helperText?: string;
|
|
32
32
|
error?: boolean;
|
|
33
|
-
name: keyof z.
|
|
34
|
-
id: keyof z.
|
|
33
|
+
name: keyof z.output<S>;
|
|
34
|
+
id: keyof z.output<S>;
|
|
35
35
|
required: boolean;
|
|
36
36
|
maxLength: number;
|
|
37
37
|
type: string;
|
|
38
|
-
defaultValue?: Partial<z.
|
|
38
|
+
defaultValue?: Partial<z.output<S>>[keyof z.output<S>];
|
|
39
39
|
};
|
|
40
40
|
validate: (formData: FormData) => Validation<S>;
|
|
41
41
|
validationError: (data: MaybeTypeOf<S>, errors: Errors<S>) => Validation<S>;
|
|
42
42
|
};
|
|
43
43
|
interface FieldProps<S extends ZodObject> {
|
|
44
44
|
children?: any;
|
|
45
|
-
name: keyof
|
|
45
|
+
name: keyof z.output<S>;
|
|
46
46
|
errors?: Validation<S>['errors'];
|
|
47
47
|
hint?: string;
|
|
48
48
|
className?: string;
|
package/dist/form/form.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../src/form/form.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../src/form/form.tsx"],"names":[],"mappings":"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"}
|
package/dist/form/form.js
CHANGED
|
@@ -3,7 +3,7 @@ import { z } from "zod";
|
|
|
3
3
|
import { createContext, memo, useMemo, useContext } from "react";
|
|
4
4
|
import clsx from "clsx";
|
|
5
5
|
const nonEmpty = "This field cannot be empty";
|
|
6
|
-
const stringRequired = () => z.string({
|
|
6
|
+
const stringRequired = () => z.string({ error: nonEmpty }).min(1, { error: nonEmpty });
|
|
7
7
|
const maxLength = (schema) => schema.maxLength || 0;
|
|
8
8
|
const minLength = (schema) => schema.minLength || 0;
|
|
9
9
|
const isRequired = (schema) => minLength(schema) > 0;
|
|
@@ -12,7 +12,7 @@ const Form = memo(function Form2({ schema, children }) {
|
|
|
12
12
|
const value = useMemo(() => ({ schema }), [schema]);
|
|
13
13
|
return /* @__PURE__ */ jsx(FormContext.Provider, { value, children });
|
|
14
14
|
});
|
|
15
|
-
const getShape = (schema) => schema.shape || schema.
|
|
15
|
+
const getShape = (schema) => schema.shape || schema.in.shape;
|
|
16
16
|
function create(schema) {
|
|
17
17
|
if (!getShape(schema)) {
|
|
18
18
|
throw new Error("Invalid schema: only z.object() or z.object().refine() are supported");
|
|
@@ -44,11 +44,11 @@ function create(schema) {
|
|
|
44
44
|
}
|
|
45
45
|
function validate(formData) {
|
|
46
46
|
const rawData = Object.fromEntries(formData);
|
|
47
|
-
const
|
|
48
|
-
if (
|
|
49
|
-
return validationError(rawData,
|
|
47
|
+
const result = schema.safeParse(rawData);
|
|
48
|
+
if (!result.success) {
|
|
49
|
+
return validationError(rawData, z.flattenError(result.error).fieldErrors);
|
|
50
50
|
}
|
|
51
|
-
return { success: true, data };
|
|
51
|
+
return { success: true, data: result.data };
|
|
52
52
|
}
|
|
53
53
|
return { register, validate, validationError };
|
|
54
54
|
}
|
package/dist/form/form.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.js","sources":["../../src/form/form.tsx"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"form.js","sources":["../../src/form/form.tsx"],"sourcesContent":["import { z } from 'zod';\nimport { Context, createContext, useContext, useMemo, JSX, FC, memo } from 'react';\nimport clsx from 'clsx';\n\nconst nonEmpty = 'This field cannot be empty';\n\nexport const stringRequired = (): z.ZodString => z.string({ error: nonEmpty }).min(1, { error: nonEmpty });\nexport const maxLength = (schema: z.ZodString): number => schema.maxLength || 0;\nexport const minLength = (schema: z.ZodString): number => schema.minLength || 0;\nexport const isRequired = (schema: z.ZodString): boolean => minLength(schema) > 0;\n\nexport type ZodObject = z.ZodObject<any> | z.ZodPipe<any, any>; // z.ZodType<any, any, any>\nexport type MaybeTypeOf<S extends ZodObject> = Partial<z.output<S>>;\nexport type SafeTypeOf<S extends ZodObject> = z.core.util.SafeParseResult<z.output<S>>['data'];\nexport type Errors<S extends ZodObject> = z.core.$ZodFlattenedError<z.output<S>>['fieldErrors'];\nexport type Validation<S extends ZodObject> =\n | {\n success: true; // this is true only if form was validated successfully\n data: SafeTypeOf<S>;\n errors?: never;\n }\n | {\n success: false;\n data?: MaybeTypeOf<S>;\n errors?: Errors<S>;\n };\n\nexport const FormContext: Context<{\n schema: ZodObject;\n}> = createContext(null as never);\n\nexport interface FormProps<S extends ZodObject> {\n schema: S;\n children: any;\n}\n\nexport const Form: FC<FormProps<any>> = memo(function Form({ schema, children }) {\n const value = useMemo(() => ({ schema }), [schema]);\n return <FormContext.Provider value={value}>{children}</FormContext.Provider>;\n});\n\nconst getShape = <S extends ZodObject>(schema: S) =>\n (schema as z.ZodObject<any>).shape || (schema as z.ZodPipe<any, any>).in.shape;\n\nexport function create<S extends ZodObject>(\n schema: S,\n): {\n register: (\n name: keyof z.output<S>,\n data?: MaybeTypeOf<S>,\n errors?: Errors<S>,\n mui?: boolean,\n ) => {\n label?: any;\n helperText?: string;\n error?: boolean;\n name: keyof z.output<S>;\n id: keyof z.output<S>;\n required: boolean;\n maxLength: number;\n type: string;\n defaultValue?: Partial<z.output<S>>[keyof z.output<S>];\n };\n validate: (formData: FormData) => Validation<S>;\n validationError: (data: MaybeTypeOf<S>, errors: Errors<S>) => Validation<S>;\n} {\n if (!getShape(schema)) {\n throw new Error('Invalid schema: only z.object() or z.object().refine() are supported');\n }\n\n function register(\n name: keyof z.output<S>,\n data?: MaybeTypeOf<S>,\n errors?: Errors<S>,\n mui: boolean = false,\n ): {\n label?: any;\n helperText?: string;\n error?: boolean;\n name: keyof z.output<S>;\n id: keyof z.output<S>;\n required: boolean;\n maxLength: number;\n type: string;\n defaultValue?: Partial<z.output<S>>[keyof z.output<S>];\n } {\n const field = getShape(schema)[name];\n return {\n name,\n id: name,\n required: isRequired(field),\n maxLength: maxLength(field),\n type: field.isEmail ? 'email' : (name as string).includes('password') ? 'password' : 'text',\n defaultValue: data?.[name],\n ...(mui\n ? {\n label: field.description,\n helperText: errors?.[name]?.join(', '),\n error: !!errors?.[name]?.length,\n }\n : {}),\n };\n }\n\n function validationError(data: MaybeTypeOf<S>, errors: Errors<S>): Validation<S> {\n return {\n success: false,\n data, // data is undefined if there are errors\n errors, // Next.js will butcher error object, so we provide something more primitive\n };\n }\n\n function validate(formData: FormData): Validation<S> {\n const rawData = Object.fromEntries(formData) as z.output<S>;\n const result = schema.safeParse(rawData);\n\n // console.log('Validate result', { error, data, rawData });\n\n if (!result.success) {\n // data is undefined if there are errors\n // Next.js will butcher error object, so we provide something more primitive\n return validationError(rawData, z.flattenError(result.error).fieldErrors as any);\n }\n\n return { success: true, data: result.data };\n }\n\n return { register, validate, validationError };\n}\n\ninterface FieldProps<S extends ZodObject> {\n children?: any;\n name: keyof z.output<S>;\n errors?: Validation<S>['errors'];\n hint?: string;\n className?: string;\n labelProps?: any;\n [key: string]: any;\n}\n\nexport const Field: FC<FieldProps<any>> = memo(function Field({\n children,\n name,\n errors,\n hint,\n className,\n labelProps,\n ...props\n}) {\n const { schema } = useContext(FormContext);\n const { description } = getShape(schema)[name];\n\n return (\n <div {...props} className={clsx('form-row', className)}>\n {description && (\n <label {...labelProps} htmlFor={name}>\n {description}\n </label>\n )}\n {children}\n {hint && <Hint>{hint}</Hint>}\n {errors?.[name as any]?.map((e: string) => (\n <Hint error key={e}>\n {e}\n </Hint>\n ))}\n </div>\n );\n});\n\nexport interface HintProps {\n children: any;\n error?: boolean;\n}\n\nexport const Hint: FC<HintProps> = memo(function Hint({ children, error }) {\n return <div className={`hint ${error ? 'hint-error' : ''}`}>{children}</div>;\n});\n"],"names":["Form","Field","Hint"],"mappings":";;;;AAIA,MAAM,WAAW;AAEV,MAAM,iBAAiB,MAAmB,EAAE,OAAO,EAAE,OAAO,UAAU,EAAE,IAAI,GAAG,EAAE,OAAO,UAAU;AAClG,MAAM,YAAY,CAAC,WAAgC,OAAO,aAAa;AACvE,MAAM,YAAY,CAAC,WAAgC,OAAO,aAAa;AACvE,MAAM,aAAa,CAAC,WAAiC,UAAU,MAAM,IAAI;AAkBzE,MAAM,cAER,cAAc,IAAa;AAOzB,MAAM,OAA2B,KAAK,SAASA,MAAK,EAAE,QAAQ,YAAY;AAC7E,QAAM,QAAQ,QAAQ,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC;AAClD,SAAO,oBAAC,YAAY,UAAZ,EAAqB,OAAe,SAAA,CAAS;AACzD,CAAC;AAED,MAAM,WAAW,CAAsB,WAClC,OAA4B,SAAU,OAA+B,GAAG;AAEtE,SAAS,OACZ,QAoBF;AACE,MAAI,CAAC,SAAS,MAAM,GAAG;AACnB,UAAM,IAAI,MAAM,sEAAsE;AAAA,EAC1F;AAEA,WAAS,SACL,MACA,MACA,QACA,MAAe,OAWjB;AACE,UAAM,QAAQ,SAAS,MAAM,EAAE,IAAI;AACnC,WAAO;AAAA,MACH;AAAA,MACA,IAAI;AAAA,MACJ,UAAU,WAAW,KAAK;AAAA,MAC1B,WAAW,UAAU,KAAK;AAAA,MAC1B,MAAM,MAAM,UAAU,UAAW,KAAgB,SAAS,UAAU,IAAI,aAAa;AAAA,MACrF,cAAc,OAAO,IAAI;AAAA,MACzB,GAAI,MACE;AAAA,QACI,OAAO,MAAM;AAAA,QACb,YAAY,SAAS,IAAI,GAAG,KAAK,IAAI;AAAA,QACrC,OAAO,CAAC,CAAC,SAAS,IAAI,GAAG;AAAA,MAAA,IAE7B,CAAA;AAAA,IAAC;AAAA,EAEf;AAEA,WAAS,gBAAgB,MAAsB,QAAkC;AAC7E,WAAO;AAAA,MACH,SAAS;AAAA,MACT;AAAA;AAAA,MACA;AAAA;AAAA,IAAA;AAAA,EAER;AAEA,WAAS,SAAS,UAAmC;AACjD,UAAM,UAAU,OAAO,YAAY,QAAQ;AAC3C,UAAM,SAAS,OAAO,UAAU,OAAO;AAIvC,QAAI,CAAC,OAAO,SAAS;AAGjB,aAAO,gBAAgB,SAAS,EAAE,aAAa,OAAO,KAAK,EAAE,WAAkB;AAAA,IACnF;AAEA,WAAO,EAAE,SAAS,MAAM,MAAM,OAAO,KAAA;AAAA,EACzC;AAEA,SAAO,EAAE,UAAU,UAAU,gBAAA;AACjC;AAYO,MAAM,QAA6B,KAAK,SAASC,OAAM;AAAA,EAC1D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACP,GAAG;AACC,QAAM,EAAE,OAAA,IAAW,WAAW,WAAW;AACzC,QAAM,EAAE,YAAA,IAAgB,SAAS,MAAM,EAAE,IAAI;AAE7C,SACI,qBAAC,SAAK,GAAG,OAAO,WAAW,KAAK,YAAY,SAAS,GAChD,UAAA;AAAA,IAAA,mCACI,SAAA,EAAO,GAAG,YAAY,SAAS,MAC3B,UAAA,aACL;AAAA,IAEH;AAAA,IACA,QAAQ,oBAAC,MAAA,EAAM,UAAA,KAAA,CAAK;AAAA,IACpB,SAAS,IAAW,GAAG,IAAI,CAAC,MACzB,oBAAC,MAAA,EAAK,OAAK,MACN,UAAA,EAAA,GADY,CAEjB,CACH;AAAA,EAAA,GACL;AAER,CAAC;AAOM,MAAM,OAAsB,KAAK,SAASC,MAAK,EAAE,UAAU,SAAS;AACvE,SAAO,oBAAC,SAAI,WAAW,QAAQ,QAAQ,eAAe,EAAE,IAAK,SAAA,CAAS;AAC1E,CAAC;"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,QAAQ,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { createClient } from "./form/client.js";
|
|
2
|
-
import { Field, Form, FormContext, Hint, create, isRequired, maxLength, minLength, stringRequired } from "./form/form.js";
|
|
3
1
|
import { apiCall, jsonContentType } from "./apiCall.js";
|
|
4
2
|
import { HotkeysContext, HotkeysProvider, useHotkeys } from "./keyboard.js";
|
|
5
3
|
import { useFetch } from "./useFetch.js";
|
|
6
4
|
import { useFetcher } from "./useFetcher.js";
|
|
5
|
+
import { createClient } from "./form/client.js";
|
|
6
|
+
import { Field, Form, FormContext, Hint, create, isRequired, maxLength, minLength, stringRequired } from "./form/form.js";
|
|
7
7
|
export {
|
|
8
8
|
Field,
|
|
9
9
|
Form,
|
package/dist/keyboard.d.ts
CHANGED
|
@@ -5,6 +5,9 @@ export type HotkeyContextType = {
|
|
|
5
5
|
setEnabled: Dispatch<SetStateAction<boolean>>;
|
|
6
6
|
};
|
|
7
7
|
export declare const HotkeysContext: Context<HotkeyContextType>;
|
|
8
|
-
export
|
|
8
|
+
export type HotkeysProviderProps = {
|
|
9
|
+
children: any;
|
|
10
|
+
};
|
|
11
|
+
export declare const HotkeysProvider: FC<HotkeysProviderProps>;
|
|
9
12
|
export declare const useHotkeys: (hotkeys: Hotkeys) => void;
|
|
10
13
|
//# sourceMappingURL=keyboard.d.ts.map
|
package/dist/keyboard.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../src/keyboard.tsx"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../src/keyboard.tsx"],"names":[],"mappings":"AAEA,OAAO,EAKH,QAAQ,EACR,cAAc,EAEd,EAAE,EAEF,OAAO,EACV,MAAM,OAAO,CAAC;AAMf,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,IAAI,CAAC,CAAC;AAEhF,MAAM,MAAM,iBAAiB,GAAG;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;CACjD,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,iBAAiB,CAGrC,CAAC;AAElB,MAAM,MAAM,oBAAoB,GAAG;IAC/B,QAAQ,EAAE,GAAG,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,EAAE,CAAC,oBAAoB,CAMnD,CAAC;AAEH,eAAO,MAAM,UAAU,GAAI,SAAS,OAAO,KAAG,IA6B7C,CAAC"}
|
package/dist/keyboard.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
import { createContext, useState, useMemo, useContext, useEffect } from "react";
|
|
3
|
+
import { createContext, memo, useState, useMemo, useContext, useEffect } from "react";
|
|
4
4
|
const isCtrlOrMeta = (e) => e.metaKey || e.ctrlKey;
|
|
5
5
|
const EVENT = "keydown";
|
|
6
6
|
const HotkeysContext = createContext(null);
|
|
7
|
-
const HotkeysProvider = ({ children })
|
|
7
|
+
const HotkeysProvider = memo(function HotkeysProvider2({ children }) {
|
|
8
8
|
const [enabled, setEnabled] = useState(true);
|
|
9
9
|
const control = useMemo(() => ({ enabled, setEnabled }), [enabled, setEnabled]);
|
|
10
10
|
return /* @__PURE__ */ jsx(HotkeysContext.Provider, { value: control, children });
|
|
11
|
-
};
|
|
11
|
+
});
|
|
12
12
|
const useHotkeys = (hotkeys) => {
|
|
13
13
|
const { enabled } = useContext(HotkeysContext);
|
|
14
14
|
useEffect(() => {
|
package/dist/keyboard.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyboard.js","sources":["../src/keyboard.tsx"],"sourcesContent":["'use client';\n\nimport {
|
|
1
|
+
{"version":3,"file":"keyboard.js","sources":["../src/keyboard.tsx"],"sourcesContent":["'use client';\n\nimport {\n useEffect,\n createContext,\n useMemo,\n useState,\n Dispatch,\n SetStateAction,\n useContext,\n FC,\n memo,\n Context,\n} from 'react';\n\nconst isCtrlOrMeta = (e: KeyboardEvent) => e.metaKey || e.ctrlKey;\n\nconst EVENT = 'keydown';\n\nexport type Hotkeys = Record<KeyboardEvent['code'], (e: KeyboardEvent) => void>;\n\nexport type HotkeyContextType = {\n enabled: boolean;\n setEnabled: Dispatch<SetStateAction<boolean>>;\n};\n\nexport const HotkeysContext: Context<HotkeyContextType> = createContext<{\n enabled: boolean;\n setEnabled: Dispatch<SetStateAction<boolean>>;\n}>(null as never);\n\nexport type HotkeysProviderProps = {\n children: any;\n};\n\nexport const HotkeysProvider: FC<HotkeysProviderProps> = memo(function HotkeysProvider({ children }) {\n const [enabled, setEnabled] = useState(true);\n\n const control = useMemo(() => ({ enabled, setEnabled }), [enabled, setEnabled]);\n\n return <HotkeysContext.Provider value={control}>{children}</HotkeysContext.Provider>;\n});\n\nexport const useHotkeys = (hotkeys: Hotkeys): void => {\n const { enabled } = useContext(HotkeysContext);\n\n useEffect(() => {\n if (typeof document === 'undefined' || !enabled) {\n return;\n }\n\n const ctrl = new AbortController();\n\n window.addEventListener(\n EVENT,\n (e: KeyboardEvent) => {\n if (!isCtrlOrMeta(e)) return;\n\n for (const [code, callback] of Object.entries(hotkeys)) {\n if (e.code === code) {\n callback(e);\n return;\n }\n }\n },\n { signal: ctrl.signal, capture: true },\n );\n\n return () => {\n ctrl.abort();\n };\n }, [hotkeys, enabled]);\n};\n"],"names":["HotkeysProvider"],"mappings":";;;AAeA,MAAM,eAAe,CAAC,MAAqB,EAAE,WAAW,EAAE;AAE1D,MAAM,QAAQ;AASP,MAAM,iBAA6C,cAGvD,IAAa;AAMT,MAAM,kBAA4C,KAAK,SAASA,iBAAgB,EAAE,YAAY;AACjG,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,IAAI;AAE3C,QAAM,UAAU,QAAQ,OAAO,EAAE,SAAS,eAAe,CAAC,SAAS,UAAU,CAAC;AAE9E,6BAAQ,eAAe,UAAf,EAAwB,OAAO,SAAU,UAAS;AAC9D,CAAC;AAEM,MAAM,aAAa,CAAC,YAA2B;AAClD,QAAM,EAAE,QAAA,IAAY,WAAW,cAAc;AAE7C,YAAU,MAAM;AACZ,QAAI,OAAO,aAAa,eAAe,CAAC,SAAS;AAC7C;AAAA,IACJ;AAEA,UAAM,OAAO,IAAI,gBAAA;AAEjB,WAAO;AAAA,MACH;AAAA,MACA,CAAC,MAAqB;AAClB,YAAI,CAAC,aAAa,CAAC,EAAG;AAEtB,mBAAW,CAAC,MAAM,QAAQ,KAAK,OAAO,QAAQ,OAAO,GAAG;AACpD,cAAI,EAAE,SAAS,MAAM;AACjB,qBAAS,CAAC;AACV;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAAA,MACA,EAAE,QAAQ,KAAK,QAAQ,SAAS,KAAA;AAAA,IAAK;AAGzC,WAAO,MAAM;AACT,WAAK,MAAA;AAAA,IACT;AAAA,EACJ,GAAG,CAAC,SAAS,OAAO,CAAC;AACzB;"}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kirill.konshin/react",
|
|
3
3
|
"description": "Utilities",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.2",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"----- BUILD -----": "",
|
|
8
8
|
"clean": "rm -rf dist .tscache tsconfig.tsbuildinfo",
|
|
9
9
|
"build": "vite build",
|
|
10
|
-
"build:index": "
|
|
10
|
+
"build:index": "ctix build",
|
|
11
11
|
"build:check-types": "attw --pack .",
|
|
12
12
|
"start": "yarn build --watch",
|
|
13
13
|
"wait": "wait-on ./dist/index.js",
|
package/src/form/form.tsx
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { z } from 'zod';
|
|
2
2
|
import { Context, createContext, useContext, useMemo, JSX, FC, memo } from 'react';
|
|
3
3
|
import clsx from 'clsx';
|
|
4
4
|
|
|
5
5
|
const nonEmpty = 'This field cannot be empty';
|
|
6
6
|
|
|
7
|
-
export const stringRequired = (): z.ZodString => z.string({
|
|
7
|
+
export const stringRequired = (): z.ZodString => z.string({ error: nonEmpty }).min(1, { error: nonEmpty });
|
|
8
8
|
export const maxLength = (schema: z.ZodString): number => schema.maxLength || 0;
|
|
9
9
|
export const minLength = (schema: z.ZodString): number => schema.minLength || 0;
|
|
10
10
|
export const isRequired = (schema: z.ZodString): boolean => minLength(schema) > 0;
|
|
11
11
|
|
|
12
|
-
export type ZodObject = z.ZodObject<any> | z.
|
|
13
|
-
export type MaybeTypeOf<S extends ZodObject> = Partial<
|
|
14
|
-
export type SafeTypeOf<S extends ZodObject> =
|
|
15
|
-
export type Errors<S extends ZodObject> =
|
|
12
|
+
export type ZodObject = z.ZodObject<any> | z.ZodPipe<any, any>; // z.ZodType<any, any, any>
|
|
13
|
+
export type MaybeTypeOf<S extends ZodObject> = Partial<z.output<S>>;
|
|
14
|
+
export type SafeTypeOf<S extends ZodObject> = z.core.util.SafeParseResult<z.output<S>>['data'];
|
|
15
|
+
export type Errors<S extends ZodObject> = z.core.$ZodFlattenedError<z.output<S>>['fieldErrors'];
|
|
16
16
|
export type Validation<S extends ZodObject> =
|
|
17
17
|
| {
|
|
18
18
|
success: true; // this is true only if form was validated successfully
|
|
@@ -40,13 +40,13 @@ export const Form: FC<FormProps<any>> = memo(function Form({ schema, children })
|
|
|
40
40
|
});
|
|
41
41
|
|
|
42
42
|
const getShape = <S extends ZodObject>(schema: S) =>
|
|
43
|
-
(schema as z.ZodObject<any>).shape || (schema as z.
|
|
43
|
+
(schema as z.ZodObject<any>).shape || (schema as z.ZodPipe<any, any>).in.shape;
|
|
44
44
|
|
|
45
45
|
export function create<S extends ZodObject>(
|
|
46
46
|
schema: S,
|
|
47
47
|
): {
|
|
48
48
|
register: (
|
|
49
|
-
name: keyof
|
|
49
|
+
name: keyof z.output<S>,
|
|
50
50
|
data?: MaybeTypeOf<S>,
|
|
51
51
|
errors?: Errors<S>,
|
|
52
52
|
mui?: boolean,
|
|
@@ -54,12 +54,12 @@ export function create<S extends ZodObject>(
|
|
|
54
54
|
label?: any;
|
|
55
55
|
helperText?: string;
|
|
56
56
|
error?: boolean;
|
|
57
|
-
name: keyof z.
|
|
58
|
-
id: keyof z.
|
|
57
|
+
name: keyof z.output<S>;
|
|
58
|
+
id: keyof z.output<S>;
|
|
59
59
|
required: boolean;
|
|
60
60
|
maxLength: number;
|
|
61
61
|
type: string;
|
|
62
|
-
defaultValue?: Partial<z.
|
|
62
|
+
defaultValue?: Partial<z.output<S>>[keyof z.output<S>];
|
|
63
63
|
};
|
|
64
64
|
validate: (formData: FormData) => Validation<S>;
|
|
65
65
|
validationError: (data: MaybeTypeOf<S>, errors: Errors<S>) => Validation<S>;
|
|
@@ -69,7 +69,7 @@ export function create<S extends ZodObject>(
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
function register(
|
|
72
|
-
name: keyof
|
|
72
|
+
name: keyof z.output<S>,
|
|
73
73
|
data?: MaybeTypeOf<S>,
|
|
74
74
|
errors?: Errors<S>,
|
|
75
75
|
mui: boolean = false,
|
|
@@ -77,12 +77,12 @@ export function create<S extends ZodObject>(
|
|
|
77
77
|
label?: any;
|
|
78
78
|
helperText?: string;
|
|
79
79
|
error?: boolean;
|
|
80
|
-
name: keyof z.
|
|
81
|
-
id: keyof z.
|
|
80
|
+
name: keyof z.output<S>;
|
|
81
|
+
id: keyof z.output<S>;
|
|
82
82
|
required: boolean;
|
|
83
83
|
maxLength: number;
|
|
84
84
|
type: string;
|
|
85
|
-
defaultValue?: Partial<z.
|
|
85
|
+
defaultValue?: Partial<z.output<S>>[keyof z.output<S>];
|
|
86
86
|
} {
|
|
87
87
|
const field = getShape(schema)[name];
|
|
88
88
|
return {
|
|
@@ -111,18 +111,18 @@ export function create<S extends ZodObject>(
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
function validate(formData: FormData): Validation<S> {
|
|
114
|
-
const rawData = Object.fromEntries(formData) as
|
|
115
|
-
const
|
|
114
|
+
const rawData = Object.fromEntries(formData) as z.output<S>;
|
|
115
|
+
const result = schema.safeParse(rawData);
|
|
116
116
|
|
|
117
117
|
// console.log('Validate result', { error, data, rawData });
|
|
118
118
|
|
|
119
|
-
if (
|
|
119
|
+
if (!result.success) {
|
|
120
120
|
// data is undefined if there are errors
|
|
121
121
|
// Next.js will butcher error object, so we provide something more primitive
|
|
122
|
-
return validationError(rawData,
|
|
122
|
+
return validationError(rawData, z.flattenError(result.error).fieldErrors as any);
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
return { success: true, data };
|
|
125
|
+
return { success: true, data: result.data };
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
return { register, validate, validationError };
|
|
@@ -130,7 +130,7 @@ export function create<S extends ZodObject>(
|
|
|
130
130
|
|
|
131
131
|
interface FieldProps<S extends ZodObject> {
|
|
132
132
|
children?: any;
|
|
133
|
-
name: keyof
|
|
133
|
+
name: keyof z.output<S>;
|
|
134
134
|
errors?: Validation<S>['errors'];
|
|
135
135
|
hint?: string;
|
|
136
136
|
className?: string;
|
|
@@ -159,7 +159,7 @@ export const Field: FC<FieldProps<any>> = memo(function Field({
|
|
|
159
159
|
)}
|
|
160
160
|
{children}
|
|
161
161
|
{hint && <Hint>{hint}</Hint>}
|
|
162
|
-
{errors?.[name]?.map((e: string) => (
|
|
162
|
+
{errors?.[name as any]?.map((e: string) => (
|
|
163
163
|
<Hint error key={e}>
|
|
164
164
|
{e}
|
|
165
165
|
</Hint>
|
package/src/index.ts
CHANGED
package/src/keyboard.tsx
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
useEffect,
|
|
5
|
+
createContext,
|
|
6
|
+
useMemo,
|
|
7
|
+
useState,
|
|
8
|
+
Dispatch,
|
|
9
|
+
SetStateAction,
|
|
10
|
+
useContext,
|
|
11
|
+
FC,
|
|
12
|
+
memo,
|
|
13
|
+
Context,
|
|
14
|
+
} from 'react';
|
|
4
15
|
|
|
5
16
|
const isCtrlOrMeta = (e: KeyboardEvent) => e.metaKey || e.ctrlKey;
|
|
6
17
|
|
|
@@ -18,13 +29,17 @@ export const HotkeysContext: Context<HotkeyContextType> = createContext<{
|
|
|
18
29
|
setEnabled: Dispatch<SetStateAction<boolean>>;
|
|
19
30
|
}>(null as never);
|
|
20
31
|
|
|
21
|
-
export
|
|
32
|
+
export type HotkeysProviderProps = {
|
|
33
|
+
children: any;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const HotkeysProvider: FC<HotkeysProviderProps> = memo(function HotkeysProvider({ children }) {
|
|
22
37
|
const [enabled, setEnabled] = useState(true);
|
|
23
38
|
|
|
24
39
|
const control = useMemo(() => ({ enabled, setEnabled }), [enabled, setEnabled]);
|
|
25
40
|
|
|
26
41
|
return <HotkeysContext.Provider value={control}>{children}</HotkeysContext.Provider>;
|
|
27
|
-
};
|
|
42
|
+
});
|
|
28
43
|
|
|
29
44
|
export const useHotkeys = (hotkeys: Hotkeys): void => {
|
|
30
45
|
const { enabled } = useContext(HotkeysContext);
|