@multiplatform.one/forms 7.77.1 → 7.78.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 (296) hide show
  1. package/dist/cjs/Button/IconButtonGroup.cjs +58 -27
  2. package/dist/cjs/Button/IconButtonGroup.native.js +64 -29
  3. package/dist/cjs/Button/IconButtonGroup.native.js.map +1 -1
  4. package/dist/cjs/Button/circleGlyph.cjs +12 -2
  5. package/dist/cjs/Button/circleGlyph.native.js +12 -1
  6. package/dist/cjs/Button/circleGlyph.native.js.map +1 -1
  7. package/dist/cjs/Button/glass.cjs +2 -1
  8. package/dist/cjs/Button/glass.native.js +44 -19
  9. package/dist/cjs/Button/glass.native.js.map +1 -1
  10. package/dist/cjs/Button/iconButtonGroupContext.cjs +7 -1
  11. package/dist/cjs/Button/iconButtonGroupContext.native.js +7 -1
  12. package/dist/cjs/Button/iconButtonGroupContext.native.js.map +1 -1
  13. package/dist/cjs/Button/index.cjs +15 -23
  14. package/dist/cjs/Button/index.native.js +15 -24
  15. package/dist/cjs/Button/index.native.js.map +1 -1
  16. package/dist/cjs/Button/webGlass.cjs +9 -5
  17. package/dist/cjs/Button/webGlass.native.js +9 -5
  18. package/dist/cjs/Button/webGlass.native.js.map +1 -1
  19. package/dist/cjs/FloatingPanel/coverRect.cjs +50 -0
  20. package/dist/cjs/FloatingPanel/coverRect.native.js +54 -0
  21. package/dist/cjs/FloatingPanel/coverRect.native.js.map +1 -0
  22. package/dist/cjs/FloatingPanel/iconEcho.cjs +3 -1
  23. package/dist/cjs/FloatingPanel/iconEcho.native.js +3 -1
  24. package/dist/cjs/FloatingPanel/iconEcho.native.js.map +1 -1
  25. package/dist/cjs/FloatingPanel/index.cjs +23 -13
  26. package/dist/cjs/FloatingPanel/index.native.js +41 -15
  27. package/dist/cjs/FloatingPanel/index.native.js.map +1 -1
  28. package/dist/cjs/InputParts/index.cjs +5 -0
  29. package/dist/cjs/InputParts/index.native.js +7 -0
  30. package/dist/cjs/InputParts/index.native.js.map +1 -1
  31. package/dist/cjs/{Button/mediaPlate.cjs → InputParts/keyboardAppearance.cjs} +7 -8
  32. package/dist/{jsx/Button/mediaPlate.native.js → cjs/InputParts/keyboardAppearance.native.js} +8 -9
  33. package/dist/cjs/InputParts/keyboardAppearance.native.js.map +1 -0
  34. package/dist/cjs/{Button/mediaPlate.native.js → fields/Duration/DurationWheel.cjs} +11 -11
  35. package/dist/cjs/fields/Duration/DurationWheel.native.js +132 -0
  36. package/dist/cjs/fields/Duration/DurationWheel.native.js.map +1 -0
  37. package/dist/cjs/fields/Duration/durationMath.cjs +19 -1
  38. package/dist/cjs/fields/Duration/durationMath.native.js +19 -1
  39. package/dist/cjs/fields/Duration/durationMath.native.js.map +1 -1
  40. package/dist/cjs/fields/Duration/durationWheelTypes.cjs +18 -0
  41. package/dist/cjs/fields/Duration/durationWheelTypes.native.js +21 -0
  42. package/dist/cjs/fields/Duration/durationWheelTypes.native.js.map +1 -0
  43. package/dist/cjs/fields/Duration/index.cjs +30 -10
  44. package/dist/cjs/fields/Duration/index.native.js +32 -12
  45. package/dist/cjs/fields/Duration/index.native.js.map +1 -1
  46. package/dist/cjs/fields/nativeDateTime/OsDateTimeSheet.cjs +8 -7
  47. package/dist/cjs/fields/nativeDateTime/OsDateTimeSheet.native.js +8 -7
  48. package/dist/cjs/fields/nativeDateTime/OsDateTimeSheet.native.js.map +1 -1
  49. package/dist/cjs/fields/nativeDateTime/osDateTimeIosDisplay.cjs +1 -1
  50. package/dist/cjs/fields/nativeDateTime/osDateTimeIosDisplay.native.js +1 -1
  51. package/dist/cjs/fields/nativeDateTime/osDateTimeIosDisplay.native.js.map +1 -1
  52. package/dist/cjs/fields/nativeDateTime/sheetKeyboard.cjs +1 -1
  53. package/dist/cjs/fields/nativeDateTime/sheetKeyboard.native.js +1 -1
  54. package/dist/cjs/fields/nativeDateTime/sheetKeyboard.native.js.map +1 -1
  55. package/dist/cjs/index.cjs +0 -1
  56. package/dist/cjs/index.native.js +0 -1
  57. package/dist/cjs/index.native.js.map +1 -1
  58. package/dist/esm/Button/IconButtonGroup.mjs +65 -33
  59. package/dist/esm/Button/IconButtonGroup.mjs.map +1 -1
  60. package/dist/esm/Button/IconButtonGroup.native.js +71 -35
  61. package/dist/esm/Button/IconButtonGroup.native.js.map +1 -1
  62. package/dist/esm/Button/circleGlyph.mjs +9 -1
  63. package/dist/esm/Button/circleGlyph.mjs.map +1 -1
  64. package/dist/esm/Button/circleGlyph.native.js +10 -1
  65. package/dist/esm/Button/circleGlyph.native.js.map +1 -1
  66. package/dist/esm/Button/glass.mjs +2 -1
  67. package/dist/esm/Button/glass.mjs.map +1 -1
  68. package/dist/esm/Button/glass.native.js +43 -19
  69. package/dist/esm/Button/glass.native.js.map +1 -1
  70. package/dist/esm/Button/iconButtonGroupContext.mjs +5 -1
  71. package/dist/esm/Button/iconButtonGroupContext.mjs.map +1 -1
  72. package/dist/esm/Button/iconButtonGroupContext.native.js +5 -1
  73. package/dist/esm/Button/iconButtonGroupContext.native.js.map +1 -1
  74. package/dist/esm/Button/index.mjs +15 -22
  75. package/dist/esm/Button/index.mjs.map +1 -1
  76. package/dist/esm/Button/index.native.js +15 -23
  77. package/dist/esm/Button/index.native.js.map +1 -1
  78. package/dist/esm/Button/webGlass.mjs +10 -6
  79. package/dist/esm/Button/webGlass.mjs.map +1 -1
  80. package/dist/esm/Button/webGlass.native.js +10 -6
  81. package/dist/esm/Button/webGlass.native.js.map +1 -1
  82. package/dist/esm/FloatingPanel/coverRect.mjs +23 -0
  83. package/dist/esm/FloatingPanel/coverRect.mjs.map +1 -0
  84. package/dist/esm/FloatingPanel/coverRect.native.js +24 -0
  85. package/dist/esm/FloatingPanel/coverRect.native.js.map +1 -0
  86. package/dist/esm/FloatingPanel/iconEcho.mjs +4 -2
  87. package/dist/esm/FloatingPanel/iconEcho.mjs.map +1 -1
  88. package/dist/esm/FloatingPanel/iconEcho.native.js +4 -2
  89. package/dist/esm/FloatingPanel/iconEcho.native.js.map +1 -1
  90. package/dist/esm/FloatingPanel/index.mjs +23 -13
  91. package/dist/esm/FloatingPanel/index.mjs.map +1 -1
  92. package/dist/esm/FloatingPanel/index.native.js +41 -15
  93. package/dist/esm/FloatingPanel/index.native.js.map +1 -1
  94. package/dist/esm/InputParts/index.mjs +6 -1
  95. package/dist/esm/InputParts/index.mjs.map +1 -1
  96. package/dist/esm/InputParts/index.native.js +8 -1
  97. package/dist/esm/InputParts/index.native.js.map +1 -1
  98. package/dist/esm/InputParts/keyboardAppearance.mjs +5 -0
  99. package/dist/esm/InputParts/keyboardAppearance.mjs.map +1 -0
  100. package/dist/esm/InputParts/keyboardAppearance.native.js +5 -0
  101. package/dist/esm/InputParts/keyboardAppearance.native.js.map +1 -0
  102. package/dist/esm/fields/Duration/DurationWheel.mjs +8 -0
  103. package/dist/esm/fields/Duration/DurationWheel.mjs.map +1 -0
  104. package/dist/esm/fields/Duration/DurationWheel.native.js +103 -0
  105. package/dist/esm/fields/Duration/DurationWheel.native.js.map +1 -0
  106. package/dist/esm/fields/Duration/durationMath.mjs +16 -1
  107. package/dist/esm/fields/Duration/durationMath.mjs.map +1 -1
  108. package/dist/esm/fields/Duration/durationMath.native.js +16 -1
  109. package/dist/esm/fields/Duration/durationMath.native.js.map +1 -1
  110. package/dist/esm/fields/Duration/durationWheelTypes.mjs +2 -0
  111. package/dist/esm/fields/Duration/durationWheelTypes.mjs.map +1 -0
  112. package/dist/esm/fields/Duration/durationWheelTypes.native.js +2 -0
  113. package/dist/esm/fields/Duration/durationWheelTypes.native.js.map +1 -0
  114. package/dist/esm/fields/Duration/index.mjs +28 -11
  115. package/dist/esm/fields/Duration/index.mjs.map +1 -1
  116. package/dist/esm/fields/Duration/index.native.js +30 -13
  117. package/dist/esm/fields/Duration/index.native.js.map +1 -1
  118. package/dist/esm/fields/nativeDateTime/OsDateTimeSheet.mjs +8 -7
  119. package/dist/esm/fields/nativeDateTime/OsDateTimeSheet.mjs.map +1 -1
  120. package/dist/esm/fields/nativeDateTime/OsDateTimeSheet.native.js +8 -7
  121. package/dist/esm/fields/nativeDateTime/OsDateTimeSheet.native.js.map +1 -1
  122. package/dist/esm/fields/nativeDateTime/osDateTimeIosDisplay.mjs +1 -1
  123. package/dist/esm/fields/nativeDateTime/osDateTimeIosDisplay.mjs.map +1 -1
  124. package/dist/esm/fields/nativeDateTime/osDateTimeIosDisplay.native.js +1 -1
  125. package/dist/esm/fields/nativeDateTime/osDateTimeIosDisplay.native.js.map +1 -1
  126. package/dist/esm/fields/nativeDateTime/sheetKeyboard.mjs +1 -1
  127. package/dist/esm/fields/nativeDateTime/sheetKeyboard.mjs.map +1 -1
  128. package/dist/esm/fields/nativeDateTime/sheetKeyboard.native.js +1 -1
  129. package/dist/esm/fields/nativeDateTime/sheetKeyboard.native.js.map +1 -1
  130. package/dist/esm/index.mjs +2 -2
  131. package/dist/esm/index.mjs.map +1 -1
  132. package/dist/esm/index.native.js +2 -2
  133. package/dist/esm/index.native.js.map +1 -1
  134. package/dist/jsx/Button/IconButtonGroup.mjs +65 -33
  135. package/dist/jsx/Button/IconButtonGroup.mjs.map +1 -1
  136. package/dist/jsx/Button/IconButtonGroup.native.js +64 -29
  137. package/dist/jsx/Button/IconButtonGroup.native.js.map +1 -1
  138. package/dist/jsx/Button/circleGlyph.mjs +9 -1
  139. package/dist/jsx/Button/circleGlyph.mjs.map +1 -1
  140. package/dist/jsx/Button/circleGlyph.native.js +12 -1
  141. package/dist/jsx/Button/circleGlyph.native.js.map +1 -1
  142. package/dist/jsx/Button/glass.mjs +2 -1
  143. package/dist/jsx/Button/glass.mjs.map +1 -1
  144. package/dist/jsx/Button/glass.native.js +44 -19
  145. package/dist/jsx/Button/glass.native.js.map +1 -1
  146. package/dist/jsx/Button/iconButtonGroupContext.mjs +5 -1
  147. package/dist/jsx/Button/iconButtonGroupContext.mjs.map +1 -1
  148. package/dist/jsx/Button/iconButtonGroupContext.native.js +7 -1
  149. package/dist/jsx/Button/iconButtonGroupContext.native.js.map +1 -1
  150. package/dist/jsx/Button/index.mjs +15 -22
  151. package/dist/jsx/Button/index.mjs.map +1 -1
  152. package/dist/jsx/Button/index.native.js +15 -24
  153. package/dist/jsx/Button/index.native.js.map +1 -1
  154. package/dist/jsx/Button/webGlass.mjs +10 -6
  155. package/dist/jsx/Button/webGlass.mjs.map +1 -1
  156. package/dist/jsx/Button/webGlass.native.js +9 -5
  157. package/dist/jsx/Button/webGlass.native.js.map +1 -1
  158. package/dist/jsx/FloatingPanel/coverRect.mjs +23 -0
  159. package/dist/jsx/FloatingPanel/coverRect.mjs.map +1 -0
  160. package/dist/jsx/FloatingPanel/coverRect.native.js +54 -0
  161. package/dist/jsx/FloatingPanel/coverRect.native.js.map +1 -0
  162. package/dist/jsx/FloatingPanel/iconEcho.mjs +4 -2
  163. package/dist/jsx/FloatingPanel/iconEcho.mjs.map +1 -1
  164. package/dist/jsx/FloatingPanel/iconEcho.native.js +3 -1
  165. package/dist/jsx/FloatingPanel/iconEcho.native.js.map +1 -1
  166. package/dist/jsx/FloatingPanel/index.mjs +23 -13
  167. package/dist/jsx/FloatingPanel/index.mjs.map +1 -1
  168. package/dist/jsx/FloatingPanel/index.native.js +41 -15
  169. package/dist/jsx/FloatingPanel/index.native.js.map +1 -1
  170. package/dist/jsx/InputParts/index.mjs +6 -1
  171. package/dist/jsx/InputParts/index.mjs.map +1 -1
  172. package/dist/jsx/InputParts/index.native.js +7 -0
  173. package/dist/jsx/InputParts/index.native.js.map +1 -1
  174. package/dist/jsx/InputParts/keyboardAppearance.mjs +5 -0
  175. package/dist/jsx/InputParts/keyboardAppearance.mjs.map +1 -0
  176. package/dist/jsx/InputParts/keyboardAppearance.native.js +33 -0
  177. package/dist/jsx/InputParts/keyboardAppearance.native.js.map +1 -0
  178. package/dist/jsx/fields/Duration/DurationWheel.mjs +8 -0
  179. package/dist/jsx/fields/Duration/DurationWheel.mjs.map +1 -0
  180. package/dist/jsx/fields/Duration/DurationWheel.native.js +132 -0
  181. package/dist/jsx/fields/Duration/DurationWheel.native.js.map +1 -0
  182. package/dist/jsx/fields/Duration/durationMath.mjs +16 -1
  183. package/dist/jsx/fields/Duration/durationMath.mjs.map +1 -1
  184. package/dist/jsx/fields/Duration/durationMath.native.js +19 -1
  185. package/dist/jsx/fields/Duration/durationMath.native.js.map +1 -1
  186. package/dist/jsx/fields/Duration/durationWheelTypes.mjs +2 -0
  187. package/dist/jsx/fields/Duration/durationWheelTypes.mjs.map +1 -0
  188. package/dist/jsx/fields/Duration/durationWheelTypes.native.js +21 -0
  189. package/dist/jsx/fields/Duration/durationWheelTypes.native.js.map +1 -0
  190. package/dist/jsx/fields/Duration/index.mjs +28 -11
  191. package/dist/jsx/fields/Duration/index.mjs.map +1 -1
  192. package/dist/jsx/fields/Duration/index.native.js +32 -12
  193. package/dist/jsx/fields/Duration/index.native.js.map +1 -1
  194. package/dist/jsx/fields/nativeDateTime/OsDateTimeSheet.mjs +8 -7
  195. package/dist/jsx/fields/nativeDateTime/OsDateTimeSheet.mjs.map +1 -1
  196. package/dist/jsx/fields/nativeDateTime/OsDateTimeSheet.native.js +8 -7
  197. package/dist/jsx/fields/nativeDateTime/OsDateTimeSheet.native.js.map +1 -1
  198. package/dist/jsx/fields/nativeDateTime/osDateTimeIosDisplay.mjs +1 -1
  199. package/dist/jsx/fields/nativeDateTime/osDateTimeIosDisplay.mjs.map +1 -1
  200. package/dist/jsx/fields/nativeDateTime/osDateTimeIosDisplay.native.js +1 -1
  201. package/dist/jsx/fields/nativeDateTime/sheetKeyboard.mjs +1 -1
  202. package/dist/jsx/fields/nativeDateTime/sheetKeyboard.mjs.map +1 -1
  203. package/dist/jsx/fields/nativeDateTime/sheetKeyboard.native.js +1 -1
  204. package/dist/jsx/fields/nativeDateTime/sheetKeyboard.native.js.map +1 -1
  205. package/dist/jsx/index.js +2 -2
  206. package/dist/jsx/index.js.map +1 -1
  207. package/dist/jsx/index.mjs +2 -2
  208. package/dist/jsx/index.mjs.map +1 -1
  209. package/dist/jsx/index.native.js +0 -1
  210. package/dist/jsx/index.native.js.map +1 -1
  211. package/package.json +8 -8
  212. package/src/Button/Button.iconButton.spec.tsx +47 -7
  213. package/src/Button/IconButtonGroup.spec.tsx +103 -19
  214. package/src/Button/IconButtonGroup.tsx +84 -46
  215. package/src/Button/circleGlyph.ts +18 -0
  216. package/src/Button/glass.native.spec.ts +62 -0
  217. package/src/Button/glass.native.ts +58 -37
  218. package/src/Button/glass.spec.ts +64 -16
  219. package/src/Button/glass.ts +16 -12
  220. package/src/Button/iconButtonGroupContext.ts +27 -3
  221. package/src/Button/index.tsx +21 -33
  222. package/src/Button/webGlass.ts +25 -18
  223. package/src/FloatingPanel/FloatingPanel.iconEcho.spec.tsx +61 -1
  224. package/src/FloatingPanel/FloatingPanel.menuFace.native.spec.tsx +104 -0
  225. package/src/FloatingPanel/coverRect.ts +42 -0
  226. package/src/FloatingPanel/iconEcho.tsx +9 -3
  227. package/src/FloatingPanel/index.native.tsx +63 -18
  228. package/src/FloatingPanel/index.tsx +35 -15
  229. package/src/InputParts/index.tsx +6 -0
  230. package/src/InputParts/keyboardAppearance.spec.ts +12 -0
  231. package/src/InputParts/keyboardAppearance.ts +4 -0
  232. package/src/fields/Duration/Duration.spec.tsx +19 -10
  233. package/src/fields/Duration/Duration.wheel.native.spec.tsx +98 -0
  234. package/src/fields/Duration/DurationWheel.native.tsx +101 -0
  235. package/src/fields/Duration/DurationWheel.tsx +11 -0
  236. package/src/fields/Duration/durationMath.spec.ts +43 -0
  237. package/src/fields/Duration/durationMath.ts +31 -0
  238. package/src/fields/Duration/durationWheelTypes.ts +18 -0
  239. package/src/fields/Duration/index.tsx +58 -27
  240. package/src/fields/nativeDateTime/OsDateTimeSheet.countdown.native.spec.tsx +121 -0
  241. package/src/fields/nativeDateTime/OsDateTimeSheet.spec.ts +4 -0
  242. package/src/fields/nativeDateTime/OsDateTimeSheet.tsx +14 -9
  243. package/src/fields/nativeDateTime/osDateTimeIosDisplay.ts +3 -3
  244. package/src/fields/nativeDateTime/sheetKeyboard.spec.ts +6 -0
  245. package/src/fields/nativeDateTime/sheetKeyboard.ts +2 -2
  246. package/src/index.ts +0 -1
  247. package/types/Button/IconButtonGroup.d.ts +7 -12
  248. package/types/Button/IconButtonGroup.d.ts.map +1 -1
  249. package/types/Button/circleGlyph.d.ts +12 -0
  250. package/types/Button/circleGlyph.d.ts.map +1 -1
  251. package/types/Button/glass.d.ts +7 -11
  252. package/types/Button/glass.d.ts.map +1 -1
  253. package/types/Button/glass.native.d.ts +22 -10
  254. package/types/Button/glass.native.d.ts.map +1 -1
  255. package/types/Button/iconButtonGroupContext.d.ts +21 -3
  256. package/types/Button/iconButtonGroupContext.d.ts.map +1 -1
  257. package/types/Button/index.d.ts +3 -10
  258. package/types/Button/index.d.ts.map +1 -1
  259. package/types/Button/webGlass.d.ts +8 -16
  260. package/types/Button/webGlass.d.ts.map +1 -1
  261. package/types/FloatingPanel/coverRect.d.ts +25 -0
  262. package/types/FloatingPanel/coverRect.d.ts.map +1 -0
  263. package/types/FloatingPanel/index.d.ts.map +1 -1
  264. package/types/FloatingPanel/index.native.d.ts.map +1 -1
  265. package/types/InputParts/index.d.ts.map +1 -1
  266. package/types/InputParts/keyboardAppearance.d.ts +3 -0
  267. package/types/InputParts/keyboardAppearance.d.ts.map +1 -0
  268. package/types/fields/Duration/DurationWheel.d.ts +5 -0
  269. package/types/fields/Duration/DurationWheel.d.ts.map +1 -0
  270. package/types/fields/Duration/DurationWheel.native.d.ts +5 -0
  271. package/types/fields/Duration/DurationWheel.native.d.ts.map +1 -0
  272. package/types/fields/Duration/durationMath.d.ts +13 -0
  273. package/types/fields/Duration/durationMath.d.ts.map +1 -1
  274. package/types/fields/Duration/durationWheelTypes.d.ts +18 -0
  275. package/types/fields/Duration/durationWheelTypes.d.ts.map +1 -0
  276. package/types/fields/Duration/index.d.ts +8 -3
  277. package/types/fields/Duration/index.d.ts.map +1 -1
  278. package/types/fields/nativeDateTime/OsDateTimeSheet.d.ts +1 -1
  279. package/types/fields/nativeDateTime/OsDateTimeSheet.d.ts.map +1 -1
  280. package/types/fields/nativeDateTime/osDateTimeIosDisplay.d.ts +2 -2
  281. package/types/fields/nativeDateTime/osDateTimeIosDisplay.d.ts.map +1 -1
  282. package/types/fields/nativeDateTime/sheetKeyboard.d.ts +1 -1
  283. package/types/fields/nativeDateTime/sheetKeyboard.d.ts.map +1 -1
  284. package/types/index.d.ts +1 -1
  285. package/types/index.d.ts.map +1 -1
  286. package/dist/cjs/Button/mediaPlate.native.js.map +0 -1
  287. package/dist/esm/Button/mediaPlate.mjs +0 -6
  288. package/dist/esm/Button/mediaPlate.mjs.map +0 -1
  289. package/dist/esm/Button/mediaPlate.native.js +0 -6
  290. package/dist/esm/Button/mediaPlate.native.js.map +0 -1
  291. package/dist/jsx/Button/mediaPlate.mjs +0 -6
  292. package/dist/jsx/Button/mediaPlate.mjs.map +0 -1
  293. package/dist/jsx/Button/mediaPlate.native.js.map +0 -1
  294. package/src/Button/mediaPlate.ts +0 -9
  295. package/types/Button/mediaPlate.d.ts +0 -10
  296. package/types/Button/mediaPlate.d.ts.map +0 -1
