create-foldkit-app 0.29.0 → 0.29.1
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/AGENTS.md +5 -112
- package/dist/templates/base/FOLDKIT.md +144 -0
- package/dist/templates/examples/api-cache/src/main.ts +36 -40
- package/dist/templates/examples/auth/src/main.ts +16 -15
- package/dist/templates/examples/auth/src/page/loggedIn/update.ts +10 -11
- package/dist/templates/examples/auth/src/page/loggedOut/page/login.ts +44 -55
- package/dist/templates/examples/auth/src/page/loggedOut/update.ts +8 -12
- package/dist/templates/examples/auth/src/update.ts +67 -73
- package/dist/templates/examples/canvas-art/src/main.ts +32 -31
- package/dist/templates/examples/charting/src/init.test.ts +6 -3
- package/dist/templates/examples/charting/src/init.ts +4 -4
- package/dist/templates/examples/charting/src/update.ts +34 -38
- package/dist/templates/examples/counter/src/main.ts +13 -13
- package/dist/templates/examples/counters/src/counter.ts +9 -8
- package/dist/templates/examples/counters/src/main.ts +20 -26
- package/dist/templates/examples/crash-view/src/main.ts +5 -3
- package/dist/templates/examples/embedding/src/main.ts +11 -9
- package/dist/templates/examples/form/src/main.ts +79 -89
- package/dist/templates/examples/generative-art/src/main.ts +6 -4
- package/dist/templates/examples/generative-art/src/update.ts +26 -23
- package/dist/templates/examples/interrupting-commands/src/main.ts +68 -66
- package/dist/templates/examples/job-application/src/main.ts +3 -4
- package/dist/templates/examples/job-application/src/step/attachments.ts +16 -19
- package/dist/templates/examples/job-application/src/step/coverLetter.ts +5 -5
- package/dist/templates/examples/job-application/src/step/education/education.ts +12 -17
- package/dist/templates/examples/job-application/src/step/education/entry.ts +29 -42
- package/dist/templates/examples/job-application/src/step/personalInfo.ts +35 -44
- package/dist/templates/examples/job-application/src/step/skills/entry.ts +15 -21
- package/dist/templates/examples/job-application/src/step/skills/skills.ts +12 -17
- package/dist/templates/examples/job-application/src/step/workHistory/entry.ts +41 -58
- package/dist/templates/examples/job-application/src/step/workHistory/workHistory.ts +12 -17
- package/dist/templates/examples/job-application/src/update.ts +26 -29
- package/dist/templates/examples/kanban/src/main.ts +3 -4
- package/dist/templates/examples/kanban/src/update.ts +31 -31
- package/dist/templates/examples/managed-resource-layer/src/main.ts +30 -34
- package/dist/templates/examples/map/src/main.ts +48 -56
- package/dist/templates/examples/pixel-art/src/comparison.bench.test.ts +34 -13
- package/dist/templates/examples/pixel-art/src/main.bench.ts +3 -3
- package/dist/templates/examples/pixel-art/src/main.ts +3 -4
- package/dist/templates/examples/pixel-art/src/update.ts +109 -100
- package/dist/templates/examples/query-sync/src/main.ts +27 -25
- package/dist/templates/examples/route-transitions/src/main.ts +46 -43
- package/dist/templates/examples/route-transitions/src/story.test.ts +11 -11
- package/dist/templates/examples/routing/src/main.ts +16 -14
- package/dist/templates/examples/routing/src/page/people.ts +23 -28
- package/dist/templates/examples/shopping-cart/src/main.ts +41 -42
- package/dist/templates/examples/shopping-cart/src/page/products.ts +28 -35
- package/dist/templates/examples/slow-warnings/src/main.ts +23 -32
- package/dist/templates/examples/snake/src/main.ts +135 -143
- package/dist/templates/examples/ssg/src/main.ts +20 -17
- package/dist/templates/examples/ssr/src/main.ts +20 -24
- package/dist/templates/examples/state-machine/src/main.ts +24 -11
- package/dist/templates/examples/state-machine/src/story.test.ts +2 -2
- package/dist/templates/examples/stopwatch/src/main.ts +42 -50
- package/dist/templates/examples/todo/src/main.ts +152 -160
- package/dist/templates/examples/ui-showcase/src/main.ts +53 -54
- package/dist/templates/examples/ui-showcase/src/scene.test.ts +2 -2
- package/dist/templates/examples/ui-showcase/src/story.test.ts +2 -2
- package/dist/templates/examples/ui-showcase/src/ui/init.ts +6 -7
- package/dist/templates/examples/ui-showcase/src/ui/update.ts +265 -336
- package/dist/templates/examples/view-transitions/src/main.ts +18 -17
- package/dist/templates/examples/weather/src/main.ts +33 -40
- package/dist/templates/examples/web-components/src/main.ts +14 -17
- package/dist/templates/examples/websocket-chat/src/main.ts +44 -50
- package/dist/templates/release.json +8 -8
- package/dist/templates/rendering/ssg/src/main.ts +20 -17
- package/dist/templates/rendering/ssr/src/main.ts +20 -24
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Array, Match as M, Option } from 'effect'
|
|
2
|
-
import {
|
|
2
|
+
import { Update } from 'foldkit'
|
|
3
3
|
import { evo } from 'foldkit/struct'
|
|
4
4
|
|
|
5
5
|
import { Dialog, Listbox, RadioGroup } from '@foldkit/ui'
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
ToolRadioGroup,
|
|
31
31
|
} from './view/toolbar'
|
|
32
32
|
|
|
33
|
-
type UpdateReturn =
|
|
33
|
+
type UpdateReturn = Update.Return<Model, Message>
|
|
34
34
|
|
|
35
35
|
const withUpdateReturn = M.withReturnType<UpdateReturn>()
|
|
36
36
|
|
|
@@ -54,11 +54,10 @@ const applyFill = (model: Model, x: number, y: number) => {
|
|
|
54
54
|
const foldErrorDialogOutMessage = M.type<Dialog.OutMessage>().pipe(
|
|
55
55
|
M.withReturnType<Update.Step<Model, Message>>(),
|
|
56
56
|
M.tagsExhaustive({
|
|
57
|
-
Opened: () => model =>
|
|
58
|
-
Closed: () => model =>
|
|
59
|
-
evo(model, { maybeExportError: () => Option.none() }),
|
|
60
|
-
|
|
61
|
-
],
|
|
57
|
+
Opened: () => model => ({ model }),
|
|
58
|
+
Closed: () => model => ({
|
|
59
|
+
model: evo(model, { maybeExportError: () => Option.none() }),
|
|
60
|
+
}),
|
|
62
61
|
}),
|
|
63
62
|
)
|
|
64
63
|
|
|
@@ -71,6 +70,15 @@ const foldErrorDialog = Update.foldChild({
|
|
|
71
70
|
foldOutMessage: foldErrorDialogOutMessage,
|
|
72
71
|
})
|
|
73
72
|
|
|
73
|
+
const foldErrorDialogOpen = Update.foldChildStep({
|
|
74
|
+
update: Dialog.open,
|
|
75
|
+
read: (model: Model) => Option.some(model.errorDialog),
|
|
76
|
+
write: (model, nextErrorDialog) =>
|
|
77
|
+
evo(model, { errorDialog: () => nextErrorDialog }),
|
|
78
|
+
toParentMessage: message => Message.GotErrorDialogMessage({ message }),
|
|
79
|
+
foldOutMessage: foldErrorDialogOutMessage,
|
|
80
|
+
})
|
|
81
|
+
|
|
74
82
|
const foldThemeListboxOutMessage: (
|
|
75
83
|
outMessage: Listbox.OutMessage,
|
|
76
84
|
) => Update.Step<Model, Message> = M.type<Listbox.OutMessage>().pipe(
|
|
@@ -82,13 +90,13 @@ const foldThemeListboxOutMessage: (
|
|
|
82
90
|
const themeIndex = Number(value)
|
|
83
91
|
const maybeNextTheme = Array.get(PALETTE_THEMES, themeIndex)
|
|
84
92
|
if (Option.isNone(maybeNextTheme)) {
|
|
85
|
-
return
|
|
93
|
+
return { model }
|
|
86
94
|
}
|
|
87
95
|
const nextModel = evo(model, {
|
|
88
96
|
paletteThemeIndex: () => themeIndex,
|
|
89
97
|
selectedColorIndex: () => DEFAULT_COLOR_INDEX,
|
|
90
98
|
})
|
|
91
|
-
return
|
|
99
|
+
return { model: nextModel, commands: [saveCanvas(nextModel)] }
|
|
92
100
|
},
|
|
93
101
|
}),
|
|
94
102
|
)
|
|
@@ -105,11 +113,10 @@ const foldThemeListbox = Update.foldChild({
|
|
|
105
113
|
const foldGridSizeConfirmDialogOutMessage = M.type<Dialog.OutMessage>().pipe(
|
|
106
114
|
M.withReturnType<Update.Step<Model, Message>>(),
|
|
107
115
|
M.tagsExhaustive({
|
|
108
|
-
Opened: () => model =>
|
|
109
|
-
Closed: () => model =>
|
|
110
|
-
evo(model, { maybePendingGridSize: () => Option.none() }),
|
|
111
|
-
|
|
112
|
-
],
|
|
116
|
+
Opened: () => model => ({ model }),
|
|
117
|
+
Closed: () => model => ({
|
|
118
|
+
model: evo(model, { maybePendingGridSize: () => Option.none() }),
|
|
119
|
+
}),
|
|
113
120
|
}),
|
|
114
121
|
)
|
|
115
122
|
|
|
@@ -123,14 +130,33 @@ const foldGridSizeConfirmDialog = Update.foldChild({
|
|
|
123
130
|
foldOutMessage: foldGridSizeConfirmDialogOutMessage,
|
|
124
131
|
})
|
|
125
132
|
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
133
|
+
const foldGridSizeConfirmDialogOpen = Update.foldChildStep({
|
|
134
|
+
update: Dialog.open,
|
|
135
|
+
read: (model: Model) => Option.some(model.gridSizeConfirmDialog),
|
|
136
|
+
write: (model, nextGridSizeConfirmDialog) =>
|
|
137
|
+
evo(model, { gridSizeConfirmDialog: () => nextGridSizeConfirmDialog }),
|
|
138
|
+
toParentMessage: message =>
|
|
139
|
+
Message.GotGridSizeConfirmDialogMessage({ message }),
|
|
140
|
+
foldOutMessage: foldGridSizeConfirmDialogOutMessage,
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
const foldGridSizeConfirmDialogClose = Update.foldChildStep({
|
|
144
|
+
update: Dialog.close,
|
|
145
|
+
read: (model: Model) => Option.some(model.gridSizeConfirmDialog),
|
|
146
|
+
write: (model, nextGridSizeConfirmDialog) =>
|
|
147
|
+
evo(model, { gridSizeConfirmDialog: () => nextGridSizeConfirmDialog }),
|
|
148
|
+
toParentMessage: message =>
|
|
149
|
+
Message.GotGridSizeConfirmDialogMessage({ message }),
|
|
150
|
+
foldOutMessage: foldGridSizeConfirmDialogOutMessage,
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
const selectTool = (model: Model, tool: Tool): UpdateReturn => ({
|
|
154
|
+
model: evo(model, { tool: () => tool }),
|
|
155
|
+
})
|
|
130
156
|
|
|
131
157
|
const selectColor = (model: Model, colorIndex: PaletteIndex): UpdateReturn => {
|
|
132
158
|
const nextModel = evo(model, { selectedColorIndex: () => colorIndex })
|
|
133
|
-
return
|
|
159
|
+
return { model: nextModel, commands: [saveCanvas(nextModel)] }
|
|
134
160
|
}
|
|
135
161
|
|
|
136
162
|
const foldToolRadioGroupOutMessage = M.type<RadioGroup.OutMessage<Tool>>().pipe(
|
|
@@ -198,32 +224,30 @@ export const update = (model: Model, message: Message) =>
|
|
|
198
224
|
PressedCell: ({ x, y }) =>
|
|
199
225
|
M.value(model.tool).pipe(
|
|
200
226
|
withUpdateReturn,
|
|
201
|
-
M.when('Brush', () =>
|
|
202
|
-
evo(model, {
|
|
227
|
+
M.when('Brush', () => ({
|
|
228
|
+
model: evo(model, {
|
|
203
229
|
grid: () => applyBrush(model, x, y),
|
|
204
230
|
undoStack: () => pushHistory(model.undoStack, model.grid),
|
|
205
231
|
redoStack: () => [],
|
|
206
232
|
isDrawing: () => true,
|
|
207
233
|
}),
|
|
208
|
-
|
|
209
|
-
]),
|
|
234
|
+
})),
|
|
210
235
|
M.when('Fill', () => {
|
|
211
236
|
const nextModel = evo(model, {
|
|
212
237
|
grid: () => applyFill(model, x, y),
|
|
213
238
|
undoStack: () => pushHistory(model.undoStack, model.grid),
|
|
214
239
|
redoStack: () => [],
|
|
215
240
|
})
|
|
216
|
-
return
|
|
241
|
+
return { model: nextModel, commands: [saveCanvas(nextModel)] }
|
|
217
242
|
}),
|
|
218
|
-
M.when('Eraser', () =>
|
|
219
|
-
evo(model, {
|
|
243
|
+
M.when('Eraser', () => ({
|
|
244
|
+
model: evo(model, {
|
|
220
245
|
grid: () => applyEraser(model, x, y),
|
|
221
246
|
undoStack: () => pushHistory(model.undoStack, model.grid),
|
|
222
247
|
redoStack: () => [],
|
|
223
248
|
isDrawing: () => true,
|
|
224
249
|
}),
|
|
225
|
-
|
|
226
|
-
]),
|
|
250
|
+
})),
|
|
227
251
|
M.exhaustive,
|
|
228
252
|
),
|
|
229
253
|
|
|
@@ -233,27 +257,30 @@ export const update = (model: Model, message: Message) =>
|
|
|
233
257
|
})
|
|
234
258
|
|
|
235
259
|
if (model.isDrawing && model.tool === 'Brush') {
|
|
236
|
-
return
|
|
260
|
+
return {
|
|
261
|
+
model: evo(withHover, { grid: () => applyBrush(model, x, y) }),
|
|
262
|
+
}
|
|
237
263
|
}
|
|
238
264
|
|
|
239
265
|
if (model.isDrawing && model.tool === 'Eraser') {
|
|
240
|
-
return
|
|
266
|
+
return {
|
|
267
|
+
model: evo(withHover, { grid: () => applyEraser(model, x, y) }),
|
|
268
|
+
}
|
|
241
269
|
}
|
|
242
270
|
|
|
243
|
-
return
|
|
271
|
+
return { model: withHover }
|
|
244
272
|
},
|
|
245
273
|
|
|
246
|
-
LeftCanvas: () =>
|
|
247
|
-
evo(model, { maybeHoveredCell: () => Option.none() }),
|
|
248
|
-
|
|
249
|
-
],
|
|
274
|
+
LeftCanvas: () => ({
|
|
275
|
+
model: evo(model, { maybeHoveredCell: () => Option.none() }),
|
|
276
|
+
}),
|
|
250
277
|
|
|
251
278
|
ReleasedMouse: () => {
|
|
252
279
|
if (!model.isDrawing) {
|
|
253
|
-
return
|
|
280
|
+
return { model }
|
|
254
281
|
}
|
|
255
282
|
const nextModel = evo(model, { isDrawing: () => false })
|
|
256
|
-
return
|
|
283
|
+
return { model: nextModel, commands: [saveCanvas(nextModel)] }
|
|
257
284
|
},
|
|
258
285
|
|
|
259
286
|
SelectedColor: ({ colorIndex }) => selectColor(model, colorIndex),
|
|
@@ -279,7 +306,7 @@ export const update = (model: Model, message: Message) =>
|
|
|
279
306
|
M.when('Both', () => 'Vertical' as const),
|
|
280
307
|
M.exhaustive,
|
|
281
308
|
)
|
|
282
|
-
return
|
|
309
|
+
return { model: evo(model, { mirrorMode: () => nextMirrorMode }) }
|
|
283
310
|
},
|
|
284
311
|
|
|
285
312
|
ToggledMirrorVertical: () => {
|
|
@@ -290,39 +317,39 @@ export const update = (model: Model, message: Message) =>
|
|
|
290
317
|
M.when('Both', () => 'Horizontal' as const),
|
|
291
318
|
M.exhaustive,
|
|
292
319
|
)
|
|
293
|
-
return
|
|
320
|
+
return { model: evo(model, { mirrorMode: () => nextMirrorMode }) }
|
|
294
321
|
},
|
|
295
322
|
|
|
296
323
|
ClickedUndo: () =>
|
|
297
324
|
Array.match(model.undoStack, {
|
|
298
|
-
onEmpty: () =>
|
|
325
|
+
onEmpty: () => ({ model }),
|
|
299
326
|
onNonEmpty: nonEmptyUndoStack => {
|
|
300
327
|
const nextModel = evo(model, {
|
|
301
328
|
grid: () => Array.lastNonEmpty(nonEmptyUndoStack),
|
|
302
329
|
undoStack: () => Array.initNonEmpty(nonEmptyUndoStack),
|
|
303
330
|
redoStack: () => [...model.redoStack, model.grid],
|
|
304
331
|
})
|
|
305
|
-
return
|
|
332
|
+
return { model: nextModel, commands: [saveCanvas(nextModel)] }
|
|
306
333
|
},
|
|
307
334
|
}),
|
|
308
335
|
|
|
309
336
|
ClickedRedo: () =>
|
|
310
337
|
Array.match(model.redoStack, {
|
|
311
|
-
onEmpty: () =>
|
|
338
|
+
onEmpty: () => ({ model }),
|
|
312
339
|
onNonEmpty: nonEmptyRedoStack => {
|
|
313
340
|
const nextModel = evo(model, {
|
|
314
341
|
grid: () => Array.lastNonEmpty(nonEmptyRedoStack),
|
|
315
342
|
undoStack: () => [...model.undoStack, model.grid],
|
|
316
343
|
redoStack: () => Array.initNonEmpty(nonEmptyRedoStack),
|
|
317
344
|
})
|
|
318
|
-
return
|
|
345
|
+
return { model: nextModel, commands: [saveCanvas(nextModel)] }
|
|
319
346
|
},
|
|
320
347
|
}),
|
|
321
348
|
|
|
322
349
|
ClickedHistoryStep: ({ stepIndex }) => {
|
|
323
350
|
const targetGrid = model.undoStack[stepIndex]
|
|
324
351
|
if (targetGrid === undefined) {
|
|
325
|
-
return
|
|
352
|
+
return { model }
|
|
326
353
|
}
|
|
327
354
|
|
|
328
355
|
const statesAfterTarget = Array.drop(model.undoStack, stepIndex + 1)
|
|
@@ -337,13 +364,13 @@ export const update = (model: Model, message: Message) =>
|
|
|
337
364
|
],
|
|
338
365
|
})
|
|
339
366
|
|
|
340
|
-
return
|
|
367
|
+
return { model: nextModel, commands: [saveCanvas(nextModel)] }
|
|
341
368
|
},
|
|
342
369
|
|
|
343
370
|
ClickedRedoStep: ({ stepIndex }) => {
|
|
344
371
|
const targetGrid = model.redoStack[stepIndex]
|
|
345
372
|
if (targetGrid === undefined) {
|
|
346
|
-
return
|
|
373
|
+
return { model }
|
|
347
374
|
}
|
|
348
375
|
|
|
349
376
|
const statesBetweenCurrentAndTarget = Array.drop(
|
|
@@ -361,7 +388,7 @@ export const update = (model: Model, message: Message) =>
|
|
|
361
388
|
redoStack: () => Array.take(model.redoStack, stepIndex),
|
|
362
389
|
})
|
|
363
390
|
|
|
364
|
-
return
|
|
391
|
+
return { model: nextModel, commands: [saveCanvas(nextModel)] }
|
|
365
392
|
},
|
|
366
393
|
|
|
367
394
|
ClickedClear: () => {
|
|
@@ -370,39 +397,33 @@ export const update = (model: Model, message: Message) =>
|
|
|
370
397
|
undoStack: () => pushHistory(model.undoStack, model.grid),
|
|
371
398
|
redoStack: () => [],
|
|
372
399
|
})
|
|
373
|
-
return
|
|
400
|
+
return { model: nextModel, commands: [saveCanvas(nextModel)] }
|
|
374
401
|
},
|
|
375
402
|
|
|
376
|
-
ClickedExport: () =>
|
|
403
|
+
ClickedExport: () => ({
|
|
377
404
|
model,
|
|
378
|
-
[
|
|
405
|
+
commands: [
|
|
379
406
|
ExportPng({
|
|
380
407
|
grid: model.grid,
|
|
381
408
|
gridSize: model.gridSize,
|
|
382
409
|
paletteThemeIndex: model.paletteThemeIndex,
|
|
383
410
|
}),
|
|
384
411
|
],
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
SucceededExportPng: () => [model, []],
|
|
412
|
+
}),
|
|
388
413
|
|
|
389
|
-
|
|
414
|
+
SucceededExportPng: () => ({ model }),
|
|
390
415
|
|
|
391
|
-
|
|
392
|
-
const [nextErrorDialog, errorDialogCommands] = Dialog.open(
|
|
393
|
-
model.errorDialog,
|
|
394
|
-
)
|
|
416
|
+
CompletedSaveCanvas: () => ({ model }),
|
|
395
417
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
418
|
+
FailedExportPng: ({ error }) =>
|
|
419
|
+
Update.combine(model, [
|
|
420
|
+
stepModel => ({
|
|
421
|
+
model: evo(stepModel, {
|
|
422
|
+
maybeExportError: () => Option.some(error),
|
|
423
|
+
}),
|
|
400
424
|
}),
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
),
|
|
404
|
-
]
|
|
405
|
-
},
|
|
425
|
+
foldErrorDialogOpen,
|
|
426
|
+
]),
|
|
406
427
|
|
|
407
428
|
GotErrorDialogMessage: ({ message }) => foldErrorDialog(model, message),
|
|
408
429
|
|
|
@@ -410,33 +431,24 @@ export const update = (model: Model, message: Message) =>
|
|
|
410
431
|
|
|
411
432
|
ConfirmedGridSizeChange: () =>
|
|
412
433
|
Option.match(model.maybePendingGridSize, {
|
|
413
|
-
onNone: () =>
|
|
414
|
-
onSome: pendingSize =>
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
}),
|
|
424
|
-
)
|
|
425
|
-
const [resizedModel] = applyGridSizeChange(model, pendingSize)
|
|
426
|
-
const nextModel = evo(resizedModel, {
|
|
427
|
-
gridSizeConfirmDialog: () => nextDialog,
|
|
428
|
-
maybePendingGridSize: () => Option.none(),
|
|
429
|
-
})
|
|
430
|
-
return [nextModel, [...mappedDialogCommands, saveCanvas(nextModel)]]
|
|
431
|
-
},
|
|
434
|
+
onNone: () => ({ model }),
|
|
435
|
+
onSome: pendingSize =>
|
|
436
|
+
Update.combine(model, [
|
|
437
|
+
stepModel => applyGridSizeChange(stepModel, pendingSize),
|
|
438
|
+
foldGridSizeConfirmDialogClose,
|
|
439
|
+
stepModel => ({
|
|
440
|
+
model: stepModel,
|
|
441
|
+
commands: [saveCanvas(stepModel)],
|
|
442
|
+
}),
|
|
443
|
+
]),
|
|
432
444
|
}),
|
|
433
445
|
|
|
434
446
|
GotGridSizeConfirmDialogMessage: ({ message }) =>
|
|
435
447
|
foldGridSizeConfirmDialog(model, message),
|
|
436
448
|
})
|
|
437
449
|
|
|
438
|
-
const applyGridSizeChange = (model: Model, size: number): UpdateReturn =>
|
|
439
|
-
evo(model, {
|
|
450
|
+
const applyGridSizeChange = (model: Model, size: number): UpdateReturn => ({
|
|
451
|
+
model: evo(model, {
|
|
440
452
|
grid: () => createEmptyGrid(size),
|
|
441
453
|
gridSize: () => size,
|
|
442
454
|
undoStack: () => [],
|
|
@@ -444,26 +456,23 @@ const applyGridSizeChange = (model: Model, size: number): UpdateReturn => [
|
|
|
444
456
|
isDrawing: () => false,
|
|
445
457
|
maybeHoveredCell: () => Option.none(),
|
|
446
458
|
}),
|
|
447
|
-
|
|
448
|
-
]
|
|
459
|
+
})
|
|
449
460
|
|
|
450
461
|
const requestGridSizeChange = (model: Model, size: number): UpdateReturn => {
|
|
451
462
|
if (size === model.gridSize) {
|
|
452
|
-
return
|
|
463
|
+
return { model }
|
|
453
464
|
}
|
|
454
465
|
|
|
455
466
|
if (isGridEmpty(model.grid)) {
|
|
456
467
|
return applyGridSizeChange(model, size)
|
|
457
468
|
}
|
|
458
469
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
470
|
+
return Update.combine(model, [
|
|
471
|
+
stepModel => ({
|
|
472
|
+
model: evo(stepModel, {
|
|
473
|
+
maybePendingGridSize: () => Option.some(size),
|
|
474
|
+
}),
|
|
464
475
|
}),
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
),
|
|
468
|
-
]
|
|
476
|
+
foldGridSizeConfirmDialogOpen,
|
|
477
|
+
])
|
|
469
478
|
}
|
|
@@ -190,14 +190,13 @@ export const init: Runtime.RoutingApplicationInit<Model, Message> = (
|
|
|
190
190
|
) => {
|
|
191
191
|
const route = urlToAppRoute(url)
|
|
192
192
|
|
|
193
|
-
return
|
|
194
|
-
{
|
|
193
|
+
return {
|
|
194
|
+
model: {
|
|
195
195
|
route,
|
|
196
196
|
dietListbox: Listbox.init({ id: 'diet-filter' }),
|
|
197
197
|
periodListbox: Listbox.init({ id: 'period-filter' }),
|
|
198
198
|
},
|
|
199
|
-
|
|
200
|
-
]
|
|
199
|
+
}
|
|
201
200
|
}
|
|
202
201
|
|
|
203
202
|
// UPDATE
|
|
@@ -267,7 +266,7 @@ const LoadExternal = Command.define('LoadExternal', {
|
|
|
267
266
|
load(href).pipe(Effect.as(Message.CompletedLoadExternal())),
|
|
268
267
|
})
|
|
269
268
|
|
|
270
|
-
type UpdateReturn =
|
|
269
|
+
type UpdateReturn = Update.Return<Model, Message>
|
|
271
270
|
const withUpdateReturn = M.withReturnType<UpdateReturn>()
|
|
272
271
|
|
|
273
272
|
const DietListbox = Listbox.create<string>()
|
|
@@ -282,15 +281,15 @@ const foldDietListboxOutMessage: (
|
|
|
282
281
|
({ value }) =>
|
|
283
282
|
model => {
|
|
284
283
|
const fields = routeToBrowseFields(model.route)
|
|
285
|
-
return
|
|
284
|
+
return {
|
|
286
285
|
model,
|
|
287
|
-
[
|
|
286
|
+
commands: [
|
|
288
287
|
ReplaceFilters({
|
|
289
288
|
...fields,
|
|
290
289
|
diet: selectionToParam(Option.some(value), Diet),
|
|
291
290
|
}),
|
|
292
291
|
],
|
|
293
|
-
|
|
292
|
+
}
|
|
294
293
|
},
|
|
295
294
|
}),
|
|
296
295
|
)
|
|
@@ -313,15 +312,15 @@ const foldPeriodListboxOutMessage: (
|
|
|
313
312
|
({ value }) =>
|
|
314
313
|
model => {
|
|
315
314
|
const fields = routeToBrowseFields(model.route)
|
|
316
|
-
return
|
|
315
|
+
return {
|
|
317
316
|
model,
|
|
318
|
-
[
|
|
317
|
+
commands: [
|
|
319
318
|
ReplaceFilters({
|
|
320
319
|
...fields,
|
|
321
320
|
period: selectionToParam(Option.some(value), Period),
|
|
322
321
|
}),
|
|
323
322
|
],
|
|
324
|
-
|
|
323
|
+
}
|
|
325
324
|
},
|
|
326
325
|
}),
|
|
327
326
|
)
|
|
@@ -337,54 +336,57 @@ const foldPeriodListbox = Update.foldChild({
|
|
|
337
336
|
|
|
338
337
|
export const update = (model: Model, message: Message) =>
|
|
339
338
|
Message.match<UpdateReturn>(message, {
|
|
340
|
-
CompletedNavigateInternal: () =>
|
|
341
|
-
CompletedLoadExternal: () =>
|
|
342
|
-
CompletedReplaceFilters: () =>
|
|
339
|
+
CompletedNavigateInternal: () => ({ model }),
|
|
340
|
+
CompletedLoadExternal: () => ({ model }),
|
|
341
|
+
CompletedReplaceFilters: () => ({ model }),
|
|
343
342
|
|
|
344
343
|
ClickedLink: ({ request }) =>
|
|
345
344
|
M.value(request).pipe(
|
|
346
345
|
withUpdateReturn,
|
|
347
346
|
M.tagsExhaustive({
|
|
348
|
-
Internal: ({ url }) =>
|
|
347
|
+
Internal: ({ url }) => ({
|
|
349
348
|
model,
|
|
350
|
-
[NavigateInternal({ url: urlToString(url) })],
|
|
351
|
-
|
|
352
|
-
External: ({ href }) =>
|
|
349
|
+
commands: [NavigateInternal({ url: urlToString(url) })],
|
|
350
|
+
}),
|
|
351
|
+
External: ({ href }) => ({
|
|
352
|
+
model,
|
|
353
|
+
commands: [LoadExternal({ href })],
|
|
354
|
+
}),
|
|
353
355
|
}),
|
|
354
356
|
),
|
|
355
357
|
|
|
356
358
|
ChangedUrl: ({ url }) => {
|
|
357
359
|
const nextRoute = urlToAppRoute(url)
|
|
358
360
|
|
|
359
|
-
return
|
|
361
|
+
return { model: evo(model, { route: () => nextRoute }) }
|
|
360
362
|
},
|
|
361
363
|
|
|
362
364
|
ChangedSearchInput: ({ value }) => {
|
|
363
365
|
const fields = routeToBrowseFields(model.route)
|
|
364
366
|
|
|
365
|
-
return
|
|
367
|
+
return {
|
|
366
368
|
model,
|
|
367
|
-
[
|
|
369
|
+
commands: [
|
|
368
370
|
ReplaceFilters({
|
|
369
371
|
...fields,
|
|
370
372
|
search: Option.liftPredicate(value, String.isNonEmpty),
|
|
371
373
|
}),
|
|
372
374
|
],
|
|
373
|
-
|
|
375
|
+
}
|
|
374
376
|
},
|
|
375
377
|
|
|
376
378
|
ClickedColumnHeader: ({ column }) => {
|
|
377
379
|
const fields = routeToBrowseFields(model.route)
|
|
378
380
|
|
|
379
|
-
return
|
|
381
|
+
return {
|
|
380
382
|
model,
|
|
381
|
-
[
|
|
383
|
+
commands: [
|
|
382
384
|
ReplaceFilters({
|
|
383
385
|
...fields,
|
|
384
386
|
sorting: nextSorting(fields.sorting, column),
|
|
385
387
|
}),
|
|
386
388
|
],
|
|
387
|
-
|
|
389
|
+
}
|
|
388
390
|
},
|
|
389
391
|
|
|
390
392
|
GotDietListboxMessage: ({ message }) => foldDietListbox(model, message),
|