@multiplatform.one/forms 7.70.0 → 7.72.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 (333) hide show
  1. package/dist/cjs/Button/index.cjs +16 -0
  2. package/dist/cjs/Button/index.native.js +16 -0
  3. package/dist/cjs/Button/index.native.js.map +1 -1
  4. package/dist/cjs/FloatingPanel/echoContext.cjs +39 -0
  5. package/dist/cjs/FloatingPanel/echoContext.native.js +42 -0
  6. package/dist/cjs/FloatingPanel/echoContext.native.js.map +1 -0
  7. package/dist/cjs/FloatingPanel/index.cjs +212 -80
  8. package/dist/cjs/FloatingPanel/index.native.js +92 -17
  9. package/dist/cjs/FloatingPanel/index.native.js.map +1 -1
  10. package/dist/cjs/FloatingPanel/panelWidth.cjs +92 -0
  11. package/dist/cjs/FloatingPanel/panelWidth.native.js +99 -0
  12. package/dist/cjs/FloatingPanel/panelWidth.native.js.map +1 -0
  13. package/dist/cjs/FloatingPanel/pointAnchor.cjs +15 -5
  14. package/dist/cjs/FloatingPanel/pointAnchor.native.js +15 -5
  15. package/dist/cjs/FloatingPanel/pointAnchor.native.js.map +1 -1
  16. package/dist/cjs/FloatingPanel/useFloatingPanel.cjs +58 -4
  17. package/dist/cjs/FloatingPanel/useFloatingPanel.native.js +69 -4
  18. package/dist/cjs/FloatingPanel/useFloatingPanel.native.js.map +1 -1
  19. package/dist/cjs/InputParts/index.cjs +20 -1
  20. package/dist/cjs/InputParts/index.native.js +22 -2
  21. package/dist/cjs/InputParts/index.native.js.map +1 -1
  22. package/dist/cjs/Wheel/NativeWheel.native.js +1 -1
  23. package/dist/cjs/Wheel/NativeWheel.native.js.map +1 -1
  24. package/dist/cjs/Wheel/index.cjs +2 -1
  25. package/dist/cjs/Wheel/index.native.js +4 -1
  26. package/dist/cjs/Wheel/index.native.js.map +1 -1
  27. package/dist/cjs/Wheel/wheelShared.cjs +6 -1
  28. package/dist/cjs/Wheel/wheelShared.native.js +7 -1
  29. package/dist/cjs/Wheel/wheelShared.native.js.map +1 -1
  30. package/dist/cjs/fields/Combobox/index.cjs +1 -0
  31. package/dist/cjs/fields/Combobox/index.native.js +1 -0
  32. package/dist/cjs/fields/Combobox/index.native.js.map +1 -1
  33. package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.cjs +6 -30
  34. package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.native.js +11 -34
  35. package/dist/cjs/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -1
  36. package/dist/cjs/fields/DatePicker/DatetimePicker.native.js.map +1 -1
  37. package/dist/cjs/fields/DatePicker/catalog.cjs +2 -28
  38. package/dist/cjs/fields/DatePicker/catalog.native.js +2 -30
  39. package/dist/cjs/fields/DatePicker/catalog.native.js.map +1 -1
  40. package/dist/cjs/fields/DatePicker/index.native.js.map +1 -1
  41. package/dist/cjs/fields/DatePicker/parts.cjs +11 -20
  42. package/dist/cjs/fields/DatePicker/parts.native.js +13 -22
  43. package/dist/cjs/fields/DatePicker/parts.native.js.map +1 -1
  44. package/dist/cjs/fields/SearchInput/index.cjs +23 -1
  45. package/dist/cjs/fields/SearchInput/index.native.js +23 -1
  46. package/dist/cjs/fields/SearchInput/index.native.js.map +1 -1
  47. package/dist/cjs/fields/Select/index.cjs +65 -44
  48. package/dist/cjs/fields/Select/index.native.js +69 -47
  49. package/dist/cjs/fields/Select/index.native.js.map +1 -1
  50. package/dist/cjs/fields/Select/shouldInlineChoices.cjs +3 -1
  51. package/dist/cjs/fields/Select/shouldInlineChoices.native.js +3 -1
  52. package/dist/cjs/fields/Select/shouldInlineChoices.native.js.map +1 -1
  53. package/dist/cjs/fields/TimePicker/catalog.cjs +4 -25
  54. package/dist/cjs/fields/TimePicker/catalog.native.js +7 -29
  55. package/dist/cjs/fields/TimePicker/catalog.native.js.map +1 -1
  56. package/dist/cjs/fields/TimePicker/index.native.js.map +1 -1
  57. package/dist/cjs/fields/TimePicker/parts.cjs +8 -21
  58. package/dist/cjs/fields/TimePicker/parts.native.js +8 -21
  59. package/dist/cjs/fields/TimePicker/parts.native.js.map +1 -1
  60. package/dist/cjs/index.native.js.map +1 -1
  61. package/dist/cjs/shared/floatingList.cjs +13 -4
  62. package/dist/cjs/shared/floatingList.native.js +15 -4
  63. package/dist/cjs/shared/floatingList.native.js.map +1 -1
  64. package/dist/esm/Button/index.mjs +17 -1
  65. package/dist/esm/Button/index.mjs.map +1 -1
  66. package/dist/esm/Button/index.native.js +17 -1
  67. package/dist/esm/Button/index.native.js.map +1 -1
  68. package/dist/esm/FloatingPanel/echoContext.mjs +11 -0
  69. package/dist/esm/FloatingPanel/echoContext.mjs.map +1 -0
  70. package/dist/esm/FloatingPanel/echoContext.native.js +11 -0
  71. package/dist/esm/FloatingPanel/echoContext.native.js.map +1 -0
  72. package/dist/esm/FloatingPanel/index.mjs +213 -83
  73. package/dist/esm/FloatingPanel/index.mjs.map +1 -1
  74. package/dist/esm/FloatingPanel/index.native.js +92 -19
  75. package/dist/esm/FloatingPanel/index.native.js.map +1 -1
  76. package/dist/esm/FloatingPanel/panelWidth.mjs +63 -0
  77. package/dist/esm/FloatingPanel/panelWidth.mjs.map +1 -0
  78. package/dist/esm/FloatingPanel/panelWidth.native.js +67 -0
  79. package/dist/esm/FloatingPanel/panelWidth.native.js.map +1 -0
  80. package/dist/esm/FloatingPanel/pointAnchor.mjs +15 -5
  81. package/dist/esm/FloatingPanel/pointAnchor.mjs.map +1 -1
  82. package/dist/esm/FloatingPanel/pointAnchor.native.js +15 -5
  83. package/dist/esm/FloatingPanel/pointAnchor.native.js.map +1 -1
  84. package/dist/esm/FloatingPanel/useFloatingPanel.mjs +58 -5
  85. package/dist/esm/FloatingPanel/useFloatingPanel.mjs.map +1 -1
  86. package/dist/esm/FloatingPanel/useFloatingPanel.native.js +69 -5
  87. package/dist/esm/FloatingPanel/useFloatingPanel.native.js.map +1 -1
  88. package/dist/esm/InputParts/index.mjs +21 -2
  89. package/dist/esm/InputParts/index.mjs.map +1 -1
  90. package/dist/esm/InputParts/index.native.js +23 -3
  91. package/dist/esm/InputParts/index.native.js.map +1 -1
  92. package/dist/esm/Wheel/NativeWheel.native.js +1 -1
  93. package/dist/esm/Wheel/NativeWheel.native.js.map +1 -1
  94. package/dist/esm/Wheel/index.mjs +2 -1
  95. package/dist/esm/Wheel/index.mjs.map +1 -1
  96. package/dist/esm/Wheel/index.native.js +4 -1
  97. package/dist/esm/Wheel/index.native.js.map +1 -1
  98. package/dist/esm/Wheel/wheelShared.mjs +6 -1
  99. package/dist/esm/Wheel/wheelShared.mjs.map +1 -1
  100. package/dist/esm/Wheel/wheelShared.native.js +7 -1
  101. package/dist/esm/Wheel/wheelShared.native.js.map +1 -1
  102. package/dist/esm/fields/Combobox/index.mjs +1 -0
  103. package/dist/esm/fields/Combobox/index.mjs.map +1 -1
  104. package/dist/esm/fields/Combobox/index.native.js +1 -0
  105. package/dist/esm/fields/Combobox/index.native.js.map +1 -1
  106. package/dist/esm/fields/DatePicker/DatetimePicker.catalog.mjs +6 -30
  107. package/dist/esm/fields/DatePicker/DatetimePicker.catalog.mjs.map +1 -1
  108. package/dist/esm/fields/DatePicker/DatetimePicker.catalog.native.js +11 -34
  109. package/dist/esm/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -1
  110. package/dist/esm/fields/DatePicker/DatetimePicker.native.js.map +1 -1
  111. package/dist/esm/fields/DatePicker/catalog.mjs +2 -28
  112. package/dist/esm/fields/DatePicker/catalog.mjs.map +1 -1
  113. package/dist/esm/fields/DatePicker/catalog.native.js +2 -30
  114. package/dist/esm/fields/DatePicker/catalog.native.js.map +1 -1
  115. package/dist/esm/fields/DatePicker/index.native.js.map +1 -1
  116. package/dist/esm/fields/DatePicker/parts.mjs +11 -20
  117. package/dist/esm/fields/DatePicker/parts.mjs.map +1 -1
  118. package/dist/esm/fields/DatePicker/parts.native.js +13 -22
  119. package/dist/esm/fields/DatePicker/parts.native.js.map +1 -1
  120. package/dist/esm/fields/SearchInput/index.mjs +25 -3
  121. package/dist/esm/fields/SearchInput/index.mjs.map +1 -1
  122. package/dist/esm/fields/SearchInput/index.native.js +25 -3
  123. package/dist/esm/fields/SearchInput/index.native.js.map +1 -1
  124. package/dist/esm/fields/Select/index.mjs +66 -45
  125. package/dist/esm/fields/Select/index.mjs.map +1 -1
  126. package/dist/esm/fields/Select/index.native.js +70 -48
  127. package/dist/esm/fields/Select/index.native.js.map +1 -1
  128. package/dist/esm/fields/Select/shouldInlineChoices.mjs +3 -1
  129. package/dist/esm/fields/Select/shouldInlineChoices.mjs.map +1 -1
  130. package/dist/esm/fields/Select/shouldInlineChoices.native.js +3 -1
  131. package/dist/esm/fields/Select/shouldInlineChoices.native.js.map +1 -1
  132. package/dist/esm/fields/TimePicker/catalog.mjs +4 -25
  133. package/dist/esm/fields/TimePicker/catalog.mjs.map +1 -1
  134. package/dist/esm/fields/TimePicker/catalog.native.js +7 -29
  135. package/dist/esm/fields/TimePicker/catalog.native.js.map +1 -1
  136. package/dist/esm/fields/TimePicker/index.native.js.map +1 -1
  137. package/dist/esm/fields/TimePicker/parts.mjs +8 -21
  138. package/dist/esm/fields/TimePicker/parts.mjs.map +1 -1
  139. package/dist/esm/fields/TimePicker/parts.native.js +8 -21
  140. package/dist/esm/fields/TimePicker/parts.native.js.map +1 -1
  141. package/dist/esm/index.mjs.map +1 -1
  142. package/dist/esm/index.native.js.map +1 -1
  143. package/dist/esm/shared/floatingList.mjs +14 -5
  144. package/dist/esm/shared/floatingList.mjs.map +1 -1
  145. package/dist/esm/shared/floatingList.native.js +16 -5
  146. package/dist/esm/shared/floatingList.native.js.map +1 -1
  147. package/dist/jsx/Button/index.mjs +17 -1
  148. package/dist/jsx/Button/index.mjs.map +1 -1
  149. package/dist/jsx/Button/index.native.js +16 -0
  150. package/dist/jsx/Button/index.native.js.map +1 -1
  151. package/dist/jsx/FloatingPanel/echoContext.mjs +11 -0
  152. package/dist/jsx/FloatingPanel/echoContext.mjs.map +1 -0
  153. package/dist/jsx/FloatingPanel/echoContext.native.js +42 -0
  154. package/dist/jsx/FloatingPanel/echoContext.native.js.map +1 -0
  155. package/dist/jsx/FloatingPanel/index.mjs +213 -83
  156. package/dist/jsx/FloatingPanel/index.mjs.map +1 -1
  157. package/dist/jsx/FloatingPanel/index.native.js +92 -17
  158. package/dist/jsx/FloatingPanel/index.native.js.map +1 -1
  159. package/dist/jsx/FloatingPanel/panelWidth.mjs +63 -0
  160. package/dist/jsx/FloatingPanel/panelWidth.mjs.map +1 -0
  161. package/dist/jsx/FloatingPanel/panelWidth.native.js +99 -0
  162. package/dist/jsx/FloatingPanel/panelWidth.native.js.map +1 -0
  163. package/dist/jsx/FloatingPanel/pointAnchor.mjs +15 -5
  164. package/dist/jsx/FloatingPanel/pointAnchor.mjs.map +1 -1
  165. package/dist/jsx/FloatingPanel/pointAnchor.native.js +15 -5
  166. package/dist/jsx/FloatingPanel/pointAnchor.native.js.map +1 -1
  167. package/dist/jsx/FloatingPanel/useFloatingPanel.mjs +58 -5
  168. package/dist/jsx/FloatingPanel/useFloatingPanel.mjs.map +1 -1
  169. package/dist/jsx/FloatingPanel/useFloatingPanel.native.js +69 -4
  170. package/dist/jsx/FloatingPanel/useFloatingPanel.native.js.map +1 -1
  171. package/dist/jsx/InputParts/index.mjs +21 -2
  172. package/dist/jsx/InputParts/index.mjs.map +1 -1
  173. package/dist/jsx/InputParts/index.native.js +22 -2
  174. package/dist/jsx/InputParts/index.native.js.map +1 -1
  175. package/dist/jsx/Wheel/NativeWheel.native.js +1 -1
  176. package/dist/jsx/Wheel/NativeWheel.native.js.map +1 -1
  177. package/dist/jsx/Wheel/index.mjs +2 -1
  178. package/dist/jsx/Wheel/index.mjs.map +1 -1
  179. package/dist/jsx/Wheel/index.native.js +4 -1
  180. package/dist/jsx/Wheel/index.native.js.map +1 -1
  181. package/dist/jsx/Wheel/wheelShared.mjs +6 -1
  182. package/dist/jsx/Wheel/wheelShared.mjs.map +1 -1
  183. package/dist/jsx/Wheel/wheelShared.native.js +7 -1
  184. package/dist/jsx/Wheel/wheelShared.native.js.map +1 -1
  185. package/dist/jsx/fields/Combobox/index.mjs +1 -0
  186. package/dist/jsx/fields/Combobox/index.mjs.map +1 -1
  187. package/dist/jsx/fields/Combobox/index.native.js +1 -0
  188. package/dist/jsx/fields/Combobox/index.native.js.map +1 -1
  189. package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.mjs +6 -30
  190. package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.mjs.map +1 -1
  191. package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.native.js +11 -34
  192. package/dist/jsx/fields/DatePicker/DatetimePicker.catalog.native.js.map +1 -1
  193. package/dist/jsx/fields/DatePicker/DatetimePicker.native.js.map +1 -1
  194. package/dist/jsx/fields/DatePicker/catalog.mjs +2 -28
  195. package/dist/jsx/fields/DatePicker/catalog.mjs.map +1 -1
  196. package/dist/jsx/fields/DatePicker/catalog.native.js +2 -30
  197. package/dist/jsx/fields/DatePicker/catalog.native.js.map +1 -1
  198. package/dist/jsx/fields/DatePicker/index.native.js.map +1 -1
  199. package/dist/jsx/fields/DatePicker/parts.mjs +11 -20
  200. package/dist/jsx/fields/DatePicker/parts.mjs.map +1 -1
  201. package/dist/jsx/fields/DatePicker/parts.native.js +13 -22
  202. package/dist/jsx/fields/DatePicker/parts.native.js.map +1 -1
  203. package/dist/jsx/fields/SearchInput/index.mjs +25 -3
  204. package/dist/jsx/fields/SearchInput/index.mjs.map +1 -1
  205. package/dist/jsx/fields/SearchInput/index.native.js +23 -1
  206. package/dist/jsx/fields/SearchInput/index.native.js.map +1 -1
  207. package/dist/jsx/fields/Select/index.mjs +66 -45
  208. package/dist/jsx/fields/Select/index.mjs.map +1 -1
  209. package/dist/jsx/fields/Select/index.native.js +69 -47
  210. package/dist/jsx/fields/Select/index.native.js.map +1 -1
  211. package/dist/jsx/fields/Select/shouldInlineChoices.mjs +3 -1
  212. package/dist/jsx/fields/Select/shouldInlineChoices.mjs.map +1 -1
  213. package/dist/jsx/fields/Select/shouldInlineChoices.native.js +3 -1
  214. package/dist/jsx/fields/Select/shouldInlineChoices.native.js.map +1 -1
  215. package/dist/jsx/fields/TimePicker/catalog.mjs +4 -25
  216. package/dist/jsx/fields/TimePicker/catalog.mjs.map +1 -1
  217. package/dist/jsx/fields/TimePicker/catalog.native.js +7 -29
  218. package/dist/jsx/fields/TimePicker/catalog.native.js.map +1 -1
  219. package/dist/jsx/fields/TimePicker/index.native.js.map +1 -1
  220. package/dist/jsx/fields/TimePicker/parts.mjs +8 -21
  221. package/dist/jsx/fields/TimePicker/parts.mjs.map +1 -1
  222. package/dist/jsx/fields/TimePicker/parts.native.js +8 -21
  223. package/dist/jsx/fields/TimePicker/parts.native.js.map +1 -1
  224. package/dist/jsx/index.js.map +1 -1
  225. package/dist/jsx/index.mjs.map +1 -1
  226. package/dist/jsx/index.native.js.map +1 -1
  227. package/dist/jsx/shared/floatingList.mjs +14 -5
  228. package/dist/jsx/shared/floatingList.mjs.map +1 -1
  229. package/dist/jsx/shared/floatingList.native.js +15 -4
  230. package/dist/jsx/shared/floatingList.native.js.map +1 -1
  231. package/package.json +8 -8
  232. package/src/Button/index.tsx +22 -0
  233. package/src/FloatingPanel/FloatingPanel.echoStretch.spec.tsx +67 -0
  234. package/src/FloatingPanel/FloatingPanel.menuFace.native.spec.tsx +193 -2
  235. package/src/FloatingPanel/FloatingPanel.seamlessCover.spec.tsx +237 -0
  236. package/src/FloatingPanel/echoContext.ts +22 -0
  237. package/src/FloatingPanel/index.native.tsx +106 -9
  238. package/src/FloatingPanel/index.tsx +310 -102
  239. package/src/FloatingPanel/panelWidth.spec.ts +158 -0
  240. package/src/FloatingPanel/panelWidth.ts +122 -0
  241. package/src/FloatingPanel/panelWidthContract.spec.ts +10 -10
  242. package/src/FloatingPanel/pointAnchor.spec.ts +64 -2
  243. package/src/FloatingPanel/pointAnchor.ts +28 -3
  244. package/src/FloatingPanel/useFloatingPanel.spec.tsx +124 -4
  245. package/src/FloatingPanel/useFloatingPanel.ts +106 -33
  246. package/src/InputParts/index.tsx +30 -1
  247. package/src/Wheel/NativeWheel.native.tsx +1 -1
  248. package/src/Wheel/Wheel.spec.tsx +9 -0
  249. package/src/Wheel/index.tsx +12 -3
  250. package/src/Wheel/wheelShared.ts +6 -2
  251. package/src/fields/Combobox/index.tsx +1 -0
  252. package/src/fields/DatePicker/DatePicker.stories.tsx +3 -3
  253. package/src/fields/DatePicker/DatetimePicker.catalog.tsx +17 -45
  254. package/src/fields/DatePicker/DatetimePicker.native.tsx +3 -0
  255. package/src/fields/DatePicker/catalog.tsx +8 -39
  256. package/src/fields/DatePicker/index.native.tsx +3 -0
  257. package/src/fields/DatePicker/parts.tsx +13 -23
  258. package/src/fields/DatePicker/seamlessCover.spec.tsx +180 -0
  259. package/src/fields/DatePicker/touchWeb.spec.tsx +109 -167
  260. package/src/fields/SearchInput/SearchInput.spec.tsx +40 -0
  261. package/src/fields/SearchInput/index.tsx +47 -2
  262. package/src/fields/Select/Select.containingBlock.spec.tsx +191 -0
  263. package/src/fields/Select/Select.stories.tsx +43 -0
  264. package/src/fields/Select/index.tsx +109 -45
  265. package/src/fields/Select/shouldInlineChoices.spec.ts +13 -0
  266. package/src/fields/Select/shouldInlineChoices.ts +6 -0
  267. package/src/fields/TimePicker/catalog.tsx +12 -33
  268. package/src/fields/TimePicker/index.native.tsx +2 -0
  269. package/src/fields/TimePicker/parts.tsx +6 -20
  270. package/src/index.ts +1 -0
  271. package/src/shared/floatingList.tsx +21 -5
  272. package/types/Button/index.d.ts.map +1 -1
  273. package/types/FloatingPanel/echoContext.d.ts +14 -0
  274. package/types/FloatingPanel/echoContext.d.ts.map +1 -0
  275. package/types/FloatingPanel/index.d.ts +59 -0
  276. package/types/FloatingPanel/index.d.ts.map +1 -1
  277. package/types/FloatingPanel/index.native.d.ts +9 -1
  278. package/types/FloatingPanel/index.native.d.ts.map +1 -1
  279. package/types/FloatingPanel/panelWidth.d.ts +71 -0
  280. package/types/FloatingPanel/panelWidth.d.ts.map +1 -0
  281. package/types/FloatingPanel/pointAnchor.d.ts +8 -1
  282. package/types/FloatingPanel/pointAnchor.d.ts.map +1 -1
  283. package/types/FloatingPanel/useFloatingPanel.d.ts +33 -2
  284. package/types/FloatingPanel/useFloatingPanel.d.ts.map +1 -1
  285. package/types/InputParts/index.d.ts +5 -1
  286. package/types/InputParts/index.d.ts.map +1 -1
  287. package/types/Wheel/index.d.ts.map +1 -1
  288. package/types/Wheel/wheelShared.d.ts +2 -1
  289. package/types/Wheel/wheelShared.d.ts.map +1 -1
  290. package/types/fields/Combobox/index.d.ts.map +1 -1
  291. package/types/fields/DatePicker/DatetimePicker.catalog.d.ts +6 -0
  292. package/types/fields/DatePicker/DatetimePicker.catalog.d.ts.map +1 -1
  293. package/types/fields/DatePicker/DatetimePicker.native.d.ts +3 -0
  294. package/types/fields/DatePicker/DatetimePicker.native.d.ts.map +1 -1
  295. package/types/fields/DatePicker/catalog.d.ts +6 -0
  296. package/types/fields/DatePicker/catalog.d.ts.map +1 -1
  297. package/types/fields/DatePicker/index.native.d.ts +3 -0
  298. package/types/fields/DatePicker/index.native.d.ts.map +1 -1
  299. package/types/fields/DatePicker/parts.d.ts +5 -7
  300. package/types/fields/DatePicker/parts.d.ts.map +1 -1
  301. package/types/fields/Input/index.d.ts +3 -1
  302. package/types/fields/Input/index.d.ts.map +1 -1
  303. package/types/fields/SearchInput/index.d.ts +11 -0
  304. package/types/fields/SearchInput/index.d.ts.map +1 -1
  305. package/types/fields/Select/index.d.ts +8 -1
  306. package/types/fields/Select/index.d.ts.map +1 -1
  307. package/types/fields/Select/shouldInlineChoices.d.ts +5 -1
  308. package/types/fields/Select/shouldInlineChoices.d.ts.map +1 -1
  309. package/types/fields/TimePicker/catalog.d.ts +7 -1
  310. package/types/fields/TimePicker/catalog.d.ts.map +1 -1
  311. package/types/fields/TimePicker/index.native.d.ts +2 -0
  312. package/types/fields/TimePicker/index.native.d.ts.map +1 -1
  313. package/types/fields/TimePicker/parts.d.ts +1 -3
  314. package/types/fields/TimePicker/parts.d.ts.map +1 -1
  315. package/types/index.d.ts +1 -0
  316. package/types/index.d.ts.map +1 -1
  317. package/types/shared/floatingList.d.ts +5 -1
  318. package/types/shared/floatingList.d.ts.map +1 -1
  319. package/dist/cjs/shared/touchWebPicker.cjs +0 -136
  320. package/dist/cjs/shared/touchWebPicker.native.js +0 -154
  321. package/dist/cjs/shared/touchWebPicker.native.js.map +0 -1
  322. package/dist/esm/shared/touchWebPicker.mjs +0 -105
  323. package/dist/esm/shared/touchWebPicker.mjs.map +0 -1
  324. package/dist/esm/shared/touchWebPicker.native.js +0 -120
  325. package/dist/esm/shared/touchWebPicker.native.js.map +0 -1
  326. package/dist/jsx/shared/touchWebPicker.mjs +0 -105
  327. package/dist/jsx/shared/touchWebPicker.mjs.map +0 -1
  328. package/dist/jsx/shared/touchWebPicker.native.js +0 -154
  329. package/dist/jsx/shared/touchWebPicker.native.js.map +0 -1
  330. package/src/shared/touchWebPicker.spec.ts +0 -98
  331. package/src/shared/touchWebPicker.tsx +0 -158
  332. package/types/shared/touchWebPicker.d.ts +0 -40
  333. package/types/shared/touchWebPicker.d.ts.map +0 -1
