@boostdev/design-system-components 1.2.3 → 1.2.5

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 (198) hide show
  1. package/AGENTS.md +19 -11
  2. package/README.md +36 -1
  3. package/dist/client.cjs +50 -50
  4. package/dist/client.css +470 -470
  5. package/dist/client.js +50 -50
  6. package/dist/index.cjs +50 -50
  7. package/dist/index.css +470 -470
  8. package/dist/index.js +50 -50
  9. package/dist/native/index.cjs +3692 -352
  10. package/dist/native/index.d.cts +359 -3
  11. package/dist/native/index.d.ts +359 -3
  12. package/dist/native/index.js +3811 -364
  13. package/dist/utils.cjs +30 -0
  14. package/dist/utils.d.cts +8 -0
  15. package/dist/utils.d.ts +8 -0
  16. package/dist/utils.js +5 -0
  17. package/package.json +10 -4
  18. package/src/client.ts +6 -0
  19. package/src/components/interaction/Button/Button.native.stories.tsx +10 -12
  20. package/src/components/interaction/Button/Button.native.tsx +3 -3
  21. package/src/components/interaction/Dialog/Dialog.native.mdx +61 -0
  22. package/src/components/interaction/Dialog/Dialog.native.spec.tsx +73 -0
  23. package/src/components/interaction/Dialog/Dialog.native.stories.tsx +53 -0
  24. package/src/components/interaction/Dialog/Dialog.native.tsx +128 -0
  25. package/src/components/interaction/Drawer/Drawer.native.mdx +58 -0
  26. package/src/components/interaction/Drawer/Drawer.native.spec.tsx +81 -0
  27. package/src/components/interaction/Drawer/Drawer.native.stories.tsx +33 -0
  28. package/src/components/interaction/Drawer/Drawer.native.tsx +175 -0
  29. package/src/components/interaction/DropdownMenu/DropdownMenu.native.mdx +74 -0
  30. package/src/components/interaction/DropdownMenu/DropdownMenu.native.spec.tsx +78 -0
  31. package/src/components/interaction/DropdownMenu/DropdownMenu.native.stories.tsx +51 -0
  32. package/src/components/interaction/DropdownMenu/DropdownMenu.native.tsx +254 -0
  33. package/src/components/interaction/Popover/Popover.native.mdx +61 -0
  34. package/src/components/interaction/Popover/Popover.native.spec.tsx +73 -0
  35. package/src/components/interaction/Popover/Popover.native.stories.tsx +44 -0
  36. package/src/components/interaction/Popover/Popover.native.tsx +87 -0
  37. package/src/components/interaction/Rating/Rating.native.mdx +55 -0
  38. package/src/components/interaction/Rating/Rating.native.spec.tsx +38 -0
  39. package/src/components/interaction/Rating/Rating.native.stories.tsx +37 -0
  40. package/src/components/interaction/Rating/Rating.native.tsx +50 -0
  41. package/src/components/interaction/Toast/Toast.native.mdx +81 -0
  42. package/src/components/interaction/Toast/Toast.native.spec.tsx +80 -0
  43. package/src/components/interaction/Toast/Toast.native.stories.tsx +47 -0
  44. package/src/components/interaction/Toast/Toast.native.tsx +202 -0
  45. package/src/components/interaction/form/Checkbox/Checkbox.native.stories.tsx +2 -4
  46. package/src/components/interaction/form/Checkbox/Checkbox.native.tsx +1 -1
  47. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.native.mdx +78 -0
  48. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.native.spec.tsx +57 -0
  49. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.native.stories.tsx +96 -0
  50. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.native.tsx +61 -0
  51. package/src/components/interaction/form/Combobox/Combobox.native.mdx +86 -0
  52. package/src/components/interaction/form/Combobox/Combobox.native.spec.tsx +60 -0
  53. package/src/components/interaction/form/Combobox/Combobox.native.stories.tsx +99 -0
  54. package/src/components/interaction/form/Combobox/Combobox.native.tsx +211 -0
  55. package/src/components/interaction/form/FileInput/FileInput.native.mdx +86 -0
  56. package/src/components/interaction/form/FileInput/FileInput.native.spec.tsx +73 -0
  57. package/src/components/interaction/form/FileInput/FileInput.native.stories.tsx +69 -0
  58. package/src/components/interaction/form/FileInput/FileInput.native.tsx +129 -0
  59. package/src/components/interaction/form/FormInput/FormInput.native.mdx +81 -0
  60. package/src/components/interaction/form/FormInput/FormInput.native.spec.tsx +51 -0
  61. package/src/components/interaction/form/FormInput/FormInput.native.stories.tsx +54 -0
  62. package/src/components/interaction/form/FormInput/FormInput.native.tsx +122 -0
  63. package/src/components/interaction/form/NumberInput/NumberInput.native.mdx +87 -0
  64. package/src/components/interaction/form/NumberInput/NumberInput.native.spec.tsx +63 -0
  65. package/src/components/interaction/form/NumberInput/NumberInput.native.stories.tsx +63 -0
  66. package/src/components/interaction/form/NumberInput/NumberInput.native.tsx +198 -0
  67. package/src/components/interaction/form/Radio/Radio.native.spec.tsx +79 -0
  68. package/src/components/interaction/form/Radio/Radio.native.stories.tsx +12 -14
  69. package/src/components/interaction/form/Radio/Radio.native.tsx +1 -1
  70. package/src/components/interaction/form/RadioGroup/RadioGroup.native.mdx +79 -0
  71. package/src/components/interaction/form/RadioGroup/RadioGroup.native.spec.tsx +66 -0
  72. package/src/components/interaction/form/RadioGroup/RadioGroup.native.stories.tsx +96 -0
  73. package/src/components/interaction/form/RadioGroup/RadioGroup.native.tsx +61 -0
  74. package/src/components/interaction/form/SegmentedControl/SegmentedControl.native.mdx +78 -0
  75. package/src/components/interaction/form/SegmentedControl/SegmentedControl.native.spec.tsx +82 -0
  76. package/src/components/interaction/form/SegmentedControl/SegmentedControl.native.stories.tsx +99 -0
  77. package/src/components/interaction/form/SegmentedControl/SegmentedControl.native.tsx +121 -0
  78. package/src/components/interaction/form/Select/Select.native.mdx +85 -0
  79. package/src/components/interaction/form/Select/Select.native.spec.tsx +64 -0
  80. package/src/components/interaction/form/Select/Select.native.stories.tsx +75 -0
  81. package/src/components/interaction/form/Select/Select.native.tsx +252 -0
  82. package/src/components/interaction/form/Slider/Slider.native.mdx +83 -0
  83. package/src/components/interaction/form/Slider/Slider.native.spec.tsx +51 -0
  84. package/src/components/interaction/form/Slider/Slider.native.stories.tsx +58 -0
  85. package/src/components/interaction/form/Slider/Slider.native.tsx +188 -0
  86. package/src/components/interaction/form/Switch/Switch.native.stories.tsx +2 -4
  87. package/src/components/interaction/form/Textarea/Textarea.native.mdx +76 -0
  88. package/src/components/interaction/form/Textarea/Textarea.native.spec.tsx +50 -0
  89. package/src/components/interaction/form/Textarea/Textarea.native.stories.tsx +50 -0
  90. package/src/components/interaction/form/Textarea/Textarea.native.tsx +108 -0
  91. package/src/components/interaction/form/atoms/Label.native.spec.tsx +39 -0
  92. package/src/components/interaction/form/atoms/Label.native.stories.tsx +1 -1
  93. package/src/components/interaction/form/atoms/Message.native.stories.tsx +1 -1
  94. package/src/components/layout/ButtonGroup/ButtonGroup.native.spec.tsx +83 -0
  95. package/src/components/layout/ButtonGroup/ButtonGroup.native.stories.tsx +13 -19
  96. package/src/components/layout/Card/Card.native.spec.tsx +102 -0
  97. package/src/components/layout/Card/Card.native.stories.tsx +9 -11
  98. package/src/components/layout/Card/Card.native.tsx +1 -1
  99. package/src/components/layout/IconWrapper/IconWrapper.native.stories.tsx +7 -11
  100. package/src/components/layout/SectionHeader/SectionHeader.native.spec.tsx +51 -0
  101. package/src/components/layout/SectionHeader/SectionHeader.native.stories.tsx +6 -8
  102. package/src/components/ui/Accordion/Accordion.native.mdx +65 -0
  103. package/src/components/ui/Accordion/Accordion.native.spec.tsx +69 -0
  104. package/src/components/ui/Accordion/Accordion.native.stories.tsx +52 -0
  105. package/src/components/ui/Accordion/Accordion.native.tsx +141 -0
  106. package/src/components/ui/Alert/Alert.native.spec.tsx +76 -0
  107. package/src/components/ui/Alert/Alert.native.stories.tsx +8 -10
  108. package/src/components/ui/Alert/Alert.native.tsx +7 -7
  109. package/src/components/ui/Avatar/Avatar.native.stories.tsx +6 -8
  110. package/src/components/ui/Avatar/Avatar.native.tsx +2 -2
  111. package/src/components/ui/Badge/Badge.native.spec.tsx +45 -0
  112. package/src/components/ui/Badge/Badge.native.stories.tsx +6 -8
  113. package/src/components/ui/Badge/Badge.native.tsx +2 -2
  114. package/src/components/ui/Breadcrumb/Breadcrumb.native.mdx +52 -0
  115. package/src/components/ui/Breadcrumb/Breadcrumb.native.spec.tsx +49 -0
  116. package/src/components/ui/Breadcrumb/Breadcrumb.native.stories.tsx +46 -0
  117. package/src/components/ui/Breadcrumb/Breadcrumb.native.tsx +83 -0
  118. package/src/components/ui/Calendar/Calendar.native.mdx +58 -0
  119. package/src/components/ui/Calendar/Calendar.native.spec.tsx +92 -0
  120. package/src/components/ui/Calendar/Calendar.native.stories.tsx +45 -0
  121. package/src/components/ui/Calendar/Calendar.native.tsx +294 -0
  122. package/src/components/ui/Carousel/Carousel.native.mdx +55 -0
  123. package/src/components/ui/Carousel/Carousel.native.spec.tsx +55 -0
  124. package/src/components/ui/Carousel/Carousel.native.stories.tsx +59 -0
  125. package/src/components/ui/Carousel/Carousel.native.tsx +184 -0
  126. package/src/components/ui/Collapsible/Collapsible.native.mdx +53 -0
  127. package/src/components/ui/Collapsible/Collapsible.native.spec.tsx +68 -0
  128. package/src/components/ui/Collapsible/Collapsible.native.stories.tsx +48 -0
  129. package/src/components/ui/Collapsible/Collapsible.native.tsx +139 -0
  130. package/src/components/ui/DescriptionList/DescriptionList.native.mdx +50 -0
  131. package/src/components/ui/DescriptionList/DescriptionList.native.spec.tsx +37 -0
  132. package/src/components/ui/DescriptionList/DescriptionList.native.stories.tsx +48 -0
  133. package/src/components/ui/DescriptionList/DescriptionList.native.tsx +54 -0
  134. package/src/components/ui/Link/Link.native.mdx +53 -0
  135. package/src/components/ui/Link/Link.native.spec.tsx +35 -0
  136. package/src/components/ui/Link/Link.native.stories.tsx +46 -0
  137. package/src/components/ui/Link/Link.native.tsx +48 -0
  138. package/src/components/ui/Loading/Loading.native.stories.tsx +6 -8
  139. package/src/components/ui/NotificationBanner/NotificationBanner.native.spec.tsx +85 -0
  140. package/src/components/ui/NotificationBanner/NotificationBanner.native.stories.tsx +8 -10
  141. package/src/components/ui/NotificationBanner/NotificationBanner.native.tsx +7 -7
  142. package/src/components/ui/Pagination/Pagination.native.mdx +62 -0
  143. package/src/components/ui/Pagination/Pagination.native.spec.tsx +86 -0
  144. package/src/components/ui/Pagination/Pagination.native.stories.tsx +47 -0
  145. package/src/components/ui/Pagination/Pagination.native.tsx +157 -0
  146. package/src/components/ui/Progress/Progress.native.spec.tsx +56 -0
  147. package/src/components/ui/Progress/Progress.native.stories.tsx +1 -1
  148. package/src/components/ui/Progress/Progress.native.tsx +2 -2
  149. package/src/components/ui/ProgressCircle/ProgressCircle.native.mdx +63 -0
  150. package/src/components/ui/ProgressCircle/ProgressCircle.native.spec.tsx +39 -0
  151. package/src/components/ui/ProgressCircle/ProgressCircle.native.stories.tsx +36 -0
  152. package/src/components/ui/ProgressCircle/ProgressCircle.native.tsx +176 -0
  153. package/src/components/ui/Separator/Separator.native.spec.tsx +39 -0
  154. package/src/components/ui/Separator/Separator.native.stories.tsx +10 -14
  155. package/src/components/ui/Skeleton/Skeleton.native.spec.tsx +39 -0
  156. package/src/components/ui/Skeleton/Skeleton.native.stories.tsx +6 -8
  157. package/src/components/ui/Skeleton/Skeleton.native.tsx +2 -1
  158. package/src/components/ui/Table/Table.native.mdx +72 -0
  159. package/src/components/ui/Table/Table.native.spec.tsx +83 -0
  160. package/src/components/ui/Table/Table.native.stories.tsx +55 -0
  161. package/src/components/ui/Table/Table.native.tsx +196 -0
  162. package/src/components/ui/Tabs/Tabs.native.mdx +65 -0
  163. package/src/components/ui/Tabs/Tabs.native.spec.tsx +65 -0
  164. package/src/components/ui/Tabs/Tabs.native.stories.tsx +57 -0
  165. package/src/components/ui/Tabs/Tabs.native.tsx +133 -0
  166. package/src/components/ui/Tooltip/Tooltip.native.mdx +47 -0
  167. package/src/components/ui/Tooltip/Tooltip.native.spec.tsx +37 -0
  168. package/src/components/ui/Tooltip/Tooltip.native.stories.tsx +38 -0
  169. package/src/components/ui/Tooltip/Tooltip.native.tsx +57 -0
  170. package/src/components/ui/Typography/Typography.native.spec.tsx +49 -0
  171. package/src/components/ui/Typography/Typography.native.stories.tsx +8 -10
  172. package/src/native/ThemeContext.tsx +3 -3
  173. package/src/native.ts +37 -0
  174. package/src/stories/ReactNative.mdx +48 -13
  175. package/src/utils.ts +6 -0
  176. package/src/web-components/interaction/BdsAccordion.stories.tsx +1 -1
  177. package/src/web-components/interaction/BdsCollapsible.stories.tsx +1 -1
  178. package/src/web-components/interaction/BdsSkipLink.stories.tsx +1 -1
  179. package/src/web-components/interaction/BdsTabs.stories.tsx +1 -1
  180. package/src/web-components/interaction/BdsTooltip.stories.tsx +1 -1
  181. package/src/web-components/interaction/form/BdsCheckbox.stories.tsx +1 -1
  182. package/src/web-components/interaction/form/BdsCheckboxGroup.stories.tsx +1 -1
  183. package/src/web-components/interaction/form/BdsCombobox.stories.tsx +1 -1
  184. package/src/web-components/interaction/form/BdsFileInput.stories.tsx +1 -1
  185. package/src/web-components/interaction/form/BdsFormInput.stories.tsx +1 -1
  186. package/src/web-components/interaction/form/BdsNumberInput.stories.tsx +1 -1
  187. package/src/web-components/interaction/form/BdsRadio.stories.tsx +1 -1
  188. package/src/web-components/interaction/form/BdsRadioGroup.stories.tsx +1 -1
  189. package/src/web-components/interaction/form/BdsSegmentedControl.stories.tsx +1 -1
  190. package/src/web-components/interaction/form/BdsSelect.stories.tsx +1 -1
  191. package/src/web-components/interaction/form/BdsSlider.stories.tsx +1 -1
  192. package/src/web-components/interaction/form/BdsSwitch.stories.tsx +1 -1
  193. package/src/web-components/interaction/form/BdsTextarea.stories.tsx +1 -1
  194. package/src/web-components/ui/BdsButtonGroup.stories.tsx +1 -1
  195. package/src/web-components/ui/BdsCard.stories.tsx +1 -1
  196. package/src/web-components/ui/BdsIconWrapper.stories.tsx +1 -1
  197. package/src/web-components/ui/BdsRating.stories.tsx +1 -1
  198. package/src/web-components/ui/BdsSectionHeader.stories.tsx +1 -1
