@dxos/plugin-space 0.7.2 → 0.7.3-staging.0905f03

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 (99) hide show
  1. package/dist/lib/browser/{chunk-DJE2HYFV.mjs → chunk-FTKV32QZ.mjs} +9 -2
  2. package/dist/lib/browser/chunk-FTKV32QZ.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-OWZKSWMX.mjs → chunk-MWKXNS5S.mjs} +13 -3
  4. package/dist/lib/browser/{chunk-OWZKSWMX.mjs.map → chunk-MWKXNS5S.mjs.map} +3 -3
  5. package/dist/lib/browser/index.mjs +1167 -786
  6. package/dist/lib/browser/index.mjs.map +4 -4
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/meta.mjs +3 -1
  9. package/dist/lib/browser/types/index.mjs +5 -3
  10. package/dist/lib/node/{chunk-FYWGZYJB.cjs → chunk-6SNOZF7Y.cjs} +18 -7
  11. package/dist/lib/node/chunk-6SNOZF7Y.cjs.map +7 -0
  12. package/dist/lib/node/{chunk-JFDDZI4Y.cjs → chunk-QNVEU2UD.cjs} +12 -4
  13. package/dist/lib/node/chunk-QNVEU2UD.cjs.map +7 -0
  14. package/dist/lib/node/index.cjs +1210 -839
  15. package/dist/lib/node/index.cjs.map +4 -4
  16. package/dist/lib/node/meta.cjs +7 -5
  17. package/dist/lib/node/meta.cjs.map +2 -2
  18. package/dist/lib/node/meta.json +1 -1
  19. package/dist/lib/node/types/index.cjs +14 -12
  20. package/dist/lib/node/types/index.cjs.map +2 -2
  21. package/dist/lib/node-esm/{chunk-MCEAI4CV.mjs → chunk-OHEAWSCA.mjs} +13 -3
  22. package/dist/lib/node-esm/{chunk-MCEAI4CV.mjs.map → chunk-OHEAWSCA.mjs.map} +3 -3
  23. package/dist/lib/node-esm/{chunk-DVUZ7A7G.mjs → chunk-UMV7XREB.mjs} +9 -2
  24. package/dist/lib/node-esm/chunk-UMV7XREB.mjs.map +7 -0
  25. package/dist/lib/node-esm/index.mjs +1167 -786
  26. package/dist/lib/node-esm/index.mjs.map +4 -4
  27. package/dist/lib/node-esm/meta.json +1 -1
  28. package/dist/lib/node-esm/meta.mjs +3 -1
  29. package/dist/lib/node-esm/types/index.mjs +5 -3
  30. package/dist/types/src/SpacePlugin.d.ts.map +1 -1
  31. package/dist/types/src/components/CreateDialog/CreateObjectDialog.d.ts +9 -0
  32. package/dist/types/src/components/CreateDialog/CreateObjectDialog.d.ts.map +1 -0
  33. package/dist/types/src/components/CreateDialog/CreateObjectDialog.stories.d.ts +10 -0
  34. package/dist/types/src/components/CreateDialog/CreateObjectDialog.stories.d.ts.map +1 -0
  35. package/dist/types/src/components/CreateDialog/CreateObjectPanel.d.ts +22 -0
  36. package/dist/types/src/components/CreateDialog/CreateObjectPanel.d.ts.map +1 -0
  37. package/dist/types/src/components/CreateDialog/CreateSpaceDialog.d.ts +3 -0
  38. package/dist/types/src/components/CreateDialog/CreateSpaceDialog.d.ts.map +1 -0
  39. package/dist/types/src/components/CreateDialog/index.d.ts +3 -0
  40. package/dist/types/src/components/CreateDialog/index.d.ts.map +1 -0
  41. package/dist/types/src/components/PopoverRenameObject.d.ts +1 -1
  42. package/dist/types/src/components/SpacePluginSettings.d.ts.map +1 -1
  43. package/dist/types/src/components/SpaceSettings/SpaceSettingsDialog.d.ts.map +1 -1
  44. package/dist/types/src/components/SpaceSettings/SpaceSettingsPanel.d.ts.map +1 -1
  45. package/dist/types/src/components/SyncStatus/InlineSyncStatus.d.ts +7 -0
  46. package/dist/types/src/components/SyncStatus/InlineSyncStatus.d.ts.map +1 -0
  47. package/dist/types/src/components/SyncStatus/InlineSyncStatus.stories.d.ts +6 -0
  48. package/dist/types/src/components/SyncStatus/InlineSyncStatus.stories.d.ts.map +1 -0
  49. package/dist/types/src/components/SyncStatus/Space.d.ts +8 -3
  50. package/dist/types/src/components/SyncStatus/Space.d.ts.map +1 -1
  51. package/dist/types/src/components/SyncStatus/SyncStatus.d.ts +3 -2
  52. package/dist/types/src/components/SyncStatus/SyncStatus.d.ts.map +1 -1
  53. package/dist/types/src/components/SyncStatus/SyncStatus.stories.d.ts +4 -4
  54. package/dist/types/src/components/SyncStatus/SyncStatus.stories.d.ts.map +1 -1
  55. package/dist/types/src/components/SyncStatus/SyncStatusDetail.stories.d.ts +9 -0
  56. package/dist/types/src/components/SyncStatus/SyncStatusDetail.stories.d.ts.map +1 -0
  57. package/dist/types/src/components/SyncStatus/index.d.ts +1 -0
  58. package/dist/types/src/components/SyncStatus/index.d.ts.map +1 -1
  59. package/dist/types/src/components/SyncStatus/sync-state.d.ts +5 -1
  60. package/dist/types/src/components/SyncStatus/sync-state.d.ts.map +1 -1
  61. package/dist/types/src/components/index.d.ts +1 -0
  62. package/dist/types/src/components/index.d.ts.map +1 -1
  63. package/dist/types/src/meta.d.ts +5 -0
  64. package/dist/types/src/meta.d.ts.map +1 -1
  65. package/dist/types/src/translations.d.ts +224 -0
  66. package/dist/types/src/translations.d.ts.map +1 -1
  67. package/dist/types/src/types/types.d.ts +14 -14
  68. package/dist/types/src/types/types.d.ts.map +1 -1
  69. package/dist/types/src/util.d.ts +3 -13
  70. package/dist/types/src/util.d.ts.map +1 -1
  71. package/package.json +38 -35
  72. package/src/SpacePlugin.tsx +203 -128
  73. package/src/components/AwaitingObject.tsx +2 -2
  74. package/src/components/CreateDialog/CreateObjectDialog.stories.tsx +83 -0
  75. package/src/components/CreateDialog/CreateObjectDialog.tsx +98 -0
  76. package/src/components/CreateDialog/CreateObjectPanel.tsx +169 -0
  77. package/src/components/CreateDialog/CreateSpaceDialog.tsx +57 -0
  78. package/src/components/CreateDialog/index.ts +6 -0
  79. package/src/components/PopoverRenameObject.tsx +1 -1
  80. package/src/components/SpacePluginSettings.tsx +3 -32
  81. package/src/components/SpaceSettings/SpaceSettingsDialog.tsx +5 -5
  82. package/src/components/SpaceSettings/SpaceSettingsPanel.tsx +2 -6
  83. package/src/components/SyncStatus/InlineSyncStatus.stories.tsx +57 -0
  84. package/src/components/SyncStatus/InlineSyncStatus.tsx +61 -0
  85. package/src/components/SyncStatus/Space.tsx +30 -6
  86. package/src/components/SyncStatus/SyncStatus.stories.tsx +15 -42
  87. package/src/components/SyncStatus/SyncStatus.tsx +32 -14
  88. package/src/components/SyncStatus/SyncStatusDetail.stories.tsx +85 -0
  89. package/src/components/SyncStatus/index.ts +1 -0
  90. package/src/components/SyncStatus/sync-state.ts +24 -0
  91. package/src/components/index.ts +1 -0
  92. package/src/meta.ts +6 -0
  93. package/src/translations.ts +15 -0
  94. package/src/types/types.ts +20 -16
  95. package/src/util.tsx +51 -141
  96. package/dist/lib/browser/chunk-DJE2HYFV.mjs.map +0 -7
  97. package/dist/lib/node/chunk-FYWGZYJB.cjs.map +0 -7
  98. package/dist/lib/node/chunk-JFDDZI4Y.cjs.map +0 -7
  99. package/dist/lib/node-esm/chunk-DVUZ7A7G.mjs.map +0 -7
@@ -1,9 +1,10 @@
1
1
  import {
2
+ CollectionAction,
2
3
  SPACE_PLUGIN,
3
4
  SPACE_PLUGIN_SHORT_ID,
4
5
  SpaceAction,
5
6
  meta_default
6
- } from "./chunk-DJE2HYFV.mjs";
7
+ } from "./chunk-FTKV32QZ.mjs";
7
8
  import {
8
9
  ActorSchema,
9
10
  ChannelType,
@@ -12,19 +13,21 @@ import {
12
13
  MessageState,
13
14
  MessageType,
14
15
  SPACE_DIRECTORY_HANDLE,
16
+ SpaceForm,
15
17
  ThreadStatus,
16
18
  ThreadType,
17
- parseSpaceInitPlugin
18
- } from "./chunk-OWZKSWMX.mjs";
19
+ parseSchemaPlugin
20
+ } from "./chunk-MWKXNS5S.mjs";
19
21
 
20
22
  // packages/plugins/plugin-space/src/SpacePlugin.tsx
21
23
  import { signal } from "@preact/signals-core";
22
- import React17 from "react";
23
- import { LayoutAction as LayoutAction2, NavigationAction as NavigationAction4, Surface, findPlugin, firstIdInPart, openIds, parseGraphPlugin, parseIntentPlugin as parseIntentPlugin2, parseLayoutPlugin, parseMetadataResolverPlugin, parseNavigationPlugin as parseNavigationPlugin2, resolvePlugin } from "@dxos/app-framework";
24
+ import React21 from "react";
25
+ import { LayoutAction as LayoutAction2, NavigationAction as NavigationAction4, Surface, filterPlugins, findPlugin, firstIdInPart, openIds, parseGraphPlugin, parseIntentPlugin as parseIntentPlugin2, parseLayoutPlugin, parseMetadataResolverPlugin, parseNavigationPlugin as parseNavigationPlugin2, resolvePlugin } from "@dxos/app-framework";
24
26
  import { EventSubscriptions } from "@dxos/async";
25
- import { isDeleted, isReactiveObject as isReactiveObject2 } from "@dxos/echo-schema";
27
+ import { S as S2 } from "@dxos/echo-schema";
26
28
  import { scheduledEffect } from "@dxos/echo-signals/core";
27
29
  import { invariant as invariant2 } from "@dxos/invariant";
30
+ import { create, isDeleted, isReactiveObject as isReactiveObject3 } from "@dxos/live-object";
28
31
  import { LocalStorageStore } from "@dxos/local-storage";
29
32
  import { log as log3 } from "@dxos/log";
30
33
  import { Migrations as Migrations2 } from "@dxos/migrations";
@@ -32,17 +35,18 @@ import { parseAttentionPlugin } from "@dxos/plugin-attention";
32
35
  import { parseClientPlugin } from "@dxos/plugin-client";
33
36
  import { createExtension, memoize as memoize2, toSignal } from "@dxos/plugin-graph";
34
37
  import { ObservabilityAction as ObservabilityAction2 } from "@dxos/plugin-observability/meta";
38
+ import { EdgeReplicationSetting as EdgeReplicationSetting3 } from "@dxos/protocols/proto/dxos/echo/metadata";
35
39
  import { PublicKey as PublicKey2 } from "@dxos/react-client";
36
- import { Expando, Filter, SpaceState as SpaceState2, create as create2, fullyQualifiedId as fullyQualifiedId4, getSpace as getSpace4, getTypename as getTypename2, isEchoObject as isEchoObject2, isSpace as isSpace2, loadObjectReferences, parseId, FQ_ID_LENGTH, SPACE_ID_LENGTH, OBJECT_ID_LENGTH } from "@dxos/react-client/echo";
40
+ import { Expando, FQ_ID_LENGTH, Filter as Filter3, OBJECT_ID_LENGTH, SPACE_ID_LENGTH, SpaceState as SpaceState2, fullyQualifiedId as fullyQualifiedId4, getSpace as getSpace5, getTypename as getTypename2, isEchoObject as isEchoObject2, isSpace as isSpace4, loadObjectReferences, parseFullyQualifiedId, parseId } from "@dxos/react-client/echo";
37
41
  import { osTranslations } from "@dxos/shell/react";
38
- import { ComplexMap as ComplexMap2, nonNullable, reduceGroupBy } from "@dxos/util";
42
+ import { ComplexMap as ComplexMap2, nonNullable as nonNullable2, reduceGroupBy } from "@dxos/util";
39
43
 
40
44
  // packages/plugins/plugin-space/src/components/AwaitingObject.tsx
41
45
  import { CheckCircle, CircleDashed, CircleNotch } from "@phosphor-icons/react";
42
46
  import React, { useEffect, useState } from "react";
43
47
  import { parseIntentPlugin, useResolvePlugin, parseNavigationPlugin, NavigationAction } from "@dxos/app-framework";
44
48
  import { useClient } from "@dxos/react-client";
45
- import { fullyQualifiedId, useQuery } from "@dxos/react-client/echo";
49
+ import { Filter, fullyQualifiedId, useQuery } from "@dxos/react-client/echo";
46
50
  import { Button, Toast, useTranslation } from "@dxos/react-ui";
47
51
  import { getSize, mx } from "@dxos/react-ui-theme";
48
52
  var WAIT_FOR_OBJECT_TIMEOUT = 18e4;
@@ -55,7 +59,7 @@ var AwaitingObject = ({ id }) => {
55
59
  const intentPlugin = useResolvePlugin(parseIntentPlugin);
56
60
  const navigationPlugin = useResolvePlugin(parseNavigationPlugin);
57
61
  const client = useClient();
58
- const objects = useQuery(client.spaces);
62
+ const objects = useQuery(client.spaces, Filter.all());
59
63
  useEffect(() => {
60
64
  if (!id) {
61
65
  return;
@@ -132,155 +136,29 @@ var AwaitingObject = ({ id }) => {
132
136
  })))));
133
137
  };
134
138
 
135
- // packages/plugins/plugin-space/src/components/CollectionMain.tsx
136
- import React2 from "react";
137
- import { useTranslation as useTranslation2 } from "@dxos/react-ui";
138
- import { baseSurface, descriptionText, mx as mx2 } from "@dxos/react-ui-theme";
139
- var CollectionMain = ({ collection }) => {
140
- const { t } = useTranslation2(SPACE_PLUGIN);
141
- return /* @__PURE__ */ React2.createElement("div", {
142
- role: "none",
143
- className: mx2(baseSurface, "min-bs-screen is-full flex items-center justify-center p-8"),
144
- "data-testid": "composer.firstRunMessage"
145
- }, /* @__PURE__ */ React2.createElement("p", {
146
- role: "alert",
147
- className: mx2(descriptionText, "border border-dashed border-neutral-400/50 rounded-lg p-8 font-normal text-lg max-is-[24rem] break-words")
148
- }, collection.name ?? t("unnamed collection label")));
149
- };
150
-
151
- // packages/plugins/plugin-space/src/components/CollectionSection.tsx
152
- import React3 from "react";
153
- import { useTranslation as useTranslation3 } from "@dxos/react-ui";
154
- var CollectionSection = ({ collection }) => {
155
- const { t } = useTranslation3(SPACE_PLUGIN);
156
- return /* @__PURE__ */ React3.createElement("div", {
157
- className: "min-bs-[3.5rem] grid grid-rows-subgrid grid-cols-subgrid items-center"
158
- }, /* @__PURE__ */ React3.createElement("span", {
159
- className: "truncate"
160
- }, collection.name ?? t("unnamed collection label")));
161
- };
162
-
163
- // packages/plugins/plugin-space/src/components/DefaultObjectSettings.tsx
164
- import React4 from "react";
165
- import { Input, useTranslation as useTranslation4 } from "@dxos/react-ui";
166
- var DefaultObjectSettings = ({ object }) => {
167
- const { t } = useTranslation4(SPACE_PLUGIN);
168
- return /* @__PURE__ */ React4.createElement("div", {
169
- role: "form",
170
- className: "flex flex-col w-full p-2 gap-1"
171
- }, /* @__PURE__ */ React4.createElement(Input.Root, null, /* @__PURE__ */ React4.createElement(Input.Label, null, t("name label")), /* @__PURE__ */ React4.createElement(Input.TextInput, {
172
- placeholder: t("name placeholder"),
173
- value: object.name ?? "",
174
- onChange: (event) => {
175
- object.name = event.target.value;
176
- }
177
- })));
178
- };
179
-
180
- // packages/plugins/plugin-space/src/components/JoinDialog.tsx
181
- import React5, { useCallback } from "react";
182
- import { LayoutAction, NavigationAction as NavigationAction2, useIntentDispatcher } from "@dxos/app-framework";
183
- import { useGraph } from "@dxos/plugin-graph";
184
- import { ObservabilityAction } from "@dxos/plugin-observability/meta";
185
- import { useSpaces } from "@dxos/react-client/echo";
186
- import { Dialog, useTranslation as useTranslation5 } from "@dxos/react-ui";
187
- import { JoinPanel } from "@dxos/shell/react";
188
- var JoinDialog = ({ navigableCollections, ...props }) => {
189
- const { t } = useTranslation5(SPACE_PLUGIN);
190
- const dispatch = useIntentDispatcher();
191
- const spaces = useSpaces();
192
- const { graph } = useGraph();
193
- const handleDone = useCallback(async (result) => {
194
- if (result?.spaceKey) {
195
- await Promise.all([
196
- dispatch({
197
- action: LayoutAction.SET_LAYOUT,
198
- data: {
199
- element: "toast",
200
- subject: {
201
- id: `${SPACE_PLUGIN}/join-success`,
202
- duration: 5e3,
203
- title: t("join success label"),
204
- closeLabel: t("dismiss label")
205
- }
206
- }
207
- }),
208
- dispatch({
209
- action: LayoutAction.SET_LAYOUT,
210
- data: {
211
- element: "dialog",
212
- state: false
213
- }
214
- })
215
- ]);
216
- }
217
- const space = spaces.find(({ key }) => result?.spaceKey?.equals(key));
218
- const target = result?.target || (navigableCollections ? space?.id : void 0);
219
- if (target) {
220
- await graph.waitForPath({
221
- target
222
- }).catch(() => {
223
- });
224
- await Promise.all([
225
- dispatch({
226
- action: NavigationAction2.OPEN,
227
- data: {
228
- activeParts: {
229
- main: [
230
- target
231
- ]
232
- }
233
- }
234
- }),
235
- dispatch({
236
- action: NavigationAction2.EXPOSE,
237
- data: {
238
- id: target
239
- }
240
- })
241
- ]);
242
- }
243
- if (space) {
244
- await dispatch({
245
- action: ObservabilityAction.SEND_EVENT,
246
- data: {
247
- name: "space.join",
248
- properties: {
249
- spaceId: space.id
250
- }
251
- }
252
- });
253
- }
254
- }, [
255
- dispatch,
256
- spaces
257
- ]);
258
- return /* @__PURE__ */ React5.createElement(Dialog.Content, null, /* @__PURE__ */ React5.createElement(JoinPanel, {
259
- ...props,
260
- exitActionParent: /* @__PURE__ */ React5.createElement(Dialog.Close, {
261
- asChild: true
262
- }),
263
- doneActionParent: /* @__PURE__ */ React5.createElement(Dialog.Close, {
264
- asChild: true
265
- }),
266
- onDone: handleDone
267
- }));
268
- };
269
-
270
- // packages/plugins/plugin-space/src/components/MenuFooter.tsx
271
- import { Planet } from "@phosphor-icons/react";
272
- import React6 from "react";
273
- import { getSpace as getSpace2 } from "@dxos/client/echo";
139
+ // packages/plugins/plugin-space/src/components/CreateDialog/CreateObjectDialog.tsx
140
+ import React3, { useCallback as useCallback2, useRef } from "react";
141
+ import { NavigationAction as NavigationAction2, useIntentDispatcher } from "@dxos/app-framework";
274
142
  import { useClient as useClient2 } from "@dxos/react-client";
