@dxos/plugin-space 0.6.12-main.5cc132e → 0.6.12-main.c974201

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/lib/browser/{chunk-DTVUOG2C.mjs → chunk-WBMH5WIP.mjs} +14 -2
  2. package/dist/lib/browser/chunk-WBMH5WIP.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +400 -177
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/types/index.mjs +7 -3
  7. package/dist/lib/node/{chunk-CVZPI2P3.cjs → chunk-GF3SRAQM.cjs} +20 -6
  8. package/dist/lib/node/chunk-GF3SRAQM.cjs.map +7 -0
  9. package/dist/lib/node/index.cjs +509 -289
  10. package/dist/lib/node/index.cjs.map +4 -4
  11. package/dist/lib/node/meta.json +1 -1
  12. package/dist/lib/node/types/index.cjs +14 -10
  13. package/dist/lib/node/types/index.cjs.map +2 -2
  14. package/dist/lib/node-esm/{chunk-LZEGRS7H.mjs → chunk-GM2YUC77.mjs} +3 -1
  15. package/dist/lib/node-esm/{chunk-LZEGRS7H.mjs.map → chunk-GM2YUC77.mjs.map} +1 -1
  16. package/dist/lib/node-esm/{chunk-DTVUOG2C.mjs → chunk-N5VC55UM.mjs} +16 -2
  17. package/dist/lib/node-esm/chunk-N5VC55UM.mjs.map +7 -0
  18. package/dist/lib/node-esm/index.mjs +402 -178
  19. package/dist/lib/node-esm/index.mjs.map +4 -4
  20. package/dist/lib/node-esm/meta.json +1 -1
  21. package/dist/lib/node-esm/meta.mjs +2 -1
  22. package/dist/lib/node-esm/types/index.mjs +8 -3
  23. package/dist/types/src/SpacePlugin.d.ts.map +1 -1
  24. package/dist/types/src/components/SaveStatus.d.ts.map +1 -1
  25. package/dist/types/src/components/ShareSpaceButton.stories.d.ts +2 -0
  26. package/dist/types/src/components/ShareSpaceButton.stories.d.ts.map +1 -1
  27. package/dist/types/src/components/SpaceMain/SpaceMain.d.ts.map +1 -1
  28. package/dist/types/src/components/SpacePresence.stories.d.ts +2 -0
  29. package/dist/types/src/components/SpacePresence.stories.d.ts.map +1 -1
  30. package/dist/types/src/components/SpaceSettings.d.ts.map +1 -1
  31. package/dist/types/src/components/SyncStatus/SyncStatus.d.ts +13 -0
  32. package/dist/types/src/components/SyncStatus/SyncStatus.d.ts.map +1 -0
  33. package/dist/types/src/components/SyncStatus/SyncStatus.stories.d.ts +115 -0
  34. package/dist/types/src/components/SyncStatus/SyncStatus.stories.d.ts.map +1 -0
  35. package/dist/types/src/components/SyncStatus/index.d.ts +2 -0
  36. package/dist/types/src/components/SyncStatus/index.d.ts.map +1 -0
  37. package/dist/types/src/components/SyncStatus/types.d.ts +14 -0
  38. package/dist/types/src/components/SyncStatus/types.d.ts.map +1 -0
  39. package/dist/types/src/components/index.d.ts +1 -0
  40. package/dist/types/src/components/index.d.ts.map +1 -1
  41. package/dist/types/src/translations.d.ts +2 -0
  42. package/dist/types/src/translations.d.ts.map +1 -1
  43. package/dist/types/src/types/thread.d.ts +13 -0
  44. package/dist/types/src/types/thread.d.ts.map +1 -1
  45. package/dist/types/src/types/types.d.ts +18 -1
  46. package/dist/types/src/types/types.d.ts.map +1 -1
  47. package/dist/types/src/util.d.ts +1 -4
  48. package/dist/types/src/util.d.ts.map +1 -1
  49. package/package.json +34 -32
  50. package/src/SpacePlugin.tsx +24 -13
  51. package/src/components/SaveStatus.tsx +6 -9
  52. package/src/components/SpaceMain/SpaceMain.tsx +1 -22
  53. package/src/components/SpaceSettings.tsx +32 -3
  54. package/src/components/SyncStatus/SyncStatus.stories.tsx +62 -0
  55. package/src/components/SyncStatus/SyncStatus.tsx +188 -0
  56. package/src/components/SyncStatus/index.ts +5 -0
  57. package/src/components/SyncStatus/types.ts +77 -0
  58. package/src/components/index.ts +1 -0
  59. package/src/translations.ts +2 -0
  60. package/src/types/thread.ts +9 -0
  61. package/src/types/types.ts +25 -1
  62. package/src/util.tsx +15 -50
  63. package/dist/lib/browser/chunk-DTVUOG2C.mjs.map +0 -7
  64. package/dist/lib/node/chunk-CVZPI2P3.cjs.map +0 -7
  65. package/dist/lib/node-esm/chunk-DTVUOG2C.mjs.map +0 -7