@@ -79,11 +79,10 @@ import { warnBareDisabled, warnPositiveTabIndex, warnSizeRecipeEscape } from "..
79
79
  import { useControlGrouped } from "../shared/groupContext";
80
80
  import { useInPanelEcho, usePanelTriggerRadiusReporter } from "../FloatingPanel/echoContext";
81
81
  import { loadGlassView } from "./glass";
82
- import { MEDIA_PLATE_WEB_STYLE } from "./mediaPlate";
83
- import { ICON_BUTTON_CIRCLE_GLYPH_RATIO } from "./circleGlyph";
82
+ import { boldStroke, GLYPH_BOLD_STROKE_UNITS, ICON_BUTTON_CIRCLE_GLYPH_RATIO } from "./circleGlyph";
84
83
  import { useIconButtonGroupGround, useIconButtonGroupMember } from "./iconButtonGroupContext";
85
84
 
86
- export { ICON_BUTTON_CIRCLE_GLYPH_RATIO };
85
+ export { GLYPH_BOLD_STROKE_UNITS, ICON_BUTTON_CIRCLE_GLYPH_RATIO };
87
86
 
88
87
  /**
89
88
  * Coordinated size recipe (Polaris slim/medium/large, Primer s/m/l, Linear
@@ -466,24 +465,6 @@ export function iconButtonGlyphPx(rowLinePx: number | undefined): number {
466
465
  /** LC-176: an inline glyph is the text's size; Phosphor's 256 grid pads ~12%. */
