@crewlethq/ui 0.31.1 → 0.33.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 (278) hide show
  1. package/README.md +151 -5
  2. package/dist/AccessDeniedCard/AccessDeniedCard.d.ts +5 -0
  3. package/dist/AccessDeniedCard/index.js +1 -5
  4. package/dist/AccessDeniedCard-QVNDMT46.css +8 -0
  5. package/dist/AppShell/index.js +4 -4
  6. package/dist/{AppShell-GCM4TDVY.css → AppShell-JTSEOA57.css} +3 -1
  7. package/dist/ArrangeGroup/ArrangeGroup.d.ts +16 -1
  8. package/dist/ArrangeGroup/index.d.ts +1 -1
  9. package/dist/ArrangeGroup/index.js +1 -1
  10. package/dist/{ArrangeGroup-GY5YMP6E.css → ArrangeGroup-KRWWOJKR.css} +43 -0
  11. package/dist/ArrangeList/index.js +2 -2
  12. package/dist/ArtifactBar/index.js +12 -12
  13. package/dist/{ArtifactBar-MLMJHWY6.css → ArtifactBar-C462VD4C.css} +8 -3
  14. package/dist/ArtifactCard/ArtifactCard.d.ts +19 -1
  15. package/dist/ArtifactCard/index.d.ts +1 -1
  16. package/dist/ArtifactCard/index.js +4 -4
  17. package/dist/{ArtifactCard-EXVAEBV6.css → ArtifactCard-AS5Z4CVI.css} +17 -2
  18. package/dist/ArtifactCover/index.js +6 -6
  19. package/dist/ArtifactIcon/index.js +5 -5
  20. package/dist/ArtifactPanel/ArtifactPanel.d.ts +6 -2
  21. package/dist/ArtifactPanel/index.js +1 -1
  22. package/dist/{ArtifactPanel-YFXT5O77.css → ArtifactPanel-HW3SU7CP.css} +25 -7
  23. package/dist/Avatar/Avatar.d.ts +6 -4
  24. package/dist/Avatar/index.js +2 -2
  25. package/dist/AvatarPicker/index.js +8 -8
  26. package/dist/Callout/index.js +1 -1
  27. package/dist/{Callout-SXXK4B5R.css → Callout-ZAVG3P66.css} +46 -6
  28. package/dist/Canvas/Canvas.d.ts +81 -4
  29. package/dist/Canvas/ShortcutTip.d.ts +22 -0
  30. package/dist/Canvas/geometry.d.ts +13 -3
  31. package/dist/Canvas/index.d.ts +4 -2
  32. package/dist/Canvas/index.js +5 -3
  33. package/dist/{Canvas-YVXHMWLN.css → Canvas-VUG2HLZK.css} +62 -3
  34. package/dist/CanvasBoard/CanvasBoard.d.ts +110 -12
  35. package/dist/CanvasBoard/budget.d.ts +9 -3
  36. package/dist/CanvasBoard/index.d.ts +2 -2
  37. package/dist/CanvasBoard/index.js +9 -5
  38. package/dist/CanvasBoard-5NNSKY6A.css +462 -0
  39. package/dist/CanvasToolbar/CanvasToolbar.d.ts +48 -0
  40. package/dist/CanvasToolbar/index.d.ts +3 -0
  41. package/dist/CanvasToolbar/index.js +12 -0
  42. package/dist/CanvasToolbar-EM5EVZED.css +34 -0
  43. package/dist/ChangeMark/index.js +4 -4
  44. package/dist/CharacterPicker/index.js +2 -2
  45. package/dist/Charts/ActivityStrip.d.ts +16 -1
  46. package/dist/Charts/BarList.d.ts +6 -0
  47. package/dist/Charts/ChartEmpty.d.ts +33 -0
  48. package/dist/Charts/Legend.d.ts +6 -0
  49. package/dist/Charts/StackedBar.d.ts +4 -1
  50. package/dist/Charts/StackedColumns.d.ts +14 -3
  51. package/dist/Charts/TimeSeries.d.ts +11 -1
  52. package/dist/Charts/index.d.ts +2 -0
  53. package/dist/Charts/index.js +1 -1
  54. package/dist/{Charts-RY4JN5FC.css → Charts-MBJG72BS.css} +140 -16
  55. package/dist/Checkbox/index.js +1 -1
  56. package/dist/{Checkbox-5UORUG3F.css → Checkbox-ALWG3WV2.css} +11 -0
  57. package/dist/CommandPalette/index.js +3 -3
  58. package/dist/{CommandPalette-HBTNKHZQ.css → CommandPalette-7CFGVBND.css} +4 -0
  59. package/dist/CommentThread/index.js +5 -5
  60. package/dist/Container/index.js +1 -1
  61. package/dist/{Container-3TSKMGNI.css → Container-34BAKG7B.css} +3 -1
  62. package/dist/{DashboardCover-RMINBODB.css → DashboardCover-KYGYMRKW.css} +42 -9
  63. package/dist/DataTable/index.js +5 -5
  64. package/dist/{DataTable-WZK3V62B.css → DataTable-NL2YWAIA.css} +4 -1
  65. package/dist/DataView/index.js +9 -9
  66. package/dist/DateTimePicker/index.js +3 -3
  67. package/dist/DocTabsEditor/DocTabsEditor.d.ts +34 -21
  68. package/dist/DocTabsEditor/index.js +4 -1
  69. package/dist/DocTabsEditor-4M452LNS.css +189 -0
  70. package/dist/Document/Document.d.ts +18 -1
  71. package/dist/Document/index.d.ts +2 -2
  72. package/dist/Document/index.js +1 -1
  73. package/dist/{Document-G3YTZIUL.css → Document-JUGCSQ4L.css} +78 -5
  74. package/dist/EditingStatus/index.js +1 -1
  75. package/dist/{EditingStatus-L6THUAN7.css → EditingStatus-NNA2CKIL.css} +17 -4
  76. package/dist/{Editor-YZ7KG2RD.js → Editor-UUZ7XKCU.js} +5 -5
  77. package/dist/EntityChip/index.js +3 -3
  78. package/dist/FactList/index.js +3 -3
  79. package/dist/FollowBanner/index.js +3 -3
  80. package/dist/Fullscreen/index.d.ts +1 -0
  81. package/dist/Fullscreen/index.js +1 -1
  82. package/dist/Fullscreen/useIdle.d.ts +16 -0
  83. package/dist/HuePicker/index.js +3 -3
  84. package/dist/ImageUpload/index.js +3 -3
  85. package/dist/Layer/index.d.ts +1 -1
  86. package/dist/Layer/index.js +1 -1
  87. package/dist/Layer/place.d.ts +18 -0
  88. package/dist/LayersList/LayersList.d.ts +57 -0
  89. package/dist/LayersList/index.d.ts +3 -0
  90. package/dist/LayersList/index.js +3 -0
  91. package/dist/LayersList-NQZEIPZB.css +82 -0
  92. package/dist/LinkInterstitial/index.js +4 -4
  93. package/dist/ListInput/index.js +1 -1
  94. package/dist/Markdown/index.js +1 -1
  95. package/dist/MarkdownEditor/index.js +5 -5
  96. package/dist/MediaMatch/index.d.ts +1 -0
  97. package/dist/MediaMatch/index.js +1 -0
  98. package/dist/MediaMatch/useMediaMatch.d.ts +19 -0
  99. package/dist/Menu/index.js +2 -2
  100. package/dist/MergeConflicts/index.js +4 -4
  101. package/dist/Modal/index.js +2 -2
  102. package/dist/{Modal-XOSV6FAH.css → Modal-7MWRCWAI.css} +30 -0
  103. package/dist/Note/index.js +1 -1
  104. package/dist/{Note-ONSKKTOA.css → Note-WI5MLZOO.css} +13 -0
  105. package/dist/OrgLabel/index.js +3 -3
  106. package/dist/OrgNode/index.js +4 -4
  107. package/dist/OrgTable/index.js +7 -7
  108. package/dist/PeopleRail/index.js +3 -3
  109. package/dist/Popover/index.js +2 -2
  110. package/dist/PresenceStack/index.js +3 -3
  111. package/dist/{PresenceStack-QSXQJND5.css → PresenceStack-FJJQVH74.css} +11 -3
  112. package/dist/PresenterView/PresenterView.d.ts +3 -0
  113. package/dist/PresenterView/index.js +5 -3
  114. package/dist/PresenterView-T3EXIQ5S.css +147 -0
  115. package/dist/Principal/index.js +3 -3
  116. package/dist/PrincipalPicker/index.js +4 -4
  117. package/dist/RichEditor/index.js +5 -5
  118. package/dist/RichEditor/schema.d.ts +1 -1
  119. package/dist/RichEditorMarkdown/index.js +3 -3
  120. package/dist/SandboxedFrame/SandboxedFrame.d.ts +44 -2
  121. package/dist/SandboxedFrame/index.d.ts +2 -2
  122. package/dist/SandboxedFrame/index.js +3 -3
  123. package/dist/SandboxedFrame-P5NASXB7.css +72 -0
  124. package/dist/Section/index.js +1 -1
  125. package/dist/{Section-QR3ILQVK.css → Section-O5AHGSOG.css} +28 -5
  126. package/dist/SegmentedControl/index.js +3 -3
  127. package/dist/Select/index.js +2 -2
  128. package/dist/ShareDialog/ShareDialog.d.ts +10 -0
  129. package/dist/ShareDialog/index.js +9 -9
  130. package/dist/{ShareDialog-YZ4F37MW.css → ShareDialog-4QDCBWMH.css} +12 -0
  131. package/dist/SheetGrid/SheetGrid.d.ts +3 -1
  132. package/dist/SheetGrid/index.js +10 -10
  133. package/dist/{SheetGrid-J3TKKXZL.css → SheetGrid-AKPUCK67.css} +106 -7
  134. package/dist/SheetModel/fit.d.ts +34 -0
  135. package/dist/SheetModel/index.d.ts +1 -0
  136. package/dist/SheetModel/index.js +1 -1
  137. package/dist/Shortcut/index.js +1 -1
  138. package/dist/Skeleton/Skeleton.d.ts +2 -1
  139. package/dist/Skeleton/index.js +1 -1
  140. package/dist/SlideCompare/SlideCompare.d.ts +6 -1
  141. package/dist/SlideCompare/index.js +3 -3
  142. package/dist/{SlideCompare-MGM3U2ME.css → SlideCompare-HTCMPQFY.css} +36 -3
  143. package/dist/SlideFilmstrip/SlideFilmstrip.d.ts +14 -3
  144. package/dist/SlideFilmstrip/index.js +3 -3
  145. package/dist/{SlideFilmstrip-BCLNAHFX.css → SlideFilmstrip-5U6Z55GS.css} +63 -2
  146. package/dist/SlideGrid/index.js +3 -3
  147. package/dist/{SlideGrid-RT6QEQEE.css → SlideGrid-S4LTJ4UU.css} +9 -5
  148. package/dist/SlideNav/SlideNav.d.ts +49 -0
  149. package/dist/SlideNav/index.d.ts +3 -0
  150. package/dist/SlideNav/index.js +4 -0
  151. package/dist/SlideNav-BLFJF6AH.css +53 -0
  152. package/dist/SlideStage/SlideStage.d.ts +14 -1
  153. package/dist/SlideStage/index.js +2 -2
  154. package/dist/{SlideStage-KGRRALXR.css → SlideStage-S2FISF4C.css} +23 -0
  155. package/dist/StatCard/StatCard.d.ts +16 -1
  156. package/dist/StatCard/index.js +1 -1
  157. package/dist/{StatCard-KPAFD4E2.css → StatCard-4T7TMWMN.css} +40 -13
  158. package/dist/Switcher/index.js +6 -6
  159. package/dist/TableCells/index.js +3 -3
  160. package/dist/Tabs/Tabs.d.ts +21 -4
  161. package/dist/Tabs/index.js +1 -1
  162. package/dist/{Tabs-CJGO35BH.css → Tabs-MMZXV5EF.css} +9 -8
  163. package/dist/TagsInput/index.js +1 -1
  164. package/dist/ThemeSwitcher/index.js +4 -4
  165. package/dist/TimeWindowPicker/index.js +4 -4
  166. package/dist/Toaster/index.js +2 -2
  167. package/dist/{Toaster-EOOOTSJT.css → Toaster-C6BQ7L6I.css} +10 -1
  168. package/dist/Toolbar/index.js +1 -1
  169. package/dist/Tooltip/index.js +2 -2
  170. package/dist/TreeCanvas/index.js +6 -4
  171. package/dist/TreeGrid/index.js +3 -3
  172. package/dist/VersionCompare/index.js +4 -4
  173. package/dist/VersionTimeline/index.js +4 -4
  174. package/dist/WidgetFrame/WidgetFrame.d.ts +8 -1
  175. package/dist/WidgetFrame/index.js +2 -2
  176. package/dist/{WidgetFrame-LRZIL62O.css → WidgetFrame-BTFW3CRK.css} +49 -5
  177. package/dist/{chunk-OJ45PPCV.js → chunk-22UEIXZE.js} +127 -32
  178. package/dist/{chunk-UZ6MA2V6.js → chunk-2DHMVB5J.js} +2 -2
  179. package/dist/{chunk-WJDQ7XQA.js → chunk-2QEDJSJC.js} +1 -1
  180. package/dist/{chunk-2HIOJ4YZ.js → chunk-3EB2AV3H.js} +2 -3
  181. package/dist/{chunk-ODT5H4MN.js → chunk-3LYWD3BO.js} +2 -2
  182. package/dist/{chunk-FAQGGX2Z.js → chunk-3TFDQLW3.js} +1 -1
  183. package/dist/{chunk-VYDFB6PJ.js → chunk-3U7S6ZUN.js} +50 -17
  184. package/dist/{chunk-A4E5YLXO.js → chunk-4B6LSFDS.js} +1 -1
  185. package/dist/{chunk-S6VG5ZFZ.js → chunk-4IJS5CPF.js} +1 -1
  186. package/dist/{chunk-UAN5NE7M.js → chunk-5AQBPHZD.js} +1 -1
  187. package/dist/{chunk-QWOPX2MN.js → chunk-5FYPE5GL.js} +2 -3
  188. package/dist/{chunk-CJKMURZO.js → chunk-5SZGKSGL.js} +1 -1
  189. package/dist/chunk-6VOS2GMB.js +54 -0
  190. package/dist/{chunk-RODMM35O.js → chunk-7Q7WDXHG.js} +5 -5
  191. package/dist/{chunk-JI5AVQLA.js → chunk-7WHDPLVJ.js} +1 -1
  192. package/dist/{chunk-QH3AKP2N.js → chunk-AC22RZKC.js} +2 -2
  193. package/dist/{chunk-ZITJKF6Z.js → chunk-AYB6AYNH.js} +1 -1
  194. package/dist/{chunk-Y5NQ2LMS.js → chunk-BY4N65PM.js} +1 -1
  195. package/dist/{chunk-YFW4MTK4.js → chunk-C7DKX453.js} +1 -1
  196. package/dist/{chunk-RCQXUT5K.js → chunk-CCAXYHQS.js} +1 -1
  197. package/dist/{chunk-4KP4RC3O.js → chunk-CI3VPIJN.js} +1 -1
  198. package/dist/{chunk-7T42VQQT.js → chunk-CPEPST4S.js} +1 -1
  199. package/dist/{chunk-AAOH2P6Y.js → chunk-DFK5EQTU.js} +5 -3
  200. package/dist/{chunk-GOSQXEZU.js → chunk-DFZMYB5X.js} +16 -10
  201. package/dist/{chunk-TGYDROIB.js → chunk-EBCHVFCS.js} +4 -4
  202. package/dist/{chunk-YDBC4DNW.js → chunk-FWYHRU7M.js} +1 -1
  203. package/dist/{chunk-CT4EZF62.js → chunk-G4ZW7A2W.js} +125 -33
  204. package/dist/chunk-GLSOD5Z4.js +33 -0
  205. package/dist/{chunk-LIXSV5YI.js → chunk-GPHWCK7M.js} +1 -1
  206. package/dist/{chunk-UQHKFF2N.js → chunk-GPWJCP3U.js} +1 -1
  207. package/dist/{chunk-77DRMDXR.js → chunk-HG5VF3TZ.js} +192 -67
  208. package/dist/{chunk-4JUKWWUD.js → chunk-HH2GKAAE.js} +1 -1
  209. package/dist/{chunk-QVE4GJAT.js → chunk-HJO4WCH6.js} +1 -1
  210. package/dist/{chunk-I3BSQUKN.js → chunk-HUVG2FFT.js} +1 -1
  211. package/dist/{chunk-3C3BRIMY.js → chunk-ILAEBSLJ.js} +3 -3
  212. package/dist/{chunk-GR55WT4R.js → chunk-IYO2N5ZH.js} +2 -2
  213. package/dist/{chunk-RWA4H2TV.js → chunk-J6ON5SYE.js} +1 -1
  214. package/dist/{chunk-NHBP2XS5.js → chunk-J6ZSH3F5.js} +49 -1
  215. package/dist/{chunk-AMNN4WDX.js → chunk-JBUMD6DS.js} +2 -2
  216. package/dist/{chunk-BWRGFKJP.js → chunk-K3IJQNB7.js} +2 -3
  217. package/dist/{chunk-LFNUH4GY.js → chunk-K4VP6ZKE.js} +1 -1
  218. package/dist/{chunk-ZR5VN5IV.js → chunk-KD2IRYCT.js} +2 -2
  219. package/dist/{chunk-SKOYC2CF.js → chunk-KK5OYNAF.js} +2 -1
  220. package/dist/{chunk-UB7TJEKZ.js → chunk-KV3ODJXH.js} +6 -7
  221. package/dist/chunk-LL5AFXU7.js +96 -0
  222. package/dist/{chunk-VYOKRN2I.js → chunk-LM3ISVJA.js} +1 -1
  223. package/dist/{chunk-O63MWA4G.js → chunk-LV4APO72.js} +10 -3
  224. package/dist/{chunk-B4EBHPK3.js → chunk-M5KZX5JE.js} +9 -2
  225. package/dist/{chunk-JODJS7MR.js → chunk-MDNVHIB2.js} +276 -47
  226. package/dist/{chunk-VOX3YRFO.js → chunk-MTMKIUWF.js} +4 -4
  227. package/dist/{chunk-HVNTQ36V.js → chunk-O37AQNLK.js} +4 -4
  228. package/dist/{chunk-HMPFGIWM.js → chunk-OMV5W53A.js} +10 -1
  229. package/dist/chunk-ONL54WMH.js +55 -0
  230. package/dist/{chunk-AKEZ3G5V.js → chunk-ONQKKHON.js} +1 -1
  231. package/dist/{chunk-LZHLSQYK.js → chunk-OOWPSBIS.js} +2 -2
  232. package/dist/{chunk-JQLTG4KH.js → chunk-ORT5IKHP.js} +62 -51
  233. package/dist/{chunk-4KWOKX2B.js → chunk-OSKJZNBT.js} +1 -1
  234. package/dist/{chunk-EHQTPVV4.js → chunk-PLTCDSTU.js} +1 -1
  235. package/dist/{chunk-5OM447RW.js → chunk-PZKHBB7D.js} +1 -1
  236. package/dist/{chunk-VEB5ERRE.js → chunk-QWNVSR6G.js} +2 -2
  237. package/dist/{chunk-IG75YMUN.js → chunk-RTPQDNW3.js} +1 -1
  238. package/dist/{chunk-SVSCLHHI.js → chunk-SZZRIHGT.js} +1 -1
  239. package/dist/{chunk-EBNI36UQ.js → chunk-T46NR3WP.js} +3 -3
  240. package/dist/{chunk-FPS3JIPQ.js → chunk-TC7DJTXI.js} +1 -1
  241. package/dist/{chunk-W5J7R5EB.js → chunk-TEUQWOWZ.js} +1 -1
  242. package/dist/chunk-THROPJZC.js +115 -0
  243. package/dist/{chunk-IDBHX5SR.js → chunk-TRQCHF2F.js} +1 -1
  244. package/dist/{chunk-M3LUNN7F.js → chunk-TYKQ33CL.js} +13 -2
  245. package/dist/{chunk-VVRL27HM.js → chunk-ULPL26BU.js} +2 -2
  246. package/dist/{chunk-6AH2XJ3Q.js → chunk-UNXLTJU7.js} +3 -3
  247. package/dist/{chunk-FC4YTTFJ.js → chunk-UQGFHNDI.js} +2 -3
  248. package/dist/{chunk-EBJREOKS.js → chunk-UXXJDIYE.js} +4 -4
  249. package/dist/{chunk-5LUI3WQP.js → chunk-V43UVX4H.js} +1 -1
  250. package/dist/{chunk-W4XYY73O.js → chunk-VHZ3AXJD.js} +1 -1
  251. package/dist/{chunk-HJEVSQN6.js → chunk-VL6CUNSX.js} +11 -5
  252. package/dist/{chunk-XDTYBF2F.js → chunk-W5XCNEZC.js} +39 -1
  253. package/dist/{chunk-LDJ3J4TQ.js → chunk-WGD2HX2A.js} +1 -1
  254. package/dist/{chunk-FQCLKD7U.js → chunk-WKEPORNM.js} +1 -1
  255. package/dist/{chunk-I3KKZ2O3.js → chunk-XEGZHHRH.js} +45 -36
  256. package/dist/{chunk-IKB6HFGK.js → chunk-XO7PUL4F.js} +6 -4
  257. package/dist/chunk-XV32RKQZ.js +142 -0
  258. package/dist/{chunk-TBMDMXEX.js → chunk-YA3AWELW.js} +1 -1
  259. package/dist/{chunk-HVIX5ECM.js → chunk-YEVG2X5R.js} +1 -1
  260. package/dist/chunk-YZFLH463.js +215 -0
  261. package/dist/{chunk-P4BOXB6E.js → chunk-Z6GFMI2Z.js} +6 -7
  262. package/dist/{chunk-YEKYVJQR.js → chunk-ZNBLFCQS.js} +2 -2
  263. package/dist/generated/index.d.ts +4 -0
  264. package/dist/generated/index.js +107 -104
  265. package/dist/index.js +107 -104
  266. package/dist/styles.css +1648 -235
  267. package/package.json +3 -3
  268. package/dist/AccessDeniedCard-WXM5DBDZ.css +0 -8
  269. package/dist/CanvasBoard-ZLPDINSM.css +0 -236
  270. package/dist/DocTabsEditor-RCOWHX5J.css +0 -78
  271. package/dist/PresenterView-T2C6ZZ3N.css +0 -103
  272. package/dist/SandboxedFrame-L6HBQZCD.css +0 -50
  273. package/dist/chunk-ALMSY7RL.js +0 -74
  274. package/dist/chunk-LR5QTFOE.js +0 -105
  275. package/dist/chunk-OGAAHVF6.js +0 -107
  276. package/dist/chunk-UZ7ZUSLH.js +0 -179
  277. package/dist/utils/useMediaMatch.d.ts +0 -12
  278. /package/dist/{chunk-OC46246T.js → chunk-2JJIN6JN.js} +0 -0