@@ -1,7 +1,8 @@
1
- import type { GraphBuilderProvides, GraphSerializerProvides, IntentResolverProvides, MetadataRecordsProvides, SettingsProvides, SurfaceProvides, TranslationsProvides } from '@dxos/app-framework';
1
+ import type { GraphBuilderProvides, GraphSerializerProvides, IntentResolverProvides, MetadataRecordsProvides, SettingsProvides, SurfaceProvides, TranslationsProvides, Plugin } from '@dxos/app-framework';
2
2
  import { type Expando } from '@dxos/echo-schema';
3
3
  import { type SchemaProvides } from '@dxos/plugin-client';
4
4
  import { type PublicKey } from '@dxos/react-client';
5
+ import { type Label } from '@dxos/react-ui';
5
6
  import { type ComplexMap } from '@dxos/util';
6
7
  export declare const SPACE_DIRECTORY_HANDLE = "dxos.org/plugin/space/directory";
7
8
  export type ObjectViewerProps = {
@@ -32,8 +33,24 @@ export type PluginState = {
32
33
  sdkMigrationRunning: Record<string, boolean>;
33
34
  };
34
35
  export type SpaceSettingsProps = {
36
+ /**
37
+ * Show closed spaces.
38
+ */
35
39
  showHidden?: boolean;
40
+ /**
41
+ * Action to perform when a space is created.
42
+ */
43
+ onSpaceCreate?: string;
44
+ };
45
+ export type SpaceInitProvides = {
46
+ space: {
47
+ onSpaceCreate: {
48
+ label: Label;
49
+ action: string;
50
+ };
51
+ };
36
52
  };
53
+ export declare const parseSpaceInitPlugin: (plugin: Plugin) => Plugin<SpaceInitProvides> | undefined;
37
54
  export type SpacePluginProvides = SurfaceProvides & IntentResolverProvides & GraphBuilderProvides & GraphSerializerProvides & MetadataRecordsProvides & SettingsProvides<SpaceSettingsProps> & TranslationsProvides & SchemaProvides & {
38
55
  space: Readonly<PluginState>;
39
56
  };
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/types/types.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,eAAO,MAAM,sBAAsB,oCAAoC,CAAC;AAExE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE9B,MAAM,MAAM,WAAW,GAAG;IACxB;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAE5E;;OAEG;IACH,iBAAiB,EAAE,UAAU,CAAC,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;IAExD;;OAEG;IACH,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAE7B;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEnC;;OAEG;IAEH,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9C,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAE1D,MAAM,MAAM,mBAAmB,GAAG,eAAe,GAC/C,sBAAsB,GACtB,oBAAoB,GACpB,uBAAuB,GACvB,uBAAuB,GACvB,gBAAgB,CAAC,kBAAkB,CAAC,GACpC,oBAAoB,GACpB,cAAc,GAAG;IACf,KAAK,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;CAC9B,CAAC;AAIJ,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;AAElE,MAAM,WAAW,qBAAqB,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO;IAChE,SAAS,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAElD;;;OAGG;IACH,WAAW,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACvE"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/types/types.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,MAAM,EACP,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,eAAO,MAAM,sBAAsB,oCAAoC,CAAC;AAExE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE9B,MAAM,MAAM,WAAW,GAAG;IACxB;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAE5E;;OAEG;IACH,iBAAiB,EAAE,UAAU,CAAC,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;IAExD;;OAEG;IACH,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAE7B;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEnC;;OAEG;IAEH,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9C,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE;QACL,aAAa,EAAE;YACb,KAAK,EAAE,KAAK,CAAC;YACb,MAAM,EAAE,MAAM,CAAC;SAChB,CAAC;KACH,CAAC;CACH,CAAC;AAEF,eAAO,MAAM,oBAAoB,WAAY,MAAM,0CACoE,CAAC;AAExH,MAAM,MAAM,mBAAmB,GAAG,eAAe,GAC/C,sBAAsB,GACtB,oBAAoB,GACpB,uBAAuB,GACvB,uBAAuB,GACvB,gBAAgB,CAAC,kBAAkB,CAAC,GACpC,oBAAoB,GACpB,cAAc,GAAG;IACf,KAAK,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;CAC9B,CAAC;AAIJ,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;AAElE,MAAM,WAAW,qBAAqB,CAAC,CAAC,SAAS,OAAO,GAAG,OAAO;IAChE,SAAS,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAElD;;;OAGG;IACH,WAAW,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACvE"}
@@ -1,5 +1,3 @@
1
- import { type IconProps } from '@phosphor-icons/react';
2
- import React from 'react';
3
1
  import { type MetadataResolver, type IntentDispatcher } from '@dxos/app-framework';
4
2
  import { type EchoReactiveObject, type Expando } from '@dxos/echo-schema';
5
3
  import { actionGroupSymbol, type ActionData, type Graph, type Node, type NodeArg } from '@dxos/plugin-graph';
@@ -36,8 +34,7 @@ export declare const constructSpaceNode: ({ space, personal, namesCache, resolve
36
34
  ns: string;
37
35
  }];
38
36
  description: any;
