@effect-app/vue-components 4.0.0-beta.92 → 4.0.0-beta.94

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.
@@ -91,6 +91,14 @@ export type FieldValidators<T> = {
91
91
  export type BaseFieldMeta = {
92
92
  required: boolean;
93
93
  nullableOrUndefined?: false | "undefined" | "null";
94
+ /**
95
+ * True when the schema property is `S.optionalKey` (AST
96
+ * `context.isOptional`) — i.e. the key should be ABSENT from the submitted
97
+ * object when empty, not present with `undefined`. Distinct from
98
+ * `required: false`, which may also mean "empty string is valid" for
99
+ * unconstrained `S.String` fields.
100
+ */
101
+ isOptionalKey?: boolean;
94
102
  };
95
103
  export type StringFieldMeta = BaseFieldMeta & {
96
104
  type: "string";
@@ -79,9 +79,9 @@ var o = /* @__PURE__ */ new Set(), s = () => globalThis.process?.env?.NODE_ENV !
79
79
  });
80
80
  if (r) {
81
81
  for (let n of r) {
82
- let r = t ? `${t}.${n.name.toString()}` : n.name.toString(), o = f(n.type), s;
83
- s = e._isNullableDiscriminatedUnion && n.name.toString() === "_tag" || e.required === !1 || n.type.context?.isOptional ? !1 : !o;
84
- let l = c(n.type);
82
+ let r = t ? `${t}.${n.name.toString()}` : n.name.toString(), o = f(n.type), s = n.type.context?.isOptional === !0, l;
83
+ l = e._isNullableDiscriminatedUnion && n.name.toString() === "_tag" || e.required === !1 || s ? !1 : !o;
84
+ let u = c(n.type);
85
85
  if (a.AST.isUnion(n.type)) {
86
86
  let e = m(n.type.types);
87
87
  if (e.some(a.AST.isObjects)) {
@@ -89,7 +89,7 @@ var o = /* @__PURE__ */ new Set(), s = () => globalThis.process?.env?.NODE_ENV !
89
89
  parent: r,
90
90
  property: n.type,
91
91
  meta: {
92
- required: s,
92
+ required: l,
93
93
  nullableOrUndefined: o
94
94
  }
95
95
  }));
@@ -112,7 +112,7 @@ var o = /* @__PURE__ */ new Set(), s = () => globalThis.process?.env?.NODE_ENV !
112
112
  type: "multiple",
113
113
  members: e.elements,
114
114
  rest: e.rest,
115
- required: s,
115
+ required: l,
116
116
  nullableOrUndefined: o
117
117
  }, e.rest && e.rest.length > 0) {
118
118
  let t = c(e.rest[0]);
@@ -145,16 +145,16 @@ var o = /* @__PURE__ */ new Set(), s = () => globalThis.process?.env?.NODE_ENV !
145
145
  parent: r,
146
146
  property: n.type,
147
147
  meta: {
148
- required: s,
148
+ required: l,
149
149
  nullableOrUndefined: o
150
150
  }
151
151
  });
152
152
  }
153
- } else if (a.AST.isObjects(l)) Object.assign(i, b({
153
+ } else if (a.AST.isObjects(u)) Object.assign(i, b({
154
154
  parent: r,
155
- propertySignatures: l.propertySignatures,
155
+ propertySignatures: u.propertySignatures,
156
156
  meta: {
157
- required: s,
157
+ required: l,
158
158
  nullableOrUndefined: o
159
159
  }
160
160
  }));
@@ -195,15 +195,16 @@ var o = /* @__PURE__ */ new Set(), s = () => globalThis.process?.env?.NODE_ENV !
195
195
  type: "multiple",
196
196
  members: n.type.elements,
197
197
  rest: n.type.rest,
198
- required: s,
198
+ required: l,
199
199
  nullableOrUndefined: o
200
200
  };
201
201
  else i[r] = b({
202
202
  parent: r,
203
203
  property: n.type,
204
204
  meta: {
205
- required: s && (!a.AST.isString(l) || !!y(l).minLength),
206
- nullableOrUndefined: o
205
+ required: l && (!a.AST.isString(u) || !!y(u).minLength),
206
+ nullableOrUndefined: o,
207
+ ...s ? { isOptionalKey: !0 } : {}
207
208
  }
208
209
  });
209
210
  }
@@ -33,7 +33,8 @@ var b = /* @__PURE__ */ o({
33
33
  id: D
34
34
  })));
