@flickfyi/flkr 0.0.141 → 0.0.153

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 (494) hide show
  1. package/node_modules/@flickfyi/attestation/.turbo/turbo-build.log +7 -7
  2. package/node_modules/@flickfyi/biscuit/.turbo/turbo-build.log +7 -7
  3. package/node_modules/@flickfyi/core/.oxlintrc.json +2 -1
  4. package/node_modules/@flickfyi/core/.turbo/turbo-build.log +499 -92
  5. package/node_modules/@flickfyi/core/README.md +58 -4
  6. package/node_modules/@flickfyi/core/dist/index.cjs +1 -1
  7. package/node_modules/@flickfyi/core/dist/index.js +35 -24
  8. package/node_modules/@flickfyi/core/dist/kowalski/calculations.d.ts +17 -0
  9. package/node_modules/@flickfyi/core/dist/kowalski/calculator.d.ts +13 -0
  10. package/node_modules/@flickfyi/core/dist/kowalski/catalog.cjs +1 -0
  11. package/node_modules/@flickfyi/core/dist/kowalski/catalog.d.cts +962 -0
  12. package/node_modules/@flickfyi/core/dist/kowalski/catalog.d.ts +962 -0
  13. package/node_modules/@flickfyi/core/dist/kowalski/catalog.js +639 -0
  14. package/node_modules/@flickfyi/core/dist/kowalski/clocks.d.ts +4 -0
  15. package/node_modules/@flickfyi/core/dist/kowalski/date-time.d.ts +22 -0
  16. package/node_modules/@flickfyi/core/dist/kowalski/details.d.ts +7 -0
  17. package/node_modules/@flickfyi/core/dist/kowalski/everyday.d.ts +8 -0
  18. package/node_modules/@flickfyi/core/dist/kowalski/format.d.ts +4 -0
  19. package/node_modules/@flickfyi/core/dist/kowalski/frame.d.ts +161 -0
  20. package/node_modules/@flickfyi/core/dist/kowalski/index.cjs +21 -0
  21. package/node_modules/@flickfyi/core/dist/kowalski/index.d.cts +8 -0
  22. package/node_modules/@flickfyi/core/dist/kowalski/index.d.ts +8 -0
  23. package/node_modules/@flickfyi/core/dist/kowalski/index.js +7496 -0
  24. package/node_modules/@flickfyi/core/dist/kowalski/productivity.d.ts +5 -0
  25. package/node_modules/@flickfyi/core/dist/kowalski/recipe.d.ts +8 -0
  26. package/node_modules/@flickfyi/core/dist/kowalski/tools.d.ts +7 -0
  27. package/node_modules/@flickfyi/core/dist/kowalski/use-clock.d.ts +6 -0
  28. package/node_modules/@flickfyi/core/dist/kowalski/use-configured-feature.d.ts +19 -0
  29. package/node_modules/@flickfyi/core/dist/kowalski/use-feature-store.d.ts +15 -0
  30. package/node_modules/@flickfyi/core/dist/kowalski.css +506 -0
  31. package/node_modules/@flickfyi/core/dist/molecules/field/field.d.ts +8 -0
  32. package/node_modules/@flickfyi/core/dist/molecules/index.cjs +1 -1
  33. package/node_modules/@flickfyi/core/dist/molecules/index.d.cts +3 -0
  34. package/node_modules/@flickfyi/core/dist/molecules/index.d.ts +3 -0
  35. package/node_modules/@flickfyi/core/dist/molecules/index.js +88 -27
  36. package/node_modules/@flickfyi/core/dist/molecules/segmented/segmented.d.ts +10 -0
  37. package/node_modules/@flickfyi/core/dist/molecules/stepper/stepper.d.ts +10 -0
  38. package/node_modules/@flickfyi/core/dist/quantum/use-store.d.ts +7 -1
  39. package/node_modules/@flickfyi/core/dist/themes.css +2 -0
  40. package/node_modules/@flickfyi/core/examples/kowalski/bill-split/bill-split.stories.tsx +15 -0
  41. package/node_modules/@flickfyi/core/examples/kowalski/bill-split/bill-split.tsx +17 -0
  42. package/node_modules/@flickfyi/core/examples/kowalski/bookmark/bookmark.stories.tsx +15 -0
  43. package/node_modules/@flickfyi/core/examples/kowalski/bookmark/bookmark.tsx +23 -0
  44. package/node_modules/@flickfyi/core/examples/kowalski/budget/budget.stories.tsx +15 -0
  45. package/node_modules/@flickfyi/core/examples/kowalski/budget/budget.tsx +26 -0
  46. package/node_modules/@flickfyi/core/examples/kowalski/calculator/calculator.stories.tsx +15 -0
  47. package/node_modules/@flickfyi/core/examples/kowalski/calculator/calculator.tsx +24 -0
  48. package/node_modules/@flickfyi/core/examples/kowalski/checklist/checklist.stories.tsx +15 -0
  49. package/node_modules/@flickfyi/core/examples/kowalski/checklist/checklist.tsx +26 -0
  50. package/node_modules/@flickfyi/core/examples/kowalski/color-palette/color-palette.stories.tsx +15 -0
  51. package/node_modules/@flickfyi/core/examples/kowalski/color-palette/color-palette.tsx +22 -0
  52. package/node_modules/@flickfyi/core/examples/kowalski/contact/contact.stories.tsx +15 -0
  53. package/node_modules/@flickfyi/core/examples/kowalski/contact/contact.tsx +23 -0
  54. package/node_modules/@flickfyi/core/examples/kowalski/countdown/countdown.stories.tsx +15 -0
  55. package/node_modules/@flickfyi/core/examples/kowalski/countdown/countdown.tsx +23 -0
  56. package/node_modules/@flickfyi/core/examples/kowalski/event/event.stories.tsx +15 -0
  57. package/node_modules/@flickfyi/core/examples/kowalski/event/event.tsx +24 -0
  58. package/node_modules/@flickfyi/core/examples/kowalski/expense/expense.stories.tsx +15 -0
  59. package/node_modules/@flickfyi/core/examples/kowalski/expense/expense.tsx +23 -0
  60. package/node_modules/@flickfyi/core/examples/kowalski/goal/goal.stories.tsx +15 -0
  61. package/node_modules/@flickfyi/core/examples/kowalski/goal/goal.tsx +24 -0
  62. package/node_modules/@flickfyi/core/examples/kowalski/habit/habit.stories.tsx +15 -0
  63. package/node_modules/@flickfyi/core/examples/kowalski/habit/habit.tsx +23 -0
  64. package/node_modules/@flickfyi/core/examples/kowalski/ledger/ledger.stories.tsx +15 -0
  65. package/node_modules/@flickfyi/core/examples/kowalski/ledger/ledger.tsx +25 -0
  66. package/node_modules/@flickfyi/core/examples/kowalski/note/note.stories.tsx +15 -0
  67. package/node_modules/@flickfyi/core/examples/kowalski/note/note.tsx +22 -0
  68. package/node_modules/@flickfyi/core/examples/kowalski/poll/poll.stories.tsx +15 -0
  69. package/node_modules/@flickfyi/core/examples/kowalski/poll/poll.tsx +26 -0
  70. package/node_modules/@flickfyi/core/examples/kowalski/random-picker/random-picker.stories.tsx +15 -0
  71. package/node_modules/@flickfyi/core/examples/kowalski/random-picker/random-picker.tsx +23 -0
  72. package/node_modules/@flickfyi/core/examples/kowalski/rating/rating.stories.tsx +15 -0
  73. package/node_modules/@flickfyi/core/examples/kowalski/rating/rating.tsx +19 -0
  74. package/node_modules/@flickfyi/core/examples/kowalski/recipe/recipe.stories.tsx +15 -0
  75. package/node_modules/@flickfyi/core/examples/kowalski/recipe/recipe.tsx +120 -0
  76. package/node_modules/@flickfyi/core/examples/kowalski/reminder/reminder.stories.tsx +15 -0
  77. package/node_modules/@flickfyi/core/examples/kowalski/reminder/reminder.tsx +23 -0
  78. package/node_modules/@flickfyi/core/examples/kowalski/rotation/rotation.stories.tsx +15 -0
  79. package/node_modules/@flickfyi/core/examples/kowalski/rotation/rotation.tsx +27 -0
  80. package/node_modules/@flickfyi/core/examples/kowalski/scoreboard/scoreboard.stories.tsx +15 -0
  81. package/node_modules/@flickfyi/core/examples/kowalski/scoreboard/scoreboard.tsx +26 -0
  82. package/node_modules/@flickfyi/core/examples/kowalski/shopping-list/shopping-list.stories.tsx +15 -0
  83. package/node_modules/@flickfyi/core/examples/kowalski/shopping-list/shopping-list.tsx +27 -0
  84. package/node_modules/@flickfyi/core/examples/kowalski/task-board/task-board.stories.tsx +15 -0
  85. package/node_modules/@flickfyi/core/examples/kowalski/task-board/task-board.tsx +27 -0
  86. package/node_modules/@flickfyi/core/examples/kowalski/theme.ts +3 -0
  87. package/node_modules/@flickfyi/core/examples/kowalski/time-zone/time-zone.stories.tsx +15 -0
  88. package/node_modules/@flickfyi/core/examples/kowalski/time-zone/time-zone.tsx +22 -0
  89. package/node_modules/@flickfyi/core/examples/kowalski/timer/timer.stories.tsx +15 -0
  90. package/node_modules/@flickfyi/core/examples/kowalski/timer/timer.tsx +23 -0
  91. package/node_modules/@flickfyi/core/examples/kowalski/trip/trip.stories.tsx +15 -0
  92. package/node_modules/@flickfyi/core/examples/kowalski/trip/trip.tsx +26 -0
  93. package/node_modules/@flickfyi/core/examples/kowalski/unit-converter/unit-converter.stories.tsx +15 -0
  94. package/node_modules/@flickfyi/core/examples/kowalski/unit-converter/unit-converter.tsx +24 -0
  95. package/node_modules/@flickfyi/core/examples/parrott/calculator/calculator.stories.tsx +3 -1
  96. package/node_modules/@flickfyi/core/examples/parrott/checklist/checklist.stories.tsx +3 -1
  97. package/node_modules/@flickfyi/core/examples/parrott/countdown/countdown.stories.tsx +3 -1
  98. package/node_modules/@flickfyi/core/examples/parrott/counter/counter.stories.tsx +1 -0
  99. package/node_modules/@flickfyi/core/examples/parrott/fortune/fortune.stories.tsx +3 -1
  100. package/node_modules/@flickfyi/core/examples/parrott/grid/grid.stories.tsx +3 -1
  101. package/node_modules/@flickfyi/core/examples/parrott/kale-smoothie/kale-smoothie.stories.tsx +1 -0
  102. package/node_modules/@flickfyi/core/examples/parrott/list/list.stories.tsx +3 -1
  103. package/node_modules/@flickfyi/core/examples/parrott/log/log.stories.tsx +3 -1
  104. package/node_modules/@flickfyi/core/examples/parrott/timed-task/timed-task.stories.tsx +3 -1
  105. package/node_modules/@flickfyi/core/examples/parrott/timer/timer.stories.tsx +3 -1
  106. package/node_modules/@flickfyi/core/fixtures/native/host/project.yml +3 -0
  107. package/node_modules/@flickfyi/core/fixtures/native/src/catalog-features.tsx +88 -0
  108. package/node_modules/@flickfyi/core/package.json +35 -5
  109. package/node_modules/@flickfyi/core/package.tsgo.json +19 -1
  110. package/node_modules/@flickfyi/core/scripts/vite-globals.d.ts +2 -0
  111. package/node_modules/@flickfyi/core/src/generated-types.d.ts +1 -0
  112. package/node_modules/@flickfyi/core/src/kowalski/README.md +9 -0
  113. package/node_modules/@flickfyi/core/src/kowalski/calculations.ts +106 -0
  114. package/node_modules/@flickfyi/core/src/kowalski/calculator.ts +243 -0
  115. package/node_modules/@flickfyi/core/src/kowalski/catalog.ts +787 -0
  116. package/node_modules/@flickfyi/core/src/kowalski/clocks.tsx +464 -0
  117. package/node_modules/@flickfyi/core/src/kowalski/date-time.tsx +469 -0
  118. package/node_modules/@flickfyi/core/src/kowalski/details.tsx +1387 -0
  119. package/node_modules/@flickfyi/core/src/kowalski/everyday.tsx +652 -0
  120. package/node_modules/@flickfyi/core/src/kowalski/format.ts +48 -0
  121. package/node_modules/@flickfyi/core/src/kowalski/frame.tsx +351 -0
  122. package/node_modules/@flickfyi/core/src/kowalski/index.ts +23 -0
  123. package/node_modules/@flickfyi/core/src/kowalski/productivity.tsx +575 -0
  124. package/node_modules/@flickfyi/core/src/kowalski/recipe.tsx +555 -0
  125. package/node_modules/@flickfyi/core/src/kowalski/stories/composition.stories.tsx +47 -0
  126. package/node_modules/@flickfyi/core/src/kowalski/stories/composition.tsx +100 -0
  127. package/node_modules/@flickfyi/core/src/kowalski/tools.tsx +1213 -0
  128. package/node_modules/@flickfyi/core/src/kowalski/use-clock.ts +19 -0
  129. package/node_modules/@flickfyi/core/src/kowalski/use-configured-feature.ts +85 -0
  130. package/node_modules/@flickfyi/core/src/kowalski/use-feature-store.ts +119 -0
  131. package/node_modules/@flickfyi/core/src/molecules/field/field.tsx +34 -0
  132. package/node_modules/@flickfyi/core/src/molecules/index.ts +3 -0
  133. package/node_modules/@flickfyi/core/src/molecules/segmented/segmented.tsx +48 -0
  134. package/node_modules/@flickfyi/core/src/molecules/stepper/stepper.tsx +54 -0
  135. package/node_modules/@flickfyi/core/src/quantum/use-store.ts +41 -16
  136. package/node_modules/@flickfyi/core/tests/fly.test.ts +34 -7
  137. package/node_modules/@flickfyi/core/tests/kowalski-calculations.test.ts +60 -0
  138. package/node_modules/@flickfyi/core/tests/kowalski-calculator.test.ts +142 -0
  139. package/node_modules/@flickfyi/core/tests/kowalski-contracts.test.ts +223 -0
  140. package/node_modules/@flickfyi/core/tests/kowalski-date-time.test.tsx +462 -0
  141. package/node_modules/@flickfyi/core/tests/kowalski-features.test.tsx +2158 -0
  142. package/node_modules/@flickfyi/core/tests/kowalski-store.test.tsx +514 -0
  143. package/node_modules/@flickfyi/core/tests/preview-build.test.ts +1 -1
  144. package/node_modules/@flickfyi/core/tests/quantum-use-store.test.ts +53 -1
  145. package/node_modules/@flickfyi/core/tests/verify-tsgo-assets.test.ts +1 -1
  146. package/node_modules/@flickfyi/core/tsconfig.vite-dts.json +2 -1
  147. package/node_modules/@flickfyi/core/tsgo.bun.lock +111 -9
  148. package/node_modules/@flickfyi/core/tsgo.package.json +21 -3
  149. package/node_modules/@flickfyi/core/vite.config.ts +9 -5
  150. package/node_modules/@flickfyi/core/vitest.config.ts +1 -1
  151. package/node_modules/@flickfyi/http-message-sig/.turbo/turbo-build.log +7 -7
  152. package/node_modules/@flickfyi/identity/.turbo/turbo-build.log +8 -9
  153. package/node_modules/@flickfyi/lens/.turbo/turbo-build.log +7 -7
  154. package/node_modules/@flickfyi/photon/.turbo/turbo-build.log +4 -4
  155. package/node_modules/@flickfyi/photon/Sources/Photon/Components/Button.swift +29 -2
  156. package/node_modules/@flickfyi/photon/Sources/PhotonVersion/Resources/photon-version.json +1 -1
  157. package/node_modules/@flickfyi/photon/Tests/PhotonTests/Components/ButtonHostTests.swift +26 -0
  158. package/node_modules/@flickfyi/photon/Tests/PhotonTests/Fixtures/StyleX/catalog-features.styles.json +1 -0
  159. package/node_modules/@flickfyi/photon/Tests/PhotonTests/Fixtures/StyleX/catalog-native.styles.json +1 -1
  160. package/node_modules/@flickfyi/photon/Tests/PhotonTests/Fixtures/StyleX/catalog-scale.styles.json +1 -1
  161. package/node_modules/@flickfyi/photon/Tests/PhotonTests/Fixtures/StyleX/catalog-theme.styles.json +1 -1
  162. package/node_modules/@flickfyi/photon/Tests/PhotonTests/Fixtures/StyleX/catalog-typography.styles.json +1 -1
  163. package/node_modules/@flickfyi/photon/Tests/PhotonTests/Fixtures/StyleX/stylex-calculator.styles.json +1 -1
  164. package/node_modules/@flickfyi/photon/dist/globals.d.ts +5 -0
  165. package/node_modules/@flickfyi/photon/dist/version.cjs +1 -1
  166. package/node_modules/@flickfyi/photon/dist/version.js +1 -1
  167. package/node_modules/@flickfyi/photon/generated/react-swiftui.d.ts +1 -0
  168. package/node_modules/@flickfyi/photon/package.json +1 -1
  169. package/node_modules/@flickfyi/photon/src/globals.d.ts +5 -0
  170. package/node_modules/@flickfyi/rwsdk-extensions/.turbo/turbo-build.log +7 -7
  171. package/node_modules/@formatjs/fast-memoize/LICENSE.md +9 -0
  172. package/node_modules/@formatjs/fast-memoize/README.md +3 -0
  173. package/node_modules/@formatjs/fast-memoize/index.d.ts +35 -0
  174. package/node_modules/@formatjs/fast-memoize/index.js +69 -0
  175. package/node_modules/@formatjs/fast-memoize/index.js.map +1 -0
  176. package/node_modules/@formatjs/fast-memoize/package.json +25 -0
  177. package/node_modules/@formatjs/icu-messageformat-parser/LICENSE.md +9 -0
  178. package/node_modules/@formatjs/icu-messageformat-parser/README.md +38 -0
  179. package/node_modules/@formatjs/icu-messageformat-parser/index.d.ts +393 -0
  180. package/node_modules/@formatjs/icu-messageformat-parser/index.js +2187 -0
  181. package/node_modules/@formatjs/icu-messageformat-parser/index.js.map +1 -0
  182. package/node_modules/@formatjs/icu-messageformat-parser/manipulator.d.ts +175 -0
  183. package/node_modules/@formatjs/icu-messageformat-parser/manipulator.js +209 -0
  184. package/node_modules/@formatjs/icu-messageformat-parser/manipulator.js.map +1 -0
  185. package/node_modules/@formatjs/icu-messageformat-parser/no-parser.d.ts +183 -0
  186. package/node_modules/@formatjs/icu-messageformat-parser/no-parser.js +162 -0
  187. package/node_modules/@formatjs/icu-messageformat-parser/no-parser.js.map +1 -0
  188. package/node_modules/@formatjs/icu-messageformat-parser/package.json +21 -0
  189. package/node_modules/@formatjs/icu-messageformat-parser/printer.d.ts +154 -0
  190. package/node_modules/@formatjs/icu-messageformat-parser/printer.js +224 -0
  191. package/node_modules/@formatjs/icu-messageformat-parser/printer.js.map +1 -0
  192. package/node_modules/@formatjs/icu-skeleton-parser/LICENSE.md +9 -0
  193. package/node_modules/@formatjs/icu-skeleton-parser/README.md +1 -0
  194. package/node_modules/@formatjs/icu-skeleton-parser/index.d.ts +67 -0
  195. package/node_modules/@formatjs/icu-skeleton-parser/index.js +380 -0
  196. package/node_modules/@formatjs/icu-skeleton-parser/index.js.map +1 -0
  197. package/node_modules/@formatjs/icu-skeleton-parser/package.json +15 -0
  198. package/node_modules/@formatjs/intl/LICENSE.md +9 -0
  199. package/node_modules/@formatjs/intl/README.md +3 -0
  200. package/node_modules/@formatjs/intl/index.d.ts +499 -0
  201. package/node_modules/@formatjs/intl/index.js +595 -0
  202. package/node_modules/@formatjs/intl/index.js.map +1 -0
  203. package/node_modules/@formatjs/intl/package.json +37 -0
  204. package/node_modules/decimal.js/LICENCE.md +23 -0
  205. package/node_modules/decimal.js/README.md +246 -0
  206. package/node_modules/decimal.js/decimal.d.ts +301 -0
  207. package/node_modules/decimal.js/decimal.js +4951 -0
  208. package/node_modules/decimal.js/decimal.mjs +4914 -0
  209. package/node_modules/decimal.js/package.json +55 -0
  210. package/node_modules/format-quantity/LICENSE +21 -0
  211. package/node_modules/format-quantity/README.md +181 -0
  212. package/node_modules/format-quantity/dist/cjs/format-quantity.cjs.development.d.ts +131 -0
  213. package/node_modules/format-quantity/dist/cjs/format-quantity.cjs.development.js +214 -0
  214. package/node_modules/format-quantity/dist/cjs/format-quantity.cjs.development.js.map +1 -0
  215. package/node_modules/format-quantity/dist/cjs/format-quantity.cjs.production.d.ts +131 -0
  216. package/node_modules/format-quantity/dist/cjs/format-quantity.cjs.production.js +2 -0
  217. package/node_modules/format-quantity/dist/cjs/format-quantity.cjs.production.js.map +1 -0
  218. package/node_modules/format-quantity/dist/cjs/index.d.ts +1 -0
  219. package/node_modules/format-quantity/dist/cjs/index.js +6 -0
  220. package/node_modules/format-quantity/dist/format-quantity.d.mts +131 -0
  221. package/node_modules/format-quantity/dist/format-quantity.legacy-esm.d.ts +131 -0
  222. package/node_modules/format-quantity/dist/format-quantity.legacy-esm.js +268 -0
  223. package/node_modules/format-quantity/dist/format-quantity.legacy-esm.js.map +1 -0
  224. package/node_modules/format-quantity/dist/format-quantity.mjs +208 -0
  225. package/node_modules/format-quantity/dist/format-quantity.mjs.map +1 -0
  226. package/node_modules/format-quantity/dist/format-quantity.production.d.mts +131 -0
  227. package/node_modules/format-quantity/dist/format-quantity.production.mjs +2 -0
  228. package/node_modules/format-quantity/dist/format-quantity.production.mjs.map +1 -0
  229. package/node_modules/format-quantity/dist/format-quantity.umd.min.js +3 -0
  230. package/node_modules/format-quantity/dist/format-quantity.umd.min.js.map +1 -0
  231. package/node_modules/format-quantity/package.json +81 -0
  232. package/node_modules/intl-messageformat/LICENSE.md +33 -0
  233. package/node_modules/intl-messageformat/README.md +3 -0
  234. package/node_modules/intl-messageformat/index.d.ts +177 -0
  235. package/node_modules/intl-messageformat/index.js +327 -0
  236. package/node_modules/intl-messageformat/index.js.map +1 -0
  237. package/node_modules/intl-messageformat/intl-messageformat.iife.js +2819 -0
  238. package/node_modules/intl-messageformat/package.json +40 -0
  239. package/node_modules/numeric-quantity/LICENSE +21 -0
  240. package/node_modules/numeric-quantity/README.md +306 -0
  241. package/node_modules/numeric-quantity/dist/cjs/index.d.ts +1 -0
  242. package/node_modules/numeric-quantity/dist/cjs/index.js +6 -0
  243. package/node_modules/numeric-quantity/dist/cjs/numeric-quantity.cjs.development.d.ts +293 -0
  244. package/node_modules/numeric-quantity/dist/cjs/numeric-quantity.cjs.development.js +579 -0
  245. package/node_modules/numeric-quantity/dist/cjs/numeric-quantity.cjs.development.js.map +1 -0
  246. package/node_modules/numeric-quantity/dist/cjs/numeric-quantity.cjs.production.d.ts +293 -0
  247. package/node_modules/numeric-quantity/dist/cjs/numeric-quantity.cjs.production.js +2 -0
  248. package/node_modules/numeric-quantity/dist/cjs/numeric-quantity.cjs.production.js.map +1 -0
  249. package/node_modules/numeric-quantity/dist/numeric-quantity.d.mts +293 -0
  250. package/node_modules/numeric-quantity/dist/numeric-quantity.iife.umd.min.js +2 -0
  251. package/node_modules/numeric-quantity/dist/numeric-quantity.iife.umd.min.js.map +1 -0
  252. package/node_modules/numeric-quantity/dist/numeric-quantity.legacy-esm.d.ts +293 -0
  253. package/node_modules/numeric-quantity/dist/numeric-quantity.legacy-esm.js +622 -0
  254. package/node_modules/numeric-quantity/dist/numeric-quantity.legacy-esm.js.map +1 -0
  255. package/node_modules/numeric-quantity/dist/numeric-quantity.mjs +564 -0
  256. package/node_modules/numeric-quantity/dist/numeric-quantity.mjs.map +1 -0
  257. package/node_modules/numeric-quantity/dist/numeric-quantity.production.d.mts +293 -0
  258. package/node_modules/numeric-quantity/dist/numeric-quantity.production.mjs +2 -0
  259. package/node_modules/numeric-quantity/dist/numeric-quantity.production.mjs.map +1 -0
  260. package/node_modules/numeric-quantity/package.json +72 -0
  261. package/node_modules/validator/LICENSE +20 -0
  262. package/node_modules/validator/README.md +269 -0
  263. package/node_modules/validator/es/index.js +218 -0
  264. package/node_modules/validator/es/lib/alpha.js +151 -0
  265. package/node_modules/validator/es/lib/blacklist.js +5 -0
  266. package/node_modules/validator/es/lib/contains.js +15 -0
  267. package/node_modules/validator/es/lib/equals.js +5 -0
  268. package/node_modules/validator/es/lib/escape.js +5 -0
  269. package/node_modules/validator/es/lib/isAbaRouting.js +15 -0
  270. package/node_modules/validator/es/lib/isAfter.js +10 -0
  271. package/node_modules/validator/es/lib/isAlpha.js +23 -0
  272. package/node_modules/validator/es/lib/isAlphanumeric.js +23 -0
  273. package/node_modules/validator/es/lib/isAscii.js +10 -0
  274. package/node_modules/validator/es/lib/isBIC.js +16 -0
  275. package/node_modules/validator/es/lib/isBase32.js +15 -0
  276. package/node_modules/validator/es/lib/isBase58.js +8 -0
  277. package/node_modules/validator/es/lib/isBase64.js +23 -0
  278. package/node_modules/validator/es/lib/isBefore.js +10 -0
  279. package/node_modules/validator/es/lib/isBoolean.js +15 -0
  280. package/node_modules/validator/es/lib/isBtcAddress.js +7 -0
  281. package/node_modules/validator/es/lib/isByteLength.js +19 -0
  282. package/node_modules/validator/es/lib/isCreditCard.js +43 -0
  283. package/node_modules/validator/es/lib/isCurrency.js +74 -0
  284. package/node_modules/validator/es/lib/isDataURI.js +31 -0
  285. package/node_modules/validator/es/lib/isDate.js +93 -0
  286. package/node_modules/validator/es/lib/isDecimal.js +22 -0
  287. package/node_modules/validator/es/lib/isDivisibleBy.js +6 -0
  288. package/node_modules/validator/es/lib/isEAN.js +70 -0
  289. package/node_modules/validator/es/lib/isEmail.js +165 -0
  290. package/node_modules/validator/es/lib/isEmpty.js +10 -0
  291. package/node_modules/validator/es/lib/isEthereumAddress.js +6 -0
  292. package/node_modules/validator/es/lib/isFQDN.js +67 -0
  293. package/node_modules/validator/es/lib/isFloat.js +14 -0
  294. package/node_modules/validator/es/lib/isFullWidth.js +6 -0
  295. package/node_modules/validator/es/lib/isHSL.js +13 -0
  296. package/node_modules/validator/es/lib/isHalfWidth.js +6 -0
  297. package/node_modules/validator/es/lib/isHash.js +21 -0
  298. package/node_modules/validator/es/lib/isHexColor.js +13 -0
  299. package/node_modules/validator/es/lib/isHexadecimal.js +6 -0
  300. package/node_modules/validator/es/lib/isIBAN.js +171 -0
  301. package/node_modules/validator/es/lib/isIMEI.js +40 -0
  302. package/node_modules/validator/es/lib/isIP.js +58 -0
  303. package/node_modules/validator/es/lib/isIPRange.js +41 -0
  304. package/node_modules/validator/es/lib/isISBN.js +47 -0
  305. package/node_modules/validator/es/lib/isISIN.js +55 -0
  306. package/node_modules/validator/es/lib/isISO15924.js +9 -0
  307. package/node_modules/validator/es/lib/isISO31661Alpha2.js +21 -0
  308. package/node_modules/validator/es/lib/isISO31661Alpha3.js +20 -0
  309. package/node_modules/validator/es/lib/isISO31661Numeric.js +8 -0
  310. package/node_modules/validator/es/lib/isISO4217.js +9 -0
  311. package/node_modules/validator/es/lib/isISO6346.js +28 -0
  312. package/node_modules/validator/es/lib/isISO6391.js +6 -0
  313. package/node_modules/validator/es/lib/isISO8601.js +42 -0
  314. package/node_modules/validator/es/lib/isISRC.js +8 -0
  315. package/node_modules/validator/es/lib/isISSN.js +19 -0
  316. package/node_modules/validator/es/lib/isIdentityCard.js +407 -0
  317. package/node_modules/validator/es/lib/isIn.js +23 -0
  318. package/node_modules/validator/es/lib/isInt.js +19 -0
  319. package/node_modules/validator/es/lib/isJSON.js +26 -0
  320. package/node_modules/validator/es/lib/isJWT.js +15 -0
  321. package/node_modules/validator/es/lib/isLatLong.js +21 -0
  322. package/node_modules/validator/es/lib/isLength.js +27 -0
  323. package/node_modules/validator/es/lib/isLicensePlate.js +58 -0
  324. package/node_modules/validator/es/lib/isLocale.js +107 -0
  325. package/node_modules/validator/es/lib/isLowercase.js +5 -0
  326. package/node_modules/validator/es/lib/isLuhnNumber.js +25 -0
  327. package/node_modules/validator/es/lib/isMACAddress.js +36 -0
  328. package/node_modules/validator/es/lib/isMD5.js +6 -0
  329. package/node_modules/validator/es/lib/isMagnetURI.js +9 -0
  330. package/node_modules/validator/es/lib/isMailtoURI.js +75 -0
  331. package/node_modules/validator/es/lib/isMimeType.js +40 -0
  332. package/node_modules/validator/es/lib/isMobilePhone.js +212 -0
  333. package/node_modules/validator/es/lib/isMongoId.js +6 -0
  334. package/node_modules/validator/es/lib/isMultibyte.js +10 -0
  335. package/node_modules/validator/es/lib/isNumeric.js +10 -0
  336. package/node_modules/validator/es/lib/isOctal.js +6 -0
  337. package/node_modules/validator/es/lib/isPassportNumber.js +145 -0
  338. package/node_modules/validator/es/lib/isPort.js +8 -0
  339. package/node_modules/validator/es/lib/isPostalCode.js +100 -0
  340. package/node_modules/validator/es/lib/isRFC3339.js +21 -0
  341. package/node_modules/validator/es/lib/isRgbColor.js +34 -0
  342. package/node_modules/validator/es/lib/isSemVer.js +14 -0
  343. package/node_modules/validator/es/lib/isSlug.js +6 -0
  344. package/node_modules/validator/es/lib/isStrongPassword.js +90 -0
  345. package/node_modules/validator/es/lib/isSurrogatePair.js +6 -0
  346. package/node_modules/validator/es/lib/isTaxID.js +1407 -0
  347. package/node_modules/validator/es/lib/isTime.js +22 -0
  348. package/node_modules/validator/es/lib/isULID.js +5 -0
  349. package/node_modules/validator/es/lib/isURL.js +241 -0
  350. package/node_modules/validator/es/lib/isUUID.js +23 -0
  351. package/node_modules/validator/es/lib/isUppercase.js +5 -0
  352. package/node_modules/validator/es/lib/isVAT.js +264 -0
  353. package/node_modules/validator/es/lib/isVariableWidth.js +7 -0
  354. package/node_modules/validator/es/lib/isWhitelisted.js +10 -0
  355. package/node_modules/validator/es/lib/ltrim.js +7 -0
  356. package/node_modules/validator/es/lib/matches.js +8 -0
  357. package/node_modules/validator/es/lib/normalizeEmail.js +131 -0
  358. package/node_modules/validator/es/lib/rtrim.js +15 -0
  359. package/node_modules/validator/es/lib/stripLow.js +7 -0
  360. package/node_modules/validator/es/lib/toBoolean.js +8 -0
  361. package/node_modules/validator/es/lib/toDate.js +6 -0
  362. package/node_modules/validator/es/lib/toFloat.js +5 -0
  363. package/node_modules/validator/es/lib/toInt.js +5 -0
  364. package/node_modules/validator/es/lib/trim.js +5 -0
  365. package/node_modules/validator/es/lib/unescape.js +8 -0
  366. package/node_modules/validator/es/lib/util/algorithms.js +79 -0
  367. package/node_modules/validator/es/lib/util/assertString.js +4 -0
  368. package/node_modules/validator/es/lib/util/checkHost.js +12 -0
  369. package/node_modules/validator/es/lib/util/includesArray.js +6 -0
  370. package/node_modules/validator/es/lib/util/includesString.js +4 -0
  371. package/node_modules/validator/es/lib/util/merge.js +14 -0
  372. package/node_modules/validator/es/lib/util/multilineRegex.js +12 -0
  373. package/node_modules/validator/es/lib/util/nullUndefinedCheck.js +3 -0
  374. package/node_modules/validator/es/lib/util/toString.js +13 -0
  375. package/node_modules/validator/es/lib/util/typeOf.js +10 -0
  376. package/node_modules/validator/es/lib/whitelist.js +5 -0
  377. package/node_modules/validator/index.js +229 -0
  378. package/node_modules/validator/lib/alpha.js +157 -0
  379. package/node_modules/validator/lib/blacklist.js +14 -0
  380. package/node_modules/validator/lib/contains.js +24 -0
  381. package/node_modules/validator/lib/equals.js +14 -0
  382. package/node_modules/validator/lib/escape.js +14 -0
  383. package/node_modules/validator/lib/isAbaRouting.js +23 -0
  384. package/node_modules/validator/lib/isAfter.js +19 -0
  385. package/node_modules/validator/lib/isAlpha.js +31 -0
  386. package/node_modules/validator/lib/isAlphanumeric.js +31 -0
  387. package/node_modules/validator/lib/isAscii.js +18 -0
  388. package/node_modules/validator/lib/isBIC.js +24 -0
  389. package/node_modules/validator/lib/isBase32.js +24 -0
  390. package/node_modules/validator/lib/isBase58.js +16 -0
  391. package/node_modules/validator/lib/isBase64.js +32 -0
  392. package/node_modules/validator/lib/isBefore.js +19 -0
  393. package/node_modules/validator/lib/isBoolean.js +24 -0
  394. package/node_modules/validator/lib/isBtcAddress.js +16 -0
  395. package/node_modules/validator/lib/isByteLength.js +27 -0
  396. package/node_modules/validator/lib/isCreditCard.js +52 -0
  397. package/node_modules/validator/lib/isCurrency.js +83 -0
  398. package/node_modules/validator/lib/isDataURI.js +40 -0
  399. package/node_modules/validator/lib/isDate.js +102 -0
  400. package/node_modules/validator/lib/isDecimal.js +31 -0
  401. package/node_modules/validator/lib/isDivisibleBy.js +15 -0
  402. package/node_modules/validator/lib/isEAN.js +78 -0
  403. package/node_modules/validator/lib/isEmail.js +174 -0
  404. package/node_modules/validator/lib/isEmpty.js +19 -0
  405. package/node_modules/validator/lib/isEthereumAddress.js +15 -0
  406. package/node_modules/validator/lib/isFQDN.js +76 -0
  407. package/node_modules/validator/lib/isFloat.js +22 -0
  408. package/node_modules/validator/lib/isFullWidth.js +14 -0
  409. package/node_modules/validator/lib/isHSL.js +22 -0
  410. package/node_modules/validator/lib/isHalfWidth.js +14 -0
  411. package/node_modules/validator/lib/isHash.js +30 -0
  412. package/node_modules/validator/lib/isHexColor.js +22 -0
  413. package/node_modules/validator/lib/isHexadecimal.js +15 -0
  414. package/node_modules/validator/lib/isIBAN.js +178 -0
  415. package/node_modules/validator/lib/isIMEI.js +49 -0
  416. package/node_modules/validator/lib/isIP.js +67 -0
  417. package/node_modules/validator/lib/isIPRange.js +50 -0
  418. package/node_modules/validator/lib/isISBN.js +56 -0
  419. package/node_modules/validator/lib/isISIN.js +64 -0
  420. package/node_modules/validator/lib/isISO15924.js +16 -0
  421. package/node_modules/validator/lib/isISO31661Alpha2.js +28 -0
  422. package/node_modules/validator/lib/isISO31661Alpha3.js +28 -0
  423. package/node_modules/validator/lib/isISO31661Numeric.js +16 -0
  424. package/node_modules/validator/lib/isISO4217.js +16 -0
  425. package/node_modules/validator/lib/isISO6346.js +35 -0
  426. package/node_modules/validator/lib/isISO6391.js +15 -0
  427. package/node_modules/validator/lib/isISO8601.js +50 -0
  428. package/node_modules/validator/lib/isISRC.js +16 -0
  429. package/node_modules/validator/lib/isISSN.js +28 -0
  430. package/node_modules/validator/lib/isIdentityCard.js +416 -0
  431. package/node_modules/validator/lib/isIn.js +32 -0
  432. package/node_modules/validator/lib/isInt.js +28 -0
  433. package/node_modules/validator/lib/isJSON.js +35 -0
  434. package/node_modules/validator/lib/isJWT.js +24 -0
  435. package/node_modules/validator/lib/isLatLong.js +30 -0
  436. package/node_modules/validator/lib/isLength.js +35 -0
  437. package/node_modules/validator/lib/isLicensePlate.js +67 -0
  438. package/node_modules/validator/lib/isLocale.js +115 -0
  439. package/node_modules/validator/lib/isLowercase.js +14 -0
  440. package/node_modules/validator/lib/isLuhnNumber.js +34 -0
  441. package/node_modules/validator/lib/isMACAddress.js +45 -0
  442. package/node_modules/validator/lib/isMD5.js +15 -0
  443. package/node_modules/validator/lib/isMagnetURI.js +18 -0
  444. package/node_modules/validator/lib/isMailtoURI.js +84 -0
  445. package/node_modules/validator/lib/isMimeType.js +48 -0
  446. package/node_modules/validator/lib/isMobilePhone.js +219 -0
  447. package/node_modules/validator/lib/isMongoId.js +15 -0
  448. package/node_modules/validator/lib/isMultibyte.js +18 -0
  449. package/node_modules/validator/lib/isNumeric.js +19 -0
  450. package/node_modules/validator/lib/isOctal.js +15 -0
  451. package/node_modules/validator/lib/isPassportNumber.js +152 -0
  452. package/node_modules/validator/lib/isPort.js +17 -0
  453. package/node_modules/validator/lib/isPostalCode.js +107 -0
  454. package/node_modules/validator/lib/isRFC3339.js +29 -0
  455. package/node_modules/validator/lib/isRgbColor.js +42 -0
  456. package/node_modules/validator/lib/isSemVer.js +22 -0
  457. package/node_modules/validator/lib/isSlug.js +15 -0
  458. package/node_modules/validator/lib/isStrongPassword.js +99 -0
  459. package/node_modules/validator/lib/isSurrogatePair.js +15 -0
  460. package/node_modules/validator/lib/isTaxID.js +1417 -0
  461. package/node_modules/validator/lib/isTime.js +31 -0
  462. package/node_modules/validator/lib/isULID.js +14 -0
  463. package/node_modules/validator/lib/isURL.js +249 -0
  464. package/node_modules/validator/lib/isUUID.js +32 -0
  465. package/node_modules/validator/lib/isUppercase.js +14 -0
  466. package/node_modules/validator/lib/isVAT.js +274 -0
  467. package/node_modules/validator/lib/isVariableWidth.js +16 -0
  468. package/node_modules/validator/lib/isWhitelisted.js +19 -0
  469. package/node_modules/validator/lib/ltrim.js +16 -0
  470. package/node_modules/validator/lib/matches.js +17 -0
  471. package/node_modules/validator/lib/normalizeEmail.js +140 -0
  472. package/node_modules/validator/lib/rtrim.js +24 -0
  473. package/node_modules/validator/lib/stripLow.js +16 -0
  474. package/node_modules/validator/lib/toBoolean.js +17 -0
  475. package/node_modules/validator/lib/toDate.js +15 -0
  476. package/node_modules/validator/lib/toFloat.js +14 -0
  477. package/node_modules/validator/lib/toInt.js +14 -0
  478. package/node_modules/validator/lib/trim.js +14 -0
  479. package/node_modules/validator/lib/unescape.js +17 -0
  480. package/node_modules/validator/lib/util/algorithms.js +88 -0
  481. package/node_modules/validator/lib/util/assertString.js +12 -0
  482. package/node_modules/validator/lib/util/checkHost.js +20 -0
  483. package/node_modules/validator/lib/util/includesArray.js +14 -0
  484. package/node_modules/validator/lib/util/includesString.js +12 -0
  485. package/node_modules/validator/lib/util/merge.js +22 -0
  486. package/node_modules/validator/lib/util/multilineRegex.js +20 -0
  487. package/node_modules/validator/lib/util/nullUndefinedCheck.js +11 -0
  488. package/node_modules/validator/lib/util/toString.js +21 -0
  489. package/node_modules/validator/lib/util/typeOf.js +18 -0
  490. package/node_modules/validator/lib/whitelist.js +14 -0
  491. package/node_modules/validator/package.json +76 -0
  492. package/node_modules/validator/validator.js +5808 -0
  493. package/node_modules/validator/validator.min.js +23 -0
  494. package/package.json +3 -3