@@ -16,9 +16,9 @@ var lineHeight = {
16
16
  // src/native/ThemeContext.tsx
17
17
  import { jsx } from "react/jsx-runtime";
18
18
  var ThemeContext = createContext(null);
19
- function ThemeProvider({ children }) {
20
- const scheme = useColorScheme();
21
- const isDark = scheme === "dark";
19
+ function ThemeProvider({ children, colorScheme }) {
20
+ const systemScheme = useColorScheme();
21
+ const isDark = (colorScheme ?? systemScheme) === "dark";
22
22
  const value = useMemo(
23
23
  () => ({ colors: isDark ? colors.dark : colors.light, isDark }),
24
24
  [isDark]
@@ -96,7 +96,7 @@ var styles2 = StyleSheet2.create({
96
96
  justifyContent: "center",
97
97
  paddingVertical: spacing.xxs,
98
98
  paddingHorizontal: spacing.xs,
99
- borderRadius: 999
99
+ borderRadius: border.radius.full
100
100
  },
101
101
  text: {
102
102
  fontSize: font.size.bodyS,
@@ -131,7 +131,7 @@ function getInitials(name) {
131
131
  }
132
132
  var styles3 = StyleSheet3.create({
133
133
  container: {
134
- borderRadius: 999,
134
+ borderRadius: border.radius.full,
135
135
  overflow: "hidden",
136
136
  alignItems: "center",
137
137
  justifyContent: "center"
@@ -258,12 +258,12 @@ var styles5 = StyleSheet5.create({
258
258
  },
259
259
  track: {
260
260
  width: "100%",
261
- borderRadius: border.radius.xs,
261
+ borderRadius: border.radius.full,
262
262
  overflow: "hidden"
263
263
  },
264
264
  fill: {
265
265
  height: "100%",
266
- borderRadius: border.radius.xs
266
+ borderRadius: border.radius.full
267
267
  }
268
268
  });
269
269
  function Progress({
@@ -312,7 +312,7 @@ import { Animated, StyleSheet as StyleSheet6 } from "react-native";
312
312
  import { jsx as jsx8 } from "react/jsx-runtime";
313
313
  var styles6 = StyleSheet6.create({
314
314
  skeleton: {
315
- borderRadius: 4,
315
+ borderRadius: border.radius.xs,
316
316
  overflow: "hidden"
317
317
  }
318
318
  });
@@ -388,18 +388,18 @@ function Alert({
388
388
  const { colors: colors2 } = useTheme();
389
389
  const isUrgent = variant === "error" || variant === "warning";
390
390
  const variantColors = {
391
- info: { bg: colors2.colorBlueSubtle, text: colors2.colorOnBlueSubtle },
392
- success: { bg: colors2.colorSuccessSubtle, text: colors2.colorOnSuccessSubtle },
393
- warning: { bg: colors2.colorOrangeSubtle, text: colors2.colorOnOrangeSubtle },
394
- error: { bg: colors2.colorRedSubtle, text: colors2.colorOnRedSubtle }
391
+ info: { bg: colors2.colorBlueSubtle, text: colors2.colorOnBlueSubtle, border: colors2.colorBlue },
392
+ success: { bg: colors2.colorSuccessSubtle, text: colors2.colorOnSuccessSubtle, border: colors2.colorSuccess },
393
+ warning: { bg: colors2.colorOrangeSubtle, text: colors2.colorOnOrangeSubtle, border: colors2.colorWarning },
394
+ error: { bg: colors2.colorRedSubtle, text: colors2.colorOnBg, border: colors2.colorError }
395
395
  };
396
- const { bg, text } = variantColors[variant];
396
+ const { bg, text, border: borderColor } = variantColors[variant];
397
397
  return /* @__PURE__ */ jsxs2(
398
398
  View5,
399
399
  {
400
400
  accessibilityRole: isUrgent ? "alert" : "none",
401
401
  accessibilityLiveRegion: isUrgent ? "assertive" : "polite",
402
- style: [styles7.alert, { backgroundColor: bg }, style],
402
+ style: [styles7.alert, { backgroundColor: bg, borderStartWidth: spacing.s, borderStartColor: borderColor }, style],
403
403
  children: [
404
404
  icon && /* @__PURE__ */ jsx9(View5, { style: styles7.icon, children: icon }),
405
405
  /* @__PURE__ */ jsxs2(View5, { style: styles7.content, children: [
@@ -454,18 +454,18 @@ function NotificationBanner({
454
454
  const { colors: colors2 } = useTheme();
455
455
  const isUrgent = variant === "error" || variant === "warning";
456
456
  const variantColors = {
457
- info: { bg: colors2.colorBlueSubtle, text: colors2.colorOnBlueSubtle },
458
- success: { bg: colors2.colorSuccessSubtle, text: colors2.colorOnSuccessSubtle },
459
- warning: { bg: colors2.colorOrangeSubtle, text: colors2.colorOnOrangeSubtle },
460
- error: { bg: colors2.colorRedSubtle, text: colors2.colorOnRedSubtle }
457
+ info: { bg: colors2.colorBlueSubtle, text: colors2.colorOnBlueSubtle, border: colors2.colorBlue },
458
+ success: { bg: colors2.colorSuccessSubtle, text: colors2.colorOnSuccessSubtle, border: colors2.colorSuccess },
459
+ warning: { bg: colors2.colorOrangeSubtle, text: colors2.colorOnOrangeSubtle, border: colors2.colorWarning },
460
+ error: { bg: colors2.colorRedSubtle, text: colors2.colorOnBg, border: colors2.colorError }
461
461
  };
462
- const { bg, text } = variantColors[variant];
462
+ const { bg, text, border: borderColor } = variantColors[variant];
463
463
  return /* @__PURE__ */ jsxs3(
464
464
  View6,
465
465
  {
466
466
  accessibilityRole: isUrgent ? "alert" : "none",
467
467
  accessibilityLiveRegion: isUrgent ? "assertive" : "polite",
468
- style: [styles8.banner, { backgroundColor: bg }, style],
468
+ style: [styles8.banner, { backgroundColor: bg, borderBottomWidth: 3, borderBottomColor: borderColor }, style],
469
469
  children: [
470
470
  /* @__PURE__ */ jsx10(Text6, { style: [styles8.content, { color: text }], children }),
471
471
  action,
@@ -485,478 +485,3924 @@ function NotificationBanner({
485
485
  );
486
486
  }
487
487
 
488
- // src/components/layout/Card/Card.native.tsx
489
- import { StyleSheet as StyleSheet9, View as View7, Pressable as Pressable3 } from "react-native";
488
+ // src/components/ui/Link/Link.native.tsx
489
+ import { StyleSheet as StyleSheet9, Text as Text7, Pressable as Pressable3, Linking } from "react-native";
490
490
  import { jsx as jsx11 } from "react/jsx-runtime";
491
- var paddingMap = {
492
- none: 0,
493
- small: spacing.s,
494
- medium: spacing.m,
495
- large: spacing.xxl
496
- };
497
- var alignMap = {
498
- start: "flex-start",
499
- center: "center",
500
- end: "flex-end"
501
- };
502
491
  var styles9 = StyleSheet9.create({
503
- card: {
504
- borderRadius: border.radius.s,
505
- overflow: "hidden"
492
+ text: {
493
+ fontSize: font.size.body,
494
+ fontFamily: font.family.body,
495
+ textDecorationLine: "underline"
496
+ },
497
+ pressed: {
498
+ opacity: 0.75
506
499
  }
507
500
  });
508
- function Card({
509
- children,
510
- variant = "default",
511
- padding = "medium",
512
- textAlign = "start",
513
- style,
514
- onPress,
515
- accessibilityLabel
516
- }) {
501
+ function Link({ href, children, accessibilityLabel, style, onPress }) {
517
502
  const { colors: colors2 } = useTheme();
518
- const variantStyle = {
519
- backgroundColor: colors2.colorBg,
520
- ...variant === "elevated" && {
521
- shadowColor: "#000",
522
- shadowOffset: { width: 0, height: 2 },
523
- shadowOpacity: 0.1,
524
- shadowRadius: 8,
525
- elevation: 4
526
- },
527
- ...variant === "outlined" && {
528
- borderWidth: 1,
529
- borderColor: colors2.colorBgSubtle
503
+ const handlePress = () => {
504
+ if (onPress) {
505
+ onPress();
506
+ } else if (href) {
507
+ Linking.openURL(href);
530
508
  }
531
509
  };
532
- const inner = {
533
- padding: paddingMap[padding],
534
- alignItems: alignMap[textAlign]
535
- };
536
- if (onPress) {
537
- return /* @__PURE__ */ jsx11(
538
- Pressable3,
539
- {
540
- onPress,
541
- accessibilityRole: "button",
542
- accessibilityLabel,
543
- style: ({ pressed }) => [styles9.card, variantStyle, inner, pressed && { opacity: 0.8 }, style],
544
- children
545
- }
546
- );
547
- }
548
- return /* @__PURE__ */ jsx11(View7, { style: [styles9.card, variantStyle, inner, style], children });
510
+ return /* @__PURE__ */ jsx11(
511
+ Pressable3,
512
+ {
513
+ onPress: handlePress,
514
+ accessibilityRole: "link",
515
+ accessibilityLabel,
516
+ style: ({ pressed }) => pressed && styles9.pressed,
517
+ children: /* @__PURE__ */ jsx11(Text7, { style: [styles9.text, { color: colors2.colorInteractiveOnBg }, style], children })
518
+ }
519
+ );
549
520
  }
550
521
 
551
- // src/components/layout/SectionHeader/SectionHeader.native.tsx
552
- import { StyleSheet as StyleSheet10, View as View8, Text as Text7 } from "react-native";
522
+ // src/components/ui/DescriptionList/DescriptionList.native.tsx
523
+ import { StyleSheet as StyleSheet10, View as View7, Text as Text8 } from "react-native";
553
524
  import { jsx as jsx12, jsxs as jsxs4 } from "react/jsx-runtime";
554
- var alignMap2 = {
555
- start: "flex-start",
556
- center: "center",
557
- end: "flex-end"
558
- };
559
- var titleStyles = StyleSheet10.create({
560
- small: {
561
- fontSize: font.size.heading3,
562
- fontFamily: font.family.heading,
563
- fontWeight: font.weight.heading,
564
- lineHeight: lineHeight.heading3
565
- },
566
- medium: {
567
- fontSize: font.size.heading2,
568
- fontFamily: font.family.heading,
569
- fontWeight: font.weight.heading,
570
- lineHeight: lineHeight.heading2
571
- },
572
- large: {
573
- fontSize: font.size.heading1,
574
- fontFamily: font.family.heading,
575
- fontWeight: font.weight.heading,
576
- lineHeight: lineHeight.heading1
577
- }
578
- });
579
525
  var styles10 = StyleSheet10.create({
580
- container: {
526
+ list: {
527
+ gap: spacing.m
528
+ },
529
+ group: {
581
530
  gap: spacing.xxs
582
531
  },
583
- subtitle: {
532
+ term: {
584
533
  fontSize: font.size.bodyS,
585
534
  fontFamily: font.family.body,
535
+ fontWeight: font.weight.semibold,
586
536
  lineHeight: lineHeight.bodyS
537
+ },
538
+ description: {
539
+ fontSize: font.size.body,
540
+ fontFamily: font.family.body,
541
+ fontWeight: font.weight.body,
542
+ lineHeight: lineHeight.body
587
543
  }
588
544
  });
589
- function SectionHeader({
590
- title,
591
- subtitle,
592
- alignment = "start",
593
- size = "medium",
594
- style
595
- }) {
545
+ function DescriptionList({ items, style }) {
596
546
  const { colors: colors2 } = useTheme();
597
- const align = alignMap2[alignment];
598
- return /* @__PURE__ */ jsxs4(View8, { style: [styles10.container, { alignItems: align }, style], children: [
599
- /* @__PURE__ */ jsx12(
600
- Text7,
601
- {
602
- accessibilityRole: "header",
603
- style: [titleStyles[size], { color: colors2.colorOnBg }],
604
- children: title
605
- }
606
- ),
607
- subtitle && /* @__PURE__ */ jsx12(Text7, { style: [styles10.subtitle, { color: colors2.colorOnBgSubtle }], children: subtitle })
608
- ] });
609
- }
610
-
611
- // src/components/layout/IconWrapper/IconWrapper.native.tsx
612
- import { View as View9 } from "react-native";
613
- import { jsx as jsx13 } from "react/jsx-runtime";
614
- function IconWrapper({ children, style, accessibilityElementsHidden }) {
615
- return /* @__PURE__ */ jsx13(
616
- View9,
617
- {
618
- style: [{ alignItems: "center", justifyContent: "center" }, style],
619
- importantForAccessibility: accessibilityElementsHidden ? "no-hide-descendants" : "auto",
620
- accessibilityElementsHidden,
621
- children
622
- }
623
- );
547
+ return /* @__PURE__ */ jsx12(View7, { style: [styles10.list, style], accessibilityRole: "list", children: items.map((item, i) => /* @__PURE__ */ jsxs4(View7, { style: styles10.group, accessibilityRole: "listitem", children: [
548
+ /* @__PURE__ */ jsx12(Text8, { style: [styles10.term, { color: colors2.colorOnBgSubtle }], children: item.term }),
549
+ typeof item.description === "string" ? /* @__PURE__ */ jsx12(Text8, { style: [styles10.description, { color: colors2.colorOnBg }], children: item.description }) : /* @__PURE__ */ jsx12(View7, { children: item.description })
550
+ ] }, i)) });
624
551
  }
625
552
 
626
- // src/components/layout/ButtonGroup/ButtonGroup.native.tsx
627
- import { StyleSheet as StyleSheet11, View as View10 } from "react-native";
628
- import { jsx as jsx14 } from "react/jsx-runtime";
553
+ // src/components/ui/Breadcrumb/Breadcrumb.native.tsx
554
+ import { StyleSheet as StyleSheet11, View as View8, Text as Text9, Pressable as Pressable4 } from "react-native";
555
+ import { Fragment, jsx as jsx13, jsxs as jsxs5 } from "react/jsx-runtime";
629
556
  var styles11 = StyleSheet11.create({
630
- group: {
557
+ container: {
631
558
  flexDirection: "row",
632
559
  flexWrap: "wrap",
633
- gap: spacing.xs
560
+ alignItems: "center"
634
561
  },
635
- column: {
636
- flexDirection: "column",
637
- gap: spacing.xs
562
+ separator: {
563
+ marginHorizontal: spacing.xs,
564
+ fontSize: font.size.body,
565
+ fontFamily: font.family.body,
566
+ lineHeight: lineHeight.body
567
+ },
568
+ itemText: {
569
+ fontSize: font.size.body,
570
+ fontFamily: font.family.body,
571
+ lineHeight: lineHeight.body
572
+ },
573
+ pressed: {
574
+ opacity: 0.75
638
575
  }
639
576
  });
640
- function ButtonGroup({ children, variant, accessibilityLabel, style }) {
641
- const isColumn = variant === "card" || variant === "modal";
642
- return /* @__PURE__ */ jsx14(
643
- View10,
577
+ function Breadcrumb({ items, style }) {
578
+ const { colors: colors2 } = useTheme();
579
+ return /* @__PURE__ */ jsx13(
580
+ View8,
644
581
  {
645
- accessibilityLabel,
646
- style: [isColumn ? styles11.column : styles11.group, style],
647
- children
582
+ style: [styles11.container, style],
583
+ accessibilityRole: "navigation",
584
+ accessibilityLabel: "Breadcrumb",
585
+ children: items.map((item, index) => {
586
+ const isLast = index === items.length - 1;
587
+ return /* @__PURE__ */ jsx13(View8, { style: { flexDirection: "row", alignItems: "center", minHeight: 44 }, children: isLast ? /* @__PURE__ */ jsx13(
588
+ Text9,
589
+ {
590
+ style: [styles11.itemText, { color: colors2.colorOnBg }],
591
+ accessibilityRole: "text",
592
+ children: item.label
593
+ }
594
+ ) : /* @__PURE__ */ jsxs5(Fragment, { children: [
595
+ /* @__PURE__ */ jsx13(
596
+ Pressable4,
597
+ {
598
+ onPress: item.onPress,
599
+ accessibilityRole: "link",
600
+ style: ({ pressed }) => pressed && styles11.pressed,
601
+ children: /* @__PURE__ */ jsx13(Text9, { style: [styles11.itemText, { color: colors2.colorInteractiveOnBg }], children: item.label })
602
+ }
603
+ ),
604
+ /* @__PURE__ */ jsx13(
605
+ Text9,
606
+ {
607
+ style: [styles11.separator, { color: colors2.colorOnBgSubtle }],
608
+ importantForAccessibility: "no",
609
+ accessibilityElementsHidden: true,
610
+ children: "/"
611
+ }
612
+ )
613
+ ] }) }, index);
614
+ })
648
615
  }
649
616
  );
650
617
  }
651
618
 
652
- // src/components/interaction/Button/Button.native.tsx
653
- import { StyleSheet as StyleSheet12, Pressable as Pressable4, Text as Text8, View as View11 } from "react-native";
654
- import { jsx as jsx15, jsxs as jsxs5 } from "react/jsx-runtime";
655
- var sizeTokens = {
656
- small: { height: 36, px: spacing.m, fontSize: font.size.bodyS, radius: border.radius.xs },
657
- medium: { height: 48, px: spacing.m, fontSize: font.size.body, radius: border.radius.s },
658
- large: { height: 56, px: spacing.xxl, fontSize: font.size.heading3, radius: border.radius.m }
619
+ // src/components/ui/ProgressCircle/ProgressCircle.native.tsx
620
+ import { StyleSheet as StyleSheet12, View as View9, Text as Text10 } from "react-native";
621
+ import { jsx as jsx14, jsxs as jsxs6 } from "react/jsx-runtime";
622
+ var SIZE_PX = {
623
+ small: 40,
624
+ medium: 64,
625
+ large: 96
626
+ };
627
+ var STROKE_WIDTH = {
628
+ small: 3,
629
+ medium: 4,
630
+ large: 5
631
+ };
632
+ var FONT_SIZE = {
633
+ small: font.size.bodyS - 2,
634
+ medium: font.size.bodyS,
635
+ large: font.size.body
659
636
  };
660
637
  var styles12 = StyleSheet12.create({
661
- pressable: {
662
- flexDirection: "row",
638
+ wrapper: {
663
639
  alignItems: "center",
664
- justifyContent: "center",
665
- gap: spacing.xs,
666
- alignSelf: "flex-start"
640
+ justifyContent: "center"
667
641
  },
668
- label: {
642
+ valueText: {
643
+ position: "absolute",
669
644
  fontFamily: font.family.body,
670
- fontWeight: font.weight.semibold,
671
- includeFontPadding: false
645
+ fontWeight: font.weight.semibold
672
646
  }
673
647
  });
674
- function Button({
675
- children,
676
- variant = "default",
677
- size = "medium",
678
- iconStart,
679
- iconEnd,
680
- disabled = false,
681
- onPress,
682
- accessibilityLabel,
683
- style
648
+ function HalfCircle({
649
+ size,
650
+ stroke,
651
+ color,
652
+ rotation
684
653
  }) {
685
- const { colors: colors2 } = useTheme();
686
- const { height, px, fontSize, radius } = sizeTokens[size];
687
- const primaryColor = colors2.colorInteractive;
688
- const onPrimaryColor = colors2.colorOnInteractive;
689
- const outlineTextColor = colors2.colorInteractiveOnBg;
690
- const isOutline = variant === "outline" || variant === "ghost";
691
- const containerStyle = {
692
- height,
693
- paddingHorizontal: px,
694
- borderRadius: radius,
695
- opacity: disabled ? 0.4 : 1,
696
- ...variant === "default" && { backgroundColor: primaryColor },
697
- ...isOutline && {
698
- backgroundColor: "transparent",
699
- borderWidth: 1,
700
- borderColor: outlineTextColor
701
- }
702
- };
703
- const textColor = variant === "default" ? onPrimaryColor : outlineTextColor;
704
- return /* @__PURE__ */ jsxs5(
705
- Pressable4,
654
+ return /* @__PURE__ */ jsx14(
655
+ View9,
706
656
  {
707
- onPress,
708
- disabled,
709
- accessibilityRole: "button",
710
- accessibilityLabel,
711
- accessibilityState: { disabled },
712
- style: ({ pressed }) => [styles12.pressable, containerStyle, pressed && { opacity: 0.75 }, style],
713
- children: [
714
- iconStart && /* @__PURE__ */ jsx15(View11, { importantForAccessibility: "no-hide-descendants", accessibilityElementsHidden: true, children: iconStart }),
715
- children && /* @__PURE__ */ jsx15(Text8, { style: [styles12.label, { fontSize, color: textColor }], children }),
716
- iconEnd && /* @__PURE__ */ jsx15(View11, { importantForAccessibility: "no-hide-descendants", children: iconEnd })
717
- ]
657
+ style: {
658
+ width: size / 2,
659
+ height: size,
660
+ overflow: "hidden"
661
+ },
662
+ children: /* @__PURE__ */ jsx14(
663
+ View9,
664
+ {
665
+ style: {
666
+ width: size,
667
+ height: size,
668
+ borderRadius: size / 2,
669
+ borderWidth: stroke,
670
+ borderColor: color,
671
+ transform: [{ rotate: `${rotation}deg` }]
672
+ }
673
+ }
674
+ )
718
675
  }
719
676
  );
720
677
  }
721
-
722
- // src/components/interaction/form/Switch/Switch.native.tsx
723
- import { Switch as RNSwitch, View as View12, StyleSheet as StyleSheet14 } from "react-native";
724
-
725
- // src/components/interaction/form/atoms/Label.native.tsx
726
- import { Text as Text9 } from "react-native";
727
- import { jsx as jsx16 } from "react/jsx-runtime";
728
- function Label({ label, style }) {
678
+ function ProgressCircle({
679
+ value,
680
+ max = 100,
681
+ size = "medium",
682
+ label,
683
+ showValue = false,
684
+ style
685
+ }) {
729
686
  const { colors: colors2 } = useTheme();
730
- return /* @__PURE__ */ jsx16(
731
- Text9,
687
+ const percentage = Math.min(100, Math.max(0, value / max * 100));
688
+ const px = SIZE_PX[size];
689
+ const stroke = STROKE_WIDTH[size];
690
+ const fillColor = colors2.colorInteractive;
691
+ const trackColor = colors2.colorBgSubtle;
692
+ const degrees = percentage / 100 * 360;
693
+ return /* @__PURE__ */ jsxs6(
694
+ View9,
732
695
  {
733
696
  style: [
734
- {
735
- fontFamily: font.family.body,
736
- fontSize: font.size.body,
737
- lineHeight: lineHeight.body,
738
- fontWeight: font.weight.semibold,
739
- color: colors2.colorOnBg
740
- },
697
+ styles12.wrapper,
698
+ { width: px, height: px },
741
699
  style
742
700
  ],
743
- children: label
701
+ accessibilityRole: "progressbar",
702
+ accessibilityLabel: label,
703
+ accessibilityValue: { min: 0, max, now: value },
704
+ children: [
705
+ /* @__PURE__ */ jsx14(
706
+ View9,
707
+ {
708
+ style: {
709
+ position: "absolute",
710
+ width: px,
711
+ height: px,
712
+ borderRadius: px / 2,
713
+ borderWidth: stroke,
714
+ borderColor: trackColor
715
+ }
716
+ }
717
+ ),
718
+ /* @__PURE__ */ jsx14(
719
+ View9,
720
+ {
721
+ style: {
722
+ position: "absolute",
723
+ width: px / 2,
724
+ height: px,
725
+ start: px / 2,
726
+ overflow: "hidden"
727
+ },
728
+ children: /* @__PURE__ */ jsx14(
729
+ HalfCircle,
730
+ {
731
+ size: px,
732
+ stroke,
733
+ color: percentage > 0 ? fillColor : "transparent",
734
+ rotation: Math.min(degrees, 180) - 180
735
+ }
736
+ )
737
+ }
738
+ ),
739
+ degrees > 180 && /* @__PURE__ */ jsx14(
740
+ View9,
741
+ {
742
+ style: {
743
+ position: "absolute",
744
+ width: px / 2,
745
+ height: px,
746
+ start: 0,
747
+ overflow: "hidden"
748
+ },
749
+ children: /* @__PURE__ */ jsx14(
750
+ View9,
751
+ {
752
+ style: {
753
+ position: "absolute",
754
+ end: 0
755
+ },
756
+ children: /* @__PURE__ */ jsx14(
757
+ HalfCircle,
758
+ {
759
+ size: px,
760
+ stroke,
761
+ color: fillColor,
762
+ rotation: Math.min(degrees - 180, 180)
763
+ }
764
+ )
765
+ }
766
+ )
767
+ }
768
+ ),
769
+ showValue && /* @__PURE__ */ jsxs6(
770
+ Text10,
771
+ {
772
+ style: [styles12.valueText, { fontSize: FONT_SIZE[size], color: colors2.colorOnBg }],
773
+ importantForAccessibility: "no",
774
+ accessibilityElementsHidden: true,
775
+ children: [
776
+ Math.round(percentage),
777
+ "%"
778
+ ]
779
+ }
780
+ )
781
+ ]
744
782
  }
745
783
  );
746
784
  }
747
785
 
748
- // src/components/interaction/form/atoms/Message.native.tsx
749
- import { StyleSheet as StyleSheet13, Text as Text10 } from "react-native";
750
- import { jsx as jsx17 } from "react/jsx-runtime";
786
+ // src/components/ui/Tooltip/Tooltip.native.tsx
787
+ import { useState } from "react";
788
+ import { StyleSheet as StyleSheet13, View as View10, Text as Text11, Pressable as Pressable5 } from "react-native";
789
+ import { jsx as jsx15, jsxs as jsxs7 } from "react/jsx-runtime";
751
790
  var styles13 = StyleSheet13.create({
752
- base: {
753
- fontFamily: font.family.body,
791
+ wrapper: {
792
+ position: "relative"
793
+ },
794
+ tooltip: {
795
+ position: "absolute",
796
+ bottom: "100%",
797
+ start: 0,
798
+ marginBottom: spacing.xxs,
799
+ paddingVertical: spacing.xxs,
800
+ paddingHorizontal: spacing.xs,
801
+ borderRadius: border.radius.full,
802
+ zIndex: 10,
803
+ alignSelf: "flex-start"
804
+ },
805
+ text: {
754
806
  fontSize: font.size.bodyS,
755
- lineHeight: lineHeight.bodyS
807
+ fontFamily: font.family.body
756
808
  }
757
809
  });
758
- function Message({ message, type, style }) {
810
+ function Tooltip({ content, children, style }) {
759
811
  const { colors: colors2 } = useTheme();
760
- if (!message) return null;
761
- const color = type === "error" ? colors2.colorError : colors2.colorOnBgSubtle;
762
- return /* @__PURE__ */ jsx17(
763
- Text10,
764
- {
765
- accessibilityRole: type === "error" ? "alert" : "none",
766
- accessibilityLiveRegion: type === "error" ? "assertive" : "polite",
767
- style: [styles13.base, { color }, style],
768
- children: message
769
- }
770
- );
812
+ const [visible, setVisible] = useState(false);
813
+ return /* @__PURE__ */ jsxs7(View10, { style: [styles13.wrapper, style], children: [
814
+ /* @__PURE__ */ jsx15(
815
+ Pressable5,
816
+ {
817
+ onLongPress: () => setVisible(true),
818
+ onPressOut: () => setVisible(false),
819
+ accessibilityHint: content,
820
+ children
821
+ }
822
+ ),
823
+ visible && /* @__PURE__ */ jsx15(
824
+ View10,
825
+ {
826
+ style: [styles13.tooltip, { backgroundColor: colors2.colorOnBg }],
827
+ accessibilityRole: "text",
828
+ accessibilityLabel: content,
829
+ children: /* @__PURE__ */ jsx15(Text11, { style: [styles13.text, { color: colors2.colorBg }], children: content })
830
+ }
831
+ )
832
+ ] });
771
833
  }
772
834
 
773
- // src/components/interaction/form/Switch/Switch.native.tsx
774
- import { jsx as jsx18, jsxs as jsxs6 } from "react/jsx-runtime";
835
+ // src/components/ui/Pagination/Pagination.native.tsx
836
+ import { StyleSheet as StyleSheet14, View as View11, Text as Text12, Pressable as Pressable6 } from "react-native";
837
+ import { jsx as jsx16, jsxs as jsxs8 } from "react/jsx-runtime";
838
+ function getPageRange(current, total) {
839
+ const delta = 1;
840
+ const range = [];
841
+ for (let i = 1; i <= total; i++) {
842
+ if (i === 1 || i === total || i >= current - delta && i <= current + delta) {
843
+ range.push(i);
844
+ } else if (range[range.length - 1] !== "...") {
845
+ range.push("...");
846
+ }
847
+ }
848
+ return range;
849
+ }
775
850
  var styles14 = StyleSheet14.create({
776
851
  container: {
852
+ flexDirection: "row",
853
+ alignItems: "center",
777
854
  gap: spacing.xxs
778
855
  },
779
- row: {
780
- flexDirection: "row",
856
+ button: {
857
+ minWidth: 44,
858
+ minHeight: 44,
781
859
  alignItems: "center",
782
- gap: spacing.xs
860
+ justifyContent: "center",
861
+ borderRadius: border.radius.full,
862
+ paddingHorizontal: spacing.xs,
863
+ paddingVertical: spacing.xxs
864
+ },
865
+ buttonText: {
866
+ fontSize: font.size.body,
867
+ fontFamily: font.family.body,
868
+ lineHeight: lineHeight.body,
869
+ fontWeight: font.weight.body
870
+ },
871
+ navText: {
872
+ fontSize: font.size.body,
873
+ fontFamily: font.family.body,
874
+ lineHeight: lineHeight.body,
875
+ fontWeight: font.weight.semibold
876
+ },
877
+ ellipsis: {
878
+ fontSize: font.size.body,
879
+ fontFamily: font.family.body,
880
+ lineHeight: lineHeight.body,
881
+ minWidth: 44,
882
+ minHeight: 44,
883
+ textAlign: "center",
884
+ textAlignVertical: "center"
885
+ },
886
+ pressed: {
887
+ opacity: 0.75
888
+ },
889
+ disabled: {
890
+ opacity: 0.4
783
891
  }
784
892
  });
785
- function Switch({
786
- label,
787
- value = false,
788
- onChange,
789
- disabled = false,
790
- error,
791
- hint,
893
+ function Pagination({
894
+ currentPage,
895
+ totalPages,
896
+ onPageChange,
792
897
  style
793
898
  }) {
794
899
  const { colors: colors2 } = useTheme();
795
- return /* @__PURE__ */ jsxs6(View12, { style: [styles14.container, style], children: [
796
- /* @__PURE__ */ jsxs6(View12, { style: styles14.row, children: [
797
- /* @__PURE__ */ jsx18(
798
- RNSwitch,
799
- {
800
- value,
801
- onValueChange: onChange,
802
- disabled,
803
- accessibilityLabel: label,
804
- accessibilityRole: "switch",
805
- accessibilityState: { checked: value, disabled },
806
- thumbColor: colors2.colorInteractive,
807
- trackColor: { false: colors2.colorBgSubtle, true: colors2.colorBlueSubtle }
808
- }
809
- ),
810
- /* @__PURE__ */ jsx18(Label, { label })
811
- ] }),
812
- /* @__PURE__ */ jsx18(Message, { type: "error", message: error }),
813
- /* @__PURE__ */ jsx18(Message, { type: "hint", message: hint })
814
- ] });
900
+ const pages = getPageRange(currentPage, totalPages);
901
+ return /* @__PURE__ */ jsxs8(
902
+ View11,
903
+ {
904
+ style: [styles14.container, style],
905
+ accessibilityRole: "navigation",
906
+ accessibilityLabel: "Pagination",
907
+ children: [
908
+ /* @__PURE__ */ jsx16(
909
+ Pressable6,
910
+ {
911
+ onPress: () => onPageChange(currentPage - 1),
912
+ disabled: currentPage <= 1,
913
+ accessibilityRole: "button",
914
+ accessibilityLabel: "Previous page",
915
+ accessibilityState: { disabled: currentPage <= 1 },
916
+ style: ({ pressed }) => [
917
+ styles14.button,
918
+ currentPage <= 1 && styles14.disabled,
919
+ pressed && !currentPage && styles14.pressed
920
+ ],
921
+ children: /* @__PURE__ */ jsx16(Text12, { style: [styles14.navText, { color: colors2.colorOnBg }], children: "\u2039" })
922
+ }
923
+ ),
924
+ pages.map(
925
+ (page, index) => page === "..." ? /* @__PURE__ */ jsx16(
926
+ Text12,
927
+ {
928
+ style: [styles14.ellipsis, { color: colors2.colorOnBgSubtle }],
929
+ importantForAccessibility: "no",
930
+ accessibilityElementsHidden: true,
931
+ children: "..."
932
+ },
933
+ `ellipsis-${index}`
934
+ ) : /* @__PURE__ */ jsx16(
935
+ Pressable6,
936
+ {
937
+ onPress: () => onPageChange(page),
938
+ accessibilityRole: "button",
939
+ accessibilityLabel: `Page ${page}`,
940
+ accessibilityState: { selected: currentPage === page },
941
+ style: ({ pressed }) => [
942
+ styles14.button,
943
+ currentPage === page && { backgroundColor: colors2.colorInteractive },
944
+ pressed && styles14.pressed
945
+ ],
946
+ children: /* @__PURE__ */ jsx16(
947
+ Text12,
948
+ {
949
+ style: [
950
+ styles14.buttonText,
951
+ {
952
+ color: currentPage === page ? colors2.colorOnInteractive : colors2.colorOnBg
953
+ },
954
+ currentPage === page && { fontWeight: font.weight.semibold }
955
+ ],
956
+ children: page
957
+ }
958
+ )
959
+ },
960
+ page
961
+ )
962
+ ),
963
+ /* @__PURE__ */ jsx16(
964
+ Pressable6,
965
+ {
966
+ onPress: () => onPageChange(currentPage + 1),
967
+ disabled: currentPage >= totalPages,
968
+ accessibilityRole: "button",
969
+ accessibilityLabel: "Next page",
970
+ accessibilityState: { disabled: currentPage >= totalPages },
971
+ style: ({ pressed }) => [
972
+ styles14.button,
973
+ currentPage >= totalPages && styles14.disabled,
974
+ pressed && styles14.pressed
975
+ ],
976
+ children: /* @__PURE__ */ jsx16(Text12, { style: [styles14.navText, { color: colors2.colorOnBg }], children: "\u203A" })
977
+ }
978
+ )
979
+ ]
980
+ }
981
+ );
815
982
  }
816
983
 
817
- // src/components/interaction/form/Checkbox/Checkbox.native.tsx
818
- import { StyleSheet as StyleSheet15, View as View13, Pressable as Pressable5 } from "react-native";
819
- import { jsx as jsx19, jsxs as jsxs7 } from "react/jsx-runtime";
820
- var BOX = 22;
984
+ // src/components/ui/Collapsible/Collapsible.native.tsx
985
+ import { useCallback, useRef as useRef2, useState as useState2 } from "react";
986
+ import {
987
+ StyleSheet as StyleSheet15,
988
+ View as View12,
989
+ Text as Text13,
990
+ Pressable as Pressable7,
991
+ Animated as Animated2,
992
+ LayoutAnimation,
993
+ Platform,
994
+ UIManager
995
+ } from "react-native";
996
+ import { jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
997
+ if (Platform.OS === "android" && UIManager.setLayoutAnimationEnabledExperimental) {
998
+ UIManager.setLayoutAnimationEnabledExperimental(true);
999
+ }
821
1000
  var styles15 = StyleSheet15.create({
822
1001
  container: {
823
- gap: spacing.xxs
1002
+ borderRadius: border.radius.m,
1003
+ overflow: "hidden"
824
1004
  },
825
- row: {
1005
+ header: {
826
1006
  flexDirection: "row",
827
1007
  alignItems: "center",
828
- gap: spacing.xs,
829
- minHeight: 44
1008
+ justifyContent: "space-between",
1009
+ minHeight: 44,
1010
+ paddingVertical: spacing.s,
1011
+ paddingHorizontal: spacing.m
830
1012
  },
831
- box: {
832
- width: BOX,
833
- height: BOX,
834
- borderRadius: border.radius.xs,
835
- borderWidth: 2,
1013
+ summaryText: {
1014
+ flex: 1,
1015
+ fontSize: font.size.body,
1016
+ fontFamily: font.family.body,
1017
+ fontWeight: font.weight.semibold,
1018
+ lineHeight: lineHeight.body
1019
+ },
1020
+ chevron: {
1021
+ fontSize: font.size.body,
1022
+ marginStart: spacing.xs
1023
+ },
1024
+ content: {
1025
+ paddingHorizontal: spacing.m,
1026
+ paddingBottom: spacing.m
1027
+ },
1028
+ pressed: {
1029
+ opacity: 0.75
1030
+ }
1031
+ });
1032
+ function Collapsible({
1033
+ summary,
1034
+ children,
1035
+ open: controlledOpen,
1036
+ defaultOpen = false,
1037
+ onToggle,
1038
+ name: _name,
1039
+ // eslint-disable-line @typescript-eslint/no-unused-vars
1040
+ style
1041
+ }) {
1042
+ const { colors: colors2 } = useTheme();
1043
+ const [internalOpen, setInternalOpen] = useState2(defaultOpen);
1044
+ const isControlled = controlledOpen !== void 0;
1045
+ const isOpen = isControlled ? controlledOpen : internalOpen;
1046
+ const rotation = useRef2(new Animated2.Value(isOpen ? 1 : 0)).current;
1047
+ const toggle = useCallback(() => {
1048
+ const next = !isOpen;
1049
+ LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
1050
+ Animated2.timing(rotation, {
1051
+ toValue: next ? 1 : 0,
1052
+ duration: 200,
1053
+ useNativeDriver: true
1054
+ }).start();
1055
+ if (!isControlled) {
1056
+ setInternalOpen(next);
1057
+ }
1058
+ onToggle?.(next);
1059
+ }, [isOpen, isControlled, onToggle, rotation]);
1060
+ const rotateZ = rotation.interpolate({
1061
+ inputRange: [0, 1],
1062
+ outputRange: ["0deg", "90deg"]
1063
+ });
1064
+ return /* @__PURE__ */ jsxs9(
1065
+ View12,
1066
+ {
1067
+ style: [styles15.container, { borderBottomWidth: 1, borderBottomColor: colors2.colorBgSubtle }, style],
1068
+ accessibilityRole: "summary",
1069
+ children: [
1070
+ /* @__PURE__ */ jsxs9(
1071
+ Pressable7,
1072
+ {
1073
+ onPress: toggle,
1074
+ accessibilityRole: "button",
1075
+ accessibilityLabel: summary,
1076
+ accessibilityState: { expanded: isOpen },
1077
+ style: ({ pressed }) => [styles15.header, pressed && styles15.pressed],
1078
+ children: [
1079
+ /* @__PURE__ */ jsx17(Text13, { style: [styles15.summaryText, { color: colors2.colorOnBg }], children: summary }),
1080
+ /* @__PURE__ */ jsx17(
1081
+ Animated2.Text,
1082
+ {
1083
+ style: [styles15.chevron, { color: colors2.colorOnBgSubtle, transform: [{ rotateZ }] }],
1084
+ importantForAccessibility: "no",
1085
+ accessibilityElementsHidden: true,
1086
+ children: "\u25B8"
1087
+ }
1088
+ )
1089
+ ]
1090
+ }
1091
+ ),
1092
+ isOpen && /* @__PURE__ */ jsx17(View12, { style: styles15.content, children })
1093
+ ]
1094
+ }
1095
+ );
1096
+ }
1097
+
1098
+ // src/components/ui/Accordion/Accordion.native.tsx
1099
+ import { useState as useState3 } from "react";
1100
+ import {
1101
+ StyleSheet as StyleSheet16,
1102
+ View as View13,
1103
+ Text as Text14,
1104
+ Pressable as Pressable8,
1105
+ LayoutAnimation as LayoutAnimation2,
1106
+ Platform as Platform2,
1107
+ UIManager as UIManager2
1108
+ } from "react-native";
1109
+ import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
1110
+ if (Platform2.OS === "android" && UIManager2.setLayoutAnimationEnabledExperimental) {
1111
+ UIManager2.setLayoutAnimationEnabledExperimental(true);
1112
+ }
1113
+ var styles16 = StyleSheet16.create({
1114
+ container: {
1115
+ overflow: "hidden",
1116
+ borderRadius: border.radius.s
1117
+ },
1118
+ item: {
1119
+ borderBottomWidth: 1
1120
+ },
1121
+ header: {
1122
+ flexDirection: "row",
836
1123
  alignItems: "center",
837
- justifyContent: "center"
1124
+ justifyContent: "space-between",
1125
+ minHeight: 44,
1126
+ paddingVertical: spacing.s,
1127
+ paddingHorizontal: spacing.m
838
1128
  },
839
- checkmark: {
840
- fontSize: 14,
841
- fontWeight: "700",
842
- lineHeight: 16
1129
+ titleText: {
1130
+ flex: 1,
1131
+ fontSize: font.size.body,
1132
+ fontFamily: font.family.body,
1133
+ fontWeight: font.weight.semibold,
1134
+ lineHeight: lineHeight.body
1135
+ },
1136
+ chevron: {
1137
+ fontSize: font.size.bodyS,
1138
+ marginStart: spacing.xs
1139
+ },
1140
+ panel: {
1141
+ paddingHorizontal: spacing.m,
1142
+ paddingBottom: spacing.m
1143
+ },
1144
+ pressed: {
1145
+ opacity: 0.75
1146
+ },
1147
+ disabled: {
1148
+ opacity: 0.4
843
1149
  }
844
1150
  });
845
- function Checkbox({
846
- label,
847
- name,
848
- checked = false,
849
- onChange,
850
- disabled = false,
851
- error,
852
- hint,
1151
+ function Accordion({
1152
+ items,
1153
+ allowMultiple = false,
1154
+ defaultOpen = [],
853
1155
  style
854
1156
  }) {
855
1157
  const { colors: colors2 } = useTheme();
856
- const borderColor = error ? colors2.colorError : checked ? colors2.colorInteractive : colors2.colorBgSubtle;
857
- const bgColor = checked ? colors2.colorInteractive : "transparent";
858
- return /* @__PURE__ */ jsxs7(View13, { style: [styles15.container, style], children: [
859
- /* @__PURE__ */ jsxs7(
860
- Pressable5,
1158
+ const [openIds, setOpenIds] = useState3(defaultOpen);
1159
+ const toggle = (id) => {
1160
+ LayoutAnimation2.configureNext(LayoutAnimation2.Presets.easeInEaseOut);
1161
+ setOpenIds((prev) => {
1162
+ const isOpen = prev.includes(id);
1163
+ if (isOpen) return prev.filter((i) => i !== id);
1164
+ return allowMultiple ? [...prev, id] : [id];
1165
+ });
1166
+ };
1167
+ return /* @__PURE__ */ jsx18(View13, { style: [styles16.container, style], children: items.map((item, index) => {
1168
+ const isOpen = openIds.includes(item.id);
1169
+ const isLast = index === items.length - 1;
1170
+ return /* @__PURE__ */ jsxs10(
1171
+ View13,
861
1172
  {
862
- onPress: () => !disabled && onChange?.(!checked),
863
- accessibilityRole: "checkbox",
864
- accessibilityLabel: typeof label === "string" ? label : name,
865
- accessibilityState: { checked, disabled },
866
- disabled,
867
- style: ({ pressed }) => [styles15.row, pressed && { opacity: 0.7 }, disabled && { opacity: 0.4 }],
1173
+ style: [
1174
+ styles16.item,
1175
+ { borderBottomColor: colors2.colorBgSubtle },
1176
+ isLast && { borderBottomWidth: 0 }
1177
+ ],
868
1178
  children: [
869
- /* @__PURE__ */ jsx19(View13, { style: [styles15.box, { borderColor, backgroundColor: bgColor }], children: checked && /* @__PURE__ */ jsx19(Label, { label: "\u2713", style: [styles15.checkmark, { color: colors2.colorOnInteractive }] }) }),
870
- /* @__PURE__ */ jsx19(Label, { label })
1179
+ /* @__PURE__ */ jsxs10(
1180
+ Pressable8,
1181
+ {
1182
+ onPress: () => toggle(item.id),
1183
+ disabled: item.disabled,
1184
+ accessibilityRole: "button",
1185
+ accessibilityState: { expanded: isOpen, disabled: item.disabled },
1186
+ style: ({ pressed }) => [
1187
+ styles16.header,
1188
+ item.disabled && styles16.disabled,
1189
+ pressed && !item.disabled && styles16.pressed
1190
+ ],
1191
+ children: [
1192
+ /* @__PURE__ */ jsx18(Text14, { style: [styles16.titleText, { color: colors2.colorOnBg }], children: typeof item.title === "string" ? item.title : item.title }),
1193
+ /* @__PURE__ */ jsx18(
1194
+ Text14,
1195
+ {
1196
+ style: [styles16.chevron, { color: colors2.colorOnBgSubtle }],
1197
+ importantForAccessibility: "no",
1198
+ accessibilityElementsHidden: true,
1199
+ children: isOpen ? "\u25BE" : "\u25B8"
1200
+ }
1201
+ )
1202
+ ]
1203
+ }
1204
+ ),
1205
+ isOpen && /* @__PURE__ */ jsx18(View13, { style: styles16.panel, accessibilityRole: "summary", children: item.content })
871
1206
  ]
1207
+ },
1208
+ item.id
1209
+ );
1210
+ }) });
1211
+ }
1212
+
1213
+ // src/components/ui/Tabs/Tabs.native.tsx
1214
+ import { useState as useState4 } from "react";
1215
+ import {
1216
+ StyleSheet as StyleSheet17,
1217
+ View as View14,
1218
+ Text as Text15,
1219
+ Pressable as Pressable9,
1220
+ ScrollView
1221
+ } from "react-native";
1222
+ import { jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
1223
+ var styles17 = StyleSheet17.create({
1224
+ container: {
1225
+ overflow: "hidden"
1226
+ },
1227
+ tabList: {
1228
+ flexDirection: "row",
1229
+ borderBottomWidth: 2
1230
+ },
1231
+ tabButton: {
1232
+ minHeight: 44,
1233
+ paddingHorizontal: spacing.m,
1234
+ paddingVertical: spacing.s,
1235
+ alignItems: "center",
1236
+ justifyContent: "center",
1237
+ borderBottomWidth: 2,
1238
+ marginBottom: -2
1239
+ },
1240
+ tabLabel: {
1241
+ fontSize: font.size.body,
1242
+ fontFamily: font.family.body,
1243
+ lineHeight: lineHeight.body
1244
+ },
1245
+ panel: {
1246
+ paddingVertical: spacing.m
1247
+ },
1248
+ pressed: {
1249
+ opacity: 0.75
1250
+ },
1251
+ disabled: {
1252
+ opacity: 0.4
1253
+ }
1254
+ });
1255
+ function Tabs({
1256
+ tabs,
1257
+ defaultTab,
1258
+ style
1259
+ }) {
1260
+ const { colors: colors2 } = useTheme();
1261
+ const [activeTab, setActiveTab] = useState4(defaultTab ?? tabs[0]?.id);
1262
+ return /* @__PURE__ */ jsxs11(View14, { style: [styles17.container, style], children: [
1263
+ /* @__PURE__ */ jsx19(
1264
+ ScrollView,
1265
+ {
1266
+ horizontal: true,
1267
+ showsHorizontalScrollIndicator: false,
1268
+ contentContainerStyle: [styles17.tabList, { borderBottomColor: colors2.colorBgSubtle }],
1269
+ accessibilityRole: "tabbar",
1270
+ children: tabs.map((tab) => {
1271
+ const isActive = activeTab === tab.id;
1272
+ return /* @__PURE__ */ jsx19(
1273
+ Pressable9,
1274
+ {
1275
+ onPress: () => setActiveTab(tab.id),
1276
+ disabled: tab.disabled,
1277
+ accessibilityRole: "tab",
1278
+ accessibilityState: {
1279
+ selected: isActive,
1280
+ disabled: tab.disabled
1281
+ },
1282
+ accessibilityLabel: typeof tab.label === "string" ? tab.label : void 0,
1283
+ style: ({ pressed }) => [
1284
+ styles17.tabButton,
1285
+ {
1286
+ borderBottomColor: isActive ? colors2.colorInteractive : "transparent"
1287
+ },
1288
+ tab.disabled && styles17.disabled,
1289
+ pressed && !tab.disabled && styles17.pressed
1290
+ ],
1291
+ children: /* @__PURE__ */ jsx19(
1292
+ Text15,
1293
+ {
1294
+ style: [
1295
+ styles17.tabLabel,
1296
+ {
1297
+ color: isActive ? colors2.colorInteractive : colors2.colorOnBgSubtle,
1298
+ fontWeight: isActive ? font.weight.semibold : font.weight.body
1299
+ }
1300
+ ],
1301
+ children: tab.label
1302
+ }
1303
+ )
1304
+ },
1305
+ tab.id
1306
+ );
1307
+ })
872
1308
  }
873
1309
  ),
874
- /* @__PURE__ */ jsx19(Message, { type: "error", message: error }),
875
- /* @__PURE__ */ jsx19(Message, { type: "hint", message: hint })
1310
+ tabs.map((tab) => {
1311
+ const isActive = activeTab === tab.id;
1312
+ if (!isActive) return null;
1313
+ return /* @__PURE__ */ jsx19(View14, { style: styles17.panel, accessibilityRole: "tabpanel", children: tab.content }, tab.id);
1314
+ })
876
1315
  ] });
877
1316
  }
878
1317
 
879
- // src/components/interaction/form/Radio/Radio.native.tsx
880
- import { StyleSheet as StyleSheet16, View as View14, Pressable as Pressable6 } from "react-native";
881
- import { jsx as jsx20, jsxs as jsxs8 } from "react/jsx-runtime";
882
- var DOT = 22;
883
- var INNER = 10;
884
- var styles16 = StyleSheet16.create({
885
- container: {
1318
+ // src/components/ui/Table/Table.native.tsx
1319
+ import {
1320
+ StyleSheet as StyleSheet18,
1321
+ View as View15,
1322
+ Text as Text16,
1323
+ ScrollView as ScrollView2,
1324
+ Pressable as Pressable10
1325
+ } from "react-native";
1326
+ import { jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
1327
+ var styles18 = StyleSheet18.create({
1328
+ wrapper: {
1329
+ borderRadius: border.radius.s,
1330
+ overflow: "hidden"
1331
+ },
1332
+ caption: {
1333
+ fontSize: font.size.bodyS,
1334
+ fontFamily: font.family.body,
1335
+ fontWeight: font.weight.semibold,
1336
+ lineHeight: lineHeight.bodyS,
1337
+ paddingVertical: spacing.xs,
1338
+ paddingHorizontal: spacing.m
1339
+ },
1340
+ headerRow: {
1341
+ flexDirection: "row"
1342
+ },
1343
+ headerCell: {
1344
+ flex: 1,
1345
+ minWidth: 100,
1346
+ paddingVertical: spacing.s,
1347
+ paddingHorizontal: spacing.m,
1348
+ flexDirection: "row",
1349
+ alignItems: "center",
886
1350
  gap: spacing.xxs
887
1351
  },
1352
+ headerText: {
1353
+ fontSize: font.size.bodyS,
1354
+ fontFamily: font.family.body,
1355
+ fontWeight: font.weight.semibold,
1356
+ lineHeight: lineHeight.bodyS
1357
+ },
1358
+ sortIndicator: {
1359
+ fontSize: font.size.bodyS
1360
+ },
888
1361
  row: {
889
1362
  flexDirection: "row",
890
- alignItems: "center",
891
- gap: spacing.xs,
1363
+ borderTopWidth: 1,
892
1364
  minHeight: 44
893
1365
  },
894
- outer: {
895
- width: DOT,
896
- height: DOT,
897
- borderRadius: DOT / 2,
898
- borderWidth: 2,
899
- alignItems: "center",
1366
+ cell: {
1367
+ flex: 1,
1368
+ minWidth: 100,
1369
+ paddingVertical: spacing.s,
1370
+ paddingHorizontal: spacing.m,
900
1371
  justifyContent: "center"
901
1372
  },
902
- inner: {
903
- width: INNER,
904
- height: INNER,
905
- borderRadius: INNER / 2
1373
+ cellText: {
1374
+ fontSize: font.size.body,
1375
+ fontFamily: font.family.body,
1376
+ fontWeight: font.weight.body,
1377
+ lineHeight: lineHeight.body
1378
+ },
1379
+ pressed: {
1380
+ opacity: 0.75
906
1381
  }
907
1382
  });
908
- function Radio({
909
- label,
910
- name,
911
- checked = false,
912
- onChange,
913
- disabled = false,
914
- error,
915
- hint,
1383
+ function Table({
1384
+ columns,
1385
+ rows,
1386
+ caption,
1387
+ sortKey,
1388
+ sortDirection,
1389
+ onSort,
916
1390
  style
917
1391
  }) {
918
1392
  const { colors: colors2 } = useTheme();
919
- const borderColor = error ? colors2.colorError : checked ? colors2.colorInteractive : colors2.colorBgSubtle;
920
- return /* @__PURE__ */ jsxs8(View14, { style: [styles16.container, style], children: [
921
- /* @__PURE__ */ jsxs8(
922
- Pressable6,
923
- {
924
- onPress: () => !disabled && onChange?.(),
925
- accessibilityRole: "radio",
926
- accessibilityLabel: typeof label === "string" ? label : name,
927
- accessibilityState: { checked, disabled },
928
- disabled,
929
- style: ({ pressed }) => [styles16.row, pressed && { opacity: 0.7 }, disabled && { opacity: 0.4 }],
930
- children: [
931
- /* @__PURE__ */ jsx20(View14, { style: [styles16.outer, { borderColor }], children: checked && /* @__PURE__ */ jsx20(View14, { style: [styles16.inner, { backgroundColor: colors2.colorInteractive }] }) }),
932
- /* @__PURE__ */ jsx20(Label, { label })
933
- ]
934
- }
935
- ),
936
- /* @__PURE__ */ jsx20(Message, { type: "error", message: error }),
937
- /* @__PURE__ */ jsx20(Message, { type: "hint", message: hint })
1393
+ const handleSort = (key) => {
1394
+ if (!onSort) return;
1395
+ const nextDirection = sortKey === key && sortDirection === "asc" ? "desc" : "asc";
1396
+ onSort(key, nextDirection);
1397
+ };
1398
+ const getSortLabel = (col) => {
1399
+ const base = `Sort by ${String(col.header)}`;
1400
+ if (sortKey !== col.key) return base;
1401
+ return `${base}, currently ${sortDirection === "asc" ? "ascending" : "descending"}`;
1402
+ };
1403
+ return /* @__PURE__ */ jsx20(
1404
+ ScrollView2,
1405
+ {
1406
+ horizontal: true,
1407
+ showsHorizontalScrollIndicator: true,
1408
+ style: [styles18.wrapper, { backgroundColor: colors2.colorBg }, style],
1409
+ children: /* @__PURE__ */ jsxs12(View15, { children: [
1410
+ caption && /* @__PURE__ */ jsx20(Text16, { style: [styles18.caption, { color: colors2.colorOnBgSubtle }], children: caption }),
1411
+ /* @__PURE__ */ jsx20(View15, { style: [styles18.headerRow, { backgroundColor: colors2.colorBgSubtle }], children: columns.map(
1412
+ (col) => col.sortable ? /* @__PURE__ */ jsxs12(
1413
+ Pressable10,
1414
+ {
1415
+ onPress: () => handleSort(col.key),
1416
+ accessibilityRole: "button",
1417
+ accessibilityLabel: getSortLabel(col),
1418
+ style: ({ pressed }) => [styles18.headerCell, pressed && styles18.pressed],
1419
+ children: [
1420
+ /* @__PURE__ */ jsx20(Text16, { style: [styles18.headerText, { color: colors2.colorOnBg }], children: col.header }),
1421
+ /* @__PURE__ */ jsx20(
1422
+ Text16,
1423
+ {
1424
+ style: [
1425
+ styles18.sortIndicator,
1426
+ {
1427
+ color: sortKey === col.key ? colors2.colorInteractive : colors2.colorOnBgSubtle
1428
+ }
1429
+ ],
1430
+ importantForAccessibility: "no",
1431
+ accessibilityElementsHidden: true,
1432
+ children: sortKey === col.key ? sortDirection === "asc" ? "\u25B2" : "\u25BC" : "\u25BD"
1433
+ }
1434
+ )
1435
+ ]
1436
+ },
1437
+ col.key
1438
+ ) : /* @__PURE__ */ jsx20(View15, { style: styles18.headerCell, children: /* @__PURE__ */ jsx20(Text16, { style: [styles18.headerText, { color: colors2.colorOnBg }], children: col.header }) }, col.key)
1439
+ ) }),
1440
+ rows.map((row, rowIndex) => /* @__PURE__ */ jsx20(
1441
+ View15,
1442
+ {
1443
+ style: [
1444
+ styles18.row,
1445
+ { borderTopColor: colors2.colorBgSubtle },
1446
+ rowIndex % 2 === 1 && { backgroundColor: colors2.colorBgSubtle }
1447
+ ],
1448
+ accessibilityRole: "none",
1449
+ children: columns.map((col) => /* @__PURE__ */ jsx20(View15, { style: styles18.cell, children: col.render ? typeof col.render(row) === "string" ? /* @__PURE__ */ jsx20(Text16, { style: [styles18.cellText, { color: colors2.colorOnBg }], children: col.render(row) }) : col.render(row) : /* @__PURE__ */ jsx20(Text16, { style: [styles18.cellText, { color: colors2.colorOnBg }], children: String(row[col.key] ?? "") }) }, col.key))
1450
+ },
1451
+ rowIndex
1452
+ ))
1453
+ ] })
1454
+ }
1455
+ );
1456
+ }
1457
+
1458
+ // src/components/ui/Calendar/Calendar.native.tsx
1459
+ import { useState as useState5 } from "react";
1460
+ import {
1461
+ StyleSheet as StyleSheet19,
1462
+ View as View16,
1463
+ Text as Text17,
1464
+ Pressable as Pressable11
1465
+ } from "react-native";
1466
+ import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
1467
+ var DAYS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
1468
+ var DAY_LABELS = {
1469
+ Su: "Sunday",
1470
+ Mo: "Monday",
1471
+ Tu: "Tuesday",
1472
+ We: "Wednesday",
1473
+ Th: "Thursday",
1474
+ Fr: "Friday",
1475
+ Sa: "Saturday"
1476
+ };
1477
+ var MONTHS = [
1478
+ "January",
1479
+ "February",
1480
+ "March",
1481
+ "April",
1482
+ "May",
1483
+ "June",
1484
+ "July",
1485
+ "August",
1486
+ "September",
1487
+ "October",
1488
+ "November",
1489
+ "December"
1490
+ ];
1491
+ function isSameDay(a, b) {
1492
+ return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
1493
+ }
1494
+ function toMidnight(date) {
1495
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
1496
+ }
1497
+ function isOutOfRange(date, min, max) {
1498
+ const d = toMidnight(date);
1499
+ if (min && d < toMidnight(min)) return true;
1500
+ return !!(max && d > toMidnight(max));
1501
+ }
1502
+ function getDaysInMonth(year, month) {
1503
+ return new Date(year, month + 1, 0).getDate();
1504
+ }
1505
+ function getFirstDayOfMonth(year, month) {
1506
+ return new Date(year, month, 1).getDay();
1507
+ }
1508
+ var DAY_SIZE = 44;
1509
+ var styles19 = StyleSheet19.create({
1510
+ container: {
1511
+ alignSelf: "flex-start"
1512
+ },
1513
+ header: {
1514
+ flexDirection: "row",
1515
+ alignItems: "center",
1516
+ justifyContent: "space-between",
1517
+ paddingVertical: spacing.xs,
1518
+ paddingHorizontal: spacing.xxs
1519
+ },
1520
+ navButton: {
1521
+ minWidth: DAY_SIZE,
1522
+ minHeight: DAY_SIZE,
1523
+ alignItems: "center",
1524
+ justifyContent: "center",
1525
+ borderRadius: border.radius.full
1526
+ },
1527
+ navText: {
1528
+ fontSize: font.size.heading3,
1529
+ fontWeight: font.weight.semibold
1530
+ },
1531
+ monthYear: {
1532
+ fontSize: font.size.body,
1533
+ fontFamily: font.family.body,
1534
+ fontWeight: font.weight.semibold,
1535
+ lineHeight: lineHeight.body
1536
+ },
1537
+ weekRow: {
1538
+ flexDirection: "row"
1539
+ },
1540
+ weekday: {
1541
+ width: DAY_SIZE,
1542
+ height: DAY_SIZE,
1543
+ alignItems: "center",
1544
+ justifyContent: "center"
1545
+ },
1546
+ weekdayText: {
1547
+ fontSize: font.size.bodyS,
1548
+ fontFamily: font.family.body,
1549
+ fontWeight: font.weight.semibold,
1550
+ lineHeight: lineHeight.bodyS
1551
+ },
1552
+ grid: {
1553
+ gap: spacing.xxxs
1554
+ },
1555
+ dayRow: {
1556
+ flexDirection: "row"
1557
+ },
1558
+ dayCell: {
1559
+ width: DAY_SIZE,
1560
+ height: DAY_SIZE,
1561
+ alignItems: "center",
1562
+ justifyContent: "center",
1563
+ borderRadius: border.radius.full
1564
+ },
1565
+ dayText: {
1566
+ fontSize: font.size.body,
1567
+ fontFamily: font.family.body,
1568
+ lineHeight: lineHeight.body
1569
+ },
1570
+ today: {
1571
+ borderWidth: 1
1572
+ },
1573
+ pressed: {
1574
+ opacity: 0.75
1575
+ },
1576
+ disabled: {
1577
+ opacity: 0.4
1578
+ }
1579
+ });
1580
+ function Calendar({
1581
+ value,
1582
+ defaultValue,
1583
+ min,
1584
+ max,
1585
+ onChange,
1586
+ style
1587
+ }) {
1588
+ const { colors: colors2 } = useTheme();
1589
+ const today = /* @__PURE__ */ new Date();
1590
+ const controlled = value !== void 0;
1591
+ const [internal, setInternal] = useState5(defaultValue);
1592
+ const selected = controlled ? value : internal;
1593
+ const [viewYear, setViewYear] = useState5(
1594
+ selected?.getFullYear() ?? today.getFullYear()
1595
+ );
1596
+ const [viewMonth, setViewMonth] = useState5(
1597
+ selected?.getMonth() ?? today.getMonth()
1598
+ );
1599
+ const daysInMonth = getDaysInMonth(viewYear, viewMonth);
1600
+ const firstDay = getFirstDayOfMonth(viewYear, viewMonth);
1601
+ const navigate = (delta) => {
1602
+ const d = new Date(viewYear, viewMonth + delta, 1);
1603
+ setViewYear(d.getFullYear());
1604
+ setViewMonth(d.getMonth());
1605
+ };
1606
+ const selectDay = (day) => {
1607
+ const date = new Date(viewYear, viewMonth, day);
1608
+ if (isOutOfRange(date, min, max)) return;
1609
+ if (!controlled) setInternal(date);
1610
+ onChange?.(date);
1611
+ };
1612
+ const cells = [
1613
+ ...Array.from({ length: firstDay }, () => null),
1614
+ ...Array.from({ length: daysInMonth }, (_, i) => ({ day: i + 1 }))
1615
+ ];
1616
+ while (cells.length % 7 !== 0) cells.push(null);
1617
+ const rows = Array.from(
1618
+ { length: cells.length / 7 },
1619
+ (_, i) => cells.slice(i * 7, i * 7 + 7)
1620
+ );
1621
+ return /* @__PURE__ */ jsxs13(
1622
+ View16,
1623
+ {
1624
+ style: [styles19.container, style],
1625
+ accessibilityRole: "none",
1626
+ accessibilityLabel: `${MONTHS[viewMonth]} ${viewYear} calendar`,
1627
+ children: [
1628
+ /* @__PURE__ */ jsxs13(View16, { style: styles19.header, children: [
1629
+ /* @__PURE__ */ jsx21(
1630
+ Pressable11,
1631
+ {
1632
+ onPress: () => navigate(-1),
1633
+ accessibilityRole: "button",
1634
+ accessibilityLabel: "Previous month",
1635
+ style: ({ pressed }) => [styles19.navButton, pressed && styles19.pressed],
1636
+ children: /* @__PURE__ */ jsx21(Text17, { style: [styles19.navText, { color: colors2.colorOnBg }], children: "\u2039" })
1637
+ }
1638
+ ),
1639
+ /* @__PURE__ */ jsxs13(
1640
+ Text17,
1641
+ {
1642
+ style: [styles19.monthYear, { color: colors2.colorOnBg }],
1643
+ accessibilityRole: "text",
1644
+ accessibilityLiveRegion: "polite",
1645
+ children: [
1646
+ MONTHS[viewMonth],
1647
+ " ",
1648
+ viewYear
1649
+ ]
1650
+ }
1651
+ ),
1652
+ /* @__PURE__ */ jsx21(
1653
+ Pressable11,
1654
+ {
1655
+ onPress: () => navigate(1),
1656
+ accessibilityRole: "button",
1657
+ accessibilityLabel: "Next month",
1658
+ style: ({ pressed }) => [styles19.navButton, pressed && styles19.pressed],
1659
+ children: /* @__PURE__ */ jsx21(Text17, { style: [styles19.navText, { color: colors2.colorOnBg }], children: "\u203A" })
1660
+ }
1661
+ )
1662
+ ] }),
1663
+ /* @__PURE__ */ jsx21(View16, { style: styles19.weekRow, children: DAYS.map((d) => /* @__PURE__ */ jsx21(View16, { style: styles19.weekday, children: /* @__PURE__ */ jsx21(
1664
+ Text17,
1665
+ {
1666
+ style: [styles19.weekdayText, { color: colors2.colorOnBgSubtle }],
1667
+ accessibilityLabel: DAY_LABELS[d],
1668
+ children: d
1669
+ }
1670
+ ) }, d)) }),
1671
+ /* @__PURE__ */ jsx21(View16, { style: styles19.grid, children: rows.map((row, rowIndex) => /* @__PURE__ */ jsx21(View16, { style: styles19.dayRow, children: row.map((cell, colIndex) => {
1672
+ if (!cell) {
1673
+ return /* @__PURE__ */ jsx21(View16, { style: styles19.dayCell }, colIndex);
1674
+ }
1675
+ const date = new Date(viewYear, viewMonth, cell.day);
1676
+ const isSelected = selected ? isSameDay(date, selected) : false;
1677
+ const isToday = isSameDay(date, today);
1678
+ const disabled = isOutOfRange(date, min, max);
1679
+ return /* @__PURE__ */ jsx21(
1680
+ Pressable11,
1681
+ {
1682
+ onPress: () => selectDay(cell.day),
1683
+ disabled,
1684
+ accessibilityRole: "button",
1685
+ accessibilityLabel: date.toLocaleDateString("en", {
1686
+ month: "long",
1687
+ day: "numeric",
1688
+ year: "numeric"
1689
+ }),
1690
+ accessibilityState: {
1691
+ selected: isSelected,
1692
+ disabled
1693
+ },
1694
+ style: ({ pressed }) => [
1695
+ styles19.dayCell,
1696
+ isSelected && {
1697
+ backgroundColor: colors2.colorInteractive
1698
+ },
1699
+ isToday && !isSelected && [
1700
+ styles19.today,
1701
+ { borderColor: colors2.colorInteractive }
1702
+ ],
1703
+ disabled && styles19.disabled,
1704
+ pressed && !disabled && styles19.pressed
1705
+ ],
1706
+ children: /* @__PURE__ */ jsx21(
1707
+ Text17,
1708
+ {
1709
+ style: [
1710
+ styles19.dayText,
1711
+ {
1712
+ color: isSelected ? colors2.colorOnInteractive : colors2.colorOnBg,
1713
+ fontWeight: isToday ? font.weight.semibold : font.weight.body
1714
+ }
1715
+ ],
1716
+ children: cell.day
1717
+ }
1718
+ )
1719
+ },
1720
+ colIndex
1721
+ );
1722
+ }) }, rowIndex)) })
1723
+ ]
1724
+ }
1725
+ );
1726
+ }
1727
+
1728
+ // src/components/ui/Carousel/Carousel.native.tsx
1729
+ import { useCallback as useCallback2, useRef as useRef3, useState as useState6 } from "react";
1730
+ import {
1731
+ StyleSheet as StyleSheet20,
1732
+ View as View17,
1733
+ Text as Text18,
1734
+ Pressable as Pressable12,
1735
+ ScrollView as ScrollView3,
1736
+ Dimensions
1737
+ } from "react-native";
1738
+ import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
1739
+ var DOT_SIZE = 8;
1740
+ var DOT_HIT_SIZE = 44;
1741
+ var styles20 = StyleSheet20.create({
1742
+ container: {
1743
+ width: "100%"
1744
+ },
1745
+ scrollView: {
1746
+ flexGrow: 0
1747
+ },
1748
+ slide: {
1749
+ justifyContent: "center",
1750
+ alignItems: "center"
1751
+ },
1752
+ nav: {
1753
+ flexDirection: "row",
1754
+ alignItems: "center",
1755
+ justifyContent: "center",
1756
+ gap: spacing.xs,
1757
+ paddingVertical: spacing.s
1758
+ },
1759
+ navButton: {
1760
+ minWidth: 44,
1761
+ minHeight: 44,
1762
+ alignItems: "center",
1763
+ justifyContent: "center",
1764
+ borderRadius: border.radius.s
1765
+ },
1766
+ navText: {
1767
+ fontSize: 20,
1768
+ fontWeight: "600"
1769
+ },
1770
+ dots: {
1771
+ flexDirection: "row",
1772
+ alignItems: "center",
1773
+ gap: spacing.xs
1774
+ },
1775
+ dotWrapper: {
1776
+ minWidth: DOT_HIT_SIZE,
1777
+ minHeight: DOT_HIT_SIZE,
1778
+ alignItems: "center",
1779
+ justifyContent: "center"
1780
+ },
1781
+ dot: {
1782
+ width: DOT_SIZE,
1783
+ height: DOT_SIZE,
1784
+ borderRadius: DOT_SIZE / 2
1785
+ },
1786
+ pressed: {
1787
+ opacity: 0.75
1788
+ }
1789
+ });
1790
+ function Carousel({
1791
+ items,
1792
+ label,
1793
+ style
1794
+ }) {
1795
+ const { colors: colors2 } = useTheme();
1796
+ const scrollRef = useRef3(null);
1797
+ const [activeIndex, setActiveIndex] = useState6(0);
1798
+ const [slideWidth, setSlideWidth] = useState6(Dimensions.get("window").width);
1799
+ const handleScroll = useCallback2(
1800
+ (e) => {
1801
+ const offset = e.nativeEvent.contentOffset.x;
1802
+ const width = e.nativeEvent.layoutMeasurement.width;
1803
+ if (width > 0) {
1804
+ const index = Math.round(offset / width);
1805
+ setActiveIndex(index);
1806
+ }
1807
+ },
1808
+ []
1809
+ );
1810
+ const scrollTo = (index) => {
1811
+ const clamped = Math.max(0, Math.min(index, items.length - 1));
1812
+ scrollRef.current?.scrollTo({ x: clamped * slideWidth, animated: true });
1813
+ };
1814
+ return /* @__PURE__ */ jsxs14(
1815
+ View17,
1816
+ {
1817
+ style: [styles20.container, style],
1818
+ accessibilityRole: "none",
1819
+ accessibilityLabel: label,
1820
+ children: [
1821
+ /* @__PURE__ */ jsx22(
1822
+ ScrollView3,
1823
+ {
1824
+ ref: scrollRef,
1825
+ horizontal: true,
1826
+ pagingEnabled: true,
1827
+ showsHorizontalScrollIndicator: false,
1828
+ onScroll: handleScroll,
1829
+ scrollEventThrottle: 16,
1830
+ onLayout: (e) => setSlideWidth(e.nativeEvent.layout.width),
1831
+ style: styles20.scrollView,
1832
+ children: items.map((item, index) => /* @__PURE__ */ jsx22(View17, { style: [styles20.slide, { width: slideWidth }], children: item }, index))
1833
+ }
1834
+ ),
1835
+ /* @__PURE__ */ jsxs14(View17, { style: styles20.nav, children: [
1836
+ /* @__PURE__ */ jsx22(
1837
+ Pressable12,
1838
+ {
1839
+ onPress: () => scrollTo(activeIndex - 1),
1840
+ disabled: activeIndex <= 0,
1841
+ accessibilityRole: "button",
1842
+ accessibilityLabel: "Previous",
1843
+ accessibilityState: { disabled: activeIndex <= 0 },
1844
+ style: ({ pressed }) => [
1845
+ styles20.navButton,
1846
+ activeIndex <= 0 && { opacity: 0.4 },
1847
+ pressed && styles20.pressed
1848
+ ],
1849
+ children: /* @__PURE__ */ jsx22(Text18, { style: [styles20.navText, { color: colors2.colorOnBg }], children: "\u2039" })
1850
+ }
1851
+ ),
1852
+ /* @__PURE__ */ jsx22(View17, { style: styles20.dots, children: items.map((_, index) => /* @__PURE__ */ jsx22(
1853
+ Pressable12,
1854
+ {
1855
+ onPress: () => scrollTo(index),
1856
+ accessibilityRole: "button",
1857
+ accessibilityLabel: `Go to slide ${index + 1}`,
1858
+ accessibilityState: { selected: activeIndex === index },
1859
+ style: styles20.dotWrapper,
1860
+ children: /* @__PURE__ */ jsx22(
1861
+ View17,
1862
+ {
1863
+ style: [
1864
+ styles20.dot,
1865
+ {
1866
+ backgroundColor: activeIndex === index ? colors2.colorInteractive : colors2.colorBgSubtle
1867
+ }
1868
+ ]
1869
+ }
1870
+ )
1871
+ },
1872
+ index
1873
+ )) }),
1874
+ /* @__PURE__ */ jsx22(
1875
+ Pressable12,
1876
+ {
1877
+ onPress: () => scrollTo(activeIndex + 1),
1878
+ disabled: activeIndex >= items.length - 1,
1879
+ accessibilityRole: "button",
1880
+ accessibilityLabel: "Next",
1881
+ accessibilityState: { disabled: activeIndex >= items.length - 1 },
1882
+ style: ({ pressed }) => [
1883
+ styles20.navButton,
1884
+ activeIndex >= items.length - 1 && { opacity: 0.4 },
1885
+ pressed && styles20.pressed
1886
+ ],
1887
+ children: /* @__PURE__ */ jsx22(Text18, { style: [styles20.navText, { color: colors2.colorOnBg }], children: "\u203A" })
1888
+ }
1889
+ )
1890
+ ] })
1891
+ ]
1892
+ }
1893
+ );
1894
+ }
1895
+
1896
+ // src/components/layout/Card/Card.native.tsx
1897
+ import { StyleSheet as StyleSheet21, View as View18, Pressable as Pressable13 } from "react-native";
1898
+ import { jsx as jsx23 } from "react/jsx-runtime";
1899
+ var paddingMap = {
1900
+ none: 0,
1901
+ small: spacing.s,
1902
+ medium: spacing.m,
1903
+ large: spacing.xxl
1904
+ };
1905
+ var alignMap = {
1906
+ start: "flex-start",
1907
+ center: "center",
1908
+ end: "flex-end"
1909
+ };
1910
+ var styles21 = StyleSheet21.create({
1911
+ card: {
1912
+ borderRadius: border.radius.m,
1913
+ overflow: "hidden"
1914
+ }
1915
+ });
1916
+ function Card({
1917
+ children,
1918
+ variant = "default",
1919
+ padding = "medium",
1920
+ textAlign = "start",
1921
+ style,
1922
+ onPress,
1923
+ accessibilityLabel
1924
+ }) {
1925
+ const { colors: colors2 } = useTheme();
1926
+ const variantStyle = {
1927
+ backgroundColor: colors2.colorBg,
1928
+ ...variant === "elevated" && {
1929
+ shadowColor: "#000",
1930
+ shadowOffset: { width: 0, height: 2 },
1931
+ shadowOpacity: 0.1,
1932
+ shadowRadius: 8,
1933
+ elevation: 4
1934
+ },
1935
+ ...variant === "outlined" && {
1936
+ borderWidth: 1,
1937
+ borderColor: colors2.colorBgSubtle
1938
+ }
1939
+ };
1940
+ const inner = {
1941
+ padding: paddingMap[padding],
1942
+ alignItems: alignMap[textAlign]
1943
+ };
1944
+ if (onPress) {
1945
+ return /* @__PURE__ */ jsx23(
1946
+ Pressable13,
1947
+ {
1948
+ onPress,
1949
+ accessibilityRole: "button",
1950
+ accessibilityLabel,
1951
+ style: ({ pressed }) => [styles21.card, variantStyle, inner, pressed && { opacity: 0.8 }, style],
1952
+ children
1953
+ }
1954
+ );
1955
+ }
1956
+ return /* @__PURE__ */ jsx23(View18, { style: [styles21.card, variantStyle, inner, style], children });
1957
+ }
1958
+
1959
+ // src/components/layout/SectionHeader/SectionHeader.native.tsx
1960
+ import { StyleSheet as StyleSheet22, View as View19, Text as Text19 } from "react-native";
1961
+ import { jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
1962
+ var alignMap2 = {
1963
+ start: "flex-start",
1964
+ center: "center",
1965
+ end: "flex-end"
1966
+ };
1967
+ var titleStyles = StyleSheet22.create({
1968
+ small: {
1969
+ fontSize: font.size.heading3,
1970
+ fontFamily: font.family.heading,
1971
+ fontWeight: font.weight.heading,
1972
+ lineHeight: lineHeight.heading3
1973
+ },
1974
+ medium: {
1975
+ fontSize: font.size.heading2,
1976
+ fontFamily: font.family.heading,
1977
+ fontWeight: font.weight.heading,
1978
+ lineHeight: lineHeight.heading2
1979
+ },
1980
+ large: {
1981
+ fontSize: font.size.heading1,
1982
+ fontFamily: font.family.heading,
1983
+ fontWeight: font.weight.heading,
1984
+ lineHeight: lineHeight.heading1
1985
+ }
1986
+ });
1987
+ var styles22 = StyleSheet22.create({
1988
+ container: {
1989
+ gap: spacing.xxs
1990
+ },
1991
+ subtitle: {
1992
+ fontSize: font.size.bodyS,
1993
+ fontFamily: font.family.body,
1994
+ lineHeight: lineHeight.bodyS
1995
+ }
1996
+ });
1997
+ function SectionHeader({
1998
+ title,
1999
+ subtitle,
2000
+ alignment = "start",
2001
+ size = "medium",
2002
+ style
2003
+ }) {
2004
+ const { colors: colors2 } = useTheme();
2005
+ const align = alignMap2[alignment];
2006
+ return /* @__PURE__ */ jsxs15(View19, { style: [styles22.container, { alignItems: align }, style], children: [
2007
+ /* @__PURE__ */ jsx24(
2008
+ Text19,
2009
+ {
2010
+ accessibilityRole: "header",
2011
+ style: [titleStyles[size], { color: colors2.colorOnBg }],
2012
+ children: title
2013
+ }
2014
+ ),
2015
+ subtitle && /* @__PURE__ */ jsx24(Text19, { style: [styles22.subtitle, { color: colors2.colorOnBgSubtle }], children: subtitle })
2016
+ ] });
2017
+ }
2018
+
2019
+ // src/components/layout/IconWrapper/IconWrapper.native.tsx
2020
+ import { View as View20 } from "react-native";
2021
+ import { jsx as jsx25 } from "react/jsx-runtime";
2022
+ function IconWrapper({ children, style, accessibilityElementsHidden }) {
2023
+ return /* @__PURE__ */ jsx25(
2024
+ View20,
2025
+ {
2026
+ style: [{ alignItems: "center", justifyContent: "center" }, style],
2027
+ importantForAccessibility: accessibilityElementsHidden ? "no-hide-descendants" : "auto",
2028
+ accessibilityElementsHidden,
2029
+ children
2030
+ }
2031
+ );
2032
+ }
2033
+
2034
+ // src/components/layout/ButtonGroup/ButtonGroup.native.tsx
2035
+ import { StyleSheet as StyleSheet23, View as View21 } from "react-native";
2036
+ import { jsx as jsx26 } from "react/jsx-runtime";
2037
+ var styles23 = StyleSheet23.create({
2038
+ group: {
2039
+ flexDirection: "row",
2040
+ flexWrap: "wrap",
2041
+ gap: spacing.xs
2042
+ },
2043
+ column: {
2044
+ flexDirection: "column",
2045
+ gap: spacing.xs
2046
+ }
2047
+ });
2048
+ function ButtonGroup({ children, variant, accessibilityLabel, style }) {
2049
+ const isColumn = variant === "card" || variant === "modal";
2050
+ return /* @__PURE__ */ jsx26(
2051
+ View21,
2052
+ {
2053
+ accessibilityLabel,
2054
+ style: [isColumn ? styles23.column : styles23.group, style],
2055
+ children
2056
+ }
2057
+ );
2058
+ }
2059
+
2060
+ // src/components/interaction/Button/Button.native.tsx
2061
+ import { StyleSheet as StyleSheet24, Pressable as Pressable14, Text as Text20, View as View22 } from "react-native";
2062
+ import { jsx as jsx27, jsxs as jsxs16 } from "react/jsx-runtime";
2063
+ var sizeTokens = {
2064
+ small: { height: 36, px: spacing.m, fontSize: font.size.bodyS, radius: border.radius.full },
2065
+ medium: { height: 48, px: spacing.m, fontSize: font.size.body, radius: border.radius.full },
2066
+ large: { height: 56, px: spacing.xxl, fontSize: font.size.heading3, radius: border.radius.full }
2067
+ };
2068
+ var styles24 = StyleSheet24.create({
2069
+ pressable: {
2070
+ flexDirection: "row",
2071
+ alignItems: "center",
2072
+ justifyContent: "center",
2073
+ gap: spacing.xs,
2074
+ alignSelf: "flex-start"
2075
+ },
2076
+ label: {
2077
+ fontFamily: font.family.body,
2078
+ fontWeight: font.weight.semibold,
2079
+ includeFontPadding: false
2080
+ }
2081
+ });
2082
+ function Button({
2083
+ children,
2084
+ variant = "default",
2085
+ size = "medium",
2086
+ iconStart,
2087
+ iconEnd,
2088
+ disabled = false,
2089
+ onPress,
2090
+ accessibilityLabel,
2091
+ style
2092
+ }) {
2093
+ const { colors: colors2 } = useTheme();
2094
+ const { height, px, fontSize, radius } = sizeTokens[size];
2095
+ const primaryColor = colors2.colorInteractive;
2096
+ const onPrimaryColor = colors2.colorOnInteractive;
2097
+ const outlineTextColor = colors2.colorInteractiveOnBg;
2098
+ const isOutline = variant === "outline" || variant === "ghost";
2099
+ const containerStyle = {
2100
+ height,
2101
+ paddingHorizontal: px,
2102
+ borderRadius: radius,
2103
+ opacity: disabled ? 0.4 : 1,
2104
+ ...variant === "default" && { backgroundColor: primaryColor },
2105
+ ...isOutline && {
2106
+ backgroundColor: "transparent",
2107
+ borderWidth: 1,
2108
+ borderColor: outlineTextColor
2109
+ }
2110
+ };
2111
+ const textColor = variant === "default" ? onPrimaryColor : outlineTextColor;
2112
+ return /* @__PURE__ */ jsxs16(
2113
+ Pressable14,
2114
+ {
2115
+ onPress,
2116
+ disabled,
2117
+ accessibilityRole: "button",
2118
+ accessibilityLabel,
2119
+ accessibilityState: { disabled },
2120
+ style: ({ pressed }) => [styles24.pressable, containerStyle, pressed && { opacity: 0.75 }, style],
2121
+ children: [
2122
+ iconStart && /* @__PURE__ */ jsx27(View22, { importantForAccessibility: "no-hide-descendants", accessibilityElementsHidden: true, children: iconStart }),
2123
+ children && /* @__PURE__ */ jsx27(Text20, { style: [styles24.label, { fontSize, color: textColor }], children }),
2124
+ iconEnd && /* @__PURE__ */ jsx27(View22, { importantForAccessibility: "no-hide-descendants", children: iconEnd })
2125
+ ]
2126
+ }
2127
+ );
2128
+ }
2129
+
2130
+ // src/components/interaction/Rating/Rating.native.tsx
2131
+ import { StyleSheet as StyleSheet25, View as View23, Text as Text21 } from "react-native";
2132
+ import { jsx as jsx28 } from "react/jsx-runtime";
2133
+ var STAR_SIZE = 24;
2134
+ var styles25 = StyleSheet25.create({
2135
+ container: {
2136
+ flexDirection: "row",
2137
+ alignItems: "center"
2138
+ },
2139
+ star: {
2140
+ fontSize: STAR_SIZE,
2141
+ fontFamily: font.family.body
2142
+ }
2143
+ });
2144
+ function Rating({ value, max = 5, style, accessibilityLabel }) {
2145
+ const { colors: colors2 } = useTheme();
2146
+ const label = accessibilityLabel ?? `${value} out of ${max} stars`;
2147
+ return /* @__PURE__ */ jsx28(
2148
+ View23,
2149
+ {
2150
+ style: [styles25.container, style],
2151
+ accessibilityRole: "image",
2152
+ accessibilityLabel: label,
2153
+ children: Array.from({ length: max }).map((_, i) => /* @__PURE__ */ jsx28(
2154
+ Text21,
2155
+ {
2156
+ style: [
2157
+ styles25.star,
2158
+ { color: i < value ? colors2.colorWarning : colors2.colorBgSubtle }
2159
+ ],
2160
+ importantForAccessibility: "no",
2161
+ accessibilityElementsHidden: true,
2162
+ children: "\u2605"
2163
+ },
2164
+ i
2165
+ ))
2166
+ }
2167
+ );
2168
+ }
2169
+
2170
+ // src/components/interaction/form/Switch/Switch.native.tsx
2171
+ import { Switch as RNSwitch, View as View24, StyleSheet as StyleSheet27 } from "react-native";
2172
+
2173
+ // src/components/interaction/form/atoms/Label.native.tsx
2174
+ import { Text as Text22 } from "react-native";
2175
+ import { jsx as jsx29 } from "react/jsx-runtime";
2176
+ function Label({ label, style }) {
2177
+ const { colors: colors2 } = useTheme();
2178
+ return /* @__PURE__ */ jsx29(
2179
+ Text22,
2180
+ {
2181
+ style: [
2182
+ {
2183
+ fontFamily: font.family.body,
2184
+ fontSize: font.size.body,
2185
+ lineHeight: lineHeight.body,
2186
+ fontWeight: font.weight.semibold,
2187
+ color: colors2.colorOnBg
2188
+ },
2189
+ style
2190
+ ],
2191
+ children: label
2192
+ }
2193
+ );
2194
+ }
2195
+
2196
+ // src/components/interaction/form/atoms/Message.native.tsx
2197
+ import { StyleSheet as StyleSheet26, Text as Text23 } from "react-native";
2198
+ import { jsx as jsx30 } from "react/jsx-runtime";
2199
+ var styles26 = StyleSheet26.create({
2200
+ base: {
2201
+ fontFamily: font.family.body,
2202
+ fontSize: font.size.bodyS,
2203
+ lineHeight: lineHeight.bodyS
2204
+ }
2205
+ });
2206
+ function Message({ message, type, style }) {
2207
+ const { colors: colors2 } = useTheme();
2208
+ if (!message) return null;
2209
+ const color = type === "error" ? colors2.colorError : colors2.colorOnBgSubtle;
2210
+ return /* @__PURE__ */ jsx30(
2211
+ Text23,
2212
+ {
2213
+ accessibilityRole: type === "error" ? "alert" : "none",
2214
+ accessibilityLiveRegion: type === "error" ? "assertive" : "polite",
2215
+ style: [styles26.base, { color }, style],
2216
+ children: message
2217
+ }
2218
+ );
2219
+ }
2220
+
2221
+ // src/components/interaction/form/Switch/Switch.native.tsx
2222
+ import { jsx as jsx31, jsxs as jsxs17 } from "react/jsx-runtime";
2223
+ var styles27 = StyleSheet27.create({
2224
+ container: {
2225
+ gap: spacing.xxs
2226
+ },
2227
+ row: {
2228
+ flexDirection: "row",
2229
+ alignItems: "center",
2230
+ gap: spacing.xs
2231
+ }
2232
+ });
2233
+ function Switch({
2234
+ label,
2235
+ value = false,
2236
+ onChange,
2237
+ disabled = false,
2238
+ error,
2239
+ hint,
2240
+ style
2241
+ }) {
2242
+ const { colors: colors2 } = useTheme();
2243
+ return /* @__PURE__ */ jsxs17(View24, { style: [styles27.container, style], children: [
2244
+ /* @__PURE__ */ jsxs17(View24, { style: styles27.row, children: [
2245
+ /* @__PURE__ */ jsx31(
2246
+ RNSwitch,
2247
+ {
2248
+ value,
2249
+ onValueChange: onChange,
2250
+ disabled,
2251
+ accessibilityLabel: label,
2252
+ accessibilityRole: "switch",
2253
+ accessibilityState: { checked: value, disabled },
2254
+ thumbColor: colors2.colorInteractive,
2255
+ trackColor: { false: colors2.colorBgSubtle, true: colors2.colorBlueSubtle }
2256
+ }
2257
+ ),
2258
+ /* @__PURE__ */ jsx31(Label, { label })
2259
+ ] }),
2260
+ /* @__PURE__ */ jsx31(Message, { type: "error", message: error }),
2261
+ /* @__PURE__ */ jsx31(Message, { type: "hint", message: hint })
2262
+ ] });
2263
+ }
2264
+
2265
+ // src/components/interaction/form/Checkbox/Checkbox.native.tsx
2266
+ import { StyleSheet as StyleSheet28, View as View25, Pressable as Pressable15 } from "react-native";
2267
+ import { jsx as jsx32, jsxs as jsxs18 } from "react/jsx-runtime";
2268
+ var BOX = 22;
2269
+ var styles28 = StyleSheet28.create({
2270
+ container: {
2271
+ gap: spacing.xxs
2272
+ },
2273
+ row: {
2274
+ flexDirection: "row",
2275
+ alignItems: "center",
2276
+ gap: spacing.xs,
2277
+ minHeight: 44
2278
+ },
2279
+ box: {
2280
+ width: BOX,
2281
+ height: BOX,
2282
+ borderRadius: border.radius.xs,
2283
+ borderWidth: 2,
2284
+ alignItems: "center",
2285
+ justifyContent: "center"
2286
+ },
2287
+ checkmark: {
2288
+ fontSize: 14,
2289
+ fontWeight: "700",
2290
+ lineHeight: 16
2291
+ }
2292
+ });
2293
+ function Checkbox({
2294
+ label,
2295
+ name,
2296
+ checked = false,
2297
+ onChange,
2298
+ disabled = false,
2299
+ error,
2300
+ hint,
2301
+ style
2302
+ }) {
2303
+ const { colors: colors2 } = useTheme();
2304
+ const borderColor = error ? colors2.colorError : checked ? colors2.colorInteractive : colors2.colorOnBg;
2305
+ const bgColor = checked ? colors2.colorInteractive : "transparent";
2306
+ return /* @__PURE__ */ jsxs18(View25, { style: [styles28.container, style], children: [
2307
+ /* @__PURE__ */ jsxs18(
2308
+ Pressable15,
2309
+ {
2310
+ onPress: () => !disabled && onChange?.(!checked),
2311
+ accessibilityRole: "checkbox",
2312
+ accessibilityLabel: typeof label === "string" ? label : name,
2313
+ accessibilityState: { checked, disabled },
2314
+ disabled,
2315
+ style: ({ pressed }) => [styles28.row, pressed && { opacity: 0.7 }, disabled && { opacity: 0.4 }],
2316
+ children: [
2317
+ /* @__PURE__ */ jsx32(View25, { style: [styles28.box, { borderColor, backgroundColor: bgColor }], children: checked && /* @__PURE__ */ jsx32(Label, { label: "\u2713", style: [styles28.checkmark, { color: colors2.colorOnInteractive }] }) }),
2318
+ /* @__PURE__ */ jsx32(Label, { label })
2319
+ ]
2320
+ }
2321
+ ),
2322
+ /* @__PURE__ */ jsx32(Message, { type: "error", message: error }),
2323
+ /* @__PURE__ */ jsx32(Message, { type: "hint", message: hint })
2324
+ ] });
2325
+ }
2326
+
2327
+ // src/components/interaction/form/CheckboxGroup/CheckboxGroup.native.tsx
2328
+ import { StyleSheet as StyleSheet29, View as View26, Text as Text24 } from "react-native";
2329
+ import { jsx as jsx33, jsxs as jsxs19 } from "react/jsx-runtime";
2330
+ var styles29 = StyleSheet29.create({
2331
+ container: {
2332
+ gap: spacing.xs
2333
+ },
2334
+ legend: {
2335
+ fontFamily: font.family.body,
2336
+ fontSize: font.size.body,
2337
+ lineHeight: lineHeight.body,
2338
+ fontWeight: font.weight.semibold
2339
+ },
2340
+ required: {
2341
+ fontWeight: font.weight.body
2342
+ },
2343
+ items: {
2344
+ gap: spacing.xxs
2345
+ }
2346
+ });
2347
+ function CheckboxGroup({
2348
+ legend,
2349
+ children,
2350
+ error,
2351
+ hint,
2352
+ required,
2353
+ disabled = false,
2354
+ style
2355
+ }) {
2356
+ const { colors: colors2 } = useTheme();
2357
+ return /* @__PURE__ */ jsxs19(
2358
+ View26,
2359
+ {
2360
+ style: [styles29.container, disabled && { opacity: 0.4 }, style],
2361
+ accessibilityRole: "none",
2362
+ accessibilityLabel: legend,
2363
+ children: [
2364
+ /* @__PURE__ */ jsxs19(Text24, { style: [styles29.legend, { color: colors2.colorOnBg }], children: [
2365
+ legend,
2366
+ required && /* @__PURE__ */ jsx33(Text24, { style: [styles29.required, { color: colors2.colorOnBgSubtle }], children: " *" })
2367
+ ] }),
2368
+ /* @__PURE__ */ jsx33(View26, { style: styles29.items, children }),
2369
+ /* @__PURE__ */ jsx33(Message, { type: "error", message: error }),
2370
+ /* @__PURE__ */ jsx33(Message, { type: "hint", message: hint })
2371
+ ]
2372
+ }
2373
+ );
2374
+ }
2375
+
2376
+ // src/components/interaction/form/Radio/Radio.native.tsx
2377
+ import { StyleSheet as StyleSheet30, View as View27, Pressable as Pressable16 } from "react-native";
2378
+ import { jsx as jsx34, jsxs as jsxs20 } from "react/jsx-runtime";
2379
+ var DOT = 22;
2380
+ var INNER = 10;
2381
+ var styles30 = StyleSheet30.create({
2382
+ container: {
2383
+ gap: spacing.xxs
2384
+ },
2385
+ row: {
2386
+ flexDirection: "row",
2387
+ alignItems: "center",
2388
+ gap: spacing.xs,
2389
+ minHeight: 44
2390
+ },
2391
+ outer: {
2392
+ width: DOT,
2393
+ height: DOT,
2394
+ borderRadius: DOT / 2,
2395
+ borderWidth: 2,
2396
+ alignItems: "center",
2397
+ justifyContent: "center"
2398
+ },
2399
+ inner: {
2400
+ width: INNER,
2401
+ height: INNER,
2402
+ borderRadius: INNER / 2
2403
+ }
2404
+ });
2405
+ function Radio({
2406
+ label,
2407
+ name,
2408
+ checked = false,
2409
+ onChange,
2410
+ disabled = false,
2411
+ error,
2412
+ hint,
2413
+ style
2414
+ }) {
2415
+ const { colors: colors2 } = useTheme();
2416
+ const borderColor = error ? colors2.colorError : checked ? colors2.colorInteractive : colors2.colorOnBg;
2417
+ return /* @__PURE__ */ jsxs20(View27, { style: [styles30.container, style], children: [
2418
+ /* @__PURE__ */ jsxs20(
2419
+ Pressable16,
2420
+ {
2421
+ onPress: () => !disabled && onChange?.(),
2422
+ accessibilityRole: "radio",
2423
+ accessibilityLabel: typeof label === "string" ? label : name,
2424
+ accessibilityState: { checked, disabled },
2425
+ disabled,
2426
+ style: ({ pressed }) => [styles30.row, pressed && { opacity: 0.7 }, disabled && { opacity: 0.4 }],
2427
+ children: [
2428
+ /* @__PURE__ */ jsx34(View27, { style: [styles30.outer, { borderColor }], children: checked && /* @__PURE__ */ jsx34(View27, { style: [styles30.inner, { backgroundColor: colors2.colorInteractive }] }) }),
2429
+ /* @__PURE__ */ jsx34(Label, { label })
2430
+ ]
2431
+ }
2432
+ ),
2433
+ /* @__PURE__ */ jsx34(Message, { type: "error", message: error }),
2434
+ /* @__PURE__ */ jsx34(Message, { type: "hint", message: hint })
2435
+ ] });
2436
+ }
2437
+
2438
+ // src/components/interaction/form/RadioGroup/RadioGroup.native.tsx
2439
+ import { StyleSheet as StyleSheet31, View as View28, Text as Text25 } from "react-native";
2440
+ import { jsx as jsx35, jsxs as jsxs21 } from "react/jsx-runtime";
2441
+ var styles31 = StyleSheet31.create({
2442
+ container: {
2443
+ gap: spacing.xs
2444
+ },
2445
+ legend: {
2446
+ fontFamily: font.family.body,
2447
+ fontSize: font.size.body,
2448
+ lineHeight: lineHeight.body,
2449
+ fontWeight: font.weight.semibold
2450
+ },
2451
+ required: {
2452
+ fontWeight: font.weight.body
2453
+ },
2454
+ items: {
2455
+ gap: spacing.xxs
2456
+ }
2457
+ });
2458
+ function RadioGroup({
2459
+ legend,
2460
+ children,
2461
+ error,
2462
+ hint,
2463
+ required,
2464
+ disabled = false,
2465
+ style
2466
+ }) {
2467
+ const { colors: colors2 } = useTheme();
2468
+ return /* @__PURE__ */ jsxs21(
2469
+ View28,
2470
+ {
2471
+ style: [styles31.container, disabled && { opacity: 0.4 }, style],
2472
+ accessibilityRole: "radiogroup",
2473
+ accessibilityLabel: legend,
2474
+ children: [
2475
+ /* @__PURE__ */ jsxs21(Text25, { style: [styles31.legend, { color: colors2.colorOnBg }], children: [
2476
+ legend,
2477
+ required && /* @__PURE__ */ jsx35(Text25, { style: [styles31.required, { color: colors2.colorOnBgSubtle }], children: " *" })
2478
+ ] }),
2479
+ /* @__PURE__ */ jsx35(View28, { style: styles31.items, children }),
2480
+ /* @__PURE__ */ jsx35(Message, { type: "error", message: error }),
2481
+ /* @__PURE__ */ jsx35(Message, { type: "hint", message: hint })
2482
+ ]
2483
+ }
2484
+ );
2485
+ }
2486
+
2487
+ // src/components/interaction/form/FileInput/FileInput.native.tsx
2488
+ import { StyleSheet as StyleSheet32, View as View29, Pressable as Pressable17, Text as Text26 } from "react-native";
2489
+ import { jsx as jsx36, jsxs as jsxs22 } from "react/jsx-runtime";
2490
+ var styles32 = StyleSheet32.create({
2491
+ container: {
2492
+ gap: spacing.xxs
2493
+ },
2494
+ dropZone: {
2495
+ alignItems: "center",
2496
+ justifyContent: "center",
2497
+ gap: spacing.xs,
2498
+ paddingVertical: spacing.xl,
2499
+ paddingHorizontal: spacing.m,
2500
+ borderWidth: 2,
2501
+ borderStyle: "dashed",
2502
+ borderRadius: border.radius.s,
2503
+ minHeight: 120
2504
+ },
2505
+ icon: {
2506
+ fontSize: 28,
2507
+ lineHeight: 32
2508
+ },
2509
+ prompt: {
2510
+ fontFamily: font.family.body,
2511
+ fontSize: font.size.body,
2512
+ lineHeight: lineHeight.body,
2513
+ textAlign: "center"
2514
+ },
2515
+ acceptHint: {
2516
+ fontFamily: font.family.body,
2517
+ fontSize: font.size.bodyS,
2518
+ lineHeight: lineHeight.bodyS,
2519
+ textAlign: "center"
2520
+ },
2521
+ fileList: {
2522
+ gap: spacing.xxs,
2523
+ alignItems: "center"
2524
+ },
2525
+ fileName: {
2526
+ fontFamily: font.family.body,
2527
+ fontSize: font.size.bodyS,
2528
+ lineHeight: lineHeight.bodyS
2529
+ }
2530
+ });
2531
+ function FileInput({
2532
+ label,
2533
+ name,
2534
+ accept,
2535
+ disabled = false,
2536
+ required,
2537
+ error,
2538
+ hint,
2539
+ onSelect,
2540
+ fileNames = [],
2541
+ style
2542
+ }) {
2543
+ const { colors: colors2 } = useTheme();
2544
+ const borderColor = error ? colors2.colorError : colors2.colorBgSubtle;
2545
+ return /* @__PURE__ */ jsxs22(View29, { style: [styles32.container, style], testID: name, children: [
2546
+ /* @__PURE__ */ jsx36(
2547
+ Label,
2548
+ {
2549
+ label: required ? `${label} *` : label
2550
+ }
2551
+ ),
2552
+ /* @__PURE__ */ jsxs22(
2553
+ Pressable17,
2554
+ {
2555
+ onPress: () => !disabled && onSelect?.(),
2556
+ disabled,
2557
+ accessibilityRole: "button",
2558
+ accessibilityLabel: `${label}, tap to select file`,
2559
+ accessibilityState: { disabled },
2560
+ style: ({ pressed }) => [
2561
+ styles32.dropZone,
2562
+ {
2563
+ borderColor,
2564
+ backgroundColor: "transparent"
2565
+ },
2566
+ pressed && { opacity: 0.7 },
2567
+ disabled && { opacity: 0.4 }
2568
+ ],
2569
+ children: [
2570
+ /* @__PURE__ */ jsx36(Text26, { style: [styles32.icon, { color: colors2.colorInteractive }], children: "\u2191" }),
2571
+ /* @__PURE__ */ jsx36(Text26, { style: [styles32.prompt, { color: colors2.colorOnBgSubtle }], children: fileNames.length > 0 ? "Selected files:" : "Tap to select file" }),
2572
+ fileNames.length > 0 && /* @__PURE__ */ jsx36(View29, { style: styles32.fileList, children: fileNames.map((fileName) => /* @__PURE__ */ jsx36(Text26, { style: [styles32.fileName, { color: colors2.colorOnBg }], children: fileName }, fileName)) }),
2573
+ accept && /* @__PURE__ */ jsx36(Text26, { style: [styles32.acceptHint, { color: colors2.colorOnBgSubtle }], children: accept })
2574
+ ]
2575
+ }
2576
+ ),
2577
+ /* @__PURE__ */ jsx36(Message, { type: "error", message: error }),
2578
+ /* @__PURE__ */ jsx36(Message, { type: "hint", message: hint })
2579
+ ] });
2580
+ }
2581
+
2582
+ // src/components/interaction/form/Combobox/Combobox.native.tsx
2583
+ import { useState as useState7, useMemo as useMemo2 } from "react";
2584
+ import {
2585
+ StyleSheet as StyleSheet33,
2586
+ View as View30,
2587
+ TextInput,
2588
+ Pressable as Pressable18,
2589
+ Text as Text27,
2590
+ ScrollView as ScrollView4
2591
+ } from "react-native";
2592
+ import { jsx as jsx37, jsxs as jsxs23 } from "react/jsx-runtime";
2593
+ var MAX_DROPDOWN_HEIGHT = 200;
2594
+ var styles33 = StyleSheet33.create({
2595
+ container: {
2596
+ gap: spacing.xxs
2597
+ },
2598
+ inputWrapper: {
2599
+ position: "relative"
2600
+ },
2601
+ input: {
2602
+ fontFamily: font.family.body,
2603
+ fontSize: font.size.body,
2604
+ lineHeight: lineHeight.body,
2605
+ paddingVertical: spacing.xs,
2606
+ paddingHorizontal: spacing.s,
2607
+ borderWidth: 1,
2608
+ borderRadius: border.radius.full,
2609
+ minHeight: 44
2610
+ },
2611
+ dropdown: {
2612
+ position: "absolute",
2613
+ top: "100%",
2614
+ start: 0,
2615
+ end: 0,
2616
+ maxHeight: MAX_DROPDOWN_HEIGHT,
2617
+ borderWidth: 1,
2618
+ borderTopWidth: 0,
2619
+ borderBottomStartRadius: border.radius.xs,
2620
+ borderBottomEndRadius: border.radius.xs,
2621
+ zIndex: 10
2622
+ },
2623
+ option: {
2624
+ paddingVertical: spacing.xs,
2625
+ paddingHorizontal: spacing.s,
2626
+ minHeight: 44,
2627
+ justifyContent: "center"
2628
+ },
2629
+ optionText: {
2630
+ fontFamily: font.family.body,
2631
+ fontSize: font.size.body,
2632
+ lineHeight: lineHeight.body
2633
+ }
2634
+ });
2635
+ function Combobox({
2636
+ label,
2637
+ name,
2638
+ options,
2639
+ placeholder,
2640
+ value,
2641
+ onChange,
2642
+ disabled = false,
2643
+ error,
2644
+ hint,
2645
+ style
2646
+ }) {
2647
+ const { colors: colors2 } = useTheme();
2648
+ const selectedOption = useMemo2(
2649
+ () => options.find((o) => o.value === value),
2650
+ [options, value]
2651
+ );
2652
+ const [inputValue, setInputValue] = useState7(selectedOption?.label ?? "");
2653
+ const [isOpen, setIsOpen] = useState7(false);
2654
+ const filtered = useMemo2(
2655
+ () => options.filter(
2656
+ (o) => o.label.toLowerCase().includes(inputValue.toLowerCase())
2657
+ ),
2658
+ [options, inputValue]
2659
+ );
2660
+ const selectOption = (option) => {
2661
+ setInputValue(option.label);
2662
+ setIsOpen(false);
2663
+ onChange?.(option.value);
2664
+ };
2665
+ const handleChangeText = (text) => {
2666
+ setInputValue(text);
2667
+ setIsOpen(true);
2668
+ };
2669
+ const handleFocus = () => {
2670
+ setIsOpen(true);
2671
+ };
2672
+ const handleBlur = () => {
2673
+ setTimeout(() => setIsOpen(false), 150);
2674
+ };
2675
+ const borderColor = error ? colors2.colorError : colors2.colorOnBg;
2676
+ return /* @__PURE__ */ jsxs23(View30, { style: [styles33.container, style], children: [
2677
+ /* @__PURE__ */ jsx37(Label, { label }),
2678
+ /* @__PURE__ */ jsxs23(View30, { style: styles33.inputWrapper, children: [
2679
+ /* @__PURE__ */ jsx37(
2680
+ TextInput,
2681
+ {
2682
+ value: inputValue,
2683
+ onChangeText: handleChangeText,
2684
+ onFocus: handleFocus,
2685
+ onBlur: handleBlur,
2686
+ placeholder,
2687
+ placeholderTextColor: colors2.colorOnBgSubtle,
2688
+ editable: !disabled,
2689
+ accessibilityRole: "combobox",
2690
+ accessibilityLabel: typeof label === "string" ? label : name,
2691
+ accessibilityState: { disabled, expanded: isOpen },
2692
+ style: [
2693
+ styles33.input,
2694
+ {
2695
+ borderColor,
2696
+ color: colors2.colorOnBg,
2697
+ backgroundColor: colors2.colorBg
2698
+ },
2699
+ disabled && { opacity: 0.4 }
2700
+ ]
2701
+ }
2702
+ ),
2703
+ isOpen && filtered.length > 0 && /* @__PURE__ */ jsx37(
2704
+ ScrollView4,
2705
+ {
2706
+ style: [
2707
+ styles33.dropdown,
2708
+ {
2709
+ borderColor: colors2.colorBgSubtle,
2710
+ backgroundColor: colors2.colorBg
2711
+ }
2712
+ ],
2713
+ keyboardShouldPersistTaps: "handled",
2714
+ nestedScrollEnabled: true,
2715
+ children: filtered.map((option) => {
2716
+ const isSelected = option.value === value;
2717
+ const isDisabled = option.disabled;
2718
+ return /* @__PURE__ */ jsx37(
2719
+ Pressable18,
2720
+ {
2721
+ onPress: () => !isDisabled && selectOption(option),
2722
+ disabled: isDisabled,
2723
+ accessibilityRole: "menuitem",
2724
+ accessibilityLabel: option.label,
2725
+ accessibilityState: { selected: isSelected, disabled: isDisabled },
2726
+ style: ({ pressed }) => [
2727
+ styles33.option,
2728
+ isSelected && { backgroundColor: colors2.colorBlueSubtle },
2729
+ pressed && !isDisabled && { backgroundColor: colors2.colorBgSubtle },
2730
+ isDisabled && { opacity: 0.4 }
2731
+ ],
2732
+ children: /* @__PURE__ */ jsx37(
2733
+ Text27,
2734
+ {
2735
+ style: [
2736
+ styles33.optionText,
2737
+ {
2738
+ color: isSelected ? colors2.colorInteractive : colors2.colorOnBg
2739
+ },
2740
+ isSelected && { fontWeight: font.weight.semibold }
2741
+ ],
2742
+ children: option.label
2743
+ }
2744
+ )
2745
+ },
2746
+ option.value
2747
+ );
2748
+ })
2749
+ }
2750
+ )
2751
+ ] }),
2752
+ /* @__PURE__ */ jsx37(Message, { type: "error", message: error }),
2753
+ /* @__PURE__ */ jsx37(Message, { type: "hint", message: hint })
2754
+ ] });
2755
+ }
2756
+
2757
+ // src/components/interaction/form/SegmentedControl/SegmentedControl.native.tsx
2758
+ import { Children } from "react";
2759
+ import { StyleSheet as StyleSheet34, View as View31, Pressable as Pressable19, Text as Text28 } from "react-native";
2760
+ import { jsx as jsx38 } from "react/jsx-runtime";
2761
+ var sizeTokens2 = {
2762
+ small: { height: 32, fontSize: font.size.bodyS, px: spacing.s },
2763
+ medium: { height: 40, fontSize: font.size.body, px: spacing.m },
2764
+ large: { height: 48, fontSize: font.size.body, px: spacing.l }
2765
+ };
2766
+ var styles34 = StyleSheet34.create({
2767
+ track: {
2768
+ flexDirection: "row",
2769
+ borderRadius: border.radius.full,
2770
+ overflow: "hidden"
2771
+ },
2772
+ item: {
2773
+ flex: 1,
2774
+ alignItems: "center",
2775
+ justifyContent: "center",
2776
+ minHeight: 44
2777
+ },
2778
+ label: {
2779
+ fontFamily: font.family.body,
2780
+ fontWeight: font.weight.semibold,
2781
+ textAlign: "center"
2782
+ }
2783
+ });
2784
+ function SegmentedControl({
2785
+ selectedIndex = 0,
2786
+ disabled = false,
2787
+ size = "medium",
2788
+ variant = "outline",
2789
+ children,
2790
+ accessibilityLabel,
2791
+ onValueChange,
2792
+ style
2793
+ }) {
2794
+ const { colors: colors2 } = useTheme();
2795
+ const { height, fontSize, px } = sizeTokens2[size];
2796
+ const items = Children.toArray(children);
2797
+ const trackStyle = variant === "filled" ? { backgroundColor: colors2.colorBgSubtle } : { backgroundColor: "transparent", borderWidth: 1, borderColor: colors2.colorBgSubtle };
2798
+ return /* @__PURE__ */ jsx38(
2799
+ View31,
2800
+ {
2801
+ style: [styles34.track, trackStyle, { borderRadius: border.radius.full }, style],
2802
+ accessibilityRole: "tablist",
2803
+ accessibilityLabel,
2804
+ children: items.map((child, index) => {
2805
+ const isActive = index === selectedIndex;
2806
+ const activeStyle = variant === "filled" ? { backgroundColor: colors2.colorInteractive } : { borderWidth: 2, borderColor: colors2.colorInteractive };
2807
+ const inactiveStyle = variant === "filled" ? {} : {};
2808
+ const textColor = variant === "filled" && isActive ? colors2.colorOnInteractive : isActive ? colors2.colorInteractive : colors2.colorOnBgSubtle;
2809
+ const label = typeof child === "string" || typeof child === "number" ? String(child) : null;
2810
+ return /* @__PURE__ */ jsx38(
2811
+ Pressable19,
2812
+ {
2813
+ onPress: () => !disabled && onValueChange?.(index),
2814
+ disabled,
2815
+ accessibilityRole: "tab",
2816
+ accessibilityLabel: label ?? void 0,
2817
+ accessibilityState: { selected: isActive, disabled },
2818
+ style: ({ pressed }) => [
2819
+ styles34.item,
2820
+ { height, paddingHorizontal: px },
2821
+ isActive ? activeStyle : inactiveStyle,
2822
+ variant === "filled" && isActive && { borderRadius: border.radius.full },
2823
+ pressed && !disabled && { opacity: 0.7 },
2824
+ disabled && { opacity: 0.4 }
2825
+ ],
2826
+ children: label !== null ? /* @__PURE__ */ jsx38(Text28, { style: [styles34.label, { fontSize, color: textColor }], children: label }) : child
2827
+ },
2828
+ index
2829
+ );
2830
+ })
2831
+ }
2832
+ );
2833
+ }
2834
+
2835
+ // src/components/interaction/form/FormInput/FormInput.native.tsx
2836
+ import { useState as useState8 } from "react";
2837
+ import {
2838
+ StyleSheet as StyleSheet35,
2839
+ View as View32,
2840
+ TextInput as TextInput2
2841
+ } from "react-native";
2842
+ import { jsx as jsx39, jsxs as jsxs24 } from "react/jsx-runtime";
2843
+ var keyboardTypeMap = {
2844
+ text: "default",
2845
+ email: "email-address",
2846
+ password: "default",
2847
+ tel: "phone-pad",
2848
+ url: "url",
2849
+ number: "numeric",
2850
+ search: "default"
2851
+ };
2852
+ var styles35 = StyleSheet35.create({
2853
+ container: {
2854
+ gap: spacing.xxs
2855
+ },
2856
+ input: {
2857
+ fontFamily: font.family.body,
2858
+ fontSize: font.size.body,
2859
+ lineHeight: lineHeight.body,
2860
+ paddingHorizontal: spacing.s,
2861
+ paddingVertical: spacing.xs,
2862
+ borderWidth: 1,
2863
+ borderRadius: border.radius.full,
2864
+ minHeight: 44
2865
+ }
2866
+ });
2867
+ function FormInput({
2868
+ label,
2869
+ name,
2870
+ type = "text",
2871
+ value,
2872
+ defaultValue,
2873
+ placeholder,
2874
+ error,
2875
+ hint,
2876
+ disabled = false,
2877
+ onChange,
2878
+ onBlur,
2879
+ onFocus,
2880
+ style
2881
+ }) {
2882
+ const { colors: colors2 } = useTheme();
2883
+ const [focused, setFocused] = useState8(false);
2884
+ const borderColor = error ? colors2.colorError : focused ? colors2.colorInteractive : colors2.colorOnBg;
2885
+ return /* @__PURE__ */ jsxs24(View32, { style: [styles35.container, style], children: [
2886
+ /* @__PURE__ */ jsx39(Label, { label }),
2887
+ /* @__PURE__ */ jsx39(
2888
+ TextInput2,
2889
+ {
2890
+ accessibilityLabel: typeof label === "string" ? label : name,
2891
+ accessibilityState: { disabled },
2892
+ accessibilityHint: hint,
2893
+ value,
2894
+ defaultValue,
2895
+ placeholder,
2896
+ placeholderTextColor: colors2.colorOnBgSubtle,
2897
+ keyboardType: keyboardTypeMap[type],
2898
+ secureTextEntry: type === "password",
2899
+ autoCapitalize: type === "email" || type === "url" ? "none" : "sentences",
2900
+ autoComplete: type === "email" ? "email" : type === "tel" ? "tel" : void 0,
2901
+ editable: !disabled,
2902
+ onChangeText: onChange,
2903
+ onFocus: () => {
2904
+ setFocused(true);
2905
+ onFocus?.();
2906
+ },
2907
+ onBlur: () => {
2908
+ setFocused(false);
2909
+ onBlur?.();
2910
+ },
2911
+ style: [
2912
+ styles35.input,
2913
+ {
2914
+ borderColor,
2915
+ color: colors2.colorOnBg,
2916
+ backgroundColor: colors2.colorBg
2917
+ },
2918
+ disabled && { opacity: 0.4 }
2919
+ ]
2920
+ }
2921
+ ),
2922
+ /* @__PURE__ */ jsx39(Message, { type: "error", message: error }),
2923
+ /* @__PURE__ */ jsx39(Message, { type: "hint", message: hint })
2924
+ ] });
2925
+ }
2926
+
2927
+ // src/components/interaction/form/Textarea/Textarea.native.tsx
2928
+ import { useState as useState9 } from "react";
2929
+ import {
2930
+ StyleSheet as StyleSheet36,
2931
+ View as View33,
2932
+ TextInput as TextInput3
2933
+ } from "react-native";
2934
+ import { jsx as jsx40, jsxs as jsxs25 } from "react/jsx-runtime";
2935
+ var styles36 = StyleSheet36.create({
2936
+ container: {
2937
+ gap: spacing.xxs
2938
+ },
2939
+ textarea: {
2940
+ fontFamily: font.family.body,
2941
+ fontSize: font.size.body,
2942
+ lineHeight: lineHeight.body,
2943
+ paddingHorizontal: spacing.s,
2944
+ paddingVertical: spacing.xs,
2945
+ borderWidth: 1,
2946
+ borderRadius: border.radius.xs,
2947
+ minHeight: 100,
2948
+ textAlignVertical: "top"
2949
+ }
2950
+ });
2951
+ function Textarea({
2952
+ label,
2953
+ name,
2954
+ value,
2955
+ defaultValue,
2956
+ placeholder,
2957
+ error,
2958
+ hint,
2959
+ disabled = false,
2960
+ numberOfLines = 4,
2961
+ onChange,
2962
+ onBlur,
2963
+ onFocus,
2964
+ style
2965
+ }) {
2966
+ const { colors: colors2 } = useTheme();
2967
+ const [focused, setFocused] = useState9(false);
2968
+ const borderColor = error ? colors2.colorError : focused ? colors2.colorInteractive : colors2.colorOnBg;
2969
+ return /* @__PURE__ */ jsxs25(View33, { style: [styles36.container, style], children: [
2970
+ /* @__PURE__ */ jsx40(Label, { label }),
2971
+ /* @__PURE__ */ jsx40(
2972
+ TextInput3,
2973
+ {
2974
+ accessibilityLabel: typeof label === "string" ? label : name,
2975
+ accessibilityState: { disabled },
2976
+ accessibilityHint: hint,
2977
+ multiline: true,
2978
+ numberOfLines,
2979
+ value,
2980
+ defaultValue,
2981
+ placeholder,
2982
+ placeholderTextColor: colors2.colorOnBgSubtle,
2983
+ editable: !disabled,
2984
+ onChangeText: onChange,
2985
+ onFocus: () => {
2986
+ setFocused(true);
2987
+ onFocus?.();
2988
+ },
2989
+ onBlur: () => {
2990
+ setFocused(false);
2991
+ onBlur?.();
2992
+ },
2993
+ style: [
2994
+ styles36.textarea,
2995
+ {
2996
+ borderColor,
2997
+ color: colors2.colorOnBg,
2998
+ backgroundColor: colors2.colorBg
2999
+ },
3000
+ disabled && { opacity: 0.4 }
3001
+ ]
3002
+ }
3003
+ ),
3004
+ /* @__PURE__ */ jsx40(Message, { type: "error", message: error }),
3005
+ /* @__PURE__ */ jsx40(Message, { type: "hint", message: hint })
3006
+ ] });
3007
+ }
3008
+
3009
+ // src/components/interaction/form/Select/Select.native.tsx
3010
+ import { useState as useState10 } from "react";
3011
+ import {
3012
+ StyleSheet as StyleSheet37,
3013
+ View as View34,
3014
+ Text as Text29,
3015
+ Pressable as Pressable20,
3016
+ Modal,
3017
+ FlatList,
3018
+ SafeAreaView
3019
+ } from "react-native";
3020
+ import { jsx as jsx41, jsxs as jsxs26 } from "react/jsx-runtime";
3021
+ var styles37 = StyleSheet37.create({
3022
+ container: {
3023
+ gap: spacing.xxs
3024
+ },
3025
+ trigger: {
3026
+ flexDirection: "row",
3027
+ alignItems: "center",
3028
+ justifyContent: "space-between",
3029
+ paddingHorizontal: spacing.s,
3030
+ paddingVertical: spacing.xs,
3031
+ borderWidth: 1,
3032
+ borderRadius: border.radius.full,
3033
+ minHeight: 44
3034
+ },
3035
+ triggerText: {
3036
+ fontFamily: font.family.body,
3037
+ fontSize: font.size.body,
3038
+ lineHeight: lineHeight.body,
3039
+ flex: 1
3040
+ },
3041
+ chevron: {
3042
+ fontFamily: font.family.body,
3043
+ fontSize: font.size.body,
3044
+ marginStart: spacing.xs
3045
+ },
3046
+ overlay: {
3047
+ flex: 1,
3048
+ justifyContent: "flex-end",
3049
+ backgroundColor: "rgba(0, 0, 0, 0.5)"
3050
+ },
3051
+ sheet: {
3052
+ maxHeight: "60%",
3053
+ borderTopStartRadius: border.radius.m,
3054
+ borderTopEndRadius: border.radius.m,
3055
+ paddingTop: spacing.m,
3056
+ paddingBottom: spacing.xxxl
3057
+ },
3058
+ sheetHeader: {
3059
+ flexDirection: "row",
3060
+ justifyContent: "space-between",
3061
+ alignItems: "center",
3062
+ paddingHorizontal: spacing.m,
3063
+ paddingBottom: spacing.s
3064
+ },
3065
+ sheetTitle: {
3066
+ fontFamily: font.family.body,
3067
+ fontSize: font.size.heading3,
3068
+ fontWeight: font.weight.semibold
3069
+ },
3070
+ closeText: {
3071
+ fontFamily: font.family.body,
3072
+ fontSize: font.size.body,
3073
+ fontWeight: font.weight.semibold
3074
+ },
3075
+ optionItem: {
3076
+ paddingHorizontal: spacing.m,
3077
+ paddingVertical: spacing.s,
3078
+ minHeight: 44,
3079
+ justifyContent: "center"
3080
+ },
3081
+ optionText: {
3082
+ fontFamily: font.family.body,
3083
+ fontSize: font.size.body,
3084
+ lineHeight: lineHeight.body
3085
+ }
3086
+ });
3087
+ function Select({
3088
+ label,
3089
+ name,
3090
+ options,
3091
+ placeholder = "Select an option",
3092
+ value,
3093
+ error,
3094
+ hint,
3095
+ disabled = false,
3096
+ onChange,
3097
+ style
3098
+ }) {
3099
+ const { colors: colors2 } = useTheme();
3100
+ const [open, setOpen] = useState10(false);
3101
+ const selectedOption = options.find((o) => o.value === value);
3102
+ const displayText = selectedOption?.label ?? placeholder;
3103
+ const isPlaceholder = !selectedOption;
3104
+ const borderColor = error ? colors2.colorError : open ? colors2.colorInteractive : colors2.colorOnBg;
3105
+ const handleSelect = (optionValue) => {
3106
+ onChange?.(optionValue);
3107
+ setOpen(false);
3108
+ };
3109
+ return /* @__PURE__ */ jsxs26(View34, { style: [styles37.container, style], children: [
3110
+ /* @__PURE__ */ jsx41(Label, { label }),
3111
+ /* @__PURE__ */ jsxs26(
3112
+ Pressable20,
3113
+ {
3114
+ accessibilityRole: "button",
3115
+ accessibilityLabel: typeof label === "string" ? `${label}, ${displayText}` : name,
3116
+ accessibilityState: { disabled, expanded: open },
3117
+ accessibilityHint: "Double tap to open options",
3118
+ disabled,
3119
+ onPress: () => setOpen(true),
3120
+ style: [
3121
+ styles37.trigger,
3122
+ {
3123
+ borderColor,
3124
+ backgroundColor: colors2.colorBg
3125
+ },
3126
+ disabled && { opacity: 0.4 }
3127
+ ],
3128
+ children: [
3129
+ /* @__PURE__ */ jsx41(
3130
+ Text29,
3131
+ {
3132
+ style: [
3133
+ styles37.triggerText,
3134
+ {
3135
+ color: isPlaceholder ? colors2.colorOnBgSubtle : colors2.colorOnBg
3136
+ }
3137
+ ],
3138
+ children: displayText
3139
+ }
3140
+ ),
3141
+ /* @__PURE__ */ jsx41(Text29, { style: [styles37.chevron, { color: colors2.colorOnBgSubtle }], "aria-hidden": true, children: "\u25BE" })
3142
+ ]
3143
+ }
3144
+ ),
3145
+ /* @__PURE__ */ jsx41(
3146
+ Modal,
3147
+ {
3148
+ visible: open,
3149
+ transparent: true,
3150
+ animationType: "slide",
3151
+ onRequestClose: () => setOpen(false),
3152
+ children: /* @__PURE__ */ jsx41(
3153
+ Pressable20,
3154
+ {
3155
+ style: styles37.overlay,
3156
+ onPress: () => setOpen(false),
3157
+ accessibilityRole: "button",
3158
+ accessibilityLabel: "Close options",
3159
+ children: /* @__PURE__ */ jsx41(
3160
+ Pressable20,
3161
+ {
3162
+ style: [styles37.sheet, { backgroundColor: colors2.colorBg }],
3163
+ onPress: () => {
3164
+ },
3165
+ children: /* @__PURE__ */ jsxs26(SafeAreaView, { children: [
3166
+ /* @__PURE__ */ jsxs26(View34, { style: styles37.sheetHeader, children: [
3167
+ /* @__PURE__ */ jsx41(Text29, { style: [styles37.sheetTitle, { color: colors2.colorOnBg }], children: typeof label === "string" ? label : "Select" }),
3168
+ /* @__PURE__ */ jsx41(
3169
+ Pressable20,
3170
+ {
3171
+ accessibilityRole: "button",
3172
+ accessibilityLabel: "Close",
3173
+ onPress: () => setOpen(false),
3174
+ hitSlop: 8,
3175
+ children: /* @__PURE__ */ jsx41(Text29, { style: [styles37.closeText, { color: colors2.colorInteractive }], children: "Done" })
3176
+ }
3177
+ )
3178
+ ] }),
3179
+ /* @__PURE__ */ jsx41(
3180
+ FlatList,
3181
+ {
3182
+ data: options,
3183
+ keyExtractor: (item) => item.value,
3184
+ renderItem: ({ item }) => {
3185
+ const isSelected = item.value === value;
3186
+ return /* @__PURE__ */ jsx41(
3187
+ Pressable20,
3188
+ {
3189
+ accessibilityRole: "button",
3190
+ accessibilityLabel: item.label,
3191
+ accessibilityState: {
3192
+ selected: isSelected,
3193
+ disabled: item.disabled
3194
+ },
3195
+ disabled: item.disabled,
3196
+ onPress: () => handleSelect(item.value),
3197
+ style: ({ pressed }) => [
3198
+ styles37.optionItem,
3199
+ isSelected && { backgroundColor: colors2.colorBgSubtle },
3200
+ pressed && { opacity: 0.7 },
3201
+ item.disabled && { opacity: 0.4 }
3202
+ ],
3203
+ children: /* @__PURE__ */ jsx41(
3204
+ Text29,
3205
+ {
3206
+ style: [
3207
+ styles37.optionText,
3208
+ {
3209
+ color: isSelected ? colors2.colorInteractive : colors2.colorOnBg,
3210
+ fontWeight: isSelected ? font.weight.semibold : font.weight.body
3211
+ }
3212
+ ],
3213
+ children: item.label
3214
+ }
3215
+ )
3216
+ }
3217
+ );
3218
+ }
3219
+ }
3220
+ )
3221
+ ] })
3222
+ }
3223
+ )
3224
+ }
3225
+ )
3226
+ }
3227
+ ),
3228
+ /* @__PURE__ */ jsx41(Message, { type: "error", message: error }),
3229
+ /* @__PURE__ */ jsx41(Message, { type: "hint", message: hint })
3230
+ ] });
3231
+ }
3232
+
3233
+ // src/components/interaction/form/Slider/Slider.native.tsx
3234
+ import { useState as useState11 } from "react";
3235
+ import {
3236
+ StyleSheet as StyleSheet38,
3237
+ View as View35,
3238
+ Text as Text30
3239
+ } from "react-native";
3240
+ import { jsx as jsx42, jsxs as jsxs27 } from "react/jsx-runtime";
3241
+ var TRACK_HEIGHT = 6;
3242
+ var THUMB_SIZE = 24;
3243
+ var styles38 = StyleSheet38.create({
3244
+ container: {
3245
+ gap: spacing.xxs
3246
+ },
3247
+ labelRow: {
3248
+ flexDirection: "row",
3249
+ justifyContent: "space-between",
3250
+ alignItems: "center"
3251
+ },
3252
+ valueText: {
3253
+ fontFamily: font.family.body,
3254
+ fontSize: font.size.bodyS,
3255
+ lineHeight: lineHeight.bodyS,
3256
+ fontWeight: font.weight.semibold
3257
+ },
3258
+ trackContainer: {
3259
+ height: THUMB_SIZE + spacing.xs * 2,
3260
+ justifyContent: "center",
3261
+ paddingHorizontal: THUMB_SIZE / 2
3262
+ },
3263
+ track: {
3264
+ height: TRACK_HEIGHT,
3265
+ borderRadius: TRACK_HEIGHT / 2,
3266
+ overflow: "hidden"
3267
+ },
3268
+ fill: {
3269
+ height: TRACK_HEIGHT,
3270
+ borderRadius: TRACK_HEIGHT / 2
3271
+ },
3272
+ thumb: {
3273
+ position: "absolute",
3274
+ width: THUMB_SIZE,
3275
+ height: THUMB_SIZE,
3276
+ borderRadius: THUMB_SIZE / 2,
3277
+ top: "50%",
3278
+ marginTop: -(THUMB_SIZE / 2),
3279
+ borderWidth: 2
3280
+ }
3281
+ });
3282
+ function clampValue(v, min, max) {
3283
+ return Math.min(max, Math.max(min, v));
3284
+ }
3285
+ function snapToStep(v, min, step) {
3286
+ return Math.round((v - min) / step) * step + min;
3287
+ }
3288
+ function Slider({
3289
+ label,
3290
+ name: _name,
3291
+ // eslint-disable-line @typescript-eslint/no-unused-vars
3292
+ value,
3293
+ defaultValue,
3294
+ min = 0,
3295
+ max = 100,
3296
+ step = 1,
3297
+ showValue = false,
3298
+ disabled = false,
3299
+ error,
3300
+ hint,
3301
+ onChange,
3302
+ style
3303
+ }) {
3304
+ const { colors: colors2 } = useTheme();
3305
+ const isControlled = value !== void 0;
3306
+ const [internalValue, setInternalValue] = useState11(defaultValue ?? min);
3307
+ const [trackWidth, setTrackWidth] = useState11(0);
3308
+ const currentValue = isControlled ? value : internalValue;
3309
+ const fillPct = max > min ? (currentValue - min) / (max - min) * 100 : 0;
3310
+ const updateValue = (v) => {
3311
+ const clamped = clampValue(v, min, max);
3312
+ const snapped = snapToStep(clamped, min, step);
3313
+ if (!isControlled) setInternalValue(snapped);
3314
+ onChange?.(snapped);
3315
+ };
3316
+ const handleTrackLayout = (e) => {
3317
+ setTrackWidth(e.nativeEvent.layout.width);
3318
+ };
3319
+ const valueFromTouch = (pageX, layoutX) => {
3320
+ const x = pageX - layoutX;
3321
+ const pct = clampValue(x / trackWidth, 0, 1);
3322
+ return pct * (max - min) + min;
3323
+ };
3324
+ const handleStartShouldSetResponder = () => !disabled;
3325
+ const handleResponderGrant = (e) => {
3326
+ const target = e.currentTarget;
3327
+ target.measure((_x, _y, _w, _h, pageX) => {
3328
+ updateValue(valueFromTouch(e.nativeEvent.pageX, pageX));
3329
+ });
3330
+ };
3331
+ const handleResponderMove = (e) => {
3332
+ const target = e.currentTarget;
3333
+ target.measure((_x, _y, _w, _h, pageX) => {
3334
+ updateValue(valueFromTouch(e.nativeEvent.pageX, pageX));
3335
+ });
3336
+ };
3337
+ return /* @__PURE__ */ jsxs27(
3338
+ View35,
3339
+ {
3340
+ style: [styles38.container, style],
3341
+ accessibilityRole: "adjustable",
3342
+ accessibilityLabel: label,
3343
+ accessibilityValue: { min, max, now: currentValue, text: String(currentValue) },
3344
+ accessibilityState: { disabled },
3345
+ children: [
3346
+ /* @__PURE__ */ jsxs27(View35, { style: styles38.labelRow, children: [
3347
+ /* @__PURE__ */ jsx42(Label, { label }),
3348
+ showValue && /* @__PURE__ */ jsx42(Text30, { style: [styles38.valueText, { color: colors2.colorOnBg }], children: currentValue })
3349
+ ] }),
3350
+ /* @__PURE__ */ jsxs27(
3351
+ View35,
3352
+ {
3353
+ style: [styles38.trackContainer, disabled && { opacity: 0.4 }],
3354
+ onLayout: handleTrackLayout,
3355
+ onStartShouldSetResponder: handleStartShouldSetResponder,
3356
+ onMoveShouldSetResponder: handleStartShouldSetResponder,
3357
+ onResponderGrant: handleResponderGrant,
3358
+ onResponderMove: handleResponderMove,
3359
+ children: [
3360
+ /* @__PURE__ */ jsx42(View35, { style: [styles38.track, { backgroundColor: colors2.colorBgSubtle }], children: /* @__PURE__ */ jsx42(
3361
+ View35,
3362
+ {
3363
+ style: [
3364
+ styles38.fill,
3365
+ {
3366
+ width: `${fillPct}%`,
3367
+ backgroundColor: error ? colors2.colorError : colors2.colorInteractive
3368
+ }
3369
+ ]
3370
+ }
3371
+ ) }),
3372
+ /* @__PURE__ */ jsx42(
3373
+ View35,
3374
+ {
3375
+ style: [
3376
+ styles38.thumb,
3377
+ {
3378
+ start: `${fillPct}%`,
3379
+ marginStart: -(THUMB_SIZE / 2),
3380
+ backgroundColor: colors2.colorBg,
3381
+ borderColor: error ? colors2.colorError : colors2.colorInteractive
3382
+ }
3383
+ ]
3384
+ }
3385
+ )
3386
+ ]
3387
+ }
3388
+ ),
3389
+ /* @__PURE__ */ jsx42(Message, { type: "error", message: error }),
3390
+ /* @__PURE__ */ jsx42(Message, { type: "hint", message: hint })
3391
+ ]
3392
+ }
3393
+ );
3394
+ }
3395
+
3396
+ // src/components/interaction/form/NumberInput/NumberInput.native.tsx
3397
+ import { useState as useState12 } from "react";
3398
+ import {
3399
+ StyleSheet as StyleSheet39,
3400
+ View as View36,
3401
+ TextInput as TextInput4,
3402
+ Text as Text31,
3403
+ Pressable as Pressable21
3404
+ } from "react-native";
3405
+ import { jsx as jsx43, jsxs as jsxs28 } from "react/jsx-runtime";
3406
+ var STEPPER_SIZE = 44;
3407
+ var styles39 = StyleSheet39.create({
3408
+ container: {
3409
+ gap: spacing.xxs
3410
+ },
3411
+ inputRow: {
3412
+ flexDirection: "row",
3413
+ alignItems: "center"
3414
+ },
3415
+ stepper: {
3416
+ width: STEPPER_SIZE,
3417
+ height: STEPPER_SIZE,
3418
+ alignItems: "center",
3419
+ justifyContent: "center",
3420
+ borderWidth: 1
3421
+ },
3422
+ stepperStart: {
3423
+ borderTopStartRadius: border.radius.full,
3424
+ borderBottomStartRadius: border.radius.full,
3425
+ borderEndWidth: 0
3426
+ },
3427
+ stepperEnd: {
3428
+ borderTopEndRadius: border.radius.full,
3429
+ borderBottomEndRadius: border.radius.full,
3430
+ borderStartWidth: 0
3431
+ },
3432
+ stepperText: {
3433
+ fontSize: 20,
3434
+ fontWeight: font.weight.semibold,
3435
+ lineHeight: 24
3436
+ },
3437
+ input: {
3438
+ flex: 1,
3439
+ fontFamily: font.family.body,
3440
+ fontSize: font.size.body,
3441
+ lineHeight: lineHeight.body,
3442
+ textAlign: "center",
3443
+ paddingHorizontal: spacing.xs,
3444
+ paddingVertical: spacing.xs,
3445
+ borderTopWidth: 1,
3446
+ borderBottomWidth: 1,
3447
+ minHeight: STEPPER_SIZE
3448
+ }
3449
+ });
3450
+ function NumberInput({
3451
+ label,
3452
+ name: _name,
3453
+ // eslint-disable-line @typescript-eslint/no-unused-vars
3454
+ value,
3455
+ defaultValue,
3456
+ min,
3457
+ max,
3458
+ step = 1,
3459
+ disabled = false,
3460
+ error,
3461
+ hint,
3462
+ onChange,
3463
+ style
3464
+ }) {
3465
+ const { colors: colors2 } = useTheme();
3466
+ const isControlled = value !== void 0;
3467
+ const [internalValue, setInternalValue] = useState12(defaultValue ?? 0);
3468
+ const currentValue = isControlled ? value : internalValue;
3469
+ const clamp = (v) => {
3470
+ const withMin = min !== void 0 ? Math.max(min, v) : v;
3471
+ return max !== void 0 ? Math.min(max, withMin) : withMin;
3472
+ };
3473
+ const update = (next) => {
3474
+ const clamped = clamp(next);
3475
+ if (!isControlled) setInternalValue(clamped);
3476
+ onChange?.(clamped);
3477
+ };
3478
+ const canDecrease = min === void 0 || currentValue > min;
3479
+ const canIncrease = max === void 0 || currentValue < max;
3480
+ const borderColor = error ? colors2.colorError : colors2.colorOnBg;
3481
+ return /* @__PURE__ */ jsxs28(View36, { style: [styles39.container, style], children: [
3482
+ /* @__PURE__ */ jsx43(Label, { label }),
3483
+ /* @__PURE__ */ jsxs28(View36, { style: [styles39.inputRow, disabled && { opacity: 0.4 }], children: [
3484
+ /* @__PURE__ */ jsx43(
3485
+ Pressable21,
3486
+ {
3487
+ accessibilityRole: "button",
3488
+ accessibilityLabel: "Decrease",
3489
+ accessibilityState: { disabled: disabled || !canDecrease },
3490
+ disabled: disabled || !canDecrease,
3491
+ onPress: () => update(currentValue - step),
3492
+ style: ({ pressed }) => [
3493
+ styles39.stepper,
3494
+ styles39.stepperStart,
3495
+ {
3496
+ borderColor,
3497
+ backgroundColor: colors2.colorBgSubtle
3498
+ },
3499
+ pressed && { opacity: 0.7 },
3500
+ (disabled || !canDecrease) && { opacity: 0.4 }
3501
+ ],
3502
+ children: /* @__PURE__ */ jsx43(
3503
+ Text31,
3504
+ {
3505
+ style: [styles39.stepperText, { color: colors2.colorOnBg }],
3506
+ "aria-hidden": true,
3507
+ children: "\u2212"
3508
+ }
3509
+ )
3510
+ }
3511
+ ),
3512
+ /* @__PURE__ */ jsx43(
3513
+ TextInput4,
3514
+ {
3515
+ accessibilityLabel: label,
3516
+ accessibilityState: { disabled },
3517
+ accessibilityValue: {
3518
+ min,
3519
+ max,
3520
+ now: currentValue,
3521
+ text: String(currentValue)
3522
+ },
3523
+ keyboardType: "numeric",
3524
+ value: String(currentValue),
3525
+ editable: !disabled,
3526
+ onChangeText: (text) => {
3527
+ const parsed = parseFloat(text);
3528
+ const safe = isNaN(parsed) ? 0 : parsed;
3529
+ update(safe);
3530
+ },
3531
+ style: [
3532
+ styles39.input,
3533
+ {
3534
+ borderColor,
3535
+ color: colors2.colorOnBg,
3536
+ backgroundColor: colors2.colorBg
3537
+ }
3538
+ ]
3539
+ }
3540
+ ),
3541
+ /* @__PURE__ */ jsx43(
3542
+ Pressable21,
3543
+ {
3544
+ accessibilityRole: "button",
3545
+ accessibilityLabel: "Increase",
3546
+ accessibilityState: { disabled: disabled || !canIncrease },
3547
+ disabled: disabled || !canIncrease,
3548
+ onPress: () => update(currentValue + step),
3549
+ style: ({ pressed }) => [
3550
+ styles39.stepper,
3551
+ styles39.stepperEnd,
3552
+ {
3553
+ borderColor,
3554
+ backgroundColor: colors2.colorBgSubtle
3555
+ },
3556
+ pressed && { opacity: 0.7 },
3557
+ (disabled || !canIncrease) && { opacity: 0.4 }
3558
+ ],
3559
+ children: /* @__PURE__ */ jsx43(
3560
+ Text31,
3561
+ {
3562
+ style: [styles39.stepperText, { color: colors2.colorOnBg }],
3563
+ "aria-hidden": true,
3564
+ children: "+"
3565
+ }
3566
+ )
3567
+ }
3568
+ )
3569
+ ] }),
3570
+ /* @__PURE__ */ jsx43(Message, { type: "error", message: error }),
3571
+ /* @__PURE__ */ jsx43(Message, { type: "hint", message: hint })
3572
+ ] });
3573
+ }
3574
+
3575
+ // src/components/interaction/Dialog/Dialog.native.tsx
3576
+ import {
3577
+ Modal as Modal2,
3578
+ View as View37,
3579
+ Pressable as Pressable22,
3580
+ Text as Text32,
3581
+ StyleSheet as StyleSheet40
3582
+ } from "react-native";
3583
+ import { jsx as jsx44, jsxs as jsxs29 } from "react/jsx-runtime";
3584
+ var styles40 = StyleSheet40.create({
3585
+ overlay: {
3586
+ flex: 1,
3587
+ justifyContent: "center",
3588
+ alignItems: "center",
3589
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
3590
+ padding: spacing.m
3591
+ },
3592
+ panel: {
3593
+ width: "100%",
3594
+ maxWidth: 480,
3595
+ borderRadius: border.radius.m,
3596
+ padding: spacing.l,
3597
+ paddingTop: spacing.xl,
3598
+ shadowColor: "#000",
3599
+ shadowOffset: { width: 0, height: 4 },
3600
+ shadowOpacity: 0.15,
3601
+ shadowRadius: 12,
3602
+ elevation: 8
3603
+ },
3604
+ header: {
3605
+ flexDirection: "row",
3606
+ justifyContent: "space-between",
3607
+ alignItems: "center",
3608
+ marginBottom: spacing.m
3609
+ },
3610
+ title: {
3611
+ fontFamily: font.family.body,
3612
+ fontSize: font.size.heading3,
3613
+ fontWeight: font.weight.semibold,
3614
+ flex: 1
3615
+ },
3616
+ closeButton: {
3617
+ position: "absolute",
3618
+ top: spacing.s,
3619
+ end: spacing.s,
3620
+ width: 44,
3621
+ height: 44,
3622
+ alignItems: "center",
3623
+ justifyContent: "center",
3624
+ zIndex: 1
3625
+ },
3626
+ closeText: {
3627
+ fontFamily: font.family.body,
3628
+ fontSize: 20,
3629
+ lineHeight: 24
3630
+ }
3631
+ });
3632
+ function Dialog({
3633
+ isOpen = false,
3634
+ onClose,
3635
+ title,
3636
+ children,
3637
+ style
3638
+ }) {
3639
+ const { colors: colors2 } = useTheme();
3640
+ return /* @__PURE__ */ jsx44(
3641
+ Modal2,
3642
+ {
3643
+ visible: isOpen,
3644
+ transparent: true,
3645
+ animationType: "fade",
3646
+ onRequestClose: onClose,
3647
+ children: /* @__PURE__ */ jsx44(
3648
+ Pressable22,
3649
+ {
3650
+ style: styles40.overlay,
3651
+ onPress: onClose,
3652
+ accessibilityRole: "button",
3653
+ accessibilityLabel: "Close dialog",
3654
+ children: /* @__PURE__ */ jsxs29(
3655
+ Pressable22,
3656
+ {
3657
+ style: [styles40.panel, { backgroundColor: colors2.colorGreySubtle }, style],
3658
+ onPress: () => {
3659
+ },
3660
+ accessibilityRole: "none",
3661
+ children: [
3662
+ /* @__PURE__ */ jsx44(
3663
+ Pressable22,
3664
+ {
3665
+ style: styles40.closeButton,
3666
+ onPress: onClose,
3667
+ accessibilityRole: "button",
3668
+ accessibilityLabel: "Close dialog",
3669
+ hitSlop: 8,
3670
+ children: /* @__PURE__ */ jsx44(
3671
+ Text32,
3672
+ {
3673
+ style: [styles40.closeText, { color: colors2.colorOnBgSubtle }],
3674
+ "aria-hidden": true,
3675
+ children: "\u2715"
3676
+ }
3677
+ )
3678
+ }
3679
+ ),
3680
+ !!title && /* @__PURE__ */ jsx44(View37, { style: styles40.header, children: /* @__PURE__ */ jsx44(Text32, { style: [styles40.title, { color: colors2.colorOnGreySubtle }], children: title }) }),
3681
+ children
3682
+ ]
3683
+ }
3684
+ )
3685
+ }
3686
+ )
3687
+ }
3688
+ );
3689
+ }
3690
+
3691
+ // src/components/interaction/Drawer/Drawer.native.tsx
3692
+ import { useEffect as useEffect2, useRef as useRef4 } from "react";
3693
+ import {
3694
+ Modal as Modal3,
3695
+ View as View38,
3696
+ Pressable as Pressable23,
3697
+ Text as Text33,
3698
+ Animated as Animated3,
3699
+ StyleSheet as StyleSheet41,
3700
+ Dimensions as Dimensions2
3701
+ } from "react-native";
3702
+ import { jsx as jsx45, jsxs as jsxs30 } from "react/jsx-runtime";
3703
+ var styles41 = StyleSheet41.create({
3704
+ overlay: {
3705
+ flex: 1,
3706
+ justifyContent: "flex-end"
3707
+ },
3708
+ panel: {
3709
+ maxHeight: "90%",
3710
+ borderTopStartRadius: border.radius.m,
3711
+ borderTopEndRadius: border.radius.m,
3712
+ paddingTop: spacing.m,
3713
+ paddingHorizontal: spacing.m,
3714
+ paddingBottom: spacing.m,
3715
+ shadowColor: "#000",
3716
+ shadowOffset: { width: 0, height: -4 },
3717
+ shadowOpacity: 0.15,
3718
+ shadowRadius: 16,
3719
+ elevation: 16
3720
+ },
3721
+ header: {
3722
+ flexDirection: "row",
3723
+ justifyContent: "space-between",
3724
+ alignItems: "center",
3725
+ paddingBottom: spacing.m,
3726
+ borderBottomWidth: 1,
3727
+ marginBottom: spacing.m
3728
+ },
3729
+ title: {
3730
+ fontFamily: font.family.body,
3731
+ fontSize: font.size.heading3,
3732
+ fontWeight: font.weight.semibold,
3733
+ flex: 1
3734
+ },
3735
+ closeButton: {
3736
+ width: 44,
3737
+ height: 44,
3738
+ alignItems: "center",
3739
+ justifyContent: "center"
3740
+ },
3741
+ closeText: {
3742
+ fontFamily: font.family.body,
3743
+ fontSize: 20,
3744
+ lineHeight: 24
3745
+ },
3746
+ body: {
3747
+ flex: 1
3748
+ }
3749
+ });
3750
+ function Drawer({
3751
+ isOpen,
3752
+ onClose,
3753
+ title,
3754
+ children,
3755
+ style
3756
+ }) {
3757
+ const { colors: colors2 } = useTheme();
3758
+ const screenHeight = Dimensions2.get("window").height;
3759
+ const slideAnim = useRef4(new Animated3.Value(screenHeight)).current;
3760
+ const backdropAnim = useRef4(new Animated3.Value(0)).current;
3761
+ useEffect2(() => {
3762
+ if (isOpen) {
3763
+ Animated3.parallel([
3764
+ Animated3.timing(slideAnim, {
3765
+ toValue: 0,
3766
+ duration: 250,
3767
+ useNativeDriver: true
3768
+ }),
3769
+ Animated3.timing(backdropAnim, {
3770
+ toValue: 1,
3771
+ duration: 250,
3772
+ useNativeDriver: true
3773
+ })
3774
+ ]).start();
3775
+ } else {
3776
+ Animated3.parallel([
3777
+ Animated3.timing(slideAnim, {
3778
+ toValue: screenHeight,
3779
+ duration: 200,
3780
+ useNativeDriver: true
3781
+ }),
3782
+ Animated3.timing(backdropAnim, {
3783
+ toValue: 0,
3784
+ duration: 200,
3785
+ useNativeDriver: true
3786
+ })
3787
+ ]).start();
3788
+ }
3789
+ }, [isOpen, slideAnim, backdropAnim, screenHeight]);
3790
+ return /* @__PURE__ */ jsx45(
3791
+ Modal3,
3792
+ {
3793
+ visible: isOpen,
3794
+ transparent: true,
3795
+ animationType: "none",
3796
+ onRequestClose: onClose,
3797
+ children: /* @__PURE__ */ jsxs30(View38, { style: styles41.overlay, children: [
3798
+ /* @__PURE__ */ jsx45(
3799
+ Animated3.View,
3800
+ {
3801
+ style: [
3802
+ StyleSheet41.absoluteFill,
3803
+ { backgroundColor: "rgba(0, 0, 0, 0.5)", opacity: backdropAnim }
3804
+ ],
3805
+ children: /* @__PURE__ */ jsx45(
3806
+ Pressable23,
3807
+ {
3808
+ style: StyleSheet41.absoluteFill,
3809
+ onPress: onClose,
3810
+ accessibilityRole: "button",
3811
+ accessibilityLabel: "Close drawer"
3812
+ }
3813
+ )
3814
+ }
3815
+ ),
3816
+ /* @__PURE__ */ jsxs30(
3817
+ Animated3.View,
3818
+ {
3819
+ style: [
3820
+ styles41.panel,
3821
+ {
3822
+ backgroundColor: colors2.colorBg,
3823
+ transform: [{ translateY: slideAnim }]
3824
+ },
3825
+ style
3826
+ ],
3827
+ accessibilityRole: "none",
3828
+ children: [
3829
+ /* @__PURE__ */ jsxs30(
3830
+ View38,
3831
+ {
3832
+ style: [styles41.header, { borderBottomColor: colors2.colorBgSubtle }],
3833
+ children: [
3834
+ !!title && /* @__PURE__ */ jsx45(Text33, { style: [styles41.title, { color: colors2.colorOnBg }], children: title }),
3835
+ /* @__PURE__ */ jsx45(
3836
+ Pressable23,
3837
+ {
3838
+ style: styles41.closeButton,
3839
+ onPress: onClose,
3840
+ accessibilityRole: "button",
3841
+ accessibilityLabel: "Close drawer",
3842
+ hitSlop: 8,
3843
+ children: /* @__PURE__ */ jsx45(
3844
+ Text33,
3845
+ {
3846
+ style: [styles41.closeText, { color: colors2.colorOnBgSubtle }],
3847
+ "aria-hidden": true,
3848
+ children: "\u2715"
3849
+ }
3850
+ )
3851
+ }
3852
+ )
3853
+ ]
3854
+ }
3855
+ ),
3856
+ /* @__PURE__ */ jsx45(View38, { style: styles41.body, children })
3857
+ ]
3858
+ }
3859
+ )
3860
+ ] })
3861
+ }
3862
+ );
3863
+ }
3864
+
3865
+ // src/components/interaction/Toast/Toast.native.tsx
3866
+ import {
3867
+ useState as useState13,
3868
+ useEffect as useEffect3,
3869
+ useRef as useRef5,
3870
+ useCallback as useCallback3,
3871
+ useMemo as useMemo3,
3872
+ createContext as createContext2,
3873
+ useContext as useContext2
3874
+ } from "react";
3875
+ import {
3876
+ View as View39,
3877
+ Text as Text34,
3878
+ Pressable as Pressable24,
3879
+ Animated as Animated4,
3880
+ StyleSheet as StyleSheet42
3881
+ } from "react-native";
3882
+ import { jsx as jsx46, jsxs as jsxs31 } from "react/jsx-runtime";
3883
+ var ToastContext = createContext2(void 0);
3884
+ var styles42 = StyleSheet42.create({
3885
+ container: {
3886
+ position: "absolute",
3887
+ top: 0,
3888
+ start: 0,
3889
+ end: 0,
3890
+ paddingTop: spacing.xxxl,
3891
+ paddingHorizontal: spacing.m,
3892
+ zIndex: 9999,
3893
+ pointerEvents: "box-none"
3894
+ },
3895
+ toast: {
3896
+ flexDirection: "row",
3897
+ alignItems: "center",
3898
+ justifyContent: "space-between",
3899
+ paddingVertical: spacing.s,
3900
+ paddingHorizontal: spacing.m,
3901
+ borderRadius: border.radius.s,
3902
+ marginBottom: spacing.xs,
3903
+ minHeight: 48
3904
+ },
3905
+ message: {
3906
+ fontFamily: font.family.body,
3907
+ fontSize: font.size.body,
3908
+ fontWeight: font.weight.semibold,
3909
+ flex: 1
3910
+ },
3911
+ closeButton: {
3912
+ width: 44,
3913
+ height: 44,
3914
+ alignItems: "center",
3915
+ justifyContent: "center",
3916
+ marginStart: spacing.xs
3917
+ },
3918
+ closeText: {
3919
+ fontFamily: font.family.body,
3920
+ fontSize: 16,
3921
+ lineHeight: 20
3922
+ }
3923
+ });
3924
+ function ToastItem({
3925
+ toast,
3926
+ onRemove
3927
+ }) {
3928
+ const { colors: colors2 } = useTheme();
3929
+ const slideAnim = useRef5(new Animated4.Value(-100)).current;
3930
+ const opacityAnim = useRef5(new Animated4.Value(0)).current;
3931
+ const variantColors = useMemo3(
3932
+ () => ({
3933
+ success: { bg: colors2.colorSuccess, text: colors2.colorOnSuccess },
3934
+ error: { bg: colors2.colorError, text: colors2.colorOnError },
3935
+ info: { bg: colors2.colorBgSubtle, text: colors2.colorOnBgSubtle }
3936
+ }),
3937
+ [colors2]
3938
+ );
3939
+ useEffect3(() => {
3940
+ Animated4.parallel([
3941
+ Animated4.timing(slideAnim, {
3942
+ toValue: 0,
3943
+ duration: 200,
3944
+ useNativeDriver: true
3945
+ }),
3946
+ Animated4.timing(opacityAnim, {
3947
+ toValue: 1,
3948
+ duration: 200,
3949
+ useNativeDriver: true
3950
+ })
3951
+ ]).start();
3952
+ }, [slideAnim, opacityAnim]);
3953
+ useEffect3(() => {
3954
+ const timer = setTimeout(onRemove, 5e3);
3955
+ return () => clearTimeout(timer);
3956
+ }, [onRemove]);
3957
+ const { bg, text } = variantColors[toast.variant];
3958
+ return /* @__PURE__ */ jsxs31(
3959
+ Animated4.View,
3960
+ {
3961
+ style: [
3962
+ styles42.toast,
3963
+ {
3964
+ backgroundColor: bg,
3965
+ transform: [{ translateY: slideAnim }],
3966
+ opacity: opacityAnim
3967
+ }
3968
+ ],
3969
+ accessibilityRole: "alert",
3970
+ accessibilityLiveRegion: "polite",
3971
+ children: [
3972
+ /* @__PURE__ */ jsx46(Text34, { style: [styles42.message, { color: text }], children: toast.message }),
3973
+ /* @__PURE__ */ jsx46(
3974
+ Pressable24,
3975
+ {
3976
+ style: styles42.closeButton,
3977
+ onPress: onRemove,
3978
+ accessibilityRole: "button",
3979
+ accessibilityLabel: "Dismiss",
3980
+ hitSlop: 8,
3981
+ children: /* @__PURE__ */ jsx46(Text34, { style: [styles42.closeText, { color: text }], "aria-hidden": true, children: "\u2715" })
3982
+ }
3983
+ )
3984
+ ]
3985
+ }
3986
+ );
3987
+ }
3988
+ function ToastProvider({
3989
+ children,
3990
+ style
3991
+ }) {
3992
+ const [toasts, setToasts] = useState13([]);
3993
+ const showToast = useCallback3((message, variant) => {
3994
+ const id = Math.random().toString(36).substring(2, 9);
3995
+ setToasts((prev) => [...prev, { id, message, variant }]);
3996
+ }, []);
3997
+ const removeToast = useCallback3((id) => {
3998
+ setToasts((prev) => prev.filter((t) => t.id !== id));
3999
+ }, []);
4000
+ const value = useMemo3(() => ({ showToast }), [showToast]);
4001
+ return /* @__PURE__ */ jsx46(ToastContext.Provider, { value, children: /* @__PURE__ */ jsxs31(View39, { style: [{ flex: 1 }, style], children: [
4002
+ children,
4003
+ toasts.length > 0 && /* @__PURE__ */ jsx46(
4004
+ View39,
4005
+ {
4006
+ style: styles42.container,
4007
+ accessibilityRole: "summary",
4008
+ accessibilityLabel: "Notifications",
4009
+ children: toasts.map((toast) => /* @__PURE__ */ jsx46(
4010
+ ToastItem,
4011
+ {
4012
+ toast,
4013
+ onRemove: () => removeToast(toast.id)
4014
+ },
4015
+ toast.id
4016
+ ))
4017
+ }
4018
+ )
4019
+ ] }) });
4020
+ }
4021
+ function useToast() {
4022
+ const context = useContext2(ToastContext);
4023
+ if (!context) {
4024
+ throw new Error("useToast must be used within a ToastProvider");
4025
+ }
4026
+ return context;
4027
+ }
4028
+
4029
+ // src/components/interaction/DropdownMenu/DropdownMenu.native.tsx
4030
+ import React, { useState as useState14, useEffect as useEffect4, useRef as useRef6 } from "react";
4031
+ import {
4032
+ Modal as Modal4,
4033
+ View as View40,
4034
+ Pressable as Pressable25,
4035
+ Text as Text35,
4036
+ FlatList as FlatList2,
4037
+ Animated as Animated5,
4038
+ StyleSheet as StyleSheet43,
4039
+ Dimensions as Dimensions3,
4040
+ SafeAreaView as SafeAreaView2
4041
+ } from "react-native";
4042
+ import { Fragment as Fragment2, jsx as jsx47, jsxs as jsxs32 } from "react/jsx-runtime";
4043
+ var styles43 = StyleSheet43.create({
4044
+ overlay: {
4045
+ flex: 1,
4046
+ justifyContent: "flex-end"
4047
+ },
4048
+ sheet: {
4049
+ maxHeight: "60%",
4050
+ borderTopStartRadius: border.radius.m,
4051
+ borderTopEndRadius: border.radius.m,
4052
+ paddingTop: spacing.m,
4053
+ paddingBottom: spacing.xxxl
4054
+ },
4055
+ sheetHeader: {
4056
+ flexDirection: "row",
4057
+ justifyContent: "space-between",
4058
+ alignItems: "center",
4059
+ paddingHorizontal: spacing.m,
4060
+ paddingBottom: spacing.s,
4061
+ borderBottomWidth: 1,
4062
+ marginBottom: spacing.xxs
4063
+ },
4064
+ sheetTitle: {
4065
+ fontFamily: font.family.body,
4066
+ fontSize: font.size.heading3,
4067
+ fontWeight: font.weight.semibold
4068
+ },
4069
+ closeText: {
4070
+ fontFamily: font.family.body,
4071
+ fontSize: font.size.body,
4072
+ fontWeight: font.weight.semibold
4073
+ },
4074
+ separator: {
4075
+ height: 1,
4076
+ marginHorizontal: spacing.m,
4077
+ marginVertical: spacing.xxs
4078
+ },
4079
+ item: {
4080
+ flexDirection: "row",
4081
+ alignItems: "center",
4082
+ paddingHorizontal: spacing.m,
4083
+ paddingVertical: spacing.s,
4084
+ minHeight: 48,
4085
+ gap: spacing.s
4086
+ },
4087
+ itemText: {
4088
+ fontFamily: font.family.body,
4089
+ fontSize: font.size.body,
4090
+ lineHeight: lineHeight.body
4091
+ }
4092
+ });
4093
+ function DropdownMenu({
4094
+ trigger,
4095
+ items,
4096
+ title = "Menu",
4097
+ style
4098
+ }) {
4099
+ const { colors: colors2 } = useTheme();
4100
+ const [open, setOpen] = useState14(false);
4101
+ const screenHeight = Dimensions3.get("window").height;
4102
+ const slideAnim = useRef6(new Animated5.Value(screenHeight)).current;
4103
+ const backdropAnim = useRef6(new Animated5.Value(0)).current;
4104
+ useEffect4(() => {
4105
+ if (open) {
4106
+ Animated5.parallel([
4107
+ Animated5.timing(slideAnim, {
4108
+ toValue: 0,
4109
+ duration: 250,
4110
+ useNativeDriver: true
4111
+ }),
4112
+ Animated5.timing(backdropAnim, {
4113
+ toValue: 1,
4114
+ duration: 250,
4115
+ useNativeDriver: true
4116
+ })
4117
+ ]).start();
4118
+ } else {
4119
+ Animated5.parallel([
4120
+ Animated5.timing(slideAnim, {
4121
+ toValue: screenHeight,
4122
+ duration: 200,
4123
+ useNativeDriver: true
4124
+ }),
4125
+ Animated5.timing(backdropAnim, {
4126
+ toValue: 0,
4127
+ duration: 200,
4128
+ useNativeDriver: true
4129
+ })
4130
+ ]).start();
4131
+ }
4132
+ }, [open, slideAnim, backdropAnim, screenHeight]);
4133
+ const handleItemPress = (item) => {
4134
+ item.onPress?.();
4135
+ setOpen(false);
4136
+ };
4137
+ return /* @__PURE__ */ jsxs32(View40, { style, children: [
4138
+ React.cloneElement(trigger, {
4139
+ onPress: () => setOpen(true),
4140
+ accessibilityRole: "button",
4141
+ accessibilityLabel: title
4142
+ }),
4143
+ /* @__PURE__ */ jsx47(
4144
+ Modal4,
4145
+ {
4146
+ visible: open,
4147
+ transparent: true,
4148
+ animationType: "none",
4149
+ onRequestClose: () => setOpen(false),
4150
+ children: /* @__PURE__ */ jsxs32(View40, { style: styles43.overlay, children: [
4151
+ /* @__PURE__ */ jsx47(
4152
+ Animated5.View,
4153
+ {
4154
+ style: [
4155
+ StyleSheet43.absoluteFill,
4156
+ { backgroundColor: "rgba(0, 0, 0, 0.5)", opacity: backdropAnim }
4157
+ ],
4158
+ children: /* @__PURE__ */ jsx47(
4159
+ Pressable25,
4160
+ {
4161
+ style: StyleSheet43.absoluteFill,
4162
+ onPress: () => setOpen(false),
4163
+ accessibilityRole: "button",
4164
+ accessibilityLabel: "Close menu"
4165
+ }
4166
+ )
4167
+ }
4168
+ ),
4169
+ /* @__PURE__ */ jsx47(
4170
+ Animated5.View,
4171
+ {
4172
+ style: [
4173
+ styles43.sheet,
4174
+ {
4175
+ backgroundColor: colors2.colorBg,
4176
+ transform: [{ translateY: slideAnim }]
4177
+ }
4178
+ ],
4179
+ children: /* @__PURE__ */ jsx47(
4180
+ Pressable25,
4181
+ {
4182
+ onPress: () => {
4183
+ },
4184
+ children: /* @__PURE__ */ jsxs32(SafeAreaView2, { children: [
4185
+ /* @__PURE__ */ jsxs32(
4186
+ View40,
4187
+ {
4188
+ style: [
4189
+ styles43.sheetHeader,
4190
+ { borderBottomColor: colors2.colorBgSubtle }
4191
+ ],
4192
+ children: [
4193
+ /* @__PURE__ */ jsx47(Text35, { style: [styles43.sheetTitle, { color: colors2.colorOnBg }], children: title }),
4194
+ /* @__PURE__ */ jsx47(
4195
+ Pressable25,
4196
+ {
4197
+ accessibilityRole: "button",
4198
+ accessibilityLabel: "Close",
4199
+ onPress: () => setOpen(false),
4200
+ hitSlop: 8,
4201
+ children: /* @__PURE__ */ jsx47(
4202
+ Text35,
4203
+ {
4204
+ style: [
4205
+ styles43.closeText,
4206
+ { color: colors2.colorInteractive }
4207
+ ],
4208
+ children: "Done"
4209
+ }
4210
+ )
4211
+ }
4212
+ )
4213
+ ]
4214
+ }
4215
+ ),
4216
+ /* @__PURE__ */ jsx47(
4217
+ FlatList2,
4218
+ {
4219
+ data: items,
4220
+ keyExtractor: (item) => item.id,
4221
+ renderItem: ({ item }) => /* @__PURE__ */ jsxs32(Fragment2, { children: [
4222
+ item.separator && /* @__PURE__ */ jsx47(
4223
+ View40,
4224
+ {
4225
+ style: [
4226
+ styles43.separator,
4227
+ { backgroundColor: colors2.colorBgSubtle }
4228
+ ],
4229
+ accessibilityRole: "none"
4230
+ }
4231
+ ),
4232
+ /* @__PURE__ */ jsxs32(
4233
+ Pressable25,
4234
+ {
4235
+ accessibilityRole: "menuitem",
4236
+ accessibilityLabel: item.label,
4237
+ accessibilityState: { disabled: item.disabled },
4238
+ disabled: item.disabled,
4239
+ onPress: () => handleItemPress(item),
4240
+ style: ({ pressed }) => [
4241
+ styles43.item,
4242
+ pressed && { backgroundColor: colors2.colorBgSubtle },
4243
+ item.disabled && { opacity: 0.4 }
4244
+ ],
4245
+ children: [
4246
+ !!item.icon && /* @__PURE__ */ jsx47(
4247
+ View40,
4248
+ {
4249
+ importantForAccessibility: "no-hide-descendants",
4250
+ accessibilityElementsHidden: true,
4251
+ children: item.icon
4252
+ }
4253
+ ),
4254
+ /* @__PURE__ */ jsx47(
4255
+ Text35,
4256
+ {
4257
+ style: [
4258
+ styles43.itemText,
4259
+ { color: colors2.colorOnBg }
4260
+ ],
4261
+ children: item.label
4262
+ }
4263
+ )
4264
+ ]
4265
+ }
4266
+ )
4267
+ ] })
4268
+ }
4269
+ )
4270
+ ] })
4271
+ }
4272
+ )
4273
+ }
4274
+ )
4275
+ ] })
4276
+ }
4277
+ )
4278
+ ] });
4279
+ }
4280
+
4281
+ // src/components/interaction/Popover/Popover.native.tsx
4282
+ import React2, { useState as useState15 } from "react";
4283
+ import {
4284
+ Modal as Modal5,
4285
+ View as View41,
4286
+ Pressable as Pressable26,
4287
+ StyleSheet as StyleSheet44
4288
+ } from "react-native";
4289
+ import { jsx as jsx48, jsxs as jsxs33 } from "react/jsx-runtime";
4290
+ var styles44 = StyleSheet44.create({
4291
+ wrapper: {
4292
+ alignSelf: "flex-start"
4293
+ },
4294
+ overlay: {
4295
+ flex: 1,
4296
+ justifyContent: "center",
4297
+ alignItems: "center",
4298
+ backgroundColor: "rgba(0, 0, 0, 0.25)",
4299
+ padding: spacing.m
4300
+ },
4301
+ panel: {
4302
+ width: "100%",
4303
+ maxWidth: 360,
4304
+ borderRadius: border.radius.s,
4305
+ padding: spacing.m,
4306
+ shadowColor: "#000",
4307
+ shadowOffset: { width: 0, height: 2 },
4308
+ shadowOpacity: 0.15,
4309
+ shadowRadius: 8,
4310
+ elevation: 4
4311
+ }
4312
+ });
4313
+ function Popover({
4314
+ children,
4315
+ content,
4316
+ accessibilityLabel,
4317
+ style
4318
+ }) {
4319
+ const { colors: colors2 } = useTheme();
4320
+ const [isOpen, setIsOpen] = useState15(false);
4321
+ return /* @__PURE__ */ jsxs33(View41, { style: [styles44.wrapper, style], children: [
4322
+ React2.cloneElement(children, {
4323
+ onPress: () => setIsOpen(true),
4324
+ accessibilityRole: "button",
4325
+ accessibilityLabel: accessibilityLabel ?? "Open popover"
4326
+ }),
4327
+ /* @__PURE__ */ jsx48(
4328
+ Modal5,
4329
+ {
4330
+ visible: isOpen,
4331
+ transparent: true,
4332
+ animationType: "fade",
4333
+ onRequestClose: () => setIsOpen(false),
4334
+ children: /* @__PURE__ */ jsx48(
4335
+ Pressable26,
4336
+ {
4337
+ style: styles44.overlay,
4338
+ onPress: () => setIsOpen(false),
4339
+ accessibilityRole: "button",
4340
+ accessibilityLabel: "Close popover",
4341
+ children: /* @__PURE__ */ jsx48(
4342
+ Pressable26,
4343
+ {
4344
+ style: [styles44.panel, { backgroundColor: colors2.colorBg }],
4345
+ onPress: () => {
4346
+ },
4347
+ accessibilityRole: "none",
4348
+ accessibilityLabel,
4349
+ children: content
4350
+ }
4351
+ )
4352
+ }
4353
+ )
4354
+ }
4355
+ )
938
4356
  ] });
939
4357
  }
940
4358
  export {
4359
+ Accordion,
941
4360
  Alert,
942
4361
  Avatar,
943
4362
  Badge,
4363
+ Breadcrumb,
944
4364
  Button,
945
4365
  ButtonGroup,
4366
+ Calendar,
946
4367
  Card,
4368
+ Carousel,
947
4369
  Checkbox,
4370
+ CheckboxGroup,
4371
+ Collapsible,
4372
+ Combobox,
4373
+ DescriptionList,
4374
+ Dialog,
4375
+ Drawer,
4376
+ DropdownMenu,
4377
+ FileInput,
4378
+ FormInput,
948
4379
  IconWrapper,
949
4380
  Label,
4381
+ Link,
950
4382
  Loading,
951
4383
  Message,
952
4384
  NotificationBanner,
4385
+ NumberInput,
4386
+ Pagination,
4387
+ Popover,
953
4388
  Progress,
4389
+ ProgressCircle,
954
4390
  Radio,
4391
+ RadioGroup,
4392
+ Rating,
955
4393
  SectionHeader,
4394
+ SegmentedControl,
4395
+ Select,
956
4396
  Separator,
957
4397
  Skeleton,
4398
+ Slider,
958
4399
  Switch,
4400
+ Table,
4401
+ Tabs,
4402
+ Textarea,
959
4403
  ThemeProvider,
4404
+ ToastProvider,
4405
+ Tooltip,
960
4406
  Typography,
961
4407
  animation,
962
4408
  border,
@@ -965,5 +4411,6 @@ export {
965
4411
  lineHeight,
966
4412
  spacing,
967
4413
  useTheme,
4414
+ useToast,
968
4415
  zIndex
969
4416
  };