@flickfyi/flkr 0.0.182 → 0.0.185

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 (243) hide show
  1. package/dist/{api-client-CAg1b8Bh.js → api-client-nn4U_Vfn.js} +1 -1
  2. package/dist/{app-DpM5nhb9.js → app-COXGJhrt.js} +3 -3
  3. package/dist/{bundler-DNrDcqyk.js → bundler-CW4YC73e.js} +4 -2
  4. package/dist/cli.js +11 -11
  5. package/dist/{delegate-DcVye0KE.js → delegate-aUVluBjB.js} +2 -2
  6. package/dist/{generate-B1l1z_FZ.js → generate-BeL1QPDi.js} +1 -1
  7. package/dist/{preview-Dqn_Tq6K.js → preview-DTVM8Csb.js} +2 -2
  8. package/dist/{publish-BmDqO1xU.js → publish-BJG-s-w5.js} +4 -4
  9. package/dist/{pull-CO80DMn8.js → pull-B_Yfjpi2.js} +1 -1
  10. package/dist/{save-8crfOeo1.js → save-UrfgmK2-.js} +2 -2
  11. package/dist/{sdk-app-BXWrf_pf.js → sdk-app-BAxznAf9.js} +3 -3
  12. package/dist/{sdk-deploy-CaEonlvx.js → sdk-deploy-D1wgQxse.js} +3 -3
  13. package/dist/{sdk-generation-CF8ATbrL.js → sdk-generation-CLQ-QrVM.js} +1 -1
  14. package/dist/{sdk-project-CKV3U3u9.js → sdk-project-BaO0fqhW.js} +1 -1
  15. package/dist/{use-auth-B6nwU2rp.js → use-auth-CtM4_BAY.js} +1 -1
  16. package/node_modules/@flickfyi/biscuit/.turbo/turbo-build.log +4 -4
  17. package/node_modules/@flickfyi/core/README.md +19 -9
  18. package/node_modules/@flickfyi/core/dist/chunks/{default-CuxDsQoM.js → default-BTmKidHV.js} +1 -1
  19. package/node_modules/@flickfyi/core/dist/chunks/{default-BB6YexEH.cjs → default-JhTq5I_y.cjs} +1 -1
  20. package/node_modules/@flickfyi/core/dist/chunks/{define-CUJRqVKY.cjs → define-BKCRhpuY.cjs} +1 -1
  21. package/node_modules/@flickfyi/core/dist/chunks/{define-e_VqSs4M.js → define-DZXgUsy7.js} +5 -5
  22. package/node_modules/@flickfyi/core/dist/kowalski/catalog.cjs +1 -1
  23. package/node_modules/@flickfyi/core/dist/kowalski/catalog.js +728 -549
  24. package/node_modules/@flickfyi/core/dist/kowalski/index.cjs +5 -5
  25. package/node_modules/@flickfyi/core/dist/kowalski/index.js +4297 -3700
  26. package/node_modules/@flickfyi/core/dist/kowalski/schemas.cjs +1 -0
  27. package/node_modules/@flickfyi/core/dist/kowalski/schemas.js +637 -0
  28. package/node_modules/@flickfyi/core/dist/kowalski-catalog.css +516 -0
  29. package/node_modules/@flickfyi/core/dist/kowalski.css +10 -0
  30. package/node_modules/@flickfyi/core/dist/themes/athletic/athletic.cjs +1 -1
  31. package/node_modules/@flickfyi/core/dist/themes/athletic/athletic.js +1 -1
  32. package/node_modules/@flickfyi/core/dist/themes/compact/compact.cjs +1 -1
  33. package/node_modules/@flickfyi/core/dist/themes/compact/compact.js +1 -1
  34. package/node_modules/@flickfyi/core/dist/themes/default/default.cjs +1 -1
  35. package/node_modules/@flickfyi/core/dist/themes/default/default.js +1 -1
  36. package/node_modules/@flickfyi/core/dist/themes/editorial/editorial.cjs +1 -1
  37. package/node_modules/@flickfyi/core/dist/themes/editorial/editorial.js +1 -1
  38. package/node_modules/@flickfyi/core/dist/themes/handwritten/handwritten.cjs +1 -1
  39. package/node_modules/@flickfyi/core/dist/themes/handwritten/handwritten.js +1 -1
  40. package/node_modules/@flickfyi/core/dist/themes/index.cjs +1 -1
  41. package/node_modules/@flickfyi/core/dist/themes/index.js +1 -1
  42. package/node_modules/@flickfyi/core/dist/themes/kids/kids.cjs +1 -1
  43. package/node_modules/@flickfyi/core/dist/themes/kids/kids.js +1 -1
  44. package/node_modules/@flickfyi/core/dist/themes/rounded/rounded.cjs +1 -1
  45. package/node_modules/@flickfyi/core/dist/themes/rounded/rounded.js +1 -1
  46. package/node_modules/@flickfyi/core/dist/themes/technical/technical.cjs +1 -1
  47. package/node_modules/@flickfyi/core/dist/themes/technical/technical.js +1 -1
  48. package/node_modules/@flickfyi/core/dist-types/hooks/use-feature-store/index.d.ts +43 -0
  49. package/node_modules/@flickfyi/core/dist-types/kowalski/calculations.d.ts +57 -3
  50. package/node_modules/@flickfyi/core/dist-types/kowalski/calculator.d.ts +7 -6
  51. package/node_modules/@flickfyi/core/dist-types/kowalski/catalog.d.cts +524 -809
  52. package/node_modules/@flickfyi/core/dist-types/kowalski/catalog.d.ts +524 -809
  53. package/node_modules/@flickfyi/core/dist-types/kowalski/components/bill-split.d.ts +38 -0
  54. package/node_modules/@flickfyi/core/dist-types/kowalski/components/bookmark.d.ts +48 -0
  55. package/node_modules/@flickfyi/core/dist-types/kowalski/components/budget.d.ts +39 -0
  56. package/node_modules/@flickfyi/core/dist-types/kowalski/components/calculator.d.ts +62 -0
  57. package/node_modules/@flickfyi/core/dist-types/kowalski/components/checklist.d.ts +35 -0
  58. package/node_modules/@flickfyi/core/dist-types/kowalski/components/color-palette.d.ts +32 -0
  59. package/node_modules/@flickfyi/core/dist-types/kowalski/components/contact.d.ts +41 -0
  60. package/node_modules/@flickfyi/core/dist-types/kowalski/components/countdown.d.ts +34 -0
  61. package/node_modules/@flickfyi/core/dist-types/kowalski/components/event.d.ts +43 -0
  62. package/node_modules/@flickfyi/core/dist-types/kowalski/components/expense.d.ts +40 -0
  63. package/node_modules/@flickfyi/core/dist-types/kowalski/components/goal.d.ts +36 -0
  64. package/node_modules/@flickfyi/core/dist-types/kowalski/components/habit.d.ts +57 -0
  65. package/node_modules/@flickfyi/core/dist-types/kowalski/components/ledger.d.ts +43 -0
  66. package/node_modules/@flickfyi/core/dist-types/kowalski/components/note.d.ts +35 -0
  67. package/node_modules/@flickfyi/core/dist-types/kowalski/components/poll.d.ts +41 -0
  68. package/node_modules/@flickfyi/core/dist-types/kowalski/components/random-picker.d.ts +69 -0
  69. package/node_modules/@flickfyi/core/dist-types/kowalski/components/rating.d.ts +33 -0
  70. package/node_modules/@flickfyi/core/dist-types/kowalski/components/reminder.d.ts +48 -0
  71. package/node_modules/@flickfyi/core/dist-types/kowalski/components/rotation.d.ts +39 -0
  72. package/node_modules/@flickfyi/core/dist-types/kowalski/components/scoreboard.d.ts +37 -0
  73. package/node_modules/@flickfyi/core/dist-types/kowalski/components/shopping-list.d.ts +41 -0
  74. package/node_modules/@flickfyi/core/dist-types/kowalski/components/task-board.d.ts +39 -0
  75. package/node_modules/@flickfyi/core/dist-types/kowalski/components/time-zone.d.ts +34 -0
  76. package/node_modules/@flickfyi/core/dist-types/kowalski/components/timer.d.ts +43 -0
  77. package/node_modules/@flickfyi/core/dist-types/kowalski/components/trip.d.ts +61 -0
  78. package/node_modules/@flickfyi/core/dist-types/kowalski/components/unit-converter.d.ts +106 -0
  79. package/node_modules/@flickfyi/core/dist-types/kowalski/create-schemas.d.ts +6 -0
  80. package/node_modules/@flickfyi/core/dist-types/kowalski/date-time.d.ts +1 -1
  81. package/node_modules/@flickfyi/core/dist-types/kowalski/everyday.d.ts +28 -8
  82. package/node_modules/@flickfyi/core/dist-types/kowalski/feature-schema.d.ts +65 -0
  83. package/node_modules/@flickfyi/core/dist-types/kowalski/format.d.ts +4 -0
  84. package/node_modules/@flickfyi/core/dist-types/kowalski/fortune.d.ts +21 -0
  85. package/node_modules/@flickfyi/core/dist-types/kowalski/frame.d.ts +4 -4
  86. package/node_modules/@flickfyi/core/dist-types/kowalski/index.d.cts +31 -7
  87. package/node_modules/@flickfyi/core/dist-types/kowalski/index.d.ts +31 -7
  88. package/node_modules/@flickfyi/core/dist-types/kowalski/lesson.d.ts +89 -0
  89. package/node_modules/@flickfyi/core/dist-types/kowalski/recipe.d.ts +129 -8
  90. package/node_modules/@flickfyi/core/dist-types/kowalski/schemas.d.cts +4 -0
  91. package/node_modules/@flickfyi/core/dist-types/kowalski/schemas.d.ts +4 -0
  92. package/node_modules/@flickfyi/core/dist-types/kowalski/time-since.d.ts +34 -0
  93. package/node_modules/@flickfyi/core/examples/example-metadata.ts +19 -2
  94. package/node_modules/@flickfyi/core/examples/kowalski/bill-split/bill-split.stories.tsx +25 -6
  95. package/node_modules/@flickfyi/core/examples/kowalski/bill-split/bill-split.tsx +6 -12
  96. package/node_modules/@flickfyi/core/examples/kowalski/bookmark/bookmark.stories.tsx +22 -5
  97. package/node_modules/@flickfyi/core/examples/kowalski/bookmark/bookmark.tsx +6 -18
  98. package/node_modules/@flickfyi/core/examples/kowalski/budget/budget.stories.tsx +26 -5
  99. package/node_modules/@flickfyi/core/examples/kowalski/budget/budget.tsx +6 -21
  100. package/node_modules/@flickfyi/core/examples/kowalski/calculator/calculator.stories.tsx +18 -5
  101. package/node_modules/@flickfyi/core/examples/kowalski/calculator/calculator.tsx +6 -19
  102. package/node_modules/@flickfyi/core/examples/kowalski/checklist/checklist.stories.tsx +25 -5
  103. package/node_modules/@flickfyi/core/examples/kowalski/checklist/checklist.tsx +6 -21
  104. package/node_modules/@flickfyi/core/examples/kowalski/color-palette/color-palette.stories.tsx +19 -6
  105. package/node_modules/@flickfyi/core/examples/kowalski/color-palette/color-palette.tsx +6 -17
  106. package/node_modules/@flickfyi/core/examples/kowalski/contact/contact.stories.tsx +30 -5
  107. package/node_modules/@flickfyi/core/examples/kowalski/contact/contact.tsx +6 -18
  108. package/node_modules/@flickfyi/core/examples/kowalski/countdown/countdown.stories.tsx +22 -5
  109. package/node_modules/@flickfyi/core/examples/kowalski/countdown/countdown.tsx +6 -18
  110. package/node_modules/@flickfyi/core/examples/kowalski/event/event.stories.tsx +23 -5
  111. package/node_modules/@flickfyi/core/examples/kowalski/event/event.tsx +6 -19
  112. package/node_modules/@flickfyi/core/examples/kowalski/expense/expense.stories.tsx +23 -5
  113. package/node_modules/@flickfyi/core/examples/kowalski/expense/expense.tsx +6 -18
  114. package/node_modules/@flickfyi/core/examples/kowalski/fortune/fortune.stories.tsx +61 -0
  115. package/node_modules/@flickfyi/core/examples/kowalski/fortune/fortune.tsx +11 -0
  116. package/node_modules/@flickfyi/core/examples/kowalski/goal/goal.stories.tsx +18 -5
  117. package/node_modules/@flickfyi/core/examples/kowalski/goal/goal.tsx +3 -19
  118. package/node_modules/@flickfyi/core/examples/kowalski/habit/habit.stories.tsx +22 -5
  119. package/node_modules/@flickfyi/core/examples/kowalski/habit/habit.tsx +6 -18
  120. package/node_modules/@flickfyi/core/examples/kowalski/ledger/ledger.stories.tsx +25 -5
  121. package/node_modules/@flickfyi/core/examples/kowalski/ledger/ledger.tsx +6 -20
  122. package/node_modules/@flickfyi/core/examples/kowalski/lesson/lesson.stories.tsx +99 -0
  123. package/node_modules/@flickfyi/core/examples/kowalski/lesson/lesson.tsx +11 -0
  124. package/node_modules/@flickfyi/core/examples/kowalski/note/note.stories.tsx +21 -5
  125. package/node_modules/@flickfyi/core/examples/kowalski/note/note.tsx +3 -17
  126. package/node_modules/@flickfyi/core/examples/kowalski/poll/poll.stories.tsx +26 -5
  127. package/node_modules/@flickfyi/core/examples/kowalski/poll/poll.tsx +3 -21
  128. package/node_modules/@flickfyi/core/examples/kowalski/random-picker/random-picker.stories.tsx +37 -6
  129. package/node_modules/@flickfyi/core/examples/kowalski/random-picker/random-picker.tsx +6 -18
  130. package/node_modules/@flickfyi/core/examples/kowalski/rating/rating.stories.tsx +18 -5
  131. package/node_modules/@flickfyi/core/examples/kowalski/rating/rating.tsx +6 -14
  132. package/node_modules/@flickfyi/core/examples/kowalski/recipe/recipe.stories.tsx +117 -5
  133. package/node_modules/@flickfyi/core/examples/kowalski/recipe/recipe.tsx +6 -115
  134. package/node_modules/@flickfyi/core/examples/kowalski/reminder/reminder.stories.tsx +22 -5
  135. package/node_modules/@flickfyi/core/examples/kowalski/reminder/reminder.tsx +6 -18
  136. package/node_modules/@flickfyi/core/examples/kowalski/rotation/rotation.stories.tsx +26 -5
  137. package/node_modules/@flickfyi/core/examples/kowalski/rotation/rotation.tsx +6 -22
  138. package/node_modules/@flickfyi/core/examples/kowalski/scoreboard/scoreboard.stories.tsx +26 -5
  139. package/node_modules/@flickfyi/core/examples/kowalski/scoreboard/scoreboard.tsx +6 -21
  140. package/node_modules/@flickfyi/core/examples/kowalski/shopping-list/shopping-list.stories.tsx +28 -6
  141. package/node_modules/@flickfyi/core/examples/kowalski/shopping-list/shopping-list.tsx +6 -22
  142. package/node_modules/@flickfyi/core/examples/kowalski/task-board/task-board.stories.tsx +27 -6
  143. package/node_modules/@flickfyi/core/examples/kowalski/task-board/task-board.tsx +6 -22
  144. package/node_modules/@flickfyi/core/examples/kowalski/time-since/time-since.stories.tsx +33 -0
  145. package/node_modules/@flickfyi/core/examples/kowalski/time-since/time-since.tsx +12 -0
  146. package/node_modules/@flickfyi/core/examples/kowalski/time-zone/time-zone.stories.tsx +22 -6
  147. package/node_modules/@flickfyi/core/examples/kowalski/time-zone/time-zone.tsx +6 -17
  148. package/node_modules/@flickfyi/core/examples/kowalski/timer/timer.stories.tsx +18 -5
  149. package/node_modules/@flickfyi/core/examples/kowalski/timer/timer.tsx +6 -18
  150. package/node_modules/@flickfyi/core/examples/kowalski/trip/trip.stories.tsx +25 -5
  151. package/node_modules/@flickfyi/core/examples/kowalski/trip/trip.tsx +3 -21
  152. package/node_modules/@flickfyi/core/examples/kowalski/unit-converter/unit-converter.stories.tsx +19 -6
  153. package/node_modules/@flickfyi/core/examples/kowalski/unit-converter/unit-converter.tsx +6 -19
  154. package/node_modules/@flickfyi/core/examples/parrott/calculator/calculator.stories.tsx +10 -3
  155. package/node_modules/@flickfyi/core/examples/parrott/calculator/calculator.tsx +2 -13
  156. package/node_modules/@flickfyi/core/examples/parrott/checklist/checklist.stories.tsx +10 -3
  157. package/node_modules/@flickfyi/core/examples/parrott/checklist/checklist.tsx +0 -8
  158. package/node_modules/@flickfyi/core/examples/parrott/countdown/countdown.stories.tsx +10 -3
  159. package/node_modules/@flickfyi/core/examples/parrott/countdown/countdown.tsx +0 -8
  160. package/node_modules/@flickfyi/core/examples/parrott/counter/counter.stories.tsx +10 -3
  161. package/node_modules/@flickfyi/core/examples/parrott/counter/counter.tsx +0 -8
  162. package/node_modules/@flickfyi/core/examples/parrott/fortune/fortune.stories.tsx +10 -3
  163. package/node_modules/@flickfyi/core/examples/parrott/fortune/fortune.tsx +0 -8
  164. package/node_modules/@flickfyi/core/examples/parrott/grid/grid.stories.tsx +10 -3
  165. package/node_modules/@flickfyi/core/examples/parrott/grid/grid.tsx +4 -9
  166. package/node_modules/@flickfyi/core/examples/parrott/kale-smoothie/kale-smoothie.stories.tsx +10 -3
  167. package/node_modules/@flickfyi/core/examples/parrott/kale-smoothie/kale-smoothie.tsx +0 -8
  168. package/node_modules/@flickfyi/core/examples/parrott/list/list.stories.tsx +10 -3
  169. package/node_modules/@flickfyi/core/examples/parrott/list/list.tsx +0 -8
  170. package/node_modules/@flickfyi/core/examples/parrott/log/log.stories.tsx +10 -3
  171. package/node_modules/@flickfyi/core/examples/parrott/log/log.tsx +0 -8
  172. package/node_modules/@flickfyi/core/examples/parrott/timed-task/timed-task.stories.tsx +10 -3
  173. package/node_modules/@flickfyi/core/examples/parrott/timed-task/timed-task.tsx +0 -8
  174. package/node_modules/@flickfyi/core/examples/parrott/timer/timer.stories.tsx +10 -3
  175. package/node_modules/@flickfyi/core/examples/parrott/timer/timer.tsx +0 -8
  176. package/node_modules/@flickfyi/core/package.json +16 -3
  177. package/node_modules/@flickfyi/core/src/{kowalski/use-configured-feature.ts → hooks/use-configured-feature/index.ts} +1 -1
  178. package/node_modules/@flickfyi/core/src/{kowalski/use-feature-store.ts → hooks/use-feature-store/index.ts} +37 -12
  179. package/node_modules/@flickfyi/core/src/kowalski/README.md +13 -0
  180. package/node_modules/@flickfyi/core/src/kowalski/calculations.ts +36 -8
  181. package/node_modules/@flickfyi/core/src/kowalski/calculator.ts +15 -7
  182. package/node_modules/@flickfyi/core/src/kowalski/catalog.ts +110 -704
  183. package/node_modules/@flickfyi/core/src/kowalski/components/bill-split.tsx +284 -0
  184. package/node_modules/@flickfyi/core/src/kowalski/components/bookmark.tsx +347 -0
  185. package/node_modules/@flickfyi/core/src/kowalski/components/budget.tsx +169 -0
  186. package/node_modules/@flickfyi/core/src/kowalski/components/calculator.tsx +202 -0
  187. package/node_modules/@flickfyi/core/src/kowalski/components/checklist.tsx +119 -0
  188. package/node_modules/@flickfyi/core/src/kowalski/components/color-palette.tsx +302 -0
  189. package/node_modules/@flickfyi/core/src/kowalski/components/contact.tsx +247 -0
  190. package/node_modules/@flickfyi/core/src/kowalski/components/countdown.tsx +173 -0
  191. package/node_modules/@flickfyi/core/src/kowalski/components/event.tsx +260 -0
  192. package/node_modules/@flickfyi/core/src/kowalski/components/expense.tsx +257 -0
  193. package/node_modules/@flickfyi/core/src/kowalski/components/goal.tsx +182 -0
  194. package/node_modules/@flickfyi/core/src/kowalski/components/habit.tsx +272 -0
  195. package/node_modules/@flickfyi/core/src/kowalski/components/ledger.tsx +211 -0
  196. package/node_modules/@flickfyi/core/src/kowalski/components/note.tsx +188 -0
  197. package/node_modules/@flickfyi/core/src/kowalski/components/poll.tsx +242 -0
  198. package/node_modules/@flickfyi/core/src/kowalski/components/random-picker.tsx +308 -0
  199. package/node_modules/@flickfyi/core/src/kowalski/components/rating.tsx +112 -0
  200. package/node_modules/@flickfyi/core/src/kowalski/components/reminder.tsx +298 -0
  201. package/node_modules/@flickfyi/core/src/kowalski/components/rotation.tsx +146 -0
  202. package/node_modules/@flickfyi/core/src/kowalski/components/scoreboard.tsx +139 -0
  203. package/node_modules/@flickfyi/core/src/kowalski/components/shopping-list.tsx +144 -0
  204. package/node_modules/@flickfyi/core/src/kowalski/components/task-board.tsx +146 -0
  205. package/node_modules/@flickfyi/core/src/kowalski/components/time-zone.tsx +240 -0
  206. package/node_modules/@flickfyi/core/src/kowalski/components/timer.tsx +225 -0
  207. package/node_modules/@flickfyi/core/src/kowalski/components/trip.tsx +338 -0
  208. package/node_modules/@flickfyi/core/src/kowalski/components/unit-converter.tsx +285 -0
  209. package/node_modules/@flickfyi/core/src/kowalski/create-schemas.ts +8 -0
  210. package/node_modules/@flickfyi/core/src/kowalski/date-time.tsx +1 -1
  211. package/node_modules/@flickfyi/core/src/kowalski/everyday.tsx +1 -640
  212. package/node_modules/@flickfyi/core/src/kowalski/feature-schema.ts +84 -0
  213. package/node_modules/@flickfyi/core/src/kowalski/format.ts +29 -3
  214. package/node_modules/@flickfyi/core/src/kowalski/fortune.tsx +67 -0
  215. package/node_modules/@flickfyi/core/src/kowalski/frame.tsx +5 -6
  216. package/node_modules/@flickfyi/core/src/kowalski/index.ts +31 -22
  217. package/node_modules/@flickfyi/core/src/kowalski/lesson.tsx +564 -0
  218. package/node_modules/@flickfyi/core/src/kowalski/recipe.tsx +78 -37
  219. package/node_modules/@flickfyi/core/src/kowalski/schemas.ts +67 -0
  220. package/node_modules/@flickfyi/core/src/kowalski/stories/composition.tsx +22 -20
  221. package/node_modules/@flickfyi/core/src/kowalski/time-since.tsx +145 -0
  222. package/node_modules/@flickfyi/core/src/molecules/progress/progress.tsx +4 -1
  223. package/node_modules/@flickfyi/core/src/oklch.ts +1 -6
  224. package/node_modules/@flickfyi/core/src/parrott/theme.ts +3 -1
  225. package/node_modules/@flickfyi/core/src/themes/editorial/editorial.ts +6 -1
  226. package/node_modules/@flickfyi/core/src/themes/palette.ts +5 -5
  227. package/node_modules/@flickfyi/core/src/themes/stories/composition.tsx +11 -9
  228. package/node_modules/@flickfyi/core/src/themes/stories/gallery.tsx +7 -11
  229. package/node_modules/@flickfyi/core/tsgo.bun.lock +7 -7
  230. package/node_modules/@flickfyi/core/tsgo.package.json +1 -1
  231. package/package.json +2 -2
  232. package/node_modules/@flickfyi/core/dist-types/kowalski/clocks.d.ts +0 -4
  233. package/node_modules/@flickfyi/core/dist-types/kowalski/details.d.ts +0 -7
  234. package/node_modules/@flickfyi/core/dist-types/kowalski/productivity.d.ts +0 -5
  235. package/node_modules/@flickfyi/core/dist-types/kowalski/tools.d.ts +0 -7
  236. package/node_modules/@flickfyi/core/dist-types/kowalski/use-feature-store.d.ts +0 -15
  237. package/node_modules/@flickfyi/core/src/kowalski/clocks.tsx +0 -464
  238. package/node_modules/@flickfyi/core/src/kowalski/details.tsx +0 -1387
  239. package/node_modules/@flickfyi/core/src/kowalski/productivity.tsx +0 -575
  240. package/node_modules/@flickfyi/core/src/kowalski/tools.tsx +0 -1213
  241. /package/node_modules/@flickfyi/core/dist-types/{kowalski/use-clock.d.ts → hooks/use-clock/index.d.ts} +0 -0
  242. /package/node_modules/@flickfyi/core/dist-types/{kowalski/use-configured-feature.d.ts → hooks/use-configured-feature/index.d.ts} +0 -0
  243. /package/node_modules/@flickfyi/core/src/{kowalski/use-clock.ts → hooks/use-clock/index.ts} +0 -0
