@effect-app/vue-components 2.6.1 → 2.7.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 (35) hide show
  1. package/dist/types/components/OmegaForm/InputProps.d.ts +10 -4
  2. package/dist/types/components/OmegaForm/OmegaTaggedUnion.vue.d.ts +9 -13
  3. package/dist/types/components/OmegaForm/OmegaTaggedUnionInternal.vue.d.ts +2 -9
  4. package/dist/types/components/OmegaForm/useOmegaForm.d.ts +2 -1
  5. package/dist/vue-components.es10.js +244 -167
  6. package/dist/vue-components.es12.js +137 -115
  7. package/dist/vue-components.es22.js +1 -1
  8. package/dist/vue-components.es23.js +1 -1
  9. package/dist/vue-components.es36.js +1 -1
  10. package/dist/vue-components.es40.js +4 -23
  11. package/dist/vue-components.es41.js +23 -5
  12. package/dist/vue-components.es42.js +5 -21
  13. package/dist/vue-components.es43.js +16 -25
  14. package/dist/vue-components.es44.js +23 -15
  15. package/dist/vue-components.es45.js +17 -7
  16. package/dist/vue-components.es46.js +12 -5
  17. package/dist/vue-components.es47.js +5 -19
  18. package/dist/vue-components.es48.js +19 -9
  19. package/dist/vue-components.es49.js +9 -31
  20. package/dist/vue-components.es50.js +25 -42
  21. package/dist/vue-components.es51.js +38 -16
  22. package/dist/vue-components.es52.js +26 -11
  23. package/dist/vue-components.es53.js +11 -4
  24. package/dist/vue-components.es54.js +1 -1
  25. package/dist/vue-components.es56.js +1 -1
  26. package/dist/vue-components.es58.js +3 -3
  27. package/dist/vue-components.es59.js +1 -1
  28. package/dist/vue-components.es8.js +29 -36
  29. package/dist/vue-components.es9.js +7 -6
  30. package/package.json +1 -1
  31. package/src/components/OmegaForm/InputProps.ts +17 -8
  32. package/src/components/OmegaForm/OmegaFormStuff.ts +52 -0
  33. package/src/components/OmegaForm/OmegaTaggedUnion.vue +16 -35
  34. package/src/components/OmegaForm/OmegaTaggedUnionInternal.vue +2 -1
  35. package/src/components/OmegaForm/useOmegaForm.ts +170 -7
@@ -4,59 +4,40 @@
4
4
  generic="
5
5
  From extends Record<PropertyKey, any>,
6
6
  To extends Record<PropertyKey, any>,
7
- Name extends DeepKeys<From>
7
+ Name extends DeepKeys<From> | undefined = DeepKeys<From>
8
8
  "
9
9
  >
10
- import { type DeepKeys, type DeepValue } from "@tanstack/vue-form"
11
- import { onMounted } from "vue"
12
- import { type TaggedUnionOption, type TaggedUnionOptionsArray } from "./InputProps"
10
+ import { type DeepKeys } from "@tanstack/vue-form"
11
+ import { type TaggedUnionOption } from "./InputProps"
13
12
  import { type FieldPath } from "./OmegaFormStuff"
14
13
  import OmegaTaggedUnionInternal from "./OmegaTaggedUnionInternal.vue"
15
14
  import { type useOmegaForm } from "./useOmegaForm"
16
15
 
