@f1studio/form-spec 5.0.0-alpha.101

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 (225) hide show
  1. package/Designer.d.ts +89 -0
  2. package/FormSpec.TS/Components/HelloComponent.js +68 -0
  3. package/FormSpec.TS/Components/HelloComponent.js.map +1 -0
  4. package/FormSpec.TS/Components/HelloComponent.ts.map +1 -0
  5. package/FormSpec.TS/Designer.js +526 -0
  6. package/FormSpec.TS/Designer.js.map +1 -0
  7. package/FormSpec.TS/Designer.ts.map +1 -0
  8. package/FormSpec.TS/FormSpec.js +5400 -0
  9. package/FormSpec.TS/FormSpec.js.map +1 -0
  10. package/FormSpec.TS/FormSpec.ts.map +1 -0
  11. package/FormSpec.TS/FormSpecHelpers.js +382 -0
  12. package/FormSpec.TS/FormSpecHelpers.js.map +1 -0
  13. package/FormSpec.TS/FormSpecHelpers.ts.map +1 -0
  14. package/FormSpec.TS/Helpers.js +732 -0
  15. package/FormSpec.TS/Helpers.js.map +1 -0
  16. package/FormSpec.TS/Helpers.ts.map +1 -0
  17. package/FormSpec.TS/Interfaces.js +257 -0
  18. package/FormSpec.TS/Interfaces.js.map +1 -0
  19. package/FormSpec.TS/Interfaces.ts.map +1 -0
  20. package/FormSpec.TS/Interop/FormSpec.Api.Helpers.js +854 -0
  21. package/FormSpec.TS/Interop/FormSpec.Api.Helpers.js.map +1 -0
  22. package/FormSpec.TS/Interop/FormSpec.Api.Helpers.ts.map +1 -0
  23. package/FormSpec.TS/Interop/FormSpec.Api.Option.js +1961 -0
  24. package/FormSpec.TS/Interop/FormSpec.Api.Option.js.map +1 -0
  25. package/FormSpec.TS/Interop/FormSpec.Api.Option.ts.map +1 -0
  26. package/FormSpec.TS/Interop/FormSpec.Values.Api.Option.js +1367 -0
  27. package/FormSpec.TS/Interop/FormSpec.Values.Api.Option.js.map +1 -0
  28. package/FormSpec.TS/Interop/FormSpec.Values.Api.Option.ts.map +1 -0
  29. package/FormSpec.TS/Logging/LogTypes.js +347 -0
  30. package/FormSpec.TS/Logging/LogTypes.js.map +1 -0
  31. package/FormSpec.TS/Logging/LogTypes.ts.map +1 -0
  32. package/FormSpec.TS/Migrator.js +230 -0
  33. package/FormSpec.TS/Migrator.js.map +1 -0
  34. package/FormSpec.TS/Migrator.ts.map +1 -0
  35. package/FormSpec.TS/PathwayDataExtractor.js +361 -0
  36. package/FormSpec.TS/PathwayDataExtractor.js.map +1 -0
  37. package/FormSpec.TS/PathwayDataExtractor.ts.map +1 -0
  38. package/FormSpec.TS/PathwayExecutor.js +1321 -0
  39. package/FormSpec.TS/PathwayExecutor.js.map +1 -0
  40. package/FormSpec.TS/PathwayExecutor.ts.map +1 -0
  41. package/FormSpec.TS/PathwayValidator.js +346 -0
  42. package/FormSpec.TS/PathwayValidator.js.map +1 -0
  43. package/FormSpec.TS/PathwayValidator.ts.map +1 -0
  44. package/FormSpec.TS/PluginInterface.js +171 -0
  45. package/FormSpec.TS/PluginInterface.js.map +1 -0
  46. package/FormSpec.TS/PluginInterface.ts.map +1 -0
  47. package/FormSpec.TS/Prelude.js +59 -0
  48. package/FormSpec.TS/Prelude.js.map +1 -0
  49. package/FormSpec.TS/Prelude.ts.map +1 -0
  50. package/FormSpec.TS/Renderers/FormSpecMarkdownRenderer.js +958 -0
  51. package/FormSpec.TS/Renderers/FormSpecMarkdownRenderer.js.map +1 -0
  52. package/FormSpec.TS/Renderers/FormSpecMarkdownRenderer.ts.map +1 -0
  53. package/FormSpec.TS/Renderers/MermaidRenderer.js +228 -0
  54. package/FormSpec.TS/Renderers/MermaidRenderer.js.map +1 -0
  55. package/FormSpec.TS/Renderers/MermaidRenderer.ts.map +1 -0
  56. package/FormSpec.TS/Renderers/PathwayRenderers.js +190 -0
  57. package/FormSpec.TS/Renderers/PathwayRenderers.js.map +1 -0
  58. package/FormSpec.TS/Renderers/PathwayRenderers.ts.map +1 -0
  59. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Base.fs +511 -0
  60. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Base.fs.js +437 -0
  61. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Base.fs.js.map +1 -0
  62. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Base.fs.ts.map +1 -0
  63. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Error.fs +16 -0
  64. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Error.fs.js +73 -0
  65. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Error.fs.js.map +1 -0
  66. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Error.fs.ts.map +1 -0
  67. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Extensions.fs +50 -0
  68. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Extensions.fs.js +72 -0
  69. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Extensions.fs.js.map +1 -0
  70. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Extensions.fs.ts.map +1 -0
  71. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Fable.Form.fableproj +28 -0
  72. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Field.fs +24 -0
  73. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Field.fs.js +56 -0
  74. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Field.fs.js.map +1 -0
  75. package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Field.fs.ts.map +1 -0
  76. package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Fable.Form.Simple.fableproj +31 -0
  77. package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Form.fs +178 -0
  78. package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Form.fs.js +464 -0
  79. package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Form.fs.js.map +1 -0
  80. package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Form.fs.ts.map +1 -0
  81. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Extensions.fs +17 -0
  82. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Hooks.fs +152 -0
  83. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Hooks.fs.js +25 -0
  84. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Hooks.fs.js.map +1 -0
  85. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Hooks.fs.ts.map +1 -0
  86. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Types.fableproj +28 -0
  87. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.fs +218 -0
  88. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.fs.js +37 -0
  89. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.fs.js.map +1 -0
  90. package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.fs.ts.map +1 -0
  91. package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.Types.fableproj +27 -0
  92. package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.fs +82 -0
  93. package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.fs.js +7 -0
  94. package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.fs.js.map +1 -0
  95. package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.fs.ts.map +1 -0
  96. package/FormSpec.TS/fable_modules/Feliz.2.7.0/BorderStyle.fs +59 -0
  97. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Colors.fs +154 -0
  98. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Colors.fs.js +32 -0
  99. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Colors.fs.js.map +1 -0
  100. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Colors.fs.ts.map +1 -0
  101. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Feliz.fableproj +42 -0
  102. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Fonts.fs +240 -0
  103. package/FormSpec.TS/fable_modules/Feliz.2.7.0/GridTypes.fs +24 -0
  104. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Html.fs +826 -0
  105. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Interop.fs +83 -0
  106. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Interop.fs.js +292 -0
  107. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Interop.fs.js.map +1 -0
  108. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Interop.fs.ts.map +1 -0
  109. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Key.fs +65 -0
  110. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Key.fs.js +229 -0
  111. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Key.fs.js.map +1 -0
  112. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Key.fs.ts.map +1 -0
  113. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Length.fs +91 -0
  114. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Locale.fs +876 -0
  115. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Properties.fs +4080 -0
  116. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Properties.fs.js +133 -0
  117. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Properties.fs.js.map +1 -0
  118. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Properties.fs.ts.map +1 -0
  119. package/FormSpec.TS/fable_modules/Feliz.2.7.0/React.fs +656 -0
  120. package/FormSpec.TS/fable_modules/Feliz.2.7.0/React.fs.js +561 -0
  121. package/FormSpec.TS/fable_modules/Feliz.2.7.0/React.fs.js.map +1 -0
  122. package/FormSpec.TS/fable_modules/Feliz.2.7.0/React.fs.ts.map +1 -0
  123. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactDOM.fs +25 -0
  124. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactDOM.fs.js +46 -0
  125. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactDOM.fs.js.map +1 -0
  126. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactDOM.fs.ts.map +1 -0
  127. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactInterop.js +63 -0
  128. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactInterop.js.map +1 -0
  129. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactTypes.fs +41 -0
  130. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactTypes.fs.js +7 -0
  131. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactTypes.fs.js.map +1 -0
  132. package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactTypes.fs.ts.map +1 -0
  133. package/FormSpec.TS/fable_modules/Feliz.2.7.0/StyleTypes.fs +53 -0
  134. package/FormSpec.TS/fable_modules/Feliz.2.7.0/StyleTypes.fs.js +7 -0
  135. package/FormSpec.TS/fable_modules/Feliz.2.7.0/StyleTypes.fs.js.map +1 -0
  136. package/FormSpec.TS/fable_modules/Feliz.2.7.0/StyleTypes.fs.ts.map +1 -0
  137. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Styles.fs +5740 -0
  138. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Svg.fs +1455 -0
  139. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Svg.fs.js +39 -0
  140. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Svg.fs.js.map +1 -0
  141. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Svg.fs.ts.map +1 -0
  142. package/FormSpec.TS/fable_modules/Feliz.2.7.0/TextDecorationLine.fs +13 -0
  143. package/FormSpec.TS/fable_modules/Feliz.2.7.0/TextDecorationStyle.fs +33 -0
  144. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Transform.fs +181 -0
  145. package/FormSpec.TS/fable_modules/Feliz.2.7.0/TransformOrigin.fs +17 -0
  146. package/FormSpec.TS/fable_modules/Feliz.2.7.0/TransitionProperty.fs +162 -0
  147. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Types.fs +13 -0
  148. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Types.fs.js +7 -0
  149. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Types.fs.js.map +1 -0
  150. package/FormSpec.TS/fable_modules/Feliz.2.7.0/Types.fs.ts.map +1 -0
  151. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Decode.fs +1768 -0
  152. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Decode.fs.js +2337 -0
  153. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Decode.fs.js.map +1 -0
  154. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Decode.fs.ts.map +1 -0
  155. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Encode.fs +811 -0
  156. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Encode.fs.js +465 -0
  157. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Encode.fs.js.map +1 -0
  158. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Encode.fs.ts.map +1 -0
  159. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Extra.fs +47 -0
  160. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Extra.fs.js +18 -0
  161. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Extra.fs.js.map +1 -0
  162. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Extra.fs.ts.map +1 -0
  163. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Thoth.Json.fableproj +34 -0
  164. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Types.fs +68 -0
  165. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Types.fs.js +355 -0
  166. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Types.fs.js.map +1 -0
  167. package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Types.fs.ts.map +1 -0
  168. package/FormSpec.TS/fable_modules/project_cracked.json +1 -0
  169. package/FormSpec.d.ts +1257 -0
  170. package/FormSpecHelpers.d.ts +50 -0
  171. package/Helpers.d.ts +147 -0
  172. package/Interfaces.d.ts +70 -0
  173. package/Interop/FormSpec.Api.Helpers.d.ts +247 -0
  174. package/Interop/FormSpec.Api.Helpers.d.ts.map +1 -0
  175. package/Interop/FormSpec.Api.Option.d.ts +384 -0
  176. package/Interop/FormSpec.Api.Option.d.ts.map +1 -0
  177. package/Interop/FormSpec.Values.Api.Option.d.ts +324 -0
  178. package/Interop/FormSpec.Values.Api.Option.d.ts.map +1 -0
  179. package/Migrator.d.ts +59 -0
  180. package/PathwayDataExtractor.d.ts +19 -0
  181. package/PathwayExecutor.d.ts +210 -0
  182. package/PathwayValidator.d.ts +52 -0
  183. package/PluginInterface.d.ts +36 -0
  184. package/Prelude.d.ts +11 -0
  185. package/README.TS.md +622 -0
  186. package/README.md +85 -0
  187. package/package.json +39 -0
  188. package/src/Components/HelloComponent.ts +48 -0
  189. package/src/Components/HelloComponent.ts.map +1 -0
  190. package/src/Designer.ts +389 -0
  191. package/src/Designer.ts.map +1 -0
  192. package/src/FormSpec.ts +3114 -0
  193. package/src/FormSpec.ts.map +1 -0
  194. package/src/FormSpecHelpers.ts +374 -0
  195. package/src/FormSpecHelpers.ts.map +1 -0
  196. package/src/Helpers.ts +765 -0
  197. package/src/Helpers.ts.map +1 -0
  198. package/src/Interfaces.ts +166 -0
  199. package/src/Interfaces.ts.map +1 -0
  200. package/src/Interop/FormSpec.Api.Helpers.ts +872 -0
  201. package/src/Interop/FormSpec.Api.Helpers.ts.map +1 -0
  202. package/src/Interop/FormSpec.Api.Option.ts +1618 -0
  203. package/src/Interop/FormSpec.Api.Option.ts.map +1 -0
  204. package/src/Interop/FormSpec.Values.Api.Option.ts +1214 -0
  205. package/src/Interop/FormSpec.Values.Api.Option.ts.map +1 -0
  206. package/src/Logging/LogTypes.ts +212 -0
  207. package/src/Logging/LogTypes.ts.map +1 -0
  208. package/src/Migrator.ts +156 -0
  209. package/src/Migrator.ts.map +1 -0
  210. package/src/PathwayDataExtractor.ts +290 -0
  211. package/src/PathwayDataExtractor.ts.map +1 -0
  212. package/src/PathwayExecutor.ts +1102 -0
  213. package/src/PathwayExecutor.ts.map +1 -0
  214. package/src/PathwayValidator.ts +244 -0
  215. package/src/PathwayValidator.ts.map +1 -0
  216. package/src/PluginInterface.ts +79 -0
  217. package/src/PluginInterface.ts.map +1 -0
  218. package/src/Prelude.ts +21 -0
  219. package/src/Prelude.ts.map +1 -0
  220. package/src/Renderers/FormSpecMarkdownRenderer.ts +874 -0
  221. package/src/Renderers/FormSpecMarkdownRenderer.ts.map +1 -0
  222. package/src/Renderers/MermaidRenderer.ts +218 -0
  223. package/src/Renderers/MermaidRenderer.ts.map +1 -0
  224. package/src/Renderers/PathwayRenderers.ts +200 -0
  225. package/src/Renderers/PathwayRenderers.ts.map +1 -0
