@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.
- package/Designer.d.ts +89 -0
- package/FormSpec.TS/Components/HelloComponent.js +68 -0
- package/FormSpec.TS/Components/HelloComponent.js.map +1 -0
- package/FormSpec.TS/Components/HelloComponent.ts.map +1 -0
- package/FormSpec.TS/Designer.js +526 -0
- package/FormSpec.TS/Designer.js.map +1 -0
- package/FormSpec.TS/Designer.ts.map +1 -0
- package/FormSpec.TS/FormSpec.js +5400 -0
- package/FormSpec.TS/FormSpec.js.map +1 -0
- package/FormSpec.TS/FormSpec.ts.map +1 -0
- package/FormSpec.TS/FormSpecHelpers.js +382 -0
- package/FormSpec.TS/FormSpecHelpers.js.map +1 -0
- package/FormSpec.TS/FormSpecHelpers.ts.map +1 -0
- package/FormSpec.TS/Helpers.js +732 -0
- package/FormSpec.TS/Helpers.js.map +1 -0
- package/FormSpec.TS/Helpers.ts.map +1 -0
- package/FormSpec.TS/Interfaces.js +257 -0
- package/FormSpec.TS/Interfaces.js.map +1 -0
- package/FormSpec.TS/Interfaces.ts.map +1 -0
- package/FormSpec.TS/Interop/FormSpec.Api.Helpers.js +854 -0
- package/FormSpec.TS/Interop/FormSpec.Api.Helpers.js.map +1 -0
- package/FormSpec.TS/Interop/FormSpec.Api.Helpers.ts.map +1 -0
- package/FormSpec.TS/Interop/FormSpec.Api.Option.js +1961 -0
- package/FormSpec.TS/Interop/FormSpec.Api.Option.js.map +1 -0
- package/FormSpec.TS/Interop/FormSpec.Api.Option.ts.map +1 -0
- package/FormSpec.TS/Interop/FormSpec.Values.Api.Option.js +1367 -0
- package/FormSpec.TS/Interop/FormSpec.Values.Api.Option.js.map +1 -0
- package/FormSpec.TS/Interop/FormSpec.Values.Api.Option.ts.map +1 -0
- package/FormSpec.TS/Logging/LogTypes.js +347 -0
- package/FormSpec.TS/Logging/LogTypes.js.map +1 -0
- package/FormSpec.TS/Logging/LogTypes.ts.map +1 -0
- package/FormSpec.TS/Migrator.js +230 -0
- package/FormSpec.TS/Migrator.js.map +1 -0
- package/FormSpec.TS/Migrator.ts.map +1 -0
- package/FormSpec.TS/PathwayDataExtractor.js +361 -0
- package/FormSpec.TS/PathwayDataExtractor.js.map +1 -0
- package/FormSpec.TS/PathwayDataExtractor.ts.map +1 -0
- package/FormSpec.TS/PathwayExecutor.js +1321 -0
- package/FormSpec.TS/PathwayExecutor.js.map +1 -0
- package/FormSpec.TS/PathwayExecutor.ts.map +1 -0
- package/FormSpec.TS/PathwayValidator.js +346 -0
- package/FormSpec.TS/PathwayValidator.js.map +1 -0
- package/FormSpec.TS/PathwayValidator.ts.map +1 -0
- package/FormSpec.TS/PluginInterface.js +171 -0
- package/FormSpec.TS/PluginInterface.js.map +1 -0
- package/FormSpec.TS/PluginInterface.ts.map +1 -0
- package/FormSpec.TS/Prelude.js +59 -0
- package/FormSpec.TS/Prelude.js.map +1 -0
- package/FormSpec.TS/Prelude.ts.map +1 -0
- package/FormSpec.TS/Renderers/FormSpecMarkdownRenderer.js +958 -0
- package/FormSpec.TS/Renderers/FormSpecMarkdownRenderer.js.map +1 -0
- package/FormSpec.TS/Renderers/FormSpecMarkdownRenderer.ts.map +1 -0
- package/FormSpec.TS/Renderers/MermaidRenderer.js +228 -0
- package/FormSpec.TS/Renderers/MermaidRenderer.js.map +1 -0
- package/FormSpec.TS/Renderers/MermaidRenderer.ts.map +1 -0
- package/FormSpec.TS/Renderers/PathwayRenderers.js +190 -0
- package/FormSpec.TS/Renderers/PathwayRenderers.js.map +1 -0
- package/FormSpec.TS/Renderers/PathwayRenderers.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Base.fs +511 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Base.fs.js +437 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Base.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Base.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Error.fs +16 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Error.fs.js +73 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Error.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Error.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Extensions.fs +50 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Extensions.fs.js +72 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Extensions.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Extensions.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Fable.Form.fableproj +28 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Field.fs +24 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Field.fs.js +56 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Field.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.Form.3.0.0/Field.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Fable.Form.Simple.fableproj +31 -0
- package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Form.fs +178 -0
- package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Form.fs.js +464 -0
- package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Form.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.Form.Simple.5.0.1/Form.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Extensions.fs +17 -0
- package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Hooks.fs +152 -0
- package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Hooks.fs.js +25 -0
- package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Hooks.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Hooks.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.Types.fableproj +28 -0
- package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.fs +218 -0
- package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.fs.js +37 -0
- package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.React.Types.18.3.0/Fable.React.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.Types.fableproj +27 -0
- package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.fs +82 -0
- package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.fs.js +7 -0
- package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Fable.ReactDom.Types.18.2.0/Fable.ReactDom.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/BorderStyle.fs +59 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Colors.fs +154 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Colors.fs.js +32 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Colors.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Colors.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Feliz.fableproj +42 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Fonts.fs +240 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/GridTypes.fs +24 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Html.fs +826 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Interop.fs +83 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Interop.fs.js +292 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Interop.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Interop.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Key.fs +65 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Key.fs.js +229 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Key.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Key.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Length.fs +91 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Locale.fs +876 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Properties.fs +4080 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Properties.fs.js +133 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Properties.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Properties.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/React.fs +656 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/React.fs.js +561 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/React.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/React.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactDOM.fs +25 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactDOM.fs.js +46 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactDOM.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactDOM.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactInterop.js +63 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactInterop.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactTypes.fs +41 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactTypes.fs.js +7 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactTypes.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/ReactTypes.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/StyleTypes.fs +53 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/StyleTypes.fs.js +7 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/StyleTypes.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/StyleTypes.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Styles.fs +5740 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Svg.fs +1455 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Svg.fs.js +39 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Svg.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Svg.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/TextDecorationLine.fs +13 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/TextDecorationStyle.fs +33 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Transform.fs +181 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/TransformOrigin.fs +17 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/TransitionProperty.fs +162 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Types.fs +13 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Types.fs.js +7 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Types.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Feliz.2.7.0/Types.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Decode.fs +1768 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Decode.fs.js +2337 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Decode.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Decode.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Encode.fs +811 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Encode.fs.js +465 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Encode.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Encode.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Extra.fs +47 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Extra.fs.js +18 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Extra.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Extra.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Thoth.Json.fableproj +34 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Types.fs +68 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Types.fs.js +355 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Types.fs.js.map +1 -0
- package/FormSpec.TS/fable_modules/Thoth.Json.10.4.1/Types.fs.ts.map +1 -0
- package/FormSpec.TS/fable_modules/project_cracked.json +1 -0
- package/FormSpec.d.ts +1257 -0
- package/FormSpecHelpers.d.ts +50 -0
- package/Helpers.d.ts +147 -0
- package/Interfaces.d.ts +70 -0
- package/Interop/FormSpec.Api.Helpers.d.ts +247 -0
- package/Interop/FormSpec.Api.Helpers.d.ts.map +1 -0
- package/Interop/FormSpec.Api.Option.d.ts +384 -0
- package/Interop/FormSpec.Api.Option.d.ts.map +1 -0
- package/Interop/FormSpec.Values.Api.Option.d.ts +324 -0
- package/Interop/FormSpec.Values.Api.Option.d.ts.map +1 -0
- package/Migrator.d.ts +59 -0
- package/PathwayDataExtractor.d.ts +19 -0
- package/PathwayExecutor.d.ts +210 -0
- package/PathwayValidator.d.ts +52 -0
- package/PluginInterface.d.ts +36 -0
- package/Prelude.d.ts +11 -0
- package/README.TS.md +622 -0
- package/README.md +85 -0
- package/package.json +39 -0
- package/src/Components/HelloComponent.ts +48 -0
- package/src/Components/HelloComponent.ts.map +1 -0
- package/src/Designer.ts +389 -0
- package/src/Designer.ts.map +1 -0
- package/src/FormSpec.ts +3114 -0
- package/src/FormSpec.ts.map +1 -0
- package/src/FormSpecHelpers.ts +374 -0
- package/src/FormSpecHelpers.ts.map +1 -0
- package/src/Helpers.ts +765 -0
- package/src/Helpers.ts.map +1 -0
- package/src/Interfaces.ts +166 -0
- package/src/Interfaces.ts.map +1 -0
- package/src/Interop/FormSpec.Api.Helpers.ts +872 -0
- package/src/Interop/FormSpec.Api.Helpers.ts.map +1 -0
- package/src/Interop/FormSpec.Api.Option.ts +1618 -0
- package/src/Interop/FormSpec.Api.Option.ts.map +1 -0
- package/src/Interop/FormSpec.Values.Api.Option.ts +1214 -0
- package/src/Interop/FormSpec.Values.Api.Option.ts.map +1 -0
- package/src/Logging/LogTypes.ts +212 -0
- package/src/Logging/LogTypes.ts.map +1 -0
- package/src/Migrator.ts +156 -0
- package/src/Migrator.ts.map +1 -0
- package/src/PathwayDataExtractor.ts +290 -0
- package/src/PathwayDataExtractor.ts.map +1 -0
- package/src/PathwayExecutor.ts +1102 -0
- package/src/PathwayExecutor.ts.map +1 -0
- package/src/PathwayValidator.ts +244 -0
- package/src/PathwayValidator.ts.map +1 -0
- package/src/PluginInterface.ts +79 -0
- package/src/PluginInterface.ts.map +1 -0
- package/src/Prelude.ts +21 -0
- package/src/Prelude.ts.map +1 -0
- package/src/Renderers/FormSpecMarkdownRenderer.ts +874 -0
- package/src/Renderers/FormSpecMarkdownRenderer.ts.map +1 -0
- package/src/Renderers/MermaidRenderer.ts +218 -0
- package/src/Renderers/MermaidRenderer.ts.map +1 -0
- package/src/Renderers/PathwayRenderers.ts +200 -0
- 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
|
+
)
|