@krizaka/ui 3.4.0 → 3.5.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 (244) hide show
  1. package/dist/argument-card.js +3 -3
  2. package/dist/chat.d.ts +187 -0
  3. package/dist/chat.js +132 -0
  4. package/dist/chat.js.map +1 -0
  5. package/dist/chunk-ECSCA3CN.js +128 -0
  6. package/dist/chunk-ECSCA3CN.js.map +1 -0
  7. package/dist/chunk-F2GKFIYK.js +47 -0
  8. package/dist/chunk-F2GKFIYK.js.map +1 -0
  9. package/dist/data-table.js +20 -134
  10. package/dist/data-table.js.map +1 -1
  11. package/dist/match-dialog.d.ts +30 -0
  12. package/dist/match-dialog.js +146 -0
  13. package/dist/match-dialog.js.map +1 -0
  14. package/dist/native.d.ts +421 -106
  15. package/dist/native.js +1535 -973
  16. package/dist/native.js.map +1 -1
  17. package/dist/page-hero.js +3 -3
  18. package/dist/photo-grid.d.ts +122 -0
  19. package/dist/photo-grid.js +94 -0
  20. package/dist/photo-grid.js.map +1 -0
  21. package/dist/step-progress.d.ts +20 -0
  22. package/dist/step-progress.js +17 -0
  23. package/dist/step-progress.js.map +1 -0
  24. package/dist/swipe-deck.d.ts +183 -0
  25. package/dist/swipe-deck.js +144 -0
  26. package/dist/swipe-deck.js.map +1 -0
  27. package/dist/tag-selector.d.ts +26 -0
  28. package/dist/tag-selector.js +21 -0
  29. package/dist/tag-selector.js.map +1 -0
  30. package/dist/verified-badge.d.ts +16 -0
  31. package/dist/verified-badge.js +23 -0
  32. package/dist/verified-badge.js.map +1 -0
  33. package/package.json +105 -7
  34. package/registry/achievement.json +1 -1
  35. package/registry/action-bar.json +1 -1
  36. package/registry/activity-feed.json +1 -1
  37. package/registry/alert.json +1 -1
  38. package/registry/app-shell.json +1 -1
  39. package/registry/argument-card.json +1 -1
  40. package/registry/audio-player.json +1 -1
  41. package/registry/auth-layout.json +1 -1
  42. package/registry/avatar.json +1 -1
  43. package/registry/badge.json +1 -1
  44. package/registry/button.json +1 -1
  45. package/registry/card-grid.json +1 -1
  46. package/registry/card.json +1 -1
  47. package/registry/catalogue-page.json +1 -1
  48. package/registry/changelog-page.json +1 -1
  49. package/registry/chat.json +917 -0
  50. package/registry/checkbox.json +1 -1
  51. package/registry/chip-link.json +1 -1
  52. package/registry/chip.json +1 -1
  53. package/registry/choice-grid.json +1 -1
  54. package/registry/code-block.json +1 -1
  55. package/registry/combobox.json +1 -1
  56. package/registry/command.json +1 -1
  57. package/registry/component-page.json +1 -1
  58. package/registry/confirm-button.json +1 -1
  59. package/registry/contact-page.json +1 -1
  60. package/registry/continue-prompt.json +1 -1
  61. package/registry/countdown.json +1 -1
  62. package/registry/cta-panel.json +1 -1
  63. package/registry/dashboard-layout.json +1 -1
  64. package/registry/data-table.json +1 -1
  65. package/registry/date-picker.json +1 -1
  66. package/registry/decision-list.json +1 -1
  67. package/registry/description-list.json +1 -1
  68. package/registry/detail-layout.json +1 -1
  69. package/registry/dialog.json +1 -1
  70. package/registry/docs-article-page.json +1 -1
  71. package/registry/docs-hub-page.json +1 -1
  72. package/registry/docs-layout.json +1 -1
  73. package/registry/dropdown-menu.json +1 -1
  74. package/registry/empty-state.json +1 -1
  75. package/registry/error-page.json +1 -1
  76. package/registry/examples/chat/conversation.d.ts +4 -0
  77. package/registry/examples/chat/conversation.js +22 -0
  78. package/registry/examples/chat/conversation.tsx +21 -0
  79. package/registry/examples/chat/inbox.d.ts +4 -0
  80. package/registry/examples/chat/inbox.js +15 -0
  81. package/registry/examples/chat/inbox.tsx +12 -0
  82. package/registry/examples/chat/native/conversation.d.ts +4 -0
  83. package/registry/examples/chat/native/conversation.dark.png +0 -0
  84. package/registry/examples/chat/native/conversation.js +23 -0
  85. package/registry/examples/chat/native/conversation.light.png +0 -0
  86. package/registry/examples/chat/native/conversation.tsx +20 -0
  87. package/registry/examples/chat/native/inbox.d.ts +4 -0
  88. package/registry/examples/chat/native/inbox.dark.png +0 -0
  89. package/registry/examples/chat/native/inbox.js +16 -0
  90. package/registry/examples/chat/native/inbox.light.png +0 -0
  91. package/registry/examples/chat/native/inbox.tsx +13 -0
  92. package/registry/examples/match-dialog/its-a-match.d.ts +4 -0
  93. package/registry/examples/match-dialog/its-a-match.js +29 -0
  94. package/registry/examples/match-dialog/its-a-match.tsx +25 -0
  95. package/registry/examples/match-dialog/native/its-a-match.d.ts +4 -0
  96. package/registry/examples/match-dialog/native/its-a-match.dark.png +0 -0
  97. package/registry/examples/match-dialog/native/its-a-match.js +28 -0
  98. package/registry/examples/match-dialog/native/its-a-match.light.png +0 -0
  99. package/registry/examples/match-dialog/native/its-a-match.tsx +22 -0
  100. package/registry/examples/photo-grid/native/profile-photos.d.ts +4 -0
  101. package/registry/examples/photo-grid/native/profile-photos.dark.png +0 -0
  102. package/registry/examples/photo-grid/native/profile-photos.js +27 -0
  103. package/registry/examples/photo-grid/native/profile-photos.light.png +0 -0
  104. package/registry/examples/photo-grid/native/profile-photos.tsx +24 -0
  105. package/registry/examples/photo-grid/profile-photos.d.ts +4 -0
  106. package/registry/examples/photo-grid/profile-photos.js +28 -0
  107. package/registry/examples/photo-grid/profile-photos.tsx +25 -0
  108. package/registry/examples/screen/native/app-shell.d.ts +4 -0
  109. package/registry/examples/screen/native/app-shell.dark.png +0 -0
  110. package/registry/examples/screen/native/app-shell.js +25 -0
  111. package/registry/examples/screen/native/app-shell.light.png +0 -0
  112. package/registry/examples/screen/native/app-shell.tsx +33 -0
  113. package/registry/examples/screen/native/auth.d.ts +4 -0
  114. package/registry/examples/screen/native/auth.dark.png +0 -0
  115. package/registry/examples/screen/native/auth.js +24 -0
  116. package/registry/examples/screen/native/auth.light.png +0 -0
  117. package/registry/examples/screen/native/auth.tsx +20 -0
  118. package/registry/examples/screen/native/chat.d.ts +4 -0
  119. package/registry/examples/screen/native/chat.dark.png +0 -0
  120. package/registry/examples/screen/native/chat.js +27 -0
  121. package/registry/examples/screen/native/chat.light.png +0 -0
  122. package/registry/examples/screen/native/chat.tsx +22 -0
  123. package/registry/examples/screen/native/feed.d.ts +4 -0
  124. package/registry/examples/screen/native/feed.dark.png +0 -0
  125. package/registry/examples/screen/native/feed.js +24 -0
  126. package/registry/examples/screen/native/feed.light.png +0 -0
  127. package/registry/examples/screen/native/feed.tsx +34 -0
  128. package/registry/examples/screen/native/profile.d.ts +4 -0
  129. package/registry/examples/screen/native/profile.dark.png +0 -0
  130. package/registry/examples/screen/native/profile.js +29 -0
  131. package/registry/examples/screen/native/profile.light.png +0 -0
  132. package/registry/examples/screen/native/profile.tsx +27 -0
  133. package/registry/examples/screen/native/settings.d.ts +4 -0
  134. package/registry/examples/screen/native/settings.dark.png +0 -0
  135. package/registry/examples/screen/native/settings.js +20 -0
  136. package/registry/examples/screen/native/settings.light.png +0 -0
  137. package/registry/examples/screen/native/settings.tsx +19 -0
  138. package/registry/examples/step-progress/native/sign-up.d.ts +4 -0
  139. package/registry/examples/step-progress/native/sign-up.dark.png +0 -0
  140. package/registry/examples/step-progress/native/sign-up.js +12 -0
  141. package/registry/examples/step-progress/native/sign-up.light.png +0 -0
  142. package/registry/examples/step-progress/native/sign-up.tsx +11 -0
  143. package/registry/examples/step-progress/sign-up.d.ts +4 -0
  144. package/registry/examples/step-progress/sign-up.js +22 -0
  145. package/registry/examples/step-progress/sign-up.tsx +16 -0
  146. package/registry/examples/swipe-deck/discover.d.ts +4 -0
  147. package/registry/examples/swipe-deck/discover.js +41 -0
  148. package/registry/examples/swipe-deck/discover.tsx +37 -0
  149. package/registry/examples/swipe-deck/native/discover.d.ts +4 -0
  150. package/registry/examples/swipe-deck/native/discover.dark.png +0 -0
  151. package/registry/examples/swipe-deck/native/discover.js +39 -0
  152. package/registry/examples/swipe-deck/native/discover.light.png +0 -0
  153. package/registry/examples/swipe-deck/native/discover.tsx +35 -0
  154. package/registry/examples/tag-selector/interests.d.ts +4 -0
  155. package/registry/examples/tag-selector/interests.js +14 -0
  156. package/registry/examples/tag-selector/interests.tsx +12 -0
  157. package/registry/examples/tag-selector/native/interests.d.ts +4 -0
  158. package/registry/examples/tag-selector/native/interests.dark.png +0 -0
  159. package/registry/examples/tag-selector/native/interests.js +15 -0
  160. package/registry/examples/tag-selector/native/interests.light.png +0 -0
  161. package/registry/examples/tag-selector/native/interests.tsx +15 -0
  162. package/registry/examples/verified-badge/native/verified.d.ts +4 -0
  163. package/registry/examples/verified-badge/native/verified.dark.png +0 -0
  164. package/registry/examples/verified-badge/native/verified.js +18 -0
  165. package/registry/examples/verified-badge/native/verified.light.png +0 -0
  166. package/registry/examples/verified-badge/native/verified.tsx +15 -0
  167. package/registry/examples/verified-badge/verified.d.ts +4 -0
  168. package/registry/examples/verified-badge/verified.js +17 -0
  169. package/registry/examples/verified-badge/verified.tsx +13 -0
  170. package/registry/field.json +1 -1
  171. package/registry/file-upload.json +1 -1
  172. package/registry/filter-bar.json +1 -1
  173. package/registry/form.json +1 -1
  174. package/registry/gallery-page.json +1 -1
  175. package/registry/glow-card.json +1 -1
  176. package/registry/goal-gauge.json +1 -1
  177. package/registry/how-it-works-page.json +1 -1
  178. package/registry/image-cropper.json +1 -1
  179. package/registry/index.json +144 -2
  180. package/registry/iso.json +1 -1
  181. package/registry/kanban.json +1 -1
  182. package/registry/kbd.json +1 -1
  183. package/registry/landing-page.json +1 -1
  184. package/registry/landscape.json +1 -1
  185. package/registry/legal-page.json +1 -1
  186. package/registry/link-card.json +1 -1
  187. package/registry/list.json +1 -1
  188. package/registry/loader.json +1 -1
  189. package/registry/longform-page.json +1 -1
  190. package/registry/map.json +2 -2
  191. package/registry/marketing-layout.json +1 -1
  192. package/registry/marquee.json +1 -1
  193. package/registry/mascot-quote.json +1 -1
  194. package/registry/mascot-state.json +1 -1
  195. package/registry/mascots.json +1 -1
  196. package/registry/match-dialog.json +300 -0
  197. package/registry/media-capture.json +1 -1
  198. package/registry/meter.json +1 -1
  199. package/registry/nav-bar.json +1 -1
  200. package/registry/number-ticker.json +1 -1
  201. package/registry/page-header.json +1 -1
  202. package/registry/page-hero.json +1 -1
  203. package/registry/page.json +1 -1
  204. package/registry/pagination.json +1 -1
  205. package/registry/photo-grid.json +302 -0
  206. package/registry/pointer-light.json +1 -1
  207. package/registry/popover.json +1 -1
  208. package/registry/pricing-page.json +1 -1
  209. package/registry/product-page.json +1 -1
  210. package/registry/profile-card.json +1 -1
  211. package/registry/progress.json +1 -1
  212. package/registry/promise-card.json +1 -1
  213. package/registry/radio-group.json +1 -1
  214. package/registry/screen.json +184 -0
  215. package/registry/scroll-stage.json +1 -1
  216. package/registry/search-field.json +1 -1
  217. package/registry/section-backdrop.json +1 -1
  218. package/registry/separator.json +1 -1
  219. package/registry/settings-layout.json +1 -1
  220. package/registry/skeleton.json +1 -1
  221. package/registry/slider.json +1 -1
  222. package/registry/slot.json +1 -1
  223. package/registry/spinner.json +1 -1
  224. package/registry/split-view.json +1 -1
  225. package/registry/stage-banner.json +1 -1
  226. package/registry/stat.json +1 -1
  227. package/registry/status-page.json +1 -1
  228. package/registry/step-progress.json +255 -0
  229. package/registry/stepper.json +1 -1
  230. package/registry/swipe-deck.json +512 -0
  231. package/registry/switch.json +1 -1
  232. package/registry/tabs.json +1 -1
  233. package/registry/tag-input.json +1 -1
  234. package/registry/tag-selector.json +276 -0
  235. package/registry/terminal-replay.json +1 -1
  236. package/registry/theme.json +1 -1
  237. package/registry/toast.json +1 -1
  238. package/registry/toc.json +1 -1
  239. package/registry/tooltip.json +1 -1
  240. package/registry/tree-view.json +1 -1
  241. package/registry/verified-badge.json +202 -0
  242. package/registry/video-player.json +1 -1
  243. package/registry/video-trimmer.json +1 -1
  244. package/registry/virtual.json +1 -1
package/dist/native.js CHANGED
@@ -900,27 +900,175 @@ var styles7 = StyleSheet7.create({
900
900
  footer: { flexDirection: "row", alignItems: "center", gap: 8, borderTopWidth: StyleSheet7.hairlineWidth, paddingTop: 12, marginTop: "auto" }
901
901
  });
902
902
 
903
- // src/native/checkbox.tsx
903
+ // src/native/chat.tsx
904
904
  import * as React7 from "react";
905
- import { Pressable as Pressable4, StyleSheet as StyleSheet8, Text as Text4, View as View6 } from "react-native";
905
+ import { Animated as Animated2, Easing, Pressable as Pressable4, StyleSheet as StyleSheet8, TextInput, View as View6 } from "react-native";
906
906
  import Svg3, { Path } from "react-native-svg";
