@krizaka/ui 3.3.0 → 3.4.0

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 (352) hide show
  1. package/dist/activity-feed.d.ts +199 -0
  2. package/dist/activity-feed.js +155 -0
  3. package/dist/activity-feed.js.map +1 -0
  4. package/dist/argument-card.js +3 -3
  5. package/dist/chunk-7Z4KHPFC.js +42 -0
  6. package/dist/chunk-7Z4KHPFC.js.map +1 -0
  7. package/dist/data-table.js +98 -131
  8. package/dist/data-table.js.map +1 -1
  9. package/dist/description-list.d.ts +105 -0
  10. package/dist/description-list.js +49 -0
  11. package/dist/description-list.js.map +1 -0
  12. package/dist/index.js +13 -66
  13. package/dist/index.js.map +1 -1
  14. package/dist/kanban.d.ts +132 -0
  15. package/dist/kanban.js +187 -0
  16. package/dist/kanban.js.map +1 -0
  17. package/dist/list.d.ts +153 -0
  18. package/dist/list.js +130 -0
  19. package/dist/list.js.map +1 -0
  20. package/dist/map.d.ts +463 -0
  21. package/dist/map.js +952 -0
  22. package/dist/map.js.map +1 -0
  23. package/dist/motion.css +12 -1
  24. package/dist/native/map.d.ts +200 -0
  25. package/dist/native/map.js +673 -0
  26. package/dist/native/map.js.map +1 -0
  27. package/dist/native/media-picker.d.ts +58 -0
  28. package/dist/native/media-picker.js +63 -0
  29. package/dist/native/media-picker.js.map +1 -0
  30. package/dist/native.d.ts +568 -6
  31. package/dist/native.js +1989 -868
  32. package/dist/native.js.map +1 -1
  33. package/dist/page-hero.js +3 -3
  34. package/dist/stat.d.ts +31 -2
  35. package/dist/stat.js +21 -4
  36. package/dist/stat.js.map +1 -1
  37. package/dist/tree-view.d.ts +111 -0
  38. package/dist/tree-view.js +154 -0
  39. package/dist/tree-view.js.map +1 -0
  40. package/package.json +147 -10
  41. package/registry/achievement.json +1 -1
  42. package/registry/action-bar.json +1 -1
  43. package/registry/action-sheet.json +121 -0
  44. package/registry/activity-feed.json +468 -0
  45. package/registry/alert.json +1 -1
  46. package/registry/app-shell.json +1 -1
  47. package/registry/argument-card.json +1 -1
  48. package/registry/audio-player.json +1 -1
  49. package/registry/auth-layout.json +1 -1
  50. package/registry/avatar.json +58 -3
  51. package/registry/badge.json +1 -1
  52. package/registry/button.json +1 -1
  53. package/registry/card-grid.json +1 -1
  54. package/registry/card.json +1 -1
  55. package/registry/catalogue-page.json +1 -1
  56. package/registry/changelog-page.json +1 -1
  57. package/registry/checkbox.json +1 -1
  58. package/registry/chip-link.json +1 -1
  59. package/registry/chip.json +1 -1
  60. package/registry/choice-grid.json +1 -1
  61. package/registry/code-block.json +1 -1
  62. package/registry/combobox.json +1 -1
  63. package/registry/command.json +1 -1
  64. package/registry/component-page.json +1 -1
  65. package/registry/confirm-button.json +1 -1
  66. package/registry/contact-page.json +1 -1
  67. package/registry/continue-prompt.json +1 -1
  68. package/registry/countdown.json +1 -1
  69. package/registry/cta-panel.json +1 -1
  70. package/registry/dashboard-layout.json +1 -1
  71. package/registry/data-table.json +1 -1
  72. package/registry/date-picker.json +2 -2
  73. package/registry/decision-list.json +1 -1
  74. package/registry/description-list.json +232 -0
  75. package/registry/detail-layout.json +1 -1
  76. package/registry/dialog.json +1 -1
  77. package/registry/docs-article-page.json +1 -1
  78. package/registry/docs-hub-page.json +1 -1
  79. package/registry/docs-layout.json +1 -1
  80. package/registry/dropdown-menu.json +1 -1
  81. package/registry/empty-state.json +1 -1
  82. package/registry/error-page.json +1 -1
  83. package/registry/examples/action-sheet/native/video-actions.d.ts +4 -0
  84. package/registry/examples/action-sheet/native/video-actions.dark.png +0 -0
  85. package/registry/examples/action-sheet/native/video-actions.js +30 -0
  86. package/registry/examples/action-sheet/native/video-actions.light.png +0 -0
  87. package/registry/examples/action-sheet/native/video-actions.tsx +24 -0
  88. package/registry/examples/activity-feed/job-activity.d.ts +4 -0
  89. package/registry/examples/activity-feed/job-activity.js +21 -0
  90. package/registry/examples/activity-feed/job-activity.tsx +17 -0
  91. package/registry/examples/activity-feed/live.d.ts +4 -0
  92. package/registry/examples/activity-feed/live.js +23 -0
  93. package/registry/examples/activity-feed/live.tsx +24 -0
  94. package/registry/examples/activity-feed/native/notifications.d.ts +4 -0
  95. package/registry/examples/activity-feed/native/notifications.dark.png +0 -0
  96. package/registry/examples/activity-feed/native/notifications.js +18 -0
  97. package/registry/examples/activity-feed/native/notifications.light.png +0 -0
  98. package/registry/examples/activity-feed/native/notifications.tsx +18 -0
  99. package/registry/examples/activity-feed/timeline.d.ts +4 -0
  100. package/registry/examples/activity-feed/timeline.js +25 -0
  101. package/registry/examples/activity-feed/timeline.tsx +19 -0
  102. package/registry/examples/avatar/native/presence.d.ts +4 -0
  103. package/registry/examples/avatar/native/presence.dark.png +0 -0
  104. package/registry/examples/avatar/native/presence.js +18 -0
  105. package/registry/examples/avatar/native/presence.light.png +0 -0
  106. package/registry/examples/avatar/native/presence.tsx +15 -0
  107. package/registry/examples/description-list/job-details.d.ts +4 -0
  108. package/registry/examples/description-list/job-details.js +23 -0
  109. package/registry/examples/description-list/job-details.tsx +17 -0
  110. package/registry/examples/description-list/key-value-grid.d.ts +4 -0
  111. package/registry/examples/description-list/key-value-grid.js +22 -0
  112. package/registry/examples/description-list/key-value-grid.tsx +16 -0
  113. package/registry/examples/description-list/native/job-details.d.ts +4 -0
  114. package/registry/examples/description-list/native/job-details.dark.png +0 -0
  115. package/registry/examples/description-list/native/job-details.js +33 -0
  116. package/registry/examples/description-list/native/job-details.light.png +0 -0
  117. package/registry/examples/description-list/native/job-details.tsx +24 -0
  118. package/registry/examples/description-list/receipt.d.ts +4 -0
  119. package/registry/examples/description-list/receipt.js +23 -0
  120. package/registry/examples/description-list/receipt.tsx +17 -0
  121. package/registry/examples/fab/native/extended.d.ts +4 -0
  122. package/registry/examples/fab/native/extended.dark.png +0 -0
  123. package/registry/examples/fab/native/extended.js +18 -0
  124. package/registry/examples/fab/native/extended.light.png +0 -0
  125. package/registry/examples/fab/native/extended.tsx +23 -0
  126. package/registry/examples/header/native/large-title.d.ts +4 -0
  127. package/registry/examples/header/native/large-title.dark.png +0 -0
  128. package/registry/examples/header/native/large-title.js +23 -0
  129. package/registry/examples/header/native/large-title.light.png +0 -0
  130. package/registry/examples/header/native/large-title.tsx +31 -0
  131. package/registry/examples/image-viewer/native/gallery.d.ts +4 -0
  132. package/registry/examples/image-viewer/native/gallery.dark.png +0 -0
  133. package/registry/examples/image-viewer/native/gallery.js +22 -0
  134. package/registry/examples/image-viewer/native/gallery.light.png +0 -0
  135. package/registry/examples/image-viewer/native/gallery.tsx +21 -0
  136. package/registry/examples/kanban/moderation.d.ts +4 -0
  137. package/registry/examples/kanban/moderation.js +35 -0
  138. package/registry/examples/kanban/moderation.tsx +37 -0
  139. package/registry/examples/list/jobs.d.ts +4 -0
  140. package/registry/examples/list/jobs.js +35 -0
  141. package/registry/examples/list/jobs.tsx +33 -0
  142. package/registry/examples/list/selectable.d.ts +4 -0
  143. package/registry/examples/list/selectable.js +33 -0
  144. package/registry/examples/list/selectable.tsx +30 -0
  145. package/registry/examples/list/virtualized.d.ts +4 -0
  146. package/registry/examples/list/virtualized.js +22 -0
  147. package/registry/examples/list/virtualized.tsx +17 -0
  148. package/registry/examples/loader/native/block.d.ts +4 -0
  149. package/registry/examples/loader/native/block.dark.png +0 -0
  150. package/registry/examples/loader/native/block.js +12 -0
  151. package/registry/examples/loader/native/block.light.png +0 -0
  152. package/registry/examples/loader/native/block.tsx +11 -0
  153. package/registry/examples/loader/native/job-wait.d.ts +4 -0
  154. package/registry/examples/loader/native/job-wait.dark.png +0 -0
  155. package/registry/examples/loader/native/job-wait.js +17 -0
  156. package/registry/examples/loader/native/job-wait.light.png +0 -0
  157. package/registry/examples/loader/native/job-wait.tsx +14 -0
  158. package/registry/examples/map/cluster.d.ts +4 -0
  159. package/registry/examples/map/cluster.js +16 -0
  160. package/registry/examples/map/cluster.tsx +18 -0
  161. package/registry/examples/map/location-picker.d.ts +4 -0
  162. package/registry/examples/map/location-picker.js +24 -0
  163. package/registry/examples/map/location-picker.tsx +22 -0
  164. package/registry/examples/map/native/location-picker.d.ts +4 -0
  165. package/registry/examples/map/native/location-picker.dark.png +0 -0
  166. package/registry/examples/map/native/location-picker.js +14 -0
  167. package/registry/examples/map/native/location-picker.light.png +0 -0
  168. package/registry/examples/map/native/location-picker.tsx +13 -0
  169. package/registry/examples/map/native/places.d.ts +4 -0
  170. package/registry/examples/map/native/places.dark.png +0 -0
  171. package/registry/examples/map/native/places.js +25 -0
  172. package/registry/examples/map/native/places.light.png +0 -0
  173. package/registry/examples/map/native/places.tsx +27 -0
  174. package/registry/examples/map/places.d.ts +4 -0
  175. package/registry/examples/map/places.js +28 -0
  176. package/registry/examples/map/places.tsx +28 -0
  177. package/registry/examples/map/static.d.ts +4 -0
  178. package/registry/examples/map/static.js +22 -0
  179. package/registry/examples/map/static.tsx +18 -0
  180. package/registry/examples/media-picker/native/story.d.ts +4 -0
  181. package/registry/examples/media-picker/native/story.dark.png +0 -0
  182. package/registry/examples/media-picker/native/story.js +30 -0
  183. package/registry/examples/media-picker/native/story.light.png +0 -0
  184. package/registry/examples/media-picker/native/story.tsx +26 -0
  185. package/registry/examples/meter/native/credits.d.ts +4 -0
  186. package/registry/examples/meter/native/credits.dark.png +0 -0
  187. package/registry/examples/meter/native/credits.js +15 -0
  188. package/registry/examples/meter/native/credits.light.png +0 -0
  189. package/registry/examples/meter/native/credits.tsx +12 -0
  190. package/registry/examples/meter/native/split-ring.d.ts +4 -0
  191. package/registry/examples/meter/native/split-ring.dark.png +0 -0
  192. package/registry/examples/meter/native/split-ring.js +24 -0
  193. package/registry/examples/meter/native/split-ring.light.png +0 -0
  194. package/registry/examples/meter/native/split-ring.tsx +19 -0
  195. package/registry/examples/number-ticker/native/balance.d.ts +4 -0
  196. package/registry/examples/number-ticker/native/balance.dark.png +0 -0
  197. package/registry/examples/number-ticker/native/balance.js +18 -0
  198. package/registry/examples/number-ticker/native/balance.light.png +0 -0
  199. package/registry/examples/number-ticker/native/balance.tsx +17 -0
  200. package/registry/examples/onboarding/native/first-launch.d.ts +4 -0
  201. package/registry/examples/onboarding/native/first-launch.dark.png +0 -0
  202. package/registry/examples/onboarding/native/first-launch.js +23 -0
  203. package/registry/examples/onboarding/native/first-launch.light.png +0 -0
  204. package/registry/examples/onboarding/native/first-launch.tsx +19 -0
  205. package/registry/examples/otp-input/native/invalid.d.ts +4 -0
  206. package/registry/examples/otp-input/native/invalid.dark.png +0 -0
  207. package/registry/examples/otp-input/native/invalid.js +15 -0
  208. package/registry/examples/otp-input/native/invalid.light.png +0 -0
  209. package/registry/examples/otp-input/native/invalid.tsx +14 -0
  210. package/registry/examples/otp-input/native/verify.d.ts +4 -0
  211. package/registry/examples/otp-input/native/verify.dark.png +0 -0
  212. package/registry/examples/otp-input/native/verify.js +17 -0
  213. package/registry/examples/otp-input/native/verify.light.png +0 -0
  214. package/registry/examples/otp-input/native/verify.tsx +14 -0
  215. package/registry/examples/permission-prompt/native/blocked.d.ts +4 -0
  216. package/registry/examples/permission-prompt/native/blocked.dark.png +0 -0
  217. package/registry/examples/permission-prompt/native/blocked.js +25 -0
  218. package/registry/examples/permission-prompt/native/blocked.light.png +0 -0
  219. package/registry/examples/permission-prompt/native/blocked.tsx +21 -0
  220. package/registry/examples/permission-prompt/native/camera.d.ts +4 -0
  221. package/registry/examples/permission-prompt/native/camera.dark.png +0 -0
  222. package/registry/examples/permission-prompt/native/camera.js +25 -0
  223. package/registry/examples/permission-prompt/native/camera.light.png +0 -0
  224. package/registry/examples/permission-prompt/native/camera.tsx +21 -0
  225. package/registry/examples/pull-to-refresh/native/feed.d.ts +4 -0
  226. package/registry/examples/pull-to-refresh/native/feed.dark.png +0 -0
  227. package/registry/examples/pull-to-refresh/native/feed.js +14 -0
  228. package/registry/examples/pull-to-refresh/native/feed.light.png +0 -0
  229. package/registry/examples/pull-to-refresh/native/feed.tsx +19 -0
  230. package/registry/examples/search-field/native/cancel.d.ts +4 -0
  231. package/registry/examples/search-field/native/cancel.dark.png +0 -0
  232. package/registry/examples/search-field/native/cancel.js +14 -0
  233. package/registry/examples/search-field/native/cancel.light.png +0 -0
  234. package/registry/examples/search-field/native/cancel.tsx +13 -0
  235. package/registry/examples/stat/grid.d.ts +4 -0
  236. package/registry/examples/stat/grid.js +17 -0
  237. package/registry/examples/stat/grid.tsx +14 -0
  238. package/registry/examples/stepper/native/run.d.ts +4 -0
  239. package/registry/examples/stepper/native/run.dark.png +0 -0
  240. package/registry/examples/stepper/native/run.js +24 -0
  241. package/registry/examples/stepper/native/run.light.png +0 -0
  242. package/registry/examples/stepper/native/run.tsx +20 -0
  243. package/registry/examples/swipeable-row/native/conversation.d.ts +4 -0
  244. package/registry/examples/swipeable-row/native/conversation.dark.png +0 -0
  245. package/registry/examples/swipeable-row/native/conversation.js +30 -0
  246. package/registry/examples/swipeable-row/native/conversation.light.png +0 -0
  247. package/registry/examples/swipeable-row/native/conversation.tsx +27 -0
  248. package/registry/examples/tab-bar/native/main-sections.d.ts +4 -0
  249. package/registry/examples/tab-bar/native/main-sections.dark.png +0 -0
  250. package/registry/examples/tab-bar/native/main-sections.js +29 -0
  251. package/registry/examples/tab-bar/native/main-sections.light.png +0 -0
  252. package/registry/examples/tab-bar/native/main-sections.tsx +30 -0
  253. package/registry/examples/tabs/native/sections.d.ts +4 -0
  254. package/registry/examples/tabs/native/sections.dark.png +0 -0
  255. package/registry/examples/tabs/native/sections.js +23 -0
  256. package/registry/examples/tabs/native/sections.light.png +0 -0
  257. package/registry/examples/tabs/native/sections.tsx +19 -0
  258. package/registry/examples/tabs/native/segmented.d.ts +4 -0
  259. package/registry/examples/tabs/native/segmented.dark.png +0 -0
  260. package/registry/examples/tabs/native/segmented.js +22 -0
  261. package/registry/examples/tabs/native/segmented.light.png +0 -0
  262. package/registry/examples/tabs/native/segmented.tsx +18 -0
  263. package/registry/examples/toast/native/snackbar.d.ts +4 -0
  264. package/registry/examples/toast/native/snackbar.dark.png +0 -0
  265. package/registry/examples/toast/native/snackbar.js +23 -0
  266. package/registry/examples/toast/native/snackbar.light.png +0 -0
  267. package/registry/examples/toast/native/snackbar.tsx +21 -0
  268. package/registry/examples/tree-view/docs.d.ts +4 -0
  269. package/registry/examples/tree-view/docs.js +24 -0
  270. package/registry/examples/tree-view/docs.tsx +22 -0
  271. package/registry/examples/tree-view/lazy.d.ts +4 -0
  272. package/registry/examples/tree-view/lazy.js +21 -0
  273. package/registry/examples/tree-view/lazy.tsx +19 -0
  274. package/registry/fab.json +122 -0
  275. package/registry/field.json +1 -1
  276. package/registry/file-upload.json +2 -2
  277. package/registry/filter-bar.json +1 -1
  278. package/registry/form.json +2 -2
  279. package/registry/gallery-page.json +1 -1
  280. package/registry/glow-card.json +1 -1
  281. package/registry/goal-gauge.json +1 -1
  282. package/registry/header.json +137 -0
  283. package/registry/how-it-works-page.json +1 -1
  284. package/registry/image-cropper.json +1 -1
  285. package/registry/image-viewer.json +107 -0
  286. package/registry/index.json +299 -25
  287. package/registry/iso.json +1 -1
  288. package/registry/kanban.json +253 -0
  289. package/registry/kbd.json +1 -1
  290. package/registry/landing-page.json +1 -1
  291. package/registry/landscape.json +1 -1
  292. package/registry/legal-page.json +1 -1
  293. package/registry/link-card.json +1 -1
  294. package/registry/list.json +367 -30
  295. package/registry/loader.json +157 -4
  296. package/registry/longform-page.json +1 -1
  297. package/registry/map.json +1368 -0
  298. package/registry/marketing-layout.json +1 -1
  299. package/registry/marquee.json +1 -1
  300. package/registry/mascot-quote.json +1 -1
  301. package/registry/mascot-state.json +1 -1
  302. package/registry/mascots.json +1 -1
  303. package/registry/media-capture.json +1 -1
  304. package/registry/media-picker.json +129 -0
  305. package/registry/meter.json +136 -4
  306. package/registry/nav-bar.json +1 -1
  307. package/registry/number-ticker.json +96 -4
  308. package/registry/onboarding.json +95 -0
  309. package/registry/otp-input.json +150 -0
  310. package/registry/page-header.json +1 -1
  311. package/registry/page-hero.json +1 -1
  312. package/registry/page.json +1 -1
  313. package/registry/pagination.json +1 -1
  314. package/registry/permission-prompt.json +172 -0
  315. package/registry/pointer-light.json +1 -1
  316. package/registry/popover.json +1 -1
  317. package/registry/pricing-page.json +1 -1
  318. package/registry/product-page.json +1 -1
  319. package/registry/profile-card.json +1 -1
  320. package/registry/progress.json +2 -2
  321. package/registry/promise-card.json +1 -1
  322. package/registry/pull-to-refresh.json +74 -0
  323. package/registry/radio-group.json +1 -1
  324. package/registry/scroll-stage.json +1 -1
  325. package/registry/search-field.json +30 -3
  326. package/registry/section-backdrop.json +1 -1
  327. package/registry/separator.json +1 -1
  328. package/registry/settings-layout.json +1 -1
  329. package/registry/skeleton.json +1 -1
  330. package/registry/slider.json +1 -1
  331. package/registry/slot.json +1 -1
  332. package/registry/spinner.json +1 -1
  333. package/registry/split-view.json +1 -1
  334. package/registry/stage-banner.json +1 -1
  335. package/registry/stat.json +68 -5
  336. package/registry/status-page.json +1 -1
  337. package/registry/stepper.json +75 -4
  338. package/registry/swipeable-row.json +124 -0
  339. package/registry/switch.json +1 -1
  340. package/registry/tab-bar.json +115 -0
  341. package/registry/tabs.json +94 -4
  342. package/registry/tag-input.json +1 -1
  343. package/registry/terminal-replay.json +1 -1
  344. package/registry/theme.json +8 -1
  345. package/registry/toast.json +17 -3
  346. package/registry/toc.json +1 -1
  347. package/registry/tooltip.json +1 -1
  348. package/registry/tree-view.json +291 -0
  349. package/registry/video-player.json +1 -1
  350. package/registry/video-trimmer.json +1 -1
  351. package/registry/virtual.json +1 -1
  352. package/skills/map/SKILL.md +35 -0
package/dist/native.js CHANGED
@@ -151,10 +151,24 @@ function monthGrid(month, weekStartsOn) {
151
151
  return Array.from({ length: 6 }, (_, w) => days.slice(w * 7, w * 7 + 7)).filter((week, w) => w < 5 || week[0].slice(0, 7) === first.slice(0, 7));
152
152
  }
153
153
 
154
- // src/native/avatar.tsx
155
- import * as React2 from "react";
156
- import { Image, StyleSheet, Text, View } from "react-native";
157
- import { SvgUri } from "react-native-svg";
154
+ // src/native/action-sheet.tsx
155
+ import { Modal, Pressable, StyleSheet as StyleSheet2, View } from "react-native";
156
+
157
+ // src/native/overlay.tsx
158
+ import * as React from "react";
159
+ var modalName = (label) => ({ "aria-label": label });
160
+ function useOpen({ open, defaultOpen = false, onOpenChange }) {
161
+ const [own, setOwn] = React.useState(defaultOpen);
162
+ const value = open ?? own;
163
+ const set = React.useCallback(
164
+ (next) => {
165
+ if (open === void 0) setOwn(next);
166
+ onOpenChange?.(next);
167
+ },
168
+ [open, onOpenChange]
169
+ );
170
+ return [value, set];
171
+ }
158
172
 
159
173
  // ../tokens/dist/native.js
160
174
  var themes = /* @__PURE__ */ Object.freeze({ dark: /* @__PURE__ */ Object.freeze({
@@ -314,24 +328,25 @@ var marks = /* @__PURE__ */ Object.freeze({
314
328
  });
315
329
 
316
330
  // src/native/theme.tsx
317
- import * as React from "react";
331
+ import * as React2 from "react";
318
332
  import { AccessibilityInfo, useColorScheme } from "react-native";
319
333
  import { jsx } from "react/jsx-runtime";
320
334
  var themes2 = themes;
321
335
  var radius2 = radius;
322
336
  var motion2 = motion;
323
337
  var stillMotion = { ...motion2, duration: { instant: 0, fast: 0, base: 0 } };
324
- var ThemeContext = React.createContext(null);
338
+ var NO_INSETS = { top: 0, right: 0, bottom: 0, left: 0 };
339
+ var ThemeContext = React2.createContext(null);
325
340
  var noop = () => void 0;
326
341
  function resolve(mode, system) {
327
342
  if (mode === "system") return system === "light" ? "light" : "dark";
328
343
  return mode;
329
344
  }
330
- function ThemeProvider({ children, mode: controlled, defaultMode = "system", onModeChange, overrides, fonts, haptics }) {
345
+ function ThemeProvider({ children, mode: controlled, defaultMode = "system", onModeChange, overrides, fonts, haptics, insets }) {
331
346
  const system = useColorScheme();
332
- const [own, setOwn] = React.useState(defaultMode);
347
+ const [own, setOwn] = React2.useState(defaultMode);
333
348
  const mode = controlled ?? own;
334
- const setMode = React.useCallback(
349
+ const setMode = React2.useCallback(
335
350
  (next) => {
336
351
  if (controlled === void 0) setOwn(next);
337
352
  onModeChange?.(next);
@@ -341,23 +356,23 @@ function ThemeProvider({ children, mode: controlled, defaultMode = "system", onM
341
356
  const scheme = resolve(mode, system);
342
357
  const override = overrides?.[scheme];
343
358
  const reduce = useReducedMotion();
344
- const theme = React.useMemo(() => override ? { ...themes2[scheme], ...override } : themes2[scheme], [scheme, override]);
345
- const value = React.useMemo(
346
- () => ({ mode, setMode, scheme, theme, radius: radius2, motion: reduce ? stillMotion : motion2, fonts: fonts ?? {}, haptic: haptics ?? noop }),
347
- [mode, setMode, scheme, theme, fonts, reduce, haptics]
359
+ const theme = React2.useMemo(() => override ? { ...themes2[scheme], ...override } : themes2[scheme], [scheme, override]);
360
+ const value = React2.useMemo(
361
+ () => ({ mode, setMode, scheme, theme, radius: radius2, motion: reduce ? stillMotion : motion2, fonts: fonts ?? {}, haptic: haptics ?? noop, insets: insets ?? NO_INSETS }),
362
+ [mode, setMode, scheme, theme, fonts, reduce, haptics, insets]
348
363
  );
349
364
  return /* @__PURE__ */ jsx(ThemeContext.Provider, { value, children });
350
365
  }
351
366
  function useTheme() {
352
- const context = React.useContext(ThemeContext);
367
+ const context = React2.useContext(ThemeContext);
353
368
  const system = useColorScheme();
354
369
  if (context) return context;
355
370
  const scheme = resolve("system", system);
356
- return { mode: "system", setMode: noop, scheme, theme: themes2[scheme], radius: radius2, motion: motion2, fonts: {}, haptic: noop };
371
+ return { mode: "system", setMode: noop, scheme, theme: themes2[scheme], radius: radius2, motion: motion2, fonts: {}, haptic: noop, insets: NO_INSETS };
357
372
  }
358
373
  function useReducedMotion() {
359
- const [reduce, setReduce] = React.useState(false);
360
- React.useEffect(() => {
374
+ const [reduce, setReduce] = React2.useState(false);
375
+ React2.useEffect(() => {
361
376
  let alive = true;
362
377
  void AccessibilityInfo.isReduceMotionEnabled().then((value) => {
363
378
  if (alive) setReduce(value);
@@ -377,77 +392,304 @@ function alpha(color, opacity) {
377
392
  return `rgba(${r},${g},${b},${opacity})`;
378
393
  }
379
394
  function useSvgId(prefix) {
380
- return `${prefix}${React.useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
395
+ return `${prefix}${React2.useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
396
+ }
397
+
398
+ // src/native/txt.tsx
399
+ import { StyleSheet, Text } from "react-native";
400
+ import { jsx as jsx2 } from "react/jsx-runtime";
401
+ var TONE = {
402
+ text: "textPrimary",
403
+ secondary: "textSecondary",
404
+ muted: "textMuted",
405
+ accent: "accentText",
406
+ success: "successText",
407
+ warning: "warningText",
408
+ danger: "dangerText",
409
+ onAccent: "onAccent",
410
+ onMedia: "textOnMedia"
411
+ };
412
+ function Txt({ variant = "body", tone: tone3 = "text", style, ...props }) {
413
+ const { theme, fonts } = useTheme();
414
+ const family = variant === "display" || variant === "title" ? fonts.display : variant === "mono" ? fonts.mono : fonts.sans;
415
+ return /* @__PURE__ */ jsx2(
416
+ Text,
417
+ {
418
+ role: variant === "display" || variant === "title" ? "heading" : void 0,
419
+ ...props,
420
+ style: [styles[variant], { color: theme[TONE[tone3]] }, family ? { fontFamily: family } : null, style]
421
+ }
422
+ );
423
+ }
424
+ var textStyles = StyleSheet.create({
425
+ display: { fontSize: 30, lineHeight: 36, fontWeight: "900", letterSpacing: -0.5 },
426
+ title: { fontSize: 18, lineHeight: 24, fontWeight: "800" },
427
+ body: { fontSize: 15, lineHeight: 21 },
428
+ caption: { fontSize: 12, lineHeight: 16 },
429
+ label: { fontSize: 14, lineHeight: 18, fontWeight: "700" },
430
+ mono: { fontSize: 14, lineHeight: 18, fontWeight: "700", fontVariant: ["tabular-nums"] }
431
+ });
432
+ var styles = textStyles;
433
+
434
+ // src/native/action-sheet.tsx
435
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
436
+ function ActionSheet({ title, description, actions, cancelLabel, ...controlled }) {
437
+ const [open, setOpen] = useOpen(controlled);
438
+ const { theme, radius: radius3, insets, haptic } = useTheme();
439
+ const reduce = useReducedMotion();
440
+ const card = { backgroundColor: theme.glassBg, borderColor: theme.glassBorder, borderTopColor: theme.edgeLight, borderRadius: radius3.xl };
441
+ return /* @__PURE__ */ jsxs(Modal, { ...modalName(title), visible: open, transparent: true, animationType: reduce ? "none" : "slide", onRequestClose: () => setOpen(false), statusBarTranslucent: true, children: [
442
+ /* @__PURE__ */ jsx3(Pressable, { "aria-hidden": true, accessible: false, style: [StyleSheet2.absoluteFill, { backgroundColor: theme.scrim }], onPress: () => setOpen(false) }),
443
+ /* @__PURE__ */ jsxs(View, { style: [styles2.bottom, styles2.actionWrap, { paddingBottom: 8 + insets.bottom }], pointerEvents: "box-none", children: [
444
+ /* @__PURE__ */ jsxs(View, { role: "menu", "aria-label": title, style: [styles2.actionCard, card], children: [
445
+ /* @__PURE__ */ jsxs(View, { style: styles2.actionHead, children: [
446
+ /* @__PURE__ */ jsx3(Txt, { variant: "caption", tone: "secondary", style: styles2.centred, children: title }),
447
+ description ? /* @__PURE__ */ jsx3(Txt, { variant: "caption", tone: "muted", style: styles2.centred, children: description }) : null
448
+ ] }),
449
+ actions.map((action, i) => /* @__PURE__ */ jsxs(
450
+ Pressable,
451
+ {
452
+ role: "menuitem",
453
+ "aria-disabled": action.disabled,
454
+ disabled: action.disabled,
455
+ onPress: () => {
456
+ haptic("selection");
457
+ setOpen(false);
458
+ action.onPress();
459
+ },
460
+ style: ({ pressed }) => [styles2.action, { borderTopColor: theme.borderSubtle, backgroundColor: pressed ? theme.surface2 : "transparent", opacity: action.disabled ? 0.4 : 1 }],
461
+ children: [
462
+ action.icon ? /* @__PURE__ */ jsx3(View, { "aria-hidden": true, children: action.icon }) : null,
463
+ /* @__PURE__ */ jsx3(Txt, { variant: "label", tone: action.destructive ? "danger" : "text", children: action.label })
464
+ ]
465
+ },
466
+ i
467
+ ))
468
+ ] }),
469
+ /* @__PURE__ */ jsx3(Pressable, { role: "button", onPress: () => setOpen(false), style: ({ pressed }) => [styles2.cancel, card, { backgroundColor: pressed ? theme.surface2 : theme.surface1 }], children: /* @__PURE__ */ jsx3(Txt, { variant: "label", children: cancelLabel }) })
470
+ ] })
471
+ ] });
472
+ }
473
+ var styles2 = StyleSheet2.create({
474
+ bottom: { flex: 1, justifyContent: "flex-end" },
475
+ actionWrap: { paddingHorizontal: 8, gap: 8 },
476
+ actionCard: { borderWidth: StyleSheet2.hairlineWidth, overflow: "hidden" },
477
+ actionHead: { paddingVertical: 12, paddingHorizontal: 16, gap: 2 },
478
+ centred: { textAlign: "center" },
479
+ action: { flexDirection: "row", alignItems: "center", justifyContent: "center", gap: 10, minHeight: 52, paddingHorizontal: 16, borderTopWidth: StyleSheet2.hairlineWidth },
480
+ cancel: { minHeight: 52, alignItems: "center", justifyContent: "center", borderWidth: StyleSheet2.hairlineWidth }
481
+ });
482
+
483
+ // src/native/activity-feed.tsx
484
+ import * as React3 from "react";
485
+ import { AccessibilityInfo as AccessibilityInfo2, SectionList, StyleSheet as StyleSheet3, View as View2 } from "react-native";
486
+
487
+ // src/activity-feed/group.ts
488
+ var dayKey = (date) => `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
489
+ function groupActivity(events, { now = /* @__PURE__ */ new Date(), locale = "en-US", today = "Today", yesterday = "Yesterday", fold = true } = {}) {
490
+ const sorted = [...events].sort((a, b) => new Date(b.at).getTime() - new Date(a.at).getTime());
491
+ const day = new Intl.DateTimeFormat(locale, { weekday: "long", month: "short", day: "numeric" });
492
+ const todayKey = dayKey(now);
493
+ const yesterdayKey = dayKey(new Date(now.getTime() - 864e5));
494
+ const groups = [];
495
+ let current = null;
496
+ let currentKey = "";
497
+ for (const event of sorted) {
498
+ const date = new Date(event.at);
499
+ const key = dayKey(date);
500
+ if (!current || key !== currentKey) {
501
+ currentKey = key;
502
+ current = { label: key === todayKey ? today : key === yesterdayKey ? yesterday : day.format(date), events: [] };
503
+ groups.push(current);
504
+ }
505
+ const last = current.events[current.events.length - 1];
506
+ if (fold && last && event.actor && event.kind && last.event.actor === event.actor && last.event.kind === event.kind) last.count += 1;
507
+ else current.events.push({ event, count: 1 });
508
+ }
509
+ return groups;
510
+ }
511
+ var UNITS = [
512
+ ["second", 60],
513
+ ["minute", 60],
514
+ ["hour", 24],
515
+ ["day", 7],
516
+ ["week", 4.35],
517
+ ["month", 12],
518
+ ["year", Number.POSITIVE_INFINITY]
519
+ ];
520
+ function timeAgo(at, { now = /* @__PURE__ */ new Date(), locale = "en-US", style = "short" } = {}) {
521
+ let value = (new Date(at).getTime() - now.getTime()) / 1e3;
522
+ let unit = "second";
523
+ for (const [name, size] of UNITS) {
524
+ unit = name;
525
+ if (Math.abs(value) < size - 0.5) break;
526
+ value /= size;
527
+ }
528
+ return new Intl.RelativeTimeFormat(locale, { numeric: "auto", style }).format(Math.round(value) + 0, unit);
529
+ }
530
+
531
+ // src/native/activity-feed.tsx
532
+ import { Fragment, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
533
+ var LABELS = { today: "Today", yesterday: "Yesterday", times: (n) => `\xD7${n}`, newEvents: (n) => n === 1 ? "1 new event" : `${n} new events` };
534
+ var tone = (t, name) => ({ neutral: t.borderStrong, accent: t.accent, success: t.success, warning: t.warning, danger: t.danger, info: t.info })[name ?? "neutral"];
535
+ function ActivityFeed({ events, "aria-label": label, locale = "en-US", now: given, fold = true, live, leading, empty, labels: words, style }) {
536
+ const { theme } = useTheme();
537
+ const labels = { ...LABELS, ...words };
538
+ const [tick, setTick] = React3.useState(() => given ?? /* @__PURE__ */ new Date());
539
+ React3.useEffect(() => {
540
+ if (given) return;
541
+ const timer2 = setInterval(() => setTick(/* @__PURE__ */ new Date()), 6e4);
542
+ return () => clearInterval(timer2);
543
+ }, [given]);
544
+ const now = given ?? tick;
545
+ const seen = React3.useRef(events.length);
546
+ React3.useEffect(() => {
547
+ const added = events.length - seen.current;
548
+ seen.current = events.length;
549
+ if (live && added > 0) AccessibilityInfo2.announceForAccessibility(labels.newEvents(added));
550
+ }, [events.length, live]);
551
+ const sections = groupActivity(events, { now, locale, today: labels.today, yesterday: labels.yesterday, fold }).map((g) => ({ title: g.label, data: g.events }));
552
+ return /* @__PURE__ */ jsx4(
553
+ SectionList,
554
+ {
555
+ "aria-label": label,
556
+ style,
557
+ sections,
558
+ keyExtractor: (item) => item.event.id,
559
+ stickySectionHeadersEnabled: true,
560
+ ListEmptyComponent: empty ? /* @__PURE__ */ jsx4(Fragment, { children: empty }) : null,
561
+ renderSectionHeader: ({ section }) => /* @__PURE__ */ jsx4(View2, { style: [styles3.heading, { backgroundColor: theme.surface0 }], children: /* @__PURE__ */ jsx4(Txt, { variant: "caption", tone: "secondary", role: "heading", style: styles3.headingText, children: section.title }) }),
562
+ renderItem: ({ item: { event, count } }) => /* @__PURE__ */ jsxs2(View2, { style: styles3.row, accessible: true, children: [
563
+ leading ? leading(event) : /* @__PURE__ */ jsx4(View2, { "aria-hidden": true, style: [styles3.marker, { backgroundColor: tone(theme, event.tone) }] }),
564
+ /* @__PURE__ */ jsxs2(View2, { style: styles3.body, children: [
565
+ /* @__PURE__ */ jsxs2(Txt, { children: [
566
+ event.title,
567
+ count > 1 ? /* @__PURE__ */ jsx4(Txt, { variant: "caption", tone: "secondary", children: ` ${labels.times(count)}` }) : null
568
+ ] }),
569
+ event.description ? /* @__PURE__ */ jsx4(Txt, { variant: "caption", tone: "secondary", children: event.description }) : null
570
+ ] }),
571
+ /* @__PURE__ */ jsx4(Txt, { variant: "caption", tone: "secondary", children: timeAgo(event.at, { now, locale }) })
572
+ ] })
573
+ }
574
+ );
381
575
  }
576
+ var styles3 = StyleSheet3.create({
577
+ heading: { paddingVertical: 6 },
578
+ headingText: { fontWeight: "700", textTransform: "uppercase", letterSpacing: 0.6 },
579
+ row: { flexDirection: "row", alignItems: "flex-start", gap: 12, paddingVertical: 10 },
580
+ marker: { width: 10, height: 10, borderRadius: 5, marginTop: 5 },
581
+ body: { flex: 1, gap: 2 }
582
+ });
382
583
 
383
584
  // src/native/avatar.tsx
384
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
585
+ import * as React4 from "react";
586
+ import { Image, StyleSheet as StyleSheet4, Text as Text2, View as View3 } from "react-native";
587
+ import Svg, { Circle, Defs, LinearGradient, Stop, SvgUri } from "react-native-svg";
588
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
385
589
  var SIDE = { xs: 20, sm: 32, md: 40, lg: 56, xl: 80 };
386
590
  function isSvgUri(uri) {
387
591
  return /^data:image\/svg\+xml[;,]/i.test(uri) || /\.svg(?:[?#]|$)/i.test(uri);
388
592
  }
389
- function AvatarRoot({ src, svg, alt = "", fallback, size = "md", style, ...props }) {
593
+ function AvatarRoot({ src, svg, alt = "", fallback, size = "md", presence, presenceLabel, ring, style, ...props }) {
390
594
  const { theme } = useTheme();
391
- const [failedSrc, setFailedSrc] = React2.useState(null);
595
+ const gradient = useSvgId("kz-ring-");
596
+ const [failedSrc, setFailedSrc] = React4.useState(null);
392
597
  const failed = Boolean(src) && failedSrc === src;
393
598
  const side = typeof size === "number" ? size : SIDE[size];
394
599
  const initial = alt.trim().charAt(0).toUpperCase();
395
600
  const content = fallback ?? initial;
396
- return /* @__PURE__ */ jsx2(
397
- View,
601
+ const picture = /* @__PURE__ */ jsx5(
602
+ View3,
398
603
  {
399
- accessible: Boolean(alt),
400
- role: alt ? "img" : void 0,
401
- "aria-label": alt || void 0,
402
- ...props,
403
- style: [styles.root, { width: side, height: side, borderRadius: side / 2, backgroundColor: theme.surface3 }, style],
404
- children: src && !failed && (svg || isSvgUri(src)) ? /* @__PURE__ */ jsx2(View, { style: StyleSheet.absoluteFill, pointerEvents: "none", children: /* @__PURE__ */ jsx2(SvgUri, { testID: props.testID ? `${props.testID}.svg` : void 0, uri: src, width: "100%", height: "100%", preserveAspectRatio: "xMidYMid slice", onError: () => setFailedSrc(src) }) }) : src && !failed ? /* @__PURE__ */ jsx2(Image, { testID: props.testID ? `${props.testID}.image` : void 0, source: { uri: src }, onError: () => setFailedSrc(src), resizeMode: "cover", style: StyleSheet.absoluteFill }) : typeof content === "string" ? /* @__PURE__ */ jsx2(Text, { style: [styles.initial, { color: theme.textSecondary, fontSize: Math.max(9, Math.round(side * 0.4)) }], children: content }) : content
604
+ accessible: Boolean(alt) && !presence && !ring,
605
+ role: alt && !presence && !ring ? "img" : void 0,
606
+ "aria-label": alt && !presence && !ring ? alt : void 0,
607
+ ...presence || ring ? {} : props,
608
+ style: [styles4.root, { width: side, height: side, borderRadius: side / 2, backgroundColor: theme.surface3 }, presence || ring ? null : style],
609
+ children: src && !failed && (svg || isSvgUri(src)) ? /* @__PURE__ */ jsx5(View3, { style: StyleSheet4.absoluteFill, pointerEvents: "none", children: /* @__PURE__ */ jsx5(SvgUri, { testID: props.testID ? `${props.testID}.svg` : void 0, uri: src, width: "100%", height: "100%", preserveAspectRatio: "xMidYMid slice", onError: () => setFailedSrc(src) }) }) : src && !failed ? /* @__PURE__ */ jsx5(Image, { testID: props.testID ? `${props.testID}.image` : void 0, source: { uri: src }, onError: () => setFailedSrc(src), resizeMode: "cover", style: StyleSheet4.absoluteFill }) : typeof content === "string" ? /* @__PURE__ */ jsx5(Text2, { style: [styles4.initial, { color: theme.textSecondary, fontSize: Math.max(9, Math.round(side * 0.4)) }], children: content }) : content
405
610
  }
406
611
  );
612
+ if (!presence && !ring) return picture;
613
+ const gap = ring ? Math.max(2.5, Math.round(side * 0.07)) : 0;
614
+ const outer = side + gap * 4;
615
+ const dot = Math.max(8, Math.round(side * 0.28));
616
+ const dotColor = presence === "online" ? theme.success : presence === "away" ? theme.warning : presence === "busy" ? theme.danger : theme.surface0;
617
+ const name = [alt, presence ? presenceLabel : null].filter(Boolean).join(", ");
618
+ return /* @__PURE__ */ jsxs3(View3, { accessible: Boolean(name), role: name ? "img" : void 0, "aria-label": name || void 0, ...props, style: [{ width: outer, height: outer, alignItems: "center", justifyContent: "center" }, style], children: [
619
+ ring ? /* @__PURE__ */ jsxs3(Svg, { width: outer, height: outer, style: StyleSheet4.absoluteFill, "aria-hidden": true, children: [
620
+ /* @__PURE__ */ jsx5(Defs, { children: /* @__PURE__ */ jsxs3(LinearGradient, { id: gradient, x1: "0", y1: "1", x2: "1", y2: "0", children: [
621
+ /* @__PURE__ */ jsx5(Stop, { offset: "0", stopColor: theme.accent }),
622
+ /* @__PURE__ */ jsx5(Stop, { offset: "1", stopColor: theme.accent2 })
623
+ ] }) }),
624
+ /* @__PURE__ */ jsx5(
625
+ Circle,
626
+ {
627
+ cx: outer / 2,
628
+ cy: outer / 2,
629
+ r: outer / 2 - gap / 2 - 0.5,
630
+ fill: "none",
631
+ strokeWidth: gap,
632
+ stroke: ring === "story" ? `url(#${gradient})` : ring === "live" ? theme.danger : theme.borderStrong
633
+ }
634
+ )
635
+ ] }) : null,
636
+ picture,
637
+ presence ? /* @__PURE__ */ jsx5(
638
+ View3,
639
+ {
640
+ "aria-hidden": true,
641
+ style: [
642
+ styles4.dot,
643
+ { width: dot, height: dot, borderRadius: dot / 2, right: gap * 2, bottom: gap * 2, backgroundColor: dotColor, borderColor: presence === "offline" ? theme.textMuted : theme.surface0 }
644
+ ]
645
+ }
646
+ ) : null
647
+ ] });
407
648
  }
408
649
  function AvatarGroup({ max, size = "md", style, children, ...props }) {
409
650
  const { theme } = useTheme();
410
- const items2 = React2.Children.toArray(children);
651
+ const items2 = React4.Children.toArray(children);
411
652
  const shown = max === void 0 ? items2 : items2.slice(0, max);
412
653
  const rest = items2.length - shown.length;
413
654
  const side = typeof size === "number" ? size : SIDE[size];
414
655
  const ring = { borderWidth: 2, borderColor: theme.surface0, marginLeft: -side / 5 };
415
- return /* @__PURE__ */ jsxs(View, { ...props, style: [styles.group, { paddingLeft: side / 5 }, style], children: [
416
- shown.map((child, i) => /* @__PURE__ */ jsx2(View, { style: [ring, { borderRadius: side }], children: React2.isValidElement(child) ? React2.cloneElement(child, { size }) : child }, i)),
417
- rest > 0 ? /* @__PURE__ */ jsx2(View, { style: [ring, { borderRadius: side }], children: /* @__PURE__ */ jsx2(AvatarRoot, { size, fallback: `+${rest}` }) }) : null
656
+ return /* @__PURE__ */ jsxs3(View3, { ...props, style: [styles4.group, { paddingLeft: side / 5 }, style], children: [
657
+ shown.map((child, i) => /* @__PURE__ */ jsx5(View3, { style: [ring, { borderRadius: side }], children: React4.isValidElement(child) ? React4.cloneElement(child, { size }) : child }, i)),
658
+ rest > 0 ? /* @__PURE__ */ jsx5(View3, { style: [ring, { borderRadius: side }], children: /* @__PURE__ */ jsx5(AvatarRoot, { size, fallback: `+${rest}` }) }) : null
418
659
  ] });
419
660
  }
420
661
  var Avatar = Object.assign(AvatarRoot, { Group: AvatarGroup });
421
- var styles = StyleSheet.create({
662
+ var styles4 = StyleSheet4.create({
422
663
  root: { overflow: "hidden", alignItems: "center", justifyContent: "center" },
423
664
  initial: { fontWeight: "700" },
424
- group: { flexDirection: "row", alignItems: "center" }
665
+ group: { flexDirection: "row", alignItems: "center" },
666
+ dot: { position: "absolute", borderWidth: 2 }
425
667
  });
426
668
 
427
669
  // src/native/badge.tsx
428
- import * as React3 from "react";
429
- import { Animated, StyleSheet as StyleSheet2, Text as Text2 } from "react-native";
430
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
431
- function look(tone2, t) {
432
- switch (tone2) {
670
+ import * as React5 from "react";
671
+ import { Animated, StyleSheet as StyleSheet5, Text as Text3 } from "react-native";
672
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
673
+ function look(tone3, t) {
674
+ switch (tone3) {
433
675
  case "accent":
434
676
  return { bg: t.accentSoft, fg: t.textPrimary, border: alpha(t.accent, 0.4), dot: t.accent };
435
677
  case "success":
436
678
  case "warning":
437
679
  case "danger":
438
- return { bg: alpha(t[tone2], 0.15), fg: t.textPrimary, border: alpha(t[tone2], 0.4), dot: t[tone2] };
680
+ return { bg: alpha(t[tone3], 0.15), fg: t.textPrimary, border: alpha(t[tone3], 0.4), dot: t[tone3] };
439
681
  case "scrim":
440
682
  return { bg: t.scrim, fg: t.textOnMedia, border: "transparent", dot: t.textOnMedia };
441
683
  default:
442
684
  return { bg: t.surface3, fg: t.textSecondary, border: "transparent", dot: t.textSecondary };
443
685
  }
444
686
  }
445
- function Badge({ tone: tone2 = "neutral", size = "sm", dot, pulse, style, children, ...props }) {
687
+ function Badge({ tone: tone3 = "neutral", size = "sm", dot, pulse, style, children, ...props }) {
446
688
  const { theme } = useTheme();
447
- const colors = look(tone2, theme);
689
+ const colors = look(tone3, theme);
448
690
  const reduce = useReducedMotion();
449
- const [opacity] = React3.useState(() => new Animated.Value(1));
450
- React3.useEffect(() => {
691
+ const [opacity] = React5.useState(() => new Animated.Value(1));
692
+ React5.useEffect(() => {
451
693
  if (!dot || !pulse || reduce) return;
452
694
  const loop = Animated.loop(
453
695
  Animated.sequence([
@@ -461,19 +703,19 @@ function Badge({ tone: tone2 = "neutral", size = "sm", dot, pulse, style, childr
461
703
  opacity.setValue(1);
462
704
  };
463
705
  }, [dot, pulse, reduce, opacity]);
464
- return /* @__PURE__ */ jsxs2(
706
+ return /* @__PURE__ */ jsxs4(
465
707
  Animated.View,
466
708
  {
467
709
  ...props,
468
- style: [styles2.root, size === "md" ? styles2.md : styles2.sm, { backgroundColor: colors.bg, borderColor: colors.border }, style],
710
+ style: [styles5.root, size === "md" ? styles5.md : styles5.sm, { backgroundColor: colors.bg, borderColor: colors.border }, style],
469
711
  children: [
470
- dot ? /* @__PURE__ */ jsx3(Animated.View, { "aria-hidden": true, style: [styles2.dot, { backgroundColor: colors.dot, opacity }] }) : null,
471
- typeof children === "string" || typeof children === "number" ? /* @__PURE__ */ jsx3(Text2, { style: [styles2.text, { color: colors.fg, fontSize: size === "md" ? 11 : 10 }], children }) : children
712
+ dot ? /* @__PURE__ */ jsx6(Animated.View, { "aria-hidden": true, style: [styles5.dot, { backgroundColor: colors.dot, opacity }] }) : null,
713
+ typeof children === "string" || typeof children === "number" ? /* @__PURE__ */ jsx6(Text3, { style: [styles5.text, { color: colors.fg, fontSize: size === "md" ? 11 : 10 }], children }) : children
472
714
  ]
473
715
  }
474
716
  );
475
717
  }
476
- var styles2 = StyleSheet2.create({
718
+ var styles5 = StyleSheet5.create({
477
719
  root: { flexDirection: "row", alignItems: "center", alignSelf: "flex-start", gap: 4, borderRadius: 9999, borderWidth: 1 },
478
720
  sm: { paddingHorizontal: 8, paddingVertical: 2 },
479
721
  md: { paddingHorizontal: 10, paddingVertical: 4 },
@@ -482,48 +724,10 @@ var styles2 = StyleSheet2.create({
482
724
  });
483
725
 
484
726
  // src/native/button.tsx
485
- import * as React4 from "react";
486
- import { ActivityIndicator, Pressable, StyleSheet as StyleSheet4, View as View2 } from "react-native";
487
- import Svg, { Defs, LinearGradient, Rect, Stop } from "react-native-svg";
488
-
489
- // src/native/txt.tsx
490
- import { StyleSheet as StyleSheet3, Text as Text3 } from "react-native";
491
- import { jsx as jsx4 } from "react/jsx-runtime";
492
- var TONE = {
493
- text: "textPrimary",
494
- secondary: "textSecondary",
495
- muted: "textMuted",
496
- accent: "accentText",
497
- success: "successText",
498
- warning: "warningText",
499
- danger: "dangerText",
500
- onAccent: "onAccent",
501
- onMedia: "textOnMedia"
502
- };
503
- function Txt({ variant = "body", tone: tone2 = "text", style, ...props }) {
504
- const { theme, fonts } = useTheme();
505
- const family = variant === "display" || variant === "title" ? fonts.display : variant === "mono" ? fonts.mono : fonts.sans;
506
- return /* @__PURE__ */ jsx4(
507
- Text3,
508
- {
509
- role: variant === "display" || variant === "title" ? "heading" : void 0,
510
- ...props,
511
- style: [styles3[variant], { color: theme[TONE[tone2]] }, family ? { fontFamily: family } : null, style]
512
- }
513
- );
514
- }
515
- var textStyles = StyleSheet3.create({
516
- display: { fontSize: 30, lineHeight: 36, fontWeight: "900", letterSpacing: -0.5 },
517
- title: { fontSize: 18, lineHeight: 24, fontWeight: "800" },
518
- body: { fontSize: 15, lineHeight: 21 },
519
- caption: { fontSize: 12, lineHeight: 16 },
520
- label: { fontSize: 14, lineHeight: 18, fontWeight: "700" },
521
- mono: { fontSize: 14, lineHeight: 18, fontWeight: "700", fontVariant: ["tabular-nums"] }
522
- });
523
- var styles3 = textStyles;
524
-
525
- // src/native/button.tsx
526
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
727
+ import * as React6 from "react";
728
+ import { ActivityIndicator, Pressable as Pressable2, StyleSheet as StyleSheet6, View as View4 } from "react-native";
729
+ import Svg2, { Defs as Defs2, LinearGradient as LinearGradient2, Rect, Stop as Stop2 } from "react-native-svg";
730
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
527
731
  function look2(variant, t) {
528
732
  switch (variant) {
529
733
  case "primary":
@@ -558,19 +762,19 @@ function useButton({ variant = "secondary", size = "md", shape = "rounded", load
558
762
  }
559
763
  function Fill({ colors, id }) {
560
764
  if (!colors.gradient) return null;
561
- return /* @__PURE__ */ jsxs3(Svg, { "aria-hidden": true, pointerEvents: "none", style: StyleSheet4.absoluteFill, width: "100%", height: "100%", children: [
562
- /* @__PURE__ */ jsx5(Defs, { children: /* @__PURE__ */ jsxs3(LinearGradient, { id, x1: "0", y1: "0", x2: "1", y2: "0", children: [
563
- /* @__PURE__ */ jsx5(Stop, { offset: "0", stopColor: colors.gradient[0] }),
564
- /* @__PURE__ */ jsx5(Stop, { offset: "1", stopColor: colors.gradient[1] })
765
+ return /* @__PURE__ */ jsxs5(Svg2, { "aria-hidden": true, pointerEvents: "none", style: StyleSheet6.absoluteFill, width: "100%", height: "100%", children: [
766
+ /* @__PURE__ */ jsx7(Defs2, { children: /* @__PURE__ */ jsxs5(LinearGradient2, { id, x1: "0", y1: "0", x2: "1", y2: "0", children: [
767
+ /* @__PURE__ */ jsx7(Stop2, { offset: "0", stopColor: colors.gradient[0] }),
768
+ /* @__PURE__ */ jsx7(Stop2, { offset: "1", stopColor: colors.gradient[1] })
565
769
  ] }) }),
566
- /* @__PURE__ */ jsx5(Rect, { width: "100%", height: "100%", fill: `url(#${id})` })
770
+ /* @__PURE__ */ jsx7(Rect, { width: "100%", height: "100%", fill: `url(#${id})` })
567
771
  ] });
568
772
  }
569
773
  function Button({ label, icon, variant, size = "md", shape, loading = false, disabled, style, ...props }) {
570
774
  const { colors, inactive, frame } = useButton({ variant, size, shape, loading, disabled });
571
- const gradientId = `kz-button-${React4.useId().replace(/:/g, "")}`;
572
- return /* @__PURE__ */ jsxs3(
573
- Pressable,
775
+ const gradientId = `kz-button-${React6.useId().replace(/:/g, "")}`;
776
+ return /* @__PURE__ */ jsxs5(
777
+ Pressable2,
574
778
  {
575
779
  role: "button",
576
780
  "aria-label": label,
@@ -578,12 +782,12 @@ function Button({ label, icon, variant, size = "md", shape, loading = false, dis
578
782
  "aria-busy": loading,
579
783
  ...props,
580
784
  disabled: inactive,
581
- style: ({ pressed }) => [styles4.base, { paddingHorizontal: PADDING[size] }, frame(pressed), style],
785
+ style: ({ pressed }) => [styles6.base, { paddingHorizontal: PADDING[size] }, frame(pressed), style],
582
786
  children: [
583
- /* @__PURE__ */ jsx5(Fill, { colors, id: gradientId }),
584
- /* @__PURE__ */ jsxs3(View2, { style: styles4.row, children: [
585
- loading ? /* @__PURE__ */ jsx5(ActivityIndicator, { "aria-hidden": true, size: "small", color: colors.fg }) : icon,
586
- /* @__PURE__ */ jsx5(Txt, { variant: "label", numberOfLines: 1, style: { color: colors.fg, fontSize: size === "sm" ? 12 : 14 }, children: label })
787
+ /* @__PURE__ */ jsx7(Fill, { colors, id: gradientId }),
788
+ /* @__PURE__ */ jsxs5(View4, { style: styles6.row, children: [
789
+ loading ? /* @__PURE__ */ jsx7(ActivityIndicator, { "aria-hidden": true, size: "small", color: colors.fg }) : icon,
790
+ /* @__PURE__ */ jsx7(Txt, { variant: "label", numberOfLines: 1, style: { color: colors.fg, fontSize: size === "sm" ? 12 : 14 }, children: label })
587
791
  ] })
588
792
  ]
589
793
  }
@@ -591,10 +795,10 @@ function Button({ label, icon, variant, size = "md", shape, loading = false, dis
591
795
  }
592
796
  function IconButton({ label, icon, variant, size = "md", shape, loading = false, disabled, style, ...props }) {
593
797
  const { colors, inactive, frame } = useButton({ variant, size, shape, loading, disabled });
594
- const gradientId = `kz-button-${React4.useId().replace(/:/g, "")}`;
798
+ const gradientId = `kz-button-${React6.useId().replace(/:/g, "")}`;
595
799
  const side = HEIGHT[size];
596
- return /* @__PURE__ */ jsxs3(
597
- Pressable,
800
+ return /* @__PURE__ */ jsxs5(
801
+ Pressable2,
598
802
  {
599
803
  role: "button",
600
804
  "aria-label": label,
@@ -603,36 +807,36 @@ function IconButton({ label, icon, variant, size = "md", shape, loading = false,
603
807
  hitSlop: side < 44 ? (44 - side) / 2 : void 0,
604
808
  ...props,
605
809
  disabled: inactive,
606
- style: ({ pressed }) => [styles4.base, frame(pressed), { width: side }, style],
810
+ style: ({ pressed }) => [styles6.base, frame(pressed), { width: side }, style],
607
811
  children: [
608
- /* @__PURE__ */ jsx5(Fill, { colors, id: gradientId }),
609
- loading ? /* @__PURE__ */ jsx5(ActivityIndicator, { "aria-hidden": true, size: "small", color: colors.fg }) : icon
812
+ /* @__PURE__ */ jsx7(Fill, { colors, id: gradientId }),
813
+ loading ? /* @__PURE__ */ jsx7(ActivityIndicator, { "aria-hidden": true, size: "small", color: colors.fg }) : icon
610
814
  ]
611
815
  }
612
816
  );
613
817
  }
614
- var styles4 = StyleSheet4.create({
818
+ var styles6 = StyleSheet6.create({
615
819
  base: { alignItems: "center", justifyContent: "center", borderWidth: 1, overflow: "hidden" },
616
820
  row: { flexDirection: "row", alignItems: "center", gap: 8 }
617
821
  });
618
822
 
619
823
  // src/native/card.tsx
620
- import { Image as Image2, Pressable as Pressable2, StyleSheet as StyleSheet5, View as View3 } from "react-native";
621
- import { jsx as jsx6 } from "react/jsx-runtime";
622
- function CardRoot({ tone: tone2 = "default", radius: radius3 = "xl", onPress, style, ...props }) {
824
+ import { Image as Image2, Pressable as Pressable3, StyleSheet as StyleSheet7, View as View5 } from "react-native";
825
+ import { jsx as jsx8 } from "react/jsx-runtime";
826
+ function CardRoot({ tone: tone3 = "default", radius: radius3 = "xl", onPress, style, ...props }) {
623
827
  const { theme, radius: r } = useTheme();
624
828
  const frame = [
625
- styles5.root,
829
+ styles7.root,
626
830
  {
627
- backgroundColor: tone2 === "elevated" ? theme.surface2 : theme.surface1,
831
+ backgroundColor: tone3 === "elevated" ? theme.surface2 : theme.surface1,
628
832
  borderColor: theme.borderDefault,
629
833
  borderRadius: r[radius3]
630
834
  },
631
- tone2 === "elevated" ? [styles5.shadow, { shadowColor: theme.scrimStrong }] : null
835
+ tone3 === "elevated" ? [styles7.shadow, { shadowColor: theme.scrimStrong }] : null
632
836
  ];
633
- if (!onPress) return /* @__PURE__ */ jsx6(View3, { ...props, style: [frame, style] });
634
- return /* @__PURE__ */ jsx6(
635
- Pressable2,
837
+ if (!onPress) return /* @__PURE__ */ jsx8(View5, { ...props, style: [frame, style] });
838
+ return /* @__PURE__ */ jsx8(
839
+ Pressable3,
636
840
  {
637
841
  role: "button",
638
842
  onPress,
@@ -644,14 +848,14 @@ function CardRoot({ tone: tone2 = "default", radius: radius3 = "xl", onPress, st
644
848
  var ASPECT = { video: 16 / 9, square: 1, portrait: 3 / 4 };
645
849
  function CardMedia({ aspect = "video", style, ...props }) {
646
850
  const { theme } = useTheme();
647
- return /* @__PURE__ */ jsx6(View3, { ...props, style: [styles5.media, { backgroundColor: theme.media }, aspect === "auto" ? null : { aspectRatio: ASPECT[aspect] }, style] });
851
+ return /* @__PURE__ */ jsx8(View5, { ...props, style: [styles7.media, { backgroundColor: theme.media }, aspect === "auto" ? null : { aspectRatio: ASPECT[aspect] }, style] });
648
852
  }
649
853
  function CardImage({ src, fallback, alt, style, ...props }) {
650
854
  const { theme } = useTheme();
651
855
  if (!src) {
652
- return /* @__PURE__ */ jsx6(View3, { "aria-hidden": true, style: [StyleSheet5.absoluteFill, styles5.center, { backgroundColor: theme.accentSoft }], children: fallback });
856
+ return /* @__PURE__ */ jsx8(View5, { "aria-hidden": true, style: [StyleSheet7.absoluteFill, styles7.center, { backgroundColor: theme.accentSoft }], children: fallback });
653
857
  }
654
- return /* @__PURE__ */ jsx6(Image2, { accessible: Boolean(alt), alt, "aria-label": alt, resizeMode: "cover", ...props, source: { uri: src }, style: [StyleSheet5.absoluteFill, style] });
858
+ return /* @__PURE__ */ jsx8(Image2, { accessible: Boolean(alt), alt, "aria-label": alt, resizeMode: "cover", ...props, source: { uri: src }, style: [StyleSheet7.absoluteFill, style] });
655
859
  }
656
860
  var CORNER = {
657
861
  "top-left": { top: 10, left: 10 },
@@ -660,21 +864,21 @@ var CORNER = {
660
864
  "bottom-right": { bottom: 10, right: 10 }
661
865
  };
662
866
  function CardOverlay({ corner = "top-left", style, ...props }) {
663
- return /* @__PURE__ */ jsx6(View3, { ...props, style: [styles5.overlay, CORNER[corner], style] });
867
+ return /* @__PURE__ */ jsx8(View5, { ...props, style: [styles7.overlay, CORNER[corner], style] });
664
868
  }
665
869
  var PADDING2 = { none: 0, sm: 12, md: 16, lg: 24 };
666
870
  function CardBody({ padding = "md", style, ...props }) {
667
- return /* @__PURE__ */ jsx6(View3, { ...props, style: [styles5.body, { padding: PADDING2[padding] }, style] });
871
+ return /* @__PURE__ */ jsx8(View5, { ...props, style: [styles7.body, { padding: PADDING2[padding] }, style] });
668
872
  }
669
873
  function CardTitle({ numberOfLines = 1, ...props }) {
670
- return /* @__PURE__ */ jsx6(Txt, { variant: "label", role: "heading", numberOfLines, ...props });
874
+ return /* @__PURE__ */ jsx8(Txt, { variant: "label", role: "heading", numberOfLines, ...props });
671
875
  }
672
876
  function CardDescription({ numberOfLines = 2, ...props }) {
673
- return /* @__PURE__ */ jsx6(Txt, { variant: "caption", tone: "secondary", numberOfLines, ...props });
877
+ return /* @__PURE__ */ jsx8(Txt, { variant: "caption", tone: "secondary", numberOfLines, ...props });
674
878
  }
675
879
  function CardFooter({ style, ...props }) {
676
880
  const { theme } = useTheme();
677
- return /* @__PURE__ */ jsx6(View3, { ...props, style: [styles5.footer, { borderTopColor: theme.borderSubtle }, style] });
881
+ return /* @__PURE__ */ jsx8(View5, { ...props, style: [styles7.footer, { borderTopColor: theme.borderSubtle }, style] });
678
882
  }
679
883
  var Card = {
680
884
  Root: CardRoot,
@@ -686,37 +890,37 @@ var Card = {
686
890
  Description: CardDescription,
687
891
  Footer: CardFooter
688
892
  };
689
- var styles5 = StyleSheet5.create({
690
- root: { overflow: "hidden", borderWidth: StyleSheet5.hairlineWidth },
893
+ var styles7 = StyleSheet7.create({
894
+ root: { overflow: "hidden", borderWidth: StyleSheet7.hairlineWidth },
691
895
  shadow: { shadowOpacity: 0.25, shadowRadius: 12, shadowOffset: { width: 0, height: 6 }, elevation: 4 },
692
896
  media: { position: "relative", overflow: "hidden", width: "100%" },
693
897
  center: { alignItems: "center", justifyContent: "center" },
694
898
  overlay: { position: "absolute", zIndex: 1, flexDirection: "row", alignItems: "center", gap: 6 },
695
899
  body: { gap: 12 },
696
- footer: { flexDirection: "row", alignItems: "center", gap: 8, borderTopWidth: StyleSheet5.hairlineWidth, paddingTop: 12, marginTop: "auto" }
900
+ footer: { flexDirection: "row", alignItems: "center", gap: 8, borderTopWidth: StyleSheet7.hairlineWidth, paddingTop: 12, marginTop: "auto" }
697
901
  });
698
902
 
699
903
  // src/native/checkbox.tsx
700
- import * as React5 from "react";
701
- import { Pressable as Pressable3, StyleSheet as StyleSheet6, Text as Text4, View as View4 } from "react-native";
702
- import Svg2, { Path } from "react-native-svg";
703
- import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
904
+ import * as React7 from "react";
905
+ import { Pressable as Pressable4, StyleSheet as StyleSheet8, Text as Text4, View as View6 } from "react-native";
906
+ import Svg3, { Path } from "react-native-svg";
907
+ import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
704
908
  function Checkbox({ children, label, checked, defaultChecked = false, onCheckedChange, error, disabled, style }) {
705
909
  const { theme, radius: radius3 } = useTheme();
706
- const [own, setOwn] = React5.useState(defaultChecked);
910
+ const [own, setOwn] = React7.useState(defaultChecked);
707
911
  const on = checked ?? own;
708
912
  const toggle = () => {
709
913
  if (checked === void 0) setOwn(!on);
710
914
  onCheckedChange?.(!on);
711
915
  };
712
- const box = /* @__PURE__ */ jsx7(
713
- View4,
916
+ const box = /* @__PURE__ */ jsx9(
917
+ View6,
714
918
  {
715
919
  style: [
716
- styles6.box,
920
+ styles8.box,
717
921
  { borderRadius: radius3.xs + 2, borderColor: error ? theme.danger : on ? theme.accent : theme.borderStrong, backgroundColor: on ? theme.accent : theme.surface1 }
718
922
  ],
719
- children: on ? /* @__PURE__ */ jsx7(Svg2, { width: 14, height: 14, viewBox: "0 0 24 24", fill: "none", stroke: theme.onAccent, strokeWidth: 3, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx7(Path, { d: "M20 6 9 17l-5-5" }) }) : null
923
+ children: on ? /* @__PURE__ */ jsx9(Svg3, { width: 14, height: 14, viewBox: "0 0 24 24", fill: "none", stroke: theme.onAccent, strokeWidth: 3, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx9(Path, { d: "M20 6 9 17l-5-5" }) }) : null
720
924
  }
721
925
  );
722
926
  const plain = children === void 0 || typeof children === "string";
@@ -729,21 +933,21 @@ function Checkbox({ children, label, checked, defaultChecked = false, onCheckedC
729
933
  disabled,
730
934
  onPress: toggle
731
935
  };
732
- return /* @__PURE__ */ jsxs4(View4, { style: [styles6.root, style], children: [
733
- plain ? /* @__PURE__ */ jsxs4(Pressable3, { ...a11y, hitSlop: 4, style: [styles6.row, disabled ? styles6.disabled : null], children: [
936
+ return /* @__PURE__ */ jsxs6(View6, { style: [styles8.root, style], children: [
937
+ plain ? /* @__PURE__ */ jsxs6(Pressable4, { ...a11y, hitSlop: 4, style: [styles8.row, disabled ? styles8.disabled : null], children: [
734
938
  box,
735
- children !== void 0 ? /* @__PURE__ */ jsx7(View4, { style: styles6.text, children: /* @__PURE__ */ jsx7(Text4, { style: [styles6.label, { color: theme.textPrimary }], children }) }) : null
939
+ children !== void 0 ? /* @__PURE__ */ jsx9(View6, { style: styles8.text, children: /* @__PURE__ */ jsx9(Text4, { style: [styles8.label, { color: theme.textPrimary }], children }) }) : null
736
940
  ] }) : (
737
941
  // Words with links: the box alone is the control (a 44-pt target, named by `label`), the links stay links.
738
- /* @__PURE__ */ jsxs4(View4, { style: [styles6.row, disabled ? styles6.disabled : null], children: [
739
- /* @__PURE__ */ jsx7(Pressable3, { ...a11y, hitSlop: 11, style: styles6.target, children: box }),
740
- /* @__PURE__ */ jsx7(View4, { style: styles6.text, children })
942
+ /* @__PURE__ */ jsxs6(View6, { style: [styles8.row, disabled ? styles8.disabled : null], children: [
943
+ /* @__PURE__ */ jsx9(Pressable4, { ...a11y, hitSlop: 11, style: styles8.target, children: box }),
944
+ /* @__PURE__ */ jsx9(View6, { style: styles8.text, children })
741
945
  ] })
742
946
  ),
743
- error ? /* @__PURE__ */ jsx7(Text4, { role: "alert", "aria-live": "polite", style: [styles6.error, { color: theme.dangerText }], children: error }) : null
947
+ error ? /* @__PURE__ */ jsx9(Text4, { role: "alert", "aria-live": "polite", style: [styles8.error, { color: theme.dangerText }], children: error }) : null
744
948
  ] });
745
949
  }
746
- var styles6 = StyleSheet6.create({
950
+ var styles8 = StyleSheet8.create({
747
951
  root: { gap: 2, alignSelf: "stretch" },
748
952
  row: { flexDirection: "row", alignItems: "center", gap: 12, minHeight: 44 },
749
953
  target: { minHeight: 44, justifyContent: "center" },
@@ -755,18 +959,18 @@ var styles6 = StyleSheet6.create({
755
959
  });
756
960
 
757
961
  // src/native/chip.tsx
758
- import * as React6 from "react";
759
- import { Pressable as Pressable4, ScrollView, StyleSheet as StyleSheet7, Text as Text5, View as View5 } from "react-native";
760
- import { Fragment, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
761
- var ChipGroupContext = React6.createContext(null);
962
+ import * as React8 from "react";
963
+ import { Pressable as Pressable5, ScrollView, StyleSheet as StyleSheet9, Text as Text5, View as View7 } from "react-native";
964
+ import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
965
+ var ChipGroupContext = React8.createContext(null);
762
966
  function Label({ children, color, size }) {
763
- if (typeof children !== "string" && typeof children !== "number") return /* @__PURE__ */ jsx8(Fragment, { children });
764
- return /* @__PURE__ */ jsx8(Text5, { style: [styles7.label, { color, fontSize: size === "sm" ? 12 : 13 }], children });
967
+ if (typeof children !== "string" && typeof children !== "number") return /* @__PURE__ */ jsx10(Fragment2, { children });
968
+ return /* @__PURE__ */ jsx10(Text5, { style: [styles9.label, { color, fontSize: size === "sm" ? 12 : 13 }], children });
765
969
  }
766
970
  function ChipBase(props) {
767
- const group = React6.useContext(ChipGroupContext);
971
+ const group = React8.useContext(ChipGroupContext);
768
972
  const { theme, radius: radius3 } = useTheme();
769
- const [own, setOwn] = React6.useState(props.removable ? false : props.defaultSelected ?? false);
973
+ const [own, setOwn] = React8.useState(props.removable ? false : props.defaultSelected ?? false);
770
974
  const size = props.size ?? group?.size ?? "md";
771
975
  const frame = (on2, pressed) => ({
772
976
  height: size === "sm" ? 28 : 36,
@@ -777,9 +981,9 @@ function ChipBase(props) {
777
981
  });
778
982
  if (props.removable) {
779
983
  const { removable: _r2, removeLabel, onRemove, disabled: disabled2, size: _s2, style: style2, children: children2, ...rest2 } = props;
780
- return /* @__PURE__ */ jsxs5(View5, { ...rest2, style: [styles7.base, frame(false, false), disabled2 ? styles7.disabled : null, style2], children: [
781
- /* @__PURE__ */ jsx8(Label, { color: theme.textSecondary, size, children: children2 }),
782
- /* @__PURE__ */ jsx8(Pressable4, { role: "button", "aria-label": removeLabel, disabled: disabled2 ?? void 0, hitSlop: 10, onPress: onRemove, style: styles7.remove, children: /* @__PURE__ */ jsx8(Text5, { style: [styles7.cross, { color: theme.textSecondary }], children: "\xD7" }) })
984
+ return /* @__PURE__ */ jsxs7(View7, { ...rest2, style: [styles9.base, frame(false, false), disabled2 ? styles9.disabled : null, style2], children: [
985
+ /* @__PURE__ */ jsx10(Label, { color: theme.textSecondary, size, children: children2 }),
986
+ /* @__PURE__ */ jsx10(Pressable5, { role: "button", "aria-label": removeLabel, disabled: disabled2 ?? void 0, hitSlop: 10, onPress: onRemove, style: styles9.remove, children: /* @__PURE__ */ jsx10(Text5, { style: [styles9.cross, { color: theme.textSecondary }], children: "\xD7" }) })
783
987
  ] });
784
988
  }
785
989
  const { removable: _r, value, selected, defaultSelected: _d, onSelectedChange, disabled: ownDisabled, size: _s, style, children, ...rest } = props;
@@ -792,8 +996,8 @@ function ChipBase(props) {
792
996
  onSelectedChange?.(!on);
793
997
  };
794
998
  const single = group?.type === "single";
795
- return /* @__PURE__ */ jsx8(
796
- Pressable4,
999
+ return /* @__PURE__ */ jsx10(
1000
+ Pressable5,
797
1001
  {
798
1002
  role: single ? "radio" : "checkbox",
799
1003
  "aria-checked": on,
@@ -801,17 +1005,17 @@ function ChipBase(props) {
801
1005
  ...rest,
802
1006
  disabled,
803
1007
  onPress: press,
804
- style: ({ pressed }) => [styles7.base, frame(on, pressed), disabled ? styles7.disabled : null, style],
805
- children: /* @__PURE__ */ jsx8(Label, { color: on ? theme.textPrimary : theme.textSecondary, size, children })
1008
+ style: ({ pressed }) => [styles9.base, frame(on, pressed), disabled ? styles9.disabled : null, style],
1009
+ children: /* @__PURE__ */ jsx10(Label, { color: on ? theme.textPrimary : theme.textSecondary, size, children })
806
1010
  }
807
1011
  );
808
1012
  }
809
1013
  function ChipGroup(props) {
810
1014
  const { size, disabled, scrollable, "aria-label": label, style, children } = props;
811
1015
  const initial = props.type === "single" ? props.defaultValue ?? "" : props.defaultValue ?? [];
812
- const [own, setOwn] = React6.useState(initial);
1016
+ const [own, setOwn] = React8.useState(initial);
813
1017
  const current = props.value ?? own;
814
- const context = React6.useMemo(() => {
1018
+ const context = React8.useMemo(() => {
815
1019
  const list = Array.isArray(current) ? current : [current];
816
1020
  return {
817
1021
  type: props.type,
@@ -826,10 +1030,10 @@ function ChipGroup(props) {
826
1030
  };
827
1031
  }, [current, props.type, props.value, props.onValueChange, size, disabled]);
828
1032
  const a11y = { role: props.type === "single" ? "radiogroup" : "group", "aria-label": label };
829
- return /* @__PURE__ */ jsx8(ChipGroupContext.Provider, { value: context, children: scrollable ? /* @__PURE__ */ jsx8(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, ...a11y, style, contentContainerStyle: styles7.row, children }) : /* @__PURE__ */ jsx8(View5, { ...a11y, style: [styles7.row, styles7.wrap, style], children }) });
1033
+ return /* @__PURE__ */ jsx10(ChipGroupContext.Provider, { value: context, children: scrollable ? /* @__PURE__ */ jsx10(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, ...a11y, style, contentContainerStyle: styles9.row, children }) : /* @__PURE__ */ jsx10(View7, { ...a11y, style: [styles9.row, styles9.wrap, style], children }) });
830
1034
  }
831
1035
  var Chip = Object.assign(ChipBase, { Group: ChipGroup });
832
- var styles7 = StyleSheet7.create({
1036
+ var styles9 = StyleSheet9.create({
833
1037
  base: { flexDirection: "row", alignItems: "center", justifyContent: "center", gap: 6, paddingHorizontal: 14, borderWidth: 1, alignSelf: "flex-start" },
834
1038
  label: { fontWeight: "600" },
835
1039
  remove: { marginRight: -6, width: 24, height: 24, alignItems: "center", justifyContent: "center" },
@@ -840,30 +1044,30 @@ var styles7 = StyleSheet7.create({
840
1044
  });
841
1045
 
842
1046
  // src/native/combobox.tsx
843
- import * as React8 from "react";
844
- import { Pressable as Pressable6, ScrollView as ScrollView2, StyleSheet as StyleSheet9, Text as Text7, TextInput, View as View7 } from "react-native";
845
- import Svg3, { Path as Path2 } from "react-native-svg";
1047
+ import * as React10 from "react";
1048
+ import { Pressable as Pressable7, ScrollView as ScrollView2, StyleSheet as StyleSheet11, Text as Text7, TextInput, View as View9 } from "react-native";
1049
+ import Svg4, { Path as Path2 } from "react-native-svg";
846
1050
 
847
1051
  // src/native/dialog.tsx
848
- import * as React7 from "react";
849
- import { Animated as Animated2, Modal, Pressable as Pressable5, StyleSheet as StyleSheet8, Text as Text6, View as View6 } from "react-native";
850
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
1052
+ import * as React9 from "react";
1053
+ import { Animated as Animated2, Modal as Modal2, Pressable as Pressable6, StyleSheet as StyleSheet10, Text as Text6, View as View8 } from "react-native";
1054
+ import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
851
1055
  function Sheet({ open, onOpenChange, title, closeLabel = "Close", children, style }) {
852
1056
  const { theme, radius: radius3, motion: motion3 } = useTheme();
853
- const [rise] = React7.useState(() => new Animated2.Value(0));
854
- React7.useEffect(() => {
1057
+ const [rise] = React9.useState(() => new Animated2.Value(0));
1058
+ React9.useEffect(() => {
855
1059
  if (open) Animated2.timing(rise, { toValue: 1, duration: motion3.duration.base * 1.6, useNativeDriver: true }).start();
856
1060
  else rise.setValue(0);
857
1061
  }, [open, rise, motion3.duration.base]);
858
- return /* @__PURE__ */ jsx9(Modal, { transparent: true, visible: open, animationType: "none", onRequestClose: () => onOpenChange(false), statusBarTranslucent: true, children: /* @__PURE__ */ jsxs6(View6, { style: styles8.backdrop, children: [
859
- /* @__PURE__ */ jsx9(Animated2.View, { style: [StyleSheet8.absoluteFill, { opacity: rise }], children: /* @__PURE__ */ jsx9(Pressable5, { role: "button", "aria-label": closeLabel, onPress: () => onOpenChange(false), style: [StyleSheet8.absoluteFill, { backgroundColor: theme.scrim }] }) }),
860
- /* @__PURE__ */ jsxs6(
1062
+ return /* @__PURE__ */ jsx11(Modal2, { transparent: true, visible: open, animationType: "none", onRequestClose: () => onOpenChange(false), statusBarTranslucent: true, children: /* @__PURE__ */ jsxs8(View8, { style: styles10.backdrop, children: [
1063
+ /* @__PURE__ */ jsx11(Animated2.View, { style: [StyleSheet10.absoluteFill, { opacity: rise }], children: /* @__PURE__ */ jsx11(Pressable6, { role: "button", "aria-label": closeLabel, onPress: () => onOpenChange(false), style: [StyleSheet10.absoluteFill, { backgroundColor: theme.scrim }] }) }),
1064
+ /* @__PURE__ */ jsxs8(
861
1065
  Animated2.View,
862
1066
  {
863
1067
  role: "dialog",
864
1068
  "aria-label": title,
865
1069
  style: [
866
- styles8.sheet,
1070
+ styles10.sheet,
867
1071
  {
868
1072
  backgroundColor: theme.surface1,
869
1073
  borderColor: theme.borderDefault,
@@ -876,37 +1080,37 @@ function Sheet({ open, onOpenChange, title, closeLabel = "Close", children, styl
876
1080
  style
877
1081
  ],
878
1082
  children: [
879
- /* @__PURE__ */ jsx9(View6, { "aria-hidden": true, style: [styles8.grip, { backgroundColor: theme.borderStrong }] }),
880
- title ? /* @__PURE__ */ jsx9(Text6, { role: "heading", style: [styles8.title, { color: theme.textPrimary }], children: title }) : null,
1083
+ /* @__PURE__ */ jsx11(View8, { "aria-hidden": true, style: [styles10.grip, { backgroundColor: theme.borderStrong }] }),
1084
+ title ? /* @__PURE__ */ jsx11(Text6, { role: "heading", style: [styles10.title, { color: theme.textPrimary }], children: title }) : null,
881
1085
  children
882
1086
  ]
883
1087
  }
884
1088
  )
885
1089
  ] }) });
886
1090
  }
887
- var styles8 = StyleSheet8.create({
1091
+ var styles10 = StyleSheet10.create({
888
1092
  backdrop: { flex: 1, justifyContent: "flex-end" },
889
- sheet: { maxHeight: "85%", paddingHorizontal: 16, paddingTop: 8, paddingBottom: 28, gap: 12, borderWidth: StyleSheet8.hairlineWidth, shadowOpacity: 0.3, shadowRadius: 16, shadowOffset: { width: 0, height: -4 }, elevation: 12 },
1093
+ sheet: { maxHeight: "85%", paddingHorizontal: 16, paddingTop: 8, paddingBottom: 28, gap: 12, borderWidth: StyleSheet10.hairlineWidth, shadowOpacity: 0.3, shadowRadius: 16, shadowOffset: { width: 0, height: -4 }, elevation: 12 },
890
1094
  grip: { alignSelf: "center", width: 40, height: 5, borderRadius: 3, marginBottom: 4 },
891
1095
  title: { fontSize: 17, fontWeight: "700" }
892
1096
  });
893
1097
 
894
1098
  // src/native/combobox.tsx
895
- import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
1099
+ import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
896
1100
  function Chevron({ color }) {
897
- return /* @__PURE__ */ jsx10(Svg3, { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx10(Path2, { d: "m6 9 6 6 6-6" }) });
1101
+ return /* @__PURE__ */ jsx12(Svg4, { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx12(Path2, { d: "m6 9 6 6 6-6" }) });
898
1102
  }
899
1103
  function Tick({ color }) {
900
- return /* @__PURE__ */ jsx10(Svg3, { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: 2.6, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx10(Path2, { d: "M20 6 9 17l-5-5" }) });
1104
+ return /* @__PURE__ */ jsx12(Svg4, { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: 2.6, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx12(Path2, { d: "M20 6 9 17l-5-5" }) });
901
1105
  }
902
1106
  function Trigger({ shared, text, onPress, open }) {
903
1107
  const { theme, radius: radius3 } = useTheme();
904
1108
  const { label, placeholder, hint, error, disabled } = shared;
905
1109
  const caption = error ?? hint;
906
- return /* @__PURE__ */ jsxs7(View7, { style: [styles9.field, shared.style], children: [
907
- /* @__PURE__ */ jsx10(Text7, { style: [styles9.label, { color: theme.textSecondary }], children: label }),
908
- /* @__PURE__ */ jsxs7(
909
- Pressable6,
1110
+ return /* @__PURE__ */ jsxs9(View9, { style: [styles11.field, shared.style], children: [
1111
+ /* @__PURE__ */ jsx12(Text7, { style: [styles11.label, { color: theme.textSecondary }], children: label }),
1112
+ /* @__PURE__ */ jsxs9(
1113
+ Pressable7,
910
1114
  {
911
1115
  role: "button",
912
1116
  "aria-label": `${label}, ${text ?? placeholder ?? ""}`.replace(/, $/, ""),
@@ -916,22 +1120,22 @@ function Trigger({ shared, text, onPress, open }) {
916
1120
  accessibilityHint: caption,
917
1121
  disabled,
918
1122
  onPress,
919
- style: [styles9.trigger, { borderRadius: radius3.md, backgroundColor: theme.surface2, borderColor: error ? theme.danger : open ? theme.accent : theme.borderDefault }, disabled ? styles9.disabled : null],
1123
+ style: [styles11.trigger, { borderRadius: radius3.md, backgroundColor: theme.surface2, borderColor: error ? theme.danger : open ? theme.accent : theme.borderDefault }, disabled ? styles11.disabled : null],
920
1124
  children: [
921
- /* @__PURE__ */ jsx10(Text7, { numberOfLines: 1, style: [styles9.triggerText, { color: text ? theme.textPrimary : theme.textSecondary }], children: text ?? placeholder ?? "" }),
922
- /* @__PURE__ */ jsx10(Chevron, { color: theme.textSecondary })
1125
+ /* @__PURE__ */ jsx12(Text7, { numberOfLines: 1, style: [styles11.triggerText, { color: text ? theme.textPrimary : theme.textSecondary }], children: text ?? placeholder ?? "" }),
1126
+ /* @__PURE__ */ jsx12(Chevron, { color: theme.textSecondary })
923
1127
  ]
924
1128
  }
925
1129
  ),
926
- caption ? /* @__PURE__ */ jsx10(Text7, { role: error ? "alert" : void 0, "aria-live": error ? "polite" : void 0, style: [styles9.caption, { color: error ? theme.dangerText : theme.textSecondary }], children: caption }) : null
1130
+ caption ? /* @__PURE__ */ jsx12(Text7, { role: error ? "alert" : void 0, "aria-live": error ? "polite" : void 0, style: [styles11.caption, { color: error ? theme.dangerText : theme.textSecondary }], children: caption }) : null
927
1131
  ] });
928
1132
  }
929
1133
  function Options({ options, isChosen, onPick, multiple }) {
930
1134
  const { theme, radius: radius3, haptic } = useTheme();
931
- return /* @__PURE__ */ jsx10(ScrollView2, { role: multiple ? "list" : "radiogroup", keyboardShouldPersistTaps: "handled", style: styles9.options, children: options.map((o) => {
1135
+ return /* @__PURE__ */ jsx12(ScrollView2, { role: multiple ? "list" : "radiogroup", keyboardShouldPersistTaps: "handled", style: styles11.options, children: options.map((o) => {
932
1136
  const chosen = isChosen(o.value);
933
- return /* @__PURE__ */ jsxs7(
934
- Pressable6,
1137
+ return /* @__PURE__ */ jsxs9(
1138
+ Pressable7,
935
1139
  {
936
1140
  role: multiple ? "checkbox" : "radio",
937
1141
  "aria-checked": chosen,
@@ -942,13 +1146,13 @@ function Options({ options, isChosen, onPick, multiple }) {
942
1146
  haptic("selection");
943
1147
  onPick(o);
944
1148
  },
945
- style: ({ pressed }) => [styles9.option, { borderRadius: radius3.md, backgroundColor: chosen ? theme.accentSoft : pressed ? theme.surface3 : "transparent" }, o.disabled ? styles9.disabled : null],
1149
+ style: ({ pressed }) => [styles11.option, { borderRadius: radius3.md, backgroundColor: chosen ? theme.accentSoft : pressed ? theme.surface3 : "transparent" }, o.disabled ? styles11.disabled : null],
946
1150
  children: [
947
- /* @__PURE__ */ jsxs7(View7, { style: styles9.optionText, children: [
948
- /* @__PURE__ */ jsx10(Text7, { style: [styles9.optionLabel, { color: theme.textPrimary, fontWeight: chosen ? "700" : "500" }], children: o.label }),
949
- o.description ? /* @__PURE__ */ jsx10(Text7, { style: [styles9.caption, { color: theme.textSecondary }], children: o.description }) : null
1151
+ /* @__PURE__ */ jsxs9(View9, { style: styles11.optionText, children: [
1152
+ /* @__PURE__ */ jsx12(Text7, { style: [styles11.optionLabel, { color: theme.textPrimary, fontWeight: chosen ? "700" : "500" }], children: o.label }),
1153
+ o.description ? /* @__PURE__ */ jsx12(Text7, { style: [styles11.caption, { color: theme.textSecondary }], children: o.description }) : null
950
1154
  ] }),
951
- chosen ? /* @__PURE__ */ jsx10(Tick, { color: theme.accentText }) : null
1155
+ chosen ? /* @__PURE__ */ jsx12(Tick, { color: theme.accentText }) : null
952
1156
  ]
953
1157
  },
954
1158
  o.value
@@ -956,16 +1160,16 @@ function Options({ options, isChosen, onPick, multiple }) {
956
1160
  }) });
957
1161
  }
958
1162
  function Select({ options, value: valueProp, defaultValue = null, onValueChange, sheetTitle, ...shared }) {
959
- const [own, setOwn] = React8.useState(defaultValue);
1163
+ const [own, setOwn] = React10.useState(defaultValue);
960
1164
  const value = valueProp !== void 0 ? valueProp : own;
961
- const [open, setOpen] = React8.useState(false);
1165
+ const [open, setOpen] = React10.useState(false);
962
1166
  const close = () => {
963
1167
  setOpen(false);
964
1168
  shared.onBlur?.();
965
1169
  };
966
- return /* @__PURE__ */ jsxs7(Fragment2, { children: [
967
- /* @__PURE__ */ jsx10(Trigger, { shared, text: options.find((o) => o.value === value)?.label ?? null, open, onPress: () => setOpen(true) }),
968
- /* @__PURE__ */ jsx10(Sheet, { open, onOpenChange: (o) => o ? setOpen(true) : close(), title: sheetTitle ?? shared.label, children: /* @__PURE__ */ jsx10(
1170
+ return /* @__PURE__ */ jsxs9(Fragment3, { children: [
1171
+ /* @__PURE__ */ jsx12(Trigger, { shared, text: options.find((o) => o.value === value)?.label ?? null, open, onPress: () => setOpen(true) }),
1172
+ /* @__PURE__ */ jsx12(Sheet, { open, onOpenChange: (o) => o ? setOpen(true) : close(), title: sheetTitle ?? shared.label, children: /* @__PURE__ */ jsx12(
969
1173
  Options,
970
1174
  {
971
1175
  options,
@@ -983,13 +1187,13 @@ var comboboxLabels = { search: "Search", loading: "Searching\u2026", empty: "No
983
1187
  function Combobox({ options = [], onSearch, multiple, value, onValueChange, labels: given, ...shared }) {
984
1188
  const labels = { ...comboboxLabels, ...given };
985
1189
  const { theme, radius: radius3 } = useTheme();
986
- const [open, setOpen] = React8.useState(false);
987
- const [query, setQuery] = React8.useState("");
988
- const [found, setFound] = React8.useState(null);
989
- const [loading, setLoading] = React8.useState(false);
990
- const [seen, setSeen] = React8.useState({});
1190
+ const [open, setOpen] = React10.useState(false);
1191
+ const [query, setQuery] = React10.useState("");
1192
+ const [found, setFound] = React10.useState(null);
1193
+ const [loading, setLoading] = React10.useState(false);
1194
+ const [seen, setSeen] = React10.useState({});
991
1195
  const chosen = value == null ? [] : typeof value === "string" ? value ? [value] : [] : [...value];
992
- React8.useEffect(() => {
1196
+ React10.useEffect(() => {
993
1197
  if (!onSearch || !open) return;
994
1198
  const controller = new AbortController();
995
1199
  const timer2 = setTimeout(() => {
@@ -1013,10 +1217,10 @@ function Combobox({ options = [], onSearch, multiple, value, onValueChange, labe
1013
1217
  setQuery("");
1014
1218
  shared.onBlur?.();
1015
1219
  };
1016
- return /* @__PURE__ */ jsxs7(Fragment2, { children: [
1017
- /* @__PURE__ */ jsx10(Trigger, { shared, text: chosen.length ? chosen.map(labelOf).join(", ") : null, open, onPress: () => setOpen(true) }),
1018
- /* @__PURE__ */ jsxs7(Sheet, { open, onOpenChange: (o) => o ? setOpen(true) : close(), title: shared.label, children: [
1019
- /* @__PURE__ */ jsx10(
1220
+ return /* @__PURE__ */ jsxs9(Fragment3, { children: [
1221
+ /* @__PURE__ */ jsx12(Trigger, { shared, text: chosen.length ? chosen.map(labelOf).join(", ") : null, open, onPress: () => setOpen(true) }),
1222
+ /* @__PURE__ */ jsxs9(Sheet, { open, onOpenChange: (o) => o ? setOpen(true) : close(), title: shared.label, children: [
1223
+ /* @__PURE__ */ jsx12(
1020
1224
  TextInput,
1021
1225
  {
1022
1226
  "aria-label": labels.search,
@@ -1027,12 +1231,12 @@ function Combobox({ options = [], onSearch, multiple, value, onValueChange, labe
1027
1231
  autoFocus: true,
1028
1232
  autoCorrect: false,
1029
1233
  returnKeyType: "search",
1030
- style: [styles9.search, { borderRadius: radius3.md, backgroundColor: theme.surface2, borderColor: theme.borderDefault, color: theme.textPrimary }]
1234
+ style: [styles11.search, { borderRadius: radius3.md, backgroundColor: theme.surface2, borderColor: theme.borderDefault, color: theme.textPrimary }]
1031
1235
  }
1032
1236
  ),
1033
- loading ? /* @__PURE__ */ jsx10(Text7, { style: [styles9.caption, { color: theme.textSecondary }], children: labels.loading }) : null,
1034
- !loading && list.length === 0 ? /* @__PURE__ */ jsx10(Text7, { style: [styles9.caption, { color: theme.textSecondary }], children: labels.empty }) : null,
1035
- /* @__PURE__ */ jsx10(
1237
+ loading ? /* @__PURE__ */ jsx12(Text7, { style: [styles11.caption, { color: theme.textSecondary }], children: labels.loading }) : null,
1238
+ !loading && list.length === 0 ? /* @__PURE__ */ jsx12(Text7, { style: [styles11.caption, { color: theme.textSecondary }], children: labels.empty }) : null,
1239
+ /* @__PURE__ */ jsx12(
1036
1240
  Options,
1037
1241
  {
1038
1242
  options: list,
@@ -1048,11 +1252,11 @@ function Combobox({ options = [], onSearch, multiple, value, onValueChange, labe
1048
1252
  }
1049
1253
  }
1050
1254
  ),
1051
- multiple ? /* @__PURE__ */ jsx10(Pressable6, { role: "button", onPress: close, style: [styles9.done, { borderRadius: radius3.md, backgroundColor: theme.accent }], children: /* @__PURE__ */ jsx10(Text7, { style: [styles9.doneText, { color: theme.onAccent }], children: labels.done }) }) : null
1255
+ multiple ? /* @__PURE__ */ jsx12(Pressable7, { role: "button", onPress: close, style: [styles11.done, { borderRadius: radius3.md, backgroundColor: theme.accent }], children: /* @__PURE__ */ jsx12(Text7, { style: [styles11.doneText, { color: theme.onAccent }], children: labels.done }) }) : null
1052
1256
  ] })
1053
1257
  ] });
1054
1258
  }
1055
- var styles9 = StyleSheet9.create({
1259
+ var styles11 = StyleSheet11.create({
1056
1260
  field: { gap: 6, alignSelf: "stretch" },
1057
1261
  label: { fontSize: 12, lineHeight: 16, fontWeight: "600" },
1058
1262
  trigger: { minHeight: 48, flexDirection: "row", alignItems: "center", gap: 8, paddingHorizontal: 14, borderWidth: 1 },
@@ -1069,9 +1273,9 @@ var styles9 = StyleSheet9.create({
1069
1273
  });
1070
1274
 
1071
1275
  // src/native/countdown.tsx
1072
- import * as React9 from "react";
1073
- import { Animated as Animated3, StyleSheet as StyleSheet10, Text as Text8 } from "react-native";
1074
- import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
1276
+ import * as React11 from "react";
1277
+ import { Animated as Animated3, StyleSheet as StyleSheet12, Text as Text8 } from "react-native";
1278
+ import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
1075
1279
  var FONT = { sm: 14, md: 20, lg: 32 };
1076
1280
  function Countdown({ target, skewMs = 0, units, urgentBelowMs = 6e4, size = "md", label, showLabel = false, style }) {
1077
1281
  const { theme, fonts } = useTheme();
@@ -1079,8 +1283,8 @@ function Countdown({ target, skewMs = 0, units, urgentBelowMs = 6e4, size = "md"
1079
1283
  const ms = useCountdown(target, skewMs);
1080
1284
  const urgent = ms > 0 && ms < urgentBelowMs;
1081
1285
  const parts = countdownParts(ms, units);
1082
- const [opacity] = React9.useState(() => new Animated3.Value(1));
1083
- React9.useEffect(() => {
1286
+ const [opacity] = React11.useState(() => new Animated3.Value(1));
1287
+ React11.useEffect(() => {
1084
1288
  if (!urgent || reduce) return;
1085
1289
  const loop = Animated3.loop(
1086
1290
  Animated3.sequence([
@@ -1096,24 +1300,24 @@ function Countdown({ target, skewMs = 0, units, urgentBelowMs = 6e4, size = "md"
1096
1300
  }, [urgent, reduce, opacity]);
1097
1301
  const color = urgent ? theme.dangerText : theme.textPrimary;
1098
1302
  const text = parts.map(([value, unit]) => `${String(value).padStart(2, "0")}${unit}`).join(" ");
1099
- return /* @__PURE__ */ jsxs8(
1303
+ return /* @__PURE__ */ jsxs10(
1100
1304
  Animated3.View,
1101
1305
  {
1102
1306
  accessible: true,
1103
1307
  role: "timer",
1104
1308
  "aria-label": `${label} ${text}`,
1105
- style: [styles10.root, style],
1309
+ style: [styles12.root, style],
1106
1310
  children: [
1107
- showLabel ? /* @__PURE__ */ jsx11(Text8, { style: [styles10.label, { color: theme.textSecondary, fontSize: Math.max(11, Math.round(FONT[size] * 0.6)) }], children: label }) : null,
1108
- parts.map(([value, unit], i) => /* @__PURE__ */ jsxs8(Animated3.View, { style: [styles10.segment, urgent && i === parts.length - 1 ? { opacity } : null], children: [
1109
- /* @__PURE__ */ jsx11(Text8, { style: [styles10.value, { color, fontSize: FONT[size] }, fonts.display ? { fontFamily: fonts.display } : null], children: String(value).padStart(2, "0") }),
1110
- /* @__PURE__ */ jsx11(Text8, { style: [styles10.unit, { color: theme.textSecondary, fontSize: Math.round(FONT[size] / 2) }], children: unit })
1311
+ showLabel ? /* @__PURE__ */ jsx13(Text8, { style: [styles12.label, { color: theme.textSecondary, fontSize: Math.max(11, Math.round(FONT[size] * 0.6)) }], children: label }) : null,
1312
+ parts.map(([value, unit], i) => /* @__PURE__ */ jsxs10(Animated3.View, { style: [styles12.segment, urgent && i === parts.length - 1 ? { opacity } : null], children: [
1313
+ /* @__PURE__ */ jsx13(Text8, { style: [styles12.value, { color, fontSize: FONT[size] }, fonts.display ? { fontFamily: fonts.display } : null], children: String(value).padStart(2, "0") }),
1314
+ /* @__PURE__ */ jsx13(Text8, { style: [styles12.unit, { color: theme.textSecondary, fontSize: Math.round(FONT[size] / 2) }], children: unit })
1111
1315
  ] }, unit))
1112
1316
  ]
1113
1317
  }
1114
1318
  );
1115
1319
  }
1116
- var styles10 = StyleSheet10.create({
1320
+ var styles12 = StyleSheet12.create({
1117
1321
  root: { flexDirection: "row", alignItems: "baseline", gap: 6 },
1118
1322
  segment: { flexDirection: "row", alignItems: "baseline" },
1119
1323
  value: { fontWeight: "900", fontVariant: ["tabular-nums"], letterSpacing: -0.3 },
@@ -1122,18 +1326,18 @@ var styles10 = StyleSheet10.create({
1122
1326
  });
1123
1327
 
1124
1328
  // src/native/date-picker.tsx
1125
- import * as React10 from "react";
1126
- import { Platform, StyleSheet as StyleSheet11, Text as Text9, TextInput as TextInput2, View as View8 } from "react-native";
1127
- import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
1329
+ import * as React12 from "react";
1330
+ import { Platform, StyleSheet as StyleSheet13, Text as Text9, TextInput as TextInput2, View as View10 } from "react-native";
1331
+ import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
1128
1332
  var LENGTH = DATE_PART_LENGTH;
1129
1333
  var dateFieldLabels = { day: "Day", month: "Month", year: "Year" };
1130
1334
  function DateField({ label, hint, error, value, defaultValue, onValueChange, onBlur, locale = "en-US", labels: given, autoComplete, disabled, inputRef, onSubmitEditing, returnKeyType = "done", style }) {
1131
1335
  const { theme, radius: radius3 } = useTheme();
1132
1336
  const labels = { ...dateFieldLabels, ...given };
1133
- const order = React10.useMemo(() => datePartsOrder(locale), [locale]);
1134
- const [parts, setParts] = React10.useState(() => splitDate(value ?? defaultValue));
1135
- const [focused, setFocused] = React10.useState(null);
1136
- const refs = { day: React10.useRef(null), month: React10.useRef(null), year: React10.useRef(null) };
1337
+ const order = React12.useMemo(() => datePartsOrder(locale), [locale]);
1338
+ const [parts, setParts] = React12.useState(() => splitDate(value ?? defaultValue));
1339
+ const [focused, setFocused] = React12.useState(null);
1340
+ const refs = { day: React12.useRef(null), month: React12.useRef(null), year: React12.useRef(null) };
1137
1341
  if (value !== void 0 && value !== composeDate(parts) && composeDate(splitDate(value)) === value) setParts(splitDate(value));
1138
1342
  const caption = error ?? hint;
1139
1343
  const change = (part, text) => {
@@ -1144,11 +1348,11 @@ function DateField({ label, hint, error, value, defaultValue, onValueChange, onB
1144
1348
  const following = order[order.indexOf(part) + 1];
1145
1349
  if (digits.length === LENGTH[part] && following) refs[following].current?.focus();
1146
1350
  };
1147
- return /* @__PURE__ */ jsxs9(View8, { role: "group", "aria-label": label, style: [styles11.root, disabled ? styles11.disabled : null, style], children: [
1148
- /* @__PURE__ */ jsx12(Text9, { style: [styles11.label, { color: theme.textSecondary }], children: label }),
1149
- /* @__PURE__ */ jsx12(View8, { style: styles11.row, children: order.map((part, i) => /* @__PURE__ */ jsxs9(View8, { style: part === "year" ? styles11.yearBox : styles11.box, children: [
1150
- /* @__PURE__ */ jsx12(Text9, { style: [styles11.part, { color: theme.textSecondary }], children: labels[part] }),
1151
- /* @__PURE__ */ jsx12(
1351
+ return /* @__PURE__ */ jsxs11(View10, { role: "group", "aria-label": label, style: [styles13.root, disabled ? styles13.disabled : null, style], children: [
1352
+ /* @__PURE__ */ jsx14(Text9, { style: [styles13.label, { color: theme.textSecondary }], children: label }),
1353
+ /* @__PURE__ */ jsx14(View10, { style: styles13.row, children: order.map((part, i) => /* @__PURE__ */ jsxs11(View10, { style: part === "year" ? styles13.yearBox : styles13.box, children: [
1354
+ /* @__PURE__ */ jsx14(Text9, { style: [styles13.part, { color: theme.textSecondary }], children: labels[part] }),
1355
+ /* @__PURE__ */ jsx14(
1152
1356
  TextInput2,
1153
1357
  {
1154
1358
  ref: (node) => {
@@ -1180,16 +1384,16 @@ function DateField({ label, hint, error, value, defaultValue, onValueChange, onB
1180
1384
  if (i === order.length - 1) onBlur?.();
1181
1385
  },
1182
1386
  style: [
1183
- styles11.input,
1387
+ styles13.input,
1184
1388
  { color: theme.textPrimary, backgroundColor: theme.surface2, borderRadius: radius3.md, borderColor: error ? theme.danger : focused === part ? theme.accent : theme.borderDefault }
1185
1389
  ]
1186
1390
  }
1187
1391
  )
1188
1392
  ] }, part)) }),
1189
- caption ? /* @__PURE__ */ jsx12(Text9, { role: error ? "alert" : void 0, "aria-live": error ? "polite" : void 0, style: [styles11.caption, { color: error ? theme.dangerText : theme.textSecondary }], children: caption }) : null
1393
+ caption ? /* @__PURE__ */ jsx14(Text9, { role: error ? "alert" : void 0, "aria-live": error ? "polite" : void 0, style: [styles13.caption, { color: error ? theme.dangerText : theme.textSecondary }], children: caption }) : null
1190
1394
  ] });
1191
1395
  }
1192
- var styles11 = StyleSheet11.create({
1396
+ var styles13 = StyleSheet13.create({
1193
1397
  root: { gap: 6, alignSelf: "stretch" },
1194
1398
  label: { fontSize: 12, lineHeight: 16, fontWeight: "600" },
1195
1399
  row: { flexDirection: "row", gap: 10 },
@@ -1202,26 +1406,26 @@ var styles11 = StyleSheet11.create({
1202
1406
  });
1203
1407
 
1204
1408
  // src/native/date-time.tsx
1205
- import * as React12 from "react";
1206
- import { Pressable as Pressable8, ScrollView as ScrollView4, StyleSheet as StyleSheet13, Text as Text11, View as View10 } from "react-native";
1207
- import Svg4, { Path as Path3 } from "react-native-svg";
1409
+ import * as React14 from "react";
1410
+ import { Pressable as Pressable9, ScrollView as ScrollView4, StyleSheet as StyleSheet15, Text as Text11, View as View12 } from "react-native";
1411
+ import Svg5, { Path as Path3 } from "react-native-svg";
1208
1412
 
1209
1413
  // src/native/wheel.tsx
1210
- import * as React11 from "react";
1211
- import { Pressable as Pressable7, ScrollView as ScrollView3, StyleSheet as StyleSheet12, Text as Text10, View as View9 } from "react-native";
1212
- import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
1414
+ import * as React13 from "react";
1415
+ import { Pressable as Pressable8, ScrollView as ScrollView3, StyleSheet as StyleSheet14, Text as Text10, View as View11 } from "react-native";
1416
+ import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
1213
1417
  var ITEM = 44;
1214
- var FrameContext = React11.createContext({ visible: 5, unset: false });
1418
+ var FrameContext = React13.createContext({ visible: 5, unset: false });
1215
1419
  function WheelPicker({ label, children, visible = 5, invalid, unset = false, style }) {
1216
1420
  const { theme, radius: radius3 } = useTheme();
1217
- return /* @__PURE__ */ jsx13(FrameContext.Provider, { value: React11.useMemo(() => ({ visible, unset }), [visible, unset]), children: /* @__PURE__ */ jsxs10(
1218
- View9,
1421
+ return /* @__PURE__ */ jsx15(FrameContext.Provider, { value: React13.useMemo(() => ({ visible, unset }), [visible, unset]), children: /* @__PURE__ */ jsxs12(
1422
+ View11,
1219
1423
  {
1220
1424
  role: "group",
1221
1425
  "aria-label": label,
1222
- style: [styles12.root, { height: ITEM * visible, borderRadius: radius3.xl, backgroundColor: theme.surface1, borderColor: invalid ? theme.danger : theme.borderDefault }, style],
1426
+ style: [styles14.root, { height: ITEM * visible, borderRadius: radius3.xl, backgroundColor: theme.surface1, borderColor: invalid ? theme.danger : theme.borderDefault }, style],
1223
1427
  children: [
1224
- /* @__PURE__ */ jsx13(View9, { pointerEvents: "none", style: [styles12.band, { top: ITEM * (visible - 1) / 2, height: ITEM, borderRadius: radius3.lg, backgroundColor: theme.surface3, borderColor: theme.borderSubtle }] }),
1428
+ /* @__PURE__ */ jsx15(View11, { pointerEvents: "none", style: [styles14.band, { top: ITEM * (visible - 1) / 2, height: ITEM, borderRadius: radius3.lg, backgroundColor: theme.surface3, borderColor: theme.borderSubtle }] }),
1225
1429
  children
1226
1430
  ]
1227
1431
  }
@@ -1229,7 +1433,7 @@ function WheelPicker({ label, children, visible = 5, invalid, unset = false, sty
1229
1433
  }
1230
1434
  function WheelDivider({ children }) {
1231
1435
  const { theme } = useTheme();
1232
- return /* @__PURE__ */ jsx13(Text10, { "aria-hidden": true, style: [styles12.divider, { color: theme.textSecondary }], children });
1436
+ return /* @__PURE__ */ jsx15(Text10, { "aria-hidden": true, style: [styles14.divider, { color: theme.textSecondary }], children });
1233
1437
  }
1234
1438
  var nearestEnabled = (options, index) => {
1235
1439
  for (let d = 0; d < options.length; d++) {
@@ -1240,14 +1444,14 @@ var nearestEnabled = (options, index) => {
1240
1444
  };
1241
1445
  function Wheel({ label, options, value: valueProp, defaultValue, onValueChange, disabled, style }) {
1242
1446
  const { theme, haptic } = useTheme();
1243
- const { visible, unset } = React11.useContext(FrameContext);
1244
- const [own, setOwn] = React11.useState(defaultValue ?? options[0]?.value ?? "");
1447
+ const { visible, unset } = React13.useContext(FrameContext);
1448
+ const [own, setOwn] = React13.useState(defaultValue ?? options[0]?.value ?? "");
1245
1449
  const value = valueProp ?? own;
1246
1450
  const index = Math.max(0, options.findIndex((o) => o.value === value));
1247
- const scroller = React11.useRef(null);
1248
- const passing = React11.useRef(index);
1249
- const [shown, setShown] = React11.useState(index);
1250
- const [seen, setSeen] = React11.useState(index);
1451
+ const scroller = React13.useRef(null);
1452
+ const passing = React13.useRef(index);
1453
+ const [shown, setShown] = React13.useState(index);
1454
+ const [seen, setSeen] = React13.useState(index);
1251
1455
  if (seen !== index) {
1252
1456
  setSeen(index);
1253
1457
  setShown(index);
@@ -1260,7 +1464,7 @@ function Wheel({ label, options, value: valueProp, defaultValue, onValueChange,
1260
1464
  if (valueProp === void 0) setOwn(option.value);
1261
1465
  if (option.value !== value) onValueChange?.(option.value);
1262
1466
  };
1263
- React11.useEffect(() => {
1467
+ React13.useEffect(() => {
1264
1468
  passing.current = index;
1265
1469
  scroller.current?.scrollTo({ y: index * ITEM, animated: false });
1266
1470
  }, [index]);
@@ -1279,8 +1483,8 @@ function Wheel({ label, options, value: valueProp, defaultValue, onValueChange,
1279
1483
  if (options[i]) commit(i);
1280
1484
  };
1281
1485
  const pad = (visible - 1) / 2 * ITEM;
1282
- return /* @__PURE__ */ jsx13(
1283
- View9,
1486
+ return /* @__PURE__ */ jsx15(
1487
+ View11,
1284
1488
  {
1285
1489
  accessible: true,
1286
1490
  role: "spinbutton",
@@ -1292,8 +1496,8 @@ function Wheel({ label, options, value: valueProp, defaultValue, onValueChange,
1292
1496
  "aria-disabled": disabled || void 0,
1293
1497
  accessibilityActions: [{ name: "increment" }, { name: "decrement" }],
1294
1498
  onAccessibilityAction: (e) => step(e.nativeEvent.actionName === "increment" ? 1 : -1),
1295
- style: [styles12.column, disabled ? styles12.disabled : null, style],
1296
- children: /* @__PURE__ */ jsx13(
1499
+ style: [styles14.column, disabled ? styles14.disabled : null, style],
1500
+ children: /* @__PURE__ */ jsx15(
1297
1501
  ScrollView3,
1298
1502
  {
1299
1503
  ref: scroller,
@@ -1313,12 +1517,12 @@ function Wheel({ label, options, value: valueProp, defaultValue, onValueChange,
1313
1517
  },
1314
1518
  children: options.map((o, i) => {
1315
1519
  const distance = Math.abs(i - shown);
1316
- return /* @__PURE__ */ jsx13(Pressable7, { focusable: false, tabIndex: -1, disabled: disabled || o.disabled, onPress: () => commit(i), style: [styles12.item, { height: ITEM }], children: /* @__PURE__ */ jsx13(
1520
+ return /* @__PURE__ */ jsx15(Pressable8, { focusable: false, tabIndex: -1, disabled: disabled || o.disabled, onPress: () => commit(i), style: [styles14.item, { height: ITEM }], children: /* @__PURE__ */ jsx15(
1317
1521
  Text10,
1318
1522
  {
1319
1523
  numberOfLines: 1,
1320
1524
  style: [
1321
- styles12.itemText,
1525
+ styles14.itemText,
1322
1526
  {
1323
1527
  color: o.disabled ? theme.textMuted : i === shown && !unset ? theme.textPrimary : theme.textSecondary,
1324
1528
  fontWeight: i === shown && !unset ? "600" : "400",
@@ -1336,9 +1540,9 @@ function Wheel({ label, options, value: valueProp, defaultValue, onValueChange,
1336
1540
  }
1337
1541
  );
1338
1542
  }
1339
- var styles12 = StyleSheet12.create({
1340
- root: { flexDirection: "row", alignItems: "stretch", borderWidth: StyleSheet12.hairlineWidth, paddingHorizontal: 6, gap: 4, overflow: "hidden", alignSelf: "flex-start" },
1341
- band: { position: "absolute", left: 6, right: 6, borderWidth: StyleSheet12.hairlineWidth },
1543
+ var styles14 = StyleSheet14.create({
1544
+ root: { flexDirection: "row", alignItems: "stretch", borderWidth: StyleSheet14.hairlineWidth, paddingHorizontal: 6, gap: 4, overflow: "hidden", alignSelf: "flex-start" },
1545
+ band: { position: "absolute", left: 6, right: 6, borderWidth: StyleSheet14.hairlineWidth },
1342
1546
  column: { minWidth: 56, flexGrow: 1 },
1343
1547
  item: { alignItems: "center", justifyContent: "center", paddingHorizontal: 8 },
1344
1548
  itemText: { fontSize: 18, fontVariant: ["tabular-nums"] },
@@ -1347,19 +1551,19 @@ var styles12 = StyleSheet12.create({
1347
1551
  });
1348
1552
 
1349
1553
  // src/native/date-time.tsx
1350
- import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
1554
+ import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
1351
1555
  var longDate = (locale, iso) => new Intl.DateTimeFormat(locale, { dateStyle: "long" }).format(toLocalDate(iso));
1352
1556
  var useOwn = (value, initial) => {
1353
- const [own, setOwn] = React12.useState(initial);
1557
+ const [own, setOwn] = React14.useState(initial);
1354
1558
  return [value !== void 0 ? value : own, (next) => value === void 0 && setOwn(next)];
1355
1559
  };
1356
1560
  function Chevron2({ direction, color }) {
1357
- return /* @__PURE__ */ jsx14(Svg4, { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx14(Path3, { d: direction === "left" ? "m15 18-6-6 6-6" : "m9 18 6-6-6-6" }) });
1561
+ return /* @__PURE__ */ jsx16(Svg5, { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx16(Path3, { d: direction === "left" ? "m15 18-6-6 6-6" : "m9 18 6-6-6-6" }) });
1358
1562
  }
1359
1563
  function NavButton({ label, direction, disabled, onPress }) {
1360
1564
  const { theme, radius: radius3 } = useTheme();
1361
- return /* @__PURE__ */ jsx14(
1362
- Pressable8,
1565
+ return /* @__PURE__ */ jsx16(
1566
+ Pressable9,
1363
1567
  {
1364
1568
  role: "button",
1365
1569
  "aria-label": label,
@@ -1367,49 +1571,49 @@ function NavButton({ label, direction, disabled, onPress }) {
1367
1571
  disabled,
1368
1572
  hitSlop: 6,
1369
1573
  onPress,
1370
- style: ({ pressed }) => [styles13.nav, { borderRadius: radius3.md, backgroundColor: pressed ? theme.surface3 : theme.surface2, borderColor: theme.borderSubtle }, disabled ? styles13.disabled : null],
1371
- children: /* @__PURE__ */ jsx14(Chevron2, { direction, color: theme.textSecondary })
1574
+ style: ({ pressed }) => [styles15.nav, { borderRadius: radius3.md, backgroundColor: pressed ? theme.surface3 : theme.surface2, borderColor: theme.borderSubtle }, disabled ? styles15.disabled : null],
1575
+ children: /* @__PURE__ */ jsx16(Chevron2, { direction, color: theme.textSecondary })
1372
1576
  }
1373
1577
  );
1374
1578
  }
1375
1579
  function Node({ color, style }) {
1376
- return /* @__PURE__ */ jsx14(View10, { "aria-hidden": true, style: [styles13.node, { backgroundColor: color }, style] });
1580
+ return /* @__PURE__ */ jsx16(View12, { "aria-hidden": true, style: [styles15.node, { backgroundColor: color }, style] });
1377
1581
  }
1378
1582
  var calendarLabels = { previousMonth: "Previous month", nextMonth: "Next month" };
1379
1583
  function Calendar({ locale, value, range, onSelect, defaultMonth, min, max, isDateDisabled, weekStartsOn, today: todayProp, labels: given, style }) {
1380
1584
  const labels = { ...calendarLabels, ...given };
1381
1585
  const { theme, radius: radius3, haptic } = useTheme();
1382
1586
  const today = todayProp ?? todayIso();
1383
- const [month, setMonth] = React12.useState(`${(defaultMonth ?? value ?? range?.start ?? today).slice(0, 7)}-01`);
1587
+ const [month, setMonth] = React14.useState(`${(defaultMonth ?? value ?? range?.start ?? today).slice(0, 7)}-01`);
1384
1588
  const start = weekStartsOn ?? weekStartOf(locale);
1385
1589
  const weeks = monthGrid(month, start);
1386
1590
  const weekday = new Intl.DateTimeFormat(locale, { weekday: "narrow" });
1387
1591
  const title = new Intl.DateTimeFormat(locale, { month: "long", year: "numeric" }).format(toLocalDate(month));
1388
1592
  const [lo, hi] = range?.end ? range.start <= range.end ? [range.start, range.end] : [range.end, range.start] : [null, null];
1389
1593
  const off = (iso) => Boolean(min && iso < min || max && iso > max || isDateDisabled?.(iso));
1390
- return /* @__PURE__ */ jsxs11(View10, { style: [styles13.calendar, { backgroundColor: theme.surface1, borderColor: theme.borderDefault, borderRadius: radius3.xl }, style], children: [
1391
- /* @__PURE__ */ jsxs11(View10, { style: styles13.header, children: [
1392
- /* @__PURE__ */ jsx14(NavButton, { label: labels.previousMonth, direction: "left", disabled: Boolean(min && addDays(month, -1) < min), onPress: () => setMonth(addMonths(month, -1)) }),
1393
- /* @__PURE__ */ jsx14(Text11, { role: "heading", "aria-live": "polite", style: [styles13.title, { color: theme.textPrimary }], children: title }),
1394
- /* @__PURE__ */ jsx14(NavButton, { label: labels.nextMonth, direction: "right", disabled: Boolean(max && addMonths(month, 1) > max), onPress: () => setMonth(addMonths(month, 1)) })
1594
+ return /* @__PURE__ */ jsxs13(View12, { style: [styles15.calendar, { backgroundColor: theme.surface1, borderColor: theme.borderDefault, borderRadius: radius3.xl }, style], children: [
1595
+ /* @__PURE__ */ jsxs13(View12, { style: styles15.header, children: [
1596
+ /* @__PURE__ */ jsx16(NavButton, { label: labels.previousMonth, direction: "left", disabled: Boolean(min && addDays(month, -1) < min), onPress: () => setMonth(addMonths(month, -1)) }),
1597
+ /* @__PURE__ */ jsx16(Text11, { role: "heading", "aria-live": "polite", style: [styles15.title, { color: theme.textPrimary }], children: title }),
1598
+ /* @__PURE__ */ jsx16(NavButton, { label: labels.nextMonth, direction: "right", disabled: Boolean(max && addMonths(month, 1) > max), onPress: () => setMonth(addMonths(month, 1)) })
1395
1599
  ] }),
1396
- /* @__PURE__ */ jsx14(View10, { style: styles13.week, "aria-hidden": true, children: weeks[0].map((iso) => /* @__PURE__ */ jsx14(Text11, { style: [styles13.weekday, { color: theme.textSecondary }], children: weekday.format(toLocalDate(iso)) }, iso)) }),
1397
- /* @__PURE__ */ jsx14(View10, { role: "radiogroup", "aria-label": title, children: weeks.map((week) => /* @__PURE__ */ jsx14(View10, { style: styles13.week, children: week.map((iso) => {
1600
+ /* @__PURE__ */ jsx16(View12, { style: styles15.week, "aria-hidden": true, children: weeks[0].map((iso) => /* @__PURE__ */ jsx16(Text11, { style: [styles15.weekday, { color: theme.textSecondary }], children: weekday.format(toLocalDate(iso)) }, iso)) }),
1601
+ /* @__PURE__ */ jsx16(View12, { role: "radiogroup", "aria-label": title, children: weeks.map((week) => /* @__PURE__ */ jsx16(View12, { style: styles15.week, children: week.map((iso) => {
1398
1602
  const outside = iso.slice(0, 7) !== month.slice(0, 7);
1399
1603
  const selected = iso === value || Boolean(range && (iso === range.start || iso === range.end));
1400
1604
  const disabled = off(iso);
1401
1605
  const band = lo && hi && lo !== hi && iso >= lo && iso <= hi;
1402
- return /* @__PURE__ */ jsx14(
1403
- View10,
1606
+ return /* @__PURE__ */ jsx16(
1607
+ View12,
1404
1608
  {
1405
1609
  style: [
1406
- styles13.cell,
1610
+ styles15.cell,
1407
1611
  band ? { backgroundColor: theme.accentSoft } : null,
1408
1612
  band && iso === lo ? { borderTopLeftRadius: radius3.lg, borderBottomLeftRadius: radius3.lg } : null,
1409
1613
  band && iso === hi ? { borderTopRightRadius: radius3.lg, borderBottomRightRadius: radius3.lg } : null
1410
1614
  ],
1411
- children: /* @__PURE__ */ jsxs11(
1412
- Pressable8,
1615
+ children: /* @__PURE__ */ jsxs13(
1616
+ Pressable9,
1413
1617
  {
1414
1618
  role: "radio",
1415
1619
  "aria-label": longDate(locale, iso),
@@ -1422,16 +1626,16 @@ function Calendar({ locale, value, range, onSelect, defaultMonth, min, max, isDa
1422
1626
  onSelect?.(iso);
1423
1627
  },
1424
1628
  style: ({ pressed }) => [
1425
- styles13.day,
1629
+ styles15.day,
1426
1630
  { borderRadius: radius3.lg },
1427
1631
  selected ? { backgroundColor: theme.accent } : pressed ? { backgroundColor: theme.surface3 } : null
1428
1632
  ],
1429
1633
  children: [
1430
- /* @__PURE__ */ jsx14(
1634
+ /* @__PURE__ */ jsx16(
1431
1635
  Text11,
1432
1636
  {
1433
1637
  style: [
1434
- styles13.dayText,
1638
+ styles15.dayText,
1435
1639
  {
1436
1640
  color: selected ? theme.onAccent : disabled ? theme.textMuted : iso === today ? theme.accentText : outside ? theme.textSecondary : theme.textPrimary,
1437
1641
  fontWeight: selected || iso === today ? "700" : "400",
@@ -1441,7 +1645,7 @@ function Calendar({ locale, value, range, onSelect, defaultMonth, min, max, isDa
1441
1645
  children: Number(iso.slice(8))
1442
1646
  }
1443
1647
  ),
1444
- iso === today ? /* @__PURE__ */ jsx14(Node, { color: selected ? theme.onAccent : theme.accent, style: styles13.todayNode }) : null
1648
+ iso === today ? /* @__PURE__ */ jsx16(Node, { color: selected ? theme.onAccent : theme.accent, style: styles15.todayNode }) : null
1445
1649
  ]
1446
1650
  }
1447
1651
  )
@@ -1453,21 +1657,21 @@ function Calendar({ locale, value, range, onSelect, defaultMonth, min, max, isDa
1453
1657
  }
1454
1658
  function MonthPicker({ locale, value, onValueChange, min, max, labels, style }) {
1455
1659
  const { theme, radius: radius3, haptic } = useTheme();
1456
- const [year, setYear] = React12.useState(Number((value ?? todayIso()).slice(0, 4)));
1660
+ const [year, setYear] = React14.useState(Number((value ?? todayIso()).slice(0, 4)));
1457
1661
  const names = monthNames(locale, "short").map((n) => n.replace(/\.$/, ""));
1458
1662
  const long = monthNames(locale, "long");
1459
- return /* @__PURE__ */ jsxs11(View10, { style: [styles13.calendar, { backgroundColor: theme.surface1, borderColor: theme.borderDefault, borderRadius: radius3.xl }, style], children: [
1460
- /* @__PURE__ */ jsxs11(View10, { style: styles13.header, children: [
1461
- /* @__PURE__ */ jsx14(NavButton, { label: labels?.previousYear ?? "Previous year", direction: "left", disabled: Boolean(min && year - 1 < Number(min.slice(0, 4))), onPress: () => setYear(year - 1) }),
1462
- /* @__PURE__ */ jsx14(Text11, { role: "heading", "aria-live": "polite", style: [styles13.title, { color: theme.textPrimary }], children: year }),
1463
- /* @__PURE__ */ jsx14(NavButton, { label: labels?.nextYear ?? "Next year", direction: "right", disabled: Boolean(max && year + 1 > Number(max.slice(0, 4))), onPress: () => setYear(year + 1) })
1663
+ return /* @__PURE__ */ jsxs13(View12, { style: [styles15.calendar, { backgroundColor: theme.surface1, borderColor: theme.borderDefault, borderRadius: radius3.xl }, style], children: [
1664
+ /* @__PURE__ */ jsxs13(View12, { style: styles15.header, children: [
1665
+ /* @__PURE__ */ jsx16(NavButton, { label: labels?.previousYear ?? "Previous year", direction: "left", disabled: Boolean(min && year - 1 < Number(min.slice(0, 4))), onPress: () => setYear(year - 1) }),
1666
+ /* @__PURE__ */ jsx16(Text11, { role: "heading", "aria-live": "polite", style: [styles15.title, { color: theme.textPrimary }], children: year }),
1667
+ /* @__PURE__ */ jsx16(NavButton, { label: labels?.nextYear ?? "Next year", direction: "right", disabled: Boolean(max && year + 1 > Number(max.slice(0, 4))), onPress: () => setYear(year + 1) })
1464
1668
  ] }),
1465
- /* @__PURE__ */ jsx14(View10, { role: "radiogroup", "aria-label": String(year), style: styles13.months, children: names.map((name, i) => {
1669
+ /* @__PURE__ */ jsx16(View12, { role: "radiogroup", "aria-label": String(year), style: styles15.months, children: names.map((name, i) => {
1466
1670
  const id = `${year}-${String(i + 1).padStart(2, "0")}`;
1467
1671
  const selected = id === value;
1468
1672
  const disabled = Boolean(min && id < min || max && id > max);
1469
- return /* @__PURE__ */ jsx14(
1470
- Pressable8,
1673
+ return /* @__PURE__ */ jsx16(
1674
+ Pressable9,
1471
1675
  {
1472
1676
  role: "radio",
1473
1677
  "aria-checked": selected,
@@ -1478,8 +1682,8 @@ function MonthPicker({ locale, value, onValueChange, min, max, labels, style })
1478
1682
  haptic("selection");
1479
1683
  onValueChange?.(id);
1480
1684
  },
1481
- style: ({ pressed }) => [styles13.month, { borderRadius: radius3.lg, backgroundColor: selected ? theme.accent : pressed ? theme.surface3 : "transparent" }, disabled ? styles13.disabled : null],
1482
- children: /* @__PURE__ */ jsx14(Text11, { style: [styles13.monthText, { color: selected ? theme.onAccent : theme.textPrimary, fontWeight: selected ? "700" : "500" }], children: name })
1685
+ style: ({ pressed }) => [styles15.month, { borderRadius: radius3.lg, backgroundColor: selected ? theme.accent : pressed ? theme.surface3 : "transparent" }, disabled ? styles15.disabled : null],
1686
+ children: /* @__PURE__ */ jsx16(Text11, { style: [styles15.monthText, { color: selected ? theme.onAccent : theme.textPrimary, fontWeight: selected ? "700" : "500" }], children: name })
1483
1687
  },
1484
1688
  id
1485
1689
  );
@@ -1493,13 +1697,13 @@ function DayStrip({ label, locale, value: valueProp, defaultValue = null, onValu
1493
1697
  const [value, setValue] = useOwn(valueProp, defaultValue);
1494
1698
  const weekday = new Intl.DateTimeFormat(locale, { weekday: "short" });
1495
1699
  const list = Array.from({ length: days }, (_, i) => addDays(first, i));
1496
- return /* @__PURE__ */ jsx14(ScrollView4, { horizontal: true, showsHorizontalScrollIndicator: false, role: "radiogroup", "aria-label": label, contentContainerStyle: styles13.strip, style, children: list.map((iso) => {
1700
+ return /* @__PURE__ */ jsx16(ScrollView4, { horizontal: true, showsHorizontalScrollIndicator: false, role: "radiogroup", "aria-label": label, contentContainerStyle: styles15.strip, style, children: list.map((iso) => {
1497
1701
  const selected = iso === value;
1498
1702
  const disabled = Boolean(isDateDisabled?.(iso));
1499
1703
  const marked = Boolean(isDateMarked?.(iso));
1500
1704
  const name = longDate(locale, iso);
1501
- return /* @__PURE__ */ jsxs11(
1502
- Pressable8,
1705
+ return /* @__PURE__ */ jsxs13(
1706
+ Pressable9,
1503
1707
  {
1504
1708
  role: "radio",
1505
1709
  "aria-checked": selected,
@@ -1513,7 +1717,7 @@ function DayStrip({ label, locale, value: valueProp, defaultValue = null, onValu
1513
1717
  onValueChange?.(iso);
1514
1718
  },
1515
1719
  style: ({ pressed }) => [
1516
- styles13.stripDay,
1720
+ styles15.stripDay,
1517
1721
  {
1518
1722
  borderRadius: radius3.xl,
1519
1723
  backgroundColor: selected ? theme.accent : disabled ? "transparent" : theme.surface2,
@@ -1523,10 +1727,10 @@ function DayStrip({ label, locale, value: valueProp, defaultValue = null, onValu
1523
1727
  }
1524
1728
  ],
1525
1729
  children: [
1526
- iso === today ? /* @__PURE__ */ jsx14(Node, { color: selected ? theme.onAccent : theme.accent, style: styles13.stripNode }) : null,
1527
- /* @__PURE__ */ jsx14(Text11, { style: [styles13.stripWeekday, { color: selected ? theme.onAccent : disabled ? theme.textMuted : theme.textSecondary }], children: weekday.format(toLocalDate(iso)).replace(/\.$/, "").toUpperCase() }),
1528
- /* @__PURE__ */ jsx14(Text11, { style: [styles13.stripNumber, { color: selected ? theme.onAccent : disabled ? theme.textMuted : theme.textPrimary }], children: Number(iso.slice(8)) }),
1529
- /* @__PURE__ */ jsx14(View10, { style: [styles13.dot, marked ? { backgroundColor: selected ? theme.onAccent : theme.textSecondary } : null] })
1730
+ iso === today ? /* @__PURE__ */ jsx16(Node, { color: selected ? theme.onAccent : theme.accent, style: styles15.stripNode }) : null,
1731
+ /* @__PURE__ */ jsx16(Text11, { style: [styles15.stripWeekday, { color: selected ? theme.onAccent : disabled ? theme.textMuted : theme.textSecondary }], children: weekday.format(toLocalDate(iso)).replace(/\.$/, "").toUpperCase() }),
1732
+ /* @__PURE__ */ jsx16(Text11, { style: [styles15.stripNumber, { color: selected ? theme.onAccent : disabled ? theme.textMuted : theme.textPrimary }], children: Number(iso.slice(8)) }),
1733
+ /* @__PURE__ */ jsx16(View12, { style: [styles15.dot, marked ? { backgroundColor: selected ? theme.onAccent : theme.textSecondary } : null] })
1530
1734
  ]
1531
1735
  },
1532
1736
  iso
@@ -1541,11 +1745,11 @@ function TimePicker({ label, locale, value: valueProp, defaultValue = null, onVa
1541
1745
  onValueChange?.(next);
1542
1746
  };
1543
1747
  if (variant === "slots")
1544
- return /* @__PURE__ */ jsx14(View10, { role: "radiogroup", "aria-label": label, style: [styles13.slots, style], children: slots.map((t) => {
1748
+ return /* @__PURE__ */ jsx16(View12, { role: "radiogroup", "aria-label": label, style: [styles15.slots, style], children: slots.map((t) => {
1545
1749
  const selected = t === value;
1546
1750
  const off = disabled || Boolean(isTimeDisabled?.(t));
1547
- return /* @__PURE__ */ jsx14(
1548
- Pressable8,
1751
+ return /* @__PURE__ */ jsx16(
1752
+ Pressable9,
1549
1753
  {
1550
1754
  role: "radio",
1551
1755
  "aria-checked": selected,
@@ -1557,7 +1761,7 @@ function TimePicker({ label, locale, value: valueProp, defaultValue = null, onVa
1557
1761
  set(t);
1558
1762
  },
1559
1763
  style: ({ pressed }) => [
1560
- styles13.slot,
1764
+ styles15.slot,
1561
1765
  {
1562
1766
  borderRadius: radius3.lg,
1563
1767
  backgroundColor: selected ? theme.accent : off ? "transparent" : theme.surface2,
@@ -1566,7 +1770,7 @@ function TimePicker({ label, locale, value: valueProp, defaultValue = null, onVa
1566
1770
  transform: [{ scale: pressed ? 0.97 : 1 }]
1567
1771
  }
1568
1772
  ],
1569
- children: /* @__PURE__ */ jsx14(Text11, { style: [styles13.slotText, { color: selected ? theme.onAccent : off ? theme.textMuted : theme.textPrimary, textDecorationLine: off ? "line-through" : "none" }], children: formatTime(locale, t) })
1773
+ children: /* @__PURE__ */ jsx16(Text11, { style: [styles15.slotText, { color: selected ? theme.onAccent : off ? theme.textMuted : theme.textPrimary, textDecorationLine: off ? "line-through" : "none" }], children: formatTime(locale, t) })
1570
1774
  },
1571
1775
  t
1572
1776
  );
@@ -1582,11 +1786,11 @@ function TimePicker({ label, locale, value: valueProp, defaultValue = null, onVa
1582
1786
  const hours = twelve ? [12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].map((h) => ({ value: String(h), label: String(h) })) : Array.from({ length: 24 }, (_, h) => ({ value: String(h), label: two(h) }));
1583
1787
  const minutes = Array.from({ length: Math.ceil(60 / minuteStep) }, (_, i) => ({ value: String(i * minuteStep), label: two(i * minuteStep) }));
1584
1788
  const [am, pmLabel] = dayPeriods(locale);
1585
- return /* @__PURE__ */ jsxs11(WheelPicker, { label: value ? `${label}, ${formatTime(locale, value)}` : label, style, children: [
1586
- /* @__PURE__ */ jsx14(Wheel, { label: labels.hours, options: hours, disabled, value: twelve ? String(h24 % 12 === 0 ? 12 : h24 % 12) : String(h24), onValueChange: (v) => put(twelve ? Number(v) % 12 + (pm ? 12 : 0) : Number(v), minute) }),
1587
- /* @__PURE__ */ jsx14(WheelDivider, { children: ":" }),
1588
- /* @__PURE__ */ jsx14(Wheel, { label: labels.minutes, options: minutes, disabled, value: String(Math.min(60 - minuteStep, Math.round(minute / minuteStep) * minuteStep)), onValueChange: (v) => put(h24, Number(v)) }),
1589
- twelve ? /* @__PURE__ */ jsx14(
1789
+ return /* @__PURE__ */ jsxs13(WheelPicker, { label: value ? `${label}, ${formatTime(locale, value)}` : label, style, children: [
1790
+ /* @__PURE__ */ jsx16(Wheel, { label: labels.hours, options: hours, disabled, value: twelve ? String(h24 % 12 === 0 ? 12 : h24 % 12) : String(h24), onValueChange: (v) => put(twelve ? Number(v) % 12 + (pm ? 12 : 0) : Number(v), minute) }),
1791
+ /* @__PURE__ */ jsx16(WheelDivider, { children: ":" }),
1792
+ /* @__PURE__ */ jsx16(Wheel, { label: labels.minutes, options: minutes, disabled, value: String(Math.min(60 - minuteStep, Math.round(minute / minuteStep) * minuteStep)), onValueChange: (v) => put(h24, Number(v)) }),
1793
+ twelve ? /* @__PURE__ */ jsx16(
1590
1794
  Wheel,
1591
1795
  {
1592
1796
  label: labels.period,
@@ -1619,22 +1823,22 @@ function DateWheel({ label, locale, value: valueProp, defaultValue = null, onVal
1619
1823
  };
1620
1824
  const last = daysInMonth(year, month);
1621
1825
  const columns = {
1622
- day: /* @__PURE__ */ jsx14(Wheel, { label: names.day, disabled, options: Array.from({ length: last }, (_, i) => ({ value: String(i + 1), label: String(i + 1), disabled: isoOf(year, month, i + 1) > hi || isoOf(year, month, i + 1) < lo })), value: String(Math.min(day, last)), onValueChange: (v) => set(year, month, Number(v)), style: styles13.dayWheel }, "day"),
1623
- month: /* @__PURE__ */ jsx14(Wheel, { label: names.month, disabled, options: months.map((n, i) => ({ value: String(i + 1), label: n, disabled: isoOf(year, i + 1, 1) > hi || isoOf(year, i + 1, daysInMonth(year, i + 1)) < lo })), value: String(month), onValueChange: (v) => set(year, Number(v), day), style: styles13.monthWheel }, "month"),
1624
- year: /* @__PURE__ */ jsx14(Wheel, { label: names.year, disabled, options: yearRange(Number(hi.slice(0, 4)), Number(lo.slice(0, 4))).map((y) => ({ value: String(y), label: String(y) })), value: String(year), onValueChange: (v) => set(Number(v), month, day), style: styles13.yearWheel }, "year")
1826
+ day: /* @__PURE__ */ jsx16(Wheel, { label: names.day, disabled, options: Array.from({ length: last }, (_, i) => ({ value: String(i + 1), label: String(i + 1), disabled: isoOf(year, month, i + 1) > hi || isoOf(year, month, i + 1) < lo })), value: String(Math.min(day, last)), onValueChange: (v) => set(year, month, Number(v)), style: styles15.dayWheel }, "day"),
1827
+ month: /* @__PURE__ */ jsx16(Wheel, { label: names.month, disabled, options: months.map((n, i) => ({ value: String(i + 1), label: n, disabled: isoOf(year, i + 1, 1) > hi || isoOf(year, i + 1, daysInMonth(year, i + 1)) < lo })), value: String(month), onValueChange: (v) => set(year, Number(v), day), style: styles15.monthWheel }, "month"),
1828
+ year: /* @__PURE__ */ jsx16(Wheel, { label: names.year, disabled, options: yearRange(Number(hi.slice(0, 4)), Number(lo.slice(0, 4))).map((y) => ({ value: String(y), label: String(y) })), value: String(year), onValueChange: (v) => set(Number(v), month, day), style: styles15.yearWheel }, "year")
1625
1829
  };
1626
1830
  const caption = error ?? hint;
1627
- return /* @__PURE__ */ jsxs11(View10, { style: [styles13.field, style], children: [
1628
- /* @__PURE__ */ jsx14(Text11, { "aria-hidden": true, style: [styles13.fieldLabel, { color: theme.textSecondary }], children: label }),
1629
- /* @__PURE__ */ jsx14(WheelPicker, { label, invalid: Boolean(error), unset: !value, children: datePartsOrder(locale).map((part) => columns[part]) }),
1630
- caption ? /* @__PURE__ */ jsx14(Text11, { role: error ? "alert" : void 0, "aria-live": error ? "polite" : void 0, style: [styles13.caption, { color: error ? theme.dangerText : theme.textSecondary }], children: caption }) : null
1831
+ return /* @__PURE__ */ jsxs13(View12, { style: [styles15.field, style], children: [
1832
+ /* @__PURE__ */ jsx16(Text11, { "aria-hidden": true, style: [styles15.fieldLabel, { color: theme.textSecondary }], children: label }),
1833
+ /* @__PURE__ */ jsx16(WheelPicker, { label, invalid: Boolean(error), unset: !value, children: datePartsOrder(locale).map((part) => columns[part]) }),
1834
+ caption ? /* @__PURE__ */ jsx16(Text11, { role: error ? "alert" : void 0, "aria-live": error ? "polite" : void 0, style: [styles15.caption, { color: error ? theme.dangerText : theme.textSecondary }], children: caption }) : null
1631
1835
  ] });
1632
1836
  }
1633
- var styles13 = StyleSheet13.create({
1634
- calendar: { padding: 12, gap: 4, borderWidth: StyleSheet13.hairlineWidth, alignSelf: "flex-start" },
1837
+ var styles15 = StyleSheet15.create({
1838
+ calendar: { padding: 12, gap: 4, borderWidth: StyleSheet15.hairlineWidth, alignSelf: "flex-start" },
1635
1839
  header: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", marginBottom: 6, gap: 8 },
1636
1840
  title: { fontSize: 15, fontWeight: "700", textTransform: "capitalize" },
1637
- nav: { width: 36, height: 36, alignItems: "center", justifyContent: "center", borderWidth: StyleSheet13.hairlineWidth },
1841
+ nav: { width: 36, height: 36, alignItems: "center", justifyContent: "center", borderWidth: StyleSheet15.hairlineWidth },
1638
1842
  week: { flexDirection: "row" },
1639
1843
  weekday: { width: 44, textAlign: "center", fontSize: 11, fontWeight: "700", paddingBottom: 4 },
1640
1844
  cell: { width: 44, height: 44, marginVertical: 1 },
@@ -1663,38 +1867,114 @@ var styles13 = StyleSheet13.create({
1663
1867
  disabled: { opacity: 0.4 }
1664
1868
  });
1665
1869
 
1870
+ // src/native/description-list.tsx
1871
+ import { StyleSheet as StyleSheet16, View as View13 } from "react-native";
1872
+ import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
1873
+ function DescriptionList({ items: items2, layout = "stacked", style }) {
1874
+ const { theme, radius: radius3 } = useTheme();
1875
+ return /* @__PURE__ */ jsx17(View13, { role: "list", style: [layout === "grid" ? styles16.grid : layout === "inline" ? null : styles16.stacked, style], children: items2.map((item, i) => {
1876
+ const value = typeof item.details === "string" || typeof item.details === "number" ? /* @__PURE__ */ jsx17(Txt, { variant: layout === "grid" ? "title" : "body", style: layout === "inline" ? styles16.right : null, children: item.details }) : item.details;
1877
+ return /* @__PURE__ */ jsxs14(
1878
+ View13,
1879
+ {
1880
+ role: "listitem",
1881
+ accessible: true,
1882
+ style: [
1883
+ layout === "inline" ? [styles16.inline, i > 0 ? { borderTopWidth: StyleSheet16.hairlineWidth, borderTopColor: theme.borderSubtle } : null] : null,
1884
+ layout === "grid" ? [styles16.card, { backgroundColor: theme.surface1, borderColor: theme.borderDefault, borderRadius: radius3.lg }] : null
1885
+ ],
1886
+ children: [
1887
+ /* @__PURE__ */ jsx17(Txt, { variant: "caption", tone: "secondary", style: layout === "grid" ? styles16.upper : null, children: item.term }),
1888
+ /* @__PURE__ */ jsxs14(View13, { style: layout === "inline" ? styles16.valueInline : styles16.value, children: [
1889
+ value,
1890
+ item.hint ? /* @__PURE__ */ jsx17(Txt, { variant: "caption", tone: "secondary", style: layout === "inline" ? styles16.right : null, children: item.hint }) : null
1891
+ ] })
1892
+ ]
1893
+ },
1894
+ item.id ?? item.term
1895
+ );
1896
+ }) });
1897
+ }
1898
+ var styles16 = StyleSheet16.create({
1899
+ stacked: { gap: 14 },
1900
+ inline: { flexDirection: "row", alignItems: "baseline", justifyContent: "space-between", gap: 16, paddingVertical: 10 },
1901
+ grid: { flexDirection: "row", flexWrap: "wrap", gap: 10 },
1902
+ card: { flexBasis: "47%", flexGrow: 1, padding: 12, gap: 4, borderWidth: StyleSheet16.hairlineWidth },
1903
+ upper: { textTransform: "uppercase", letterSpacing: 0.6, fontWeight: "700" },
1904
+ value: { gap: 2, marginTop: 2 },
1905
+ valueInline: { flexShrink: 1, alignItems: "flex-end", gap: 2 },
1906
+ right: { textAlign: "right" }
1907
+ });
1908
+
1666
1909
  // src/native/empty-state.tsx
1667
- import { StyleSheet as StyleSheet14, View as View11 } from "react-native";
1668
- import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
1910
+ import { StyleSheet as StyleSheet17, View as View14 } from "react-native";
1911
+ import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
1669
1912
  function EmptyState({ icon, title, description, action, style, ...props }) {
1670
1913
  const { theme } = useTheme();
1671
- return /* @__PURE__ */ jsxs12(View11, { ...props, style: [styles14.root, style], children: [
1672
- icon ? /* @__PURE__ */ jsx15(View11, { "aria-hidden": true, style: [styles14.icon, { backgroundColor: theme.surface2 }], children: icon }) : null,
1673
- /* @__PURE__ */ jsx15(Txt, { variant: "label", role: "heading", style: styles14.center, children: title }),
1674
- description ? /* @__PURE__ */ jsx15(Txt, { tone: "secondary", style: styles14.center, children: description }) : null,
1675
- action ? /* @__PURE__ */ jsx15(View11, { style: styles14.action, children: action }) : null
1914
+ return /* @__PURE__ */ jsxs15(View14, { ...props, style: [styles17.root, style], children: [
1915
+ icon ? /* @__PURE__ */ jsx18(View14, { "aria-hidden": true, style: [styles17.icon, { backgroundColor: theme.surface2 }], children: icon }) : null,
1916
+ /* @__PURE__ */ jsx18(Txt, { variant: "label", role: "heading", style: styles17.center, children: title }),
1917
+ description ? /* @__PURE__ */ jsx18(Txt, { tone: "secondary", style: styles17.center, children: description }) : null,
1918
+ action ? /* @__PURE__ */ jsx18(View14, { style: styles17.action, children: action }) : null
1676
1919
  ] });
1677
1920
  }
1678
- var styles14 = StyleSheet14.create({
1921
+ var styles17 = StyleSheet17.create({
1679
1922
  root: { alignItems: "center", justifyContent: "center", gap: 8, paddingVertical: 40, paddingHorizontal: 24 },
1680
1923
  icon: { width: 48, height: 48, borderRadius: 24, alignItems: "center", justifyContent: "center", marginBottom: 4 },
1681
1924
  center: { textAlign: "center", maxWidth: 360 },
1682
1925
  action: { marginTop: 8, flexDirection: "row", flexWrap: "wrap", justifyContent: "center", gap: 8 }
1683
1926
  });
1684
1927
 
1928
+ // src/native/fab.tsx
1929
+ import { Pressable as Pressable10, StyleSheet as StyleSheet18, View as View15 } from "react-native";
1930
+ import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
1931
+ function Fab({ label, icon, onPress, extended, placement = "end", offset = 0, style }) {
1932
+ const { theme, insets, haptic } = useTheme();
1933
+ const position = placement === "center" ? { alignSelf: "center" } : placement === "start" ? { left: 16 + insets.left } : { right: 16 + insets.right };
1934
+ return /* @__PURE__ */ jsx19(View15, { pointerEvents: "box-none", style: [styles18.layer, placement === "center" ? styles18.centre : null], children: /* @__PURE__ */ jsxs16(
1935
+ Pressable10,
1936
+ {
1937
+ role: "button",
1938
+ "aria-label": label,
1939
+ onPress: () => {
1940
+ haptic("impact");
1941
+ onPress();
1942
+ },
1943
+ style: ({ pressed }) => [
1944
+ styles18.fab,
1945
+ extended ? styles18.extended : null,
1946
+ position,
1947
+ { bottom: 16 + insets.bottom + offset, backgroundColor: pressed ? theme.accentHover : theme.accent, borderTopColor: theme.edgeOnFill, shadowColor: theme.scrimStrong },
1948
+ style
1949
+ ],
1950
+ children: [
1951
+ /* @__PURE__ */ jsx19(View15, { "aria-hidden": true, children: icon }),
1952
+ extended ? /* @__PURE__ */ jsx19(Txt, { variant: "label", tone: "onAccent", "aria-hidden": true, numberOfLines: 1, style: styles18.label, children: label }) : null
1953
+ ]
1954
+ }
1955
+ ) });
1956
+ }
1957
+ var styles18 = StyleSheet18.create({
1958
+ layer: { position: "absolute", top: 0, right: 0, bottom: 0, left: 0 },
1959
+ centre: { alignItems: "center" },
1960
+ fab: { borderTopWidth: 1, borderColor: "transparent", position: "absolute", minWidth: 56, height: 56, borderRadius: 28, alignItems: "center", justifyContent: "center", flexDirection: "row", gap: 8, shadowOpacity: 0.3, shadowRadius: 12, shadowOffset: { width: 0, height: 6 }, elevation: 6 },
1961
+ extended: { paddingHorizontal: 20 },
1962
+ label: { flexShrink: 0 }
1963
+ });
1964
+
1685
1965
  // src/native/field.tsx
1686
- import * as React13 from "react";
1687
- import { StyleSheet as StyleSheet15, Text as Text12, TextInput as TextInput3, View as View12 } from "react-native";
1688
- import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
1966
+ import * as React15 from "react";
1967
+ import { StyleSheet as StyleSheet19, Text as Text12, TextInput as TextInput3, View as View16 } from "react-native";
1968
+ import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
1689
1969
  function TextField({ label, hint, error, value, defaultValue, onValueChange, disabled, end, inputRef, style, multiline, onFocus, onBlur, ...props }) {
1690
1970
  const { theme, radius: radius3 } = useTheme();
1691
- const [focused, setFocused] = React13.useState(false);
1971
+ const [focused, setFocused] = React15.useState(false);
1692
1972
  const caption = error ?? hint;
1693
1973
  const border = error ? theme.danger : focused ? theme.accent : theme.borderDefault;
1694
- return /* @__PURE__ */ jsxs13(View12, { style: [styles15.root, disabled ? styles15.disabled : null, style], children: [
1695
- /* @__PURE__ */ jsx16(Text12, { style: [styles15.label, { color: theme.textSecondary }], children: label }),
1696
- /* @__PURE__ */ jsxs13(View12, { style: [styles15.frame, multiline ? styles15.multiline : null, { borderRadius: radius3.md, borderColor: border, backgroundColor: theme.surface2 }], children: [
1697
- /* @__PURE__ */ jsx16(
1974
+ return /* @__PURE__ */ jsxs17(View16, { style: [styles19.root, disabled ? styles19.disabled : null, style], children: [
1975
+ /* @__PURE__ */ jsx20(Text12, { style: [styles19.label, { color: theme.textSecondary }], children: label }),
1976
+ /* @__PURE__ */ jsxs17(View16, { style: [styles19.frame, multiline ? styles19.multiline : null, { borderRadius: radius3.md, borderColor: border, backgroundColor: theme.surface2 }], children: [
1977
+ /* @__PURE__ */ jsx20(
1698
1978
  TextInput3,
1699
1979
  {
1700
1980
  ref: inputRef,
@@ -1716,16 +1996,16 @@ function TextField({ label, hint, error, value, defaultValue, onValueChange, dis
1716
1996
  setFocused(false);
1717
1997
  onBlur?.(event);
1718
1998
  },
1719
- style: [styles15.input, multiline ? styles15.inputMultiline : null, { color: theme.textPrimary }],
1999
+ style: [styles19.input, multiline ? styles19.inputMultiline : null, { color: theme.textPrimary }],
1720
2000
  ...props
1721
2001
  }
1722
2002
  ),
1723
- end ? /* @__PURE__ */ jsx16(View12, { style: styles15.end, children: end }) : null
2003
+ end ? /* @__PURE__ */ jsx20(View16, { style: styles19.end, children: end }) : null
1724
2004
  ] }),
1725
- caption ? /* @__PURE__ */ jsx16(Text12, { role: error ? "alert" : void 0, "aria-live": error ? "polite" : void 0, style: [styles15.caption, { color: error ? theme.dangerText : theme.textSecondary }], children: caption }) : null
2005
+ caption ? /* @__PURE__ */ jsx20(Text12, { role: error ? "alert" : void 0, "aria-live": error ? "polite" : void 0, style: [styles19.caption, { color: error ? theme.dangerText : theme.textSecondary }], children: caption }) : null
1726
2006
  ] });
1727
2007
  }
1728
- var styles15 = StyleSheet15.create({
2008
+ var styles19 = StyleSheet19.create({
1729
2009
  root: { gap: 6, alignSelf: "stretch" },
1730
2010
  label: { fontSize: 12, lineHeight: 16, fontWeight: "600" },
1731
2011
  frame: { flexDirection: "row", alignItems: "center", minHeight: 44, paddingHorizontal: 12, borderWidth: 1 },
@@ -1738,17 +2018,17 @@ var styles15 = StyleSheet15.create({
1738
2018
  });
1739
2019
 
1740
2020
  // src/native/goal-gauge.tsx
1741
- import { Animated as Animated5, StyleSheet as StyleSheet16, View as View13 } from "react-native";
2021
+ import { Animated as Animated5, StyleSheet as StyleSheet20, View as View17 } from "react-native";
1742
2022
 
1743
2023
  // src/native/story-motion.ts
1744
- import * as React14 from "react";
1745
- import { AccessibilityInfo as AccessibilityInfo2, Animated as Animated4, Easing } from "react-native";
2024
+ import * as React16 from "react";
2025
+ import { AccessibilityInfo as AccessibilityInfo3, Animated as Animated4, Easing } from "react-native";
1746
2026
  function useEntrance(animated, delay = 0, duration = 700) {
1747
- const [value] = React14.useState(() => new Animated4.Value(animated ? 0 : 1));
1748
- React14.useEffect(() => {
2027
+ const [value] = React16.useState(() => new Animated4.Value(animated ? 0 : 1));
2028
+ React16.useEffect(() => {
1749
2029
  if (!animated) return;
1750
2030
  let cancelled = false;
1751
- void AccessibilityInfo2.isReduceMotionEnabled().then((reduce) => {
2031
+ void AccessibilityInfo3.isReduceMotionEnabled().then((reduce) => {
1752
2032
  if (cancelled) return;
1753
2033
  if (reduce) value.setValue(1);
1754
2034
  else Animated4.timing(value, { toValue: 1, duration, delay, easing: Easing.out(Easing.cubic), useNativeDriver: true }).start();
@@ -1761,17 +2041,17 @@ function useEntrance(animated, delay = 0, duration = 700) {
1761
2041
  }
1762
2042
 
1763
2043
  // src/native/goal-gauge.tsx
1764
- import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
2044
+ import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
1765
2045
  function Cell({ lit, animate, order, animated, arcade }) {
1766
2046
  const { theme } = useTheme();
1767
2047
  const t = useEntrance(animated && animate, 300 + order * 100, 350);
1768
2048
  const spentOpacity = arcade ? 0.14 : 1;
1769
2049
  const opacity = !animate ? 1 : lit ? t.interpolate({ inputRange: [0, 1], outputRange: [0.25, 1] }) : t.interpolate({ inputRange: [0, 1], outputRange: [1, arcade ? 0.14 : 1] });
1770
2050
  const color = lit || arcade ? theme.accent : theme.surface3;
1771
- return /* @__PURE__ */ jsx17(
2051
+ return /* @__PURE__ */ jsx21(
1772
2052
  Animated5.View,
1773
2053
  {
1774
- style: [styles16.cell, arcade ? styles16.cellArcade : null, { backgroundColor: color, opacity: lit || animate ? opacity : spentOpacity }]
2054
+ style: [styles20.cell, arcade ? styles20.cellArcade : null, { backgroundColor: color, opacity: lit || animate ? opacity : spentOpacity }]
1775
2055
  }
1776
2056
  );
1777
2057
  }
@@ -1781,8 +2061,8 @@ function GoalGauge({ label, segments, value, valueText, mode = "fill", showLabel
1781
2061
  const lit = Math.min(total, Math.max(0, Math.round(value ?? total)));
1782
2062
  const words = valueText ?? `${lit} / ${total}`;
1783
2063
  const arcade = variant === "arcade";
1784
- return /* @__PURE__ */ jsxs14(
1785
- View13,
2064
+ return /* @__PURE__ */ jsxs18(
2065
+ View17,
1786
2066
  {
1787
2067
  accessible: true,
1788
2068
  role: "meter",
@@ -1792,22 +2072,22 @@ function GoalGauge({ label, segments, value, valueText, mode = "fill", showLabel
1792
2072
  "aria-valuenow": lit,
1793
2073
  "aria-valuetext": words,
1794
2074
  ...props,
1795
- style: [styles16.root, style],
2075
+ style: [styles20.root, style],
1796
2076
  children: [
1797
- showLabel ? /* @__PURE__ */ jsxs14(View13, { "aria-hidden": true, style: [styles16.head, arcade ? styles16.headArcade : null], children: [
1798
- /* @__PURE__ */ jsx17(Txt, { variant: arcade ? "mono" : "caption", tone: "secondary", children: arcade ? label.toUpperCase() : label }),
1799
- arcade ? null : /* @__PURE__ */ jsx17(Txt, { variant: "caption", children: words })
2077
+ showLabel ? /* @__PURE__ */ jsxs18(View17, { "aria-hidden": true, style: [styles20.head, arcade ? styles20.headArcade : null], children: [
2078
+ /* @__PURE__ */ jsx21(Txt, { variant: arcade ? "mono" : "caption", tone: "secondary", children: arcade ? label.toUpperCase() : label }),
2079
+ arcade ? null : /* @__PURE__ */ jsx21(Txt, { variant: "caption", children: words })
1800
2080
  ] }) : null,
1801
- /* @__PURE__ */ jsx17(View13, { "aria-hidden": true, style: [styles16.cells, arcade ? [styles16.cellsArcade, { borderColor: theme.borderSubtle, backgroundColor: theme.surface1 }] : null], children: Array.from({ length: total }, (_, i) => {
2081
+ /* @__PURE__ */ jsx21(View17, { "aria-hidden": true, style: [styles20.cells, arcade ? [styles20.cellsArcade, { borderColor: theme.borderSubtle, backgroundColor: theme.surface1 }] : null], children: Array.from({ length: total }, (_, i) => {
1802
2082
  const on = i < lit;
1803
2083
  const animate = mode === "fill" ? on : !on;
1804
- return /* @__PURE__ */ jsx17(Cell, { lit: on, animate, order: mode === "fill" ? i : i - lit, animated, arcade }, i);
2084
+ return /* @__PURE__ */ jsx21(Cell, { lit: on, animate, order: mode === "fill" ? i : i - lit, animated, arcade }, i);
1805
2085
  }) })
1806
2086
  ]
1807
2087
  }
1808
2088
  );
1809
2089
  }
1810
- var styles16 = StyleSheet16.create({
2090
+ var styles20 = StyleSheet20.create({
1811
2091
  root: { alignSelf: "stretch", gap: 8 },
1812
2092
  head: { flexDirection: "row", justifyContent: "space-between", alignItems: "baseline", gap: 12 },
1813
2093
  headArcade: { justifyContent: "center" },
@@ -1817,9 +2097,190 @@ var styles16 = StyleSheet16.create({
1817
2097
  cellArcade: { height: 10, borderRadius: 1 }
1818
2098
  });
1819
2099
 
2100
+ // src/native/header.tsx
2101
+ import * as React17 from "react";
2102
+ import { Animated as Animated6, Pressable as Pressable11, StyleSheet as StyleSheet21, View as View18 } from "react-native";
2103
+ import Svg6, { Path as Path4 } from "react-native-svg";
2104
+ import { jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
2105
+ var BAR = 44;
2106
+ var LARGE = 52;
2107
+ function Header({ title, subtitle, scrollY, size = "large", backLabel, onBack, actions, children, style }) {
2108
+ const { theme, insets } = useTheme();
2109
+ const reduce = useReducedMotion();
2110
+ const large = size === "large";
2111
+ const fixed = React17.useMemo(() => new Animated6.Value(large ? 0 : 1), [large]);
2112
+ const progress = scrollY && large ? scrollY.interpolate({ inputRange: [0, LARGE], outputRange: [0, 1], extrapolate: "clamp" }) : fixed;
2113
+ const smallOpacity = progress.interpolate({ inputRange: [0.6, 1], outputRange: [0, 1], extrapolate: "clamp" });
2114
+ const largeOpacity = progress.interpolate({ inputRange: [0, 0.7], outputRange: [1, 0], extrapolate: "clamp" });
2115
+ const largeShift = reduce ? 0 : progress.interpolate({ inputRange: [0, 1], outputRange: [0, -10] });
2116
+ const largeHeight = progress.interpolate({ inputRange: [0, 1], outputRange: [LARGE + (subtitle ? 18 : 0), 0] });
2117
+ return /* @__PURE__ */ jsxs19(View18, { style: [{ paddingTop: insets.top, backgroundColor: theme.surface0 }, style], children: [
2118
+ /* @__PURE__ */ jsxs19(View18, { style: styles21.bar, children: [
2119
+ /* @__PURE__ */ jsx22(View18, { style: styles21.side, children: onBack && backLabel ? /* @__PURE__ */ jsxs19(Pressable11, { role: "button", "aria-label": backLabel, onPress: onBack, hitSlop: 8, style: styles21.back, children: [
2120
+ /* @__PURE__ */ jsx22(Svg6, { width: 22, height: 22, viewBox: "0 0 24 24", "aria-hidden": true, children: /* @__PURE__ */ jsx22(Path4, { d: "M15 5l-7 7 7 7", stroke: theme.accentText, strokeWidth: 2.4, fill: "none", strokeLinecap: "round", strokeLinejoin: "round" }) }),
2121
+ /* @__PURE__ */ jsx22(Txt, { variant: "label", tone: "accent", numberOfLines: 1, children: backLabel })
2122
+ ] }) : null }),
2123
+ /* @__PURE__ */ jsx22(Animated6.View, { style: [styles21.middle, { opacity: smallOpacity }], "aria-hidden": large, children: /* @__PURE__ */ jsx22(Txt, { variant: "label", numberOfLines: 1, role: large ? void 0 : "heading", children: title }) }),
2124
+ /* @__PURE__ */ jsx22(View18, { style: [styles21.side, styles21.right], children: actions })
2125
+ ] }),
2126
+ large ? /* @__PURE__ */ jsx22(Animated6.View, { style: { height: largeHeight, overflow: "hidden" }, children: /* @__PURE__ */ jsxs19(Animated6.View, { style: [styles21.large, { opacity: largeOpacity, transform: [{ translateY: largeShift }] }], children: [
2127
+ /* @__PURE__ */ jsx22(Txt, { variant: "display", numberOfLines: 1, role: "heading", style: styles21.largeTitle, children: title }),
2128
+ subtitle ? /* @__PURE__ */ jsx22(Txt, { variant: "caption", tone: "secondary", children: subtitle }) : null
2129
+ ] }) }) : null,
2130
+ children ? /* @__PURE__ */ jsx22(View18, { style: styles21.children, children }) : null,
2131
+ /* @__PURE__ */ jsx22(Animated6.View, { "aria-hidden": true, style: [styles21.rule, { backgroundColor: theme.borderSubtle, opacity: smallOpacity }] })
2132
+ ] });
2133
+ }
2134
+ function useCollapsingHeader() {
2135
+ const [scrollY] = React17.useState(() => new Animated6.Value(0));
2136
+ const onScroll = React17.useMemo(() => Animated6.event([{ nativeEvent: { contentOffset: { y: scrollY } } }], { useNativeDriver: false }), [scrollY]);
2137
+ return { scrollY, onScroll };
2138
+ }
2139
+ var styles21 = StyleSheet21.create({
2140
+ bar: { height: BAR, flexDirection: "row", alignItems: "center", paddingHorizontal: 8 },
2141
+ side: { flex: 1, flexDirection: "row", alignItems: "center" },
2142
+ right: { justifyContent: "flex-end", gap: 4 },
2143
+ middle: { flex: 2, alignItems: "center" },
2144
+ back: { flexDirection: "row", alignItems: "center", gap: 2, minHeight: 44, paddingRight: 8 },
2145
+ large: { paddingHorizontal: 16, paddingBottom: 6 },
2146
+ largeTitle: { fontSize: 32, lineHeight: 40 },
2147
+ children: { paddingHorizontal: 16, paddingBottom: 8 },
2148
+ rule: { height: StyleSheet21.hairlineWidth }
2149
+ });
2150
+
2151
+ // src/native/image-viewer.tsx
2152
+ import * as React18 from "react";
2153
+ import { AccessibilityInfo as AccessibilityInfo4, Animated as Animated7, Image as Image3, Modal as Modal3, PanResponder, Pressable as Pressable12, StyleSheet as StyleSheet22, useWindowDimensions, View as View19 } from "react-native";
2154
+ import { jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
2155
+ var MAX_SCALE = 4;
2156
+ function ImageViewer({ images, index, onIndexChange, closeLabel, positionLabel = (n, total) => `${n} / ${total}` }) {
2157
+ const { theme, insets, haptic } = useTheme();
2158
+ const reduce = useReducedMotion();
2159
+ const { width, height } = useWindowDimensions();
2160
+ const open = index !== null && images[index] !== void 0;
2161
+ const [scale] = React18.useState(() => new Animated7.Value(1));
2162
+ const [pan] = React18.useState(() => new Animated7.ValueXY({ x: 0, y: 0 }));
2163
+ const [dismiss2] = React18.useState(() => new Animated7.Value(0));
2164
+ const state = React18.useRef({ scale: 1, x: 0, y: 0, pinch: 0, base: 1, lastTap: 0 });
2165
+ const reset = React18.useCallback(() => {
2166
+ state.current = { ...state.current, scale: 1, x: 0, y: 0 };
2167
+ scale.setValue(1);
2168
+ pan.setValue({ x: 0, y: 0 });
2169
+ dismiss2.setValue(0);
2170
+ }, [scale, pan, dismiss2]);
2171
+ React18.useEffect(() => {
2172
+ reset();
2173
+ if (open) AccessibilityInfo4.announceForAccessibility(`${images[index].alt}, ${positionLabel(index + 1, images.length)}`);
2174
+ }, [index]);
2175
+ const go = (to) => {
2176
+ if (to < 0 || to >= images.length) return;
2177
+ haptic("selection");
2178
+ onIndexChange(to);
2179
+ };
2180
+ const animateTo = (value, to) => reduce ? value.setValue(to) : Animated7.spring(value, { toValue: to, useNativeDriver: true, damping: 20 }).start();
2181
+ const distance = (touches) => Math.hypot(touches[0].pageX - touches[1].pageX, touches[0].pageY - touches[1].pageY);
2182
+ const responder = React18.useMemo(
2183
+ () => PanResponder.create({
2184
+ onStartShouldSetPanResponder: () => true,
2185
+ onMoveShouldSetPanResponder: (_, g) => Math.abs(g.dx) > 4 || Math.abs(g.dy) > 4,
2186
+ onPanResponderGrant: (e) => {
2187
+ const now = Date.now();
2188
+ const s = state.current;
2189
+ if (e.nativeEvent.touches.length === 1 && now - s.lastTap < 280) {
2190
+ const next = s.scale > 1 ? 1 : 2.5;
2191
+ s.scale = next;
2192
+ s.x = 0;
2193
+ s.y = 0;
2194
+ animateTo(scale, next);
2195
+ pan.setValue({ x: 0, y: 0 });
2196
+ }
2197
+ s.lastTap = now;
2198
+ s.pinch = 0;
2199
+ },
2200
+ onPanResponderMove: (e, g) => {
2201
+ const s = state.current;
2202
+ const touches = e.nativeEvent.touches;
2203
+ if (touches.length === 2) {
2204
+ const d = distance(touches);
2205
+ if (!s.pinch) {
2206
+ s.pinch = d;
2207
+ s.base = s.scale;
2208
+ }
2209
+ s.scale = Math.min(MAX_SCALE, Math.max(1, s.base * (d / s.pinch)));
2210
+ scale.setValue(s.scale);
2211
+ return;
2212
+ }
2213
+ if (s.scale > 1) pan.setValue({ x: s.x + g.dx, y: s.y + g.dy });
2214
+ else if (Math.abs(g.dy) > Math.abs(g.dx)) dismiss2.setValue(Math.max(0, g.dy));
2215
+ else pan.setValue({ x: g.dx, y: 0 });
2216
+ },
2217
+ onPanResponderRelease: (_, g) => {
2218
+ const s = state.current;
2219
+ if (s.pinch) {
2220
+ s.pinch = 0;
2221
+ if (s.scale <= 1.02) reset();
2222
+ return;
2223
+ }
2224
+ if (s.scale > 1) {
2225
+ s.x += g.dx;
2226
+ s.y += g.dy;
2227
+ return;
2228
+ }
2229
+ if (g.dy > 120 || g.vy > 1.2) return onIndexChange(null);
2230
+ if (g.dx < -width / 4 || g.vx < -0.8) go((index ?? 0) + 1);
2231
+ else if (g.dx > width / 4 || g.vx > 0.8) go((index ?? 0) - 1);
2232
+ animateTo(dismiss2, 0);
2233
+ Animated7.spring(pan, { toValue: { x: 0, y: 0 }, useNativeDriver: true }).start();
2234
+ }
2235
+ }),
2236
+ [index, width, images.length]
2237
+ // eslint-disable-line react-hooks/exhaustive-deps -- the gesture reads refs
2238
+ );
2239
+ if (!open) return null;
2240
+ const image = images[index];
2241
+ const backdrop = dismiss2.interpolate({ inputRange: [0, height / 2], outputRange: [1, 0.3], extrapolate: "clamp" });
2242
+ return /* @__PURE__ */ jsxs20(Modal3, { ...modalName(image.alt), visible: true, transparent: true, animationType: reduce ? "none" : "fade", onRequestClose: () => onIndexChange(null), statusBarTranslucent: true, children: [
2243
+ /* @__PURE__ */ jsx23(Animated7.View, { style: [StyleSheet22.absoluteFill, { backgroundColor: theme.media, opacity: backdrop }] }),
2244
+ /* @__PURE__ */ jsx23(
2245
+ View19,
2246
+ {
2247
+ style: StyleSheet22.absoluteFill,
2248
+ accessible: true,
2249
+ role: "img",
2250
+ "aria-label": `${image.alt}, ${positionLabel(index + 1, images.length)}`,
2251
+ accessibilityActions: [{ name: "increment" }, { name: "decrement" }, { name: "escape" }],
2252
+ onAccessibilityAction: (e) => {
2253
+ const name = e.nativeEvent.actionName;
2254
+ if (name === "increment") go(index + 1);
2255
+ if (name === "decrement") go(index - 1);
2256
+ if (name === "escape") onIndexChange(null);
2257
+ },
2258
+ ...responder.panHandlers,
2259
+ children: /* @__PURE__ */ jsx23(Animated7.View, { style: { width, height, transform: [{ translateX: pan.x }, { translateY: Animated7.add(pan.y, dismiss2) }, { scale }] }, children: /* @__PURE__ */ jsx23(Image3, { source: { uri: image.uri }, resizeMode: "contain", style: { width, height }, accessibilityIgnoresInvertColors: true }) })
2260
+ }
2261
+ ),
2262
+ /* @__PURE__ */ jsxs20(View19, { pointerEvents: "box-none", style: [styles22.top, { paddingTop: insets.top + 8 }], children: [
2263
+ /* @__PURE__ */ jsx23(View19, { "aria-hidden": true, style: [styles22.counter, { backgroundColor: theme.scrimStrong }], children: /* @__PURE__ */ jsx23(Txt, { variant: "label", tone: "onMedia", children: positionLabel(index + 1, images.length) }) }),
2264
+ /* @__PURE__ */ jsx23(Pressable12, { role: "button", "aria-label": closeLabel, hitSlop: 12, onPress: () => onIndexChange(null), style: [styles22.close, { backgroundColor: theme.scrimStrong }], children: /* @__PURE__ */ jsx23(Txt, { tone: "onMedia", style: styles22.cross, "aria-hidden": true, children: "\xD7" }) })
2265
+ ] }),
2266
+ image.caption ? /* @__PURE__ */ jsx23(View19, { pointerEvents: "none", style: [styles22.caption, { paddingBottom: insets.bottom + 16, backgroundColor: theme.scrimStrong }], children: /* @__PURE__ */ jsx23(Txt, { tone: "onMedia", children: image.caption }) }) : null
2267
+ ] });
2268
+ }
2269
+ function prefetchNeighbours(images, index) {
2270
+ if (index === null) return;
2271
+ for (const i of [index - 1, index + 1]) if (images[i]) void Image3.prefetch(images[i].uri).catch(() => void 0);
2272
+ }
2273
+ var styles22 = StyleSheet22.create({
2274
+ top: { position: "absolute", top: 0, left: 0, right: 0, flexDirection: "row", alignItems: "center", justifyContent: "space-between", paddingHorizontal: 16 },
2275
+ counter: { paddingHorizontal: 10, paddingVertical: 4, borderRadius: 999 },
2276
+ close: { width: 40, height: 40, borderRadius: 20, alignItems: "center", justifyContent: "center" },
2277
+ cross: { fontSize: 24, lineHeight: 26 },
2278
+ caption: { position: "absolute", left: 0, right: 0, bottom: 0, paddingTop: 12, paddingHorizontal: 16 }
2279
+ });
2280
+
1820
2281
  // src/native/KrizakaMark.tsx
1821
- import { View as View14 } from "react-native";
1822
- import Svg5, { Circle, Defs as Defs2, G as Group, LinearGradient as LinearGradient2, Path as Path4, RadialGradient, Stop as Stop2 } from "react-native-svg";
2282
+ import { View as View20 } from "react-native";
2283
+ import Svg7, { Circle as Circle2, Defs as Defs3, G as Group, LinearGradient as LinearGradient3, Path as Path5, RadialGradient, Stop as Stop3 } from "react-native-svg";
1823
2284
 
1824
2285
  // src/marks/krizaka-geometry.ts
1825
2286
  var KRIZAKA = {
@@ -1841,24 +2302,24 @@ var KRIZAKA = {
1841
2302
  };
1842
2303
 
1843
2304
  // src/native/mark-motion.ts
1844
- import { useEffect as useEffect8, useState as useState14 } from "react";
1845
- import { AccessibilityInfo as AccessibilityInfo3, Animated as Animated6, Easing as Easing2 } from "react-native";
2305
+ import { useEffect as useEffect10, useState as useState18 } from "react";
2306
+ import { AccessibilityInfo as AccessibilityInfo5, Animated as Animated8, Easing as Easing2 } from "react-native";
1846
2307
  var markA11y = (title) => title ? { accessible: true, accessibilityRole: "image", accessibilityLabel: title } : { accessibilityElementsHidden: true, importantForAccessibility: "no-hide-descendants" };
1847
2308
  function useMarkMotion(size, animated, spinMs = 3e4) {
1848
- const [spin] = useState14(() => new Animated6.Value(0));
1849
- const [pulse] = useState14(() => new Animated6.Value(0));
1850
- useEffect8(() => {
2309
+ const [spin] = useState18(() => new Animated8.Value(0));
2310
+ const [pulse] = useState18(() => new Animated8.Value(0));
2311
+ useEffect10(() => {
1851
2312
  if (!animated) return;
1852
2313
  let loops = [];
1853
2314
  let cancelled = false;
1854
- void AccessibilityInfo3.isReduceMotionEnabled().then((reduce) => {
2315
+ void AccessibilityInfo5.isReduceMotionEnabled().then((reduce) => {
1855
2316
  if (reduce || cancelled) return;
1856
2317
  loops = [
1857
- Animated6.loop(Animated6.timing(spin, { toValue: 1, duration: spinMs, easing: Easing2.linear, useNativeDriver: true })),
1858
- Animated6.loop(
1859
- Animated6.sequence([
1860
- Animated6.timing(pulse, { toValue: 1, duration: 1600, easing: Easing2.inOut(Easing2.ease), useNativeDriver: true }),
1861
- Animated6.timing(pulse, { toValue: 0, duration: 1600, easing: Easing2.inOut(Easing2.ease), useNativeDriver: true })
2318
+ Animated8.loop(Animated8.timing(spin, { toValue: 1, duration: spinMs, easing: Easing2.linear, useNativeDriver: true })),
2319
+ Animated8.loop(
2320
+ Animated8.sequence([
2321
+ Animated8.timing(pulse, { toValue: 1, duration: 1600, easing: Easing2.inOut(Easing2.ease), useNativeDriver: true }),
2322
+ Animated8.timing(pulse, { toValue: 0, duration: 1600, easing: Easing2.inOut(Easing2.ease), useNativeDriver: true })
1862
2323
  ])
1863
2324
  )
1864
2325
  ];
@@ -1870,7 +2331,7 @@ function useMarkMotion(size, animated, spinMs = 3e4) {
1870
2331
  };
1871
2332
  }, [animated, spin, pulse, spinMs]);
1872
2333
  return {
1873
- Animated: Animated6,
2334
+ Animated: Animated8,
1874
2335
  layer: { position: "absolute", width: size, height: size },
1875
2336
  spinStyle: { transform: [{ rotate: spin.interpolate({ inputRange: [0, 1], outputRange: ["0deg", "360deg"] }) }] },
1876
2337
  pulseStyle: { opacity: pulse.interpolate({ inputRange: [0, 1], outputRange: [0.85, 1] }) }
@@ -1878,39 +2339,39 @@ function useMarkMotion(size, animated, spinMs = 3e4) {
1878
2339
  }
1879
2340
 
1880
2341
  // src/native/KrizakaMark.tsx
1881
- import { Fragment as Fragment3, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
2342
+ import { Fragment as Fragment4, jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
1882
2343
  function KrizakaMark({ size = 48, animated = true, title, neutral }) {
1883
2344
  const { theme } = useTheme();
1884
- const { Animated: Animated17, layer, spinStyle, pulseStyle } = useMarkMotion(size, animated);
2345
+ const { Animated: Animated22, layer, spinStyle, pulseStyle } = useMarkMotion(size, animated);
1885
2346
  const id = useSvgId("kzm");
1886
2347
  const viewBox = size < 48 ? KRIZAKA.croppedViewBox : KRIZAKA.viewBox;
1887
2348
  const stroke = neutral ?? theme.textMuted;
1888
- const blue = /* @__PURE__ */ jsx18(LinearGradient2, { id: `${id}b`, gradientUnits: "userSpaceOnUse", x1: KRIZAKA.blue.x1 + KRIZAKA.offset, y1: KRIZAKA.blue.y1 + KRIZAKA.offset, x2: KRIZAKA.blue.x2 + KRIZAKA.offset, y2: KRIZAKA.blue.y2 + KRIZAKA.offset, children: KRIZAKA.blue.stops.map(([offset, color]) => /* @__PURE__ */ jsx18(Stop2, { offset, stopColor: color }, offset)) });
1889
- const dot = (c) => /* @__PURE__ */ jsxs15(Fragment3, { children: [
1890
- /* @__PURE__ */ jsx18(Circle, { cx: c.cx, cy: c.cy, r: c.r, fill: `url(#${id}b)` }),
1891
- /* @__PURE__ */ jsx18(Circle, { cx: c.cx, cy: c.cy, r: c.inner, fill: KRIZAKA.highlight })
2349
+ const blue = /* @__PURE__ */ jsx24(LinearGradient3, { id: `${id}b`, gradientUnits: "userSpaceOnUse", x1: KRIZAKA.blue.x1 + KRIZAKA.offset, y1: KRIZAKA.blue.y1 + KRIZAKA.offset, x2: KRIZAKA.blue.x2 + KRIZAKA.offset, y2: KRIZAKA.blue.y2 + KRIZAKA.offset, children: KRIZAKA.blue.stops.map(([offset, color]) => /* @__PURE__ */ jsx24(Stop3, { offset, stopColor: color }, offset)) });
2350
+ const dot = (c) => /* @__PURE__ */ jsxs21(Fragment4, { children: [
2351
+ /* @__PURE__ */ jsx24(Circle2, { cx: c.cx, cy: c.cy, r: c.r, fill: `url(#${id}b)` }),
2352
+ /* @__PURE__ */ jsx24(Circle2, { cx: c.cx, cy: c.cy, r: c.inner, fill: KRIZAKA.highlight })
1892
2353
  ] });
1893
- return /* @__PURE__ */ jsxs15(View14, { style: { width: size, height: size }, ...markA11y(title), children: [
1894
- /* @__PURE__ */ jsxs15(Svg5, { viewBox, style: layer, children: [
1895
- /* @__PURE__ */ jsxs15(Defs2, { children: [
1896
- /* @__PURE__ */ jsxs15(RadialGradient, { id: `${id}g`, cx: "50%", cy: "50%", r: "50%", children: [
1897
- /* @__PURE__ */ jsx18(Stop2, { offset: "0%", stopColor: KRIZAKA.glow.color, stopOpacity: KRIZAKA.glow.opacity }),
1898
- /* @__PURE__ */ jsx18(Stop2, { offset: "100%", stopColor: KRIZAKA.glow.color, stopOpacity: 0 })
2354
+ return /* @__PURE__ */ jsxs21(View20, { style: { width: size, height: size }, ...markA11y(title), children: [
2355
+ /* @__PURE__ */ jsxs21(Svg7, { viewBox, style: layer, children: [
2356
+ /* @__PURE__ */ jsxs21(Defs3, { children: [
2357
+ /* @__PURE__ */ jsxs21(RadialGradient, { id: `${id}g`, cx: "50%", cy: "50%", r: "50%", children: [
2358
+ /* @__PURE__ */ jsx24(Stop3, { offset: "0%", stopColor: KRIZAKA.glow.color, stopOpacity: KRIZAKA.glow.opacity }),
2359
+ /* @__PURE__ */ jsx24(Stop3, { offset: "100%", stopColor: KRIZAKA.glow.color, stopOpacity: 0 })
1899
2360
  ] }),
1900
- /* @__PURE__ */ jsxs15(LinearGradient2, { id: `${id}i`, gradientUnits: "userSpaceOnUse", x1: KRIZAKA.ink.x1 + KRIZAKA.offset, y1: KRIZAKA.ink.y1 + KRIZAKA.offset, x2: KRIZAKA.ink.x2 + KRIZAKA.offset, y2: KRIZAKA.ink.y2 + KRIZAKA.offset, children: [
1901
- /* @__PURE__ */ jsx18(Stop2, { offset: "0%", stopColor: theme.textSecondary }),
1902
- /* @__PURE__ */ jsx18(Stop2, { offset: "100%", stopColor: theme.textPrimary })
2361
+ /* @__PURE__ */ jsxs21(LinearGradient3, { id: `${id}i`, gradientUnits: "userSpaceOnUse", x1: KRIZAKA.ink.x1 + KRIZAKA.offset, y1: KRIZAKA.ink.y1 + KRIZAKA.offset, x2: KRIZAKA.ink.x2 + KRIZAKA.offset, y2: KRIZAKA.ink.y2 + KRIZAKA.offset, children: [
2362
+ /* @__PURE__ */ jsx24(Stop3, { offset: "0%", stopColor: theme.textSecondary }),
2363
+ /* @__PURE__ */ jsx24(Stop3, { offset: "100%", stopColor: theme.textPrimary })
1903
2364
  ] }),
1904
2365
  blue
1905
2366
  ] }),
1906
- size >= 48 ? /* @__PURE__ */ jsx18(Circle, { cx: 200, cy: 200, r: 190, fill: `url(#${id}g)` }) : null,
1907
- /* @__PURE__ */ jsx18(Circle, { cx: 200, cy: 200, r: KRIZAKA.ring.r, stroke, strokeWidth: KRIZAKA.ring.width, opacity: 0.35, fill: "none" }),
1908
- /* @__PURE__ */ jsx18(Group, { transform: `translate(${KRIZAKA.offset} ${KRIZAKA.offset})`, children: /* @__PURE__ */ jsx18(Path4, { d: KRIZAKA.shield, stroke: `url(#${id}i)`, strokeWidth: KRIZAKA.stroke, strokeLinecap: "round", strokeLinejoin: "round", fill: "none" }) })
2367
+ size >= 48 ? /* @__PURE__ */ jsx24(Circle2, { cx: 200, cy: 200, r: 190, fill: `url(#${id}g)` }) : null,
2368
+ /* @__PURE__ */ jsx24(Circle2, { cx: 200, cy: 200, r: KRIZAKA.ring.r, stroke, strokeWidth: KRIZAKA.ring.width, opacity: 0.35, fill: "none" }),
2369
+ /* @__PURE__ */ jsx24(Group, { transform: `translate(${KRIZAKA.offset} ${KRIZAKA.offset})`, children: /* @__PURE__ */ jsx24(Path5, { d: KRIZAKA.shield, stroke: `url(#${id}i)`, strokeWidth: KRIZAKA.stroke, strokeLinecap: "round", strokeLinejoin: "round", fill: "none" }) })
1909
2370
  ] }),
1910
- /* @__PURE__ */ jsx18(Animated17.View, { style: [layer, spinStyle], children: /* @__PURE__ */ jsx18(Svg5, { viewBox, style: layer, children: /* @__PURE__ */ jsx18(Circle, { cx: 200, cy: 200, r: KRIZAKA.orbit.r, stroke, strokeWidth: KRIZAKA.orbit.width, strokeDasharray: KRIZAKA.orbit.dash, opacity: 0.6, fill: "none" }) }) }),
1911
- /* @__PURE__ */ jsx18(Animated17.View, { style: [layer, pulseStyle], children: /* @__PURE__ */ jsxs15(Svg5, { viewBox, style: layer, children: [
1912
- /* @__PURE__ */ jsx18(Defs2, { children: blue }),
1913
- /* @__PURE__ */ jsxs15(Group, { transform: `translate(${KRIZAKA.offset} ${KRIZAKA.offset})`, children: [
2371
+ /* @__PURE__ */ jsx24(Animated22.View, { style: [layer, spinStyle], children: /* @__PURE__ */ jsx24(Svg7, { viewBox, style: layer, children: /* @__PURE__ */ jsx24(Circle2, { cx: 200, cy: 200, r: KRIZAKA.orbit.r, stroke, strokeWidth: KRIZAKA.orbit.width, strokeDasharray: KRIZAKA.orbit.dash, opacity: 0.6, fill: "none" }) }) }),
2372
+ /* @__PURE__ */ jsx24(Animated22.View, { style: [layer, pulseStyle], children: /* @__PURE__ */ jsxs21(Svg7, { viewBox, style: layer, children: [
2373
+ /* @__PURE__ */ jsx24(Defs3, { children: blue }),
2374
+ /* @__PURE__ */ jsxs21(Group, { transform: `translate(${KRIZAKA.offset} ${KRIZAKA.offset})`, children: [
1914
2375
  dot(KRIZAKA.node),
1915
2376
  dot(KRIZAKA.core)
1916
2377
  ] })
@@ -1918,14 +2379,115 @@ function KrizakaMark({ size = 48, animated = true, title, neutral }) {
1918
2379
  ] });
1919
2380
  }
1920
2381
 
2382
+ // src/native/loader.tsx
2383
+ import * as React19 from "react";
2384
+ import { AccessibilityInfo as AccessibilityInfo6, Animated as Animated9, Easing as Easing3, StyleSheet as StyleSheet23, View as View21 } from "react-native";
2385
+ import Svg8, { Circle as Circle3, Path as Path6 } from "react-native-svg";
2386
+ import { jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
2387
+ var HEX = "M12 3 19.79 7.5 19.79 16.5 12 21 4.21 16.5 4.21 7.5Z";
2388
+ var PERIMETER = 54;
2389
+ function LoaderGlyph({ state = "loading", value, size = 20, color }) {
2390
+ const { theme } = useTheme();
2391
+ const reduce = useReducedMotion();
2392
+ const [spin] = React19.useState(() => new Animated9.Value(0));
2393
+ const known = typeof value === "number" && Number.isFinite(value);
2394
+ React19.useEffect(() => {
2395
+ if (state !== "loading" || known || reduce) return;
2396
+ const loop = Animated9.loop(Animated9.timing(spin, { toValue: 1, duration: 1400, easing: Easing3.linear, useNativeDriver: true }));
2397
+ loop.start();
2398
+ return () => loop.stop();
2399
+ }, [state, known, reduce, spin]);
2400
+ const stroke = color ?? (state === "success" ? theme.success : state === "error" ? theme.danger : theme.accent);
2401
+ const fill = state !== "loading" ? 1 : known ? Math.min(1, Math.max(0, value)) : 0.3;
2402
+ const rotate = spin.interpolate({ inputRange: [0, 1], outputRange: ["0deg", "360deg"] });
2403
+ return /* @__PURE__ */ jsx25(Animated9.View, { "aria-hidden": true, style: { width: size, height: size, transform: state === "loading" && !known ? [{ rotate }] : [] }, children: /* @__PURE__ */ jsxs22(Svg8, { width: size, height: size, viewBox: "0 0 24 24", fill: "none", children: [
2404
+ /* @__PURE__ */ jsx25(Path6, { d: HEX, stroke, strokeOpacity: 0.22, strokeWidth: 2.2, strokeLinejoin: "round" }),
2405
+ /* @__PURE__ */ jsx25(Path6, { d: HEX, stroke, strokeWidth: 2.2, strokeLinejoin: "round", strokeLinecap: "round", strokeDasharray: `${fill * PERIMETER} ${PERIMETER}` }),
2406
+ state === "loading" ? /* @__PURE__ */ jsx25(Circle3, { cx: 12, cy: 12, r: 2.6, fill: stroke }) : null,
2407
+ state === "success" ? /* @__PURE__ */ jsx25(Path6, { d: "M8.3 12.3l2.6 2.6 4.9-5.3", stroke, strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round" }) : null,
2408
+ state === "error" ? /* @__PURE__ */ jsx25(Path6, { d: "M9.4 9.4l5.2 5.2M14.6 9.4l-5.2 5.2", stroke, strokeWidth: 2.2, strokeLinecap: "round" }) : null
2409
+ ] }) });
2410
+ }
2411
+ function useDelayedWait(active, delay = 250, minDuration = 600) {
2412
+ const [shown, setShown] = React19.useState(false);
2413
+ const since = React19.useRef(0);
2414
+ React19.useEffect(() => {
2415
+ if (active && !shown) {
2416
+ const timer2 = setTimeout(() => {
2417
+ since.current = Date.now();
2418
+ setShown(true);
2419
+ }, delay);
2420
+ return () => clearTimeout(timer2);
2421
+ }
2422
+ if (!active && shown) {
2423
+ const timer2 = setTimeout(() => setShown(false), Math.max(0, minDuration - (Date.now() - since.current)));
2424
+ return () => clearTimeout(timer2);
2425
+ }
2426
+ return void 0;
2427
+ }, [active, shown, delay, minDuration]);
2428
+ return shown;
2429
+ }
2430
+ var GLYPH = { inline: 20, block: 36, overlay: 36, page: 56 };
2431
+ function Loader({ label, status = "loading", successLabel, errorLabel, value, eta, delay = 250, minDuration = 600, endDuration = 1600, variant = "inline", style }) {
2432
+ const { theme, radius: radius3 } = useTheme();
2433
+ const waiting = useDelayedWait(status === "loading", delay, minDuration);
2434
+ const [ending, setEnding] = React19.useState(null);
2435
+ const seen = React19.useRef(false);
2436
+ React19.useEffect(() => {
2437
+ if (waiting) {
2438
+ seen.current = true;
2439
+ return;
2440
+ }
2441
+ if (!seen.current || status === "loading") return;
2442
+ seen.current = false;
2443
+ if (endDuration <= 0) return;
2444
+ const show2 = setTimeout(() => setEnding(status), 0);
2445
+ const hide = Number.isFinite(endDuration) ? setTimeout(() => setEnding(null), endDuration) : void 0;
2446
+ return () => {
2447
+ clearTimeout(show2);
2448
+ clearTimeout(hide);
2449
+ };
2450
+ }, [waiting, status, endDuration]);
2451
+ const phase = waiting ? "loading" : ending;
2452
+ const words = phase === "success" ? successLabel ?? label : phase === "error" ? errorLabel ?? label : label;
2453
+ React19.useEffect(() => {
2454
+ if (phase) AccessibilityInfo6.announceForAccessibility(words);
2455
+ }, [phase, words]);
2456
+ if (!phase) return null;
2457
+ const known = phase === "loading" && typeof value === "number" && Number.isFinite(value);
2458
+ const detail = phase === "loading" ? [known ? `${Math.round(Math.min(1, Math.max(0, value)) * 100)} %` : null, eta].filter(Boolean).join(" \xB7 ") : "";
2459
+ const stacked = variant !== "inline";
2460
+ const box = /* @__PURE__ */ jsxs22(View21, { style: [stacked ? styles23.stacked : styles23.inline, variant === "overlay" ? { backgroundColor: alpha(theme.surface1, 0.92), borderColor: theme.borderDefault, borderRadius: radius3.lg, ...styles23.card } : null], children: [
2461
+ /* @__PURE__ */ jsx25(LoaderGlyph, { state: phase, value: known ? value : null, size: GLYPH[variant] }),
2462
+ /* @__PURE__ */ jsxs22(View21, { style: stacked ? styles23.center : styles23.text, children: [
2463
+ /* @__PURE__ */ jsx25(Txt, { variant: variant === "page" ? "title" : "label", style: stacked ? styles23.centered : null, children: words }),
2464
+ detail ? /* @__PURE__ */ jsx25(Txt, { variant: "caption", tone: "secondary", style: stacked ? styles23.centered : null, children: detail }) : null
2465
+ ] })
2466
+ ] });
2467
+ const a11y = { accessible: true, role: "progressbar", "aria-label": words, "aria-busy": phase === "loading", accessibilityLiveRegion: "polite" };
2468
+ if (variant === "overlay" || variant === "page")
2469
+ return /* @__PURE__ */ jsx25(View21, { ...a11y, style: [StyleSheet23.absoluteFill, styles23.cover, variant === "page" ? { backgroundColor: alpha(theme.surface0, 0.86) } : null, style], children: box });
2470
+ return /* @__PURE__ */ jsx25(View21, { ...a11y, style: [variant === "block" ? styles23.block : null, style], children: box });
2471
+ }
2472
+ var styles23 = StyleSheet23.create({
2473
+ inline: { flexDirection: "row", alignItems: "center", gap: 10 },
2474
+ stacked: { alignItems: "center", gap: 10 },
2475
+ card: { paddingHorizontal: 24, paddingVertical: 20, borderWidth: StyleSheet23.hairlineWidth },
2476
+ text: { flexShrink: 1, gap: 2 },
2477
+ center: { alignItems: "center", gap: 2 },
2478
+ centered: { textAlign: "center" },
2479
+ block: { paddingVertical: 40, alignItems: "center" },
2480
+ cover: { alignItems: "center", justifyContent: "center", zIndex: 10 }
2481
+ });
2482
+
1921
2483
  // src/native/mascot-state.tsx
1922
- import * as React16 from "react";
1923
- import { AccessibilityInfo as AccessibilityInfo5, Animated as Animated8, Easing as Easing4, StyleSheet as StyleSheet17, View as View16 } from "react-native";
2484
+ import * as React21 from "react";
2485
+ import { AccessibilityInfo as AccessibilityInfo8, Animated as Animated11, Easing as Easing5, StyleSheet as StyleSheet24, View as View23 } from "react-native";
1924
2486
 
1925
2487
  // src/native/mascots.tsx
1926
- import { useEffect as useEffect9, useState as useState15 } from "react";
1927
- import { AccessibilityInfo as AccessibilityInfo4, Animated as Animated7, Easing as Easing3, View as View15 } from "react-native";
1928
- import Svg6, { Circle as Circle2, Defs as Defs3, Ellipse, G, LinearGradient as LinearGradient3, Path as Path5, Rect as Rect2, Stop as Stop3 } from "react-native-svg";
2488
+ import { useEffect as useEffect12, useState as useState20 } from "react";
2489
+ import { AccessibilityInfo as AccessibilityInfo7, Animated as Animated10, Easing as Easing4, View as View22 } from "react-native";
2490
+ import Svg9, { Circle as Circle4, Defs as Defs4, Ellipse, G, LinearGradient as LinearGradient4, Path as Path7, Rect as Rect2, Stop as Stop4 } from "react-native-svg";
1929
2491
 
1930
2492
  // src/mascots/geometry.ts
1931
2493
  var mirror = (d) => d.replace(/(-?\d+(?:\.\d+)?) (-?\d+(?:\.\d+)?)/g, (_, x, y) => `${120 - Number(x)} ${y}`);
@@ -2083,17 +2645,17 @@ var SHADE = "#000000";
2083
2645
  var PARCEL = ["#f59e0b", "#d97706", "#b45309"];
2084
2646
 
2085
2647
  // src/native/mascots.tsx
2086
- import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
2648
+ import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
2087
2649
  function useBob(animated) {
2088
- const [y] = useState15(() => new Animated7.Value(0));
2089
- useEffect9(() => {
2650
+ const [y] = useState20(() => new Animated10.Value(0));
2651
+ useEffect12(() => {
2090
2652
  if (!animated) return;
2091
2653
  let loop;
2092
2654
  let cancelled = false;
2093
- void AccessibilityInfo4.isReduceMotionEnabled().then((reduce) => {
2655
+ void AccessibilityInfo7.isReduceMotionEnabled().then((reduce) => {
2094
2656
  if (reduce || cancelled) return;
2095
- const step = (toValue) => Animated7.timing(y, { toValue, duration: 1800, easing: Easing3.inOut(Easing3.ease), useNativeDriver: true });
2096
- loop = Animated7.loop(Animated7.sequence([step(-2.5), step(0)]));
2657
+ const step = (toValue) => Animated10.timing(y, { toValue, duration: 1800, easing: Easing4.inOut(Easing4.ease), useNativeDriver: true });
2658
+ loop = Animated10.loop(Animated10.sequence([step(-2.5), step(0)]));
2097
2659
  loop.start();
2098
2660
  });
2099
2661
  return () => {
@@ -2103,13 +2665,13 @@ function useBob(animated) {
2103
2665
  }, [animated, y]);
2104
2666
  return y;
2105
2667
  }
2106
- function Mascot({ bird = "owl", mood = "welcome", tone: tone2 = "brand", size = 96, animated = true, title, style }) {
2668
+ function Mascot({ bird = "owl", mood = "welcome", tone: tone3 = "brand", size = 96, animated = true, title, style }) {
2107
2669
  const { theme } = useTheme();
2108
2670
  const id = useSvgId("kzb");
2109
2671
  const bob = useBob(animated);
2110
2672
  const g = BIRDS[bird];
2111
2673
  const brand = { from: theme.accent2, to: theme.accent, wing: theme.accent, detail: theme.accent2, beak: theme.warning, eye: theme.textPrimary };
2112
- const p = tone2 === "own" ? OWN_PALETTES[bird] : brand;
2674
+ const p = tone3 === "own" ? OWN_PALETTES[bird] : brand;
2113
2675
  const outline = theme.borderStrong;
2114
2676
  const body = `url(#${id})`;
2115
2677
  const line = { stroke: outline, strokeWidth: 1.4, strokeLinejoin: "round" };
@@ -2117,62 +2679,62 @@ function Mascot({ bird = "owl", mood = "welcome", tone: tone2 = "brand", size =
2117
2679
  const look3 = mood === "thinking" ? 1.4 : 0;
2118
2680
  const rot = (deg, [x, y]) => `rotate(${deg} ${x} ${y})`;
2119
2681
  const [wl, wr] = g.wings;
2120
- return /* @__PURE__ */ jsx19(View15, { style: [{ width: size, height: size }, style], ...markA11y(title), children: /* @__PURE__ */ jsx19(Animated7.View, { style: { transform: [{ translateY: bob }] }, children: /* @__PURE__ */ jsxs16(Svg6, { width: size, height: size, viewBox: "0 0 120 120", children: [
2121
- /* @__PURE__ */ jsx19(Defs3, { children: /* @__PURE__ */ jsxs16(LinearGradient3, { id, x1: "0", y1: "0", x2: "0", y2: "1", children: [
2122
- /* @__PURE__ */ jsx19(Stop3, { offset: "0%", stopColor: p.from }),
2123
- /* @__PURE__ */ jsx19(Stop3, { offset: "100%", stopColor: p.to })
2682
+ return /* @__PURE__ */ jsx26(View22, { style: [{ width: size, height: size }, style], ...markA11y(title), children: /* @__PURE__ */ jsx26(Animated10.View, { style: { transform: [{ translateY: bob }] }, children: /* @__PURE__ */ jsxs23(Svg9, { width: size, height: size, viewBox: "0 0 120 120", children: [
2683
+ /* @__PURE__ */ jsx26(Defs4, { children: /* @__PURE__ */ jsxs23(LinearGradient4, { id, x1: "0", y1: "0", x2: "0", y2: "1", children: [
2684
+ /* @__PURE__ */ jsx26(Stop4, { offset: "0%", stopColor: p.from }),
2685
+ /* @__PURE__ */ jsx26(Stop4, { offset: "100%", stopColor: p.to })
2124
2686
  ] }) }),
2125
- /* @__PURE__ */ jsx19(Ellipse, { cx: g.shadow[0], cy: g.shadow[1], rx: g.shadow[2], ry: g.shadow[3], fill: SHADE, opacity: 0.14 }),
2126
- mood === "empty" && /* @__PURE__ */ jsx19(Path5, { d: MOOD_PARTS.tray, stroke: outline, strokeWidth: 1.6, strokeDasharray: "3 3", fill: "none" }),
2127
- g.legs.map((d) => /* @__PURE__ */ jsx19(Path5, { d, stroke: p.beak, strokeWidth: 2.6, strokeLinecap: "round", fill: "none" }, d)),
2128
- g.back?.map((d) => d.endsWith("Z") ? /* @__PURE__ */ jsx19(Path5, { d, fill: p.detail, ...line }, d) : /* @__PURE__ */ jsx19(Path5, { d, stroke: outline, strokeWidth: 1.4, fill: "none" }, d)),
2129
- g.parcel?.map((d, i) => /* @__PURE__ */ jsx19(Path5, { d, fill: PARCEL[i], ...line }, d)),
2130
- /* @__PURE__ */ jsx19(Path5, { d: g.body, fill: body, ...line }),
2131
- /* @__PURE__ */ jsx19(Path5, { d: g.belly, fill: LIGHT, opacity: 0.28 }),
2687
+ /* @__PURE__ */ jsx26(Ellipse, { cx: g.shadow[0], cy: g.shadow[1], rx: g.shadow[2], ry: g.shadow[3], fill: SHADE, opacity: 0.14 }),
2688
+ mood === "empty" && /* @__PURE__ */ jsx26(Path7, { d: MOOD_PARTS.tray, stroke: outline, strokeWidth: 1.6, strokeDasharray: "3 3", fill: "none" }),
2689
+ g.legs.map((d) => /* @__PURE__ */ jsx26(Path7, { d, stroke: p.beak, strokeWidth: 2.6, strokeLinecap: "round", fill: "none" }, d)),
2690
+ g.back?.map((d) => d.endsWith("Z") ? /* @__PURE__ */ jsx26(Path7, { d, fill: p.detail, ...line }, d) : /* @__PURE__ */ jsx26(Path7, { d, stroke: outline, strokeWidth: 1.4, fill: "none" }, d)),
2691
+ g.parcel?.map((d, i) => /* @__PURE__ */ jsx26(Path7, { d, fill: PARCEL[i], ...line }, d)),
2692
+ /* @__PURE__ */ jsx26(Path7, { d: g.body, fill: body, ...line }),
2693
+ /* @__PURE__ */ jsx26(Path7, { d: g.belly, fill: LIGHT, opacity: 0.28 }),
2132
2694
  [wl, wr].map((w, i) => {
2133
2695
  const turn = mood === "success" ? i === 0 ? 28 : -28 : mood === "welcome" && i === 1 ? -20 : 0;
2134
- return /* @__PURE__ */ jsxs16(G, { transform: turn ? rot(turn, w.pivot) : void 0, children: [
2135
- /* @__PURE__ */ jsx19(Path5, { d: w.d, fill: p.wing, ...line }),
2136
- /* @__PURE__ */ jsx19(Path5, { d: w.d, fill: SHADE, opacity: 0.16 })
2696
+ return /* @__PURE__ */ jsxs23(G, { transform: turn ? rot(turn, w.pivot) : void 0, children: [
2697
+ /* @__PURE__ */ jsx26(Path7, { d: w.d, fill: p.wing, ...line }),
2698
+ /* @__PURE__ */ jsx26(Path7, { d: w.d, fill: SHADE, opacity: 0.16 })
2137
2699
  ] }, i);
2138
2700
  }),
2139
- g.neck && /* @__PURE__ */ jsx19(Path5, { d: g.neck.d, stroke: body, strokeWidth: g.neck.width, strokeLinecap: "round", fill: "none" }),
2140
- g.head.r > 0 && /* @__PURE__ */ jsx19(Circle2, { cx: g.head.cx, cy: g.head.cy, r: g.head.r, fill: body, ...line }),
2141
- g.details.map((d) => /* @__PURE__ */ jsx19(Path5, { d, fill: p.detail, ...line }, d)),
2142
- g.visor && /* @__PURE__ */ jsx19(Rect2, { x: g.visor.x, y: g.visor.y, width: g.visor.w, height: g.visor.h, rx: 4, fill: theme.surface0, ...line }),
2701
+ g.neck && /* @__PURE__ */ jsx26(Path7, { d: g.neck.d, stroke: body, strokeWidth: g.neck.width, strokeLinecap: "round", fill: "none" }),
2702
+ g.head.r > 0 && /* @__PURE__ */ jsx26(Circle4, { cx: g.head.cx, cy: g.head.cy, r: g.head.r, fill: body, ...line }),
2703
+ g.details.map((d) => /* @__PURE__ */ jsx26(Path7, { d, fill: p.detail, ...line }, d)),
2704
+ g.visor && /* @__PURE__ */ jsx26(Rect2, { x: g.visor.x, y: g.visor.y, width: g.visor.w, height: g.visor.h, rx: 4, fill: theme.surface0, ...line }),
2143
2705
  g.eyes.at.map(
2144
- (at, i) => mood === "empty" && g.eyes.white > 0 ? /* @__PURE__ */ jsxs16(G, { children: [
2145
- /* @__PURE__ */ jsx19(Circle2, { cx: at[0], cy: at[1], r: g.eyes.white, fill: LIGHT, ...line }),
2146
- /* @__PURE__ */ jsx19(Circle2, { cx: at[0], cy: at[1] + g.eyes.pupil * 0.7, r: g.eyes.pupil, fill: SHADE }),
2147
- /* @__PURE__ */ jsx19(Path5, { d: upperLid(at, g.eyes.white), fill: p.detail, ...line })
2148
- ] }, i) : mood === "success" || mood === "empty" ? /* @__PURE__ */ jsx19(Path5, { d: mood === "success" ? archEye(at, eyeR * 0.85) : lidEye(at, eyeR * 0.8), stroke: g.visor ? p.eye : outline, strokeWidth: 2.2, strokeLinecap: "round", fill: "none" }, i) : /* @__PURE__ */ jsxs16(G, { children: [
2149
- g.eyes.white > 0 && /* @__PURE__ */ jsx19(Circle2, { cx: at[0], cy: at[1], r: g.eyes.white, fill: LIGHT, ...line }),
2150
- /* @__PURE__ */ jsx19(Circle2, { cx: at[0] + look3, cy: at[1] - look3, r: g.eyes.pupil, fill: g.visor ? p.eye : SHADE })
2706
+ (at, i) => mood === "empty" && g.eyes.white > 0 ? /* @__PURE__ */ jsxs23(G, { children: [
2707
+ /* @__PURE__ */ jsx26(Circle4, { cx: at[0], cy: at[1], r: g.eyes.white, fill: LIGHT, ...line }),
2708
+ /* @__PURE__ */ jsx26(Circle4, { cx: at[0], cy: at[1] + g.eyes.pupil * 0.7, r: g.eyes.pupil, fill: SHADE }),
2709
+ /* @__PURE__ */ jsx26(Path7, { d: upperLid(at, g.eyes.white), fill: p.detail, ...line })
2710
+ ] }, i) : mood === "success" || mood === "empty" ? /* @__PURE__ */ jsx26(Path7, { d: mood === "success" ? archEye(at, eyeR * 0.85) : lidEye(at, eyeR * 0.8), stroke: g.visor ? p.eye : outline, strokeWidth: 2.2, strokeLinecap: "round", fill: "none" }, i) : /* @__PURE__ */ jsxs23(G, { children: [
2711
+ g.eyes.white > 0 && /* @__PURE__ */ jsx26(Circle4, { cx: at[0], cy: at[1], r: g.eyes.white, fill: LIGHT, ...line }),
2712
+ /* @__PURE__ */ jsx26(Circle4, { cx: at[0] + look3, cy: at[1] - look3, r: g.eyes.pupil, fill: g.visor ? p.eye : SHADE })
2151
2713
  ] }, i)
2152
2714
  ),
2153
- g.glasses && g.eyes.at.map(([x, y]) => /* @__PURE__ */ jsx19(Circle2, { cx: x, cy: y, r: 6.5, fill: "none", stroke: outline, strokeWidth: 1.3 }, x)),
2154
- mood === "error" && g.eyes.at.map((at, i) => /* @__PURE__ */ jsx19(Path5, { d: brow(at, eyeR, g.eyes.at.length === 1 ? 1 : i === 0 ? -1 : 1), stroke: outline, strokeWidth: 2, strokeLinecap: "round" }, i)),
2155
- /* @__PURE__ */ jsx19(Path5, { d: g.beak, fill: p.beak, ...line }),
2156
- mood === "thinking" && MOOD_PARTS.dots.map(([cx, cy, r], i) => /* @__PURE__ */ jsx19(Circle2, { cx, cy, r, fill: theme.textSecondary, opacity: 0.5 + i * 0.25 }, cx)),
2157
- (mood === "success" || mood === "error") && /* @__PURE__ */ jsx19(Circle2, { cx: MOOD_PARTS.badge.cx, cy: MOOD_PARTS.badge.cy, r: MOOD_PARTS.badge.r, fill: mood === "success" ? theme.success : theme.danger }),
2158
- mood === "success" && /* @__PURE__ */ jsx19(Path5, { d: MOOD_PARTS.check, stroke: theme.surface0, strokeWidth: 2.6, strokeLinecap: "round", strokeLinejoin: "round", fill: "none" }),
2159
- mood === "error" && /* @__PURE__ */ jsx19(Path5, { d: MOOD_PARTS.bang.line, stroke: theme.surface0, strokeWidth: 2.8, strokeLinecap: "round" }),
2160
- mood === "error" && /* @__PURE__ */ jsx19(Circle2, { cx: MOOD_PARTS.bang.dot[0], cy: MOOD_PARTS.bang.dot[1], r: 1.6, fill: theme.surface0 })
2715
+ g.glasses && g.eyes.at.map(([x, y]) => /* @__PURE__ */ jsx26(Circle4, { cx: x, cy: y, r: 6.5, fill: "none", stroke: outline, strokeWidth: 1.3 }, x)),
2716
+ mood === "error" && g.eyes.at.map((at, i) => /* @__PURE__ */ jsx26(Path7, { d: brow(at, eyeR, g.eyes.at.length === 1 ? 1 : i === 0 ? -1 : 1), stroke: outline, strokeWidth: 2, strokeLinecap: "round" }, i)),
2717
+ /* @__PURE__ */ jsx26(Path7, { d: g.beak, fill: p.beak, ...line }),
2718
+ mood === "thinking" && MOOD_PARTS.dots.map(([cx, cy, r], i) => /* @__PURE__ */ jsx26(Circle4, { cx, cy, r, fill: theme.textSecondary, opacity: 0.5 + i * 0.25 }, cx)),
2719
+ (mood === "success" || mood === "error") && /* @__PURE__ */ jsx26(Circle4, { cx: MOOD_PARTS.badge.cx, cy: MOOD_PARTS.badge.cy, r: MOOD_PARTS.badge.r, fill: mood === "success" ? theme.success : theme.danger }),
2720
+ mood === "success" && /* @__PURE__ */ jsx26(Path7, { d: MOOD_PARTS.check, stroke: theme.surface0, strokeWidth: 2.6, strokeLinecap: "round", strokeLinejoin: "round", fill: "none" }),
2721
+ mood === "error" && /* @__PURE__ */ jsx26(Path7, { d: MOOD_PARTS.bang.line, stroke: theme.surface0, strokeWidth: 2.8, strokeLinecap: "round" }),
2722
+ mood === "error" && /* @__PURE__ */ jsx26(Circle4, { cx: MOOD_PARTS.bang.dot[0], cy: MOOD_PARTS.bang.dot[1], r: 1.6, fill: theme.surface0 })
2161
2723
  ] }) }) });
2162
2724
  }
2163
2725
 
2164
2726
  // src/native/mascot-state.tsx
2165
- import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
2727
+ import { jsx as jsx27, jsxs as jsxs24 } from "react/jsx-runtime";
2166
2728
  var SIZE = { sm: 64, md: 96, lg: 128 };
2167
2729
  function useArrival(animated) {
2168
- const [value] = React16.useState(() => new Animated8.Value(animated ? 0 : 1));
2169
- React16.useEffect(() => {
2730
+ const [value] = React21.useState(() => new Animated11.Value(animated ? 0 : 1));
2731
+ React21.useEffect(() => {
2170
2732
  if (!animated) return;
2171
2733
  let cancelled = false;
2172
- void AccessibilityInfo5.isReduceMotionEnabled().then((reduce) => {
2734
+ void AccessibilityInfo8.isReduceMotionEnabled().then((reduce) => {
2173
2735
  if (cancelled) return;
2174
2736
  if (reduce) value.setValue(1);
2175
- else Animated8.timing(value, { toValue: 1, duration: 420, easing: Easing4.out(Easing4.cubic), useNativeDriver: true }).start();
2737
+ else Animated11.timing(value, { toValue: 1, duration: 420, easing: Easing5.out(Easing5.cubic), useNativeDriver: true }).start();
2176
2738
  });
2177
2739
  return () => {
2178
2740
  cancelled = true;
@@ -2180,33 +2742,33 @@ function useArrival(animated) {
2180
2742
  }, [animated, value]);
2181
2743
  return value;
2182
2744
  }
2183
- function MascotState({ bird = "owl", mood = "empty", title, description, action, size = "md", layout = "stacked", tone: tone2, animated = true, style, ...props }) {
2745
+ function MascotState({ bird = "owl", mood = "empty", title, description, action, size = "md", layout = "stacked", tone: tone3, animated = true, style, ...props }) {
2184
2746
  const opacity = useArrival(animated);
2185
2747
  const inline = layout === "inline";
2186
- return /* @__PURE__ */ jsxs17(
2187
- Animated8.View,
2748
+ return /* @__PURE__ */ jsxs24(
2749
+ Animated11.View,
2188
2750
  {
2189
2751
  role: mood === "error" ? "alert" : "status",
2190
2752
  accessibilityLiveRegion: mood === "error" ? "assertive" : "polite",
2191
2753
  "aria-busy": mood === "thinking" ? true : void 0,
2192
2754
  ...props,
2193
- style: [inline ? styles17.inline : styles17.stacked, { opacity, transform: [{ translateY: opacity.interpolate({ inputRange: [0, 1], outputRange: [6, 0] }) }] }, style],
2755
+ style: [inline ? styles24.inline : styles24.stacked, { opacity, transform: [{ translateY: opacity.interpolate({ inputRange: [0, 1], outputRange: [6, 0] }) }] }, style],
2194
2756
  children: [
2195
- /* @__PURE__ */ jsx20(Mascot, { bird, mood, tone: tone2, size: SIZE[size], animated }),
2196
- /* @__PURE__ */ jsxs17(View16, { style: inline ? styles17.wordsInline : styles17.words, children: [
2197
- /* @__PURE__ */ jsx20(Txt, { variant: "label", role: "heading", style: inline ? null : styles17.center, children: title }),
2198
- description ? /* @__PURE__ */ jsx20(Txt, { tone: "secondary", style: inline ? null : styles17.center, children: description }) : null,
2199
- action ? /* @__PURE__ */ jsx20(View16, { style: [styles17.action, inline ? null : styles17.actionCentred], children: action }) : null
2757
+ /* @__PURE__ */ jsx27(Mascot, { bird, mood, tone: tone3, size: SIZE[size], animated }),
2758
+ /* @__PURE__ */ jsxs24(View23, { style: inline ? styles24.wordsInline : styles24.words, children: [
2759
+ /* @__PURE__ */ jsx27(Txt, { variant: "label", role: "heading", style: inline ? null : styles24.center, children: title }),
2760
+ description ? /* @__PURE__ */ jsx27(Txt, { tone: "secondary", style: inline ? null : styles24.center, children: description }) : null,
2761
+ action ? /* @__PURE__ */ jsx27(View23, { style: [styles24.action, inline ? null : styles24.actionCentred], children: action }) : null
2200
2762
  ] })
2201
2763
  ]
2202
2764
  }
2203
2765
  );
2204
2766
  }
2205
- var ErrorState = (props) => /* @__PURE__ */ jsx20(MascotState, { mood: "error", ...props });
2206
- var SuccessState = (props) => /* @__PURE__ */ jsx20(MascotState, { mood: "success", ...props });
2207
- var LoadingState = (props) => /* @__PURE__ */ jsx20(MascotState, { mood: "thinking", ...props });
2208
- var WelcomeState = (props) => /* @__PURE__ */ jsx20(MascotState, { mood: "welcome", ...props });
2209
- var styles17 = StyleSheet17.create({
2767
+ var ErrorState = (props) => /* @__PURE__ */ jsx27(MascotState, { mood: "error", ...props });
2768
+ var SuccessState = (props) => /* @__PURE__ */ jsx27(MascotState, { mood: "success", ...props });
2769
+ var LoadingState = (props) => /* @__PURE__ */ jsx27(MascotState, { mood: "thinking", ...props });
2770
+ var WelcomeState = (props) => /* @__PURE__ */ jsx27(MascotState, { mood: "welcome", ...props });
2771
+ var styles24 = StyleSheet24.create({
2210
2772
  stacked: { alignItems: "center", justifyContent: "center", gap: 12, paddingVertical: 40, paddingHorizontal: 24 },
2211
2773
  inline: { flexDirection: "row", alignItems: "center", gap: 16 },
2212
2774
  words: { alignItems: "center", gap: 6 },
@@ -2216,9 +2778,150 @@ var styles17 = StyleSheet17.create({
2216
2778
  actionCentred: { justifyContent: "center" }
2217
2779
  });
2218
2780
 
2781
+ // src/native/meter.tsx
2782
+ import { StyleSheet as StyleSheet25, View as View24 } from "react-native";
2783
+ import Svg10, { Circle as Circle5 } from "react-native-svg";
2784
+ import { jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
2785
+ var THICK = { sm: 6, md: 8, lg: 12 };
2786
+ var RING = { sm: 56, md: 96, lg: 144 };
2787
+ var partColor = (t, i) => [t.accent, t.warning, t.success, t.textSecondary, t.danger][i % 5];
2788
+ function Meter({ label, value = 0, min = 0, max = 100, valueText, thresholds, optimum = "low", parts, variant = "bar", size = "md", showLabel, children, style }) {
2789
+ const { theme } = useTheme();
2790
+ const span = max - min || 1;
2791
+ const ratio = Math.min(1, Math.max(0, (value - min) / span));
2792
+ const level = !thresholds ? "ok" : ratio >= thresholds.high ? optimum === "low" ? "danger" : "success" : ratio >= thresholds.low ? "warning" : optimum === "low" ? "success" : "danger";
2793
+ const tone3 = { ok: theme.accent, success: theme.success, warning: theme.warning, danger: theme.danger }[level];
2794
+ const words = valueText ?? `${Math.round(ratio * 100)} %`;
2795
+ const shares = (parts ?? []).map((p, i) => ({ ...p, color: partColor(theme, i), ratio: Math.min(1, Math.max(0, p.value / span)), words: p.valueText ?? `${Math.round(p.value / span * 100)} %` }));
2796
+ const a11y = parts ? { role: "group", "aria-label": `${label}: ${shares.map((p) => `${p.label} ${p.words}`).join(", ")}` } : { role: "meter", "aria-label": label, "aria-valuemin": min, "aria-valuemax": max, "aria-valuenow": Math.min(max, Math.max(min, value)), "aria-valuetext": words };
2797
+ const legend = parts ? /* @__PURE__ */ jsx28(View24, { style: styles25.legend, "aria-hidden": true, children: shares.map((p, i) => /* @__PURE__ */ jsxs25(View24, { style: styles25.legendItem, children: [
2798
+ /* @__PURE__ */ jsx28(View24, { style: [styles25.swatch, { backgroundColor: p.color }] }),
2799
+ /* @__PURE__ */ jsx28(Txt, { variant: "caption", children: p.label }),
2800
+ /* @__PURE__ */ jsx28(Txt, { variant: "caption", tone: "secondary", children: p.words })
2801
+ ] }, i)) }) : null;
2802
+ if (variant === "ring") {
2803
+ const side = RING[size];
2804
+ const r = 44;
2805
+ const c = 2 * Math.PI * r;
2806
+ let offset = 0;
2807
+ const arcs = parts ? shares.map((p) => {
2808
+ const arc = { color: p.color, len: p.ratio, start: offset };
2809
+ offset += p.ratio;
2810
+ return arc;
2811
+ }) : [{ color: tone3, len: ratio, start: 0 }];
2812
+ return /* @__PURE__ */ jsxs25(View24, { accessible: true, ...a11y, style: [styles25.ringRoot, style], children: [
2813
+ /* @__PURE__ */ jsxs25(View24, { style: { width: side, height: side }, children: [
2814
+ /* @__PURE__ */ jsxs25(Svg10, { width: side, height: side, viewBox: "0 0 100 100", style: { transform: [{ rotate: "-90deg" }] }, children: [
2815
+ /* @__PURE__ */ jsx28(Circle5, { cx: 50, cy: 50, r, fill: "none", stroke: theme.borderDefault, strokeWidth: 9 }),
2816
+ arcs.map((a, i) => /* @__PURE__ */ jsx28(Circle5, { cx: 50, cy: 50, r, fill: "none", stroke: a.color, strokeWidth: 9, strokeDasharray: `${Math.max(0, a.len * c - (parts ? 2 : 0))} ${c}`, strokeDashoffset: -a.start * c, strokeLinecap: parts ? "butt" : "round" }, i))
2817
+ ] }),
2818
+ children !== void 0 ? /* @__PURE__ */ jsx28(View24, { style: [StyleSheet25.absoluteFill, styles25.center], children }) : null
2819
+ ] }),
2820
+ legend
2821
+ ] });
2822
+ }
2823
+ return /* @__PURE__ */ jsxs25(View24, { accessible: true, ...a11y, style: [styles25.root, style], children: [
2824
+ showLabel ? /* @__PURE__ */ jsxs25(View24, { style: styles25.header, "aria-hidden": true, children: [
2825
+ /* @__PURE__ */ jsx28(Txt, { variant: "caption", numberOfLines: 1, style: styles25.caption, children: label }),
2826
+ !parts ? /* @__PURE__ */ jsx28(Txt, { variant: "caption", tone: "secondary", children: words }) : null
2827
+ ] }) : null,
2828
+ /* @__PURE__ */ jsx28(View24, { style: [styles25.track, { height: THICK[size], backgroundColor: theme.surface3 }], children: parts ? shares.map((p, i) => /* @__PURE__ */ jsx28(View24, { style: { width: `${p.ratio * 100}%`, backgroundColor: p.color } }, i)) : /* @__PURE__ */ jsx28(View24, { style: [styles25.fill, { width: `${ratio * 100}%`, backgroundColor: tone3 }] }) }),
2829
+ legend
2830
+ ] });
2831
+ }
2832
+ var styles25 = StyleSheet25.create({
2833
+ root: { width: "100%", gap: 6 },
2834
+ header: { flexDirection: "row", alignItems: "baseline", gap: 8 },
2835
+ caption: { flex: 1, fontWeight: "600" },
2836
+ track: { flexDirection: "row", gap: 2, borderRadius: 999, overflow: "hidden", width: "100%" },
2837
+ fill: { height: "100%", borderRadius: 999 },
2838
+ legend: { flexDirection: "row", flexWrap: "wrap", columnGap: 14, rowGap: 4, marginTop: 4 },
2839
+ legendItem: { flexDirection: "row", alignItems: "center", gap: 6 },
2840
+ swatch: { width: 8, height: 8, borderRadius: 4 },
2841
+ ringRoot: { alignItems: "center", gap: 8 },
2842
+ center: { alignItems: "center", justifyContent: "center" }
2843
+ });
2844
+
2845
+ // src/native/number-ticker.tsx
2846
+ import * as React22 from "react";
2847
+ import { AccessibilityInfo as AccessibilityInfo9, Animated as Animated12, Easing as Easing6, Text as Text13 } from "react-native";
2848
+ import { jsx as jsx29 } from "react/jsx-runtime";
2849
+ function NumberTicker({ value, locale, format, trigger = "mount", duration = 1100, announce, variant = "display", tone: tone3 = "text", style }) {
2850
+ const reduce = useReducedMotion();
2851
+ const writer = React22.useMemo(() => new Intl.NumberFormat(locale, format), [locale, format]);
2852
+ const [shown, setShown] = React22.useState(() => reduce ? value : trigger === "mount" ? 0 : value);
2853
+ const [anim] = React22.useState(() => new Animated12.Value(trigger === "mount" ? 0 : value));
2854
+ const first = React22.useRef(true);
2855
+ React22.useEffect(() => {
2856
+ const isFirst = first.current;
2857
+ first.current = false;
2858
+ if (reduce || !isFirst && trigger === "mount" || isFirst && trigger === "change") {
2859
+ anim.setValue(value);
2860
+ setShown(value);
2861
+ if (!isFirst && announce) AccessibilityInfo9.announceForAccessibility(writer.format(value));
2862
+ return;
2863
+ }
2864
+ const id = anim.addListener(({ value: v }) => setShown(v));
2865
+ const run = Animated12.timing(anim, { toValue: value, duration, easing: Easing6.out(Easing6.cubic), useNativeDriver: false });
2866
+ run.start(({ finished }) => {
2867
+ if (finished) setShown(value);
2868
+ });
2869
+ if (!isFirst && announce) AccessibilityInfo9.announceForAccessibility(writer.format(value));
2870
+ return () => {
2871
+ run.stop();
2872
+ anim.removeListener(id);
2873
+ };
2874
+ }, [value, reduce, trigger, duration, announce, anim, writer]);
2875
+ const digits = Number.isInteger(value) ? Math.round(shown) : shown;
2876
+ return /* @__PURE__ */ jsx29(Txt, { variant, tone: tone3, "aria-label": writer.format(value), style: [{ fontVariant: ["tabular-nums"] }, style], children: /* @__PURE__ */ jsx29(Text13, { "aria-hidden": true, children: writer.format(digits) }) });
2877
+ }
2878
+
2879
+ // src/native/onboarding.tsx
2880
+ import * as React23 from "react";
2881
+ import { ScrollView as ScrollView5, StyleSheet as StyleSheet26, View as View25 } from "react-native";
2882
+ import { jsx as jsx30, jsxs as jsxs26 } from "react/jsx-runtime";
2883
+ function Onboarding({ slides, labels, onDone, style }) {
2884
+ const { theme, insets, haptic } = useTheme();
2885
+ const [width, setWidth] = React23.useState(0);
2886
+ const [page, setPage] = React23.useState(0);
2887
+ const scroller = React23.useRef(null);
2888
+ const last = page === slides.length - 1;
2889
+ const go = (to) => {
2890
+ scroller.current?.scrollTo({ x: to * width, animated: true });
2891
+ setPage(to);
2892
+ haptic("selection");
2893
+ };
2894
+ const onScroll = (e) => {
2895
+ if (width > 0) setPage(Math.round(e.nativeEvent.contentOffset.x / width));
2896
+ };
2897
+ return /* @__PURE__ */ jsxs26(View25, { style: [styles26.root, { backgroundColor: theme.surface0, paddingTop: insets.top + 8, paddingBottom: insets.bottom + 16 }, style], onLayout: (e) => setWidth(e.nativeEvent.layout.width), children: [
2898
+ /* @__PURE__ */ jsx30(View25, { style: styles26.top, children: !last ? /* @__PURE__ */ jsx30(Button, { label: labels.skip, variant: "ghost", size: "sm", onPress: onDone }) : /* @__PURE__ */ jsx30(View25, { style: styles26.spacer }) }),
2899
+ /* @__PURE__ */ jsx30(ScrollView5, { ref: scroller, tabIndex: 0, horizontal: true, pagingEnabled: true, showsHorizontalScrollIndicator: false, onMomentumScrollEnd: onScroll, style: styles26.flex, children: slides.map((slide, i) => /* @__PURE__ */ jsxs26(View25, { style: [styles26.slide, { width: width || void 0 }], accessible: true, "aria-label": `${labels.position(i + 1, slides.length)}. ${slide.title}. ${slide.description}`, "aria-hidden": i !== page, children: [
2900
+ slide.visual ? /* @__PURE__ */ jsx30(View25, { style: styles26.visual, children: slide.visual }) : null,
2901
+ /* @__PURE__ */ jsx30(Txt, { variant: "display", style: styles26.centred, children: slide.title }),
2902
+ /* @__PURE__ */ jsx30(Txt, { tone: "secondary", style: [styles26.centred, styles26.description], children: slide.description })
2903
+ ] }, i)) }),
2904
+ /* @__PURE__ */ jsx30(View25, { style: styles26.dots, "aria-hidden": true, children: slides.map((_, i) => /* @__PURE__ */ jsx30(View25, { style: [styles26.dot, { width: i === page ? 22 : 8, backgroundColor: i === page ? theme.accent : theme.borderStrong }] }, i)) }),
2905
+ /* @__PURE__ */ jsx30(View25, { style: styles26.bottom, children: /* @__PURE__ */ jsx30(Button, { label: last ? labels.done : labels.next, variant: last ? "gradient" : "primary", size: "lg", onPress: () => last ? onDone() : go(page + 1) }) })
2906
+ ] });
2907
+ }
2908
+ var styles26 = StyleSheet26.create({
2909
+ root: { flex: 1 },
2910
+ top: { flexDirection: "row", justifyContent: "flex-end", paddingHorizontal: 16, minHeight: 32 },
2911
+ spacer: { height: 32 },
2912
+ flex: { flex: 1 },
2913
+ slide: { flex: 1, alignItems: "center", justifyContent: "center", paddingHorizontal: 32, gap: 12 },
2914
+ visual: { marginBottom: 12 },
2915
+ centred: { textAlign: "center" },
2916
+ description: { maxWidth: 340 },
2917
+ dots: { flexDirection: "row", justifyContent: "center", gap: 6, marginVertical: 16 },
2918
+ dot: { height: 8, borderRadius: 4 },
2919
+ bottom: { paddingHorizontal: 24 }
2920
+ });
2921
+
2219
2922
  // src/native/OrazakaMark.tsx
2220
- import { View as View17 } from "react-native";
2221
- import Svg7, { Circle as Circle3, Defs as Defs4, LinearGradient as LinearGradient4, Path as Path6, RadialGradient as RadialGradient2, Stop as Stop4 } from "react-native-svg";
2923
+ import { View as View26 } from "react-native";
2924
+ import Svg11, { Circle as Circle6, Defs as Defs5, LinearGradient as LinearGradient5, Path as Path8, RadialGradient as RadialGradient2, Stop as Stop5 } from "react-native-svg";
2222
2925
 
2223
2926
  // src/marks/orazaka-geometry.ts
2224
2927
  var orange = marks.orazaka[marks.orazaka.length - 1][1];
@@ -2247,41 +2950,41 @@ var ORAZAKA = {
2247
2950
  };
2248
2951
 
2249
2952
  // src/native/OrazakaMark.tsx
2250
- import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
2953
+ import { jsx as jsx31, jsxs as jsxs27 } from "react/jsx-runtime";
2251
2954
  function OrazakaMark({ size = 48, animated = true, title, neutral }) {
2252
2955
  const { theme } = useTheme();
2253
- const { Animated: Animated17, layer, spinStyle, pulseStyle } = useMarkMotion(size, animated);
2956
+ const { Animated: Animated22, layer, spinStyle, pulseStyle } = useMarkMotion(size, animated);
2254
2957
  const id = useSvgId("ozm");
2255
2958
  const viewBox = size < 48 ? ORAZAKA.croppedViewBox : ORAZAKA.viewBox;
2256
2959
  const stroke = neutral ?? theme.textMuted;
2257
- const gradient = /* @__PURE__ */ jsx21(LinearGradient4, { id: `${id}a`, gradientUnits: "userSpaceOnUse", x1: ORAZAKA.gradient.x1, y1: ORAZAKA.gradient.y1, x2: ORAZAKA.gradient.x2, y2: ORAZAKA.gradient.y2, children: ORAZAKA.gradient.stops.map(([offset, color]) => /* @__PURE__ */ jsx21(Stop4, { offset, stopColor: color }, offset)) });
2960
+ const gradient = /* @__PURE__ */ jsx31(LinearGradient5, { id: `${id}a`, gradientUnits: "userSpaceOnUse", x1: ORAZAKA.gradient.x1, y1: ORAZAKA.gradient.y1, x2: ORAZAKA.gradient.x2, y2: ORAZAKA.gradient.y2, children: ORAZAKA.gradient.stops.map(([offset, color]) => /* @__PURE__ */ jsx31(Stop5, { offset, stopColor: color }, offset)) });
2258
2961
  const fill = `url(#${id}a)`;
2259
- return /* @__PURE__ */ jsxs18(View17, { style: { width: size, height: size }, ...markA11y(title), children: [
2260
- /* @__PURE__ */ jsxs18(Svg7, { viewBox, style: layer, children: [
2261
- /* @__PURE__ */ jsx21(Defs4, { children: /* @__PURE__ */ jsxs18(RadialGradient2, { id: `${id}g`, cx: "50%", cy: "50%", r: "50%", children: [
2262
- /* @__PURE__ */ jsx21(Stop4, { offset: "0%", stopColor: ORAZAKA.glow.color, stopOpacity: ORAZAKA.glow.opacity }),
2263
- /* @__PURE__ */ jsx21(Stop4, { offset: "100%", stopColor: ORAZAKA.glow.color, stopOpacity: 0 })
2962
+ return /* @__PURE__ */ jsxs27(View26, { style: { width: size, height: size }, ...markA11y(title), children: [
2963
+ /* @__PURE__ */ jsxs27(Svg11, { viewBox, style: layer, children: [
2964
+ /* @__PURE__ */ jsx31(Defs5, { children: /* @__PURE__ */ jsxs27(RadialGradient2, { id: `${id}g`, cx: "50%", cy: "50%", r: "50%", children: [
2965
+ /* @__PURE__ */ jsx31(Stop5, { offset: "0%", stopColor: ORAZAKA.glow.color, stopOpacity: ORAZAKA.glow.opacity }),
2966
+ /* @__PURE__ */ jsx31(Stop5, { offset: "100%", stopColor: ORAZAKA.glow.color, stopOpacity: 0 })
2264
2967
  ] }) }),
2265
- size >= 48 ? /* @__PURE__ */ jsx21(Circle3, { cx: ORAZAKA.center, cy: ORAZAKA.center, r: 190, fill: `url(#${id}g)` }) : null,
2266
- /* @__PURE__ */ jsx21(Circle3, { cx: ORAZAKA.center, cy: ORAZAKA.center, r: ORAZAKA.orbit.r, stroke, strokeWidth: ORAZAKA.orbit.width, strokeDasharray: ORAZAKA.orbit.dash, opacity: 0.6, fill: "none" }),
2267
- /* @__PURE__ */ jsx21(Circle3, { cx: ORAZAKA.center, cy: ORAZAKA.center, r: ORAZAKA.ring.r, stroke, strokeWidth: ORAZAKA.ring.width, opacity: 0.35, fill: "none" })
2968
+ size >= 48 ? /* @__PURE__ */ jsx31(Circle6, { cx: ORAZAKA.center, cy: ORAZAKA.center, r: 190, fill: `url(#${id}g)` }) : null,
2969
+ /* @__PURE__ */ jsx31(Circle6, { cx: ORAZAKA.center, cy: ORAZAKA.center, r: ORAZAKA.orbit.r, stroke, strokeWidth: ORAZAKA.orbit.width, strokeDasharray: ORAZAKA.orbit.dash, opacity: 0.6, fill: "none" }),
2970
+ /* @__PURE__ */ jsx31(Circle6, { cx: ORAZAKA.center, cy: ORAZAKA.center, r: ORAZAKA.ring.r, stroke, strokeWidth: ORAZAKA.ring.width, opacity: 0.35, fill: "none" })
2268
2971
  ] }),
2269
- /* @__PURE__ */ jsx21(Animated17.View, { style: [layer, spinStyle], children: /* @__PURE__ */ jsxs18(Svg7, { viewBox, style: layer, children: [
2270
- /* @__PURE__ */ jsx21(Defs4, { children: gradient }),
2271
- ORAZAKA.shards.map((d) => /* @__PURE__ */ jsx21(Path6, { d, fill, stroke: fill, strokeWidth: ORAZAKA.shardStroke, strokeLinejoin: "round" }, d))
2972
+ /* @__PURE__ */ jsx31(Animated22.View, { style: [layer, spinStyle], children: /* @__PURE__ */ jsxs27(Svg11, { viewBox, style: layer, children: [
2973
+ /* @__PURE__ */ jsx31(Defs5, { children: gradient }),
2974
+ ORAZAKA.shards.map((d) => /* @__PURE__ */ jsx31(Path8, { d, fill, stroke: fill, strokeWidth: ORAZAKA.shardStroke, strokeLinejoin: "round" }, d))
2272
2975
  ] }) }),
2273
- /* @__PURE__ */ jsx21(Animated17.View, { style: [layer, pulseStyle], children: /* @__PURE__ */ jsxs18(Svg7, { viewBox, style: layer, children: [
2274
- /* @__PURE__ */ jsx21(Defs4, { children: gradient }),
2275
- /* @__PURE__ */ jsx21(Circle3, { cx: ORAZAKA.center, cy: ORAZAKA.center, r: ORAZAKA.core.r, fill }),
2276
- /* @__PURE__ */ jsx21(Circle3, { cx: ORAZAKA.center, cy: ORAZAKA.center, r: ORAZAKA.core.inner, fill: ORAZAKA.highlight })
2976
+ /* @__PURE__ */ jsx31(Animated22.View, { style: [layer, pulseStyle], children: /* @__PURE__ */ jsxs27(Svg11, { viewBox, style: layer, children: [
2977
+ /* @__PURE__ */ jsx31(Defs5, { children: gradient }),
2978
+ /* @__PURE__ */ jsx31(Circle6, { cx: ORAZAKA.center, cy: ORAZAKA.center, r: ORAZAKA.core.r, fill }),
2979
+ /* @__PURE__ */ jsx31(Circle6, { cx: ORAZAKA.center, cy: ORAZAKA.center, r: ORAZAKA.core.inner, fill: ORAZAKA.highlight })
2277
2980
  ] }) })
2278
2981
  ] });
2279
2982
  }
2280
2983
 
2281
2984
  // src/native/OrochiaMark.tsx
2282
- import { useEffect as useEffect11, useState as useState17 } from "react";
2283
- import { AccessibilityInfo as AccessibilityInfo6, Animated as Animated9, Easing as Easing5, View as View18 } from "react-native";
2284
- import Svg8, { Circle as Circle4, Defs as Defs5, Ellipse as Ellipse2, G as Group2, LinearGradient as LinearGradient5, Path as Path7, RadialGradient as RadialGradient3, Stop as Stop5 } from "react-native-svg";
2985
+ import { useEffect as useEffect15, useState as useState24 } from "react";
2986
+ import { AccessibilityInfo as AccessibilityInfo10, Animated as Animated13, Easing as Easing7, View as View27 } from "react-native";
2987
+ import Svg12, { Circle as Circle7, Defs as Defs6, Ellipse as Ellipse2, G as Group2, LinearGradient as LinearGradient6, Path as Path9, RadialGradient as RadialGradient3, Stop as Stop6 } from "react-native-svg";
2285
2988
 
2286
2989
  // src/marks/orochia-geometry.ts
2287
2990
  var OROCHIA = {
@@ -2308,25 +3011,25 @@ var OROCHIA = {
2308
3011
  };
2309
3012
 
2310
3013
  // src/native/OrochiaMark.tsx
2311
- import { jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
3014
+ import { jsx as jsx32, jsxs as jsxs28 } from "react/jsx-runtime";
2312
3015
  var CENTER = OROCHIA.offset + 180;
2313
3016
  function OrochiaMark({ size = 48, animated = true, title, neutral: neutralProp }) {
2314
3017
  const { theme } = useTheme();
2315
3018
  const neutral = neutralProp ?? theme.textMuted;
2316
- const [spin] = useState17(() => new Animated9.Value(0));
2317
- const [pulse] = useState17(() => new Animated9.Value(0));
2318
- useEffect11(() => {
3019
+ const [spin] = useState24(() => new Animated13.Value(0));
3020
+ const [pulse] = useState24(() => new Animated13.Value(0));
3021
+ useEffect15(() => {
2319
3022
  if (!animated) return;
2320
3023
  let loops = [];
2321
3024
  let cancelled = false;
2322
- void AccessibilityInfo6.isReduceMotionEnabled().then((reduce) => {
3025
+ void AccessibilityInfo10.isReduceMotionEnabled().then((reduce) => {
2323
3026
  if (reduce || cancelled) return;
2324
3027
  loops = [
2325
- Animated9.loop(Animated9.timing(spin, { toValue: 1, duration: 3e4, easing: Easing5.linear, useNativeDriver: true })),
2326
- Animated9.loop(
2327
- Animated9.sequence([
2328
- Animated9.timing(pulse, { toValue: 1, duration: 1600, easing: Easing5.inOut(Easing5.ease), useNativeDriver: true }),
2329
- Animated9.timing(pulse, { toValue: 0, duration: 1600, easing: Easing5.inOut(Easing5.ease), useNativeDriver: true })
3028
+ Animated13.loop(Animated13.timing(spin, { toValue: 1, duration: 3e4, easing: Easing7.linear, useNativeDriver: true })),
3029
+ Animated13.loop(
3030
+ Animated13.sequence([
3031
+ Animated13.timing(pulse, { toValue: 1, duration: 1600, easing: Easing7.inOut(Easing7.ease), useNativeDriver: true }),
3032
+ Animated13.timing(pulse, { toValue: 0, duration: 1600, easing: Easing7.inOut(Easing7.ease), useNativeDriver: true })
2330
3033
  ])
2331
3034
  )
2332
3035
  ];
@@ -2340,44 +3043,117 @@ function OrochiaMark({ size = 48, animated = true, title, neutral: neutralProp }
2340
3043
  const viewBox = size < 48 ? OROCHIA.croppedViewBox : OROCHIA.viewBox;
2341
3044
  const layer = { position: "absolute", width: size, height: size };
2342
3045
  const a11y = title ? { accessible: true, accessibilityRole: "image", accessibilityLabel: title } : { accessibilityElementsHidden: true, importantForAccessibility: "no-hide-descendants" };
2343
- const bodyGradient = /* @__PURE__ */ jsx22(LinearGradient5, { id: "body", gradientUnits: "userSpaceOnUse", x1: OROCHIA.body.x1 + OROCHIA.offset, y1: OROCHIA.body.y1 + OROCHIA.offset, x2: OROCHIA.body.x2 + OROCHIA.offset, y2: OROCHIA.body.y2 + OROCHIA.offset, children: OROCHIA.body.stops.map(([offset, color]) => /* @__PURE__ */ jsx22(Stop5, { offset, stopColor: color }, offset)) });
2344
- return /* @__PURE__ */ jsxs19(View18, { style: { width: size, height: size }, ...a11y, children: [
2345
- /* @__PURE__ */ jsxs19(Svg8, { viewBox, style: layer, children: [
2346
- /* @__PURE__ */ jsx22(Defs5, { children: /* @__PURE__ */ jsxs19(RadialGradient3, { id: "glow", cx: "50%", cy: "50%", r: "50%", children: [
2347
- /* @__PURE__ */ jsx22(Stop5, { offset: "0%", stopColor: OROCHIA.glow.color, stopOpacity: OROCHIA.glow.opacity }),
2348
- /* @__PURE__ */ jsx22(Stop5, { offset: "100%", stopColor: OROCHIA.glow.color, stopOpacity: 0 })
3046
+ const bodyGradient = /* @__PURE__ */ jsx32(LinearGradient6, { id: "body", gradientUnits: "userSpaceOnUse", x1: OROCHIA.body.x1 + OROCHIA.offset, y1: OROCHIA.body.y1 + OROCHIA.offset, x2: OROCHIA.body.x2 + OROCHIA.offset, y2: OROCHIA.body.y2 + OROCHIA.offset, children: OROCHIA.body.stops.map(([offset, color]) => /* @__PURE__ */ jsx32(Stop6, { offset, stopColor: color }, offset)) });
3047
+ return /* @__PURE__ */ jsxs28(View27, { style: { width: size, height: size }, ...a11y, children: [
3048
+ /* @__PURE__ */ jsxs28(Svg12, { viewBox, style: layer, children: [
3049
+ /* @__PURE__ */ jsx32(Defs6, { children: /* @__PURE__ */ jsxs28(RadialGradient3, { id: "glow", cx: "50%", cy: "50%", r: "50%", children: [
3050
+ /* @__PURE__ */ jsx32(Stop6, { offset: "0%", stopColor: OROCHIA.glow.color, stopOpacity: OROCHIA.glow.opacity }),
3051
+ /* @__PURE__ */ jsx32(Stop6, { offset: "100%", stopColor: OROCHIA.glow.color, stopOpacity: 0 })
2349
3052
  ] }) }),
2350
- /* @__PURE__ */ jsx22(Circle4, { cx: CENTER, cy: CENTER, r: 170, fill: "url(#glow)" }),
2351
- /* @__PURE__ */ jsx22(Circle4, { cx: CENTER, cy: CENTER, r: OROCHIA.ring.r, stroke: neutral, strokeWidth: OROCHIA.ring.width, opacity: 0.35, fill: "none" })
3053
+ /* @__PURE__ */ jsx32(Circle7, { cx: CENTER, cy: CENTER, r: 170, fill: "url(#glow)" }),
3054
+ /* @__PURE__ */ jsx32(Circle7, { cx: CENTER, cy: CENTER, r: OROCHIA.ring.r, stroke: neutral, strokeWidth: OROCHIA.ring.width, opacity: 0.35, fill: "none" })
2352
3055
  ] }),
2353
- /* @__PURE__ */ jsx22(Animated9.View, { style: [layer, { transform: [{ rotate: spin.interpolate({ inputRange: [0, 1], outputRange: ["0deg", "360deg"] }) }] }], children: /* @__PURE__ */ jsx22(Svg8, { viewBox, style: layer, children: /* @__PURE__ */ jsx22(Circle4, { cx: CENTER, cy: CENTER, r: OROCHIA.orbit.r, stroke: neutral, strokeWidth: OROCHIA.orbit.width, strokeDasharray: OROCHIA.orbit.dash, opacity: 0.6, fill: "none" }) }) }),
2354
- /* @__PURE__ */ jsxs19(Svg8, { viewBox, style: layer, children: [
2355
- /* @__PURE__ */ jsx22(Defs5, { children: bodyGradient }),
2356
- /* @__PURE__ */ jsxs19(Group2, { transform: `translate(${OROCHIA.offset} ${OROCHIA.offset})`, children: [
2357
- /* @__PURE__ */ jsx22(Path7, { d: OROCHIA.arc, stroke: "url(#body)", strokeWidth: 22, strokeLinecap: "round", fill: "none" }),
2358
- /* @__PURE__ */ jsx22(Path7, { d: OROCHIA.arc, stroke: OROCHIA.scales.color, strokeOpacity: OROCHIA.scales.opacity, strokeWidth: OROCHIA.scales.width, strokeLinecap: "round", strokeDasharray: OROCHIA.scales.dash, fill: "none" }),
2359
- /* @__PURE__ */ jsx22(Path7, { d: OROCHIA.neck, stroke: "url(#body)", strokeWidth: 14, strokeLinecap: "round", fill: "none" }),
2360
- /* @__PURE__ */ jsx22(Path7, { d: OROCHIA.tail, stroke: "url(#body)", strokeWidth: 6, strokeLinecap: "round", fill: "none" }),
2361
- /* @__PURE__ */ jsx22(Ellipse2, { cx: OROCHIA.head.cx, cy: OROCHIA.head.cy, rx: OROCHIA.head.rx, ry: OROCHIA.head.ry, rotation: OROCHIA.head.rotate, origin: `${OROCHIA.head.cx}, ${OROCHIA.head.cy}`, fill: "url(#body)" }),
2362
- /* @__PURE__ */ jsx22(Path7, { d: OROCHIA.tongue.d, stroke: OROCHIA.tongue.color, strokeWidth: 3, strokeLinecap: "round", fill: "none" })
3056
+ /* @__PURE__ */ jsx32(Animated13.View, { style: [layer, { transform: [{ rotate: spin.interpolate({ inputRange: [0, 1], outputRange: ["0deg", "360deg"] }) }] }], children: /* @__PURE__ */ jsx32(Svg12, { viewBox, style: layer, children: /* @__PURE__ */ jsx32(Circle7, { cx: CENTER, cy: CENTER, r: OROCHIA.orbit.r, stroke: neutral, strokeWidth: OROCHIA.orbit.width, strokeDasharray: OROCHIA.orbit.dash, opacity: 0.6, fill: "none" }) }) }),
3057
+ /* @__PURE__ */ jsxs28(Svg12, { viewBox, style: layer, children: [
3058
+ /* @__PURE__ */ jsx32(Defs6, { children: bodyGradient }),
3059
+ /* @__PURE__ */ jsxs28(Group2, { transform: `translate(${OROCHIA.offset} ${OROCHIA.offset})`, children: [
3060
+ /* @__PURE__ */ jsx32(Path9, { d: OROCHIA.arc, stroke: "url(#body)", strokeWidth: 22, strokeLinecap: "round", fill: "none" }),
3061
+ /* @__PURE__ */ jsx32(Path9, { d: OROCHIA.arc, stroke: OROCHIA.scales.color, strokeOpacity: OROCHIA.scales.opacity, strokeWidth: OROCHIA.scales.width, strokeLinecap: "round", strokeDasharray: OROCHIA.scales.dash, fill: "none" }),
3062
+ /* @__PURE__ */ jsx32(Path9, { d: OROCHIA.neck, stroke: "url(#body)", strokeWidth: 14, strokeLinecap: "round", fill: "none" }),
3063
+ /* @__PURE__ */ jsx32(Path9, { d: OROCHIA.tail, stroke: "url(#body)", strokeWidth: 6, strokeLinecap: "round", fill: "none" }),
3064
+ /* @__PURE__ */ jsx32(Ellipse2, { cx: OROCHIA.head.cx, cy: OROCHIA.head.cy, rx: OROCHIA.head.rx, ry: OROCHIA.head.ry, rotation: OROCHIA.head.rotate, origin: `${OROCHIA.head.cx}, ${OROCHIA.head.cy}`, fill: "url(#body)" }),
3065
+ /* @__PURE__ */ jsx32(Path9, { d: OROCHIA.tongue.d, stroke: OROCHIA.tongue.color, strokeWidth: 3, strokeLinecap: "round", fill: "none" })
2363
3066
  ] })
2364
3067
  ] }),
2365
- /* @__PURE__ */ jsx22(Animated9.View, { style: [layer, { opacity: pulse.interpolate({ inputRange: [0, 1], outputRange: [0.85, 1] }) }], children: /* @__PURE__ */ jsxs19(Svg8, { viewBox, style: layer, children: [
2366
- /* @__PURE__ */ jsx22(Defs5, { children: /* @__PURE__ */ jsx22(LinearGradient5, { id: "flame", x1: "50%", y1: "100%", x2: "50%", y2: "0%", children: OROCHIA.flameGradient.stops.map(([offset, color]) => /* @__PURE__ */ jsx22(Stop5, { offset, stopColor: color }, offset)) }) }),
2367
- /* @__PURE__ */ jsxs19(Group2, { transform: `translate(${OROCHIA.offset} ${OROCHIA.offset})`, children: [
2368
- /* @__PURE__ */ jsx22(Circle4, { cx: OROCHIA.eye.cx, cy: OROCHIA.eye.cy, r: OROCHIA.eye.r, fill: OROCHIA.eye.color }),
2369
- /* @__PURE__ */ jsx22(Path7, { d: OROCHIA.flame.d, transform: `translate(${OROCHIA.flame.translate[0]} ${OROCHIA.flame.translate[1]}) scale(${OROCHIA.flame.scale})`, fill: "url(#flame)" })
3068
+ /* @__PURE__ */ jsx32(Animated13.View, { style: [layer, { opacity: pulse.interpolate({ inputRange: [0, 1], outputRange: [0.85, 1] }) }], children: /* @__PURE__ */ jsxs28(Svg12, { viewBox, style: layer, children: [
3069
+ /* @__PURE__ */ jsx32(Defs6, { children: /* @__PURE__ */ jsx32(LinearGradient6, { id: "flame", x1: "50%", y1: "100%", x2: "50%", y2: "0%", children: OROCHIA.flameGradient.stops.map(([offset, color]) => /* @__PURE__ */ jsx32(Stop6, { offset, stopColor: color }, offset)) }) }),
3070
+ /* @__PURE__ */ jsxs28(Group2, { transform: `translate(${OROCHIA.offset} ${OROCHIA.offset})`, children: [
3071
+ /* @__PURE__ */ jsx32(Circle7, { cx: OROCHIA.eye.cx, cy: OROCHIA.eye.cy, r: OROCHIA.eye.r, fill: OROCHIA.eye.color }),
3072
+ /* @__PURE__ */ jsx32(Path9, { d: OROCHIA.flame.d, transform: `translate(${OROCHIA.flame.translate[0]} ${OROCHIA.flame.translate[1]}) scale(${OROCHIA.flame.scale})`, fill: "url(#flame)" })
2370
3073
  ] })
2371
3074
  ] }) })
2372
3075
  ] });
2373
3076
  }
2374
3077
 
3078
+ // src/native/otp-input.tsx
3079
+ import * as React25 from "react";
3080
+ import { Platform as Platform2, Pressable as Pressable13, StyleSheet as StyleSheet27, TextInput as TextInput4, View as View28 } from "react-native";
3081
+ import { jsx as jsx33, jsxs as jsxs29 } from "react/jsx-runtime";
3082
+ function OtpInput({ label, length = 6, value, onValueChange, onComplete, mode = "numeric", invalid, disabled, autoFocus, style }) {
3083
+ const { theme, radius: radius3, haptic } = useTheme();
3084
+ const [own, setOwn] = React25.useState("");
3085
+ const code = value ?? own;
3086
+ const [focused, setFocused] = React25.useState(false);
3087
+ const input = React25.useRef(null);
3088
+ React25.useEffect(() => {
3089
+ if (invalid) haptic("warning");
3090
+ }, [invalid, haptic]);
3091
+ const change = (raw) => {
3092
+ const next = (mode === "numeric" ? raw.replace(/\D/g, "") : raw.replace(/\s/g, "").toUpperCase()).slice(0, length);
3093
+ if (value === void 0) setOwn(next);
3094
+ onValueChange?.(next);
3095
+ if (next.length === length && code.length !== length) {
3096
+ haptic("success");
3097
+ onComplete?.(next);
3098
+ }
3099
+ };
3100
+ return /* @__PURE__ */ jsxs29(Pressable13, { onPress: () => input.current?.focus(), disabled, accessible: false, style: [styles27.root, style], children: [
3101
+ /* @__PURE__ */ jsx33(View28, { style: styles27.boxes, "aria-hidden": true, children: Array.from({ length }, (_, i) => {
3102
+ const active = focused && i === Math.min(code.length, length - 1);
3103
+ return /* @__PURE__ */ jsx33(
3104
+ View28,
3105
+ {
3106
+ style: [
3107
+ styles27.box,
3108
+ {
3109
+ borderRadius: radius3.md,
3110
+ backgroundColor: theme.surface2,
3111
+ borderColor: invalid ? theme.danger : active ? theme.ring : theme.borderDefault,
3112
+ borderWidth: invalid || active ? 2 : 1
3113
+ }
3114
+ ],
3115
+ children: /* @__PURE__ */ jsx33(Txt, { variant: "title", children: code[i] ?? "" })
3116
+ },
3117
+ i
3118
+ );
3119
+ }) }),
3120
+ /* @__PURE__ */ jsx33(
3121
+ TextInput4,
3122
+ {
3123
+ ref: input,
3124
+ "aria-label": label,
3125
+ "aria-invalid": invalid || void 0,
3126
+ value: code,
3127
+ onChangeText: change,
3128
+ maxLength: length,
3129
+ editable: !disabled,
3130
+ autoFocus,
3131
+ keyboardType: mode === "numeric" ? "number-pad" : "default",
3132
+ textContentType: "oneTimeCode",
3133
+ autoComplete: Platform2.OS === "android" && mode === "numeric" ? "sms-otp" : "one-time-code",
3134
+ autoCapitalize: "characters",
3135
+ autoCorrect: false,
3136
+ caretHidden: true,
3137
+ onFocus: () => setFocused(true),
3138
+ onBlur: () => setFocused(false),
3139
+ style: styles27.hidden
3140
+ }
3141
+ )
3142
+ ] });
3143
+ }
3144
+ var styles27 = StyleSheet27.create({
3145
+ root: { alignSelf: "flex-start" },
3146
+ boxes: { flexDirection: "row", gap: 8 },
3147
+ box: { width: 46, height: 56, alignItems: "center", justifyContent: "center" },
3148
+ hidden: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0, opacity: 0.011, color: "transparent" }
3149
+ });
3150
+
2375
3151
  // src/native/pagination.tsx
2376
- import { Pressable as Pressable9, StyleSheet as StyleSheet18, Text as Text13, View as View19 } from "react-native";
2377
- import Svg9, { Path as Path8 } from "react-native-svg";
2378
- import { jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
3152
+ import { Pressable as Pressable14, StyleSheet as StyleSheet28, Text as Text14, View as View29 } from "react-native";
3153
+ import Svg13, { Path as Path10 } from "react-native-svg";
3154
+ import { jsx as jsx34, jsxs as jsxs30 } from "react/jsx-runtime";
2379
3155
  function Chevron3({ direction, color }) {
2380
- return /* @__PURE__ */ jsx23(Svg9, { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx23(Path8, { d: direction === "left" ? "m15 6-6 6 6 6" : "m9 6 6 6-6 6" }) });
3156
+ return /* @__PURE__ */ jsx34(Svg13, { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx34(Path10, { d: direction === "left" ? "m15 6-6 6 6 6" : "m9 6 6 6-6 6" }) });
2381
3157
  }
2382
3158
  function Pagination({ page = 1, pageCount, onPageChange, hasPrevious, hasNext, onPrevious, onNext, status, disabled, labels, style }) {
2383
3159
  const { theme, radius: radius3 } = useTheme();
@@ -2386,8 +3162,8 @@ function Pagination({ page = 1, pageCount, onPageChange, hasPrevious, hasNext, o
2386
3162
  const current = Math.min(Math.max(1, page), count);
2387
3163
  const canPrevious = !disabled && (paged ? current > 1 : Boolean(hasPrevious));
2388
3164
  const canNext = !disabled && (paged ? current < count : Boolean(hasNext));
2389
- const button = (direction, enabled, onPress, label) => /* @__PURE__ */ jsx23(
2390
- Pressable9,
3165
+ const button = (direction, enabled, onPress, label) => /* @__PURE__ */ jsx34(
3166
+ Pressable14,
2391
3167
  {
2392
3168
  role: "button",
2393
3169
  "aria-label": label,
@@ -2396,29 +3172,66 @@ function Pagination({ page = 1, pageCount, onPageChange, hasPrevious, hasNext, o
2396
3172
  hitSlop: 6,
2397
3173
  onPress,
2398
3174
  style: ({ pressed }) => [
2399
- styles18.button,
3175
+ styles28.button,
2400
3176
  { borderRadius: radius3.sm, borderColor: theme.borderDefault, backgroundColor: theme.surface1, opacity: enabled ? pressed ? 0.8 : 1 : 0.4 }
2401
3177
  ],
2402
- children: /* @__PURE__ */ jsx23(Chevron3, { direction, color: theme.textPrimary })
3178
+ children: /* @__PURE__ */ jsx34(Chevron3, { direction, color: theme.textPrimary })
2403
3179
  }
2404
3180
  );
2405
3181
  const text = status ?? (paged ? labels.compact(current, count) : null);
2406
- return /* @__PURE__ */ jsxs20(View19, { role: "navigation", style: [styles18.row, style], children: [
3182
+ return /* @__PURE__ */ jsxs30(View29, { role: "navigation", style: [styles28.row, style], children: [
2407
3183
  button("left", canPrevious, paged ? () => onPageChange?.(current - 1) : onPrevious, labels.previous),
2408
- text ? /* @__PURE__ */ jsx23(Text13, { "aria-live": "polite", style: [styles18.status, { color: theme.textSecondary }], children: text }) : null,
3184
+ text ? /* @__PURE__ */ jsx34(Text14, { "aria-live": "polite", style: [styles28.status, { color: theme.textSecondary }], children: text }) : null,
2409
3185
  button("right", canNext, paged ? () => onPageChange?.(current + 1) : onNext, labels.next)
2410
3186
  ] });
2411
3187
  }
2412
- var styles18 = StyleSheet18.create({
3188
+ var styles28 = StyleSheet28.create({
2413
3189
  row: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", gap: 12 },
2414
- button: { width: 44, height: 44, alignItems: "center", justifyContent: "center", borderWidth: StyleSheet18.hairlineWidth },
3190
+ button: { width: 44, height: 44, alignItems: "center", justifyContent: "center", borderWidth: StyleSheet28.hairlineWidth },
2415
3191
  status: { fontSize: 13, fontWeight: "600", fontVariant: ["tabular-nums"] }
2416
3192
  });
2417
3193
 
3194
+ // src/native/permission-prompt.tsx
3195
+ import { StyleSheet as StyleSheet29, View as View30 } from "react-native";
3196
+ import { Fragment as Fragment5, jsx as jsx35, jsxs as jsxs31 } from "react/jsx-runtime";
3197
+ function PermissionPrompt({
3198
+ status,
3199
+ title,
3200
+ description,
3201
+ allowLabel,
3202
+ onAllow,
3203
+ settingsLabel,
3204
+ onOpenSettings,
3205
+ blockedDescription,
3206
+ dismissLabel,
3207
+ onDismiss,
3208
+ mascot = "falcon",
3209
+ children,
3210
+ style
3211
+ }) {
3212
+ const { theme, radius: radius3 } = useTheme();
3213
+ if (status === "granted") return /* @__PURE__ */ jsx35(Fragment5, { children: children ?? null });
3214
+ const blocked = status === "blocked" || status === "denied" && Boolean(onOpenSettings);
3215
+ return /* @__PURE__ */ jsxs31(View30, { style: [styles29.root, { backgroundColor: theme.surface1, borderColor: theme.borderSubtle, borderRadius: radius3.xl }, style], children: [
3216
+ /* @__PURE__ */ jsx35(Mascot, { bird: mascot, mood: blocked ? "error" : "welcome", size: 104 }),
3217
+ /* @__PURE__ */ jsx35(Txt, { variant: "title", style: styles29.centred, children: title }),
3218
+ /* @__PURE__ */ jsx35(Txt, { tone: "secondary", style: styles29.centred, children: blocked && blockedDescription ? blockedDescription : description }),
3219
+ /* @__PURE__ */ jsxs31(View30, { style: styles29.actions, children: [
3220
+ blocked && settingsLabel && onOpenSettings ? /* @__PURE__ */ jsx35(Button, { label: settingsLabel, variant: "primary", onPress: onOpenSettings }) : /* @__PURE__ */ jsx35(Button, { label: allowLabel, variant: "primary", onPress: onAllow }),
3221
+ dismissLabel && onDismiss ? /* @__PURE__ */ jsx35(Button, { label: dismissLabel, variant: "ghost", onPress: onDismiss }) : null
3222
+ ] })
3223
+ ] });
3224
+ }
3225
+ var styles29 = StyleSheet29.create({
3226
+ root: { alignItems: "center", gap: 10, padding: 24, borderWidth: StyleSheet29.hairlineWidth },
3227
+ centred: { textAlign: "center", maxWidth: 340 },
3228
+ actions: { marginTop: 8, gap: 8, alignSelf: "stretch" }
3229
+ });
3230
+
2418
3231
  // src/native/phoenix.tsx
2419
- import { useEffect as useEffect12, useState as useState18 } from "react";
2420
- import { AccessibilityInfo as AccessibilityInfo7, Animated as Animated10, Easing as Easing6, View as View20 } from "react-native";
2421
- import Svg10, { Circle as Circle5, Defs as Defs6, LinearGradient as LinearGradient6, Path as Path9, RadialGradient as RadialGradient4, Stop as Stop6 } from "react-native-svg";
3232
+ import { useEffect as useEffect17, useState as useState26 } from "react";
3233
+ import { AccessibilityInfo as AccessibilityInfo11, Animated as Animated14, Easing as Easing8, View as View31 } from "react-native";
3234
+ import Svg14, { Circle as Circle8, Defs as Defs7, LinearGradient as LinearGradient7, Path as Path11, RadialGradient as RadialGradient4, Stop as Stop7 } from "react-native-svg";
2422
3235
 
2423
3236
  // src/mascots/phoenix-geometry.ts
2424
3237
  var PHOENIX = {
@@ -2441,17 +3254,17 @@ var PHOENIX_PALETTES = {
2441
3254
  };
2442
3255
 
2443
3256
  // src/native/phoenix.tsx
2444
- import { jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
3257
+ import { jsx as jsx36, jsxs as jsxs32 } from "react/jsx-runtime";
2445
3258
  function useFloat(animated) {
2446
- const [y] = useState18(() => new Animated10.Value(0));
2447
- useEffect12(() => {
3259
+ const [y] = useState26(() => new Animated14.Value(0));
3260
+ useEffect17(() => {
2448
3261
  if (!animated) return;
2449
3262
  let loop;
2450
3263
  let cancelled = false;
2451
- void AccessibilityInfo7.isReduceMotionEnabled().then((reduce) => {
3264
+ void AccessibilityInfo11.isReduceMotionEnabled().then((reduce) => {
2452
3265
  if (reduce || cancelled) return;
2453
- const step = (toValue) => Animated10.timing(y, { toValue, duration: 2500, easing: Easing6.inOut(Easing6.ease), useNativeDriver: true });
2454
- loop = Animated10.loop(Animated10.sequence([step(-6), step(0)]));
3266
+ const step = (toValue) => Animated14.timing(y, { toValue, duration: 2500, easing: Easing8.inOut(Easing8.ease), useNativeDriver: true });
3267
+ loop = Animated14.loop(Animated14.sequence([step(-6), step(0)]));
2455
3268
  loop.start();
2456
3269
  });
2457
3270
  return () => {
@@ -2461,41 +3274,41 @@ function useFloat(animated) {
2461
3274
  }, [animated, y]);
2462
3275
  return y;
2463
3276
  }
2464
- function Phoenix({ tone: tone2 = "own", size = 120, animated = true, title, style }) {
3277
+ function Phoenix({ tone: tone3 = "own", size = 120, animated = true, title, style }) {
2465
3278
  const { theme } = useTheme();
2466
3279
  const id = useSvgId("kzp");
2467
3280
  const y = useFloat(animated);
2468
- const p = tone2 === "brand" ? { left: [theme.accent2, theme.accent], right: [theme.accent, theme.accent2], core: ["#ffffff", theme.accent], body: theme.surface3, edge: theme.borderStrong, crest: theme.accent } : PHOENIX_PALETTES.own;
2469
- return /* @__PURE__ */ jsx24(View20, { style: [{ width: size, height: size }, style], ...markA11y(title), children: /* @__PURE__ */ jsx24(Animated10.View, { style: { transform: [{ translateY: y }] }, children: /* @__PURE__ */ jsxs21(Svg10, { width: size, height: size, viewBox: "0 0 120 120", children: [
2470
- /* @__PURE__ */ jsxs21(Defs6, { children: [
2471
- /* @__PURE__ */ jsxs21(LinearGradient6, { id: `${id}l`, x1: "1", y1: "0", x2: "0", y2: "1", children: [
2472
- /* @__PURE__ */ jsx24(Stop6, { offset: "0%", stopColor: p.left[0] }),
2473
- /* @__PURE__ */ jsx24(Stop6, { offset: "100%", stopColor: p.left[1] })
3281
+ const p = tone3 === "brand" ? { left: [theme.accent2, theme.accent], right: [theme.accent, theme.accent2], core: ["#ffffff", theme.accent], body: theme.surface3, edge: theme.borderStrong, crest: theme.accent } : PHOENIX_PALETTES.own;
3282
+ return /* @__PURE__ */ jsx36(View31, { style: [{ width: size, height: size }, style], ...markA11y(title), children: /* @__PURE__ */ jsx36(Animated14.View, { style: { transform: [{ translateY: y }] }, children: /* @__PURE__ */ jsxs32(Svg14, { width: size, height: size, viewBox: "0 0 120 120", children: [
3283
+ /* @__PURE__ */ jsxs32(Defs7, { children: [
3284
+ /* @__PURE__ */ jsxs32(LinearGradient7, { id: `${id}l`, x1: "1", y1: "0", x2: "0", y2: "1", children: [
3285
+ /* @__PURE__ */ jsx36(Stop7, { offset: "0%", stopColor: p.left[0] }),
3286
+ /* @__PURE__ */ jsx36(Stop7, { offset: "100%", stopColor: p.left[1] })
2474
3287
  ] }),
2475
- /* @__PURE__ */ jsxs21(LinearGradient6, { id: `${id}r`, x1: "0", y1: "0", x2: "1", y2: "1", children: [
2476
- /* @__PURE__ */ jsx24(Stop6, { offset: "0%", stopColor: p.right[0] }),
2477
- /* @__PURE__ */ jsx24(Stop6, { offset: "100%", stopColor: p.right[1] })
3288
+ /* @__PURE__ */ jsxs32(LinearGradient7, { id: `${id}r`, x1: "0", y1: "0", x2: "1", y2: "1", children: [
3289
+ /* @__PURE__ */ jsx36(Stop7, { offset: "0%", stopColor: p.right[0] }),
3290
+ /* @__PURE__ */ jsx36(Stop7, { offset: "100%", stopColor: p.right[1] })
2478
3291
  ] }),
2479
- /* @__PURE__ */ jsxs21(RadialGradient4, { id: `${id}c`, children: [
2480
- /* @__PURE__ */ jsx24(Stop6, { offset: "0%", stopColor: p.core[0] }),
2481
- /* @__PURE__ */ jsx24(Stop6, { offset: "100%", stopColor: p.core[1], stopOpacity: 0 })
3292
+ /* @__PURE__ */ jsxs32(RadialGradient4, { id: `${id}c`, children: [
3293
+ /* @__PURE__ */ jsx36(Stop7, { offset: "0%", stopColor: p.core[0] }),
3294
+ /* @__PURE__ */ jsx36(Stop7, { offset: "100%", stopColor: p.core[1], stopOpacity: 0 })
2482
3295
  ] })
2483
3296
  ] }),
2484
- /* @__PURE__ */ jsx24(Path9, { d: PHOENIX.wingL, fill: `url(#${id}l)` }),
2485
- /* @__PURE__ */ jsx24(Path9, { d: PHOENIX.wingR, fill: `url(#${id}r)` }),
2486
- /* @__PURE__ */ jsx24(Path9, { d: PHOENIX.tailL, fill: `url(#${id}l)`, opacity: 0.7 }),
2487
- /* @__PURE__ */ jsx24(Path9, { d: PHOENIX.tailR, fill: `url(#${id}r)`, opacity: 0.7 }),
2488
- /* @__PURE__ */ jsx24(Path9, { d: PHOENIX.body, fill: p.body, stroke: p.edge, strokeOpacity: 0.5 }),
2489
- /* @__PURE__ */ jsx24(Circle5, { cx: 60, cy: 58, r: 12, fill: `url(#${id}c)` }),
2490
- /* @__PURE__ */ jsx24(Circle5, { cx: 60, cy: 58, r: 3.5, fill: "#ffffff" }),
2491
- /* @__PURE__ */ jsx24(Path9, { d: PHOENIX.crest, stroke: p.crest, strokeWidth: 2, strokeLinecap: "round" })
3297
+ /* @__PURE__ */ jsx36(Path11, { d: PHOENIX.wingL, fill: `url(#${id}l)` }),
3298
+ /* @__PURE__ */ jsx36(Path11, { d: PHOENIX.wingR, fill: `url(#${id}r)` }),
3299
+ /* @__PURE__ */ jsx36(Path11, { d: PHOENIX.tailL, fill: `url(#${id}l)`, opacity: 0.7 }),
3300
+ /* @__PURE__ */ jsx36(Path11, { d: PHOENIX.tailR, fill: `url(#${id}r)`, opacity: 0.7 }),
3301
+ /* @__PURE__ */ jsx36(Path11, { d: PHOENIX.body, fill: p.body, stroke: p.edge, strokeOpacity: 0.5 }),
3302
+ /* @__PURE__ */ jsx36(Circle8, { cx: 60, cy: 58, r: 12, fill: `url(#${id}c)` }),
3303
+ /* @__PURE__ */ jsx36(Circle8, { cx: 60, cy: 58, r: 3.5, fill: "#ffffff" }),
3304
+ /* @__PURE__ */ jsx36(Path11, { d: PHOENIX.crest, stroke: p.crest, strokeWidth: 2, strokeLinecap: "round" })
2492
3305
  ] }) }) });
2493
3306
  }
2494
3307
 
2495
3308
  // src/native/YazakiaMark.tsx
2496
- import React19 from "react";
2497
- import { View as View21 } from "react-native";
2498
- import Svg11, { Circle as Circle6, Defs as Defs7, LinearGradient as LinearGradient7, Path as Path10, RadialGradient as RadialGradient5, Stop as Stop7 } from "react-native-svg";
3309
+ import React27 from "react";
3310
+ import { View as View32 } from "react-native";
3311
+ import Svg15, { Circle as Circle9, Defs as Defs8, LinearGradient as LinearGradient8, Path as Path12, RadialGradient as RadialGradient5, Stop as Stop8 } from "react-native-svg";
2499
3312
 
2500
3313
  // src/marks/yazakia-geometry.ts
2501
3314
  var turquoise = marks.yazakia[marks.yazakia.length - 1][1];
@@ -2525,54 +3338,54 @@ var YAZAKIA = {
2525
3338
  };
2526
3339
 
2527
3340
  // src/native/YazakiaMark.tsx
2528
- import { jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
3341
+ import { jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
2529
3342
  function YazakiaMark({ size = 48, animated = true, title, neutral }) {
2530
3343
  const { theme } = useTheme();
2531
- const { Animated: Animated17, layer, spinStyle, pulseStyle } = useMarkMotion(size, animated);
3344
+ const { Animated: Animated22, layer, spinStyle, pulseStyle } = useMarkMotion(size, animated);
2532
3345
  const id = useSvgId("yzm");
2533
3346
  const viewBox = size < 48 ? YAZAKIA.croppedViewBox : YAZAKIA.viewBox;
2534
3347
  const stroke = neutral ?? theme.textMuted;
2535
- const gradient = /* @__PURE__ */ jsx25(LinearGradient7, { id: `${id}a`, gradientUnits: "userSpaceOnUse", x1: YAZAKIA.gradient.x1, y1: YAZAKIA.gradient.y1, x2: YAZAKIA.gradient.x2, y2: YAZAKIA.gradient.y2, children: YAZAKIA.gradient.stops.map(([offset, color]) => /* @__PURE__ */ jsx25(Stop7, { offset, stopColor: color }, offset)) });
3348
+ const gradient = /* @__PURE__ */ jsx37(LinearGradient8, { id: `${id}a`, gradientUnits: "userSpaceOnUse", x1: YAZAKIA.gradient.x1, y1: YAZAKIA.gradient.y1, x2: YAZAKIA.gradient.x2, y2: YAZAKIA.gradient.y2, children: YAZAKIA.gradient.stops.map(([offset, color]) => /* @__PURE__ */ jsx37(Stop8, { offset, stopColor: color }, offset)) });
2536
3349
  const fill = `url(#${id}a)`;
2537
- return /* @__PURE__ */ jsxs22(View21, { style: { width: size, height: size }, ...markA11y(title), children: [
2538
- /* @__PURE__ */ jsxs22(Svg11, { viewBox, style: layer, children: [
2539
- /* @__PURE__ */ jsxs22(Defs7, { children: [
2540
- /* @__PURE__ */ jsxs22(RadialGradient5, { id: `${id}g`, cx: "50%", cy: "50%", r: "50%", children: [
2541
- /* @__PURE__ */ jsx25(Stop7, { offset: "0%", stopColor: YAZAKIA.glow.color, stopOpacity: YAZAKIA.glow.opacity }),
2542
- /* @__PURE__ */ jsx25(Stop7, { offset: "100%", stopColor: YAZAKIA.glow.color, stopOpacity: 0 })
3350
+ return /* @__PURE__ */ jsxs33(View32, { style: { width: size, height: size }, ...markA11y(title), children: [
3351
+ /* @__PURE__ */ jsxs33(Svg15, { viewBox, style: layer, children: [
3352
+ /* @__PURE__ */ jsxs33(Defs8, { children: [
3353
+ /* @__PURE__ */ jsxs33(RadialGradient5, { id: `${id}g`, cx: "50%", cy: "50%", r: "50%", children: [
3354
+ /* @__PURE__ */ jsx37(Stop8, { offset: "0%", stopColor: YAZAKIA.glow.color, stopOpacity: YAZAKIA.glow.opacity }),
3355
+ /* @__PURE__ */ jsx37(Stop8, { offset: "100%", stopColor: YAZAKIA.glow.color, stopOpacity: 0 })
2543
3356
  ] }),
2544
3357
  gradient
2545
3358
  ] }),
2546
- size >= 48 ? /* @__PURE__ */ jsx25(Circle6, { cx: YAZAKIA.center, cy: YAZAKIA.center, r: 190, fill: `url(#${id}g)` }) : null,
2547
- /* @__PURE__ */ jsx25(Circle6, { cx: YAZAKIA.center, cy: YAZAKIA.center, r: YAZAKIA.ring.r, stroke, strokeWidth: YAZAKIA.ring.width, opacity: 0.35, fill: "none" }),
2548
- YAZAKIA.voices.map((v, i) => /* @__PURE__ */ jsxs22(React19.Fragment, { children: [
2549
- /* @__PURE__ */ jsx25(Path10, { d: v.body, fill }),
2550
- /* @__PURE__ */ jsx25(Path10, { d: v.tail, fill }),
2551
- i === 0 ? /* @__PURE__ */ jsx25(Path10, { d: `${v.body} ${v.tail}`, fill: YAZAKIA.shade.color, opacity: YAZAKIA.shade.opacity }) : null
3359
+ size >= 48 ? /* @__PURE__ */ jsx37(Circle9, { cx: YAZAKIA.center, cy: YAZAKIA.center, r: 190, fill: `url(#${id}g)` }) : null,
3360
+ /* @__PURE__ */ jsx37(Circle9, { cx: YAZAKIA.center, cy: YAZAKIA.center, r: YAZAKIA.ring.r, stroke, strokeWidth: YAZAKIA.ring.width, opacity: 0.35, fill: "none" }),
3361
+ YAZAKIA.voices.map((v, i) => /* @__PURE__ */ jsxs33(React27.Fragment, { children: [
3362
+ /* @__PURE__ */ jsx37(Path12, { d: v.body, fill }),
3363
+ /* @__PURE__ */ jsx37(Path12, { d: v.tail, fill }),
3364
+ i === 0 ? /* @__PURE__ */ jsx37(Path12, { d: `${v.body} ${v.tail}`, fill: YAZAKIA.shade.color, opacity: YAZAKIA.shade.opacity }) : null
2552
3365
  ] }, v.body))
2553
3366
  ] }),
2554
- /* @__PURE__ */ jsx25(Animated17.View, { style: [layer, spinStyle], children: /* @__PURE__ */ jsxs22(Svg11, { viewBox, style: layer, children: [
2555
- /* @__PURE__ */ jsx25(Defs7, { children: gradient }),
2556
- /* @__PURE__ */ jsx25(Circle6, { cx: YAZAKIA.center, cy: YAZAKIA.center, r: YAZAKIA.orbit.r, stroke, strokeWidth: YAZAKIA.orbit.width, strokeDasharray: YAZAKIA.orbit.dash, opacity: 0.6, fill: "none" }),
2557
- YAZAKIA.pair.at.map(([cx, cy]) => /* @__PURE__ */ jsx25(Circle6, { cx, cy, r: YAZAKIA.pair.r, fill }, cx))
3367
+ /* @__PURE__ */ jsx37(Animated22.View, { style: [layer, spinStyle], children: /* @__PURE__ */ jsxs33(Svg15, { viewBox, style: layer, children: [
3368
+ /* @__PURE__ */ jsx37(Defs8, { children: gradient }),
3369
+ /* @__PURE__ */ jsx37(Circle9, { cx: YAZAKIA.center, cy: YAZAKIA.center, r: YAZAKIA.orbit.r, stroke, strokeWidth: YAZAKIA.orbit.width, strokeDasharray: YAZAKIA.orbit.dash, opacity: 0.6, fill: "none" }),
3370
+ YAZAKIA.pair.at.map(([cx, cy]) => /* @__PURE__ */ jsx37(Circle9, { cx, cy, r: YAZAKIA.pair.r, fill }, cx))
2558
3371
  ] }) }),
2559
- /* @__PURE__ */ jsx25(Animated17.View, { style: [layer, pulseStyle], children: /* @__PURE__ */ jsxs22(Svg11, { viewBox, style: layer, children: [
2560
- /* @__PURE__ */ jsxs22(Defs7, { children: [
3372
+ /* @__PURE__ */ jsx37(Animated22.View, { style: [layer, pulseStyle], children: /* @__PURE__ */ jsxs33(Svg15, { viewBox, style: layer, children: [
3373
+ /* @__PURE__ */ jsxs33(Defs8, { children: [
2561
3374
  gradient,
2562
- /* @__PURE__ */ jsxs22(LinearGradient7, { id: `${id}l`, gradientUnits: "userSpaceOnUse", x1: 0, y1: YAZAKIA.lens.y1, x2: 0, y2: YAZAKIA.lens.y2, children: [
2563
- /* @__PURE__ */ jsx25(Stop7, { offset: "0%", stopColor: YAZAKIA.highlight.color, stopOpacity: YAZAKIA.highlight.from }),
2564
- /* @__PURE__ */ jsx25(Stop7, { offset: "100%", stopColor: YAZAKIA.highlight.color, stopOpacity: YAZAKIA.highlight.to })
3375
+ /* @__PURE__ */ jsxs33(LinearGradient8, { id: `${id}l`, gradientUnits: "userSpaceOnUse", x1: 0, y1: YAZAKIA.lens.y1, x2: 0, y2: YAZAKIA.lens.y2, children: [
3376
+ /* @__PURE__ */ jsx37(Stop8, { offset: "0%", stopColor: YAZAKIA.highlight.color, stopOpacity: YAZAKIA.highlight.from }),
3377
+ /* @__PURE__ */ jsx37(Stop8, { offset: "100%", stopColor: YAZAKIA.highlight.color, stopOpacity: YAZAKIA.highlight.to })
2565
3378
  ] })
2566
3379
  ] }),
2567
- /* @__PURE__ */ jsx25(Path10, { d: YAZAKIA.lens.d, fill }),
2568
- /* @__PURE__ */ jsx25(Path10, { d: YAZAKIA.lens.d, fill: `url(#${id}l)` })
3380
+ /* @__PURE__ */ jsx37(Path12, { d: YAZAKIA.lens.d, fill }),
3381
+ /* @__PURE__ */ jsx37(Path12, { d: YAZAKIA.lens.d, fill: `url(#${id}l)` })
2569
3382
  ] }) })
2570
3383
  ] });
2571
3384
  }
2572
3385
 
2573
3386
  // src/native/YororisMark.tsx
2574
- import { View as View22 } from "react-native";
2575
- import Svg12, { Circle as Circle7, Defs as Defs8, LinearGradient as LinearGradient8, Path as Path11, RadialGradient as RadialGradient6, Stop as Stop8 } from "react-native-svg";
3387
+ import { View as View33 } from "react-native";
3388
+ import Svg16, { Circle as Circle10, Defs as Defs9, LinearGradient as LinearGradient9, Path as Path13, RadialGradient as RadialGradient6, Stop as Stop9 } from "react-native-svg";
2576
3389
 
2577
3390
  // src/marks/yororis-geometry.ts
2578
3391
  var sand = marks.yororis[0][1];
@@ -2608,65 +3421,65 @@ var YORORIS = {
2608
3421
  };
2609
3422
 
2610
3423
  // src/native/YororisMark.tsx
2611
- import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
3424
+ import { jsx as jsx38, jsxs as jsxs34 } from "react/jsx-runtime";
2612
3425
  function YororisMark({ size = 48, animated = true, title, neutral }) {
2613
3426
  const { theme } = useTheme();
2614
- const { Animated: Animated17, layer, spinStyle, pulseStyle } = useMarkMotion(size, animated, 36e3);
3427
+ const { Animated: Animated22, layer, spinStyle, pulseStyle } = useMarkMotion(size, animated, 36e3);
2615
3428
  const id = useSvgId("yrm");
2616
3429
  const viewBox = size < 48 ? YORORIS.croppedViewBox : YORORIS.viewBox;
2617
3430
  const stroke = neutral ?? theme.textMuted;
2618
- const gradient = /* @__PURE__ */ jsx26(LinearGradient8, { id: `${id}a`, gradientUnits: "userSpaceOnUse", x1: YORORIS.gradient.x1, y1: YORORIS.gradient.y1, x2: YORORIS.gradient.x2, y2: YORORIS.gradient.y2, children: YORORIS.gradient.stops.map(([offset, color]) => /* @__PURE__ */ jsx26(Stop8, { offset, stopColor: color }, offset)) });
3431
+ const gradient = /* @__PURE__ */ jsx38(LinearGradient9, { id: `${id}a`, gradientUnits: "userSpaceOnUse", x1: YORORIS.gradient.x1, y1: YORORIS.gradient.y1, x2: YORORIS.gradient.x2, y2: YORORIS.gradient.y2, children: YORORIS.gradient.stops.map(([offset, color]) => /* @__PURE__ */ jsx38(Stop9, { offset, stopColor: color }, offset)) });
2619
3432
  const fill = `url(#${id}a)`;
2620
- return /* @__PURE__ */ jsxs23(View22, { style: { width: size, height: size }, ...markA11y(title), children: [
2621
- /* @__PURE__ */ jsxs23(Svg12, { viewBox, style: layer, children: [
2622
- /* @__PURE__ */ jsxs23(Defs8, { children: [
2623
- /* @__PURE__ */ jsxs23(RadialGradient6, { id: `${id}g`, cx: "50%", cy: "50%", r: "50%", children: [
2624
- /* @__PURE__ */ jsx26(Stop8, { offset: "0%", stopColor: YORORIS.glow.color, stopOpacity: YORORIS.glow.opacity }),
2625
- /* @__PURE__ */ jsx26(Stop8, { offset: "100%", stopColor: YORORIS.glow.color, stopOpacity: 0 })
3433
+ return /* @__PURE__ */ jsxs34(View33, { style: { width: size, height: size }, ...markA11y(title), children: [
3434
+ /* @__PURE__ */ jsxs34(Svg16, { viewBox, style: layer, children: [
3435
+ /* @__PURE__ */ jsxs34(Defs9, { children: [
3436
+ /* @__PURE__ */ jsxs34(RadialGradient6, { id: `${id}g`, cx: "50%", cy: "50%", r: "50%", children: [
3437
+ /* @__PURE__ */ jsx38(Stop9, { offset: "0%", stopColor: YORORIS.glow.color, stopOpacity: YORORIS.glow.opacity }),
3438
+ /* @__PURE__ */ jsx38(Stop9, { offset: "100%", stopColor: YORORIS.glow.color, stopOpacity: 0 })
2626
3439
  ] }),
2627
3440
  gradient
2628
3441
  ] }),
2629
- size >= 48 ? /* @__PURE__ */ jsx26(Circle7, { cx: YORORIS.center, cy: YORORIS.center, r: 190, fill: `url(#${id}g)` }) : null,
2630
- /* @__PURE__ */ jsx26(Circle7, { cx: YORORIS.center, cy: YORORIS.center, r: YORORIS.ring.r, stroke, strokeWidth: YORORIS.ring.width, opacity: 0.35, fill: "none" }),
2631
- /* @__PURE__ */ jsx26(Path11, { d: YORORIS.stem, stroke: fill, strokeWidth: YORORIS.stroke, strokeLinecap: "round", fill: "none" }),
2632
- YORORIS.leaves.map((d) => /* @__PURE__ */ jsx26(Path11, { d, fill }, d)),
2633
- /* @__PURE__ */ jsx26(Path11, { d: YORORIS.veins, stroke: YORORIS.vein.color, strokeOpacity: YORORIS.vein.opacity, strokeWidth: YORORIS.vein.width, strokeLinecap: "round", strokeDasharray: YORORIS.vein.dash, fill: "none" })
3442
+ size >= 48 ? /* @__PURE__ */ jsx38(Circle10, { cx: YORORIS.center, cy: YORORIS.center, r: 190, fill: `url(#${id}g)` }) : null,
3443
+ /* @__PURE__ */ jsx38(Circle10, { cx: YORORIS.center, cy: YORORIS.center, r: YORORIS.ring.r, stroke, strokeWidth: YORORIS.ring.width, opacity: 0.35, fill: "none" }),
3444
+ /* @__PURE__ */ jsx38(Path13, { d: YORORIS.stem, stroke: fill, strokeWidth: YORORIS.stroke, strokeLinecap: "round", fill: "none" }),
3445
+ YORORIS.leaves.map((d) => /* @__PURE__ */ jsx38(Path13, { d, fill }, d)),
3446
+ /* @__PURE__ */ jsx38(Path13, { d: YORORIS.veins, stroke: YORORIS.vein.color, strokeOpacity: YORORIS.vein.opacity, strokeWidth: YORORIS.vein.width, strokeLinecap: "round", strokeDasharray: YORORIS.vein.dash, fill: "none" })
2634
3447
  ] }),
2635
- /* @__PURE__ */ jsx26(Animated17.View, { style: [layer, spinStyle], children: /* @__PURE__ */ jsxs23(Svg12, { viewBox, style: layer, children: [
2636
- /* @__PURE__ */ jsx26(Defs8, { children: gradient }),
2637
- /* @__PURE__ */ jsx26(Circle7, { cx: YORORIS.center, cy: YORORIS.center, r: YORORIS.orbit.r, stroke, strokeWidth: YORORIS.orbit.width, strokeDasharray: YORORIS.orbit.dash, opacity: 0.6, fill: "none" }),
2638
- /* @__PURE__ */ jsx26(Circle7, { cx: YORORIS.moment.at[0], cy: YORORIS.moment.at[1], r: YORORIS.moment.r, fill })
3448
+ /* @__PURE__ */ jsx38(Animated22.View, { style: [layer, spinStyle], children: /* @__PURE__ */ jsxs34(Svg16, { viewBox, style: layer, children: [
3449
+ /* @__PURE__ */ jsx38(Defs9, { children: gradient }),
3450
+ /* @__PURE__ */ jsx38(Circle10, { cx: YORORIS.center, cy: YORORIS.center, r: YORORIS.orbit.r, stroke, strokeWidth: YORORIS.orbit.width, strokeDasharray: YORORIS.orbit.dash, opacity: 0.6, fill: "none" }),
3451
+ /* @__PURE__ */ jsx38(Circle10, { cx: YORORIS.moment.at[0], cy: YORORIS.moment.at[1], r: YORORIS.moment.r, fill })
2639
3452
  ] }) }),
2640
- /* @__PURE__ */ jsx26(Animated17.View, { style: [layer, pulseStyle], children: /* @__PURE__ */ jsxs23(Svg12, { viewBox, style: layer, children: [
2641
- /* @__PURE__ */ jsx26(Defs8, { children: /* @__PURE__ */ jsx26(LinearGradient8, { id: `${id}c`, x1: "50%", y1: "100%", x2: "50%", y2: "0%", children: YORORIS.coreGradient.stops.map(([offset, color]) => /* @__PURE__ */ jsx26(Stop8, { offset, stopColor: color }, offset)) }) }),
2642
- /* @__PURE__ */ jsx26(Circle7, { cx: YORORIS.core.cx, cy: YORORIS.core.cy, r: YORORIS.core.r, fill: `url(#${id}c)` }),
2643
- /* @__PURE__ */ jsx26(Circle7, { cx: YORORIS.core.cx, cy: YORORIS.core.cy, r: YORORIS.core.inner, fill: YORORIS.highlight })
3453
+ /* @__PURE__ */ jsx38(Animated22.View, { style: [layer, pulseStyle], children: /* @__PURE__ */ jsxs34(Svg16, { viewBox, style: layer, children: [
3454
+ /* @__PURE__ */ jsx38(Defs9, { children: /* @__PURE__ */ jsx38(LinearGradient9, { id: `${id}c`, x1: "50%", y1: "100%", x2: "50%", y2: "0%", children: YORORIS.coreGradient.stops.map(([offset, color]) => /* @__PURE__ */ jsx38(Stop9, { offset, stopColor: color }, offset)) }) }),
3455
+ /* @__PURE__ */ jsx38(Circle10, { cx: YORORIS.core.cx, cy: YORORIS.core.cy, r: YORORIS.core.r, fill: `url(#${id}c)` }),
3456
+ /* @__PURE__ */ jsx38(Circle10, { cx: YORORIS.core.cx, cy: YORORIS.core.cy, r: YORORIS.core.inner, fill: YORORIS.highlight })
2644
3457
  ] }) })
2645
3458
  ] });
2646
3459
  }
2647
3460
 
2648
3461
  // src/native/ProductMark.tsx
2649
- import { jsx as jsx27 } from "react/jsx-runtime";
3462
+ import { jsx as jsx39 } from "react/jsx-runtime";
2650
3463
  function ProductMark({ id, ...props }) {
2651
- if (id === "krizaka") return /* @__PURE__ */ jsx27(KrizakaMark, { ...props });
2652
- if (id === "orazaka") return /* @__PURE__ */ jsx27(OrazakaMark, { ...props });
2653
- if (id === "yazakia") return /* @__PURE__ */ jsx27(YazakiaMark, { ...props });
2654
- if (id === "yororis") return /* @__PURE__ */ jsx27(YororisMark, { ...props });
2655
- return /* @__PURE__ */ jsx27(OrochiaMark, { ...props });
3464
+ if (id === "krizaka") return /* @__PURE__ */ jsx39(KrizakaMark, { ...props });
3465
+ if (id === "orazaka") return /* @__PURE__ */ jsx39(OrazakaMark, { ...props });
3466
+ if (id === "yazakia") return /* @__PURE__ */ jsx39(YazakiaMark, { ...props });
3467
+ if (id === "yororis") return /* @__PURE__ */ jsx39(YororisMark, { ...props });
3468
+ return /* @__PURE__ */ jsx39(OrochiaMark, { ...props });
2656
3469
  }
2657
3470
 
2658
3471
  // src/native/profile-card.tsx
2659
- import * as React20 from "react";
2660
- import { Animated as Animated11, StyleSheet as StyleSheet19, View as View23 } from "react-native";
2661
- import { jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
3472
+ import * as React28 from "react";
3473
+ import { Animated as Animated15, StyleSheet as StyleSheet30, View as View34 } from "react-native";
3474
+ import { jsx as jsx40, jsxs as jsxs35 } from "react/jsx-runtime";
2662
3475
  var ratioOf = (value, max = 100) => Math.min(1, Math.max(0, value / (max || 1)));
2663
3476
  function Bar({ label, ratio, words, animated, delay }) {
2664
3477
  const { theme } = useTheme();
2665
3478
  const t = useEntrance(animated, delay, 900);
2666
- const [width, setWidth] = React20.useState(0);
3479
+ const [width, setWidth] = React28.useState(0);
2667
3480
  const translateX = t.interpolate({ inputRange: [0, 1], outputRange: [-width * ratio, 0] });
2668
- return /* @__PURE__ */ jsx28(
2669
- View23,
3481
+ return /* @__PURE__ */ jsx40(
3482
+ View34,
2670
3483
  {
2671
3484
  accessible: true,
2672
3485
  role: "meter",
@@ -2676,42 +3489,42 @@ function Bar({ label, ratio, words, animated, delay }) {
2676
3489
  "aria-valuenow": Math.round(ratio * 100),
2677
3490
  "aria-valuetext": words,
2678
3491
  onLayout: (e) => setWidth(e.nativeEvent.layout.width),
2679
- style: [styles19.track, { backgroundColor: theme.surface3 }],
2680
- children: /* @__PURE__ */ jsx28(Animated11.View, { style: [styles19.fill, { width: `${ratio * 100}%`, backgroundColor: theme.accent, transform: [{ translateX }] }] })
3492
+ style: [styles30.track, { backgroundColor: theme.surface3 }],
3493
+ children: /* @__PURE__ */ jsx40(Animated15.View, { style: [styles30.fill, { width: `${ratio * 100}%`, backgroundColor: theme.accent, transform: [{ translateX }] }] })
2681
3494
  }
2682
3495
  );
2683
3496
  }
2684
3497
  function ProfileCard({ visual, name, statLabel, value = 100, valueText, stats, caption, children, animated = true, style, ...props }) {
2685
3498
  const { theme, radius: radius3 } = useTheme();
2686
3499
  const ratio = ratioOf(value);
2687
- return /* @__PURE__ */ jsxs24(View23, { ...props, style: [styles19.root, { backgroundColor: theme.surface1, borderColor: theme.borderSubtle, borderRadius: radius3.xl }, style], children: [
2688
- /* @__PURE__ */ jsx28(View23, { "aria-hidden": true, style: [styles19.disc, { backgroundColor: theme.surface2, borderColor: theme.accentSoft }], children: visual }),
2689
- /* @__PURE__ */ jsxs24(View23, { style: styles19.head, children: [
2690
- /* @__PURE__ */ jsx28(Txt, { variant: "title", style: styles19.name, children: name }),
2691
- statLabel ? /* @__PURE__ */ jsxs24(Txt, { variant: "caption", tone: "secondary", children: [
3500
+ return /* @__PURE__ */ jsxs35(View34, { ...props, style: [styles30.root, { backgroundColor: theme.surface1, borderColor: theme.borderSubtle, borderRadius: radius3.xl }, style], children: [
3501
+ /* @__PURE__ */ jsx40(View34, { "aria-hidden": true, style: [styles30.disc, { backgroundColor: theme.surface2, borderColor: theme.accentSoft }], children: visual }),
3502
+ /* @__PURE__ */ jsxs35(View34, { style: styles30.head, children: [
3503
+ /* @__PURE__ */ jsx40(Txt, { variant: "title", style: styles30.name, children: name }),
3504
+ statLabel ? /* @__PURE__ */ jsxs35(Txt, { variant: "caption", tone: "secondary", children: [
2692
3505
  statLabel,
2693
3506
  " ",
2694
- /* @__PURE__ */ jsx28(Txt, { variant: "caption", children: valueText ?? `${Math.round(ratio * 100)} %` })
3507
+ /* @__PURE__ */ jsx40(Txt, { variant: "caption", children: valueText ?? `${Math.round(ratio * 100)} %` })
2695
3508
  ] }) : null
2696
3509
  ] }),
2697
- statLabel ? /* @__PURE__ */ jsx28(Bar, { label: statLabel, ratio, words: valueText ?? `${Math.round(ratio * 100)} %`, animated, delay: 200 }) : null,
3510
+ statLabel ? /* @__PURE__ */ jsx40(Bar, { label: statLabel, ratio, words: valueText ?? `${Math.round(ratio * 100)} %`, animated, delay: 200 }) : null,
2698
3511
  stats?.map((s, i) => {
2699
3512
  const r = ratioOf(s.value, s.max);
2700
3513
  const words = s.valueText ?? `${Math.round(r * 100)} %`;
2701
- return /* @__PURE__ */ jsxs24(View23, { style: styles19.stat, children: [
2702
- /* @__PURE__ */ jsxs24(View23, { "aria-hidden": true, style: styles19.statHead, children: [
2703
- /* @__PURE__ */ jsx28(Txt, { variant: "caption", tone: "secondary", children: s.label }),
2704
- /* @__PURE__ */ jsx28(Txt, { variant: "caption", children: words })
3514
+ return /* @__PURE__ */ jsxs35(View34, { style: styles30.stat, children: [
3515
+ /* @__PURE__ */ jsxs35(View34, { "aria-hidden": true, style: styles30.statHead, children: [
3516
+ /* @__PURE__ */ jsx40(Txt, { variant: "caption", tone: "secondary", children: s.label }),
3517
+ /* @__PURE__ */ jsx40(Txt, { variant: "caption", children: words })
2705
3518
  ] }),
2706
- /* @__PURE__ */ jsx28(Bar, { label: s.label, ratio: r, words, animated, delay: 320 + i * 120 })
3519
+ /* @__PURE__ */ jsx40(Bar, { label: s.label, ratio: r, words, animated, delay: 320 + i * 120 })
2707
3520
  ] }, s.label);
2708
3521
  }),
2709
- caption ? /* @__PURE__ */ jsx28(Txt, { variant: "caption", tone: "secondary", style: styles19.caption, children: caption }) : null,
2710
- children ? /* @__PURE__ */ jsx28(View23, { style: styles19.extra, children }) : null
3522
+ caption ? /* @__PURE__ */ jsx40(Txt, { variant: "caption", tone: "secondary", style: styles30.caption, children: caption }) : null,
3523
+ children ? /* @__PURE__ */ jsx40(View34, { style: styles30.extra, children }) : null
2711
3524
  ] });
2712
3525
  }
2713
- var styles19 = StyleSheet19.create({
2714
- root: { alignItems: "center", gap: 12, padding: 20, borderWidth: StyleSheet19.hairlineWidth },
3526
+ var styles30 = StyleSheet30.create({
3527
+ root: { alignItems: "center", gap: 12, padding: 20, borderWidth: StyleSheet30.hairlineWidth },
2715
3528
  disc: { width: 104, height: 104, borderRadius: 52, borderWidth: 1, alignItems: "center", justifyContent: "center", overflow: "hidden" },
2716
3529
  head: { flexDirection: "row", alignSelf: "stretch", alignItems: "center", justifyContent: "space-between", gap: 8 },
2717
3530
  name: { flexShrink: 1, fontSize: 17 },
@@ -2724,13 +3537,13 @@ var styles19 = StyleSheet19.create({
2724
3537
  });
2725
3538
 
2726
3539
  // src/native/progress.tsx
2727
- import * as React21 from "react";
2728
- import { Animated as Animated12, Easing as Easing7, StyleSheet as StyleSheet20, View as View24 } from "react-native";
2729
- import Svg13, { Circle as Circle8, Defs as Defs9, LinearGradient as LinearGradient9, Rect as Rect3, Stop as Stop9 } from "react-native-svg";
2730
- import { jsx as jsx29, jsxs as jsxs25 } from "react/jsx-runtime";
2731
- var AnimatedCircle = Animated12.createAnimatedComponent(Circle8);
2732
- var BAR = { sm: 4, md: 8, lg: 12 };
2733
- var RING = { sm: 40, md: 80, lg: 144 };
3540
+ import * as React29 from "react";
3541
+ import { Animated as Animated16, Easing as Easing9, StyleSheet as StyleSheet31, View as View35 } from "react-native";
3542
+ import Svg17, { Circle as Circle11, Defs as Defs10, LinearGradient as LinearGradient10, Rect as Rect3, Stop as Stop10 } from "react-native-svg";
3543
+ import { jsx as jsx41, jsxs as jsxs36 } from "react/jsx-runtime";
3544
+ var AnimatedCircle = Animated16.createAnimatedComponent(Circle11);
3545
+ var BAR2 = { sm: 4, md: 8, lg: 12 };
3546
+ var RING2 = { sm: 40, md: 80, lg: 144 };
2734
3547
  var STROKE = { sm: 12, md: 9, lg: 7 };
2735
3548
  function Progress({ variant = "bar", size = "md", value, max = 100, label, valueText, children, style }) {
2736
3549
  const { theme } = useTheme();
@@ -2739,21 +3552,21 @@ function Progress({ variant = "bar", size = "md", value, max = 100, label, value
2739
3552
  const known = typeof value === "number" && Number.isFinite(value);
2740
3553
  const ratio = known ? Math.min(1, Math.max(0, value / (max || 1))) : 0;
2741
3554
  const percent = Math.round(ratio * 100);
2742
- const [progress] = React21.useState(() => new Animated12.Value(ratio));
2743
- const [spin] = React21.useState(() => new Animated12.Value(0));
2744
- const [track, setTrack] = React21.useState(0);
2745
- React21.useEffect(() => {
3555
+ const [progress] = React29.useState(() => new Animated16.Value(ratio));
3556
+ const [spin] = React29.useState(() => new Animated16.Value(0));
3557
+ const [track, setTrack] = React29.useState(0);
3558
+ React29.useEffect(() => {
2746
3559
  if (reduce) {
2747
3560
  progress.setValue(ratio);
2748
3561
  return;
2749
3562
  }
2750
- const animation = Animated12.timing(progress, { toValue: ratio, duration: 700, easing: Easing7.out(Easing7.cubic), useNativeDriver: false });
3563
+ const animation = Animated16.timing(progress, { toValue: ratio, duration: 700, easing: Easing9.out(Easing9.cubic), useNativeDriver: false });
2751
3564
  animation.start();
2752
3565
  return () => animation.stop();
2753
3566
  }, [ratio, reduce, progress]);
2754
- React21.useEffect(() => {
3567
+ React29.useEffect(() => {
2755
3568
  if (known || reduce) return;
2756
- const loop = Animated12.loop(Animated12.timing(spin, { toValue: 1, duration: 1200, easing: Easing7.linear, useNativeDriver: true }));
3569
+ const loop = Animated16.loop(Animated16.timing(spin, { toValue: 1, duration: 1200, easing: Easing9.linear, useNativeDriver: true }));
2757
3570
  loop.start();
2758
3571
  return () => {
2759
3572
  loop.stop();
@@ -2769,22 +3582,22 @@ function Progress({ variant = "bar", size = "md", value, max = 100, label, value
2769
3582
  "aria-valuenow": known ? Math.min(max, Math.max(0, value)) : void 0,
2770
3583
  "aria-valuetext": known ? valueText ?? `${percent}%` : valueText
2771
3584
  };
2772
- const gradient = /* @__PURE__ */ jsx29(Defs9, { children: /* @__PURE__ */ jsxs25(LinearGradient9, { id, x1: "0", y1: "0", x2: "1", y2: variant === "ring" ? "1" : "0", children: [
2773
- /* @__PURE__ */ jsx29(Stop9, { offset: "0", stopColor: theme.accent }),
2774
- /* @__PURE__ */ jsx29(Stop9, { offset: "1", stopColor: theme.accent2 })
3585
+ const gradient = /* @__PURE__ */ jsx41(Defs10, { children: /* @__PURE__ */ jsxs36(LinearGradient10, { id, x1: "0", y1: "0", x2: "1", y2: variant === "ring" ? "1" : "0", children: [
3586
+ /* @__PURE__ */ jsx41(Stop10, { offset: "0", stopColor: theme.accent }),
3587
+ /* @__PURE__ */ jsx41(Stop10, { offset: "1", stopColor: theme.accent2 })
2775
3588
  ] }) });
2776
3589
  if (variant === "ring") {
2777
- const side = RING[size];
3590
+ const side = RING2[size];
2778
3591
  const stroke = STROKE[size];
2779
3592
  const r = 50 - stroke / 2;
2780
3593
  const circumference = 2 * Math.PI * r;
2781
3594
  const offset = known ? progress.interpolate({ inputRange: [0, 1], outputRange: [circumference, 0] }) : circumference * 0.75;
2782
3595
  const rotate = spin.interpolate({ inputRange: [0, 1], outputRange: ["0deg", "360deg"] });
2783
- return /* @__PURE__ */ jsxs25(View24, { ...a11y, style: [styles20.ring, { width: side, height: side }, style], children: [
2784
- /* @__PURE__ */ jsx29(Animated12.View, { style: [StyleSheet20.absoluteFill, { transform: [{ rotate: known ? "-90deg" : rotate }] }], children: /* @__PURE__ */ jsxs25(Svg13, { width: side, height: side, viewBox: "0 0 100 100", children: [
3596
+ return /* @__PURE__ */ jsxs36(View35, { ...a11y, style: [styles31.ring, { width: side, height: side }, style], children: [
3597
+ /* @__PURE__ */ jsx41(Animated16.View, { style: [StyleSheet31.absoluteFill, { transform: [{ rotate: known ? "-90deg" : rotate }] }], children: /* @__PURE__ */ jsxs36(Svg17, { width: side, height: side, viewBox: "0 0 100 100", children: [
2785
3598
  gradient,
2786
- /* @__PURE__ */ jsx29(Circle8, { cx: 50, cy: 50, r, fill: "none", stroke: theme.borderDefault, strokeWidth: stroke }),
2787
- /* @__PURE__ */ jsx29(
3599
+ /* @__PURE__ */ jsx41(Circle11, { cx: 50, cy: 50, r, fill: "none", stroke: theme.borderDefault, strokeWidth: stroke }),
3600
+ /* @__PURE__ */ jsx41(
2788
3601
  AnimatedCircle,
2789
3602
  {
2790
3603
  cx: 50,
@@ -2804,43 +3617,51 @@ function Progress({ variant = "bar", size = "md", value, max = 100, label, value
2804
3617
  }
2805
3618
  const width = known ? progress.interpolate({ inputRange: [0, 1], outputRange: ["0%", "100%"] }) : "40%";
2806
3619
  const translate = spin.interpolate({ inputRange: [0, 1], outputRange: [-0.4 * track, track] });
2807
- return /* @__PURE__ */ jsx29(
2808
- View24,
3620
+ return /* @__PURE__ */ jsx41(
3621
+ View35,
2809
3622
  {
2810
3623
  ...a11y,
2811
3624
  onLayout: known ? void 0 : (event) => setTrack(event.nativeEvent.layout.width),
2812
- style: [styles20.bar, { height: BAR[size], backgroundColor: theme.surface3 }, style],
2813
- children: /* @__PURE__ */ jsx29(Animated12.View, { style: [styles20.fill, { width }, known || reduce ? null : { transform: [{ translateX: translate }] }], children: /* @__PURE__ */ jsxs25(Svg13, { width: "100%", height: "100%", preserveAspectRatio: "none", children: [
3625
+ style: [styles31.bar, { height: BAR2[size], backgroundColor: theme.surface3 }, style],
3626
+ children: /* @__PURE__ */ jsx41(Animated16.View, { style: [styles31.fill, { width }, known || reduce ? null : { transform: [{ translateX: translate }] }], children: /* @__PURE__ */ jsxs36(Svg17, { width: "100%", height: "100%", preserveAspectRatio: "none", children: [
2814
3627
  gradient,
2815
- /* @__PURE__ */ jsx29(Rect3, { x: 0, y: 0, width: "100%", height: "100%", fill: `url(#${id})` })
3628
+ /* @__PURE__ */ jsx41(Rect3, { x: 0, y: 0, width: "100%", height: "100%", fill: `url(#${id})` })
2816
3629
  ] }) })
2817
3630
  }
2818
3631
  );
2819
3632
  }
2820
- var styles20 = StyleSheet20.create({
3633
+ var styles31 = StyleSheet31.create({
2821
3634
  ring: { alignItems: "center", justifyContent: "center" },
2822
3635
  bar: { width: "100%", overflow: "hidden", borderRadius: 9999 },
2823
3636
  fill: { height: "100%", overflow: "hidden", borderRadius: 9999 }
2824
3637
  });
2825
3638
 
3639
+ // src/native/pull-to-refresh.tsx
3640
+ import { RefreshControl } from "react-native";
3641
+ import { jsx as jsx42 } from "react/jsx-runtime";
3642
+ function PullToRefresh({ label, ...props }) {
3643
+ const { theme } = useTheme();
3644
+ return /* @__PURE__ */ jsx42(RefreshControl, { ...props, tintColor: theme.accent, colors: [theme.accent], progressBackgroundColor: theme.surface2, title: label, titleColor: theme.textSecondary });
3645
+ }
3646
+
2826
3647
  // src/native/radio-group.tsx
2827
- import * as React22 from "react";
2828
- import { Animated as Animated13, Pressable as Pressable10, StyleSheet as StyleSheet21, Text as Text14, View as View25 } from "react-native";
2829
- import Svg14, { Path as Path12 } from "react-native-svg";
2830
- import { jsx as jsx30, jsxs as jsxs26 } from "react/jsx-runtime";
3648
+ import * as React30 from "react";
3649
+ import { Animated as Animated17, Pressable as Pressable15, StyleSheet as StyleSheet32, Text as Text15, View as View36 } from "react-native";
3650
+ import Svg18, { Path as Path14 } from "react-native-svg";
3651
+ import { jsx as jsx43, jsxs as jsxs37 } from "react/jsx-runtime";
2831
3652
  function Check({ color }) {
2832
- return /* @__PURE__ */ jsx30(Svg14, { width: 12, height: 12, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: 3.2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx30(Path12, { d: "M20 6 9 17l-5-5" }) });
3653
+ return /* @__PURE__ */ jsx43(Svg18, { width: 12, height: 12, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: 3.2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx43(Path14, { d: "M20 6 9 17l-5-5" }) });
2833
3654
  }
2834
3655
  function Key({ option, checked, disabled, onPress }) {
2835
3656
  const { theme, radius: radius3, motion: motion3 } = useTheme();
2836
- const [held, setHeld] = React22.useState(false);
2837
- const [sink] = React22.useState(() => new Animated13.Value(checked ? 1 : 0));
3657
+ const [held, setHeld] = React30.useState(false);
3658
+ const [sink] = React30.useState(() => new Animated17.Value(checked ? 1 : 0));
2838
3659
  const down = checked || held;
2839
- React22.useEffect(() => {
2840
- Animated13.timing(sink, { toValue: down ? 1 : 0, duration: motion3.duration.fast, useNativeDriver: true }).start();
3660
+ React30.useEffect(() => {
3661
+ Animated17.timing(sink, { toValue: down ? 1 : 0, duration: motion3.duration.fast, useNativeDriver: true }).start();
2841
3662
  }, [down, sink, motion3.duration.fast]);
2842
- return /* @__PURE__ */ jsxs26(
2843
- Pressable10,
3663
+ return /* @__PURE__ */ jsxs37(
3664
+ Pressable15,
2844
3665
  {
2845
3666
  role: "radio",
2846
3667
  "aria-checked": checked,
@@ -2850,14 +3671,14 @@ function Key({ option, checked, disabled, onPress }) {
2850
3671
  onPress,
2851
3672
  onPressIn: () => setHeld(true),
2852
3673
  onPressOut: () => setHeld(false),
2853
- style: [styles21.keySlot, disabled ? styles21.disabled : null],
3674
+ style: [styles32.keySlot, disabled ? styles32.disabled : null],
2854
3675
  children: [
2855
- /* @__PURE__ */ jsx30(View25, { style: [styles21.ledge, { borderRadius: radius3.lg, backgroundColor: checked ? theme.accentHover : theme.borderStrong }] }),
2856
- /* @__PURE__ */ jsxs26(
2857
- Animated13.View,
3676
+ /* @__PURE__ */ jsx43(View36, { style: [styles32.ledge, { borderRadius: radius3.lg, backgroundColor: checked ? theme.accentHover : theme.borderStrong }] }),
3677
+ /* @__PURE__ */ jsxs37(
3678
+ Animated17.View,
2858
3679
  {
2859
3680
  style: [
2860
- styles21.key,
3681
+ styles32.key,
2861
3682
  {
2862
3683
  borderRadius: radius3.lg,
2863
3684
  backgroundColor: checked ? theme.accent : theme.surface2,
@@ -2866,8 +3687,8 @@ function Key({ option, checked, disabled, onPress }) {
2866
3687
  }
2867
3688
  ],
2868
3689
  children: [
2869
- /* @__PURE__ */ jsx30(Text14, { style: [styles21.keyLabel, { color: checked ? theme.onAccent : theme.textPrimary }], children: option.label }),
2870
- option.hint ? /* @__PURE__ */ jsx30(Text14, { style: [styles21.keyHint, { color: checked ? theme.onAccent : theme.textSecondary }], children: option.hint }) : null
3690
+ /* @__PURE__ */ jsx43(Text15, { style: [styles32.keyLabel, { color: checked ? theme.onAccent : theme.textPrimary }], children: option.label }),
3691
+ option.hint ? /* @__PURE__ */ jsx43(Text15, { style: [styles32.keyHint, { color: checked ? theme.onAccent : theme.textSecondary }], children: option.hint }) : null
2871
3692
  ]
2872
3693
  }
2873
3694
  )
@@ -2877,7 +3698,7 @@ function Key({ option, checked, disabled, onPress }) {
2877
3698
  }
2878
3699
  function RadioGroup({ label, options, value: valueProp, defaultValue = null, onValueChange, variant = "list", error, disabled, style }) {
2879
3700
  const { theme, radius: radius3, haptic } = useTheme();
2880
- const [own, setOwn] = React22.useState(defaultValue);
3701
+ const [own, setOwn] = React30.useState(defaultValue);
2881
3702
  const value = valueProp !== void 0 ? valueProp : own;
2882
3703
  const pick = (v) => {
2883
3704
  haptic(variant === "buttons" ? "impact" : "selection");
@@ -2888,10 +3709,10 @@ function RadioGroup({ label, options, value: valueProp, defaultValue = null, onV
2888
3709
  const checked = o.value === value;
2889
3710
  const off = Boolean(disabled || o.disabled);
2890
3711
  const name = o.description ? `${o.label}, ${o.description}` : o.label;
2891
- if (variant === "buttons") return /* @__PURE__ */ jsx30(Key, { option: o, checked, disabled: off, onPress: () => pick(o.value) }, o.value);
3712
+ if (variant === "buttons") return /* @__PURE__ */ jsx43(Key, { option: o, checked, disabled: off, onPress: () => pick(o.value) }, o.value);
2892
3713
  if (variant === "segmented")
2893
- return /* @__PURE__ */ jsx30(
2894
- Pressable10,
3714
+ return /* @__PURE__ */ jsx43(
3715
+ Pressable15,
2895
3716
  {
2896
3717
  role: "radio",
2897
3718
  "aria-checked": checked,
@@ -2899,14 +3720,14 @@ function RadioGroup({ label, options, value: valueProp, defaultValue = null, onV
2899
3720
  "aria-disabled": off || void 0,
2900
3721
  disabled: off,
2901
3722
  onPress: () => pick(o.value),
2902
- style: [styles21.segment, { borderRadius: radius3.md }, checked ? { backgroundColor: theme.surface0, borderColor: theme.borderDefault } : null, off ? styles21.disabled : null],
2903
- children: /* @__PURE__ */ jsx30(Text14, { numberOfLines: 1, style: [styles21.segmentLabel, { color: checked ? theme.textPrimary : theme.textSecondary }], children: o.label })
3723
+ style: [styles32.segment, { borderRadius: radius3.md }, checked ? { backgroundColor: theme.surface0, borderColor: theme.borderDefault } : null, off ? styles32.disabled : null],
3724
+ children: /* @__PURE__ */ jsx43(Text15, { numberOfLines: 1, style: [styles32.segmentLabel, { color: checked ? theme.textPrimary : theme.textSecondary }], children: o.label })
2904
3725
  },
2905
3726
  o.value
2906
3727
  );
2907
3728
  if (variant === "cards")
2908
- return /* @__PURE__ */ jsxs26(
2909
- Pressable10,
3729
+ return /* @__PURE__ */ jsxs37(
3730
+ Pressable15,
2910
3731
  {
2911
3732
  role: "radio",
2912
3733
  "aria-checked": checked,
@@ -2915,40 +3736,40 @@ function RadioGroup({ label, options, value: valueProp, defaultValue = null, onV
2915
3736
  disabled: off,
2916
3737
  onPress: () => pick(o.value),
2917
3738
  style: ({ pressed }) => [
2918
- styles21.card,
3739
+ styles32.card,
2919
3740
  { borderRadius: radius3.xl, backgroundColor: checked ? theme.accentSoft : theme.surface1, borderColor: checked ? theme.accent : theme.borderDefault, transform: [{ scale: pressed ? 0.98 : 1 }] },
2920
- off ? styles21.disabled : null
3741
+ off ? styles32.disabled : null
2921
3742
  ],
2922
3743
  children: [
2923
- /* @__PURE__ */ jsx30(View25, { style: [styles21.cardCheck, { borderColor: checked ? theme.accent : theme.borderStrong, backgroundColor: checked ? theme.accent : theme.surface1 }], children: checked ? /* @__PURE__ */ jsx30(Check, { color: theme.onAccent }) : null }),
2924
- /* @__PURE__ */ jsx30(Text14, { style: [styles21.cardLabel, { color: theme.textPrimary }], children: o.label }),
2925
- o.description ? /* @__PURE__ */ jsx30(Text14, { style: [styles21.cardDescription, { color: theme.textSecondary }], children: o.description }) : null
3744
+ /* @__PURE__ */ jsx43(View36, { style: [styles32.cardCheck, { borderColor: checked ? theme.accent : theme.borderStrong, backgroundColor: checked ? theme.accent : theme.surface1 }], children: checked ? /* @__PURE__ */ jsx43(Check, { color: theme.onAccent }) : null }),
3745
+ /* @__PURE__ */ jsx43(Text15, { style: [styles32.cardLabel, { color: theme.textPrimary }], children: o.label }),
3746
+ o.description ? /* @__PURE__ */ jsx43(Text15, { style: [styles32.cardDescription, { color: theme.textSecondary }], children: o.description }) : null
2926
3747
  ]
2927
3748
  },
2928
3749
  o.value
2929
3750
  );
2930
- return /* @__PURE__ */ jsxs26(Pressable10, { role: "radio", "aria-checked": checked, "aria-label": name, "aria-disabled": off || void 0, disabled: off, onPress: () => pick(o.value), style: [styles21.row, off ? styles21.disabled : null], children: [
2931
- /* @__PURE__ */ jsx30(View25, { style: [styles21.dot, { borderColor: checked ? theme.accent : theme.borderStrong, backgroundColor: checked ? theme.accent : theme.surface1 }], children: checked ? /* @__PURE__ */ jsx30(View25, { style: [styles21.dotIn, { backgroundColor: theme.onAccent }] }) : null }),
2932
- /* @__PURE__ */ jsxs26(View25, { style: styles21.rowText, children: [
2933
- /* @__PURE__ */ jsx30(Text14, { style: [styles21.rowLabel, { color: theme.textPrimary }], children: o.label }),
2934
- o.description ? /* @__PURE__ */ jsx30(Text14, { style: [styles21.cardDescription, { color: theme.textSecondary }], children: o.description }) : null
3751
+ return /* @__PURE__ */ jsxs37(Pressable15, { role: "radio", "aria-checked": checked, "aria-label": name, "aria-disabled": off || void 0, disabled: off, onPress: () => pick(o.value), style: [styles32.row, off ? styles32.disabled : null], children: [
3752
+ /* @__PURE__ */ jsx43(View36, { style: [styles32.dot, { borderColor: checked ? theme.accent : theme.borderStrong, backgroundColor: checked ? theme.accent : theme.surface1 }], children: checked ? /* @__PURE__ */ jsx43(View36, { style: [styles32.dotIn, { backgroundColor: theme.onAccent }] }) : null }),
3753
+ /* @__PURE__ */ jsxs37(View36, { style: styles32.rowText, children: [
3754
+ /* @__PURE__ */ jsx43(Text15, { style: [styles32.rowLabel, { color: theme.textPrimary }], children: o.label }),
3755
+ o.description ? /* @__PURE__ */ jsx43(Text15, { style: [styles32.cardDescription, { color: theme.textSecondary }], children: o.description }) : null
2935
3756
  ] })
2936
3757
  ] }, o.value);
2937
3758
  });
2938
- return /* @__PURE__ */ jsxs26(View25, { style: [styles21.root, style], children: [
2939
- /* @__PURE__ */ jsx30(
2940
- View25,
3759
+ return /* @__PURE__ */ jsxs37(View36, { style: [styles32.root, style], children: [
3760
+ /* @__PURE__ */ jsx43(
3761
+ View36,
2941
3762
  {
2942
3763
  role: "radiogroup",
2943
3764
  "aria-label": label,
2944
- style: variant === "segmented" ? [styles21.track, { borderRadius: radius3.lg, backgroundColor: theme.surface2, borderColor: error ? theme.danger : theme.borderDefault }] : variant === "buttons" ? styles21.keys : variant === "cards" ? styles21.cards : styles21.list,
3765
+ style: variant === "segmented" ? [styles32.track, { borderRadius: radius3.lg, backgroundColor: theme.surface2, borderColor: error ? theme.danger : theme.borderDefault }] : variant === "buttons" ? styles32.keys : variant === "cards" ? styles32.cards : styles32.list,
2945
3766
  children: body
2946
3767
  }
2947
3768
  ),
2948
- error ? /* @__PURE__ */ jsx30(Text14, { role: "alert", "aria-live": "polite", style: [styles21.error, { color: theme.dangerText }], children: error }) : null
3769
+ error ? /* @__PURE__ */ jsx43(Text15, { role: "alert", "aria-live": "polite", style: [styles32.error, { color: theme.dangerText }], children: error }) : null
2949
3770
  ] });
2950
3771
  }
2951
- var styles21 = StyleSheet21.create({
3772
+ var styles32 = StyleSheet32.create({
2952
3773
  root: { gap: 6, alignSelf: "stretch" },
2953
3774
  list: { gap: 2 },
2954
3775
  row: { flexDirection: "row", alignItems: "center", gap: 12, minHeight: 44 },
@@ -2967,38 +3788,41 @@ var styles21 = StyleSheet21.create({
2967
3788
  key: { minHeight: 48, paddingHorizontal: 16, paddingVertical: 8, alignItems: "center", justifyContent: "center", gap: 1, borderWidth: 1 },
2968
3789
  keyLabel: { fontSize: 15, fontWeight: "700" },
2969
3790
  keyHint: { fontSize: 11, fontWeight: "500" },
2970
- track: { flexDirection: "row", padding: 3, gap: 3, borderWidth: StyleSheet21.hairlineWidth, height: 42 },
2971
- segment: { flex: 1, alignItems: "center", justifyContent: "center", paddingHorizontal: 8, borderWidth: StyleSheet21.hairlineWidth, borderColor: "transparent" },
3791
+ track: { flexDirection: "row", padding: 3, gap: 3, borderWidth: StyleSheet32.hairlineWidth, height: 42 },
3792
+ segment: { flex: 1, alignItems: "center", justifyContent: "center", paddingHorizontal: 8, borderWidth: StyleSheet32.hairlineWidth, borderColor: "transparent" },
2972
3793
  segmentLabel: { fontSize: 13, fontWeight: "600" },
2973
3794
  error: { fontSize: 12, lineHeight: 16 },
2974
3795
  disabled: { opacity: 0.4 }
2975
3796
  });
2976
3797
 
2977
3798
  // src/native/search-field.tsx
2978
- import * as React23 from "react";
2979
- import { Pressable as Pressable11, StyleSheet as StyleSheet22, TextInput as TextInput4, View as View26 } from "react-native";
2980
- import Svg15, { Circle as Circle9, Path as Path13 } from "react-native-svg";
2981
- import { jsx as jsx31, jsxs as jsxs27 } from "react/jsx-runtime";
2982
- function SearchField({ label, value, defaultValue = "", onValueChange, onSearch, debounce = 300, onSubmit, clearLabel, style, placeholder, ...props }) {
3799
+ import * as React31 from "react";
3800
+ import { Pressable as Pressable16, StyleSheet as StyleSheet33, TextInput as TextInput5, View as View37 } from "react-native";
3801
+ import Svg19, { Circle as Circle12, Path as Path15 } from "react-native-svg";
3802
+ import { jsx as jsx44, jsxs as jsxs38 } from "react/jsx-runtime";
3803
+ function SearchField({ label, value, defaultValue = "", onValueChange, onSearch, debounce = 300, onSubmit, clearLabel, cancelLabel, onCancel, style, placeholder, onFocus, onBlur, ...props }) {
3804
+ const [focused, setFocused] = React31.useState(false);
3805
+ const input = React31.useRef(null);
2983
3806
  const { theme, radius: radius3 } = useTheme();
2984
- const [own, setOwn] = React23.useState(defaultValue);
3807
+ const [own, setOwn] = React31.useState(defaultValue);
2985
3808
  const query = value ?? own;
2986
- const timer2 = React23.useRef(void 0);
2987
- React23.useEffect(() => () => clearTimeout(timer2.current), []);
3809
+ const timer2 = React31.useRef(void 0);
3810
+ React31.useEffect(() => () => clearTimeout(timer2.current), []);
2988
3811
  const change = (next) => {
2989
3812
  if (value === void 0) setOwn(next);
2990
3813
  onValueChange?.(next);
2991
3814
  clearTimeout(timer2.current);
2992
3815
  if (onSearch) timer2.current = setTimeout(() => onSearch(next), debounce);
2993
3816
  };
2994
- return /* @__PURE__ */ jsxs27(View26, { style: [styles22.frame, { borderRadius: radius3.md, borderColor: theme.borderDefault, backgroundColor: theme.surface2 }, style], children: [
2995
- /* @__PURE__ */ jsxs27(Svg15, { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: theme.textSecondary, strokeWidth: 2, strokeLinecap: "round", "aria-hidden": true, children: [
2996
- /* @__PURE__ */ jsx31(Circle9, { cx: 11, cy: 11, r: 7 }),
2997
- /* @__PURE__ */ jsx31(Path13, { d: "m20 20-3.5-3.5" })
3817
+ const field = /* @__PURE__ */ jsxs38(View37, { style: [styles33.frame, { borderRadius: radius3.md, borderColor: theme.borderDefault, backgroundColor: theme.surface2 }, style], children: [
3818
+ /* @__PURE__ */ jsxs38(Svg19, { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: theme.textSecondary, strokeWidth: 2, strokeLinecap: "round", "aria-hidden": true, children: [
3819
+ /* @__PURE__ */ jsx44(Circle12, { cx: 11, cy: 11, r: 7 }),
3820
+ /* @__PURE__ */ jsx44(Path15, { d: "m20 20-3.5-3.5" })
2998
3821
  ] }),
2999
- /* @__PURE__ */ jsx31(
3000
- TextInput4,
3822
+ /* @__PURE__ */ jsx44(
3823
+ TextInput5,
3001
3824
  {
3825
+ ref: input,
3002
3826
  role: "searchbox",
3003
3827
  "aria-label": label,
3004
3828
  value: query,
@@ -3014,34 +3838,63 @@ function SearchField({ label, value, defaultValue = "", onValueChange, onSearch,
3014
3838
  onSearch?.(query);
3015
3839
  onSubmit?.(query);
3016
3840
  },
3017
- style: [styles22.input, { color: theme.textPrimary }],
3841
+ style: [styles33.input, { color: theme.textPrimary }],
3842
+ onFocus: (e) => {
3843
+ setFocused(true);
3844
+ onFocus?.(e);
3845
+ },
3846
+ onBlur: (e) => {
3847
+ setFocused(false);
3848
+ onBlur?.(e);
3849
+ },
3018
3850
  ...props
3019
3851
  }
3020
3852
  ),
3021
- query ? /* @__PURE__ */ jsx31(Pressable11, { role: "button", "aria-label": clearLabel, hitSlop: 10, onPress: () => change(""), style: styles22.clear, children: /* @__PURE__ */ jsx31(Svg15, { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: theme.textSecondary, strokeWidth: 2.4, strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx31(Path13, { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
3853
+ query ? /* @__PURE__ */ jsx44(Pressable16, { role: "button", "aria-label": clearLabel, hitSlop: 10, onPress: () => change(""), style: styles33.clear, children: /* @__PURE__ */ jsx44(Svg19, { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: theme.textSecondary, strokeWidth: 2.4, strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx44(Path15, { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
3854
+ ] });
3855
+ if (!cancelLabel || !onCancel) return field;
3856
+ return /* @__PURE__ */ jsxs38(View37, { style: styles33.bar, children: [
3857
+ /* @__PURE__ */ jsx44(View37, { style: styles33.grow, children: field }),
3858
+ focused || query ? /* @__PURE__ */ jsx44(
3859
+ Pressable16,
3860
+ {
3861
+ role: "button",
3862
+ onPress: () => {
3863
+ change("");
3864
+ input.current?.blur();
3865
+ onCancel();
3866
+ },
3867
+ hitSlop: 8,
3868
+ style: styles33.cancel,
3869
+ children: /* @__PURE__ */ jsx44(Txt, { variant: "label", tone: "accent", children: cancelLabel })
3870
+ }
3871
+ ) : null
3022
3872
  ] });
3023
3873
  }
3024
- var styles22 = StyleSheet22.create({
3025
- frame: { flexDirection: "row", alignItems: "center", gap: 8, height: 44, paddingLeft: 12, paddingRight: 6, borderWidth: StyleSheet22.hairlineWidth },
3874
+ var styles33 = StyleSheet33.create({
3875
+ frame: { flexDirection: "row", alignItems: "center", gap: 8, height: 44, paddingLeft: 12, paddingRight: 6, borderWidth: StyleSheet33.hairlineWidth },
3026
3876
  input: { flex: 1, height: "100%", fontSize: 15, paddingVertical: 0 },
3877
+ bar: { flexDirection: "row", alignItems: "center", gap: 10 },
3878
+ grow: { flex: 1 },
3879
+ cancel: { minHeight: 44, justifyContent: "center" },
3027
3880
  clear: { width: 32, height: 32, alignItems: "center", justifyContent: "center" }
3028
3881
  });
3029
3882
 
3030
3883
  // src/native/segmented.tsx
3031
- import { Pressable as Pressable12, StyleSheet as StyleSheet23, Text as Text15, View as View27 } from "react-native";
3032
- import { jsx as jsx32 } from "react/jsx-runtime";
3884
+ import { Pressable as Pressable17, StyleSheet as StyleSheet34, Text as Text16, View as View38 } from "react-native";
3885
+ import { jsx as jsx45 } from "react/jsx-runtime";
3033
3886
  function Segmented({ options, value, onValueChange, size = "md", "aria-label": label, style }) {
3034
3887
  const { theme, radius: radius3 } = useTheme();
3035
- return /* @__PURE__ */ jsx32(
3036
- View27,
3888
+ return /* @__PURE__ */ jsx45(
3889
+ View38,
3037
3890
  {
3038
3891
  role: "tablist",
3039
3892
  "aria-label": label,
3040
- style: [styles23.track, { backgroundColor: theme.surface2, borderColor: theme.borderSubtle, borderRadius: radius3.md, height: size === "sm" ? 32 : 40 }, style],
3893
+ style: [styles34.track, { backgroundColor: theme.surface2, borderColor: theme.borderSubtle, borderRadius: radius3.md, height: size === "sm" ? 32 : 40 }, style],
3041
3894
  children: options.map((option) => {
3042
3895
  const selected = option.value === value;
3043
- return /* @__PURE__ */ jsx32(
3044
- Pressable12,
3896
+ return /* @__PURE__ */ jsx45(
3897
+ Pressable17,
3045
3898
  {
3046
3899
  role: "tab",
3047
3900
  "aria-selected": selected,
@@ -3051,12 +3904,12 @@ function Segmented({ options, value, onValueChange, size = "md", "aria-label": l
3051
3904
  if (!selected) onValueChange(option.value);
3052
3905
  },
3053
3906
  style: [
3054
- styles23.segment,
3907
+ styles34.segment,
3055
3908
  { borderRadius: radius3.sm },
3056
3909
  selected ? { backgroundColor: theme.surface0, borderColor: theme.borderDefault } : null,
3057
- option.disabled ? styles23.disabled : null
3910
+ option.disabled ? styles34.disabled : null
3058
3911
  ],
3059
- children: /* @__PURE__ */ jsx32(Text15, { numberOfLines: 1, style: [styles23.label, { color: selected ? theme.textPrimary : theme.textSecondary, fontSize: size === "sm" ? 12 : 13 }], children: option.label })
3912
+ children: /* @__PURE__ */ jsx45(Text16, { numberOfLines: 1, style: [styles34.label, { color: selected ? theme.textPrimary : theme.textSecondary, fontSize: size === "sm" ? 12 : 13 }], children: option.label })
3060
3913
  },
3061
3914
  option.value
3062
3915
  );
@@ -3064,17 +3917,17 @@ function Segmented({ options, value, onValueChange, size = "md", "aria-label": l
3064
3917
  }
3065
3918
  );
3066
3919
  }
3067
- var styles23 = StyleSheet23.create({
3068
- track: { flexDirection: "row", padding: 3, gap: 3, borderWidth: StyleSheet23.hairlineWidth },
3069
- segment: { flex: 1, alignItems: "center", justifyContent: "center", paddingHorizontal: 8, borderWidth: StyleSheet23.hairlineWidth, borderColor: "transparent" },
3920
+ var styles34 = StyleSheet34.create({
3921
+ track: { flexDirection: "row", padding: 3, gap: 3, borderWidth: StyleSheet34.hairlineWidth },
3922
+ segment: { flex: 1, alignItems: "center", justifyContent: "center", paddingHorizontal: 8, borderWidth: StyleSheet34.hairlineWidth, borderColor: "transparent" },
3070
3923
  label: { fontWeight: "600" },
3071
3924
  disabled: { opacity: 0.4 }
3072
3925
  });
3073
3926
 
3074
3927
  // src/native/skeleton.tsx
3075
- import * as React24 from "react";
3076
- import { Animated as Animated14 } from "react-native";
3077
- import { jsx as jsx33 } from "react/jsx-runtime";
3928
+ import * as React32 from "react";
3929
+ import { Animated as Animated18 } from "react-native";
3930
+ import { jsx as jsx46 } from "react/jsx-runtime";
3078
3931
  var SHAPE = {
3079
3932
  text: { width: "100%", height: 12, radius: 4 },
3080
3933
  circle: { width: 40, height: 40, radius: 9999 },
@@ -3083,13 +3936,13 @@ var SHAPE = {
3083
3936
  function Skeleton({ shape = "text", width, height, style, testID }) {
3084
3937
  const { theme } = useTheme();
3085
3938
  const reduce = useReducedMotion();
3086
- const [opacity] = React24.useState(() => new Animated14.Value(1));
3087
- React24.useEffect(() => {
3939
+ const [opacity] = React32.useState(() => new Animated18.Value(1));
3940
+ React32.useEffect(() => {
3088
3941
  if (reduce) return;
3089
- const loop = Animated14.loop(
3090
- Animated14.sequence([
3091
- Animated14.timing(opacity, { toValue: 0.5, duration: 900, useNativeDriver: true }),
3092
- Animated14.timing(opacity, { toValue: 1, duration: 900, useNativeDriver: true })
3942
+ const loop = Animated18.loop(
3943
+ Animated18.sequence([
3944
+ Animated18.timing(opacity, { toValue: 0.5, duration: 900, useNativeDriver: true }),
3945
+ Animated18.timing(opacity, { toValue: 1, duration: 900, useNativeDriver: true })
3093
3946
  ])
3094
3947
  );
3095
3948
  loop.start();
@@ -3100,8 +3953,8 @@ function Skeleton({ shape = "text", width, height, style, testID }) {
3100
3953
  }, [reduce, opacity]);
3101
3954
  const s = SHAPE[shape];
3102
3955
  const side = shape === "circle" ? width ?? height ?? s.width : void 0;
3103
- return /* @__PURE__ */ jsx33(
3104
- Animated14.View,
3956
+ return /* @__PURE__ */ jsx46(
3957
+ Animated18.View,
3105
3958
  {
3106
3959
  testID,
3107
3960
  "aria-hidden": true,
@@ -3114,10 +3967,10 @@ function Skeleton({ shape = "text", width, height, style, testID }) {
3114
3967
  }
3115
3968
 
3116
3969
  // src/native/slider.tsx
3117
- import * as React25 from "react";
3118
- import { PanResponder, StyleSheet as StyleSheet24, Text as Text16, View as View28 } from "react-native";
3119
- import Svg16, { Defs as Defs10, LinearGradient as LinearGradient10, Rect as Rect4, Stop as Stop10 } from "react-native-svg";
3120
- import { jsx as jsx34, jsxs as jsxs28 } from "react/jsx-runtime";
3970
+ import * as React33 from "react";
3971
+ import { PanResponder as PanResponder2, StyleSheet as StyleSheet35, Text as Text17, View as View39 } from "react-native";
3972
+ import Svg20, { Defs as Defs11, LinearGradient as LinearGradient11, Rect as Rect4, Stop as Stop11 } from "react-native-svg";
3973
+ import { jsx as jsx47, jsxs as jsxs39 } from "react/jsx-runtime";
3121
3974
  var THUMB = 26;
3122
3975
  var toArray = (v) => v === void 0 ? void 0 : typeof v === "number" ? [v] : [...v];
3123
3976
  function Slider({
@@ -3135,7 +3988,7 @@ function Slider({
3135
3988
  floatingValue,
3136
3989
  ticks,
3137
3990
  marks: marks2,
3138
- tone: tone2 = "gradient",
3991
+ tone: tone3 = "gradient",
3139
3992
  orientation = "horizontal",
3140
3993
  disabled,
3141
3994
  style
@@ -3143,20 +3996,20 @@ function Slider({
3143
3996
  const { theme, radius: radius3, haptic } = useTheme();
3144
3997
  const range = Array.isArray(value ?? defaultValue);
3145
3998
  const vertical = orientation === "vertical";
3146
- const [inner, setInner] = React25.useState(() => toArray(defaultValue) ?? [min]);
3999
+ const [inner, setInner] = React33.useState(() => toArray(defaultValue) ?? [min]);
3147
4000
  const current = toArray(value) ?? inner;
3148
- const [length, setLength] = React25.useState(0);
3149
- const [dragging, setDragging] = React25.useState(null);
4001
+ const [length, setLength] = React33.useState(0);
4002
+ const [dragging, setDragging] = React33.useState(null);
3150
4003
  const gradientId = useSvgId("kzs");
3151
4004
  const out = (next) => range ? [next[0], next[1]] : next[0];
3152
4005
  const snap = (v) => Math.min(max, Math.max(min, Math.round((v - min) / step) * step + min));
3153
4006
  const pct = (v) => (v - min) / (max - min || 1);
3154
- const live = React25.useRef({ current, length, vertical, disabled });
3155
- React25.useLayoutEffect(() => {
4007
+ const live = React33.useRef({ current, length, vertical, disabled });
4008
+ React33.useLayoutEffect(() => {
3156
4009
  live.current = { current, length, vertical, disabled };
3157
4010
  });
3158
- const active = React25.useRef(0);
3159
- const start = React25.useRef(0);
4011
+ const active = React33.useRef(0);
4012
+ const start = React33.useRef(0);
3160
4013
  const set = (next) => {
3161
4014
  if (value === void 0) setInner(next);
3162
4015
  onValueChange?.(out(next));
@@ -3177,12 +4030,12 @@ function Slider({
3177
4030
  return min + p * (max - min);
3178
4031
  };
3179
4032
  const commit = () => onValueCommit?.(out(live.current.current));
3180
- const handlers = React25.useRef({ move, at, commit });
3181
- React25.useLayoutEffect(() => {
4033
+ const handlers = React33.useRef({ move, at, commit });
4034
+ React33.useLayoutEffect(() => {
3182
4035
  handlers.current = { move, at, commit };
3183
4036
  });
3184
- const [responder] = React25.useState(
3185
- () => PanResponder.create({
4037
+ const [responder] = React33.useState(
4038
+ () => PanResponder2.create({
3186
4039
  onStartShouldSetPanResponder: () => !live.current.disabled,
3187
4040
  onMoveShouldSetPanResponder: () => !live.current.disabled,
3188
4041
  onPanResponderTerminationRequest: () => false,
@@ -3209,24 +4062,24 @@ function Slider({
3209
4062
  const along = (p) => vertical ? { bottom: p * length } : { left: p * length };
3210
4063
  const onLayout = (e) => setLength(vertical ? e.nativeEvent.layout.height : e.nativeEvent.layout.width);
3211
4064
  const fill = vertical ? { bottom: pct(lo) * length, height: (pct(hi) - pct(lo)) * length, left: 0, right: 0 } : { left: pct(lo) * length, width: (pct(hi) - pct(lo)) * length, top: 0, bottom: 0 };
3212
- return /* @__PURE__ */ jsxs28(View28, { style: [styles24.root, vertical ? styles24.rootVertical : null, disabled ? styles24.disabled : null, style], children: [
3213
- showLabel ? /* @__PURE__ */ jsxs28(View28, { style: styles24.header, children: [
3214
- /* @__PURE__ */ jsx34(Text16, { style: [styles24.label, { color: theme.textSecondary }], children: label }),
3215
- /* @__PURE__ */ jsx34(Text16, { "aria-hidden": true, style: [styles24.value, { color: theme.textSecondary }], children: current.map(formatValue).join(" \u2013 ") })
4065
+ return /* @__PURE__ */ jsxs39(View39, { style: [styles35.root, vertical ? styles35.rootVertical : null, disabled ? styles35.disabled : null, style], children: [
4066
+ showLabel ? /* @__PURE__ */ jsxs39(View39, { style: styles35.header, children: [
4067
+ /* @__PURE__ */ jsx47(Text17, { style: [styles35.label, { color: theme.textSecondary }], children: label }),
4068
+ /* @__PURE__ */ jsx47(Text17, { "aria-hidden": true, style: [styles35.value, { color: theme.textSecondary }], children: current.map(formatValue).join(" \u2013 ") })
3216
4069
  ] }) : null,
3217
- /* @__PURE__ */ jsxs28(View28, { ...responder.panHandlers, style: vertical ? styles24.controlVertical : styles24.control, children: [
3218
- /* @__PURE__ */ jsxs28(View28, { onLayout, pointerEvents: "none", style: [vertical ? styles24.trackVertical : styles24.track, { borderRadius: radius3.full, backgroundColor: theme.surface3 }], children: [
3219
- /* @__PURE__ */ jsx34(View28, { style: [styles24.fill, fill, { borderRadius: radius3.full, overflow: "hidden", backgroundColor: theme.accent }], children: tone2 === "gradient" ? /* @__PURE__ */ jsxs28(Svg16, { width: "100%", height: "100%", "aria-hidden": true, children: [
3220
- /* @__PURE__ */ jsx34(Defs10, { children: /* @__PURE__ */ jsxs28(LinearGradient10, { id: gradientId, x1: "0", y1: vertical ? "1" : "0", x2: vertical ? "0" : "1", y2: "0", children: [
3221
- /* @__PURE__ */ jsx34(Stop10, { offset: "0", stopColor: theme.accent }),
3222
- /* @__PURE__ */ jsx34(Stop10, { offset: "1", stopColor: theme.accent2 })
4070
+ /* @__PURE__ */ jsxs39(View39, { ...responder.panHandlers, style: vertical ? styles35.controlVertical : styles35.control, children: [
4071
+ /* @__PURE__ */ jsxs39(View39, { onLayout, pointerEvents: "none", style: [vertical ? styles35.trackVertical : styles35.track, { borderRadius: radius3.full, backgroundColor: theme.surface3 }], children: [
4072
+ /* @__PURE__ */ jsx47(View39, { style: [styles35.fill, fill, { borderRadius: radius3.full, overflow: "hidden", backgroundColor: theme.accent }], children: tone3 === "gradient" ? /* @__PURE__ */ jsxs39(Svg20, { width: "100%", height: "100%", "aria-hidden": true, children: [
4073
+ /* @__PURE__ */ jsx47(Defs11, { children: /* @__PURE__ */ jsxs39(LinearGradient11, { id: gradientId, x1: "0", y1: vertical ? "1" : "0", x2: vertical ? "0" : "1", y2: "0", children: [
4074
+ /* @__PURE__ */ jsx47(Stop11, { offset: "0", stopColor: theme.accent }),
4075
+ /* @__PURE__ */ jsx47(Stop11, { offset: "1", stopColor: theme.accent2 })
3223
4076
  ] }) }),
3224
- /* @__PURE__ */ jsx34(Rect4, { width: "100%", height: "100%", fill: `url(#${gradientId})` })
4077
+ /* @__PURE__ */ jsx47(Rect4, { width: "100%", height: "100%", fill: `url(#${gradientId})` })
3225
4078
  ] }) : null }),
3226
- tickValues.map((t) => /* @__PURE__ */ jsx34(View28, { style: [vertical ? styles24.tickVertical : styles24.tick, along(pct(t)), { backgroundColor: t > lo && t < hi ? theme.onAccent : theme.borderStrong }] }, t))
4079
+ tickValues.map((t) => /* @__PURE__ */ jsx47(View39, { style: [vertical ? styles35.tickVertical : styles35.tick, along(pct(t)), { backgroundColor: t > lo && t < hi ? theme.onAccent : theme.borderStrong }] }, t))
3227
4080
  ] }),
3228
- current.map((v, i) => /* @__PURE__ */ jsx34(
3229
- View28,
4081
+ current.map((v, i) => /* @__PURE__ */ jsx47(
4082
+ View39,
3230
4083
  {
3231
4084
  accessible: true,
3232
4085
  role: "slider",
@@ -3245,16 +4098,16 @@ function Slider({
3245
4098
  onValueCommit?.(out(values));
3246
4099
  },
3247
4100
  pointerEvents: "none",
3248
- style: [styles24.thumb, vertical ? { bottom: pct(v) * length, left: (44 - THUMB) / 2, marginLeft: 0, marginTop: 0 } : { left: pct(v) * length - THUMB / 2, top: 0 }, { borderColor: theme.accent, backgroundColor: theme.textOnMedia, shadowColor: theme.scrimStrong }],
3249
- children: floatingValue === "always" || floatingValue && dragging === i ? /* @__PURE__ */ jsx34(View28, { "aria-hidden": true, style: [vertical ? styles24.bubbleVertical : styles24.bubble, { backgroundColor: theme.textPrimary, borderRadius: radius3.md }], children: /* @__PURE__ */ jsx34(Text16, { style: [styles24.bubbleText, { color: theme.surface0 }], children: formatValue(v) }) }) : null
4101
+ style: [styles35.thumb, vertical ? { bottom: pct(v) * length, left: (44 - THUMB) / 2, marginLeft: 0, marginTop: 0 } : { left: pct(v) * length - THUMB / 2, top: 0 }, { borderColor: theme.accent, backgroundColor: theme.textOnMedia, shadowColor: theme.scrimStrong }],
4102
+ children: floatingValue === "always" || floatingValue && dragging === i ? /* @__PURE__ */ jsx47(View39, { "aria-hidden": true, style: [vertical ? styles35.bubbleVertical : styles35.bubble, { backgroundColor: theme.textPrimary, borderRadius: radius3.md }], children: /* @__PURE__ */ jsx47(Text17, { style: [styles35.bubbleText, { color: theme.surface0 }], children: formatValue(v) }) }) : null
3250
4103
  },
3251
4104
  i
3252
4105
  ))
3253
4106
  ] }),
3254
- marks2?.length && !vertical ? /* @__PURE__ */ jsx34(View28, { "aria-hidden": true, style: styles24.marks, children: marks2.map((m) => /* @__PURE__ */ jsx34(Text16, { style: [styles24.mark, { left: pct(m.value) * length, color: theme.textSecondary, transform: [{ translateX: m.value === min ? 0 : m.value === max ? -40 : -20 }], textAlign: m.value === min ? "left" : m.value === max ? "right" : "center" }], children: m.label }, m.value)) }) : null
4107
+ marks2?.length && !vertical ? /* @__PURE__ */ jsx47(View39, { "aria-hidden": true, style: styles35.marks, children: marks2.map((m) => /* @__PURE__ */ jsx47(Text17, { style: [styles35.mark, { left: pct(m.value) * length, color: theme.textSecondary, transform: [{ translateX: m.value === min ? 0 : m.value === max ? -40 : -20 }], textAlign: m.value === min ? "left" : m.value === max ? "right" : "center" }], children: m.label }, m.value)) }) : null
3255
4108
  ] });
3256
4109
  }
3257
- var styles24 = StyleSheet24.create({
4110
+ var styles35 = StyleSheet35.create({
3258
4111
  root: { gap: 8, alignSelf: "stretch" },
3259
4112
  rootVertical: { alignSelf: "flex-start", alignItems: "center" },
3260
4113
  header: { flexDirection: "row", justifyContent: "space-between", alignItems: "baseline", gap: 12 },
@@ -3290,10 +4143,10 @@ var styles24 = StyleSheet24.create({
3290
4143
 
3291
4144
  // src/native/spinner.tsx
3292
4145
  import { ActivityIndicator as ActivityIndicator2 } from "react-native";
3293
- import { jsx as jsx35 } from "react/jsx-runtime";
4146
+ import { jsx as jsx48 } from "react/jsx-runtime";
3294
4147
  function Spinner({ label, size = "md", ...props }) {
3295
4148
  const { theme } = useTheme();
3296
- return /* @__PURE__ */ jsx35(
4149
+ return /* @__PURE__ */ jsx48(
3297
4150
  ActivityIndicator2,
3298
4151
  {
3299
4152
  accessible: true,
@@ -3307,31 +4160,162 @@ function Spinner({ label, size = "md", ...props }) {
3307
4160
  );
3308
4161
  }
3309
4162
 
4163
+ // src/native/stepper.tsx
4164
+ import { StyleSheet as StyleSheet36, View as View40 } from "react-native";
4165
+ import Svg21, { Circle as Circle13, Path as Path16 } from "react-native-svg";
4166
+ import { jsx as jsx49, jsxs as jsxs40 } from "react/jsx-runtime";
4167
+ var WORDS = { done: "done", current: "in progress", upcoming: "to come", error: "failed" };
4168
+ function Stepper({ steps, current = 0, orientation = "vertical", statusLabels, "aria-label": label, style }) {
4169
+ const { theme } = useTheme();
4170
+ const words = { ...WORDS, ...statusLabels };
4171
+ const vertical = orientation === "vertical";
4172
+ return /* @__PURE__ */ jsx49(View40, { role: "list", "aria-label": label, style: [vertical ? styles36.column : styles36.row, style], children: steps.map((step, i) => {
4173
+ const status = step.status ?? (i < current ? "done" : i === current ? "current" : "upcoming");
4174
+ const last = i === steps.length - 1;
4175
+ const node = status === "current" ? /* @__PURE__ */ jsx49(LoaderGlyph, { value: step.value ?? null, size: 24 }) : status === "error" ? /* @__PURE__ */ jsx49(LoaderGlyph, { state: "error", size: 24 }) : /* @__PURE__ */ jsxs40(Svg21, { width: 24, height: 24, viewBox: "0 0 24 24", "aria-hidden": true, children: [
4176
+ /* @__PURE__ */ jsx49(Circle13, { cx: 12, cy: 12, r: 10, fill: status === "done" ? theme.accent : "none", stroke: status === "done" ? theme.accent : theme.borderStrong, strokeWidth: 2 }),
4177
+ status === "done" ? /* @__PURE__ */ jsx49(Path16, { d: "M7.5 12.3l3 3 6-6.3", stroke: theme.onAccent, strokeWidth: 2.2, fill: "none", strokeLinecap: "round", strokeLinejoin: "round" }) : null
4178
+ ] });
4179
+ const connector = !last ? /* @__PURE__ */ jsx49(View40, { "aria-hidden": true, style: [vertical ? styles36.vLine : styles36.hLine, { backgroundColor: status === "done" ? theme.accent : theme.borderDefault }] }) : null;
4180
+ return /* @__PURE__ */ jsxs40(View40, { role: "listitem", accessible: true, "aria-label": `${step.title}, ${words[status]}`, style: vertical ? styles36.vStep : styles36.hStep, children: [
4181
+ /* @__PURE__ */ jsxs40(View40, { style: vertical ? styles36.vRail : styles36.hRail, children: [
4182
+ node,
4183
+ connector
4184
+ ] }),
4185
+ /* @__PURE__ */ jsxs40(View40, { style: [styles36.body, vertical && !last ? { paddingBottom: 20 } : null], children: [
4186
+ /* @__PURE__ */ jsx49(Txt, { variant: "label", tone: status === "upcoming" ? "secondary" : "text", numberOfLines: vertical ? void 0 : 2, children: step.title }),
4187
+ step.description ? /* @__PURE__ */ jsx49(Txt, { variant: "caption", tone: "secondary", children: step.description }) : null,
4188
+ step.content && (status === "current" || status === "error") ? /* @__PURE__ */ jsx49(View40, { style: styles36.content, children: step.content }) : null
4189
+ ] })
4190
+ ] }, i);
4191
+ }) });
4192
+ }
4193
+ var styles36 = StyleSheet36.create({
4194
+ column: { gap: 0 },
4195
+ row: { flexDirection: "row" },
4196
+ vStep: { flexDirection: "row", gap: 12 },
4197
+ hStep: { flex: 1, gap: 8 },
4198
+ vRail: { alignItems: "center", width: 24 },
4199
+ hRail: { flexDirection: "row", alignItems: "center" },
4200
+ vLine: { width: 2, flex: 1, marginVertical: 4, borderRadius: 1 },
4201
+ hLine: { height: 2, flex: 1, marginHorizontal: 6, borderRadius: 1 },
4202
+ body: { flex: 1, gap: 2, paddingTop: 2 },
4203
+ content: { marginTop: 8 }
4204
+ });
4205
+
4206
+ // src/native/swipeable-row.tsx
4207
+ import * as React34 from "react";
4208
+ import { Animated as Animated19, PanResponder as PanResponder3, Pressable as Pressable18, StyleSheet as StyleSheet37, View as View41 } from "react-native";
4209
+ import { jsx as jsx50, jsxs as jsxs41 } from "react/jsx-runtime";
4210
+ var toneColor = (t, tone3) => ({ neutral: t.surface3, accent: t.accent, success: t.success, warning: t.warning, danger: t.danger })[tone3 ?? "neutral"];
4211
+ var toneText = (tone3) => tone3 === "neutral" || tone3 === void 0 ? "text" : "onAccent";
4212
+ function SwipeableRow({ children, trailing = [], leading = [], fullSwipe = 0.6, actionWidth = 80, onActivate, testID, style }) {
4213
+ const { theme, haptic } = useTheme();
4214
+ const reduce = useReducedMotion();
4215
+ const [x] = React34.useState(() => new Animated19.Value(0));
4216
+ const [width, setWidth] = React34.useState(0);
4217
+ const rest = React34.useRef(0);
4218
+ const armed = React34.useRef(false);
4219
+ const settle = (to) => {
4220
+ rest.current = to;
4221
+ if (reduce) x.setValue(to);
4222
+ else Animated19.spring(x, { toValue: to, useNativeDriver: true, damping: 22, stiffness: 240 }).start();
4223
+ };
4224
+ const run = (action) => {
4225
+ settle(0);
4226
+ action.onPress();
4227
+ };
4228
+ const pan = React34.useMemo(
4229
+ () => PanResponder3.create({
4230
+ onMoveShouldSetPanResponder: (_, g) => Math.abs(g.dx) > 8 && Math.abs(g.dx) > Math.abs(g.dy) * 1.5,
4231
+ onPanResponderMove: (_, g) => {
4232
+ let next = rest.current + g.dx;
4233
+ if (next < 0 && trailing.length === 0) next = 0;
4234
+ if (next > 0 && leading.length === 0) next = 0;
4235
+ x.setValue(next);
4236
+ const past = fullSwipe !== false && width > 0 && Math.abs(next) > width * fullSwipe;
4237
+ if (past !== armed.current) {
4238
+ armed.current = past;
4239
+ if (past) haptic("impact");
4240
+ }
4241
+ },
4242
+ onPanResponderRelease: (_, g) => {
4243
+ const at = rest.current + g.dx;
4244
+ if (armed.current) {
4245
+ armed.current = false;
4246
+ const action = at < 0 ? trailing[0] : leading[0];
4247
+ if (action) return run(action);
4248
+ }
4249
+ const open = at < 0 ? -trailing.length * actionWidth : leading.length * actionWidth;
4250
+ settle(Math.abs(at) > actionWidth / 2 ? open : 0);
4251
+ },
4252
+ onPanResponderTerminate: () => settle(0)
4253
+ }),
4254
+ [trailing, leading, fullSwipe, width, actionWidth]
4255
+ // eslint-disable-line react-hooks/exhaustive-deps -- run/settle are stable in effect
4256
+ );
4257
+ const side = (actions, edge) => /* @__PURE__ */ jsx50(View41, { "aria-hidden": true, style: [styles37.side, edge === "left" ? { left: 0 } : { right: 0, flexDirection: "row-reverse" }], children: actions.map((action, i) => (
4258
+ // eslint-disable-next-line react-hooks/refs -- runs on a press, never during render
4259
+ /* @__PURE__ */ jsxs41(Pressable18, { focusable: false, tabIndex: -1, onPress: () => run(action), style: [styles37.action, { width: actionWidth, backgroundColor: toneColor(theme, action.tone) }], children: [
4260
+ action.icon,
4261
+ /* @__PURE__ */ jsx50(Txt, { variant: "caption", tone: toneText(action.tone), style: styles37.actionText, numberOfLines: 1, children: action.label })
4262
+ ] }, i)
4263
+ )) });
4264
+ const all = [...leading, ...trailing];
4265
+ return /* @__PURE__ */ jsxs41(View41, { style: [styles37.root, style], onLayout: (e) => setWidth(e.nativeEvent.layout.width), children: [
4266
+ leading.length > 0 ? side(leading, "left") : null,
4267
+ trailing.length > 0 ? side(trailing, "right") : null,
4268
+ /* @__PURE__ */ jsx50(
4269
+ Animated19.View,
4270
+ {
4271
+ ...pan.panHandlers,
4272
+ accessible: true,
4273
+ testID,
4274
+ accessibilityActions: [...onActivate ? [{ name: "activate" }] : [], ...all.map((a) => ({ name: a.label, label: a.label }))],
4275
+ onAccessibilityAction: (e) => {
4276
+ if (e.nativeEvent.actionName === "activate") return onActivate?.();
4277
+ const action = all.find((a) => a.label === e.nativeEvent.actionName);
4278
+ if (action) action.onPress();
4279
+ },
4280
+ style: [styles37.front, { backgroundColor: theme.surface0, transform: [{ translateX: x }] }],
4281
+ children
4282
+ }
4283
+ )
4284
+ ] });
4285
+ }
4286
+ var styles37 = StyleSheet37.create({
4287
+ root: { overflow: "hidden" },
4288
+ side: { position: "absolute", top: 0, bottom: 0, flexDirection: "row" },
4289
+ action: { alignItems: "center", justifyContent: "center", gap: 4, paddingHorizontal: 6 },
4290
+ actionText: { fontWeight: "700" },
4291
+ front: {}
4292
+ });
4293
+
3310
4294
  // src/native/switch.tsx
3311
- import * as React26 from "react";
3312
- import { Animated as Animated15, Pressable as Pressable13, StyleSheet as StyleSheet25, Text as Text17, View as View29 } from "react-native";
3313
- import { jsx as jsx36, jsxs as jsxs29 } from "react/jsx-runtime";
4295
+ import * as React35 from "react";
4296
+ import { Animated as Animated20, Pressable as Pressable19, StyleSheet as StyleSheet38, Text as Text18, View as View42 } from "react-native";
4297
+ import { jsx as jsx51, jsxs as jsxs42 } from "react/jsx-runtime";
3314
4298
  var SIZES = { sm: { w: 40, h: 24, knob: 18 }, md: { w: 52, h: 32, knob: 26 } };
3315
4299
  function Switch({ label, checked, defaultChecked = false, onCheckedChange, description, showLabel, size = "md", error, disabled, style }) {
3316
4300
  const { theme, motion: motion3, haptic } = useTheme();
3317
- const [own, setOwn] = React26.useState(defaultChecked);
4301
+ const [own, setOwn] = React35.useState(defaultChecked);
3318
4302
  const on = checked ?? own;
3319
4303
  const d = SIZES[size];
3320
4304
  const travel = d.w - d.knob - (d.h - d.knob);
3321
- const [x] = React26.useState(() => new Animated15.Value(on ? 1 : 0));
3322
- React26.useEffect(() => {
3323
- Animated15.timing(x, { toValue: on ? 1 : 0, duration: motion3.duration.base, useNativeDriver: true }).start();
4305
+ const [x] = React35.useState(() => new Animated20.Value(on ? 1 : 0));
4306
+ React35.useEffect(() => {
4307
+ Animated20.timing(x, { toValue: on ? 1 : 0, duration: motion3.duration.base, useNativeDriver: true }).start();
3324
4308
  }, [on, x, motion3.duration.base]);
3325
4309
  const toggle = () => {
3326
4310
  haptic("selection");
3327
4311
  if (checked === void 0) setOwn(!on);
3328
4312
  onCheckedChange?.(!on);
3329
4313
  };
3330
- const track = /* @__PURE__ */ jsx36(View29, { style: [styles25.track, { width: d.w, height: d.h, borderRadius: d.h / 2, backgroundColor: on ? theme.accent : theme.surface3, borderColor: error ? theme.danger : on ? theme.accent : theme.borderDefault }], children: /* @__PURE__ */ jsx36(
3331
- Animated15.View,
4314
+ const track = /* @__PURE__ */ jsx51(View42, { style: [styles38.track, { width: d.w, height: d.h, borderRadius: d.h / 2, backgroundColor: on ? theme.accent : theme.surface3, borderColor: error ? theme.danger : on ? theme.accent : theme.borderDefault }], children: /* @__PURE__ */ jsx51(
4315
+ Animated20.View,
3332
4316
  {
3333
4317
  style: [
3334
- styles25.knob,
4318
+ styles38.knob,
3335
4319
  {
3336
4320
  width: d.knob,
3337
4321
  height: d.knob,
@@ -3353,19 +4337,19 @@ function Switch({ label, checked, defaultChecked = false, onCheckedChange, descr
3353
4337
  onPress: toggle
3354
4338
  };
3355
4339
  if (!showLabel)
3356
- return /* @__PURE__ */ jsx36(Pressable13, { ...a11y, hitSlop: 8, style: [disabled ? styles25.disabled : null, style], children: track });
3357
- return /* @__PURE__ */ jsxs29(View29, { style: [styles25.root, style], children: [
3358
- /* @__PURE__ */ jsxs29(Pressable13, { ...a11y, style: [styles25.row, disabled ? styles25.disabled : null], children: [
3359
- /* @__PURE__ */ jsxs29(View29, { style: styles25.text, children: [
3360
- /* @__PURE__ */ jsx36(Text17, { style: [styles25.label, { color: theme.textPrimary }], children: label }),
3361
- description ? /* @__PURE__ */ jsx36(Text17, { style: [styles25.description, { color: theme.textSecondary }], children: description }) : null
4340
+ return /* @__PURE__ */ jsx51(Pressable19, { ...a11y, hitSlop: { top: (44 - d.h) / 2, bottom: (44 - d.h) / 2, left: Math.max(0, (44 - d.w) / 2), right: Math.max(0, (44 - d.w) / 2) }, style: [disabled ? styles38.disabled : null, style], children: track });
4341
+ return /* @__PURE__ */ jsxs42(View42, { style: [styles38.root, style], children: [
4342
+ /* @__PURE__ */ jsxs42(Pressable19, { ...a11y, style: [styles38.row, disabled ? styles38.disabled : null], children: [
4343
+ /* @__PURE__ */ jsxs42(View42, { style: styles38.text, children: [
4344
+ /* @__PURE__ */ jsx51(Text18, { style: [styles38.label, { color: theme.textPrimary }], children: label }),
4345
+ description ? /* @__PURE__ */ jsx51(Text18, { style: [styles38.description, { color: theme.textSecondary }], children: description }) : null
3362
4346
  ] }),
3363
4347
  track
3364
4348
  ] }),
3365
- error ? /* @__PURE__ */ jsx36(Text17, { role: "alert", "aria-live": "polite", style: [styles25.description, { color: theme.dangerText }], children: error }) : null
4349
+ error ? /* @__PURE__ */ jsx51(Text18, { role: "alert", "aria-live": "polite", style: [styles38.description, { color: theme.dangerText }], children: error }) : null
3366
4350
  ] });
3367
4351
  }
3368
- var styles25 = StyleSheet25.create({
4352
+ var styles38 = StyleSheet38.create({
3369
4353
  root: { gap: 2, alignSelf: "stretch" },
3370
4354
  row: { flexDirection: "row", alignItems: "center", gap: 16, minHeight: 48 },
3371
4355
  text: { flex: 1, gap: 2 },
@@ -3376,10 +4360,109 @@ var styles25 = StyleSheet25.create({
3376
4360
  disabled: { opacity: 0.4 }
3377
4361
  });
3378
4362
 
4363
+ // src/native/tab-bar.tsx
4364
+ import { Pressable as Pressable20, StyleSheet as StyleSheet39, Text as Text19, View as View43 } from "react-native";
4365
+ import { jsx as jsx52, jsxs as jsxs43 } from "react/jsx-runtime";
4366
+ function TabBar({ items: items2, value, onValueChange, onReselect, "aria-label": label, style }) {
4367
+ const { theme, insets, haptic } = useTheme();
4368
+ return /* @__PURE__ */ jsx52(View43, { role: "tablist", "aria-label": label, style: [styles39.bar, { backgroundColor: theme.glassBg, borderTopColor: theme.glassBorder, paddingBottom: Math.max(6, insets.bottom) }, style], children: items2.map((item) => {
4369
+ const selected = item.value === value;
4370
+ const color = selected ? theme.accentText : theme.textSecondary;
4371
+ const badge = item.badge === true ? "" : typeof item.badge === "number" && item.badge > 0 ? item.badge > 99 ? "99+" : String(item.badge) : null;
4372
+ return /* @__PURE__ */ jsxs43(
4373
+ Pressable20,
4374
+ {
4375
+ role: "tab",
4376
+ "aria-selected": selected,
4377
+ onPress: () => {
4378
+ haptic("selection");
4379
+ if (selected) onReselect?.(item.value);
4380
+ else onValueChange(item.value);
4381
+ },
4382
+ style: ({ pressed }) => [styles39.item, { opacity: pressed ? 0.7 : 1 }],
4383
+ children: [
4384
+ /* @__PURE__ */ jsxs43(View43, { "aria-hidden": true, style: styles39.icon, children: [
4385
+ item.icon(selected, color),
4386
+ badge !== null ? /* @__PURE__ */ jsx52(View43, { style: [badge ? styles39.count : styles39.dot, { backgroundColor: theme.danger, borderColor: theme.surface1 }], children: badge ? /* @__PURE__ */ jsx52(Text19, { style: [styles39.countText, { color: theme.onAccent }], children: badge }) : null }) : null
4387
+ ] }),
4388
+ /* @__PURE__ */ jsx52(Text19, { numberOfLines: 1, style: [styles39.label, { color, fontWeight: selected ? "700" : "500" }], children: item.label }),
4389
+ badge !== null && item.badgeLabel ? /* @__PURE__ */ jsx52(Text19, { style: styles39.unseen, children: `, ${item.badgeLabel}` }) : null
4390
+ ]
4391
+ },
4392
+ item.value
4393
+ );
4394
+ }) });
4395
+ }
4396
+ var styles39 = StyleSheet39.create({
4397
+ bar: { flexDirection: "row", borderTopWidth: StyleSheet39.hairlineWidth, paddingTop: 6 },
4398
+ item: { flex: 1, alignItems: "center", gap: 2, minHeight: 48, justifyContent: "center" },
4399
+ icon: { width: 28, height: 26, alignItems: "center", justifyContent: "center" },
4400
+ label: { fontSize: 11, lineHeight: 14 },
4401
+ unseen: { position: "absolute", width: 1, height: 1, overflow: "hidden", opacity: 0 },
4402
+ count: { position: "absolute", top: -4, left: 16, minWidth: 18, height: 18, borderRadius: 9, paddingHorizontal: 4, alignItems: "center", justifyContent: "center", borderWidth: 2 },
4403
+ countText: { fontSize: 10, fontWeight: "800", lineHeight: 12 },
4404
+ dot: { position: "absolute", top: 0, right: 0, width: 10, height: 10, borderRadius: 5, borderWidth: 2 }
4405
+ });
4406
+
4407
+ // src/native/tabs.tsx
4408
+ import * as React36 from "react";
4409
+ import { Pressable as Pressable21, ScrollView as ScrollView6, StyleSheet as StyleSheet40, View as View44 } from "react-native";
4410
+ import { jsx as jsx53, jsxs as jsxs44 } from "react/jsx-runtime";
4411
+ function Tabs({ items: items2, value, defaultValue, onValueChange, "aria-label": label, variant = "underline", style }) {
4412
+ const { theme, radius: radius3, haptic } = useTheme();
4413
+ const [own, setOwn] = React36.useState(defaultValue ?? items2[0]?.value);
4414
+ const current = value ?? own;
4415
+ const select = (next) => {
4416
+ if (next === current) return;
4417
+ haptic("selection");
4418
+ if (value === void 0) setOwn(next);
4419
+ onValueChange?.(next);
4420
+ };
4421
+ const segmented = variant === "segmented";
4422
+ const tabs = items2.map((item) => {
4423
+ const selected = item.value === current;
4424
+ return /* @__PURE__ */ jsx53(
4425
+ Pressable21,
4426
+ {
4427
+ role: "tab",
4428
+ "aria-selected": selected,
4429
+ "aria-disabled": item.disabled,
4430
+ disabled: item.disabled,
4431
+ onPress: () => select(item.value),
4432
+ style: [
4433
+ segmented ? styles40.segment : styles40.tab,
4434
+ segmented && selected ? { backgroundColor: theme.surface0, borderColor: theme.borderDefault, borderRadius: radius3.sm } : null,
4435
+ !segmented ? { borderBottomColor: selected ? theme.accent : "transparent" } : null,
4436
+ item.disabled ? styles40.disabled : null
4437
+ ],
4438
+ children: /* @__PURE__ */ jsxs44(Txt, { variant: "label", tone: selected ? "text" : "secondary", numberOfLines: 1, children: [
4439
+ item.label,
4440
+ item.count !== void 0 ? /* @__PURE__ */ jsx53(Txt, { variant: "caption", tone: "secondary", children: ` ${item.count}` }) : null
4441
+ ] })
4442
+ },
4443
+ item.value
4444
+ );
4445
+ });
4446
+ const panel = items2.find((i) => i.value === current)?.content;
4447
+ return /* @__PURE__ */ jsxs44(View44, { style: [styles40.root, style], children: [
4448
+ segmented ? /* @__PURE__ */ jsx53(View44, { role: "tablist", "aria-label": label, style: [styles40.track, { backgroundColor: theme.surface2, borderColor: theme.borderSubtle, borderRadius: radius3.md }], children: tabs }) : /* @__PURE__ */ jsx53(View44, { style: [styles40.underline, { borderBottomColor: theme.borderSubtle }], children: /* @__PURE__ */ jsx53(ScrollView6, { horizontal: true, showsHorizontalScrollIndicator: false, role: "tablist", "aria-label": label, contentContainerStyle: styles40.scroll, children: tabs }) }),
4449
+ panel !== void 0 ? /* @__PURE__ */ jsx53(View44, { role: "tabpanel", children: panel }) : null
4450
+ ] });
4451
+ }
4452
+ var styles40 = StyleSheet40.create({
4453
+ root: { gap: 12 },
4454
+ underline: { borderBottomWidth: StyleSheet40.hairlineWidth },
4455
+ scroll: { gap: 4, paddingHorizontal: 4 },
4456
+ tab: { minHeight: 44, justifyContent: "center", paddingHorizontal: 12, borderBottomWidth: 2 },
4457
+ track: { flexDirection: "row", padding: 3, gap: 3, borderWidth: StyleSheet40.hairlineWidth, height: 40 },
4458
+ segment: { flex: 1, alignItems: "center", justifyContent: "center", paddingHorizontal: 8, borderWidth: StyleSheet40.hairlineWidth, borderColor: "transparent" },
4459
+ disabled: { opacity: 0.4 }
4460
+ });
4461
+
3379
4462
  // src/native/toast.tsx
3380
- import * as React27 from "react";
3381
- import { AccessibilityInfo as AccessibilityInfo8, Animated as Animated16, Pressable as Pressable14, StyleSheet as StyleSheet26, Text as Text18, View as View30 } from "react-native";
3382
- import { Fragment as Fragment4, jsx as jsx37, jsxs as jsxs30 } from "react/jsx-runtime";
4463
+ import * as React37 from "react";
4464
+ import { AccessibilityInfo as AccessibilityInfo12, Animated as Animated21, PanResponder as PanResponder4, Pressable as Pressable22, StyleSheet as StyleSheet41, Text as Text20, View as View45 } from "react-native";
4465
+ import { Fragment as Fragment6, jsx as jsx54, jsxs as jsxs45 } from "react/jsx-runtime";
3383
4466
  var items = [];
3384
4467
  var listeners2 = /* @__PURE__ */ new Set();
3385
4468
  var counter = 0;
@@ -3403,87 +4486,104 @@ function dismiss(id) {
3403
4486
  emit();
3404
4487
  gone.forEach((t) => t.onDismiss?.());
3405
4488
  }
3406
- var tone = (name) => (title, options) => show(title, { ...options, tone: name });
4489
+ var tone2 = (name) => (title, options) => show(title, { ...options, tone: name });
3407
4490
  var toast = Object.assign(show, {
3408
- success: tone("success"),
3409
- warning: tone("warning"),
3410
- error: tone("error"),
3411
- info: tone("info"),
4491
+ success: tone2("success"),
4492
+ warning: tone2("warning"),
4493
+ error: tone2("error"),
4494
+ info: tone2("info"),
3412
4495
  dismiss
3413
4496
  });
3414
4497
  function ToastView({ item, closeLabel, duration }) {
3415
- const { theme, radius: radius3 } = useTheme();
4498
+ const { theme, radius: radius3, haptic } = useTheme();
3416
4499
  const reduce = useReducedMotion();
3417
- const [enter] = React27.useState(() => new Animated16.Value(reduce ? 1 : 0));
3418
- React27.useEffect(() => {
4500
+ const [swipe] = React37.useState(() => new Animated21.Value(0));
4501
+ const drag = React37.useMemo(
4502
+ () => PanResponder4.create({
4503
+ onMoveShouldSetPanResponder: (_, g) => Math.abs(g.dx) > 8 && Math.abs(g.dx) > Math.abs(g.dy),
4504
+ onPanResponderMove: (_, g) => swipe.setValue(g.dx),
4505
+ onPanResponderRelease: (_, g) => {
4506
+ if (Math.abs(g.dx) > 96 || Math.abs(g.vx) > 0.9) {
4507
+ Animated21.timing(swipe, { toValue: Math.sign(g.dx) * 480, duration: 160, useNativeDriver: true }).start(() => dismiss(item.id));
4508
+ } else Animated21.spring(swipe, { toValue: 0, useNativeDriver: true }).start();
4509
+ }
4510
+ }),
4511
+ [swipe, item.id]
4512
+ );
4513
+ React37.useEffect(() => {
4514
+ if (item.tone === "success" || item.tone === "warning") haptic(item.tone);
4515
+ if (item.tone === "error") haptic("warning");
4516
+ }, [item.id]);
4517
+ const [enter] = React37.useState(() => new Animated21.Value(reduce ? 1 : 0));
4518
+ React37.useEffect(() => {
3419
4519
  if (reduce) enter.setValue(1);
3420
- else Animated16.timing(enter, { toValue: 1, duration: 220, useNativeDriver: true }).start();
4520
+ else Animated21.timing(enter, { toValue: 1, duration: 220, useNativeDriver: true }).start();
3421
4521
  }, [enter, reduce]);
3422
- React27.useEffect(() => {
3423
- AccessibilityInfo8.announceForAccessibility(item.description ? `${item.title}. ${item.description}` : item.title);
4522
+ React37.useEffect(() => {
4523
+ AccessibilityInfo12.announceForAccessibility(item.description ? `${item.title}. ${item.description}` : item.title);
3424
4524
  }, [item.title, item.description]);
3425
4525
  const ms = item.duration ?? duration;
3426
- React27.useEffect(() => {
4526
+ React37.useEffect(() => {
3427
4527
  if (!Number.isFinite(ms)) return;
3428
4528
  const timer2 = setTimeout(() => dismiss(item.id), ms);
3429
4529
  return () => clearTimeout(timer2);
3430
4530
  }, [item.id, ms]);
3431
4531
  const edge = { success: theme.success, warning: theme.warning, error: theme.danger, info: theme.info, default: theme.borderDefault }[item.tone ?? "default"];
3432
- const text = /* @__PURE__ */ jsxs30(Fragment4, { children: [
3433
- item.icon ? /* @__PURE__ */ jsx37(View30, { "aria-hidden": true, children: item.icon }) : null,
3434
- /* @__PURE__ */ jsxs30(View30, { style: styles26.content, children: [
3435
- /* @__PURE__ */ jsx37(Txt, { variant: "label", numberOfLines: 2, children: item.title }),
3436
- item.description ? /* @__PURE__ */ jsx37(Txt, { variant: "caption", tone: "secondary", numberOfLines: 3, children: item.description }) : null
4532
+ const text = /* @__PURE__ */ jsxs45(Fragment6, { children: [
4533
+ item.icon ? /* @__PURE__ */ jsx54(View45, { "aria-hidden": true, children: item.icon }) : null,
4534
+ /* @__PURE__ */ jsxs45(View45, { style: styles41.content, children: [
4535
+ /* @__PURE__ */ jsx54(Txt, { variant: "label", numberOfLines: 2, children: item.title }),
4536
+ item.description ? /* @__PURE__ */ jsx54(Txt, { variant: "caption", tone: "secondary", numberOfLines: 3, children: item.description }) : null
3437
4537
  ] })
3438
4538
  ] });
3439
- const body = /* @__PURE__ */ jsxs30(Fragment4, { children: [
3440
- item.onPress ? /* @__PURE__ */ jsx37(
3441
- Pressable14,
4539
+ const body = /* @__PURE__ */ jsxs45(Fragment6, { children: [
4540
+ item.onPress ? /* @__PURE__ */ jsx54(
4541
+ Pressable22,
3442
4542
  {
3443
4543
  role: "button",
3444
4544
  onPress: () => {
3445
4545
  item.onPress?.();
3446
4546
  dismiss(item.id);
3447
4547
  },
3448
- style: ({ pressed }) => [styles26.main, { opacity: pressed ? 0.8 : 1 }],
4548
+ style: ({ pressed }) => [styles41.main, { opacity: pressed ? 0.8 : 1 }],
3449
4549
  children: text
3450
4550
  }
3451
- ) : /* @__PURE__ */ jsx37(View30, { style: styles26.main, children: text }),
3452
- item.action ? /* @__PURE__ */ jsx37(
3453
- Pressable14,
4551
+ ) : /* @__PURE__ */ jsx54(View45, { style: styles41.main, children: text }),
4552
+ item.action ? /* @__PURE__ */ jsx54(
4553
+ Pressable22,
3454
4554
  {
3455
4555
  role: "button",
3456
4556
  onPress: () => {
3457
4557
  item.action?.onPress();
3458
4558
  dismiss(item.id);
3459
4559
  },
3460
- style: [styles26.action, { backgroundColor: theme.accent, borderRadius: radius3.sm }],
3461
- children: /* @__PURE__ */ jsx37(Text18, { style: [styles26.actionLabel, { color: theme.onAccent }], children: item.action.label })
4560
+ style: [styles41.action, { backgroundColor: theme.accent, borderRadius: radius3.sm }],
4561
+ children: /* @__PURE__ */ jsx54(Text20, { style: [styles41.actionLabel, { color: theme.onAccent }], children: item.action.label })
3462
4562
  }
3463
4563
  ) : null,
3464
- /* @__PURE__ */ jsx37(Pressable14, { role: "button", "aria-label": closeLabel, hitSlop: 10, onPress: () => dismiss(item.id), style: styles26.close, children: /* @__PURE__ */ jsx37(Text18, { style: [styles26.cross, { color: theme.textSecondary }], children: "\xD7" }) })
4564
+ /* @__PURE__ */ jsx54(Pressable22, { role: "button", "aria-label": closeLabel, hitSlop: 10, onPress: () => dismiss(item.id), style: styles41.close, children: /* @__PURE__ */ jsx54(Text20, { style: [styles41.cross, { color: theme.textSecondary }], children: "\xD7" }) })
3465
4565
  ] });
3466
4566
  const frame = [
3467
- styles26.toast,
4567
+ styles41.toast,
3468
4568
  { backgroundColor: theme.surface2, borderColor: theme.borderDefault, borderLeftColor: edge, borderRadius: radius3.lg, shadowColor: theme.scrimStrong }
3469
4569
  ];
3470
- const motion3 = { transform: [{ translateY: enter.interpolate({ inputRange: [0, 1], outputRange: [-8, 0] }) }] };
3471
- return /* @__PURE__ */ jsx37(Animated16.View, { "aria-live": "polite", style: motion3, children: /* @__PURE__ */ jsx37(View30, { style: frame, children: body }) });
4570
+ const motion3 = { transform: [{ translateY: enter.interpolate({ inputRange: [0, 1], outputRange: [-8, 0] }) }, { translateX: swipe }] };
4571
+ return /* @__PURE__ */ jsx54(Animated21.View, { "aria-live": "polite", style: motion3, ...drag.panHandlers, children: /* @__PURE__ */ jsx54(View45, { style: frame, children: body }) });
3472
4572
  }
3473
4573
  function Toaster({ closeLabel, position = "top", offset = 12, duration = 6e3, max = 3 }) {
3474
- const all = React27.useSyncExternalStore(subscribe2, snapshot, snapshot);
4574
+ const all = React37.useSyncExternalStore(subscribe2, snapshot, snapshot);
3475
4575
  const shown = all.slice(-max);
3476
4576
  if (shown.length === 0) return null;
3477
- return /* @__PURE__ */ jsx37(View30, { pointerEvents: "box-none", style: [styles26.stack, position === "top" ? { top: offset } : { bottom: offset }], children: (position === "top" ? shown : [...shown].reverse()).map((item) => /* @__PURE__ */ jsx37(ToastView, { item, closeLabel, duration }, item.id)) });
4577
+ return /* @__PURE__ */ jsx54(View45, { pointerEvents: "box-none", style: [styles41.stack, position === "top" ? { top: offset } : { bottom: offset }], children: (position === "top" ? shown : [...shown].reverse()).map((item) => /* @__PURE__ */ jsx54(ToastView, { item, closeLabel, duration }, item.id)) });
3478
4578
  }
3479
- var styles26 = StyleSheet26.create({
4579
+ var styles41 = StyleSheet41.create({
3480
4580
  stack: { position: "absolute", left: 12, right: 12, gap: 8, zIndex: 100 },
3481
4581
  toast: {
3482
4582
  flexDirection: "row",
3483
4583
  alignItems: "center",
3484
4584
  gap: 10,
3485
4585
  padding: 12,
3486
- borderWidth: StyleSheet26.hairlineWidth,
4586
+ borderWidth: StyleSheet41.hairlineWidth,
3487
4587
  borderLeftWidth: 4,
3488
4588
  shadowOpacity: 0.3,
3489
4589
  shadowRadius: 16,
@@ -3498,6 +4598,8 @@ var styles26 = StyleSheet26.create({
3498
4598
  cross: { fontSize: 18, lineHeight: 20, fontWeight: "700" }
3499
4599
  });
3500
4600
  export {
4601
+ ActionSheet,
4602
+ ActivityFeed,
3501
4603
  Avatar,
3502
4604
  AvatarGroup,
3503
4605
  AvatarRoot,
@@ -3520,22 +4622,34 @@ export {
3520
4622
  DateField,
3521
4623
  DateWheel,
3522
4624
  DayStrip,
4625
+ DescriptionList,
3523
4626
  EmptyState,
3524
4627
  ErrorState,
4628
+ Fab,
3525
4629
  GoalGauge,
4630
+ Header,
3526
4631
  IconButton,
4632
+ ImageViewer,
3527
4633
  KrizakaMark,
4634
+ Loader,
4635
+ LoaderGlyph,
3528
4636
  LoadingState,
3529
4637
  Mascot,
3530
4638
  MascotState,
4639
+ Meter,
3531
4640
  MonthPicker,
4641
+ NumberTicker,
4642
+ Onboarding,
3532
4643
  OrazakaMark,
3533
4644
  OrochiaMark,
4645
+ OtpInput,
3534
4646
  Pagination,
4647
+ PermissionPrompt,
3535
4648
  Phoenix,
3536
4649
  ProductMark,
3537
4650
  ProfileCard,
3538
4651
  Progress,
4652
+ PullToRefresh,
3539
4653
  RadioGroup,
3540
4654
  SearchField,
3541
4655
  Segmented,
@@ -3544,8 +4658,12 @@ export {
3544
4658
  Skeleton,
3545
4659
  Slider,
3546
4660
  Spinner,
4661
+ Stepper,
3547
4662
  SuccessState,
4663
+ SwipeableRow,
3548
4664
  Switch,
4665
+ TabBar,
4666
+ Tabs,
3549
4667
  TextField,
3550
4668
  ThemeProvider,
3551
4669
  TimePicker,
@@ -3571,13 +4689,16 @@ export {
3571
4689
  isRealDate,
3572
4690
  latestBirthDate,
3573
4691
  monthNames,
4692
+ prefetchNeighbours,
3574
4693
  splitDuration,
3575
4694
  textStyles,
3576
4695
  timeSlots,
3577
4696
  timeToMinutes,
3578
4697
  toast,
3579
4698
  todayIso,
4699
+ useCollapsingHeader,
3580
4700
  useCountdown,
4701
+ useDelayedWait,
3581
4702
  useReducedMotion,
3582
4703
  useTheme,
3583
4704
  uses12Hours