ballerina-core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/main.ts +149 -0
- package/package.json +20 -0
- package/src/apiResultStatus/state.ts +7 -0
- package/src/async/domains/mirroring/domains/collection/coroutines/synchronizers.ts +334 -0
- package/src/async/domains/mirroring/domains/collection/state.ts +137 -0
- package/src/async/domains/mirroring/domains/entity/domains/loaded-collection/state.ts +24 -0
- package/src/async/domains/mirroring/domains/entity/domains/loaded-collection-entity/state.ts +27 -0
- package/src/async/domains/mirroring/domains/entity/domains/loaded-entities/state.ts +12 -0
- package/src/async/domains/mirroring/domains/entity/domains/loaded-entity/state.ts +29 -0
- package/src/async/domains/mirroring/domains/entity/state.ts +22 -0
- package/src/async/domains/mirroring/domains/singleton/coroutines/synchronizers.ts +216 -0
- package/src/async/domains/mirroring/domains/singleton/state.ts +57 -0
- package/src/async/domains/mirroring/domains/synchronization-result/state.ts +2 -0
- package/src/async/domains/mirroring/domains/synchronized-entities/state.ts +23 -0
- package/src/async/domains/promise/state.ts +13 -0
- package/src/async/domains/synchronized/coroutines/synchronize.ts +62 -0
- package/src/async/domains/synchronized/state.ts +20 -0
- package/src/async/state.ts +144 -0
- package/src/baseEntity/domains/identifiable/state.ts +29 -0
- package/src/collections/domains/array/state.ts +16 -0
- package/src/collections/domains/immutable/domains/list/state.ts +20 -0
- package/src/collections/domains/immutable/domains/map/state.ts +33 -0
- package/src/collections/domains/immutable/domains/orderedMap/state.ts +117 -0
- package/src/collections/domains/immutable/domains/ordereredSet/state.ts +19 -0
- package/src/collections/domains/immutable/domains/set/state.ts +15 -0
- package/src/collections/domains/maybe/state.ts +20 -0
- package/src/collections/domains/product/state.ts +47 -0
- package/src/collections/domains/sum/state.ts +82 -0
- package/src/coroutines/builder.tsx +66 -0
- package/src/coroutines/state.ts +574 -0
- package/src/coroutines/template.tsx +119 -0
- package/src/debounced/coroutines/debounce.ts +118 -0
- package/src/debounced/state.ts +61 -0
- package/src/diagnostics/domains/message-box/state.ts +4 -0
- package/src/foreignMutations/state.ts +4 -0
- package/src/forms/domains/attachments/views/attachments-view.tsx +22 -0
- package/src/forms/domains/collection/domains/reference/state.ts +18 -0
- package/src/forms/domains/collection/domains/selection/state.ts +5 -0
- package/src/forms/domains/launcher/domains/create/coroutines/runner.ts +60 -0
- package/src/forms/domains/launcher/domains/create/state.ts +71 -0
- package/src/forms/domains/launcher/domains/create/template.tsx +66 -0
- package/src/forms/domains/launcher/domains/edit/coroutines/runner.ts +47 -0
- package/src/forms/domains/launcher/domains/edit/state.ts +55 -0
- package/src/forms/domains/launcher/domains/edit/template.tsx +39 -0
- package/src/forms/domains/parser/domains/validator/state.ts +423 -0
- package/src/forms/domains/parser/state.tsx +311 -0
- package/src/forms/domains/primitives/domains/boolean/state.ts +13 -0
- package/src/forms/domains/primitives/domains/boolean/template.tsx +24 -0
- package/src/forms/domains/primitives/domains/date/state.ts +23 -0
- package/src/forms/domains/primitives/domains/date/template.tsx +31 -0
- package/src/forms/domains/primitives/domains/enum/state.ts +27 -0
- package/src/forms/domains/primitives/domains/enum/template.tsx +52 -0
- package/src/forms/domains/primitives/domains/enum-multiselect/state.ts +18 -0
- package/src/forms/domains/primitives/domains/enum-multiselect/template.tsx +56 -0
- package/src/forms/domains/primitives/domains/number/state.ts +8 -0
- package/src/forms/domains/primitives/domains/number/template.tsx +26 -0
- package/src/forms/domains/primitives/domains/searchable-infinite-stream/state.ts +55 -0
- package/src/forms/domains/primitives/domains/searchable-infinite-stream/template.tsx +114 -0
- package/src/forms/domains/primitives/domains/searchable-infinite-stream-multiselect/state.ts +27 -0
- package/src/forms/domains/primitives/domains/searchable-infinite-stream-multiselect/template.tsx +119 -0
- package/src/forms/domains/primitives/domains/string/state.ts +12 -0
- package/src/forms/domains/primitives/domains/string/template.tsx +24 -0
- package/src/forms/domains/singleton/domains/descriptors/entity/state.ts +9 -0
- package/src/forms/domains/singleton/domains/descriptors/field/domains/base/state.ts +5 -0
- package/src/forms/domains/singleton/domains/descriptors/field/domains/boolean/state.ts +6 -0
- package/src/forms/domains/singleton/domains/descriptors/field/domains/custom/state.ts +21 -0
- package/src/forms/domains/singleton/domains/descriptors/field/domains/date/state.ts +6 -0
- package/src/forms/domains/singleton/domains/descriptors/field/domains/enum/state.ts +7 -0
- package/src/forms/domains/singleton/domains/descriptors/field/domains/infinite-enum/state.ts +8 -0
- package/src/forms/domains/singleton/domains/descriptors/field/domains/number/state.ts +7 -0
- package/src/forms/domains/singleton/domains/descriptors/field/domains/string/state.ts +7 -0
- package/src/forms/domains/singleton/domains/descriptors/field/state.ts +16 -0
- package/src/forms/domains/singleton/domains/descriptors/form/state.ts +13 -0
- package/src/forms/domains/singleton/domains/form-label/state.ts +2 -0
- package/src/forms/domains/singleton/state.ts +87 -0
- package/src/forms/domains/singleton/template.tsx +92 -0
- package/src/forms/domains/singleton/views/field-views.ts +23 -0
- package/src/forms/domains/singleton/views/simple-inputs/base.ts +5 -0
- package/src/forms/domains/singleton/views/simple-inputs/boolean.tsx +4 -0
- package/src/forms/domains/singleton/views/simple-inputs/date.tsx +4 -0
- package/src/forms/domains/singleton/views/simple-inputs/number.tsx +4 -0
- package/src/forms/domains/singleton/views/simple-inputs/string.tsx +4 -0
- package/src/fun/domains/curry/state.ts +6 -0
- package/src/fun/domains/id/state.ts +2 -0
- package/src/fun/domains/predicate/domains/bool-expr.ts +98 -0
- package/src/fun/domains/predicate/state.ts +29 -0
- package/src/fun/domains/simpleCallback/state.ts +3 -0
- package/src/fun/domains/uncurry/state.ts +5 -0
- package/src/fun/domains/unit/state.ts +3 -0
- package/src/fun/domains/updater/domains/caseUpdater/state.ts +44 -0
- package/src/fun/domains/updater/domains/mapUpdater/state.ts +36 -0
- package/src/fun/domains/updater/domains/maybeUpdater/state.ts +45 -0
- package/src/fun/domains/updater/domains/orderedMapUpdater/state.ts +26 -0
- package/src/fun/domains/updater/domains/orderedSetUpdater/state.ts +23 -0
- package/src/fun/domains/updater/domains/replaceWith/state.ts +3 -0
- package/src/fun/domains/updater/domains/simpleUpdater/domains/baseSimpleUpdater/state.ts +18 -0
- package/src/fun/domains/updater/domains/simpleUpdater/state.ts +72 -0
- package/src/fun/domains/updater/state.ts +86 -0
- package/src/fun/state.ts +33 -0
- package/src/infinite-data-stream/coroutines/builder.ts +8 -0
- package/src/infinite-data-stream/coroutines/infiniteLoader.ts +51 -0
- package/src/infinite-data-stream/coroutines/runner.ts +12 -0
- package/src/infinite-data-stream/state.ts +175 -0
- package/src/infinite-data-stream/template.tsx +16 -0
- package/src/math/domains/DOMRect/state.ts +12 -0
- package/src/math/domains/number/state.ts +9 -0
- package/src/math/domains/rect/state.ts +22 -0
- package/src/math/domains/rgba/state.ts +87 -0
- package/src/math/domains/size2/state.ts +14 -0
- package/src/math/domains/vector2/state.ts +16 -0
- package/src/queue/state.ts +42 -0
- package/src/state/domains/repository/state.ts +14 -0
- package/src/template/state.tsx +198 -0
- package/src/validation/state.ts +2 -0
- package/src/value/domains/mutable-value/state.ts +13 -0
- package/src/value/state.ts +12 -0
- package/src/visibility/state.ts +3 -0
- package/tsconfig.json +22 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { simpleUpdater, BasicUpdater, Updater, SimpleCallback } from "../../../../../../main";
|
|
2
|
+
import { Debounced } from "../../../../../debounced/state";
|
|
3
|
+
import { BasicFun } from "../../../../../fun/state";
|
|
4
|
+
import { InfiniteStreamState } from "../../../../../infinite-data-stream/state";
|
|
5
|
+
import { View } from "../../../../../template/state";
|
|
6
|
+
import { Value } from "../../../../../value/state";
|
|
7
|
+
import { CollectionReference } from "../../../collection/domains/reference/state";
|
|
8
|
+
import { CollectionSelection } from "../../../collection/domains/selection/state";
|
|
9
|
+
import { FormLabel } from "../../../singleton/domains/form-label/state";
|
|
10
|
+
import { OnChange, SharedFormState } from "../../../singleton/state";
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
export type SearchableInfiniteStreamState<Element extends CollectionReference> =
|
|
14
|
+
SharedFormState &
|
|
15
|
+
{ searchText: Debounced<Value<string>>; status: "open" | "closed"; stream: InfiniteStreamState<Element>; getChunk: BasicFun<string, InfiniteStreamState<Element>["getChunk"]>; };
|
|
16
|
+
export const SearchableInfiniteStreamState = <Element extends CollectionReference>() => ({
|
|
17
|
+
Default: (searchText: string, getChunk: BasicFun<string, InfiniteStreamState<Element>["getChunk"]>): SearchableInfiniteStreamState<Element> => ({
|
|
18
|
+
...SharedFormState.Default(),
|
|
19
|
+
searchText: Debounced.Default(Value.Default(searchText)),
|
|
20
|
+
status: "closed",
|
|
21
|
+
getChunk,
|
|
22
|
+
stream: InfiniteStreamState<Element>().Default(10, getChunk(searchText))
|
|
23
|
+
}),
|
|
24
|
+
Updaters: {
|
|
25
|
+
Core: {
|
|
26
|
+
...simpleUpdater<SearchableInfiniteStreamState<Element>>()("status"),
|
|
27
|
+
...simpleUpdater<SearchableInfiniteStreamState<Element>>()("stream"),
|
|
28
|
+
...simpleUpdater<SearchableInfiniteStreamState<Element>>()("searchText"),
|
|
29
|
+
},
|
|
30
|
+
Template: {
|
|
31
|
+
searchText: (_: BasicUpdater<string>): Updater<SearchableInfiniteStreamState<Element>> => SearchableInfiniteStreamState<Element>().Updaters.Core.searchText(
|
|
32
|
+
Debounced.Updaters.Template.value(
|
|
33
|
+
Value.Updaters.value(
|
|
34
|
+
_
|
|
35
|
+
)
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
export type SearchableInfiniteStreamView<Element extends CollectionReference, Context extends FormLabel, ForeignMutationsExpected> =
|
|
42
|
+
View<
|
|
43
|
+
Context & Value<CollectionSelection<Element>> & SearchableInfiniteStreamState<Element> & {
|
|
44
|
+
hasMoreValues:boolean
|
|
45
|
+
},
|
|
46
|
+
SearchableInfiniteStreamState<Element>,
|
|
47
|
+
ForeignMutationsExpected & {
|
|
48
|
+
onChange: OnChange<CollectionSelection<Element>>;
|
|
49
|
+
toggleOpen:SimpleCallback<void>
|
|
50
|
+
clearSelection:SimpleCallback<void>
|
|
51
|
+
setSearchText:SimpleCallback<string>
|
|
52
|
+
select:SimpleCallback<Element>
|
|
53
|
+
loadMore:SimpleCallback<void>
|
|
54
|
+
reload:SimpleCallback<void>
|
|
55
|
+
}>;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { List } from "immutable";
|
|
2
|
+
import { SimpleCallback, Debounce, InfiniteStreamLoader, id, replaceWith, BasicFun, Synchronize, Unit, ValidateRunner } from "../../../../../../main";
|
|
3
|
+
import { CoTypedFactory } from "../../../../../coroutines/builder";
|
|
4
|
+
import { Debounced } from "../../../../../debounced/state";
|
|
5
|
+
import { InfiniteStreamState } from "../../../../../infinite-data-stream/state";
|
|
6
|
+
import { Template } from "../../../../../template/state";
|
|
7
|
+
import { Value } from "../../../../../value/state";
|
|
8
|
+
import { CollectionReference } from "../../../collection/domains/reference/state";
|
|
9
|
+
import { CollectionSelection } from "../../../collection/domains/selection/state";
|
|
10
|
+
import { FormLabel } from "../../../singleton/domains/form-label/state";
|
|
11
|
+
import { FieldValidation, FieldValidationWithPath, FormValidatorSynchronized, OnChange, ValidationError } from "../../../singleton/state";
|
|
12
|
+
import { SearchableInfiniteStreamState, SearchableInfiniteStreamView } from "./state";
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
export const SearchableInfiniteStreamForm = <Element extends CollectionReference, Context extends FormLabel, ForeignMutationsExpected>(
|
|
16
|
+
validation:BasicFun<CollectionSelection<Element>, Promise<FieldValidation>>
|
|
17
|
+
) => {
|
|
18
|
+
const Co = CoTypedFactory<Context & Value<CollectionSelection<Element>>, SearchableInfiniteStreamState<Element>>();
|
|
19
|
+
const DebouncerCo = CoTypedFactory<Context & { onDebounce: SimpleCallback<void>; } & Value<CollectionSelection<Element>>, SearchableInfiniteStreamState<Element>>();
|
|
20
|
+
const DebouncedCo = CoTypedFactory<{ onDebounce: SimpleCallback<void>; }, Value<string>>();
|
|
21
|
+
const debouncer = DebouncerCo.Repeat(
|
|
22
|
+
DebouncerCo.Seq([
|
|
23
|
+
Debounce<Value<string>, { onDebounce: SimpleCallback<void>; }>(
|
|
24
|
+
DebouncedCo.GetState().then(current => DebouncedCo.Do(() => current.onDebounce()))
|
|
25
|
+
//.SetState(SearchNow.Updaters.reloadsRequested(_ => _ + 1))
|
|
26
|
+
.then(_ => DebouncedCo.Return("success")),
|
|
27
|
+
250
|
|
28
|
+
).embed(_ => ({ ..._, ..._.searchText }), SearchableInfiniteStreamState<Element>().Updaters.Core.searchText),
|
|
29
|
+
DebouncerCo.Wait(0)
|
|
30
|
+
])
|
|
31
|
+
);
|
|
32
|
+
const debouncerRunner = DebouncerCo.Template<ForeignMutationsExpected & { onChange: OnChange<CollectionSelection<Element>>; }>(
|
|
33
|
+
debouncer,
|
|
34
|
+
{
|
|
35
|
+
interval: 15,
|
|
36
|
+
runFilter: props => Debounced.Operations.shouldCoroutineRun(props.context.searchText)
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
const loaderRunner = Co.Template<ForeignMutationsExpected & { onChange: OnChange<CollectionSelection<Element>>; }>(
|
|
40
|
+
InfiniteStreamLoader<Element>().embed(_ => _.stream, SearchableInfiniteStreamState<Element>().Updaters.Core.stream),
|
|
41
|
+
{
|
|
42
|
+
interval: 15,
|
|
43
|
+
runFilter: props => InfiniteStreamState().Operations.shouldCoroutineRun(props.context.stream)
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
return Template.Default<Context & Value<CollectionSelection<Element>>, SearchableInfiniteStreamState<Element>, ForeignMutationsExpected & { onChange: OnChange<CollectionSelection<Element>>; },
|
|
48
|
+
SearchableInfiniteStreamView<Element, Context, ForeignMutationsExpected>>(props => <>
|
|
49
|
+
<props.view {...props}
|
|
50
|
+
context={{
|
|
51
|
+
...props.context,
|
|
52
|
+
hasMoreValues: !(props.context.stream.loadedElements.last()?.hasMoreValues == false),
|
|
53
|
+
}}
|
|
54
|
+
foreignMutations={{
|
|
55
|
+
...props.foreignMutations,
|
|
56
|
+
toggleOpen: () => props.setState(
|
|
57
|
+
SearchableInfiniteStreamState<Element>().Updaters.Core.status(
|
|
58
|
+
replaceWith(
|
|
59
|
+
props.context.status == "closed" ? "open" : "closed")
|
|
60
|
+
).then(
|
|
61
|
+
props.context.stream.loadedElements.count() == 0 ?
|
|
62
|
+
SearchableInfiniteStreamState<Element>().Updaters.Core.stream(
|
|
63
|
+
InfiniteStreamState<Element>().Updaters.Template.loadMore()
|
|
64
|
+
)
|
|
65
|
+
: id
|
|
66
|
+
)
|
|
67
|
+
),
|
|
68
|
+
clearSelection: () => {
|
|
69
|
+
props.foreignMutations.onChange(
|
|
70
|
+
replaceWith(
|
|
71
|
+
CollectionSelection<Element>().Default.right("no selection")
|
|
72
|
+
), List()
|
|
73
|
+
)
|
|
74
|
+
},
|
|
75
|
+
setSearchText: _ =>
|
|
76
|
+
props.setState(
|
|
77
|
+
SearchableInfiniteStreamState<Element>().Updaters.Template.searchText(
|
|
78
|
+
replaceWith(_)
|
|
79
|
+
)
|
|
80
|
+
),
|
|
81
|
+
loadMore: () =>
|
|
82
|
+
props.setState(
|
|
83
|
+
SearchableInfiniteStreamState<Element>().Updaters.Core.stream(
|
|
84
|
+
InfiniteStreamState<Element>().Updaters.Template.loadMore()
|
|
85
|
+
)
|
|
86
|
+
),
|
|
87
|
+
reload: () =>
|
|
88
|
+
props.setState(
|
|
89
|
+
SearchableInfiniteStreamState<Element>().Updaters.Template.searchText(
|
|
90
|
+
replaceWith("")
|
|
91
|
+
)
|
|
92
|
+
),
|
|
93
|
+
select: _ =>
|
|
94
|
+
props.foreignMutations.onChange(replaceWith<CollectionSelection<Element>>(CollectionSelection<Element>().Default.left(_)), List()),
|
|
95
|
+
}}
|
|
96
|
+
/>
|
|
97
|
+
</>
|
|
98
|
+
).any([
|
|
99
|
+
loaderRunner,
|
|
100
|
+
debouncerRunner.mapContextFromProps(props => ({
|
|
101
|
+
...props.context,
|
|
102
|
+
onDebounce: () => props.setState(
|
|
103
|
+
SearchableInfiniteStreamState<Element>().Updaters.Core.stream(
|
|
104
|
+
InfiniteStreamState<Element>().Updaters.Template.reload(
|
|
105
|
+
props.context.getChunk(props.context.searchText.value)
|
|
106
|
+
)
|
|
107
|
+
)
|
|
108
|
+
)
|
|
109
|
+
})),
|
|
110
|
+
ValidateRunner<Context, SearchableInfiniteStreamState<Element>, ForeignMutationsExpected, CollectionSelection<Element>>(
|
|
111
|
+
_ => validation(_).then(FieldValidationWithPath.Default.fromFieldValidation)
|
|
112
|
+
),
|
|
113
|
+
]);
|
|
114
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { OrderedMap } from "immutable";
|
|
2
|
+
import { Guid, SimpleCallback } from "../../../../../../main";
|
|
3
|
+
import { View } from "../../../../../template/state";
|
|
4
|
+
import { Value } from "../../../../../value/state";
|
|
5
|
+
import { CollectionReference } from "../../../collection/domains/reference/state";
|
|
6
|
+
import { FormLabel } from "../../../singleton/domains/form-label/state";
|
|
7
|
+
import { OnChange } from "../../../singleton/state";
|
|
8
|
+
import { SearchableInfiniteStreamState } from "../searchable-infinite-stream/state";
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
export type InfiniteStreamMultiselectView<Element extends CollectionReference, Context extends FormLabel, ForeignMutationsExpected> =
|
|
12
|
+
View<
|
|
13
|
+
Context & Value<OrderedMap<Guid, Element>> & SearchableInfiniteStreamState<Element> & {
|
|
14
|
+
hasMoreValues:boolean,
|
|
15
|
+
isLoading:boolean,
|
|
16
|
+
availableOptions:Array<Element>
|
|
17
|
+
},
|
|
18
|
+
SearchableInfiniteStreamState<Element>,
|
|
19
|
+
ForeignMutationsExpected & {
|
|
20
|
+
onChange: OnChange<OrderedMap<Guid, Element>>;
|
|
21
|
+
toggleOpen:SimpleCallback<void>
|
|
22
|
+
clearSelection:SimpleCallback<void>
|
|
23
|
+
setSearchText:SimpleCallback<string>
|
|
24
|
+
toggleSelection:SimpleCallback<Element>
|
|
25
|
+
loadMore:SimpleCallback<void>
|
|
26
|
+
reload:SimpleCallback<void>
|
|
27
|
+
}>;
|
package/src/forms/domains/primitives/domains/searchable-infinite-stream-multiselect/template.tsx
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { List, OrderedMap } from "immutable";
|
|
2
|
+
import { Guid, SimpleCallback, Debounce, InfiniteStreamLoader, CollectionSelection, id, replaceWith, OrderedMapRepo, AsyncState, BasicFun, Synchronize, Unit, ValidateRunner } from "../../../../../../main";
|
|
3
|
+
import { CoTypedFactory } from "../../../../../coroutines/builder";
|
|
4
|
+
import { Debounced } from "../../../../../debounced/state";
|
|
5
|
+
import { InfiniteStreamState } from "../../../../../infinite-data-stream/state";
|
|
6
|
+
import { Template } from "../../../../../template/state";
|
|
7
|
+
import { Value } from "../../../../../value/state";
|
|
8
|
+
import { CollectionReference } from "../../../collection/domains/reference/state";
|
|
9
|
+
import { FormLabel } from "../../../singleton/domains/form-label/state";
|
|
10
|
+
import { FieldValidation, FieldValidationWithPath, FormValidatorSynchronized, OnChange, ValidationError } from "../../../singleton/state";
|
|
11
|
+
import { SearchableInfiniteStreamState } from "../searchable-infinite-stream/state";
|
|
12
|
+
import { InfiniteStreamMultiselectView } from "./state";
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
export const InfiniteMultiselectDropdownForm = <Element extends CollectionReference, Context extends FormLabel, ForeignMutationsExpected>(
|
|
16
|
+
validation:BasicFun<OrderedMap<Guid, Element>, Promise<FieldValidation>>
|
|
17
|
+
) => {
|
|
18
|
+
const Co = CoTypedFactory<Context & Value<OrderedMap<Guid, Element>>, SearchableInfiniteStreamState<Element>>();
|
|
19
|
+
const DebouncerCo = CoTypedFactory<Context & { onDebounce: SimpleCallback<void>; } & Value<OrderedMap<Guid, Element>>, SearchableInfiniteStreamState<Element>>();
|
|
20
|
+
const DebouncedCo = CoTypedFactory<{ onDebounce: SimpleCallback<void>; }, Value<string>>();
|
|
21
|
+
const debouncer = DebouncerCo.Repeat(
|
|
22
|
+
DebouncerCo.Seq([
|
|
23
|
+
Debounce<Value<string>, { onDebounce: SimpleCallback<void>; }>(
|
|
24
|
+
DebouncedCo.GetState().then(current => DebouncedCo.Do(() => current.onDebounce()))
|
|
25
|
+
//.SetState(SearchNow.Updaters.reloadsRequested(_ => _ + 1))
|
|
26
|
+
.then(_ => DebouncedCo.Return("success")),
|
|
27
|
+
250
|
|
28
|
+
).embed(_ => ({ ..._, ..._.searchText }), SearchableInfiniteStreamState<Element>().Updaters.Core.searchText),
|
|
29
|
+
DebouncerCo.Wait(0)
|
|
30
|
+
])
|
|
31
|
+
);
|
|
32
|
+
const debouncerRunner = DebouncerCo.Template<ForeignMutationsExpected & { onChange: OnChange<OrderedMap<Guid, Element>>; }>(
|
|
33
|
+
debouncer,
|
|
34
|
+
{
|
|
35
|
+
interval: 15,
|
|
36
|
+
runFilter: props => Debounced.Operations.shouldCoroutineRun(props.context.searchText)
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
const loaderRunner = Co.Template<ForeignMutationsExpected & { onChange: OnChange<OrderedMap<Guid, Element>>; }>(
|
|
40
|
+
InfiniteStreamLoader<Element>().embed(_ => _.stream, SearchableInfiniteStreamState<Element>().Updaters.Core.stream),
|
|
41
|
+
{
|
|
42
|
+
interval: 15,
|
|
43
|
+
runFilter: props => InfiniteStreamState().Operations.shouldCoroutineRun(props.context.stream)
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
return Template.Default<Context & Value<OrderedMap<Guid, Element>>, SearchableInfiniteStreamState<Element>, ForeignMutationsExpected & { onChange: OnChange<OrderedMap<Guid, Element>>; }, InfiniteStreamMultiselectView<Element, Context, ForeignMutationsExpected>>(props => <>
|
|
48
|
+
<props.view {...props}
|
|
49
|
+
context={{
|
|
50
|
+
...props.context,
|
|
51
|
+
hasMoreValues: !(props.context.stream.loadedElements.last()?.hasMoreValues == false),
|
|
52
|
+
isLoading: AsyncState.Operations.isLoading(props.context.stream.loadingMore),
|
|
53
|
+
availableOptions: props.context.stream.loadedElements.valueSeq().flatMap(chunk =>
|
|
54
|
+
chunk.data.valueSeq()
|
|
55
|
+
).toArray()
|
|
56
|
+
}}
|
|
57
|
+
foreignMutations={{
|
|
58
|
+
...props.foreignMutations,
|
|
59
|
+
toggleOpen: () => props.setState(
|
|
60
|
+
SearchableInfiniteStreamState<Element>().Updaters.Core.status(
|
|
61
|
+
replaceWith(
|
|
62
|
+
props.context.status == "closed" ? "open" : "closed")
|
|
63
|
+
).then(
|
|
64
|
+
props.context.stream.loadedElements.count() == 0 ?
|
|
65
|
+
SearchableInfiniteStreamState<Element>().Updaters.Core.stream(
|
|
66
|
+
InfiniteStreamState<Element>().Updaters.Template.loadMore()
|
|
67
|
+
)
|
|
68
|
+
: id
|
|
69
|
+
)
|
|
70
|
+
),
|
|
71
|
+
clearSelection: () => {
|
|
72
|
+
props.foreignMutations.onChange(
|
|
73
|
+
OrderedMapRepo.Updaters.clear(), List()
|
|
74
|
+
)
|
|
75
|
+
},
|
|
76
|
+
setSearchText: _ =>
|
|
77
|
+
props.setState(
|
|
78
|
+
SearchableInfiniteStreamState<Element>().Updaters.Template.searchText(
|
|
79
|
+
replaceWith(_)
|
|
80
|
+
)
|
|
81
|
+
),
|
|
82
|
+
loadMore: () =>
|
|
83
|
+
props.setState(
|
|
84
|
+
SearchableInfiniteStreamState<Element>().Updaters.Core.stream(
|
|
85
|
+
InfiniteStreamState<Element>().Updaters.Template.loadMore()
|
|
86
|
+
)
|
|
87
|
+
),
|
|
88
|
+
reload: () =>
|
|
89
|
+
props.setState(
|
|
90
|
+
SearchableInfiniteStreamState<Element>().Updaters.Template.searchText(
|
|
91
|
+
replaceWith("")
|
|
92
|
+
)
|
|
93
|
+
),
|
|
94
|
+
toggleSelection: element =>
|
|
95
|
+
props.foreignMutations.onChange(
|
|
96
|
+
props.context.value.has(element.id) ?
|
|
97
|
+
OrderedMapRepo.Updaters.remove(element.id) :
|
|
98
|
+
OrderedMapRepo.Updaters.set(element.id, element),
|
|
99
|
+
List()),
|
|
100
|
+
}}
|
|
101
|
+
/>
|
|
102
|
+
</>
|
|
103
|
+
).any([
|
|
104
|
+
loaderRunner,
|
|
105
|
+
debouncerRunner.mapContextFromProps(props => ({
|
|
106
|
+
...props.context,
|
|
107
|
+
onDebounce: () => props.setState(
|
|
108
|
+
SearchableInfiniteStreamState<Element>().Updaters.Core.stream(
|
|
109
|
+
InfiniteStreamState<Element>().Updaters.Template.reload(
|
|
110
|
+
props.context.getChunk(props.context.searchText.value)
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
)
|
|
114
|
+
})),
|
|
115
|
+
ValidateRunner<Context, SearchableInfiniteStreamState<Element>, ForeignMutationsExpected, OrderedMap<Guid, Element>>(
|
|
116
|
+
_ => validation(_).then(FieldValidationWithPath.Default.fromFieldValidation)
|
|
117
|
+
),
|
|
118
|
+
]);
|
|
119
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { SimpleCallback, Unit } from "../../../../../../main";
|
|
2
|
+
import { View } from "../../../../../template/state";
|
|
3
|
+
import { Value } from "../../../../../value/state";
|
|
4
|
+
import { FormLabel } from "../../../singleton/domains/form-label/state";
|
|
5
|
+
import { OnChange, SharedFormState } from "../../../singleton/state";
|
|
6
|
+
|
|
7
|
+
export type StringView<Context extends FormLabel, ForeignMutationsExpected> =
|
|
8
|
+
View<
|
|
9
|
+
Context & Value<string> & SharedFormState,
|
|
10
|
+
SharedFormState,
|
|
11
|
+
ForeignMutationsExpected & { onChange: OnChange<string>; setNewValue: SimpleCallback<string> }
|
|
12
|
+
>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { List } from "immutable";
|
|
2
|
+
import { BasicFun, CoTypedFactory, Debounce, Debounced, replaceWith, Synchronize, Unit, ValidateRunner } from "../../../../../../main";
|
|
3
|
+
import { Template } from "../../../../../template/state";
|
|
4
|
+
import { Value } from "../../../../../value/state";
|
|
5
|
+
import { FormLabel } from "../../../singleton/domains/form-label/state";
|
|
6
|
+
import { FieldValidation, FieldValidationWithPath, FormValidatorSynchronized, OnChange, SharedFormState, ValidationError } from "../../../singleton/state";
|
|
7
|
+
import { StringView } from "./state";
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
export const StringForm = <Context extends FormLabel, ForeignMutationsExpected>(
|
|
11
|
+
validation:BasicFun<string, Promise<FieldValidation>>) => {
|
|
12
|
+
return Template.Default<Context & Value<string>, SharedFormState, ForeignMutationsExpected & { onChange: OnChange<string>; }, StringView<Context, ForeignMutationsExpected>>(props => <>
|
|
13
|
+
<props.view {...props}
|
|
14
|
+
foreignMutations={{
|
|
15
|
+
...props.foreignMutations,
|
|
16
|
+
setNewValue: (_) => props.foreignMutations.onChange(replaceWith(_), List())
|
|
17
|
+
}} />
|
|
18
|
+
</>
|
|
19
|
+
).any([
|
|
20
|
+
ValidateRunner<Context, SharedFormState, ForeignMutationsExpected, string>(
|
|
21
|
+
_ => validation(_).then(FieldValidationWithPath.Default.fromFieldValidation)
|
|
22
|
+
),
|
|
23
|
+
])
|
|
24
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FieldDescriptor } from "../field/state";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export type EntityDescriptor<E, EnumKeys, InfiniteEnumKeys, CustomTypeFields, Context> = {
|
|
5
|
+
[k in keyof E]: FieldDescriptor<E, EnumKeys, InfiniteEnumKeys, CustomTypeFields, k, Context>;
|
|
6
|
+
};
|
|
7
|
+
export const EntityDescriptor = {
|
|
8
|
+
Default: <E, EnumKeys, InfiniteEnumKeys, CustomTypeFields, Context>(_: EntityDescriptor<E, EnumKeys, InfiniteEnumKeys, CustomTypeFields, Context>): EntityDescriptor<E, EnumKeys, InfiniteEnumKeys, CustomTypeFields, Context> => _
|
|
9
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { BaseConfig } from "../base/state";
|
|
2
|
+
|
|
3
|
+
export type BooleanConfig = { kind: "boolean"; } & BaseConfig;
|
|
4
|
+
export const BooleanConfig = {
|
|
5
|
+
Default: (visible?: boolean, disabled?: boolean): BooleanConfig => ({ kind: "boolean", ...(BaseConfig.Default(visible, disabled)) })
|
|
6
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { SimpleCallback, BasicUpdater } from "../../../../../../../../../main";
|
|
2
|
+
import { SingletonFormWritableState } from "../../../../../state";
|
|
3
|
+
import { BaseConfig } from "../base/state";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export type CustomTypeConfig<E, EnumKeys, InfiniteEnumKeys, CustomTypeFields, k extends (keyof E) & (keyof CustomTypeFields), Context> =
|
|
7
|
+
{
|
|
8
|
+
kind: "custom"; k: k;
|
|
9
|
+
render: (props: {
|
|
10
|
+
context:Context,
|
|
11
|
+
state:CustomTypeFields[k],
|
|
12
|
+
entityValue: E;
|
|
13
|
+
fieldValue: E[k];
|
|
14
|
+
onChange: SimpleCallback<E[k]>;
|
|
15
|
+
setState: SimpleCallback<BasicUpdater<SingletonFormWritableState<E, EnumKeys, InfiniteEnumKeys, CustomTypeFields>>>;
|
|
16
|
+
}) => JSX.Element;
|
|
17
|
+
} & BaseConfig;
|
|
18
|
+
export const CustomTypeConfig = {
|
|
19
|
+
Default: <E, EnumKeys, InfiniteEnumKeys, CustomTypeFields, k extends (keyof E) & (keyof CustomTypeFields), Context>(
|
|
20
|
+
k: k, render: CustomTypeConfig<E, EnumKeys, InfiniteEnumKeys, CustomTypeFields, k, Context>["render"], visible?: boolean, disabled?: boolean): CustomTypeConfig<E, EnumKeys, InfiniteEnumKeys, CustomTypeFields, k, Context> => ({ kind: "custom", k, render, visible: visible ?? true, disabled: disabled ?? false })
|
|
21
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { SmallIdentifiable } from "../../../../../../../../../main";
|
|
2
|
+
import { BaseConfig } from "../base/state";
|
|
3
|
+
|
|
4
|
+
export type EnumConfig<V> = { kind: "enum"; choices: Array<SmallIdentifiable & { displayName: string; value: V; }>; } & BaseConfig;
|
|
5
|
+
export const EnumConfig = {
|
|
6
|
+
Default: <V>(choices: EnumConfig<V>["choices"], visible?: boolean, disabled?: boolean): EnumConfig<V> => ({ kind: "enum", choices, ...(BaseConfig.Default(visible, disabled)) })
|
|
7
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { SmallIdentifiable } from "../../../../../../../../../main";
|
|
2
|
+
import { InfiniteStreamState } from "../../../../../../../../infinite-data-stream/state";
|
|
3
|
+
import { BaseConfig } from "../base/state";
|
|
4
|
+
|
|
5
|
+
export type InfiniteEnumConfig<V extends SmallIdentifiable> = { kind: "infinite-enum"; getChunk: InfiniteStreamState<V>["getChunk"]; } & BaseConfig;
|
|
6
|
+
export const InfiniteEnumConfig = {
|
|
7
|
+
Default: <V extends SmallIdentifiable>(getChunk: InfiniteStreamState<V>["getChunk"], visible?: boolean, disabled?: boolean): InfiniteEnumConfig<V> => ({ kind: "infinite-enum", getChunk, ...(BaseConfig.Default(visible, disabled)) })
|
|
8
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { BaseConfig } from "../base/state";
|
|
2
|
+
|
|
3
|
+
export type NumberConfig = { kind: "number"; } & BaseConfig;
|
|
4
|
+
export const NumberConfig = {
|
|
5
|
+
Default: (visible?: boolean, disabled?: boolean): NumberConfig => ({ kind: "number", ...(BaseConfig.Default(visible, disabled)) })
|
|
6
|
+
};
|
|
7
|
+
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { BaseConfig } from "../base/state";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export type StringConfig = { kind: "string"; } & BaseConfig;
|
|
5
|
+
export const StringConfig = {
|
|
6
|
+
Default: (visible?: boolean, disabled?: boolean): StringConfig => ({ kind: "string", ...(BaseConfig.Default(visible, disabled)) })
|
|
7
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SmallIdentifiable } from "../../../../../../../main";
|
|
2
|
+
import { NumberConfig } from "./domains/number/state";
|
|
3
|
+
import { StringConfig } from "./domains/string/state";
|
|
4
|
+
import { BooleanConfig } from "./domains/boolean/state";
|
|
5
|
+
import { DateConfig } from "./domains/date/state";
|
|
6
|
+
import { EnumConfig } from "./domains/enum/state";
|
|
7
|
+
import { InfiniteEnumConfig } from "./domains/infinite-enum/state";
|
|
8
|
+
import { CustomTypeConfig } from "./domains/custom/state";
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
export type FieldDescriptor<E, EnumKeys, InfiniteEnumKeys, CustomTypeFields, k extends keyof E, Context> =
|
|
12
|
+
k extends keyof CustomTypeFields ?
|
|
13
|
+
CustomTypeConfig<E, EnumKeys, InfiniteEnumKeys, CustomTypeFields, k, Context> :
|
|
14
|
+
k extends EnumKeys ? EnumConfig<E[k]> :
|
|
15
|
+
k extends InfiniteEnumKeys ? E[k] extends SmallIdentifiable ? InfiniteEnumConfig<E[k]> :
|
|
16
|
+
{ kind: "error - infinite enum requires 'extends Identifiable'"; } : E[k] extends number ? NumberConfig : E[k] extends string ? StringConfig : E[k] extends string ? StringConfig : E[k] extends boolean ? BooleanConfig : E[k] extends Date ? DateConfig : { kind: "error - type not supported "; };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Template } from "../../../../../../template/state";
|
|
2
|
+
import { SingletonFormReadonlyContext, SingletonFormWritableState, SingletonFormForeignMutationsExpected } from "../../../state";
|
|
3
|
+
import { FieldViews } from "../../../views/field-views";
|
|
4
|
+
import { EntityDescriptor } from "../entity/state";
|
|
5
|
+
|
|
6
|
+
export type FormDefinition<Entity, EnumKeys, InfiniteEnumKeys, CustomTypeFields, Context> = {
|
|
7
|
+
entityDescriptor: EntityDescriptor<Entity, EnumKeys, InfiniteEnumKeys, CustomTypeFields, Context>;
|
|
8
|
+
fieldOrder: Array<keyof Entity>;
|
|
9
|
+
};
|
|
10
|
+
export type FormTemplateAndDefinition<Entity, EnumKeys, InfiniteEnumKeys, CustomTypeFields, Context> = {
|
|
11
|
+
template: Template<
|
|
12
|
+
SingletonFormReadonlyContext<Entity, EnumKeys, InfiniteEnumKeys, CustomTypeFields, Context> & SingletonFormWritableState<Entity, EnumKeys, InfiniteEnumKeys, CustomTypeFields>, SingletonFormWritableState<Entity, EnumKeys, InfiniteEnumKeys, CustomTypeFields>, SingletonFormForeignMutationsExpected<Entity, EnumKeys, InfiniteEnumKeys>, FieldViews>;
|
|
13
|
+
} & FormDefinition<Entity, EnumKeys, InfiniteEnumKeys, CustomTypeFields, Context>;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { List, OrderedMap, OrderedSet } from "immutable"
|
|
2
|
+
import { BasicUpdater, id, BasicPredicate, SimpleCallback, Unit, Debounced, Synchronized, unit, replaceWith, CoTypedFactory, Debounce, Synchronize, BasicFun } from "../../../../main"
|
|
3
|
+
import { Template, View } from "../../../template/state"
|
|
4
|
+
import { Value } from "../../../value/state"
|
|
5
|
+
|
|
6
|
+
export type ToPathUnions<a> = a[keyof a]
|
|
7
|
+
export type Paths<Entity, NestedPaths = Unit> = {
|
|
8
|
+
[f in keyof Entity]:
|
|
9
|
+
f extends keyof NestedPaths ?
|
|
10
|
+
[f, ToPathUnions<NestedPaths[f]>]
|
|
11
|
+
: [f]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// type OtherNestedThing = { x:boolean, y:string }
|
|
15
|
+
// type Address = { city:string, street:string, number:number, other:OtherNestedThing }
|
|
16
|
+
// type Person = { name:string, surname:string, birthday:Date, address:Address, other:OtherNestedThing }
|
|
17
|
+
// type OtherNestedThingPaths = Paths<OtherNestedThing, Unit>
|
|
18
|
+
// type AddressPaths = Paths<Address, { other:OtherNestedThingPaths }>
|
|
19
|
+
// type PersonPaths = ToPathUnions<Paths<Person, { address:AddressPaths, other:OtherNestedThingPaths }>>
|
|
20
|
+
// const f = (_:PersonPaths) => {
|
|
21
|
+
// if (_[0] == "name") return
|
|
22
|
+
// if (_[0] == "surname") return
|
|
23
|
+
// if (_[0] == "birthday") return
|
|
24
|
+
// if (_[0] == "address") {
|
|
25
|
+
// _[1][0] == "city"
|
|
26
|
+
// if (_[1][0] == "other") {
|
|
27
|
+
// _[1][1][0] == "x"
|
|
28
|
+
// }
|
|
29
|
+
// return
|
|
30
|
+
// }
|
|
31
|
+
// _[1][0] == "x"
|
|
32
|
+
// }
|
|
33
|
+
|
|
34
|
+
export type ValidationError = string
|
|
35
|
+
export type FieldValidation = Array<ValidationError>
|
|
36
|
+
export type Path = Array<string>
|
|
37
|
+
export type ValidationErrorWithPath = [Path, ValidationError]
|
|
38
|
+
export type FieldValidationWithPath = Array<ValidationErrorWithPath>
|
|
39
|
+
export const FieldValidationWithPath = {
|
|
40
|
+
Default:{
|
|
41
|
+
fromFieldValidation:(_:FieldValidation) : FieldValidationWithPath =>
|
|
42
|
+
_.map(_ => ([[], _])),
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export type FormValidatorSynchronized = Synchronized<Unit, FieldValidationWithPath>
|
|
46
|
+
export type SharedFormState = { modifiedByUser: boolean, validation: Debounced<FormValidatorSynchronized> }
|
|
47
|
+
export const SharedFormState = {
|
|
48
|
+
Default: (): SharedFormState => ({
|
|
49
|
+
modifiedByUser: false,
|
|
50
|
+
// start the validation so that it immediately runs and registers the first errors such as missing values and such
|
|
51
|
+
validation: Debounced.Updaters.Template.value<FormValidatorSynchronized>(Synchronized.Updaters.value(replaceWith(unit)))(Debounced.Default(Synchronized.Default(unit)))
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
export type EntityFormState<Entity, Fields extends (keyof Entity) & (keyof FieldStates), FieldStates, Context, ForeignMutationsExpected> =
|
|
55
|
+
{ [f in Fields]: FieldStates[f] & SharedFormState } & SharedFormState
|
|
56
|
+
export type EntityFormContext<Entity, Fields extends (keyof Entity) & (keyof FieldStates), FieldStates, Context, ForeignMutationsExpected> =
|
|
57
|
+
Context & EntityFormState<Entity, Fields, FieldStates, Context, ForeignMutationsExpected> & { visibleFields: OrderedMap<Fields, BasicPredicate<Context>> } & Value<Entity>
|
|
58
|
+
export type OnChange<Entity> = (updater: BasicUpdater<Entity>, path: List<string>) => void
|
|
59
|
+
export type EntityFormForeignMutationsExpected<Entity, Fields extends (keyof Entity) & (keyof FieldStates), FieldStates, Context, ForeignMutationsExpected> =
|
|
60
|
+
ForeignMutationsExpected & { onChange: OnChange<Entity> }
|
|
61
|
+
|
|
62
|
+
export type FieldTemplates<Entity, Fields extends (keyof Entity) & (keyof FieldStates), FieldStates, Context, ForeignMutationsExpected> = {
|
|
63
|
+
[f in Fields]: EmbeddedFieldTemplate<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export type EntityFormView<Entity, Fields extends (keyof Entity) & (keyof FieldStates), FieldStates, Context, ForeignMutationsExpected> =
|
|
67
|
+
View<EntityFormContext<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>, EntityFormState<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>, EntityFormForeignMutationsExpected<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>, {
|
|
68
|
+
EmbeddedFields: FieldTemplates<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>,
|
|
69
|
+
VisibleFieldKeys: OrderedSet<Fields>
|
|
70
|
+
}>
|
|
71
|
+
export type EntityFormTemplate<Entity, Fields extends (keyof Entity) & (keyof FieldStates), FieldStates, Context, ForeignMutationsExpected> =
|
|
72
|
+
Template<
|
|
73
|
+
EntityFormContext<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>,
|
|
74
|
+
EntityFormState<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>,
|
|
75
|
+
EntityFormForeignMutationsExpected<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>,
|
|
76
|
+
EntityFormView<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>
|
|
77
|
+
>
|
|
78
|
+
export type EmbeddedFieldTemplate<Entity, Fields extends (keyof Entity) & (keyof FieldStates), FieldStates, Context, ForeignMutationsExpected> =
|
|
79
|
+
Template<
|
|
80
|
+
EntityFormContext<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>,
|
|
81
|
+
EntityFormState<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>,
|
|
82
|
+
EntityFormForeignMutationsExpected<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>
|
|
83
|
+
>
|
|
84
|
+
|
|
85
|
+
export type FormStateFromEntity<E, S> = {
|
|
86
|
+
[f in keyof E]: f extends keyof S ? S[f] & SharedFormState : SharedFormState
|
|
87
|
+
} & SharedFormState
|