39
- icon: (props: IconProps) => React.JSX.Element;
40
- iconSymbol: string;
37
+ icon: string;
41
38
  disabled: boolean;
42
39
  testId: string;
43
40
  };
@@ -1 +1 @@
1
- {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../src/util.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../src/util.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,gBAAgB,EAAoB,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACrG,OAAO,EACL,KAAK,kBAAkB,EAIvB,KAAK,OAAO,EAIb,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAGL,iBAAiB,EACjB,KAAK,UAAU,EACf,KAAK,KAAK,EACV,KAAK,IAAI,EAET,KAAK,OAAO,EAIb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAML,KAAK,IAAI,EACT,KAAK,YAAY,EAEjB,KAAK,YAAY,EACjB,KAAK,KAAK,EACX,MAAM,yBAAyB,CAAC;AAKjC,eAAO,MAAM,MAAM,iCAA2B,CAAC;AAC/C,eAAO,MAAM,UAAU,wBAAwB,CAAC;AAChD,eAAO,MAAM,mBAAmB,+BAA+B,CAAC;AAEhE,eAAO,MAAM,MAAM,kBAAkB,CAAC;AAItC;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,kBAAkB,CAAC,GAAG,CAAC,gBAC9C,KAAK,GAAG,IAAI,WACjB,YAAY,CAAC,CAAC,CAAC,YACd,YAAY,KACrB,CAAC,EAaH,CAAC;AAEF,eAAO,MAAM,mBAAmB,UACvB,KAAK,6BACmB;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,KACzF,MAAM,GAAG,CAAC,MAAM,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAQlC,CAAC;AAqFF,eAAO,MAAM,kBAAkB,8CAK5B;IACD,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,OAAO,EAAE,gBAAgB,CAAC;CAC3B;;;;;;gBAvG0B,MAAM;;;;;;;CA4HhC,CAAC;AAEF,eAAO,MAAM,0BAA0B,wBAAyB;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,gBAAgB,CAAA;CAAE,wCAkD3G,CAAC;AAEF,eAAO,MAAM,qBAAqB,8CAK/B;IACD,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,0BAiHA,CAAC;AAEF,eAAO,MAAM,gBAAgB,gCAI1B;IACD,MAAM,EAAE,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAChC,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,gBAAgB,CAAC;CAC3B;;;;;aA+BA,CAAC;AAEF,eAAO,MAAM,2BAA2B,0BAGrC;IACD,MAAM,EAAE,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAChC,QAAQ,EAAE,gBAAgB,CAAC;CAC5B,wCA+CA,CAAC;AAEF,eAAO,MAAM,sBAAsB,wBAGhC;IACD,IAAI,EAAE,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,QAAQ,EAAE,gBAAgB,CAAC;CAC5B,0BAiEA,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,UAAW,KAAK,WAAW,MAAM,sBAW3D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,WACnB,kBAAkB,CAAC,GAAG,CAAC,WACtB,gBAAgB,KACxB,OAAO,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAenC,CAAC;AAEF;;GAEG;AAEH,eAAO,MAAM,WAAW,WAAkB,OAAO,WAAW,gBAAgB,KAAG,OAAO,CAAC,OAAO,CAQ7F,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/plugin-space",
3
- "version": "0.6.12-main.5cc132e",
3
+ "version": "0.6.12-main.c974201",
4
4
  "description": "DXOS Surface plugin for DXOS ECHO Spaces",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -54,30 +54,32 @@
54
54
  "lodash.get": "^4.4.2",
55
55
  "react-drag-drop-files": "^2.3.8",
56
56
  "react-is": "~18.2.0",
57
- "@dxos/app-framework": "0.6.12-main.5cc132e",
58
- "@dxos/automerge": "0.6.12-main.5cc132e",
59
- "@dxos/context": "0.6.12-main.5cc132e",
60
- "@dxos/client": "0.6.12-main.5cc132e",
61
- "@dxos/display-name": "0.6.12-main.5cc132e",
62
- "@dxos/async": "0.6.12-main.5cc132e",
63
- "@dxos/echo-schema": "0.6.12-main.5cc132e",
64
- "@dxos/invariant": "0.6.12-main.5cc132e",
65
- "@dxos/keys": "0.6.12-main.5cc132e",
66
- "@dxos/log": "0.6.12-main.5cc132e",
67
- "@dxos/local-storage": "0.6.12-main.5cc132e",
68
- "@dxos/migrations": "0.6.12-main.5cc132e",
69
- "@dxos/plugin-attention": "0.6.12-main.5cc132e",
70
- "@dxos/plugin-client": "0.6.12-main.5cc132e",
71
- "@dxos/plugin-graph": "0.6.12-main.5cc132e",
72
- "@dxos/plugin-metadata": "0.6.12-main.5cc132e",
73
- "@dxos/plugin-settings": "0.6.12-main.5cc132e",
74
- "@dxos/plugin-status-bar": "0.6.12-main.5cc132e",
75
- "@dxos/react-ui-editor": "0.6.12-main.5cc132e",
76
- "@dxos/plugin-observability": "0.6.12-main.5cc132e",
77
- "@dxos/react-ui-attention": "0.6.12-main.5cc132e",
78
- "@dxos/react-client": "0.6.12-main.5cc132e",
79
- "@dxos/shell": "0.6.12-main.5cc132e",
80
- "@dxos/util": "0.6.12-main.5cc132e"
57
+ "@dxos/app-framework": "0.6.12-main.c974201",
58
+ "@dxos/async": "0.6.12-main.c974201",
59
+ "@dxos/automerge": "0.6.12-main.c974201",
60
+ "@dxos/client": "0.6.12-main.c974201",
61
+ "@dxos/display-name": "0.6.12-main.c974201",
62
+ "@dxos/invariant": "0.6.12-main.c974201",
63
+ "@dxos/echo-schema": "0.6.12-main.c974201",
64
+ "@dxos/local-storage": "0.6.12-main.c974201",
65
+ "@dxos/keys": "0.6.12-main.c974201",
66
+ "@dxos/migrations": "0.6.12-main.c974201",
67
+ "@dxos/log": "0.6.12-main.c974201",
68
+ "@dxos/plugin-attention": "0.6.12-main.c974201",
69
+ "@dxos/plugin-client": "0.6.12-main.c974201",
70
+ "@dxos/context": "0.6.12-main.c974201",
71
+ "@dxos/plugin-graph": "0.6.12-main.c974201",
72
+ "@dxos/plugin-observability": "0.6.12-main.c974201",
73
+ "@dxos/plugin-metadata": "0.6.12-main.c974201",
74
+ "@dxos/plugin-settings": "0.6.12-main.c974201",
75
+ "@dxos/protocols": "0.6.12-main.c974201",
76
+ "@dxos/plugin-status-bar": "0.6.12-main.c974201",
77
+ "@dxos/react-client": "0.6.12-main.c974201",
78
+ "@dxos/react-ui-attention": "0.6.12-main.c974201",
79
+ "@dxos/react-ui-editor": "0.6.12-main.c974201",
80
+ "@dxos/react-ui-syntax-highlighter": "0.6.12-main.c974201",
81
+ "@dxos/shell": "0.6.12-main.c974201",
82
+ "@dxos/util": "0.6.12-main.c974201"
81
83
  },