@@ -1,13 +1,29 @@
1
- import { LayerNodeBridge } from './chunk-VYOKRN2I.js';
2
- import { LAYER_REPOSITION_EVENT, LayerHost } from './chunk-HMPFGIWM.js';
1
+ import { LayerNodeBridge } from './chunk-LM3ISVJA.js';
2
+ import { Kbd } from './chunk-SMBKXWML.js';
3
+ import { Tooltip } from './chunk-5FYPE5GL.js';
4
+ import { LAYER_REPOSITION_EVENT, LayerHost } from './chunk-OMV5W53A.js';
3
5
  import { Button } from './chunk-OG6CL3EB.js';
4
6
  import { IconButton } from './chunk-4FQT6ZAY.js';
5
7
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
6
8
  import { cx } from './chunk-ODEQTPFM.js';
7
- import './Canvas-YVXHMWLN.css';
9
+ import './Canvas-VUG2HLZK.css';
8
10
  import { useId, useRef, useState, useCallback, useLayoutEffect, useImperativeHandle, useEffect } from 'react';
9
- import { ZoomOutGlyph, ZoomInGlyph, FullscreenGlyph } from '@crewlethq/icons/glyphs';
10
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
11
+ import { CURSORS, ZoomOutGlyph, ZoomInGlyph, FullscreenGlyph } from '@crewlethq/icons/glyphs';
12
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
13
+
14
+ function ShortcutTip({ label, keys, placement = "top", children }) {
15
+ return /* @__PURE__ */ jsx(
16
+ Tooltip,
17
+ {
18
+ placement,
19
+ content: /* @__PURE__ */ jsxs("span", { className: "crewlet-shortcut-tip", children: [
20
+ label,
21
+ /* @__PURE__ */ jsx(Kbd, { keys, subtle: true })
22
+ ] }),
23
+ children
24
+ }
25
+ );
26
+ }
11
27
 
