@effect-app/vue-components 3.0.1 → 3.0.3

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.
@@ -1,5 +1,5 @@
1
1
  import { useForm as K } from "@tanstack/vue-form";
2
- import { Data as T, S as W, Effect as d, Fiber as $, Option as P, Array as F } from "effect-app";
2
+ import { Data as T, S as W, Effect as d, Fiber as $, Option as j, Array as F } from "effect-app";
3
3
  import { runtimeFiberAsPromise as z } from "./vue-components.es17.js";
4
4
  import { computed as x, onUnmounted as D, onMounted as G, onBeforeUnmount as Z, watch as R, ref as Q, h as J } from "vue";
5
5
  import { useIntl as X } from "./vue-components.es3.js";
@@ -29,19 +29,19 @@ const M = (i) => function(s) {
29
29
  }, ce = (i) => function(s) {
30
30
  return {
31
31
  setup() {
32
- const { fieldMap: f, form: m } = i, a = m.useStore((v) => v.errors), g = m.useStore((v) => v.fieldMeta), p = m.useStore((v) => v.errorMap), j = ae(m), A = x(() => {
32
+ const { fieldMap: f, form: m } = i, a = m.useStore((v) => v.errors), g = m.useStore((v) => v.fieldMeta), p = m.useStore((v) => v.errorMap), A = ae(m), L = x(() => {
33
33
  const v = F.filterMap(
34
34
  Object.entries(g.value),
35
35
  ([O, h]) => {
36
36
  const w = h.errors ?? [];
37
- if (!w.length) return P.none();
37
+ if (!w.length) return j.none();
38
38
  const u = f.value.get(O);
39
- return u ? P.some({
39
+ return u ? j.some({
40
40
  label: u.label,
41
41
  inputId: u.id,
42
42
  // Only show the first error
43
43
  errors: [w[0]?.message].filter(Boolean)
44
- }) : P.none();
44
+ }) : j.none();
45
45
  }
46
46
  ), o = [];
47
47
  if (p.value.onSubmit) {
@@ -53,7 +53,7 @@ const M = (i) => function(s) {
53
53
  const E = u.path.join(".");
54
54
  if (!f.value.has(E)) {
55
55
  o.push({
56
- label: j(E),
56
+ label: A(E),
57
57
  inputId: E,
58
58
  errors: [u.message].filter(Boolean)
59
59
  });
@@ -66,7 +66,7 @@ const M = (i) => function(s) {
66
66
  });
67
67
  return {
68
68
  generalErrors: a,
69
- errors: A
69
+ errors: L
70
70
  };
71
71
  },
72
72
  render({ errors: f, generalErrors: m }) {
@@ -84,12 +84,12 @@ const M = (i) => function(s) {
84
84
  return s.persistency.id;
85
85
  const e = window.location.pathname, r = Object.keys(a);
86
86
  return `${e}-${r.join("-")}`;
87
- }), j = () => {
87
+ }), A = () => {
88
88
  const e = new URLSearchParams(window.location.search);
89
89
  e.delete(p.value);
90
90
  const r = new URL(window.location.href);
91
91
  r.search = e.toString(), window.history.replaceState({}, "", r.toString());
92
- }, A = x(() => {
92
+ }, L = x(() => {
93
93
  let e;
94
94
  const r = s?.persistency;
95
95
  if (
@@ -110,7 +110,7 @@ const M = (i) => function(s) {
110
110
  if (r?.policies && b(r.policies, "querystring"))
111
111
  try {
112
112
  const t = new URLSearchParams(window.location.search).get(p.value);
113
- j(), t && (e = N(e || {}, JSON.parse(t)));
113
+ A(), t && (e = N(e || {}, JSON.parse(t)));
114
114
  } catch (n) {
115
115
  console.error(n);
116
116
  }
@@ -145,7 +145,7 @@ const M = (i) => function(s) {
145
145
  )
146
146
  ) : t;
147
147
  }) : void 0,
148
- defaultValues: A.value
148
+ defaultValues: L.value
149
149
  }), O = () => {
150
150
  Object.keys(a).forEach((e) => {
151
151
  o.setFieldValue(e, void 0);
@@ -195,13 +195,13 @@ const M = (i) => function(s) {
195
195
  const I = (e) => d.currentSpan.pipe(
196
196
  d.option,
197
197
  d.flatMap(
198
- (r) => d.promise(() => o.handleSubmit(P.isSome(r) ? { currentSpan: r.value, ...e } : e))
198
+ (r) => d.promise(() => o.handleSubmit(j.isSome(r) ? { currentSpan: r.value, ...e } : e))
199
199
  )
200
200
  ), q = (e) => e?.checkErrors ? I(e?.meta).pipe(d.flatMap(d.fnUntraced(function* () {
201
201
  const r = o.getAllErrors();
202
202
  if (Object.keys(r.fields).length || r.form.errors.length)
203
203
  return yield* new ie({ form: r.form, fields: r.fields });
204
- }))) : I(e?.meta), B = o.handleSubmit, L = Q(/* @__PURE__ */ new Map()), y = Object.assign(o, {
204
+ }))) : I(e?.meta), B = o.handleSubmit, P = Q(/* @__PURE__ */ new Map()), y = Object.assign(o, {
205
205
  i18nNamespace: s?.i18nNamespace,
206
206
  ignorePreventCloseEvents: s?.ignorePreventCloseEvents,
207
207
  meta: a,
@@ -214,9 +214,13 @@ const M = (i) => function(s) {
214
214
  // /** @experimental */
215
215
  handleSubmitEffect: q,
216
216
  registerField: (e) => {
217
- R(e, (r) => L.value.set(r.name, { label: r.label, id: r.id }), { immediate: !0 }), D(() => L.value.delete(e.value.name));
217
+ R(e, (r) => {
218
+ P.value.set(r.name, { label: r.label, id: r.id });
219
+ }, { immediate: !0 }), D(() => {
220
+ P.value.get(e.value.name)?.id === e.value.id && P.value.delete(e.value.name);
221
+ });
218
222
  }
219
- }), V = { form: y, fieldMap: L };
223
+ }), V = { form: y, fieldMap: P };
220
224
  return Object.assign(y, {
221
225
  // Type-level properties for performance optimization (not used at runtime)
222
226
  _paths: void 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect-app/vue-components",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
4
4
  "peerDependencies": {
5
5
  "@mdi/js": "^7.4.47",
6
6
  "effect": "^3.19.3",
@@ -102,6 +102,7 @@ props.register(computed(() => ({ name: props.field.name, label: props.label, id
102
102
  // This ensures errors persist when Field components re-mount due to :key changes
103
103
  const _errors = computed(() => {
104
104
  const fieldMeta = formFieldMeta.value[props.field.name] as any
105
+ // Treat errors as an array (like useOmegaForm does)
105
106
  return fieldMeta?.errors ?? []
106
107
  })
107
108
  const errors = computed(() =>
@@ -962,8 +962,18 @@ export const useOmegaForm = <
962
962
  // /** @experimental */
963
963
  handleSubmitEffect,
964
964
  registerField: (field: ComputedRef<{ name: string; label: string; id: string }>) => {
965
- watch(field, (f) => fieldMap.value.set(f.name, { label: f.label, id: f.id }), { immediate: true })
966
- onUnmounted(() => fieldMap.value.delete(field.value.name)) // todo; perhap only when owned (id match)
965
+ watch(field, (f) => {
966
+ fieldMap.value.set(f.name, { label: f.label, id: f.id })
967
+ }, { immediate: true })
968
+ onUnmounted(() => {
969
+ // Only delete if we still own this entry (id matches)
970
+ // This prevents old components from deleting entries registered by new components
971
+ // during re-mount transitions (e.g., when :key changes)
972
+ const currentEntry = fieldMap.value.get(field.value.name)
973
+ if (currentEntry?.id === field.value.id) {
974
+ fieldMap.value.delete(field.value.name)
975
+ }
976
+ })
967
977
  }
968
978
  })
969
979
 
@@ -5,7 +5,9 @@ const Key = Symbol("injected") as InjectionKey<Map<string, { label: string; id:
5
5
 
6
6
  export const useRegisterField = (field: ComputedRef<{ name: string; label: string; id: string }>) => {
7
7
  const map = injectCertain(Key)
8
- watch(field, (f) => map.set(f.name, { label: f.label, id: f.id }), { immediate: true })
8
+ watch(field, (f) => {
9
+ map.set(f.name, { label: f.label, id: f.id })
10
+ }, { immediate: true })
9
11
  onUnmounted(() => map.delete(field.value.name)) // todo; perhap only when owned
10
12
  }
11
13