@dxos/react-ui 0.1.26 → 0.1.27-next.6f5e1d5

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 (142) hide show
  1. package/dist/lib/browser/index.mjs +1025 -473
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/components/IdentityList/DeviceList.d.ts +7 -0
  5. package/dist/types/src/components/IdentityList/DeviceList.d.ts.map +1 -0
  6. package/dist/types/src/components/IdentityList/IdentityListItem.d.ts +4 -3
  7. package/dist/types/src/components/IdentityList/IdentityListItem.d.ts.map +1 -1
  8. package/dist/types/src/components/IdentityList/IdentityListItem.stories.d.ts +3 -2
  9. package/dist/types/src/components/IdentityList/IdentityListItem.stories.d.ts.map +1 -1
  10. package/dist/types/src/components/IdentityList/SpaceMemberList.d.ts +3 -2
  11. package/dist/types/src/components/IdentityList/SpaceMemberList.d.ts.map +1 -1
  12. package/dist/types/src/components/IdentityList/SpaceMemberListContainer.d.ts +3 -1
  13. package/dist/types/src/components/IdentityList/SpaceMemberListContainer.d.ts.map +1 -1
  14. package/dist/types/src/components/IdentityList/index.d.ts +1 -0
  15. package/dist/types/src/components/IdentityList/index.d.ts.map +1 -1
  16. package/dist/types/src/components/InvitationList/InvitationList.d.ts.map +1 -1
  17. package/dist/types/src/components/InvitationList/InvitationListItem.d.ts.map +1 -1
  18. package/dist/types/src/components/InvitationList/InvitationStatusAvatar.d.ts +6 -1
  19. package/dist/types/src/components/InvitationList/InvitationStatusAvatar.d.ts.map +1 -1
  20. package/dist/types/src/components/InvitationList/InvitationStatusAvatar.stories.d.ts +1 -1
  21. package/dist/types/src/components/SpaceList/SpaceListItem.d.ts +7 -0
  22. package/dist/types/src/components/SpaceList/SpaceListItem.d.ts.map +1 -0
  23. package/dist/types/src/components/SpaceList/index.d.ts +2 -0
  24. package/dist/types/src/components/SpaceList/index.d.ts.map +1 -0
  25. package/dist/types/src/components/index.d.ts +1 -0
  26. package/dist/types/src/components/index.d.ts.map +1 -1
  27. package/dist/types/src/composites/DevicesDialog/DevicesDialog.d.ts +6 -0
  28. package/dist/types/src/composites/DevicesDialog/DevicesDialog.d.ts.map +1 -0
  29. package/dist/types/src/composites/DevicesDialog/index.d.ts +2 -0
  30. package/dist/types/src/composites/DevicesDialog/index.d.ts.map +1 -0
  31. package/dist/types/src/composites/IdentityPopover/IdentityPopover.d.ts +2 -2
  32. package/dist/types/src/composites/IdentityPopover/IdentityPopover.d.ts.map +1 -1
  33. package/dist/types/src/composites/JoinDialog/JoinDialog.d.ts +1 -1
  34. package/dist/types/src/composites/JoinDialog/JoinDialog.d.ts.map +1 -1
  35. package/dist/types/src/composites/JoinDialog/JoinDialog.stories.d.ts +2 -2
  36. package/dist/types/src/composites/JoinDialog/JoinDialog.stories.d.ts.map +1 -1
  37. package/dist/types/src/composites/Shell/Shell.d.ts +6 -0
  38. package/dist/types/src/composites/Shell/Shell.d.ts.map +1 -0
  39. package/dist/types/src/composites/Shell/index.d.ts +2 -0
  40. package/dist/types/src/composites/Shell/index.d.ts.map +1 -0
  41. package/dist/types/src/composites/SpaceDialog/SpaceDialog.d.ts +6 -0
  42. package/dist/types/src/composites/SpaceDialog/SpaceDialog.d.ts.map +1 -0
  43. package/dist/types/src/composites/SpaceDialog/index.d.ts +2 -0
  44. package/dist/types/src/composites/SpaceDialog/index.d.ts.map +1 -0
  45. package/dist/types/src/composites/index.d.ts +2 -0
  46. package/dist/types/src/composites/index.d.ts.map +1 -1
  47. package/dist/types/src/layouts/PanelAlertDialog/PanelAlertDialog.d.ts.map +1 -1
  48. package/dist/types/src/layouts/PanelDialog/PanelDialog.d.ts +14 -0
  49. package/dist/types/src/layouts/PanelDialog/PanelDialog.d.ts.map +1 -0
  50. package/dist/types/src/layouts/PanelDialog/index.d.ts +2 -0
  51. package/dist/types/src/layouts/PanelDialog/index.d.ts.map +1 -0
  52. package/dist/types/src/layouts/index.d.ts +1 -0
  53. package/dist/types/src/layouts/index.d.ts.map +1 -1
  54. package/dist/types/src/panels/DevicesPanel/DevicesPanel.d.ts +10 -0
  55. package/dist/types/src/panels/DevicesPanel/DevicesPanel.d.ts.map +1 -0
  56. package/dist/types/src/panels/DevicesPanel/index.d.ts +2 -0
  57. package/dist/types/src/panels/DevicesPanel/index.d.ts.map +1 -0
  58. package/dist/types/src/panels/IdentityPanel/IdentityPanel.d.ts +2 -2
  59. package/dist/types/src/panels/IdentityPanel/IdentityPanel.d.ts.map +1 -1
  60. package/dist/types/src/panels/JoinPanel/JoinHeading.d.ts +3 -0
  61. package/dist/types/src/panels/JoinPanel/JoinHeading.d.ts.map +1 -1
  62. package/dist/types/src/panels/JoinPanel/JoinPanel.d.ts +1 -1
  63. package/dist/types/src/panels/JoinPanel/JoinPanel.d.ts.map +1 -1
  64. package/dist/types/src/panels/JoinPanel/JoinPanelProps.d.ts +6 -5
  65. package/dist/types/src/panels/JoinPanel/JoinPanelProps.d.ts.map +1 -1
  66. package/dist/types/src/panels/JoinPanel/view-states/AdditionMethodSelector.d.ts +2 -2
  67. package/dist/types/src/panels/JoinPanel/view-states/AdditionMethodSelector.d.ts.map +1 -1
  68. package/dist/types/src/panels/JoinPanel/view-states/IdentityAdded.d.ts +12 -4
  69. package/dist/types/src/panels/JoinPanel/view-states/IdentityAdded.d.ts.map +1 -1
  70. package/dist/types/src/panels/JoinPanel/view-states/IdentityInput.d.ts.map +1 -1
  71. package/dist/types/src/panels/JoinPanel/view-states/IdentitySelector.d.ts +2 -2
  72. package/dist/types/src/panels/JoinPanel/view-states/IdentitySelector.d.ts.map +1 -1
  73. package/dist/types/src/panels/JoinPanel/view-states/InvitationAccepted.d.ts.map +1 -1
  74. package/dist/types/src/panels/JoinPanel/view-states/InvitationAuthenticator.d.ts.map +1 -1
  75. package/dist/types/src/panels/JoinPanel/view-states/InvitationInput.d.ts.map +1 -1
  76. package/dist/types/src/panels/JoinPanel/view-states/InvitationRescuer.d.ts.map +1 -1
  77. package/dist/types/src/panels/JoinPanel/view-states/ViewState.d.ts +2 -2
  78. package/dist/types/src/panels/JoinPanel/view-states/ViewState.d.ts.map +1 -1
  79. package/dist/types/src/panels/SpacePanel/SpacePanel.d.ts +12 -0
  80. package/dist/types/src/panels/SpacePanel/SpacePanel.d.ts.map +1 -0
  81. package/dist/types/src/panels/SpacePanel/SpacePanel.stories.d.ts +9 -0
  82. package/dist/types/src/panels/SpacePanel/SpacePanel.stories.d.ts.map +1 -0
  83. package/dist/types/src/panels/SpacePanel/index.d.ts +2 -0
  84. package/dist/types/src/panels/SpacePanel/index.d.ts.map +1 -0
  85. package/dist/types/src/panels/index.d.ts +2 -0
  86. package/dist/types/src/panels/index.d.ts.map +1 -1
  87. package/dist/types/src/styles/dialogStyles.d.ts +3 -0
  88. package/dist/types/src/styles/dialogStyles.d.ts.map +1 -0
  89. package/dist/types/src/styles/index.d.ts +1 -0
  90. package/dist/types/src/styles/index.d.ts.map +1 -1
  91. package/dist/types/src/translations/locales/en-US.d.ts +12 -1
  92. package/dist/types/src/translations/locales/en-US.d.ts.map +1 -1
  93. package/package.json +12 -11
  94. package/src/components/IdentityList/DeviceList.tsx +31 -0
  95. package/src/components/IdentityList/IdentityListItem.tsx +17 -5
  96. package/src/components/IdentityList/SpaceMemberList.tsx +10 -8
  97. package/src/components/IdentityList/SpaceMemberListContainer.tsx +7 -6
  98. package/src/components/IdentityList/index.ts +1 -0
  99. package/src/components/InvitationList/InvitationList.stories.tsx +1 -1
  100. package/src/components/InvitationList/InvitationList.tsx +12 -6
  101. package/src/components/InvitationList/InvitationListItem.tsx +30 -25
  102. package/src/components/InvitationList/InvitationStatusAvatar.tsx +10 -5
  103. package/src/components/SpaceList/SpaceListItem.tsx +32 -0
  104. package/src/components/SpaceList/index.ts +5 -0
  105. package/src/components/index.ts +1 -0
  106. package/src/composites/DevicesDialog/DevicesDialog.tsx +38 -0
  107. package/src/composites/DevicesDialog/index.ts +5 -0
  108. package/src/composites/IdentityPopover/IdentityPopover.tsx +3 -3
  109. package/src/composites/JoinDialog/JoinDialog.stories.tsx +59 -58
  110. package/src/composites/JoinDialog/JoinDialog.tsx +3 -1
  111. package/src/composites/Shell/Shell.tsx +86 -0
  112. package/src/composites/Shell/index.ts +5 -0
  113. package/src/composites/SpaceDialog/SpaceDialog.tsx +38 -0
  114. package/src/composites/SpaceDialog/index.ts +5 -0
  115. package/src/composites/index.ts +3 -0
  116. package/src/layouts/PanelAlertDialog/PanelAlertDialog.tsx +4 -8
  117. package/src/layouts/PanelDialog/PanelDialog.tsx +41 -0
  118. package/src/layouts/PanelDialog/index.ts +5 -0
  119. package/src/layouts/PanelSidebar/PanelSidebar.tsx +1 -1
  120. package/src/layouts/index.ts +1 -0
  121. package/src/panels/DevicesPanel/DevicesPanel.tsx +101 -0
  122. package/src/panels/DevicesPanel/index.ts +5 -0
  123. package/src/panels/IdentityPanel/IdentityPanel.tsx +5 -5
  124. package/src/panels/JoinPanel/JoinHeading.tsx +41 -19
  125. package/src/panels/JoinPanel/JoinPanel.tsx +35 -14
  126. package/src/panels/JoinPanel/JoinPanelProps.ts +6 -10
  127. package/src/panels/JoinPanel/view-states/AdditionMethodSelector.tsx +8 -2
  128. package/src/panels/JoinPanel/view-states/IdentityAdded.tsx +67 -28
  129. package/src/panels/JoinPanel/view-states/IdentityInput.tsx +9 -2
  130. package/src/panels/JoinPanel/view-states/IdentitySelector.tsx +8 -6
  131. package/src/panels/JoinPanel/view-states/InvitationAccepted.tsx +1 -0
  132. package/src/panels/JoinPanel/view-states/InvitationAuthenticator.tsx +4 -1
  133. package/src/panels/JoinPanel/view-states/InvitationInput.tsx +8 -1
  134. package/src/panels/JoinPanel/view-states/InvitationRescuer.tsx +4 -1
  135. package/src/panels/JoinPanel/view-states/ViewState.tsx +3 -3
  136. package/src/panels/SpacePanel/SpacePanel.stories.tsx +53 -0
  137. package/src/panels/SpacePanel/SpacePanel.tsx +90 -0
  138. package/src/panels/SpacePanel/index.ts +5 -0
  139. package/src/panels/index.ts +2 -0
  140. package/src/styles/dialogStyles.ts +8 -0
  141. package/src/styles/index.ts +1 -0
  142. package/src/translations/locales/en-US.ts +14 -3
@@ -4,10 +4,13 @@ var __export = (target, all) => {
4
4
  __defProp(target, name, { get: all[name], enumerable: true });
5
5
  };
6
6
 
7
+ // packages/apps/patterns/react-ui/src/components/IdentityList/DeviceList.tsx
8
+ import React2 from "react";
9
+
7
10
  // packages/apps/patterns/react-ui/src/components/IdentityList/IdentityListItem.tsx
8
11
  import React from "react";
9
12
  import { SpaceMember } from "@dxos/client";
