@flickfyi/flkr 0.0.140 → 0.0.146

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 +502 -95
  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 +9 -9
  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,514 @@
1
+ // @vitest-environment happy-dom
2
+ import {
3
+ act,
4
+ cleanup,
5
+ fireEvent,
6
+ render,
7
+ renderHook,
8
+ screen,
9
+ waitFor,
10
+ } from '@testing-library/react'
11
+ import { Activity, createElement } from 'react'
12
+ import { afterEach, describe, expect, it, vi } from 'vitest'
13
+ import { z } from 'zod/v4'
14
+
15
+ import { kowalskiCatalog } from '~/kowalski/catalog'
16
+ import { useConfiguredFeature } from '~/kowalski/use-configured-feature'
17
+ import { useFeatureStore } from '~/kowalski/use-feature-store'
18
+
19
+ afterEach(() => {
20
+ cleanup()
21
+ vi.unstubAllGlobals()
22
+ })
23
+
24
+ describe('Kowalski Quantum persistence', () => {
25
+ it('recovers an initial open failure by manual retry without remounting or reopening on rerender', async () => {
26
+ const native = nativeStore({ configuration: null, progress: 2 })
27
+ const subscribe = vi.spyOn(native.store, 'subscribe')
28
+ const openStore = vi
29
+ .fn<() => Promise<typeof native.store>>()
30
+ .mockRejectedValueOnce(new Error('Open failed'))
31
+ .mockResolvedValue(native.store)
32
+ vi.stubGlobal('Quantum', { openStore })
33
+ const hook = renderHook(() =>
34
+ useFeatureStore({
35
+ initialState: { configuration: null, progress: 0 },
36
+ name: 'RetryOpen',
37
+ schema: kowalskiCatalog.goal.storeSchema,
38
+ })
39
+ )
40
+ await waitFor(() =>
41
+ expect(hook.result.current.error).toBe(
42
+ 'Could not load this feature. Please try again.'
43
+ )
44
+ )
45
+ expect(hook.result.current.ready).toBe(false)
46
+ expect(hook.result.current.retry).toBeTypeOf('function')
47
+ hook.rerender()
48
+ expect(openStore).toHaveBeenCalledOnce()
49
+ act(() => hook.result.current.retry?.())
50
+ await waitFor(() => expect(hook.result.current.ready).toBe(true))
51
+ expect(hook.result.current.value.progress).toBe(2)
52
+ expect(hook.result.current.error).toBeUndefined()
53
+ expect(hook.result.current.retry).toBeUndefined()
54
+ act(() => hook.result.current.set({ progress: 3 }))
55
+ await waitFor(() => expect(hook.result.current.value.progress).toBe(3))
56
+ hook.rerender()
57
+ expect(openStore).toHaveBeenCalledTimes(2)
58
+ expect(subscribe).toHaveBeenCalledOnce()
59
+ })
60
+
61
+ it('preserves its last good value after a malformed snapshot and recovers by retrying', async () => {
62
+ const native = nativeStore({ configuration: null, progress: 2 })
63
+ const subscribe = vi.spyOn(native.store, 'subscribe')
64
+ const openStore = vi.fn(async () => native.store)
65
+ vi.stubGlobal('Quantum', { openStore })
66
+ const hook = renderHook(() =>
67
+ useFeatureStore({
68
+ initialState: { configuration: null, progress: 0 },
69
+ name: 'RetrySnapshot',
70
+ schema: kowalskiCatalog.goal.storeSchema,
71
+ })
72
+ )
73
+ await waitFor(() => expect(hook.result.current.ready).toBe(true))
74
+ await act(async () =>
75
+ subscribe.mock.calls[0]?.[0]({
76
+ rawValue: { configuration: null, progress: 'invalid' },
77
+ version: 0,
78
+ })
79
+ )
80
+ await waitFor(() =>
81
+ expect(hook.result.current.error).toBe(
82
+ 'Could not load this feature. Please try again.'
83
+ )
84
+ )
85
+ expect(hook.result.current.value.progress).toBe(2)
86
+ expect(hook.result.current.ready).toBe(false)
87
+ act(() => expect(hook.result.current.set({ progress: 3 })).toBe(false))
88
+ hook.rerender()
89
+ expect(subscribe).toHaveBeenCalledOnce()
90
+ act(() => hook.result.current.retry?.())
91
+ await waitFor(() => expect(hook.result.current.ready).toBe(true))
92
+ expect(hook.result.current.value.progress).toBe(2)
93
+ expect(hook.result.current.error).toBeUndefined()
94
+ expect(hook.result.current.retry).toBeUndefined()
95
+ expect(openStore).toHaveBeenCalledTimes(2)
96
+ expect(subscribe).toHaveBeenCalledTimes(2)
97
+ })
98
+
99
+ it('retries a rejected configuration revision explicitly without retrying in a loop', async () => {
100
+ const schema = kowalskiCatalog.note.storeSchema
101
+ const seed = schema.parse({ body: { value: 'Seed' }, title: { value: 'Before' } })
102
+ const native = nativeStore({ ...seed, configuration: seed, configurationRevision: 1 })
103
+ const save = native.store.setAsync.bind(native.store)
104
+ native.store.setAsync = vi.fn(save).mockRejectedValueOnce(new Error('SQLite failed'))
105
+ vi.stubGlobal('Quantum', { openStore: async () => native.store })
106
+ const hook = renderHook(() =>
107
+ useConfiguredFeature({
108
+ name: 'NoteRetry',
109
+ revision: 2,
110
+ schema,
111
+ scope: 'private',
112
+ seed: { ...seed, title: { value: 'After' } },
113
+ })
114
+ )
115
+ await waitFor(() => expect(hook.result.current.error).toContain('Could not save'))
116
+ expect(native.value().title.value).toBe('Before')
117
+ hook.rerender()
118
+ expect(native.store.setAsync).toHaveBeenCalledOnce()
119
+ expect(hook.result.current.retry).toBeTypeOf('function')
120
+ act(() => hook.result.current.retry?.())
121
+ await waitFor(() => expect(native.value().configurationRevision).toBe(2))
122
+ expect(native.value().title.value).toBe('After')
123
+ expect(native.store.setAsync).toHaveBeenCalledTimes(2)
124
+ await waitFor(() => expect(hook.result.current.error).toBeUndefined())
125
+ expect(hook.result.current.retry).toBeUndefined()
126
+ })
127
+
128
+ it('stores authored configuration as a structured value', async () => {
129
+ const schema = kowalskiCatalog.note.storeSchema
130
+ const seed = schema.parse({ body: { value: 'Writing' }, title: { value: 'Title' } })
131
+ vi.stubGlobal('Quantum', {
132
+ openStore: async ({ initialState }: { initialState: typeof seed }) =>
133
+ nativeStore(initialState).store,
134
+ })
135
+ const hook = renderHook(() =>
136
+ useConfiguredFeature({
137
+ name: 'Structured',
138
+ revision: 1,
139
+ schema,
140
+ scope: 'private',
141
+ seed,
142
+ })
143
+ )
144
+ await waitFor(() => expect(hook.result.current.ready).toBe(true))
145
+ expect(hook.result.current.value.configuration).toEqual(seed)
146
+ })
147
+ it('shows rejection rollback after an Activity resubscribes through a new native proxy', async () => {
148
+ const native = nativeStore({ configuration: null, progress: 2 })
149
+ let opens = 0
150
+ let rejectWrite: ((error: Error) => void) | undefined
151
+ vi.stubGlobal('Quantum', {
152
+ async openStore() {
153
+ opens++
154
+ return {
155
+ ...native.store,
156
+ setAsync: () =>
157
+ new Promise<{ rawValue: unknown; version: number }>((_resolve, reject) => {
158
+ rejectWrite = reject
159
+ }),
160
+ }
161
+ },
162
+ })
163
+ function Probe() {
164
+ const store = useFeatureStore({
165
+ initialState: native.value(),
166
+ name: 'ActivityGoal',
167
+ schema: kowalskiCatalog.goal.storeSchema,
168
+ })
169
+ return createElement(
170
+ 'div',
171
+ {},
172
+ createElement('span', {}, String(store.value.progress)),
173
+ createElement('span', {}, store.error),
174
+ createElement(
175
+ 'button',
176
+ { disabled: !store.ready, onClick: () => store.set({ progress: 3 }) },
177
+ 'Add'
178
+ )
179
+ )
180
+ }
181
+ const tree = (mode: 'visible' | 'hidden') =>
182
+ createElement(Activity, { mode }, createElement(Probe))
183
+ const view = render(tree('visible'))
184
+ await waitFor(() =>
185
+ expect(screen.getByRole('button').hasAttribute('disabled')).toBe(false)
186
+ )
187
+ fireEvent.click(screen.getByRole('button'))
188
+ expect(screen.getByText('3')).toBeTruthy()
189
+ await act(async () => view.rerender(tree('hidden')))
190
+ await act(async () => view.rerender(tree('visible')))
191
+ await waitFor(() => expect(opens).toBe(2))
192
+ await act(async () => rejectWrite?.(new Error('Old proxy write rejected')))
193
+ await waitFor(() =>
194
+ expect(
195
+ screen.getByText('Could not save this change. Please try again.')
196
+ ).toBeTruthy()
197
+ )
198
+ expect(screen.getByText('2')).toBeTruthy()
199
+ })
200
+ it('retries a configuration independently after rebinding to another store', async () => {
201
+ const schema = kowalskiCatalog.note.storeSchema
202
+ const seed = schema.parse({ body: { value: 'Seed' }, title: { value: 'Before' } })
203
+ const initial = { ...seed, configuration: seed, configurationRevision: 1 }
204
+ const a = nativeStore(initial)
205
+ const b = nativeStore(initial)
206
+ a.store.setAsync = vi.fn().mockRejectedValue(new Error('Rejected A'))
207
+ vi.stubGlobal('Quantum', {
208
+ openStore: async ({ name }: { name: string }) => (name === 'A' ? a.store : b.store),
209
+ })
210
+ const hook = renderHook(
211
+ ({ name }) =>
212
+ useConfiguredFeature({
213
+ name,
214
+ revision: 2,
215
+ schema,
216
+ scope: 'private',
217
+ seed: { ...seed, title: { value: 'After' } },
218
+ }),
219
+ { initialProps: { name: 'A' } }
220
+ )
221
+ await waitFor(() => expect(hook.result.current.error).toContain('Could not save'))
222
+ hook.rerender({ name: 'B' })
223
+ await waitFor(() => expect(b.value().title.value).toBe('After'))
224
+ expect(a.store.setAsync).toHaveBeenCalledOnce()
225
+ })
226
+ it.each([false, true])(
227
+ 'disables unconfirmable or read-only writes (read-only=%s)',
228
+ async readOnly => {
229
+ const native = nativeStore({ configuration: null, progress: 2 })
230
+ const store = {
231
+ ...native.store,
232
+ canWrite: !readOnly,
233
+ setAsync: readOnly ? native.store.setAsync : undefined,
234
+ }
235
+ vi.stubGlobal('Quantum', { openStore: async () => store })
236
+ const hook = renderHook(() =>
237
+ useFeatureStore({
238
+ initialState: native.value(),
239
+ name: 'ReadOnly',
240
+ schema: kowalskiCatalog.goal.storeSchema,
241
+ })
242
+ )
243
+ await waitFor(() =>
244
+ expect(hook.result.current.error).toContain(
245
+ readOnly ? 'read-only' : 'Update Flick'
246
+ )
247
+ )
248
+ expect(hook.result.current.ready).toBe(false)
249
+ act(() => expect(hook.result.current.set({ progress: 3 })).toBe(false))
250
+ expect(native.value().progress).toBe(2)
251
+ }
252
+ )
253
+ it('retains rapid taps while native write acknowledgments arrive later', async () => {
254
+ let persisted = { configuration: null, configurationRevision: 0, progress: 2 }
255
+ let notify: ((raw: { rawValue: unknown; version: number }) => void) | undefined
256
+ const pending: Array<{
257
+ patch: Partial<typeof persisted>
258
+ resolve: (raw: { rawValue: unknown; version: number }) => void
259
+ }> = []
260
+ vi.stubGlobal('Quantum', {
261
+ openStore: async () => ({
262
+ set() {},
263
+ setAsync: (patch: Partial<typeof persisted>) =>
264
+ new Promise<{ rawValue: unknown; version: number }>(resolve => {
265
+ pending.push({ patch, resolve })
266
+ }),
267
+ subscribe(listener: typeof notify) {
268
+ notify = listener
269
+ listener?.({ rawValue: persisted, version: 0 })
270
+ return () => {}
271
+ },
272
+ }),
273
+ })
274
+ const hook = renderHook(() =>
275
+ useFeatureStore({
276
+ initialState: persisted,
277
+ name: 'DeferredGoal',
278
+ schema: kowalskiCatalog.goal.storeSchema,
279
+ })
280
+ )
281
+ await waitFor(() => expect(hook.result.current.ready).toBe(true))
282
+ act(() => {
283
+ for (let index = 0; index < 3; index++) {
284
+ hook.result.current.set(current => ({ progress: current.progress + 1 }))
285
+ }
286
+ })
287
+ await act(async () => {
288
+ const write = pending.shift()
289
+ persisted = { ...persisted, ...write?.patch }
290
+ const raw = { rawValue: persisted, version: 0 }
291
+ notify?.(raw)
292
+ write?.resolve(raw)
293
+ })
294
+ expect(hook.result.current.value.progress).toBe(5)
295
+ act(() => hook.result.current.set(current => ({ progress: current.progress + 1 })))
296
+ for (let index = 0; index < 5 && pending.length; index++) {
297
+ await act(async () => {
298
+ const write = pending.shift()
299
+ persisted = { ...persisted, ...write?.patch }
300
+ const raw = { rawValue: persisted, version: 0 }
301
+ notify?.(raw)
302
+ write?.resolve(raw)
303
+ })
304
+ }
305
+ expect(persisted.progress).toBe(6)
306
+ expect(hook.result.current.value.progress).toBe(6)
307
+ })
308
+ it('rolls back a rejected asynchronous save and exposes the failure', async () => {
309
+ const native = nativeStore({ configuration: null, progress: 2 })
310
+ native.store.setAsync = vi.fn().mockRejectedValue(new Error('SQLite failed'))
311
+ vi.stubGlobal('Quantum', { openStore: async () => native.store })
312
+ const hook = renderHook(() =>
313
+ useFeatureStore({
314
+ initialState: native.value(),
315
+ name: 'Rejected',
316
+ schema: kowalskiCatalog.goal.storeSchema,
317
+ })
318
+ )
319
+ await waitFor(() => expect(hook.result.current.ready).toBe(true))
320
+ act(() => hook.result.current.set({ progress: 3 }))
321
+ expect(hook.result.current.value.progress).toBe(3)
322
+ await waitFor(() => expect(hook.result.current.error).toContain('Could not save'))
323
+ expect(hook.result.current.value.progress).toBe(2)
324
+ })
325
+ it('accepts a successful merged text value rather than waiting for an exact echo', async () => {
326
+ const schema = z.object({
327
+ body: z.string(),
328
+ configuration: z.null(),
329
+ title: z.string(),
330
+ })
331
+ const native = nativeStore({ body: 'Seed', configuration: null, title: 'Before' })
332
+ native.store.setAsync = async () => {
333
+ native.store.set({ body: 'Peer + mine' })
334
+ return { rawValue: native.value(), version: 0 }
335
+ }
336
+ vi.stubGlobal('Quantum', { openStore: async () => native.store })
337
+ const hook = renderHook(() =>
338
+ useFeatureStore({ initialState: native.value(), name: 'Merged', schema })
339
+ )
340
+ await waitFor(() => expect(hook.result.current.ready).toBe(true))
341
+ act(() => hook.result.current.set({ body: 'Mine' }))
342
+ await waitFor(() => expect(hook.result.current.value.body).toBe('Peer + mine'))
343
+ act(() => native.store.set({ body: 'Later peer edit' }))
344
+ await waitFor(() => expect(hook.result.current.value.body).toBe('Later peer edit'))
345
+ })
346
+ it('preserves a conflicting live Trip range without consuming the new revision', async () => {
347
+ const schema = kowalskiCatalog.trip.storeSchema
348
+ const seed = schema.parse({
349
+ endDate: { value: '2026-10-25' },
350
+ startDate: { value: '2026-10-20' },
351
+ })
352
+ const native = nativeStore({
353
+ ...seed,
354
+ configuration: seed,
355
+ configurationRevision: 1,
356
+ startDate: { value: '2026-10-24' },
357
+ })
358
+ vi.stubGlobal('Quantum', { openStore: async () => native.store })
359
+ const hook = renderHook(() =>
360
+ useConfiguredFeature({
361
+ name: 'Trip',
362
+ revision: 2,
363
+ schema,
364
+ scope: 'private',
365
+ seed: { ...seed, endDate: { value: '2026-10-22' } },
366
+ })
367
+ )
368
+ await waitFor(() => expect(hook.result.current.error).toContain('conflicts'))
369
+ expect(native.value()).toMatchObject({
370
+ configurationRevision: 1,
371
+ endDate: { value: '2026-10-25' },
372
+ startDate: { value: '2026-10-24' },
373
+ })
374
+ act(() => hook.result.current.set({ startDate: { value: '2026-10-21' } }))
375
+ await waitFor(() =>
376
+ expect(native.value()).toMatchObject({
377
+ configurationRevision: 2,
378
+ endDate: { value: '2026-10-22' },
379
+ startDate: { value: '2026-10-21' },
380
+ })
381
+ )
382
+ })
383
+ it('applies only changed configuration fields and rejects an older installed configuration', async () => {
384
+ const schema = kowalskiCatalog.note.storeSchema
385
+ const original = schema.parse({ body: { value: 'Seed' }, title: { value: 'Before' } })
386
+ const native = nativeStore({
387
+ ...original,
388
+ body: { value: 'My writing' },
389
+ configuration: original,
390
+ configurationRevision: 1,
391
+ title: { value: 'My title' },
392
+ })
393
+ vi.stubGlobal('Quantum', { openStore: async () => native.store })
394
+ const hook = renderHook(
395
+ ({ revision, title }) =>
396
+ useConfiguredFeature({
397
+ name: 'NoteOne',
398
+ revision,
399
+ schema,
400
+ scope: 'private',
401
+ seed: schema.parse({ body: { value: 'Seed' }, title: { value: title } }),
402
+ }),
403
+ { initialProps: { revision: 2, title: 'After' } }
404
+ )
405
+ await waitFor(() => expect(native.value().title.value).toBe('After'))
406
+ expect(native.value().body.value).toBe('My writing')
407
+ hook.rerender({ revision: 1, title: 'Before' })
408
+ await waitFor(() => expect(hook.result.current.ready).toBe(true))
409
+ expect(native.value().title.value).toBe('After')
410
+ expect(native.value().configurationRevision).toBe(2)
411
+ })
412
+ it('waits for saved data before allowing a mutation and retains untouched fields', async () => {
413
+ let resolveOpen:
414
+ | ((store: ReturnType<typeof nativeStore>['store']) => void)
415
+ | undefined
416
+ const opening = new Promise<ReturnType<typeof nativeStore>['store']>(resolve => {
417
+ resolveOpen = resolve
418
+ })
419
+ const native = nativeStore({ completed_sleepingBag: true, configuration: null })
420
+ vi.stubGlobal('Quantum', { openStore: () => opening })
421
+ const { result } = renderHook(() =>
422
+ useFeatureStore({
423
+ initialState: { configuration: null },
424
+ name: 'KowalskiChecklist',
425
+ schema: kowalskiCatalog.checklist.storeSchema,
426
+ })
427
+ )
428
+ expect(result.current.ready).toBe(false)
429
+ act(() => {
430
+ expect(result.current.set({ completed_tent: true })).toBe(false)
431
+ })
432
+ resolveOpen?.(native.store)
433
+ await waitFor(() => expect(result.current.ready).toBe(true))
434
+ expect(result.current.value.completed_sleepingBag).toBe(true)
435
+ act(() => result.current.set({ completed_tent: true }))
436
+ await waitFor(() =>
437
+ expect(native.value()).toEqual({
438
+ completed_sleepingBag: true,
439
+ completed_tent: true,
440
+ configuration: null,
441
+ })
442
+ )
443
+ })
444
+
445
+ it('reads its own rapid writes without losing increments before subscription parsing completes', async () => {
446
+ const native = nativeStore({ configuration: null, progress: 2 })
447
+ vi.stubGlobal('Quantum', { openStore: async () => native.store })
448
+ const { result } = renderHook(() =>
449
+ useFeatureStore({
450
+ initialState: { configuration: null, progress: 0 },
451
+ name: 'KowalskiGoal',
452
+ schema: kowalskiCatalog.goal.storeSchema,
453
+ })
454
+ )
455
+ await waitFor(() => expect(result.current.ready).toBe(true))
456
+ act(() => {
457
+ result.current.set(current => ({ progress: current.progress + 1 }))
458
+ result.current.set(current => ({ progress: current.progress + 1 }))
459
+ result.current.set(current => ({ progress: current.progress + 1 }))
460
+ })
461
+ expect(native.value().progress).toBe(5)
462
+ await waitFor(() => expect(result.current.value.progress).toBe(5))
463
+ })
464
+
465
+ it('reopens the same store without resetting it from new initial values', async () => {
466
+ const native = nativeStore({ configuration: null, progress: 7 })
467
+ vi.stubGlobal('Quantum', { openStore: async () => native.store })
468
+ const first = renderHook(() =>
469
+ useFeatureStore({
470
+ initialState: { configuration: null, progress: 0 },
471
+ name: 'KowalskiGoal',
472
+ schema: kowalskiCatalog.goal.storeSchema,
473
+ })
474
+ )
475
+ await waitFor(() => expect(first.result.current.ready).toBe(true))
476
+ first.unmount()
477
+ const second = renderHook(() =>
478
+ useFeatureStore({
479
+ initialState: { configuration: null, progress: 99 },
480
+ name: 'KowalskiGoal',
481
+ schema: kowalskiCatalog.goal.storeSchema,
482
+ })
483
+ )
484
+ await waitFor(() => expect(second.result.current.ready).toBe(true))
485
+ expect(second.result.current.value.progress).toBe(7)
486
+ })
487
+ })
488
+
489
+ function nativeStore<T extends Record<string, unknown>>(initial: T) {
490
+ let value = initial
491
+ const listeners = new Set<(raw: { rawValue: unknown; version: number }) => void>()
492
+ return {
493
+ store: {
494
+ set(patch: Partial<T>) {
495
+ value = { ...value, ...patch }
496
+ for (const listener of listeners) {
497
+ listener({ rawValue: value, version: 0 })
498
+ }
499
+ },
500
+ async setAsync(patch: Partial<T>) {
501
+ this.set(patch)
502
+ return { rawValue: value, version: 0 }
503
+ },
504
+ subscribe(listener: (raw: { rawValue: unknown; version: number }) => void) {
505
+ listeners.add(listener)
506
+ listener({ rawValue: value, version: 0 })
507
+ return () => {
508
+ listeners.delete(listener)
509
+ }
510
+ },
511
+ },
512
+ value: () => value,
513
+ }
514
+ }
@@ -25,7 +25,7 @@ const previews = Object.entries(config.environments ?? {})
25
25
  const filename = build.lib.fileName('iife', basename(build.lib.entry, '.tsx'))