907
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
907
+ import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
908
+ var STATUS = { sending: "Sending", sent: "Sent", delivered: "Delivered", read: "Read", failed: "Not sent" };
909
+ function MessageBubble({ text, mine, time, status, showStatus, context, onRetry, grouped = "single", labels, style }) {
910
+ const { theme, radius: radius3 } = useTheme();
911
+ const words = { ...STATUS, ...labels?.status };
912
+ const failed = status === "failed";
913
+ const big = radius3.xl;
914
+ const tight = 6;
915
+ const corners = mine ? { borderTopRightRadius: grouped === "middle" || grouped === "last" ? tight : big, borderBottomRightRadius: grouped === "first" || grouped === "middle" ? tight : big } : { borderTopLeftRadius: grouped === "middle" || grouped === "last" ? tight : big, borderBottomLeftRadius: grouped === "first" || grouped === "middle" ? tight : big };
916
+ const tone3 = mine ? "onAccent" : "text";
917
+ const bubble = /* @__PURE__ */ jsxs6(
918
+ View6,
919
+ {
920
+ style: [
921
+ styles8.bubble,
922
+ { borderRadius: big, backgroundColor: mine ? theme.accent : theme.surface2, opacity: status === "sending" ? 0.7 : 1 },
923
+ corners,
924
+ failed ? { borderWidth: 2, borderColor: theme.danger } : null
925
+ ],
926
+ children: [
927
+ context ? /* @__PURE__ */ jsx9(Txt, { variant: "caption", tone: mine ? "onAccent" : "secondary", style: styles8.context, children: context }) : null,
928
+ /* @__PURE__ */ jsx9(Txt, { tone: tone3, children: text }),
929
+ time ? /* @__PURE__ */ jsx9(Txt, { variant: "caption", tone: tone3, style: styles8.time, children: time }) : null
930
+ ]
931
+ }
932
+ );
933
+ const name = [text, time, failed ? `${words.failed}. ${labels?.retry ?? ""}` : null].filter(Boolean).join(", ");
934
+ return /* @__PURE__ */ jsxs6(View6, { style: [styles8.row, mine ? styles8.mine : styles8.theirs, style], children: [
935
+ failed && onRetry ? /* @__PURE__ */ jsx9(Pressable4, { role: "button", "aria-label": name, onPress: onRetry, style: styles8.max, children: bubble }) : /* @__PURE__ */ jsx9(View6, { accessible: true, "aria-label": name, style: styles8.max, children: bubble }),
936
+ showStatus && status ? /* @__PURE__ */ jsxs6(View6, { style: styles8.status, children: [
937
+ status === "delivered" || status === "read" || status === "sent" ? /* @__PURE__ */ jsx9(Svg3, { width: 14, height: 14, viewBox: "0 0 24 24", "aria-hidden": true, children: /* @__PURE__ */ jsx9(Path, { d: status === "sent" ? "M5 12.5l4.5 4.5L19 7.5" : "M2 12.5l4.5 4.5L16 7.5M9 15l2 2 9.5-9.5", fill: "none", stroke: status === "read" ? theme.accent : theme.textSecondary, strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round" }) }) : null,
938
+ /* @__PURE__ */ jsx9(Txt, { variant: "caption", tone: failed ? "danger" : "secondary", children: words[status] })
939
+ ] }) : null
940
+ ] });
941
+ }
942
+ function TypingIndicator({ label, showLabel, style }) {
943
+ const { theme, radius: radius3 } = useTheme();
944
+ const reduce = useReducedMotion();
945
+ const [t] = React7.useState(() => new Animated2.Value(0));
946
+ React7.useEffect(() => {
947
+ if (reduce) return;
948
+ const loop = Animated2.loop(Animated2.timing(t, { toValue: 1, duration: 1200, easing: Easing.linear, useNativeDriver: true }));
949
+ loop.start();
950
+ return () => loop.stop();
951
+ }, [reduce, t]);
952
+ return /* @__PURE__ */ jsxs6(View6, { accessible: true, role: "progressbar", "aria-label": label, accessibilityLiveRegion: "polite", style: [styles8.typingRow, style], children: [
953
+ /* @__PURE__ */ jsx9(View6, { style: [styles8.typing, { backgroundColor: theme.surface2, borderRadius: radius3.xl }], children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx9(
954
+ Animated2.View,
955
+ {
956
+ style: [
957
+ styles8.dot,
958
+ { backgroundColor: theme.textSecondary },
959
+ reduce ? null : { opacity: t.interpolate({ inputRange: [0, (i + 1) / 4, (i + 2) / 4, 1], outputRange: [0.35, 1, 0.35, 0.35], extrapolate: "clamp" }) }
960
+ ]
961
+ },
962
+ i
963
+ )) }),
964
+ showLabel ? /* @__PURE__ */ jsx9(Txt, { variant: "caption", tone: "secondary", children: label }) : null
965
+ ] });
966
+ }
967
+ function MessageComposer({ value, onValueChange, onSend, placeholder, sendLabel, leading, disabledReason, maxLength = 4e3, style }) {
968
+ const { theme, radius: radius3, insets, haptic } = useTheme();
969
+ const ready = value.trim().length > 0;
970
+ return /* @__PURE__ */ jsx9(View6, { style: [styles8.composer, { borderTopColor: theme.borderSubtle, backgroundColor: theme.surface0, paddingBottom: 8 + insets.bottom }, style], children: disabledReason ? /* @__PURE__ */ jsx9(Txt, { tone: "secondary", style: styles8.flex, children: disabledReason }) : /* @__PURE__ */ jsxs6(Fragment2, { children: [
971
+ leading,
972
+ /* @__PURE__ */ jsx9(
973
+ TextInput,
974
+ {
975
+ "aria-label": placeholder,
976
+ value,
977
+ onChangeText: onValueChange,
978
+ placeholder,
979
+ placeholderTextColor: theme.textMuted,
980
+ multiline: true,
981
+ maxLength,
982
+ style: [styles8.input, { borderRadius: radius3.xl, borderColor: theme.borderDefault, backgroundColor: theme.surface1, color: theme.textPrimary }]
983
+ }
984
+ ),
985
+ /* @__PURE__ */ jsx9(
986
+ Pressable4,
987
+ {
988
+ role: "button",
989
+ "aria-label": sendLabel,
990
+ "aria-disabled": !ready,
991
+ disabled: !ready,
992
+ onPress: () => {
993
+ haptic("impact");
994
+ onSend();
995
+ },
996
+ style: ({ pressed }) => [styles8.send, { backgroundColor: ready ? pressed ? theme.accentHover : theme.accent : theme.surface3 }],
997
+ children: /* @__PURE__ */ jsx9(Svg3, { width: 18, height: 18, viewBox: "0 0 24 24", "aria-hidden": true, children: /* @__PURE__ */ jsx9(Path, { d: "M4 12l16-8-6 16-2.5-6.5L4 12z", fill: ready ? theme.onAccent : theme.textMuted }) })
998
+ }
999
+ )
1000
+ ] }) });
1001
+ }
1002
+ function ConversationItem({ name, avatar, presence, presenceLabel, preview, typing, time, unread = 0, unreadLabel, onPress, style }) {
1003
+ const { theme, radius: radius3 } = useTheme();
1004
+ const said = [unread > 0 ? unreadLabel : null, presence ? presenceLabel : null].filter(Boolean).join(", ");
1005
+ return /* @__PURE__ */ jsxs6(
1006
+ Pressable4,
1007
+ {
1008
+ role: "button",
1009
+ onPress,
1010
+ style: ({ pressed }) => [styles8.item, { backgroundColor: pressed ? theme.surface2 : theme.surface0 }, style],
1011
+ children: [
1012
+ /* @__PURE__ */ jsx9(View6, { "aria-hidden": true, children: /* @__PURE__ */ jsx9(Avatar, { src: avatar, alt: name, size: "lg", presence, presenceLabel }) }),
1013
+ /* @__PURE__ */ jsxs6(View6, { style: styles8.flex, children: [
1014
+ /* @__PURE__ */ jsxs6(View6, { style: styles8.top, children: [
1015
+ /* @__PURE__ */ jsx9(Txt, { variant: "label", numberOfLines: 1, style: [styles8.flex, unread > 0 ? styles8.bold : null], children: name }),
1016
+ time ? /* @__PURE__ */ jsx9(Txt, { variant: "caption", tone: unread > 0 ? "accent" : "secondary", children: time }) : null
1017
+ ] }),
1018
+ /* @__PURE__ */ jsxs6(View6, { style: styles8.top, children: [
1019
+ /* @__PURE__ */ jsx9(Txt, { variant: "caption", tone: typing ? "accent" : unread > 0 ? "text" : "secondary", numberOfLines: 1, style: styles8.flex, children: preview }),
1020
+ unread > 0 ? /* @__PURE__ */ jsx9(View6, { "aria-hidden": unreadLabel ? true : void 0, style: [styles8.count, { backgroundColor: theme.accent, borderRadius: radius3.full }], children: /* @__PURE__ */ jsx9(Txt, { variant: "caption", tone: "onAccent", style: styles8.bold, children: unread > 99 ? "99+" : unread }) }) : null
1021
+ ] })
1022
+ ] }),
1023
+ said ? /* @__PURE__ */ jsx9(Txt, { style: styles8.readOnly, children: said }) : null
1024
+ ]
1025
+ }
1026
+ );
1027
+ }
1028
+ var styles8 = StyleSheet8.create({
1029
+ readOnly: { position: "absolute", width: 1, height: 1, overflow: "hidden", opacity: 0 },
1030
+ row: { gap: 2 },
1031
+ mine: { alignItems: "flex-end" },
1032
+ theirs: { alignItems: "flex-start" },
1033
+ max: { maxWidth: "80%" },
1034
+ bubble: { paddingHorizontal: 12, paddingVertical: 8, gap: 2 },
1035
+ context: { opacity: 0.85 },
1036
+ time: { alignSelf: "flex-end", fontSize: 11 },
1037
+ status: { flexDirection: "row", alignItems: "center", gap: 4 },
1038
+ typingRow: { flexDirection: "row", alignItems: "center", gap: 8, alignSelf: "flex-start" },
1039
+ typing: { flexDirection: "row", gap: 4, paddingHorizontal: 14, paddingVertical: 12 },
1040
+ dot: { width: 7, height: 7, borderRadius: 4 },
1041
+ composer: { flexDirection: "row", alignItems: "flex-end", gap: 8, paddingHorizontal: 12, paddingTop: 8, borderTopWidth: StyleSheet8.hairlineWidth },
1042
+ input: { flex: 1, maxHeight: 120, minHeight: 40, borderWidth: 1, paddingHorizontal: 14, paddingTop: 10, paddingBottom: 10, fontSize: 16 },
1043
+ send: { width: 40, height: 40, borderRadius: 20, alignItems: "center", justifyContent: "center" },
1044
+ flex: { flex: 1 },
1045
+ item: { flexDirection: "row", alignItems: "center", gap: 12, paddingHorizontal: 16, paddingVertical: 10 },
1046
+ top: { flexDirection: "row", alignItems: "center", gap: 8 },
1047
+ bold: { fontWeight: "800" },
1048
+ count: { minWidth: 20, height: 20, paddingHorizontal: 6, alignItems: "center", justifyContent: "center" }
1049
+ });
1050
+
1051
+ // src/native/checkbox.tsx
1052
+ import * as React8 from "react";
1053
+ import { Pressable as Pressable5, StyleSheet as StyleSheet9, Text as Text4, View as View7 } from "react-native";
1054
+ import Svg4, { Path as Path2 } from "react-native-svg";
1055
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
908
1056
  function Checkbox({ children, label, checked, defaultChecked = false, onCheckedChange, error, disabled, style }) {
909
1057
  const { theme, radius: radius3 } = useTheme();
910
- const [own, setOwn] = React7.useState(defaultChecked);
1058
+ const [own, setOwn] = React8.useState(defaultChecked);
911
1059
  const on = checked ?? own;
912
1060
  const toggle = () => {
913
1061
  if (checked === void 0) setOwn(!on);
914
1062
  onCheckedChange?.(!on);
915
1063
  };
916
- const box = /* @__PURE__ */ jsx9(
917
- View6,
1064
+ const box = /* @__PURE__ */ jsx10(
1065
+ View7,
918
1066
  {
919
1067
  style: [
920
- styles8.box,
1068
+ styles9.box,
921
1069
  { borderRadius: radius3.xs + 2, borderColor: error ? theme.danger : on ? theme.accent : theme.borderStrong, backgroundColor: on ? theme.accent : theme.surface1 }
922
1070
  ],
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
1071
+ children: on ? /* @__PURE__ */ jsx10(Svg4, { 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__ */ jsx10(Path2, { d: "M20 6 9 17l-5-5" }) }) : null
924
1072
  }
925
1073
  );
926
1074
  const plain = children === void 0 || typeof children === "string";
@@ -933,21 +1081,21 @@ function Checkbox({ children, label, checked, defaultChecked = false, onCheckedC
933
1081
  disabled,
934
1082
  onPress: toggle
935
1083
  };
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: [
1084
+ return /* @__PURE__ */ jsxs7(View7, { style: [styles9.root, style], children: [
1085
+ plain ? /* @__PURE__ */ jsxs7(Pressable5, { ...a11y, hitSlop: 4, style: [styles9.row, disabled ? styles9.disabled : null], children: [
938
1086
  box,
939
- children !== void 0 ? /* @__PURE__ */ jsx9(View6, { style: styles8.text, children: /* @__PURE__ */ jsx9(Text4, { style: [styles8.label, { color: theme.textPrimary }], children }) }) : null
1087
+ children !== void 0 ? /* @__PURE__ */ jsx10(View7, { style: styles9.text, children: /* @__PURE__ */ jsx10(Text4, { style: [styles9.label, { color: theme.textPrimary }], children }) }) : null
940
1088
  ] }) : (
941
1089
  // Words with links: the box alone is the control (a 44-pt target, named by `label`), the links stay links.
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 })
1090
+ /* @__PURE__ */ jsxs7(View7, { style: [styles9.row, disabled ? styles9.disabled : null], children: [
1091
+ /* @__PURE__ */ jsx10(Pressable5, { ...a11y, hitSlop: 11, style: styles9.target, children: box }),
1092
+ /* @__PURE__ */ jsx10(View7, { style: styles9.text, children })
945
1093
  ] })
946
1094
  ),
947
- error ? /* @__PURE__ */ jsx9(Text4, { role: "alert", "aria-live": "polite", style: [styles8.error, { color: theme.dangerText }], children: error }) : null
1095
+ error ? /* @__PURE__ */ jsx10(Text4, { role: "alert", "aria-live": "polite", style: [styles9.error, { color: theme.dangerText }], children: error }) : null
948
1096
  ] });
949
1097
  }
950
- var styles8 = StyleSheet8.create({
1098
+ var styles9 = StyleSheet9.create({
951
1099
  root: { gap: 2, alignSelf: "stretch" },
952
1100
  row: { flexDirection: "row", alignItems: "center", gap: 12, minHeight: 44 },
953
1101
  target: { minHeight: 44, justifyContent: "center" },
@@ -959,18 +1107,18 @@ var styles8 = StyleSheet8.create({
959
1107
  });
960
1108
 
961
1109
  // src/native/chip.tsx
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);
1110
+ import * as React9 from "react";
1111
+ import { Pressable as Pressable6, ScrollView, StyleSheet as StyleSheet10, Text as Text5, View as View8 } from "react-native";
1112
+ import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
1113
+ var ChipGroupContext = React9.createContext(null);
966
1114
  function Label({ children, color, size }) {
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 });
1115
+ if (typeof children !== "string" && typeof children !== "number") return /* @__PURE__ */ jsx11(Fragment3, { children });
1116
+ return /* @__PURE__ */ jsx11(Text5, { style: [styles10.label, { color, fontSize: size === "sm" ? 12 : 13 }], children });
969
1117
  }
970
1118
  function ChipBase(props) {
971
- const group = React8.useContext(ChipGroupContext);
1119
+ const group = React9.useContext(ChipGroupContext);
972
1120
  const { theme, radius: radius3 } = useTheme();
973
- const [own, setOwn] = React8.useState(props.removable ? false : props.defaultSelected ?? false);
1121
+ const [own, setOwn] = React9.useState(props.removable ? false : props.defaultSelected ?? false);
974
1122
  const size = props.size ?? group?.size ?? "md";
975
1123
  const frame = (on2, pressed) => ({
976
1124
  height: size === "sm" ? 28 : 36,
@@ -981,9 +1129,9 @@ function ChipBase(props) {
981
1129
  });
982
1130
  if (props.removable) {
983
1131
  const { removable: _r2, removeLabel, onRemove, disabled: disabled2, size: _s2, style: style2, children: children2, ...rest2 } = props;
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" }) })
1132
+ return /* @__PURE__ */ jsxs8(View8, { ...rest2, style: [styles10.base, frame(false, false), disabled2 ? styles10.disabled : null, style2], children: [
1133
+ /* @__PURE__ */ jsx11(Label, { color: theme.textSecondary, size, children: children2 }),
1134
+ /* @__PURE__ */ jsx11(Pressable6, { role: "button", "aria-label": removeLabel, disabled: disabled2 ?? void 0, hitSlop: 10, onPress: onRemove, style: styles10.remove, children: /* @__PURE__ */ jsx11(Text5, { style: [styles10.cross, { color: theme.textSecondary }], children: "\xD7" }) })
987
1135
  ] });
988
1136
  }
989
1137
  const { removable: _r, value, selected, defaultSelected: _d, onSelectedChange, disabled: ownDisabled, size: _s, style, children, ...rest } = props;
@@ -996,8 +1144,8 @@ function ChipBase(props) {
996
1144
  onSelectedChange?.(!on);
997
1145
  };
998
1146
  const single = group?.type === "single";
999
- return /* @__PURE__ */ jsx10(
1000
- Pressable5,
1147
+ return /* @__PURE__ */ jsx11(
1148
+ Pressable6,
1001
1149
  {
1002
1150
  role: single ? "radio" : "checkbox",
1003
1151
  "aria-checked": on,
@@ -1005,17 +1153,17 @@ function ChipBase(props) {
1005
1153
  ...rest,
1006
1154
  disabled,
1007
1155
  onPress: press,
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 })
1156
+ style: ({ pressed }) => [styles10.base, frame(on, pressed), disabled ? styles10.disabled : null, style],
1157
+ children: /* @__PURE__ */ jsx11(Label, { color: on ? theme.textPrimary : theme.textSecondary, size, children })
1010
1158
  }
1011
1159
  );
1012
1160
  }
1013
1161
  function ChipGroup(props) {
1014
1162
  const { size, disabled, scrollable, "aria-label": label, style, children } = props;
1015
1163
  const initial = props.type === "single" ? props.defaultValue ?? "" : props.defaultValue ?? [];
1016
- const [own, setOwn] = React8.useState(initial);
1164
+ const [own, setOwn] = React9.useState(initial);
1017
1165
  const current = props.value ?? own;
1018
- const context = React8.useMemo(() => {
1166
+ const context = React9.useMemo(() => {
1019
1167
  const list = Array.isArray(current) ? current : [current];
1020
1168
  return {
1021
1169
  type: props.type,
@@ -1030,10 +1178,10 @@ function ChipGroup(props) {
1030
1178
  };
1031
1179
  }, [current, props.type, props.value, props.onValueChange, size, disabled]);
1032
1180
  const a11y = { role: props.type === "single" ? "radiogroup" : "group", "aria-label": label };
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 }) });
1181
+ return /* @__PURE__ */ jsx11(ChipGroupContext.Provider, { value: context, children: scrollable ? /* @__PURE__ */ jsx11(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, ...a11y, style, contentContainerStyle: styles10.row, children }) : /* @__PURE__ */ jsx11(View8, { ...a11y, style: [styles10.row, styles10.wrap, style], children }) });
1034
1182
  }
1035
1183
  var Chip = Object.assign(ChipBase, { Group: ChipGroup });
1036
- var styles9 = StyleSheet9.create({
1184
+ var styles10 = StyleSheet10.create({
1037
1185
  base: { flexDirection: "row", alignItems: "center", justifyContent: "center", gap: 6, paddingHorizontal: 14, borderWidth: 1, alignSelf: "flex-start" },
1038
1186
  label: { fontWeight: "600" },
1039
1187
  remove: { marginRight: -6, width: 24, height: 24, alignItems: "center", justifyContent: "center" },
@@ -1044,30 +1192,30 @@ var styles9 = StyleSheet9.create({
1044
1192
  });
1045
1193
 
1046
1194
  // src/native/combobox.tsx
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";
1195
+ import * as React11 from "react";
1196
+ import { Pressable as Pressable8, ScrollView as ScrollView2, StyleSheet as StyleSheet12, Text as Text7, TextInput as TextInput2, View as View10 } from "react-native";
1197
+ import Svg5, { Path as Path3 } from "react-native-svg";
1050
1198
 
1051
1199
  // src/native/dialog.tsx
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";
1200
+ import * as React10 from "react";
1201
+ import { Animated as Animated3, Modal as Modal2, Pressable as Pressable7, StyleSheet as StyleSheet11, Text as Text6, View as View9 } from "react-native";
1202
+ import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
1055
1203
  function Sheet({ open, onOpenChange, title, closeLabel = "Close", children, style }) {
1056
1204
  const { theme, radius: radius3, motion: motion3 } = useTheme();
1057
- const [rise] = React9.useState(() => new Animated2.Value(0));
1058
- React9.useEffect(() => {
1059
- if (open) Animated2.timing(rise, { toValue: 1, duration: motion3.duration.base * 1.6, useNativeDriver: true }).start();
1205
+ const [rise] = React10.useState(() => new Animated3.Value(0));
1206
+ React10.useEffect(() => {
1207
+ if (open) Animated3.timing(rise, { toValue: 1, duration: motion3.duration.base * 1.6, useNativeDriver: true }).start();
1060
1208
  else rise.setValue(0);
1061
1209
  }, [open, rise, motion3.duration.base]);
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(
1065
- Animated2.View,
1210
+ return /* @__PURE__ */ jsx12(Modal2, { transparent: true, visible: open, animationType: "none", onRequestClose: () => onOpenChange(false), statusBarTranslucent: true, children: /* @__PURE__ */ jsxs9(View9, { style: styles11.backdrop, children: [
1211
+ /* @__PURE__ */ jsx12(Animated3.View, { style: [StyleSheet11.absoluteFill, { opacity: rise }], children: /* @__PURE__ */ jsx12(Pressable7, { role: "button", "aria-label": closeLabel, onPress: () => onOpenChange(false), style: [StyleSheet11.absoluteFill, { backgroundColor: theme.scrim }] }) }),
1212
+ /* @__PURE__ */ jsxs9(
1213
+ Animated3.View,
1066
1214
  {
1067
1215
  role: "dialog",
1068
1216
  "aria-label": title,
1069
1217
  style: [
1070
- styles10.sheet,
1218
+ styles11.sheet,
1071
1219
  {
1072
1220
  backgroundColor: theme.surface1,
1073
1221
  borderColor: theme.borderDefault,
@@ -1080,37 +1228,37 @@ function Sheet({ open, onOpenChange, title, closeLabel = "Close", children, styl
1080
1228
  style
1081
1229
  ],
1082
1230
  children: [
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,
1231
+ /* @__PURE__ */ jsx12(View9, { "aria-hidden": true, style: [styles11.grip, { backgroundColor: theme.borderStrong }] }),
1232
+ title ? /* @__PURE__ */ jsx12(Text6, { role: "heading", style: [styles11.title, { color: theme.textPrimary }], children: title }) : null,
1085
1233
  children
1086
1234
  ]
1087
1235
  }
1088
1236
  )
1089
1237
  ] }) });
1090
1238
  }
1091
- var styles10 = StyleSheet10.create({
1239
+ var styles11 = StyleSheet11.create({
1092
1240
  backdrop: { flex: 1, justifyContent: "flex-end" },
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 },
1241
+ sheet: { maxHeight: "85%", paddingHorizontal: 16, paddingTop: 8, paddingBottom: 28, gap: 12, borderWidth: StyleSheet11.hairlineWidth, shadowOpacity: 0.3, shadowRadius: 16, shadowOffset: { width: 0, height: -4 }, elevation: 12 },
1094
1242
  grip: { alignSelf: "center", width: 40, height: 5, borderRadius: 3, marginBottom: 4 },
1095
1243
  title: { fontSize: 17, fontWeight: "700" }
1096
1244
  });
1097
1245
 
1098
1246
  // src/native/combobox.tsx
1099
- import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
1247
+ import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
1100
1248
  function Chevron({ color }) {
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" }) });
1249
+ return /* @__PURE__ */ jsx13(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__ */ jsx13(Path3, { d: "m6 9 6 6 6-6" }) });
1102
1250
  }
1103
1251
  function Tick({ color }) {
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" }) });
1252
+ return /* @__PURE__ */ jsx13(Svg5, { 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__ */ jsx13(Path3, { d: "M20 6 9 17l-5-5" }) });
1105
1253
  }
1106
1254
  function Trigger({ shared, text, onPress, open }) {
1107
1255
  const { theme, radius: radius3 } = useTheme();
1108
1256
  const { label, placeholder, hint, error, disabled } = shared;
1109
1257
  const caption = error ?? hint;
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,
1258
+ return /* @__PURE__ */ jsxs10(View10, { style: [styles12.field, shared.style], children: [
1259
+ /* @__PURE__ */ jsx13(Text7, { style: [styles12.label, { color: theme.textSecondary }], children: label }),
1260
+ /* @__PURE__ */ jsxs10(
1261
+ Pressable8,
1114
1262
  {
1115
1263
  role: "button",
1116
1264
  "aria-label": `${label}, ${text ?? placeholder ?? ""}`.replace(/, $/, ""),
@@ -1120,22 +1268,22 @@ function Trigger({ shared, text, onPress, open }) {
1120
1268
  accessibilityHint: caption,
1121
1269
  disabled,
1122
1270
  onPress,
1123
- style: [styles11.trigger, { borderRadius: radius3.md, backgroundColor: theme.surface2, borderColor: error ? theme.danger : open ? theme.accent : theme.borderDefault }, disabled ? styles11.disabled : null],
1271
+ style: [styles12.trigger, { borderRadius: radius3.md, backgroundColor: theme.surface2, borderColor: error ? theme.danger : open ? theme.accent : theme.borderDefault }, disabled ? styles12.disabled : null],
1124
1272
  children: [
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 })
1273
+ /* @__PURE__ */ jsx13(Text7, { numberOfLines: 1, style: [styles12.triggerText, { color: text ? theme.textPrimary : theme.textSecondary }], children: text ?? placeholder ?? "" }),
1274
+ /* @__PURE__ */ jsx13(Chevron, { color: theme.textSecondary })
1127
1275
  ]
1128
1276
  }
1129
1277
  ),
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
1278
+ caption ? /* @__PURE__ */ jsx13(Text7, { role: error ? "alert" : void 0, "aria-live": error ? "polite" : void 0, style: [styles12.caption, { color: error ? theme.dangerText : theme.textSecondary }], children: caption }) : null
1131
1279
  ] });
1132
1280
  }
1133
1281
  function Options({ options, isChosen, onPick, multiple }) {
1134
1282
  const { theme, radius: radius3, haptic } = useTheme();
1135
- return /* @__PURE__ */ jsx12(ScrollView2, { role: multiple ? "list" : "radiogroup", keyboardShouldPersistTaps: "handled", style: styles11.options, children: options.map((o) => {
1283
+ return /* @__PURE__ */ jsx13(ScrollView2, { role: multiple ? "list" : "radiogroup", keyboardShouldPersistTaps: "handled", style: styles12.options, children: options.map((o) => {
1136
1284
  const chosen = isChosen(o.value);
1137
- return /* @__PURE__ */ jsxs9(
1138
- Pressable7,
1285
+ return /* @__PURE__ */ jsxs10(
1286
+ Pressable8,
1139
1287
  {
1140
1288
  role: multiple ? "checkbox" : "radio",
1141
1289
  "aria-checked": chosen,
@@ -1146,13 +1294,13 @@ function Options({ options, isChosen, onPick, multiple }) {
1146
1294
  haptic("selection");
1147
1295
  onPick(o);
1148
1296
  },
1149
- style: ({ pressed }) => [styles11.option, { borderRadius: radius3.md, backgroundColor: chosen ? theme.accentSoft : pressed ? theme.surface3 : "transparent" }, o.disabled ? styles11.disabled : null],
1297
+ style: ({ pressed }) => [styles12.option, { borderRadius: radius3.md, backgroundColor: chosen ? theme.accentSoft : pressed ? theme.surface3 : "transparent" }, o.disabled ? styles12.disabled : null],
1150
1298
  children: [
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
1299
+ /* @__PURE__ */ jsxs10(View10, { style: styles12.optionText, children: [
1300
+ /* @__PURE__ */ jsx13(Text7, { style: [styles12.optionLabel, { color: theme.textPrimary, fontWeight: chosen ? "700" : "500" }], children: o.label }),
1301
+ o.description ? /* @__PURE__ */ jsx13(Text7, { style: [styles12.caption, { color: theme.textSecondary }], children: o.description }) : null
1154
1302
  ] }),
1155
- chosen ? /* @__PURE__ */ jsx12(Tick, { color: theme.accentText }) : null
1303
+ chosen ? /* @__PURE__ */ jsx13(Tick, { color: theme.accentText }) : null
1156
1304
  ]
1157
1305
  },
1158
1306
  o.value
@@ -1160,16 +1308,16 @@ function Options({ options, isChosen, onPick, multiple }) {
1160
1308
  }) });
1161
1309
  }
1162
1310
  function Select({ options, value: valueProp, defaultValue = null, onValueChange, sheetTitle, ...shared }) {
1163
- const [own, setOwn] = React10.useState(defaultValue);
1311
+ const [own, setOwn] = React11.useState(defaultValue);
1164
1312
  const value = valueProp !== void 0 ? valueProp : own;
1165
- const [open, setOpen] = React10.useState(false);
1313
+ const [open, setOpen] = React11.useState(false);
1166
1314
  const close = () => {
1167
1315
  setOpen(false);
1168
1316
  shared.onBlur?.();
1169
1317
  };
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(
1318
+ return /* @__PURE__ */ jsxs10(Fragment4, { children: [
1319
+ /* @__PURE__ */ jsx13(Trigger, { shared, text: options.find((o) => o.value === value)?.label ?? null, open, onPress: () => setOpen(true) }),
1320
+ /* @__PURE__ */ jsx13(Sheet, { open, onOpenChange: (o) => o ? setOpen(true) : close(), title: sheetTitle ?? shared.label, children: /* @__PURE__ */ jsx13(
1173
1321
  Options,
1174
1322
  {
1175
1323
  options,
@@ -1187,13 +1335,13 @@ var comboboxLabels = { search: "Search", loading: "Searching\u2026", empty: "No
1187
1335
  function Combobox({ options = [], onSearch, multiple, value, onValueChange, labels: given, ...shared }) {
1188
1336
  const labels = { ...comboboxLabels, ...given };
1189
1337
  const { theme, radius: radius3 } = useTheme();
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({});
1338
+ const [open, setOpen] = React11.useState(false);
1339
+ const [query, setQuery] = React11.useState("");
1340
+ const [found, setFound] = React11.useState(null);
1341
+ const [loading, setLoading] = React11.useState(false);
1342
+ const [seen, setSeen] = React11.useState({});
1195
1343
  const chosen = value == null ? [] : typeof value === "string" ? value ? [value] : [] : [...value];
1196
- React10.useEffect(() => {
1344
+ React11.useEffect(() => {
1197
1345
  if (!onSearch || !open) return;
1198
1346
  const controller = new AbortController();
1199
1347
  const timer2 = setTimeout(() => {
@@ -1217,11 +1365,11 @@ function Combobox({ options = [], onSearch, multiple, value, onValueChange, labe
1217
1365
  setQuery("");
1218
1366
  shared.onBlur?.();
1219
1367
  };
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(
1224
- TextInput,
1368
+ return /* @__PURE__ */ jsxs10(Fragment4, { children: [
1369
+ /* @__PURE__ */ jsx13(Trigger, { shared, text: chosen.length ? chosen.map(labelOf).join(", ") : null, open, onPress: () => setOpen(true) }),
1370
+ /* @__PURE__ */ jsxs10(Sheet, { open, onOpenChange: (o) => o ? setOpen(true) : close(), title: shared.label, children: [
1371
+ /* @__PURE__ */ jsx13(
1372
+ TextInput2,
1225
1373
  {
1226
1374
  "aria-label": labels.search,
1227
1375
  placeholder: labels.search,
@@ -1231,12 +1379,12 @@ function Combobox({ options = [], onSearch, multiple, value, onValueChange, labe
1231
1379
  autoFocus: true,
1232
1380
  autoCorrect: false,
1233
1381
  returnKeyType: "search",
1234
- style: [styles11.search, { borderRadius: radius3.md, backgroundColor: theme.surface2, borderColor: theme.borderDefault, color: theme.textPrimary }]
1382
+ style: [styles12.search, { borderRadius: radius3.md, backgroundColor: theme.surface2, borderColor: theme.borderDefault, color: theme.textPrimary }]
1235
1383
  }
1236
1384
  ),
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(
1385
+ loading ? /* @__PURE__ */ jsx13(Text7, { style: [styles12.caption, { color: theme.textSecondary }], children: labels.loading }) : null,
1386
+ !loading && list.length === 0 ? /* @__PURE__ */ jsx13(Text7, { style: [styles12.caption, { color: theme.textSecondary }], children: labels.empty }) : null,
1387
+ /* @__PURE__ */ jsx13(
1240
1388
  Options,
1241
1389
  {
1242
1390
  options: list,
@@ -1252,11 +1400,11 @@ function Combobox({ options = [], onSearch, multiple, value, onValueChange, labe
1252
1400
  }
1253
1401
  }
1254
1402
  ),
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
1403
+ multiple ? /* @__PURE__ */ jsx13(Pressable8, { role: "button", onPress: close, style: [styles12.done, { borderRadius: radius3.md, backgroundColor: theme.accent }], children: /* @__PURE__ */ jsx13(Text7, { style: [styles12.doneText, { color: theme.onAccent }], children: labels.done }) }) : null
1256
1404
  ] })
1257
1405
  ] });
1258
1406
  }
1259
- var styles11 = StyleSheet11.create({
1407
+ var styles12 = StyleSheet12.create({
1260
1408
  field: { gap: 6, alignSelf: "stretch" },
1261
1409
  label: { fontSize: 12, lineHeight: 16, fontWeight: "600" },
1262
1410
  trigger: { minHeight: 48, flexDirection: "row", alignItems: "center", gap: 8, paddingHorizontal: 14, borderWidth: 1 },
@@ -1273,9 +1421,9 @@ var styles11 = StyleSheet11.create({
1273
1421
  });
1274
1422
 
1275
1423
  // src/native/countdown.tsx
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";
1424
+ import * as React12 from "react";
1425
+ import { Animated as Animated4, StyleSheet as StyleSheet13, Text as Text8 } from "react-native";
1426
+ import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
1279
1427
  var FONT = { sm: 14, md: 20, lg: 32 };
1280
1428
  function Countdown({ target, skewMs = 0, units, urgentBelowMs = 6e4, size = "md", label, showLabel = false, style }) {
1281
1429
  const { theme, fonts } = useTheme();
@@ -1283,13 +1431,13 @@ function Countdown({ target, skewMs = 0, units, urgentBelowMs = 6e4, size = "md"
1283
1431
  const ms = useCountdown(target, skewMs);
1284
1432
  const urgent = ms > 0 && ms < urgentBelowMs;
1285
1433
  const parts = countdownParts(ms, units);
1286
- const [opacity] = React11.useState(() => new Animated3.Value(1));
1287
- React11.useEffect(() => {
1434
+ const [opacity] = React12.useState(() => new Animated4.Value(1));
1435
+ React12.useEffect(() => {
1288
1436
  if (!urgent || reduce) return;
1289
- const loop = Animated3.loop(
1290
- Animated3.sequence([
1291
- Animated3.timing(opacity, { toValue: 0.4, duration: 500, useNativeDriver: true }),
1292
- Animated3.timing(opacity, { toValue: 1, duration: 500, useNativeDriver: true })
1437
+ const loop = Animated4.loop(
1438
+ Animated4.sequence([
1439
+ Animated4.timing(opacity, { toValue: 0.4, duration: 500, useNativeDriver: true }),
1440
+ Animated4.timing(opacity, { toValue: 1, duration: 500, useNativeDriver: true })
1293
1441
  ])
1294
1442
  );
1295
1443
  loop.start();
@@ -1300,24 +1448,24 @@ function Countdown({ target, skewMs = 0, units, urgentBelowMs = 6e4, size = "md"
1300
1448
  }, [urgent, reduce, opacity]);
1301
1449
  const color = urgent ? theme.dangerText : theme.textPrimary;
1302
1450
  const text = parts.map(([value, unit]) => `${String(value).padStart(2, "0")}${unit}`).join(" ");
1303
- return /* @__PURE__ */ jsxs10(
1304
- Animated3.View,
1451
+ return /* @__PURE__ */ jsxs11(
1452
+ Animated4.View,
1305
1453
  {
1306
1454
  accessible: true,
1307
1455
  role: "timer",
1308
1456
  "aria-label": `${label} ${text}`,
1309
- style: [styles12.root, style],
1457
+ style: [styles13.root, style],
1310
1458
  children: [
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 })
1459
+ showLabel ? /* @__PURE__ */ jsx14(Text8, { style: [styles13.label, { color: theme.textSecondary, fontSize: Math.max(11, Math.round(FONT[size] * 0.6)) }], children: label }) : null,
1460
+ parts.map(([value, unit], i) => /* @__PURE__ */ jsxs11(Animated4.View, { style: [styles13.segment, urgent && i === parts.length - 1 ? { opacity } : null], children: [
1461
+ /* @__PURE__ */ jsx14(Text8, { style: [styles13.value, { color, fontSize: FONT[size] }, fonts.display ? { fontFamily: fonts.display } : null], children: String(value).padStart(2, "0") }),
1462
+ /* @__PURE__ */ jsx14(Text8, { style: [styles13.unit, { color: theme.textSecondary, fontSize: Math.round(FONT[size] / 2) }], children: unit })
1315
1463
  ] }, unit))
1316
1464
  ]
1317
1465
  }
1318
1466
  );
1319
1467
  }
1320
- var styles12 = StyleSheet12.create({
1468
+ var styles13 = StyleSheet13.create({
1321
1469
  root: { flexDirection: "row", alignItems: "baseline", gap: 6 },
1322
1470
  segment: { flexDirection: "row", alignItems: "baseline" },
1323
1471
  value: { fontWeight: "900", fontVariant: ["tabular-nums"], letterSpacing: -0.3 },
@@ -1326,18 +1474,18 @@ var styles12 = StyleSheet12.create({
1326
1474
  });
1327
1475
 
1328
1476
  // src/native/date-picker.tsx
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";
1477
+ import * as React13 from "react";
1478
+ import { Platform, StyleSheet as StyleSheet14, Text as Text9, TextInput as TextInput3, View as View11 } from "react-native";
1479
+ import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
1332
1480
  var LENGTH = DATE_PART_LENGTH;
1333
1481
  var dateFieldLabels = { day: "Day", month: "Month", year: "Year" };
1334
1482
  function DateField({ label, hint, error, value, defaultValue, onValueChange, onBlur, locale = "en-US", labels: given, autoComplete, disabled, inputRef, onSubmitEditing, returnKeyType = "done", style }) {
1335
1483
  const { theme, radius: radius3 } = useTheme();
1336
1484
  const labels = { ...dateFieldLabels, ...given };
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) };
1485
+ const order = React13.useMemo(() => datePartsOrder(locale), [locale]);
1486
+ const [parts, setParts] = React13.useState(() => splitDate(value ?? defaultValue));
1487
+ const [focused, setFocused] = React13.useState(null);
1488
+ const refs = { day: React13.useRef(null), month: React13.useRef(null), year: React13.useRef(null) };
1341
1489
  if (value !== void 0 && value !== composeDate(parts) && composeDate(splitDate(value)) === value) setParts(splitDate(value));
1342
1490
  const caption = error ?? hint;
1343
1491
  const change = (part, text) => {
@@ -1348,12 +1496,12 @@ function DateField({ label, hint, error, value, defaultValue, onValueChange, onB
1348
1496
  const following = order[order.indexOf(part) + 1];
1349
1497
  if (digits.length === LENGTH[part] && following) refs[following].current?.focus();
1350
1498
  };
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(
1356
- TextInput2,
1499
+ return /* @__PURE__ */ jsxs12(View11, { role: "group", "aria-label": label, style: [styles14.root, disabled ? styles14.disabled : null, style], children: [
1500
+ /* @__PURE__ */ jsx15(Text9, { style: [styles14.label, { color: theme.textSecondary }], children: label }),
1501
+ /* @__PURE__ */ jsx15(View11, { style: styles14.row, children: order.map((part, i) => /* @__PURE__ */ jsxs12(View11, { style: part === "year" ? styles14.yearBox : styles14.box, children: [
1502
+ /* @__PURE__ */ jsx15(Text9, { style: [styles14.part, { color: theme.textSecondary }], children: labels[part] }),
1503
+ /* @__PURE__ */ jsx15(
1504
+ TextInput3,
1357
1505
  {
1358
1506
  ref: (node) => {
1359
1507
  refs[part].current = node;
@@ -1384,16 +1532,16 @@ function DateField({ label, hint, error, value, defaultValue, onValueChange, onB
1384
1532
  if (i === order.length - 1) onBlur?.();
1385
1533
  },
1386
1534
  style: [
1387
- styles13.input,
1535
+ styles14.input,
1388
1536
  { color: theme.textPrimary, backgroundColor: theme.surface2, borderRadius: radius3.md, borderColor: error ? theme.danger : focused === part ? theme.accent : theme.borderDefault }
1389
1537
  ]
1390
1538
  }
1391
1539
  )
1392
1540
  ] }, part)) }),
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
1541
+ caption ? /* @__PURE__ */ jsx15(Text9, { role: error ? "alert" : void 0, "aria-live": error ? "polite" : void 0, style: [styles14.caption, { color: error ? theme.dangerText : theme.textSecondary }], children: caption }) : null
1394
1542
  ] });
1395
1543
  }
1396
- var styles13 = StyleSheet13.create({
1544
+ var styles14 = StyleSheet14.create({
1397
1545
  root: { gap: 6, alignSelf: "stretch" },
1398
1546
  label: { fontSize: 12, lineHeight: 16, fontWeight: "600" },
1399
1547
  row: { flexDirection: "row", gap: 10 },
@@ -1406,26 +1554,26 @@ var styles13 = StyleSheet13.create({
1406
1554
  });
1407
1555
 
1408
1556
  // src/native/date-time.tsx
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";
1557
+ import * as React15 from "react";
1558
+ import { Pressable as Pressable10, ScrollView as ScrollView4, StyleSheet as StyleSheet16, Text as Text11, View as View13 } from "react-native";
1559
+ import Svg6, { Path as Path4 } from "react-native-svg";
1412
1560
 
1413
1561
  // src/native/wheel.tsx
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";
1562
+ import * as React14 from "react";
1563
+ import { Pressable as Pressable9, ScrollView as ScrollView3, StyleSheet as StyleSheet15, Text as Text10, View as View12 } from "react-native";
1564
+ import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
1417
1565
  var ITEM = 44;
1418
- var FrameContext = React13.createContext({ visible: 5, unset: false });
1566
+ var FrameContext = React14.createContext({ visible: 5, unset: false });
1419
1567
  function WheelPicker({ label, children, visible = 5, invalid, unset = false, style }) {
1420
1568
  const { theme, radius: radius3 } = useTheme();
1421
- return /* @__PURE__ */ jsx15(FrameContext.Provider, { value: React13.useMemo(() => ({ visible, unset }), [visible, unset]), children: /* @__PURE__ */ jsxs12(
1422
- View11,
1569
+ return /* @__PURE__ */ jsx16(FrameContext.Provider, { value: React14.useMemo(() => ({ visible, unset }), [visible, unset]), children: /* @__PURE__ */ jsxs13(
1570
+ View12,
1423
1571
  {
1424
1572
  role: "group",
1425
1573
  "aria-label": label,
1426
- style: [styles14.root, { height: ITEM * visible, borderRadius: radius3.xl, backgroundColor: theme.surface1, borderColor: invalid ? theme.danger : theme.borderDefault }, style],
1574
+ style: [styles15.root, { height: ITEM * visible, borderRadius: radius3.xl, backgroundColor: theme.surface1, borderColor: invalid ? theme.danger : theme.borderDefault }, style],
1427
1575
  children: [
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 }] }),
1576
+ /* @__PURE__ */ jsx16(View12, { pointerEvents: "none", style: [styles15.band, { top: ITEM * (visible - 1) / 2, height: ITEM, borderRadius: radius3.lg, backgroundColor: theme.surface3, borderColor: theme.borderSubtle }] }),
1429
1577
  children
1430
1578
  ]
1431
1579
  }
@@ -1433,7 +1581,7 @@ function WheelPicker({ label, children, visible = 5, invalid, unset = false, sty
1433
1581
  }
1434
1582
  function WheelDivider({ children }) {
1435
1583
  const { theme } = useTheme();
1436
- return /* @__PURE__ */ jsx15(Text10, { "aria-hidden": true, style: [styles14.divider, { color: theme.textSecondary }], children });
1584
+ return /* @__PURE__ */ jsx16(Text10, { "aria-hidden": true, style: [styles15.divider, { color: theme.textSecondary }], children });
1437
1585
  }
1438
1586
  var nearestEnabled = (options, index) => {
1439
1587
  for (let d = 0; d < options.length; d++) {
@@ -1444,14 +1592,14 @@ var nearestEnabled = (options, index) => {
1444
1592
  };
1445
1593
  function Wheel({ label, options, value: valueProp, defaultValue, onValueChange, disabled, style }) {
1446
1594
  const { theme, haptic } = useTheme();
1447
- const { visible, unset } = React13.useContext(FrameContext);
1448
- const [own, setOwn] = React13.useState(defaultValue ?? options[0]?.value ?? "");
1595
+ const { visible, unset } = React14.useContext(FrameContext);
1596
+ const [own, setOwn] = React14.useState(defaultValue ?? options[0]?.value ?? "");
1449
1597
  const value = valueProp ?? own;
1450
1598
  const index = Math.max(0, options.findIndex((o) => o.value === value));
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);
1599
+ const scroller = React14.useRef(null);
1600
+ const passing = React14.useRef(index);
1601
+ const [shown, setShown] = React14.useState(index);
1602
+ const [seen, setSeen] = React14.useState(index);
1455
1603
  if (seen !== index) {
1456
1604
  setSeen(index);
1457
1605
  setShown(index);
@@ -1464,7 +1612,7 @@ function Wheel({ label, options, value: valueProp, defaultValue, onValueChange,
1464
1612
  if (valueProp === void 0) setOwn(option.value);
1465
1613
  if (option.value !== value) onValueChange?.(option.value);
1466
1614
  };
1467
- React13.useEffect(() => {
1615
+ React14.useEffect(() => {
1468
1616
  passing.current = index;
1469
1617
  scroller.current?.scrollTo({ y: index * ITEM, animated: false });
1470
1618
  }, [index]);
@@ -1483,8 +1631,8 @@ function Wheel({ label, options, value: valueProp, defaultValue, onValueChange,
1483
1631
  if (options[i]) commit(i);
1484
1632
  };
1485
1633
  const pad = (visible - 1) / 2 * ITEM;
1486
- return /* @__PURE__ */ jsx15(
1487
- View11,
1634
+ return /* @__PURE__ */ jsx16(
1635
+ View12,
1488
1636
  {
1489
1637
  accessible: true,
1490
1638
  role: "spinbutton",
@@ -1496,8 +1644,8 @@ function Wheel({ label, options, value: valueProp, defaultValue, onValueChange,
1496
1644
  "aria-disabled": disabled || void 0,
1497
1645
  accessibilityActions: [{ name: "increment" }, { name: "decrement" }],
1498
1646
  onAccessibilityAction: (e) => step(e.nativeEvent.actionName === "increment" ? 1 : -1),
1499
- style: [styles14.column, disabled ? styles14.disabled : null, style],
1500
- children: /* @__PURE__ */ jsx15(
1647
+ style: [styles15.column, disabled ? styles15.disabled : null, style],
1648
+ children: /* @__PURE__ */ jsx16(
1501
1649
  ScrollView3,
1502
1650
  {
1503
1651
  ref: scroller,
@@ -1517,12 +1665,12 @@ function Wheel({ label, options, value: valueProp, defaultValue, onValueChange,
1517
1665
  },
1518
1666
  children: options.map((o, i) => {
1519
1667
  const distance = Math.abs(i - shown);
1520
- return /* @__PURE__ */ jsx15(Pressable8, { focusable: false, tabIndex: -1, disabled: disabled || o.disabled, onPress: () => commit(i), style: [styles14.item, { height: ITEM }], children: /* @__PURE__ */ jsx15(
1668
+ return /* @__PURE__ */ jsx16(Pressable9, { focusable: false, tabIndex: -1, disabled: disabled || o.disabled, onPress: () => commit(i), style: [styles15.item, { height: ITEM }], children: /* @__PURE__ */ jsx16(
1521
1669
  Text10,
1522
1670
  {
1523
1671
  numberOfLines: 1,
1524
1672
  style: [
1525
- styles14.itemText,
1673
+ styles15.itemText,
1526
1674
  {
1527
1675
  color: o.disabled ? theme.textMuted : i === shown && !unset ? theme.textPrimary : theme.textSecondary,
1528
1676
  fontWeight: i === shown && !unset ? "600" : "400",
@@ -1540,9 +1688,9 @@ function Wheel({ label, options, value: valueProp, defaultValue, onValueChange,
1540
1688
  }
1541
1689
  );
1542
1690
  }
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 },
1691
+ var styles15 = StyleSheet15.create({
1692
+ root: { flexDirection: "row", alignItems: "stretch", borderWidth: StyleSheet15.hairlineWidth, paddingHorizontal: 6, gap: 4, overflow: "hidden", alignSelf: "flex-start" },
1693
+ band: { position: "absolute", left: 6, right: 6, borderWidth: StyleSheet15.hairlineWidth },
1546
1694
  column: { minWidth: 56, flexGrow: 1 },
1547
1695
  item: { alignItems: "center", justifyContent: "center", paddingHorizontal: 8 },
1548
1696
  itemText: { fontSize: 18, fontVariant: ["tabular-nums"] },
@@ -1551,19 +1699,19 @@ var styles14 = StyleSheet14.create({
1551
1699
  });
1552
1700
 
1553
1701
  // src/native/date-time.tsx
1554
- import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
1702
+ import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
1555
1703
  var longDate = (locale, iso) => new Intl.DateTimeFormat(locale, { dateStyle: "long" }).format(toLocalDate(iso));
1556
1704
  var useOwn = (value, initial) => {
1557
- const [own, setOwn] = React14.useState(initial);
1705
+ const [own, setOwn] = React15.useState(initial);
1558
1706
  return [value !== void 0 ? value : own, (next) => value === void 0 && setOwn(next)];
1559
1707
  };
1560
1708
  function Chevron2({ direction, color }) {
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" }) });
1709
+ return /* @__PURE__ */ jsx17(Svg6, { 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__ */ jsx17(Path4, { d: direction === "left" ? "m15 18-6-6 6-6" : "m9 18 6-6-6-6" }) });
1562
1710
  }
1563
1711
  function NavButton({ label, direction, disabled, onPress }) {
1564
1712
  const { theme, radius: radius3 } = useTheme();
1565
- return /* @__PURE__ */ jsx16(
1566
- Pressable9,
1713
+ return /* @__PURE__ */ jsx17(
1714
+ Pressable10,
1567
1715
  {
1568
1716
  role: "button",
1569
1717
  "aria-label": label,
@@ -1571,49 +1719,49 @@ function NavButton({ label, direction, disabled, onPress }) {
1571
1719
  disabled,
1572
1720
  hitSlop: 6,
1573
1721
  onPress,
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 })
1722
+ style: ({ pressed }) => [styles16.nav, { borderRadius: radius3.md, backgroundColor: pressed ? theme.surface3 : theme.surface2, borderColor: theme.borderSubtle }, disabled ? styles16.disabled : null],
1723
+ children: /* @__PURE__ */ jsx17(Chevron2, { direction, color: theme.textSecondary })
1576
1724
  }
1577
1725
  );
1578
1726
  }
1579
1727
  function Node({ color, style }) {
1580
- return /* @__PURE__ */ jsx16(View12, { "aria-hidden": true, style: [styles15.node, { backgroundColor: color }, style] });
1728
+ return /* @__PURE__ */ jsx17(View13, { "aria-hidden": true, style: [styles16.node, { backgroundColor: color }, style] });
1581
1729
  }
1582
1730
  var calendarLabels = { previousMonth: "Previous month", nextMonth: "Next month" };
1583
1731
  function Calendar({ locale, value, range, onSelect, defaultMonth, min, max, isDateDisabled, weekStartsOn, today: todayProp, labels: given, style }) {
1584
1732
  const labels = { ...calendarLabels, ...given };
1585
1733
  const { theme, radius: radius3, haptic } = useTheme();
1586
1734
  const today = todayProp ?? todayIso();
1587
- const [month, setMonth] = React14.useState(`${(defaultMonth ?? value ?? range?.start ?? today).slice(0, 7)}-01`);
1735
+ const [month, setMonth] = React15.useState(`${(defaultMonth ?? value ?? range?.start ?? today).slice(0, 7)}-01`);
1588
1736
  const start = weekStartsOn ?? weekStartOf(locale);
1589
1737
  const weeks = monthGrid(month, start);
1590
1738
  const weekday = new Intl.DateTimeFormat(locale, { weekday: "narrow" });
1591
1739
  const title = new Intl.DateTimeFormat(locale, { month: "long", year: "numeric" }).format(toLocalDate(month));
1592
1740
  const [lo, hi] = range?.end ? range.start <= range.end ? [range.start, range.end] : [range.end, range.start] : [null, null];
1593
1741
  const off = (iso) => Boolean(min && iso < min || max && iso > max || isDateDisabled?.(iso));
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)) })
1742
+ return /* @__PURE__ */ jsxs14(View13, { style: [styles16.calendar, { backgroundColor: theme.surface1, borderColor: theme.borderDefault, borderRadius: radius3.xl }, style], children: [
1743
+ /* @__PURE__ */ jsxs14(View13, { style: styles16.header, children: [
1744
+ /* @__PURE__ */ jsx17(NavButton, { label: labels.previousMonth, direction: "left", disabled: Boolean(min && addDays(month, -1) < min), onPress: () => setMonth(addMonths(month, -1)) }),
1745
+ /* @__PURE__ */ jsx17(Text11, { role: "heading", "aria-live": "polite", style: [styles16.title, { color: theme.textPrimary }], children: title }),
1746
+ /* @__PURE__ */ jsx17(NavButton, { label: labels.nextMonth, direction: "right", disabled: Boolean(max && addMonths(month, 1) > max), onPress: () => setMonth(addMonths(month, 1)) })
1599
1747
  ] }),
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) => {
1748
+ /* @__PURE__ */ jsx17(View13, { style: styles16.week, "aria-hidden": true, children: weeks[0].map((iso) => /* @__PURE__ */ jsx17(Text11, { style: [styles16.weekday, { color: theme.textSecondary }], children: weekday.format(toLocalDate(iso)) }, iso)) }),
1749
+ /* @__PURE__ */ jsx17(View13, { role: "radiogroup", "aria-label": title, children: weeks.map((week) => /* @__PURE__ */ jsx17(View13, { style: styles16.week, children: week.map((iso) => {
1602
1750
  const outside = iso.slice(0, 7) !== month.slice(0, 7);
1603
1751
  const selected = iso === value || Boolean(range && (iso === range.start || iso === range.end));
1604
1752
  const disabled = off(iso);
1605
1753
  const band = lo && hi && lo !== hi && iso >= lo && iso <= hi;
1606
- return /* @__PURE__ */ jsx16(
1607
- View12,
1754
+ return /* @__PURE__ */ jsx17(
1755
+ View13,
1608
1756
  {
1609
1757
  style: [
1610
- styles15.cell,
1758
+ styles16.cell,
1611
1759
  band ? { backgroundColor: theme.accentSoft } : null,
1612
1760
  band && iso === lo ? { borderTopLeftRadius: radius3.lg, borderBottomLeftRadius: radius3.lg } : null,
1613
1761
  band && iso === hi ? { borderTopRightRadius: radius3.lg, borderBottomRightRadius: radius3.lg } : null
1614
1762
  ],
1615
- children: /* @__PURE__ */ jsxs13(
1616
- Pressable9,
1763
+ children: /* @__PURE__ */ jsxs14(
1764
+ Pressable10,
1617
1765
  {
1618
1766
  role: "radio",
1619
1767
  "aria-label": longDate(locale, iso),
@@ -1626,16 +1774,16 @@ function Calendar({ locale, value, range, onSelect, defaultMonth, min, max, isDa
1626
1774
  onSelect?.(iso);
1627
1775
  },
1628
1776
  style: ({ pressed }) => [
1629
- styles15.day,
1777
+ styles16.day,
1630
1778
  { borderRadius: radius3.lg },
1631
1779
  selected ? { backgroundColor: theme.accent } : pressed ? { backgroundColor: theme.surface3 } : null
1632
1780
  ],
1633
1781
  children: [
1634
- /* @__PURE__ */ jsx16(
1782
+ /* @__PURE__ */ jsx17(
1635
1783
  Text11,
1636
1784
  {
1637
1785
  style: [
1638
- styles15.dayText,
1786
+ styles16.dayText,
1639
1787
  {
1640
1788
  color: selected ? theme.onAccent : disabled ? theme.textMuted : iso === today ? theme.accentText : outside ? theme.textSecondary : theme.textPrimary,
1641
1789
  fontWeight: selected || iso === today ? "700" : "400",
@@ -1645,7 +1793,7 @@ function Calendar({ locale, value, range, onSelect, defaultMonth, min, max, isDa
1645
1793
  children: Number(iso.slice(8))
1646
1794
  }
1647
1795
  ),
1648
- iso === today ? /* @__PURE__ */ jsx16(Node, { color: selected ? theme.onAccent : theme.accent, style: styles15.todayNode }) : null
1796
+ iso === today ? /* @__PURE__ */ jsx17(Node, { color: selected ? theme.onAccent : theme.accent, style: styles16.todayNode }) : null
1649
1797
  ]
1650
1798
  }
1651
1799
  )
@@ -1657,21 +1805,21 @@ function Calendar({ locale, value, range, onSelect, defaultMonth, min, max, isDa
1657
1805
  }
1658
1806
  function MonthPicker({ locale, value, onValueChange, min, max, labels, style }) {
1659
1807
  const { theme, radius: radius3, haptic } = useTheme();
1660
- const [year, setYear] = React14.useState(Number((value ?? todayIso()).slice(0, 4)));
1808
+ const [year, setYear] = React15.useState(Number((value ?? todayIso()).slice(0, 4)));
1661
1809
  const names = monthNames(locale, "short").map((n) => n.replace(/\.$/, ""));
1662
1810
  const long = monthNames(locale, "long");
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) })
1811
+ return /* @__PURE__ */ jsxs14(View13, { style: [styles16.calendar, { backgroundColor: theme.surface1, borderColor: theme.borderDefault, borderRadius: radius3.xl }, style], children: [
1812
+ /* @__PURE__ */ jsxs14(View13, { style: styles16.header, children: [
1813
+ /* @__PURE__ */ jsx17(NavButton, { label: labels?.previousYear ?? "Previous year", direction: "left", disabled: Boolean(min && year - 1 < Number(min.slice(0, 4))), onPress: () => setYear(year - 1) }),
1814
+ /* @__PURE__ */ jsx17(Text11, { role: "heading", "aria-live": "polite", style: [styles16.title, { color: theme.textPrimary }], children: year }),
1815
+ /* @__PURE__ */ jsx17(NavButton, { label: labels?.nextYear ?? "Next year", direction: "right", disabled: Boolean(max && year + 1 > Number(max.slice(0, 4))), onPress: () => setYear(year + 1) })
1668
1816
  ] }),
1669
- /* @__PURE__ */ jsx16(View12, { role: "radiogroup", "aria-label": String(year), style: styles15.months, children: names.map((name, i) => {
1817
+ /* @__PURE__ */ jsx17(View13, { role: "radiogroup", "aria-label": String(year), style: styles16.months, children: names.map((name, i) => {
1670
1818
  const id = `${year}-${String(i + 1).padStart(2, "0")}`;
1671
1819
  const selected = id === value;
1672
1820
  const disabled = Boolean(min && id < min || max && id > max);
1673
- return /* @__PURE__ */ jsx16(
1674
- Pressable9,
1821
+ return /* @__PURE__ */ jsx17(
1822
+ Pressable10,
1675
1823
  {
1676
1824
  role: "radio",
1677
1825
  "aria-checked": selected,
@@ -1682,8 +1830,8 @@ function MonthPicker({ locale, value, onValueChange, min, max, labels, style })
1682
1830
  haptic("selection");
1683
1831
  onValueChange?.(id);
1684
1832
  },
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 })
1833
+ style: ({ pressed }) => [styles16.month, { borderRadius: radius3.lg, backgroundColor: selected ? theme.accent : pressed ? theme.surface3 : "transparent" }, disabled ? styles16.disabled : null],
1834
+ children: /* @__PURE__ */ jsx17(Text11, { style: [styles16.monthText, { color: selected ? theme.onAccent : theme.textPrimary, fontWeight: selected ? "700" : "500" }], children: name })
1687
1835
  },
1688
1836
  id
1689
1837
  );
@@ -1697,13 +1845,13 @@ function DayStrip({ label, locale, value: valueProp, defaultValue = null, onValu
1697
1845
  const [value, setValue] = useOwn(valueProp, defaultValue);
1698
1846
  const weekday = new Intl.DateTimeFormat(locale, { weekday: "short" });
1699
1847
  const list = Array.from({ length: days }, (_, i) => addDays(first, i));
1700
- return /* @__PURE__ */ jsx16(ScrollView4, { horizontal: true, showsHorizontalScrollIndicator: false, role: "radiogroup", "aria-label": label, contentContainerStyle: styles15.strip, style, children: list.map((iso) => {
1848
+ return /* @__PURE__ */ jsx17(ScrollView4, { horizontal: true, showsHorizontalScrollIndicator: false, role: "radiogroup", "aria-label": label, contentContainerStyle: styles16.strip, style, children: list.map((iso) => {
1701
1849
  const selected = iso === value;
1702
1850
  const disabled = Boolean(isDateDisabled?.(iso));
1703
1851
  const marked = Boolean(isDateMarked?.(iso));
1704
1852
  const name = longDate(locale, iso);
1705
- return /* @__PURE__ */ jsxs13(
1706
- Pressable9,
1853
+ return /* @__PURE__ */ jsxs14(
1854
+ Pressable10,
1707
1855
  {
1708
1856
  role: "radio",
1709
1857
  "aria-checked": selected,
@@ -1717,7 +1865,7 @@ function DayStrip({ label, locale, value: valueProp, defaultValue = null, onValu
1717
1865
  onValueChange?.(iso);
1718
1866
  },
1719
1867
  style: ({ pressed }) => [
1720
- styles15.stripDay,
1868
+ styles16.stripDay,
1721
1869
  {
1722
1870
  borderRadius: radius3.xl,
1723
1871
  backgroundColor: selected ? theme.accent : disabled ? "transparent" : theme.surface2,
@@ -1727,10 +1875,10 @@ function DayStrip({ label, locale, value: valueProp, defaultValue = null, onValu
1727
1875
  }
1728
1876
  ],
1729
1877
  children: [
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] })
1878
+ iso === today ? /* @__PURE__ */ jsx17(Node, { color: selected ? theme.onAccent : theme.accent, style: styles16.stripNode }) : null,
1879
+ /* @__PURE__ */ jsx17(Text11, { style: [styles16.stripWeekday, { color: selected ? theme.onAccent : disabled ? theme.textMuted : theme.textSecondary }], children: weekday.format(toLocalDate(iso)).replace(/\.$/, "").toUpperCase() }),
1880
+ /* @__PURE__ */ jsx17(Text11, { style: [styles16.stripNumber, { color: selected ? theme.onAccent : disabled ? theme.textMuted : theme.textPrimary }], children: Number(iso.slice(8)) }),
1881
+ /* @__PURE__ */ jsx17(View13, { style: [styles16.dot, marked ? { backgroundColor: selected ? theme.onAccent : theme.textSecondary } : null] })
1734
1882
  ]
1735
1883
  },
1736
1884
  iso
@@ -1745,11 +1893,11 @@ function TimePicker({ label, locale, value: valueProp, defaultValue = null, onVa
1745
1893
  onValueChange?.(next);
1746
1894
  };
1747
1895
  if (variant === "slots")
1748
- return /* @__PURE__ */ jsx16(View12, { role: "radiogroup", "aria-label": label, style: [styles15.slots, style], children: slots.map((t) => {
1896
+ return /* @__PURE__ */ jsx17(View13, { role: "radiogroup", "aria-label": label, style: [styles16.slots, style], children: slots.map((t) => {
1749
1897
  const selected = t === value;
1750
1898
  const off = disabled || Boolean(isTimeDisabled?.(t));
1751
- return /* @__PURE__ */ jsx16(
1752
- Pressable9,
1899
+ return /* @__PURE__ */ jsx17(
1900
+ Pressable10,
1753
1901
  {
1754
1902
  role: "radio",
1755
1903
  "aria-checked": selected,
@@ -1761,7 +1909,7 @@ function TimePicker({ label, locale, value: valueProp, defaultValue = null, onVa
1761
1909
  set(t);
1762
1910
  },
1763
1911
  style: ({ pressed }) => [
1764
- styles15.slot,
1912
+ styles16.slot,
1765
1913
  {
1766
1914
  borderRadius: radius3.lg,
1767
1915
  backgroundColor: selected ? theme.accent : off ? "transparent" : theme.surface2,
@@ -1770,7 +1918,7 @@ function TimePicker({ label, locale, value: valueProp, defaultValue = null, onVa
1770
1918
  transform: [{ scale: pressed ? 0.97 : 1 }]
1771
1919
  }
1772
1920
  ],
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) })
1921
+ children: /* @__PURE__ */ jsx17(Text11, { style: [styles16.slotText, { color: selected ? theme.onAccent : off ? theme.textMuted : theme.textPrimary, textDecorationLine: off ? "line-through" : "none" }], children: formatTime(locale, t) })
1774
1922
  },
1775
1923
  t
1776
1924
  );
@@ -1786,11 +1934,11 @@ function TimePicker({ label, locale, value: valueProp, defaultValue = null, onVa
1786
1934
  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) }));
1787
1935
  const minutes = Array.from({ length: Math.ceil(60 / minuteStep) }, (_, i) => ({ value: String(i * minuteStep), label: two(i * minuteStep) }));
1788
1936
  const [am, pmLabel] = dayPeriods(locale);
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(
1937
+ return /* @__PURE__ */ jsxs14(WheelPicker, { label: value ? `${label}, ${formatTime(locale, value)}` : label, style, children: [
1938
+ /* @__PURE__ */ jsx17(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) }),
1939
+ /* @__PURE__ */ jsx17(WheelDivider, { children: ":" }),
1940
+ /* @__PURE__ */ jsx17(Wheel, { label: labels.minutes, options: minutes, disabled, value: String(Math.min(60 - minuteStep, Math.round(minute / minuteStep) * minuteStep)), onValueChange: (v) => put(h24, Number(v)) }),
1941
+ twelve ? /* @__PURE__ */ jsx17(
1794
1942
  Wheel,
1795
1943
  {
1796
1944
  label: labels.period,
@@ -1823,22 +1971,22 @@ function DateWheel({ label, locale, value: valueProp, defaultValue = null, onVal
1823
1971
  };
1824
1972
  const last = daysInMonth(year, month);
1825
1973
  const columns = {
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")
1974
+ day: /* @__PURE__ */ jsx17(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: styles16.dayWheel }, "day"),
1975
+ month: /* @__PURE__ */ jsx17(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: styles16.monthWheel }, "month"),
1976
+ year: /* @__PURE__ */ jsx17(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: styles16.yearWheel }, "year")
1829
1977
  };
1830
1978
  const caption = error ?? hint;
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
1979
+ return /* @__PURE__ */ jsxs14(View13, { style: [styles16.field, style], children: [
1980
+ /* @__PURE__ */ jsx17(Text11, { "aria-hidden": true, style: [styles16.fieldLabel, { color: theme.textSecondary }], children: label }),
1981
+ /* @__PURE__ */ jsx17(WheelPicker, { label, invalid: Boolean(error), unset: !value, children: datePartsOrder(locale).map((part) => columns[part]) }),
1982
+ caption ? /* @__PURE__ */ jsx17(Text11, { role: error ? "alert" : void 0, "aria-live": error ? "polite" : void 0, style: [styles16.caption, { color: error ? theme.dangerText : theme.textSecondary }], children: caption }) : null
1835
1983
  ] });
1836
1984
  }
1837
- var styles15 = StyleSheet15.create({
1838
- calendar: { padding: 12, gap: 4, borderWidth: StyleSheet15.hairlineWidth, alignSelf: "flex-start" },
1985
+ var styles16 = StyleSheet16.create({
1986
+ calendar: { padding: 12, gap: 4, borderWidth: StyleSheet16.hairlineWidth, alignSelf: "flex-start" },
1839
1987
  header: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", marginBottom: 6, gap: 8 },
1840
1988
  title: { fontSize: 15, fontWeight: "700", textTransform: "capitalize" },
1841
- nav: { width: 36, height: 36, alignItems: "center", justifyContent: "center", borderWidth: StyleSheet15.hairlineWidth },
1989
+ nav: { width: 36, height: 36, alignItems: "center", justifyContent: "center", borderWidth: StyleSheet16.hairlineWidth },
1842
1990
  week: { flexDirection: "row" },
1843
1991
  weekday: { width: 44, textAlign: "center", fontSize: 11, fontWeight: "700", paddingBottom: 4 },
1844
1992
  cell: { width: 44, height: 44, marginVertical: 1 },
@@ -1868,26 +2016,26 @@ var styles15 = StyleSheet15.create({
1868
2016
  });
1869
2017
 
1870
2018
  // 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";
2019
+ import { StyleSheet as StyleSheet17, View as View14 } from "react-native";
2020
+ import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
1873
2021
  function DescriptionList({ items: items2, layout = "stacked", style }) {
1874
2022
  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,
2023
+ return /* @__PURE__ */ jsx18(View14, { role: "list", style: [layout === "grid" ? styles17.grid : layout === "inline" ? null : styles17.stacked, style], children: items2.map((item, i) => {
2024
+ const value = typeof item.details === "string" || typeof item.details === "number" ? /* @__PURE__ */ jsx18(Txt, { variant: layout === "grid" ? "title" : "body", style: layout === "inline" ? styles17.right : null, children: item.details }) : item.details;
2025
+ return /* @__PURE__ */ jsxs15(
2026
+ View14,
1879
2027
  {
1880
2028
  role: "listitem",
1881
2029
  accessible: true,
1882
2030
  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
2031
+ layout === "inline" ? [styles17.inline, i > 0 ? { borderTopWidth: StyleSheet17.hairlineWidth, borderTopColor: theme.borderSubtle } : null] : null,
2032
+ layout === "grid" ? [styles17.card, { backgroundColor: theme.surface1, borderColor: theme.borderDefault, borderRadius: radius3.lg }] : null
1885
2033
  ],
1886
2034
  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: [
2035
+ /* @__PURE__ */ jsx18(Txt, { variant: "caption", tone: "secondary", style: layout === "grid" ? styles17.upper : null, children: item.term }),
2036
+ /* @__PURE__ */ jsxs15(View14, { style: layout === "inline" ? styles17.valueInline : styles17.value, children: [
1889
2037
  value,
1890
- item.hint ? /* @__PURE__ */ jsx17(Txt, { variant: "caption", tone: "secondary", style: layout === "inline" ? styles16.right : null, children: item.hint }) : null
2038
+ item.hint ? /* @__PURE__ */ jsx18(Txt, { variant: "caption", tone: "secondary", style: layout === "inline" ? styles17.right : null, children: item.hint }) : null
1891
2039
  ] })
1892
2040
  ]
1893
2041
  },
@@ -1895,11 +2043,11 @@ function DescriptionList({ items: items2, layout = "stacked", style }) {
1895
2043
  );
1896
2044
  }) });
1897
2045
  }
1898
- var styles16 = StyleSheet16.create({
2046
+ var styles17 = StyleSheet17.create({
1899
2047
  stacked: { gap: 14 },
1900
2048
  inline: { flexDirection: "row", alignItems: "baseline", justifyContent: "space-between", gap: 16, paddingVertical: 10 },
1901
2049
  grid: { flexDirection: "row", flexWrap: "wrap", gap: 10 },
1902
- card: { flexBasis: "47%", flexGrow: 1, padding: 12, gap: 4, borderWidth: StyleSheet16.hairlineWidth },
2050
+ card: { flexBasis: "47%", flexGrow: 1, padding: 12, gap: 4, borderWidth: StyleSheet17.hairlineWidth },
1903
2051
  upper: { textTransform: "uppercase", letterSpacing: 0.6, fontWeight: "700" },
1904
2052
  value: { gap: 2, marginTop: 2 },
1905
2053
  valueInline: { flexShrink: 1, alignItems: "flex-end", gap: 2 },
@@ -1907,18 +2055,18 @@ var styles16 = StyleSheet16.create({
1907
2055
  });
1908
2056
 
1909
2057
  // src/native/empty-state.tsx
1910
- import { StyleSheet as StyleSheet17, View as View14 } from "react-native";
1911
- import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
2058
+ import { StyleSheet as StyleSheet18, View as View15 } from "react-native";
2059
+ import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
1912
2060
  function EmptyState({ icon, title, description, action, style, ...props }) {
1913
2061
  const { theme } = useTheme();
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
2062
+ return /* @__PURE__ */ jsxs16(View15, { ...props, style: [styles18.root, style], children: [
2063
+ icon ? /* @__PURE__ */ jsx19(View15, { "aria-hidden": true, style: [styles18.icon, { backgroundColor: theme.surface2 }], children: icon }) : null,
2064
+ /* @__PURE__ */ jsx19(Txt, { variant: "label", role: "heading", style: styles18.center, children: title }),
2065
+ description ? /* @__PURE__ */ jsx19(Txt, { tone: "secondary", style: styles18.center, children: description }) : null,
2066
+ action ? /* @__PURE__ */ jsx19(View15, { style: styles18.action, children: action }) : null
1919
2067
  ] });
1920
2068
  }
1921
- var styles17 = StyleSheet17.create({
2069
+ var styles18 = StyleSheet18.create({
1922
2070
  root: { alignItems: "center", justifyContent: "center", gap: 8, paddingVertical: 40, paddingHorizontal: 24 },
1923
2071
  icon: { width: 48, height: 48, borderRadius: 24, alignItems: "center", justifyContent: "center", marginBottom: 4 },
1924
2072
  center: { textAlign: "center", maxWidth: 360 },
@@ -1926,13 +2074,13 @@ var styles17 = StyleSheet17.create({
1926
2074
  });
1927
2075
 
1928
2076
  // 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";
2077
+ import { Pressable as Pressable11, StyleSheet as StyleSheet19, View as View16 } from "react-native";
2078
+ import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
1931
2079
  function Fab({ label, icon, onPress, extended, placement = "end", offset = 0, style }) {
1932
2080
  const { theme, insets, haptic } = useTheme();
1933
2081
  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,
2082
+ return /* @__PURE__ */ jsx20(View16, { pointerEvents: "box-none", style: [styles19.layer, placement === "center" ? styles19.centre : null], children: /* @__PURE__ */ jsxs17(
2083
+ Pressable11,
1936
2084
  {
1937
2085
  role: "button",
1938
2086
  "aria-label": label,
@@ -1941,20 +2089,20 @@ function Fab({ label, icon, onPress, extended, placement = "end", offset = 0, st
1941
2089
  onPress();
1942
2090
  },
1943
2091
  style: ({ pressed }) => [
1944
- styles18.fab,
1945
- extended ? styles18.extended : null,
2092
+ styles19.fab,
2093
+ extended ? styles19.extended : null,
1946
2094
  position,
1947
2095
  { bottom: 16 + insets.bottom + offset, backgroundColor: pressed ? theme.accentHover : theme.accent, borderTopColor: theme.edgeOnFill, shadowColor: theme.scrimStrong },
1948
2096
  style
1949
2097
  ],
1950
2098
  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
2099
+ /* @__PURE__ */ jsx20(View16, { "aria-hidden": true, children: icon }),
2100
+ extended ? /* @__PURE__ */ jsx20(Txt, { variant: "label", tone: "onAccent", "aria-hidden": true, numberOfLines: 1, style: styles19.label, children: label }) : null
1953
2101
  ]
1954
2102
  }
1955
2103
  ) });
1956
2104
  }
1957
- var styles18 = StyleSheet18.create({
2105
+ var styles19 = StyleSheet19.create({
1958
2106
  layer: { position: "absolute", top: 0, right: 0, bottom: 0, left: 0 },
1959
2107
  centre: { alignItems: "center" },
1960
2108
  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 },
@@ -1963,19 +2111,19 @@ var styles18 = StyleSheet18.create({
1963
2111
  });
1964
2112
 
1965
2113
  // src/native/field.tsx
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";
2114
+ import * as React16 from "react";
2115
+ import { StyleSheet as StyleSheet20, Text as Text12, TextInput as TextInput4, View as View17 } from "react-native";
2116
+ import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
1969
2117
  function TextField({ label, hint, error, value, defaultValue, onValueChange, disabled, end, inputRef, style, multiline, onFocus, onBlur, ...props }) {
1970
2118
  const { theme, radius: radius3 } = useTheme();
1971
- const [focused, setFocused] = React15.useState(false);
2119
+ const [focused, setFocused] = React16.useState(false);
1972
2120
  const caption = error ?? hint;
1973
2121
  const border = error ? theme.danger : focused ? theme.accent : theme.borderDefault;
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(
1978
- TextInput3,
2122
+ return /* @__PURE__ */ jsxs18(View17, { style: [styles20.root, disabled ? styles20.disabled : null, style], children: [
2123
+ /* @__PURE__ */ jsx21(Text12, { style: [styles20.label, { color: theme.textSecondary }], children: label }),
2124
+ /* @__PURE__ */ jsxs18(View17, { style: [styles20.frame, multiline ? styles20.multiline : null, { borderRadius: radius3.md, borderColor: border, backgroundColor: theme.surface2 }], children: [
2125
+ /* @__PURE__ */ jsx21(
2126
+ TextInput4,
1979
2127
  {
1980
2128
  ref: inputRef,
1981
2129
  "aria-label": label,
@@ -1996,16 +2144,16 @@ function TextField({ label, hint, error, value, defaultValue, onValueChange, dis
1996
2144
  setFocused(false);
1997
2145
  onBlur?.(event);
1998
2146
  },
1999
- style: [styles19.input, multiline ? styles19.inputMultiline : null, { color: theme.textPrimary }],
2147
+ style: [styles20.input, multiline ? styles20.inputMultiline : null, { color: theme.textPrimary }],
2000
2148
  ...props
2001
2149
  }
2002
2150
  ),
2003
- end ? /* @__PURE__ */ jsx20(View16, { style: styles19.end, children: end }) : null
2151
+ end ? /* @__PURE__ */ jsx21(View17, { style: styles20.end, children: end }) : null
2004
2152
  ] }),
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
2153
+ caption ? /* @__PURE__ */ jsx21(Text12, { role: error ? "alert" : void 0, "aria-live": error ? "polite" : void 0, style: [styles20.caption, { color: error ? theme.dangerText : theme.textSecondary }], children: caption }) : null
2006
2154
  ] });
2007
2155
  }
2008
- var styles19 = StyleSheet19.create({
2156
+ var styles20 = StyleSheet20.create({
2009
2157
  root: { gap: 6, alignSelf: "stretch" },
2010
2158
  label: { fontSize: 12, lineHeight: 16, fontWeight: "600" },
2011
2159
  frame: { flexDirection: "row", alignItems: "center", minHeight: 44, paddingHorizontal: 12, borderWidth: 1 },
@@ -2018,20 +2166,20 @@ var styles19 = StyleSheet19.create({
2018
2166
  });
2019
2167
 
2020
2168
  // src/native/goal-gauge.tsx
2021
- import { Animated as Animated5, StyleSheet as StyleSheet20, View as View17 } from "react-native";
2169
+ import { Animated as Animated6, StyleSheet as StyleSheet21, View as View18 } from "react-native";
2022
2170
 
2023
2171
  // src/native/story-motion.ts
2024
- import * as React16 from "react";
2025
- import { AccessibilityInfo as AccessibilityInfo3, Animated as Animated4, Easing } from "react-native";
2172
+ import * as React17 from "react";
2173
+ import { AccessibilityInfo as AccessibilityInfo3, Animated as Animated5, Easing as Easing2 } from "react-native";
2026
2174
  function useEntrance(animated, delay = 0, duration = 700) {
2027
- const [value] = React16.useState(() => new Animated4.Value(animated ? 0 : 1));
2028
- React16.useEffect(() => {
2175
+ const [value] = React17.useState(() => new Animated5.Value(animated ? 0 : 1));
2176
+ React17.useEffect(() => {
2029
2177
  if (!animated) return;
2030
2178
  let cancelled = false;
2031
2179
  void AccessibilityInfo3.isReduceMotionEnabled().then((reduce) => {
2032
2180
  if (cancelled) return;
2033
2181
  if (reduce) value.setValue(1);
2034
- else Animated4.timing(value, { toValue: 1, duration, delay, easing: Easing.out(Easing.cubic), useNativeDriver: true }).start();
2182
+ else Animated5.timing(value, { toValue: 1, duration, delay, easing: Easing2.out(Easing2.cubic), useNativeDriver: true }).start();
2035
2183
  });
2036
2184
  return () => {
2037
2185
  cancelled = true;
@@ -2041,17 +2189,17 @@ function useEntrance(animated, delay = 0, duration = 700) {
2041
2189
  }
2042
2190
 
2043
2191
  // src/native/goal-gauge.tsx
2044
- import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
2192
+ import { jsx as jsx22, jsxs as jsxs19 } from "react/jsx-runtime";
2045
2193
  function Cell({ lit, animate, order, animated, arcade }) {
2046
2194
  const { theme } = useTheme();
2047
2195
  const t = useEntrance(animated && animate, 300 + order * 100, 350);
2048
2196
  const spentOpacity = arcade ? 0.14 : 1;
2049
2197
  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] });
2050
2198
  const color = lit || arcade ? theme.accent : theme.surface3;
2051
- return /* @__PURE__ */ jsx21(
2052
- Animated5.View,
2199
+ return /* @__PURE__ */ jsx22(
2200
+ Animated6.View,
2053
2201
  {
2054
- style: [styles20.cell, arcade ? styles20.cellArcade : null, { backgroundColor: color, opacity: lit || animate ? opacity : spentOpacity }]
2202
+ style: [styles21.cell, arcade ? styles21.cellArcade : null, { backgroundColor: color, opacity: lit || animate ? opacity : spentOpacity }]
2055
2203
  }
2056
2204
  );
2057
2205
  }
@@ -2061,8 +2209,8 @@ function GoalGauge({ label, segments, value, valueText, mode = "fill", showLabel
2061
2209
  const lit = Math.min(total, Math.max(0, Math.round(value ?? total)));
2062
2210
  const words = valueText ?? `${lit} / ${total}`;
2063
2211
  const arcade = variant === "arcade";
2064
- return /* @__PURE__ */ jsxs18(
2065
- View17,
2212
+ return /* @__PURE__ */ jsxs19(
2213
+ View18,
2066
2214
  {
2067
2215
  accessible: true,
2068
2216
  role: "meter",
@@ -2072,22 +2220,22 @@ function GoalGauge({ label, segments, value, valueText, mode = "fill", showLabel
2072
2220
  "aria-valuenow": lit,
2073
2221
  "aria-valuetext": words,
2074
2222
  ...props,
2075
- style: [styles20.root, style],
2223
+ style: [styles21.root, style],
2076
2224
  children: [
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 })
2225
+ showLabel ? /* @__PURE__ */ jsxs19(View18, { "aria-hidden": true, style: [styles21.head, arcade ? styles21.headArcade : null], children: [
2226
+ /* @__PURE__ */ jsx22(Txt, { variant: arcade ? "mono" : "caption", tone: "secondary", children: arcade ? label.toUpperCase() : label }),
2227
+ arcade ? null : /* @__PURE__ */ jsx22(Txt, { variant: "caption", children: words })
2080
2228
  ] }) : null,
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) => {
2229
+ /* @__PURE__ */ jsx22(View18, { "aria-hidden": true, style: [styles21.cells, arcade ? [styles21.cellsArcade, { borderColor: theme.borderSubtle, backgroundColor: theme.surface1 }] : null], children: Array.from({ length: total }, (_, i) => {
2082
2230
  const on = i < lit;
2083
2231
  const animate = mode === "fill" ? on : !on;
2084
- return /* @__PURE__ */ jsx21(Cell, { lit: on, animate, order: mode === "fill" ? i : i - lit, animated, arcade }, i);
2232
+ return /* @__PURE__ */ jsx22(Cell, { lit: on, animate, order: mode === "fill" ? i : i - lit, animated, arcade }, i);
2085
2233
  }) })
2086
2234
  ]
2087
2235
  }
2088
2236
  );
2089
2237
  }
2090
- var styles20 = StyleSheet20.create({
2238
+ var styles21 = StyleSheet21.create({
2091
2239
  root: { alignSelf: "stretch", gap: 8 },
2092
2240
  head: { flexDirection: "row", justifyContent: "space-between", alignItems: "baseline", gap: 12 },
2093
2241
  headArcade: { justifyContent: "center" },
@@ -2098,45 +2246,45 @@ var styles20 = StyleSheet20.create({
2098
2246
  });
2099
2247
 
2100
2248
  // 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";
2249
+ import * as React18 from "react";
2250
+ import { Animated as Animated7, Pressable as Pressable12, StyleSheet as StyleSheet22, View as View19 } from "react-native";
2251
+ import Svg7, { Path as Path5 } from "react-native-svg";
2252
+ import { jsx as jsx23, jsxs as jsxs20 } from "react/jsx-runtime";
2105
2253
  var BAR = 44;
2106
2254
  var LARGE = 52;
2107
2255
  function Header({ title, subtitle, scrollY, size = "large", backLabel, onBack, actions, children, style }) {
2108
2256
  const { theme, insets } = useTheme();
2109
2257
  const reduce = useReducedMotion();
2110
2258
  const large = size === "large";
2111
- const fixed = React17.useMemo(() => new Animated6.Value(large ? 0 : 1), [large]);
2259
+ const fixed = React18.useMemo(() => new Animated7.Value(large ? 0 : 1), [large]);
2112
2260
  const progress = scrollY && large ? scrollY.interpolate({ inputRange: [0, LARGE], outputRange: [0, 1], extrapolate: "clamp" }) : fixed;
2113
2261
  const smallOpacity = progress.interpolate({ inputRange: [0.6, 1], outputRange: [0, 1], extrapolate: "clamp" });
2114
2262
  const largeOpacity = progress.interpolate({ inputRange: [0, 0.7], outputRange: [1, 0], extrapolate: "clamp" });
2115
2263
  const largeShift = reduce ? 0 : progress.interpolate({ inputRange: [0, 1], outputRange: [0, -10] });
2116
2264
  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 })
2265
+ return /* @__PURE__ */ jsxs20(View19, { style: [{ paddingTop: insets.top, backgroundColor: theme.surface0 }, style], children: [
2266
+ /* @__PURE__ */ jsxs20(View19, { style: styles22.bar, children: [
2267
+ /* @__PURE__ */ jsx23(View19, { style: styles22.side, children: onBack && backLabel ? /* @__PURE__ */ jsxs20(Pressable12, { role: "button", "aria-label": backLabel, onPress: onBack, hitSlop: 8, style: styles22.back, children: [
2268
+ /* @__PURE__ */ jsx23(Svg7, { width: 22, height: 22, viewBox: "0 0 24 24", "aria-hidden": true, children: /* @__PURE__ */ jsx23(Path5, { d: "M15 5l-7 7 7 7", stroke: theme.accentText, strokeWidth: 2.4, fill: "none", strokeLinecap: "round", strokeLinejoin: "round" }) }),
2269
+ /* @__PURE__ */ jsx23(Txt, { variant: "label", tone: "accent", numberOfLines: 1, children: backLabel })
2122
2270
  ] }) : 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 })
2271
+ /* @__PURE__ */ jsx23(Animated7.View, { style: [styles22.middle, { opacity: smallOpacity }], "aria-hidden": large, children: /* @__PURE__ */ jsx23(Txt, { variant: "label", numberOfLines: 1, role: large ? void 0 : "heading", children: title }) }),
2272
+ /* @__PURE__ */ jsx23(View19, { style: [styles22.side, styles22.right], children: actions })
2125
2273
  ] }),
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
2274
+ large ? /* @__PURE__ */ jsx23(Animated7.View, { style: { height: largeHeight, overflow: "hidden" }, children: /* @__PURE__ */ jsxs20(Animated7.View, { style: [styles22.large, { opacity: largeOpacity, transform: [{ translateY: largeShift }] }], children: [
2275
+ /* @__PURE__ */ jsx23(Txt, { variant: "display", numberOfLines: 1, role: "heading", style: styles22.largeTitle, children: title }),
2276
+ subtitle ? /* @__PURE__ */ jsx23(Txt, { variant: "caption", tone: "secondary", children: subtitle }) : null
2129
2277
  ] }) }) : 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 }] })
2278
+ children ? /* @__PURE__ */ jsx23(View19, { style: styles22.children, children }) : null,
2279
+ /* @__PURE__ */ jsx23(Animated7.View, { "aria-hidden": true, style: [styles22.rule, { backgroundColor: theme.borderSubtle, opacity: smallOpacity }] })
2132
2280
  ] });
2133
2281
  }
2134
2282
  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]);
2283
+ const [scrollY] = React18.useState(() => new Animated7.Value(0));
2284
+ const onScroll = React18.useMemo(() => Animated7.event([{ nativeEvent: { contentOffset: { y: scrollY } } }], { useNativeDriver: false }), [scrollY]);
2137
2285
  return { scrollY, onScroll };
2138
2286
  }
2139
- var styles21 = StyleSheet21.create({
2287
+ var styles22 = StyleSheet22.create({
2140
2288
  bar: { height: BAR, flexDirection: "row", alignItems: "center", paddingHorizontal: 8 },
2141
2289
  side: { flex: 1, flexDirection: "row", alignItems: "center" },
2142
2290
  right: { justifyContent: "flex-end", gap: 4 },
@@ -2145,30 +2293,30 @@ var styles21 = StyleSheet21.create({
2145
2293
  large: { paddingHorizontal: 16, paddingBottom: 6 },
2146
2294
  largeTitle: { fontSize: 32, lineHeight: 40 },
2147
2295
  children: { paddingHorizontal: 16, paddingBottom: 8 },
2148
- rule: { height: StyleSheet21.hairlineWidth }
2296
+ rule: { height: StyleSheet22.hairlineWidth }
2149
2297
  });
2150
2298
 
2151
2299
  // 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";
2300
+ import * as React19 from "react";
2301
+ import { AccessibilityInfo as AccessibilityInfo4, Animated as Animated8, Image as Image3, Modal as Modal3, PanResponder, Pressable as Pressable13, StyleSheet as StyleSheet23, useWindowDimensions, View as View20 } from "react-native";
2302
+ import { jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
2155
2303
  var MAX_SCALE = 4;
2156
2304
  function ImageViewer({ images, index, onIndexChange, closeLabel, positionLabel = (n, total) => `${n} / ${total}` }) {
2157
2305
  const { theme, insets, haptic } = useTheme();
2158
2306
  const reduce = useReducedMotion();
2159
2307
  const { width, height } = useWindowDimensions();
2160
2308
  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(() => {
2309
+ const [scale] = React19.useState(() => new Animated8.Value(1));
2310
+ const [pan] = React19.useState(() => new Animated8.ValueXY({ x: 0, y: 0 }));
2311
+ const [dismiss2] = React19.useState(() => new Animated8.Value(0));
2312
+ const state = React19.useRef({ scale: 1, x: 0, y: 0, pinch: 0, base: 1, lastTap: 0 });
2313
+ const reset = React19.useCallback(() => {
2166
2314
  state.current = { ...state.current, scale: 1, x: 0, y: 0 };
2167
2315
  scale.setValue(1);
2168
2316
  pan.setValue({ x: 0, y: 0 });
2169
2317
  dismiss2.setValue(0);
2170
2318
  }, [scale, pan, dismiss2]);
2171
- React18.useEffect(() => {
2319
+ React19.useEffect(() => {
2172
2320
  reset();
2173
2321
  if (open) AccessibilityInfo4.announceForAccessibility(`${images[index].alt}, ${positionLabel(index + 1, images.length)}`);
2174
2322
  }, [index]);
@@ -2177,9 +2325,9 @@ function ImageViewer({ images, index, onIndexChange, closeLabel, positionLabel =
2177
2325
  haptic("selection");
2178
2326
  onIndexChange(to);
2179
2327
  };
2180
- const animateTo = (value, to) => reduce ? value.setValue(to) : Animated7.spring(value, { toValue: to, useNativeDriver: true, damping: 20 }).start();
2328
+ const animateTo = (value, to) => reduce ? value.setValue(to) : Animated8.spring(value, { toValue: to, useNativeDriver: true, damping: 20 }).start();
2181
2329
  const distance = (touches) => Math.hypot(touches[0].pageX - touches[1].pageX, touches[0].pageY - touches[1].pageY);
2182
- const responder = React18.useMemo(
2330
+ const responder = React19.useMemo(
2183
2331
  () => PanResponder.create({
2184
2332
  onStartShouldSetPanResponder: () => true,
2185
2333
  onMoveShouldSetPanResponder: (_, g) => Math.abs(g.dx) > 4 || Math.abs(g.dy) > 4,
@@ -2230,7 +2378,7 @@ function ImageViewer({ images, index, onIndexChange, closeLabel, positionLabel =
2230
2378
  if (g.dx < -width / 4 || g.vx < -0.8) go((index ?? 0) + 1);
2231
2379
  else if (g.dx > width / 4 || g.vx > 0.8) go((index ?? 0) - 1);
2232
2380
  animateTo(dismiss2, 0);
2233
- Animated7.spring(pan, { toValue: { x: 0, y: 0 }, useNativeDriver: true }).start();
2381
+ Animated8.spring(pan, { toValue: { x: 0, y: 0 }, useNativeDriver: true }).start();
2234
2382
  }
2235
2383
  }),
2236
2384
  [index, width, images.length]
@@ -2239,12 +2387,12 @@ function ImageViewer({ images, index, onIndexChange, closeLabel, positionLabel =
2239
2387
  if (!open) return null;
2240
2388
  const image = images[index];
2241
2389
  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,
2390
+ return /* @__PURE__ */ jsxs21(Modal3, { ...modalName(image.alt), visible: true, transparent: true, animationType: reduce ? "none" : "fade", onRequestClose: () => onIndexChange(null), statusBarTranslucent: true, children: [
2391
+ /* @__PURE__ */ jsx24(Animated8.View, { style: [StyleSheet23.absoluteFill, { backgroundColor: theme.media, opacity: backdrop }] }),
2392
+ /* @__PURE__ */ jsx24(
2393
+ View20,
2246
2394
  {
2247
- style: StyleSheet22.absoluteFill,
2395
+ style: StyleSheet23.absoluteFill,
2248
2396
  accessible: true,
2249
2397
  role: "img",
2250
2398
  "aria-label": `${image.alt}, ${positionLabel(index + 1, images.length)}`,
@@ -2256,21 +2404,21 @@ function ImageViewer({ images, index, onIndexChange, closeLabel, positionLabel =
2256
2404
  if (name === "escape") onIndexChange(null);
2257
2405
  },
2258
2406
  ...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 }) })
2407
+ children: /* @__PURE__ */ jsx24(Animated8.View, { style: { width, height, transform: [{ translateX: pan.x }, { translateY: Animated8.add(pan.y, dismiss2) }, { scale }] }, children: /* @__PURE__ */ jsx24(Image3, { source: { uri: image.uri }, resizeMode: "contain", style: { width, height }, accessibilityIgnoresInvertColors: true }) })
2260
2408
  }
2261
2409
  ),
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" }) })
2410
+ /* @__PURE__ */ jsxs21(View20, { pointerEvents: "box-none", style: [styles23.top, { paddingTop: insets.top + 8 }], children: [
2411
+ /* @__PURE__ */ jsx24(View20, { "aria-hidden": true, style: [styles23.counter, { backgroundColor: theme.scrimStrong }], children: /* @__PURE__ */ jsx24(Txt, { variant: "label", tone: "onMedia", children: positionLabel(index + 1, images.length) }) }),
2412
+ /* @__PURE__ */ jsx24(Pressable13, { role: "button", "aria-label": closeLabel, hitSlop: 12, onPress: () => onIndexChange(null), style: [styles23.close, { backgroundColor: theme.scrimStrong }], children: /* @__PURE__ */ jsx24(Txt, { tone: "onMedia", style: styles23.cross, "aria-hidden": true, children: "\xD7" }) })
2265
2413
  ] }),
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
2414
+ image.caption ? /* @__PURE__ */ jsx24(View20, { pointerEvents: "none", style: [styles23.caption, { paddingBottom: insets.bottom + 16, backgroundColor: theme.scrimStrong }], children: /* @__PURE__ */ jsx24(Txt, { tone: "onMedia", children: image.caption }) }) : null
2267
2415
  ] });
2268
2416
  }
2269
2417
  function prefetchNeighbours(images, index) {
2270
2418
  if (index === null) return;
2271
2419
  for (const i of [index - 1, index + 1]) if (images[i]) void Image3.prefetch(images[i].uri).catch(() => void 0);
2272
2420
  }
2273
- var styles22 = StyleSheet22.create({
2421
+ var styles23 = StyleSheet23.create({
2274
2422
  top: { position: "absolute", top: 0, left: 0, right: 0, flexDirection: "row", alignItems: "center", justifyContent: "space-between", paddingHorizontal: 16 },
2275
2423
  counter: { paddingHorizontal: 10, paddingVertical: 4, borderRadius: 999 },
2276
2424
  close: { width: 40, height: 40, borderRadius: 20, alignItems: "center", justifyContent: "center" },
@@ -2279,8 +2427,8 @@ var styles22 = StyleSheet22.create({
2279
2427
  });
2280
2428
 
2281
2429
  // src/native/KrizakaMark.tsx
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";
2430
+ import { View as View21 } from "react-native";
2431
+ import Svg8, { Circle as Circle2, Defs as Defs3, G as Group, LinearGradient as LinearGradient3, Path as Path6, RadialGradient, Stop as Stop3 } from "react-native-svg";
2284
2432
 
2285
2433
  // src/marks/krizaka-geometry.ts
2286
2434
  var KRIZAKA = {
@@ -2302,24 +2450,24 @@ var KRIZAKA = {
2302
2450
  };
2303
2451
 
2304
2452
  // src/native/mark-motion.ts
2305
- import { useEffect as useEffect10, useState as useState18 } from "react";
2306
- import { AccessibilityInfo as AccessibilityInfo5, Animated as Animated8, Easing as Easing2 } from "react-native";
2453
+ import { useEffect as useEffect11, useState as useState19 } from "react";
2454
+ import { AccessibilityInfo as AccessibilityInfo5, Animated as Animated9, Easing as Easing3 } from "react-native";
2307
2455
  var markA11y = (title) => title ? { accessible: true, accessibilityRole: "image", accessibilityLabel: title } : { accessibilityElementsHidden: true, importantForAccessibility: "no-hide-descendants" };
2308
2456
  function useMarkMotion(size, animated, spinMs = 3e4) {
2309
- const [spin] = useState18(() => new Animated8.Value(0));
2310
- const [pulse] = useState18(() => new Animated8.Value(0));
2311
- useEffect10(() => {
2457
+ const [spin] = useState19(() => new Animated9.Value(0));
2458
+ const [pulse] = useState19(() => new Animated9.Value(0));
2459
+ useEffect11(() => {
2312
2460
  if (!animated) return;
2313
2461
  let loops = [];
2314
2462
  let cancelled = false;
2315
2463
  void AccessibilityInfo5.isReduceMotionEnabled().then((reduce) => {
2316
2464
  if (reduce || cancelled) return;
2317
2465
  loops = [
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 })
2466
+ Animated9.loop(Animated9.timing(spin, { toValue: 1, duration: spinMs, easing: Easing3.linear, useNativeDriver: true })),
2467
+ Animated9.loop(
2468
+ Animated9.sequence([
2469
+ Animated9.timing(pulse, { toValue: 1, duration: 1600, easing: Easing3.inOut(Easing3.ease), useNativeDriver: true }),
2470
+ Animated9.timing(pulse, { toValue: 0, duration: 1600, easing: Easing3.inOut(Easing3.ease), useNativeDriver: true })
2323
2471
  ])
2324
2472
  )
2325
2473
  ];
@@ -2331,7 +2479,7 @@ function useMarkMotion(size, animated, spinMs = 3e4) {
2331
2479
  };
2332
2480
  }, [animated, spin, pulse, spinMs]);
2333
2481
  return {
2334
- Animated: Animated8,
2482
+ Animated: Animated9,
2335
2483
  layer: { position: "absolute", width: size, height: size },
2336
2484
  spinStyle: { transform: [{ rotate: spin.interpolate({ inputRange: [0, 1], outputRange: ["0deg", "360deg"] }) }] },
2337
2485
  pulseStyle: { opacity: pulse.interpolate({ inputRange: [0, 1], outputRange: [0.85, 1] }) }
@@ -2339,39 +2487,39 @@ function useMarkMotion(size, animated, spinMs = 3e4) {
2339
2487
  }
2340
2488
 
2341
2489
  // src/native/KrizakaMark.tsx
2342
- import { Fragment as Fragment4, jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
2490
+ import { Fragment as Fragment5, jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
2343
2491
  function KrizakaMark({ size = 48, animated = true, title, neutral }) {
2344
2492
  const { theme } = useTheme();
2345
- const { Animated: Animated22, layer, spinStyle, pulseStyle } = useMarkMotion(size, animated);
2493
+ const { Animated: Animated25, layer, spinStyle, pulseStyle } = useMarkMotion(size, animated);
2346
2494
  const id = useSvgId("kzm");
2347
2495
  const viewBox = size < 48 ? KRIZAKA.croppedViewBox : KRIZAKA.viewBox;
2348
2496
  const stroke = neutral ?? theme.textMuted;
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 })
2497
+ const blue = /* @__PURE__ */ jsx25(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__ */ jsx25(Stop3, { offset, stopColor: color }, offset)) });
2498
+ const dot = (c) => /* @__PURE__ */ jsxs22(Fragment5, { children: [
2499
+ /* @__PURE__ */ jsx25(Circle2, { cx: c.cx, cy: c.cy, r: c.r, fill: `url(#${id}b)` }),
2500
+ /* @__PURE__ */ jsx25(Circle2, { cx: c.cx, cy: c.cy, r: c.inner, fill: KRIZAKA.highlight })
2353
2501
  ] });
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 })
2502
+ return /* @__PURE__ */ jsxs22(View21, { style: { width: size, height: size }, ...markA11y(title), children: [
2503
+ /* @__PURE__ */ jsxs22(Svg8, { viewBox, style: layer, children: [
2504
+ /* @__PURE__ */ jsxs22(Defs3, { children: [
2505
+ /* @__PURE__ */ jsxs22(RadialGradient, { id: `${id}g`, cx: "50%", cy: "50%", r: "50%", children: [
2506
+ /* @__PURE__ */ jsx25(Stop3, { offset: "0%", stopColor: KRIZAKA.glow.color, stopOpacity: KRIZAKA.glow.opacity }),
2507
+ /* @__PURE__ */ jsx25(Stop3, { offset: "100%", stopColor: KRIZAKA.glow.color, stopOpacity: 0 })
2360
2508
  ] }),
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 })
2509
+ /* @__PURE__ */ jsxs22(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: [
2510
+ /* @__PURE__ */ jsx25(Stop3, { offset: "0%", stopColor: theme.textSecondary }),
2511
+ /* @__PURE__ */ jsx25(Stop3, { offset: "100%", stopColor: theme.textPrimary })
2364
2512
  ] }),
2365
2513
  blue
2366
2514
  ] }),
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" }) })
2515
+ size >= 48 ? /* @__PURE__ */ jsx25(Circle2, { cx: 200, cy: 200, r: 190, fill: `url(#${id}g)` }) : null,
2516
+ /* @__PURE__ */ jsx25(Circle2, { cx: 200, cy: 200, r: KRIZAKA.ring.r, stroke, strokeWidth: KRIZAKA.ring.width, opacity: 0.35, fill: "none" }),
2517
+ /* @__PURE__ */ jsx25(Group, { transform: `translate(${KRIZAKA.offset} ${KRIZAKA.offset})`, children: /* @__PURE__ */ jsx25(Path6, { d: KRIZAKA.shield, stroke: `url(#${id}i)`, strokeWidth: KRIZAKA.stroke, strokeLinecap: "round", strokeLinejoin: "round", fill: "none" }) })
2370
2518
  ] }),
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: [
2519
+ /* @__PURE__ */ jsx25(Animated25.View, { style: [layer, spinStyle], children: /* @__PURE__ */ jsx25(Svg8, { viewBox, style: layer, children: /* @__PURE__ */ jsx25(Circle2, { cx: 200, cy: 200, r: KRIZAKA.orbit.r, stroke, strokeWidth: KRIZAKA.orbit.width, strokeDasharray: KRIZAKA.orbit.dash, opacity: 0.6, fill: "none" }) }) }),
2520
+ /* @__PURE__ */ jsx25(Animated25.View, { style: [layer, pulseStyle], children: /* @__PURE__ */ jsxs22(Svg8, { viewBox, style: layer, children: [
2521
+ /* @__PURE__ */ jsx25(Defs3, { children: blue }),
2522
+ /* @__PURE__ */ jsxs22(Group, { transform: `translate(${KRIZAKA.offset} ${KRIZAKA.offset})`, children: [
2375
2523
  dot(KRIZAKA.node),
2376
2524
  dot(KRIZAKA.core)
2377
2525
  ] })
@@ -2380,38 +2528,38 @@ function KrizakaMark({ size = 48, animated = true, title, neutral }) {
2380
2528
  }
2381
2529
 
2382
2530
  // 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";
2531
+ import * as React20 from "react";
2532
+ import { AccessibilityInfo as AccessibilityInfo6, Animated as Animated10, Easing as Easing4, StyleSheet as StyleSheet24, View as View22 } from "react-native";
2533
+ import Svg9, { Circle as Circle3, Path as Path7 } from "react-native-svg";
2534
+ import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
2387
2535
  var HEX = "M12 3 19.79 7.5 19.79 16.5 12 21 4.21 16.5 4.21 7.5Z";
2388
2536
  var PERIMETER = 54;
2389
2537
  function LoaderGlyph({ state = "loading", value, size = 20, color }) {
2390
2538
  const { theme } = useTheme();
2391
2539
  const reduce = useReducedMotion();
2392
- const [spin] = React19.useState(() => new Animated9.Value(0));
2540
+ const [spin] = React20.useState(() => new Animated10.Value(0));
2393
2541
  const known = typeof value === "number" && Number.isFinite(value);
2394
- React19.useEffect(() => {
2542
+ React20.useEffect(() => {
2395
2543
  if (state !== "loading" || known || reduce) return;
2396
- const loop = Animated9.loop(Animated9.timing(spin, { toValue: 1, duration: 1400, easing: Easing3.linear, useNativeDriver: true }));
2544
+ const loop = Animated10.loop(Animated10.timing(spin, { toValue: 1, duration: 1400, easing: Easing4.linear, useNativeDriver: true }));
2397
2545
  loop.start();
2398
2546
  return () => loop.stop();
2399
2547
  }, [state, known, reduce, spin]);
2400
2548
  const stroke = color ?? (state === "success" ? theme.success : state === "error" ? theme.danger : theme.accent);
2401
2549
  const fill = state !== "loading" ? 1 : known ? Math.min(1, Math.max(0, value)) : 0.3;
2402
2550
  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
2551
+ return /* @__PURE__ */ jsx26(Animated10.View, { "aria-hidden": true, style: { width: size, height: size, transform: state === "loading" && !known ? [{ rotate }] : [] }, children: /* @__PURE__ */ jsxs23(Svg9, { width: size, height: size, viewBox: "0 0 24 24", fill: "none", children: [
2552
+ /* @__PURE__ */ jsx26(Path7, { d: HEX, stroke, strokeOpacity: 0.22, strokeWidth: 2.2, strokeLinejoin: "round" }),
2553
+ /* @__PURE__ */ jsx26(Path7, { d: HEX, stroke, strokeWidth: 2.2, strokeLinejoin: "round", strokeLinecap: "round", strokeDasharray: `${fill * PERIMETER} ${PERIMETER}` }),
2554
+ state === "loading" ? /* @__PURE__ */ jsx26(Circle3, { cx: 12, cy: 12, r: 2.6, fill: stroke }) : null,
2555
+ state === "success" ? /* @__PURE__ */ jsx26(Path7, { d: "M8.3 12.3l2.6 2.6 4.9-5.3", stroke, strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round" }) : null,
2556
+ state === "error" ? /* @__PURE__ */ jsx26(Path7, { d: "M9.4 9.4l5.2 5.2M14.6 9.4l-5.2 5.2", stroke, strokeWidth: 2.2, strokeLinecap: "round" }) : null
2409
2557
  ] }) });
2410
2558
  }
2411
2559
  function useDelayedWait(active, delay = 250, minDuration = 600) {
2412
- const [shown, setShown] = React19.useState(false);
2413
- const since = React19.useRef(0);
2414
- React19.useEffect(() => {
2560
+ const [shown, setShown] = React20.useState(false);
2561
+ const since = React20.useRef(0);
2562
+ React20.useEffect(() => {
2415
2563
  if (active && !shown) {
2416
2564
  const timer2 = setTimeout(() => {
2417
2565
  since.current = Date.now();
@@ -2431,9 +2579,9 @@ var GLYPH = { inline: 20, block: 36, overlay: 36, page: 56 };
2431
2579
  function Loader({ label, status = "loading", successLabel, errorLabel, value, eta, delay = 250, minDuration = 600, endDuration = 1600, variant = "inline", style }) {
2432
2580
  const { theme, radius: radius3 } = useTheme();
2433
2581
  const waiting = useDelayedWait(status === "loading", delay, minDuration);
2434
- const [ending, setEnding] = React19.useState(null);
2435
- const seen = React19.useRef(false);
2436
- React19.useEffect(() => {
2582
+ const [ending, setEnding] = React20.useState(null);
2583
+ const seen = React20.useRef(false);
2584
+ React20.useEffect(() => {
2437
2585
  if (waiting) {
2438
2586
  seen.current = true;
2439
2587
  return;
@@ -2450,29 +2598,29 @@ function Loader({ label, status = "loading", successLabel, errorLabel, value, et
2450
2598
  }, [waiting, status, endDuration]);
2451
2599
  const phase = waiting ? "loading" : ending;
2452
2600
  const words = phase === "success" ? successLabel ?? label : phase === "error" ? errorLabel ?? label : label;
2453
- React19.useEffect(() => {
2601
+ React20.useEffect(() => {
2454
2602
  if (phase) AccessibilityInfo6.announceForAccessibility(words);
2455
2603
  }, [phase, words]);
2456
2604
  if (!phase) return null;
2457
2605
  const known = phase === "loading" && typeof value === "number" && Number.isFinite(value);
2458
2606
  const detail = phase === "loading" ? [known ? `${Math.round(Math.min(1, Math.max(0, value)) * 100)} %` : null, eta].filter(Boolean).join(" \xB7 ") : "";
2459
2607
  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
2608
+ const box = /* @__PURE__ */ jsxs23(View22, { style: [stacked ? styles24.stacked : styles24.inline, variant === "overlay" ? { backgroundColor: alpha(theme.surface1, 0.92), borderColor: theme.borderDefault, borderRadius: radius3.lg, ...styles24.card } : null], children: [
2609
+ /* @__PURE__ */ jsx26(LoaderGlyph, { state: phase, value: known ? value : null, size: GLYPH[variant] }),
2610
+ /* @__PURE__ */ jsxs23(View22, { style: stacked ? styles24.center : styles24.text, children: [
2611
+ /* @__PURE__ */ jsx26(Txt, { variant: variant === "page" ? "title" : "label", style: stacked ? styles24.centered : null, children: words }),
2612
+ detail ? /* @__PURE__ */ jsx26(Txt, { variant: "caption", tone: "secondary", style: stacked ? styles24.centered : null, children: detail }) : null
2465
2613
  ] })
2466
2614
  ] });
2467
2615
  const a11y = { accessible: true, role: "progressbar", "aria-label": words, "aria-busy": phase === "loading", accessibilityLiveRegion: "polite" };
2468
2616
  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 });
2617
+ return /* @__PURE__ */ jsx26(View22, { ...a11y, style: [StyleSheet24.absoluteFill, styles24.cover, variant === "page" ? { backgroundColor: alpha(theme.surface0, 0.86) } : null, style], children: box });
2618
+ return /* @__PURE__ */ jsx26(View22, { ...a11y, style: [variant === "block" ? styles24.block : null, style], children: box });
2471
2619
  }
2472
- var styles23 = StyleSheet23.create({
2620
+ var styles24 = StyleSheet24.create({
2473
2621
  inline: { flexDirection: "row", alignItems: "center", gap: 10 },
2474
2622
  stacked: { alignItems: "center", gap: 10 },
2475
- card: { paddingHorizontal: 24, paddingVertical: 20, borderWidth: StyleSheet23.hairlineWidth },
2623
+ card: { paddingHorizontal: 24, paddingVertical: 20, borderWidth: StyleSheet24.hairlineWidth },
2476
2624
  text: { flexShrink: 1, gap: 2 },
2477
2625
  center: { alignItems: "center", gap: 2 },
2478
2626
  centered: { textAlign: "center" },
@@ -2481,13 +2629,13 @@ var styles23 = StyleSheet23.create({
2481
2629
  });
2482
2630
 
2483
2631
  // src/native/mascot-state.tsx
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";
2632
+ import * as React22 from "react";
2633
+ import { AccessibilityInfo as AccessibilityInfo8, Animated as Animated12, Easing as Easing6, StyleSheet as StyleSheet25, View as View24 } from "react-native";
2486
2634
 
2487
2635
  // src/native/mascots.tsx
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";
2636
+ import { useEffect as useEffect13, useState as useState21 } from "react";
2637
+ import { AccessibilityInfo as AccessibilityInfo7, Animated as Animated11, Easing as Easing5, View as View23 } from "react-native";
2638
+ import Svg10, { Circle as Circle4, Defs as Defs4, Ellipse, G, LinearGradient as LinearGradient4, Path as Path8, Rect as Rect2, Stop as Stop4 } from "react-native-svg";
2491
2639
 
2492
2640
  // src/mascots/geometry.ts
2493
2641
  var mirror = (d) => d.replace(/(-?\d+(?:\.\d+)?) (-?\d+(?:\.\d+)?)/g, (_, x, y) => `${120 - Number(x)} ${y}`);
@@ -2645,17 +2793,17 @@ var SHADE = "#000000";
2645
2793
  var PARCEL = ["#f59e0b", "#d97706", "#b45309"];
2646
2794
 
2647
2795
  // src/native/mascots.tsx
2648
- import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
2796
+ import { jsx as jsx27, jsxs as jsxs24 } from "react/jsx-runtime";
2649
2797
  function useBob(animated) {
2650
- const [y] = useState20(() => new Animated10.Value(0));
2651
- useEffect12(() => {
2798
+ const [y] = useState21(() => new Animated11.Value(0));
2799
+ useEffect13(() => {
2652
2800
  if (!animated) return;
2653
2801
  let loop;
2654
2802
  let cancelled = false;
2655
2803
  void AccessibilityInfo7.isReduceMotionEnabled().then((reduce) => {
2656
2804
  if (reduce || cancelled) return;
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)]));
2805
+ const step = (toValue) => Animated11.timing(y, { toValue, duration: 1800, easing: Easing5.inOut(Easing5.ease), useNativeDriver: true });
2806
+ loop = Animated11.loop(Animated11.sequence([step(-2.5), step(0)]));
2659
2807
  loop.start();
2660
2808
  });
2661
2809
  return () => {
@@ -2679,62 +2827,62 @@ function Mascot({ bird = "owl", mood = "welcome", tone: tone3 = "brand", size =
2679
2827
  const look3 = mood === "thinking" ? 1.4 : 0;
2680
2828
  const rot = (deg, [x, y]) => `rotate(${deg} ${x} ${y})`;
2681
2829
  const [wl, wr] = g.wings;
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 })
2830
+ return /* @__PURE__ */ jsx27(View23, { style: [{ width: size, height: size }, style], ...markA11y(title), children: /* @__PURE__ */ jsx27(Animated11.View, { style: { transform: [{ translateY: bob }] }, children: /* @__PURE__ */ jsxs24(Svg10, { width: size, height: size, viewBox: "0 0 120 120", children: [
2831
+ /* @__PURE__ */ jsx27(Defs4, { children: /* @__PURE__ */ jsxs24(LinearGradient4, { id, x1: "0", y1: "0", x2: "0", y2: "1", children: [
2832
+ /* @__PURE__ */ jsx27(Stop4, { offset: "0%", stopColor: p.from }),
2833
+ /* @__PURE__ */ jsx27(Stop4, { offset: "100%", stopColor: p.to })
2686
2834
  ] }) }),
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 }),
2835
+ /* @__PURE__ */ jsx27(Ellipse, { cx: g.shadow[0], cy: g.shadow[1], rx: g.shadow[2], ry: g.shadow[3], fill: SHADE, opacity: 0.14 }),
2836
+ mood === "empty" && /* @__PURE__ */ jsx27(Path8, { d: MOOD_PARTS.tray, stroke: outline, strokeWidth: 1.6, strokeDasharray: "3 3", fill: "none" }),
2837
+ g.legs.map((d) => /* @__PURE__ */ jsx27(Path8, { d, stroke: p.beak, strokeWidth: 2.6, strokeLinecap: "round", fill: "none" }, d)),
2838
+ g.back?.map((d) => d.endsWith("Z") ? /* @__PURE__ */ jsx27(Path8, { d, fill: p.detail, ...line }, d) : /* @__PURE__ */ jsx27(Path8, { d, stroke: outline, strokeWidth: 1.4, fill: "none" }, d)),
2839
+ g.parcel?.map((d, i) => /* @__PURE__ */ jsx27(Path8, { d, fill: PARCEL[i], ...line }, d)),
2840
+ /* @__PURE__ */ jsx27(Path8, { d: g.body, fill: body, ...line }),
2841
+ /* @__PURE__ */ jsx27(Path8, { d: g.belly, fill: LIGHT, opacity: 0.28 }),
2694
2842
  [wl, wr].map((w, i) => {
2695
2843
  const turn = mood === "success" ? i === 0 ? 28 : -28 : mood === "welcome" && i === 1 ? -20 : 0;
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 })
2844
+ return /* @__PURE__ */ jsxs24(G, { transform: turn ? rot(turn, w.pivot) : void 0, children: [
2845
+ /* @__PURE__ */ jsx27(Path8, { d: w.d, fill: p.wing, ...line }),
2846
+ /* @__PURE__ */ jsx27(Path8, { d: w.d, fill: SHADE, opacity: 0.16 })
2699
2847
  ] }, i);
2700
2848
  }),
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 }),
2849
+ g.neck && /* @__PURE__ */ jsx27(Path8, { d: g.neck.d, stroke: body, strokeWidth: g.neck.width, strokeLinecap: "round", fill: "none" }),
2850
+ g.head.r > 0 && /* @__PURE__ */ jsx27(Circle4, { cx: g.head.cx, cy: g.head.cy, r: g.head.r, fill: body, ...line }),
2851
+ g.details.map((d) => /* @__PURE__ */ jsx27(Path8, { d, fill: p.detail, ...line }, d)),
2852
+ g.visor && /* @__PURE__ */ jsx27(Rect2, { x: g.visor.x, y: g.visor.y, width: g.visor.w, height: g.visor.h, rx: 4, fill: theme.surface0, ...line }),
2705
2853
  g.eyes.at.map(
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 })
2854
+ (at, i) => mood === "empty" && g.eyes.white > 0 ? /* @__PURE__ */ jsxs24(G, { children: [
2855
+ /* @__PURE__ */ jsx27(Circle4, { cx: at[0], cy: at[1], r: g.eyes.white, fill: LIGHT, ...line }),
2856
+ /* @__PURE__ */ jsx27(Circle4, { cx: at[0], cy: at[1] + g.eyes.pupil * 0.7, r: g.eyes.pupil, fill: SHADE }),
2857
+ /* @__PURE__ */ jsx27(Path8, { d: upperLid(at, g.eyes.white), fill: p.detail, ...line })
2858
+ ] }, i) : mood === "success" || mood === "empty" ? /* @__PURE__ */ jsx27(Path8, { 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__ */ jsxs24(G, { children: [
2859
+ g.eyes.white > 0 && /* @__PURE__ */ jsx27(Circle4, { cx: at[0], cy: at[1], r: g.eyes.white, fill: LIGHT, ...line }),
2860
+ /* @__PURE__ */ jsx27(Circle4, { cx: at[0] + look3, cy: at[1] - look3, r: g.eyes.pupil, fill: g.visor ? p.eye : SHADE })
2713
2861
  ] }, i)
2714
2862
  ),
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 })
2863
+ g.glasses && g.eyes.at.map(([x, y]) => /* @__PURE__ */ jsx27(Circle4, { cx: x, cy: y, r: 6.5, fill: "none", stroke: outline, strokeWidth: 1.3 }, x)),
2864
+ mood === "error" && g.eyes.at.map((at, i) => /* @__PURE__ */ jsx27(Path8, { d: brow(at, eyeR, g.eyes.at.length === 1 ? 1 : i === 0 ? -1 : 1), stroke: outline, strokeWidth: 2, strokeLinecap: "round" }, i)),
2865
+ /* @__PURE__ */ jsx27(Path8, { d: g.beak, fill: p.beak, ...line }),
2866
+ mood === "thinking" && MOOD_PARTS.dots.map(([cx, cy, r], i) => /* @__PURE__ */ jsx27(Circle4, { cx, cy, r, fill: theme.textSecondary, opacity: 0.5 + i * 0.25 }, cx)),
2867
+ (mood === "success" || mood === "error") && /* @__PURE__ */ jsx27(Circle4, { cx: MOOD_PARTS.badge.cx, cy: MOOD_PARTS.badge.cy, r: MOOD_PARTS.badge.r, fill: mood === "success" ? theme.success : theme.danger }),
2868
+ mood === "success" && /* @__PURE__ */ jsx27(Path8, { d: MOOD_PARTS.check, stroke: theme.surface0, strokeWidth: 2.6, strokeLinecap: "round", strokeLinejoin: "round", fill: "none" }),
2869
+ mood === "error" && /* @__PURE__ */ jsx27(Path8, { d: MOOD_PARTS.bang.line, stroke: theme.surface0, strokeWidth: 2.8, strokeLinecap: "round" }),
2870
+ mood === "error" && /* @__PURE__ */ jsx27(Circle4, { cx: MOOD_PARTS.bang.dot[0], cy: MOOD_PARTS.bang.dot[1], r: 1.6, fill: theme.surface0 })
2723
2871
  ] }) }) });
2724
2872
  }
2725
2873
 
2726
2874
  // src/native/mascot-state.tsx
2727
- import { jsx as jsx27, jsxs as jsxs24 } from "react/jsx-runtime";
2875
+ import { jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
2728
2876
  var SIZE = { sm: 64, md: 96, lg: 128 };
2729
2877
  function useArrival(animated) {
2730
- const [value] = React21.useState(() => new Animated11.Value(animated ? 0 : 1));
2731
- React21.useEffect(() => {
2878
+ const [value] = React22.useState(() => new Animated12.Value(animated ? 0 : 1));
2879
+ React22.useEffect(() => {
2732
2880
  if (!animated) return;
2733
2881
  let cancelled = false;
2734
2882
  void AccessibilityInfo8.isReduceMotionEnabled().then((reduce) => {
2735
2883
  if (cancelled) return;
2736
2884
  if (reduce) value.setValue(1);
2737
- else Animated11.timing(value, { toValue: 1, duration: 420, easing: Easing5.out(Easing5.cubic), useNativeDriver: true }).start();
2885
+ else Animated12.timing(value, { toValue: 1, duration: 420, easing: Easing6.out(Easing6.cubic), useNativeDriver: true }).start();
2738
2886
  });
2739
2887
  return () => {
2740
2888
  cancelled = true;
@@ -2745,30 +2893,30 @@ function useArrival(animated) {
2745
2893
  function MascotState({ bird = "owl", mood = "empty", title, description, action, size = "md", layout = "stacked", tone: tone3, animated = true, style, ...props }) {
2746
2894
  const opacity = useArrival(animated);
2747
2895
  const inline = layout === "inline";
2748
- return /* @__PURE__ */ jsxs24(
2749
- Animated11.View,
2896
+ return /* @__PURE__ */ jsxs25(
2897
+ Animated12.View,
2750
2898
  {
2751
2899
  role: mood === "error" ? "alert" : "status",
2752
2900
  accessibilityLiveRegion: mood === "error" ? "assertive" : "polite",
2753
2901
  "aria-busy": mood === "thinking" ? true : void 0,
2754
2902
  ...props,
2755
- style: [inline ? styles24.inline : styles24.stacked, { opacity, transform: [{ translateY: opacity.interpolate({ inputRange: [0, 1], outputRange: [6, 0] }) }] }, style],
2903
+ style: [inline ? styles25.inline : styles25.stacked, { opacity, transform: [{ translateY: opacity.interpolate({ inputRange: [0, 1], outputRange: [6, 0] }) }] }, style],
2756
2904
  children: [
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
2905
+ /* @__PURE__ */ jsx28(Mascot, { bird, mood, tone: tone3, size: SIZE[size], animated }),
2906
+ /* @__PURE__ */ jsxs25(View24, { style: inline ? styles25.wordsInline : styles25.words, children: [
2907
+ /* @__PURE__ */ jsx28(Txt, { variant: "label", role: "heading", style: inline ? null : styles25.center, children: title }),
2908
+ description ? /* @__PURE__ */ jsx28(Txt, { tone: "secondary", style: inline ? null : styles25.center, children: description }) : null,
2909
+ action ? /* @__PURE__ */ jsx28(View24, { style: [styles25.action, inline ? null : styles25.actionCentred], children: action }) : null
2762
2910
  ] })
2763
2911
  ]
2764
2912
  }
2765
2913
  );
2766
2914
  }
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({
2915
+ var ErrorState = (props) => /* @__PURE__ */ jsx28(MascotState, { mood: "error", ...props });
2916
+ var SuccessState = (props) => /* @__PURE__ */ jsx28(MascotState, { mood: "success", ...props });
2917
+ var LoadingState = (props) => /* @__PURE__ */ jsx28(MascotState, { mood: "thinking", ...props });
2918
+ var WelcomeState = (props) => /* @__PURE__ */ jsx28(MascotState, { mood: "welcome", ...props });
2919
+ var styles25 = StyleSheet25.create({
2772
2920
  stacked: { alignItems: "center", justifyContent: "center", gap: 12, paddingVertical: 40, paddingHorizontal: 24 },
2773
2921
  inline: { flexDirection: "row", alignItems: "center", gap: 16 },
2774
2922
  words: { alignItems: "center", gap: 6 },
@@ -2778,10 +2926,70 @@ var styles24 = StyleSheet24.create({
2778
2926
  actionCentred: { justifyContent: "center" }
2779
2927
  });
2780
2928
 
2929
+ // src/native/match-dialog.tsx
2930
+ import * as React23 from "react";
2931
+ import { AccessibilityInfo as AccessibilityInfo9, Animated as Animated13, Easing as Easing7, Modal as Modal4, Pressable as Pressable14, StyleSheet as StyleSheet26, View as View25 } from "react-native";
2932
+ import Svg11, { Path as Path9 } from "react-native-svg";
2933
+ import { jsx as jsx29, jsxs as jsxs26 } from "react/jsx-runtime";
2934
+ function MatchDialog({ open, onOpenChange, title, description, people, primaryLabel, onPrimary, secondaryLabel }) {
2935
+ const { theme, haptic } = useTheme();
2936
+ const reduce = useReducedMotion();
2937
+ const [t] = React23.useState(() => new Animated13.Value(0));
2938
+ React23.useEffect(() => {
2939
+ if (!open) return;
2940
+ haptic("success");
2941
+ AccessibilityInfo9.announceForAccessibility([title, description].filter(Boolean).join(". "));
2942
+ if (reduce) return;
2943
+ t.setValue(0);
2944
+ Animated13.timing(t, { toValue: 1, duration: 520, easing: Easing7.out(Easing7.back(1.6)), useNativeDriver: true }).start();
2945
+ }, [open]);
2946
+ React23.useEffect(() => {
2947
+ if (open && reduce) {
2948
+ t.stopAnimation();
2949
+ t.setValue(1);
2950
+ }
2951
+ }, [open, reduce, t]);
2952
+ const side = (dir) => ({ transform: [{ translateX: t.interpolate({ inputRange: [0, 1], outputRange: [dir * 110, dir * 50] }) }, { rotate: dir === -1 ? "-8deg" : "8deg" }] });
2953
+ return /* @__PURE__ */ jsx29(Modal4, { ...modalName(title), visible: open, transparent: true, animationType: reduce ? "none" : "fade", onRequestClose: () => onOpenChange(false), statusBarTranslucent: true, children: /* @__PURE__ */ jsxs26(View25, { accessibilityViewIsModal: true, style: [styles26.screen, { backgroundColor: theme.accent }], children: [
2954
+ /* @__PURE__ */ jsx29(View25, { style: [StyleSheet26.absoluteFill, { backgroundColor: theme.accent2, opacity: 0.55 }] }),
2955
+ /* @__PURE__ */ jsx29(Txt, { variant: "display", tone: "onAccent", style: styles26.title, children: title }),
2956
+ description ? /* @__PURE__ */ jsx29(Txt, { tone: "onAccent", style: styles26.center, children: description }) : null,
2957
+ /* @__PURE__ */ jsxs26(View25, { style: styles26.pair, "aria-hidden": true, children: [
2958
+ /* @__PURE__ */ jsx29(Animated13.View, { style: [styles26.photo, side(-1), { borderColor: theme.onAccent }], children: /* @__PURE__ */ jsx29(Avatar, { src: people[0].src, alt: "", fallback: people[0].name.charAt(0), size: 112 }) }),
2959
+ /* @__PURE__ */ jsx29(Animated13.View, { style: [styles26.photo, side(1), { borderColor: theme.onAccent }], children: /* @__PURE__ */ jsx29(Avatar, { src: people[1].src, alt: "", fallback: people[1].name.charAt(0), size: 112 }) }),
2960
+ /* @__PURE__ */ jsx29(Animated13.View, { style: [styles26.heart, { backgroundColor: theme.onAccent, transform: [{ scale: t }] }], children: /* @__PURE__ */ jsx29(Svg11, { width: 26, height: 26, viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx29(Path9, { d: "M12 20s-7-4.4-7-10a4 4 0 0 1 7-2.6A4 4 0 0 1 19 10c0 5.6-7 10-7 10z", fill: theme.accent }) }) })
2961
+ ] }),
2962
+ /* @__PURE__ */ jsxs26(View25, { style: styles26.actions, children: [
2963
+ /* @__PURE__ */ jsx29(
2964
+ Button,
2965
+ {
2966
+ label: primaryLabel,
2967
+ size: "lg",
2968
+ onPress: () => {
2969
+ onOpenChange(false);
2970
+ onPrimary();
2971
+ }
2972
+ }
2973
+ ),
2974
+ /* @__PURE__ */ jsx29(Pressable14, { role: "button", onPress: () => onOpenChange(false), style: ({ pressed }) => [styles26.secondary, { borderColor: theme.onAccent, opacity: pressed ? 0.8 : 1 }], children: /* @__PURE__ */ jsx29(Txt, { variant: "label", tone: "onAccent", children: secondaryLabel }) })
2975
+ ] })
2976
+ ] }) });
2977
+ }
2978
+ var styles26 = StyleSheet26.create({
2979
+ screen: { flex: 1, alignItems: "center", justifyContent: "center", gap: 12, padding: 32 },
2980
+ title: { textAlign: "center", fontSize: 40, lineHeight: 46 },
2981
+ center: { textAlign: "center", maxWidth: 300 },
2982
+ pair: { flexDirection: "row", alignItems: "center", justifyContent: "center", height: 170, marginVertical: 24, width: 300 },
2983
+ photo: { position: "absolute", borderWidth: 4, borderRadius: 64 },
2984
+ heart: { position: "absolute", bottom: 4, width: 48, height: 48, borderRadius: 24, alignItems: "center", justifyContent: "center" },
2985
+ actions: { alignSelf: "stretch", gap: 10, maxWidth: 360, width: "100%" },
2986
+ secondary: { minHeight: 48, borderRadius: 999, borderWidth: 1.5, alignItems: "center", justifyContent: "center" }
2987
+ });
2988
+
2781
2989
  // 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";
2990
+ import { StyleSheet as StyleSheet27, View as View26 } from "react-native";
2991
+ import Svg12, { Circle as Circle5 } from "react-native-svg";
2992
+ import { jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
2785
2993
  var THICK = { sm: 6, md: 8, lg: 12 };
2786
2994
  var RING = { sm: 56, md: 96, lg: 144 };
2787
2995
  var partColor = (t, i) => [t.accent, t.warning, t.success, t.textSecondary, t.danger][i % 5];
@@ -2794,10 +3002,10 @@ function Meter({ label, value = 0, min = 0, max = 100, valueText, thresholds, op
2794
3002
  const words = valueText ?? `${Math.round(ratio * 100)} %`;
2795
3003
  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
3004
  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 })
3005
+ const legend = parts ? /* @__PURE__ */ jsx30(View26, { style: styles27.legend, "aria-hidden": true, children: shares.map((p, i) => /* @__PURE__ */ jsxs27(View26, { style: styles27.legendItem, children: [
3006
+ /* @__PURE__ */ jsx30(View26, { style: [styles27.swatch, { backgroundColor: p.color }] }),
3007
+ /* @__PURE__ */ jsx30(Txt, { variant: "caption", children: p.label }),
3008
+ /* @__PURE__ */ jsx30(Txt, { variant: "caption", tone: "secondary", children: p.words })
2801
3009
  ] }, i)) }) : null;
2802
3010
  if (variant === "ring") {
2803
3011
  const side = RING[size];
@@ -2809,27 +3017,27 @@ function Meter({ label, value = 0, min = 0, max = 100, valueText, thresholds, op
2809
3017
  offset += p.ratio;
2810
3018
  return arc;
2811
3019
  }) : [{ 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))
3020
+ return /* @__PURE__ */ jsxs27(View26, { accessible: true, ...a11y, style: [styles27.ringRoot, style], children: [
3021
+ /* @__PURE__ */ jsxs27(View26, { style: { width: side, height: side }, children: [
3022
+ /* @__PURE__ */ jsxs27(Svg12, { width: side, height: side, viewBox: "0 0 100 100", style: { transform: [{ rotate: "-90deg" }] }, children: [
3023
+ /* @__PURE__ */ jsx30(Circle5, { cx: 50, cy: 50, r, fill: "none", stroke: theme.borderDefault, strokeWidth: 9 }),
3024
+ arcs.map((a, i) => /* @__PURE__ */ jsx30(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
3025
  ] }),
2818
- children !== void 0 ? /* @__PURE__ */ jsx28(View24, { style: [StyleSheet25.absoluteFill, styles25.center], children }) : null
3026
+ children !== void 0 ? /* @__PURE__ */ jsx30(View26, { style: [StyleSheet27.absoluteFill, styles27.center], children }) : null
2819
3027
  ] }),
2820
3028
  legend
2821
3029
  ] });
2822
3030
  }
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
3031
+ return /* @__PURE__ */ jsxs27(View26, { accessible: true, ...a11y, style: [styles27.root, style], children: [
3032
+ showLabel ? /* @__PURE__ */ jsxs27(View26, { style: styles27.header, "aria-hidden": true, children: [
3033
+ /* @__PURE__ */ jsx30(Txt, { variant: "caption", numberOfLines: 1, style: styles27.caption, children: label }),
3034
+ !parts ? /* @__PURE__ */ jsx30(Txt, { variant: "caption", tone: "secondary", children: words }) : null
2827
3035
  ] }) : 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 }] }) }),
3036
+ /* @__PURE__ */ jsx30(View26, { style: [styles27.track, { height: THICK[size], backgroundColor: theme.surface3 }], children: parts ? shares.map((p, i) => /* @__PURE__ */ jsx30(View26, { style: { width: `${p.ratio * 100}%`, backgroundColor: p.color } }, i)) : /* @__PURE__ */ jsx30(View26, { style: [styles27.fill, { width: `${ratio * 100}%`, backgroundColor: tone3 }] }) }),
2829
3037
  legend
2830
3038
  ] });
2831
3039
  }
2832
- var styles25 = StyleSheet25.create({
3040
+ var styles27 = StyleSheet27.create({
2833
3041
  root: { width: "100%", gap: 6 },
2834
3042
  header: { flexDirection: "row", alignItems: "baseline", gap: 8 },
2835
3043
  caption: { flex: 1, fontWeight: "600" },
@@ -2843,48 +3051,48 @@ var styles25 = StyleSheet25.create({
2843
3051
  });
2844
3052
 
2845
3053
  // 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";
3054
+ import * as React24 from "react";
3055
+ import { AccessibilityInfo as AccessibilityInfo10, Animated as Animated14, Easing as Easing8, Text as Text13 } from "react-native";
3056
+ import { jsx as jsx31 } from "react/jsx-runtime";
2849
3057
  function NumberTicker({ value, locale, format, trigger = "mount", duration = 1100, announce, variant = "display", tone: tone3 = "text", style }) {
2850
3058
  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(() => {
3059
+ const writer = React24.useMemo(() => new Intl.NumberFormat(locale, format), [locale, format]);
3060
+ const [shown, setShown] = React24.useState(() => reduce ? value : trigger === "mount" ? 0 : value);
3061
+ const [anim] = React24.useState(() => new Animated14.Value(trigger === "mount" ? 0 : value));
3062
+ const first = React24.useRef(true);
3063
+ React24.useEffect(() => {
2856
3064
  const isFirst = first.current;
2857
3065
  first.current = false;
2858
3066
  if (reduce || !isFirst && trigger === "mount" || isFirst && trigger === "change") {
2859
3067
  anim.setValue(value);
2860
3068
  setShown(value);
2861
- if (!isFirst && announce) AccessibilityInfo9.announceForAccessibility(writer.format(value));
3069
+ if (!isFirst && announce) AccessibilityInfo10.announceForAccessibility(writer.format(value));
2862
3070
  return;
2863
3071
  }
2864
3072
  const id = anim.addListener(({ value: v }) => setShown(v));
2865
- const run = Animated12.timing(anim, { toValue: value, duration, easing: Easing6.out(Easing6.cubic), useNativeDriver: false });
3073
+ const run = Animated14.timing(anim, { toValue: value, duration, easing: Easing8.out(Easing8.cubic), useNativeDriver: false });
2866
3074
  run.start(({ finished }) => {
2867
3075
  if (finished) setShown(value);
2868
3076
  });
2869
- if (!isFirst && announce) AccessibilityInfo9.announceForAccessibility(writer.format(value));
3077
+ if (!isFirst && announce) AccessibilityInfo10.announceForAccessibility(writer.format(value));
2870
3078
  return () => {
2871
3079
  run.stop();
2872
3080
  anim.removeListener(id);
2873
3081
  };
2874
3082
  }, [value, reduce, trigger, duration, announce, anim, writer]);
2875
3083
  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) }) });
3084
+ return /* @__PURE__ */ jsx31(Txt, { variant, tone: tone3, "aria-label": writer.format(value), style: [{ fontVariant: ["tabular-nums"] }, style], children: /* @__PURE__ */ jsx31(Text13, { "aria-hidden": true, children: writer.format(digits) }) });
2877
3085
  }
2878
3086
 
2879
3087
  // 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";
3088
+ import * as React25 from "react";
3089
+ import { ScrollView as ScrollView5, StyleSheet as StyleSheet28, View as View27 } from "react-native";
3090
+ import { jsx as jsx32, jsxs as jsxs28 } from "react/jsx-runtime";
2883
3091
  function Onboarding({ slides, labels, onDone, style }) {
2884
3092
  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);
3093
+ const [width, setWidth] = React25.useState(0);
3094
+ const [page, setPage] = React25.useState(0);
3095
+ const scroller = React25.useRef(null);
2888
3096
  const last = page === slides.length - 1;
2889
3097
  const go = (to) => {
2890
3098
  scroller.current?.scrollTo({ x: to * width, animated: true });
@@ -2894,18 +3102,18 @@ function Onboarding({ slides, labels, onDone, style }) {
2894
3102
  const onScroll = (e) => {
2895
3103
  if (width > 0) setPage(Math.round(e.nativeEvent.contentOffset.x / width));
2896
3104
  };
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 })
3105
+ return /* @__PURE__ */ jsxs28(View27, { style: [styles28.root, { backgroundColor: theme.surface0, paddingTop: insets.top + 8, paddingBottom: insets.bottom + 16 }, style], onLayout: (e) => setWidth(e.nativeEvent.layout.width), children: [
3106
+ /* @__PURE__ */ jsx32(View27, { style: styles28.top, children: !last ? /* @__PURE__ */ jsx32(Button, { label: labels.skip, variant: "ghost", size: "sm", onPress: onDone }) : /* @__PURE__ */ jsx32(View27, { style: styles28.spacer }) }),
3107
+ /* @__PURE__ */ jsx32(ScrollView5, { ref: scroller, tabIndex: 0, horizontal: true, pagingEnabled: true, showsHorizontalScrollIndicator: false, onMomentumScrollEnd: onScroll, style: styles28.flex, children: slides.map((slide, i) => /* @__PURE__ */ jsxs28(View27, { style: [styles28.slide, { width: width || void 0 }], accessible: true, "aria-label": `${labels.position(i + 1, slides.length)}. ${slide.title}. ${slide.description}`, "aria-hidden": i !== page, children: [
3108
+ slide.visual ? /* @__PURE__ */ jsx32(View27, { style: styles28.visual, children: slide.visual }) : null,
3109
+ /* @__PURE__ */ jsx32(Txt, { variant: "display", style: styles28.centred, children: slide.title }),
3110
+ /* @__PURE__ */ jsx32(Txt, { tone: "secondary", style: [styles28.centred, styles28.description], children: slide.description })
2903
3111
  ] }, 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) }) })
3112
+ /* @__PURE__ */ jsx32(View27, { style: styles28.dots, "aria-hidden": true, children: slides.map((_, i) => /* @__PURE__ */ jsx32(View27, { style: [styles28.dot, { width: i === page ? 22 : 8, backgroundColor: i === page ? theme.accent : theme.borderStrong }] }, i)) }),
3113
+ /* @__PURE__ */ jsx32(View27, { style: styles28.bottom, children: /* @__PURE__ */ jsx32(Button, { label: last ? labels.done : labels.next, variant: last ? "gradient" : "primary", size: "lg", onPress: () => last ? onDone() : go(page + 1) }) })
2906
3114
  ] });
2907
3115
  }
2908
- var styles26 = StyleSheet26.create({
3116
+ var styles28 = StyleSheet28.create({
2909
3117
  root: { flex: 1 },
2910
3118
  top: { flexDirection: "row", justifyContent: "flex-end", paddingHorizontal: 16, minHeight: 32 },
2911
3119
  spacer: { height: 32 },
@@ -2920,8 +3128,8 @@ var styles26 = StyleSheet26.create({
2920
3128
  });
2921
3129
 
2922
3130
  // src/native/OrazakaMark.tsx
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";
3131
+ import { View as View28 } from "react-native";
3132
+ import Svg13, { Circle as Circle6, Defs as Defs5, LinearGradient as LinearGradient5, Path as Path10, RadialGradient as RadialGradient2, Stop as Stop5 } from "react-native-svg";
2925
3133
 
2926
3134
  // src/marks/orazaka-geometry.ts
2927
3135
  var orange = marks.orazaka[marks.orazaka.length - 1][1];
@@ -2950,41 +3158,41 @@ var ORAZAKA = {
2950
3158
  };
2951
3159
 
2952
3160
  // src/native/OrazakaMark.tsx
2953
- import { jsx as jsx31, jsxs as jsxs27 } from "react/jsx-runtime";
3161
+ import { jsx as jsx33, jsxs as jsxs29 } from "react/jsx-runtime";
2954
3162
  function OrazakaMark({ size = 48, animated = true, title, neutral }) {
2955
3163
  const { theme } = useTheme();
2956
- const { Animated: Animated22, layer, spinStyle, pulseStyle } = useMarkMotion(size, animated);
3164
+ const { Animated: Animated25, layer, spinStyle, pulseStyle } = useMarkMotion(size, animated);
2957
3165
  const id = useSvgId("ozm");
2958
3166
  const viewBox = size < 48 ? ORAZAKA.croppedViewBox : ORAZAKA.viewBox;
2959
3167
  const stroke = neutral ?? theme.textMuted;
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)) });
3168
+ const gradient = /* @__PURE__ */ jsx33(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__ */ jsx33(Stop5, { offset, stopColor: color }, offset)) });
2961
3169
  const fill = `url(#${id}a)`;
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 })
3170
+ return /* @__PURE__ */ jsxs29(View28, { style: { width: size, height: size }, ...markA11y(title), children: [
3171
+ /* @__PURE__ */ jsxs29(Svg13, { viewBox, style: layer, children: [
3172
+ /* @__PURE__ */ jsx33(Defs5, { children: /* @__PURE__ */ jsxs29(RadialGradient2, { id: `${id}g`, cx: "50%", cy: "50%", r: "50%", children: [
3173
+ /* @__PURE__ */ jsx33(Stop5, { offset: "0%", stopColor: ORAZAKA.glow.color, stopOpacity: ORAZAKA.glow.opacity }),
3174
+ /* @__PURE__ */ jsx33(Stop5, { offset: "100%", stopColor: ORAZAKA.glow.color, stopOpacity: 0 })
2967
3175
  ] }) }),
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" })
3176
+ size >= 48 ? /* @__PURE__ */ jsx33(Circle6, { cx: ORAZAKA.center, cy: ORAZAKA.center, r: 190, fill: `url(#${id}g)` }) : null,
3177
+ /* @__PURE__ */ jsx33(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" }),
3178
+ /* @__PURE__ */ jsx33(Circle6, { cx: ORAZAKA.center, cy: ORAZAKA.center, r: ORAZAKA.ring.r, stroke, strokeWidth: ORAZAKA.ring.width, opacity: 0.35, fill: "none" })
2971
3179
  ] }),
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))
3180
+ /* @__PURE__ */ jsx33(Animated25.View, { style: [layer, spinStyle], children: /* @__PURE__ */ jsxs29(Svg13, { viewBox, style: layer, children: [
3181
+ /* @__PURE__ */ jsx33(Defs5, { children: gradient }),
3182
+ ORAZAKA.shards.map((d) => /* @__PURE__ */ jsx33(Path10, { d, fill, stroke: fill, strokeWidth: ORAZAKA.shardStroke, strokeLinejoin: "round" }, d))
2975
3183
  ] }) }),
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 })
3184
+ /* @__PURE__ */ jsx33(Animated25.View, { style: [layer, pulseStyle], children: /* @__PURE__ */ jsxs29(Svg13, { viewBox, style: layer, children: [
3185
+ /* @__PURE__ */ jsx33(Defs5, { children: gradient }),
3186
+ /* @__PURE__ */ jsx33(Circle6, { cx: ORAZAKA.center, cy: ORAZAKA.center, r: ORAZAKA.core.r, fill }),
3187
+ /* @__PURE__ */ jsx33(Circle6, { cx: ORAZAKA.center, cy: ORAZAKA.center, r: ORAZAKA.core.inner, fill: ORAZAKA.highlight })
2980
3188
  ] }) })
2981
3189
  ] });
2982
3190
  }
2983
3191
 
2984
3192
  // src/native/OrochiaMark.tsx
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";
3193
+ import { useEffect as useEffect17, useState as useState26 } from "react";
3194
+ import { AccessibilityInfo as AccessibilityInfo11, Animated as Animated15, Easing as Easing9, View as View29 } from "react-native";
3195
+ import Svg14, { Circle as Circle7, Defs as Defs6, Ellipse as Ellipse2, G as Group2, LinearGradient as LinearGradient6, Path as Path11, RadialGradient as RadialGradient3, Stop as Stop6 } from "react-native-svg";
2988
3196
 
2989
3197
  // src/marks/orochia-geometry.ts
2990
3198
  var OROCHIA = {
@@ -3011,25 +3219,25 @@ var OROCHIA = {
3011
3219
  };
3012
3220
 
3013
3221
  // src/native/OrochiaMark.tsx
3014
- import { jsx as jsx32, jsxs as jsxs28 } from "react/jsx-runtime";
3222
+ import { jsx as jsx34, jsxs as jsxs30 } from "react/jsx-runtime";
3015
3223
  var CENTER = OROCHIA.offset + 180;
3016
3224
  function OrochiaMark({ size = 48, animated = true, title, neutral: neutralProp }) {
3017
3225
  const { theme } = useTheme();
3018
3226
  const neutral = neutralProp ?? theme.textMuted;
3019
- const [spin] = useState24(() => new Animated13.Value(0));
3020
- const [pulse] = useState24(() => new Animated13.Value(0));
3021
- useEffect15(() => {
3227
+ const [spin] = useState26(() => new Animated15.Value(0));
3228
+ const [pulse] = useState26(() => new Animated15.Value(0));
3229
+ useEffect17(() => {
3022
3230
  if (!animated) return;
3023
3231
  let loops = [];
3024
3232
  let cancelled = false;
3025
- void AccessibilityInfo10.isReduceMotionEnabled().then((reduce) => {
3233
+ void AccessibilityInfo11.isReduceMotionEnabled().then((reduce) => {
3026
3234
  if (reduce || cancelled) return;
3027
3235
  loops = [
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 })
3236
+ Animated15.loop(Animated15.timing(spin, { toValue: 1, duration: 3e4, easing: Easing9.linear, useNativeDriver: true })),
3237
+ Animated15.loop(
3238
+ Animated15.sequence([
3239
+ Animated15.timing(pulse, { toValue: 1, duration: 1600, easing: Easing9.inOut(Easing9.ease), useNativeDriver: true }),
3240
+ Animated15.timing(pulse, { toValue: 0, duration: 1600, easing: Easing9.inOut(Easing9.ease), useNativeDriver: true })
3033
3241
  ])
3034
3242
  )
3035
3243
  ];
@@ -3043,49 +3251,49 @@ function OrochiaMark({ size = 48, animated = true, title, neutral: neutralProp }
3043
3251
  const viewBox = size < 48 ? OROCHIA.croppedViewBox : OROCHIA.viewBox;
3044
3252
  const layer = { position: "absolute", width: size, height: size };
3045
3253
  const a11y = title ? { accessible: true, accessibilityRole: "image", accessibilityLabel: title } : { accessibilityElementsHidden: true, importantForAccessibility: "no-hide-descendants" };
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 })
3254
+ const bodyGradient = /* @__PURE__ */ jsx34(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__ */ jsx34(Stop6, { offset, stopColor: color }, offset)) });
3255
+ return /* @__PURE__ */ jsxs30(View29, { style: { width: size, height: size }, ...a11y, children: [
3256
+ /* @__PURE__ */ jsxs30(Svg14, { viewBox, style: layer, children: [
3257
+ /* @__PURE__ */ jsx34(Defs6, { children: /* @__PURE__ */ jsxs30(RadialGradient3, { id: "glow", cx: "50%", cy: "50%", r: "50%", children: [
3258
+ /* @__PURE__ */ jsx34(Stop6, { offset: "0%", stopColor: OROCHIA.glow.color, stopOpacity: OROCHIA.glow.opacity }),
3259
+ /* @__PURE__ */ jsx34(Stop6, { offset: "100%", stopColor: OROCHIA.glow.color, stopOpacity: 0 })
3052
3260
  ] }) }),
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" })
3261
+ /* @__PURE__ */ jsx34(Circle7, { cx: CENTER, cy: CENTER, r: 170, fill: "url(#glow)" }),
3262
+ /* @__PURE__ */ jsx34(Circle7, { cx: CENTER, cy: CENTER, r: OROCHIA.ring.r, stroke: neutral, strokeWidth: OROCHIA.ring.width, opacity: 0.35, fill: "none" })
3055
3263
  ] }),
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" })
3264
+ /* @__PURE__ */ jsx34(Animated15.View, { style: [layer, { transform: [{ rotate: spin.interpolate({ inputRange: [0, 1], outputRange: ["0deg", "360deg"] }) }] }], children: /* @__PURE__ */ jsx34(Svg14, { viewBox, style: layer, children: /* @__PURE__ */ jsx34(Circle7, { cx: CENTER, cy: CENTER, r: OROCHIA.orbit.r, stroke: neutral, strokeWidth: OROCHIA.orbit.width, strokeDasharray: OROCHIA.orbit.dash, opacity: 0.6, fill: "none" }) }) }),
3265
+ /* @__PURE__ */ jsxs30(Svg14, { viewBox, style: layer, children: [
3266
+ /* @__PURE__ */ jsx34(Defs6, { children: bodyGradient }),
3267
+ /* @__PURE__ */ jsxs30(Group2, { transform: `translate(${OROCHIA.offset} ${OROCHIA.offset})`, children: [
3268
+ /* @__PURE__ */ jsx34(Path11, { d: OROCHIA.arc, stroke: "url(#body)", strokeWidth: 22, strokeLinecap: "round", fill: "none" }),
3269
+ /* @__PURE__ */ jsx34(Path11, { d: OROCHIA.arc, stroke: OROCHIA.scales.color, strokeOpacity: OROCHIA.scales.opacity, strokeWidth: OROCHIA.scales.width, strokeLinecap: "round", strokeDasharray: OROCHIA.scales.dash, fill: "none" }),
3270
+ /* @__PURE__ */ jsx34(Path11, { d: OROCHIA.neck, stroke: "url(#body)", strokeWidth: 14, strokeLinecap: "round", fill: "none" }),
3271
+ /* @__PURE__ */ jsx34(Path11, { d: OROCHIA.tail, stroke: "url(#body)", strokeWidth: 6, strokeLinecap: "round", fill: "none" }),
3272
+ /* @__PURE__ */ jsx34(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)" }),
3273
+ /* @__PURE__ */ jsx34(Path11, { d: OROCHIA.tongue.d, stroke: OROCHIA.tongue.color, strokeWidth: 3, strokeLinecap: "round", fill: "none" })
3066
3274
  ] })
3067
3275
  ] }),
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)" })
3276
+ /* @__PURE__ */ jsx34(Animated15.View, { style: [layer, { opacity: pulse.interpolate({ inputRange: [0, 1], outputRange: [0.85, 1] }) }], children: /* @__PURE__ */ jsxs30(Svg14, { viewBox, style: layer, children: [
3277
+ /* @__PURE__ */ jsx34(Defs6, { children: /* @__PURE__ */ jsx34(LinearGradient6, { id: "flame", x1: "50%", y1: "100%", x2: "50%", y2: "0%", children: OROCHIA.flameGradient.stops.map(([offset, color]) => /* @__PURE__ */ jsx34(Stop6, { offset, stopColor: color }, offset)) }) }),
3278
+ /* @__PURE__ */ jsxs30(Group2, { transform: `translate(${OROCHIA.offset} ${OROCHIA.offset})`, children: [
3279
+ /* @__PURE__ */ jsx34(Circle7, { cx: OROCHIA.eye.cx, cy: OROCHIA.eye.cy, r: OROCHIA.eye.r, fill: OROCHIA.eye.color }),
3280
+ /* @__PURE__ */ jsx34(Path11, { d: OROCHIA.flame.d, transform: `translate(${OROCHIA.flame.translate[0]} ${OROCHIA.flame.translate[1]}) scale(${OROCHIA.flame.scale})`, fill: "url(#flame)" })
3073
3281
  ] })
3074
3282
  ] }) })
3075
3283
  ] });
3076
3284
  }
3077
3285
 
3078
3286
  // 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";
3287
+ import * as React27 from "react";
3288
+ import { Platform as Platform2, Pressable as Pressable15, StyleSheet as StyleSheet29, TextInput as TextInput5, View as View30 } from "react-native";
3289
+ import { jsx as jsx35, jsxs as jsxs31 } from "react/jsx-runtime";
3082
3290
  function OtpInput({ label, length = 6, value, onValueChange, onComplete, mode = "numeric", invalid, disabled, autoFocus, style }) {
3083
3291
  const { theme, radius: radius3, haptic } = useTheme();
3084
- const [own, setOwn] = React25.useState("");
3292
+ const [own, setOwn] = React27.useState("");
3085
3293
  const code = value ?? own;
3086
- const [focused, setFocused] = React25.useState(false);
3087
- const input = React25.useRef(null);
3088
- React25.useEffect(() => {
3294
+ const [focused, setFocused] = React27.useState(false);
3295
+ const input = React27.useRef(null);
3296
+ React27.useEffect(() => {
3089
3297
  if (invalid) haptic("warning");
3090
3298
  }, [invalid, haptic]);
3091
3299
  const change = (raw) => {
@@ -3097,14 +3305,14 @@ function OtpInput({ label, length = 6, value, onValueChange, onComplete, mode =
3097
3305
  onComplete?.(next);
3098
3306
  }
3099
3307
  };
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) => {
3308
+ return /* @__PURE__ */ jsxs31(Pressable15, { onPress: () => input.current?.focus(), disabled, accessible: false, style: [styles29.root, style], children: [
3309
+ /* @__PURE__ */ jsx35(View30, { style: styles29.boxes, "aria-hidden": true, children: Array.from({ length }, (_, i) => {
3102
3310
  const active = focused && i === Math.min(code.length, length - 1);
3103
- return /* @__PURE__ */ jsx33(
3104
- View28,
3311
+ return /* @__PURE__ */ jsx35(
3312
+ View30,
3105
3313
  {
3106
3314
  style: [
3107
- styles27.box,
3315
+ styles29.box,
3108
3316
  {
3109
3317
  borderRadius: radius3.md,
3110
3318
  backgroundColor: theme.surface2,
@@ -3112,13 +3320,13 @@ function OtpInput({ label, length = 6, value, onValueChange, onComplete, mode =
3112
3320
  borderWidth: invalid || active ? 2 : 1
3113
3321
  }
3114
3322
  ],
3115
- children: /* @__PURE__ */ jsx33(Txt, { variant: "title", children: code[i] ?? "" })
3323
+ children: /* @__PURE__ */ jsx35(Txt, { variant: "title", children: code[i] ?? "" })
3116
3324
  },
3117
3325
  i
3118
3326
  );
3119
3327
  }) }),
3120
- /* @__PURE__ */ jsx33(
3121
- TextInput4,
3328
+ /* @__PURE__ */ jsx35(
3329
+ TextInput5,
3122
3330
  {
3123
3331
  ref: input,
3124
3332
  "aria-label": label,
@@ -3136,12 +3344,12 @@ function OtpInput({ label, length = 6, value, onValueChange, onComplete, mode =
3136
3344
  caretHidden: true,
3137
3345
  onFocus: () => setFocused(true),
3138
3346
  onBlur: () => setFocused(false),
3139
- style: styles27.hidden
3347
+ style: styles29.hidden
3140
3348
  }
3141
3349
  )
3142
3350
  ] });
3143
3351
  }
3144
- var styles27 = StyleSheet27.create({
3352
+ var styles29 = StyleSheet29.create({
3145
3353
  root: { alignSelf: "flex-start" },
3146
3354
  boxes: { flexDirection: "row", gap: 8 },
3147
3355
  box: { width: 46, height: 56, alignItems: "center", justifyContent: "center" },
@@ -3149,11 +3357,11 @@ var styles27 = StyleSheet27.create({
3149
3357
  });
3150
3358
 
3151
3359
  // src/native/pagination.tsx
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";
3360
+ import { Pressable as Pressable16, StyleSheet as StyleSheet30, Text as Text14, View as View31 } from "react-native";
3361
+ import Svg15, { Path as Path12 } from "react-native-svg";
3362
+ import { jsx as jsx36, jsxs as jsxs32 } from "react/jsx-runtime";
3155
3363
  function Chevron3({ direction, color }) {
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" }) });
3364
+ return /* @__PURE__ */ jsx36(Svg15, { 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__ */ jsx36(Path12, { d: direction === "left" ? "m15 6-6 6 6 6" : "m9 6 6 6-6 6" }) });
3157
3365
  }
3158
3366
  function Pagination({ page = 1, pageCount, onPageChange, hasPrevious, hasNext, onPrevious, onNext, status, disabled, labels, style }) {
3159
3367
  const { theme, radius: radius3 } = useTheme();
@@ -3162,8 +3370,8 @@ function Pagination({ page = 1, pageCount, onPageChange, hasPrevious, hasNext, o
3162
3370
  const current = Math.min(Math.max(1, page), count);
3163
3371
  const canPrevious = !disabled && (paged ? current > 1 : Boolean(hasPrevious));
3164
3372
  const canNext = !disabled && (paged ? current < count : Boolean(hasNext));
3165
- const button = (direction, enabled, onPress, label) => /* @__PURE__ */ jsx34(
3166
- Pressable14,
3373
+ const button = (direction, enabled, onPress, label) => /* @__PURE__ */ jsx36(
3374
+ Pressable16,
3167
3375
  {
3168
3376
  role: "button",
3169
3377
  "aria-label": label,
@@ -3172,28 +3380,28 @@ function Pagination({ page = 1, pageCount, onPageChange, hasPrevious, hasNext, o
3172
3380
  hitSlop: 6,
3173
3381
  onPress,
3174
3382
  style: ({ pressed }) => [
3175
- styles28.button,
3383
+ styles30.button,
3176
3384
  { borderRadius: radius3.sm, borderColor: theme.borderDefault, backgroundColor: theme.surface1, opacity: enabled ? pressed ? 0.8 : 1 : 0.4 }
3177
3385
  ],
3178
- children: /* @__PURE__ */ jsx34(Chevron3, { direction, color: theme.textPrimary })
3386
+ children: /* @__PURE__ */ jsx36(Chevron3, { direction, color: theme.textPrimary })
3179
3387
  }
3180
3388
  );
3181
3389
  const text = status ?? (paged ? labels.compact(current, count) : null);
3182
- return /* @__PURE__ */ jsxs30(View29, { role: "navigation", style: [styles28.row, style], children: [
3390
+ return /* @__PURE__ */ jsxs32(View31, { role: "navigation", style: [styles30.row, style], children: [
3183
3391
  button("left", canPrevious, paged ? () => onPageChange?.(current - 1) : onPrevious, labels.previous),
3184
- text ? /* @__PURE__ */ jsx34(Text14, { "aria-live": "polite", style: [styles28.status, { color: theme.textSecondary }], children: text }) : null,
3392
+ text ? /* @__PURE__ */ jsx36(Text14, { "aria-live": "polite", style: [styles30.status, { color: theme.textSecondary }], children: text }) : null,
3185
3393
  button("right", canNext, paged ? () => onPageChange?.(current + 1) : onNext, labels.next)
3186
3394
  ] });
3187
3395
  }
3188
- var styles28 = StyleSheet28.create({
3396
+ var styles30 = StyleSheet30.create({
3189
3397
  row: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", gap: 12 },
3190
- button: { width: 44, height: 44, alignItems: "center", justifyContent: "center", borderWidth: StyleSheet28.hairlineWidth },
3398
+ button: { width: 44, height: 44, alignItems: "center", justifyContent: "center", borderWidth: StyleSheet30.hairlineWidth },
3191
3399
  status: { fontSize: 13, fontWeight: "600", fontVariant: ["tabular-nums"] }
3192
3400
  });
3193
3401
 
3194
3402
  // 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";
3403
+ import { StyleSheet as StyleSheet31, View as View32 } from "react-native";
3404
+ import { Fragment as Fragment6, jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
3197
3405
  function PermissionPrompt({
3198
3406
  status,
3199
3407
  title,
@@ -3210,28 +3418,28 @@ function PermissionPrompt({
3210
3418
  style
3211
3419
  }) {
3212
3420
  const { theme, radius: radius3 } = useTheme();
3213
- if (status === "granted") return /* @__PURE__ */ jsx35(Fragment5, { children: children ?? null });
3421
+ if (status === "granted") return /* @__PURE__ */ jsx37(Fragment6, { children: children ?? null });
3214
3422
  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
3423
+ return /* @__PURE__ */ jsxs33(View32, { style: [styles31.root, { backgroundColor: theme.surface1, borderColor: theme.borderSubtle, borderRadius: radius3.xl }, style], children: [
3424
+ /* @__PURE__ */ jsx37(Mascot, { bird: mascot, mood: blocked ? "error" : "welcome", size: 104 }),
3425
+ /* @__PURE__ */ jsx37(Txt, { variant: "title", style: styles31.centred, children: title }),
3426
+ /* @__PURE__ */ jsx37(Txt, { tone: "secondary", style: styles31.centred, children: blocked && blockedDescription ? blockedDescription : description }),
3427
+ /* @__PURE__ */ jsxs33(View32, { style: styles31.actions, children: [
3428
+ blocked && settingsLabel && onOpenSettings ? /* @__PURE__ */ jsx37(Button, { label: settingsLabel, variant: "primary", onPress: onOpenSettings }) : /* @__PURE__ */ jsx37(Button, { label: allowLabel, variant: "primary", onPress: onAllow }),
3429
+ dismissLabel && onDismiss ? /* @__PURE__ */ jsx37(Button, { label: dismissLabel, variant: "ghost", onPress: onDismiss }) : null
3222
3430
  ] })
3223
3431
  ] });
3224
3432
  }
3225
- var styles29 = StyleSheet29.create({
3226
- root: { alignItems: "center", gap: 10, padding: 24, borderWidth: StyleSheet29.hairlineWidth },
3433
+ var styles31 = StyleSheet31.create({
3434
+ root: { alignItems: "center", gap: 10, padding: 24, borderWidth: StyleSheet31.hairlineWidth },
3227
3435
  centred: { textAlign: "center", maxWidth: 340 },
3228
3436
  actions: { marginTop: 8, gap: 8, alignSelf: "stretch" }
3229
3437
  });
3230
3438
 
3231
3439
  // src/native/phoenix.tsx
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";
3440
+ import { useEffect as useEffect19, useState as useState28 } from "react";
3441
+ import { AccessibilityInfo as AccessibilityInfo12, Animated as Animated16, Easing as Easing10, View as View33 } from "react-native";
3442
+ import Svg16, { Circle as Circle8, Defs as Defs7, LinearGradient as LinearGradient7, Path as Path13, RadialGradient as RadialGradient4, Stop as Stop7 } from "react-native-svg";
3235
3443
 
3236
3444
  // src/mascots/phoenix-geometry.ts
3237
3445
  var PHOENIX = {
@@ -3254,17 +3462,17 @@ var PHOENIX_PALETTES = {
3254
3462
  };
3255
3463
 
3256
3464
  // src/native/phoenix.tsx
3257
- import { jsx as jsx36, jsxs as jsxs32 } from "react/jsx-runtime";
3465
+ import { jsx as jsx38, jsxs as jsxs34 } from "react/jsx-runtime";
3258
3466
  function useFloat(animated) {
3259
- const [y] = useState26(() => new Animated14.Value(0));
3260
- useEffect17(() => {
3467
+ const [y] = useState28(() => new Animated16.Value(0));
3468
+ useEffect19(() => {
3261
3469
  if (!animated) return;
3262
3470
  let loop;
3263
3471
  let cancelled = false;
3264
- void AccessibilityInfo11.isReduceMotionEnabled().then((reduce) => {
3472
+ void AccessibilityInfo12.isReduceMotionEnabled().then((reduce) => {
3265
3473
  if (reduce || cancelled) return;
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)]));
3474
+ const step = (toValue) => Animated16.timing(y, { toValue, duration: 2500, easing: Easing10.inOut(Easing10.ease), useNativeDriver: true });
3475
+ loop = Animated16.loop(Animated16.sequence([step(-6), step(0)]));
3268
3476
  loop.start();
3269
3477
  });
3270
3478
  return () => {
@@ -3279,36 +3487,131 @@ function Phoenix({ tone: tone3 = "own", size = 120, animated = true, title, styl
3279
3487
  const id = useSvgId("kzp");
3280
3488
  const y = useFloat(animated);
3281
3489
  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] })
3490
+ return /* @__PURE__ */ jsx38(View33, { style: [{ width: size, height: size }, style], ...markA11y(title), children: /* @__PURE__ */ jsx38(Animated16.View, { style: { transform: [{ translateY: y }] }, children: /* @__PURE__ */ jsxs34(Svg16, { width: size, height: size, viewBox: "0 0 120 120", children: [
3491
+ /* @__PURE__ */ jsxs34(Defs7, { children: [
3492
+ /* @__PURE__ */ jsxs34(LinearGradient7, { id: `${id}l`, x1: "1", y1: "0", x2: "0", y2: "1", children: [
3493
+ /* @__PURE__ */ jsx38(Stop7, { offset: "0%", stopColor: p.left[0] }),
3494
+ /* @__PURE__ */ jsx38(Stop7, { offset: "100%", stopColor: p.left[1] })
3287
3495
  ] }),
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] })
3496
+ /* @__PURE__ */ jsxs34(LinearGradient7, { id: `${id}r`, x1: "0", y1: "0", x2: "1", y2: "1", children: [
3497
+ /* @__PURE__ */ jsx38(Stop7, { offset: "0%", stopColor: p.right[0] }),
3498
+ /* @__PURE__ */ jsx38(Stop7, { offset: "100%", stopColor: p.right[1] })
3291
3499
  ] }),
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 })
3500
+ /* @__PURE__ */ jsxs34(RadialGradient4, { id: `${id}c`, children: [
3501
+ /* @__PURE__ */ jsx38(Stop7, { offset: "0%", stopColor: p.core[0] }),
3502
+ /* @__PURE__ */ jsx38(Stop7, { offset: "100%", stopColor: p.core[1], stopOpacity: 0 })
3295
3503
  ] })
3296
3504
  ] }),
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" })
3505
+ /* @__PURE__ */ jsx38(Path13, { d: PHOENIX.wingL, fill: `url(#${id}l)` }),
3506
+ /* @__PURE__ */ jsx38(Path13, { d: PHOENIX.wingR, fill: `url(#${id}r)` }),
3507
+ /* @__PURE__ */ jsx38(Path13, { d: PHOENIX.tailL, fill: `url(#${id}l)`, opacity: 0.7 }),
3508
+ /* @__PURE__ */ jsx38(Path13, { d: PHOENIX.tailR, fill: `url(#${id}r)`, opacity: 0.7 }),
3509
+ /* @__PURE__ */ jsx38(Path13, { d: PHOENIX.body, fill: p.body, stroke: p.edge, strokeOpacity: 0.5 }),
3510
+ /* @__PURE__ */ jsx38(Circle8, { cx: 60, cy: 58, r: 12, fill: `url(#${id}c)` }),
3511
+ /* @__PURE__ */ jsx38(Circle8, { cx: 60, cy: 58, r: 3.5, fill: "#ffffff" }),
3512
+ /* @__PURE__ */ jsx38(Path13, { d: PHOENIX.crest, stroke: p.crest, strokeWidth: 2, strokeLinecap: "round" })
3305
3513
  ] }) }) });
3306
3514
  }
3307
3515
 
3516
+ // src/native/photo-grid.tsx
3517
+ import * as React29 from "react";
3518
+ import { Image as Image4, Pressable as Pressable17, StyleSheet as StyleSheet32, View as View34 } from "react-native";
3519
+ import Svg17, { Path as Path14 } from "react-native-svg";
3520
+ import { jsx as jsx39, jsxs as jsxs35 } from "react/jsx-runtime";
3521
+ function PhotoGrid({ value, onValueChange, onAdd, slots = 6, required = 1, columns = 3, labels, style }) {
3522
+ const { theme, radius: radius3, haptic } = useTheme();
3523
+ const [menu, setMenu] = React29.useState(null);
3524
+ const move = (from, to) => {
3525
+ if (to < 0 || to >= value.length || from === to) return;
3526
+ const next = [...value];
3527
+ const [photo] = next.splice(from, 1);
3528
+ next.splice(to, 0, photo);
3529
+ haptic("selection");
3530
+ onValueChange(next);
3531
+ };
3532
+ const remove = (i) => {
3533
+ haptic("impact");
3534
+ onValueChange(value.filter((_, j) => j !== i));
3535
+ };
3536
+ const width = `${100 / columns}%`;
3537
+ return /* @__PURE__ */ jsxs35(View34, { style: [styles32.grid, style], children: [
3538
+ Array.from({ length: slots }, (_, i) => {
3539
+ const photo = value[i];
3540
+ const cell = [styles32.slot, { borderRadius: radius3.lg, aspectRatio: 3 / 4 }];
3541
+ return /* @__PURE__ */ jsx39(View34, { style: [styles32.cell, { width }], children: photo ? /* @__PURE__ */ jsxs35(
3542
+ Pressable17,
3543
+ {
3544
+ role: "button",
3545
+ "aria-label": [labels.photo(i + 1), photo.alt, i === 0 ? labels.main : null].filter(Boolean).join(", "),
3546
+ onPress: () => setMenu(i),
3547
+ onLongPress: () => {
3548
+ haptic("impact");
3549
+ setMenu(i);
3550
+ },
3551
+ accessibilityActions: [
3552
+ ...i > 0 ? [{ name: "makeMain", label: labels.makeMain }, { name: "earlier", label: labels.moveEarlier }] : [],
3553
+ ...i < value.length - 1 ? [{ name: "later", label: labels.moveLater }] : [],
3554
+ { name: "remove", label: labels.remove }
3555
+ ],
3556
+ onAccessibilityAction: (e) => {
3557
+ const name = e.nativeEvent.actionName;
3558
+ if (name === "makeMain") move(i, 0);
3559
+ if (name === "earlier") move(i, i - 1);
3560
+ if (name === "later") move(i, i + 1);
3561
+ if (name === "remove") remove(i);
3562
+ },
3563
+ style: [...cell, { backgroundColor: theme.surface3, overflow: "hidden" }],
3564
+ children: [
3565
+ /* @__PURE__ */ jsx39(Image4, { source: { uri: photo.uri }, style: StyleSheet32.absoluteFill, resizeMode: "cover" }),
3566
+ i === 0 ? /* @__PURE__ */ jsx39(View34, { style: [styles32.main, { backgroundColor: theme.accent, borderRadius: radius3.full }], children: /* @__PURE__ */ jsx39(Txt, { variant: "caption", tone: "onAccent", style: styles32.mainText, children: labels.main }) }) : null
3567
+ ]
3568
+ }
3569
+ ) : /* @__PURE__ */ jsx39(
3570
+ Pressable17,
3571
+ {
3572
+ role: "button",
3573
+ "aria-label": labels.add,
3574
+ disabled: !onAdd || i > value.length,
3575
+ onPress: onAdd,
3576
+ style: ({ pressed }) => [
3577
+ ...cell,
3578
+ styles32.empty,
3579
+ { borderColor: i < required ? theme.accent : theme.borderStrong, backgroundColor: pressed ? theme.surface2 : theme.surface1, opacity: i > value.length ? 0.5 : 1 }
3580
+ ],
3581
+ children: /* @__PURE__ */ jsx39(View34, { style: [styles32.plus, { backgroundColor: i === value.length ? theme.accent : theme.surface3, borderRadius: radius3.full }], children: /* @__PURE__ */ jsx39(Svg17, { width: 16, height: 16, viewBox: "0 0 24 24", "aria-hidden": true, children: /* @__PURE__ */ jsx39(Path14, { d: "M12 5v14M5 12h14", stroke: i === value.length ? theme.onAccent : theme.textSecondary, strokeWidth: 2.6, strokeLinecap: "round" }) }) })
3582
+ }
3583
+ ) }, photo?.id ?? `empty-${i}`);
3584
+ }),
3585
+ /* @__PURE__ */ jsx39(
3586
+ ActionSheet,
3587
+ {
3588
+ open: menu !== null,
3589
+ onOpenChange: (open) => !open && setMenu(null),
3590
+ title: menu !== null ? labels.photo(menu + 1) : "",
3591
+ cancelLabel: labels.cancel,
3592
+ actions: menu === null ? [] : [
3593
+ ...menu > 0 ? [{ label: labels.makeMain, onPress: () => move(menu, 0) }, { label: labels.moveEarlier, onPress: () => move(menu, menu - 1) }] : [],
3594
+ ...menu < value.length - 1 ? [{ label: labels.moveLater, onPress: () => move(menu, menu + 1) }] : [],
3595
+ { label: labels.remove, destructive: true, onPress: () => remove(menu) }
3596
+ ]
3597
+ }
3598
+ )
3599
+ ] });
3600
+ }
3601
+ var styles32 = StyleSheet32.create({
3602
+ grid: { flexDirection: "row", flexWrap: "wrap", marginHorizontal: -4 },
3603
+ cell: { padding: 4 },
3604
+ slot: { width: "100%" },
3605
+ empty: { borderWidth: 1.5, borderStyle: "dashed", alignItems: "center", justifyContent: "center" },
3606
+ plus: { width: 32, height: 32, alignItems: "center", justifyContent: "center" },
3607
+ main: { position: "absolute", left: 6, bottom: 6, paddingHorizontal: 8, paddingVertical: 2 },
3608
+ mainText: { fontWeight: "800", textTransform: "uppercase", letterSpacing: 0.5 }
3609
+ });
3610
+
3308
3611
  // src/native/YazakiaMark.tsx
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";
3612
+ import React30 from "react";
3613
+ import { View as View35 } from "react-native";
3614
+ import Svg18, { Circle as Circle9, Defs as Defs8, LinearGradient as LinearGradient8, Path as Path15, RadialGradient as RadialGradient5, Stop as Stop8 } from "react-native-svg";
3312
3615
 
3313
3616
  // src/marks/yazakia-geometry.ts
3314
3617
  var turquoise = marks.yazakia[marks.yazakia.length - 1][1];
@@ -3338,54 +3641,54 @@ var YAZAKIA = {
3338
3641
  };
3339
3642
 
3340
3643
  // src/native/YazakiaMark.tsx
3341
- import { jsx as jsx37, jsxs as jsxs33 } from "react/jsx-runtime";
3644
+ import { jsx as jsx40, jsxs as jsxs36 } from "react/jsx-runtime";
3342
3645
  function YazakiaMark({ size = 48, animated = true, title, neutral }) {
3343
3646
  const { theme } = useTheme();
3344
- const { Animated: Animated22, layer, spinStyle, pulseStyle } = useMarkMotion(size, animated);
3647
+ const { Animated: Animated25, layer, spinStyle, pulseStyle } = useMarkMotion(size, animated);
3345
3648
  const id = useSvgId("yzm");
3346
3649
  const viewBox = size < 48 ? YAZAKIA.croppedViewBox : YAZAKIA.viewBox;
3347
3650
  const stroke = neutral ?? theme.textMuted;
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)) });
3651
+ const gradient = /* @__PURE__ */ jsx40(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__ */ jsx40(Stop8, { offset, stopColor: color }, offset)) });
3349
3652
  const fill = `url(#${id}a)`;
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 })
3653
+ return /* @__PURE__ */ jsxs36(View35, { style: { width: size, height: size }, ...markA11y(title), children: [
3654
+ /* @__PURE__ */ jsxs36(Svg18, { viewBox, style: layer, children: [
3655
+ /* @__PURE__ */ jsxs36(Defs8, { children: [
3656
+ /* @__PURE__ */ jsxs36(RadialGradient5, { id: `${id}g`, cx: "50%", cy: "50%", r: "50%", children: [
3657
+ /* @__PURE__ */ jsx40(Stop8, { offset: "0%", stopColor: YAZAKIA.glow.color, stopOpacity: YAZAKIA.glow.opacity }),
3658
+ /* @__PURE__ */ jsx40(Stop8, { offset: "100%", stopColor: YAZAKIA.glow.color, stopOpacity: 0 })
3356
3659
  ] }),
3357
3660
  gradient
3358
3661
  ] }),
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
3662
+ size >= 48 ? /* @__PURE__ */ jsx40(Circle9, { cx: YAZAKIA.center, cy: YAZAKIA.center, r: 190, fill: `url(#${id}g)` }) : null,
3663
+ /* @__PURE__ */ jsx40(Circle9, { cx: YAZAKIA.center, cy: YAZAKIA.center, r: YAZAKIA.ring.r, stroke, strokeWidth: YAZAKIA.ring.width, opacity: 0.35, fill: "none" }),
3664
+ YAZAKIA.voices.map((v, i) => /* @__PURE__ */ jsxs36(React30.Fragment, { children: [
3665
+ /* @__PURE__ */ jsx40(Path15, { d: v.body, fill }),
3666
+ /* @__PURE__ */ jsx40(Path15, { d: v.tail, fill }),
3667
+ i === 0 ? /* @__PURE__ */ jsx40(Path15, { d: `${v.body} ${v.tail}`, fill: YAZAKIA.shade.color, opacity: YAZAKIA.shade.opacity }) : null
3365
3668
  ] }, v.body))
3366
3669
  ] }),
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))
3670
+ /* @__PURE__ */ jsx40(Animated25.View, { style: [layer, spinStyle], children: /* @__PURE__ */ jsxs36(Svg18, { viewBox, style: layer, children: [
3671
+ /* @__PURE__ */ jsx40(Defs8, { children: gradient }),
3672
+ /* @__PURE__ */ jsx40(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" }),
3673
+ YAZAKIA.pair.at.map(([cx, cy]) => /* @__PURE__ */ jsx40(Circle9, { cx, cy, r: YAZAKIA.pair.r, fill }, cx))
3371
3674
  ] }) }),
3372
- /* @__PURE__ */ jsx37(Animated22.View, { style: [layer, pulseStyle], children: /* @__PURE__ */ jsxs33(Svg15, { viewBox, style: layer, children: [
3373
- /* @__PURE__ */ jsxs33(Defs8, { children: [
3675
+ /* @__PURE__ */ jsx40(Animated25.View, { style: [layer, pulseStyle], children: /* @__PURE__ */ jsxs36(Svg18, { viewBox, style: layer, children: [
3676
+ /* @__PURE__ */ jsxs36(Defs8, { children: [
3374
3677
  gradient,
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 })
3678
+ /* @__PURE__ */ jsxs36(LinearGradient8, { id: `${id}l`, gradientUnits: "userSpaceOnUse", x1: 0, y1: YAZAKIA.lens.y1, x2: 0, y2: YAZAKIA.lens.y2, children: [
3679
+ /* @__PURE__ */ jsx40(Stop8, { offset: "0%", stopColor: YAZAKIA.highlight.color, stopOpacity: YAZAKIA.highlight.from }),
3680
+ /* @__PURE__ */ jsx40(Stop8, { offset: "100%", stopColor: YAZAKIA.highlight.color, stopOpacity: YAZAKIA.highlight.to })
3378
3681
  ] })
3379
3682
  ] }),
3380
- /* @__PURE__ */ jsx37(Path12, { d: YAZAKIA.lens.d, fill }),
3381
- /* @__PURE__ */ jsx37(Path12, { d: YAZAKIA.lens.d, fill: `url(#${id}l)` })
3683
+ /* @__PURE__ */ jsx40(Path15, { d: YAZAKIA.lens.d, fill }),
3684
+ /* @__PURE__ */ jsx40(Path15, { d: YAZAKIA.lens.d, fill: `url(#${id}l)` })
3382
3685
  ] }) })
3383
3686
  ] });
3384
3687
  }
3385
3688
 
3386
3689
  // src/native/YororisMark.tsx
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";
3690
+ import { View as View36 } from "react-native";
3691
+ import Svg19, { Circle as Circle10, Defs as Defs9, LinearGradient as LinearGradient9, Path as Path16, RadialGradient as RadialGradient6, Stop as Stop9 } from "react-native-svg";
3389
3692
 
3390
3693
  // src/marks/yororis-geometry.ts
3391
3694
  var sand = marks.yororis[0][1];
@@ -3421,65 +3724,65 @@ var YORORIS = {
3421
3724
  };
3422
3725
 
3423
3726
  // src/native/YororisMark.tsx
3424
- import { jsx as jsx38, jsxs as jsxs34 } from "react/jsx-runtime";
3727
+ import { jsx as jsx41, jsxs as jsxs37 } from "react/jsx-runtime";
3425
3728
  function YororisMark({ size = 48, animated = true, title, neutral }) {
3426
3729
  const { theme } = useTheme();
3427
- const { Animated: Animated22, layer, spinStyle, pulseStyle } = useMarkMotion(size, animated, 36e3);
3730
+ const { Animated: Animated25, layer, spinStyle, pulseStyle } = useMarkMotion(size, animated, 36e3);
3428
3731
  const id = useSvgId("yrm");
3429
3732
  const viewBox = size < 48 ? YORORIS.croppedViewBox : YORORIS.viewBox;
3430
3733
  const stroke = neutral ?? theme.textMuted;
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)) });
3734
+ const gradient = /* @__PURE__ */ jsx41(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__ */ jsx41(Stop9, { offset, stopColor: color }, offset)) });
3432
3735
  const fill = `url(#${id}a)`;
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 })
3736
+ return /* @__PURE__ */ jsxs37(View36, { style: { width: size, height: size }, ...markA11y(title), children: [
3737
+ /* @__PURE__ */ jsxs37(Svg19, { viewBox, style: layer, children: [
3738
+ /* @__PURE__ */ jsxs37(Defs9, { children: [
3739
+ /* @__PURE__ */ jsxs37(RadialGradient6, { id: `${id}g`, cx: "50%", cy: "50%", r: "50%", children: [
3740
+ /* @__PURE__ */ jsx41(Stop9, { offset: "0%", stopColor: YORORIS.glow.color, stopOpacity: YORORIS.glow.opacity }),
3741
+ /* @__PURE__ */ jsx41(Stop9, { offset: "100%", stopColor: YORORIS.glow.color, stopOpacity: 0 })
3439
3742
  ] }),
3440
3743
  gradient
3441
3744
  ] }),
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" })
3745
+ size >= 48 ? /* @__PURE__ */ jsx41(Circle10, { cx: YORORIS.center, cy: YORORIS.center, r: 190, fill: `url(#${id}g)` }) : null,
3746
+ /* @__PURE__ */ jsx41(Circle10, { cx: YORORIS.center, cy: YORORIS.center, r: YORORIS.ring.r, stroke, strokeWidth: YORORIS.ring.width, opacity: 0.35, fill: "none" }),
3747
+ /* @__PURE__ */ jsx41(Path16, { d: YORORIS.stem, stroke: fill, strokeWidth: YORORIS.stroke, strokeLinecap: "round", fill: "none" }),
3748
+ YORORIS.leaves.map((d) => /* @__PURE__ */ jsx41(Path16, { d, fill }, d)),
3749
+ /* @__PURE__ */ jsx41(Path16, { d: YORORIS.veins, stroke: YORORIS.vein.color, strokeOpacity: YORORIS.vein.opacity, strokeWidth: YORORIS.vein.width, strokeLinecap: "round", strokeDasharray: YORORIS.vein.dash, fill: "none" })
3447
3750
  ] }),
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 })
3751
+ /* @__PURE__ */ jsx41(Animated25.View, { style: [layer, spinStyle], children: /* @__PURE__ */ jsxs37(Svg19, { viewBox, style: layer, children: [
3752
+ /* @__PURE__ */ jsx41(Defs9, { children: gradient }),
3753
+ /* @__PURE__ */ jsx41(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" }),
3754
+ /* @__PURE__ */ jsx41(Circle10, { cx: YORORIS.moment.at[0], cy: YORORIS.moment.at[1], r: YORORIS.moment.r, fill })
3452
3755
  ] }) }),
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 })
3756
+ /* @__PURE__ */ jsx41(Animated25.View, { style: [layer, pulseStyle], children: /* @__PURE__ */ jsxs37(Svg19, { viewBox, style: layer, children: [
3757
+ /* @__PURE__ */ jsx41(Defs9, { children: /* @__PURE__ */ jsx41(LinearGradient9, { id: `${id}c`, x1: "50%", y1: "100%", x2: "50%", y2: "0%", children: YORORIS.coreGradient.stops.map(([offset, color]) => /* @__PURE__ */ jsx41(Stop9, { offset, stopColor: color }, offset)) }) }),
3758
+ /* @__PURE__ */ jsx41(Circle10, { cx: YORORIS.core.cx, cy: YORORIS.core.cy, r: YORORIS.core.r, fill: `url(#${id}c)` }),
3759
+ /* @__PURE__ */ jsx41(Circle10, { cx: YORORIS.core.cx, cy: YORORIS.core.cy, r: YORORIS.core.inner, fill: YORORIS.highlight })
3457
3760
  ] }) })
3458
3761
  ] });
3459
3762
  }
3460
3763
 
3461
3764
  // src/native/ProductMark.tsx
3462
- import { jsx as jsx39 } from "react/jsx-runtime";
3765
+ import { jsx as jsx42 } from "react/jsx-runtime";
3463
3766
  function ProductMark({ id, ...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 });
3767
+ if (id === "krizaka") return /* @__PURE__ */ jsx42(KrizakaMark, { ...props });
3768
+ if (id === "orazaka") return /* @__PURE__ */ jsx42(OrazakaMark, { ...props });
3769
+ if (id === "yazakia") return /* @__PURE__ */ jsx42(YazakiaMark, { ...props });
3770
+ if (id === "yororis") return /* @__PURE__ */ jsx42(YororisMark, { ...props });
3771
+ return /* @__PURE__ */ jsx42(OrochiaMark, { ...props });
3469
3772
  }
3470
3773
 
3471
3774
  // src/native/profile-card.tsx
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";
3775
+ import * as React31 from "react";
3776
+ import { Animated as Animated17, StyleSheet as StyleSheet33, View as View37 } from "react-native";
3777
+ import { jsx as jsx43, jsxs as jsxs38 } from "react/jsx-runtime";
3475
3778
  var ratioOf = (value, max = 100) => Math.min(1, Math.max(0, value / (max || 1)));
3476
3779
  function Bar({ label, ratio, words, animated, delay }) {
3477
3780
  const { theme } = useTheme();
3478
3781
  const t = useEntrance(animated, delay, 900);
3479
- const [width, setWidth] = React28.useState(0);
3782
+ const [width, setWidth] = React31.useState(0);
3480
3783
  const translateX = t.interpolate({ inputRange: [0, 1], outputRange: [-width * ratio, 0] });
3481
- return /* @__PURE__ */ jsx40(
3482
- View34,
3784
+ return /* @__PURE__ */ jsx43(
3785
+ View37,
3483
3786
  {
3484
3787
  accessible: true,
3485
3788
  role: "meter",
@@ -3489,42 +3792,42 @@ function Bar({ label, ratio, words, animated, delay }) {
3489
3792
  "aria-valuenow": Math.round(ratio * 100),
3490
3793
  "aria-valuetext": words,
3491
3794
  onLayout: (e) => setWidth(e.nativeEvent.layout.width),
3492
- style: [styles30.track, { backgroundColor: theme.surface3 }],
3493
- children: /* @__PURE__ */ jsx40(Animated15.View, { style: [styles30.fill, { width: `${ratio * 100}%`, backgroundColor: theme.accent, transform: [{ translateX }] }] })
3795
+ style: [styles33.track, { backgroundColor: theme.surface3 }],
3796
+ children: /* @__PURE__ */ jsx43(Animated17.View, { style: [styles33.fill, { width: `${ratio * 100}%`, backgroundColor: theme.accent, transform: [{ translateX }] }] })
3494
3797
  }
3495
3798
  );
3496
3799
  }
3497
3800
  function ProfileCard({ visual, name, statLabel, value = 100, valueText, stats, caption, children, animated = true, style, ...props }) {
3498
3801
  const { theme, radius: radius3 } = useTheme();
3499
3802
  const ratio = ratioOf(value);
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: [
3803
+ return /* @__PURE__ */ jsxs38(View37, { ...props, style: [styles33.root, { backgroundColor: theme.surface1, borderColor: theme.borderSubtle, borderRadius: radius3.xl }, style], children: [
3804
+ /* @__PURE__ */ jsx43(View37, { "aria-hidden": true, style: [styles33.disc, { backgroundColor: theme.surface2, borderColor: theme.accentSoft }], children: visual }),
3805
+ /* @__PURE__ */ jsxs38(View37, { style: styles33.head, children: [
3806
+ /* @__PURE__ */ jsx43(Txt, { variant: "title", style: styles33.name, children: name }),
3807
+ statLabel ? /* @__PURE__ */ jsxs38(Txt, { variant: "caption", tone: "secondary", children: [
3505
3808
  statLabel,
3506
3809
  " ",
3507
- /* @__PURE__ */ jsx40(Txt, { variant: "caption", children: valueText ?? `${Math.round(ratio * 100)} %` })
3810
+ /* @__PURE__ */ jsx43(Txt, { variant: "caption", children: valueText ?? `${Math.round(ratio * 100)} %` })
3508
3811
  ] }) : null
3509
3812
  ] }),
3510
- statLabel ? /* @__PURE__ */ jsx40(Bar, { label: statLabel, ratio, words: valueText ?? `${Math.round(ratio * 100)} %`, animated, delay: 200 }) : null,
3813
+ statLabel ? /* @__PURE__ */ jsx43(Bar, { label: statLabel, ratio, words: valueText ?? `${Math.round(ratio * 100)} %`, animated, delay: 200 }) : null,
3511
3814
  stats?.map((s, i) => {
3512
3815
  const r = ratioOf(s.value, s.max);
3513
3816
  const words = s.valueText ?? `${Math.round(r * 100)} %`;
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 })
3817
+ return /* @__PURE__ */ jsxs38(View37, { style: styles33.stat, children: [
3818
+ /* @__PURE__ */ jsxs38(View37, { "aria-hidden": true, style: styles33.statHead, children: [
3819
+ /* @__PURE__ */ jsx43(Txt, { variant: "caption", tone: "secondary", children: s.label }),
3820
+ /* @__PURE__ */ jsx43(Txt, { variant: "caption", children: words })
3518
3821
  ] }),
3519
- /* @__PURE__ */ jsx40(Bar, { label: s.label, ratio: r, words, animated, delay: 320 + i * 120 })
3822
+ /* @__PURE__ */ jsx43(Bar, { label: s.label, ratio: r, words, animated, delay: 320 + i * 120 })
3520
3823
  ] }, s.label);
3521
3824
  }),
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
3825
+ caption ? /* @__PURE__ */ jsx43(Txt, { variant: "caption", tone: "secondary", style: styles33.caption, children: caption }) : null,
3826
+ children ? /* @__PURE__ */ jsx43(View37, { style: styles33.extra, children }) : null
3524
3827
  ] });
3525
3828
  }
3526
- var styles30 = StyleSheet30.create({
3527
- root: { alignItems: "center", gap: 12, padding: 20, borderWidth: StyleSheet30.hairlineWidth },
3829
+ var styles33 = StyleSheet33.create({
3830
+ root: { alignItems: "center", gap: 12, padding: 20, borderWidth: StyleSheet33.hairlineWidth },
3528
3831
  disc: { width: 104, height: 104, borderRadius: 52, borderWidth: 1, alignItems: "center", justifyContent: "center", overflow: "hidden" },
3529
3832
  head: { flexDirection: "row", alignSelf: "stretch", alignItems: "center", justifyContent: "space-between", gap: 8 },
3530
3833
  name: { flexShrink: 1, fontSize: 17 },
@@ -3537,11 +3840,11 @@ var styles30 = StyleSheet30.create({
3537
3840
  });
3538
3841
 
3539
3842
  // src/native/progress.tsx
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);
3843
+ import * as React32 from "react";
3844
+ import { Animated as Animated18, Easing as Easing11, StyleSheet as StyleSheet34, View as View38 } from "react-native";
3845
+ import Svg20, { Circle as Circle11, Defs as Defs10, LinearGradient as LinearGradient10, Rect as Rect3, Stop as Stop10 } from "react-native-svg";
3846
+ import { jsx as jsx44, jsxs as jsxs39 } from "react/jsx-runtime";
3847
+ var AnimatedCircle = Animated18.createAnimatedComponent(Circle11);
3545
3848
  var BAR2 = { sm: 4, md: 8, lg: 12 };
3546
3849
  var RING2 = { sm: 40, md: 80, lg: 144 };
3547
3850
  var STROKE = { sm: 12, md: 9, lg: 7 };
@@ -3552,21 +3855,21 @@ function Progress({ variant = "bar", size = "md", value, max = 100, label, value
3552
3855
  const known = typeof value === "number" && Number.isFinite(value);
3553
3856
  const ratio = known ? Math.min(1, Math.max(0, value / (max || 1))) : 0;
3554
3857
  const percent = Math.round(ratio * 100);
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(() => {
3858
+ const [progress] = React32.useState(() => new Animated18.Value(ratio));
3859
+ const [spin] = React32.useState(() => new Animated18.Value(0));
3860
+ const [track, setTrack] = React32.useState(0);
3861
+ React32.useEffect(() => {
3559
3862
  if (reduce) {
3560
3863
  progress.setValue(ratio);
3561
3864
  return;
3562
3865
  }
3563
- const animation = Animated16.timing(progress, { toValue: ratio, duration: 700, easing: Easing9.out(Easing9.cubic), useNativeDriver: false });
3866
+ const animation = Animated18.timing(progress, { toValue: ratio, duration: 700, easing: Easing11.out(Easing11.cubic), useNativeDriver: false });
3564
3867
  animation.start();
3565
3868
  return () => animation.stop();
3566
3869
  }, [ratio, reduce, progress]);
3567
- React29.useEffect(() => {
3870
+ React32.useEffect(() => {
3568
3871
  if (known || reduce) return;
3569
- const loop = Animated16.loop(Animated16.timing(spin, { toValue: 1, duration: 1200, easing: Easing9.linear, useNativeDriver: true }));
3872
+ const loop = Animated18.loop(Animated18.timing(spin, { toValue: 1, duration: 1200, easing: Easing11.linear, useNativeDriver: true }));
3570
3873
  loop.start();
3571
3874
  return () => {
3572
3875
  loop.stop();
@@ -3582,9 +3885,9 @@ function Progress({ variant = "bar", size = "md", value, max = 100, label, value
3582
3885
  "aria-valuenow": known ? Math.min(max, Math.max(0, value)) : void 0,
3583
3886
  "aria-valuetext": known ? valueText ?? `${percent}%` : valueText
3584
3887
  };
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 })
3888
+ const gradient = /* @__PURE__ */ jsx44(Defs10, { children: /* @__PURE__ */ jsxs39(LinearGradient10, { id, x1: "0", y1: "0", x2: "1", y2: variant === "ring" ? "1" : "0", children: [
3889
+ /* @__PURE__ */ jsx44(Stop10, { offset: "0", stopColor: theme.accent }),
3890
+ /* @__PURE__ */ jsx44(Stop10, { offset: "1", stopColor: theme.accent2 })
3588
3891
  ] }) });
3589
3892
  if (variant === "ring") {
3590
3893
  const side = RING2[size];
@@ -3593,11 +3896,11 @@ function Progress({ variant = "bar", size = "md", value, max = 100, label, value
3593
3896
  const circumference = 2 * Math.PI * r;
3594
3897
  const offset = known ? progress.interpolate({ inputRange: [0, 1], outputRange: [circumference, 0] }) : circumference * 0.75;
3595
3898
  const rotate = spin.interpolate({ inputRange: [0, 1], outputRange: ["0deg", "360deg"] });
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: [
3899
+ return /* @__PURE__ */ jsxs39(View38, { ...a11y, style: [styles34.ring, { width: side, height: side }, style], children: [
3900
+ /* @__PURE__ */ jsx44(Animated18.View, { style: [StyleSheet34.absoluteFill, { transform: [{ rotate: known ? "-90deg" : rotate }] }], children: /* @__PURE__ */ jsxs39(Svg20, { width: side, height: side, viewBox: "0 0 100 100", children: [
3598
3901
  gradient,
3599
- /* @__PURE__ */ jsx41(Circle11, { cx: 50, cy: 50, r, fill: "none", stroke: theme.borderDefault, strokeWidth: stroke }),
3600
- /* @__PURE__ */ jsx41(
3902
+ /* @__PURE__ */ jsx44(Circle11, { cx: 50, cy: 50, r, fill: "none", stroke: theme.borderDefault, strokeWidth: stroke }),
3903
+ /* @__PURE__ */ jsx44(
3601
3904
  AnimatedCircle,
3602
3905
  {
3603
3906
  cx: 50,
@@ -3617,20 +3920,20 @@ function Progress({ variant = "bar", size = "md", value, max = 100, label, value
3617
3920
  }
3618
3921
  const width = known ? progress.interpolate({ inputRange: [0, 1], outputRange: ["0%", "100%"] }) : "40%";
3619
3922
  const translate = spin.interpolate({ inputRange: [0, 1], outputRange: [-0.4 * track, track] });
3620
- return /* @__PURE__ */ jsx41(
3621
- View35,
3923
+ return /* @__PURE__ */ jsx44(
3924
+ View38,
3622
3925
  {
3623
3926
  ...a11y,
3624
3927
  onLayout: known ? void 0 : (event) => setTrack(event.nativeEvent.layout.width),
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: [
3928
+ style: [styles34.bar, { height: BAR2[size], backgroundColor: theme.surface3 }, style],
3929
+ children: /* @__PURE__ */ jsx44(Animated18.View, { style: [styles34.fill, { width }, known || reduce ? null : { transform: [{ translateX: translate }] }], children: /* @__PURE__ */ jsxs39(Svg20, { width: "100%", height: "100%", preserveAspectRatio: "none", children: [
3627
3930
  gradient,
3628
- /* @__PURE__ */ jsx41(Rect3, { x: 0, y: 0, width: "100%", height: "100%", fill: `url(#${id})` })
3931
+ /* @__PURE__ */ jsx44(Rect3, { x: 0, y: 0, width: "100%", height: "100%", fill: `url(#${id})` })
3629
3932
  ] }) })
3630
3933
  }
3631
3934
  );
3632
3935
  }
3633
- var styles31 = StyleSheet31.create({
3936
+ var styles34 = StyleSheet34.create({
3634
3937
  ring: { alignItems: "center", justifyContent: "center" },
3635
3938
  bar: { width: "100%", overflow: "hidden", borderRadius: 9999 },
3636
3939
  fill: { height: "100%", overflow: "hidden", borderRadius: 9999 }
@@ -3638,30 +3941,30 @@ var styles31 = StyleSheet31.create({
3638
3941
 
3639
3942
  // src/native/pull-to-refresh.tsx
3640
3943
  import { RefreshControl } from "react-native";
3641
- import { jsx as jsx42 } from "react/jsx-runtime";
3944
+ import { jsx as jsx45 } from "react/jsx-runtime";
3642
3945
  function PullToRefresh({ label, ...props }) {
3643
3946
  const { theme } = useTheme();
3644
- return /* @__PURE__ */ jsx42(RefreshControl, { ...props, tintColor: theme.accent, colors: [theme.accent], progressBackgroundColor: theme.surface2, title: label, titleColor: theme.textSecondary });
3947
+ return /* @__PURE__ */ jsx45(RefreshControl, { ...props, tintColor: theme.accent, colors: [theme.accent], progressBackgroundColor: theme.surface2, title: label, titleColor: theme.textSecondary });
3645
3948
  }
3646
3949
 
3647
3950
  // src/native/radio-group.tsx
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";
3951
+ import * as React33 from "react";
3952
+ import { Animated as Animated19, Pressable as Pressable18, StyleSheet as StyleSheet35, Text as Text15, View as View39 } from "react-native";
3953
+ import Svg21, { Path as Path17 } from "react-native-svg";
3954
+ import { jsx as jsx46, jsxs as jsxs40 } from "react/jsx-runtime";
3652
3955
  function Check({ color }) {
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" }) });
3956
+ return /* @__PURE__ */ jsx46(Svg21, { 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__ */ jsx46(Path17, { d: "M20 6 9 17l-5-5" }) });
3654
3957
  }
3655
3958
  function Key({ option, checked, disabled, onPress }) {
3656
3959
  const { theme, radius: radius3, motion: motion3 } = useTheme();
3657
- const [held, setHeld] = React30.useState(false);
3658
- const [sink] = React30.useState(() => new Animated17.Value(checked ? 1 : 0));
3960
+ const [held, setHeld] = React33.useState(false);
3961
+ const [sink] = React33.useState(() => new Animated19.Value(checked ? 1 : 0));
3659
3962
  const down = checked || held;
3660
- React30.useEffect(() => {
3661
- Animated17.timing(sink, { toValue: down ? 1 : 0, duration: motion3.duration.fast, useNativeDriver: true }).start();
3963
+ React33.useEffect(() => {
3964
+ Animated19.timing(sink, { toValue: down ? 1 : 0, duration: motion3.duration.fast, useNativeDriver: true }).start();
3662
3965
  }, [down, sink, motion3.duration.fast]);
3663
- return /* @__PURE__ */ jsxs37(
3664
- Pressable15,
3966
+ return /* @__PURE__ */ jsxs40(
3967
+ Pressable18,
3665
3968
  {
3666
3969
  role: "radio",
3667
3970
  "aria-checked": checked,
@@ -3671,14 +3974,14 @@ function Key({ option, checked, disabled, onPress }) {
3671
3974
  onPress,
3672
3975
  onPressIn: () => setHeld(true),
3673
3976
  onPressOut: () => setHeld(false),
3674
- style: [styles32.keySlot, disabled ? styles32.disabled : null],
3977
+ style: [styles35.keySlot, disabled ? styles35.disabled : null],
3675
3978
  children: [
3676
- /* @__PURE__ */ jsx43(View36, { style: [styles32.ledge, { borderRadius: radius3.lg, backgroundColor: checked ? theme.accentHover : theme.borderStrong }] }),
3677
- /* @__PURE__ */ jsxs37(
3678
- Animated17.View,
3979
+ /* @__PURE__ */ jsx46(View39, { style: [styles35.ledge, { borderRadius: radius3.lg, backgroundColor: checked ? theme.accentHover : theme.borderStrong }] }),
3980
+ /* @__PURE__ */ jsxs40(
3981
+ Animated19.View,
3679
3982
  {
3680
3983
  style: [
3681
- styles32.key,
3984
+ styles35.key,
3682
3985
  {
3683
3986
  borderRadius: radius3.lg,
3684
3987
  backgroundColor: checked ? theme.accent : theme.surface2,
@@ -3687,8 +3990,8 @@ function Key({ option, checked, disabled, onPress }) {
3687
3990
  }
3688
3991
  ],
3689
3992
  children: [
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
3993
+ /* @__PURE__ */ jsx46(Text15, { style: [styles35.keyLabel, { color: checked ? theme.onAccent : theme.textPrimary }], children: option.label }),
3994
+ option.hint ? /* @__PURE__ */ jsx46(Text15, { style: [styles35.keyHint, { color: checked ? theme.onAccent : theme.textSecondary }], children: option.hint }) : null
3692
3995
  ]
3693
3996
  }
3694
3997
  )
@@ -3698,7 +4001,7 @@ function Key({ option, checked, disabled, onPress }) {
3698
4001
  }
3699
4002
  function RadioGroup({ label, options, value: valueProp, defaultValue = null, onValueChange, variant = "list", error, disabled, style }) {
3700
4003
  const { theme, radius: radius3, haptic } = useTheme();
3701
- const [own, setOwn] = React30.useState(defaultValue);
4004
+ const [own, setOwn] = React33.useState(defaultValue);
3702
4005
  const value = valueProp !== void 0 ? valueProp : own;
3703
4006
  const pick = (v) => {
3704
4007
  haptic(variant === "buttons" ? "impact" : "selection");
@@ -3709,10 +4012,10 @@ function RadioGroup({ label, options, value: valueProp, defaultValue = null, onV
3709
4012
  const checked = o.value === value;
3710
4013
  const off = Boolean(disabled || o.disabled);
3711
4014
  const name = o.description ? `${o.label}, ${o.description}` : o.label;
3712
- if (variant === "buttons") return /* @__PURE__ */ jsx43(Key, { option: o, checked, disabled: off, onPress: () => pick(o.value) }, o.value);
4015
+ if (variant === "buttons") return /* @__PURE__ */ jsx46(Key, { option: o, checked, disabled: off, onPress: () => pick(o.value) }, o.value);
3713
4016
  if (variant === "segmented")
3714
- return /* @__PURE__ */ jsx43(
3715
- Pressable15,
4017
+ return /* @__PURE__ */ jsx46(
4018
+ Pressable18,
3716
4019
  {
3717
4020
  role: "radio",
3718
4021
  "aria-checked": checked,
@@ -3720,14 +4023,14 @@ function RadioGroup({ label, options, value: valueProp, defaultValue = null, onV
3720
4023
  "aria-disabled": off || void 0,
3721
4024
  disabled: off,
3722
4025
  onPress: () => pick(o.value),
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 })
4026
+ style: [styles35.segment, { borderRadius: radius3.md }, checked ? { backgroundColor: theme.surface0, borderColor: theme.borderDefault } : null, off ? styles35.disabled : null],
4027
+ children: /* @__PURE__ */ jsx46(Text15, { numberOfLines: 1, style: [styles35.segmentLabel, { color: checked ? theme.textPrimary : theme.textSecondary }], children: o.label })
3725
4028
  },
3726
4029
  o.value
3727
4030
  );
3728
4031
  if (variant === "cards")
3729
- return /* @__PURE__ */ jsxs37(
3730
- Pressable15,
4032
+ return /* @__PURE__ */ jsxs40(
4033
+ Pressable18,
3731
4034
  {
3732
4035
  role: "radio",
3733
4036
  "aria-checked": checked,
@@ -3736,40 +4039,40 @@ function RadioGroup({ label, options, value: valueProp, defaultValue = null, onV
3736
4039
  disabled: off,
3737
4040
  onPress: () => pick(o.value),
3738
4041
  style: ({ pressed }) => [
3739
- styles32.card,
4042
+ styles35.card,
3740
4043
  { borderRadius: radius3.xl, backgroundColor: checked ? theme.accentSoft : theme.surface1, borderColor: checked ? theme.accent : theme.borderDefault, transform: [{ scale: pressed ? 0.98 : 1 }] },
3741
- off ? styles32.disabled : null
4044
+ off ? styles35.disabled : null
3742
4045
  ],
3743
4046
  children: [
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
4047
+ /* @__PURE__ */ jsx46(View39, { style: [styles35.cardCheck, { borderColor: checked ? theme.accent : theme.borderStrong, backgroundColor: checked ? theme.accent : theme.surface1 }], children: checked ? /* @__PURE__ */ jsx46(Check, { color: theme.onAccent }) : null }),
4048
+ /* @__PURE__ */ jsx46(Text15, { style: [styles35.cardLabel, { color: theme.textPrimary }], children: o.label }),
4049
+ o.description ? /* @__PURE__ */ jsx46(Text15, { style: [styles35.cardDescription, { color: theme.textSecondary }], children: o.description }) : null
3747
4050
  ]
3748
4051
  },
3749
4052
  o.value
3750
4053
  );
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
4054
+ return /* @__PURE__ */ jsxs40(Pressable18, { role: "radio", "aria-checked": checked, "aria-label": name, "aria-disabled": off || void 0, disabled: off, onPress: () => pick(o.value), style: [styles35.row, off ? styles35.disabled : null], children: [
4055
+ /* @__PURE__ */ jsx46(View39, { style: [styles35.dot, { borderColor: checked ? theme.accent : theme.borderStrong, backgroundColor: checked ? theme.accent : theme.surface1 }], children: checked ? /* @__PURE__ */ jsx46(View39, { style: [styles35.dotIn, { backgroundColor: theme.onAccent }] }) : null }),
4056
+ /* @__PURE__ */ jsxs40(View39, { style: styles35.rowText, children: [
4057
+ /* @__PURE__ */ jsx46(Text15, { style: [styles35.rowLabel, { color: theme.textPrimary }], children: o.label }),
4058
+ o.description ? /* @__PURE__ */ jsx46(Text15, { style: [styles35.cardDescription, { color: theme.textSecondary }], children: o.description }) : null
3756
4059
  ] })
3757
4060
  ] }, o.value);
3758
4061
  });
3759
- return /* @__PURE__ */ jsxs37(View36, { style: [styles32.root, style], children: [
3760
- /* @__PURE__ */ jsx43(
3761
- View36,
4062
+ return /* @__PURE__ */ jsxs40(View39, { style: [styles35.root, style], children: [
4063
+ /* @__PURE__ */ jsx46(
4064
+ View39,
3762
4065
  {
3763
4066
  role: "radiogroup",
3764
4067
  "aria-label": label,
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,
4068
+ style: variant === "segmented" ? [styles35.track, { borderRadius: radius3.lg, backgroundColor: theme.surface2, borderColor: error ? theme.danger : theme.borderDefault }] : variant === "buttons" ? styles35.keys : variant === "cards" ? styles35.cards : styles35.list,
3766
4069
  children: body
3767
4070
  }
3768
4071
  ),
3769
- error ? /* @__PURE__ */ jsx43(Text15, { role: "alert", "aria-live": "polite", style: [styles32.error, { color: theme.dangerText }], children: error }) : null
4072
+ error ? /* @__PURE__ */ jsx46(Text15, { role: "alert", "aria-live": "polite", style: [styles35.error, { color: theme.dangerText }], children: error }) : null
3770
4073
  ] });
3771
4074
  }
3772
- var styles32 = StyleSheet32.create({
4075
+ var styles35 = StyleSheet35.create({
3773
4076
  root: { gap: 6, alignSelf: "stretch" },
3774
4077
  list: { gap: 2 },
3775
4078
  row: { flexDirection: "row", alignItems: "center", gap: 12, minHeight: 44 },
@@ -3788,39 +4091,54 @@ var styles32 = StyleSheet32.create({
3788
4091
  key: { minHeight: 48, paddingHorizontal: 16, paddingVertical: 8, alignItems: "center", justifyContent: "center", gap: 1, borderWidth: 1 },
3789
4092
  keyLabel: { fontSize: 15, fontWeight: "700" },
3790
4093
  keyHint: { fontSize: 11, fontWeight: "500" },
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" },
4094
+ track: { flexDirection: "row", padding: 3, gap: 3, borderWidth: StyleSheet35.hairlineWidth, height: 42 },
4095
+ segment: { flex: 1, alignItems: "center", justifyContent: "center", paddingHorizontal: 8, borderWidth: StyleSheet35.hairlineWidth, borderColor: "transparent" },
3793
4096
  segmentLabel: { fontSize: 13, fontWeight: "600" },
3794
4097
  error: { fontSize: 12, lineHeight: 16 },
3795
4098
  disabled: { opacity: 0.4 }
3796
4099
  });
3797
4100
 
4101
+ // src/native/screen.tsx
4102
+ import { KeyboardAvoidingView, Platform as Platform3, ScrollView as ScrollView6, StyleSheet as StyleSheet36, View as View40 } from "react-native";
4103
+ import { Fragment as Fragment7, jsx as jsx47, jsxs as jsxs41 } from "react/jsx-runtime";
4104
+ function Screen({ header, footer, children, scroll = true, keyboard = true, padding = 16, surface = "surface0", contentStyle }) {
4105
+ const { theme, insets } = useTheme();
4106
+ const body = scroll ? /* @__PURE__ */ jsx47(ScrollView6, { style: styles36.flex, contentContainerStyle: [{ padding, paddingTop: header ? padding : padding + insets.top, gap: 16 }, contentStyle], keyboardShouldPersistTaps: "handled", tabIndex: 0, children }) : /* @__PURE__ */ jsx47(View40, { style: [styles36.flex, { paddingTop: header ? 0 : insets.top }, contentStyle], children });
4107
+ const inner = /* @__PURE__ */ jsxs41(Fragment7, { children: [
4108
+ header,
4109
+ body,
4110
+ footer
4111
+ ] });
4112
+ return /* @__PURE__ */ jsx47(View40, { style: [styles36.flex, { backgroundColor: theme[surface] }], children: keyboard ? /* @__PURE__ */ jsx47(KeyboardAvoidingView, { style: styles36.flex, behavior: Platform3.OS === "ios" ? "padding" : void 0, children: inner }) : inner });
4113
+ }
4114
+ var styles36 = StyleSheet36.create({ flex: { flex: 1 } });
4115
+
3798
4116
  // src/native/search-field.tsx
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";
4117
+ import * as React34 from "react";
4118
+ import { Pressable as Pressable19, StyleSheet as StyleSheet37, TextInput as TextInput6, View as View41 } from "react-native";
4119
+ import Svg22, { Circle as Circle12, Path as Path18 } from "react-native-svg";
4120
+ import { jsx as jsx48, jsxs as jsxs42 } from "react/jsx-runtime";
3803
4121
  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);
4122
+ const [focused, setFocused] = React34.useState(false);
4123
+ const input = React34.useRef(null);
3806
4124
  const { theme, radius: radius3 } = useTheme();
3807
- const [own, setOwn] = React31.useState(defaultValue);
4125
+ const [own, setOwn] = React34.useState(defaultValue);
3808
4126
  const query = value ?? own;
3809
- const timer2 = React31.useRef(void 0);
3810
- React31.useEffect(() => () => clearTimeout(timer2.current), []);
4127
+ const timer2 = React34.useRef(void 0);
4128
+ React34.useEffect(() => () => clearTimeout(timer2.current), []);
3811
4129
  const change = (next) => {
3812
4130
  if (value === void 0) setOwn(next);
3813
4131
  onValueChange?.(next);
3814
4132
  clearTimeout(timer2.current);
3815
4133
  if (onSearch) timer2.current = setTimeout(() => onSearch(next), debounce);
3816
4134
  };
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" })
4135
+ const field = /* @__PURE__ */ jsxs42(View41, { style: [styles37.frame, { borderRadius: radius3.md, borderColor: theme.borderDefault, backgroundColor: theme.surface2 }, style], children: [
4136
+ /* @__PURE__ */ jsxs42(Svg22, { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: theme.textSecondary, strokeWidth: 2, strokeLinecap: "round", "aria-hidden": true, children: [
4137
+ /* @__PURE__ */ jsx48(Circle12, { cx: 11, cy: 11, r: 7 }),
4138
+ /* @__PURE__ */ jsx48(Path18, { d: "m20 20-3.5-3.5" })
3821
4139
  ] }),
3822
- /* @__PURE__ */ jsx44(
3823
- TextInput5,
4140
+ /* @__PURE__ */ jsx48(
4141
+ TextInput6,
3824
4142
  {
3825
4143
  ref: input,
3826
4144
  role: "searchbox",
@@ -3838,7 +4156,7 @@ function SearchField({ label, value, defaultValue = "", onValueChange, onSearch,
3838
4156
  onSearch?.(query);
3839
4157
  onSubmit?.(query);
3840
4158
  },
3841
- style: [styles33.input, { color: theme.textPrimary }],
4159
+ style: [styles37.input, { color: theme.textPrimary }],
3842
4160
  onFocus: (e) => {
3843
4161
  setFocused(true);
3844
4162
  onFocus?.(e);
@@ -3850,13 +4168,13 @@ function SearchField({ label, value, defaultValue = "", onValueChange, onSearch,
3850
4168
  ...props
3851
4169
  }
3852
4170
  ),
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
4171
+ query ? /* @__PURE__ */ jsx48(Pressable19, { role: "button", "aria-label": clearLabel, hitSlop: 10, onPress: () => change(""), style: styles37.clear, children: /* @__PURE__ */ jsx48(Svg22, { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: theme.textSecondary, strokeWidth: 2.4, strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx48(Path18, { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
3854
4172
  ] });
3855
4173
  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,
4174
+ return /* @__PURE__ */ jsxs42(View41, { style: styles37.bar, children: [
4175
+ /* @__PURE__ */ jsx48(View41, { style: styles37.grow, children: field }),
4176
+ focused || query ? /* @__PURE__ */ jsx48(
4177
+ Pressable19,
3860
4178
  {
3861
4179
  role: "button",
3862
4180
  onPress: () => {
@@ -3865,14 +4183,14 @@ function SearchField({ label, value, defaultValue = "", onValueChange, onSearch,
3865
4183
  onCancel();
3866
4184
  },
3867
4185
  hitSlop: 8,
3868
- style: styles33.cancel,
3869
- children: /* @__PURE__ */ jsx44(Txt, { variant: "label", tone: "accent", children: cancelLabel })
4186
+ style: styles37.cancel,
4187
+ children: /* @__PURE__ */ jsx48(Txt, { variant: "label", tone: "accent", children: cancelLabel })
3870
4188
  }
3871
4189
  ) : null
3872
4190
  ] });
3873
4191
  }
3874
- var styles33 = StyleSheet33.create({
3875
- frame: { flexDirection: "row", alignItems: "center", gap: 8, height: 44, paddingLeft: 12, paddingRight: 6, borderWidth: StyleSheet33.hairlineWidth },
4192
+ var styles37 = StyleSheet37.create({
4193
+ frame: { flexDirection: "row", alignItems: "center", gap: 8, height: 44, paddingLeft: 12, paddingRight: 6, borderWidth: StyleSheet37.hairlineWidth },
3876
4194
  input: { flex: 1, height: "100%", fontSize: 15, paddingVertical: 0 },
3877
4195
  bar: { flexDirection: "row", alignItems: "center", gap: 10 },
3878
4196
  grow: { flex: 1 },
@@ -3881,20 +4199,20 @@ var styles33 = StyleSheet33.create({
3881
4199
  });
3882
4200
 
3883
4201
  // src/native/segmented.tsx
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";
4202
+ import { Pressable as Pressable20, StyleSheet as StyleSheet38, Text as Text16, View as View42 } from "react-native";
4203
+ import { jsx as jsx49 } from "react/jsx-runtime";
3886
4204
  function Segmented({ options, value, onValueChange, size = "md", "aria-label": label, style }) {
3887
4205
  const { theme, radius: radius3 } = useTheme();
3888
- return /* @__PURE__ */ jsx45(
3889
- View38,
4206
+ return /* @__PURE__ */ jsx49(
4207
+ View42,
3890
4208
  {
3891
4209
  role: "tablist",
3892
4210
  "aria-label": label,
3893
- style: [styles34.track, { backgroundColor: theme.surface2, borderColor: theme.borderSubtle, borderRadius: radius3.md, height: size === "sm" ? 32 : 40 }, style],
4211
+ style: [styles38.track, { backgroundColor: theme.surface2, borderColor: theme.borderSubtle, borderRadius: radius3.md, height: size === "sm" ? 32 : 40 }, style],
3894
4212
  children: options.map((option) => {
3895
4213
  const selected = option.value === value;
3896
- return /* @__PURE__ */ jsx45(
3897
- Pressable17,
4214
+ return /* @__PURE__ */ jsx49(
4215
+ Pressable20,
3898
4216
  {
3899
4217
  role: "tab",
3900
4218
  "aria-selected": selected,
@@ -3904,12 +4222,12 @@ function Segmented({ options, value, onValueChange, size = "md", "aria-label": l
3904
4222
  if (!selected) onValueChange(option.value);
3905
4223
  },
3906
4224
  style: [
3907
- styles34.segment,
4225
+ styles38.segment,
3908
4226
  { borderRadius: radius3.sm },
3909
4227
  selected ? { backgroundColor: theme.surface0, borderColor: theme.borderDefault } : null,
3910
- option.disabled ? styles34.disabled : null
4228
+ option.disabled ? styles38.disabled : null
3911
4229
  ],
3912
- children: /* @__PURE__ */ jsx45(Text16, { numberOfLines: 1, style: [styles34.label, { color: selected ? theme.textPrimary : theme.textSecondary, fontSize: size === "sm" ? 12 : 13 }], children: option.label })
4230
+ children: /* @__PURE__ */ jsx49(Text16, { numberOfLines: 1, style: [styles38.label, { color: selected ? theme.textPrimary : theme.textSecondary, fontSize: size === "sm" ? 12 : 13 }], children: option.label })
3913
4231
  },
3914
4232
  option.value
3915
4233
  );
@@ -3917,17 +4235,17 @@ function Segmented({ options, value, onValueChange, size = "md", "aria-label": l
3917
4235
  }
3918
4236
  );
3919
4237
  }
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" },
4238
+ var styles38 = StyleSheet38.create({
4239
+ track: { flexDirection: "row", padding: 3, gap: 3, borderWidth: StyleSheet38.hairlineWidth },
4240
+ segment: { flex: 1, alignItems: "center", justifyContent: "center", paddingHorizontal: 8, borderWidth: StyleSheet38.hairlineWidth, borderColor: "transparent" },
3923
4241
  label: { fontWeight: "600" },
3924
4242
  disabled: { opacity: 0.4 }
3925
4243
  });
3926
4244
 
3927
4245
  // src/native/skeleton.tsx
3928
- import * as React32 from "react";
3929
- import { Animated as Animated18 } from "react-native";
3930
- import { jsx as jsx46 } from "react/jsx-runtime";
4246
+ import * as React35 from "react";
4247
+ import { Animated as Animated20 } from "react-native";
4248
+ import { jsx as jsx50 } from "react/jsx-runtime";
3931
4249
  var SHAPE = {
3932
4250
  text: { width: "100%", height: 12, radius: 4 },
3933
4251
  circle: { width: 40, height: 40, radius: 9999 },
@@ -3936,13 +4254,13 @@ var SHAPE = {
3936
4254
  function Skeleton({ shape = "text", width, height, style, testID }) {
3937
4255
  const { theme } = useTheme();
3938
4256
  const reduce = useReducedMotion();
3939
- const [opacity] = React32.useState(() => new Animated18.Value(1));
3940
- React32.useEffect(() => {
4257
+ const [opacity] = React35.useState(() => new Animated20.Value(1));
4258
+ React35.useEffect(() => {
3941
4259
  if (reduce) return;
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 })
4260
+ const loop = Animated20.loop(
4261
+ Animated20.sequence([
4262
+ Animated20.timing(opacity, { toValue: 0.5, duration: 900, useNativeDriver: true }),
4263
+ Animated20.timing(opacity, { toValue: 1, duration: 900, useNativeDriver: true })
3946
4264
  ])
3947
4265
  );
3948
4266
  loop.start();
@@ -3953,8 +4271,8 @@ function Skeleton({ shape = "text", width, height, style, testID }) {
3953
4271
  }, [reduce, opacity]);
3954
4272
  const s = SHAPE[shape];
3955
4273
  const side = shape === "circle" ? width ?? height ?? s.width : void 0;
3956
- return /* @__PURE__ */ jsx46(
3957
- Animated18.View,
4274
+ return /* @__PURE__ */ jsx50(
4275
+ Animated20.View,
3958
4276
  {
3959
4277
  testID,
3960
4278
  "aria-hidden": true,
@@ -3967,10 +4285,10 @@ function Skeleton({ shape = "text", width, height, style, testID }) {
3967
4285
  }
3968
4286
 
3969
4287
  // src/native/slider.tsx
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";
4288
+ import * as React36 from "react";
4289
+ import { PanResponder as PanResponder2, StyleSheet as StyleSheet39, Text as Text17, View as View43 } from "react-native";
4290
+ import Svg23, { Defs as Defs11, LinearGradient as LinearGradient11, Rect as Rect4, Stop as Stop11 } from "react-native-svg";
4291
+ import { jsx as jsx51, jsxs as jsxs43 } from "react/jsx-runtime";
3974
4292
  var THUMB = 26;
3975
4293
  var toArray = (v) => v === void 0 ? void 0 : typeof v === "number" ? [v] : [...v];
3976
4294
  function Slider({
@@ -3996,20 +4314,20 @@ function Slider({
3996
4314
  const { theme, radius: radius3, haptic } = useTheme();
3997
4315
  const range = Array.isArray(value ?? defaultValue);
3998
4316
  const vertical = orientation === "vertical";
3999
- const [inner, setInner] = React33.useState(() => toArray(defaultValue) ?? [min]);
4317
+ const [inner, setInner] = React36.useState(() => toArray(defaultValue) ?? [min]);
4000
4318
  const current = toArray(value) ?? inner;
4001
- const [length, setLength] = React33.useState(0);
4002
- const [dragging, setDragging] = React33.useState(null);
4319
+ const [length, setLength] = React36.useState(0);
4320
+ const [dragging, setDragging] = React36.useState(null);
4003
4321
  const gradientId = useSvgId("kzs");
4004
4322
  const out = (next) => range ? [next[0], next[1]] : next[0];
4005
4323
  const snap = (v) => Math.min(max, Math.max(min, Math.round((v - min) / step) * step + min));
4006
4324
  const pct = (v) => (v - min) / (max - min || 1);
4007
- const live = React33.useRef({ current, length, vertical, disabled });
4008
- React33.useLayoutEffect(() => {
4325
+ const live = React36.useRef({ current, length, vertical, disabled });
4326
+ React36.useLayoutEffect(() => {
4009
4327
  live.current = { current, length, vertical, disabled };
4010
4328
  });
4011
- const active = React33.useRef(0);
4012
- const start = React33.useRef(0);
4329
+ const active = React36.useRef(0);
4330
+ const start = React36.useRef(0);
4013
4331
  const set = (next) => {
4014
4332
  if (value === void 0) setInner(next);
4015
4333
  onValueChange?.(out(next));
@@ -4030,11 +4348,11 @@ function Slider({
4030
4348
  return min + p * (max - min);
4031
4349
  };
4032
4350
  const commit = () => onValueCommit?.(out(live.current.current));
4033
- const handlers = React33.useRef({ move, at, commit });
4034
- React33.useLayoutEffect(() => {
4351
+ const handlers = React36.useRef({ move, at, commit });
4352
+ React36.useLayoutEffect(() => {
4035
4353
  handlers.current = { move, at, commit };
4036
4354
  });
4037
- const [responder] = React33.useState(
4355
+ const [responder] = React36.useState(
4038
4356
  () => PanResponder2.create({
4039
4357
  onStartShouldSetPanResponder: () => !live.current.disabled,
4040
4358
  onMoveShouldSetPanResponder: () => !live.current.disabled,
@@ -4062,24 +4380,24 @@ function Slider({
4062
4380
  const along = (p) => vertical ? { bottom: p * length } : { left: p * length };
4063
4381
  const onLayout = (e) => setLength(vertical ? e.nativeEvent.layout.height : e.nativeEvent.layout.width);
4064
4382
  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 };
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 ") })
4383
+ return /* @__PURE__ */ jsxs43(View43, { style: [styles39.root, vertical ? styles39.rootVertical : null, disabled ? styles39.disabled : null, style], children: [
4384
+ showLabel ? /* @__PURE__ */ jsxs43(View43, { style: styles39.header, children: [
4385
+ /* @__PURE__ */ jsx51(Text17, { style: [styles39.label, { color: theme.textSecondary }], children: label }),
4386
+ /* @__PURE__ */ jsx51(Text17, { "aria-hidden": true, style: [styles39.value, { color: theme.textSecondary }], children: current.map(formatValue).join(" \u2013 ") })
4069
4387
  ] }) : null,
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 })
4388
+ /* @__PURE__ */ jsxs43(View43, { ...responder.panHandlers, style: vertical ? styles39.controlVertical : styles39.control, children: [
4389
+ /* @__PURE__ */ jsxs43(View43, { onLayout, pointerEvents: "none", style: [vertical ? styles39.trackVertical : styles39.track, { borderRadius: radius3.full, backgroundColor: theme.surface3 }], children: [
4390
+ /* @__PURE__ */ jsx51(View43, { style: [styles39.fill, fill, { borderRadius: radius3.full, overflow: "hidden", backgroundColor: theme.accent }], children: tone3 === "gradient" ? /* @__PURE__ */ jsxs43(Svg23, { width: "100%", height: "100%", "aria-hidden": true, children: [
4391
+ /* @__PURE__ */ jsx51(Defs11, { children: /* @__PURE__ */ jsxs43(LinearGradient11, { id: gradientId, x1: "0", y1: vertical ? "1" : "0", x2: vertical ? "0" : "1", y2: "0", children: [
4392
+ /* @__PURE__ */ jsx51(Stop11, { offset: "0", stopColor: theme.accent }),
4393
+ /* @__PURE__ */ jsx51(Stop11, { offset: "1", stopColor: theme.accent2 })
4076
4394
  ] }) }),
4077
- /* @__PURE__ */ jsx47(Rect4, { width: "100%", height: "100%", fill: `url(#${gradientId})` })
4395
+ /* @__PURE__ */ jsx51(Rect4, { width: "100%", height: "100%", fill: `url(#${gradientId})` })
4078
4396
  ] }) : null }),
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))
4397
+ tickValues.map((t) => /* @__PURE__ */ jsx51(View43, { style: [vertical ? styles39.tickVertical : styles39.tick, along(pct(t)), { backgroundColor: t > lo && t < hi ? theme.onAccent : theme.borderStrong }] }, t))
4080
4398
  ] }),
4081
- current.map((v, i) => /* @__PURE__ */ jsx47(
4082
- View39,
4399
+ current.map((v, i) => /* @__PURE__ */ jsx51(
4400
+ View43,
4083
4401
  {
4084
4402
  accessible: true,
4085
4403
  role: "slider",
@@ -4098,16 +4416,16 @@ function Slider({
4098
4416
  onValueCommit?.(out(values));
4099
4417
  },
4100
4418
  pointerEvents: "none",
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
4419
+ style: [styles39.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 }],
4420
+ children: floatingValue === "always" || floatingValue && dragging === i ? /* @__PURE__ */ jsx51(View43, { "aria-hidden": true, style: [vertical ? styles39.bubbleVertical : styles39.bubble, { backgroundColor: theme.textPrimary, borderRadius: radius3.md }], children: /* @__PURE__ */ jsx51(Text17, { style: [styles39.bubbleText, { color: theme.surface0 }], children: formatValue(v) }) }) : null
4103
4421
  },
4104
4422
  i
4105
4423
  ))
4106
4424
  ] }),
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
4425
+ marks2?.length && !vertical ? /* @__PURE__ */ jsx51(View43, { "aria-hidden": true, style: styles39.marks, children: marks2.map((m) => /* @__PURE__ */ jsx51(Text17, { style: [styles39.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
4108
4426
  ] });
4109
4427
  }
4110
- var styles35 = StyleSheet35.create({
4428
+ var styles39 = StyleSheet39.create({
4111
4429
  root: { gap: 8, alignSelf: "stretch" },
4112
4430
  rootVertical: { alignSelf: "flex-start", alignItems: "center" },
4113
4431
  header: { flexDirection: "row", justifyContent: "space-between", alignItems: "baseline", gap: 12 },
@@ -4143,10 +4461,10 @@ var styles35 = StyleSheet35.create({
4143
4461
 
4144
4462
  // src/native/spinner.tsx
4145
4463
  import { ActivityIndicator as ActivityIndicator2 } from "react-native";
4146
- import { jsx as jsx48 } from "react/jsx-runtime";
4464
+ import { jsx as jsx52 } from "react/jsx-runtime";
4147
4465
  function Spinner({ label, size = "md", ...props }) {
4148
4466
  const { theme } = useTheme();
4149
- return /* @__PURE__ */ jsx48(
4467
+ return /* @__PURE__ */ jsx52(
4150
4468
  ActivityIndicator2,
4151
4469
  {
4152
4470
  accessible: true,
@@ -4160,37 +4478,63 @@ function Spinner({ label, size = "md", ...props }) {
4160
4478
  );
4161
4479
  }
4162
4480
 
4481
+ // src/native/step-progress.tsx
4482
+ import { Pressable as Pressable21, StyleSheet as StyleSheet40, View as View44 } from "react-native";
4483
+ import Svg24, { Path as Path19 } from "react-native-svg";
4484
+ import { jsx as jsx53, jsxs as jsxs44 } from "react/jsx-runtime";
4485
+ function StepProgress({ step, total, label, backLabel, onBack, trailing, style }) {
4486
+ const { theme, insets } = useTheme();
4487
+ const words = label(step, total);
4488
+ return /* @__PURE__ */ jsxs44(View44, { style: [styles40.root, { paddingTop: insets.top + 8 }, style], children: [
4489
+ /* @__PURE__ */ jsxs44(View44, { style: styles40.row, children: [
4490
+ onBack && backLabel ? /* @__PURE__ */ jsx53(Pressable21, { role: "button", "aria-label": backLabel, hitSlop: 10, onPress: onBack, style: styles40.back, children: /* @__PURE__ */ jsx53(Svg24, { width: 22, height: 22, viewBox: "0 0 24 24", "aria-hidden": true, children: /* @__PURE__ */ jsx53(Path19, { d: "M15 5l-7 7 7 7", stroke: theme.textPrimary, strokeWidth: 2.4, fill: "none", strokeLinecap: "round", strokeLinejoin: "round" }) }) }) : /* @__PURE__ */ jsx53(View44, { style: styles40.back }),
4491
+ /* @__PURE__ */ jsx53(View44, { accessible: true, role: "progressbar", "aria-label": words, "aria-valuemin": 1, "aria-valuemax": total, "aria-valuenow": step, "aria-valuetext": words, style: styles40.bars, children: Array.from({ length: total }, (_, i) => /* @__PURE__ */ jsx53(View44, { style: [styles40.bar, { backgroundColor: i < step ? theme.accent : theme.surface3 }] }, i)) }),
4492
+ /* @__PURE__ */ jsx53(View44, { style: styles40.trailing, children: trailing })
4493
+ ] }),
4494
+ /* @__PURE__ */ jsx53(Txt, { variant: "caption", tone: "secondary", style: styles40.words, "aria-hidden": true, children: words })
4495
+ ] });
4496
+ }
4497
+ var styles40 = StyleSheet40.create({
4498
+ root: { paddingHorizontal: 12, gap: 6 },
4499
+ row: { flexDirection: "row", alignItems: "center", gap: 8 },
4500
+ back: { width: 40, height: 40, alignItems: "center", justifyContent: "center" },
4501
+ bars: { flex: 1, flexDirection: "row", gap: 4 },
4502
+ bar: { flex: 1, height: 4, borderRadius: 2 },
4503
+ trailing: { minWidth: 40, alignItems: "flex-end" },
4504
+ words: { textAlign: "center" }
4505
+ });
4506
+
4163
4507
  // 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";
4508
+ import { StyleSheet as StyleSheet41, View as View45 } from "react-native";
4509
+ import Svg25, { Circle as Circle13, Path as Path20 } from "react-native-svg";
4510
+ import { jsx as jsx54, jsxs as jsxs45 } from "react/jsx-runtime";
4167
4511
  var WORDS = { done: "done", current: "in progress", upcoming: "to come", error: "failed" };
4168
4512
  function Stepper({ steps, current = 0, orientation = "vertical", statusLabels, "aria-label": label, style }) {
4169
4513
  const { theme } = useTheme();
4170
4514
  const words = { ...WORDS, ...statusLabels };
4171
4515
  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) => {
4516
+ return /* @__PURE__ */ jsx54(View45, { role: "list", "aria-label": label, style: [vertical ? styles41.column : styles41.row, style], children: steps.map((step, i) => {
4173
4517
  const status = step.status ?? (i < current ? "done" : i === current ? "current" : "upcoming");
4174
4518
  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
4519
+ const node = status === "current" ? /* @__PURE__ */ jsx54(LoaderGlyph, { value: step.value ?? null, size: 24 }) : status === "error" ? /* @__PURE__ */ jsx54(LoaderGlyph, { state: "error", size: 24 }) : /* @__PURE__ */ jsxs45(Svg25, { width: 24, height: 24, viewBox: "0 0 24 24", "aria-hidden": true, children: [
4520
+ /* @__PURE__ */ jsx54(Circle13, { cx: 12, cy: 12, r: 10, fill: status === "done" ? theme.accent : "none", stroke: status === "done" ? theme.accent : theme.borderStrong, strokeWidth: 2 }),
4521
+ status === "done" ? /* @__PURE__ */ jsx54(Path20, { d: "M7.5 12.3l3 3 6-6.3", stroke: theme.onAccent, strokeWidth: 2.2, fill: "none", strokeLinecap: "round", strokeLinejoin: "round" }) : null
4178
4522
  ] });
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: [
4523
+ const connector = !last ? /* @__PURE__ */ jsx54(View45, { "aria-hidden": true, style: [vertical ? styles41.vLine : styles41.hLine, { backgroundColor: status === "done" ? theme.accent : theme.borderDefault }] }) : null;
4524
+ return /* @__PURE__ */ jsxs45(View45, { role: "listitem", accessible: true, "aria-label": `${step.title}, ${words[status]}`, style: vertical ? styles41.vStep : styles41.hStep, children: [
4525
+ /* @__PURE__ */ jsxs45(View45, { style: vertical ? styles41.vRail : styles41.hRail, children: [
4182
4526
  node,
4183
4527
  connector
4184
4528
  ] }),
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
4529
+ /* @__PURE__ */ jsxs45(View45, { style: [styles41.body, vertical && !last ? { paddingBottom: 20 } : null], children: [
4530
+ /* @__PURE__ */ jsx54(Txt, { variant: "label", tone: status === "upcoming" ? "secondary" : "text", numberOfLines: vertical ? void 0 : 2, children: step.title }),
4531
+ step.description ? /* @__PURE__ */ jsx54(Txt, { variant: "caption", tone: "secondary", children: step.description }) : null,
4532
+ step.content && (status === "current" || status === "error") ? /* @__PURE__ */ jsx54(View45, { style: styles41.content, children: step.content }) : null
4189
4533
  ] })
4190
4534
  ] }, i);
4191
4535
  }) });
4192
4536
  }
4193
- var styles36 = StyleSheet36.create({
4537
+ var styles41 = StyleSheet41.create({
4194
4538
  column: { gap: 0 },
4195
4539
  row: { flexDirection: "row" },
4196
4540
  vStep: { flexDirection: "row", gap: 12 },
@@ -4203,30 +4547,184 @@ var styles36 = StyleSheet36.create({
4203
4547
  content: { marginTop: 8 }
4204
4548
  });
4205
4549
 
4550
+ // src/native/swipe-deck.tsx
4551
+ import * as React37 from "react";
4552
+ import { AccessibilityInfo as AccessibilityInfo13, Animated as Animated21, Image as Image5, PanResponder as PanResponder3, Platform as Platform4, Pressable as Pressable22, StyleSheet as StyleSheet42, useWindowDimensions as useWindowDimensions2, View as View46 } from "react-native";
4553
+ import Svg26, { Defs as Defs12, LinearGradient as LinearGradient12, Path as Path21, Rect as Rect5, Stop as Stop12 } from "react-native-svg";
4554
+ import { Fragment as Fragment8, jsx as jsx55, jsxs as jsxs46 } from "react/jsx-runtime";
4555
+ function PersonCard({ photos, name, age, badge, meta, bio, footer, photoLabel = (n, t) => `Photo ${n} of ${t}`, style }) {
4556
+ const { theme, radius: radius3 } = useTheme();
4557
+ const [index, setIndex] = React37.useState(0);
4558
+ const gradient = useSvgId("kz-profile-");
4559
+ const photo = photos[index];
4560
+ return /* @__PURE__ */ jsxs46(
4561
+ View46,
4562
+ {
4563
+ accessible: Platform4.OS !== "web",
4564
+ accessibilityActions: photos.length > 1 ? [{ name: "increment" }, { name: "decrement" }] : [],
4565
+ onAccessibilityAction: (e) => setIndex((i) => Math.max(0, Math.min(photos.length - 1, i + (e.nativeEvent.actionName === "increment" ? 1 : -1)))),
4566
+ role: Platform4.OS === "web" ? "group" : "img",
4567
+ "aria-label": [`${name}${age !== void 0 ? `, ${age}` : ""}`, bio, photos.length > 1 ? photoLabel(index + 1, photos.length) : null].filter(Boolean).join(". "),
4568
+ style: [styles42.card, { borderRadius: radius3.xl, backgroundColor: theme.media }, style],
4569
+ children: [
4570
+ photo ? /* @__PURE__ */ jsx55(Image5, { source: { uri: photo.uri }, style: StyleSheet42.absoluteFill, resizeMode: "cover" }) : null,
4571
+ photos.length > 1 ? /* @__PURE__ */ jsxs46(Fragment8, { children: [
4572
+ /* @__PURE__ */ jsx55(View46, { style: styles42.bars, "aria-hidden": true, children: photos.map((_, i) => /* @__PURE__ */ jsx55(View46, { style: [styles42.bar, { backgroundColor: theme.textOnMedia, opacity: i === index ? 1 : 0.4 }] }, i)) }),
4573
+ /* @__PURE__ */ jsx55(Pressable22, { "aria-hidden": true, accessible: false, focusable: false, tabIndex: -1, style: [styles42.half, { left: 0 }], onPress: () => setIndex((i) => Math.max(0, i - 1)) }),
4574
+ /* @__PURE__ */ jsx55(Pressable22, { "aria-hidden": true, accessible: false, focusable: false, tabIndex: -1, style: [styles42.half, { right: 0 }], onPress: () => setIndex((i) => Math.min(photos.length - 1, i + 1)) })
4575
+ ] }) : null,
4576
+ /* @__PURE__ */ jsxs46(View46, { pointerEvents: "box-none", style: styles42.bottom, children: [
4577
+ /* @__PURE__ */ jsxs46(Svg26, { style: StyleSheet42.absoluteFill, width: "100%", height: "100%", "aria-hidden": true, children: [
4578
+ /* @__PURE__ */ jsx55(Defs12, { children: /* @__PURE__ */ jsxs46(LinearGradient12, { id: gradient, x1: "0", y1: "0", x2: "0", y2: "1", children: [
4579
+ /* @__PURE__ */ jsx55(Stop12, { offset: "0", stopColor: theme.scrimStrong, stopOpacity: 0 }),
4580
+ /* @__PURE__ */ jsx55(Stop12, { offset: "0.5", stopColor: theme.scrimStrong, stopOpacity: 0.8 }),
4581
+ /* @__PURE__ */ jsx55(Stop12, { offset: "1", stopColor: theme.scrimStrong, stopOpacity: 1 })
4582
+ ] }) }),
4583
+ /* @__PURE__ */ jsx55(Rect5, { width: "100%", height: "100%", fill: `url(#${gradient})` })
4584
+ ] }),
4585
+ /* @__PURE__ */ jsxs46(View46, { style: styles42.text, children: [
4586
+ /* @__PURE__ */ jsxs46(View46, { style: styles42.nameRow, children: [
4587
+ /* @__PURE__ */ jsxs46(Txt, { variant: "display", tone: "onMedia", style: styles42.name, numberOfLines: 1, children: [
4588
+ name,
4589
+ age !== void 0 ? /* @__PURE__ */ jsx55(Txt, { variant: "display", tone: "onMedia", style: styles42.age, children: ` ${age}` }) : null
4590
+ ] }),
4591
+ badge
4592
+ ] }),
4593
+ meta,
4594
+ bio ? /* @__PURE__ */ jsx55(Txt, { tone: "onMedia", numberOfLines: 2, children: bio }) : null,
4595
+ footer ? /* @__PURE__ */ jsx55(View46, { style: styles42.footer, children: footer }) : null
4596
+ ] })
4597
+ ] })
4598
+ ]
4599
+ }
4600
+ );
4601
+ }
4602
+ function SwipeDeck({ items: items2, getId, renderCard, onSwipe, empty, labels, hideButtons, style }) {
4603
+ const { theme, haptic } = useTheme();
4604
+ const reduce = useReducedMotion();
4605
+ const { width } = useWindowDimensions2();
4606
+ const [x] = React37.useState(() => new Animated21.Value(0));
4607
+ const top = items2[0];
4608
+ const decide = React37.useCallback(
4609
+ (direction) => {
4610
+ if (!top) return;
4611
+ haptic("impact");
4612
+ const done = () => {
4613
+ x.setValue(0);
4614
+ onSwipe(top, direction);
4615
+ if (items2.length === 1 && labels.empty) AccessibilityInfo13.announceForAccessibility(labels.empty);
4616
+ };
4617
+ if (reduce) return done();
4618
+ Animated21.timing(x, { toValue: (direction === "like" ? 1.4 : -1.4) * width, duration: 220, useNativeDriver: true }).start(done);
4619
+ },
4620
+ [top, haptic, reduce, x, width, onSwipe, items2.length, labels.empty]
4621
+ );
4622
+ const pan = React37.useMemo(
4623
+ () => PanResponder3.create({
4624
+ onMoveShouldSetPanResponder: (_, g) => Math.abs(g.dx) > 8 && Math.abs(g.dx) > Math.abs(g.dy),
4625
+ onPanResponderMove: (_, g) => x.setValue(g.dx),
4626
+ onPanResponderRelease: (_, g) => {
4627
+ if (g.dx > width / 3 || g.vx > 1) decide("like");
4628
+ else if (g.dx < -width / 3 || g.vx < -1) decide("pass");
4629
+ else Animated21.spring(x, { toValue: 0, useNativeDriver: true, friction: 6 }).start();
4630
+ }
4631
+ }),
4632
+ [x, width, decide]
4633
+ );
4634
+ const rotate = x.interpolate({ inputRange: [-width, 0, width], outputRange: ["-14deg", "0deg", "14deg"] });
4635
+ const likeOpacity = x.interpolate({ inputRange: [0, width / 4], outputRange: [0, 1], extrapolate: "clamp" });
4636
+ const passOpacity = x.interpolate({ inputRange: [-width / 4, 0], outputRange: [1, 0], extrapolate: "clamp" });
4637
+ const button = (direction) => /* @__PURE__ */ jsx55(
4638
+ Pressable22,
4639
+ {
4640
+ role: "button",
4641
+ "aria-label": direction === "like" ? labels.like : labels.pass,
4642
+ disabled: !top,
4643
+ onPress: () => decide(direction),
4644
+ style: ({ pressed }) => [
4645
+ styles42.button,
4646
+ { borderColor: direction === "like" ? theme.success : theme.danger, backgroundColor: theme.surface1, transform: [{ scale: pressed ? 0.92 : 1 }], opacity: top ? 1 : 0.4 }
4647
+ ],
4648
+ children: /* @__PURE__ */ jsx55(Svg26, { width: 28, height: 28, viewBox: "0 0 24 24", "aria-hidden": true, children: direction === "like" ? /* @__PURE__ */ jsx55(Path21, { d: "M12 20s-7-4.4-7-10a4 4 0 0 1 7-2.6A4 4 0 0 1 19 10c0 5.6-7 10-7 10z", fill: theme.success }) : /* @__PURE__ */ jsx55(Path21, { d: "M6 6l12 12M18 6 6 18", stroke: theme.danger, strokeWidth: 3, strokeLinecap: "round" }) })
4649
+ }
4650
+ );
4651
+ return /* @__PURE__ */ jsxs46(View46, { style: [styles42.deck, style], children: [
4652
+ /* @__PURE__ */ jsxs46(View46, { style: styles42.stack, children: [
4653
+ !top ? empty ?? null : null,
4654
+ items2.slice(0, 2).reverse().map((item) => {
4655
+ const isTop = item === top;
4656
+ return /* @__PURE__ */ jsxs46(
4657
+ Animated21.View,
4658
+ {
4659
+ ...isTop ? pan.panHandlers : {},
4660
+ accessibilityActions: isTop ? [{ name: "like", label: labels.like }, { name: "pass", label: labels.pass }] : [],
4661
+ onAccessibilityAction: (e) => isTop && decide(e.nativeEvent.actionName),
4662
+ "aria-hidden": !isTop,
4663
+ importantForAccessibility: isTop ? "auto" : "no-hide-descendants",
4664
+ pointerEvents: isTop ? "auto" : "none",
4665
+ style: [StyleSheet42.absoluteFill, isTop ? { transform: [{ translateX: x }, { rotate }] } : { transform: [{ scale: 0.96 }], opacity: 0.9 }],
4666
+ children: [
4667
+ renderCard(item),
4668
+ isTop ? /* @__PURE__ */ jsxs46(Fragment8, { children: [
4669
+ /* @__PURE__ */ jsx55(Animated21.View, { pointerEvents: "none", style: [styles42.stamp, styles42.stampLike, { borderColor: theme.success, opacity: likeOpacity }], "aria-hidden": true, children: /* @__PURE__ */ jsx55(Txt, { variant: "title", style: { color: theme.success }, children: labels.likeStamp ?? labels.like.toUpperCase() }) }),
4670
+ /* @__PURE__ */ jsx55(Animated21.View, { pointerEvents: "none", style: [styles42.stamp, styles42.stampPass, { borderColor: theme.danger, opacity: passOpacity }], "aria-hidden": true, children: /* @__PURE__ */ jsx55(Txt, { variant: "title", style: { color: theme.danger }, children: labels.passStamp ?? labels.pass.toUpperCase() }) })
4671
+ ] }) : null
4672
+ ]
4673
+ },
4674
+ getId(item)
4675
+ );
4676
+ })
4677
+ ] }),
4678
+ hideButtons ? null : /* @__PURE__ */ jsxs46(View46, { style: styles42.buttons, children: [
4679
+ button("pass"),
4680
+ button("like")
4681
+ ] })
4682
+ ] });
4683
+ }
4684
+ var styles42 = StyleSheet42.create({
4685
+ card: { flex: 1, overflow: "hidden" },
4686
+ bars: { position: "absolute", top: 8, left: 8, right: 8, flexDirection: "row", gap: 4 },
4687
+ bar: { flex: 1, height: 3, borderRadius: 2 },
4688
+ half: { position: "absolute", top: 0, bottom: "40%", width: "40%" },
4689
+ bottom: { position: "absolute", left: 0, right: 0, bottom: 0, paddingTop: 80 },
4690
+ text: { padding: 16, gap: 6 },
4691
+ nameRow: { flexDirection: "row", alignItems: "center", gap: 8 },
4692
+ name: { flexShrink: 1, fontSize: 28, lineHeight: 34 },
4693
+ age: { fontWeight: "400", fontSize: 26 },
4694
+ footer: { flexDirection: "row", flexWrap: "wrap", gap: 6, marginTop: 4 },
4695
+ deck: { flex: 1, gap: 16 },
4696
+ stack: { flex: 1 },
4697
+ stamp: { position: "absolute", top: 40, borderWidth: 3, borderRadius: 8, paddingHorizontal: 10, paddingVertical: 2 },
4698
+ stampLike: { left: 24, transform: [{ rotate: "-14deg" }] },
4699
+ stampPass: { right: 24, transform: [{ rotate: "14deg" }] },
4700
+ buttons: { flexDirection: "row", justifyContent: "center", gap: 28 },
4701
+ button: { width: 64, height: 64, borderRadius: 32, borderWidth: 2, alignItems: "center", justifyContent: "center" }
4702
+ });
4703
+
4206
4704
  // 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";
4705
+ import * as React38 from "react";
4706
+ import { Animated as Animated22, PanResponder as PanResponder4, Pressable as Pressable23, StyleSheet as StyleSheet43, View as View47 } from "react-native";
4707
+ import { jsx as jsx56, jsxs as jsxs47 } from "react/jsx-runtime";
4210
4708
  var toneColor = (t, tone3) => ({ neutral: t.surface3, accent: t.accent, success: t.success, warning: t.warning, danger: t.danger })[tone3 ?? "neutral"];
4211
4709
  var toneText = (tone3) => tone3 === "neutral" || tone3 === void 0 ? "text" : "onAccent";
4212
4710
  function SwipeableRow({ children, trailing = [], leading = [], fullSwipe = 0.6, actionWidth = 80, onActivate, testID, style }) {
4213
4711
  const { theme, haptic } = useTheme();
4214
4712
  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);
4713
+ const [x] = React38.useState(() => new Animated22.Value(0));
4714
+ const [width, setWidth] = React38.useState(0);
4715
+ const rest = React38.useRef(0);
4716
+ const armed = React38.useRef(false);
4219
4717
  const settle = (to) => {
4220
4718
  rest.current = to;
4221
4719
  if (reduce) x.setValue(to);
4222
- else Animated19.spring(x, { toValue: to, useNativeDriver: true, damping: 22, stiffness: 240 }).start();
4720
+ else Animated22.spring(x, { toValue: to, useNativeDriver: true, damping: 22, stiffness: 240 }).start();
4223
4721
  };
4224
4722
  const run = (action) => {
4225
4723
  settle(0);
4226
4724
  action.onPress();
4227
4725
  };
4228
- const pan = React34.useMemo(
4229
- () => PanResponder3.create({
4726
+ const pan = React38.useMemo(
4727
+ () => PanResponder4.create({
4230
4728
  onMoveShouldSetPanResponder: (_, g) => Math.abs(g.dx) > 8 && Math.abs(g.dx) > Math.abs(g.dy) * 1.5,
4231
4729
  onPanResponderMove: (_, g) => {
4232
4730
  let next = rest.current + g.dx;
@@ -4254,19 +4752,19 @@ function SwipeableRow({ children, trailing = [], leading = [], fullSwipe = 0.6,
4254
4752
  [trailing, leading, fullSwipe, width, actionWidth]
4255
4753
  // eslint-disable-line react-hooks/exhaustive-deps -- run/settle are stable in effect
4256
4754
  );
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) => (
4755
+ const side = (actions, edge) => /* @__PURE__ */ jsx56(View47, { "aria-hidden": true, style: [styles43.side, edge === "left" ? { left: 0 } : { right: 0, flexDirection: "row-reverse" }], children: actions.map((action, i) => (
4258
4756
  // 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: [
4757
+ /* @__PURE__ */ jsxs47(Pressable23, { focusable: false, tabIndex: -1, onPress: () => run(action), style: [styles43.action, { width: actionWidth, backgroundColor: toneColor(theme, action.tone) }], children: [
4260
4758
  action.icon,
4261
- /* @__PURE__ */ jsx50(Txt, { variant: "caption", tone: toneText(action.tone), style: styles37.actionText, numberOfLines: 1, children: action.label })
4759
+ /* @__PURE__ */ jsx56(Txt, { variant: "caption", tone: toneText(action.tone), style: styles43.actionText, numberOfLines: 1, children: action.label })
4262
4760
  ] }, i)
4263
4761
  )) });
4264
4762
  const all = [...leading, ...trailing];
4265
- return /* @__PURE__ */ jsxs41(View41, { style: [styles37.root, style], onLayout: (e) => setWidth(e.nativeEvent.layout.width), children: [
4763
+ return /* @__PURE__ */ jsxs47(View47, { style: [styles43.root, style], onLayout: (e) => setWidth(e.nativeEvent.layout.width), children: [
4266
4764
  leading.length > 0 ? side(leading, "left") : null,
4267
4765
  trailing.length > 0 ? side(trailing, "right") : null,
4268
- /* @__PURE__ */ jsx50(
4269
- Animated19.View,
4766
+ /* @__PURE__ */ jsx56(
4767
+ Animated22.View,
4270
4768
  {
4271
4769
  ...pan.panHandlers,
4272
4770
  accessible: true,
@@ -4277,13 +4775,13 @@ function SwipeableRow({ children, trailing = [], leading = [], fullSwipe = 0.6,
4277
4775
  const action = all.find((a) => a.label === e.nativeEvent.actionName);
4278
4776
  if (action) action.onPress();
4279
4777
  },
4280
- style: [styles37.front, { backgroundColor: theme.surface0, transform: [{ translateX: x }] }],
4778
+ style: [styles43.front, { backgroundColor: theme.surface0, transform: [{ translateX: x }] }],
4281
4779
  children
4282
4780
  }
4283
4781
  )
4284
4782
  ] });
4285
4783
  }
4286
- var styles37 = StyleSheet37.create({
4784
+ var styles43 = StyleSheet43.create({
4287
4785
  root: { overflow: "hidden" },
4288
4786
  side: { position: "absolute", top: 0, bottom: 0, flexDirection: "row" },
4289
4787
  action: { alignItems: "center", justifyContent: "center", gap: 4, paddingHorizontal: 6 },
@@ -4292,30 +4790,30 @@ var styles37 = StyleSheet37.create({
4292
4790
  });
4293
4791
 
4294
4792
  // src/native/switch.tsx
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";
4793
+ import * as React39 from "react";
4794
+ import { Animated as Animated23, Pressable as Pressable24, StyleSheet as StyleSheet44, Text as Text18, View as View48 } from "react-native";
4795
+ import { jsx as jsx57, jsxs as jsxs48 } from "react/jsx-runtime";
4298
4796
  var SIZES = { sm: { w: 40, h: 24, knob: 18 }, md: { w: 52, h: 32, knob: 26 } };
4299
4797
  function Switch({ label, checked, defaultChecked = false, onCheckedChange, description, showLabel, size = "md", error, disabled, style }) {
4300
4798
  const { theme, motion: motion3, haptic } = useTheme();
4301
- const [own, setOwn] = React35.useState(defaultChecked);
4799
+ const [own, setOwn] = React39.useState(defaultChecked);
4302
4800
  const on = checked ?? own;
4303
4801
  const d = SIZES[size];
4304
4802
  const travel = d.w - d.knob - (d.h - d.knob);
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();
4803
+ const [x] = React39.useState(() => new Animated23.Value(on ? 1 : 0));
4804
+ React39.useEffect(() => {
4805
+ Animated23.timing(x, { toValue: on ? 1 : 0, duration: motion3.duration.base, useNativeDriver: true }).start();
4308
4806
  }, [on, x, motion3.duration.base]);
4309
4807
  const toggle = () => {
4310
4808
  haptic("selection");
4311
4809
  if (checked === void 0) setOwn(!on);
4312
4810
  onCheckedChange?.(!on);
4313
4811
  };
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,
4812
+ const track = /* @__PURE__ */ jsx57(View48, { style: [styles44.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__ */ jsx57(
4813
+ Animated23.View,
4316
4814
  {
4317
4815
  style: [
4318
- styles38.knob,
4816
+ styles44.knob,
4319
4817
  {
4320
4818
  width: d.knob,
4321
4819
  height: d.knob,
@@ -4337,19 +4835,19 @@ function Switch({ label, checked, defaultChecked = false, onCheckedChange, descr
4337
4835
  onPress: toggle
4338
4836
  };
4339
4837
  if (!showLabel)
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
4838
+ return /* @__PURE__ */ jsx57(Pressable24, { ...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 ? styles44.disabled : null, style], children: track });
4839
+ return /* @__PURE__ */ jsxs48(View48, { style: [styles44.root, style], children: [
4840
+ /* @__PURE__ */ jsxs48(Pressable24, { ...a11y, style: [styles44.row, disabled ? styles44.disabled : null], children: [
4841
+ /* @__PURE__ */ jsxs48(View48, { style: styles44.text, children: [
4842
+ /* @__PURE__ */ jsx57(Text18, { style: [styles44.label, { color: theme.textPrimary }], children: label }),
4843
+ description ? /* @__PURE__ */ jsx57(Text18, { style: [styles44.description, { color: theme.textSecondary }], children: description }) : null
4346
4844
  ] }),
4347
4845
  track
4348
4846
  ] }),
4349
- error ? /* @__PURE__ */ jsx51(Text18, { role: "alert", "aria-live": "polite", style: [styles38.description, { color: theme.dangerText }], children: error }) : null
4847
+ error ? /* @__PURE__ */ jsx57(Text18, { role: "alert", "aria-live": "polite", style: [styles44.description, { color: theme.dangerText }], children: error }) : null
4350
4848
  ] });
4351
4849
  }
4352
- var styles38 = StyleSheet38.create({
4850
+ var styles44 = StyleSheet44.create({
4353
4851
  root: { gap: 2, alignSelf: "stretch" },
4354
4852
  row: { flexDirection: "row", alignItems: "center", gap: 16, minHeight: 48 },
4355
4853
  text: { flex: 1, gap: 2 },
@@ -4361,16 +4859,16 @@ var styles38 = StyleSheet38.create({
4361
4859
  });
4362
4860
 
4363
4861
  // 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";
4862
+ import { Pressable as Pressable25, StyleSheet as StyleSheet45, Text as Text19, View as View49 } from "react-native";
4863
+ import { jsx as jsx58, jsxs as jsxs49 } from "react/jsx-runtime";
4366
4864
  function TabBar({ items: items2, value, onValueChange, onReselect, "aria-label": label, style }) {
4367
4865
  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) => {
4866
+ return /* @__PURE__ */ jsx58(View49, { role: "tablist", "aria-label": label, style: [styles45.bar, { backgroundColor: theme.glassBg, borderTopColor: theme.glassBorder, paddingBottom: Math.max(6, insets.bottom) }, style], children: items2.map((item) => {
4369
4867
  const selected = item.value === value;
4370
4868
  const color = selected ? theme.accentText : theme.textSecondary;
4371
4869
  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,
4870
+ return /* @__PURE__ */ jsxs49(
4871
+ Pressable25,
4374
4872
  {
4375
4873
  role: "tab",
4376
4874
  "aria-selected": selected,
@@ -4379,22 +4877,22 @@ function TabBar({ items: items2, value, onValueChange, onReselect, "aria-label":
4379
4877
  if (selected) onReselect?.(item.value);
4380
4878
  else onValueChange(item.value);
4381
4879
  },
4382
- style: ({ pressed }) => [styles39.item, { opacity: pressed ? 0.7 : 1 }],
4880
+ style: ({ pressed }) => [styles45.item, { opacity: pressed ? 0.7 : 1 }],
4383
4881
  children: [
4384
- /* @__PURE__ */ jsxs43(View43, { "aria-hidden": true, style: styles39.icon, children: [
4882
+ /* @__PURE__ */ jsxs49(View49, { "aria-hidden": true, style: styles45.icon, children: [
4385
4883
  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
4884
+ badge !== null ? /* @__PURE__ */ jsx58(View49, { style: [badge ? styles45.count : styles45.dot, { backgroundColor: theme.danger, borderColor: theme.surface1 }], children: badge ? /* @__PURE__ */ jsx58(Text19, { style: [styles45.countText, { color: theme.onAccent }], children: badge }) : null }) : null
4387
4885
  ] }),
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
4886
+ /* @__PURE__ */ jsx58(Text19, { numberOfLines: 1, style: [styles45.label, { color, fontWeight: selected ? "700" : "500" }], children: item.label }),
4887
+ badge !== null && item.badgeLabel ? /* @__PURE__ */ jsx58(Text19, { style: styles45.unseen, children: `, ${item.badgeLabel}` }) : null
4390
4888
  ]
4391
4889
  },
4392
4890
  item.value
4393
4891
  );
4394
4892
  }) });
4395
4893
  }
4396
- var styles39 = StyleSheet39.create({
4397
- bar: { flexDirection: "row", borderTopWidth: StyleSheet39.hairlineWidth, paddingTop: 6 },
4894
+ var styles45 = StyleSheet45.create({
4895
+ bar: { flexDirection: "row", borderTopWidth: StyleSheet45.hairlineWidth, paddingTop: 6 },
4398
4896
  item: { flex: 1, alignItems: "center", gap: 2, minHeight: 48, justifyContent: "center" },
4399
4897
  icon: { width: 28, height: 26, alignItems: "center", justifyContent: "center" },
4400
4898
  label: { fontSize: 11, lineHeight: 14 },
@@ -4405,12 +4903,12 @@ var styles39 = StyleSheet39.create({
4405
4903
  });
4406
4904
 
4407
4905
  // 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";
4906
+ import * as React40 from "react";
4907
+ import { Pressable as Pressable26, ScrollView as ScrollView7, StyleSheet as StyleSheet46, View as View50 } from "react-native";
4908
+ import { jsx as jsx59, jsxs as jsxs50 } from "react/jsx-runtime";
4411
4909
  function Tabs({ items: items2, value, defaultValue, onValueChange, "aria-label": label, variant = "underline", style }) {
4412
4910
  const { theme, radius: radius3, haptic } = useTheme();
4413
- const [own, setOwn] = React36.useState(defaultValue ?? items2[0]?.value);
4911
+ const [own, setOwn] = React40.useState(defaultValue ?? items2[0]?.value);
4414
4912
  const current = value ?? own;
4415
4913
  const select = (next) => {
4416
4914
  if (next === current) return;
@@ -4421,8 +4919,8 @@ function Tabs({ items: items2, value, defaultValue, onValueChange, "aria-label":
4421
4919
  const segmented = variant === "segmented";
4422
4920
  const tabs = items2.map((item) => {
4423
4921
  const selected = item.value === current;
4424
- return /* @__PURE__ */ jsx53(
4425
- Pressable21,
4922
+ return /* @__PURE__ */ jsx59(
4923
+ Pressable26,
4426
4924
  {
4427
4925
  role: "tab",
4428
4926
  "aria-selected": selected,
@@ -4430,39 +4928,67 @@ function Tabs({ items: items2, value, defaultValue, onValueChange, "aria-label":
4430
4928
  disabled: item.disabled,
4431
4929
  onPress: () => select(item.value),
4432
4930
  style: [
4433
- segmented ? styles40.segment : styles40.tab,
4931
+ segmented ? styles46.segment : styles46.tab,
4434
4932
  segmented && selected ? { backgroundColor: theme.surface0, borderColor: theme.borderDefault, borderRadius: radius3.sm } : null,
4435
4933
  !segmented ? { borderBottomColor: selected ? theme.accent : "transparent" } : null,
4436
- item.disabled ? styles40.disabled : null
4934
+ item.disabled ? styles46.disabled : null
4437
4935
  ],
4438
- children: /* @__PURE__ */ jsxs44(Txt, { variant: "label", tone: selected ? "text" : "secondary", numberOfLines: 1, children: [
4936
+ children: /* @__PURE__ */ jsxs50(Txt, { variant: "label", tone: selected ? "text" : "secondary", numberOfLines: 1, children: [
4439
4937
  item.label,
4440
- item.count !== void 0 ? /* @__PURE__ */ jsx53(Txt, { variant: "caption", tone: "secondary", children: ` ${item.count}` }) : null
4938
+ item.count !== void 0 ? /* @__PURE__ */ jsx59(Txt, { variant: "caption", tone: "secondary", children: ` ${item.count}` }) : null
4441
4939
  ] })
4442
4940
  },
4443
4941
  item.value
4444
4942
  );
4445
4943
  });
4446
4944
  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
4945
+ return /* @__PURE__ */ jsxs50(View50, { style: [styles46.root, style], children: [
4946
+ segmented ? /* @__PURE__ */ jsx59(View50, { role: "tablist", "aria-label": label, style: [styles46.track, { backgroundColor: theme.surface2, borderColor: theme.borderSubtle, borderRadius: radius3.md }], children: tabs }) : /* @__PURE__ */ jsx59(View50, { style: [styles46.underline, { borderBottomColor: theme.borderSubtle }], children: /* @__PURE__ */ jsx59(ScrollView7, { horizontal: true, showsHorizontalScrollIndicator: false, role: "tablist", "aria-label": label, contentContainerStyle: styles46.scroll, children: tabs }) }),
4947
+ panel !== void 0 ? /* @__PURE__ */ jsx59(View50, { role: "tabpanel", children: panel }) : null
4450
4948
  ] });
4451
4949
  }
4452
- var styles40 = StyleSheet40.create({
4950
+ var styles46 = StyleSheet46.create({
4453
4951
  root: { gap: 12 },
4454
- underline: { borderBottomWidth: StyleSheet40.hairlineWidth },
4952
+ underline: { borderBottomWidth: StyleSheet46.hairlineWidth },
4455
4953
  scroll: { gap: 4, paddingHorizontal: 4 },
4456
4954
  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" },
4955
+ track: { flexDirection: "row", padding: 3, gap: 3, borderWidth: StyleSheet46.hairlineWidth, height: 40 },
4956
+ segment: { flex: 1, alignItems: "center", justifyContent: "center", paddingHorizontal: 8, borderWidth: StyleSheet46.hairlineWidth, borderColor: "transparent" },
4459
4957
  disabled: { opacity: 0.4 }
4460
4958
  });
4461
4959
 
4960
+ // src/native/tag-selector.tsx
4961
+ import { StyleSheet as StyleSheet47, View as View51 } from "react-native";
4962
+ import { jsx as jsx60, jsxs as jsxs51 } from "react/jsx-runtime";
4963
+ function TagSelector({ label, options, value, onValueChange, max, countLabel, style }) {
4964
+ const { haptic } = useTheme();
4965
+ const full = max !== void 0 && value.length >= max;
4966
+ return /* @__PURE__ */ jsxs51(View51, { style: [styles47.root, style], children: [
4967
+ /* @__PURE__ */ jsx60(View51, { role: "group", "aria-label": label, style: styles47.wrap, children: options.map((option) => {
4968
+ const on = value.includes(option.value);
4969
+ return /* @__PURE__ */ jsx60(
4970
+ Chip,
4971
+ {
4972
+ selected: on,
4973
+ disabled: !on && full,
4974
+ onSelectedChange: (next) => {
4975
+ haptic("selection");
4976
+ onValueChange(next ? [...value, option.value] : value.filter((v) => v !== option.value));
4977
+ },
4978
+ children: option.label
4979
+ },
4980
+ option.value
4981
+ );
4982
+ }) }),
4983
+ max !== void 0 && countLabel ? /* @__PURE__ */ jsx60(Txt, { variant: "caption", tone: full ? "accent" : "secondary", "aria-live": "polite", children: countLabel(value.length, max) }) : null
4984
+ ] });
4985
+ }
4986
+ var styles47 = StyleSheet47.create({ root: { gap: 8 }, wrap: { flexDirection: "row", flexWrap: "wrap", gap: 8 } });
4987
+
4462
4988
  // src/native/toast.tsx
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";
4989
+ import * as React41 from "react";
4990
+ import { AccessibilityInfo as AccessibilityInfo14, Animated as Animated24, PanResponder as PanResponder5, Pressable as Pressable27, StyleSheet as StyleSheet48, Text as Text20, View as View52 } from "react-native";
4991
+ import { Fragment as Fragment9, jsx as jsx61, jsxs as jsxs52 } from "react/jsx-runtime";
4466
4992
  var items = [];
4467
4993
  var listeners2 = /* @__PURE__ */ new Set();
4468
4994
  var counter = 0;
@@ -4497,93 +5023,93 @@ var toast = Object.assign(show, {
4497
5023
  function ToastView({ item, closeLabel, duration }) {
4498
5024
  const { theme, radius: radius3, haptic } = useTheme();
4499
5025
  const reduce = useReducedMotion();
4500
- const [swipe] = React37.useState(() => new Animated21.Value(0));
4501
- const drag = React37.useMemo(
4502
- () => PanResponder4.create({
5026
+ const [swipe] = React41.useState(() => new Animated24.Value(0));
5027
+ const drag = React41.useMemo(
5028
+ () => PanResponder5.create({
4503
5029
  onMoveShouldSetPanResponder: (_, g) => Math.abs(g.dx) > 8 && Math.abs(g.dx) > Math.abs(g.dy),
4504
5030
  onPanResponderMove: (_, g) => swipe.setValue(g.dx),
4505
5031
  onPanResponderRelease: (_, g) => {
4506
5032
  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();
5033
+ Animated24.timing(swipe, { toValue: Math.sign(g.dx) * 480, duration: 160, useNativeDriver: true }).start(() => dismiss(item.id));
5034
+ } else Animated24.spring(swipe, { toValue: 0, useNativeDriver: true }).start();
4509
5035
  }
4510
5036
  }),
4511
5037
  [swipe, item.id]
4512
5038
  );
4513
- React37.useEffect(() => {
5039
+ React41.useEffect(() => {
4514
5040
  if (item.tone === "success" || item.tone === "warning") haptic(item.tone);
4515
5041
  if (item.tone === "error") haptic("warning");
4516
5042
  }, [item.id]);
4517
- const [enter] = React37.useState(() => new Animated21.Value(reduce ? 1 : 0));
4518
- React37.useEffect(() => {
5043
+ const [enter] = React41.useState(() => new Animated24.Value(reduce ? 1 : 0));
5044
+ React41.useEffect(() => {
4519
5045
  if (reduce) enter.setValue(1);
4520
- else Animated21.timing(enter, { toValue: 1, duration: 220, useNativeDriver: true }).start();
5046
+ else Animated24.timing(enter, { toValue: 1, duration: 220, useNativeDriver: true }).start();
4521
5047
  }, [enter, reduce]);
4522
- React37.useEffect(() => {
4523
- AccessibilityInfo12.announceForAccessibility(item.description ? `${item.title}. ${item.description}` : item.title);
5048
+ React41.useEffect(() => {
5049
+ AccessibilityInfo14.announceForAccessibility(item.description ? `${item.title}. ${item.description}` : item.title);
4524
5050
  }, [item.title, item.description]);
4525
5051
  const ms = item.duration ?? duration;
4526
- React37.useEffect(() => {
5052
+ React41.useEffect(() => {
4527
5053
  if (!Number.isFinite(ms)) return;
4528
5054
  const timer2 = setTimeout(() => dismiss(item.id), ms);
4529
5055
  return () => clearTimeout(timer2);
4530
5056
  }, [item.id, ms]);
4531
5057
  const edge = { success: theme.success, warning: theme.warning, error: theme.danger, info: theme.info, default: theme.borderDefault }[item.tone ?? "default"];
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
5058
+ const text = /* @__PURE__ */ jsxs52(Fragment9, { children: [
5059
+ item.icon ? /* @__PURE__ */ jsx61(View52, { "aria-hidden": true, children: item.icon }) : null,
5060
+ /* @__PURE__ */ jsxs52(View52, { style: styles48.content, children: [
5061
+ /* @__PURE__ */ jsx61(Txt, { variant: "label", numberOfLines: 2, children: item.title }),
5062
+ item.description ? /* @__PURE__ */ jsx61(Txt, { variant: "caption", tone: "secondary", numberOfLines: 3, children: item.description }) : null
4537
5063
  ] })
4538
5064
  ] });
4539
- const body = /* @__PURE__ */ jsxs45(Fragment6, { children: [
4540
- item.onPress ? /* @__PURE__ */ jsx54(
4541
- Pressable22,
5065
+ const body = /* @__PURE__ */ jsxs52(Fragment9, { children: [
5066
+ item.onPress ? /* @__PURE__ */ jsx61(
5067
+ Pressable27,
4542
5068
  {
4543
5069
  role: "button",
4544
5070
  onPress: () => {
4545
5071
  item.onPress?.();
4546
5072
  dismiss(item.id);
4547
5073
  },
4548
- style: ({ pressed }) => [styles41.main, { opacity: pressed ? 0.8 : 1 }],
5074
+ style: ({ pressed }) => [styles48.main, { opacity: pressed ? 0.8 : 1 }],
4549
5075
  children: text
4550
5076
  }
4551
- ) : /* @__PURE__ */ jsx54(View45, { style: styles41.main, children: text }),
4552
- item.action ? /* @__PURE__ */ jsx54(
4553
- Pressable22,
5077
+ ) : /* @__PURE__ */ jsx61(View52, { style: styles48.main, children: text }),
5078
+ item.action ? /* @__PURE__ */ jsx61(
5079
+ Pressable27,
4554
5080
  {
4555
5081
  role: "button",
4556
5082
  onPress: () => {
4557
5083
  item.action?.onPress();
4558
5084
  dismiss(item.id);
4559
5085
  },
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 })
5086
+ style: [styles48.action, { backgroundColor: theme.accent, borderRadius: radius3.sm }],
5087
+ children: /* @__PURE__ */ jsx61(Text20, { style: [styles48.actionLabel, { color: theme.onAccent }], children: item.action.label })
4562
5088
  }
4563
5089
  ) : null,
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" }) })
5090
+ /* @__PURE__ */ jsx61(Pressable27, { role: "button", "aria-label": closeLabel, hitSlop: 10, onPress: () => dismiss(item.id), style: styles48.close, children: /* @__PURE__ */ jsx61(Text20, { style: [styles48.cross, { color: theme.textSecondary }], children: "\xD7" }) })
4565
5091
  ] });
4566
5092
  const frame = [
4567
- styles41.toast,
5093
+ styles48.toast,
4568
5094
  { backgroundColor: theme.surface2, borderColor: theme.borderDefault, borderLeftColor: edge, borderRadius: radius3.lg, shadowColor: theme.scrimStrong }
4569
5095
  ];
4570
5096
  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 }) });
5097
+ return /* @__PURE__ */ jsx61(Animated24.View, { "aria-live": "polite", style: motion3, ...drag.panHandlers, children: /* @__PURE__ */ jsx61(View52, { style: frame, children: body }) });
4572
5098
  }
4573
5099
  function Toaster({ closeLabel, position = "top", offset = 12, duration = 6e3, max = 3 }) {
4574
- const all = React37.useSyncExternalStore(subscribe2, snapshot, snapshot);
5100
+ const all = React41.useSyncExternalStore(subscribe2, snapshot, snapshot);
4575
5101
  const shown = all.slice(-max);
4576
5102
  if (shown.length === 0) return null;
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)) });
5103
+ return /* @__PURE__ */ jsx61(View52, { pointerEvents: "box-none", style: [styles48.stack, position === "top" ? { top: offset } : { bottom: offset }], children: (position === "top" ? shown : [...shown].reverse()).map((item) => /* @__PURE__ */ jsx61(ToastView, { item, closeLabel, duration }, item.id)) });
4578
5104
  }
4579
- var styles41 = StyleSheet41.create({
5105
+ var styles48 = StyleSheet48.create({
4580
5106
  stack: { position: "absolute", left: 12, right: 12, gap: 8, zIndex: 100 },
4581
5107
  toast: {
4582
5108
  flexDirection: "row",
4583
5109
  alignItems: "center",
4584
5110
  gap: 10,
4585
5111
  padding: 12,
4586
- borderWidth: StyleSheet41.hairlineWidth,
5112
+ borderWidth: StyleSheet48.hairlineWidth,
4587
5113
  borderLeftWidth: 4,
4588
5114
  shadowOpacity: 0.3,
4589
5115
  shadowRadius: 16,
@@ -4597,6 +5123,30 @@ var styles41 = StyleSheet41.create({
4597
5123
  close: { width: 28, height: 28, alignItems: "center", justifyContent: "center" },
4598
5124
  cross: { fontSize: 18, lineHeight: 20, fontWeight: "700" }
4599
5125
  });
5126
+
5127
+ // src/native/verified-badge.tsx
5128
+ import { StyleSheet as StyleSheet49, View as View53 } from "react-native";
5129
+ import Svg27, { Path as Path22 } from "react-native-svg";
5130
+ import { jsx as jsx62, jsxs as jsxs53 } from "react/jsx-runtime";
5131
+ function VerifiedBadge({ label, showLabel, size = 16, on = "surface" }) {
5132
+ const { theme } = useTheme();
5133
+ return /* @__PURE__ */ jsxs53(View53, { accessible: true, role: "img", "aria-label": label, style: styles49.row, children: [
5134
+ /* @__PURE__ */ jsxs53(Svg27, { width: size, height: size, viewBox: "0 0 24 24", "aria-hidden": true, children: [
5135
+ /* @__PURE__ */ jsx62(
5136
+ Path22,
5137
+ {
5138
+ d: "M12 2.5l2.4 1.7 2.9-.1.9 2.8 2.3 1.8-.9 2.8.9 2.8-2.3 1.8-.9 2.8-2.9-.1L12 21.5l-2.4-1.7-2.9.1-.9-2.8-2.3-1.8.9-2.8-.9-2.8 2.3-1.8.9-2.8 2.9.1z",
5139
+ fill: theme.accent,
5140
+ stroke: on === "media" ? theme.textOnMedia : "none",
5141
+ strokeWidth: 1.2
5142
+ }
5143
+ ),
5144
+ /* @__PURE__ */ jsx62(Path22, { d: "M8.3 12.3l2.5 2.5 4.9-5.2", fill: "none", stroke: theme.onAccent, strokeWidth: 2.2, strokeLinecap: "round", strokeLinejoin: "round" })
5145
+ ] }),
5146
+ showLabel ? /* @__PURE__ */ jsx62(Txt, { variant: "caption", tone: on === "media" ? "onMedia" : "accent", style: styles49.text, children: label }) : null
5147
+ ] });
5148
+ }
5149
+ var styles49 = StyleSheet49.create({ row: { flexDirection: "row", alignItems: "center", gap: 4 }, text: { fontWeight: "700" } });
4600
5150
  export {
4601
5151
  ActionSheet,
4602
5152
  ActivityFeed,
@@ -4618,6 +5168,7 @@ export {
4618
5168
  Checkbox,
4619
5169
  Chip,
4620
5170
  Combobox,
5171
+ ConversationItem,
4621
5172
  Countdown,
4622
5173
  DateField,
4623
5174
  DateWheel,
@@ -4636,6 +5187,9 @@ export {
4636
5187
  LoadingState,
4637
5188
  Mascot,
4638
5189
  MascotState,
5190
+ MatchDialog,
5191
+ MessageBubble,
5192
+ MessageComposer,
4639
5193
  Meter,
4640
5194
  MonthPicker,
4641
5195
  NumberTicker,
@@ -4645,12 +5199,15 @@ export {
4645
5199
  OtpInput,
4646
5200
  Pagination,
4647
5201
  PermissionPrompt,
5202
+ PersonCard,
4648
5203
  Phoenix,
5204
+ PhotoGrid,
4649
5205
  ProductMark,
4650
5206
  ProfileCard,
4651
5207
  Progress,
4652
5208
  PullToRefresh,
4653
5209
  RadioGroup,
5210
+ Screen,
4654
5211
  SearchField,
4655
5212
  Segmented,
4656
5213
  Select,
@@ -4658,17 +5215,22 @@ export {
4658
5215
  Skeleton,
4659
5216
  Slider,
4660
5217
  Spinner,
5218
+ StepProgress,
4661
5219
  Stepper,
4662
5220
  SuccessState,
5221
+ SwipeDeck,
4663
5222
  SwipeableRow,
4664
5223
  Switch,
4665
5224
  TabBar,
4666
5225
  Tabs,
5226
+ TagSelector,
4667
5227
  TextField,
4668
5228
  ThemeProvider,
4669
5229
  TimePicker,
4670
5230
  Toaster,
4671
5231
  Txt,
5232
+ TypingIndicator,
5233
+ VerifiedBadge,
4672
5234
  WelcomeState,
4673
5235
  Wheel,
4674
5236
  WheelDivider,