@@ -0,0 +1,787 @@
1
+ import isURL from 'validator/lib/isURL.js'
2
+ import { z } from 'zod/v4'
3
+
4
+ /** A feature's store name; without one it is Kowalski<ExportName>. */
5
+ export const kowalskiFeatureId = z
6
+ .string()
7
+ .regex(/^[A-Za-z][A-Za-z0-9]*$/)
8
+ .optional()
9
+ export const kowalskiScope = z.enum(['private', 'public']).default('private')
10
+
11
+ /** Per-item store fields are `<prefix><item id>`; Florge checks their keys from this map. */
12
+ export const entryPrefixes = {
13
+ budget: 'spent_',
14
+ checklist: 'completed_',
15
+ habit: 'completed_',
16
+ poll: 'vote_',
17
+ recipe: 'step_',
18
+ scoreboard: 'score_',
19
+ shoppingList: 'got_',
20
+ taskBoard: 'status_',
21
+ } as const
22
+
23
+ /** In JavaScript `Date#getUTCDay` order, so index 0 is Sunday. */
24
+ export const weekdayNames = [
25
+ 'sunday',
26
+ 'monday',
27
+ 'tuesday',
28
+ 'wednesday',
29
+ 'thursday',
30
+ 'friday',
31
+ 'saturday',
32
+ ] as const
33
+
34
+ /** Pure contracts shared by Core, Florge, and the catalog; no rendering imports. */
35
+ export const kowalskiCatalog = {
36
+ billSplit: {
37
+ description:
38
+ 'Split a bill equally with an optional tip, rounding in the selected currency.',
39
+ exportName: 'BillSplit',
40
+ props: featureProps({
41
+ currency: currency(),
42
+ people: z.number().int().min(1).max(1000),
43
+ tipPercent: z.number().min(0).max(100).default(0),
44
+ title: title('Split the bill'),
45
+ total: z.number().min(0).max(1e12),
46
+ }),
47
+ storeSchema: store({
48
+ people: z.number().int().min(1).max(1000).default(1),
49
+ tipPercent: z.number().min(0).max(100).default(0),
50
+ total: z.number().min(0).max(1e12).default(0),
51
+ }),
52
+ },
53
+ bookmark: {
54
+ description: 'Display, edit, and retain a web bookmark. No implicit metadata fetch.',
55
+ exportName: 'Bookmark',
56
+ props: featureProps({
57
+ note: z.string().max(10_000).default(''),
58
+ title: title(),
59
+ url: webAddress(),
60
+ }),
61
+ storeSchema: store({
62
+ note: replacement(z.string().max(10_000).default('')),
63
+ title: replacement(z.string().max(160).default('')),
64
+ url: replacement(webAddress().nullable().default(null)),
65
+ }),
66
+ },
67
+ budget: {
68
+ description:
69
+ 'Track spending against category limits for one budget period. No bank connection or payments.',
70
+ exportName: 'Budget',
71
+ props: featureProps({
72
+ categories: identifiedList(
73
+ { label: z.string().min(1).max(80), limit: z.number().positive().max(1e12) },
74
+ 12
75
+ ),
76
+ currency: currency(),
77
+ title: title('Budget'),
78
+ }),
79
+ storeSchema: entries(entryPrefixes.budget, z.number().min(0).max(1e12), {}),
80
+ },
81
+ calculator: {
82
+ description:
83
+ 'A persistent keypad calculator with chained arithmetic, decimals, sign, percent, and repeated equals. Supports +, -, *, /. No executable expression strings.',
84
+ exportName: 'Calculator',
85
+ props: featureProps({
86
+ left: z.number().default(0),
87
+ operator: z.enum(['+', '-', '*', '/']).default('+'),
88
+ right: z.number().default(0),
89
+ title: title('Calculate'),
90
+ }),
91
+ storeSchema: store({
92
+ calculation: z
93
+ .object({
94
+ entry: z
95
+ .string()
96
+ .max(40)
97
+ .regex(/^(?:-?\d+(?:\.\d*)?(?:e[+-]?\d+)?|Error)$/),
98
+ left: z.number(),
99
+ operator: z.enum(['+', '-', '*', '/']),
100
+ overwrite: z.boolean(),
101
+ phase: z.enum(['left', 'operator', 'right', 'result', 'error']),
102
+ right: z.number(),
103
+ })
104
+ .refine(
105
+ calculation =>
106
+ calculation.phase === 'error'
107
+ ? calculation.entry === 'Error'
108
+ : calculation.entry !== 'Error' &&
109
+ Number.isFinite(Number(calculation.entry)),
110
+ 'Calculator entry must match its phase and represent a finite number.'
111
+ )
112
+ .default({
113
+ entry: '0',
114
+ left: 0,
115
+ operator: '+',
116
+ overwrite: false,
117
+ phase: 'left',
118
+ right: 0,
119
+ }),
120
+ }),
121
+ },
122
+ checklist: {
123
+ description:
124
+ 'A persistent checklist with independent completion and progress. No external actions.',
125
+ exportName: 'Checklist',
126
+ props: featureProps({
127
+ items: identifiedList({ label: z.string().min(1).max(500) }, 100),
128
+ title: title(),
129
+ }),
130
+ storeSchema: entries(entryPrefixes.checklist, z.boolean(), {}),
131
+ },
132
+ colorPalette: {
133
+ description: 'Choose and retain an sRGB color and display matching shades.',
134
+ exportName: 'ColorPalette',
135
+ props: featureProps({
136
+ color: z.string().regex(/^#[\da-fA-F]{6}$/),
137
+ title: title('Palette'),
138
+ }),
139
+ storeSchema: store({
140
+ color: replacement(
141
+ z
142
+ .string()
143
+ .regex(/^#[\da-fA-F]{6}$/)
144
+ .default('#6366f1')
145
+ ),
146
+ }),
147
+ },
148
+ contact: {
149
+ description:
150
+ 'Display, edit, and retain a contact. Does not insert into the address book.',
151
+ exportName: 'Contact',
152
+ props: featureProps({
153
+ email: z.email().optional(),
154
+ name: z.string().min(1).max(160),
155
+ phone: z.string().min(1).max(80).optional(),
156
+ }),
157
+ storeSchema: store({
158
+ email: replacement(z.email().nullable().default(null)),
159
+ name: replacement(z.string().max(160).default('')),
160
+ phone: replacement(z.string().min(1).max(80).nullable().default(null)),
161
+ }),
162
+ },
163
+ countdown: {
164
+ description:
165
+ 'Count down to an explicit instant. Resolve missing dates before instantiation.',
166
+ exportName: 'Countdown',
167
+ props: featureProps({
168
+ target: z.iso.datetime({ offset: true }),
169
+ timeZone: timeZone().default('UTC'),
170
+ title: title(),
171
+ }),
172
+ storeSchema: store({
173
+ target: replacement(z.iso.datetime({ offset: true }).nullable().default(null)),
174
+ }),
175
+ },
176
+ event: {
177
+ description:
178
+ 'Save and edit event details in the app. Does not create a calendar event.',
179
+ exportName: 'Event',
180
+ props: featureProps({
181
+ location: z.string().max(500).default(''),
182
+ startsAt: z.iso.datetime({ offset: true }).nullable().default(null),
183
+ timeZone: timeZone().default('UTC'),
184
+ title: title(),
185
+ }),
186
+ storeSchema: store({
187
+ location: replacement(z.string().max(500).default('')),
188
+ startsAt: replacement(z.iso.datetime({ offset: true }).nullable().default(null)),
189
+ title: replacement(z.string().max(160).default('')),
190
+ }),
191
+ },
192
+ expense: {
193
+ description:
194
+ 'Edit and retain one expense. No payments, bank connection, or exchange-rate lookup.',
195
+ exportName: 'Expense',
196
+ props: featureProps({
197
+ amount: z.number().min(0).max(1e12),
198
+ category: z.string().max(80).default('Other'),
199
+ currency: currency(),
200
+ title: title(),
201
+ }),
202
+ storeSchema: store({
203
+ amount: z.number().min(0).max(1e12).default(0),
204
+ category: replacement(z.string().max(80).default('Other')),
205
+ title: replacement(z.string().max(160).default('')),
206
+ }),
207
+ },
208
+ goal: {
209
+ description:
210
+ 'A personal goal with editable progress, target, and a fixed increment. Not a distributed counter.',
211
+ exportName: 'Goal',
212
+ props: featureProps({
213
+ progress: z.number().min(0).max(1e12).default(0),
214
+ step: z.number().positive().max(1e9).default(1),
215
+ target: z.number().positive().max(1e12),
216
+ title: title(),
217
+ unit: z.string().max(40).default(''),
218
+ }),
219
+ storeSchema: store({ progress: z.number().min(0).default(0) }),
220
+ },
221
+ habit: {
222
+ description:
223
+ 'Track a habit by local date and edit its weekday schedule. No notifications.',
224
+ exportName: 'Habit',
225
+ props: featureProps({
226
+ timeZone: timeZone().default('UTC'),
227
+ title: title(),
228
+ weekdays: weekdays(),
229
+ }),
230
+ storeSchema: entries(entryPrefixes.habit, z.boolean(), { weekdays: weekdays() }),
231
+ },
232
+ ledger: {
233
+ description:
234
+ 'A running tab of shared costs between two people, split evenly, with settle up. No payments.',
235
+ exportName: 'Ledger',
236
+ props: featureProps({
237
+ currency: currency(),
238
+ people: identifiedList({ label: z.string().min(1).max(80) }, 2, 2),
239
+ title: title('Shared tab'),
240
+ }),
241
+ storeSchema: store({
242
+ entries: z
243
+ .array(
244
+ z.strictObject({
245
+ amount: z.number().positive().max(1e12),
246
+ id: itemId(),
247
+ label: z.string().max(160),
248
+ paidBy: itemId(),
249
+ })
250
+ )
251
+ .max(200)
252
+ .default([]),
253
+ }),
254
+ },
255
+ note: {
256
+ description: 'An editable persistent note. Plain text; no HTML or code execution.',
257
+ exportName: 'Note',
258
+ props: featureProps({
259
+ body: z.string().max(20_000),
260
+ title: z.string().max(160),
261
+ }),
262
+ storeSchema: store({
263
+ body: replacement(z.string().max(20_000).default('')),
264
+ title: replacement(z.string().max(160).default('')),
265
+ }),
266
+ },
267
+ poll: {
268
+ exportName: 'Poll',
269
+ description:
270
+ 'Cast or change a vote and derive totals from votes. Shared voting only when explicitly requested.',
271
+ props: featureProps({
272
+ options: identifiedList({ label: z.string().min(1).max(160) }, 12, 2),
273
+ question: z.string().min(1).max(500),
274
+ shared: z.boolean().default(false),
275
+ }),
276
+ // Each vote_<voter> holds an option id.
277
+ storeSchema: entries(entryPrefixes.poll, itemId(), {}),
278
+ },
279
+ randomPicker: {
280
+ description:
281
+ 'Flip a coin, roll a die, or pick from a bounded integer range or list. Retains the last result.',
282
+ exportName: 'RandomPicker',
283
+ props: z.discriminatedUnion('mode', [
284
+ featureProps({ mode: z.literal('coin'), title: title('Pick one') }),
285
+ featureProps({ mode: z.literal('dice'), title: title('Pick one') }),
286
+ featureProps({
287
+ maximum: z.number().int().min(-1e9).max(1e9),
288
+ minimum: z.number().int().min(-1e9).max(1e9),
289
+ mode: z.literal('range'),
290
+ title: title('Pick one'),
291
+ }).refine(value => value.minimum <= value.maximum, {
292
+ message: 'Minimum cannot exceed maximum.',
293
+ path: ['maximum'],
294
+ }),
295
+ featureProps({
296
+ mode: z.literal('list'),
297
+ options: z.array(z.string().min(1).max(160)).min(1).max(100),
298
+ title: title('Pick one'),
299
+ }),
300
+ ]),
301
+ // The last pick, with the choices it was drawn from so a changed picker drops it.
302
+ storeSchema: store({
303
+ result: z
304
+ .strictObject({
305
+ domain: pickerDomain(),
306
+ value: z.union([z.number().int(), z.string().max(160)]),
307
+ })
308
+ .nullable()
309
+ .default(null),
310
+ }),
311
+ },
312
+ rating: {
313
+ description: 'Rate one thing from one to five stars and keep a short note about it.',
314
+ exportName: 'Rating',
315
+ props: featureProps({
316
+ subject: z.string().min(1).max(160),
317
+ title: title('Your rating'),
318
+ }),
319
+ storeSchema: store({
320
+ note: replacement(z.string().max(2000).default('')),
321
+ stars: z.number().int().min(0).max(5).default(0),
322
+ }),
323
+ },
324
+ recipe: {
325
+ description:
326
+ 'Cook a recipe whose steps follow the Recipe Graph Format (rgf/0-draft): each step uses ingredients or earlier step outputs, waits on the steps in after, and may carry a duration, doneness cue, and attention. Ingredients carry a numeric amount and unit, and meta.servings is a number, so amounts scale with servings. Shows running timers, the current step, and the next few. No nutrition or shopping lookup.',
327
+ exportName: 'Recipe',
328
+ props: featureProps({
329
+ ingredients: identifiedList(
330
+ {
331
+ amount: z.number().positive().max(1e6).optional(),
332
+ label: z.string().min(1).max(160),
333
+ notes: z.array(z.string().max(160)).max(10).optional(),
334
+ unit: z.string().max(40).optional(),
335
+ },
336
+ 60
337
+ ),
338
+ servings: z.number().int().min(1).max(100).optional(),
339
+ // Steps follow RGF (rgf/0-draft): uses, outputs, and after form the dependency graph.
340
+ steps: z
341
+ .array(
342
+ z.strictObject({
343
+ after: z.array(itemId()).max(60).optional(),
344
+ attention: z.enum(['active', 'passive']).optional(),
345
+ doneness: z.string().max(200).optional(),
346
+ duration: z
347
+ .strictObject({
348
+ maxMinutes: z.number().nonnegative().max(10_080).optional(),
349
+ minMinutes: z.number().nonnegative().max(10_080).optional(),
350
+ raw: z.string().min(1).max(80),
351
+ })
352
+ .refine(
353
+ duration =>
354
+ duration.minMinutes === undefined ||
355
+ duration.maxMinutes === undefined ||
356
+ duration.minMinutes <= duration.maxMinutes,
357
+ 'minMinutes cannot exceed maxMinutes.'
358
+ )
359
+ .optional(),
360
+ equipment: z.array(z.string().min(1).max(160)).max(20).optional(),
361
+ id: itemId(),
362
+ instruction: z.string().min(1).max(500),
363
+ kind: z.enum(['setup', 'transform', 'wait', 'serve']).optional(),
364
+ label: z.string().max(80).optional(),
365
+ outputs: z
366
+ .array(z.strictObject({ id: itemId(), name: z.string().max(160).optional() }))
367
+ .max(10)
368
+ .optional(),
369
+ temperature: z.string().min(1).max(80).optional(),
370
+ uses: z
371
+ .array(
372
+ z.strictObject({
373
+ id: itemId(),
374
+ portion: z.string().max(80).optional(),
375
+ source: z.discriminatedUnion('kind', [
376
+ z.strictObject({ ingredientId: itemId(), kind: z.literal('ingredient') }),
377
+ z.strictObject({ kind: z.literal('output'), outputId: itemId() }),
378
+ ]),
379
+ })
380
+ )
381
+ .max(30)
382
+ .default([]),
383
+ })
384
+ )
385
+ .min(1)
386
+ .max(60),
387
+ title: title(),
388
+ yield: z.string().max(160).optional(),
389
+ }).superRefine((recipe, context) => {
390
+ // Every edge points at an earlier step, so the graph is acyclic.
391
+ const ingredients = new Set(recipe.ingredients.map(ingredient => ingredient.id))
392
+ const steps = new Set<string>()
393
+ const outputs = new Set<string>()
394
+ for (const step of recipe.steps) {
395
+ const valid =
396
+ !steps.has(step.id) &&
397
+ (step.after ?? []).every(id => steps.has(id)) &&
398
+ step.uses.every(use =>
399
+ use.source.kind === 'ingredient'
400
+ ? ingredients.has(use.source.ingredientId)
401
+ : outputs.has(use.source.outputId)
402
+ )
403
+ if (!valid) {
404
+ context.addIssue({
405
+ code: 'custom',
406
+ message: `Step ${step.id} needs a unique ID and can only use ingredients and earlier steps.`,
407
+ })
408
+ }
409
+ steps.add(step.id)
410
+ for (const output of step.outputs ?? []) {
411
+ if (outputs.has(output.id)) {
412
+ context.addIssue({ code: 'custom', message: 'Output IDs must be unique.' })
413
+ }
414
+ outputs.add(output.id)
415
+ }
416
+ }
417
+ }),
418
+ // Each step_<id> holds whether the step is done and when its timer ends.
419
+ storeSchema: entries(
420
+ entryPrefixes.recipe,
421
+ z.strictObject({ done: z.boolean(), endsAt: z.number().nullable() }),
422
+ {
423
+ cooking: z.boolean().default(false),
424
+ servings: z.number().int().min(1).max(100).default(1),
425
+ }
426
+ ),
427
+ },
428
+ reminder: {
429
+ description:
430
+ 'Complete, reopen, and edit an in-app reminder. Does not schedule notifications.',
431
+ exportName: 'Reminder',
432
+ props: featureProps({
433
+ dueAt: z.iso.datetime({ offset: true }).nullable().default(null),
434
+ recurrence: z.enum(['none', 'daily', 'weekly']).default('none'),
435
+ timeZone: timeZone().optional(),
436
+ title: z.string().min(1).max(500),
437
+ }),
438
+ storeSchema: store({
439
+ completedAt: z.number().nullable().default(null),
440
+ dueAt: replacement(z.iso.datetime({ offset: true }).nullable().default(null)),
441
+ title: replacement(z.string().max(500).default('')),
442
+ }),
443
+ },
444
+ rotation: {
445
+ description:
446
+ 'Take turns through a fixed group in order and pass the turn on when done.',
447
+ exportName: 'Rotation',
448
+ props: featureProps({
449
+ people: identifiedList({ label: z.string().min(1).max(80) }, 20, 2),
450
+ task: z.string().min(1).max(160),
451
+ title: title('Whose turn'),
452
+ }),
453
+ // The person whose turn it is; null means the first person.
454
+ storeSchema: store({
455
+ completed: z.number().int().min(0).default(0),
456
+ turn: itemId().nullable().default(null),
457
+ }),
458
+ },
459
+ scoreboard: {
460
+ description:
461
+ 'Keep score for a few players with a fixed step. Not a distributed counter or a league.',
462
+ exportName: 'Scoreboard',
463
+ props: featureProps({
464
+ players: identifiedList({ label: z.string().min(1).max(80) }, 12, 2),
465
+ step: z.number().int().positive().max(1000).default(1),
466
+ title: title('Scores'),
467
+ }),
468
+ storeSchema: entries(entryPrefixes.scoreboard, z.number().int(), {}),
469
+ },
470
+ shoppingList: {
471
+ description:
472
+ 'Check items off a shopping list with optional prices and a running cart total. No ordering.',
473
+ exportName: 'ShoppingList',
474
+ props: featureProps({
475
+ currency: currency(),
476
+ items: identifiedList(
477
+ {
478
+ label: z.string().min(1).max(160),
479
+ price: z.number().min(0).max(1e9).optional(),
480
+ quantity: z.number().int().min(1).max(999).default(1),
481
+ },
482
+ 100
483
+ ),
484
+ title: title('Shopping list'),
485
+ }),
486
+ storeSchema: entries(entryPrefixes.shoppingList, z.boolean(), {}),
487
+ },
488
+ taskBoard: {
489
+ description:
490
+ 'Move tasks between To do, Doing, and Done. No assignees, dates, or sync.',
491
+ exportName: 'TaskBoard',
492
+ props: featureProps({
493
+ tasks: identifiedList({ label: z.string().min(1).max(500) }, 50),
494
+ title: title('Tasks'),
495
+ }),
496
+ storeSchema: entries(entryPrefixes.taskBoard, z.enum(['todo', 'doing', 'done']), {}),
497
+ },
498
+ timeZone: {
499
+ description:
500
+ 'Compare local times in named time zones, live or at an explicit instant.',
501
+ exportName: 'TimeZone',
502
+ props: featureProps({
503
+ at: z.iso.datetime({ offset: true }).nullable().default(null),
504
+ title: title('World clock'),
505
+ zones: z.array(timeZone()).min(2).max(6),
506
+ }),
507
+ storeSchema: store({
508
+ at: replacement(z.iso.datetime({ offset: true }).nullable().default(null)),
509
+ }),
510
+ },
511
+ timer: {
512
+ description:
513
+ 'Countdown, focus, break, or stopwatch. Start, pause, resume, reset; no background alarm.',
514
+ exportName: 'Timer',
515
+ props: featureProps({
516
+ durationSeconds: z.number().int().min(1).max(604_800).default(300),
517
+ mode: z.enum(['countdown', 'focus', 'break', 'stopwatch']).default('countdown'),
518
+ title: title('Timer'),
519
+ }),
520
+ storeSchema: store({
521
+ elapsedSeconds: z.number().min(0).default(0),
522
+ startedAt: z.number().nullable().default(null),
523
+ }),
524
+ },
525
+ trip: {
526
+ description: 'Edit and retain trip details. No bookings or itinerary retrieval.',
527
+ exportName: 'Trip',
528
+ props: featureProps({
529
+ destination: z.string().min(1).max(160),
530
+ endDate: z.iso.date().nullable().default(null),
531
+ origin: z.string().min(1).max(160),
532
+ startDate: z.iso.date().nullable().default(null),
533
+ title: title('Trip'),
534
+ transport: z.enum(['car', 'train', 'plane', 'walk', 'other']).default('other'),
535
+ }).refine(
536
+ value => !value.startDate || !value.endDate || value.endDate >= value.startDate,
537
+ {
538
+ message: 'The trip cannot end before it starts.',
539
+ path: ['endDate'],
540
+ }
541
+ ),
542
+ storeSchema: store({
543
+ destination: replacement(z.string().max(160).default('')),
544
+ endDate: replacement(z.iso.date().nullable().default(null)),
545
+ origin: replacement(z.string().max(160).default('')),
546
+ startDate: replacement(z.iso.date().nullable().default(null)),
547
+ }).refine(
548
+ value =>
549
+ !value.startDate.value ||
550
+ !value.endDate.value ||
551
+ value.endDate.value >= value.startDate.value,
552
+ 'The trip cannot end before it starts.'
553
+ ),
554
+ },
555
+ unitConverter: {
556
+ description:
557
+ 'Convert compatible length, mass, or temperature units deterministically.',
558
+ exportName: 'UnitConverter',
559
+ props: featureProps({
560
+ from: unit(),
561
+ title: title('Convert'),
562
+ to: unit(),
563
+ value: z.number(),
564
+ }).refine(
565
+ ({ from, to }) => unitDefinitions[from].dimension === unitDefinitions[to].dimension,
566
+ {
567
+ message: 'Source and destination units must measure the same dimension.',
568
+ path: ['to'],
569
+ }
570
+ ),
571
+ storeSchema: store({
572
+ from: replacement(unit().default('km')),
573
+ to: replacement(unit().default('mi')),
574
+ value: z.number().default(0),
575
+ }).refine(
576
+ ({ from, to }) =>
577
+ unitDefinitions[from.value].dimension === unitDefinitions[to.value].dimension,
578
+ 'Incompatible units.'
579
+ ),
580
+ },
581
+ }
582
+
583
+ export type KowalskiComponent = keyof typeof kowalskiCatalog
584
+ export const kowalskiComponentSchema = z.enum([
585
+ 'checklist',
586
+ 'timer',
587
+ 'habit',
588
+ 'goal',
589
+ 'poll',
590
+ 'event',
591
+ 'reminder',
592
+ 'trip',
593
+ 'countdown',
594
+ 'timeZone',
595
+ 'colorPalette',
596
+ 'billSplit',
597
+ 'expense',
598
+ 'unitConverter',
599
+ 'calculator',
600
+ 'randomPicker',
601
+ 'contact',
602
+ 'bookmark',
603
+ 'note',
604
+ 'budget',
605
+ 'scoreboard',
606
+ 'taskBoard',
607
+ 'recipe',
608
+ 'rotation',
609
+ 'shoppingList',
610
+ 'rating',
611
+ 'ledger',
612
+ ])
613
+ export type KowalskiInput<K extends KowalskiComponent> = z.input<
614
+ (typeof kowalskiCatalog)[K]['props']
615
+ >
616
+ export type KowalskiProps<K extends KowalskiComponent> = z.output<
617
+ (typeof kowalskiCatalog)[K]['props']
618
+ >
619
+ export type KowalskiState<K extends KowalskiComponent> = z.output<
620
+ (typeof kowalskiCatalog)[K]['storeSchema']
621
+ >
622
+ export type PickerDomain = NonNullable<KowalskiState<'randomPicker'>['result']>['domain']
623
+ export type Weekday = (typeof weekdayNames)[number]
624
+
625
+ export const pollVoterSchema = z.object({
626
+ configuration: z.string().default(''),
627
+ voter: z.string().min(1),
628
+ })
629
+
630
+ export const webAddressOptions = {
631
+ max_allowed_length: 2048,
632
+ protocols: ['http', 'https'],
633
+ require_host: true,
634
+ require_protocol: true,
635
+ require_tld: false,
636
+ require_valid_protocol: true,
637
+ }
638
+
639
+ /** SI relationships; temperature offsets are applied before scaling. */
640
+ export const unitDefinitions = {
641
+ c: { dimension: 'temperature', factor: 1, offset: 0 },
642
+ f: { dimension: 'temperature', factor: 5 / 9, offset: -32 },
643
+ ft: { dimension: 'length', factor: 0.3048, offset: 0 },
644
+ g: { dimension: 'mass', factor: 0.001, offset: 0 },
645
+ k: { dimension: 'temperature', factor: 1, offset: -273.15 },
646
+ kg: { dimension: 'mass', factor: 1, offset: 0 },
647
+ km: { dimension: 'length', factor: 1000, offset: 0 },
648
+ lb: { dimension: 'mass', factor: 0.45359237, offset: 0 },
649
+ m: { dimension: 'length', factor: 1, offset: 0 },
650
+ mi: { dimension: 'length', factor: 1609.344, offset: 0 },
651
+ }
652
+
653
+ function featureProps<Shape extends z.ZodRawShape>(shape: Shape) {
654
+ return z.strictObject({
655
+ id: kowalskiFeatureId,
656
+ revision: z.number().int().min(0).default(0),
657
+ scope: kowalskiScope,
658
+ ...shape,
659
+ })
660
+ }
661
+
662
+ function currency() {
663
+ return z
664
+ .string()
665
+ .regex(/^[A-Z]{3}$/)
666
+ .default('USD')
667
+ }
668
+
669
+ /**
670
+ * Per-item state as top-level `<prefix><id>` fields, which Quantum patches independently.
671
+ * The template-literal record types them by prefix, so they never collide with the named
672
+ * fields; any other key is rejected.
673
+ */
674
+ function entries<
675
+ Prefix extends string,
676
+ Value extends z.ZodType,
677
+ Shape extends z.ZodRawShape,
678
+ >(prefix: Prefix, value: Value, shape: Shape) {
679
+ const named = store(shape)
680
+ const keys = new Set(Object.keys(named.shape))
681
+ return z
682
+ .intersection(named.loose(), z.looseRecord(z.templateLiteral([prefix, z.string()]), value))
683
+ .refine(
684
+ state => Object.keys(state).every(key => keys.has(key) || key.startsWith(prefix)),
685
+ `Item fields must start with ${prefix}.`
686
+ )
687
+ }
688
+
689
+ /** Items with required stable ids, which key their saved state. */
690
+ function identifiedList<Shape extends z.ZodRawShape>(shape: Shape, max: number, min = 1) {
691
+ return z
692
+ .array(z.strictObject(shape).extend({ id: itemId() }))
693
+ .min(min)
694
+ .max(max)
695
+ .refine(uniqueIds, 'IDs must be unique.')
696
+ }
697
+
698
+ /** Free-form ids; they key Quantum state, so __proto__ is out. */
699
+ function itemId() {
700
+ return z
701
+ .string()
702
+ .min(1)
703
+ .max(80)
704
+ .refine(id => id !== '__proto__')
705
+ }
706
+
707
+ /**
708
+ * The choices a pick was drawn from. A plain union of strict variants (anyOf in JSON
709
+ * Schema) stays representable in the generated Quantum store source; oneOf does not.
710
+ */
711
+ function pickerDomain() {
712
+ return z.union([
713
+ z.strictObject({ mode: z.literal('coin') }),
714
+ z.strictObject({ mode: z.literal('dice') }),
715
+ z.strictObject({
716
+ maximum: z.number().int(),
717
+ minimum: z.number().int(),
718
+ mode: z.literal('range'),
719
+ }),
720
+ z.strictObject({
721
+ mode: z.literal('list'),
722
+ options: z.array(z.string().max(160)).max(100),
723
+ }),
724
+ ])
725
+ }
726
+
727
+ function store<Shape extends z.ZodRawShape>(shape: Shape) {
728
+ return z.object({
729
+ configuration: z.record(z.string(), z.unknown()).nullable().default(null),
730
+ configurationRevision: z.number().int().min(0).default(0),
731
+ ...shape,
732
+ })
733
+ }
734
+
735
+ /** A feature heading: never empty. */
736
+ function title(): z.ZodString
737
+ function title(fallback: string): z.ZodDefault<z.ZodString>
738
+ function title(fallback?: string) {
739
+ const schema = z.string().min(1).max(160)
740
+ return fallback === undefined ? schema : schema.default(fallback)
741
+ }
742
+
743
+ function uniqueIds(items: ReadonlyArray<object>) {
744
+ const ids = items.map(item => ('id' in item ? item.id : undefined))
745
+ return new Set(ids).size === ids.length
746
+ }
747
+
748
+ function unit() {
749
+ return z.enum(['m', 'km', 'mi', 'ft', 'kg', 'g', 'lb', 'c', 'f', 'k'])
750
+ }
751
+
752
+ function timeZone() {
753
+ return z
754
+ .string()
755
+ .max(80)
756
+ .refine(value => {
757
+ try {
758
+ new Intl.DateTimeFormat('en', { timeZone: value }).format(0)
759
+ return true
760
+ } catch {
761
+ return false
762
+ }
763
+ }, 'Use a valid IANA time zone.')
764
+ }
765
+
766
+ /** Scheduled days of the week, by name. */
767
+ function weekdays() {
768
+ return z
769
+ .array(z.enum(weekdayNames))
770
+ .max(7)
771
+ .default([...weekdayNames])
772
+ }
773
+
774
+ function webAddress() {
775
+ return z
776
+ .string()
777
+ .max(2048)
778
+ .refine(
779
+ value => isURL(value, webAddressOptions),
780
+ 'Use a valid HTTP or HTTPS address.'
781
+ )
782
+ }
783
+
784
+ /** Catalog fields are whole-value replacements, not collaborative text insertions. */
785
+ function replacement<Schema extends z.ZodType>(schema: Schema) {
786
+ return z.object({ value: schema }).default(() => ({ value: schema.parse(undefined) }))
787
+ }