35
35
  let j = t(() => k.value[b.field.name]?.errors ?? []), M = t(() => j.value.map((e) => e?.message).filter(Boolean)), N = (e) => e == null || e === !1 || e === "" || Number.isNaN(e), P = (e) => {
36
- N(e) && b.meta?.type !== "boolean" && b.meta?.nullableOrUndefined ? b.field.handleChange(b.meta.nullableOrUndefined === "undefined" ? void 0 : null) : b.field.handleChange(e), b.field.setMeta((e) => ({
36
+ let t = !1;
37
+ N(e) && b.meta?.type !== "boolean" ? b.meta?.nullableOrUndefined ? b.field.handleChange(b.meta.nullableOrUndefined === "undefined" ? void 0 : null) : b.meta?.isOptionalKey ? (b.field.form.deleteField(b.field.name), t = !0) : b.field.handleChange(e) : b.field.handleChange(e), t || b.field.setMeta((e) => ({
37
38
  ...e,
38
39
  errorMap: {
39
40
  ...e.errorMap,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect-app/vue-components",
3
- "version": "4.0.0-beta.92",
3
+ "version": "4.0.0-beta.94",
4
4
  "peerDependencies": {
5
5
  "@mdi/js": "^7.4.47",
6
6
  "effect": "^4.0.0-beta.47",
@@ -58,8 +58,8 @@
58
58
  "highlight.js": "^11.11.1",
59
59
  "mitt": "^3.0.1",
60
60
  "vue3-highlightjs": "^1.0.5",
61
- "@effect-app/vue": "4.0.0-beta.92",
62
- "effect-app": "4.0.0-beta.92"
61
+ "@effect-app/vue": "4.0.0-beta.94",
62
+ "effect-app": "4.0.0-beta.94"
63
63
  },
64
64
  "scripts": {
65
65
  "check": "vue-tsc",
@@ -256,6 +256,14 @@ export type FieldValidators<T> = {
256
256
  export type BaseFieldMeta = {
257
257
  required: boolean
258
258
  nullableOrUndefined?: false | "undefined" | "null"
259
+ /**
260
+ * True when the schema property is `S.optionalKey` (AST
261
+ * `context.isOptional`) — i.e. the key should be ABSENT from the submitted
262
+ * object when empty, not present with `undefined`. Distinct from
263
+ * `required: false`, which may also mean "empty string is valid" for
264
+ * unconstrained `S.String` fields.
265
+ */
266
+ isOptionalKey?: boolean
259
267
  }
260
268
 
261
269
  export type StringFieldMeta = BaseFieldMeta & {
@@ -519,6 +527,8 @@ export const createMeta = <T = any>(
519
527
  const key = parent ? `${parent}.${p.name.toString()}` : p.name.toString()
520
528
  const nullableOrUndefined = isNullableOrUndefined(p.type)
521
529
 
530
+ const isOptionalKey = (p.type as any).context?.isOptional === true
531
+
522
532
  // Determine if this field should be required:
523
533
  // - For nullable discriminated unions, only _tag should be non-required
524
534
  // - optionalKey fields are not required
@@ -530,7 +540,7 @@ export const createMeta = <T = any>(
530
540
  } else if (meta.required === false) {
531
541
  // Explicitly set to non-required (legacy behavior for backwards compatibility)
532
542
  isRequired = false
533
- } else if ((p.type as any).context?.isOptional) {
543
+ } else if (isOptionalKey) {
534
544
  isRequired = false
535
545
  } else {
536
546
  // Calculate from the property itself
@@ -741,7 +751,8 @@ export const createMeta = <T = any>(
741
751
  // TODO: handle this better via the createMeta minLength parsing
742
752
  required: isRequired
743
753
  && (!S.AST.isString(typeToProcess) || !!getFieldMetadataFromAst(typeToProcess).minLength),
744
- nullableOrUndefined
754
+ nullableOrUndefined,
755
+ ...(isOptionalKey ? { isOptionalKey: true } : {})
745
756
  }
746
757
  })
747
758
 
@@ -119,6 +119,7 @@ const isFalsyButNotZero = (value: unknown): boolean => {
119
119
  // we remove value and errors when the field is empty and not required
120
120
  // convert nullish value to null or undefined based on schema
121
121
  const handleChange: OmegaFieldInternalApi<From, Name>["handleChange"] = (value) => {
122
+ let fieldDeleted = false
122
123
  if (isFalsyButNotZero(value) && props.meta?.type !== "boolean") {
123
124
  // Only convert to null/undefined if the field is actually nullable or optional
124
125
  if (props.meta?.nullableOrUndefined) {
@@ -128,6 +129,14 @@ const handleChange: OmegaFieldInternalApi<From, Name>["handleChange"] = (value)
128
129
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
129
130
  : null as any
130
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
131
140
  } else {
132
141
  // Keep the actual value (e.g., empty string for S.String fields)
133
142
  props.field.handleChange(value)
@@ -138,7 +147,10 @@ const handleChange: OmegaFieldInternalApi<From, Name>["handleChange"] = (value)
138
147
 
139
148
  // whenever we change the field, regardless if we set it to null, we should reset onSubmit.
140
149
  // not sure why this is not the case in tanstack form.
141
- props.field.setMeta((m) => ({ ...m, errorMap: { ...m.errorMap, onSubmit: undefined } }))
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
+ }
142
154
  }
143
155
 
144
156
  // Note: Default value normalization (converting empty strings to null/undefined for nullable fields)