82
84
  "devDependencies": {
83
85
  "@babel/core": "^7.18.13",
@@ -88,17 +90,17 @@
88
90
  "react": "~18.2.0",
89
91
  "react-dom": "~18.2.0",
90
92
  "vite": "5.4.7",
91
- "@dxos/react-ui": "0.6.12-main.5cc132e",
92
- "@dxos/storybook-utils": "0.6.12-main.5cc132e",
93
- "@dxos/react-ui-theme": "0.6.12-main.5cc132e"
93
+ "@dxos/react-ui-theme": "0.6.12-main.c974201",
94
+ "@dxos/react-ui": "0.6.12-main.c974201",
95
+ "@dxos/storybook-utils": "0.6.12-main.c974201"
94
96
  },
95
97
  "optionalDependencies": {
96
98
  "@babel/core": "^7.18.13",
97
99
  "@phosphor-icons/react": "^2.1.5",
98
- "react": "^18.0.0",
99
- "react-dom": "^18.0.0",
100
- "@dxos/react-ui": "0.6.12-main.5cc132e",
101
- "@dxos/react-ui-theme": "0.6.12-main.5cc132e"
100
+ "react": "~18.2.0",
101
+ "react-dom": "~18.2.0",
102
+ "@dxos/react-ui": "0.6.12-main.c974201",
103
+ "@dxos/react-ui-theme": "0.6.12-main.c974201"
102
104
  },
