@dxos/react-ui 0.1.24 → 0.1.25-next.3c6b542

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