@effect-app/vue-components 4.0.0-beta.12 → 4.0.0-beta.120
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/README.md +24 -0
- package/dist/reset.css +52 -0
- package/dist/types/components/OmegaForm/OmegaAutoGen.vue.d.ts +1 -1
- package/dist/types/components/OmegaForm/OmegaFormStuff.d.ts +30 -15
- package/dist/types/components/OmegaForm/useOmegaForm.d.ts +3 -5
- package/dist/types/utils/index.d.ts +6 -7
- package/dist/vue-components.es.js +21 -44
- package/dist/vue-components10.es.js +5 -0
- package/dist/vue-components11.es.js +13 -0
- package/dist/vue-components12.es.js +445 -0
- package/dist/vue-components13.es.js +4 -0
- package/dist/vue-components14.es.js +38 -0
- package/dist/vue-components15.es.js +27 -0
- package/dist/vue-components16.es.js +28 -0
- package/dist/vue-components17.es.js +7 -0
- package/dist/vue-components18.es.js +18 -0
- package/dist/vue-components19.es.js +36 -0
- package/dist/vue-components2.es.js +11 -0
- package/dist/vue-components20.es.js +18 -0
- package/dist/vue-components21.es.js +21 -0
- package/dist/vue-components22.es.js +30 -0
- package/dist/vue-components23.es.js +7 -0
- package/dist/vue-components24.es.js +9 -0
- package/dist/vue-components25.es.js +38 -0
- package/dist/vue-components26.es.js +25 -0
- package/dist/vue-components27.es.js +128 -0
- package/dist/vue-components28.es.js +24 -0
- package/dist/vue-components29.es.js +21 -0
- package/dist/vue-components3.es.js +54 -0
- package/dist/vue-components30.es.js +9 -0
- package/dist/vue-components31.es.js +19 -0
- package/dist/vue-components32.es.js +5 -0
- package/dist/vue-components33.es.js +29 -0
- package/dist/vue-components34.es.js +5 -0
- package/dist/vue-components35.es.js +29 -0
- package/dist/vue-components36.es.js +6 -0
- package/dist/vue-components37.es.js +18 -0
- package/dist/vue-components38.es.js +56 -0
- package/dist/vue-components39.es.js +5 -0
- package/dist/vue-components4.es.js +5 -0
- package/dist/vue-components40.es.js +44 -0
- package/dist/vue-components41.es.js +5 -0
- package/dist/vue-components42.es.js +84 -0
- package/dist/vue-components44.es.js +8 -0
- package/dist/vue-components45.es.js +7 -0
- package/dist/vue-components46.es.js +267 -0
- package/dist/vue-components48.es.js +6 -0
- package/dist/vue-components49.es.js +80 -0
- package/dist/vue-components5.es.js +24 -0
- package/dist/vue-components50.es.js +5 -0
- package/dist/vue-components51.es.js +66 -0
- package/dist/vue-components52.es.js +5 -0
- package/dist/vue-components53.es.js +24 -0
- package/dist/vue-components54.es.js +5 -0
- package/dist/vue-components55.es.js +59 -0
- package/dist/vue-components56.es.js +5 -0
- package/dist/vue-components57.es.js +12 -0
- package/dist/vue-components58.es.js +22 -0
- package/dist/vue-components6.es.js +13 -0
- package/dist/vue-components60.es.js +7 -0
- package/dist/vue-components61.es.js +235 -0
- package/dist/vue-components62.es.js +33 -0
- package/dist/vue-components63.es.js +8 -0
- package/dist/vue-components64.es.js +36 -0
- package/dist/vue-components7.es.js +28 -0
- package/dist/vue-components8.es.js +47 -0
- package/dist/vue-components9.es.js +5 -0
- package/package.json +30 -25
- package/src/components/CommandButton.vue +1 -1
- package/src/components/OmegaForm/OmegaAutoGen.vue +25 -30
- package/src/components/OmegaForm/OmegaErrorsInternal.vue +2 -3
- package/src/components/OmegaForm/OmegaFormStuff.ts +513 -353
- package/src/components/OmegaForm/OmegaInternalInput.vue +22 -6
- package/src/components/OmegaForm/useOmegaForm.ts +57 -36
- package/src/reset.css +52 -0
- package/src/utils/index.ts +9 -10
- package/dist/vue-components.es10.js +0 -237
- package/dist/vue-components.es100.js +0 -4
- package/dist/vue-components.es11.js +0 -32
- package/dist/vue-components.es12.js +0 -439
- package/dist/vue-components.es13.js +0 -49
- package/dist/vue-components.es14.js +0 -4
- package/dist/vue-components.es15.js +0 -4
- package/dist/vue-components.es16.js +0 -13
- package/dist/vue-components.es17.js +0 -725
- package/dist/vue-components.es18.js +0 -143
- package/dist/vue-components.es19.js +0 -6
- package/dist/vue-components.es2.js +0 -30
- package/dist/vue-components.es20.js +0 -13
- package/dist/vue-components.es21.js +0 -5
- package/dist/vue-components.es22.js +0 -26
- package/dist/vue-components.es23.js +0 -6
- package/dist/vue-components.es24.js +0 -10
- package/dist/vue-components.es25.js +0 -57
- package/dist/vue-components.es26.js +0 -71
- package/dist/vue-components.es27.js +0 -8
- package/dist/vue-components.es28.js +0 -8
- package/dist/vue-components.es29.js +0 -5
- package/dist/vue-components.es3.js +0 -16
- package/dist/vue-components.es30.js +0 -5
- package/dist/vue-components.es31.js +0 -4
- package/dist/vue-components.es32.js +0 -4
- package/dist/vue-components.es33.js +0 -4
- package/dist/vue-components.es34.js +0 -4
- package/dist/vue-components.es35.js +0 -19
- package/dist/vue-components.es36.js +0 -320
- package/dist/vue-components.es37.js +0 -563
- package/dist/vue-components.es38.js +0 -29
- package/dist/vue-components.es39.js +0 -54
- package/dist/vue-components.es4.js +0 -52
- package/dist/vue-components.es40.js +0 -66
- package/dist/vue-components.es41.js +0 -6
- package/dist/vue-components.es42.js +0 -6
- package/dist/vue-components.es43.js +0 -26
- package/dist/vue-components.es44.js +0 -77
- package/dist/vue-components.es45.js +0 -42
- package/dist/vue-components.es46.js +0 -316
- package/dist/vue-components.es47.js +0 -101
- package/dist/vue-components.es48.js +0 -33
- package/dist/vue-components.es49.js +0 -4
- package/dist/vue-components.es5.js +0 -52
- package/dist/vue-components.es50.js +0 -4
- package/dist/vue-components.es51.js +0 -4
- package/dist/vue-components.es52.js +0 -113
- package/dist/vue-components.es54.js +0 -9
- package/dist/vue-components.es55.js +0 -34
- package/dist/vue-components.es57.js +0 -194
- package/dist/vue-components.es59.js +0 -40
- package/dist/vue-components.es6.js +0 -69
- package/dist/vue-components.es60.js +0 -85
- package/dist/vue-components.es61.js +0 -43
- package/dist/vue-components.es62.js +0 -7
- package/dist/vue-components.es63.js +0 -6
- package/dist/vue-components.es64.js +0 -25
- package/dist/vue-components.es65.js +0 -7
- package/dist/vue-components.es66.js +0 -23
- package/dist/vue-components.es67.js +0 -32
- package/dist/vue-components.es68.js +0 -24
- package/dist/vue-components.es69.js +0 -14
- package/dist/vue-components.es7.js +0 -83
- package/dist/vue-components.es70.js +0 -7
- package/dist/vue-components.es71.js +0 -21
- package/dist/vue-components.es72.js +0 -11
- package/dist/vue-components.es73.js +0 -33
- package/dist/vue-components.es74.js +0 -50
- package/dist/vue-components.es75.js +0 -28
- package/dist/vue-components.es76.js +0 -103
- package/dist/vue-components.es77.js +0 -84
- package/dist/vue-components.es78.js +0 -17
- package/dist/vue-components.es79.js +0 -34
- package/dist/vue-components.es8.js +0 -63
- package/dist/vue-components.es80.js +0 -23
- package/dist/vue-components.es81.js +0 -14
- package/dist/vue-components.es82.js +0 -115
- package/dist/vue-components.es83.js +0 -5
- package/dist/vue-components.es84.js +0 -4
- package/dist/vue-components.es85.js +0 -4
- package/dist/vue-components.es86.js +0 -18
- package/dist/vue-components.es87.js +0 -72
- package/dist/vue-components.es88.js +0 -10
- package/dist/vue-components.es89.js +0 -4
- package/dist/vue-components.es9.js +0 -21
- package/dist/vue-components.es90.js +0 -17
- package/dist/vue-components.es91.js +0 -13
- package/dist/vue-components.es92.js +0 -67
- package/dist/vue-components.es93.js +0 -58
- package/dist/vue-components.es94.js +0 -19
- package/dist/vue-components.es95.js +0 -35
- package/dist/vue-components.es96.js +0 -31
- package/dist/vue-components.es97.js +0 -44
- package/dist/vue-components.es98.js +0 -4
- package/dist/vue-components.es99.js +0 -46
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<slot v-bind="{ ...inputProps.inputProps, field: inputProps.field, state: inputProps.state }">
|
|
3
|
-
<div :class="
|
|
3
|
+
<div :class="rootClass">
|
|
4
4
|
<OmegaInputVuetify
|
|
5
5
|
v-if="vuetified"
|
|
6
6
|
v-bind="{ ...attrsWithoutClass, ...inputProps, class: props.inputClass }"
|
|
@@ -78,6 +78,8 @@ const attrsWithoutClass = computed(() => {
|
|
|
78
78
|
return rest
|
|
79
79
|
})
|
|
80
80
|
|
|
81
|
+
const rootClass = computed(() => attrs.class as any)
|
|
82
|
+
|
|
81
83
|
const id = useId()
|
|
82
84
|
|
|
83
85
|
const fieldApi = props.field
|
|
@@ -117,6 +119,7 @@ const isFalsyButNotZero = (value: unknown): boolean => {
|
|
|
117
119
|
// we remove value and errors when the field is empty and not required
|
|
118
120
|
// convert nullish value to null or undefined based on schema
|
|
119
121
|
const handleChange: OmegaFieldInternalApi<From, Name>["handleChange"] = (value) => {
|
|
122
|
+
let fieldDeleted = false
|
|
120
123
|
if (isFalsyButNotZero(value) && props.meta?.type !== "boolean") {
|
|
121
124
|
// Only convert to null/undefined if the field is actually nullable or optional
|
|
122
125
|
if (props.meta?.nullableOrUndefined) {
|
|
@@ -126,6 +129,14 @@ const handleChange: OmegaFieldInternalApi<From, Name>["handleChange"] = (value)
|
|
|
126
129
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
127
130
|
: null as any
|
|
128
131
|
)
|
|
132
|
+
} else if (props.meta?.isOptionalKey) {
|
|
133
|
+
// `S.optionalKey` expects the key to be ABSENT from the submitted
|
|
134
|
+
// object, not present-with-undefined. Remove it from form state
|
|
135
|
+
// rather than setting it to `undefined`. Note: this is distinct
|
|
136
|
+
// from `required: false`, which may also just mean "empty string
|
|
137
|
+
// is valid" for unconstrained `S.String` fields.
|
|
138
|
+
props.field.form.deleteField(props.field.name)
|
|
139
|
+
fieldDeleted = true
|
|
129
140
|
} else {
|
|
130
141
|
// Keep the actual value (e.g., empty string for S.String fields)
|
|
131
142
|
props.field.handleChange(value)
|
|
@@ -136,7 +147,10 @@ const handleChange: OmegaFieldInternalApi<From, Name>["handleChange"] = (value)
|
|
|
136
147
|
|
|
137
148
|
// whenever we change the field, regardless if we set it to null, we should reset onSubmit.
|
|
138
149
|
// not sure why this is not the case in tanstack form.
|
|
139
|
-
|
|
150
|
+
// Skip when the field was deleted — its meta no longer exists in the form store.
|
|
151
|
+
if (!fieldDeleted) {
|
|
152
|
+
props.field.setMeta((m) => ({ ...m, errorMap: { ...m.errorMap, onSubmit: undefined } }))
|
|
153
|
+
}
|
|
140
154
|
}
|
|
141
155
|
|
|
142
156
|
// Note: Default value normalization (converting empty strings to null/undefined for nullable fields)
|
|
@@ -163,11 +177,13 @@ const inputProps: ComputedRef<InputProps<From, Name>> = computed(() => ({
|
|
|
163
177
|
minLength: props.meta?.type === "string" && props.meta?.minLength,
|
|
164
178
|
maxLength: props.meta?.type === "string" && props.meta?.maxLength,
|
|
165
179
|
max: (props.meta?.type === "number")
|
|
166
|
-
|
|
167
|
-
?? (typeof props.meta?.exclusiveMaximum === "number"
|
|
180
|
+
? (props.meta?.maximum
|
|
181
|
+
?? (typeof props.meta?.exclusiveMaximum === "number" ? props.meta.exclusiveMaximum - 1 : undefined))
|
|
182
|
+
: undefined,
|
|
168
183
|
min: (props.meta?.type === "number")
|
|
169
|
-
|
|
170
|
-
?? (typeof props.meta?.exclusiveMinimum === "number"
|
|
184
|
+
? (props.meta?.minimum
|
|
185
|
+
?? (typeof props.meta?.exclusiveMinimum === "number" ? props.meta.exclusiveMinimum + 1 : undefined))
|
|
186
|
+
: undefined,
|
|
171
187
|
errorMessages: errors.value,
|
|
172
188
|
error: !!errors.value.length,
|
|
173
189
|
type: fieldType.value,
|
|
@@ -3,24 +3,21 @@
|
|
|
3
3
|
|
|
4
4
|
import * as api from "@opentelemetry/api"
|
|
5
5
|
import { type DeepKeys, DeepValue, type FormAsyncValidateOrFn, type FormValidateOrFn, type StandardSchemaV1, StandardSchemaV1Issue, useForm, ValidationError, ValidationErrorMap } from "@tanstack/vue-form"
|
|
6
|
+
import { Array, Context, Data, Effect, Fiber, Option, Order, S } from "effect-app"
|
|
6
7
|
import { runtimeFiberAsPromise, UnionToTuples } from "effect-app/utils"
|
|
7
|
-
import * as Data from "effect/Data"
|
|
8
|
-
import * as Effect from "effect/Effect"
|
|
9
|
-
import * as Fiber from "effect/Fiber"
|
|
10
|
-
import * as Option from "effect/Option"
|
|
11
|
-
import * as Order from "effect/Order"
|
|
12
|
-
import * as S from "effect/Schema"
|
|
13
8
|
import { Component, computed, ComputedRef, ConcreteComponent, h, type InjectionKey, onBeforeUnmount, onMounted, onUnmounted, Ref, ref, watch } from "vue"
|
|
14
9
|
import { useIntl } from "../../utils"
|
|
15
10
|
import { MergedInputProps } from "./InputProps"
|
|
16
11
|
import OmegaArray from "./OmegaArray.vue"
|
|
17
12
|
import OmegaAutoGen from "./OmegaAutoGen.vue"
|
|
18
13
|
import OmegaErrorsInternal from "./OmegaErrorsInternal.vue"
|
|
19
|
-
import { BaseProps, deepMerge, defaultsValueFromSchema, DefaultTypeProps, FieldPath, type FormProps, generateMetaFromSchema, type MetaRecord, type NestedKeyOf, OmegaArrayProps, OmegaAutoGenMeta, OmegaError, type OmegaFormApi, OmegaFormState } from "./OmegaFormStuff"
|
|
14
|
+
import { BaseProps, deepMerge, defaultsValueFromSchema, DefaultTypeProps, FieldPath, type FormProps, generateMetaFromSchema, type MetaRecord, type NestedKeyOf, OmegaArrayProps, OmegaAutoGenMeta, OmegaError, type OmegaFormApi, OmegaFormState, toFormSchema } from "./OmegaFormStuff"
|
|
20
15
|
import OmegaInput from "./OmegaInput.vue"
|
|
21
16
|
import OmegaTaggedUnion from "./OmegaTaggedUnion.vue"
|
|
22
17
|
import OmegaForm from "./OmegaWrapper.vue"
|
|
23
18
|
|
|
19
|
+
import { makeRunPromise } from "@effect-app/vue/runtime"
|
|
20
|
+
|
|
24
21
|
type keysRule<T> =
|
|
25
22
|
| {
|
|
26
23
|
keys?: NestedKeyOf<T>[]
|
|
@@ -107,26 +104,25 @@ const eHoc = (errorProps: {
|
|
|
107
104
|
|
|
108
105
|
const errors = computed(() => {
|
|
109
106
|
// Collect errors from fieldMeta (field-level errors for registered fields)
|
|
110
|
-
const fieldErrors = Object
|
|
111
|
-
|
|
112
|
-
.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
return acc
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const fieldInfo = fieldMap.value.get(key)
|
|
119
|
-
if (!fieldInfo) {
|
|
120
|
-
return acc
|
|
121
|
-
}
|
|
107
|
+
const fieldErrors = Object.entries(fieldMeta.value).reduce<OmegaError[]>((acc, [key, m]) => {
|
|
108
|
+
const fieldErrors = (m as { errors?: Array<{ message?: string }> } | undefined)?.errors ?? []
|
|
109
|
+
if (!fieldErrors.length) {
|
|
110
|
+
return acc
|
|
111
|
+
}
|
|
122
112
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
inputId: fieldInfo.id,
|
|
126
|
-
errors: [fieldErrors[0]?.message].filter(Boolean) as string[]
|
|
127
|
-
})
|
|
113
|
+
const fieldInfo = fieldMap.value.get(key)
|
|
114
|
+
if (!fieldInfo) {
|
|
128
115
|
return acc
|
|
129
|
-
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
acc.push({
|
|
119
|
+
label: fieldInfo.label,
|
|
120
|
+
inputId: fieldInfo.id,
|
|
121
|
+
errors: [fieldErrors[0]?.message].filter(Boolean) as string[]
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
return acc
|
|
125
|
+
}, [])
|
|
130
126
|
|
|
131
127
|
// Collect errors from errorMap.onSubmit ONLY for fields that are NOT registered
|
|
132
128
|
// (registered fields already have their errors in fieldMeta)
|
|
@@ -401,7 +397,7 @@ export interface OmegaFormReturn<
|
|
|
401
397
|
> extends OF<From, To> {
|
|
402
398
|
// Pre-computed type aliases - computed ONCE for performance
|
|
403
399
|
_paths: FieldPath<From>
|
|
404
|
-
_keys:
|
|
400
|
+
_keys: NestedKeyOf<From>
|
|
405
401
|
_schema: S.Codec<To, From, never>
|
|
406
402
|
|
|
407
403
|
// this crazy thing here is copied from the OmegaFormInput.vue.d.ts, with `From` removed as Generic, instead closed over from the From generic above..
|
|
@@ -674,6 +670,8 @@ export interface OmegaFormReturn<
|
|
|
674
670
|
}
|
|
675
671
|
}
|
|
676
672
|
|
|
673
|
+
const runPromise = makeRunPromise(Context.empty())
|
|
674
|
+
|
|
677
675
|
export const useOmegaForm = <
|
|
678
676
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
679
677
|
From extends Record<PropertyKey, any>,
|
|
@@ -686,8 +684,9 @@ export const useOmegaForm = <
|
|
|
686
684
|
omegaConfig?: OmegaConfig<To>
|
|
687
685
|
): OmegaFormReturn<From, To, TypeProps> => {
|
|
688
686
|
if (!schema) throw new Error("Schema is required")
|
|
689
|
-
const
|
|
690
|
-
const
|
|
687
|
+
const formCompatibleSchema = toFormSchema(schema)
|
|
688
|
+
const standardSchema = S.toStandardSchemaV1(formCompatibleSchema)
|
|
689
|
+
const decode = S.decodeUnknownEffect(formCompatibleSchema)
|
|
691
690
|
|
|
692
691
|
const { meta, unionMeta } = generateMetaFromSchema(schema)
|
|
693
692
|
|
|
@@ -796,17 +795,20 @@ export const useOmegaForm = <
|
|
|
796
795
|
? ({ formApi, meta, value }) =>
|
|
797
796
|
wrapWithSpan(meta?.currentSpan, async () => {
|
|
798
797
|
// validators only validate, they don't actually transform, so we have to do that manually here.
|
|
799
|
-
const parsedValue = await
|
|
798
|
+
const parsedValue = await runPromise(decode(value))
|
|
800
799
|
const r = tanstackFormOptions.onSubmit!({
|
|
801
800
|
formApi: formApi as OmegaFormApi<From, To>,
|
|
802
801
|
meta,
|
|
803
802
|
value: parsedValue
|
|
804
803
|
})
|
|
805
804
|
if (Fiber.isFiber(r)) {
|
|
806
|
-
return await runtimeFiberAsPromise(r
|
|
805
|
+
return await runtimeFiberAsPromise(r)
|
|
807
806
|
}
|
|
808
807
|
if (Effect.isEffect(r)) {
|
|
809
|
-
|
|
808
|
+
const effectResult = await runPromise(r)
|
|
809
|
+
return Fiber.isFiber(effectResult)
|
|
810
|
+
? await runtimeFiberAsPromise(effectResult)
|
|
811
|
+
: effectResult
|
|
810
812
|
}
|
|
811
813
|
return r
|
|
812
814
|
})
|
|
@@ -836,11 +838,12 @@ export const useOmegaForm = <
|
|
|
836
838
|
|
|
837
839
|
const persistFilter = (persistency: OmegaConfig<From>["persistency"]) => {
|
|
838
840
|
if (!persistency) return
|
|
839
|
-
|
|
840
|
-
|
|
841
|
+
const { banKeys, keys } = persistency
|
|
842
|
+
if (Array.isArray(keys)) {
|
|
843
|
+
return createNestedObjectFromPaths(keys as string[])
|
|
841
844
|
}
|
|
842
|
-
if (Array.isArray(
|
|
843
|
-
const subs = Object.keys(meta).filter((metakey) =>
|
|
845
|
+
if (Array.isArray(banKeys)) {
|
|
846
|
+
const subs = Object.keys(meta).filter((metakey) => banKeys.includes(metakey as any))
|
|
844
847
|
return createNestedObjectFromPaths(subs)
|
|
845
848
|
}
|
|
846
849
|
return form.store.state.values
|
|
@@ -939,7 +942,7 @@ export const useOmegaForm = <
|
|
|
939
942
|
? handleSubmitEffect_(options?.meta).pipe(Effect.flatMap(Effect.fnUntraced(function*() {
|
|
940
943
|
const errors = form.getAllErrors()
|
|
941
944
|
if (Object.keys(errors.fields).length || errors.form.errors.length) {
|
|
942
|
-
return yield* new FormErrors({ form: errors.form, fields: errors.fields })
|
|
945
|
+
return yield* Effect.fail(new FormErrors({ form: errors.form, fields: errors.fields }))
|
|
943
946
|
}
|
|
944
947
|
})))
|
|
945
948
|
: handleSubmitEffect_(options?.meta)
|
|
@@ -976,6 +979,24 @@ export const useOmegaForm = <
|
|
|
976
979
|
}
|
|
977
980
|
})
|
|
978
981
|
|
|
982
|
+
// Clear all field onSubmit errors when any value changes after a failed submission.
|
|
983
|
+
// Form-level onSubmit validation (e.g. union schemas) distributes errors to individual fields.
|
|
984
|
+
// TanStack only clears the changed field's onSubmit error, leaving sibling fields with stale
|
|
985
|
+
// errors that keep isFieldsValid=false and block re-submission.
|
|
986
|
+
const lastSubmitAttempts = ref(0)
|
|
987
|
+
const submissionAttempts = form.useStore((s) => s.submissionAttempts)
|
|
988
|
+
const formValues = form.useStore((s) => s.values)
|
|
989
|
+
watch(formValues, () => {
|
|
990
|
+
if (lastSubmitAttempts.value === submissionAttempts.value) return
|
|
991
|
+
lastSubmitAttempts.value = submissionAttempts.value
|
|
992
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
993
|
+
for (const info of Object.values(form.fieldInfo) as any[]) {
|
|
994
|
+
if (info?.instance?.state.meta.errorMap?.onSubmit) {
|
|
995
|
+
info.instance.setMeta((prev: any) => ({ ...prev, errorMap: { ...prev.errorMap, onSubmit: undefined } }))
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
}, { deep: true })
|
|
999
|
+
|
|
979
1000
|
const errorContext = { form: formWithExtras, fieldMap }
|
|
980
1001
|
|
|
981
1002
|
return Object.assign(formWithExtras, {
|
package/src/reset.css
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Supplemental CSS reset for Vuetify 4.
|
|
3
|
+
* Vuetify 4 removed the aggressive global reset that v3 included.
|
|
4
|
+
* Import this file to restore equivalent behavior:
|
|
5
|
+
* import '@effect-app/vue-components/reset.css'
|
|
6
|
+
*/
|
|
7
|
+
@layer vuetify-reset {
|
|
8
|
+
body {
|
|
9
|
+
margin: 0;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
ul,
|
|
13
|
+
ol {
|
|
14
|
+
margin: 0;
|
|
15
|
+
padding: 0;
|
|
16
|
+
list-style: none;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
h1,
|
|
20
|
+
h2,
|
|
21
|
+
h3,
|
|
22
|
+
h4,
|
|
23
|
+
h5,
|
|
24
|
+
h6 {
|
|
25
|
+
margin: 0;
|
|
26
|
+
font-size: inherit;
|
|
27
|
+
font-weight: inherit;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
p {
|
|
31
|
+
margin: 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
input,
|
|
35
|
+
textarea,
|
|
36
|
+
select {
|
|
37
|
+
border: 0;
|
|
38
|
+
background: transparent;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
a {
|
|
42
|
+
text-decoration: none;
|
|
43
|
+
color: inherit;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
figure,
|
|
47
|
+
details,
|
|
48
|
+
summary {
|
|
49
|
+
margin: 0;
|
|
50
|
+
padding: 0;
|
|
51
|
+
}
|
|
52
|
+
}
|
package/src/utils/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type makeIntl } from "@effect-app/vue"
|
|
2
|
-
import {
|
|
2
|
+
import type { S } from "effect-app"
|
|
3
3
|
import { inject, type InjectionKey, provide } from "vue"
|
|
4
4
|
|
|
5
5
|
export const useIntlKey = Symbol() as InjectionKey<
|
|
@@ -17,16 +17,15 @@ export const provideIntl = (
|
|
|
17
17
|
) => provide(useIntlKey, intl)
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* @returns The source AST (the decoded/type form, which is the AST itself in v4)
|
|
20
|
+
* Walks the encoding chain of the given AST node to its source (encoded)
|
|
21
|
+
* side. Shallow — does not recurse into children, so inner prop-level
|
|
22
|
+
* transformations (e.g. `FiniteFromString`) keep their decoded shape
|
|
23
|
+
* while struct-level `decodeTo` transformations are unwrapped to their
|
|
24
|
+
* input side (e.g. `NonNegativeInt` rather than the decoded `PositiveInt`).
|
|
26
25
|
*/
|
|
27
26
|
export function getTransformationFrom(ast: S.AST.AST) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
while (ast.encoding) {
|
|
28
|
+
ast = ast.encoding[0].to
|
|
29
|
+
}
|
|
31
30
|
return ast
|
|
32
31
|
}
|
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
import { useForm as J } from "@tanstack/vue-form";
|
|
2
|
-
import { runtimeFiberAsPromise as q } from "./vue-components.es20.js";
|
|
3
|
-
import { TaggedError as B } from "./vue-components.es21.js";
|
|
4
|
-
import { currentSpan as K, runPromise as x, isEffect as T, flatMap as k, fnUntraced as z, option as G, promise as Z } from "./vue-components.es22.js";
|
|
5
|
-
import { isFiber as Q } from "./vue-components.es23.js";
|
|
6
|
-
import { isSome as X } from "./vue-components.es24.js";
|
|
7
|
-
import { toStandardSchemaV1 as Y, decodeEffect as C } from "./vue-components.es18.js";
|
|
8
|
-
import { computed as _, onUnmounted as I, onMounted as ee, onBeforeUnmount as re, watch as V, ref as te, h as N } from "vue";
|
|
9
|
-
import { useIntl as se } from "./vue-components.es3.js";
|
|
10
|
-
import ne from "./vue-components.es25.js";
|
|
11
|
-
import oe from "./vue-components.es26.js";
|
|
12
|
-
import ie from "./vue-components.es27.js";
|
|
13
|
-
import { generateMetaFromSchema as ae, deepMerge as W, defaultsValueFromSchema as ce } from "./vue-components.es12.js";
|
|
14
|
-
import le from "./vue-components.es6.js";
|
|
15
|
-
import ue from "./vue-components.es8.js";
|
|
16
|
-
import de from "./vue-components.es28.js";
|
|
17
|
-
import { trace as D } from "./vue-components.es29.js";
|
|
18
|
-
import { context as P } from "./vue-components.es30.js";
|
|
19
|
-
class me extends B("FormErrors") {
|
|
20
|
-
}
|
|
21
|
-
const A = (i) => function(s) {
|
|
22
|
-
return {
|
|
23
|
-
render() {
|
|
24
|
-
return N(s, {
|
|
25
|
-
form: i,
|
|
26
|
-
...this.$attrs
|
|
27
|
-
}, this.$slots);
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
}, fe = (i) => {
|
|
31
|
-
const { formatMessage: l } = se(), s = (a) => a.replace(/([A-Z])/g, " $1").replace(/^./, (g) => g.toUpperCase()).trim(), m = (a) => l ? l({ id: `general.fields.${a}`, defaultMessage: s(a) }) : s(a);
|
|
32
|
-
return (a) => i.i18nNamespace ? l({ id: `${i.i18nNamespace}.fields.${a}`, defaultMessage: m(a) }) : m(a);
|
|
33
|
-
}, pe = (i) => function(s) {
|
|
34
|
-
return {
|
|
35
|
-
setup() {
|
|
36
|
-
const { fieldMap: m, form: f } = i, a = f.useStore((v) => v.errors), g = f.useStore((v) => v.fieldMeta), p = f.useStore((v) => v.errorMap), M = fe(f), L = _(() => {
|
|
37
|
-
const v = Object.entries(g.value).reduce((b, [h, y]) => {
|
|
38
|
-
const u = y?.errors ?? [];
|
|
39
|
-
if (!u.length)
|
|
40
|
-
return b;
|
|
41
|
-
const d = m.value.get(h);
|
|
42
|
-
return d && b.push({
|
|
43
|
-
label: d.label,
|
|
44
|
-
inputId: d.id,
|
|
45
|
-
errors: [u[0]?.message].filter(Boolean)
|
|
46
|
-
}), b;
|
|
47
|
-
}, []), o = [];
|
|
48
|
-
if (p.value.onSubmit) {
|
|
49
|
-
for (const [b, h] of Object.entries(p.value.onSubmit))
|
|
50
|
-
if (Array.isArray(h) && h.length)
|
|
51
|
-
for (const y of h) {
|
|
52
|
-
const u = y;
|
|
53
|
-
if (u?.path && Array.isArray(u.path) && u.path.length) {
|
|
54
|
-
const d = u.path.join(".");
|
|
55
|
-
if (!m.value.has(d)) {
|
|
56
|
-
o.push({
|
|
57
|
-
label: M(d),
|
|
58
|
-
inputId: d,
|
|
59
|
-
errors: [u.message].filter(Boolean)
|
|
60
|
-
});
|
|
61
|
-
break;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
return [...v, ...o];
|
|
67
|
-
});
|
|
68
|
-
return {
|
|
69
|
-
generalErrors: a,
|
|
70
|
-
errors: L
|
|
71
|
-
};
|
|
72
|
-
},
|
|
73
|
-
render({ errors: m, generalErrors: f }) {
|
|
74
|
-
return N(s, {
|
|
75
|
-
errors: m,
|
|
76
|
-
generalErrors: f,
|
|
77
|
-
...this.$attrs
|
|
78
|
-
}, this.$slots);
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
}, S = (i, l) => i.includes(l), xe = (i, l, s) => {
|
|
82
|
-
if (!i) throw new Error("Schema is required");
|
|
83
|
-
const m = Y(i), f = C(i), { meta: a, unionMeta: g } = ae(i), p = _(() => {
|
|
84
|
-
if (s?.persistency?.id)
|
|
85
|
-
return s.persistency.id;
|
|
86
|
-
const e = window.location.pathname, r = Object.keys(a);
|
|
87
|
-
return `${e}-${r.join("-")}`;
|
|
88
|
-
}), M = () => {
|
|
89
|
-
const e = new URLSearchParams(window.location.search);
|
|
90
|
-
e.delete(p.value);
|
|
91
|
-
const r = new URL(window.location.href);
|
|
92
|
-
r.search = e.toString(), window.history.replaceState({}, "", r.toString());
|
|
93
|
-
}, L = _(() => {
|
|
94
|
-
let e;
|
|
95
|
-
const r = s?.persistency;
|
|
96
|
-
if (
|
|
97
|
-
// query string has higher priority than local/session storage
|
|
98
|
-
r?.policies && !e && (S(r.policies, "local") || S(r.policies, "session"))
|
|
99
|
-
) {
|
|
100
|
-
const n = S(r.policies, "local") ? localStorage : sessionStorage;
|
|
101
|
-
if (n)
|
|
102
|
-
try {
|
|
103
|
-
const t = JSON.parse(
|
|
104
|
-
n.getItem(p.value) || "{}"
|
|
105
|
-
);
|
|
106
|
-
n.removeItem(p.value), e = t;
|
|
107
|
-
} catch (t) {
|
|
108
|
-
console.error(t);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
if (r?.policies && S(r.policies, "querystring"))
|
|
112
|
-
try {
|
|
113
|
-
const t = new URLSearchParams(window.location.search).get(p.value);
|
|
114
|
-
M(), t && (e = W(e || {}, JSON.parse(t)));
|
|
115
|
-
} catch (n) {
|
|
116
|
-
console.error(n);
|
|
117
|
-
}
|
|
118
|
-
e ??= {};
|
|
119
|
-
const c = {
|
|
120
|
-
tanstack: l?.defaultValues || {},
|
|
121
|
-
persistency: e,
|
|
122
|
-
schema: ce(i)
|
|
123
|
-
};
|
|
124
|
-
return (s?.defaultValuesPriority || ["tanstack", "persistency", "schema"]).reverse().reduce(
|
|
125
|
-
(n, t) => Object.keys(n).length ? W(n, c[t]) : c[t],
|
|
126
|
-
{}
|
|
127
|
-
);
|
|
128
|
-
}), v = (e, r) => e ? P.with(D.setSpan(P.active(), e), r) : r(), o = J({
|
|
129
|
-
...l,
|
|
130
|
-
validators: {
|
|
131
|
-
onSubmit: m,
|
|
132
|
-
...l?.validators || {}
|
|
133
|
-
},
|
|
134
|
-
onSubmit: l?.onSubmit ? ({ formApi: e, meta: r, value: c }) => v(r?.currentSpan, async () => {
|
|
135
|
-
const n = await x(f(c)), t = l.onSubmit({
|
|
136
|
-
formApi: e,
|
|
137
|
-
meta: r,
|
|
138
|
-
value: n
|
|
139
|
-
});
|
|
140
|
-
return Q(t) ? await q(t) : T(t) ? await x(t) : t;
|
|
141
|
-
}) : void 0,
|
|
142
|
-
defaultValues: L.value
|
|
143
|
-
}), b = () => {
|
|
144
|
-
Object.keys(a).forEach((e) => {
|
|
145
|
-
o.setFieldValue(e, void 0);
|
|
146
|
-
});
|
|
147
|
-
}, h = (e) => e.reduce((r, c) => {
|
|
148
|
-
const n = c.split(".");
|
|
149
|
-
return n.reduce((t, E, O) => (O === n.length - 1 ? t[E] = o.getFieldValue(c) : t[E] = t[E] ?? {}, t[E]), r), r;
|
|
150
|
-
}, {}), y = (e) => {
|
|
151
|
-
if (e) {
|
|
152
|
-
if (Array.isArray(e.keys))
|
|
153
|
-
return h(e.keys);
|
|
154
|
-
if (Array.isArray(e.banKeys)) {
|
|
155
|
-
const r = Object.keys(a).filter((c) => e.banKeys?.includes(c));
|
|
156
|
-
return h(r);
|
|
157
|
-
}
|
|
158
|
-
return o.store.state.values;
|
|
159
|
-
}
|
|
160
|
-
}, u = () => {
|
|
161
|
-
const e = s?.persistency;
|
|
162
|
-
if (!(!e?.policies || e.policies.length === 0) && (S(e.policies, "local") || S(e.policies, "session"))) {
|
|
163
|
-
const r = S(e.policies, "local") ? localStorage : sessionStorage;
|
|
164
|
-
if (!r) return;
|
|
165
|
-
const c = y(e);
|
|
166
|
-
return r.setItem(p.value, JSON.stringify(c));
|
|
167
|
-
}
|
|
168
|
-
}, d = () => {
|
|
169
|
-
const e = s?.persistency;
|
|
170
|
-
if (!(!e?.policies || e.policies.length === 0) && S(e.policies, "querystring")) {
|
|
171
|
-
const r = y(e), c = new URLSearchParams(window.location.search);
|
|
172
|
-
c.set(p.value, JSON.stringify(r));
|
|
173
|
-
const n = new URL(window.location.href);
|
|
174
|
-
n.search = c.toString(), window.history.replaceState({}, "", n.toString());
|
|
175
|
-
}
|
|
176
|
-
}, $ = (e) => {
|
|
177
|
-
o.store.state.isDirty && e.preventDefault();
|
|
178
|
-
};
|
|
179
|
-
if (I(u), ee(() => {
|
|
180
|
-
window.addEventListener("beforeunload", u), window.addEventListener("blur", d), s?.preventWindowExit && s.preventWindowExit !== "nope" && window.addEventListener("beforeunload", $);
|
|
181
|
-
}), re(() => {
|
|
182
|
-
window.removeEventListener("beforeunload", u), window.removeEventListener("blur", d), s?.preventWindowExit && s.preventWindowExit !== "nope" && window.removeEventListener("beforeunload", $);
|
|
183
|
-
}), s?.preventWindowExit === "prevent-and-reset") {
|
|
184
|
-
const e = o.useStore((t) => t.isSubmitting), r = o.useStore((t) => t.submissionAttempts), c = o.useStore((t) => t.canSubmit), n = o.useStore((t) => t.values);
|
|
185
|
-
V([e, r], ([t, E], [O]) => {
|
|
186
|
-
O && !t && E > 0 && c.value && o.reset(n.value);
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
const j = (e) => K.pipe(
|
|
190
|
-
G,
|
|
191
|
-
k(
|
|
192
|
-
(r) => Z(() => o.handleSubmit(X(r) ? { currentSpan: r.value, ...e } : e))
|
|
193
|
-
)
|
|
194
|
-
), R = (e) => e?.checkErrors ? j(e?.meta).pipe(k(z(function* () {
|
|
195
|
-
const r = o.getAllErrors();
|
|
196
|
-
if (Object.keys(r.fields).length || r.form.errors.length)
|
|
197
|
-
return yield* new me({ form: r.form, fields: r.fields });
|
|
198
|
-
}))) : j(e?.meta), H = o.handleSubmit, F = te(/* @__PURE__ */ new Map()), w = Object.assign(o, {
|
|
199
|
-
i18nNamespace: s?.i18nNamespace,
|
|
200
|
-
ignorePreventCloseEvents: s?.ignorePreventCloseEvents,
|
|
201
|
-
meta: a,
|
|
202
|
-
unionMeta: g,
|
|
203
|
-
clear: b,
|
|
204
|
-
handleSubmit: (e) => {
|
|
205
|
-
const r = D.getSpan(P.active());
|
|
206
|
-
return H({ currentSpan: r, ...e });
|
|
207
|
-
},
|
|
208
|
-
// /** @experimental */
|
|
209
|
-
handleSubmitEffect: R,
|
|
210
|
-
registerField: (e) => {
|
|
211
|
-
V(e, (r) => {
|
|
212
|
-
F.value.set(r.name, { label: r.label, id: r.id });
|
|
213
|
-
}, { immediate: !0 }), I(() => {
|
|
214
|
-
F.value.get(e.value.name)?.id === e.value.id && F.value.delete(e.value.name);
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
}), U = { form: w, fieldMap: F };
|
|
218
|
-
return Object.assign(w, {
|
|
219
|
-
// Type-level properties for performance optimization (not used at runtime)
|
|
220
|
-
_paths: void 0,
|
|
221
|
-
_keys: void 0,
|
|
222
|
-
_schema: i,
|
|
223
|
-
errorContext: U,
|
|
224
|
-
Form: A(w)(de),
|
|
225
|
-
Input: A(w)(s?.input ?? le),
|
|
226
|
-
TaggedUnion: A(w)(ue),
|
|
227
|
-
Field: o.Field,
|
|
228
|
-
Errors: pe(U)(ie),
|
|
229
|
-
Array: A(w)(ne),
|
|
230
|
-
AutoGen: A(w)(oe)
|
|
231
|
-
});
|
|
232
|
-
};
|
|
233
|
-
export {
|
|
234
|
-
me as FormErrors,
|
|
235
|
-
fe as useErrorLabel,
|
|
236
|
-
xe as useOmegaForm
|
|
237
|
-
};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import l from "./vue-components.es35.js";
|
|
2
|
-
import { inject as c, provide as u } from "vue";
|
|
3
|
-
import { onMountedWithCleanup as f } from "./vue-components.es16.js";
|
|
4
|
-
const p = () => l(), i = /* @__PURE__ */ Symbol("DialogBus"), r = () => c(i, null), g = () => {
|
|
5
|
-
const n = p();
|
|
6
|
-
return u(i, n), n;
|
|
7
|
-
}, d = (n) => {
|
|
8
|
-
const o = r();
|
|
9
|
-
if (!o)
|
|
10
|
-
return;
|
|
11
|
-
const s = n();
|
|
12
|
-
f(() => {
|
|
13
|
-
const e = (t) => {
|
|
14
|
-
s.value && (confirm("Es sind ungespeicherte Änderungen vorhanden. Wirklich schließen?") || (t.prevent = !0));
|
|
15
|
-
};
|
|
16
|
-
return o.on("dialog-closing", e), () => o.off("dialog-closing", e);
|
|
17
|
-
});
|
|
18
|
-
}, h = (n) => {
|
|
19
|
-
let o = r();
|
|
20
|
-
return o || (o = g()), () => {
|
|
21
|
-
const e = {};
|
|
22
|
-
o.emit("dialog-closing", e), e.prevent ? typeof e.prevent == "object" && "then" in e.prevent && e.prevent.then((t) => {
|
|
23
|
-
t !== !1 && n();
|
|
24
|
-
}) : n();
|
|
25
|
-
};
|
|
26
|
-
};
|
|
27
|
-
export {
|
|
28
|
-
r as injectBus,
|
|
29
|
-
g as provideBus,
|
|
30
|
-
h as useOnClose,
|
|
31
|
-
d as usePreventClose
|
|
32
|
-
};
|