@satinhq/kit 0.0.0-stage → 0.1.0-beta.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 (1154) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +96 -0
  3. package/README.md +454 -2
  4. package/THIRD_PARTY_NOTICES.md +65 -0
  5. package/bin/satin.mjs +13 -0
  6. package/dist/acknowledgements/Acknowledgements.d.ts +4 -0
  7. package/dist/acknowledgements/Acknowledgements.js +42 -0
  8. package/dist/acknowledgements/bundledNotices.d.ts +4 -0
  9. package/dist/acknowledgements/bundledNotices.js +58 -0
  10. package/dist/acknowledgements/inventory.d.ts +17 -0
  11. package/dist/acknowledgements/inventory.js +10 -0
  12. package/dist/acknowledgements/inventory.json +39 -0
  13. package/dist/actions/ActionMenu.d.ts +30 -0
  14. package/dist/actions/ActionMenu.js +103 -0
  15. package/dist/actions/RowActions.d.ts +42 -0
  16. package/dist/actions/RowActions.js +820 -0
  17. package/dist/actions/contextMotion.d.ts +78 -0
  18. package/dist/actions/contextMotion.js +329 -0
  19. package/dist/actions/motion.d.ts +19 -0
  20. package/dist/actions/motion.js +74 -0
  21. package/dist/actions/nativeContextAppearance.json +86 -0
  22. package/dist/actions/nativeContextMotion.json +734 -0
  23. package/dist/actions/nativeMotion.json +388 -0
  24. package/dist/actions/preview.d.ts +27 -0
  25. package/dist/actions/preview.js +217 -0
  26. package/dist/actions/recognizers.d.ts +24 -0
  27. package/dist/actions/recognizers.js +87 -0
  28. package/dist/actions/rowScrub.d.ts +59 -0
  29. package/dist/actions/rowScrub.js +400 -0
  30. package/dist/actions/swipeSpring.d.ts +14 -0
  31. package/dist/actions/swipeSpring.js +35 -0
  32. package/dist/actions/types.d.ts +71 -0
  33. package/dist/actions/types.js +28 -0
  34. package/dist/app/InstallComponents.d.ts +16 -0
  35. package/dist/app/InstallComponents.js +104 -0
  36. package/dist/app/InstallationDiagnostics.d.ts +7 -0
  37. package/dist/app/InstallationDiagnostics.js +23 -0
  38. package/dist/app/OrientationGuard.d.ts +8 -0
  39. package/dist/app/OrientationGuard.js +9 -0
  40. package/dist/app/appearance.d.ts +18 -0
  41. package/dist/app/appearance.js +15 -0
  42. package/dist/app/appearanceStore.d.ts +30 -0
  43. package/dist/app/appearanceStore.js +228 -0
  44. package/dist/app/backgroundUpdate.d.ts +20 -0
  45. package/dist/app/backgroundUpdate.js +151 -0
  46. package/dist/app/buildInfo.d.ts +11 -0
  47. package/dist/app/buildInfo.js +12 -0
  48. package/dist/app/buildInfoBuild.d.ts +3 -0
  49. package/dist/app/buildInfoBuild.js +12 -0
  50. package/dist/app/checkCli.d.ts +1 -0
  51. package/dist/app/checkCli.js +73 -0
  52. package/dist/app/coldLaunchUpdate.d.ts +14 -0
  53. package/dist/app/coldLaunchUpdate.js +384 -0
  54. package/dist/app/definition.d.ts +85 -0
  55. package/dist/app/definition.js +347 -0
  56. package/dist/app/deployment.d.ts +28 -0
  57. package/dist/app/deployment.js +352 -0
  58. package/dist/app/deploymentBuild.d.ts +3 -0
  59. package/dist/app/deploymentBuild.js +55 -0
  60. package/dist/app/earlyWorker.d.ts +3 -0
  61. package/dist/app/earlyWorker.js +77 -0
  62. package/dist/app/head.d.ts +10 -0
  63. package/dist/app/head.js +120 -0
  64. package/dist/app/icons.d.ts +4 -0
  65. package/dist/app/icons.js +35 -0
  66. package/dist/app/install.d.ts +18 -0
  67. package/dist/app/install.js +82 -0
  68. package/dist/app/installCheck.d.ts +2 -0
  69. package/dist/app/installCheck.js +148 -0
  70. package/dist/app/installContext.d.ts +35 -0
  71. package/dist/app/installContext.js +45 -0
  72. package/dist/app/installCustom.d.ts +25 -0
  73. package/dist/app/installCustom.js +55 -0
  74. package/dist/app/installExperience.d.ts +22 -0
  75. package/dist/app/installExperience.js +389 -0
  76. package/dist/app/installExperienceDevice.d.ts +29 -0
  77. package/dist/app/installExperienceDevice.js +160 -0
  78. package/dist/app/installExperienceHome.d.ts +16 -0
  79. package/dist/app/installExperienceHome.js +304 -0
  80. package/dist/app/installExperienceRuntime.d.ts +37 -0
  81. package/dist/app/installExperienceRuntime.js +285 -0
  82. package/dist/app/installPolicy.d.ts +28 -0
  83. package/dist/app/installPolicy.js +90 -0
  84. package/dist/app/installQr.d.ts +10 -0
  85. package/dist/app/installQr.js +139 -0
  86. package/dist/app/installStrings.d.ts +52 -0
  87. package/dist/app/installStrings.js +75 -0
  88. package/dist/app/installTipPath.d.ts +12 -0
  89. package/dist/app/installTipPath.js +9 -0
  90. package/dist/app/installationFailure.d.ts +14 -0
  91. package/dist/app/installationFailure.js +38 -0
  92. package/dist/app/launch.d.ts +7 -0
  93. package/dist/app/launch.js +241 -0
  94. package/dist/app/launchReadiness.d.ts +9 -0
  95. package/dist/app/launchReadiness.js +72 -0
  96. package/dist/app/launchScreen.d.ts +16 -0
  97. package/dist/app/launchScreen.js +14 -0
  98. package/dist/app/launchScreenRuntime.d.ts +19 -0
  99. package/dist/app/launchScreenRuntime.js +313 -0
  100. package/dist/app/launchWatchdog.d.ts +1 -0
  101. package/dist/app/launchWatchdog.js +202 -0
  102. package/dist/app/manifests.d.ts +19 -0
  103. package/dist/app/manifests.js +20 -0
  104. package/dist/app/mdm.d.ts +3 -0
  105. package/dist/app/mdm.js +20 -0
  106. package/dist/app/mediaCheck.d.ts +9 -0
  107. package/dist/app/mediaCheck.js +122 -0
  108. package/dist/app/mediaTypes.d.ts +2 -0
  109. package/dist/app/mediaTypes.js +13 -0
  110. package/dist/app/platformPolicy.d.ts +3 -0
  111. package/dist/app/platformPolicy.js +10 -0
  112. package/dist/app/platformScripts.d.ts +6 -0
  113. package/dist/app/platformScripts.js +65 -0
  114. package/dist/app/releaseUpdates.d.ts +7 -0
  115. package/dist/app/releaseUpdates.js +53 -0
  116. package/dist/app/runtime.d.ts +9 -0
  117. package/dist/app/runtime.js +38 -0
  118. package/dist/app/startup.d.ts +30 -0
  119. package/dist/app/startup.js +24 -0
  120. package/dist/app/statusBand.d.ts +11 -0
  121. package/dist/app/statusBand.js +257 -0
  122. package/dist/app/viewport.d.ts +3 -0
  123. package/dist/app/viewport.js +42 -0
  124. package/dist/app/viewportValue.d.ts +5 -0
  125. package/dist/app/viewportValue.js +14 -0
  126. package/dist/app/vite.d.ts +27 -0
  127. package/dist/app/vite.js +440 -0
  128. package/dist/app/warmImage.d.ts +3 -0
  129. package/dist/app/warmImage.js +59 -0
  130. package/dist/content/content.d.ts +153 -0
  131. package/dist/content/content.js +315 -0
  132. package/dist/content/layout.d.ts +26 -0
  133. package/dist/content/layout.js +114 -0
  134. package/dist/content/scaledMetric.d.ts +3 -0
  135. package/dist/content/scaledMetric.js +68 -0
  136. package/dist/content/typography.d.ts +83 -0
  137. package/dist/content/typography.js +32 -0
  138. package/dist/controls/ActivityIndicatorSegments.d.ts +4 -0
  139. package/dist/controls/ActivityIndicatorSegments.js +5 -0
  140. package/dist/controls/ColorPicker.d.ts +20 -0
  141. package/dist/controls/ColorPicker.js +70 -0
  142. package/dist/controls/ControlRow.d.ts +5 -0
  143. package/dist/controls/ControlRow.js +10 -0
  144. package/dist/controls/DatePicker.d.ts +41 -0
  145. package/dist/controls/DatePicker.js +148 -0
  146. package/dist/controls/ProgressView.d.ts +17 -0
  147. package/dist/controls/ProgressView.js +24 -0
  148. package/dist/controls/civilDate.d.ts +49 -0
  149. package/dist/controls/civilDate.js +112 -0
  150. package/dist/data/database.d.ts +154 -0
  151. package/dist/data/database.js +710 -0
  152. package/dist/data/value-equal.d.ts +2 -0
  153. package/dist/data/value-equal.js +36 -0
  154. package/dist/data/write-store.d.ts +38 -0
  155. package/dist/data/write-store.js +192 -0
  156. package/dist/dev-menu/DevMenu.d.ts +1 -0
  157. package/dist/dev-menu/DevMenu.js +121 -0
  158. package/dist/dev-menu/actions.d.ts +12 -0
  159. package/dist/dev-menu/actions.js +99 -0
  160. package/dist/dev-menu/build.d.ts +5 -0
  161. package/dist/dev-menu/build.js +40 -0
  162. package/dist/dev-menu/gesture.d.ts +18 -0
  163. package/dist/dev-menu/gesture.js +109 -0
  164. package/dist/dev-menu/shake.d.ts +2 -0
  165. package/dist/dev-menu/shake.js +36 -0
  166. package/dist/dev-menu/types.d.ts +8 -0
  167. package/dist/dev-menu/types.js +1 -0
  168. package/dist/diagnostics.d.ts +3 -0
  169. package/dist/diagnostics.js +4 -0
  170. package/dist/docs/app-recipes.md +411 -0
  171. package/dist/docs/components/file-importer.md +54 -0
  172. package/dist/docs/components/paste-button.md +48 -0
  173. package/dist/docs/components/photos-picker.md +53 -0
  174. package/dist/docs/components/share-link.md +58 -0
  175. package/dist/docs/content.md +159 -0
  176. package/dist/docs/controls.md +151 -0
  177. package/dist/docs/data.md +332 -0
  178. package/dist/docs/limitations.md +40 -0
  179. package/dist/docs/messaging-scroll.md +234 -0
  180. package/dist/docs/networking.md +190 -0
  181. package/dist/docs/push.md +215 -0
  182. package/dist/docs/swiftui-reference.md +1895 -0
  183. package/dist/docs/symbols.md +293 -0
  184. package/dist/docs/tokens.md +60 -0
  185. package/dist/fidelity/devAssertions.d.ts +21 -0
  186. package/dist/fidelity/devAssertions.js +199 -0
  187. package/dist/focus/focusIntentMachine.d.ts +106 -0
  188. package/dist/focus/focusIntentMachine.js +359 -0
  189. package/dist/focus/navigationFocus.d.ts +42 -0
  190. package/dist/focus/navigationFocus.js +241 -0
  191. package/dist/focus/programmaticFocus.d.ts +15 -0
  192. package/dist/focus/programmaticFocus.js +152 -0
  193. package/dist/gestures/GestureView.d.ts +12 -0
  194. package/dist/gestures/GestureView.js +321 -0
  195. package/dist/gestures/arena.d.ts +138 -0
  196. package/dist/gestures/arena.js +417 -0
  197. package/dist/gestures/existingCompetitors.d.ts +79 -0
  198. package/dist/gestures/existingCompetitors.js +82 -0
  199. package/dist/gestures/gesture.d.ts +62 -0
  200. package/dist/gestures/gesture.js +107 -0
  201. package/dist/glass/ControlLens.d.ts +46 -0
  202. package/dist/glass/ControlLens.js +88 -0
  203. package/dist/glass/GlassBar.d.ts +9 -0
  204. package/dist/glass/GlassBar.js +22 -0
  205. package/dist/glass/GlassConfusionReview.d.ts +3 -0
  206. package/dist/glass/GlassConfusionReview.js +185 -0
  207. package/dist/glass/GlassEffect.d.ts +69 -0
  208. package/dist/glass/GlassEffect.js +550 -0
  209. package/dist/glass/GlassMaterialRoot.d.ts +7 -0
  210. package/dist/glass/GlassMaterialRoot.js +39 -0
  211. package/dist/glass/GlassPresentation.d.ts +28 -0
  212. package/dist/glass/GlassPresentation.js +1038 -0
  213. package/dist/glass/GlassProbeIcons.d.ts +8 -0
  214. package/dist/glass/GlassProbeIcons.js +12 -0
  215. package/dist/glass/GlassProbeOverlay.d.ts +52 -0
  216. package/dist/glass/GlassProbeOverlay.js +45 -0
  217. package/dist/glass/GlassTextField.d.ts +22 -0
  218. package/dist/glass/GlassTextField.js +12 -0
  219. package/dist/glass/MaterialEffectRoot.d.ts +9 -0
  220. package/dist/glass/MaterialEffectRoot.js +189 -0
  221. package/dist/glass/Menu.d.ts +3 -0
  222. package/dist/glass/Menu.js +35 -0
  223. package/dist/glass/MenuStack.d.ts +23 -0
  224. package/dist/glass/MenuStack.js +371 -0
  225. package/dist/glass/MenuSymbol.d.ts +7 -0
  226. package/dist/glass/MenuSymbol.js +16 -0
  227. package/dist/glass/MorphEllipsisArtwork.d.ts +2 -0
  228. package/dist/glass/MorphEllipsisArtwork.js +6 -0
  229. package/dist/glass/TabBar.d.ts +29 -0
  230. package/dist/glass/TabBar.js +169 -0
  231. package/dist/glass/capability.d.ts +25 -0
  232. package/dist/glass/capability.js +63 -0
  233. package/dist/glass/captureWindow.d.ts +60 -0
  234. package/dist/glass/captureWindow.js +119 -0
  235. package/dist/glass/confusionSession.d.ts +41 -0
  236. package/dist/glass/confusionSession.js +44 -0
  237. package/dist/glass/contactPhysics.d.ts +130 -0
  238. package/dist/glass/contactPhysics.js +214 -0
  239. package/dist/glass/context.d.ts +37 -0
  240. package/dist/glass/context.js +11 -0
  241. package/dist/glass/errorAlert.d.ts +6 -0
  242. package/dist/glass/errorAlert.js +57 -0
  243. package/dist/glass/errors.d.ts +22 -0
  244. package/dist/glass/errors.js +78 -0
  245. package/dist/glass/failurePolicy.d.ts +4 -0
  246. package/dist/glass/failurePolicy.js +20 -0
  247. package/dist/glass/fallback/material.d.ts +16 -0
  248. package/dist/glass/fallback/material.js +87 -0
  249. package/dist/glass/fallback/regions.d.ts +16 -0
  250. package/dist/glass/fallback/regions.js +249 -0
  251. package/dist/glass/fallback/runtime.d.ts +72 -0
  252. package/dist/glass/fallback/runtime.js +278 -0
  253. package/dist/glass/fallback/selection.d.ts +2 -0
  254. package/dist/glass/fallback/selection.js +9 -0
  255. package/dist/glass/fieldGeometry.d.ts +28 -0
  256. package/dist/glass/fieldGeometry.js +64 -0
  257. package/dist/glass/fieldMotion.d.ts +42 -0
  258. package/dist/glass/fieldMotion.js +47 -0
  259. package/dist/glass/glassContact.d.ts +76 -0
  260. package/dist/glass/glassContact.js +153 -0
  261. package/dist/glass/glassProbeSettings.d.ts +18 -0
  262. package/dist/glass/glassProbeSettings.js +133 -0
  263. package/dist/glass/lens/Scene.d.ts +108 -0
  264. package/dist/glass/lens/Scene.js +553 -0
  265. package/dist/glass/lens/backgrounds.json +103 -0
  266. package/dist/glass/lens/bitmapBackdrop.d.ts +14 -0
  267. package/dist/glass/lens/bitmapBackdrop.js +35 -0
  268. package/dist/glass/lens/controlLift.d.ts +94 -0
  269. package/dist/glass/lens/controlLift.js +78 -0
  270. package/dist/glass/lens/data.d.ts +19 -0
  271. package/dist/glass/lens/data.js +161 -0
  272. package/dist/glass/lens/drawableTop.d.ts +16 -0
  273. package/dist/glass/lens/drawableTop.js +15 -0
  274. package/dist/glass/lens/icons.d.ts +9 -0
  275. package/dist/glass/lens/icons.js +34 -0
  276. package/dist/glass/lens/interactiveContact.d.ts +33 -0
  277. package/dist/glass/lens/interactiveContact.js +158 -0
  278. package/dist/glass/lens/interactivePress.d.ts +95 -0
  279. package/dist/glass/lens/interactivePress.js +169 -0
  280. package/dist/glass/lens/ios27GlyphFit.json +126 -0
  281. package/dist/glass/lens/lensLightingSamples.json +1 -0
  282. package/dist/glass/lens/lensPress.d.ts +22 -0
  283. package/dist/glass/lens/lensPress.js +68 -0
  284. package/dist/glass/lens/lensPressSamples.json +1 -0
  285. package/dist/glass/lens/liquidMotion.d.ts +50 -0
  286. package/dist/glass/lens/liquidMotion.js +239 -0
  287. package/dist/glass/lens/materialGlassRecipes.json +776 -0
  288. package/dist/glass/lens/materialUniforms.d.ts +22 -0
  289. package/dist/glass/lens/materialUniforms.js +117 -0
  290. package/dist/glass/lens/menu-closing-close-fit.json +380 -0
  291. package/dist/glass/lens/menu-opening-native-fits.json +911 -0
  292. package/dist/glass/lens/menuContextFit.json +88 -0
  293. package/dist/glass/lens/menuContextOpacity.json +98 -0
  294. package/dist/glass/lens/menuContextPresentation.d.ts +15 -0
  295. package/dist/glass/lens/menuContextPresentation.js +65 -0
  296. package/dist/glass/lens/menuCornerFit.json +252 -0
  297. package/dist/glass/lens/menuCornerMotion.d.ts +9 -0
  298. package/dist/glass/lens/menuCornerMotion.js +5 -0
  299. package/dist/glass/lens/menuDropFit.json +64 -0
  300. package/dist/glass/lens/menuField.d.ts +178 -0
  301. package/dist/glass/lens/menuField.js +564 -0
  302. package/dist/glass/lens/menuGesturePresentation.d.ts +12 -0
  303. package/dist/glass/lens/menuGesturePresentation.js +42 -0
  304. package/dist/glass/lens/menuGlyphDropFit.json +38 -0
  305. package/dist/glass/lens/menuMorphFit.json +564 -0
  306. package/dist/glass/lens/menuMorphMotion.d.ts +70 -0
  307. package/dist/glass/lens/menuMorphMotion.js +219 -0
  308. package/dist/glass/lens/menuMorphPhoneFit.json +85 -0
  309. package/dist/glass/lens/menuMotion.d.ts +81 -0
  310. package/dist/glass/lens/menuMotion.js +323 -0
  311. package/dist/glass/lens/menuPlacement.d.ts +5 -0
  312. package/dist/glass/lens/menuPlacement.js +29 -0
  313. package/dist/glass/lens/menuSpring.d.ts +18 -0
  314. package/dist/glass/lens/menuSpring.js +29 -0
  315. package/dist/glass/lens/menuTouchLight.d.ts +13 -0
  316. package/dist/glass/lens/menuTouchLight.js +147 -0
  317. package/dist/glass/lens/mirrorConstants.d.ts +1 -0
  318. package/dist/glass/lens/mirrorConstants.js +2 -0
  319. package/dist/glass/lens/mirrorExtents.d.ts +52 -0
  320. package/dist/glass/lens/mirrorExtents.js +264 -0
  321. package/dist/glass/lens/mirrorInvalidation.d.ts +6 -0
  322. package/dist/glass/lens/mirrorInvalidation.js +10 -0
  323. package/dist/glass/lens/mirrorReuse.d.ts +20 -0
  324. package/dist/glass/lens/mirrorReuse.js +166 -0
  325. package/dist/glass/lens/motion.d.ts +62 -0
  326. package/dist/glass/lens/motion.js +93 -0
  327. package/dist/glass/lens/recordedMotion.d.ts +6 -0
  328. package/dist/glass/lens/recordedMotion.js +44 -0
  329. package/dist/glass/lens/referenceBackground.d.ts +9 -0
  330. package/dist/glass/lens/referenceBackground.js +151 -0
  331. package/dist/glass/lens/referenceProfiles.d.ts +21 -0
  332. package/dist/glass/lens/referenceProfiles.js +33 -0
  333. package/dist/glass/lens/referenceRegularTint.d.ts +12 -0
  334. package/dist/glass/lens/referenceRegularTint.js +41 -0
  335. package/dist/glass/lens/scopeSegments.d.ts +12 -0
  336. package/dist/glass/lens/scopeSegments.js +18 -0
  337. package/dist/glass/lens/scrollAnchoring.d.ts +15 -0
  338. package/dist/glass/lens/scrollAnchoring.js +17 -0
  339. package/dist/glass/lens/selectionParameters.json +94 -0
  340. package/dist/glass/lens/shapeParameters.json +198 -0
  341. package/dist/glass/lens/tab-motion-native-fits.json +778 -0
  342. package/dist/glass/lens/tabAccessoryMotion.d.ts +52 -0
  343. package/dist/glass/lens/tabAccessoryMotion.js +52 -0
  344. package/dist/glass/lens/tabChromaRimModel.d.ts +43 -0
  345. package/dist/glass/lens/tabChromaRimModel.js +93 -0
  346. package/dist/glass/lens/tabCollapseInkSamples.json +49 -0
  347. package/dist/glass/lens/tabCompactGesture.d.ts +15 -0
  348. package/dist/glass/lens/tabCompactGesture.js +50 -0
  349. package/dist/glass/lens/tabGeometryAttack.json +70 -0
  350. package/dist/glass/lens/tabGlyphColours.d.ts +17 -0
  351. package/dist/glass/lens/tabGlyphColours.js +37 -0
  352. package/dist/glass/lens/tabInterruptedDecaySamples.json +245 -0
  353. package/dist/glass/lens/tabInterruptedRestoreSamples.json +290 -0
  354. package/dist/glass/lens/tabMaterialModel.d.ts +10 -0
  355. package/dist/glass/lens/tabMaterialModel.js +108 -0
  356. package/dist/glass/lens/tabMinimizeInk.d.ts +15 -0
  357. package/dist/glass/lens/tabMinimizeInk.js +14 -0
  358. package/dist/glass/lens/tabMinimizeMotion.d.ts +36 -0
  359. package/dist/glass/lens/tabMinimizeMotion.js +107 -0
  360. package/dist/glass/lens/tabMinimizeSamples.json +411 -0
  361. package/dist/glass/lens/tabMotion.d.ts +91 -0
  362. package/dist/glass/lens/tabMotion.js +478 -0
  363. package/dist/glass/lens/tabMotionFit.d.ts +76 -0
  364. package/dist/glass/lens/tabMotionFit.js +61 -0
  365. package/dist/glass/lens/tabNativeSymbols.d.ts +1 -0
  366. package/dist/glass/lens/tabNativeSymbols.js +7 -0
  367. package/dist/glass/lens/tabPresentation.d.ts +21 -0
  368. package/dist/glass/lens/tabPresentation.js +20 -0
  369. package/dist/glass/lens/tabRelease.d.ts +5 -0
  370. package/dist/glass/lens/tabRelease.js +14 -0
  371. package/dist/glass/lens/tabRestoreMotion.d.ts +19 -0
  372. package/dist/glass/lens/tabRestoreMotion.js +65 -0
  373. package/dist/glass/lens/tabRestoreSamples.json +1272 -0
  374. package/dist/glass/lens/tabSearchMember.d.ts +38 -0
  375. package/dist/glass/lens/tabSearchMember.js +74 -0
  376. package/dist/glass/lens/tabSelectionMaterial.d.ts +20 -0
  377. package/dist/glass/lens/tabSelectionMaterial.js +23 -0
  378. package/dist/glass/lens/tabSelectionMeasurements.test-fixture.d.ts +9 -0
  379. package/dist/glass/lens/tabSelectionMeasurements.test-fixture.js +74 -0
  380. package/dist/glass/lens/tabSettingsSymbol.d.ts +1 -0
  381. package/dist/glass/lens/tabSettingsSymbol.js +2 -0
  382. package/dist/glass/lens/tabShapeResponse.d.ts +7 -0
  383. package/dist/glass/lens/tabShapeResponse.js +30 -0
  384. package/dist/glass/lens/theme.d.ts +18 -0
  385. package/dist/glass/lens/theme.js +40 -0
  386. package/dist/glass/lens/trace.d.ts +2 -0
  387. package/dist/glass/lens/trace.js +27 -0
  388. package/dist/glass/liquidContext.d.ts +31 -0
  389. package/dist/glass/liquidContext.js +2 -0
  390. package/dist/glass/menuPanelPlacement.d.ts +51 -0
  391. package/dist/glass/menuPanelPlacement.js +128 -0
  392. package/dist/glass/menuPresenter.d.ts +34 -0
  393. package/dist/glass/menuPresenter.js +983 -0
  394. package/dist/glass/menuSymbolMasks.d.ts +1 -0
  395. package/dist/glass/menuSymbolMasks.js +1 -0
  396. package/dist/glass/menuSymbolTokens.d.ts +22 -0
  397. package/dist/glass/menuSymbolTokens.js +12 -0
  398. package/dist/glass/menuTriggerGeometry.d.ts +99 -0
  399. package/dist/glass/menuTriggerGeometry.js +126 -0
  400. package/dist/glass/menuTriggerSnapshot.d.ts +77 -0
  401. package/dist/glass/menuTriggerSnapshot.js +69 -0
  402. package/dist/glass/menuTypes.d.ts +22 -0
  403. package/dist/glass/menuTypes.js +1 -0
  404. package/dist/glass/morphField.d.ts +18 -0
  405. package/dist/glass/morphField.js +139 -0
  406. package/dist/glass/presentationFrame.d.ts +43 -0
  407. package/dist/glass/presentationFrame.js +82 -0
  408. package/dist/glass/pressHighlight.d.ts +9 -0
  409. package/dist/glass/pressHighlight.js +158 -0
  410. package/dist/glass/regionRegistry.d.ts +93 -0
  411. package/dist/glass/regionRegistry.js +313 -0
  412. package/dist/glass/regions.d.ts +262 -0
  413. package/dist/glass/regions.js +147 -0
  414. package/dist/glass/regularMaterialContext.d.ts +45 -0
  415. package/dist/glass/regularMaterialContext.js +118 -0
  416. package/dist/glass/regularTriggerMaterial.d.ts +19 -0
  417. package/dist/glass/regularTriggerMaterial.js +111 -0
  418. package/dist/glass/regularTriggerRim.d.ts +163 -0
  419. package/dist/glass/regularTriggerRim.js +436 -0
  420. package/dist/glass/renderSpecs.d.ts +454 -0
  421. package/dist/glass/renderSpecs.js +231 -0
  422. package/dist/glass/rendererContract.d.ts +205 -0
  423. package/dist/glass/rendererContract.js +18 -0
  424. package/dist/glass/shapeTrack.d.ts +53 -0
  425. package/dist/glass/shapeTrack.js +74 -0
  426. package/dist/glass/shapeTrackRegistry.d.ts +40 -0
  427. package/dist/glass/shapeTrackRegistry.js +49 -0
  428. package/dist/glass/sourceDamage.d.ts +6 -0
  429. package/dist/glass/sourceDamage.js +8 -0
  430. package/dist/glass/submenuMotion.d.ts +205 -0
  431. package/dist/glass/submenuMotion.js +306 -0
  432. package/dist/glass/tabBarModel.d.ts +12 -0
  433. package/dist/glass/tabBarModel.js +32 -0
  434. package/dist/glass/testing.d.ts +14 -0
  435. package/dist/glass/testing.js +14 -0
  436. package/dist/glass/tokens.d.ts +79 -0
  437. package/dist/glass/tokens.js +86 -0
  438. package/dist/glass/toolbarMaterialContext.d.ts +28 -0
  439. package/dist/glass/toolbarMaterialContext.js +66 -0
  440. package/dist/glass/topLayer.d.ts +5 -0
  441. package/dist/glass/topLayer.js +10 -0
  442. package/dist/glass/unionOutline.d.ts +11 -0
  443. package/dist/glass/unionOutline.js +98 -0
  444. package/dist/glass/visibleDeadline.d.ts +21 -0
  445. package/dist/glass/visibleDeadline.js +61 -0
  446. package/dist/glass/webgpu/accessoryMorph.d.ts +99 -0
  447. package/dist/glass/webgpu/accessoryMorph.js +473 -0
  448. package/dist/glass/webgpu/accessoryTrack.d.ts +47 -0
  449. package/dist/glass/webgpu/accessoryTrack.js +59 -0
  450. package/dist/glass/webgpu/areaMips.d.ts +50 -0
  451. package/dist/glass/webgpu/areaMips.js +166 -0
  452. package/dist/glass/webgpu/backdrop.d.ts +86 -0
  453. package/dist/glass/webgpu/backdrop.js +243 -0
  454. package/dist/glass/webgpu/backdropLayers.d.ts +29 -0
  455. package/dist/glass/webgpu/backdropLayers.js +182 -0
  456. package/dist/glass/webgpu/backgroundLayers.d.ts +71 -0
  457. package/dist/glass/webgpu/backgroundLayers.js +385 -0
  458. package/dist/glass/webgpu/cadence.d.ts +18 -0
  459. package/dist/glass/webgpu/cadence.js +35 -0
  460. package/dist/glass/webgpu/canvasSubmission.d.ts +6 -0
  461. package/dist/glass/webgpu/canvasSubmission.js +22 -0
  462. package/dist/glass/webgpu/capture.d.ts +77 -0
  463. package/dist/glass/webgpu/capture.js +534 -0
  464. package/dist/glass/webgpu/captureBands.d.ts +39 -0
  465. package/dist/glass/webgpu/captureBands.js +53 -0
  466. package/dist/glass/webgpu/captureContext.d.ts +1 -0
  467. package/dist/glass/webgpu/captureContext.js +6 -0
  468. package/dist/glass/webgpu/captureDemand.d.ts +44 -0
  469. package/dist/glass/webgpu/captureDemand.js +81 -0
  470. package/dist/glass/webgpu/captureRelease.d.ts +18 -0
  471. package/dist/glass/webgpu/captureRelease.js +39 -0
  472. package/dist/glass/webgpu/client.d.ts +49 -0
  473. package/dist/glass/webgpu/client.js +336 -0
  474. package/dist/glass/webgpu/contextBackdrop.d.ts +6 -0
  475. package/dist/glass/webgpu/contextBackdrop.js +13 -0
  476. package/dist/glass/webgpu/contextComposite.d.ts +64 -0
  477. package/dist/glass/webgpu/contextComposite.js +66 -0
  478. package/dist/glass/webgpu/decodedImage.d.ts +1 -0
  479. package/dist/glass/webgpu/decodedImage.js +2 -0
  480. package/dist/glass/webgpu/deviceLimits.d.ts +5 -0
  481. package/dist/glass/webgpu/deviceLimits.js +8 -0
  482. package/dist/glass/webgpu/edgePass.d.ts +9 -0
  483. package/dist/glass/webgpu/edgePass.js +170 -0
  484. package/dist/glass/webgpu/entry.worker.d.ts +1 -0
  485. package/dist/glass/webgpu/entry.worker.js +28 -0
  486. package/dist/glass/webgpu/errorCode.d.ts +3 -0
  487. package/dist/glass/webgpu/errorCode.js +27 -0
  488. package/dist/glass/webgpu/errors.d.ts +8 -0
  489. package/dist/glass/webgpu/errors.js +55 -0
  490. package/dist/glass/webgpu/fieldInk.d.ts +9 -0
  491. package/dist/glass/webgpu/fieldInk.js +62 -0
  492. package/dist/glass/webgpu/foreground.d.ts +29 -0
  493. package/dist/glass/webgpu/foreground.js +313 -0
  494. package/dist/glass/webgpu/frameClock.d.ts +34 -0
  495. package/dist/glass/webgpu/frameClock.js +60 -0
  496. package/dist/glass/webgpu/frameGraph.d.ts +57 -0
  497. package/dist/glass/webgpu/frameGraph.js +287 -0
  498. package/dist/glass/webgpu/frameProbe.d.ts +58 -0
  499. package/dist/glass/webgpu/frameProbe.js +181 -0
  500. package/dist/glass/webgpu/interactionProfiles.d.ts +10 -0
  501. package/dist/glass/webgpu/interactionProfiles.js +25 -0
  502. package/dist/glass/webgpu/keptGlyphs.d.ts +68 -0
  503. package/dist/glass/webgpu/keptGlyphs.js +85 -0
  504. package/dist/glass/webgpu/keyboardBackdrop.d.ts +12 -0
  505. package/dist/glass/webgpu/keyboardBackdrop.js +51 -0
  506. package/dist/glass/webgpu/lagTrace.d.ts +31 -0
  507. package/dist/glass/webgpu/lagTrace.js +22 -0
  508. package/dist/glass/webgpu/layers.d.ts +100 -0
  509. package/dist/glass/webgpu/layers.js +301 -0
  510. package/dist/glass/webgpu/lensDebug.d.ts +4 -0
  511. package/dist/glass/webgpu/lensDebug.js +28 -0
  512. package/dist/glass/webgpu/lensDiffusion.d.ts +2 -0
  513. package/dist/glass/webgpu/lensDiffusion.js +20 -0
  514. package/dist/glass/webgpu/lensLightingFit.json +222 -0
  515. package/dist/glass/webgpu/menuLiftInput.d.ts +30 -0
  516. package/dist/glass/webgpu/menuLiftInput.js +39 -0
  517. package/dist/glass/webgpu/menuSurfaceGuard.d.ts +17 -0
  518. package/dist/glass/webgpu/menuSurfaceGuard.js +26 -0
  519. package/dist/glass/webgpu/minimize.d.ts +184 -0
  520. package/dist/glass/webgpu/minimize.js +470 -0
  521. package/dist/glass/webgpu/navigationAtlasCopy.d.ts +12 -0
  522. package/dist/glass/webgpu/navigationAtlasCopy.js +121 -0
  523. package/dist/glass/webgpu/navigationTracks.d.ts +3 -0
  524. package/dist/glass/webgpu/navigationTracks.js +84 -0
  525. package/dist/glass/webgpu/passes.d.ts +204 -0
  526. package/dist/glass/webgpu/passes.js +394 -0
  527. package/dist/glass/webgpu/pendingSurfaceInput.d.ts +29 -0
  528. package/dist/glass/webgpu/pendingSurfaceInput.js +51 -0
  529. package/dist/glass/webgpu/preparedSourcePixels.d.ts +21 -0
  530. package/dist/glass/webgpu/preparedSourcePixels.js +43 -0
  531. package/dist/glass/webgpu/presentationBackdrop.d.ts +3 -0
  532. package/dist/glass/webgpu/presentationBackdrop.js +33 -0
  533. package/dist/glass/webgpu/presentationDiffusion.d.ts +48 -0
  534. package/dist/glass/webgpu/presentationDiffusion.js +57 -0
  535. package/dist/glass/webgpu/presentationMaterial.d.ts +9 -0
  536. package/dist/glass/webgpu/presentationMaterial.js +156 -0
  537. package/dist/glass/webgpu/presenterViewport.d.ts +11 -0
  538. package/dist/glass/webgpu/presenterViewport.js +193 -0
  539. package/dist/glass/webgpu/production.d.ts +552 -0
  540. package/dist/glass/webgpu/production.js +1929 -0
  541. package/dist/glass/webgpu/productionInstalls.d.ts +53 -0
  542. package/dist/glass/webgpu/productionInstalls.js +225 -0
  543. package/dist/glass/webgpu/productionNavigation.d.ts +5 -0
  544. package/dist/glass/webgpu/productionNavigation.js +360 -0
  545. package/dist/glass/webgpu/productionPinnedTop.d.ts +80 -0
  546. package/dist/glass/webgpu/productionPinnedTop.js +77 -0
  547. package/dist/glass/webgpu/productionPinnedTopPrepare.d.ts +21 -0
  548. package/dist/glass/webgpu/productionPinnedTopPrepare.js +132 -0
  549. package/dist/glass/webgpu/productionPlanes.d.ts +135 -0
  550. package/dist/glass/webgpu/productionPlanes.js +412 -0
  551. package/dist/glass/webgpu/productionPrepare.d.ts +18 -0
  552. package/dist/glass/webgpu/productionPrepare.js +832 -0
  553. package/dist/glass/webgpu/productionTracks.d.ts +73 -0
  554. package/dist/glass/webgpu/productionTracks.js +22 -0
  555. package/dist/glass/webgpu/productionViewport.d.ts +20 -0
  556. package/dist/glass/webgpu/productionViewport.js +52 -0
  557. package/dist/glass/webgpu/profile.d.ts +37 -0
  558. package/dist/glass/webgpu/profile.js +101 -0
  559. package/dist/glass/webgpu/raster.d.ts +337 -0
  560. package/dist/glass/webgpu/raster.js +1360 -0
  561. package/dist/glass/webgpu/rasterMaterial.d.ts +19 -0
  562. package/dist/glass/webgpu/rasterMaterial.js +197 -0
  563. package/dist/glass/webgpu/rasterShaders.d.ts +7 -0
  564. package/dist/glass/webgpu/rasterShaders.js +105 -0
  565. package/dist/glass/webgpu/rasterUniforms.d.ts +304 -0
  566. package/dist/glass/webgpu/rasterUniforms.js +415 -0
  567. package/dist/glass/webgpu/regionBackdrop.d.ts +8 -0
  568. package/dist/glass/webgpu/regionBackdrop.js +12 -0
  569. package/dist/glass/webgpu/regionBridge.d.ts +145 -0
  570. package/dist/glass/webgpu/regionBridge.js +1691 -0
  571. package/dist/glass/webgpu/regionScene.d.ts +294 -0
  572. package/dist/glass/webgpu/regionScene.js +2144 -0
  573. package/dist/glass/webgpu/renderer.d.ts +8 -0
  574. package/dist/glass/webgpu/renderer.js +1478 -0
  575. package/dist/glass/webgpu/residentPlanes.d.ts +69 -0
  576. package/dist/glass/webgpu/residentPlanes.js +104 -0
  577. package/dist/glass/webgpu/restMaterial.d.ts +6 -0
  578. package/dist/glass/webgpu/restMaterial.js +65 -0
  579. package/dist/glass/webgpu/resumeOverlay.d.ts +44 -0
  580. package/dist/glass/webgpu/resumeOverlay.js +82 -0
  581. package/dist/glass/webgpu/sampleTrace.d.ts +11 -0
  582. package/dist/glass/webgpu/sampleTrace.js +50 -0
  583. package/dist/glass/webgpu/scrollEdgeBackdrop.d.ts +89 -0
  584. package/dist/glass/webgpu/scrollEdgeBackdrop.js +177 -0
  585. package/dist/glass/webgpu/scrollEdgePose.d.ts +4 -0
  586. package/dist/glass/webgpu/scrollEdgePose.js +49 -0
  587. package/dist/glass/webgpu/selectionThumb.d.ts +81 -0
  588. package/dist/glass/webgpu/selectionThumb.js +209 -0
  589. package/dist/glass/webgpu/shaders.d.ts +67 -0
  590. package/dist/glass/webgpu/shaders.js +595 -0
  591. package/dist/glass/webgpu/sharedLift.d.ts +7 -0
  592. package/dist/glass/webgpu/sharedLift.js +223 -0
  593. package/dist/glass/webgpu/sourcePixels.d.ts +42 -0
  594. package/dist/glass/webgpu/sourcePixels.js +140 -0
  595. package/dist/glass/webgpu/sourcePixels.worker.d.ts +1 -0
  596. package/dist/glass/webgpu/sourcePixels.worker.js +62 -0
  597. package/dist/glass/webgpu/tabGlyphInk.d.ts +14 -0
  598. package/dist/glass/webgpu/tabGlyphInk.js +72 -0
  599. package/dist/glass/webgpu/touchLight.d.ts +4 -0
  600. package/dist/glass/webgpu/touchLight.js +15 -0
  601. package/dist/glass/worker/client.d.ts +21 -0
  602. package/dist/glass/worker/client.js +152 -0
  603. package/dist/glass/worker/experiment.d.ts +13 -0
  604. package/dist/glass/worker/experiment.js +221 -0
  605. package/dist/glass/worker/fixture.d.ts +21 -0
  606. package/dist/glass/worker/fixture.js +152 -0
  607. package/dist/glass/worker/protocol.d.ts +439 -0
  608. package/dist/glass/worker/protocol.js +5 -0
  609. package/dist/graphicsProbe.d.ts +19 -0
  610. package/dist/graphicsProbe.js +111 -0
  611. package/dist/haptics/SensoryButton.d.ts +21 -0
  612. package/dist/haptics/SensoryButton.js +80 -0
  613. package/dist/image/ContentAdmission.d.ts +19 -0
  614. package/dist/image/ContentAdmission.js +70 -0
  615. package/dist/image/Image.d.ts +30 -0
  616. package/dist/image/Image.js +341 -0
  617. package/dist/image/asset.d.ts +9 -0
  618. package/dist/image/asset.js +1 -0
  619. package/dist/image/contentReadiness.d.ts +7 -0
  620. package/dist/image/contentReadiness.js +54 -0
  621. package/dist/image/imports.d.ts +4 -0
  622. package/dist/image/resource.d.ts +53 -0
  623. package/dist/image/resource.js +286 -0
  624. package/dist/image/vite.d.ts +3 -0
  625. package/dist/image/vite.js +63 -0
  626. package/dist/index.d.ts +87 -0
  627. package/dist/index.js +102 -0
  628. package/dist/install.d.ts +8 -0
  629. package/dist/install.js +8 -0
  630. package/dist/internal.d.ts +96 -0
  631. package/dist/internal.js +80 -0
  632. package/dist/keyboard/adapter.d.ts +82 -0
  633. package/dist/keyboard/adapter.js +727 -0
  634. package/dist/keyboard/avoidance.d.ts +24 -0
  635. package/dist/keyboard/avoidance.js +283 -0
  636. package/dist/keyboard/caretMirror.d.ts +13 -0
  637. package/dist/keyboard/caretMirror.js +122 -0
  638. package/dist/keyboard/expectedKeyboard.d.ts +10 -0
  639. package/dist/keyboard/expectedKeyboard.js +60 -0
  640. package/dist/keyboard/geometry.d.ts +10 -0
  641. package/dist/keyboard/geometry.js +21 -0
  642. package/dist/keyboard/modalTapFocus.d.ts +41 -0
  643. package/dist/keyboard/modalTapFocus.js +224 -0
  644. package/dist/keyboard/motion.d.ts +54 -0
  645. package/dist/keyboard/motion.js +80 -0
  646. package/dist/keyboard/translation.d.ts +12 -0
  647. package/dist/keyboard/translation.js +19 -0
  648. package/dist/layout/adaptiveTabsContext.d.ts +5 -0
  649. package/dist/layout/adaptiveTabsContext.js +2 -0
  650. package/dist/layout/deviceIdiom.d.ts +4 -0
  651. package/dist/layout/deviceIdiom.js +12 -0
  652. package/dist/layout/layoutClass.d.ts +44 -0
  653. package/dist/layout/layoutClass.js +102 -0
  654. package/dist/layout/navigationLayoutContext.d.ts +8 -0
  655. package/dist/layout/navigationLayoutContext.js +5 -0
  656. package/dist/list-form/ListForm.d.ts +158 -0
  657. package/dist/list-form/ListForm.js +427 -0
  658. package/dist/list-form/ListItem.d.ts +30 -0
  659. package/dist/list-form/ListItem.js +251 -0
  660. package/dist/list-form/RowLabel.d.ts +14 -0
  661. package/dist/list-form/RowLabel.js +11 -0
  662. package/dist/list-form/Slider.d.ts +18 -0
  663. package/dist/list-form/Slider.js +235 -0
  664. package/dist/list-form/StepperButton.d.ts +9 -0
  665. package/dist/list-form/StepperButton.js +60 -0
  666. package/dist/list-form/Toggle.d.ts +16 -0
  667. package/dist/list-form/Toggle.js +204 -0
  668. package/dist/list-form/editMotion.d.ts +15 -0
  669. package/dist/list-form/editMotion.js +25 -0
  670. package/dist/list-form/editing.d.ts +102 -0
  671. package/dist/list-form/editing.js +51 -0
  672. package/dist/list-form/listContext.d.ts +4 -0
  673. package/dist/list-form/listContext.js +5 -0
  674. package/dist/list-form/offsets.d.ts +26 -0
  675. package/dist/list-form/offsets.js +34 -0
  676. package/dist/list-form/reorder.d.ts +20 -0
  677. package/dist/list-form/reorder.js +193 -0
  678. package/dist/list-form/rowMotion.d.ts +11 -0
  679. package/dist/list-form/rowMotion.js +236 -0
  680. package/dist/list-form/rowMotionScope.d.ts +14 -0
  681. package/dist/list-form/rowMotionScope.js +61 -0
  682. package/dist/list-form/separatorInsets.d.ts +4 -0
  683. package/dist/list-form/separatorInsets.js +87 -0
  684. package/dist/list-form/sliderContact.d.ts +40 -0
  685. package/dist/list-form/sliderContact.js +98 -0
  686. package/dist/list-form/state.d.ts +5 -0
  687. package/dist/list-form/state.js +8 -0
  688. package/dist/list-form/toggleContact.d.ts +55 -0
  689. package/dist/list-form/toggleContact.js +164 -0
  690. package/dist/media/controller.d.ts +7 -0
  691. package/dist/media/controller.js +612 -0
  692. package/dist/media/react.d.ts +9 -0
  693. package/dist/media/react.js +38 -0
  694. package/dist/media/systemMedia.d.ts +6 -0
  695. package/dist/media/systemMedia.js +200 -0
  696. package/dist/media/types.d.ts +83 -0
  697. package/dist/media/types.js +1 -0
  698. package/dist/menu/menuContact.d.ts +20 -0
  699. package/dist/menu/menuContact.js +286 -0
  700. package/dist/menu/menuGesture.d.ts +84 -0
  701. package/dist/menu/menuGesture.js +502 -0
  702. package/dist/menu/menuInteraction.d.ts +17 -0
  703. package/dist/menu/menuInteraction.js +34 -0
  704. package/dist/menu/menuOutside.d.ts +9 -0
  705. package/dist/menu/menuOutside.js +58 -0
  706. package/dist/menu/menuPanelContact.d.ts +11 -0
  707. package/dist/menu/menuPanelContact.js +77 -0
  708. package/dist/menu/menuTriggerHold.d.ts +3 -0
  709. package/dist/menu/menuTriggerHold.js +52 -0
  710. package/dist/menu/sampledMotion.d.ts +37 -0
  711. package/dist/menu/sampledMotion.js +86 -0
  712. package/dist/modal/lifecycle.d.ts +10 -0
  713. package/dist/modal/lifecycle.js +189 -0
  714. package/dist/motion/TransitionView.d.ts +12 -0
  715. package/dist/motion/TransitionView.js +118 -0
  716. package/dist/motion/animate.d.ts +20 -0
  717. package/dist/motion/animate.js +79 -0
  718. package/dist/motion/animationValue.d.ts +25 -0
  719. package/dist/motion/animationValue.js +42 -0
  720. package/dist/motion/composerMotion.d.ts +3 -0
  721. package/dist/motion/composerMotion.js +15 -0
  722. package/dist/motion/layoutTransaction.d.ts +7 -0
  723. package/dist/motion/layoutTransaction.js +28 -0
  724. package/dist/motion/matchedGeometry.d.ts +55 -0
  725. package/dist/motion/matchedGeometry.js +412 -0
  726. package/dist/motion/springPath.d.ts +27 -0
  727. package/dist/motion/springPath.js +46 -0
  728. package/dist/motion/springTrack.d.ts +33 -0
  729. package/dist/motion/springTrack.js +69 -0
  730. package/dist/motion/transition.d.ts +48 -0
  731. package/dist/motion/transition.js +56 -0
  732. package/dist/motion/transitionImages.d.ts +7 -0
  733. package/dist/motion/transitionImages.js +49 -0
  734. package/dist/motionProbe.d.ts +227 -0
  735. package/dist/motionProbe.js +697 -0
  736. package/dist/motionProbeControls.d.ts +2 -0
  737. package/dist/motionProbeControls.js +118 -0
  738. package/dist/motionProbeDelivery.d.ts +15 -0
  739. package/dist/motionProbeDelivery.js +84 -0
  740. package/dist/navigation/DetailList.d.ts +9 -0
  741. package/dist/navigation/DetailList.js +7 -0
  742. package/dist/navigation/NavigationChrome.d.ts +18 -0
  743. package/dist/navigation/NavigationChrome.js +195 -0
  744. package/dist/navigation/NavigationSearchRow.d.ts +9 -0
  745. package/dist/navigation/NavigationSearchRow.js +101 -0
  746. package/dist/navigation/NavigationTitleSlots.d.ts +18 -0
  747. package/dist/navigation/NavigationTitleSlots.js +64 -0
  748. package/dist/navigation/NavigatorHost.d.ts +17 -0
  749. package/dist/navigation/NavigatorHost.js +534 -0
  750. package/dist/navigation/ScreenContainer.d.ts +31 -0
  751. package/dist/navigation/ScreenContainer.js +219 -0
  752. package/dist/navigation/ScrubSourceFrames.d.ts +18 -0
  753. package/dist/navigation/ScrubSourceFrames.js +67 -0
  754. package/dist/navigation/Sidebar.d.ts +16 -0
  755. package/dist/navigation/Sidebar.js +20 -0
  756. package/dist/navigation/SidebarSymbol.d.ts +4 -0
  757. package/dist/navigation/SidebarSymbol.js +6 -0
  758. package/dist/navigation/ToolbarGlass.d.ts +2 -0
  759. package/dist/navigation/ToolbarGlass.js +429 -0
  760. package/dist/navigation/TransitionEdge.d.ts +4 -0
  761. package/dist/navigation/TransitionEdge.js +33 -0
  762. package/dist/navigation/bottomToolbarGeometry.d.ts +6 -0
  763. package/dist/navigation/bottomToolbarGeometry.js +14 -0
  764. package/dist/navigation/chromeCurves.d.ts +48 -0
  765. package/dist/navigation/chromeCurves.js +255 -0
  766. package/dist/navigation/glassTransition.d.ts +32 -0
  767. package/dist/navigation/glassTransition.js +55 -0
  768. package/dist/navigation/horizontalDrag.d.ts +6 -0
  769. package/dist/navigation/horizontalDrag.js +15 -0
  770. package/dist/navigation/interactivePop.d.ts +45 -0
  771. package/dist/navigation/interactivePop.js +86 -0
  772. package/dist/navigation/interactivePopTypes.d.ts +85 -0
  773. package/dist/navigation/interactivePopTypes.js +36 -0
  774. package/dist/navigation/keyboard.d.ts +9 -0
  775. package/dist/navigation/keyboard.js +55 -0
  776. package/dist/navigation/motion.d.ts +19 -0
  777. package/dist/navigation/motion.js +645 -0
  778. package/dist/navigation/motionTokens.d.ts +43 -0
  779. package/dist/navigation/motionTokens.js +75 -0
  780. package/dist/navigation/nativeScrubExperiment.d.ts +5 -0
  781. package/dist/navigation/nativeScrubExperiment.js +153 -0
  782. package/dist/navigation/nativeScrubSource.d.ts +15 -0
  783. package/dist/navigation/nativeScrubSource.js +88 -0
  784. package/dist/navigation/navigationChromeModel.d.ts +8 -0
  785. package/dist/navigation/navigationChromeModel.js +30 -0
  786. package/dist/navigation/navigationContext.d.ts +22 -0
  787. package/dist/navigation/navigationContext.js +65 -0
  788. package/dist/navigation/navigationEdge.d.ts +4 -0
  789. package/dist/navigation/navigationEdge.js +101 -0
  790. package/dist/navigation/pointerPop.d.ts +32 -0
  791. package/dist/navigation/pointerPop.js +206 -0
  792. package/dist/navigation/probeLayers.d.ts +7 -0
  793. package/dist/navigation/probeLayers.js +8 -0
  794. package/dist/navigation/registry.d.ts +14 -0
  795. package/dist/navigation/registry.js +31 -0
  796. package/dist/navigation/releaseDecision.d.ts +21 -0
  797. package/dist/navigation/releaseDecision.js +94 -0
  798. package/dist/navigation/releaseTrajectory.d.ts +20 -0
  799. package/dist/navigation/releaseTrajectory.js +95 -0
  800. package/dist/navigation/releaseVelocity.d.ts +9 -0
  801. package/dist/navigation/releaseVelocity.js +38 -0
  802. package/dist/navigation/routeCodec.d.ts +33 -0
  803. package/dist/navigation/routeCodec.js +123 -0
  804. package/dist/navigation/scrollEdge.d.ts +18 -0
  805. package/dist/navigation/scrollEdge.js +66 -0
  806. package/dist/navigation/scrubFrameLoop.d.ts +44 -0
  807. package/dist/navigation/scrubFrameLoop.js +129 -0
  808. package/dist/navigation/sidebarSelection.d.ts +5 -0
  809. package/dist/navigation/sidebarSelection.js +8 -0
  810. package/dist/navigation/splitContext.d.ts +17 -0
  811. package/dist/navigation/splitContext.js +9 -0
  812. package/dist/navigation/splitState.d.ts +46 -0
  813. package/dist/navigation/splitState.js +130 -0
  814. package/dist/navigation/stack.d.ts +25 -0
  815. package/dist/navigation/stack.js +136 -0
  816. package/dist/navigation/store.d.ts +80 -0
  817. package/dist/navigation/store.js +464 -0
  818. package/dist/navigation/toolbarGlassMotion.d.ts +40 -0
  819. package/dist/navigation/toolbarGlassMotion.js +202 -0
  820. package/dist/navigation/toolbarMinimization.d.ts +9 -0
  821. package/dist/navigation/toolbarMinimization.js +76 -0
  822. package/dist/navigation/toolbarMotionOwner.d.ts +6 -0
  823. package/dist/navigation/toolbarMotionOwner.js +30 -0
  824. package/dist/navigation/touchArbitration.d.ts +34 -0
  825. package/dist/navigation/touchArbitration.js +550 -0
  826. package/dist/navigation/tracking.d.ts +7 -0
  827. package/dist/navigation/tracking.js +19 -0
  828. package/dist/navigation/transitionBindings.d.ts +31 -0
  829. package/dist/navigation/transitionBindings.js +106 -0
  830. package/dist/navigation/transitionChrome.d.ts +31 -0
  831. package/dist/navigation/transitionChrome.js +380 -0
  832. package/dist/navigation/transitionPose.d.ts +52 -0
  833. package/dist/navigation/transitionPose.js +295 -0
  834. package/dist/navigation/types.d.ts +133 -0
  835. package/dist/navigation/types.js +1 -0
  836. package/dist/navigation/zoomDrag.d.ts +3 -0
  837. package/dist/navigation/zoomDrag.js +125 -0
  838. package/dist/navigation/zoomGeometry.d.ts +48 -0
  839. package/dist/navigation/zoomGeometry.js +94 -0
  840. package/dist/navigation/zoomGlass.d.ts +27 -0
  841. package/dist/navigation/zoomGlass.js +64 -0
  842. package/dist/navigation/zoomMotion.d.ts +73 -0
  843. package/dist/navigation/zoomMotion.js +104 -0
  844. package/dist/navigation/zoomTransition.d.ts +82 -0
  845. package/dist/navigation/zoomTransition.js +975 -0
  846. package/dist/presentation/Presentation.d.ts +61 -0
  847. package/dist/presentation/Presentation.js +92 -0
  848. package/dist/presentation/PresentationSurface.d.ts +29 -0
  849. package/dist/presentation/PresentationSurface.js +586 -0
  850. package/dist/presentation/PresentedSheet.d.ts +2 -0
  851. package/dist/presentation/PresentedSheet.js +571 -0
  852. package/dist/presentation/activity.d.ts +3 -0
  853. package/dist/presentation/activity.js +24 -0
  854. package/dist/presentation/coldLaunch.d.ts +2 -0
  855. package/dist/presentation/coldLaunch.js +19 -0
  856. package/dist/presentation/dismiss.d.ts +26 -0
  857. package/dist/presentation/dismiss.js +30 -0
  858. package/dist/presentation/glassMotion.d.ts +39 -0
  859. package/dist/presentation/glassMotion.js +259 -0
  860. package/dist/presentation/glassReady.d.ts +11 -0
  861. package/dist/presentation/glassReady.js +246 -0
  862. package/dist/presentation/model.d.ts +108 -0
  863. package/dist/presentation/model.js +183 -0
  864. package/dist/presentation/motion.d.ts +56 -0
  865. package/dist/presentation/motion.js +263 -0
  866. package/dist/presentation/presentationMotion.d.ts +10 -0
  867. package/dist/presentation/presentationMotion.js +74 -0
  868. package/dist/presentation/presentationSource.d.ts +2 -0
  869. package/dist/presentation/presentationSource.js +28 -0
  870. package/dist/presentation/sheetChromeContext.d.ts +2 -0
  871. package/dist/presentation/sheetChromeContext.js +3 -0
  872. package/dist/presentation/sheetMaterialTransition.d.ts +14 -0
  873. package/dist/presentation/sheetMaterialTransition.js +33 -0
  874. package/dist/presentation/sheetReleaseMotion.d.ts +18 -0
  875. package/dist/presentation/sheetReleaseMotion.js +123 -0
  876. package/dist/presentation/useAlertKeyboardMotion.d.ts +8 -0
  877. package/dist/presentation/useAlertKeyboardMotion.js +104 -0
  878. package/dist/press/Pressable.d.ts +19 -0
  879. package/dist/press/Pressable.js +16 -0
  880. package/dist/press/activation.d.ts +20 -0
  881. package/dist/press/activation.js +28 -0
  882. package/dist/press/contactReceipt.d.ts +23 -0
  883. package/dist/press/contactReceipt.js +177 -0
  884. package/dist/press/gestureArbitration.d.ts +13 -0
  885. package/dist/press/gestureArbitration.js +38 -0
  886. package/dist/press/stateMachine.d.ts +29 -0
  887. package/dist/press/stateMachine.js +39 -0
  888. package/dist/press/tokens.d.ts +18 -0
  889. package/dist/press/tokens.js +19 -0
  890. package/dist/press/usePressInteraction.d.ts +30 -0
  891. package/dist/press/usePressInteraction.js +247 -0
  892. package/dist/public/Label.d.ts +16 -0
  893. package/dist/public/Label.js +40 -0
  894. package/dist/public/NativeFilePicker.d.ts +19 -0
  895. package/dist/public/NativeFilePicker.js +75 -0
  896. package/dist/public/Screen.d.ts +42 -0
  897. package/dist/public/Screen.js +87 -0
  898. package/dist/public/actions.d.ts +16 -0
  899. package/dist/public/actions.js +15 -0
  900. package/dist/public/buttonBorderShape.d.ts +7 -0
  901. package/dist/public/buttonBorderShape.js +9 -0
  902. package/dist/public/chrome.d.ts +3 -0
  903. package/dist/public/chrome.js +5 -0
  904. package/dist/public/colors.d.ts +29 -0
  905. package/dist/public/colors.js +28 -0
  906. package/dist/public/context.d.ts +19 -0
  907. package/dist/public/context.js +8 -0
  908. package/dist/public/controlStyle.d.ts +93 -0
  909. package/dist/public/controlStyle.js +52 -0
  910. package/dist/public/controls.d.ts +360 -0
  911. package/dist/public/controls.js +301 -0
  912. package/dist/public/definition.d.ts +65 -0
  913. package/dist/public/definition.js +58 -0
  914. package/dist/public/deviceActions.d.ts +23 -0
  915. package/dist/public/deviceActions.js +87 -0
  916. package/dist/public/environment.d.ts +77 -0
  917. package/dist/public/environment.js +171 -0
  918. package/dist/public/fieldContext.d.ts +2 -0
  919. package/dist/public/fieldContext.js +3 -0
  920. package/dist/public/filePickers.d.ts +25 -0
  921. package/dist/public/filePickers.js +11 -0
  922. package/dist/public/glass.d.ts +31 -0
  923. package/dist/public/glass.js +29 -0
  924. package/dist/public/glassValue.d.ts +19 -0
  925. package/dist/public/glassValue.js +32 -0
  926. package/dist/public/keyboard.d.ts +4 -0
  927. package/dist/public/keyboard.js +6 -0
  928. package/dist/public/navigationTransition.d.ts +48 -0
  929. package/dist/public/navigationTransition.js +49 -0
  930. package/dist/public/pickerNavigation.d.ts +7 -0
  931. package/dist/public/pickerNavigation.js +64 -0
  932. package/dist/public/presentation.d.ts +40 -0
  933. package/dist/public/presentation.js +21 -0
  934. package/dist/public/presentationContext.d.ts +2 -0
  935. package/dist/public/presentationContext.js +3 -0
  936. package/dist/public/routeRegistry.d.ts +3 -0
  937. package/dist/public/routeRegistry.js +10 -0
  938. package/dist/public/routes.d.ts +74 -0
  939. package/dist/public/routes.js +105 -0
  940. package/dist/public/runtime.d.ts +134 -0
  941. package/dist/public/runtime.js +292 -0
  942. package/dist/public/screenChrome.d.ts +91 -0
  943. package/dist/public/screenChrome.js +187 -0
  944. package/dist/public/scroll.d.ts +38 -0
  945. package/dist/public/scroll.js +7 -0
  946. package/dist/public/storage.d.ts +9 -0
  947. package/dist/public/storage.js +9 -0
  948. package/dist/public/structure.d.ts +65 -0
  949. package/dist/public/structure.js +40 -0
  950. package/dist/public/toolbar.d.ts +37 -0
  951. package/dist/public/toolbar.js +76 -0
  952. package/dist/push/PushPermissionExplainer.d.ts +14 -0
  953. package/dist/push/PushPermissionExplainer.js +30 -0
  954. package/dist/push/notifications.d.ts +54 -0
  955. package/dist/push/notifications.js +276 -0
  956. package/dist/push/routes.d.ts +20 -0
  957. package/dist/push/routes.js +63 -0
  958. package/dist/push/schema.d.ts +42 -0
  959. package/dist/push/schema.js +41 -0
  960. package/dist/push/urlProjection.d.ts +24 -0
  961. package/dist/push/urlProjection.js +207 -0
  962. package/dist/reachability/controller.d.ts +21 -0
  963. package/dist/reachability/controller.js +202 -0
  964. package/dist/reachability/model.d.ts +94 -0
  965. package/dist/reachability/model.js +131 -0
  966. package/dist/reachability/react.d.ts +29 -0
  967. package/dist/reachability/react.js +69 -0
  968. package/dist/restoration/navigation.d.ts +9 -0
  969. package/dist/restoration/navigation.js +55 -0
  970. package/dist/restoration/react.d.ts +6 -0
  971. package/dist/restoration/react.js +21 -0
  972. package/dist/restoration/routes.d.ts +22 -0
  973. package/dist/restoration/routes.js +166 -0
  974. package/dist/restoration/scene.d.ts +44 -0
  975. package/dist/restoration/scene.js +284 -0
  976. package/dist/root/SatinRoot.d.ts +25 -0
  977. package/dist/root/SatinRoot.js +512 -0
  978. package/dist/root/mountSatin.d.ts +12 -0
  979. package/dist/root/mountSatin.js +60 -0
  980. package/dist/root/runtimeContext.d.ts +26 -0
  981. package/dist/root/runtimeContext.js +30 -0
  982. package/dist/safe-area/Overlay.d.ts +9 -0
  983. package/dist/safe-area/Overlay.js +26 -0
  984. package/dist/safe-area/SafeAreaInset.d.ts +25 -0
  985. package/dist/safe-area/SafeAreaInset.js +138 -0
  986. package/dist/safe-area/bottomInsetGeometry.d.ts +12 -0
  987. package/dist/safe-area/bottomInsetGeometry.js +73 -0
  988. package/dist/safe-area/context.d.ts +15 -0
  989. package/dist/safe-area/context.js +8 -0
  990. package/dist/safe-area/displayCorners.d.ts +21 -0
  991. package/dist/safe-area/displayCorners.js +70 -0
  992. package/dist/safe-area/keyboardCarrier.d.ts +26 -0
  993. package/dist/safe-area/keyboardCarrier.js +394 -0
  994. package/dist/safe-area/keyboardCarrierGeometry.d.ts +37 -0
  995. package/dist/safe-area/keyboardCarrierGeometry.js +49 -0
  996. package/dist/safe-area/modifiers.d.ts +52 -0
  997. package/dist/safe-area/modifiers.js +86 -0
  998. package/dist/safe-area/useSafeAreaMetrics.d.ts +83 -0
  999. package/dist/safe-area/useSafeAreaMetrics.js +367 -0
  1000. package/dist/safe-area/windowChrome.d.ts +7 -0
  1001. package/dist/safe-area/windowChrome.js +14 -0
  1002. package/dist/scroll/RefreshControl.d.ts +8 -0
  1003. package/dist/scroll/RefreshControl.js +135 -0
  1004. package/dist/scroll/ScrollSurface.d.ts +62 -0
  1005. package/dist/scroll/ScrollSurface.js +278 -0
  1006. package/dist/scroll/ScrollTarget.d.ts +6 -0
  1007. package/dist/scroll/ScrollTarget.js +11 -0
  1008. package/dist/scroll/edgePolicy.d.ts +21 -0
  1009. package/dist/scroll/edgePolicy.js +17 -0
  1010. package/dist/scroll/insertionMotion.d.ts +15 -0
  1011. package/dist/scroll/insertionMotion.js +128 -0
  1012. package/dist/scroll/nativeScroll.d.ts +14 -0
  1013. package/dist/scroll/nativeScroll.js +71 -0
  1014. package/dist/scroll/position.d.ts +31 -0
  1015. package/dist/scroll/position.js +273 -0
  1016. package/dist/scroll/pressOwnership.d.ts +4 -0
  1017. package/dist/scroll/pressOwnership.js +65 -0
  1018. package/dist/scroll/refreshMotion.d.ts +9 -0
  1019. package/dist/scroll/refreshMotion.js +15 -0
  1020. package/dist/scroll/refreshable.d.ts +6 -0
  1021. package/dist/scroll/refreshable.js +50 -0
  1022. package/dist/scroll/registry.d.ts +38 -0
  1023. package/dist/scroll/registry.js +261 -0
  1024. package/dist/scroll/screenGeometry.d.ts +8 -0
  1025. package/dist/scroll/screenGeometry.js +50 -0
  1026. package/dist/scroll/scrollIndicator.d.ts +7 -0
  1027. package/dist/scroll/scrollIndicator.js +114 -0
  1028. package/dist/scroll/scrollJump.d.ts +7 -0
  1029. package/dist/scroll/scrollJump.js +16 -0
  1030. package/dist/scroll/types.d.ts +12 -0
  1031. package/dist/scroll/types.js +1 -0
  1032. package/dist/search/SearchDrawer.d.ts +16 -0
  1033. package/dist/search/SearchDrawer.js +421 -0
  1034. package/dist/search/SearchScopesBar.d.ts +6 -0
  1035. package/dist/search/SearchScopesBar.js +12 -0
  1036. package/dist/search/SearchToolbarField.d.ts +8 -0
  1037. package/dist/search/SearchToolbarField.js +115 -0
  1038. package/dist/search/searchBackdrop.d.ts +12 -0
  1039. package/dist/search/searchBackdrop.js +45 -0
  1040. package/dist/search/searchChrome.d.ts +13 -0
  1041. package/dist/search/searchChrome.js +31 -0
  1042. package/dist/search/searchMotion.d.ts +30 -0
  1043. package/dist/search/searchMotion.js +46 -0
  1044. package/dist/search/searchPlacement.d.ts +11 -0
  1045. package/dist/search/searchPlacement.js +15 -0
  1046. package/dist/search/searchable.d.ts +46 -0
  1047. package/dist/search/searchable.js +5 -0
  1048. package/dist/search/useSearchPresentation.d.ts +15 -0
  1049. package/dist/search/useSearchPresentation.js +61 -0
  1050. package/dist/server.d.ts +7 -0
  1051. package/dist/server.js +144 -0
  1052. package/dist/settings/DisclosureIndicator.d.ts +4 -0
  1053. package/dist/settings/DisclosureIndicator.js +6 -0
  1054. package/dist/settings/tokens.d.ts +129 -0
  1055. package/dist/settings/tokens.js +143 -0
  1056. package/dist/shapes/corners.d.ts +14 -0
  1057. package/dist/shapes/corners.js +80 -0
  1058. package/dist/styles.css +9078 -0
  1059. package/dist/styles.css.d.ts +3 -0
  1060. package/dist/sw/activationState.d.ts +20 -0
  1061. package/dist/sw/activationState.js +39 -0
  1062. package/dist/sw/generator.d.ts +14 -0
  1063. package/dist/sw/generator.js +26 -0
  1064. package/dist/sw/manifest.d.ts +32 -0
  1065. package/dist/sw/manifest.js +137 -0
  1066. package/dist/sw/protocol.d.ts +7 -0
  1067. package/dist/sw/protocol.js +7 -0
  1068. package/dist/sw/pushRuntime.d.ts +2 -0
  1069. package/dist/sw/pushRuntime.js +161 -0
  1070. package/dist/sw/registerAppShell.d.ts +25 -0
  1071. package/dist/sw/registerAppShell.js +259 -0
  1072. package/dist/sw/renderServiceWorker.d.ts +10 -0
  1073. package/dist/sw/renderServiceWorker.js +370 -0
  1074. package/dist/sw/requestRouting.d.ts +13 -0
  1075. package/dist/sw/requestRouting.js +26 -0
  1076. package/dist/sw/updateCheck.d.ts +2 -0
  1077. package/dist/sw/updateCheck.js +25 -0
  1078. package/dist/sw/vite.d.ts +20 -0
  1079. package/dist/sw/vite.js +71 -0
  1080. package/dist/symbols/Symbol.d.ts +33 -0
  1081. package/dist/symbols/Symbol.js +59 -0
  1082. package/dist/symbols/catalogue.d.ts +4 -0
  1083. package/dist/symbols/catalogue.js +4139 -0
  1084. package/dist/symbols/exclusions.d.ts +2 -0
  1085. package/dist/symbols/exclusions.js +4 -0
  1086. package/dist/symbols/inheritedWeight.d.ts +3 -0
  1087. package/dist/symbols/inheritedWeight.js +104 -0
  1088. package/dist/symbols/metrics.d.ts +38 -0
  1089. package/dist/symbols/metrics.js +53 -0
  1090. package/dist/symbols/svg.d.ts +3 -0
  1091. package/dist/symbols/svg.js +16 -0
  1092. package/dist/symbols/types.d.ts +30 -0
  1093. package/dist/symbols/types.js +1 -0
  1094. package/dist/tabs/TabSection.d.ts +12 -0
  1095. package/dist/tabs/TabSection.js +4 -0
  1096. package/dist/tabs/TabSidebarSurface.d.ts +7 -0
  1097. package/dist/tabs/TabSidebarSurface.js +29 -0
  1098. package/dist/tabs/TabView.d.ts +28 -0
  1099. package/dist/tabs/TabView.js +258 -0
  1100. package/dist/tabs/accessoryContact.d.ts +2 -0
  1101. package/dist/tabs/accessoryContact.js +42 -0
  1102. package/dist/tabs/compactBar.d.ts +4 -0
  1103. package/dist/tabs/compactBar.js +28 -0
  1104. package/dist/tabs/context.d.ts +8 -0
  1105. package/dist/tabs/context.js +6 -0
  1106. package/dist/tabs/keyboard.d.ts +3 -0
  1107. package/dist/tabs/keyboard.js +23 -0
  1108. package/dist/tabs/model.d.ts +6 -0
  1109. package/dist/tabs/model.js +16 -0
  1110. package/dist/tabs/presentation.d.ts +7 -0
  1111. package/dist/tabs/presentation.js +14 -0
  1112. package/dist/tabs/sourceRevision.d.ts +3 -0
  1113. package/dist/tabs/sourceRevision.js +36 -0
  1114. package/dist/tabs/tabSidebarGlyph.d.ts +2 -0
  1115. package/dist/tabs/tabSidebarGlyph.js +11 -0
  1116. package/dist/tasks/useTask.d.ts +16 -0
  1117. package/dist/tasks/useTask.js +67 -0
  1118. package/dist/testing.d.ts +9 -0
  1119. package/dist/testing.js +11 -0
  1120. package/dist/text-input/TextEditor.d.ts +25 -0
  1121. package/dist/text-input/TextEditor.js +74 -0
  1122. package/dist/text-input/TextField.d.ts +32 -0
  1123. package/dist/text-input/TextField.js +29 -0
  1124. package/dist/text-input/editorGeometry.d.ts +2 -0
  1125. package/dist/text-input/editorGeometry.js +6 -0
  1126. package/dist/text-input/editorTextLayout.d.ts +2 -0
  1127. package/dist/text-input/editorTextLayout.js +31 -0
  1128. package/dist/text-input/focusChain.d.ts +27 -0
  1129. package/dist/text-input/focusChain.js +62 -0
  1130. package/dist/text-input/kinds.d.ts +8 -0
  1131. package/dist/text-input/kinds.js +34 -0
  1132. package/dist/text-input/measureEditor.d.ts +2 -0
  1133. package/dist/text-input/measureEditor.js +50 -0
  1134. package/dist/text-input/submit.d.ts +9 -0
  1135. package/dist/text-input/submit.js +7 -0
  1136. package/dist/unstable.d.ts +16 -0
  1137. package/dist/unstable.js +16 -0
  1138. package/dist/vite.d.ts +3 -0
  1139. package/dist/vite.js +3 -0
  1140. package/dist/web/WebView.d.ts +42 -0
  1141. package/dist/web/WebView.js +115 -0
  1142. package/dist/web/authentication.d.ts +75 -0
  1143. package/dist/web/authentication.js +488 -0
  1144. package/dist/web/openURL.d.ts +37 -0
  1145. package/dist/web/openURL.js +89 -0
  1146. package/dist/web/urlPolicy.d.ts +3 -0
  1147. package/dist/web/urlPolicy.js +19 -0
  1148. package/dist/web/useWebAuthentication.d.ts +3 -0
  1149. package/dist/web/useWebAuthentication.js +6 -0
  1150. package/dist/zoom/Zoomable.d.ts +10 -0
  1151. package/dist/zoom/Zoomable.js +116 -0
  1152. package/dist/zoom/geometry.d.ts +11 -0
  1153. package/dist/zoom/geometry.js +16 -0
  1154. package/package.json +115 -3