12
28
  // src/Canvas/geometry.ts
13
29
  var IDENTITY_VIEW = { x: 0, y: 0, k: 1 };
@@ -26,9 +42,9 @@ var CANVAS_REVEAL_PADDING = 24;
26
42
  var CANVAS_PAN_STEP = 64;
27
43
  var CANVAS_TAP_SLOP = { mouse: 4, pen: 4, touch: 10 };
28
44
  var CANVAS_ZOOM_LIMITS = { min: CANVAS_MIN_ZOOM, max: CANVAS_MAX_ZOOM };
29
- function zoomLimits(content, viewport, largestItem, padding = CANVAS_FIT_PADDING) {
45
+ function zoomLimits(content, viewport, largestItem, padding = CANVAS_FIT_PADDING, floor = CANVAS_MIN_ZOOM) {
30
46
  const measured = content !== null && viewport.width > 0 && viewport.height > 0;
31
- const min = measured ? fitView(content, viewport, padding).k : CANVAS_MIN_ZOOM;
47
+ const min = measured ? fitView(content, viewport, padding, floor).k : floor;
32
48
  const room = viewport.width - 2 * padding;
33
49
  const wanted = largestItem !== void 0 && largestItem > 0 && room > 0 ? room / largestItem : CANVAS_MAX_ZOOM;
34
50
  const max = Math.min(CANVAS_ZOOM_CEILING, Math.max(CANVAS_MAX_ZOOM, wanted));
@@ -73,13 +89,13 @@ function clampPan(view, content, viewport, margin = CANVAS_PAN_MARGIN) {
73
89
  k: view.k
74
90
  };
75
91
  }
76
- function fitView(content, viewport, padding = CANVAS_FIT_PADDING) {
92
+ function fitView(content, viewport, padding = CANVAS_FIT_PADDING, floor = CANVAS_MIN_ZOOM) {
77
93
  if (viewport.width <= 0 || viewport.height <= 0) return IDENTITY_VIEW;
78
94
  const roomX = Math.max(0, viewport.width - 2 * padding);
79
95
  const roomY = Math.max(0, viewport.height - 2 * padding);
80
96
  const scaleX = content.width > 0 ? roomX / content.width : Infinity;
81
97
  const scaleY = content.height > 0 ? roomY / content.height : Infinity;
82
- const k = Math.max(CANVAS_MIN_ZOOM, Math.min(CANVAS_FIT_MAX_ZOOM, scaleX, scaleY));
98
+ const k = Math.max(floor, Math.min(CANVAS_FIT_MAX_ZOOM, scaleX, scaleY));
83
99
  const drawnHeight = content.height * k;
84
100
  const x = (viewport.width - content.width * k) / 2 - content.x * k;
85
101
  const y = drawnHeight <= roomY ? (viewport.height - drawnHeight) / 2 - content.y * k : padding - content.y * k;
@@ -145,10 +161,11 @@ var LABELS = {
145
161
  zoomIn: "Zoom in",
146
162
  zoomOut: "Zoom out",
147
163
  fit: "Fit to view",
164
+ actualSize: "Zoom to 100%",
148
165
  zoom: (percent) => `Zoom is ${percent} percent. Set a zoom level`,
149
166
  zoomLevel: "Zoom level, percent",
150
167
  done: "Done",
151
- keys: "Plus and minus zoom this canvas and zero fits everything in view. With the canvas itself focused, the arrow keys pan it."
168
+ keys: "Plus and minus zoom this canvas, zero or Shift 1 fits everything in view, and Shift 0 shows it at actual size. With the canvas itself focused, the arrow keys pan it."
152
169
  };
153
170
  var INTERACTIVE = "button, a[href], input, select, textarea, [contenteditable='true'], label";
154
171
  var TYPING = "input, textarea, select, [contenteditable='true']";
@@ -160,11 +177,15 @@ function Canvas({
160
177
  controls = true,
161
178
  controlsPlacement = "bottom-right",
162
179
  controlsExtra,
180
+ controlsActualSize = false,
163
181
  controlsBelow,
164
182
  hint,
165
183
  largestItemWidth,
166
184
  dimmed = false,
167
185
  ground = "plain",
186
+ minZoom = CANVAS_MIN_ZOOM,
187
+ cursor = "hand",
188
+ refitOnResize = false,
168
189
  touch = true,
169
190
  labels,
170
191
  onReady,
@@ -190,10 +211,17 @@ function Canvas({
190
211
  contentNow.current = content;
191
212
  touchNow.current = touchActive;
192
213
  sizeNow.current = size;
193
- const limits = zoomLimits(content, size, largestItemWidth);
214
+ const limits = zoomLimits(content, size, largestItemWidth, CANVAS_FIT_PADDING, minZoom);
194
215
  const limitsNow = useRef(limits);
195
216
  limitsNow.current = limits;
217
+ const floorNow = useRef(minZoom);
218
+ floorNow.current = minZoom;
219
+ const fitOf = useCallback(
220
+ (bounds, viewportSize = sizeNow.current) => fitView(bounds, viewportSize, CANVAS_FIT_PADDING, floorNow.current),
221
+ []
222
+ );
196
223
  const left = useRef(null);
224
+ const fitted = useRef(null);
197
225
  const apply = useCallback((next, eased) => {
198
226
  const bounds = contentNow.current;
199
227
  const clamped = bounds ? clampPan(next, bounds, sizeNow.current) : next;
@@ -203,6 +231,13 @@ function Canvas({
203
231
  viewNow.current = clamped;
204
232
  setView(clamped);
205
233
  }, []);
234
+ const fitNow = useCallback(
235
+ (bounds) => {
236
+ apply(fitOf(bounds), "near");
237
+ fitted.current = viewNow.current;
238
+ },
239
+ [apply, fitOf]
240
+ );
206
241
  useLayoutEffect(() => {
207
242
  const el = viewport.current;
208
243
  if (!el || typeof ResizeObserver === "undefined") return;
@@ -217,15 +252,29 @@ function Canvas({
217
252
  announceReady.current = onReady;
218
253
  useLayoutEffect(() => {
219
254
  if (ready || !content || size.width <= 0 || size.height <= 0) return;
220
- const first = fitView(content, size);
255
+ const first = fitOf(content, size);
221
256
  viewNow.current = first;
257
+ fitted.current = first;
222
258
  setView(first);
223
259
  setReady(true);
224
260
  announceReady.current?.();
225
- }, [ready, content, size]);
261
+ }, [ready, content, size, fitOf]);
262
+ const sizeSeen = useRef(size);
226
263
  useLayoutEffect(() => {
227
- if (ready) apply(viewNow.current);
228
- }, [ready, size, content, apply]);
264
+ if (!ready) return;
265
+ const resized = sizeSeen.current.width !== size.width || sizeSeen.current.height !== size.height;
266
+ sizeSeen.current = size;
267
+ const was = fitted.current;
268
+ const now = viewNow.current;
269
+ const untouched = was !== null && was.x === now.x && was.y === now.y && was.k === now.k;
270
+ if (refitOnResize && resized && untouched && content) {
271
+ apply(fitOf(content), false);
272
+ fitted.current = viewNow.current;
273
+ } else {
274
+ apply(now);
275
+ if (untouched) fitted.current = viewNow.current;
276
+ }
277
+ }, [ready, size, content, apply, fitOf, refitOnResize]);
229
278
  const reportView = useRef(onViewChange);
230
279
  reportView.current = onViewChange;
231
280
  useLayoutEffect(() => {
@@ -239,17 +288,26 @@ function Canvas({
239
288
  setAnimate(false);
240
289
  layer?.dispatchEvent(new CustomEvent(LAYER_REPOSITION_EVENT, { detail: viewNow.current }));
241
290
  };
291
+ const local = useCallback((event) => {
292
+ const rect = viewport.current?.getBoundingClientRect();
293
+ return { x: event.clientX - (rect?.left ?? 0), y: event.clientY - (rect?.top ?? 0) };
294
+ }, []);
242
295
  useImperativeHandle(
243
296
  ref,
244
297
  () => ({
245
298
  fit: () => {
246
299
  const bounds = contentNow.current;
247
- if (bounds) apply(fitView(bounds, sizeNow.current), "near");
300
+ if (bounds) fitNow(bounds);
248
301
  },
249
302
  zoomBy: (factor) => {
250
303
  const { width, height } = sizeNow.current;
251
304
  apply(zoomAt(viewNow.current, factor, { x: width / 2, y: height / 2 }, limitsNow.current), "near");
252
305
  },
306
+ zoomTo: (scale) => {
307
+ const { width, height } = sizeNow.current;
308
+ const factor = scale / viewNow.current.k;
309
+ apply(zoomAt(viewNow.current, factor, { x: width / 2, y: height / 2 }, limitsNow.current), "near");
310
+ },
253
311
  reveal: (target) => {
254
312
  const next = revealView(viewNow.current, target, sizeNow.current);
255
313
  if (next.x !== viewNow.current.x || next.y !== viewNow.current.y) apply(next, "near");
@@ -268,9 +326,10 @@ function Canvas({
268
326
  left.current = null;
269
327
  apply(was, "travel");
270
328
  },
271
- screenRect: (target) => screenRect(viewNow.current, target)
329
+ screenRect: (target) => screenRect(viewNow.current, target),
330
+ worldAt: (client) => toWorld(viewNow.current, local({ clientX: client.x, clientY: client.y }))
272
331
  }),
273
- [apply]
332
+ [apply, fitNow, local]
274
333
  );
275
334
  useEffect(() => {
276
335
  const el = viewport.current;
@@ -294,10 +353,6 @@ function Canvas({
294
353
  }, [apply]);
295
354
  const pointers = useRef(/* @__PURE__ */ new Map());
296
355
  const gesture = useRef(null);
297
- const local = useCallback((event) => {
298
- const rect = viewport.current?.getBoundingClientRect();
299
- return { x: event.clientX - (rect?.left ?? 0), y: event.clientY - (rect?.top ?? 0) };
300
- }, []);
301
356
  const endGesture = useCallback(() => {
302
357
  gesture.current = null;
303
358
  setPanning(false);
@@ -411,12 +466,17 @@ function Canvas({
411
466
  const { width, height } = sizeNow.current;
412
467
  const centre = { x: width / 2, y: height / 2 };
413
468
  let handled = true;
414
- if (event.key === "+" || mod && event.key === "=") {
469
+ const shiftDigit = event.shiftKey && !mod && !event.altKey ? event.code : "";
470
+ if (shiftDigit === "Digit0") {
471
+ centreZoom(1 / viewNow.current.k);
472
+ } else if (shiftDigit === "Digit1") {
473
+ if (content) fitNow(content);
474
+ } else if (event.key === "+" || mod && event.key === "=") {
415
475
  apply(zoomAt(viewNow.current, CANVAS_ZOOM_STEP, centre, limitsNow.current), "near");
416
476
  } else if (event.key === "-") {
417
477
  apply(zoomAt(viewNow.current, 1 / CANVAS_ZOOM_STEP, centre, limitsNow.current), "near");
418
478
  } else if (event.key === "0") {
419
- if (content) apply(fitView(content, sizeNow.current), "near");
479
+ if (content) fitNow(content);
420
480
  } else if (!onViewport) {
421
481
  handled = false;
422
482
  } else if (!mod && !event.altKey && event.key.startsWith("Arrow")) {
@@ -455,6 +515,8 @@ function Canvas({
455
515
  {
456
516
  className: cx("crewlet-canvas", className),
457
517
  ref: root,
518
+ style: ground === "grid" ? { ...CURSOR_PROPERTIES, ...gridProperties(view) } : CURSOR_PROPERTIES,
519
+ "data-cursor": cursor,
458
520
  "data-dimmed": dimmed,
459
521
  "data-ground": ground,
460
522
  "data-ready": ready,
@@ -501,16 +563,17 @@ function Canvas({
501
563
  (controls || touchActive) && /* @__PURE__ */ jsxs("div", { className: "crewlet-canvas__bar", children: [
502
564
  touchActive && /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", onClick: () => setTouchActive(false), children: text.done }),
503
565
  controls && /* @__PURE__ */ jsxs(Fragment, { children: [
504
- /* @__PURE__ */ jsx(
566
+ /* @__PURE__ */ jsx(ShortcutTip, { label: text.zoomOut, keys: ["-"], children: /* @__PURE__ */ jsx(
505
567
  IconButton,
506
568
  {
507
569
  size: "sm",
508
570
  label: text.zoomOut,
571
+ title: "",
509
572
  icon: /* @__PURE__ */ jsx(ZoomOutGlyph, {}),
510
573
  onClick: () => centreZoom(1 / CANVAS_ZOOM_STEP),
511
574
  disabled: !ready
512
575
  }
513
- ),
576
+ ) }),
514
577
  /* @__PURE__ */ jsx(
515
578
  ZoomReadout,
516
579
  {
@@ -521,26 +584,39 @@ function Canvas({
521
584
  disabled: !ready
522
585
  }
523
586
  ),
524
- /* @__PURE__ */ jsx(
587
+ /* @__PURE__ */ jsx(ShortcutTip, { label: text.zoomIn, keys: ["+"], children: /* @__PURE__ */ jsx(
525
588
  IconButton,
526
589
  {
527
590
  size: "sm",
528
591
  label: text.zoomIn,
592
+ title: "",
529
593
  icon: /* @__PURE__ */ jsx(ZoomInGlyph, {}),
530
594
  onClick: () => centreZoom(CANVAS_ZOOM_STEP),
531
595
  disabled: !ready
532
596
  }
533
- ),
534
- /* @__PURE__ */ jsx(
597
+ ) }),
598
+ controlsActualSize && /* @__PURE__ */ jsx(ShortcutTip, { label: text.actualSize, keys: ["Shift", "0"], children: /* @__PURE__ */ jsx(
599
+ "button",
600
+ {
601
+ type: "button",
602
+ className: "crewlet-canvas__zoom crewlet-canvas__actual",
603
+ "aria-label": text.actualSize,
604
+ onClick: () => centreZoom(1 / viewNow.current.k),
605
+ disabled: !ready,
606
+ children: "1:1"
607
+ }
608
+ ) }),
609
+ /* @__PURE__ */ jsx(ShortcutTip, { label: text.fit, keys: ["Shift", "1"], children: /* @__PURE__ */ jsx(
535
610
  IconButton,
536
611
  {
537
612
  size: "sm",
538
613
  label: text.fit,
614
+ title: "",
539
615
  icon: /* @__PURE__ */ jsx(FullscreenGlyph, {}),
540
- onClick: () => content && apply(fitView(content, sizeNow.current), "near"),
616
+ onClick: () => content && fitNow(content),
541
617
  disabled: !ready
542
618
  }
543
- ),
619
+ ) }),
544
620
  controlsExtra
545
621
  ] })
546
622
  ] }),
@@ -552,6 +628,25 @@ function Canvas({
552
628
  }
553
629
  );
554
630
  }
631
+ function gridOf(view) {
632
+ const k = view.k > 0 && Number.isFinite(view.k) ? view.k : 1;
633
+ return { scale: k * 2 ** -Math.floor(Math.log2(k)), x: view.x, y: view.y };
634
+ }
635
+ var CURSOR_PROPERTIES = {
636
+ "--crewlet-canvas-cursor-pointer": CURSORS.pointer,
637
+ "--crewlet-canvas-cursor-hand": CURSORS.hand,
638
+ "--crewlet-canvas-cursor-grabbing": CURSORS.grabbing,
639
+ "--crewlet-canvas-cursor-crosshair": CURSORS.crosshair,
640
+ "--crewlet-canvas-cursor-text": CURSORS.text
641
+ };
642
+ function gridProperties(view) {
643
+ const grid = gridOf(view);
644
+ return {
645
+ "--crewlet-canvas-grid-scale": String(grid.scale),
646
+ "--crewlet-canvas-grid-x": `${grid.x}px`,
647
+ "--crewlet-canvas-grid-y": `${grid.y}px`
648
+ };
649
+ }
555
650
  function ZoomReadout({
556
651
  zoom,
557
652
  onZoom,
@@ -633,4 +728,4 @@ function swallowNextClick(within) {
633
728
  setTimeout(() => window.removeEventListener("click", swallow, { capture: true }), 0);
634
729
  }
635
730
 
636
- export { CANVAS_COMPOSE_CONTEXT, CANVAS_FIT_MAX_ZOOM, CANVAS_FIT_PADDING, CANVAS_FOCUS_CONTEXT, CANVAS_MAX_ZOOM, CANVAS_MIN_ZOOM, CANVAS_PAN_MARGIN, CANVAS_PAN_STEP, CANVAS_REVEAL_PADDING, CANVAS_TAP_SLOP, CANVAS_WHEEL_LINE_PX, CANVAS_WHEEL_ZOOM_PER_PIXEL, CANVAS_ZOOM_CEILING, CANVAS_ZOOM_LIMITS, CANVAS_ZOOM_STEP, Canvas, IDENTITY_VIEW, anchorView, beyondSlop, clampPan, clampZoom, fitView, panBy, pinchView, regionView, revealView, screenRect, toScreen, toWorld, wheelPixels, wheelZoomFactor, zoomAt, zoomLimits };
731
+ export { CANVAS_COMPOSE_CONTEXT, CANVAS_FIT_MAX_ZOOM, CANVAS_FIT_PADDING, CANVAS_FOCUS_CONTEXT, CANVAS_MAX_ZOOM, CANVAS_MIN_ZOOM, CANVAS_PAN_MARGIN, CANVAS_PAN_STEP, CANVAS_REVEAL_PADDING, CANVAS_TAP_SLOP, CANVAS_WHEEL_LINE_PX, CANVAS_WHEEL_ZOOM_PER_PIXEL, CANVAS_ZOOM_CEILING, CANVAS_ZOOM_LIMITS, CANVAS_ZOOM_STEP, Canvas, IDENTITY_VIEW, ShortcutTip, anchorView, beyondSlop, clampPan, clampZoom, fitView, gridOf, panBy, pinchView, regionView, revealView, screenRect, toScreen, toWorld, wheelPixels, wheelZoomFactor, zoomAt, zoomLimits };
@@ -1,5 +1,5 @@
1
- import { Select } from './chunk-FC4YTTFJ.js';
2
- import { Popover } from './chunk-BWRGFKJP.js';
1
+ import { Select } from './chunk-UQGFHNDI.js';
2
+ import { Popover } from './chunk-K3IJQNB7.js';
3
3
  import { today, shiftMonth, CalendarGrid, compareDays } from './chunk-GXQ3B46I.js';
4
4
  import { Input } from './chunk-6QFAK2WV.js';
5
5
  import { isComposing } from './chunk-R25RGPUB.js';
@@ -1,5 +1,5 @@
1
1
  import { useThemePreference, useDensityPreference } from './chunk-Z24ZUSTX.js';
2
- import { SegmentedControl } from './chunk-RCQXUT5K.js';
2
+ import { SegmentedControl } from './chunk-CCAXYHQS.js';
3
3
  import { SunGlyph, MonitorGlyph, MoonGlyph } from '@crewlethq/icons/glyphs';
4
4
  import { jsx } from 'react/jsx-runtime';
5
5
 
@@ -1,4 +1,4 @@
1
- import { useLayerContainer, viewportBounds, LAYER_GAP, outsideBounds, placePopup, LAYER_REPOSITION_EVENT } from './chunk-HMPFGIWM.js';
1
+ import { useLayerContainer, viewportBounds, LAYER_GAP, anchorGone, placePopup, LAYER_REPOSITION_EVENT } from './chunk-OMV5W53A.js';
2
2
  import { usePopupLayer } from './chunk-R25RGPUB.js';
3
3
  import { Button } from './chunk-OG6CL3EB.js';
4
4
  import { IconButton } from './chunk-4FQT6ZAY.js';
@@ -99,14 +99,13 @@ function Menu({
99
99
  width: rect.width,
100
100
  height: rect.height
101
101
  };
102
- const whole = { x: 0, y: 0, width: host.width, height: host.height };
103
102
  const bounds = {
104
103
  x: LAYER_GAP,
105
104
  y: LAYER_GAP,
106
105
  width: host.width - 2 * LAYER_GAP,
107
106
  height: host.height - 2 * LAYER_GAP
108
107
  };
109
- if (outsideBounds(local, whole)) {
108
+ if (anchorGone(rect, host, inHost)) {
110
109
  close(true);
111
110
  return;
112
111
  }
@@ -1,9 +1,9 @@
1
1
  import { presenceHueClass } from './chunk-I6POAB4V.js';
2
2
  import { presenceLabels, presenceOrder } from './chunk-Z7JYG5TF.js';
3
- import { AVATAR_SIZES, Avatar } from './chunk-5OM447RW.js';
3
+ import { AVATAR_SIZES, Avatar } from './chunk-PZKHBB7D.js';
4
4
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
5
5
  import { cx } from './chunk-ODEQTPFM.js';
6
- import './PresenceStack-QSXQJND5.css';
6
+ import './PresenceStack-FJJQVH74.css';
7
7
  import { isCrewletCharacter } from '@crewlethq/icons/characters';
8
8
  import { jsxs, jsx } from 'react/jsx-runtime';
9
9
 
@@ -1,6 +1,6 @@
1
1
  import { useHeadingLevel, headingTag, HeadingLevelProvider, nextHeadingLevel } from './chunk-PQADV6P6.js';
2
2
  import { cx } from './chunk-ODEQTPFM.js';
3
- import './Section-QR3ILQVK.css';
3
+ import './Section-O5AHGSOG.css';
4
4
  import { useId } from 'react';
5
5
  import { jsxs, jsx } from 'react/jsx-runtime';
6
6
 
@@ -1,25 +1,26 @@
1
- import { Skeleton } from './chunk-W5J7R5EB.js';
1
+ import { Skeleton } from './chunk-TEUQWOWZ.js';
2
2
  import { frameThemeMessage, readFrameHello, frameOriginMatches, negotiateBridge, FRAME_MESSAGE, portTargetOrigin, checkFrameSandbox, httpOrigin, isFrameNonce, frameFragment, readOpenLink, externalUrl, isFocusExit } from './chunk-F6V2PTN6.js';
3
- import { Callout } from './chunk-SVSCLHHI.js';
3
+ import { Callout } from './chunk-SZZRIHGT.js';
4
4
  import { Button } from './chunk-OG6CL3EB.js';
5
5
  import { cx } from './chunk-ODEQTPFM.js';
6
- import './SandboxedFrame-L6HBQZCD.css';
6
+ import './SandboxedFrame-P5NASXB7.css';
7
7
  import { useState, useMemo, useRef, useEffect } from 'react';
8
8
  import { jsx, jsxs } from 'react/jsx-runtime';
9
9
 
10
10
  var LABELS = {
11
11
  loading: (title) => `Loading ${title}`,
12
- failed: "This page failed to load.",
12
+ failed: "This page failed to load",
13
13
  failedDetail: "It did not finish starting. Reload it, and if it fails again, ask its owner to republish it.",
14
- navigated: "This page left its frame, so it was closed.",
14
+ navigated: "This page left its frame, so it was closed",
15
15
  navigatedDetail: "An artifact may only show its own pages. Reload it to open it again.",
16
- refused: "This page cannot be shown safely.",
16
+ refused: "This page cannot be shown safely",
17
17
  refusedDetail: "It arrived with a frame policy this dashboard does not accept.",
18
- outdated: "This page needs a newer dashboard.",
18
+ outdated: "This page needs a newer dashboard",
19
19
  outdatedDetail: "Reload the dashboard to update it, then open the page again.",
20
20
  reload: "Reload"
21
21
  };
22
22
  var FRAME_HELLO_TIMEOUT_MS = 1e4;
23
+ var FRAME_LOAD_GRACE_MS = 1500;
23
24
  function framePolicy(src, origin, mode, sandbox, nonce, theme) {
24
25
  const verdict = checkFrameSandbox(sandbox, mode);
25
26
  if (!verdict.ok) return { ok: false, refusal: { kind: "sandbox", tokens: verdict.refused } };
@@ -54,6 +55,7 @@ function FrameInstance(props) {
54
55
  onRefusal: _onRefusal,
55
56
  onReload,
56
57
  helloTimeoutMs = FRAME_HELLO_TIMEOUT_MS,
58
+ loadGraceMs = FRAME_LOAD_GRACE_MS,
57
59
  labels,
58
60
  className,
59
61
  ...rest
@@ -168,7 +170,7 @@ function FrameInstance(props) {
168
170
  }
169
171
  owed = true;
170
172
  clearTimeout(loadTimer);
171
- loadTimer = setTimeout(() => end(greeted > 0 ? "navigated" : "failed"), helloTimeoutMs);
173
+ loadTimer = setTimeout(() => end(greeted > 0 ? "navigated" : "failed"), Math.min(helloTimeoutMs, loadGraceMs));
172
174
  };
173
175
  window.addEventListener("message", onWindowMessage);
174
176
  frame.addEventListener("load", onLoad);
@@ -183,7 +185,7 @@ function FrameInstance(props) {
183
185
  clearTimeout(loadTimer);
184
186
  closePort();
185
187
  };
186
- }, [policy, mode, nonce, helloTimeoutMs]);
188
+ }, [policy, mode, nonce, helloTimeoutMs, loadGraceMs]);
187
189
  const { mode: themeMode, palette, density } = theme;
188
190
  useEffect(() => {
189
191
  portRef.current?.postMessage(frameThemeMessage({ mode: themeMode, palette, density }));
@@ -216,17 +218,15 @@ function FrameInstance(props) {
216
218
  ...credentialless
217
219
  }
218
220
  ) : null,
219
- state === "loading" ? /* @__PURE__ */ jsx("div", { className: "crewlet-sandboxed-frame__loading", children: /* @__PURE__ */ jsx(Skeleton, { variant: "box", width: "100%", height: "100%", label: text.loading(title) }) }) : null,
220
- ending ? /* @__PURE__ */ jsx("div", { className: "crewlet-sandboxed-frame__end", children: /* @__PURE__ */ jsx(
221
- Callout,
221
+ state === "loading" ? /* @__PURE__ */ jsx(FrameLoading, { label: text.loading(title) }) : null,
222
+ ending ? /* @__PURE__ */ jsx(
223
+ FrameEnd,
222
224
  {
223
- variant: "danger",
224
- title: text[ending.title],
225
- live: "polite",
225
+ heading: text[ending.title],
226
226
  action: onReload ? /* @__PURE__ */ jsx(Button, { variant: "outline", size: "small", onClick: onReload, children: text.reload }) : void 0,
227
227
  children: text[ending.detail]
228
228
  }
229
- ) }) : null
229
+ ) : null
230
230
  ]
231
231
  }
232
232
  );
@@ -239,5 +239,38 @@ var END_TEXT = {
239
239
  refused: { title: "refused", detail: "refusedDetail" },
240
240
  outdated: { title: "outdated", detail: "outdatedDetail" }
241
241
  };
242
+ function FrameLoading({ label }) {
243
+ return /* @__PURE__ */ jsx("div", { className: "crewlet-sandboxed-frame__loading", children: /* @__PURE__ */ jsx(
244
+ Skeleton,
245
+ {
246
+ variant: "box",
247
+ width: "100%",
248
+ height: "100%",
249
+ marginTop: 0,
250
+ borderRadius: "var(--radius-md)",
251
+ label
252
+ }
253
+ ) });
254
+ }
255
+ function FrameEnd({ heading, action, children }) {
256
+ return /* @__PURE__ */ jsx("div", { className: "crewlet-sandboxed-frame__end", children: /* @__PURE__ */ jsx(Callout, { variant: "danger", title: heading, live: "polite", action, children }) });
257
+ }
258
+ function SandboxedFramePlaceholder({ title, label, className, ...rest }) {
259
+ return /* @__PURE__ */ jsx(
260
+ "div",
261
+ {
262
+ ...rest,
263
+ role: "region",
264
+ "aria-label": title,
265
+ "aria-busy": true,
266
+ "data-state": "loading",
267
+ className: cx("crewlet-sandboxed-frame", className),
268
+ children: /* @__PURE__ */ jsx(FrameLoading, { label: label ?? LABELS.loading(title) })
269
+ }
270
+ );
271
+ }
272
+ function SandboxedFrameNotice({ title, heading, action, children, className, ...rest }) {
273
+ return /* @__PURE__ */ jsx("div", { ...rest, role: "region", "aria-label": title, "data-state": "failed", className: cx("crewlet-sandboxed-frame", className), children: /* @__PURE__ */ jsx(FrameEnd, { heading, action, children }) });
274
+ }
242
275
 
243
- export { FRAME_HELLO_TIMEOUT_MS, SandboxedFrame };
276
+ export { FRAME_HELLO_TIMEOUT_MS, FRAME_LOAD_GRACE_MS, SandboxedFrame, SandboxedFrameNotice, SandboxedFramePlaceholder };
@@ -1,4 +1,4 @@
1
- import { MARKDOWN_CALLOUT_NAMES } from './chunk-SKOYC2CF.js';
1
+ import { MARKDOWN_CALLOUT_NAMES } from './chunk-KK5OYNAF.js';
2
2
 
3
3
  // src/RichEditor/types.ts
4
4
  var RICH_EDITOR_LABELS = {
@@ -1,5 +1,5 @@
1
1
  import { useTreeState, useMeasuredSizes, layoutForest, treeAncestors, useLayoutAnchor, treeExpandable, layoutConnectors, treeItemAction, treeStep, treePosInSet, treeSetSize, treeLevel, placeGroups } from './chunk-MY374UUD.js';
2
- import { CANVAS_COMPOSE_CONTEXT, CANVAS_FIT_MAX_ZOOM, Canvas } from './chunk-OJ45PPCV.js';
2
+ import { CANVAS_COMPOSE_CONTEXT, CANVAS_FIT_MAX_ZOOM, Canvas } from './chunk-22UEIXZE.js';
3
3
  import { focusables } from './chunk-R25RGPUB.js';
4
4
  import { cx } from './chunk-ODEQTPFM.js';
5
5
  import './TreeCanvas-L2XYONWL.css';
@@ -1,4 +1,4 @@
1
- import { AVATAR_SIZES, Avatar } from './chunk-5OM447RW.js';
1
+ import { AVATAR_SIZES, Avatar } from './chunk-PZKHBB7D.js';
2
2
  import { cx } from './chunk-ODEQTPFM.js';
3
3
  import './Avatar-3C2H2WA4.css';
4
4
  import './AvatarStack-GEJBNV7E.css';
@@ -1,4 +1,4 @@
1
- import { useLayerContainer, viewportBounds, LAYER_GAP, outsideBounds, placePopup, LAYER_REPOSITION_EVENT } from './chunk-HMPFGIWM.js';
1
+ import { useLayerContainer, viewportBounds, LAYER_GAP, anchorGone, placePopup, LAYER_REPOSITION_EVENT } from './chunk-OMV5W53A.js';
2
2
  import { usePopupLayer } from './chunk-R25RGPUB.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import './Tooltip-LKQF7CE4.css';
@@ -100,14 +100,13 @@ function Tooltip({
100
100
  width: rect.width,
101
101
  height: rect.height
102
102
  };
103
- const whole = { x: 0, y: 0, width: host.width, height: host.height };
104
103
  const bounds = {
105
104
  x: LAYER_GAP,
106
105
  y: LAYER_GAP,
107
106
  width: host.width - 2 * LAYER_GAP,
108
107
  height: host.height - 2 * LAYER_GAP
109
108
  };
110
- if (outsideBounds({ ...local, x: rect.x - (inHost ? host.x : 0) }, whole)) {
109
+ if (anchorGone(rect, host, inHost)) {
111
110
  setOpen(false);
112
111
  return;
113
112
  }
@@ -1,5 +1,5 @@
1
1
  import { cx } from './chunk-ODEQTPFM.js';
2
- import './Note-ONSKKTOA.css';
2
+ import './Note-WI5MLZOO.css';
3
3
  import { forwardRef, useId } from 'react';
4
4
  import { jsxs, jsx } from 'react/jsx-runtime';
5
5
 
@@ -0,0 +1,54 @@
1
+ import { IconButton } from './chunk-4FQT6ZAY.js';
2
+ import { cx } from './chunk-ODEQTPFM.js';
3
+ import './SlideNav-BLFJF6AH.css';
4
+ import { ChevronLeftGlyph, ChevronRightGlyph } from '@crewlethq/icons/glyphs';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ var SLIDE_NAV_LABELS = {
8
+ nav: "Slide controls",
9
+ previous: "Previous slide",
10
+ next: "Next slide",
11
+ start: "This is the first slide",
12
+ end: "End of the deck",
13
+ position: (position, total) => `${position} of ${total}`
14
+ };
15
+ function SlideNav({
16
+ position,
17
+ total,
18
+ onPrevious,
19
+ onNext,
20
+ tone = "page",
21
+ children,
22
+ className,
23
+ labels
24
+ }) {
25
+ const text = { ...SLIDE_NAV_LABELS, ...labels };
26
+ return /* @__PURE__ */ jsxs("div", { className: cx("crewlet-slide-nav", `crewlet-slide-nav--${tone}`, className), role: "group", "aria-label": text.nav, children: [
27
+ /* @__PURE__ */ jsx(
28
+ IconButton,
29
+ {
30
+ label: text.previous,
31
+ icon: /* @__PURE__ */ jsx(ChevronLeftGlyph, {}),
32
+ variant: "ghost",
33
+ size: "sm",
34
+ onClick: onPrevious,
35
+ disabledReason: position <= 1 ? text.start : void 0
36
+ }
37
+ ),
38
+ /* @__PURE__ */ jsx("span", { className: "crewlet-slide-nav__position", children: text.position(position, total) }),
39
+ /* @__PURE__ */ jsx(
40
+ IconButton,
41
+ {
42
+ label: text.next,
43
+ icon: /* @__PURE__ */ jsx(ChevronRightGlyph, {}),
44
+ variant: "ghost",
45
+ size: "sm",
46
+ onClick: onNext,
47
+ disabledReason: position >= total ? text.end : void 0
48
+ }
49
+ ),
50
+ children ? /* @__PURE__ */ jsx("span", { className: "crewlet-slide-nav__more", children }) : null
51
+ ] });
52
+ }
53
+
54
+ export { SLIDE_NAV_LABELS, SlideNav };
@@ -1,14 +1,14 @@
1
1
  import { PageHeader } from './chunk-HOXGBLEY.js';
2
- import { Toolbar } from './chunk-PGRPNDWM.js';
3
- import { DateTimePicker } from './chunk-Y5NQ2LMS.js';
4
- import { DataTable } from './chunk-EBJREOKS.js';
2
+ import { DateTimePicker } from './chunk-BY4N65PM.js';
3
+ import { DataTable } from './chunk-UXXJDIYE.js';
5
4
  import { useListbox, useOptionKeys } from './chunk-F73MC7EZ.js';
6
- import { Popover } from './chunk-BWRGFKJP.js';
5
+ import { Toolbar } from './chunk-PGRPNDWM.js';
6
+ import { Popover } from './chunk-K3IJQNB7.js';
7
7
  import { Input } from './chunk-6QFAK2WV.js';
8
8
  import { Kbd } from './chunk-SMBKXWML.js';
9
9
  import { RelativeTime } from './chunk-3CZ7XAVY.js';
10
10
  import { Count } from './chunk-BHHIIK3M.js';
11
- import { Menu } from './chunk-2HIOJ4YZ.js';
11
+ import { Menu } from './chunk-3EB2AV3H.js';
12
12
  import { Button } from './chunk-OG6CL3EB.js';
13
13
  import { IconButton } from './chunk-4FQT6ZAY.js';
14
14
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
@@ -1,4 +1,4 @@
1
- import { Tooltip } from './chunk-QWOPX2MN.js';
1
+ import { Tooltip } from './chunk-5FYPE5GL.js';
2
2
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import './FactList-G2H73NFR.css';