@effect-app/vue-components 2.7.11 → 2.9.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.
Files changed (46) hide show
  1. package/dist/types/components/OmegaForm/defaultAST.d.ts +4 -0
  2. package/dist/types/components/OmegaForm/useOmegaForm.d.ts +1 -0
  3. package/dist/vue-components.es10.js +149 -239
  4. package/dist/vue-components.es17.js +97 -5
  5. package/dist/vue-components.es20.js +2 -2
  6. package/dist/vue-components.es21.js +2 -2
  7. package/dist/vue-components.es22.js +1 -1
  8. package/dist/vue-components.es23.js +1 -1
  9. package/dist/vue-components.es31.js +4 -2
  10. package/dist/vue-components.es32.js +1 -1
  11. package/dist/vue-components.es33.js +2 -111
  12. package/dist/vue-components.es34.js +113 -0
  13. package/dist/vue-components.es36.js +7 -32
  14. package/dist/vue-components.es37.js +34 -0
  15. package/dist/vue-components.es41.js +4 -23
  16. package/dist/vue-components.es42.js +23 -5
  17. package/dist/vue-components.es43.js +5 -21
  18. package/dist/vue-components.es44.js +16 -25
  19. package/dist/vue-components.es45.js +23 -15
  20. package/dist/vue-components.es46.js +17 -7
  21. package/dist/vue-components.es47.js +12 -5
  22. package/dist/vue-components.es48.js +5 -19
  23. package/dist/vue-components.es49.js +19 -9
  24. package/dist/vue-components.es50.js +9 -31
  25. package/dist/vue-components.es51.js +25 -42
  26. package/dist/vue-components.es52.js +38 -16
  27. package/dist/vue-components.es53.js +26 -11
  28. package/dist/vue-components.es54.js +11 -65
  29. package/dist/vue-components.es55.js +54 -45
  30. package/dist/vue-components.es56.js +54 -15
  31. package/dist/vue-components.es57.js +15 -31
  32. package/dist/vue-components.es58.js +30 -26
  33. package/dist/vue-components.es59.js +29 -42
  34. package/dist/vue-components.es60.js +42 -2
  35. package/dist/vue-components.es61.js +2 -44
  36. package/dist/vue-components.es62.js +44 -2
  37. package/dist/vue-components.es63.js +4 -0
  38. package/dist/vue-components.es7.js +1 -1
  39. package/dist/vue-components.es9.js +33 -10
  40. package/package.json +23 -23
  41. package/src/components/OmegaForm/OmegaTaggedUnionInternal.vue +50 -1
  42. package/src/components/OmegaForm/defaultAST.ts +191 -0
  43. package/src/components/OmegaForm/useOmegaForm.ts +5 -187
  44. package/dist/vue-components.es35.js +0 -9
  45. package/dist/vue-components.es40.js +0 -6
  46. /package/dist/{vue-components.es38.js → vue-components.es39.js} +0 -0
@@ -1,4 +1,44 @@
1
- var r = "1.9.0";
1
+ import { ROOT_CONTEXT as l } from "./vue-components.es42.js";
2
+ var c = function(t, o) {
3
+ var n = typeof Symbol == "function" && t[Symbol.iterator];
4
+ if (!n) return t;
5
+ var e = n.call(t), a, r = [], u;
6
+ try {
7
+ for (; (o === void 0 || o-- > 0) && !(a = e.next()).done; ) r.push(a.value);
8
+ } catch (i) {
9
+ u = { error: i };
10
+ } finally {
11
+ try {
12
+ a && !a.done && (n = e.return) && n.call(e);
13
+ } finally {
14
+ if (u) throw u.error;
15
+ }
16
+ }
17
+ return r;
18
+ }, p = function(t, o, n) {
19
+ if (n || arguments.length === 2) for (var e = 0, a = o.length, r; e < a; e++)
20
+ (r || !(e in o)) && (r || (r = Array.prototype.slice.call(o, 0, e)), r[e] = o[e]);
21
+ return t.concat(r || Array.prototype.slice.call(o));
22
+ }, y = (
23
+ /** @class */
24
+ (function() {
25
+ function t() {
26
+ }
27
+ return t.prototype.active = function() {
28
+ return l;
29
+ }, t.prototype.with = function(o, n, e) {
30
+ for (var a = [], r = 3; r < arguments.length; r++)
31
+ a[r - 3] = arguments[r];
32
+ return n.call.apply(n, p([e], c(a), !1));
33
+ }, t.prototype.bind = function(o, n) {
34
+ return n;
35
+ }, t.prototype.enable = function() {
36
+ return this;
37
+ }, t.prototype.disable = function() {
38
+ return this;
39
+ }, t;
40
+ })()
41
+ );
2
42
  export {
3
- r as VERSION
43
+ y as NoopContextManager
4
44
  };
