@arbidocs/blocks 0.4.112 → 0.4.114

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 (53) hide show
  1. package/dist/agents/index.cjs +208 -208
  2. package/dist/agents/index.js +3 -3
  3. package/dist/chat/index.cjs +131 -131
  4. package/dist/chat/index.js +4 -4
  5. package/dist/{chunk-6RHHMBZ5.js → chunk-2FUJXMGO.js} +5 -5
  6. package/dist/{chunk-6RHHMBZ5.js.map → chunk-2FUJXMGO.js.map} +1 -1
  7. package/dist/{chunk-XKSFJYOD.cjs → chunk-5UHAWSEX.cjs} +4 -4
  8. package/dist/{chunk-XKSFJYOD.cjs.map → chunk-5UHAWSEX.cjs.map} +1 -1
  9. package/dist/{chunk-ZP4IFW2E.js → chunk-6Z7DLJU2.js} +4 -4
  10. package/dist/{chunk-ZP4IFW2E.js.map → chunk-6Z7DLJU2.js.map} +1 -1
  11. package/dist/{chunk-KZJAG7T3.js → chunk-7XF5SFJ2.js} +3 -3
  12. package/dist/{chunk-KZJAG7T3.js.map → chunk-7XF5SFJ2.js.map} +1 -1
  13. package/dist/{chunk-VGOFFCMT.cjs → chunk-B6MVQCXW.cjs} +3 -3
  14. package/dist/{chunk-VGOFFCMT.cjs.map → chunk-B6MVQCXW.cjs.map} +1 -1
  15. package/dist/{chunk-HBBJYRGI.cjs → chunk-CK4C3IQR.cjs} +9 -9
  16. package/dist/{chunk-HBBJYRGI.cjs.map → chunk-CK4C3IQR.cjs.map} +1 -1
  17. package/dist/{chunk-VLOPZHFH.js → chunk-D3N67Q4D.js} +3 -3
  18. package/dist/{chunk-VLOPZHFH.js.map → chunk-D3N67Q4D.js.map} +1 -1
  19. package/dist/{chunk-Z2NSU7D5.cjs → chunk-FXUQZFAN.cjs} +4 -4
  20. package/dist/{chunk-Z2NSU7D5.cjs.map → chunk-FXUQZFAN.cjs.map} +1 -1
  21. package/dist/{chunk-BV7FEMSI.js → chunk-OKERRHLH.js} +3 -3
  22. package/dist/{chunk-BV7FEMSI.js.map → chunk-OKERRHLH.js.map} +1 -1
  23. package/dist/{chunk-VP4KJ4LK.cjs → chunk-S2KVJYBD.cjs} +11 -8
  24. package/dist/chunk-S2KVJYBD.cjs.map +1 -0
  25. package/dist/{chunk-HBF4BDRU.cjs → chunk-S6BOINC4.cjs} +7 -7
  26. package/dist/{chunk-HBF4BDRU.cjs.map → chunk-S6BOINC4.cjs.map} +1 -1
  27. package/dist/{chunk-NRUPUDWB.js → chunk-TCNYKDYE.js} +7 -4
  28. package/dist/chunk-TCNYKDYE.js.map +1 -0
  29. package/dist/{chunk-2UAJVK3C.cjs → chunk-UDK553WP.cjs} +4 -4
  30. package/dist/{chunk-2UAJVK3C.cjs.map → chunk-UDK553WP.cjs.map} +1 -1
  31. package/dist/{chunk-CXZ7FPTQ.js → chunk-WN64RF46.js} +3 -3
  32. package/dist/{chunk-CXZ7FPTQ.js.map → chunk-WN64RF46.js.map} +1 -1
  33. package/dist/collaboration/index.cjs +1 -1
  34. package/dist/collaboration/index.js +1 -1
  35. package/dist/connect/index.cjs +17 -17
  36. package/dist/connect/index.js +6 -6
  37. package/dist/facts/index.cjs +1 -1
  38. package/dist/facts/index.js +1 -1
  39. package/dist/files/index.cjs +1 -1
  40. package/dist/files/index.js +1 -1
  41. package/dist/index.cjs +412 -412
  42. package/dist/index.js +9 -9
  43. package/dist/shell/Shell.d.ts +5 -0
  44. package/dist/shell/index.cjs +69 -69
  45. package/dist/shell/index.js +4 -4
  46. package/dist/studio/index.cjs +4 -4
  47. package/dist/studio/index.js +3 -3
  48. package/dist/workflow-canvas/index.cjs +10 -10
  49. package/dist/workflow-canvas/index.js +3 -3
  50. package/node_modules/@arbidocs/coedit/package.json +1 -1
  51. package/package.json +4 -4
  52. package/dist/chunk-NRUPUDWB.js.map +0 -1
  53. package/dist/chunk-VP4KJ4LK.cjs.map +0 -1
