@effect-app/vue-components 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +184 -0
- package/dist/types/components/OmegaForm/OmegaErrors.vue.d.ts +2 -0
- package/dist/types/components/OmegaForm/OmegaErrorsContext.d.ts +35 -0
- package/dist/types/components/OmegaForm/OmegaFormStuff.d.ts +85 -0
- package/dist/types/components/OmegaForm/OmegaInput.vue.d.ts +38 -0
- package/dist/types/components/OmegaForm/OmegaInternalInput.vue.d.ts +25 -0
- package/dist/types/components/OmegaForm/OmegaWrapper.vue.d.ts +43 -0
- package/dist/types/components/OmegaForm/getOmegaStore.d.ts +3 -0
- package/dist/types/components/OmegaForm/index.d.ts +52 -0
- package/dist/types/components/OmegaForm/useOmegaForm.d.ts +6 -0
- package/dist/types/components/TestComponent.vue.d.ts +6 -0
- package/dist/types/components/index.d.ts +3 -0
- package/dist/types/constants/index.d.ts +1 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/utils/index.d.ts +7 -0
- package/dist/vue-components.css +1 -0
- package/dist/vue-components.es.js +624 -0
- package/package.json +48 -0
- package/src/assets/.keep +0 -0
- package/src/components/OmegaForm/OmegaErrors.vue +143 -0
- package/src/components/OmegaForm/OmegaErrorsContext.ts +64 -0
- package/src/components/OmegaForm/OmegaFormStuff.ts +575 -0
- package/src/components/OmegaForm/OmegaInput.vue +91 -0
- package/src/components/OmegaForm/OmegaInternalInput.vue +216 -0
- package/src/components/OmegaForm/OmegaWrapper.vue +137 -0
- package/src/components/OmegaForm/getOmegaStore.ts +32 -0
- package/src/components/OmegaForm/index.ts +29 -0
- package/src/components/OmegaForm/useOmegaForm.ts +61 -0
- package/src/components/TestComponent.vue +15 -0
- package/src/components/index.ts +6 -0
- package/src/components/style.css +3 -0
- package/src/constants/index.ts +1 -0
- package/src/env.d.ts +8 -0
- package/src/index.ts +17 -0
- package/src/utils/index.ts +12 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="omega-input">
|
|
3
|
+
<v-text-field
|
|
4
|
+
v-if="fieldType === 'email' || fieldType === 'text'"
|
|
5
|
+
:id="id"
|
|
6
|
+
:required="meta?.required"
|
|
7
|
+
:min-length="meta?.type === 'string' && meta?.minLength"
|
|
8
|
+
:max-length="meta?.type === 'string' && meta?.maxLength"
|
|
9
|
+
:type="fieldType"
|
|
10
|
+
:name="field.name"
|
|
11
|
+
:label="`${label}${meta?.required ? ' *' : ''}`"
|
|
12
|
+
:model-value="field.state.value"
|
|
13
|
+
:error-messages="showedErrors"
|
|
14
|
+
:error="!!showedErrors.length"
|
|
15
|
+
@update:model-value="field.handleChange"
|
|
16
|
+
@blur="setRealDirty"
|
|
17
|
+
/>
|
|
18
|
+
<v-text-field
|
|
19
|
+
v-if="fieldType === 'number'"
|
|
20
|
+
:id="id"
|
|
21
|
+
:required="meta?.required"
|
|
22
|
+
:min="meta?.type === 'number' && meta.minimum"
|
|
23
|
+
:max="meta?.type === 'number' && meta.maximum"
|
|
24
|
+
:type="fieldType"
|
|
25
|
+
:name="field.name"
|
|
26
|
+
:label="`${label}${meta?.required ? ' *' : ''}`"
|
|
27
|
+
:model-value="field.state.value"
|
|
28
|
+
:error-messages="showedErrors"
|
|
29
|
+
:error="!!showedErrors.length"
|
|
30
|
+
@update:model-value="
|
|
31
|
+
(e: any) => {
|
|
32
|
+
field.handleChange(Number(e))
|
|
33
|
+
}
|
|
34
|
+
"
|
|
35
|
+
@blur="setRealDirty"
|
|
36
|
+
/>
|
|
37
|
+
<div
|
|
38
|
+
v-if="fieldType === 'select' || fieldType === 'multiple'"
|
|
39
|
+
:class="fieldType !== 'multiple' && 'd-flex align-center'"
|
|
40
|
+
>
|
|
41
|
+
<v-select
|
|
42
|
+
:id="id"
|
|
43
|
+
:required="meta?.required"
|
|
44
|
+
:multiple="fieldType === 'multiple'"
|
|
45
|
+
:chips="fieldType === 'multiple'"
|
|
46
|
+
:name="field.name"
|
|
47
|
+
:model-value="field.state.value"
|
|
48
|
+
:label="`${label}${meta?.required ? ' *' : ''}`"
|
|
49
|
+
:items="options"
|
|
50
|
+
:error-messages="showedErrors"
|
|
51
|
+
:error="!!showedErrors.length"
|
|
52
|
+
@update:model-value="field.handleChange"
|
|
53
|
+
@blur="setRealDirty"
|
|
54
|
+
/>
|
|
55
|
+
<v-btn
|
|
56
|
+
v-if="fieldType !== 'multiple'"
|
|
57
|
+
variant-btn="secondary"
|
|
58
|
+
:variant-icon="mdiRefresh"
|
|
59
|
+
class="mr-2"
|
|
60
|
+
title="Reset"
|
|
61
|
+
@click="field.handleChange(undefined)"
|
|
62
|
+
></v-btn>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
</template>
|
|
66
|
+
|
|
67
|
+
<script setup lang="ts" generic="To">
|
|
68
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
69
|
+
import { VTextField, VSelect } from "vuetify/components"
|
|
70
|
+
import { mdiRefresh } from "@mdi/js"
|
|
71
|
+
import { useStore, type FieldApi } from "@tanstack/vue-form"
|
|
72
|
+
import type {
|
|
73
|
+
FieldValidators,
|
|
74
|
+
MetaRecord,
|
|
75
|
+
NestedKeyOf,
|
|
76
|
+
TypeOverride,
|
|
77
|
+
} from "./OmegaFormStuff"
|
|
78
|
+
import { useOmegaErrors } from "./OmegaErrorsContext"
|
|
79
|
+
import { useId, computed, watch, onMounted, ref, watchEffect } from "vue"
|
|
80
|
+
|
|
81
|
+
const props = defineProps<{
|
|
82
|
+
field: FieldApi<
|
|
83
|
+
any,
|
|
84
|
+
any,
|
|
85
|
+
any,
|
|
86
|
+
any,
|
|
87
|
+
any,
|
|
88
|
+
any,
|
|
89
|
+
any,
|
|
90
|
+
any,
|
|
91
|
+
any,
|
|
92
|
+
any,
|
|
93
|
+
any,
|
|
94
|
+
any,
|
|
95
|
+
any,
|
|
96
|
+
any,
|
|
97
|
+
any,
|
|
98
|
+
any,
|
|
99
|
+
any,
|
|
100
|
+
any,
|
|
101
|
+
any
|
|
102
|
+
>
|
|
103
|
+
meta: MetaRecord<To>[NestedKeyOf<To>]
|
|
104
|
+
label: string
|
|
105
|
+
options?: { title: string; value: string }[]
|
|
106
|
+
type?: TypeOverride
|
|
107
|
+
validators?: FieldValidators<To>
|
|
108
|
+
}>()
|
|
109
|
+
|
|
110
|
+
const id = useId()
|
|
111
|
+
|
|
112
|
+
const fieldApi = props.field
|
|
113
|
+
|
|
114
|
+
const fieldState = useStore(fieldApi.store, state => state)
|
|
115
|
+
|
|
116
|
+
const fieldType = computed(() => {
|
|
117
|
+
if (props.type) return props.type
|
|
118
|
+
if (props.meta?.type === "string") {
|
|
119
|
+
if (props.meta.format === "email") return "email"
|
|
120
|
+
return "text"
|
|
121
|
+
}
|
|
122
|
+
return props.meta?.type || "unknown"
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
const fieldValue = computed(() => fieldState.value.value)
|
|
126
|
+
const errors = computed(() =>
|
|
127
|
+
fieldState.value.meta.errors.map((e: any) => e.message).filter(Boolean),
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
// we remove value and errors when the field is empty and not required
|
|
131
|
+
//watchEffect will trigger infinite times with both free fieldValue and errors, so bet to watch a stupid boolean
|
|
132
|
+
watch(
|
|
133
|
+
() => [!!fieldValue.value],
|
|
134
|
+
() => {
|
|
135
|
+
if (errors.value.length && !fieldValue.value && !props.meta?.required) {
|
|
136
|
+
fieldApi.setValue(
|
|
137
|
+
props.meta?.nullableOrUndefined === "undefined" ? undefined : null,
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
onMounted(() => {
|
|
144
|
+
if (
|
|
145
|
+
!fieldValue.value &&
|
|
146
|
+
!props.meta?.required &&
|
|
147
|
+
props.meta?.nullableOrUndefined === "null"
|
|
148
|
+
) {
|
|
149
|
+
fieldApi.setValue(null)
|
|
150
|
+
}
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
const realDirty = ref(false)
|
|
154
|
+
const setRealDirty = () => {
|
|
155
|
+
realDirty.value = true
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const { addError, formSubmissionAttempts, removeError } = useOmegaErrors()
|
|
159
|
+
|
|
160
|
+
watchEffect(() => {
|
|
161
|
+
if (formSubmissionAttempts.value > 0) {
|
|
162
|
+
realDirty.value = true
|
|
163
|
+
}
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
const showedErrors = computed(() => {
|
|
167
|
+
// single select field can be validated on change
|
|
168
|
+
if (!realDirty.value && fieldType.value !== "select") return []
|
|
169
|
+
return errors.value
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
watch(
|
|
173
|
+
() => fieldState.value.meta.errors,
|
|
174
|
+
() => {
|
|
175
|
+
if (fieldState.value.meta.errors.length) {
|
|
176
|
+
addError({
|
|
177
|
+
inputId: id,
|
|
178
|
+
errors: fieldState.value.meta.errors
|
|
179
|
+
.map((e: any) => e.message)
|
|
180
|
+
.filter(Boolean),
|
|
181
|
+
label: props.label,
|
|
182
|
+
})
|
|
183
|
+
} else {
|
|
184
|
+
removeError(id)
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
)
|
|
188
|
+
</script>
|
|
189
|
+
|
|
190
|
+
<style>
|
|
191
|
+
.omega-input {
|
|
192
|
+
.v-input__details:has(.v-messages:empty) {
|
|
193
|
+
grid-template-rows: 0fr;
|
|
194
|
+
transition: all 0.2s;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
& .v-messages:empty {
|
|
198
|
+
min-height: 0;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
& .v-input__details:has(.v-messages) {
|
|
202
|
+
transition: all 0.2s;
|
|
203
|
+
overflow: hidden;
|
|
204
|
+
min-height: 0;
|
|
205
|
+
display: grid;
|
|
206
|
+
grid-template-rows: 1fr;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
& .v-messages {
|
|
210
|
+
transition: all 0.2s;
|
|
211
|
+
> * {
|
|
212
|
+
transition-duration: 0s !important;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
</style>
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<form @submit.prevent.stop="form.handleSubmit()">
|
|
3
|
+
<fieldset :disabled="formIsSubmitting">
|
|
4
|
+
<slot :form="form" :subscribed-values="subscribedValues" />
|
|
5
|
+
</fieldset>
|
|
6
|
+
</form>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<script
|
|
10
|
+
setup
|
|
11
|
+
lang="ts"
|
|
12
|
+
generic="
|
|
13
|
+
From extends Record<PropertyKey, any>,
|
|
14
|
+
To extends Record<PropertyKey, any>,
|
|
15
|
+
K extends keyof OmegaFormState<To, From> = keyof OmegaFormState<To, From>
|
|
16
|
+
"
|
|
17
|
+
>
|
|
18
|
+
/**
|
|
19
|
+
* Form component that wraps TanStack Form's useForm hook
|
|
20
|
+
*
|
|
21
|
+
* Usage:
|
|
22
|
+
* <Form :default-values="..." :on-submit="..." :validators="..." ...etc>
|
|
23
|
+
* <template #default="{ form }">
|
|
24
|
+
* <!-- Children with access to form -->
|
|
25
|
+
* <component :is="form.Field" name="fieldName">
|
|
26
|
+
* <template #default="{ field }">
|
|
27
|
+
* <input
|
|
28
|
+
* :value="field.state.value"
|
|
29
|
+
* @input="e => field.handleChange(e.target.value)"
|
|
30
|
+
* />
|
|
31
|
+
* </template>
|
|
32
|
+
* </component>
|
|
33
|
+
* </template>
|
|
34
|
+
* </Form>
|
|
35
|
+
*
|
|
36
|
+
* <Form :default-values="..." :on-submit="..." :validators="..." ...etc>
|
|
37
|
+
* <template #default="{ form }">
|
|
38
|
+
* <Input :form="form" name="foobar" />
|
|
39
|
+
* </template>
|
|
40
|
+
* </Form>
|
|
41
|
+
*
|
|
42
|
+
* <Form :schema="schema" :subscribe="['values', 'isSubmitting']">
|
|
43
|
+
* <template #default="{ form, subscribedValues }">
|
|
44
|
+
* <Input :form="form" name="foobar" />
|
|
45
|
+
* </template>
|
|
46
|
+
* </Form>
|
|
47
|
+
*/
|
|
48
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
49
|
+
import { useStore, type StandardSchemaV1Issue } from "@tanstack/vue-form"
|
|
50
|
+
import { type S } from "effect-app"
|
|
51
|
+
import {
|
|
52
|
+
type FilterItems,
|
|
53
|
+
type FormProps,
|
|
54
|
+
type MetaRecord,
|
|
55
|
+
type OmegaFormApi,
|
|
56
|
+
type OmegaFormState,
|
|
57
|
+
} from "./OmegaFormStuff"
|
|
58
|
+
import { getOmegaStore } from "./getOmegaStore"
|
|
59
|
+
import { provideOmegaErrors } from "./OmegaErrorsContext"
|
|
60
|
+
import { useOmegaForm } from "./useOmegaForm"
|
|
61
|
+
import { watch } from "vue"
|
|
62
|
+
|
|
63
|
+
const props = defineProps<
|
|
64
|
+
{
|
|
65
|
+
subscribe?: K[]
|
|
66
|
+
} & (
|
|
67
|
+
| {
|
|
68
|
+
form: OmegaFormApi<To, From> & {
|
|
69
|
+
meta: MetaRecord<To>
|
|
70
|
+
filterItems?: FilterItems
|
|
71
|
+
}
|
|
72
|
+
schema?: undefined
|
|
73
|
+
}
|
|
74
|
+
| (FormProps<To, From> & {
|
|
75
|
+
form?: undefined
|
|
76
|
+
schema: S.Schema<From, To, never>
|
|
77
|
+
})
|
|
78
|
+
)
|
|
79
|
+
>()
|
|
80
|
+
|
|
81
|
+
const form = props.form ?? useOmegaForm<From, To>(props.schema, props)
|
|
82
|
+
|
|
83
|
+
const formIsSubmitting = useStore(form.store, state => state.isSubmitting)
|
|
84
|
+
|
|
85
|
+
defineExpose(form)
|
|
86
|
+
|
|
87
|
+
const subscribedValues = getOmegaStore(
|
|
88
|
+
form as OmegaFormApi<To, From>,
|
|
89
|
+
props.subscribe,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
const formSubmissionAttempts = useStore(
|
|
93
|
+
form.store,
|
|
94
|
+
state => state.submissionAttempts,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
const errors = form.useStore(state => state.errors)
|
|
98
|
+
|
|
99
|
+
watch(
|
|
100
|
+
() => [form.filterItems, errors.value],
|
|
101
|
+
() => {
|
|
102
|
+
const filterItems: FilterItems | undefined = form.filterItems
|
|
103
|
+
if (!filterItems) return {}
|
|
104
|
+
if (!errors.value) return {}
|
|
105
|
+
const errorList = Object.values(errors.value)
|
|
106
|
+
.filter(
|
|
107
|
+
(fieldErrors): fieldErrors is Record<string, StandardSchemaV1Issue[]> =>
|
|
108
|
+
Boolean(fieldErrors),
|
|
109
|
+
)
|
|
110
|
+
.flatMap(fieldErrors =>
|
|
111
|
+
Object.values(fieldErrors)
|
|
112
|
+
.flat()
|
|
113
|
+
.map((issue: StandardSchemaV1Issue) => issue.message),
|
|
114
|
+
)
|
|
115
|
+
if (errorList.some(e => e === filterItems.message)) {
|
|
116
|
+
filterItems.items.forEach((item: any) => {
|
|
117
|
+
const m: any = form.getFieldMeta(item)
|
|
118
|
+
form.setFieldMeta(item, {
|
|
119
|
+
...m,
|
|
120
|
+
errorMap: {
|
|
121
|
+
onSubmit: [{ path: [item], message: filterItems.message }],
|
|
122
|
+
},
|
|
123
|
+
})
|
|
124
|
+
})
|
|
125
|
+
}
|
|
126
|
+
return {}
|
|
127
|
+
},
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
provideOmegaErrors(formSubmissionAttempts, errors)
|
|
131
|
+
</script>
|
|
132
|
+
|
|
133
|
+
<style scoped>
|
|
134
|
+
fieldset {
|
|
135
|
+
display: contents;
|
|
136
|
+
}
|
|
137
|
+
</style>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useStore } from "@tanstack/vue-form"
|
|
2
|
+
import { type Ref, computed } from "vue"
|
|
3
|
+
import type { OmegaFormState, OmegaFormApi } from "./OmegaFormStuff"
|
|
4
|
+
|
|
5
|
+
export function getOmegaStore<
|
|
6
|
+
To,
|
|
7
|
+
From,
|
|
8
|
+
K extends keyof OmegaFormState<To, From> = keyof OmegaFormState<To, From>,
|
|
9
|
+
>(
|
|
10
|
+
form: OmegaFormApi<To, From>,
|
|
11
|
+
subscribe?: K[],
|
|
12
|
+
): Ref<
|
|
13
|
+
K[] extends undefined
|
|
14
|
+
? Record<string, never>
|
|
15
|
+
: Pick<OmegaFormState<To, From>, K>
|
|
16
|
+
> {
|
|
17
|
+
return computed(() => {
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
+
if (!subscribe) return {} as any
|
|
20
|
+
|
|
21
|
+
const state = useStore(form.store, state => {
|
|
22
|
+
const result = {} as Pick<OmegaFormState<To, From>, K>
|
|
23
|
+
for (const key of subscribe) {
|
|
24
|
+
result[key] = state[key]
|
|
25
|
+
}
|
|
26
|
+
return result
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
return state.value
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
31
|
+
}) as any // Type assertion needed due to Vue's computed typing limitations
|
|
32
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { defineCustomElement } from "vue"
|
|
2
|
+
import { default as OmegaForm } from "./OmegaWrapper.vue"
|
|
3
|
+
import { default as OmegaInput } from "./OmegaInput.vue"
|
|
4
|
+
import { default as OmegaErrors } from "./OmegaErrors.vue"
|
|
5
|
+
|
|
6
|
+
export * as OmegaErrorsContext from "./OmegaErrorsContext"
|
|
7
|
+
export * from "./OmegaFormStuff"
|
|
8
|
+
export { useOmegaForm } from "./useOmegaForm"
|
|
9
|
+
export { default } from "./OmegaWrapper.vue"
|
|
10
|
+
|
|
11
|
+
export { OmegaForm, OmegaInput, OmegaErrors }
|
|
12
|
+
|
|
13
|
+
const OmegaFormCE = defineCustomElement(OmegaForm)
|
|
14
|
+
const OmegaInputCE = defineCustomElement(OmegaInput)
|
|
15
|
+
const OmegaErrorsCE = defineCustomElement(OmegaErrors)
|
|
16
|
+
|
|
17
|
+
export { OmegaFormCE, OmegaInputCE, OmegaErrorsCE }
|
|
18
|
+
|
|
19
|
+
export function registerOmegaForm() {
|
|
20
|
+
if (!customElements.get("omega-form")) {
|
|
21
|
+
customElements.define("omega-form", OmegaFormCE)
|
|
22
|
+
}
|
|
23
|
+
if (!customElements.get("omega-input")) {
|
|
24
|
+
customElements.define("omega-input", OmegaInputCE)
|
|
25
|
+
}
|
|
26
|
+
if (!customElements.get("omega-errors")) {
|
|
27
|
+
customElements.define("omega-errors", OmegaErrorsCE)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useForm,
|
|
3
|
+
type FormValidateOrFn,
|
|
4
|
+
type FormAsyncValidateOrFn,
|
|
5
|
+
type StandardSchemaV1,
|
|
6
|
+
} from "@tanstack/vue-form"
|
|
7
|
+
import { S } from "effect-app"
|
|
8
|
+
import {
|
|
9
|
+
generateMetaFromSchema,
|
|
10
|
+
type FilterItems,
|
|
11
|
+
type FormProps,
|
|
12
|
+
type MetaRecord,
|
|
13
|
+
type OmegaFormApi,
|
|
14
|
+
} from "./OmegaFormStuff"
|
|
15
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
16
|
+
export const useOmegaForm = <
|
|
17
|
+
From extends Record<PropertyKey, any>,
|
|
18
|
+
To extends Record<PropertyKey, any>,
|
|
19
|
+
>(
|
|
20
|
+
schema: S.Schema<From, To, never>,
|
|
21
|
+
options?: NoInfer<FormProps<To, From>>,
|
|
22
|
+
): OmegaFormApi<To, From> & {
|
|
23
|
+
meta: MetaRecord<To>
|
|
24
|
+
filterItems?: FilterItems
|
|
25
|
+
} => {
|
|
26
|
+
if (!schema) throw new Error("Schema is required")
|
|
27
|
+
const standardSchema = S.standardSchemaV1(schema)
|
|
28
|
+
|
|
29
|
+
const { filterItems, meta } = generateMetaFromSchema(schema)
|
|
30
|
+
|
|
31
|
+
const form = useForm<
|
|
32
|
+
To,
|
|
33
|
+
FormValidateOrFn<To> | undefined,
|
|
34
|
+
FormValidateOrFn<To> | undefined,
|
|
35
|
+
StandardSchemaV1<To, From>,
|
|
36
|
+
FormValidateOrFn<To> | undefined,
|
|
37
|
+
FormAsyncValidateOrFn<To> | undefined,
|
|
38
|
+
FormValidateOrFn<To> | undefined,
|
|
39
|
+
FormAsyncValidateOrFn<To> | undefined,
|
|
40
|
+
FormAsyncValidateOrFn<To> | undefined,
|
|
41
|
+
FormAsyncValidateOrFn<To> | undefined
|
|
42
|
+
>({
|
|
43
|
+
...options,
|
|
44
|
+
validators: {
|
|
45
|
+
onSubmit: standardSchema,
|
|
46
|
+
...(options?.validators || {}),
|
|
47
|
+
},
|
|
48
|
+
onSubmit: options?.onSubmit
|
|
49
|
+
? ({ formApi, meta, value }) =>
|
|
50
|
+
options.onSubmit?.({
|
|
51
|
+
formApi: formApi as OmegaFormApi<To, From>,
|
|
52
|
+
meta,
|
|
53
|
+
value: value as unknown as From,
|
|
54
|
+
})
|
|
55
|
+
: undefined,
|
|
56
|
+
}) satisfies OmegaFormApi<To, From>
|
|
57
|
+
|
|
58
|
+
const exposed = Object.assign(form, { meta, filterItems })
|
|
59
|
+
|
|
60
|
+
return exposed
|
|
61
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="cool">I'm so <span class="super">{{ cool }}</span> {{ test }}</div>
|
|
3
|
+
</template>
|
|
4
|
+
<style scoped>
|
|
5
|
+
.super {
|
|
6
|
+
color: aqua;
|
|
7
|
+
}
|
|
8
|
+
</style>
|
|
9
|
+
<script setup lang="ts">
|
|
10
|
+
import "./style.css"
|
|
11
|
+
import { ref, defineProps } from "vue"
|
|
12
|
+
const cool = ref("COOL")
|
|
13
|
+
|
|
14
|
+
defineProps<{ test: string }>()
|
|
15
|
+
</script>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
package/src/env.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
2
|
+
|
|
3
|
+
declare module '*.vue' {
|
|
4
|
+
import { DefineComponent } from 'vue'
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
|
|
6
|
+
const component: DefineComponent<{}, {}, any>
|
|
7
|
+
export default component
|
|
8
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { App } from 'vue'
|
|
2
|
+
import * as components from './components'
|
|
3
|
+
|
|
4
|
+
function install (app: App) {
|
|
5
|
+
for (const key in components) {
|
|
6
|
+
// @ts-expect-error
|
|
7
|
+
app.component(key, components[key])
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// import './assets/main.scss'
|
|
12
|
+
|
|
13
|
+
export default { install }
|
|
14
|
+
|
|
15
|
+
export * from './components'
|
|
16
|
+
export * from './constants'
|
|
17
|
+
export * from './utils'
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { inject, InjectionKey, provide, ref } from "vue";
|
|
2
|
+
import { makeIntl} from "@effect-app/vue"
|
|
3
|
+
|
|
4
|
+
const intlKey = Symbol() as InjectionKey<ReturnType<ReturnType<typeof makeIntl>["useIntl"]>>
|
|
5
|
+
export const useIntl = () => {
|
|
6
|
+
const intl = inject(intlKey)
|
|
7
|
+
if (!intl) {
|
|
8
|
+
throw new Error("useIntl must be used within a IntlProvider")
|
|
9
|
+
}
|
|
10
|
+
return intl
|
|
11
|
+
}
|
|
12
|
+
export const provideIntl = (intl: ReturnType<ReturnType<typeof makeIntl>["useIntl"]>) => provide(intlKey, intl)
|