26
26
  return { entry: build.lib.entry, filename, output: resolve(build.outDir, filename) }
27
27
  })
28
- const canonicalExamples = globSync('examples/parrott/*/*.tsx', { cwd: packageRoot })
28
+ const canonicalExamples = globSync(['examples/parrott/*/*.tsx', 'examples/kowalski/*/*.tsx'], { cwd: packageRoot })
29
29
  .filter(entry => basename(dirname(entry)) === basename(entry, '.tsx'))
30
30
  .map(entry => resolve(packageRoot, entry))
31
31
 
@@ -5,7 +5,7 @@ import { act, cleanup, renderHook, waitFor } from '@testing-library/react'
5
5
  import { afterEach, describe, expect, it, vi } from 'vitest'
6
6
  import { z } from 'zod'
7
7
 
8
- import { createQuantumStoreAdapter, usePublicStore } from '../src/quantum/use-store'
8
+ import { createQuantumStoreAdapter, usePublicStore } from '~/quantum/use-store'
9
9
 
10
10
  afterEach(() => {
11
11
  cleanup()
@@ -120,6 +120,58 @@ function isTestState(value: unknown): value is TestState {
120
120
  }
121
121
 
122
122
  describe('createQuantumStoreAdapter', () => {
123
+ it('ignores a stale parse failure after accepting a newer snapshot', async () => {
124
+ const native = createTestStore()
125
+ const pending = createDeferred<TestState>()
126
+ const onLoadError = vi.fn()
127
+ const adapter = createQuantumStoreAdapter(
128
+ async () => native.store,
129
+ { count: 0 },
130
+ raw =>
131
+ raw.rawValue === 'delayed failure' ? pending.promise : parseTestSnapshot(raw),
132
+ onLoadError
133
+ )
134
+ const unsubscribe = adapter.subscribe(vi.fn())
135
+ await waitFor(() => expect(native.store.subscribe).toHaveBeenCalledOnce())
136
+ native.store.subscribe.mock.calls[0]?.[0]({ rawValue: 'delayed failure', version: 0 })
137
+ native.emit({ count: 2 })
138
+ await Promise.resolve()
139
+ pending.reject(new Error('Stale malformed payload'))
140
+ await Promise.allSettled([pending.promise])
141
+ await Promise.resolve()
142
+ expect(adapter.getSnapshot()).toEqual({ count: 2 })
143
+ expect(onLoadError).not.toHaveBeenCalled()
144
+ unsubscribe()
145
+ })
146
+
147
+ it('retries by replacing one subscription and ignores failures from the old generation', async () => {
148
+ const native = createTestStore()
149
+ const pending = createDeferred<TestState>()
150
+ const onLoadError = vi.fn()
151
+ const adapter = createQuantumStoreAdapter(
152
+ async () => native.store,
153
+ { count: 0 },
154
+ raw =>
155
+ raw.rawValue === 'delayed failure' ? pending.promise : parseTestSnapshot(raw),
156
+ onLoadError
157
+ )
158
+ const unsubscribe = adapter.subscribe(vi.fn())
159
+ await waitFor(() => expect(native.store.subscribe).toHaveBeenCalledOnce())
160
+ native.store.subscribe.mock.calls[0]?.[0]({ rawValue: 'delayed failure', version: 0 })
161
+ adapter.retry()
162
+ await waitFor(() => expect(native.store.subscribe).toHaveBeenCalledTimes(2))
163
+ expect(native.unsubscribe).toHaveBeenCalledOnce()
164
+ native.emit({ count: 3 })
165
+ await Promise.resolve()
166
+ pending.reject(new Error('Old generation'))
167
+ await Promise.allSettled([pending.promise])
168
+ await Promise.resolve()
169
+ expect(adapter.getSnapshot()).toEqual({ count: 3 })
170
+ expect(onLoadError).not.toHaveBeenCalled()
171
+ unsubscribe()
172
+ expect(native.unsubscribe).toHaveBeenCalledTimes(2)
173
+ })
174
+
123
175
  it('preserves an undefined snapshot until a legacy store hydrates', async () => {
124
176
  const open = createDeferred<ReturnType<typeof createTestStore>['store']>()
125
177
  const store = createTestStore()
@@ -21,7 +21,7 @@ it.each(['package.tsgo.json', 'tsgo.package.json'])(
21
21
  '%s keeps the UI layer after its Core dependency with each module owned once',
22
22
  file => {
23
23
  const { runtime } = JSON.parse(readFileSync(resolve(import.meta.dirname, '..', file), 'utf8'))
24
- expect(runtime.libraries.map((library: { name: string }) => library.name)).toEqual(['core', 'ui', 'lens'])
24
+ expect(runtime.libraries.map((library: { name: string }) => library.name)).toEqual(['core', 'ui', 'lens', 'kowalski'])
25
25
  expect(runtime.libraries[1]).toEqual({
26
26
  name: 'ui',
27
27
  dependencies: ['core'],
@@ -14,7 +14,8 @@
14
14
  "**/*.typecheck.*",
15
15
  "**/*.stories.tsx",
16
16
  "src/storybook",
17
- "src/themes/stories"
17
+ "src/themes/stories",
18
+ "src/kowalski/stories"
18
19
  ],
19
20
  "compilerOptions": {
20
21
  "paths": {