@@ -0,0 +1,182 @@
1
+ import { Flex, Icon, Text } from '@flickfyi/core'
2
+ import * as stylex from '@stylexjs/stylex'
3
+ import { Decimal } from 'decimal.js'
4
+ import { useMemo } from 'react'
5
+ import { z } from 'zod/v4'
6
+
7
+ import { useConfiguredFeature } from '~/hooks/use-configured-feature'
8
+ import type { CreateSchemas } from '~/kowalski/create-schemas'
9
+ import { featureFields, store } from '~/kowalski/feature-schema'
10
+ import { format } from '~/kowalski/format'
11
+ import {
12
+ FeatureAction,
13
+ FeatureFrame,
14
+ FeatureProgress,
15
+ FeatureWell,
16
+ layout,
17
+ } from '~/kowalski/frame'
18
+ import { space, text } from '~/themes/scale.stylex'
19
+ import { appearance, roles } from '~/themes/shared'
20
+ import { font } from '~/themes/tokens.stylex'
21
+
22
+ const defaultId = 'KowalskiGoal'
23
+ const defaultScope = 'private'
24
+
25
+ export const GoalData = /* @__PURE__ */ z
26
+ .strictObject({
27
+ progress: z.number().optional().describe('Progress so far. Omit for 0.'),
28
+ step: z
29
+ .number()
30
+ .optional()
31
+ .describe('How much one tap adds, e.g. 1 or 0.5. Omit for 1.'),
32
+ target: z.number().describe('The amount that completes the goal, e.g. 10.'),
33
+ title: z.string().describe('A short heading.'),
34
+ unit: z
35
+ .string()
36
+ .optional()
37
+ .describe('A short unit after the numbers, e.g. "km" or "pages". Omit for none.'),
38
+ })
39
+ .describe(
40
+ 'A personal goal with editable progress, target, and a fixed increment. Not a distributed counter.'
41
+ )
42
+
43
+ export type GoalData = z.infer<typeof GoalData>
44
+
45
+ export const GoalProps = z.strictObject({
46
+ data: GoalData,
47
+ ...featureFields,
48
+ scope: featureFields.scope.default(defaultScope),
49
+ })
50
+
51
+ export type GoalProps = z.input<typeof GoalProps> & {
52
+ style?: stylex.StyleXArray<stylex.StyleXStyles>
53
+ }
54
+
55
+ export const goalStoreSchema = store({ progress: z.number().default(0) })
56
+
57
+ export const createSchemas: CreateSchemas = ({
58
+ id = defaultId,
59
+ scope = defaultScope,
60
+ } = {}) => ({
61
+ [`stores/${scope}/${id}`]: goalStoreSchema,
62
+ })
63
+
64
+ export function Goal({ data, id, revision = 0, scope = defaultScope, style }: GoalProps) {
65
+ const schema = goalStoreSchema
66
+ const store = useConfiguredFeature({
67
+ name: id ?? defaultId,
68
+ revision,
69
+ schema,
70
+ scope,
71
+ seed: schema.parse({ progress: data.progress }),
72
+ })
73
+ const progress = store.value.progress
74
+ const step = data.step ?? 1
75
+ const loading = !store.ready && !store.error
76
+ const reached = !loading && progress >= data.target
77
+ const number = useMemo(
78
+ () =>
79
+ format.formatters.getNumberFormat(format.locale, { maximumSignificantDigits: 17 }),
80
+ []
81
+ )
82
+ const distance = new Decimal(data.target).minus(progress).abs().toNumber()
83
+ const progressLabel = loading ? '—' : number.format(progress)
84
+ const targetLabel = number.format(data.target)
85
+ const distanceLabel = number.format(distance)
86
+ const stepLabel = number.format(step)
87
+ const nextProgress = new Decimal(progress).plus(step).toNumber()
88
+ const previousProgress = Decimal.max(0, new Decimal(progress).minus(step)).toNumber()
89
+ const unit = data.unit ? ` ${data.unit}` : ''
90
+ const change = (direction: -1 | 1) =>
91
+ store.set(current => {
92
+ const next = Decimal.max(
93
+ 0,
94
+ new Decimal(current.progress).plus(step * direction)
95
+ ).toNumber()
96
+ return { progress: Number.isFinite(next) ? next : current.progress }
97
+ })
98
+ return (
99
+ <FeatureFrame
100
+ style={style}
101
+ onRetry={store.retry}
102
+ notice={store.error}
103
+ component="goal"
104
+ title={data.title}
105
+ >
106
+ <FeatureWell>
107
+ <Flex {...stylex.props(goalStyles.metric)}>
108
+ <Text
109
+ animated="numeric"
110
+ {...stylex.props(roles.display, goalStyles.value(progressLabel.length))}
111
+ >
112
+ {progressLabel}
113
+ </Text>
114
+ <Text {...stylex.props(roles.muted)}>{`of ${targetLabel}${unit}`}</Text>
115
+ </Flex>
116
+ <FeatureProgress
117
+ component="goal"
118
+ value={loading ? 0 : data.target > 0 ? progress / data.target : 1}
119
+ />
120
+ {(loading || reached) && (
121
+ <Flex {...stylex.props(goalStyles.status)}>
122
+ {reached && (
123
+ <Icon name="checkmark.circle.fill" {...stylex.props(appearance.accent)} />
124
+ )}
125
+ <Text {...stylex.props(roles.muted, reached && appearance.accent)}>
126
+ {loading
127
+ ? 'Loading saved progress…'
128
+ : progress > data.target
129
+ ? `Goal reached, ${distanceLabel}${unit} beyond your target`
130
+ : 'Goal reached'}
131
+ </Text>
132
+ </Flex>
133
+ )}
134
+ </FeatureWell>
135
+ <Flex {...stylex.props(goalStyles.controls)}>
136
+ <Flex {...stylex.props(layout.actions)}>
137
+ <FeatureAction
138
+ component="goal"
139
+ disabled={!store.ready || previousProgress === progress}
140
+ onClick={() => change(-1)}
141
+ >{`−${stepLabel}`}</FeatureAction>
142
+ <FeatureAction
143
+ component="goal"
144
+ variant="primary"
145
+ disabled={
146
+ !store.ready || !Number.isFinite(nextProgress) || nextProgress === progress
147
+ }
148
+ onClick={() => change(1)}
149
+ >{`+${stepLabel}`}</FeatureAction>
150
+ </Flex>
151
+ {store.saving && <Text {...stylex.props(roles.muted)}>Saving progress…</Text>}
152
+ {store.ready && nextProgress === progress && previousProgress === progress && (
153
+ <Text {...stylex.props(roles.muted)}>
154
+ This increment is too small to change this total.
155
+ </Text>
156
+ )}
157
+ </Flex>
158
+ </FeatureFrame>
159
+ )
160
+ }
161
+
162
+ const goalStyles = /* @__PURE__ */ stylex.create({
163
+ controls: { gap: space[2] },
164
+ metric: {
165
+ alignItems: 'baseline',
166
+ flexDirection: 'row',
167
+ flexWrap: 'wrap',
168
+ gap: space[2],
169
+ },
170
+ status: { alignItems: 'center', flexDirection: 'row', gap: space[1.5] },
171
+ value: (length: number) => ({
172
+ fontSize: length > 12 ? text.xl : length > 7 ? text['4xl'] : font.displaySize,
173
+ lineHeight:
174
+ length > 12
175
+ ? text.xlLeading
176
+ : length > 7
177
+ ? text['4xlLeading']
178
+ : font.displayLeading,
179
+ maxWidth: '100%',
180
+ minWidth: 0,
181
+ }),
182
+ })
@@ -0,0 +1,272 @@
1
+ import { Flex, Text } from '@flickfyi/core'
2
+ import { Button } from '@flickfyi/core/atoms'
3
+ import { Field } from '@flickfyi/core/molecules'
4
+ import * as stylex from '@stylexjs/stylex'
5
+ import { isEqual } from 'lodash'
6
+ import { Info } from 'luxon'
7
+ import { useState } from 'react'
8
+ import { z } from 'zod/v4'
9
+
10
+ import { useClock } from '~/hooks/use-clock'
11
+ import { useConfiguredFeature } from '~/hooks/use-configured-feature'
12
+ import { localDate } from '~/kowalski/calculations'
13
+ import type { CreateSchemas } from '~/kowalski/create-schemas'
14
+ import { entries, featureFields } from '~/kowalski/feature-schema'
15
+ import { format, resolveTimeZone } from '~/kowalski/format'
16
+ import { FeatureAction, FeatureFrame, FeatureWell, layout } from '~/kowalski/frame'
17
+ import { radius, size, space } from '~/themes/scale.stylex'
18
+ import { appearance, button, roles } from '~/themes/shared'
19
+ import { colors } from '~/themes/tokens.stylex'
20
+
21
+ export const weekdayNames = [
22
+ 'sunday',
23
+ 'monday',
24
+ 'tuesday',
25
+ 'wednesday',
26
+ 'thursday',
27
+ 'friday',
28
+ 'saturday',
29
+ ] as const
30
+
31
+ const defaultId = 'KowalskiHabit'
32
+ const defaultScope = 'private'
33
+
34
+ export const HabitData = /* @__PURE__ */ z
35
+ .strictObject({
36
+ timeZone: z
37
+ .string()
38
+ .optional()
39
+ .describe('An IANA time zone, e.g. "America/New_York". Omit for UTC.'),
40
+ title: z.string().describe('A short heading.'),
41
+ weekdays: z
42
+ .array(z.enum(weekdayNames))
43
+ .optional()
44
+ .describe('The days the habit is scheduled. Omit for every day.'),
45
+ })
46
+ .describe(
47
+ 'Track a habit by local date and edit its weekday schedule. No notifications.'
48
+ )
49
+
50
+ export type HabitData = z.infer<typeof HabitData>
51
+
52
+ export const HabitProps = z.strictObject({
53
+ data: HabitData,
54
+ ...featureFields,
55
+ scope: featureFields.scope.default(defaultScope),
56
+ })
57
+
58
+ export type HabitProps = z.input<typeof HabitProps> & {
59
+ style?: stylex.StyleXArray<stylex.StyleXStyles>
60
+ }
61
+
62
+ export const habitStoreSchema = entries('completed_', z.boolean(), {
63
+ weekdays: z.array(z.enum(weekdayNames)).default([...weekdayNames]),
64
+ })
65
+
66
+ export const createSchemas: CreateSchemas = ({
67
+ id = defaultId,
68
+ scope = defaultScope,
69
+ } = {}) => ({
70
+ [`stores/${scope}/${id}`]: habitStoreSchema,
71
+ })
72
+
73
+ export function Habit({
74
+ data,
75
+ id,
76
+ revision = 0,
77
+ scope = defaultScope,
78
+ style,
79
+ }: HabitProps) {
80
+ const [editingSchedule, setEditingSchedule] = useState(false)
81
+ const schema = habitStoreSchema
82
+ const store = useConfiguredFeature({
83
+ name: id ?? defaultId,
84
+ revision,
85
+ schema,
86
+ scope,
87
+ seed: schema.parse({ weekdays: data.weekdays }),
88
+ })
89
+ const now = useClock()
90
+ const today = localDate(now, resolveTimeZone(data.timeZone))
91
+ const loading = !store.ready && !store.error
92
+ const dayOf = (date: string) => weekdayNames[new Date(`${date}T00:00:00Z`).getUTCDay()]
93
+ // Luxon lists weekdays Monday first; weekdayNames is Sunday first.
94
+ const shortName = (day: Weekday) =>
95
+ Info.weekdays('short', { locale: format.locale })[(weekdayNames.indexOf(day) + 6) % 7]
96
+ const scheduled = store.value.weekdays.includes(dayOf(today))
97
+ const done = store.value[`completed_${today}`] ?? false
98
+ const mondayFirst = [...weekdayNames.slice(1), weekdayNames[0]]
99
+ const selected = mondayFirst.filter(day => store.value.weekdays.includes(day))
100
+ const schedule =
101
+ selected.length === 7
102
+ ? 'Every day'
103
+ : selected.length === 0
104
+ ? 'No scheduled days'
105
+ : isEqual(selected, mondayFirst.slice(0, 5))
106
+ ? 'Monday to Friday'
107
+ : isEqual(selected, mondayFirst.slice(5))
108
+ ? 'Saturday & Sunday'
109
+ : format.formatList(selected.map(shortName), { type: 'unit' })
110
+ const days = Array.from({ length: 7 }, (_, index) => {
111
+ const date = new Date(`${today}T00:00:00Z`)
112
+ date.setUTCDate(date.getUTCDate() - 6 + index)
113
+ const key = date.toISOString().slice(0, 10)
114
+ return {
115
+ complete: store.value[`completed_${key}`] ?? false,
116
+ date: key,
117
+ label: shortName(dayOf(key)),
118
+ number: date.getUTCDate(),
119
+ scheduled: store.value.weekdays.includes(dayOf(key)),
120
+ }
121
+ })
122
+ return (
123
+ <FeatureFrame
124
+ style={style}
125
+ onRetry={store.retry}
126
+ notice={store.error}
127
+ component="habit"
128
+ title={data.title}
129
+ >
130
+ <Field label="Schedule">
131
+ <Flex {...stylex.props(habitStyles.row)}>
132
+ <Text {...stylex.props(roles.text, layout.grow)}>
133
+ {loading ? 'Loading saved schedule…' : schedule}
134
+ </Text>
135
+ <Button
136
+ disabled={!store.ready}
137
+ onClick={() => setEditingSchedule(current => !current)}
138
+ style={[button.quiet, layout.trailingAction]}
139
+ >
140
+ <Text>{editingSchedule ? 'Done editing' : 'Edit schedule'}</Text>
141
+ </Button>
142
+ </Flex>
143
+ {editingSchedule && (
144
+ <>
145
+ <Flex {...stylex.props(habitStyles.weekdays)}>
146
+ {mondayFirst.map(day => (
147
+ <Button
148
+ key={day}
149
+ selected={store.value.weekdays.includes(day)}
150
+ disabled={!store.ready}
151
+ onClick={() => {
152
+ store.set(current => ({
153
+ weekdays: current.weekdays.includes(day)
154
+ ? current.weekdays.filter(value => value !== day)
155
+ : [...current.weekdays, day],
156
+ }))
157
+ }}
158
+ style={[button.secondary, habitStyles.weekday]}
159
+ >
160
+ <Text>{shortName(day)}</Text>
161
+ </Button>
162
+ ))}
163
+ </Flex>
164
+ <Text {...stylex.props(roles.muted)}>
165
+ Changes save as you tap. Completed days stay saved when the schedule
166
+ changes.
167
+ </Text>
168
+ </>
169
+ )}
170
+ </Field>
171
+ <Field label="Last seven days">
172
+ {loading ? (
173
+ <Text {...stylex.props(roles.muted)}>Loading saved history…</Text>
174
+ ) : (
175
+ <Flex {...stylex.props(habitStyles.history)}>
176
+ {days.map(day => (
177
+ <Flex key={day.date} {...stylex.props(habitStyles.day)}>
178
+ <Text
179
+ {...stylex.props(roles.muted, day.date === today && appearance.accent)}
180
+ >
181
+ {day.date === today ? 'Today' : day.label}
182
+ </Text>
183
+ <Flex
184
+ {...stylex.props(
185
+ appearance.surface,
186
+ habitStyles.date,
187
+ day.date === today && appearance.selected,
188
+ day.complete && habitStyles.completedDate,
189
+ !day.scheduled && !day.complete && habitStyles.offDay
190
+ )}
191
+ >
192
+ <Text>{day.number}</Text>
193
+ </Flex>
194
+ </Flex>
195
+ ))}
196
+ </Flex>
197
+ )}
198
+ </Field>
199
+ <FeatureWell>
200
+ <Flex {...stylex.props(habitStyles.row)}>
201
+ <Text {...stylex.props(roles.h1)}>
202
+ {loading ? 'Loading…' : done ? 'Complete' : scheduled ? 'Not yet' : 'Off day'}
203
+ </Text>
204
+ <Text {...stylex.props(roles.muted)}>
205
+ {format.formatters
206
+ .getDateTimeFormat(format.locale, {
207
+ day: 'numeric',
208
+ month: 'short',
209
+ timeZone: 'UTC',
210
+ weekday: 'short',
211
+ })
212
+ .format(new Date(`${today}T00:00:00Z`))}
213
+ </Text>
214
+ </Flex>
215
+ <Text {...stylex.props(roles.muted)}>
216
+ {loading
217
+ ? 'Loading saved completions…'
218
+ : scheduled
219
+ ? 'Scheduled today'
220
+ : done
221
+ ? 'Completed on an off day'
222
+ : 'No completion needed today'}
223
+ </Text>
224
+ </FeatureWell>
225
+ {store.saving && <Text {...stylex.props(roles.muted)}>Saving changes…</Text>}
226
+ <FeatureAction
227
+ component="habit"
228
+ variant={done || !scheduled ? 'secondary' : 'primary'}
229
+ icon={done ? 'arrow.uturn.backward' : 'checkmark'}
230
+ size="lg"
231
+ disabled={!store.ready}
232
+ onClick={() => {
233
+ store.set(current => ({
234
+ [`completed_${today}`]: !current[`completed_${today}`],
235
+ }))
236
+ }}
237
+ >
238
+ {done ? 'Undo' : 'Complete today'}
239
+ </FeatureAction>
240
+ </FeatureFrame>
241
+ )
242
+ }
243
+
244
+ // A week strip: state reads from the date chip alone (filled, plain, or faded).
245
+ const habitStyles = /* @__PURE__ */ stylex.create({
246
+ completedDate: {
247
+ backgroundColor: colors.accent,
248
+ borderColor: colors.accent,
249
+ color: colors.onAccent,
250
+ },
251
+ date: {
252
+ alignItems: 'center',
253
+ borderRadius: radius.full,
254
+ height: size[9],
255
+ justifyContent: 'center',
256
+ width: size[9],
257
+ },
258
+ day: { alignItems: 'center', flexBasis: '0%', flexGrow: 1, gap: space[2], minWidth: 0 },
259
+ history: { flexDirection: 'row', gap: space[1] },
260
+ offDay: { opacity: 0.5 },
261
+ row: {
262
+ alignItems: 'center',
263
+ flexDirection: 'row',
264
+ flexWrap: 'wrap',
265
+ gap: space[3],
266
+ justifyContent: 'space-between',
267
+ },
268
+ weekday: { flexBasis: '22%', flexGrow: 1, textAlign: 'center' },
269
+ weekdays: { flexDirection: 'row', flexWrap: 'wrap', gap: space[2] },
270
+ })
271
+
272
+ type Weekday = (typeof weekdayNames)[number]
@@ -0,0 +1,211 @@
1
+ import { Text } from '@flickfyi/core'
2
+ import { Input } from '@flickfyi/core/atoms'
3
+ import { Field, List, Segmented } from '@flickfyi/core/molecules'
4
+ import * as stylex from '@stylexjs/stylex'
5
+ import { useState } from 'react'
6
+ import { z } from 'zod/v4'
7
+
8
+ import { useConfiguredFeature } from '~/hooks/use-configured-feature'
9
+ import { formatCurrency } from '~/kowalski/calculations'
10
+ import type { CreateSchemas } from '~/kowalski/create-schemas'
11
+ import { everydayStyles } from '~/kowalski/everyday'
12
+ import { featureFields, store } from '~/kowalski/feature-schema'
13
+ import { parseNumberInput, resolveCurrency } from '~/kowalski/format'
14
+ import {
15
+ FeatureAction,
16
+ FeatureFacts,
17
+ FeatureFrame,
18
+ FeatureWell,
19
+ layout,
20
+ } from '~/kowalski/frame'
21
+ import { roles } from '~/themes/shared'
22
+
23
+ const defaultId = 'KowalskiLedger'
24
+ const defaultScope = 'private'
25
+
26
+ export const LedgerData = /* @__PURE__ */ z
27
+ .strictObject({
28
+ currency: z
29
+ .string()
30
+ .optional()
31
+ .describe('A three-letter ISO currency code, e.g. "USD" or "EUR". Omit for "USD".'),
32
+ people: z
33
+ .array(
34
+ z.strictObject({
35
+ id: z.string().describe('A short ID, unique within this list, e.g. "tent".'),
36
+ label: z.string().describe('A person’s name.'),
37
+ })
38
+ )
39
+ .describe('Exactly two people sharing the tab.'),
40
+ title: z.string().optional().describe('A short heading. Omit for "Shared tab".'),
41
+ })
42
+ .describe(
43
+ 'A running tab of shared costs between two people, split evenly, with settle up. No payments.'
44
+ )
45
+
46
+ export type LedgerData = z.infer<typeof LedgerData>
47
+
48
+ export const LedgerProps = z.strictObject({
49
+ data: LedgerData,
50
+ ...featureFields,
51
+ scope: featureFields.scope.default(defaultScope),
52
+ })
53
+
54
+ export type LedgerProps = z.input<typeof LedgerProps> & {
55
+ style?: stylex.StyleXArray<stylex.StyleXStyles>
56
+ }
57
+
58
+ export const ledgerStoreSchema = store({
59
+ entries: z
60
+ .array(
61
+ z.strictObject({
62
+ amount: z.number(),
63
+ id: z.string(),
64
+ label: z.string(),
65
+ paidBy: z.string(),
66
+ })
67
+ )
68
+ .default([]),
69
+ })
70
+
71
+ export const createSchemas: CreateSchemas = ({
72
+ id = defaultId,
73
+ scope = defaultScope,
74
+ } = {}) => ({
75
+ [`stores/${scope}/${id}`]: ledgerStoreSchema,
76
+ })
77
+
78
+ export function Ledger({
79
+ data,
80
+ id,
81
+ revision = 0,
82
+ scope = defaultScope,
83
+ style,
84
+ }: LedgerProps) {
85
+ const schema = ledgerStoreSchema
86
+ const store = useConfiguredFeature({
87
+ name: id ?? defaultId,
88
+ revision,
89
+ schema,
90
+ scope,
91
+ seed: schema.parse({}),
92
+ })
93
+ const first = data.people[0] ?? { id: 'first', label: 'Person 1' }
94
+ const second = data.people[1] ?? { id: 'second', label: 'Person 2' }
95
+ const [label, setLabel] = useState({ value: '' })
96
+ const [amount, setAmount] = useState({ value: '' })
97
+ const [paidBy, setPaidBy] = useState(first.id)
98
+ const money = (value: number) => formatCurrency(value, data.currency)
99
+ const nameOf = (id: string) => (id === first.id ? first.label : second.label)
100
+ const parsed = parseNumberInput(amount.value, resolveCurrency(data.currency))
101
+ const valid = Number.isFinite(parsed) && parsed > 0
102
+ // Every cost is shared evenly, so whoever paid is owed half of it.
103
+ const balance = store.value.entries.reduce(
104
+ (sum, entry) => sum + (entry.paidBy === first.id ? entry.amount : -entry.amount) / 2,
105
+ 0
106
+ )
107
+ const settled = Math.abs(balance) < 0.005
108
+ return (
109
+ <FeatureFrame
110
+ style={style}
111
+ onRetry={store.retry}
112
+ notice={store.error}
113
+ component="ledger"
114
+ title={data.title ?? 'Shared tab'}
115
+ detail={`${first.label} and ${second.label} · costs split evenly`}
116
+ >
117
+ <FeatureWell style={everydayStyles.centered}>
118
+ <Text {...stylex.props(roles.h1)}>
119
+ {settled ? 'All square' : money(Math.abs(balance))}
120
+ </Text>
121
+ {!settled && (
122
+ <Text {...stylex.props(roles.muted)}>
123
+ {balance > 0
124
+ ? `${second.label} owes ${first.label}`
125
+ : `${first.label} owes ${second.label}`}
126
+ </Text>
127
+ )}
128
+ </FeatureWell>
129
+ {store.value.entries.length > 0 && (
130
+ <>
131
+ <FeatureAction
132
+ component="ledger"
133
+ disabled={!store.ready}
134
+ onClick={() => store.set(() => ({ entries: [] }))}
135
+ >
136
+ Settle up
137
+ </FeatureAction>
138
+ <FeatureFacts>
139
+ {store.value.entries.slice(0, 20).map(entry => (
140
+ <List.Item
141
+ description={`Paid by ${nameOf(entry.paidBy)}`}
142
+ key={entry.id}
143
+ label={entry.label || 'Shared cost'}
144
+ trailing={money(entry.amount)}
145
+ />
146
+ ))}
147
+ </FeatureFacts>
148
+ </>
149
+ )}
150
+ <Field label="What for">
151
+ <Input
152
+ placeholder="What for"
153
+ value={label.value}
154
+ onChange={value => setLabel({ value })}
155
+ style={[layout.input]}
156
+ />
157
+ </Field>
158
+ <Field
159
+ error={amount.value && !valid && 'Enter an amount within the supported range.'}
160
+ label="Amount"
161
+ >
162
+ <Input
163
+ placeholder="Amount"
164
+ value={amount.value}
165
+ onChange={value => setAmount({ value })}
166
+ style={[layout.input]}
167
+ />
168
+ </Field>
169
+ <Field label="Paid by">
170
+ <Segmented
171
+ options={data.people.map(person => ({
172
+ label: person.label,
173
+ value: person.id,
174
+ }))}
175
+ value={paidBy}
176
+ onChange={setPaidBy}
177
+ />
178
+ </Field>
179
+ <FeatureAction
180
+ component="ledger"
181
+ disabled={
182
+ !valid || !store.ready || store.saving || store.value.entries.length >= 200
183
+ }
184
+ icon="plus"
185
+ size="lg"
186
+ variant="primary"
187
+ onClick={() =>
188
+ store.set(
189
+ current => ({
190
+ entries: [
191
+ {
192
+ amount: parsed,
193
+ id: `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`,
194
+ label: label.value.trim(),
195
+ paidBy,
196
+ },
197
+ ...current.entries,
198
+ ],
199
+ }),
200
+ () => {
201
+ setAmount(current => (current === amount ? { value: '' } : current))
202
+ setLabel(current => (current === label ? { value: '' } : current))
203
+ }
204
+ )
205
+ }
206
+ >
207
+ Add to the tab
208
+ </FeatureAction>
209
+ </FeatureFrame>
210
+ )
211
+ }