@@ -7,9 +7,12 @@ import { renderWithProviders } from "@multiplatform.one/test-utils";
7
7
  import { act } from "@testing-library/react";
8
8
  import { useState, type ReactNode } from "react";
9
9
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
10
- import { Text, XStack, YStack } from "tamagui";
10
+ import { Text, XStack, YStack, getTokens, getVariableValue } from "tamagui";
11
+ import { Button } from "../Button";
12
+ import { Input as InputParts } from "../InputParts";
11
13
  import { OverlayStackProvider } from "../shared/overlayStack";
12
14
  import { MENU_MIN_WIDTH, type CompactFace } from "./compactFace";
15
+ import type { PanelWidth } from "./panelWidth";
13
16
  import { FloatingPanel } from "./index.native";
14
17
  import { panelViewportPadding } from "./useFloatingPanel";
15
18
 
@@ -49,13 +52,22 @@ afterEach(() => {
49
52
  vi.useRealTimers();
50
53
  });
51
54
 
52
- function Menu({ face, attach = false }: { face?: CompactFace; attach?: boolean }) {
55
+ function Menu({
56
+ face,
57
+ attach = false,
58
+ width,
59
+ }: {
60
+ face?: CompactFace;
61
+ attach?: boolean;
62
+ width?: PanelWidth;
63
+ }) {
53
64
  const [open, setOpen] = useState(false);
54
65
  return (
55
66
  <FloatingPanel
56
67
  open={open}
57
68
  onOpenChange={setOpen}
58
69
  compactFace={face}
70
+ {...(width === undefined ? null : { panelWidth: width })}
59
71
  {...(attach ? { anchorMode: "attach" as const, triggerEcho: false } : null)}
60
72
  triggerSizing="content"
61
73
  contentPadding="none"
@@ -207,6 +219,134 @@ describe("FloatingPanel native menu face (FZ-7830)", () => {
207
219
  });
208
220
  });
209
221
 
222
+ function IconMenu() {
223
+ const [open, setOpen] = useState(false);
224
+ return (
225
+ <FloatingPanel
226
+ open={open}
227
+ onOpenChange={setOpen}
228
+ compactFace="menu"
229
+ anchorMode="cover-trigger"
230
+ triggerEcho={false}
231
+ coverAlign="auto"
232
+ triggerSizing="content"
233
+ contentPadding="none"
234
+ trigger={<Text>◐</Text>}
235
+ triggerA11y={{ label: "Appearance" }}
236
+ >
237
+ <Text>System</Text>
238
+ </FloatingPanel>
239
+ );
240
+ }
241
+
242
+ function ButtonMenu() {
243
+ const [open, setOpen] = useState(false);
244
+ return (
245
+ <FloatingPanel
246
+ open={open}
247
+ onOpenChange={setOpen}
248
+ compactFace="menu"
249
+ contentPadding="none"
250
+ trigger={<Button data-testid="pill">Status: All</Button>}
251
+ triggerA11y={{ label: "Filter status" }}
252
+ >
253
+ <Text>Open</Text>
254
+ </FloatingPanel>
255
+ );
256
+ }
257
+
258
+ function FieldMenu() {
259
+ const [open, setOpen] = useState(false);
260
+ return (
261
+ <FloatingPanel
262
+ open={open}
263
+ onOpenChange={setOpen}
264
+ compactFace="menu"
265
+ contentPadding="none"
266
+ trigger={
267
+ <InputParts>
268
+ <InputParts.Box data-testid="field-box">
269
+ <Text>United States</Text>
270
+ </InputParts.Box>
271
+ </InputParts>
272
+ }
273
+ triggerA11y={{ label: "Country" }}
274
+ >
275
+ <Text>Canada</Text>
276
+ </FloatingPanel>
277
+ );
278
+ }
279
+
280
+ const frame = () =>
281
+ document.querySelector<HTMLElement>('[data-testid="floating-panel-menu-surface"]');
282
+ const corners = (el: Element) =>
283
+ Array.from(el.classList)
284
+ .filter((c) => /^_b[tb][lr]r-/.test(c))
285
+ .sort();
286
+ const radiusAtoms = (px: number) =>
287
+ [`_bblr-${px}px`, `_bbrr-${px}px`, `_btlr-${px}px`, `_btrr-${px}px`].sort();
288
+
289
+ describe("LC-112 seamless cover on native (FZ-8438)", () => {
290
+ it("opens an icon trigger's menu ON the button from its top trailing corner (rv_d86cc201997dffd4)", () => {
291
+ trigger = { x: 330, y: 60, width: 44, height: 44 };
292
+ const result = renderWithProviders(<IconMenu />);
293
+ tap(result.getByRole("button", { name: "Appearance" }));
294
+ const panel = menu() as HTMLElement;
295
+ layout(panel, MENU_MIN_WIDTH, 180);
296
+ expect(panel.style.top).toBe(`${trigger.y}px`);
297
+ expect(panel.style.left).toBe(`${trigger.x + trigger.width - MENU_MIN_WIDTH}px`);
298
+ expect(echo()).toBeNull();
299
+ expect(sheet()).toBeNull();
300
+ expect(corners(frame() as HTMLElement)).toEqual(radiusAtoms(22));
301
+ });
302
+
303
+ it("keeps the shadow on an unclipped frame and clips inside it (FZ-8414)", () => {
304
+ const result = renderWithProviders(<IconMenu />);
305
+ tap(result.getByRole("button", { name: "Appearance" }));
306
+ const outer = frame() as HTMLElement;
307
+ expect(outer.className).not.toMatch(/(?:^| )_ox-hidden|_ov-hidden|_o-hidden/);
308
+ expect(getComputedStyle(outer).overflow).not.toBe("hidden");
309
+ const inner = outer.firstElementChild as HTMLElement;
310
+ expect(inner.className).toMatch(/hidden/);
311
+ });
312
+
313
+ it("echoes a field with no border or fill of its own and repeats the field's arc", () => {
314
+ trigger = { x: 20, y: 240, width: 300, height: 44 };
315
+ const result = renderWithProviders(<FieldMenu />);
316
+ const live = result.getByTestId("field-box");
317
+ const atom = corners(live).find((c) => c.startsWith("_btlr-")) as string;
318
+ expect(atom).toBeTruthy();
319
+ const token = atom.match(/^_btlr-t-radius-(.+)$/);
320
+ const drawn = token
321
+ ? Number(getVariableValue((getTokens().radius as Record<string, unknown>)[`$${token[1]}`]))
322
+ : Number(atom.match(/^_btlr-([\d.]+)px$/)?.[1]);
323
+ tap(result.getByRole("button", { name: "Country" }));
324
+ const row = echo() as HTMLElement;
325
+ expect(row).not.toBeNull();
326
+ const box = row.querySelector('[data-testid="field-box"]') as HTMLElement;
327
+ expect(box.className).toMatch(/_bbc-transparent/);
328
+ expect(box.className).toMatch(/_bg-transparent/);
329
+ expect(live.className).not.toMatch(/_bbc-transparent/);
330
+ expect(corners(frame() as HTMLElement)).toEqual(radiusAtoms(Math.min(drawn, 22)));
331
+ });
332
+
333
+ it("echoes a labelled Button trigger with no border or fill of its own", () => {
334
+ trigger = { x: 20, y: 240, width: 140, height: 44 };
335
+ const result = renderWithProviders(<ButtonMenu />);
336
+ const live = result.getByTestId("pill");
337
+ tap(result.getByRole("button", { name: "Filter status" }));
338
+ const row = echo() as HTMLElement;
339
+ expect(row).not.toBeNull();
340
+ // The echo is the trigger's own box at the start edge, not the menu's width.
341
+ expect(row.style.width).toBe("140px");
342
+ expect(row.style.alignSelf).toBe("flex-start");
343
+ const pill = row.querySelector('[data-testid="pill"]') as HTMLElement;
344
+ expect(pill.className).toMatch(/_bbc-transparent|_btc-transparent/);
345
+ expect(pill.className).toMatch(/_bg-transparent/);
346
+ expect(live.className).not.toBe(pill.className);
347
+ });
348
+ });
349
+
210
350
  /** The SHC account menu's shape: an avatar-sized trigger over rows that fill their width. */
211
351
  function AccountMenu() {
212
352
  const [open, setOpen] = useState(false);
@@ -263,3 +403,54 @@ describe("FloatingPanel native menu face width (FZ-8220)", () => {
263
403
  expect(menu()?.style.minWidth).toBe("320px");
264
404
  });
265
405
  });
