@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,173 @@
1
+ import { Flex, Text } from '@flickfyi/core'
2
+ import * as stylex from '@stylexjs/stylex'
3
+ import { z } from 'zod/v4'
4
+
5
+ import { useClock } from '~/hooks/use-clock'
6
+ import { useConfiguredFeature } from '~/hooks/use-configured-feature'
7
+ import { parseInstant } from '~/kowalski/calculations'
8
+ import type { CreateSchemas } from '~/kowalski/create-schemas'
9
+ import { FeatureDateTime } from '~/kowalski/date-time'
10
+ import { featureFields, replacement, store } from '~/kowalski/feature-schema'
11
+ import { format } from '~/kowalski/format'
12
+ import { FeatureFrame, FeatureWell } from '~/kowalski/frame'
13
+ import { space, text } from '~/themes/scale.stylex'
14
+ import { roles } from '~/themes/shared'
15
+ import { font } from '~/themes/tokens.stylex'
16
+
17
+ const defaultId = 'KowalskiCountdown'
18
+ const defaultScope = 'private'
19
+
20
+ export const CountdownData = /* @__PURE__ */ z
21
+ .strictObject({
22
+ target: z
23
+ .string()
24
+ .describe(
25
+ 'The moment to count down to, as ISO 8601 with an offset, e.g. "2026-12-31T23:59:59-08:00".'
26
+ ),
27
+ timeZone: z
28
+ .string()
29
+ .optional()
30
+ .describe('An IANA time zone, e.g. "America/New_York". Omit for UTC.'),
31
+ title: z.string().describe('A short heading.'),
32
+ })
33
+ .describe(
34
+ 'Count down to an explicit instant. Resolve missing dates before instantiation.'
35
+ )
36
+
37
+ export type CountdownData = z.infer<typeof CountdownData>
38
+
39
+ export const CountdownProps = z.strictObject({
40
+ data: CountdownData,
41
+ ...featureFields,
42
+ scope: featureFields.scope.default(defaultScope),
43
+ })
44
+
45
+ export type CountdownProps = z.input<typeof CountdownProps> & {
46
+ style?: stylex.StyleXArray<stylex.StyleXStyles>
47
+ }
48
+
49
+ export const countdownStoreSchema = store({
50
+ target: replacement(z.string().nullable().default(null)),
51
+ })
52
+
53
+ export const createSchemas: CreateSchemas = ({
54
+ id = defaultId,
55
+ scope = defaultScope,
56
+ } = {}) => ({
57
+ [`stores/${scope}/${id}`]: countdownStoreSchema,
58
+ })
59
+
60
+ export function Countdown({
61
+ data,
62
+ id,
63
+ revision = 0,
64
+ scope = defaultScope,
65
+ style,
66
+ }: CountdownProps) {
67
+ const schema = countdownStoreSchema
68
+ const store = useConfiguredFeature({
69
+ name: id ?? defaultId,
70
+ revision,
71
+ schema,
72
+ scope,
73
+ seed: schema.parse({ target: { value: data.target } }),
74
+ })
75
+ const now = useClock()
76
+ const target = parseInstant(store.value.target.value)
77
+ const seconds = target === null ? 0 : Math.max(0, Math.ceil((target - now) / 1000))
78
+ const units = [
79
+ { label: 'day', value: Math.floor(seconds / 86_400) },
80
+ { label: 'hour', value: Math.floor((seconds % 86_400) / 3600) },
81
+ { label: 'minute', value: Math.floor((seconds % 3600) / 60) },
82
+ { label: 'second', value: seconds % 60 },
83
+ ]
84
+ const leadingIndex = seconds >= 86_400 ? 0 : seconds >= 3600 ? 1 : seconds >= 60 ? 2 : 3
85
+ const leading = units[leadingIndex]
86
+ const amount = format.formatNumber(leading.value)
87
+ return (
88
+ <FeatureFrame
89
+ style={style}
90
+ onRetry={store.retry}
91
+ notice={store.error}
92
+ component="countdown"
93
+ title={data.title}
94
+ >
95
+ <FeatureWell style={countdownStyles.remaining}>
96
+ <Text
97
+ animated={seconds > 0 ? 'numeric' : undefined}
98
+ {...stylex.props(
99
+ roles.display,
100
+ countdownStyles.amount(amount.length),
101
+ seconds === 0 && countdownStyles.arrived
102
+ )}
103
+ >
104
+ {target === null ? '—' : seconds === 0 ? 'It’s time' : amount}
105
+ </Text>
106
+ <Text {...stylex.props(roles.muted)}>
107
+ {target === null
108
+ ? 'Choose a target below'
109
+ : seconds === 0
110
+ ? 'Your countdown has arrived'
111
+ : `${format.formatNumberToParts(leading.value, { style: 'unit', unit: leading.label, unitDisplay: 'long' }).find(part => part.type === 'unit')?.value} to go`}
112
+ </Text>
113
+ {seconds > 0 && leadingIndex < 3 && (
114
+ <Flex {...stylex.props(countdownStyles.units)}>
115
+ {units.slice(leadingIndex + 1).map(unit => (
116
+ <Flex key={unit.label} {...stylex.props(countdownStyles.unit)}>
117
+ <Text animated="numeric" {...stylex.props(roles.strong)}>
118
+ {format.formatNumber(unit.value)}
119
+ </Text>
120
+ <Text {...stylex.props(roles.muted)}>
121
+ {
122
+ format
123
+ .formatNumberToParts(unit.value, {
124
+ style: 'unit',
125
+ unit: unit.label,
126
+ unitDisplay: 'long',
127
+ })
128
+ .find(part => part.type === 'unit')?.value
129
+ }
130
+ </Text>
131
+ </Flex>
132
+ ))}
133
+ </Flex>
134
+ )}
135
+ </FeatureWell>
136
+ <FeatureDateTime
137
+ component="countdown"
138
+ label="Target date & time"
139
+ ready={store.ready}
140
+ saving={store.saving}
141
+ timeZone={data.timeZone ?? 'UTC'}
142
+ value={store.value.target.value || null}
143
+ onChange={(target, onSaved) =>
144
+ target === null
145
+ ? false
146
+ : store.set(() => ({ target: { value: target } }), onSaved)
147
+ }
148
+ />
149
+ </FeatureFrame>
150
+ )
151
+ }
152
+
153
+ const countdownStyles = /* @__PURE__ */ stylex.create({
154
+ amount: (length: number) => ({
155
+ fontSize: length > 6 ? text['4xl'] : length > 4 ? text['6xl'] : font.displaySize,
156
+ lineHeight:
157
+ length > 6
158
+ ? text['4xlLeading']
159
+ : length > 4
160
+ ? text['6xlLeading']
161
+ : font.displayLeading,
162
+ }),
163
+ arrived: { fontSize: text['4xl'], lineHeight: text['4xlLeading'] },
164
+ remaining: { alignItems: 'stretch', gap: space[2], textAlign: 'center' },
165
+ unit: { alignItems: 'baseline', flexDirection: 'row', gap: space[1] },
166
+ units: {
167
+ columnGap: space[3],
168
+ flexDirection: 'row',
169
+ flexWrap: 'wrap',
170
+ justifyContent: 'center',
171
+ rowGap: space[1],
172
+ },
173
+ })
@@ -0,0 +1,260 @@
1
+ import { Flex, Text } from '@flickfyi/core'
2
+ import { Input } from '@flickfyi/core/atoms'
3
+ import { List } from '@flickfyi/core/molecules'
4
+ import { Event as EventEntity } from '@flickfyi/schemas/event'
5
+ import * as stylex from '@stylexjs/stylex'
6
+ import { useState } from 'react'
7
+ import { z } from 'zod/v4'
8
+
9
+ import { useConfiguredFeature } from '~/hooks/use-configured-feature'
10
+ import { parseInstant } from '~/kowalski/calculations'
11
+ import type { CreateSchemas } from '~/kowalski/create-schemas'
12
+ import { FeatureDateTime } from '~/kowalski/date-time'
13
+ import { featureFields, replacement, store } from '~/kowalski/feature-schema'
14
+ import { format, resolveTimeZone } from '~/kowalski/format'
15
+ import { FeatureAction, FeatureFacts, FeatureFrame, layout } from '~/kowalski/frame'
16
+ import { space, text } from '~/themes/scale.stylex'
17
+ import { roles } from '~/themes/shared'
18
+
19
+ const defaultId = 'KowalskiEvent'
20
+ const defaultScope = 'private'
21
+
22
+ export const EventData = EventEntity
23
+
24
+ export type EventData = EventEntity
25
+
26
+ export const EventProps = z.strictObject({
27
+ data: EventData,
28
+ ...featureFields,
29
+ scope: featureFields.scope.default(defaultScope),
30
+ })
31
+
32
+ export type EventProps = z.input<typeof EventProps> & {
33
+ style?: stylex.StyleXArray<stylex.StyleXStyles>
34
+ }
35
+
36
+ export const eventStoreSchema = store({
37
+ location: replacement(z.string().default('')),
38
+ startsAt: replacement(z.string().nullable().default(null)),
39
+ title: replacement(z.string().default('')),
40
+ })
41
+
42
+ export const createSchemas: CreateSchemas = ({
43
+ id = defaultId,
44
+ scope = defaultScope,
45
+ } = {}) => ({
46
+ [`stores/${scope}/${id}`]: eventStoreSchema,
47
+ })
48
+
49
+ export function Event({
50
+ data,
51
+ id,
52
+ revision = 0,
53
+ scope = defaultScope,
54
+ style,
55
+ }: EventProps) {
56
+ const schema = eventStoreSchema
57
+ const store = useConfiguredFeature({
58
+ name: id ?? defaultId,
59
+ revision,
60
+ schema,
61
+ scope,
62
+ seed: schema.parse({
63
+ location: { value: data.location },
64
+ startsAt: { value: data.startsAt },
65
+ title: { value: data.title },
66
+ }),
67
+ })
68
+ const timeZone = resolveTimeZone(data.timeZone)
69
+ const [draft, setDraft] = useState<{
70
+ location: string
71
+ startsAt: string | null
72
+ title: string
73
+ }>({
74
+ location: '',
75
+ startsAt: data.startsAt ?? null,
76
+ title: '',
77
+ })
78
+ const [baseline, setBaseline] = useState<typeof draft | null>(null)
79
+ const [editingDate, setEditingDate] = useState(false)
80
+ const editing = baseline !== null
81
+ const title = store.value.title.value.trim()
82
+ ? store.value.title.value
83
+ : 'Untitled event'
84
+ const instant = parseInstant(store.value.startsAt.value)
85
+ const timeParts =
86
+ instant === null
87
+ ? []
88
+ : format.formatters
89
+ .getDateTimeFormat(format.locale, {
90
+ fractionalSecondDigits: instant % 1000 === 0 ? undefined : 3,
91
+ hour: 'numeric',
92
+ hour12: true,
93
+ minute: '2-digit',
94
+ second: instant % 60_000 === 0 ? undefined : '2-digit',
95
+ timeZone,
96
+ timeZoneName: 'long',
97
+ })
98
+ .formatToParts(instant)
99
+ const validTitle = draft.title.trim().length > 0
100
+ const changed =
101
+ baseline &&
102
+ (draft.title !== baseline.title ||
103
+ draft.location !== baseline.location ||
104
+ draft.startsAt !== baseline.startsAt)
105
+ return (
106
+ <FeatureFrame
107
+ style={style}
108
+ onRetry={store.retry}
109
+ notice={store.error}
110
+ component="event"
111
+ title={title}
112
+ detail={
113
+ instant === null
114
+ ? 'Date to be decided'
115
+ : format.formatters
116
+ .getDateTimeFormat(format.locale, {
117
+ day: 'numeric',
118
+ month: 'long',
119
+ timeZone,
120
+ weekday: 'long',
121
+ })
122
+ .format(instant)
123
+ }
124
+ >
125
+ {editing && !store.saving ? (
126
+ <Flex {...stylex.props(eventStyles.editor)}>
127
+ <Flex {...stylex.props(layout.field)}>
128
+ <Text {...stylex.props(roles.label, layout.fieldLabel)}>Title</Text>
129
+ <Input
130
+ placeholder="Title"
131
+ value={draft.title}
132
+ onChange={title => setDraft(current => ({ ...current, title }))}
133
+ style={[layout.input]}
134
+ />
135
+ {!validTitle && (
136
+ <Text {...stylex.props(roles.muted)}>Add an event title.</Text>
137
+ )}
138
+ </Flex>
139
+ <FeatureDateTime
140
+ inline
141
+ clearable
142
+ component="event"
143
+ label="Start date & time"
144
+ onChange={startsAt => setDraft(current => ({ ...current, startsAt }))}
145
+ onEditingChange={setEditingDate}
146
+ ready={store.ready}
147
+ timeZone={timeZone}
148
+ value={draft.startsAt}
149
+ />
150
+ <Flex {...stylex.props(layout.field)}>
151
+ <Flex {...stylex.props(eventStyles.fieldLabel)}>
152
+ <Text {...stylex.props(roles.label, layout.fieldLabel)}>Location</Text>
153
+ <Text {...stylex.props(roles.muted, eventStyles.optional)}>Optional</Text>
154
+ </Flex>
155
+ <Input
156
+ placeholder="Location"
157
+ value={draft.location}
158
+ onChange={location => setDraft(current => ({ ...current, location }))}
159
+ style={[layout.input]}
160
+ />
161
+ </Flex>
162
+ <Flex {...stylex.props(layout.actions)}>
163
+ <FeatureAction component="event" onClick={() => setBaseline(null)}>
164
+ Cancel
165
+ </FeatureAction>
166
+ <FeatureAction
167
+ component="event"
168
+ disabled={
169
+ editingDate || store.saving || !store.ready || !changed || !validTitle
170
+ }
171
+ onClick={() => {
172
+ if (editingDate || !baseline || !changed || !validTitle) {
173
+ return
174
+ }
175
+ store.set(
176
+ current => ({
177
+ ...(draft.title !== baseline.title &&
178
+ draft.title !== current.title.value && {
179
+ title: { value: draft.title },
180
+ }),
181
+ ...(draft.startsAt !== baseline.startsAt &&
182
+ draft.startsAt !== current.startsAt.value && {
183
+ startsAt: { value: draft.startsAt },
184
+ }),
185
+ ...(draft.location !== baseline.location &&
186
+ draft.location !== current.location.value && {
187
+ location: { value: draft.location },
188
+ }),
189
+ }),
190
+ () => setBaseline(null)
191
+ )
192
+ }}
193
+ variant="primary"
194
+ >
195
+ Save changes
196
+ </FeatureAction>
197
+ </Flex>
198
+ </Flex>
199
+ ) : (
200
+ <>
201
+ {store.saving ? (
202
+ <Text {...stylex.props(roles.muted)}>Saving changes…</Text>
203
+ ) : !store.ready && !store.error ? (
204
+ <Text {...stylex.props(roles.muted)}>Loading event…</Text>
205
+ ) : null}
206
+ <FeatureFacts>
207
+ <List.Item
208
+ label="Time"
209
+ trailing={
210
+ instant === null
211
+ ? 'Not set'
212
+ : timeParts
213
+ .filter(part => part.type !== 'timeZoneName')
214
+ .map(part => part.value)
215
+ .join('')
216
+ .trim()
217
+ }
218
+ />
219
+ <List.Item
220
+ label="Where"
221
+ trailing={
222
+ store.value.location.value.trim()
223
+ ? store.value.location.value
224
+ : 'To be decided'
225
+ }
226
+ />
227
+ </FeatureFacts>
228
+ {!editing && (
229
+ <FeatureAction
230
+ component="event"
231
+ disabled={!store.ready || store.saving}
232
+ icon="pencil"
233
+ onClick={() => {
234
+ const values = {
235
+ location: store.value.location.value,
236
+ startsAt: store.value.startsAt.value,
237
+ title: store.value.title.value,
238
+ }
239
+ setDraft(values)
240
+ setBaseline(values)
241
+ }}
242
+ >
243
+ Edit event
244
+ </FeatureAction>
245
+ )}
246
+ </>
247
+ )}
248
+ </FeatureFrame>
249
+ )
250
+ }
251
+
252
+ const eventStyles = /* @__PURE__ */ stylex.create({
253
+ editor: { gap: space[5] },
254
+ fieldLabel: {
255
+ alignItems: 'center',
256
+ flexDirection: 'row',
257
+ justifyContent: 'space-between',
258
+ },
259
+ optional: { fontSize: text['xs'] },
260
+ })
@@ -0,0 +1,257 @@
1
+ import { Flex, Text } from '@flickfyi/core'
2
+ import { Input } from '@flickfyi/core/atoms'
3
+ import { Field } 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 { featureFields, replacement, store } from '~/kowalski/feature-schema'
12
+ import { parseNumberInput, resolveCurrency } from '~/kowalski/format'
13
+ import { FeatureAction, FeatureFrame, FeatureWell, layout } from '~/kowalski/frame'
14
+ import { text } from '~/themes/scale.stylex'
15
+ import { roles } from '~/themes/shared'
16
+
17
+ const defaultId = 'KowalskiExpense'
18
+ const defaultScope = 'private'
19
+
20
+ export const ExpenseData = /* @__PURE__ */ z
21
+ .strictObject({
22
+ amount: z.number().describe('The amount spent, e.g. 12.5.'),
23
+ category: z
24
+ .string()
25
+ .optional()
26
+ .describe('A short category, e.g. "Food". Omit for "Other".'),
27
+ currency: z
28
+ .string()
29
+ .optional()
30
+ .describe('A three-letter ISO currency code, e.g. "USD" or "EUR". Omit for "USD".'),
31
+ title: z.string().describe('A short heading.'),
32
+ })
33
+ .describe(
34
+ 'Edit and retain one expense. No payments, bank connection, or exchange-rate lookup.'
35
+ )
36
+
37
+ export type ExpenseData = z.infer<typeof ExpenseData>
38
+
39
+ export const ExpenseProps = z.strictObject({
40
+ data: ExpenseData,
41
+ ...featureFields,
42
+ scope: featureFields.scope.default(defaultScope),
43
+ })
44
+
45
+ export type ExpenseProps = z.input<typeof ExpenseProps> & {
46
+ style?: stylex.StyleXArray<stylex.StyleXStyles>
47
+ }
48
+
49
+ export const expenseStoreSchema = store({
50
+ amount: z.number().default(0),
51
+ category: replacement(z.string().default('Other')),
52
+ title: replacement(z.string().default('')),
53
+ })
54
+
55
+ export const createSchemas: CreateSchemas = ({
56
+ id = defaultId,
57
+ scope = defaultScope,
58
+ } = {}) => ({
59
+ [`stores/${scope}/${id}`]: expenseStoreSchema,
60
+ })
61
+
62
+ export function Expense({
63
+ data,
64
+ id,
65
+ revision = 0,
66
+ scope = defaultScope,
67
+ style,
68
+ }: ExpenseProps) {
69
+ const schema = expenseStoreSchema
70
+ const store = useConfiguredFeature({
71
+ name: id ?? defaultId,
72
+ revision,
73
+ schema,
74
+ scope,
75
+ seed: schema.parse({
76
+ amount: data.amount,
77
+ category: { value: data.category },
78
+ title: { value: data.title },
79
+ }),
80
+ })
81
+ const [draft, setDraft] = useState({ amount: '', category: '', title: '' })
82
+ const [baseline, setBaseline] = useState<typeof draft | null>(null)
83
+ const editing = baseline !== null
84
+ const currency = resolveCurrency(data.currency)
85
+ const amount = parseNumberInput(draft.amount, currency)
86
+ const validAmount = amount >= 0
87
+ const validTitle = draft.title.trim().length > 0
88
+ const changed =
89
+ baseline !== null &&
90
+ (amount !== parseNumberInput(baseline.amount, currency) ||
91
+ draft.category !== baseline.category ||
92
+ draft.title !== baseline.title)
93
+ const formattedAmount = formatCurrency(store.value.amount, currency)
94
+ return (
95
+ <FeatureFrame
96
+ style={style}
97
+ onRetry={store.retry}
98
+ notice={store.error}
99
+ component="expense"
100
+ title={
101
+ editing
102
+ ? 'Edit expense'
103
+ : store.value.title.value.trim()
104
+ ? store.value.title.value
105
+ : 'Untitled expense'
106
+ }
107
+ >
108
+ {editing ? (
109
+ <>
110
+ <Field
111
+ error={!validAmount && 'Enter an amount.'}
112
+ label={currency === 'USD' ? 'Amount' : `Amount (${currency})`}
113
+ >
114
+ {store.saving ? (
115
+ <Text {...stylex.props(roles.text)}>{draft.amount}</Text>
116
+ ) : (
117
+ <Input
118
+ placeholder="Amount"
119
+ value={draft.amount}
120
+ onChange={value => setDraft(current => ({ ...current, amount: value }))}
121
+ style={[layout.input]}
122
+ />
123
+ )}
124
+ </Field>
125
+ {(
126
+ [
127
+ {
128
+ key: 'title',
129
+ label: 'Description',
130
+ valid: validTitle,
131
+ validation: 'Add a description.',
132
+ },
133
+ { key: 'category', label: 'Category', valid: true, validation: '' },
134
+ ] as const
135
+ ).map(field => (
136
+ <Field
137
+ error={!field.valid && field.validation}
138
+ key={field.key}
139
+ label={field.label}
140
+ >
141
+ {store.saving ? (
142
+ <Text {...stylex.props(roles.text)}>
143
+ {draft[field.key] || 'Uncategorized'}
144
+ </Text>
145
+ ) : (
146
+ <Input
147
+ placeholder={field.label}
148
+ value={draft[field.key]}
149
+ onChange={value =>
150
+ setDraft(current => ({ ...current, [field.key]: value }))
151
+ }
152
+ style={[layout.input]}
153
+ />
154
+ )}
155
+ </Field>
156
+ ))}
157
+ <Flex {...stylex.props(layout.actions)}>
158
+ <FeatureAction
159
+ component="expense"
160
+ disabled={store.saving}
161
+ onClick={() => {
162
+ if (!store.saving) {
163
+ setBaseline(null)
164
+ }
165
+ }}
166
+ >
167
+ Cancel
168
+ </FeatureAction>
169
+ <FeatureAction
170
+ component="expense"
171
+ disabled={
172
+ store.saving || !store.ready || !changed || !validAmount || !validTitle
173
+ }
174
+ variant="primary"
175
+ onClick={() => {
176
+ if (
177
+ !baseline ||
178
+ !store.ready ||
179
+ store.saving ||
180
+ !changed ||
181
+ !validAmount ||
182
+ !validTitle
183
+ ) {
184
+ return
185
+ }
186
+ store.set(
187
+ () => ({
188
+ ...(amount !== parseNumberInput(baseline.amount, currency) && {
189
+ amount,
190
+ }),
191
+ ...(draft.category !== baseline.category && {
192
+ category: { value: draft.category },
193
+ }),
194
+ ...(draft.title !== baseline.title && {
195
+ title: { value: draft.title },
196
+ }),
197
+ }),
198
+ () => setBaseline(null)
199
+ )
200
+ }}
201
+ >
202
+ {store.saving ? 'Saving…' : 'Save changes'}
203
+ </FeatureAction>
204
+ </Flex>
205
+ {store.saving && <Text {...stylex.props(roles.muted)}>Saving changes…</Text>}
206
+ </>
207
+ ) : (
208
+ <>
209
+ <FeatureWell>
210
+ <Text
211
+ animated="numeric"
212
+ {...stylex.props(
213
+ roles.display,
214
+ expenseStyles.amount(formattedAmount.length)
215
+ )}
216
+ >
217
+ {formattedAmount}
218
+ </Text>
219
+ <Text {...stylex.props(roles.muted)}>
220
+ {store.value.category.value.trim()
221
+ ? store.value.category.value
222
+ : 'Uncategorized'}
223
+ </Text>
224
+ </FeatureWell>
225
+ {!editing && (
226
+ <FeatureAction
227
+ component="expense"
228
+ disabled={!store.ready || store.saving}
229
+ icon="pencil"
230
+ onClick={() => {
231
+ const values = {
232
+ amount: formattedAmount,
233
+ category: store.value.category.value,
234
+ title: store.value.title.value,
235
+ }
236
+ setBaseline(values)
237
+ setDraft(values)
238
+ }}
239
+ >
240
+ Edit expense
241
+ </FeatureAction>
242
+ )}
243
+ </>
244
+ )}
245
+ </FeatureFrame>
246
+ )
247
+ }
248
+
249
+ // Long amounts step down the display scale so they never overflow the well.
250
+ const expenseStyles = /* @__PURE__ */ stylex.create({
251
+ amount: (length: number) => ({
252
+ fontSize: length > 16 ? text.lg : length > 9 ? text['2xl'] : text['4xl'],
253
+ lineHeight:
254
+ length > 16 ? text.lgLeading : length > 9 ? text['2xlLeading'] : text['4xlLeading'],
255
+ width: '100%',
256
+ }),
257
+ })