create-foldkit-app 0.38.0 → 0.39.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/dist/templates/base/FOLDKIT.md +3 -1
- package/dist/templates/examples/canvas-art/src/main.ts +1 -1
- package/dist/templates/examples/charting/src/chartHost.ts +3 -4
- package/dist/templates/examples/charting/src/entry.ts +0 -2
- package/dist/templates/examples/charting/src/view/chart.ts +101 -36
- package/dist/templates/examples/embedding/src/main.ts +3 -3
- package/dist/templates/examples/generative-art/src/subscription.ts +1 -1
- package/dist/templates/examples/job-application/src/step/education/education.ts +14 -16
- package/dist/templates/examples/job-application/src/step/skills/skills.ts +14 -16
- package/dist/templates/examples/job-application/src/step/workHistory/workHistory.ts +14 -16
- package/dist/templates/examples/map/src/entry.ts +1 -2
- package/dist/templates/examples/map/src/main.ts +123 -145
- package/dist/templates/examples/map/src/mapHost.ts +10 -12
- package/dist/templates/examples/map/src/mount.test.ts +93 -68
- package/dist/templates/examples/pixel-art/src/subscription.ts +5 -5
- package/dist/templates/examples/routing/src/main.ts +3 -3
- package/dist/templates/examples/slow-warnings/src/main.ts +4 -4
- package/dist/templates/examples/snake/src/main.ts +4 -3
- package/dist/templates/examples/ssg/src/entry.server.ts +2 -0
- package/dist/templates/examples/ssg/src/entry.ts +1 -0
- package/dist/templates/examples/ssr/package.json +1 -1
- package/dist/templates/examples/ssr/src/entry.server.ts +2 -0
- package/dist/templates/examples/ssr/src/entry.ts +1 -0
- package/dist/templates/examples/stopwatch/src/main.ts +1 -0
- package/dist/templates/examples/ui-showcase/src/main.ts +49 -37
- package/dist/templates/examples/ui-showcase/src/ui/subscriptions.ts +1 -18
- package/dist/templates/examples/ui-showcase/src/ui/update.ts +2 -12
- package/dist/templates/examples/ui-showcase/src/ui/view/calendar.ts +9 -7
- package/dist/templates/examples/ui-showcase/src/ui/view/checkbox.ts +80 -65
- package/dist/templates/examples/ui-showcase/src/ui/view/dialog.ts +102 -123
- package/dist/templates/examples/ui-showcase/src/ui/view/disclosure.ts +128 -120
- package/dist/templates/examples/ui-showcase/src/ui/view/fieldset.ts +173 -144
- package/dist/templates/examples/ui-showcase/src/ui/view/fileDrop.ts +17 -15
- package/dist/templates/examples/ui-showcase/src/ui/view/hoverIntent.ts +64 -56
- package/dist/templates/examples/ui-showcase/src/ui/view/input.ts +32 -33
- package/dist/templates/examples/ui-showcase/src/ui/view/meter.ts +82 -73
- package/dist/templates/examples/ui-showcase/src/ui/view/popover.ts +100 -81
- package/dist/templates/examples/ui-showcase/src/ui/view/progress.ts +83 -68
- package/dist/templates/examples/ui-showcase/src/ui/view/radioGroup.ts +79 -85
- package/dist/templates/examples/ui-showcase/src/ui/view/select.ts +63 -67
- package/dist/templates/examples/ui-showcase/src/ui/view/slider.ts +72 -72
- package/dist/templates/examples/ui-showcase/src/ui/view/switch.ts +25 -26
- package/dist/templates/examples/ui-showcase/src/ui/view/tabs.ts +58 -46
- package/dist/templates/examples/ui-showcase/src/ui/view/textarea.ts +32 -39
- package/dist/templates/examples/ui-showcase/src/ui/view/tooltip.ts +48 -36
- package/dist/templates/examples/websocket-chat/src/main.ts +44 -18
- package/dist/templates/examples/websocket-chat/src/story.test.ts +33 -6
- package/dist/templates/release.json +12 -11
- package/dist/templates/rendering/ssg/src/entry.server.ts +2 -0
- package/dist/templates/rendering/ssg/src/entry.ts +1 -0
- package/dist/templates/rendering/ssg/vite.config.ts +1 -0
- package/dist/templates/rendering/ssr/scripts/serve.ts +4 -145
- package/dist/templates/rendering/ssr/src/entry.server.ts +2 -0
- package/dist/templates/rendering/ssr/src/entry.ts +1 -0
- package/dist/templates/rendering/ssr/vite.config.ts +1 -0
- package/dist/utils/files.js +2 -0
- package/package.json +1 -1
- package/dist/templates/examples/charting/src/subscription.ts +0 -70
|
@@ -108,7 +108,9 @@ For DOM operations (focus, scroll, modals, scroll lock), Foldkit ships a `Dom` m
|
|
|
108
108
|
|
|
109
109
|
### File Organization
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
Keep the runtime boot separate from the pure definitions. `src/entry.ts` calls `Runtime.makeApplication`, then `Runtime.run` for a client-rendered app or `Runtime.hydrate` for an SSR or SSG app. A client-rendered app references that entry from `index.html`. An SSR or SSG app names it in `ssr.clientEntry` in `vite.config.ts`, imports CSS from it, and exports `renderDocument` from `src/entry.server.ts` to produce the complete document. Its source tree has no `index.html`.
|
|
112
|
+
|
|
113
|
+
The definitions (Model, Messages, init, update, view, Commands) never call `Runtime.run` or `Runtime.hydrate`, so tests and server entries can import them without booting a browser runtime. Keep both calls out of `main.ts`.
|
|
112
114
|
|
|
113
115
|
For a small app the definitions all fit in one `src/main.ts`. Split a unit into its own file when it has _both_ a distinct reason to change _and_ a name you'd give it unprompted: the pure domain core into `timer.ts` or `domain.ts`, the view into `view.ts` (or a `components/` directory), a Command's owned resource into its own module. Split on that revealed seam, not on line count alone. A file that has grown large is _evidence_ a seam has formed, so treat its size as a prompt to re-check for one. Two splits are forced: extract Messages to `message.ts` when Commands need the constructors (this breaks the cycle between `command.ts` and `main.ts`), and colocate Commands with the update that returns them. Exemplars: counter and stopwatch are a single `main.ts`; kanban splits `domain` / `command` / `message` / `model`; typing-game splits views by page.
|
|
114
116
|
|
|
@@ -159,7 +159,7 @@ export const update = (model: Model, message: Message) =>
|
|
|
159
159
|
// SUBSCRIPTION
|
|
160
160
|
|
|
161
161
|
export const subscriptions = Subscription.make<Model, Message>()(_entry => ({
|
|
162
|
-
frame: Subscription.
|
|
162
|
+
frame: Subscription.animationFrameEntry({
|
|
163
163
|
isActive: model => model.isRunning,
|
|
164
164
|
toMessage: deltaTime => Message.TickedFrame({ deltaTime }),
|
|
165
165
|
}),
|
|
@@ -10,11 +10,10 @@ export const setChart = (hostId: string, chart: EChartsType): void => {
|
|
|
10
10
|
export const getChart = (hostId: string): Option.Option<EChartsType> =>
|
|
11
11
|
Option.fromNullishOr(chartsByHostId.get(hostId))
|
|
12
12
|
|
|
13
|
-
export const removeChart = (hostId: string): void => {
|
|
14
|
-
|
|
13
|
+
export const removeChart = (hostId: string, chart: EChartsType): void => {
|
|
14
|
+
chart.dispose()
|
|
15
15
|
|
|
16
|
-
if (
|
|
17
|
-
maybeChart.value.dispose()
|
|
16
|
+
if (chartsByHostId.get(hostId) === chart) {
|
|
18
17
|
chartsByHostId.delete(hostId)
|
|
19
18
|
}
|
|
20
19
|
}
|
|
@@ -4,7 +4,6 @@ import { registerEcharts } from './echarts'
|
|
|
4
4
|
import { init } from './init'
|
|
5
5
|
import { Message } from './message'
|
|
6
6
|
import { Model } from './model'
|
|
7
|
-
import { subscriptions } from './subscription'
|
|
8
7
|
import { update } from './update'
|
|
9
8
|
import { view } from './view/index'
|
|
10
9
|
|
|
@@ -15,7 +14,6 @@ const application = Runtime.makeApplication({
|
|
|
15
14
|
init,
|
|
16
15
|
update,
|
|
17
16
|
view,
|
|
18
|
-
subscriptions,
|
|
19
17
|
container: document.getElementById('root'),
|
|
20
18
|
devTools: {
|
|
21
19
|
Message,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as echarts from 'echarts/core'
|
|
2
|
-
import { Effect, Option, Schema } from 'effect'
|
|
2
|
+
import { Effect, Option, Queue, Schema, Stream, pipe } from 'effect'
|
|
3
3
|
import { Mount } from 'foldkit'
|
|
4
4
|
import type { Html } from 'foldkit/html'
|
|
5
5
|
import { HtmlBuilder } from 'foldkit/html'
|
|
@@ -13,49 +13,114 @@ import { formatInteger } from './format'
|
|
|
13
13
|
|
|
14
14
|
export const CHART_HOST_ID = 'charting-chart'
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
16
|
+
type MountChartMessage =
|
|
17
|
+
| typeof Message.SucceededMountChart.Type
|
|
18
|
+
| typeof Message.FailedMountChart.Type
|
|
19
|
+
| typeof Message.ClickedChartDatum.Type
|
|
20
|
+
|
|
21
|
+
const toChartMountError = (error: unknown): Error =>
|
|
22
|
+
error instanceof Error ? error : new Error(`Failed to mount chart: ${error}`)
|
|
23
|
+
|
|
24
|
+
const ChartClickEvent = Schema.Struct({
|
|
25
|
+
data: Schema.OptionFromOptional(Schema.Struct({ id: Schema.String })),
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const datumIdFromChartClickEvent = (event: unknown): Option.Option<string> =>
|
|
29
|
+
pipe(
|
|
30
|
+
event,
|
|
31
|
+
Schema.decodeUnknownOption(ChartClickEvent),
|
|
32
|
+
Option.flatMap(({ data }) => data),
|
|
33
|
+
Option.map(({ id }) => id),
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
const observeChartResizeAndClickEvents = (
|
|
37
|
+
element: HTMLElement,
|
|
38
|
+
chart: ReturnType<typeof echarts.init>,
|
|
39
|
+
queue: Queue.Enqueue<MountChartMessage>,
|
|
40
|
+
) =>
|
|
41
|
+
Effect.acquireRelease(
|
|
42
|
+
Effect.try({
|
|
43
|
+
try: () => {
|
|
44
|
+
const resizeObserver = new ResizeObserver(() => chart.resize())
|
|
45
|
+
const onWindowResize = () => chart.resize()
|
|
46
|
+
const onClick = (event: unknown) => {
|
|
47
|
+
const maybeDatumId = datumIdFromChartClickEvent(event)
|
|
48
|
+
|
|
49
|
+
if (Option.isSome(maybeDatumId)) {
|
|
50
|
+
Queue.offerUnsafe(
|
|
51
|
+
queue,
|
|
52
|
+
Message.ClickedChartDatum({ datumId: maybeDatumId.value }),
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
try {
|
|
31
58
|
resizeObserver.observe(element)
|
|
32
|
-
const onWindowResize = () => chart.resize()
|
|
33
59
|
window.addEventListener('resize', onWindowResize)
|
|
34
|
-
|
|
35
|
-
return { resizeObserver, onWindowResize }
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
error instanceof Error
|
|
39
|
-
? error
|
|
40
|
-
: new Error(`Failed to mount chart: ${error}`),
|
|
41
|
-
}),
|
|
42
|
-
({ resizeObserver, onWindowResize }) =>
|
|
43
|
-
Effect.sync(() => {
|
|
44
|
-
resizeObserver.disconnect()
|
|
60
|
+
chart.on('click', onClick)
|
|
61
|
+
return { resizeObserver, onWindowResize, onClick }
|
|
62
|
+
} catch (error) {
|
|
63
|
+
chart.off('click', onClick)
|
|
45
64
|
window.removeEventListener('resize', onWindowResize)
|
|
46
|
-
|
|
65
|
+
resizeObserver.disconnect()
|
|
66
|
+
throw error
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
catch: toChartMountError,
|
|
70
|
+
}),
|
|
71
|
+
({ resizeObserver, onWindowResize, onClick }) =>
|
|
72
|
+
Effect.sync(() => {
|
|
73
|
+
chart.off('click', onClick)
|
|
74
|
+
window.removeEventListener('resize', onWindowResize)
|
|
75
|
+
resizeObserver.disconnect()
|
|
76
|
+
}),
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
const mountChart = (element: Element, hostId: string) =>
|
|
80
|
+
Stream.callback<MountChartMessage>(queue =>
|
|
81
|
+
Effect.gen(function* () {
|
|
82
|
+
if (!(element instanceof HTMLElement)) {
|
|
83
|
+
Queue.offerUnsafe(
|
|
84
|
+
queue,
|
|
85
|
+
Message.FailedMountChart({
|
|
86
|
+
reason: 'Chart host is not an HTMLElement.',
|
|
87
|
+
}),
|
|
88
|
+
)
|
|
89
|
+
return yield* Effect.never
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const chart = yield* Effect.acquireRelease(
|
|
93
|
+
Effect.try({
|
|
94
|
+
try: () => echarts.init(element, undefined, { renderer: 'canvas' }),
|
|
95
|
+
catch: toChartMountError,
|
|
47
96
|
}),
|
|
48
|
-
|
|
49
|
-
|
|
97
|
+
chart => Effect.sync(() => removeChart(hostId, chart)),
|
|
98
|
+
)
|
|
99
|
+
setChart(hostId, chart)
|
|
100
|
+
|
|
101
|
+
yield* observeChartResizeAndClickEvents(element, chart, queue)
|
|
102
|
+
|
|
103
|
+
Queue.offerUnsafe(queue, Message.SucceededMountChart({ hostId }))
|
|
104
|
+
return yield* Effect.never
|
|
105
|
+
}).pipe(
|
|
50
106
|
Effect.catch(error =>
|
|
51
|
-
Effect.
|
|
107
|
+
Effect.sync(() =>
|
|
108
|
+
Queue.offerUnsafe(
|
|
109
|
+
queue,
|
|
110
|
+
Message.FailedMountChart({ reason: error.message }),
|
|
111
|
+
),
|
|
112
|
+
),
|
|
52
113
|
),
|
|
53
|
-
)
|
|
54
|
-
|
|
114
|
+
),
|
|
115
|
+
)
|
|
55
116
|
|
|
56
|
-
export const MountChart = Mount.
|
|
117
|
+
export const MountChart = Mount.defineStream('MountChart', {
|
|
57
118
|
args: { hostId: Schema.String },
|
|
58
|
-
messages: [
|
|
119
|
+
messages: [
|
|
120
|
+
Message.SucceededMountChart,
|
|
121
|
+
Message.FailedMountChart,
|
|
122
|
+
Message.ClickedChartDatum,
|
|
123
|
+
],
|
|
59
124
|
execute: ({ element, hostId }) => mountChart(element, hostId),
|
|
60
125
|
})
|
|
61
126
|
|
|
@@ -79,10 +79,10 @@ export const update = (model: Model, message: Message) =>
|
|
|
79
79
|
const TICK_INTERVAL = Duration.seconds(1)
|
|
80
80
|
|
|
81
81
|
export const subscriptions = Subscription.make<Model, Message>()(_entry => ({
|
|
82
|
-
tick: Subscription.
|
|
83
|
-
Stream.tick(TICK_INTERVAL).pipe(Stream.map(Message.Ticked)),
|
|
82
|
+
tick: Subscription.persistentEntry(
|
|
83
|
+
Stream.tick(TICK_INTERVAL).pipe(Stream.drop(1), Stream.map(Message.Ticked)),
|
|
84
84
|
),
|
|
85
|
-
hostStep: Port.
|
|
85
|
+
hostStep: Port.subscriptionEntry(ports.inbound.stepChanged, step =>
|
|
86
86
|
Message.ChangedStep({ step }),
|
|
87
87
|
),
|
|
88
88
|
}))
|
|
@@ -23,7 +23,7 @@ const noiseScaleSliderSubscriptions = Subscription.lift({
|
|
|
23
23
|
})
|
|
24
24
|
|
|
25
25
|
const frameSubscription = Subscription.make<Model, Message>()(_entry => ({
|
|
26
|
-
frame: Subscription.
|
|
26
|
+
frame: Subscription.animationFrameEntry({
|
|
27
27
|
isActive: model => model.isRunning,
|
|
28
28
|
toMessage: deltaTimeMs => Message.TickedFrame({ deltaTimeMs }),
|
|
29
29
|
}),
|
|
@@ -54,9 +54,7 @@ export const GenerateEntryId = Command.define('GenerateEntryId', {
|
|
|
54
54
|
|
|
55
55
|
// UPDATE
|
|
56
56
|
|
|
57
|
-
const foldEntryOutMessage:
|
|
58
|
-
entryId: string,
|
|
59
|
-
) => (outMessage: Entry.OutMessage) => Update.Step<Model, Message> = entryId =>
|
|
57
|
+
const foldEntryOutMessage = (entryId: string) =>
|
|
60
58
|
Entry.OutMessage.match<Update.Step<Model, Message>>({
|
|
61
59
|
Removed: () => model => ({
|
|
62
60
|
model: modifyFields(model, {
|
|
@@ -65,18 +63,18 @@ const foldEntryOutMessage: (
|
|
|
65
63
|
}),
|
|
66
64
|
})
|
|
67
65
|
|
|
68
|
-
const foldEntry = (
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
66
|
+
const foldEntry = Update.foldChildAt({
|
|
67
|
+
update: Entry.update,
|
|
68
|
+
readAt: (model: Model, entryId: string) =>
|
|
69
|
+
Array.findFirst(model.entries, entry => entry.id === entryId),
|
|
70
|
+
writeAt: (model, entryId, nextEntry) =>
|
|
71
|
+
modifyFields(model, {
|
|
72
|
+
entries: Array.map(entry => (entry.id === entryId ? nextEntry : entry)),
|
|
73
|
+
}),
|
|
74
|
+
toParentMessage: (entryId, message) =>
|
|
75
|
+
Message.GotEntryMessage({ entryId, message }),
|
|
76
|
+
foldOutMessage: foldEntryOutMessage,
|
|
77
|
+
})
|
|
80
78
|
|
|
81
79
|
export const update = (model: Model, message: Message) =>
|
|
82
80
|
Message.match<Update.Return<Model, Message>>(message, {
|
|
@@ -97,7 +95,7 @@ export const update = (model: Model, message: Message) =>
|
|
|
97
95
|
}),
|
|
98
96
|
|
|
99
97
|
GotEntryMessage: ({ entryId, message }) =>
|
|
100
|
-
foldEntry(
|
|
98
|
+
foldEntry(model, entryId, message),
|
|
101
99
|
})
|
|
102
100
|
|
|
103
101
|
// VALIDATION SUMMARY
|
|
@@ -51,9 +51,7 @@ export const GenerateEntryId = Command.define('GenerateEntryId', {
|
|
|
51
51
|
|
|
52
52
|
// UPDATE
|
|
53
53
|
|
|
54
|
-
const foldEntryOutMessage:
|
|
55
|
-
entryId: string,
|
|
56
|
-
) => (outMessage: Entry.OutMessage) => Update.Step<Model, Message> = entryId =>
|
|
54
|
+
const foldEntryOutMessage = (entryId: string) =>
|
|
57
55
|
Entry.OutMessage.match<Update.Step<Model, Message>>({
|
|
58
56
|
Removed: () => model => ({
|
|
59
57
|
model: modifyFields(model, {
|
|
@@ -62,18 +60,18 @@ const foldEntryOutMessage: (
|
|
|
62
60
|
}),
|
|
63
61
|
})
|
|
64
62
|
|
|
65
|
-
const foldEntry = (
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
63
|
+
const foldEntry = Update.foldChildAt({
|
|
64
|
+
update: Entry.update,
|
|
65
|
+
readAt: (model: Model, entryId: string) =>
|
|
66
|
+
Array.findFirst(model.entries, entry => entry.id === entryId),
|
|
67
|
+
writeAt: (model, entryId, nextEntry) =>
|
|
68
|
+
modifyFields(model, {
|
|
69
|
+
entries: Array.map(entry => (entry.id === entryId ? nextEntry : entry)),
|
|
70
|
+
}),
|
|
71
|
+
toParentMessage: (entryId, message) =>
|
|
72
|
+
Message.GotEntryMessage({ entryId, message }),
|
|
73
|
+
foldOutMessage: foldEntryOutMessage,
|
|
74
|
+
})
|
|
77
75
|
|
|
78
76
|
export const update = (model: Model, message: Message) =>
|
|
79
77
|
Message.match<Update.Return<Model, Message>>(message, {
|
|
@@ -94,7 +92,7 @@ export const update = (model: Model, message: Message) =>
|
|
|
94
92
|
}),
|
|
95
93
|
|
|
96
94
|
GotEntryMessage: ({ entryId, message }) =>
|
|
97
|
-
foldEntry(
|
|
95
|
+
foldEntry(model, entryId, message),
|
|
98
96
|
})
|
|
99
97
|
|
|
100
98
|
// VALIDATION SUMMARY
|
|
@@ -54,9 +54,7 @@ export const GenerateEntryId = Command.define('GenerateEntryId', {
|
|
|
54
54
|
|
|
55
55
|
// UPDATE
|
|
56
56
|
|
|
57
|
-
const foldEntryOutMessage:
|
|
58
|
-
entryId: string,
|
|
59
|
-
) => (outMessage: Entry.OutMessage) => Update.Step<Model, Message> = entryId =>
|
|
57
|
+
const foldEntryOutMessage = (entryId: string) =>
|
|
60
58
|
Entry.OutMessage.match<Update.Step<Model, Message>>({
|
|
61
59
|
Removed: () => model => ({
|
|
62
60
|
model: modifyFields(model, {
|
|
@@ -65,18 +63,18 @@ const foldEntryOutMessage: (
|
|
|
65
63
|
}),
|
|
66
64
|
})
|
|
67
65
|
|
|
68
|
-
const foldEntry = (
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
66
|
+
const foldEntry = Update.foldChildAt({
|
|
67
|
+
update: Entry.update,
|
|
68
|
+
readAt: (model: Model, entryId: string) =>
|
|
69
|
+
Array.findFirst(model.entries, entry => entry.id === entryId),
|
|
70
|
+
writeAt: (model, entryId, nextEntry) =>
|
|
71
|
+
modifyFields(model, {
|
|
72
|
+
entries: Array.map(entry => (entry.id === entryId ? nextEntry : entry)),
|
|
73
|
+
}),
|
|
74
|
+
toParentMessage: (entryId, message) =>
|
|
75
|
+
Message.GotEntryMessage({ entryId, message }),
|
|
76
|
+
foldOutMessage: foldEntryOutMessage,
|
|
77
|
+
})
|
|
80
78
|
|
|
81
79
|
export const update = (model: Model, message: Message) =>
|
|
82
80
|
Message.match<Update.Return<Model, Message>>(message, {
|
|
@@ -97,7 +95,7 @@ export const update = (model: Model, message: Message) =>
|
|
|
97
95
|
}),
|
|
98
96
|
|
|
99
97
|
GotEntryMessage: ({ entryId, message }) =>
|
|
100
|
-
foldEntry(
|
|
98
|
+
foldEntry(model, entryId, message),
|
|
101
99
|
})
|
|
102
100
|
|
|
103
101
|
// VALIDATION SUMMARY
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { Runtime } from 'foldkit'
|
|
2
2
|
|
|
3
|
-
import { Message, Model, init,
|
|
3
|
+
import { Message, Model, init, update, view } from './main'
|
|
4
4
|
|
|
5
5
|
const application = Runtime.makeApplication({
|
|
6
6
|
Model,
|
|
7
7
|
init,
|
|
8
8
|
update,
|
|
9
9
|
view,
|
|
10
|
-
subscriptions,
|
|
11
10
|
container: document.getElementById('root'),
|
|
12
11
|
devTools: {
|
|
13
12
|
Message,
|