@effect-app/vue-components 0.2.8 → 0.3.0
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/dist/types/components/OmegaForm/OmegaWrapper.vue.d.ts +7 -14
- package/dist/types/components/OmegaForm/getOmegaStore.d.ts +1 -1
- package/dist/types/components/OmegaForm/index.d.ts +3 -4
- package/dist/types/components/OmegaForm/useOmegaForm.d.ts +20 -3
- package/dist/vue-components.es11.js +17 -15
- package/dist/vue-components.es15.js +4 -89
- package/dist/vue-components.es16.js +93 -11
- package/dist/vue-components.es17.js +11 -2
- package/dist/vue-components.es18.js +2 -115
- package/dist/vue-components.es19.js +117 -0
- package/dist/{vue-components.es20.js → vue-components.es21.js} +1 -1
- package/dist/vue-components.es5.js +82 -16
- package/dist/vue-components.es7.js +2 -2
- package/dist/vue-components.es8.js +1 -1
- package/package.json +11 -2
- package/src/components/OmegaForm/OmegaInternalInput.vue +6 -0
- package/src/components/OmegaForm/OmegaWrapper.vue +10 -8
- package/src/components/OmegaForm/getOmegaStore.ts +1 -1
- package/src/components/OmegaForm/useOmegaForm.ts +133 -11
- package/src/stories/OmegaForm/ComplexForm.vue +81 -0
- package/src/stories/OmegaForm/EmailForm.vue +48 -0
- package/src/stories/OmegaForm/PersistencyForm.vue +65 -0
- package/src/stories/OmegaForm/SimpleForm.vue +30 -0
- package/src/stories/OmegaForm/SimpleFormVuetifyDefault.vue +15 -0
- package/src/stories/OmegaForm/SumExample.vue +39 -0
- package/src/stories/OmegaForm.stories.ts +83 -0
- package/src/stories/README.md +29 -0
- package/src/stories/tsconfig.json +4 -0
|
@@ -1,25 +1,91 @@
|
|
|
1
|
-
import { useForm as
|
|
2
|
-
import { S as
|
|
3
|
-
import { generateMetaFromSchema as
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { useForm as E } from "@tanstack/vue-form";
|
|
2
|
+
import { S as j, Match as n } from "effect-app";
|
|
3
|
+
import { generateMetaFromSchema as A } from "./vue-components.es6.js";
|
|
4
|
+
import { computed as b, onUnmounted as I, onMounted as K, onBeforeUnmount as M } from "vue";
|
|
5
|
+
import { constVoid as x } from "./vue-components.es15.js";
|
|
6
|
+
const m = (i, e, u) => {
|
|
7
|
+
if (!i) throw new Error("Schema is required");
|
|
8
|
+
const a = j.standardSchemaV1(i), { filterItems: f, meta: y } = A(i), o = b(() => {
|
|
9
|
+
var d;
|
|
10
|
+
if ((d = u == null ? void 0 : u.persistency) != null && d.id)
|
|
11
|
+
return u.persistency.id;
|
|
12
|
+
const l = window.location.pathname, r = Object.keys(y);
|
|
13
|
+
return `${l}-${r.join("-")}`;
|
|
14
|
+
}), w = b(() => {
|
|
15
|
+
var r;
|
|
16
|
+
if (e != null && e.defaultValues && !((r = u == null ? void 0 : u.persistency) != null && r.overrideDefaultValues))
|
|
17
|
+
return e.defaultValues;
|
|
18
|
+
const l = u == null ? void 0 : u.persistency;
|
|
19
|
+
return n.value(l).pipe(
|
|
20
|
+
n.when(
|
|
21
|
+
{ method: (d) => ["local", "session"].includes(d) },
|
|
22
|
+
(d) => {
|
|
23
|
+
const c = d.method === "local" ? localStorage : sessionStorage;
|
|
24
|
+
if (c)
|
|
25
|
+
try {
|
|
26
|
+
const s = JSON.parse(
|
|
27
|
+
c.getItem(o.value) || "{}"
|
|
28
|
+
);
|
|
29
|
+
return c.removeItem(o.value), s;
|
|
30
|
+
} catch (s) {
|
|
31
|
+
return console.error(s), {};
|
|
32
|
+
}
|
|
33
|
+
return {};
|
|
34
|
+
}
|
|
35
|
+
),
|
|
36
|
+
n.orElse(() => ({}))
|
|
37
|
+
);
|
|
38
|
+
}), h = E({
|
|
7
39
|
...e,
|
|
8
40
|
validators: {
|
|
9
41
|
onSubmit: a,
|
|
10
42
|
...(e == null ? void 0 : e.validators) || {}
|
|
11
43
|
},
|
|
12
|
-
onSubmit: e != null && e.onSubmit ? ({ formApi:
|
|
13
|
-
var
|
|
14
|
-
return (
|
|
15
|
-
formApi:
|
|
16
|
-
meta:
|
|
17
|
-
value:
|
|
44
|
+
onSubmit: e != null && e.onSubmit ? ({ formApi: l, meta: r, value: d }) => {
|
|
45
|
+
var t;
|
|
46
|
+
return (t = e.onSubmit) == null ? void 0 : t.call(e, {
|
|
47
|
+
formApi: l,
|
|
48
|
+
meta: r,
|
|
49
|
+
value: d
|
|
18
50
|
});
|
|
19
|
-
} : void 0
|
|
20
|
-
|
|
21
|
-
|
|
51
|
+
} : void 0,
|
|
52
|
+
defaultValues: w.value
|
|
53
|
+
}), V = Object.assign(h, { meta: y, filterItems: f, clear: () => {
|
|
54
|
+
Object.keys(y).forEach((l) => {
|
|
55
|
+
h.setFieldValue(l, void 0);
|
|
56
|
+
});
|
|
57
|
+
} }), v = () => {
|
|
58
|
+
const l = u == null ? void 0 : u.persistency;
|
|
59
|
+
n.value(l).pipe(
|
|
60
|
+
n.when(
|
|
61
|
+
{ method: (r) => ["local", "session"].includes(r) },
|
|
62
|
+
(r) => {
|
|
63
|
+
const t = r.method === "local" ? localStorage : sessionStorage;
|
|
64
|
+
if (t)
|
|
65
|
+
return Array.isArray(r.keys) && Object.keys(y).filter(
|
|
66
|
+
(s) => {
|
|
67
|
+
var S;
|
|
68
|
+
return !((S = r.keys) != null && S.includes(s));
|
|
69
|
+
}
|
|
70
|
+
).forEach((s) => {
|
|
71
|
+
h.setFieldValue(s, void 0);
|
|
72
|
+
}), Array.isArray(r.banKeys) && r.banKeys.forEach((c) => {
|
|
73
|
+
h.setFieldValue(c, void 0);
|
|
74
|
+
}), t.setItem(
|
|
75
|
+
o.value,
|
|
76
|
+
JSON.stringify(h.store.state.values)
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
),
|
|
80
|
+
n.orElse(x)
|
|
81
|
+
);
|
|
82
|
+
};
|
|
83
|
+
return I(v), K(() => {
|
|
84
|
+
window.addEventListener("beforeunload", v);
|
|
85
|
+
}), M(() => {
|
|
86
|
+
window.removeEventListener("beforeunload", v);
|
|
87
|
+
}), V;
|
|
22
88
|
};
|
|
23
89
|
export {
|
|
24
|
-
|
|
90
|
+
m as useOmegaForm
|
|
25
91
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
(function(){"use strict";try{if(typeof document<"u"){var n=document.createElement("style");if(n.appendChild(document.createTextNode("fieldset[data-v-
|
|
1
|
+
(function(){"use strict";try{if(typeof document<"u"){var n=document.createElement("style");if(n.appendChild(document.createTextNode("fieldset[data-v-fd152523]{display:contents}")),document.head.appendChild(n),window.customElements){const e=window.customElements.define;window.customElements.define=function(i,t){const d=t.prototype.connectedCallback;return t.prototype.connectedCallback=function(){if(d&&d.call(this),this.shadowRoot){const o=document.createElement("style");o.appendChild(document.createTextNode("fieldset[data-v-fd152523]{display:contents}")),this.shadowRoot.appendChild(o)}},e.call(window.customElements,i,t)}}}}catch(e){console.error("vite-plugin-css-injected-by-js",e)}})();
|
|
2
2
|
import o from "./vue-components.es11.js";
|
|
3
3
|
import m from "./vue-components.es12.js";
|
|
4
|
-
const a = /* @__PURE__ */ m(o, [["__scopeId", "data-v-
|
|
4
|
+
const a = /* @__PURE__ */ m(o, [["__scopeId", "data-v-fd152523"]]);
|
|
5
5
|
export {
|
|
6
6
|
a as default
|
|
7
7
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineComponent as i, computed as t, createBlock as p, openBlock as d, resolveDynamicComponent as u, withCtx as r, createVNode as f, mergeProps as c, renderSlot as v, normalizeProps as h, guardReactiveProps as g } from "vue";
|
|
2
2
|
import { generateInputStandardSchemaFromFieldMeta as y } from "./vue-components.es6.js";
|
|
3
|
-
import b from "./vue-components.
|
|
3
|
+
import b from "./vue-components.es16.js";
|
|
4
4
|
const S = /* @__PURE__ */ i({
|
|
5
5
|
inheritAttrs: !1,
|
|
6
6
|
__name: "OmegaInput",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect-app/vue-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@mdi/js": "^7.4.47",
|
|
6
6
|
"@tanstack/vue-form": "^1.2.4",
|
|
@@ -14,6 +14,12 @@
|
|
|
14
14
|
"vuetify": "^3.7.19"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
|
+
"@storybook/addon-essentials": "^8.6.12",
|
|
18
|
+
"@storybook/addon-interactions": "^8.6.12",
|
|
19
|
+
"@storybook/blocks": "^8.6.12",
|
|
20
|
+
"@storybook/testing-library": "^0.2.2",
|
|
21
|
+
"@storybook/vue3": "^8.6.12",
|
|
22
|
+
"@storybook/vue3-vite": "^8.6.12",
|
|
17
23
|
"@types/node": "^22.13.14",
|
|
18
24
|
"@typescript-eslint/eslint-plugin": "8.29.0",
|
|
19
25
|
"@typescript-eslint/parser": "8.29.0",
|
|
@@ -24,6 +30,7 @@
|
|
|
24
30
|
"eslint-plugin-vue": "^10.0.0",
|
|
25
31
|
"rimraf": "^6.0.1",
|
|
26
32
|
"sass": "^1.86.0",
|
|
33
|
+
"storybook": "^8.6.12",
|
|
27
34
|
"typescript": "^5.8.2",
|
|
28
35
|
"vite": "^6.2.3",
|
|
29
36
|
"vite-plugin-css-injected-by-js": "^3.5.2",
|
|
@@ -52,6 +59,8 @@
|
|
|
52
59
|
"docs:build": "vitepress build docs",
|
|
53
60
|
"docs:serve": "vitepress serve docs",
|
|
54
61
|
"lint": "NODE_OPTIONS=--max-old-space-size=8192 eslint src",
|
|
55
|
-
"autofix": "pnpm lint --fix"
|
|
62
|
+
"autofix": "pnpm lint --fix",
|
|
63
|
+
"storybook": "storybook dev -p 6006",
|
|
64
|
+
"build-storybook": "storybook build"
|
|
56
65
|
}
|
|
57
66
|
}
|
|
@@ -106,6 +106,12 @@ const setRealDirty = () => {
|
|
|
106
106
|
realDirty.value = true
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
onMounted(() => {
|
|
110
|
+
if (fieldValue.value) {
|
|
111
|
+
setRealDirty()
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
|
|
109
115
|
const showedErrors = computed(() => {
|
|
110
116
|
// single select field can be validated on change
|
|
111
117
|
if (!realDirty.value && fieldType.value !== "select") return []
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<form @submit.prevent.stop="form.handleSubmit()">
|
|
2
|
+
<form novalidate @submit.prevent.stop="form.handleSubmit()">
|
|
3
3
|
<fieldset :disabled="formIsSubmitting">
|
|
4
4
|
<slot :form="form" :subscribed-values="subscribedValues" />
|
|
5
5
|
</fieldset>
|
|
@@ -51,26 +51,27 @@ import { type S } from "effect-app"
|
|
|
51
51
|
import {
|
|
52
52
|
type FilterItems,
|
|
53
53
|
type FormProps,
|
|
54
|
-
type MetaRecord,
|
|
55
54
|
type OmegaFormApi,
|
|
56
55
|
type OmegaFormState,
|
|
57
56
|
type ShowErrorsOn,
|
|
58
57
|
} from "./OmegaFormStuff"
|
|
59
58
|
import { getOmegaStore } from "./getOmegaStore"
|
|
60
59
|
import { provideOmegaErrors } from "./OmegaErrorsContext"
|
|
61
|
-
import {
|
|
60
|
+
import {
|
|
61
|
+
type OmegaConfig,
|
|
62
|
+
type OmegaFormReturn,
|
|
63
|
+
useOmegaForm,
|
|
64
|
+
} from "./useOmegaForm"
|
|
62
65
|
import { watch } from "vue"
|
|
63
66
|
|
|
64
67
|
const props = defineProps<
|
|
65
68
|
{
|
|
69
|
+
omegaConfig?: OmegaConfig<From>
|
|
66
70
|
subscribe?: K[]
|
|
67
71
|
showErrorsOn?: ShowErrorsOn
|
|
68
72
|
} & (
|
|
69
73
|
| {
|
|
70
|
-
form:
|
|
71
|
-
meta: MetaRecord<To>
|
|
72
|
-
filterItems?: FilterItems
|
|
73
|
-
}
|
|
74
|
+
form: OmegaFormReturn<To, From>
|
|
74
75
|
schema?: undefined
|
|
75
76
|
}
|
|
76
77
|
| (FormProps<To, From> & {
|
|
@@ -80,7 +81,8 @@ const props = defineProps<
|
|
|
80
81
|
)
|
|
81
82
|
>()
|
|
82
83
|
|
|
83
|
-
const form =
|
|
84
|
+
const form =
|
|
85
|
+
props.form ?? useOmegaForm<From, To>(props.schema, props, props.omegaConfig)
|
|
84
86
|
|
|
85
87
|
const formIsSubmitting = useStore(form.store, state => state.isSubmitting)
|
|
86
88
|
|
|
@@ -1,17 +1,45 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1
2
|
import {
|
|
2
3
|
useForm,
|
|
3
4
|
type FormValidateOrFn,
|
|
4
5
|
type FormAsyncValidateOrFn,
|
|
5
6
|
type StandardSchemaV1,
|
|
6
7
|
} from "@tanstack/vue-form"
|
|
7
|
-
import { S } from "effect-app"
|
|
8
|
+
import { Match, S } from "effect-app"
|
|
8
9
|
import {
|
|
9
10
|
generateMetaFromSchema,
|
|
11
|
+
type NestedKeyOf,
|
|
10
12
|
type FilterItems,
|
|
11
13
|
type FormProps,
|
|
12
14
|
type MetaRecord,
|
|
13
15
|
type OmegaFormApi,
|
|
14
16
|
} from "./OmegaFormStuff"
|
|
17
|
+
import { computed, onBeforeUnmount, onMounted, onUnmounted } from "vue"
|
|
18
|
+
import { constVoid } from "effect/Function"
|
|
19
|
+
|
|
20
|
+
type keysRule<T> =
|
|
21
|
+
| {
|
|
22
|
+
keys?: NestedKeyOf<T>[]
|
|
23
|
+
banKeys?: "You should only use one of banKeys or keys, not both, moron"
|
|
24
|
+
}
|
|
25
|
+
| {
|
|
26
|
+
keys?: "You should only use one of banKeys or keys, not both, moron"
|
|
27
|
+
banKeys?: NestedKeyOf<T>[]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type OmegaConfig<T> = {
|
|
31
|
+
persistency?: {
|
|
32
|
+
method?: "session" | "local" | "none"
|
|
33
|
+
overrideDefaultValues?: boolean
|
|
34
|
+
id?: string
|
|
35
|
+
} & keysRule<T>
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface OmegaFormReturn<To, From> extends OmegaFormApi<To, From> {
|
|
39
|
+
meta: MetaRecord<To>
|
|
40
|
+
filterItems?: FilterItems
|
|
41
|
+
clear: () => void
|
|
42
|
+
}
|
|
15
43
|
|
|
16
44
|
export const useOmegaForm = <
|
|
17
45
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -20,16 +48,55 @@ export const useOmegaForm = <
|
|
|
20
48
|
To extends Record<PropertyKey, any>,
|
|
21
49
|
>(
|
|
22
50
|
schema: S.Schema<From, To, never>,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
filterItems?: FilterItems
|
|
27
|
-
} => {
|
|
51
|
+
tanstackFormOptions?: NoInfer<FormProps<To, From>>,
|
|
52
|
+
omegaConfig?: OmegaConfig<From>,
|
|
53
|
+
): OmegaFormReturn<To, From> => {
|
|
28
54
|
if (!schema) throw new Error("Schema is required")
|
|
29
55
|
const standardSchema = S.standardSchemaV1(schema)
|
|
30
56
|
|
|
31
57
|
const { filterItems, meta } = generateMetaFromSchema(schema)
|
|
32
58
|
|
|
59
|
+
const persistencyKey = computed(() => {
|
|
60
|
+
if (omegaConfig?.persistency?.id) {
|
|
61
|
+
return omegaConfig.persistency.id
|
|
62
|
+
}
|
|
63
|
+
const path = window.location.pathname
|
|
64
|
+
const keys = Object.keys(meta)
|
|
65
|
+
return `${path}-${keys.join("-")}`
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
const defaultValues = computed(() => {
|
|
69
|
+
if (
|
|
70
|
+
tanstackFormOptions?.defaultValues &&
|
|
71
|
+
!omegaConfig?.persistency?.overrideDefaultValues
|
|
72
|
+
)
|
|
73
|
+
return tanstackFormOptions.defaultValues
|
|
74
|
+
const persistency = omegaConfig?.persistency
|
|
75
|
+
return Match.value(persistency).pipe(
|
|
76
|
+
Match.when(
|
|
77
|
+
{ method: method => ["local", "session"].includes(method) },
|
|
78
|
+
persistency => {
|
|
79
|
+
const method = persistency.method
|
|
80
|
+
const storage = method === "local" ? localStorage : sessionStorage
|
|
81
|
+
if (storage) {
|
|
82
|
+
try {
|
|
83
|
+
const value = JSON.parse(
|
|
84
|
+
storage.getItem(persistencyKey.value) || "{}",
|
|
85
|
+
)
|
|
86
|
+
storage.removeItem(persistencyKey.value)
|
|
87
|
+
return value
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error(error)
|
|
90
|
+
return {}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return {}
|
|
94
|
+
},
|
|
95
|
+
),
|
|
96
|
+
Match.orElse(() => ({})),
|
|
97
|
+
)
|
|
98
|
+
})
|
|
99
|
+
|
|
33
100
|
const form = useForm<
|
|
34
101
|
To,
|
|
35
102
|
FormValidateOrFn<To> | undefined,
|
|
@@ -42,22 +109,77 @@ export const useOmegaForm = <
|
|
|
42
109
|
FormAsyncValidateOrFn<To> | undefined,
|
|
43
110
|
FormAsyncValidateOrFn<To> | undefined
|
|
44
111
|
>({
|
|
45
|
-
...
|
|
112
|
+
...tanstackFormOptions,
|
|
46
113
|
validators: {
|
|
47
114
|
onSubmit: standardSchema,
|
|
48
|
-
...(
|
|
115
|
+
...(tanstackFormOptions?.validators || {}),
|
|
49
116
|
},
|
|
50
|
-
onSubmit:
|
|
117
|
+
onSubmit: tanstackFormOptions?.onSubmit
|
|
51
118
|
? ({ formApi, meta, value }) =>
|
|
52
|
-
|
|
119
|
+
tanstackFormOptions.onSubmit?.({
|
|
53
120
|
formApi: formApi as OmegaFormApi<To, From>,
|
|
54
121
|
meta,
|
|
55
122
|
value: value as unknown as From,
|
|
56
123
|
})
|
|
57
124
|
: undefined,
|
|
125
|
+
defaultValues: defaultValues.value as any,
|
|
58
126
|
}) satisfies OmegaFormApi<To, From>
|
|
59
127
|
|
|
60
|
-
const
|
|
128
|
+
const clear = () => {
|
|
129
|
+
Object.keys(meta).forEach((key: any) => {
|
|
130
|
+
form.setFieldValue(key, undefined)
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const exposed = Object.assign(form, { meta, filterItems, clear })
|
|
135
|
+
|
|
136
|
+
// This is fragile as fuck. It's an experiment, it's only used because
|
|
137
|
+
// it's not a core feature of our products, so even if the this is not consistent
|
|
138
|
+
// it's not a big deal. So not take this code as a good example of how to do things.
|
|
139
|
+
// This is done only because this function is called before the component is destroyed,
|
|
140
|
+
// so the state would be lost anyway. So in this case we can play with the state, without
|
|
141
|
+
// worrying about the side effects.
|
|
142
|
+
const persistData = () => {
|
|
143
|
+
const persistency = omegaConfig?.persistency
|
|
144
|
+
Match.value(persistency).pipe(
|
|
145
|
+
Match.when(
|
|
146
|
+
{ method: method => ["local", "session"].includes(method) },
|
|
147
|
+
persistency => {
|
|
148
|
+
const method = persistency.method
|
|
149
|
+
const storage = method === "local" ? localStorage : sessionStorage
|
|
150
|
+
if (storage) {
|
|
151
|
+
if (Array.isArray(persistency.keys)) {
|
|
152
|
+
const subs = Object.keys(meta).filter(
|
|
153
|
+
metakey => !persistency.keys?.includes(metakey as any),
|
|
154
|
+
)
|
|
155
|
+
subs.forEach(key => {
|
|
156
|
+
form.setFieldValue(key as any, undefined)
|
|
157
|
+
})
|
|
158
|
+
}
|
|
159
|
+
if (Array.isArray(persistency.banKeys)) {
|
|
160
|
+
persistency.banKeys.forEach(key => {
|
|
161
|
+
form.setFieldValue(key as any, undefined)
|
|
162
|
+
})
|
|
163
|
+
}
|
|
164
|
+
return storage.setItem(
|
|
165
|
+
persistencyKey.value,
|
|
166
|
+
JSON.stringify(form.store.state.values),
|
|
167
|
+
)
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
),
|
|
171
|
+
Match.orElse(constVoid),
|
|
172
|
+
)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
onUnmounted(persistData)
|
|
176
|
+
|
|
177
|
+
onMounted(() => {
|
|
178
|
+
window.addEventListener("beforeunload", persistData)
|
|
179
|
+
})
|
|
180
|
+
onBeforeUnmount(() => {
|
|
181
|
+
window.removeEventListener("beforeunload", persistData)
|
|
182
|
+
})
|
|
61
183
|
|
|
62
184
|
return exposed
|
|
63
185
|
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<OmegaForm :form="form">
|
|
3
|
+
<template #default="{ form }">
|
|
4
|
+
<OmegaInput label="aString" :form="form" name="aString" />
|
|
5
|
+
<OmegaInput label="aStringMin2" :form="form" name="aStringMin2" />
|
|
6
|
+
<OmegaInput label="aStringMin2Max4" :form="form" name="aStringMin2Max4" />
|
|
7
|
+
<OmegaInput
|
|
8
|
+
label="aStringMin2Max3Nullable"
|
|
9
|
+
:form="form"
|
|
10
|
+
name="aStringMin2Max3Nullable"
|
|
11
|
+
/>
|
|
12
|
+
<OmegaInput label="aNumber" :form="form" name="aNumber" />
|
|
13
|
+
<OmegaInput label="aNumberMin2" :form="form" name="aNumberMin2" />
|
|
14
|
+
<OmegaInput label="aNumberMin2Max" :form="form" name="aNumberMin2Max" />
|
|
15
|
+
<OmegaInput
|
|
16
|
+
label="aNumberMin2Max4Nullable"
|
|
17
|
+
:form="form"
|
|
18
|
+
name="aNumberMin2Max4Nullable"
|
|
19
|
+
/>
|
|
20
|
+
<OmegaInput
|
|
21
|
+
label="aSelect"
|
|
22
|
+
:form="form"
|
|
23
|
+
name="aSelect"
|
|
24
|
+
:options="[
|
|
25
|
+
{ title: 'a', value: 'a' },
|
|
26
|
+
{ title: 'b', value: 'b' },
|
|
27
|
+
{ title: 'c', value: 'c' },
|
|
28
|
+
]"
|
|
29
|
+
/>
|
|
30
|
+
<button>Submit</button>
|
|
31
|
+
<button type="reset" @click.prevent="form.clear()">Clear</button>
|
|
32
|
+
<button type="button" @click="form.reset()">Reset</button>
|
|
33
|
+
</template>
|
|
34
|
+
</OmegaForm>
|
|
35
|
+
</template>
|
|
36
|
+
|
|
37
|
+
<script setup lang="ts">
|
|
38
|
+
import { S } from "effect-app"
|
|
39
|
+
import { OmegaForm, OmegaInput, useOmegaForm } from "../../components/OmegaForm"
|
|
40
|
+
|
|
41
|
+
const form = useOmegaForm(
|
|
42
|
+
S.Struct({
|
|
43
|
+
aString: S.String,
|
|
44
|
+
aStringMin2: S.String.pipe(S.minLength(2)),
|
|
45
|
+
aStringMin2Max4: S.String.pipe(S.minLength(2)).pipe(S.maxLength(4)),
|
|
46
|
+
aStringMin2Max3Nullable: S.UndefinedOr(
|
|
47
|
+
S.String.pipe(S.minLength(2)).pipe(S.maxLength(3)),
|
|
48
|
+
),
|
|
49
|
+
aNumber: S.Number,
|
|
50
|
+
aNumberMin2: S.Number.pipe(S.greaterThan(2)),
|
|
51
|
+
aNumberMin2Max: S.Number.pipe(S.greaterThan(2)).pipe(S.lessThan(4)),
|
|
52
|
+
aNumberMin2Max4Nullable: S.NullOr(S.Number.pipe(S.between(2, 4))),
|
|
53
|
+
aSelect: S.Union(S.Literal("a"), S.Literal("b"), S.Literal("c")),
|
|
54
|
+
}),
|
|
55
|
+
{
|
|
56
|
+
onSubmit: ({
|
|
57
|
+
value,
|
|
58
|
+
}: {
|
|
59
|
+
value: {
|
|
60
|
+
aString: string
|
|
61
|
+
aStringMin2: string
|
|
62
|
+
aStringMin2Max4: string
|
|
63
|
+
aStringMin2Max3Nullable?: string
|
|
64
|
+
aNumber: number
|
|
65
|
+
aNumberMin2: number
|
|
66
|
+
aNumberMin2Max: number
|
|
67
|
+
aNumberMin2Max4Nullable: number | null
|
|
68
|
+
aSelect: "a" | "b" | "c"
|
|
69
|
+
}
|
|
70
|
+
}) => {
|
|
71
|
+
console.log(value)
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
persistency: {
|
|
76
|
+
method: "local",
|
|
77
|
+
overrideDefaultValues: true,
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
)
|
|
81
|
+
</script>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<OmegaForm
|
|
3
|
+
:schema="schema"
|
|
4
|
+
:on-submit="onSubmit"
|
|
5
|
+
:default-values="defaultValues"
|
|
6
|
+
>
|
|
7
|
+
<template #default="{ form }">
|
|
8
|
+
<OmegaInput label="email" name="email" :form="form" />
|
|
9
|
+
<OmegaInput label="confirm" name="confirm" :form="form" />
|
|
10
|
+
<button>submit</button>
|
|
11
|
+
<OmegaErrors />
|
|
12
|
+
</template>
|
|
13
|
+
</OmegaForm>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<script setup lang="ts">
|
|
17
|
+
import { S } from "effect-app"
|
|
18
|
+
import { OmegaForm, OmegaInput, OmegaErrors } from "../../components/OmegaForm"
|
|
19
|
+
|
|
20
|
+
const schema = S.Struct({
|
|
21
|
+
email: S.Email,
|
|
22
|
+
confirm: S.Email,
|
|
23
|
+
}).pipe(
|
|
24
|
+
S.filter(
|
|
25
|
+
form => {
|
|
26
|
+
if (form.email !== form.confirm) {
|
|
27
|
+
return false
|
|
28
|
+
}
|
|
29
|
+
return true
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
message: () => "Email and confirmation must match",
|
|
33
|
+
jsonSchema: {
|
|
34
|
+
items: ["confirm"],
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
),
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
const defaultValues = {
|
|
41
|
+
email: "mimmo@asd.it",
|
|
42
|
+
confirm: "amerelli@asd.it",
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const onSubmit = ({ value }: { value: { email: string; confirm: string } }) => {
|
|
46
|
+
console.log(value)
|
|
47
|
+
}
|
|
48
|
+
</script>
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<OmegaForm
|
|
3
|
+
:form="addForm"
|
|
4
|
+
:subscribe="['errors', 'values']"
|
|
5
|
+
show-errors-on="onChange"
|
|
6
|
+
>
|
|
7
|
+
<template #default="{ form, subscribedValues: { errors, values } }">
|
|
8
|
+
<div>Errors: {{ errors }}</div>
|
|
9
|
+
<div>Values: {{ values }}</div>
|
|
10
|
+
<OmegaInput label="first" :form="form" name="first" />
|
|
11
|
+
<div>+</div>
|
|
12
|
+
<OmegaInput label="second" :form="form" name="second" />
|
|
13
|
+
<br />
|
|
14
|
+
<hr />
|
|
15
|
+
<br />
|
|
16
|
+
<OmegaInput label="third.fourth" :form="form" name="third.fourth" />
|
|
17
|
+
<OmegaInput label="third.fifth" :form="form" name="third.fifth" />
|
|
18
|
+
</template>
|
|
19
|
+
</OmegaForm>
|
|
20
|
+
|
|
21
|
+
<!-- Technically you can do this only with a subscribe but only inside OmegaForm Context -->
|
|
22
|
+
<div>
|
|
23
|
+
<div>Sum: {{ sum }}</div>
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script setup lang="ts">
|
|
28
|
+
import { S } from "effect-app"
|
|
29
|
+
import { OmegaForm, OmegaInput, useOmegaForm } from "../../components/OmegaForm"
|
|
30
|
+
import { ref, watch } from "vue"
|
|
31
|
+
|
|
32
|
+
const sum = ref(0)
|
|
33
|
+
const AddSchema = S.Struct({
|
|
34
|
+
first: S.Number,
|
|
35
|
+
second: S.Number.pipe(S.greaterThan(3)),
|
|
36
|
+
third: S.Struct({
|
|
37
|
+
fourth: S.Number,
|
|
38
|
+
fifth: S.Number,
|
|
39
|
+
}),
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const addForm = useOmegaForm(
|
|
43
|
+
AddSchema,
|
|
44
|
+
{},
|
|
45
|
+
{
|
|
46
|
+
persistency: {
|
|
47
|
+
method: "session",
|
|
48
|
+
keys: ["first", "third.fourth"],
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
const values = addForm.useStore(({ values }) => values)
|
|
54
|
+
|
|
55
|
+
watch(values, ({ first, second }) => {
|
|
56
|
+
sum.value = first + second
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
// TODO: Implement this when we have a way to persist the form values
|
|
60
|
+
// {
|
|
61
|
+
// persist: "session",
|
|
62
|
+
// persistKeys: ["riskCategoryPeriod"],
|
|
63
|
+
// persistBanKeys: ["riskCategory"],
|
|
64
|
+
// }
|
|
65
|
+
</script>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<OmegaForm :schema="schema" :on-submit="onSubmit" :subscribe="['values']">
|
|
3
|
+
<template #default="{ form, subscribedValues: { values } }">
|
|
4
|
+
<div>values: {{ values }}</div>
|
|
5
|
+
<OmegaInput label="asder2" name="asder2" :form="form">
|
|
6
|
+
<template #default="inputProps">
|
|
7
|
+
<label :for="inputProps.name">{{ inputProps.label }}</label>
|
|
8
|
+
<input
|
|
9
|
+
:id="inputProps.name"
|
|
10
|
+
v-model="inputProps.field.state.value"
|
|
11
|
+
:name="inputProps.name"
|
|
12
|
+
style="border: 1px solid red"
|
|
13
|
+
@change="(e: any) => inputProps.field.handleChange(e.target.value)"
|
|
14
|
+
/>
|
|
15
|
+
</template>
|
|
16
|
+
</OmegaInput>
|
|
17
|
+
<button>submit</button>
|
|
18
|
+
</template>
|
|
19
|
+
</OmegaForm>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<script setup lang="ts">
|
|
23
|
+
import { S } from "effect-app"
|
|
24
|
+
import { OmegaForm, OmegaInput } from "../../components/OmegaForm"
|
|
25
|
+
|
|
26
|
+
const schema = S.Struct({ asder2: S.String })
|
|
27
|
+
const onSubmit = ({ value }: { value: { asder2: string } }) => {
|
|
28
|
+
console.log(value)
|
|
29
|
+
}
|
|
30
|
+
</script>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<OmegaForm :schema="schema" :subscribe="['values']">
|
|
3
|
+
<template #default="{ form, subscribedValues: { values } }">
|
|
4
|
+
<OmegaInput label="aString" :form="form" name="aString" />
|
|
5
|
+
<pre>{{ values }}</pre>
|
|
6
|
+
</template>
|
|
7
|
+
</OmegaForm>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script setup lang="ts">
|
|
11
|
+
import { S } from "effect-app"
|
|
12
|
+
import { OmegaForm, OmegaInput } from "../../components/OmegaForm"
|
|
13
|
+
|
|
14
|
+
const schema = S.Struct({ aString: S.UndefinedOr(S.String) })
|
|
15
|
+
</script>
|