@hzblj/kara-components 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (291) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/README.md +31 -3
  3. package/lib/module/atoms/activity-indicator/activity-indicator.android.js +42 -0
  4. package/lib/module/atoms/activity-indicator/activity-indicator.android.js.map +1 -0
  5. package/lib/module/atoms/activity-indicator/activity-indicator.ios.js +19 -0
  6. package/lib/module/atoms/activity-indicator/activity-indicator.ios.js.map +1 -0
  7. package/lib/module/atoms/activity-indicator/activity-indicator.types.js +4 -0
  8. package/lib/module/atoms/activity-indicator/activity-indicator.types.js.map +1 -0
  9. package/lib/module/atoms/activity-indicator/index.js +2 -1
  10. package/lib/module/atoms/activity-indicator/index.js.map +1 -1
  11. package/lib/module/atoms/avatar/avatar.js +2 -4
  12. package/lib/module/atoms/avatar/avatar.js.map +1 -1
  13. package/lib/module/atoms/blur-view/blur-view.android.js +100 -0
  14. package/lib/module/atoms/blur-view/blur-view.android.js.map +1 -0
  15. package/lib/module/atoms/blur-view/blur-view.ios.js +43 -0
  16. package/lib/module/atoms/blur-view/blur-view.ios.js.map +1 -0
  17. package/lib/module/atoms/blur-view/blur-view.types.js +4 -0
  18. package/lib/module/atoms/blur-view/blur-view.types.js.map +1 -0
  19. package/lib/module/atoms/blur-view/index.js +5 -0
  20. package/lib/module/atoms/blur-view/index.js.map +1 -0
  21. package/lib/module/atoms/checkbox/checkbox.android.js +7 -3
  22. package/lib/module/atoms/checkbox/checkbox.android.js.map +1 -1
  23. package/lib/module/atoms/date-picker/date-picker.ios.js +32 -11
  24. package/lib/module/atoms/date-picker/date-picker.ios.js.map +1 -1
  25. package/lib/module/atoms/glass-view/glass-view.android.js +36 -5
  26. package/lib/module/atoms/glass-view/glass-view.android.js.map +1 -1
  27. package/lib/module/atoms/image/image.js +13 -6
  28. package/lib/module/atoms/image/image.js.map +1 -1
  29. package/lib/module/atoms/image/image.types.js +4 -0
  30. package/lib/module/atoms/image/image.types.js.map +1 -0
  31. package/lib/module/atoms/image/index.js +1 -0
  32. package/lib/module/atoms/image/index.js.map +1 -1
  33. package/lib/module/atoms/index.js +1 -1
  34. package/lib/module/atoms/index.js.map +1 -1
  35. package/lib/module/atoms/island/island.android.js +6 -2
  36. package/lib/module/atoms/island/island.android.js.map +1 -1
  37. package/lib/module/atoms/island/island.ios.js +5 -2
  38. package/lib/module/atoms/island/island.ios.js.map +1 -1
  39. package/lib/module/atoms/pressable/pressable.js +38 -6
  40. package/lib/module/atoms/pressable/pressable.js.map +1 -1
  41. package/lib/module/atoms/rn-flat-list/rn-flat-list.js +10 -9
  42. package/lib/module/atoms/rn-flat-list/rn-flat-list.js.map +1 -1
  43. package/lib/module/atoms/rn-section-list/rn-section-list.js +5 -8
  44. package/lib/module/atoms/rn-section-list/rn-section-list.js.map +1 -1
  45. package/lib/module/atoms/rn-text/rn-text.js +5 -2
  46. package/lib/module/atoms/rn-text/rn-text.js.map +1 -1
  47. package/lib/module/atoms/segmented-control/index.js +1 -1
  48. package/lib/module/atoms/segmented-control/index.js.map +1 -1
  49. package/lib/module/atoms/segmented-control/segmented-control.android.js +74 -0
  50. package/lib/module/atoms/segmented-control/segmented-control.android.js.map +1 -0
  51. package/lib/module/atoms/segmented-control/segmented-control.ios.js +44 -0
  52. package/lib/module/atoms/segmented-control/segmented-control.ios.js.map +1 -0
  53. package/lib/module/atoms/skeleton/skeleton.js +5 -5
  54. package/lib/module/atoms/skeleton/skeleton.js.map +1 -1
  55. package/lib/module/atoms/switch/switch.android.js +4 -1
  56. package/lib/module/atoms/switch/switch.android.js.map +1 -1
  57. package/lib/module/atoms/text/text.android.js +5 -2
  58. package/lib/module/atoms/text/text.android.js.map +1 -1
  59. package/lib/module/atoms/text/text.ios.js +14 -3
  60. package/lib/module/atoms/text/text.ios.js.map +1 -1
  61. package/lib/module/molecules/collapsible/collapsible.android.js +37 -7
  62. package/lib/module/molecules/collapsible/collapsible.android.js.map +1 -1
  63. package/lib/module/molecules/navigation-bar/navigation-bar.android.js +2 -8
  64. package/lib/module/molecules/navigation-bar/navigation-bar.android.js.map +1 -1
  65. package/lib/module/molecules/pager/pager.android.js +5 -4
  66. package/lib/module/molecules/pager/pager.android.js.map +1 -1
  67. package/lib/module/molecules/scroll-edge-container/scroll-edge-container.android.js +114 -11
  68. package/lib/module/molecules/scroll-edge-container/scroll-edge-container.android.js.map +1 -1
  69. package/lib/module/molecules/search-bar/search-bar.js +15 -2
  70. package/lib/module/molecules/search-bar/search-bar.js.map +1 -1
  71. package/lib/module/molecules/stepper/stepper.ios.js +45 -8
  72. package/lib/module/molecules/stepper/stepper.ios.js.map +1 -1
  73. package/lib/module/molecules/tooltip/tooltip.android.js +16 -5
  74. package/lib/module/molecules/tooltip/tooltip.android.js.map +1 -1
  75. package/lib/module/organisms/action-sheet/action-sheet.android.js +41 -20
  76. package/lib/module/organisms/action-sheet/action-sheet.android.js.map +1 -1
  77. package/lib/module/organisms/action-sheet/action-sheet.ios.js +24 -8
  78. package/lib/module/organisms/action-sheet/action-sheet.ios.js.map +1 -1
  79. package/lib/module/organisms/alert/alert.ios.js +15 -2
  80. package/lib/module/organisms/alert/alert.ios.js.map +1 -1
  81. package/lib/module/organisms/form/form.android.js +22 -9
  82. package/lib/module/organisms/form/form.android.js.map +1 -1
  83. package/lib/module/organisms/swipe-actions/swipe-actions.android.js +125 -11
  84. package/lib/module/organisms/swipe-actions/swipe-actions.android.js.map +1 -1
  85. package/lib/module/organisms/swipe-actions/swipe-actions.ios.js +46 -18
  86. package/lib/module/organisms/swipe-actions/swipe-actions.ios.js.map +1 -1
  87. package/lib/module/ripple-clip.js +9 -1
  88. package/lib/module/ripple-clip.js.map +1 -1
  89. package/lib/module/templates/screen/screen.android.js +31 -10
  90. package/lib/module/templates/screen/screen.android.js.map +1 -1
  91. package/lib/typescript/atoms/activity-indicator/activity-indicator.d.ts +1 -3
  92. package/lib/typescript/atoms/activity-indicator/activity-indicator.ios.d.ts +3 -0
  93. package/lib/typescript/atoms/activity-indicator/activity-indicator.types.d.ts +17 -0
  94. package/lib/typescript/atoms/activity-indicator/index.d.ts +1 -0
  95. package/lib/typescript/atoms/avatar/avatar.types.d.ts +5 -0
  96. package/lib/typescript/atoms/badge/badge.types.d.ts +3 -0
  97. package/lib/typescript/atoms/blur-view/blur-view.d.ts +1 -0
  98. package/lib/typescript/atoms/blur-view/blur-view.ios.d.ts +3 -0
  99. package/lib/typescript/atoms/blur-view/blur-view.types.d.ts +31 -0
  100. package/lib/typescript/atoms/blur-view/index.d.ts +2 -0
  101. package/lib/typescript/atoms/box/a-box.d.ts +1 -1
  102. package/lib/typescript/atoms/button/button.types.d.ts +12 -0
  103. package/lib/typescript/atoms/card/card.types.d.ts +6 -0
  104. package/lib/typescript/atoms/checkbox/checkbox.types.d.ts +5 -0
  105. package/lib/typescript/atoms/chip/chip.types.d.ts +5 -0
  106. package/lib/typescript/atoms/color-picker/color-picker.types.d.ts +4 -0
  107. package/lib/typescript/atoms/date-picker/date-picker.ios.d.ts +6 -1
  108. package/lib/typescript/atoms/date-picker/date-picker.types.d.ts +14 -0
  109. package/lib/typescript/atoms/divider/divider.types.d.ts +3 -0
  110. package/lib/typescript/atoms/fab/fab.types.d.ts +7 -0
  111. package/lib/typescript/atoms/glass-view/glass-view.types.d.ts +13 -5
  112. package/lib/typescript/atoms/h-stack/h-stack.types.d.ts +6 -0
  113. package/lib/typescript/atoms/icon/icon.types.d.ts +8 -0
  114. package/lib/typescript/atoms/icon-button/icon-button.types.d.ts +5 -0
  115. package/lib/typescript/atoms/image/image.d.ts +12 -4
  116. package/lib/typescript/atoms/image/image.types.d.ts +4 -0
  117. package/lib/typescript/atoms/image/index.d.ts +1 -0
  118. package/lib/typescript/atoms/index.d.ts +1 -1
  119. package/lib/typescript/atoms/island/island.types.d.ts +10 -2
  120. package/lib/typescript/atoms/list/list.types.d.ts +2 -0
  121. package/lib/typescript/atoms/picker/picker.types.d.ts +12 -0
  122. package/lib/typescript/atoms/pressable/pressable.types.d.ts +10 -0
  123. package/lib/typescript/atoms/progress/progress.types.d.ts +6 -0
  124. package/lib/typescript/atoms/rn-flat-list/rn-flat-list.d.ts +5 -8
  125. package/lib/typescript/atoms/rn-flat-list/rn-flat-list.types.d.ts +3 -1
  126. package/lib/typescript/atoms/rn-scroll-view/rn-scroll-view.types.d.ts +4 -0
  127. package/lib/typescript/atoms/rn-section-list/rn-section-list.d.ts +2 -8
  128. package/lib/typescript/atoms/rn-section-list/rn-section-list.types.d.ts +3 -1
  129. package/lib/typescript/atoms/rn-text/rn-text.types.d.ts +10 -1
  130. package/lib/typescript/atoms/rn-view/rn-view.types.d.ts +2 -0
  131. package/lib/typescript/atoms/scroll-view/scroll-view.types.d.ts +4 -0
  132. package/lib/typescript/atoms/segmented-control/segmented-control.d.ts +1 -6
  133. package/lib/typescript/atoms/segmented-control/segmented-control.ios.d.ts +7 -0
  134. package/lib/typescript/atoms/segmented-control/segmented-control.types.d.ts +13 -0
  135. package/lib/typescript/atoms/skeleton/skeleton.types.d.ts +11 -2
  136. package/lib/typescript/atoms/slider/slider.types.d.ts +7 -0
  137. package/lib/typescript/atoms/spacer/spacer.types.d.ts +3 -0
  138. package/lib/typescript/atoms/surface/surface.types.d.ts +7 -0
  139. package/lib/typescript/atoms/switch/switch.types.d.ts +8 -0
  140. package/lib/typescript/atoms/text/text.types.d.ts +18 -1
  141. package/lib/typescript/atoms/text-field/text-field.types.d.ts +12 -0
  142. package/lib/typescript/atoms/v-stack/v-stack.types.d.ts +9 -0
  143. package/lib/typescript/atoms/z-stack/z-stack.types.d.ts +8 -0
  144. package/lib/typescript/molecules/collapsible/collapsible.types.d.ts +8 -0
  145. package/lib/typescript/molecules/empty-state/empty-state.types.d.ts +5 -0
  146. package/lib/typescript/molecules/label/label.types.d.ts +6 -0
  147. package/lib/typescript/molecules/labeled-content/labeled-content.types.d.ts +6 -0
  148. package/lib/typescript/molecules/link/link.types.d.ts +6 -0
  149. package/lib/typescript/molecules/list-item/list-item.types.d.ts +9 -0
  150. package/lib/typescript/molecules/navigation-bar/navigation-bar.types.d.ts +8 -0
  151. package/lib/typescript/molecules/pager/pager.types.d.ts +2 -0
  152. package/lib/typescript/molecules/radio-group/radio-group.types.d.ts +10 -0
  153. package/lib/typescript/molecules/rn-list-item/rn-list-item.types.d.ts +1 -1
  154. package/lib/typescript/molecules/rn-tooltip/rn-tooltip.types.d.ts +11 -0
  155. package/lib/typescript/molecules/scroll-edge-container/scroll-edge-container.types.d.ts +7 -2
  156. package/lib/typescript/molecules/search-bar/search-bar.types.d.ts +8 -0
  157. package/lib/typescript/molecules/stepper/stepper.ios.d.ts +5 -0
  158. package/lib/typescript/molecules/stepper/stepper.types.d.ts +10 -0
  159. package/lib/typescript/molecules/tooltip/tooltip.types.d.ts +12 -0
  160. package/lib/typescript/organisms/action-sheet/action-sheet.types.d.ts +8 -0
  161. package/lib/typescript/organisms/alert/alert.types.d.ts +11 -0
  162. package/lib/typescript/organisms/context-menu/context-menu.types.d.ts +4 -0
  163. package/lib/typescript/organisms/fab-menu/fab-menu.types.d.ts +2 -0
  164. package/lib/typescript/organisms/form/form.types.d.ts +6 -0
  165. package/lib/typescript/organisms/menu/menu.types.d.ts +17 -0
  166. package/lib/typescript/organisms/sheet/sheet.types.d.ts +19 -0
  167. package/lib/typescript/organisms/snackbar/snackbar.types.d.ts +8 -0
  168. package/lib/typescript/organisms/swipe-actions/swipe-actions.types.d.ts +36 -13
  169. package/lib/typescript/templates/screen/screen.types.d.ts +9 -0
  170. package/package.json +5 -7
  171. package/src/atoms/activity-indicator/activity-indicator.android.tsx +32 -0
  172. package/src/atoms/activity-indicator/activity-indicator.ios.tsx +15 -0
  173. package/src/atoms/activity-indicator/activity-indicator.types.ts +20 -0
  174. package/src/atoms/activity-indicator/index.ts +1 -0
  175. package/src/atoms/avatar/avatar.tsx +1 -1
  176. package/src/atoms/avatar/avatar.types.ts +5 -0
  177. package/src/atoms/badge/badge.types.ts +3 -0
  178. package/src/atoms/blur-view/blur-view.android.tsx +68 -0
  179. package/src/atoms/blur-view/blur-view.ios.tsx +37 -0
  180. package/src/atoms/blur-view/blur-view.types.ts +34 -0
  181. package/src/atoms/blur-view/index.ts +2 -0
  182. package/src/atoms/button/button.types.ts +12 -0
  183. package/src/atoms/card/card.types.ts +6 -0
  184. package/src/atoms/checkbox/checkbox.android.tsx +7 -3
  185. package/src/atoms/checkbox/checkbox.types.ts +5 -0
  186. package/src/atoms/chip/chip.types.ts +5 -0
  187. package/src/atoms/color-picker/color-picker.types.ts +4 -0
  188. package/src/atoms/date-picker/date-picker.ios.tsx +33 -13
  189. package/src/atoms/date-picker/date-picker.types.ts +14 -0
  190. package/src/atoms/divider/divider.types.ts +3 -0
  191. package/src/atoms/fab/fab.types.ts +7 -0
  192. package/src/atoms/glass-view/glass-view.android.tsx +41 -3
  193. package/src/atoms/glass-view/glass-view.types.ts +13 -5
  194. package/src/atoms/h-stack/h-stack.types.ts +6 -0
  195. package/src/atoms/icon/icon.types.ts +8 -0
  196. package/src/atoms/icon-button/icon-button.types.ts +5 -0
  197. package/src/atoms/image/image.tsx +11 -12
  198. package/src/atoms/image/image.types.ts +6 -0
  199. package/src/atoms/image/index.ts +1 -0
  200. package/src/atoms/index.ts +1 -1
  201. package/src/atoms/island/island.android.tsx +10 -2
  202. package/src/atoms/island/island.ios.tsx +4 -2
  203. package/src/atoms/island/island.types.ts +10 -2
  204. package/src/atoms/list/list.types.ts +2 -0
  205. package/src/atoms/picker/picker.types.ts +12 -0
  206. package/src/atoms/pressable/pressable.tsx +46 -6
  207. package/src/atoms/pressable/pressable.types.ts +10 -0
  208. package/src/atoms/progress/progress.types.ts +6 -0
  209. package/src/atoms/rn-flat-list/rn-flat-list.tsx +8 -8
  210. package/src/atoms/rn-flat-list/rn-flat-list.types.ts +3 -1
  211. package/src/atoms/rn-scroll-view/rn-scroll-view.types.ts +4 -0
  212. package/src/atoms/rn-section-list/rn-section-list.tsx +5 -8
  213. package/src/atoms/rn-section-list/rn-section-list.types.ts +3 -1
  214. package/src/atoms/rn-text/rn-text.tsx +6 -3
  215. package/src/atoms/rn-text/rn-text.types.ts +15 -5
  216. package/src/atoms/rn-view/rn-view.types.ts +2 -0
  217. package/src/atoms/scroll-view/scroll-view.types.ts +4 -0
  218. package/src/atoms/segmented-control/segmented-control.android.tsx +79 -0
  219. package/src/atoms/segmented-control/segmented-control.ios.tsx +47 -0
  220. package/src/atoms/segmented-control/segmented-control.types.ts +13 -0
  221. package/src/atoms/skeleton/skeleton.tsx +4 -4
  222. package/src/atoms/skeleton/skeleton.types.ts +11 -2
  223. package/src/atoms/slider/slider.types.ts +7 -0
  224. package/src/atoms/spacer/spacer.types.ts +3 -0
  225. package/src/atoms/surface/surface.types.ts +7 -0
  226. package/src/atoms/switch/switch.android.tsx +4 -1
  227. package/src/atoms/switch/switch.types.ts +8 -0
  228. package/src/atoms/text/text.android.tsx +7 -1
  229. package/src/atoms/text/text.ios.tsx +14 -3
  230. package/src/atoms/text/text.types.ts +18 -1
  231. package/src/atoms/text-field/text-field.types.ts +12 -0
  232. package/src/atoms/v-stack/v-stack.types.ts +9 -0
  233. package/src/atoms/z-stack/z-stack.types.ts +8 -0
  234. package/src/molecules/collapsible/collapsible.android.tsx +47 -7
  235. package/src/molecules/collapsible/collapsible.types.ts +8 -0
  236. package/src/molecules/empty-state/empty-state.types.ts +5 -0
  237. package/src/molecules/label/label.types.ts +6 -0
  238. package/src/molecules/labeled-content/labeled-content.types.ts +6 -0
  239. package/src/molecules/link/link.types.ts +6 -0
  240. package/src/molecules/list-item/list-item.types.ts +9 -0
  241. package/src/molecules/navigation-bar/navigation-bar.android.tsx +1 -6
  242. package/src/molecules/navigation-bar/navigation-bar.types.ts +8 -0
  243. package/src/molecules/pager/pager.android.tsx +4 -1
  244. package/src/molecules/pager/pager.types.ts +2 -0
  245. package/src/molecules/radio-group/radio-group.types.ts +10 -0
  246. package/src/molecules/rn-list-item/rn-list-item.types.ts +1 -1
  247. package/src/molecules/rn-tooltip/rn-tooltip.types.ts +11 -0
  248. package/src/molecules/scroll-edge-container/scroll-edge-container.android.tsx +103 -10
  249. package/src/molecules/scroll-edge-container/scroll-edge-container.types.ts +7 -2
  250. package/src/molecules/search-bar/search-bar.tsx +9 -2
  251. package/src/molecules/search-bar/search-bar.types.ts +8 -0
  252. package/src/molecules/stepper/stepper.ios.tsx +37 -1
  253. package/src/molecules/stepper/stepper.types.ts +10 -0
  254. package/src/molecules/tooltip/tooltip.android.tsx +17 -9
  255. package/src/molecules/tooltip/tooltip.types.ts +12 -0
  256. package/src/organisms/action-sheet/action-sheet.android.tsx +37 -19
  257. package/src/organisms/action-sheet/action-sheet.ios.tsx +22 -9
  258. package/src/organisms/action-sheet/action-sheet.types.ts +8 -0
  259. package/src/organisms/alert/alert.ios.tsx +11 -1
  260. package/src/organisms/alert/alert.types.ts +11 -0
  261. package/src/organisms/context-menu/context-menu.types.ts +4 -0
  262. package/src/organisms/fab-menu/fab-menu.types.ts +2 -0
  263. package/src/organisms/form/form.android.tsx +15 -7
  264. package/src/organisms/form/form.types.ts +6 -0
  265. package/src/organisms/menu/menu.types.ts +17 -0
  266. package/src/organisms/sheet/sheet.types.ts +19 -0
  267. package/src/organisms/snackbar/snackbar.types.ts +8 -0
  268. package/src/organisms/swipe-actions/swipe-actions.android.tsx +129 -9
  269. package/src/organisms/swipe-actions/swipe-actions.ios.tsx +45 -11
  270. package/src/organisms/swipe-actions/swipe-actions.types.ts +37 -14
  271. package/src/ripple-clip.ts +10 -1
  272. package/src/templates/screen/screen.android.tsx +33 -12
  273. package/src/templates/screen/screen.types.ts +9 -0
  274. package/lib/module/atoms/activity-indicator/activity-indicator.js +0 -14
  275. package/lib/module/atoms/activity-indicator/activity-indicator.js.map +0 -1
  276. package/lib/module/atoms/flash-list/flash-list.js +0 -31
  277. package/lib/module/atoms/flash-list/flash-list.js.map +0 -1
  278. package/lib/module/atoms/flash-list/flash-list.types.js +0 -4
  279. package/lib/module/atoms/flash-list/flash-list.types.js.map +0 -1
  280. package/lib/module/atoms/flash-list/index.js +0 -5
  281. package/lib/module/atoms/flash-list/index.js.map +0 -1
  282. package/lib/module/atoms/segmented-control/segmented-control.js +0 -40
  283. package/lib/module/atoms/segmented-control/segmented-control.js.map +0 -1
  284. package/lib/typescript/atoms/flash-list/flash-list.d.ts +0 -8
  285. package/lib/typescript/atoms/flash-list/flash-list.types.d.ts +0 -18
  286. package/lib/typescript/atoms/flash-list/index.d.ts +0 -2
  287. package/src/atoms/activity-indicator/activity-indicator.tsx +0 -9
  288. package/src/atoms/flash-list/flash-list.tsx +0 -28
  289. package/src/atoms/flash-list/flash-list.types.ts +0 -20
  290. package/src/atoms/flash-list/index.ts +0 -2
  291. package/src/atoms/segmented-control/segmented-control.tsx +0 -47