275
- import { DropdownMenu, toLocalizedString, useTranslation as useTranslation6 } from "@dxos/react-ui";
143
+ import { getSpace as getSpace2, isReactiveObject as isReactiveObject2, isSpace as isSpace3, useSpaces } from "@dxos/react-client/echo";
144
+ import { Button as Button2, Dialog, Icon as Icon2, useTranslation as useTranslation3 } from "@dxos/react-ui";
145
+
146
+ // packages/plugins/plugin-space/src/components/CreateDialog/CreateObjectPanel.tsx
147
+ import React2, { useCallback, useState as useState2 } from "react";
148
+ import { getObjectAnnotation as getObjectAnnotation2, S } from "@dxos/echo-schema";
149
+ import { isSpace as isSpace2 } from "@dxos/react-client/echo";
150
+ import { Icon, IconButton, Input, toLocalizedString, useTranslation as useTranslation2 } from "@dxos/react-ui";
151
+ import { Form, InputHeader } from "@dxos/react-ui-form";
152
+ import { SearchList } from "@dxos/react-ui-searchlist";
153
+ import { nonNullable } from "@dxos/util";
276
154
 
277
155
  // packages/plugins/plugin-space/src/util.tsx
278
- import { NavigationAction as NavigationAction3 } from "@dxos/app-framework";
279
- import { create, isReactiveObject, getTypename, getSchema, getObjectAnnotation, EXPANDO_TYPENAME } from "@dxos/echo-schema";
156
+ import { EXPANDO_TYPENAME, getObjectAnnotation, getTypename } from "@dxos/echo-schema";
280
157
  import { invariant } from "@dxos/invariant";
158
+ import { getSchema, isReactiveObject } from "@dxos/live-object";
281
159
  import { Migrations } from "@dxos/migrations";
282
- import { ACTION_TYPE, ACTION_GROUP_TYPE, actionGroupSymbol, getGraph, cleanup, memoize } from "@dxos/plugin-graph";
283
- import { fullyQualifiedId as fullyQualifiedId2, getSpace, isEchoObject, isSpace, SpaceState } from "@dxos/react-client/echo";
160
+ import { ACTION_GROUP_TYPE, ACTION_TYPE, cleanup, getGraph, memoize } from "@dxos/plugin-graph";
161
+ import { Filter as Filter2, fullyQualifiedId as fullyQualifiedId2, getSpace, isEchoObject, isSpace, SpaceState } from "@dxos/react-client/echo";
284
162
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/plugins/plugin-space/src/util.tsx";
285
163
  var SPACES = `${SPACE_PLUGIN}-spaces`;
286
164
  var SPACE_TYPE = "dxos.org/type/Space";
@@ -288,7 +166,10 @@ var COMPOSER_SPACE_LOCK = "dxos.org/plugin/space/lock";
288
166
  var SHARED = "shared-spaces";
289
167
  var EMPTY_ARRAY = [];
290
168
  var memoizeQuery = (spaceOrEcho, filter, options) => {
291
- const key = isSpace(spaceOrEcho) ? spaceOrEcho.id : void 0;
169
+ const key = JSON.stringify({
170
+ space: isSpace(spaceOrEcho) ? spaceOrEcho.id : void 0,
171
+ filter: Filter2.from(filter).toProto()
172
+ });
292
173
  const query = memoize(() => isSpace(spaceOrEcho) ? spaceOrEcho.db.query(filter, options) : spaceOrEcho?.query(filter, options), key);
293
174
  const unsubscribe = memoize(() => query?.subscribe(), key);
294
175
  cleanup(() => unsubscribe?.());
@@ -380,69 +261,6 @@ var constructSpaceNode = ({ space, navigable = false, personal, namesCache, reso
380
261
  }
381
262
  };
382
263
  };