103
105
  "publishConfig": {
104
106
  "access": "public"
@@ -2,7 +2,6 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { CardsThree, type IconProps, Plus, SignIn, Warning } from '@phosphor-icons/react';
6
5
  import { effect, signal } from '@preact/signals-core';
7
6
  import React from 'react';
8
7
 
@@ -67,6 +66,7 @@ import {
67
66
  SmallPresenceLive,
68
67
  SpacePresence,
69
68
  SpaceSettings,
69
+ SyncStatus,
70
70
  } from './components';
71
71
  import meta, { SPACE_PLUGIN, SpaceAction } from './meta';
72
72
  import translations from './translations';
@@ -119,7 +119,9 @@ export const SpacePlugin = ({
119
119
  firstRun,
120
120
  onFirstRun,
121
121
  }: SpacePluginOptions = {}): PluginDefinition<SpacePluginProvides> => {
122
- const settings = new LocalStorageStore<SpaceSettingsProps>(SPACE_PLUGIN);
122
+ const settings = new LocalStorageStore<SpaceSettingsProps>(SPACE_PLUGIN, {
123
+ onSpaceCreate: 'dxos.org/plugin/markdown/action/create',
124
+ });
123
125
  const state = new LocalStorageStore<PluginState>(SPACE_PLUGIN, {
124
126
  awaiting: undefined,
125
127
  spaceNames: {},
@@ -341,8 +343,7 @@ export const SpacePlugin = ({
341
343
  records: {
342
344
  [CollectionType.typename]: {
343
345
  placeholder: ['unnamed collection label', { ns: SPACE_PLUGIN }],
344
- icon: (props: IconProps) => <CardsThree {...props} />,
345
- iconSymbol: 'ph--cards-three--regular',
346
+ icon: 'ph--cards-three--regular',
346
347
  // TODO(wittjosiah): Move out of metadata.
347
348
  loadReferences: (collection: CollectionType) =>
348
349
  loadObjectReferences(collection, (collection) => [
@@ -443,7 +444,12 @@ export const SpacePlugin = ({
443
444
  return <MenuFooter object={data.object} />;
444
445
  }
445
446
  case 'status': {
446
- return <SaveStatus />;
447
+ return (
448
+ <>
449
+ <SyncStatus />
450
+ <SaveStatus />
451
+ </>
452
+ );
447
453
  }
448
454
  default:
449
455
  return null;
@@ -544,8 +550,7 @@ export const SpacePlugin = ({
544
550
  },
545
551
  properties: {
546
552
  label: ['create space label', { ns: SPACE_PLUGIN }],
547
- icon: (props: IconProps) => <Plus {...props} />,
548
- iconSymbol: 'ph--plus--regular',
553
+ icon: 'ph--plus--regular',
549
554
  disposition: 'toolbar',
550
555
  testId: 'spacePlugin.createSpace',
551
556
  },
@@ -565,8 +570,7 @@ export const SpacePlugin = ({
565
570
  },
566
571
  properties: {
567
572
  label: ['join space label', { ns: SPACE_PLUGIN }],
568
- icon: (props: IconProps) => <SignIn {...props} />,
569
- iconSymbol: 'ph--sign-in--regular',
573
+ icon: 'ph--sign-in--regular',
570
574
  testId: 'spacePlugin.joinSpace',
571
575
  },
572
576
  },
@@ -809,6 +813,15 @@ export const SpacePlugin = ({
809
813
  data: { space, id: space.id, activeParts: { main: [space.id] } },
810
814
 
811
815
  intents: [
816
+ ...(settings.values.onSpaceCreate
817
+ ? [
818
+ [
819
+ { action: settings.values.onSpaceCreate, data: { space } },
820
+ { action: SpaceAction.ADD_OBJECT, data: { target: space } },
821
+ { action: NavigationAction.EXPOSE },
822
+ ],
823
+ ]
824
+ : []),
812
825
  [
813
826
  {
814
827
  action: ObservabilityAction.SEND_EVENT,
@@ -1024,8 +1037,7 @@ export const SpacePlugin = ({
1024
1037
  title: translations[0]['en-US'][SPACE_PLUGIN]['space limit label'],
1025
1038
  description: translations[0]['en-US'][SPACE_PLUGIN]['space limit description'],
1026
1039
  duration: 5_000,
1027
- icon: (props: IconProps) => <Warning {...props} />,
1028
- iconSymbol: 'ph--warning--regular',
1040
+ icon: 'ph--warning--regular',
1029
1041
  actionLabel: translations[0]['en-US'][SPACE_PLUGIN]['remove deleted objects label'],
1030
1042
  actionAlt: translations[0]['en-US'][SPACE_PLUGIN]['remove deleted objects alt'],
1031
1043
  // TODO(wittjosiah): Use OS namespace.
@@ -1064,7 +1076,7 @@ export const SpacePlugin = ({
1064
1076
  }
1065
1077
 
1066
1078
  return {
1067
- data: { id: object.id, object, activeParts: { main: [fullyQualifiedId(object)] } },
1079
+ data: { id: fullyQualifiedId(object), object, activeParts: { main: [fullyQualifiedId(object)] } },
1068
1080
  intents: [
1069
1081
  [
1070
1082
  {
@@ -1119,7 +1131,6 @@ export const SpacePlugin = ({
1119
1131
  activeParts: {
1120
1132
  main: deletionData.wasActive,
1121
1133
  sidebar: deletionData.wasActive,
1122
- complementary: deletionData.wasActive,
1123
1134
  },
1124
1135
  },
1125
1136
  });
@@ -2,25 +2,22 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { ArrowsClockwise, CheckCircle } from '@phosphor-icons/react';
6
- import React, { useEffect } from 'react';
5
+ import React, { useEffect, useState } from 'react';
7
6
 
8
- import type { UnsubscribeCallback } from '@dxos/async';
9
- import type { Client } from '@dxos/client';
7
+ import { type UnsubscribeCallback } from '@dxos/async';
8
+ import { type Client } from '@dxos/client';
10
9
  import { type Space, type SpaceId } from '@dxos/client/echo';
11
10
  import { Context } from '@dxos/context';
12
11
  import { StatusBar } from '@dxos/plugin-status-bar';
13
12
  import { useClient } from '@dxos/react-client';
14
- import { useTranslation } from '@dxos/react-ui';
15
- import { getSize } from '@dxos/react-ui-theme';
13
+ import { Icon, useTranslation } from '@dxos/react-ui';
16
14
 
17
15
  import { SPACE_PLUGIN } from '../meta';
18
16
 
19
17
  export const SaveStatus = () => {
20
18
  const { t } = useTranslation(SPACE_PLUGIN);
21
19
  const client = useClient();
22
- const [state, setState] = React.useState<'saved' | 'saving'>('saved');
23
-
20
+ const [state, setState] = useState<'saved' | 'saving'>('saved');
24
21
  useEffect(() => {
25
22
  return createClientSaveTracker(client, (state) => {
26
23
  setState(state);
@@ -29,7 +26,7 @@ export const SaveStatus = () => {
29
26
 
30
27
  return (
31
28
  <StatusBar.Item title={state === 'saving' ? t('saving label') : t('saved label')}>
32
- {state === 'saving' ? <ArrowsClockwise className={getSize(3)} /> : <CheckCircle className={getSize(3)} />}
29
+ <Icon icon={state === 'saving' ? 'ph--arrows-clockwise--regular' : 'ph--check-circle--regular'} size={4} />
33
30
  </StatusBar.Item>
34
31
  );
35
32
  };
@@ -6,35 +6,14 @@ import { Command } from '@phosphor-icons/react';
6
6
  import React from 'react';
7
7
 
8
8
  import { Surface } from '@dxos/app-framework';
9
- import { type Action } from '@dxos/plugin-graph';
10
9
  import { SpaceState, type Space } from '@dxos/react-client/echo';
11
- import { Button, Main, useTranslation, toLocalizedString } from '@dxos/react-ui';
10
+ import { Main, useTranslation } from '@dxos/react-ui';
12
11
  import { getSize, mx, topbarBlockPaddingStart } from '@dxos/react-ui-theme';
13
12
  import { ClipboardProvider } from '@dxos/shell/react';
14
13
 
15
14
  import { SpaceMembersSection } from './SpaceMembersSection';
16
15
  import { SPACE_PLUGIN } from '../../meta';
17
16
 
18
- const _InFlowSpaceActions = ({ actionsMap }: { actionsMap: Record<string, Action> }) => {
19
- const { t } = useTranslation(SPACE_PLUGIN);
20
- return (
21
- <section className='mbe-4 col-start-2 col-end-4 md:col-end-7 grid gap-2 auto-rows-min grid-cols-[repeat(auto-fill,minmax(8rem,1fr))]'>
22
- {Object.entries(actionsMap)
23
- .filter(([_, { properties }]) => properties?.mainAreaDisposition === 'in-flow')
24
- .map(([actionId, { data: invoke, properties }]) => {
25
- const Icon = properties?.icon;
26
- const label = properties?.label;
27
- return (
28
- <Button key={actionId} classNames='block text-center plb-2 font-normal'>
29
- {Icon && <Icon size={5} className='mli-auto' />}
30
- <p>{toLocalizedString(label, t)}</p>
31
- </Button>
32
- );
33
- })}
34
- </section>
35
- );
36
- };
37
-
38
17
  const KeyShortcuts = () => {
39
18
  const { t } = useTranslation(SPACE_PLUGIN);
40
19
  return (
@@ -4,16 +4,17 @@
4
4
 
5
5
  import React from 'react';
6
6
 
7
- import { useIntentDispatcher } from '@dxos/app-framework';
7
+ import { useIntentDispatcher, useResolvePlugins } from '@dxos/app-framework';
8
8
  import { SettingsValue } from '@dxos/plugin-settings';
9
- import { Input, useTranslation } from '@dxos/react-ui';
9
+ import { Input, Select, toLocalizedString, useTranslation } from '@dxos/react-ui';
10
10
 
11
11
  import { SpaceAction, SPACE_PLUGIN } from '../meta';
12
- import { type SpaceSettingsProps } from '../types';
12
+ import { parseSpaceInitPlugin, type SpaceSettingsProps } from '../types';
13
13
 
14
14
  export const SpaceSettings = ({ settings }: { settings: SpaceSettingsProps }) => {
15
15
  const { t } = useTranslation(SPACE_PLUGIN);
16
16
  const dispatch = useIntentDispatcher();
17
+ const plugins = useResolvePlugins(parseSpaceInitPlugin);
17
18
 
18
19
  return (
19
20
  <>
@@ -29,6 +30,34 @@ export const SpaceSettings = ({ settings }: { settings: SpaceSettingsProps }) =>
29
30
  }
30
31
  />
31
32
  </SettingsValue>
33
+
34
+ <SettingsValue label={t('default on space create label')}>
35
+ <Select.Root
36
+ value={settings.onSpaceCreate}
37
+ onValueChange={(value) => {
38
+ settings.onSpaceCreate = value;
39
+ }}
40
+ >
41
+ <Select.TriggerButton />
42
+ <Select.Portal>
43
+ <Select.Content>
44
+ <Select.Viewport>
45
+ {plugins.map(
46
+ ({
47
+ provides: {
48
+ space: { onSpaceCreate },
49
+ },
50
+ }) => (
51
+ <Select.Option key={onSpaceCreate.action} value={onSpaceCreate.action}>
52
+ {toLocalizedString(onSpaceCreate.label, t)}
53
+ </Select.Option>
54
+ ),
55
+ )}
56
+ </Select.Viewport>
57
+ </Select.Content>
58
+ </Select.Portal>
59
+ </Select.Root>
60
+ </SettingsValue>
32
61
  </>
33
62
  );
34
63
  };
@@ -0,0 +1,62 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import '@dxos-theme';
6
+
7
+ import React from 'react';
8
+
9
+ import { SpaceId } from '@dxos/keys';
10
+ import { withTheme, withLayout } from '@dxos/storybook-utils';
11
+
12
+ import { SyncStatusDetail, SyncStatusIndicator } from './SyncStatus';
13
+ import { getSyncSummary, type SpaceSyncStateMap } from './types';
14
+ import translations from '../../translations';
15
+
16
+ const Story = (props: any) => {
17
+ return (
18
+ <div className='flex flex-col-reverse p-4 '>
19
+ <SyncStatusIndicator {...props} />
20
+ </div>
21
+ );
22
+ };
23
+
24
+ export default {
25
+ title: 'plugin-space/SyncStatusIndicator',
26
+ decorators: [withTheme, withLayout({ fullscreen: true })],
27
+ component: SyncStatusIndicator,
28
+ parameters: { translations },
29
+ render: Story,
30
+ };
31
+
32
+ const random = ({ min, max }: { min: number; max: number }) => min + Math.floor(Math.random() * (max - min));
33
+
34
+ const state: SpaceSyncStateMap = Array.from({ length: 5 }).reduce<SpaceSyncStateMap>((map) => {
35
+ const total = random({ min: 10, max: 500 });
36
+ const haveLocal = random({ min: 0, max: total });
37
+ const haveRemote = random({ min: 0, max: total });
38
+ map[SpaceId.random()] = {
39
+ localDocumentCount: haveLocal,
40
+ remoteDocumentCount: haveRemote,
41
+ missingOnLocal: total - haveLocal,
42
+ missingOnRemote: total - haveRemote,
43
+ differentDocuments: 0,
44
+ };
45
+
46
+ return map;
47
+ }, {});
48
+
49
+ export const Default = {
50
+ args: {
51
+ state,
52
+ },
53
+ };
54
+
55
+ export const Detail = {
56
+ render: SyncStatusDetail,
57
+ args: {
58
+ state,
59
+ summary: getSyncSummary(state),
60
+ classNames: 'm-2 w-[200px] border border-separator rounded-md',
61
+ },
62
+ };
@@ -0,0 +1,188 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import React, { type HTMLAttributes, useEffect, useState } from 'react';
6
+
7
+ import { StatusBar } from '@dxos/plugin-status-bar';
8
+ import { Icon, Popover, useTranslation } from '@dxos/react-ui';
9
+ import { type ThemedClassName } from '@dxos/react-ui';
10
+ import { SyntaxHighlighter } from '@dxos/react-ui-syntax-highlighter';
11
+ import { mx } from '@dxos/react-ui-theme';
12
+
13
+ import { type Progress, type PeerSyncState, type SpaceSyncStateMap, getSyncSummary, useSyncState } from './types';
14
+ import { SPACE_PLUGIN } from '../../meta';
15
+
16
+ const SYNC_STALLED_TIMEOUT = 5_000;
17
+
18
+ const styles = {
19
+ barBg: 'bg-neutral-50 dark:bg-green-900 text-black',
20
+ barFg: 'bg-neutral-100 bg-green-500',
21
+ barHover: 'dark:hover:bg-green-500',
22
+ };
23
+
24
+ export const SyncStatus = () => {
25
+ const state = useSyncState();
26
+ return <SyncStatusIndicator state={state} />;
27
+ };
28
+
29
+ export const SyncStatusIndicator = ({ state }: { state: SpaceSyncStateMap }) => {
30
+ const summary = getSyncSummary(state);
31
+ const offline = false;
32
+
33
+ const needsToUpload = summary.differentDocuments > 0 || summary.missingOnRemote > 0;
34
+ const needsToDownload = summary.differentDocuments > 0 || summary.missingOnLocal > 0;
35
+ const [classNames, setClassNames] = useState<string>();
36
+ useEffect(() => {
37
+ setClassNames(undefined);
38
+ if (!needsToUpload && !needsToDownload) {
39
+ return;
40
+ }
41
+
42
+ const t = setTimeout(() => {
43
+ setClassNames('text-orange-500');
44
+ }, SYNC_STALLED_TIMEOUT);
45
+ return () => clearTimeout(t);
46
+ }, [needsToUpload, needsToDownload]);
47
+
48
+ return (
49
+ <StatusBar.Item>
50
+ <Popover.Root>
51
+ <Popover.Trigger>
52
+ <Icon
53
+ icon={
54
+ offline
55
+ ? 'ph--cloud-x--regular'
56
+ : needsToUpload
57
+ ? 'ph--cloud-arrow-up--regular'
58
+ : needsToDownload
59
+ ? 'ph--cloud-arrow-down--regular'
60
+ : 'ph--cloud-check--regular'
61
+ }
62
+ size={4}
63
+ classNames={classNames}
64
+ />
65
+ </Popover.Trigger>
66
+ <Popover.Content>
67
+ <SyncStatusDetail state={state} summary={summary} debug={false} />
68
+ </Popover.Content>
69
+ </Popover.Root>
70
+ </StatusBar.Item>
71
+ );
72
+ };
73
+
74
+ export const SyncStatusDetail = ({
75
+ classNames,
76
+ state,
77
+ summary,
78
+ debug,
79
+ }: ThemedClassName<{
80
+ state: SpaceSyncStateMap;
81
+ summary: PeerSyncState;
82
+ debug?: boolean;
83
+ }>) => {
84
+ const { t } = useTranslation(SPACE_PLUGIN);
85
+ const entries = Object.entries(state).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
86
+
87
+ // TODO(burdon): Normalize to max document count?
88
+ return (
89
+ <div className={mx('flex flex-col text-xs min-w-[16rem]', classNames)}>
90
+ <h1 className='p-2'>{t('sync status title')}</h1>
91
+ <div className='flex flex-col gap-[2px] my-[2px]'>
92
+ {entries.map(([spaceId, state]) => (
93
+ <SpaceRow key={spaceId} spaceId={spaceId} state={state} />
94
+ ))}
95
+ </div>
96
+ {debug && <SyntaxHighlighter language='json'>{JSON.stringify(summary, null, 2)}</SyntaxHighlighter>}
97
+ </div>
98
+ );
99
+ };
100
+
101
+ const useActive = (count: number) => {
102
+ const [current, setCurrent] = useState(count);
103
+ const [active, setActive] = useState(false);
104
+ useEffect(() => {
105
+ let t: NodeJS.Timeout | undefined;
106
+ if (count !== current) {
107
+ setActive(true);
108
+ setCurrent(count);
109
+ t && clearTimeout(t);
110
+ t = setTimeout(() => {
111
+ setActive(false);
112
+ }, SYNC_STALLED_TIMEOUT);
113
+ }
114
+
115
+ return () => {
116
+ setActive(false);
117
+ clearTimeout(t);
118
+ };
119
+ }, [count, current]);
120
+ return active;
121
+ };
122
+
123
+ const SpaceRow = ({
124
+ spaceId,
125
+ state: { localDocumentCount, remoteDocumentCount, missingOnLocal, missingOnRemote },
126
+ }: {
127
+ spaceId: string;
128
+ state: PeerSyncState;
129
+ }) => {
130
+ const downActive = useActive(localDocumentCount);
131
+ const upActive = useActive(remoteDocumentCount);
132
+
133
+ return (
134
+ <div
135
+ className={mx('flex items-center mx-[2px] gap-[2px] cursor-pointer', styles.barHover)}
136
+ title={spaceId}
137
+ onClick={() => {
138
+ void navigator.clipboard.writeText(spaceId);
139
+ }}
140
+ >
141
+ <Icon
142
+ icon='ph--arrow-fat-line-left--regular'
143
+ size={3}
144
+ classNames={mx(downActive && 'animate-[pulse_1s_infinite]')}
145
+ />
146
+ <Candle
147
+ up={{ count: remoteDocumentCount, total: remoteDocumentCount + missingOnRemote }}
148
+ down={{ count: localDocumentCount, total: localDocumentCount + missingOnLocal }}
149
+ title={spaceId}
150
+ />
151
+ <Icon
152
+ icon='ph--arrow-fat-line-right--regular'
153
+ size={3}
154
+ classNames={mx(upActive && 'animate-[pulse_1s_step-start_infinite]')}
155
+ />
156
+ </div>
157
+ );
158
+ };
159
+
160
+ type CandleProps = ThemedClassName<Pick<HTMLAttributes<HTMLDivElement>, 'title'>> & { up: Progress; down: Progress };
161
+
162
+ const Candle = ({ classNames, up, down }: CandleProps) => {
163
+ return (
164
+ <div className={mx('grid grid-cols-[1fr_2rem_1fr] w-full h-3', classNames)}>
165
+ <Bar classNames='justify-end' {...up} />
166
+ <div className='relative'>
167
+ <div className={mx('absolute inset-0 flex items-center justify-center text-xs', styles.barBg)}>{up.total}</div>
168
+ </div>
169
+ <Bar {...down} />
170
+ </div>
171
+ );
172
+ };
173
+
174
+ const Bar = ({ classNames, count, total }: ThemedClassName<Progress>) => {
175
+ let p = (count / total) * 100;
176
+ if (count < total) {
177
+ p = Math.min(p, 95);
178
+ }
179
+
180
+ return (
181
+ <div className={mx('relative flex w-full', styles.barBg, classNames)}>
182
+ <div className={mx('shrink-0', styles.barFg)} style={{ width: `${p}%` }}></div>
183
+ {count !== total && (
184
+ <div className='absolute top-0 bottom-0 flex items-center mx-0.5 text-black text-xs'>{count}</div>
185
+ )}
186
+ </div>
187
+ );
188
+ };