@moldable-ai/ui 0.2.19 → 0.2.21

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 (464) hide show
  1. package/dist/catalog/catalog-coverage.d.ts +15 -0
  2. package/dist/catalog/catalog-coverage.d.ts.map +1 -0
  3. package/dist/catalog/catalog-coverage.js +44 -0
  4. package/dist/catalog/catalog-manifest.d.ts +6 -0
  5. package/dist/catalog/catalog-manifest.d.ts.map +1 -0
  6. package/dist/catalog/catalog-manifest.js +117 -0
  7. package/dist/catalog/catalog-types.d.ts +64 -0
  8. package/dist/catalog/catalog-types.d.ts.map +1 -0
  9. package/dist/catalog/catalog-types.js +20 -0
  10. package/dist/catalog/component-catalog.d.ts +14 -0
  11. package/dist/catalog/component-catalog.d.ts.map +1 -0
  12. package/dist/catalog/component-catalog.js +49 -0
  13. package/dist/catalog/core-catalog-exclusions.d.ts +8 -0
  14. package/dist/catalog/core-catalog-exclusions.d.ts.map +1 -0
  15. package/dist/catalog/core-catalog-exclusions.js +151 -0
  16. package/dist/catalog/core-catalog.d.ts +2 -0
  17. package/dist/catalog/core-catalog.d.ts.map +1 -0
  18. package/dist/catalog/core-catalog.js +19 -0
  19. package/dist/catalog/core-collection-stories.d.ts +3 -0
  20. package/dist/catalog/core-collection-stories.d.ts.map +1 -0
  21. package/dist/catalog/core-collection-stories.js +42 -0
  22. package/dist/catalog/core-control-stories.d.ts +3 -0
  23. package/dist/catalog/core-control-stories.d.ts.map +1 -0
  24. package/dist/catalog/core-control-stories.js +94 -0
  25. package/dist/catalog/core-feedback-stories.d.ts +3 -0
  26. package/dist/catalog/core-feedback-stories.d.ts.map +1 -0
  27. package/dist/catalog/core-feedback-stories.js +50 -0
  28. package/dist/catalog/core-foundation-stories.d.ts +3 -0
  29. package/dist/catalog/core-foundation-stories.d.ts.map +1 -0
  30. package/dist/catalog/core-foundation-stories.js +53 -0
  31. package/dist/catalog/core-navigation-stories.d.ts +3 -0
  32. package/dist/catalog/core-navigation-stories.d.ts.map +1 -0
  33. package/dist/catalog/core-navigation-stories.js +25 -0
  34. package/dist/catalog/core-overlay-stories.d.ts +3 -0
  35. package/dist/catalog/core-overlay-stories.d.ts.map +1 -0
  36. package/dist/catalog/core-overlay-stories.js +20 -0
  37. package/dist/catalog/index.d.ts +7 -0
  38. package/dist/catalog/index.d.ts.map +1 -0
  39. package/dist/catalog/index.js +6 -0
  40. package/dist/components/app-error-boundary.d.ts +1 -0
  41. package/dist/components/app-error-boundary.d.ts.map +1 -1
  42. package/dist/components/app-error-boundary.js +13 -0
  43. package/dist/components/chat/chat-image-lightbox.d.ts +9 -0
  44. package/dist/components/chat/chat-image-lightbox.d.ts.map +1 -0
  45. package/dist/components/chat/chat-image-lightbox.js +9 -0
  46. package/dist/components/chat/chat-message.d.ts +19 -1
  47. package/dist/components/chat/chat-message.d.ts.map +1 -1
  48. package/dist/components/chat/chat-message.js +66 -16
  49. package/dist/components/chat/chat-messages.d.ts +5 -2
  50. package/dist/components/chat/chat-messages.d.ts.map +1 -1
  51. package/dist/components/chat/chat-messages.js +61 -6
  52. package/dist/components/chat/chat-panel.d.ts +49 -6
  53. package/dist/components/chat/chat-panel.d.ts.map +1 -1
  54. package/dist/components/chat/chat-panel.js +196 -163
  55. package/dist/components/chat/conversation-history.d.ts +39 -5
  56. package/dist/components/chat/conversation-history.d.ts.map +1 -1
  57. package/dist/components/chat/conversation-history.js +192 -26
  58. package/dist/components/chat/index.d.ts +2 -2
  59. package/dist/components/chat/index.d.ts.map +1 -1
  60. package/dist/components/chat/index.js +1 -1
  61. package/dist/components/chat/tool-handlers.d.ts.map +1 -1
  62. package/dist/components/chat/tool-handlers.js +40 -2
  63. package/dist/components/chat/vertical-scroll-fade.d.ts +6 -0
  64. package/dist/components/chat/vertical-scroll-fade.d.ts.map +1 -0
  65. package/dist/components/chat/vertical-scroll-fade.js +12 -0
  66. package/dist/components/native-capabilities/bluetooth-panel-helpers.d.ts +9 -0
  67. package/dist/components/native-capabilities/bluetooth-panel-helpers.d.ts.map +1 -0
  68. package/dist/components/native-capabilities/bluetooth-panel-helpers.js +37 -0
  69. package/dist/components/native-capabilities/bluetooth-panel.d.ts +56 -0
  70. package/dist/components/native-capabilities/bluetooth-panel.d.ts.map +1 -0
  71. package/dist/components/native-capabilities/bluetooth-panel.js +470 -0
  72. package/dist/components/native-capabilities/camera-preview.d.ts +39 -0
  73. package/dist/components/native-capabilities/camera-preview.d.ts.map +1 -0
  74. package/dist/components/native-capabilities/camera-preview.js +228 -0
  75. package/dist/components/native-capabilities/capability-badge.d.ts +23 -0
  76. package/dist/components/native-capabilities/capability-badge.d.ts.map +1 -0
  77. package/dist/components/native-capabilities/capability-badge.js +39 -0
  78. package/dist/components/native-capabilities/capability-matrix.d.ts +14 -0
  79. package/dist/components/native-capabilities/capability-matrix.d.ts.map +1 -0
  80. package/dist/components/native-capabilities/capability-matrix.js +97 -0
  81. package/dist/components/native-capabilities/clipboard-button.d.ts +26 -0
  82. package/dist/components/native-capabilities/clipboard-button.d.ts.map +1 -0
  83. package/dist/components/native-capabilities/clipboard-button.js +99 -0
  84. package/dist/components/native-capabilities/device-io-controls.d.ts +4 -0
  85. package/dist/components/native-capabilities/device-io-controls.d.ts.map +1 -0
  86. package/dist/components/native-capabilities/device-io-controls.js +28 -0
  87. package/dist/components/native-capabilities/device-list.d.ts +20 -0
  88. package/dist/components/native-capabilities/device-list.d.ts.map +1 -0
  89. package/dist/components/native-capabilities/device-list.js +14 -0
  90. package/dist/components/native-capabilities/display-map.d.ts +23 -0
  91. package/dist/components/native-capabilities/display-map.d.ts.map +1 -0
  92. package/dist/components/native-capabilities/display-map.js +114 -0
  93. package/dist/components/native-capabilities/haptic-button.d.ts +26 -0
  94. package/dist/components/native-capabilities/haptic-button.d.ts.map +1 -0
  95. package/dist/components/native-capabilities/haptic-button.js +94 -0
  96. package/dist/components/native-capabilities/hid-panel.d.ts +40 -0
  97. package/dist/components/native-capabilities/hid-panel.d.ts.map +1 -0
  98. package/dist/components/native-capabilities/hid-panel.js +373 -0
  99. package/dist/components/native-capabilities/index.d.ts +27 -0
  100. package/dist/components/native-capabilities/index.d.ts.map +1 -0
  101. package/dist/components/native-capabilities/index.js +26 -0
  102. package/dist/components/native-capabilities/live-indicator.d.ts +15 -0
  103. package/dist/components/native-capabilities/live-indicator.d.ts.map +1 -0
  104. package/dist/components/native-capabilities/live-indicator.js +26 -0
  105. package/dist/components/native-capabilities/local-auth-button.d.ts +33 -0
  106. package/dist/components/native-capabilities/local-auth-button.d.ts.map +1 -0
  107. package/dist/components/native-capabilities/local-auth-button.js +115 -0
  108. package/dist/components/native-capabilities/location-panel.d.ts +29 -0
  109. package/dist/components/native-capabilities/location-panel.d.ts.map +1 -0
  110. package/dist/components/native-capabilities/location-panel.js +146 -0
  111. package/dist/components/native-capabilities/microphone-meter.d.ts +35 -0
  112. package/dist/components/native-capabilities/microphone-meter.d.ts.map +1 -0
  113. package/dist/components/native-capabilities/microphone-meter.js +244 -0
  114. package/dist/components/native-capabilities/midi-monitor.d.ts +54 -0
  115. package/dist/components/native-capabilities/midi-monitor.d.ts.map +1 -0
  116. package/dist/components/native-capabilities/midi-monitor.js +534 -0
  117. package/dist/components/native-capabilities/native-capability-panel.d.ts +11 -0
  118. package/dist/components/native-capabilities/native-capability-panel.d.ts.map +1 -0
  119. package/dist/components/native-capabilities/native-capability-panel.js +28 -0
  120. package/dist/components/native-capabilities/notification-panel.d.ts +24 -0
  121. package/dist/components/native-capabilities/notification-panel.d.ts.map +1 -0
  122. package/dist/components/native-capabilities/notification-panel.js +124 -0
  123. package/dist/components/native-capabilities/power-blocker-controller.d.ts +19 -0
  124. package/dist/components/native-capabilities/power-blocker-controller.d.ts.map +1 -0
  125. package/dist/components/native-capabilities/power-blocker-controller.js +83 -0
  126. package/dist/components/native-capabilities/power-panel.d.ts +67 -0
  127. package/dist/components/native-capabilities/power-panel.d.ts.map +1 -0
  128. package/dist/components/native-capabilities/power-panel.js +309 -0
  129. package/dist/components/native-capabilities/readout.d.ts +10 -0
  130. package/dist/components/native-capabilities/readout.d.ts.map +1 -0
  131. package/dist/components/native-capabilities/readout.js +11 -0
  132. package/dist/components/native-capabilities/screen-share-preview.d.ts +36 -0
  133. package/dist/components/native-capabilities/screen-share-preview.d.ts.map +1 -0
  134. package/dist/components/native-capabilities/screen-share-preview.js +191 -0
  135. package/dist/components/native-capabilities/secure-storage-panel.d.ts +36 -0
  136. package/dist/components/native-capabilities/secure-storage-panel.d.ts.map +1 -0
  137. package/dist/components/native-capabilities/secure-storage-panel.js +193 -0
  138. package/dist/components/native-capabilities/serial-console.d.ts +64 -0
  139. package/dist/components/native-capabilities/serial-console.d.ts.map +1 -0
  140. package/dist/components/native-capabilities/serial-console.js +399 -0
  141. package/dist/components/native-capabilities/shortcut-recorder.d.ts +35 -0
  142. package/dist/components/native-capabilities/shortcut-recorder.d.ts.map +1 -0
  143. package/dist/components/native-capabilities/shortcut-recorder.js +217 -0
  144. package/dist/components/native-capabilities/stream-log.d.ts +35 -0
  145. package/dist/components/native-capabilities/stream-log.d.ts.map +1 -0
  146. package/dist/components/native-capabilities/stream-log.js +65 -0
  147. package/dist/components/native-capabilities/system-audio-monitor.d.ts +34 -0
  148. package/dist/components/native-capabilities/system-audio-monitor.d.ts.map +1 -0
  149. package/dist/components/native-capabilities/system-audio-monitor.js +275 -0
  150. package/dist/components/native-capabilities/usb-panel.d.ts +54 -0
  151. package/dist/components/native-capabilities/usb-panel.d.ts.map +1 -0
  152. package/dist/components/native-capabilities/usb-panel.js +363 -0
  153. package/dist/components/native-capabilities/use-capability.d.ts +20 -0
  154. package/dist/components/native-capabilities/use-capability.d.ts.map +1 -0
  155. package/dist/components/native-capabilities/use-capability.js +61 -0
  156. package/dist/components/ui/alert-dialog.d.ts +7 -3
  157. package/dist/components/ui/alert-dialog.d.ts.map +1 -1
  158. package/dist/components/ui/alert-dialog.js +9 -5
  159. package/dist/components/ui/alert.d.ts +19 -3
  160. package/dist/components/ui/alert.d.ts.map +1 -1
  161. package/dist/components/ui/alert.js +25 -8
  162. package/dist/components/ui/app-frame.d.ts +28 -0
  163. package/dist/components/ui/app-frame.d.ts.map +1 -0
  164. package/dist/components/ui/app-frame.js +95 -0
  165. package/dist/components/ui/button-group.d.ts +1 -1
  166. package/dist/components/ui/button.js +1 -1
  167. package/dist/components/ui/collapsible.d.ts +9 -1
  168. package/dist/components/ui/collapsible.d.ts.map +1 -1
  169. package/dist/components/ui/collapsible.js +13 -2
  170. package/dist/components/ui/collection-navigation.d.ts +8 -0
  171. package/dist/components/ui/collection-navigation.d.ts.map +1 -0
  172. package/dist/components/ui/collection-navigation.js +19 -0
  173. package/dist/components/ui/color-well.d.ts +13 -0
  174. package/dist/components/ui/color-well.d.ts.map +1 -0
  175. package/dist/components/ui/color-well.js +30 -0
  176. package/dist/components/ui/command.d.ts +5 -1
  177. package/dist/components/ui/command.d.ts.map +1 -1
  178. package/dist/components/ui/command.js +13 -1
  179. package/dist/components/ui/confirm-dialog.d.ts +19 -0
  180. package/dist/components/ui/confirm-dialog.d.ts.map +1 -0
  181. package/dist/components/ui/confirm-dialog.js +45 -0
  182. package/dist/components/ui/date-field.d.ts +19 -0
  183. package/dist/components/ui/date-field.d.ts.map +1 -0
  184. package/dist/components/ui/date-field.js +54 -0
  185. package/dist/components/ui/date-picker.d.ts +24 -0
  186. package/dist/components/ui/date-picker.d.ts.map +1 -0
  187. package/dist/components/ui/date-picker.js +92 -0
  188. package/dist/components/ui/dialog.d.ts +4 -2
  189. package/dist/components/ui/dialog.d.ts.map +1 -1
  190. package/dist/components/ui/dialog.js +8 -5
  191. package/dist/components/ui/edge-fade.d.ts +11 -0
  192. package/dist/components/ui/edge-fade.d.ts.map +1 -0
  193. package/dist/components/ui/edge-fade.js +41 -0
  194. package/dist/components/ui/empty.d.ts +7 -2
  195. package/dist/components/ui/empty.d.ts.map +1 -1
  196. package/dist/components/ui/empty.js +20 -7
  197. package/dist/components/ui/field.d.ts +1 -1
  198. package/dist/components/ui/grid.d.ts +24 -0
  199. package/dist/components/ui/grid.d.ts.map +1 -0
  200. package/dist/components/ui/grid.js +258 -0
  201. package/dist/components/ui/icon-button.d.ts +15 -0
  202. package/dist/components/ui/icon-button.d.ts.map +1 -0
  203. package/dist/components/ui/icon-button.js +15 -0
  204. package/dist/components/ui/index.d.ts +23 -0
  205. package/dist/components/ui/index.d.ts.map +1 -1
  206. package/dist/components/ui/index.js +23 -0
  207. package/dist/components/ui/input-group.d.ts +1 -1
  208. package/dist/components/ui/inspector.d.ts +15 -0
  209. package/dist/components/ui/inspector.d.ts.map +1 -0
  210. package/dist/components/ui/inspector.js +26 -0
  211. package/dist/components/ui/kbd.d.ts +1 -1
  212. package/dist/components/ui/list.d.ts +28 -0
  213. package/dist/components/ui/list.d.ts.map +1 -0
  214. package/dist/components/ui/list.js +235 -0
  215. package/dist/components/ui/material.d.ts +34 -0
  216. package/dist/components/ui/material.d.ts.map +1 -0
  217. package/dist/components/ui/material.js +34 -0
  218. package/dist/components/ui/message-scroller-controller.d.ts +162 -0
  219. package/dist/components/ui/message-scroller-controller.d.ts.map +1 -0
  220. package/dist/components/ui/message-scroller-controller.js +888 -0
  221. package/dist/components/ui/message-scroller-layout-stability.d.ts +33 -0
  222. package/dist/components/ui/message-scroller-layout-stability.d.ts.map +1 -0
  223. package/dist/components/ui/message-scroller-layout-stability.js +153 -0
  224. package/dist/components/ui/message-scroller-policy.d.ts +74 -0
  225. package/dist/components/ui/message-scroller-policy.d.ts.map +1 -0
  226. package/dist/components/ui/message-scroller-policy.js +129 -0
  227. package/dist/components/ui/message-scroller-primitive.d.ts +55 -0
  228. package/dist/components/ui/message-scroller-primitive.d.ts.map +1 -0
  229. package/dist/components/ui/message-scroller-primitive.js +226 -0
  230. package/dist/components/ui/message-scroller.d.ts +11 -0
  231. package/dist/components/ui/message-scroller.d.ts.map +1 -0
  232. package/dist/components/ui/message-scroller.js +25 -0
  233. package/dist/components/ui/navigation-button-group.d.ts +16 -0
  234. package/dist/components/ui/navigation-button-group.d.ts.map +1 -0
  235. package/dist/components/ui/navigation-button-group.js +9 -0
  236. package/dist/components/ui/notification-dot.d.ts +4 -0
  237. package/dist/components/ui/notification-dot.d.ts.map +1 -0
  238. package/dist/components/ui/notification-dot.js +7 -0
  239. package/dist/components/ui/number-input.d.ts +16 -0
  240. package/dist/components/ui/number-input.d.ts.map +1 -0
  241. package/dist/components/ui/number-input.js +56 -0
  242. package/dist/components/ui/panel.d.ts +18 -0
  243. package/dist/components/ui/panel.d.ts.map +1 -0
  244. package/dist/components/ui/panel.js +40 -0
  245. package/dist/components/ui/popover.d.ts +9 -2
  246. package/dist/components/ui/popover.d.ts.map +1 -1
  247. package/dist/components/ui/popover.js +14 -4
  248. package/dist/components/ui/scroll-area.d.ts +8 -2
  249. package/dist/components/ui/scroll-area.d.ts.map +1 -1
  250. package/dist/components/ui/scroll-area.js +6 -3
  251. package/dist/components/ui/search-field.d.ts +19 -0
  252. package/dist/components/ui/search-field.d.ts.map +1 -0
  253. package/dist/components/ui/search-field.js +64 -0
  254. package/dist/components/ui/segmented-control.d.ts +21 -0
  255. package/dist/components/ui/segmented-control.d.ts.map +1 -0
  256. package/dist/components/ui/segmented-control.js +62 -0
  257. package/dist/components/ui/sheet.d.ts +4 -2
  258. package/dist/components/ui/sheet.d.ts.map +1 -1
  259. package/dist/components/ui/sheet.js +12 -9
  260. package/dist/components/ui/sidebar.js +1 -1
  261. package/dist/components/ui/sonner.d.ts +4 -3
  262. package/dist/components/ui/sonner.d.ts.map +1 -1
  263. package/dist/components/ui/sonner.js +7 -6
  264. package/dist/components/ui/split-view.d.ts +11 -0
  265. package/dist/components/ui/split-view.d.ts.map +1 -0
  266. package/dist/components/ui/split-view.js +13 -0
  267. package/dist/components/ui/status.d.ts +13 -0
  268. package/dist/components/ui/status.d.ts.map +1 -0
  269. package/dist/components/ui/status.js +36 -0
  270. package/dist/components/ui/table.d.ts +11 -2
  271. package/dist/components/ui/table.d.ts.map +1 -1
  272. package/dist/components/ui/table.js +33 -6
  273. package/dist/components/ui/text.d.ts +17 -0
  274. package/dist/components/ui/text.d.ts.map +1 -0
  275. package/dist/components/ui/text.js +55 -0
  276. package/dist/components/ui/toggle.d.ts +12 -4
  277. package/dist/components/ui/toggle.d.ts.map +1 -1
  278. package/dist/components/ui/toggle.js +13 -2
  279. package/dist/components/ui/toolbar.d.ts +27 -0
  280. package/dist/components/ui/toolbar.d.ts.map +1 -0
  281. package/dist/components/ui/toolbar.js +71 -0
  282. package/dist/components/ui/tooltip.d.ts +8 -3
  283. package/dist/components/ui/tooltip.d.ts.map +1 -1
  284. package/dist/components/ui/tooltip.js +11 -6
  285. package/dist/index.d.ts +2 -2
  286. package/dist/index.d.ts.map +1 -1
  287. package/dist/index.js +4 -4
  288. package/dist/lib/frame-lifecycle.d.ts +29 -0
  289. package/dist/lib/frame-lifecycle.d.ts.map +1 -1
  290. package/dist/lib/frame-lifecycle.js +85 -0
  291. package/dist/lib/native-capabilities/access.d.ts +13 -0
  292. package/dist/lib/native-capabilities/access.d.ts.map +1 -0
  293. package/dist/lib/native-capabilities/access.js +53 -0
  294. package/dist/lib/native-capabilities/bluetooth-access.d.ts +14 -0
  295. package/dist/lib/native-capabilities/bluetooth-access.d.ts.map +1 -0
  296. package/dist/lib/native-capabilities/bluetooth-access.js +43 -0
  297. package/dist/lib/native-capabilities/bluetooth-connection.d.ts +19 -0
  298. package/dist/lib/native-capabilities/bluetooth-connection.d.ts.map +1 -0
  299. package/dist/lib/native-capabilities/bluetooth-connection.js +88 -0
  300. package/dist/lib/native-capabilities/bluetooth-gatt.d.ts +7 -0
  301. package/dist/lib/native-capabilities/bluetooth-gatt.d.ts.map +1 -0
  302. package/dist/lib/native-capabilities/bluetooth-gatt.js +77 -0
  303. package/dist/lib/native-capabilities/bluetooth-internal.d.ts +10 -0
  304. package/dist/lib/native-capabilities/bluetooth-internal.d.ts.map +1 -0
  305. package/dist/lib/native-capabilities/bluetooth-internal.js +105 -0
  306. package/dist/lib/native-capabilities/bluetooth-native-fallback.d.ts +33 -0
  307. package/dist/lib/native-capabilities/bluetooth-native-fallback.d.ts.map +1 -0
  308. package/dist/lib/native-capabilities/bluetooth-native-fallback.js +214 -0
  309. package/dist/lib/native-capabilities/bluetooth-types.d.ts +85 -0
  310. package/dist/lib/native-capabilities/bluetooth-types.d.ts.map +1 -0
  311. package/dist/lib/native-capabilities/bluetooth-types.js +2 -0
  312. package/dist/lib/native-capabilities/bluetooth.d.ts +7 -0
  313. package/dist/lib/native-capabilities/bluetooth.d.ts.map +1 -0
  314. package/dist/lib/native-capabilities/bluetooth.js +4 -0
  315. package/dist/lib/native-capabilities/bridge.d.ts +23 -0
  316. package/dist/lib/native-capabilities/bridge.d.ts.map +1 -0
  317. package/dist/lib/native-capabilities/bridge.js +266 -0
  318. package/dist/lib/native-capabilities/capabilities.d.ts +7 -0
  319. package/dist/lib/native-capabilities/capabilities.d.ts.map +1 -0
  320. package/dist/lib/native-capabilities/capabilities.js +95 -0
  321. package/dist/lib/native-capabilities/clipboard.d.ts +11 -0
  322. package/dist/lib/native-capabilities/clipboard.d.ts.map +1 -0
  323. package/dist/lib/native-capabilities/clipboard.js +58 -0
  324. package/dist/lib/native-capabilities/device-io-errors.d.ts +11 -0
  325. package/dist/lib/native-capabilities/device-io-errors.d.ts.map +1 -0
  326. package/dist/lib/native-capabilities/device-io-errors.js +82 -0
  327. package/dist/lib/native-capabilities/displays.d.ts +38 -0
  328. package/dist/lib/native-capabilities/displays.d.ts.map +1 -0
  329. package/dist/lib/native-capabilities/displays.js +12 -0
  330. package/dist/lib/native-capabilities/global-shortcuts.d.ts +86 -0
  331. package/dist/lib/native-capabilities/global-shortcuts.d.ts.map +1 -0
  332. package/dist/lib/native-capabilities/global-shortcuts.js +351 -0
  333. package/dist/lib/native-capabilities/haptics.d.ts +25 -0
  334. package/dist/lib/native-capabilities/haptics.d.ts.map +1 -0
  335. package/dist/lib/native-capabilities/haptics.js +18 -0
  336. package/dist/lib/native-capabilities/hid-native.d.ts +26 -0
  337. package/dist/lib/native-capabilities/hid-native.d.ts.map +1 -0
  338. package/dist/lib/native-capabilities/hid-native.js +229 -0
  339. package/dist/lib/native-capabilities/hid.d.ts +52 -0
  340. package/dist/lib/native-capabilities/hid.d.ts.map +1 -0
  341. package/dist/lib/native-capabilities/hid.js +163 -0
  342. package/dist/lib/native-capabilities/index.d.ts +40 -0
  343. package/dist/lib/native-capabilities/index.d.ts.map +1 -0
  344. package/dist/lib/native-capabilities/index.js +21 -0
  345. package/dist/lib/native-capabilities/local-authentication.d.ts +32 -0
  346. package/dist/lib/native-capabilities/local-authentication.d.ts.map +1 -0
  347. package/dist/lib/native-capabilities/local-authentication.js +46 -0
  348. package/dist/lib/native-capabilities/location.d.ts +49 -0
  349. package/dist/lib/native-capabilities/location.d.ts.map +1 -0
  350. package/dist/lib/native-capabilities/location.js +114 -0
  351. package/dist/lib/native-capabilities/media-permissions.d.ts +28 -0
  352. package/dist/lib/native-capabilities/media-permissions.d.ts.map +1 -0
  353. package/dist/lib/native-capabilities/media-permissions.js +37 -0
  354. package/dist/lib/native-capabilities/media.d.ts +17 -0
  355. package/dist/lib/native-capabilities/media.d.ts.map +1 -0
  356. package/dist/lib/native-capabilities/media.js +104 -0
  357. package/dist/lib/native-capabilities/midi-access.d.ts +13 -0
  358. package/dist/lib/native-capabilities/midi-access.d.ts.map +1 -0
  359. package/dist/lib/native-capabilities/midi-access.js +68 -0
  360. package/dist/lib/native-capabilities/midi-internal.d.ts +12 -0
  361. package/dist/lib/native-capabilities/midi-internal.d.ts.map +1 -0
  362. package/dist/lib/native-capabilities/midi-internal.js +88 -0
  363. package/dist/lib/native-capabilities/midi-native-fallback.d.ts +27 -0
  364. package/dist/lib/native-capabilities/midi-native-fallback.d.ts.map +1 -0
  365. package/dist/lib/native-capabilities/midi-native-fallback.js +127 -0
  366. package/dist/lib/native-capabilities/midi-ports.d.ts +6 -0
  367. package/dist/lib/native-capabilities/midi-ports.d.ts.map +1 -0
  368. package/dist/lib/native-capabilities/midi-ports.js +115 -0
  369. package/dist/lib/native-capabilities/midi-types.d.ts +25 -0
  370. package/dist/lib/native-capabilities/midi-types.d.ts.map +1 -0
  371. package/dist/lib/native-capabilities/midi-types.js +1 -0
  372. package/dist/lib/native-capabilities/midi.d.ts +6 -0
  373. package/dist/lib/native-capabilities/midi.d.ts.map +1 -0
  374. package/dist/lib/native-capabilities/midi.js +3 -0
  375. package/dist/lib/native-capabilities/native-device-io.d.ts +28 -0
  376. package/dist/lib/native-capabilities/native-device-io.d.ts.map +1 -0
  377. package/dist/lib/native-capabilities/native-device-io.js +91 -0
  378. package/dist/lib/native-capabilities/native-device-lifecycle.d.ts +13 -0
  379. package/dist/lib/native-capabilities/native-device-lifecycle.d.ts.map +1 -0
  380. package/dist/lib/native-capabilities/native-device-lifecycle.js +40 -0
  381. package/dist/lib/native-capabilities/notifications.d.ts +38 -0
  382. package/dist/lib/native-capabilities/notifications.d.ts.map +1 -0
  383. package/dist/lib/native-capabilities/notifications.js +50 -0
  384. package/dist/lib/native-capabilities/power-session.d.ts +113 -0
  385. package/dist/lib/native-capabilities/power-session.d.ts.map +1 -0
  386. package/dist/lib/native-capabilities/power-session.js +264 -0
  387. package/dist/lib/native-capabilities/secure-storage.d.ts +36 -0
  388. package/dist/lib/native-capabilities/secure-storage.d.ts.map +1 -0
  389. package/dist/lib/native-capabilities/secure-storage.js +64 -0
  390. package/dist/lib/native-capabilities/serial-native.d.ts +23 -0
  391. package/dist/lib/native-capabilities/serial-native.d.ts.map +1 -0
  392. package/dist/lib/native-capabilities/serial-native.js +181 -0
  393. package/dist/lib/native-capabilities/serial.d.ts +76 -0
  394. package/dist/lib/native-capabilities/serial.d.ts.map +1 -0
  395. package/dist/lib/native-capabilities/serial.js +215 -0
  396. package/dist/lib/native-capabilities/system-audio.d.ts +127 -0
  397. package/dist/lib/native-capabilities/system-audio.d.ts.map +1 -0
  398. package/dist/lib/native-capabilities/system-audio.js +330 -0
  399. package/dist/lib/native-capabilities/types.d.ts +62 -0
  400. package/dist/lib/native-capabilities/types.d.ts.map +1 -0
  401. package/dist/lib/native-capabilities/types.js +27 -0
  402. package/dist/lib/native-capabilities/usb-native.d.ts +39 -0
  403. package/dist/lib/native-capabilities/usb-native.d.ts.map +1 -0
  404. package/dist/lib/native-capabilities/usb-native.js +217 -0
  405. package/dist/lib/native-capabilities/usb.d.ts +85 -0
  406. package/dist/lib/native-capabilities/usb.d.ts.map +1 -0
  407. package/dist/lib/native-capabilities/usb.js +225 -0
  408. package/dist/lib/theme.d.ts.map +1 -1
  409. package/dist/lib/theme.js +2 -1
  410. package/docs/README.md +39 -0
  411. package/docs/accessibility.md +32 -0
  412. package/docs/adaptive-materials.md +79 -0
  413. package/docs/app-anatomy.md +74 -0
  414. package/docs/component-catalog.md +82 -0
  415. package/docs/component-guide-template.md +37 -0
  416. package/docs/design-tokens.md +185 -0
  417. package/docs/foundations.md +58 -0
  418. package/docs/native-integration.md +33 -0
  419. package/docs/standalone-app-windows.md +136 -0
  420. package/package.json +8 -3
  421. package/src/components/ui/alert-dialog.md +31 -0
  422. package/src/components/ui/alert.md +77 -0
  423. package/src/components/ui/app-frame.md +38 -0
  424. package/src/components/ui/badge.md +57 -0
  425. package/src/components/ui/button.md +76 -0
  426. package/src/components/ui/collapsible.md +52 -0
  427. package/src/components/ui/color-well.md +11 -0
  428. package/src/components/ui/combobox.md +42 -0
  429. package/src/components/ui/command.md +54 -0
  430. package/src/components/ui/date-field.md +32 -0
  431. package/src/components/ui/date-picker.md +55 -0
  432. package/src/components/ui/dialog.md +40 -0
  433. package/src/components/ui/edge-fade.md +7 -0
  434. package/src/components/ui/empty.md +87 -0
  435. package/src/components/ui/field.md +77 -0
  436. package/src/components/ui/grid.md +109 -0
  437. package/src/components/ui/icon-button.md +36 -0
  438. package/src/components/ui/inspector.md +11 -0
  439. package/src/components/ui/item.md +87 -0
  440. package/src/components/ui/list.md +140 -0
  441. package/src/components/ui/material.md +51 -0
  442. package/src/components/ui/navigation-button-group.md +46 -0
  443. package/src/components/ui/notification-dot.md +7 -0
  444. package/src/components/ui/number-input.md +19 -0
  445. package/src/components/ui/panel.md +11 -0
  446. package/src/components/ui/popover.md +31 -0
  447. package/src/components/ui/resizable.md +66 -0
  448. package/src/components/ui/scroll-area.md +72 -0
  449. package/src/components/ui/search-field.md +33 -0
  450. package/src/components/ui/segmented-control.md +36 -0
  451. package/src/components/ui/sheet.md +30 -0
  452. package/src/components/ui/sidebar.md +113 -0
  453. package/src/components/ui/sonner.md +37 -0
  454. package/src/components/ui/split-view.md +15 -0
  455. package/src/components/ui/status.md +12 -0
  456. package/src/components/ui/table.md +37 -0
  457. package/src/components/ui/tabs.md +66 -0
  458. package/src/components/ui/text.md +17 -0
  459. package/src/components/ui/toggle-button.md +48 -0
  460. package/src/components/ui/toggle-group.md +80 -0
  461. package/src/components/ui/toggle.md +73 -0
  462. package/src/components/ui/toolbar.md +26 -0
  463. package/src/components/ui/tooltip.md +31 -0
  464. package/src/styles/index.css +704 -3