383
- var constructSpaceActionGroups = ({ space, navigable, dispatch }) => {
384
- const state = space.state.get();
385
- const hasPendingMigration = checkPendingMigration(space);
386
- const getId = (id) => `${id}/${space.id}`;
387
- if (state !== SpaceState.SPACE_READY || hasPendingMigration) {
388
- return [];
389
- }
390
- const collection = space.properties[CollectionType.typename];
391
- const actions = [
392
- {
393
- id: getId(SpaceAction.ADD_OBJECT),
394
- type: ACTION_GROUP_TYPE,
395
- data: actionGroupSymbol,
396
- properties: {
397
- label: [
398
- "create object in space label",
399
- {
400
- ns: SPACE_PLUGIN
401
- }
402
- ],
403
- icon: "ph--plus--regular",
404
- disposition: "toolbar",
405
- menuType: "searchList",
406
- testId: "spacePlugin.createObject"
407
- },
408
- nodes: [
409
- {
410
- id: getId(SpaceAction.ADD_OBJECT.replace("object", "collection")),
411
- type: ACTION_TYPE,
412
- data: () => dispatch([
413
- {
414
- plugin: SPACE_PLUGIN,
415
- action: SpaceAction.ADD_OBJECT,
416
- data: {
417
- target: collection,
418
- object: create(CollectionType, {
419
- objects: [],
420
- views: {}
421
- })
422
- }
423
- },
424
- ...navigable ? [
425
- {
426
- action: NavigationAction3.OPEN
427
- }
428
- ] : []
429
- ]),
430
- properties: {
431
- label: [
432
- "create collection label",
433
- {
434
- ns: SPACE_PLUGIN
435
- }
436
- ],
437
- icon: "ph--cards-three--regular",
438
- testId: "spacePlugin.createCollection"
439
- }
440
- }
441
- ]
442
- }
443
- ];
444
- return actions;
445
- };
446
264
  var constructSpaceActions = ({ space, dispatch, personal, migrating }) => {
447
265
  const state = space.state.get();
448
266
  const hasPendingMigration = checkPendingMigration(space);
@@ -477,6 +295,29 @@ var constructSpaceActions = ({ space, dispatch, personal, migrating }) => {
477
295
  if (state === SpaceState.SPACE_READY && !hasPendingMigration) {
478
296
  const locked = space.properties[COMPOSER_SPACE_LOCK];
479
297
  actions.push({
298
+ id: getId(SpaceAction.OPEN_CREATE_OBJECT),
299
+ type: ACTION_TYPE,
300
+ data: async () => {
301
+ await dispatch({
302
+ plugin: SPACE_PLUGIN,
303
+ action: SpaceAction.OPEN_CREATE_OBJECT,
304
+ data: {
305
+ target: space
306
+ }
307
+ });
308
+ },
309
+ properties: {
310
+ label: [
311
+ "create object in space label",
312
+ {
313
+ ns: SPACE_PLUGIN
314
+ }
315
+ ],
316
+ icon: "ph--plus--regular",
317
+ disposition: "toolbar",
318
+ testId: "spacePlugin.createObject"
319
+ }
320
+ }, {
480
321
  id: getId(SpaceAction.SHARE),
481
322
  type: ACTION_TYPE,
482
323
  data: async () => {
@@ -666,71 +507,36 @@ var createObjectNode = ({ object, space, navigable = false, resolve }) => {
666
507
  }
667
508
  };
668
509
  };
669
- var constructObjectActionGroups = ({ object, navigable, dispatch }) => {
670
- if (!(object instanceof CollectionType)) {
671
- return [];
672
- }
673
- const collection = object;
674
- const getId = (id) => `${id}/${fullyQualifiedId2(object)}`;
675
- const actions = [
676
- {
677
- id: getId(SpaceAction.ADD_OBJECT),
678
- type: ACTION_GROUP_TYPE,
679
- data: actionGroupSymbol,
680
- properties: {
681
- label: [
682
- "create object in collection label",
683
- {
684
- ns: SPACE_PLUGIN
685
- }
686
- ],
687
- icon: "ph--plus--regular",
688
- disposition: "toolbar",
689
- menuType: "searchList",
690
- testId: "spacePlugin.createObject"
691
- },
692
- nodes: [
693
- {
694
- id: getId(SpaceAction.ADD_OBJECT.replace("object", "collection")),
695
- type: ACTION_TYPE,
696
- data: () => dispatch([
697
- {
698
- plugin: SPACE_PLUGIN,
699
- action: SpaceAction.ADD_OBJECT,
700
- data: {
701
- target: collection,
702
- object: create(CollectionType, {
703
- objects: [],
704
- views: {}
705
- })
706
- }
707
- },
708
- ...navigable ? [
709
- {
710
- action: NavigationAction3.OPEN
711
- }
712
- ] : []
713
- ]),
714
- properties: {
715
- label: [
716
- "create collection label",
717
- {
718
- ns: SPACE_PLUGIN
719
- }
720
- ],
721
- icon: "ph--cards-three--regular",
722
- testId: "spacePlugin.createCollection"
723
- }
724
- }
725
- ]
726
- }
727
- ];
728
- return actions;
729
- };
730
510
  var constructObjectActions = ({ node, dispatch }) => {
731
511
  const object = node.data;
732
512
  const getId = (id) => `${id}/${fullyQualifiedId2(object)}`;
733
513
  const actions = [
514
+ ...object instanceof CollectionType ? [
515
+ {
516
+ id: getId(SpaceAction.ADD_OBJECT),
517
+ type: ACTION_TYPE,
518
+ data: async () => {
519
+ await dispatch({
520
+ plugin: SPACE_PLUGIN,
521
+ action: SpaceAction.OPEN_CREATE_OBJECT,
522
+ data: {
523
+ target: object
524
+ }
525
+ });
526
+ },
527
+ properties: {
528
+ label: [
529
+ "create object in collection label",
530
+ {
531
+ ns: SPACE_PLUGIN
532
+ }
533
+ ],
534
+ icon: "ph--plus--regular",
535
+ disposition: "toolbar",
536
+ testId: "spacePlugin.createObject"
537
+ }
538
+ }
539
+ ] : [],
734
540
  {
735
541
  id: getId(SpaceAction.RENAME_OBJECT),
736
542
  type: ACTION_TYPE,
@@ -843,7 +649,7 @@ var cloneObject = async (object, resolve, newSpace) => {
843
649
  const serializer = metadata.serializer;
844
650
  invariant(serializer, `No serializer for type: ${typename}`, {
845
651
  F: __dxlog_file,
846
- L: 634,
652
+ L: 544,
847
653
  S: void 0,
848
654
  A: [
849
655
  "serializer",
@@ -860,30 +666,427 @@ var cloneObject = async (object, resolve, newSpace) => {
860
666
  });
861
667
  };
862
668
 
863
- // packages/plugins/plugin-space/src/components/MenuFooter.tsx
864
- var MenuFooter = ({ object }) => {
865
- const { t } = useTranslation6(SPACE_PLUGIN);
669
+ // packages/plugins/plugin-space/src/components/CreateDialog/CreateObjectPanel.tsx
670
+ var CreateObjectPanel = ({ schemas, spaces, typename: initialTypename, target: initialTarget, name: initialName, defaultSpaceId, resolve, onCreateObject }) => {
671
+ const { t } = useTranslation2(SPACE_PLUGIN);
672
+ const [typename, setTypename] = useState2(initialTypename);
673
+ const [target, setTarget] = useState2(initialTarget);
674
+ const schema = schemas.find((schema2) => getObjectAnnotation2(schema2)?.typename === typename);
675
+ const options = schemas.map(getObjectAnnotation2).filter(nonNullable);
676
+ const handleClearSchema = useCallback(() => setTypename(void 0), []);
677
+ const handleClearTarget = useCallback(() => setTarget(void 0), []);
678
+ const handleCreateObject = useCallback(async ({ name }) => {
679
+ if (!schema || !target) {
680
+ return;
681
+ }
682
+ await onCreateObject?.({
683
+ schema,
684
+ target,
685
+ name
686
+ });
687
+ }, [
688
+ onCreateObject,
689
+ schema,
690
+ target
691
+ ]);
692
+ const schemaInput = /* @__PURE__ */ React2.createElement(SearchList.Root, {
693
+ label: t("schema input label"),
694
+ classNames: "flex flex-col grow overflow-hidden my-2 px-2"
695
+ }, /* @__PURE__ */ React2.createElement(SearchList.Input, {
696
+ autoFocus: true,
697
+ "data-testid": "create-object-form.schema-input",
698
+ placeholder: t("schema input placeholder"),
699
+ classNames: "px-1 my-2"
700
+ }), /* @__PURE__ */ React2.createElement(SearchList.Content, {
701
+ classNames: "max-bs-[24rem] overflow-auto"
702
+ }, options.map((option) => /* @__PURE__ */ React2.createElement(SearchList.Item, {
703
+ key: option.typename,
704
+ value: t("typename label", {
705
+ ns: option.typename,
706
+ defaultValue: option.typename
707
+ }),
708
+ onSelect: () => setTypename(option.typename),
709
+ classNames: "flex items-center gap-2"
710
+ }, /* @__PURE__ */ React2.createElement("span", {
711
+ className: "flex gap-2 items-center grow truncate"
712
+ }, /* @__PURE__ */ React2.createElement(Icon, {
713
+ icon: resolve?.(option.typename).icon ?? "ph--placeholder--regular",
714
+ size: 5
715
+ }), t("typename label", {
716
+ ns: option.typename,
717
+ defaultValue: option.typename
718
+ }))))));
719
+ const spaceInput = /* @__PURE__ */ React2.createElement(SearchList.Root, {
720
+ label: t("space input label"),
721
+ classNames: "flex flex-col grow overflow-hidden my-2 px-2"
722
+ }, /* @__PURE__ */ React2.createElement(SearchList.Input, {
723
+ autoFocus: true,
724
+ "data-testid": "create-object-form.space-input",
725
+ placeholder: t("space input placeholder"),
726
+ classNames: "px-1 my-2"
727
+ }), /* @__PURE__ */ React2.createElement(SearchList.Content, {
728
+ classNames: "max-bs-[24rem] overflow-auto"
729
+ }, spaces.map((space) => /* @__PURE__ */ React2.createElement(SearchList.Item, {
730
+ key: space.id,
731
+ value: toLocalizedString(getSpaceDisplayName(space, {
732
+ personal: space.id === defaultSpaceId
733
+ }), t),
734
+ onSelect: () => setTarget(space),
735
+ classNames: "flex items-center gap-2"
736
+ }, /* @__PURE__ */ React2.createElement("span", {
737
+ className: "grow truncate"
738
+ }, toLocalizedString(getSpaceDisplayName(space, {
739
+ personal: space.id === defaultSpaceId
740
+ }), t))))));
741
+ const form = /* @__PURE__ */ React2.createElement(Form, {
742
+ autoFocus: true,
743
+ values: {
744
+ name: initialName
745
+ },
746
+ schema: S.Struct({
747
+ name: S.optional(S.String)
748
+ }),
749
+ testId: "create-object-form",
750
+ onSave: handleCreateObject
751
+ });
752
+ return /* @__PURE__ */ React2.createElement("div", {
753
+ role: "form",
754
+ className: "flex flex-col gap-2"
755
+ }, target && /* @__PURE__ */ React2.createElement("div", {
756
+ role: "none",
757
+ className: "px-2"
758
+ }, /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(InputHeader, null, /* @__PURE__ */ React2.createElement(Input.Label, null, t(isSpace2(target) ? "creating in space label" : "creating in collection label"))), /* @__PURE__ */ React2.createElement("div", {
759
+ role: "none",
760
+ className: "flex gap-2"
761
+ }, /* @__PURE__ */ React2.createElement(Input.TextInput, {
762
+ disabled: true,
763
+ value: isSpace2(target) ? toLocalizedString(getSpaceDisplayName(target, {
764
+ personal: target.id === defaultSpaceId
765
+ }), t) : target.name || t("unnamed collection label")
766
+ }), /* @__PURE__ */ React2.createElement(IconButton, {
767
+ iconOnly: true,
768
+ icon: "ph--x--regular",
769
+ label: t("clear input label"),
770
+ onClick: handleClearTarget
771
+ })))), schema && /* @__PURE__ */ React2.createElement("div", {
772
+ role: "none",
773
+ className: "px-2"
774
+ }, /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(InputHeader, null, /* @__PURE__ */ React2.createElement(Input.Label, null, t("creating object type label"))), /* @__PURE__ */ React2.createElement("div", {
775
+ role: "none",
776
+ className: "flex gap-2"
777
+ }, /* @__PURE__ */ React2.createElement(Input.TextInput, {
778
+ disabled: true,
779
+ value: t("typename label", {
780
+ ns: schema.typename,
781
+ defaultValue: schema.typename
782
+ })
783
+ }), /* @__PURE__ */ React2.createElement(IconButton, {
784
+ iconOnly: true,
785
+ icon: "ph--x--regular",
786
+ label: t("clear input label"),
787
+ onClick: handleClearSchema
788
+ })))), !schema ? schemaInput : !target ? spaceInput : form);
789
+ };
790
+
791
+ // packages/plugins/plugin-space/src/components/CreateDialog/CreateObjectDialog.tsx
792
+ var CreateObjectDialog = ({ schemas, target, typename, name, navigableCollections, resolve }) => {
793
+ const closeRef = useRef(null);
794
+ const { t } = useTranslation3(SPACE_PLUGIN);
866
795
  const client = useClient2();
867
- const space = getSpace2(object);
868
- const spaceName = space ? getSpaceDisplayName(space, {
796
+ const spaces = useSpaces();
797
+ const dispatch = useIntentDispatcher();
798
+ const handleCreateObject = useCallback2(async ({ schema, target: _target, name: name2 }) => {
799
+ const target2 = isSpace3(_target) ? _target.properties[CollectionType.typename] : _target;
800
+ const createObjectAction = resolve?.(schema.typename)?.createObject;
801
+ if (!createObjectAction || !target2) {
802
+ return;
803
+ }
804
+ closeRef.current?.click();
805
+ const space = isSpace3(target2) ? target2 : getSpace2(target2);
806
+ const result = await dispatch({
807
+ action: createObjectAction,
808
+ data: {
809
+ name: name2,
810
+ space
811
+ }
812
+ });
813
+ const object = result?.data;
814
+ if (isReactiveObject2(object)) {
815
+ await dispatch([
816
+ {
817
+ plugin: SPACE_PLUGIN,
818
+ action: SpaceAction.ADD_OBJECT,
819
+ data: {
820
+ target: target2,
821
+ object
822
+ }
823
+ },
824
+ ...!(object instanceof CollectionType) || navigableCollections ? [
825
+ {
826
+ action: NavigationAction2.OPEN
827
+ }
828
+ ] : []
829
+ ]);
830
+ }
831
+ }, [
832
+ dispatch,
833
+ resolve
834
+ ]);
835
+ return (
836
+ // TODO(wittjosiah): The tablist dialog pattern is copied from @dxos/plugin-manager.
837
+ // Consider factoring it out to the tabs package.
838
+ /* @__PURE__ */ React3.createElement(Dialog.Content, {
839
+ classNames: "p-0 bs-content min-bs-[15rem] max-bs-full md:max-is-[40rem] overflow-hidden"
840
+ }, /* @__PURE__ */ React3.createElement("div", {
841
+ role: "none",
842
+ className: "flex justify-between pbs-3 pis-2 pie-3 @md:pbs-4 @md:pis-4 @md:pie-5"
843
+ }, /* @__PURE__ */ React3.createElement(Dialog.Title, null, t("create object dialog title")), /* @__PURE__ */ React3.createElement(Dialog.Close, {
844
+ asChild: true
845
+ }, /* @__PURE__ */ React3.createElement(Button2, {
846
+ ref: closeRef,
847
+ density: "fine",
848
+ variant: "ghost",
849
+ autoFocus: true
850
+ }, /* @__PURE__ */ React3.createElement(Icon2, {
851
+ icon: "ph--x--regular",
852
+ size: 4
853
+ })))), /* @__PURE__ */ React3.createElement("div", {
854
+ className: "p-4"
855
+ }, /* @__PURE__ */ React3.createElement(CreateObjectPanel, {
856
+ schemas,
857
+ spaces,
858
+ target,
859
+ typename,
860
+ name,
861
+ defaultSpaceId: client.spaces.default.id,
862
+ resolve,
863
+ onCreateObject: handleCreateObject
864
+ })))
865
+ );
866
+ };
867
+
868
+ // packages/plugins/plugin-space/src/components/CreateDialog/CreateSpaceDialog.tsx
869
+ import React4, { useCallback as useCallback3, useRef as useRef2 } from "react";
870
+ import { useIntentDispatcher as useIntentDispatcher2 } from "@dxos/app-framework";
871
+ import { Button as Button3, Dialog as Dialog2, Icon as Icon3, useTranslation as useTranslation4 } from "@dxos/react-ui";
872
+ import { Form as Form2 } from "@dxos/react-ui-form";
873
+ var initialValues = {
874
+ edgeReplication: true
875
+ };
876
+ var CreateSpaceDialog = () => {
877
+ const closeRef = useRef2(null);
878
+ const { t } = useTranslation4(SPACE_PLUGIN);
879
+ const dispatch = useIntentDispatcher2();
880
+ const handleCreateSpace = useCallback3(async (data) => {
881
+ const result = await dispatch({
882
+ action: SpaceAction.CREATE,
883
+ data
884
+ });
885
+ const target = result?.data.space;
886
+ if (target) {
887
+ await dispatch({
888
+ action: SpaceAction.OPEN_CREATE_OBJECT,
889
+ data: {
890
+ target
891
+ }
892
+ });
893
+ }
894
+ }, [
895
+ dispatch
896
+ ]);
897
+ return (
898
+ // TODO(wittjosiah): The tablist dialog pattern is copied from @dxos/plugin-manager.
899
+ // Consider factoring it out to the tabs package.
900
+ /* @__PURE__ */ React4.createElement(Dialog2.Content, {
901
+ classNames: "p-0 bs-content min-bs-[15rem] max-bs-full md:max-is-[40rem] overflow-hidden"
902
+ }, /* @__PURE__ */ React4.createElement("div", {
903
+ role: "none",
904
+ className: "flex justify-between pbs-3 pis-2 pie-3 @md:pbs-4 @md:pis-4 @md:pie-5"
905
+ }, /* @__PURE__ */ React4.createElement(Dialog2.Title, null, t("create space dialog title")), /* @__PURE__ */ React4.createElement(Dialog2.Close, {
906
+ asChild: true
907
+ }, /* @__PURE__ */ React4.createElement(Button3, {
908
+ ref: closeRef,
909
+ density: "fine",
910
+ variant: "ghost",
911
+ autoFocus: true
912
+ }, /* @__PURE__ */ React4.createElement(Icon3, {
913
+ icon: "ph--x--regular",
914
+ size: 4
915
+ })))), /* @__PURE__ */ React4.createElement("div", {
916
+ className: "p-4"
917
+ }, /* @__PURE__ */ React4.createElement(Form2, {
918
+ testId: "create-space-form",
919
+ values: initialValues,
920
+ schema: SpaceForm,
921
+ onSave: handleCreateSpace
922
+ })))
923
+ );
924
+ };
925
+
926
+ // packages/plugins/plugin-space/src/components/CollectionMain.tsx
927
+ import React5 from "react";
928
+ import { useTranslation as useTranslation5 } from "@dxos/react-ui";
929
+ import { baseSurface, descriptionText, mx as mx2 } from "@dxos/react-ui-theme";
930
+ var CollectionMain = ({ collection }) => {
931
+ const { t } = useTranslation5(SPACE_PLUGIN);
932
+ return /* @__PURE__ */ React5.createElement("div", {
933
+ role: "none",
934
+ className: mx2(baseSurface, "min-bs-screen is-full flex items-center justify-center p-8"),
935
+ "data-testid": "composer.firstRunMessage"
936
+ }, /* @__PURE__ */ React5.createElement("p", {
937
+ role: "alert",
938
+ className: mx2(descriptionText, "border border-dashed border-neutral-400/50 rounded-lg p-8 font-normal text-lg max-is-[24rem] break-words")
939
+ }, collection.name ?? t("unnamed collection label")));
940
+ };
941
+
942
+ // packages/plugins/plugin-space/src/components/CollectionSection.tsx
943
+ import React6 from "react";
944
+ import { useTranslation as useTranslation6 } from "@dxos/react-ui";
945
+ var CollectionSection = ({ collection }) => {
946
+ const { t } = useTranslation6(SPACE_PLUGIN);
947
+ return /* @__PURE__ */ React6.createElement("div", {
948
+ className: "min-bs-[3.5rem] grid grid-rows-subgrid grid-cols-subgrid items-center"
949
+ }, /* @__PURE__ */ React6.createElement("span", {
950
+ className: "truncate"
951
+ }, collection.name ?? t("unnamed collection label")));
952
+ };
953
+
954
+ // packages/plugins/plugin-space/src/components/DefaultObjectSettings.tsx
955
+ import React7 from "react";
956
+ import { Input as Input2, useTranslation as useTranslation7 } from "@dxos/react-ui";
957
+ var DefaultObjectSettings = ({ object }) => {
958
+ const { t } = useTranslation7(SPACE_PLUGIN);
959
+ return /* @__PURE__ */ React7.createElement("div", {
960
+ role: "form",
961
+ className: "flex flex-col w-full p-2 gap-1"
962
+ }, /* @__PURE__ */ React7.createElement(Input2.Root, null, /* @__PURE__ */ React7.createElement(Input2.Label, null, t("name label")), /* @__PURE__ */ React7.createElement(Input2.TextInput, {
963
+ placeholder: t("name placeholder"),
964
+ value: object.name ?? "",
965
+ onChange: (event) => {
966
+ object.name = event.target.value;
967
+ }
968
+ })));
969
+ };
970
+
971
+ // packages/plugins/plugin-space/src/components/JoinDialog.tsx
972
+ import React8, { useCallback as useCallback4 } from "react";
973
+ import { LayoutAction, NavigationAction as NavigationAction3, useIntentDispatcher as useIntentDispatcher3 } from "@dxos/app-framework";
974
+ import { useGraph } from "@dxos/plugin-graph";
975
+ import { ObservabilityAction } from "@dxos/plugin-observability/meta";
976
+ import { useSpaces as useSpaces2 } from "@dxos/react-client/echo";
977
+ import { Dialog as Dialog3, useTranslation as useTranslation8 } from "@dxos/react-ui";
978
+ import { JoinPanel } from "@dxos/shell/react";
979
+ var JoinDialog = ({ navigableCollections, ...props }) => {
980
+ const { t } = useTranslation8(SPACE_PLUGIN);
981
+ const dispatch = useIntentDispatcher3();
982
+ const spaces = useSpaces2();
983
+ const { graph } = useGraph();
984
+ const handleDone = useCallback4(async (result) => {
985
+ if (result?.spaceKey) {
986
+ await Promise.all([
987
+ dispatch({
988
+ action: LayoutAction.SET_LAYOUT,
989
+ data: {
990
+ element: "toast",
991
+ subject: {
992
+ id: `${SPACE_PLUGIN}/join-success`,
993
+ duration: 5e3,
994
+ title: t("join success label"),
995
+ closeLabel: t("dismiss label")
996
+ }
997
+ }
998
+ }),
999
+ dispatch({
1000
+ action: LayoutAction.SET_LAYOUT,
1001
+ data: {
1002
+ element: "dialog",
1003
+ state: false
1004
+ }
1005
+ })
1006
+ ]);
1007
+ }
1008
+ const space = spaces.find(({ key }) => result?.spaceKey?.equals(key));
1009
+ const target = result?.target || (navigableCollections ? space?.id : void 0);
1010
+ if (target) {
1011
+ await graph.waitForPath({
1012
+ target
1013
+ }).catch(() => {
1014
+ });
1015
+ await Promise.all([
1016
+ dispatch({
1017
+ action: NavigationAction3.OPEN,
1018
+ data: {
1019
+ activeParts: {
1020
+ main: [
1021
+ target
1022
+ ]
1023
+ }
1024
+ }
1025
+ }),
1026
+ dispatch({
1027
+ action: NavigationAction3.EXPOSE,
1028
+ data: {
1029
+ id: target
1030
+ }
1031
+ })
1032
+ ]);
1033
+ }
1034
+ if (space) {
1035
+ await dispatch({
1036
+ action: ObservabilityAction.SEND_EVENT,
1037
+ data: {
1038
+ name: "space.join",
1039
+ properties: {
1040
+ spaceId: space.id
1041
+ }
1042
+ }
1043
+ });
1044
+ }
1045
+ }, [
1046
+ dispatch,
1047
+ spaces
1048
+ ]);
1049
+ return /* @__PURE__ */ React8.createElement(Dialog3.Content, null, /* @__PURE__ */ React8.createElement(JoinPanel, {
1050
+ ...props,
1051
+ exitActionParent: /* @__PURE__ */ React8.createElement(Dialog3.Close, {
1052
+ asChild: true
1053
+ }),
1054
+ doneActionParent: /* @__PURE__ */ React8.createElement(Dialog3.Close, {
1055
+ asChild: true
1056
+ }),
1057
+ onDone: handleDone
1058
+ }));
1059
+ };
1060
+
1061
+ // packages/plugins/plugin-space/src/components/MenuFooter.tsx
1062
+ import { Planet } from "@phosphor-icons/react";
1063
+ import React9 from "react";
1064
+ import { getSpace as getSpace3 } from "@dxos/client/echo";
1065
+ import { useClient as useClient3 } from "@dxos/react-client";
1066
+ import { DropdownMenu, toLocalizedString as toLocalizedString2, useTranslation as useTranslation9 } from "@dxos/react-ui";
1067
+ var MenuFooter = ({ object }) => {
1068
+ const { t } = useTranslation9(SPACE_PLUGIN);
1069
+ const client = useClient3();
1070
+ const space = getSpace3(object);
1071
+ const spaceName = space ? getSpaceDisplayName(space, {
869
1072
  personal: client.spaces.default === space
870
1073
  }) : "";
871
- return space ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(DropdownMenu.Separator, null), /* @__PURE__ */ React6.createElement(DropdownMenu.GroupLabel, null, t("menu footer label")), /* @__PURE__ */ React6.createElement("dl", {
1074
+ return space ? /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(DropdownMenu.Separator, null), /* @__PURE__ */ React9.createElement(DropdownMenu.GroupLabel, null, t("menu footer label")), /* @__PURE__ */ React9.createElement("dl", {
872
1075
  className: "pis-2 mbe-2 text-xs grid grid-cols-[max-content_1fr] gap-2"
873
- }, /* @__PURE__ */ React6.createElement("dt", {
1076
+ }, /* @__PURE__ */ React9.createElement("dt", {
874
1077
  className: "uppercase text-[.75em] tracking-wide font-medium mbs-px self-start"
875
- }, t("location label")), /* @__PURE__ */ React6.createElement("dd", {
1078
+ }, t("location label")), /* @__PURE__ */ React9.createElement("dd", {
876
1079
  className: "line-clamp-3"
877
- }, /* @__PURE__ */ React6.createElement(Planet, {
1080
+ }, /* @__PURE__ */ React9.createElement(Planet, {
878
1081
  className: "inline-block mie-1"
879
- }), toLocalizedString(spaceName, t)))) : null;
1082
+ }), toLocalizedString2(spaceName, t)))) : null;
880
1083
  };
881
1084
 
882
1085
  // packages/plugins/plugin-space/src/components/PersistenceStatus.tsx
883
1086
  import { ArrowsCounterClockwise, CheckCircle as CheckCircle2, Warning } from "@phosphor-icons/react";
884
- import React7, { useEffect as useEffect2, useState as useState2 } from "react";
1087
+ import React10, { useEffect as useEffect2, useState as useState3 } from "react";
885
1088
  import { debounce } from "@dxos/async";
886
- import { Tooltip, useTranslation as useTranslation7 } from "@dxos/react-ui";
1089
+ import { Tooltip, useTranslation as useTranslation10 } from "@dxos/react-ui";
887
1090
  import { getSize as getSize2, mx as mx3, staticPlaceholderText, warningText } from "@dxos/react-ui-theme";
888
1091
  var Status;
889
1092
  (function(Status2) {
@@ -892,10 +1095,10 @@ var Status;
892
1095
  Status2[Status2["ERROR"] = 2] = "ERROR";
893
1096
  })(Status || (Status = {}));
894
1097
  var PersistenceStatus = ({ db }) => {
895
- const { t } = useTranslation7(SPACE_PLUGIN);
896
- const [displayMessage, setDisplayMessage] = useState2(false);
897
- const [status, naturalSetStatus] = useState2(0);
898
- const [prevStatus, setPrevStatus] = useState2(0);
1098
+ const { t } = useTranslation10(SPACE_PLUGIN);
1099
+ const [displayMessage, setDisplayMessage] = useState3(false);
1100
+ const [status, naturalSetStatus] = useState3(0);
1101
+ const [prevStatus, setPrevStatus] = useState3(0);
899
1102
  const _setStatus = debounce(naturalSetStatus, 500);
900
1103
  useEffect2(() => {
901
1104
  setPrevStatus(status);
@@ -909,49 +1112,49 @@ var PersistenceStatus = ({ db }) => {
909
1112
  ]);
910
1113
  switch (status) {
911
1114
  case 2:
912
- return /* @__PURE__ */ React7.createElement("div", {
1115
+ return /* @__PURE__ */ React10.createElement("div", {
913
1116
  className: "flex items-center"
914
- }, /* @__PURE__ */ React7.createElement(Warning, {
1117
+ }, /* @__PURE__ */ React10.createElement(Warning, {
915
1118
  className: mx3(getSize2(4), "me-1")
916
- }), /* @__PURE__ */ React7.createElement("span", {
1119
+ }), /* @__PURE__ */ React10.createElement("span", {
917
1120
  className: mx3("text-sm", warningText)
918
1121
  }, t("persistence error label")));
919
1122
  case 1:
920
- return /* @__PURE__ */ React7.createElement("div", {
1123
+ return /* @__PURE__ */ React10.createElement("div", {
921
1124
  className: "flex items-center"
922
- }, /* @__PURE__ */ React7.createElement(ArrowsCounterClockwise, {
1125
+ }, /* @__PURE__ */ React10.createElement(ArrowsCounterClockwise, {
923
1126
  className: mx3(getSize2(4), "me-1")
924
- }), /* @__PURE__ */ React7.createElement("span", {
1127
+ }), /* @__PURE__ */ React10.createElement("span", {
925
1128
  className: mx3("text-sm", staticPlaceholderText)
926
1129
  }, t("persistence pending label")));
927
1130
  case 0:
928
1131
  default:
929
- return /* @__PURE__ */ React7.createElement(Tooltip.Root, {
1132
+ return /* @__PURE__ */ React10.createElement(Tooltip.Root, {
930
1133
  delayDuration: 400
931
- }, /* @__PURE__ */ React7.createElement(Tooltip.Trigger, {
1134
+ }, /* @__PURE__ */ React10.createElement(Tooltip.Trigger, {
932
1135
  role: "status",
933
1136
  className: "flex items-center"
934
- }, /* @__PURE__ */ React7.createElement(CheckCircle2, {
1137
+ }, /* @__PURE__ */ React10.createElement(CheckCircle2, {
935
1138
  className: mx3(getSize2(4), "me-1")
936
- }), displayMessage && /* @__PURE__ */ React7.createElement("span", {
1139
+ }), displayMessage && /* @__PURE__ */ React10.createElement("span", {
937
1140
  className: mx3("text-sm", staticPlaceholderText)
938
- }, t("persisted locally label"))), /* @__PURE__ */ React7.createElement(Tooltip.Portal, null, /* @__PURE__ */ React7.createElement(Tooltip.Content, {
1141
+ }, t("persisted locally label"))), /* @__PURE__ */ React10.createElement(Tooltip.Portal, null, /* @__PURE__ */ React10.createElement(Tooltip.Content, {
939
1142
  classNames: "z-10"
940
- }, t("persisted locally message"), /* @__PURE__ */ React7.createElement(Tooltip.Arrow, null))));
1143
+ }, t("persisted locally message"), /* @__PURE__ */ React10.createElement(Tooltip.Arrow, null))));
941
1144
  }
942
1145
  };
943
1146
 
944
1147
  // packages/plugins/plugin-space/src/components/PopoverRenameObject.tsx
945
- import React8, { useCallback as useCallback2, useRef, useState as useState3 } from "react";
1148
+ import React11, { useCallback as useCallback5, useRef as useRef3, useState as useState4 } from "react";
946
1149
  import { log } from "@dxos/log";
947
- import { Button as Button2, Input as Input2, Popover, useTranslation as useTranslation8 } from "@dxos/react-ui";
1150
+ import { Button as Button4, Input as Input3, Popover, useTranslation as useTranslation11 } from "@dxos/react-ui";
948
1151
  var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/plugins/plugin-space/src/components/PopoverRenameObject.tsx";
949
1152
  var PopoverRenameObject = ({ object: obj }) => {
950
- const { t } = useTranslation8(SPACE_PLUGIN);
951
- const doneButton = useRef(null);
1153
+ const { t } = useTranslation11(SPACE_PLUGIN);
1154
+ const doneButton = useRef3(null);
952
1155
  const object = obj;
953
- const [name, setName] = useState3(object.name || object.title || "");
954
- const handleDone = useCallback2(() => {
1156
+ const [name, setName] = useState4(object.name || object.title || "");
1157
+ const handleDone = useCallback5(() => {
955
1158
  try {
956
1159
  object.name = name;
957
1160
  } catch {
@@ -972,23 +1175,23 @@ var PopoverRenameObject = ({ object: obj }) => {
972
1175
  object,
973
1176
  name
974
1177
  ]);
975
- return /* @__PURE__ */ React8.createElement("div", {
1178
+ return /* @__PURE__ */ React11.createElement("div", {
976
1179
  role: "none",
977
1180
  className: "p-1 flex gap-2"
978
- }, /* @__PURE__ */ React8.createElement("div", {
1181
+ }, /* @__PURE__ */ React11.createElement("div", {
979
1182
  role: "none",
980
1183
  className: "flex-1"
981
- }, /* @__PURE__ */ React8.createElement(Input2.Root, null, /* @__PURE__ */ React8.createElement(Input2.Label, {
1184
+ }, /* @__PURE__ */ React11.createElement(Input3.Root, null, /* @__PURE__ */ React11.createElement(Input3.Label, {
982
1185
  srOnly: true
983
- }, t("object name label")), /* @__PURE__ */ React8.createElement(Input2.TextInput, {
1186
+ }, t("object name label")), /* @__PURE__ */ React11.createElement(Input3.TextInput, {
984
1187
  placeholder: t("object title placeholder"),
985
1188
  value: name,
986
1189
  "data-testid": "spacePlugin.renameObject.input",
987
1190
  onChange: ({ target: { value } }) => setName(value),
988
1191
  onKeyDown: ({ key }) => key === "Enter" && doneButton.current?.click()
989
- }))), /* @__PURE__ */ React8.createElement(Popover.Close, {
1192
+ }))), /* @__PURE__ */ React11.createElement(Popover.Close, {
990
1193
  asChild: true
991
- }, /* @__PURE__ */ React8.createElement(Button2, {
1194
+ }, /* @__PURE__ */ React11.createElement(Button4, {
992
1195
  ref: doneButton,
993
1196
  classNames: "self-stretch",
994
1197
  onClick: handleDone
@@ -998,36 +1201,36 @@ var PopoverRenameObject = ({ object: obj }) => {
998
1201
  };
999
1202
 
1000
1203
  // packages/plugins/plugin-space/src/components/PopoverRenameSpace.tsx
1001
- import React9, { useCallback as useCallback3, useRef as useRef2, useState as useState4 } from "react";
1002
- import { Button as Button3, Input as Input3, Popover as Popover2, useTranslation as useTranslation9 } from "@dxos/react-ui";
1204
+ import React12, { useCallback as useCallback6, useRef as useRef4, useState as useState5 } from "react";
1205
+ import { Button as Button5, Input as Input4, Popover as Popover2, useTranslation as useTranslation12 } from "@dxos/react-ui";
1003
1206
  var PopoverRenameSpace = ({ space }) => {
1004
- const { t } = useTranslation9(SPACE_PLUGIN);
1005
- const doneButton = useRef2(null);
1006
- const [name, setName] = useState4(space.properties.name ?? "");
1007
- const handleDone = useCallback3(() => {
1207
+ const { t } = useTranslation12(SPACE_PLUGIN);
1208
+ const doneButton = useRef4(null);
1209
+ const [name, setName] = useState5(space.properties.name ?? "");
1210
+ const handleDone = useCallback6(() => {
1008
1211
  space.properties.name = name;
1009
1212
  }, [
1010
1213
  space,
1011
1214
  name
1012
1215
  ]);
1013
- return /* @__PURE__ */ React9.createElement("div", {
1216
+ return /* @__PURE__ */ React12.createElement("div", {
1014
1217
  role: "none",
1015
1218
  className: "p-1 flex gap-2"
1016
- }, /* @__PURE__ */ React9.createElement("div", {
1219
+ }, /* @__PURE__ */ React12.createElement("div", {
1017
1220
  role: "none",
1018
1221
  className: "flex-1"
1019
- }, /* @__PURE__ */ React9.createElement(Input3.Root, null, /* @__PURE__ */ React9.createElement(Input3.Label, {
1222
+ }, /* @__PURE__ */ React12.createElement(Input4.Root, null, /* @__PURE__ */ React12.createElement(Input4.Label, {
1020
1223
  srOnly: true
1021
- }, t("space name label")), /* @__PURE__ */ React9.createElement(Input3.TextInput, {
1224
+ }, t("space name label")), /* @__PURE__ */ React12.createElement(Input4.TextInput, {
1022
1225
  defaultValue: space.properties.name ?? "",
1023
1226
  placeholder: t("unnamed space label"),
1024
1227
  onChange: ({ target: { value } }) => setName(value),
1025
1228
  // TODO(wittjosiah): Ideally this should access the popover context to close the popover.
1026
1229
  // Currently this is not possible because Radix does not expose the popover context.
1027
1230
  onKeyDown: ({ key }) => key === "Enter" && doneButton.current?.click()
1028
- }))), /* @__PURE__ */ React9.createElement(Popover2.Close, {
1231
+ }))), /* @__PURE__ */ React12.createElement(Popover2.Close, {
1029
1232
  asChild: true
1030
- }, /* @__PURE__ */ React9.createElement(Button3, {
1233
+ }, /* @__PURE__ */ React12.createElement(Button5, {
1031
1234
  ref: doneButton,
1032
1235
  classNames: "self-stretch",
1033
1236
  onClick: handleDone
@@ -1037,12 +1240,12 @@ var PopoverRenameSpace = ({ space }) => {
1037
1240
  };
1038
1241
 
1039
1242
  // packages/plugins/plugin-space/src/components/ShareSpaceButton.tsx
1040
- import React10 from "react";
1041
- import { useIntentDispatcher as useIntentDispatcher2 } from "@dxos/app-framework";
1042
- import { IconButton, useTranslation as useTranslation10 } from "@dxos/react-ui";
1243
+ import React13 from "react";
1244
+ import { useIntentDispatcher as useIntentDispatcher4 } from "@dxos/app-framework";
1245
+ import { IconButton as IconButton2, useTranslation as useTranslation13 } from "@dxos/react-ui";
1043
1246
  var ShareSpaceButton = ({ space }) => {
1044
- const dispatch = useIntentDispatcher2();
1045
- return /* @__PURE__ */ React10.createElement(ShareSpaceButtonImpl, {
1247
+ const dispatch = useIntentDispatcher4();
1248
+ return /* @__PURE__ */ React13.createElement(ShareSpaceButtonImpl, {
1046
1249
  onClick: () => dispatch({
1047
1250
  action: SpaceAction.SHARE,
1048
1251
  data: {
@@ -1052,8 +1255,8 @@ var ShareSpaceButton = ({ space }) => {
1052
1255
  });
1053
1256
  };
1054
1257
  var ShareSpaceButtonImpl = ({ onClick }) => {
1055
- const { t } = useTranslation10(SPACE_PLUGIN);
1056
- return /* @__PURE__ */ React10.createElement(IconButton, {
1258
+ const { t } = useTranslation13(SPACE_PLUGIN);
1259
+ return /* @__PURE__ */ React13.createElement(IconButton2, {
1057
1260
  "data-testid": "spacePlugin.shareSpaceButton",
1058
1261
  icon: "ph--users--regular",
1059
1262
  label: t("share space label"),
@@ -1062,13 +1265,13 @@ var ShareSpaceButtonImpl = ({ onClick }) => {
1062
1265
  };
1063
1266
 
1064
1267
  // packages/plugins/plugin-space/src/components/SpacePresence.tsx
1065
- import React11, { useCallback as useCallback4, useEffect as useEffect3, useState as useState5 } from "react";
1268
+ import React14, { useCallback as useCallback7, useEffect as useEffect3, useState as useState6 } from "react";
1066
1269
  import { usePlugin } from "@dxos/app-framework";
1067
1270
  import { generateName } from "@dxos/display-name";
1068
- import { PublicKey, useClient as useClient3 } from "@dxos/react-client";
1069
- import { getSpace as getSpace3, useMembers, fullyQualifiedId as fullyQualifiedId3 } from "@dxos/react-client/echo";
1271
+ import { PublicKey, useClient as useClient4 } from "@dxos/react-client";
1272
+ import { getSpace as getSpace4, useMembers, fullyQualifiedId as fullyQualifiedId3 } from "@dxos/react-client/echo";
1070
1273
  import { useIdentity } from "@dxos/react-client/halo";
1071
- import { Avatar, AvatarGroup, AvatarGroupItem, Tooltip as Tooltip2, useTranslation as useTranslation11, List, ListItem, useDefaultValue } from "@dxos/react-ui";
1274
+ import { Avatar, AvatarGroup, AvatarGroupItem, Tooltip as Tooltip2, useTranslation as useTranslation14, List, ListItem, useDefaultValue } from "@dxos/react-ui";
1072
1275
  import { AttentionGlyph, useAttention } from "@dxos/react-ui-attention";
1073
1276
  import { ComplexMap, keyToFallback } from "@dxos/util";
1074
1277
  var REFRESH_INTERVAL = 5e3;
@@ -1077,17 +1280,17 @@ var noViewers = new ComplexMap(PublicKey.hash);
1077
1280
  var getName = (identity) => identity.profile?.displayName ?? generateName(identity.identityKey.toHex());
1078
1281
  var SpacePresence = ({ object, spaceKey }) => {
1079
1282
  const spacePlugin = usePlugin(SPACE_PLUGIN);
1080
- const client = useClient3();
1283
+ const client = useClient4();
1081
1284
  const identity = useIdentity();
1082
- const space = spaceKey ? client.spaces.get(spaceKey) : getSpace3(object);
1285
+ const space = spaceKey ? client.spaces.get(spaceKey) : getSpace4(object);
1083
1286
  const spaceMembers = useMembers(space?.key);
1084
- const [_moment, setMoment] = useState5(Date.now());
1287
+ const [_moment, setMoment] = useState6(Date.now());
1085
1288
  useEffect3(() => {
1086
1289
  const interval = setInterval(() => setMoment(Date.now()), REFRESH_INTERVAL);
1087
1290
  return () => clearInterval(interval);
1088
1291
  }, []);
1089
- const memberOnline = useCallback4((member) => member.presence === 1, []);
1090
- const memberIsNotSelf = useCallback4((member) => !identity?.identityKey.equals(member.identity.identityKey), [
1292
+ const memberOnline = useCallback7((member) => member.presence === 1, []);
1293
+ const memberIsNotSelf = useCallback7((member) => !identity?.identityKey.equals(member.identity.identityKey), [
1091
1294
  identity?.identityKey
1092
1295
  ]);
1093
1296
  if (!identity || !spacePlugin || !space) {
@@ -1105,7 +1308,7 @@ var SpacePresence = ({ object, spaceKey }) => {
1105
1308
  lastSeen
1106
1309
  };
1107
1310
  }).toSorted((a, b) => a.lastSeen - b.lastSeen);
1108
- return /* @__PURE__ */ React11.createElement(FullPresence, {
1311
+ return /* @__PURE__ */ React14.createElement(FullPresence, {
1109
1312
  members: membersForObject
1110
1313
  });
1111
1314
  };
@@ -1115,38 +1318,38 @@ var FullPresence = (props) => {
1115
1318
  if (members.length === 0) {
1116
1319
  return null;
1117
1320
  }
1118
- return /* @__PURE__ */ React11.createElement(AvatarGroup.Root, {
1321
+ return /* @__PURE__ */ React14.createElement(AvatarGroup.Root, {
1119
1322
  size,
1120
1323
  classNames: "mbs-2 mie-4",
1121
1324
  "data-testid": "spacePlugin.presence"
1122
- }, members.slice(0, 3).map((member, i) => /* @__PURE__ */ React11.createElement(Tooltip2.Root, {
1325
+ }, members.slice(0, 3).map((member, i) => /* @__PURE__ */ React14.createElement(Tooltip2.Root, {
1123
1326
  key: member.identity.identityKey.toHex()
1124
- }, /* @__PURE__ */ React11.createElement(Tooltip2.Trigger, null, /* @__PURE__ */ React11.createElement(PrensenceAvatar, {
1327
+ }, /* @__PURE__ */ React14.createElement(Tooltip2.Trigger, null, /* @__PURE__ */ React14.createElement(PrensenceAvatar, {
1125
1328
  identity: member.identity,
1126
1329
  group: true,
1127
1330
  match: member.currentlyAttended,
1128
1331
  index: members.length - i,
1129
1332
  onClick: () => onMemberClick?.(member)
1130
- })), /* @__PURE__ */ React11.createElement(Tooltip2.Portal, null, /* @__PURE__ */ React11.createElement(Tooltip2.Content, {
1333
+ })), /* @__PURE__ */ React14.createElement(Tooltip2.Portal, null, /* @__PURE__ */ React14.createElement(Tooltip2.Content, {
1131
1334
  side: "bottom"
1132
- }, /* @__PURE__ */ React11.createElement("span", null, getName(member.identity)), /* @__PURE__ */ React11.createElement(Tooltip2.Arrow, null))))), members.length > 3 && /* @__PURE__ */ React11.createElement(Tooltip2.Root, null, /* @__PURE__ */ React11.createElement(Tooltip2.Trigger, null, /* @__PURE__ */ React11.createElement(AvatarGroupItem.Root, {
1335
+ }, /* @__PURE__ */ React14.createElement("span", null, getName(member.identity)), /* @__PURE__ */ React14.createElement(Tooltip2.Arrow, null))))), members.length > 3 && /* @__PURE__ */ React14.createElement(Tooltip2.Root, null, /* @__PURE__ */ React14.createElement(Tooltip2.Trigger, null, /* @__PURE__ */ React14.createElement(AvatarGroupItem.Root, {
1133
1336
  status: "inactive"
1134
- }, /* @__PURE__ */ React11.createElement(Avatar.Frame, {
1337
+ }, /* @__PURE__ */ React14.createElement(Avatar.Frame, {
1135
1338
  style: {
1136
1339
  zIndex: members.length - 4
1137
1340
  }
1138
- }, /* @__PURE__ */ React11.createElement(Avatar.Fallback, {
1341
+ }, /* @__PURE__ */ React14.createElement(Avatar.Fallback, {
1139
1342
  text: `+${members.length - 3}`
1140
- })))), /* @__PURE__ */ React11.createElement(Tooltip2.Portal, null, /* @__PURE__ */ React11.createElement(Tooltip2.Content, {
1343
+ })))), /* @__PURE__ */ React14.createElement(Tooltip2.Portal, null, /* @__PURE__ */ React14.createElement(Tooltip2.Content, {
1141
1344
  side: "bottom"
1142
- }, /* @__PURE__ */ React11.createElement(Tooltip2.Arrow, null), /* @__PURE__ */ React11.createElement(List, {
1345
+ }, /* @__PURE__ */ React14.createElement(Tooltip2.Arrow, null), /* @__PURE__ */ React14.createElement(List, {
1143
1346
  classNames: "max-h-56 overflow-y-auto"
1144
- }, members.map((member) => /* @__PURE__ */ React11.createElement(ListItem.Root, {
1347
+ }, members.map((member) => /* @__PURE__ */ React14.createElement(ListItem.Root, {
1145
1348
  key: member.identity.identityKey.toHex(),
1146
1349
  classNames: "flex gap-2 items-center cursor-pointer mbe-2",
1147
1350
  onClick: () => onMemberClick?.(member),
1148
1351
  "data-testid": "identity-list-item"
1149
- }, /* @__PURE__ */ React11.createElement(PrensenceAvatar, {
1352
+ }, /* @__PURE__ */ React14.createElement(PrensenceAvatar, {
1150
1353
  identity: member.identity,
1151
1354
  showName: true,
1152
1355
  match: member.currentlyAttended
@@ -1156,10 +1359,10 @@ var PrensenceAvatar = ({ identity, showName, match, group, index, onClick }) =>
1156
1359
  const Root = group ? AvatarGroupItem.Root : Avatar.Root;
1157
1360
  const status = match ? "current" : "active";
1158
1361
  const fallbackValue = keyToFallback(identity.identityKey);
1159
- return /* @__PURE__ */ React11.createElement(Root, {
1362
+ return /* @__PURE__ */ React14.createElement(Root, {
1160
1363
  status,
1161
1364
  hue: identity.profile?.data?.hue || fallbackValue.hue
1162
- }, /* @__PURE__ */ React11.createElement(Avatar.Frame, {
1365
+ }, /* @__PURE__ */ React14.createElement(Avatar.Frame, {
1163
1366
  "data-testid": "spacePlugin.presence.member",
1164
1367
  "data-status": status,
1165
1368
  ...index ? {
@@ -1168,9 +1371,9 @@ var PrensenceAvatar = ({ identity, showName, match, group, index, onClick }) =>
1168
1371
  }
1169
1372
  } : {},
1170
1373
  onClick: () => onClick?.()
1171
- }, /* @__PURE__ */ React11.createElement(Avatar.Fallback, {
1374
+ }, /* @__PURE__ */ React14.createElement(Avatar.Fallback, {
1172
1375
  text: identity.profile?.data?.emoji || fallbackValue.emoji
1173
- })), showName && /* @__PURE__ */ React11.createElement(Avatar.Label, {
1376
+ })), showName && /* @__PURE__ */ React14.createElement(Avatar.Label, {
1174
1377
  classNames: "text-sm truncate pli-2"
1175
1378
  }, getName(identity)));
1176
1379
  };
@@ -1179,7 +1382,7 @@ var SmallPresenceLive = ({ id, viewers }) => {
1179
1382
  const moment = Date.now();
1180
1383
  return Array.from(viewers2.values()).filter(({ lastSeen }) => moment - lastSeen < ACTIVITY_DURATION);
1181
1384
  };
1182
- const [activeViewers, setActiveViewers] = useState5(viewers ? getActiveViewers(viewers) : []);
1385
+ const [activeViewers, setActiveViewers] = useState6(viewers ? getActiveViewers(viewers) : []);
1183
1386
  useEffect3(() => {
1184
1387
  if (viewers) {
1185
1388
  setActiveViewers(getActiveViewers(viewers));
@@ -1191,44 +1394,43 @@ var SmallPresenceLive = ({ id, viewers }) => {
1191
1394
  }, [
1192
1395
  viewers
1193
1396
  ]);
1194
- return /* @__PURE__ */ React11.createElement(SmallPresence, {
1397
+ return /* @__PURE__ */ React14.createElement(SmallPresence, {
1195
1398
  id,
1196
1399
  count: activeViewers.length
1197
1400
  });
1198
1401
  };
1199
1402
  var SmallPresence = ({ id, count }) => {
1200
- const { t } = useTranslation11(SPACE_PLUGIN);
1403
+ const { t } = useTranslation14(SPACE_PLUGIN);
1201
1404
  const { hasAttention, isAncestor, isRelated } = useAttention(id);
1202
1405
  const attention = hasAttention || isAncestor || isRelated;
1203
- return /* @__PURE__ */ React11.createElement(Tooltip2.Root, null, /* @__PURE__ */ React11.createElement(Tooltip2.Trigger, {
1406
+ return /* @__PURE__ */ React14.createElement(Tooltip2.Root, null, /* @__PURE__ */ React14.createElement(Tooltip2.Trigger, {
1204
1407
  asChild: true
1205
- }, /* @__PURE__ */ React11.createElement("div", {
1408
+ }, /* @__PURE__ */ React14.createElement("div", {
1206
1409
  role: "none",
1207
1410
  className: "flex",
1208
1411
  "data-attention": attention
1209
- }, /* @__PURE__ */ React11.createElement(AttentionGlyph, {
1412
+ }, /* @__PURE__ */ React14.createElement(AttentionGlyph, {
1210
1413
  presence: count > 1 ? "many" : count === 1 ? "one" : "none",
1211
1414
  classNames: "self-center mie-1"
1212
- }))), /* @__PURE__ */ React11.createElement(Tooltip2.Portal, null, /* @__PURE__ */ React11.createElement(Tooltip2.Content, {
1415
+ }))), /* @__PURE__ */ React14.createElement(Tooltip2.Portal, null, /* @__PURE__ */ React14.createElement(Tooltip2.Content, {
1213
1416
  side: "bottom",
1214
1417
  classNames: "z-[70]"
1215
- }, /* @__PURE__ */ React11.createElement("span", null, t("presence label", {
1418
+ }, /* @__PURE__ */ React14.createElement("span", null, t("presence label", {
1216
1419
  count
1217
- })), /* @__PURE__ */ React11.createElement(Tooltip2.Arrow, null))));
1420
+ })), /* @__PURE__ */ React14.createElement(Tooltip2.Arrow, null))));
1218
1421
  };
1219
1422
 
1220
1423
  // packages/plugins/plugin-space/src/components/SpacePluginSettings.tsx
1221
- import React12 from "react";
1222
- import { useIntentDispatcher as useIntentDispatcher3, useResolvePlugins } from "@dxos/app-framework";
1223
- import { Input as Input4, Select, toLocalizedString as toLocalizedString2, useTranslation as useTranslation12 } from "@dxos/react-ui";
1424
+ import React15 from "react";
1425
+ import { useIntentDispatcher as useIntentDispatcher5 } from "@dxos/app-framework";
1426
+ import { Input as Input5, useTranslation as useTranslation15 } from "@dxos/react-ui";
1224
1427
  import { DeprecatedFormInput } from "@dxos/react-ui-form";
1225
1428
  var SpacePluginSettings = ({ settings }) => {
1226
- const { t } = useTranslation12(SPACE_PLUGIN);
1227
- const dispatch = useIntentDispatcher3();
1228
- const plugins = useResolvePlugins(parseSpaceInitPlugin);
1229
- return /* @__PURE__ */ React12.createElement(React12.Fragment, null, /* @__PURE__ */ React12.createElement(DeprecatedFormInput, {
1429
+ const { t } = useTranslation15(SPACE_PLUGIN);
1430
+ const dispatch = useIntentDispatcher5();
1431
+ return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(DeprecatedFormInput, {
1230
1432
  label: t("show hidden spaces label")
1231
- }, /* @__PURE__ */ React12.createElement(Input4.Switch, {
1433
+ }, /* @__PURE__ */ React15.createElement(Input5.Switch, {
1232
1434
  checked: settings.showHidden,
1233
1435
  onCheckedChange: (checked) => dispatch({
1234
1436
  plugin: SPACE_PLUGIN,
@@ -1237,49 +1439,35 @@ var SpacePluginSettings = ({ settings }) => {
1237
1439
  state: !!checked
1238
1440
  }
1239
1441
  })
1240
- })), /* @__PURE__ */ React12.createElement(DeprecatedFormInput, {
1241
- label: t("default on space create label")
1242
- }, /* @__PURE__ */ React12.createElement(Select.Root, {
1243
- value: settings.onSpaceCreate,
1244
- onValueChange: (value) => {
1245
- settings.onSpaceCreate = value;
1246
- }
1247
- }, /* @__PURE__ */ React12.createElement(Select.TriggerButton, null), /* @__PURE__ */ React12.createElement(Select.Portal, null, /* @__PURE__ */ React12.createElement(Select.Content, null, /* @__PURE__ */ React12.createElement(Select.Viewport, null, plugins.map(({ provides: { space: { onSpaceCreate } } }) => /* @__PURE__ */ React12.createElement(Select.Option, {
1248
- key: onSpaceCreate.action,
1249
- value: onSpaceCreate.action
1250
- }, toLocalizedString2(onSpaceCreate.label, t)))))))));
1442
+ })));
1251
1443
  };
1252
1444
 
1253
1445
  // packages/plugins/plugin-space/src/components/SpaceSettings/SpaceSettingsDialog.tsx
1254
- import React14, { useState as useState7 } from "react";
1255
- import { useClient as useClient5 } from "@dxos/react-client";
1256
- import { Button as Button4, Dialog as Dialog2, Icon, toLocalizedString as toLocalizedString3, useTranslation as useTranslation14 } from "@dxos/react-ui";
1446
+ import React17, { useState as useState8 } from "react";
1447
+ import { useClient as useClient6 } from "@dxos/react-client";
1448
+ import { Button as Button6, Clipboard, Dialog as Dialog4, Icon as Icon4, toLocalizedString as toLocalizedString3, useTranslation as useTranslation17 } from "@dxos/react-ui";
1257
1449
  import { Tabs } from "@dxos/react-ui-tabs";
1258
- import { ClipboardProvider, SpacePanel } from "@dxos/shell/react";
1450
+ import { SpacePanel } from "@dxos/shell/react";
1259
1451
 
1260
1452
  // packages/plugins/plugin-space/src/components/SpaceSettings/SpaceSettingsPanel.tsx
1261
- import React13, { useCallback as useCallback5, useState as useState6 } from "react";
1453
+ import React16, { useCallback as useCallback8, useState as useState7 } from "react";
1262
1454
  import { log as log2 } from "@dxos/log";
1263
1455
  import { EdgeReplicationSetting } from "@dxos/protocols/proto/dxos/echo/metadata";
1264
- import { useClient as useClient4 } from "@dxos/react-client";
1265
- import { DeviceType, useDevices } from "@dxos/react-client/halo";
1266
- import { Input as Input5, useTranslation as useTranslation13 } from "@dxos/react-ui";
1456
+ import { useClient as useClient5 } from "@dxos/react-client";
1457
+ import { Input as Input6, useTranslation as useTranslation16 } from "@dxos/react-ui";
1267
1458
  import { DeprecatedFormInput as DeprecatedFormInput2 } from "@dxos/react-ui-form";
1268
1459
  var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/plugins/plugin-space/src/components/SpaceSettings/SpaceSettingsPanel.tsx";
1269
1460
  var SpaceSettingsPanel = ({ space }) => {
1270
- const { t } = useTranslation13(SPACE_PLUGIN);
1271
- const client = useClient4();
1272
- const devices = useDevices();
1273
- const managedDeviceAvailable = devices.find((device) => device.profile?.type === DeviceType.AGENT_MANAGED);
1274
- const edgeAgents = Boolean(client.config.values.runtime?.client?.edgeFeatures?.agents);
1275
- const edgeReplicationAvailable = edgeAgents && managedDeviceAvailable;
1276
- const [edgeReplication, setEdgeReplication] = useState6(space.internal.data.edgeReplication === EdgeReplicationSetting.ENABLED);
1277
- const toggleEdgeReplication = useCallback5(async (next) => {
1461
+ const { t } = useTranslation16(SPACE_PLUGIN);
1462
+ const client = useClient5();
1463
+ const edgeEnabled = Boolean(client.config.values.runtime?.client?.edgeFeatures?.echoReplicator);
1464
+ const [edgeReplication, setEdgeReplication] = useState7(space.internal.data.edgeReplication === EdgeReplicationSetting.ENABLED);
1465
+ const toggleEdgeReplication = useCallback8(async (next) => {
1278
1466
  setEdgeReplication(next);
1279
1467
  await space?.internal.setEdgeReplicationPreference(next ? EdgeReplicationSetting.ENABLED : EdgeReplicationSetting.DISABLED).catch((err) => {
1280
1468
  log2.catch(err, void 0, {
1281
1469
  F: __dxlog_file3,
1282
- L: 39,
1470
+ L: 35,
1283
1471
  S: void 0,
1284
1472
  C: (f, a) => f(...a)
1285
1473
  });
@@ -1288,116 +1476,247 @@ var SpaceSettingsPanel = ({ space }) => {
1288
1476
  }, [
1289
1477
  space
1290
1478
  ]);
1291
- return /* @__PURE__ */ React13.createElement("div", {
1479
+ return /* @__PURE__ */ React16.createElement("div", {
1292
1480
  role: "form",
1293
1481
  className: "flex flex-col"
1294
- }, /* @__PURE__ */ React13.createElement(DeprecatedFormInput2, {
1482
+ }, /* @__PURE__ */ React16.createElement(DeprecatedFormInput2, {
1295
1483
  label: t("name label")
1296
- }, /* @__PURE__ */ React13.createElement(Input5.TextInput, {
1484
+ }, /* @__PURE__ */ React16.createElement(Input6.TextInput, {
1297
1485
  placeholder: t("unnamed space label"),
1298
1486
  value: space.properties.name ?? "",
1299
1487
  onChange: (event) => {
1300
1488
  space.properties.name = event.target.value;
1301
1489
  }
1302
- })), edgeReplicationAvailable && /* @__PURE__ */ React13.createElement(DeprecatedFormInput2, {
1490
+ })), edgeEnabled && /* @__PURE__ */ React16.createElement(DeprecatedFormInput2, {
1303
1491
  label: t("edge replication label")
1304
- }, /* @__PURE__ */ React13.createElement(Input5.Switch, {
1492
+ }, /* @__PURE__ */ React16.createElement(Input6.Switch, {
1305
1493
  checked: edgeReplication,
1306
1494
  onCheckedChange: toggleEdgeReplication
1307
1495
  })));
1308
1496
  };
1309
1497
 
1310
- // packages/plugins/plugin-space/src/components/SpaceSettings/SpaceSettingsDialog.tsx
1311
- var SpaceSettingsDialog = ({ space, target, createInvitationUrl, initialTab = "members", namesCache }) => {
1312
- const { t } = useTranslation14(SPACE_PLUGIN);
1313
- const client = useClient5();
1314
- const [tabsActivePart, setTabsActivePart] = useState7("list");
1315
- const [selected, setSelected] = useState7(initialTab);
1316
- const locked = space.properties[COMPOSER_SPACE_LOCK];
1317
- const name = getSpaceDisplayName(space, {
1318
- personal: client.spaces.default === space,
1319
- namesCache
1320
- });
1321
- return (
1322
- // TODO(wittjosiah): The tablist dialog pattern is copied from @dxos/plugin-manager.
1323
- // Consider factoring it out to the tabs package.
1324
- /* @__PURE__ */ React14.createElement(Dialog2.Content, {
1325
- classNames: "p-0 bs-content min-bs-[15rem] max-bs-full md:max-is-[40rem] overflow-hidden"
1326
- }, /* @__PURE__ */ React14.createElement("div", {
1327
- role: "none",
1328
- className: "flex justify-between pbs-3 pis-2 pie-3 @md:pbs-4 @md:pis-4 @md:pie-5"
1329
- }, /* @__PURE__ */ React14.createElement(Dialog2.Title, {
1330
- onClick: () => setTabsActivePart("list"),
1331
- "aria-description": t("click to return to tablist description"),
1332
- classNames: "flex cursor-pointer items-center group/title"
1333
- }, /* @__PURE__ */ React14.createElement(Icon, {
1334
- icon: "ph--caret-left--regular",
1335
- size: 4,
1336
- classNames: [
1337
- "@md:hidden",
1338
- tabsActivePart === "list" && "invisible"
1339
- ]
1340
- }), /* @__PURE__ */ React14.createElement("span", {
1341
- className: tabsActivePart !== "list" ? "group-hover/title:underline @md:group-hover/title:no-underline underline-offset-4 decoration-1" : ""
1342
- }, toLocalizedString3(name, t))), /* @__PURE__ */ React14.createElement(Dialog2.Close, {
1343
- asChild: true
1344
- }, /* @__PURE__ */ React14.createElement(Button4, {
1345
- density: "fine",
1346
- variant: "ghost",
1347
- autoFocus: true
1348
- }, /* @__PURE__ */ React14.createElement(Icon, {
1349
- icon: "ph--x--regular",
1350
- size: 3
1351
- })))), /* @__PURE__ */ React14.createElement(Tabs.Root, {
1352
- orientation: "vertical",
1353
- value: selected,
1354
- onValueChange: setSelected,
1355
- activePart: tabsActivePart,
1356
- onActivePartChange: setTabsActivePart,
1357
- classNames: "flex flex-col flex-1 mbs-2"
1358
- }, /* @__PURE__ */ React14.createElement(Tabs.Viewport, {
1359
- classNames: "flex-1 min-bs-0"
1360
- }, /* @__PURE__ */ React14.createElement("div", {
1361
- role: "none",
1362
- className: "overflow-y-auto pli-3 @md:pis-2 @md:pie-0 mbe-4 border-r border-separator"
1363
- }, /* @__PURE__ */ React14.createElement(Tabs.Tablist, {
1364
- classNames: "flex flex-col max-bs-none min-is-[200px] gap-4 overflow-y-auto"
1365
- }, /* @__PURE__ */ React14.createElement("div", {
1366
- role: "none",
1367
- className: "flex flex-col ml-1"
1368
- }, /* @__PURE__ */ React14.createElement(Tabs.Tab, {
1369
- value: "settings"
1370
- }, t("settings tab label")), /* @__PURE__ */ React14.createElement(Tabs.Tab, {
1371
- value: "members",
1372
- disabled: locked
1373
- }, t("members tab label"))))), /* @__PURE__ */ React14.createElement(Tabs.Tabpanel, {
1374
- value: "settings",
1375
- classNames: "pli-3 @md:pli-5 max-bs-dvh overflow-y-auto"
1376
- }, /* @__PURE__ */ React14.createElement(SpaceSettingsPanel, {
1377
- space
1378
- })), /* @__PURE__ */ React14.createElement(Tabs.Tabpanel, {
1379
- value: "members",
1380
- classNames: "pli-3 @md:pli-5 max-bs-dvh overflow-y-auto"
1381
- }, /* @__PURE__ */ React14.createElement(ClipboardProvider, null, /* @__PURE__ */ React14.createElement(SpacePanel, {
1382
- space,
1383
- hideHeading: true,
1384
- target,
1385
- createInvitationUrl
1386
- }))))))
1387
- );
1498
+ // packages/plugins/plugin-space/src/components/SpaceSettings/SpaceSettingsDialog.tsx
1499
+ var SpaceSettingsDialog = ({ space, target, createInvitationUrl, initialTab = "members", namesCache }) => {
1500
+ const { t } = useTranslation17(SPACE_PLUGIN);
1501
+ const client = useClient6();
1502
+ const [tabsActivePart, setTabsActivePart] = useState8("list");
1503
+ const [selected, setSelected] = useState8(initialTab);
1504
+ const locked = space.properties[COMPOSER_SPACE_LOCK];
1505
+ const name = getSpaceDisplayName(space, {
1506
+ personal: client.spaces.default === space,
1507
+ namesCache
1508
+ });
1509
+ return (
1510
+ // TODO(wittjosiah): The tablist dialog pattern is copied from @dxos/plugin-manager.
1511
+ // Consider factoring it out to the tabs package.
1512
+ /* @__PURE__ */ React17.createElement(Dialog4.Content, {
1513
+ classNames: "p-0 bs-content min-bs-[15rem] max-bs-full md:max-is-[40rem] overflow-hidden"
1514
+ }, /* @__PURE__ */ React17.createElement("div", {
1515
+ role: "none",
1516
+ className: "flex justify-between pbs-3 pis-2 pie-3 @md:pbs-4 @md:pis-4 @md:pie-5"
1517
+ }, /* @__PURE__ */ React17.createElement(Dialog4.Title, {
1518
+ onClick: () => setTabsActivePart("list"),
1519
+ "aria-description": t("click to return to tablist description"),
1520
+ classNames: "flex cursor-pointer items-center group/title"
1521
+ }, /* @__PURE__ */ React17.createElement(Icon4, {
1522
+ icon: "ph--caret-left--regular",
1523
+ size: 4,
1524
+ classNames: [
1525
+ "@md:hidden",
1526
+ tabsActivePart === "list" && "invisible"
1527
+ ]
1528
+ }), /* @__PURE__ */ React17.createElement("span", {
1529
+ className: tabsActivePart !== "list" ? "group-hover/title:underline @md:group-hover/title:no-underline underline-offset-4 decoration-1" : ""
1530
+ }, toLocalizedString3(name, t))), /* @__PURE__ */ React17.createElement(Dialog4.Close, {
1531
+ asChild: true
1532
+ }, /* @__PURE__ */ React17.createElement(Button6, {
1533
+ density: "fine",
1534
+ variant: "ghost",
1535
+ autoFocus: true
1536
+ }, /* @__PURE__ */ React17.createElement(Icon4, {
1537
+ icon: "ph--x--regular",
1538
+ size: 4
1539
+ })))), /* @__PURE__ */ React17.createElement(Tabs.Root, {
1540
+ orientation: "vertical",
1541
+ value: selected,
1542
+ onValueChange: setSelected,
1543
+ activePart: tabsActivePart,
1544
+ onActivePartChange: setTabsActivePart,
1545
+ classNames: "flex flex-col flex-1 mbs-2"
1546
+ }, /* @__PURE__ */ React17.createElement(Tabs.Viewport, {
1547
+ classNames: "flex-1 min-bs-0"
1548
+ }, /* @__PURE__ */ React17.createElement("div", {
1549
+ role: "none",
1550
+ className: "overflow-y-auto pli-3 @md:pis-2 @md:pie-0 mbe-4 border-r border-separator"
1551
+ }, /* @__PURE__ */ React17.createElement(Tabs.Tablist, {
1552
+ classNames: "flex flex-col max-bs-none min-is-[200px] gap-4 overflow-y-auto"
1553
+ }, /* @__PURE__ */ React17.createElement("div", {
1554
+ role: "none",
1555
+ className: "flex flex-col ml-1"
1556
+ }, /* @__PURE__ */ React17.createElement(Tabs.Tab, {
1557
+ value: "settings"
1558
+ }, t("settings tab label")), /* @__PURE__ */ React17.createElement(Tabs.Tab, {
1559
+ value: "members",
1560
+ disabled: locked
1561
+ }, t("members tab label"))))), /* @__PURE__ */ React17.createElement(Tabs.Tabpanel, {
1562
+ value: "settings",
1563
+ classNames: "pli-3 @md:pli-5 max-bs-dvh overflow-y-auto"
1564
+ }, /* @__PURE__ */ React17.createElement(SpaceSettingsPanel, {
1565
+ space
1566
+ })), /* @__PURE__ */ React17.createElement(Tabs.Tabpanel, {
1567
+ value: "members",
1568
+ classNames: "pli-3 @md:pli-5 max-bs-dvh overflow-y-auto"
1569
+ }, /* @__PURE__ */ React17.createElement(Clipboard.Provider, null, /* @__PURE__ */ React17.createElement(SpacePanel, {
1570
+ space,
1571
+ hideHeading: true,
1572
+ target,
1573
+ createInvitationUrl
1574
+ }))))))
1575
+ );
1576
+ };
1577
+
1578
+ // packages/plugins/plugin-space/src/components/SyncStatus/InlineSyncStatus.tsx
1579
+ import React18, { useEffect as useEffect5, useMemo, useState as useState10 } from "react";
1580
+ import { QueryEdgeStatusResponse } from "@dxos/protocols/proto/dxos/client/services";
1581
+ import { EdgeReplicationSetting as EdgeReplicationSetting2 } from "@dxos/protocols/proto/dxos/echo/metadata";
1582
+ import { useClient as useClient8 } from "@dxos/react-client";
1583
+ import { Icon as Icon5, useTranslation as useTranslation18 } from "@dxos/react-ui";
1584
+
1585
+ // packages/plugins/plugin-space/src/components/SyncStatus/sync-state.ts
1586
+ import { useEffect as useEffect4, useState as useState9 } from "react";
1587
+ import { Context } from "@dxos/context";
1588
+ import { EdgeService } from "@dxos/protocols";
1589
+ import { useClient as useClient7 } from "@dxos/react-client";
1590
+ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/plugins/plugin-space/src/components/SyncStatus/sync-state.ts";
1591
+ var createEmptyEdgeSyncState = () => ({
1592
+ missingOnLocal: 0,
1593
+ missingOnRemote: 0,
1594
+ localDocumentCount: 0,
1595
+ remoteDocumentCount: 0,
1596
+ differentDocuments: 0
1597
+ });
1598
+ var getSyncSummary = (syncMap) => {
1599
+ return Object.entries(syncMap).reduce((summary, [_spaceId, peerState]) => {
1600
+ summary.missingOnLocal += peerState.missingOnLocal;
1601
+ summary.missingOnRemote += peerState.missingOnRemote;
1602
+ summary.localDocumentCount += peerState.localDocumentCount;
1603
+ summary.remoteDocumentCount += peerState.remoteDocumentCount;
1604
+ summary.differentDocuments += peerState.differentDocuments;
1605
+ return summary;
1606
+ }, createEmptyEdgeSyncState());
1607
+ };
1608
+ var isEdgePeerId = (peerId, spaceId) => peerId.startsWith(`${EdgeService.AUTOMERGE_REPLICATOR}:${spaceId}`);
1609
+ var useSyncState = () => {
1610
+ const client = useClient7();
1611
+ const [spaceState, setSpaceState] = useState9({});
1612
+ useEffect4(() => {
1613
+ const ctx = new Context(void 0, {
1614
+ F: __dxlog_file4,
1615
+ L: 48
1616
+ });
1617
+ const createSubscriptions = (spaces) => {
1618
+ for (const space of spaces) {
1619
+ if (spaceState[space.id]) {
1620
+ continue;
1621
+ }
1622
+ ctx.onDispose(space.crud.subscribeToSyncState(ctx, ({ peers = [] }) => {
1623
+ const syncState = peers.find((state) => isEdgePeerId(state.peerId, space.id));
1624
+ if (syncState) {
1625
+ setSpaceState((spaceState2) => ({
1626
+ ...spaceState2,
1627
+ [space.id]: syncState
1628
+ }));
1629
+ }
1630
+ }));
1631
+ }
1632
+ };
1633
+ createSubscriptions(client.spaces.get());
1634
+ client.spaces.subscribe((spaces) => {
1635
+ createSubscriptions(spaces);
1636
+ });
1637
+ return () => {
1638
+ void ctx.dispose();
1639
+ };
1640
+ }, [
1641
+ client
1642
+ ]);
1643
+ return spaceState;
1644
+ };
1645
+ var useSpaceSyncState = (space) => {
1646
+ const [spaceState, setSpaceState] = useState9();
1647
+ useEffect4(() => {
1648
+ const ctx = new Context(void 0, {
1649
+ F: __dxlog_file4,
1650
+ L: 87
1651
+ });
1652
+ space.crud.subscribeToSyncState(ctx, ({ peers = [] }) => {
1653
+ const syncState = peers.find((state) => isEdgePeerId(state.peerId, space.id));
1654
+ if (syncState) {
1655
+ setSpaceState(syncState);
1656
+ }
1657
+ });
1658
+ return () => {
1659
+ void ctx.dispose();
1660
+ };
1661
+ }, [
1662
+ space
1663
+ ]);
1664
+ return spaceState;
1665
+ };
1666
+
1667
+ // packages/plugins/plugin-space/src/components/SyncStatus/InlineSyncStatus.tsx
1668
+ var useEdgeStatus = () => {
1669
+ const [status, setStatus] = useState10(QueryEdgeStatusResponse.EdgeStatus.NOT_CONNECTED);
1670
+ const client = useClient8();
1671
+ useEffect5(() => {
1672
+ client.services.services.EdgeAgentService?.queryEdgeStatus().subscribe(({ status: status2 }) => {
1673
+ setStatus(status2);
1674
+ });
1675
+ }, [
1676
+ client
1677
+ ]);
1678
+ return status;
1679
+ };
1680
+ var InlineSyncStatus = ({ space }) => {
1681
+ const connectedToEdge = useEdgeStatus() === QueryEdgeStatusResponse.EdgeStatus.CONNECTED;
1682
+ const edgeSyncEnabled = space.internal.data.edgeReplication === EdgeReplicationSetting2.ENABLED;
1683
+ const syncState = useSpaceSyncState(space);
1684
+ if (!connectedToEdge || !edgeSyncEnabled || !syncState || syncState.missingOnLocal === 0) {
1685
+ return null;
1686
+ }
1687
+ return /* @__PURE__ */ React18.createElement(InlineSyncStatusIndicator, null);
1688
+ };
1689
+ var InlineSyncStatusIndicator = () => {
1690
+ const { t } = useTranslation18(SPACE_PLUGIN);
1691
+ const animationProps = useMemo(() => ({
1692
+ // Synchronize animations.
1693
+ animationDelay: `-${Date.now() % 2e3}ms`
1694
+ }), []);
1695
+ return /* @__PURE__ */ React18.createElement("div", {
1696
+ role: "status",
1697
+ "aria-label": t("syncing message"),
1698
+ className: "flex items-center"
1699
+ }, /* @__PURE__ */ React18.createElement(Icon5, {
1700
+ icon: "ph--circle-notch--regular",
1701
+ size: 3,
1702
+ style: animationProps,
1703
+ classNames: "text-subdued animate-[spin_2s_linear_infinite]"
1704
+ }));
1388
1705
  };
1389
1706
 
1390
1707
  // packages/plugins/plugin-space/src/components/SyncStatus/SyncStatus.tsx
1391
- import React16, { useEffect as useEffect6, useState as useState10 } from "react";
1708
+ import React20, { useCallback as useCallback9, useEffect as useEffect7, useState as useState12 } from "react";
1392
1709
  import { StatusBar } from "@dxos/plugin-status-bar";
1393
- import { useClient as useClient7 } from "@dxos/react-client";
1394
- import { Icon as Icon3, Popover as Popover3, useTranslation as useTranslation15 } from "@dxos/react-ui";
1710
+ import { useClient as useClient10 } from "@dxos/react-client";
1711
+ import { Icon as Icon7, Input as Input7, Popover as Popover3, useTranslation as useTranslation20 } from "@dxos/react-ui";
1395
1712
  import { SyntaxHighlighter } from "@dxos/react-ui-syntax-highlighter";
1396
1713
  import { mx as mx5 } from "@dxos/react-ui-theme";
1397
1714
 
1398
1715
  // packages/plugins/plugin-space/src/components/SyncStatus/Space.tsx
1399
- import React15, { useEffect as useEffect4, useState as useState8 } from "react";
1400
- import { Icon as Icon2 } from "@dxos/react-ui";
1716
+ import React19, { useEffect as useEffect6, useState as useState11 } from "react";
1717
+ import { useClient as useClient9 } from "@dxos/react-client";
1718
+ import { useSpace } from "@dxos/react-client/echo";
1719
+ import { Icon as Icon6, toLocalizedString as toLocalizedString4, useTranslation as useTranslation19 } from "@dxos/react-ui";
1401
1720
  import { mx as mx4 } from "@dxos/react-ui-theme";
1402
1721
  var SYNC_STALLED_TIMEOUT = 5e3;
1403
1722
  var styles = {
@@ -1406,9 +1725,9 @@ var styles = {
1406
1725
  barHover: "dark:hover:bg-green-500"
1407
1726
  };
1408
1727
  var useActive = (count) => {
1409
- const [current, setCurrent] = useState8(count);
1410
- const [active, setActive] = useState8(false);
1411
- useEffect4(() => {
1728
+ const [current, setCurrent] = useState11(count);
1729
+ const [active, setActive] = useState11(false);
1730
+ useEffect6(() => {
1412
1731
  let t;
1413
1732
  if (count !== current) {
1414
1733
  setActive(true);
@@ -1428,20 +1747,38 @@ var useActive = (count) => {
1428
1747
  ]);
1429
1748
  return active;
1430
1749
  };
1431
- var SpaceRow = ({ spaceId, state: { localDocumentCount, remoteDocumentCount, missingOnLocal, missingOnRemote } }) => {
1750
+ var SpaceRowContainer = ({ spaceId, state }) => {
1751
+ const { t } = useTranslation19(SPACE_PLUGIN);
1752
+ const client = useClient9();
1753
+ const space = useSpace(spaceId);
1754
+ if (!space) {
1755
+ return null;
1756
+ }
1757
+ const spaceName = toLocalizedString4(getSpaceDisplayName(space, {
1758
+ personal: space === client.spaces.default
1759
+ }), t);
1760
+ return /* @__PURE__ */ React19.createElement(SpaceRow, {
1761
+ spaceId,
1762
+ spaceName,
1763
+ state
1764
+ });
1765
+ };
1766
+ var SpaceRow = ({ spaceId, spaceName, state: { localDocumentCount, remoteDocumentCount, missingOnLocal, missingOnRemote } }) => {
1432
1767
  const downActive = useActive(localDocumentCount);
1433
1768
  const upActive = useActive(remoteDocumentCount);
1434
- return /* @__PURE__ */ React15.createElement("div", {
1435
- className: mx4("flex items-center mx-[2px] gap-[2px] cursor-pointer", styles.barHover),
1769
+ return /* @__PURE__ */ React19.createElement("div", {
1770
+ className: "flex items-center mx-0.5 gap-0.5 cursor-pointer",
1436
1771
  title: spaceId,
1437
1772
  onClick: () => {
1438
1773
  void navigator.clipboard.writeText(spaceId);
1439
1774
  }
1440
- }, /* @__PURE__ */ React15.createElement(Icon2, {
1775
+ }, /* @__PURE__ */ React19.createElement("span", {
1776
+ className: "is-1/2 truncate"
1777
+ }, spaceName), /* @__PURE__ */ React19.createElement(Icon6, {
1441
1778
  icon: "ph--arrow-fat-line-left--regular",
1442
1779
  size: 3,
1443
1780
  classNames: mx4(downActive && "animate-[pulse_1s_infinite]")
1444
- }), /* @__PURE__ */ React15.createElement(Candle, {
1781
+ }), /* @__PURE__ */ React19.createElement(Candle, {
1445
1782
  up: {
1446
1783
  count: remoteDocumentCount,
1447
1784
  total: remoteDocumentCount + missingOnRemote
@@ -1451,44 +1788,44 @@ var SpaceRow = ({ spaceId, state: { localDocumentCount, remoteDocumentCount, mis
1451
1788
  total: localDocumentCount + missingOnLocal
1452
1789
  },
1453
1790
  title: spaceId
1454
- }), /* @__PURE__ */ React15.createElement(Icon2, {
1791
+ }), /* @__PURE__ */ React19.createElement(Icon6, {
1455
1792
  icon: "ph--arrow-fat-line-right--regular",
1456
1793
  size: 3,
1457
1794
  classNames: mx4(upActive && "animate-[pulse_1s_step-start_infinite]")
1458
1795
  }));
1459
1796
  };
1460
1797
  var Candle = ({ classNames, up, down }) => {
1461
- return /* @__PURE__ */ React15.createElement("div", {
1798
+ return /* @__PURE__ */ React19.createElement("div", {
1462
1799
  className: mx4("grid grid-cols-[1fr_2rem_1fr] w-full h-3", classNames)
1463
- }, /* @__PURE__ */ React15.createElement(Bar, {
1800
+ }, /* @__PURE__ */ React19.createElement(Bar, {
1464
1801
  classNames: "justify-end",
1465
1802
  ...up
1466
- }), /* @__PURE__ */ React15.createElement("div", {
1803
+ }), /* @__PURE__ */ React19.createElement("div", {
1467
1804
  className: "relative"
1468
- }, /* @__PURE__ */ React15.createElement("div", {
1805
+ }, /* @__PURE__ */ React19.createElement("div", {
1469
1806
  className: mx4("absolute inset-0 flex items-center justify-center text-xs", styles.barBg)
1470
- }, up.total)), /* @__PURE__ */ React15.createElement(Bar, down));
1807
+ }, up.total)), /* @__PURE__ */ React19.createElement(Bar, down));
1471
1808
  };
1472
1809
  var Bar = ({ classNames, count, total }) => {
1473
1810
  let p = count / total * 100;
1474
1811
  if (count < total) {
1475
1812
  p = Math.min(p, 95);
1476
1813
  }
1477
- return /* @__PURE__ */ React15.createElement("div", {
1814
+ return /* @__PURE__ */ React19.createElement("div", {
1478
1815
  className: mx4("relative flex w-full", styles.barBg, classNames)
1479
- }, /* @__PURE__ */ React15.createElement("div", {
1816
+ }, /* @__PURE__ */ React19.createElement("div", {
1480
1817
  className: mx4("shrink-0", styles.barFg),
1481
1818
  style: {
1482
1819
  width: `${p}%`
1483
1820
  }
1484
- }), count !== total && /* @__PURE__ */ React15.createElement("div", {
1821
+ }), count !== total && /* @__PURE__ */ React19.createElement("div", {
1485
1822
  className: "absolute top-0 bottom-0 flex items-center mx-0.5 text-black text-xs"
1486
1823
  }, count));
1487
1824
  };
1488
1825
 
1489
1826
  // packages/plugins/plugin-space/src/components/SyncStatus/save-tracker.ts
1490
- import { Context } from "@dxos/context";
1491
- var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/plugins/plugin-space/src/components/SyncStatus/save-tracker.ts";
1827
+ import { Context as Context2 } from "@dxos/context";
1828
+ var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/plugins/plugin-space/src/components/SyncStatus/save-tracker.ts";
1492
1829
  var createClientSaveTracker = (client, cb) => {
1493
1830
  const unsubscribeCallbacks = {};
1494
1831
  const state = {};
@@ -1515,8 +1852,8 @@ var createClientSaveTracker = (client, cb) => {
1515
1852
  };
1516
1853
  };
1517
1854
  var createSpaceSaveTracker = (space, cb) => {
1518
- const ctx = new Context(void 0, {
1519
- F: __dxlog_file4,
1855
+ const ctx = new Context2(void 0, {
1856
+ F: __dxlog_file5,
1520
1857
  L: 40
1521
1858
  });
1522
1859
  void space.waitUntilReady().then(() => {
@@ -1577,84 +1914,23 @@ var getIcon = (status) => {
1577
1914
  }
1578
1915
  };
1579
1916
 
1580
- // packages/plugins/plugin-space/src/components/SyncStatus/sync-state.ts
1581
- import { useEffect as useEffect5, useState as useState9 } from "react";
1582
- import { Context as Context2 } from "@dxos/context";
1583
- import { EdgeService } from "@dxos/protocols";
1584
- import { useClient as useClient6 } from "@dxos/react-client";
1585
- var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/plugins/plugin-space/src/components/SyncStatus/sync-state.ts";
1586
- var createEmptyEdgeSyncState = () => ({
1587
- missingOnLocal: 0,
1588
- missingOnRemote: 0,
1589
- localDocumentCount: 0,
1590
- remoteDocumentCount: 0,
1591
- differentDocuments: 0
1592
- });
1593
- var getSyncSummary = (syncMap) => {
1594
- return Object.entries(syncMap).reduce((summary, [_spaceId, peerState]) => {
1595
- summary.missingOnLocal += peerState.missingOnLocal;
1596
- summary.missingOnRemote += peerState.missingOnRemote;
1597
- summary.localDocumentCount += peerState.localDocumentCount;
1598
- summary.remoteDocumentCount += peerState.remoteDocumentCount;
1599
- summary.differentDocuments += peerState.differentDocuments;
1600
- return summary;
1601
- }, createEmptyEdgeSyncState());
1602
- };
1603
- var isEdgePeerId = (peerId, spaceId) => peerId.startsWith(`${EdgeService.AUTOMERGE_REPLICATOR}:${spaceId}`);
1604
- var useSyncState = () => {
1605
- const client = useClient6();
1606
- const [spaceState, setSpaceState] = useState9({});
1607
- useEffect5(() => {
1608
- const ctx = new Context2(void 0, {
1609
- F: __dxlog_file5,
1610
- L: 48
1611
- });
1612
- const createSubscriptions = (spaces) => {
1613
- for (const space of spaces) {
1614
- if (spaceState[space.id]) {
1615
- continue;
1616
- }
1617
- ctx.onDispose(space.crud.subscribeToSyncState(ctx, ({ peers = [] }) => {
1618
- const syncState = peers.find((state) => isEdgePeerId(state.peerId, space.id));
1619
- if (syncState) {
1620
- setSpaceState((spaceState2) => ({
1621
- ...spaceState2,
1622
- [space.id]: syncState
1623
- }));
1624
- }
1625
- }));
1626
- }
1627
- };
1628
- createSubscriptions(client.spaces.get());
1629
- client.spaces.subscribe((spaces) => {
1630
- createSubscriptions(spaces);
1631
- });
1632
- return () => {
1633
- void ctx.dispose();
1634
- };
1635
- }, [
1636
- client
1637
- ]);
1638
- return spaceState;
1639
- };
1640
-
1641
1917
  // packages/plugins/plugin-space/src/components/SyncStatus/SyncStatus.tsx
1642
1918
  var SyncStatus = () => {
1643
- const client = useClient7();
1919
+ const client = useClient10();
1644
1920
  const state = useSyncState();
1645
- const [saved, setSaved] = useState10(true);
1646
- useEffect6(() => {
1921
+ const [saved, setSaved] = useState12(true);
1922
+ useEffect7(() => {
1647
1923
  return createClientSaveTracker(client, (state2) => {
1648
1924
  setSaved(state2 === "saved");
1649
1925
  });
1650
1926
  }, []);
1651
- return /* @__PURE__ */ React16.createElement(SyncStatusIndicator, {
1927
+ return /* @__PURE__ */ React20.createElement(SyncStatusIndicator, {
1652
1928
  state,
1653
1929
  saved
1654
1930
  });
1655
1931
  };
1656
1932
  var SyncStatusIndicator = ({ state, saved }) => {
1657
- const { t } = useTranslation15(SPACE_PLUGIN);
1933
+ const { t } = useTranslation20(SPACE_PLUGIN);
1658
1934
  const summary = getSyncSummary(state);
1659
1935
  const offline = Object.values(state).length === 0;
1660
1936
  const needsToUpload = summary.differentDocuments > 0 || summary.missingOnRemote > 0;
@@ -1665,8 +1941,8 @@ var SyncStatusIndicator = ({ state, saved }) => {
1665
1941
  needsToUpload,
1666
1942
  needsToDownload
1667
1943
  });
1668
- const [classNames, setClassNames] = useState10();
1669
- useEffect6(() => {
1944
+ const [classNames, setClassNames] = useState12();
1945
+ useEffect7(() => {
1670
1946
  setClassNames(void 0);
1671
1947
  if (offline || !needsToUpload && !needsToDownload) {
1672
1948
  return;
@@ -1681,23 +1957,23 @@ var SyncStatusIndicator = ({ state, saved }) => {
1681
1957
  needsToDownload
1682
1958
  ]);
1683
1959
  const title = t(`${status} label`);
1684
- const icon = /* @__PURE__ */ React16.createElement(Icon3, {
1960
+ const icon = /* @__PURE__ */ React20.createElement(Icon7, {
1685
1961
  icon: getIcon(status),
1686
1962
  size: 4,
1687
1963
  classNames
1688
1964
  });
1689
1965
  if (offline) {
1690
- return /* @__PURE__ */ React16.createElement(StatusBar.Item, {
1966
+ return /* @__PURE__ */ React20.createElement(StatusBar.Item, {
1691
1967
  title
1692
1968
  }, icon);
1693
1969
  } else {
1694
- return /* @__PURE__ */ React16.createElement(Popover3.Root, null, /* @__PURE__ */ React16.createElement(Popover3.Trigger, {
1970
+ return /* @__PURE__ */ React20.createElement(Popover3.Root, null, /* @__PURE__ */ React20.createElement(Popover3.Trigger, {
1695
1971
  asChild: true
1696
- }, /* @__PURE__ */ React16.createElement(StatusBar.Button, {
1972
+ }, /* @__PURE__ */ React20.createElement(StatusBar.Button, {
1697
1973
  title
1698
- }, icon)), /* @__PURE__ */ React16.createElement(Popover3.Portal, null, /* @__PURE__ */ React16.createElement(Popover3.Content, {
1974
+ }, icon)), /* @__PURE__ */ React20.createElement(Popover3.Portal, null, /* @__PURE__ */ React20.createElement(Popover3.Content, {
1699
1975
  sideOffset: 16
1700
- }, /* @__PURE__ */ React16.createElement(SyncStatusDetail, {
1976
+ }, /* @__PURE__ */ React20.createElement(SyncStatusDetail, {
1701
1977
  state,
1702
1978
  summary,
1703
1979
  debug: false
@@ -1705,17 +1981,36 @@ var SyncStatusIndicator = ({ state, saved }) => {
1705
1981
  }
1706
1982
  };
1707
1983
  var SyncStatusDetail = ({ classNames, state, summary, debug }) => {
1708
- const { t } = useTranslation15(SPACE_PLUGIN);
1709
- const entries = Object.entries(state).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
1710
- return /* @__PURE__ */ React16.createElement("div", {
1711
- className: mx5("flex flex-col gap-3 p-2 text-xs min-w-[16rem]", classNames)
1712
- }, /* @__PURE__ */ React16.createElement("h1", null, t("sync status title")), /* @__PURE__ */ React16.createElement("div", {
1984
+ const [showAll, setShowAll] = useState12(false);
1985
+ const { t } = useTranslation20(SPACE_PLUGIN);
1986
+ const entries = Object.entries(state).filter(([_, value]) => showAll || value.missingOnLocal + value.missingOnRemote > 0).toSorted(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
1987
+ const handleCheckedChange = useCallback9((state2) => setShowAll(state2), [
1988
+ setShowAll
1989
+ ]);
1990
+ return /* @__PURE__ */ React20.createElement("div", {
1991
+ className: mx5("flex flex-col gap-3 p-2 text-xs min-w-96", classNames)
1992
+ }, /* @__PURE__ */ React20.createElement("div", {
1993
+ role: "none",
1994
+ className: "flex items-center"
1995
+ }, /* @__PURE__ */ React20.createElement("h1", {
1996
+ className: "flex-1"
1997
+ }, t("sync status title")), /* @__PURE__ */ React20.createElement("div", {
1998
+ className: "flex items-center gap-2"
1999
+ }, /* @__PURE__ */ React20.createElement(Input7.Root, null, /* @__PURE__ */ React20.createElement(Input7.Label, {
2000
+ classNames: "text-xs"
2001
+ }, t("show all label")), /* @__PURE__ */ React20.createElement(Input7.Checkbox, {
2002
+ checked: showAll,
2003
+ onCheckedChange: handleCheckedChange
2004
+ })))), /* @__PURE__ */ React20.createElement("div", {
1713
2005
  className: "flex flex-col gap-2"
1714
- }, entries.map(([spaceId, state2]) => /* @__PURE__ */ React16.createElement(SpaceRow, {
2006
+ }, entries.length === 0 && /* @__PURE__ */ React20.createElement("div", {
2007
+ role: "none",
2008
+ className: "flex justify-center"
2009
+ }, t("no sync status label")), entries.map(([spaceId, state2]) => /* @__PURE__ */ React20.createElement(SpaceRowContainer, {
1715
2010
  key: spaceId,
1716
2011
  spaceId,
1717
2012
  state: state2
1718
- }))), debug && /* @__PURE__ */ React16.createElement(SyntaxHighlighter, {
2013
+ }))), debug && /* @__PURE__ */ React20.createElement(SyntaxHighlighter, {
1719
2014
  language: "json"
1720
2015
  }, JSON.stringify(summary, null, 2)));
1721
2016
  };
@@ -1724,6 +2019,9 @@ var SyncStatusDetail = ({ classNames, state, summary, debug }) => {
1724
2019
  var translations_default = [
1725
2020
  {
1726
2021
  "en-US": {
2022
+ [CollectionType.typename]: {
2023
+ "typename label": "Collection"
2024
+ },
1727
2025
  [SPACE_PLUGIN]: {
1728
2026
  "plugin name": "Spaces",
1729
2027
  "first run message": "Nothing selected.",
@@ -1817,7 +2115,18 @@ var translations_default = [
1817
2115
  "open settings panel label": "Show Settings",
1818
2116
  "open space settings label": "Space Settings",
1819
2117
  "members tab label": "Members",
1820
- "settings tab label": "Settings"
2118
+ "settings tab label": "Settings",
2119
+ "syncing message": "Space syncing",
2120
+ "show all label": "Show all",
2121
+ "no sync status label": "No space with missing objects.",
2122
+ "create space dialog title": "Create Space",
2123
+ "create object dialog title": "Create Object",
2124
+ "space input placeholder": "Select space",
2125
+ "schema input placeholder": "Select object type",
2126
+ "creating object type label": "Type",
2127
+ "creating in space label": "In Space",
2128
+ "creating in collection label": "In Collection",
2129
+ "clear input label": "Clear"
1821
2130
  }
1822
2131
  }
1823
2132
  }
@@ -1831,9 +2140,7 @@ var SPACE_MAX_OBJECTS = 500;
1831
2140
  var DIRECTORY_TYPE = "text/directory";
1832
2141
  var parseSpacePlugin = (plugin) => Array.isArray(plugin?.provides.space?.enabled) ? plugin : void 0;
1833
2142
  var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "spaceInvitationCode", firstRun, onFirstRun } = {}) => {
1834
- const settings = new LocalStorageStore(SPACE_PLUGIN, {
1835
- onSpaceCreate: "dxos.org/plugin/markdown/action/create"
1836
- });
2143
+ const settings = new LocalStorageStore(SPACE_PLUGIN, {});
1837
2144
  const state = new LocalStorageStore(SPACE_PLUGIN, {
1838
2145
  awaiting: void 0,
1839
2146
  spaceNames: {},
@@ -1841,17 +2148,20 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
1841
2148
  // TODO(wittjosiah): Stop using (Complex)Map inside reactive object.
1842
2149
  viewersByIdentity: new ComplexMap2(PublicKey2.hash),
1843
2150
  sdkMigrationRunning: {},
1844
- navigableCollections: false
2151
+ navigableCollections: false,
2152
+ enabledEdgeReplication: false
1845
2153
  });
1846
2154
  const subscriptions = new EventSubscriptions();
1847
2155
  const spaceSubscriptions = new EventSubscriptions();
1848
2156
  const graphSubscriptions = /* @__PURE__ */ new Map();
2157
+ const schemas = [];
1849
2158
  let clientPlugin;
1850
2159
  let graphPlugin;
1851
2160
  let intentPlugin;
1852
2161
  let layoutPlugin;
1853
2162
  let navigationPlugin;
1854
2163
  let attentionPlugin;
2164
+ let metadataPlugin;
1855
2165
  const createSpaceInvitationUrl = (invitationCode) => {
1856
2166
  const baseUrl = new URL(invitationUrl);
1857
2167
  baseUrl.searchParams.set(invitationParam, invitationCode);
@@ -1871,11 +2181,11 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
1871
2181
  if (typeof defaultSpace.properties[COMPOSER_SPACE_LOCK] !== "boolean") {
1872
2182
  defaultSpace.properties[COMPOSER_SPACE_LOCK] = true;
1873
2183
  }
1874
- const { objects: [spacesOrder] } = await defaultSpace.db.query(Filter.schema(Expando, {
2184
+ const { objects: [spacesOrder] } = await defaultSpace.db.query(Filter3.schema(Expando, {
1875
2185
  key: SHARED
1876
2186
  })).run();
1877
2187
  if (!spacesOrder) {
1878
- defaultSpace.db.add(create2({
2188
+ defaultSpace.db.add(create({
1879
2189
  key: SHARED,
1880
2190
  order: []
1881
2191
  }));
@@ -1915,25 +2225,42 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
1915
2225
  });
1916
2226
  }).unsubscribe);
1917
2227
  subscriptions.add(scheduledEffect(() => ({
1918
- ids: openIds(location.active),
1919
- removed: location.closed ? [
1920
- location.closed
1921
- ].flat() : []
1922
- }), ({ ids, removed }) => {
2228
+ open: openIds(location.active, layout.layoutMode === "solo" ? [
2229
+ "solo"
2230
+ ] : [
2231
+ "main"
2232
+ ]),
2233
+ closed: [
2234
+ ...location.closed
2235
+ ]
2236
+ }), ({ open, closed }) => {
1923
2237
  const send = () => {
1924
2238
  const spaces = client.spaces.get();
1925
2239
  const identity = client.halo.identity.get();
1926
2240
  if (identity && location.active) {
1927
- const idsBySpace = reduceGroupBy(ids, (id) => {
1928
- const [spaceId] = id.split(":");
1929
- return spaceId;
2241
+ const idsBySpace = reduceGroupBy(open, (id) => {
2242
+ try {
2243
+ const [spaceId] = parseFullyQualifiedId(id);
2244
+ return spaceId;
2245
+ } catch {
2246
+ return null;
2247
+ }
2248
+ });
2249
+ const removedBySpace = reduceGroupBy(closed, (id) => {
2250
+ try {
2251
+ const [spaceId] = parseFullyQualifiedId(id);
2252
+ return spaceId;
2253
+ } catch {
2254
+ return null;
2255
+ }
1930
2256
  });
1931
2257
  for (const space of spaces) {
1932
2258
  if (!idsBySpace.has(space.id)) {
1933
2259
  idsBySpace.set(space.id, []);
1934
2260
  }
1935
2261
  }
1936
- for (const [spaceId, ids2] of idsBySpace) {
2262
+ for (const [spaceId, added] of idsBySpace) {
2263
+ const removed = removedBySpace.get(spaceId) ?? [];
1937
2264
  const space = spaces.find((space2) => space2.id === spaceId);
1938
2265
  if (!space) {
1939
2266
  continue;
@@ -1943,15 +2270,14 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
1943
2270
  attended: attention.attended ? [
1944
2271
  ...attention.attended
1945
2272
  ] : [],
1946
- added: ids2,
1947
- // TODO(Zan): When we re-open a part, we should remove it from the removed list in the navigation plugin.
1948
- removed: removed.filter((id) => !ids2.includes(id))
2273
+ added,
2274
+ removed
1949
2275
  }).catch((err) => {
1950
2276
  log3.warn("Failed to broadcast active node for presence.", {
1951
2277
  err: err.message
1952
2278
  }, {
1953
2279
  F: __dxlog_file6,
1954
- L: 294,
2280
+ L: 320,
1955
2281
  S: void 0,
1956
2282
  C: (f, a) => f(...a)
1957
2283
  });
@@ -1969,7 +2295,8 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
1969
2295
  spaceSubscriptions.add(space.listen("viewing", (message) => {
1970
2296
  const { added, removed, attended } = message.payload;
1971
2297
  const identityKey = PublicKey2.safeFrom(message.payload.identityKey);
1972
- if (identityKey && Array.isArray(added) && Array.isArray(removed)) {
2298
+ const currentIdentity = client.halo.identity.get();
2299
+ if (identityKey && !currentIdentity?.identityKey.equals(identityKey) && Array.isArray(added) && Array.isArray(removed)) {
1973
2300
  added.forEach((id) => {
1974
2301
  if (typeof id === "string") {
1975
2302
  if (!(id in state.values.viewersByObject)) {
@@ -1996,6 +2323,19 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
1996
2323
  });
1997
2324
  }).unsubscribe);
1998
2325
  };
2326
+ const setEdgeReplicationDefault = async (client) => {
2327
+ try {
2328
+ await Promise.all(client.spaces.get().map((space) => space.internal.setEdgeReplicationPreference(EdgeReplicationSetting3.ENABLED)));
2329
+ state.values.enabledEdgeReplication = true;
2330
+ } catch (err) {
2331
+ log3.catch(err, void 0, {
2332
+ F: __dxlog_file6,
2333
+ L: 389,
2334
+ S: void 0,
2335
+ C: (f, a) => f(...a)
2336
+ });
2337
+ }
2338
+ };
1999
2339
  return {
2000
2340
  meta: meta_default,
2001
2341
  ready: async (plugins) => {
@@ -2008,12 +2348,16 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2008
2348
  state.prop({
2009
2349
  key: "spaceNames",
2010
2350
  type: LocalStorageStore.json()
2351
+ }).prop({
2352
+ key: "enabledEdgeReplication",
2353
+ type: LocalStorageStore.bool()
2011
2354
  });
2012
2355
  if (findPlugin(plugins, "dxos.org/plugin/stack")) {
2013
2356
  state.values.navigableCollections = true;
2014
2357
  }
2015
2358
  graphPlugin = resolvePlugin(plugins, parseGraphPlugin);
2016
2359
  layoutPlugin = resolvePlugin(plugins, parseLayoutPlugin);
2360
+ metadataPlugin = resolvePlugin(plugins, parseMetadataResolverPlugin);
2017
2361
  navigationPlugin = resolvePlugin(plugins, parseNavigationPlugin2);
2018
2362
  attentionPlugin = resolvePlugin(plugins, parseAttentionPlugin);
2019
2363
  clientPlugin = resolvePlugin(plugins, parseClientPlugin);
@@ -2023,9 +2367,21 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2023
2367
  }
2024
2368
  const client = clientPlugin.provides.client;
2025
2369
  const dispatch = intentPlugin.provides.intent.dispatch;
2370
+ schemas.push(...filterPlugins(plugins, parseSchemaPlugin).map((plugin) => plugin.provides.echo.schema).filter(nonNullable2).reduce((acc, schema) => {
2371
+ return [
2372
+ ...acc,
2373
+ ...schema
2374
+ ];
2375
+ }));
2376
+ client.addTypes(schemas);
2377
+ filterPlugins(plugins, parseSchemaPlugin).forEach((plugin) => {
2378
+ if (plugin.provides.echo.system) {
2379
+ client.addTypes(plugin.provides.echo.system);
2380
+ }
2381
+ });
2026
2382
  const handleFirstRun = async () => {
2027
2383
  const defaultSpace = client.spaces.default;
2028
- defaultSpace.properties[CollectionType.typename] = create2(CollectionType, {
2384
+ defaultSpace.properties[CollectionType.typename] = create(CollectionType, {
2029
2385
  objects: [],
2030
2386
  views: {}
2031
2387
  });
@@ -2046,6 +2402,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2046
2402
  await handleFirstRun();
2047
2403
  }
2048
2404
  await onSpaceReady();
2405
+ await setEdgeReplicationDefault(client);
2049
2406
  }
2050
2407
  }).unsubscribe);
2051
2408
  },
@@ -2077,12 +2434,13 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2077
2434
  }
2078
2435
  ]
2079
2436
  },
2080
- root: () => state.values.awaiting ? /* @__PURE__ */ React17.createElement(AwaitingObject, {
2437
+ root: () => state.values.awaiting ? /* @__PURE__ */ React21.createElement(AwaitingObject, {
2081
2438
  id: state.values.awaiting
2082
2439
  }) : null,
2083
2440
  metadata: {
2084
2441
  records: {
2085
2442
  [CollectionType.typename]: {
2443
+ createObject: CollectionAction.CREATE,
2086
2444
  placeholder: [
2087
2445
  "unnamed collection label",
2088
2446
  {
@@ -2107,7 +2465,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2107
2465
  component: ({ data, role, ...rest }) => {
2108
2466
  switch (role) {
2109
2467
  case "article":
2110
- return isSpace2(data.object) && data.object.state.get() === SpaceState2.SPACE_READY ? /* @__PURE__ */ React17.createElement(Surface, {
2468
+ return isSpace4(data.object) && data.object.state.get() === SpaceState2.SPACE_READY ? /* @__PURE__ */ React21.createElement(Surface, {
2111
2469
  data: {
2112
2470
  object: data.object.properties[CollectionType.typename],
2113
2471
  id: data.object.id
@@ -2115,89 +2473,100 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2115
2473
  role,
2116
2474
  ...rest
2117
2475
  }) : data.object instanceof CollectionType ? {
2118
- node: /* @__PURE__ */ React17.createElement(CollectionMain, {
2476
+ node: /* @__PURE__ */ React21.createElement(CollectionMain, {
2119
2477
  collection: data.object
2120
2478
  }),
2121
2479
  disposition: "fallback"
2122
2480
  } : null;
2481
+ // TODO(burdon): Add role name syntax to minimal plugin docs.
2123
2482
  case "complementary--settings":
2124
- return isSpace2(data.subject) ? /* @__PURE__ */ React17.createElement(SpaceSettingsPanel, {
2483
+ return isSpace4(data.subject) ? /* @__PURE__ */ React21.createElement(SpaceSettingsPanel, {
2125
2484
  space: data.subject
2126
2485
  }) : isEchoObject2(data.subject) ? {
2127
- node: /* @__PURE__ */ React17.createElement(DefaultObjectSettings, {
2486
+ node: /* @__PURE__ */ React21.createElement(DefaultObjectSettings, {
2128
2487
  object: data.subject
2129
2488
  }),
2130
2489
  disposition: "fallback"
2131
2490
  } : null;
2132
2491
  case "dialog":
2133
2492
  if (data.component === "dxos.org/plugin/space/SpaceSettingsDialog") {
2134
- return /* @__PURE__ */ React17.createElement(SpaceSettingsDialog, {
2493
+ return /* @__PURE__ */ React21.createElement(SpaceSettingsDialog, {
2135
2494
  ...data.subject,
2136
2495
  createInvitationUrl: createSpaceInvitationUrl
2137
2496
  });
2138
2497
  } else if (data.component === "dxos.org/plugin/space/JoinDialog") {
2139
- return /* @__PURE__ */ React17.createElement(JoinDialog, data.subject);
2498
+ return /* @__PURE__ */ React21.createElement(JoinDialog, data.subject);
2499
+ } else if (data.component === "dxos.org/plugin/space/CreateSpaceDialog") {
2500
+ return /* @__PURE__ */ React21.createElement(CreateSpaceDialog, null);
2501
+ } else if (data.component === "dxos.org/plugin/space/CreateObjectDialog") {
2502
+ return /* @__PURE__ */ React21.createElement(CreateObjectDialog, {
2503
+ ...data.subject,
2504
+ schemas,
2505
+ navigableCollections: state.values.navigableCollections,
2506
+ resolve: metadataPlugin?.provides.metadata.resolver
2507
+ });
2140
2508
  }
2141
2509
  return null;
2142
2510
  case "popover": {
2143
- if (data.component === "dxos.org/plugin/space/RenameSpacePopover" && isSpace2(data.subject)) {
2144
- return /* @__PURE__ */ React17.createElement(PopoverRenameSpace, {
2511
+ if (data.component === "dxos.org/plugin/space/RenameSpacePopover" && isSpace4(data.subject)) {
2512
+ return /* @__PURE__ */ React21.createElement(PopoverRenameSpace, {
2145
2513
  space: data.subject
2146
2514
  });
2147
2515
  }
2148
- if (data.component === "dxos.org/plugin/space/RenameObjectPopover" && isReactiveObject2(data.subject)) {
2149
- return /* @__PURE__ */ React17.createElement(PopoverRenameObject, {
2516
+ if (data.component === "dxos.org/plugin/space/RenameObjectPopover" && isReactiveObject3(data.subject)) {
2517
+ return /* @__PURE__ */ React21.createElement(PopoverRenameObject, {
2150
2518
  object: data.subject
2151
2519
  });
2152
2520
  }
2153
2521
  return null;
2154
2522
  }
2155
- // TODO(burdon): Add role name syntax to minimal plugin docs.
2156
- case "presence--glyph": {
2157
- return isReactiveObject2(data.object) ? /* @__PURE__ */ React17.createElement(SmallPresenceLive, {
2523
+ case "navtree-item-end": {
2524
+ return isReactiveObject3(data.object) ? /* @__PURE__ */ React21.createElement(SmallPresenceLive, {
2158
2525
  id: data.id,
2159
2526
  viewers: state.values.viewersByObject[fullyQualifiedId4(data.object)]
2160
- }) : /* @__PURE__ */ React17.createElement(SmallPresence, {
2161
- id: data.id,
2162
- count: 0
2163
- });
2164
- }
2165
- case "navbar-start": {
2166
- return null;
2527
+ }) : isSpace4(data.object) ? /* @__PURE__ */ React21.createElement(InlineSyncStatus, {
2528
+ space: data.object
2529
+ }) : (
2530
+ // TODO(wittjosiah): Attention glyph for non-echo items should be handled elsewhere.
2531
+ /* @__PURE__ */ React21.createElement(SmallPresence, {
2532
+ id: data.id,
2533
+ count: 0
2534
+ })
2535
+ );
2167
2536
  }
2168
2537
  case "navbar-end": {
2169
- if (!isEchoObject2(data.object) && !isSpace2(data.object)) {
2538
+ if (!isEchoObject2(data.object) && !isSpace4(data.object)) {
2170
2539
  return null;
2171
2540
  }
2172
- const space = isSpace2(data.object) ? data.object : getSpace4(data.object);
2173
- const object = isSpace2(data.object) ? data.object.state.get() === SpaceState2.SPACE_READY ? space?.properties[CollectionType.typename] : void 0 : data.object;
2541
+ const space = isSpace4(data.object) ? data.object : getSpace5(data.object);
2542
+ const object = isSpace4(data.object) ? data.object.state.get() === SpaceState2.SPACE_READY ? space?.properties[CollectionType.typename] : void 0 : data.object;
2174
2543
  return space && object ? {
2175
- node: /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement(SpacePresence, {
2544
+ node: /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement(SpacePresence, {
2176
2545
  object
2177
- }), space.properties[COMPOSER_SPACE_LOCK] ? null : /* @__PURE__ */ React17.createElement(ShareSpaceButton, {
2546
+ }), space.properties[COMPOSER_SPACE_LOCK] ? null : /* @__PURE__ */ React21.createElement(ShareSpaceButton, {
2178
2547
  space
2179
2548
  })),
2180
2549
  disposition: "hoist"
2181
2550
  } : null;
2182
2551
  }
2183
2552
  case "section":
2184
- return data.object instanceof CollectionType ? /* @__PURE__ */ React17.createElement(CollectionSection, {
2553
+ return data.object instanceof CollectionType ? /* @__PURE__ */ React21.createElement(CollectionSection, {
2185
2554
  collection: data.object
2186
2555
  }) : null;
2187
2556
  case "settings":
2188
- return data.plugin === meta_default.id ? /* @__PURE__ */ React17.createElement(SpacePluginSettings, {
2557
+ return data.plugin === meta_default.id ? /* @__PURE__ */ React21.createElement(SpacePluginSettings, {
2189
2558
  settings: settings.values
2190
2559
  }) : null;
2191
2560
  case "menu-footer":
2192
2561
  if (isEchoObject2(data.object)) {
2193
- return /* @__PURE__ */ React17.createElement(MenuFooter, {
2562
+ return /* @__PURE__ */ React21.createElement(MenuFooter, {
2194
2563
  object: data.object
2195
2564
  });
2196
2565
  } else {
2197
2566
  return null;
2198
2567
  }
2199
2568
  case "status": {
2200
- return /* @__PURE__ */ React17.createElement(SyncStatus, null);
2569
+ return /* @__PURE__ */ React21.createElement(SyncStatus, null);
2201
2570
  }
2202
2571
  default:
2203
2572
  return null;
@@ -2207,72 +2576,60 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2207
2576
  graph: {
2208
2577
  builder: (plugins) => {
2209
2578
  const clientPlugin2 = resolvePlugin(plugins, parseClientPlugin);
2210
- const metadataPlugin = resolvePlugin(plugins, parseMetadataResolverPlugin);
2579
+ const metadataPlugin2 = resolvePlugin(plugins, parseMetadataResolverPlugin);
2211
2580
  const graphPlugin2 = resolvePlugin(plugins, parseGraphPlugin);
2212
2581
  const client = clientPlugin2?.provides.client;
2213
2582
  const dispatch = intentPlugin?.provides.intent.dispatch;
2214
- const resolve = metadataPlugin?.provides.metadata.resolver;
2583
+ const resolve = metadataPlugin2?.provides.metadata.resolver;
2215
2584
  const graph = graphPlugin2?.provides.graph;
2216
2585
  if (!client || !dispatch || !resolve || !graph) {
2217
2586
  return [];
2218
2587
  }
2588
+ const spacesNode = {
2589
+ id: SPACES,
2590
+ type: SPACES,
2591
+ cacheable: [
2592
+ "label",
2593
+ "role"
2594
+ ],
2595
+ properties: {
2596
+ label: [
2597
+ "spaces label",
2598
+ {
2599
+ ns: SPACE_PLUGIN
2600
+ }
2601
+ ],
2602
+ testId: "spacePlugin.spaces",
2603
+ role: "branch",
2604
+ disabled: true,
2605
+ childrenPersistenceClass: "echo",
2606
+ onRearrangeChildren: async (nextOrder) => {
2607
+ graph._sortEdges(SPACES, "outbound", nextOrder.map(({ id }) => id));
2608
+ const { objects: [spacesOrder] } = await client.spaces.default.db.query(Filter3.schema(Expando, {
2609
+ key: SHARED
2610
+ })).run();
2611
+ if (spacesOrder) {
2612
+ spacesOrder.order = nextOrder.map(({ id }) => id);
2613
+ } else {
2614
+ log3.warn("spaces order object not found", void 0, {
2615
+ F: __dxlog_file6,
2616
+ L: 649,
2617
+ S: void 0,
2618
+ C: (f, a) => f(...a)
2619
+ });
2620
+ }
2621
+ }
2622
+ }
2623
+ };
2219
2624
  return [
2220
2625
  // Create spaces group node.
2221
2626
  createExtension({
2222
2627
  id: `${SPACE_PLUGIN}/root`,
2223
2628
  filter: (node) => node.id === "root",
2224
- connector: () => {
2225
- const isReady = toSignal((onChange) => {
2226
- let defaultSpaceUnsubscribe;
2227
- client.spaces.isReady.subscribe((ready) => {
2228
- if (ready) {
2229
- defaultSpaceUnsubscribe = client.spaces.default.state.subscribe(() => onChange()).unsubscribe;
2230
- }
2231
- });
2232
- return () => defaultSpaceUnsubscribe?.();
2233
- }, () => client.spaces.isReady.get() && client.spaces.default.state.get() === SpaceState2.SPACE_READY);
2234
- if (!isReady) {
2235
- return [];
2236
- }
2237
- return [
2238
- {
2239
- id: SPACES,
2240
- type: SPACES,
2241
- cacheable: [
2242
- "label",
2243
- "role"
2244
- ],
2245
- properties: {
2246
- label: [
2247
- "spaces label",
2248
- {
2249
- ns: SPACE_PLUGIN
2250
- }
2251
- ],
2252
- testId: "spacePlugin.spaces",
2253
- role: "branch",
2254
- disabled: true,
2255
- childrenPersistenceClass: "echo",
2256
- onRearrangeChildren: async (nextOrder) => {
2257
- graph._sortEdges(SPACES, "outbound", nextOrder.map(({ id }) => id));
2258
- const { objects: [spacesOrder] } = await client.spaces.default.db.query(Filter.schema(Expando, {
2259
- key: SHARED
2260
- })).run();
2261
- if (spacesOrder) {
2262
- spacesOrder.order = nextOrder.map(({ id }) => id);
2263
- } else {
2264
- log3.warn("spaces order object not found", void 0, {
2265
- F: __dxlog_file6,
2266
- L: 599,
2267
- S: void 0,
2268
- C: (f, a) => f(...a)
2269
- });
2270
- }
2271
- }
2272
- }
2273
- }
2274
- ];
2275
- }
2629
+ connector: () => [
2630
+ spacesNode
2631
+ ],
2632
+ resolver: ({ id }) => id === SPACES ? spacesNode : void 0
2276
2633
  }),
2277
2634
  // Create space nodes.
2278
2635
  createExtension({
@@ -2280,11 +2637,11 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2280
2637
  filter: (node) => node.id === SPACES,
2281
2638
  actions: () => [
2282
2639
  {
2283
- id: SpaceAction.CREATE,
2640
+ id: SpaceAction.OPEN_CREATE_SPACE,
2284
2641
  data: async () => {
2285
2642
  await dispatch({
2286
2643
  plugin: SPACE_PLUGIN,
2287
- action: SpaceAction.CREATE
2644
+ action: SpaceAction.OPEN_CREATE_SPACE
2288
2645
  });
2289
2646
  },
2290
2647
  properties: {
@@ -2295,8 +2652,8 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2295
2652
  }
2296
2653
  ],
2297
2654
  icon: "ph--plus--regular",
2298
- disposition: "item",
2299
2655
  testId: "spacePlugin.createSpace",
2656
+ disposition: "item",
2300
2657
  className: "border-t border-separator"
2301
2658
  }
2302
2659
  },
@@ -2316,8 +2673,8 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2316
2673
  }
2317
2674
  ],
2318
2675
  icon: "ph--sign-in--regular",
2319
- disposition: "item",
2320
- testId: "spacePlugin.joinSpace"
2676
+ testId: "spacePlugin.joinSpace",
2677
+ disposition: "item"
2321
2678
  }
2322
2679
  }
2323
2680
  ],
@@ -2328,7 +2685,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2328
2685
  return;
2329
2686
  }
2330
2687
  try {
2331
- const [spacesOrder] = memoizeQuery(client.spaces.default, Filter.schema(Expando, {
2688
+ const [spacesOrder] = memoizeQuery(client.spaces.default, Filter3.schema(Expando, {
2332
2689
  key: SHARED
2333
2690
  }));
2334
2691
  const order = spacesOrder?.order ?? [];
@@ -2375,15 +2732,10 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2375
2732
  }
2376
2733
  }
2377
2734
  }),
2378
- // Create space actions and action groups.
2735
+ // Create space actions.
2379
2736
  createExtension({
2380
2737
  id: `${SPACE_PLUGIN}/actions`,
2381
- filter: (node) => isSpace2(node.data),
2382
- actionGroups: ({ node }) => constructSpaceActionGroups({
2383
- space: node.data,
2384
- dispatch,
2385
- navigable: state.values.navigableCollections
2386
- }),
2738
+ filter: (node) => isSpace4(node.data),
2387
2739
  actions: ({ node }) => {
2388
2740
  const space = node.data;
2389
2741
  return constructSpaceActions({
@@ -2397,7 +2749,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2397
2749
  // Create nodes for objects in the root collection of a space.
2398
2750
  createExtension({
2399
2751
  id: `${SPACE_PLUGIN}/root-collection`,
2400
- filter: (node) => isSpace2(node.data),
2752
+ filter: (node) => isSpace4(node.data),
2401
2753
  connector: ({ node }) => {
2402
2754
  const space = node.data;
2403
2755
  const spaceState = toSignal((onChange) => space.state.subscribe(() => onChange()).unsubscribe, () => space.state.get(), space.id);
@@ -2408,12 +2760,12 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2408
2760
  if (!collection) {
2409
2761
  return;
2410
2762
  }
2411
- return collection.objects.filter(nonNullable).map((object) => createObjectNode({
2763
+ return collection.objects.filter(nonNullable2).map((object) => createObjectNode({
2412
2764
  object,
2413
2765
  space,
2414
2766
  resolve,
2415
2767
  navigable: state.values.navigableCollections
2416
- })).filter(nonNullable);
2768
+ })).filter(nonNullable2);
2417
2769
  }
2418
2770
  }),
2419
2771
  // Create nodes for objects in a collection or by its fully qualified id.
@@ -2422,16 +2774,16 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2422
2774
  filter: (node) => node.data instanceof CollectionType,
2423
2775
  connector: ({ node }) => {
2424
2776
  const collection = node.data;
2425
- const space = getSpace4(collection);
2777
+ const space = getSpace5(collection);
2426
2778
  if (!space) {
2427
2779
  return;
2428
2780
  }
2429
- return collection.objects.filter(nonNullable).map((object) => createObjectNode({
2781
+ return collection.objects.filter(nonNullable2).map((object) => createObjectNode({
2430
2782
  object,
2431
2783
  space,
2432
2784
  resolve,
2433
2785
  navigable: state.values.navigableCollections
2434
- })).filter(nonNullable);
2786
+ })).filter(nonNullable2);
2435
2787
  },
2436
2788
  resolver: ({ id }) => {
2437
2789
  if (id.length !== FQ_ID_LENGTH) {
@@ -2454,7 +2806,14 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2454
2806
  if (!store.value) {
2455
2807
  void space.db.query({
2456
2808
  id: objectId
2457
- }).first().then((o) => store.value = o);
2809
+ }).first().then((o) => store.value = o).catch((err) => log3.catch(err, {
2810
+ objectId
2811
+ }, {
2812
+ F: __dxlog_file6,
2813
+ L: 872,
2814
+ S: void 0,
2815
+ C: (f, a) => f(...a)
2816
+ }));
2458
2817
  }
2459
2818
  }, id);
2460
2819
  const object = store.value;
@@ -2477,11 +2836,6 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2477
2836
  createExtension({
2478
2837
  id: `${SPACE_PLUGIN}/object-actions`,
2479
2838
  filter: (node) => isEchoObject2(node.data),
2480
- actionGroups: ({ node }) => constructObjectActionGroups({
2481
- object: node.data,
2482
- dispatch,
2483
- navigable: state.values.navigableCollections
2484
- }),
2485
2839
  actions: ({ node }) => constructObjectActions({
2486
2840
  node,
2487
2841
  dispatch
@@ -2525,15 +2879,9 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2525
2879
  }
2526
2880
  };
2527
2881
  }
2528
- const object = toSignal((onChange) => {
2529
- const timeout = setTimeout(async () => {
2530
- await space?.db.query({
2531
- id: objectId
2532
- }).first();
2533
- onChange();
2534
- });
2535
- return () => clearTimeout(timeout);
2536
- }, () => space?.db.getObjectById(objectId), subjectId);
2882
+ const [object] = memoizeQuery(space, {
2883
+ id: objectId
2884
+ });
2537
2885
  if (!object || !subjectId) {
2538
2886
  return;
2539
2887
  }
@@ -2603,7 +2951,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2603
2951
  type: DIRECTORY_TYPE
2604
2952
  }),
2605
2953
  deserialize: async (data, ancestors) => {
2606
- const space = ancestors.find(isSpace2);
2954
+ const space = ancestors.find(isSpace4);
2607
2955
  const collection = ancestors.findLast((ancestor) => ancestor instanceof CollectionType) ?? space?.properties[CollectionType.typename];
2608
2956
  if (!space || !collection) {
2609
2957
  return;
@@ -2613,7 +2961,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2613
2961
  action: SpaceAction.ADD_OBJECT,
2614
2962
  data: {
2615
2963
  target: collection,
2616
- object: create2(CollectionType, {
2964
+ object: create(CollectionType, {
2617
2965
  name: data.name,
2618
2966
  objects: [],
2619
2967
  views: {}
@@ -2637,13 +2985,36 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2637
2985
  data: true
2638
2986
  };
2639
2987
  }
2988
+ case SpaceAction.OPEN_CREATE_SPACE: {
2989
+ return {
2990
+ data: true,
2991
+ intents: [
2992
+ [
2993
+ {
2994
+ action: LayoutAction2.SET_LAYOUT,
2995
+ data: {
2996
+ element: "dialog",
2997
+ component: "dxos.org/plugin/space/CreateSpaceDialog",
2998
+ dialogBlockAlign: "start",
2999
+ subject: intent.data
3000
+ }
3001
+ }
3002
+ ]
3003
+ ]
3004
+ };
3005
+ }
2640
3006
  case SpaceAction.CREATE: {
2641
- if (!client) {
3007
+ if (!client || !S2.is(SpaceForm)(intent.data)) {
2642
3008
  return;
2643
3009
  }
2644
- const space = await client.spaces.create(intent.data);
3010
+ const space = await client.spaces.create({
3011
+ name: intent.data.name
3012
+ });
3013
+ if (intent.data.edgeReplication) {
3014
+ await space.internal.setEdgeReplicationPreference(EdgeReplicationSetting3.ENABLED);
3015
+ }
2645
3016
  await space.waitUntilReady();
2646
- const collection = create2(CollectionType, {
3017
+ const collection = create(CollectionType, {
2647
3018
  objects: [],
2648
3019
  views: {}
2649
3020
  });
@@ -2662,28 +3033,6 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2662
3033
  }
2663
3034
  },
2664
3035
  intents: [
2665
- ...settings.values.onSpaceCreate ? [
2666
- [
2667
- {
2668
- action: settings.values.onSpaceCreate,
2669
- data: {
2670
- space
2671
- }
2672
- },
2673
- {
2674
- action: SpaceAction.ADD_OBJECT,
2675
- data: {
2676
- target: space
2677
- }
2678
- },
2679
- {
2680
- action: NavigationAction4.OPEN
2681
- },
2682
- {
2683
- action: NavigationAction4.EXPOSE
2684
- }
2685
- ]
2686
- ] : [],
2687
3036
  [
2688
3037
  {
2689
3038
  action: ObservabilityAction2.SEND_EVENT,
@@ -2720,7 +3069,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2720
3069
  }
2721
3070
  case SpaceAction.SHARE: {
2722
3071
  const space = intent.data?.space;
2723
- if (isSpace2(space) && !space.properties[COMPOSER_SPACE_LOCK]) {
3072
+ if (isSpace4(space) && !space.properties[COMPOSER_SPACE_LOCK]) {
2724
3073
  const active = navigationPlugin?.provides.location.active;
2725
3074
  const mode = layoutPlugin?.provides.layout.layoutMode;
2726
3075
  const current = active ? firstIdInPart(active, mode === "solo" ? "solo" : "main") : void 0;
@@ -2762,7 +3111,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2762
3111
  }
2763
3112
  case SpaceAction.LOCK: {
2764
3113
  const space = intent.data?.space;
2765
- if (isSpace2(space)) {
3114
+ if (isSpace4(space)) {
2766
3115
  space.properties[COMPOSER_SPACE_LOCK] = true;
2767
3116
  return {
2768
3117
  data: true,
@@ -2785,7 +3134,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2785
3134
  }
2786
3135
  case SpaceAction.UNLOCK: {
2787
3136
  const space = intent.data?.space;
2788
- if (isSpace2(space)) {
3137
+ if (isSpace4(space)) {
2789
3138
  space.properties[COMPOSER_SPACE_LOCK] = false;
2790
3139
  return {
2791
3140
  data: true,
@@ -2808,7 +3157,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2808
3157
  }
2809
3158
  case SpaceAction.RENAME: {
2810
3159
  const { caller, space } = intent.data ?? {};
2811
- if (typeof caller === "string" && isSpace2(space)) {
3160
+ if (typeof caller === "string" && isSpace4(space)) {
2812
3161
  return {
2813
3162
  intents: [
2814
3163
  [
@@ -2829,7 +3178,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2829
3178
  }
2830
3179
  case SpaceAction.OPEN_SETTINGS: {
2831
3180
  const space = intent.data?.space;
2832
- if (isSpace2(space)) {
3181
+ if (isSpace4(space)) {
2833
3182
  return {
2834
3183
  data: true,
2835
3184
  intents: [
@@ -2855,7 +3204,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2855
3204
  }
2856
3205
  case SpaceAction.OPEN: {
2857
3206
  const space = intent.data?.space;
2858
- if (isSpace2(space)) {
3207
+ if (isSpace4(space)) {
2859
3208
  await space.open();
2860
3209
  return {
2861
3210
  data: true
@@ -2865,7 +3214,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2865
3214
  }
2866
3215
  case SpaceAction.CLOSE: {
2867
3216
  const space = intent.data?.space;
2868
- if (isSpace2(space)) {
3217
+ if (isSpace4(space)) {
2869
3218
  await space.close();
2870
3219
  return {
2871
3220
  data: true
@@ -2875,7 +3224,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2875
3224
  }
2876
3225
  case SpaceAction.MIGRATE: {
2877
3226
  const space = intent.data?.space;
2878
- if (isSpace2(space)) {
3227
+ if (isSpace4(space)) {
2879
3228
  if (space.state.get() === SpaceState2.SPACE_REQUIRES_MIGRATION) {
2880
3229
  state.values.sdkMigrationRunning[space.id] = true;
2881
3230
  await space.internal.migrate();
@@ -2902,12 +3251,30 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2902
3251
  }
2903
3252
  break;
2904
3253
  }
3254
+ case SpaceAction.OPEN_CREATE_OBJECT: {
3255
+ return {
3256
+ data: true,
3257
+ intents: [
3258
+ [
3259
+ {
3260
+ action: LayoutAction2.SET_LAYOUT,
3261
+ data: {
3262
+ element: "dialog",
3263
+ component: "dxos.org/plugin/space/CreateObjectDialog",
3264
+ dialogBlockAlign: "start",
3265
+ subject: intent.data
3266
+ }
3267
+ }
3268
+ ]
3269
+ ]
3270
+ };
3271
+ }
2905
3272
  case SpaceAction.ADD_OBJECT: {
2906
3273
  const object = intent.data?.object ?? intent.data?.result;
2907
- if (!isReactiveObject2(object)) {
3274
+ if (!isReactiveObject3(object)) {
2908
3275
  return;
2909
3276
  }
2910
- const space = isSpace2(intent.data?.target) ? intent.data?.target : getSpace4(intent.data?.target);
3277
+ const space = isSpace4(intent.data?.target) ? intent.data?.target : getSpace5(intent.data?.target);
2911
3278
  if (!space) {
2912
3279
  return;
2913
3280
  }
@@ -2951,12 +3318,12 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2951
3318
  }
2952
3319
  if (intent.data?.target instanceof CollectionType) {
2953
3320
  intent.data?.target.objects.push(object);
2954
- } else if (isSpace2(intent.data?.target)) {
3321
+ } else if (isSpace4(intent.data?.target)) {
2955
3322
  const collection = space.properties[CollectionType.typename];
2956
3323
  if (collection instanceof CollectionType) {
2957
3324
  collection.objects.push(object);
2958
3325
  } else {
2959
- const collection2 = create2(CollectionType, {
3326
+ const collection2 = create(CollectionType, {
2960
3327
  objects: [
2961
3328
  object
2962
3329
  ],
@@ -2996,15 +3363,15 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
2996
3363
  const objects = intent.data?.objects ?? intent.data?.result;
2997
3364
  invariant2(Array.isArray(objects), void 0, {
2998
3365
  F: __dxlog_file6,
2999
- L: 1346,
3366
+ L: 1411,
3000
3367
  S: void 0,
3001
3368
  A: [
3002
3369
  "Array.isArray(objects)",
3003
3370
  ""
3004
3371
  ]
3005
3372
  });
3006
- const space = getSpace4(objects[0]);
3007
- if (!space || !objects.every((obj) => isEchoObject2(obj) && getSpace4(obj) === space)) {
3373
+ const space = getSpace5(objects[0]);
3374
+ if (!space || !objects.every((obj) => isEchoObject2(obj) && getSpace5(obj) === space)) {
3008
3375
  return;
3009
3376
  }
3010
3377
  const resolve = resolvePlugin(plugins, parseMetadataResolverPlugin)?.provides.metadata.resolver;
@@ -3090,7 +3457,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
3090
3457
  case SpaceAction.RENAME_OBJECT: {
3091
3458
  const object = intent.data?.object ?? intent.data?.result;
3092
3459
  const caller = intent.data?.caller;
3093
- if (isReactiveObject2(object) && caller) {
3460
+ if (isReactiveObject3(object) && caller) {
3094
3461
  return {
3095
3462
  intents: [
3096
3463
  [
@@ -3112,7 +3479,7 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
3112
3479
  case SpaceAction.DUPLICATE_OBJECT: {
3113
3480
  const originalObject = intent.data?.object ?? intent.data?.result;
3114
3481
  const resolve = resolvePlugin(plugins, parseMetadataResolverPlugin)?.provides.metadata.resolver;
3115
- const space = isSpace2(intent.data?.target) ? intent.data?.target : getSpace4(intent.data?.target);
3482
+ const space = isSpace4(intent.data?.target) ? intent.data?.target : getSpace5(intent.data?.target);
3116
3483
  if (!isEchoObject2(originalObject) || !resolve || !space) {
3117
3484
  return;
3118
3485
  }
@@ -3137,6 +3504,16 @@ var SpacePlugin = ({ invitationUrl = window.location.origin, invitationParam = "
3137
3504
  data: true
3138
3505
  };
3139
3506
  }
3507
+ case CollectionAction.CREATE: {
3508
+ const collection = create(CollectionType, {
3509
+ name: intent.data?.name,
3510
+ objects: [],
3511
+ views: {}
3512
+ });
3513
+ return {
3514
+ data: collection
3515
+ };
3516
+ }
3140
3517
  }
3141
3518
  }
3142
3519
  }
@@ -3151,12 +3528,17 @@ export {
3151
3528
  AwaitingObject,
3152
3529
  COMPOSER_SPACE_LOCK,
3153
3530
  ChannelType,
3531
+ CollectionAction,
3154
3532
  CollectionMain,
3155
3533
  CollectionSection,
3156
3534
  CollectionType,
3157
3535
  ContactType,
3536
+ CreateObjectDialog,
3537
+ CreateSpaceDialog,
3158
3538
  DefaultObjectSettings,
3159
3539
  FullPresence,
3540
+ InlineSyncStatus,
3541
+ InlineSyncStatusIndicator,
3160
3542
  JoinDialog,
3161
3543
  MenuFooter,
3162
3544
  MessageState,
@@ -3175,6 +3557,7 @@ export {
3175
3557
  SmallPresence,
3176
3558
  SmallPresenceLive,
3177
3559
  SpaceAction,
3560
+ SpaceForm,
3178
3561
  SpacePlugin,
3179
3562
  SpacePluginSettings,
3180
3563
  SpacePresence,
@@ -3186,9 +3569,7 @@ export {
3186
3569
  ThreadStatus,
3187
3570
  ThreadType,
3188
3571
  cloneObject,
3189
- constructObjectActionGroups,
3190
3572
  constructObjectActions,
3191
- constructSpaceActionGroups,
3192
3573
  constructSpaceActions,
3193
3574
  constructSpaceNode,
3194
3575
  createObjectNode,
@@ -3197,7 +3578,7 @@ export {
3197
3578
  getNestedObjects,
3198
3579
  getSpaceDisplayName,
3199
3580
  memoizeQuery,
3200
- parseSpaceInitPlugin,
3581
+ parseSchemaPlugin,
3201
3582
  parseSpacePlugin,
3202
3583
  translations_default as translations
3203
3584
  };