@effect-app/vue-components 4.0.0-beta.22 → 4.0.0-beta.221

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 (264) hide show
  1. package/README.md +13 -9
  2. package/dist/reset.css +39 -38
  3. package/dist/types/components/CommandButton.vue.d.ts +6 -4
  4. package/dist/types/components/OmegaForm/OmegaArray.vue.d.ts +1 -1
  5. package/dist/types/components/OmegaForm/OmegaAutoGen.vue.d.ts +2 -2
  6. package/dist/types/components/OmegaForm/OmegaErrorsInternal.vue.d.ts +1 -1
  7. package/dist/types/components/OmegaForm/OmegaFormInput.vue.d.ts +1 -1
  8. package/dist/types/components/OmegaForm/OmegaInput.vue.d.ts +1 -1
  9. package/dist/types/components/OmegaForm/OmegaInternalInput.vue.d.ts +2 -1
  10. package/dist/types/components/OmegaForm/OmegaWrapper.vue.d.ts +1 -1
  11. package/dist/types/components/OmegaForm/createUseFormWithCustomInput.d.ts +2 -2
  12. package/dist/types/components/OmegaForm/errors.d.ts +33 -0
  13. package/dist/types/components/OmegaForm/getOmegaStore.d.ts +1 -1
  14. package/dist/types/components/OmegaForm/hocs.d.ts +3 -0
  15. package/dist/types/components/OmegaForm/index.d.ts +13 -3
  16. package/dist/types/components/OmegaForm/inputs.d.ts +4 -0
  17. package/dist/types/components/OmegaForm/meta/checks.d.ts +4 -0
  18. package/dist/types/components/OmegaForm/meta/createMeta.d.ts +33 -0
  19. package/dist/types/components/OmegaForm/meta/defaults.d.ts +2 -0
  20. package/dist/types/components/OmegaForm/meta/redacted.d.ts +2 -0
  21. package/dist/types/components/OmegaForm/meta/types.d.ts +56 -0
  22. package/dist/types/components/OmegaForm/meta/walker.d.ts +18 -0
  23. package/dist/types/components/OmegaForm/persistency.d.ts +58 -0
  24. package/dist/types/components/OmegaForm/submit.d.ts +60 -0
  25. package/dist/types/components/OmegaForm/types.d.ts +283 -0
  26. package/dist/types/components/OmegaForm/useOmegaForm.d.ts +7 -213
  27. package/dist/types/components/OmegaForm/validation/localized.d.ts +10 -0
  28. package/dist/types/index.d.ts +0 -1
  29. package/dist/types/utils/index.d.ts +8 -8
  30. package/dist/vue-components.es.js +29 -44
  31. package/dist/vue-components10.es.js +5 -0
  32. package/dist/vue-components100.es.js +269 -0
  33. package/dist/vue-components102.es.js +8 -0
  34. package/dist/vue-components103.es.js +73 -0
  35. package/dist/vue-components104.es.js +5 -0
  36. package/dist/vue-components105.es.js +52 -0
  37. package/dist/vue-components106.es.js +5 -0
  38. package/dist/vue-components107.es.js +24 -0
  39. package/dist/vue-components108.es.js +5 -0
  40. package/dist/vue-components109.es.js +59 -0
  41. package/dist/vue-components11.es.js +20 -0
  42. package/dist/vue-components110.es.js +5 -0
  43. package/dist/vue-components111.es.js +12 -0
  44. package/dist/vue-components112.es.js +22 -0
  45. package/dist/vue-components114.es.js +9 -0
  46. package/dist/vue-components115.es.js +4 -0
  47. package/dist/vue-components116.es.js +38 -0
  48. package/dist/vue-components117.es.js +27 -0
  49. package/dist/vue-components118.es.js +28 -0
  50. package/dist/vue-components119.es.js +7 -0
  51. package/dist/vue-components12.es.js +27 -0
  52. package/dist/vue-components120.es.js +18 -0
  53. package/dist/vue-components121.es.js +36 -0
  54. package/dist/vue-components122.es.js +18 -0
  55. package/dist/vue-components123.es.js +21 -0
  56. package/dist/vue-components124.es.js +30 -0
  57. package/dist/vue-components125.es.js +7 -0
  58. package/dist/vue-components126.es.js +9 -0
  59. package/dist/vue-components127.es.js +38 -0
  60. package/dist/vue-components128.es.js +25 -0
  61. package/dist/vue-components129.es.js +128 -0
  62. package/dist/vue-components13.es.js +70 -0
  63. package/dist/vue-components130.es.js +24 -0
  64. package/dist/vue-components131.es.js +21 -0
  65. package/dist/vue-components132.es.js +9 -0
  66. package/dist/vue-components133.es.js +19 -0
  67. package/dist/vue-components134.es.js +5 -0
  68. package/dist/vue-components135.es.js +29 -0
  69. package/dist/vue-components136.es.js +5 -0
  70. package/dist/vue-components137.es.js +43 -0
  71. package/dist/vue-components138.es.js +82 -0
  72. package/dist/vue-components139.es.js +33 -0
  73. package/dist/vue-components14.es.js +15 -0
  74. package/dist/vue-components140.es.js +19 -0
  75. package/dist/vue-components141.es.js +48 -0
  76. package/dist/vue-components15.es.js +29 -0
  77. package/dist/vue-components16.es.js +53 -0
  78. package/dist/vue-components17.es.js +87 -0
  79. package/dist/vue-components18.es.js +4 -0
  80. package/dist/vue-components19.es.js +4 -0
  81. package/dist/vue-components2.es.js +20 -0
  82. package/dist/vue-components20.es.js +19 -0
  83. package/dist/vue-components21.es.js +73 -0
  84. package/dist/vue-components22.es.js +14 -0
  85. package/dist/vue-components23.es.js +26 -0
  86. package/dist/vue-components24.es.js +252 -0
  87. package/dist/vue-components25.es.js +65 -0
  88. package/dist/vue-components26.es.js +68 -0
  89. package/dist/vue-components27.es.js +8 -0
  90. package/dist/vue-components28.es.js +12 -0
  91. package/dist/vue-components29.es.js +6 -0
  92. package/dist/vue-components3.es.js +86 -0
  93. package/dist/vue-components30.es.js +28 -0
  94. package/dist/vue-components31.es.js +75 -0
  95. package/dist/vue-components32.es.js +109 -0
  96. package/dist/vue-components33.es.js +57 -0
  97. package/dist/vue-components34.es.js +7 -0
  98. package/dist/vue-components35.es.js +4 -0
  99. package/dist/vue-components36.es.js +6 -0
  100. package/dist/vue-components37.es.js +688 -0
  101. package/dist/vue-components38.es.js +7 -0
  102. package/dist/vue-components39.es.js +5 -0
  103. package/dist/vue-components4.es.js +5 -0
  104. package/dist/vue-components40.es.js +6 -0
  105. package/dist/vue-components41.es.js +27 -0
  106. package/dist/vue-components42.es.js +5 -0
  107. package/dist/vue-components43.es.js +48 -0
  108. package/dist/vue-components44.es.js +70 -0
  109. package/dist/vue-components45.es.js +9 -0
  110. package/dist/vue-components46.es.js +10 -0
  111. package/dist/vue-components47.es.js +8 -0
  112. package/dist/vue-components48.es.js +173 -0
  113. package/dist/vue-components49.es.js +14 -0
  114. package/dist/vue-components5.es.js +24 -0
  115. package/dist/vue-components50.es.js +11 -0
  116. package/dist/vue-components51.es.js +4 -0
  117. package/dist/vue-components52.es.js +7 -0
  118. package/dist/vue-components53.es.js +29 -0
  119. package/dist/vue-components54.es.js +221 -0
  120. package/dist/vue-components55.es.js +85 -0
  121. package/dist/vue-components56.es.js +74 -0
  122. package/dist/vue-components57.es.js +819 -0
  123. package/dist/vue-components58.es.js +4 -0
  124. package/dist/vue-components59.es.js +109 -0
  125. package/dist/vue-components6.es.js +13 -0
  126. package/dist/vue-components60.es.js +54 -0
  127. package/dist/vue-components61.es.js +520 -0
  128. package/dist/vue-components62.es.js +440 -0
  129. package/dist/vue-components63.es.js +10 -0
  130. package/dist/vue-components64.es.js +13 -0
  131. package/dist/vue-components65.es.js +19 -0
  132. package/dist/vue-components66.es.js +29 -0
  133. package/dist/vue-components67.es.js +22 -0
  134. package/dist/vue-components68.es.js +30 -0
  135. package/dist/vue-components69.es.js +29 -0
  136. package/dist/vue-components7.es.js +13 -0
  137. package/dist/vue-components70.es.js +73 -0
  138. package/dist/vue-components71.es.js +6 -0
  139. package/dist/vue-components72.es.js +18 -0
  140. package/dist/vue-components73.es.js +5 -0
  141. package/dist/vue-components74.es.js +70 -0
  142. package/dist/vue-components75.es.js +140 -0
  143. package/dist/vue-components76.es.js +4 -0
  144. package/dist/vue-components77.es.js +21 -0
  145. package/dist/vue-components78.es.js +55 -0
  146. package/dist/vue-components79.es.js +9 -0
  147. package/dist/vue-components8.es.js +35 -0
  148. package/dist/vue-components80.es.js +16 -0
  149. package/dist/vue-components81.es.js +39 -0
  150. package/dist/vue-components82.es.js +49 -0
  151. package/dist/vue-components83.es.js +128 -0
  152. package/dist/vue-components84.es.js +65 -0
  153. package/dist/vue-components85.es.js +63 -0
  154. package/dist/vue-components86.es.js +25 -0
  155. package/dist/vue-components87.es.js +5 -0
  156. package/dist/vue-components88.es.js +80 -0
  157. package/dist/vue-components89.es.js +95 -0
  158. package/dist/vue-components9.es.js +47 -0
  159. package/dist/vue-components90.es.js +73 -0
  160. package/dist/vue-components91.es.js +12 -0
  161. package/dist/vue-components92.es.js +56 -0
  162. package/dist/vue-components93.es.js +5 -0
  163. package/dist/vue-components94.es.js +44 -0
  164. package/dist/vue-components95.es.js +5 -0
  165. package/dist/vue-components96.es.js +84 -0
  166. package/dist/vue-components98.es.js +8 -0
  167. package/dist/vue-components99.es.js +9 -0
  168. package/package.json +29 -29
  169. package/src/components/CommandButton.vue +55 -7
  170. package/src/components/OmegaForm/OmegaArray.vue +2 -4
  171. package/src/components/OmegaForm/OmegaAutoGen.vue +3 -2
  172. package/src/components/OmegaForm/OmegaErrorsInternal.vue +1 -1
  173. package/src/components/OmegaForm/OmegaFormInput.vue +1 -1
  174. package/src/components/OmegaForm/OmegaInput.vue +7 -36
  175. package/src/components/OmegaForm/OmegaInputVuetify.vue +5 -2
  176. package/src/components/OmegaForm/OmegaInternalInput.vue +12 -6
  177. package/src/components/OmegaForm/OmegaTaggedUnion.vue +2 -1
  178. package/src/components/OmegaForm/OmegaTaggedUnionInternal.vue +1 -1
  179. package/src/components/OmegaForm/OmegaWrapper.vue +1 -1
  180. package/src/components/OmegaForm/blockDialog.ts +18 -6
  181. package/src/components/OmegaForm/createUseFormWithCustomInput.ts +2 -1
  182. package/src/components/OmegaForm/errors.ts +136 -0
  183. package/src/components/OmegaForm/getOmegaStore.ts +1 -1
  184. package/src/components/OmegaForm/hocs.ts +19 -0
  185. package/src/components/OmegaForm/index.ts +16 -4
  186. package/src/components/OmegaForm/inputs.ts +22 -0
  187. package/src/components/OmegaForm/meta/checks.ts +82 -0
  188. package/src/components/OmegaForm/meta/createMeta.ts +140 -0
  189. package/src/components/OmegaForm/meta/defaults.ts +134 -0
  190. package/src/components/OmegaForm/meta/redacted.ts +66 -0
  191. package/src/components/OmegaForm/meta/types.ts +78 -0
  192. package/src/components/OmegaForm/meta/walker.ts +248 -0
  193. package/src/components/OmegaForm/persistency.ts +247 -0
  194. package/src/components/OmegaForm/submit.ts +131 -0
  195. package/src/components/OmegaForm/types.ts +753 -0
  196. package/src/components/OmegaForm/useOmegaForm.ts +59 -893
  197. package/src/components/OmegaForm/useRegisterField.ts +1 -1
  198. package/src/components/OmegaForm/validation/localized.ts +203 -0
  199. package/src/index.ts +0 -1
  200. package/src/reset.css +39 -38
  201. package/src/utils/index.ts +11 -8
  202. package/dist/types/components/OmegaForm/OmegaFormStuff.d.ts +0 -159
  203. package/dist/types/constants/index.d.ts +0 -1
  204. package/dist/vue-components.es10.js +0 -239
  205. package/dist/vue-components.es11.js +0 -32
  206. package/dist/vue-components.es12.js +0 -503
  207. package/dist/vue-components.es13.js +0 -49
  208. package/dist/vue-components.es14.js +0 -4
  209. package/dist/vue-components.es15.js +0 -4
  210. package/dist/vue-components.es16.js +0 -6
  211. package/dist/vue-components.es17.js +0 -13
  212. package/dist/vue-components.es18.js +0 -57
  213. package/dist/vue-components.es19.js +0 -56
  214. package/dist/vue-components.es2.js +0 -30
  215. package/dist/vue-components.es20.js +0 -8
  216. package/dist/vue-components.es21.js +0 -8
  217. package/dist/vue-components.es22.js +0 -5
  218. package/dist/vue-components.es23.js +0 -5
  219. package/dist/vue-components.es24.js +0 -4
  220. package/dist/vue-components.es25.js +0 -4
  221. package/dist/vue-components.es26.js +0 -4
  222. package/dist/vue-components.es27.js +0 -4
  223. package/dist/vue-components.es28.js +0 -19
  224. package/dist/vue-components.es29.js +0 -13
  225. package/dist/vue-components.es3.js +0 -17
  226. package/dist/vue-components.es30.js +0 -194
  227. package/dist/vue-components.es32.js +0 -31
  228. package/dist/vue-components.es33.js +0 -6
  229. package/dist/vue-components.es34.js +0 -4
  230. package/dist/vue-components.es35.js +0 -4
  231. package/dist/vue-components.es36.js +0 -113
  232. package/dist/vue-components.es38.js +0 -9
  233. package/dist/vue-components.es39.js +0 -34
  234. package/dist/vue-components.es4.js +0 -52
  235. package/dist/vue-components.es41.js +0 -6
  236. package/dist/vue-components.es42.js +0 -25
  237. package/dist/vue-components.es43.js +0 -7
  238. package/dist/vue-components.es44.js +0 -23
  239. package/dist/vue-components.es45.js +0 -32
  240. package/dist/vue-components.es46.js +0 -24
  241. package/dist/vue-components.es47.js +0 -14
  242. package/dist/vue-components.es48.js +0 -7
  243. package/dist/vue-components.es49.js +0 -21
  244. package/dist/vue-components.es5.js +0 -52
  245. package/dist/vue-components.es50.js +0 -11
  246. package/dist/vue-components.es51.js +0 -33
  247. package/dist/vue-components.es52.js +0 -50
  248. package/dist/vue-components.es53.js +0 -28
  249. package/dist/vue-components.es54.js +0 -13
  250. package/dist/vue-components.es55.js +0 -67
  251. package/dist/vue-components.es56.js +0 -58
  252. package/dist/vue-components.es57.js +0 -19
  253. package/dist/vue-components.es58.js +0 -35
  254. package/dist/vue-components.es59.js +0 -31
  255. package/dist/vue-components.es6.js +0 -69
  256. package/dist/vue-components.es60.js +0 -44
  257. package/dist/vue-components.es61.js +0 -4
  258. package/dist/vue-components.es62.js +0 -46
  259. package/dist/vue-components.es63.js +0 -4
  260. package/dist/vue-components.es7.js +0 -83
  261. package/dist/vue-components.es8.js +0 -63
  262. package/dist/vue-components.es9.js +0 -21
  263. package/src/components/OmegaForm/OmegaFormStuff.ts +0 -1276
  264. package/src/constants/index.ts +0 -1
