@hzblj/kara-components 0.20.0 → 0.21.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 (480) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/lib/module/atoms/activity-indicator/activity-indicator.android.js +1 -1
  3. package/lib/module/atoms/activity-indicator/activity-indicator.android.js.map +1 -1
  4. package/lib/module/atoms/activity-indicator/activity-indicator.ios.js +1 -1
  5. package/lib/module/atoms/activity-indicator/activity-indicator.ios.js.map +1 -1
  6. package/lib/module/atoms/badge/badge.android.js +1 -1
  7. package/lib/module/atoms/badge/badge.android.js.map +1 -1
  8. package/lib/module/atoms/badge/badge.ios.js +1 -1
  9. package/lib/module/atoms/badge/badge.ios.js.map +1 -1
  10. package/lib/module/atoms/blur-view/blur-view.android.js +22 -1
  11. package/lib/module/atoms/blur-view/blur-view.android.js.map +1 -1
  12. package/lib/module/atoms/blur-view/blur-view.ios.js +20 -0
  13. package/lib/module/atoms/blur-view/blur-view.ios.js.map +1 -1
  14. package/lib/module/atoms/button/button.android.js +1 -1
  15. package/lib/module/atoms/button/button.android.js.map +1 -1
  16. package/lib/module/atoms/button/button.ios.js +1 -1
  17. package/lib/module/atoms/button/button.ios.js.map +1 -1
  18. package/lib/module/atoms/card/card.android.js +1 -1
  19. package/lib/module/atoms/card/card.android.js.map +1 -1
  20. package/lib/module/atoms/card/card.ios.js +1 -1
  21. package/lib/module/atoms/card/card.ios.js.map +1 -1
  22. package/lib/module/atoms/checkbox/checkbox.android.js +1 -1
  23. package/lib/module/atoms/checkbox/checkbox.android.js.map +1 -1
  24. package/lib/module/atoms/checkbox/checkbox.ios.js +1 -1
  25. package/lib/module/atoms/checkbox/checkbox.ios.js.map +1 -1
  26. package/lib/module/atoms/color-picker/color-picker.android.js +1 -1
  27. package/lib/module/atoms/color-picker/color-picker.android.js.map +1 -1
  28. package/lib/module/atoms/color-picker/color-picker.ios.js +1 -1
  29. package/lib/module/atoms/color-picker/color-picker.ios.js.map +1 -1
  30. package/lib/module/atoms/date-picker/date-picker.android.js +1 -1
  31. package/lib/module/atoms/date-picker/date-picker.android.js.map +1 -1
  32. package/lib/module/atoms/date-picker/date-picker.ios.js +1 -1
  33. package/lib/module/atoms/date-picker/date-picker.ios.js.map +1 -1
  34. package/lib/module/atoms/divider/divider.android.js +1 -1
  35. package/lib/module/atoms/divider/divider.android.js.map +1 -1
  36. package/lib/module/atoms/divider/divider.ios.js +1 -1
  37. package/lib/module/atoms/divider/divider.ios.js.map +1 -1
  38. package/lib/module/atoms/fab/fab.android.js +1 -1
  39. package/lib/module/atoms/fab/fab.android.js.map +1 -1
  40. package/lib/module/atoms/fab/fab.ios.js +1 -1
  41. package/lib/module/atoms/fab/fab.ios.js.map +1 -1
  42. package/lib/module/atoms/glyph/glyph-button.android.js.map +1 -0
  43. package/lib/module/atoms/glyph/glyph-button.ios.js.map +1 -0
  44. package/lib/module/atoms/glyph/glyph-button.types.js.map +1 -0
  45. package/lib/module/atoms/glyph/glyph.android.js.map +1 -0
  46. package/lib/module/atoms/glyph/glyph.ios.js.map +1 -0
  47. package/lib/module/atoms/glyph/glyph.types.js.map +1 -0
  48. package/lib/module/atoms/glyph/index.js.map +1 -0
  49. package/lib/module/atoms/glyph/rn-glyph.android.js.map +1 -0
  50. package/lib/module/atoms/glyph/rn-glyph.ios.js.map +1 -0
  51. package/lib/module/atoms/h-stack/h-stack.android.js +2 -2
  52. package/lib/module/atoms/h-stack/h-stack.android.js.map +1 -1
  53. package/lib/module/atoms/h-stack/h-stack.ios.js +2 -2
  54. package/lib/module/atoms/h-stack/h-stack.ios.js.map +1 -1
  55. package/lib/module/atoms/icon/icon.android.js +1 -1
  56. package/lib/module/atoms/icon/icon.android.js.map +1 -1
  57. package/lib/module/atoms/icon/icon.ios.js +1 -1
  58. package/lib/module/atoms/icon/icon.ios.js.map +1 -1
  59. package/lib/module/atoms/icon-button/icon-button.android.js +1 -1
  60. package/lib/module/atoms/icon-button/icon-button.android.js.map +1 -1
  61. package/lib/module/atoms/icon-button/icon-button.ios.js +1 -1
  62. package/lib/module/atoms/icon-button/icon-button.ios.js.map +1 -1
  63. package/lib/module/atoms/island/island.android.js +3 -1
  64. package/lib/module/atoms/island/island.android.js.map +1 -1
  65. package/lib/module/atoms/island/island.ios.js +3 -1
  66. package/lib/module/atoms/island/island.ios.js.map +1 -1
  67. package/lib/module/atoms/list/list.android.js +2 -2
  68. package/lib/module/atoms/list/list.android.js.map +1 -1
  69. package/lib/module/atoms/list/list.ios.js +1 -1
  70. package/lib/module/atoms/list/list.ios.js.map +1 -1
  71. package/lib/module/atoms/picker/picker.android.js +2 -2
  72. package/lib/module/atoms/picker/picker.android.js.map +1 -1
  73. package/lib/module/atoms/picker/picker.ios.js +1 -1
  74. package/lib/module/atoms/picker/picker.ios.js.map +1 -1
  75. package/lib/module/atoms/pressable/pressable.js +1 -1
  76. package/lib/module/atoms/pressable/pressable.js.map +1 -1
  77. package/lib/module/atoms/progress/progress.android.js +1 -1
  78. package/lib/module/atoms/progress/progress.android.js.map +1 -1
  79. package/lib/module/atoms/progress/progress.ios.js +1 -1
  80. package/lib/module/atoms/progress/progress.ios.js.map +1 -1
  81. package/lib/module/atoms/scroll-view/scroll-view.android.js +2 -2
  82. package/lib/module/atoms/scroll-view/scroll-view.android.js.map +1 -1
  83. package/lib/module/atoms/scroll-view/scroll-view.ios.js +1 -1
  84. package/lib/module/atoms/scroll-view/scroll-view.ios.js.map +1 -1
  85. package/lib/module/atoms/segmented-control/segmented-control.android.js +1 -1
  86. package/lib/module/atoms/segmented-control/segmented-control.android.js.map +1 -1
  87. package/lib/module/atoms/segmented-control/segmented-control.ios.js +1 -1
  88. package/lib/module/atoms/segmented-control/segmented-control.ios.js.map +1 -1
  89. package/lib/module/atoms/slider/slider.android.js +1 -1
  90. package/lib/module/atoms/slider/slider.android.js.map +1 -1
  91. package/lib/module/atoms/slider/slider.ios.js +1 -1
  92. package/lib/module/atoms/slider/slider.ios.js.map +1 -1
  93. package/lib/module/atoms/spacer/spacer.android.js +1 -1
  94. package/lib/module/atoms/spacer/spacer.android.js.map +1 -1
  95. package/lib/module/atoms/spacer/spacer.ios.js +1 -1
  96. package/lib/module/atoms/spacer/spacer.ios.js.map +1 -1
  97. package/lib/module/atoms/surface/surface.android.js +1 -1
  98. package/lib/module/atoms/surface/surface.android.js.map +1 -1
  99. package/lib/module/atoms/surface/surface.ios.js +1 -1
  100. package/lib/module/atoms/surface/surface.ios.js.map +1 -1
  101. package/lib/module/atoms/switch/switch.android.js +1 -1
  102. package/lib/module/atoms/switch/switch.android.js.map +1 -1
  103. package/lib/module/atoms/switch/switch.ios.js +1 -1
  104. package/lib/module/atoms/switch/switch.ios.js.map +1 -1
  105. package/lib/module/atoms/text/text.android.js +1 -1
  106. package/lib/module/atoms/text/text.android.js.map +1 -1
  107. package/lib/module/atoms/text/text.ios.js +1 -1
  108. package/lib/module/atoms/text/text.ios.js.map +1 -1
  109. package/lib/module/atoms/text-field/text-field.android.js +2 -2
  110. package/lib/module/atoms/text-field/text-field.android.js.map +1 -1
  111. package/lib/module/atoms/text-field/text-field.ios.js +1 -1
  112. package/lib/module/atoms/text-field/text-field.ios.js.map +1 -1
  113. package/lib/module/atoms/v-stack/v-stack.android.js +2 -2
  114. package/lib/module/atoms/v-stack/v-stack.android.js.map +1 -1
  115. package/lib/module/atoms/v-stack/v-stack.ios.js +2 -2
  116. package/lib/module/atoms/v-stack/v-stack.ios.js.map +1 -1
  117. package/lib/module/atoms/z-stack/z-stack.android.js +2 -2
  118. package/lib/module/atoms/z-stack/z-stack.android.js.map +1 -1
  119. package/lib/module/atoms/z-stack/z-stack.ios.js +2 -2
  120. package/lib/module/atoms/z-stack/z-stack.ios.js.map +1 -1
  121. package/lib/module/hooks/host-context.js.map +1 -0
  122. package/lib/module/hooks/use-refresh-state.js.map +1 -0
  123. package/lib/module/hooks/use-stack-modifiers.js.map +1 -0
  124. package/lib/module/molecules/collapsible/collapsible.android.js +2 -2
  125. package/lib/module/molecules/collapsible/collapsible.android.js.map +1 -1
  126. package/lib/module/molecules/collapsible/collapsible.ios.js +1 -1
  127. package/lib/module/molecules/collapsible/collapsible.ios.js.map +1 -1
  128. package/lib/module/molecules/labeled-content/labeled-content.js +1 -1
  129. package/lib/module/molecules/labeled-content/labeled-content.js.map +1 -1
  130. package/lib/module/molecules/list-item/list-item.js +1 -1
  131. package/lib/module/molecules/list-item/list-item.js.map +1 -1
  132. package/lib/module/molecules/navigation-bar/navigation-bar.constants.js +5 -0
  133. package/lib/module/molecules/navigation-bar/navigation-bar.constants.js.map +1 -0
  134. package/lib/module/molecules/navigation-bar/navigation-bar.ios.js +31 -4
  135. package/lib/module/molecules/navigation-bar/navigation-bar.ios.js.map +1 -1
  136. package/lib/module/molecules/pager/pager.android.js +1 -1
  137. package/lib/module/molecules/pager/pager.android.js.map +1 -1
  138. package/lib/module/molecules/pager/pager.ios.js +1 -1
  139. package/lib/module/molecules/pager/pager.ios.js.map +1 -1
  140. package/lib/module/molecules/radio-group/radio-group.android.js +1 -1
  141. package/lib/module/molecules/radio-group/radio-group.android.js.map +1 -1
  142. package/lib/module/molecules/radio-group/radio-group.ios.js +2 -2
  143. package/lib/module/molecules/radio-group/radio-group.ios.js.map +1 -1
  144. package/lib/module/molecules/rn-list-item/rn-list-item.js +1 -1
  145. package/lib/module/molecules/rn-list-item/rn-list-item.js.map +1 -1
  146. package/lib/module/molecules/rn-tooltip/rn-tooltip.android.js +1 -1
  147. package/lib/module/molecules/rn-tooltip/rn-tooltip.android.js.map +1 -1
  148. package/lib/module/molecules/search-bar/search-bar.js +1 -1
  149. package/lib/module/molecules/search-bar/search-bar.js.map +1 -1
  150. package/lib/module/molecules/stepper/stepper.android.js +2 -2
  151. package/lib/module/molecules/stepper/stepper.android.js.map +1 -1
  152. package/lib/module/molecules/stepper/stepper.ios.js +1 -1
  153. package/lib/module/molecules/stepper/stepper.ios.js.map +1 -1
  154. package/lib/module/molecules/tooltip/tooltip.android.js +1 -1
  155. package/lib/module/molecules/tooltip/tooltip.android.js.map +1 -1
  156. package/lib/module/molecules/tooltip/tooltip.ios.js +1 -1
  157. package/lib/module/molecules/tooltip/tooltip.ios.js.map +1 -1
  158. package/lib/module/organisms/action-sheet/action-sheet.android.js +1 -1
  159. package/lib/module/organisms/action-sheet/action-sheet.android.js.map +1 -1
  160. package/lib/module/organisms/action-sheet/action-sheet.ios.js +1 -1
  161. package/lib/module/organisms/action-sheet/action-sheet.ios.js.map +1 -1
  162. package/lib/module/organisms/alert/alert.android.js +1 -1
  163. package/lib/module/organisms/alert/alert.android.js.map +1 -1
  164. package/lib/module/organisms/alert/alert.ios.js +1 -1
  165. package/lib/module/organisms/alert/alert.ios.js.map +1 -1
  166. package/lib/module/organisms/context-menu/context-menu.android.js +2 -2
  167. package/lib/module/organisms/context-menu/context-menu.android.js.map +1 -1
  168. package/lib/module/organisms/fab-menu/fab-menu.android.js +2 -2
  169. package/lib/module/organisms/fab-menu/fab-menu.android.js.map +1 -1
  170. package/lib/module/organisms/fab-menu/fab-menu.ios.js +2 -2
  171. package/lib/module/organisms/fab-menu/fab-menu.ios.js.map +1 -1
  172. package/lib/module/organisms/form/form.android.js +1 -1
  173. package/lib/module/organisms/form/form.android.js.map +1 -1
  174. package/lib/module/organisms/form/form.ios.js +1 -1
  175. package/lib/module/organisms/form/form.ios.js.map +1 -1
  176. package/lib/module/organisms/header/header-color.js +8 -0
  177. package/lib/module/organisms/header/header-color.js.map +1 -0
  178. package/lib/module/organisms/header/header-inset.android.js +6 -0
  179. package/lib/module/organisms/header/header-inset.android.js.map +1 -0
  180. package/lib/module/organisms/header/header-inset.ios.js +19 -0
  181. package/lib/module/organisms/header/header-inset.ios.js.map +1 -0
  182. package/lib/module/organisms/header/header-options.android.js +180 -0
  183. package/lib/module/organisms/header/header-options.android.js.map +1 -0
  184. package/lib/module/organisms/header/header-options.ios.js +145 -0
  185. package/lib/module/organisms/header/header-options.ios.js.map +1 -0
  186. package/lib/module/organisms/header/header-options.types.js +4 -0
  187. package/lib/module/organisms/header/header-options.types.js.map +1 -0
  188. package/lib/module/organisms/header/header-search-accessory.android.js +5 -0
  189. package/lib/module/organisms/header/header-search-accessory.android.js.map +1 -0
  190. package/lib/module/organisms/header/header-search-accessory.ios.js +35 -0
  191. package/lib/module/organisms/header/header-search-accessory.ios.js.map +1 -0
  192. package/lib/module/organisms/header/header-search-accessory.types.js +4 -0
  193. package/lib/module/organisms/header/header-search-accessory.types.js.map +1 -0
  194. package/lib/module/organisms/header/header-search-input.android.js +80 -0
  195. package/lib/module/organisms/header/header-search-input.android.js.map +1 -0
  196. package/lib/module/organisms/header/header-search-input.ios.js +8 -0
  197. package/lib/module/organisms/header/header-search-input.ios.js.map +1 -0
  198. package/lib/module/organisms/header/header-search-input.types.js +4 -0
  199. package/lib/module/organisms/header/header-search-input.types.js.map +1 -0
  200. package/lib/module/organisms/header/header-search-scrim.js +62 -0
  201. package/lib/module/organisms/header/header-search-scrim.js.map +1 -0
  202. package/lib/module/organisms/header/header-title.js +230 -0
  203. package/lib/module/organisms/header/header-title.js.map +1 -0
  204. package/lib/module/organisms/header/header.types.js +4 -0
  205. package/lib/module/organisms/header/header.types.js.map +1 -0
  206. package/lib/module/organisms/header/hero-header-background.android.js +33 -0
  207. package/lib/module/organisms/header/hero-header-background.android.js.map +1 -0
  208. package/lib/module/organisms/header/hero-header-background.ios.js +40 -0
  209. package/lib/module/organisms/header/hero-header-background.ios.js.map +1 -0
  210. package/lib/module/organisms/header/hero-header-background.types.js +4 -0
  211. package/lib/module/organisms/header/hero-header-background.types.js.map +1 -0
  212. package/lib/module/organisms/header/index.js +13 -0
  213. package/lib/module/organisms/header/index.js.map +1 -0
  214. package/lib/module/organisms/header/native-subtitle.android.js +5 -0
  215. package/lib/module/organisms/header/native-subtitle.android.js.map +1 -0
  216. package/lib/module/organisms/header/native-subtitle.ios.js +22 -0
  217. package/lib/module/organisms/header/native-subtitle.ios.js.map +1 -0
  218. package/lib/module/organisms/header/native-subtitle.types.js +4 -0
  219. package/lib/module/organisms/header/native-subtitle.types.js.map +1 -0
  220. package/lib/module/organisms/header/sheet-grabber.android.js +5 -0
  221. package/lib/module/organisms/header/sheet-grabber.android.js.map +1 -0
  222. package/lib/module/organisms/header/sheet-grabber.ios.js +15 -0
  223. package/lib/module/organisms/header/sheet-grabber.ios.js.map +1 -0
  224. package/lib/module/organisms/header/sheet-grabber.types.js +4 -0
  225. package/lib/module/organisms/header/sheet-grabber.types.js.map +1 -0
  226. package/lib/module/organisms/header/use-header-bar-inset.android.js +4 -0
  227. package/lib/module/organisms/header/use-header-bar-inset.android.js.map +1 -0
  228. package/lib/module/organisms/header/use-header-bar-inset.ios.js +9 -0
  229. package/lib/module/organisms/header/use-header-bar-inset.ios.js.map +1 -0
  230. package/lib/module/organisms/header/use-header-bar-inset.types.js +2 -0
  231. package/lib/module/organisms/header/use-header-bar-inset.types.js.map +1 -0
  232. package/lib/module/organisms/header/use-header-scroll-to-top.js +51 -0
  233. package/lib/module/organisms/header/use-header-scroll-to-top.js.map +1 -0
  234. package/lib/module/organisms/header/use-header-search.js +135 -0
  235. package/lib/module/organisms/header/use-header-search.js.map +1 -0
  236. package/lib/module/organisms/header/use-header.js +74 -0
  237. package/lib/module/organisms/header/use-header.js.map +1 -0
  238. package/lib/module/organisms/header/use-hero-header.js +189 -0
  239. package/lib/module/organisms/header/use-hero-header.js.map +1 -0
  240. package/lib/module/organisms/header/use-stack-screen-options.js +77 -0
  241. package/lib/module/organisms/header/use-stack-screen-options.js.map +1 -0
  242. package/lib/module/organisms/menu/menu.android.js +2 -2
  243. package/lib/module/organisms/menu/menu.android.js.map +1 -1
  244. package/lib/module/organisms/menu/menu.ios.js +1 -1
  245. package/lib/module/organisms/menu/menu.ios.js.map +1 -1
  246. package/lib/module/organisms/sheet/use-sheet-header.js +3 -1
  247. package/lib/module/organisms/sheet/use-sheet-header.js.map +1 -1
  248. package/lib/module/organisms/snackbar/snackbar.js +1 -1
  249. package/lib/module/organisms/snackbar/snackbar.js.map +1 -1
  250. package/lib/module/organisms/swipe-actions/swipe-actions.android.js +1 -1
  251. package/lib/module/organisms/swipe-actions/swipe-actions.android.js.map +1 -1
  252. package/lib/module/organisms/swipe-actions/swipe-actions.ios.js +1 -1
  253. package/lib/module/organisms/swipe-actions/swipe-actions.ios.js.map +1 -1
  254. package/lib/module/templates/screen/screen.android.js +3 -3
  255. package/lib/module/templates/screen/screen.android.js.map +1 -1
  256. package/lib/module/templates/screen/screen.ios.js +3 -3
  257. package/lib/module/templates/screen/screen.ios.js.map +1 -1
  258. package/lib/module/utils/ripple-clip.js.map +1 -0
  259. package/lib/module/utils/tap-modifiers.js.map +1 -0
  260. package/lib/typescript/atoms/blur-view/blur-view.types.d.ts +8 -0
  261. package/lib/typescript/atoms/island/island.types.d.ts +17 -0
  262. package/lib/typescript/molecules/navigation-bar/navigation-bar.constants.d.ts +2 -0
  263. package/lib/typescript/molecules/navigation-bar/navigation-bar.types.d.ts +67 -4
  264. package/lib/typescript/organisms/header/header-color.d.ts +6 -0
  265. package/lib/typescript/organisms/header/header-inset.d.ts +1 -0
  266. package/lib/typescript/organisms/header/header-inset.ios.d.ts +2 -0
  267. package/lib/typescript/organisms/header/header-options.d.ts +1 -0
  268. package/lib/typescript/organisms/header/header-options.ios.d.ts +2 -0
  269. package/lib/typescript/organisms/header/header-options.types.d.ts +4 -0
  270. package/lib/typescript/organisms/header/header-search-accessory.d.ts +1 -0
  271. package/lib/typescript/organisms/header/header-search-accessory.ios.d.ts +6 -0
  272. package/lib/typescript/organisms/header/header-search-accessory.types.d.ts +9 -0
  273. package/lib/typescript/organisms/header/header-search-input.d.ts +1 -0
  274. package/lib/typescript/organisms/header/header-search-input.ios.d.ts +5 -0
  275. package/lib/typescript/organisms/header/header-search-input.types.d.ts +17 -0
  276. package/lib/typescript/organisms/header/header-search-scrim.d.ts +11 -0
  277. package/lib/typescript/organisms/header/header-title.d.ts +22 -0
  278. package/lib/typescript/organisms/header/header.types.d.ts +440 -0
  279. package/lib/typescript/organisms/header/hero-header-background.d.ts +1 -0
  280. package/lib/typescript/organisms/header/hero-header-background.ios.d.ts +7 -0
  281. package/lib/typescript/organisms/header/hero-header-background.types.d.ts +9 -0
  282. package/lib/typescript/organisms/header/index.d.ts +11 -0
  283. package/lib/typescript/organisms/header/native-subtitle.d.ts +1 -0
  284. package/lib/typescript/organisms/header/native-subtitle.ios.d.ts +4 -0
  285. package/lib/typescript/organisms/header/native-subtitle.types.d.ts +6 -0
  286. package/lib/typescript/organisms/header/sheet-grabber.d.ts +1 -0
  287. package/lib/typescript/organisms/header/sheet-grabber.ios.d.ts +7 -0
  288. package/lib/typescript/organisms/header/sheet-grabber.types.d.ts +6 -0
  289. package/lib/typescript/organisms/header/use-header-bar-inset.d.ts +1 -0
  290. package/lib/typescript/organisms/header/use-header-bar-inset.ios.d.ts +1 -0
  291. package/lib/typescript/organisms/header/use-header-bar-inset.types.d.ts +6 -0
  292. package/lib/typescript/organisms/header/use-header-scroll-to-top.d.ts +8 -0
  293. package/lib/typescript/organisms/header/use-header-search.d.ts +12 -0
  294. package/lib/typescript/organisms/header/use-header.d.ts +14 -0
  295. package/lib/typescript/organisms/header/use-hero-header.d.ts +10 -0
  296. package/lib/typescript/organisms/header/use-stack-screen-options.d.ts +17 -0
  297. package/lib/typescript/templates/screen/screen.types.d.ts +6 -2
  298. package/package.json +24 -5
  299. package/src/atoms/activity-indicator/activity-indicator.android.tsx +1 -1
  300. package/src/atoms/activity-indicator/activity-indicator.ios.tsx +1 -1
  301. package/src/atoms/badge/badge.android.tsx +1 -1
  302. package/src/atoms/badge/badge.ios.tsx +1 -1
  303. package/src/atoms/blur-view/blur-view.android.tsx +28 -1
  304. package/src/atoms/blur-view/blur-view.ios.tsx +25 -0
  305. package/src/atoms/blur-view/blur-view.types.ts +8 -0
  306. package/src/atoms/button/button.android.tsx +1 -1
  307. package/src/atoms/button/button.ios.tsx +1 -1
  308. package/src/atoms/card/card.android.tsx +1 -1
  309. package/src/atoms/card/card.ios.tsx +1 -1
  310. package/src/atoms/checkbox/checkbox.android.tsx +1 -1
  311. package/src/atoms/checkbox/checkbox.ios.tsx +1 -1
  312. package/src/atoms/color-picker/color-picker.android.tsx +1 -1
  313. package/src/atoms/color-picker/color-picker.ios.tsx +1 -1
  314. package/src/atoms/date-picker/date-picker.android.tsx +1 -1
  315. package/src/atoms/date-picker/date-picker.ios.tsx +1 -1
  316. package/src/atoms/divider/divider.android.tsx +1 -1
  317. package/src/atoms/divider/divider.ios.tsx +1 -1
  318. package/src/atoms/fab/fab.android.tsx +1 -1
  319. package/src/atoms/fab/fab.ios.tsx +1 -1
  320. package/src/atoms/h-stack/h-stack.android.tsx +2 -2
  321. package/src/atoms/h-stack/h-stack.ios.tsx +2 -2
  322. package/src/atoms/icon/icon.android.tsx +1 -1
  323. package/src/atoms/icon/icon.ios.tsx +1 -1
  324. package/src/atoms/icon-button/icon-button.android.tsx +1 -1
  325. package/src/atoms/icon-button/icon-button.ios.tsx +1 -1
  326. package/src/atoms/island/island.android.tsx +3 -1
  327. package/src/atoms/island/island.ios.tsx +10 -2
  328. package/src/atoms/island/island.types.ts +18 -0
  329. package/src/atoms/list/list.android.tsx +2 -2
  330. package/src/atoms/list/list.ios.tsx +1 -1
  331. package/src/atoms/picker/picker.android.tsx +2 -3
  332. package/src/atoms/picker/picker.ios.tsx +1 -1
  333. package/src/atoms/pressable/pressable.tsx +1 -1
  334. package/src/atoms/progress/progress.android.tsx +1 -1
  335. package/src/atoms/progress/progress.ios.tsx +1 -1
  336. package/src/atoms/scroll-view/scroll-view.android.tsx +2 -2
  337. package/src/atoms/scroll-view/scroll-view.ios.tsx +1 -1
  338. package/src/atoms/segmented-control/segmented-control.android.tsx +1 -1
  339. package/src/atoms/segmented-control/segmented-control.ios.tsx +1 -1
  340. package/src/atoms/slider/slider.android.tsx +1 -1
  341. package/src/atoms/slider/slider.ios.tsx +1 -1
  342. package/src/atoms/spacer/spacer.android.tsx +1 -1
  343. package/src/atoms/spacer/spacer.ios.tsx +1 -1
  344. package/src/atoms/surface/surface.android.tsx +1 -1
  345. package/src/atoms/surface/surface.ios.tsx +1 -1
  346. package/src/atoms/switch/switch.android.tsx +1 -1
  347. package/src/atoms/switch/switch.ios.tsx +1 -1
  348. package/src/atoms/text/text.android.tsx +1 -1
  349. package/src/atoms/text/text.ios.tsx +1 -1
  350. package/src/atoms/text-field/text-field.android.tsx +2 -2
  351. package/src/atoms/text-field/text-field.ios.tsx +1 -1
  352. package/src/atoms/v-stack/v-stack.android.tsx +2 -2
  353. package/src/atoms/v-stack/v-stack.ios.tsx +2 -2
  354. package/src/atoms/z-stack/z-stack.android.tsx +2 -2
  355. package/src/atoms/z-stack/z-stack.ios.tsx +2 -2
  356. package/src/molecules/collapsible/collapsible.android.tsx +2 -2
  357. package/src/molecules/collapsible/collapsible.ios.tsx +1 -1
  358. package/src/molecules/labeled-content/labeled-content.tsx +1 -1
  359. package/src/molecules/list-item/list-item.tsx +1 -2
  360. package/src/molecules/navigation-bar/navigation-bar.constants.ts +2 -0
  361. package/src/molecules/navigation-bar/navigation-bar.ios.tsx +35 -5
  362. package/src/molecules/navigation-bar/navigation-bar.types.ts +69 -5
  363. package/src/molecules/pager/pager.android.tsx +1 -1
  364. package/src/molecules/pager/pager.ios.tsx +1 -1
  365. package/src/molecules/radio-group/radio-group.android.tsx +1 -1
  366. package/src/molecules/radio-group/radio-group.ios.tsx +2 -2
  367. package/src/molecules/rn-list-item/rn-list-item.tsx +1 -1
  368. package/src/molecules/rn-tooltip/rn-tooltip.android.tsx +1 -1
  369. package/src/molecules/search-bar/search-bar.tsx +1 -1
  370. package/src/molecules/stepper/stepper.android.tsx +2 -2
  371. package/src/molecules/stepper/stepper.ios.tsx +1 -1
  372. package/src/molecules/tooltip/tooltip.android.tsx +1 -1
  373. package/src/molecules/tooltip/tooltip.ios.tsx +1 -1
  374. package/src/organisms/action-sheet/action-sheet.android.tsx +1 -1
  375. package/src/organisms/action-sheet/action-sheet.ios.tsx +1 -1
  376. package/src/organisms/alert/alert.android.tsx +1 -1
  377. package/src/organisms/alert/alert.ios.tsx +1 -1
  378. package/src/organisms/context-menu/context-menu.android.tsx +2 -2
  379. package/src/organisms/fab-menu/fab-menu.android.tsx +2 -2
  380. package/src/organisms/fab-menu/fab-menu.ios.tsx +2 -3
  381. package/src/organisms/form/form.android.tsx +1 -1
  382. package/src/organisms/form/form.ios.tsx +1 -1
  383. package/src/organisms/header/header-color.ts +7 -0
  384. package/src/organisms/header/header-inset.android.tsx +3 -0
  385. package/src/organisms/header/header-inset.ios.tsx +12 -0
  386. package/src/organisms/header/header-options.android.tsx +168 -0
  387. package/src/organisms/header/header-options.ios.tsx +138 -0
  388. package/src/organisms/header/header-options.types.ts +6 -0
  389. package/src/organisms/header/header-search-accessory.android.tsx +4 -0
  390. package/src/organisms/header/header-search-accessory.ios.tsx +42 -0
  391. package/src/organisms/header/header-search-accessory.types.ts +12 -0
  392. package/src/organisms/header/header-search-input.android.tsx +89 -0
  393. package/src/organisms/header/header-search-input.ios.tsx +7 -0
  394. package/src/organisms/header/header-search-input.types.ts +21 -0
  395. package/src/organisms/header/header-search-scrim.tsx +49 -0
  396. package/src/organisms/header/header-title.tsx +220 -0
  397. package/src/organisms/header/header.types.ts +416 -0
  398. package/src/organisms/header/hero-header-background.android.tsx +22 -0
  399. package/src/organisms/header/hero-header-background.ios.tsx +26 -0
  400. package/src/organisms/header/hero-header-background.types.ts +11 -0
  401. package/src/organisms/header/index.ts +11 -0
  402. package/src/organisms/header/native-subtitle.android.tsx +5 -0
  403. package/src/organisms/header/native-subtitle.ios.tsx +22 -0
  404. package/src/organisms/header/native-subtitle.types.ts +8 -0
  405. package/src/organisms/header/sheet-grabber.android.tsx +4 -0
  406. package/src/organisms/header/sheet-grabber.ios.tsx +12 -0
  407. package/src/organisms/header/sheet-grabber.types.ts +8 -0
  408. package/src/organisms/header/use-header-bar-inset.android.ts +1 -0
  409. package/src/organisms/header/use-header-bar-inset.ios.ts +7 -0
  410. package/src/organisms/header/use-header-bar-inset.types.ts +6 -0
  411. package/src/organisms/header/use-header-scroll-to-top.ts +48 -0
  412. package/src/organisms/header/use-header-search.tsx +138 -0
  413. package/src/organisms/header/use-header.ts +67 -0
  414. package/src/organisms/header/use-hero-header.tsx +222 -0
  415. package/src/organisms/header/use-stack-screen-options.ts +66 -0
  416. package/src/organisms/menu/menu.android.tsx +2 -2
  417. package/src/organisms/menu/menu.ios.tsx +1 -1
  418. package/src/organisms/sheet/use-sheet-header.tsx +4 -1
  419. package/src/organisms/snackbar/snackbar.tsx +1 -1
  420. package/src/organisms/swipe-actions/swipe-actions.android.tsx +1 -1
  421. package/src/organisms/swipe-actions/swipe-actions.ios.tsx +1 -1
  422. package/src/templates/screen/screen.android.tsx +8 -3
  423. package/src/templates/screen/screen.ios.tsx +8 -3
  424. package/src/templates/screen/screen.types.ts +7 -2
  425. package/lib/module/glyph/glyph-button.android.js.map +0 -1
  426. package/lib/module/glyph/glyph-button.ios.js.map +0 -1
  427. package/lib/module/glyph/glyph-button.types.js.map +0 -1
  428. package/lib/module/glyph/glyph.android.js.map +0 -1
  429. package/lib/module/glyph/glyph.ios.js.map +0 -1
  430. package/lib/module/glyph/glyph.types.js.map +0 -1
  431. package/lib/module/glyph/index.js.map +0 -1
  432. package/lib/module/glyph/rn-glyph.android.js.map +0 -1
  433. package/lib/module/glyph/rn-glyph.ios.js.map +0 -1
  434. package/lib/module/host-context.js.map +0 -1
  435. package/lib/module/ripple-clip.js.map +0 -1
  436. package/lib/module/tap-modifiers.js.map +0 -1
  437. package/lib/module/use-refresh-state.js.map +0 -1
  438. package/lib/module/use-stack-modifiers.js.map +0 -1
  439. /package/lib/module/{glyph → atoms/glyph}/glyph-button.android.js +0 -0
  440. /package/lib/module/{glyph → atoms/glyph}/glyph-button.ios.js +0 -0
  441. /package/lib/module/{glyph → atoms/glyph}/glyph-button.types.js +0 -0
  442. /package/lib/module/{glyph → atoms/glyph}/glyph.android.js +0 -0
  443. /package/lib/module/{glyph → atoms/glyph}/glyph.ios.js +0 -0
  444. /package/lib/module/{glyph → atoms/glyph}/glyph.types.js +0 -0
  445. /package/lib/module/{glyph → atoms/glyph}/index.js +0 -0
  446. /package/lib/module/{glyph → atoms/glyph}/rn-glyph.android.js +0 -0
  447. /package/lib/module/{glyph → atoms/glyph}/rn-glyph.ios.js +0 -0
  448. /package/lib/module/{host-context.js → hooks/host-context.js} +0 -0
  449. /package/lib/module/{use-refresh-state.js → hooks/use-refresh-state.js} +0 -0
  450. /package/lib/module/{use-stack-modifiers.js → hooks/use-stack-modifiers.js} +0 -0
  451. /package/lib/module/{ripple-clip.js → utils/ripple-clip.js} +0 -0
  452. /package/lib/module/{tap-modifiers.js → utils/tap-modifiers.js} +0 -0
  453. /package/lib/typescript/{glyph → atoms/glyph}/glyph-button.d.ts +0 -0
  454. /package/lib/typescript/{glyph → atoms/glyph}/glyph-button.ios.d.ts +0 -0
  455. /package/lib/typescript/{glyph → atoms/glyph}/glyph-button.types.d.ts +0 -0
  456. /package/lib/typescript/{glyph → atoms/glyph}/glyph.d.ts +0 -0
  457. /package/lib/typescript/{glyph → atoms/glyph}/glyph.ios.d.ts +0 -0
  458. /package/lib/typescript/{glyph → atoms/glyph}/glyph.types.d.ts +0 -0
  459. /package/lib/typescript/{glyph → atoms/glyph}/index.d.ts +0 -0
  460. /package/lib/typescript/{glyph → atoms/glyph}/rn-glyph.d.ts +0 -0
  461. /package/lib/typescript/{glyph → atoms/glyph}/rn-glyph.ios.d.ts +0 -0
  462. /package/lib/typescript/{host-context.d.ts → hooks/host-context.d.ts} +0 -0
  463. /package/lib/typescript/{use-refresh-state.d.ts → hooks/use-refresh-state.d.ts} +0 -0
  464. /package/lib/typescript/{use-stack-modifiers.d.ts → hooks/use-stack-modifiers.d.ts} +0 -0
  465. /package/lib/typescript/{ripple-clip.d.ts → utils/ripple-clip.d.ts} +0 -0
  466. /package/lib/typescript/{tap-modifiers.d.ts → utils/tap-modifiers.d.ts} +0 -0
  467. /package/src/{glyph → atoms/glyph}/glyph-button.android.tsx +0 -0
  468. /package/src/{glyph → atoms/glyph}/glyph-button.ios.tsx +0 -0
  469. /package/src/{glyph → atoms/glyph}/glyph-button.types.ts +0 -0
  470. /package/src/{glyph → atoms/glyph}/glyph.android.tsx +0 -0
  471. /package/src/{glyph → atoms/glyph}/glyph.ios.tsx +0 -0
  472. /package/src/{glyph → atoms/glyph}/glyph.types.ts +0 -0
  473. /package/src/{glyph → atoms/glyph}/index.ts +0 -0
  474. /package/src/{glyph → atoms/glyph}/rn-glyph.android.tsx +0 -0
  475. /package/src/{glyph → atoms/glyph}/rn-glyph.ios.tsx +0 -0
  476. /package/src/{host-context.tsx → hooks/host-context.tsx} +0 -0
  477. /package/src/{use-refresh-state.ts → hooks/use-refresh-state.ts} +0 -0
  478. /package/src/{use-stack-modifiers.ts → hooks/use-stack-modifiers.ts} +0 -0
  479. /package/src/{ripple-clip.ts → utils/ripple-clip.ts} +0 -0
  480. /package/src/{tap-modifiers.ts → utils/tap-modifiers.ts} +0 -0
