@limonify/zest-ui 0.3.1 → 0.4.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 (381) hide show
  1. package/README.md +3 -0
  2. package/lib/alert-dialog/index.parts.d.ts +1 -1
  3. package/lib/alert-dialog/index.parts.d.ts.map +1 -1
  4. package/lib/alert-dialog/index.parts.js.map +1 -1
  5. package/lib/autocomplete/handle.d.ts +15 -0
  6. package/lib/autocomplete/handle.d.ts.map +1 -0
  7. package/lib/autocomplete/handle.js +12 -0
  8. package/lib/autocomplete/handle.js.map +1 -0
  9. package/lib/autocomplete/index.d.ts +1 -0
  10. package/lib/autocomplete/index.d.ts.map +1 -1
  11. package/lib/autocomplete/index.parts.d.ts +1 -0
  12. package/lib/autocomplete/index.parts.d.ts.map +1 -1
  13. package/lib/autocomplete/index.parts.js +3 -1
  14. package/lib/autocomplete/index.parts.js.map +1 -1
  15. package/lib/autocomplete/root/AutocompleteRoot.d.ts +55 -16
  16. package/lib/autocomplete/root/AutocompleteRoot.d.ts.map +1 -1
  17. package/lib/autocomplete/root/AutocompleteRoot.js +2 -18
  18. package/lib/autocomplete/root/AutocompleteRoot.js.map +1 -1
  19. package/lib/avatar/fallback/AvatarFallback.d.ts.map +1 -1
  20. package/lib/avatar/fallback/AvatarFallback.js +3 -1
  21. package/lib/avatar/fallback/AvatarFallback.js.map +1 -1
  22. package/lib/avatar/image/AvatarImage.d.ts.map +1 -1
  23. package/lib/avatar/image/AvatarImage.js +5 -0
  24. package/lib/avatar/image/AvatarImage.js.map +1 -1
  25. package/lib/checkbox/root/CheckboxRoot.d.ts.map +1 -1
  26. package/lib/checkbox/root/CheckboxRoot.js +9 -4
  27. package/lib/checkbox/root/CheckboxRoot.js.map +1 -1
  28. package/lib/combobox/backdrop/ComboboxBackdrop.d.ts.map +1 -1
  29. package/lib/combobox/backdrop/ComboboxBackdrop.js +10 -2
  30. package/lib/combobox/backdrop/ComboboxBackdrop.js.map +1 -1
  31. package/lib/combobox/empty/ComboboxEmpty.d.ts.map +1 -1
  32. package/lib/combobox/empty/ComboboxEmpty.js +4 -1
  33. package/lib/combobox/empty/ComboboxEmpty.js.map +1 -1
  34. package/lib/combobox/index.d.ts +2 -0
  35. package/lib/combobox/index.d.ts.map +1 -1
  36. package/lib/combobox/index.js +3 -1
  37. package/lib/combobox/index.js.map +1 -1
  38. package/lib/combobox/index.parts.d.ts +1 -0
  39. package/lib/combobox/index.parts.d.ts.map +1 -1
  40. package/lib/combobox/index.parts.js +4 -1
  41. package/lib/combobox/index.parts.js.map +1 -1
  42. package/lib/combobox/input/ComboboxInput.d.ts +24 -3
  43. package/lib/combobox/input/ComboboxInput.d.ts.map +1 -1
  44. package/lib/combobox/input/ComboboxInput.js +68 -8
  45. package/lib/combobox/input/ComboboxInput.js.map +1 -1
  46. package/lib/combobox/item/ComboboxItem.d.ts +11 -1
  47. package/lib/combobox/item/ComboboxItem.d.ts.map +1 -1
  48. package/lib/combobox/item/ComboboxItem.js +9 -4
  49. package/lib/combobox/item/ComboboxItem.js.map +1 -1
  50. package/lib/combobox/list/ComboboxList.d.ts +1 -1
  51. package/lib/combobox/list/ComboboxList.d.ts.map +1 -1
  52. package/lib/combobox/list/ComboboxList.js +4 -1
  53. package/lib/combobox/list/ComboboxList.js.map +1 -1
  54. package/lib/combobox/popup/ComboboxPopup.d.ts +26 -0
  55. package/lib/combobox/popup/ComboboxPopup.d.ts.map +1 -1
  56. package/lib/combobox/popup/ComboboxPopup.js +18 -2
  57. package/lib/combobox/popup/ComboboxPopup.js.map +1 -1
  58. package/lib/combobox/portal/ComboboxPortal.d.ts.map +1 -1
  59. package/lib/combobox/portal/ComboboxPortal.js +8 -4
  60. package/lib/combobox/portal/ComboboxPortal.js.map +1 -1
  61. package/lib/combobox/portal/ComboboxPortalContext.d.ts +4 -0
  62. package/lib/combobox/portal/ComboboxPortalContext.d.ts.map +1 -0
  63. package/lib/combobox/portal/ComboboxPortalContext.js +48 -0
  64. package/lib/combobox/portal/ComboboxPortalContext.js.map +1 -0
  65. package/lib/combobox/positioner/ComboboxPositioner.d.ts +11 -1
  66. package/lib/combobox/positioner/ComboboxPositioner.d.ts.map +1 -1
  67. package/lib/combobox/positioner/ComboboxPositioner.js +67 -7
  68. package/lib/combobox/positioner/ComboboxPositioner.js.map +1 -1
  69. package/lib/combobox/positioner/ComboboxPositionerContext.d.ts +9 -0
  70. package/lib/combobox/positioner/ComboboxPositionerContext.d.ts.map +1 -0
  71. package/lib/combobox/positioner/ComboboxPositionerContext.js +48 -0
  72. package/lib/combobox/positioner/ComboboxPositionerContext.js.map +1 -0
  73. package/lib/combobox/root/ComboboxItemsContext.d.ts +18 -0
  74. package/lib/combobox/root/ComboboxItemsContext.d.ts.map +1 -0
  75. package/lib/combobox/root/ComboboxItemsContext.js +55 -0
  76. package/lib/combobox/root/ComboboxItemsContext.js.map +1 -0
  77. package/lib/combobox/root/ComboboxRoot.d.ts +77 -21
  78. package/lib/combobox/root/ComboboxRoot.d.ts.map +1 -1
  79. package/lib/combobox/root/ComboboxRoot.js +4 -23
  80. package/lib/combobox/root/ComboboxRoot.js.map +1 -1
  81. package/lib/combobox/root/ComboboxRootContext.d.ts +4 -43
  82. package/lib/combobox/root/ComboboxRootContext.d.ts.map +1 -1
  83. package/lib/combobox/root/ComboboxRootContext.js.map +1 -1
  84. package/lib/combobox/root/ComboboxTransitionContext.d.ts +8 -0
  85. package/lib/combobox/root/ComboboxTransitionContext.d.ts.map +1 -0
  86. package/lib/combobox/root/ComboboxTransitionContext.js +44 -0
  87. package/lib/combobox/root/ComboboxTransitionContext.js.map +1 -0
  88. package/lib/combobox/root/useRenderComboboxRoot.d.ts +39 -0
  89. package/lib/combobox/root/useRenderComboboxRoot.d.ts.map +1 -0
  90. package/lib/combobox/root/useRenderComboboxRoot.js +136 -0
  91. package/lib/combobox/root/useRenderComboboxRoot.js.map +1 -0
  92. package/lib/combobox/store/ComboboxHandle.d.ts +42 -0
  93. package/lib/combobox/store/ComboboxHandle.d.ts.map +1 -0
  94. package/lib/combobox/store/ComboboxHandle.js +65 -0
  95. package/lib/combobox/store/ComboboxHandle.js.map +1 -0
  96. package/lib/combobox/store/ComboboxStore.d.ts +147 -0
  97. package/lib/combobox/store/ComboboxStore.d.ts.map +1 -0
  98. package/lib/combobox/store/ComboboxStore.js +127 -0
  99. package/lib/combobox/store/ComboboxStore.js.map +1 -0
  100. package/lib/combobox/value/ComboboxValue.d.ts.map +1 -1
  101. package/lib/combobox/value/ComboboxValue.js +2 -1
  102. package/lib/combobox/value/ComboboxValue.js.map +1 -1
  103. package/lib/context-menu/positioner/ContextMenuPositioner.d.ts +19 -3
  104. package/lib/context-menu/positioner/ContextMenuPositioner.d.ts.map +1 -1
  105. package/lib/context-menu/positioner/ContextMenuPositioner.js +56 -7
  106. package/lib/context-menu/positioner/ContextMenuPositioner.js.map +1 -1
  107. package/lib/context-menu/root/ContextMenuRoot.d.ts +8 -0
  108. package/lib/context-menu/root/ContextMenuRoot.d.ts.map +1 -1
  109. package/lib/dialog/backdrop/DialogBackdrop.d.ts +9 -0
  110. package/lib/dialog/backdrop/DialogBackdrop.d.ts.map +1 -1
  111. package/lib/dialog/backdrop/DialogBackdrop.js +3 -1
  112. package/lib/dialog/backdrop/DialogBackdrop.js.map +1 -1
  113. package/lib/dialog/popup/DialogPopup.d.ts +9 -0
  114. package/lib/dialog/popup/DialogPopup.d.ts.map +1 -1
  115. package/lib/dialog/popup/DialogPopup.js +2 -2
  116. package/lib/dialog/popup/DialogPopup.js.map +1 -1
  117. package/lib/dialog/popup/useDialogPopupProps.d.ts +2 -0
  118. package/lib/dialog/popup/useDialogPopupProps.d.ts.map +1 -1
  119. package/lib/dialog/popup/useDialogPopupProps.js +4 -0
  120. package/lib/dialog/popup/useDialogPopupProps.js.map +1 -1
  121. package/lib/dialog/root/DialogNestingContext.d.ts +20 -0
  122. package/lib/dialog/root/DialogNestingContext.d.ts.map +1 -0
  123. package/lib/dialog/root/DialogNestingContext.js +53 -0
  124. package/lib/dialog/root/DialogNestingContext.js.map +1 -0
  125. package/lib/dialog/root/useRenderDialogRoot.d.ts.map +1 -1
  126. package/lib/dialog/root/useRenderDialogRoot.js +26 -2
  127. package/lib/dialog/root/useRenderDialogRoot.js.map +1 -1
  128. package/lib/dialog/store/DialogStore.d.ts +19 -2
  129. package/lib/dialog/store/DialogStore.d.ts.map +1 -1
  130. package/lib/dialog/store/DialogStore.js +14 -2
  131. package/lib/dialog/store/DialogStore.js.map +1 -1
  132. package/lib/drawer/index.parts.d.ts +1 -1
  133. package/lib/drawer/index.parts.d.ts.map +1 -1
  134. package/lib/drawer/index.parts.js.map +1 -1
  135. package/lib/drawer/popup/DrawerPopup.d.ts +9 -0
  136. package/lib/drawer/popup/DrawerPopup.d.ts.map +1 -1
  137. package/lib/drawer/popup/DrawerPopup.js +3 -1
  138. package/lib/drawer/popup/DrawerPopup.js.map +1 -1
  139. package/lib/filter/index.d.ts +2 -0
  140. package/lib/filter/index.d.ts.map +1 -0
  141. package/lib/filter/index.js +6 -0
  142. package/lib/filter/index.js.map +1 -0
  143. package/lib/filter/useFilter.d.ts +45 -0
  144. package/lib/filter/useFilter.d.ts.map +1 -0
  145. package/lib/filter/useFilter.js +96 -0
  146. package/lib/filter/useFilter.js.map +1 -0
  147. package/lib/index.d.ts +1 -0
  148. package/lib/index.d.ts.map +1 -1
  149. package/lib/index.js +1 -0
  150. package/lib/index.js.map +1 -1
  151. package/lib/internals/field/useFieldControlRegistration.d.ts +25 -6
  152. package/lib/internals/field/useFieldControlRegistration.d.ts.map +1 -1
  153. package/lib/internals/field/useFieldControlRegistration.js +93 -6
  154. package/lib/internals/field/useFieldControlRegistration.js.map +1 -1
  155. package/lib/menu/popup/MenuPopup.d.ts +10 -0
  156. package/lib/menu/popup/MenuPopup.d.ts.map +1 -1
  157. package/lib/menu/popup/MenuPopup.js +10 -1
  158. package/lib/menu/popup/MenuPopup.js.map +1 -1
  159. package/lib/menu/positioner/MenuPositioner.d.ts +10 -0
  160. package/lib/menu/positioner/MenuPositioner.d.ts.map +1 -1
  161. package/lib/menu/positioner/MenuPositioner.js +9 -1
  162. package/lib/menu/positioner/MenuPositioner.js.map +1 -1
  163. package/lib/menu/store/MenuStore.d.ts +11 -0
  164. package/lib/menu/store/MenuStore.d.ts.map +1 -1
  165. package/lib/menu/store/MenuStore.js +4 -0
  166. package/lib/menu/store/MenuStore.js.map +1 -1
  167. package/lib/menu/submenu-trigger/MenuSubmenuTrigger.d.ts.map +1 -1
  168. package/lib/menu/submenu-trigger/MenuSubmenuTrigger.js +3 -0
  169. package/lib/menu/submenu-trigger/MenuSubmenuTrigger.js.map +1 -1
  170. package/lib/menu/trigger/MenuTrigger.d.ts.map +1 -1
  171. package/lib/menu/trigger/MenuTrigger.js +4 -1
  172. package/lib/menu/trigger/MenuTrigger.js.map +1 -1
  173. package/lib/meter/indicator/MeterIndicator.d.ts +2 -1
  174. package/lib/meter/indicator/MeterIndicator.d.ts.map +1 -1
  175. package/lib/meter/indicator/MeterIndicator.js +1 -2
  176. package/lib/meter/indicator/MeterIndicator.js.map +1 -1
  177. package/lib/meter/label/MeterLabel.d.ts +2 -1
  178. package/lib/meter/label/MeterLabel.d.ts.map +1 -1
  179. package/lib/meter/label/MeterLabel.js +1 -2
  180. package/lib/meter/label/MeterLabel.js.map +1 -1
  181. package/lib/meter/root/MeterRoot.d.ts +21 -0
  182. package/lib/meter/root/MeterRoot.d.ts.map +1 -1
  183. package/lib/meter/root/MeterRoot.js +2 -2
  184. package/lib/meter/root/MeterRoot.js.map +1 -1
  185. package/lib/meter/root/MeterRootContext.d.ts +5 -0
  186. package/lib/meter/root/MeterRootContext.d.ts.map +1 -1
  187. package/lib/meter/root/MeterRootContext.js.map +1 -1
  188. package/lib/meter/track/MeterTrack.d.ts +2 -1
  189. package/lib/meter/track/MeterTrack.d.ts.map +1 -1
  190. package/lib/meter/track/MeterTrack.js +1 -2
  191. package/lib/meter/track/MeterTrack.js.map +1 -1
  192. package/lib/meter/value/MeterValue.d.ts +2 -1
  193. package/lib/meter/value/MeterValue.d.ts.map +1 -1
  194. package/lib/meter/value/MeterValue.js +1 -2
  195. package/lib/meter/value/MeterValue.js.map +1 -1
  196. package/lib/number-field/input/NumberFieldInput.d.ts.map +1 -1
  197. package/lib/number-field/input/NumberFieldInput.js +11 -2
  198. package/lib/number-field/input/NumberFieldInput.js.map +1 -1
  199. package/lib/number-field/root/NumberFieldRoot.d.ts.map +1 -1
  200. package/lib/number-field/root/NumberFieldRoot.js +5 -2
  201. package/lib/number-field/root/NumberFieldRoot.js.map +1 -1
  202. package/lib/otp-field/input/OTPFieldInput.d.ts.map +1 -1
  203. package/lib/otp-field/input/OTPFieldInput.js +4 -0
  204. package/lib/otp-field/input/OTPFieldInput.js.map +1 -1
  205. package/lib/otp-field/root/OTPFieldRoot.d.ts.map +1 -1
  206. package/lib/otp-field/root/OTPFieldRoot.js +20 -2
  207. package/lib/otp-field/root/OTPFieldRoot.js.map +1 -1
  208. package/lib/popover/popup/PopoverPopup.d.ts +10 -0
  209. package/lib/popover/popup/PopoverPopup.d.ts.map +1 -1
  210. package/lib/popover/popup/PopoverPopup.js +10 -1
  211. package/lib/popover/popup/PopoverPopup.js.map +1 -1
  212. package/lib/popover/positioner/PopoverPositioner.d.ts +10 -0
  213. package/lib/popover/positioner/PopoverPositioner.d.ts.map +1 -1
  214. package/lib/popover/positioner/PopoverPositioner.js +4 -0
  215. package/lib/popover/positioner/PopoverPositioner.js.map +1 -1
  216. package/lib/popover/store/PopoverStore.d.ts +11 -0
  217. package/lib/popover/store/PopoverStore.d.ts.map +1 -1
  218. package/lib/popover/store/PopoverStore.js +4 -0
  219. package/lib/popover/store/PopoverStore.js.map +1 -1
  220. package/lib/popover/trigger/PopoverTrigger.d.ts.map +1 -1
  221. package/lib/popover/trigger/PopoverTrigger.js +4 -1
  222. package/lib/popover/trigger/PopoverTrigger.js.map +1 -1
  223. package/lib/progress/root/ProgressRoot.d.ts +21 -0
  224. package/lib/progress/root/ProgressRoot.d.ts.map +1 -1
  225. package/lib/progress/root/ProgressRoot.js +1 -1
  226. package/lib/progress/root/ProgressRoot.js.map +1 -1
  227. package/lib/radio-group/RadioGroup.d.ts.map +1 -1
  228. package/lib/radio-group/RadioGroup.js +5 -2
  229. package/lib/radio-group/RadioGroup.js.map +1 -1
  230. package/lib/select/backdrop/SelectBackdrop.d.ts.map +1 -1
  231. package/lib/select/backdrop/SelectBackdrop.js +3 -0
  232. package/lib/select/backdrop/SelectBackdrop.js.map +1 -1
  233. package/lib/select/index.parts.d.ts +1 -0
  234. package/lib/select/index.parts.d.ts.map +1 -1
  235. package/lib/select/index.parts.js +4 -1
  236. package/lib/select/index.parts.js.map +1 -1
  237. package/lib/select/popup/SelectPopup.d.ts +8 -0
  238. package/lib/select/popup/SelectPopup.d.ts.map +1 -1
  239. package/lib/select/popup/SelectPopup.js +10 -1
  240. package/lib/select/popup/SelectPopup.js.map +1 -1
  241. package/lib/select/positioner/SelectPositioner.d.ts +9 -0
  242. package/lib/select/positioner/SelectPositioner.d.ts.map +1 -1
  243. package/lib/select/positioner/SelectPositioner.js +9 -1
  244. package/lib/select/positioner/SelectPositioner.js.map +1 -1
  245. package/lib/select/root/SelectRoot.d.ts +45 -4
  246. package/lib/select/root/SelectRoot.d.ts.map +1 -1
  247. package/lib/select/root/SelectRoot.js +43 -5
  248. package/lib/select/root/SelectRoot.js.map +1 -1
  249. package/lib/select/store/SelectHandle.d.ts +42 -0
  250. package/lib/select/store/SelectHandle.d.ts.map +1 -0
  251. package/lib/select/store/SelectHandle.js +69 -0
  252. package/lib/select/store/SelectHandle.js.map +1 -0
  253. package/lib/select/store/SelectStore.d.ts +33 -0
  254. package/lib/select/store/SelectStore.d.ts.map +1 -1
  255. package/lib/select/store/SelectStore.js +17 -1
  256. package/lib/select/store/SelectStore.js.map +1 -1
  257. package/lib/select/trigger/SelectTrigger.d.ts +18 -3
  258. package/lib/select/trigger/SelectTrigger.d.ts.map +1 -1
  259. package/lib/select/trigger/SelectTrigger.js +51 -4
  260. package/lib/select/trigger/SelectTrigger.js.map +1 -1
  261. package/lib/slider/root/SliderRoot.d.ts.map +1 -1
  262. package/lib/slider/root/SliderRoot.js +9 -1
  263. package/lib/slider/root/SliderRoot.js.map +1 -1
  264. package/lib/slider/thumb/SliderThumb.d.ts.map +1 -1
  265. package/lib/slider/thumb/SliderThumb.js +10 -2
  266. package/lib/slider/thumb/SliderThumb.js.map +1 -1
  267. package/lib/switch/root/SwitchRoot.d.ts.map +1 -1
  268. package/lib/switch/root/SwitchRoot.js +6 -2
  269. package/lib/switch/root/SwitchRoot.js.map +1 -1
  270. package/lib/tabs/tab/TabsTab.d.ts +2 -10
  271. package/lib/tabs/tab/TabsTab.d.ts.map +1 -1
  272. package/lib/tooltip/popup/TooltipPopup.d.ts +10 -0
  273. package/lib/tooltip/popup/TooltipPopup.d.ts.map +1 -1
  274. package/lib/tooltip/popup/TooltipPopup.js +10 -1
  275. package/lib/tooltip/popup/TooltipPopup.js.map +1 -1
  276. package/lib/tooltip/positioner/TooltipPositioner.d.ts +10 -0
  277. package/lib/tooltip/positioner/TooltipPositioner.d.ts.map +1 -1
  278. package/lib/tooltip/positioner/TooltipPositioner.js +4 -0
  279. package/lib/tooltip/positioner/TooltipPositioner.js.map +1 -1
  280. package/lib/tooltip/store/TooltipStore.d.ts +11 -0
  281. package/lib/tooltip/store/TooltipStore.d.ts.map +1 -1
  282. package/lib/tooltip/store/TooltipStore.js +11 -1
  283. package/lib/tooltip/store/TooltipStore.js.map +1 -1
  284. package/lib/tooltip/trigger/TooltipTrigger.d.ts.map +1 -1
  285. package/lib/tooltip/trigger/TooltipTrigger.js +4 -1
  286. package/lib/tooltip/trigger/TooltipTrigger.js.map +1 -1
  287. package/package.json +1 -1
  288. package/src/alert-dialog/index.parts.ts +1 -1
  289. package/src/autocomplete/handle.ts +18 -0
  290. package/src/autocomplete/index.parts.ts +1 -0
  291. package/src/autocomplete/index.ts +1 -0
  292. package/src/autocomplete/root/AutocompleteRoot.tsx +65 -50
  293. package/src/avatar/fallback/AvatarFallback.tsx +3 -1
  294. package/src/avatar/image/AvatarImage.tsx +5 -0
  295. package/src/checkbox/root/CheckboxRoot.tsx +7 -2
  296. package/src/combobox/backdrop/ComboboxBackdrop.tsx +10 -2
  297. package/src/combobox/empty/ComboboxEmpty.tsx +5 -1
  298. package/src/combobox/index.parts.ts +1 -0
  299. package/src/combobox/index.ts +2 -0
  300. package/src/combobox/input/ComboboxInput.tsx +118 -23
  301. package/src/combobox/item/ComboboxItem.tsx +24 -5
  302. package/src/combobox/list/ComboboxList.tsx +7 -2
  303. package/src/combobox/popup/ComboboxPopup.tsx +44 -2
  304. package/src/combobox/portal/ComboboxPortal.tsx +19 -13
  305. package/src/combobox/portal/ComboboxPortalContext.ts +15 -0
  306. package/src/combobox/positioner/ComboboxPositioner.tsx +52 -7
  307. package/src/combobox/positioner/ComboboxPositionerContext.ts +23 -0
  308. package/src/combobox/root/ComboboxItemsContext.ts +32 -0
  309. package/src/combobox/root/ComboboxRoot.tsx +94 -56
  310. package/src/combobox/root/ComboboxRootContext.ts +3 -43
  311. package/src/combobox/root/ComboboxTransitionContext.ts +15 -0
  312. package/src/combobox/root/useRenderComboboxRoot.tsx +189 -0
  313. package/src/combobox/store/ComboboxHandle.ts +64 -0
  314. package/src/combobox/store/ComboboxStore.ts +249 -0
  315. package/src/combobox/value/ComboboxValue.tsx +2 -1
  316. package/src/context-menu/positioner/ContextMenuPositioner.tsx +90 -10
  317. package/src/context-menu/root/ContextMenuRoot.tsx +8 -0
  318. package/src/dialog/backdrop/DialogBackdrop.tsx +12 -1
  319. package/src/dialog/popup/DialogPopup.tsx +11 -2
  320. package/src/dialog/popup/useDialogPopupProps.ts +4 -0
  321. package/src/dialog/root/DialogNestingContext.ts +27 -0
  322. package/src/dialog/root/useRenderDialogRoot.tsx +37 -2
  323. package/src/dialog/store/DialogStore.ts +24 -2
  324. package/src/drawer/index.parts.ts +1 -1
  325. package/src/drawer/popup/DrawerPopup.tsx +12 -1
  326. package/src/filter/index.ts +5 -0
  327. package/src/filter/useFilter.ts +95 -0
  328. package/src/index.ts +1 -0
  329. package/src/internals/field/useFieldControlRegistration.ts +86 -6
  330. package/src/menu/popup/MenuPopup.tsx +20 -1
  331. package/src/menu/positioner/MenuPositioner.tsx +19 -1
  332. package/src/menu/store/MenuStore.ts +13 -0
  333. package/src/menu/submenu-trigger/MenuSubmenuTrigger.tsx +3 -0
  334. package/src/menu/trigger/MenuTrigger.tsx +5 -2
  335. package/src/meter/indicator/MeterIndicator.tsx +3 -4
  336. package/src/meter/label/MeterLabel.tsx +3 -4
  337. package/src/meter/root/MeterRoot.tsx +29 -4
  338. package/src/meter/root/MeterRootContext.ts +5 -0
  339. package/src/meter/track/MeterTrack.tsx +3 -4
  340. package/src/meter/value/MeterValue.tsx +3 -4
  341. package/src/number-field/input/NumberFieldInput.tsx +11 -2
  342. package/src/number-field/root/NumberFieldRoot.tsx +4 -2
  343. package/src/otp-field/input/OTPFieldInput.tsx +4 -0
  344. package/src/otp-field/root/OTPFieldRoot.tsx +22 -2
  345. package/src/popover/popup/PopoverPopup.tsx +20 -1
  346. package/src/popover/positioner/PopoverPositioner.tsx +14 -0
  347. package/src/popover/store/PopoverStore.ts +13 -0
  348. package/src/popover/trigger/PopoverTrigger.tsx +5 -2
  349. package/src/progress/root/ProgressRoot.tsx +25 -1
  350. package/src/radio-group/RadioGroup.tsx +5 -2
  351. package/src/select/backdrop/SelectBackdrop.tsx +4 -0
  352. package/src/select/index.parts.ts +1 -0
  353. package/src/select/popup/SelectPopup.tsx +18 -1
  354. package/src/select/positioner/SelectPositioner.tsx +18 -1
  355. package/src/select/root/SelectRoot.tsx +109 -9
  356. package/src/select/store/SelectHandle.ts +68 -0
  357. package/src/select/store/SelectStore.ts +44 -1
  358. package/src/select/trigger/SelectTrigger.tsx +81 -8
  359. package/src/slider/root/SliderRoot.tsx +11 -1
  360. package/src/slider/thumb/SliderThumb.tsx +10 -1
  361. package/src/switch/root/SwitchRoot.tsx +5 -2
  362. package/src/tabs/tab/TabsTab.tsx +2 -10
  363. package/src/tooltip/popup/TooltipPopup.tsx +20 -1
  364. package/src/tooltip/positioner/TooltipPositioner.tsx +14 -0
  365. package/src/tooltip/store/TooltipStore.ts +20 -1
  366. package/src/tooltip/trigger/TooltipTrigger.tsx +5 -2
  367. package/lib/combobox/root/useComboboxRoot.d.ts +0 -29
  368. package/lib/combobox/root/useComboboxRoot.d.ts.map +0 -1
  369. package/lib/combobox/root/useComboboxRoot.js +0 -168
  370. package/lib/combobox/root/useComboboxRoot.js.map +0 -1
  371. package/lib/utils/fastObjectShallowCompare.d.ts +0 -2
  372. package/lib/utils/fastObjectShallowCompare.d.ts.map +0 -1
  373. package/lib/utils/fastObjectShallowCompare.js +0 -29
  374. package/lib/utils/fastObjectShallowCompare.js.map +0 -1
  375. package/lib/utils/mergeObjects.d.ts +0 -2
  376. package/lib/utils/mergeObjects.d.ts.map +0 -1
  377. package/lib/utils/mergeObjects.js +0 -16
  378. package/lib/utils/mergeObjects.js.map +0 -1
  379. package/src/combobox/root/useComboboxRoot.ts +0 -190
  380. package/src/utils/fastObjectShallowCompare.ts +0 -30
  381. package/src/utils/mergeObjects.ts +0 -15
