create-foldkit-app 0.32.0 → 0.32.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.
Files changed (149) hide show
  1. package/dist/commands/create.js +9 -7
  2. package/dist/templates/base/FOLDKIT.md +22 -6
  3. package/dist/templates/examples/api-cache/src/data.ts +14 -14
  4. package/dist/templates/examples/api-cache/src/main.ts +42 -39
  5. package/dist/templates/examples/auth/src/command.ts +3 -3
  6. package/dist/templates/examples/auth/src/domain/session.ts +8 -6
  7. package/dist/templates/examples/auth/src/main.ts +11 -11
  8. package/dist/templates/examples/auth/src/message.ts +3 -3
  9. package/dist/templates/examples/auth/src/model.ts +2 -2
  10. package/dist/templates/examples/auth/src/page/loggedIn/index.ts +1 -1
  11. package/dist/templates/examples/auth/src/page/loggedIn/view.ts +3 -3
  12. package/dist/templates/examples/auth/src/page/loggedOut/index.ts +1 -1
  13. package/dist/templates/examples/auth/src/page/loggedOut/page/login.ts +9 -17
  14. package/dist/templates/examples/auth/src/page/loggedOut/update.ts +4 -6
  15. package/dist/templates/examples/auth/src/page/loggedOut/view.ts +3 -3
  16. package/dist/templates/examples/auth/src/route.ts +2 -2
  17. package/dist/templates/examples/auth/src/update.ts +37 -40
  18. package/dist/templates/examples/auth/src/view.ts +6 -6
  19. package/dist/templates/examples/canvas-art/src/main.ts +22 -30
  20. package/dist/templates/examples/charting/src/command.ts +3 -3
  21. package/dist/templates/examples/charting/src/domain.ts +53 -48
  22. package/dist/templates/examples/charting/src/echarts.ts +6 -6
  23. package/dist/templates/examples/charting/src/githubApi.ts +33 -34
  24. package/dist/templates/examples/charting/src/http.ts +7 -7
  25. package/dist/templates/examples/charting/src/message.ts +6 -6
  26. package/dist/templates/examples/charting/src/model.ts +6 -6
  27. package/dist/templates/examples/charting/src/npmApi.ts +19 -15
  28. package/dist/templates/examples/charting/src/subscription.ts +5 -5
  29. package/dist/templates/examples/charting/src/telemetry.test.ts +18 -12
  30. package/dist/templates/examples/charting/src/telemetry.ts +11 -18
  31. package/dist/templates/examples/charting/src/update.ts +17 -23
  32. package/dist/templates/examples/charting/src/view/chart.ts +2 -2
  33. package/dist/templates/examples/counter/src/main.ts +2 -2
  34. package/dist/templates/examples/counters/src/counter.ts +2 -2
  35. package/dist/templates/examples/counters/src/main.ts +8 -8
  36. package/dist/templates/examples/embedding/src/main.ts +10 -7
  37. package/dist/templates/examples/form/src/main.ts +18 -14
  38. package/dist/templates/examples/generative-art/src/command.ts +7 -2
  39. package/dist/templates/examples/generative-art/src/message.ts +14 -14
  40. package/dist/templates/examples/generative-art/src/model.ts +21 -21
  41. package/dist/templates/examples/generative-art/src/update.ts +15 -17
  42. package/dist/templates/examples/interrupting-commands/src/main.ts +30 -27
  43. package/dist/templates/examples/job-application/src/domain/proficiencyLevel.ts +2 -2
  44. package/dist/templates/examples/job-application/src/domain/pronounOption.ts +2 -2
  45. package/dist/templates/examples/job-application/src/domain/step.ts +11 -11
  46. package/dist/templates/examples/job-application/src/main.ts +5 -5
  47. package/dist/templates/examples/job-application/src/message.ts +2 -2
  48. package/dist/templates/examples/job-application/src/model.ts +5 -5
  49. package/dist/templates/examples/job-application/src/step/attachments.ts +32 -34
  50. package/dist/templates/examples/job-application/src/step/coverLetter.ts +4 -4
  51. package/dist/templates/examples/job-application/src/step/education/education.ts +11 -14
  52. package/dist/templates/examples/job-application/src/step/education/entry.ts +21 -22
  53. package/dist/templates/examples/job-application/src/step/personalInfo.ts +44 -54
  54. package/dist/templates/examples/job-application/src/step/skills/entry.ts +12 -14
  55. package/dist/templates/examples/job-application/src/step/skills/skills.ts +11 -14
  56. package/dist/templates/examples/job-application/src/step/workHistory/entry.ts +43 -45
  57. package/dist/templates/examples/job-application/src/step/workHistory/workHistory.ts +11 -14
  58. package/dist/templates/examples/job-application/src/update.ts +17 -17
  59. package/dist/templates/examples/job-application/src/view/attachments.ts +5 -5
  60. package/dist/templates/examples/job-application/src/view/datePicker.ts +3 -3
  61. package/dist/templates/examples/job-application/src/view/field.ts +5 -5
  62. package/dist/templates/examples/job-application/src/view/index.ts +28 -22
  63. package/dist/templates/examples/kanban/src/command.ts +4 -4
  64. package/dist/templates/examples/kanban/src/domain/card.ts +6 -6
  65. package/dist/templates/examples/kanban/src/domain/column.ts +9 -9
  66. package/dist/templates/examples/kanban/src/main.ts +4 -4
  67. package/dist/templates/examples/kanban/src/message.ts +6 -6
  68. package/dist/templates/examples/kanban/src/model.ts +11 -9
  69. package/dist/templates/examples/kanban/src/update.ts +5 -5
  70. package/dist/templates/examples/managed-resource-layer/src/main.ts +20 -20
  71. package/dist/templates/examples/map/src/locations.ts +7 -7
  72. package/dist/templates/examples/map/src/main.ts +83 -44
  73. package/dist/templates/examples/map/src/mount.test.ts +127 -0
  74. package/dist/templates/examples/pixel-art/src/command.ts +12 -5
  75. package/dist/templates/examples/pixel-art/src/main.ts +4 -4
  76. package/dist/templates/examples/pixel-art/src/message.ts +7 -7
  77. package/dist/templates/examples/pixel-art/src/model.ts +34 -29
  78. package/dist/templates/examples/pixel-art/src/subscription.ts +2 -2
  79. package/dist/templates/examples/pixel-art/src/update.ts +79 -86
  80. package/dist/templates/examples/query-sync/src/main.ts +106 -102
  81. package/dist/templates/examples/route-transitions/src/data.ts +6 -6
  82. package/dist/templates/examples/route-transitions/src/main.ts +23 -29
  83. package/dist/templates/examples/route-transitions/src/route.ts +3 -3
  84. package/dist/templates/examples/routing/src/fileTree.ts +10 -8
  85. package/dist/templates/examples/routing/src/main.ts +23 -21
  86. package/dist/templates/examples/routing/src/page/people.ts +14 -22
  87. package/dist/templates/examples/routing/src/route.ts +7 -7
  88. package/dist/templates/examples/shopping-cart/src/main.ts +30 -31
  89. package/dist/templates/examples/shopping-cart/src/page/products.ts +10 -10
  90. package/dist/templates/examples/shopping-cart/src/route.ts +6 -4
  91. package/dist/templates/examples/slow-warnings/src/main.ts +35 -43
  92. package/dist/templates/examples/snake/src/domain/snake.ts +2 -2
  93. package/dist/templates/examples/snake/src/main.ts +39 -47
  94. package/dist/templates/examples/ssg/src/main.ts +5 -5
  95. package/dist/templates/examples/ssg/src/route.ts +2 -2
  96. package/dist/templates/examples/ssr/src/cookie.ts +3 -3
  97. package/dist/templates/examples/ssr/src/main.ts +10 -10
  98. package/dist/templates/examples/state-machine/src/main.ts +55 -53
  99. package/dist/templates/examples/state-machine/src/view.ts +7 -7
  100. package/dist/templates/examples/stopwatch/src/main.ts +10 -10
  101. package/dist/templates/examples/todo/src/main.ts +41 -34
  102. package/dist/templates/examples/ui-showcase/src/main.ts +54 -42
  103. package/dist/templates/examples/ui-showcase/src/scene.test.ts +1 -1
  104. package/dist/templates/examples/ui-showcase/src/ui/init.ts +1 -2
  105. package/dist/templates/examples/ui-showcase/src/ui/message.ts +17 -18
  106. package/dist/templates/examples/ui-showcase/src/ui/model.ts +47 -44
  107. package/dist/templates/examples/ui-showcase/src/ui/subscriptions.ts +1 -1
  108. package/dist/templates/examples/ui-showcase/src/ui/toast.ts +4 -4
  109. package/dist/templates/examples/ui-showcase/src/ui/update.ts +287 -298
  110. package/dist/templates/examples/ui-showcase/src/ui/view/animation.ts +2 -2
  111. package/dist/templates/examples/ui-showcase/src/ui/view/button.ts +1 -1
  112. package/dist/templates/examples/ui-showcase/src/ui/view/calendar.ts +4 -4
  113. package/dist/templates/examples/ui-showcase/src/ui/view/checkbox.ts +1 -1
  114. package/dist/templates/examples/ui-showcase/src/ui/view/combobox.ts +1 -1
  115. package/dist/templates/examples/ui-showcase/src/ui/view/datePicker.ts +4 -4
  116. package/dist/templates/examples/ui-showcase/src/ui/view/dialog.ts +1 -1
  117. package/dist/templates/examples/ui-showcase/src/ui/view/disclosure.ts +1 -1
  118. package/dist/templates/examples/ui-showcase/src/ui/view/dragAndDrop.ts +1 -1
  119. package/dist/templates/examples/ui-showcase/src/ui/view/fieldset.ts +1 -1
  120. package/dist/templates/examples/ui-showcase/src/ui/view/fileDrop.ts +6 -6
  121. package/dist/templates/examples/ui-showcase/src/ui/view/hoverIntent.ts +9 -20
  122. package/dist/templates/examples/ui-showcase/src/ui/view/input.ts +1 -1
  123. package/dist/templates/examples/ui-showcase/src/ui/view/listbox.ts +1 -1
  124. package/dist/templates/examples/ui-showcase/src/ui/view/menu.ts +15 -15
  125. package/dist/templates/examples/ui-showcase/src/ui/view/popover.ts +1 -1
  126. package/dist/templates/examples/ui-showcase/src/ui/view/radioGroup.ts +1 -1
  127. package/dist/templates/examples/ui-showcase/src/ui/view/select.ts +1 -1
  128. package/dist/templates/examples/ui-showcase/src/ui/view/slider.ts +1 -1
  129. package/dist/templates/examples/ui-showcase/src/ui/view/switch.ts +1 -1
  130. package/dist/templates/examples/ui-showcase/src/ui/view/tabs.ts +7 -7
  131. package/dist/templates/examples/ui-showcase/src/ui/view/textarea.ts +1 -1
  132. package/dist/templates/examples/ui-showcase/src/ui/view/toast.ts +8 -8
  133. package/dist/templates/examples/ui-showcase/src/ui/view/tooltip.ts +1 -1
  134. package/dist/templates/examples/ui-showcase/src/ui/view/virtualList.ts +7 -7
  135. package/dist/templates/examples/view-transitions/src/artwork.ts +7 -7
  136. package/dist/templates/examples/view-transitions/src/main.ts +6 -6
  137. package/dist/templates/examples/view-transitions/src/route.ts +3 -3
  138. package/dist/templates/examples/weather/src/main.ts +42 -42
  139. package/dist/templates/examples/weather/src/story.test.ts +5 -5
  140. package/dist/templates/examples/web-components/src/main.ts +16 -16
  141. package/dist/templates/examples/websocket-chat/src/main.ts +30 -30
  142. package/dist/templates/release.json +13 -13
  143. package/dist/templates/rendering/ssg/src/main.ts +5 -5
  144. package/dist/templates/rendering/ssg/src/route.ts +2 -2
  145. package/dist/templates/rendering/ssr/server/main.ts +15 -15
  146. package/dist/templates/rendering/ssr/src/cookie.ts +3 -3
  147. package/dist/templates/rendering/ssr/src/main.ts +10 -10
  148. package/dist/utils/packages.js +17 -0
  149. package/package.json +1 -1