17
- const props = defineProps<{
18
- name: Name
16
+ defineProps<{
17
+ name?: Name
19
18
  form: ReturnType<typeof useOmegaForm<From, To>>
20
19
  type?: "select" | "radio"
21
- options: TaggedUnionOptionsArray<From, Name>
20
+ options: TaggedUnionOption<From, Name>[]
22
21
  label?: string
23
22
  }>()
24
-
25
- // Initialize the union field on mount
26
- onMounted(() => {
27
- const currentValue = props.form.getFieldValue(props.name)
28
- const meta = props.form.meta[props.name as keyof typeof props.form.meta]
29
-
30
- if (currentValue === undefined) {
31
- if (meta?.nullableOrUndefined === "null" || !meta?.required) {
32
- // Initialize to null for nullable/optional unions
33
- props.form.setFieldValue(props.name, null as DeepValue<From, Name>)
34
- } else {
35
- // For required unions, initialize with first non-null option
36
- const firstOption = props.options.find((opt) => opt.value !== null)
37
- if (firstOption && firstOption.value) {
38
- props.form.setFieldValue(props.name, {
39
- _tag: firstOption.value
40
- } as DeepValue<From, Name>)
41
- }
42
- }
43
- }
44
- })
45
23
  </script>
46
24
 
47
25
  <template>
48
- <form.Input
49
- :name="`${name}._tag` as FieldPath<From>"
50
- :label="label"
51
- :type="type ?? 'select'"
52
- :options="options as unknown as TaggedUnionOption<From, Name>[]"
53
- />
54
- <form.Field :name="name">
26
+ <slot name="OmegaCustomInput">
27
+ <form.Input
28
+ :name="(name ? `${name}._tag` : '_tag') as FieldPath<From>"
29
+ :label="label"
30
+ :type="type ?? 'select'"
31
+ :options="options"
32
+ />
33
+ </slot>
34
+ <form.Field :name="(name ?? '') as any">
55
35
  <template #default="{ field, state }">
56
36
  <slot v-if="state.value" />
57
37
  <OmegaTaggedUnionInternal
58
38
  :field="field as any"
59
39
  :state="state.value"
40
+ :name="name"
60
41
  >
61
42
  <template
62
43
  v-for="(_, slotname) in $slots"
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <slot
3
3
  v-if="state?._tag"
4
- :name="state?._tag"
4
+ :name="`${name ? `${name}.` : ''}${state?._tag}`"
5
5
  v-bind="{ field, state }"
6
6
  />
7
7
  </template>
@@ -22,6 +22,7 @@ import { type OmegaFieldInternalApi } from "./InputProps"
22
22
  const props = defineProps<{
23
23
  state: DeepValue<From, Name>
24
24
  field: OmegaFieldInternalApi<From, Name>
25
+ name?: DeepKeys<From>
25
26
  }>()
26
27
 
27
28
  // Watch for _tag changes
@@ -16,6 +16,86 @@ import OmegaInput from "./OmegaInput.vue"
16
16
  import OmegaTaggedUnion from "./OmegaTaggedUnion.vue"
17
17
  import OmegaForm from "./OmegaWrapper.vue"
18
18
 
19
+ /**
20
+ * Recursively makes all properties in a schema optional, including nested objects.
21
+ * Unlike S.partial which only makes top-level properties optional, this utility
22
+ * traverses the schema tree and applies partial transformation at every level.
23
+ *
24
+ * Handles:
25
+ * - TypeLiteral (structs): Makes all properties optional and recursively processes nested types
26
+ * - Union types: Recursively applies partial to each union member
27
+ * - Transformation types: Applies partial to both 'from' and 'to' sides
28
+ */
29
+ const partialRecursive = <A, I, R>(schema: S.Schema<A, I, R>): S.Schema<Partial<A>, Partial<I>, R> => {
30
+ const ast = schema.ast
31
+
32
+ // Handle Union types - recursively apply partial to each member
33
+ if (ast._tag === "Union") {
34
+ const partialMembers = (ast as any).types.map((memberAst: any) => {
35
+ const memberSchema = S.make(memberAst)
36
+ const partialMember = partialRecursive(memberSchema as any)
37
+ return partialMember.ast
38
+ })
39
+
40
+ const newAst = {
41
+ ...ast,
42
+ types: partialMembers
43
+ }
44
+
45
+ return S.make(newAst as any)
46
+ }
47
+
48
+ // Handle Transformation types (e.g., withDefaultConstructor)
49
+ if (ast._tag === "Transformation") {
50
+ // For transformations, apply partial to both the 'from' and 'to' sides
51
+ const fromSchema = S.make((ast as any).from)
52
+ const toSchema = S.make((ast as any).to)
53
+ const partialFrom = partialRecursive(fromSchema as any)
54
+ const partialTo = partialRecursive(toSchema as any)
55
+
56
+ const newAst = {
57
+ ...ast,
58
+ from: partialFrom.ast,
59
+ to: partialTo.ast
60
+ }
61
+
62
+ return S.make(newAst as any)
63
+ }
64
+
65
+ // If this is a TypeLiteral (struct), recursively apply partial to nested fields
66
+ if (ast._tag === "TypeLiteral") {
67
+ const fields = ast.propertySignatures.map((prop: any) => {
68
+ const propType = prop.type
69
+ let newType = propType
70
+
71
+ // Recursively handle nested complex types (structs, unions, transformations)
72
+ if (propType._tag === "TypeLiteral" || propType._tag === "Union" || propType._tag === "Transformation") {
73
+ const nestedSchema = S.make(propType)
74
+ const recursivePartial = partialRecursive(nestedSchema as any)
75
+ newType = recursivePartial.ast
76
+ }
77
+
78
+ // Create a new property signature with isOptional: true
79
+ return {
80
+ ...prop,
81
+ type: newType,
82
+ isOptional: true
83
+ }
84
+ })
85
+
86
+ const newAst = {
87
+ ...ast,
88
+ propertySignatures: fields
89
+ }
90
+
91
+ return S.make(newAst as any)
92
+ }
93
+
94
+ // For other schema types (primitives, refinements, etc.), return as-is
95
+ // These types don't need to be made partial, and S.partial doesn't support them anyway
96
+ return schema as any
97
+ }
98
+
19
99
  type keysRule<T> =
20
100
  | {
21
101
  keys?: NestedKeyOf<T>[]
@@ -433,9 +513,10 @@ export interface OmegaFormReturn<
433
513
  never
434
514
  >
435
515
  & {
436
- name: Name
516
+ name?: Name
437
517
  type?: "select" | "radio"
438
518
  options: import("./InputProps").TaggedUnionOptionsArray<From, Name>
519
+ _debugName?: [NoInfer<Name>]
439
520
  label?: string
440
521
  }
441
522
  & {}
@@ -706,22 +787,104 @@ export const useOmegaForm = <
706
787
  return normalized
707
788
  }
708
789
 
790
+ // Helper function to recursively extract default values from schema AST
791
+ const extractDefaultsFromAST = (schemaObj: any): any => {
792
+ const result: Record<string, any> = {}
793
+
794
+ // Check if this schema is a union
795
+ if (schemaObj?.members && Array.isArray(schemaObj.members)) {
796
+ // For unions, we try to find the first member that has a complete set of defaults
797
+ // Priority is given to members with default values for discriminator fields
798
+ for (const member of schemaObj.members) {
799
+ const memberDefaults = extractDefaultsFromAST(member)
800
+ if (Object.keys(memberDefaults).length > 0) {
801
+ // Check if this member has a default value for a discriminator field (like _tag)
802
+ // If it does, use this member's defaults
803
+ const hasDiscriminatorDefault = member?.fields && Object.entries(member.fields).some(
804
+ ([key, fieldSchema]: [string, any]) => {
805
+ // Common discriminator field names
806
+ if (key === "_tag" || key === "type" || key === "kind") {
807
+ return fieldSchema?.ast?.defaultValue !== undefined
808
+ }
809
+ return false
810
+ }
811
+ )
812
+
813
+ if (hasDiscriminatorDefault) {
814
+ return memberDefaults
815
+ }
816
+ }
817
+ }
818
+ // If no member has a discriminator default, return empty
819
+ return {}
820
+ }
821
+
822
+ // Check if this schema has fields (struct)
823
+ if (schemaObj?.fields && typeof schemaObj.fields === "object") {
824
+ for (const [key, fieldSchema] of Object.entries(schemaObj.fields)) {
825
+ // Check if this field has a default value in its AST
826
+ if ((fieldSchema as any)?.ast?.defaultValue) {
827
+ try {
828
+ const defaultValue = (fieldSchema as any).ast.defaultValue()
829
+ if (defaultValue !== undefined) {
830
+ result[key] = defaultValue
831
+ }
832
+ } catch {
833
+ // Silently ignore if defaultValue() throws
834
+ }
835
+ }
836
+
837
+ // Recursively check nested fields for structs and unions
838
+ const nestedDefaults = extractDefaultsFromAST(fieldSchema as any)
839
+ if (Object.keys(nestedDefaults).length > 0) {
840
+ // If we already have a default value for this key, merge with nested
841
+ if (result[key] && typeof result[key] === "object") {
842
+ Object.assign(result[key], nestedDefaults)
843
+ } else if (!result[key]) {
844
+ // Only set nested defaults if we don't have a default value
845
+ result[key] = nestedDefaults
846
+ }
847
+ }
848
+ }
849
+ }
850
+
851
+ return result
852
+ }
853
+
709
854
  // Extract default values from schema constructors (e.g., withDefaultConstructor)
710
855
  const extractSchemaDefaults = (defaultValues: Partial<From> = {}) => {
856
+ let result: Partial<From> = {}
857
+
711
858
  try {
859
+ // First try to use schema.make() if available
860
+ // First try to use schema.make() if available
712
861
  // Note: Partial schemas don't have .make() method yet (https://github.com/Effect-TS/effect/issues/4222)
713
- if ("make" in schema && typeof (schema as any).make === "function") {
714
- return (schema as any).make(defaultValues, { disableValidation: true })
715
- }
862
+ const decoded = (schema as any).make(defaultValues)
863
+ result = S.encodeSync(partialRecursive(schema))(decoded)
716
864
  } catch (error) {
717
- console.warn("Could not extract schema constructor defaults:", error)
718
- return {}
865
+ // If make() fails, try to extract defaults from AST
866
+ if (window.location.hostname === "localhost") {
867
+ console.warn("schema.make() failed, extracting defaults from AST:", error)
868
+ }
869
+ try {
870
+ const astDefaults = extractDefaultsFromAST(schema)
871
+ result = S.encodeSync(partialRecursive(schema))(astDefaults)
872
+ } catch (astError) {
873
+ if (window.location.hostname === "localhost") {
874
+ console.warn("Could not extract defaults from AST:", astError)
875
+ }
876
+ }
719
877
  }
878
+ return deepMerge(result, defaultValues)
720
879
  }
721
880
 
722
881
  const defaultValues = computed(() => {
723
882
  // Normalize tanstack default values at the beginning
724
- const normalizedTanstackDefaults = extractSchemaDefaults(normalizeDefaultValues(tanstackFormOptions?.defaultValues))
883
+ const normalizedTanstackDefaults = extractSchemaDefaults(
884
+ normalizeDefaultValues(
885
+ tanstackFormOptions?.defaultValues
886
+ )
887
+ )
725
888
 
726
889
  if (
727
890
  normalizedTanstackDefaults