@@ -2,6 +2,8 @@
2
2
  import { Pressable, StyleSheet, type GestureResponderEvent } from 'react-native';
3
3
  import { useComboboxRootContext } from '../root/ComboboxRootContext';
4
4
  import { useRenderElement } from '../../use-render/useRenderElement';
5
+ import { createChangeEventDetails } from '../../utils/createChangeEventDetails';
6
+ import { REASONS } from '../../utils/reasons';
5
7
  import type { ZestUIComponentProps } from '../../types';
6
8
 
7
9
  /**
@@ -11,7 +13,8 @@ import type { ZestUIComponentProps } from '../../types';
11
13
  export function ComboboxBackdrop(componentProps: ComboboxBackdrop.Props) {
12
14
  const { render, className, style, ref, ...elementProps } = componentProps;
13
15
 
14
- const { open, setOpen } = useComboboxRootContext();
16
+ const store = useComboboxRootContext();
17
+ const open = store.useState('open');
15
18
 
16
19
  const state: ComboboxBackdropState = { open };
17
20
 
@@ -22,7 +25,12 @@ export function ComboboxBackdrop(componentProps: ComboboxBackdrop.Props) {
22
25
  {
23
26
  style: StyleSheet.absoluteFill,
24
27
  onPress(event: GestureResponderEvent) {
25
- setOpen(false, event);
28
+ if (store.select('disablePointerDismissal')) {
29
+ return;
30
+ }
31
+
32
+ store.setOpen(false, createChangeEventDetails(REASONS.outsidePress, event));
33
+ store.select('inputRef')?.current?.blur();
26
34
  },
27
35
  },
28
36
  elementProps,
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
  import { View } from 'react-native';
3
3
  import { useComboboxRootContext } from '../root/ComboboxRootContext';
4
+ import { useComboboxItemsContext } from '../root/ComboboxItemsContext';
4
5
  import { useRenderElement } from '../../use-render/useRenderElement';
5
6
  import type { ZestUIComponentProps } from '../../types';
6
7
 
@@ -11,7 +12,10 @@ import type { ZestUIComponentProps } from '../../types';
11
12
  export function ComboboxEmpty(componentProps: ComboboxEmpty.Props) {
12
13
  const { render, className, style, ref, ...elementProps } = componentProps;
13
14
 
14
- const { filteredItems, open } = useComboboxRootContext();
15
+ const store = useComboboxRootContext();
16
+ const { filteredItems } = useComboboxItemsContext();
17
+
18
+ const open = store.useState('open');
15
19
 
16
20
  const state: ComboboxEmptyState = { open };
17
21
 
@@ -1,4 +1,5 @@
1
1
  export { ComboboxRoot as Root } from './root/ComboboxRoot';
2
+ export { createComboboxHandle as createHandle, ComboboxHandle as Handle } from './store/ComboboxHandle';
2
3
  export { ComboboxInput as Input } from './input/ComboboxInput';
3
4
  export { ComboboxPortal as Portal } from './portal/ComboboxPortal';
4
5
  export { ComboboxBackdrop as Backdrop } from './backdrop/ComboboxBackdrop';
@@ -14,3 +14,5 @@ export {
14
14
  useComboboxRootContext,
15
15
  type ComboboxItem as ComboboxItemData,
16
16
  } from './root/ComboboxRootContext';
17
+ export { ComboboxHandle } from './store/ComboboxHandle';
18
+ export type { ComboboxItems } from './store/ComboboxStore';
@@ -1,36 +1,88 @@
1
1
  'use client';
2
2
  import * as React from 'react';
3
- import { TextInput } from 'react-native';
4
- import { useComboboxRootContext } from '../root/ComboboxRootContext';
3
+ import { TextInput, type LayoutChangeEvent } from 'react-native';
4
+ import { ComboboxRootContext } from '../root/ComboboxRootContext';
5
5
  import { useRenderElement } from '../../use-render/useRenderElement';
6
+ import { useId } from '../../hooks/useId';
7
+ import { useIsoLayoutEffect } from '../../hooks/useIsoLayoutEffect';
6
8
  import { useMergedRefs } from '../../hooks/useMergedRefs';
9
+ import { usePopupHandleStore } from '../../utils/popups/usePopupHandleStore';
10
+ import { createChangeEventDetails } from '../../utils/createChangeEventDetails';
11
+ import { REASONS } from '../../utils/reasons';
12
+ import type { ComboboxHandle } from '../store/ComboboxHandle';
13
+ import type { ComboboxStore } from '../store/ComboboxStore';
7
14
  import type { ZestUIComponentProps } from '../../types';
8
15
 
9
16
  /**
10
17
  * The text input that filters the list, and the element the popup is anchored to.
11
18
  * Renders a `<TextInput>`.
19
+ *
20
+ * Pass a `handle` to render the input outside of its `Combobox.Root`: there is
21
+ * no context reaching across, so the handle is what connects the two.
12
22
  */