@@ -252,7 +252,7 @@ function PageContainer({
252
252
  {
253
253
  "data-slot": "page-container",
254
254
  className: cn(
255
- "@container bg-background pb-safe",
255
+ "bg-background pb-safe",
256
256
  minScreen ? "min-h-screen" : "h-full min-h-0",
257
257
  className
258
258
  ),
@@ -322,5 +322,5 @@ function ToolButton({
322
322
  }
323
323
 
324
324
  export { BlocksTooltipProvider, DEFAULT_OVERLAY_ZONE_ID, DEFAULT_PAGE_CONTAINER_PADDING, DEFAULT_SIDEBAR_TOGGLE_BUTTON_LABELS, PageContainer, SHELL_BOTTOM_INSET_VAR, Shell, SidebarToggleButton, ToolButton, useDrawerBehavior, useOverlayZoneId, useShellBottomInset };
325
- //# sourceMappingURL=chunk-KZJAG7T3.js.map
326
- //# sourceMappingURL=chunk-KZJAG7T3.js.map
325
+ //# sourceMappingURL=chunk-7XF5SFJ2.js.map
326
+ //# sourceMappingURL=chunk-7XF5SFJ2.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/bottom-inset.ts","../src/provider/TooltipScope.tsx","../src/lib/use-drawer.ts","../src/shell/Shell.tsx","../src/shell/ToolButton.tsx"],"names":["useEffect","createContext","useContext","jsx","useRef","cn"],"mappings":";;;;;;AASO,IAAM,sBAAA,GAAyB;AAEtC,IAAM,SAAA,uBAAgB,GAAA,EAA0B;AAGhD,SAAS,KAAA,GAAc;AACrB,EAAA,IAAI,OAAO,aAAa,WAAA,EAAa;AACrC,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,KAAA,MAAW,OAAA,IAAW,UAAU,MAAA,EAAO,UAAW,IAAA,CAAK,GAAA,CAAI,KAAA,EAAO,OAAA,EAAS,CAAA;AAC3E,EAAA,MAAM,KAAA,GAAQ,SAAS,eAAA,CAAgB,KAAA;AACvC,EAAA,IAAI,KAAA,GAAQ,CAAA,EAAG,KAAA,CAAM,WAAA,CAAY,sBAAA,EAAwB,GAAG,IAAA,CAAK,KAAA,CAAM,KAAK,CAAC,CAAA,EAAA,CAAI,CAAA;AAAA,OAC5E,KAAA,CAAM,eAAe,sBAAsB,CAAA;AAClD;AASO,SAAS,mBAAA,CACd,GAAA,EACA,OAAA,GAAmB,IAAA,EACb;AACN,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,KAAK,GAAA,CAAI,OAAA;AACf,IAAA,IAAI,CAAC,OAAA,IAAW,CAAC,EAAA,EAAI;AACrB,IAAA,MAAM,GAAA,0BAAa,oBAAoB,CAAA;AACvC,IAAA,SAAA,CAAU,GAAA,CAAI,KAAK,MAAM;AACvB,MAAA,MAAM,IAAA,GAAO,GAAG,qBAAA,EAAsB;AACtC,MAAA,OAAO,IAAA,CAAK,MAAA,GAAS,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,GAAG,MAAA,CAAO,WAAA,GAAc,IAAA,CAAK,GAAG,CAAA,GAAI,CAAA;AAAA,IACxE,CAAC,CAAA;AACD,IAAA,KAAA,EAAM;AAEN,IAAA,MAAM,IAAA,GAAO,aAAA,CAAc,EAAA,EAAI,KAAK,CAAA;AACpC,IAAA,MAAA,CAAO,gBAAA,CAAiB,UAAU,KAAK,CAAA;AACvC,IAAA,OAAO,MAAM;AACX,MAAA,IAAA,EAAK;AACL,MAAA,MAAA,CAAO,mBAAA,CAAoB,UAAU,KAAK,CAAA;AAC1C,MAAA,SAAA,CAAU,OAAO,GAAG,CAAA;AACpB,MAAA,KAAA,EAAM;AAAA,IACR,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,GAAA,EAAK,OAAO,CAAC,CAAA;AACnB;AClDA,IAAM,mBAAA,GAAsB,cAAc,KAAK,CAAA;AAOxC,SAAS,qBAAA,CAAsB,EAAE,QAAA,EAAS,EAA4B;AAC3E,EAAA,MAAM,QAAA,GAAW,WAAW,mBAAmB,CAAA;AAC/C,EAAA,IAAI,QAAA,EAAU,uBAAO,GAAA,CAAA,QAAA,EAAA,EAAG,QAAA,EAAS,CAAA;AACjC,EAAA,uBACE,GAAA,CAAC,oBAAoB,QAAA,EAApB,EAA6B,OAAK,IAAA,EACjC,QAAA,kBAAA,GAAA,CAAC,eAAA,EAAA,EAAiB,QAAA,EAAS,CAAA,EAC7B,CAAA;AAEJ;AChBA,IAAM,SAAA,GACJ,2IAAA;AAEF,SAAS,YAAY,SAAA,EAAuC;AAC1D,EAAA,OAAO,MAAM,IAAA,CAAK,SAAA,CAAU,gBAAA,CAA8B,SAAS,CAAC,CAAA,CAAE,MAAA;AAAA,IACpE,CAAC,EAAA,KAAO,CAAC,EAAA,CAAG,OAAA,CAAQ,SAAS,CAAA,IAAK,EAAA,CAAG,YAAA,CAAa,aAAa,CAAA,KAAM;AAAA,GACvE;AACF;AAWO,SAAS,iBAAA,CACd,MAAA,EACA,OAAA,EACA,YAAA,EACM;AAEN,EAAA,MAAM,UAAA,GAAa,OAAO,OAAO,CAAA;AACjC,EAAAA,UAAU,MAAM;AACd,IAAA,UAAA,CAAW,OAAA,GAAU,OAAA;AAAA,EACvB,CAAC,CAAA;AAED,EAAAA,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,MAAA,EAAQ;AACb,IAAA,MAAM,gBAAA,GAAmB,QAAA,CAAS,IAAA,CAAK,KAAA,CAAM,QAAA;AAC7C,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,aAAA,YAAyB,WAAA,GAAc,SAAS,aAAA,GAAgB,IAAA;AACxF,IAAA,QAAA,CAAS,IAAA,CAAK,MAAM,QAAA,GAAW,QAAA;AAE/B,IAAA,MAAM,SAAA,GAAY,cAAc,OAAA,IAAW,IAAA;AAC3C,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,SAAS,CAAA,CAAE,CAAC,CAAA;AACtC,MAAA,IAAI,KAAA,QAAa,KAAA,EAAM;AAAA,WAClB;AACH,QAAA,IAAI,CAAC,UAAU,YAAA,CAAa,UAAU,GAAG,SAAA,CAAU,YAAA,CAAa,YAAY,IAAI,CAAA;AAChF,QAAA,SAAA,CAAU,KAAA,EAAM;AAAA,MAClB;AAAA,IACF;AAEA,IAAA,MAAM,KAAA,GAAQ,CAAC,CAAA,KAAqB;AAClC,MAAA,IAAI,CAAA,CAAE,QAAQ,QAAA,EAAU;AACtB,QAAA,UAAA,CAAW,OAAA,EAAQ;AACnB,QAAA;AAAA,MACF;AACA,MAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,KAAA,IAAS,CAAC,SAAA,EAAW;AACnC,MAAA,MAAM,KAAA,GAAQ,YAAY,SAAS,CAAA;AACnC,MAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA;AAAA,MACF;AACA,MAAA,MAAM,SAAA,GAAY,MAAM,CAAC,CAAA;AACzB,MAAA,MAAM,QAAA,GAAW,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,CAAC,CAAA;AACvC,MAAA,MAAM,SAAS,QAAA,CAAS,aAAA;AACxB,MAAA,IAAI,CAAC,SAAA,CAAU,QAAA,CAAS,MAAM,CAAA,EAAG;AAC/B,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,SAAA,CAAU,KAAA,EAAM;AAAA,MAClB,CAAA,MAAA,IAAW,CAAA,CAAE,QAAA,IAAY,MAAA,KAAW,SAAA,EAAW;AAC7C,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,QAAA,CAAS,KAAA,EAAM;AAAA,MACjB,CAAA,MAAA,IAAW,CAAC,CAAA,CAAE,QAAA,IAAY,WAAW,QAAA,EAAU;AAC7C,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,SAAA,CAAU,KAAA,EAAM;AAAA,MAClB;AAAA,IACF,CAAA;AACA,IAAA,MAAA,CAAO,gBAAA,CAAiB,WAAW,KAAK,CAAA;AACxC,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,IAAA,CAAK,MAAM,QAAA,GAAW,gBAAA;AAC/B,MAAA,MAAA,CAAO,mBAAA,CAAoB,WAAW,KAAK,CAAA;AAC3C,MAAA,IAAI,MAAA,EAAQ,WAAA,EAAa,MAAA,CAAO,KAAA,EAAM;AAAA,IACxC,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,YAAY,CAAC,CAAA;AAC3B;AChEO,IAAM,uBAAA,GAA0B;AAEvC,IAAM,kBAAA,GAAqBC,cAAc,uBAAuB,CAAA;AAGzD,SAAS,gBAAA,GAA2B;AACzC,EAAA,OAAOC,WAAW,kBAAkB,CAAA;AACtC;AAyBA,SAAS,SAAA,CAAU;AAAA,EACjB,MAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,aAAA,EAAe;AACjB,CAAA,EAAmB;AACjB,EAAA,uBACEC,IAAC,qBAAA,EAAA,EACC,QAAA,kBAAA,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,OAAA;AAAA,MACV,aAAA,EAAa,MAAA;AAAA,MACb,SAAA,EAAW,EAAA,CAAG,8BAAA,EAAgC,SAAS,CAAA;AAAA,MAEtD,QAAA,EAAA;AAAA,QAAA,MAAA;AAAA,QACA,MAAA;AAAA,wBAED,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sCAAA,EACZ,QAAA,EAAA;AAAA,UAAA,OAAA;AAAA,UACA,QAAA;AAAA,UACA,KAAA;AAAA,UACA;AAAA,SAAA,EACH,CAAA;AAAA,QACC;AAAA;AAAA;AAAA,GACH,EACF,CAAA;AAEJ;AAmBA,SAAS,YAAA,CAAa;AAAA,EACpB,QAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,aAAA,GAAgB,uBAAA;AAAA,EAChB;AACF,CAAA,EAAsB;AACpB,EAAA,uBACEA,GAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,eAAA;AAAA,MACV,SAAA,EAAW,EAAA,CAAG,8BAAA,EAAgC,SAAS,CAAA;AAAA,MACvD,OAAA;AAAA,MAEA,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yBAAA,EACb,QAAA,EAAA;AAAA,wBAAAA,GAAAA,CAAC,kBAAA,CAAmB,QAAA,EAAnB,EAA4B,OAAO,aAAA,EAIlC,QAAA,kBAAAA,GAAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAK,SAAA,EAAW,SAAA,EAAU,iCAAA,EAC5B,UACH,CAAA,EACF,CAAA;AAAA,wBACAA,GAAAA,CAAC,KAAA,EAAA,EAAI,EAAA,EAAI,aAAA,EAAe,aAAU,cAAA,EAAe;AAAA,OAAA,EACnD;AAAA;AAAA,GACF;AAEJ;AAWA,SAAS,WAAA,CAAY,EAAE,QAAA,EAAU,OAAA,EAAS,WAAU,EAAqB;AACvE,EAAA;AAAA;AAAA,oBAEE,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,WAAA,EAAU,cAAA;AAAA,QACV,SAAA,EAAW,EAAA,CAAG,kEAAA,EAAoE,SAAS,CAAA;AAAA,QAE3F,QAAA,EAAA;AAAA,0BAAAA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4CAAA,EACb,QAAA,kBAAAA,IAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qCAAA,EAAuC,QAAA,EAAS,CAAA,EACjE,CAAA;AAAA,0BACAA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qEACZ,QAAA,EAAA,OAAA,EACH;AAAA;AAAA;AAAA;AACF;AAEJ;AAuBA,SAAS,SAAA,CAAU;AAAA,EACjB,MAAA;AAAA,EACA,YAAA;AAAA,EACA,KAAA,GAAQ,OAAA;AAAA,EACR,QAAA,GAAW,KAAA;AAAA,EACX,KAAA;AAAA,EACA,UAAA,GAAa,OAAA;AAAA,EACb,QAAA;AAAA,EACA,SAAA;AAAA,EACA,aAAA,EAAe;AACjB,CAAA,EAAmB;AAGjB,EAAA,MAAM,SAAA,GAAYC,OAAuB,IAAI,CAAA;AAC7C,EAAA,MAAM,WAAA,GAAc,YAAY,MAAM,YAAA,GAAe,KAAK,CAAA,EAAG,CAAC,YAAY,CAAC,CAAA;AAC3E,EAAA,iBAAA,CAAkB,MAAA,IAAU,QAAA,EAAU,WAAA,EAAa,SAAS,CAAA;AAC5D,EAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AACpB,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,uBACE,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAK,SAAA;AAAA,QACL,IAAA,EAAK,QAAA;AAAA,QACL,YAAA,EAAW,MAAA;AAAA,QACX,YAAA,EAAY,KAAA;AAAA,QACZ,WAAA,EAAU,YAAA;AAAA,QACV,YAAA,EAAW,MAAA;AAAA,QACX,aAAA,EAAY,MAAA;AAAA,QACZ,aAAA,EAAa,MAAA;AAAA,QACb,SAAA,EAAW,EAAA,CAAG,gDAAA,EAAkD,SAAS,CAAA;AAAA,QAExE,QAAA,EAAA;AAAA,UAAA,YAAA,oBACCD,GAAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,QAAA;AAAA,cACL,OAAA,EAAS,MAAM,YAAA,CAAa,KAAK,CAAA;AAAA,cACjC,YAAA,EAAY,UAAA;AAAA,cACZ,SAAA,EAAU,iFAAA;AAAA,cAEV,QAAA,kBAAAA,GAAAA,CAAC,CAAA,EAAA,EAAE,SAAA,EAAU,QAAA,EAAS;AAAA;AAAA,WACxB;AAAA,UAED;AAAA;AAAA;AAAA,KACH;AAAA,EAEJ;AACA,EAAA,uBACEA,GAAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACC,YAAA,EAAY,KAAA;AAAA,MACZ,WAAA,EAAU,YAAA;AAAA,MACV,YAAA,EAAW,MAAA;AAAA,MACX,aAAA,EAAa,MAAA;AAAA,MACb,KAAA,EAAO,EAAE,KAAA,EAAM;AAAA,MACf,SAAA,EAAW,EAAA;AAAA,QACT,6EAAA;AAAA,QACA;AAAA,OACF;AAAA,MAEC;AAAA;AAAA,GACH;AAEJ;AAEO,IAAM,KAAA,GAAQ;AAAA,EACnB,IAAA,EAAM,SAAA;AAAA,EACN,OAAA,EAAS,YAAA;AAAA,EACT,MAAA,EAAQ,WAAA;AAAA,EACR,IAAA,EAAM;AACR;AAuBO,IAAM,8BAAA,GAAiC;AAMvC,SAAS,aAAA,CAAc;AAAA,EAC5B,QAAA;AAAA,EACA,IAAA,GAAO,KAAA;AAAA,EACP,SAAA,GAAY,KAAA;AAAA,EACZ,QAAA,GAAW,WAAA;AAAA,EACX,OAAA,GAAU,8BAAA;AAAA,EACV,cAAA;AAAA,EACA;AACF,CAAA,EAAuB;AACrB,EAAA,uBACEA,GAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,gBAAA;AAAA,MACV,SAAA,EAAW,EAAA;AAAA,QACT,kCAAA;AAAA,QACA,YAAY,cAAA,GAAiB,gBAAA;AAAA,QAC7B;AAAA,OACF;AAAA,MAEA,QAAA,kBAAAA,GAAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAW,EAAA;AAAA,YACT,6CAAA;AAAA,YACA,OAAA;AAAA,YACA,CAAC,IAAA,IAAQ,EAAA,CAAG,SAAA,EAAW,QAAQ,CAAA;AAAA,YAC/B;AAAA,WACF;AAAA,UAEC;AAAA;AAAA;AACH;AAAA,GACF;AAEJ;AAQO,IAAM,oCAAA,GAAkE;AAAA,EAC7E,YAAA,EAAc,eAAA;AAAA,EACd,WAAA,EAAa;AACf;AAWO,SAAS,mBAAA,CAAoB;AAAA,EAClC,MAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA,eAAe,MAAA,GAAS;AAC1B,CAAA,EAA6B;AAC3B,EAAA,MAAM,CAAA,GAAI,EAAE,GAAG,oCAAA,EAAsC,GAAG,MAAA,EAAO;AAC/D,EAAA,MAAM,KAAA,GAAQ,MAAA,GAAS,CAAA,CAAE,YAAA,GAAe,CAAA,CAAE,WAAA;AAC1C,EAAA,uBACEA,GAAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,QAAA;AAAA,MACL,OAAA,EAAS,QAAA;AAAA,MACT,SAAA,EAAU,kHAAA;AAAA,MACV,YAAA,EAAY,KAAA;AAAA,MACZ,KAAA,EAAO,KAAA;AAAA,MACP,aAAA,EAAa,MAAA;AAAA,MAEb,QAAA,kBAAAA,GAAAA,CAAC,SAAA,EAAA,EAAU,SAAA,EAAU,QAAA,EAAS;AAAA;AAAA,GAChC;AAEJ;ACrUO,SAAS,UAAA,CAAW;AAAA,EACzB,OAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA,GAAS,KAAA;AAAA,EACT,aAAA,EAAe,MAAA;AAAA,EACf;AACF,CAAA,EAAoB;AAClB,EAAA,uBACEA,GAAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,QAAA;AAAA,MACL,OAAA;AAAA,MACA,KAAA,EAAO,KAAA;AAAA,MACP,YAAA,EAAY,KAAA;AAAA,MACZ,WAAA,EAAU,aAAA;AAAA,MACV,aAAA,EAAa,MAAA;AAAA,MACb,SAAA,EAAWE,EAAAA;AAAA,QACT,4JAAA;AAAA,QACA,SAAS,kCAAA,GAAqC;AAAA,OAChD;AAAA,MAEC;AAAA;AAAA,GACH;AAEJ","file":"chunk-KZJAG7T3.js","sourcesContent":["import { useEffect, type RefObject } from 'react'\nimport { observeResize } from './observe-resize'\n\n/**\n * The CSS custom property that carries how much of the screen's bottom edge is taken by pinned\n * bars (the phone tab bar, a chat composer), set on `<html>`. A floating element (the install\n * prompt, a toast, a back-to-top button) positions itself `calc(var(--shell-bottom-inset, 0px) +\n * 0.75rem)` so it never covers those bars.\n */\nexport const SHELL_BOTTOM_INSET_VAR = '--shell-bottom-inset'\n\nconst measurers = new Map<symbol, () => number>()\n\n/** Re-measure every registered bar and publish the largest: bars stack, so the tallest reach wins. */\nfunction apply(): void {\n if (typeof document === 'undefined') return\n let inset = 0\n for (const measure of measurers.values()) inset = Math.max(inset, measure())\n const style = document.documentElement.style\n if (inset > 0) style.setProperty(SHELL_BOTTOM_INSET_VAR, `${Math.round(inset)}px`)\n else style.removeProperty(SHELL_BOTTOM_INSET_VAR)\n}\n\n/**\n * Report a bottom-pinned element to {@link SHELL_BOTTOM_INSET_VAR}: its distance from the top of\n * the element to the bottom of the viewport, so a composer above the tab bar counts the tab bar\n * too (contributions are combined with `max`, not summed). An element that is not rendered\n * (`display: none`, e.g. the phone-only tab bar on a desktop width) contributes 0. Used by\n * `MobileTabBar` and the chat composer; call it from your own bottom bar.\n */\nexport function useShellBottomInset(\n ref: RefObject<HTMLElement | null>,\n enabled: boolean = true\n): void {\n useEffect(() => {\n const el = ref.current\n if (!enabled || !el) return\n const key = Symbol('shell-bottom-inset')\n measurers.set(key, () => {\n const rect = el.getBoundingClientRect()\n return rect.height > 0 ? Math.max(0, window.innerHeight - rect.top) : 0\n })\n apply()\n // Any bar resizing moves the others (a composer sits on top of the tab bar): re-measure all.\n const stop = observeResize(el, apply)\n window.addEventListener('resize', apply)\n return () => {\n stop()\n window.removeEventListener('resize', apply)\n measurers.delete(key)\n apply()\n }\n }, [ref, enabled])\n}\n","import { createContext, useContext, type ReactNode } from 'react'\nimport { TooltipProvider } from '@arbidocs/react/ui'\n\nconst TooltipScopeContext = createContext(false)\n\n/**\n * A TooltipProvider that mounts once: inside another `BlocksTooltipProvider` (e.g. a Sidebar under\n * Shell.Root) it renders its children as-is, so tooltips share one delay group. Blocks that show\n * tooltips use this instead of the kit's provider.\n */\nexport function BlocksTooltipProvider({ children }: { children: ReactNode }) {\n const isNested = useContext(TooltipScopeContext)\n if (isNested) return <>{children}</>\n return (\n <TooltipScopeContext.Provider value>\n <TooltipProvider>{children}</TooltipProvider>\n </TooltipScopeContext.Provider>\n )\n}\n","import { useEffect, useRef, type RefObject } from 'react'\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n\nfunction focusableIn(container: HTMLElement): HTMLElement[] {\n return Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE)).filter(\n (el) => !el.closest('[inert]') && el.getAttribute('aria-hidden') !== 'true'\n )\n}\n\n/**\n * Behaviour of a modal surface (off-canvas drawer, full-screen dock) while it is open: the page\n * behind does not scroll, Escape closes it, focus moves inside and Tab/Shift+Tab cycle within it\n * (portalled popovers opened from inside stay reachable: only the wrap-around is intercepted),\n * and focus returns to the opener on close. Restores the previous body overflow on close/unmount.\n *\n * Pass `containerRef` (the element carrying `role=\"dialog\"`) to get the focus handling; without it\n * only scroll lock and Escape apply.\n */\nexport function useDrawerBehavior(\n isOpen: boolean,\n onClose: () => void,\n containerRef?: RefObject<HTMLElement | null>\n): void {\n // A fresh `onClose` identity per render must not re-run the effect (it would steal focus).\n const onCloseRef = useRef(onClose)\n useEffect(() => {\n onCloseRef.current = onClose\n })\n\n useEffect(() => {\n if (!isOpen) return\n const previousOverflow = document.body.style.overflow\n const opener = document.activeElement instanceof HTMLElement ? document.activeElement : null\n document.body.style.overflow = 'hidden'\n\n const container = containerRef?.current ?? null\n if (container) {\n const first = focusableIn(container)[0]\n if (first) first.focus()\n else {\n if (!container.hasAttribute('tabindex')) container.setAttribute('tabindex', '-1')\n container.focus()\n }\n }\n\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onCloseRef.current()\n return\n }\n if (e.key !== 'Tab' || !container) return\n const items = focusableIn(container)\n if (items.length === 0) {\n e.preventDefault()\n return\n }\n const firstItem = items[0]\n const lastItem = items[items.length - 1]\n const active = document.activeElement\n if (!container.contains(active)) {\n e.preventDefault()\n firstItem.focus()\n } else if (e.shiftKey && active === firstItem) {\n e.preventDefault()\n lastItem.focus()\n } else if (!e.shiftKey && active === lastItem) {\n e.preventDefault()\n firstItem.focus()\n }\n }\n window.addEventListener('keydown', onKey)\n return () => {\n document.body.style.overflow = previousOverflow\n window.removeEventListener('keydown', onKey)\n if (opener?.isConnected) opener.focus()\n }\n }, [isOpen, containerRef])\n}\n","import {\n createContext,\n useCallback,\n useContext,\n useRef,\n type MouseEventHandler,\n type ReactNode,\n type Ref,\n} from 'react'\nimport { PanelLeft, X } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { useDrawerBehavior } from '../lib/use-drawer'\nimport { BlocksTooltipProvider } from '../provider/TooltipScope'\n\n/** Default id of the element overlay-mode panels portal into (see `Shell.Content`). */\nexport const DEFAULT_OVERLAY_ZONE_ID = 'app-overlay-zone'\n\nconst OverlayZoneContext = createContext(DEFAULT_OVERLAY_ZONE_ID)\n\n/** The id of the enclosing `Shell.Content` overlay zone, for panels that portal into it. */\nexport function useOverlayZoneId(): string {\n return useContext(OverlayZoneContext)\n}\n\nexport interface ShellRootProps {\n /** Full-width strip above everything (e.g. a deletion-pending banner). */\n banner?: ReactNode\n /** Top chrome: a Shell.Topbar on list pages, a MobileAppBar on phones; omit for none. */\n topbar?: ReactNode\n /** The Sidebar.Root (and its drawer backdrop). */\n sidebar?: ReactNode\n /** Phone bottom navigation. */\n tabBar?: ReactNode\n /** Right-hand column beside the content: a `Shell.Dock` (chat, inspector...). */\n aside?: ReactNode\n /** Extra layers inside the body row (connection monitor, …). */\n overlays?: ReactNode\n /** The Shell.Content region. */\n children: ReactNode\n className?: string\n 'data-testid'?: string\n}\n\n/**\n * The application frame: banner, top chrome, then a body row holding the sidebar beside the\n * content, then the phone tab bar. Every region is a slot, so a custom UI composes its own.\n */\nfunction ShellRoot({\n banner,\n topbar,\n sidebar,\n tabBar,\n aside,\n overlays,\n children,\n className,\n 'data-testid': testId,\n}: ShellRootProps) {\n return (\n <BlocksTooltipProvider>\n <div\n data-slot=\"shell\"\n data-testid={testId}\n className={cn('flex h-screen h-dvh flex-col', className)}\n >\n {banner}\n {topbar}\n {/* `relative` anchors the sidebar's slide-out overlays to this row. */}\n <div className=\"relative flex flex-1 overflow-hidden\">\n {sidebar}\n {children}\n {aside}\n {overlays}\n </div>\n {tabBar}\n </div>\n </BlocksTooltipProvider>\n )\n}\n\nexport interface ShellContentProps {\n children: ReactNode\n /** Scrolling element, for scroll restoration. */\n scrollRef?: Ref<HTMLDivElement>\n onClick?: MouseEventHandler<HTMLDivElement>\n /**\n * Overlay-mode panels portal into this id and cover the content column only. Defaults to\n * `DEFAULT_OVERLAY_ZONE_ID`; descendants read it with `useOverlayZoneId()`.\n */\n overlayZoneId?: string\n className?: string\n}\n\n/**\n * The content column beside the sidebar. It is `relative` so overlay-mode panels (portalled into\n * the overlay zone) cover this region only, leaving the sidebar and its actions interactive.\n */\nfunction ShellContent({\n children,\n scrollRef,\n onClick,\n overlayZoneId = DEFAULT_OVERLAY_ZONE_ID,\n className,\n}: ShellContentProps) {\n return (\n <div\n data-slot=\"shell-content\"\n className={cn('flex min-w-0 flex-1 flex-col', className)}\n onClick={onClick}\n >\n <div className=\"relative min-h-0 flex-1\">\n <OverlayZoneContext.Provider value={overlayZoneId}>\n {/* The content column is a CSS container: pages and parts size by its width with\n container variants (`@3xl:`...), so an open dock or a narrow window is honoured,\n which viewport breakpoints cannot do. */}\n <div ref={scrollRef} className=\"@container h-full overflow-auto\">\n {children}\n </div>\n </OverlayZoneContext.Provider>\n <div id={overlayZoneId} data-slot=\"overlay-zone\" />\n </div>\n </div>\n )\n}\n\nexport interface ShellTopbarProps {\n /** Left side: guidance / breadcrumbs, centred in the page column. */\n children?: ReactNode\n /** Right side: the action cluster. */\n actions?: ReactNode\n className?: string\n}\n\n/** A minimal white header for pages with no sidebar (the workspaces list). */\nfunction ShellTopbar({ children, actions, className }: ShellTopbarProps) {\n return (\n // `relative z-30` keeps dropdowns the header opens above the page region (a later sibling).\n <div\n data-slot=\"shell-topbar\"\n className={cn('relative z-30 flex h-14 shrink-0 items-center bg-background px-2', className)}\n >\n <div className=\"mx-auto flex w-full max-w-6xl items-center\">\n <div className=\"hidden min-w-0 flex-1 px-6 sm:block\">{children}</div>\n </div>\n <div className=\"absolute right-4 top-1/2 flex -translate-y-1/2 items-center gap-1\">\n {actions}\n </div>\n </div>\n )\n}\n\nexport interface ShellDockProps {\n isOpen: boolean\n /** Called with `false` by the mobile close button. */\n onOpenChange?: (isOpen: boolean) => void\n /** Desktop width (CSS length or px). Default 24rem. */\n width?: number | string\n /** Phone layout: the dock covers the screen instead of sitting beside the content. */\n isMobile?: boolean\n /** Accessible name of the dock. */\n label: string\n /** Mobile close button label. */\n closeLabel?: string\n children: ReactNode\n className?: string\n 'data-testid'?: string\n}\n\n/**\n * A right-hand dock for a companion surface (chat, inspector). Controlled: the host owns\n * `isOpen`, the width and the mobile breakpoint. Pass it to `Shell.Root` as `aside`.\n */\nfunction ShellDock({\n isOpen,\n onOpenChange,\n width = '24rem',\n isMobile = false,\n label,\n closeLabel = 'Close',\n children,\n className,\n 'data-testid': testId,\n}: ShellDockProps) {\n // The phone dock covers the screen, so it is a modal: Escape closes, focus is trapped and\n // returns to the opener.\n const mobileRef = useRef<HTMLDivElement>(null)\n const closeMobile = useCallback(() => onOpenChange?.(false), [onOpenChange])\n useDrawerBehavior(isOpen && isMobile, closeMobile, mobileRef)\n if (!isOpen) return null\n if (isMobile) {\n return (\n <div\n ref={mobileRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={label}\n data-slot=\"shell-dock\"\n data-state=\"open\"\n data-mobile=\"true\"\n data-testid={testId}\n className={cn('fixed inset-0 z-40 flex flex-col bg-background', className)}\n >\n {onOpenChange && (\n <button\n type=\"button\"\n onClick={() => onOpenChange(false)}\n aria-label={closeLabel}\n className=\"absolute right-2 top-2 z-10 rounded-md p-2 text-muted-foreground hover:bg-muted\"\n >\n <X className=\"size-5\" />\n </button>\n )}\n {children}\n </div>\n )\n }\n return (\n <aside\n aria-label={label}\n data-slot=\"shell-dock\"\n data-state=\"open\"\n data-testid={testId}\n style={{ width }}\n className={cn(\n 'flex shrink-0 flex-col overflow-hidden border-l border-border bg-background',\n className\n )}\n >\n {children}\n </aside>\n )\n}\n\nexport const Shell = {\n Root: ShellRoot,\n Content: ShellContent,\n Topbar: ShellTopbar,\n Dock: ShellDock,\n}\n\nexport interface PageContainerProps {\n children: ReactNode\n /** Full width instead of the centred 72rem column. */\n wide?: boolean\n /** Stand-alone use: at least a screen tall, instead of filling the parent. */\n minScreen?: boolean\n /** Max width of the centred column (any Tailwind `max-w-*` class). Default `max-w-6xl`. */\n maxWidth?: string\n /**\n * Horizontal padding of the inner column (any Tailwind `px-*` classes, responsive variants\n * welcome). Default `px-4 sm:px-6 lg:px-8`; pass `px-0` for a full-bleed page, or the class\n * string of your own gutter. Use this prop, not `innerClassName`, to change the gutter: the\n * classes are concatenated without a merge step, so a second `px-*` would not reliably win.\n */\n padding?: string\n /** Extra classes for the inner column. */\n innerClassName?: string\n className?: string\n}\n\n/** Default gutter of {@link PageContainer}: tight on a phone, roomier from tablet up. */\nexport const DEFAULT_PAGE_CONTAINER_PADDING = 'px-4 sm:px-6 lg:px-8'\n\n/**\n * Page body wrapper: a white canvas with the standard 72rem column (or full width) and a responsive side gutter. Fills its\n * parent by default so sticky headers and h-full pages keep a definite height chain.\n */\nexport function PageContainer({\n children,\n wide = false,\n minScreen = false,\n maxWidth = 'max-w-6xl',\n padding = DEFAULT_PAGE_CONTAINER_PADDING,\n innerClassName,\n className,\n}: PageContainerProps) {\n return (\n <div\n data-slot=\"page-container\"\n className={cn(\n '@container bg-background pb-safe',\n minScreen ? 'min-h-screen' : 'h-full min-h-0',\n className\n )}\n >\n <div\n className={cn(\n 'flex h-full w-full min-w-0 flex-col pb-safe',\n padding,\n !wide && cn('mx-auto', maxWidth),\n innerClassName\n )}\n >\n {children}\n </div>\n </div>\n )\n}\n\n/** Fixed strings of the sidebar toggle. */\nexport interface SidebarToggleButtonLabels {\n closeSidebar: string\n openSidebar: string\n}\n\nexport const DEFAULT_SIDEBAR_TOGGLE_BUTTON_LABELS: SidebarToggleButtonLabels = {\n closeSidebar: 'Close sidebar',\n openSidebar: 'Open sidebar',\n}\n\nexport interface SidebarToggleButtonProps {\n /** The sidebar is open (pinned). */\n isOpen: boolean\n onToggle: () => void\n labels?: Partial<SidebarToggleButtonLabels>\n 'data-testid'?: string\n}\n\n/** Opens/closes the sidebar from a page header, so the control sits in the same spot everywhere. */\nexport function SidebarToggleButton({\n isOpen,\n onToggle,\n labels,\n 'data-testid': testId = 'tabheader-sidebar-toggle',\n}: SidebarToggleButtonProps) {\n const l = { ...DEFAULT_SIDEBAR_TOGGLE_BUTTON_LABELS, ...labels }\n const label = isOpen ? l.closeSidebar : l.openSidebar\n return (\n <button\n type=\"button\"\n onClick={onToggle}\n className=\"rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground pointer-coarse:p-2.5\"\n aria-label={label}\n title={label}\n data-testid={testId}\n >\n <PanelLeft className=\"size-5\" />\n </button>\n )\n}\n","import type { ReactNode } from 'react'\nimport { cn } from '@arbidocs/react/ui'\n\nexport interface ToolButtonProps {\n onClick: () => void\n /** Accessible name and native tooltip. */\n label: string\n /** The panel/page this opens is showing. */\n active?: boolean\n 'data-testid'?: string\n children: ReactNode\n}\n\n/** An icon button for a topbar or toolbar: 36px (44px coarse), selection tint while active. */\nexport function ToolButton({\n onClick,\n label,\n active = false,\n 'data-testid': testId,\n children,\n}: ToolButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title={label}\n aria-label={label}\n data-slot=\"tool-button\"\n data-testid={testId}\n className={cn(\n 'relative flex size-9 shrink-0 items-center justify-center rounded-md transition-colors hover:bg-accent hover:text-accent-foreground pointer-coarse:size-11',\n active ? 'bg-accent text-accent-foreground' : 'text-muted-foreground'\n )}\n >\n {children}\n </button>\n )\n}\n"]}
1
+ {"version":3,"sources":["../src/lib/bottom-inset.ts","../src/provider/TooltipScope.tsx","../src/lib/use-drawer.ts","../src/shell/Shell.tsx","../src/shell/ToolButton.tsx"],"names":["useEffect","createContext","useContext","jsx","useRef","cn"],"mappings":"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","file":"chunk-7XF5SFJ2.js","sourcesContent":["import { useEffect, type RefObject } from 'react'\nimport { observeResize } from './observe-resize'\n\n/**\n * The CSS custom property that carries how much of the screen's bottom edge is taken by pinned\n * bars (the phone tab bar, a chat composer), set on `<html>`. A floating element (the install\n * prompt, a toast, a back-to-top button) positions itself `calc(var(--shell-bottom-inset, 0px) +\n * 0.75rem)` so it never covers those bars.\n */\nexport const SHELL_BOTTOM_INSET_VAR = '--shell-bottom-inset'\n\nconst measurers = new Map<symbol, () => number>()\n\n/** Re-measure every registered bar and publish the largest: bars stack, so the tallest reach wins. */\nfunction apply(): void {\n if (typeof document === 'undefined') return\n let inset = 0\n for (const measure of measurers.values()) inset = Math.max(inset, measure())\n const style = document.documentElement.style\n if (inset > 0) style.setProperty(SHELL_BOTTOM_INSET_VAR, `${Math.round(inset)}px`)\n else style.removeProperty(SHELL_BOTTOM_INSET_VAR)\n}\n\n/**\n * Report a bottom-pinned element to {@link SHELL_BOTTOM_INSET_VAR}: its distance from the top of\n * the element to the bottom of the viewport, so a composer above the tab bar counts the tab bar\n * too (contributions are combined with `max`, not summed). An element that is not rendered\n * (`display: none`, e.g. the phone-only tab bar on a desktop width) contributes 0. Used by\n * `MobileTabBar` and the chat composer; call it from your own bottom bar.\n */\nexport function useShellBottomInset(\n ref: RefObject<HTMLElement | null>,\n enabled: boolean = true\n): void {\n useEffect(() => {\n const el = ref.current\n if (!enabled || !el) return\n const key = Symbol('shell-bottom-inset')\n measurers.set(key, () => {\n const rect = el.getBoundingClientRect()\n return rect.height > 0 ? Math.max(0, window.innerHeight - rect.top) : 0\n })\n apply()\n // Any bar resizing moves the others (a composer sits on top of the tab bar): re-measure all.\n const stop = observeResize(el, apply)\n window.addEventListener('resize', apply)\n return () => {\n stop()\n window.removeEventListener('resize', apply)\n measurers.delete(key)\n apply()\n }\n }, [ref, enabled])\n}\n","import { createContext, useContext, type ReactNode } from 'react'\nimport { TooltipProvider } from '@arbidocs/react/ui'\n\nconst TooltipScopeContext = createContext(false)\n\n/**\n * A TooltipProvider that mounts once: inside another `BlocksTooltipProvider` (e.g. a Sidebar under\n * Shell.Root) it renders its children as-is, so tooltips share one delay group. Blocks that show\n * tooltips use this instead of the kit's provider.\n */\nexport function BlocksTooltipProvider({ children }: { children: ReactNode }) {\n const isNested = useContext(TooltipScopeContext)\n if (isNested) return <>{children}</>\n return (\n <TooltipScopeContext.Provider value>\n <TooltipProvider>{children}</TooltipProvider>\n </TooltipScopeContext.Provider>\n )\n}\n","import { useEffect, useRef, type RefObject } from 'react'\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n\nfunction focusableIn(container: HTMLElement): HTMLElement[] {\n return Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE)).filter(\n (el) => !el.closest('[inert]') && el.getAttribute('aria-hidden') !== 'true'\n )\n}\n\n/**\n * Behaviour of a modal surface (off-canvas drawer, full-screen dock) while it is open: the page\n * behind does not scroll, Escape closes it, focus moves inside and Tab/Shift+Tab cycle within it\n * (portalled popovers opened from inside stay reachable: only the wrap-around is intercepted),\n * and focus returns to the opener on close. Restores the previous body overflow on close/unmount.\n *\n * Pass `containerRef` (the element carrying `role=\"dialog\"`) to get the focus handling; without it\n * only scroll lock and Escape apply.\n */\nexport function useDrawerBehavior(\n isOpen: boolean,\n onClose: () => void,\n containerRef?: RefObject<HTMLElement | null>\n): void {\n // A fresh `onClose` identity per render must not re-run the effect (it would steal focus).\n const onCloseRef = useRef(onClose)\n useEffect(() => {\n onCloseRef.current = onClose\n })\n\n useEffect(() => {\n if (!isOpen) return\n const previousOverflow = document.body.style.overflow\n const opener = document.activeElement instanceof HTMLElement ? document.activeElement : null\n document.body.style.overflow = 'hidden'\n\n const container = containerRef?.current ?? null\n if (container) {\n const first = focusableIn(container)[0]\n if (first) first.focus()\n else {\n if (!container.hasAttribute('tabindex')) container.setAttribute('tabindex', '-1')\n container.focus()\n }\n }\n\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onCloseRef.current()\n return\n }\n if (e.key !== 'Tab' || !container) return\n const items = focusableIn(container)\n if (items.length === 0) {\n e.preventDefault()\n return\n }\n const firstItem = items[0]\n const lastItem = items[items.length - 1]\n const active = document.activeElement\n if (!container.contains(active)) {\n e.preventDefault()\n firstItem.focus()\n } else if (e.shiftKey && active === firstItem) {\n e.preventDefault()\n lastItem.focus()\n } else if (!e.shiftKey && active === lastItem) {\n e.preventDefault()\n firstItem.focus()\n }\n }\n window.addEventListener('keydown', onKey)\n return () => {\n document.body.style.overflow = previousOverflow\n window.removeEventListener('keydown', onKey)\n if (opener?.isConnected) opener.focus()\n }\n }, [isOpen, containerRef])\n}\n","import {\n createContext,\n useCallback,\n useContext,\n useRef,\n type MouseEventHandler,\n type ReactNode,\n type Ref,\n} from 'react'\nimport { PanelLeft, X } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { useDrawerBehavior } from '../lib/use-drawer'\nimport { BlocksTooltipProvider } from '../provider/TooltipScope'\n\n/** Default id of the element overlay-mode panels portal into (see `Shell.Content`). */\nexport const DEFAULT_OVERLAY_ZONE_ID = 'app-overlay-zone'\n\nconst OverlayZoneContext = createContext(DEFAULT_OVERLAY_ZONE_ID)\n\n/** The id of the enclosing `Shell.Content` overlay zone, for panels that portal into it. */\nexport function useOverlayZoneId(): string {\n return useContext(OverlayZoneContext)\n}\n\nexport interface ShellRootProps {\n /** Full-width strip above everything (e.g. a deletion-pending banner). */\n banner?: ReactNode\n /** Top chrome: a Shell.Topbar on list pages, a MobileAppBar on phones; omit for none. */\n topbar?: ReactNode\n /** The Sidebar.Root (and its drawer backdrop). */\n sidebar?: ReactNode\n /** Phone bottom navigation. */\n tabBar?: ReactNode\n /** Right-hand column beside the content: a `Shell.Dock` (chat, inspector...). */\n aside?: ReactNode\n /** Extra layers inside the body row (connection monitor, …). */\n overlays?: ReactNode\n /** The Shell.Content region. */\n children: ReactNode\n className?: string\n 'data-testid'?: string\n}\n\n/**\n * The application frame: banner, top chrome, then a body row holding the sidebar beside the\n * content, then the phone tab bar. Every region is a slot, so a custom UI composes its own.\n */\nfunction ShellRoot({\n banner,\n topbar,\n sidebar,\n tabBar,\n aside,\n overlays,\n children,\n className,\n 'data-testid': testId,\n}: ShellRootProps) {\n return (\n <BlocksTooltipProvider>\n <div\n data-slot=\"shell\"\n data-testid={testId}\n className={cn('flex h-screen h-dvh flex-col', className)}\n >\n {banner}\n {topbar}\n {/* `relative` anchors the sidebar's slide-out overlays to this row. */}\n <div className=\"relative flex flex-1 overflow-hidden\">\n {sidebar}\n {children}\n {aside}\n {overlays}\n </div>\n {tabBar}\n </div>\n </BlocksTooltipProvider>\n )\n}\n\nexport interface ShellContentProps {\n children: ReactNode\n /** Scrolling element, for scroll restoration. */\n scrollRef?: Ref<HTMLDivElement>\n onClick?: MouseEventHandler<HTMLDivElement>\n /**\n * Overlay-mode panels portal into this id and cover the content column only. Defaults to\n * `DEFAULT_OVERLAY_ZONE_ID`; descendants read it with `useOverlayZoneId()`.\n */\n overlayZoneId?: string\n className?: string\n}\n\n/**\n * The content column beside the sidebar. It is `relative` so overlay-mode panels (portalled into\n * the overlay zone) cover this region only, leaving the sidebar and its actions interactive.\n */\nfunction ShellContent({\n children,\n scrollRef,\n onClick,\n overlayZoneId = DEFAULT_OVERLAY_ZONE_ID,\n className,\n}: ShellContentProps) {\n return (\n <div\n data-slot=\"shell-content\"\n className={cn('flex min-w-0 flex-1 flex-col', className)}\n onClick={onClick}\n >\n <div className=\"relative min-h-0 flex-1\">\n <OverlayZoneContext.Provider value={overlayZoneId}>\n {/* The content column is a CSS container: pages and parts size by its width with\n container variants (`@3xl:`...), so an open dock or a narrow window is honoured,\n which viewport breakpoints cannot do. */}\n <div ref={scrollRef} className=\"@container h-full overflow-auto\">\n {children}\n </div>\n </OverlayZoneContext.Provider>\n <div id={overlayZoneId} data-slot=\"overlay-zone\" />\n </div>\n </div>\n )\n}\n\nexport interface ShellTopbarProps {\n /** Left side: guidance / breadcrumbs, centred in the page column. */\n children?: ReactNode\n /** Right side: the action cluster. */\n actions?: ReactNode\n className?: string\n}\n\n/** A minimal white header for pages with no sidebar (the workspaces list). */\nfunction ShellTopbar({ children, actions, className }: ShellTopbarProps) {\n return (\n // `relative z-30` keeps dropdowns the header opens above the page region (a later sibling).\n <div\n data-slot=\"shell-topbar\"\n className={cn('relative z-30 flex h-14 shrink-0 items-center bg-background px-2', className)}\n >\n <div className=\"mx-auto flex w-full max-w-6xl items-center\">\n <div className=\"hidden min-w-0 flex-1 px-6 sm:block\">{children}</div>\n </div>\n <div className=\"absolute right-4 top-1/2 flex -translate-y-1/2 items-center gap-1\">\n {actions}\n </div>\n </div>\n )\n}\n\nexport interface ShellDockProps {\n isOpen: boolean\n /** Called with `false` by the mobile close button. */\n onOpenChange?: (isOpen: boolean) => void\n /** Desktop width (CSS length or px). Default 24rem. */\n width?: number | string\n /** Phone layout: the dock covers the screen instead of sitting beside the content. */\n isMobile?: boolean\n /** Accessible name of the dock. */\n label: string\n /** Mobile close button label. */\n closeLabel?: string\n children: ReactNode\n className?: string\n 'data-testid'?: string\n}\n\n/**\n * A right-hand dock for a companion surface (chat, inspector). Controlled: the host owns\n * `isOpen`, the width and the mobile breakpoint. Pass it to `Shell.Root` as `aside`.\n */\nfunction ShellDock({\n isOpen,\n onOpenChange,\n width = '24rem',\n isMobile = false,\n label,\n closeLabel = 'Close',\n children,\n className,\n 'data-testid': testId,\n}: ShellDockProps) {\n // The phone dock covers the screen, so it is a modal: Escape closes, focus is trapped and\n // returns to the opener.\n const mobileRef = useRef<HTMLDivElement>(null)\n const closeMobile = useCallback(() => onOpenChange?.(false), [onOpenChange])\n useDrawerBehavior(isOpen && isMobile, closeMobile, mobileRef)\n if (!isOpen) return null\n if (isMobile) {\n return (\n <div\n ref={mobileRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={label}\n data-slot=\"shell-dock\"\n data-state=\"open\"\n data-mobile=\"true\"\n data-testid={testId}\n className={cn('fixed inset-0 z-40 flex flex-col bg-background', className)}\n >\n {onOpenChange && (\n <button\n type=\"button\"\n onClick={() => onOpenChange(false)}\n aria-label={closeLabel}\n className=\"absolute right-2 top-2 z-10 rounded-md p-2 text-muted-foreground hover:bg-muted\"\n >\n <X className=\"size-5\" />\n </button>\n )}\n {children}\n </div>\n )\n }\n return (\n <aside\n aria-label={label}\n data-slot=\"shell-dock\"\n data-state=\"open\"\n data-testid={testId}\n style={{ width }}\n className={cn(\n 'flex shrink-0 flex-col overflow-hidden border-l border-border bg-background',\n className\n )}\n >\n {children}\n </aside>\n )\n}\n\nexport const Shell = {\n Root: ShellRoot,\n Content: ShellContent,\n Topbar: ShellTopbar,\n Dock: ShellDock,\n}\n\nexport interface PageContainerProps {\n children: ReactNode\n /** Full width instead of the centred 72rem column. */\n wide?: boolean\n /** Stand-alone use: at least a screen tall, instead of filling the parent. */\n minScreen?: boolean\n /** Max width of the centred column (any Tailwind `max-w-*` class). Default `max-w-6xl`. */\n maxWidth?: string\n /**\n * Horizontal padding of the inner column (any Tailwind `px-*` classes, responsive variants\n * welcome). Default `px-4 sm:px-6 lg:px-8`; pass `px-0` for a full-bleed page, or the class\n * string of your own gutter. Use this prop, not `innerClassName`, to change the gutter: the\n * classes are concatenated without a merge step, so a second `px-*` would not reliably win.\n */\n padding?: string\n /** Extra classes for the inner column. */\n innerClassName?: string\n className?: string\n}\n\n/** Default gutter of {@link PageContainer}: tight on a phone, roomier from tablet up. */\nexport const DEFAULT_PAGE_CONTAINER_PADDING = 'px-4 sm:px-6 lg:px-8'\n\n/**\n * Page body wrapper: a white canvas with the standard 72rem column (or full width) and a responsive side gutter. Fills its\n * parent by default so sticky headers and h-full pages keep a definite height chain.\n *\n * NOT a CSS container: its content (a long thread) overflows it into the host's scroller, and\n * Chrome before ~v130 gives `container-type` layout containment, which turns that overflow into\n * ink overflow — the scroller sees no scroll height, so no scrollbar and a dead wheel. Container\n * queries resolve against the scroll surface instead (Shell.Content, the app's DockZone).\n */\nexport function PageContainer({\n children,\n wide = false,\n minScreen = false,\n maxWidth = 'max-w-6xl',\n padding = DEFAULT_PAGE_CONTAINER_PADDING,\n innerClassName,\n className,\n}: PageContainerProps) {\n return (\n <div\n data-slot=\"page-container\"\n className={cn(\n 'bg-background pb-safe',\n minScreen ? 'min-h-screen' : 'h-full min-h-0',\n className\n )}\n >\n <div\n className={cn(\n 'flex h-full w-full min-w-0 flex-col pb-safe',\n padding,\n !wide && cn('mx-auto', maxWidth),\n innerClassName\n )}\n >\n {children}\n </div>\n </div>\n )\n}\n\n/** Fixed strings of the sidebar toggle. */\nexport interface SidebarToggleButtonLabels {\n closeSidebar: string\n openSidebar: string\n}\n\nexport const DEFAULT_SIDEBAR_TOGGLE_BUTTON_LABELS: SidebarToggleButtonLabels = {\n closeSidebar: 'Close sidebar',\n openSidebar: 'Open sidebar',\n}\n\nexport interface SidebarToggleButtonProps {\n /** The sidebar is open (pinned). */\n isOpen: boolean\n onToggle: () => void\n labels?: Partial<SidebarToggleButtonLabels>\n 'data-testid'?: string\n}\n\n/** Opens/closes the sidebar from a page header, so the control sits in the same spot everywhere. */\nexport function SidebarToggleButton({\n isOpen,\n onToggle,\n labels,\n 'data-testid': testId = 'tabheader-sidebar-toggle',\n}: SidebarToggleButtonProps) {\n const l = { ...DEFAULT_SIDEBAR_TOGGLE_BUTTON_LABELS, ...labels }\n const label = isOpen ? l.closeSidebar : l.openSidebar\n return (\n <button\n type=\"button\"\n onClick={onToggle}\n className=\"rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground pointer-coarse:p-2.5\"\n aria-label={label}\n title={label}\n data-testid={testId}\n >\n <PanelLeft className=\"size-5\" />\n </button>\n )\n}\n","import type { ReactNode } from 'react'\nimport { cn } from '@arbidocs/react/ui'\n\nexport interface ToolButtonProps {\n onClick: () => void\n /** Accessible name and native tooltip. */\n label: string\n /** The panel/page this opens is showing. */\n active?: boolean\n 'data-testid'?: string\n children: ReactNode\n}\n\n/** An icon button for a topbar or toolbar: 36px (44px coarse), selection tint while active. */\nexport function ToolButton({\n onClick,\n label,\n active = false,\n 'data-testid': testId,\n children,\n}: ToolButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title={label}\n aria-label={label}\n data-slot=\"tool-button\"\n data-testid={testId}\n className={cn(\n 'relative flex size-9 shrink-0 items-center justify-center rounded-md transition-colors hover:bg-accent hover:text-accent-foreground pointer-coarse:size-11',\n active ? 'bg-accent text-accent-foreground' : 'text-muted-foreground'\n )}\n >\n {children}\n </button>\n )\n}\n"]}
@@ -254,7 +254,7 @@ function PageContainer({
254
254
  {
255
255
  "data-slot": "page-container",
256
256
  className: ui.cn(
257
- "@container bg-background pb-safe",
257
+ "bg-background pb-safe",
258
258
  minScreen ? "min-h-screen" : "h-full min-h-0",
259
259
  className
260
260
  ),
@@ -335,5 +335,5 @@ exports.ToolButton = ToolButton;
335
335
  exports.useDrawerBehavior = useDrawerBehavior;
336
336
  exports.useOverlayZoneId = useOverlayZoneId;
337
337
  exports.useShellBottomInset = useShellBottomInset;
338
- //# sourceMappingURL=chunk-VGOFFCMT.cjs.map
339
- //# sourceMappingURL=chunk-VGOFFCMT.cjs.map
338
+ //# sourceMappingURL=chunk-B6MVQCXW.cjs.map
339
+ //# sourceMappingURL=chunk-B6MVQCXW.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/bottom-inset.ts","../src/provider/TooltipScope.tsx","../src/lib/use-drawer.ts","../src/shell/Shell.tsx","../src/shell/ToolButton.tsx"],"names":["useEffect","observeResize","createContext","useContext","jsx","Fragment","TooltipProvider","useRef","jsxs","cn","useCallback","X","PanelLeft"],"mappings":"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","file":"chunk-VGOFFCMT.cjs","sourcesContent":["import { useEffect, type RefObject } from 'react'\nimport { observeResize } from './observe-resize'\n\n/**\n * The CSS custom property that carries how much of the screen's bottom edge is taken by pinned\n * bars (the phone tab bar, a chat composer), set on `<html>`. A floating element (the install\n * prompt, a toast, a back-to-top button) positions itself `calc(var(--shell-bottom-inset, 0px) +\n * 0.75rem)` so it never covers those bars.\n */\nexport const SHELL_BOTTOM_INSET_VAR = '--shell-bottom-inset'\n\nconst measurers = new Map<symbol, () => number>()\n\n/** Re-measure every registered bar and publish the largest: bars stack, so the tallest reach wins. */\nfunction apply(): void {\n if (typeof document === 'undefined') return\n let inset = 0\n for (const measure of measurers.values()) inset = Math.max(inset, measure())\n const style = document.documentElement.style\n if (inset > 0) style.setProperty(SHELL_BOTTOM_INSET_VAR, `${Math.round(inset)}px`)\n else style.removeProperty(SHELL_BOTTOM_INSET_VAR)\n}\n\n/**\n * Report a bottom-pinned element to {@link SHELL_BOTTOM_INSET_VAR}: its distance from the top of\n * the element to the bottom of the viewport, so a composer above the tab bar counts the tab bar\n * too (contributions are combined with `max`, not summed). An element that is not rendered\n * (`display: none`, e.g. the phone-only tab bar on a desktop width) contributes 0. Used by\n * `MobileTabBar` and the chat composer; call it from your own bottom bar.\n */\nexport function useShellBottomInset(\n ref: RefObject<HTMLElement | null>,\n enabled: boolean = true\n): void {\n useEffect(() => {\n const el = ref.current\n if (!enabled || !el) return\n const key = Symbol('shell-bottom-inset')\n measurers.set(key, () => {\n const rect = el.getBoundingClientRect()\n return rect.height > 0 ? Math.max(0, window.innerHeight - rect.top) : 0\n })\n apply()\n // Any bar resizing moves the others (a composer sits on top of the tab bar): re-measure all.\n const stop = observeResize(el, apply)\n window.addEventListener('resize', apply)\n return () => {\n stop()\n window.removeEventListener('resize', apply)\n measurers.delete(key)\n apply()\n }\n }, [ref, enabled])\n}\n","import { createContext, useContext, type ReactNode } from 'react'\nimport { TooltipProvider } from '@arbidocs/react/ui'\n\nconst TooltipScopeContext = createContext(false)\n\n/**\n * A TooltipProvider that mounts once: inside another `BlocksTooltipProvider` (e.g. a Sidebar under\n * Shell.Root) it renders its children as-is, so tooltips share one delay group. Blocks that show\n * tooltips use this instead of the kit's provider.\n */\nexport function BlocksTooltipProvider({ children }: { children: ReactNode }) {\n const isNested = useContext(TooltipScopeContext)\n if (isNested) return <>{children}</>\n return (\n <TooltipScopeContext.Provider value>\n <TooltipProvider>{children}</TooltipProvider>\n </TooltipScopeContext.Provider>\n )\n}\n","import { useEffect, useRef, type RefObject } from 'react'\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n\nfunction focusableIn(container: HTMLElement): HTMLElement[] {\n return Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE)).filter(\n (el) => !el.closest('[inert]') && el.getAttribute('aria-hidden') !== 'true'\n )\n}\n\n/**\n * Behaviour of a modal surface (off-canvas drawer, full-screen dock) while it is open: the page\n * behind does not scroll, Escape closes it, focus moves inside and Tab/Shift+Tab cycle within it\n * (portalled popovers opened from inside stay reachable: only the wrap-around is intercepted),\n * and focus returns to the opener on close. Restores the previous body overflow on close/unmount.\n *\n * Pass `containerRef` (the element carrying `role=\"dialog\"`) to get the focus handling; without it\n * only scroll lock and Escape apply.\n */\nexport function useDrawerBehavior(\n isOpen: boolean,\n onClose: () => void,\n containerRef?: RefObject<HTMLElement | null>\n): void {\n // A fresh `onClose` identity per render must not re-run the effect (it would steal focus).\n const onCloseRef = useRef(onClose)\n useEffect(() => {\n onCloseRef.current = onClose\n })\n\n useEffect(() => {\n if (!isOpen) return\n const previousOverflow = document.body.style.overflow\n const opener = document.activeElement instanceof HTMLElement ? document.activeElement : null\n document.body.style.overflow = 'hidden'\n\n const container = containerRef?.current ?? null\n if (container) {\n const first = focusableIn(container)[0]\n if (first) first.focus()\n else {\n if (!container.hasAttribute('tabindex')) container.setAttribute('tabindex', '-1')\n container.focus()\n }\n }\n\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onCloseRef.current()\n return\n }\n if (e.key !== 'Tab' || !container) return\n const items = focusableIn(container)\n if (items.length === 0) {\n e.preventDefault()\n return\n }\n const firstItem = items[0]\n const lastItem = items[items.length - 1]\n const active = document.activeElement\n if (!container.contains(active)) {\n e.preventDefault()\n firstItem.focus()\n } else if (e.shiftKey && active === firstItem) {\n e.preventDefault()\n lastItem.focus()\n } else if (!e.shiftKey && active === lastItem) {\n e.preventDefault()\n firstItem.focus()\n }\n }\n window.addEventListener('keydown', onKey)\n return () => {\n document.body.style.overflow = previousOverflow\n window.removeEventListener('keydown', onKey)\n if (opener?.isConnected) opener.focus()\n }\n }, [isOpen, containerRef])\n}\n","import {\n createContext,\n useCallback,\n useContext,\n useRef,\n type MouseEventHandler,\n type ReactNode,\n type Ref,\n} from 'react'\nimport { PanelLeft, X } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { useDrawerBehavior } from '../lib/use-drawer'\nimport { BlocksTooltipProvider } from '../provider/TooltipScope'\n\n/** Default id of the element overlay-mode panels portal into (see `Shell.Content`). */\nexport const DEFAULT_OVERLAY_ZONE_ID = 'app-overlay-zone'\n\nconst OverlayZoneContext = createContext(DEFAULT_OVERLAY_ZONE_ID)\n\n/** The id of the enclosing `Shell.Content` overlay zone, for panels that portal into it. */\nexport function useOverlayZoneId(): string {\n return useContext(OverlayZoneContext)\n}\n\nexport interface ShellRootProps {\n /** Full-width strip above everything (e.g. a deletion-pending banner). */\n banner?: ReactNode\n /** Top chrome: a Shell.Topbar on list pages, a MobileAppBar on phones; omit for none. */\n topbar?: ReactNode\n /** The Sidebar.Root (and its drawer backdrop). */\n sidebar?: ReactNode\n /** Phone bottom navigation. */\n tabBar?: ReactNode\n /** Right-hand column beside the content: a `Shell.Dock` (chat, inspector...). */\n aside?: ReactNode\n /** Extra layers inside the body row (connection monitor, …). */\n overlays?: ReactNode\n /** The Shell.Content region. */\n children: ReactNode\n className?: string\n 'data-testid'?: string\n}\n\n/**\n * The application frame: banner, top chrome, then a body row holding the sidebar beside the\n * content, then the phone tab bar. Every region is a slot, so a custom UI composes its own.\n */\nfunction ShellRoot({\n banner,\n topbar,\n sidebar,\n tabBar,\n aside,\n overlays,\n children,\n className,\n 'data-testid': testId,\n}: ShellRootProps) {\n return (\n <BlocksTooltipProvider>\n <div\n data-slot=\"shell\"\n data-testid={testId}\n className={cn('flex h-screen h-dvh flex-col', className)}\n >\n {banner}\n {topbar}\n {/* `relative` anchors the sidebar's slide-out overlays to this row. */}\n <div className=\"relative flex flex-1 overflow-hidden\">\n {sidebar}\n {children}\n {aside}\n {overlays}\n </div>\n {tabBar}\n </div>\n </BlocksTooltipProvider>\n )\n}\n\nexport interface ShellContentProps {\n children: ReactNode\n /** Scrolling element, for scroll restoration. */\n scrollRef?: Ref<HTMLDivElement>\n onClick?: MouseEventHandler<HTMLDivElement>\n /**\n * Overlay-mode panels portal into this id and cover the content column only. Defaults to\n * `DEFAULT_OVERLAY_ZONE_ID`; descendants read it with `useOverlayZoneId()`.\n */\n overlayZoneId?: string\n className?: string\n}\n\n/**\n * The content column beside the sidebar. It is `relative` so overlay-mode panels (portalled into\n * the overlay zone) cover this region only, leaving the sidebar and its actions interactive.\n */\nfunction ShellContent({\n children,\n scrollRef,\n onClick,\n overlayZoneId = DEFAULT_OVERLAY_ZONE_ID,\n className,\n}: ShellContentProps) {\n return (\n <div\n data-slot=\"shell-content\"\n className={cn('flex min-w-0 flex-1 flex-col', className)}\n onClick={onClick}\n >\n <div className=\"relative min-h-0 flex-1\">\n <OverlayZoneContext.Provider value={overlayZoneId}>\n {/* The content column is a CSS container: pages and parts size by its width with\n container variants (`@3xl:`...), so an open dock or a narrow window is honoured,\n which viewport breakpoints cannot do. */}\n <div ref={scrollRef} className=\"@container h-full overflow-auto\">\n {children}\n </div>\n </OverlayZoneContext.Provider>\n <div id={overlayZoneId} data-slot=\"overlay-zone\" />\n </div>\n </div>\n )\n}\n\nexport interface ShellTopbarProps {\n /** Left side: guidance / breadcrumbs, centred in the page column. */\n children?: ReactNode\n /** Right side: the action cluster. */\n actions?: ReactNode\n className?: string\n}\n\n/** A minimal white header for pages with no sidebar (the workspaces list). */\nfunction ShellTopbar({ children, actions, className }: ShellTopbarProps) {\n return (\n // `relative z-30` keeps dropdowns the header opens above the page region (a later sibling).\n <div\n data-slot=\"shell-topbar\"\n className={cn('relative z-30 flex h-14 shrink-0 items-center bg-background px-2', className)}\n >\n <div className=\"mx-auto flex w-full max-w-6xl items-center\">\n <div className=\"hidden min-w-0 flex-1 px-6 sm:block\">{children}</div>\n </div>\n <div className=\"absolute right-4 top-1/2 flex -translate-y-1/2 items-center gap-1\">\n {actions}\n </div>\n </div>\n )\n}\n\nexport interface ShellDockProps {\n isOpen: boolean\n /** Called with `false` by the mobile close button. */\n onOpenChange?: (isOpen: boolean) => void\n /** Desktop width (CSS length or px). Default 24rem. */\n width?: number | string\n /** Phone layout: the dock covers the screen instead of sitting beside the content. */\n isMobile?: boolean\n /** Accessible name of the dock. */\n label: string\n /** Mobile close button label. */\n closeLabel?: string\n children: ReactNode\n className?: string\n 'data-testid'?: string\n}\n\n/**\n * A right-hand dock for a companion surface (chat, inspector). Controlled: the host owns\n * `isOpen`, the width and the mobile breakpoint. Pass it to `Shell.Root` as `aside`.\n */\nfunction ShellDock({\n isOpen,\n onOpenChange,\n width = '24rem',\n isMobile = false,\n label,\n closeLabel = 'Close',\n children,\n className,\n 'data-testid': testId,\n}: ShellDockProps) {\n // The phone dock covers the screen, so it is a modal: Escape closes, focus is trapped and\n // returns to the opener.\n const mobileRef = useRef<HTMLDivElement>(null)\n const closeMobile = useCallback(() => onOpenChange?.(false), [onOpenChange])\n useDrawerBehavior(isOpen && isMobile, closeMobile, mobileRef)\n if (!isOpen) return null\n if (isMobile) {\n return (\n <div\n ref={mobileRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={label}\n data-slot=\"shell-dock\"\n data-state=\"open\"\n data-mobile=\"true\"\n data-testid={testId}\n className={cn('fixed inset-0 z-40 flex flex-col bg-background', className)}\n >\n {onOpenChange && (\n <button\n type=\"button\"\n onClick={() => onOpenChange(false)}\n aria-label={closeLabel}\n className=\"absolute right-2 top-2 z-10 rounded-md p-2 text-muted-foreground hover:bg-muted\"\n >\n <X className=\"size-5\" />\n </button>\n )}\n {children}\n </div>\n )\n }\n return (\n <aside\n aria-label={label}\n data-slot=\"shell-dock\"\n data-state=\"open\"\n data-testid={testId}\n style={{ width }}\n className={cn(\n 'flex shrink-0 flex-col overflow-hidden border-l border-border bg-background',\n className\n )}\n >\n {children}\n </aside>\n )\n}\n\nexport const Shell = {\n Root: ShellRoot,\n Content: ShellContent,\n Topbar: ShellTopbar,\n Dock: ShellDock,\n}\n\nexport interface PageContainerProps {\n children: ReactNode\n /** Full width instead of the centred 72rem column. */\n wide?: boolean\n /** Stand-alone use: at least a screen tall, instead of filling the parent. */\n minScreen?: boolean\n /** Max width of the centred column (any Tailwind `max-w-*` class). Default `max-w-6xl`. */\n maxWidth?: string\n /**\n * Horizontal padding of the inner column (any Tailwind `px-*` classes, responsive variants\n * welcome). Default `px-4 sm:px-6 lg:px-8`; pass `px-0` for a full-bleed page, or the class\n * string of your own gutter. Use this prop, not `innerClassName`, to change the gutter: the\n * classes are concatenated without a merge step, so a second `px-*` would not reliably win.\n */\n padding?: string\n /** Extra classes for the inner column. */\n innerClassName?: string\n className?: string\n}\n\n/** Default gutter of {@link PageContainer}: tight on a phone, roomier from tablet up. */\nexport const DEFAULT_PAGE_CONTAINER_PADDING = 'px-4 sm:px-6 lg:px-8'\n\n/**\n * Page body wrapper: a white canvas with the standard 72rem column (or full width) and a responsive side gutter. Fills its\n * parent by default so sticky headers and h-full pages keep a definite height chain.\n */\nexport function PageContainer({\n children,\n wide = false,\n minScreen = false,\n maxWidth = 'max-w-6xl',\n padding = DEFAULT_PAGE_CONTAINER_PADDING,\n innerClassName,\n className,\n}: PageContainerProps) {\n return (\n <div\n data-slot=\"page-container\"\n className={cn(\n '@container bg-background pb-safe',\n minScreen ? 'min-h-screen' : 'h-full min-h-0',\n className\n )}\n >\n <div\n className={cn(\n 'flex h-full w-full min-w-0 flex-col pb-safe',\n padding,\n !wide && cn('mx-auto', maxWidth),\n innerClassName\n )}\n >\n {children}\n </div>\n </div>\n )\n}\n\n/** Fixed strings of the sidebar toggle. */\nexport interface SidebarToggleButtonLabels {\n closeSidebar: string\n openSidebar: string\n}\n\nexport const DEFAULT_SIDEBAR_TOGGLE_BUTTON_LABELS: SidebarToggleButtonLabels = {\n closeSidebar: 'Close sidebar',\n openSidebar: 'Open sidebar',\n}\n\nexport interface SidebarToggleButtonProps {\n /** The sidebar is open (pinned). */\n isOpen: boolean\n onToggle: () => void\n labels?: Partial<SidebarToggleButtonLabels>\n 'data-testid'?: string\n}\n\n/** Opens/closes the sidebar from a page header, so the control sits in the same spot everywhere. */\nexport function SidebarToggleButton({\n isOpen,\n onToggle,\n labels,\n 'data-testid': testId = 'tabheader-sidebar-toggle',\n}: SidebarToggleButtonProps) {\n const l = { ...DEFAULT_SIDEBAR_TOGGLE_BUTTON_LABELS, ...labels }\n const label = isOpen ? l.closeSidebar : l.openSidebar\n return (\n <button\n type=\"button\"\n onClick={onToggle}\n className=\"rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground pointer-coarse:p-2.5\"\n aria-label={label}\n title={label}\n data-testid={testId}\n >\n <PanelLeft className=\"size-5\" />\n </button>\n )\n}\n","import type { ReactNode } from 'react'\nimport { cn } from '@arbidocs/react/ui'\n\nexport interface ToolButtonProps {\n onClick: () => void\n /** Accessible name and native tooltip. */\n label: string\n /** The panel/page this opens is showing. */\n active?: boolean\n 'data-testid'?: string\n children: ReactNode\n}\n\n/** An icon button for a topbar or toolbar: 36px (44px coarse), selection tint while active. */\nexport function ToolButton({\n onClick,\n label,\n active = false,\n 'data-testid': testId,\n children,\n}: ToolButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title={label}\n aria-label={label}\n data-slot=\"tool-button\"\n data-testid={testId}\n className={cn(\n 'relative flex size-9 shrink-0 items-center justify-center rounded-md transition-colors hover:bg-accent hover:text-accent-foreground pointer-coarse:size-11',\n active ? 'bg-accent text-accent-foreground' : 'text-muted-foreground'\n )}\n >\n {children}\n </button>\n )\n}\n"]}
1
+ {"version":3,"sources":["../src/lib/bottom-inset.ts","../src/provider/TooltipScope.tsx","../src/lib/use-drawer.ts","../src/shell/Shell.tsx","../src/shell/ToolButton.tsx"],"names":["useEffect","observeResize","createContext","useContext","jsx","Fragment","TooltipProvider","useRef","jsxs","cn","useCallback","X","PanelLeft"],"mappings":"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","file":"chunk-B6MVQCXW.cjs","sourcesContent":["import { useEffect, type RefObject } from 'react'\nimport { observeResize } from './observe-resize'\n\n/**\n * The CSS custom property that carries how much of the screen's bottom edge is taken by pinned\n * bars (the phone tab bar, a chat composer), set on `<html>`. A floating element (the install\n * prompt, a toast, a back-to-top button) positions itself `calc(var(--shell-bottom-inset, 0px) +\n * 0.75rem)` so it never covers those bars.\n */\nexport const SHELL_BOTTOM_INSET_VAR = '--shell-bottom-inset'\n\nconst measurers = new Map<symbol, () => number>()\n\n/** Re-measure every registered bar and publish the largest: bars stack, so the tallest reach wins. */\nfunction apply(): void {\n if (typeof document === 'undefined') return\n let inset = 0\n for (const measure of measurers.values()) inset = Math.max(inset, measure())\n const style = document.documentElement.style\n if (inset > 0) style.setProperty(SHELL_BOTTOM_INSET_VAR, `${Math.round(inset)}px`)\n else style.removeProperty(SHELL_BOTTOM_INSET_VAR)\n}\n\n/**\n * Report a bottom-pinned element to {@link SHELL_BOTTOM_INSET_VAR}: its distance from the top of\n * the element to the bottom of the viewport, so a composer above the tab bar counts the tab bar\n * too (contributions are combined with `max`, not summed). An element that is not rendered\n * (`display: none`, e.g. the phone-only tab bar on a desktop width) contributes 0. Used by\n * `MobileTabBar` and the chat composer; call it from your own bottom bar.\n */\nexport function useShellBottomInset(\n ref: RefObject<HTMLElement | null>,\n enabled: boolean = true\n): void {\n useEffect(() => {\n const el = ref.current\n if (!enabled || !el) return\n const key = Symbol('shell-bottom-inset')\n measurers.set(key, () => {\n const rect = el.getBoundingClientRect()\n return rect.height > 0 ? Math.max(0, window.innerHeight - rect.top) : 0\n })\n apply()\n // Any bar resizing moves the others (a composer sits on top of the tab bar): re-measure all.\n const stop = observeResize(el, apply)\n window.addEventListener('resize', apply)\n return () => {\n stop()\n window.removeEventListener('resize', apply)\n measurers.delete(key)\n apply()\n }\n }, [ref, enabled])\n}\n","import { createContext, useContext, type ReactNode } from 'react'\nimport { TooltipProvider } from '@arbidocs/react/ui'\n\nconst TooltipScopeContext = createContext(false)\n\n/**\n * A TooltipProvider that mounts once: inside another `BlocksTooltipProvider` (e.g. a Sidebar under\n * Shell.Root) it renders its children as-is, so tooltips share one delay group. Blocks that show\n * tooltips use this instead of the kit's provider.\n */\nexport function BlocksTooltipProvider({ children }: { children: ReactNode }) {\n const isNested = useContext(TooltipScopeContext)\n if (isNested) return <>{children}</>\n return (\n <TooltipScopeContext.Provider value>\n <TooltipProvider>{children}</TooltipProvider>\n </TooltipScopeContext.Provider>\n )\n}\n","import { useEffect, useRef, type RefObject } from 'react'\n\nconst FOCUSABLE =\n 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])'\n\nfunction focusableIn(container: HTMLElement): HTMLElement[] {\n return Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE)).filter(\n (el) => !el.closest('[inert]') && el.getAttribute('aria-hidden') !== 'true'\n )\n}\n\n/**\n * Behaviour of a modal surface (off-canvas drawer, full-screen dock) while it is open: the page\n * behind does not scroll, Escape closes it, focus moves inside and Tab/Shift+Tab cycle within it\n * (portalled popovers opened from inside stay reachable: only the wrap-around is intercepted),\n * and focus returns to the opener on close. Restores the previous body overflow on close/unmount.\n *\n * Pass `containerRef` (the element carrying `role=\"dialog\"`) to get the focus handling; without it\n * only scroll lock and Escape apply.\n */\nexport function useDrawerBehavior(\n isOpen: boolean,\n onClose: () => void,\n containerRef?: RefObject<HTMLElement | null>\n): void {\n // A fresh `onClose` identity per render must not re-run the effect (it would steal focus).\n const onCloseRef = useRef(onClose)\n useEffect(() => {\n onCloseRef.current = onClose\n })\n\n useEffect(() => {\n if (!isOpen) return\n const previousOverflow = document.body.style.overflow\n const opener = document.activeElement instanceof HTMLElement ? document.activeElement : null\n document.body.style.overflow = 'hidden'\n\n const container = containerRef?.current ?? null\n if (container) {\n const first = focusableIn(container)[0]\n if (first) first.focus()\n else {\n if (!container.hasAttribute('tabindex')) container.setAttribute('tabindex', '-1')\n container.focus()\n }\n }\n\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onCloseRef.current()\n return\n }\n if (e.key !== 'Tab' || !container) return\n const items = focusableIn(container)\n if (items.length === 0) {\n e.preventDefault()\n return\n }\n const firstItem = items[0]\n const lastItem = items[items.length - 1]\n const active = document.activeElement\n if (!container.contains(active)) {\n e.preventDefault()\n firstItem.focus()\n } else if (e.shiftKey && active === firstItem) {\n e.preventDefault()\n lastItem.focus()\n } else if (!e.shiftKey && active === lastItem) {\n e.preventDefault()\n firstItem.focus()\n }\n }\n window.addEventListener('keydown', onKey)\n return () => {\n document.body.style.overflow = previousOverflow\n window.removeEventListener('keydown', onKey)\n if (opener?.isConnected) opener.focus()\n }\n }, [isOpen, containerRef])\n}\n","import {\n createContext,\n useCallback,\n useContext,\n useRef,\n type MouseEventHandler,\n type ReactNode,\n type Ref,\n} from 'react'\nimport { PanelLeft, X } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { useDrawerBehavior } from '../lib/use-drawer'\nimport { BlocksTooltipProvider } from '../provider/TooltipScope'\n\n/** Default id of the element overlay-mode panels portal into (see `Shell.Content`). */\nexport const DEFAULT_OVERLAY_ZONE_ID = 'app-overlay-zone'\n\nconst OverlayZoneContext = createContext(DEFAULT_OVERLAY_ZONE_ID)\n\n/** The id of the enclosing `Shell.Content` overlay zone, for panels that portal into it. */\nexport function useOverlayZoneId(): string {\n return useContext(OverlayZoneContext)\n}\n\nexport interface ShellRootProps {\n /** Full-width strip above everything (e.g. a deletion-pending banner). */\n banner?: ReactNode\n /** Top chrome: a Shell.Topbar on list pages, a MobileAppBar on phones; omit for none. */\n topbar?: ReactNode\n /** The Sidebar.Root (and its drawer backdrop). */\n sidebar?: ReactNode\n /** Phone bottom navigation. */\n tabBar?: ReactNode\n /** Right-hand column beside the content: a `Shell.Dock` (chat, inspector...). */\n aside?: ReactNode\n /** Extra layers inside the body row (connection monitor, …). */\n overlays?: ReactNode\n /** The Shell.Content region. */\n children: ReactNode\n className?: string\n 'data-testid'?: string\n}\n\n/**\n * The application frame: banner, top chrome, then a body row holding the sidebar beside the\n * content, then the phone tab bar. Every region is a slot, so a custom UI composes its own.\n */\nfunction ShellRoot({\n banner,\n topbar,\n sidebar,\n tabBar,\n aside,\n overlays,\n children,\n className,\n 'data-testid': testId,\n}: ShellRootProps) {\n return (\n <BlocksTooltipProvider>\n <div\n data-slot=\"shell\"\n data-testid={testId}\n className={cn('flex h-screen h-dvh flex-col', className)}\n >\n {banner}\n {topbar}\n {/* `relative` anchors the sidebar's slide-out overlays to this row. */}\n <div className=\"relative flex flex-1 overflow-hidden\">\n {sidebar}\n {children}\n {aside}\n {overlays}\n </div>\n {tabBar}\n </div>\n </BlocksTooltipProvider>\n )\n}\n\nexport interface ShellContentProps {\n children: ReactNode\n /** Scrolling element, for scroll restoration. */\n scrollRef?: Ref<HTMLDivElement>\n onClick?: MouseEventHandler<HTMLDivElement>\n /**\n * Overlay-mode panels portal into this id and cover the content column only. Defaults to\n * `DEFAULT_OVERLAY_ZONE_ID`; descendants read it with `useOverlayZoneId()`.\n */\n overlayZoneId?: string\n className?: string\n}\n\n/**\n * The content column beside the sidebar. It is `relative` so overlay-mode panels (portalled into\n * the overlay zone) cover this region only, leaving the sidebar and its actions interactive.\n */\nfunction ShellContent({\n children,\n scrollRef,\n onClick,\n overlayZoneId = DEFAULT_OVERLAY_ZONE_ID,\n className,\n}: ShellContentProps) {\n return (\n <div\n data-slot=\"shell-content\"\n className={cn('flex min-w-0 flex-1 flex-col', className)}\n onClick={onClick}\n >\n <div className=\"relative min-h-0 flex-1\">\n <OverlayZoneContext.Provider value={overlayZoneId}>\n {/* The content column is a CSS container: pages and parts size by its width with\n container variants (`@3xl:`...), so an open dock or a narrow window is honoured,\n which viewport breakpoints cannot do. */}\n <div ref={scrollRef} className=\"@container h-full overflow-auto\">\n {children}\n </div>\n </OverlayZoneContext.Provider>\n <div id={overlayZoneId} data-slot=\"overlay-zone\" />\n </div>\n </div>\n )\n}\n\nexport interface ShellTopbarProps {\n /** Left side: guidance / breadcrumbs, centred in the page column. */\n children?: ReactNode\n /** Right side: the action cluster. */\n actions?: ReactNode\n className?: string\n}\n\n/** A minimal white header for pages with no sidebar (the workspaces list). */\nfunction ShellTopbar({ children, actions, className }: ShellTopbarProps) {\n return (\n // `relative z-30` keeps dropdowns the header opens above the page region (a later sibling).\n <div\n data-slot=\"shell-topbar\"\n className={cn('relative z-30 flex h-14 shrink-0 items-center bg-background px-2', className)}\n >\n <div className=\"mx-auto flex w-full max-w-6xl items-center\">\n <div className=\"hidden min-w-0 flex-1 px-6 sm:block\">{children}</div>\n </div>\n <div className=\"absolute right-4 top-1/2 flex -translate-y-1/2 items-center gap-1\">\n {actions}\n </div>\n </div>\n )\n}\n\nexport interface ShellDockProps {\n isOpen: boolean\n /** Called with `false` by the mobile close button. */\n onOpenChange?: (isOpen: boolean) => void\n /** Desktop width (CSS length or px). Default 24rem. */\n width?: number | string\n /** Phone layout: the dock covers the screen instead of sitting beside the content. */\n isMobile?: boolean\n /** Accessible name of the dock. */\n label: string\n /** Mobile close button label. */\n closeLabel?: string\n children: ReactNode\n className?: string\n 'data-testid'?: string\n}\n\n/**\n * A right-hand dock for a companion surface (chat, inspector). Controlled: the host owns\n * `isOpen`, the width and the mobile breakpoint. Pass it to `Shell.Root` as `aside`.\n */\nfunction ShellDock({\n isOpen,\n onOpenChange,\n width = '24rem',\n isMobile = false,\n label,\n closeLabel = 'Close',\n children,\n className,\n 'data-testid': testId,\n}: ShellDockProps) {\n // The phone dock covers the screen, so it is a modal: Escape closes, focus is trapped and\n // returns to the opener.\n const mobileRef = useRef<HTMLDivElement>(null)\n const closeMobile = useCallback(() => onOpenChange?.(false), [onOpenChange])\n useDrawerBehavior(isOpen && isMobile, closeMobile, mobileRef)\n if (!isOpen) return null\n if (isMobile) {\n return (\n <div\n ref={mobileRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={label}\n data-slot=\"shell-dock\"\n data-state=\"open\"\n data-mobile=\"true\"\n data-testid={testId}\n className={cn('fixed inset-0 z-40 flex flex-col bg-background', className)}\n >\n {onOpenChange && (\n <button\n type=\"button\"\n onClick={() => onOpenChange(false)}\n aria-label={closeLabel}\n className=\"absolute right-2 top-2 z-10 rounded-md p-2 text-muted-foreground hover:bg-muted\"\n >\n <X className=\"size-5\" />\n </button>\n )}\n {children}\n </div>\n )\n }\n return (\n <aside\n aria-label={label}\n data-slot=\"shell-dock\"\n data-state=\"open\"\n data-testid={testId}\n style={{ width }}\n className={cn(\n 'flex shrink-0 flex-col overflow-hidden border-l border-border bg-background',\n className\n )}\n >\n {children}\n </aside>\n )\n}\n\nexport const Shell = {\n Root: ShellRoot,\n Content: ShellContent,\n Topbar: ShellTopbar,\n Dock: ShellDock,\n}\n\nexport interface PageContainerProps {\n children: ReactNode\n /** Full width instead of the centred 72rem column. */\n wide?: boolean\n /** Stand-alone use: at least a screen tall, instead of filling the parent. */\n minScreen?: boolean\n /** Max width of the centred column (any Tailwind `max-w-*` class). Default `max-w-6xl`. */\n maxWidth?: string\n /**\n * Horizontal padding of the inner column (any Tailwind `px-*` classes, responsive variants\n * welcome). Default `px-4 sm:px-6 lg:px-8`; pass `px-0` for a full-bleed page, or the class\n * string of your own gutter. Use this prop, not `innerClassName`, to change the gutter: the\n * classes are concatenated without a merge step, so a second `px-*` would not reliably win.\n */\n padding?: string\n /** Extra classes for the inner column. */\n innerClassName?: string\n className?: string\n}\n\n/** Default gutter of {@link PageContainer}: tight on a phone, roomier from tablet up. */\nexport const DEFAULT_PAGE_CONTAINER_PADDING = 'px-4 sm:px-6 lg:px-8'\n\n/**\n * Page body wrapper: a white canvas with the standard 72rem column (or full width) and a responsive side gutter. Fills its\n * parent by default so sticky headers and h-full pages keep a definite height chain.\n *\n * NOT a CSS container: its content (a long thread) overflows it into the host's scroller, and\n * Chrome before ~v130 gives `container-type` layout containment, which turns that overflow into\n * ink overflow — the scroller sees no scroll height, so no scrollbar and a dead wheel. Container\n * queries resolve against the scroll surface instead (Shell.Content, the app's DockZone).\n */\nexport function PageContainer({\n children,\n wide = false,\n minScreen = false,\n maxWidth = 'max-w-6xl',\n padding = DEFAULT_PAGE_CONTAINER_PADDING,\n innerClassName,\n className,\n}: PageContainerProps) {\n return (\n <div\n data-slot=\"page-container\"\n className={cn(\n 'bg-background pb-safe',\n minScreen ? 'min-h-screen' : 'h-full min-h-0',\n className\n )}\n >\n <div\n className={cn(\n 'flex h-full w-full min-w-0 flex-col pb-safe',\n padding,\n !wide && cn('mx-auto', maxWidth),\n innerClassName\n )}\n >\n {children}\n </div>\n </div>\n )\n}\n\n/** Fixed strings of the sidebar toggle. */\nexport interface SidebarToggleButtonLabels {\n closeSidebar: string\n openSidebar: string\n}\n\nexport const DEFAULT_SIDEBAR_TOGGLE_BUTTON_LABELS: SidebarToggleButtonLabels = {\n closeSidebar: 'Close sidebar',\n openSidebar: 'Open sidebar',\n}\n\nexport interface SidebarToggleButtonProps {\n /** The sidebar is open (pinned). */\n isOpen: boolean\n onToggle: () => void\n labels?: Partial<SidebarToggleButtonLabels>\n 'data-testid'?: string\n}\n\n/** Opens/closes the sidebar from a page header, so the control sits in the same spot everywhere. */\nexport function SidebarToggleButton({\n isOpen,\n onToggle,\n labels,\n 'data-testid': testId = 'tabheader-sidebar-toggle',\n}: SidebarToggleButtonProps) {\n const l = { ...DEFAULT_SIDEBAR_TOGGLE_BUTTON_LABELS, ...labels }\n const label = isOpen ? l.closeSidebar : l.openSidebar\n return (\n <button\n type=\"button\"\n onClick={onToggle}\n className=\"rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground pointer-coarse:p-2.5\"\n aria-label={label}\n title={label}\n data-testid={testId}\n >\n <PanelLeft className=\"size-5\" />\n </button>\n )\n}\n","import type { ReactNode } from 'react'\nimport { cn } from '@arbidocs/react/ui'\n\nexport interface ToolButtonProps {\n onClick: () => void\n /** Accessible name and native tooltip. */\n label: string\n /** The panel/page this opens is showing. */\n active?: boolean\n 'data-testid'?: string\n children: ReactNode\n}\n\n/** An icon button for a topbar or toolbar: 36px (44px coarse), selection tint while active. */\nexport function ToolButton({\n onClick,\n label,\n active = false,\n 'data-testid': testId,\n children,\n}: ToolButtonProps) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n title={label}\n aria-label={label}\n data-slot=\"tool-button\"\n data-testid={testId}\n className={cn(\n 'relative flex size-9 shrink-0 items-center justify-center rounded-md transition-colors hover:bg-accent hover:text-accent-foreground pointer-coarse:size-11',\n active ? 'bg-accent text-accent-foreground' : 'text-muted-foreground'\n )}\n >\n {children}\n </button>\n )\n}\n"]}
@@ -1,9 +1,9 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var chunkXKSFJYOD_cjs = require('./chunk-XKSFJYOD.cjs');
5
- var chunkVP4KJ4LK_cjs = require('./chunk-VP4KJ4LK.cjs');
6
- var chunkVGOFFCMT_cjs = require('./chunk-VGOFFCMT.cjs');
4
+ var chunk5UHAWSEX_cjs = require('./chunk-5UHAWSEX.cjs');
5
+ var chunkS2KVJYBD_cjs = require('./chunk-S2KVJYBD.cjs');
6
+ var chunkB6MVQCXW_cjs = require('./chunk-B6MVQCXW.cjs');
7
7
  var chunk7UTB4PHM_cjs = require('./chunk-7UTB4PHM.cjs');
8
8
  var chunkMWDW5UBW_cjs = require('./chunk-MWDW5UBW.cjs');
9
9
  var chunkMHVNT4J3_cjs = require('./chunk-MHVNT4J3.cjs');
@@ -493,7 +493,7 @@ function ModelPickerPopover({
493
493
  title = "Select AI Model",
494
494
  children
495
495
  }) {
496
- return /* @__PURE__ */ jsxRuntime.jsx(chunkVGOFFCMT_cjs.BlocksTooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Popover, { open, onOpenChange, children: [
496
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkB6MVQCXW_cjs.BlocksTooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Popover, { open, onOpenChange, children: [
497
497
  /* @__PURE__ */ jsxRuntime.jsxs(ui.Tooltip, { children: [
498
498
  /* @__PURE__ */ jsxRuntime.jsx(ui.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(ui.PopoverTrigger, { asChild: true, children: trigger }) }),
499
499
  tooltip && !open && /* @__PURE__ */ jsxRuntime.jsx(ui.TooltipContent, { side: "top", children: tooltip })
@@ -1599,9 +1599,9 @@ function LabelPinRow({
1599
1599
  );
1600
1600
  }
1601
1601
  function AssistantToaster(props) {
1602
- const dock = chunkVP4KJ4LK_cjs.useAssistantDock();
1603
- const { isDockAvailable } = chunkVP4KJ4LK_cjs.useChatSurface();
1604
- return /* @__PURE__ */ jsxRuntime.jsx(chunkXKSFJYOD_cjs.Toaster, { ...props, dockOpen: dock.isOpen && isDockAvailable });
1602
+ const dock = chunkS2KVJYBD_cjs.useAssistantDock();
1603
+ const { isDockAvailable } = chunkS2KVJYBD_cjs.useChatSurface();
1604
+ return /* @__PURE__ */ jsxRuntime.jsx(chunk5UHAWSEX_cjs.Toaster, { ...props, dockOpen: dock.isOpen && isDockAvailable });
1605
1605
  }
1606
1606
  function hasMessageBody(value, recipientLabel = "ARBI") {
1607
1607
  const text = value.trim();
@@ -1866,5 +1866,5 @@ exports.transcriptRuns = transcriptRuns;
1866
1866
  exports.useDismissibleCard = useDismissibleCard;
1867
1867
  exports.useLongPaste = useLongPaste;
1868
1868
  exports.useRecipientDraft = useRecipientDraft;
1869
- //# sourceMappingURL=chunk-HBBJYRGI.cjs.map
1870
- //# sourceMappingURL=chunk-HBBJYRGI.cjs.map
1869
+ //# sourceMappingURL=chunk-CK4C3IQR.cjs.map
1870
+ //# sourceMappingURL=chunk-CK4C3IQR.cjs.map