create-foldkit-app 0.35.1 → 0.35.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/dist/templates/base/FOLDKIT.md +2 -2
  2. package/dist/templates/examples/api-cache/package.json +2 -2
  3. package/dist/templates/examples/api-cache/src/main.fixture.ts +4 -4
  4. package/dist/templates/examples/api-cache/src/main.ts +12 -12
  5. package/dist/templates/examples/api-cache/src/story.test.ts +6 -6
  6. package/dist/templates/examples/auth/package.json +2 -2
  7. package/dist/templates/examples/auth/src/page/loggedOut/page/login.scene.test.ts +2 -2
  8. package/dist/templates/examples/auth/src/page/loggedOut/page/login.story.test.ts +2 -2
  9. package/dist/templates/examples/auth/src/page/loggedOut/page/login.ts +5 -5
  10. package/dist/templates/examples/auth/src/page/loggedOut/update.ts +2 -2
  11. package/dist/templates/examples/auth/src/scene.test.ts +2 -2
  12. package/dist/templates/examples/auth/src/update.ts +3 -3
  13. package/dist/templates/examples/canvas-art/package.json +2 -2
  14. package/dist/templates/examples/canvas-art/src/main.ts +6 -6
  15. package/dist/templates/examples/canvas-art/src/scene.test.ts +3 -3
  16. package/dist/templates/examples/canvas-art/src/story.test.ts +3 -3
  17. package/dist/templates/examples/charting/package.json +2 -2
  18. package/dist/templates/examples/charting/src/main.fixture.ts +2 -2
  19. package/dist/templates/examples/charting/src/scene.test.ts +3 -3
  20. package/dist/templates/examples/charting/src/story.test.ts +2 -2
  21. package/dist/templates/examples/charting/src/update.ts +18 -16
  22. package/dist/templates/examples/counter/package.json +2 -2
  23. package/dist/templates/examples/counter/src/main.ts +4 -4
  24. package/dist/templates/examples/counters/package.json +2 -2
  25. package/dist/templates/examples/counters/src/counter.ts +3 -3
  26. package/dist/templates/examples/counters/src/main.ts +7 -5
  27. package/dist/templates/examples/crash-view/package.json +2 -2
  28. package/dist/templates/examples/embedding/package.json +2 -2
  29. package/dist/templates/examples/embedding/src/main.ts +5 -3
  30. package/dist/templates/examples/embedding/src/scene.test.ts +2 -2
  31. package/dist/templates/examples/embedding/src/story.test.ts +2 -2
  32. package/dist/templates/examples/form/package.json +2 -2
  33. package/dist/templates/examples/form/src/main.ts +9 -9
  34. package/dist/templates/examples/form/src/scene.test.ts +5 -5
  35. package/dist/templates/examples/form/src/story.test.ts +4 -4
  36. package/dist/templates/examples/generative-art/package.json +2 -2
  37. package/dist/templates/examples/generative-art/src/scene.test.ts +2 -2
  38. package/dist/templates/examples/generative-art/src/story.test.ts +3 -3
  39. package/dist/templates/examples/generative-art/src/update.ts +11 -11
  40. package/dist/templates/examples/interrupting-commands/package.json +2 -2
  41. package/dist/templates/examples/interrupting-commands/src/main.ts +8 -6
  42. package/dist/templates/examples/job-application/package.json +2 -2
  43. package/dist/templates/examples/job-application/src/main.fixture.ts +9 -9
  44. package/dist/templates/examples/job-application/src/scene.test.ts +13 -13
  45. package/dist/templates/examples/job-application/src/step/attachments/attachments.ts +7 -7
  46. package/dist/templates/examples/job-application/src/step/coverLetter/coverLetter.ts +2 -2
  47. package/dist/templates/examples/job-application/src/step/education/education.ts +6 -6
  48. package/dist/templates/examples/job-application/src/step/education/entry/entry.ts +14 -8
  49. package/dist/templates/examples/job-application/src/step/personalInfo/personalInfo.ts +20 -15
  50. package/dist/templates/examples/job-application/src/step/personalInfo/story.test.ts +2 -2
  51. package/dist/templates/examples/job-application/src/step/skills/entry/entry.ts +7 -5
  52. package/dist/templates/examples/job-application/src/step/skills/skills.ts +6 -6
  53. package/dist/templates/examples/job-application/src/step/workHistory/entry/entry.ts +13 -12
  54. package/dist/templates/examples/job-application/src/step/workHistory/workHistory.ts +6 -6
  55. package/dist/templates/examples/job-application/src/story.test.ts +10 -10
  56. package/dist/templates/examples/job-application/src/update.ts +25 -18
  57. package/dist/templates/examples/kanban/package.json +2 -2
  58. package/dist/templates/examples/kanban/src/domain/column.ts +9 -6
  59. package/dist/templates/examples/kanban/src/update.ts +8 -8
  60. package/dist/templates/examples/managed-resource-layer/package.json +2 -2
  61. package/dist/templates/examples/managed-resource-layer/src/main.ts +11 -7
  62. package/dist/templates/examples/managed-resource-layer/src/story.test.ts +3 -3
  63. package/dist/templates/examples/map/package.json +2 -2
  64. package/dist/templates/examples/map/src/main.fixture.ts +2 -2
  65. package/dist/templates/examples/map/src/main.ts +11 -11
  66. package/dist/templates/examples/map/src/scene.test.ts +4 -4
  67. package/dist/templates/examples/map/src/story.test.ts +4 -4
  68. package/dist/templates/examples/pixel-art/package.json +2 -2
  69. package/dist/templates/examples/pixel-art/src/comparison.bench.test.ts +2 -2
  70. package/dist/templates/examples/pixel-art/src/main.bench.ts +7 -3
  71. package/dist/templates/examples/pixel-art/src/scene.test.ts +5 -5
  72. package/dist/templates/examples/pixel-art/src/story.test.ts +4 -4
  73. package/dist/templates/examples/pixel-art/src/subscription.ts +2 -2
  74. package/dist/templates/examples/pixel-art/src/update.ts +49 -33
  75. package/dist/templates/examples/query-sync/package.json +2 -2
  76. package/dist/templates/examples/query-sync/src/main.ts +4 -4
  77. package/dist/templates/examples/query-sync/src/scene.test.ts +4 -4
  78. package/dist/templates/examples/query-sync/src/story.test.ts +2 -2
  79. package/dist/templates/examples/route-transitions/package.json +2 -2
  80. package/dist/templates/examples/route-transitions/src/main.ts +10 -10
  81. package/dist/templates/examples/route-transitions/src/story.test.ts +10 -6
  82. package/dist/templates/examples/routing/package.json +2 -2
  83. package/dist/templates/examples/routing/src/main.ts +13 -17
  84. package/dist/templates/examples/routing/src/page/people.ts +4 -4
  85. package/dist/templates/examples/shopping-cart/package.json +2 -2
  86. package/dist/templates/examples/shopping-cart/src/domain/cart.ts +4 -4
  87. package/dist/templates/examples/shopping-cart/src/main.ts +12 -12
  88. package/dist/templates/examples/shopping-cart/src/page/products.ts +2 -2
  89. package/dist/templates/examples/shopping-cart/src/scene.test.ts +10 -8
  90. package/dist/templates/examples/shopping-cart/src/story.test.ts +7 -7
  91. package/dist/templates/examples/slow-warnings/package.json +2 -2
  92. package/dist/templates/examples/slow-warnings/src/handleSlow.test.ts +2 -2
  93. package/dist/templates/examples/slow-warnings/src/main.ts +8 -8
  94. package/dist/templates/examples/slow-warnings/src/scene.test.ts +2 -2
  95. package/dist/templates/examples/slow-warnings/src/story.test.ts +2 -2
  96. package/dist/templates/examples/snake/package.json +2 -2
  97. package/dist/templates/examples/snake/src/main.ts +10 -10
  98. package/dist/templates/examples/snake/src/scene.test.ts +10 -5
  99. package/dist/templates/examples/snake/src/story.test.ts +6 -6
  100. package/dist/templates/examples/ssg/package.json +2 -2
  101. package/dist/templates/examples/ssg/src/main.ts +3 -3
  102. package/dist/templates/examples/ssr/package.json +4 -4
  103. package/dist/templates/examples/ssr/src/main.ts +3 -3
  104. package/dist/templates/examples/state-machine/package.json +2 -2
  105. package/dist/templates/examples/state-machine/src/main.ts +14 -10
  106. package/dist/templates/examples/stopwatch/package.json +2 -2
  107. package/dist/templates/examples/stopwatch/src/main.ts +5 -5
  108. package/dist/templates/examples/stopwatch/src/story.test.ts +2 -2
  109. package/dist/templates/examples/todo/package.json +2 -2
  110. package/dist/templates/examples/todo/src/main.ts +17 -17
  111. package/dist/templates/examples/todo/src/scene.test.ts +4 -4
  112. package/dist/templates/examples/todo/src/story.test.ts +22 -16
  113. package/dist/templates/examples/ui-showcase/package.json +2 -2
  114. package/dist/templates/examples/ui-showcase/src/main.ts +8 -5
  115. package/dist/templates/examples/ui-showcase/src/story.test.ts +3 -3
  116. package/dist/templates/examples/ui-showcase/src/ui/init.ts +4 -1
  117. package/dist/templates/examples/ui-showcase/src/ui/subscriptions.ts +10 -0
  118. package/dist/templates/examples/ui-showcase/src/ui/update.ts +119 -91
  119. package/dist/templates/examples/ui-showcase/src/ui/view/toast.ts +20 -3
  120. package/dist/templates/examples/view-transitions/package.json +2 -2
  121. package/dist/templates/examples/view-transitions/src/main.ts +3 -3
  122. package/dist/templates/examples/weather/package.json +2 -2
  123. package/dist/templates/examples/weather/src/main.ts +5 -5
  124. package/dist/templates/examples/web-components/package.json +2 -2
  125. package/dist/templates/examples/web-components/src/main.ts +4 -4
  126. package/dist/templates/examples/websocket-chat/package.json +2 -2
  127. package/dist/templates/examples/websocket-chat/src/main.ts +8 -8
  128. package/dist/templates/examples/websocket-chat/src/scene.test.ts +18 -6
  129. package/dist/templates/examples/websocket-chat/src/story.test.ts +15 -9
  130. package/dist/templates/release.json +13 -13
  131. package/dist/templates/rendering/ssg/src/main.ts +3 -3
  132. package/dist/templates/rendering/ssr/scripts/serve.ts +2 -2
  133. package/dist/templates/rendering/ssr/src/main.ts +3 -3
  134. package/package.json +5 -5