@@ -1,18 +1,52 @@
1
- import {SwipeActions as SwiftUISwipeActions} from '@expo/ui/swift-ui'
1
+ import {Button, Image, Label, SwipeActions as SwiftUISwipeActions} from '@expo/ui/swift-ui'
2
+ import {tint} from '@expo/ui/swift-ui/modifiers'
3
+ import {iconResourceName} from '@hzblj/kara-native'
4
+ import {useAppTheme} from '@hzblj/kara-theme'
2
5
 
3
6
  import {useHostGuard} from '../../host-context'
4
- import type {SwipeActionsComponent, SwipeActionsGroupProps, SwipeActionsProps} from './swipe-actions.types'
7
+ import type {SwipeAction, SwipeActionsComponent, SwipeActionsProps} from './swipe-actions.types'
5
8
 
6
- const SwipeActionsRoot = ({children, testID}: SwipeActionsProps) => {
7
- useHostGuard('SwipeActions')
9
+ type ActionsProps = {actions: SwipeAction[]; allowsFullSwipe: boolean; edge: 'leading' | 'trailing'}
10
+
11
+ /**
12
+ * The edge's buttons, a `Label` each — iOS 26 draws its icon on a round button with the title under it; earlier
13
+ * versions, in a row of the usual height, the icon alone. No `destructive` role: SwiftUI would animate the row out by itself, and whether it goes is
14
+ * the list's data to say.
15
+ */
16
+ const Actions = ({actions, allowsFullSwipe, edge}: ActionsProps) => {
17
+ const theme = useAppTheme()
8
18
 
9
- return <SwiftUISwipeActions testID={testID}>{children}</SwiftUISwipeActions>
19
+ return (
20
+ <SwiftUISwipeActions.Actions allowsFullSwipe={allowsFullSwipe} edge={edge}>
21
+ {actions.map(action => (
22
+ <Button
23
+ key={action.label}
24
+ modifiers={[
25
+ tint(theme.color(action.tint ?? (action.destructive ? 'fill.destructive.primary' : 'fill.accent.primary'))),
26
+ ]}
27
+ onPress={action.onPress}
28
+ >
29
+ <Label icon={<Image assetName={iconResourceName(action.icon)} />} title={action.label} />
30
+ </Button>
31
+ ))}
32
+ </SwiftUISwipeActions.Actions>
33
+ )
10
34
  }
11
35
 
12
- const SwipeActionsGroup = ({allowsFullSwipe = true, children, edge = 'trailing'}: SwipeActionsGroupProps) => (
13
- <SwiftUISwipeActions.Actions allowsFullSwipe={allowsFullSwipe} edge={edge}>
14
- {children}
15
- </SwiftUISwipeActions.Actions>
16
- )
36
+ export const SwipeActions: SwipeActionsComponent = ({
37
+ allowsFullSwipe = true,
38
+ children,
39
+ leading = [],
40
+ testID,
41
+ trailing = [],
42
+ }: SwipeActionsProps) => {
43
+ useHostGuard('SwipeActions')
17
44
 
18
- export const SwipeActions: SwipeActionsComponent = Object.assign(SwipeActionsRoot, {Actions: SwipeActionsGroup})
45
+ return (
46
+ <SwiftUISwipeActions testID={testID}>
47
+ {children}
48
+ {leading.length > 0 ? <Actions actions={leading} allowsFullSwipe={allowsFullSwipe} edge="leading" /> : null}
49
+ {trailing.length > 0 ? <Actions actions={trailing} allowsFullSwipe={allowsFullSwipe} edge="trailing" /> : null}
50
+ </SwiftUISwipeActions>
51
+ )
52
+ }
@@ -1,24 +1,47 @@
1
+ import type {ColorToken} from '@hzblj/kara-theme'
1
2
  import type {ReactNode} from 'react'
2
3
 
3
- export type SwipeActionsEdge = 'leading' | 'trailing'
4
+ import type {IconName} from '../../atoms/icon'
5
+
6
+ /** One button a swiped row uncovers. */
7
+ export type SwipeAction = {
8
+ /** Fills the button with `fill.destructive.primary` unless `tint` says otherwise. */
9
+ destructive?: boolean
10
+ /** One of the app's icons, on the button — a round one on iOS 26, as in Mail, a filled stadium on Android. */
11
+ icon: IconName
12
+ /**
13
+ * The action's name, written under the button — before iOS 26 a row of the usual height shows the icon alone and
14
+ * keeps the label for VoiceOver. Actions are keyed by it, so keep labels unique within one row.
15
+ */
16
+ label: string
17
+ /** Called when the button is pressed. The row closes by itself. */
18
+ onPress: () => void
19
+ /**
20
+ * The button's fill — `fill.destructive.primary` for a destructive action, `fill.accent.primary` otherwise. The icon
21
+ * on it is white, so pick a fill that holds white in both appearances.
22
+ */
23
+ tint?: ColorToken
24
+ }
4
25
 
5
26
  /**
6
- * Swipe-to-reveal buttons on a row. iOS only — Compose ships no equivalent, so on Android the
7
- * row renders exactly as it would without this wrapper and the action buttons are dropped.
8
- * Degrading that way rather than to `null` keeps the content on screen.
27
+ * A list row with buttons behind it, uncovered by a swipe — SwiftUI's `swipeActions` on iOS, and on Android, where
28
+ * Compose has none, kara's own: the row slides on an anchored drag and the buttons show in the strip it leaves. One
29
+ * row is open at a time on both; a tap on an open row closes it. A native organism — it belongs inside a `List`.
9
30
  */
10
31
  export type SwipeActionsProps = {
11
- children: ReactNode
12
- testID?: string
13
- }
14
-
15
- export type SwipeActionsGroupProps = {
16
- /** Whether swiping all the way performs the first action in the group. */
32
+ /**
33
+ * iOS: a swipe all the way across performs the edge's first action, as in Mail. Android has no full swipe. `true`
34
+ * by default, as in SwiftUI.
35
+ */
17
36
  allowsFullSwipe?: boolean
37
+ /** The row. */
18
38
  children: ReactNode
19
- edge?: SwipeActionsEdge
39
+ /** The buttons at the leading edge, uncovered by a swipe toward the trailing one. The first sits outermost. */
40
+ leading?: SwipeAction[]
41
+ /** Test identifier. iOS: on the row. Android: the row is a Compose node, reach it by its content. */
42
+ testID?: string
43
+ /** The buttons at the trailing edge, uncovered by a swipe toward the leading one. The first sits outermost. */
44
+ trailing?: SwipeAction[]
20
45
  }
21
46
 
22
- export type SwipeActionsComponent = ((props: SwipeActionsProps) => ReactNode) & {
23
- Actions: (props: SwipeActionsGroupProps) => ReactNode
24
- }
47
+ export type SwipeActionsComponent = (props: SwipeActionsProps) => ReactNode
@@ -23,6 +23,9 @@ const CONTENT_KEYS = new Set<string>([
23
23
 
24
24
  const FILL: ViewStyle = {flexGrow: 1}
25
25
 
26
+ /** What gives the outer view a height of its own, rather than its content's. */
27
+ const SIZING_KEYS = ['aspectRatio', 'flex', 'flexBasis', 'flexGrow', 'height', 'minHeight'] as const
28
+
26
29
  /**
27
30
  * Splits a resolved style for a pressable with an Android ripple. The ripple is drawn as the pressable's foreground,
28
31
  * which its own `overflow: hidden` does not clip — so it would spill past rounded corners. A parent clips its
@@ -43,5 +46,11 @@ export const splitForRipple = (style: ViewStyle | undefined): {inner: ViewStyle[
43
46
  }
44
47
  }
45
48
 
46
- return {inner: [FILL, inner as ViewStyle], outer: outer as ViewStyle}
49
+ // Only a sized outer view needs the pressable stretched to it. Sized by its content it must not be: Yoga grows a
50
+ // `flexGrow` child of a fit-content parent to the most it may take — inside a row centred on its cross axis, the
51
+ // pressable would stretch to the row's full height and leave its content at the top.
52
+ const sized =
53
+ SIZING_KEYS.some(key => flat[key] !== undefined) || (flat.top !== undefined && flat.bottom !== undefined)
54
+
55
+ return {inner: sized ? [FILL, inner as ViewStyle] : [inner as ViewStyle], outer: outer as ViewStyle}
47
56
  }
@@ -1,24 +1,45 @@
1
1
  import {Column, Host} from '@expo/ui/jetpack-compose'
2
+ import {padding} from '@expo/ui/jetpack-compose/modifiers'
2
3
  import {useSxModifiers} from '@hzblj/kara-sx'
3
4
  import {useAppTheme} from '@hzblj/kara-theme'
4
- import {StyleSheet} from 'react-native'
5
+ import {useCallback, useMemo, useRef, useState} from 'react'
6
+ import {StatusBar, StyleSheet, View} from 'react-native'
5
7
  import {HostBoundary} from '../../host-context'
6
8
  import type {ScreenComponent, ScreenProps} from './screen.types'
7
9
 
10
+ /**
11
+ * The content keeps clear of as much of the status bar as the screen covers — all of it when nothing sits above the
12
+ * screen, none under a navigation bar — the way a SwiftUI host keeps to the safe area. Compose would draw under it:
13
+ * the app is edge to edge, and `Host` pads for nothing. The background still runs to the edge.
14
+ */
8
15
  export const Screen: ScreenComponent = ({bg = 'surface.base', children, ignoreKeyboardInset, testID}: ScreenProps) => {
9
16
  const theme = useAppTheme()
10
- const modifiers = useSxModifiers({bg, tall: true, wide: true})
17
+ const frame = useRef<View>(null)
18
+ const [statusBarOverlap, setStatusBarOverlap] = useState(0)
19
+ const sx = useSxModifiers({bg, tall: true, wide: true})
20
+ const modifiers = useMemo(
21
+ () => (statusBarOverlap > 0 ? [...sx, padding(0, statusBarOverlap, 0, 0)] : sx),
22
+ [statusBarOverlap, sx]
23
+ )
24
+
25
+ const onLayout = useCallback(() => {
26
+ frame.current?.measureInWindow((_x, y) => {
27
+ setStatusBarOverlap(Math.max(0, Math.round((StatusBar.currentHeight ?? 0) - y)))
28
+ })
29
+ }, [])
11
30
 
12
31
  return (
13
- <Host
14
- colorScheme={theme.dark ? 'dark' : 'light'}
15
- ignoreSafeAreaKeyboardInsets={ignoreKeyboardInset}
16
- seedColor={theme.materialSeed}
17
- style={StyleSheet.absoluteFill}
18
- >
19
- <Column modifiers={modifiers}>
20
- <HostBoundary>{children}</HostBoundary>
21
- </Column>
22
- </Host>
32
+ <View onLayout={onLayout} ref={frame} style={StyleSheet.absoluteFill} testID={testID}>
33
+ <Host
34
+ colorScheme={theme.dark ? 'dark' : 'light'}
35
+ ignoreSafeAreaKeyboardInsets={ignoreKeyboardInset}
36
+ seedColor={theme.materialSeed}
37
+ style={StyleSheet.absoluteFill}
38
+ >
39
+ <Column modifiers={modifiers}>
40
+ <HostBoundary>{children}</HostBoundary>
41
+ </Column>
42
+ </Host>
43
+ </View>
23
44
  )
24
45
  }
@@ -1,10 +1,19 @@
1
1
  import type {Sx} from '@hzblj/kara-sx'
2
2
  import type {ReactNode} from 'react'
3
3
 
4
+ /**
5
+ * The full-bleed native host a screen starts with — a SwiftUI or Compose `Host` filling its parent, so native atoms
6
+ * render anywhere inside it. The background runs to the edges; the content keeps clear of the status bar where the
7
+ * screen covers it (no navigation bar above), on Android as SwiftUI's safe area does on iOS.
8
+ */
4
9
  export type ScreenProps = {
10
+ /** The screen's colour. `surface.base` by default. */
5
11
  bg?: Sx['bg']
12
+ /** Laid out in a column that fills the screen. */
6
13
  children?: ReactNode
14
+ /** Keeps the content where it is when the keyboard opens, instead of avoiding it. Android reads it once, on mount. */
7
15
  ignoreKeyboardInset?: boolean
16
+ /** Test identifier — on the host view on iOS, on the view around it on Android. */
8
17
  testID?: string
9
18
  }
10
19
 
@@ -1,14 +0,0 @@
1
- "use strict";
2
-
3
- import { useAppTheme } from '@hzblj/kara-theme';
4
- import { ActivityIndicator as RNActivityIndicator } from 'react-native';
5
- import { jsx as _jsx } from "react/jsx-runtime";
6
- export const ActivityIndicator = props => {
7
- const theme = useAppTheme();
8
- return /*#__PURE__*/_jsx(RNActivityIndicator, {
9
- color: theme.color('fill.accent.primary'),
10
- size: "small",
11
- ...props
12
- });
13
- };
14
- //# sourceMappingURL=activity-indicator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["useAppTheme","ActivityIndicator","RNActivityIndicator","jsx","_jsx","props","theme","color","size"],"sourceRoot":"../../../../src","sources":["atoms/activity-indicator/activity-indicator.tsx"],"mappings":";;AAAA,SAAQA,WAAW,QAAO,mBAAmB;AAE7C,SAAqCC,iBAAiB,IAAIC,mBAAmB,QAAO,cAAc;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAElG,OAAO,MAAMH,iBAA6C,GAAGI,KAAK,IAAI;EACpE,MAAMC,KAAK,GAAGN,WAAW,CAAC,CAAC;EAE3B,oBAAOI,IAAA,CAACF,mBAAmB;IAACK,KAAK,EAAED,KAAK,CAACC,KAAK,CAAC,qBAAqB,CAAE;IAACC,IAAI,EAAC,OAAO;IAAA,GAAKH;EAAK,CAAG,CAAC;AACnG,CAAC","ignoreList":[]}
@@ -1,31 +0,0 @@
1
- "use strict";
2
-
3
- import { useSplitSx, useSx } from '@hzblj/kara-sx';
4
- import { FlashList as ShopifyFlashList } from '@shopify/flash-list';
5
- import { jsx as _jsx } from "react/jsx-runtime";
6
- /** Stands in for an absent `content`, because a hook cannot be called conditionally. */
7
- const NO_SX = {};
8
-
9
- /**
10
- * The default list in this codebase: recycles its rows, so it holds a long list at a steady cost.
11
- *
12
- * `RnFlatList` and `RnSectionList` are the alternatives, and only for rows that host native views —
13
- * see either one for why recycling and absolute positioning cannot carry an `@expo/ui` host.
14
- */
15
- export const FlashList = ({
16
- content,
17
- data,
18
- renderItem,
19
- ...props
20
- }) => {
21
- const [style, rest] = useSplitSx(props);
22
- const contentStyle = useSx(content ?? NO_SX);
23
- return /*#__PURE__*/_jsx(ShopifyFlashList, {
24
- data: data,
25
- renderItem: renderItem,
26
- ...rest,
27
- contentContainerStyle: content === undefined ? undefined : contentStyle,
28
- style: style
29
- });
30
- };
31
- //# sourceMappingURL=flash-list.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["useSplitSx","useSx","FlashList","ShopifyFlashList","jsx","_jsx","NO_SX","content","data","renderItem","props","style","rest","contentStyle","contentContainerStyle","undefined"],"sourceRoot":"../../../../src","sources":["atoms/flash-list/flash-list.tsx"],"mappings":";;AAAA,SAAQA,UAAU,EAAEC,KAAK,QAAO,gBAAgB;AAChD,SAAQC,SAAS,IAAIC,gBAAgB,QAAO,qBAAqB;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAIjE;AACA,MAAMC,KAAK,GAAG,CAAC,CAAC;;AAEhB;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMJ,SAAS,GAAGA,CAAS;EAACK,OAAO;EAAEC,IAAI;EAAEC,UAAU;EAAE,GAAGC;AAA4B,CAAC,KAAK;EACjG,MAAM,CAACC,KAAK,EAAEC,IAAI,CAAC,GAAGZ,UAAU,CAACU,KAAgC,CAAC;EAClE,MAAMG,YAAY,GAAGZ,KAAK,CAACM,OAAO,IAAID,KAAK,CAAC;EAE5C,oBACED,IAAA,CAACF,gBAAgB;IACfK,IAAI,EAAEA,IAAK;IACXC,UAAU,EAAEA,UAAW;IAAA,GACnBG,IAAI;IACRE,qBAAqB,EAAEP,OAAO,KAAKQ,SAAS,GAAGA,SAAS,GAAGF,YAAa;IACxEF,KAAK,EAAEA;EAAM,CACd,CAAC;AAEN,CAAC","ignoreList":[]}
@@ -1,4 +0,0 @@
1
- "use strict";
2
-
3
- export {};
4
- //# sourceMappingURL=flash-list.types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":[],"sourceRoot":"../../../../src","sources":["atoms/flash-list/flash-list.types.ts"],"mappings":"","ignoreList":[]}
@@ -1,5 +0,0 @@
1
- "use strict";
2
-
3
- export * from "./flash-list.js";
4
- export * from "./flash-list.types.js";
5
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":[],"sourceRoot":"../../../../src","sources":["atoms/flash-list/index.ts"],"mappings":";;AAAA,cAAc,iBAAc;AAC5B,cAAc,uBAAoB","ignoreList":[]}
@@ -1,40 +0,0 @@
1
- "use strict";
2
-
3
- import { SegmentedControl as NativeSegmentedControl } from '@expo/ui/community/segmented-control';
4
- import { useAppTheme } from '@hzblj/kara-theme';
5
- import { useCallback } from 'react';
6
- import { Platform } from 'react-native';
7
- import { haptics } from "../../haptics/index.js";
8
- import { jsx as _jsx } from "react/jsx-runtime";
9
- /**
10
- * `UISegmentedControl` on iOS, Material's single-choice segmented buttons on Android. A new segment plays `selection`
11
- * on Android, whose buttons play nothing of their own; iOS 26's control already gives its own feedback.
12
- */
13
- export const SegmentedControl = ({
14
- disabled = false,
15
- onChange,
16
- selectedIndex,
17
- testID,
18
- values
19
- }) => {
20
- const theme = useAppTheme();
21
- const onNativeChange = useCallback(event => {
22
- const index = event.nativeEvent.selectedSegmentIndex;
23
-
24
- // Material reports a tap on the segment that is already selected too.
25
- if (Platform.OS === 'android' && index !== selectedIndex) {
26
- haptics.selection();
27
- }
28
- onChange?.(index, event.nativeEvent.value);
29
- }, [onChange, selectedIndex]);
30
- return /*#__PURE__*/_jsx(NativeSegmentedControl, {
31
- appearance: theme.dark ? 'dark' : 'light',
32
- enabled: !disabled,
33
- onChange: onNativeChange,
34
- selectedIndex: selectedIndex,
35
- testID: testID,
36
- tintColor: theme.colorString('surface.primary'),
37
- values: values
38
- });
39
- };
40
- //# sourceMappingURL=segmented-control.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["SegmentedControl","NativeSegmentedControl","useAppTheme","useCallback","Platform","haptics","jsx","_jsx","disabled","onChange","selectedIndex","testID","values","theme","onNativeChange","event","index","nativeEvent","selectedSegmentIndex","OS","selection","value","appearance","dark","enabled","tintColor","colorString"],"sourceRoot":"../../../../src","sources":["atoms/segmented-control/segmented-control.tsx"],"mappings":";;AAAA,SAAQA,gBAAgB,IAAIC,sBAAsB,QAAO,sCAAsC;AAC/F,SAAQC,WAAW,QAAO,mBAAmB;AAC7C,SAAQC,WAAW,QAAO,OAAO;AACjC,SAAQC,QAAQ,QAAO,cAAc;AAErC,SAAQC,OAAO,QAAO,wBAAe;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAGrC;AACA;AACA;AACA;AACA,OAAO,MAAMP,gBAA2C,GAAGA,CAAC;EAC1DQ,QAAQ,GAAG,KAAK;EAChBC,QAAQ;EACRC,aAAa;EACbC,MAAM;EACNC;AACqB,CAAC,KAAK;EAC3B,MAAMC,KAAK,GAAGX,WAAW,CAAC,CAAC;EAE3B,MAAMY,cAAc,GAAGX,WAAW,CAC/BY,KAAmE,IAAK;IACvE,MAAMC,KAAK,GAAGD,KAAK,CAACE,WAAW,CAACC,oBAAoB;;IAEpD;IACA,IAAId,QAAQ,CAACe,EAAE,KAAK,SAAS,IAAIH,KAAK,KAAKN,aAAa,EAAE;MACxDL,OAAO,CAACe,SAAS,CAAC,CAAC;IACrB;IAEAX,QAAQ,GAAGO,KAAK,EAAED,KAAK,CAACE,WAAW,CAACI,KAAK,CAAC;EAC5C,CAAC,EACD,CAACZ,QAAQ,EAAEC,aAAa,CAC1B,CAAC;EAED,oBACEH,IAAA,CAACN,sBAAsB;IACrBqB,UAAU,EAAET,KAAK,CAACU,IAAI,GAAG,MAAM,GAAG,OAAQ;IAC1CC,OAAO,EAAE,CAAChB,QAAS;IACnBC,QAAQ,EAAEK,cAAe;IACzBJ,aAAa,EAAEA,aAAc;IAC7BC,MAAM,EAAEA,MAAO;IACfc,SAAS,EAAEZ,KAAK,CAACa,WAAW,CAAC,iBAAiB,CAAE;IAChDd,MAAM,EAAEA;EAAO,CAChB,CAAC;AAEN,CAAC","ignoreList":[]}
@@ -1,8 +0,0 @@
1
- import type { FlashListProps } from './flash-list.types';
2
- /**
3
- * The default list in this codebase: recycles its rows, so it holds a long list at a steady cost.
4
- *
5
- * `RnFlatList` and `RnSectionList` are the alternatives, and only for rows that host native views —
6
- * see either one for why recycling and absolute positioning cannot carry an `@expo/ui` host.
7
- */
8
- export declare const FlashList: <TItem>({ content, data, renderItem, ...props }: FlashListProps<TItem>) => import("react").JSX.Element;
@@ -1,18 +0,0 @@
1
- import type { ResponsiveViewSx } from '@hzblj/kara-sx';
2
- import type { FlashListRef, FlashListProps as ShopifyFlashListProps } from '@shopify/flash-list';
3
- import type { Ref } from 'react';
4
- /**
5
- * Top-level `sx` styles the viewport; `content` styles the scrolling content container — the same split
6
- * as `RnScrollView` and the React Native lists.
7
- *
8
- * Padding belongs in `content` here and nowhere else. FlashList measures its rows against its own
9
- * `style`, and padding there throws that measurement off; its docs put it as "margin is okay but padding
10
- * is not". `content` has no such limit, because it lands on the scroll view's content container.
11
- *
12
- * `ref` is declared because this is a wrapper rather than the re-export it used to be — React 19 passes
13
- * it as a plain prop, and a `FlashListRef` is how a caller reaches `scrollToIndex` and friends.
14
- */
15
- export type FlashListProps<TItem> = ResponsiveViewSx & Omit<ShopifyFlashListProps<TItem>, 'contentContainerStyle' | 'style'> & {
16
- content?: ResponsiveViewSx;
17
- ref?: Ref<FlashListRef<TItem>>;
18
- };
@@ -1,2 +0,0 @@
1
- export * from './flash-list';
2
- export * from './flash-list.types';
@@ -1,9 +0,0 @@
1
- import {useAppTheme} from '@hzblj/kara-theme'
2
- import type {FC} from 'react'
3
- import {type ActivityIndicatorProps, ActivityIndicator as RNActivityIndicator} from 'react-native'
4
-
5
- export const ActivityIndicator: FC<ActivityIndicatorProps> = props => {
6
- const theme = useAppTheme()
7
-
8
- return <RNActivityIndicator color={theme.color('fill.accent.primary')} size="small" {...props} />
9
- }
@@ -1,28 +0,0 @@
1
- import {useSplitSx, useSx} from '@hzblj/kara-sx'
2
- import {FlashList as ShopifyFlashList} from '@shopify/flash-list'
3
-
4
- import type {FlashListProps} from './flash-list.types'
5
-
6
- /** Stands in for an absent `content`, because a hook cannot be called conditionally. */
7
- const NO_SX = {}
8
-
9
- /**
10
- * The default list in this codebase: recycles its rows, so it holds a long list at a steady cost.
11
- *
12
- * `RnFlatList` and `RnSectionList` are the alternatives, and only for rows that host native views —
13
- * see either one for why recycling and absolute positioning cannot carry an `@expo/ui` host.
14
- */
15
- export const FlashList = <TItem,>({content, data, renderItem, ...props}: FlashListProps<TItem>) => {
16
- const [style, rest] = useSplitSx(props as Record<string, unknown>)
17
- const contentStyle = useSx(content ?? NO_SX)
18
-
19
- return (
20
- <ShopifyFlashList
21
- data={data}
22
- renderItem={renderItem}
23
- {...rest}
24
- contentContainerStyle={content === undefined ? undefined : contentStyle}
25
- style={style}
26
- />
27
- )
28
- }
@@ -1,20 +0,0 @@
1
- import type {ResponsiveViewSx} from '@hzblj/kara-sx'
2
- import type {FlashListRef, FlashListProps as ShopifyFlashListProps} from '@shopify/flash-list'
3
- import type {Ref} from 'react'
4
-
5
- /**
6
- * Top-level `sx` styles the viewport; `content` styles the scrolling content container — the same split
7
- * as `RnScrollView` and the React Native lists.
8
- *
9
- * Padding belongs in `content` here and nowhere else. FlashList measures its rows against its own
10
- * `style`, and padding there throws that measurement off; its docs put it as "margin is okay but padding
11
- * is not". `content` has no such limit, because it lands on the scroll view's content container.
12
- *
13
- * `ref` is declared because this is a wrapper rather than the re-export it used to be — React 19 passes
14
- * it as a plain prop, and a `FlashListRef` is how a caller reaches `scrollToIndex` and friends.
15
- */
16
- export type FlashListProps<TItem> = ResponsiveViewSx &
17
- Omit<ShopifyFlashListProps<TItem>, 'contentContainerStyle' | 'style'> & {
18
- content?: ResponsiveViewSx
19
- ref?: Ref<FlashListRef<TItem>>
20
- }
@@ -1,2 +0,0 @@
1
- export * from './flash-list'
2
- export * from './flash-list.types'
@@ -1,47 +0,0 @@
1
- import {SegmentedControl as NativeSegmentedControl} from '@expo/ui/community/segmented-control'
2
- import {useAppTheme} from '@hzblj/kara-theme'
3
- import {useCallback} from 'react'
4
- import {Platform} from 'react-native'
5
-
6
- import {haptics} from '../../haptics'
7
- import type {SegmentedControlComponent, SegmentedControlProps} from './segmented-control.types'
8
-
9
- /**
10
- * `UISegmentedControl` on iOS, Material's single-choice segmented buttons on Android. A new segment plays `selection`
11
- * on Android, whose buttons play nothing of their own; iOS 26's control already gives its own feedback.
12
- */
13
- export const SegmentedControl: SegmentedControlComponent = ({
14
- disabled = false,
15
- onChange,
16
- selectedIndex,
17
- testID,
18
- values,
19
- }: SegmentedControlProps) => {
20
- const theme = useAppTheme()
21
-
22
- const onNativeChange = useCallback(
23
- (event: {nativeEvent: {selectedSegmentIndex: number; value: string}}) => {
24
- const index = event.nativeEvent.selectedSegmentIndex
25
-
26
- // Material reports a tap on the segment that is already selected too.
27
- if (Platform.OS === 'android' && index !== selectedIndex) {
28
- haptics.selection()
29
- }
30
-
31
- onChange?.(index, event.nativeEvent.value)
32
- },
33
- [onChange, selectedIndex]
34
- )
35
-
36
- return (
37
- <NativeSegmentedControl
38
- appearance={theme.dark ? 'dark' : 'light'}
39
- enabled={!disabled}
40
- onChange={onNativeChange}
41
- selectedIndex={selectedIndex}
42
- testID={testID}
43
- tintColor={theme.colorString('surface.primary')}
44
- values={values}
45
- />
46
- )
47
- }