@@ -0,0 +1,220 @@
1
+ import {type ReactNode, useCallback, useMemo, useState} from 'react'
2
+ import {type LayoutChangeEvent, Platform, StyleSheet, useWindowDimensions, View} from 'react-native'
3
+ import Animated, {
4
+ Extrapolation,
5
+ interpolate,
6
+ type SharedValue,
7
+ useAnimatedReaction,
8
+ useAnimatedStyle,
9
+ useDerivedValue,
10
+ useSharedValue,
11
+ } from 'react-native-reanimated'
12
+ import {scheduleOnRN} from 'react-native-worklets'
13
+
14
+ import {RnText} from '../../atoms/rn-text'
15
+ import type {HeaderOptions} from './header.types'
16
+ import {hasNativeSubtitle, NativeSubtitle} from './native-subtitle'
17
+
18
+ /** Past half, a revealed title counts as shown: the native title and subtitle switch then. */
19
+ const REVEALED_THRESHOLD = 0.5
20
+
21
+ /** iOS centres a custom title view in what the bar items leave; this much stays for them on a leading title. */
22
+ const LEADING_TITLE_RESERVED_WIDTH = 200
23
+
24
+ const styles = StyleSheet.create({
25
+ largeTitle: {paddingHorizontal: 16, paddingVertical: 8},
26
+ leadingTitleAndroid: {paddingStart: 2, paddingTop: 1},
27
+ leadingTitleIos: {flexShrink: 1, paddingTop: 1},
28
+ shrink: {flexShrink: 1},
29
+ })
30
+
31
+ export const useIsTitleRevealed = (progress?: SharedValue<number>) => {
32
+ const [revealed, setRevealed] = useState(() => progress === undefined || progress.value > REVEALED_THRESHOLD)
33
+
34
+ useAnimatedReaction(
35
+ () => progress === undefined || progress.value > REVEALED_THRESHOLD,
36
+ (isRevealed, wasRevealed) => {
37
+ if (isRevealed !== wasRevealed) {
38
+ scheduleOnRN(setRevealed, isRevealed)
39
+ }
40
+ }
41
+ )
42
+
43
+ return revealed
44
+ }
45
+
46
+ const Reveal = ({children, progress}: {children: ReactNode; progress: SharedValue<number>}) => {
47
+ const animatedStyle = useAnimatedStyle(() => ({opacity: progress.value}))
48
+
49
+ return <Animated.View style={[styles.shrink, animatedStyle]}>{children}</Animated.View>
50
+ }
51
+
52
+ const BarTitle = ({title}: {title: string}) => (
53
+ <RnText accessibilityRole="header" allowFontScaling={false} numberOfLines={1} variant="headline">
54
+ {title}
55
+ </RnText>
56
+ )
57
+
58
+ const LeadingTitle = ({subtitle, title}: {subtitle: string; title: string}) => {
59
+ const {width} = useWindowDimensions()
60
+ const content = (
61
+ <>
62
+ <RnText accessibilityRole="header" allowFontScaling={false} numberOfLines={1} variant="subheadlineMedium">
63
+ {title}
64
+ </RnText>
65
+ <RnText allowFontScaling={false} color="content.secondary" numberOfLines={1} variant="label">
66
+ {subtitle}
67
+ </RnText>
68
+ </>
69
+ )
70
+
71
+ if (Platform.OS === 'ios') {
72
+ return (
73
+ <View style={[styles.leadingTitleIos, {width}]}>
74
+ <View style={{maxWidth: width - LEADING_TITLE_RESERVED_WIDTH}}>{content}</View>
75
+ </View>
76
+ )
77
+ }
78
+
79
+ return <View style={[styles.leadingTitleAndroid, {maxWidth: width - LEADING_TITLE_RESERVED_WIDTH}]}>{content}</View>
80
+ }
81
+
82
+ const LargeTitle = ({height, title}: {height: SharedValue<number>; title: string}) => {
83
+ const onLayout = useCallback(
84
+ (event: LayoutChangeEvent) => {
85
+ height.value = event.nativeEvent.layout.height
86
+ },
87
+ [height]
88
+ )
89
+
90
+ return (
91
+ <View onLayout={onLayout} style={styles.largeTitle}>
92
+ <RnText accessibilityRole="header" allowFontScaling={false} numberOfLines={1} variant="headingM">
93
+ {title}
94
+ </RnText>
95
+ </View>
96
+ )
97
+ }
98
+
99
+ const CollapsingTitle = ({
100
+ height,
101
+ scrollY,
102
+ title,
103
+ }: {
104
+ height: SharedValue<number>
105
+ scrollY: SharedValue<number>
106
+ title: string
107
+ }) => {
108
+ const progress = useDerivedValue(() => {
109
+ if (height.value === 0) {
110
+ return 0
111
+ }
112
+
113
+ return interpolate(scrollY.value, [height.value / 2, height.value], [0, 1], Extrapolation.CLAMP)
114
+ })
115
+
116
+ return (
117
+ <Reveal progress={progress}>
118
+ <BarTitle title={title} />
119
+ </Reveal>
120
+ )
121
+ }
122
+
123
+ type TitleParams = {
124
+ largeTitle?: boolean
125
+ subtitle?: string
126
+ title?: string
127
+ titleHidden: boolean
128
+ titleRevealProgress?: SharedValue<number>
129
+ }
130
+
131
+ /**
132
+ * The title half of a header: the options that show the title (centred, leading with a subtitle, revealed on scroll or
133
+ * large), plus on Android the large title row and the scroll worklet that collapses it into the bar, as Material's large
134
+ * top app bar does. iOS needs neither: the large title is UIKit's own.
135
+ */
136
+ export const useHeaderTitle = ({largeTitle, subtitle, title, titleHidden, titleRevealProgress}: TitleParams) => {
137
+ const scrollY = useSharedValue(0)
138
+ const largeTitleHeight = useSharedValue(0)
139
+ const revealed = useIsTitleRevealed(titleRevealProgress)
140
+ const isAndroidLargeTitle = Platform.OS === 'android' && largeTitle === true && !!title
141
+
142
+ const onScroll = useCallback(
143
+ (offsetY: number) => {
144
+ 'worklet'
145
+ scrollY.value = offsetY
146
+ },
147
+ [scrollY]
148
+ )
149
+
150
+ const options = useMemo((): HeaderOptions => {
151
+ const titleOptions: HeaderOptions = {}
152
+
153
+ if (largeTitle !== undefined) {
154
+ titleOptions.headerLargeTitleEnabled = Platform.OS === 'ios' && largeTitle
155
+ }
156
+
157
+ if (title === undefined) {
158
+ return titleOptions
159
+ }
160
+
161
+ titleOptions.title = title
162
+
163
+ if (titleHidden) {
164
+ titleOptions.headerTitle = ''
165
+ return titleOptions
166
+ }
167
+
168
+ if (subtitle !== undefined && hasNativeSubtitle) {
169
+ const shownTitle = revealed ? title : ''
170
+
171
+ // The subtitle styles the screen's navigation item from inside its tree, which `headerBackground` is.
172
+ titleOptions.headerBackground = () => <NativeSubtitle subtitle={subtitle} subtitleHidden={!revealed} />
173
+ titleOptions.headerTitle = shownTitle
174
+ titleOptions.title = shownTitle
175
+ return titleOptions
176
+ }
177
+
178
+ if (subtitle !== undefined) {
179
+ const leadingTitle = <LeadingTitle subtitle={subtitle} title={title} />
180
+
181
+ titleOptions.headerTitle = () =>
182
+ titleRevealProgress ? <Reveal progress={titleRevealProgress}>{leadingTitle}</Reveal> : leadingTitle
183
+ return titleOptions
184
+ }
185
+
186
+ if (titleRevealProgress) {
187
+ titleOptions.headerTitle = () => (
188
+ <Reveal progress={titleRevealProgress}>
189
+ <BarTitle title={title} />
190
+ </Reveal>
191
+ )
192
+ return titleOptions
193
+ }
194
+
195
+ if (isAndroidLargeTitle) {
196
+ titleOptions.headerTitle = () => <CollapsingTitle height={largeTitleHeight} scrollY={scrollY} title={title} />
197
+ return titleOptions
198
+ }
199
+
200
+ titleOptions.headerTitle = title
201
+ return titleOptions
202
+ }, [
203
+ isAndroidLargeTitle,
204
+ largeTitle,
205
+ largeTitleHeight,
206
+ revealed,
207
+ scrollY,
208
+ subtitle,
209
+ title,
210
+ titleHidden,
211
+ titleRevealProgress,
212
+ ])
213
+
214
+ const largeTitleRow = useMemo(
215
+ () => (isAndroidLargeTitle && title ? <LargeTitle height={largeTitleHeight} title={title} /> : null),
216
+ [isAndroidLargeTitle, largeTitleHeight, title]
217
+ )
218
+
219
+ return {largeTitle: largeTitleRow, onScroll, options, revealed}
220
+ }
@@ -0,0 +1,416 @@
1
+ import type {ColorToken} from '@hzblj/kara-theme'
2
+ import type {ReactElement, ReactNode, RefObject} from 'react'
3
+ import type {ColorValue, ImageSourcePropType} from 'react-native'
4
+ import type {SharedValue} from 'react-native-reanimated'
5
+ import type {SearchBarCommands} from 'react-native-screens'
6
+ import type {SFSymbol} from 'sf-symbols-typescript'
7
+
8
+ import type {IconName} from '../../atoms/icon'
9
+ import type {SearchFieldVoice} from '../../molecules/navigation-bar/navigation-bar.types'
10
+
11
+ type HeaderActionBase = {
12
+ /**
13
+ * iOS 26: neighbouring actions on one side share a glass capsule; this gives the action its own. A close next to
14
+ * other actions usually wants it. Material has no grouped capsules, so Android ignores it.
15
+ */
16
+ separated?: boolean
17
+ /** iOS: the bar item's `identifier`, which UI tests match; Android: the button's test tag. */
18
+ testID?: string
19
+ }
20
+
21
+ /**
22
+ * The platform's own back or close: a chevron or a cross (an SF Symbol on iOS, a Material Symbol on Android), named
23
+ * `Back` / `Close` for VoiceOver and TalkBack unless given another label. `icon` puts one of the app's icons in their
24
+ * place.
25
+ */
26
+ export type HeaderNavigationAction = HeaderActionBase & {
27
+ /** One of the app's icons in place of the platform's glyph. */
28
+ icon?: IconName
29
+ /** What VoiceOver and TalkBack say. `Back` or `Close` by default. */
30
+ label?: string
31
+ /** Called when the action is pressed. */
32
+ onPress: () => void
33
+ type: 'back' | 'close'
34
+ }
35
+
36
+ /** An action drawn as one of the app's icons. */
37
+ export type HeaderIconAction = HeaderActionBase & {
38
+ /** iOS 26: a badge on the item, a count or a short text. Android ignores it. */
39
+ badge?: number | string
40
+ /** The icon's colour. The header's own tint by default. */
41
+ color?: ColorToken
42
+ /** Dims the action and stops it responding. */
43
+ disabled?: boolean
44
+ /** One of the app's icons. */
45
+ icon: IconName
46
+ /**
47
+ * What VoiceOver and TalkBack say, since an icon has no words of its own, and the row iOS 26 shows when the items no
48
+ * longer fit and collapse into its overflow menu.
49
+ */
50
+ label: string
51
+ /** Shows a spinner in the action's place while what it started is still running. */
52
+ loading?: boolean
53
+ /** Called when the action is pressed. */
54
+ onPress: () => void
55
+ /** iOS: draws the item in its selected state. Android ignores it. */
56
+ selected?: boolean
57
+ type: 'icon'
58
+ }
59
+
60
+ /** An action drawn as its label: "Edit", "Done". */
61
+ export type HeaderTextAction = HeaderActionBase & {
62
+ /** Dims the action and stops it responding. */
63
+ disabled?: boolean
64
+ /** The action's text. */
65
+ label: string
66
+ /** Called when the action is pressed. */
67
+ onPress: () => void
68
+ /** iOS: the prominent style, filled on iOS 26. Android ignores it. */
69
+ prominent?: boolean
70
+ type: 'text'
71
+ }
72
+
73
+ /** One row of a header menu. */
74
+ export type HeaderMenuAction = {
75
+ /** iOS: a checkmark before the row, for a menu that picks one of several. Android ignores it. */
76
+ checked?: boolean
77
+ /** iOS: a second line under the label. Android ignores it. */
78
+ description?: string
79
+ /** Draws the row in the destructive colour. */
80
+ destructive?: boolean
81
+ /** Greys the row out and stops it responding. */
82
+ disabled?: boolean
83
+ /** One of the app's icons, beside the label. */
84
+ icon?: IconName
85
+ /** The row's text. */
86
+ label: string
87
+ /** Called when the row is chosen; the menu closes by itself. */
88
+ onPress: () => void
89
+ type: 'action'
90
+ }
91
+
92
+ /**
93
+ * A group of rows: on iOS a nested menu, or with `inline` a section of its parent. Android's dropdown has no nesting,
94
+ * so it lists the group's rows in place.
95
+ */
96
+ export type HeaderSubmenu = {
97
+ /** iOS: one of the app's icons beside the group's label. */
98
+ icon?: IconName
99
+ /** iOS: shows the rows as a section of the parent menu instead of behind a row of their own. */
100
+ inline?: boolean
101
+ /** The group's rows, top to bottom. */
102
+ items: HeaderMenuItem[]
103
+ /** The group's label. */
104
+ label: string
105
+ type: 'submenu'
106
+ }
107
+
108
+ export type HeaderMenuItem = HeaderMenuAction | HeaderSubmenu
109
+
110
+ /** An icon that opens a menu: a `UIMenu` from the bar item on iOS, a Material dropdown under it on Android. */
111
+ export type HeaderMenu = HeaderActionBase & {
112
+ /** One of the app's icons on the item. */
113
+ icon: IconName
114
+ /** The menu's rows, top to bottom. */
115
+ items: HeaderMenuItem[]
116
+ /** What VoiceOver and TalkBack say for the item: "More options". */
117
+ label: string
118
+ /** iOS: a title above the rows. Android ignores it. */
119
+ title?: string
120
+ type: 'menu'
121
+ }
122
+
123
+ /** Any React Native element in the header, for what the other actions cannot draw: an avatar, a count. */
124
+ export type HeaderCustomAction = {
125
+ /** The element, laid out at its own size. */
126
+ element: ReactElement
127
+ /** Identifies the element among the side's actions. */
128
+ key: string
129
+ /** iOS 26: keeps the element apart from its neighbours' shared glass. Android ignores it. */
130
+ separated?: boolean
131
+ type: 'custom'
132
+ }
133
+
134
+ /**
135
+ * One action of a screen's header. iOS draws them as the navigation bar's own `UIBarButtonItem`s (the same glass,
136
+ * press and overflow menu as the system's), Android as Material icon and text buttons in the top app bar.
137
+ */
138
+ export type HeaderAction =
139
+ | HeaderCustomAction
140
+ | HeaderIconAction
141
+ | HeaderMenu
142
+ | HeaderNavigationAction
143
+ | HeaderTextAction
144
+
145
+ export type HeaderParams = {
146
+ /**
147
+ * Hides the stack's own back button. On Android a trailing `close` then takes the navigation icon's place at the
148
+ * start, as Material's full-screen dialogs have it, unless there are leading actions.
149
+ */
150
+ backHidden?: boolean
151
+ /**
152
+ * A large title that collapses into the bar as the list scrolls. iOS draws UIKit's own; Android, where the native
153
+ * stack has none, puts it into the content as the list's first row (`largeTitle` in the result) and fades the bar's
154
+ * title in once that row has scrolled away, as Material's large top app bar does. Wire `onScroll` for it.
155
+ */
156
+ largeTitle?: boolean
157
+ /**
158
+ * The leading side's actions, in screen order from the edge. On iOS they follow the back button. Unset leaves the
159
+ * side as the stack's options have it; an empty array clears it.
160
+ */
161
+ leadingActions?: HeaderAction[]
162
+ /**
163
+ * A search field in the header, from `useHeaderSearch`: UIKit's search bar under the title on iOS. Android has no
164
+ * field in its top app bar, so `useHeaderSearch` gives the screen a row of its own to put under it.
165
+ */
166
+ search?: HeaderSearchBarOptions
167
+ /**
168
+ * A line under the title, both on the leading side. iOS 26 sets it as the navigation item's own subtitle, which
169
+ * truncates and morphs between screens natively; elsewhere a title and subtitle are drawn in the bar.
170
+ */
171
+ subtitle?: string
172
+ /** The screen's title, in the bar. */
173
+ title?: string
174
+ /** Keeps the bar without a title, for a screen that draws its own under it. */
175
+ titleHidden?: boolean
176
+ /**
177
+ * Fades the title (and subtitle) in as this goes from 0 to 1, for a detail screen whose title appears once its image
178
+ * has scrolled away. Past half, iOS 26 switches its native title and subtitle on with a cross-dissolve.
179
+ */
180
+ titleRevealProgress?: SharedValue<number>
181
+ /**
182
+ * The trailing side's actions, in screen order toward the edge: the close usually last. Unset leaves the side as the
183
+ * stack's options have it; an empty array clears it.
184
+ */
185
+ trailingActions?: HeaderAction[]
186
+ }
187
+
188
+ type NativeHeaderItemIcon = {name: SFSymbol; type: 'sfSymbol'} | {source: ImageSourcePropType; type: 'image'}
189
+
190
+ type NativeHeaderItemShared = {
191
+ accessibilityLabel?: string
192
+ badge?: {value: number | string}
193
+ disabled?: boolean
194
+ icon?: NativeHeaderItemIcon
195
+ identifier?: string
196
+ label: string
197
+ sharesBackground?: boolean
198
+ tintColor?: ColorValue
199
+ variant?: 'done' | 'plain' | 'prominent'
200
+ }
201
+
202
+ export type NativeHeaderMenuElement =
203
+ | {
204
+ description?: string
205
+ destructive?: boolean
206
+ disabled?: boolean
207
+ icon?: NativeHeaderItemIcon
208
+ label: string
209
+ onPress: () => void
210
+ state?: 'mixed' | 'off' | 'on'
211
+ type: 'action'
212
+ }
213
+ | {icon?: NativeHeaderItemIcon; inline?: boolean; items: NativeHeaderMenuElement[]; label: string; type: 'submenu'}
214
+
215
+ /** A native-stack header item, the shape React Navigation's and Expo Router's native stacks both take. */
216
+ export type NativeHeaderItem =
217
+ | (NativeHeaderItemShared & {menu: {items: NativeHeaderMenuElement[]; title?: string}; type: 'menu'})
218
+ | (NativeHeaderItemShared & {onPress: () => void; selected?: boolean; type: 'button'})
219
+ | {element: ReactElement; hidesSharedBackground?: boolean; type: 'custom'}
220
+ | {spacing: number; type: 'spacing'}
221
+
222
+ export type HeaderItemProps = {
223
+ /** Whether the stack can go back from this screen. */
224
+ canGoBack?: boolean
225
+ /** The header's tint. */
226
+ tintColor?: ColorValue
227
+ }
228
+
229
+ /**
230
+ * Native-stack screen options, as React Navigation's native stack and Expo Router's `Stack` both take them: spread them
231
+ * into `options`, or hand them to `navigation.setOptions`.
232
+ */
233
+ export type HeaderOptions = {
234
+ headerBackground?: () => ReactNode
235
+ headerBackVisible?: boolean
236
+ headerBlurEffect?: 'none' | 'systemChromeMaterial'
237
+ headerLargeTitleEnabled?: boolean
238
+ headerLeft?: (props: HeaderItemProps) => ReactNode
239
+ headerRight?: (props: HeaderItemProps) => ReactNode
240
+ headerSearchBarOptions?: HeaderSearchBarOptions
241
+ headerShown?: boolean
242
+ headerStyle?: {backgroundColor?: string}
243
+ headerTintColor?: string
244
+ headerTitle?: string | (() => ReactNode)
245
+ headerTransparent?: boolean
246
+ scrollEdgeEffects?: {top?: 'automatic' | 'hidden'}
247
+ statusBarStyle?: 'auto' | 'dark' | 'light'
248
+ title?: string
249
+ unstable_headerLeftItems?: (props: HeaderItemProps) => NativeHeaderItem[]
250
+ unstable_headerRightItems?: (props: HeaderItemProps) => NativeHeaderItem[]
251
+ }
252
+
253
+ /** What a list under the header needs from it. */
254
+ export type HeaderContent = {
255
+ /**
256
+ * Hand it to the list: `automatic` lets iOS inset the content under its transparent bar, `never` (a hero header)
257
+ * lets the content run under it.
258
+ */
259
+ contentInsetAdjustmentBehavior: 'automatic' | 'never'
260
+ /** Android, with `largeTitle`: the large title, to render as the list's first row. `null` everywhere else. */
261
+ largeTitle: ReactElement | null
262
+ /** A worklet to call with the list's vertical offset from its scroll handler, for what follows the scroll. */
263
+ onScroll: (offsetY: number) => void
264
+ }
265
+
266
+ /** `HeaderContent` plus the options, for a screen that sets them itself (Expo Router's `<Stack.Screen options>`). */
267
+ export type HeaderOptionsResult = HeaderContent & {
268
+ options: HeaderOptions
269
+ }
270
+
271
+ /** UIKit's search bar options, as the native stack takes them (`headerSearchBarOptions`). */
272
+ export type HeaderSearchBarOptions = {
273
+ allowToolbarIntegration?: boolean
274
+ autoCapitalize?: 'characters' | 'none' | 'sentences' | 'words'
275
+ hideNavigationBar?: boolean
276
+ hideWhenScrolling?: boolean
277
+ obscureBackground?: boolean
278
+ onBlur?: () => void
279
+ onCancelButtonPress?: () => void
280
+ onChangeText?: (event: {nativeEvent: {text: string}}) => void
281
+ onFocus?: () => void
282
+ placeholder?: string
283
+ placement?: 'automatic' | 'inline' | 'integrated' | 'integratedButton' | 'integratedCentered' | 'stacked'
284
+ ref?: RefObject<SearchBarCommands | null>
285
+ tintColor?: string
286
+ }
287
+
288
+ /**
289
+ * Where the search goes on iOS: `stacked` in a row under the title (title and items kept); `integratedButton` as a
290
+ * search button in the bar's trailing corner that opens the field in the bar, the title and items hidden meanwhile.
291
+ * The integrated field's close is the system's: iOS gives it no other glyph.
292
+ */
293
+ export type HeaderSearchPlacement = 'integratedButton' | 'stacked'
294
+
295
+ export type HeaderSearchParams = {
296
+ /** iOS: the cancel circle beside a focused stacked field (iOS 26), one of the app's icons; the system cross unset. */
297
+ cancelIcon?: IconName
298
+ /** The field's clear button, one of the app's icons; the platform's unset. */
299
+ clearIcon?: IconName
300
+ /** Off leaves the header without a field, for a screen that searches only sometimes. On by default. */
301
+ enabled?: boolean
302
+ /** Shown while the field is empty. `Search` by default. */
303
+ placeholder?: string
304
+ /** iOS: `stacked` by default. Android always puts its field in a row under the bar. */
305
+ placement?: HeaderSearchPlacement
306
+ /** A microphone in the field: see `SearchFieldVoice`. Write what it hears with `setText`. */
307
+ voice?: SearchFieldVoice
308
+ }
309
+
310
+ /**
311
+ * A header's search: what to give `useHeader` (`searchBar`, iOS), the row Android puts under its bar (`searchInput`),
312
+ * the scrim that washes the content out while the field is focused and empty (render it last, over the content), and
313
+ * the query to filter by.
314
+ */
315
+ export type HeaderSearch = {
316
+ /** Empties the field and ends the search. */
317
+ clear: () => void
318
+ /** The field's text. */
319
+ query: string
320
+ /**
321
+ * Over the content while the field is focused and empty; a tap on it ends the search. On iOS it also carries the
322
+ * field's glyphs and voice, which have to sit in the screen's tree. Render it last.
323
+ */
324
+ scrim: ReactElement | null
325
+ /** Android: the Material search field, a row to put right under the bar. `null` on iOS. */
326
+ searchInput: ReactElement | null
327
+ /** iOS: `search` for `useHeader`. `undefined` on Android. */
328
+ searchBar: HeaderSearchBarOptions | undefined
329
+ /** Puts text into the field and the query, the way dictation fills it in. */
330
+ setText: (text: string) => void
331
+ }
332
+
333
+ /** Whether the header over a hero is light (over a dark image) or dark (over a light one). */
334
+ export type HeroHeaderStyle = 'dark' | 'light'
335
+
336
+ export type HeroHeaderParams = Pick<HeaderParams, 'backHidden' | 'leadingActions' | 'subtitle' | 'trailingActions'> & {
337
+ /** The hero's height: the header fades in while the part of it under the bar scrolls away. */
338
+ heroHeight: number
339
+ /**
340
+ * Holds the header in its revealed look while above 0, for a hero that opens with an intro (the bar's background, tint
341
+ * and status bar; the title and the trailing actions follow the scroll alone).
342
+ */
343
+ introProgress?: SharedValue<number>
344
+ /** The items and status bar over the hero. `light` (over a dark image) by default. */
345
+ overHeroStyle?: HeroHeaderStyle
346
+ /** Trailing actions that join the bar, in front of `trailingActions`, once the title is revealed. */
347
+ revealedTrailingActions?: HeaderAction[]
348
+ /** The screen's title, revealed in the bar once the hero has scrolled away. */
349
+ title: string
350
+ }
351
+
352
+ /** A hero header: a transparent bar over a full-bleed image that fades in as the image scrolls away. */
353
+ export type HeroHeader = HeaderContent & {
354
+ /**
355
+ * The bar's background below iOS 26 and on Android, and the status bar over the hero. Render it after the list.
356
+ */
357
+ background: ReactElement
358
+ /** How far the header has faded in, intro included: 0 over the hero, 1 revealed. */
359
+ progress: SharedValue<number>
360
+ /** The same from the scroll alone, without the intro. */
361
+ scrollProgress: SharedValue<number>
362
+ }
363
+
364
+ /**
365
+ * What `useHeroHeader` needs of a screen's navigation object, React Navigation's and Expo Router's `useNavigation()`
366
+ * both: setting options, and whether the screen is focused, so its status bar applies to it alone.
367
+ */
368
+ export type HeroHeaderNavigation = HeaderNavigation & {
369
+ addListener(event: 'blur' | 'focus', callback: () => void): () => void
370
+ isFocused(): boolean
371
+ }
372
+
373
+ /** A native stack's screen options, as React Navigation's native stack and Expo Router's `Stack` both take them. */
374
+ export type StackScreenOptions = {
375
+ contentStyle?: {backgroundColor?: string}
376
+ headerBackButtonDisplayMode?: 'default' | 'generic' | 'minimal'
377
+ headerBlurEffect?: 'none' | 'systemChromeMaterial'
378
+ headerLargeTitleEnabled?: boolean
379
+ headerLargeTitleShadowVisible?: boolean
380
+ headerLargeTitleStyle?: {color?: string; fontFamily?: string; fontSize?: number}
381
+ headerShadowVisible?: boolean
382
+ headerShown?: boolean
383
+ headerStyle?: {backgroundColor?: string}
384
+ headerTintColor?: string
385
+ headerTitleStyle?: {color?: string; fontFamily?: string; fontSize?: number}
386
+ headerTransparent?: boolean
387
+ scrollEdgeEffects?: {top?: 'automatic' | 'hidden'}
388
+ }
389
+
390
+ /** What `useHeader` needs of a screen's navigation object: React Navigation's and Expo Router's `useNavigation()` both. */
391
+ export type HeaderNavigation = {
392
+ setOptions(options: HeaderOptions): void
393
+ }
394
+
395
+ /** Something a list can scroll with: a `ScrollView`, a `FlatList`, a `FlashList` or a `LegendList`. */
396
+ export type HeaderScrollable =
397
+ | {getScrollResponder: () => {scrollTo: (options: {animated?: boolean; y?: number}) => void} | null | undefined}
398
+ | {scrollTo: (options: {animated?: boolean; y?: number}) => void}
399
+ | {scrollToOffset: (params: {animated?: boolean; offset: number}) => void}
400
+
401
+ export type HeaderScrollToTopOptions = {
402
+ /** Whether the screen has a large title, which the top includes on iOS. */
403
+ largeTitle?: boolean
404
+ /** Extra room above the content, for a bar the screen lays out under the header itself. */
405
+ topInset?: number
406
+ }
407
+
408
+ /** What React Navigation's and Expo Router's `useScrollToTop` call when its tab is pressed again. */
409
+ export type HeaderScrollToTopRef = RefObject<{scrollToTop: () => void}>
410
+
411
+ export type HeaderInsetProps = {
412
+ /** The content that starts right under the header. */
413
+ children?: ReactNode
414
+ }
415
+
416
+ export type HeaderInsetComponent = (props: HeaderInsetProps) => ReactNode
@@ -0,0 +1,22 @@
1
+ import {useAppTheme} from '@hzblj/kara-theme'
2
+ import {StyleSheet} from 'react-native'
3
+ import Animated, {useAnimatedStyle} from 'react-native-reanimated'
4
+
5
+ import type {HeroHeaderBackgroundComponent, HeroHeaderBackgroundProps} from './hero-header-background.types'
6
+
7
+ const styles = StyleSheet.create({
8
+ bar: {left: 0, position: 'absolute', right: 0, top: 0},
9
+ })
10
+
11
+ /** The top app bar's surface, fading in behind the transparent bar as the hero scrolls away. */
12
+ export const HeroHeaderBackground: HeroHeaderBackgroundComponent = ({height, progress}: HeroHeaderBackgroundProps) => {
13
+ const theme = useAppTheme()
14
+ const animatedStyle = useAnimatedStyle(() => ({opacity: progress.value}))
15
+
16
+ return (
17
+ <Animated.View
18
+ pointerEvents="none"
19
+ style={[styles.bar, {backgroundColor: theme.color('surface.base'), height}, animatedStyle]}
20
+ />
21
+ )
22
+ }
@@ -0,0 +1,26 @@
1
+ import {isScrollEdgeEffectAvailable} from '@hzblj/kara-native'
2
+ import {StyleSheet, View} from 'react-native'
3
+
4
+ import {BlurView} from '../../atoms/blur-view'
5
+ import type {HeroHeaderBackgroundComponent, HeroHeaderBackgroundProps} from './hero-header-background.types'
6
+
7
+ const styles = StyleSheet.create({
8
+ bar: {left: 0, position: 'absolute', right: 0, top: 0},
9
+ })
10
+
11
+ /**
12
+ * iOS 26 draws the bar's background itself: its scroll edge effect, switched on once the reveal starts. Before it the
13
+ * bar's own blur cannot fade, so the bar's chrome material comes in behind the transparent bar by its intensity, the
14
+ * way UIKit fades a material in, rather than by its opacity.
15
+ */
16
+ export const HeroHeaderBackground: HeroHeaderBackgroundComponent = ({height, progress}: HeroHeaderBackgroundProps) => {
17
+ if (isScrollEdgeEffectAvailable()) {
18
+ return null
19
+ }
20
+
21
+ return (
22
+ <View pointerEvents="none" style={[styles.bar, {height}]}>
23
+ <BlurView flex={1} intensity={progress} material="ultraThick" />
24
+ </View>
25
+ )
26
+ }