@@ -1,46 +1,4 @@
1
- import { VERSION as d } from "./vue-components.es60.js";
2
- var h = /^(\d+)\.(\d+)\.(\d+)(-(.+))?$/;
3
- function s(c) {
4
- var m = /* @__PURE__ */ new Set([c]), f = /* @__PURE__ */ new Set(), t = c.match(h);
5
- if (!t)
6
- return function() {
7
- return !1;
8
- };
9
- var e = {
10
- major: +t[1],
11
- minor: +t[2],
12
- patch: +t[3],
13
- prerelease: t[4]
14
- };
15
- if (e.prerelease != null)
16
- return function(r) {
17
- return r === c;
18
- };
19
- function a(n) {
20
- return f.add(n), !1;
21
- }
22
- function p(n) {
23
- return m.add(n), !0;
24
- }
25
- return function(r) {
26
- if (m.has(r))
27
- return !0;
28
- if (f.has(r))
29
- return !1;
30
- var i = r.match(h);
31
- if (!i)
32
- return a(r);
33
- var u = {
34
- major: +i[1],
35
- minor: +i[2],
36
- patch: +i[3],
37
- prerelease: i[4]
38
- };
39
- return u.prerelease != null || e.major !== u.major ? a(r) : e.major === 0 ? e.minor === u.minor && e.patch <= u.patch ? p(r) : a(r) : e.minor <= u.minor ? p(r) : a(r);
40
- };
41
- }
42
- var v = s(d);
1
+ var r = "1.9.0";
43
2
  export {
44
- s as _makeCompatibilityCheck,
45
- v as isCompatible
3
+ r as VERSION
46
4
  };
@@ -1,4 +1,46 @@
1
- var o = typeof globalThis == "object" ? globalThis : typeof self == "object" ? self : typeof window == "object" ? window : typeof global == "object" ? global : {};
1
+ import { VERSION as d } from "./vue-components.es61.js";
2
+ var h = /^(\d+)\.(\d+)\.(\d+)(-(.+))?$/;
3
+ function s(c) {
4
+ var m = /* @__PURE__ */ new Set([c]), f = /* @__PURE__ */ new Set(), t = c.match(h);
5
+ if (!t)
6
+ return function() {
7
+ return !1;
8
+ };
9
+ var e = {
10
+ major: +t[1],
11
+ minor: +t[2],
12
+ patch: +t[3],
13
+ prerelease: t[4]
14
+ };
15
+ if (e.prerelease != null)
16
+ return function(r) {
17
+ return r === c;
18
+ };
19
+ function a(n) {
20
+ return f.add(n), !1;
21
+ }
22
+ function p(n) {
23
+ return m.add(n), !0;
24
+ }
25
+ return function(r) {
26
+ if (m.has(r))
27
+ return !0;
28
+ if (f.has(r))
29
+ return !1;
30
+ var i = r.match(h);
31
+ if (!i)
32
+ return a(r);
33
+ var u = {
34
+ major: +i[1],
35
+ minor: +i[2],
36
+ patch: +i[3],
37
+ prerelease: i[4]
38
+ };
39
+ return u.prerelease != null || e.major !== u.major ? a(r) : e.major === 0 ? e.minor === u.minor && e.patch <= u.patch ? p(r) : a(r) : e.minor <= u.minor ? p(r) : a(r);
40
+ };
41
+ }
42
+ var v = s(d);
2
43
  export {
3
- o as _globalThis
44
+ s as _makeCompatibilityCheck,
45
+ v as isCompatible
4
46
  };
@@ -0,0 +1,4 @@
1
+ var o = typeof globalThis == "object" ? globalThis : typeof self == "object" ? self : typeof window == "object" ? window : typeof global == "object" ? global : {};
2
+ export {
3
+ o as _globalThis
4
+ };
@@ -1,7 +1,7 @@
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
2
  import { defineComponent as $, computed as n, getCurrentInstance as N, useAttrs as S, useSlots as k, useId as q, renderSlot as u, normalizeProps as s, guardReactiveProps as d, createElementVNode as B, normalizeClass as w, createBlock as I, createCommentVNode as L, unref as A, openBlock as F, mergeProps as O, createSlots as R, withCtx as V } from "vue";