@@ -0,0 +1,888 @@
1
+ import { MessageScrollerPolicy } from './message-scroller-policy';
2
+ const READING_LEAF_SELECTOR = '[data-message-scroll-anchor]';
3
+ const POSITION_EPSILON_PX = 0.5;
4
+ const WARMUP_BATCH_SIZE = 3;
5
+ const PROGRAMMATIC_SCROLL_TIMEOUT_MS = 800;
6
+ function now() {
7
+ return typeof performance !== 'undefined' ? performance.now() : Date.now();
8
+ }
9
+ const EMPTY_SCROLLABLE = { start: false, end: false };
10
+ const EMPTY_VISIBILITY = {
11
+ currentAnchorId: null,
12
+ visibleMessageIds: [],
13
+ };
14
+ export function createExternalStore(initial, isEqual) {
15
+ let snapshot = initial;
16
+ const listeners = new Set();
17
+ return {
18
+ getSnapshot: () => snapshot,
19
+ hasListeners: () => listeners.size > 0,
20
+ setSnapshot: (next) => {
21
+ if (isEqual(snapshot, next))
22
+ return;
23
+ snapshot = next;
24
+ listeners.forEach((listener) => listener());
25
+ },
26
+ subscribe: (listener, onFirst, onLast) => {
27
+ const wasEmpty = listeners.size === 0;
28
+ listeners.add(listener);
29
+ if (wasEmpty)
30
+ onFirst?.();
31
+ return () => {
32
+ listeners.delete(listener);
33
+ if (listeners.size === 0)
34
+ onLast?.();
35
+ };
36
+ },
37
+ };
38
+ }
39
+ function scrollableEquals(a, b) {
40
+ return a.start === b.start && a.end === b.end;
41
+ }
42
+ function visibilityEquals(a, b) {
43
+ return (a.currentAnchorId === b.currentAnchorId &&
44
+ a.visibleMessageIds.length === b.visibleMessageIds.length &&
45
+ a.visibleMessageIds.every((id, index) => id === b.visibleMessageIds[index]));
46
+ }
47
+ export function isMessageScrollerAtEnd(viewport, threshold) {
48
+ return maxScrollTop(viewport) - viewport.scrollTop <= threshold;
49
+ }
50
+ /**
51
+ * Snapshot of the stable leaves the reader can currently see, preferring
52
+ * fine-grained `[data-message-scroll-anchor]` leaves (their tops do not move
53
+ * when a disclosure collapses inside the same message) over whole items.
54
+ */
55
+ export function captureReadingLeaves(viewport, content, items) {
56
+ const leaves = [
57
+ ...Array.from(content.querySelectorAll(READING_LEAF_SELECTOR)),
58
+ ...items,
59
+ ];
60
+ const viewportRect = viewport.getBoundingClientRect();
61
+ return leaves.map((element) => {
62
+ const rect = element.getBoundingClientRect();
63
+ return {
64
+ element,
65
+ top: rect.top - viewportRect.top,
66
+ bottom: rect.bottom - viewportRect.top,
67
+ };
68
+ });
69
+ }
70
+ /**
71
+ * Re-pins the first still-visible captured leaf after content above it
72
+ * changed size. Native scroll anchoring may already have compensated; the
73
+ * measured delta is zero then and this is deliberately a no-op.
74
+ */
75
+ export function restoreReadingLeaves(viewport, leaves) {
76
+ const visible = leaves.find(({ element, top, bottom }) => {
77
+ if (!element.isConnected)
78
+ return false;
79
+ const rect = element.getBoundingClientRect();
80
+ return rect.height > 0 && bottom > 0 && top < viewport.clientHeight;
81
+ });
82
+ if (!visible)
83
+ return false;
84
+ const delta = elementViewportTop(visible.element, viewport) - visible.top;
85
+ if (Math.abs(delta) <= POSITION_EPSILON_PX)
86
+ return false;
87
+ viewport.scrollTop += delta;
88
+ return true;
89
+ }
90
+ /**
91
+ * The single DOM-side owner of transcript scrolling. Every behavior that can
92
+ * move the viewport — follow-the-end, turn anchoring, prepend preservation,
93
+ * reading-position stability while rows above collapse — routes through this
94
+ * controller and its {@link MessageScrollerPolicy}, so nothing here can fight
95
+ * the reader (or another controller) for the scroll position.
96
+ */
97
+ export class MessageScrollerController {
98
+ scrollableStore = createExternalStore(EMPTY_SCROLLABLE, scrollableEquals);
99
+ visibilityStore = createExternalStore(EMPTY_VISIBILITY, visibilityEquals);
100
+ policy;
101
+ options;
102
+ preserveScrollOnPrepend = true;
103
+ root = null;
104
+ viewport = null;
105
+ content = null;
106
+ spacer = null;
107
+ messageElements = new Map();
108
+ handledTurnAnchors = new WeakSet();
109
+ visibleMessageIds = new Set();
110
+ warmedItems = new WeakSet();
111
+ lastScrollTop = 0;
112
+ previousFirstItem = null;
113
+ previousItemCount = 0;
114
+ anchoredElement = null;
115
+ trackedFirstVisible = null;
116
+ readingLeaves = [];
117
+ pendingScrollToMessage = null;
118
+ defaultPositionApplied = false;
119
+ spacerHeight = 0;
120
+ spacerGap = 0;
121
+ programmaticDeadline = 0;
122
+ stateFrame = null;
123
+ visibilityFrame = null;
124
+ warmupHandle = null;
125
+ warmupUsesIdleCallback = false;
126
+ intersectionObserver = null;
127
+ constructor(options) {
128
+ this.options = options;
129
+ this.policy = new MessageScrollerPolicy(options.autoScroll);
130
+ }
131
+ get viewportElement() {
132
+ return this.viewport;
133
+ }
134
+ // MARK: - Element wiring
135
+ setRoot(element) {
136
+ this.root = element;
137
+ if (element)
138
+ this.applyStateAttributes();
139
+ }
140
+ setViewport(element) {
141
+ this.viewport = element;
142
+ if (element) {
143
+ this.lastScrollTop = element.scrollTop;
144
+ this.applyStateAttributes();
145
+ }
146
+ }
147
+ setContent(element) {
148
+ this.content = element;
149
+ }
150
+ setSpacer(element) {
151
+ this.spacer = element;
152
+ this.spacerGap = element ? readRowGap(element.parentElement) : 0;
153
+ }
154
+ registerMessage(messageId, element, previous) {
155
+ if (element) {
156
+ this.messageElements.set(messageId, element);
157
+ this.intersectionObserver?.observe(element);
158
+ this.scheduleVisibilitySync();
159
+ if (this.pendingScrollToMessage?.messageId === messageId) {
160
+ this.flushPendingScrollToMessage();
161
+ }
162
+ return;
163
+ }
164
+ if (previous && this.messageElements.get(messageId) === previous) {
165
+ this.messageElements.delete(messageId);
166
+ this.visibleMessageIds.delete(messageId);
167
+ this.intersectionObserver?.unobserve(previous);
168
+ this.scheduleVisibilitySync();
169
+ }
170
+ }
171
+ // MARK: - Public scroll commands
172
+ scrollToEnd = (options = {}) => {
173
+ const viewport = this.viewport;
174
+ if (!viewport)
175
+ return false;
176
+ this.setSpacerHeight(0);
177
+ this.anchoredElement = null;
178
+ this.readingLeaves = [];
179
+ this.policy.jumpToEnd();
180
+ this.performScroll(maxScrollTop(viewport), options.behavior ?? 'auto');
181
+ this.scheduleVisibilitySync();
182
+ return true;
183
+ };
184
+ scrollToStart = (options = {}) => {
185
+ const viewport = this.viewport;
186
+ if (!viewport)
187
+ return false;
188
+ this.setSpacerHeight(0);
189
+ this.anchoredElement = null;
190
+ this.readingLeaves = [];
191
+ this.policy.jumpToStart();
192
+ this.performScroll(0, options.behavior ?? 'auto');
193
+ this.scheduleVisibilitySync();
194
+ return true;
195
+ };
196
+ scrollToMessage = (messageId, options) => {
197
+ const element = this.messageElements.get(messageId);
198
+ if (element) {
199
+ if (this.scrollToElement(element, options)) {
200
+ this.pendingScrollToMessage = null;
201
+ return true;
202
+ }
203
+ this.pendingScrollToMessage = { messageId, options };
204
+ return true;
205
+ }
206
+ if (this.previousItemCount === 0) {
207
+ this.pendingScrollToMessage = { messageId, options };
208
+ this.defaultPositionApplied = true;
209
+ return true;
210
+ }
211
+ return false;
212
+ };
213
+ scrollToElement(element, options = {}, { keepPreviousPeek = false } = {}) {
214
+ const viewport = this.viewport;
215
+ const content = this.content;
216
+ if (!viewport || !content || !content.contains(element))
217
+ return false;
218
+ const margin = (options.scrollMargin ?? this.options.scrollMargin) +
219
+ (keepPreviousPeek ? this.options.scrollPreviousItemPeek : 0);
220
+ const padding = readBlockPadding(content);
221
+ const target = alignedScrollTarget({
222
+ align: options.align ?? 'start',
223
+ element,
224
+ margin,
225
+ padding,
226
+ viewport,
227
+ });
228
+ // Growing the spacer first lets a late-transcript anchor actually reach
229
+ // the requested position even when little content follows it. The
230
+ // measurement must exclude the spacer itself: measuring through the
231
+ // content box would yield `required − current` instead of the absolute
232
+ // requirement, and the resulting resize feedback oscillated the spacer
233
+ // between the two values on every ResizeObserver tick.
234
+ const shortfall = target +
235
+ viewport.clientHeight -
236
+ contentBottomWithoutSpacer(viewport, content, this.itemChildren());
237
+ this.setSpacerHeight(Math.max(0, Math.ceil(shortfall)));
238
+ this.readingLeaves = [];
239
+ if (keepPreviousPeek) {
240
+ this.anchoredElement = element;
241
+ this.policy.anchorToTurn();
242
+ }
243
+ else {
244
+ this.anchoredElement = null;
245
+ this.policy.beginJump();
246
+ }
247
+ this.performScroll(target, options.behavior ?? 'auto');
248
+ this.scheduleVisibilitySync();
249
+ return true;
250
+ }
251
+ // MARK: - DOM events
252
+ handleScroll() {
253
+ const viewport = this.viewport;
254
+ if (!viewport)
255
+ return;
256
+ if (this.policy.programmaticTarget !== null &&
257
+ now() > this.programmaticDeadline) {
258
+ this.policy.cancelProgrammaticScroll();
259
+ }
260
+ const scrollTop = viewport.scrollTop;
261
+ const userScrolled = this.policy.handleScrollEvent({
262
+ scrollTop,
263
+ lastScrollTop: this.lastScrollTop,
264
+ atEnd: this.isAtEnd(),
265
+ });
266
+ this.lastScrollTop = scrollTop;
267
+ if (userScrolled) {
268
+ if (this.policy.mode !== 'anchored')
269
+ this.anchoredElement = null;
270
+ // A snapshot captured before this ownership change describes a layout
271
+ // the reader has scrolled away from; restoring against it would
272
+ // teleport the viewport. A fresh capture lands next frame.
273
+ this.readingLeaves = [];
274
+ }
275
+ this.scheduleStateCommit();
276
+ this.scheduleVisibilitySync();
277
+ }
278
+ handleWheel(deltaY) {
279
+ this.policy.handleUserIntent(deltaY < 0 ? 'up' : 'down');
280
+ if (this.policy.mode !== 'anchored')
281
+ this.anchoredElement = null;
282
+ this.readingLeaves = [];
283
+ this.scheduleStateCommit();
284
+ }
285
+ handleTouchMove() {
286
+ this.policy.handleUserIntent('unknown');
287
+ this.anchoredElement = null;
288
+ this.readingLeaves = [];
289
+ this.scheduleStateCommit();
290
+ }
291
+ handleScrollKey() {
292
+ this.policy.handleUserIntent('unknown');
293
+ this.anchoredElement = null;
294
+ this.readingLeaves = [];
295
+ this.scheduleStateCommit();
296
+ }
297
+ /**
298
+ * Content box resized (streaming growth, images decoding, disclosures
299
+ * collapsing, `content-visibility` reveals). Which way the viewport moves
300
+ * — if at all — is entirely the policy's call.
301
+ */
302
+ handleResize() {
303
+ const viewport = this.viewport;
304
+ if (!viewport) {
305
+ return;
306
+ }
307
+ switch (this.policy.resizeAction()) {
308
+ case 'stick-to-end': {
309
+ const target = maxScrollTop(viewport);
310
+ if (Math.abs(viewport.scrollTop - target) > POSITION_EPSILON_PX) {
311
+ this.performScroll(target, 'auto');
312
+ }
313
+ break;
314
+ }
315
+ case 'reanchor': {
316
+ const anchored = this.anchoredElement;
317
+ if (anchored?.isConnected) {
318
+ this.scrollToElement(anchored, { align: 'start' }, { keepPreviousPeek: true });
319
+ }
320
+ else {
321
+ this.anchoredElement = null;
322
+ this.policy.release();
323
+ }
324
+ break;
325
+ }
326
+ case 'preserve-reading-position':
327
+ this.restoreReadingPosition();
328
+ break;
329
+ case 'none':
330
+ break;
331
+ }
332
+ this.scheduleStateCommit();
333
+ this.scheduleVisibilitySync();
334
+ }
335
+ /** Children of the content element changed. Runs before the next paint. */
336
+ handleContentMutation() {
337
+ const children = this.itemChildren();
338
+ const previousFirst = this.previousFirstItem;
339
+ const previousCount = this.previousItemCount;
340
+ this.previousFirstItem = children[0] ?? null;
341
+ this.previousItemCount = children.length;
342
+ this.scheduleWarmup();
343
+ if (this.flushPendingScrollToMessage())
344
+ return;
345
+ if (previousCount === 0) {
346
+ // Everything present at mount is history; only anchors appended after
347
+ // this point can represent a new turn. Without this seeding, a later
348
+ // equal-count row replacement would treat the conversation's oldest
349
+ // prompt as "unhandled" and yank the viewport to the top.
350
+ this.markTurnAnchorsHandled(children, 0);
351
+ if (children.length > 0)
352
+ this.applyDefaultPosition(children);
353
+ this.scheduleStateCommit();
354
+ this.scheduleVisibilitySync();
355
+ return;
356
+ }
357
+ const previousFirstIndex = previousFirst
358
+ ? children.indexOf(previousFirst)
359
+ : -1;
360
+ if (this.preserveScrollOnPrepend && previousFirstIndex > 0) {
361
+ this.markTurnAnchorsHandled(children, 0);
362
+ this.preservePrependPosition();
363
+ return;
364
+ }
365
+ if (children.length > previousCount) {
366
+ const appendedAnchor = firstTurnAnchorAt(children, previousCount);
367
+ if (appendedAnchor) {
368
+ this.markTurnAnchorsHandled(children, previousCount);
369
+ if (this.policy.followsEnd &&
370
+ countTurnAnchorsAt(children, previousCount) > 1) {
371
+ // Several anchors at once is a history restore, not a new turn.
372
+ this.scrollToEnd();
373
+ return;
374
+ }
375
+ this.anchorTurn(appendedAnchor);
376
+ return;
377
+ }
378
+ }
379
+ if (children.length === previousCount && this.policy.mode === 'anchored') {
380
+ // A terminal snapshot can replace the live turn's rows one-for-one
381
+ // with their persisted forms; keep that turn anchored. The live turn
382
+ // is the newest anchor, so scan from the end.
383
+ let replacement = null;
384
+ for (let index = children.length - 1; index >= 0; index -= 1) {
385
+ const child = children[index];
386
+ if (child?.dataset.scrollAnchor === 'true' &&
387
+ !this.handledTurnAnchors.has(child)) {
388
+ replacement = child;
389
+ break;
390
+ }
391
+ }
392
+ if (replacement) {
393
+ this.markTurnAnchorsHandled(children, 0);
394
+ this.anchorTurn(replacement);
395
+ return;
396
+ }
397
+ }
398
+ if (this.policy.followsEnd) {
399
+ this.scrollToEnd();
400
+ return;
401
+ }
402
+ this.scheduleStateCommit();
403
+ this.scheduleVisibilitySync();
404
+ }
405
+ observeVisibility() {
406
+ const viewport = this.viewport;
407
+ if (!viewport || !this.visibilityStore.hasListeners())
408
+ return;
409
+ if (typeof IntersectionObserver === 'undefined') {
410
+ this.scheduleVisibilitySync();
411
+ return;
412
+ }
413
+ if (!this.intersectionObserver) {
414
+ this.intersectionObserver = new IntersectionObserver((entries) => {
415
+ for (const entry of entries) {
416
+ const messageId = entry.target.dataset.messageId;
417
+ if (!messageId)
418
+ continue;
419
+ if (entry.isIntersecting)
420
+ this.visibleMessageIds.add(messageId);
421
+ else
422
+ this.visibleMessageIds.delete(messageId);
423
+ }
424
+ this.scheduleVisibilitySync();
425
+ }, {
426
+ root: viewport,
427
+ rootMargin: `${-(this.options.scrollMargin + this.options.scrollPreviousItemPeek)}px 0px 0px 0px`,
428
+ threshold: [0, 0.01, 0.5, 1],
429
+ });
430
+ this.messageElements.forEach((element) => {
431
+ this.intersectionObserver?.observe(element);
432
+ });
433
+ }
434
+ this.scheduleVisibilitySync();
435
+ }
436
+ unobserveVisibility() {
437
+ if (this.visibilityFrame !== null) {
438
+ cancelAnimationFrame(this.visibilityFrame);
439
+ this.visibilityFrame = null;
440
+ }
441
+ this.intersectionObserver?.disconnect();
442
+ this.intersectionObserver = null;
443
+ this.visibleMessageIds.clear();
444
+ this.visibilityStore.setSnapshot(EMPTY_VISIBILITY);
445
+ }
446
+ resetDefaultPosition() {
447
+ this.defaultPositionApplied = false;
448
+ }
449
+ updateOptions(options) {
450
+ const autoScrollChanged = options.autoScroll !== this.options.autoScroll;
451
+ this.options = options;
452
+ this.policy.autoScroll = options.autoScroll;
453
+ if (autoScrollChanged && options.autoScroll && this.isAtEnd()) {
454
+ this.policy.jumpToEnd();
455
+ }
456
+ }
457
+ destroy() {
458
+ // Nulling the frame handles matters as much as cancelling them: the
459
+ // controller outlives a StrictMode unmount/remount cycle, and a stale
460
+ // non-null handle would block every future scheduled commit.
461
+ if (this.stateFrame !== null) {
462
+ cancelAnimationFrame(this.stateFrame);
463
+ this.stateFrame = null;
464
+ }
465
+ if (this.visibilityFrame !== null) {
466
+ cancelAnimationFrame(this.visibilityFrame);
467
+ this.visibilityFrame = null;
468
+ }
469
+ this.cancelWarmup();
470
+ this.unobserveVisibility();
471
+ }
472
+ // MARK: - Positioning
473
+ applyDefaultPosition(children) {
474
+ if (this.defaultPositionApplied)
475
+ return;
476
+ this.defaultPositionApplied = true;
477
+ const position = this.options.defaultScrollPosition;
478
+ if (position === 'start') {
479
+ this.scrollToStart();
480
+ return;
481
+ }
482
+ if (position === 'last-anchor') {
483
+ const viewport = this.viewport;
484
+ const content = this.content;
485
+ const lastAnchor = [...children]
486
+ .reverse()
487
+ .find((child) => child.dataset.scrollAnchor === 'true');
488
+ if (viewport && content && lastAnchor) {
489
+ const remaining = contentBottomWithoutSpacer(viewport, content, children) -
490
+ elementTopInContent(lastAnchor, viewport);
491
+ if (remaining > viewport.clientHeight) {
492
+ this.scrollToElement(lastAnchor, { align: 'start' }, { keepPreviousPeek: true });
493
+ return;
494
+ }
495
+ }
496
+ }
497
+ this.scrollToEnd();
498
+ }
499
+ anchorTurn(anchor) {
500
+ this.handledTurnAnchors.add(anchor);
501
+ this.scrollToElement(anchor, { align: 'start' }, { keepPreviousPeek: true });
502
+ }
503
+ markTurnAnchorsHandled(children, fromIndex) {
504
+ for (let index = fromIndex; index < children.length; index += 1) {
505
+ const child = children[index];
506
+ if (child?.dataset.scrollAnchor === 'true') {
507
+ this.handledTurnAnchors.add(child);
508
+ }
509
+ }
510
+ }
511
+ /**
512
+ * Older rows were inserted above the reader. Compensate the scroll offset
513
+ * by the tracked first-visible row's displacement in the same mutation
514
+ * pass, before the shifted layout can paint.
515
+ */
516
+ preservePrependPosition() {
517
+ const viewport = this.viewport;
518
+ const tracked = this.trackedFirstVisible;
519
+ if (viewport && tracked?.element.isConnected) {
520
+ if (this.policy.followsEnd) {
521
+ this.scrollToEnd();
522
+ return;
523
+ }
524
+ const delta = elementViewportTop(tracked.element, viewport) - tracked.top;
525
+ if (Math.abs(delta) > POSITION_EPSILON_PX) {
526
+ viewport.scrollTop += delta;
527
+ this.lastScrollTop = viewport.scrollTop;
528
+ }
529
+ this.trackFirstVisibleItem();
530
+ }
531
+ this.scheduleStateCommit();
532
+ this.scheduleVisibilitySync();
533
+ }
534
+ performScroll(target, behavior) {
535
+ const viewport = this.viewport;
536
+ if (!viewport)
537
+ return;
538
+ // Clamp to what the viewport can actually reach: an unreachable target
539
+ // would never register arrival and would park the policy in a state
540
+ // where the next reader scroll is misread as programmatic motion.
541
+ const clamped = Math.min(Math.max(0, target), maxScrollTop(viewport));
542
+ this.policy.beginProgrammaticScroll(clamped);
543
+ const resolveInPlace = behavior === 'auto' ||
544
+ typeof viewport.scrollTo !== 'function' ||
545
+ Math.abs(viewport.scrollTop - clamped) <= POSITION_EPSILON_PX;
546
+ if (resolveInPlace) {
547
+ viewport.scrollTop = clamped;
548
+ this.lastScrollTop = viewport.scrollTop;
549
+ this.policy.handleScrollEvent({
550
+ scrollTop: viewport.scrollTop,
551
+ lastScrollTop: this.lastScrollTop,
552
+ atEnd: this.isAtEnd(),
553
+ });
554
+ this.scheduleStateCommit();
555
+ return;
556
+ }
557
+ // A smooth scroll that gets interrupted (content shrank, animation
558
+ // dropped) may never emit an arriving event; past the deadline the
559
+ // policy stops treating movement as its own.
560
+ this.programmaticDeadline = now() + PROGRAMMATIC_SCROLL_TIMEOUT_MS;
561
+ viewport.scrollTo({ top: clamped, behavior });
562
+ this.scheduleStateCommit();
563
+ }
564
+ // MARK: - Reading-position stability
565
+ /**
566
+ * Snapshot of stable leaves the reader can see. When a disclosure above
567
+ * them collapses (or a hidden row re-measures), the first still-visible
568
+ * leaf is re-pinned so the text under the reader's eyes never shifts.
569
+ */
570
+ snapshotReadingLeaves() {
571
+ const viewport = this.viewport;
572
+ const content = this.content;
573
+ if (!viewport || !content)
574
+ return;
575
+ this.readingLeaves = captureReadingLeaves(viewport, content, this.itemChildren());
576
+ }
577
+ restoreReadingPosition() {
578
+ const viewport = this.viewport;
579
+ if (!viewport)
580
+ return;
581
+ if (restoreReadingLeaves(viewport, this.readingLeaves)) {
582
+ this.lastScrollTop = viewport.scrollTop;
583
+ this.snapshotReadingLeaves();
584
+ }
585
+ }
586
+ trackFirstVisibleItem() {
587
+ const viewport = this.viewport;
588
+ if (!viewport) {
589
+ this.trackedFirstVisible = null;
590
+ return;
591
+ }
592
+ const viewportRect = viewport.getBoundingClientRect();
593
+ for (const child of this.itemChildren()) {
594
+ const rect = child.getBoundingClientRect();
595
+ if (rect.bottom > viewportRect.top && rect.top < viewportRect.bottom) {
596
+ this.trackedFirstVisible = {
597
+ element: child,
598
+ top: rect.top - viewportRect.top,
599
+ };
600
+ return;
601
+ }
602
+ }
603
+ this.trackedFirstVisible = null;
604
+ }
605
+ // MARK: - State stores
606
+ scheduleStateCommit() {
607
+ if (this.stateFrame !== null)
608
+ return;
609
+ this.stateFrame = requestAnimationFrame(() => {
610
+ this.stateFrame = null;
611
+ this.commitFrameState();
612
+ });
613
+ }
614
+ /**
615
+ * Once per frame: publish the scrollable edges and refresh the geometry
616
+ * snapshots (tracked first-visible row, reading leaves) that prepend
617
+ * preservation and reading-position restores compare against. Capturing
618
+ * here — instead of on every scroll event — bounds rect reads to one pass
619
+ * per frame.
620
+ */
621
+ commitFrameState() {
622
+ const viewport = this.viewport;
623
+ if (!viewport)
624
+ return;
625
+ const threshold = this.options.scrollEdgeThreshold;
626
+ const scrollable = {
627
+ start: viewport.scrollTop > threshold,
628
+ // While following, transient off-end moments (content grew; the
629
+ // follow-up scroll lands next tick) must not flash the jump button.
630
+ end: !this.policy.followsEnd &&
631
+ maxScrollTop(viewport) - viewport.scrollTop > threshold,
632
+ };
633
+ this.scrollableStore.setSnapshot(scrollable);
634
+ this.applyStateAttributes();
635
+ if (!this.policy.followsEnd) {
636
+ this.trackFirstVisibleItem();
637
+ if (this.policy.mode === 'free')
638
+ this.snapshotReadingLeaves();
639
+ }
640
+ }
641
+ applyStateAttributes() {
642
+ const scrollable = this.scrollableStore.getSnapshot();
643
+ const label = [
644
+ scrollable.start ? 'start' : null,
645
+ scrollable.end ? 'end' : null,
646
+ ]
647
+ .filter(Boolean)
648
+ .join(' ');
649
+ for (const element of [this.root, this.viewport]) {
650
+ if (!element)
651
+ continue;
652
+ if (label)
653
+ element.setAttribute('data-scrollable', label);
654
+ else
655
+ element.removeAttribute('data-scrollable');
656
+ element.toggleAttribute('data-autoscrolling', this.policy.programmaticTarget !== null);
657
+ }
658
+ }
659
+ scheduleVisibilitySync() {
660
+ if (!this.visibilityStore.hasListeners())
661
+ return;
662
+ if (this.visibilityFrame !== null)
663
+ return;
664
+ this.visibilityFrame = requestAnimationFrame(() => {
665
+ this.visibilityFrame = null;
666
+ if (!this.visibilityStore.hasListeners())
667
+ return;
668
+ this.visibilityStore.setSnapshot(this.computeVisibility());
669
+ });
670
+ }
671
+ computeVisibility() {
672
+ const viewport = this.viewport;
673
+ const content = this.content;
674
+ if (!viewport || !content)
675
+ return EMPTY_VISIBILITY;
676
+ const viewportRect = viewport.getBoundingClientRect();
677
+ const anchorLine = viewportRect.top +
678
+ this.options.scrollMargin +
679
+ this.options.scrollPreviousItemPeek;
680
+ const useRectFallback = typeof IntersectionObserver === 'undefined';
681
+ const visibleIds = [];
682
+ let currentAnchorId = null;
683
+ for (const child of this.itemChildren()) {
684
+ const messageId = child.dataset.messageId;
685
+ if (!messageId)
686
+ continue;
687
+ const isAnchor = child.dataset.scrollAnchor === 'true';
688
+ const rect = isAnchor || useRectFallback ? child.getBoundingClientRect() : null;
689
+ const isVisible = useRectFallback && rect
690
+ ? rect.bottom > anchorLine && rect.top < viewportRect.bottom
691
+ : this.visibleMessageIds.has(messageId);
692
+ if (isVisible)
693
+ visibleIds.push(messageId);
694
+ if (isAnchor && rect && rect.top <= anchorLine + POSITION_EPSILON_PX) {
695
+ currentAnchorId = messageId;
696
+ }
697
+ }
698
+ if (visibleIds.length === 0 && currentAnchorId === null) {
699
+ return EMPTY_VISIBILITY;
700
+ }
701
+ return { currentAnchorId, visibleMessageIds: visibleIds };
702
+ }
703
+ // MARK: - Content-visibility warm-up
704
+ /**
705
+ * Rows outside the viewport skip rendering via `content-visibility: auto`
706
+ * and a placeholder intrinsic size. Their first reveal during an upward
707
+ * scroll pays first-time layout of complex markdown — felt as hitches on
708
+ * the first pass through history. Rendering each row once at idle records
709
+ * its real size (the `auto` keyword keeps last-remembered sizes), so the
710
+ * first real scroll finds everything measured and warm.
711
+ */
712
+ scheduleWarmup() {
713
+ if (this.warmupHandle !== null)
714
+ return;
715
+ const run = () => {
716
+ this.warmupHandle = null;
717
+ this.warmupBatch();
718
+ };
719
+ if (typeof requestIdleCallback === 'function') {
720
+ this.warmupUsesIdleCallback = true;
721
+ this.warmupHandle = requestIdleCallback(run, { timeout: 1_000 });
722
+ }
723
+ else {
724
+ this.warmupUsesIdleCallback = false;
725
+ this.warmupHandle = window.setTimeout(run, 150);
726
+ }
727
+ }
728
+ warmupBatch() {
729
+ if (typeof getComputedStyle !== 'function')
730
+ return;
731
+ const batch = [];
732
+ for (const child of this.itemChildren()) {
733
+ if (this.warmedItems.has(child))
734
+ continue;
735
+ this.warmedItems.add(child);
736
+ const style = getComputedStyle(child);
737
+ const contentVisibility = style.getPropertyValue('content-visibility').trim() || 'visible';
738
+ if (contentVisibility === 'auto')
739
+ batch.push(child);
740
+ if (batch.length >= WARMUP_BATCH_SIZE)
741
+ break;
742
+ }
743
+ if (batch.length === 0)
744
+ return;
745
+ for (const element of batch) {
746
+ element.style.contentVisibility = 'visible';
747
+ }
748
+ requestAnimationFrame(() => {
749
+ // Back to the stylesheet's `auto`; the rendered pass left a
750
+ // remembered intrinsic size behind.
751
+ for (const element of batch) {
752
+ element.style.contentVisibility = '';
753
+ }
754
+ this.scheduleWarmup();
755
+ });
756
+ }
757
+ cancelWarmup() {
758
+ if (this.warmupHandle === null)
759
+ return;
760
+ if (this.warmupUsesIdleCallback &&
761
+ typeof cancelIdleCallback === 'function') {
762
+ cancelIdleCallback(this.warmupHandle);
763
+ }
764
+ else {
765
+ clearTimeout(this.warmupHandle);
766
+ }
767
+ this.warmupHandle = null;
768
+ }
769
+ // MARK: - Helpers
770
+ flushPendingScrollToMessage() {
771
+ const pending = this.pendingScrollToMessage;
772
+ if (!pending)
773
+ return false;
774
+ const element = this.messageElements.get(pending.messageId);
775
+ if (!element || !this.scrollToElement(element, pending.options)) {
776
+ return false;
777
+ }
778
+ this.pendingScrollToMessage = null;
779
+ this.defaultPositionApplied = true;
780
+ return true;
781
+ }
782
+ setSpacerHeight(height) {
783
+ const spacer = this.spacer;
784
+ const next = Math.max(0, Math.ceil(height));
785
+ if (!spacer || this.spacerHeight === next)
786
+ return;
787
+ this.spacerHeight = next;
788
+ spacer.hidden = next === 0;
789
+ spacer.style.height = `${next}px`;
790
+ spacer.style.marginTop = next > 0 ? `${-this.spacerGap}px` : '';
791
+ }
792
+ itemChildren() {
793
+ const content = this.content;
794
+ if (!content)
795
+ return [];
796
+ return Array.from(content.children).filter((child) => child instanceof HTMLElement && child !== this.spacer);
797
+ }
798
+ isAtEnd() {
799
+ const viewport = this.viewport;
800
+ if (!viewport)
801
+ return true;
802
+ return isMessageScrollerAtEnd(viewport, this.options.scrollEdgeThreshold);
803
+ }
804
+ }
805
+ function maxScrollTop(viewport) {
806
+ return Math.max(0, viewport.scrollHeight - viewport.clientHeight);
807
+ }
808
+ function elementViewportTop(element, viewport) {
809
+ return (element.getBoundingClientRect().top - viewport.getBoundingClientRect().top);
810
+ }
811
+ function elementTopInContent(element, viewport) {
812
+ return elementViewportTop(element, viewport) + viewport.scrollTop;
813
+ }
814
+ function readBlockPadding(element) {
815
+ if (!element || typeof getComputedStyle !== 'function') {
816
+ return { start: 0, end: 0 };
817
+ }
818
+ const style = getComputedStyle(element);
819
+ return {
820
+ start: parsePx(style.paddingBlockStart || style.paddingTop),
821
+ end: parsePx(style.paddingBlockEnd || style.paddingBottom),
822
+ };
823
+ }
824
+ function parsePx(value) {
825
+ const parsed = Number.parseFloat(value || '0');
826
+ return Number.isFinite(parsed) ? parsed : 0;
827
+ }
828
+ /**
829
+ * The content-space bottom of the real transcript: the lowest item edge plus
830
+ * the content's own padding. Measured from items instead of the content box
831
+ * so the anchoring spacer never feeds back into its own requirement.
832
+ */
833
+ function contentBottomWithoutSpacer(viewport, content, items) {
834
+ const viewportRect = viewport.getBoundingClientRect();
835
+ const padding = readBlockPadding(content);
836
+ let bottom = padding.start + padding.end;
837
+ for (const item of items) {
838
+ const rect = item.getBoundingClientRect();
839
+ bottom = Math.max(bottom, rect.bottom - viewportRect.top + viewport.scrollTop + padding.end);
840
+ }
841
+ return bottom;
842
+ }
843
+ function alignedScrollTarget({ align, element, margin, padding, viewport, }) {
844
+ const top = elementTopInContent(element, viewport);
845
+ const height = element.getBoundingClientRect().height;
846
+ if (align === 'center') {
847
+ const available = Math.max(0, viewport.clientHeight - padding.start - padding.end);
848
+ return top - padding.start - (available - height) / 2 - margin;
849
+ }
850
+ if (align === 'end') {
851
+ return top - viewport.clientHeight + height + padding.end + margin;
852
+ }
853
+ if (align === 'nearest') {
854
+ const bottom = top + height;
855
+ const visibleTop = viewport.scrollTop + padding.start;
856
+ const visibleBottom = viewport.scrollTop + viewport.clientHeight - padding.end;
857
+ if (top >= visibleTop && bottom <= visibleBottom)
858
+ return viewport.scrollTop;
859
+ return top < visibleTop
860
+ ? top - padding.start - margin
861
+ : bottom - viewport.clientHeight + padding.end + margin;
862
+ }
863
+ return top - padding.start - margin;
864
+ }
865
+ function firstTurnAnchorAt(children, startIndex) {
866
+ for (let index = startIndex; index < children.length; index += 1) {
867
+ if (children[index]?.dataset.scrollAnchor === 'true') {
868
+ return children[index] ?? null;
869
+ }
870
+ }
871
+ return null;
872
+ }
873
+ function countTurnAnchorsAt(children, startIndex) {
874
+ let count = 0;
875
+ for (let index = startIndex; index < children.length; index += 1) {
876
+ if (children[index]?.dataset.scrollAnchor === 'true')
877
+ count += 1;
878
+ }
879
+ return count;
880
+ }
881
+ function readRowGap(element) {
882
+ if (!element || typeof getComputedStyle !== 'function')
883
+ return 0;
884
+ const style = getComputedStyle(element);
885
+ const gap = style.rowGap === 'normal' ? style.gap : style.rowGap;
886
+ const parsed = Number.parseFloat(gap || '0');
887
+ return Number.isFinite(parsed) ? parsed : 0;
888
+ }