@arbidocs/blocks 0.5.106 → 0.5.107
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.
- package/README.md +60 -6
- package/dist/{ConnectedCallDock-P7LK2HYF.cjs → ConnectedCallDock-H3WWFGXF.cjs} +8 -8
- package/dist/{ConnectedCallDock-P7LK2HYF.cjs.map → ConnectedCallDock-H3WWFGXF.cjs.map} +1 -1
- package/dist/{ConnectedCallDock-NEZJNTKH.js → ConnectedCallDock-TDYRHPAK.js} +6 -6
- package/dist/{ConnectedCallDock-NEZJNTKH.js.map → ConnectedCallDock-TDYRHPAK.js.map} +1 -1
- package/dist/{ConnectedCallRoom-FXTR4YFI.cjs → ConnectedCallRoom-55O5OUN7.cjs} +7 -7
- package/dist/{ConnectedCallRoom-FXTR4YFI.cjs.map → ConnectedCallRoom-55O5OUN7.cjs.map} +1 -1
- package/dist/{ConnectedCallRoom-K3X6ICCG.js → ConnectedCallRoom-Z6F6WCLH.js} +6 -6
- package/dist/{ConnectedCallRoom-K3X6ICCG.js.map → ConnectedCallRoom-Z6F6WCLH.js.map} +1 -1
- package/dist/{ConnectedNativeDocxComparison-7VJKOKYU.cjs → ConnectedNativeDocxComparison-DGBZJ4XA.cjs} +10 -10
- package/dist/{ConnectedNativeDocxComparison-7VJKOKYU.cjs.map → ConnectedNativeDocxComparison-DGBZJ4XA.cjs.map} +1 -1
- package/dist/{ConnectedNativeDocxComparison-FENZYWDH.js → ConnectedNativeDocxComparison-NVZRVNOS.js} +9 -9
- package/dist/{ConnectedNativeDocxComparison-FENZYWDH.js.map → ConnectedNativeDocxComparison-NVZRVNOS.js.map} +1 -1
- package/dist/{ConnectedNativeDocxEditor-HB5BHGZ2.cjs → ConnectedNativeDocxEditor-R4WINUUB.cjs} +10 -10
- package/dist/{ConnectedNativeDocxEditor-HB5BHGZ2.cjs.map → ConnectedNativeDocxEditor-R4WINUUB.cjs.map} +1 -1
- package/dist/{ConnectedNativeDocxEditor-CNQAMO2N.js → ConnectedNativeDocxEditor-RSVBN7DY.js} +8 -8
- package/dist/{ConnectedNativeDocxEditor-CNQAMO2N.js.map → ConnectedNativeDocxEditor-RSVBN7DY.js.map} +1 -1
- package/dist/{ConnectedProductionSetDialog-O4FWTZNF.js → ConnectedProductionSetDialog-2DFBXE2X.js} +5 -5
- package/dist/{ConnectedProductionSetDialog-O4FWTZNF.js.map → ConnectedProductionSetDialog-2DFBXE2X.js.map} +1 -1
- package/dist/{ConnectedProductionSetDialog-ENAIZWPK.cjs → ConnectedProductionSetDialog-KYDPQ7SG.cjs} +6 -6
- package/dist/{ConnectedProductionSetDialog-ENAIZWPK.cjs.map → ConnectedProductionSetDialog-KYDPQ7SG.cjs.map} +1 -1
- package/dist/{ConnectedStreamedWordArtifact-ILMKFCDC.js → ConnectedStreamedWordArtifact-HLJ5IIOU.js} +9 -9
- package/dist/ConnectedStreamedWordArtifact-HLJ5IIOU.js.map +1 -0
- package/dist/{ConnectedStreamedWordArtifact-BF6JET2D.cjs → ConnectedStreamedWordArtifact-JQ34AOUU.cjs} +10 -10
- package/dist/ConnectedStreamedWordArtifact-JQ34AOUU.cjs.map +1 -0
- package/dist/{DocumentReviewCard-UOLXZKZE.js → DocumentReviewCard-7JSXRJZ2.js} +6 -6
- package/dist/{DocumentReviewCard-UOLXZKZE.js.map → DocumentReviewCard-7JSXRJZ2.js.map} +1 -1
- package/dist/{DocumentReviewCard-QVQ2LGFH.cjs → DocumentReviewCard-C4HVT3WM.cjs} +8 -8
- package/dist/{DocumentReviewCard-QVQ2LGFH.cjs.map → DocumentReviewCard-C4HVT3WM.cjs.map} +1 -1
- package/dist/{FilesViewerDialog-5ELQYWAZ.js → FilesViewerDialog-IMQTZWKD.js} +16 -16
- package/dist/{FilesViewerDialog-5ELQYWAZ.js.map → FilesViewerDialog-IMQTZWKD.js.map} +1 -1
- package/dist/{FilesViewerDialog-XNGHHWYS.cjs → FilesViewerDialog-UP7GFHYN.cjs} +23 -23
- package/dist/{FilesViewerDialog-XNGHHWYS.cjs.map → FilesViewerDialog-UP7GFHYN.cjs.map} +1 -1
- package/dist/{RechartsRenderer-EJRIFAAP.js → RechartsRenderer-23OF4H6X.js} +3 -3
- package/dist/{RechartsRenderer-EJRIFAAP.js.map → RechartsRenderer-23OF4H6X.js.map} +1 -1
- package/dist/{RechartsRenderer-CNFQ5EHF.cjs → RechartsRenderer-GIRCW7DB.cjs} +4 -4
- package/dist/{RechartsRenderer-CNFQ5EHF.cjs.map → RechartsRenderer-GIRCW7DB.cjs.map} +1 -1
- package/dist/{WorkspaceTableView-HRCV6WR7.cjs → WorkspaceTableView-PJM47B5F.cjs} +8 -8
- package/dist/{WorkspaceTableView-HRCV6WR7.cjs.map → WorkspaceTableView-PJM47B5F.cjs.map} +1 -1
- package/dist/{WorkspaceTableView-DIMTW5P5.js → WorkspaceTableView-YDA7A4UJ.js} +6 -6
- package/dist/{WorkspaceTableView-DIMTW5P5.js.map → WorkspaceTableView-YDA7A4UJ.js.map} +1 -1
- package/dist/{ai-E6FA4Y4J.cjs → ai-ADS6YSS2.cjs} +17 -17
- package/dist/ai-ADS6YSS2.cjs.map +1 -0
- package/dist/{ai-WASSGEMI.js → ai-KHWTGBT5.js} +9 -9
- package/dist/ai-KHWTGBT5.js.map +1 -0
- package/dist/auth/index.cjs +32 -32
- package/dist/auth/index.js +1 -1
- package/dist/calls/index.cjs +49 -49
- package/dist/calls/index.js +10 -10
- package/dist/{chunk-VJAMDAR6.cjs → chunk-22KAKJ3W.cjs} +4 -4
- package/dist/{chunk-VJAMDAR6.cjs.map → chunk-22KAKJ3W.cjs.map} +1 -1
- package/dist/{chunk-DEIF2VAA.js → chunk-3GFQNJYE.js} +3 -3
- package/dist/{chunk-DEIF2VAA.js.map → chunk-3GFQNJYE.js.map} +1 -1
- package/dist/{chunk-LUO46ELJ.cjs → chunk-3YZKDCWY.cjs} +2 -2
- package/dist/chunk-3YZKDCWY.cjs.map +1 -0
- package/dist/{chunk-5OUOPKGE.cjs → chunk-45OU2UAA.cjs} +18 -18
- package/dist/{chunk-5OUOPKGE.cjs.map → chunk-45OU2UAA.cjs.map} +1 -1
- package/dist/{chunk-JXKNPKU6.cjs → chunk-4CIVQWAX.cjs} +4 -4
- package/dist/{chunk-JXKNPKU6.cjs.map → chunk-4CIVQWAX.cjs.map} +1 -1
- package/dist/{chunk-VOI26MXJ.cjs → chunk-5AC52BHL.cjs} +16 -16
- package/dist/{chunk-VOI26MXJ.cjs.map → chunk-5AC52BHL.cjs.map} +1 -1
- package/dist/{chunk-OG3TI5GX.js → chunk-6M5NAAWX.js} +47 -5
- package/dist/chunk-6M5NAAWX.js.map +1 -0
- package/dist/{chunk-IIUEDF3F.js → chunk-6ZYOUT73.js} +7 -7
- package/dist/{chunk-IIUEDF3F.js.map → chunk-6ZYOUT73.js.map} +1 -1
- package/dist/{chunk-TRI3LQVR.js → chunk-7S7YVBFK.js} +5 -5
- package/dist/{chunk-TRI3LQVR.js.map → chunk-7S7YVBFK.js.map} +1 -1
- package/dist/{chunk-QN5GTCPB.cjs → chunk-7V4OCZS6.cjs} +8 -8
- package/dist/{chunk-QN5GTCPB.cjs.map → chunk-7V4OCZS6.cjs.map} +1 -1
- package/dist/{chunk-S7NJVJJX.cjs → chunk-AHMRYY7J.cjs} +25 -25
- package/dist/{chunk-S7NJVJJX.cjs.map → chunk-AHMRYY7J.cjs.map} +1 -1
- package/dist/{chunk-GK5BMDS6.js → chunk-AVGHTUPE.js} +4 -4
- package/dist/{chunk-GK5BMDS6.js.map → chunk-AVGHTUPE.js.map} +1 -1
- package/dist/{chunk-RAYNCZ7O.js → chunk-AZCMKGDG.js} +3 -3
- package/dist/{chunk-RAYNCZ7O.js.map → chunk-AZCMKGDG.js.map} +1 -1
- package/dist/{chunk-IJVU5MZA.js → chunk-BAUZUIHB.js} +5 -5
- package/dist/{chunk-IJVU5MZA.js.map → chunk-BAUZUIHB.js.map} +1 -1
- package/dist/{chunk-2VHZUSFW.js → chunk-BBWLFK3C.js} +3 -3
- package/dist/{chunk-2VHZUSFW.js.map → chunk-BBWLFK3C.js.map} +1 -1
- package/dist/{chunk-MW7FGIF4.cjs → chunk-BFVCYBND.cjs} +9 -9
- package/dist/{chunk-MW7FGIF4.cjs.map → chunk-BFVCYBND.cjs.map} +1 -1
- package/dist/{chunk-7ONU7EWY.js → chunk-BH6IKGZ3.js} +5 -5
- package/dist/{chunk-7ONU7EWY.js.map → chunk-BH6IKGZ3.js.map} +1 -1
- package/dist/{chunk-RNX5LAQK.cjs → chunk-C42WBPH4.cjs} +7 -7
- package/dist/{chunk-RNX5LAQK.cjs.map → chunk-C42WBPH4.cjs.map} +1 -1
- package/dist/{chunk-LM5CPXJO.cjs → chunk-CRLFLMTK.cjs} +19 -13
- package/dist/chunk-CRLFLMTK.cjs.map +1 -0
- package/dist/{chunk-CWC6W2NE.cjs → chunk-D35EHOK5.cjs} +11 -11
- package/dist/{chunk-CWC6W2NE.cjs.map → chunk-D35EHOK5.cjs.map} +1 -1
- package/dist/{chunk-BMHW7WTF.js → chunk-DBKZANTC.js} +4 -4
- package/dist/{chunk-BMHW7WTF.js.map → chunk-DBKZANTC.js.map} +1 -1
- package/dist/{chunk-Q5U6Y2NO.js → chunk-E2P4JJLJ.js} +4 -45
- package/dist/chunk-E2P4JJLJ.js.map +1 -0
- package/dist/{chunk-D3GZWKHW.cjs → chunk-EKSHUNJI.cjs} +9 -9
- package/dist/{chunk-D3GZWKHW.cjs.map → chunk-EKSHUNJI.cjs.map} +1 -1
- package/dist/{chunk-5XQNXDST.js → chunk-FPOKWML2.js} +18 -5
- package/dist/chunk-FPOKWML2.js.map +1 -0
- package/dist/{chunk-M4TM3K52.cjs → chunk-FSXQHEFQ.cjs} +16 -16
- package/dist/{chunk-M4TM3K52.cjs.map → chunk-FSXQHEFQ.cjs.map} +1 -1
- package/dist/{chunk-35BADIIF.cjs → chunk-GX75YCWJ.cjs} +23 -23
- package/dist/{chunk-35BADIIF.cjs.map → chunk-GX75YCWJ.cjs.map} +1 -1
- package/dist/{chunk-7IF3E3I2.cjs → chunk-I7CJDF3V.cjs} +4 -4
- package/dist/{chunk-7IF3E3I2.cjs.map → chunk-I7CJDF3V.cjs.map} +1 -1
- package/dist/{chunk-KYLQRS3O.js → chunk-IHOV6OTA.js} +4 -4
- package/dist/{chunk-KYLQRS3O.js.map → chunk-IHOV6OTA.js.map} +1 -1
- package/dist/{chunk-OXHAZN43.cjs → chunk-IXL2KJOZ.cjs} +26 -26
- package/dist/{chunk-OXHAZN43.cjs.map → chunk-IXL2KJOZ.cjs.map} +1 -1
- package/dist/{chunk-632JXVXY.js → chunk-KIXFXCHL.js} +15 -9
- package/dist/chunk-KIXFXCHL.js.map +1 -0
- package/dist/{chunk-PIWT2GCY.cjs → chunk-LFYKB7KF.cjs} +15 -15
- package/dist/{chunk-PIWT2GCY.cjs.map → chunk-LFYKB7KF.cjs.map} +1 -1
- package/dist/{chunk-7Q6EVFMT.js → chunk-LYW5A35J.js} +9 -9
- package/dist/{chunk-7Q6EVFMT.js.map → chunk-LYW5A35J.js.map} +1 -1
- package/dist/chunk-NFK2SEUD.js +577 -0
- package/dist/chunk-NFK2SEUD.js.map +1 -0
- package/dist/{chunk-TJQMC7GJ.cjs → chunk-NNBL3HPG.cjs} +4 -4
- package/dist/{chunk-TJQMC7GJ.cjs.map → chunk-NNBL3HPG.cjs.map} +1 -1
- package/dist/{chunk-Y5P5ZMHQ.js → chunk-NWBCZ4PA.js} +4 -4
- package/dist/{chunk-Y5P5ZMHQ.js.map → chunk-NWBCZ4PA.js.map} +1 -1
- package/dist/{chunk-5UMZXDGL.cjs → chunk-O27K7KTZ.cjs} +161 -7
- package/dist/chunk-O27K7KTZ.cjs.map +1 -0
- package/dist/{chunk-GARDQALH.js → chunk-OLAYDOPC.js} +5 -5
- package/dist/{chunk-GARDQALH.js.map → chunk-OLAYDOPC.js.map} +1 -1
- package/dist/chunk-ORELHENJ.cjs +594 -0
- package/dist/chunk-ORELHENJ.cjs.map +1 -0
- package/dist/{chunk-NUOMPVKQ.js → chunk-OWHO2TO3.js} +3 -3
- package/dist/{chunk-NUOMPVKQ.js.map → chunk-OWHO2TO3.js.map} +1 -1
- package/dist/{chunk-6XNWGOS3.cjs → chunk-PHDUN4SG.cjs} +187 -80
- package/dist/chunk-PHDUN4SG.cjs.map +1 -0
- package/dist/{chunk-KGUBKE3V.cjs → chunk-PL7O3RJJ.cjs} +48 -4
- package/dist/chunk-PL7O3RJJ.cjs.map +1 -0
- package/dist/{chunk-BH4MK2J5.js → chunk-QG6MRLZG.js} +2 -2
- package/dist/chunk-QG6MRLZG.js.map +1 -0
- package/dist/{chunk-YPTZNQPJ.cjs → chunk-RCZRI72J.cjs} +4 -4
- package/dist/{chunk-YPTZNQPJ.cjs.map → chunk-RCZRI72J.cjs.map} +1 -1
- package/dist/{chunk-E7STRFBT.cjs → chunk-SCLGUHLU.cjs} +4 -4
- package/dist/{chunk-E7STRFBT.cjs.map → chunk-SCLGUHLU.cjs.map} +1 -1
- package/dist/{chunk-EOTJX536.js → chunk-T5ZMG6MC.js} +3 -3
- package/dist/{chunk-EOTJX536.js.map → chunk-T5ZMG6MC.js.map} +1 -1
- package/dist/{chunk-LWEX3AOZ.js → chunk-TG4IICWO.js} +4 -4
- package/dist/{chunk-LWEX3AOZ.js.map → chunk-TG4IICWO.js.map} +1 -1
- package/dist/{chunk-ET3W24JV.js → chunk-TNKPQ3EF.js} +9 -9
- package/dist/{chunk-ET3W24JV.js.map → chunk-TNKPQ3EF.js.map} +1 -1
- package/dist/{chunk-QFKL4HV2.js → chunk-U5F5P4YU.js} +118 -15
- package/dist/chunk-U5F5P4YU.js.map +1 -0
- package/dist/{chunk-N52PBUAP.cjs → chunk-U6LQ6Z3P.cjs} +10 -10
- package/dist/{chunk-N52PBUAP.cjs.map → chunk-U6LQ6Z3P.cjs.map} +1 -1
- package/dist/{chunk-JNVJQCGF.cjs → chunk-UCA4JLLJ.cjs} +4 -4
- package/dist/{chunk-JNVJQCGF.cjs.map → chunk-UCA4JLLJ.cjs.map} +1 -1
- package/dist/{chunk-3RUQHIDC.js → chunk-UQ2OBHMV.js} +7 -7
- package/dist/{chunk-3RUQHIDC.js.map → chunk-UQ2OBHMV.js.map} +1 -1
- package/dist/{chunk-VYJF4ZQY.cjs → chunk-V6C2MBFY.cjs} +3 -2
- package/dist/chunk-V6C2MBFY.cjs.map +1 -0
- package/dist/{chunk-O4X7HXLF.cjs → chunk-VCEX7COE.cjs} +2 -45
- package/dist/chunk-VCEX7COE.cjs.map +1 -0
- package/dist/{chunk-QTSNHGSI.js → chunk-WFM6E7DD.js} +3 -3
- package/dist/{chunk-QTSNHGSI.js.map → chunk-WFM6E7DD.js.map} +1 -1
- package/dist/{chunk-SY2WD6VA.cjs → chunk-WI3BVKEC.cjs} +5 -5
- package/dist/{chunk-SY2WD6VA.cjs.map → chunk-WI3BVKEC.cjs.map} +1 -1
- package/dist/{chunk-LWCLAAEX.js → chunk-WJHRWXWJ.js} +3 -3
- package/dist/{chunk-LWCLAAEX.js.map → chunk-WJHRWXWJ.js.map} +1 -1
- package/dist/{chunk-FVZ2CN4A.js → chunk-WQH2WWZE.js} +3 -2
- package/dist/chunk-WQH2WWZE.js.map +1 -0
- package/dist/{chunk-V2CKYM4B.cjs → chunk-XHN5KOI2.cjs} +9 -9
- package/dist/{chunk-V2CKYM4B.cjs.map → chunk-XHN5KOI2.cjs.map} +1 -1
- package/dist/{chunk-DBHBJIF4.js → chunk-YJWAGXYM.js} +3 -3
- package/dist/{chunk-DBHBJIF4.js.map → chunk-YJWAGXYM.js.map} +1 -1
- package/dist/{chunk-KUI2IC7W.js → chunk-YLKHTBYA.js} +3 -3
- package/dist/{chunk-KUI2IC7W.js.map → chunk-YLKHTBYA.js.map} +1 -1
- package/dist/{chunk-73FJ6L6I.cjs → chunk-ZMVF7EYJ.cjs} +18 -5
- package/dist/chunk-ZMVF7EYJ.cjs.map +1 -0
- package/dist/{chunk-CEVVGJQX.js → chunk-ZNY5W3VX.js} +162 -9
- package/dist/chunk-ZNY5W3VX.js.map +1 -0
- package/dist/connect/docx.cjs +13 -13
- package/dist/connect/docx.js +9 -9
- package/dist/connect/index.cjs +1100 -884
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.d.ts +1 -0
- package/dist/connect/index.js +475 -274
- package/dist/connect/index.js.map +1 -1
- package/dist/connect/viewer.cjs +12 -12
- package/dist/connect/viewer.js +10 -10
- package/dist/connection/account-cluster/ConnectedAccountCluster.d.ts +1 -1
- package/dist/connection/dashboards/ConnectedDashboardsPage.d.ts +13 -2
- package/dist/connection/dashboards/index.d.ts +1 -1
- package/dist/connection/dashboards/templates.d.ts +14 -3
- package/dist/connection/remote-control/ConnectedRemoteControlConsent.d.ts +17 -0
- package/dist/connection/remote-control/ConnectedRemoteControlIndicator.d.ts +8 -0
- package/dist/connection/remote-control/ConnectedRemoteControlSwitch.d.ts +1 -0
- package/dist/connection/remote-control/index.d.ts +4 -0
- package/dist/connection/remote-control/remoteControl.d.ts +40 -0
- package/dist/connection/routes/useDeepLinkSync.d.ts +4 -1
- package/dist/connection/runtime/ConnectedAppRuntime.d.ts +1 -1
- package/dist/connection/settings-page/settingsSections.d.ts +1 -1
- package/dist/connection/tags/ConnectedTagTable.d.ts +1 -1
- package/dist/dashboards/index.cjs +327 -116
- package/dist/dashboards/index.cjs.map +1 -1
- package/dist/dashboards/index.js +311 -101
- package/dist/dashboards/index.js.map +1 -1
- package/dist/embed/index.cjs +21 -21
- package/dist/embed/index.js +14 -14
- package/dist/guided/GuidedCursor.d.ts +21 -0
- package/dist/guided/cursor.d.ts +56 -0
- package/dist/guided/index.d.ts +5 -0
- package/dist/guided/runner.d.ts +30 -0
- package/dist/guided/sequences.d.ts +80 -0
- package/dist/guided/surfaces.d.ts +13 -0
- package/dist/guided/useGuidedRuns.d.ts +3 -0
- package/dist/index.cjs +171 -135
- package/dist/index.d.ts +1 -0
- package/dist/index.js +7 -7
- package/dist/provider/host.d.ts +6 -0
- package/dist/settings/PlanBadge.d.ts +1 -1
- package/dist/settings/TipsEditor.d.ts +6 -3
- package/dist/settings/index.cjs +152 -151
- package/dist/settings/index.js +3 -2
- package/dist/shell/index.cjs +46 -46
- package/dist/shell/index.js +3 -3
- package/dist/studio/index.cjs +15 -15
- package/dist/studio/index.js +9 -9
- package/dist/styles.css +1 -1
- package/dist/workflow-canvas/index.cjs +25 -25
- package/dist/workflow-canvas/index.js +13 -13
- package/node_modules/@arbidocs/coedit/package.json +1 -1
- package/package.json +5 -5
- package/dist/ConnectedStreamedWordArtifact-BF6JET2D.cjs.map +0 -1
- package/dist/ConnectedStreamedWordArtifact-ILMKFCDC.js.map +0 -1
- package/dist/ai-E6FA4Y4J.cjs.map +0 -1
- package/dist/ai-WASSGEMI.js.map +0 -1
- package/dist/chunk-5UMZXDGL.cjs.map +0 -1
- package/dist/chunk-5XQNXDST.js.map +0 -1
- package/dist/chunk-632JXVXY.js.map +0 -1
- package/dist/chunk-6XNWGOS3.cjs.map +0 -1
- package/dist/chunk-73FJ6L6I.cjs.map +0 -1
- package/dist/chunk-BH4MK2J5.js.map +0 -1
- package/dist/chunk-C4TGESIB.cjs +0 -260
- package/dist/chunk-C4TGESIB.cjs.map +0 -1
- package/dist/chunk-CEVVGJQX.js.map +0 -1
- package/dist/chunk-FVZ2CN4A.js.map +0 -1
- package/dist/chunk-KGUBKE3V.cjs.map +0 -1
- package/dist/chunk-LM5CPXJO.cjs.map +0 -1
- package/dist/chunk-LUO46ELJ.cjs.map +0 -1
- package/dist/chunk-MHFWGIF4.js +0 -254
- package/dist/chunk-MHFWGIF4.js.map +0 -1
- package/dist/chunk-O4X7HXLF.cjs.map +0 -1
- package/dist/chunk-OG3TI5GX.js.map +0 -1
- package/dist/chunk-Q5U6Y2NO.js.map +0 -1
- package/dist/chunk-QFKL4HV2.js.map +0 -1
- package/dist/chunk-VYJF4ZQY.cjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tips/registry.ts","../src/guided/cursor.ts","../src/guided/surfaces.ts","../src/guided/runner.ts","../src/guided/sequences.ts","../src/guided/useGuidedRuns.ts","../src/components/UsageMeter.tsx"],"names":["useEffect","createElement","MousePointerClick","useSyncExternalStore","sleep","notify","useHost","jsxs","jsx","cn"],"mappings":"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","file":"chunk-ORELHENJ.cjs","sourcesContent":["/**\n * The contextual tips engine: which tips apply where, and the editable layer over them. The tips\n * themselves (their words, pages, situations and actions) are the site's content; a site hands\n * them to {@link createTipsRegistry} once and shows the result in `TipCard` / its tip bar, edits it\n * in `TipsEditorDialog`, and hides tips per user with `useDismissedTips` (`@arbidocs/react`).\n *\n * Each tip has a stable `code`. The editable layer (`TipsContent`) overrides a built-in tip's\n * message, action or page, hides it, or adds tips authored in the editor; swapping it in\n * (`setContent`) updates every subscriber without a reload.\n */\n\n/** Max length of a tip message: the bar is one line, so a tip is one short sentence. */\nexport const TIP_MAX_CHARS = 80\n/** Max length of a tip's action label, so the inline button doesn't dominate. */\nexport const TIP_CTA_LABEL_MAX_CHARS = 24\n\n/**\n * A tip's action: a label and exactly one target. `action` and `sequence` are the site's own ids\n * (what its action registry runs); `href` opens in a new window.\n */\nexport interface TipCta<Action extends string = string, Sequence extends string = string> {\n label: string\n action?: Action\n sequence?: Sequence\n href?: string\n}\n\nexport interface TipDefinition<Context extends string, State, Cta> {\n /** Stable id (e.g. a page letter and a number). */\n code: string\n context: Context\n message: string\n /** Situation predicate; omitted: always applies on its page. */\n when?: (state: State) => boolean\n cta?: Cta\n /** Higher shows first. Default 0. */\n priority?: number\n /** Using the action also hides the tip for good (a one-shot offer, now taken). */\n dismissOnCta?: boolean\n}\n\n/** The editable layer over a built-in tip: omitted fields keep the built-in's; `cta: null` drops it. */\nexport interface TipOverride<Context extends string, Cta> {\n message?: string\n cta?: Cta | null\n context?: Context\n hidden?: boolean\n}\n\n/** A tip written in the editor: no situation predicate, so it always applies on its page. */\nexport interface CustomTip<Context extends string, Cta> {\n code: string\n context: Context\n message: string\n cta?: Cta\n priority?: number\n hidden?: boolean\n}\n\n/** The whole editable layer (a site keeps it as JSON next to its tips). */\nexport interface TipsContent<Context extends string, Cta> {\n overrides: Record<string, TipOverride<Context, Cta>>\n custom: CustomTip<Context, Cta>[]\n}\n\n/** A tip as the editor lists it: its effective form, where it came from and whether it is off. */\nexport interface EditorTip<Context extends string, State, Cta> {\n tip: TipDefinition<Context, State, Cta>\n isCustom: boolean\n isHidden: boolean\n}\n\nexport interface TipsRegistryConfig<Context extends string, State, Cta> {\n tips: readonly TipDefinition<Context, State, Cta>[]\n /** The committed editable layer. */\n content: TipsContent<Context, Cta>\n /** The page whose tips show on every page. */\n everywhere: Context\n /** Where a tip can be placed, with the editor's labels (\"All pages\" first, say). */\n placements: readonly { value: Context; label: string }[]\n /** The editor's label for \"off\". Default \"Hidden (off)\". */\n hiddenLabel?: string\n}\n\nexport type TipPlacement<Context extends string> = Context | 'hidden'\n\nexport interface TipsRegistry<Context extends string, State, Cta> {\n /** Tips for a page whose situation matches, highest priority first (plus every-page tips). */\n select: (context: Context, state: State) => TipDefinition<Context, State, Cta>[]\n /** Every tip for the editor, across pages, hidden ones included. */\n editorTips: () => EditorTip<Context, State, Cta>[]\n /** The live editable layer. */\n getContent: () => TipsContent<Context, Cta>\n /** Swap the editable layer and notify subscribers (no reload). */\n setContent: (next: TipsContent<Context, Cta>) => void\n /** Follow changes to the editable layer; returns the unsubscribe. */\n subscribe: (listener: () => void) => () => void\n /** The page whose tips show on every page (where a new tip starts in the editor). */\n everywhere: Context\n /** The editor's placement choices: each page, then \"off\". */\n placements: readonly { value: TipPlacement<Context>; label: string }[]\n placementLabel: (placement: TipPlacement<Context>) => string\n}\n\nexport function createTipsRegistry<Context extends string, State, Cta>(\n config: TipsRegistryConfig<Context, State, Cta>\n): TipsRegistry<Context, State, Cta> {\n const { tips, everywhere, hiddenLabel = 'Hidden (off)' } = config\n let content = config.content\n const listeners = new Set<() => void>()\n type Tip = TipDefinition<Context, State, Cta>\n\n const effective = (tip: Tip): { tip: Tip; hidden: boolean } => {\n const o = content.overrides?.[tip.code]\n if (!o) return { tip, hidden: false }\n return {\n tip: {\n ...tip,\n message: o.message ?? tip.message,\n cta: o.cta === null ? undefined : (o.cta ?? tip.cta),\n context: o.context ?? tip.context,\n },\n hidden: o.hidden === true,\n }\n }\n const custom = () => content.custom ?? []\n const applies = (tipContext: Context, context: Context) =>\n tipContext === context || tipContext === everywhere\n const placements: { value: TipPlacement<Context>; label: string }[] = [\n ...config.placements,\n { value: 'hidden', label: hiddenLabel },\n ]\n\n return {\n select: (context, state) => {\n const builtins = tips\n .map(effective)\n .filter(\n ({ tip, hidden }) =>\n !hidden && applies(tip.context, context) && (!tip.when || tip.when(state))\n )\n .map(({ tip }) => tip)\n const authored = custom().filter((t) => t.hidden !== true && applies(t.context, context))\n return [...builtins, ...(authored as Tip[])].sort(\n (a, b) => (b.priority ?? 0) - (a.priority ?? 0)\n )\n },\n editorTips: () => [\n ...tips.map((t) => {\n const e = effective(t)\n return { tip: e.tip, isCustom: false, isHidden: e.hidden }\n }),\n ...custom().map((t) => ({ tip: t as Tip, isCustom: true, isHidden: t.hidden === true })),\n ],\n getContent: () => content,\n setContent: (next) => {\n content = next\n listeners.forEach((listener) => listener())\n },\n subscribe: (listener) => {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n everywhere,\n placements,\n placementLabel: (p) => placements.find((o) => o.value === p)?.label ?? p,\n }\n}\n","/**\n * guidedCursor — a framework-agnostic controller for the on-screen \"someone is driving the UI\"\n * cursor. `<GuidedCursor/>` renders whatever this controller says; anything can drive it:\n *\n * await guidedCursor.glideTo('[data-testid=\"sidebar-documents-button\"]')\n * guidedCursor.ripple()\n *\n * Its consumers: the guided-run runner (a tip's \"Show me\", the tips editor's tester) and remote\n * control over the websocket, where the backend dictates the steps and the frontend performs them\n * visibly.\n *\n * The look (ring, click squish/glow, ripple) is defined by ./cursor-visuals.json, the single source\n * of truth also consumed by `<GuidedCursor/>` and by ARBI-frontend's demo-video recorder\n * (scripts/lib/cursor-overlay.cjs).\n */\n\nconst GLIDE_MS = 580\nconst SCROLL_SETTLE_MS = 180\nconst DEFAULT_WAIT_MS = 1200\n// Let the ring paint at its current spot before moving, so the CSS transition\n// animates the glide instead of the show+move batching into a teleport.\nconst PAINT_MS = 60\n\nconst sleep = (ms: number) => new Promise<void>((r) => setTimeout(r, ms))\n\ninterface CursorSnapshot {\n visible: boolean\n x: number\n y: number\n}\n\ntype RippleListener = (x: number, y: number) => void\n\nclass GuidedCursorController {\n /** Glide duration (ms) — exported so the component's CSS transition matches. */\n readonly glideMs = GLIDE_MS\n\n private snap: CursorSnapshot = { visible: false, x: -100, y: -100 }\n private listeners = new Set<() => void>()\n private rippleListeners = new Set<RippleListener>()\n // The user's real pointer, so a run begins where their eye already is (they\n // just clicked \"Show me\"). Defaults to the lower-left, near the sidebar tips.\n private lastPointer = {\n x: typeof window !== 'undefined' ? 120 : 0,\n y: typeof window !== 'undefined' ? window.innerHeight - 60 : 0,\n }\n\n constructor() {\n if (typeof window !== 'undefined') {\n const track = (e: PointerEvent | MouseEvent) => {\n this.lastPointer = { x: e.clientX, y: e.clientY }\n }\n window.addEventListener('pointermove', track, { passive: true })\n window.addEventListener('pointerdown', track, { passive: true })\n }\n }\n\n // external-store contract (useSyncExternalStore). getSnapshot returns a stable\n // reference between changes, so React only re-renders on real moves.\n subscribe = (cb: () => void): (() => void) => {\n this.listeners.add(cb)\n return () => this.listeners.delete(cb)\n }\n getSnapshot = (): CursorSnapshot => this.snap\n onRipple = (cb: RippleListener): (() => void) => {\n this.rippleListeners.add(cb)\n return () => this.rippleListeners.delete(cb)\n }\n\n private commit(next: Partial<CursorSnapshot>) {\n this.snap = { ...this.snap, ...next }\n this.listeners.forEach((l) => l())\n }\n\n prefersReducedMotion(): boolean {\n return (\n typeof window !== 'undefined' &&\n !!window.matchMedia?.('(prefers-reduced-motion: reduce)').matches\n )\n }\n\n show(): void {\n if (this.snap.visible) return\n // Appear at the user's real pointer, then glide from there (not from an\n // off-screen corner) so the motion starts where they're already looking.\n this.snap = { visible: true, x: this.lastPointer.x, y: this.lastPointer.y }\n this.listeners.forEach((l) => l())\n }\n hide(): void {\n if (this.snap.visible) this.commit({ visible: false })\n }\n moveTo(x: number, y: number): void {\n this.commit({ x, y })\n }\n\n /** Emit a click ripple at the cursor's current position. */\n ripple(): void {\n const { x, y } = this.snap\n this.rippleListeners.forEach((l) => l(x, y))\n }\n\n /** Resolve a selector to an element, briefly polling since the target may only\n * appear after a prior step navigates / opens a panel. */\n private async resolve(target: string | Element, waitMs: number): Promise<Element | null> {\n if (typeof target !== 'string') return target\n const deadline = Date.now() + waitMs\n let found = document.querySelector<HTMLElement>(target)\n while (!found && Date.now() < deadline) {\n await sleep(50)\n found = document.querySelector<HTMLElement>(target)\n }\n return found\n }\n\n /**\n * Glide the cursor to the centre of `target` (a CSS selector or an element),\n * scrolling it into view first. Resolves once the glide is done, so callers\n * can `await` it before performing the action. Returns false if the target\n * can't be found (after briefly waiting for it to appear).\n */\n async glideTo(\n target: string | Element,\n opts?: { durationMs?: number; waitMs?: number }\n ): Promise<boolean> {\n const el = await this.resolve(target, opts?.waitMs ?? DEFAULT_WAIT_MS)\n if (!el) return false\n\n const reduced = this.prefersReducedMotion()\n el.scrollIntoView({ block: 'center', inline: 'center', behavior: reduced ? 'auto' : 'smooth' })\n await sleep(reduced ? 0 : SCROLL_SETTLE_MS)\n\n const rect = el.getBoundingClientRect()\n const x = rect.left + rect.width / 2\n const y = rect.top + rect.height / 2\n\n this.show()\n if (!reduced) await sleep(PAINT_MS)\n this.moveTo(x, y)\n await sleep(reduced ? 0 : (opts?.durationMs ?? GLIDE_MS))\n return true\n }\n}\n\n/** Shared controller singleton — drive from anywhere (tips, the tester, remote control). */\nexport const guidedCursor = new GuidedCursorController()\n","/**\n * Which of remote control's surfaces are on screen. A remote run needs the user to see who asks\n * (the consent prompt) and what it does (the guided cursor): with either missing, it is refused.\n *\n * Remote control's own controls, and the forms that hold credentials or endpoints, carry\n * `REMOTE_CONTROL_SURFACE` (`data-remote-control-surface`): a remote run never acts inside them (nor\n * on a label of a control inside them), so a one-off grant cannot press \"Allow for this session\" or\n * the switch itself, nor change a connection.\n */\nimport { useEffect } from 'react'\n\nexport type GuidedSurface = 'consent' | 'cursor'\n\nconst mounted: Record<GuidedSurface, number> = { consent: 0, cursor: 0 }\n\n/** Count `surface` as on screen while the calling component is mounted. */\nexport function useMountedSurface(surface: GuidedSurface): void {\n useEffect(() => {\n mounted[surface] += 1\n return () => {\n mounted[surface] -= 1\n }\n }, [surface])\n}\n\n/** Whether `surface` is on screen now. */\nexport const isSurfaceMounted = (surface: GuidedSurface): boolean => mounted[surface] > 0\n\n/**\n * The attribute that marks an off-limits surface: remote control's own controls (the consent\n * prompt, the pill, the Privacy switch's row) and the forms that hold credentials or endpoints\n * (model connections, calendar and mail connects). A remote run never acts inside one.\n */\nexport const REMOTE_CONTROL_SURFACE = 'data-remote-control-surface'\n\n/** The attribute that marks a secret field whatever its current type (a revealed password). */\nexport const SENSITIVE_INPUT = 'data-sensitive-input'\n","/**\n * Guided-run runner — the single, source-agnostic execution engine.\n *\n * Executes a guided run (a list of UI operations) by, for each step: gliding the shared\n * [[guidedCursor]] to the step's `target`, rippling on it, then performing the real interaction\n * (`click` / `type`) — so the run is exactly what a user would do, visibly. Each step's `note` is\n * announced through the notification system (the shared `notify` store) with a distinctive icon\n * so guided actions stand out in the activity log. prefers-reduced-motion skips the glide.\n *\n * Every source runs through here: a tip's \"Show me\" and the tips editor's tester (by a site's\n * `GuidedRuns.run`), and remote control, gated by consent (`createRemoteControl`). The registered\n * run in flight is published (`useActiveGuidedRun`) so UI can show / cancel it.\n */\n\nimport { createElement, useSyncExternalStore } from 'react'\nimport { MousePointerClick } from 'lucide-react'\nimport { notify } from '@arbidocs/react/shell'\nimport type { GuidedStep } from '@arbidocs/react'\nimport { guidedCursor } from './cursor'\nimport { REMOTE_CONTROL_SURFACE, SENSITIVE_INPUT } from './surfaces'\n\n// A consistent icon tags every guided-run toast so guided actions are\n// distinguishable in the activity log from ordinary notifications.\nconst guidedStepIcon = createElement(MousePointerClick, { className: 'h-4 w-4' })\n\n/** Default human-paced pause between steps (ms). Mirrors the tip-bar cadence. */\nconst DEFAULT_PAUSE_MS = 900\n/** Dwell after arriving at a target (ripple visible) before acting. */\nconst DWELL_MS = 280\n/** The longest a remote run may wait for a target or pause after a step (ms). */\nconst MAX_REMOTE_WAIT_MS = 5000\n/** `autocomplete` tokens that name a secret: never typed into. */\nconst SECRET_AUTOCOMPLETE = new Set(['current-password', 'new-password', 'one-time-code'])\n\n// The registered run in flight (a run is a one-off: never saved), for the UI that shows it.\nlet activeRun: string | null = null\nconst activeListeners = new Set<() => void>()\nconst setActiveRun = (id: string | null) => {\n if (activeRun === id) return\n activeRun = id\n activeListeners.forEach((listener) => listener())\n}\nconst subscribeActive = (listener: () => void) => {\n activeListeners.add(listener)\n return () => {\n activeListeners.delete(listener)\n }\n}\nconst getActiveRun = () => activeRun\n\n/** The registered run the runner is executing, or null when idle (or running ad-hoc steps). */\nexport const useActiveGuidedRun = (): string | null =>\n useSyncExternalStore(subscribeActive, getActiveRun, getActiveRun)\n\n// Monotonic token: every run/cancel bumps it, so an in-flight loop can detect it\n// was superseded (a newer run) or cancelled and stop without racing.\nlet runToken = 0\n\nconst sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms))\n\n/** Dispatch a realistic click so real handlers respond — including Radix menus\n * (trigger opens on pointerdown, items select on pointerup/click), which a bare\n * element.click() would miss. */\nfunction clickElement(el: HTMLElement): void {\n const rect = el.getBoundingClientRect()\n // No `view` — jsdom rejects it and handlers don't need it; clientX/Y + bubbles\n // are what matter to trigger real listeners (including Radix menus).\n const base = {\n bubbles: true,\n cancelable: true,\n clientX: rect.left + rect.width / 2,\n clientY: rect.top + rect.height / 2,\n }\n // jsdom (tests) has no constructable PointerEvent; fall back to MouseEvent so\n // the type-named event still fires listeners.\n const pointer = (type: string) => {\n try {\n return new PointerEvent(type, {\n ...base,\n pointerId: 1,\n pointerType: 'mouse',\n isPrimary: true,\n })\n } catch {\n // jsdom (tests) has no view-accepting PointerEvent; a same-typed MouseEvent\n // still fires the listeners.\n return new MouseEvent(type, base)\n }\n }\n el.dispatchEvent(pointer('pointerdown'))\n el.dispatchEvent(new MouseEvent('mousedown', base))\n el.dispatchEvent(pointer('pointerup'))\n el.dispatchEvent(new MouseEvent('mouseup', base))\n el.dispatchEvent(new MouseEvent('click', base))\n el.focus?.()\n}\n\n/** A field that holds a secret: a password (also while revealed, `SENSITIVE_INPUT`), a hidden\n * field, or one the browser fills with a password or a one-time code. */\nfunction isSensitiveField(el: HTMLInputElement | HTMLTextAreaElement): boolean {\n if (el.hasAttribute(SENSITIVE_INPUT)) return true\n if (el instanceof HTMLInputElement && (el.type === 'password' || el.type === 'hidden'))\n return true\n const tokens = (el.getAttribute('autocomplete') ?? '').toLowerCase().split(/\\s+/)\n return tokens.some((token) => SECRET_AUTOCOMPLETE.has(token))\n}\n\n/** Type text into an input/textarea, firing a React-visible input event. Never a secret field\n * (`isSensitiveField`): a guided run types what the user can watch, nothing secret or unseen. */\nfunction typeInto(el: HTMLElement, value: string): void {\n if (!(el instanceof HTMLInputElement) && !(el instanceof HTMLTextAreaElement)) return\n if (isSensitiveField(el)) {\n console.warn('[guided] Refusing to type into a password, secret or hidden field')\n return\n }\n el.focus()\n const setter = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(el), 'value')?.set\n setter?.call(el, value)\n el.dispatchEvent(new Event('input', { bubbles: true }))\n}\n\nconst insideSurface = (el: Element): boolean => !!el.closest(`[${REMOTE_CONTROL_SURFACE}]`)\n\n/**\n * Whether a remote step may not act on `el`: it is inside an off-limits surface (remote control's\n * own controls, credential and endpoint forms), or it is (or sits in) a label whose control is,\n * since clicking a label clicks its control.\n */\nfunction isOffLimits(el: HTMLElement): boolean {\n if (insideSurface(el)) return true\n const label = el instanceof HTMLLabelElement ? el : el.closest('label')\n const control = label?.control\n return !!label && (insideSurface(label) || (!!control && insideSurface(control)))\n}\n\n/** Whether the user can see `el`: a remote run acts only on what the user can watch. */\nfunction isWatchable(el: HTMLElement): boolean {\n const rect = el.getBoundingClientRect()\n if (rect.width === 0 || rect.height === 0) return false\n return typeof el.checkVisibility === 'function' ? el.checkVisibility() : true\n}\n\n/** Perform a step's interaction on the resolved element. A remote run never acts on an\n * off-limits surface (`isOffLimits`) nor on an element the user cannot see. */\nfunction performStep(step: GuidedStep, el: HTMLElement, remote: boolean): void {\n if (remote && isOffLimits(el)) {\n console.warn('[guided] Refusing a remote step on an off-limits surface', step.target)\n return\n }\n if (remote && !isWatchable(el)) {\n console.warn('[guided] Refusing a remote step on an element the user cannot see', step.target)\n return\n }\n if (step.do === 'type') typeInto(el, step.value ?? '')\n else clickElement(el)\n}\n\nexport interface GuidedRunOptions {\n /**\n * A run remote control started: it never acts on an off-limits surface or an unseen element,\n * and waits and pauses at most `MAX_REMOTE_WAIT_MS`.\n */\n remote?: boolean\n}\n\n/** Stop any running guided run and clear progress state. */\nexport function cancelGuidedRun(): void {\n runToken += 1\n guidedCursor.hide()\n setActiveRun(null)\n}\n\n/**\n * Run guided steps one by one, paced for a human to follow. A new call supersedes any in-flight\n * run. `id` names the registered run they are (published while it runs), or null for ad-hoc steps.\n */\nexport async function runGuidedSteps(\n steps: GuidedStep[],\n id: string | null,\n { remote = false }: GuidedRunOptions = {}\n): Promise<void> {\n if (steps.length === 0) return\n\n // A remote run cannot hold the screen: its waits and pauses are capped.\n const bound = (ms: number | undefined) =>\n remote && ms !== undefined ? Math.min(ms, MAX_REMOTE_WAIT_MS) : ms\n const myToken = (runToken += 1)\n const superseded = () => runToken !== myToken\n setActiveRun(id)\n\n for (const step of steps) {\n if (superseded()) return\n\n if (step.note) notify.info(step.note, { icon: guidedStepIcon })\n\n // Glide to the step's target, ripple, then perform the real interaction. If\n // the target never appears (e.g. a prior step didn't open its panel), skip\n // acting rather than firing blindly.\n const landed = await guidedCursor.glideTo(step.target, { waitMs: bound(step.waitMs) })\n if (superseded()) return\n if (landed) {\n guidedCursor.ripple()\n await sleep(DWELL_MS)\n if (superseded()) return\n const el = document.querySelector<HTMLElement>(step.target)\n if (el) performStep(step, el, remote)\n }\n\n await sleep(bound(step.pauseMs) ?? DEFAULT_PAUSE_MS)\n }\n\n if (superseded()) return\n guidedCursor.hide()\n setActiveRun(null)\n}\n","/**\n * Guided runs: the registry.\n *\n * A guided run is an ordered list of UI operations — each targets a real on-screen element (by a\n * `[data-testid=...]` selector) and performs a real interaction on it. The runner (./runner.ts)\n * executes it by gliding the guided cursor to each target, rippling, then doing the interaction,\n * so a \"Show me\" (or a remote-control run) is exactly what a user would do, visibly.\n *\n * By construction there is no \"silent step\": every step has a `target`, so a guided run can never\n * fire an effect with nothing on screen to point at. Instant dispatch lives in the action\n * catalogue (`defineActions`, palette and shortcuts); guided runs drive the UI instead.\n *\n * The kit ships the runs that demonstrate its built-in actions (`KIT_SEQUENCES`, `KIT_DEMOS`); a\n * host adds its own, and may replace a kit run by giving one with the same id, with\n * `createGuidedRuns` in its host config (`guided`). Every registered id is also what a\n * remote-control `sequence_id` may name, nothing else.\n */\nimport type { GuidedStep } from '@arbidocs/react'\nimport type { TipCta } from '../tips/registry'\nimport { cancelGuidedRun, runGuidedSteps, type GuidedRunOptions } from './runner'\n\nexport interface SequenceDef<Id extends string = string> {\n id: Id\n /** Human label for the tester / a tip-editor dropdown. */\n label: string\n description?: string\n steps: GuidedStep[]\n}\n\n/** The ids of the kit's own guided runs. */\nexport type KitSequenceId = 'upload-a-document' | 'invite-a-colleague' | 'open-plan-usage'\n\n/** The kit's guided runs: walks to the built-in actions' doors. Every step targets a real element. */\nexport const KIT_SEQUENCES: Record<KitSequenceId, SequenceDef<KitSequenceId>> = {\n 'upload-a-document': {\n id: 'upload-a-document',\n label: 'Upload a document',\n description: 'Open Documents and start the uploader.',\n steps: [\n { target: '[data-testid=\"sidebar-documents-button\"]', note: 'Open Documents…' },\n {\n target: '[data-testid=\"documents-upload-button\"]',\n note: 'Start the uploader — drop files here.',\n },\n ],\n },\n 'invite-a-colleague': {\n id: 'invite-a-colleague',\n label: 'Invite a colleague',\n description: 'Open the account menu, then Contacts, then add a contact by email.',\n steps: [\n { target: '[data-testid=\"sidebar-user-profile\"]', note: 'Open your account menu…' },\n { target: '[data-testid=\"sidebar-contacts-button\"]', note: 'Open Contacts…' },\n { target: '[data-testid=\"dm-invite-chip\"]', note: 'Add a contact by email.' },\n ],\n },\n 'open-plan-usage': {\n id: 'open-plan-usage',\n label: 'View plan & usage',\n description: 'Open the account menu, then Plan & Usage.',\n steps: [\n { target: '[data-testid=\"sidebar-user-profile\"]', note: 'Open your account menu…' },\n { target: '[data-testid=\"user-menu-projects\"]', note: 'Choose Plan & Usage.' },\n ],\n },\n}\n\n/**\n * The built-in actions a \"Show me\" demonstrates with a guided run instead of dispatching at once\n * (`createBuiltinActions` ids → run ids).\n */\nexport const KIT_DEMOS: Readonly<Record<string, KitSequenceId>> = {\n 'upload-documents': 'upload-a-document',\n 'open-invite-contacts': 'invite-a-colleague',\n // The panel opens from the account menu: Show me walks that path.\n 'open-projects': 'open-plan-usage',\n}\n\nexport interface GuidedRunsConfig<Id extends string> {\n /** The host's own runs, beside the kit's (an equal id replaces the kit's). */\n sequences?: Readonly<Record<Id, SequenceDef<Id>>>\n /** The host's actions a \"Show me\" demonstrates with a run (action id → run id). */\n demos?: Readonly<Record<string, Id | KitSequenceId>>\n /** The guided cursor's mark image. Default: a cyan ring. */\n cursorMark?: string\n /**\n * Let a backend assistant drive the UI (remote control): its socket handler, consent prompt,\n * pill and Settings → Privacy switch. Default off; \"Show me\" runs work either way.\n */\n remoteControl?: boolean\n}\n\n/** The guided runs of a site: the kit's and the host's (`createGuidedRuns`). */\nexport interface GuidedRuns<Id extends string = string> {\n readonly sequences: Readonly<Record<Id, SequenceDef<Id>>>\n /** Action id → the run that demonstrates it. */\n readonly demos: Readonly<Record<string, Id>>\n readonly cursorMark?: string\n /** Remote control is on for this site (`GuidedRunsConfig.remoteControl`). */\n readonly remoteControl: boolean\n /** Options for a run picker (the tips editor's dropdown and tester). */\n readonly options: readonly { value: Id; label: string }[]\n /** True when `value` is a registered run (a remote `sequence_id` must be). */\n isSequenceId(value: string): value is Id\n /**\n * Run a registered run or ad-hoc steps, paced for a human to follow; a new run supersedes the\n * one in flight. An unknown id runs nothing. `remote`: a run remote control started.\n */\n run(input: Id | GuidedStep[], options?: GuidedRunOptions): Promise<void>\n /**\n * A tip's action: a URL (new window), a named run, or one action. \"Show me\" is a GUIDED run, so\n * an action with a demo runs that, the cursor gliding to its door; any other action dispatches\n * at once (`runAction`).\n */\n runCta<Action extends string>(cta: TipCta<Action, Id>, runAction: (id: Action) => void): void\n /** Stop the run in flight. */\n cancel(): void\n}\n\n/** The site's guided runs: the kit's plus the host's own runs and demos. */\nexport function createGuidedRuns<Id extends string = never>(\n config: GuidedRunsConfig<Id> = {}\n): GuidedRuns<Id | KitSequenceId> {\n type AnyId = Id | KitSequenceId\n const sequences = { ...KIT_SEQUENCES, ...config.sequences } as Record<AnyId, SequenceDef<AnyId>>\n const demos = { ...KIT_DEMOS, ...config.demos } as Record<string, AnyId>\n const isSequenceId = (value: string): value is AnyId =>\n Object.prototype.hasOwnProperty.call(sequences, value)\n const runs: GuidedRuns<AnyId> = {\n sequences,\n demos,\n cursorMark: config.cursorMark,\n remoteControl: config.remoteControl === true,\n options: Object.values<SequenceDef<AnyId>>(sequences).map((s) => ({\n value: s.id,\n label: s.label,\n })),\n isSequenceId,\n async run(input, options) {\n if (typeof input !== 'string') return runGuidedSteps(input, null, options)\n if (!isSequenceId(input)) {\n console.warn(`runSequence: \"${input}\" is not a known guided run`)\n return\n }\n return runGuidedSteps(sequences[input].steps, input, options)\n },\n // Through `runs.run`, the one way in, so whoever watches it sees a CTA's run too.\n runCta(cta, runAction) {\n if (cta.href) {\n window.open(cta.href, '_blank', 'noopener,noreferrer')\n return\n }\n if (cta.sequence) {\n void runs.run(cta.sequence)\n return\n }\n if (!cta.action) return\n const demo = Object.prototype.hasOwnProperty.call(demos, cta.action)\n ? demos[cta.action]\n : undefined\n if (demo) void runs.run(demo)\n else runAction(cta.action)\n },\n cancel: cancelGuidedRun,\n }\n return runs\n}\n","import { useHost } from '../provider/host'\nimport { createGuidedRuns, type GuidedRuns } from './sequences'\n\n/** The kit's runs alone, for a host that adds none. */\nconst KIT_RUNS: GuidedRuns = createGuidedRuns()\n\n/** The site's guided runs: the host's (`guided`, from `createGuidedRuns`), else the kit's. */\nexport function useGuidedRuns(): GuidedRuns {\n return useHost().guided ?? KIT_RUNS\n}\n","import type { ReactNode } from 'react'\nimport type { LucideIcon } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\n\n/**\n * What an allowance is made of, in the meter's own unit (£ of AI usage, GB, users): what was used, the plan's part\n * of the allowance, the top-ups on top of it, and how much more automatic top-ups may still add before a usage cap\n * (or budget) stops them.\n */\nexport interface UsageMeterAllowance {\n used: number\n /** The plan's part of the allowance (marked on the bar when top-ups or automatic room follow it). */\n plan: number\n /** Top-ups on top of the plan: the allowance now is `plan + topUps`. */\n topUps?: number\n /**\n * Room automatic top-ups may still add before the cap stops them (drawn hatched after the allowance).\n * `null` = no limit (nothing drawn: the room is unbounded); omitted = not applicable.\n */\n autoRoom?: number | null\n}\n\n/** Pressure on an allowance: under 80% used, 80% to under 100%, or at / over it. */\nexport type UsageMeterState = 'under' | 'near' | 'over'\n\n/** The allowance meter's pressure state for `used` of `allowance`. */\nexport function usageMeterState(used: number, allowance: number): UsageMeterState {\n if (allowance <= 0) return used > 0 ? 'over' : 'under'\n const ratio = used / allowance\n return ratio >= 1 ? 'over' : ratio >= 0.8 ? 'near' : 'under'\n}\n\nconst STATE_TONE: Record<UsageMeterState, string> = {\n under: 'bg-primary',\n near: 'bg-yellow-500',\n over: 'bg-red-500',\n}\n\nconst pctOf = (n: number, scale: number) =>\n scale > 0 ? Math.max(0, Math.min(100, (n / scale) * 100)) : 0\n\n/** Legend swatches, matching the bar's segments. */\nconst SWATCH = {\n plan: 'bg-muted-foreground/40',\n topUps: 'bg-primary/30',\n autoRoom: 'bg-muted',\n}\n\nconst HATCH = {\n backgroundImage: 'repeating-linear-gradient(135deg, currentColor 0 1.5px, transparent 1.5px 5px)',\n} as const\n\n/** The segmented bar of an allowance meter: used, the plan mark, top-ups, and the automatic room. */\nfunction AllowanceBar({ allowance, label }: { allowance: UsageMeterAllowance; label: string }) {\n const { used, plan } = allowance\n const topUps = Math.max(0, allowance.topUps ?? 0)\n const room = Math.max(0, allowance.autoRoom ?? 0)\n const total = plan + topUps\n const scale = Math.max(total + room, used, Number.EPSILON)\n const state = usageMeterState(used, total)\n const usedPct = total > 0 ? Math.round((used / total) * 100) : used > 0 ? 100 : 0\n const markPlan = plan > 0 && plan < scale && (topUps > 0 || room > 0)\n return (\n <div className=\"relative h-2 overflow-hidden rounded-full bg-muted\" data-slot=\"usage-meter-bar\">\n {topUps > 0 && (\n <div\n className={cn('absolute inset-y-0', SWATCH.topUps)}\n style={{ left: `${pctOf(plan, scale)}%`, width: `${pctOf(topUps, scale)}%` }}\n data-slot=\"usage-meter-topups\"\n />\n )}\n {room > 0 && (\n <div\n className=\"absolute inset-y-0 text-muted-foreground/35\"\n style={{ left: `${pctOf(total, scale)}%`, width: `${pctOf(room, scale)}%`, ...HATCH }}\n data-slot=\"usage-meter-auto-room\"\n />\n )}\n <div\n className={cn(\n 'absolute inset-y-0 left-0 rounded-full transition-[width]',\n STATE_TONE[state]\n )}\n style={{ width: `${pctOf(Math.min(used, scale), scale)}%` }}\n role=\"progressbar\"\n aria-valuenow={Math.min(usedPct, 100)}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-label={label}\n data-state={state}\n />\n {markPlan && (\n <div\n className=\"absolute inset-y-0 w-0.5 -translate-x-1/2 bg-foreground/70\"\n style={{ left: `${pctOf(plan, scale)}%` }}\n aria-hidden\n data-slot=\"usage-meter-plan-mark\"\n />\n )}\n {room > 0 && total > 0 && (\n <div\n className=\"absolute inset-y-0 w-px bg-foreground/40\"\n style={{ left: `${pctOf(total, scale)}%` }}\n aria-hidden\n />\n )}\n </div>\n )\n}\n\n/**\n * One labelled quota meter: icon + label on the left, used-of-limit on the right, a thin bar underneath.\n *\n * Simple mode (`pct`): the bar's tone follows pressure with the shared green → yellow → red gradation — green while\n * there's room, yellow past the halfway mark, red at the limit — so a stack of meters reads at a glance which quota\n * is the one to think about.\n *\n * Allowance mode (`allowance`): the bar spans the allowance plus what automatic top-ups may still add; it marks the\n * plan's part, shades the top-ups, hatches the automatic room, and fills what was used (red at the allowance, yellow\n * from 80%). `legend` names the segments; `details` (next period, cap) sit under the bar and `actions` (+ / −) beside\n * it. The meter's `data-state` is `under` / `near` / `over`.\n */\nexport function UsageMeter({\n icon: Icon,\n label,\n value,\n pct = 0,\n hint,\n allowance,\n legend,\n details,\n actions,\n className,\n testId,\n}: {\n icon?: LucideIcon\n label: string\n /** Formatted used-of-limit text, e.g. \"1,200 / 25,000\" or \"40 / 500 MB\". */\n value: string\n /** Simple mode: fill percentage, 0–100 (values are clamped). Ignored with `allowance`. */\n pct?: number\n /** Inline parenthetical after the label, e.g. \"resets May 31, 2025\" —\n * same font as the label, so the meter never grows an extra row. */\n hint?: string\n /** Allowance mode: the allowance's parts, in the meter's unit. */\n allowance?: UsageMeterAllowance\n /** Formatted legend entries for the allowance's segments (each shown only when set). */\n legend?: { plan?: string; topUps?: string; autoRoom?: string }\n details?: ReactNode\n actions?: ReactNode\n className?: string\n testId?: string\n}) {\n const clamped = Math.max(0, Math.min(100, pct))\n // Shared green → yellow → red gradation (same thresholds as the project-card\n // quota badges): green with room, yellow past the halfway mark, red at limit.\n const tone = clamped >= 100 ? 'bg-red-500' : clamped >= 50 ? 'bg-yellow-500' : 'bg-primary'\n const state = allowance\n ? usageMeterState(allowance.used, allowance.plan + Math.max(0, allowance.topUps ?? 0))\n : undefined\n const legendItems = legend\n ? (\n [\n ['plan', legend.plan],\n ['topUps', legend.topUps],\n ['autoRoom', legend.autoRoom],\n ] as const\n ).filter(([, text]) => !!text)\n : []\n\n const meter = (\n <div className=\"min-w-0 flex-1 space-y-1.5\">\n <div className=\"flex min-w-0 items-center justify-between gap-3 text-sm\">\n <span\n className={cn(\n 'flex min-w-0 items-center gap-1.5',\n allowance ? 'font-medium text-foreground' : 'text-muted-foreground'\n )}\n >\n {Icon && <Icon className=\"size-3.5 shrink-0\" />}\n <span className=\"truncate\">\n {label}\n {hint ? ` (${hint})` : ''}\n </span>\n </span>\n <span\n className=\"shrink-0 font-medium tabular-nums text-foreground\"\n data-slot=\"usage-meter-value\"\n >\n {value}\n </span>\n </div>\n {allowance ? (\n <AllowanceBar allowance={allowance} label={label} />\n ) : (\n <div className=\"h-1.5 overflow-hidden rounded-full bg-muted\">\n <div\n className={cn('h-full rounded-full transition-[width]', tone)}\n style={{ width: `${clamped}%` }}\n role=\"progressbar\"\n aria-valuenow={clamped}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-label={label}\n />\n </div>\n )}\n {legendItems.length > 0 && (\n <ul\n className=\"flex flex-wrap gap-x-4 gap-y-1 text-xs tabular-nums text-muted-foreground\"\n data-slot=\"usage-meter-legend\"\n >\n {legendItems.map(([key, text]) => (\n <li\n key={key}\n className=\"flex items-center gap-1.5\"\n data-slot={`usage-meter-legend-${key}`}\n >\n <span\n className={cn(\n 'inline-block size-2 rounded-sm',\n SWATCH[key],\n key === 'autoRoom' && 'text-muted-foreground/60'\n )}\n style={key === 'autoRoom' ? HATCH : undefined}\n aria-hidden\n />\n {text}\n </li>\n ))}\n </ul>\n )}\n {details && <div className=\"space-y-1 text-xs text-muted-foreground\">{details}</div>}\n </div>\n )\n\n if (!actions) {\n return (\n <div className={cn('space-y-1.5', className)} data-testid={testId} data-state={state}>\n {meter}\n </div>\n )\n }\n // The actions sit beside the meter when the meter's own box is wide enough, under it otherwise\n // (a container query, so a narrow panel on a wide screen stacks too); nothing overflows at 390px.\n return (\n <div className={cn('@container', className)} data-testid={testId} data-state={state}>\n <div className=\"flex flex-col gap-3 @lg:flex-row @lg:items-start @lg:gap-6\">\n {meter}\n <div\n className=\"flex min-w-0 flex-wrap items-center gap-2 @lg:w-60 @lg:shrink-0 @lg:flex-col @lg:items-stretch\"\n data-slot=\"usage-meter-actions\"\n >\n {actions}\n </div>\n </div>\n </div>\n )\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { ArbiHost } from './chunk-
|
|
2
|
+
import { ArbiHost } from './chunk-QG6MRLZG.js';
|
|
3
3
|
import { useBlocksEnvironment } from './chunk-YUHSDOPW.js';
|
|
4
4
|
import { closeAllDialogs } from './chunk-WTTPZMZ7.js';
|
|
5
5
|
import { createContext, useState, useRef, useEffect, useCallback, useMemo, useContext } from 'react';
|
|
@@ -363,5 +363,5 @@ function useConnectedWorkspace() {
|
|
|
363
363
|
}
|
|
364
364
|
|
|
365
365
|
export { ConnectionProvider, SESSION_EXPIRED_MESSAGE, isAuthenticated, useConnectedWorkspace, useConnection, useConnectionUser, useOptionalConnection };
|
|
366
|
-
//# sourceMappingURL=chunk-
|
|
367
|
-
//# sourceMappingURL=chunk-
|
|
366
|
+
//# sourceMappingURL=chunk-OWHO2TO3.js.map
|
|
367
|
+
//# sourceMappingURL=chunk-OWHO2TO3.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/connection/ConnectionProvider.tsx"],"names":["login"],"mappings":"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","file":"chunk-NUOMPVKQ.js","sourcesContent":["/**\n * The demo/live connection layer for a host app. Holds auth + workspace\n * selection state and exposes it via {@link useConnection}, so every surface\n * works identically whether it's talking to a live ARBI backend or the seeded\n * demo workspace. Host-specific values (backend URL, demo identity, default\n * workspace/assistant ids) arrive once through {@link ArbiConnectionConfig}.\n */\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react'\nimport {\n arbiAccountClient,\n clearSealedDrafts,\n wipeOfflineMail,\n toProfileView,\n useArbi,\n useArbiSessionState,\n useArbiSessionStore,\n useSwitchWorkspace,\n type AccountClient,\n type LoginProfile,\n type ProfileView,\n} from '@arbidocs/react'\nimport { clearChatArtifacts } from '@arbidocs/react/shell'\nimport type { ArbiMode, ArbiUser, ConnectionStatus, ArbiConnectionConfig } from './types'\nimport { useBlocksEnvironment } from '../provider/environment'\nimport { ArbiHost } from '../provider/host'\nimport { closeAllDialogs } from '../provider/dialog-registry'\n\ninterface ConnectionValue {\n mode: ArbiMode\n status: ConnectionStatus\n user: ArbiUser | null\n /** The selected workspace: the session state's (`useArbiSessionState`), set by `setWorkspace`. */\n workspaceId: string | null\n apiConfigured: boolean\n apiUrl: string\n /**\n * The deployment domain the user's keys are derived for (`arbi.getDeploymentDomain()`), for the\n * document tools' e-signing. `undefined` in demo mode.\n */\n deploymentDomain: string | undefined\n error: string | null\n /** Default assistant config ext_id (for the AI hooks). */\n assistantConfig?: string\n /**\n * The demo's workspace when none is selected. Never set signed in to a live backend: there the\n * selection is the only workspace (none while a switch is in flight), never a remembered one.\n */\n fallbackWorkspaceId?: string\n /** Authenticate. Live login when a backend is configured, otherwise the demo workspace. */\n login: (email: string, password: string) => Promise<void>\n /** One-click demo entry (no backend required). */\n enterDemo: () => void\n logout: () => void\n /**\n * Affirmatively select a workspace: opens it on the server (via the SDK),\n * updates the app-wide state, and persists the choice so it survives future\n * logins. This is the single entry point for \"the user is now in workspace X\".\n */\n setWorkspace: (id: string) => Promise<void>\n /**\n * Re-assert the selected workspace on the server session (idempotent `/open`).\n * Call before a workspace-scoped write when the session may have lost its open\n * workspace (token re-login, backend restart, session expiry) — the server\n * resolves the workspace from the session, so a dropped `/open` yields\n * \"No active workspace\" until it's re-opened.\n */\n ensureWorkspaceOpen: () => Promise<void>\n}\n\nconst ConnectionContext = createContext<ConnectionValue | null>(null)\n\n/**\n * Persist the affirmatively-selected workspace per backend AND per signed-in user, so a returning\n * user lands back in the workspace they last chose, while the next person on a shared browser\n * never starts from someone else's workspace id. Namespaced by apiUrl so distinct deployments\n * (and the demo workspace) don't clobber each other. Cleared on logout.\n */\nconst WORKSPACE_STORAGE_PREFIX = 'arbi:selectedWorkspace'\nconst normalizeUserKey = (email: string) => email.trim().toLowerCase()\n\n/** Exported for tests. */\nexport const workspaceStorageKey = (apiUrl: string, userKey: string) =>\n `${WORKSPACE_STORAGE_PREFIX}:${apiUrl || 'demo'}:${normalizeUserKey(userKey)}`\n\n/** The pre-isolation key (apiUrl only). Never read: removed so it cannot leak across users. */\nconst legacyWorkspaceStorageKey = (apiUrl: string) =>\n `${WORKSPACE_STORAGE_PREFIX}:${apiUrl || 'demo'}`\n\nfunction readPersistedWorkspace(apiUrl: string, userKey: string | null): string | null {\n if (!userKey) return null\n try {\n return window.localStorage.getItem(workspaceStorageKey(apiUrl, userKey))\n } catch {\n return null\n }\n}\n\nfunction persistWorkspace(apiUrl: string, userKey: string | null, id: string | null): void {\n if (!userKey) return\n try {\n if (id) window.localStorage.setItem(workspaceStorageKey(apiUrl, userKey), id)\n else window.localStorage.removeItem(workspaceStorageKey(apiUrl, userKey))\n window.localStorage.removeItem(legacyWorkspaceStorageKey(apiUrl))\n } catch {\n // Storage unavailable (private mode, SSR) — selection stays in-memory only.\n }\n}\n\n/** Shown on the sign-in screen after the session could not be recovered. */\nexport const SESSION_EXPIRED_MESSAGE = 'Your session expired. Sign in again.'\n\n/** The connection user for a profile: its full name, falling back to the email local part. */\nfunction userFromProfile(profile: LoginProfile, externalId?: string): ArbiUser {\n const fullName = [profile.givenName, profile.familyName]\n .map((part) => part?.trim())\n .filter(Boolean)\n .join(' ')\n return {\n name: fullName || profile.email.split('@')[0],\n email: profile.email,\n externalId,\n picture: profile.picture,\n }\n}\n\n/**\n * The sign-in layer of a blocks-only site, mounted by its host (`defaultHost`): login, demo mode\n * and the selected workspace, over the host's session state (the selected workspace lives there,\n * so every block reads one value). Its account client is the host's `account` below it.\n */\nexport function ConnectionProvider({\n config,\n children,\n}: {\n config: ArbiConnectionConfig\n children: ReactNode\n}) {\n const arbi = useArbi()\n const session = useArbiSessionStore()\n const { switchWorkspace, openSelectedWorkspace, settled } = useSwitchWorkspace()\n const isLiveConfigured = config.apiUrl.length > 0\n const demoWorkspaceId = config.demoWorkspaceId ?? 'demo-workspace'\n\n const [status, setStatus] = useState<ConnectionStatus>(\n isLiveConfigured ? 'connecting' : 'disconnected'\n )\n const [user, setUser] = useState<ArbiUser | null>(null)\n const workspaceId = useArbiSessionState((s) => s.workspaceId)\n const selectWorkspaceId = session.setWorkspaceId\n const [mode, setMode] = useState<ArbiMode>('demo')\n const [error, setError] = useState<string | null>(null)\n // Dialogs belong to the signed-in session. A first signed-out mount may carry an invitation\n // intent, so clear only after an authenticated (or demo) session actually ends. A workspace\n // switch / sign-in can pass through `connecting` without ending that session.\n const hadDialogSession = useRef(false)\n useEffect(() => {\n if (status === 'authenticated' || status === 'demo') {\n hadDialogSession.current = true\n } else if (status !== 'connecting' && hadDialogSession.current) {\n hadDialogSession.current = false\n closeAllDialogs()\n }\n }, [status])\n // Who the persisted workspace belongs to; set at sign-in, cleared at logout.\n const storageUserRef = useRef<string | null>(null)\n // Moves at each logout: a sign-in still finishing from before it does not sign back in.\n const sessionRun = useRef(0)\n\n // The SDK could not recover the session (token refused, workspace not re-openable): drop to\n // 'disconnected' with a plain message, so the host's gate sends the user to sign in instead of\n // every call failing with a raw backend error. The remembered workspace is kept for next login.\n useEffect(\n () =>\n arbi.onSessionExpired?.(() => {\n storageUserRef.current = null\n setUser(null)\n selectWorkspaceId(null)\n setStatus('disconnected')\n setError(SESSION_EXPIRED_MESSAGE)\n }),\n [arbi, selectWorkspaceId]\n )\n\n // A saved name, picture or email reaches every surface reading `useConnection().user`.\n useEffect(\n () =>\n arbi.user.onProfileChange?.((profile) =>\n setUser((current) => (current ? userFromProfile(profile, current.externalId) : current))\n ),\n [arbi]\n )\n\n const enterDemo = useCallback(() => {\n setMode('demo')\n setStatus('demo')\n setError(null)\n setUser({ name: config.demoUser.name, email: config.demoUser.email })\n selectWorkspaceId(demoWorkspaceId)\n }, [config.demoUser.name, config.demoUser.email, demoWorkspaceId, selectWorkspaceId])\n\n /**\n * The session signed in, by whatever path (`login` below, a sign-in page on the host's `Arbi`,\n * a restored session): open the user's workspace and resolve who they are.\n */\n const completeSignIn = useCallback(\n async (email: string) => {\n const run = sessionRun.current\n const signedOut = () => run !== sessionRun.current\n setMode('live')\n setStatus('connecting')\n setError(null)\n try {\n storageUserRef.current = normalizeUserKey(email)\n const workspaces = await arbi.workspaces.list()\n if (workspaces?.length) {\n // Prefer the workspace the user last affirmatively selected (persisted),\n // then the configured workspace (there may be several — e.g. a\n // marketing/KM workspace), then whichever happens to be first. Ternary\n // (not `&&`) so an empty value can't leak `\"\"` into `target`.\n const persisted = readPersistedWorkspace(config.apiUrl, storageUserRef.current)\n const preferred = persisted ?? config.workspaceId\n const target =\n (preferred ? workspaces.find((w) => w.external_id === preferred) : undefined) ??\n (config.requireWorkspaceSelection ? undefined : workspaces[0])\n if (target) {\n selectWorkspaceId(target.external_id)\n if (!(await openSelectedWorkspace()))\n throw new Error('Could not open your workspace. Try signing in again.')\n persistWorkspace(config.apiUrl, storageUserRef.current, target.external_id)\n }\n }\n // The profile (name + avatar) comes with the login response. A session restored without\n // a login has none, so fall back to finding ourselves in the workspace roster; the email\n // local part is only the last resort, never the answer when a profile name exists.\n let resolved: ArbiUser = { name: email.split('@')[0], email }\n const me = arbi.user.identity()\n const profile = arbi.user.profile?.()\n if (profile) {\n resolved = userFromProfile(profile, me?.externalId)\n } else {\n try {\n const members = await arbi.workspaces.listUsers()\n const self = members.find((m) => m.user.external_id === me?.externalId)?.user\n if (self) {\n const fullName = [self.given_name, self.family_name].filter(Boolean).join(' ').trim()\n resolved = {\n name: fullName || email.split('@')[0],\n email: self.email || email,\n externalId: self.external_id,\n picture: self.picture ?? null,\n }\n } else if (me?.externalId) {\n resolved.externalId = me.externalId\n }\n } catch {\n // Roster not available (e.g. no workspace) — keep the fallback identity.\n }\n }\n if (signedOut()) return\n setUser(resolved)\n setStatus('authenticated')\n } catch (e) {\n if (signedOut()) return\n // Surface the real error — no silent fallback to a fake session.\n setError(e instanceof Error ? e.message : 'Sign-in failed. Check your credentials.')\n setStatus('error')\n }\n },\n [\n arbi,\n config.workspaceId,\n config.apiUrl,\n config.requireWorkspaceSelection,\n selectWorkspaceId,\n openSelectedWorkspace,\n ]\n )\n\n // Every sign-in on the host's `Arbi` lands here, whichever page or kit made it.\n const signingIn = useRef<Promise<void>>(Promise.resolve())\n useEffect(\n () =>\n arbi.onSignedIn?.((login) => {\n signingIn.current = completeSignIn(\n login.profile?.email ??\n arbi.session?.getState().userEmail ??\n arbi.user.identity()?.email ??\n ''\n )\n }),\n [arbi, completeSignIn]\n )\n\n /** Authenticate: a live login when a backend is configured, otherwise the demo workspace. */\n const login = useCallback(\n async (email: string, password: string) => {\n setError(null)\n if (!isLiveConfigured) {\n enterDemo()\n return\n }\n setStatus('connecting')\n setMode('live')\n try {\n // Signed in: `completeSignIn` follows (onSignedIn); done once it is.\n await arbi.login(email, password)\n await signingIn.current\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Sign-in failed. Check your credentials.')\n setStatus('error')\n }\n },\n [arbi, enterDemo, isLiveConfigured]\n )\n\n // The session kept on this device signs in again (no password; the key stays encrypted on the\n // device). Run once even under StrictMode.\n const restoreStarted = useRef(false)\n useEffect(() => {\n if (restoreStarted.current || !isLiveConfigured) return\n restoreStarted.current = true\n arbi\n .restore()\n .catch(() => false)\n .then(async (restored) => {\n if (restored) await signingIn.current\n else setStatus('disconnected')\n })\n }, [arbi, isLiveConfigured])\n\n // Signing out: resolves once the mail kept on this device is gone too (the account client's\n // `signOut` waits for it); `logout` starts it.\n const signOutConnection = useCallback(async () => {\n sessionRun.current++\n // The SDK stops the session's work (requests, re-logins, opens, the queries in flight) before\n // the server revokes the token.\n if (mode === 'live') {\n void arbi.logout?.()\n }\n // What was typed never outlives the session (it is sealed, but kept for no one now).\n clearSealedDrafts()\n // Nor do the documents its chats were writing in this tab.\n clearChatArtifacts()\n setUser(null)\n selectWorkspaceId(null)\n persistWorkspace(config.apiUrl, storageUserRef.current, null)\n storageUserRef.current = null\n setStatus('disconnected')\n setError(null)\n // Nor does the mail kept on this device (the per-device choices stay, #2187). The sign-out is\n // done once it is gone.\n await wipeOfflineMail().catch(() => {})\n }, [arbi, mode, config.apiUrl, selectWorkspaceId])\n const logout = useCallback(() => {\n void signOutConnection()\n }, [signOutConnection])\n\n // Affirmative selection: the shared workspace switch (live), then remember it so the next\n // login lands there too. This provider IS the host's navigation, so it alone (with sign-in and\n // ensureWorkspaceOpen, which re-open the host's own selection) changes the workspace; kits reach\n // another workspace with `arbi.workspaces.open`.\n const setWorkspace = useCallback(\n async (id: string) => {\n if (mode === 'live' && arbi.isLoggedIn) {\n if (!(await switchWorkspace({ id }))) throw new Error('Could not open the workspace')\n } else {\n selectWorkspaceId(id)\n }\n persistWorkspace(config.apiUrl, storageUserRef.current, id)\n },\n [arbi, mode, config.apiUrl, selectWorkspaceId, switchWorkspace]\n )\n\n // Re-open the selected workspace on the session if the server may have dropped it. Idempotent.\n // A switch in flight is waited out first, then only the selection as of then is opened (none:\n // nothing). Never a remembered or configured workspace: kits call this before reading, and\n // opening another workspace than the selected one would leave the server session in it.\n const ensureWorkspaceOpen = useCallback(async () => {\n if (mode !== 'live' || !arbi.isLoggedIn) return\n await settled()\n if (!session.getState().workspaceId) return\n await openSelectedWorkspace()\n }, [arbi, session, mode, settled, openSelectedWorkspace])\n\n const value = useMemo<ConnectionValue>(\n () => ({\n mode,\n status,\n user,\n workspaceId,\n apiConfigured: isLiveConfigured,\n apiUrl: config.apiUrl,\n deploymentDomain: isLiveConfigured ? arbi.getDeploymentDomain() : undefined,\n error,\n assistantConfig: config.assistantConfig,\n fallbackWorkspaceId: mode === 'live' ? undefined : config.workspaceId,\n login,\n enterDemo,\n logout,\n setWorkspace,\n ensureWorkspaceOpen,\n }),\n [\n mode,\n status,\n user,\n workspaceId,\n isLiveConfigured,\n config.apiUrl,\n arbi,\n config.assistantConfig,\n config.workspaceId,\n error,\n login,\n enterDemo,\n logout,\n setWorkspace,\n ensureWorkspaceOpen,\n ]\n )\n\n const account = useConnectionAccount(arbi, user, signOutConnection)\n const authenticated = status === 'authenticated'\n const host = useMemo(\n () => ({ account: { client: account, useEnabled: () => authenticated } }),\n [account, authenticated]\n )\n\n return (\n <ConnectionContext.Provider value={value}>\n <ArbiHost config={host}>{children}</ArbiHost>\n </ConnectionContext.Provider>\n )\n}\n\n/**\n * The account client of the settings blocks below: the SDK's, with sign-out going through this\n * connection (so its state is cleared too) and, for a session restored without a login (no SDK\n * profile), the connection user as the profile.\n */\nfunction useConnectionAccount(\n arbi: ReturnType<typeof useArbi>,\n user: ArbiUser | null,\n logout: () => Promise<void>\n): AccountClient {\n const userRef = useRef(user)\n const logoutRef = useRef(logout)\n logoutRef.current = logout\n const listeners = useRef(new Set<() => void>())\n useEffect(() => {\n userRef.current = user\n listeners.current.forEach((listener) => listener())\n }, [user])\n return useMemo(() => {\n const base = arbiAccountClient(arbi)\n return {\n ...base,\n profile: (): ProfileView | null => {\n const own = base.profile()\n const fallback = userRef.current\n if (own || !fallback) return own\n return {\n ...toProfileView({\n givenName: '',\n familyName: null,\n picture: fallback.picture ?? null,\n email: fallback.email,\n isSso: false,\n }),\n fullName: fallback.name,\n }\n },\n onProfileChange: (listener) => {\n listeners.current.add(listener)\n const off = base.onProfileChange(listener)\n return () => {\n listeners.current.delete(listener)\n off()\n }\n },\n signOut: async ({ everywhere } = {}) => {\n try {\n if (everywhere) await arbi.sessions.logoutAll()\n } finally {\n await logoutRef.current()\n }\n },\n }\n }, [arbi])\n}\n\n/** The sign-in layer of `defaultHost`, or null under a host that keeps its own session. */\nexport function useOptionalConnection(): ConnectionValue | null {\n return useContext(ConnectionContext)\n}\n\nexport function useConnection(): ConnectionValue {\n const ctx = useContext(ConnectionContext)\n if (!ctx) throw new Error('useConnection needs the sign-in layer of `defaultHost` above it')\n return ctx\n}\n\n/** The sign-in layer's person (a demo session's identity too); none without `defaultHost`. */\nexport function useConnectionUser(): ArbiUser | null {\n return useContext(ConnectionContext)?.user ?? null\n}\n\nexport const isAuthenticated = (s: ConnectionStatus) => s === 'demo' || s === 'authenticated'\n\n/** The open workspace as the connected kits see it, whoever hosts them. */\nexport interface ConnectedWorkspace {\n /** The selected workspace (the session state's; with a connection, else its fallback). */\n workspaceId: string | null\n /** Signed in to a live backend: workspace-scoped queries may run. */\n live: boolean\n /** The signed-in user (their name and email, e.g. to sign a document). */\n user: ArbiUser | null\n /** The signed-in user's external id. */\n userId: string | undefined\n /** Re-assert the workspace on the server session before a workspace-scoped write. */\n ensureWorkspaceOpen: () => Promise<void>\n /**\n * Go into a workspace: select it (with a connection) and show it (`BlocksEnvironment.\n * openWorkspace`, where a host without a connection also switches its session).\n */\n openWorkspace: (workspaceId: string, options?: { name?: string }) => Promise<void>\n}\n\nconst keptOpenByHost = async () => {}\n\n/** The signed-in user of a host's own session, from its login profile. */\nfunction sessionUser(arbi: ReturnType<typeof useArbi>): ArbiUser | null {\n if (!arbi.isLoggedIn) return null\n const me = arbi.user.identity()\n const profile = arbi.user.profile()\n if (!me) return null\n return profile\n ? userFromProfile(profile, me.externalId)\n : { name: (me.email ?? '').split('@')[0], email: me.email ?? '', externalId: me.externalId }\n}\n\n/**\n * The workspace for a connected kit: the sign-in layer's (`defaultHost`) when there is one, else the\n * host's own session (an app whose host config has its `arbi` and `session` and keeps its\n * workspace open itself). So a kit runs the same in Clarum and in the ARBI app.\n */\nexport function useConnectedWorkspace(): ConnectedWorkspace {\n const connection = useContext(ConnectionContext)\n const arbi = useArbi()\n const sessionWorkspaceId = useArbiSessionState((s) => s.workspaceId)\n const live = connection ? connection.status === 'authenticated' : arbi.isLoggedIn\n const user = connection ? connection.user : live ? sessionUser(arbi) : null\n const userKey = `${user?.externalId ?? ''}|${user?.name ?? ''}|${user?.email ?? ''}`\n const { openWorkspace: showWorkspace } = useBlocksEnvironment()\n return useMemo(\n () => ({\n workspaceId: connection\n ? (connection.workspaceId ?? connection.fallbackWorkspaceId ?? null)\n : sessionWorkspaceId,\n live,\n user,\n userId: user?.externalId,\n ensureWorkspaceOpen: connection?.ensureWorkspaceOpen ?? keptOpenByHost,\n openWorkspace: async (workspaceId: string, options?: { name?: string }) => {\n if (connection) await connection.setWorkspace(workspaceId)\n showWorkspace(workspaceId, options)\n },\n }),\n // `user` is rebuilt each render without a connection: its key says when it changed.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [connection, sessionWorkspaceId, live, userKey, showWorkspace]\n )\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/connection/ConnectionProvider.tsx"],"names":["login"],"mappings":"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","file":"chunk-OWHO2TO3.js","sourcesContent":["/**\n * The demo/live connection layer for a host app. Holds auth + workspace\n * selection state and exposes it via {@link useConnection}, so every surface\n * works identically whether it's talking to a live ARBI backend or the seeded\n * demo workspace. Host-specific values (backend URL, demo identity, default\n * workspace/assistant ids) arrive once through {@link ArbiConnectionConfig}.\n */\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react'\nimport {\n arbiAccountClient,\n clearSealedDrafts,\n wipeOfflineMail,\n toProfileView,\n useArbi,\n useArbiSessionState,\n useArbiSessionStore,\n useSwitchWorkspace,\n type AccountClient,\n type LoginProfile,\n type ProfileView,\n} from '@arbidocs/react'\nimport { clearChatArtifacts } from '@arbidocs/react/shell'\nimport type { ArbiMode, ArbiUser, ConnectionStatus, ArbiConnectionConfig } from './types'\nimport { useBlocksEnvironment } from '../provider/environment'\nimport { ArbiHost } from '../provider/host'\nimport { closeAllDialogs } from '../provider/dialog-registry'\n\ninterface ConnectionValue {\n mode: ArbiMode\n status: ConnectionStatus\n user: ArbiUser | null\n /** The selected workspace: the session state's (`useArbiSessionState`), set by `setWorkspace`. */\n workspaceId: string | null\n apiConfigured: boolean\n apiUrl: string\n /**\n * The deployment domain the user's keys are derived for (`arbi.getDeploymentDomain()`), for the\n * document tools' e-signing. `undefined` in demo mode.\n */\n deploymentDomain: string | undefined\n error: string | null\n /** Default assistant config ext_id (for the AI hooks). */\n assistantConfig?: string\n /**\n * The demo's workspace when none is selected. Never set signed in to a live backend: there the\n * selection is the only workspace (none while a switch is in flight), never a remembered one.\n */\n fallbackWorkspaceId?: string\n /** Authenticate. Live login when a backend is configured, otherwise the demo workspace. */\n login: (email: string, password: string) => Promise<void>\n /** One-click demo entry (no backend required). */\n enterDemo: () => void\n logout: () => void\n /**\n * Affirmatively select a workspace: opens it on the server (via the SDK),\n * updates the app-wide state, and persists the choice so it survives future\n * logins. This is the single entry point for \"the user is now in workspace X\".\n */\n setWorkspace: (id: string) => Promise<void>\n /**\n * Re-assert the selected workspace on the server session (idempotent `/open`).\n * Call before a workspace-scoped write when the session may have lost its open\n * workspace (token re-login, backend restart, session expiry) — the server\n * resolves the workspace from the session, so a dropped `/open` yields\n * \"No active workspace\" until it's re-opened.\n */\n ensureWorkspaceOpen: () => Promise<void>\n}\n\nconst ConnectionContext = createContext<ConnectionValue | null>(null)\n\n/**\n * Persist the affirmatively-selected workspace per backend AND per signed-in user, so a returning\n * user lands back in the workspace they last chose, while the next person on a shared browser\n * never starts from someone else's workspace id. Namespaced by apiUrl so distinct deployments\n * (and the demo workspace) don't clobber each other. Cleared on logout.\n */\nconst WORKSPACE_STORAGE_PREFIX = 'arbi:selectedWorkspace'\nconst normalizeUserKey = (email: string) => email.trim().toLowerCase()\n\n/** Exported for tests. */\nexport const workspaceStorageKey = (apiUrl: string, userKey: string) =>\n `${WORKSPACE_STORAGE_PREFIX}:${apiUrl || 'demo'}:${normalizeUserKey(userKey)}`\n\n/** The pre-isolation key (apiUrl only). Never read: removed so it cannot leak across users. */\nconst legacyWorkspaceStorageKey = (apiUrl: string) =>\n `${WORKSPACE_STORAGE_PREFIX}:${apiUrl || 'demo'}`\n\nfunction readPersistedWorkspace(apiUrl: string, userKey: string | null): string | null {\n if (!userKey) return null\n try {\n return window.localStorage.getItem(workspaceStorageKey(apiUrl, userKey))\n } catch {\n return null\n }\n}\n\nfunction persistWorkspace(apiUrl: string, userKey: string | null, id: string | null): void {\n if (!userKey) return\n try {\n if (id) window.localStorage.setItem(workspaceStorageKey(apiUrl, userKey), id)\n else window.localStorage.removeItem(workspaceStorageKey(apiUrl, userKey))\n window.localStorage.removeItem(legacyWorkspaceStorageKey(apiUrl))\n } catch {\n // Storage unavailable (private mode, SSR) — selection stays in-memory only.\n }\n}\n\n/** Shown on the sign-in screen after the session could not be recovered. */\nexport const SESSION_EXPIRED_MESSAGE = 'Your session expired. Sign in again.'\n\n/** The connection user for a profile: its full name, falling back to the email local part. */\nfunction userFromProfile(profile: LoginProfile, externalId?: string): ArbiUser {\n const fullName = [profile.givenName, profile.familyName]\n .map((part) => part?.trim())\n .filter(Boolean)\n .join(' ')\n return {\n name: fullName || profile.email.split('@')[0],\n email: profile.email,\n externalId,\n picture: profile.picture,\n }\n}\n\n/**\n * The sign-in layer of a blocks-only site, mounted by its host (`defaultHost`): login, demo mode\n * and the selected workspace, over the host's session state (the selected workspace lives there,\n * so every block reads one value). Its account client is the host's `account` below it.\n */\nexport function ConnectionProvider({\n config,\n children,\n}: {\n config: ArbiConnectionConfig\n children: ReactNode\n}) {\n const arbi = useArbi()\n const session = useArbiSessionStore()\n const { switchWorkspace, openSelectedWorkspace, settled } = useSwitchWorkspace()\n const isLiveConfigured = config.apiUrl.length > 0\n const demoWorkspaceId = config.demoWorkspaceId ?? 'demo-workspace'\n\n const [status, setStatus] = useState<ConnectionStatus>(\n isLiveConfigured ? 'connecting' : 'disconnected'\n )\n const [user, setUser] = useState<ArbiUser | null>(null)\n const workspaceId = useArbiSessionState((s) => s.workspaceId)\n const selectWorkspaceId = session.setWorkspaceId\n const [mode, setMode] = useState<ArbiMode>('demo')\n const [error, setError] = useState<string | null>(null)\n // Dialogs belong to the signed-in session. A first signed-out mount may carry an invitation\n // intent, so clear only after an authenticated (or demo) session actually ends. A workspace\n // switch / sign-in can pass through `connecting` without ending that session.\n const hadDialogSession = useRef(false)\n useEffect(() => {\n if (status === 'authenticated' || status === 'demo') {\n hadDialogSession.current = true\n } else if (status !== 'connecting' && hadDialogSession.current) {\n hadDialogSession.current = false\n closeAllDialogs()\n }\n }, [status])\n // Who the persisted workspace belongs to; set at sign-in, cleared at logout.\n const storageUserRef = useRef<string | null>(null)\n // Moves at each logout: a sign-in still finishing from before it does not sign back in.\n const sessionRun = useRef(0)\n\n // The SDK could not recover the session (token refused, workspace not re-openable): drop to\n // 'disconnected' with a plain message, so the host's gate sends the user to sign in instead of\n // every call failing with a raw backend error. The remembered workspace is kept for next login.\n useEffect(\n () =>\n arbi.onSessionExpired?.(() => {\n storageUserRef.current = null\n setUser(null)\n selectWorkspaceId(null)\n setStatus('disconnected')\n setError(SESSION_EXPIRED_MESSAGE)\n }),\n [arbi, selectWorkspaceId]\n )\n\n // A saved name, picture or email reaches every surface reading `useConnection().user`.\n useEffect(\n () =>\n arbi.user.onProfileChange?.((profile) =>\n setUser((current) => (current ? userFromProfile(profile, current.externalId) : current))\n ),\n [arbi]\n )\n\n const enterDemo = useCallback(() => {\n setMode('demo')\n setStatus('demo')\n setError(null)\n setUser({ name: config.demoUser.name, email: config.demoUser.email })\n selectWorkspaceId(demoWorkspaceId)\n }, [config.demoUser.name, config.demoUser.email, demoWorkspaceId, selectWorkspaceId])\n\n /**\n * The session signed in, by whatever path (`login` below, a sign-in page on the host's `Arbi`,\n * a restored session): open the user's workspace and resolve who they are.\n */\n const completeSignIn = useCallback(\n async (email: string) => {\n const run = sessionRun.current\n const signedOut = () => run !== sessionRun.current\n setMode('live')\n setStatus('connecting')\n setError(null)\n try {\n storageUserRef.current = normalizeUserKey(email)\n const workspaces = await arbi.workspaces.list()\n if (workspaces?.length) {\n // Prefer the workspace the user last affirmatively selected (persisted),\n // then the configured workspace (there may be several — e.g. a\n // marketing/KM workspace), then whichever happens to be first. Ternary\n // (not `&&`) so an empty value can't leak `\"\"` into `target`.\n const persisted = readPersistedWorkspace(config.apiUrl, storageUserRef.current)\n const preferred = persisted ?? config.workspaceId\n const target =\n (preferred ? workspaces.find((w) => w.external_id === preferred) : undefined) ??\n (config.requireWorkspaceSelection ? undefined : workspaces[0])\n if (target) {\n selectWorkspaceId(target.external_id)\n if (!(await openSelectedWorkspace()))\n throw new Error('Could not open your workspace. Try signing in again.')\n persistWorkspace(config.apiUrl, storageUserRef.current, target.external_id)\n }\n }\n // The profile (name + avatar) comes with the login response. A session restored without\n // a login has none, so fall back to finding ourselves in the workspace roster; the email\n // local part is only the last resort, never the answer when a profile name exists.\n let resolved: ArbiUser = { name: email.split('@')[0], email }\n const me = arbi.user.identity()\n const profile = arbi.user.profile?.()\n if (profile) {\n resolved = userFromProfile(profile, me?.externalId)\n } else {\n try {\n const members = await arbi.workspaces.listUsers()\n const self = members.find((m) => m.user.external_id === me?.externalId)?.user\n if (self) {\n const fullName = [self.given_name, self.family_name].filter(Boolean).join(' ').trim()\n resolved = {\n name: fullName || email.split('@')[0],\n email: self.email || email,\n externalId: self.external_id,\n picture: self.picture ?? null,\n }\n } else if (me?.externalId) {\n resolved.externalId = me.externalId\n }\n } catch {\n // Roster not available (e.g. no workspace) — keep the fallback identity.\n }\n }\n if (signedOut()) return\n setUser(resolved)\n setStatus('authenticated')\n } catch (e) {\n if (signedOut()) return\n // Surface the real error — no silent fallback to a fake session.\n setError(e instanceof Error ? e.message : 'Sign-in failed. Check your credentials.')\n setStatus('error')\n }\n },\n [\n arbi,\n config.workspaceId,\n config.apiUrl,\n config.requireWorkspaceSelection,\n selectWorkspaceId,\n openSelectedWorkspace,\n ]\n )\n\n // Every sign-in on the host's `Arbi` lands here, whichever page or kit made it.\n const signingIn = useRef<Promise<void>>(Promise.resolve())\n useEffect(\n () =>\n arbi.onSignedIn?.((login) => {\n signingIn.current = completeSignIn(\n login.profile?.email ??\n arbi.session?.getState().userEmail ??\n arbi.user.identity()?.email ??\n ''\n )\n }),\n [arbi, completeSignIn]\n )\n\n /** Authenticate: a live login when a backend is configured, otherwise the demo workspace. */\n const login = useCallback(\n async (email: string, password: string) => {\n setError(null)\n if (!isLiveConfigured) {\n enterDemo()\n return\n }\n setStatus('connecting')\n setMode('live')\n try {\n // Signed in: `completeSignIn` follows (onSignedIn); done once it is.\n await arbi.login(email, password)\n await signingIn.current\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Sign-in failed. Check your credentials.')\n setStatus('error')\n }\n },\n [arbi, enterDemo, isLiveConfigured]\n )\n\n // The session kept on this device signs in again (no password; the key stays encrypted on the\n // device). Run once even under StrictMode.\n const restoreStarted = useRef(false)\n useEffect(() => {\n if (restoreStarted.current || !isLiveConfigured) return\n restoreStarted.current = true\n arbi\n .restore()\n .catch(() => false)\n .then(async (restored) => {\n if (restored) await signingIn.current\n else setStatus('disconnected')\n })\n }, [arbi, isLiveConfigured])\n\n // Signing out: resolves once the mail kept on this device is gone too (the account client's\n // `signOut` waits for it); `logout` starts it.\n const signOutConnection = useCallback(async () => {\n sessionRun.current++\n // The SDK stops the session's work (requests, re-logins, opens, the queries in flight) before\n // the server revokes the token.\n if (mode === 'live') {\n void arbi.logout?.()\n }\n // What was typed never outlives the session (it is sealed, but kept for no one now).\n clearSealedDrafts()\n // Nor do the documents its chats were writing in this tab.\n clearChatArtifacts()\n setUser(null)\n selectWorkspaceId(null)\n persistWorkspace(config.apiUrl, storageUserRef.current, null)\n storageUserRef.current = null\n setStatus('disconnected')\n setError(null)\n // Nor does the mail kept on this device (the per-device choices stay, #2187). The sign-out is\n // done once it is gone.\n await wipeOfflineMail().catch(() => {})\n }, [arbi, mode, config.apiUrl, selectWorkspaceId])\n const logout = useCallback(() => {\n void signOutConnection()\n }, [signOutConnection])\n\n // Affirmative selection: the shared workspace switch (live), then remember it so the next\n // login lands there too. This provider IS the host's navigation, so it alone (with sign-in and\n // ensureWorkspaceOpen, which re-open the host's own selection) changes the workspace; kits reach\n // another workspace with `arbi.workspaces.open`.\n const setWorkspace = useCallback(\n async (id: string) => {\n if (mode === 'live' && arbi.isLoggedIn) {\n if (!(await switchWorkspace({ id }))) throw new Error('Could not open the workspace')\n } else {\n selectWorkspaceId(id)\n }\n persistWorkspace(config.apiUrl, storageUserRef.current, id)\n },\n [arbi, mode, config.apiUrl, selectWorkspaceId, switchWorkspace]\n )\n\n // Re-open the selected workspace on the session if the server may have dropped it. Idempotent.\n // A switch in flight is waited out first, then only the selection as of then is opened (none:\n // nothing). Never a remembered or configured workspace: kits call this before reading, and\n // opening another workspace than the selected one would leave the server session in it.\n const ensureWorkspaceOpen = useCallback(async () => {\n if (mode !== 'live' || !arbi.isLoggedIn) return\n await settled()\n if (!session.getState().workspaceId) return\n await openSelectedWorkspace()\n }, [arbi, session, mode, settled, openSelectedWorkspace])\n\n const value = useMemo<ConnectionValue>(\n () => ({\n mode,\n status,\n user,\n workspaceId,\n apiConfigured: isLiveConfigured,\n apiUrl: config.apiUrl,\n deploymentDomain: isLiveConfigured ? arbi.getDeploymentDomain() : undefined,\n error,\n assistantConfig: config.assistantConfig,\n fallbackWorkspaceId: mode === 'live' ? undefined : config.workspaceId,\n login,\n enterDemo,\n logout,\n setWorkspace,\n ensureWorkspaceOpen,\n }),\n [\n mode,\n status,\n user,\n workspaceId,\n isLiveConfigured,\n config.apiUrl,\n arbi,\n config.assistantConfig,\n config.workspaceId,\n error,\n login,\n enterDemo,\n logout,\n setWorkspace,\n ensureWorkspaceOpen,\n ]\n )\n\n const account = useConnectionAccount(arbi, user, signOutConnection)\n const authenticated = status === 'authenticated'\n const host = useMemo(\n () => ({ account: { client: account, useEnabled: () => authenticated } }),\n [account, authenticated]\n )\n\n return (\n <ConnectionContext.Provider value={value}>\n <ArbiHost config={host}>{children}</ArbiHost>\n </ConnectionContext.Provider>\n )\n}\n\n/**\n * The account client of the settings blocks below: the SDK's, with sign-out going through this\n * connection (so its state is cleared too) and, for a session restored without a login (no SDK\n * profile), the connection user as the profile.\n */\nfunction useConnectionAccount(\n arbi: ReturnType<typeof useArbi>,\n user: ArbiUser | null,\n logout: () => Promise<void>\n): AccountClient {\n const userRef = useRef(user)\n const logoutRef = useRef(logout)\n logoutRef.current = logout\n const listeners = useRef(new Set<() => void>())\n useEffect(() => {\n userRef.current = user\n listeners.current.forEach((listener) => listener())\n }, [user])\n return useMemo(() => {\n const base = arbiAccountClient(arbi)\n return {\n ...base,\n profile: (): ProfileView | null => {\n const own = base.profile()\n const fallback = userRef.current\n if (own || !fallback) return own\n return {\n ...toProfileView({\n givenName: '',\n familyName: null,\n picture: fallback.picture ?? null,\n email: fallback.email,\n isSso: false,\n }),\n fullName: fallback.name,\n }\n },\n onProfileChange: (listener) => {\n listeners.current.add(listener)\n const off = base.onProfileChange(listener)\n return () => {\n listeners.current.delete(listener)\n off()\n }\n },\n signOut: async ({ everywhere } = {}) => {\n try {\n if (everywhere) await arbi.sessions.logoutAll()\n } finally {\n await logoutRef.current()\n }\n },\n }\n }, [arbi])\n}\n\n/** The sign-in layer of `defaultHost`, or null under a host that keeps its own session. */\nexport function useOptionalConnection(): ConnectionValue | null {\n return useContext(ConnectionContext)\n}\n\nexport function useConnection(): ConnectionValue {\n const ctx = useContext(ConnectionContext)\n if (!ctx) throw new Error('useConnection needs the sign-in layer of `defaultHost` above it')\n return ctx\n}\n\n/** The sign-in layer's person (a demo session's identity too); none without `defaultHost`. */\nexport function useConnectionUser(): ArbiUser | null {\n return useContext(ConnectionContext)?.user ?? null\n}\n\nexport const isAuthenticated = (s: ConnectionStatus) => s === 'demo' || s === 'authenticated'\n\n/** The open workspace as the connected kits see it, whoever hosts them. */\nexport interface ConnectedWorkspace {\n /** The selected workspace (the session state's; with a connection, else its fallback). */\n workspaceId: string | null\n /** Signed in to a live backend: workspace-scoped queries may run. */\n live: boolean\n /** The signed-in user (their name and email, e.g. to sign a document). */\n user: ArbiUser | null\n /** The signed-in user's external id. */\n userId: string | undefined\n /** Re-assert the workspace on the server session before a workspace-scoped write. */\n ensureWorkspaceOpen: () => Promise<void>\n /**\n * Go into a workspace: select it (with a connection) and show it (`BlocksEnvironment.\n * openWorkspace`, where a host without a connection also switches its session).\n */\n openWorkspace: (workspaceId: string, options?: { name?: string }) => Promise<void>\n}\n\nconst keptOpenByHost = async () => {}\n\n/** The signed-in user of a host's own session, from its login profile. */\nfunction sessionUser(arbi: ReturnType<typeof useArbi>): ArbiUser | null {\n if (!arbi.isLoggedIn) return null\n const me = arbi.user.identity()\n const profile = arbi.user.profile()\n if (!me) return null\n return profile\n ? userFromProfile(profile, me.externalId)\n : { name: (me.email ?? '').split('@')[0], email: me.email ?? '', externalId: me.externalId }\n}\n\n/**\n * The workspace for a connected kit: the sign-in layer's (`defaultHost`) when there is one, else the\n * host's own session (an app whose host config has its `arbi` and `session` and keeps its\n * workspace open itself). So a kit runs the same in Clarum and in the ARBI app.\n */\nexport function useConnectedWorkspace(): ConnectedWorkspace {\n const connection = useContext(ConnectionContext)\n const arbi = useArbi()\n const sessionWorkspaceId = useArbiSessionState((s) => s.workspaceId)\n const live = connection ? connection.status === 'authenticated' : arbi.isLoggedIn\n const user = connection ? connection.user : live ? sessionUser(arbi) : null\n const userKey = `${user?.externalId ?? ''}|${user?.name ?? ''}|${user?.email ?? ''}`\n const { openWorkspace: showWorkspace } = useBlocksEnvironment()\n return useMemo(\n () => ({\n workspaceId: connection\n ? (connection.workspaceId ?? connection.fallbackWorkspaceId ?? null)\n : sessionWorkspaceId,\n live,\n user,\n userId: user?.externalId,\n ensureWorkspaceOpen: connection?.ensureWorkspaceOpen ?? keptOpenByHost,\n openWorkspace: async (workspaceId: string, options?: { name?: string }) => {\n if (connection) await connection.setWorkspace(workspaceId)\n showWorkspace(workspaceId, options)\n },\n }),\n // `user` is rebuilt each render without a connection: its key says when it changed.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [connection, sessionWorkspaceId, live, userKey, showWorkspace]\n )\n}\n"]}
|