@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
@@ -5,6 +5,7 @@ import { useControlled } from '../../hooks/useControlled';
5
5
  import { useId } from '../../hooks/useId';
6
6
  import { useStableCallback } from '../../hooks/useStableCallback';
7
7
  import { useRenderElement } from '../../use-render/useRenderElement';
8
+ import { useFieldControlRegistration } from '../../internals/field/useFieldControlRegistration';
8
9
  import { CompositeList } from '../../internals/composite/list/CompositeList';
9
10
  import type { ZestUIComponentProps } from '../../types';
10
11
  import type { ZestChangeEventDetails } from '../../utils/createChangeEventDetails';
@@ -31,7 +32,7 @@ export function OTPFieldRoot(componentProps: OTPFieldRoot.Props) {
31
32
  autoComplete = 'one-time-code',
32
33
  className,
33
34
  defaultValue,
34
- disabled = false,
35
+ disabled: disabledProp = false,
35
36
  id: idProp,
36
37
  length,
37
38
  mask = false,
@@ -48,6 +49,12 @@ export function OTPFieldRoot(componentProps: OTPFieldRoot.Props) {
48
49
  ...elementProps
49
50
  } = componentProps;
50
51
 
52
+ const { fieldDisabled, fieldProps, markChanged, markTouched } = useFieldControlRegistration({
53
+ initialValue: normalizeOTPValue(defaultValue ?? valueProp, length, validationType, normalizeValue),
54
+ });
55
+
56
+ const disabled = disabledProp || fieldDisabled;
57
+
51
58
  const id = useId(idProp);
52
59
 
53
60
  const [value, setValueState] = useControlled<string>({
@@ -103,8 +110,11 @@ export function OTPFieldRoot(componentProps: OTPFieldRoot.Props) {
103
110
  }
104
111
 
105
112
  setValueState(normalized);
113
+ markChanged(normalized);
106
114
 
107
115
  if (normalized.length === length) {
116
+ // A complete code ends the interaction; there is no blur to wait for.
117
+ markTouched(normalized);
108
118
  onValueComplete?.(normalized, createChangeEventDetails(eventDetails.reason));
109
119
  }
110
120
 
@@ -169,7 +179,17 @@ export function OTPFieldRoot(componentProps: OTPFieldRoot.Props) {
169
179
  const element = useRenderElement(View, componentProps, {
170
180
  state,
171
181
  ref,
172
- props: elementProps,
182
+ props: [
183
+ {
184
+ // The slots are separate inputs but one field: without a group role a
185
+ // screen reader announces N unrelated text boxes. Pass
186
+ // `accessibilityLabel` to name the code being entered.
187
+ role: 'group' as const,
188
+ accessibilityState: { disabled: disabled || undefined },
189
+ ...fieldProps,
190
+ },
191
+ elementProps,
192
+ ],
173
193
  });
174
194
 
175
195
  return (
@@ -20,10 +20,19 @@ export function PopoverPopup(componentProps: PopoverPopup.Props) {
20
20
  const { transitionStatus } = usePopoverTransitionContext() ?? { transitionStatus: undefined };
21
21
 
22
22
  const open = store.useState('open');
23
+ const triggerWidth = store.useState('triggerWidth');
24
+ const triggerHeight = store.useState('triggerHeight');
23
25
  const titleElementId = store.useState('titleElementId');
24
26
  const descriptionElementId = store.useState('descriptionElementId');
25
27
 
26
- const state: PopoverPopupState = { open, transitionStatus, side, align };
28
+ const state: PopoverPopupState = {
29
+ open,
30
+ transitionStatus,
31
+ side,
32
+ align,
33
+ triggerWidth,
34
+ triggerHeight,
35
+ };
27
36
 
28
37
  return useRenderElement(View, componentProps, {
29
38
  state,
@@ -61,6 +70,16 @@ export interface PopoverPopupState {
61
70
  * The alignment the popup was actually placed with.
62
71
  */
63
72
  align: Align;
73
+ /**
74
+ * The trigger's measured width, available for consumers to size the popup
75
+ * against its anchor. This is the React Native equivalent of the web's
76
+ * `--anchor-width` CSS variable.
77
+ */
78
+ triggerWidth: number | undefined;
79
+ /**
80
+ * The trigger's measured height.
81
+ */
82
+ triggerHeight: number | undefined;
64
83
  }
65
84
 
66
85
  export interface PopoverPopupProps extends ZestUIComponentProps<typeof View, PopoverPopupState> {}
@@ -38,6 +38,8 @@ export function PopoverPositioner(componentProps: PopoverPositioner.Props) {
38
38
  usePopoverPortalContext();
39
39
  const store = usePopoverRootContext();
40
40
  const open = store.useState('open');
41
+ const triggerWidth = store.useState('triggerWidth');
42
+ const triggerHeight = store.useState('triggerHeight');
41
43
  const triggerNode = store.useState('triggerNode');
42
44
 
43
45
  const positioning = useAnchorPositioning({
@@ -72,6 +74,8 @@ export function PopoverPositioner(componentProps: PopoverPositioner.Props) {
72
74
  open,
73
75
  side: positioning.side,
74
76
  align: positioning.align,
77
+ triggerWidth,
78
+ triggerHeight,
75
79
  };
76
80
 
77
81
  const contextValue: PopoverPositionerContext = React.useMemo(
@@ -114,6 +118,16 @@ export interface PopoverPositionerState {
114
118
  * The alignment the popup was actually placed with.
115
119
  */
116
120
  align: Align;
121
+ /**
122
+ * The trigger's measured width, available for consumers to size the popup
123
+ * against its anchor. This is the React Native equivalent of the web's
124
+ * `--anchor-width` CSS variable.
125
+ */
126
+ triggerWidth: number | undefined;
127
+ /**
128
+ * The trigger's measured height.
129
+ */
130
+ triggerHeight: number | undefined;
117
131
  }
118
132
 
119
133
  export interface PopoverPositionerProps
@@ -22,6 +22,15 @@ export type State = {
22
22
  * different subtree from the Trigger, so the store is what carries it across.
23
23
  */
24
24
  triggerNode: unknown;
25
+ /**
26
+ * The trigger's measured width, the React Native counterpart of the web's
27
+ * `--anchor-width` CSS variable.
28
+ */
29
+ triggerWidth: number | undefined;
30
+ /**
31
+ * The trigger's measured height.
32
+ */
33
+ triggerHeight: number | undefined;
25
34
  /**
26
35
  * Set by the Positioner so the Trigger can request a reposition when it is
27
36
  * laid out. React Native has no `autoUpdate`.
@@ -57,6 +66,8 @@ const selectors = {
57
66
  descriptionElementId: createSelector((state: State) => state.descriptionElementId),
58
67
  disablePointerDismissal: createSelector((state: State) => state.disablePointerDismissal),
59
68
  triggerNode: createSelector((state: State) => state.triggerNode),
69
+ triggerWidth: createSelector((state: State) => state.triggerWidth),
70
+ triggerHeight: createSelector((state: State) => state.triggerHeight),
60
71
  update: createSelector((state: State) => state.update),
61
72
  payload: createSelector((state: State) => state.payload),
62
73
  triggerId: createSelector((state: State) => state.triggerIdProp ?? state.triggerId),
@@ -75,6 +86,8 @@ export class PopoverStore extends ReactStore<Readonly<State>, Context, typeof se
75
86
  descriptionElementId: undefined,
76
87
  disablePointerDismissal: false,
77
88
  triggerNode: null,
89
+ triggerWidth: undefined,
90
+ triggerHeight: undefined,
78
91
  update: undefined,
79
92
  payload: undefined,
80
93
  triggerId: null,
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import * as React from 'react';
3
- import { Pressable, type GestureResponderEvent } from 'react-native';
3
+ import { Pressable, type GestureResponderEvent, type LayoutChangeEvent } from 'react-native';
4
4
  import { PopoverRootContext } from '../root/PopoverRootContext';
5
5
  import { useRenderElement } from '../../use-render/useRenderElement';
6
6
  import { useButton } from '../../internals/use-button/useButton';
@@ -99,7 +99,10 @@ export function PopoverTrigger<Payload = unknown>(componentProps: PopoverTrigger
99
99
  onPressOut() {
100
100
  setPressed(false);
101
101
  },
102
- onLayout() {
102
+ onLayout(event: LayoutChangeEvent) {
103
+ const { width, height } = event.nativeEvent.layout;
104
+ store.set('triggerWidth', width);
105
+ store.set('triggerHeight', height);
103
106
  // Nothing tracks the anchor globally in React Native, so a moved or
104
107
  // resized trigger has to ask the positioner to recompute.
105
108
  store.state.update?.();
@@ -62,7 +62,10 @@ export function ProgressRoot(componentProps: ProgressRoot.Props) {
62
62
  : formatNumber(percentageValue / 100, locale, { style: 'percent' });
63
63
  }
64
64
 
65
- const state: ProgressRootState = React.useMemo(() => ({ status }), [status]);
65
+ const state: ProgressRootState = React.useMemo(
66
+ () => ({ status, value: clampedValue, min, max, percent: percentageValue, formattedValue }),
67
+ [status, clampedValue, min, max, percentageValue, formattedValue],
68
+ );
66
69
 
67
70
  const contextValue: ProgressRootContext = React.useMemo(
68
71
  () => ({ formattedValue, percentageValue, setLabelId, state, value }),
@@ -102,6 +105,27 @@ export interface ProgressRootState {
102
105
  * The current status.
103
106
  */
104
107
  status: ProgressStatus;
108
+ /**
109
+ * The current value, clamped into `[min, max]`, or `null` while indeterminate.
110
+ */
111
+ value: number | null;
112
+ /**
113
+ * The minimum value.
114
+ */
115
+ min: number;
116
+ /**
117
+ * The maximum value.
118
+ */
119
+ max: number;
120
+ /**
121
+ * How far the value sits through the range, `0`–`100`, or `null` while
122
+ * indeterminate. This is what an indicator's width comes from.
123
+ */
124
+ percent: number | null;
125
+ /**
126
+ * The value as text, through `format`/`locale`. Empty while indeterminate.
127
+ */
128
+ formattedValue: string;
105
129
  }
106
130
 
107
131
  export interface ProgressRootProps extends ZestUIComponentProps<typeof View, ProgressRootState> {
@@ -29,7 +29,9 @@ export function RadioGroup<Value = any>(componentProps: RadioGroup.Props<Value>)
29
29
  ...elementProps
30
30
  } = componentProps;
31
31
 
32
- const { fieldDisabled, fieldProps, validateField } = useFieldControlRegistration();
32
+ const { fieldDisabled, fieldProps, markChanged, markTouched } = useFieldControlRegistration({
33
+ initialValue: defaultValue ?? valueProp,
34
+ });
33
35
 
34
36
  const disabled = disabledProp || fieldDisabled;
35
37
 
@@ -49,7 +51,8 @@ export function RadioGroup<Value = any>(componentProps: RadioGroup.Props<Value>)
49
51
  }
50
52
 
51
53
  setCheckedValueUnwrapped(value);
52
- validateField(value);
54
+ markChanged(value);
55
+ markTouched(value);
53
56
  },
54
57
  );
55
58
 
@@ -25,6 +25,10 @@ export function SelectBackdrop(componentProps: SelectBackdrop.Props) {
25
25
  {
26
26
  style: StyleSheet.absoluteFill,
27
27
  onPress(event: GestureResponderEvent) {
28
+ if (store.select('disablePointerDismissal')) {
29
+ return;
30
+ }
31
+
28
32
  store.setOpen(false, createChangeEventDetails(REASONS.outsidePress, event));
29
33
  },
30
34
  },
@@ -1,4 +1,5 @@
1
1
  export { SelectRoot as Root } from './root/SelectRoot';
2
+ export { createSelectHandle as createHandle, SelectHandle as Handle } from './store/SelectHandle';
2
3
  export { SelectLabel as Label } from './label/SelectLabel';
3
4
  export { SelectTrigger as Trigger } from './trigger/SelectTrigger';
4
5
  export { SelectValue as Value } from './value/SelectValue';
@@ -21,8 +21,17 @@ export function SelectPopup(componentProps: SelectPopup.Props) {
21
21
  const { transitionStatus } = useSelectTransitionContext() ?? { transitionStatus: undefined };
22
22
 
23
23
  const open = store.useState('open');
24
+ const triggerWidth = store.useState('triggerWidth');
25
+ const triggerHeight = store.useState('triggerHeight');
24
26
 
25
- const state: SelectPopupState = { open, transitionStatus, side, align };
27
+ const state: SelectPopupState = {
28
+ open,
29
+ transitionStatus,
30
+ side,
31
+ align,
32
+ triggerWidth,
33
+ triggerHeight,
34
+ };
26
35
 
27
36
  const element = useRenderElement(View, componentProps, {
28
37
  state,
@@ -59,6 +68,14 @@ export interface SelectPopupState {
59
68
  * The alignment the popup was actually placed with.
60
69
  */
61
70
  align: Align;
71
+ /**
72
+ * The trigger's measured width, available for consumers to apply to the popup.
73
+ */
74
+ triggerWidth: number | undefined;
75
+ /**
76
+ * The trigger's measured height.
77
+ */
78
+ triggerHeight: number | undefined;
62
79
  }
63
80
 
64
81
  export interface SelectPopupProps extends ZestUIComponentProps<typeof View, SelectPopupState> {}
@@ -39,6 +39,8 @@ export function SelectPositioner(componentProps: SelectPositioner.Props) {
39
39
  const store = useSelectRootContext();
40
40
  const open = store.useState('open');
41
41
  const triggerNode = store.useState('triggerNode');
42
+ const triggerWidth = store.useState('triggerWidth');
43
+ const triggerHeight = store.useState('triggerHeight');
42
44
 
43
45
  const positioning = useAnchorPositioning({
44
46
  align,
@@ -65,7 +67,13 @@ export function SelectPositioner(componentProps: SelectPositioner.Props) {
65
67
 
66
68
  const mergedRef = useMergedRefs(ref, refs.setFloating);
67
69
 
68
- const state: SelectPositionerState = { open, side: positioning.side, align: positioning.align };
70
+ const state: SelectPositionerState = {
71
+ open,
72
+ side: positioning.side,
73
+ align: positioning.align,
74
+ triggerWidth,
75
+ triggerHeight,
76
+ };
69
77
 
70
78
  const contextValue: SelectPositionerContext = React.useMemo(
71
79
  () => ({ side: positioning.side, align: positioning.align, arrowRef, arrowStyles }),
@@ -97,6 +105,15 @@ export interface SelectPositionerState {
97
105
  open: boolean;
98
106
  side: Side;
99
107
  align: Align;
108
+ /**
109
+ * The trigger's measured width, available for consumers to apply to the popup.
110
+ * This is the React Native equivalent of the web's `--anchor-width` CSS variable.
111
+ */
112
+ triggerWidth: number | undefined;
113
+ /**
114
+ * The trigger's measured height.
115
+ */
116
+ triggerHeight: number | undefined;
100
117
  }
101
118
 
102
119
  export interface SelectPositionerProps
@@ -1,9 +1,13 @@
1
1
  'use client';
2
2
  import * as React from 'react';
3
3
  import { useRefWithInit } from '../../hooks/useRefWithInit';
4
+ import { useStableCallback } from '../../hooks/useStableCallback';
4
5
  import { useTransitionStatus } from '../../internals/useTransitionStatus';
6
+ import { usePopupRootHandle } from '../../utils/popups/usePopupRootHandle';
7
+ import { useFieldControlRegistration } from '../../internals/field/useFieldControlRegistration';
5
8
  import type { ZestChangeEventDetails } from '../../utils/createChangeEventDetails';
6
9
  import type { REASONS } from '../../utils/reasons';
10
+ import type { SelectHandle } from '../store/SelectHandle';
7
11
  import { SelectStore, type SelectItems } from '../store/SelectStore';
8
12
  import { SelectRootContext } from './SelectRootContext';
9
13
  import { SelectTransitionContext } from './SelectTransitionContext';
@@ -15,12 +19,18 @@ import { SelectTransitionContext } from './SelectTransitionContext';
15
19
  * Unlike the web version there is no hidden `<select>`: React Native has no form
16
20
  * submission, so `name`/`form` are omitted. Multi-select is not ported yet.
17
21
  */
18
- export function SelectRoot<Value = any>(props: SelectRoot.Props<Value>) {
22
+ export function SelectRoot<Value = any, Payload = unknown>(
23
+ props: SelectRoot.Props<Value, Payload>,
24
+ ) {
19
25
  const {
26
+ actionsRef,
20
27
  children,
21
28
  defaultOpen = false,
29
+ defaultTriggerId = null,
22
30
  defaultValue,
23
- disabled = false,
31
+ disablePointerDismissal = false,
32
+ disabled: disabledProp = false,
33
+ handle,
24
34
  items,
25
35
  multiple = false,
26
36
  onOpenChange,
@@ -28,9 +38,16 @@ export function SelectRoot<Value = any>(props: SelectRoot.Props<Value>) {
28
38
  open,
29
39
  readOnly = false,
30
40
  required = false,
41
+ triggerId,
31
42
  value,
32
43
  } = props;
33
44
 
45
+ const { fieldDisabled, markChanged, markTouched } = useFieldControlRegistration({
46
+ initialValue: defaultValue ?? value ?? (multiple ? [] : undefined),
47
+ });
48
+
49
+ const disabled = disabledProp || fieldDisabled;
50
+
34
51
  const store = useRefWithInit(
35
52
  () =>
36
53
  new SelectStore({
@@ -45,18 +62,60 @@ export function SelectRoot<Value = any>(props: SelectRoot.Props<Value>) {
45
62
  disabled,
46
63
  readOnly,
47
64
  required,
65
+ disablePointerDismissal,
66
+ triggerId: defaultTriggerId,
67
+ triggerIdProp: triggerId,
48
68
  }),
49
69
  ).current;
50
70
 
71
+ // Wrapping the consumer's callbacks is what lets a select report itself to a
72
+ // surrounding `Field.Root`: choosing a value makes the field dirty, and
73
+ // closing the popup is the select's equivalent of a blur.
74
+ const handleValueChange = useStableCallback(
75
+ (nextValue: Value, eventDetails: SelectRoot.ChangeEventDetails) => {
76
+ onValueChange?.(nextValue, eventDetails);
77
+
78
+ if (eventDetails.isCanceled) {
79
+ return;
80
+ }
81
+
82
+ markChanged(nextValue);
83
+ },
84
+ );
85
+
86
+ const handleOpenChange = useStableCallback(
87
+ (nextOpen: boolean, eventDetails: SelectRoot.ChangeEventDetails) => {
88
+ onOpenChange?.(nextOpen, eventDetails);
89
+
90
+ if (eventDetails.isCanceled || nextOpen) {
91
+ return;
92
+ }
93
+
94
+ markTouched(store.select('value'));
95
+ },
96
+ );
97
+
51
98
  store.useControlledProp('openProp', open);
52
99
  store.useControlledProp('valueProp', value);
53
- store.useContextCallback('onOpenChange', onOpenChange);
54
- store.useContextCallback('onValueChange', onValueChange);
55
- store.useSyncedValues({ disabled, readOnly, required, items, multiple });
100
+ store.useControlledProp('triggerIdProp', triggerId);
101
+ store.useContextCallback('onOpenChange', handleOpenChange);
102
+ store.useContextCallback('onValueChange', handleValueChange);
103
+ store.useSyncedValues({
104
+ disabled,
105
+ readOnly,
106
+ required,
107
+ items,
108
+ multiple,
109
+ disablePointerDismissal,
110
+ });
111
+
112
+ usePopupRootHandle({ store, handle, actionsRef });
56
113
 
57
114
  const resolvedOpen = store.useState('open');
58
115
  const { transitionStatus } = useTransitionStatus(resolvedOpen, false, true);
59
116
 
117
+ const payload = store.useState('payload') as Payload;
118
+
60
119
  const transitionContextValue = React.useMemo(
61
120
  () => ({ transitionStatus }),
62
121
  [transitionStatus],
@@ -65,7 +124,7 @@ export function SelectRoot<Value = any>(props: SelectRoot.Props<Value>) {
65
124
  return (
66
125
  <SelectRootContext.Provider value={store}>
67
126
  <SelectTransitionContext.Provider value={transitionContextValue}>
68
- {children}
127
+ {typeof children === 'function' ? children(payload) : children}
69
128
  </SelectTransitionContext.Provider>
70
129
  </SelectRootContext.Provider>
71
130
  );
@@ -73,7 +132,19 @@ export function SelectRoot<Value = any>(props: SelectRoot.Props<Value>) {
73
132
 
74
133
  export interface SelectRootState {}
75
134
 
76
- export interface SelectRootProps<Value = any> {
135
+ export interface SelectRootActions {
136
+ /**
137
+ * Unmounts the popup without firing `onOpenChange`. Call it after an
138
+ * externally controlled closing animation finishes.
139
+ */
140
+ unmount: () => void;
141
+ /**
142
+ * Closes the popup, reporting the `imperative-action` reason.
143
+ */
144
+ close: () => void;
145
+ }
146
+
147
+ export interface SelectRootProps<Value = any, Payload = unknown> {
77
148
  /**
78
149
  * The value of the currently selected item.
79
150
  *
@@ -145,10 +216,38 @@ export interface SelectRootProps<Value = any> {
145
216
  * ```
146
217
  */
147
218
  items?: SelectItems | undefined;
219
+ /**
220
+ * Whether to prevent the popup from closing on presses outside it.
221
+ * @default false
222
+ */
223
+ disablePointerDismissal?: boolean | undefined;
224
+ /**
225
+ * A ref to imperative actions.
226
+ */
227
+ actionsRef?: React.RefObject<SelectRoot.Actions | null> | undefined;
228
+ /**
229
+ * A handle associating this select with triggers rendered outside it, and
230
+ * letting it be opened and closed imperatively. Create one with
231
+ * `Select.createHandle()`.
232
+ */
233
+ handle?: SelectHandle<Payload> | undefined;
234
+ /**
235
+ * The id of the trigger the popup is anchored to. Useful together with the
236
+ * `open` prop, to control which trigger a controlled select belongs to.
237
+ */
238
+ triggerId?: string | null | undefined;
239
+ /**
240
+ * The id of the trigger the popup is initially anchored to. Useful together
241
+ * with `defaultOpen`.
242
+ */
243
+ defaultTriggerId?: string | null | undefined;
148
244
  /**
149
245
  * The content of the select.
246
+ *
247
+ * Pass a function to receive the payload the select was opened with, via a
248
+ * trigger's `payload` prop.
150
249
  */
151
- children?: React.ReactNode;
250
+ children?: React.ReactNode | ((payload: Payload) => React.ReactNode);
152
251
  }
153
252
 
154
253
  export type SelectRootChangeEventReason =
@@ -163,7 +262,8 @@ export type SelectRootChangeEventDetails = ZestChangeEventDetails<SelectRootChan
163
262
 
164
263
  export namespace SelectRoot {
165
264
  export type State = SelectRootState;
166
- export type Props<TValue = any> = SelectRootProps<TValue>;
265
+ export type Props<TValue = any, TPayload = unknown> = SelectRootProps<TValue, TPayload>;
266
+ export type Actions = SelectRootActions;
167
267
  export type ChangeEventReason = SelectRootChangeEventReason;
168
268
  export type ChangeEventDetails = SelectRootChangeEventDetails;
169
269
  }
@@ -0,0 +1,68 @@
1
+ import { SelectStore } from './SelectStore';
2
+ import { BasePopupHandle } from '../../utils/popups/BasePopupHandle';
3
+
4
+ /**
5
+ * Controls a select imperatively, and associates `Select.Trigger`s rendered
6
+ * outside the root with it. Create one with `Select.createHandle()` and pass it
7
+ * to the root's and the triggers' `handle` prop.
8
+ *
9
+ * The imperative methods only take effect while a root using this handle is
10
+ * mounted; calls made before one attaches (or after it unmounts) are ignored.
11
+ */
12
+ // `Payload` is unused in the class body but load-bearing in the public API: a
13
+ // `Select.Root`'s `handle?: SelectHandle<Payload>` prop is what infers the
14
+ // payload type its `children(payload)` receives.
15
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
16
+ export class SelectHandle<Payload = unknown> extends BasePopupHandle<SelectStore, SelectStore> {
17
+ constructor() {
18
+ // `true`: a select popup is anchored to its trigger, so opening it by an
19
+ // unknown trigger id is an error rather than a warning — there would be
20
+ // nothing to anchor to.
21
+ super(new SelectStore(), 'Select', true);
22
+ }
23
+
24
+ /**
25
+ * Points the positioner at the trigger the popup was opened by. Without this
26
+ * an imperative open would anchor to whatever was last pressed.
27
+ */
28
+ protected override associateTrigger(store: SelectStore, triggerNode: unknown) {
29
+ if (triggerNode !== undefined) {
30
+ store.set('triggerNode', triggerNode);
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Opens the popup, anchored to the trigger with the given id.
36
+ *
37
+ * Call this from an event handler or an effect, never during rendering.
38
+ *
39
+ * @param triggerId The `nativeID` of a mounted `Select.Trigger` carrying this handle.
40
+ */
41
+ open(triggerId: string) {
42
+ this.openByTrigger(triggerId);
43
+ }
44
+
45
+ /**
46
+ * Closes the popup.
47
+ *
48
+ * Call this from an event handler or an effect, never during rendering.
49
+ */
50
+ close() {
51
+ this.closePopup();
52
+ }
53
+
54
+ /**
55
+ * Whether the popup is open. `false` while no root is attached.
56
+ */
57
+ get isOpen() {
58
+ return this.attachedStore?.select('open') ?? false;
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Creates a handle that connects a `Select.Root` to `Select.Trigger`s rendered
64
+ * outside it, and controls it imperatively.
65
+ */
66
+ export function createSelectHandle<Payload = unknown>(): SelectHandle<Payload> {
67
+ return new SelectHandle<Payload>();
68
+ }