@effect-app/vue 0.87.0-next.3 → 0.87.0-next.5

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/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @effect-app/vue
2
2
 
3
+ ## 0.87.0-next.5
4
+
5
+ ### Patch Changes
6
+
7
+ - 52da734: mini form
8
+ - Updated dependencies [52da734]
9
+ - @effect-app/vue@0.87.0-next.5
10
+
11
+ ## 0.87.0-next.4
12
+
13
+ ### Patch Changes
14
+
15
+ - Updated dependencies [fde3e90]
16
+ - @effect-app/schema@0.150.0-next.2
17
+ - @effect-app/core@0.97.0-next.1
18
+ - @effect-app/prelude@0.107.0-next.4
19
+ - @effect-app/vue@0.87.0-next.4
20
+
3
21
  ## 0.87.0-next.3
4
22
 
5
23
  ### Patch Changes
package/_cjs/form.cjs ADDED
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.convertIn = convertIn;
7
+ exports.convertOut = convertOut;
8
+ exports.convertOutInt = convertOutInt;
9
+ exports.translate = exports.customSchemaErrors = void 0;
10
+ var _intl = require("@formatjs/intl");
11
+ var _vue = require("vue");
12
+ function convertIn(v, type) {
13
+ return v === null ? "" : type === "text" ? v : `${v}`;
14
+ }
15
+ function convertOutInt(v, type) {
16
+ v = v == null ? v : v.trim();
17
+ const c = v === "" ? null : type === "float" ? parseFloat(v) : type === "int" ? parseInt(v) : v;
18
+ return c;
19
+ }
20
+ function convertOut(v, set, type) {
21
+ return set(convertOutInt(v, type));
22
+ }
23
+ const f = Symbol();
24
+ class PhantomTypeParameter {}
25
+ // type GetSchemaFromProp<T> = T extends Field<infer S, any, any, any> ? S
26
+ // : never
27
+ const defaultIntl = (0, _intl.createIntl)({
28
+ locale: "en"
29
+ });
30
+ const translate = exports.translate = (0, _vue.ref)(defaultIntl.formatMessage.bind(defaultIntl));
31
+ const customSchemaErrors = exports.customSchemaErrors = (0, _vue.ref)(new Map());
32
+ //# sourceMappingURL=form.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form.cjs","names":["_intl","require","_vue","convertIn","v","type","convertOutInt","trim","c","parseFloat","parseInt","convertOut","set","f","Symbol","PhantomTypeParameter","defaultIntl","createIntl","locale","translate","exports","ref","formatMessage","bind","customSchemaErrors","Map"],"sources":["../_src/form.ts"],"sourcesContent":[null],"mappings":";;;;;;;;;AACA,IAAAA,KAAA,GAAAC,OAAA;AACA,IAAAC,IAAA,GAAAD,OAAA;AAEM,SAAUE,SAASA,CAACC,CAAgB,EAAEC,IAA+B;EACzE,OAAOD,CAAC,KAAK,IAAI,GAAG,EAAE,GAAGC,IAAI,KAAK,MAAM,GAAGD,CAAC,GAAG,GAAGA,CAAC,EAAE;AACvD;AAEM,SAAUE,aAAaA,CAACF,CAAS,EAAEC,IAA+B;EACtED,CAAC,GAAGA,CAAC,IAAI,IAAI,GAAGA,CAAC,GAAGA,CAAC,CAACG,IAAI,EAAE;EAC5B,MAAMC,CAAC,GAAGJ,CAAC,KAAK,EAAE,GAAG,IAAI,GAAGC,IAAI,KAAK,OAAO,GAAGI,UAAU,CAACL,CAAC,CAAC,GAAGC,IAAI,KAAK,KAAK,GAAGK,QAAQ,CAACN,CAAC,CAAC,GAAGA,CAAC;EAC/F,OAAOI,CAAC;AACV;AAEM,SAAUG,UAAUA,CAACP,CAAS,EAAEQ,GAAgC,EAAEP,IAA+B;EACrG,OAAOO,GAAG,CAACN,aAAa,CAACF,CAAC,EAAEC,IAAI,CAAC,CAAC;AACpC;AAyBA,MAAMQ,CAAC,GAAGC,MAAM,EAAE;AAClB,MAAeC,oBAAoB;AAcnC;AACA;AAEA,MAAMC,WAAW,GAAG,IAAAC,gBAAU,EAAC;EAAEC,MAAM,EAAE;AAAI,CAAE,CAAC;AACzC,MAAMC,SAAS,GAAAC,OAAA,CAAAD,SAAA,GAAG,IAAAE,QAAG,EAAkCL,WAAW,CAACM,aAAa,CAACC,IAAI,CAACP,WAAW,CAAC,CAAC;AACnG,MAAMQ,kBAAkB,GAAAJ,OAAA,CAAAI,kBAAA,GAAG,IAAAH,QAAG,EACnC,IAAII,GAAG,EAAE,CACV"}
package/_src/form.ts ADDED
@@ -0,0 +1,220 @@
1
+ import type { Schema } from "@effect-app/schema"
2
+ import { createIntl, type IntlFormatters } from "@formatjs/intl"
3
+ import { ref } from "vue"
4
+
5
+ export function convertIn(v: string | null, type?: "text" | "float" | "int") {
6
+ return v === null ? "" : type === "text" ? v : `${v}`
7
+ }
8
+
9
+ export function convertOutInt(v: string, type?: "text" | "float" | "int") {
10
+ v = v == null ? v : v.trim()
11
+ const c = v === "" ? null : type === "float" ? parseFloat(v) : type === "int" ? parseInt(v) : v
12
+ return c
13
+ }
14
+
15
+ export function convertOut(v: string, set: (v: unknown | null) => void, type?: "text" | "float" | "int") {
16
+ return set(convertOutInt(v, type))
17
+ }
18
+
19
+ // export function buildFieldInfoFromFields<Fields extends StructFields>(
20
+ // fields: Fields
21
+ // ) {
22
+ // return fields.$$.keys.reduce(
23
+ // (prev, cur) => {
24
+ // prev[cur] = buildFieldInfo(fields[cur] as AnyField, cur)
25
+ // return prev
26
+ // },
27
+ // {} as {
28
+ // [K in keyof Fields]: FieldInfo<
29
+ // Schema.From<GetSchemaFromProp<Fields[K]>>,
30
+ // Schema.To<GetSchemaFromProp<Fields[K]>>
31
+ // >
32
+ // }
33
+ // )
34
+ // }
35
+
36
+ export interface FieldMetadata {
37
+ minLength: number | undefined
38
+ maxLength: number | undefined
39
+ required: boolean
40
+ }
41
+
42
+ const f = Symbol()
43
+ abstract class PhantomTypeParameter<
44
+ Identifier extends keyof any,
45
+ InstantiatedType
46
+ > {
47
+ protected abstract readonly _: {
48
+ readonly [NameP in Identifier]: (_: InstantiatedType) => InstantiatedType
49
+ }
50
+ }
51
+ export interface FieldInfo<Tin, Tout> extends PhantomTypeParameter<typeof f, { in: Tin; out: Tout }> {
52
+ rules: ((v: string) => boolean | string)[]
53
+ metadata: FieldMetadata
54
+ type: "text" | "float" | "int" // todo; multi-line vs single line text
55
+ }
56
+
57
+ // type GetSchemaFromProp<T> = T extends Field<infer S, any, any, any> ? S
58
+ // : never
59
+
60
+ const defaultIntl = createIntl({ locale: "en" })
61
+ export const translate = ref<IntlFormatters["formatMessage"]>(defaultIntl.formatMessage.bind(defaultIntl))
62
+ export const customSchemaErrors = ref<Map<Schema<any, any>, (message: string, e: unknown, v: unknown) => string>>(
63
+ new Map()
64
+ )
65
+
66
+ // function buildFieldInfo(
67
+ // propOrSchema: Schema<any, any>,
68
+ // fieldKey: PropertyKey
69
+ // ): FieldInfo<any, any> {
70
+ // const metadata = getMetadataFromSchemaOrProp(propOrSchema) // TODO
71
+ // const schema = propOrSchema
72
+ // const parse = schema.parseEither
73
+
74
+ // const nullable = AST.isUnion(schema.ast) && schema.ast.types.includes(Schema2.null.ast)
75
+
76
+ // function renderError(e: any, v: unknown) {
77
+ // const err = drawError(e)
78
+ // const custom = customSchemaErrors.value.get(schema)
79
+ // ?? (nullable?.self ? customSchemaErrors.value.get(nullable.self) : undefined)
80
+ // return custom ? custom(err, e, v) : translate.value(
81
+ // { defaultMessage: "The entered value is not a valid {type}: {message}", id: "validation.not_a_valid" },
82
+ // {
83
+ // type: translate.value({
84
+ // defaultMessage: capitalize(fieldKey.toString()),
85
+ // id: `fieldNames.${String(fieldKey)}`
86
+ // }),
87
+ // message: err.slice(err.indexOf("expected")) // TODO: this is not translated.
88
+ // }
89
+ // )
90
+ // }
91
+
92
+ // const stringRules = [
93
+ // (v: string | null) =>
94
+ // v === null
95
+ // || metadata.minLength === undefined
96
+ // || v.length >= metadata.minLength
97
+ // || translate.value({
98
+ // defaultMessage: "The field requires at least {minLength} characters",
99
+ // id: "validation.string.minLength"
100
+ // }, {
101
+ // minLength: metadata.minLength
102
+ // }),
103
+ // (v: string | null) =>
104
+ // v === null
105
+ // || metadata.maxLength === undefined
106
+ // || v.length <= metadata.maxLength
107
+ // || translate.value({
108
+ // defaultMessage: "The field cannot have more than {maxLength} characters",
109
+ // id: "validation.string.maxLength"
110
+ // }, {
111
+ // maxLength: metadata.maxLength
112
+ // })
113
+ // ]
114
+
115
+ // const numberRules = [
116
+ // (v: number | null) =>
117
+ // v === null
118
+ // || metadata.minimum === undefined
119
+ // || metadata.minimumExclusive && v > metadata.minimum
120
+ // || !metadata.minimumExclusive && v >= metadata.minimum
121
+ // || translate.value({
122
+ // defaultMessage: "The value should be {isExclusive, select, true {larger than} other {at least}} {minimum}",
123
+ // id: "validation.number.min"
124
+ // }, { isExclusive: metadata.minimumExclusive, minimum: metadata.minimum }),
125
+ // (v: number | null) =>
126
+ // v === null
127
+ // || metadata.maximum === undefined
128
+ // || metadata.maximumExclusive && v < metadata.maximum
129
+ // || !metadata.maximumExclusive && v <= metadata.maximum
130
+ // || translate.value({
131
+ // defaultMessage: "The value should be {isExclusive, select, true {smaller than} other {at most}} {maximum}",
132
+ // id: "validation.number.max"
133
+ // }, { isExclusive: metadata.maximumExclusive, maximum: metadata.maximum })
134
+ // ]
135
+
136
+ // const parseRule = (v: unknown) =>
137
+ // pipe(
138
+ // parse(v),
139
+ // (_) =>
140
+ // _.match(
141
+ // {
142
+ // onLeft: (_) => renderError(_, v),
143
+ // onRight: ([_, optErr]) =>
144
+ // optErr.isSome()
145
+ // ? renderError(optErr.value, v)
146
+ // : true
147
+ // }
148
+ // )
149
+ // )
150
+
151
+ // type UnknownRule = (v: unknown) => boolean | string
152
+ // const rules: UnknownRule[] = [
153
+ // ...(metadata.type === "text"
154
+ // ? stringRules
155
+ // : numberRules) as UnknownRule[],
156
+ // parseRule as UnknownRule
157
+ // ]
158
+
159
+ // const info = {
160
+ // type: metadata.type,
161
+ // rules: [
162
+ // (v: string) =>
163
+ // !metadata.required
164
+ // || v !== ""
165
+ // || translate.value({ defaultMessage: "The field cannot be empty", id: "validation.empty" }),
166
+ // (v: string) => {
167
+ // const converted = convertOutInt(v, metadata.type)
168
+
169
+ // for (const r of rules) {
170
+ // const res = r(converted)
171
+ // if (res !== true) {
172
+ // return res
173
+ // }
174
+ // }
175
+
176
+ // return true
177
+ // }
178
+ // ],
179
+ // metadata
180
+ // }
181
+
182
+ // return info as any
183
+ // }
184
+
185
+ // export const buildFormFromSchema = <
186
+ // Fields extends StructFields,
187
+ // OnSubmitA
188
+ // >(
189
+ // s: Schema<
190
+ // Simplify<FromStruct<Fields>>,
191
+ // Simplify<ToStruct<Fields>>
192
+ // >,
193
+ // state: Ref<FromStruct<Fields>>,
194
+ // onSubmit: (a: ToStruct<Fields>) => Promise<OnSubmitA>
195
+ // ) => {
196
+ // const fields = buildFieldInfoFromFields(s.Api.fields)
197
+ // const parse = s.parseSync
198
+ // const isDirty = ref(false)
199
+ // const isValid = ref(true)
200
+
201
+ // const submit1 = <A>(onSubmit: (a: To) => Promise<A>) => async <T extends Promise<{ valid: boolean }>>(e: T) => {
202
+ // const r = await e
203
+ // if (!r.valid) return
204
+ // return onSubmit(parse(state.value))
205
+ // }
206
+ // const submit = submit1(onSubmit)
207
+
208
+ // watch(
209
+ // state,
210
+ // (v) => {
211
+ // // TODO: do better
212
+ // isDirty.value = JSON.stringify(v) !== JSON.stringify(state.value)
213
+ // },
214
+ // { deep: true }
215
+ // )
216
+
217
+ // const submitFromState = () => submit(Promise.resolve({ valid: isValid.value }))
218
+
219
+ // return { fields, submit, submitFromState, isDirty, isValid }
220
+ // }
package/dist/form.d.ts ADDED
@@ -0,0 +1,30 @@
1
+ import type { Schema } from "@effect-app/schema";
2
+ export declare function convertIn(v: string | null, type?: "text" | "float" | "int"): string;
3
+ export declare function convertOutInt(v: string, type?: "text" | "float" | "int"): string | number | null;
4
+ export declare function convertOut(v: string, set: (v: unknown | null) => void, type?: "text" | "float" | "int"): void;
5
+ export interface FieldMetadata {
6
+ minLength: number | undefined;
7
+ maxLength: number | undefined;
8
+ required: boolean;
9
+ }
10
+ declare const f: unique symbol;
11
+ declare abstract class PhantomTypeParameter<Identifier extends keyof any, InstantiatedType> {
12
+ protected abstract readonly _: {
13
+ readonly [NameP in Identifier]: (_: InstantiatedType) => InstantiatedType;
14
+ };
15
+ }
16
+ export interface FieldInfo<Tin, Tout> extends PhantomTypeParameter<typeof f, {
17
+ in: Tin;
18
+ out: Tout;
19
+ }> {
20
+ rules: ((v: string) => boolean | string)[];
21
+ metadata: FieldMetadata;
22
+ type: "text" | "float" | "int";
23
+ }
24
+ export declare const translate: import("vue").Ref<{
25
+ (descriptor: import("@formatjs/intl").MessageDescriptor, values?: Record<string, import("intl-messageformat").PrimitiveType | import("intl-messageformat").FormatXMLElementFn<string, string>> | undefined, opts?: import("intl-messageformat").Options | undefined): string;
26
+ <T extends unknown>(descriptor: import("@formatjs/intl").MessageDescriptor, values?: Record<string, import("intl-messageformat").PrimitiveType | T | import("intl-messageformat").FormatXMLElementFn<T>> | undefined, opts?: import("intl-messageformat").Options | undefined): string | T | (string | T)[];
27
+ }>;
28
+ export declare const customSchemaErrors: import("vue").Ref<Map<Schema<any, any>, (message: string, e: unknown, v: unknown) => string>>;
29
+ export {};
30
+ //# sourceMappingURL=form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../_src/form.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAIhD,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,UAE1E;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,0BAIvE;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,QAEtG;AAmBD,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,QAAA,MAAM,CAAC,eAAW,CAAA;AAClB,uBAAe,oBAAoB,CACjC,UAAU,SAAS,MAAM,GAAG,EAC5B,gBAAgB;IAEhB,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE;QAC7B,QAAQ,EAAE,KAAK,IAAI,UAAU,GAAG,CAAC,CAAC,EAAE,gBAAgB,KAAK,gBAAgB;KAC1E,CAAA;CACF;AACD,MAAM,WAAW,SAAS,CAAC,GAAG,EAAE,IAAI,CAAE,SAAQ,oBAAoB,CAAC,OAAO,CAAC,EAAE;IAAE,EAAE,EAAE,GAAG,CAAC;IAAC,GAAG,EAAE,IAAI,CAAA;CAAE,CAAC;IAClG,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,GAAG,MAAM,CAAC,EAAE,CAAA;IAC1C,QAAQ,EAAE,aAAa,CAAA;IACvB,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,CAAA;CAC/B;AAMD,eAAO,MAAM,SAAS;;;EAAoF,CAAA;AAC1G,eAAO,MAAM,kBAAkB,oDAAuC,MAAM,KAAK,OAAO,KAAK,OAAO,KAAK,MAAM,EAE9G,CAAA"}
package/dist/form.js ADDED
@@ -0,0 +1,22 @@
1
+ import { createIntl } from "@formatjs/intl";
2
+ import { ref } from "vue";
3
+ export function convertIn(v, type) {
4
+ return v === null ? "" : type === "text" ? v : `${v}`;
5
+ }
6
+ export function convertOutInt(v, type) {
7
+ v = v == null ? v : v.trim();
8
+ const c = v === "" ? null : type === "float" ? parseFloat(v) : type === "int" ? parseInt(v) : v;
9
+ return c;
10
+ }
11
+ export function convertOut(v, set, type) {
12
+ return set(convertOutInt(v, type));
13
+ }
14
+ const f = Symbol();
15
+ class PhantomTypeParameter {
16
+ }
17
+ // type GetSchemaFromProp<T> = T extends Field<infer S, any, any, any> ? S
18
+ // : never
19
+ const defaultIntl = createIntl({ locale: "en" });
20
+ export const translate = ref(defaultIntl.formatMessage.bind(defaultIntl));
21
+ export const customSchemaErrors = ref(new Map());
22
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL19zcmMvZm9ybS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsVUFBVSxFQUF1QixNQUFNLGdCQUFnQixDQUFBO0FBQ2hFLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxLQUFLLENBQUE7QUFFekIsTUFBTSxVQUFVLFNBQVMsQ0FBQyxDQUFnQixFQUFFLElBQStCO0lBQ3pFLE9BQU8sQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUE7QUFDdkQsQ0FBQztBQUVELE1BQU0sVUFBVSxhQUFhLENBQUMsQ0FBUyxFQUFFLElBQStCO0lBQ3RFLENBQUMsR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQTtJQUM1QixNQUFNLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxPQUFPLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7SUFDL0YsT0FBTyxDQUFDLENBQUE7QUFDVixDQUFDO0FBRUQsTUFBTSxVQUFVLFVBQVUsQ0FBQyxDQUFTLEVBQUUsR0FBZ0MsRUFBRSxJQUErQjtJQUNyRyxPQUFPLEdBQUcsQ0FBQyxhQUFhLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUE7QUFDcEMsQ0FBQztBQXlCRCxNQUFNLENBQUMsR0FBRyxNQUFNLEVBQUUsQ0FBQTtBQUNsQixNQUFlLG9CQUFvQjtDQU9sQztBQU9ELDBFQUEwRTtBQUMxRSxZQUFZO0FBRVosTUFBTSxXQUFXLEdBQUcsVUFBVSxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUE7QUFDaEQsTUFBTSxDQUFDLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBa0MsV0FBVyxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQTtBQUMxRyxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxHQUFHLENBQ25DLElBQUksR0FBRyxFQUFFLENBQ1YsQ0FBQSJ9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect-app/vue",
3
- "version": "0.87.0-next.3",
3
+ "version": "0.87.0-next.5",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -12,10 +12,10 @@
12
12
  "query-string": "^8.1.0",