@@ -2,10 +2,10 @@ import { clsx } from 'clsx'
2
2
  import {
3
3
  Array,
4
4
  Effect,
5
- Match as M,
5
+ Match,
6
6
  Option,
7
7
  Order,
8
- Schema as S,
8
+ Schema,
9
9
  SchemaTransformation,
10
10
  String,
11
11
  Types,
@@ -25,9 +25,15 @@ import { AnchorConfig } from '@foldkit/ui/listbox'
25
25
 
26
26
  import { type Dinosaur, dinosaurs } from './data'
27
27
 
28
- const Diet = S.Literals(['Carnivore', 'Herbivore', 'Omnivore'])
29
- const Period = S.Literals(['Triassic', 'Jurassic', 'Cretaceous'])
30
- const SortColumn = S.Literals(['Name', 'Period', 'Diet', 'Length', 'Weight'])
28
+ const Diet = Schema.Literals(['Carnivore', 'Herbivore', 'Omnivore'])
29
+ const Period = Schema.Literals(['Triassic', 'Jurassic', 'Cretaceous'])
30
+ const SortColumn = Schema.Literals([
31
+ 'Name',
32
+ 'Period',
33
+ 'Diet',
34
+ 'Length',
35
+ 'Weight',
36
+ ])
31
37
  type SortColumn = typeof SortColumn.Type
32
38
 
33
39
  export const Sorting = defineTaggedUnion({
@@ -44,12 +50,12 @@ const periodFilterItems: ReadonlyArray<string> = ['', ...Period.literals]
44
50
 
45
51
  const SORT_PARAM_SEPARATOR = ':'
46
52
 
47
- const optionFromValidParam = <A extends string>(schema: S.Codec<A, A>) => {
48
- const decode = S.decodeUnknownOption(schema)
53
+ const optionFromValidParam = <A extends string>(schema: Schema.Codec<A, A>) => {
54
+ const decode = Schema.decodeUnknownOption(schema)
49
55
 
50
- return S.OptionFromOptional(S.String).pipe(
51
- S.decodeTo(
52
- S.Option(schema),
56
+ return Schema.OptionFromOptional(Schema.String).pipe(
57
+ Schema.decodeTo(
58
+ Schema.Option(schema),
53
59
  SchemaTransformation.transform({
54
60
  decode: (maybeRaw: Option.Option<string>): Option.Option<A> =>
55
61
  Option.flatMap(maybeRaw, decode),
@@ -60,14 +66,14 @@ const optionFromValidParam = <A extends string>(schema: S.Codec<A, A>) => {
60
66
  )
61
67
  }
62
68
 
63
- const SortDirection = S.Literals(['Ascending', 'Descending'])
69
+ const SortDirection = Schema.Literals(['Ascending', 'Descending'])
64
70
 
65
71
  const sortingFromParam = (() => {
66
- const decodeColumn = S.decodeUnknownOption(SortColumn)
67
- const decodeDirection = S.decodeUnknownOption(SortDirection)
72
+ const decodeColumn = Schema.decodeUnknownOption(SortColumn)
73
+ const decodeDirection = Schema.decodeUnknownOption(SortDirection)
68
74
 
69
- return S.OptionFromOptional(S.String).pipe(
70
- S.decodeTo(
75
+ return Schema.OptionFromOptional(Schema.String).pipe(
76
+ Schema.decodeTo(
71
77
  Sorting,
72
78
  SchemaTransformation.transform({
73
79
  decode: (maybeRaw: Option.Option<string>): Sorting =>
@@ -90,10 +96,14 @@ const sortingFromParam = (() => {
90
96
  ),
91
97
  }),
92
98
  Option.map(({ column, direction }) =>
93
- M.value(direction).pipe(
94
- M.when('Ascending', () => Sorting.Ascending({ column })),
95
- M.when('Descending', () => Sorting.Descending({ column })),
96
- M.exhaustive,
99
+ Match.value(direction).pipe(
100
+ Match.when('Ascending', () =>
101
+ Sorting.Ascending({ column }),
102
+ ),
103
+ Match.when('Descending', () =>
104
+ Sorting.Descending({ column }),
105
+ ),
106
+ Match.exhaustive,
97
107
  ),
98
108
  ),
99
109
  Option.getOrElse(() => Sorting.Unsorted()),
@@ -115,12 +125,12 @@ const sortingFromParam = (() => {
115
125
 
116
126
  export const AppRoute = defineRouteUnion({
117
127
  Browse: {
118
- search: S.Option(S.String),
128
+ search: Schema.Option(Schema.String),
119
129
  sorting: Sorting,
120
- diet: S.Option(Diet),
121
- period: S.Option(Period),
130
+ diet: Schema.Option(Diet),
131
+ period: Schema.Option(Period),
122
132
  },
123
- NotFound: { path: S.String },
133
+ NotFound: { path: Schema.String },
124
134
  })
125
135
 
126
136
  export type AppRoute = typeof AppRoute.Type
@@ -128,8 +138,8 @@ export type AppRoute = typeof AppRoute.Type
128
138
  export const browseRouter = pipe(
129
139
  Route.root,
130
140
  Route.query(
131
- S.Struct({
132
- search: S.OptionFromOptional(S.String),
141
+ Schema.Struct({
142
+ search: Schema.OptionFromOptional(Schema.String),
133
143
  sorting: sortingFromParam,
134
144
  diet: optionFromValidParam(Diet),
135
145
  period: optionFromValidParam(Period),
@@ -143,7 +153,7 @@ const urlToAppRoute = Route.parseUrlWithFallback(routeParser, AppRoute.NotFound)
143
153
 
144
154
  // MODEL
145
155
 
146
- export const Model = S.Struct({
156
+ export const Model = Schema.Struct({
147
157
  route: AppRoute,
148
158
  dietListbox: Listbox.Model,
149
159
  periodListbox: Listbox.Model,
@@ -158,7 +168,7 @@ export const Message = defineMessageUnion({
158
168
  CompletedReplaceFilters: {},
159
169
  ClickedLink: { request: UrlRequest },
160
170
  ChangedUrl: { url: Url },
161
- ChangedSearchInput: { value: S.String },
171
+ ChangedSearchInput: { value: Schema.String },
162
172
  ClickedColumnHeader: { column: SortColumn },
163
173
  GotDietListboxMessage: { message: Listbox.Message },
164
174
  GotPeriodListboxMessage: { message: Listbox.Message },
@@ -178,9 +188,9 @@ const emptyBrowseFields: BrowseFields = {
178
188
  }
179
189
 
180
190
  const routeToBrowseFields = (route: AppRoute): BrowseFields =>
181
- M.value(route).pipe(
182
- M.tag('Browse', route => route),
183
- M.orElse(() => emptyBrowseFields),
191
+ Match.value(route).pipe(
192
+ Match.tag('Browse', route => route),
193
+ Match.orElse(() => emptyBrowseFields),
184
194
  )
185
195
 
186
196
  export const init: Runtime.RoutingApplicationInit<Model, Message> = (
@@ -216,18 +226,18 @@ const columnSortDirection = (
216
226
  const nextSorting = (sorting: Sorting, column: SortColumn): Sorting =>
217
227
  pipe(
218
228
  columnSortDirection(sorting, column),
219
- M.value,
220
- M.when('Unsorted', () => Sorting.Ascending({ column })),
221
- M.when('Ascending', () => Sorting.Descending({ column })),
222
- M.when('Descending', () => Sorting.Unsorted()),
223
- M.exhaustive,
229
+ Match.value,
230
+ Match.when('Unsorted', () => Sorting.Ascending({ column })),
231
+ Match.when('Ascending', () => Sorting.Descending({ column })),
232
+ Match.when('Descending', () => Sorting.Unsorted()),
233
+ Match.exhaustive,
224
234
  )
225
235
 
226
236
  const selectionToParam = <A extends string>(
227
237
  maybeSelectedItem: Option.Option<string>,
228
- schema: S.Codec<A, A>,
238
+ schema: Schema.Codec<A, A>,
229
239
  ): Option.Option<A> => {
230
- const decode = S.decodeUnknownOption(schema)
240
+ const decode = Schema.decodeUnknownOption(schema)
231
241
 
232
242
  return pipe(
233
243
  maybeSelectedItem,
@@ -238,10 +248,10 @@ const selectionToParam = <A extends string>(
238
248
 
239
249
  export const ReplaceFilters = Command.define('ReplaceFilters', {
240
250
  args: {
241
- search: S.Option(S.String),
251
+ search: Schema.Option(Schema.String),
242
252
  sorting: Sorting,
243
- diet: S.Option(Diet),
244
- period: S.Option(Period),
253
+ diet: Schema.Option(Diet),
254
+ period: Schema.Option(Period),
245
255
  },
246
256
  messages: [Message.CompletedReplaceFilters],
247
257
  execute: fields =>
@@ -251,14 +261,14 @@ export const ReplaceFilters = Command.define('ReplaceFilters', {
251
261
  })
252
262
 
253
263
  const NavigateInternal = Command.define('NavigateInternal', {
254
- args: { url: S.String },
264
+ args: { url: Schema.String },
255
265
  messages: [Message.CompletedNavigateInternal],
256
266
  execute: ({ url }) =>
257
267
  pushUrl(url).pipe(Effect.as(Message.CompletedNavigateInternal())),
258
268
  })
259
269
 
260
270
  const LoadExternal = Command.define('LoadExternal', {
261
- args: { href: S.String },
271
+ args: { href: Schema.String },
262
272
  messages: [Message.CompletedLoadExternal],
263
273
  execute: ({ href }) =>
264
274
  load(href).pipe(Effect.as(Message.CompletedLoadExternal())),
@@ -269,27 +279,24 @@ type UpdateReturn = Update.Return<Model, Message>
269
279
  const DietListbox = Listbox.create<string>()
270
280
  const PeriodListbox = Listbox.create<string>()
271
281
 
272
- const foldDietListboxOutMessage: (
273
- outMessage: Listbox.OutMessage,
274
- ) => Update.Step<Model, Message> = M.type<Listbox.OutMessage>().pipe(
275
- M.withReturnType<Update.Step<Model, Message>>(),
276
- M.tagsExhaustive({
277
- Selected:
278
- ({ value }) =>
279
- model => {
280
- const fields = routeToBrowseFields(model.route)
281
- return {
282
- model,
283
- commands: [
284
- ReplaceFilters({
285
- ...fields,
286
- diet: selectionToParam(Option.some(value), Diet),
287
- }),
288
- ],
289
- }
290
- },
291
- }),
292
- )
282
+ const foldDietListboxOutMessage = Listbox.OutMessage.match<
283
+ Update.Step<Model, Message>
284
+ >({
285
+ Selected:
286
+ ({ value }) =>
287
+ model => {
288
+ const fields = routeToBrowseFields(model.route)
289
+ return {
290
+ model,
291
+ commands: [
292
+ ReplaceFilters({
293
+ ...fields,
294
+ diet: selectionToParam(Option.some(value), Diet),
295
+ }),
296
+ ],
297
+ }
298
+ },
299
+ })
293
300
 
294
301
  const foldDietListbox = Update.foldChild({
295
302
  update: DietListbox.update,
@@ -300,27 +307,24 @@ const foldDietListbox = Update.foldChild({
300
307
  foldOutMessage: foldDietListboxOutMessage,
301
308
  })
302
309
 
303
- const foldPeriodListboxOutMessage: (
304
- outMessage: Listbox.OutMessage,
305
- ) => Update.Step<Model, Message> = M.type<Listbox.OutMessage>().pipe(
306
- M.withReturnType<Update.Step<Model, Message>>(),
307
- M.tagsExhaustive({
308
- Selected:
309
- ({ value }) =>
310
- model => {
311
- const fields = routeToBrowseFields(model.route)
312
- return {
313
- model,
314
- commands: [
315
- ReplaceFilters({
316
- ...fields,
317
- period: selectionToParam(Option.some(value), Period),
318
- }),
319
- ],
320
- }
321
- },
322
- }),
323
- )
310
+ const foldPeriodListboxOutMessage = Listbox.OutMessage.match<
311
+ Update.Step<Model, Message>
312
+ >({
313
+ Selected:
314
+ ({ value }) =>
315
+ model => {
316
+ const fields = routeToBrowseFields(model.route)
317
+ return {
318
+ model,
319
+ commands: [
320
+ ReplaceFilters({
321
+ ...fields,
322
+ period: selectionToParam(Option.some(value), Period),
323
+ }),
324
+ ],
325
+ }
326
+ },
327
+ })
324
328
 
325
329
  const foldPeriodListbox = Update.foldChild({
326
330
  update: PeriodListbox.update,
@@ -439,11 +443,11 @@ const filterAndSort = (fields: BrowseFields): ReadonlyArray<Dinosaur> =>
439
443
  )
440
444
 
441
445
  const sortIndicator = (column: SortColumn, sorting: Sorting): string =>
442
- M.value(columnSortDirection(sorting, column)).pipe(
443
- M.when('Unsorted', () => ''),
444
- M.when('Ascending', () => '↑'),
445
- M.when('Descending', () => '↓'),
446
- M.exhaustive,
446
+ Match.value(columnSortDirection(sorting, column)).pipe(
447
+ Match.when('Unsorted', () => ''),
448
+ Match.when('Ascending', () => '↑'),
449
+ Match.when('Descending', () => '↓'),
450
+ Match.exhaustive,
447
451
  )
448
452
 
449
453
  const BADGE_BASE = 'px-2 py-0.5 rounded-full text-xs font-medium'
@@ -503,19 +507,19 @@ const dinosaurRowView = (dinosaur: Dinosaur, h: HtmlBuilder<Message>): Html =>
503
507
  )
504
508
 
505
509
  const sortAriaLabel = (column: SortColumn, sorting: Sorting): string =>
506
- M.value(columnSortDirection(sorting, column)).pipe(
507
- M.when('Unsorted', () => `Sort by ${column}`),
508
- M.when('Ascending', () => `Sort by ${column}, currently ascending`),
509
- M.when('Descending', () => `Sort by ${column}, currently descending`),
510
- M.exhaustive,
510
+ Match.value(columnSortDirection(sorting, column)).pipe(
511
+ Match.when('Unsorted', () => `Sort by ${column}`),
512
+ Match.when('Ascending', () => `Sort by ${column}, currently ascending`),
513
+ Match.when('Descending', () => `Sort by ${column}, currently descending`),
514
+ Match.exhaustive,
511
515
  )
512
516
 
513
517
  const ariaSortValue = (column: SortColumn, sorting: Sorting): string =>
514
- M.value(columnSortDirection(sorting, column)).pipe(
515
- M.when('Unsorted', () => 'none'),
516
- M.when('Ascending', () => 'ascending'),
517
- M.when('Descending', () => 'descending'),
518
- M.exhaustive,
518
+ Match.value(columnSortDirection(sorting, column)).pipe(
519
+ Match.when('Unsorted', () => 'none'),
520
+ Match.when('Ascending', () => 'ascending'),
521
+ Match.when('Descending', () => 'descending'),
522
+ Match.exhaustive,
519
523
  )
520
524
 
521
525
  const sortableColumnHeader = (
@@ -852,9 +856,9 @@ const notFoundView = (path: string, h: HtmlBuilder<Message>): Html =>
852
856
  )
853
857
 
854
858
  const routeTitle = (route: Model['route']): string =>
855
- M.value(route).pipe(
856
- M.tag('Browse', () => 'Dinosaur Explorer'),
857
- M.orElse(() => 'Not Found | Dinosaur Explorer'),
859
+ Match.value(route).pipe(
860
+ Match.tag('Browse', () => 'Dinosaur Explorer'),
861
+ Match.orElse(() => 'Not Found | Dinosaur Explorer'),
858
862
  )
859
863
 
860
864
  export const view = (model: Model, h: HtmlBuilder<Message>): Document => {
@@ -1,10 +1,10 @@
1
- import { Array, Option, Schema as S, pipe } from 'effect'
1
+ import { Array, Option, Schema, pipe } from 'effect'
2
2
 
3
- export const Painting = S.Struct({
4
- id: S.Number,
5
- title: S.String,
6
- artist: S.String,
7
- gradient: S.String,
3
+ export const Painting = Schema.Struct({
4
+ id: Schema.Number,
5
+ title: Schema.String,
6
+ artist: Schema.String,
7
+ gradient: Schema.String,
8
8
  })
9
9
  export type Painting = typeof Painting.Type
10
10
 
@@ -1,12 +1,4 @@
1
- import {
2
- Array,
3
- Duration,
4
- Effect,
5
- Match as M,
6
- Option,
7
- Schema as S,
8
- pipe,
9
- } from 'effect'
1
+ import { Array, Duration, Effect, Match, Option, Schema, pipe } from 'effect'
10
2
  import { Command, Runtime, Update } from 'foldkit'
11
3
  import { Document, Html, HtmlBuilder } from 'foldkit/html'
12
4
  import { defineMessageUnion } from 'foldkit/message'
@@ -35,30 +27,30 @@ const MAX_LOGGED_TRANSITIONS = 20
35
27
 
36
28
  // MODEL
37
29
 
38
- export const CatalogStatus = S.Literals(['Idle', 'Loading', 'Ready'])
30
+ export const CatalogStatus = Schema.Literals(['Idle', 'Loading', 'Ready'])
39
31
  export type CatalogStatus = typeof CatalogStatus.Type
40
32
 
41
33
  export const PaintingStatus = defineTaggedUnion({
42
34
  Idle: {},
43
- Loading: { paintingId: S.Number },
44
- Ready: { paintingId: S.Number },
35
+ Loading: { paintingId: Schema.Number },
36
+ Ready: { paintingId: Schema.Number },
45
37
  })
46
38
  export type PaintingStatus = typeof PaintingStatus.Type
47
39
 
48
- export const LoggedTransition = S.Struct({
49
- sequenceNumber: S.Number,
50
- maybePreviousRoute: S.Option(AppRoute),
40
+ export const LoggedTransition = Schema.Struct({
41
+ sequenceNumber: Schema.Number,
42
+ maybePreviousRoute: Schema.Option(AppRoute),
51
43
  nextRoute: AppRoute,
52
44
  })
53
45
  export type LoggedTransition = typeof LoggedTransition.Type
54
46
 
55
- export const Model = S.Struct({
47
+ export const Model = Schema.Struct({
56
48
  route: AppRoute,
57
- transitionLog: S.Array(LoggedTransition),
49
+ transitionLog: Schema.Array(LoggedTransition),
58
50
  catalogStatus: CatalogStatus,
59
51
  paintingStatus: PaintingStatus,
60
- studioDraft: S.String,
61
- maybeSavedDraft: S.Option(S.String),
52
+ studioDraft: Schema.String,
53
+ maybeSavedDraft: Schema.Option(Schema.String),
62
54
  })
63
55
  export type Model = typeof Model.Type
64
56
 
@@ -70,9 +62,9 @@ export const Message = defineMessageUnion({
70
62
  ClickedLink: { request: UrlRequest },
71
63
  ChangedUrl: { url: Url },
72
64
  SucceededLoadCatalog: {},
73
- SucceededLoadPainting: { paintingId: S.Number },
74
- UpdatedStudioDraft: { value: S.String },
75
- SucceededSaveDraft: { draft: S.String },
65
+ SucceededLoadPainting: { paintingId: Schema.Number },
66
+ UpdatedStudioDraft: { value: Schema.String },
67
+ SucceededSaveDraft: { draft: Schema.String },
76
68
  })
77
69
 
78
70
  export type Message = typeof Message.Type
@@ -80,14 +72,14 @@ export type Message = typeof Message.Type
80
72
  // COMMAND
81
73
 
82
74
  const NavigateInternal = Command.define('NavigateInternal', {
83
- args: { url: S.String },
75
+ args: { url: Schema.String },
84
76
  messages: [Message.CompletedNavigateInternal],
85
77
  execute: ({ url }) =>
86
78
  pushUrl(url).pipe(Effect.as(Message.CompletedNavigateInternal())),
87
79
  })
88
80
 
89
81
  const LoadExternal = Command.define('LoadExternal', {
90
- args: { href: S.String },
82
+ args: { href: Schema.String },
91
83
  messages: [Message.CompletedLoadExternal],
92
84
  execute: ({ href }) =>
93
85
  load(href).pipe(Effect.as(Message.CompletedLoadExternal())),
@@ -101,7 +93,7 @@ export const LoadCatalog = Command.define('LoadCatalog', {
101
93
  })
102
94
 
103
95
  export const LoadPainting = Command.define('LoadPainting', {
104
- args: { paintingId: S.Number },
96
+ args: { paintingId: Schema.Number },
105
97
  messages: [Message.SucceededLoadPainting],
106
98
  execute: ({ paintingId }) =>
107
99
  Effect.sleep(PAINTING_LATENCY).pipe(
@@ -110,7 +102,7 @@ export const LoadPainting = Command.define('LoadPainting', {
110
102
  })
111
103
 
112
104
  export const SaveDraft = Command.define('SaveDraft', {
113
- args: { draft: S.String },
105
+ args: { draft: Schema.String },
114
106
  messages: [Message.SucceededSaveDraft],
115
107
  execute: ({ draft }) =>
116
108
  Effect.sleep(SAVE_LATENCY).pipe(
@@ -748,9 +740,11 @@ const transitionLogView = (
748
740
  )
749
741
 
750
742
  const routeTitle = (route: AppRoute): string =>
751
- M.value(route).pipe(
752
- M.tag('Home', () => 'Route Transitions'),
753
- M.orElse(currentRoute => `${routeLabel(currentRoute)} | Route Transitions`),
743
+ Match.value(route).pipe(
744
+ Match.tag('Home', () => 'Route Transitions'),
745
+ Match.orElse(
746
+ currentRoute => `${routeLabel(currentRoute)} | Route Transitions`,
747
+ ),
754
748
  )
755
749
 
756
750
  export const view = (model: Model, h: HtmlBuilder<Message>): Document => {
@@ -1,13 +1,13 @@
1
- import { Schema as S, pipe } from 'effect'
1
+ import { Schema, pipe } from 'effect'
2
2
  import { Route } from 'foldkit'
3
3
  import { defineRouteUnion, int, literal, slash } from 'foldkit/route'
4
4
 
5
5
  export const AppRoute = defineRouteUnion({
6
6
  Home: {},
7
7
  Gallery: {},
8
- Painting: { paintingId: S.Number },
8
+ Painting: { paintingId: Schema.Number },
9
9
  Studio: {},
10
- NotFound: { path: S.String },
10
+ NotFound: { path: Schema.String },
11
11
  })
12
12
 
13
13
  export type AppRoute = typeof AppRoute.Type
@@ -1,4 +1,4 @@
1
- import { Array, Match as M, Option, Schema as S, pipe } from 'effect'
1
+ import { Array, Match, Option, Schema, pipe } from 'effect'
2
2
  import { taggedStruct } from 'foldkit/schema'
3
3
 
4
4
  export type File = typeof File.Type
@@ -10,16 +10,18 @@ export type Directory = Readonly<{
10
10
  export type FileTreeEntry = File | Directory
11
11
 
12
12
  export const File = taggedStruct('File', {
13
- name: S.String,
14
- sizeInBytes: S.Number,
13
+ name: Schema.String,
14
+ sizeInBytes: Schema.Number,
15
15
  })
16
16
 
17
17
  export const Directory = taggedStruct('Directory', {
18
- name: S.String,
19
- entries: S.Array(S.suspend((): S.Codec<FileTreeEntry> => FileTreeEntry)),
18
+ name: Schema.String,
19
+ entries: Schema.Array(
20
+ Schema.suspend((): Schema.Codec<FileTreeEntry> => FileTreeEntry),
21
+ ),
20
22
  })
21
23
 
22
- export const FileTreeEntry = S.Union([File, Directory])
24
+ export const FileTreeEntry = Schema.Union([File, Directory])
23
25
 
24
26
  export const fileTree: ReadonlyArray<FileTreeEntry> = [
25
27
  Directory({
@@ -57,8 +59,8 @@ const findDirectoryEntries = (
57
59
  pipe(
58
60
  Array.findFirst(entries, entry => entry.name === name),
59
61
  Option.flatMap(entry =>
60
- M.value(entry).pipe(
61
- M.tagsExhaustive({
62
+ Match.value(entry).pipe(
63
+ Match.tagsExhaustive({
62
64
  File: () => Option.none(),
63
65
  Directory: directory => Option.some(directory.entries),
64
66
  }),
@@ -1,4 +1,4 @@
1
- import { Array, Effect, Match as M, Option, Schema as S } from 'effect'
1
+ import { Array, Effect, Match, Option, Schema } from 'effect'
2
2
  import { Command, Runtime, Update } from 'foldkit'
3
3
  import { Document, Html, HtmlBuilder } from 'foldkit/html'
4
4
  import { defineMessageUnion } from 'foldkit/message'
@@ -28,7 +28,7 @@ export { AppRoute } from './route'
28
28
 
29
29
  // MODEL
30
30
 
31
- export const Model = S.Struct({
31
+ export const Model = Schema.Struct({
32
32
  route: AppRoute,
33
33
  peoplePage: People.Model,
34
34
  })
@@ -54,9 +54,9 @@ export const init: Runtime.RoutingApplicationInit<Model, Message> = (
54
54
  ) => {
55
55
  const route = urlToAppRoute(url)
56
56
 
57
- const initialPeopleRoute = M.value(route).pipe(
58
- M.tag('People', peopleRoute => peopleRoute),
59
- M.orElse(() => AppRoute.People({ searchText: Option.none() })),
57
+ const initialPeopleRoute = Match.value(route).pipe(
58
+ Match.tag('People', peopleRoute => peopleRoute),
59
+ Match.orElse(() => AppRoute.People({ searchText: Option.none() })),
60
60
  )
61
61
 
62
62
  const peopleInit = People.init(initialPeopleRoute)
@@ -71,14 +71,14 @@ export const init: Runtime.RoutingApplicationInit<Model, Message> = (
71
71
  // COMMAND
72
72
 
73
73
  const NavigateInternal = Command.define('NavigateInternal', {
74
- args: { url: S.String },
74
+ args: { url: Schema.String },
75
75
  messages: [Message.CompletedNavigateInternal],
76
76
  execute: ({ url }) =>
77
77
  pushUrl(url).pipe(Effect.as(Message.CompletedNavigateInternal())),
78
78
  })
79
79
 
80
80
  const LoadExternal = Command.define('LoadExternal', {
81
- args: { href: S.String },
81
+ args: { href: Schema.String },
82
82
  messages: [Message.CompletedLoadExternal],
83
83
  execute: ({ href }) =>
84
84
  load(href).pipe(Effect.as(Message.CompletedLoadExternal())),
@@ -127,10 +127,12 @@ export const update = (model: Model, message: Message) =>
127
127
  ChangedUrl: ({ url }) => {
128
128
  const nextRoute = urlToAppRoute(url)
129
129
 
130
- const routeSteps = M.value(nextRoute).pipe(
131
- M.withReturnType<ReadonlyArray<Update.Step<Model, Message>>>(),
132
- M.tag('People', peopleRoute => [foldPeopleRouteChanged(peopleRoute)]),
133
- M.orElse(() => []),
130
+ const routeSteps = Match.value(nextRoute).pipe(
131
+ Match.withReturnType<ReadonlyArray<Update.Step<Model, Message>>>(),
132
+ Match.tag('People', peopleRoute => [
133
+ foldPeopleRouteChanged(peopleRoute),
134
+ ]),
135
+ Match.orElse(() => []),
134
136
  )
135
137
 
136
138
  return Update.combine(model, [setRoute(nextRoute), ...routeSteps])
@@ -372,8 +374,8 @@ const entryListView = (
372
374
  ],
373
375
  [entry.name],
374
376
  ),
375
- M.value(entry).pipe(
376
- M.tagsExhaustive({
377
+ Match.value(entry).pipe(
378
+ Match.tagsExhaustive({
377
379
  File: file =>
378
380
  h.span(
379
381
  [h.Class('text-sm text-gray-500')],
@@ -484,8 +486,8 @@ const filesView = (
484
486
  const content = Option.match(maybeEntry, {
485
487
  onNone: () => missingEntryView(path, h),
486
488
  onSome: entry =>
487
- M.value(entry).pipe(
488
- M.tagsExhaustive({
489
+ Match.value(entry).pipe(
490
+ Match.tagsExhaustive({
489
491
  File: file => fileDetailView(file, h),
490
492
  Directory: directory => entryListView(path, directory.entries, h),
491
493
  }),
@@ -518,15 +520,15 @@ const notFoundView = (path: string, h: HtmlBuilder<Message>): Html =>
518
520
  )
519
521
 
520
522
  const routeTitle = (route: Model['route']): string =>
521
- M.value(route).pipe(
522
- M.tag('Home', () => 'Routing'),
523
- M.tag('Person', ({ personId }) => `Person ${personId} | Routing`),
524
- M.tag('FilesIndex', () => 'Files | Routing'),
525
- M.tag(
523
+ Match.value(route).pipe(
524
+ Match.tag('Home', () => 'Routing'),
525
+ Match.tag('Person', ({ personId }) => `Person ${personId} | Routing`),
526
+ Match.tag('FilesIndex', () => 'Files | Routing'),
527
+ Match.tag(
526
528
  'Files',
527
529
  ({ path }) => `${Array.lastNonEmpty(path)} | Files | Routing`,
528
530
  ),
529
- M.orElse(({ _tag }) => `${_tag} | Routing`),
531
+ Match.orElse(({ _tag }) => `${_tag} | Routing`),
530
532
  )
531
533
 
532
534
  export const view = (model: Model, h: HtmlBuilder<Message>): Document => {