@@ -1,5 +1,6 @@
1
1
  import mitt from "mitt"
2
2
  import { inject, type InjectionKey, provide, type Ref } from "vue"
3
+ import { useIntl } from "../../utils"
3
4
  import { onMountedWithCleanup } from "./onMountedWithCleanup"
4
5
 
5
6
  export type DialogClosing = { prevent?: boolean | Promise<boolean> }
@@ -19,11 +20,19 @@ export const usePreventClose = (mkIsDirty: () => Ref<boolean>) => {
19
20
  if (!bus) {
20
21
  return
21
22
  }
23
+ const { formatMessage, trans } = useIntl()
22
24
  const isDirty = mkIsDirty()
25
+ const defaultMessage = "There are unsaved changes. Are you sure you want to close?"
23
26
  onMountedWithCleanup(() => {
24
27
  const onDialogClosing = (evt: DialogClosing) => {
25
28
  if (isDirty.value) {
26
- if (!confirm("Es sind ungespeicherte Änderungen vorhanden. Wirklich schließen?")) {
29
+ // Mirror the guard pattern in errors.ts: a custom `useIntl` mock may
30
+ // only provide `trans`, so fall back through trans → defaultMessage.
31
+ const message = formatMessage
32
+ ? formatMessage({ id: "form.unsaved_changes_confirm", defaultMessage })
33
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- key may not be registered in the locale catalog
34
+ : trans?.("form.unsaved_changes_confirm" as any) ?? defaultMessage
35
+ if (!confirm(message)) {
27
36
  evt.prevent = true
28
37
  }
29
38
  }
@@ -46,11 +55,14 @@ export const useOnClose = (close: () => void) => {
46
55
  bus.emit("dialog-closing", evt)
47
56
  if (evt.prevent) {
48
57
  if (typeof evt.prevent === "object" && "then" in evt.prevent) {
49
- evt.prevent.then((r) => {
50
- if (r !== false) {
51
- close()
52
- }
53
- })
58
+ evt
59
+ .prevent
60
+ .then((r) => {
61
+ if (r) {
62
+ close()
63
+ }
64
+ })
65
+ .catch(console.error)
54
66
  }
55
67
  } else {
56
68
  close()
@@ -1,8 +1,9 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any -- TanStack Form / Vue render-fn slot interop */
1
2
  import type { DeepKeys } from "@tanstack/vue-form"
2
3
  import { type Component, h } from "vue"
3
4
  import type { MergedInputProps } from "./InputProps"
4
- import { type DefaultTypeProps } from "./OmegaFormStuff"
5
5
  import OmegaInput from "./OmegaInput.vue"
6
+ import { type DefaultTypeProps } from "./types"
6
7
  import { useOmegaForm } from "./useOmegaForm"
7
8
 
8
9
  export const createUseFormWithCustomInput = <
@@ -0,0 +1,136 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+
3
+ import { type Component, computed, type ComputedRef, type ConcreteComponent, h, onUnmounted, type Ref, ref, watch } from "vue"
4
+ import { useIntl } from "../../utils"
5
+ import type { OmegaError } from "./types"
6
+ import type { OF } from "./useOmegaForm"
7
+
8
+ export const useErrorLabel = (form: OF<any, any>) => {
9
+ const { formatMessage } = useIntl()
10
+ const humanize = (str: string) => {
11
+ return str
12
+ .replace(/([A-Z])/g, " $1") // Add space before capital letters
13
+ .replace(/^./, (char) => char.toUpperCase()) // Capitalize the first letter
14
+ .trim() // Remove leading/trailing spaces
15
+ }
16
+ const fallback = (propsName: string) =>
17
+ formatMessage
18
+ ? formatMessage({ id: `general.fields.${propsName}`, defaultMessage: humanize(propsName) })
19
+ : humanize(propsName)
20
+ const i18n = (propsName: string) =>
21
+ form.i18nNamespace
22
+ ? formatMessage({ id: `${form.i18nNamespace}.fields.${propsName}`, defaultMessage: fallback(propsName) })
23
+ : fallback(propsName)
24
+
25
+ return i18n
26
+ }
27
+
28
+ export const eHoc = (errorProps: {
29
+ form: OF<any, any>
30
+ fieldMap: Ref<Map<string, { id: string; label: string }>>
31
+ }) => {
32
+ return function FormHoc<P>(
33
+ WrappedComponent: Component<P>
34
+ ): ConcreteComponent<P> {
35
+ return {
36
+ setup() {
37
+ const { fieldMap, form } = errorProps
38
+ const generalErrors = form.useStore((state) => state.errors)
39
+ const fieldMeta = form.useStore((state) => state.fieldMeta)
40
+ const errorMap = form.useStore((state) => state.errorMap)
41
+
42
+ const errorLabel = useErrorLabel(form)
43
+
44
+ const errors = computed(() => {
45
+ // Collect errors from fieldMeta (field-level errors for registered fields)
46
+ const fieldErrors = Object.entries(fieldMeta.value).reduce<OmegaError[]>((acc, [key, m]) => {
47
+ const fieldErrors = (m as { errors?: Array<{ message?: string }> } | undefined)?.errors ?? []
48
+ if (!fieldErrors.length) {
49
+ return acc
50
+ }
51
+
52
+ const fieldInfo = fieldMap.value.get(key)
53
+ if (!fieldInfo) {
54
+ return acc
55
+ }
56
+
57
+ acc.push({
58
+ label: fieldInfo.label,
59
+ inputId: fieldInfo.id,
60
+ errors: [fieldErrors[0]?.message].filter(Boolean) as string[]
61
+ })
62
+
63
+ return acc
64
+ }, [])
65
+
66
+ // Collect errors from errorMap.onDynamic / errorMap.onSubmit ONLY for fields that are NOT registered
67
+ // (registered fields already have their errors in fieldMeta).
68
+ // Our localized standard schema writes to onDynamic via validationLogic: revalidateLogic();
69
+ // caller-provided validators.onSubmit (via tanstackFormOptions spread) writes to onSubmit.
70
+ const submitErrors: OmegaError[] = []
71
+ const submitIssueMaps = [errorMap.value.onDynamic, errorMap.value.onSubmit].filter(
72
+ Boolean
73
+ ) as unknown as Array<
74
+ Record<string, unknown>
75
+ >
76
+ const seenPaths = new Set<string>()
77
+ for (const issuesByPath of submitIssueMaps) {
78
+ for (const [_, issues] of Object.entries(issuesByPath)) {
79
+ if (Array.isArray(issues) && issues.length) {
80
+ for (const issue of issues) {
81
+ const issAny: any = issue
82
+ if (issAny?.path && Array.isArray(issAny.path) && issAny.path.length) {
83
+ const fieldPath = issAny.path.join(".")
84
+ if (!fieldMap.value.has(fieldPath) && !seenPaths.has(fieldPath)) {
85
+ seenPaths.add(fieldPath)
86
+ submitErrors.push({
87
+ label: errorLabel(fieldPath),
88
+ inputId: fieldPath,
89
+ errors: [issAny.message].filter(Boolean)
90
+ })
91
+ break
92
+ }
93
+ }
94
+ }
95
+ }
96
+ }
97
+ }
98
+
99
+ // Combine both error sources (no need to check for duplicates since they're mutually exclusive)
100
+ return [...fieldErrors, ...submitErrors]
101
+ })
102
+
103
+ return {
104
+ generalErrors,
105
+ errors
106
+ }
107
+ },
108
+ render({ errors, generalErrors }: any) {
109
+ return h(WrappedComponent, {
110
+ errors,
111
+ generalErrors,
112
+ ...this.$attrs
113
+ }, this.$slots)
114
+ }
115
+ }
116
+ }
117
+ }
118
+
119
+ export const makeFieldMap = () => {
120
+ const fieldMap = ref(new Map<string, { label: string; id: string }>())
121
+ const registerField = (field: ComputedRef<{ name: string; label: string; id: string }>) => {
122
+ watch(field, (f) => {
123
+ fieldMap.value.set(f.name, { label: f.label, id: f.id })
124
+ }, { immediate: true })
125
+ onUnmounted(() => {
126
+ // Only delete if we still own this entry (id matches)
127
+ // This prevents old components from deleting entries registered by new components
128
+ // during re-mount transitions (e.g., when :key changes)
129
+ const currentEntry = fieldMap.value.get(field.value.name)
130
+ if (currentEntry?.id === field.value.id) {
131
+ fieldMap.value.delete(field.value.name)
132
+ }
133
+ })
134
+ }
135
+ return { fieldMap, registerField }
136
+ }
@@ -1,6 +1,6 @@
1
1
  import { useStore } from "@tanstack/vue-form"
2
2
  import { computed, type Ref } from "vue"
3
- import type { OmegaFormApi, OmegaFormState } from "./OmegaFormStuff"
3
+ import type { OmegaFormApi, OmegaFormState } from "./types"
4
4
 
5
5
  export function getOmegaStore<
6
6
  To,
@@ -0,0 +1,19 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+
3
+ import { type Component, type ConcreteComponent, h } from "vue"
4
+ import type { OF } from "./useOmegaForm"
5
+
6
+ export const fHoc = (form: OF<any, any>) => {
7
+ return function FormHoc<P>(
8
+ WrappedComponent: Component<P>
9
+ ): ConcreteComponent<P> {
10
+ return {
11
+ render() {
12
+ return h(WrappedComponent, {
13
+ form,
14
+ ...this.$attrs
15
+ }, this.$slots)
16
+ }
17
+ }
18
+ }
19
+ }
@@ -1,5 +1,17 @@
1
- export * from "./OmegaFormStuff"
2
- export { type OmegaConfig, type OmegaFormReturn, useOmegaForm } from "./useOmegaForm"
1
+ import type * as S from "effect-app/Schema"
2
+
3
+ export { getInputType, type SupportedInputs } from "./inputs"
4
+ export { createMeta, generateMetaFromSchema, isNullableOrUndefined, metadataFromAst } from "./meta/createMeta"
5
+ export type { CreateMeta, FilterItems } from "./meta/createMeta"
6
+ export { defaultsValueFromSchema } from "./meta/defaults"
7
+ export { toFormSchema } from "./meta/redacted"
8
+ export type { BaseFieldMeta, BooleanFieldMeta, DateFieldMeta, FieldMeta, MetaRecord, MultipleFieldMeta, NestedKeyOf, NumberFieldMeta, SelectFieldMeta, StringFieldMeta, UnknownFieldMeta } from "./meta/types"
9
+ export { deepMerge } from "./persistency"
10
+ export type { BaseProps, DefaultTypeProps, FieldPath, FieldPath_, FieldValidators, FormComponent, FormProps, FormType, OmegaArrayProps, OmegaAutoGenMeta, OmegaError, OmegaFormApi, OmegaFormParams, OmegaFormState, OmegaInputProps, OmegaInputPropsBase, PrefixFromDepth, TypeOverride, TypesWithOptions } from "./types"
11
+ export { makeStandardSchemaV1Hooks, toLocalizedStandardSchemaV1 } from "./validation/localized"
12
+
13
+ export { FormErrors, OmegaFormKey, useErrorLabel, useOmegaForm } from "./useOmegaForm"
14
+ export type { defaultValuesPriorityUnion, OF, OmegaConfig, OmegaFormReturn, Policies } from "./useOmegaForm"
3
15
 
4
16
  export { type ExtractTagValue, type ExtractUnionBranch, type InputProps, type MergedInputProps, type TaggedUnionOption, type TaggedUnionOptionsArray, type TaggedUnionProps } from "./InputProps"
5
17
  export { default as OmegaInput } from "./OmegaInput.vue"
@@ -9,6 +21,6 @@ export { default as OmegaTaggedUnionInternal } from "./OmegaTaggedUnionInternal.
9
21
 
10
22
  export { useOnClose, usePreventClose } from "./blockDialog"
11
23
 
12
- export { getInputType } from "./OmegaFormStuff"
13
-
14
24
  export { createUseFormWithCustomInput } from "./createUseFormWithCustomInput"
25
+
26
+ export const duplicateSchema = <From, To>(schema: S.Codec<To, From>) => schema
@@ -0,0 +1,22 @@
1
+ const supportedInputs = [
2
+ "button",
3
+ "checkbox",
4
+ "color",
5
+ "date",
6
+ "email",
7
+ "number",
8
+ "password",
9
+ "radio",
10
+ "range",
11
+ "search",
12
+ "submit",
13
+ "tel",
14
+ "text",
15
+ "time",
16
+ "url"
17
+ ] as const
18
+
19
+ export type SupportedInputs = typeof supportedInputs[number]
20
+
21
+ export const getInputType = (input: string): SupportedInputs =>
22
+ (supportedInputs as readonly string[]).includes(input) ? input as SupportedInputs : "text"
@@ -0,0 +1,82 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import * as S from "effect-app/Schema"
3
+ import type * as Record from "effect/Record"
4
+ import type { FieldMeta } from "./types"
5
+
6
+ export const getCheckMetas = (property: S.AST.AST): Array<Record<string, any>> => {
7
+ const checks = property.checks ?? []
8
+
9
+ return checks.flatMap((check) => {
10
+ if (check._tag === "FilterGroup") {
11
+ return check.checks.flatMap((inner) => {
12
+ const meta = inner.annotations?.meta
13
+ return meta && typeof meta === "object" ? [meta as Record<string, any>] : []
14
+ })
15
+ }
16
+
17
+ const meta = check.annotations?.meta
18
+ return meta && typeof meta === "object" ? [meta as Record<string, any>] : []
19
+ })
20
+ }
21
+
22
+ export const getFieldMetadataFromAst = (property: S.AST.AST) => {
23
+ const base: Partial<FieldMeta> & Record<string, unknown> = {
24
+ description: S.AST.resolveDescription(property)
25
+ }
26
+ const checks = getCheckMetas(property)
27
+
28
+ if (S.AST.isString(property)) {
29
+ base.type = "string"
30
+ for (const check of checks) {
31
+ switch (check._tag) {
32
+ case "isMinLength":
33
+ base.minLength = check.minLength
34
+ break
35
+ case "isMaxLength":
36
+ base.maxLength = check.maxLength
37
+ break
38
+ }
39
+ }
40
+
41
+ const format = property.annotations?.["format"]
42
+ if (format === "email") {
43
+ base.format = "email"
44
+ }
45
+ } else if (S.AST.isNumber(property)) {
46
+ base.type = "number"
47
+ for (const check of checks) {
48
+ switch (check._tag) {
49
+ case "isInt":
50
+ base.refinement = "int"
51
+ break
52
+ case "isGreaterThanOrEqualTo":
53
+ base.minimum = check.minimum
54
+ break
55
+ case "isLessThanOrEqualTo":
56
+ base.maximum = check.maximum
57
+ break
58
+ case "isBetween":
59
+ base.minimum = check.minimum
60
+ base.maximum = check.maximum
61
+ break
62
+ case "isGreaterThan":
63
+ base.exclusiveMinimum = check.exclusiveMinimum
64
+ break
65
+ case "isLessThan":
66
+ base.exclusiveMaximum = check.exclusiveMaximum
67
+ break
68
+ }
69
+ }
70
+ } else if (S.AST.isBoolean(property)) {
71
+ base.type = "boolean"
72
+ } else if (
73
+ S.AST.isDeclaration(property)
74
+ && (property.annotations as any)?.typeConstructor?._tag === "Date"
75
+ ) {
76
+ base.type = "date"
77
+ } else {
78
+ base.type = "unknown"
79
+ }
80
+
81
+ return base
82
+ }
@@ -0,0 +1,140 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import type * as Effect from "effect-app/Effect"
3
+ import * as S from "effect-app/Schema"
4
+ import type * as Record from "effect/Record"
5
+ import { getTransformationFrom } from "../../../utils"
6
+ import type { FieldMeta, MetaRecord } from "./types"
7
+ import { classifyAndWalkUnion, leafMetaForAst, type ParentMeta, type WalkerContext, walkStruct } from "./walker"
8
+
9
+ export type FilterItems = {
10
+ items: readonly [string, ...string[]]
11
+ message:
12
+ | string
13
+ | Effect.Effect<string>
14
+ | { readonly message: string | Effect.Effect<string> }
15
+ }
16
+
17
+ export type CreateMeta =
18
+ & {
19
+ parent?: string
20
+ meta?: Record<string, any>
21
+ nullableOrUndefined?: false | "undefined" | "null"
22
+ }
23
+ & (
24
+ | {
25
+ propertySignatures: readonly S.AST.PropertySignature[]
26
+ property?: never
27
+ }
28
+ | {
29
+ propertySignatures?: never
30
+ property: S.AST.AST
31
+ }
32
+ )
33
+
34
+ export const unwrapDeclaration = (property: S.AST.AST): S.AST.AST => {
35
+ let current = getTransformationFrom(property)
36
+
37
+ while (S.AST.isDeclaration(current) && current.typeParameters.length > 0) {
38
+ current = getTransformationFrom(current.typeParameters[0])
39
+ }
40
+
41
+ return current
42
+ }
43
+
44
+ export const isNullableOrUndefined = (property: false | S.AST.AST | undefined) => {
45
+ if (!property || !S.AST.isUnion(property)) return false
46
+ if (property.types.find((_) => S.AST.isUndefined(_))) {
47
+ return "undefined"
48
+ }
49
+ if (property.types.find((_) => S.AST.isNull(_))) return "null"
50
+ return false
51
+ }
52
+
53
+ export const createMeta = <T = any>(
54
+ { meta = {}, parent = "", property, propertySignatures }: CreateMeta,
55
+ acc: Partial<MetaRecord<T>> = {}
56
+ ): MetaRecord<T> | FieldMeta => {
57
+ const ctx: WalkerContext<T> = { acc, unionMeta: {} }
58
+
59
+ if (propertySignatures) {
60
+ const parentMeta: ParentMeta = {
61
+ required: meta.required !== false,
62
+ nullableOrUndefined: meta.nullableOrUndefined ?? false
63
+ }
64
+ walkStruct(propertySignatures, parent, parentMeta, ctx)
65
+ return acc
66
+ }
67
+
68
+ if (property) {
69
+ const nullableOrUndefined = isNullableOrUndefined(property)
70
+ const unwrapped = unwrapDeclaration(property)
71
+ const required = !Object.hasOwnProperty.call(meta, "required")
72
+ ? !nullableOrUndefined
73
+ : (meta.required as boolean)
74
+
75
+ const parentMeta: ParentMeta = {
76
+ required,
77
+ nullableOrUndefined: (meta.nullableOrUndefined ?? nullableOrUndefined) as false | "null" | "undefined"
78
+ }
79
+
80
+ if (S.AST.isObjects(unwrapped)) {
81
+ walkStruct(unwrapped.propertySignatures, parent, parentMeta, ctx)
82
+ return acc
83
+ }
84
+
85
+ if (S.AST.isUnion(unwrapped)) {
86
+ // For property-mode, return a FieldMeta by running through classifyAndWalkUnion
87
+ // and then pulling out the result at `parent` key
88
+ const leafCtx: WalkerContext<T> = { acc: {}, unionMeta: {} }
89
+ classifyAndWalkUnion(unwrapped, parent, parentMeta, leafCtx)
90
+ const result = (leafCtx.acc as any)[parent]
91
+ if (result) return result as FieldMeta
92
+ }
93
+
94
+ return leafMetaForAst(unwrapped, parentMeta)
95
+ }
96
+
97
+ return acc
98
+ }
99
+
100
+ export const metadataFromAst = <From, To>(
101
+ schema: S.Codec<To, From>
102
+ ): {
103
+ meta: MetaRecord<To>
104
+ defaultValues: Record<string, any>
105
+ unionMeta: Record<string, MetaRecord<To>>
106
+ } => {
107
+ const ast = unwrapDeclaration(schema.ast)
108
+ const newMeta: Partial<MetaRecord<To>> = {}
109
+ const defaultValues: Record<string, any> = {}
110
+ const unionMeta: Record<string, MetaRecord<To>> = {}
111
+
112
+ const ctx: WalkerContext<To> = { acc: newMeta, unionMeta }
113
+
114
+ if (S.AST.isUnion(ast)) {
115
+ // Root-level discriminated union
116
+ classifyAndWalkUnion(ast, "", { required: true, nullableOrUndefined: false }, ctx)
117
+
118
+ return { meta: newMeta as MetaRecord<To>, defaultValues, unionMeta }
119
+ }
120
+
121
+ if (S.AST.isObjects(ast)) {
122
+ walkStruct(ast.propertySignatures, "", { required: true, nullableOrUndefined: false }, ctx)
123
+
124
+ return { meta: newMeta as MetaRecord<To>, defaultValues, unionMeta }
125
+ }
126
+
127
+ return { meta: newMeta as MetaRecord<To>, defaultValues, unionMeta }
128
+ }
129
+
130
+ export const generateMetaFromSchema = <From, To>(
131
+ schema: S.Codec<To, From>
132
+ ): {
133
+ schema: S.Codec<To, From>
134
+ meta: MetaRecord<To>
135
+ unionMeta: Record<string, MetaRecord<To>>
136
+ } => {
137
+ const { meta, unionMeta } = metadataFromAst(schema)
138
+
139
+ return { schema, meta, unionMeta }
140
+ }
@@ -0,0 +1,134 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import * as Effect from "effect-app/Effect"
3
+ import * as Option from "effect-app/Option"
4
+ import * as S from "effect-app/Schema"
5
+ import { isNullableOrUndefined, unwrapDeclaration } from "./createMeta"
6
+
7
+ const extractDefaultFromLink = (link: any): unknown | undefined => {
8
+ if (!link?.transformation?.decode?.run) return undefined
9
+ try {
10
+ const result = Effect.runSync(link.transformation.decode.run(Option.none())) as Option.Option<unknown>
11
+ return Option.isSome(result) ? result.value : undefined
12
+ } catch {
13
+ return undefined
14
+ }
15
+ }
16
+
17
+ const getDefaultFromAst = (property: S.AST.AST) => {
18
+ // 1. Check withConstructorDefault (stored in context.defaultValue)
19
+ const constructorLink = property.context?.defaultValue?.[0]
20
+ const constructorDefault = extractDefaultFromLink(constructorLink)
21
+ if (constructorDefault !== undefined) return constructorDefault
22
+
23
+ // 2. Check withDecodingDefault (stored in encoding)
24
+ const encodingLink = property.encoding?.[0]
25
+ if (encodingLink && property.context?.isOptional) {
26
+ return extractDefaultFromLink(encodingLink)
27
+ }
28
+
29
+ return undefined
30
+ }
31
+
32
+ type SchemaWithMembers = {
33
+ members: readonly S.Schema<any>[]
34
+ }
35
+
36
+ function hasMembers(schema: any): schema is SchemaWithMembers {
37
+ return schema && "members" in schema && Array.isArray(schema.members)
38
+ }
39
+
40
+ // Internal implementation with WeakSet tracking
41
+ export const defaultsValueFromSchema = (
42
+ schema: S.Schema<any>,
43
+ record: Record<string, any> = {}
44
+ ): any => {
45
+ const ast = schema.ast
46
+ const defaultValue = getDefaultFromAst(ast)
47
+
48
+ if (defaultValue !== undefined) {
49
+ return defaultValue
50
+ }
51
+
52
+ if (isNullableOrUndefined(schema.ast) === "null") {
53
+ return null
54
+ }
55
+ if (isNullableOrUndefined(schema.ast) === "undefined") {
56
+ return undefined
57
+ }
58
+
59
+ // Handle structs via AST (covers plain structs, transformed schemas like decodeTo, Class, etc.)
60
+ const objectsAst = S.AST.isObjects(ast)
61
+ ? ast
62
+ : S.AST.isDeclaration(ast)
63
+ ? unwrapDeclaration(ast)
64
+ : undefined
65
+ if (objectsAst && S.AST.isObjects(objectsAst)) {
66
+ const result: Record<string, any> = {}
67
+
68
+ for (const prop of objectsAst.propertySignatures) {
69
+ const key = prop.name.toString()
70
+ const propType = prop.type
71
+
72
+ const propDefault = getDefaultFromAst(propType)
73
+ if (propDefault !== undefined) {
74
+ result[key] = propDefault
75
+ continue
76
+ }
77
+
78
+ const propSchema = S.make(propType)
79
+ const propValue = defaultsValueFromSchema(propSchema, record[key] || {})
80
+
81
+ if (propValue !== undefined) {
82
+ result[key] = propValue
83
+ } else if (isNullableOrUndefined(propType) === "undefined") {
84
+ result[key] = undefined
85
+ }
86
+ }
87
+
88
+ return { ...result, ...record }
89
+ }
90
+
91
+ // Handle unions via AST or schema-level .members
92
+ const unionTypes = S.AST.isUnion(ast)
93
+ ? ast.types
94
+ : hasMembers(schema)
95
+ ? schema.members.map((m) => m.ast)
96
+ : undefined
97
+ if (unionTypes) {
98
+ const mergedFields: Record<string, { ast: S.AST.AST }> = {}
99
+
100
+ for (const memberAstRaw of unionTypes) {
101
+ const memberAst = unwrapDeclaration(memberAstRaw)
102
+ if (!S.AST.isObjects(memberAst)) continue
103
+
104
+ for (const prop of memberAst.propertySignatures) {
105
+ const key = prop.name.toString()
106
+ const fieldDefault = getDefaultFromAst(prop.type)
107
+ const existingDefault = mergedFields[key] ? getDefaultFromAst(mergedFields[key].ast) : undefined
108
+
109
+ if (!mergedFields[key] || (fieldDefault !== undefined && existingDefault === undefined)) {
110
+ mergedFields[key] = { ast: prop.type }
111
+ }
112
+ }
113
+ }
114
+
115
+ if (Object.keys(mergedFields).length === 0) {
116
+ return Object.keys(record).length > 0 ? record : undefined
117
+ }
118
+
119
+ return Object.entries(mergedFields).reduce((acc, [key, { ast: propAst }]) => {
120
+ acc[key] = defaultsValueFromSchema(S.make(propAst), record[key] || {})
121
+ return acc
122
+ }, record)
123
+ }
124
+
125
+ if (Object.keys(record).length === 0) {
126
+ if (S.AST.isString(ast)) {
127
+ return ""
128
+ }
129
+
130
+ if (S.AST.isBoolean(ast)) {
131
+ return false
132
+ }
133
+ }
134
+ }