3
3
  import { useStore as z } from "@tanstack/vue-form";
4
- import T from "./vue-components.es38.js";
4
+ import T from "./vue-components.es39.js";
5
5
 
6
6
  const H = /* @__PURE__ */ $({
7
7
  inheritAttrs: !1,
@@ -1,5 +1,8 @@
1
- import { defineComponent as s, watch as m, renderSlot as o, createCommentVNode as r, normalizeProps as f, mergeProps as i } from "vue";
2
- const d = /* @__PURE__ */ s({
1
+ import { defineComponent as l, watch as f, renderSlot as d, createCommentVNode as u, normalizeProps as c, mergeProps as p } from "vue";
2
+ import { S as i } from "effect-app";
3
+ import { getTransformationFrom as h } from "./vue-components.es3.js";
4
+ import { extractSchemaDefaults as S } from "./vue-components.es17.js";
5
+ const b = /* @__PURE__ */ l({
3
6
  __name: "OmegaTaggedUnionInternal",
4
7
  props: {
5
8
  state: {},
@@ -7,15 +10,35 @@ const d = /* @__PURE__ */ s({
7
10
  name: {},
8
11
  form: {}
9
12
  },
10
- setup(e) {
11
- const a = e, l = a.form.useStore(({ values: t }) => t);
12
- return m(() => a.state, (t, n) => {
13
- t === null && a.field.setValue(null), t !== n && (a.form.reset(l.value), setTimeout(() => {
14
- a.field.validate("change");
15
- }, 0));
16
- }), (t, n) => e.state ? o(t.$slots, `${e.name ? `${e.name}.` : ""}${e.state}`, f(i({ key: 0 }, { field: e.field, state: e.state }))) : r("", !0);
13
+ setup(r) {
14
+ const e = r, s = e.form.useStore(({ values: t }) => t);
15
+ return f(() => e.state, (t, o) => {
16
+ if (t === null && e.field.setValue(null), t !== o) {
17
+ if (e.name === void 0 && i.AST.isUnion(e.form._schema.ast)) {
18
+ const n = e.form._schema.ast.types.map((a, m) => ({ original: m, unwrapped: h(a) })).flatMap(
19
+ (a) => i.AST.isTypeLiteral(a.unwrapped) || i.AST.isTransformation(a.unwrapped) ? a.unwrapped.propertySignatures.filter((m) => i.AST.isLiteral(m.type) && m.type.literal === t).length > 0 ? [a.original] : [] : []
20
+ )[0];
21
+ if (n != null && "members" in e.form._schema && Array.isArray(e.form._schema.members)) {
22
+ const a = Object.assign(
23
+ S(
24
+ e.form._schema.members[n],
25
+ s.value
26
+ ),
27
+ { _tag: t }
28
+ );
29
+ e.form.reset(a), setTimeout(() => {
30
+ e.field.validate("change");
31
+ }, 0);
32
+ return;
33
+ }
34
+ }
35
+ e.form.reset(s.value), setTimeout(() => {
36
+ e.field.validate("change");
37
+ }, 0);
38
+ }
39
+ }, { immediate: !0 }), (t, o) => r.state ? d(t.$slots, `${r.name ? `${r.name}.` : ""}${r.state}`, c(p({ key: 0 }, { field: r.field, state: r.state }))) : u("", !0);
17
40
  }
18
41
  });
19
42
  export {
20
- d as default
43
+ b as default
21
44
  };
package/package.json CHANGED
@@ -1,39 +1,39 @@
1
1
  {
2
2
  "name": "@effect-app/vue-components",
3
- "version": "2.7.11",
3
+ "version": "2.9.0",
4
4
  "peerDependencies": {
5
5
  "@mdi/js": "^7.4.47",
6
- "effect": "^3.18.0",
7
- "intl-messageformat": "^10.7.16",
6
+ "effect": "^3.19.3",
7
+ "intl-messageformat": "^10.7.18",
8
8
  "mdi-js": "^1.0.1",
9
9
  "primeflex": "^4.0.0",
10
10
  "primeicons": "^7.0.0",
11
- "primevue": "^4.3.9",
12
- "vue": "^3.5.22",
13
- "vuetify": "^3.10.3"
11
+ "primevue": "^4.4.1",
12
+ "vue": "^3.5.24",
13
+ "vuetify": "^3.10.9"
14
14
  },
15
15
  "devDependencies": {
16
- "@storybook/vue3": "^9.1.9",
17
- "@storybook/vue3-vite": "^9.1.9",
18
- "@types/node": "^24.6.0",
16
+ "@storybook/vue3": "^10.0.6",
17
+ "@storybook/vue3-vite": "^10.0.6",
18
+ "@types/node": "^24.10.0",
19
19
  "@vitejs/plugin-vue": "^6.0.1",
20
20
  "@vue/test-utils": "^2.4.6",
21
- "@vueuse/core": "^13.9.0",
21
+ "@vueuse/core": "^14.0.0",
22
22
  "dprint": "^0.50.2",
23
- "jsdom": "^27.0.0",
24
- "rimraf": "^6.0.1",
25
- "sass": "^1.93.2",
26
- "storybook": "^9.1.9",
27
- "typescript": "~5.9.2",
28
- "vite": "^7.1.7",
23
+ "jsdom": "^27.1.0",
24
+ "rimraf": "^6.1.0",
25
+ "sass": "^1.94.0",
26
+ "storybook": "^10.0.6",
27
+ "typescript": "~5.9.3",
28
+ "vite": "^7.2.2",
29
29
  "vite-plugin-css-injected-by-js": "^3.5.2",
30
30
  "vitepress": "^1.6.4",
31
- "vitest": "^3.2.4",
32
- "vue-router": "^4.5.1",
31
+ "vitest": "^4.0.8",
32
+ "vue-router": "^4.6.3",
33
33
  "vue-toastification": "^2.0.0-rc.5",
34
- "vue-tsc": "^3.1.0",
35
- "vuetify": "^3.10.3",
36
- "@effect-app/eslint-shared-config": "0.3.4"
34
+ "vue-tsc": "^3.1.3",
35
+ "vuetify": "^3.10.9",
36
+ "@effect-app/eslint-shared-config": "0.4.0"
37
37
  },
38
38
  "files": [
39
39
  "src",
@@ -53,8 +53,8 @@
53
53
  "highlight.js": "^11.11.1",
54
54
  "mitt": "^3.0.1",
55
55
  "vue3-highlightjs": "^1.0.5",
56
- "@effect-app/vue": "2.92.2",
57
- "effect-app": "3.12.0"
56
+ "@effect-app/vue": "2.93.0",
57
+ "effect-app": "3.13.0"
58
58
  },
59
59
  "scripts": {
60
60
  "build": "pnpm build:run",
@@ -16,7 +16,10 @@
16
16
  "
17
17
  >
18
18
  import { type DeepKeys, type DeepValue } from "@tanstack/vue-form"
19
+ import { S } from "effect-app"
19
20
  import { watch } from "vue"
21
+ import { getTransformationFrom } from "../../utils"
22
+ import { extractSchemaDefaults } from "./defaultAST"
20
23
  import { type OmegaFieldInternalApi } from "./InputProps"
21
24
  import { type useOmegaForm } from "./useOmegaForm"
22
25
 
@@ -34,11 +37,57 @@ watch(() => props.state, (newTag, oldTag) => {
34
37
  if (newTag === null) {
35
38
  props.field.setValue(null as DeepValue<From, Name>)
36
39
  }
40
+
37
41
  if (newTag !== oldTag) {
42
+ // get default values from AST for the new tag (only for root level tagged unions)
43
+ if (props.name === void 0 && S.AST.isUnion(props.form._schema.ast)) {
44
+ const indexOfSelectedMember = props
45
+ .form
46
+ ._schema
47
+ .ast
48
+ .types
49
+ .map((t, i) => ({ original: i, unwrapped: getTransformationFrom(t) }))
50
+ .flatMap((x) =>
51
+ S.AST.isTypeLiteral(x.unwrapped) || S.AST.isTransformation(x.unwrapped)
52
+ ? x
53
+ .unwrapped
54
+ .propertySignatures
55
+ .filter((ps) => S.AST.isLiteral(ps.type) && ps.type.literal === newTag)
56
+ .length > 0
57
+ ? [x.original]
58
+ : []
59
+ : []
60
+ )[0]
61
+
62
+ // even if the type doesn't say so, indexOfSelectedMember may be undefined
63
+ if (
64
+ indexOfSelectedMember != void 0
65
+ && "members" in props.form._schema
66
+ && Array.isArray(props.form._schema.members)
67
+ ) {
68
+ const defaultsOfSelectedMember = Object.assign(
69
+ extractSchemaDefaults(
70
+ props
71
+ .form
72
+ ._schema
73
+ .members[indexOfSelectedMember],
74
+ values.value
75
+ ),
76
+ { _tag: newTag }
77
+ )
78
+
79
+ props.form.reset(defaultsOfSelectedMember)
80
+ setTimeout(() => {
81
+ props.field.validate("change")
82
+ }, 0)
83
+ return
84
+ }
85
+ }
86
+
38
87
  props.form.reset(values.value)
39
88
  setTimeout(() => {
40
89
  props.field.validate("change")
41
90
  }, 0)
42
91
  }
43
- })
92
+ }, { immediate: true })
44
93
  </script>
@@ -0,0 +1,191 @@
1
+ import { isObject } from "@vueuse/core"
2
+ import { S } from "effect-app"
3
+ import { isNullableOrUndefined } from "./OmegaFormStuff"
4
+
5
+ export function deepMerge(target: any, source: any) {
6
+ for (const key in source) {
7
+ if (Array.isArray(source[key])) {
8
+ // Arrays should be copied directly, not deep merged
9
+ target[key] = source[key]
10
+ } else if (source[key] && isObject(source[key])) {
11
+ if (!target[key]) {
12
+ target[key] = {}
13
+ }
14
+ deepMerge(target[key], source[key])
15
+ } else {
16
+ target[key] = source[key]
17
+ }
18
+ }
19
+ return target
20
+ }
21
+
22
+ /**
23
+ * Recursively makes all properties in a schema optional, including nested objects.
24
+ * Unlike S.partial which only makes top-level properties optional, this utility
25
+ * traverses the schema tree and applies partial transformation at every level.
26
+ *
27
+ * Handles:
28
+ * - TypeLiteral (structs): Makes all properties optional and recursively processes nested types
29
+ * - Union types: Recursively applies partial to each union member
30
+ * - Transformation types: Applies partial to both 'from' and 'to' sides
31
+ */
32
+ const partialRecursive = <A, I, R>(schema: S.Schema<A, I, R>): S.Schema<Partial<A>, Partial<I>, R> => {
33
+ const ast = schema.ast
34
+
35
+ // Handle Refinement types (e.g., NonEmptyArray, filters on ExtendedClass)
36
+ if (ast._tag === "Refinement") {
37
+ const refinementAst = ast as any
38
+ // For refinements, bypass the filter and recursively apply partial to the underlying type
39
+ const fromSchema = S.make(refinementAst.from)
40
+ return partialRecursive(fromSchema as any)
41
+ }
42
+
43
+ // Handle Union types - recursively apply partial to each member
44
+ if (ast._tag === "Union") {
45
+ const partialMembers = (ast as any).types.map((memberAst: any) => {
46
+ const memberSchema = S.make(memberAst)
47
+ const partialMember = partialRecursive(memberSchema as any)
48
+ return partialMember.ast
49
+ })
50
+
51
+ const newAst = {
52
+ ...ast,
53
+ types: partialMembers
54
+ }
55
+
56
+ return S.make(newAst as any)
57
+ }
58
+
59
+ // Handle Transformation types (e.g., withDefaultConstructor, ExtendedClass)
60
+ if (ast._tag === "Transformation") {
61
+ const transformAst = ast as any
62
+
63
+ // Special handling for ExtendedClass (Declaration in 'to' side)
64
+ if (transformAst.to._tag === "Declaration") {
65
+ // For ExtendedClass, extract the TypeLiteral from the 'from' side
66
+ // and make that partial, bypassing the Declaration entirely
67
+ const fromSchema = S.make(transformAst.from)
68
+ return partialRecursive(fromSchema as any)
69
+ }
70
+
71
+ // For other transformations, apply partial to both sides
72
+ const fromSchema = S.make(transformAst.from)
73
+ const toSchema = S.make(transformAst.to)
74
+ const partialFrom = partialRecursive(fromSchema as any)
75
+ const partialTo = partialRecursive(toSchema as any)
76
+
77
+ const newAst = {
78
+ ...ast,
79
+ from: partialFrom.ast,
80
+ to: partialTo.ast
81
+ }
82
+
83
+ return S.make(newAst as any)
84
+ }
85
+
86
+ // If this is a TypeLiteral (struct), recursively apply partial to nested fields
87
+ if (ast._tag === "TypeLiteral") {
88
+ const fields = ast.propertySignatures.map((prop: any) => {
89
+ const propType = prop.type
90
+ let newType = propType
91
+
92
+ // Recursively handle nested complex types (structs, unions, transformations, refinements)
93
+ if (
94
+ propType._tag === "TypeLiteral" || propType._tag === "Union" || propType
95
+ ._tag === "Transformation" || propType
96
+ ._tag === "Refinement"
97
+ ) {
98
+ const nestedSchema = S.make(propType)
99
+ const recursivePartial = partialRecursive(nestedSchema as any)
100
+ newType = recursivePartial.ast
101
+ }
102
+
103
+ // Create a new property signature with isOptional: true
104
+ return {
105
+ ...prop,
106
+ type: newType,
107
+ isOptional: true
108
+ }
109
+ })
110
+
111
+ const newAst = {
112
+ ...ast,
113
+ propertySignatures: fields
114
+ }
115
+
116
+ return S.make(newAst as any)
117
+ }
118
+
119
+ // For other schema types (primitives, refinements, etc.), return as-is
120
+ // These types don't need to be made partial, and S.partial doesn't support them anyway
121
+ return schema as any
122
+ }
123
+
124
+ // Helper function to recursively extract default values from schema AST swag ast
125
+ export const extractDefaultsFromAST = (schemaObj: any): any => {
126
+ const result: Record<string, any> = {}
127
+
128
+ // Check if this schema has fields (struct)
129
+ if (schemaObj?.fields && typeof schemaObj.fields === "object") {
130
+ for (const [key, fieldSchema] of Object.entries(schemaObj.fields)) {
131
+ // Check if this field has a default value in its AST
132
+ if ((fieldSchema as any)?.ast?.defaultValue) {
133
+ try {
134
+ const defaultValue = (fieldSchema as any).ast.defaultValue()
135
+ result[key] = defaultValue
136
+ } catch {
137
+ // Silently ignore if defaultValue() throws
138
+ }
139
+ } else {
140
+ // TODO Should we put to null/undefined only leaves?
141
+ const ast = (fieldSchema as any)?.ast
142
+ const nullableOrUndefined = isNullableOrUndefined(ast)
143
+ switch (nullableOrUndefined) {
144
+ case "null":
145
+ result[key] = null
146
+ break
147
+ case "undefined":
148
+ result[key] = undefined
149
+ break
150
+ }
151
+ }
152
+
153
+ // Recursively check nested fields for structs and unions
154
+ const nestedDefaults = extractDefaultsFromAST(fieldSchema as any)
155
+ if (Object.keys(nestedDefaults).length > 0) {
156
+ // If we already have a default value for this key, merge with nested
157
+ if (result[key] && typeof result[key] === "object") {
158
+ Object.assign(result[key], nestedDefaults)
159
+ } else if (!result[key]) {
160
+ // Only set nested defaults if we don't have a default value
161
+ result[key] = nestedDefaults
162
+ }
163
+ }
164
+ }
165
+ } else {
166
+ if (schemaObj?.from?.fields && typeof schemaObj?.from?.fields === "object") {
167
+ return extractDefaultsFromAST(schemaObj.from)
168
+ }
169
+ }
170
+
171
+ return result
172
+ }
173
+
174
+ // Extract default values from schema constructors (e.g., withDefaultConstructor) swag schema defaults
175
+ export const extractSchemaDefaults = <From, To>(
176
+ schema: S.Schema<To, From, never>,
177
+ defaultValues: Partial<From> = {}
178
+ ) => {
179
+ let result: Partial<From> = {}
180
+
181
+ try {
182
+ const astDefaults = extractDefaultsFromAST(schema)
183
+ result = S.encodeSync(partialRecursive(schema))(astDefaults)
184
+ } catch (astError) {
185
+ if (window.location.hostname === "localhost") {
186
+ console.warn("Could not extract defaults from AST:", astError)
187
+ }
188
+ }
189
+
190
+ return deepMerge(result, defaultValues)
191
+ }