@dxos/plugin-space 0.8.1-main.ae460ac → 0.8.1-staging.31c3ee1
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/dist/lib/browser/{app-graph-builder-MGK5HWPZ.mjs → app-graph-builder-GMFCSOLG.mjs} +33 -6
- package/dist/lib/browser/app-graph-builder-GMFCSOLG.mjs.map +7 -0
- package/dist/lib/browser/{app-graph-serializer-FOWFLYGU.mjs → app-graph-serializer-DSF2U3A5.mjs} +7 -7
- package/dist/lib/browser/{app-graph-serializer-FOWFLYGU.mjs.map → app-graph-serializer-DSF2U3A5.mjs.map} +2 -2
- package/dist/lib/browser/{chunk-UDWHTKB5.mjs → chunk-5BDV575R.mjs} +22 -16
- package/dist/lib/browser/chunk-5BDV575R.mjs.map +7 -0
- package/dist/lib/browser/{chunk-ULA2UQJ4.mjs → chunk-AYW4IDRT.mjs} +15 -65
- package/dist/lib/browser/chunk-AYW4IDRT.mjs.map +7 -0
- package/dist/lib/browser/{chunk-PCEP3KQY.mjs → chunk-DVZEJGCK.mjs} +854 -587
- package/dist/lib/browser/chunk-DVZEJGCK.mjs.map +7 -0
- package/dist/lib/browser/{chunk-NU7WDVGN.mjs → chunk-KVRYWFZU.mjs} +3 -3
- package/dist/lib/browser/chunk-KVRYWFZU.mjs.map +7 -0
- package/dist/lib/browser/{chunk-23RVI5FZ.mjs → chunk-LO5UL6RU.mjs} +49 -16
- package/dist/lib/browser/chunk-LO5UL6RU.mjs.map +7 -0
- package/dist/lib/browser/{chunk-PQXZCNAU.mjs → chunk-PTKYMZWO.mjs} +1 -1
- package/dist/lib/browser/chunk-PTKYMZWO.mjs.map +7 -0
- package/dist/lib/browser/{identity-created-FYGS6TBH.mjs → identity-created-JR7BNXFH.mjs} +3 -3
- package/dist/lib/browser/index.mjs +40 -45
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/{intent-resolver-GPNAQ2SG.mjs → intent-resolver-OG62I5IL.mjs} +69 -44
- package/dist/lib/browser/intent-resolver-OG62I5IL.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-root-4CCSD7TZ.mjs → react-root-VPSIJ6EU.mjs} +6 -6
- package/dist/lib/browser/{react-surface-FKMRI3WV.mjs → react-surface-KOSYP574.mjs} +39 -38
- package/dist/lib/browser/react-surface-KOSYP574.mjs.map +7 -0
- package/dist/lib/browser/{schema-5W3DSY2E.mjs → schema-FHTA26SW.mjs} +3 -3
- package/dist/lib/browser/schema-tools-YAXPRIXP.mjs +123 -0
- package/dist/lib/browser/schema-tools-YAXPRIXP.mjs.map +7 -0
- package/dist/lib/browser/{settings-PHPCXX33.mjs → settings-PJPTJUPE.mjs} +3 -3
- package/dist/lib/browser/{spaces-ready-K47RR7N2.mjs → spaces-ready-BSSP7HHG.mjs} +8 -8
- package/dist/lib/browser/spaces-ready-BSSP7HHG.mjs.map +7 -0
- package/dist/lib/browser/{state-INJ63O57.mjs → state-X7VLCC6E.mjs} +5 -3
- package/dist/lib/browser/state-X7VLCC6E.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +2 -10
- package/dist/lib/node/{app-graph-builder-ZIUBXRPA.cjs → app-graph-builder-DPY7AUZE.cjs} +73 -46
- package/dist/lib/node/app-graph-builder-DPY7AUZE.cjs.map +7 -0
- package/dist/lib/node/{app-graph-serializer-VQOGHKXL.cjs → app-graph-serializer-JELGJUAY.cjs} +21 -21
- package/dist/lib/node/{app-graph-serializer-VQOGHKXL.cjs.map → app-graph-serializer-JELGJUAY.cjs.map} +2 -2
- package/dist/lib/node/{chunk-WZR6OAN3.cjs → chunk-6P2DB4QQ.cjs} +4 -4
- package/dist/lib/node/{chunk-WZR6OAN3.cjs.map → chunk-6P2DB4QQ.cjs.map} +2 -2
- package/dist/lib/node/{chunk-QE4GVR6C.cjs → chunk-APYLLIMY.cjs} +919 -657
- package/dist/lib/node/chunk-APYLLIMY.cjs.map +7 -0
- package/dist/lib/node/{chunk-YZKNRFHU.cjs → chunk-IKIDS6XF.cjs} +10 -10
- package/dist/lib/node/chunk-IKIDS6XF.cjs.map +7 -0
- package/dist/lib/node/{chunk-U6DYXAR3.cjs → chunk-PU2EYH4E.cjs} +27 -21
- package/dist/lib/node/chunk-PU2EYH4E.cjs.map +7 -0
- package/dist/lib/node/{chunk-OVGKWJOC.cjs → chunk-TUZWEPGX.cjs} +99 -66
- package/dist/lib/node/chunk-TUZWEPGX.cjs.map +7 -0
- package/dist/lib/node/{chunk-WAJKBO3J.cjs → chunk-WDEIFDTX.cjs} +19 -73
- package/dist/lib/node/chunk-WDEIFDTX.cjs.map +7 -0
- package/dist/lib/node/{identity-created-AXI64BLE.cjs → identity-created-XU4HFV2T.cjs} +7 -7
- package/dist/lib/node/index.cjs +105 -111
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/{intent-resolver-ICHHI6I6.cjs → intent-resolver-UMF6MLOH.cjs} +133 -107
- package/dist/lib/node/intent-resolver-UMF6MLOH.cjs.map +7 -0
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/{react-root-TCBTUOOJ.cjs → react-root-ZRFHMM7R.cjs} +12 -12
- package/dist/lib/node/{react-surface-JSCCIZS5.cjs → react-surface-72U57CIU.cjs} +78 -76
- package/dist/lib/node/react-surface-72U57CIU.cjs.map +7 -0
- package/dist/lib/node/{schema-YN7WVFRX.cjs → schema-PPJ5BZ3A.cjs} +7 -7
- package/dist/lib/node/schema-tools-BLIMOZYY.cjs +146 -0
- package/dist/lib/node/schema-tools-BLIMOZYY.cjs.map +7 -0
- package/dist/lib/node/{settings-5QYFWNH7.cjs → settings-WVFP2UEP.cjs} +8 -8
- package/dist/lib/node/{spaces-ready-FQNAKR7G.cjs → spaces-ready-7DNZSUOG.cjs} +16 -16
- package/dist/lib/node/spaces-ready-7DNZSUOG.cjs.map +7 -0
- package/dist/lib/node/{state-57UE3DYE.cjs → state-5KX6WBJH.cjs} +10 -8
- package/dist/lib/node/state-5KX6WBJH.cjs.map +7 -0
- package/dist/lib/node/types/index.cjs +13 -21
- package/dist/lib/node/types/index.cjs.map +2 -2
- package/dist/lib/node-esm/{app-graph-builder-TERVM2SL.mjs → app-graph-builder-42IGWRPL.mjs} +33 -6
- package/dist/lib/node-esm/app-graph-builder-42IGWRPL.mjs.map +7 -0
- package/dist/lib/node-esm/{app-graph-serializer-GZRSWHEN.mjs → app-graph-serializer-FXONFKOE.mjs} +7 -7
- package/dist/lib/node-esm/{app-graph-serializer-GZRSWHEN.mjs.map → app-graph-serializer-FXONFKOE.mjs.map} +2 -2
- package/dist/lib/node-esm/{chunk-2TQ2AJEZ.mjs → chunk-3ZOUV4DF.mjs} +22 -16
- package/dist/lib/node-esm/chunk-3ZOUV4DF.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-TRNZQEEN.mjs → chunk-FC4UHDPL.mjs} +15 -65
- package/dist/lib/node-esm/chunk-FC4UHDPL.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-HJCEJNW3.mjs → chunk-HMCIZ7G7.mjs} +854 -587
- package/dist/lib/node-esm/chunk-HMCIZ7G7.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-ICCM4YRJ.mjs → chunk-MSWEFAPD.mjs} +1 -1
- package/dist/lib/node-esm/chunk-MSWEFAPD.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-6RSVVEPS.mjs → chunk-PIYAWT5N.mjs} +3 -3
- package/dist/lib/node-esm/chunk-PIYAWT5N.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-PGH5L7MV.mjs → chunk-ZGLK25WQ.mjs} +49 -16
- package/dist/lib/node-esm/chunk-ZGLK25WQ.mjs.map +7 -0
- package/dist/lib/node-esm/{identity-created-3CGEXNPO.mjs → identity-created-WJKAS2PV.mjs} +3 -3
- package/dist/lib/node-esm/index.mjs +40 -45
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/{intent-resolver-VR42K5GE.mjs → intent-resolver-67C5MOIE.mjs} +69 -44
- package/dist/lib/node-esm/intent-resolver-67C5MOIE.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{react-root-THJBSTQS.mjs → react-root-XPRWMZGT.mjs} +6 -6
- package/dist/lib/node-esm/{react-surface-Z3BBQ5HX.mjs → react-surface-MUE6M34Y.mjs} +39 -38
- package/dist/lib/node-esm/react-surface-MUE6M34Y.mjs.map +7 -0
- package/dist/lib/node-esm/{schema-LOR2EVGY.mjs → schema-OUZKVYM5.mjs} +3 -3
- package/dist/lib/node-esm/schema-tools-IU7EX5A5.mjs +125 -0
- package/dist/lib/node-esm/schema-tools-IU7EX5A5.mjs.map +7 -0
- package/dist/lib/node-esm/{settings-H6MXTEQM.mjs → settings-FJZPC2TV.mjs} +3 -3
- package/dist/lib/node-esm/{spaces-ready-HKAQG5SA.mjs → spaces-ready-7X5PGB2V.mjs} +8 -8
- package/dist/lib/node-esm/spaces-ready-7X5PGB2V.mjs.map +7 -0
- package/dist/lib/node-esm/{state-VYA6OFHD.mjs → state-Z6E2YTNC.mjs} +5 -3
- package/dist/lib/node-esm/state-Z6E2YTNC.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +2 -10
- package/dist/types/src/SpacePlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/capabilities/capabilities.d.ts +4 -3
- package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +1 -1
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts +1 -2
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/schema-tool.test.d.ts +2 -0
- package/dist/types/src/capabilities/schema-tool.test.d.ts.map +1 -0
- package/dist/types/src/capabilities/schema-tools.d.ts +13 -0
- package/dist/types/src/capabilities/schema-tools.d.ts.map +1 -0
- package/dist/types/src/capabilities/state.d.ts.map +1 -1
- package/dist/types/src/components/AwaitingObject.d.ts +2 -1
- package/dist/types/src/components/AwaitingObject.d.ts.map +1 -1
- package/dist/types/src/components/CollectionMain.d.ts +2 -1
- package/dist/types/src/components/CollectionMain.d.ts.map +1 -1
- package/dist/types/src/components/CollectionSection.d.ts +2 -1
- package/dist/types/src/components/CollectionSection.d.ts.map +1 -1
- package/dist/types/src/components/CreateDialog/CreateObjectDialog.d.ts +2 -1
- package/dist/types/src/components/CreateDialog/CreateObjectDialog.d.ts.map +1 -1
- package/dist/types/src/components/CreateDialog/CreateObjectPanel.d.ts +2 -1
- package/dist/types/src/components/CreateDialog/CreateObjectPanel.d.ts.map +1 -1
- package/dist/types/src/components/CreateDialog/CreateSpaceDialog.d.ts +2 -1
- package/dist/types/src/components/CreateDialog/CreateSpaceDialog.d.ts.map +1 -1
- package/dist/types/src/components/JoinDialog.d.ts +2 -1
- package/dist/types/src/components/JoinDialog.d.ts.map +1 -1
- package/dist/types/src/components/MembersContainer.d.ts +7 -0
- package/dist/types/src/components/MembersContainer.d.ts.map +1 -0
- package/dist/types/src/components/MembersContainer.stories.d.ts +8 -0
- package/dist/types/src/components/MembersContainer.stories.d.ts.map +1 -0
- package/dist/types/src/components/MenuFooter.d.ts +2 -1
- package/dist/types/src/components/MenuFooter.d.ts.map +1 -1
- package/dist/types/src/components/{AdvancedObjectSettings → ObjectSettingsContainer}/AdvancedObjectSettings.d.ts +2 -1
- package/dist/types/src/components/ObjectSettingsContainer/AdvancedObjectSettings.d.ts.map +1 -0
- package/dist/types/src/components/ObjectSettingsContainer/BaseObjectSettings.d.ts +8 -0
- package/dist/types/src/components/ObjectSettingsContainer/BaseObjectSettings.d.ts.map +1 -0
- package/dist/types/src/components/{AdvancedObjectSettings → ObjectSettingsContainer}/ForeignKeys.d.ts +2 -1
- package/dist/types/src/components/ObjectSettingsContainer/ForeignKeys.d.ts.map +1 -0
- package/dist/types/src/components/ObjectSettingsContainer/ObjectSettingsContainer.d.ts +8 -0
- package/dist/types/src/components/ObjectSettingsContainer/ObjectSettingsContainer.d.ts.map +1 -0
- package/dist/types/src/components/ObjectSettingsContainer/index.d.ts +2 -0
- package/dist/types/src/components/ObjectSettingsContainer/index.d.ts.map +1 -0
- package/dist/types/src/components/PersistenceStatus.d.ts +2 -1
- package/dist/types/src/components/PersistenceStatus.d.ts.map +1 -1
- package/dist/types/src/components/PopoverAddSpace.d.ts +2 -1
- package/dist/types/src/components/PopoverAddSpace.d.ts.map +1 -1
- package/dist/types/src/components/PopoverRenameObject.d.ts +2 -1
- package/dist/types/src/components/PopoverRenameObject.d.ts.map +1 -1
- package/dist/types/src/components/PopoverRenameSpace.d.ts +2 -1
- package/dist/types/src/components/PopoverRenameSpace.d.ts.map +1 -1
- package/dist/types/src/components/ShareSpaceButton.d.ts +3 -2
- package/dist/types/src/components/ShareSpaceButton.d.ts.map +1 -1
- package/dist/types/src/components/SpacePluginSettings.d.ts +2 -1
- package/dist/types/src/components/SpacePluginSettings.d.ts.map +1 -1
- package/dist/types/src/components/SpacePresence.d.ts +5 -4
- package/dist/types/src/components/SpacePresence.d.ts.map +1 -1
- package/dist/types/src/components/SpacePresence.stories.d.ts +3 -2
- package/dist/types/src/components/SpacePresence.stories.d.ts.map +1 -1
- package/dist/types/src/components/SpaceSettings/SpacePropertiesForm.d.ts +7 -0
- package/dist/types/src/components/SpaceSettings/SpacePropertiesForm.d.ts.map +1 -0
- package/dist/types/src/components/SpaceSettings/SpacePropertiesForm.stories.d.ts +7 -0
- package/dist/types/src/components/SpaceSettings/SpacePropertiesForm.stories.d.ts.map +1 -0
- package/dist/types/src/components/SpaceSettings/SpaceSettingsContainer.d.ts +9 -0
- package/dist/types/src/components/SpaceSettings/SpaceSettingsContainer.d.ts.map +1 -0
- package/dist/types/src/components/SpaceSettings/index.d.ts +2 -2
- package/dist/types/src/components/SpaceSettings/index.d.ts.map +1 -1
- package/dist/types/src/components/SyncStatus/InlineSyncStatus.d.ts +2 -1
- package/dist/types/src/components/SyncStatus/InlineSyncStatus.d.ts.map +1 -1
- package/dist/types/src/components/SyncStatus/Space.d.ts +3 -2
- package/dist/types/src/components/SyncStatus/Space.d.ts.map +1 -1
- package/dist/types/src/components/SyncStatus/SyncStatus.d.ts +4 -3
- package/dist/types/src/components/SyncStatus/SyncStatus.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +2 -2
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/events.d.ts +1 -1
- package/dist/types/src/events.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +2 -5
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +53 -36
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/thread.d.ts +92 -197
- package/dist/types/src/types/thread.d.ts.map +1 -1
- package/dist/types/src/types/types.d.ts +10 -0
- package/dist/types/src/types/types.d.ts.map +1 -1
- package/dist/types/src/util.d.ts +12 -0
- package/dist/types/src/util.d.ts.map +1 -1
- package/package.json +45 -40
- package/src/SpacePlugin.tsx +12 -11
- package/src/capabilities/app-graph-builder.ts +20 -0
- package/src/capabilities/app-graph-serializer.ts +2 -2
- package/src/capabilities/capabilities.ts +3 -3
- package/src/capabilities/index.ts +1 -0
- package/src/capabilities/intent-resolver.ts +66 -38
- package/src/capabilities/react-surface.tsx +30 -28
- package/src/capabilities/schema-tool.test.ts +45 -0
- package/src/capabilities/schema-tools.ts +124 -0
- package/src/capabilities/spaces-ready.ts +3 -3
- package/src/capabilities/state.ts +2 -0
- package/src/components/CreateDialog/CreateObjectDialog.tsx +3 -6
- package/src/components/CreateDialog/CreateObjectPanel.tsx +6 -6
- package/src/components/JoinDialog.tsx +43 -27
- package/src/components/MembersContainer.stories.tsx +34 -0
- package/src/components/MembersContainer.tsx +255 -0
- package/src/components/{AdvancedObjectSettings → ObjectSettingsContainer}/AdvancedObjectSettings.tsx +2 -2
- package/src/components/ObjectSettingsContainer/BaseObjectSettings.tsx +47 -0
- package/src/components/ObjectSettingsContainer/ObjectSettingsContainer.tsx +36 -0
- package/src/components/ObjectSettingsContainer/index.ts +5 -0
- package/src/components/PopoverRenameObject.tsx +1 -1
- package/src/components/SpacePresence.tsx +25 -23
- package/src/components/SpaceSettings/{SpaceSettingsPanel.stories.tsx → SpacePropertiesForm.stories.tsx} +6 -6
- package/src/components/SpaceSettings/SpacePropertiesForm.tsx +136 -0
- package/src/components/SpaceSettings/SpaceSettingsContainer.tsx +63 -0
- package/src/components/SpaceSettings/index.ts +2 -2
- package/src/components/SyncStatus/SyncStatus.tsx +1 -1
- package/src/components/SyncStatus/save-tracker.ts +5 -5
- package/src/components/index.ts +2 -2
- package/src/events.ts +2 -2
- package/src/meta.ts +2 -2
- package/src/translations.ts +21 -12
- package/src/types/thread.ts +2 -56
- package/src/types/types.ts +15 -6
- package/src/util.tsx +30 -9
- package/dist/lib/browser/app-graph-builder-MGK5HWPZ.mjs.map +0 -7
- package/dist/lib/browser/chunk-23RVI5FZ.mjs.map +0 -7
- package/dist/lib/browser/chunk-NU7WDVGN.mjs.map +0 -7
- package/dist/lib/browser/chunk-PCEP3KQY.mjs.map +0 -7
- package/dist/lib/browser/chunk-PQXZCNAU.mjs.map +0 -7
- package/dist/lib/browser/chunk-UDWHTKB5.mjs.map +0 -7
- package/dist/lib/browser/chunk-ULA2UQJ4.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-GPNAQ2SG.mjs.map +0 -7
- package/dist/lib/browser/react-surface-FKMRI3WV.mjs.map +0 -7
- package/dist/lib/browser/spaces-ready-K47RR7N2.mjs.map +0 -7
- package/dist/lib/browser/state-INJ63O57.mjs.map +0 -7
- package/dist/lib/node/app-graph-builder-ZIUBXRPA.cjs.map +0 -7
- package/dist/lib/node/chunk-OVGKWJOC.cjs.map +0 -7
- package/dist/lib/node/chunk-QE4GVR6C.cjs.map +0 -7
- package/dist/lib/node/chunk-U6DYXAR3.cjs.map +0 -7
- package/dist/lib/node/chunk-WAJKBO3J.cjs.map +0 -7
- package/dist/lib/node/chunk-YZKNRFHU.cjs.map +0 -7
- package/dist/lib/node/intent-resolver-ICHHI6I6.cjs.map +0 -7
- package/dist/lib/node/react-surface-JSCCIZS5.cjs.map +0 -7
- package/dist/lib/node/spaces-ready-FQNAKR7G.cjs.map +0 -7
- package/dist/lib/node/state-57UE3DYE.cjs.map +0 -7
- package/dist/lib/node-esm/app-graph-builder-TERVM2SL.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-2TQ2AJEZ.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-6RSVVEPS.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-HJCEJNW3.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-ICCM4YRJ.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-PGH5L7MV.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-TRNZQEEN.mjs.map +0 -7
- package/dist/lib/node-esm/intent-resolver-VR42K5GE.mjs.map +0 -7
- package/dist/lib/node-esm/react-surface-Z3BBQ5HX.mjs.map +0 -7
- package/dist/lib/node-esm/spaces-ready-HKAQG5SA.mjs.map +0 -7
- package/dist/lib/node-esm/state-VYA6OFHD.mjs.map +0 -7
- package/dist/types/src/components/AdvancedObjectSettings/AdvancedObjectSettings.d.ts.map +0 -1
- package/dist/types/src/components/AdvancedObjectSettings/ForeignKeys.d.ts.map +0 -1
- package/dist/types/src/components/AdvancedObjectSettings/index.d.ts +0 -2
- package/dist/types/src/components/AdvancedObjectSettings/index.d.ts.map +0 -1
- package/dist/types/src/components/BaseObjectSettings.d.ts +0 -6
- package/dist/types/src/components/BaseObjectSettings.d.ts.map +0 -1
- package/dist/types/src/components/SpaceSettings/SpaceSettingsDialog.d.ts +0 -10
- package/dist/types/src/components/SpaceSettings/SpaceSettingsDialog.d.ts.map +0 -1
- package/dist/types/src/components/SpaceSettings/SpaceSettingsDialog.stories.d.ts +0 -7
- package/dist/types/src/components/SpaceSettings/SpaceSettingsDialog.stories.d.ts.map +0 -1
- package/dist/types/src/components/SpaceSettings/SpaceSettingsPanel.d.ts +0 -6
- package/dist/types/src/components/SpaceSettings/SpaceSettingsPanel.d.ts.map +0 -1
- package/dist/types/src/components/SpaceSettings/SpaceSettingsPanel.stories.d.ts +0 -7
- package/dist/types/src/components/SpaceSettings/SpaceSettingsPanel.stories.d.ts.map +0 -1
- package/src/components/AdvancedObjectSettings/index.ts +0 -5
- package/src/components/BaseObjectSettings.tsx +0 -40
- package/src/components/SpaceSettings/SpaceSettingsDialog.stories.tsx +0 -43
- package/src/components/SpaceSettings/SpaceSettingsDialog.tsx +0 -120
- package/src/components/SpaceSettings/SpaceSettingsPanel.tsx +0 -83
- /package/dist/lib/browser/{identity-created-FYGS6TBH.mjs.map → identity-created-JR7BNXFH.mjs.map} +0 -0
- /package/dist/lib/browser/{react-root-4CCSD7TZ.mjs.map → react-root-VPSIJ6EU.mjs.map} +0 -0
- /package/dist/lib/browser/{schema-5W3DSY2E.mjs.map → schema-FHTA26SW.mjs.map} +0 -0
- /package/dist/lib/browser/{settings-PHPCXX33.mjs.map → settings-PJPTJUPE.mjs.map} +0 -0
- /package/dist/lib/node/{identity-created-AXI64BLE.cjs.map → identity-created-XU4HFV2T.cjs.map} +0 -0
- /package/dist/lib/node/{react-root-TCBTUOOJ.cjs.map → react-root-ZRFHMM7R.cjs.map} +0 -0
- /package/dist/lib/node/{schema-YN7WVFRX.cjs.map → schema-PPJ5BZ3A.cjs.map} +0 -0
- /package/dist/lib/node/{settings-5QYFWNH7.cjs.map → settings-WVFP2UEP.cjs.map} +0 -0
- /package/dist/lib/node-esm/{identity-created-3CGEXNPO.mjs.map → identity-created-WJKAS2PV.mjs.map} +0 -0
- /package/dist/lib/node-esm/{react-root-THJBSTQS.mjs.map → react-root-XPRWMZGT.mjs.map} +0 -0
- /package/dist/lib/node-esm/{schema-LOR2EVGY.mjs.map → schema-OUZKVYM5.mjs.map} +0 -0
- /package/dist/lib/node-esm/{settings-H6MXTEQM.mjs.map → settings-FJZPC2TV.mjs.map} +0 -0
- /package/src/components/{AdvancedObjectSettings → ObjectSettingsContainer}/ForeignKeys.tsx +0 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, it, expect } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import { S } from '@dxos/echo-schema';
|
|
8
|
+
|
|
9
|
+
import { TypeNameSchema } from './schema-tools';
|
|
10
|
+
|
|
11
|
+
describe('TypeNameSchema format', () => {
|
|
12
|
+
const valid = [
|
|
13
|
+
'example.com/usCities',
|
|
14
|
+
'dxos.org/Contact',
|
|
15
|
+
'dxos.org/Table',
|
|
16
|
+
'dxos.org/Table/Contact',
|
|
17
|
+
'dxos.org/PluginName/TypeName',
|
|
18
|
+
// Case variations
|
|
19
|
+
'DXOS.org/Table',
|
|
20
|
+
'dxos.ORG/table',
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
const invalid = [
|
|
24
|
+
'http://dxos.org/Table', // No protocol allowed
|
|
25
|
+
'dxos.org/', // Must have type path
|
|
26
|
+
// TODO(dmaretskyi): Decide if we want to ban numbers.
|
|
27
|
+
// 'dxos.org/1Type', // Path segments must start with letter
|
|
28
|
+
'dxos.org/Type!', // Invalid character
|
|
29
|
+
'.org/Type', // Must have domain
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
const validate = S.validateSync(TypeNameSchema);
|
|
33
|
+
|
|
34
|
+
valid.forEach((typename) => {
|
|
35
|
+
it(`should accept valid typename: ${typename}`, () => {
|
|
36
|
+
expect(() => validate(typename)).not.toThrow();
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
invalid.forEach((typename) => {
|
|
41
|
+
it(`should reject invalid typename: ${typename}`, () => {
|
|
42
|
+
expect(() => validate(typename)).toThrow();
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
});
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { DescriptionAnnotationId, ExamplesAnnotationId, TitleAnnotationId } from 'effect/SchemaAST';
|
|
6
|
+
|
|
7
|
+
import { Capabilities, contributes, type PromiseIntentDispatcher } from '@dxos/app-framework';
|
|
8
|
+
import { defineTool, ToolResult } from '@dxos/artifact';
|
|
9
|
+
import { type Space } from '@dxos/client/echo';
|
|
10
|
+
import { FormatEnum, FormatEnums, S, SelectOptionSchema, GeoPoint, toJsonSchema } from '@dxos/echo-schema';
|
|
11
|
+
import { invariant } from '@dxos/invariant';
|
|
12
|
+
import { hues } from '@dxos/react-ui-theme';
|
|
13
|
+
import { getSchemaFromPropertyDefinitions } from '@dxos/schema';
|
|
14
|
+
|
|
15
|
+
// TODO(burdon): Factor out.
|
|
16
|
+
declare global {
|
|
17
|
+
interface ToolContextExtensions {
|
|
18
|
+
space?: Space;
|
|
19
|
+
dispatch?: PromiseIntentDispatcher;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// TODO(ZaymonFC): Move this somewhere common.
|
|
24
|
+
export const TypeNameSchema = S.String.pipe(
|
|
25
|
+
S.pattern(/^\w+\.\w{2,}\/[\w/]+$/i),
|
|
26
|
+
S.annotations({
|
|
27
|
+
[TitleAnnotationId]: 'TypeName',
|
|
28
|
+
[DescriptionAnnotationId]:
|
|
29
|
+
'Domain-style type name path. Dashes are not allowed. Use camel case for the final component of the type name.',
|
|
30
|
+
[ExamplesAnnotationId]: ['example.com/type/Document', 'example.com/type/FlightList'],
|
|
31
|
+
}),
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const formatDescription = `The format of the property. Additional information:
|
|
35
|
+
${FormatEnum.GeoPoint}: ${JSON.stringify(toJsonSchema(GeoPoint))}
|
|
36
|
+
This tuple is GeoJSON. You must specify \`${FormatEnum.GeoPoint}\` as [Longitude, Latitude]`;
|
|
37
|
+
|
|
38
|
+
// TODO(ZaymonFC): All properties are default optional, but maybe we should allow for required properties.
|
|
39
|
+
const PropertyDefinitionSchema = S.Struct({
|
|
40
|
+
name: S.String.annotations({ [DescriptionAnnotationId]: 'The name of the property.' }),
|
|
41
|
+
format: S.Union(...FormatEnums.map((format) => S.Literal(format))).annotations({
|
|
42
|
+
[DescriptionAnnotationId]: formatDescription,
|
|
43
|
+
}),
|
|
44
|
+
config: S.optional(
|
|
45
|
+
S.Struct({
|
|
46
|
+
options: S.optional(
|
|
47
|
+
S.Array(SelectOptionSchema)
|
|
48
|
+
.annotations({
|
|
49
|
+
description: `Options for SingleSelect/MultiSelect formats. Available colors: ${hues.join(', ')}`,
|
|
50
|
+
})
|
|
51
|
+
.pipe(S.mutable),
|
|
52
|
+
),
|
|
53
|
+
}),
|
|
54
|
+
),
|
|
55
|
+
}).pipe(S.mutable);
|
|
56
|
+
|
|
57
|
+
const SYSTEM_NAMESPACE = 'dxos.org/echo/schema';
|
|
58
|
+
|
|
59
|
+
export default () =>
|
|
60
|
+
contributes(Capabilities.Tools, [
|
|
61
|
+
defineTool(SYSTEM_NAMESPACE, {
|
|
62
|
+
name: 'list',
|
|
63
|
+
description: 'List registered schemas in the space.',
|
|
64
|
+
caption: 'Listing registered schemas...',
|
|
65
|
+
schema: S.Struct({}),
|
|
66
|
+
execute: async (_input, { extensions }) => {
|
|
67
|
+
invariant(extensions?.space, 'No space.');
|
|
68
|
+
const space = extensions.space;
|
|
69
|
+
|
|
70
|
+
const schemas = await space.db.schemaRegistry.query({}).run();
|
|
71
|
+
return ToolResult.Success(
|
|
72
|
+
schemas.map((schema) => ({
|
|
73
|
+
typename: schema.typename,
|
|
74
|
+
version: schema.version,
|
|
75
|
+
})),
|
|
76
|
+
);
|
|
77
|
+
},
|
|
78
|
+
}),
|
|
79
|
+
defineTool(SYSTEM_NAMESPACE, {
|
|
80
|
+
name: 'get',
|
|
81
|
+
description: 'Get a specific schema by its typename.',
|
|
82
|
+
caption: 'Getting schema...',
|
|
83
|
+
schema: S.Struct({
|
|
84
|
+
typename: S.String.annotations({
|
|
85
|
+
description: 'The fully qualified typename of the schema.',
|
|
86
|
+
}),
|
|
87
|
+
}),
|
|
88
|
+
execute: async ({ typename }, { extensions }) => {
|
|
89
|
+
invariant(extensions?.space, 'No space.');
|
|
90
|
+
const space = extensions.space;
|
|
91
|
+
|
|
92
|
+
const schema = await space.db.schemaRegistry.query({ typename }).firstOrUndefined();
|
|
93
|
+
if (!schema) {
|
|
94
|
+
return ToolResult.Error(`Schema not found: ${typename}`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return ToolResult.Success(schema);
|
|
98
|
+
},
|
|
99
|
+
}),
|
|
100
|
+
defineTool(SYSTEM_NAMESPACE, {
|
|
101
|
+
name: 'create',
|
|
102
|
+
description: 'Create a new schema with the provided definition.',
|
|
103
|
+
caption: 'Creating schema...',
|
|
104
|
+
schema: S.Struct({
|
|
105
|
+
typename: TypeNameSchema.annotations({
|
|
106
|
+
description:
|
|
107
|
+
'The fully qualified schema typename. Must start with a domain, and then one or more path components (e.g., "example.com/type/TypeName").',
|
|
108
|
+
}),
|
|
109
|
+
properties: S.Array(PropertyDefinitionSchema).pipe(
|
|
110
|
+
S.annotations({ description: 'Array of property definitions for the schema.' }),
|
|
111
|
+
S.mutable,
|
|
112
|
+
),
|
|
113
|
+
}),
|
|
114
|
+
execute: async ({ typename, properties }, { extensions }) => {
|
|
115
|
+
invariant(extensions?.space, 'No space.');
|
|
116
|
+
const space = extensions.space;
|
|
117
|
+
|
|
118
|
+
const schema = getSchemaFromPropertyDefinitions(typename, properties);
|
|
119
|
+
const [registeredSchema] = await space.db.schemaRegistry.register([schema]);
|
|
120
|
+
|
|
121
|
+
return ToolResult.Success(registeredSchema);
|
|
122
|
+
},
|
|
123
|
+
}),
|
|
124
|
+
]);
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { contributes, createIntent, type PluginsContext, Capabilities, LayoutAction } from '@dxos/app-framework';
|
|
6
|
-
import {
|
|
6
|
+
import { SubscriptionList } from '@dxos/async';
|
|
7
7
|
import { Expando } from '@dxos/echo-schema';
|
|
8
8
|
import { scheduledEffect } from '@dxos/echo-signals/core';
|
|
9
9
|
import { create } from '@dxos/live-object';
|
|
@@ -24,8 +24,8 @@ const ACTIVE_NODE_BROADCAST_INTERVAL = 30_000;
|
|
|
24
24
|
const WAIT_FOR_OBJECT_TIMEOUT = 1000;
|
|
25
25
|
|
|
26
26
|
export default async (context: PluginsContext) => {
|
|
27
|
-
const subscriptions = new
|
|
28
|
-
const spaceSubscriptions = new
|
|
27
|
+
const subscriptions = new SubscriptionList();
|
|
28
|
+
const spaceSubscriptions = new SubscriptionList();
|
|
29
29
|
|
|
30
30
|
const { dispatchPromise: dispatch } = context.requestCapability(Capabilities.IntentDispatcher);
|
|
31
31
|
const { graph } = context.requestCapability(Capabilities.AppGraph);
|
|
@@ -14,9 +14,11 @@ import { SPACE_PLUGIN } from '../meta';
|
|
|
14
14
|
import { type PluginState } from '../types';
|
|
15
15
|
|
|
16
16
|
export default (context: PluginsContext) => {
|
|
17
|
+
const sections = context.requestCapabilities(SpaceCapabilities.SettingsSection);
|
|
17
18
|
const state = new LocalStorageStore<PluginState>(SPACE_PLUGIN, {
|
|
18
19
|
awaiting: undefined,
|
|
19
20
|
spaceNames: {},
|
|
21
|
+
spaceSettingsOpenSections: sections.map((section) => section.id),
|
|
20
22
|
viewersByObject: {},
|
|
21
23
|
// TODO(wittjosiah): Stop using (Complex)Map inside reactive object.
|
|
22
24
|
viewersByIdentity: new ComplexMap(PublicKey.hash),
|
|
@@ -22,7 +22,7 @@ import { Button, Dialog, Icon, useTranslation } from '@dxos/react-ui';
|
|
|
22
22
|
import { CreateObjectPanel, type CreateObjectPanelProps } from './CreateObjectPanel';
|
|
23
23
|
import { SpaceCapabilities } from '../../capabilities';
|
|
24
24
|
import { SPACE_PLUGIN } from '../../meta';
|
|
25
|
-
import {
|
|
25
|
+
import { type ObjectForm, SpaceAction } from '../../types';
|
|
26
26
|
|
|
27
27
|
export const CREATE_OBJECT_DIALOG = `${SPACE_PLUGIN}/CreateObjectDialog`;
|
|
28
28
|
|
|
@@ -53,16 +53,13 @@ export const CreateObjectDialog = ({
|
|
|
53
53
|
const handleCreateObject = useCallback(
|
|
54
54
|
async ({
|
|
55
55
|
form,
|
|
56
|
-
target
|
|
56
|
+
target,
|
|
57
57
|
data = {},
|
|
58
58
|
}: {
|
|
59
59
|
form: ObjectForm;
|
|
60
60
|
target: CreateObjectPanelProps['target'];
|
|
61
61
|
data?: Record<string, any>;
|
|
62
62
|
}) => {
|
|
63
|
-
const target = isSpace(_target)
|
|
64
|
-
? (_target.properties[CollectionType.typename]?.target as CollectionType | undefined)
|
|
65
|
-
: _target;
|
|
66
63
|
if (!target) {
|
|
67
64
|
// TODO(wittjosiah): UI feedback.
|
|
68
65
|
return;
|
|
@@ -76,7 +73,7 @@ export const CreateObjectDialog = ({
|
|
|
76
73
|
const result = await dispatch(form.getIntent(data, { space }));
|
|
77
74
|
const object = result.data?.object;
|
|
78
75
|
if (isReactiveObject(object)) {
|
|
79
|
-
const addObjectIntent = createIntent(SpaceAction.AddObject, { target, object });
|
|
76
|
+
const addObjectIntent = createIntent(SpaceAction.AddObject, { target, object, hidden: form.hidden });
|
|
80
77
|
const shouldNavigate = _shouldNavigate ?? (() => true);
|
|
81
78
|
if (shouldNavigate(object)) {
|
|
82
79
|
await dispatch(pipe(addObjectIntent, chain(LayoutAction.Open, { part: 'main' })));
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import React, { useCallback, useState } from 'react';
|
|
6
6
|
|
|
7
7
|
import { Surface, isSurfaceAvailable, usePluginManager } from '@dxos/app-framework';
|
|
8
|
-
import {
|
|
8
|
+
import { getTypeAnnotation, type TypeAnnotation, type S } from '@dxos/echo-schema';
|
|
9
9
|
import { invariant } from '@dxos/invariant';
|
|
10
10
|
import { type SpaceId, type Space } from '@dxos/react-client/echo';
|
|
11
11
|
import { Icon, type ThemedClassName, toLocalizedString, useTranslation } from '@dxos/react-ui';
|
|
@@ -69,9 +69,9 @@ export const CreateObjectPanel = ({
|
|
|
69
69
|
const { t } = useTranslation(SPACE_PLUGIN);
|
|
70
70
|
const [typename, setTypename] = useState<string | undefined>(initialTypename);
|
|
71
71
|
const [target, setTarget] = useState<Space | CollectionType | undefined>(initialTarget);
|
|
72
|
-
const form = forms.find((form) =>
|
|
73
|
-
const options:
|
|
74
|
-
.map((form) =>
|
|
72
|
+
const form = forms.find((form) => getTypeAnnotation(form.objectSchema)?.typename === typename);
|
|
73
|
+
const options: TypeAnnotation[] = forms
|
|
74
|
+
.map((form) => getTypeAnnotation(form.objectSchema))
|
|
75
75
|
.filter(isNonNullable)
|
|
76
76
|
.sort((a, b) => {
|
|
77
77
|
const nameA = t('typename label', { ns: a.typename, defaultValue: a.typename });
|
|
@@ -92,7 +92,7 @@ export const CreateObjectPanel = ({
|
|
|
92
92
|
const handleSetTypename = useCallback(
|
|
93
93
|
async (typename: string) => {
|
|
94
94
|
invariant(target, 'target is required');
|
|
95
|
-
const form = forms.find((form) =>
|
|
95
|
+
const form = forms.find((form) => getTypeAnnotation(form.objectSchema)?.typename === typename);
|
|
96
96
|
if (form && !form.formSchema) {
|
|
97
97
|
await onCreateObject?.({ form, target });
|
|
98
98
|
} else {
|
|
@@ -170,7 +170,7 @@ const SelectSchema = ({
|
|
|
170
170
|
resolve,
|
|
171
171
|
onChange,
|
|
172
172
|
}: {
|
|
173
|
-
options:
|
|
173
|
+
options: TypeAnnotation[];
|
|
174
174
|
onChange: (type: string) => void;
|
|
175
175
|
} & Pick<CreateObjectPanelProps, 'resolve'>) => {
|
|
176
176
|
const { t } = useTranslation(SPACE_PLUGIN);
|
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
import React, { useCallback } from 'react';
|
|
6
6
|
|
|
7
7
|
import { createIntent, LayoutAction, useAppGraph, useIntentDispatcher } from '@dxos/app-framework';
|
|
8
|
-
import {
|
|
8
|
+
import { Trigger } from '@dxos/async';
|
|
9
9
|
import { ObservabilityAction } from '@dxos/plugin-observability/types';
|
|
10
10
|
import { useClient } from '@dxos/react-client';
|
|
11
|
+
import { type Space } from '@dxos/react-client/echo';
|
|
11
12
|
import { type InvitationResult } from '@dxos/react-client/invitations';
|
|
12
13
|
import { Dialog, useTranslation } from '@dxos/react-ui';
|
|
13
14
|
import { JoinPanel, type JoinPanelProps } from '@dxos/shell/react';
|
|
@@ -28,34 +29,44 @@ export const JoinDialog = ({ navigableCollections, onDone, ...props }: JoinDialo
|
|
|
28
29
|
|
|
29
30
|
const handleDone = useCallback(
|
|
30
31
|
async (result: InvitationResult | null) => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
createIntent(LayoutAction.AddToast, {
|
|
35
|
-
part: 'toast',
|
|
36
|
-
subject: {
|
|
37
|
-
id: `${SPACE_PLUGIN}/join-success`,
|
|
38
|
-
duration: 5_000,
|
|
39
|
-
title: ['join success label', { ns: SPACE_PLUGIN }],
|
|
40
|
-
closeLabel: ['dismiss label', { ns: SPACE_PLUGIN }],
|
|
41
|
-
},
|
|
42
|
-
}),
|
|
43
|
-
),
|
|
44
|
-
dispatch(
|
|
45
|
-
createIntent(LayoutAction.UpdateDialog, {
|
|
46
|
-
part: 'dialog',
|
|
47
|
-
options: {
|
|
48
|
-
state: false,
|
|
49
|
-
},
|
|
50
|
-
}),
|
|
51
|
-
),
|
|
52
|
-
]);
|
|
32
|
+
const spaceKey = result?.spaceKey;
|
|
33
|
+
if (!spaceKey) {
|
|
34
|
+
return;
|
|
53
35
|
}
|
|
54
36
|
|
|
55
|
-
|
|
37
|
+
await Promise.all([
|
|
38
|
+
dispatch(
|
|
39
|
+
createIntent(LayoutAction.AddToast, {
|
|
40
|
+
part: 'toast',
|
|
41
|
+
subject: {
|
|
42
|
+
id: `${SPACE_PLUGIN}/join-success`,
|
|
43
|
+
duration: 5_000,
|
|
44
|
+
title: ['join success label', { ns: SPACE_PLUGIN }],
|
|
45
|
+
closeLabel: ['dismiss label', { ns: SPACE_PLUGIN }],
|
|
46
|
+
},
|
|
47
|
+
}),
|
|
48
|
+
),
|
|
49
|
+
dispatch(
|
|
50
|
+
createIntent(LayoutAction.UpdateDialog, {
|
|
51
|
+
part: 'dialog',
|
|
52
|
+
options: {
|
|
53
|
+
state: false,
|
|
54
|
+
},
|
|
55
|
+
}),
|
|
56
|
+
),
|
|
57
|
+
]);
|
|
58
|
+
|
|
59
|
+
let space = client.spaces.get(spaceKey);
|
|
56
60
|
if (!space) {
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
// TODO(wittjosiah): Add api to wait for a space.
|
|
62
|
+
const trigger = new Trigger<Space>();
|
|
63
|
+
client.spaces.subscribe(() => {
|
|
64
|
+
const space = client.spaces.get(spaceKey);
|
|
65
|
+
if (space) {
|
|
66
|
+
trigger.wake(space);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
space = await trigger.wait();
|
|
59
70
|
}
|
|
60
71
|
|
|
61
72
|
await dispatch(createIntent(LayoutAction.SwitchWorkspace, { part: 'workspace', subject: space.id }));
|
|
@@ -78,7 +89,12 @@ export const JoinDialog = ({ navigableCollections, onDone, ...props }: JoinDialo
|
|
|
78
89
|
|
|
79
90
|
if (space) {
|
|
80
91
|
await dispatch(
|
|
81
|
-
createIntent(ObservabilityAction.SendEvent, {
|
|
92
|
+
createIntent(ObservabilityAction.SendEvent, {
|
|
93
|
+
name: 'space.join',
|
|
94
|
+
properties: {
|
|
95
|
+
spaceId: space.id,
|
|
96
|
+
},
|
|
97
|
+
}),
|
|
82
98
|
);
|
|
83
99
|
}
|
|
84
100
|
},
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import '@dxos-theme';
|
|
6
|
+
|
|
7
|
+
import { type StoryObj, type Meta } from '@storybook/react';
|
|
8
|
+
|
|
9
|
+
import { withClientProvider } from '@dxos/react-client/testing';
|
|
10
|
+
import { osTranslations } from '@dxos/shell/react';
|
|
11
|
+
import { withTheme, withLayout } from '@dxos/storybook-utils';
|
|
12
|
+
|
|
13
|
+
import { MembersContainer } from './MembersContainer';
|
|
14
|
+
import translations from '../translations';
|
|
15
|
+
|
|
16
|
+
const meta: Meta = {
|
|
17
|
+
title: 'plugins/plugin-space/MembersContainer',
|
|
18
|
+
component: MembersContainer,
|
|
19
|
+
decorators: [
|
|
20
|
+
withClientProvider({ createIdentity: true, createSpace: true }),
|
|
21
|
+
withTheme,
|
|
22
|
+
withLayout({ tooltips: true }),
|
|
23
|
+
],
|
|
24
|
+
parameters: {
|
|
25
|
+
layout: 'fullscreen',
|
|
26
|
+
translations: [...translations, osTranslations],
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default meta;
|
|
31
|
+
|
|
32
|
+
type Story = StoryObj<typeof MembersContainer>;
|
|
33
|
+
|
|
34
|
+
export const Default: Story = {};
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Check, X } from '@phosphor-icons/react';
|
|
6
|
+
import React, { type Dispatch, type SetStateAction, useMemo, useState } from 'react';
|
|
7
|
+
import { QR } from 'react-qr-rounded';
|
|
8
|
+
|
|
9
|
+
import { log } from '@dxos/log';
|
|
10
|
+
import { useConfig } from '@dxos/react-client';
|
|
11
|
+
import { fullyQualifiedId, useSpaceInvitations, type Space } from '@dxos/react-client/echo';
|
|
12
|
+
import { type CancellableInvitationObservable, Invitation, InvitationEncoder } from '@dxos/react-client/invitations';
|
|
13
|
+
import { Button, Clipboard, Icon, useId, useTranslation } from '@dxos/react-ui';
|
|
14
|
+
import { ControlSection, ControlFrame, ControlFrameItem } from '@dxos/react-ui-form';
|
|
15
|
+
import { StackItem } from '@dxos/react-ui-stack';
|
|
16
|
+
import { getSize, mx } from '@dxos/react-ui-theme';
|
|
17
|
+
import {
|
|
18
|
+
type ActionMenuItem,
|
|
19
|
+
AuthCode,
|
|
20
|
+
BifurcatedAction,
|
|
21
|
+
Centered,
|
|
22
|
+
Emoji,
|
|
23
|
+
InvitationList,
|
|
24
|
+
SpaceMemberList,
|
|
25
|
+
Viewport,
|
|
26
|
+
} from '@dxos/shell/react';
|
|
27
|
+
import { hexToEmoji } from '@dxos/util';
|
|
28
|
+
|
|
29
|
+
import { SPACE_PLUGIN } from '../meta';
|
|
30
|
+
import { CollectionType } from '../types';
|
|
31
|
+
|
|
32
|
+
// TODO(wittjosiah): Copied from Shell.
|
|
33
|
+
const activeActionKey = 'dxos:react-shell/space-manager/active-action';
|
|
34
|
+
|
|
35
|
+
const handleInvitationEvent = (invitation: Invitation, subscription: ZenObservable.Subscription) => {
|
|
36
|
+
const invitationCode = InvitationEncoder.encode(invitation);
|
|
37
|
+
if (invitation.state === Invitation.State.CONNECTING) {
|
|
38
|
+
log.info(JSON.stringify({ invitationCode, authCode: invitation.authCode }));
|
|
39
|
+
subscription.unsubscribe();
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const MembersContainer = ({
|
|
44
|
+
space,
|
|
45
|
+
createInvitationUrl,
|
|
46
|
+
}: {
|
|
47
|
+
space: Space;
|
|
48
|
+
createInvitationUrl: (invitationCode: string) => string;
|
|
49
|
+
}) => {
|
|
50
|
+
const { t } = useTranslation('os');
|
|
51
|
+
const config = useConfig();
|
|
52
|
+
const invitations = useSpaceInvitations(space.key);
|
|
53
|
+
const visibleInvitations = invitations?.filter(
|
|
54
|
+
(invitation) => ![Invitation.State.CANCELLED].includes(invitation.get().state),
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const [activeAction, setInternalActiveAction] = useState(localStorage.getItem(activeActionKey) ?? 'inviteMany');
|
|
58
|
+
|
|
59
|
+
const setActiveAction = (nextAction: string) => {
|
|
60
|
+
setInternalActiveAction(nextAction);
|
|
61
|
+
localStorage.setItem(activeActionKey, nextAction);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// TODO(wittjosiah): Track which was the most recently viewed object.
|
|
65
|
+
const target = space.properties[CollectionType.typename]?.target?.objects[0]?.target;
|
|
66
|
+
|
|
67
|
+
const inviteActions = useMemo(
|
|
68
|
+
(): Record<string, ActionMenuItem> => ({
|
|
69
|
+
inviteOne: {
|
|
70
|
+
label: t('invite one label'),
|
|
71
|
+
description: t('invite one description'),
|
|
72
|
+
icon: () => <Icon icon='ph--user-plus--regular' size={5} />,
|
|
73
|
+
testId: 'membersContainer.inviteOne',
|
|
74
|
+
onClick: () => {
|
|
75
|
+
const invitation = space.share?.({
|
|
76
|
+
type: Invitation.Type.INTERACTIVE,
|
|
77
|
+
authMethod: Invitation.AuthMethod.SHARED_SECRET,
|
|
78
|
+
multiUse: false,
|
|
79
|
+
target: target && fullyQualifiedId(target),
|
|
80
|
+
});
|
|
81
|
+
if (invitation && config.values.runtime?.app?.env?.DX_ENVIRONMENT !== 'production') {
|
|
82
|
+
const subscription: ZenObservable.Subscription = invitation.subscribe((invitation) =>
|
|
83
|
+
handleInvitationEvent(invitation, subscription),
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
inviteMany: {
|
|
89
|
+
label: t('invite many label'),
|
|
90
|
+
description: t('invite many description'),
|
|
91
|
+
icon: () => <Icon icon='ph--users-three--regular' size={5} />,
|
|
92
|
+
testId: 'membersContainer.inviteMany',
|
|
93
|
+
onClick: () => {
|
|
94
|
+
const invitation = space.share?.({
|
|
95
|
+
type: Invitation.Type.DELEGATED,
|
|
96
|
+
authMethod: Invitation.AuthMethod.KNOWN_PUBLIC_KEY,
|
|
97
|
+
multiUse: true,
|
|
98
|
+
target: target && fullyQualifiedId(target),
|
|
99
|
+
});
|
|
100
|
+
if (invitation && config.values.runtime?.app?.env?.DX_ENVIRONMENT !== 'production') {
|
|
101
|
+
const subscription: ZenObservable.Subscription = invitation.subscribe((invitation) =>
|
|
102
|
+
handleInvitationEvent(invitation, subscription),
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
}),
|
|
108
|
+
[t, space, target],
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
const [selectedInvitation, setSelectedInvitation] = useState<CancellableInvitationObservable | null>(null);
|
|
112
|
+
const handleSend = (event: { type: 'selectInvitation'; invitation: CancellableInvitationObservable }) => {
|
|
113
|
+
setSelectedInvitation(event.invitation);
|
|
114
|
+
};
|
|
115
|
+
const handleBack = () => {
|
|
116
|
+
setSelectedInvitation(null);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<StackItem.Content classNames='p-2 block overflow-y-auto'>
|
|
121
|
+
<ControlSection
|
|
122
|
+
title={t('members verbose label', { ns: SPACE_PLUGIN })}
|
|
123
|
+
description={t('members description', { ns: SPACE_PLUGIN })}
|
|
124
|
+
>
|
|
125
|
+
<ControlFrame>
|
|
126
|
+
<ControlFrameItem title={t('members label', { ns: SPACE_PLUGIN })}>
|
|
127
|
+
<SpaceMemberList spaceKey={space.key} includeSelf />
|
|
128
|
+
</ControlFrameItem>
|
|
129
|
+
<ControlFrameItem title={t('invitations label', { ns: SPACE_PLUGIN })}>
|
|
130
|
+
{selectedInvitation && <InvitationSection {...selectedInvitation} onBack={handleBack} />}
|
|
131
|
+
{!selectedInvitation && (
|
|
132
|
+
<>
|
|
133
|
+
<p className='text-description mbe-2'>{t('space invitation description', { ns: SPACE_PLUGIN })}</p>
|
|
134
|
+
<InvitationList
|
|
135
|
+
className='mb-2'
|
|
136
|
+
send={handleSend}
|
|
137
|
+
invitations={visibleInvitations ?? []}
|
|
138
|
+
onClickRemove={(invitation) => invitation.cancel()}
|
|
139
|
+
createInvitationUrl={createInvitationUrl}
|
|
140
|
+
/>
|
|
141
|
+
<BifurcatedAction
|
|
142
|
+
actions={inviteActions}
|
|
143
|
+
activeAction={activeAction}
|
|
144
|
+
onChangeActiveAction={setActiveAction as Dispatch<SetStateAction<string>>}
|
|
145
|
+
data-testid='membersContainer.createInvitation'
|
|
146
|
+
/>
|
|
147
|
+
</>
|
|
148
|
+
)}
|
|
149
|
+
</ControlFrameItem>
|
|
150
|
+
</ControlFrame>
|
|
151
|
+
</ControlSection>
|
|
152
|
+
</StackItem.Content>
|
|
153
|
+
);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
// TODO(wittjosiah): Reconcile the below components with DevicesContainer in @dxos/plugin-client.
|
|
157
|
+
|
|
158
|
+
type InvitationComponentProps = Partial<
|
|
159
|
+
Pick<Invitation, 'authCode' | 'invitationId'> & {
|
|
160
|
+
state: Invitation.State;
|
|
161
|
+
url: string;
|
|
162
|
+
onBack: () => void;
|
|
163
|
+
}
|
|
164
|
+
>;
|
|
165
|
+
|
|
166
|
+
const InvitationSection = ({
|
|
167
|
+
state = Invitation.State.INIT,
|
|
168
|
+
authCode,
|
|
169
|
+
invitationId = 'never',
|
|
170
|
+
url = 'never',
|
|
171
|
+
onBack,
|
|
172
|
+
}: InvitationComponentProps) => {
|
|
173
|
+
const activeView =
|
|
174
|
+
state < 0
|
|
175
|
+
? 'init'
|
|
176
|
+
: state >= Invitation.State.CANCELLED
|
|
177
|
+
? 'complete'
|
|
178
|
+
: state >= Invitation.State.READY_FOR_AUTHENTICATION && authCode
|
|
179
|
+
? 'auth-code'
|
|
180
|
+
: 'qr-code';
|
|
181
|
+
return (
|
|
182
|
+
<Viewport.Root activeView={activeView}>
|
|
183
|
+
<Viewport.Views>
|
|
184
|
+
<Viewport.View id='init'>
|
|
185
|
+
{/* This view intentionally left blank while conditionally rendering the viewport. */}
|
|
186
|
+
</Viewport.View>
|
|
187
|
+
<Viewport.View id='complete'>
|
|
188
|
+
<InvitationComplete statusValue={state} />
|
|
189
|
+
</Viewport.View>
|
|
190
|
+
<Viewport.View id='auth-code'>
|
|
191
|
+
<InvitationAuthCode id={invitationId} code={authCode ?? 'never'} onCancel={onBack} />
|
|
192
|
+
</Viewport.View>
|
|
193
|
+
<Viewport.View id='qr-code'>
|
|
194
|
+
<InvitationQR id={invitationId} url={url} onCancel={onBack} />
|
|
195
|
+
</Viewport.View>
|
|
196
|
+
</Viewport.Views>
|
|
197
|
+
</Viewport.Root>
|
|
198
|
+
);
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const InvitationQR = ({ id, url, onCancel }: { id: string; url: string; onCancel?: () => void }) => {
|
|
202
|
+
const { t } = useTranslation('os');
|
|
203
|
+
const qrLabel = useId('members-container__qr-code');
|
|
204
|
+
const emoji = hexToEmoji(id);
|
|
205
|
+
return (
|
|
206
|
+
<Clipboard.Provider>
|
|
207
|
+
<p className='text-description'>{t('qr code description', { ns: SPACE_PLUGIN })}</p>
|
|
208
|
+
<div role='group' className='grid grid-cols-[1fr_min-content] mlb-2 gap-2'>
|
|
209
|
+
<div role='none' className='is-full aspect-square relative text-description'>
|
|
210
|
+
<QR
|
|
211
|
+
rounding={100}
|
|
212
|
+
backgroundColor='transparent'
|
|
213
|
+
color='currentColor'
|
|
214
|
+
aria-labelledby={qrLabel}
|
|
215
|
+
errorCorrectionLevel='Q'
|
|
216
|
+
cutout={true}
|
|
217
|
+
>
|
|
218
|
+
{url ?? 'never'}
|
|
219
|
+
</QR>
|
|
220
|
+
<Centered>
|
|
221
|
+
<Emoji text={emoji} />
|
|
222
|
+
</Centered>
|
|
223
|
+
</div>
|
|
224
|
+
<span id={qrLabel} className='sr-only'>
|
|
225
|
+
{t('qr label')}
|
|
226
|
+
</span>
|
|
227
|
+
<Clipboard.Button value={url ?? 'never'} />
|
|
228
|
+
</div>
|
|
229
|
+
<Button variant='ghost' onClick={onCancel}>
|
|
230
|
+
{t('cancel label')}
|
|
231
|
+
</Button>
|
|
232
|
+
</Clipboard.Provider>
|
|
233
|
+
);
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const InvitationAuthCode = ({ id, code, onCancel }: { id: string; code: string; onCancel?: () => void }) => {
|
|
237
|
+
const { t } = useTranslation('os');
|
|
238
|
+
const emoji = hexToEmoji(id);
|
|
239
|
+
|
|
240
|
+
return (
|
|
241
|
+
<>
|
|
242
|
+
<p className='text-description'>{t('auth other device emoji message')}</p>
|
|
243
|
+
{emoji && <Emoji text={emoji} className='mli-auto mlb-2 text-center' />}
|
|
244
|
+
<p className='text-description'>{t('auth code message')}</p>
|
|
245
|
+
<AuthCode code={code} large classNames='mli-auto mlb-2 text-center grow' />
|
|
246
|
+
<Button variant='ghost' onClick={onCancel}>
|
|
247
|
+
{t('cancel label')}
|
|
248
|
+
</Button>
|
|
249
|
+
</>
|
|
250
|
+
);
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
const InvitationComplete = ({ statusValue }: { statusValue: number }) => {
|
|
254
|
+
return statusValue > 0 ? <Check className={mx('m-1.5', getSize(6))} /> : <X className={mx('m-1.5', getSize(6))} />;
|
|
255
|
+
};
|