406
+
407
+ describe("FloatingPanel native menu face panelWidth (LC-112, FZ-8438 r3)", () => {
408
+ const room = 390 - 2 * panelViewportPadding;
409
+ const open = (width?: PanelWidth) => {
410
+ const result = renderWithProviders(<Menu face="menu" width={width} />);
411
+ tap(result.getByRole("button", { name: "Stack actions" }));
412
+ return menu() as HTMLElement;
413
+ };
414
+
415
+ it('"content" is the default: the 250pt pull-down floor, up to the room', () => {
416
+ const panel = open();
417
+ expect(panel.style.minWidth).toBe(`${MENU_MIN_WIDTH}px`);
418
+ expect(panel.style.maxWidth).toBe(`${room}px`);
419
+ expect(panel.style.width).toBe("");
420
+ });
421
+
422
+ it('"trigger" is exactly the trigger\'s width', () => {
423
+ const panel = open("trigger");
424
+ expect([panel.style.minWidth, panel.style.width, panel.style.maxWidth]).toEqual([
425
+ "120px",
426
+ "120px",
427
+ "120px",
428
+ ]);
429
+ });
430
+
431
+ it('"screen" from a trigger in the gutter spans the gutters, start edge on the trigger\'s', () => {
432
+ const panel = open("screen");
433
+ const gutters = 390 - 2 * trigger.x;
434
+ expect(panel.style.width).toBe(`${gutters}px`);
435
+ layout(panel, gutters, 180);
436
+ expect(panel.style.left).toBe(`${trigger.x}px`);
437
+ expect(panel.style.top).toBe(`${trigger.y}px`);
438
+ });
439
+
440
+ it('"screen" from a trigger deep in the row fills the room, top edge on the trigger\'s', () => {
441
+ trigger = { x: 186, y: 240, width: 120, height: 44 };
442
+ const panel = open("screen");
443
+ expect(panel.style.width).toBe(`${room}px`);
444
+ layout(panel, room, 180);
445
+ expect(panel.style.left).toBe(`${panelViewportPadding}px`);
446
+ expect(panel.style.top).toBe(`${trigger.y}px`);
447
+ });
448
+
449
+ it("a number is a fixed width, capped at the room", () => {
450
+ expect(open(300).style.width).toBe("300px");
451
+ });
452
+
453
+ it("a number wider than the room stops at the margins", () => {
454
+ expect(open(900).style.width).toBe(`${room}px`);
455
+ });
456
+ });
@@ -0,0 +1,237 @@
1
+ /**
2
+ * LC-112 seamless cover (FZ-8438, Clay's rv_a07d4308a6c445b6 and
3
+ * rv_0ea65e640a0ef261 notes; rv_d86cc201997dffd4 for icon triggers). An open
4
+ * panel is ONE surface laid exactly over its trigger: same top edge, left
5
+ * edge and corner arc, the trigger's content echoed in place with no border,
6
+ * fill or divider of its own, drawn above the trigger.
7
+ */
8
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
9
+ import { Preset } from "@multiplatform.one/theme";
10
+ import { fireEvent, waitFor, within } from "@testing-library/react";
11
+ import { useState } from "react";
12
+ import { afterEach, describe, expect, it, vi } from "vitest";
13
+ import { Text } from "tamagui";
14
+ import { Button } from "../Button";
15
+ import { FloatingPanel } from "./index";
16
+
17
+ type Rect = { x: number; y: number; width: number; height: number };
18
+
19
+ function measure(trigger: Rect, panelWidth = 240) {
20
+ const original = HTMLElement.prototype.getBoundingClientRect;
21
+ const rect = {
22
+ ...trigger,
23
+ top: trigger.y,
24
+ left: trigger.x,
25
+ right: trigger.x + trigger.width,
26
+ bottom: trigger.y + trigger.height,
27
+ toJSON: () => ({}),
28
+ };
29
+ vi.spyOn(HTMLElement.prototype, "getBoundingClientRect").mockImplementation(
30
+ function (this: HTMLElement) {
31
+ if (this.hasAttribute("data-fp-reference") || this.dataset.testid === "field") return rect;
32
+ return original.call(this);
33
+ },
34
+ );
35
+ vi.spyOn(HTMLElement.prototype, "offsetWidth", "get").mockImplementation(
36
+ function (this: HTMLElement) {
37
+ return this.hasAttribute("data-fp-panel") ? panelWidth : 0;
38
+ },
39
+ );
40
+ vi.spyOn(HTMLElement.prototype, "scrollHeight", "get").mockImplementation(
41
+ function (this: HTMLElement) {
42
+ return this.hasAttribute("data-fp-panel") ? 160 : 0;
43
+ },
44
+ );
45
+ }
46
+
47
+ /** A field the way a browser paints it: border, fill and a 10px arc. */
48
+ function Field({ radius }: { radius: number }) {
49
+ return (
50
+ <div
51
+ data-testid="field"
52
+ role="combobox"
53
+ aria-expanded={false}
54
+ tabIndex={0}
55
+ style={{
56
+ borderTopLeftRadius: `${radius}px`,
57
+ borderRadius: `${radius}px`,
58
+ border: "1px solid rgb(200, 200, 200)",
59
+ borderBottom: "1px solid rgb(200, 200, 200)",
60
+ backgroundColor: "rgb(250, 250, 250)",
61
+ boxShadow: "0 1px 2px rgba(0, 0, 0, 0.1)",
62
+ }}
63
+ >
64
+ Mar 5, 2026
65
+ </div>
66
+ );
67
+ }
68
+
69
+ function FieldPanel({ radius = 10 }: { radius?: number }) {
70
+ const [open, setOpen] = useState(false);
71
+ return (
72
+ <FloatingPanel
73
+ open={open}
74
+ onOpenChange={setOpen}
75
+ contentPadding="none"
76
+ trigger={<Field radius={radius} />}
77
+ >
78
+ <Text>March 2026</Text>
79
+ </FloatingPanel>
80
+ );
81
+ }
82
+
83
+ function IconPanel({ align = "auto" }: { align?: "start" | "auto" }) {
84
+ const [open, setOpen] = useState(false);
85
+ return (
86
+ <FloatingPanel
87
+ open={open}
88
+ onOpenChange={setOpen}
89
+ anchorMode="cover-trigger"
90
+ triggerEcho={false}
91
+ coverAlign={align}
92
+ widthMode="fit-content"
93
+ triggerSizing="content"
94
+ trigger={<Button aria-label="Appearance">◐</Button>}
95
+ >
96
+ <Text>System</Text>
97
+ </FloatingPanel>
98
+ );
99
+ }
100
+
101
+ const corners = (el: Element) =>
102
+ Array.from(el.classList)
103
+ .filter((c) => /^_b[tb][lr]r-/.test(c))
104
+ .sort();
105
+
106
+ const radiusAtoms = (px: number) =>
107
+ [`_bblr-${px}px`, `_bbrr-${px}px`, `_btlr-${px}px`, `_btrr-${px}px`].sort();
108
+
109
+ async function openField(result: ReturnType<typeof renderWithProviders>) {
110
+ fireEvent.click(result.getByTestId("field"), { detail: 0 });
111
+ const panel = (await result.findByTestId("floating-panel-viewport")) as HTMLElement;
112
+ return panel;
113
+ }
114
+
115
+ afterEach(() => {
116
+ vi.restoreAllMocks();
117
+ });
118
+
119
+ describe("LC-112 seamless cover: one surface over the field (FZ-8438)", () => {
120
+ const field = { x: 16, y: 42, width: 400, height: 40 };
121
+
122
+ it("lays the panel's top and start edges on the field's", async () => {
123
+ measure(field);
124
+ const result = renderWithProviders(<FieldPanel />);
125
+ const panel = await openField(result);
126
+ await waitFor(() => expect(panel.style.top).toBe(`${field.y}px`));
127
+ expect(panel.style.left).toBe(`${field.x}px`);
128
+ const echo = panel.querySelector<HTMLElement>("[data-fp-trigger-row]");
129
+ expect(echo?.style.width).toBe(`${field.width}px`);
130
+ expect(echo?.style.height).toBe(`${field.height}px`);
131
+ });
132
+
133
+ it("draws the field's own arc at all four corners", async () => {
134
+ measure(field);
135
+ const result = renderWithProviders(<FieldPanel radius={10} />);
136
+ const panel = await openField(result);
137
+ await waitFor(() => expect(corners(panel)).toEqual(radiusAtoms(10)));
138
+ });
139
+
140
+ it("keeps the field's arc past the container cap (full preset, 20px on a 40px field)", async () => {
141
+ measure(field);
142
+ const result = renderWithProviders(
143
+ <Preset overrides={{ borderRadius: "full" }}>
144
+ <FieldPanel radius={50} />
145
+ </Preset>,
146
+ );
147
+ const panel = await openField(result);
148
+ await waitFor(() => expect(corners(panel)).toEqual(radiusAtoms(20)));
149
+ });
150
+
151
+ it("echoes the field with no border, fill, shadow or divider of its own", async () => {
152
+ measure(field);
153
+ const result = renderWithProviders(<FieldPanel />);
154
+ const panel = await openField(result);
155
+ const frame = await waitFor(() => {
156
+ const found = panel.querySelector<HTMLElement>("[data-fp-echo-frame]");
157
+ expect(found).not.toBeNull();
158
+ return found as HTMLElement;
159
+ });
160
+ expect(frame.textContent).toBe("Mar 5, 2026");
161
+ expect(frame.style.getPropertyValue("border-color")).toBe("transparent");
162
+ expect(frame.style.getPropertyPriority("border-color")).toBe("important");
163
+ expect(frame.style.getPropertyValue("background-color")).toBe("transparent");
164
+ expect(frame.style.getPropertyValue("box-shadow")).toBe("none");
165
+ const bottom = getComputedStyle(frame).borderBottomColor;
166
+ expect(["transparent", "rgba(0, 0, 0, 0)"]).toContain(bottom);
167
+ // Layout keeps the field's widths, so the echoed text sits where it did.
168
+ expect(getComputedStyle(frame).borderBottomWidth).toBe("1px");
169
+ const row = panel.querySelector<HTMLElement>("[data-fp-trigger-row]") as HTMLElement;
170
+ expect(row.style.backgroundColor).toBe(getComputedStyle(panel).backgroundColor);
171
+ // The live field keeps its chrome; only the echo drops it.
172
+ expect(result.getByTestId("field").style.backgroundColor).toBe("rgb(250, 250, 250)");
173
+ });
174
+
175
+ it("draws above the field: a fixed, stacked layer later in the document", async () => {
176
+ measure(field);
177
+ const result = renderWithProviders(<FieldPanel />);
178
+ const panel = await openField(result);
179
+ await waitFor(() => expect(panel.style.top).toBe(`${field.y}px`));
180
+ expect(panel.style.position).toBe("fixed");
181
+ expect(Number(panel.style.zIndex)).toBeGreaterThan(0);
182
+ const live = result.getByTestId("field");
183
+ expect(live.compareDocumentPosition(panel) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
184
+ expect(live.contains(panel)).toBe(false);
185
+ });
186
+ });
187
+
188
+ describe("LC-112 icon trigger: the menu opens on its button (rv_d86cc201997dffd4)", () => {
189
+ it("opens from the button's top trailing corner at the end edge, with no echo row", async () => {
190
+ const viewportWidth = document.documentElement.clientWidth || window.innerWidth;
191
+ const button = { x: viewportWidth - 16 - 44, y: 12, width: 44, height: 44 };
192
+ measure(button, 200);
193
+ const result = renderWithProviders(<IconPanel />);
194
+ fireEvent.click(result.getByRole("button", { name: "Appearance" }), { detail: 0 });
195
+ const panel = (await result.findByTestId("floating-panel-viewport")) as HTMLElement;
196
+ await waitFor(() => expect(panel.style.top).toBe(`${button.y}px`));
197
+ expect(panel.style.left).toBe(`${button.x + button.width - 200}px`);
198
+ expect(panel.style.transformOrigin).toBe("top right");
199
+ expect(panel.querySelector("[data-fp-trigger-row]")).toBeNull();
200
+ expect(result.queryByTestId("floating-panel-sheet")).toBeNull();
201
+ });
202
+
203
+ it("opens from the button's top leading corner where that fits", async () => {
204
+ const button = { x: 16, y: 12, width: 44, height: 44 };
205
+ measure(button, 200);
206
+ const result = renderWithProviders(<IconPanel />);
207
+ fireEvent.click(result.getByRole("button", { name: "Appearance" }), { detail: 0 });
208
+ const panel = (await result.findByTestId("floating-panel-viewport")) as HTMLElement;
209
+ await waitFor(() => expect(panel.style.top).toBe(`${button.y}px`));
210
+ expect(panel.style.left).toBe(`${button.x}px`);
211
+ expect(panel.style.transformOrigin).toBe("top left");
212
+ expect(within(panel).queryByRole("button", { name: "Appearance" })).toBeNull();
213
+ });
214
+
215
+ it("slides up over its button near the bottom edge instead of opening a sheet", async () => {
216
+ const button = { x: 16, y: window.innerHeight - 60, width: 44, height: 44 };
217
+ measure(button, 200);
218
+ const result = renderWithProviders(<IconPanel />);
219
+ fireEvent.click(result.getByRole("button", { name: "Appearance" }), { detail: 0 });
220
+ const panel = (await result.findByTestId("floating-panel-viewport")) as HTMLElement;
221
+ await waitFor(() => expect(panel.style.visibility).toBe("visible"));
222
+ const top = parseFloat(panel.style.top);
223
+ expect(top).toBeLessThan(button.y);
224
+ expect(top + 160).toBeGreaterThanOrEqual(button.y + button.height);
225
+ expect(panel.style.left).toBe(`${button.x}px`);
226
+ expect(result.queryByTestId("floating-panel-sheet")).toBeNull();
227
+ });
228
+
229
+ it("never end-aligns a custom first row (triggerEcho off, coverAlign start): it collides to the sheet", async () => {
230
+ const viewportWidth = document.documentElement.clientWidth || window.innerWidth;
231
+ const button = { x: viewportWidth - 16 - 44, y: 12, width: 44, height: 44 };
232
+ measure(button, 200);
233
+ const result = renderWithProviders(<IconPanel align="start" />);
234
+ fireEvent.click(result.getByRole("button", { name: "Appearance" }), { detail: 0 });
235
+ expect(await result.findByTestId("floating-panel-sheet")).toBeTruthy();
236
+ });
237
+ });
@@ -0,0 +1,22 @@
1
+ import { createContext, useContext } from "react";
2
+
3
+ /**
4
+ * LC-112 seamless cover (FZ-8438): true while a field is drawn as the echo row
5
+ * of the panel covering it. The field keeps its geometry and drops its own
6
+ * border, fill and shadow, so the panel's edge and surface are the only ones.
7
+ */
8
+ export const PanelEchoContext = createContext(false);
9
+
10
+ export function useInPanelEcho(): boolean {
11
+ return useContext(PanelEchoContext);
12
+ }
13
+
14
+ /**
15
+ * Native has no computed style to read, so a trigger's frame reports the
16
+ * radius it draws and a covering panel repeats it at all four corners.
17
+ */
18
+ export const PanelTriggerRadiusContext = createContext<((radius: number) => void) | null>(null);
19
+
20
+ export function usePanelTriggerRadiusReporter(): ((radius: number) => void) | null {
21
+ return useContext(PanelTriggerRadiusContext);
22
+ }