13
13
  "swrv": "^1.0.4",
14
14
  "vue": "^3.3.13",
15
- "@effect-app/vue": "0.87.0-next.3",
16
- "@effect-app/prelude": "0.107.0-next.3",
17
- "@effect-app/schema": "0.150.0-next.1",
18
- "@effect-app/core": "0.97.0-next.0"
15
+ "@effect-app/prelude": "0.107.0-next.4",
16
+ "@effect-app/core": "0.97.0-next.1",
17
+ "@effect-app/vue": "0.87.0-next.5",
18
+ "@effect-app/schema": "0.150.0-next.2"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@rollup/pluginutils": "^5.1.0",
@@ -56,6 +56,16 @@
56
56
  "default": "./_cjs/_global.cjs"
57
57
  }
58
58
  },
59
+ "./form": {
60
+ "import": {
61
+ "types": "./dist/form.d.ts",
62
+ "default": "./dist/form.js"
63
+ },
64
+ "require": {
65
+ "types": "./dist/form.d.ts",
66
+ "default": "./_cjs/form.cjs"
67
+ }
68
+ },
59
69
  "./hooks": {
60
70
  "import": {
61
71
  "types": "./dist/hooks.d.ts",
package/_src/form.ts.bak DELETED
@@ -1,224 +0,0 @@
1
- import { type drawError, type Field, getMetadataFromSchemaOrProp } from "@effect-app/prelude/schema"
2
- import type { AnyField, FromStruct, Schema, StructFields, To, ToStruct } from "@effect-app/schema"
3
- import { AST } from "@effect-app/schema/schema"
4
- import { createIntl, type IntlFormatters } from "@formatjs/intl"
5
- import type { Simplify } from "effect/Types"
6
- import type { Ref } from "vue"
7
- import { capitalize, ref, watch } from "vue"
8
-
9
- export function convertIn(v: string | null, type?: "text" | "float" | "int") {
10
- return v === null ? "" : type === "text" ? v : `${v}`
11
- }
12
-
13
- export function convertOutInt(v: string, type?: "text" | "float" | "int") {
14
- v = v == null ? v : v.trim()
15
- const c = v === "" ? null : type === "float" ? parseFloat(v) : type === "int" ? parseInt(v) : v
16
- return c
17
- }
18
-
19
- export function convertOut(v: string, set: (v: unknown | null) => void, type?: "text" | "float" | "int") {
20
- return set(convertOutInt(v, type))
21
- }
22
-
23
- export function buildFieldInfoFromFields<Fields extends StructFields>(
24
- fields: Fields
25
- ) {
26
- return fields.$$.keys.reduce(
27
- (prev, cur) => {
28
- prev[cur] = buildFieldInfo(fields[cur] as AnyField, cur)
29
- return prev
30
- },
31
- {} as {
32
- [K in keyof Fields]: FieldInfo<
33
- Schema.From<GetSchemaFromProp<Fields[K]>>,
34
- Schema.To<GetSchemaFromProp<Fields[K]>>
35
- >
36
- }
37
- )
38
- }
39
-
40
- export interface FieldMetadata {
41
- minLength: number | undefined
42
- maxLength: number | undefined
43
- required: boolean
44
- }
45
-
46
- const f = Symbol()
47
- abstract class PhantomTypeParameter<
48
- Identifier extends keyof any,
49
- InstantiatedType
50
- > {
51
- protected abstract readonly _: {
52
- readonly [NameP in Identifier]: (_: InstantiatedType) => InstantiatedType
53
- }
54
- }
55
- export interface FieldInfo<Tin, Tout> extends PhantomTypeParameter<typeof f, { in: Tin; out: Tout }> {
56
- rules: ((v: string) => boolean | string)[]
57
- metadata: FieldMetadata
58
- type: "text" | "float" | "int" // todo; multi-line vs single line text
59
- }
60
-
61
- type GetSchemaFromProp<T> = T extends Field<infer S, any, any, any> ? S
62
- : never
63
-
64
- const defaultIntl = createIntl({ locale: "en" })
65
- export const translate = ref<IntlFormatters["formatMessage"]>(defaultIntl.formatMessage.bind(defaultIntl))
66
- export const customSchemaErrors = ref<Map<Schema<any, any>, (message: string, e: unknown, v: unknown) => string>>(
67
- new Map()
68
- )
69
-
70
- function buildFieldInfo(
71
- propOrSchema: Schema<any, any>,
72
- fieldKey: PropertyKey
73
- ): FieldInfo<any, any> {
74
- const metadata = getMetadataFromSchemaOrProp(propOrSchema) // TODO
75
- const schema = propOrSchema
76
- const parse = schema.parseEither
77
-
78
- const nullable = AST.isUnion(schema.ast) && schema.ast.types.includes(Schema2.null.ast)
79
-
80
- function renderError(e: any, v: unknown) {
81
- const err = drawError(e)
82
- const custom = customSchemaErrors.value.get(schema)
83
- ?? (nullable?.self ? customSchemaErrors.value.get(nullable.self) : undefined)
84
- return custom ? custom(err, e, v) : translate.value(
85
- { defaultMessage: "The entered value is not a valid {type}: {message}", id: "validation.not_a_valid" },
86
- {
87
- type: translate.value({
88
- defaultMessage: capitalize(fieldKey.toString()),
89
- id: `fieldNames.${String(fieldKey)}`
90
- }),
91
- message: err.slice(err.indexOf("expected")) // TODO: this is not translated.
92
- }
93
- )
94
- }
95
-
96
- const stringRules = [
97
- (v: string | null) =>
98
- v === null
99
- || metadata.minLength === undefined
100
- || v.length >= metadata.minLength
101
- || translate.value({
102
- defaultMessage: "The field requires at least {minLength} characters",
103
- id: "validation.string.minLength"
104
- }, {
105
- minLength: metadata.minLength
106
- }),
107
- (v: string | null) =>
108
- v === null
109
- || metadata.maxLength === undefined
110
- || v.length <= metadata.maxLength
111
- || translate.value({
112
- defaultMessage: "The field cannot have more than {maxLength} characters",
113
- id: "validation.string.maxLength"
114
- }, {
115
- maxLength: metadata.maxLength
116
- })
117
- ]
118
-
119
- const numberRules = [
120
- (v: number | null) =>
121
- v === null
122
- || metadata.minimum === undefined
123
- || metadata.minimumExclusive && v > metadata.minimum
124
- || !metadata.minimumExclusive && v >= metadata.minimum
125
- || translate.value({
126
- defaultMessage: "The value should be {isExclusive, select, true {larger than} other {at least}} {minimum}",
127
- id: "validation.number.min"
128
- }, { isExclusive: metadata.minimumExclusive, minimum: metadata.minimum }),
129
- (v: number | null) =>
130
- v === null
131
- || metadata.maximum === undefined
132
- || metadata.maximumExclusive && v < metadata.maximum
133
- || !metadata.maximumExclusive && v <= metadata.maximum
134
- || translate.value({
135
- defaultMessage: "The value should be {isExclusive, select, true {smaller than} other {at most}} {maximum}",
136
- id: "validation.number.max"
137
- }, { isExclusive: metadata.maximumExclusive, maximum: metadata.maximum })
138
- ]
139
-
140
- const parseRule = (v: unknown) =>
141
- pipe(
142
- parse(v),
143
- (_) =>
144
- _.match(
145
- {
146
- onLeft: (_) => renderError(_, v),
147
- onRight: ([_, optErr]) =>
148
- optErr.isSome()
149
- ? renderError(optErr.value, v)
150
- : true
151
- }
152
- )
153
- )
154
-
155
- type UnknownRule = (v: unknown) => boolean | string
156
- const rules: UnknownRule[] = [
157
- ...(metadata.type === "text"
158
- ? stringRules
159
- : numberRules) as UnknownRule[],
160
- parseRule as UnknownRule
161
- ]
162
-
163
- const info = {
164
- type: metadata.type,
165
- rules: [
166
- (v: string) =>
167
- !metadata.required
168
- || v !== ""
169
- || translate.value({ defaultMessage: "The field cannot be empty", id: "validation.empty" }),
170
- (v: string) => {
171
- const converted = convertOutInt(v, metadata.type)
172
-
173
- for (const r of rules) {
174
- const res = r(converted)
175
- if (res !== true) {
176
- return res
177
- }
178
- }
179
-
180
- return true
181
- }
182
- ],
183
- metadata
184
- }
185
-
186
- return info as any
187
- }
188
-
189
- export const buildFormFromSchema = <
190
- Fields extends StructFields,
191
- OnSubmitA
192
- >(
193
- s: Schema<
194
- Simplify<FromStruct<Fields>>,
195
- Simplify<ToStruct<Fields>>
196
- >,
197
- state: Ref<FromStruct<Fields>>,
198
- onSubmit: (a: ToStruct<Fields>) => Promise<OnSubmitA>
199
- ) => {
200
- const fields = buildFieldInfoFromFields(s.Api.fields)
201
- const parse = s.parseSync
202
- const isDirty = ref(false)
203
- const isValid = ref(true)
204
-
205
- const submit1 = <A>(onSubmit: (a: To) => Promise<A>) => async <T extends Promise<{ valid: boolean }>>(e: T) => {
206
- const r = await e
207
- if (!r.valid) return
208
- return onSubmit(parse(state.value))
209
- }
210
- const submit = submit1(onSubmit)
211
-
212
- watch(
213
- state,
214
- (v) => {
215
- // TODO: do better
216
- isDirty.value = JSON.stringify(v) !== JSON.stringify(state.value)
217
- },
218
- { deep: true }
219
- )
220
-
221
- const submitFromState = () => submit(Promise.resolve({ valid: isValid.value }))
222
-
223
- return { fields, submit, submitFromState, isDirty, isValid }
224
- }