panelui-native 0.71.0 → 0.75.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 (306) hide show
  1. package/README.md +5 -2
  2. package/lib/module/components/accordion/index.js +10 -4
  3. package/lib/module/components/accordion/index.js.map +1 -1
  4. package/lib/module/components/area-chart/index.js +1 -0
  5. package/lib/module/components/area-chart/index.js.map +1 -1
  6. package/lib/module/components/avatar/avatar-group.js +64 -0
  7. package/lib/module/components/avatar/avatar-group.js.map +1 -0
  8. package/lib/module/components/avatar/index.js +84 -2
  9. package/lib/module/components/avatar/index.js.map +1 -1
  10. package/lib/module/components/breadcrumb/index.js +2 -1
  11. package/lib/module/components/breadcrumb/index.js.map +1 -1
  12. package/lib/module/components/button/index.js +7 -5
  13. package/lib/module/components/button/index.js.map +1 -1
  14. package/lib/module/components/carousel/index.js +1 -1
  15. package/lib/module/components/carousel/index.js.map +1 -1
  16. package/lib/module/components/chip/index.js +2 -2
  17. package/lib/module/components/chip/index.js.map +1 -1
  18. package/lib/module/components/code-block/index.js.map +1 -1
  19. package/lib/module/components/collapsible/index.js +5 -1
  20. package/lib/module/components/collapsible/index.js.map +1 -1
  21. package/lib/module/components/color-picker/color-picker-accessibility.js +12 -0
  22. package/lib/module/components/color-picker/color-picker-accessibility.js.map +1 -0
  23. package/lib/module/components/color-picker/index.js +9 -5
  24. package/lib/module/components/color-picker/index.js.map +1 -1
  25. package/lib/module/components/date-time-picker/index.js +11 -3
  26. package/lib/module/components/date-time-picker/index.js.map +1 -1
  27. package/lib/module/components/drawer/index.js +58 -13
  28. package/lib/module/components/drawer/index.js.map +1 -1
  29. package/lib/module/components/fab/index.js +7 -6
  30. package/lib/module/components/fab/index.js.map +1 -1
  31. package/lib/module/components/flow/index.js +1 -1
  32. package/lib/module/components/flow/index.js.map +1 -1
  33. package/lib/module/components/frame/index.js +2 -2
  34. package/lib/module/components/frame/index.js.map +1 -1
  35. package/lib/module/components/grid-item/index.js +2 -2
  36. package/lib/module/components/grid-item/index.js.map +1 -1
  37. package/lib/module/components/heatmap-chart/index.js +1 -0
  38. package/lib/module/components/heatmap-chart/index.js.map +1 -1
  39. package/lib/module/components/hex-chart/index.js +1 -0
  40. package/lib/module/components/hex-chart/index.js.map +1 -1
  41. package/lib/module/components/input/index.js +7 -4
  42. package/lib/module/components/input/index.js.map +1 -1
  43. package/lib/module/components/input/input-content-padding.js +6 -0
  44. package/lib/module/components/input/input-content-padding.js.map +1 -0
  45. package/lib/module/components/input-group/index.js +21 -11
  46. package/lib/module/components/input-group/index.js.map +1 -1
  47. package/lib/module/components/input-group/input-group-measurements.js +60 -0
  48. package/lib/module/components/input-group/input-group-measurements.js.map +1 -0
  49. package/lib/module/components/item/index.js +2 -2
  50. package/lib/module/components/item/index.js.map +1 -1
  51. package/lib/module/components/line-chart/index.js +1 -0
  52. package/lib/module/components/line-chart/index.js.map +1 -1
  53. package/lib/module/components/marker/index.js +2 -2
  54. package/lib/module/components/marker/index.js.map +1 -1
  55. package/lib/module/components/marquee/index.js +9 -12
  56. package/lib/module/components/marquee/index.js.map +1 -1
  57. package/lib/module/components/marquee/marquee-math.js +39 -0
  58. package/lib/module/components/marquee/marquee-math.js.map +1 -0
  59. package/lib/module/components/menu/index.js +11 -3
  60. package/lib/module/components/menu/index.js.map +1 -1
  61. package/lib/module/components/otp-input/index.js +3 -1
  62. package/lib/module/components/otp-input/index.js.map +1 -1
  63. package/lib/module/components/otp-input/otp-input-state.js +7 -0
  64. package/lib/module/components/otp-input/otp-input-state.js.map +1 -0
  65. package/lib/module/components/pagination/index.js +27 -11
  66. package/lib/module/components/pagination/index.js.map +1 -1
  67. package/lib/module/components/panelside/index.js +7 -2
  68. package/lib/module/components/panelside/index.js.map +1 -1
  69. package/lib/module/components/planner/index.js +46 -11
  70. package/lib/module/components/planner/index.js.map +1 -1
  71. package/lib/module/components/planner/planner-today.js +8 -0
  72. package/lib/module/components/planner/planner-today.js.map +1 -0
  73. package/lib/module/components/plot/index.js +113 -53
  74. package/lib/module/components/plot/index.js.map +1 -1
  75. package/lib/module/components/plot/plot-series-registry.js +32 -0
  76. package/lib/module/components/plot/plot-series-registry.js.map +1 -0
  77. package/lib/module/components/post/index.js +4 -4
  78. package/lib/module/components/post/index.js.map +1 -1
  79. package/lib/module/components/radio-group/index.js +2 -1
  80. package/lib/module/components/radio-group/index.js.map +1 -1
  81. package/lib/module/components/radio-group/radio-group-value.js +8 -0
  82. package/lib/module/components/radio-group/radio-group-value.js.map +1 -0
  83. package/lib/module/components/rating/index.js +7 -4
  84. package/lib/module/components/rating/index.js.map +1 -1
  85. package/lib/module/components/rating/rating-inputs.js +15 -0
  86. package/lib/module/components/rating/rating-inputs.js.map +1 -0
  87. package/lib/module/components/search-bar/index.js +331 -0
  88. package/lib/module/components/search-bar/index.js.map +1 -0
  89. package/lib/module/components/search-bar/search-bar-debounce.js +23 -0
  90. package/lib/module/components/search-bar/search-bar-debounce.js.map +1 -0
  91. package/lib/module/components/select/index.js +9 -1
  92. package/lib/module/components/select/index.js.map +1 -1
  93. package/lib/module/components/select/native-select-contract.js +11 -0
  94. package/lib/module/components/select/native-select-contract.js.map +1 -0
  95. package/lib/module/components/split-view/index.js +439 -0
  96. package/lib/module/components/split-view/index.js.map +1 -0
  97. package/lib/module/components/split-view/split-view-math.js +132 -0
  98. package/lib/module/components/split-view/split-view-math.js.map +1 -0
  99. package/lib/module/components/splitter/index.js +433 -0
  100. package/lib/module/components/splitter/index.js.map +1 -0
  101. package/lib/module/components/splitter/splitter-math.js +206 -0
  102. package/lib/module/components/splitter/splitter-math.js.map +1 -0
  103. package/lib/module/components/steps/index.js +16 -5
  104. package/lib/module/components/steps/index.js.map +1 -1
  105. package/lib/module/components/steps/steps-trigger.js +6 -0
  106. package/lib/module/components/steps/steps-trigger.js.map +1 -0
  107. package/lib/module/components/table/index.js +3 -4
  108. package/lib/module/components/table/index.js.map +1 -1
  109. package/lib/module/components/tag-input/index.js +15 -10
  110. package/lib/module/components/tag-input/index.js.map +1 -1
  111. package/lib/module/components/tag-input/tag-input-state.js +14 -0
  112. package/lib/module/components/tag-input/tag-input-state.js.map +1 -0
  113. package/lib/module/components/textarea/index.js +9 -4
  114. package/lib/module/components/textarea/index.js.map +1 -1
  115. package/lib/module/components/textarea/textarea-disabled.js +6 -0
  116. package/lib/module/components/textarea/textarea-disabled.js.map +1 -0
  117. package/lib/module/components/timeline/index.js +352 -47
  118. package/lib/module/components/timeline/index.js.map +1 -1
  119. package/lib/module/components/timeline/timeline-geometry.js +11 -0
  120. package/lib/module/components/timeline/timeline-geometry.js.map +1 -0
  121. package/lib/module/components/toast/index.js +18 -1
  122. package/lib/module/components/toast/index.js.map +1 -1
  123. package/lib/module/components/toast/toast-store.js +36 -4
  124. package/lib/module/components/toast/toast-store.js.map +1 -1
  125. package/lib/module/components/toggle-button/index.js +1 -1
  126. package/lib/module/components/toggle-button/index.js.map +1 -1
  127. package/lib/module/components/tour/index.js +4 -2
  128. package/lib/module/components/tour/index.js.map +1 -1
  129. package/lib/module/components/tour/tour-card-measurement.js +24 -0
  130. package/lib/module/components/tour/tour-card-measurement.js.map +1 -0
  131. package/lib/module/components/tree/index.js +13 -8
  132. package/lib/module/components/tree/index.js.map +1 -1
  133. package/lib/module/hooks/use-keyboard-avoidance.js.map +1 -1
  134. package/lib/module/index.js +3 -0
  135. package/lib/module/index.js.map +1 -1
  136. package/lib/module/utils/chart.js +50 -7
  137. package/lib/module/utils/chart.js.map +1 -1
  138. package/lib/typescript/src/components/accordion/index.d.ts +2 -2
  139. package/lib/typescript/src/components/accordion/index.d.ts.map +1 -1
  140. package/lib/typescript/src/components/area-chart/index.d.ts.map +1 -1
  141. package/lib/typescript/src/components/avatar/avatar-group.d.ts +46 -0
  142. package/lib/typescript/src/components/avatar/avatar-group.d.ts.map +1 -0
  143. package/lib/typescript/src/components/avatar/index.d.ts +23 -1
  144. package/lib/typescript/src/components/avatar/index.d.ts.map +1 -1
  145. package/lib/typescript/src/components/breadcrumb/index.d.ts.map +1 -1
  146. package/lib/typescript/src/components/button/index.d.ts.map +1 -1
  147. package/lib/typescript/src/components/code-block/index.d.ts +3 -3
  148. package/lib/typescript/src/components/code-block/index.d.ts.map +1 -1
  149. package/lib/typescript/src/components/collapsible/index.d.ts +2 -2
  150. package/lib/typescript/src/components/collapsible/index.d.ts.map +1 -1
  151. package/lib/typescript/src/components/color-picker/color-picker-accessibility.d.ts +8 -0
  152. package/lib/typescript/src/components/color-picker/color-picker-accessibility.d.ts.map +1 -0
  153. package/lib/typescript/src/components/color-picker/index.d.ts.map +1 -1
  154. package/lib/typescript/src/components/date-time-picker/index.d.ts.map +1 -1
  155. package/lib/typescript/src/components/drawer/index.d.ts.map +1 -1
  156. package/lib/typescript/src/components/fab/index.d.ts +4 -2
  157. package/lib/typescript/src/components/fab/index.d.ts.map +1 -1
  158. package/lib/typescript/src/components/heatmap-chart/index.d.ts.map +1 -1
  159. package/lib/typescript/src/components/hex-chart/index.d.ts.map +1 -1
  160. package/lib/typescript/src/components/input/index.d.ts.map +1 -1
  161. package/lib/typescript/src/components/input/input-content-padding.d.ts +2 -0
  162. package/lib/typescript/src/components/input/input-content-padding.d.ts.map +1 -0
  163. package/lib/typescript/src/components/input-group/index.d.ts.map +1 -1
  164. package/lib/typescript/src/components/input-group/input-group-measurements.d.ts +16 -0
  165. package/lib/typescript/src/components/input-group/input-group-measurements.d.ts.map +1 -0
  166. package/lib/typescript/src/components/line-chart/index.d.ts.map +1 -1
  167. package/lib/typescript/src/components/marquee/index.d.ts +1 -1
  168. package/lib/typescript/src/components/marquee/index.d.ts.map +1 -1
  169. package/lib/typescript/src/components/marquee/marquee-math.d.ts +21 -0
  170. package/lib/typescript/src/components/marquee/marquee-math.d.ts.map +1 -0
  171. package/lib/typescript/src/components/menu/index.d.ts +1 -1
  172. package/lib/typescript/src/components/menu/index.d.ts.map +1 -1
  173. package/lib/typescript/src/components/otp-input/index.d.ts.map +1 -1
  174. package/lib/typescript/src/components/otp-input/otp-input-state.d.ts +3 -0
  175. package/lib/typescript/src/components/otp-input/otp-input-state.d.ts.map +1 -0
  176. package/lib/typescript/src/components/pagination/index.d.ts.map +1 -1
  177. package/lib/typescript/src/components/panelside/index.d.ts +1 -1
  178. package/lib/typescript/src/components/panelside/index.d.ts.map +1 -1
  179. package/lib/typescript/src/components/plan/index.d.ts +2 -2
  180. package/lib/typescript/src/components/planner/index.d.ts.map +1 -1
  181. package/lib/typescript/src/components/planner/planner-today.d.ts +2 -0
  182. package/lib/typescript/src/components/planner/planner-today.d.ts.map +1 -0
  183. package/lib/typescript/src/components/plot/index.d.ts +60 -6
  184. package/lib/typescript/src/components/plot/index.d.ts.map +1 -1
  185. package/lib/typescript/src/components/plot/plot-series-registry.d.ts +8 -0
  186. package/lib/typescript/src/components/plot/plot-series-registry.d.ts.map +1 -0
  187. package/lib/typescript/src/components/radio-group/index.d.ts.map +1 -1
  188. package/lib/typescript/src/components/radio-group/radio-group-value.d.ts +2 -0
  189. package/lib/typescript/src/components/radio-group/radio-group-value.d.ts.map +1 -0
  190. package/lib/typescript/src/components/rating/index.d.ts.map +1 -1
  191. package/lib/typescript/src/components/rating/rating-inputs.d.ts +4 -0
  192. package/lib/typescript/src/components/rating/rating-inputs.d.ts.map +1 -0
  193. package/lib/typescript/src/components/search-bar/index.d.ts +216 -0
  194. package/lib/typescript/src/components/search-bar/index.d.ts.map +1 -0
  195. package/lib/typescript/src/components/search-bar/search-bar-debounce.d.ts +7 -0
  196. package/lib/typescript/src/components/search-bar/search-bar-debounce.d.ts.map +1 -0
  197. package/lib/typescript/src/components/select/index.d.ts.map +1 -1
  198. package/lib/typescript/src/components/select/native-select-contract.d.ts +11 -0
  199. package/lib/typescript/src/components/select/native-select-contract.d.ts.map +1 -0
  200. package/lib/typescript/src/components/split-view/index.d.ts +159 -0
  201. package/lib/typescript/src/components/split-view/index.d.ts.map +1 -0
  202. package/lib/typescript/src/components/split-view/split-view-math.d.ts +54 -0
  203. package/lib/typescript/src/components/split-view/split-view-math.d.ts.map +1 -0
  204. package/lib/typescript/src/components/splitter/index.d.ts +78 -0
  205. package/lib/typescript/src/components/splitter/index.d.ts.map +1 -0
  206. package/lib/typescript/src/components/splitter/splitter-math.d.ts +67 -0
  207. package/lib/typescript/src/components/splitter/splitter-math.d.ts.map +1 -0
  208. package/lib/typescript/src/components/steps/index.d.ts +2 -2
  209. package/lib/typescript/src/components/steps/index.d.ts.map +1 -1
  210. package/lib/typescript/src/components/steps/steps-trigger.d.ts +2 -0
  211. package/lib/typescript/src/components/steps/steps-trigger.d.ts.map +1 -0
  212. package/lib/typescript/src/components/tag-input/index.d.ts.map +1 -1
  213. package/lib/typescript/src/components/tag-input/tag-input-state.d.ts +12 -0
  214. package/lib/typescript/src/components/tag-input/tag-input-state.d.ts.map +1 -0
  215. package/lib/typescript/src/components/textarea/index.d.ts.map +1 -1
  216. package/lib/typescript/src/components/textarea/textarea-disabled.d.ts +2 -0
  217. package/lib/typescript/src/components/textarea/textarea-disabled.d.ts.map +1 -0
  218. package/lib/typescript/src/components/timeline/index.d.ts +36 -2
  219. package/lib/typescript/src/components/timeline/index.d.ts.map +1 -1
  220. package/lib/typescript/src/components/timeline/timeline-geometry.d.ts +4 -0
  221. package/lib/typescript/src/components/timeline/timeline-geometry.d.ts.map +1 -0
  222. package/lib/typescript/src/components/toast/index.d.ts.map +1 -1
  223. package/lib/typescript/src/components/toast/toast-store.d.ts +7 -2
  224. package/lib/typescript/src/components/toast/toast-store.d.ts.map +1 -1
  225. package/lib/typescript/src/components/tour/index.d.ts.map +1 -1
  226. package/lib/typescript/src/components/tour/tour-card-measurement.d.ts +14 -0
  227. package/lib/typescript/src/components/tour/tour-card-measurement.d.ts.map +1 -0
  228. package/lib/typescript/src/components/tree/index.d.ts +3 -4
  229. package/lib/typescript/src/components/tree/index.d.ts.map +1 -1
  230. package/lib/typescript/src/hooks/use-keyboard-avoidance.d.ts +2 -2
  231. package/lib/typescript/src/hooks/use-keyboard-avoidance.d.ts.map +1 -1
  232. package/lib/typescript/src/index.d.ts +5 -2
  233. package/lib/typescript/src/index.d.ts.map +1 -1
  234. package/lib/typescript/src/utils/chart.d.ts +28 -3
  235. package/lib/typescript/src/utils/chart.d.ts.map +1 -1
  236. package/package.json +1 -1
  237. package/src/components/accordion/index.tsx +17 -7
  238. package/src/components/area-chart/index.tsx +8 -0
  239. package/src/components/avatar/avatar-group.ts +78 -0
  240. package/src/components/avatar/index.tsx +121 -1
  241. package/src/components/breadcrumb/index.tsx +2 -1
  242. package/src/components/button/index.tsx +3 -2
  243. package/src/components/carousel/index.tsx +1 -1
  244. package/src/components/chip/index.tsx +2 -2
  245. package/src/components/code-block/index.tsx +3 -3
  246. package/src/components/collapsible/index.tsx +13 -4
  247. package/src/components/color-picker/color-picker-accessibility.ts +12 -0
  248. package/src/components/color-picker/index.tsx +30 -10
  249. package/src/components/date-time-picker/index.tsx +11 -3
  250. package/src/components/drawer/index.tsx +42 -14
  251. package/src/components/fab/index.tsx +21 -11
  252. package/src/components/flow/index.tsx +1 -1
  253. package/src/components/frame/index.tsx +2 -2
  254. package/src/components/grid-item/index.tsx +2 -2
  255. package/src/components/heatmap-chart/index.tsx +7 -1
  256. package/src/components/hex-chart/index.tsx +7 -1
  257. package/src/components/input/index.tsx +6 -2
  258. package/src/components/input/input-content-padding.ts +3 -0
  259. package/src/components/input-group/index.tsx +45 -12
  260. package/src/components/input-group/input-group-measurements.ts +98 -0
  261. package/src/components/item/index.tsx +2 -2
  262. package/src/components/line-chart/index.tsx +9 -0
  263. package/src/components/marker/index.tsx +2 -2
  264. package/src/components/marquee/index.tsx +14 -12
  265. package/src/components/marquee/marquee-math.ts +37 -0
  266. package/src/components/menu/index.tsx +11 -3
  267. package/src/components/otp-input/index.tsx +3 -1
  268. package/src/components/otp-input/otp-input-state.ts +7 -0
  269. package/src/components/pagination/index.tsx +26 -13
  270. package/src/components/panelside/index.tsx +7 -2
  271. package/src/components/plan/index.tsx +2 -2
  272. package/src/components/planner/index.tsx +44 -11
  273. package/src/components/planner/planner-today.ts +5 -0
  274. package/src/components/plot/index.tsx +199 -51
  275. package/src/components/plot/plot-series-registry.ts +41 -0
  276. package/src/components/post/index.tsx +4 -4
  277. package/src/components/radio-group/index.tsx +4 -1
  278. package/src/components/radio-group/radio-group-value.ts +9 -0
  279. package/src/components/rating/index.tsx +11 -4
  280. package/src/components/rating/rating-inputs.ts +19 -0
  281. package/src/components/search-bar/index.tsx +441 -0
  282. package/src/components/search-bar/search-bar-debounce.ts +35 -0
  283. package/src/components/select/index.tsx +10 -1
  284. package/src/components/select/native-select-contract.ts +12 -0
  285. package/src/components/split-view/index.tsx +565 -0
  286. package/src/components/split-view/split-view-math.ts +146 -0
  287. package/src/components/splitter/index.tsx +589 -0
  288. package/src/components/splitter/splitter-math.ts +244 -0
  289. package/src/components/steps/index.tsx +35 -9
  290. package/src/components/steps/steps-trigger.ts +6 -0
  291. package/src/components/table/index.tsx +2 -2
  292. package/src/components/tag-input/index.tsx +13 -11
  293. package/src/components/tag-input/tag-input-state.ts +18 -0
  294. package/src/components/textarea/index.tsx +8 -4
  295. package/src/components/textarea/textarea-disabled.ts +6 -0
  296. package/src/components/timeline/index.tsx +405 -46
  297. package/src/components/timeline/timeline-geometry.ts +9 -0
  298. package/src/components/toast/index.tsx +26 -1
  299. package/src/components/toast/toast-store.ts +43 -8
  300. package/src/components/toggle-button/index.tsx +1 -1
  301. package/src/components/tour/index.tsx +11 -3
  302. package/src/components/tour/tour-card-measurement.ts +29 -0
  303. package/src/components/tree/index.tsx +17 -12
  304. package/src/hooks/use-keyboard-avoidance.ts +7 -2
  305. package/src/index.ts +19 -0
  306. package/src/utils/chart.ts +66 -7
