@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,469 @@
1
+ import { Flex, Text } from '@flickfyi/core'
2
+ import { Button, Input, Picker } from '@flickfyi/core/atoms'
3
+ import * as stylex from '@stylexjs/stylex'
4
+ import { sortBy } from 'lodash'
5
+ import { DateTime } from 'luxon'
6
+ import { useEffect, useRef, useState } from 'react'
7
+
8
+ import { space } from '~/themes/scale.stylex'
9
+ import { button, roles } from '~/themes/shared'
10
+
11
+ import type { KowalskiComponent } from './catalog'
12
+ import { format } from './format'
13
+ import { FeatureAction, layout } from './frame'
14
+
15
+ /** Stores an instant and edits calendar time in the supplied IANA timezone. */
16
+ export function FeatureDateTime(props: DateEditorProps & { timeZone: string }) {
17
+ return <DateEditor {...props} dateOnly={false} />
18
+ }
19
+
20
+ /** Date-only values remain calendar dates, without device timezone conversion. */
21
+ export function FeatureDate(props: DateEditorProps) {
22
+ return <DateEditor {...props} dateOnly timeZone="UTC" />
23
+ }
24
+
25
+ type DateEditorProps = {
26
+ actionLabel?: string
27
+ clearable?: boolean
28
+ compact?: boolean
29
+ component: KowalskiComponent
30
+ label: string
31
+ inline?: boolean
32
+ onChange: (value: string | null, onSaved?: () => void) => boolean | void
33
+ onEditingChange?: (editing: boolean) => void
34
+ ready: boolean
35
+ saving?: boolean
36
+ submitLabel?: string
37
+ value: string | null
38
+ }
39
+
40
+ type CalendarFields = {
41
+ day: number
42
+ hour: number
43
+ millisecond: number
44
+ minute: number
45
+ month: number
46
+ second: number
47
+ year: number
48
+ }
49
+
50
+ function DateEditor({
51
+ actionLabel,
52
+ clearable = false,
53
+ compact = false,
54
+ component,
55
+ dateOnly,
56
+ label,
57
+ inline = false,
58
+ onChange,
59
+ onEditingChange,
60
+ ready,
61
+ saving,
62
+ submitLabel,
63
+ timeZone,
64
+ value,
65
+ }: DateEditorProps & { dateOnly: boolean; timeZone: string }) {
66
+ const [editing, setEditing] = useState(false)
67
+ const [editorValue, setEditorValue] = useState(value)
68
+ useEffect(() => {
69
+ if (!inline) {
70
+ onEditingChange?.(editing)
71
+ return () => onEditingChange?.(false)
72
+ }
73
+ }, [editing, inline, onEditingChange])
74
+ const close = () => {
75
+ setEditing(false)
76
+ onEditingChange?.(false)
77
+ }
78
+ const instant = value ? Date.parse(dateOnly ? `${value}T12:00:00Z` : value) : undefined
79
+ const action = dateOnly ? 'date' : 'date & time'
80
+ if (inline && ready) {
81
+ return (
82
+ <CalendarEditor
83
+ clearable={clearable}
84
+ component={component}
85
+ dateOnly={dateOnly}
86
+ inline
87
+ label={label}
88
+ onCancel={close}
89
+ onChange={onChange}
90
+ onEditingChange={onEditingChange}
91
+ timeZone={timeZone}
92
+ value={value}
93
+ />
94
+ )
95
+ }
96
+ return (
97
+ <Flex {...stylex.props(dateStyles.section)}>
98
+ {!compact && <Text {...stylex.props(roles.label)}>{label}</Text>}
99
+ {!compact &&
100
+ !editing &&
101
+ (instant === undefined ? (
102
+ <Text {...stylex.props(roles.muted)}>No date set</Text>
103
+ ) : (
104
+ <Flex {...stylex.props(dateStyles.summary)}>
105
+ <Text {...stylex.props(roles.strong)}>
106
+ {formatCalendarDate(instant, timeZone)}
107
+ </Text>
108
+ {!dateOnly && (
109
+ <Text {...stylex.props(roles.muted)}>
110
+ {formatCalendarTime(instant, timeZone)}
111
+ </Text>
112
+ )}
113
+ </Flex>
114
+ ))}
115
+ {editing && ready ? (
116
+ <CalendarEditor
117
+ key={`${editorValue}:${timeZone}`}
118
+ clearable={clearable}
119
+ component={component}
120
+ dateOnly={dateOnly}
121
+ onCancel={close}
122
+ onChange={next => {
123
+ const result = saving === undefined ? onChange(next) : onChange(next, close)
124
+ if (result === undefined || (saving === undefined && result)) {
125
+ close()
126
+ }
127
+ }}
128
+ saving={saving}
129
+ submitLabel={submitLabel}
130
+ timeZone={timeZone}
131
+ value={editorValue}
132
+ />
133
+ ) : (
134
+ <FeatureAction
135
+ component={component}
136
+ disabled={!ready || saving}
137
+ icon="calendar"
138
+ onClick={() => {
139
+ setEditorValue(value)
140
+ setEditing(true)
141
+ onEditingChange?.(true)
142
+ }}
143
+ >
144
+ {actionLabel ?? `${value ? 'Change' : 'Choose'} ${action}`}
145
+ </FeatureAction>
146
+ )}
147
+ </Flex>
148
+ )
149
+ }
150
+
151
+ function CalendarEditor({
152
+ clearable,
153
+ component,
154
+ dateOnly,
155
+ inline = false,
156
+ label = 'Date & time',
157
+ onCancel,
158
+ onChange,
159
+ onEditingChange,
160
+ saving,
161
+ submitLabel,
162
+ timeZone,
163
+ value,
164
+ }: Omit<DateEditorProps, 'label' | 'ready'> & {
165
+ dateOnly: boolean
166
+ label?: string
167
+ onCancel: () => void
168
+ timeZone: string
169
+ }) {
170
+ const [originalValue] = useState(value)
171
+ const [original] = useState(() =>
172
+ value
173
+ ? DateTime.fromISO(dateOnly ? `${value}T12:00:00` : value, {
174
+ locale: 'en-US',
175
+ zone: timeZone,
176
+ })
177
+ : DateTime.fromMillis(Math.ceil((Date.now() + 3_600_000) / 3_600_000) * 3_600_000, {
178
+ locale: 'en-US',
179
+ zone: timeZone,
180
+ })
181
+ )
182
+ const timePattern = original.millisecond
183
+ ? 'h:mm:ss.SSS a'
184
+ : original.second
185
+ ? 'h:mm:ss a'
186
+ : 'h:mm a'
187
+ const [dateText, setDateText] = useState(original.toFormat('MM/dd/yyyy'))
188
+ const [timeText, setTimeText] = useState(original.toFormat(timePattern))
189
+ const [offset, setOffset] = useState(original.offset)
190
+ const [removed, setRemoved] = useState(inline && value === null)
191
+ const parsedDate = DateTime.fromFormat(dateText.trim(), 'M/d/yyyy', {
192
+ locale: 'en-US',
193
+ zone: 'UTC',
194
+ })
195
+ const parsedTime =
196
+ ['h:mm:ss.SSS a', 'h:mm:ss a', 'h:mm a']
197
+ .map(pattern =>
198
+ DateTime.fromFormat(timeText.trim().toUpperCase(), pattern, {
199
+ locale: 'en-US',
200
+ zone: 'UTC',
201
+ })
202
+ )
203
+ .find(candidate => candidate.isValid) ?? DateTime.invalid('Invalid time')
204
+ const fields =
205
+ parsedDate.isValid && (dateOnly || parsedTime.isValid)
206
+ ? {
207
+ ...calendarFields(parsedDate),
208
+ hour: dateOnly ? 12 : parsedTime.hour,
209
+ millisecond: dateOnly ? 0 : parsedTime.millisecond,
210
+ minute: dateOnly ? 0 : parsedTime.minute,
211
+ second: dateOnly ? 0 : parsedTime.second,
212
+ }
213
+ : undefined
214
+ const candidates = fields ? calendarCandidates(fields, timeZone) : []
215
+ const date = candidates.find(candidate => candidate.offset === offset) ?? candidates[0]
216
+ const instant = date?.toMillis()
217
+ const valid = removed || instant !== undefined
218
+ const unchanged =
219
+ fields &&
220
+ JSON.stringify(fields) === JSON.stringify(calendarFields(original)) &&
221
+ date?.offset === original.offset
222
+ const nextValue = removed
223
+ ? null
224
+ : instant === undefined
225
+ ? undefined
226
+ : unchanged && originalValue
227
+ ? originalValue
228
+ : dateOnly
229
+ ? new Date(instant).toISOString().slice(0, 10)
230
+ : new Date(instant).toISOString()
231
+ const lastEmitted = useRef(originalValue)
232
+ useEffect(() => {
233
+ if (inline) {
234
+ onEditingChange?.(!valid)
235
+ return () => onEditingChange?.(false)
236
+ }
237
+ }, [inline, onEditingChange, valid])
238
+ useEffect(() => {
239
+ if (inline && nextValue !== undefined && nextValue !== lastEmitted.current) {
240
+ lastEmitted.current = nextValue
241
+ onChange(nextValue)
242
+ }
243
+ }, [inline, nextValue, onChange])
244
+ if (saving) {
245
+ return (
246
+ <Flex {...stylex.props(dateStyles.editor)}>
247
+ <Text {...stylex.props(roles.muted)}>Saving date…</Text>
248
+ {instant !== undefined && (
249
+ <Text {...stylex.props(roles.text)}>
250
+ {formatCalendarDate(instant, timeZone)}
251
+ {!dateOnly && ` · ${formatCalendarTime(instant, timeZone)}`}
252
+ </Text>
253
+ )}
254
+ </Flex>
255
+ )
256
+ }
257
+ return (
258
+ <Flex {...stylex.props(dateStyles.editor)}>
259
+ {inline && (
260
+ <Flex {...stylex.props(dateStyles.heading)}>
261
+ <Text {...stylex.props(roles.strong)}>{label}</Text>
262
+ {clearable && !removed && (
263
+ <Button
264
+ accessibilityLabel={`Remove ${label.toLowerCase()}`}
265
+ onClick={() => setRemoved(true)}
266
+ style={button.quiet}
267
+ >
268
+ <Text>Clear</Text>
269
+ </Button>
270
+ )}
271
+ </Flex>
272
+ )}
273
+ {removed ? (
274
+ <FeatureAction component={component} onClick={() => setRemoved(false)}>
275
+ Add date
276
+ </FeatureAction>
277
+ ) : (
278
+ <Flex {...stylex.props(dateStyles.fields)}>
279
+ <Flex {...stylex.props(dateStyles.field)}>
280
+ {(!inline || !dateOnly) && <Text {...stylex.props(roles.muted)}>Date</Text>}
281
+ <Input placeholder="MM/DD/YYYY" value={dateText} onChange={setDateText} />
282
+ </Flex>
283
+ {!dateOnly && (
284
+ <Flex {...stylex.props(dateStyles.field)}>
285
+ <Text {...stylex.props(roles.muted)}>Time</Text>
286
+ <Input placeholder="h:mm AM/PM" value={timeText} onChange={setTimeText} />
287
+ </Flex>
288
+ )}
289
+ </Flex>
290
+ )}
291
+ {!removed && !dateOnly && (
292
+ <Text {...stylex.props(roles.muted)}>
293
+ {zoneName(instant ?? original.toMillis(), timeZone)}
294
+ </Text>
295
+ )}
296
+ {!removed && candidates.length > 1 && (
297
+ <Flex {...stylex.props(dateStyles.section)}>
298
+ <Text {...stylex.props(roles.muted)}>
299
+ This time happens twice when the clocks change. Choose an occurrence.
300
+ </Text>
301
+ <CalendarChoice
302
+ component={component}
303
+ label="Occurrence"
304
+ onChange={choice => {
305
+ const selected = candidates.find(
306
+ (candidate, index) => offsetChoice(candidate, index) === choice
307
+ )
308
+ if (selected) {
309
+ setOffset(selected.offset)
310
+ }
311
+ }}
312
+ options={candidates.map(offsetChoice)}
313
+ value={offsetChoice(
314
+ date ?? candidates[0],
315
+ candidates.indexOf(date ?? candidates[0])
316
+ )}
317
+ />
318
+ </Flex>
319
+ )}
320
+ {!valid && (
321
+ <Text {...stylex.props(roles.muted)}>
322
+ {fields
323
+ ? 'This time is skipped when the clocks change. Choose another time.'
324
+ : dateOnly
325
+ ? 'Enter a valid date (MM/DD/YYYY).'
326
+ : 'Enter a valid date (MM/DD/YYYY) and time (h:mm AM/PM).'}
327
+ </Text>
328
+ )}
329
+ {!inline && (
330
+ <Flex {...stylex.props(layout.actions)}>
331
+ <FeatureAction component={component} onClick={onCancel}>
332
+ Cancel
333
+ </FeatureAction>
334
+ <FeatureAction
335
+ component={component}
336
+ disabled={!valid}
337
+ onClick={() => {
338
+ if (nextValue !== undefined) {
339
+ onChange(nextValue)
340
+ }
341
+ }}
342
+ variant="primary"
343
+ >
344
+ {submitLabel ?? 'Save date'}
345
+ </FeatureAction>
346
+ </Flex>
347
+ )}
348
+ {!inline && clearable && value && (
349
+ <FeatureAction
350
+ component={component}
351
+ onClick={() => onChange(null)}
352
+ variant="quiet"
353
+ >
354
+ Remove date
355
+ </FeatureAction>
356
+ )}
357
+ </Flex>
358
+ )
359
+ }
360
+
361
+ function CalendarChoice({
362
+ label,
363
+ onChange,
364
+ options,
365
+ value,
366
+ }: {
367
+ component: KowalskiComponent
368
+ label: string
369
+ onChange: (value: string) => void
370
+ options: string[]
371
+ value: string
372
+ }) {
373
+ return (
374
+ <Picker
375
+ label={label}
376
+ onChange={next => {
377
+ if (options.includes(next)) {
378
+ onChange(next)
379
+ }
380
+ }}
381
+ value={value}
382
+ style={dateStyles.choice}
383
+ >
384
+ {options.map(option => (
385
+ <Text key={option} value={option}>
386
+ {option}
387
+ </Text>
388
+ ))}
389
+ </Picker>
390
+ )
391
+ }
392
+
393
+ function calendarFields(date: DateTime): CalendarFields {
394
+ return {
395
+ day: date.day,
396
+ hour: date.hour,
397
+ millisecond: date.millisecond,
398
+ minute: date.minute,
399
+ month: date.month,
400
+ second: date.second,
401
+ year: date.year,
402
+ }
403
+ }
404
+
405
+ function calendarCandidates(fields: CalendarFields, timeZone: string) {
406
+ const date = DateTime.fromObject(fields, { zone: timeZone })
407
+ return date.isValid && JSON.stringify(calendarFields(date)) === JSON.stringify(fields)
408
+ ? sortBy(date.getPossibleOffsets(), candidate => candidate.toMillis())
409
+ : []
410
+ }
411
+
412
+ function offsetChoice(date: DateTime, index: number) {
413
+ return `${index === 0 ? 'First' : 'Second'} · ${date.offsetNameLong}`
414
+ }
415
+
416
+ function formatCalendarDate(instant: number, timeZone: string) {
417
+ return format.formatters
418
+ .getDateTimeFormat(format.locale, {
419
+ day: 'numeric',
420
+ era:
421
+ DateTime.fromMillis(instant, { zone: timeZone }).year <= 0 ? 'short' : undefined,
422
+ month: 'long',
423
+ timeZone,
424
+ weekday: 'short',
425
+ year: 'numeric',
426
+ })
427
+ .format(instant)
428
+ }
429
+
430
+ function formatCalendarTime(instant: number, timeZone: string) {
431
+ const precise = new Date(instant)
432
+ return format.formatters
433
+ .getDateTimeFormat(format.locale, {
434
+ hour: 'numeric',
435
+ hour12: true,
436
+ minute: '2-digit',
437
+ ...(precise.getUTCSeconds() !== 0 || precise.getUTCMilliseconds() !== 0
438
+ ? { second: '2-digit' }
439
+ : {}),
440
+ ...(precise.getUTCMilliseconds() === 0 ? {} : { fractionalSecondDigits: 3 }),
441
+ timeZone,
442
+ timeZoneName: 'short',
443
+ })
444
+ .format(instant)
445
+ }
446
+
447
+ function zoneName(instant: number, timeZone: string) {
448
+ return (
449
+ format.formatters
450
+ .getDateTimeFormat(format.locale, { timeZone, timeZoneName: 'long' })
451
+ .formatToParts(instant)
452
+ .find(part => part.type === 'timeZoneName')?.value ?? timeZone.replaceAll('_', ' ')
453
+ )
454
+ }
455
+
456
+ const dateStyles = stylex.create({
457
+ choice: { width: '100%' },
458
+ editor: { gap: space[3] },
459
+ field: { flexBasis: '8rem', flexGrow: 1, gap: space[1.5], minWidth: 0 },
460
+ fields: { flexDirection: 'row', flexWrap: 'wrap', gap: space[2] },
461
+ heading: {
462
+ alignItems: 'center',
463
+ flexDirection: 'row',
464
+ gap: space[2],
465
+ justifyContent: 'space-between',
466
+ },
467
+ section: { gap: space[3] },
468
+ summary: { gap: space[1] },
469
+ })