@effect-app/vue-components 1.3.0 → 1.4.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.
@@ -9,6 +9,7 @@ export type InputProps<From extends Record<PropertyKey, any>, TName extends Deep
9
9
  min?: number | false;
10
10
  name: string;
11
11
  modelValue: DeepValue<From, TName>;
12
+ handleChange: (value: DeepValue<From, TName>) => void;
12
13
  errorMessages: string[];
13
14
  error: boolean;
14
15
  field: OmegaFieldInternalApi<From, TName>;
@@ -1,7 +1,6 @@
1
1
  import { type DeepKeys, type DeepValue } from "@tanstack/vue-form";
2
2
  import { type OmegaInputProps } from "./OmegaFormStuff";
3
- declare const __VLS_export: <// dprint ignore - somehow with 120 chars, this becomes a mess. should report it.
4
- From extends Record<PropertyKey, any>, To extends Record<PropertyKey, any>>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
3
+ declare const __VLS_export: <From extends Record<PropertyKey, any>, To extends Record<PropertyKey, any>>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
5
4
  props: __VLS_PrettifyLocal<Omit<OmegaInputProps<From, To>, "validators" | "options" | "label" | "type" | "items"> & {
6
5
  defaultItems?: DeepValue<From, DeepKeys<From>>;
7
6
  items?: "please use `defaultItems` instead";
@@ -1,6 +1,5 @@
1
1
  import { type OmegaInputPropsBase } from "./OmegaFormStuff";
2
- declare const __VLS_export: <// dprint ignore - somehow with 120 chars, this becomes a mess. should report it.
3
- From extends Record<PropertyKey, any>, To extends Record<PropertyKey, any>>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
2
+ declare const __VLS_export: <From extends Record<PropertyKey, any>, To extends Record<PropertyKey, any>>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
4
3
  props: __VLS_PrettifyLocal<OmegaInputPropsBase<From, To>> & import("vue").PublicProps;
5
4
  expose: (exposed: {}) => void;
6
5
  attrs: any;
@@ -14,6 +13,7 @@ From extends Record<PropertyKey, any>, To extends Record<PropertyKey, any>>(__VL
14
13
  min?: number | false;
15
14
  name: string;
16
15
  modelValue: import("@tanstack/vue-form").DeepValue<From, any>;
16
+ handleChange: (value: import("@tanstack/vue-form").DeepValue<From, any>) => void;
17
17
  errorMessages: string[];
18
18
  error: boolean;
19
19
  field: import("./InputProps").OmegaFieldInternalApi<From, any>;
@@ -25,6 +25,7 @@ declare const __VLS_export: <From extends Record<PropertyKey, any>, Name extends
25
25
  min?: number | false;
26
26
  name: string;
27
27
  modelValue: import("@tanstack/vue-form").DeepValue<From, Name>;
28
+ handleChange: (value: import("@tanstack/vue-form").DeepValue<From, Name>) => void;
28
29
  errorMessages: string[];
29
30
  error: boolean;
30
31
  field: OmegaFieldInternalApi<From, Name>;
@@ -1,8 +1,8 @@
1
- (function(){"use strict";try{if(typeof document<"u"){var n=document.createElement("style");if(n.appendChild(document.createTextNode("fieldset[data-v-8d0c5c48]{display:contents}fieldset[disabled][data-v-8d0c5c48]>*{pointer-events:none}")),document.head.appendChild(n),window.customElements){const e=window.customElements.define;window.customElements.define=function(c,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-8d0c5c48]{display:contents}fieldset[disabled][data-v-8d0c5c48]>*{pointer-events:none}")),this.shadowRoot.appendChild(o)}},e.call(window.customElements,c,t)}}}}catch(e){console.error("vite-plugin-css-injected-by-js",e)}})();
1
+ (function(){"use strict";try{if(typeof document<"u"){var n=document.createElement("style");if(n.appendChild(document.createTextNode("fieldset[data-v-440e1a59]{display:contents}fieldset[disabled][data-v-440e1a59]>*{pointer-events:none}")),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-440e1a59]{display:contents}fieldset[disabled][data-v-440e1a59]>*{pointer-events:none}")),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.es28.js";
3
3
 
4
4
  import m from "./vue-components.es27.js";
5
- const c = /* @__PURE__ */ m(o, [["__scopeId", "data-v-8d0c5c48"]]);
5
+ const e = /* @__PURE__ */ m(o, [["__scopeId", "data-v-440e1a59"]]);
6
6
  export {
7
- c as default
7
+ e as default
8
8
  };
@@ -1,4 +1,4 @@
1
- import { defineComponent as b, resolveComponent as o, createElementBlock as m, openBlock as r, createBlock as i, createCommentVNode as u, resolveDynamicComponent as d, mergeProps as a, unref as f, withCtx as h, Fragment as c, renderList as V } from "vue";
1
+ import { defineComponent as b, resolveComponent as o, createElementBlock as m, openBlock as r, createBlock as u, createCommentVNode as i, resolveDynamicComponent as s, mergeProps as a, unref as h, withCtx as f, Fragment as c, renderList as V } from "vue";
2
2
  import { getInputType as C } from "./vue-components.es8.js";
3
3
  const U = /* @__PURE__ */ b({
4
4
  inheritAttrs: !1,
@@ -10,13 +10,13 @@ const U = /* @__PURE__ */ b({
10
10
  emits: ["focus", "blur"],
11
11
  setup(e) {
12
12
  return (l, n) => {
13
- const s = o("v-text-field"), P = o("v-textarea"), p = o("v-radio"), g = o("v-radio-group"), v = o("v-select"), y = o("v-autocomplete");
13
+ const d = o("v-text-field"), P = o("v-textarea"), p = o("v-radio"), g = o("v-radio-group"), v = o("v-select"), y = o("v-autocomplete");
14
14
  return r(), m("div", {
15
15
  class: "omega-input",
16
16
  onFocusout: n[4] || (n[4] = (t) => l.$emit("blur", t)),
17
17
  onFocusin: n[5] || (n[5] = (t) => l.$emit("focus", t))
18
18
  }, [
19
- e.inputProps.type === "boolean" || e.inputProps.type === "switch" ? (r(), i(d(e.inputProps.type === "boolean" ? "v-checkbox" : "v-switch"), a({
19
+ e.inputProps.type === "boolean" || e.inputProps.type === "switch" ? (r(), u(s(e.inputProps.type === "boolean" ? "v-checkbox" : "v-switch"), a({
20
20
  key: 0,
21
21
  id: e.inputProps.id,
22
22
  name: e.inputProps.name,
@@ -26,24 +26,24 @@ const U = /* @__PURE__ */ b({
26
26
  ripple: ""
27
27
  }, l.$attrs, {
28
28
  "model-value": e.vuetifyValue,
29
- onChange: n[0] || (n[0] = (t) => e.inputProps.field.handleChange(t.target.checked))
30
- }), null, 16, ["id", "name", "label", "error-messages", "error", "model-value"])) : u("", !0),
31
- e.inputProps.type === "email" || e.inputProps.type === "string" || e.inputProps.type === "password" ? (r(), i(s, a({
29
+ onChange: n[0] || (n[0] = (t) => e.inputProps.handleChange(t.target.checked))
30
+ }), null, 16, ["id", "name", "label", "error-messages", "error", "model-value"])) : i("", !0),
31
+ e.inputProps.type === "email" || e.inputProps.type === "string" || e.inputProps.type === "password" ? (r(), u(d, a({
32
32
  key: 1,
33
33
  id: e.inputProps.id,
34
34
  required: e.inputProps.required,
35
35
  "min-length": e.inputProps.minLength,
36
36
  "max-length": e.inputProps.maxLength,
37
- type: f(C)(e.inputProps.type),
37
+ type: h(C)(e.inputProps.type),
38
38
  name: e.inputProps.name,
39
39
  label: e.inputProps.label,
40
40
  "error-messages": e.inputProps.errorMessages,
41
41
  error: e.inputProps.error
42
42
  }, l.$attrs, {
43
43
  "model-value": e.vuetifyValue,
44
- "onUpdate:modelValue": e.inputProps.field.handleChange
45
- }), null, 16, ["id", "required", "min-length", "max-length", "type", "name", "label", "error-messages", "error", "model-value", "onUpdate:modelValue"])) : u("", !0),
46
- e.inputProps.type === "text" ? (r(), i(P, a({
44
+ "onUpdate:modelValue": e.inputProps.handleChange
45
+ }), null, 16, ["id", "required", "min-length", "max-length", "type", "name", "label", "error-messages", "error", "model-value", "onUpdate:modelValue"])) : i("", !0),
46
+ e.inputProps.type === "text" ? (r(), u(P, a({
47
47
  key: 2,
48
48
  id: e.inputProps.id,
49
49
  required: e.inputProps.required,
@@ -55,9 +55,9 @@ const U = /* @__PURE__ */ b({
55
55
  error: e.inputProps.error
56
56
  }, l.$attrs, {
57
57
  "model-value": e.vuetifyValue,
58
- "onUpdate:modelValue": e.inputProps.field.handleChange
59
- }), null, 16, ["id", "required", "min-length", "max-length", "name", "label", "error-messages", "error", "model-value", "onUpdate:modelValue"])) : u("", !0),
60
- e.inputProps.type === "number" || e.inputProps.type === "range" ? (r(), i(d(e.inputProps.type === "range" ? "v-slider" : "v-text-field"), a({
58
+ "onUpdate:modelValue": e.inputProps.handleChange
59
+ }), null, 16, ["id", "required", "min-length", "max-length", "name", "label", "error-messages", "error", "model-value", "onUpdate:modelValue"])) : i("", !0),
60
+ e.inputProps.type === "number" || e.inputProps.type === "range" ? (r(), u(s(e.inputProps.type === "range" ? "v-slider" : "v-text-field"), a({
61
61
  key: 3,
62
62
  id: e.inputProps.id,
63
63
  required: e.inputProps.required,
@@ -71,10 +71,10 @@ const U = /* @__PURE__ */ b({
71
71
  }, l.$attrs, {
72
72
  "model-value": e.vuetifyValue,
73
73
  "onUpdate:modelValue": n[1] || (n[1] = (t) => {
74
- t || t === 0 ? e.inputProps.field.handleChange(Number(t)) : e.inputProps.field.handleChange(void 0);
74
+ t || t === 0 ? e.inputProps.handleChange(Number(t)) : e.inputProps.handleChange(void 0);
75
75
  })
76
- }), null, 16, ["id", "required", "min", "max", "type", "name", "label", "error-messages", "error", "model-value"])) : u("", !0),
77
- e.inputProps.type === "radio" ? (r(), i(g, a({
76
+ }), null, 16, ["id", "required", "min", "max", "type", "name", "label", "error-messages", "error", "model-value"])) : i("", !0),
77
+ e.inputProps.type === "radio" ? (r(), u(g, a({
78
78
  key: 4,
79
79
  id: e.inputProps.id,
80
80
  name: e.inputProps.name,
@@ -83,18 +83,18 @@ const U = /* @__PURE__ */ b({
83
83
  error: e.inputProps.error
84
84
  }, l.$attrs, {
85
85
  "model-value": e.vuetifyValue,
86
- "onUpdate:modelValue": e.inputProps.field.handleChange
86
+ "onUpdate:modelValue": e.inputProps.handleChange
87
87
  }), {
88
- default: h(() => [
89
- (r(!0), m(c, null, V(e.inputProps.options, (t) => (r(), i(p, {
88
+ default: f(() => [
89
+ (r(!0), m(c, null, V(e.inputProps.options, (t) => (r(), u(p, {
90
90
  key: t.value,
91
91
  label: t.title,
92
92
  value: t.value
93
93
  }, null, 8, ["label", "value"]))), 128))
94
94
  ]),
95
95
  _: 1
96
- }, 16, ["id", "name", "label", "error-messages", "error", "model-value", "onUpdate:modelValue"])) : u("", !0),
97
- e.inputProps.type === "select" || e.inputProps.type === "multiple" ? (r(), i(v, a({
96
+ }, 16, ["id", "name", "label", "error-messages", "error", "model-value", "onUpdate:modelValue"])) : i("", !0),
97
+ e.inputProps.type === "select" || e.inputProps.type === "multiple" ? (r(), u(v, a({
98
98
  key: 5,
99
99
  id: e.inputProps.id,
100
100
  clearable: e.inputProps.type === "select",
@@ -108,10 +108,10 @@ const U = /* @__PURE__ */ b({
108
108
  error: e.inputProps.error
109
109
  }, l.$attrs, {
110
110
  "model-value": e.vuetifyValue,
111
- onClear: n[2] || (n[2] = (t) => e.inputProps.field.handleChange(void 0)),
112
- "onUpdate:modelValue": e.inputProps.field.handleChange
113
- }), null, 16, ["id", "clearable", "required", "multiple", "chips", "name", "label", "items", "error-messages", "error", "model-value", "onUpdate:modelValue"])) : u("", !0),
114
- e.inputProps.type === "autocomplete" || e.inputProps.type === "autocompletemultiple" ? (r(), i(y, a({
111
+ onClear: n[2] || (n[2] = (t) => e.inputProps.handleChange(void 0)),
112
+ "onUpdate:modelValue": e.inputProps.handleChange
113
+ }), null, 16, ["id", "clearable", "required", "multiple", "chips", "name", "label", "items", "error-messages", "error", "model-value", "onUpdate:modelValue"])) : i("", !0),
114
+ e.inputProps.type === "autocomplete" || e.inputProps.type === "autocompletemultiple" ? (r(), u(y, a({
115
115
  key: 6,
116
116
  id: e.inputProps.id,
117
117
  clearable: e.inputProps.type === "autocomplete",
@@ -125,9 +125,9 @@ const U = /* @__PURE__ */ b({
125
125
  chips: e.inputProps.type === "autocompletemultiple"
126
126
  }, l.$attrs, {
127
127
  "model-value": e.vuetifyValue,
128
- onClear: n[3] || (n[3] = (t) => e.inputProps.field.handleChange(void 0)),
129
- "onUpdate:modelValue": e.inputProps.field.handleChange
130
- }), null, 16, ["id", "clearable", "multiple", "required", "name", "label", "items", "error-messages", "error", "chips", "model-value", "onUpdate:modelValue"])) : u("", !0)
128
+ onClear: n[3] || (n[3] = (t) => e.inputProps.handleChange(void 0)),
129
+ "onUpdate:modelValue": e.inputProps.handleChange
130
+ }), null, 16, ["id", "clearable", "multiple", "required", "name", "label", "items", "error-messages", "error", "chips", "model-value", "onUpdate:modelValue"])) : i("", !0)
131
131
  ], 32);
132
132
  };
133
133
  }
@@ -1,9 +1,9 @@
1
1
  (function(){"use strict";try{if(typeof document<"u"){var i=document.createElement("style");if(i.appendChild(document.createTextNode(".omega-input .v-input__details:has(.v-messages:empty){grid-template-rows:0fr;transition:all .2s}.omega-input .v-messages:empty{min-height:0}.omega-input .v-input__details:has(.v-messages){transition:all .2s;overflow:hidden;min-height:0;display:grid;grid-template-rows:1fr}.omega-input .v-messages{transition:all .2s}.omega-input .v-messages>*{transition-duration:0s!important}.omega-input [role=alert]:has(.v-messages:empty){padding:0}.omega-input .v-btn{cursor:pointer;width:auto;appearance:none;box-shadow:none;display:block;min-width:auto;height:auto;padding:.5em .5em .5em 1em}")),document.head.appendChild(i),window.customElements){const e=window.customElements.define;window.customElements.define=function(s,t){const n=t.prototype.connectedCallback;return t.prototype.connectedCallback=function(){if(n&&n.call(this),this.shadowRoot){const a=document.createElement("style");a.appendChild(document.createTextNode(".omega-input .v-input__details:has(.v-messages:empty){grid-template-rows:0fr;transition:all .2s}.omega-input .v-messages:empty{min-height:0}.omega-input .v-input__details:has(.v-messages){transition:all .2s;overflow:hidden;min-height:0;display:grid;grid-template-rows:1fr}.omega-input .v-messages{transition:all .2s}.omega-input .v-messages>*{transition-duration:0s!important}.omega-input [role=alert]:has(.v-messages:empty){padding:0}.omega-input .v-btn{cursor:pointer;width:auto;appearance:none;box-shadow:none;display:block;min-width:auto;height:auto;padding:.5em .5em .5em 1em}")),this.shadowRoot.appendChild(a)}},e.call(window.customElements,s,t)}}}}catch(e){console.error("vite-plugin-css-injected-by-js",e)}})();
2
- import { defineComponent as E, getCurrentInstance as V, useId as w, computed as a, watch as d, nextTick as N, onMounted as c, ref as $, watchEffect as k, onUnmounted as B, renderSlot as I, normalizeProps as _, guardReactiveProps as q, createElementVNode as F, normalizeClass as L, createBlock as O, createCommentVNode as P, unref as S, openBlock as T, mergeProps as U } from "vue";
2
+ import { defineComponent as x, getCurrentInstance as N, useId as V, computed as a, onMounted as c, ref as $, watchEffect as B, watch as I, onUnmounted as _, renderSlot as k, normalizeProps as q, guardReactiveProps as D, createElementVNode as F, normalizeClass as L, createBlock as O, createCommentVNode as P, unref as M, openBlock as S, mergeProps as U } from "vue";
3
3
  import { useStore as z } from "@tanstack/vue-form";
4
4
  import A from "./vue-components.es20.js";
5
5
 
6
- const H = /* @__PURE__ */ E({
6
+ const H = /* @__PURE__ */ x({
7
7
  inheritAttrs: !1,
8
8
  __name: "OmegaInternalInput",
9
9
  props: {
@@ -15,48 +15,46 @@ const H = /* @__PURE__ */ E({
15
15
  validators: {}
16
16
  },
17
17
  setup(v) {
18
- const e = v, g = V()?.appContext.components.VTextField, n = w(), o = e.field, r = z(o.store, (t) => t), m = a(() => e.type ? e.type : e.meta?.type === "string" ? e.meta.format === "email" ? "email" : "string" : e.meta?.type || "unknown"), l = a(() => r.value.value), y = a(
18
+ const e = v, g = N()?.appContext.components.VTextField, n = V(), l = e.field, r = z(l.store, (t) => t), u = a(() => e.type ? e.type : e.meta?.type === "string" ? e.meta.format === "email" ? "email" : "string" : e.meta?.type || "unknown"), m = a(() => r.value.value), h = a(
19
19
  () => (
20
20
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
21
  r.value.meta.errors.map((t) => t?.message).filter(Boolean)
22
22
  )
23
- ), h = (t) => t == null || t === !1 || t === "" || Number.isNaN(t);
24
- d(
25
- () => !!l.value,
26
- () => {
27
- h(l.value) && e.meta?.type !== "boolean" && N(() => {
28
- o.setValue(
29
- e.meta?.nullableOrUndefined === "undefined" ? void 0 : null
30
- );
31
- });
23
+ ), y = (t) => t == null || t === !1 || t === "" || Number.isNaN(t), b = (t) => {
24
+ y(t) && e.meta?.type !== "boolean" ? e.field.handleChange(
25
+ e.meta?.nullableOrUndefined === "undefined" ? void 0 : null
26
+ ) : e.field.handleChange(t);
27
+ };
28
+ c(() => {
29
+ if (!m.value && !e.meta?.required && e.meta?.nullableOrUndefined === "null") {
30
+ const t = r.value.meta.isDirty;
31
+ l.setValue(null), l.setMeta((p) => ({ ...p, isDirty: t }));
32
32
  }
33
- ), c(() => {
34
- !l.value && !e.meta?.required && e.meta?.nullableOrUndefined === "null" && o.setValue(null);
35
33
  });
36
- const { mapError: b, removeError: f, showErrors: x, showErrorsOn: C } = e.field.form.errorContext, s = $(!1);
37
- k(() => {
38
- (x.value || C === "onChange") && (s.value = !0);
34
+ const { mapError: C, removeError: d, showErrors: E, showErrorsOn: w } = e.field.form.errorContext, o = $(!1);
35
+ B(() => {
36
+ (E.value || w === "onChange") && (o.value = !0);
39
37
  });
40
- const i = () => {
41
- s.value = !0;
38
+ const s = () => {
39
+ o.value = !0;
42
40
  };
43
41
  c(() => {
44
- l.value && i();
42
+ m.value && s();
45
43
  });
46
- const p = a(() => !s.value && m.value !== "select" ? [] : y.value);
47
- d(
44
+ const f = a(() => !o.value && u.value !== "select" ? [] : h.value);
45
+ I(
48
46
  () => r.value.meta.errors,
49
47
  () => {
50
- r.value.meta.errors.length ? b({
48
+ r.value.meta.errors.length ? C({
51
49
  inputId: n,
52
50
  errors: r.value.meta.errors.map((t) => t.message).filter(Boolean),
53
51
  label: e.label
54
- }) : f(n);
52
+ }) : d(n);
55
53
  }
56
- ), B(() => {
57
- f(n), e.field.form.deleteField(e.field.name);
54
+ ), _(() => {
55
+ d(n), e.field.form.deleteField(e.field.name);
58
56
  });
59
- const u = a(() => ({
57
+ const i = a(() => ({
60
58
  id: n,
61
59
  required: e.meta?.required,
62
60
  minLength: e.meta?.type === "string" && e.meta?.minLength,
@@ -65,24 +63,25 @@ const H = /* @__PURE__ */ E({
65
63
  min: e.meta?.type === "number" && e.meta?.minimum,
66
64
  name: e.field.name,
67
65
  modelValue: e.field.state.value,
68
- errorMessages: p.value,
69
- error: !!p.value.length,
66
+ handleChange: b,
67
+ errorMessages: f.value,
68
+ error: !!f.value.length,
70
69
  field: e.field,
71
- setRealDirty: i,
72
- type: m.value,
70
+ setRealDirty: s,
71
+ type: u.value,
73
72
  label: `${e.label}${e.meta?.required ? " *" : ""}`,
74
73
  options: e.options
75
74
  }));
76
- return (t, M) => I(t.$slots, "default", _(q(u.value)), () => [
75
+ return (t, p) => k(t.$slots, "default", q(D(i.value)), () => [
77
76
  F("div", {
78
77
  class: L(t.$attrs.class),
79
- onFocusout: i
78
+ onFocusout: s
80
79
  }, [
81
- S(g) ? (T(), O(A, U({
80
+ M(g) ? (S(), O(A, U({
82
81
  key: 0,
83
- "input-props": u.value
82
+ "input-props": i.value
84
83
  }, t.$attrs, {
85
- "vuetify-value": u.value.field.state.value
84
+ "vuetify-value": i.value.field.state.value
86
85
  }), null, 16, ["input-props", "vuetify-value"])) : P("", !0)
87
86
  ], 34)
88
87
  ]);
@@ -1,6 +1,7 @@
1
- import { S as n, Option as c, pipe as L } from "effect-app";
2
- import { useIntl as U, getTransformationFrom as _ } from "./vue-components.es3.js";
3
- const N = n.NonEmptyArray(n.String), E = (e) => n.AST.isUnion(e) && e.types.find((i) => i._tag === "UndefinedKeyword" || i === n.Null.ast), g = (e) => !e || !n.AST.isUnion(e) ? !1 : e.types.find((i) => i._tag === "UndefinedKeyword") ? "undefined" : e.types.find((i) => i === n.Null.ast) ? "null" : !1, m = ({ meta: e = {}, parent: i = "", property: t, propertySignatures: p }, o = {}) => {
1
+ import { S as n, Option as c, pipe as q } from "effect-app";
2
+ import { getMetadataFromSchema as U } from "@effect-app/vue/form";
3
+ import { useIntl as _, getTransformationFrom as N } from "./vue-components.es3.js";
4
+ const w = n.NonEmptyArray(n.String), E = (e) => n.AST.isUnion(e) && e.types.find((i) => i._tag === "UndefinedKeyword" || i === n.Null.ast), g = (e) => !e || !n.AST.isUnion(e) ? !1 : e.types.find((i) => i._tag === "UndefinedKeyword") ? "undefined" : e.types.find((i) => i === n.Null.ast) ? "null" : !1, m = ({ meta: e = {}, parent: i = "", property: t, propertySignatures: p }, o = {}) => {
4
5
  if (t && t._tag === "Transformation")
5
6
  return m({
6
7
  parent: i,
@@ -18,7 +19,7 @@ const N = n.NonEmptyArray(n.String), E = (e) => n.AST.isUnion(e) && e.types.find
18
19
  if (n.AST.isUnion(r.type)) {
19
20
  const T = r.type.types.filter(
20
21
  (s) => s._tag !== "UndefinedKeyword" && s !== n.Null.ast
21
- ).map(_);
22
+ ).map(N);
22
23
  if (T.some(
23
24
  (s) => "propertySignatures" in s
24
25
  )) {
@@ -148,7 +149,12 @@ const N = n.NonEmptyArray(n.String), E = (e) => n.AST.isUnion(e) && e.types.find
148
149
  const T = m({
149
150
  parent: l,
150
151
  property: r.type,
151
- meta: { required: u, nullableOrUndefined: a }
152
+ meta: {
153
+ // an empty string is valid for a S.String field, so we should not mark it as required
154
+ // TODO: handle this better via the createMeta minLength parsing
155
+ required: u && (r.type._tag !== "StringKeyword" || U(r.type).minLength),
156
+ nullableOrUndefined: a
157
+ }
152
158
  });
153
159
  o[l] = T;
154
160
  }
@@ -201,10 +207,10 @@ const N = n.NonEmptyArray(n.String), E = (e) => n.AST.isUnion(e) && e.types.find
201
207
  ), e);
202
208
  }
203
209
  return o;
204
- }, q = (e) => {
210
+ }, L = (e) => {
205
211
  const i = e.ast, t = {};
206
212
  if (i._tag === "Transformation" || i._tag === "Refinement")
207
- return q(n.make(i.from));
213
+ return L(n.make(i.from));
208
214
  if ("propertySignatures" in i) {
209
215
  const p = m({
210
216
  propertySignatures: i.propertySignatures
@@ -220,13 +226,13 @@ const N = n.NonEmptyArray(n.String), E = (e) => n.AST.isUnion(e) && e.types.find
220
226
  o(p);
221
227
  }
222
228
  return t;
223
- }, I = (e) => n.extend(e, n.Struct({})), K = (e) => {
224
- const i = q(e), t = L(
229
+ }, P = (e) => n.extend(e, n.Struct({})), F = (e) => {
230
+ const i = L(e), t = q(
225
231
  e.ast,
226
232
  c.liftPredicate((p) => p._tag === "Refinement" && "filter" in p),
227
233
  c.flatMap((p) => n.AST.getJSONSchemaAnnotation(p)),
228
234
  c.filter((p) => "items" in p),
229
- c.filterMap(({ items: p }) => n.decodeUnknownOption(N)(p)),
235
+ c.filterMap(({ items: p }) => n.decodeUnknownOption(w)(p)),
230
236
  c.zipWith(
231
237
  n.AST.getMessageAnnotation(e.ast),
232
238
  (p, o) => ({
@@ -237,8 +243,8 @@ const N = n.NonEmptyArray(n.String), E = (e) => n.AST.isUnion(e) && e.types.find
237
243
  c.getOrUndefined
238
244
  );
239
245
  return { schema: e, meta: i, filterItems: t };
240
- }, P = (e) => {
241
- const { trans: i } = U();
246
+ }, j = (e) => {
247
+ const { trans: i } = _();
242
248
  let t;
243
249
  switch (e.type) {
244
250
  case "string":
@@ -320,7 +326,7 @@ const N = n.NonEmptyArray(n.String), E = (e) => n.AST.isUnion(e) && e.types.find
320
326
  message: () => i("validation.empty")
321
327
  })
322
328
  ) : t = n.NullishOr(t), n.standardSchemaV1(t);
323
- }, j = (e, i) => n.NullOr(e).pipe(
329
+ }, R = (e, i) => n.NullOr(e).pipe(
324
330
  n.transform(n.typeSchema(e), {
325
331
  decode: (t) => t ?? i(),
326
332
  encode: (t) => t
@@ -341,12 +347,12 @@ const N = n.NonEmptyArray(n.String), E = (e) => n.AST.isUnion(e) && e.types.find
341
347
  "text",
342
348
  "time",
343
349
  "url"
344
- ], F = (e) => k.includes(e) ? e : "text";
350
+ ], J = (e) => k.includes(e) ? e : "text";
345
351
  export {
346
352
  m as createMeta,
347
- I as duplicateSchema,
348
- P as generateInputStandardSchemaFromFieldMeta,
349
- K as generateMetaFromSchema,
350
- F as getInputType,
351
- j as nullableInput
353
+ P as duplicateSchema,
354
+ j as generateInputStandardSchemaFromFieldMeta,
355
+ F as generateMetaFromSchema,
356
+ J as getInputType,
357
+ R as nullableInput
352
358
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect-app/vue-components",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "peerDependencies": {
5
5
  "@mdi/js": "^7.4.47",
6
6
  "effect": "^3.18.0",
@@ -30,7 +30,7 @@
30
30
  "vitest": "^3.2.4",
31
31
  "vue-router": "^4.5.1",
32
32
  "vue-tsc": "^3.1.0",
33
- "@effect-app/eslint-shared-config": "0.3.0"
33
+ "@effect-app/eslint-shared-config": "0.3.1"
34
34
  },
35
35
  "files": [
36
36
  "src",
@@ -36,6 +36,7 @@ export type InputProps<From extends Record<PropertyKey, any>, TName extends Deep
36
36
  min?: number | false
37
37
  name: string
38
38
  modelValue: DeepValue<From, TName>
39
+ handleChange: (value: DeepValue<From, TName>) => void
39
40
  errorMessages: string[]
40
41
  error: boolean
41
42
  field: OmegaFieldInternalApi<From, TName>
@@ -1,5 +1,6 @@
1
1
  import { type Effect, Option, pipe, type Record, S } from "effect-app"
2
2
  /* eslint-disable @typescript-eslint/no-explicit-any */
3
+ import { getMetadataFromSchema } from "@effect-app/vue/form"
3
4
  import { type DeepKeys, type FieldAsyncValidateOrFn, type FieldValidateOrFn, type FormApi, type FormAsyncValidateOrFn, type FormOptions, type FormState, type FormValidateOrFn, type StandardSchemaV1, type VueFormApi } from "@tanstack/vue-form"
4
5
  import { type RuntimeFiber } from "effect/Fiber"
5
6
  import { getTransformationFrom, useIntl } from "../../utils"
@@ -492,7 +493,12 @@ export const createMeta = <T = any>(
492
493
  const newMeta = createMeta<T>({
493
494
  parent: key,
494
495
  property: p.type,
495
- meta: { required: isRequired, nullableOrUndefined }
496
+ meta: {
497
+ // an empty string is valid for a S.String field, so we should not mark it as required
498
+ // TODO: handle this better via the createMeta minLength parsing
499
+ required: isRequired && (p.type._tag !== "StringKeyword" || getMetadataFromSchema(p.type).minLength),
500
+ nullableOrUndefined
501
+ }
496
502
  })
497
503
 
498
504
  acc[key as NestedKeyOf<T>] = newMeta as FieldMeta
@@ -15,7 +15,7 @@
15
15
  ripple
16
16
  v-bind="$attrs"
17
17
  :model-value="vuetifyValue"
18
- @change="(e: any) => inputProps.field.handleChange(e.target.checked)"
18
+ @change="(e: any) => inputProps.handleChange(e.target.checked)"
19
19
  />
20
20
  <v-text-field
21
21
  v-if="inputProps.type === 'email' || inputProps.type === 'string' || inputProps.type === 'password'"
@@ -30,7 +30,7 @@
30
30
  :error="inputProps.error"
31
31
  v-bind="$attrs"
32
32
  :model-value="vuetifyValue"
33
- @update:model-value="inputProps.field.handleChange"
33
+ @update:model-value="inputProps.handleChange"
34
34
  />
35
35
  <v-textarea
36
36
  v-if="inputProps.type === 'text'"
@@ -44,7 +44,7 @@
44
44
  :error="inputProps.error"
45
45
  v-bind="$attrs"
46
46
  :model-value="vuetifyValue"
47
- @update:model-value="inputProps.field.handleChange"
47
+ @update:model-value="inputProps.handleChange"
48
48
  />
49
49
  <component
50
50
  :is="inputProps.type === 'range' ? 'v-slider' : 'v-text-field'"
@@ -62,9 +62,9 @@
62
62
  :model-value="vuetifyValue"
63
63
  @update:model-value="(e: any) => {
64
64
  if (e || e === 0) {
65
- inputProps.field.handleChange(Number(e) as any)
65
+ inputProps.handleChange(Number(e) as any)
66
66
  } else {
67
- inputProps.field.handleChange(undefined as any)
67
+ inputProps.handleChange(undefined as any)
68
68
  }
69
69
  }"
70
70
  />
@@ -77,7 +77,7 @@
77
77
  :error="inputProps.error"
78
78
  v-bind="$attrs"
79
79
  :model-value="vuetifyValue"
80
- @update:model-value="inputProps.field.handleChange"
80
+ @update:model-value="inputProps.handleChange"
81
81
  >
82
82
  <v-radio
83
83
  v-for="option in inputProps.options"
@@ -101,8 +101,8 @@
101
101
  :error="inputProps.error"
102
102
  v-bind="$attrs"
103
103
  :model-value="vuetifyValue"
104
- @clear="inputProps.field.handleChange(undefined as any)"
105
- @update:model-value="inputProps.field.handleChange"
104
+ @clear="inputProps.handleChange(undefined as any)"
105
+ @update:model-value="inputProps.handleChange"
106
106
  />
107
107
 
108
108
  <v-autocomplete
@@ -120,8 +120,8 @@
120
120
  :chips="inputProps.type === 'autocompletemultiple'"
121
121
  v-bind="$attrs"
122
122
  :model-value="vuetifyValue"
123
- @clear="inputProps.field.handleChange(undefined as any)"
124
- @update:model-value="inputProps.field.handleChange"
123
+ @clear="inputProps.handleChange(undefined as any)"
124
+ @update:model-value="inputProps.handleChange"
125
125
  />
126
126
  </div>
127
127
  </template>
@@ -20,7 +20,7 @@
20
20
  generic="From extends Record<PropertyKey, any>, Name extends DeepKeys<From>"
21
21
  >
22
22
  import { type DeepKeys, useStore } from "@tanstack/vue-form"
23
- import { computed, type ComputedRef, getCurrentInstance, nextTick, onMounted, onUnmounted, ref, useId, watch, watchEffect } from "vue"
23
+ import { computed, type ComputedRef, getCurrentInstance, onMounted, onUnmounted, ref, useId, watch, watchEffect } from "vue"
24
24
  import type { InputProps, OmegaFieldInternalApi } from "./InputProps"
25
25
  import type { FieldValidators, MetaRecord, NestedKeyOf, TypeOverride } from "./OmegaFormStuff"
26
26
  import OmegaInputVuetify from "./OmegaInputVuetify.vue"
@@ -67,31 +67,35 @@ const isFalsyButNotZero = (value: unknown): boolean => {
67
67
  }
68
68
 
69
69
  // we remove value and errors when the field is empty and not required
70
- // watchEffect will trigger infinite times with both free fieldValue and errors, so bet to watch a stupid boolean
71
- watch(
72
- () => !!fieldValue.value,
73
- () => {
74
- if (isFalsyButNotZero(fieldValue.value) && props.meta?.type !== "boolean") {
75
- nextTick(() => {
76
- fieldApi.setValue(
77
- props.meta?.nullableOrUndefined === "undefined"
78
- ? undefined
79
- : null as any
80
- )
81
- })
82
- }
70
+
71
+ // convert nullish value to null or undefined based on schema
72
+ const handleChange: OmegaFieldInternalApi<From, Name>["handleChange"] = (value) => {
73
+ if (isFalsyButNotZero(value) && props.meta?.type !== "boolean") {
74
+ props.field.handleChange(
75
+ props.meta?.nullableOrUndefined === "undefined"
76
+ ? undefined
77
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
78
+ : null as any
79
+ )
80
+ } else {
81
+ props.field.handleChange(value)
83
82
  }
84
- )
83
+ }
85
84
 
85
+ // TODO: it would be cleaner when default values are handled in the form initialization via Schema or by the one using the form component..
86
86
  onMounted(() => {
87
87
  if (
88
88
  !fieldValue.value
89
89
  && !props.meta?.required
90
90
  && props.meta?.nullableOrUndefined === "null"
91
91
  ) {
92
+ const isDirty = fieldState.value.meta.isDirty
92
93
  fieldApi.setValue(null as any)
94
+ // make sure we restore the previous dirty state..
95
+ fieldApi.setMeta((_) => ({ ..._, isDirty }))
93
96
  }
94
97
  })
98
+
95
99
  const { mapError, removeError, showErrors, showErrorsOn } = (props.field.form as any).errorContext // todo; update types to include extended Omega Form props
96
100
 
97
101
  const realDirty = ref(false)
@@ -153,6 +157,7 @@ const inputProps: ComputedRef<InputProps<From, Name>> = computed(() => ({
153
157
  min: props.meta?.type === "number" && props.meta?.minimum,
154
158
  name: props.field.name,
155
159
  modelValue: props.field.state.value,
160
+ handleChange,
156
161
  errorMessages: showedErrors.value,
157
162
  error: !!showedErrors.value.length,
158
163
  field: props.field,