@@ -71,6 +71,7 @@ import {
71
71
  View,
72
72
  type AccessibilityActionEvent,
73
73
  type LayoutChangeEvent,
74
+ type ViewStyle,
74
75
  } from 'react-native';
75
76
  import MaskedView from '@react-native-masked-view/masked-view';
76
77
  import { LinearGradient } from 'expo-linear-gradient';
@@ -107,6 +108,7 @@ import {
107
108
  import { cn } from '../../utils/cn';
108
109
  import { selectionTick } from '../../utils/haptics';
109
110
  import { Popover, type PopoverContentProps } from '../popover';
111
+ import { enabledColorPickerAction } from './color-picker-accessibility';
110
112
 
111
113
  /** Settles a thumb that was moved by something other than a finger. */
112
114
  const TIMING = { duration: 140 } as const;
@@ -585,7 +587,10 @@ const ColorPickerArea = forwardRef<View, ColorPickerAreaProps>(
585
587
  };
586
588
 
587
589
  const onAccessibilityAction = (event: AccessibilityActionEvent) => {
588
- const action = event.nativeEvent.actionName;
590
+ const action = enabledColorPickerAction(
591
+ event.nativeEvent.actionName,
592
+ ctx.disabled
593
+ );
589
594
  if (action === 'increment') nudge('saturation', 1);
590
595
  else if (action === 'decrement') nudge('saturation', -1);
591
596
  else if (action === 'brighter') nudge('brightness', 1);
@@ -663,8 +668,8 @@ interface ChannelTrackProps {
663
668
  /** What fills the track — a hue ramp, or a masked translucency ramp. */
664
669
  children: ReactNode;
665
670
  gesture: ReturnType<typeof Gesture.Race>;
666
- thumbStyle: ReturnType<typeof useAnimatedStyle>;
667
- thumbFillStyle: ReturnType<typeof useAnimatedStyle>;
671
+ thumbStyle: ReturnType<typeof useAnimatedStyle<ViewStyle>>;
672
+ thumbFillStyle: ReturnType<typeof useAnimatedStyle<ViewStyle>>;
668
673
  onLayout: (event: LayoutChangeEvent) => void;
669
674
  size: ColorPickerSize;
670
675
  className?: string;
@@ -828,8 +833,12 @@ const ColorPickerHue = forwardRef<View, ColorPickerHueProps>(
828
833
  disabled={ctx.disabled}
829
834
  accessibilityValue={{ min: 0, max: 360, now: announced, text: `${announced}°` }}
830
835
  onAccessibilityAction={(event) => {
831
- if (event.nativeEvent.actionName === 'increment') nudge(1);
832
- else if (event.nativeEvent.actionName === 'decrement') nudge(-1);
836
+ const action = enabledColorPickerAction(
837
+ event.nativeEvent.actionName,
838
+ ctx.disabled
839
+ );
840
+ if (action === 'increment') nudge(1);
841
+ else if (action === 'decrement') nudge(-1);
833
842
  }}
834
843
  >
835
844
  <LinearGradient
@@ -947,8 +956,12 @@ const ColorPickerAlpha = forwardRef<View, ColorPickerAlphaProps>(
947
956
  text: `${announced}%`,
948
957
  }}
949
958
  onAccessibilityAction={(event) => {
950
- if (event.nativeEvent.actionName === 'increment') nudge(1);
951
- else if (event.nativeEvent.actionName === 'decrement') nudge(-1);
959
+ const action = enabledColorPickerAction(
960
+ event.nativeEvent.actionName,
961
+ ctx.disabled
962
+ );
963
+ if (action === 'increment') nudge(1);
964
+ else if (action === 'decrement') nudge(-1);
952
965
  }}
953
966
  >
954
967
  <Checkerboard />
@@ -1503,8 +1516,12 @@ const ColorPickerBrightness = forwardRef<View, ColorPickerBrightnessProps>(
1503
1516
  text: `${announced}%`,
1504
1517
  }}
1505
1518
  onAccessibilityAction={(event) => {
1506
- if (event.nativeEvent.actionName === 'increment') nudge(1);
1507
- else if (event.nativeEvent.actionName === 'decrement') nudge(-1);
1519
+ const action = enabledColorPickerAction(
1520
+ event.nativeEvent.actionName,
1521
+ ctx.disabled
1522
+ );
1523
+ if (action === 'increment') nudge(1);
1524
+ else if (action === 'decrement') nudge(-1);
1508
1525
  }}
1509
1526
  >
1510
1527
  <LinearGradient
@@ -1666,7 +1683,10 @@ const ColorPickerWheel = forwardRef<View, ColorPickerWheelProps>(
1666
1683
  };
1667
1684
 
1668
1685
  const onAccessibilityAction = (event: AccessibilityActionEvent) => {
1669
- const action = event.nativeEvent.actionName;
1686
+ const action = enabledColorPickerAction(
1687
+ event.nativeEvent.actionName,
1688
+ ctx.disabled
1689
+ );
1670
1690
  if (action === 'increment') nudge('hue', 1);
1671
1691
  else if (action === 'decrement') nudge('hue', -1);
1672
1692
  else if (action === 'saturate') nudge('saturation', 1);
@@ -84,6 +84,9 @@ const DEFAULT_PLACEHOLDER = 'Pick a date and time';
84
84
  */
85
85
  const PANEL_WIDTH = 308;
86
86
 
87
+ /** A stable rule that makes every calendar day unavailable while disabled. */
88
+ const DISABLE_ALL_DATES = () => true;
89
+
87
90
  /** How a `Date` is written on the closed trigger. */
88
91
  function describe(
89
92
  value: Date,
@@ -204,18 +207,23 @@ function DateTimePickerRoot({
204
207
 
205
208
  const setOpen = useCallback(
206
209
  (next: boolean) => {
210
+ if (disabled && next) return;
207
211
  if (!isOpenControlled) setInternalOpen(next);
208
212
  onOpenChange?.(next);
209
213
  },
210
- [isOpenControlled, onOpenChange]
214
+ [disabled, isOpenControlled, onOpenChange]
211
215
  );
212
216
 
213
217
  const commit = useCallback(
214
218
  (next: Date) => {
219
+ // A controlled caller can keep the panel mounted or open while disabled.
220
+ // Guard the value boundary as well as the visible controls so a stale
221
+ // press cannot commit during the same render that disables the picker.
222
+ if (disabled) return;
215
223
  if (!isValueControlled) setInternalValue(next);
216
224
  onValueChange?.(next);
217
225
  },
218
- [isValueControlled, onValueChange]
226
+ [disabled, isValueControlled, onValueChange]
219
227
  );
220
228
 
221
229
  /*
@@ -281,7 +289,7 @@ function DateTimePickerRoot({
281
289
  mode="single"
282
290
  selected={value}
283
291
  onSelect={handleDay}
284
- disabled={disabledDates}
292
+ disabled={disabled ? DISABLE_ALL_DATES : disabledDates}
285
293
  minDate={minDate}
286
294
  maxDate={maxDate}
287
295
  startMonth={minDate}
@@ -66,14 +66,11 @@ import {
66
66
  } from 'react-native';
67
67
  import { Gesture, GestureDetector } from 'react-native-gesture-handler';
68
68
  import Animated, {
69
+ Easing,
69
70
  SlideInDown,
70
71
  SlideInLeft,
71
72
  SlideInRight,
72
73
  SlideInUp,
73
- SlideOutDown,
74
- SlideOutLeft,
75
- SlideOutRight,
76
- SlideOutUp,
77
74
  runOnJS,
78
75
  useAnimatedStyle,
79
76
  useSharedValue,
@@ -96,6 +93,9 @@ import {
96
93
  import { cn } from '../../utils/cn';
97
94
 
98
95
  const SPRING = { damping: 24, stiffness: 300, mass: 0.7 } as const;
96
+ /** How long the panel takes to leave, whether by a drag or a press. */
97
+ const EXIT_DURATION = 200;
98
+
99
99
  /** How far a drag has to travel outward before releasing it dismisses. */
100
100
  const DISMISS_DISTANCE = 80;
101
101
  /** A flick this fast dismisses regardless of how far it got. */
@@ -375,9 +375,11 @@ function DrawerContent({
375
375
  const velocity =
376
376
  (horizontal ? event.velocityX : event.velocityY) * outward;
377
377
  if (travel.value > DISMISS_DISTANCE || velocity > DISMISS_VELOCITY) {
378
- travel.value = withTiming(extent, { duration: 180 }, (finished) => {
379
- if (finished) runOnJS(close)();
380
- });
378
+ // Straight to the exit, without finishing the slide first. The exit
379
+ // starts from wherever `travel` is and carries it the rest of the
380
+ // way, so driving it to `extent` here would be the same distance
381
+ // animated twice.
382
+ runOnJS(close)();
381
383
  } else {
382
384
  travel.value = withSpring(0, SPRING);
383
385
  }
@@ -433,12 +435,38 @@ function DrawerContent({
433
435
  bottom: SlideInDown,
434
436
  }[physical];
435
437
 
436
- const exiting = {
437
- left: SlideOutLeft,
438
- right: SlideOutRight,
439
- top: SlideOutUp,
440
- bottom: SlideOutDown,
441
- }[physical];
438
+ /*
439
+ * The slide out is written by hand, because the panel is not always at rest
440
+ * when it starts.
441
+ *
442
+ * A preset animates from the view's *layout* position and applies its own
443
+ * transform, which overrides the one the drag was already using. So a
444
+ * swipe-dismiss played twice: the gesture carried the panel off-screen, and
445
+ * then the exit put it back at zero and slid it out again. Seeding the
446
+ * initial transform from `travel` makes the two one animation — the exit
447
+ * picks the panel up wherever the finger left it and carries it the rest of
448
+ * the way. A press on the close button or the backdrop leaves `travel` at
449
+ * zero, so that path is the same slide it always was.
450
+ */
451
+ const exiting = useCallback(() => {
452
+ 'worklet';
453
+ const shift = extent * outward;
454
+ const from = travel.value * outward;
455
+ const timing = { duration: EXIT_DURATION, easing: Easing.out(Easing.quad) };
456
+
457
+ return {
458
+ initialValues: {
459
+ transform: horizontal
460
+ ? [{ translateX: from }, { translateY: 0 }]
461
+ : [{ translateX: 0 }, { translateY: from }],
462
+ },
463
+ animations: {
464
+ transform: horizontal
465
+ ? [{ translateX: withTiming(shift, timing) }, { translateY: 0 }]
466
+ : [{ translateX: 0 }, { translateY: withTiming(shift, timing) }],
467
+ },
468
+ };
469
+ }, [extent, horizontal, outward, travel]);
442
470
 
443
471
  /*
444
472
  * The inset and the panel's own padding stack rather than compete.
@@ -499,7 +527,7 @@ function DrawerContent({
499
527
  .damping(24)
500
528
  .stiffness(260)
501
529
  .mass(0.7)}
502
- exiting={exiting.duration(200)}
530
+ exiting={exiting}
503
531
  accessibilityViewIsModal
504
532
  className={panelVariants({ side, className })}
505
533
  {...props}
@@ -85,7 +85,10 @@ import { tv, type VariantProps } from 'tailwind-variants';
85
85
  import { useCSSVariable } from 'uniwind';
86
86
  import { IconColorProvider } from '../../icons';
87
87
  import { useBackHandler } from '../../hooks/use-back-handler';
88
- import { AnimatedPressable } from '../../primitives/animated-pressable';
88
+ import {
89
+ AnimatedPressable,
90
+ type AnimatedPressableProps,
91
+ } from '../../primitives/animated-pressable';
89
92
  import { Scrim } from '../../primitives/scrim';
90
93
  import { Text } from '../../primitives/text';
91
94
  import { cn } from '../../utils/cn';
@@ -180,7 +183,9 @@ function anchor(placement: FabPlacement, offset: number) {
180
183
  * Fab
181
184
  * -------------------------------------------------------------------------- */
182
185
 
183
- export interface FabProps extends Omit<ViewProps, 'children'>, FabVariantProps {
186
+ export interface FabProps
187
+ extends Omit<AnimatedPressableProps, 'children' | 'style' | 'disabled'>,
188
+ Omit<FabVariantProps, 'disabled'> {
184
189
  className?: string;
185
190
  /** The glyph. Sized by you — this is the one thing that should not guess. */
186
191
  icon?: ReactNode;
@@ -201,7 +206,8 @@ export interface FabProps extends Omit<ViewProps, 'children'>, FabVariantProps {
201
206
  placement?: FabPlacement;
202
207
  /** Distance from the edges when `placement` is set, in points. */
203
208
  offset?: number;
204
- onPress?: () => void;
209
+ /** Placement-aware view style. Press-state styling belongs in `className`. */
210
+ style?: ViewProps['style'];
205
211
  disabled?: boolean;
206
212
  /**
207
213
  * A tick on press. Off by default — needs the optional `expo-haptics`, and
@@ -231,33 +237,37 @@ const FabRoot = forwardRef<View, FabProps>(
231
237
  },
232
238
  ref
233
239
  ) => {
240
+ const isDisabled = Boolean(disabled);
234
241
  const { root, label } = fabVariants({
235
242
  size,
236
243
  variant,
237
244
  extended: extended && !!children,
238
- disabled,
245
+ disabled: isDisabled,
239
246
  });
240
247
 
241
248
  const themed = useCSSVariable(CONTENT_COLOR_VAR[variant ?? 'primary']);
242
249
  const contentColor =
243
250
  typeof themed === 'string' ? themed : undefined;
244
251
 
245
- const handlePress = useCallback(() => {
246
- if (haptics) selectionTick();
247
- onPress?.();
248
- }, [haptics, onPress]);
252
+ const handlePress = useCallback<NonNullable<AnimatedPressableProps['onPress']>>(
253
+ (event) => {
254
+ if (haptics) selectionTick();
255
+ onPress?.(event);
256
+ },
257
+ [haptics, onPress]
258
+ );
249
259
 
250
260
  return (
251
261
  <IconColorProvider color={contentColor}>
252
262
  <AnimatedPressable
253
263
  ref={ref}
264
+ {...props}
254
265
  accessibilityRole="button"
255
- accessibilityState={{ disabled }}
256
- disabled={disabled}
266
+ accessibilityState={{ disabled: isDisabled }}
267
+ disabled={isDisabled}
257
268
  onPress={handlePress}
258
269
  className={root({ className })}
259
270
  style={[placement ? anchor(placement, offset) : null, style]}
260
- {...props}
261
271
  >
262
272
  {icon}
263
273
  {extended && children ? (
@@ -1254,6 +1254,7 @@ function FlowNode({
1254
1254
  <FlowNodeContext.Provider value={id}>
1255
1255
  <GestureDetector gesture={gesture}>
1256
1256
  <Animated.View
1257
+ {...props}
1257
1258
  collapsable={false}
1258
1259
  onLayout={onLayout}
1259
1260
  style={[{ position: 'absolute', top: 0, left: 0 }, style]}
@@ -1267,7 +1268,6 @@ function FlowNode({
1267
1268
  accessibilityState={{ selected }}
1268
1269
  accessibilityActions={nodeActions}
1269
1270
  onAccessibilityAction={handleAccessibilityAction}
1270
- {...props}
1271
1271
  >
1272
1272
  {textChildren(children)}
1273
1273
  </Animated.View>
@@ -398,7 +398,7 @@ const FrameRow = forwardRef<View, FrameRowProps>(
398
398
 
399
399
  if (!onPress) {
400
400
  return (
401
- <View ref={ref} className={classes} {...(props as ViewProps)}>
401
+ <View ref={ref} {...(props as ViewProps)} className={classes}>
402
402
  {body}
403
403
  </View>
404
404
  );
@@ -407,10 +407,10 @@ const FrameRow = forwardRef<View, FrameRowProps>(
407
407
  return (
408
408
  <Pressable
409
409
  ref={ref}
410
+ {...props}
410
411
  accessibilityRole="button"
411
412
  onPress={onPress}
412
413
  className={classes}
413
- {...props}
414
414
  >
415
415
  {body}
416
416
  </Pressable>
@@ -334,9 +334,9 @@ const GridItemRoot = forwardRef<View, GridItemProps>(
334
334
  return (
335
335
  <View
336
336
  ref={ref}
337
+ {...(props as ViewProps)}
337
338
  accessibilityState={{ disabled: !!disabled }}
338
339
  className={root({ className })}
339
- {...(props as ViewProps)}
340
340
  >
341
341
  {textChildren(children)}
342
342
  </View>
@@ -346,12 +346,12 @@ const GridItemRoot = forwardRef<View, GridItemProps>(
346
346
  return (
347
347
  <AnimatedPressable
348
348
  ref={ref}
349
+ {...props}
349
350
  accessibilityRole="button"
350
351
  accessibilityState={{ disabled: !!disabled }}
351
352
  disabled={disabled}
352
353
  onPress={onPress}
353
354
  className={root({ className })}
354
- {...props}
355
355
  >
356
356
  {textChildren(children)}
357
357
  </AnimatedPressable>
@@ -628,7 +628,13 @@ const HeatmapChartRoot = forwardRef<View, HeatmapChartProps>(function HeatmapCha
628
628
  <Svg width={grid.width} height={grid.height} style={StyleSheet.absoluteFill}>
629
629
  <Defs>
630
630
  <ClipPath id={clipId}>
631
- <AnimatedRect x={0} y={0} height={grid.height} animatedProps={clipProps} />
631
+ <AnimatedRect
632
+ x={0}
633
+ y={0}
634
+ width={grid.width}
635
+ height={grid.height}
636
+ animatedProps={clipProps}
637
+ />
632
638
  </ClipPath>
633
639
  </Defs>
634
640
  <G clipPath={`url(#${clipId})`}>
@@ -534,7 +534,13 @@ const HexChartRoot = forwardRef<HexChartHandle, HexChartProps>(function HexChart
534
534
  animatedProps={ellipseProps}
535
535
  />
536
536
  ) : (
537
- <AnimatedRect x={0} y={0} height={height} animatedProps={rectProps} />
537
+ <AnimatedRect
538
+ x={0}
539
+ y={0}
540
+ width={width}
541
+ height={height}
542
+ animatedProps={rectProps}
543
+ />
538
544
  )}
539
545
  </ClipPath>
540
546
  </Defs>
@@ -59,6 +59,7 @@ import { IconColorProvider } from '../../icons';
59
59
  import { KeyboardAvoider } from '../../primitives/keyboard-avoider';
60
60
  import { Text, textChildren } from '../../primitives/text';
61
61
  import { Label } from '../label';
62
+ import { inputContentPadding } from './input-content-padding';
62
63
 
63
64
  /** Long enough to read as a transition, short enough not to lag a fast tab. */
64
65
  const FOCUS_DURATION = 150;
@@ -303,6 +304,9 @@ export const Input = forwardRef<TextInput, InputProps>(
303
304
  setEndWidth(event.nativeEvent.layout.width);
304
305
  }, []);
305
306
 
307
+ const startPadding = inputContentPadding(startWidth, !!startContent);
308
+ const endPadding = inputContentPadding(endWidth, !!endContent);
309
+
306
310
  /*
307
311
  * The content is quieter than the value. An icon at the same weight as the
308
312
  * text reads as part of what was typed, and the placeholder colour is
@@ -325,8 +329,8 @@ export const Input = forwardRef<TextInput, InputProps>(
325
329
  borderStyle,
326
330
  // Only the side that has content, and only once it has been
327
331
  // measured — a 0 here would wipe out the field's own padding.
328
- startWidth ? { paddingStart: startWidth } : null,
329
- endWidth ? { paddingEnd: endWidth } : null,
332
+ startPadding ? { paddingStart: startPadding } : null,
333
+ endPadding ? { paddingEnd: endPadding } : null,
330
334
  // Caller styles come last so InputGroup can pad the field around its
331
335
  // decorators, but never last enough to drop the animated border.
332
336
  style,
@@ -0,0 +1,3 @@
1
+ export function inputContentPadding(width: number, present: boolean): number | undefined {
2
+ return present && width > 0 && Number.isFinite(width) ? width : undefined;
3
+ }
@@ -11,7 +11,6 @@ import {
11
11
  useCallback,
12
12
  useContext,
13
13
  useMemo,
14
- useState,
15
14
  type ReactNode,
16
15
  } from 'react';
17
16
  import {
@@ -23,6 +22,12 @@ import {
23
22
  import { tv } from 'tailwind-variants';
24
23
  import { Input, type InputProps } from '../input';
25
24
  import { textChildren } from '../../primitives/text';
25
+ import {
26
+ useInputGroupDecoratorMeasurement,
27
+ useInputGroupMeasurements,
28
+ type InputGroupDecoratorOwner,
29
+ type InputGroupDecoratorSide,
30
+ } from './input-group-measurements';
26
31
 
27
32
  const inputGroupVariants = tv({
28
33
  slots: {
@@ -41,8 +46,15 @@ interface InputGroupState {
41
46
  isDisabled: boolean;
42
47
  prefixWidth: number;
43
48
  suffixWidth: number;
44
- setPrefixWidth: (width: number) => void;
45
- setSuffixWidth: (width: number) => void;
49
+ measureDecorator: (
50
+ side: InputGroupDecoratorSide,
51
+ owner: InputGroupDecoratorOwner,
52
+ width: number
53
+ ) => void;
54
+ removeDecorator: (
55
+ side: InputGroupDecoratorSide,
56
+ owner: InputGroupDecoratorOwner
57
+ ) => void;
46
58
  }
47
59
 
48
60
  const InputGroupContext = createContext<InputGroupState | null>(null);
@@ -61,12 +73,24 @@ export interface InputGroupProps extends ViewProps {
61
73
  const InputGroupRoot = forwardRef<View, InputGroupProps>(
62
74
  ({ className, isDisabled = false, children, ...props }, ref) => {
63
75
  const { root } = inputGroupVariants();
64
- const [prefixWidth, setPrefixWidth] = useState(0);
65
- const [suffixWidth, setSuffixWidth] = useState(0);
76
+ const { prefixWidth, suffixWidth, measureDecorator, removeDecorator } =
77
+ useInputGroupMeasurements();
66
78
 
67
79
  const value = useMemo<InputGroupState>(
68
- () => ({ isDisabled, prefixWidth, suffixWidth, setPrefixWidth, setSuffixWidth }),
69
- [isDisabled, prefixWidth, suffixWidth]
80
+ () => ({
81
+ isDisabled,
82
+ prefixWidth,
83
+ suffixWidth,
84
+ measureDecorator,
85
+ removeDecorator,
86
+ }),
87
+ [
88
+ isDisabled,
89
+ prefixWidth,
90
+ suffixWidth,
91
+ measureDecorator,
92
+ removeDecorator,
93
+ ]
70
94
  );
71
95
 
72
96
  return (
@@ -97,14 +121,18 @@ function createDecorator(side: 'prefix' | 'suffix') {
97
121
  ({ className, isDecorative = false, onLayout, children, ...props }, ref) => {
98
122
  const group = useInputGroup();
99
123
  const slots = inputGroupVariants({ isDisabled: group?.isDisabled ?? false });
100
- const setWidth = side === 'prefix' ? group?.setPrefixWidth : group?.setSuffixWidth;
124
+ const measure = useInputGroupDecoratorMeasurement(
125
+ side,
126
+ group?.measureDecorator,
127
+ group?.removeDecorator
128
+ );
101
129
 
102
130
  const handleLayout = useCallback(
103
131
  (event: LayoutChangeEvent) => {
104
- setWidth?.(event.nativeEvent.layout.width);
132
+ measure(event.nativeEvent.layout.width);
105
133
  onLayout?.(event);
106
134
  },
107
- [setWidth, onLayout]
135
+ [measure, onLayout]
108
136
  );
109
137
 
110
138
  return (
@@ -146,8 +174,13 @@ const InputGroupInput = forwardRef<TextInput, InputGroupInputProps>(
146
174
  style={[
147
175
  // Only override padding on the side that actually has a decorator —
148
176
  // a 0 here would wipe out the field's default horizontal padding.
149
- group?.prefixWidth ? { paddingLeft: group.prefixWidth } : null,
150
- group?.suffixWidth ? { paddingRight: group.suffixWidth } : null,
177
+ //
178
+ // `paddingStart`/`paddingEnd`, not left/right: the decorators are
179
+ // inset with `start-0`/`end-0`, so under `Direction dir="rtl"` Yoga
180
+ // moves them to the other edge. Physical padding stays where it was
181
+ // written and leaves the value running underneath them.
182
+ group?.prefixWidth ? { paddingStart: group.prefixWidth } : null,
183
+ group?.suffixWidth ? { paddingEnd: group.suffixWidth } : null,
151
184
  style,
152
185
  ]}
153
186
  {...props}
@@ -0,0 +1,98 @@
1
+ import { useCallback, useLayoutEffect, useRef, useState } from 'react';
2
+
3
+ export type InputGroupDecoratorSide = 'prefix' | 'suffix';
4
+ export type InputGroupDecoratorOwner = symbol;
5
+
6
+ type Widths = Record<InputGroupDecoratorSide, number>;
7
+ type Registries = Record<
8
+ InputGroupDecoratorSide,
9
+ Map<InputGroupDecoratorOwner, number>
10
+ >;
11
+
12
+ export interface InputGroupMeasurements {
13
+ prefixWidth: number;
14
+ suffixWidth: number;
15
+ measureDecorator: (
16
+ side: InputGroupDecoratorSide,
17
+ owner: InputGroupDecoratorOwner,
18
+ width: number
19
+ ) => void;
20
+ removeDecorator: (
21
+ side: InputGroupDecoratorSide,
22
+ owner: InputGroupDecoratorOwner
23
+ ) => void;
24
+ }
25
+
26
+ type MeasureDecorator = InputGroupMeasurements['measureDecorator'];
27
+ type RemoveDecorator = InputGroupMeasurements['removeDecorator'];
28
+
29
+ const emptyWidths = (): Widths => ({ prefix: 0, suffix: 0 });
30
+
31
+ function measuredWidth(registry: Map<InputGroupDecoratorOwner, number>) {
32
+ let width = 0;
33
+ for (const candidate of registry.values()) width = Math.max(width, candidate);
34
+ return width;
35
+ }
36
+
37
+ /** Keeps measured padding tied to the decorators that are still mounted. */
38
+ export function useInputGroupMeasurements(): InputGroupMeasurements {
39
+ const registries = useRef<Registries>({ prefix: new Map(), suffix: new Map() });
40
+ const [widths, setWidths] = useState<Widths>(emptyWidths);
41
+
42
+ const commitWidth = useCallback((side: InputGroupDecoratorSide) => {
43
+ const width = measuredWidth(registries.current[side]);
44
+ setWidths((current) =>
45
+ current[side] === width ? current : { ...current, [side]: width }
46
+ );
47
+ }, []);
48
+
49
+ const measureDecorator = useCallback(
50
+ (side: InputGroupDecoratorSide, owner: InputGroupDecoratorOwner, width: number) => {
51
+ const registry = registries.current[side];
52
+ if (Number.isFinite(width) && width > 0) registry.set(owner, width);
53
+ else registry.delete(owner);
54
+ commitWidth(side);
55
+ },
56
+ [commitWidth]
57
+ );
58
+
59
+ const removeDecorator = useCallback(
60
+ (side: InputGroupDecoratorSide, owner: InputGroupDecoratorOwner) => {
61
+ if (!registries.current[side].delete(owner)) return;
62
+ commitWidth(side);
63
+ },
64
+ [commitWidth]
65
+ );
66
+
67
+ return {
68
+ prefixWidth: widths.prefix,
69
+ suffixWidth: widths.suffix,
70
+ measureDecorator,
71
+ removeDecorator,
72
+ };
73
+ }
74
+
75
+ /** Gives one mounted decorator an owner token and unregisters only that owner. */
76
+ export function useInputGroupDecoratorMeasurement(
77
+ side: InputGroupDecoratorSide,
78
+ measureDecorator: MeasureDecorator | undefined,
79
+ removeDecorator: RemoveDecorator | undefined
80
+ ) {
81
+ const owner = useRef<InputGroupDecoratorOwner>(Symbol(side));
82
+ const width = useRef(0);
83
+
84
+ useLayoutEffect(() => {
85
+ // Re-register the last layout if React replays effects in Strict Mode or
86
+ // the decorator moves between InputGroup providers.
87
+ if (width.current > 0) measureDecorator?.(side, owner.current, width.current);
88
+ return () => removeDecorator?.(side, owner.current);
89
+ }, [measureDecorator, removeDecorator, side]);
90
+
91
+ return useCallback(
92
+ (nextWidth: number) => {
93
+ width.current = nextWidth;
94
+ measureDecorator?.(side, owner.current, nextWidth);
95
+ },
96
+ [measureDecorator, side]
97
+ );
98
+ }
@@ -148,21 +148,21 @@ const ItemRoot = forwardRef<View, ItemProps>(
148
148
  const body = !onPress ? (
149
149
  <View
150
150
  ref={ref}
151
+ {...(props as ViewProps)}
151
152
  accessibilityState={{ disabled: !!disabled }}
152
153
  className={root({ className })}
153
- {...(props as ViewProps)}
154
154
  >
155
155
  {textChildren(children)}
156
156
  </View>
157
157
  ) : (
158
158
  <AnimatedPressable
159
159
  ref={ref}
160
+ {...props}
160
161
  accessibilityRole="button"
161
162
  accessibilityState={{ disabled: !!disabled }}
162
163
  disabled={disabled}
163
164
  onPress={onPress}
164
165
  className={root({ className })}
165
- {...props}
166
166
  >
167
167
  {textChildren(children)}
168
168
  </AnimatedPressable>