@@ -0,0 +1,2144 @@
1
+ import { sampleKeyboardTranslation } from '../../keyboard/translation.js';
2
+ import { accessoryPose, accessoryOffset } from './accessoryTrack.js';
3
+ import { shapeTrackRunning, trackedShapeSpec } from '../shapeTrack.js';
4
+ import { MenuTouchLight } from '../lens/menuTouchLight.js';
5
+ import { FIELD_MOTION_DURATION, ZERO_FIELD_VELOCITY, sampleFieldMember, followFieldTarget, } from '../fieldMotion.js';
6
+ import { sampleMenuCorner } from '../lens/menuCornerMotion.js';
7
+ import { transitionMenuMorph, menuMorphDuration, menuMotionProfile as emergeProfile, menuMorphEndpoint, MENU_MORPH_ZERO, } from '../lens/menuMorphMotion.js';
8
+ import { lowerShapeTop } from '../lens/drawableTop.js';
9
+ import { menuMaterialProgress } from '../lens/menuMotion.js';
10
+ import { glassBlendRadius } from '../morphField.js';
11
+ import { menuFieldFrame, menuSeed, plainMenuPresentation } from '../lens/menuField.js';
12
+ import { menuContextPresentation } from '../lens/menuContextPresentation.js';
13
+ import { contextSampleInset } from './contextComposite.js';
14
+ import { Backdrop } from './backdrop.js';
15
+ import { FrameGraph } from './frameGraph.js';
16
+ import { TabMotion, TAB_INTERACTIVE_MOTION } from '../lens/tabMotion.js';
17
+ import { InteractivePress, interactivePressScale, interactiveHighlight, withHighlight, INTERACTIVE_HIGHLIGHT_RELEASE_MS, } from '../lens/interactivePress.js';
18
+ import { GLASS_CONTACT_PHYSICS, glassContactKind } from '../contactPhysics.js';
19
+ import { InteractiveContact, GLASS_CONTACT_REST, } from '../lens/interactiveContact.js';
20
+ import { GLASS_RENDERER_PROTOCOL, } from '../rendererContract.js';
21
+ import { frameUnion, glassPresenterBounds, glassRadius, glassViewportFrame, isPlainMenuSource, validateGlassRegions, } from '../regions.js';
22
+ import { LayerDevice } from './layers.js';
23
+ import { controlLensSize, controlLiftProfile } from '../lens/controlLift.js';
24
+ import { SelectionThumb, selectionPill } from './selectionThumb.js';
25
+ import { WebGPURaster, drawableCosts } from './raster.js';
26
+ import { glassTiming, glassNow } from './profile.js';
27
+ /** A presenter is a DOM stacking slot. Its shader coordinates remain local. */
28
+ export function regionSpec(region, presenter, scene) {
29
+ const inset = contextSampleInset(region.material.treatment);
30
+ const frame = glassViewportFrame(region, scene.scrolls), radius = glassRadius(region.shape, frame.width, frame.height);
31
+ const spec = {
32
+ id: `region:${region.id}`,
33
+ backdropExclusions: region.backdropExclusions,
34
+ // A menu's glass sees the dim it was opened over. That includes its submenu platters: on
35
+ // their own they would sample the undimmed page, so a bright colour behind the dim (a sent
36
+ // bubble) shone through them at full strength.
37
+ backdropMenuOverlay: !!region.emerge || !!region.inMenuPanel || region.material.treatment === 'contextMenu',
38
+ variant: region.material.variant,
39
+ treatment: region.material.treatment,
40
+ sheetOpaqueMix: region.sheetOpaqueMix,
41
+ popoverArrow: region.popoverArrow,
42
+ // A segmented glass (the scope bar) is pressed like interactive glass: it lights too.
43
+ tint: (region.material.interactive && !region.material.control) || region.selection
44
+ ? withHighlight(region.material.tint, HIGHLIGHT_FLOOR)
45
+ : region.material.tint,
46
+ frameX: frame.x - presenter.origin.x,
47
+ frameY: frame.y - presenter.origin.y,
48
+ frameWidth: frame.width,
49
+ frameHeight: frame.height,
50
+ radius,
51
+ sampleWidth: frame.width + 2 * inset,
52
+ sampleHeight: frame.height + 2 * inset,
53
+ sampleInsetX: inset,
54
+ sampleInsetY: inset,
55
+ shaderAperture: true,
56
+ materialMix: 1,
57
+ // Every menu surface is the menu recipe's frosted material, as native's is: the root menu (the
58
+ // emerging region) and its submenu platters alike. Through the bar recipe (a 2.9 px blur) the
59
+ // page's text and bubbles read clearly through the menu. The root's morph from its trigger
60
+ // blends from the bar recipe (emergeRegionSpec `recipeMix`).
61
+ materialProfile: region.material.treatment === 'contextMenu' || region.inMenuPanel || region.emerge
62
+ ? 'menu'
63
+ : (region.material.recipe ?? 'chrome'),
64
+ shape: {
65
+ blendRadius: 0,
66
+ rimAlpha: (region.material.treatment && region.material.treatment !== 'contextMenu') ||
67
+ region.material.variant === 'clear'
68
+ ? 0
69
+ : 1,
70
+ whiteMix: 0,
71
+ first: {
72
+ centerX: frame.width / 2,
73
+ centerY: frame.height / 2,
74
+ halfWidth: frame.width / 2,
75
+ halfHeight: frame.height / 2,
76
+ radius,
77
+ ...(typeof region.shape === 'object' && region.shape.bottomCornerRadius !== undefined
78
+ ? {
79
+ bottomRadius: Math.min(region.shape.bottomCornerRadius, frame.width / 2, frame.height / 2),
80
+ }
81
+ : {}),
82
+ },
83
+ },
84
+ };
85
+ if (region.selection)
86
+ return { ...spec, tabSelection: selectionPill(spec, region.selection) };
87
+ // A control's lens is installed transparent at rest, before the page lifts it.
88
+ const control = region.material.control;
89
+ return control ? controlLensSpec(spec, control, 0, spec.frameWidth / 2) : spec;
90
+ }
91
+ /** The selection's labels as ink: the region's whole foreground atlas, captured in the region's
92
+ * sample space (regionBridge), drawn over the pill (rasterMaterial encodeTabSelection). */
93
+ export function selectionInk(spec, foreground) {
94
+ if (!spec.tabSelection || !foreground)
95
+ return spec;
96
+ const { width, height } = foreground;
97
+ return {
98
+ ...spec,
99
+ ink: {
100
+ atlas: { width, height },
101
+ layers: [
102
+ {
103
+ source: { x: 0, y: 0, width, height },
104
+ frame: { x: -spec.sampleInsetX, y: -spec.sampleInsetY, width, height },
105
+ opacity: 1,
106
+ blur: 0,
107
+ lens: 0,
108
+ lensWidth: 1,
109
+ },
110
+ ],
111
+ },
112
+ };
113
+ }
114
+ export function fieldRegionSpec(regions, presenter, scene) {
115
+ const base = regionSpec(regions[0], presenter, scene), inset = base.sampleInsetX;
116
+ const members = regions.map(region => {
117
+ const frame = glassViewportFrame(region, scene.scrolls);
118
+ return {
119
+ centerX: frame.x + frame.width / 2 - presenter.origin.x - inset,
120
+ centerY: frame.y + frame.height / 2 - presenter.origin.y - inset,
121
+ halfWidth: frame.width / 2,
122
+ halfHeight: frame.height / 2,
123
+ radius: glassRadius(region.shape, frame.width, frame.height),
124
+ };
125
+ });
126
+ return {
127
+ ...base,
128
+ frameX: inset,
129
+ frameY: inset,
130
+ frameWidth: presenter.width - 2 * inset,
131
+ frameHeight: presenter.height - 2 * inset,
132
+ sampleWidth: presenter.width,
133
+ sampleHeight: presenter.height,
134
+ shape: {
135
+ ...base.shape,
136
+ first: members[0],
137
+ members,
138
+ blendRadius: glassBlendRadius(regions[0].container.spacing),
139
+ },
140
+ };
141
+ }
142
+ /** The phone menu table's time zero after the trigger's release epoch. The fit's zero is native
143
+ * release +43 ms (menuMorphPhoneFit.json); our release epoch is the page's commit and the frame
144
+ * then reaches the screen later, so Catalyst captures (BC5) trailed native by about 25 ms at 43.
145
+ * 20 aligns the measured outline within the native recording's ±30 ms calibration. */
146
+ const MENU_PHONE_RELEASE_LEAD = 20;
147
+ /** How long a phone close holds its open pose after its scene arrives (see the close start). */
148
+ const MENU_PHONE_CLOSE_HOLD = 10;
149
+ /** A release older than this is not the one that opened the menu (keyboard, reopen). */
150
+ const MENU_RELEASE_ANCHOR_WINDOW = 400;
151
+ export { menuMotionProfile as emergeProfile } from '../lens/menuMorphMotion.js';
152
+ /** Shared measured mass 1, stiffness 186.57, damping 25.13. */
153
+ export function fieldSpringProgress(ms) {
154
+ const t = Math.max(0, ms) / 1000, a = 25.13 / 2, w = Math.sqrt(186.57 - a * a);
155
+ return 1 - Math.exp(-a * t) * (Math.cos(w * t) + (a / w) * Math.sin(w * t));
156
+ }
157
+ /** Interactive glass always carries a tint so the press highlight's pass exists from install (no
158
+ * mid-press reallocation); the floor is invisible (1/10000 white). */
159
+ const HIGHLIGHT_FLOOR = 1e-4;
160
+ /** An emerging region samples over its trigger and panel (the presenter bounds). Its glass is one
161
+ * field of two members (lens/menuField.ts): the panel member moves from the trigger's seed (its
162
+ * round part at the menu's own button: the whole trigger when it is a circle; progress 0) to the
163
+ * panel (1) inside that fixed envelope, and the trigger member holds, is absorbed on open and
164
+ * grows back on close. `field` gives the time since the morph's first frame; without it the pose
165
+ * alone decides (the trigger member is present only at progress 0). */
166
+ export function emergeRegionSpec(spec, region, presenter, progress, corner = { rounding: 0 }, liveSource, field, appearance = 'dark') {
167
+ const pose = typeof progress === 'number'
168
+ ? {
169
+ ...MENU_MORPH_ZERO,
170
+ centerX: progress,
171
+ centerY: progress,
172
+ width: progress,
173
+ height: progress,
174
+ }
175
+ : progress;
176
+ const source = liveSource ?? region.emerge?.from;
177
+ if (!source)
178
+ return spec;
179
+ const rest = region.emerge?.returnTo ?? source;
180
+ const from = source;
181
+ const inset = spec.sampleInsetX, bounds = glassPresenterBounds(region.frame, inset, region.emerge);
182
+ const ux = bounds.x + inset, uy = bounds.y + inset, uw = bounds.width - 2 * inset, uh = bounds.height - 2 * inset;
183
+ const lerp = (a, b, p) => a + (b - a) * p;
184
+ const panel = {
185
+ cx: region.frame.x + region.frame.width / 2 - ux,
186
+ cy: region.frame.y + region.frame.height / 2 - uy,
187
+ hw: region.frame.width / 2,
188
+ hh: region.frame.height / 2,
189
+ r: spec.shape.first.radius,
190
+ };
191
+ /** A trigger rectangle (viewport points) as a field member in the presenter's frame. */
192
+ const member = (rect) => ({
193
+ centerX: rect.x + rect.width / 2 - ux,
194
+ centerY: rect.y + rect.height / 2 - uy,
195
+ halfWidth: rect.width / 2,
196
+ halfHeight: rect.height / 2,
197
+ radius: Math.min(rect.radius, rect.width / 2, rect.height / 2),
198
+ });
199
+ const anchor = region.emerge?.anchor && {
200
+ x: region.emerge.anchor.x - ux,
201
+ y: region.emerge.anchor.y - uy,
202
+ };
203
+ const home = member(rest);
204
+ // The drop leaves from the trigger's seed: the pressed aperture's on open, the released
205
+ // trigger's on the way back. For a circle both are the trigger itself.
206
+ // A plain source draws no glass at rest, so its drop grows from (and pours back into) the
207
+ // centre of its seed: menuDropFit.json (a label) and menuGlyphDropFit.json (a glyph) were
208
+ // fitted from that point.
209
+ const seedOf = (shape) => {
210
+ if (region.emerge?.sourceKind === 'context')
211
+ return shape;
212
+ const seed = menuSeed(shape, anchor);
213
+ return isPlainMenuSource(region.emerge?.sourceKind)
214
+ ? { ...seed, halfWidth: 0.05, halfHeight: 0.05, radius: 0.05 }
215
+ : seed;
216
+ };
217
+ const pressed = seedOf(member(from));
218
+ const released = seedOf(home);
219
+ const trigger = {
220
+ cx: pressed.centerX,
221
+ cy: pressed.centerY,
222
+ hw: pressed.halfWidth,
223
+ hh: pressed.halfHeight,
224
+ r: pressed.radius,
225
+ };
226
+ // Return corrections are additive and axis-specific. Multiplying a changing
227
+ // source by (1-progress) inflated the middle of a close and lost the measured path.
228
+ const hw = Math.max(1, lerp(trigger.hw, panel.hw, pose.width) +
229
+ (released.halfWidth - pressed.halfWidth) * pose.returnWidth);
230
+ const hh = Math.max(1, lerp(trigger.hh, panel.hh, pose.height) +
231
+ (released.halfHeight - pressed.halfHeight) * pose.returnHeight);
232
+ const cx = lerp(trigger.cx, panel.cx, pose.centerX) + (released.centerX - pressed.centerX) * pose.returnX;
233
+ const cy = lerp(trigger.cy, panel.cy, pose.centerY) + (released.centerY - pressed.centerY) * pose.returnY;
234
+ // A plain drop's rounding and fade are its own measured curves: it has no glass button to
235
+ // return to.
236
+ const sourceKind = region.emerge?.sourceKind;
237
+ const plainPresentation = sourceKind === 'label' || sourceKind === 'glyph'
238
+ ? plainMenuPresentation(sourceKind, field?.direction ?? 'open', field?.ms ?? 0, field?.settled ?? pose.width >= 1)
239
+ : undefined;
240
+ const contextPresentation = region.emerge?.sourceKind === 'context'
241
+ ? menuContextPresentation(field?.direction ?? 'open', field?.ms ?? 0, field?.settled ?? false, appearance)
242
+ : undefined;
243
+ const moving = lowerShapeTop({
244
+ centerX: cx,
245
+ centerY: cy,
246
+ halfWidth: hw,
247
+ halfHeight: hh,
248
+ // The recorded iPad corner curve squares the early aperture; the phone drop stays round.
249
+ radius: Math.max(0, Math.min(lerp(trigger.r, panel.r, contextPresentation?.radiusProgress ?? pose.width) +
250
+ (released.radius - pressed.radius) * pose.returnWidth +
251
+ (contextPresentation?.rounding ??
252
+ plainPresentation?.rounding ??
253
+ Math.max(0, corner.rounding)) *
254
+ Math.min(hw, hh), hw, hh)),
255
+ }, uy);
256
+ const local = (rect) => ({
257
+ ...rect,
258
+ x: rect.x - ux,
259
+ y: rect.y - uy,
260
+ });
261
+ const ink = region.emerge?.ink;
262
+ const direction = field?.direction ?? 'open';
263
+ const frame = menuFieldFrame({
264
+ sourceKind: region.emerge?.sourceKind,
265
+ direction,
266
+ ms: field?.ms ?? (pose.width >= 1 ? Infinity : 0),
267
+ panel: moving,
268
+ home,
269
+ anchor,
270
+ pressedScale: source.width / rest.width,
271
+ pressHighlight: field?.pressHighlight ?? 0,
272
+ panelFrame: local(region.frame),
273
+ rows: ink?.rows && !(direction === 'open' && region.emerge?.inkDom)
274
+ ? { source: ink.rows.source, frame: local(ink.rows.frame) }
275
+ : undefined,
276
+ glyph: ink?.glyph ? { source: ink.glyph.source, frame: local(ink.glyph.frame) } : undefined,
277
+ settled: field?.settled ?? pose.width >= 1,
278
+ });
279
+ // A source with nothing visible at rest (a label, a recognising context press) prewarms its
280
+ // glass transparent until the presenter is ready; then it is drawn whole.
281
+ const held = (isPlainMenuSource(region.emerge?.sourceKind) ||
282
+ region.emerge?.recognitionEpoch !== undefined) &&
283
+ direction === 'open' &&
284
+ region.emerge.ready === false;
285
+ return {
286
+ ...spec,
287
+ opacity: held
288
+ ? 0
289
+ : (contextPresentation?.opacity ?? plainPresentation?.opacity ?? spec.opacity),
290
+ prewarmTransparent: held,
291
+ frameX: ux - presenter.origin.x,
292
+ frameY: uy - presenter.origin.y,
293
+ frameWidth: uw,
294
+ frameHeight: uh,
295
+ sampleWidth: uw + 2 * inset,
296
+ sampleHeight: uh + 2 * inset,
297
+ // The press highlight carried from the trigger; the floor keeps its pass allocated.
298
+ tint: withHighlight(region.material.tint, Math.max(HIGHLIGHT_FLOOR, frame.highlight)),
299
+ shape: {
300
+ ...spec.shape,
301
+ first: frame.members[0],
302
+ members: frame.members,
303
+ blendRadius: frame.blendRadius,
304
+ },
305
+ ...(ink && frame.ink.length ? { ink: { atlas: ink.atlas, layers: frame.ink } } : {}),
306
+ recipeMix: field?.recipeMix ??
307
+ emergeRecipeMix(sourceKind, direction, field?.ms ?? (pose.width >= 1 ? Infinity : 0)),
308
+ };
309
+ }
310
+ /** Where an emerging menu's material is between its trigger's bar glass (0) and the menu's
311
+ * frosted material (1). A glass button, or a plain glyph's glass bubble, turns into the menu
312
+ * material on native's measured curve (menuMaterialProgress), so the morph starts on the
313
+ * trigger's own glass and ends on the menu's without a swap. A context menu or a text label has
314
+ * no glass to start from: its menu is the frosted material from its first visible frame. */
315
+ function emergeRecipeMix(sourceKind, direction, ms, from = direction === 'open' ? 0 : 1) {
316
+ if (sourceKind === 'context' || sourceKind === 'label')
317
+ return 1;
318
+ const progress = menuMaterialProgress(direction, ms / 1000);
319
+ return direction === 'open' ? from + (1 - from) * progress : from * progress;
320
+ }
321
+ /** The shared native press growth (INTERACTIVE_GLASS_PRESS): a surface's 160pt circle becomes
322
+ * 164pt while held, a button grows 16pt wide. Preserve the material and expand its actual
323
+ * aperture; never cover it with the unfiltered page. `amount` is the press spring (it
324
+ * overshoots on press and undershoots on release). `pose` is the contact's follow and squish
325
+ * (InteractiveContact): it moves the grown shape and changes its width and height, keeping a
326
+ * capsule's ends round.
327
+ */
328
+ export function pressedRegionSpec(spec, amount, kind = 'surface', memberIndex = 0, pose = GLASS_CONTACT_REST) {
329
+ if (amount === 0 && pose === GLASS_CONTACT_REST)
330
+ return spec;
331
+ const member = spec.shape.members?.[memberIndex] ?? spec.shape.first;
332
+ const scale = interactivePressScale(kind, member.halfWidth * 2, amount);
333
+ const halfWidth = Math.max(1, member.halfWidth * scale + pose.width / 2);
334
+ const halfHeight = Math.max(1, member.halfHeight * scale + pose.height / 2);
335
+ const capsule = member.radius >= Math.min(member.halfWidth, member.halfHeight) - 0.01;
336
+ const grown = {
337
+ ...member,
338
+ centerX: member.centerX + pose.x,
339
+ centerY: member.centerY + pose.y,
340
+ halfWidth,
341
+ halfHeight,
342
+ radius: capsule
343
+ ? Math.min(halfWidth, halfHeight)
344
+ : Math.min(member.radius * scale, halfWidth, halfHeight),
345
+ };
346
+ const members = spec.shape.members?.map((shape, index) => (index === memberIndex ? grown : shape));
347
+ return {
348
+ ...spec,
349
+ shape: {
350
+ ...spec.shape,
351
+ first: members?.[0] ?? grown,
352
+ ...(members ? { members } : {}),
353
+ },
354
+ };
355
+ }
356
+ /** A Toggle or Slider thumb lens inside its control's frame: a capsule of the lifted size at the
357
+ * contact's lens centre (frame-local CSS px). At rest it is prepared but transparent; the page's
358
+ * opaque white thumb covers the hand-off while the lens grows. */
359
+ export function controlLensSpec(spec, kind, amount, centerX) {
360
+ const size = controlLensSize(kind, amount);
361
+ const first = {
362
+ ...spec.shape.first,
363
+ centerX,
364
+ halfWidth: size.width / 2,
365
+ halfHeight: size.height / 2,
366
+ radius: size.height / 2,
367
+ };
368
+ return {
369
+ ...spec,
370
+ // The held lens keeps the clear material's rim (native shows a darker lens edge).
371
+ shape: { ...spec.shape, first, rimAlpha: 1 },
372
+ opacity: amount > 0 ? 1 : 0,
373
+ prewarmTransparent: true,
374
+ };
375
+ }
376
+ /** Implements the public scene/source protocol on the page's existing GPU owner. */
377
+ export class RegionScene {
378
+ samplePixels = 0;
379
+ scene = { revision: 0, layers: [], regions: [], scrolls: [] };
380
+ presenters = new Map();
381
+ sources = new Map();
382
+ emptyForeground;
383
+ drop(id) {
384
+ const source = this.sources.get(id);
385
+ if (!source)
386
+ return;
387
+ source.lease.release();
388
+ this.sources.delete(id);
389
+ }
390
+ /** Install the chrome's shared capture (already retained in the frame graph under
391
+ * `key`) as the root backdrop: one transfer and one upload serve chrome and regions. */
392
+ async shareSource(descriptor, bitmap, key, ordered = false) {
393
+ const previous = this.sources.get(descriptor.id);
394
+ // Standalone source updates reject stale captures. The worker transport can explicitly
395
+ // restore an older resident capture after a pop; its request revision already orders it.
396
+ if (!ordered && previous && previous.descriptor.revision >= descriptor.revision)
397
+ return;
398
+ const lease = FrameGraph.for(this.owner).image(key, bitmap);
399
+ this.drop(descriptor.id);
400
+ this.sources.set(descriptor.id, { descriptor, bitmap: lease.value, lease });
401
+ this.sourcesChanged = true;
402
+ // The settled capture after a navigation replaces its route atlas.
403
+ if (descriptor.id === 'root-backdrop')
404
+ this.navigation = undefined;
405
+ await this.install();
406
+ }
407
+ get sharedRevision() {
408
+ return this.sources.get('root-backdrop')?.descriptor.revision;
409
+ }
410
+ get navigationActive() {
411
+ return !!this.navigation;
412
+ }
413
+ motions = new Map();
414
+ touchLights = new Map();
415
+ /** Scope thumbs in flight (GlassRegion.selection): segment index from → to since `start`. */
416
+ /** The thumbs of segmented regions (the search scope bar), by region id. */
417
+ thumbs = new Map();
418
+ reducedMotion = false;
419
+ /** Emerging regions (glass Menus): direction, start (epoch ms) and the progress it starts from. */
420
+ emerges = new Map();
421
+ fields = new Map();
422
+ appearance;
423
+ /** Presenters whose backdrop only moved (scroll under a fixed region): redrawn once
424
+ * in the next worker frame instead of reinstalled and fenced per scroll event. */
425
+ moved = new Set();
426
+ /** A pressed interactive region is being dragged or held (its motion is live). */
427
+ get pressing() {
428
+ return [...this.motions.values()].some(m => m.motion.needsFrame ||
429
+ m.press.needsFrame ||
430
+ this.highlighting(m, performance.timeOrigin + performance.now()));
431
+ }
432
+ /** The press highlight still changes (held: its first 600 ms; released: its fade). */
433
+ highlighting(m, at) {
434
+ return (m.downAt !== undefined &&
435
+ (m.upAt === undefined
436
+ ? at < m.downAt + 620
437
+ : at < m.upAt + INTERACTIVE_HIGHLIGHT_RELEASE_MS + 20));
438
+ }
439
+ /** A backdrop plane scrolled or the plane set changed: redraw only presenters whose
440
+ * composed backdrop differs (scroll-attached glass over its own plane does not). */
441
+ backdropMoved() {
442
+ for (const p of this.presenters.values())
443
+ if (p.raster?.spec && !p.covered && !p.suspended && p.raster.backdropStale())
444
+ this.moved.add(p);
445
+ }
446
+ /** The plane set is about to be replaced by another tab's (a source preparation committed).
447
+ * `regionIds` are the regions of tabs that are not selected. Called BEFORE the new planes are
448
+ * installed, so each of those presenters is drawn one last time over its own tab's backdrop (a
449
+ * press still animating is settled at rest first) and then parked: from here on its canvas keeps
450
+ * those pixels, and nothing can draw another tab's backdrop into it. */
451
+ holdForBackdropChange(regionIds) {
452
+ const held = new Set(regionIds);
453
+ this.scene = {
454
+ ...this.scene,
455
+ regions: this.scene.regions.map(region => held.has(region.id) && !region.suspended ? { ...region, suspended: true } : region),
456
+ };
457
+ // A press that is still animating ends at rest (drawn over the region's own backdrop).
458
+ for (const id of held) {
459
+ const state = this.motions.get(id);
460
+ if (!state || !this.motionLive(state))
461
+ continue;
462
+ state.motion.reset(0);
463
+ state.press.reset();
464
+ state.downAt = undefined;
465
+ state.upAt = undefined;
466
+ this.presentMotion(id, state);
467
+ }
468
+ for (const p of this.presenters.values()) {
469
+ if (!held.has(p.descriptor.regionIds[0]) || p.parked)
470
+ continue;
471
+ p.suspended = true;
472
+ this.moved.delete(p);
473
+ // Repainted while nothing could be submitted (an appearance change waiting to be presented):
474
+ // its canvas still shows the old appearance. `present` draws it, then parks it.
475
+ if (p.parkAfterPresent)
476
+ continue;
477
+ // A merge or split still running ends at its target (drawn over the region's own backdrop).
478
+ const field = this.fields.get(p.descriptor.id);
479
+ if (field) {
480
+ this.fields.delete(p.descriptor.id);
481
+ if (p.raster?.spec && !p.covered) {
482
+ p.raster.updateSpec(field.to);
483
+ p.raster.draw(0);
484
+ }
485
+ }
486
+ // Never drawn (it mounted while its tab was hidden): nothing to keep, nothing to sample.
487
+ if (!p.raster || !p.materialKey) {
488
+ this.park(p);
489
+ continue;
490
+ }
491
+ if (p.raster.spec && !p.covered && p.raster.backdropStale())
492
+ p.raster.draw(0);
493
+ this.park(p);
494
+ }
495
+ }
496
+ /** The new plane set is installed. Every region that is not in `heldIds` belongs to the selected
497
+ * tab: it resumes now (the next install redraws it over its own backdrop), at the same point of
498
+ * the batch where an unheld region is redrawn. */
499
+ resumeForBackdropChange(heldIds) {
500
+ const held = new Set(heldIds);
501
+ this.scene = {
502
+ ...this.scene,
503
+ regions: this.scene.regions.map(region => region.suspended && !held.has(region.id) ? { ...region, suspended: false } : region),
504
+ };
505
+ }
506
+ /** Install what the last resume left pending: a parked presenter whose region is no longer held.
507
+ * Nothing is pending in a scene that held nothing, so a renderer without regions (or one that has
508
+ * not been given its appearance yet) is never installed from here. */
509
+ async installPending() {
510
+ const pending = [...this.presenters.values()].some(presenter => {
511
+ if (!presenter.parked)
512
+ return false;
513
+ const region = this.scene.regions.find(r => r.id === presenter.descriptor.regionIds[0]);
514
+ return !!region && !region.suspended;
515
+ });
516
+ if (pending)
517
+ await this.install();
518
+ }
519
+ motionLive(state) {
520
+ const at = performance.timeOrigin + performance.now();
521
+ return (state.motion.needsFrame ||
522
+ state.press.needsFrame ||
523
+ this.highlighting(state, at) ||
524
+ !!state.contact?.needsFrame(at));
525
+ }
526
+ park(p) {
527
+ p.raster?.park();
528
+ p.parked = true;
529
+ p.parkAfterPresent = false;
530
+ p.key = undefined;
531
+ p.storageKey = undefined;
532
+ }
533
+ /** Marks parked presenters whose region is not held for a repaint; true when there is one. */
534
+ repaintVisibleParked() {
535
+ let any = false;
536
+ for (const p of this.presenters.values())
537
+ if (p.parked && !p.suspended) {
538
+ p.repaint = true;
539
+ any = true;
540
+ }
541
+ return any;
542
+ }
543
+ keyboardSampledAt = -Infinity;
544
+ get active() {
545
+ return ([...this.presenters.values()].some(p => !p.parked && !p.suspended && p.keyboard && this.keyboardSampledAt < p.keyboard.end) ||
546
+ this.scene.regions.some(region => {
547
+ const track = region.presentationViewportTrack ?? region.accessoryViewportTrack ?? region.accessoryTrack;
548
+ return (track &&
549
+ track.epoch !== Number.MAX_VALUE &&
550
+ performance.timeOrigin + performance.now() < track.epoch + track.duration);
551
+ }) ||
552
+ this.scene.regions.some(region => region.shapeTrack &&
553
+ shapeTrackRunning(region.shapeTrack, performance.timeOrigin + performance.now())) ||
554
+ [...this.touchLights.values()].some(light => light.needsFrame(performance.timeOrigin + performance.now())) ||
555
+ this.fields.size > 0 ||
556
+ [...this.thumbs.values()].some(thumb => thumb.live(performance.timeOrigin + performance.now())) ||
557
+ this.moved.size > 0 ||
558
+ [...this.motions.values()].some(m => this.motionLive(m)) ||
559
+ [...this.emerges.values()].some(e => this.emergeRunning(e, performance.timeOrigin + performance.now()) ||
560
+ (e.direction === 'close' && !e.settled && !e.frozen)));
561
+ }
562
+ emergeRunning(e, at) {
563
+ if (e.held || e.frozen)
564
+ return false;
565
+ // An open runs until its settled frame hands the rows back to the page.
566
+ if (e.shown && e.direction === 'open' && !e.inkNotified)
567
+ return true;
568
+ return e.shown
569
+ ? at < e.start + menuMorphDuration(e.direction, e.idiom) + 34
570
+ : at < e.start + 1000;
571
+ }
572
+ emergeSample(state, at) {
573
+ if (state.held)
574
+ return { pose: state.from, velocity: MENU_MORPH_ZERO };
575
+ if (this.reducedMotion) {
576
+ return { pose: menuMorphEndpoint(state.direction), velocity: MENU_MORPH_ZERO };
577
+ }
578
+ return transitionMenuMorph(state.direction, at - state.start, state.from, state.velocity, state.idiom, this.appearance);
579
+ }
580
+ presentEmerge(id, at, present = true) {
581
+ if (this.deferred || !this.visible)
582
+ return;
583
+ const region = this.scene.regions.find(r => r.id === id), state = this.emerges.get(id);
584
+ if (!region || !state)
585
+ return;
586
+ const presenters = [...this.presenters.values()].filter(p => p.descriptor.regionIds[0] === id && p.raster?.spec);
587
+ if (!presenters.length)
588
+ return;
589
+ // The trigger's press highlight continues in the field until the drop leaves (native).
590
+ const trigger = region.emerge?.sourceRegionId
591
+ ? this.motions.get(region.emerge.sourceRegionId)
592
+ : undefined;
593
+ const liveHighlight = state.direction === 'open' && trigger?.downAt !== undefined
594
+ ? interactiveHighlight('menu', this.appearance, trigger.downAt, trigger.upAt, at)
595
+ : 0;
596
+ // The morph starts at the panel glass's first presented frame, not when its scene arrived: a
597
+ // new presenter's setup (~100 ms under load) otherwise ate the start of the morph.
598
+ if (!state.held && !state.frozen) {
599
+ if (!state.shown) {
600
+ // Menu captured the pressed trigger at activation. Its release spring may already
601
+ // have material by this first visible frame; do not replace that frozen source.
602
+ if (state.direction === 'open' && region.emerge?.from)
603
+ state.source = region.emerge.from;
604
+ state.shown = true;
605
+ // The phone table is timed from the trigger's release (+43 ms); anchoring there keeps
606
+ // capture and pipeline latency out of the motion (it only skips the held first knots).
607
+ const released = trigger?.upAt;
608
+ state.start =
609
+ state.direction === 'open' && region.emerge?.recognitionEpoch !== undefined
610
+ ? region.emerge.recognitionEpoch
611
+ : state.direction === 'open' &&
612
+ state.idiom === 'phone' &&
613
+ released !== undefined &&
614
+ at - released < MENU_RELEASE_ANCHOR_WINDOW
615
+ ? Math.min(at, released + MENU_PHONE_RELEASE_LEAD)
616
+ : at;
617
+ state.pressHighlight = liveHighlight;
618
+ glassTiming('menu-morph-start', at, state.direction);
619
+ }
620
+ state.progress = this.emergeSample(state, at).pose;
621
+ state.corner = this.reducedMotion
622
+ ? { rounding: 0 }
623
+ : sampleMenuCorner(state.direction, at - state.start, state.cornerFrom, state.cornerVelocity).pose;
624
+ }
625
+ const ms = state.shown && !state.held ? at - state.start : 0;
626
+ const duration = menuMorphDuration(state.direction, state.idiom);
627
+ const field = state.frozen && state.field
628
+ ? state.field
629
+ : {
630
+ direction: state.direction,
631
+ ms,
632
+ pressHighlight: state.shown ? (state.pressHighlight ?? 0) : liveHighlight,
633
+ settled: this.reducedMotion || (state.direction === 'open' && ms >= duration),
634
+ recipeMix: emergeRecipeMix(region.emerge?.sourceKind, state.direction, this.reducedMotion ? Infinity : ms, state.materialFrom),
635
+ };
636
+ state.field = field;
637
+ let drawn = false;
638
+ for (const p of presenters) {
639
+ const spec = emergeRegionSpec(regionSpec(region, p.descriptor, this.scene), region, p.descriptor, state.progress, state.corner, state.source, field, this.appearance);
640
+ p.raster.updateSpec(this.illuminate(spec, region, p.descriptor, at));
641
+ if (present) {
642
+ p.raster.draw(0);
643
+ drawn ||= p.descriptor.role === 'material';
644
+ }
645
+ }
646
+ // Ink hand-off with the page's live rows, after a submitted frame: the page shows its rows
647
+ // once the glass draws them settled, and hides them once the glass draws them closing.
648
+ // Either order overlaps identical ink for a frame rather than leaving a blank panel.
649
+ if (!drawn || !state.shown || state.held || state.frozen)
650
+ return;
651
+ if (state.direction === 'close' && !state.inkNotified) {
652
+ state.inkNotified = true;
653
+ this.notify({
654
+ type: 'emerge-ink',
655
+ regionId: id,
656
+ generation: state.generation,
657
+ phase: 'close-started',
658
+ });
659
+ }
660
+ else if (state.direction === 'open' && field.settled && !state.inkNotified) {
661
+ state.inkNotified = true;
662
+ this.notify({
663
+ type: 'emerge-ink',
664
+ regionId: id,
665
+ generation: state.generation,
666
+ phase: 'open-settled',
667
+ });
668
+ }
669
+ }
670
+ /** A navigation in progress: presenters over the settled chrome backdrop compose its route atlas
671
+ * (the moving routes, the destination included) in place of the content plane, at the pose of
672
+ * every worker frame, as native glass shows the page moving under it. The next settled backdrop
673
+ * (the capture after the navigation) ends it. */
674
+ navigation;
675
+ async navigationSource(navigation) {
676
+ // The running track's pose: presenters never present the atlas without it (all routes at rest).
677
+ this.navigation = { ...navigation, deferPresent: navigation.deferPresent ?? !!navigation.pose };
678
+ await this.install();
679
+ }
680
+ setNavigation(pose, key, draw = true) {
681
+ if (!this.navigation || (key !== undefined && key !== this.navigation.key))
682
+ return;
683
+ this.navigation.pose = pose;
684
+ for (const p of this.presenters.values())
685
+ if (p.navigation === this.navigation.key && p.raster?.spec && !p.covered) {
686
+ p.raster.setNavigation(this.presenterNavigationPose(pose, p.zoomRoute));
687
+ if (draw && this.visible && !this.deferred)
688
+ p.raster.draw(0);
689
+ }
690
+ }
691
+ presenterNavigationPose(pose, route) {
692
+ if (route === undefined)
693
+ return pose;
694
+ return {
695
+ ...pose,
696
+ routes: pose.routes?.map((_, index) => ({ x: index === route ? 0 : 1e9, dim: 0 })),
697
+ };
698
+ }
699
+ /** Glass changing size inside a still canvas: draw each frame's shape at its presentation time. */
700
+ presentShapeTracks(at) {
701
+ for (const region of this.scene.regions) {
702
+ const track = region.shapeTrack;
703
+ if (!track)
704
+ continue;
705
+ for (const p of this.presenters.values()) {
706
+ if (!p.descriptor.regionIds.includes(region.id) ||
707
+ !p.raster?.spec ||
708
+ p.parked ||
709
+ p.suspended ||
710
+ p.descriptor.role === 'lift')
711
+ continue;
712
+ p.raster.updateSpec(this.shapeAt(region, p.raster.spec, track, at));
713
+ if (this.visible && !this.deferred)
714
+ p.raster.draw(0);
715
+ }
716
+ }
717
+ }
718
+ shapeAt(region, spec, track, at) {
719
+ return trackedShapeSpec(spec, track, at, (width, height) => glassRadius(region.shape, width, height));
720
+ }
721
+ presentTrackedViewport(at) {
722
+ for (const region of this.scene.regions) {
723
+ const track = region.presentationViewportTrack ?? region.accessoryViewportTrack ?? region.accessoryTrack;
724
+ if (!track)
725
+ continue;
726
+ const foreground = this.sources.get(`foreground:${region.id}`);
727
+ for (const p of this.presenters.values()) {
728
+ if (!p.descriptor.regionIds.includes(region.id) ||
729
+ !p.raster?.spec ||
730
+ p.parked ||
731
+ p.descriptor.role === 'lift')
732
+ continue;
733
+ // A pressed accessory draws through its press, which poses the run underneath it
734
+ // (`posedRegionSpec`). Posing here as well would draw the run without the press.
735
+ const interaction = this.motions.get(region.id);
736
+ const pressed = region.accessoryTrack &&
737
+ interaction &&
738
+ (interaction.press.amount !== 0 || this.interactionMoving(interaction, at))
739
+ ? interaction
740
+ : undefined;
741
+ if (region.accessoryTrack?.held && foreground) {
742
+ // A held-still canvas keeps its sampling viewport; the glass moves inside it.
743
+ if (pressed)
744
+ this.presentMotion(region.id, pressed, at);
745
+ else {
746
+ p.raster.updateSpec(accessoryPose(p.raster.spec, region.accessoryTrack, at, foreground.descriptor, this.restingFrame(region, p.descriptor)));
747
+ if (this.visible && !this.deferred)
748
+ p.raster.draw(0);
749
+ }
750
+ continue;
751
+ }
752
+ const offset = accessoryOffset(track, at);
753
+ // The DOM viewport observer is paused for this sampling track. Update the
754
+ // sampling viewport itself: an older liveViewport overrides viewportOrigin.
755
+ p.raster.setViewport({
756
+ x: p.descriptor.origin.x + offset.x,
757
+ y: p.descriptor.origin.y + offset.y,
758
+ scaleX: 1,
759
+ scaleY: 1,
760
+ });
761
+ if (p.accessorySourceOrigin)
762
+ p.raster.setSourceOrigin({
763
+ x: p.accessorySourceOrigin.x + offset.x,
764
+ y: p.accessorySourceOrigin.y + offset.y,
765
+ });
766
+ if (pressed) {
767
+ this.presentMotion(region.id, pressed, at);
768
+ continue;
769
+ }
770
+ if (region.accessoryTrack && foreground)
771
+ p.raster.updateSpec(accessoryPose(p.raster.spec, region.accessoryTrack, at, foreground.descriptor));
772
+ if (this.visible && !this.deferred)
773
+ p.raster.draw(0);
774
+ }
775
+ }
776
+ }
777
+ /** Whether a region's press or contact still moves (or lights) its glass at `at`. */
778
+ interactionMoving(state, at) {
779
+ return (state.motion.needsFrame ||
780
+ state.press.needsFrame ||
781
+ this.highlighting(state, at) ||
782
+ !!state.contact?.needsFrame(at));
783
+ }
784
+ /**
785
+ * `spec` (a region's scene spec in `presenter`) posed by its shape track and by the bottom
786
+ * accessory's run at `at` when one is live: the run's capsule width and ink and, for a held-still canvas, its travel
787
+ * inside the canvas. Without a run (or before its ink arrives) it is `spec` unchanged.
788
+ *
789
+ * The run and a press both draw the accessory, and a press builds on this pose. A press that
790
+ * rebuilt from the scene spec drew the run's whole envelope, without ink, at the committed
791
+ * row, until the run's next frame: the owner's smudge recording (a finger on the mini player
792
+ * while the bar collapsed) showed that empty capsule running past the Search circle.
793
+ */
794
+ posedRegionSpec(region, presenter, spec, at) {
795
+ // Glass changing size inside a still canvas (a submenu growing or collapsing) presses
796
+ // the frame it is drawn at, not its whole envelope.
797
+ const shaped = region.shapeTrack ? this.shapeAt(region, spec, region.shapeTrack, at) : spec;
798
+ const track = region.accessoryTrack;
799
+ const foreground = this.sources.get(`foreground:${region.id}`);
800
+ if (!track || !foreground)
801
+ return shaped;
802
+ const resting = track.held ? this.restingFrame(region, presenter) : undefined;
803
+ return accessoryPose(shaped, track, at, foreground.descriptor, resting);
804
+ }
805
+ /** Where a region's glass frame sits in its presenter at the region's laid-out position. */
806
+ restingFrame(region, presenter) {
807
+ const frame = glassViewportFrame(region, this.scene.scrolls);
808
+ return { x: frame.x - presenter.origin.x, y: frame.y - presenter.origin.y };
809
+ }
810
+ /**
811
+ * The time the last frame sampled the tracks at. A draw between frames (an install or a
812
+ * scroll update) poses accessory tracks at that time too: the other surfaces of the frame,
813
+ * such as the tab bar on its minimize track, stay where that frame sampled them, and a pose
814
+ * taken at the draw's own time put the moving accessory a frame ahead of the bar.
815
+ */
816
+ sampledAt;
817
+ trackClock() {
818
+ return this.sampledAt ?? performance.timeOrigin + performance.now();
819
+ }
820
+ sample(at, presentationAt = at) {
821
+ this.sampledAt = presentationAt;
822
+ if (this.sourcePending)
823
+ return;
824
+ // Only compositor-owned viewport trajectories use the predicted presentation
825
+ // time. Input, canvas-owned animation and teardown keep the actual clock.
826
+ // Keyboard motion has no presentation lead: source and lens use the actual
827
+ // carrier clock, including its endpoint hold while the document is stalled.
828
+ this.keyboardSampledAt = at;
829
+ for (const p of this.presenters.values()) {
830
+ if (!p.keyboard || !p.viewport || !p.raster || p.parked || p.suspended)
831
+ continue;
832
+ p.viewport = { ...p.viewport, y: sampleKeyboardTranslation(p.keyboard, at) };
833
+ p.raster.setViewport(p.viewport);
834
+ if (p.raster.backdropStale())
835
+ this.moved.add(p);
836
+ }
837
+ this.presentTrackedViewport(presentationAt);
838
+ this.presentShapeTracks(presentationAt);
839
+ for (const [id, thumb] of this.thumbs)
840
+ if (thumb.live(at)) {
841
+ thumb.sample(at, this.reducedMotion, this.appearance);
842
+ this.presentSelection(id, at);
843
+ }
844
+ for (const [id, motion] of this.fields) {
845
+ const p = this.presenters.get(id);
846
+ // A parked presenter has no setup to move: its field ended when it was held.
847
+ if (!p?.raster || p.parked) {
848
+ this.fields.delete(id);
849
+ continue;
850
+ }
851
+ const elapsed = at - motion.start;
852
+ const members = motion.to.shape.members.map((member, index) => sampleFieldMember(motion.from.shape.members[index] ?? member, member, motion.velocity[index] ?? ZERO_FIELD_VELOCITY, elapsed, this.reducedMotion).value);
853
+ p.raster.updateSpec({
854
+ ...motion.to,
855
+ shape: { ...motion.to.shape, first: members[0], members },
856
+ });
857
+ if (this.visible && !this.deferred)
858
+ p.raster.draw(0);
859
+ if (this.reducedMotion || elapsed >= FIELD_MOTION_DURATION)
860
+ this.fields.delete(id);
861
+ }
862
+ if (this.visible && !this.deferred && this.moved.size) {
863
+ // A presenter is marked when its plane scrolls. Scroll-attached glass is marked then too,
864
+ // because the scroll reaches the renderer before the scene that moves the glass with it;
865
+ // once that scene is in, its backdrop is the one it last drew. Drawing it anyway re-encoded
866
+ // and presented every glass canvas of a scrolling page in every frame (10 canvases, 3.5 MP
867
+ // on the glass components page). With the renderer in the document that work is part of
868
+ // the page's own frame, and the page missed frames.
869
+ const installed = Backdrop.for(this.owner).installed;
870
+ for (const p of this.moved) {
871
+ if (installed && !p.raster?.backdropStale())
872
+ continue;
873
+ p.raster?.draw(0);
874
+ }
875
+ }
876
+ this.moved.clear();
877
+ for (const [id, state] of this.emerges) {
878
+ if (this.emergeRunning(state, at))
879
+ this.presentEmerge(id, at);
880
+ // A close morph at its end (or one whose panel never presented): the page may tear it down.
881
+ if (state.direction === 'close' &&
882
+ !state.frozen &&
883
+ !state.settled &&
884
+ (state.shown
885
+ ? at >= state.start + menuMorphDuration('close', state.idiom)
886
+ : !this.emergeRunning(state, at))) {
887
+ state.settled = true;
888
+ this.notify({ type: 'emerge-settled', regionId: id, generation: state.generation });
889
+ }
890
+ }
891
+ for (const [id, light] of this.touchLights) {
892
+ if (!light.needsFrame(at))
893
+ continue;
894
+ const emerge = this.emerges.get(id);
895
+ if (emerge && this.emergeRunning(emerge, at))
896
+ continue;
897
+ const region = this.scene.regions.find(region => region.id === id);
898
+ if (!region || !this.visible || this.deferred)
899
+ continue;
900
+ for (const presenter of this.presenters.values()) {
901
+ if (!presenter.descriptor.regionIds.includes(id) ||
902
+ !presenter.raster?.spec ||
903
+ presenter.parked)
904
+ continue;
905
+ presenter.raster.updateSpec(this.illuminate(presenter.raster.spec, region, presenter.descriptor, at));
906
+ presenter.raster.draw(0);
907
+ }
908
+ }
909
+ for (const [id, state] of this.motions) {
910
+ if (!this.interactionMoving(state, at))
911
+ continue;
912
+ if (state.motion.needsFrame)
913
+ state.motion.sample(at, this.reducedMotion);
914
+ state.press.sample(at, this.reducedMotion);
915
+ this.presentMotion(id, state, at);
916
+ }
917
+ }
918
+ /** A selection the page changed slides its thumb from wherever it is now (SelectionThumb). */
919
+ retargetSelections(regions) {
920
+ const now = performance.timeOrigin + performance.now();
921
+ for (const region of regions) {
922
+ if (!region.selection) {
923
+ this.thumbs.delete(region.id);
924
+ continue;
925
+ }
926
+ const thumb = this.thumbs.get(region.id);
927
+ if (!thumb) {
928
+ this.thumbs.set(region.id, new SelectionThumb(region.frame, region.selection));
929
+ continue;
930
+ }
931
+ thumb.configure(region.frame, region.selection);
932
+ thumb.select(region.selection.index, now, this.reducedMotion);
933
+ }
934
+ for (const id of this.thumbs.keys())
935
+ if (!regions.some(region => region.id === id))
936
+ this.thumbs.delete(id);
937
+ }
938
+ /** The finger on a segmented region's thumb. */
939
+ selectionInput(region, input) {
940
+ let thumb = this.thumbs.get(region.id);
941
+ if (!thumb) {
942
+ thumb = new SelectionThumb(region.frame, region.selection);
943
+ this.thumbs.set(region.id, thumb);
944
+ }
945
+ thumb.input(input, this.reducedMotion);
946
+ this.presentSelection(region.id, performance.timeOrigin + performance.now());
947
+ }
948
+ /** The bar draws its pill where the thumb is; its lift overlay draws the lens over the bar. */
949
+ presentSelection(id, at) {
950
+ const thumb = this.thumbs.get(id);
951
+ const region = this.scene.regions.find(r => r.id === id);
952
+ if (!thumb || !region?.selection || this.deferred || !this.visible)
953
+ return;
954
+ thumb.sample(at, this.reducedMotion, this.appearance);
955
+ for (const p of this.presenters.values()) {
956
+ if (!p.descriptor.regionIds.includes(id) || p.descriptor.regionIds.length !== 1)
957
+ continue;
958
+ if (!p.raster?.spec || p.parked)
959
+ continue;
960
+ const base = selectionInk(regionSpec(region, p.descriptor, this.scene), this.sources.get(`foreground:${id}`)?.descriptor);
961
+ p.raster.updateSpec(this.posedSelection(base, region, p.descriptor, thumb, at));
962
+ if (p.descriptor.role === 'lift')
963
+ p.raster.setLift(thumb.lift());
964
+ p.raster.draw(0);
965
+ }
966
+ }
967
+ illuminate(spec, region, presenter, at) {
968
+ const controller = this.touchLights.get(region.id);
969
+ if (!controller)
970
+ return spec;
971
+ const light = controller.sample(this.appearance, at);
972
+ const frame = glassViewportFrame(region, this.scene.scrolls);
973
+ return {
974
+ ...spec,
975
+ touchLight: light
976
+ ? {
977
+ ...light,
978
+ x: light.x + frame.x - presenter.origin.x - spec.frameX,
979
+ y: light.y + frame.y - presenter.origin.y - spec.frameY,
980
+ }
981
+ : undefined,
982
+ };
983
+ }
984
+ /** A segmented region with its thumb where the motion has it, and its bar grown and lit while
985
+ * a finger presses it (the segmented row of GLASS_CONTACT_PHYSICS). */
986
+ posedSelection(spec, region, presenter, thumb, at) {
987
+ return this.pressLight(thumb.pose(spec, region.selection), region, presenter, {
988
+ kind: 'segmented',
989
+ light: thumb.touchLight,
990
+ memberIndex: undefined,
991
+ downAt: thumb.pressedAt,
992
+ upAt: thumb.releasedAt,
993
+ at,
994
+ });
995
+ }
996
+ presentMotion(id, { motion, press, downAt, upAt, lensCenter, contact, }, at = performance.timeOrigin + performance.now(), present = true) {
997
+ if (this.deferred || !this.visible)
998
+ return;
999
+ const region = this.scene.regions.find(r => r.id === id);
1000
+ if (!region)
1001
+ return;
1002
+ const control = region.material.control;
1003
+ if (control) {
1004
+ // The lens is the lift overlay's moving lens (the tab selection's optics: rim, refraction
1005
+ // bands, exterior shadow); the material presenter stays transparent under it.
1006
+ for (const p of this.presenters.values())
1007
+ if (p.descriptor.role === 'lift' &&
1008
+ p.descriptor.regionIds.includes(id) &&
1009
+ p.raster?.spec &&
1010
+ !p.parked) {
1011
+ const base = regionSpec(region, p.descriptor, this.scene);
1012
+ const lifted = press.amount > 0 || motion.lensMix > 0;
1013
+ const lens = controlLensSpec(base, control, press.amount, lensCenter ?? base.frameWidth / 2);
1014
+ p.raster.updateSpec({ ...lens, opacity: lifted ? 1 : 0 });
1015
+ p.raster.setLift({
1016
+ amount: lifted ? 1 : 0,
1017
+ source: 'transmissive',
1018
+ profile: 'control',
1019
+ glyphVibrancy: [0, 0],
1020
+ glyphLayout: 'content',
1021
+ capsule: lens.shape.first,
1022
+ optics: { ...motion.optics(), foregroundScaleX: 0, foregroundScaleY: 0 },
1023
+ });
1024
+ if (present)
1025
+ p.raster.draw(0);
1026
+ }
1027
+ return;
1028
+ }
1029
+ const kind = glassContactKind(region.material);
1030
+ const pose = contact?.pose(at, this.reducedMotion) ?? GLASS_CONTACT_REST;
1031
+ const light = contact?.light.sample(this.appearance, at);
1032
+ for (const p of this.presenters.values())
1033
+ if (p.descriptor.regionIds.includes(id) && p.raster?.spec && !p.parked) {
1034
+ const members = p.descriptor.regionIds
1035
+ .map(memberId => this.scene.regions.find(candidate => candidate.id === memberId))
1036
+ .filter((member) => member !== undefined);
1037
+ const memberIndex = members.findIndex(member => member.id === id);
1038
+ const base = members.length > 1
1039
+ ? fieldRegionSpec(members, p.descriptor, this.scene)
1040
+ : this.posedRegionSpec(region, p.descriptor, regionSpec(region, p.descriptor, this.scene), at);
1041
+ const grown = pressedRegionSpec(base, press.amount, kind, memberIndex, pose);
1042
+ p.raster.updateSpec(this.pressLight(grown, region, p.descriptor, {
1043
+ kind,
1044
+ light,
1045
+ memberIndex: members.length > 1 ? memberIndex : undefined,
1046
+ downAt,
1047
+ upAt,
1048
+ at,
1049
+ }));
1050
+ if (present)
1051
+ p.raster.draw(0);
1052
+ }
1053
+ }
1054
+ /**
1055
+ * The light of a pressed interactive shape: the menu's touch light at the finger
1056
+ * (InteractiveContact). Each kind's light is a row of GLASS_CONTACT_PHYSICS: a button-like
1057
+ * glass whitens across its shape on its measured curve; a surface's light is the menu field
1058
+ * scaled to native, over a held floor across the whole shape. In a field of several members the light stays inside the
1059
+ * pressed member's aperture (one member's light never spills onto its neighbours).
1060
+ */
1061
+ pressLight(spec, region, presenter, press) {
1062
+ const { kind, light, memberIndex, downAt, upAt, at } = press;
1063
+ const physics = GLASS_CONTACT_PHYSICS[kind].light;
1064
+ const surface = physics.kind === 'finger';
1065
+ if (downAt === undefined || (surface && !light))
1066
+ return { ...spec, touchLight: undefined };
1067
+ // The light's own envelope (rise, release fade) shapes a surface's floor too.
1068
+ const envelope = light && surface ? Math.min(1, light.intensity / physics.menuPeak) : 0;
1069
+ const floor = surface ? physics.floor * envelope : 0;
1070
+ const intensity = surface
1071
+ ? (light?.intensity ?? 0) * physics.scale
1072
+ : interactiveHighlight(kind, this.appearance, downAt, upAt, at);
1073
+ // A press without a finger (a button driven only by its press state) whitens uniformly.
1074
+ if (!light)
1075
+ return memberIndex === undefined
1076
+ ? {
1077
+ ...spec,
1078
+ touchLight: undefined,
1079
+ tint: withHighlight(region.material.tint, Math.max(HIGHLIGHT_FLOOR, intensity)),
1080
+ }
1081
+ : {
1082
+ ...spec,
1083
+ touchLight: undefined,
1084
+ memberHighlight: {
1085
+ member: memberIndex,
1086
+ amount: Math.max(0, intensity - HIGHLIGHT_FLOOR) / (1 - HIGHLIGHT_FLOOR),
1087
+ },
1088
+ };
1089
+ const frame = glassViewportFrame(region, this.scene.scrolls);
1090
+ const touchLight = {
1091
+ ...light,
1092
+ intensity,
1093
+ x: light.x + frame.x - presenter.origin.x - spec.frameX,
1094
+ y: light.y + frame.y - presenter.origin.y - spec.frameY,
1095
+ };
1096
+ if (memberIndex !== undefined)
1097
+ return {
1098
+ ...spec,
1099
+ touchLight: undefined,
1100
+ // The resting floor is already in the shared material. Composite only the remaining
1101
+ // floor and the touch light inside the pressed member's aperture.
1102
+ memberHighlight: {
1103
+ member: memberIndex,
1104
+ amount: Math.max(0, floor - HIGHLIGHT_FLOOR),
1105
+ light: touchLight,
1106
+ },
1107
+ };
1108
+ return {
1109
+ ...spec,
1110
+ tint: withHighlight(region.material.tint, Math.max(HIGHLIGHT_FLOOR, floor)),
1111
+ touchLight,
1112
+ };
1113
+ }
1114
+ setLensDebug(view) {
1115
+ for (const p of this.presenters.values()) {
1116
+ p.raster?.setLensDebug(view);
1117
+ p.raster?.draw(0);
1118
+ }
1119
+ }
1120
+ deferred = false;
1121
+ visible = true;
1122
+ sourceRevision;
1123
+ sourcePending = false;
1124
+ topologyPending = false;
1125
+ /** A capture cannot draw retained geometry from the previous root/layout. Keep its
1126
+ * last submitted pixels until the matching scene arrives; do not reset any motion. */
1127
+ beginSourceChange(revision) {
1128
+ this.sourceRevision = revision;
1129
+ this.sourcePending = true;
1130
+ }
1131
+ submissionAllowed;
1132
+ owner;
1133
+ /** Worker-to-page events (a close morph that ended, so its panel can be torn down). */
1134
+ notify;
1135
+ constructor(owner, notify = () => { }, submissionAllowed = () => true) {
1136
+ this.submissionAllowed = () => !this.sourcePending && submissionAllowed();
1137
+ this.owner = owner;
1138
+ this.notify = notify;
1139
+ }
1140
+ async request(request) {
1141
+ switch (request.type) {
1142
+ case 'transaction': {
1143
+ this.deferred = true;
1144
+ try {
1145
+ for (const operation of request.requests)
1146
+ await this.request(operation);
1147
+ }
1148
+ finally {
1149
+ this.deferred = false;
1150
+ }
1151
+ await this.install();
1152
+ return this.presentationReceipt();
1153
+ }
1154
+ case 'initialize':
1155
+ if (request.protocol !== GLASS_RENDERER_PROTOCOL)
1156
+ throw Error('Unsupported glass renderer protocol');
1157
+ this.appearance = request.appearance;
1158
+ this.reducedMotion = request.reducedMotion;
1159
+ return;
1160
+ case 'update-presenter': {
1161
+ const p = this.presenters.get(request.presenter.id);
1162
+ if (!p)
1163
+ throw Error('Missing glass presenter');
1164
+ // Rebase retained shapes only when the envelope moves within its container.
1165
+ // Scrolling translates both origins together; rebasing that translation makes
1166
+ // the next scene start a false spring and redraw the entire union every frame.
1167
+ const from = p.descriptor.fieldOrigin;
1168
+ const to = request.presenter.fieldOrigin;
1169
+ // A resizing container (for example a bottom-anchored composer) moves its
1170
+ // origin as part of the layout change. Preserve its previous screen pose
1171
+ // for the morph; only a size-preserving translation is ordinary scrolling.
1172
+ const resized = p.descriptor.width !== request.presenter.width ||
1173
+ p.descriptor.height !== request.presenter.height;
1174
+ const translationX = from && to && !resized ? from.x - to.x : 0;
1175
+ const translationY = from && to && !resized ? from.y - to.y : 0;
1176
+ const offsetX = p.descriptor.origin.x - request.presenter.origin.x - translationX;
1177
+ const offsetY = p.descriptor.origin.y - request.presenter.origin.y - translationY;
1178
+ const previous = p.raster?.spec;
1179
+ if (previous?.shape.members && (offsetX || offsetY)) {
1180
+ const shift = (spec) => {
1181
+ const members = spec.shape.members.map(member => ({
1182
+ ...member,
1183
+ centerX: member.centerX + offsetX,
1184
+ centerY: member.centerY + offsetY,
1185
+ }));
1186
+ return { ...spec, shape: { ...spec.shape, first: members[0], members } };
1187
+ };
1188
+ p.raster?.updateSpec(shift(previous));
1189
+ const motion = this.fields.get(request.presenter.id);
1190
+ if (motion) {
1191
+ motion.from = shift(motion.from);
1192
+ motion.to = shift(motion.to);
1193
+ }
1194
+ }
1195
+ p.descriptor = request.presenter;
1196
+ return;
1197
+ }
1198
+ case 'region-shape-track': {
1199
+ this.scene = {
1200
+ ...this.scene,
1201
+ regions: this.scene.regions.map(region => region.id === request.regionId ? { ...region, shapeTrack: request.track } : region),
1202
+ };
1203
+ return;
1204
+ }
1205
+ case 'region-presentation-track': {
1206
+ // Late input from a previous modal show cannot move its replacement.
1207
+ this.scene = {
1208
+ ...this.scene,
1209
+ regions: this.scene.regions.map(region => region.id === request.regionId &&
1210
+ region.presentationContentEpoch === request.contentEpoch
1211
+ ? { ...region, presentationViewportTrack: request.track }
1212
+ : region),
1213
+ };
1214
+ return;
1215
+ }
1216
+ case 'presenter-viewport': {
1217
+ const presenter = this.presenters.get(request.id);
1218
+ // A queued geometry read can outlive its presenter during close/navigation.
1219
+ if (!presenter)
1220
+ return;
1221
+ const viewport = request.viewport;
1222
+ if (!Object.values(viewport).every(Number.isFinite) ||
1223
+ viewport.scaleX <= 0 ||
1224
+ viewport.scaleY <= 0)
1225
+ throw Error('Invalid glass viewport mapping');
1226
+ presenter.viewport = viewport;
1227
+ presenter.keyboard = request.keyboard;
1228
+ if (!presenter.raster || presenter.parked || presenter.suspended)
1229
+ return;
1230
+ // An observation queued before the transition cannot take viewport ownership
1231
+ // back from its sampling track, or publish one frame at the old position.
1232
+ if (this.scene.regions.some(region => (region.presentationViewportTrack ||
1233
+ region.accessoryViewportTrack ||
1234
+ region.accessoryTrack) &&
1235
+ presenter.descriptor.regionIds.includes(region.id)))
1236
+ return;
1237
+ if (request.keyboard) {
1238
+ // Draw from the worker frame after the backdrop has sampled this same clock.
1239
+ this.moved.add(presenter);
1240
+ return;
1241
+ }
1242
+ presenter.raster.setViewport(viewport);
1243
+ if (this.visible && !this.deferred && presenter.raster.backdropStale())
1244
+ presenter.raster.draw(0);
1245
+ return;
1246
+ }
1247
+ case 'attach-presenter': {
1248
+ if (this.presenters.has(request.presenter.id))
1249
+ throw Error('Duplicate glass presenter ' + request.presenter.id);
1250
+ if (request.presenter.width <= 0 ||
1251
+ request.presenter.height <= 0 ||
1252
+ !Number.isFinite(request.presenter.resolution) ||
1253
+ request.presenter.resolution <= 0)
1254
+ throw Error('Invalid glass presenter dimensions');
1255
+ this.presenters.set(request.presenter.id, {
1256
+ descriptor: request.presenter,
1257
+ canvas: request.canvas,
1258
+ });
1259
+ return;
1260
+ }
1261
+ case 'detach-presenter': {
1262
+ const p = this.presenters.get(request.id);
1263
+ p?.raster?.dispose();
1264
+ this.owner.detach(request.id);
1265
+ this.presenters.delete(request.id);
1266
+ this.fields.delete(request.id);
1267
+ return;
1268
+ }
1269
+ case 'scene': {
1270
+ if (this.sourceRevision !== undefined &&
1271
+ request.snapshot.sourceRevision !== this.sourceRevision)
1272
+ return { superseded: true, presented: [] };
1273
+ // Exclusions come from live DOM order; captured dialog planes retire later.
1274
+ // Never expose a departing plane by installing its close scene first. The
1275
+ // source batch and its matching scene release this hold without a timed delay.
1276
+ // Extra live owners may still be preparing their first plane. A reparented
1277
+ // region can change exclusions immediately when the captured order agrees.
1278
+ const owners = request.snapshot.backdropOwners;
1279
+ if (owners) {
1280
+ const captured = [
1281
+ ...new Set(Backdrop.for(this.owner).layers.flatMap(layer => (layer.owner ? [layer.owner] : []))),
1282
+ ];
1283
+ const order = owners.filter(owner => captured.includes(owner));
1284
+ if (captured.length !== order.length ||
1285
+ captured.some((owner, index) => owner !== order[index])) {
1286
+ this.topologyPending = true;
1287
+ return { superseded: true, presented: [] };
1288
+ }
1289
+ }
1290
+ this.topologyPending = false;
1291
+ if (request.snapshot.revision < this.scene.revision)
1292
+ throw Error('Stale glass scene revision');
1293
+ const budget = validateGlassRegions(request.snapshot.regions, Math.max(1, ...[...this.presenters.values()].map(p => p.descriptor.resolution)));
1294
+ glassTiming('sample-pixel-budget', glassNow(), String(budget.samplePixels));
1295
+ for (const region of request.snapshot.regions) {
1296
+ if (!request.snapshot.layers.some(l => JSON.stringify(l) === JSON.stringify(region.layer)))
1297
+ throw Error('Undeclared glass region layer ' + region.layer.id);
1298
+ const presentation = region.material.treatment;
1299
+ if (presentation) {
1300
+ const requiredVariant = presentation === 'sheet' ||
1301
+ presentation === 'expandedSheet' ||
1302
+ presentation === 'contextBackdrop' ||
1303
+ presentation === 'contextPreview'
1304
+ ? 'clear'
1305
+ : 'regular';
1306
+ if (region.material.tint ||
1307
+ region.material.variant !== requiredVariant ||
1308
+ region.material.interactive)
1309
+ throw Error('Unsupported named presentation material');
1310
+ }
1311
+ if (typeof region.shape === 'object' &&
1312
+ region.shape.cornerStyle === 'continuous' &&
1313
+ !presentation)
1314
+ throw Error('Unsupported continuous region corner profile');
1315
+ }
1316
+ for (const [id, state] of this.motions) {
1317
+ const before = this.scene.regions.find(r => r.id === id), after = request.snapshot.regions.find(r => r.id === id);
1318
+ if (after &&
1319
+ before &&
1320
+ (before.frame.width !== after.frame.width || before.frame.height !== after.frame.height)) {
1321
+ state.motion.configure([after.frame.width / 2], after.frame.width, after.frame.height, after.frame.width);
1322
+ state.motion.reset(0);
1323
+ state.press.reset();
1324
+ }
1325
+ }
1326
+ this.retargetSelections(request.snapshot.regions);
1327
+ this.sourcePending = false;
1328
+ this.scene = request.snapshot;
1329
+ this.samplePixels = budget.samplePixels;
1330
+ for (const id of this.touchLights.keys())
1331
+ if (!this.scene.regions.some(region => region.id === id && region.material.touchLight))
1332
+ this.touchLights.delete(id);
1333
+ for (const [id] of this.motions)
1334
+ if (!this.scene.regions.some(r => r.id === id))
1335
+ this.motions.delete(id);
1336
+ const now = performance.timeOrigin + performance.now();
1337
+ for (const [id] of this.emerges)
1338
+ if (!this.scene.regions.some(r => r.id === id && r.emerge))
1339
+ this.emerges.delete(id);
1340
+ for (const region of this.scene.regions) {
1341
+ if (!region.emerge)
1342
+ continue;
1343
+ const state = this.emerges.get(region.id), direction = region.emerge.closing ? 'close' : 'open';
1344
+ const generation = region.emerge.generation, held = direction === 'open' && region.emerge.ready === false;
1345
+ if (state && direction === 'close' && region.emerge.fading) {
1346
+ // Freeze the last frame actually presented, including its field/ink clock.
1347
+ state.frozen = true;
1348
+ continue;
1349
+ }
1350
+ if (!state)
1351
+ this.emerges.set(region.id, {
1352
+ direction,
1353
+ start: now,
1354
+ from: direction === 'open' ? { ...MENU_MORPH_ZERO } : menuMorphEndpoint('open'),
1355
+ velocity: { ...MENU_MORPH_ZERO },
1356
+ progress: direction === 'open' ? { ...MENU_MORPH_ZERO } : menuMorphEndpoint('open'),
1357
+ cornerFrom: { rounding: 0 },
1358
+ cornerVelocity: { rounding: 0 },
1359
+ corner: { rounding: 0 },
1360
+ generation,
1361
+ held,
1362
+ idiom: emergeProfile(region.emerge),
1363
+ });
1364
+ else if (state.frozen || state.direction !== direction || state.generation !== generation)
1365
+ this.emerges.set(region.id, {
1366
+ direction,
1367
+ // The phone close table's zero is the tap +45 ms; its scene arrives about 10 ms
1368
+ // sooner (Catalyst, native measurements), so the menu holds that long, as native does.
1369
+ start: direction === 'close' &&
1370
+ region.emerge.idiom === 'phone' &&
1371
+ region.emerge.sourceKind === undefined
1372
+ ? now + MENU_PHONE_CLOSE_HOLD
1373
+ : now,
1374
+ from: this.emergeSample(state, now).pose,
1375
+ velocity: this.emergeSample(state, now).velocity,
1376
+ // Continue from the material that was actually presented, using the same measured
1377
+ // curve over the remaining distance. Uninterrupted tracks retain their native fit.
1378
+ materialFrom: state.field?.recipeMix ??
1379
+ emergeRecipeMix(region.emerge.sourceKind, state.direction, state.field?.ms ?? 0, state.materialFrom),
1380
+ cornerFrom: state.corner,
1381
+ cornerVelocity: sampleMenuCorner(state.direction, now - state.start, state.cornerFrom, state.cornerVelocity).velocity,
1382
+ corner: state.corner,
1383
+ source: state.source,
1384
+ progress: state.progress,
1385
+ // A context close starts its clock at its first presented frame. The page hides its
1386
+ // live rows only after that frame (emerge-ink), so the one frame that shows both must
1387
+ // draw the ink exactly where the rows are; timed from the scene's arrival, it had
1388
+ // already moved and the rows showed twice (Music Home tile, 2026-10-14).
1389
+ shown: held || (direction === 'close' && region.emerge.sourceKind === 'context')
1390
+ ? false
1391
+ : state.shown,
1392
+ generation,
1393
+ held,
1394
+ idiom: emergeProfile(region.emerge),
1395
+ });
1396
+ else if (state.held !== held) {
1397
+ state.held = held;
1398
+ state.shown = false;
1399
+ state.start = now;
1400
+ }
1401
+ }
1402
+ for (const [id, source] of this.sources)
1403
+ if (source.descriptor.role === 'foreground' &&
1404
+ !this.scene.regions.some(r => r.id === source.descriptor.regionId)) {
1405
+ source.lease.release();
1406
+ this.sources.delete(id);
1407
+ }
1408
+ await this.install();
1409
+ return this.presentationReceipt();
1410
+ }
1411
+ case 'source': {
1412
+ if (request.source.role !== 'transmitted-backdrop' &&
1413
+ request.source.role !== 'foreground') {
1414
+ request.bitmap.close();
1415
+ throw Error('Unsupported glass source role ' + request.source.role);
1416
+ }
1417
+ if (request.bitmap.width <= 0 ||
1418
+ request.bitmap.height <= 0 ||
1419
+ request.source.width * request.source.resolution !== request.bitmap.width ||
1420
+ request.source.height * request.source.resolution !== request.bitmap.height) {
1421
+ request.bitmap.close();
1422
+ throw Error('Invalid glass source bitmap dimensions');
1423
+ }
1424
+ const previous = this.sources.get(request.source.id);
1425
+ if (previous && previous.descriptor.revision > request.source.revision) {
1426
+ request.bitmap.close();
1427
+ throw Error(`Stale glass source revision: ${request.source.revision} after ${previous.descriptor.revision}`);
1428
+ }
1429
+ const source = request.source, key = source.role === 'foreground'
1430
+ ? `${source.id}:${source.revision}`
1431
+ : (source.id === 'root-backdrop'
1432
+ ? `production:${source.revision}`
1433
+ : `region:${source.id}:${source.revision}`) + ':front';
1434
+ const lease = FrameGraph.for(this.owner).image(key, request.bitmap);
1435
+ previous?.lease.release();
1436
+ this.sources.set(source.id, { descriptor: source, bitmap: lease.value, lease });
1437
+ this.sourcesChanged = true;
1438
+ // The settled capture after a navigation replaces its route atlas.
1439
+ if (source.id === 'root-backdrop')
1440
+ this.navigation = undefined;
1441
+ await this.install();
1442
+ return this.presentationReceipt();
1443
+ }
1444
+ case 'release-source':
1445
+ this.drop(request.id);
1446
+ for (const p of this.presenters.values())
1447
+ if (p.sourceId === request.id) {
1448
+ p.raster?.clear();
1449
+ p.raster?.setCovered(true);
1450
+ p.covered = true;
1451
+ p.key = undefined;
1452
+ p.storageKey = undefined;
1453
+ }
1454
+ return;
1455
+ case 'interaction': {
1456
+ const input = request.interaction, region = this.scene.regions.find(r => r.id === input.regionId);
1457
+ if (!region)
1458
+ return;
1459
+ if (region.selection) {
1460
+ this.selectionInput(region, input);
1461
+ return;
1462
+ }
1463
+ if (region.material.touchLight) {
1464
+ let light = this.touchLights.get(region.id);
1465
+ if (!light) {
1466
+ light = new MenuTouchLight();
1467
+ this.touchLights.set(region.id, light);
1468
+ }
1469
+ light.input(input);
1470
+ return;
1471
+ }
1472
+ if (!region.material.interactive)
1473
+ return;
1474
+ if (!Number.isFinite(input.epoch))
1475
+ throw Error('Invalid glass interaction epoch');
1476
+ let state = this.motions.get(region.id);
1477
+ if (state && input.epoch < state.epoch)
1478
+ return;
1479
+ if (!state) {
1480
+ const motion = new TabMotion(TAB_INTERACTIVE_MOTION);
1481
+ motion.configure([region.frame.width / 2], region.frame.width, region.frame.height, region.frame.width);
1482
+ motion.reset(0);
1483
+ const profile = region.material.control
1484
+ ? controlLiftProfile(region.material.control)
1485
+ : undefined;
1486
+ state = { motion, press: new InteractivePress(profile), epoch: 0 };
1487
+ this.motions.set(region.id, state);
1488
+ }
1489
+ state.epoch = input.epoch;
1490
+ const { motion, press } = state;
1491
+ if (region.material.control) {
1492
+ // The page owns activation and the thumb's position; the lens follows both. The tab
1493
+ // motion runs only for its lens optics: the control's own springs size the lens.
1494
+ if (input.contact)
1495
+ state.lensCenter = input.contact.x;
1496
+ const x = state.lensCenter ?? region.frame.width / 2;
1497
+ if (input.phase === 'rest' || this.reducedMotion) {
1498
+ press.reset();
1499
+ motion.reset(0);
1500
+ }
1501
+ else if (input.phase === 'pressed') {
1502
+ press.down(input.epoch);
1503
+ motion.down(x, 0, input.epoch);
1504
+ }
1505
+ else if (input.phase === 'dragging')
1506
+ motion.move(x);
1507
+ else if (input.phase === 'releasing') {
1508
+ press.up(input.epoch);
1509
+ motion.up(input.epoch);
1510
+ }
1511
+ this.presentMotion(region.id, state);
1512
+ return;
1513
+ }
1514
+ // Each kind of interactive glass presses with its own row of the contact table; a region
1515
+ // whose kind changed (a toolbar item swapped in place) starts a contact of the new kind.
1516
+ const contactKind = glassContactKind(region.material);
1517
+ if (!state.contact || state.contactKind !== contactKind) {
1518
+ state.contact = new InteractiveContact(GLASS_CONTACT_PHYSICS[contactKind]);
1519
+ state.contactKind = contactKind;
1520
+ }
1521
+ // A press without a finger position (chrome buttons driven by their press state) lights
1522
+ // from the shape's centre.
1523
+ state.contact.input(input.phase === 'pressed' && !input.contact
1524
+ ? { ...input, contact: { x: region.frame.width / 2, y: region.frame.height / 2 } }
1525
+ : input);
1526
+ if (input.phase === 'rest') {
1527
+ motion.reset(0);
1528
+ press.reset();
1529
+ state.downAt = undefined;
1530
+ state.upAt = undefined;
1531
+ this.presentMotion(region.id, state);
1532
+ }
1533
+ else if (this.reducedMotion) {
1534
+ motion.reset(0);
1535
+ press.reset();
1536
+ if (input.phase === 'pressed') {
1537
+ state.downAt = input.epoch;
1538
+ state.upAt = undefined;
1539
+ }
1540
+ else if (input.phase !== 'dragging')
1541
+ state.upAt = input.epoch;
1542
+ this.presentMotion(region.id, state);
1543
+ }
1544
+ else if (input.phase === 'pressed') {
1545
+ motion.down(region.frame.width / 2, 0, input.epoch);
1546
+ press.down(input.epoch);
1547
+ state.downAt = input.epoch;
1548
+ state.upAt = undefined;
1549
+ }
1550
+ else if (input.phase === 'dragging')
1551
+ motion.move(input.contact?.x ?? region.frame.width / 2);
1552
+ else {
1553
+ motion.up(input.epoch);
1554
+ press.up(input.epoch);
1555
+ state.upAt = input.epoch;
1556
+ }
1557
+ return;
1558
+ }
1559
+ case 'morph':
1560
+ throw Error('Unsupported glass morph: worker morph material pending');
1561
+ case 'appearance':
1562
+ if (this.appearance === request.value && this.reducedMotion === request.reducedMotion)
1563
+ return;
1564
+ this.appearance = request.value;
1565
+ this.reducedMotion = request.reducedMotion;
1566
+ if (this.reducedMotion)
1567
+ for (const [id, state] of this.motions) {
1568
+ state.motion.reset(0);
1569
+ state.press.reset();
1570
+ this.presentMotion(id, state);
1571
+ }
1572
+ await this.install(true);
1573
+ return;
1574
+ case 'visibility':
1575
+ if (request.visible) {
1576
+ await this.prepareResume();
1577
+ this.present();
1578
+ }
1579
+ else {
1580
+ this.visible = false;
1581
+ // The last frame's time is not a time to pose anything at after a resume.
1582
+ this.sampledAt = undefined;
1583
+ this.touchLights.clear();
1584
+ for (const p of this.presenters.values()) {
1585
+ if (p.raster?.spec?.touchLight)
1586
+ p.raster.updateSpec({ ...p.raster.spec, touchLight: undefined });
1587
+ p.raster?.setVisible(false);
1588
+ if (p.descriptor.role === 'lift' && p.raster?.spec)
1589
+ p.raster.setLift({
1590
+ amount: 0,
1591
+ source: 'transmissive',
1592
+ optics: new TabMotion().optics(),
1593
+ });
1594
+ }
1595
+ for (const state of this.motions.values()) {
1596
+ state.motion.reset(0);
1597
+ state.press.reset();
1598
+ state.downAt = undefined;
1599
+ state.upAt = undefined;
1600
+ state.contact = undefined;
1601
+ }
1602
+ }
1603
+ return;
1604
+ case 'purge':
1605
+ return this.request({ type: 'visibility', visible: false });
1606
+ case 'restore':
1607
+ return this.request({ type: 'visibility', visible: true });
1608
+ case 'diagnostics':
1609
+ return this.diagnostics();
1610
+ case 'dispose':
1611
+ for (const [id, p] of this.presenters) {
1612
+ p.raster?.dispose();
1613
+ this.owner.detach(id);
1614
+ }
1615
+ this.presenters.clear();
1616
+ this.touchLights.clear();
1617
+ for (const source of this.sources.values())
1618
+ source.lease.release();
1619
+ this.sources.clear();
1620
+ this.emptyForeground?.release();
1621
+ this.emptyForeground = undefined;
1622
+ return;
1623
+ }
1624
+ }
1625
+ /** New source images (uploads) since the last install: only those need a completion fence. */
1626
+ presentationReceipt() {
1627
+ if (this.topologyPending)
1628
+ return { superseded: true, presented: [] };
1629
+ return {
1630
+ navigation: this.navigation?.key,
1631
+ presented: (this.submissionAllowed() ? [...this.presenters.values()] : [])
1632
+ .filter(p => p.descriptor.role === 'material' && p.raster?.spec && !p.covered && this.visible)
1633
+ .flatMap(p => p.descriptor.regionIds.filter(id => {
1634
+ const region = this.scene.regions.find(region => region.id === id);
1635
+ const sheetEpoch = region?.presentationContentEpoch;
1636
+ const accessoryEpoch = region?.accessoryViewportTrack?.epoch;
1637
+ return ((sheetEpoch === undefined || p.presentationContentEpoch === sheetEpoch) &&
1638
+ (accessoryEpoch === undefined || p.accessoryContentEpoch === accessoryEpoch));
1639
+ })),
1640
+ };
1641
+ }
1642
+ sourcesChanged = false;
1643
+ async install(force = false) {
1644
+ if (!this.appearance)
1645
+ throw Error('Glass material requires a presented appearance');
1646
+ if (this.deferred || this.sourcePending)
1647
+ return;
1648
+ let fence = force || this.sourcesChanged;
1649
+ this.sourcesChanged = false;
1650
+ const installed = [];
1651
+ for (const p of this.presenters.values()) {
1652
+ const members = this.scene.regions.filter(r => p.descriptor.regionIds.includes(r.id));
1653
+ const region = this.scene.regions.find(r => r.id === p.descriptor.regionIds[0]);
1654
+ if (!region) {
1655
+ if (!p.covered)
1656
+ p.raster?.clear();
1657
+ p.raster?.setCovered(true);
1658
+ p.covered = true;
1659
+ continue;
1660
+ }
1661
+ if (region.layer.id !== p.descriptor.layerId)
1662
+ throw Error('Glass presenter/region layer mismatch');
1663
+ const resumed = !!p.suspended && !region.suspended;
1664
+ p.suspended = !!region.suspended;
1665
+ // The root transmitted capture is in viewport/content coordinates. A layer
1666
+ // may instead provide its own capture; no frosted source is substituted.
1667
+ const source = [...this.sources.values()].find(s => s.descriptor.role === 'transmitted-backdrop' &&
1668
+ s.descriptor.layerId === region.layer.id) ??
1669
+ [...this.sources.values()].find(s => s.descriptor.role === 'transmitted-backdrop' && s.descriptor.layerId === 'chrome');
1670
+ if (!source)
1671
+ continue;
1672
+ const frame = glassViewportFrame(region, this.scene.scrolls);
1673
+ const inset = contextSampleInset(region.material.treatment);
1674
+ const reach = region.accessoryReach;
1675
+ const held = !!region.accessoryTrack?.held;
1676
+ const bounds = region.emerge
1677
+ ? glassPresenterBounds(frame, inset, region.emerge)
1678
+ : glassPresenterBounds(reach ? frameUnion(frame, reach) : frame, inset);
1679
+ if (!region.container)
1680
+ p.descriptor = {
1681
+ ...p.descriptor,
1682
+ origin: { x: bounds.x, y: bounds.y },
1683
+ width: bounds.width,
1684
+ height: bounds.height,
1685
+ };
1686
+ const viewportTrack = region.presentationViewportTrack ?? region.accessoryViewportTrack ?? region.accessoryTrack;
1687
+ const accessoryTranslation = viewportTrack && !held ? accessoryOffset(viewportTrack, this.trackClock()) : undefined;
1688
+ const viewport = held
1689
+ ? { x: p.descriptor.origin.x, y: p.descriptor.origin.y, scaleX: 1, scaleY: 1 }
1690
+ : accessoryTranslation
1691
+ ? {
1692
+ x: p.descriptor.origin.x + accessoryTranslation.x,
1693
+ y: p.descriptor.origin.y + accessoryTranslation.y,
1694
+ scaleX: 1,
1695
+ scaleY: 1,
1696
+ }
1697
+ : p.viewport;
1698
+ // installRetained can draw immediately. Its first sample must use the same
1699
+ // track-owned viewport as later frames, before the ink handoff is acknowledged.
1700
+ if (!p.suspended && viewport)
1701
+ p.raster?.setViewport(viewport);
1702
+ const emerging = this.emerges.get(region.id);
1703
+ let spec = region.container
1704
+ ? fieldRegionSpec(members, p.descriptor, this.scene)
1705
+ : emerging
1706
+ ? emergeRegionSpec(regionSpec(region, p.descriptor, this.scene), region, p.descriptor, emerging.progress, emerging.corner, emerging.source, emerging.field ?? {
1707
+ direction: emerging.direction,
1708
+ ms: 0,
1709
+ pressHighlight: 0,
1710
+ settled: false,
1711
+ recipeMix: emerging.materialFrom,
1712
+ }, this.appearance)
1713
+ : regionSpec(region, p.descriptor, this.scene);
1714
+ const memberIds = region.container ? members.map(member => member.id) : undefined;
1715
+ if (memberIds && p.raster?.spec?.shape.members) {
1716
+ const previous = p.raster.spec;
1717
+ const running = this.fields.get(p.descriptor.id);
1718
+ const previousIds = running?.memberIds ?? p.fieldMemberIds ?? memberIds;
1719
+ const membershipChanged = previousIds.length !== memberIds.length ||
1720
+ memberIds.some((id, index) => id !== previousIds[index]);
1721
+ if (membershipChanged ||
1722
+ JSON.stringify((running?.to ?? previous).shape.members) !==
1723
+ JSON.stringify(spec.shape.members)) {
1724
+ const start = performance.timeOrigin + performance.now();
1725
+ const previousIndexes = memberIds.map(id => previousIds.indexOf(id));
1726
+ if (region.container?.continuous) {
1727
+ if (running) {
1728
+ const followed = spec.shape.members.map((target, index) => followFieldTarget(running.from.shape.members[previousIndexes[index]] ?? target, running.to.shape.members[previousIndexes[index]] ?? target, target));
1729
+ running.from = {
1730
+ ...spec,
1731
+ shape: { ...spec.shape, first: followed[0], members: followed },
1732
+ };
1733
+ running.to = spec;
1734
+ running.velocity = previousIndexes.map(index => running.velocity[index] ?? ZERO_FIELD_VELOCITY);
1735
+ running.memberIds = memberIds;
1736
+ const sampled = spec.shape.members.map((target, index) => sampleFieldMember(followed[index], target, running.velocity[index] ?? ZERO_FIELD_VELOCITY, start - running.start, this.reducedMotion).value);
1737
+ spec = { ...spec, shape: { ...spec.shape, first: sampled[0], members: sampled } };
1738
+ }
1739
+ }
1740
+ else {
1741
+ const samples = spec.shape.members.map((target, index) => running
1742
+ ? sampleFieldMember(running.from.shape.members[previousIndexes[index]] ?? target, running.to.shape.members[previousIndexes[index]] ?? target, running.velocity[previousIndexes[index]] ?? ZERO_FIELD_VELOCITY, start - running.start, this.reducedMotion)
1743
+ : {
1744
+ value: previous.shape.members[previousIndexes[index]] ?? target,
1745
+ velocity: ZERO_FIELD_VELOCITY,
1746
+ });
1747
+ const fromMembers = samples.map(sample => sample.value);
1748
+ const fromSpec = {
1749
+ ...spec,
1750
+ shape: { ...spec.shape, first: fromMembers[0], members: fromMembers },
1751
+ };
1752
+ this.fields.set(p.descriptor.id, {
1753
+ start,
1754
+ from: fromSpec,
1755
+ to: spec,
1756
+ velocity: samples.map(sample => sample.velocity),
1757
+ memberIds,
1758
+ });
1759
+ glassTiming('field-morph-start', start, p.descriptor.id);
1760
+ members.forEach((member, index) => {
1761
+ const from = fromMembers[index];
1762
+ const to = spec.shape.members?.[index];
1763
+ if (!from || !to)
1764
+ return;
1765
+ const velocity = samples[index].velocity;
1766
+ this.notify({
1767
+ type: 'field-motion',
1768
+ regionId: member.id,
1769
+ start,
1770
+ duration: this.reducedMotion ? 0 : FIELD_MOTION_DURATION,
1771
+ offsetX: from.centerX - to.centerX,
1772
+ offsetY: from.centerY - to.centerY,
1773
+ scaleX: from.halfWidth / to.halfWidth,
1774
+ scaleY: from.halfHeight / to.halfHeight,
1775
+ velocityX: velocity.centerX,
1776
+ velocityY: velocity.centerY,
1777
+ velocityScaleX: velocity.halfWidth / to.halfWidth,
1778
+ velocityScaleY: velocity.halfHeight / to.halfHeight,
1779
+ });
1780
+ });
1781
+ spec = fromSpec;
1782
+ }
1783
+ }
1784
+ else if (running)
1785
+ spec = { ...spec, shape: previous.shape };
1786
+ }
1787
+ if (memberIds)
1788
+ p.fieldMemberIds = memberIds;
1789
+ const sourceScroll = source.descriptor.layerId === 'chrome'
1790
+ ? this.scene.scrolls.find(s => s.id === 'webgpu-source-root')
1791
+ : undefined;
1792
+ const baseSourceOrigin = {
1793
+ x: p.descriptor.origin.x - source.descriptor.origin.x + (sourceScroll?.offsetX ?? 0),
1794
+ y: p.descriptor.origin.y - source.descriptor.origin.y + (sourceScroll?.offsetY ?? 0),
1795
+ };
1796
+ p.accessorySourceOrigin = viewportTrack && !held ? baseSourceOrigin : undefined;
1797
+ const sourceOrigin = region.presentationViewportTrack && accessoryTranslation
1798
+ ? {
1799
+ x: baseSourceOrigin.x + accessoryTranslation.x,
1800
+ y: baseSourceOrigin.y + accessoryTranslation.y,
1801
+ }
1802
+ : baseSourceOrigin;
1803
+ const foreground = this.sources.get(`foreground:${region.id}`);
1804
+ if (region.accessoryTrack && foreground)
1805
+ spec = accessoryPose(spec, region.accessoryTrack, this.trackClock(), foreground.descriptor);
1806
+ if (region.shapeTrack)
1807
+ spec = this.shapeAt(region, spec, region.shapeTrack, this.trackClock());
1808
+ if (region.selection)
1809
+ spec = selectionInk(spec, foreground?.descriptor);
1810
+ const thumb = this.thumbs.get(region.id);
1811
+ if (region.selection && thumb)
1812
+ spec = this.posedSelection(spec, region, p.descriptor, thumb, performance.timeOrigin + performance.now());
1813
+ spec = this.illuminate(spec, region, p.descriptor, performance.timeOrigin + performance.now());
1814
+ const materialKey = JSON.stringify([spec, foreground?.descriptor, this.appearance]);
1815
+ if (p.suspended) {
1816
+ // Held: backdrop changes do not redraw it. Its canvas keeps its pixels until the region's
1817
+ // own inputs change (or its canvas lost them): then it is repainted below exactly as an
1818
+ // unheld region would be, never left showing an old appearance or size.
1819
+ this.moved.delete(p);
1820
+ // Never drawn (it mounted while its tab was hidden, or its only draw failed): the planes
1821
+ // installed now are another tab's. It stays empty and parked; its own tab's commit is its
1822
+ // first sample.
1823
+ if (!p.materialKey) {
1824
+ p.parked = true;
1825
+ continue;
1826
+ }
1827
+ if (p.materialKey === materialKey && !p.repaint)
1828
+ continue;
1829
+ }
1830
+ // The composed screen backdrop is sampled at the presenter's current viewport position.
1831
+ p.raster?.setViewportOrigin(p.descriptor.origin);
1832
+ if (p.descriptor.role === 'lift' &&
1833
+ !foreground &&
1834
+ region.material.press !== 'button' &&
1835
+ region.material.press !== 'bar' &&
1836
+ !region.material.control)
1837
+ continue;
1838
+ // Over the settled chrome backdrop a running navigation's atlas is the source (viewport space).
1839
+ // A held presenter belongs to a tab that is not on screen: the navigation is not under it, and
1840
+ // its repaint must be presented now (the atlas path defers that), before it is parked again.
1841
+ // The DOM removes its zoom registration at settlement before the fresh source
1842
+ // batch arrives. Keep this presenter's accepted route until that batch retires
1843
+ // the atlas; dropping it here briefly samples the previous page's plane.
1844
+ const zoomRoute = region.zoomRoute ?? (this.navigation ? p.zoomRoute : undefined);
1845
+ const navigation = (source.descriptor.layerId === 'chrome' || zoomRoute !== undefined) && !p.suspended
1846
+ ? this.navigation
1847
+ : undefined;
1848
+ const key = JSON.stringify([
1849
+ spec,
1850
+ sourceOrigin,
1851
+ source.descriptor,
1852
+ foreground?.descriptor,
1853
+ this.appearance,
1854
+ navigation?.key,
1855
+ zoomRoute,
1856
+ ]), storageKey = JSON.stringify([
1857
+ spec,
1858
+ source.descriptor,
1859
+ foreground?.descriptor,
1860
+ this.appearance,
1861
+ navigation?.key,
1862
+ zoomRoute,
1863
+ ]);
1864
+ // Releasing a prewarmed pose changes no texture key. Start and submit its
1865
+ // timeline before a scene receipt can release the DOM rows.
1866
+ if (emerging && !emerging.held && !emerging.shown && p.raster?.spec && !navigation)
1867
+ this.presentEmerge(region.id, performance.timeOrigin + performance.now());
1868
+ // A retained scene key is not a submission for a new motion epoch. Install material
1869
+ // once for each sheet entrance or accessory run before acknowledging that run. The
1870
+ // two epochs stay independent when an accessory is nested inside a presentation.
1871
+ const presentationDraw = (region.presentationContentEpoch !== undefined &&
1872
+ p.presentationContentEpoch !== region.presentationContentEpoch) ||
1873
+ (region.accessoryViewportTrack !== undefined &&
1874
+ p.accessoryContentEpoch !== region.accessoryViewportTrack.epoch);
1875
+ if (presentationDraw)
1876
+ fence = true;
1877
+ if (!force &&
1878
+ !presentationDraw &&
1879
+ p.key !== key &&
1880
+ p.storageKey === storageKey &&
1881
+ p.raster?.spec &&
1882
+ !p.covered) {
1883
+ p.raster.setSourceOrigin(navigation ? { x: p.descriptor.origin.x, y: p.descriptor.origin.y } : sourceOrigin);
1884
+ p.key = key;
1885
+ if (p.raster.backdropStale() || !Backdrop.for(this.owner).installed)
1886
+ this.moved.add(p);
1887
+ continue;
1888
+ }
1889
+ if (!force && !presentationDraw && p.key === key) {
1890
+ p.raster?.setCovered(false);
1891
+ if (p.covered)
1892
+ p.raster?.draw(0);
1893
+ // The backdrop may have moved while the region was held (nothing redrew it then).
1894
+ else if (resumed && p.raster?.spec && p.raster.backdropStale())
1895
+ this.moved.add(p);
1896
+ p.covered = false;
1897
+ continue;
1898
+ }
1899
+ if (!p.raster) {
1900
+ p.raster = new WebGPURaster();
1901
+ if (viewport)
1902
+ p.raster.setViewport(viewport);
1903
+ p.raster.setSubmissionGate(this.submissionAllowed);
1904
+ await p.raster.init(p.canvas, this.owner, region.layer, p.descriptor);
1905
+ p.raster.setVisible(this.visible);
1906
+ fence = true;
1907
+ }
1908
+ if (!foreground && !this.emptyForeground)
1909
+ this.emptyForeground = FrameGraph.for(this.owner).image('region:empty', await createImageBitmap(new ImageData(1, 1)));
1910
+ const glyphs = foreground?.lease ?? this.emptyForeground;
1911
+ p.raster.setCovered(false);
1912
+ p.raster.installRetained({
1913
+ viewportOrigin: p.descriptor.origin,
1914
+ spec,
1915
+ liftOverlay: p.descriptor.role === 'lift',
1916
+ lift: p.descriptor.role === 'lift'
1917
+ ? { amount: 0, source: 'transmissive', optics: new TabMotion().optics() }
1918
+ : undefined,
1919
+ navigationAtlas: navigation ? navigation.routes : 1,
1920
+ ...(navigation
1921
+ ? {
1922
+ contentLayer: navigation.contentLayer,
1923
+ navigationCoverage: {
1924
+ width: navigation.width,
1925
+ height: navigation.height,
1926
+ rows: navigation.rows ?? [{ top: 0, bottom: navigation.height }],
1927
+ },
1928
+ }
1929
+ : {}),
1930
+ appearance: this.appearance,
1931
+ sourceWidth: navigation ? navigation.width : source.descriptor.width,
1932
+ sourceOrigin: navigation
1933
+ ? { x: p.descriptor.origin.x, y: p.descriptor.origin.y }
1934
+ : sourceOrigin,
1935
+ sourceKey: navigation
1936
+ ? navigation.key
1937
+ : source.descriptor.id === 'root-backdrop'
1938
+ ? `production:${source.descriptor.revision}`
1939
+ : `region:${source.descriptor.id}:${source.descriptor.revision}`,
1940
+ glyphKey: foreground
1941
+ ? `${foreground.descriptor.id}:${foreground.descriptor.revision}`
1942
+ : 'region:empty',
1943
+ width: p.descriptor.width,
1944
+ height: p.descriptor.height,
1945
+ resolution: p.descriptor.resolution,
1946
+ }, navigation ? navigation.lease : source.lease, glyphs, !navigation);
1947
+ p.navigation = navigation?.key;
1948
+ p.zoomRoute = zoomRoute;
1949
+ // A running track draws every presenter in its next worker frame: no extra draw here.
1950
+ if (navigation?.pose)
1951
+ p.raster.setNavigation(this.presenterNavigationPose(navigation.pose, p.zoomRoute));
1952
+ installed.push(p);
1953
+ p.key = key;
1954
+ p.storageKey = storageKey;
1955
+ p.materialKey = materialKey;
1956
+ p.repaint = false;
1957
+ this.moved.delete(p);
1958
+ p.covered = false;
1959
+ p.sourceId = source.descriptor.id;
1960
+ const state = this.motions.get(region.id);
1961
+ if (state)
1962
+ this.presentMotion(region.id, state, performance.timeOrigin + performance.now(), !navigation);
1963
+ if (this.emerges.has(region.id))
1964
+ this.presentEmerge(region.id, performance.timeOrigin + performance.now(), !navigation);
1965
+ if (navigation && !navigation.deferPresent && this.visible)
1966
+ p.raster.draw(0);
1967
+ // A parked presenter repainted while still held goes back to holding pixels only. A held
1968
+ // presenter whose draw could not be submitted (the renderer presents an appearance change
1969
+ // in one step, later) still shows the old appearance: it keeps its setup until `present`
1970
+ // has drawn it, and is parked then.
1971
+ if (region.accessoryTrack &&
1972
+ p.accessoryEpoch !== region.accessoryTrack.epoch &&
1973
+ foreground &&
1974
+ this.visible &&
1975
+ !this.deferred &&
1976
+ this.submissionAllowed()) {
1977
+ // A held-still canvas already samples where it is (see the install viewport above).
1978
+ const offset = region.accessoryTrack.held
1979
+ ? { x: 0, y: 0 }
1980
+ : accessoryOffset(region.accessoryTrack, this.trackClock());
1981
+ // The DOM viewport observer is paused for this sampling track. Update the
1982
+ // sampling viewport itself: an older liveViewport overrides viewportOrigin.
1983
+ p.raster.setViewport({
1984
+ x: p.descriptor.origin.x + offset.x,
1985
+ y: p.descriptor.origin.y + offset.y,
1986
+ scaleX: 1,
1987
+ scaleY: 1,
1988
+ });
1989
+ p.raster.setSourceOrigin({ x: sourceOrigin.x + offset.x, y: sourceOrigin.y + offset.y });
1990
+ p.raster.draw(0);
1991
+ p.accessoryEpoch = region.accessoryTrack.epoch;
1992
+ this.notify({
1993
+ type: 'accessory-ink',
1994
+ regionId: region.id,
1995
+ epoch: region.accessoryTrack.epoch,
1996
+ });
1997
+ }
1998
+ const submitted = this.submissionAllowed();
1999
+ if (submitted && this.visible && !navigation?.deferPresent) {
2000
+ p.presentationContentEpoch = region.presentationContentEpoch;
2001
+ p.accessoryContentEpoch = region.accessoryViewportTrack?.epoch;
2002
+ }
2003
+ const holdsPixelsOnly = !!p.suspended && (!!p.parked || !!p.parkAfterPresent);
2004
+ if (holdsPixelsOnly && submitted)
2005
+ this.park(p);
2006
+ else {
2007
+ p.parkAfterPresent = !!p.suspended && (holdsPixelsOnly || !submitted);
2008
+ p.parked = false;
2009
+ }
2010
+ }
2011
+ // Every presenter uses this one ordered device queue. One completion fence covers a
2012
+ // transaction that uploaded sources or created presenters; a geometry-only update (a
2013
+ // presentation moving or resizing) is not fenced, so it never blocks the worker's queue
2014
+ // behind GPU completion. Its GPU errors still surface through the draw scopes.
2015
+ if (!fence)
2016
+ return;
2017
+ try {
2018
+ await installed.at(-1)?.raster?.settled();
2019
+ }
2020
+ catch (error) {
2021
+ // The draws of this install are not known to have completed: none of it counts as drawn.
2022
+ for (const p of installed) {
2023
+ p.key = undefined;
2024
+ p.storageKey = undefined;
2025
+ p.materialKey = undefined;
2026
+ p.repaint = true;
2027
+ p.presentationContentEpoch = undefined;
2028
+ p.accessoryContentEpoch = undefined;
2029
+ }
2030
+ throw error;
2031
+ }
2032
+ }
2033
+ async prepareResume() {
2034
+ // Retained viewport and accessory tracks are posed where they are now, before anything is
2035
+ // drawn: the first resumed frame showed the pose sampled before the hide (an accessory
2036
+ // halfway between its rows). Not visible yet, so this only poses.
2037
+ this.sampledAt = undefined;
2038
+ this.presentTrackedViewport(performance.timeOrigin + performance.now());
2039
+ this.visible = true;
2040
+ for (const p of this.presenters.values())
2041
+ p.raster?.setVisible(true, true);
2042
+ // After an app resume or a device restore (the page's fresh appearance reply arrives here for
2043
+ // both): a parked presenter of a region that is on screen has nothing to draw its pixels from,
2044
+ // so it is installed again. A hidden tab's parked presenter stays parked: the only planes
2045
+ // installed are another tab's, and its own tab's commit is its next draw.
2046
+ if (this.repaintVisibleParked())
2047
+ await this.install();
2048
+ }
2049
+ present() {
2050
+ if (!this.visible || this.sourcePending)
2051
+ return;
2052
+ // A parked presenter holds pixels only: it has nothing to draw until it is installed again.
2053
+ for (const p of this.presenters.values()) {
2054
+ if (p.parked)
2055
+ continue;
2056
+ p.raster?.draw(0);
2057
+ // Held, and repainted while nothing could be submitted: drawn now, it holds pixels again.
2058
+ if (p.parkAfterPresent && this.submissionAllowed())
2059
+ this.park(p);
2060
+ }
2061
+ }
2062
+ navigationRasters() {
2063
+ return [...this.presenters.values()]
2064
+ .filter(p => p.navigation === this.navigation?.key && !!p.navigation && p.raster?.spec && !p.covered)
2065
+ .map(p => p.raster);
2066
+ }
2067
+ async snapshot(id) {
2068
+ const raster = this.presenters.get(id)?.raster;
2069
+ if (!raster)
2070
+ throw Error('Unknown glass presenter snapshot ' + id);
2071
+ return raster.snapshot();
2072
+ }
2073
+ diagnostics() {
2074
+ return {
2075
+ navigation: this.navigation
2076
+ ? { key: this.navigation.key, pose: this.navigation.pose }
2077
+ : undefined,
2078
+ drawableCosts: drawableCosts(),
2079
+ samplePixels: this.samplePixels,
2080
+ presenterCosts: [...this.presenters.values()].map(p => ({
2081
+ id: p.descriptor.id,
2082
+ regions: p.descriptor.regionIds,
2083
+ role: p.descriptor.role,
2084
+ zoomRoute: p.zoomRoute,
2085
+ width: p.canvas.width,
2086
+ height: p.canvas.height,
2087
+ stats: p.raster ? { ...p.raster.stats } : null,
2088
+ presentation: p.raster?.presentation() ?? null,
2089
+ })),
2090
+ presenterOrigins: [...this.presenters.values()].map(p => [
2091
+ p.descriptor.regionIds[0],
2092
+ p.descriptor.role,
2093
+ Math.round(p.descriptor.origin.x),
2094
+ Math.round(p.descriptor.origin.y),
2095
+ Math.round(p.descriptor.width),
2096
+ (p.raster?.composedBackdropKey ?? '').slice(0, 160),
2097
+ p.key ? JSON.parse(p.key)[2]?.revision : undefined,
2098
+ p.covered,
2099
+ ]),
2100
+ // What each presenter last drew: where its glass frame sits in the canvas, how wide the
2101
+ // capsule is and how many ink layers the renderer drew over it (0: the page owns the ink).
2102
+ regionPoses: [...this.presenters.values()].map(p => {
2103
+ const spec = p.raster?.spec;
2104
+ const id = p.descriptor.regionIds[0];
2105
+ const region = this.scene.regions.find(candidate => candidate.id === id);
2106
+ return {
2107
+ region: id,
2108
+ accessoryTrack: region?.accessoryTrack
2109
+ ? { epoch: region.accessoryTrack.epoch, held: !!region.accessoryTrack.held }
2110
+ : null,
2111
+ foreground: this.sources.has(`foreground:${id}`),
2112
+ interaction: this.motions.has(id),
2113
+ role: p.descriptor.role,
2114
+ canvas: { x: p.descriptor.origin.x, y: p.descriptor.origin.y, width: p.descriptor.width },
2115
+ frame: spec ? { x: spec.frameX, y: spec.frameY } : null,
2116
+ capsuleWidth: spec ? spec.shape.first.halfWidth * 2 : null,
2117
+ inkLayers: spec?.ink?.layers.length ?? 0,
2118
+ covered: p.covered,
2119
+ parked: !!p.parked,
2120
+ };
2121
+ }),
2122
+ interactions: [...this.motions].map(([id, s]) => ({
2123
+ id,
2124
+ epoch: s.epoch,
2125
+ active: s.motion.active,
2126
+ pending: s.motion.needsFrame || s.press.needsFrame,
2127
+ amount: s.motion.lensMix,
2128
+ press: s.press.amount,
2129
+ model: 'retained-material',
2130
+ })),
2131
+ backend: 'webgpu',
2132
+ canvasContexts: this.owner.stats?.canvasContexts ?? 0,
2133
+ devices: this.owner.liveDevice ? 1 : 0,
2134
+ draws: [...this.presenters.values()].reduce((n, p) => n + (p.raster?.stats.draws ?? 0), 0),
2135
+ submissions: [...this.presenters.values()].reduce((n, p) => n + (p.raster?.stats.submissions ?? 0), 0),
2136
+ presenters: this.presenters.size,
2137
+ regions: this.scene.regions.length,
2138
+ sources: this.sources.size,
2139
+ retainedSourceBytes: [...this.sources.values()].reduce((n, s) => n + s.bitmap.width * s.bitmap.height * 4, 0),
2140
+ visible: this.visible,
2141
+ scene: this.scene,
2142
+ };
2143
+ }
2144
+ }