@@ -0,0 +1,511 @@
1
+ module Fable.Form.Base
2
+
3
+ open Fable.Form.Extensions
4
+
5
+ /// <summary>
6
+ /// Represents a filled field
7
+ /// </summary>
8
+ type FilledField<'Field> =
9
+ {
10
+ State: 'Field
11
+ Error: Error.Error option
12
+ IsDisabled: bool
13
+ IsReadOnly: bool
14
+ }
15
+
16
+ /// <summary>
17
+ /// Represents a filled form
18
+ ///
19
+ /// You can obtain this by using <see cref="fill"/>
20
+ /// </summary>
21
+ type FilledForm<'Output, 'Field> =
22
+ {
23
+ Fields: FilledField<'Field> list
24
+ Result: Result<'Output, (Error.Error * Error.Error list)>
25
+ IsEmpty: bool
26
+ }
27
+
28
+ /// <summary>
29
+ /// A <see cref="T:Form"/> which can contain any type of 'field'
30
+ /// </summary>
31
+ [<NoComparison; NoEquality>]
32
+ type Form<'Values, 'Output, 'Field> = Form of ('Values -> FilledForm<'Output, 'Field>)
33
+
34
+ /// <summary>
35
+ /// <see cref="T:FieldConfig"/> is a contract allowing you to describe how a field will behave
36
+ /// </summary>
37
+ [<NoComparison; NoEquality>]
38
+ type FieldConfig<'Attributes, 'Input, 'Values, 'Output> =
39
+ {
40
+ /// <summary>
41
+ /// Function that valides the <c>'Input</c> value and produce an <c>Ok 'Ouput</c> on success or an <c>Error</c> describing the problem
42
+ /// </summary>
43
+ Parser: 'Input -> Result<'Output, string>
44
+ /// <summary>
45
+ /// Function which defined how to access the <c>'Input</c> from <c>'Value</c> type
46
+ /// </summary>
47
+ Value: 'Values -> 'Input
48
+ /// <summary>
49
+ /// Function which defined how the current form <c>'Values</c> should be update with the new <c>'Input</c>
50
+ /// </summary>
51
+ Update: 'Input -> 'Values -> 'Values
52
+ /// <summary>
53
+ /// Define how to obtain a potential external error. Useful when dealing with Server-side validation for example
54
+ /// </summary>
55
+ Error: 'Values -> string option
56
+ /// <summary>
57
+ /// Type used to represents data specific to the field. For example, you can use it to ask the user to provide a label and placeholder.
58
+ /// </summary>
59
+ Attributes: 'Attributes
60
+ }
61
+
62
+ /// <summary>
63
+ /// Represents a custom field on a form that has been filled with some values.
64
+ /// </summary>
65
+ type CustomField<'Output, 'Field> =
66
+ {
67
+ /// <summary>
68
+ /// The field
69
+ /// </summary>
70
+ State: 'Field
71
+ /// <summary>
72
+ /// The result of the field
73
+ /// </summary>
74
+ Result: Result<'Output, (Error.Error * Error.Error list)>
75
+ /// <summary>
76
+ /// Whether the field is empty or not.
77
+ ///
78
+ /// <para>
79
+ /// <c>True</c>, if it is empty
80
+ /// </para>
81
+ ///
82
+ /// <para>
83
+ /// <c/>False<c/>, otherwise
84
+ /// </para>
85
+ /// </summary>
86
+ IsEmpty: bool
87
+ }
88
+
89
+ /// <summary>
90
+ /// Create a form that always succeeds when filled.
91
+ ///
92
+ /// Note: You can choose to discard one of the function argument. The classic example for that is when dealing with a <c>repeatPasswordField</c>
93
+ ///
94
+ /// <para>
95
+ /// <code lang="fsharp">
96
+ /// Form.succeed (fun password _ -> password )
97
+ /// |> Form.append passwordField
98
+ /// |> Form.append repeatPasswordField
99
+ /// </code>
100
+ /// </para>
101
+ /// </summary>
102
+ /// <param name="output">The value to return when the form is filled</param>
103
+ /// <returns>The given <c>Output</c></returns>
104
+ let succeed (output: 'Output) : Form<'Values, 'Output, 'Field> =
105
+ Form(fun _ ->
106
+ {
107
+ Fields = []
108
+ Result = Ok output
109
+ IsEmpty = true
110
+ }
111
+ )
112
+
113
+ /// <summary>
114
+ /// Fill a form with some <c>'Values</c>
115
+ /// </summary>
116
+ /// <returns>
117
+ /// - A list of the fields of the form, with their errors
118
+ /// - The result of the filled form which can be:
119
+ /// - The correct <c>'Output</c>
120
+ /// - A non-empty list of validation errors
121
+ /// - Whether the form is empty or not
122
+ /// </returns>
123
+ let fill<'Values, 'Output, 'Field>
124
+ (Form form: Form<'Values, 'Output, 'Field>)
125
+ (values: 'Values)
126
+ : FilledForm<'Output, 'Field>
127
+ =
128
+ form values
129
+
130
+ /// <summary>
131
+ /// Create a custom field
132
+ /// </summary>
133
+ /// <param name="fillField">A function given some <c>'Values</c> that produce a <see cref="T:FilledField"/></param>
134
+ /// <returns>
135
+ /// A form build by applying <c>fillField</c> to a provided <c>'Values</c>
136
+ /// </returns>
137
+ let custom (fillField: 'Values -> CustomField<'Output, 'Field>) : Form<'Values, 'Output, 'Field> =
138
+ Form(fun values ->
139
+ let filled = fillField values
140
+
141
+ {
142
+ Fields =
143
+ [
144
+ {
145
+ State = filled.State
146
+ Error =
147
+ if filled.IsEmpty then
148
+ Some Error.RequiredFieldIsEmpty
149
+
150
+ else
151
+ match filled.Result with
152
+ | Ok _ -> None
153
+
154
+ | Error(firstError, _) -> Some firstError
155
+ IsDisabled = false
156
+ IsReadOnly = false
157
+ }
158
+ ]
159
+ Result = filled.Result
160
+ IsEmpty = filled.IsEmpty
161
+ }
162
+ )
163
+
164
+ /// <summary>
165
+ /// Build a form that depends on its own <c>'Values</c>
166
+ ///
167
+ /// This is useful when a field need to checks it's value against another field value.
168
+ ///
169
+ /// The classic example for using <c>meta</c> is when dealing with a repeat password field.
170
+ /// </summary>
171
+ /// <param name="fn">Function to apply to transform the form values</param>
172
+ /// <returns>A new form resulting of the application of <c>fn</c> when filling it</returns>
173
+ let meta (fn: 'Values -> Form<'Values, 'Output, 'Field>) : Form<'Values, 'Output, 'Field> =
174
+ Form(fun values -> fill (fn values) values)
175
+
176
+ /// <summary>
177
+ /// Transform the values of a form.
178
+ ///
179
+ /// This function is useful when you want to re-use existing form or nest them.
180
+ /// </summary>
181
+ /// <param name="fn">Function to apply transform the data</param>
182
+ /// <param name="form">The form to which we want to pass the result of the transformation</param>
183
+ /// <returns>
184
+ /// A new form resulting of <c>fn >> fill form</c>
185
+ /// </returns>
186
+ let mapValues (fn: 'A -> 'B) (form: Form<'B, 'Output, 'Field>) : Form<'A, 'Output, 'Field> =
187
+
188
+ Form(fn >> fill form)
189
+
190
+ /// <summary>
191
+ /// Apply the given function to all the field
192
+ /// </summary>
193
+ /// <param name="fn">Function to apply</param>
194
+ /// <param name="form">Form containing the list of fields to which we want to apply the function</param>
195
+ /// <returns>A new form, when <c>fn</c> has been apply to all the field of <c>form</c></returns>
196
+ let mapField (fn: 'A -> 'B) (form: Form<'Values, 'Output, 'A>) : Form<'Values, 'Output, 'B> =
197
+ Form(fun values ->
198
+ let filled = fill form values
199
+
200
+ {
201
+ Fields =
202
+ filled.Fields
203
+ |> List.map (fun filledField ->
204
+ {
205
+ State = fn filledField.State
206
+ Error = filledField.Error
207
+ IsDisabled = filledField.IsDisabled
208
+ IsReadOnly = filledField.IsReadOnly
209
+ }
210
+ )
211
+ Result = filled.Result
212
+ IsEmpty = filled.IsEmpty
213
+ }
214
+ )
215
+
216
+ /// <summary>
217
+ /// Append a form to another one while <b>capturing</b> the output of the first one
218
+ /// </summary>
219
+ /// <param name="newForm">Form to append</param>
220
+ /// <param name="currentForm">Form to append to</param>
221
+ /// <returns>A new form resulting in the combination of <c>newForm</c> and <c>currentForm</c></returns>
222
+ let append
223
+ (newForm: Form<'Values, 'A, 'Field>)
224
+ (currentForm: Form<'Values, 'A -> 'B, 'Field>)
225
+ : Form<'Values, 'B, 'Field>
226
+ =
227
+ Form(fun values ->
228
+ let filledNew = fill newForm values
229
+
230
+ let filledCurrent = fill currentForm values
231
+
232
+ let fields = filledCurrent.Fields @ filledNew.Fields
233
+
234
+ let isEmpty = filledCurrent.IsEmpty && filledNew.IsEmpty
235
+
236
+ match filledCurrent.Result with
237
+ | Ok fn ->
238
+ {
239
+ Fields = fields
240
+ Result = Result.map fn filledNew.Result
241
+ IsEmpty = isEmpty
242
+ }
243
+
244
+ | Error(firstError, otherErrors) ->
245
+ match filledNew.Result with
246
+ | Ok _ ->
247
+ {
248
+ Fields = fields
249
+ Result = Error(firstError, otherErrors)
250
+ IsEmpty = isEmpty
251
+ }
252
+
253
+ | Error(newFirstError, newOtherErrors) ->
254
+ {
255
+ Fields = fields
256
+ Result = Error(firstError, otherErrors @ (newFirstError :: newOtherErrors))
257
+ IsEmpty = isEmpty
258
+ }
259
+ )
260
+
261
+ /// <summary>
262
+ /// Fill a form <c>andThen</c> fill another one.
263
+ ///
264
+ /// This type of form is useful when some part of your form can dynamically change based on the value of another field.
265
+ /// </summary>
266
+ /// <param name="child">The child form</param>
267
+ /// <param name="parent">The parent form which is filled first</param>
268
+ /// <returns>A new form which is the result of filling the <c>parent</c> and then filling the <c>child</c> form</returns>
269
+ let andThen
270
+ (child: 'A -> Form<'Values, 'B, 'Field>)
271
+ (parent: Form<'Values, 'A, 'Field>)
272
+ : Form<'Values, 'B, 'Field>
273
+ =
274
+
275
+ Form(fun values ->
276
+ let filled = fill parent values
277
+
278
+ match filled.Result with
279
+ | Ok output ->
280
+ let childFilled = fill (child output) values
281
+
282
+ {
283
+ Fields = filled.Fields @ childFilled.Fields
284
+ Result = childFilled.Result
285
+ IsEmpty = filled.IsEmpty && childFilled.IsEmpty
286
+ }
287
+
288
+ | Error errors ->
289
+ {
290
+ Fields = filled.Fields
291
+ Result = Error errors
292
+ IsEmpty = filled.IsEmpty
293
+ }
294
+ )
295
+
296
+ /// <summary>
297
+ /// Disable a form
298
+ ///
299
+ /// You can combine this with meta to disable parts of a form based on its own values.
300
+ /// </summary>
301
+ /// <param name="form">The form to disable</param>
302
+ /// <returns>A new form which has been marked as disabled</returns>
303
+ let disable (form: Form<'Values, 'Output, 'Field>) : Form<'Values, 'Output, 'Field> =
304
+ Form(fun values ->
305
+ let filled = fill form values
306
+
307
+ {
308
+ Fields =
309
+ filled.Fields
310
+ |> List.map (fun filledField ->
311
+ { filledField with
312
+ IsDisabled = true
313
+ }
314
+ )
315
+ Result = filled.Result
316
+ IsEmpty = filled.IsEmpty
317
+ }
318
+ )
319
+
320
+ /// <summary>
321
+ /// Disable a form based on a condition
322
+ ///
323
+ /// You can combine this with meta to disable parts of a form based on its own values.
324
+ /// </summary>
325
+ /// <param name="condition">The condition to check</param>
326
+ /// <param name="form">The form to disable</param>
327
+ /// <returns>A new form which has been marked as disabled if the condition is <c>true</c></returns>
328
+ let disableIf
329
+ (condition: bool)
330
+ (form: Form<'Values, 'Output, 'Field>)
331
+ : Form<'Values, 'Output, 'Field>
332
+ =
333
+ if condition then
334
+ disable form
335
+ else
336
+ form
337
+
338
+ /// <summary>
339
+ /// Make a form read-only
340
+ ///
341
+ /// You can combine this with meta to make parts of a form read-only based on its own values.
342
+ /// </summary>
343
+ /// <param name="form">The form to make read-only</param>
344
+ /// <returns>A new form which has been marked as read-only</returns>
345
+ let readOnly (form: Form<'Values, 'Output, 'Field>) : Form<'Values, 'Output, 'Field> =
346
+ Form(fun values ->
347
+ let filled = fill form values
348
+
349
+ {
350
+ Fields =
351
+ filled.Fields
352
+ |> List.map (fun filledField ->
353
+ { filledField with
354
+ IsReadOnly = true
355
+ }
356
+ )
357
+ Result = filled.Result
358
+ IsEmpty = filled.IsEmpty
359
+ }
360
+ )
361
+
362
+ /// <summary>
363
+ /// Make a form read-only based on a condition
364
+ ///
365
+ /// You can combine this with meta to make parts of a form read-only based on its own values.
366
+ /// </summary>
367
+ /// <param name="condition">The condition to check</param>
368
+ /// <param name="form">The form to make read-only</param>
369
+ /// <returns>A new form which has been marked as read-only if the condition is <c>true</c></returns>
370
+ let readOnlyIf
371
+ (condition: bool)
372
+ (form: Form<'Values, 'Output, 'Field>)
373
+ : Form<'Values, 'Output, 'Field>
374
+ =
375
+ if condition then
376
+ readOnly form
377
+ else
378
+ form
379
+
380
+ /// <summary>
381
+ /// Transform the 'output' of a form
382
+ ///
383
+ /// You can use it to keep your forms decoupled from your specific view messages:
384
+ ///
385
+ /// <code lang="fsharp">
386
+ /// Base.map SignUp signupForm
387
+ /// </code>
388
+ /// </summary>
389
+ let map (fn: 'A -> 'B) (form: Form<'Values, 'A, 'Field>) : Form<'Values, 'B, 'Field> =
390
+
391
+ Form(fun values ->
392
+ let filled = fill form values
393
+
394
+ {
395
+ Fields = filled.Fields
396
+ Result = Result.map fn filled.Result
397
+ IsEmpty = filled.IsEmpty
398
+ }
399
+ )
400
+
401
+ /// <summary>
402
+ /// Create function which is used to created a single form field
403
+ ///
404
+ /// This functions is meant to be used when you want to design your own View layer.
405
+ ///
406
+ /// See how it is use for Fable.Form.Simple <a href="https://github.com/MangelMaxime/Fable.Form/blob/91c70b9504706fd3d65fd0bbcad97d865b18284a/packages/Fable.Form.Simple/TextField.fs#L15-L17">TextField</a>
407
+ /// </summary>
408
+ /// <param name="isEmpty">Function used to detect if the field is empty</param>
409
+ /// <param name="build">Field builder configuration</param>
410
+ /// <param name="config">Field configuration</param>
411
+ /// <returns>A form containing a single field</returns>
412
+ let field
413
+ (isEmpty: 'Input -> bool)
414
+ (build: Field.Field<'Attributes, 'Input, 'Values> -> 'Field)
415
+ (config: FieldConfig<'Attributes, 'Input, 'Values, 'Output>)
416
+ : Form<'Values, 'Output, 'Field>
417
+ =
418
+
419
+ let requiredParser value =
420
+ if isEmpty value then
421
+ Error(Error.RequiredFieldIsEmpty, [])
422
+ else
423
+ config.Parser value
424
+ |> Result.mapError (fun error -> (Error.ValidationFailed error, []))
425
+
426
+ let parse values =
427
+ requiredParser (config.Value values)
428
+ |> Result.andThen (fun output ->
429
+ config.Error values
430
+ |> Option.map (fun error -> Error(Error.External error, []))
431
+ |> Option.defaultValue (Ok output)
432
+ )
433
+
434
+ let field_ values =
435
+ let value = config.Value values
436
+
437
+ let update newValue = config.Update newValue values
438
+
439
+ build
440
+ {
441
+ Value = value
442
+ Update = update
443
+ Attributes = config.Attributes
444
+ }
445
+
446
+ Form(fun values ->
447
+ let result = parse values
448
+
449
+ let (error, isEmpty_) =
450
+ match result with
451
+ | Ok _ -> (None, false)
452
+
453
+ | Error(firstError, _) -> Some firstError, firstError = Error.RequiredFieldIsEmpty
454
+
455
+ {
456
+ Fields =
457
+ [
458
+ {
459
+ State = field_ values
460
+ Error = error
461
+ IsDisabled = false
462
+ IsReadOnly = false
463
+ }
464
+ ]
465
+ Result = result
466
+ IsEmpty = isEmpty_
467
+ }
468
+ )
469
+
470
+ /// <summary>
471
+ /// Make a form optional.
472
+ ///
473
+ /// An optional form succeeds when:
474
+ /// - All of its fields are empty, in this case it returns <c>None</c>
475
+ /// - All of its fields are correct, in this case it returns <c>Some 'Output</c>
476
+ /// </summary>
477
+ /// <param name="form">The form to make optional</param>
478
+ /// <returns>A form producing an optional 'Output</returns>
479
+ let optional (form: Form<'Values, 'Output, 'Field>) : Form<'Values, 'Output option, 'Field> =
480
+
481
+ Form(fun values ->
482
+ let filled = fill form values
483
+
484
+ match filled.Result with
485
+ | Ok value ->
486
+ {
487
+ Fields = filled.Fields
488
+ Result = Ok(Some value)
489
+ IsEmpty = filled.IsEmpty
490
+ }
491
+
492
+ | Error(firstError, otherErrors) ->
493
+ if filled.IsEmpty then
494
+ {
495
+ Fields =
496
+ filled.Fields
497
+ |> List.map (fun field ->
498
+ { field with
499
+ Error = None
500
+ }
501
+ )
502
+ Result = Ok None
503
+ IsEmpty = filled.IsEmpty
504
+ }
505
+ else
506
+ {
507
+ Fields = filled.Fields
508
+ Result = Error(firstError, otherErrors)
509
+ IsEmpty = false
510
+ }
511
+ )