467
466
  const INLINE_GLYPH_RATIO = 1.2;
468
467
 
469
- /**
470
- * LC-176: Phosphor bold's stem is 0.12 of its ink, an SF Symbols bold plus's
471
- * 0.18 (measured at 17 and 24pt). An outline stroke this wide, in the 256-unit
472
- * grid, brings a bold glyph to SF semibold-bold (0.154); a wider one closes
473
- * Phosphor bold's 16-unit counters (the trash lid, copy's overlap).
474
- */
475
- export const GLYPH_BOLD_STROKE_UNITS = 8;
476
-
477
- function boldStroke(weight: "regular" | "bold", color = "currentColor") {
478
- return weight === "bold"
479
- ? {
480
- stroke: color,
481
- strokeWidth: GLYPH_BOLD_STROKE_UNITS,
482
- strokeLinejoin: "round" as const,
483
- }
484
- : undefined;
485
- }
486
-
487
468
  function withGlyphWeight(
488
469
  icon: IconLike | undefined,
489
470
  size: number,
@@ -868,9 +849,9 @@ export function Button({
868
849
  (labelled && chromeless && accentInk === true && edge === "start");
869
850
  const labelLine = labelLinePx(knobProps.body.fontFamily);
870
851
  const glyphFloor = iconButtonGlyphPx(labelLine);
871
- // LC-176: on iOS 26 a bar's icon button floats on Liquid Glass, the native
872
- // bar button. Elsewhere, and on a binary without the module, it stays the
873
- // bare tinted glyph.
852
+ // LC-176: on iOS 26 a bar's icon button sits in system Liquid Glass, the
853
+ // native bar button. Elsewhere, and on a binary without the module, it stays
854
+ // the bare tinted glyph; nothing re-creates the glass (FZ-8666).
874
855
  const glassGroup = groupGround === "glass";
875
856
  const GlassView =
876
857
  iconButton && !inlineGlyph && !nested && accentInk && barSurface && !selectedFill && !glassGroup
@@ -1113,7 +1094,8 @@ export function Button({
1113
1094
  // A plain button is ink on the bar: no shadow at rest (E-FLAT).
1114
1095
  const plainTier = tier === "plain";
1115
1096
  // LC-176: hover and press light a soft plate on web; on native the glyph
1116
- // dims, as an iOS bar button does. The media plate deepens instead.
1097
+ // dims, and on glass the system answers the press instead. The media plate
1098
+ // deepens instead.
1117
1099
  const glyphState = iconButton && !selectedFill;
1118
1100
  const iconHover = glyphState
1119
1101
  ? isWeb
@@ -1125,7 +1107,9 @@ export function Button({
1125
1107
  const iconPress = glyphState
1126
1108
  ? isWeb
1127
1109
  ? hostScoped({ backgroundColor: "$backgroundPress" })
1128
- : { backgroundColor: "transparent", opacity: ICON_BUTTON_PRESS_OPACITY }
1110
+ : GlassView || glassGroup
1111
+ ? { backgroundColor: "transparent" }
1112
+ : { backgroundColor: "transparent", opacity: ICON_BUTTON_PRESS_OPACITY }
1129
1113
  : mediaPlate
1130
1114
  ? { backgroundColor: "$shadow5" }
1131
1115
  : undefined;
@@ -1192,7 +1176,6 @@ export function Button({
1192
1176
  ? {
1193
1177
  borderRadius: 100000,
1194
1178
  backgroundColor: "$shadow4",
1195
- ...(isWeb ? { style: MEDIA_PLATE_WEB_STYLE } : undefined),
1196
1179
  }
1197
1180
  : undefined)}
1198
1181
  {...(edge && !inlineGlyph && chromeless && !selectedFill && !isCircular
@@ -1363,8 +1346,8 @@ export function Button({
1363
1346
  {GlassView ? (
1364
1347
  <GlassView
1365
1348
  glassEffectStyle="regular"
1366
- isInteractive
1367
- pointerEvents="none"
1349
+ isInteractive={!unavailable}
1350
+ colorScheme={darkScheme ? "dark" : "light"}
1368
1351
  style={{
1369
1352
  position: "absolute",
1370
1353
  top: glassInset,
@@ -1372,10 +1355,15 @@ export function Button({
1372
1355
  bottom: glassInset,
1373
1356
  left: glassInset,
1374
1357
  borderRadius: visualPx / 2,
1358
+ alignItems: "center",
1359
+ justifyContent: "center",
1375
1360
  }}
1376
- />
1377
- ) : null}
1378
- {iconElement}
1361
+ >
1362
+ {iconElement}
1363
+ </GlassView>
1364
+ ) : (
1365
+ iconElement
1366
+ )}
1379
1367
  {labelContent}
1380
1368
  {iconAfterElement}
1381
1369
  </ButtonFrame>
@@ -1444,5 +1432,5 @@ export function IconButton(props: IconButtonProps) {
1444
1432
  return <Button {...props} />;
1445
1433
  }
1446
1434
 
1447
- export { IconButtonGroup, ICON_BUTTON_GLASS_MERGE_PX } from "./IconButtonGroup";
1435
+ export { IconButtonGroup } from "./IconButtonGroup";
1448
1436
  export type { IconButtonGroupProps } from "./IconButtonGroup";
@@ -1,7 +1,6 @@
1
1
  import { isDarkThemeName } from "@multiplatform.one/theme";
2
- import { createElement } from "react";
2
+ import { createElement, Fragment, type ReactNode } from "react";
3
3
  import { useThemeName, YStack } from "tamagui";
4
- import { MEDIA_PLATE_WEB_STYLE } from "./mediaPlate";
5
4
 
6
5
  type GlassNavigator = { userAgent?: string; platform?: string; maxTouchPoints?: number };
7
6
 
@@ -19,24 +18,32 @@ export function isAppleTouchWeb(
19
18
  }
20
19
 
21
20
  const webGlassMarker = { "data-mp-glass": "web" };
21
+ const webGlassBlur = {
22
+ backdropFilter: "blur(16px) saturate(180%)",
23
+ WebkitBackdropFilter: "blur(16px) saturate(180%)",
24
+ } as const;
22
25
 
23
26
  /**
24
- * LC-176: the Liquid Glass face iOS Safari draws under a bar's icon buttons,
25
- * one circle for a lone button or one capsule for an `IconButtonGroup`. It is
26
- * a layer under the glyphs (absolute, z -1 in the button's stacking context):
27
- * a near-white material in light and a raised grey in dark, edged by a soft
28
- * drop shadow alone, with the media plate's blur.
27
+ * LC-176: the drawn face `loadGlassView` can give iOS Safari, one circle for a
28
+ * lone button or one capsule for an `IconButtonGroup`. Off by default: the
29
+ * compare in `glass.ts` decides whether it stays. Its children stay siblings
30
+ * above the layer (absolute, z -1 in the button's stacking context).
29
31
  */
30
- export function WebGlassFace({ style }: { style?: unknown }) {
32
+ export function WebGlassFace({ style, children }: { style?: unknown; children?: ReactNode }) {
31
33
  const dark = isDarkThemeName(useThemeName());
32
- return createElement(YStack, {
33
- pointerEvents: "none",
34
- backgroundColor: dark ? "$color4" : "$color1",
35
- opacity: 0.92,
36
- shadowColor: "$shadowColor",
37
- shadowRadius: 10,
38
- shadowOffset: { width: 0, height: 3 },
39
- ...webGlassMarker,
40
- style: { ...(style as object), zIndex: -1, ...MEDIA_PLATE_WEB_STYLE },
41
- });
34
+ return createElement(
35
+ Fragment,
36
+ null,
37
+ createElement(YStack, {
38
+ pointerEvents: "none",
39
+ backgroundColor: dark ? "$color4" : "$color1",
40
+ opacity: 0.92,
41
+ shadowColor: "$shadowColor",
42
+ shadowRadius: 10,
43
+ shadowOffset: { width: 0, height: 3 },
44
+ ...webGlassMarker,
45
+ style: { ...(style as object), zIndex: -1, ...webGlassBlur },
46
+ }),
47
+ children,
48
+ );
42
49
  }
@@ -8,10 +8,11 @@ import { PlusIcon, XIcon } from "@phosphor-icons/react";
8
8
  import { renderWithProviders } from "@multiplatform.one/test-utils";
9
9
  import { fireEvent, render, waitFor, within } from "@testing-library/react";
10
10
  import { useState } from "react";
11
- import { Surface, useBarSurface } from "@multiplatform.one/theme";
11
+ import { MIN_PRESS_TARGET, Surface, useBarSurface } from "@multiplatform.one/theme";
12
12
  import { afterEach, describe, expect, it, vi } from "vitest";
13
13
  import { Text } from "tamagui";
14
14
  import { Button } from "../Button";
15
+ import { GLYPH_BOLD_STROKE_UNITS } from "../Button/circleGlyph";
15
16
  import { FloatingPanel } from "./index";
16
17
  import { usePanelIconEchoBox } from "./echoContext";
17
18
  import { PanelHeader } from "./PanelHeader";
@@ -98,6 +99,31 @@ function AddPanel({ kind = "close", header = false }: { kind?: IconEcho; header?
98
99
  );
99
100
  }
100
101
 
102
+ /** An account menu opened from a 32pt avatar (no `icon`, so its X is a circle). */
103
+ function AvatarPanel() {
104
+ return (
105
+ <FloatingPanel
106
+ open
107
+ onOpenChange={() => {}}
108
+ anchorMode="cover-trigger"
109
+ compactFace="menu"
110
+ triggerEcho={false}
111
+ iconEcho="menu"
112
+ coverAlign="auto"
113
+ widthMode="fit-content"
114
+ triggerSizing="content"
115
+ contentPadding="none"
116
+ trigger={
117
+ <span role="button" aria-label="Account">
118
+ AD
119
+ </span>
120
+ }
121
+ >
122
+ <Text>Sign out</Text>
123
+ </FloatingPanel>
124
+ );
125
+ }
126
+
101
127
  const glyphPath = (node: Element | null | undefined) =>
102
128
  node?.querySelector("svg path")?.getAttribute("d");
103
129
 
@@ -294,4 +320,38 @@ describe("LC-112 icon trigger echo on the web (FZ-8480)", () => {
294
320
  expect(panel.style.transformOrigin).toBe("bottom left");
295
321
  expect(result.queryByTestId("floating-panel-sheet")).toBeNull();
296
322
  });
323
+
324
+ it("strokes the avatar's X to the bar buttons' bold stem (FZ-8480 follow-up)", async () => {
325
+ measure({ x: 100, y: 12, width: 44, height: 44 });
326
+ const bar = renderWithProviders(<AddPanel kind="menu" />);
327
+ const barPanel = await open(bar);
328
+ const barX = within(barPanel).getByRole("button", { name: "Close" }).querySelector("svg");
329
+ expect(barX?.getAttribute("stroke-width")).toBe(String(GLYPH_BOLD_STROKE_UNITS));
330
+ bar.unmount();
331
+ const result = renderWithProviders(<AvatarPanel />);
332
+ const panel = (await result.findByTestId("floating-panel-viewport")) as HTMLElement;
333
+ const avatarX = within(panel).getByRole("button", { name: "Close" }).querySelector("svg");
334
+ expect(avatarX?.getAttribute("stroke-width")).toBe(barX?.getAttribute("stroke-width"));
335
+ expect(avatarX?.getAttribute("stroke-linejoin")).toBe("round");
336
+ });
337
+
338
+ it("covers a 32pt avatar at its 44pt target, its centre on the row-icon column (FZ-8480 GAP)", async () => {
339
+ const avatar = { x: 100, y: 18, width: 32, height: 32 };
340
+ measure(avatar, 240);
341
+ const result = renderWithProviders(<AvatarPanel />);
342
+ const panel = (await result.findByTestId("floating-panel-viewport")) as HTMLElement;
343
+ await waitFor(() => expect(panel.style.visibility).toBe("visible"));
344
+ const inset = (MIN_PRESS_TARGET - avatar.width) / 2;
345
+ expect(panel.style.left).toBe(`${avatar.x - inset}px`);
346
+ expect(panel.style.top).toBe(`${avatar.y - inset}px`);
347
+ const row = panel.querySelector<HTMLElement>("[data-fp-icon-echo]") as HTMLElement;
348
+ expect(row.style.height).toBe(`${MIN_PRESS_TARGET}px`);
349
+ const box = row.querySelector<HTMLElement>("[data-fp-icon-echo-box]") as HTMLElement;
350
+ expect(box.style.width).toBe(`${avatar.width}px`);
351
+ expect(box.style.marginLeft).toBe(`${inset}px`);
352
+ expect(box.style.marginTop).toBe(`${inset}px`);
353
+ // The X's centre sits half a press target in, the centre of a menu row's
354
+ // leading glyph slot.
355
+ expect(inset + avatar.width / 2).toBe(MIN_PRESS_TARGET / 2);
356
+ });
297
357
  });
@@ -9,7 +9,13 @@ import { PlusIcon, XIcon } from "@phosphor-icons/react";
9
9
  import { useState, type ReactNode } from "react";
10
10
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
11
11
  import { Text, XStack, YStack, getTokens, getVariableValue } from "tamagui";
12
+ import { MIN_PRESS_TARGET } from "@multiplatform.one/theme";
12
13
  import { Button } from "../Button";
14
+ import {
15
+ IconButtonGroupSurfaceContext,
16
+ type IconButtonGroupPlate,
17
+ type IconButtonGroupSurface,
18
+ } from "../Button/iconButtonGroupContext";
13
19
  import { Input as InputParts } from "../InputParts";
14
20
  import { OverlayStackProvider } from "../shared/overlayStack";
15
21
  import { MENU_MIN_WIDTH, type CompactFace } from "./compactFace";
@@ -540,3 +546,101 @@ describe("LC-112 icon trigger echo on native (FZ-8480, rv_2607879d3bdaf9bf)", ()
540
546
  expect(glyphPath(iconEcho())).not.toBe(glyphPath(live));
541
547
  });
542
548
  });
549
+
550
+ const capsuleSurface = (plate: IconButtonGroupPlate): IconButtonGroupSurface => ({
551
+ measure: (callback) => callback(plate),
552
+ });
553
+
554
+ describe("LC-112 grouped glass capsule on native (FZ-8550, Round 37 second pass)", () => {
555
+ const plate = { x: 200, y: 50, width: 174, height: 44, radius: 22 };
556
+
557
+ it("covers the whole capsule from context at its radius; only the pressed trigger shows, as its X", () => {
558
+ trigger = { x: 330, y: 50, width: 44, height: 44 };
559
+ const result = renderWithProviders(
560
+ <IconButtonGroupSurfaceContext.Provider value={capsuleSurface(plate)}>
561
+ <EchoMenu kind="menu" />
562
+ </IconButtonGroupSurfaceContext.Provider>,
563
+ );
564
+ tap(result.getAllByRole("button", { name: "Add node" })[0]!);
565
+ const panel = menu() as HTMLElement;
566
+ layout(panel, MENU_MIN_WIDTH, 180);
567
+ const left = parseFloat(panel.style.left);
568
+ const top = parseFloat(panel.style.top);
569
+ // The panel's frame contains the capsule's: same top edge, both ends.
570
+ expect(top).toBe(plate.y);
571
+ expect(left).toBeLessThanOrEqual(plate.x);
572
+ expect(left + MENU_MIN_WIDTH).toBeGreaterThanOrEqual(plate.x + plate.width);
573
+ expect(left).toBe(plate.x + plate.width - MENU_MIN_WIDTH);
574
+ expect(corners(frame() as HTMLElement)).toEqual(radiusAtoms(plate.radius));
575
+ // The band is the capsule's height; the X keeps the trigger's own box.
576
+ const band = iconBand() as HTMLElement;
577
+ expect(band.style.height).toBe(`${plate.height}px`);
578
+ const box = band.firstElementChild as HTMLElement;
579
+ expect(box.style.width).toBe(`${trigger.width}px`);
580
+ expect(box.style.marginInlineStart || box.style.marginLeft).toBe(`${trigger.x - left}px`);
581
+ // Only the pressed trigger shows, as an X; nothing else of the group.
582
+ const echoes = document.querySelectorAll('[data-testid="floating-panel-icon-echo"]');
583
+ expect(echoes).toHaveLength(1);
584
+ const x = render(<XIcon weight="bold" />);
585
+ expect(glyphPath(echoes[0] as Element)).toBe(glyphPath(x.container));
586
+ x.unmount();
587
+ });
588
+
589
+ it("takes the capsule's width as its floor when the capsule is wider than the menu", () => {
590
+ const wide = { x: 16, y: 50, width: 358, height: 44, radius: 22 };
591
+ trigger = { x: 330, y: 50, width: 44, height: 44 };
592
+ const result = renderWithProviders(
593
+ <IconButtonGroupSurfaceContext.Provider value={capsuleSurface(wide)}>
594
+ <EchoMenu kind="menu" />
595
+ </IconButtonGroupSurfaceContext.Provider>,
596
+ );
597
+ tap(result.getAllByRole("button", { name: "Add node" })[0]!);
598
+ const panel = menu() as HTMLElement;
599
+ expect(panel.style.minWidth).toBe(`${wide.width}px`);
600
+ layout(panel, wide.width, 180);
601
+ expect(panel.style.left).toBe(`${wide.x}px`);
602
+ });
603
+
604
+ it("waits for the capsule before it shows, so it never opens on the button alone first", () => {
605
+ trigger = { x: 330, y: 50, width: 44, height: 44 };
606
+ let answer: ((plate: IconButtonGroupPlate | null) => void) | null = null;
607
+ const result = renderWithProviders(
608
+ <IconButtonGroupSurfaceContext.Provider
609
+ value={{
610
+ measure: (callback) => {
611
+ answer = callback;
612
+ },
613
+ }}
614
+ >
615
+ <EchoMenu kind="menu" />
616
+ </IconButtonGroupSurfaceContext.Provider>,
617
+ );
618
+ tap(result.getAllByRole("button", { name: "Add node" })[0]!);
619
+ const panel = menu() as HTMLElement;
620
+ layout(panel, MENU_MIN_WIDTH, 180);
621
+ expect(panel.style.opacity).toBe("0");
622
+ act(() => answer?.(plate));
623
+ expect(panel.style.opacity).toBe("1");
624
+ expect(panel.style.left).toBe(`${plate.x + plate.width - MENU_MIN_WIDTH}px`);
625
+ });
626
+
627
+ it("covers a 32pt avatar at its 44pt target, so its centre is the row-icon column (FZ-8480)", () => {
628
+ trigger = { x: 100, y: 56, width: 32, height: 32 };
629
+ const result = renderWithProviders(<EchoMenu kind="menu" />);
630
+ tap(result.getAllByRole("button", { name: "Add node" })[0]!);
631
+ const panel = menu() as HTMLElement;
632
+ layout(panel, MENU_MIN_WIDTH, 180);
633
+ const inset = (MIN_PRESS_TARGET - trigger.width) / 2;
634
+ expect(panel.style.left).toBe(`${trigger.x - inset}px`);
635
+ expect(panel.style.top).toBe(`${trigger.y - inset}px`);
636
+ const band = iconBand() as HTMLElement;
637
+ expect(band.style.height).toBe(`${MIN_PRESS_TARGET}px`);
638
+ const box = band.firstElementChild as HTMLElement;
639
+ expect(box.style.width).toBe(`${trigger.width}px`);
640
+ expect(box.style.marginTop).toBe(`${inset}px`);
641
+ expect(box.style.marginInlineStart || box.style.marginLeft).toBe(`${inset}px`);
642
+ // The X's centre sits half a press target in: where a row's leading
643
+ // glyph centres (row inset plus half its 18pt slot, on the frame border).
644
+ expect(inset + trigger.width / 2).toBe(MIN_PRESS_TARGET / 2);
645
+ });
646
+ });
@@ -0,0 +1,42 @@
1
+ import { MIN_PRESS_TARGET } from "@multiplatform.one/theme";
2
+ import type { TriggerRect } from "./pointAnchor";
3
+
4
+ /**
5
+ * The 44pt box an icon trigger is pressed in, centred on the trigger
6
+ * (LC-176). A trigger drawn smaller than its target (a 32pt avatar) is
7
+ * covered at its target, so the panel's row-icon column, which centres on
8
+ * a 44pt start inset, runs through the trigger's centre and the X drawn on
9
+ * it (FZ-8480 GAP). A trigger at least that big is its own box.
10
+ */
11
+ export function pressTargetRect(trigger: TriggerRect, min = MIN_PRESS_TARGET): TriggerRect {
12
+ const width = Math.max(trigger.width, min);
13
+ const height = Math.max(trigger.height, min);
14
+ return {
15
+ x: trigger.x - (width - trigger.width) / 2,
16
+ y: trigger.y - (height - trigger.height) / 2,
17
+ width,
18
+ height,
19
+ };
20
+ }
21
+
22
+ /**
23
+ * The surface a panel opened from an icon trigger covers (LC-112, FZ-8480
24
+ * Round 37): the plate the trigger sits on. In a grouped glass capsule
25
+ * that is the capsule (FZ-8550); a lone trigger is its press target.
26
+ */
27
+ export function iconCoverRect(trigger: TriggerRect, group: TriggerRect | null): TriggerRect {
28
+ return group ?? pressTargetRect(trigger);
29
+ }
30
+
31
+ /**
32
+ * Where the trigger sits inside the surface its panel covers: the X box's
33
+ * offset from the cover's top, and the band's height. Null when the cover is
34
+ * the trigger itself.
35
+ */
36
+ export function echoInCover(
37
+ trigger: TriggerRect,
38
+ cover: TriggerRect,
39
+ ): { top: number; height: number } | null {
40
+ if (cover.y === trigger.y && cover.height === trigger.height) return null;
41
+ return { top: trigger.y - cover.y, height: cover.height };
42
+ }
@@ -2,7 +2,7 @@ import { XIcon } from "@phosphor-icons/react";
2
2
  import { cloneElement, isValidElement, useState, type ReactElement, type ReactNode } from "react";
3
3
  import { SurfaceContext, type SurfaceIntent } from "@multiplatform.one/theme";
4
4
  import { useTheme, View } from "tamagui";
5
- import { ICON_BUTTON_CIRCLE_GLYPH_RATIO } from "../Button/circleGlyph";
5
+ import { boldStroke, ICON_BUTTON_CIRCLE_GLYPH_RATIO } from "../Button/circleGlyph";
6
6
  import { t } from "../shared/t";
7
7
 
8
8
  /**
@@ -83,10 +83,15 @@ const avatarPlate = "$selectedBackground";
83
83
  /** The X's glyph before the circle has measured itself. */
84
84
  const circleGlyphFallbackPx = 18;
85
85
 
86
- /** An X in a circle the size of the trigger it replaces (an avatar). */
86
+ /**
87
+ * An X in a circle the size of the trigger it replaces (an avatar), stroked
88
+ * to the bar buttons' bold stem (LC-176), so every X in a bar reads at one
89
+ * weight.
90
+ */
87
91
  function CircleClose({ label, onClose }: { label: string; onClose: () => void }) {
88
92
  const theme = useTheme();
89
93
  const [side, setSide] = useState(0);
94
+ const ink = theme.selectedColor?.val ?? theme.color?.val;
90
95
  return (
91
96
  <View
92
97
  role="button"
@@ -110,7 +115,8 @@ function CircleClose({ label, onClose }: { label: string; onClose: () => void })
110
115
  <XIcon
111
116
  size={side > 0 ? Math.round(side * ICON_BUTTON_CIRCLE_GLYPH_RATIO) : circleGlyphFallbackPx}
112
117
  weight="bold"
113
- color={theme.selectedColor?.val ?? theme.color?.val}
118
+ color={ink}
119
+ {...boldStroke("bold", typeof ink === "string" ? ink : undefined)}
114
120
  aria-hidden
115
121
  />
116
122
  </View>