reactive_flexlist.km 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. import window from '../ui/web/window';
  2. do { window::mount Root };
  3. type Todo {
  4. content: String,
  5. finished: Bool
  6. };
  7. function SmallButton:
  8. &(String,Async) => ui::Component
  9. &(args) => ({ ui::Button args } with { ui::Style ['min-width-2'] });
  10. const Root: ui::Component :=
  11. let center := { ui::StyledContainer ['center'] },
  12. let row := { ui::StyledContainer ['row'] },
  13. \ list := use { ui::State { FlexList::[Todo] () } },
  14. let add-item-from: &(Reactive[String]) => Sync :=
  15. &(buffer) =>
  16. \ content := sync buffer.{->},
  17. \ id := sync { gen-monotonic-id-string () },
  18. \ sync (list append (id, { content, finished: No })),
  19. (buffer <- ''),
  20. let insert-item-after: &(FlexListKey) => Sync :=
  21. &(pivot) =>
  22. \ id := sync { gen-monotonic-id-string () },
  23. { insert (list, {after:pivot}, (id, { content: '', finished: No })) },
  24. { center [
  25. \ buffer := use { ui::State::[String] '' },
  26. { row [
  27. { ui::Input buffer },
  28. { ui::Button ('Add', { add-item-from buffer }) }
  29. ] },
  30. \ (id, index, item) := ui::ListView list,
  31. let content := (item proj |.(content)|),
  32. let finished := (item proj |.(finished)|),
  33. { row [
  34. { ui::Checkbox finished },
  35. { ui::Input content },
  36. { row [
  37. { SmallButton ('↑', (list move-up id)) }
  38. . { with { ui::EnableCond { not (index is-first-in list) } } },
  39. { SmallButton ('↓', (list move-down id)) }
  40. . { with { ui::EnableCond { not (index is-last-in list) } } },
  41. { SmallButton ('+', { insert-item-after id }) },
  42. { SmallButton ('×', (list delete id)) }
  43. ] }
  44. ] }
  45. ] };