10
- import { Avatar, useTranslation } from "@dxos/react-components";
13
+ import { Avatar, mx, useTranslation } from "@dxos/react-components";
11
14
  function _extends() {
12
15
  _extends = Object.assign || function(target) {
13
16
  for (var i = 1; i < arguments.length; i++) {
@@ -22,18 +25,20 @@ function _extends() {
22
25
  };
23
26
  return _extends.apply(this, arguments);
24
27
  }
25
- var IdentityListItem = ({ identity, presence }) => {
26
- var _a;
28
+ var IdentityListItem = ({ identity, presence, onClick }) => {
29
+ var _a, _b;
27
30
  const { t } = useTranslation("os");
28
31
  return /* @__PURE__ */ React.createElement("li", {
29
- className: "flex gap-2 items-center"
32
+ className: mx("flex gap-2 items-center", onClick && "cursor-pointer"),
33
+ onClick: () => onClick == null ? void 0 : onClick(),
34
+ "data-testid": "identity-list-item"
30
35
  }, /* @__PURE__ */ React.createElement(Avatar, _extends({}, {
31
36
  variant: "circle",
32
37
  size: 9,
33
38
  fallbackValue: identity.identityKey.toHex(),
34
39
  label: /* @__PURE__ */ React.createElement("p", {
35
40
  className: "text-sm truncate"
36
- }, (_a = identity.displayName) != null ? _a : identity.identityKey.truncate()),
41
+ }, (_b = (_a = identity.profile) == null ? void 0 : _a.displayName) != null ? _b : identity.identityKey.truncate()),
37
42
  ...presence === SpaceMember.PresenceState.OFFLINE && {
38
43
  status: "inactive",
39
44
  description: /* @__PURE__ */ React.createElement("p", {
@@ -54,38 +59,64 @@ var IdentityListItem = ({ identity, presence }) => {
54
59
  })));
55
60
  };
56
61
 
57
- // packages/apps/patterns/react-ui/src/components/IdentityList/SpaceMemberList.tsx
58
- import React2 from "react";
59
- var SpaceMemberList = ({ spaceMembers }) => {
62
+ // packages/apps/patterns/react-ui/src/components/IdentityList/DeviceList.tsx
63
+ var DeviceList = ({ devices, onSelect }) => {
60
64
  return /* @__PURE__ */ React2.createElement("ul", {
61
65
  className: "flex flex-col gap-2"
62
- }, spaceMembers.filter((spaceMember) => spaceMember.profile).map((spaceMember) => {
66
+ }, devices.map((device) => {
67
+ var _a;
68
+ const identity = {
69
+ identityKey: device.deviceKey,
70
+ profile: {
71
+ displayName: (_a = device.profile) == null ? void 0 : _a.displayName
72
+ }
73
+ };
63
74
  return /* @__PURE__ */ React2.createElement(IdentityListItem, {
64
- key: spaceMember.identityKey.toHex(),
65
- identity: spaceMember.profile,
66
- presence: spaceMember.presence
75
+ key: device.deviceKey.toHex(),
76
+ identity,
77
+ onClick: onSelect && (() => onSelect(device))
78
+ });
79
+ }));
80
+ };
81
+
82
+ // packages/apps/patterns/react-ui/src/components/IdentityList/SpaceMemberList.tsx
83
+ import React3 from "react";
84
+ var SpaceMemberList = ({ members, onSelect }) => {
85
+ return /* @__PURE__ */ React3.createElement("ul", {
86
+ className: "flex flex-col gap-2"
87
+ }, members.filter((member) => member.identity).map((member) => {
88
+ return /* @__PURE__ */ React3.createElement(IdentityListItem, {
89
+ key: member.identity.identityKey.toHex(),
90
+ identity: member.identity,
91
+ presence: member.presence,
92
+ onClick: onSelect && (() => onSelect(member))
67
93
  });
68
94
  }));
69
95
  };
70
96
 
71
97
  // packages/apps/patterns/react-ui/src/components/IdentityList/SpaceMemberListContainer.tsx
72
- import React3, { useMemo } from "react";
98
+ import React4, { useMemo } from "react";
73
99
  import { useClient, useMembers } from "@dxos/react-client";
74
- var SpaceMemberListContainer = ({ spaceKey, includeSelf }) => {
100
+ var SpaceMemberListContainer = ({ spaceKey, includeSelf, onSelect }) => {
75
101
  const client = useClient();
76
102
  const allUnsortedMembers = useMembers(spaceKey);
77
- const spaceMembers = useMemo(() => includeSelf ? allUnsortedMembers.sort((a) => a.identityKey.equals(client.halo.profile.identityKey) ? -1 : 1) : allUnsortedMembers.filter((member) => !member.identityKey.equals(client.halo.profile.identityKey)), [
103
+ const members = useMemo(() => includeSelf ? allUnsortedMembers.sort((a) => a.identity.identityKey.equals(client.halo.identity.identityKey) ? -1 : 1) : allUnsortedMembers.filter((member) => !member.identity.identityKey.equals(client.halo.identity.identityKey)), [
78
104
  allUnsortedMembers
79
105
  ]);
80
- return /* @__PURE__ */ React3.createElement(SpaceMemberList, {
81
- spaceMembers
106
+ return /* @__PURE__ */ React4.createElement(SpaceMemberList, {
107
+ members,
108
+ onSelect
82
109
  });
83
110
  };
84
111
 
85
112
  // packages/apps/patterns/react-ui/src/components/InvitationList/InvitationStatusAvatar.tsx
86
- import React4 from "react";
113
+ import React5 from "react";
87
114
  import { Invitation as Invitation3 } from "@dxos/client";
88
- import { getSize } from "@dxos/react-components";
115
+ import { getSize, mx as mx2 } from "@dxos/react-components";
116
+
117
+ // packages/apps/patterns/react-ui/src/styles/dialogStyles.ts
118
+ var defaultOverlay = "fixed inset-0 backdrop-blur z-50 overflow-auto grid place-items-center p-2 md:p-4 lg:p-8";
119
+ var defaultDialogContent = "is-full min-is-[260px] max-is-[320px] rounded-md shadow-md backdrop-blur-md";
89
120
 
90
121
  // packages/apps/patterns/react-ui/src/styles/panelStyles.ts
91
122
  var defaultSurface = "bg-neutral-50/[.72] dark:bg-neutral-950/[.72]";
@@ -166,7 +197,7 @@ function _extends2() {
166
197
  return _extends2.apply(this, arguments);
167
198
  }
168
199
  var svgSize = 32;
169
- var strokeWidth = 4;
200
+ var strokeWidth = 5;
170
201
  var radius = (svgSize - strokeWidth) / 2;
171
202
  var circumference = Math.PI * 2 * radius;
172
203
  var gap = circumference / 12;
@@ -179,19 +210,20 @@ var circleProps = {
179
210
  cx: svgSize / 2,
180
211
  cy: svgSize / 2,
181
212
  r: radius,
182
- strokeWidth: 4,
213
+ strokeWidth,
183
214
  strokeDasharray: `${segment - gap} ${2 * segment + gap}`
184
215
  };
185
- var InvitationStatusAvatar = ({ size = 10, status, haltedAt }) => {
216
+ var InvitationStatusAvatar = ({ size = 10, status, haltedAt, slots = {} }) => {
217
+ var _a;
186
218
  const resolvedColor = resolvedStrokeColor(status);
187
219
  const halted = status === Invitation3.State.CANCELLED || status === Invitation3.State.TIMEOUT || status === Invitation3.State.ERROR;
188
220
  const cursor = invitationStatusValue.get(halted ? haltedAt : status);
189
- return /* @__PURE__ */ React4.createElement("svg", {
221
+ return /* @__PURE__ */ React5.createElement("svg", _extends2({}, slots.svg, {
190
222
  viewBox: `0 0 ${svgSize} ${svgSize}`,
191
- className: getSize(size)
192
- }, [
223
+ className: mx2(getSize(size), (_a = slots.svg) == null ? void 0 : _a.className)
224
+ }), [
193
225
  ...Array(nSegments)
194
- ].map((_, index) => /* @__PURE__ */ React4.createElement("circle", _extends2({
226
+ ].map((_, index) => /* @__PURE__ */ React5.createElement("circle", _extends2({
195
227
  key: index
196
228
  }, circleProps, {
197
229
  strokeDashoffset: index * segment + baseOffset,
@@ -203,9 +235,9 @@ var InvitationStatusAvatar = ({ size = 10, status, haltedAt }) => {
203
235
  import * as AccordionPrimitive from "@radix-ui/react-accordion";
204
236
  import { Copy, ProhibitInset, QrCode, X } from "phosphor-react";
205
237
  import { QRCodeSVG } from "qrcode.react";
206
- import React5, { useCallback } from "react";
238
+ import React6, { useCallback } from "react";
207
239
  import { useInvitationStatus } from "@dxos/react-client";
208
- import { Button, getSize as getSize2, mx, useTranslation as useTranslation2 } from "@dxos/react-components";
240
+ import { Button, getSize as getSize2, mx as mx3, useId, useTranslation as useTranslation2 } from "@dxos/react-components";
209
241
  function _extends3() {
210
242
  _extends3 = Object.assign || function(target) {
211
243
  for (var i = 1; i < arguments.length; i++) {
@@ -223,85 +255,96 @@ function _extends3() {
223
255
  var InvitationListItem = ({ invitation, value, onClickRemove, createInvitationUrl }) => {
224
256
  var _a;
225
257
  const { t } = useTranslation2("os");
258
+ const qrLabel = useId("qrLabel");
226
259
  const { cancel, status, haltedAt, invitationCode, authenticationCode } = useInvitationStatus(invitation);
227
260
  const statusValue = (_a = invitationStatusValue.get(status)) != null ? _a : 0;
228
261
  const isCancellable = statusValue < 4 && statusValue >= 0;
229
262
  const showShare = statusValue < 3 && statusValue >= 0;
230
- const showPin = statusValue === 3;
263
+ const showAuthCode = statusValue === 3;
231
264
  const handleClickRemove = useCallback(() => onClickRemove(invitation), [
232
265
  invitation,
233
266
  onClickRemove
234
267
  ]);
235
268
  const invitationUrl = invitationCode && createInvitationUrl(invitationCode);
236
- const handleCLickCopy = useCallback(() => {
269
+ const handleClickCopy = useCallback(() => {
237
270
  if (invitationUrl) {
238
271
  void navigator.clipboard.writeText(invitationUrl);
239
272
  }
240
273
  }, [
241
274
  invitationUrl
242
275
  ]);
243
- return /* @__PURE__ */ React5.createElement(AccordionPrimitive.Item, {
276
+ return /* @__PURE__ */ React6.createElement(AccordionPrimitive.Item, {
244
277
  value
245
- }, /* @__PURE__ */ React5.createElement(AccordionPrimitive.Header, {
278
+ }, /* @__PURE__ */ React6.createElement(AccordionPrimitive.Header, {
246
279
  className: "flex gap-2 items-center"
247
- }, /* @__PURE__ */ React5.createElement(InvitationStatusAvatar, _extends3({}, {
280
+ }, /* @__PURE__ */ React6.createElement(InvitationStatusAvatar, _extends3({}, {
248
281
  status,
249
- haltedAt
250
- })), showShare && invitationUrl ? /* @__PURE__ */ React5.createElement(AccordionPrimitive.Trigger, {
282
+ haltedAt,
283
+ size: 8
284
+ })), showShare && invitationUrl ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(AccordionPrimitive.Trigger, {
251
285
  asChild: true
252
- }, /* @__PURE__ */ React5.createElement(Button, {
253
- className: "grow flex gap-1"
254
- }, /* @__PURE__ */ React5.createElement("span", null, t("open share panel label")), /* @__PURE__ */ React5.createElement(QrCode, {
286
+ }, /* @__PURE__ */ React6.createElement(Button, {
287
+ className: "grow flex gap-1",
288
+ "data-testid": "show-qrcode"
289
+ }, /* @__PURE__ */ React6.createElement("span", null, t("open share panel label")), /* @__PURE__ */ React6.createElement(QrCode, {
290
+ className: getSize2(4),
291
+ weight: "bold"
292
+ }))), /* @__PURE__ */ React6.createElement(Button, {
293
+ className: "flex gap-1",
294
+ onClick: handleClickCopy,
295
+ "data-testid": "copy-invitation"
296
+ }, /* @__PURE__ */ React6.createElement("span", {
297
+ className: "pli-1"
298
+ }, t("copy invitation code label")), /* @__PURE__ */ React6.createElement(Copy, {
255
299
  className: getSize2(4),
256
300
  weight: "bold"
257
- }))) : showPin ? /* @__PURE__ */ React5.createElement("p", {
301
+ }))) : showAuthCode ? /* @__PURE__ */ React6.createElement("p", {
258
302
  className: "grow text-xl text-center text-success-500 dark:text-success-300 font-mono"
259
- }, authenticationCode) : /* @__PURE__ */ React5.createElement("span", {
303
+ }, authenticationCode) : /* @__PURE__ */ React6.createElement("span", {
260
304
  role: "none",
261
305
  className: "grow"
262
- }), isCancellable ? /* @__PURE__ */ React5.createElement(Button, {
306
+ }), isCancellable ? /* @__PURE__ */ React6.createElement(Button, {
263
307
  variant: "ghost",
264
- compact: true,
265
308
  className: "flex gap-1",
266
- onClick: cancel
267
- }, /* @__PURE__ */ React5.createElement("span", {
309
+ onClick: cancel,
310
+ "data-testid": "cancel-invitation"
311
+ }, /* @__PURE__ */ React6.createElement("span", {
268
312
  className: "sr-only"
269
- }, t("cancel invitation label")), /* @__PURE__ */ React5.createElement(ProhibitInset, {
313
+ }, t("cancel invitation label")), /* @__PURE__ */ React6.createElement(ProhibitInset, {
270
314
  className: getSize2(4),
271
315
  weight: "bold"
272
- })) : /* @__PURE__ */ React5.createElement(Button, {
316
+ })) : /* @__PURE__ */ React6.createElement(Button, {
273
317
  variant: "ghost",
274
- compact: true,
275
318
  className: "flex gap-1",
276
- onClick: handleClickRemove
277
- }, /* @__PURE__ */ React5.createElement("span", {
319
+ onClick: handleClickRemove,
320
+ "data-testid": "remove-invitation"
321
+ }, /* @__PURE__ */ React6.createElement("span", {
278
322
  className: "sr-only"
279
- }, t("remove invitation label")), /* @__PURE__ */ React5.createElement(X, {
323
+ }, t("remove invitation label")), /* @__PURE__ */ React6.createElement(X, {
280
324
  className: getSize2(4),
281
325
  weight: "bold"
282
- }))), showShare && invitationUrl && /* @__PURE__ */ React5.createElement(AccordionPrimitive.Content, null, /* @__PURE__ */ React5.createElement(Button, {
283
- className: "flex gap-2 is-full p-2",
284
- onClick: handleCLickCopy
285
- }, /* @__PURE__ */ React5.createElement(QRCodeSVG, {
326
+ }))), showShare && invitationUrl && /* @__PURE__ */ React6.createElement(AccordionPrimitive.Content, {
327
+ className: "flex gap-2 is-full radix-state-open:p-1 items-center"
328
+ }, /* @__PURE__ */ React6.createElement(QRCodeSVG, {
286
329
  bgColor: "transparent",
287
330
  fgColor: "currentColor",
288
331
  value: invitationUrl,
289
- className: mx("grow aspect-square is-24 bs-auto")
290
- }), /* @__PURE__ */ React5.createElement("span", {
291
- className: "pli-1"
292
- }, t("copy invitation code label"), /* @__PURE__ */ React5.createElement(Copy, {
293
- className: mx(getSize2(4), "inline mis-1"),
294
- weight: "bold"
295
- })))));
332
+ className: mx3("grow-[2] aspect-square is-24 bs-auto"),
333
+ "aria-labelledby": qrLabel
334
+ }), /* @__PURE__ */ React6.createElement("span", {
335
+ className: "pli-1 flex-1 font-system-normal text-sm text-center",
336
+ id: qrLabel
337
+ }, t("qr label"))));
296
338
  };
297
339
 
298
340
  // packages/apps/patterns/react-ui/src/components/InvitationList/InvitationListContainer.tsx
299
- import React7, { useCallback as useCallback2 } from "react";
341
+ import React8, { useCallback as useCallback2 } from "react";
300
342
  import { useSpace, useSpaceInvitations } from "@dxos/react-client";
301
343
 
302
344
  // packages/apps/patterns/react-ui/src/components/InvitationList/InvitationList.tsx
303
345
  import { Root as AccordionRoot } from "@radix-ui/react-accordion";
304
- import React6 from "react";
346
+ import React7 from "react";
347
+ import { defaultDescription, DensityProvider, mx as mx4, useTranslation as useTranslation3 } from "@dxos/react-components";
305
348
  function _extends4() {
306
349
  _extends4 = Object.assign || function(target) {
307
350
  for (var i = 1; i < arguments.length; i++) {
@@ -317,18 +360,24 @@ function _extends4() {
317
360
  return _extends4.apply(this, arguments);
318
361
  }
319
362
  var InvitationList = ({ invitations, ...invitationProps }) => {
320
- return /* @__PURE__ */ React6.createElement(AccordionRoot, {
363
+ const { t } = useTranslation3("os");
364
+ return invitations.length ? /* @__PURE__ */ React7.createElement(AccordionRoot, {
321
365
  type: "single",
322
- collapsible: true
366
+ collapsible: true,
367
+ className: "flex flex-col gap-1"
368
+ }, /* @__PURE__ */ React7.createElement(DensityProvider, {
369
+ density: "fine"
323
370
  }, invitations.map((invitation, index) => {
324
371
  var _a, _b;
325
372
  const value = (_b = (_a = invitation.invitation) == null ? void 0 : _a.invitationId) != null ? _b : `inv_${index}`;
326
- return /* @__PURE__ */ React6.createElement(InvitationListItem, _extends4({
373
+ return /* @__PURE__ */ React7.createElement(InvitationListItem, _extends4({
327
374
  key: value,
328
375
  value,
329
376
  invitation
330
377
  }, invitationProps));
331
- }));
378
+ }))) : /* @__PURE__ */ React7.createElement("p", {
379
+ className: mx4(defaultDescription, "text-center p-2")
380
+ }, t("empty invitations message"));
332
381
  };
333
382
 
334
383
  // packages/apps/patterns/react-ui/src/components/InvitationList/InvitationListContainer.tsx
@@ -354,7 +403,7 @@ var InvitationListContainer = ({ spaceKey, createInvitationUrl }) => {
354
403
  }, [
355
404
  space
356
405
  ]);
357
- return /* @__PURE__ */ React7.createElement(InvitationList, _extends5({
406
+ return /* @__PURE__ */ React8.createElement(InvitationList, _extends5({
358
407
  invitations
359
408
  }, {
360
409
  onClickRemove,
@@ -363,8 +412,8 @@ var InvitationListContainer = ({ spaceKey, createInvitationUrl }) => {
363
412
  };
364
413
 
365
414
  // packages/apps/patterns/react-ui/src/components/PanelSeparator/PanelSeparator.tsx
366
- import React8 from "react";
367
- import { mx as mx2 } from "@dxos/react-components";
415
+ import React9 from "react";
416
+ import { mx as mx5 } from "@dxos/react-components";
368
417
  function _extends6() {
369
418
  _extends6 = Object.assign || function(target) {
370
419
  for (var i = 1; i < arguments.length; i++) {
@@ -380,20 +429,17 @@ function _extends6() {
380
429
  return _extends6.apply(this, arguments);
381
430
  }
382
431
  var PanelSeparator = ({ className, ...props }) => {
383
- return /* @__PURE__ */ React8.createElement("span", _extends6({
432
+ return /* @__PURE__ */ React9.createElement("span", _extends6({
384
433
  role: "none"
385
434
  }, props, {
386
- className: mx2("block bs-px mlb-1 bg-neutral-800/10 dark:bg-neutral-200/10", className)
435
+ className: mx5("block bs-px mlb-1 bg-neutral-800/10 dark:bg-neutral-200/10", className)
387
436
  }));
388
437
  };
389
438
 
390
- // packages/apps/patterns/react-ui/src/composites/IdentityPopover/IdentityPopover.tsx
391
- import React24 from "react";
392
- import { Avatar as Avatar7, mx as mx16 } from "@dxos/react-components";
393
-
394
- // packages/apps/patterns/react-ui/src/layouts/PanelPopover/PanelPopover.tsx
395
- import React9 from "react";
396
- import { mx as mx3, Popover } from "@dxos/react-components";
439
+ // packages/apps/patterns/react-ui/src/components/SpaceList/SpaceListItem.tsx
440
+ import React10, { forwardRef } from "react";
441
+ import { Avatar as Avatar2, mx as mx6 } from "@dxos/react-components";
442
+ import { humanize } from "@dxos/util";
397
443
  function _extends7() {
398
444
  _extends7 = Object.assign || function(target) {
399
445
  for (var i = 1; i < arguments.length; i++) {
@@ -408,23 +454,69 @@ function _extends7() {
408
454
  };
409
455
  return _extends7.apply(this, arguments);
410
456
  }
457
+ var SpaceListItem = /* @__PURE__ */ forwardRef(({ space, onClick }, ref) => {
458
+ var _a;
459
+ return /* @__PURE__ */ React10.createElement("li", {
460
+ className: mx6("flex gap-2 items-center", onClick && "cursor-pointer"),
461
+ onClick: () => onClick == null ? void 0 : onClick(),
462
+ ref,
463
+ "data-testid": "space-list-item"
464
+ }, /* @__PURE__ */ React10.createElement(Avatar2, _extends7({}, {
465
+ variant: "circle",
466
+ size: 9,
467
+ fallbackValue: space.key.toHex(),
468
+ label: /* @__PURE__ */ React10.createElement("p", {
469
+ className: "text-sm truncate"
470
+ }, (_a = space.properties.name) != null ? _a : humanize(space.key)),
471
+ slots: {
472
+ labels: {
473
+ className: "block shrink overflow-hidden"
474
+ },
475
+ root: {
476
+ className: "shrink-0"
477
+ }
478
+ }
479
+ })));
480
+ });
481
+
482
+ // packages/apps/patterns/react-ui/src/composites/IdentityPopover/IdentityPopover.tsx
483
+ import React29 from "react";
484
+ import { Avatar as Avatar8, mx as mx23 } from "@dxos/react-components";
485
+
486
+ // packages/apps/patterns/react-ui/src/layouts/PanelPopover/PanelPopover.tsx
487
+ import React11 from "react";
488
+ import { mx as mx7, Popover } from "@dxos/react-components";
489
+ function _extends8() {
490
+ _extends8 = Object.assign || function(target) {
491
+ for (var i = 1; i < arguments.length; i++) {
492
+ var source = arguments[i];
493
+ for (var key in source) {
494
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
495
+ target[key] = source[key];
496
+ }
497
+ }
498
+ }
499
+ return target;
500
+ };
501
+ return _extends8.apply(this, arguments);
502
+ }
411
503
  var PanelPopover = ({ slots, children, ...popoverProps }) => {
412
504
  var _a, _b, _c;
413
- return /* @__PURE__ */ React9.createElement(Popover, _extends7({
505
+ return /* @__PURE__ */ React11.createElement(Popover, _extends8({
414
506
  slots: {
415
507
  arrow: {
416
508
  ...slots == null ? void 0 : slots.arrow,
417
- className: mx3(defaultArrow, (_a = slots == null ? void 0 : slots.arrow) == null ? void 0 : _a.className)
509
+ className: mx7(defaultArrow, (_a = slots == null ? void 0 : slots.arrow) == null ? void 0 : _a.className)
418
510
  },
419
511
  content: {
420
512
  collisionPadding: 8,
421
513
  sideOffset: 4,
422
514
  ...slots == null ? void 0 : slots.content,
423
- className: mx3(defaultSurface, (_b = slots == null ? void 0 : slots.content) == null ? void 0 : _b.className)
515
+ className: mx7(defaultSurface, (_b = slots == null ? void 0 : slots.content) == null ? void 0 : _b.className)
424
516
  },
425
517
  trigger: {
426
518
  ...slots == null ? void 0 : slots.trigger,
427
- className: mx3("", (_c = slots == null ? void 0 : slots.trigger) == null ? void 0 : _c.className)
519
+ className: mx7("", (_c = slots == null ? void 0 : slots.trigger) == null ? void 0 : _c.className)
428
520
  },
429
521
  ...slots
430
522
  }
@@ -433,10 +525,10 @@ var PanelPopover = ({ slots, children, ...popoverProps }) => {
433
525
 
434
526
  // packages/apps/patterns/react-ui/src/layouts/PanelSidebar/PanelSidebar.tsx
435
527
  import * as DialogPrimitive from "@radix-ui/react-dialog";
436
- import React10, { createContext, useCallback as useCallback3, useContext, useState } from "react";
437
- import { defaultOverlay, mx as mx4, useMediaQuery, useTranslation as useTranslation3 } from "@dxos/react-components";
438
- function _extends8() {
439
- _extends8 = Object.assign || function(target) {
528
+ import React12, { createContext, useCallback as useCallback3, useContext, useState } from "react";
529
+ import { defaultOverlay as defaultOverlay2, mx as mx8, useMediaQuery, useTranslation as useTranslation4 } from "@dxos/react-components";
530
+ function _extends9() {
531
+ _extends9 = Object.assign || function(target) {
440
532
  for (var i = 1; i < arguments.length; i++) {
441
533
  var source = arguments[i];
442
534
  for (var key in source) {
@@ -447,7 +539,7 @@ function _extends8() {
447
539
  }
448
540
  return target;
449
541
  };
450
- return _extends8.apply(this, arguments);
542
+ return _extends9.apply(this, arguments);
451
543
  }
452
544
  var PanelSidebarContext = /* @__PURE__ */ createContext({
453
545
  displayState: "hide",
@@ -464,7 +556,7 @@ var useTogglePanelSidebar = () => {
464
556
  };
465
557
  var PanelSidebarProvider = ({ children, slots }) => {
466
558
  var _a, _b, _c;
467
- const { t } = useTranslation3("os");
559
+ const { t } = useTranslation4("os");
468
560
  const [isLg] = useMediaQuery("lg", {
469
561
  ssr: false
470
562
  });
@@ -487,37 +579,37 @@ var PanelSidebarProvider = ({ children, slots }) => {
487
579
  }, 0);
488
580
  };
489
581
  const setDisplayState = (displayState2) => displayState2 === "show" ? internalShow() : internalHide();
490
- return /* @__PURE__ */ React10.createElement(PanelSidebarContext.Provider, {
582
+ return /* @__PURE__ */ React12.createElement(PanelSidebarContext.Provider, {
491
583
  value: {
492
584
  setDisplayState,
493
585
  displayState
494
586
  }
495
- }, /* @__PURE__ */ React10.createElement(DialogPrimitive.Root, {
587
+ }, /* @__PURE__ */ React12.createElement(DialogPrimitive.Root, {
496
588
  open: domShow,
497
589
  modal: !isLg
498
- }, /* @__PURE__ */ React10.createElement(DialogPrimitive.Content, _extends8({
590
+ }, /* @__PURE__ */ React12.createElement(DialogPrimitive.Content, _extends9({
499
591
  onOpenAutoFocus: (event) => isLg && event.preventDefault(),
500
592
  onCloseAutoFocus: (event) => isLg && event.preventDefault()
501
593
  }, slots == null ? void 0 : slots.content, {
502
- className: mx4("fixed block-start-0 block-end-0 is-sidebar z-50 overscroll-contain overflow-x-hidden overflow-y-auto", "transition-[inset-inline-start,inset-inline-end] duration-200 ease-in-out", transitionShow ? "inline-start-0" : "-inline-start-sidebar", (_a = slots == null ? void 0 : slots.content) == null ? void 0 : _a.className)
503
- }), /* @__PURE__ */ React10.createElement(DialogPrimitive.Title, {
594
+ className: mx8("fixed block-start-0 block-end-0 is-sidebar z-30 overscroll-contain overflow-x-hidden overflow-y-auto", "transition-[inset-inline-start,inset-inline-end] duration-200 ease-in-out", transitionShow ? "inline-start-0" : "-inline-start-sidebar", (_a = slots == null ? void 0 : slots.content) == null ? void 0 : _a.className)
595
+ }), /* @__PURE__ */ React12.createElement(DialogPrimitive.Title, {
504
596
  className: "sr-only"
505
- }, t("sidebar label")), (_b = slots == null ? void 0 : slots.content) == null ? void 0 : _b.children), !isLg && /* @__PURE__ */ React10.createElement(DialogPrimitive.Overlay, {
506
- className: mx4(defaultOverlay, "transition-opacity duration-200 ease-in-out", transitionShow ? "opacity-100" : "opacity-0"),
597
+ }, t("sidebar label")), (_b = slots == null ? void 0 : slots.content) == null ? void 0 : _b.children), !isLg && /* @__PURE__ */ React12.createElement(DialogPrimitive.Overlay, {
598
+ className: mx8(defaultOverlay2, "transition-opacity duration-200 ease-in-out", transitionShow ? "opacity-100" : "opacity-0"),
507
599
  onClick: internalHide
508
- }), /* @__PURE__ */ React10.createElement("div", _extends8({
600
+ }), /* @__PURE__ */ React12.createElement("div", _extends9({
509
601
  role: "none"
510
602
  }, slots == null ? void 0 : slots.main, {
511
- className: mx4("transition-[padding-inline-start] duration-200 ease-in-out", isLg && isOpen ? "pis-sidebar" : "pis-0", (_c = slots == null ? void 0 : slots.main) == null ? void 0 : _c.className)
603
+ className: mx8("transition-[padding-inline-start] duration-200 ease-in-out", isLg && isOpen ? "pis-sidebar" : "pis-0", (_c = slots == null ? void 0 : slots.main) == null ? void 0 : _c.className)
512
604
  }), children)));
513
605
  };
514
606
 
515
607
  // packages/apps/patterns/react-ui/src/layouts/PanelAlertDialog/PanelAlertDialog.tsx
516
608
  import * as AlertDialog from "@radix-ui/react-alert-dialog";
517
- import React11 from "react";
518
- import { mx as mx5 } from "@dxos/react-components";
519
- function _extends9() {
520
- _extends9 = Object.assign || function(target) {
609
+ import React13 from "react";
610
+ import { mx as mx9 } from "@dxos/react-components";
611
+ function _extends10() {
612
+ _extends10 = Object.assign || function(target) {
521
613
  for (var i = 1; i < arguments.length; i++) {
522
614
  var source = arguments[i];
523
615
  for (var key in source) {
@@ -528,67 +620,186 @@ function _extends9() {
528
620
  }
529
621
  return target;
530
622
  };
531
- return _extends9.apply(this, arguments);
623
+ return _extends10.apply(this, arguments);
532
624
  }
533
625
  var PanelAlertDialog = ({ titleId, slots = {}, children }) => {
534
626
  var _a, _b;
535
- return /* @__PURE__ */ React11.createElement(AlertDialog.Root, _extends9({
627
+ return /* @__PURE__ */ React13.createElement(AlertDialog.Root, _extends10({
536
628
  defaultOpen: true
537
- }, slots.root), slots.trigger && /* @__PURE__ */ React11.createElement(AlertDialog.Trigger, _extends9({}, slots.trigger)), /* @__PURE__ */ React11.createElement(AlertDialog.Overlay, _extends9({}, slots.overlay, {
538
- className: mx5("fixed inset-0 backdrop-blur z-50 overflow-auto grid place-items-center p-2 md:p-4 lg:p-8", (_a = slots.overlay) == null ? void 0 : _a.className)
539
- }), /* @__PURE__ */ React11.createElement(AlertDialog.Content, _extends9({
629
+ }, slots.root), slots.trigger && /* @__PURE__ */ React13.createElement(AlertDialog.Trigger, _extends10({}, slots.trigger)), /* @__PURE__ */ React13.createElement(AlertDialog.Overlay, _extends10({}, slots.overlay, {
630
+ className: mx9(defaultOverlay, "z-40", (_a = slots.overlay) == null ? void 0 : _a.className)
631
+ }), /* @__PURE__ */ React13.createElement(AlertDialog.Content, _extends10({
540
632
  onEscapeKeyDown: (event) => event.preventDefault()
541
633
  }, slots.content, {
542
634
  "aria-labelledby": titleId,
543
- className: mx5("is-full min-is-[260px] max-is-[320px] shadow-md backdrop-blur-md", (_b = slots.content) == null ? void 0 : _b.className)
635
+ className: mx9(defaultDialogContent, (_b = slots.content) == null ? void 0 : _b.className)
544
636
  }), children)));
545
637
  };
546
638
 
547
- // packages/apps/patterns/react-ui/src/panels/IdentityPanel/IdentityPanel.tsx
548
- import React12 from "react";
549
- import { useClient as useClient2 } from "@dxos/react-client";
550
- import { Avatar as Avatar2, Button as Button2, ThemeContext, useTranslation as useTranslation4 } from "@dxos/react-components";
551
- var IdentityPanel = ({ identity, onClickManageProfile }) => {
639
+ // packages/apps/patterns/react-ui/src/layouts/PanelDialog/PanelDialog.tsx
640
+ import * as Dialog from "@radix-ui/react-dialog";
641
+ import React14 from "react";
642
+ import { mx as mx10 } from "@dxos/react-components";
643
+ function _extends11() {
644
+ _extends11 = Object.assign || function(target) {
645
+ for (var i = 1; i < arguments.length; i++) {
646
+ var source = arguments[i];
647
+ for (var key in source) {
648
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
649
+ target[key] = source[key];
650
+ }
651
+ }
652
+ }
653
+ return target;
654
+ };
655
+ return _extends11.apply(this, arguments);
656
+ }
657
+ var PanelDialog = ({ titleId, slots = {}, children }) => {
658
+ var _a, _b;
659
+ return /* @__PURE__ */ React14.createElement(Dialog.Root, _extends11({
660
+ defaultOpen: true
661
+ }, slots.root), slots.trigger && /* @__PURE__ */ React14.createElement(Dialog.Trigger, _extends11({}, slots.trigger)), /* @__PURE__ */ React14.createElement(Dialog.Overlay, _extends11({}, slots.overlay, {
662
+ className: mx10(defaultOverlay, "z-40", (_a = slots.overlay) == null ? void 0 : _a.className)
663
+ }), /* @__PURE__ */ React14.createElement(Dialog.Content, _extends11({
664
+ onOpenAutoFocus: (event) => event.preventDefault(),
665
+ onCloseAutoFocus: (event) => event.preventDefault()
666
+ }, slots.content, {
667
+ "aria-labelledby": titleId,
668
+ className: mx10(defaultDialogContent, (_b = slots.content) == null ? void 0 : _b.className)
669
+ }), children)));
670
+ };
671
+
672
+ // packages/apps/patterns/react-ui/src/panels/DevicesPanel/DevicesPanel.tsx
673
+ import { UserPlus, X as X2 } from "phosphor-react";
674
+ import React15, { cloneElement, useReducer } from "react";
675
+ import { useClient as useClient2, useDevices, useHaloInvitations, useIdentity } from "@dxos/react-client";
676
+ import { Button as Button2, DensityProvider as DensityProvider2, getSize as getSize3, mx as mx11, Tooltip, useTranslation as useTranslation5 } from "@dxos/react-components";
677
+ function _extends12() {
678
+ _extends12 = Object.assign || function(target) {
679
+ for (var i = 1; i < arguments.length; i++) {
680
+ var source = arguments[i];
681
+ for (var key in source) {
682
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
683
+ target[key] = source[key];
684
+ }
685
+ }
686
+ }
687
+ return target;
688
+ };
689
+ return _extends12.apply(this, arguments);
690
+ }
691
+ var DeviceListView = ({ createInvitationUrl, titleId, onDone, doneActionParent }) => {
552
692
  var _a;
553
- const { t } = useTranslation4("os");
693
+ const { t } = useTranslation5("os");
554
694
  const client = useClient2();
695
+ const identity = useIdentity();
696
+ const devices = useDevices();
697
+ const invitations = useHaloInvitations();
698
+ const displayName = (_a = identity == null ? void 0 : identity.profile) == null ? void 0 : _a.displayName;
699
+ if (!identity) {
700
+ return null;
701
+ }
702
+ const doneButton = /* @__PURE__ */ React15.createElement(Button2, {
703
+ variant: "ghost",
704
+ onClick: () => onDone == null ? void 0 : onDone(),
705
+ "data-testid": "show-all-spaces"
706
+ }, /* @__PURE__ */ React15.createElement(X2, {
707
+ className: getSize3(4),
708
+ weight: "bold"
709
+ }));
710
+ return /* @__PURE__ */ React15.createElement("div", {
711
+ role: "none",
712
+ className: "flex flex-col"
713
+ }, /* @__PURE__ */ React15.createElement("div", {
714
+ role: "none",
715
+ className: mx11(subduedSurface, "rounded-bs-md flex items-center p-2 gap-2")
716
+ }, /* @__PURE__ */ React15.createElement("h2", {
717
+ id: titleId,
718
+ className: mx11("grow font-system-medium", !displayName && "font-mono")
719
+ }, displayName != null ? displayName : identity.identityKey.truncate()), /* @__PURE__ */ React15.createElement(Tooltip, {
720
+ content: t("close label"),
721
+ zIndex: "z-50"
722
+ }, doneActionParent ? /* @__PURE__ */ cloneElement(doneActionParent, {}, doneButton) : doneButton)), /* @__PURE__ */ React15.createElement("div", {
723
+ role: "region",
724
+ className: mx11(defaultSurface, "rounded-be-md p-2")
725
+ }, /* @__PURE__ */ React15.createElement(InvitationList, {
726
+ invitations,
727
+ onClickRemove: ({ invitation }) => invitation && client.halo.removeInvitation(invitation.invitationId),
728
+ createInvitationUrl
729
+ }), /* @__PURE__ */ React15.createElement(Button2, {
730
+ className: "is-full flex gap-2 mbs-2",
731
+ onClick: () => client.halo.createInvitation(),
732
+ "data-testid": "create-space-invitation"
733
+ }, /* @__PURE__ */ React15.createElement("span", null, t("create space invitation label")), /* @__PURE__ */ React15.createElement(UserPlus, {
734
+ className: getSize3(4),
735
+ weight: "bold"
736
+ })), /* @__PURE__ */ React15.createElement(PanelSeparator, null), /* @__PURE__ */ React15.createElement(DeviceList, {
737
+ devices
738
+ })));
739
+ };
740
+ var DevicesPanel = (props) => {
741
+ const reducer = (state, action) => {
742
+ const nextState = {
743
+ ...state
744
+ };
745
+ switch (action.type) {
746
+ case null:
747
+ }
748
+ return nextState;
749
+ };
750
+ const [panelState] = useReducer(reducer, {
751
+ activeView: "device list"
752
+ });
753
+ return /* @__PURE__ */ React15.createElement(DensityProvider2, {
754
+ density: "fine"
755
+ }, panelState.activeView === "device list" ? /* @__PURE__ */ React15.createElement(DeviceListView, _extends12({}, props)) : null);
756
+ };
757
+
758
+ // packages/apps/patterns/react-ui/src/panels/IdentityPanel/IdentityPanel.tsx
759
+ import React16 from "react";
760
+ import { useClient as useClient3 } from "@dxos/react-client";
761
+ import { Avatar as Avatar3, Button as Button3, ThemeContext, useTranslation as useTranslation6 } from "@dxos/react-components";
762
+ var IdentityPanel = ({ identity, onClickManageProfile }) => {
763
+ var _a, _b;
764
+ const { t } = useTranslation6("os");
765
+ const client = useClient3();
555
766
  const defaultManageProfile = () => {
556
767
  const remoteSource = new URL((client == null ? void 0 : client.config.get("runtime.client.remoteSource")) || "https://halo.dxos.org");
557
768
  const tab = window.open(remoteSource.origin, "_blank");
558
769
  tab == null ? void 0 : tab.focus();
559
770
  };
560
- return /* @__PURE__ */ React12.createElement(ThemeContext.Provider, {
771
+ return /* @__PURE__ */ React16.createElement(ThemeContext.Provider, {
561
772
  value: {
562
- themeVariant: "os"
773
+ themeVariant: "os",
774
+ rootDensity: "fine"
563
775
  }
564
- }, /* @__PURE__ */ React12.createElement("div", {
776
+ }, /* @__PURE__ */ React16.createElement("div", {
565
777
  className: "flex flex-col gap-2 justify-center items-center"
566
- }, /* @__PURE__ */ React12.createElement(Avatar2, {
778
+ }, /* @__PURE__ */ React16.createElement(Avatar3, {
567
779
  size: 16,
568
780
  variant: "circle",
569
781
  fallbackValue: identity.identityKey.toHex(),
570
- label: (_a = identity.displayName) != null ? _a : ""
571
- }), /* @__PURE__ */ React12.createElement(Button2, {
572
- compact: true,
782
+ label: (_b = (_a = identity.profile) == null ? void 0 : _a.displayName) != null ? _b : ""
783
+ }), /* @__PURE__ */ React16.createElement(Button3, {
573
784
  onClick: onClickManageProfile != null ? onClickManageProfile : defaultManageProfile,
574
785
  className: "is-full"
575
786
  }, t("manage profile label"))));
576
787
  };
577
788
 
578
789
  // packages/apps/patterns/react-ui/src/panels/JoinPanel/JoinPanel.tsx
579
- import React23, { useEffect, useReducer } from "react";
790
+ import React27, { useEffect, useReducer as useReducer2, useState as useState6 } from "react";
580
791
  import { InvitationEncoder as InvitationEncoder2 } from "@dxos/client";
581
792
  import { log } from "@dxos/log";
582
- import { useClient as useClient5, useIdentity } from "@dxos/react-client";
583
- import { useId as useId3 } from "@dxos/react-components";
793
+ import { useClient as useClient6, useIdentity as useIdentity2 } from "@dxos/react-client";
794
+ import { DensityProvider as DensityProvider3, useId as useId4 } from "@dxos/react-components";
584
795
 
585
796
  // packages/apps/patterns/react-ui/src/panels/JoinPanel/JoinHeading.tsx
586
797
  import { ProhibitInset as ProhibitInset2 } from "phosphor-react";
587
- import React13, { cloneElement, forwardRef } from "react";
588
- import { useSpace as useSpace2 } from "@dxos/react-client";
589
- import { Avatar as Avatar3, Button as Button3, getSize as getSize3, Heading, mx as mx6, Trans, useId, useTranslation as useTranslation5 } from "@dxos/react-components";
590
- function _extends10() {
591
- _extends10 = Object.assign || function(target) {
798
+ import React17, { cloneElement as cloneElement2 } from "react";
799
+ import { useSpace as useSpace2, withReactorRef } from "@dxos/react-client";
800
+ import { Avatar as Avatar4, Button as Button4, getSize as getSize4, Heading, mx as mx12, Trans, useId as useId2, useTranslation as useTranslation7 } from "@dxos/react-components";
801
+ function _extends13() {
802
+ _extends13 = Object.assign || function(target) {
592
803
  for (var i = 1; i < arguments.length; i++) {
593
804
  var source = arguments[i];
594
805
  for (var key in source) {
@@ -599,70 +810,76 @@ function _extends10() {
599
810
  }
600
811
  return target;
601
812
  };
602
- return _extends10.apply(this, arguments);
813
+ return _extends13.apply(this, arguments);
603
814
  }
604
- var JoinHeading = /* @__PURE__ */ forwardRef(({ titleId, invitation, onExit, exitActionParent }, ref) => {
605
- var _a, _b, _c, _d, _e;
606
- const { t } = useTranslation5("os");
815
+ var JoinHeading = withReactorRef(({ mode, titleId, invitation, onExit, exitActionParent, preventExit }, ref) => {
816
+ var _a, _b, _c, _d, _e, _f;
817
+ const { t } = useTranslation7("os");
607
818
  const space = useSpace2((_a = invitation == null ? void 0 : invitation.invitation) == null ? void 0 : _a.spaceKey);
608
- const spaceTitle = (_b = space == null ? void 0 : space.properties.name) != null ? _b : "(Space not available)";
609
- const nameId = useId("spaceDisplayName");
610
- const exitButton = /* @__PURE__ */ React13.createElement(Button3, _extends10({
611
- compact: true,
819
+ const name = mode === "halo-only" ? "(Unknown identity)" : (_b = space == null ? void 0 : space.properties.name) != null ? _b : "(Space name not available)";
820
+ const nameId = useId2(mode === "halo-only" ? "identityDisplayName" : "spaceDisplayName");
821
+ const invitationKey = mode === "halo-only" ? (_d = (_c = invitation == null ? void 0 : invitation.invitation) == null ? void 0 : _c.identityKey) == null ? void 0 : _d.toHex() : (_f = (_e = invitation == null ? void 0 : invitation.invitation) == null ? void 0 : _e.identityKey) == null ? void 0 : _f.toHex();
822
+ const exitButton = /* @__PURE__ */ React17.createElement(Button4, _extends13({
612
823
  variant: "ghost"
613
824
  }, onExit && {
614
825
  onClick: onExit
615
826
  }, {
616
- className: "grow-0 shrink-0"
617
- }), /* @__PURE__ */ React13.createElement(ProhibitInset2, {
618
- className: getSize3(5)
619
- }), /* @__PURE__ */ React13.createElement("span", {
827
+ className: "grow-0 shrink-0",
828
+ "data-testid": "join-exit"
829
+ }), /* @__PURE__ */ React17.createElement(ProhibitInset2, {
830
+ className: getSize4(5)
831
+ }), /* @__PURE__ */ React17.createElement("span", {
620
832
  className: "sr-only"
621
833
  }, t("exit label")));
622
- return /* @__PURE__ */ React13.createElement("div", {
834
+ return /* @__PURE__ */ React17.createElement("div", {
623
835
  role: "none",
624
- className: mx6(subduedSurface, "p-2 rounded-bs-md"),
836
+ className: mx12(subduedSurface, "p-2 rounded-bs-md"),
625
837
  ref
626
- }, /* @__PURE__ */ React13.createElement("div", {
838
+ }, /* @__PURE__ */ React17.createElement("div", {
627
839
  role: "group",
628
840
  className: "flex items-center gap-2"
629
- }, /* @__PURE__ */ React13.createElement(Avatar3, {
630
- fallbackValue: (_e = (_d = (_c = invitation == null ? void 0 : invitation.invitation) == null ? void 0 : _c.spaceKey) == null ? void 0 : _d.toHex()) != null ? _e : "",
841
+ }, invitationKey ? /* @__PURE__ */ React17.createElement(Avatar4, {
842
+ fallbackValue: invitationKey,
631
843
  labelId: nameId
632
- }), /* @__PURE__ */ React13.createElement(Heading, {
844
+ }) : /* @__PURE__ */ React17.createElement("span", {
845
+ role: "none",
846
+ className: mx12(getSize4(10), "bg-neutral-300 dark:bg-neutral-700 rounded-full")
847
+ }), /* @__PURE__ */ React17.createElement(Heading, {
633
848
  level: 1,
634
849
  className: "font-body font-normal text-base grow",
635
850
  id: titleId
636
- }, /* @__PURE__ */ React13.createElement(Trans, _extends10({}, {
637
- defaults: t("join space heading"),
851
+ }, invitation ? /* @__PURE__ */ React17.createElement(Trans, _extends13({}, {
852
+ defaults: t("joining heading"),
638
853
  components: {
639
- small: /* @__PURE__ */ React13.createElement("span", {
854
+ small: /* @__PURE__ */ React17.createElement("span", {
640
855
  className: "block leading-none mbe-1 font-system-medium text-sm"
641
856
  }),
642
- large: /* @__PURE__ */ React13.createElement("span", {
857
+ large: /* @__PURE__ */ React17.createElement("span", {
643
858
  className: "block leading-none",
644
859
  id: nameId
645
860
  })
646
861
  },
647
862
  values: {
648
- spaceTitle
863
+ name
649
864
  }
650
- }))), exitActionParent ? /* @__PURE__ */ cloneElement(exitActionParent, {}, exitButton) : exitButton));
865
+ })) : /* @__PURE__ */ React17.createElement("span", {
866
+ className: "block leading-none font-system-medium text-sm"
867
+ }, mode === "halo-only" ? t("halo heading") : t("join space heading"))), !preventExit && mode !== "halo-only" && (exitActionParent ? /* @__PURE__ */ cloneElement2(exitActionParent, {}, exitButton) : exitButton)));
651
868
  });
652
869
 
653
870
  // packages/apps/patterns/react-ui/src/panels/JoinPanel/view-states/AdditionMethodSelector.tsx
654
871
  import { CaretLeft, CaretRight, Plus, QrCode as QrCode2, Textbox } from "phosphor-react";
655
- import React15 from "react";
656
- import { Button as Button4, CompoundButton, getSize as getSize5, mx as mx8, useTranslation as useTranslation7 } from "@dxos/react-components";
872
+ import React19 from "react";
873
+ import { Button as Button5, CompoundButton, getSize as getSize6, mx as mx14, useTranslation as useTranslation9 } from "@dxos/react-components";
657
874
 
658
875
  // packages/apps/patterns/react-ui/src/panels/JoinPanel/view-states/ViewState.tsx
659
- import { CheckCircle, HourglassSimple, X as X2 } from "phosphor-react";
660
- import React14, { useMemo as useMemo2 } from "react";
876
+ import { CheckCircle, HourglassSimple, X as X3 } from "phosphor-react";
877
+ import React18, { useMemo as useMemo2 } from "react";
661
878
  import { Invitation as Invitation4 } from "@dxos/client";
662
879
  import { useInvitationStatus as useInvitationStatus2 } from "@dxos/react-client";
663
- import { mx as mx7, useTranslation as useTranslation6, Trans as Trans2, Avatar as Avatar4, useId as useId2, getSize as getSize4, strongShimmer } from "@dxos/react-components";
664
- function _extends11() {
665
- _extends11 = Object.assign || function(target) {
880
+ import { mx as mx13, useTranslation as useTranslation8, Trans as Trans2, Avatar as Avatar5, useId as useId3, getSize as getSize5, strongShimmer } from "@dxos/react-components";
881
+ function _extends14() {
882
+ _extends14 = Object.assign || function(target) {
666
883
  for (var i = 1; i < arguments.length; i++) {
667
884
  var source = arguments[i];
668
885
  for (var key in source) {
@@ -673,39 +890,39 @@ function _extends11() {
673
890
  }
674
891
  return target;
675
892
  };
676
- return _extends11.apply(this, arguments);
893
+ return _extends14.apply(this, arguments);
677
894
  }
678
- var stripe = mx7("rounded-full grow", getSize4(3));
895
+ var stripe = mx13("rounded-full grow", getSize5(3));
679
896
  var ViewStateHeading = ({ children, className, ...props }) => {
680
- return /* @__PURE__ */ React14.createElement("h2", _extends11({}, props, {
681
- className: mx7("font-system-medium text-sm md:text-base mbe-1 mli-1 text-center", className)
897
+ return /* @__PURE__ */ React18.createElement("h2", _extends14({}, props, {
898
+ className: mx13("font-system-medium text-sm md:text-base mbe-1 mli-1 text-center", className)
682
899
  }), children);
683
900
  };
684
901
  var PureViewStateInvitation = ({ halted, cursor, label, resolvedColor }) => {
685
- const labelId = useId2("invitationState");
686
- return /* @__PURE__ */ React14.createElement("div", {
902
+ const labelId = useId3("invitationState");
903
+ return /* @__PURE__ */ React18.createElement("div", {
687
904
  role: "none",
688
- className: mx7(defaultSurface, "pli-2 pbs-2")
689
- }, /* @__PURE__ */ React14.createElement("div", {
905
+ className: mx13(defaultSurface, "pli-2 pbs-2")
906
+ }, /* @__PURE__ */ React18.createElement("div", {
690
907
  role: "status",
691
908
  "aria-labelledby": labelId,
692
909
  className: "flex gap-2 items-center mlb-1"
693
- }, /* @__PURE__ */ React14.createElement("div", {
910
+ }, /* @__PURE__ */ React18.createElement("div", {
694
911
  role: "none",
695
- className: mx7(stripe, !halted && cursor === 1 && strongShimmer, cursor === 2 ? halted ? resolvedColor : activeBgColor : cursor > 1 ? resolvedColor : inactiveBgColor)
696
- }), /* @__PURE__ */ React14.createElement("div", {
912
+ className: mx13(stripe, !halted && cursor === 1 && strongShimmer, cursor === 2 ? halted ? resolvedColor : activeBgColor : cursor > 1 ? resolvedColor : inactiveBgColor)
913
+ }), /* @__PURE__ */ React18.createElement("div", {
697
914
  role: "none",
698
- className: mx7(stripe, !halted && cursor === 3 && strongShimmer, cursor === 3 ? halted ? resolvedColor : activeBgColor : cursor > 3 ? resolvedColor : inactiveBgColor)
699
- }), /* @__PURE__ */ React14.createElement("div", {
915
+ className: mx13(stripe, !halted && cursor === 3 && strongShimmer, cursor === 3 ? halted ? resolvedColor : activeBgColor : cursor > 3 ? resolvedColor : inactiveBgColor)
916
+ }), /* @__PURE__ */ React18.createElement("div", {
700
917
  role: "none",
701
- className: mx7(stripe, cursor > 3 ? halted ? resolvedColor : resolvedColor : inactiveBgColor)
702
- })), /* @__PURE__ */ React14.createElement(ViewStateHeading, {
918
+ className: mx13(stripe, cursor > 3 ? halted ? resolvedColor : resolvedColor : inactiveBgColor)
919
+ })), /* @__PURE__ */ React18.createElement(ViewStateHeading, {
703
920
  id: labelId,
704
921
  className: "mbs-2 flex justify-center items-center gap-2"
705
922
  }, label));
706
923
  };
707
924
  var ViewStateInvitationStatus = ({ activeInvitation }) => {
708
- const { t } = useTranslation6("os");
925
+ const { t } = useTranslation8("os");
709
926
  const { status, haltedAt } = useInvitationStatus2(activeInvitation);
710
927
  const halted = status === Invitation4.State.CANCELLED || status === Invitation4.State.TIMEOUT || status === Invitation4.State.ERROR;
711
928
  const cursor = invitationStatusValue.get(halted ? haltedAt : status);
@@ -713,24 +930,24 @@ var ViewStateInvitationStatus = ({ activeInvitation }) => {
713
930
  const statusLabelMap = useMemo2(() => /* @__PURE__ */ new Map([
714
931
  [
715
932
  Invitation4.State.ERROR,
716
- /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(X2, {
933
+ /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(X3, {
717
934
  weight: "bold",
718
- className: mx7(getSize4(4), "text-error-600 dark:text-error-400")
719
- }), /* @__PURE__ */ React14.createElement("span", null, t("error status label")))
935
+ className: mx13(getSize5(4), "text-error-600 dark:text-error-400")
936
+ }), /* @__PURE__ */ React18.createElement("span", null, t("error status label")))
720
937
  ],
721
938
  [
722
939
  Invitation4.State.TIMEOUT,
723
- /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(HourglassSimple, {
940
+ /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(HourglassSimple, {
724
941
  weight: "fill",
725
- className: mx7(getSize4(4), "text-warning-600 dark:text-warning-400")
726
- }), /* @__PURE__ */ React14.createElement("span", null, t("timeout status label")))
942
+ className: mx13(getSize5(4), "text-warning-600 dark:text-warning-400")
943
+ }), /* @__PURE__ */ React18.createElement("span", null, t("timeout status label")))
727
944
  ],
728
945
  [
729
946
  Invitation4.State.CANCELLED,
730
- /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(X2, {
947
+ /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(X3, {
731
948
  weight: "bold",
732
- className: mx7(getSize4(4), "text-warning-600 dark:text-warning-400")
733
- }), /* @__PURE__ */ React14.createElement("span", null, t("cancelled status label")))
949
+ className: mx13(getSize5(4), "text-warning-600 dark:text-warning-400")
950
+ }), /* @__PURE__ */ React18.createElement("span", null, t("cancelled status label")))
734
951
  ],
735
952
  [
736
953
  Invitation4.State.INIT,
@@ -750,15 +967,15 @@ var ViewStateInvitationStatus = ({ activeInvitation }) => {
750
967
  ],
751
968
  [
752
969
  Invitation4.State.SUCCESS,
753
- /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement(CheckCircle, {
970
+ /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(CheckCircle, {
754
971
  weight: "fill",
755
- className: mx7(getSize4(4), "text-success-600 dark:text-success-400")
756
- }), /* @__PURE__ */ React14.createElement("span", null, t("success status label")))
972
+ className: mx13(getSize5(4), "text-success-600 dark:text-success-400")
973
+ }), /* @__PURE__ */ React18.createElement("span", null, t("success status label")))
757
974
  ]
758
975
  ]), [
759
976
  t
760
977
  ]);
761
- return /* @__PURE__ */ React14.createElement(PureViewStateInvitation, _extends11({}, {
978
+ return /* @__PURE__ */ React18.createElement(PureViewStateInvitation, _extends14({}, {
762
979
  label: statusLabelMap.get(status),
763
980
  resolvedColor,
764
981
  cursor,
@@ -766,54 +983,54 @@ var ViewStateInvitationStatus = ({ activeInvitation }) => {
766
983
  }));
767
984
  };
768
985
  var ViewState = ({ active, children, className, dispatch, selectedIdentity, activeInvitation, ...props }) => {
769
- var _a;
770
- const { t } = useTranslation6("os");
771
- const identityLabel = useId2("selectedIdentityLabel");
772
- return /* @__PURE__ */ React14.createElement("div", _extends11({
986
+ var _a, _b;
987
+ const { t } = useTranslation8("os");
988
+ const identityLabel = useId3("selectedIdentityLabel");
989
+ return /* @__PURE__ */ React18.createElement("div", _extends14({
773
990
  role: "none"
774
991
  }, props, !active && {
775
992
  "aria-hidden": true
776
993
  }, {
777
- className: mx7("is-[50%] flex flex-col", active ? "order-2" : "order-4", className)
778
- }), selectedIdentity && /* @__PURE__ */ React14.createElement("div", {
994
+ className: mx13("is-[50%] flex flex-col", active ? "order-2" : "order-4", className)
995
+ }), selectedIdentity && /* @__PURE__ */ React18.createElement("div", {
779
996
  role: "none",
780
- className: mx7(subduedSurface, "flex-none flex items-center gap-1 pli-2 pbe-1.5")
781
- }, /* @__PURE__ */ React14.createElement(Trans2, _extends11({}, {
997
+ className: mx13(subduedSurface, "flex-none flex items-center gap-1 pli-2 pbe-1.5")
998
+ }, /* @__PURE__ */ React18.createElement(Trans2, _extends14({}, {
782
999
  defaults: t("join space as identity heading"),
783
1000
  components: {
784
- icon: /* @__PURE__ */ React14.createElement(Avatar4, {
1001
+ icon: /* @__PURE__ */ React18.createElement(Avatar5, {
785
1002
  size: 4,
786
1003
  fallbackValue: selectedIdentity === true ? "" : selectedIdentity.identityKey.toHex(),
787
1004
  labelId: identityLabel
788
1005
  }),
789
- label: /* @__PURE__ */ React14.createElement("span", {
1006
+ label: /* @__PURE__ */ React18.createElement("span", {
790
1007
  id: identityLabel
791
1008
  }),
792
- part: /* @__PURE__ */ React14.createElement("span", {
1009
+ part: /* @__PURE__ */ React18.createElement("span", {
793
1010
  role: "none",
794
1011
  className: "flex items-center gap-1 leading-none"
795
1012
  })
796
1013
  },
797
1014
  values: {
798
- labelValue: selectedIdentity === true ? "\xA0" : (_a = selectedIdentity.displayName) != null ? _a : selectedIdentity.identityKey.truncate()
1015
+ labelValue: selectedIdentity === true ? "\xA0" : (_b = (_a = selectedIdentity.profile) == null ? void 0 : _a.displayName) != null ? _b : selectedIdentity.identityKey.truncate()
799
1016
  }
800
- }))), activeInvitation && (activeInvitation === true ? /* @__PURE__ */ React14.createElement(PureViewStateInvitation, _extends11({}, {
1017
+ }))), activeInvitation && (activeInvitation === true ? /* @__PURE__ */ React18.createElement(PureViewStateInvitation, _extends14({}, {
801
1018
  halted: false,
802
1019
  status: Invitation4.State.INIT,
803
1020
  label: t("invitation input label"),
804
1021
  cursor: 0,
805
1022
  resolvedColor: inactiveBgColor
806
- })) : /* @__PURE__ */ React14.createElement(ViewStateInvitationStatus, _extends11({}, {
1023
+ })) : /* @__PURE__ */ React18.createElement(ViewStateInvitationStatus, _extends14({}, {
807
1024
  activeInvitation
808
- }))), /* @__PURE__ */ React14.createElement("div", {
1025
+ }))), /* @__PURE__ */ React18.createElement("div", {
809
1026
  role: "region",
810
- className: mx7(defaultSurface, "rounded-be-md grow shrink-0 flex flex-col gap-1 p-2")
1027
+ className: mx13(defaultSurface, "rounded-be-md grow shrink-0 flex flex-col gap-1 p-2")
811
1028
  }, children));
812
1029
  };
813
1030
 
814
1031
  // packages/apps/patterns/react-ui/src/panels/JoinPanel/view-states/AdditionMethodSelector.tsx
815
- function _extends12() {
816
- _extends12 = Object.assign || function(target) {
1032
+ function _extends15() {
1033
+ _extends15 = Object.assign || function(target) {
817
1034
  for (var i = 1; i < arguments.length; i++) {
818
1035
  var source = arguments[i];
819
1036
  for (var key in source) {
@@ -824,16 +1041,16 @@ function _extends12() {
824
1041
  }
825
1042
  return target;
826
1043
  };
827
- return _extends12.apply(this, arguments);
1044
+ return _extends15.apply(this, arguments);
828
1045
  }
829
1046
  var AdditionMethodSelector = ({ availableIdentities, ...viewStateProps }) => {
830
1047
  const disabled = !viewStateProps.active;
831
1048
  const { dispatch } = viewStateProps;
832
- const { t } = useTranslation7("os");
1049
+ const { t } = useTranslation9("os");
833
1050
  const sharedButtonProps = {
834
1051
  disabled,
835
- after: /* @__PURE__ */ React15.createElement(CaretRight, {
836
- className: getSize5(4),
1052
+ after: /* @__PURE__ */ React19.createElement(CaretRight, {
1053
+ className: getSize6(4),
837
1054
  weight: "bold"
838
1055
  }),
839
1056
  slots: {
@@ -842,59 +1059,65 @@ var AdditionMethodSelector = ({ availableIdentities, ...viewStateProps }) => {
842
1059
  }
843
1060
  }
844
1061
  };
845
- return /* @__PURE__ */ React15.createElement(ViewState, _extends12({}, viewStateProps), /* @__PURE__ */ React15.createElement(ViewStateHeading, null, t("addition method selector title")), /* @__PURE__ */ React15.createElement("div", {
1062
+ return /* @__PURE__ */ React19.createElement(ViewState, _extends15({}, viewStateProps), /* @__PURE__ */ React19.createElement(ViewStateHeading, null, t("addition method selector title")), /* @__PURE__ */ React19.createElement("div", {
846
1063
  role: "none",
847
1064
  className: "flex flex-col gap-1 grow"
848
- }, /* @__PURE__ */ React15.createElement(CompoundButton, _extends12({}, sharedButtonProps, {
1065
+ }, /* @__PURE__ */ React19.createElement(CompoundButton, _extends15({}, sharedButtonProps, {
849
1066
  description: t("create identity description"),
850
- before: /* @__PURE__ */ React15.createElement(Plus, {
851
- className: getSize5(6)
1067
+ before: /* @__PURE__ */ React19.createElement(Plus, {
1068
+ className: getSize6(6)
852
1069
  }),
853
1070
  onClick: () => dispatch({
854
1071
  type: "select addition method",
855
1072
  method: "create identity"
856
1073
  }),
857
- "data-autofocus": "addition method selector"
858
- }), t("create identity label")), /* @__PURE__ */ React15.createElement(CompoundButton, _extends12({}, sharedButtonProps, {
1074
+ "data-autofocus": "addition method selector",
1075
+ "data-testid": "create-identity"
1076
+ }), t("create identity label")), /* @__PURE__ */ React19.createElement(CompoundButton, _extends15({}, sharedButtonProps, {
859
1077
  description: t("join identity description"),
860
- before: /* @__PURE__ */ React15.createElement(QrCode2, {
861
- className: getSize5(6)
1078
+ before: /* @__PURE__ */ React19.createElement(QrCode2, {
1079
+ className: getSize6(6)
862
1080
  }),
863
1081
  onClick: () => dispatch({
864
1082
  type: "select addition method",
865
1083
  method: "accept device invitation"
866
- })
867
- }), t("join identity label")), /* @__PURE__ */ React15.createElement(CompoundButton, _extends12({}, sharedButtonProps, {
1084
+ }),
1085
+ "data-testid": "join-identity"
1086
+ }), t("join identity label")), /* @__PURE__ */ React19.createElement(CompoundButton, _extends15({}, sharedButtonProps, {
1087
+ // TODO(mykola): Implement recover.
1088
+ disabled: true,
868
1089
  description: t("recover identity description"),
869
- before: /* @__PURE__ */ React15.createElement(Textbox, {
870
- className: getSize5(6)
1090
+ before: /* @__PURE__ */ React19.createElement(Textbox, {
1091
+ className: getSize6(6)
871
1092
  }),
872
1093
  onClick: () => dispatch({
873
1094
  type: "select addition method",
874
1095
  method: "recover identity"
875
- })
876
- }), t("recover identity label"))), /* @__PURE__ */ React15.createElement(Button4, {
1096
+ }),
1097
+ "data-testid": "recover-identity"
1098
+ }), t("recover identity label"))), /* @__PURE__ */ React19.createElement(Button5, {
877
1099
  disabled: disabled || availableIdentities.length < 1,
878
1100
  onClick: () => dispatch({
879
1101
  type: "deselect identity"
880
- })
881
- }, /* @__PURE__ */ React15.createElement(CaretLeft, {
882
- className: getSize5(4),
1102
+ }),
1103
+ "data-testid": "deselect-identity"
1104
+ }, /* @__PURE__ */ React19.createElement(CaretLeft, {
1105
+ className: getSize6(4),
883
1106
  weight: "bold"
884
- }), /* @__PURE__ */ React15.createElement("span", {
1107
+ }), /* @__PURE__ */ React19.createElement("span", {
885
1108
  className: "grow"
886
- }, t("deselect identity label")), /* @__PURE__ */ React15.createElement(CaretRight, {
887
- className: mx8(getSize5(4), "invisible"),
1109
+ }, t("deselect identity label")), /* @__PURE__ */ React19.createElement(CaretRight, {
1110
+ className: mx14(getSize6(4), "invisible"),
888
1111
  weight: "bold"
889
1112
  })));
890
1113
  };
891
1114
 
892
1115
  // packages/apps/patterns/react-ui/src/panels/JoinPanel/view-states/IdentityAdded.tsx
893
- import { CaretLeft as CaretLeft2, CaretRight as CaretRight2 } from "phosphor-react";
894
- import React16 from "react";
895
- import { Avatar as Avatar5, Button as Button5, getSize as getSize6, mx as mx9, useTranslation as useTranslation8 } from "@dxos/react-components";
896
- function _extends13() {
897
- _extends13 = Object.assign || function(target) {
1116
+ import { CaretLeft as CaretLeft2, CaretRight as CaretRight2, Check } from "phosphor-react";
1117
+ import React20, { cloneElement as cloneElement3 } from "react";
1118
+ import { Avatar as Avatar6, Button as Button6, getSize as getSize7, mx as mx15, useTranslation as useTranslation10 } from "@dxos/react-components";
1119
+ function _extends16() {
1120
+ _extends16 = Object.assign || function(target) {
898
1121
  for (var i = 1; i < arguments.length; i++) {
899
1122
  var source = arguments[i];
900
1123
  for (var key in source) {
@@ -905,27 +1128,51 @@ function _extends13() {
905
1128
  }
906
1129
  return target;
907
1130
  };
908
- return _extends13.apply(this, arguments);
1131
+ return _extends16.apply(this, arguments);
909
1132
  }
910
- var IdentityAdded = ({ addedIdentity, ...viewStateProps }) => {
911
- var _a, _b, _c;
1133
+ var Done = ({ onDone, doneActionParent, active }) => {
1134
+ const disabled = !active;
1135
+ const { t } = useTranslation10("os");
1136
+ const doneButton = /* @__PURE__ */ React20.createElement(Button6, _extends16({}, onDone && {
1137
+ onClick: () => onDone(null)
1138
+ }, {
1139
+ disabled,
1140
+ className: "grow flex items-center gap-2 pli-2",
1141
+ "data-autofocus": "identity added",
1142
+ "data-testid": "identity-added-done"
1143
+ }), /* @__PURE__ */ React20.createElement(CaretLeft2, {
1144
+ weight: "bold",
1145
+ className: mx15(getSize7(2), "invisible")
1146
+ }), /* @__PURE__ */ React20.createElement("span", {
1147
+ className: "grow"
1148
+ }, t("done label")), /* @__PURE__ */ React20.createElement(Check, {
1149
+ weight: "bold",
1150
+ className: getSize7(4)
1151
+ }));
1152
+ return doneActionParent ? /* @__PURE__ */ cloneElement3(doneActionParent, {}, doneButton) : doneButton;
1153
+ };
1154
+ var IdentityAdded = ({ mode, addedIdentity, onDone, doneActionParent, ...viewStateProps }) => {
1155
+ var _a, _b, _c, _d, _e;
912
1156
  const disabled = !viewStateProps.active;
913
1157
  const { dispatch } = viewStateProps;
914
- const { t } = useTranslation8("os");
915
- return /* @__PURE__ */ React16.createElement(ViewState, _extends13({}, viewStateProps), /* @__PURE__ */ React16.createElement(ViewStateHeading, null, t("identity added label")), /* @__PURE__ */ React16.createElement("div", {
1158
+ const { t } = useTranslation10("os");
1159
+ return /* @__PURE__ */ React20.createElement(ViewState, _extends16({}, viewStateProps), /* @__PURE__ */ React20.createElement(ViewStateHeading, null, t("identity added label")), /* @__PURE__ */ React20.createElement("div", {
916
1160
  role: "none",
917
1161
  className: "grow flex flex-col items-center justify-center text-center gap-2"
918
- }, /* @__PURE__ */ React16.createElement(Avatar5, {
1162
+ }, /* @__PURE__ */ React20.createElement(Avatar6, {
919
1163
  size: 20,
920
1164
  fallbackValue: (_a = addedIdentity == null ? void 0 : addedIdentity.identityKey.toHex()) != null ? _a : "",
921
- label: /* @__PURE__ */ React16.createElement("p", {
922
- className: mx9("text-lg", !(addedIdentity == null ? void 0 : addedIdentity.displayName) && "font-mono")
923
- }, (_c = (_b = addedIdentity == null ? void 0 : addedIdentity.displayName) != null ? _b : addedIdentity == null ? void 0 : addedIdentity.identityKey.truncate()) != null ? _c : "\xA0"),
1165
+ label: /* @__PURE__ */ React20.createElement("p", {
1166
+ className: mx15("text-lg", !((_b = addedIdentity == null ? void 0 : addedIdentity.profile) == null ? void 0 : _b.displayName) && "font-mono")
1167
+ }, (_e = (_d = (_c = addedIdentity == null ? void 0 : addedIdentity.profile) == null ? void 0 : _c.displayName) != null ? _d : addedIdentity == null ? void 0 : addedIdentity.identityKey.truncate()) != null ? _e : "\xA0"),
924
1168
  variant: "circle",
925
1169
  status: "active"
926
- })), /* @__PURE__ */ React16.createElement("div", {
1170
+ })), mode === "halo-only" ? /* @__PURE__ */ React20.createElement(Done, _extends16({
1171
+ onDone,
1172
+ doneActionParent
1173
+ }, viewStateProps)) : /* @__PURE__ */ React20.createElement("div", {
927
1174
  className: "flex gap-2"
928
- }, /* @__PURE__ */ React16.createElement(Button5, {
1175
+ }, /* @__PURE__ */ React20.createElement(Button6, {
929
1176
  disabled: disabled || !addedIdentity,
930
1177
  className: "grow flex items-center gap-2 pli-2 order-2",
931
1178
  onClick: () => addedIdentity && dispatch({
@@ -933,33 +1180,33 @@ var IdentityAdded = ({ addedIdentity, ...viewStateProps }) => {
933
1180
  identity: addedIdentity
934
1181
  }),
935
1182
  "data-autofocus": "identity added"
936
- }, /* @__PURE__ */ React16.createElement(CaretLeft2, {
1183
+ }, /* @__PURE__ */ React20.createElement(CaretLeft2, {
937
1184
  weight: "bold",
938
- className: mx9(getSize6(2), "invisible")
939
- }), /* @__PURE__ */ React16.createElement("span", {
1185
+ className: mx15(getSize7(2), "invisible")
1186
+ }), /* @__PURE__ */ React20.createElement("span", {
940
1187
  className: "grow"
941
- }, t("continue label")), /* @__PURE__ */ React16.createElement(CaretRight2, {
1188
+ }, t("continue label")), /* @__PURE__ */ React20.createElement(CaretRight2, {
942
1189
  weight: "bold",
943
- className: getSize6(4)
944
- })), /* @__PURE__ */ React16.createElement(Button5, {
1190
+ className: getSize7(4)
1191
+ })), /* @__PURE__ */ React20.createElement(Button6, {
945
1192
  disabled,
946
1193
  onClick: () => dispatch({
947
1194
  type: "deselect identity"
948
1195
  }),
949
1196
  className: "flex items-center gap-2 pis-2 pie-4"
950
- }, /* @__PURE__ */ React16.createElement(CaretLeft2, {
1197
+ }, /* @__PURE__ */ React20.createElement(CaretLeft2, {
951
1198
  weight: "bold",
952
- className: getSize6(4)
953
- }), /* @__PURE__ */ React16.createElement("span", null, t("deselect identity label")))));
1199
+ className: getSize7(4)
1200
+ }), /* @__PURE__ */ React20.createElement("span", null, t("deselect identity label")))));
954
1201
  };
955
1202
 
956
1203
  // packages/apps/patterns/react-ui/src/panels/JoinPanel/view-states/IdentitySelector.tsx
957
1204
  import * as RadioGroup from "@radix-ui/react-radio-group";
958
- import { CaretLeft as CaretLeft3, CaretRight as CaretRight3, UserPlus } from "phosphor-react";
959
- import React17, { useCallback as useCallback4, useState as useState2 } from "react";
960
- import { Avatar as Avatar6, Button as Button6, themeVariantFocus, getSize as getSize7, mx as mx10, useTranslation as useTranslation9 } from "@dxos/react-components";
961
- function _extends14() {
962
- _extends14 = Object.assign || function(target) {
1205
+ import { CaretLeft as CaretLeft3, CaretRight as CaretRight3, UserPlus as UserPlus2 } from "phosphor-react";
1206
+ import React21, { useCallback as useCallback4, useState as useState2 } from "react";
1207
+ import { Avatar as Avatar7, Button as Button7, themeVariantFocus, getSize as getSize8, mx as mx16, useTranslation as useTranslation11 } from "@dxos/react-components";
1208
+ function _extends17() {
1209
+ _extends17 = Object.assign || function(target) {
963
1210
  for (var i = 1; i < arguments.length; i++) {
964
1211
  var source = arguments[i];
965
1212
  for (var key in source) {
@@ -970,84 +1217,86 @@ function _extends14() {
970
1217
  }
971
1218
  return target;
972
1219
  };
973
- return _extends14.apply(this, arguments);
1220
+ return _extends17.apply(this, arguments);
974
1221
  }
975
1222
  var IdentitySelector = ({ availableIdentities, ...viewStateProps }) => {
976
1223
  const { dispatch } = viewStateProps;
977
1224
  const disabled = !viewStateProps.active;
978
- const { t } = useTranslation9("os");
1225
+ const { t } = useTranslation11("os");
979
1226
  const [activeIdentity, setActiveIdentity] = useState2(availableIdentities[0]);
980
1227
  const onValueChange = useCallback4((nextHex) => setActiveIdentity(availableIdentities.find((identity) => identity.identityKey.toHex() === nextHex) || activeIdentity), [
981
1228
  availableIdentities
982
1229
  ]);
983
- return /* @__PURE__ */ React17.createElement(ViewState, _extends14({}, viewStateProps), /* @__PURE__ */ React17.createElement(ViewStateHeading, null, t("identity selector title")), /* @__PURE__ */ React17.createElement(RadioGroup.Root, {
1230
+ return /* @__PURE__ */ React21.createElement(ViewState, _extends17({}, viewStateProps), /* @__PURE__ */ React21.createElement(ViewStateHeading, null, t("identity selector title")), /* @__PURE__ */ React21.createElement(RadioGroup.Root, {
984
1231
  disabled,
985
1232
  value: activeIdentity == null ? void 0 : activeIdentity.identityKey.toHex(),
986
1233
  onValueChange,
987
1234
  className: "overflow-y-auto grow shrink min-bs-10 pli-1 -mli-1",
988
1235
  "aria-label": t("identity radio group title"),
989
1236
  "data-autofocus": "identity selector"
990
- }, availableIdentities.map(({ displayName, identityKey }) => {
991
- var _a;
1237
+ }, availableIdentities.map(({ profile, identityKey }) => {
1238
+ var _a, _b;
992
1239
  const hex = identityKey.toHex();
993
1240
  const inputId = `identitySelector__item--${hex}`;
994
1241
  const labelId = `identitySelector__itemLabel--${hex}`;
995
- return /* @__PURE__ */ React17.createElement("label", {
1242
+ return /* @__PURE__ */ React21.createElement("label", {
996
1243
  htmlFor: inputId,
997
1244
  key: hex,
998
1245
  className: "flex items-center mbe-2 gap-2 cursor-pointer"
999
- }, /* @__PURE__ */ React17.createElement(RadioGroup.Item, {
1246
+ }, /* @__PURE__ */ React21.createElement(RadioGroup.Item, {
1000
1247
  id: inputId,
1001
1248
  "aria-labelledby": labelId,
1002
1249
  value: hex,
1003
- className: mx10("peer relative w-4 h-4 rounded-full", "border border-transparent text-white", "radix-state-checked:bg-primary-600", "radix-state-unchecked:bg-neutral-100 dark:radix-state-unchecked:bg-neutral-900", themeVariantFocus("os"))
1004
- }, /* @__PURE__ */ React17.createElement(RadioGroup.Indicator, {
1250
+ className: mx16("peer relative w-4 h-4 rounded-full", "border border-transparent text-white", "radix-state-checked:bg-primary-600", "radix-state-unchecked:bg-neutral-100 dark:radix-state-unchecked:bg-neutral-900", themeVariantFocus("os")),
1251
+ "data-testid": "identity-selector-item"
1252
+ }, /* @__PURE__ */ React21.createElement(RadioGroup.Indicator, {
1005
1253
  className: "absolute inset-0 flex items-center justify-center leading-0"
1006
- }, /* @__PURE__ */ React17.createElement("div", {
1254
+ }, /* @__PURE__ */ React21.createElement("div", {
1007
1255
  className: "w-1.5 h-1.5 rounded-full bg-white"
1008
- }))), /* @__PURE__ */ React17.createElement(Avatar6, {
1256
+ }))), /* @__PURE__ */ React21.createElement(Avatar7, {
1009
1257
  fallbackValue: hex,
1010
1258
  labelId,
1011
1259
  variant: "circle"
1012
- }), /* @__PURE__ */ React17.createElement("span", {
1260
+ }), /* @__PURE__ */ React21.createElement("span", {
1013
1261
  id: labelId,
1014
- className: mx10(!displayName && "font-mono")
1015
- }, (_a = displayName != null ? displayName : identityKey.truncate()) != null ? _a : ""));
1016
- })), /* @__PURE__ */ React17.createElement(Button6, {
1262
+ className: mx16(!(profile == null ? void 0 : profile.displayName) && "font-mono")
1263
+ }, (_b = (_a = profile == null ? void 0 : profile.displayName) != null ? _a : identityKey.truncate()) != null ? _b : ""));
1264
+ })), /* @__PURE__ */ React21.createElement(Button7, {
1017
1265
  disabled,
1018
- compact: true,
1019
1266
  onClick: () => dispatch({
1020
1267
  type: "add identity"
1021
1268
  }),
1022
- className: "flex items-center gap-2 pli-2"
1023
- }, /* @__PURE__ */ React17.createElement("span", null, t("add identity label")), /* @__PURE__ */ React17.createElement(UserPlus, {
1269
+ className: "flex items-center gap-2 pli-2",
1270
+ "data-testid": "add-identity"
1271
+ }, /* @__PURE__ */ React21.createElement("span", null, t("add identity label")), /* @__PURE__ */ React21.createElement(UserPlus2, {
1024
1272
  weight: "bold",
1025
- className: getSize7(3.5)
1026
- })), /* @__PURE__ */ React17.createElement(Button6, {
1273
+ className: getSize8(3.5)
1274
+ })), /* @__PURE__ */ React21.createElement(Button7, {
1027
1275
  disabled: disabled || !activeIdentity,
1028
1276
  className: "flex items-center gap-2 pli-2",
1029
1277
  onClick: () => dispatch({
1030
1278
  type: "select identity",
1031
1279
  identity: activeIdentity
1032
- })
1033
- }, /* @__PURE__ */ React17.createElement(CaretLeft3, {
1280
+ }),
1281
+ "data-testid": "select-identity"
1282
+ }, /* @__PURE__ */ React21.createElement(CaretLeft3, {
1034
1283
  weight: "bold",
1035
- className: mx10(getSize7(4), "invisible")
1036
- }), /* @__PURE__ */ React17.createElement("span", {
1284
+ className: mx16(getSize8(4), "invisible")
1285
+ }), /* @__PURE__ */ React21.createElement("span", {
1037
1286
  className: "grow"
1038
- }, t("continue label")), /* @__PURE__ */ React17.createElement(CaretRight3, {
1287
+ }, t("continue label")), /* @__PURE__ */ React21.createElement(CaretRight3, {
1039
1288
  weight: "bold",
1040
- className: getSize7(4)
1289
+ className: getSize8(4)
1041
1290
  })));
1042
1291
  };
1043
1292
 
1044
1293
  // packages/apps/patterns/react-ui/src/panels/JoinPanel/view-states/IdentityInput.tsx
1045
1294
  import { CaretLeft as CaretLeft4, CaretRight as CaretRight4 } from "phosphor-react";
1046
- import React18, { useState as useState3 } from "react";
1047
- import { useClient as useClient3 } from "@dxos/react-client";
1048
- import { Button as Button7, getSize as getSize8, Input, mx as mx11, useTranslation as useTranslation10 } from "@dxos/react-components";
1049
- function _extends15() {
1050
- _extends15 = Object.assign || function(target) {
1295
+ import React22, { useState as useState3 } from "react";
1296
+ import { useClient as useClient4 } from "@dxos/react-client";
1297
+ import { Button as Button8, getSize as getSize9, Input, mx as mx17, useTranslation as useTranslation12 } from "@dxos/react-components";
1298
+ function _extends18() {
1299
+ _extends18 = Object.assign || function(target) {
1051
1300
  for (var i = 1; i < arguments.length; i++) {
1052
1301
  var source = arguments[i];
1053
1302
  for (var key in source) {
@@ -1058,18 +1307,18 @@ function _extends15() {
1058
1307
  }
1059
1308
  return target;
1060
1309
  };
1061
- return _extends15.apply(this, arguments);
1310
+ return _extends18.apply(this, arguments);
1062
1311
  }
1063
1312
  var IdentityInput = ({ method, ...viewStateProps }) => {
1064
1313
  const disabled = !viewStateProps.active;
1065
1314
  const { dispatch } = viewStateProps;
1066
- const { t } = useTranslation10("os");
1315
+ const { t } = useTranslation12("os");
1067
1316
  const [inputValue, setInputValue] = useState3("");
1068
- const client = useClient3();
1317
+ const client = useClient4();
1069
1318
  const [validationMessage, setValidationMessage] = useState3("");
1070
1319
  const isRecover = method === "recover identity";
1071
1320
  const handleNext = () => {
1072
- void client.halo.createProfile({
1321
+ void client.halo.createIdentity({
1073
1322
  [isRecover ? "seedphrase" : "displayName"]: inputValue
1074
1323
  }).then((identity) => {
1075
1324
  dispatch({
@@ -1080,9 +1329,9 @@ var IdentityInput = ({ method, ...viewStateProps }) => {
1080
1329
  setValidationMessage(t(isRecover ? "failed to recover identity message" : "failed to create identity message"));
1081
1330
  });
1082
1331
  };
1083
- return /* @__PURE__ */ React18.createElement(ViewState, _extends15({}, viewStateProps), /* @__PURE__ */ React18.createElement(Input, _extends15({
1332
+ return /* @__PURE__ */ React22.createElement(ViewState, _extends18({}, viewStateProps), /* @__PURE__ */ React22.createElement(Input, _extends18({
1084
1333
  disabled,
1085
- label: /* @__PURE__ */ React18.createElement(ViewStateHeading, null, t(isRecover ? "recover identity input label" : "new identity input label")),
1334
+ label: /* @__PURE__ */ React22.createElement(ViewStateHeading, null, t(isRecover ? "recover identity input label" : "new identity input label")),
1086
1335
  onChange: ({ target: { value } }) => setInputValue(value),
1087
1336
  slots: {
1088
1337
  root: {
@@ -1096,42 +1345,46 @@ var IdentityInput = ({ method, ...viewStateProps }) => {
1096
1345
  }, validationMessage.length && {
1097
1346
  validationValence: "error",
1098
1347
  validationMessage
1099
- })), /* @__PURE__ */ React18.createElement("div", {
1348
+ }, {
1349
+ "data-testid": "identity-input"
1350
+ })), /* @__PURE__ */ React22.createElement("div", {
1100
1351
  role: "none",
1101
1352
  className: "grow"
1102
- }), /* @__PURE__ */ React18.createElement("div", {
1353
+ }), /* @__PURE__ */ React22.createElement("div", {
1103
1354
  className: "flex gap-2"
1104
- }, /* @__PURE__ */ React18.createElement(Button7, {
1355
+ }, /* @__PURE__ */ React22.createElement(Button8, {
1105
1356
  disabled,
1106
1357
  className: "grow flex items-center gap-2 pli-2 order-2",
1107
- onClick: handleNext
1108
- }, /* @__PURE__ */ React18.createElement(CaretLeft4, {
1358
+ onClick: handleNext,
1359
+ "data-testid": `${method === "recover identity" ? "recover" : "create"}-identity-input-continue`
1360
+ }, /* @__PURE__ */ React22.createElement(CaretLeft4, {
1109
1361
  weight: "bold",
1110
- className: mx11(getSize8(2), "invisible")
1111
- }), /* @__PURE__ */ React18.createElement("span", {
1362
+ className: mx17(getSize9(2), "invisible")
1363
+ }), /* @__PURE__ */ React22.createElement("span", {
1112
1364
  className: "grow"
1113
- }, t("continue label")), /* @__PURE__ */ React18.createElement(CaretRight4, {
1365
+ }, t("continue label")), /* @__PURE__ */ React22.createElement(CaretRight4, {
1114
1366
  weight: "bold",
1115
- className: getSize8(4)
1116
- })), /* @__PURE__ */ React18.createElement(Button7, {
1367
+ className: getSize9(4)
1368
+ })), /* @__PURE__ */ React22.createElement(Button8, {
1117
1369
  disabled,
1118
1370
  onClick: () => dispatch({
1119
1371
  type: "add identity"
1120
1372
  }),
1121
- className: "flex items-center gap-2 pis-2 pie-4"
1122
- }, /* @__PURE__ */ React18.createElement(CaretLeft4, {
1373
+ className: "flex items-center gap-2 pis-2 pie-4",
1374
+ "data-testid": `${method === "recover identity" ? "recover" : "create"}-identity-input-back`
1375
+ }, /* @__PURE__ */ React22.createElement(CaretLeft4, {
1123
1376
  weight: "bold",
1124
- className: getSize8(4)
1125
- }), /* @__PURE__ */ React18.createElement("span", null, t("back label")))));
1377
+ className: getSize9(4)
1378
+ }), /* @__PURE__ */ React22.createElement("span", null, t("back label")))));
1126
1379
  };
1127
1380
 
1128
1381
  // packages/apps/patterns/react-ui/src/panels/JoinPanel/view-states/InvitationAccepted.tsx
1129
- import { CaretLeft as CaretLeft5, Check } from "phosphor-react";
1130
- import React19, { cloneElement as cloneElement2 } from "react";
1382
+ import { CaretLeft as CaretLeft5, Check as Check2 } from "phosphor-react";
1383
+ import React23, { cloneElement as cloneElement4 } from "react";
1131
1384
  import { useInvitationStatus as useInvitationStatus3 } from "@dxos/react-client";
1132
- import { Button as Button8, getSize as getSize9, mx as mx12, useTranslation as useTranslation11 } from "@dxos/react-components";
1133
- function _extends16() {
1134
- _extends16 = Object.assign || function(target) {
1385
+ import { Button as Button9, getSize as getSize10, mx as mx18, useTranslation as useTranslation13 } from "@dxos/react-components";
1386
+ function _extends19() {
1387
+ _extends19 = Object.assign || function(target) {
1135
1388
  for (var i = 1; i < arguments.length; i++) {
1136
1389
  var source = arguments[i];
1137
1390
  for (var key in source) {
@@ -1142,50 +1395,51 @@ function _extends16() {
1142
1395
  }
1143
1396
  return target;
1144
1397
  };
1145
- return _extends16.apply(this, arguments);
1398
+ return _extends19.apply(this, arguments);
1146
1399
  }
1147
1400
  var PureInvitationAcceptedContent = ({ onDone, result, invitationType, doneActionParent, active }) => {
1148
1401
  const disabled = !active;
1149
- const { t } = useTranslation11("os");
1150
- const doneButton = /* @__PURE__ */ React19.createElement(Button8, _extends16({}, onDone && {
1402
+ const { t } = useTranslation13("os");
1403
+ const doneButton = /* @__PURE__ */ React23.createElement(Button9, _extends19({}, onDone && {
1151
1404
  onClick: () => onDone(result)
1152
1405
  }, {
1153
1406
  disabled,
1154
1407
  className: "grow flex items-center gap-2 pli-2",
1155
- "data-autofocus": `${invitationType} invitation acceptor; invitation accepted`
1156
- }), /* @__PURE__ */ React19.createElement(CaretLeft5, {
1408
+ "data-autofocus": `${invitationType} invitation acceptor; invitation accepted`,
1409
+ "data-testid": `${invitationType}-invitation-accepted-done`
1410
+ }), /* @__PURE__ */ React23.createElement(CaretLeft5, {
1157
1411
  weight: "bold",
1158
- className: mx12(getSize9(2), "invisible")
1159
- }), /* @__PURE__ */ React19.createElement("span", {
1412
+ className: mx18(getSize10(2), "invisible")
1413
+ }), /* @__PURE__ */ React23.createElement("span", {
1160
1414
  className: "grow"
1161
- }, t("done label")), /* @__PURE__ */ React19.createElement(Check, {
1415
+ }, t("done label")), /* @__PURE__ */ React23.createElement(Check2, {
1162
1416
  weight: "bold",
1163
- className: getSize9(4)
1417
+ className: getSize10(4)
1164
1418
  }));
1165
- return doneActionParent ? /* @__PURE__ */ cloneElement2(doneActionParent, {}, doneButton) : doneButton;
1419
+ return doneActionParent ? /* @__PURE__ */ cloneElement4(doneActionParent, {}, doneButton) : doneButton;
1166
1420
  };
1167
1421
  var InvitationAcceptedContent = (props) => {
1168
1422
  const { result } = useInvitationStatus3(props.activeInvitation);
1169
- return /* @__PURE__ */ React19.createElement(PureInvitationAcceptedContent, _extends16({}, props, {
1423
+ return /* @__PURE__ */ React23.createElement(PureInvitationAcceptedContent, _extends19({}, props, {
1170
1424
  result
1171
1425
  }));
1172
1426
  };
1173
1427
  var InvitationAccepted = (props) => {
1174
1428
  const { invitationType: _invitationType, doneActionParent: _doneActionParent, onDone: _onDone, ...viewStateProps } = props;
1175
1429
  const { activeInvitation } = viewStateProps;
1176
- return /* @__PURE__ */ React19.createElement(ViewState, _extends16({}, viewStateProps), !activeInvitation || activeInvitation === true ? /* @__PURE__ */ React19.createElement(PureInvitationAcceptedContent, _extends16({}, props, {
1430
+ return /* @__PURE__ */ React23.createElement(ViewState, _extends19({}, viewStateProps), !activeInvitation || activeInvitation === true ? /* @__PURE__ */ React23.createElement(PureInvitationAcceptedContent, _extends19({}, props, {
1177
1431
  result: null
1178
- })) : /* @__PURE__ */ React19.createElement(InvitationAcceptedContent, _extends16({}, props)));
1432
+ })) : /* @__PURE__ */ React23.createElement(InvitationAcceptedContent, _extends19({}, props)));
1179
1433
  };
1180
1434
 
1181
1435
  // packages/apps/patterns/react-ui/src/panels/JoinPanel/view-states/InvitationInput.tsx
1182
1436
  import { CaretLeft as CaretLeft6, CaretRight as CaretRight5 } from "phosphor-react";
1183
- import React20, { useState as useState4 } from "react";
1437
+ import React24, { useState as useState4 } from "react";
1184
1438
  import { InvitationEncoder } from "@dxos/client";
1185
- import { useClient as useClient4 } from "@dxos/react-client";
1186
- import { Button as Button9, getSize as getSize10, Input as Input2, mx as mx13, useTranslation as useTranslation12 } from "@dxos/react-components";
1187
- function _extends17() {
1188
- _extends17 = Object.assign || function(target) {
1439
+ import { useClient as useClient5 } from "@dxos/react-client";
1440
+ import { Button as Button10, getSize as getSize11, Input as Input2, mx as mx19, useTranslation as useTranslation14 } from "@dxos/react-components";
1441
+ function _extends20() {
1442
+ _extends20 = Object.assign || function(target) {
1189
1443
  for (var i = 1; i < arguments.length; i++) {
1190
1444
  var source = arguments[i];
1191
1445
  for (var key in source) {
@@ -1196,22 +1450,22 @@ function _extends17() {
1196
1450
  }
1197
1451
  return target;
1198
1452
  };
1199
- return _extends17.apply(this, arguments);
1453
+ return _extends20.apply(this, arguments);
1200
1454
  }
1201
1455
  var InvitationInput = ({ invitationType, ...viewStateProps }) => {
1202
- const client = useClient4();
1456
+ const client = useClient5();
1203
1457
  const disabled = !viewStateProps.active;
1204
1458
  const { dispatch } = viewStateProps;
1205
- const { t } = useTranslation12("os");
1459
+ const { t } = useTranslation14("os");
1206
1460
  const [inputValue, setInputValue] = useState4("");
1207
1461
  const handleNext = () => dispatch({
1208
1462
  type: "connecting invitation",
1209
1463
  from: invitationType,
1210
1464
  invitation: client[invitationType === "halo" ? "halo" : "echo"].acceptInvitation(InvitationEncoder.decode(inputValue))
1211
1465
  });
1212
- return /* @__PURE__ */ React20.createElement(ViewState, _extends17({}, viewStateProps), /* @__PURE__ */ React20.createElement(Input2, {
1466
+ return /* @__PURE__ */ React24.createElement(ViewState, _extends20({}, viewStateProps), /* @__PURE__ */ React24.createElement(Input2, {
1213
1467
  disabled,
1214
- label: /* @__PURE__ */ React20.createElement(ViewStateHeading, null, t("invitation input label")),
1468
+ label: /* @__PURE__ */ React24.createElement(ViewStateHeading, null, t("invitation input label")),
1215
1469
  onChange: ({ target: { value } }) => setInputValue(value),
1216
1470
  slots: {
1217
1471
  root: {
@@ -1224,44 +1478,47 @@ var InvitationInput = ({ invitationType, ...viewStateProps }) => {
1224
1478
  "data-autofocus": `${invitationType} invitation acceptor; invitation input`,
1225
1479
  onKeyUp: ({ key }) => key === "Enter" && handleNext()
1226
1480
  }
1227
- }
1228
- }), /* @__PURE__ */ React20.createElement("div", {
1481
+ },
1482
+ "data-testid": "invitation-input"
1483
+ }), /* @__PURE__ */ React24.createElement("div", {
1229
1484
  role: "none",
1230
1485
  className: "grow"
1231
- }), /* @__PURE__ */ React20.createElement("div", {
1486
+ }), /* @__PURE__ */ React24.createElement("div", {
1232
1487
  className: "flex gap-2"
1233
- }, /* @__PURE__ */ React20.createElement(Button9, {
1488
+ }, /* @__PURE__ */ React24.createElement(Button10, {
1234
1489
  disabled,
1235
1490
  className: "grow flex items-center gap-2 pli-2 order-2",
1236
- onClick: handleNext
1237
- }, /* @__PURE__ */ React20.createElement(CaretLeft6, {
1491
+ onClick: handleNext,
1492
+ "data-testid": `${invitationType}-invitation-input-continue`
1493
+ }, /* @__PURE__ */ React24.createElement(CaretLeft6, {
1238
1494
  weight: "bold",
1239
- className: mx13(getSize10(2), "invisible")
1240
- }), /* @__PURE__ */ React20.createElement("span", {
1495
+ className: mx19(getSize11(2), "invisible")
1496
+ }), /* @__PURE__ */ React24.createElement("span", {
1241
1497
  className: "grow"
1242
- }, t("continue label")), /* @__PURE__ */ React20.createElement(CaretRight5, {
1498
+ }, t("continue label")), /* @__PURE__ */ React24.createElement(CaretRight5, {
1243
1499
  weight: "bold",
1244
- className: getSize10(4)
1245
- })), /* @__PURE__ */ React20.createElement(Button9, {
1500
+ className: getSize11(4)
1501
+ })), /* @__PURE__ */ React24.createElement(Button10, {
1246
1502
  disabled,
1247
1503
  onClick: () => dispatch({
1248
1504
  type: "add identity"
1249
1505
  }),
1250
- className: "flex items-center gap-2 pis-2 pie-4"
1251
- }, /* @__PURE__ */ React20.createElement(CaretLeft6, {
1506
+ className: "flex items-center gap-2 pis-2 pie-4",
1507
+ "data-testid": `${invitationType}-invitation-input-back`
1508
+ }, /* @__PURE__ */ React24.createElement(CaretLeft6, {
1252
1509
  weight: "bold",
1253
- className: getSize10(4)
1254
- }), /* @__PURE__ */ React20.createElement("span", null, t("back label")))));
1510
+ className: getSize11(4)
1511
+ }), /* @__PURE__ */ React24.createElement("span", null, t("back label")))));
1255
1512
  };
1256
1513
 
1257
1514
  // packages/apps/patterns/react-ui/src/panels/JoinPanel/view-states/InvitationRescuer.tsx
1258
1515
  import { ArrowsClockwise, CaretLeft as CaretLeft7, CaretRight as CaretRight6 } from "phosphor-react";
1259
- import React21 from "react";
1516
+ import React25 from "react";
1260
1517
  import { Invitation as Invitation5 } from "@dxos/client";
1261
1518
  import { useInvitationStatus as useInvitationStatus4 } from "@dxos/react-client";
1262
- import { Button as Button10, getSize as getSize11, mx as mx14, useTranslation as useTranslation13 } from "@dxos/react-components";
1263
- function _extends18() {
1264
- _extends18 = Object.assign || function(target) {
1519
+ import { Button as Button11, getSize as getSize12, mx as mx20, useTranslation as useTranslation15 } from "@dxos/react-components";
1520
+ function _extends21() {
1521
+ _extends21 = Object.assign || function(target) {
1265
1522
  for (var i = 1; i < arguments.length; i++) {
1266
1523
  var source = arguments[i];
1267
1524
  for (var key in source) {
@@ -1272,78 +1529,82 @@ function _extends18() {
1272
1529
  }
1273
1530
  return target;
1274
1531
  };
1275
- return _extends18.apply(this, arguments);
1532
+ return _extends21.apply(this, arguments);
1276
1533
  }
1277
1534
  var InvitationActions = ({ activeInvitation, disabled, dispatch, invitationType }) => {
1278
1535
  const { status, cancel } = useInvitationStatus4(activeInvitation);
1279
- const { t } = useTranslation13("os");
1536
+ const { t } = useTranslation15("os");
1280
1537
  switch (status) {
1281
1538
  case Invitation5.State.CONNECTING:
1282
- return /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement("div", {
1539
+ return /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement("div", {
1283
1540
  role: "none",
1284
1541
  className: "grow"
1285
- }), /* @__PURE__ */ React21.createElement("div", {
1542
+ }), /* @__PURE__ */ React25.createElement("div", {
1286
1543
  className: "flex gap-2"
1287
- }, /* @__PURE__ */ React21.createElement(Button10, {
1544
+ }, /* @__PURE__ */ React25.createElement(Button11, {
1288
1545
  disabled: true,
1289
- className: "grow flex items-center gap-2 pli-2 order-2"
1290
- }, /* @__PURE__ */ React21.createElement(CaretLeft7, {
1546
+ className: "grow flex items-center gap-2 pli-2 order-2",
1547
+ "data-testid": "next"
1548
+ }, /* @__PURE__ */ React25.createElement(CaretLeft7, {
1291
1549
  weight: "bold",
1292
- className: mx14(getSize11(2), "invisible")
1293
- }), /* @__PURE__ */ React21.createElement("span", {
1550
+ className: mx20(getSize12(2), "invisible")
1551
+ }), /* @__PURE__ */ React25.createElement("span", {
1294
1552
  className: "grow"
1295
- }, t("next label")), /* @__PURE__ */ React21.createElement(CaretRight6, {
1553
+ }, t("next label")), /* @__PURE__ */ React25.createElement(CaretRight6, {
1296
1554
  weight: "bold",
1297
- className: getSize11(4)
1298
- })), /* @__PURE__ */ React21.createElement(Button10, {
1555
+ className: getSize12(4)
1556
+ })), /* @__PURE__ */ React25.createElement(Button11, {
1299
1557
  disabled,
1300
1558
  className: "flex items-center gap-2 pis-2 pie-4",
1301
1559
  onClick: cancel,
1302
- "data-autofocus": `${invitationType} invitation acceptor; invitation rescuer`
1303
- }, /* @__PURE__ */ React21.createElement(CaretLeft7, {
1560
+ "data-autofocus": `${invitationType} invitation acceptor; invitation rescuer`,
1561
+ "data-testid": "invitation-rescuer-cancel"
1562
+ }, /* @__PURE__ */ React25.createElement(CaretLeft7, {
1304
1563
  weight: "bold",
1305
- className: getSize11(4)
1306
- }), /* @__PURE__ */ React21.createElement("span", null, t("cancel label")))));
1564
+ className: getSize12(4)
1565
+ }), /* @__PURE__ */ React25.createElement("span", null, t("cancel label")))));
1307
1566
  case Invitation5.State.TIMEOUT:
1308
1567
  case Invitation5.State.CANCELLED:
1309
1568
  case Invitation5.State.ERROR:
1310
1569
  default:
1311
- return /* @__PURE__ */ React21.createElement(Button10, {
1570
+ return /* @__PURE__ */ React25.createElement(Button11, {
1312
1571
  disabled,
1313
1572
  className: "grow flex items-center gap-2 pli-2",
1314
1573
  onClick: () => dispatch({
1315
1574
  type: "reset invitation",
1316
1575
  from: invitationType
1317
1576
  }),
1318
- "data-autofocus": `${invitationType} invitation acceptor; invitation rescuer`
1319
- }, /* @__PURE__ */ React21.createElement(CaretLeft7, {
1577
+ "data-autofocus": `${invitationType} invitation acceptor; invitation rescuer`,
1578
+ "data-testid": "invitation-rescuer-reset"
1579
+ }, /* @__PURE__ */ React25.createElement(CaretLeft7, {
1320
1580
  weight: "bold",
1321
- className: mx14(getSize11(5), "invisible")
1322
- }), /* @__PURE__ */ React21.createElement("span", {
1581
+ className: mx20(getSize12(5), "invisible")
1582
+ }), /* @__PURE__ */ React25.createElement("span", {
1323
1583
  className: "grow"
1324
- }, t("reset label")), /* @__PURE__ */ React21.createElement(ArrowsClockwise, {
1584
+ }, t("reset label")), /* @__PURE__ */ React25.createElement(ArrowsClockwise, {
1325
1585
  weight: "bold",
1326
- className: getSize11(5)
1586
+ className: getSize12(5)
1327
1587
  }));
1328
1588
  }
1329
1589
  };
1330
1590
  var InvitationRescuer = ({ invitationType, ...viewStateProps }) => {
1331
1591
  const disabled = !viewStateProps.active;
1332
1592
  const { dispatch, activeInvitation } = viewStateProps;
1333
- const { t } = useTranslation13("os");
1334
- return /* @__PURE__ */ React21.createElement(ViewState, _extends18({}, viewStateProps), activeInvitation === true || !activeInvitation ? /* @__PURE__ */ React21.createElement(Button10, {
1593
+ const { t } = useTranslation15("os");
1594
+ return /* @__PURE__ */ React25.createElement(ViewState, _extends21({}, viewStateProps), activeInvitation === true || !activeInvitation ? /* @__PURE__ */ React25.createElement(Button11, {
1335
1595
  disabled,
1336
1596
  className: "grow flex items-center gap-2 pli-2",
1337
- "data-autofocus": "space invitation acceptor; invitation rescuer"
1338
- }, /* @__PURE__ */ React21.createElement(CaretLeft7, {
1597
+ "data-autofocus": "space invitation acceptor; invitation rescuer",
1598
+ "data-testid": "invitation-rescuer-connect"
1599
+ }, /* @__PURE__ */ React25.createElement(CaretLeft7, {
1339
1600
  weight: "bold",
1340
- className: mx14(getSize11(5), "invisible")
1341
- }), /* @__PURE__ */ React21.createElement("span", {
1601
+ className: mx20(getSize12(5), "invisible")
1602
+ }), /* @__PURE__ */ React25.createElement("span", {
1342
1603
  className: "grow"
1343
- }, t("connect label")), /* @__PURE__ */ React21.createElement(ArrowsClockwise, {
1604
+ }, t("connect label")), /* @__PURE__ */ React25.createElement(ArrowsClockwise, {
1344
1605
  weight: "bold",
1345
- className: getSize11(5)
1346
- })) : /* @__PURE__ */ React21.createElement(InvitationActions, _extends18({}, {
1606
+ className: getSize12(5)
1607
+ })) : /* @__PURE__ */ React25.createElement(InvitationActions, _extends21({}, {
1347
1608
  activeInvitation,
1348
1609
  disabled,
1349
1610
  dispatch,
@@ -1353,11 +1614,11 @@ var InvitationRescuer = ({ invitationType, ...viewStateProps }) => {
1353
1614
 
1354
1615
  // packages/apps/patterns/react-ui/src/panels/JoinPanel/view-states/InvitationAuthenticator.tsx
1355
1616
  import { CaretLeft as CaretLeft8, CaretRight as CaretRight7 } from "phosphor-react";
1356
- import React22, { useCallback as useCallback5, useState as useState5 } from "react";
1617
+ import React26, { useCallback as useCallback5, useState as useState5 } from "react";
1357
1618
  import { useInvitationStatus as useInvitationStatus5 } from "@dxos/react-client";
1358
- import { Button as Button11, getSize as getSize12, Input as Input3, mx as mx15, useTranslation as useTranslation14 } from "@dxos/react-components";
1359
- function _extends19() {
1360
- _extends19 = Object.assign || function(target) {
1619
+ import { Button as Button12, getSize as getSize13, Input as Input3, mx as mx21, useTranslation as useTranslation16 } from "@dxos/react-components";
1620
+ function _extends22() {
1621
+ _extends22 = Object.assign || function(target) {
1361
1622
  for (var i = 1; i < arguments.length; i++) {
1362
1623
  var source = arguments[i];
1363
1624
  for (var key in source) {
@@ -1368,13 +1629,13 @@ function _extends19() {
1368
1629
  }
1369
1630
  return target;
1370
1631
  };
1371
- return _extends19.apply(this, arguments);
1632
+ return _extends22.apply(this, arguments);
1372
1633
  }
1373
1634
  var pinLength = 6;
1374
1635
  var PureInvitationAuthenticatorContent = ({ disabled, failed, dispatch, invitationType, onChange, onAuthenticate }) => {
1375
- const { t } = useTranslation14("os");
1376
- return /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement(Input3, _extends19({
1377
- label: t("pin input label"),
1636
+ const { t } = useTranslation16("os");
1637
+ return /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(Input3, _extends22({
1638
+ label: t("auth code input label"),
1378
1639
  size: "pin",
1379
1640
  length: pinLength,
1380
1641
  onChange,
@@ -1399,35 +1660,39 @@ var PureInvitationAuthenticatorContent = ({ disabled, failed, dispatch, invitati
1399
1660
  }, failed && {
1400
1661
  validationValence: "error",
1401
1662
  validationMessage: t("failed to authenticate message")
1402
- })), /* @__PURE__ */ React22.createElement("div", {
1663
+ }, {
1664
+ "data-testid": "auth-code-input"
1665
+ })), /* @__PURE__ */ React26.createElement("div", {
1403
1666
  role: "none",
1404
1667
  className: "grow"
1405
- }), /* @__PURE__ */ React22.createElement("div", {
1668
+ }), /* @__PURE__ */ React26.createElement("div", {
1406
1669
  className: "flex gap-2"
1407
- }, /* @__PURE__ */ React22.createElement(Button11, {
1670
+ }, /* @__PURE__ */ React26.createElement(Button12, {
1408
1671
  disabled,
1409
1672
  className: "grow flex items-center gap-2 pli-2 order-2",
1410
1673
  onClick: onAuthenticate,
1411
- "data-autofocus-pinlength": invitationType
1412
- }, /* @__PURE__ */ React22.createElement(CaretLeft8, {
1674
+ "data-autofocus-pinlength": invitationType,
1675
+ "data-testid": `${invitationType}-invitation-authenticator-next`
1676
+ }, /* @__PURE__ */ React26.createElement(CaretLeft8, {
1413
1677
  weight: "bold",
1414
- className: mx15(getSize12(2), "invisible")
1415
- }), /* @__PURE__ */ React22.createElement("span", {
1678
+ className: mx21(getSize13(2), "invisible")
1679
+ }), /* @__PURE__ */ React26.createElement("span", {
1416
1680
  className: "grow"
1417
- }, t("next label")), /* @__PURE__ */ React22.createElement(CaretRight7, {
1681
+ }, t("next label")), /* @__PURE__ */ React26.createElement(CaretRight7, {
1418
1682
  weight: "bold",
1419
- className: getSize12(4)
1420
- })), /* @__PURE__ */ React22.createElement(Button11, {
1683
+ className: getSize13(4)
1684
+ })), /* @__PURE__ */ React26.createElement(Button12, {
1421
1685
  disabled,
1422
1686
  className: "flex items-center gap-2 pis-2 pie-4",
1423
1687
  onClick: () => dispatch({
1424
1688
  type: "cancel invitation",
1425
1689
  from: invitationType
1426
- })
1427
- }, /* @__PURE__ */ React22.createElement(CaretLeft8, {
1690
+ }),
1691
+ "data-testid": `${invitationType}-invitation-authenticator-cancel`
1692
+ }, /* @__PURE__ */ React26.createElement(CaretLeft8, {
1428
1693
  weight: "bold",
1429
- className: getSize12(4)
1430
- }), /* @__PURE__ */ React22.createElement("span", null, t("cancel label")))));
1694
+ className: getSize13(4)
1695
+ }), /* @__PURE__ */ React26.createElement("span", null, t("cancel label")))));
1431
1696
  };
1432
1697
  var InvitationAuthenticatorContent = ({ disabled, invitation, dispatch, invitationType, failed }) => {
1433
1698
  const [pinValue, setPinValue] = useState5("");
@@ -1454,7 +1719,7 @@ var InvitationAuthenticatorContent = ({ disabled, invitation, dispatch, invitati
1454
1719
  authenticate,
1455
1720
  pinValue
1456
1721
  ]);
1457
- return /* @__PURE__ */ React22.createElement(PureInvitationAuthenticatorContent, _extends19({}, {
1722
+ return /* @__PURE__ */ React26.createElement(PureInvitationAuthenticatorContent, _extends22({}, {
1458
1723
  disabled,
1459
1724
  failed,
1460
1725
  dispatch,
@@ -1466,7 +1731,7 @@ var InvitationAuthenticatorContent = ({ disabled, invitation, dispatch, invitati
1466
1731
  var InvitationAuthenticator = ({ invitationType, failed, ...viewStateProps }) => {
1467
1732
  const disabled = !viewStateProps.active;
1468
1733
  const { activeInvitation, dispatch } = viewStateProps;
1469
- return /* @__PURE__ */ React22.createElement(ViewState, _extends19({}, viewStateProps), !activeInvitation || activeInvitation === true ? /* @__PURE__ */ React22.createElement(PureInvitationAuthenticatorContent, _extends19({}, {
1734
+ return /* @__PURE__ */ React26.createElement(ViewState, _extends22({}, viewStateProps), !activeInvitation || activeInvitation === true ? /* @__PURE__ */ React26.createElement(PureInvitationAuthenticatorContent, _extends22({}, {
1470
1735
  disabled,
1471
1736
  failed,
1472
1737
  dispatch,
@@ -1475,7 +1740,7 @@ var InvitationAuthenticator = ({ invitationType, failed, ...viewStateProps }) =>
1475
1740
  },
1476
1741
  onAuthenticate: () => {
1477
1742
  }
1478
- })) : /* @__PURE__ */ React22.createElement(InvitationAuthenticatorContent, _extends19({}, {
1743
+ })) : /* @__PURE__ */ React26.createElement(InvitationAuthenticatorContent, _extends22({}, {
1479
1744
  disabled,
1480
1745
  failed,
1481
1746
  invitation: activeInvitation,
@@ -1485,8 +1750,8 @@ var InvitationAuthenticator = ({ invitationType, failed, ...viewStateProps }) =>
1485
1750
  };
1486
1751
 
1487
1752
  // packages/apps/patterns/react-ui/src/panels/JoinPanel/JoinPanel.tsx
1488
- function _extends20() {
1489
- _extends20 = Object.assign || function(target) {
1753
+ function _extends23() {
1754
+ _extends23 = Object.assign || function(target) {
1490
1755
  for (var i = 1; i < arguments.length; i++) {
1491
1756
  var source = arguments[i];
1492
1757
  for (var key in source) {
@@ -1497,13 +1762,14 @@ function _extends20() {
1497
1762
  }
1498
1763
  return target;
1499
1764
  };
1500
- return _extends20.apply(this, arguments);
1765
+ return _extends23.apply(this, arguments);
1501
1766
  }
1502
- var JoinPanel = ({ initialInvitationCode, titleId: propsTitleId, exitActionParent, onExit, doneActionParent, onDone }) => {
1503
- const client = useClient5();
1504
- const internalTitleId = useId3("joinPanel__title");
1767
+ var JoinPanel = ({ mode, initialInvitationCode, titleId: propsTitleId, exitActionParent, onExit, doneActionParent, onDone, preventExit }) => {
1768
+ const client = useClient6();
1769
+ const internalTitleId = useId4("joinPanel__title");
1505
1770
  const titleId = propsTitleId != null ? propsTitleId : internalTitleId;
1506
- const identity = useIdentity();
1771
+ const identity = useIdentity2();
1772
+ const [prevIdentity, setPrevIdentity] = useState6(identity);
1507
1773
  const availableIdentities = identity ? [
1508
1774
  identity
1509
1775
  ] : [];
@@ -1524,7 +1790,7 @@ var JoinPanel = ({ initialInvitationCode, titleId: propsTitleId, exitActionParen
1524
1790
  if (action.method === "accept device invitation") {
1525
1791
  nextState.activeView = "halo invitation acceptor";
1526
1792
  if (state.unredeemedHaloInvitationCode) {
1527
- nextState.haloInvitation = client.echo.acceptInvitation(InvitationEncoder2.decode(state.unredeemedHaloInvitationCode));
1793
+ nextState.haloInvitation = client.halo.acceptInvitation(InvitationEncoder2.decode(state.unredeemedHaloInvitationCode));
1528
1794
  nextState.unredeemedHaloInvitationCode = void 0;
1529
1795
  nextState.haloViewState = "invitation authenticator";
1530
1796
  } else {
@@ -1588,20 +1854,21 @@ var JoinPanel = ({ initialInvitationCode, titleId: propsTitleId, exitActionParen
1588
1854
  nextState[action.from === "halo" ? "haloViewState" : "spaceViewState"] = "invitation input";
1589
1855
  break;
1590
1856
  }
1591
- log.debug("[join panel reducer]", {
1857
+ log("[join panel reducer]", {
1592
1858
  action,
1593
1859
  nextState
1594
1860
  }, {
1595
1861
  file: "JoinPanel.tsx",
1596
- line: 123,
1862
+ line: 125,
1597
1863
  scope: void 0,
1598
1864
  callSite: (f, a) => f(...a)
1599
1865
  });
1600
1866
  return nextState;
1601
1867
  };
1602
- const [joinState, dispatch] = useReducer(reducer, {
1603
- unredeemedHaloInvitationCode: void 0,
1604
- unredeemedSpaceInvitationCode: initialInvitationCode,
1868
+ const unredeemedHaloInvitationCode = mode === "halo-only" ? initialInvitationCode : void 0;
1869
+ const [joinState, dispatch] = useReducer2(reducer, {
1870
+ unredeemedHaloInvitationCode,
1871
+ unredeemedSpaceInvitationCode: mode === "halo-only" ? void 0 : initialInvitationCode,
1605
1872
  spaceInvitation: void 0,
1606
1873
  haloInvitation: void 0,
1607
1874
  activeView: availableIdentities.length > 0 ? "identity selector" : "addition method selector",
@@ -1610,13 +1877,30 @@ var JoinPanel = ({ initialInvitationCode, titleId: propsTitleId, exitActionParen
1610
1877
  spaceViewState: "invitation input",
1611
1878
  haloViewState: "invitation input"
1612
1879
  });
1880
+ if (identity !== prevIdentity) {
1881
+ setPrevIdentity(identity);
1882
+ identity && !prevIdentity && dispatch({
1883
+ type: "added identity",
1884
+ identity
1885
+ });
1886
+ }
1887
+ useEffect(() => {
1888
+ if (unredeemedHaloInvitationCode) {
1889
+ dispatch({
1890
+ type: "select addition method",
1891
+ method: "accept device invitation"
1892
+ });
1893
+ }
1894
+ }, [
1895
+ unredeemedHaloInvitationCode
1896
+ ]);
1613
1897
  useEffect(() => {
1614
1898
  const attrValue = joinState.activeView === "identity input" ? `${joinState.activeView}; ${joinState.additionMethod}` : joinState.activeView === "space invitation acceptor" ? `${joinState.activeView}; ${joinState.spaceViewState}` : joinState.activeView === "halo invitation acceptor" ? `${joinState.activeView}; ${joinState.haloViewState}` : joinState.activeView;
1615
- log.debug("[autofocus value]", {
1899
+ log("[autofocus value]", {
1616
1900
  attrValue
1617
1901
  }, {
1618
1902
  file: "JoinPanel.tsx",
1619
- line: 149,
1903
+ line: 163,
1620
1904
  scope: void 0,
1621
1905
  callSite: (f, a) => f(...a)
1622
1906
  });
@@ -1691,45 +1975,49 @@ var JoinPanel = ({ initialInvitationCode, titleId: propsTitleId, exitActionParen
1691
1975
  }, [
1692
1976
  joinState.haloInvitation
1693
1977
  ]);
1694
- return /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(JoinHeading, _extends20({}, {
1978
+ return /* @__PURE__ */ React27.createElement(DensityProvider3, {
1979
+ density: "fine"
1980
+ }, /* @__PURE__ */ React27.createElement(JoinHeading, _extends23({}, {
1981
+ mode,
1695
1982
  titleId,
1696
1983
  invitation: joinState.spaceInvitation,
1697
1984
  onExit,
1698
- exitActionParent
1699
- })), /* @__PURE__ */ React23.createElement("div", {
1985
+ exitActionParent,
1986
+ preventExit
1987
+ })), /* @__PURE__ */ React27.createElement("div", {
1700
1988
  role: "none",
1701
1989
  className: "is-full overflow-hidden"
1702
- }, /* @__PURE__ */ React23.createElement("div", {
1990
+ }, /* @__PURE__ */ React27.createElement("div", {
1703
1991
  role: "none",
1704
1992
  className: "flex is-[1300%]",
1705
1993
  "aria-live": "polite"
1706
- }, /* @__PURE__ */ React23.createElement(IdentitySelector, _extends20({}, {
1994
+ }, /* @__PURE__ */ React27.createElement(IdentitySelector, _extends23({}, {
1707
1995
  dispatch,
1708
1996
  availableIdentities,
1709
1997
  active: joinState.activeView === "identity selector"
1710
- })), /* @__PURE__ */ React23.createElement(AdditionMethodSelector, _extends20({}, {
1998
+ })), /* @__PURE__ */ React27.createElement(AdditionMethodSelector, _extends23({}, {
1711
1999
  dispatch,
1712
2000
  availableIdentities,
1713
2001
  active: joinState.activeView === "addition method selector"
1714
- })), /* @__PURE__ */ React23.createElement(IdentityInput, _extends20({}, {
2002
+ })), /* @__PURE__ */ React27.createElement(IdentityInput, _extends23({}, {
1715
2003
  dispatch,
1716
2004
  active: joinState.activeView === "identity input" && joinState.additionMethod === "create identity",
1717
2005
  method: "create identity"
1718
- })), /* @__PURE__ */ React23.createElement(IdentityInput, _extends20({}, {
2006
+ })), /* @__PURE__ */ React27.createElement(IdentityInput, _extends23({}, {
1719
2007
  dispatch,
1720
2008
  active: joinState.activeView === "identity input" && joinState.additionMethod === "recover identity",
1721
2009
  method: "recover identity"
1722
- })), /* @__PURE__ */ React23.createElement(InvitationInput, _extends20({}, {
2010
+ })), /* @__PURE__ */ React27.createElement(InvitationInput, _extends23({}, {
1723
2011
  dispatch,
1724
2012
  activeInvitation: joinState.haloInvitation || true,
1725
2013
  active: joinState.activeView === "halo invitation acceptor" && joinState.haloViewState === "invitation input",
1726
2014
  invitationType: "halo"
1727
- })), /* @__PURE__ */ React23.createElement(InvitationRescuer, _extends20({}, {
2015
+ })), /* @__PURE__ */ React27.createElement(InvitationRescuer, _extends23({}, {
1728
2016
  dispatch,
1729
2017
  activeInvitation: joinState.haloInvitation || true,
1730
2018
  active: joinState.activeView === "halo invitation acceptor" && joinState.haloViewState === "invitation rescuer",
1731
2019
  invitationType: "halo"
1732
- })), /* @__PURE__ */ React23.createElement(InvitationAuthenticator, _extends20({}, {
2020
+ })), /* @__PURE__ */ React27.createElement(InvitationAuthenticator, _extends23({}, {
1733
2021
  dispatch,
1734
2022
  activeInvitation: joinState.haloInvitation || true,
1735
2023
  active: joinState.activeView === "halo invitation acceptor" && joinState.haloViewState === "invitation authenticator",
@@ -1737,28 +2025,33 @@ var JoinPanel = ({ initialInvitationCode, titleId: propsTitleId, exitActionParen
1737
2025
  ...joinState.spaceInvitationAnnotation === "authentication failed" && {
1738
2026
  failed: true
1739
2027
  }
1740
- })), /* @__PURE__ */ React23.createElement(InvitationAccepted, _extends20({}, {
2028
+ })), /* @__PURE__ */ React27.createElement(InvitationAccepted, _extends23({}, {
1741
2029
  dispatch,
1742
2030
  activeInvitation: joinState.haloInvitation || true,
1743
2031
  active: joinState.activeView === "halo invitation acceptor" && joinState.haloViewState === "invitation accepted",
1744
- invitationType: "halo"
1745
- })), /* @__PURE__ */ React23.createElement(IdentityAdded, _extends20({}, {
2032
+ invitationType: "halo",
2033
+ doneActionParent,
2034
+ onDone
2035
+ })), /* @__PURE__ */ React27.createElement(IdentityAdded, _extends23({}, {
2036
+ mode,
1746
2037
  dispatch,
1747
2038
  addedIdentity: joinState.selectedIdentity,
1748
- active: joinState.activeView === "identity added"
1749
- })), /* @__PURE__ */ React23.createElement(InvitationInput, _extends20({}, {
2039
+ active: joinState.activeView === "identity added",
2040
+ doneActionParent,
2041
+ onDone
2042
+ })), /* @__PURE__ */ React27.createElement(InvitationInput, _extends23({}, {
1750
2043
  dispatch,
1751
2044
  activeInvitation: joinState.spaceInvitation || true,
1752
2045
  selectedIdentity: joinState.selectedIdentity,
1753
2046
  active: joinState.activeView === "space invitation acceptor" && joinState.spaceViewState === "invitation input",
1754
2047
  invitationType: "space"
1755
- })), /* @__PURE__ */ React23.createElement(InvitationRescuer, _extends20({}, {
2048
+ })), /* @__PURE__ */ React27.createElement(InvitationRescuer, _extends23({}, {
1756
2049
  dispatch,
1757
2050
  activeInvitation: joinState.spaceInvitation || true,
1758
2051
  selectedIdentity: joinState.selectedIdentity,
1759
2052
  active: joinState.activeView === "space invitation acceptor" && joinState.spaceViewState === "invitation rescuer",
1760
2053
  invitationType: "space"
1761
- })), /* @__PURE__ */ React23.createElement(InvitationAuthenticator, _extends20({}, {
2054
+ })), /* @__PURE__ */ React27.createElement(InvitationAuthenticator, _extends23({}, {
1762
2055
  dispatch,
1763
2056
  activeInvitation: joinState.spaceInvitation || true,
1764
2057
  selectedIdentity: joinState.selectedIdentity,
@@ -1767,7 +2060,7 @@ var JoinPanel = ({ initialInvitationCode, titleId: propsTitleId, exitActionParen
1767
2060
  ...joinState.spaceInvitationAnnotation === "authentication failed" && {
1768
2061
  failed: true
1769
2062
  }
1770
- })), /* @__PURE__ */ React23.createElement(InvitationAccepted, _extends20({}, {
2063
+ })), /* @__PURE__ */ React27.createElement(InvitationAccepted, _extends23({}, {
1771
2064
  dispatch,
1772
2065
  activeInvitation: joinState.spaceInvitation || true,
1773
2066
  selectedIdentity: joinState.selectedIdentity,
@@ -1778,9 +2071,81 @@ var JoinPanel = ({ initialInvitationCode, titleId: propsTitleId, exitActionParen
1778
2071
  })))));
1779
2072
  };
1780
2073
 
2074
+ // packages/apps/patterns/react-ui/src/panels/SpacePanel/SpacePanel.tsx
2075
+ import { UserPlus as UserPlus3 } from "phosphor-react";
2076
+ import React28, { useReducer as useReducer3 } from "react";
2077
+ import { useSpaceInvitations as useSpaceInvitations2 } from "@dxos/react-client";
2078
+ import { Button as Button13, DensityProvider as DensityProvider4, getSize as getSize14, mx as mx22, useTranslation as useTranslation17 } from "@dxos/react-components";
2079
+ function _extends24() {
2080
+ _extends24 = Object.assign || function(target) {
2081
+ for (var i = 1; i < arguments.length; i++) {
2082
+ var source = arguments[i];
2083
+ for (var key in source) {
2084
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
2085
+ target[key] = source[key];
2086
+ }
2087
+ }
2088
+ }
2089
+ return target;
2090
+ };
2091
+ return _extends24.apply(this, arguments);
2092
+ }
2093
+ var CurrentSpaceView = ({ space, createInvitationUrl, titleId }) => {
2094
+ const { t } = useTranslation17("os");
2095
+ const invitations = useSpaceInvitations2(space == null ? void 0 : space.key);
2096
+ const name = space == null ? void 0 : space.properties.name;
2097
+ if (!space) {
2098
+ return null;
2099
+ }
2100
+ return /* @__PURE__ */ React28.createElement("div", {
2101
+ role: "none",
2102
+ className: "flex flex-col"
2103
+ }, /* @__PURE__ */ React28.createElement("div", {
2104
+ role: "none",
2105
+ className: mx22(subduedSurface, "rounded-bs-md flex items-center p-2 gap-2")
2106
+ }, /* @__PURE__ */ React28.createElement("h2", {
2107
+ id: titleId,
2108
+ className: mx22("grow font-system-medium", !name && "font-mono")
2109
+ }, name != null ? name : space.key.truncate())), /* @__PURE__ */ React28.createElement("div", {
2110
+ role: "region",
2111
+ className: mx22(defaultSurface, "rounded-be-md p-2")
2112
+ }, /* @__PURE__ */ React28.createElement(InvitationList, {
2113
+ invitations,
2114
+ onClickRemove: ({ invitation }) => invitation && (space == null ? void 0 : space.removeInvitation(invitation.invitationId)),
2115
+ createInvitationUrl
2116
+ }), /* @__PURE__ */ React28.createElement(Button13, {
2117
+ className: "is-full flex gap-2 mbs-2",
2118
+ onClick: () => space == null ? void 0 : space.createInvitation(),
2119
+ "data-testid": "create-space-invitation"
2120
+ }, /* @__PURE__ */ React28.createElement("span", null, t("create space invitation label")), /* @__PURE__ */ React28.createElement(UserPlus3, {
2121
+ className: getSize14(4),
2122
+ weight: "bold"
2123
+ })), /* @__PURE__ */ React28.createElement(PanelSeparator, null), /* @__PURE__ */ React28.createElement(SpaceMemberListContainer, {
2124
+ spaceKey: space.key,
2125
+ includeSelf: true
2126
+ })));
2127
+ };
2128
+ var SpacePanel = (props) => {
2129
+ const reducer = (state, action) => {
2130
+ const nextState = {
2131
+ ...state
2132
+ };
2133
+ switch (action.type) {
2134
+ case null:
2135
+ }
2136
+ return nextState;
2137
+ };
2138
+ const [panelState] = useReducer3(reducer, {
2139
+ activeView: "current space"
2140
+ });
2141
+ return /* @__PURE__ */ React28.createElement(DensityProvider4, {
2142
+ density: "fine"
2143
+ }, panelState.activeView === "current space" ? /* @__PURE__ */ React28.createElement(CurrentSpaceView, _extends24({}, props)) : null);
2144
+ };
2145
+
1781
2146
  // packages/apps/patterns/react-ui/src/composites/IdentityPopover/IdentityPopover.tsx
1782
- function _extends21() {
1783
- _extends21 = Object.assign || function(target) {
2147
+ function _extends25() {
2148
+ _extends25 = Object.assign || function(target) {
1784
2149
  for (var i = 1; i < arguments.length; i++) {
1785
2150
  var source = arguments[i];
1786
2151
  for (var key in source) {
@@ -1791,26 +2156,26 @@ function _extends21() {
1791
2156
  }
1792
2157
  return target;
1793
2158
  };
1794
- return _extends21.apply(this, arguments);
2159
+ return _extends25.apply(this, arguments);
1795
2160
  }
1796
2161
  var IdentityPopover = ({ identity, openTrigger, slots, triggerIsInToolbar = true, onClickManageProfile, ...popoverProps }) => {
1797
- var _a, _b;
1798
- return /* @__PURE__ */ React24.createElement(PanelPopover, _extends21({}, popoverProps, {
1799
- openTrigger: openTrigger != null ? openTrigger : /* @__PURE__ */ React24.createElement(Avatar7, {
2162
+ var _a, _b, _c;
2163
+ return /* @__PURE__ */ React29.createElement(PanelPopover, _extends25({}, popoverProps, {
2164
+ openTrigger: openTrigger != null ? openTrigger : /* @__PURE__ */ React29.createElement(Avatar8, {
1800
2165
  size: 10,
1801
2166
  variant: "circle",
1802
2167
  fallbackValue: identity.identityKey.toHex(),
1803
- label: (_a = identity.displayName) != null ? _a : ""
2168
+ label: (_b = (_a = identity.profile) == null ? void 0 : _a.displayName) != null ? _b : ""
1804
2169
  }),
1805
2170
  slots: {
1806
2171
  ...slots,
1807
2172
  trigger: {
1808
2173
  ...slots == null ? void 0 : slots.trigger,
1809
- className: mx16("flex justify-self-end pointer-events-auto bg-white dark:bg-neutral-700 p-0.5 button-elevation rounded-full", (_b = slots == null ? void 0 : slots.trigger) == null ? void 0 : _b.className)
2174
+ className: mx23("flex justify-self-end pointer-events-auto bg-white dark:bg-neutral-700 p-0.5 button-elevation rounded-full", (_c = slots == null ? void 0 : slots.trigger) == null ? void 0 : _c.className)
1810
2175
  }
1811
2176
  },
1812
2177
  triggerIsInToolbar
1813
- }), /* @__PURE__ */ React24.createElement(IdentityPanel, _extends21({}, {
2178
+ }), /* @__PURE__ */ React29.createElement(IdentityPanel, _extends25({}, {
1814
2179
  identity,
1815
2180
  onClickManageProfile
1816
2181
  })));
@@ -1818,10 +2183,10 @@ var IdentityPopover = ({ identity, openTrigger, slots, triggerIsInToolbar = true
1818
2183
 
1819
2184
  // packages/apps/patterns/react-ui/src/composites/JoinDialog/JoinDialog.tsx
1820
2185
  import { Action, Cancel } from "@radix-ui/react-alert-dialog";
1821
- import React25 from "react";
1822
- import { ThemeContext as ThemeContext2, useId as useId4 } from "@dxos/react-components";
1823
- function _extends22() {
1824
- _extends22 = Object.assign || function(target) {
2186
+ import React30 from "react";
2187
+ import { ThemeContext as ThemeContext2, useId as useId5 } from "@dxos/react-components";
2188
+ function _extends26() {
2189
+ _extends26 = Object.assign || function(target) {
1825
2190
  for (var i = 1; i < arguments.length; i++) {
1826
2191
  var source = arguments[i];
1827
2192
  for (var key in source) {
@@ -1832,29 +2197,196 @@ function _extends22() {
1832
2197
  }
1833
2198
  return target;
1834
2199
  };
1835
- return _extends22.apply(this, arguments);
2200
+ return _extends26.apply(this, arguments);
1836
2201
  }
1837
2202
  var JoinDialog = ({ slots, ...joinPanelProps }) => {
1838
- const titleId = useId4("joinDialog__title");
1839
- return /* @__PURE__ */ React25.createElement(PanelAlertDialog, _extends22({}, {
2203
+ const titleId = useId5("joinDialog__title");
2204
+ return /* @__PURE__ */ React30.createElement(PanelAlertDialog, _extends26({}, {
1840
2205
  slots,
1841
2206
  titleId
1842
- }), /* @__PURE__ */ React25.createElement(ThemeContext2.Provider, {
2207
+ }), /* @__PURE__ */ React30.createElement(ThemeContext2.Provider, {
1843
2208
  value: {
1844
2209
  themeVariant: "os"
1845
2210
  }
1846
- }, /* @__PURE__ */ React25.createElement(JoinPanel, _extends22({}, {
2211
+ }, /* @__PURE__ */ React30.createElement(JoinPanel, _extends26({}, {
1847
2212
  ...joinPanelProps,
1848
2213
  titleId,
1849
- exitActionParent: /* @__PURE__ */ React25.createElement(Cancel, {
2214
+ exitActionParent: /* @__PURE__ */ React30.createElement(Cancel, {
1850
2215
  asChild: true
1851
2216
  }),
1852
- doneActionParent: /* @__PURE__ */ React25.createElement(Action, {
2217
+ doneActionParent: /* @__PURE__ */ React30.createElement(Action, {
1853
2218
  asChild: true
1854
2219
  })
1855
2220
  }))));
1856
2221
  };
1857
2222
 
2223
+ // packages/apps/patterns/react-ui/src/composites/Shell/Shell.tsx
2224
+ import React33, { useEffect as useEffect2, useState as useState7 } from "react";
2225
+ import { ShellDisplay, ShellLayout } from "@dxos/protocols/proto/dxos/iframe";
2226
+ import { useClient as useClient7, useSpace as useSpace3, useSpaces } from "@dxos/react-client";
2227
+
2228
+ // packages/apps/patterns/react-ui/src/composites/DevicesDialog/DevicesDialog.tsx
2229
+ import { Close } from "@radix-ui/react-dialog";
2230
+ import React31 from "react";
2231
+ import { ThemeContext as ThemeContext3, useId as useId6 } from "@dxos/react-components";
2232
+ function _extends27() {
2233
+ _extends27 = Object.assign || function(target) {
2234
+ for (var i = 1; i < arguments.length; i++) {
2235
+ var source = arguments[i];
2236
+ for (var key in source) {
2237
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
2238
+ target[key] = source[key];
2239
+ }
2240
+ }
2241
+ }
2242
+ return target;
2243
+ };
2244
+ return _extends27.apply(this, arguments);
2245
+ }
2246
+ var DevicesDialog = ({ slots, ...devicesDialogProps }) => {
2247
+ const titleId = useId6("spaceDialog__title");
2248
+ return /* @__PURE__ */ React31.createElement(PanelDialog, _extends27({}, {
2249
+ slots: {
2250
+ ...slots,
2251
+ root: {
2252
+ onOpenChange: (open) => {
2253
+ var _a;
2254
+ return open || ((_a = devicesDialogProps.onDone) == null ? void 0 : _a.call(devicesDialogProps));
2255
+ },
2256
+ ...slots == null ? void 0 : slots.root
2257
+ }
2258
+ },
2259
+ titleId
2260
+ }), /* @__PURE__ */ React31.createElement(ThemeContext3.Provider, {
2261
+ value: {
2262
+ themeVariant: "os"
2263
+ }
2264
+ }, /* @__PURE__ */ React31.createElement(DevicesPanel, _extends27({}, {
2265
+ ...devicesDialogProps,
2266
+ titleId,
2267
+ doneActionParent: /* @__PURE__ */ React31.createElement(Close, {
2268
+ asChild: true
2269
+ })
2270
+ }))));
2271
+ };
2272
+
2273
+ // packages/apps/patterns/react-ui/src/composites/SpaceDialog/SpaceDialog.tsx
2274
+ import { Close as Close2 } from "@radix-ui/react-dialog";
2275
+ import React32 from "react";
2276
+ import { ThemeContext as ThemeContext4, useId as useId7 } from "@dxos/react-components";
2277
+ function _extends28() {
2278
+ _extends28 = Object.assign || function(target) {
2279
+ for (var i = 1; i < arguments.length; i++) {
2280
+ var source = arguments[i];
2281
+ for (var key in source) {
2282
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
2283
+ target[key] = source[key];
2284
+ }
2285
+ }
2286
+ }
2287
+ return target;
2288
+ };
2289
+ return _extends28.apply(this, arguments);
2290
+ }
2291
+ var SpaceDialog = ({ slots, ...spacePanelProps }) => {
2292
+ const titleId = useId7("spaceDialog__title");
2293
+ return /* @__PURE__ */ React32.createElement(PanelDialog, _extends28({}, {
2294
+ slots: {
2295
+ ...slots,
2296
+ root: {
2297
+ onOpenChange: (open) => {
2298
+ var _a;
2299
+ return open || ((_a = spacePanelProps.onDone) == null ? void 0 : _a.call(spacePanelProps));
2300
+ },
2301
+ ...slots == null ? void 0 : slots.root
2302
+ }
2303
+ },
2304
+ titleId
2305
+ }), /* @__PURE__ */ React32.createElement(ThemeContext4.Provider, {
2306
+ value: {
2307
+ themeVariant: "os"
2308
+ }
2309
+ }, /* @__PURE__ */ React32.createElement(SpacePanel, _extends28({}, {
2310
+ ...spacePanelProps,
2311
+ titleId,
2312
+ doneActionParent: /* @__PURE__ */ React32.createElement(Close2, {
2313
+ asChild: true
2314
+ })
2315
+ }))));
2316
+ };
2317
+
2318
+ // packages/apps/patterns/react-ui/src/composites/Shell/Shell.tsx
2319
+ var Shell = ({ runtime, origin }) => {
2320
+ const [{ layout, invitationCode, spaceKey }, setLayout] = useState7({
2321
+ layout: runtime.layout,
2322
+ invitationCode: runtime.invitationCode,
2323
+ spaceKey: runtime.spaceKey
2324
+ });
2325
+ const client = useClient7();
2326
+ const spaces = useSpaces();
2327
+ const space = useSpace3(spaceKey);
2328
+ useEffect2(() => {
2329
+ return runtime.layoutUpdate.on((request) => setLayout(request));
2330
+ }, [
2331
+ runtime
2332
+ ]);
2333
+ switch (layout) {
2334
+ case ShellLayout.INITIALIZE_IDENTITY:
2335
+ return /* @__PURE__ */ React33.createElement(JoinDialog, {
2336
+ mode: "halo-only",
2337
+ initialInvitationCode: invitationCode,
2338
+ onDone: async () => {
2339
+ spaces.length > 0 || await client.echo.createSpace();
2340
+ await runtime.setAppContext({
2341
+ display: ShellDisplay.NONE
2342
+ });
2343
+ runtime.setLayout(ShellLayout.DEFAULT);
2344
+ }
2345
+ });
2346
+ case ShellLayout.DEVICE_INVITATIONS:
2347
+ return /* @__PURE__ */ React33.createElement(DevicesDialog, {
2348
+ createInvitationUrl: (invitationCode2) => `${origin}?haloInvitationCode=${invitationCode2}`,
2349
+ onDone: async () => {
2350
+ await runtime.setAppContext({
2351
+ display: ShellDisplay.NONE
2352
+ });
2353
+ runtime.setLayout(ShellLayout.DEFAULT);
2354
+ }
2355
+ });
2356
+ case ShellLayout.SPACE_INVITATIONS:
2357
+ return /* @__PURE__ */ React33.createElement(SpaceDialog, {
2358
+ space,
2359
+ createInvitationUrl: (invitationCode2) => `${origin}?spaceInvitationCode=${invitationCode2}`,
2360
+ onDone: async () => {
2361
+ await runtime.setAppContext({
2362
+ display: ShellDisplay.NONE
2363
+ });
2364
+ runtime.setLayout(ShellLayout.DEFAULT);
2365
+ }
2366
+ });
2367
+ case ShellLayout.JOIN_SPACE:
2368
+ return /* @__PURE__ */ React33.createElement(JoinDialog, {
2369
+ initialInvitationCode: invitationCode,
2370
+ onDone: async (result) => {
2371
+ var _a;
2372
+ await runtime.setAppContext({
2373
+ display: ShellDisplay.NONE,
2374
+ spaceKey: (_a = result == null ? void 0 : result.spaceKey) != null ? _a : void 0
2375
+ });
2376
+ runtime.setLayout(ShellLayout.DEFAULT);
2377
+ },
2378
+ onExit: async () => {
2379
+ await runtime.setAppContext({
2380
+ display: ShellDisplay.NONE
2381
+ });
2382
+ runtime.setLayout(ShellLayout.DEFAULT);
2383
+ }
2384
+ });
2385
+ default:
2386
+ return null;
2387
+ }
2388
+ };
2389
+
1858
2390
  // packages/apps/patterns/react-ui/src/translations/locales/en-US.ts
1859
2391
  var en_US_exports = {};
1860
2392
  __export(en_US_exports, {
@@ -1866,7 +2398,9 @@ var os = {
1866
2398
  "sidebar label": "DXOS sidebar",
1867
2399
  "copy invitation code label": "Copy",
1868
2400
  "open share panel label": "Share",
1869
- "join space heading": "<small>Joining</small><large>{{spaceTitle}}</large>",
2401
+ "joining heading": "<small>Joining</small><large>{{name}}</large>",
2402
+ "join space heading": "Join a space",
2403
+ "halo heading": "Initialize device identity",
1870
2404
  "exit label": "Exit",
1871
2405
  "identity selector title": "Join as",
1872
2406
  "identity radio group title": "Select an identity you\u2019ve associated with this device already",
@@ -1874,6 +2408,7 @@ var os = {
1874
2408
  "continue label": "Continue",
1875
2409
  "back label": "Back",
1876
2410
  "next label": "Next",
2411
+ "close label": "Close",
1877
2412
  "auth choices label": "Choose an identity",
1878
2413
  "create identity label": "Create an identity",
1879
2414
  "create identity description": "Create a new identity.",
@@ -1903,8 +2438,16 @@ var os = {
1903
2438
  "cancel label": "Cancel",
1904
2439
  "done label": "Done",
1905
2440
  "reset label": "Start over",
1906
- "pin input label": "The PIN provided by the invitation sender",
1907
- "invitation input label": "Paste an invitation code or URL"
2441
+ "auth code input label": "Auth code provided by the invitation sender",
2442
+ "invitation input label": "Paste an invitation code or URL",
2443
+ "create space invitation label": "Invite",
2444
+ "qr label": "Scan to accept invitation",
2445
+ "empty invitations message": "No pending invitations",
2446
+ "show all spaces label": "All spaces",
2447
+ "all spaces label": "All spaces",
2448
+ "create space label": "Create a new space",
2449
+ "join space label": "Join a space",
2450
+ "show current space label": "Current space"
1908
2451
  };
1909
2452
 
1910
2453
  // packages/apps/patterns/react-ui/src/translations/index.ts
@@ -1912,6 +2455,8 @@ var osTranslations = {
1912
2455
  "en-US": en_US_exports
1913
2456
  };
1914
2457
  export {
2458
+ DeviceList,
2459
+ DevicesPanel,
1915
2460
  IdentityListItem,
1916
2461
  IdentityPanel,
1917
2462
  IdentityPopover,
@@ -1922,12 +2467,17 @@ export {
1922
2467
  JoinDialog,
1923
2468
  JoinPanel,
1924
2469
  PanelAlertDialog,
2470
+ PanelDialog,
1925
2471
  PanelPopover,
1926
2472
  PanelSeparator,
1927
2473
  PanelSidebarContext,
1928
2474
  PanelSidebarProvider,
2475
+ Shell,
2476
+ SpaceDialog,
2477
+ SpaceListItem,
1929
2478
  SpaceMemberList,
1930
2479
  SpaceMemberListContainer,
2480
+ SpacePanel,
1931
2481
  activeBgColor,
1932
2482
  activeStrokeColor,
1933
2483
  activeTextColor,
@@ -1935,6 +2485,8 @@ export {
1935
2485
  cancelledStrokeColor,
1936
2486
  cancelledTextColor,
1937
2487
  defaultArrow,
2488
+ defaultDialogContent,
2489
+ defaultOverlay,
1938
2490
  defaultSurface,
1939
2491
  errorBgColor,
1940
2492
  errorStrokeColor,