@@ -16,7 +16,7 @@ import type { Document, Html } from 'foldkit/html'
16
16
  import { HtmlBuilder } from 'foldkit/html'
17
17
  import { defineMessageUnion } from 'foldkit/message'
18
18
  import { defineTaggedUnion } from 'foldkit/schema'
19
- import { evo } from 'foldkit/struct'
19
+ import { modifyFields } from 'foldkit/struct'
20
20
  import type { Map as MapInstance } from 'maplibre-gl'
21
21
  import maplibreWorkerUrl from 'maplibre-gl/dist/maplibre-gl-worker.mjs?worker&url'
22
22
 
@@ -210,19 +210,19 @@ const findLocation = (
210
210
  export const update = (model: Model, message: Message) =>
211
211
  Message.match<Update.Return<Model, Message>>(message, {
212
212
  SucceededMountMap: ({ hostId }) => ({
213
- model: evo(model, { maybeMapHostId: () => Option.some(hostId) }),
213
+ model: modifyFields(model, { maybeMapHostId: () => Option.some(hostId) }),
214
214
  }),
215
215
 
216
216
  FailedMountMap: ({ reason }) => ({
217
- model: evo(model, { maybeMapError: () => Option.some(reason) }),
217
+ model: modifyFields(model, { maybeMapError: () => Option.some(reason) }),
218
218
  }),
219
219
 
220
220
  MovedMap: ({ bounds }) => ({
221
- model: evo(model, { maybeBounds: () => Option.some(bounds) }),
221
+ model: modifyFields(model, { maybeBounds: () => Option.some(bounds) }),
222
222
  }),
223
223
 
224
224
  ClickedMarker: ({ locationId }) => ({
225
- model: evo(model, {
225
+ model: modifyFields(model, {
226
226
  maybeSelectedLocationId: () => Option.some(locationId),
227
227
  }),
228
228
  }),
@@ -231,7 +231,7 @@ export const update = (model: Model, message: Message) =>
231
231
  Option.match(findLocation(model, locationId), {
232
232
  onNone: () => ({ model }),
233
233
  onSome: ({ lng, lat }) => ({
234
- model: evo(model, {
234
+ model: modifyFields(model, {
235
235
  maybeSelectedLocationId: () => Option.some(locationId),
236
236
  }),
237
237
  commands: [
@@ -246,25 +246,25 @@ export const update = (model: Model, message: Message) =>
246
246
  }),
247
247
 
248
248
  UpdatedSearchQuery: ({ value }) => ({
249
- model: evo(model, { searchQuery: () => value }),
249
+ model: modifyFields(model, { searchQuery: () => value }),
250
250
  }),
251
251
 
252
252
  ClickedFindMe: () => ({
253
- model: evo(model, {
253
+ model: modifyFields(model, {
254
254
  geolocateState: () => GeolocateState.Locating(),
255
255
  }),
256
256
  commands: [LockBodyScroll(), Geolocate()],
257
257
  }),
258
258
 
259
259
  DismissedGeolocate: () => ({
260
- model: evo(model, {
260
+ model: modifyFields(model, {
261
261
  geolocateState: () => GeolocateState.Idle(),
262
262
  }),
263
263
  commands: [UnlockBodyScroll()],
264
264
  }),
265
265
 
266
266
  SucceededGeolocate: ({ lng, lat }) => ({
267
- model: evo(model, {
267
+ model: modifyFields(model, {
268
268
  maybeUserLocation: () => Option.some({ lng, lat }),
269
269
  geolocateState: () => GeolocateState.Idle(),
270
270
  }),
@@ -280,7 +280,7 @@ export const update = (model: Model, message: Message) =>
280
280
  }),
281
281
 
282
282
  FailedGeolocate: ({ reason }) => ({
283
- model: evo(model, {
283
+ model: modifyFields(model, {
284
284
  geolocateState: () => GeolocateState.Failed({ reason }),
285
285
  }),
286
286
  }),
@@ -11,7 +11,7 @@ import {
11
11
  text,
12
12
  type,
13
13
  } from 'foldkit/scene'
14
- import { evo } from 'foldkit/struct'
14
+ import { modifyFields } from 'foldkit/struct'
15
15
  import { describe, test } from 'vitest'
16
16
 
17
17
  import {
@@ -93,7 +93,7 @@ describe('view', () => {
93
93
  scene(
94
94
  { update, view },
95
95
  given(
96
- evo(mountedModel, {
96
+ modifyFields(mountedModel, {
97
97
  geolocateState: () =>
98
98
  GeolocateState.Failed({
99
99
  reason: 'Permission denied',
@@ -112,7 +112,7 @@ describe('view', () => {
112
112
  scene(
113
113
  { update, view },
114
114
  given(
115
- evo(initialModel, {
115
+ modifyFields(initialModel, {
116
116
  maybeMapError: () => Option.some('Network timeout'),
117
117
  }),
118
118
  ),
@@ -126,7 +126,7 @@ describe('view', () => {
126
126
  scene(
127
127
  { update, view },
128
128
  given(
129
- evo(mountedModel, {
129
+ modifyFields(mountedModel, {
130
130
  maybeBounds: () =>
131
131
  Option.some({
132
132
  west: -180,
@@ -1,6 +1,6 @@
1
1
  import { Option } from 'effect'
2
2
  import { Command, given, message, model, story } from 'foldkit/story'
3
- import { evo } from 'foldkit/struct'
3
+ import { modifyFields } from 'foldkit/struct'
4
4
  import { expect, test } from 'vitest'
5
5
 
6
6
  import {
@@ -141,7 +141,7 @@ test('a successful geolocation result clears the locating state and flies the ma
141
141
  story(
142
142
  update,
143
143
  given(
144
- evo(mountedModel, {
144
+ modifyFields(mountedModel, {
145
145
  geolocateState: () => GeolocateState.Locating(),
146
146
  }),
147
147
  ),
@@ -162,7 +162,7 @@ test('a failed geolocation result surfaces the reason in the geolocate state', (
162
162
  story(
163
163
  update,
164
164
  given(
165
- evo(initialModel, {
165
+ modifyFields(initialModel, {
166
166
  geolocateState: () => GeolocateState.Locating(),
167
167
  }),
168
168
  ),
@@ -180,7 +180,7 @@ test('dismissing the geolocate overlay returns to idle', () => {
180
180
  story(
181
181
  update,
182
182
  given(
183
- evo(initialModel, {
183
+ modifyFields(initialModel, {
184
184
  geolocateState: () => GeolocateState.Failed({ reason: 'Timed out' }),
185
185
  }),
186
186
  ),
@@ -10,10 +10,10 @@
10
10
  "bench": "vitest run --config vitest.bench.config.ts"
11
11
  },
12
12
  "dependencies": {
13
- "@effect/platform-browser": "4.0.0-rc.115",
13
+ "@effect/platform-browser": "4.0.0-rc.116",
14
14
  "@foldkit/ui": "workspace:*",
15
15
  "clsx": "^2.1.1",
16
- "effect": "4.0.0-rc.115",
16
+ "effect": "4.0.0-rc.116",
17
17
  "foldkit": "workspace:*"
18
18
  },
19
19
  "devDependencies": {
@@ -4,7 +4,7 @@
4
4
  * Run: pnpm --filter pixel-art-example exec vitest run src/comparison.bench.ts
5
5
  */
6
6
  import { Option } from 'effect'
7
- import { evo } from 'foldkit/struct'
7
+ import { modifyFields } from 'foldkit/struct'
8
8
  import { test } from 'vitest'
9
9
 
10
10
  import { Dialog, Listbox } from '@foldkit/ui'
@@ -162,7 +162,7 @@ test('benchmark', () => {
162
162
  {
163
163
  name: 'Flood fill (16\u00d716)',
164
164
  foldkit: () => {
165
- const m: Model = evo(foldkitModel, { tool: () => 'Fill' })
165
+ const m: Model = modifyFields(foldkitModel, { tool: () => 'Fill' })
166
166
  update(m, Message.PressedCell({ x: 0, y: 0 }))
167
167
  },
168
168
  react: () => {
@@ -1,5 +1,5 @@
1
1
  import { Option } from 'effect'
2
- import { evo } from 'foldkit/struct'
2
+ import { modifyFields } from 'foldkit/struct'
3
3
  import { describe, test } from 'vitest'
4
4
 
5
5
  import { Dialog, Listbox, RadioGroup } from '@foldkit/ui'
@@ -82,7 +82,9 @@ describe('update: single operations', () => {
82
82
 
83
83
  test('flood fill (empty grid)', async ({ bench }) => {
84
84
  await bench('flood fill (empty grid)', () => {
85
- const fillModel: Model = evo(initialModel, { tool: () => 'Fill' })
85
+ const fillModel: Model = modifyFields(initialModel, {
86
+ tool: () => 'Fill',
87
+ })
86
88
  dispatch(fillModel, Message.PressedCell({ x: 0, y: 0 }))
87
89
  }).run()
88
90
  })
@@ -135,7 +137,9 @@ describe('update: paint sequence (16x16 grid)', () => {
135
137
 
136
138
  test('paint 50 cells with mirror mode', async ({ bench }) => {
137
139
  await bench('paint 50 cells with mirror mode', () => {
138
- let model: Model = evo(initialModel, { mirrorMode: () => 'Both' })
140
+ let model: Model = modifyFields(initialModel, {
141
+ mirrorMode: () => 'Both',
142
+ })
139
143
  for (let i = 0; i < 50; i++) {
140
144
  const x = (i * 7 + 3) % GRID_SIZE
141
145
  const y = (i * 11 + 5) % GRID_SIZE
@@ -9,7 +9,7 @@ import {
9
9
  scene,
10
10
  text,
11
11
  } from 'foldkit/scene'
12
- import { evo } from 'foldkit/struct'
12
+ import { modifyFields } from 'foldkit/struct'
13
13
  import { describe, test } from 'vitest'
14
14
 
15
15
  import { Dialog, Listbox, RadioGroup } from '@foldkit/ui'
@@ -53,7 +53,7 @@ const createTestModel = (): Model => ({
53
53
  })
54
54
 
55
55
  const createPaintedModel = (): Model =>
56
- evo(createTestModel(), {
56
+ modifyFields(createTestModel(), {
57
57
  grid: () =>
58
58
  createEmptyGrid(4).map((row, y) =>
59
59
  row.map((cell, x) =>
@@ -186,7 +186,7 @@ describe('history panel', () => {
186
186
  })
187
187
 
188
188
  test('undo enables after painting and re-disables after undoing', () => {
189
- const modelWithHistory: Model = evo(createTestModel(), {
189
+ const modelWithHistory: Model = modifyFields(createTestModel(), {
190
190
  grid: () =>
191
191
  createEmptyGrid(4).map((row, y) =>
192
192
  row.map((cell, x) =>
@@ -228,7 +228,7 @@ describe('grid size change', () => {
228
228
  })
229
229
 
230
230
  test('confirming grid size change closes dialog and saves canvas', () => {
231
- const modelWithPendingResize: Model = evo(createTestModel(), {
231
+ const modelWithPendingResize: Model = modifyFields(createTestModel(), {
232
232
  maybePendingGridSize: () => Option.some(8),
233
233
  gridSizeConfirmDialog: () =>
234
234
  Dialog.boot({
@@ -254,7 +254,7 @@ describe('grid size change', () => {
254
254
  })
255
255
 
256
256
  test('cancelling grid size change keeps current size', () => {
257
- const modelWithPendingResize: Model = evo(createTestModel(), {
257
+ const modelWithPendingResize: Model = modifyFields(createTestModel(), {
258
258
  maybePendingGridSize: () => Option.some(8),
259
259
  gridSizeConfirmDialog: () =>
260
260
  Dialog.boot({
@@ -1,6 +1,6 @@
1
1
  import { Equal, Option } from 'effect'
2
2
  import { Command, given, message, model, story } from 'foldkit/story'
3
- import { evo } from 'foldkit/struct'
3
+ import { modifyFields } from 'foldkit/struct'
4
4
  import { describe, expect, test } from 'vitest'
5
5
 
6
6
  import { Dialog, Listbox, RadioGroup } from '@foldkit/ui'
@@ -254,7 +254,7 @@ describe('fill tool', () => {
254
254
  const gridWithBarrier = createEmptyGrid(4).map(row =>
255
255
  row.map((cell, x) => (x === 2 ? Option.some<PaletteIndex>(1) : cell)),
256
256
  )
257
- const modelWithBarrier = evo(emptyModel, {
257
+ const modelWithBarrier = modifyFields(emptyModel, {
258
258
  grid: () => gridWithBarrier,
259
259
  })
260
260
 
@@ -290,7 +290,7 @@ describe('grid size', () => {
290
290
  })
291
291
 
292
292
  test('painted canvas opens confirmation dialog', () => {
293
- const paintedModel: Model = evo(emptyModel, {
293
+ const paintedModel: Model = modifyFields(emptyModel, {
294
294
  grid: () =>
295
295
  createEmptyGrid(4).map((row, y) =>
296
296
  row.map((cell, x) =>
@@ -313,7 +313,7 @@ describe('grid size', () => {
313
313
  })
314
314
 
315
315
  test('confirming grid size change resets canvas and history', () => {
316
- const modelWithPending: Model = evo(emptyModel, {
316
+ const modelWithPending: Model = modifyFields(emptyModel, {
317
317
  maybePendingGridSize: () => Option.some(8),
318
318
  gridSizeConfirmDialog: () =>
319
319
  Dialog.boot({
@@ -43,7 +43,7 @@ export const subscriptions = Subscription.make<Model, Message>()(entry => ({
43
43
  Subscription.fromEventFilterMapPreventDefault({
44
44
  target: document,
45
45
  type: 'keydown',
46
- toMessage: toUndoRedoMessage,
46
+ filterMapEvent: toUndoRedoMessage,
47
47
  }),
48
48
  ),
49
49
 
@@ -51,7 +51,7 @@ export const subscriptions = Subscription.make<Model, Message>()(entry => ({
51
51
  Subscription.fromEventFilterMap({
52
52
  target: document,
53
53
  type: 'keydown',
54
- toMessage: toToolMessage,
54
+ filterMapEvent: toToolMessage,
55
55
  }),
56
56
  ),
57
57
 
@@ -1,6 +1,6 @@
1
1
  import { Array, Match, Option } from 'effect'
2
2
  import { Update } from 'foldkit'
3
- import { evo } from 'foldkit/struct'
3
+ import { modifyFields } from 'foldkit/struct'
4
4
 
5
5
  import { Dialog, Listbox, RadioGroup } from '@foldkit/ui'
6
6
 
@@ -56,7 +56,7 @@ const foldErrorDialogOutMessage = Dialog.OutMessage.match<
56
56
  >({
57
57
  Opened: () => model => ({ model }),
58
58
  Closed: () => model => ({
59
- model: evo(model, { maybeExportError: () => Option.none() }),
59
+ model: modifyFields(model, { maybeExportError: () => Option.none() }),
60
60
  }),
61
61
  })
62
62
 
@@ -64,7 +64,7 @@ const foldErrorDialog = Update.foldChild({
64
64
  update: Dialog.update,
65
65
  read: (model: Model) => Option.some(model.errorDialog),
66
66
  write: (model, nextErrorDialog) =>
67
- evo(model, { errorDialog: () => nextErrorDialog }),
67
+ modifyFields(model, { errorDialog: () => nextErrorDialog }),
68
68
  toParentMessage: message => Message.GotErrorDialogMessage({ message }),
69
69
  foldOutMessage: foldErrorDialogOutMessage,
70
70
  })
@@ -73,7 +73,7 @@ const foldErrorDialogOpen = Update.foldChildStep({
73
73
  update: Dialog.open,
74
74
  read: (model: Model) => Option.some(model.errorDialog),
75
75
  write: (model, nextErrorDialog) =>
76
- evo(model, { errorDialog: () => nextErrorDialog }),
76
+ modifyFields(model, { errorDialog: () => nextErrorDialog }),
77
77
  toParentMessage: message => Message.GotErrorDialogMessage({ message }),
78
78
  foldOutMessage: foldErrorDialogOutMessage,
79
79
  })
@@ -89,7 +89,7 @@ const foldThemeListboxOutMessage = Listbox.OutMessage.match<
89
89
  if (Option.isNone(maybeNextTheme)) {
90
90
  return { model }
91
91
  }
92
- const nextModel = evo(model, {
92
+ const nextModel = modifyFields(model, {
93
93
  paletteThemeIndex: () => themeIndex,
94
94
  selectedColorIndex: () => DEFAULT_COLOR_INDEX,
95
95
  })
@@ -101,7 +101,7 @@ const foldThemeListbox = Update.foldChild({
101
101
  update: ThemeListbox.update,
102
102
  read: (model: Model) => Option.some(model.themeListbox),
103
103
  write: (model, nextThemeListbox) =>
104
- evo(model, { themeListbox: () => nextThemeListbox }),
104
+ modifyFields(model, { themeListbox: () => nextThemeListbox }),
105
105
  toParentMessage: message => Message.GotThemeListboxMessage({ message }),
106
106
  foldOutMessage: foldThemeListboxOutMessage,
107
107
  })
@@ -111,7 +111,7 @@ const foldGridSizeConfirmDialogOutMessage = Dialog.OutMessage.match<
111
111
  >({
112
112
  Opened: () => model => ({ model }),
113
113
  Closed: () => model => ({
114
- model: evo(model, { maybePendingGridSize: () => Option.none() }),
114
+ model: modifyFields(model, { maybePendingGridSize: () => Option.none() }),
115
115
  }),
116
116
  })
117
117
 
@@ -119,7 +119,9 @@ const foldGridSizeConfirmDialog = Update.foldChild({
119
119
  update: Dialog.update,
120
120
  read: (model: Model) => Option.some(model.gridSizeConfirmDialog),
121
121
  write: (model, nextGridSizeConfirmDialog) =>
122
- evo(model, { gridSizeConfirmDialog: () => nextGridSizeConfirmDialog }),
122
+ modifyFields(model, {
123
+ gridSizeConfirmDialog: () => nextGridSizeConfirmDialog,
124
+ }),
123
125
  toParentMessage: message =>
124
126
  Message.GotGridSizeConfirmDialogMessage({ message }),
125
127
  foldOutMessage: foldGridSizeConfirmDialogOutMessage,
@@ -129,7 +131,9 @@ const foldGridSizeConfirmDialogOpen = Update.foldChildStep({
129
131
  update: Dialog.open,
130
132
  read: (model: Model) => Option.some(model.gridSizeConfirmDialog),
131
133
  write: (model, nextGridSizeConfirmDialog) =>
132
- evo(model, { gridSizeConfirmDialog: () => nextGridSizeConfirmDialog }),
134
+ modifyFields(model, {
135
+ gridSizeConfirmDialog: () => nextGridSizeConfirmDialog,
136
+ }),
133
137
  toParentMessage: message =>
134
138
  Message.GotGridSizeConfirmDialogMessage({ message }),
135
139
  foldOutMessage: foldGridSizeConfirmDialogOutMessage,
@@ -139,18 +143,22 @@ const foldGridSizeConfirmDialogClose = Update.foldChildStep({
139
143
  update: Dialog.close,
140
144
  read: (model: Model) => Option.some(model.gridSizeConfirmDialog),
141
145
  write: (model, nextGridSizeConfirmDialog) =>
142
- evo(model, { gridSizeConfirmDialog: () => nextGridSizeConfirmDialog }),
146
+ modifyFields(model, {
147
+ gridSizeConfirmDialog: () => nextGridSizeConfirmDialog,
148
+ }),
143
149
  toParentMessage: message =>
144
150
  Message.GotGridSizeConfirmDialogMessage({ message }),
145
151
  foldOutMessage: foldGridSizeConfirmDialogOutMessage,
146
152
  })
147
153
 
148
154
  const selectTool = (model: Model, tool: Tool): UpdateReturn => ({
149
- model: evo(model, { tool: () => tool }),
155
+ model: modifyFields(model, { tool: () => tool }),
150
156
  })
151
157
 
152
158
  const selectColor = (model: Model, colorIndex: PaletteIndex): UpdateReturn => {
153
- const nextModel = evo(model, { selectedColorIndex: () => colorIndex })
159
+ const nextModel = modifyFields(model, {
160
+ selectedColorIndex: () => colorIndex,
161
+ })
154
162
  return { model: nextModel, commands: [saveCanvas(nextModel)] }
155
163
  }
156
164
 
@@ -168,7 +176,7 @@ const foldToolRadioGroup = Update.foldChild({
168
176
  update: ToolRadioGroup.update,
169
177
  read: (model: Model) => Option.some(model.toolRadioGroup),
170
178
  write: (model, nextToolRadioGroup) =>
171
- evo(model, { toolRadioGroup: () => nextToolRadioGroup }),
179
+ modifyFields(model, { toolRadioGroup: () => nextToolRadioGroup }),
172
180
  toParentMessage: message => Message.GotToolRadioGroupMessage({ message }),
173
181
  foldOutMessage: foldToolRadioGroupOutMessage,
174
182
  })
@@ -186,7 +194,7 @@ const foldGridSizeRadioGroup = Update.foldChild({
186
194
  update: GridSizeRadioGroup.update,
187
195
  read: (model: Model) => Option.some(model.gridSizeRadioGroup),
188
196
  write: (model, nextGridSizeRadioGroup) =>
189
- evo(model, { gridSizeRadioGroup: () => nextGridSizeRadioGroup }),
197
+ modifyFields(model, { gridSizeRadioGroup: () => nextGridSizeRadioGroup }),
190
198
  toParentMessage: message => Message.GotGridSizeRadioGroupMessage({ message }),
191
199
  foldOutMessage: foldGridSizeRadioGroupOutMessage,
192
200
  })
@@ -207,7 +215,7 @@ const foldPaletteRadioGroup = Update.foldChild({
207
215
  update: PaletteRadioGroup.update,
208
216
  read: (model: Model) => Option.some(model.paletteRadioGroup),
209
217
  write: (model, nextPaletteRadioGroup) =>
210
- evo(model, { paletteRadioGroup: () => nextPaletteRadioGroup }),
218
+ modifyFields(model, { paletteRadioGroup: () => nextPaletteRadioGroup }),
211
219
  toParentMessage: message => Message.GotPaletteRadioGroupMessage({ message }),
212
220
  foldOutMessage: foldPaletteRadioGroupOutMessage,
213
221
  })
@@ -218,7 +226,7 @@ export const update = (model: Model, message: Message) =>
218
226
  Match.value(model.tool).pipe(
219
227
  withUpdateReturn,
220
228
  Match.when('Brush', () => ({
221
- model: evo(model, {
229
+ model: modifyFields(model, {
222
230
  grid: () => applyBrush(model, x, y),
223
231
  undoStack: () => pushHistory(model.undoStack, model.grid),
224
232
  redoStack: () => [],
@@ -226,7 +234,7 @@ export const update = (model: Model, message: Message) =>
226
234
  }),
227
235
  })),
228
236
  Match.when('Fill', () => {
229
- const nextModel = evo(model, {
237
+ const nextModel = modifyFields(model, {
230
238
  grid: () => applyFill(model, x, y),
231
239
  undoStack: () => pushHistory(model.undoStack, model.grid),
232
240
  redoStack: () => [],
@@ -234,7 +242,7 @@ export const update = (model: Model, message: Message) =>
234
242
  return { model: nextModel, commands: [saveCanvas(nextModel)] }
235
243
  }),
236
244
  Match.when('Eraser', () => ({
237
- model: evo(model, {
245
+ model: modifyFields(model, {
238
246
  grid: () => applyEraser(model, x, y),
239
247
  undoStack: () => pushHistory(model.undoStack, model.grid),
240
248
  redoStack: () => [],
@@ -245,19 +253,23 @@ export const update = (model: Model, message: Message) =>
245
253
  ),
246
254
 
247
255
  EnteredCell: ({ x, y }) => {
248
- const withHover = evo(model, {
256
+ const withHover = modifyFields(model, {
249
257
  maybeHoveredCell: () => Option.some({ x, y }),
250
258
  })
251
259
 
252
260
  if (model.isDrawing && model.tool === 'Brush') {
253
261
  return {
254
- model: evo(withHover, { grid: () => applyBrush(model, x, y) }),
262
+ model: modifyFields(withHover, {
263
+ grid: () => applyBrush(model, x, y),
264
+ }),
255
265
  }
256
266
  }
257
267
 
258
268
  if (model.isDrawing && model.tool === 'Eraser') {
259
269
  return {
260
- model: evo(withHover, { grid: () => applyEraser(model, x, y) }),
270
+ model: modifyFields(withHover, {
271
+ grid: () => applyEraser(model, x, y),
272
+ }),
261
273
  }
262
274
  }
263
275
 
@@ -265,14 +277,14 @@ export const update = (model: Model, message: Message) =>
265
277
  },
266
278
 
267
279
  LeftCanvas: () => ({
268
- model: evo(model, { maybeHoveredCell: () => Option.none() }),
280
+ model: modifyFields(model, { maybeHoveredCell: () => Option.none() }),
269
281
  }),
270
282
 
271
283
  ReleasedMouse: () => {
272
284
  if (!model.isDrawing) {
273
285
  return { model }
274
286
  }
275
- const nextModel = evo(model, { isDrawing: () => false })
287
+ const nextModel = modifyFields(model, { isDrawing: () => false })
276
288
  return { model: nextModel, commands: [saveCanvas(nextModel)] }
277
289
  },
278
290
 
@@ -299,7 +311,9 @@ export const update = (model: Model, message: Message) =>
299
311
  Match.when('Both', () => 'Vertical' as const),
300
312
  Match.exhaustive,
301
313
  )
302
- return { model: evo(model, { mirrorMode: () => nextMirrorMode }) }
314
+ return {
315
+ model: modifyFields(model, { mirrorMode: () => nextMirrorMode }),
316
+ }
303
317
  },
304
318
 
305
319
  ToggledMirrorVertical: () => {
@@ -310,14 +324,16 @@ export const update = (model: Model, message: Message) =>
310
324
  Match.when('Both', () => 'Horizontal' as const),
311
325
  Match.exhaustive,
312
326
  )
313
- return { model: evo(model, { mirrorMode: () => nextMirrorMode }) }
327
+ return {
328
+ model: modifyFields(model, { mirrorMode: () => nextMirrorMode }),
329
+ }
314
330
  },
315
331
 
316
332
  ClickedUndo: () =>
317
333
  Array.match(model.undoStack, {
318
334
  onEmpty: () => ({ model }),
319
335
  onNonEmpty: nonEmptyUndoStack => {
320
- const nextModel = evo(model, {
336
+ const nextModel = modifyFields(model, {
321
337
  grid: () => Array.lastNonEmpty(nonEmptyUndoStack),
322
338
  undoStack: () => Array.initNonEmpty(nonEmptyUndoStack),
323
339
  redoStack: () => [...model.redoStack, model.grid],
@@ -330,7 +346,7 @@ export const update = (model: Model, message: Message) =>
330
346
  Array.match(model.redoStack, {
331
347
  onEmpty: () => ({ model }),
332
348
  onNonEmpty: nonEmptyRedoStack => {
333
- const nextModel = evo(model, {
349
+ const nextModel = modifyFields(model, {
334
350
  grid: () => Array.lastNonEmpty(nonEmptyRedoStack),
335
351
  undoStack: () => [...model.undoStack, model.grid],
336
352
  redoStack: () => Array.initNonEmpty(nonEmptyRedoStack),
@@ -347,7 +363,7 @@ export const update = (model: Model, message: Message) =>
347
363
 
348
364
  const statesAfterTarget = Array.drop(model.undoStack, stepIndex + 1)
349
365
 
350
- const nextModel = evo(model, {
366
+ const nextModel = modifyFields(model, {
351
367
  grid: () => targetGrid,
352
368
  undoStack: () => Array.take(model.undoStack, stepIndex),
353
369
  redoStack: () => [
@@ -371,7 +387,7 @@ export const update = (model: Model, message: Message) =>
371
387
  stepIndex + 1,
372
388
  )
373
389
 
374
- const nextModel = evo(model, {
390
+ const nextModel = modifyFields(model, {
375
391
  grid: () => targetGrid,
376
392
  undoStack: () => [
377
393
  ...model.undoStack,
@@ -385,7 +401,7 @@ export const update = (model: Model, message: Message) =>
385
401
  },
386
402
 
387
403
  ClickedClear: () => {
388
- const nextModel = evo(model, {
404
+ const nextModel = modifyFields(model, {
389
405
  grid: () => createEmptyGrid(model.gridSize),
390
406
  undoStack: () => pushHistory(model.undoStack, model.grid),
391
407
  redoStack: () => [],
@@ -411,7 +427,7 @@ export const update = (model: Model, message: Message) =>
411
427
  FailedExportPng: ({ error }) =>
412
428
  Update.combine(model, [
413
429
  stepModel => ({
414
- model: evo(stepModel, {
430
+ model: modifyFields(stepModel, {
415
431
  maybeExportError: () => Option.some(error),
416
432
  }),
417
433
  }),
@@ -441,7 +457,7 @@ export const update = (model: Model, message: Message) =>
441
457
  })
442
458
 
443
459
  const applyGridSizeChange = (model: Model, size: number): UpdateReturn => ({
444
- model: evo(model, {
460
+ model: modifyFields(model, {
445
461
  grid: () => createEmptyGrid(size),
446
462
  gridSize: () => size,
447
463
  undoStack: () => [],
@@ -462,7 +478,7 @@ const requestGridSizeChange = (model: Model, size: number): UpdateReturn => {
462
478
 
463
479
  return Update.combine(model, [
464
480
  stepModel => ({
465
- model: evo(stepModel, {
481
+ model: modifyFields(stepModel, {
466
482
  maybePendingGridSize: () => Option.some(size),
467
483
  }),
468
484
  }),
@@ -9,10 +9,10 @@
9
9
  "test": "vitest run"
10
10
  },
11
11
  "dependencies": {
12
- "@effect/platform-browser": "4.0.0-rc.115",
12
+ "@effect/platform-browser": "4.0.0-rc.116",
13
13
  "@foldkit/ui": "workspace:*",
14
14
  "clsx": "^2.1.1",
15
- "effect": "4.0.0-rc.115",
15
+ "effect": "4.0.0-rc.116",
16
16
  "foldkit": "workspace:*"
17
17
  },
18
18
  "devDependencies": {
@@ -17,7 +17,7 @@ import { defineMessageUnion } from 'foldkit/message'
17
17
  import { UrlRequest, load, pushUrl, replaceUrl } from 'foldkit/navigation'
18
18
  import { defineRouteUnion } from 'foldkit/route'
19
19
  import { defineTaggedUnion } from 'foldkit/schema'
20
- import { evo } from 'foldkit/struct'
20
+ import { modifyFields } from 'foldkit/struct'
21
21
  import { Url, toString as urlToString } from 'foldkit/url'
22
22
 
23
23
  import { Button, Input, Listbox } from '@foldkit/ui'
@@ -302,7 +302,7 @@ const foldDietListbox = Update.foldChild({
302
302
  update: DietListbox.update,
303
303
  read: (model: Model) => Option.some(model.dietListbox),
304
304
  write: (model, nextDietListbox) =>
305
- evo(model, { dietListbox: () => nextDietListbox }),
305
+ modifyFields(model, { dietListbox: () => nextDietListbox }),
306
306
  toParentMessage: message => Message.GotDietListboxMessage({ message }),
307
307
  foldOutMessage: foldDietListboxOutMessage,
308
308
  })
@@ -330,7 +330,7 @@ const foldPeriodListbox = Update.foldChild({
330
330
  update: PeriodListbox.update,
331
331
  read: (model: Model) => Option.some(model.periodListbox),
332
332
  write: (model, nextPeriodListbox) =>
333
- evo(model, { periodListbox: () => nextPeriodListbox }),
333
+ modifyFields(model, { periodListbox: () => nextPeriodListbox }),
334
334
  toParentMessage: message => Message.GotPeriodListboxMessage({ message }),
335
335
  foldOutMessage: foldPeriodListboxOutMessage,
336
336
  })
@@ -356,7 +356,7 @@ export const update = (model: Model, message: Message) =>
356
356
  ChangedUrl: ({ url }) => {
357
357
  const nextRoute = urlToAppRoute(url)
358
358
 
359
- return { model: evo(model, { route: () => nextRoute }) }
359
+ return { model: modifyFields(model, { route: () => nextRoute }) }
360
360
  },
361
361
 
362
362
  ChangedSearchInput: ({ value }) => {