13
- export function ComboboxInput(componentProps: ComboboxInput.Props) {
14
- const { render, className, style, ref, ...elementProps } = componentProps;
15
-
23
+ export function ComboboxInput<Payload = unknown>(componentProps: ComboboxInput.Props<Payload>) {
16
24
  const {
17
- open,
18
- setOpen,
19
- inputValue,
20
- setInputValue,
21
- disabled,
22
- openOnFocus,
23
- setTriggerNode,
24
- update,
25
- } = useComboboxRootContext();
25
+ render,
26
+ className,
27
+ style,
28
+ handle,
29
+ nativeID: idProp,
30
+ payload,
31
+ ref,
32
+ ...elementProps
33
+ } = componentProps;
34
+
35
+ const rootStore = React.useContext(ComboboxRootContext);
36
+ const handleStore = usePopupHandleStore(handle);
37
+
38
+ // An input inside a root uses that root; a detached one follows its handle,
39
+ // which resolves to the attached root's store or to an inert fallback.
40
+ const store = (handleStore ?? rootStore) as ComboboxStore | undefined;
41
+
42
+ if (store === undefined) {
43
+ throw new Error(
44
+ 'Zest: Combobox.Input must be placed within <Combobox.Root> or <Autocomplete.Root>, or given a `handle` it shares with one.',
45
+ );
46
+ }
47
+
48
+ const id = useId(idProp ?? undefined);
26
49
 
50
+ const open = store.useState('open');
51
+ const disabled = store.useState('disabled');
52
+ const inputValue = store.useState('inputValue');
53
+ const openOnFocus = store.useState('openOnFocus');
54
+ const update = store.useState('update');
55
+
56
+ const internalRef = React.useRef<TextInput>(null);
57
+
58
+ useIsoLayoutEffect(() => {
59
+ store.set('inputRef', internalRef);
60
+ }, [store]);
61
+
62
+ const triggerRef = React.useRef<unknown>(null);
27
63
  const anchorRef = React.useCallback(
28
64
  (node: unknown) => {
29
- setTriggerNode(node);
65
+ triggerRef.current = node;
66
+ store.set('triggerNode', node);
30
67
  },
31
- [setTriggerNode],
68
+ [store],
32
69
  );
33
- const mergedRef = useMergedRefs(ref, anchorRef);
70
+ const mergedRef = useMergedRefs(ref, anchorRef, internalRef);
71
+
72
+ // Registering into whichever store is current is what lets a handle resolve
73
+ // `open(id)`. The effect re-runs when the handle swaps stores, migrating the
74
+ // registration to the root that just attached.
75
+ useIsoLayoutEffect(() => {
76
+ if (id === undefined) {
77
+ return undefined;
78
+ }
79
+
80
+ store.context.triggerNodes.add(id, triggerRef.current);
81
+
82
+ return () => {
83
+ store.context.triggerNodes.delete(id);
84
+ };
85
+ }, [store, id]);
34
86
 
35
87
  const state: ComboboxInputState = { open, disabled };
36
88
 
@@ -39,20 +91,45 @@ export function ComboboxInput(componentProps: ComboboxInput.Props) {
39
91
  ref: mergedRef,
40
92
  props: [
41
93
  {
94
+ nativeID: id,
42
95
  value: inputValue,
43
96
  editable: !disabled,
44
97
  onChangeText(text: string) {
45
- setInputValue(text);
98
+ // One event details object is shared, so canceling the text change
99
+ // also stops the list from opening.
100
+ const eventDetails = createChangeEventDetails(REASONS.inputChange);
101
+
102
+ store.setInputValue(text, eventDetails);
103
+
104
+ if (eventDetails.isCanceled) {
105
+ return;
106
+ }
107
+
108
+ // Typing reopens the list so suggestions follow the query.
109
+ if (!store.select('open') && text.length > 0) {
110
+ store.setOpen(true, eventDetails);
111
+ }
46
112
  },
47
113
  onFocus() {
114
+ if (payload !== undefined) {
115
+ store.set('payload', payload);
116
+ }
117
+ if (id !== undefined) {
118
+ store.set('triggerId', id);
119
+ }
120
+
48
121
  if (openOnFocus) {
49
- setOpen(true);
122
+ store.setOpen(true, createChangeEventDetails(REASONS.triggerFocus));
50
123
  }
51
124
  },
52
- onLayout() {
125
+ onLayout(event: LayoutChangeEvent) {
126
+ const { width, height } = event.nativeEvent.layout;
127
+ store.set('triggerWidth', width);
128
+ store.set('triggerHeight', height);
53
129
  update?.();
54
130
  },
55
131
  accessibilityRole: 'search' as const,
132
+ accessibilityState: { expanded: open, disabled: disabled || undefined },
56
133
  'aria-expanded': open,
57
134
  'aria-autocomplete': 'list' as const,
58
135
  },
@@ -62,14 +139,32 @@ export function ComboboxInput(componentProps: ComboboxInput.Props) {
62
139
  }
63
140
 
64
141
  export interface ComboboxInputState {
142
+ /**
143
+ * Whether the list is currently open.
144
+ */
65
145
  open: boolean;
146
+ /**
147
+ * Whether the component should ignore user interaction.
148
+ */
66
149
  disabled: boolean;
67
150
  }
68
151
 
69
- export interface ComboboxInputProps
70
- extends Omit<ZestUIComponentProps<typeof TextInput, ComboboxInputState>, 'value'> {}
152
+ export interface ComboboxInputProps<Payload = unknown>
153
+ extends Omit<ZestUIComponentProps<typeof TextInput, ComboboxInputState>, 'value'> {
154
+ /**
155
+ * A handle shared with a `Combobox.Root`, which is what lets this input live
156
+ * outside of it. Create one with `Combobox.createHandle()`.
157
+ *
158
+ * The input's `nativeID` is the id a handle's `open(triggerId)` resolves.
159
+ */
160
+ handle?: ComboboxHandle | undefined;
161
+ /**
162
+ * A payload handed to the root's children when they are a function.
163
+ */
164
+ payload?: Payload | undefined;
165
+ }
71
166
 
72
167
  export namespace ComboboxInput {
73
168
  export type State = ComboboxInputState;
74
- export type Props = ComboboxInputProps;
169
+ export type Props<Payload = unknown> = ComboboxInputProps<Payload>;
75
170
  }
@@ -1,9 +1,12 @@
1
1
  'use client';
2
2
  import * as React from 'react';
3
3
  import { Pressable, type GestureResponderEvent } from 'react-native';
4
- import { useComboboxRootContext, type ComboboxItem as ComboboxItemData } from '../root/ComboboxRootContext';
4
+ import { useComboboxRootContext } from '../root/ComboboxRootContext';
5
5
  import { useRenderElement } from '../../use-render/useRenderElement';
6
6
  import { useCompositeListItem } from '../../internals/composite/list/useCompositeListItem';
7
+ import { createChangeEventDetails } from '../../utils/createChangeEventDetails';
8
+ import { REASONS } from '../../utils/reasons';
9
+ import type { ComboboxItem as ComboboxItemData } from '../store/ComboboxStore';
7
10
  import type { ZestUIComponentProps } from '../../types';
8
11
 
9
12
  /**
@@ -13,13 +16,18 @@ import type { ZestUIComponentProps } from '../../types';
13
16
  export function ComboboxItem(componentProps: ComboboxItem.Props) {
14
17
  const { render, className, style, item, ref, ...elementProps } = componentProps;
15
18
 
16
- const { selectedValue, selectItem } = useComboboxRootContext();
17
- const { onLayout } = useCompositeListItem();
19
+ const store = useComboboxRootContext();
20
+ const selectedValue = store.useState('value');
21
+
22
+ const { index, onLayout } = useCompositeListItem();
18
23
 
19
24
  const [pressed, setPressed] = React.useState(false);
20
25
  const selected = selectedValue === item.value;
21
26
 
22
- const state: ComboboxItemState = { selected, pressed };
27
+ const state: ComboboxItemState = React.useMemo(
28
+ () => ({ selected, pressed, index }),
29
+ [selected, pressed, index],
30
+ );
23
31
 
24
32
  return useRenderElement(Pressable, componentProps, {
25
33
  state,
@@ -28,7 +36,8 @@ export function ComboboxItem(componentProps: ComboboxItem.Props) {
28
36
  {
29
37
  onLayout,
30
38
  onPress(event: GestureResponderEvent) {
31
- selectItem(item, event);
39
+ store.selectItem(item, createChangeEventDetails(REASONS.itemPress, event));
40
+ store.select('inputRef')?.current?.blur();
32
41
  },
33
42
  onPressIn: () => setPressed(true),
34
43
  onPressOut: () => setPressed(false),
@@ -43,8 +52,18 @@ export function ComboboxItem(componentProps: ComboboxItem.Props) {
43
52
  }
44
53
 
45
54
  export interface ComboboxItemState {
55
+ /**
56
+ * Whether this item is the selected one.
57
+ */
46
58
  selected: boolean;
59
+ /**
60
+ * Whether the item is currently pressed.
61
+ */
47
62
  pressed: boolean;
63
+ /**
64
+ * The item's index in the list, in visual order.
65
+ */
66
+ index: number;
48
67
  }
49
68
 
50
69
  export interface ComboboxItemProps extends ZestUIComponentProps<typeof Pressable, ComboboxItemState> {
@@ -1,8 +1,10 @@
1
1
  'use client';
2
2
  import * as React from 'react';
3
3
  import { View } from 'react-native';
4
- import { useComboboxRootContext, type ComboboxItem } from '../root/ComboboxRootContext';
4
+ import { useComboboxRootContext } from '../root/ComboboxRootContext';
5
+ import { useComboboxItemsContext } from '../root/ComboboxItemsContext';
5
6
  import { useRenderElement } from '../../use-render/useRenderElement';
7
+ import type { ComboboxItem } from '../store/ComboboxStore';
6
8
  import type { ZestUIComponentProps } from '../../types';
7
9
 
8
10
  /**
@@ -16,7 +18,10 @@ import type { ZestUIComponentProps } from '../../types';
16
18
  export function ComboboxList(componentProps: ComboboxList.Props) {
17
19
  const { render, className, style, children, ref, ...elementProps } = componentProps;
18
20
 
19
- const { filteredItems, open } = useComboboxRootContext();
21
+ const store = useComboboxRootContext();
22
+ const { filteredItems } = useComboboxItemsContext();
23
+
24
+ const open = store.useState('open');
20
25
 
21
26
  const state: ComboboxListState = { open, empty: filteredItems.length === 0 };
22
27
 
@@ -1,8 +1,12 @@
1
1
  'use client';
2
2
  import { View } from 'react-native';
3
3
  import { useComboboxRootContext } from '../root/ComboboxRootContext';
4
+ import { useComboboxPositionerContext } from '../positioner/ComboboxPositionerContext';
5
+ import { useComboboxTransitionContext } from '../root/ComboboxTransitionContext';
4
6
  import { useRenderElement } from '../../use-render/useRenderElement';
5
7
  import { CompositeList } from '../../internals/composite/list/CompositeList';
8
+ import type { Align, Side } from '../../utils/useAnchorPositioning';
9
+ import type { TransitionStatus } from '../../internals/useTransitionStatus';
6
10
  import type { ZestUIComponentProps } from '../../types';
7
11
 
8
12
  /**
@@ -12,9 +16,22 @@ import type { ZestUIComponentProps } from '../../types';
12
16
  export function ComboboxPopup(componentProps: ComboboxPopup.Props) {
13
17
  const { render, className, style, ref, ...elementProps } = componentProps;
14
18
 
15
- const { open } = useComboboxRootContext();
19
+ const store = useComboboxRootContext();
20
+ const { side, align } = useComboboxPositionerContext();
21
+ const { transitionStatus } = useComboboxTransitionContext() ?? { transitionStatus: undefined };
16
22
 
17
- const state: ComboboxPopupState = { open };
23
+ const open = store.useState('open');
24
+ const triggerWidth = store.useState('triggerWidth');
25
+ const triggerHeight = store.useState('triggerHeight');
26
+
27
+ const state: ComboboxPopupState = {
28
+ open,
29
+ transitionStatus,
30
+ side,
31
+ align,
32
+ triggerWidth,
33
+ triggerHeight,
34
+ };
18
35
 
19
36
  const element = useRenderElement(View, componentProps, {
20
37
  state,
@@ -29,11 +46,36 @@ export function ComboboxPopup(componentProps: ComboboxPopup.Props) {
29
46
  ],
30
47
  });
31
48
 
49
+ // Items register here so they can be indexed in visual order.
32
50
  return <CompositeList>{element}</CompositeList>;
33
51
  }
34
52
 
35
53
  export interface ComboboxPopupState {
54
+ /**
55
+ * Whether the list is currently open.
56
+ */
36
57
  open: boolean;
58
+ /**
59
+ * The transition status of the list: `'starting'` as it opens (auto-clears to
60
+ * `undefined` after one frame), `'ending'` once it is closing.
61
+ */
62
+ transitionStatus: TransitionStatus;
63
+ /**
64
+ * The side the popup was actually placed on, after collision handling.
65
+ */
66
+ side: Side;
67
+ /**
68
+ * The alignment the popup was actually placed with.
69
+ */
70
+ align: Align;
71
+ /**
72
+ * The input's measured width, available for consumers to apply to the popup.
73
+ */
74
+ triggerWidth: number | undefined;
75
+ /**
76
+ * The input's measured height.
77
+ */
78
+ triggerHeight: number | undefined;
37
79
  }
38
80
 
39
81
  export interface ComboboxPopupProps extends ZestUIComponentProps<typeof View, ComboboxPopupState> {}
@@ -2,6 +2,9 @@
2
2
  import * as React from 'react';
3
3
  import { Modal, type NativeSyntheticEvent } from 'react-native';
4
4
  import { useComboboxRootContext } from '../root/ComboboxRootContext';
5
+ import { ComboboxPortalContext } from './ComboboxPortalContext';
6
+ import { createChangeEventDetails } from '../../utils/createChangeEventDetails';
7
+ import { REASONS } from '../../utils/reasons';
5
8
 
6
9
  /**
7
10
  * Moves the popup to the top of the app, as an RN `Modal` like the rest of the
@@ -10,7 +13,8 @@ import { useComboboxRootContext } from '../root/ComboboxRootContext';
10
13
  export function ComboboxPortal(props: ComboboxPortal.Props) {
11
14
  const { children, keepMounted = false } = props;
12
15
 
13
- const { open, setOpen } = useComboboxRootContext();
16
+ const store = useComboboxRootContext();
17
+ const open = store.useState('open');
14
18
 
15
19
  const shouldRender = open || keepMounted;
16
20
  if (!shouldRender) {
@@ -18,18 +22,20 @@ export function ComboboxPortal(props: ComboboxPortal.Props) {
18
22
  }
19
23
 
20
24
  return (
21
- <Modal
22
- transparent
23
- visible={open}
24
- animationType="fade"
25
- statusBarTranslucent
26
- navigationBarTranslucent
27
- onRequestClose={(event: NativeSyntheticEvent<unknown>) => {
28
- setOpen(false, event);
29
- }}
30
- >
31
- {children}
32
- </Modal>
25
+ <ComboboxPortalContext.Provider value={keepMounted}>
26
+ <Modal
27
+ transparent
28
+ visible={open}
29
+ animationType="fade"
30
+ statusBarTranslucent
31
+ navigationBarTranslucent
32
+ onRequestClose={(event: NativeSyntheticEvent<unknown>) => {
33
+ store.setOpen(false, createChangeEventDetails(REASONS.escapeKey, event));
34
+ }}
35
+ >
36
+ {children}
37
+ </Modal>
38
+ </ComboboxPortalContext.Provider>
33
39
  );
34
40
  }
35
41
 
@@ -0,0 +1,15 @@
1
+ 'use client';
2
+ import * as React from 'react';
3
+
4
+ export const ComboboxPortalContext = React.createContext<boolean | undefined>(undefined);
5
+
6
+ export function useComboboxPortalContext() {
7
+ const context = React.useContext(ComboboxPortalContext);
8
+ if (context === undefined) {
9
+ throw new Error(
10
+ 'Zest: ComboboxPortalContext is missing. <Combobox.Positioner> must be placed within <Combobox.Portal>.',
11
+ );
12
+ }
13
+
14
+ return context;
15
+ }
@@ -1,6 +1,9 @@
1
1
  'use client';
2
+ import * as React from 'react';
2
3
  import { View } from 'react-native';
3
4
  import { useComboboxRootContext } from '../root/ComboboxRootContext';
5
+ import { useComboboxPortalContext } from '../portal/ComboboxPortalContext';
6
+ import { ComboboxPositionerContext } from './ComboboxPositionerContext';
4
7
  import { useRenderElement } from '../../use-render/useRenderElement';
5
8
  import { useIsoLayoutEffect } from '../../hooks/useIsoLayoutEffect';
6
9
  import { useMergedRefs } from '../../hooks/useMergedRefs';
@@ -32,7 +35,13 @@ export function ComboboxPositioner(componentProps: ComboboxPositioner.Props) {
32
35
  ...elementProps
33
36
  } = componentProps;
34
37
 
35
- const { open, triggerNode, setUpdate } = useComboboxRootContext();
38
+ useComboboxPortalContext();
39
+ const store = useComboboxRootContext();
40
+
41
+ const open = store.useState('open');
42
+ const triggerNode = store.useState('triggerNode');
43
+ const triggerWidth = store.useState('triggerWidth');
44
+ const triggerHeight = store.useState('triggerHeight');
36
45
 
37
46
  const positioning = useAnchorPositioning({
38
47
  align,
@@ -51,25 +60,61 @@ export function ComboboxPositioner(componentProps: ComboboxPositioner.Props) {
51
60
  }, [refs, triggerNode]);
52
61
 
53
62
  useIsoLayoutEffect(() => {
54
- setUpdate(update);
55
- return () => setUpdate(undefined);
56
- }, [setUpdate, update]);
63
+ store.set('update', update);
64
+ return () => {
65
+ store.set('update', undefined);
66
+ };
67
+ }, [store, update]);
57
68
 
58
69
  const mergedRef = useMergedRefs(ref, refs.setFloating);
59
70
 
60
- const state: ComboboxPositionerState = { open, side: positioning.side, align: positioning.align };
71
+ const state: ComboboxPositionerState = {
72
+ open,
73
+ side: positioning.side,
74
+ align: positioning.align,
75
+ triggerWidth,
76
+ triggerHeight,
77
+ };
78
+
79
+ const contextValue: ComboboxPositionerContext = React.useMemo(
80
+ () => ({ side: positioning.side, align: positioning.align }),
81
+ [positioning.side, positioning.align],
82
+ );
61
83
 
62
- return useRenderElement(View, componentProps, {
84
+ const element = useRenderElement(View, componentProps, {
63
85
  state,
64
86
  ref: mergedRef,
65
- props: [{ style: positionerStyles, onLayout: () => update() }, elementProps],
87
+ props: [
88
+ {
89
+ style: positionerStyles,
90
+ onLayout() {
91
+ update();
92
+ },
93
+ },
94
+ elementProps,
95
+ ],
66
96
  });
97
+
98
+ return (
99
+ <ComboboxPositionerContext.Provider value={contextValue}>
100
+ {element}
101
+ </ComboboxPositionerContext.Provider>
102
+ );
67
103
  }
68
104
 
69
105
  export interface ComboboxPositionerState {
70
106
  open: boolean;
71
107
  side: Side;
72
108
  align: Align;
109
+ /**
110
+ * The input's measured width, available for consumers to apply to the popup.
111
+ * This is the React Native equivalent of the web's `--anchor-width` CSS variable.
112
+ */
113
+ triggerWidth: number | undefined;
114
+ /**
115
+ * The input's measured height.
116
+ */
117
+ triggerHeight: number | undefined;
73
118
  }
74
119
 
75
120
  export interface ComboboxPositionerProps
@@ -0,0 +1,23 @@
1
+ 'use client';
2
+ import * as React from 'react';
3
+ import type { Align, Side } from '../../utils/useAnchorPositioning';
4
+
5
+ export interface ComboboxPositionerContext {
6
+ side: Side;
7
+ align: Align;
8
+ }
9
+
10
+ export const ComboboxPositionerContext = React.createContext<
11
+ ComboboxPositionerContext | undefined
12
+ >(undefined);
13
+
14
+ export function useComboboxPositionerContext() {
15
+ const context = React.useContext(ComboboxPositionerContext);
16
+ if (context === undefined) {
17
+ throw new Error(
18
+ 'Zest: ComboboxPositionerContext is missing. <Combobox.Popup> must be placed within <Combobox.Positioner>.',
19
+ );
20
+ }
21
+
22
+ return context;
23
+ }
@@ -0,0 +1,32 @@
1
+ 'use client';
2
+ import * as React from 'react';
3
+ import type { ComboboxItem } from '../store/ComboboxStore';
4
+
5
+ export interface ComboboxItemsContext {
6
+ /**
7
+ * The items left after filtering by the current query.
8
+ */
9
+ filteredItems: ComboboxItem[];
10
+ }
11
+
12
+ /**
13
+ * The filtered view of the items.
14
+ *
15
+ * This is derived from the store rather than stored in it: a synced store value
16
+ * only lands in a layout effect, which would leave the list one commit behind
17
+ * the text the user just typed.
18
+ */
19
+ export const ComboboxItemsContext = React.createContext<ComboboxItemsContext | undefined>(
20
+ undefined,
21
+ );
22
+
23
+ export function useComboboxItemsContext() {
24
+ const context = React.useContext(ComboboxItemsContext);
25
+ if (context === undefined) {
26
+ throw new Error(
27
+ 'Zest: ComboboxItemsContext is missing. Combobox parts must be placed within <Combobox.Root> or <Autocomplete.Root>.',
28
+ );
29
+ }
30
+
31
+ return context;
32
+ }