@dxos/shell 0.3.11-main.5a4849d → 0.3.11-main.5cbcf4e

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 (138) hide show
  1. package/dist/bundle/shell.mjs +38268 -0
  2. package/dist/bundle/shell.mjs.map +1 -0
  3. package/dist/bundle/shell.umd.js +216 -0
  4. package/dist/bundle/shell.umd.js.map +1 -0
  5. package/dist/bundle/style.css +1 -0
  6. package/dist/lib/browser/meta.json +1 -1
  7. package/dist/lib/browser/react.mjs +755 -438
  8. package/dist/lib/browser/react.mjs.map +4 -4
  9. package/dist/lib/browser/testing/index.mjs +35 -14
  10. package/dist/lib/browser/testing/index.mjs.map +3 -3
  11. package/dist/types/src/components/IdentityList/DeviceList.d.ts.map +1 -1
  12. package/dist/types/src/components/IdentityList/DeviceList.js +5 -3
  13. package/dist/types/src/components/IdentityList/DeviceList.js.map +1 -1
  14. package/dist/types/src/components/IdentityList/SpaceMemberList.js +1 -1
  15. package/dist/types/src/components/IdentityList/SpaceMemberList.js.map +1 -1
  16. package/dist/types/src/components/Panel/Action.d.ts.map +1 -1
  17. package/dist/types/src/components/Panel/Action.js +3 -18
  18. package/dist/types/src/components/Panel/Action.js.map +1 -1
  19. package/dist/types/src/composites/Shell/Shell.d.ts.map +1 -1
  20. package/dist/types/src/composites/Shell/Shell.js +15 -5
  21. package/dist/types/src/composites/Shell/Shell.js.map +1 -1
  22. package/dist/types/src/panels/IdentityPanel/IdentityPanel.d.ts.map +1 -1
  23. package/dist/types/src/panels/IdentityPanel/IdentityPanel.js +24 -7
  24. package/dist/types/src/panels/IdentityPanel/IdentityPanel.js.map +1 -1
  25. package/dist/types/src/panels/IdentityPanel/IdentityPanel.stories.d.ts +6 -0
  26. package/dist/types/src/panels/IdentityPanel/IdentityPanel.stories.d.ts.map +1 -1
  27. package/dist/types/src/panels/IdentityPanel/IdentityPanel.stories.js +26 -3
  28. package/dist/types/src/panels/IdentityPanel/IdentityPanel.stories.js.map +1 -1
  29. package/dist/types/src/panels/IdentityPanel/IdentityPanelProps.d.ts +19 -8
  30. package/dist/types/src/panels/IdentityPanel/IdentityPanelProps.d.ts.map +1 -1
  31. package/dist/types/src/panels/IdentityPanel/identityMachine.d.ts +1 -1
  32. package/dist/types/src/panels/IdentityPanel/identityMachine.d.ts.map +1 -1
  33. package/dist/types/src/panels/IdentityPanel/identityMachine.js +12 -3
  34. package/dist/types/src/panels/IdentityPanel/identityMachine.js.map +1 -1
  35. package/dist/types/src/panels/IdentityPanel/steps/AgentForm.d.ts +3 -0
  36. package/dist/types/src/panels/IdentityPanel/steps/AgentForm.d.ts.map +1 -0
  37. package/dist/types/src/panels/IdentityPanel/steps/AgentForm.js +26 -0
  38. package/dist/types/src/panels/IdentityPanel/steps/AgentForm.js.map +1 -0
  39. package/dist/types/src/panels/IdentityPanel/steps/DeviceManager.d.ts +10 -0
  40. package/dist/types/src/panels/IdentityPanel/steps/DeviceManager.d.ts.map +1 -0
  41. package/dist/types/src/panels/IdentityPanel/steps/DeviceManager.js +23 -0
  42. package/dist/types/src/panels/IdentityPanel/steps/DeviceManager.js.map +1 -0
  43. package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.d.ts.map +1 -1
  44. package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.js +9 -1
  45. package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.js.map +1 -1
  46. package/dist/types/src/panels/IdentityPanel/steps/ProfileForm.d.ts +0 -1
  47. package/dist/types/src/panels/IdentityPanel/steps/ProfileForm.d.ts.map +1 -1
  48. package/dist/types/src/panels/IdentityPanel/steps/ProfileForm.js +2 -3
  49. package/dist/types/src/panels/IdentityPanel/steps/ProfileForm.js.map +1 -1
  50. package/dist/types/src/panels/IdentityPanel/steps/SignOutChooser.d.ts +16 -0
  51. package/dist/types/src/panels/IdentityPanel/steps/SignOutChooser.d.ts.map +1 -0
  52. package/dist/types/src/panels/IdentityPanel/steps/SignOutChooser.js +40 -0
  53. package/dist/types/src/panels/IdentityPanel/steps/SignOutChooser.js.map +1 -0
  54. package/dist/types/src/panels/IdentityPanel/steps/index.d.ts +3 -0
  55. package/dist/types/src/panels/IdentityPanel/steps/index.d.ts.map +1 -1
  56. package/dist/types/src/panels/IdentityPanel/steps/index.js +3 -0
  57. package/dist/types/src/panels/IdentityPanel/steps/index.js.map +1 -1
  58. package/dist/types/src/panels/IdentityPanel/useAgentHandlers.d.ts +15 -0
  59. package/dist/types/src/panels/IdentityPanel/useAgentHandlers.d.ts.map +1 -0
  60. package/dist/types/src/panels/IdentityPanel/useAgentHandlers.js +78 -0
  61. package/dist/types/src/panels/IdentityPanel/useAgentHandlers.js.map +1 -0
  62. package/dist/types/src/panels/JoinPanel/JoinPanel.js +4 -3
  63. package/dist/types/src/panels/JoinPanel/JoinPanel.js.map +1 -1
  64. package/dist/types/src/panels/JoinPanel/joinMachine.d.ts +1 -1
  65. package/dist/types/src/panels/JoinPanel/joinMachine.d.ts.map +1 -1
  66. package/dist/types/src/panels/JoinPanel/joinMachine.js +15 -18
  67. package/dist/types/src/panels/JoinPanel/joinMachine.js.map +1 -1
  68. package/dist/types/src/panels/JoinPanel/steps/AdditionMethodChooser.js +3 -3
  69. package/dist/types/src/panels/JoinPanel/steps/AdditionMethodChooser.js.map +1 -1
  70. package/dist/types/src/panels/JoinPanel/steps/InvitationInput.d.ts.map +1 -1
  71. package/dist/types/src/panels/JoinPanel/steps/InvitationInput.js +13 -6
  72. package/dist/types/src/panels/JoinPanel/steps/InvitationInput.js.map +1 -1
  73. package/dist/types/src/panels/JoinPanel/steps/InvitationRescuer.js.map +1 -1
  74. package/dist/types/src/panels/JoinPanel/steps/ResetIdentity.js +1 -1
  75. package/dist/types/src/panels/JoinPanel/steps/ResetIdentity.js.map +1 -1
  76. package/dist/types/src/panels/Panels.stories.d.ts.map +1 -1
  77. package/dist/types/src/panels/Panels.stories.js +1 -3
  78. package/dist/types/src/panels/Panels.stories.js.map +1 -1
  79. package/dist/types/src/panels/SpacePanel/SpacePanel.d.ts.map +1 -1
  80. package/dist/types/src/panels/SpacePanel/SpacePanel.js +5 -3
  81. package/dist/types/src/panels/SpacePanel/SpacePanel.js.map +1 -1
  82. package/dist/types/src/panels/SpacePanel/SpacePanel.stories.d.ts.map +1 -1
  83. package/dist/types/src/panels/SpacePanel/SpacePanel.stories.js +2 -2
  84. package/dist/types/src/panels/SpacePanel/SpacePanel.stories.js.map +1 -1
  85. package/dist/types/src/panels/SpacePanel/SpacePanelProps.d.ts +1 -0
  86. package/dist/types/src/panels/SpacePanel/SpacePanelProps.d.ts.map +1 -1
  87. package/dist/types/src/panels/SpacePanel/steps/SpaceManager.d.ts +1 -0
  88. package/dist/types/src/panels/SpacePanel/steps/SpaceManager.d.ts.map +1 -1
  89. package/dist/types/src/panels/SpacePanel/steps/SpaceManager.js +3 -1
  90. package/dist/types/src/panels/SpacePanel/steps/SpaceManager.js.map +1 -1
  91. package/dist/types/src/playwright/invitations-manager.d.ts +1 -0
  92. package/dist/types/src/playwright/invitations-manager.d.ts.map +1 -1
  93. package/dist/types/src/playwright/invitations-manager.js +4 -1
  94. package/dist/types/src/playwright/invitations-manager.js.map +1 -1
  95. package/dist/types/src/playwright/invitations.spec.js +15 -0
  96. package/dist/types/src/playwright/invitations.spec.js.map +1 -1
  97. package/dist/types/src/styles/invitationStatusStyles.d.ts.map +1 -1
  98. package/dist/types/src/styles/invitationStatusStyles.js.map +1 -1
  99. package/dist/types/src/testing/shell-manager.d.ts +5 -4
  100. package/dist/types/src/testing/shell-manager.d.ts.map +1 -1
  101. package/dist/types/src/testing/shell-manager.js +36 -12
  102. package/dist/types/src/testing/shell-manager.js.map +1 -1
  103. package/dist/types/src/translations/locales/en-US.d.ts +6 -0
  104. package/dist/types/src/translations/locales/en-US.d.ts.map +1 -1
  105. package/dist/types/src/translations/locales/en-US.js +7 -1
  106. package/dist/types/src/translations/locales/en-US.js.map +1 -1
  107. package/package.json +22 -21
  108. package/src/components/IdentityList/DeviceList.tsx +7 -5
  109. package/src/components/IdentityList/SpaceMemberList.tsx +1 -1
  110. package/src/components/Panel/Action.tsx +4 -19
  111. package/src/composites/Shell/Shell.tsx +16 -3
  112. package/src/panels/IdentityPanel/IdentityPanel.stories.tsx +44 -2
  113. package/src/panels/IdentityPanel/IdentityPanel.tsx +35 -8
  114. package/src/panels/IdentityPanel/IdentityPanelProps.ts +27 -8
  115. package/src/panels/IdentityPanel/identityMachine.ts +13 -4
  116. package/src/panels/IdentityPanel/steps/AgentForm.tsx +61 -0
  117. package/src/panels/IdentityPanel/steps/DeviceManager.tsx +41 -0
  118. package/src/panels/IdentityPanel/steps/IdentityActionChooser.tsx +13 -4
  119. package/src/panels/IdentityPanel/steps/ProfileForm.tsx +1 -1
  120. package/src/panels/IdentityPanel/steps/SignOutChooser.tsx +84 -0
  121. package/src/panels/IdentityPanel/steps/index.ts +3 -0
  122. package/src/panels/IdentityPanel/useAgentHandlers.ts +88 -0
  123. package/src/panels/JoinPanel/JoinPanel.tsx +2 -2
  124. package/src/panels/JoinPanel/joinMachine.ts +16 -19
  125. package/src/panels/JoinPanel/steps/AdditionMethodChooser.tsx +3 -3
  126. package/src/panels/JoinPanel/steps/InvitationInput.tsx +7 -1
  127. package/src/panels/JoinPanel/steps/InvitationRescuer.tsx +2 -2
  128. package/src/panels/JoinPanel/steps/ResetIdentity.tsx +1 -1
  129. package/src/panels/Panels.stories.tsx +2 -2
  130. package/src/panels/SpacePanel/SpacePanel.stories.tsx +2 -1
  131. package/src/panels/SpacePanel/SpacePanel.tsx +4 -1
  132. package/src/panels/SpacePanel/SpacePanelProps.ts +1 -0
  133. package/src/panels/SpacePanel/steps/SpaceManager.tsx +4 -1
  134. package/src/playwright/invitations-manager.ts +5 -1
  135. package/src/playwright/invitations.spec.ts +19 -0
  136. package/src/styles/invitationStatusStyles.ts +6 -6
  137. package/src/testing/shell-manager.ts +40 -13
  138. package/src/translations/locales/en-US.ts +7 -1
@@ -182,9 +182,9 @@ var DeviceList = ({ devices, onSelect }) => {
182
182
  }, devices.map((device) => {
183
183
  const identity = {
184
184
  identityKey: device.deviceKey,
185
- profile: {
185
+ profile: device.profile ? {
186
186
  displayName: `${device.profile?.platform} (${device.profile?.platformVersion}) on ${device.profile?.os} (${device.profile?.osVersion}) ${device.profile?.architecture ?? "Unknown"}-bit`
187
- }
187
+ } : void 0
188
188
  };
189
189
  return /* @__PURE__ */ React5.createElement(IdentityListItem, {
190
190
  key: device.deviceKey.toHex(),
@@ -220,7 +220,8 @@ var SpaceMemberListImpl = ({ members, onSelect }) => {
220
220
  const { t } = useTranslation3("os");
221
221
  const visibleMembers = members.filter((member) => member.identity);
222
222
  return visibleMembers.length > 0 ? /* @__PURE__ */ React6.createElement(List2, {
223
- classNames: "flex flex-col gap-2"
223
+ classNames: "flex flex-col gap-2",
224
+ "data-testid": "space-members-list"
224
225
  }, visibleMembers.map((member) => {
225
226
  return /* @__PURE__ */ React6.createElement(IdentityListItem, {
226
227
  key: member.identity.identityKey.toHex(),
@@ -521,12 +522,6 @@ import { useControllableState } from "@radix-ui/react-use-controllable-state";
521
522
  import React11, { forwardRef as forwardRef2 } from "react";
522
523
  import { Button as Button3, DropdownMenu, useTranslation as useTranslation5 } from "@dxos/react-ui";
523
524
  import { descriptionText as descriptionText4, getSize as getSize3, mx as mx9 } from "@dxos/react-ui-theme";
524
- var buttonColorFragment = (props) => {
525
- const resolvedVariant = props.variant ?? "default";
526
- return [
527
- !props.disabled ? resolvedVariant === "default" ? "bg-neutral-25 hover:bg-white hover:text-primary-500 active:bg-neutral-25 dark:active:bg-neutral-800" : resolvedVariant === "ghost" ? "active:bg-neutral-125 dark:active:bg-neutral-800" : resolvedVariant === "primary" ? "active:bg-primary-700 dark:active:bg-primary-500" : "" : ""
528
- ];
529
- };
530
525
  var defaultActions = {
531
526
  noopAction: {
532
527
  label: "No-op",
@@ -552,8 +547,7 @@ var BifurcatedAction = /* @__PURE__ */ forwardRef2((props, forwardedRef) => {
552
547
  ...rest,
553
548
  classNames: [
554
549
  "bs-11 flex-1 min-is-0 flex gap-2 rounded-ie-none",
555
- classNames,
556
- ...buttonColorFragment(props)
550
+ classNames
557
551
  ],
558
552
  ref: forwardedRef,
559
553
  variant,
@@ -563,8 +557,7 @@ var BifurcatedAction = /* @__PURE__ */ forwardRef2((props, forwardedRef) => {
563
557
  }, /* @__PURE__ */ React11.createElement(Button3, {
564
558
  classNames: [
565
559
  "bs-11 flex-none rounded-is-none",
566
- classNames,
567
- ...buttonColorFragment(props)
560
+ classNames
568
561
  ]
569
562
  }, /* @__PURE__ */ React11.createElement("span", {
570
563
  className: "sr-only"
@@ -598,8 +591,7 @@ var Action = /* @__PURE__ */ forwardRef2((props, forwardedRef) => {
598
591
  classNames: [
599
592
  isFull && "is-full",
600
593
  "bs-11 flex gap-2 mbs-2",
601
- classNames,
602
- ...buttonColorFragment(props)
594
+ classNames
603
595
  ],
604
596
  ref: forwardedRef,
605
597
  variant
@@ -813,17 +805,17 @@ var SpaceListItem = /* @__PURE__ */ forwardRef7(({ space, onClick }, ref) => {
813
805
  });
814
806
 
815
807
  // packages/sdk/shell/src/composites/IdentityDialog/IdentityDialog.tsx
816
- import React37 from "react";
808
+ import React40 from "react";
817
809
  import { Dialog, useId as useId9 } from "@dxos/react-ui";
818
810
 
819
811
  // packages/sdk/shell/src/panels/IdentityPanel/IdentityPanel.tsx
820
- import React24, { useEffect as useEffect2, useMemo as useMemo3 } from "react";
812
+ import React27, { useEffect as useEffect3, useMemo as useMemo3 } from "react";
821
813
  import { generateName as generateName2 } from "@dxos/display-name";
822
814
  import { log as log3 } from "@dxos/log";
823
815
  import { useClient as useClient3 } from "@dxos/react-client";
824
- import { useIdentity } from "@dxos/react-client/halo";
816
+ import { useIdentity, useDevices, useHaloInvitations as useHaloInvitations2 } from "@dxos/react-client/halo";
825
817
  import { useInvitationStatus as useInvitationStatus2 } from "@dxos/react-client/invitations";
826
- import { Avatar as Avatar4, DensityProvider as DensityProvider2, useId as useId5, useJdenticonHref as useJdenticonHref3, useTranslation as useTranslation10 } from "@dxos/react-ui";
818
+ import { Avatar as Avatar4, DensityProvider as DensityProvider2, useId as useId5, useJdenticonHref as useJdenticonHref3, useTranslation as useTranslation13 } from "@dxos/react-ui";
827
819
 
828
820
  // packages/sdk/shell/src/panels/IdentityPanel/identityMachine.ts
829
821
  import { useMachine } from "@xstate/react";
@@ -844,6 +836,14 @@ var identityMachine = createMachine({
844
836
  states: {
845
837
  choosingAction: {},
846
838
  managingDeviceInvitation: {},
839
+ managingAgent: {
840
+ initial: "idle",
841
+ states: {
842
+ idle: {},
843
+ pending: {}
844
+ }
845
+ },
846
+ managingDevices: {},
847
847
  managingProfile: {
848
848
  initial: "idle",
849
849
  states: {
@@ -863,7 +863,8 @@ var identityMachine = createMachine({
863
863
  actions: "log"
864
864
  }
865
865
  }
866
- }
866
+ },
867
+ signingOut: {}
867
868
  },
868
869
  on: {
869
870
  unchooseAction: {
@@ -873,13 +874,6 @@ var identityMachine = createMachine({
873
874
  "log"
874
875
  ]
875
876
  },
876
- chooseDevices: {
877
- target: ".managingDeviceInvitation",
878
- actions: [
879
- "unsetInvitation",
880
- "log"
881
- ]
882
- },
883
877
  deselectInvitation: {
884
878
  target: ".choosingAction",
885
879
  actions: [
@@ -894,9 +888,21 @@ var identityMachine = createMachine({
894
888
  "log"
895
889
  ]
896
890
  },
891
+ chooseDevices: {
892
+ target: ".managingDevices",
893
+ actions: "log"
894
+ },
897
895
  chooseProfile: {
898
896
  target: ".managingProfile",
899
897
  actions: "log"
898
+ },
899
+ chooseSignOut: {
900
+ target: ".signingOut",
901
+ actions: "log"
902
+ },
903
+ chooseAgent: {
904
+ target: ".managingAgent",
905
+ actions: "log"
900
906
  }
901
907
  }
902
908
  }, {
@@ -916,7 +922,7 @@ var identityMachine = createMachine({
916
922
  context
917
923
  }, {
918
924
  F: __dxlog_file,
919
- L: 95,
925
+ L: 104,
920
926
  S: void 0,
921
927
  C: (f, a) => f(...a)
922
928
  });
@@ -937,13 +943,67 @@ var useIdentityMachine = (client, options) => {
937
943
  });
938
944
  };
939
945
 
946
+ // packages/sdk/shell/src/panels/IdentityPanel/steps/AgentForm.tsx
947
+ import React21 from "react";
948
+ import { useTranslation as useTranslation7 } from "@dxos/react-ui";
949
+ var AgentForm = (props) => {
950
+ const { active, onAgentCreate, onAgentDestroy, send, validationMessage, agentStatus, agentActive, agentProviderDisabled } = props;
951
+ const disabled = !active;
952
+ const { t } = useTranslation7("os");
953
+ return /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement("div", {
954
+ role: "none",
955
+ className: "grow flex flex-col justify-center"
956
+ }, /* @__PURE__ */ React21.createElement(Input, {
957
+ validationMessage,
958
+ label: /* @__PURE__ */ React21.createElement(StepHeading, null, "Agent Status"),
959
+ disabled,
960
+ "data-testid": "agent-status",
961
+ value: agentStatus
962
+ })), /* @__PURE__ */ React21.createElement(Actions, null, /* @__PURE__ */ React21.createElement(Action, {
963
+ disabled: agentActive || agentProviderDisabled,
964
+ onClick: () => onAgentCreate?.(),
965
+ "data-testid": "create-agent"
966
+ }, "Create Agent"), /* @__PURE__ */ React21.createElement(Action, {
967
+ disabled: !agentActive || agentProviderDisabled,
968
+ onClick: () => onAgentDestroy?.(),
969
+ "data-testid": "destroy-agent"
970
+ }, "Destroy Agent"), /* @__PURE__ */ React21.createElement(Action, {
971
+ disabled,
972
+ onClick: () => send?.({
973
+ type: "unchooseAction"
974
+ }),
975
+ "data-testid": "update-profile-form-back"
976
+ }, t("back label"))));
977
+ };
978
+
979
+ // packages/sdk/shell/src/panels/IdentityPanel/steps/DeviceManager.tsx
980
+ import React22 from "react";
981
+ import { useTranslation as useTranslation8 } from "@dxos/react-ui";
982
+ var DeviceManager = ({ devices, active, send }) => {
983
+ const { t } = useTranslation8("os");
984
+ const disabled = !active;
985
+ return /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement("div", {
986
+ role: "none",
987
+ className: "grow"
988
+ }, /* @__PURE__ */ React22.createElement(DeviceList, {
989
+ devices
990
+ })), /* @__PURE__ */ React22.createElement(Actions, null, /* @__PURE__ */ React22.createElement(Action, {
991
+ variant: "ghost",
992
+ disabled,
993
+ onClick: () => send?.({
994
+ type: "unchooseAction"
995
+ }),
996
+ "data-testid": "manage-devices-back"
997
+ }, t("back label"))));
998
+ };
999
+
940
1000
  // packages/sdk/shell/src/panels/IdentityPanel/steps/IdentityActionChooser.tsx
941
- import { CaretRight, Plus, Power, UserGear } from "@phosphor-icons/react";
942
- import React21, { useCallback as useCallback4 } from "react";
1001
+ import { CaretRight, Devices, Plus, Power, UserGear, HardDrive } from "@phosphor-icons/react";
1002
+ import React23, { useCallback as useCallback4 } from "react";
943
1003
  import { useClient as useClient2 } from "@dxos/react-client";
944
1004
  import { useHaloInvitations } from "@dxos/react-client/halo";
945
1005
  import { Invitation as Invitation3, InvitationEncoder } from "@dxos/react-client/invitations";
946
- import { DensityProvider, useTranslation as useTranslation7 } from "@dxos/react-ui";
1006
+ import { DensityProvider, useTranslation as useTranslation9 } from "@dxos/react-ui";
947
1007
  import { getSize as getSize6 } from "@dxos/react-ui-theme";
948
1008
  var IdentityActionChooser = (props) => {
949
1009
  const { send } = props;
@@ -973,69 +1033,95 @@ var IdentityActionChooser = (props) => {
973
1033
  invitation
974
1034
  });
975
1035
  };
976
- return /* @__PURE__ */ React21.createElement(IdentityActionChooserImpl, {
1036
+ return /* @__PURE__ */ React23.createElement(IdentityActionChooserImpl, {
977
1037
  ...props,
978
1038
  onCreateInvitationClick: (e) => createInvitation(e)
979
1039
  });
980
1040
  };
981
1041
  var IdentityActionChooserImpl = ({ onCreateInvitationClick, active, send, onDone, doneActionParent }) => {
982
- const { t } = useTranslation7("os");
983
- return /* @__PURE__ */ React21.createElement("div", {
1042
+ const { t } = useTranslation9("os");
1043
+ return /* @__PURE__ */ React23.createElement("div", {
984
1044
  role: "none",
985
1045
  className: "grow flex flex-col gap-1"
986
- }, /* @__PURE__ */ React21.createElement(DensityProvider, {
1046
+ }, /* @__PURE__ */ React23.createElement(DensityProvider, {
987
1047
  density: "coarse"
988
- }, /* @__PURE__ */ React21.createElement("div", {
1048
+ }, /* @__PURE__ */ React23.createElement("div", {
989
1049
  className: "grow justify-center flex flex-col gap-1"
990
- }, /* @__PURE__ */ React21.createElement(Action, {
1050
+ }, /* @__PURE__ */ React23.createElement(Action, {
1051
+ "data-testid": "manage-agent",
1052
+ onClick: () => send?.({
1053
+ type: "chooseAgent"
1054
+ }),
1055
+ classNames: "plb-4"
1056
+ }, /* @__PURE__ */ React23.createElement(HardDrive, {
1057
+ className: getSize6(6)
1058
+ }), /* @__PURE__ */ React23.createElement("span", {
1059
+ className: "grow mli-3"
1060
+ }, "Manage Agent"), /* @__PURE__ */ React23.createElement(CaretRight, {
1061
+ weight: "bold",
1062
+ className: getSize6(4)
1063
+ })), /* @__PURE__ */ React23.createElement(Action, {
991
1064
  disabled: !active,
992
1065
  "data-testid": "devices-panel.create-invitation",
993
1066
  onClick: onCreateInvitationClick,
994
1067
  classNames: "plb-4"
995
- }, /* @__PURE__ */ React21.createElement(Plus, {
1068
+ }, /* @__PURE__ */ React23.createElement(Plus, {
1069
+ className: getSize6(6)
1070
+ }), /* @__PURE__ */ React23.createElement("span", {
1071
+ className: "grow mli-3"
1072
+ }, t("choose add device label")), /* @__PURE__ */ React23.createElement(CaretRight, {
1073
+ weight: "bold",
1074
+ className: getSize6(4)
1075
+ })), /* @__PURE__ */ React23.createElement(Action, {
1076
+ "data-testid": "manage-devices",
1077
+ onClick: () => send?.({
1078
+ type: "chooseDevices"
1079
+ }),
1080
+ classNames: "plb-4"
1081
+ }, /* @__PURE__ */ React23.createElement(Devices, {
996
1082
  className: getSize6(6)
997
- }), /* @__PURE__ */ React21.createElement("span", {
1083
+ }), /* @__PURE__ */ React23.createElement("span", {
998
1084
  className: "grow mli-3"
999
- }, t("choose devices label")), /* @__PURE__ */ React21.createElement(CaretRight, {
1085
+ }, t("choose devices label")), /* @__PURE__ */ React23.createElement(CaretRight, {
1000
1086
  weight: "bold",
1001
1087
  className: getSize6(4)
1002
- })), /* @__PURE__ */ React21.createElement(Action, {
1088
+ })), /* @__PURE__ */ React23.createElement(Action, {
1003
1089
  "data-testid": "manage-profile",
1004
1090
  onClick: () => send?.({
1005
1091
  type: "chooseProfile"
1006
1092
  }),
1007
1093
  classNames: "plb-4"
1008
- }, /* @__PURE__ */ React21.createElement(UserGear, {
1094
+ }, /* @__PURE__ */ React23.createElement(UserGear, {
1009
1095
  className: getSize6(6)
1010
- }), /* @__PURE__ */ React21.createElement("span", {
1096
+ }), /* @__PURE__ */ React23.createElement("span", {
1011
1097
  className: "grow mli-3"
1012
- }, t("choose profile label")), /* @__PURE__ */ React21.createElement(CaretRight, {
1098
+ }, t("choose profile label")), /* @__PURE__ */ React23.createElement(CaretRight, {
1013
1099
  weight: "bold",
1014
1100
  className: getSize6(4)
1015
- })), /* @__PURE__ */ React21.createElement(Action, {
1016
- disabled: true,
1017
- "data-testid": "sign-out",
1018
- onClick: () => {
1019
- },
1101
+ })), /* @__PURE__ */ React23.createElement(Action, {
1102
+ "data-testid": "devices-panel.sign-out",
1103
+ onClick: () => send?.({
1104
+ type: "chooseSignOut"
1105
+ }),
1020
1106
  classNames: "plb-4"
1021
- }, /* @__PURE__ */ React21.createElement(Power, {
1107
+ }, /* @__PURE__ */ React23.createElement(Power, {
1022
1108
  className: getSize6(6)
1023
- }), /* @__PURE__ */ React21.createElement("span", {
1109
+ }), /* @__PURE__ */ React23.createElement("span", {
1024
1110
  className: "grow mli-3"
1025
- }, t("choose sign out label")), /* @__PURE__ */ React21.createElement(CaretRight, {
1111
+ }, t("choose sign out label")), /* @__PURE__ */ React23.createElement(CaretRight, {
1026
1112
  weight: "bold",
1027
1113
  className: getSize6(4)
1028
1114
  })))));
1029
1115
  };
1030
1116
 
1031
1117
  // packages/sdk/shell/src/panels/IdentityPanel/steps/ProfileForm.tsx
1032
- import React22, { useState as useState3 } from "react";
1118
+ import React24, { useState as useState3 } from "react";
1033
1119
  import { log as log2 } from "@dxos/log";
1034
- import { useTranslation as useTranslation8 } from "@dxos/react-ui";
1120
+ import { useTranslation as useTranslation10 } from "@dxos/react-ui";
1035
1121
  var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/IdentityPanel/steps/ProfileForm.tsx";
1036
1122
  var ProfileForm = (props) => {
1037
1123
  const { onUpdateProfile } = props;
1038
- const { t } = useTranslation8("os");
1124
+ const { t } = useTranslation10("os");
1039
1125
  const [validationMessage, setValidationMessage] = useState3("");
1040
1126
  const handleUpdateProfile = async (profile) => {
1041
1127
  await onUpdateProfile?.(profile).catch((error) => {
@@ -1048,7 +1134,7 @@ var ProfileForm = (props) => {
1048
1134
  setValidationMessage(t("failed to update profile message"));
1049
1135
  });
1050
1136
  };
1051
- return /* @__PURE__ */ React22.createElement(ProfileFormImpl, {
1137
+ return /* @__PURE__ */ React24.createElement(ProfileFormImpl, {
1052
1138
  ...props,
1053
1139
  onUpdateProfile: handleUpdateProfile,
1054
1140
  validationMessage
@@ -1057,14 +1143,14 @@ var ProfileForm = (props) => {
1057
1143
  var ProfileFormImpl = (props) => {
1058
1144
  const { active, profile, send, onUpdateProfile, validationMessage } = props;
1059
1145
  const disabled = !active;
1060
- const { t } = useTranslation8("os");
1146
+ const { t } = useTranslation10("os");
1061
1147
  const [inputValue, setInputValue] = useState3(profile?.displayName ?? "");
1062
- return /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement("div", {
1148
+ return /* @__PURE__ */ React24.createElement(React24.Fragment, null, /* @__PURE__ */ React24.createElement("div", {
1063
1149
  role: "none",
1064
1150
  className: "grow flex flex-col justify-center"
1065
- }, /* @__PURE__ */ React22.createElement(Input, {
1151
+ }, /* @__PURE__ */ React24.createElement(Input, {
1066
1152
  validationMessage,
1067
- label: /* @__PURE__ */ React22.createElement(StepHeading, null, t("display name input label")),
1153
+ label: /* @__PURE__ */ React24.createElement(StepHeading, null, t("display name input label")),
1068
1154
  disabled,
1069
1155
  "data-testid": "display-name-input",
1070
1156
  placeholder: t("display name input placeholder"),
@@ -1073,14 +1159,14 @@ var ProfileFormImpl = (props) => {
1073
1159
  onKeyDown: ({ key }) => key === "Enter" && onUpdateProfile?.({
1074
1160
  displayName: inputValue
1075
1161
  })
1076
- })), /* @__PURE__ */ React22.createElement(Actions, null, /* @__PURE__ */ React22.createElement(Action, {
1162
+ })), /* @__PURE__ */ React24.createElement(Actions, null, /* @__PURE__ */ React24.createElement(Action, {
1077
1163
  variant: "ghost",
1078
1164
  disabled,
1079
1165
  onClick: () => send?.({
1080
1166
  type: "unchooseAction"
1081
1167
  }),
1082
1168
  "data-testid": "update-profile-form-back"
1083
- }, t("back label")), /* @__PURE__ */ React22.createElement(Action, {
1169
+ }, t("back label")), /* @__PURE__ */ React24.createElement(Action, {
1084
1170
  variant: "primary",
1085
1171
  disabled,
1086
1172
  onClick: () => onUpdateProfile?.({
@@ -1090,23 +1176,164 @@ var ProfileFormImpl = (props) => {
1090
1176
  }, t("done label"))));
1091
1177
  };
1092
1178
 
1179
+ // packages/sdk/shell/src/panels/IdentityPanel/steps/SignOutChooser.tsx
1180
+ import { Warning } from "@phosphor-icons/react";
1181
+ import React25 from "react";
1182
+ import { Message, useTranslation as useTranslation11 } from "@dxos/react-ui";
1183
+ import { getSize as getSize7, mx as mx18 } from "@dxos/react-ui-theme";
1184
+ var SignOutChooser = (props) => {
1185
+ const { t } = useTranslation11("os");
1186
+ const onResetDevice = () => {
1187
+ if (window.confirm(t("reset device confirm message"))) {
1188
+ void props.onResetDevice?.();
1189
+ }
1190
+ };
1191
+ return /* @__PURE__ */ React25.createElement(SignOutChooserImpl, {
1192
+ disabled: !props.active,
1193
+ onBack: () => props.send?.({
1194
+ type: "unchooseAction"
1195
+ }),
1196
+ onResetDevice,
1197
+ onJoinNewIdentity: props.onJoinNewIdentity
1198
+ });
1199
+ };
1200
+ var SignOutChooserImpl = ({ disabled, onResetDevice, onJoinNewIdentity, onBack }) => {
1201
+ const { t } = useTranslation11("os");
1202
+ return /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement("div", {
1203
+ role: "none",
1204
+ className: "grow flex flex-col justify-center"
1205
+ }, /* @__PURE__ */ React25.createElement(Message.Root, {
1206
+ valence: "error"
1207
+ }, /* @__PURE__ */ React25.createElement(Message.Title, null, /* @__PURE__ */ React25.createElement(Warning, {
1208
+ className: mx18(getSize7(6), "inline mie-2")
1209
+ }), t("sign out chooser title")), /* @__PURE__ */ React25.createElement(Message.Body, null, t("sign out chooser message")))), /* @__PURE__ */ React25.createElement(Actions, null, /* @__PURE__ */ React25.createElement(Action, {
1210
+ disabled,
1211
+ onClick: onBack
1212
+ }, t("back label")), /* @__PURE__ */ React25.createElement(Action, {
1213
+ variant: "primary",
1214
+ "data-testid": "sign-out.join-new-identity",
1215
+ classNames: "!bg-error-500 hover:!bg-error-550",
1216
+ disabled,
1217
+ onClick: onJoinNewIdentity
1218
+ }, t("join new identity label")), /* @__PURE__ */ React25.createElement(Action, {
1219
+ variant: "primary",
1220
+ "data-testid": "sign-out.reset-device",
1221
+ classNames: "!bg-error-500 hover:!bg-error-550",
1222
+ disabled,
1223
+ onClick: onResetDevice
1224
+ }, t("reset device label"))));
1225
+ };
1226
+
1227
+ // packages/sdk/shell/src/panels/IdentityPanel/useAgentHandlers.ts
1228
+ import { useCallback as useCallback5, useEffect as useEffect2, useState as useState4 } from "react";
1229
+ import { invariant } from "@dxos/invariant";
1230
+ import { useAgentHostingProviderClient } from "@dxos/react-client";
1231
+ import { Invitation as Invitation4, InvitationEncoder as InvitationEncoder2 } from "@dxos/react-client/invitations";
1232
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/IdentityPanel/useAgentHandlers.ts";
1233
+ var useAgentHandlers = ({ client, invitations, identity }) => {
1234
+ const [validationMessage, setValidationMessage] = useState4("");
1235
+ const [agentStatus, setAgentStatus] = useState4("");
1236
+ const [agentActive, setAgentActive] = useState4(false);
1237
+ const agentHostingProviderClient = useAgentHostingProviderClient(client.config);
1238
+ useEffect2(() => {
1239
+ const fetchAgentStatus = async () => {
1240
+ if (agentHostingProviderClient) {
1241
+ const agentStatus2 = await agentHostingProviderClient?.getAgent(identity?.identityKey.truncate() ?? "foo");
1242
+ if (agentStatus2) {
1243
+ setAgentActive(true);
1244
+ setAgentStatus(agentStatus2);
1245
+ } else {
1246
+ setAgentActive(false);
1247
+ setValidationMessage("No agent deployed via provider.");
1248
+ }
1249
+ } else {
1250
+ setValidationMessage("No agent provider configured.");
1251
+ }
1252
+ };
1253
+ void fetchAgentStatus();
1254
+ }, []);
1255
+ const handleAgentCreate = useCallback5(async (invitation) => {
1256
+ const invitationCode = InvitationEncoder2.encode(invitation);
1257
+ if (invitation.state === Invitation4.State.CONNECTING) {
1258
+ console.log(JSON.stringify({
1259
+ invitationCode,
1260
+ authCode: invitation.authCode
1261
+ }));
1262
+ invariant(identity, "Identity not found", {
1263
+ F: __dxlog_file3,
1264
+ L: 50,
1265
+ S: void 0,
1266
+ A: [
1267
+ "identity",
1268
+ "'Identity not found'"
1269
+ ]
1270
+ });
1271
+ if (agentHostingProviderClient) {
1272
+ try {
1273
+ const res = await agentHostingProviderClient?.createAgent(invitationCode, identity.identityKey.truncate());
1274
+ setAgentStatus(res);
1275
+ setAgentActive(true);
1276
+ setValidationMessage("");
1277
+ } catch (err) {
1278
+ setValidationMessage(`error creating agent: ${err.message}`);
1279
+ }
1280
+ }
1281
+ }
1282
+ }, []);
1283
+ const onAgentCreate = async () => {
1284
+ invitations.forEach((invitation2) => invitation2.cancel());
1285
+ const invitation = client.halo.share({
1286
+ type: Invitation4.Type.MULTIUSE,
1287
+ authMethod: Invitation4.AuthMethod.NONE
1288
+ });
1289
+ invitation.subscribe(handleAgentCreate);
1290
+ };
1291
+ const onAgentDestroy = async () => {
1292
+ const identity2 = client.halo.identity.get();
1293
+ invariant(identity2, "Identity not found", {
1294
+ F: __dxlog_file3,
1295
+ L: 76,
1296
+ S: void 0,
1297
+ A: [
1298
+ "identity",
1299
+ "'Identity not found'"
1300
+ ]
1301
+ });
1302
+ try {
1303
+ await agentHostingProviderClient?.destroyAgent(identity2.identityKey.truncate());
1304
+ setValidationMessage("No agent deployed via provider.");
1305
+ setAgentStatus("");
1306
+ setAgentActive(false);
1307
+ } catch (err) {
1308
+ setValidationMessage(`error destroying agent: ${err.message}`);
1309
+ }
1310
+ };
1311
+ return {
1312
+ onAgentCreate,
1313
+ onAgentDestroy,
1314
+ validationMessage,
1315
+ agentStatus,
1316
+ agentActive
1317
+ };
1318
+ };
1319
+
1093
1320
  // packages/sdk/shell/src/steps/InvitationManager.tsx
1094
1321
  import { Check as Check3, X as X3 } from "@phosphor-icons/react";
1095
- import React23, { useMemo as useMemo2 } from "react";
1322
+ import React26, { useMemo as useMemo2 } from "react";
1096
1323
  import { QR } from "react-qr-rounded";
1097
- import { Invitation as Invitation4 } from "@dxos/react-client/invitations";
1098
- import { useId as useId4, useTranslation as useTranslation9 } from "@dxos/react-ui";
1099
- import { descriptionText as descriptionText7, getSize as getSize7, mx as mx18 } from "@dxos/react-ui-theme";
1324
+ import { Invitation as Invitation5 } from "@dxos/react-client/invitations";
1325
+ import { useId as useId4, useTranslation as useTranslation12 } from "@dxos/react-ui";
1326
+ import { descriptionText as descriptionText7, getSize as getSize8, mx as mx19 } from "@dxos/react-ui-theme";
1100
1327
  var InvitationManagerView = ({ children, ...props }) => {
1101
- return /* @__PURE__ */ React23.createElement(Viewport.View, {
1328
+ return /* @__PURE__ */ React26.createElement(Viewport.View, {
1102
1329
  ...props,
1103
1330
  classNames: "grow flex flex-col justify-around items-center"
1104
1331
  }, children);
1105
1332
  };
1106
1333
  var InvitationManager = ({ invitationUrl, active, send, status, type, authCode, id }) => {
1107
- const { t } = useTranslation9("os");
1334
+ const { t } = useTranslation12("os");
1108
1335
  const qrLabel = useId4("invitation-manager__qr-code");
1109
- const statusValue = type === Invitation4.Type.MULTIUSE ? 0 : invitationStatusValue.get(status) ?? 0;
1336
+ const statusValue = type === Invitation5.Type.MULTIUSE ? 0 : invitationStatusValue.get(status) ?? 0;
1110
1337
  const showAuthCode = statusValue === 3;
1111
1338
  const emoji2 = toEmoji(id ?? "");
1112
1339
  const activeView = useMemo2(() => {
@@ -1122,50 +1349,50 @@ var InvitationManager = ({ invitationUrl, active, send, status, type, authCode,
1122
1349
  }, [
1123
1350
  statusValue
1124
1351
  ]);
1125
- return /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(Viewport.Root, {
1352
+ return /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(Viewport.Root, {
1126
1353
  activeView,
1127
1354
  classNames: "grow plb-1"
1128
- }, /* @__PURE__ */ React23.createElement(Viewport.Views, null, /* @__PURE__ */ React23.createElement(InvitationManagerView, {
1355
+ }, /* @__PURE__ */ React26.createElement(Viewport.Views, null, /* @__PURE__ */ React26.createElement(InvitationManagerView, {
1129
1356
  id: "showing qr",
1130
1357
  emoji: emoji2
1131
- }, /* @__PURE__ */ React23.createElement("p", {
1358
+ }, /* @__PURE__ */ React26.createElement("p", {
1132
1359
  className: "text-sm mlb-1 font-normal text-center"
1133
- }, t(type === Invitation4.Type.MULTIUSE ? "invite many qr label" : "invite one qr label")), /* @__PURE__ */ React23.createElement("div", {
1360
+ }, t(type === Invitation5.Type.MULTIUSE ? "invite many qr label" : "invite one qr label")), /* @__PURE__ */ React26.createElement("div", {
1134
1361
  role: "none",
1135
- className: mx18(descriptionText7, "is-full max-is-[14rem] relative")
1136
- }, /* @__PURE__ */ React23.createElement(QR, {
1362
+ className: mx19(descriptionText7, "is-full max-is-[14rem] relative")
1363
+ }, /* @__PURE__ */ React26.createElement(QR, {
1137
1364
  rounding: 100,
1138
1365
  backgroundColor: "transparent",
1139
1366
  color: "currentColor",
1140
- className: mx18("is-full bs-full p-2", showAuthCode && "invisible"),
1367
+ className: mx19("is-full bs-full p-2", showAuthCode && "invisible"),
1141
1368
  "aria-labelledby": qrLabel,
1142
1369
  errorCorrectionLevel: "Q",
1143
1370
  cutout: true
1144
- }, invitationUrl ?? "never"), /* @__PURE__ */ React23.createElement(Centered, null, /* @__PURE__ */ React23.createElement(Emoji, {
1371
+ }, invitationUrl ?? "never"), /* @__PURE__ */ React26.createElement(Centered, null, /* @__PURE__ */ React26.createElement(Emoji, {
1145
1372
  text: emoji2
1146
- }))), /* @__PURE__ */ React23.createElement("span", {
1373
+ }))), /* @__PURE__ */ React26.createElement("span", {
1147
1374
  id: qrLabel,
1148
1375
  className: "sr-only"
1149
- }, t("qr label")), /* @__PURE__ */ React23.createElement(CopyButton, {
1376
+ }, t("qr label")), /* @__PURE__ */ React26.createElement(CopyButton, {
1150
1377
  variant: "ghost",
1151
1378
  value: invitationUrl ?? "never"
1152
- })), /* @__PURE__ */ React23.createElement(InvitationManagerView, {
1379
+ })), /* @__PURE__ */ React26.createElement(InvitationManagerView, {
1153
1380
  id: "showing auth code"
1154
- }, /* @__PURE__ */ React23.createElement(Label, null, t("auth code message")), /* @__PURE__ */ React23.createElement(AuthCode, {
1381
+ }, /* @__PURE__ */ React26.createElement(Label, null, t("auth code message")), /* @__PURE__ */ React26.createElement(AuthCode, {
1155
1382
  code: authCode,
1156
1383
  large: true,
1157
1384
  classNames: "text-black dark:text-white"
1158
- }), /* @__PURE__ */ React23.createElement(Label, null, "Be sure the other device is showing this symbol:"), emoji2 && /* @__PURE__ */ React23.createElement(Emoji, {
1385
+ }), /* @__PURE__ */ React26.createElement(Label, null, "Be sure the other device is showing this symbol:"), emoji2 && /* @__PURE__ */ React26.createElement(Emoji, {
1159
1386
  text: emoji2
1160
- })), /* @__PURE__ */ React23.createElement(InvitationManagerView, {
1387
+ })), /* @__PURE__ */ React26.createElement(InvitationManagerView, {
1161
1388
  id: "showing final"
1162
- }, statusValue > 0 ? /* @__PURE__ */ React23.createElement(Check3, {
1163
- className: mx18("m-1.5", getSize7(6))
1164
- }) : /* @__PURE__ */ React23.createElement(X3, {
1165
- className: mx18("m-1.5", getSize7(6))
1166
- })))), /* @__PURE__ */ React23.createElement(Actions, {
1389
+ }, statusValue > 0 ? /* @__PURE__ */ React26.createElement(Check3, {
1390
+ className: mx19("m-1.5", getSize8(6))
1391
+ }) : /* @__PURE__ */ React26.createElement(X3, {
1392
+ className: mx19("m-1.5", getSize8(6))
1393
+ })))), /* @__PURE__ */ React26.createElement(Actions, {
1167
1394
  classNames: "mbs-4"
1168
- }, /* @__PURE__ */ React23.createElement(Action, {
1395
+ }, /* @__PURE__ */ React26.createElement(Action, {
1169
1396
  disabled: !active,
1170
1397
  onClick: () => send?.({
1171
1398
  type: "deselectInvitation"
@@ -1174,36 +1401,38 @@ var InvitationManager = ({ invitationUrl, active, send, status, type, authCode,
1174
1401
  };
1175
1402
 
1176
1403
  // packages/sdk/shell/src/panels/IdentityPanel/IdentityPanel.tsx
1177
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/IdentityPanel/IdentityPanel.tsx";
1404
+ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/IdentityPanel/IdentityPanel.tsx";
1178
1405
  var viewStyles = "pbs-1 pbe-3 pli-3";
1179
1406
  var IdentityHeading = ({ titleId, title, identity, onDone }) => {
1180
1407
  const fallbackHref = useJdenticonHref3(identity.identityKey.toHex(), 12);
1181
- return /* @__PURE__ */ React24.createElement(Heading, {
1408
+ return /* @__PURE__ */ React27.createElement(Heading, {
1182
1409
  titleId,
1183
1410
  title,
1184
- corner: /* @__PURE__ */ React24.createElement(CloseButton, {
1411
+ corner: /* @__PURE__ */ React27.createElement(CloseButton, {
1185
1412
  onDone
1186
1413
  })
1187
- }, /* @__PURE__ */ React24.createElement(Avatar4.Root, {
1414
+ }, /* @__PURE__ */ React27.createElement(Avatar4.Root, {
1188
1415
  size: 12,
1189
1416
  variant: "circle",
1190
1417
  status: "active"
1191
- }, /* @__PURE__ */ React24.createElement(Avatar4.Frame, {
1418
+ }, /* @__PURE__ */ React27.createElement(Avatar4.Frame, {
1192
1419
  classNames: "block mbs-4 mbe-2 mli-auto chromatic-ignore"
1193
- }, /* @__PURE__ */ React24.createElement(Avatar4.Fallback, {
1420
+ }, /* @__PURE__ */ React27.createElement(Avatar4.Fallback, {
1194
1421
  href: fallbackHref
1195
- })), /* @__PURE__ */ React24.createElement(Avatar4.Label, {
1196
- classNames: "block text-center font-light text-xl"
1422
+ })), /* @__PURE__ */ React27.createElement(Avatar4.Label, {
1423
+ classNames: "block text-center font-light text-xl",
1424
+ "data-testid": "identityHeading.displayName"
1197
1425
  }, identity.profile?.displayName ?? generateName2(identity.identityKey.toHex()))));
1198
1426
  };
1199
1427
  var IdentityPanelImpl = (props) => {
1200
- const { identity, titleId, activeView, onUpdateProfile, IdentityActionChooser: IdentityActionChooserComponent = IdentityActionChooser, InvitationManager: InvitationManagerComponent = InvitationManager, onDone, ...rest } = props;
1201
- const { t } = useTranslation10("os");
1428
+ const { identity, titleId, activeView, onUpdateProfile, onResetDevice, onJoinNewIdentity, IdentityActionChooser: IdentityActionChooserComponent = IdentityActionChooser, InvitationManager: InvitationManagerComponent = InvitationManager, onDone, ...rest } = props;
1429
+ const { t } = useTranslation13("os");
1202
1430
  const title = useMemo3(() => {
1203
1431
  switch (activeView) {
1204
- case "device manager":
1432
+ case "agent manager":
1433
+ return "Manage Agent";
1205
1434
  case "device invitation manager":
1206
- return t("choose devices label");
1435
+ return t("choose add device label");
1207
1436
  default:
1208
1437
  return t("identity heading");
1209
1438
  }
@@ -1211,41 +1440,62 @@ var IdentityPanelImpl = (props) => {
1211
1440
  activeView,
1212
1441
  t
1213
1442
  ]);
1214
- return /* @__PURE__ */ React24.createElement(DensityProvider2, {
1443
+ return /* @__PURE__ */ React27.createElement(DensityProvider2, {
1215
1444
  density: "fine"
1216
- }, /* @__PURE__ */ React24.createElement(IdentityHeading, {
1445
+ }, /* @__PURE__ */ React27.createElement(IdentityHeading, {
1217
1446
  identity,
1218
1447
  titleId,
1219
1448
  title,
1220
1449
  onDone
1221
- }), /* @__PURE__ */ React24.createElement(Viewport.Root, {
1450
+ }), /* @__PURE__ */ React27.createElement(Viewport.Root, {
1222
1451
  activeView
1223
- }, /* @__PURE__ */ React24.createElement(Viewport.Views, null, /* @__PURE__ */ React24.createElement(Viewport.View, {
1452
+ }, /* @__PURE__ */ React27.createElement(Viewport.Views, null, /* @__PURE__ */ React27.createElement(Viewport.View, {
1224
1453
  id: "identity action chooser",
1225
1454
  classNames: viewStyles
1226
- }, /* @__PURE__ */ React24.createElement(IdentityActionChooserComponent, {
1455
+ }, /* @__PURE__ */ React27.createElement(IdentityActionChooserComponent, {
1227
1456
  active: activeView === "identity action chooser",
1228
1457
  ...rest
1229
- })), /* @__PURE__ */ React24.createElement(Viewport.View, {
1458
+ })), /* @__PURE__ */ React27.createElement(Viewport.View, {
1230
1459
  id: "device invitation manager",
1231
1460
  classNames: viewStyles
1232
- }, /* @__PURE__ */ React24.createElement(InvitationManagerComponent, {
1461
+ }, /* @__PURE__ */ React27.createElement(InvitationManagerComponent, {
1233
1462
  active: activeView === "device invitation manager",
1234
1463
  ...rest,
1235
1464
  invitationUrl: rest.createInvitationUrl(rest.invitationCode)
1236
- })), /* @__PURE__ */ React24.createElement(Viewport.View, {
1465
+ })), /* @__PURE__ */ React27.createElement(Viewport.View, {
1466
+ id: "device manager",
1467
+ classNames: viewStyles
1468
+ }, /* @__PURE__ */ React27.createElement(DeviceManager, {
1469
+ active: activeView === "device manager",
1470
+ ...rest
1471
+ })), /* @__PURE__ */ React27.createElement(Viewport.View, {
1237
1472
  classNames: viewStyles,
1238
1473
  id: "update profile form"
1239
- }, /* @__PURE__ */ React24.createElement(ProfileForm, {
1474
+ }, /* @__PURE__ */ React27.createElement(ProfileForm, {
1240
1475
  send: rest.send,
1241
1476
  active: activeView === "update profile form",
1242
1477
  profile: identity.profile,
1243
1478
  onUpdateProfile
1479
+ })), /* @__PURE__ */ React27.createElement(Viewport.View, {
1480
+ classNames: viewStyles,
1481
+ id: "signing out"
1482
+ }, /* @__PURE__ */ React27.createElement(SignOutChooser, {
1483
+ send: rest.send,
1484
+ active: activeView === "signing out",
1485
+ onResetDevice,
1486
+ onJoinNewIdentity
1487
+ })), /* @__PURE__ */ React27.createElement(Viewport.View, {
1488
+ classNames: viewStyles,
1489
+ id: "agent manager"
1490
+ }, /* @__PURE__ */ React27.createElement(AgentForm, {
1491
+ send: rest.send,
1492
+ active: activeView === "agent manager",
1493
+ ...rest
1244
1494
  })))));
1245
1495
  };
1246
1496
  var IdentityPanelWithInvitationImpl = ({ invitation, ...props }) => {
1247
1497
  const invitationStatus = useInvitationStatus2(invitation);
1248
- return /* @__PURE__ */ React24.createElement(IdentityPanelImpl, {
1498
+ return /* @__PURE__ */ React27.createElement(IdentityPanelImpl, {
1249
1499
  ...props,
1250
1500
  ...invitationStatus
1251
1501
  });
@@ -1253,17 +1503,24 @@ var IdentityPanelWithInvitationImpl = ({ invitation, ...props }) => {
1253
1503
  var IdentityPanel = ({ titleId: propsTitleId, createInvitationUrl = (code) => code, ...props }) => {
1254
1504
  const titleId = useId5("identityPanel__heading", propsTitleId);
1255
1505
  const client = useClient3();
1506
+ const devices = useDevices();
1256
1507
  const identity = useIdentity();
1508
+ const invitations = useHaloInvitations2();
1509
+ const agentProps = useAgentHandlers({
1510
+ client,
1511
+ identity,
1512
+ invitations
1513
+ });
1257
1514
  if (!identity) {
1258
1515
  console.error("IdentityPanel rendered with no active identity.");
1259
1516
  return null;
1260
1517
  }
1261
1518
  const [identityState, identitySend, identityService] = useIdentityMachine(client);
1262
- useEffect2(() => {
1519
+ useEffect3(() => {
1263
1520
  const subscription = identityService.subscribe((state) => {
1264
1521
  log3("[state]", state, {
1265
- F: __dxlog_file3,
1266
- L: 117,
1522
+ F: __dxlog_file4,
1523
+ L: 138,
1267
1524
  S: void 0,
1268
1525
  C: (f, a) => f(...a)
1269
1526
  });
@@ -1278,6 +1535,8 @@ var IdentityPanel = ({ titleId: propsTitleId, createInvitationUrl = (code) => co
1278
1535
  return "identity action chooser";
1279
1536
  case identityState.matches("managingDeviceInvitation"):
1280
1537
  return "device invitation manager";
1538
+ case identityState.matches("managingDevices"):
1539
+ return "device manager";
1281
1540
  case [
1282
1541
  {
1283
1542
  managingProfile: "idle"
@@ -1287,6 +1546,17 @@ var IdentityPanel = ({ titleId: propsTitleId, createInvitationUrl = (code) => co
1287
1546
  }
1288
1547
  ].some(identityState.matches):
1289
1548
  return "update profile form";
1549
+ case identityState.matches("signingOut"):
1550
+ return "signing out";
1551
+ case [
1552
+ {
1553
+ managingAgent: "idle"
1554
+ },
1555
+ {
1556
+ managingAgent: "pending"
1557
+ }
1558
+ ].some(identityState.matches):
1559
+ return "agent manager";
1290
1560
  default:
1291
1561
  return "identity action chooser";
1292
1562
  }
@@ -1302,20 +1572,22 @@ var IdentityPanel = ({ titleId: propsTitleId, createInvitationUrl = (code) => co
1302
1572
  const implProps = {
1303
1573
  ...props,
1304
1574
  identity,
1575
+ devices,
1305
1576
  activeView,
1306
1577
  send: identitySend,
1307
1578
  titleId,
1308
1579
  createInvitationUrl,
1309
- onUpdateProfile
1580
+ onUpdateProfile,
1581
+ ...agentProps
1310
1582
  };
1311
- return identityState.context.invitation ? /* @__PURE__ */ React24.createElement(IdentityPanelWithInvitationImpl, {
1583
+ return identityState.context.invitation ? /* @__PURE__ */ React27.createElement(IdentityPanelWithInvitationImpl, {
1312
1584
  ...implProps,
1313
1585
  invitation: identityState.context.invitation
1314
- }) : /* @__PURE__ */ React24.createElement(IdentityPanelImpl, implProps);
1586
+ }) : /* @__PURE__ */ React27.createElement(IdentityPanelImpl, implProps);
1315
1587
  };
1316
1588
 
1317
1589
  // packages/sdk/shell/src/panels/JoinPanel/JoinPanel.tsx
1318
- import React34, { useCallback as useCallback6, useEffect as useEffect4, useMemo as useMemo4 } from "react";
1590
+ import React37, { useCallback as useCallback7, useEffect as useEffect5, useMemo as useMemo4 } from "react";
1319
1591
  import { log as log8 } from "@dxos/log";
1320
1592
  import { useClient as useClient6, useMulticastObservable } from "@dxos/react-client";
1321
1593
  import { useIdentity as useIdentity2 } from "@dxos/react-client/halo";
@@ -1323,25 +1595,25 @@ import { DensityProvider as DensityProvider3, useId as useId7, useThemeContext a
1323
1595
 
1324
1596
  // packages/sdk/shell/src/panels/JoinPanel/JoinHeading.tsx
1325
1597
  import { X as X4 } from "@phosphor-icons/react";
1326
- import React25, { cloneElement, forwardRef as forwardRef8 } from "react";
1327
- import { Button as Button5, useTranslation as useTranslation11 } from "@dxos/react-ui";
1328
- import { descriptionText as descriptionText8, getSize as getSize8, mx as mx19 } from "@dxos/react-ui-theme";
1598
+ import React28, { cloneElement, forwardRef as forwardRef8 } from "react";
1599
+ import { Button as Button5, useTranslation as useTranslation14 } from "@dxos/react-ui";
1600
+ import { descriptionText as descriptionText8, getSize as getSize9, mx as mx20 } from "@dxos/react-ui-theme";
1329
1601
  var JoinHeading = /* @__PURE__ */ forwardRef8(({ mode, titleId, onExit, exitActionParent }, forwardedRef) => {
1330
- const { t } = useTranslation11("os");
1331
- const exitButton = /* @__PURE__ */ React25.createElement(Button5, {
1602
+ const { t } = useTranslation14("os");
1603
+ const exitButton = /* @__PURE__ */ React28.createElement(Button5, {
1332
1604
  variant: "ghost",
1333
1605
  ...onExit && {
1334
1606
  onClick: onExit
1335
1607
  },
1336
- classNames: mx19(descriptionText8, "plb-0 pli-2 absolute block-start-0 inline-end-0 z-[1]"),
1608
+ classNames: mx20(descriptionText8, "plb-0 pli-2 absolute block-start-0 inline-end-0 z-[1]"),
1337
1609
  "data-testid": "join-exit"
1338
- }, /* @__PURE__ */ React25.createElement(X4, {
1610
+ }, /* @__PURE__ */ React28.createElement(X4, {
1339
1611
  weight: "bold",
1340
- className: getSize8(4)
1341
- }), /* @__PURE__ */ React25.createElement("span", {
1612
+ className: getSize9(4)
1613
+ }), /* @__PURE__ */ React28.createElement("span", {
1342
1614
  className: "sr-only"
1343
1615
  }, t("exit label")));
1344
- return /* @__PURE__ */ React25.createElement(Heading, {
1616
+ return /* @__PURE__ */ React28.createElement(Heading, {
1345
1617
  ref: forwardedRef,
1346
1618
  titleId,
1347
1619
  title: t(mode === "halo-only" ? "selecting identity heading" : "joining space heading"),
@@ -1356,14 +1628,15 @@ var JoinHeading = /* @__PURE__ */ forwardRef8(({ mode, titleId, onExit, exitActi
1356
1628
 
1357
1629
  // packages/sdk/shell/src/panels/JoinPanel/joinMachine.ts
1358
1630
  import { useMachine as useMachine2 } from "@xstate/react";
1359
- import { useCallback as useCallback5 } from "react";
1631
+ import { useCallback as useCallback6 } from "react";
1360
1632
  import { assign as assign2, createMachine as createMachine2 } from "xstate";
1361
1633
  import { log as log4 } from "@dxos/log";
1362
- import { Invitation as Invitation5, InvitationEncoder as InvitationEncoder2 } from "@dxos/react-client/invitations";
1363
- var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/joinMachine.ts";
1634
+ import { AlreadyJoinedError } from "@dxos/react-client";
1635
+ import { Invitation as Invitation6, InvitationEncoder as InvitationEncoder3 } from "@dxos/react-client/invitations";
1636
+ var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/joinMachine.ts";
1364
1637
  var getInvitationSubscribable = (Kind, invitation) => {
1365
1638
  log4("[subscribing to invitation]", invitation, {
1366
- F: __dxlog_file4,
1639
+ F: __dxlog_file5,
1367
1640
  L: 88,
1368
1641
  S: void 0,
1369
1642
  C: (f, a) => f(...a)
@@ -1371,12 +1644,12 @@ var getInvitationSubscribable = (Kind, invitation) => {
1371
1644
  return {
1372
1645
  subscribe: (next, onError, complete) => invitation.subscribe((invitation2) => {
1373
1646
  switch (invitation2.state) {
1374
- case Invitation5.State.CONNECTING: {
1647
+ case Invitation6.State.CONNECTING: {
1375
1648
  log4("[invitation connecting]", {
1376
1649
  Kind,
1377
1650
  invitation: invitation2
1378
1651
  }, {
1379
- F: __dxlog_file4,
1652
+ F: __dxlog_file5,
1380
1653
  L: 99,
1381
1654
  S: void 0,
1382
1655
  C: (f, a) => f(...a)
@@ -1386,12 +1659,12 @@ var getInvitationSubscribable = (Kind, invitation) => {
1386
1659
  invitation: invitation2
1387
1660
  });
1388
1661
  }
1389
- case Invitation5.State.CONNECTED: {
1662
+ case Invitation6.State.CONNECTED: {
1390
1663
  log4("[invitation connected]", {
1391
1664
  Kind,
1392
1665
  invitation: invitation2
1393
1666
  }, {
1394
- F: __dxlog_file4,
1667
+ F: __dxlog_file5,
1395
1668
  L: 104,
1396
1669
  S: void 0,
1397
1670
  C: (f, a) => f(...a)
@@ -1401,12 +1674,12 @@ var getInvitationSubscribable = (Kind, invitation) => {
1401
1674
  invitation: invitation2
1402
1675
  });
1403
1676
  }
1404
- case Invitation5.State.READY_FOR_AUTHENTICATION: {
1677
+ case Invitation6.State.READY_FOR_AUTHENTICATION: {
1405
1678
  log4("[invitation ready for authentication]", {
1406
1679
  Kind,
1407
1680
  invitation: invitation2
1408
1681
  }, {
1409
- F: __dxlog_file4,
1682
+ F: __dxlog_file5,
1410
1683
  L: 109,
1411
1684
  S: void 0,
1412
1685
  C: (f, a) => f(...a)
@@ -1416,12 +1689,12 @@ var getInvitationSubscribable = (Kind, invitation) => {
1416
1689
  invitation: invitation2
1417
1690
  });
1418
1691
  }
1419
- case Invitation5.State.AUTHENTICATING: {
1692
+ case Invitation6.State.AUTHENTICATING: {
1420
1693
  log4("[invitation authenticating]", {
1421
1694
  Kind,
1422
1695
  invitation: invitation2
1423
1696
  }, {
1424
- F: __dxlog_file4,
1697
+ F: __dxlog_file5,
1425
1698
  L: 114,
1426
1699
  S: void 0,
1427
1700
  C: (f, a) => f(...a)
@@ -1431,12 +1704,12 @@ var getInvitationSubscribable = (Kind, invitation) => {
1431
1704
  invitation: invitation2
1432
1705
  });
1433
1706
  }
1434
- case Invitation5.State.SUCCESS: {
1707
+ case Invitation6.State.SUCCESS: {
1435
1708
  log4("[invitation success]", {
1436
1709
  Kind,
1437
1710
  invitation: invitation2
1438
1711
  }, {
1439
- F: __dxlog_file4,
1712
+ F: __dxlog_file5,
1440
1713
  L: 119,
1441
1714
  S: void 0,
1442
1715
  C: (f, a) => f(...a)
@@ -1447,11 +1720,11 @@ var getInvitationSubscribable = (Kind, invitation) => {
1447
1720
  });
1448
1721
  return complete?.();
1449
1722
  }
1450
- case Invitation5.State.CANCELLED: {
1723
+ case Invitation6.State.CANCELLED: {
1451
1724
  log4.warn("[invitation cancelled]", {
1452
1725
  Kind
1453
1726
  }, {
1454
- F: __dxlog_file4,
1727
+ F: __dxlog_file5,
1455
1728
  L: 125,
1456
1729
  S: void 0,
1457
1730
  C: (f, a) => f(...a)
@@ -1461,11 +1734,11 @@ var getInvitationSubscribable = (Kind, invitation) => {
1461
1734
  reason: "cancelled"
1462
1735
  });
1463
1736
  }
1464
- case Invitation5.State.TIMEOUT: {
1737
+ case Invitation6.State.TIMEOUT: {
1465
1738
  log4.error("[invitation timeout]", {
1466
1739
  Kind
1467
1740
  }, {
1468
- F: __dxlog_file4,
1741
+ F: __dxlog_file5,
1469
1742
  L: 130,
1470
1743
  S: void 0,
1471
1744
  C: (f, a) => f(...a)
@@ -1477,12 +1750,28 @@ var getInvitationSubscribable = (Kind, invitation) => {
1477
1750
  }
1478
1751
  }
1479
1752
  }, (error) => {
1753
+ if (error instanceof AlreadyJoinedError) {
1754
+ log4("[already joined]", {
1755
+ Kind,
1756
+ error
1757
+ }, {
1758
+ F: __dxlog_file5,
1759
+ L: 137,
1760
+ S: void 0,
1761
+ C: (f, a) => f(...a)
1762
+ });
1763
+ next({
1764
+ type: `success${Kind}Invitation`,
1765
+ invitation: invitation.get()
1766
+ });
1767
+ return complete?.();
1768
+ }
1480
1769
  log4.error("[invitation errored]", {
1481
1770
  Kind,
1482
1771
  error
1483
1772
  }, {
1484
- F: __dxlog_file4,
1485
- L: 136,
1773
+ F: __dxlog_file5,
1774
+ L: 142,
1486
1775
  S: void 0,
1487
1776
  C: (f, a) => f(...a)
1488
1777
  });
@@ -1544,7 +1833,7 @@ var acceptingInvitationTemplate = (Kind, successTarget) => {
1544
1833
  {
1545
1834
  cond: (context) => {
1546
1835
  const invitation = context[Kind.toLowerCase()].invitation;
1547
- return !invitation || invitation?.state === Invitation5.State.CONNECTING;
1836
+ return !invitation || invitation?.state === Invitation6.State.CONNECTING;
1548
1837
  },
1549
1838
  target: `connecting${Kind}Invitation`,
1550
1839
  actions: "log"
@@ -1801,13 +2090,13 @@ var joinMachine = createMachine2({
1801
2090
  } : context.space
1802
2091
  }),
1803
2092
  log: (context, event) => {
1804
- log4.info("[transition]", {
2093
+ log4("[transition]", {
1805
2094
  event,
1806
2095
  haloInvitation: context.halo.invitation,
1807
2096
  spaceInvitation: context.space.invitation
1808
2097
  }, {
1809
- F: __dxlog_file4,
1810
- L: 400,
2098
+ F: __dxlog_file5,
2099
+ L: 406,
1811
2100
  S: void 0,
1812
2101
  C: (f, a) => f(...a)
1813
2102
  });
@@ -1820,8 +2109,8 @@ var defaultCodeFromUrl = (invitationType, text) => {
1820
2109
  return searchParams.get(`${invitationType}InvitationCode`) ?? searchParams.get(`${invitationType}Invitation`) ?? searchParams.get("invitationCode") ?? searchParams.get("invitation") ?? text;
1821
2110
  } catch (err) {
1822
2111
  log4.catch(err, void 0, {
1823
- F: __dxlog_file4,
1824
- L: 427,
2112
+ F: __dxlog_file5,
2113
+ L: 433,
1825
2114
  S: void 0,
1826
2115
  C: (f, a) => f(...a)
1827
2116
  });
@@ -1829,10 +2118,11 @@ var defaultCodeFromUrl = (invitationType, text) => {
1829
2118
  }
1830
2119
  };
1831
2120
  var useJoinMachine = (client, options) => {
1832
- const redeemHaloInvitationCode = useCallback5(({ halo }) => {
2121
+ const redeemHaloInvitationCode = useCallback6(({ halo }) => {
1833
2122
  if (halo.unredeemedCode) {
1834
2123
  try {
1835
- const invitationObservable = client.halo.join(InvitationEncoder2.decode(defaultCodeFromUrl("halo", halo.unredeemedCode)));
2124
+ const invitation = InvitationEncoder3.decode(defaultCodeFromUrl("halo", halo.unredeemedCode));
2125
+ const invitationObservable = client.halo.join(invitation);
1836
2126
  return {
1837
2127
  ...halo,
1838
2128
  invitationObservable,
@@ -1840,8 +2130,8 @@ var useJoinMachine = (client, options) => {
1840
2130
  };
1841
2131
  } catch (err) {
1842
2132
  log4.error("Could not redeem device invitation code", err, {
1843
- F: __dxlog_file4,
1844
- L: 449,
2133
+ F: __dxlog_file5,
2134
+ L: 454,
1845
2135
  S: void 0,
1846
2136
  C: (f, a) => f(...a)
1847
2137
  });
@@ -1853,27 +2143,20 @@ var useJoinMachine = (client, options) => {
1853
2143
  }, [
1854
2144
  client
1855
2145
  ]);
1856
- const redeemSpaceInvitationCode = useCallback5(({ space }) => {
2146
+ const redeemSpaceInvitationCode = useCallback6(({ space }) => {
1857
2147
  if (space.unredeemedCode) {
1858
2148
  try {
1859
- const invitation = InvitationEncoder2.decode(defaultCodeFromUrl("space", space.unredeemedCode));
1860
- if (space.succeededKeys?.has(invitation.spaceKey?.toHex() ?? "never")) {
1861
- return {
1862
- ...space,
1863
- invitation
1864
- };
1865
- } else {
1866
- const invitationObservable = client.spaces.join(invitation);
1867
- return {
1868
- ...space,
1869
- invitationObservable,
1870
- invitationSubscribable: getInvitationSubscribable("Space", invitationObservable)
1871
- };
1872
- }
2149
+ const invitation = InvitationEncoder3.decode(defaultCodeFromUrl("space", space.unredeemedCode));
2150
+ const invitationObservable = client.spaces.join(invitation);
2151
+ return {
2152
+ ...space,
2153
+ invitationObservable,
2154
+ invitationSubscribable: getInvitationSubscribable("Space", invitationObservable)
2155
+ };
1873
2156
  } catch (err) {
1874
2157
  log4.error("Could not redeem space invitation code", err, {
1875
- F: __dxlog_file4,
1876
- L: 479,
2158
+ F: __dxlog_file5,
2159
+ L: 476,
1877
2160
  S: void 0,
1878
2161
  C: (f, a) => f(...a)
1879
2162
  });
@@ -1885,7 +2168,7 @@ var useJoinMachine = (client, options) => {
1885
2168
  }, [
1886
2169
  client
1887
2170
  ]);
1888
- const invalidateHaloInvitationCode = useCallback5(({ halo }) => {
2171
+ const invalidateHaloInvitationCode = useCallback6(({ halo }) => {
1889
2172
  if (halo.unredeemedCode) {
1890
2173
  options?.onInvalidateInvitationCode?.(halo.unredeemedCode);
1891
2174
  return {
@@ -1898,7 +2181,7 @@ var useJoinMachine = (client, options) => {
1898
2181
  }, [
1899
2182
  options?.onInvalidateInvitationCode
1900
2183
  ]);
1901
- const invalidateSpaceInvitationCode = useCallback5(({ space }) => {
2184
+ const invalidateSpaceInvitationCode = useCallback6(({ space }) => {
1902
2185
  if (space.unredeemedCode) {
1903
2186
  options?.onInvalidateInvitationCode?.(space.unredeemedCode);
1904
2187
  return {
@@ -1933,17 +2216,17 @@ var useJoinMachine = (client, options) => {
1933
2216
 
1934
2217
  // packages/sdk/shell/src/panels/JoinPanel/steps/AdditionMethodChooser.tsx
1935
2218
  import { CaretRight as CaretRight2, Plus as Plus2, QrCode, Textbox } from "@phosphor-icons/react";
1936
- import React26 from "react";
1937
- import { useTranslation as useTranslation12 } from "@dxos/react-ui";
1938
- import { getSize as getSize9 } from "@dxos/react-ui-theme";
2219
+ import React29 from "react";
2220
+ import { useTranslation as useTranslation15 } from "@dxos/react-ui";
2221
+ import { getSize as getSize10 } from "@dxos/react-ui-theme";
1939
2222
  var AdditionMethodChooser = (viewStateProps) => {
1940
2223
  const disabled = !viewStateProps.active;
1941
2224
  const { send } = viewStateProps;
1942
- const { t } = useTranslation12("os");
2225
+ const { t } = useTranslation15("os");
1943
2226
  const sharedButtonProps = {
1944
2227
  disabled,
1945
- after: /* @__PURE__ */ React26.createElement(CaretRight2, {
1946
- className: getSize9(4),
2228
+ after: /* @__PURE__ */ React29.createElement(CaretRight2, {
2229
+ className: getSize10(4),
1947
2230
  weight: "bold"
1948
2231
  }),
1949
2232
  slots: {
@@ -1952,77 +2235,77 @@ var AdditionMethodChooser = (viewStateProps) => {
1952
2235
  }
1953
2236
  }
1954
2237
  };
1955
- return /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(StepHeading, null, t("addition method chooser title")), /* @__PURE__ */ React26.createElement("div", {
2238
+ return /* @__PURE__ */ React29.createElement(React29.Fragment, null, /* @__PURE__ */ React29.createElement(StepHeading, null, t("addition method chooser title")), /* @__PURE__ */ React29.createElement("div", {
1956
2239
  role: "none",
1957
2240
  className: "flex flex-col gap-1 grow"
1958
- }, /* @__PURE__ */ React26.createElement(CompoundButton, {
2241
+ }, /* @__PURE__ */ React29.createElement(CompoundButton, {
1959
2242
  ...sharedButtonProps,
1960
2243
  description: t("create identity description"),
1961
- before: /* @__PURE__ */ React26.createElement(Plus2, {
1962
- className: getSize9(6)
2244
+ before: /* @__PURE__ */ React29.createElement(Plus2, {
2245
+ className: getSize10(6)
1963
2246
  }),
1964
2247
  onClick: () => send({
1965
2248
  type: "createIdentity"
1966
2249
  }),
1967
2250
  "data-autofocus": "choosingAuthMethod",
1968
- "data-testid": "create-identity"
1969
- }, t("create identity label")), /* @__PURE__ */ React26.createElement(CompoundButton, {
2251
+ "data-testid": "identity-chooser.create-identity"
2252
+ }, t("create identity label")), /* @__PURE__ */ React29.createElement(CompoundButton, {
1970
2253
  ...sharedButtonProps,
1971
2254
  description: t("join identity description"),
1972
- before: /* @__PURE__ */ React26.createElement(QrCode, {
1973
- className: getSize9(6)
2255
+ before: /* @__PURE__ */ React29.createElement(QrCode, {
2256
+ className: getSize10(6)
1974
2257
  }),
1975
2258
  onClick: () => send({
1976
2259
  type: "acceptHaloInvitation"
1977
2260
  }),
1978
- "data-testid": "join-identity"
1979
- }, t("join identity label")), /* @__PURE__ */ React26.createElement(CompoundButton, {
2261
+ "data-testid": "identity-chooser.join-identity"
2262
+ }, t("join identity label")), /* @__PURE__ */ React29.createElement(CompoundButton, {
1980
2263
  ...sharedButtonProps,
1981
2264
  // TODO(mykola): Implement recover.
1982
2265
  disabled: true,
1983
2266
  description: t("recover identity description"),
1984
- before: /* @__PURE__ */ React26.createElement(Textbox, {
1985
- className: getSize9(6)
2267
+ before: /* @__PURE__ */ React29.createElement(Textbox, {
2268
+ className: getSize10(6)
1986
2269
  }),
1987
2270
  onClick: () => send({
1988
2271
  type: "recoverIdentity"
1989
2272
  }),
1990
- "data-testid": "recover-identity"
2273
+ "data-testid": "identity-chooser.recover-identity"
1991
2274
  }, t("recover identity label"))));
1992
2275
  };
1993
2276
 
1994
2277
  // packages/sdk/shell/src/panels/JoinPanel/steps/IdentityAdded.tsx
1995
- import React27, { cloneElement as cloneElement2 } from "react";
2278
+ import React30, { cloneElement as cloneElement2 } from "react";
1996
2279
  import { generateName as generateName3 } from "@dxos/display-name";
1997
- import { Avatar as Avatar5, useId as useId6, useJdenticonHref as useJdenticonHref4, useTranslation as useTranslation13 } from "@dxos/react-ui";
1998
- import { mx as mx20 } from "@dxos/react-ui-theme";
2280
+ import { Avatar as Avatar5, useId as useId6, useJdenticonHref as useJdenticonHref4, useTranslation as useTranslation16 } from "@dxos/react-ui";
2281
+ import { mx as mx21 } from "@dxos/react-ui-theme";
1999
2282
  var IdentityAdded = (props) => {
2000
2283
  const { mode, addedIdentity, active, send, onDone, doneActionParent } = props;
2001
2284
  const disabled = !active;
2002
- const { t } = useTranslation13("os");
2285
+ const { t } = useTranslation16("os");
2003
2286
  const fallbackValue = addedIdentity?.identityKey.toHex();
2004
2287
  const labelId = useId6("identityListItem__label");
2005
2288
  const jdenticon = useJdenticonHref4(fallbackValue ?? "", 12);
2006
2289
  const displayName = addedIdentity?.profile?.displayName ?? (addedIdentity && generateName3(addedIdentity?.identityKey.toHex()));
2007
- const doneAction = /* @__PURE__ */ React27.createElement(Action, {
2290
+ const doneAction = /* @__PURE__ */ React30.createElement(Action, {
2008
2291
  ...onDone && {
2009
2292
  onClick: () => onDone(null)
2010
2293
  },
2011
2294
  disabled,
2012
2295
  "data-autofocus": "confirmingAddedIdentity",
2013
2296
  "data-testid": "identity-added-done"
2014
- }, /* @__PURE__ */ React27.createElement("span", null, t("done label")));
2015
- return /* @__PURE__ */ React27.createElement(React27.Fragment, null, /* @__PURE__ */ React27.createElement(StepHeading, null, t("identity added label")), /* @__PURE__ */ React27.createElement("div", {
2297
+ }, /* @__PURE__ */ React30.createElement("span", null, t("done label")));
2298
+ return /* @__PURE__ */ React30.createElement(React30.Fragment, null, /* @__PURE__ */ React30.createElement(StepHeading, null, t("identity added label")), /* @__PURE__ */ React30.createElement("div", {
2016
2299
  role: "none",
2017
2300
  className: "grow flex flex-col items-center justify-center text-center gap-2"
2018
- }, /* @__PURE__ */ React27.createElement(Avatar5.Root, {
2301
+ }, /* @__PURE__ */ React30.createElement(Avatar5.Root, {
2019
2302
  status: "active",
2020
2303
  labelId
2021
- }, /* @__PURE__ */ React27.createElement(Avatar5.Frame, null, /* @__PURE__ */ React27.createElement(Avatar5.Fallback, {
2304
+ }, /* @__PURE__ */ React30.createElement(Avatar5.Frame, null, /* @__PURE__ */ React30.createElement(Avatar5.Fallback, {
2022
2305
  href: jdenticon
2023
- })), /* @__PURE__ */ React27.createElement(Avatar5.Label, {
2024
- classNames: mx20("text-lg truncate", !addedIdentity?.profile?.displayName && "font-mono")
2025
- }, displayName))), /* @__PURE__ */ React27.createElement(Actions, null, mode === "halo-only" ? doneActionParent ? /* @__PURE__ */ cloneElement2(doneActionParent, {}, doneAction) : doneAction : /* @__PURE__ */ React27.createElement(Action, {
2306
+ })), /* @__PURE__ */ React30.createElement(Avatar5.Label, {
2307
+ classNames: mx21("text-lg truncate", !addedIdentity?.profile?.displayName && "font-mono")
2308
+ }, displayName))), /* @__PURE__ */ React30.createElement(Actions, null, mode === "halo-only" ? doneActionParent ? /* @__PURE__ */ cloneElement2(doneActionParent, {}, doneAction) : doneAction : /* @__PURE__ */ React30.createElement(Action, {
2026
2309
  variant: "primary",
2027
2310
  disabled: disabled || !addedIdentity,
2028
2311
  onClick: () => addedIdentity && send({
@@ -2034,17 +2317,17 @@ var IdentityAdded = (props) => {
2034
2317
  };
2035
2318
 
2036
2319
  // packages/sdk/shell/src/panels/JoinPanel/steps/IdentityInput.tsx
2037
- import React28, { useState as useState4 } from "react";
2320
+ import React31, { useState as useState5 } from "react";
2038
2321
  import { log as log5 } from "@dxos/log";
2039
2322
  import { useClient as useClient4 } from "@dxos/react-client";
2040
- import { useTranslation as useTranslation14 } from "@dxos/react-ui";
2041
- var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/steps/IdentityInput.tsx";
2323
+ import { useTranslation as useTranslation17 } from "@dxos/react-ui";
2324
+ var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/steps/IdentityInput.tsx";
2042
2325
  var IdentityInput = (props) => {
2043
2326
  const { send, method } = props;
2044
2327
  const isRecover = method === "recover identity";
2045
2328
  const client = useClient4();
2046
- const { t } = useTranslation14("os");
2047
- const [validationMessage, setValidationMessage] = useState4("");
2329
+ const { t } = useTranslation17("os");
2330
+ const [validationMessage, setValidationMessage] = useState5("");
2048
2331
  const createIdentity = (displayName) => {
2049
2332
  void client.halo.createIdentity({
2050
2333
  [isRecover ? "seedphrase" : "displayName"]: displayName
@@ -2055,7 +2338,7 @@ var IdentityInput = (props) => {
2055
2338
  });
2056
2339
  }, (error) => {
2057
2340
  log5.catch(error, void 0, {
2058
- F: __dxlog_file5,
2341
+ F: __dxlog_file6,
2059
2342
  L: 37,
2060
2343
  S: void 0,
2061
2344
  C: (f, a) => f(...a)
@@ -2063,7 +2346,7 @@ var IdentityInput = (props) => {
2063
2346
  setValidationMessage(t(isRecover ? "failed to recover identity message" : "failed to create identity message"));
2064
2347
  });
2065
2348
  };
2066
- return /* @__PURE__ */ React28.createElement(IdentityInputImpl, {
2349
+ return /* @__PURE__ */ React31.createElement(IdentityInputImpl, {
2067
2350
  ...props,
2068
2351
  onDisplayNameConfirm: createIdentity,
2069
2352
  validationMessage
@@ -2072,27 +2355,27 @@ var IdentityInput = (props) => {
2072
2355
  var IdentityInputImpl = (props) => {
2073
2356
  const { method, send, active, onDisplayNameConfirm, validationMessage } = props;
2074
2357
  const disabled = !active;
2075
- const { t } = useTranslation14("os");
2076
- const [inputValue, setInputValue] = useState4("");
2358
+ const { t } = useTranslation17("os");
2359
+ const [inputValue, setInputValue] = useState5("");
2077
2360
  const isRecover = method === "recover identity";
2078
- return /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement("div", {
2361
+ return /* @__PURE__ */ React31.createElement(React31.Fragment, null, /* @__PURE__ */ React31.createElement("div", {
2079
2362
  role: "none",
2080
2363
  className: "grow flex flex-col justify-center"
2081
- }, /* @__PURE__ */ React28.createElement(Input, {
2364
+ }, /* @__PURE__ */ React31.createElement(Input, {
2082
2365
  validationMessage,
2083
- label: /* @__PURE__ */ React28.createElement(StepHeading, null, t(isRecover ? "recover identity input label" : "new identity input label")),
2366
+ label: /* @__PURE__ */ React31.createElement(StepHeading, null, t(isRecover ? "recover identity input label" : "new identity input label")),
2084
2367
  disabled,
2085
2368
  "data-testid": "identity-input",
2086
2369
  placeholder: isRecover ? "Type your recovery phrase" : "Type a display name",
2087
2370
  onChange: ({ target: { value } }) => setInputValue(value)
2088
- })), /* @__PURE__ */ React28.createElement(Actions, null, /* @__PURE__ */ React28.createElement(Action, {
2371
+ })), /* @__PURE__ */ React31.createElement(Actions, null, /* @__PURE__ */ React31.createElement(Action, {
2089
2372
  variant: "ghost",
2090
2373
  disabled,
2091
2374
  onClick: () => send?.({
2092
2375
  type: "deselectAuthMethod"
2093
2376
  }),
2094
2377
  "data-testid": `${method === "recover identity" ? "recover" : "create"}-identity-input-back`
2095
- }, t("back label")), /* @__PURE__ */ React28.createElement(Action, {
2378
+ }, t("back label")), /* @__PURE__ */ React31.createElement(Action, {
2096
2379
  variant: "primary",
2097
2380
  disabled,
2098
2381
  onClick: () => onDisplayNameConfirm?.(inputValue),
@@ -2101,32 +2384,32 @@ var IdentityInputImpl = (props) => {
2101
2384
  };
2102
2385
 
2103
2386
  // packages/sdk/shell/src/panels/JoinPanel/steps/InvitationAccepted.tsx
2104
- import React29, { cloneElement as cloneElement3 } from "react";
2105
- import { useTranslation as useTranslation15 } from "@dxos/react-ui";
2387
+ import React32, { cloneElement as cloneElement3 } from "react";
2388
+ import { useTranslation as useTranslation18 } from "@dxos/react-ui";
2106
2389
  var InvitationAccepted = (props) => {
2107
2390
  const { active, Kind, doneActionParent, onDone } = props;
2108
2391
  const disabled = !active;
2109
- const { t } = useTranslation15("os");
2110
- const doneAction = /* @__PURE__ */ React29.createElement(Action, {
2392
+ const { t } = useTranslation18("os");
2393
+ const doneAction = /* @__PURE__ */ React32.createElement(Action, {
2111
2394
  variant: "primary",
2112
2395
  onClick: onDone,
2113
2396
  disabled,
2114
2397
  "data-autofocus": `success${Kind}Invitation finishingJoining${Kind}`,
2115
2398
  "data-testid": `${Kind.toLowerCase()}-invitation-accepted-done`
2116
2399
  }, t("done label"));
2117
- return /* @__PURE__ */ React29.createElement(React29.Fragment, null, /* @__PURE__ */ React29.createElement("div", {
2400
+ return /* @__PURE__ */ React32.createElement(React32.Fragment, null, /* @__PURE__ */ React32.createElement("div", {
2118
2401
  role: "none",
2119
2402
  className: "grow flex flex-col justify-center"
2120
- }, /* @__PURE__ */ React29.createElement("p", {
2403
+ }, /* @__PURE__ */ React32.createElement("p", {
2121
2404
  className: "text-center text-sm font-normal"
2122
- }, t("welcome message"))), /* @__PURE__ */ React29.createElement(Actions, null, doneActionParent ? /* @__PURE__ */ cloneElement3(doneActionParent, {}, doneAction) : doneAction));
2405
+ }, t("welcome message"))), /* @__PURE__ */ React32.createElement(Actions, null, doneActionParent ? /* @__PURE__ */ cloneElement3(doneActionParent, {}, doneAction) : doneAction));
2123
2406
  };
2124
2407
 
2125
2408
  // packages/sdk/shell/src/panels/JoinPanel/steps/InvitationInput.tsx
2126
- import React30, { useState as useState5, useEffect as useEffect3, cloneElement as cloneElement4 } from "react";
2409
+ import React33, { useState as useState6, useEffect as useEffect4, cloneElement as cloneElement4 } from "react";
2127
2410
  import { log as log6 } from "@dxos/log";
2128
- import { useTranslation as useTranslation16 } from "@dxos/react-ui";
2129
- var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/steps/InvitationInput.tsx";
2411
+ import { useTranslation as useTranslation19 } from "@dxos/react-ui";
2412
+ var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/steps/InvitationInput.tsx";
2130
2413
  var invitationCodeFromUrl = (text) => {
2131
2414
  try {
2132
2415
  const searchParams = new URLSearchParams(text.substring(text.lastIndexOf("?")));
@@ -2134,7 +2417,7 @@ var invitationCodeFromUrl = (text) => {
2134
2417
  return invitation ?? text;
2135
2418
  } catch (err) {
2136
2419
  log6.catch(err, void 0, {
2137
- F: __dxlog_file6,
2420
+ F: __dxlog_file7,
2138
2421
  L: 25,
2139
2422
  S: void 0,
2140
2423
  C: (f, a) => f(...a)
@@ -2145,21 +2428,26 @@ var invitationCodeFromUrl = (text) => {
2145
2428
  var InvitationInput = (props) => {
2146
2429
  const { Kind, active, send, unredeemedCode, onExit, exitActionParent, onDone, doneActionParent, succeededKeys } = props;
2147
2430
  const disabled = !active;
2148
- const { t } = useTranslation16("os");
2149
- const [inputValue, setInputValue] = useState5(unredeemedCode ?? "");
2150
- useEffect3(() => {
2431
+ const { t } = useTranslation19("os");
2432
+ const [inputValue, setInputValue] = useState6(unredeemedCode ?? "");
2433
+ useEffect4(() => {
2151
2434
  unredeemedCode && setInputValue(unredeemedCode ?? "");
2152
2435
  }, [
2153
2436
  unredeemedCode
2154
2437
  ]);
2155
- const handleNext = () => send({
2156
- type: `set${Kind}InvitationCode`,
2157
- code: invitationCodeFromUrl(inputValue),
2158
- ...Kind === "Space" && {
2159
- succeededKeys
2438
+ const handleNext = () => {
2439
+ if (inputValue.trim().length === 0) {
2440
+ return;
2160
2441
  }
2161
- });
2162
- const exitAction = /* @__PURE__ */ React30.createElement(Action, {
2442
+ send({
2443
+ type: `set${Kind}InvitationCode`,
2444
+ code: invitationCodeFromUrl(inputValue),
2445
+ ...Kind === "Space" && {
2446
+ succeededKeys
2447
+ }
2448
+ });
2449
+ };
2450
+ const exitAction = /* @__PURE__ */ React33.createElement(Action, {
2163
2451
  variant: "ghost",
2164
2452
  disabled,
2165
2453
  ...onExit ? {
@@ -2169,11 +2457,12 @@ var InvitationInput = (props) => {
2169
2457
  },
2170
2458
  "data-testid": "join-exit"
2171
2459
  }, t("cancel label"));
2172
- return /* @__PURE__ */ React30.createElement(React30.Fragment, null, /* @__PURE__ */ React30.createElement("div", {
2460
+ return /* @__PURE__ */ React33.createElement(React33.Fragment, null, /* @__PURE__ */ React33.createElement("div", {
2173
2461
  role: "none",
2174
2462
  className: "grow flex flex-col justify-center"
2175
- }, /* @__PURE__ */ React30.createElement(Input, {
2176
- label: /* @__PURE__ */ React30.createElement(StepHeading, null, t("invitation input label")),
2463
+ }, /* @__PURE__ */ React33.createElement(Input, {
2464
+ label: /* @__PURE__ */ React33.createElement(StepHeading, null, t("invitation input label")),
2465
+ // TODO(burdon): Translation.
2177
2466
  placeholder: "Type an invitation code",
2178
2467
  disabled,
2179
2468
  value: inputValue,
@@ -2181,14 +2470,14 @@ var InvitationInput = (props) => {
2181
2470
  "data-autofocus": `inputting${Kind}InvitationCode`,
2182
2471
  "data-testid": `${Kind.toLowerCase()}-invitation-input`,
2183
2472
  onKeyUp: ({ key }) => key === "Enter" && handleNext()
2184
- })), /* @__PURE__ */ React30.createElement(Actions, null, Kind === "Halo" ? /* @__PURE__ */ React30.createElement(Action, {
2473
+ })), /* @__PURE__ */ React33.createElement(Actions, null, Kind === "Halo" ? /* @__PURE__ */ React33.createElement(Action, {
2185
2474
  variant: "ghost",
2186
2475
  disabled,
2187
2476
  onClick: () => send({
2188
2477
  type: "deselectAuthMethod"
2189
2478
  }),
2190
2479
  "data-testid": `${Kind.toLowerCase()}-invitation-input-back`
2191
- }, t("back label")) : exitActionParent ? /* @__PURE__ */ cloneElement4(exitActionParent, {}, exitAction) : doneActionParent ? /* @__PURE__ */ cloneElement4(doneActionParent, {}, exitAction) : exitAction, /* @__PURE__ */ React30.createElement(Action, {
2480
+ }, t("back label")) : exitActionParent ? /* @__PURE__ */ cloneElement4(exitActionParent, {}, exitAction) : doneActionParent ? /* @__PURE__ */ cloneElement4(doneActionParent, {}, exitAction) : exitAction, /* @__PURE__ */ React33.createElement(Action, {
2192
2481
  variant: "primary",
2193
2482
  disabled,
2194
2483
  onClick: handleNext,
@@ -2197,8 +2486,8 @@ var InvitationInput = (props) => {
2197
2486
  };
2198
2487
 
2199
2488
  // packages/sdk/shell/src/panels/JoinPanel/steps/InvitationRescuer.tsx
2200
- import React31 from "react";
2201
- import { useTranslation as useTranslation17 } from "@dxos/react-ui";
2489
+ import React34 from "react";
2490
+ import { useTranslation as useTranslation20 } from "@dxos/react-ui";
2202
2491
  import { descriptionText as descriptionText9 } from "@dxos/react-ui-theme";
2203
2492
  var InvitationActions = ({
2204
2493
  // `invitationState` does report correct state, but here we evaluate whether `failReason` is a better source of truth
@@ -2210,14 +2499,14 @@ var InvitationActions = ({
2210
2499
  Kind,
2211
2500
  failReason
2212
2501
  }) => {
2213
- const { t } = useTranslation17("os");
2502
+ const { t } = useTranslation20("os");
2214
2503
  if (failReason) {
2215
- return /* @__PURE__ */ React31.createElement(React31.Fragment, null, /* @__PURE__ */ React31.createElement(StepHeading, {
2504
+ return /* @__PURE__ */ React34.createElement(React34.Fragment, null, /* @__PURE__ */ React34.createElement(StepHeading, {
2216
2505
  className: descriptionText9
2217
- }, t(failReason === "timeout" ? "timeout status label" : failReason === "cancelled" ? "cancelled status label" : "error status label")), /* @__PURE__ */ React31.createElement("div", {
2506
+ }, t(failReason === "timeout" ? "timeout status label" : failReason === "cancelled" ? "cancelled status label" : "error status label")), /* @__PURE__ */ React34.createElement("div", {
2218
2507
  role: "none",
2219
2508
  className: "grow"
2220
- }), /* @__PURE__ */ React31.createElement(Actions, null, /* @__PURE__ */ React31.createElement(Action, {
2509
+ }), /* @__PURE__ */ React34.createElement(Actions, null, /* @__PURE__ */ React34.createElement(Action, {
2221
2510
  disabled: !active,
2222
2511
  onClick: () => send({
2223
2512
  type: `reset${Kind}Invitation`
@@ -2225,16 +2514,16 @@ var InvitationActions = ({
2225
2514
  "data-testid": "invitation-rescuer-reset"
2226
2515
  }, t("reset label"))));
2227
2516
  } else {
2228
- return /* @__PURE__ */ React31.createElement(React31.Fragment, null, /* @__PURE__ */ React31.createElement(StepHeading, {
2517
+ return /* @__PURE__ */ React34.createElement(React34.Fragment, null, /* @__PURE__ */ React34.createElement(StepHeading, {
2229
2518
  className: descriptionText9
2230
- }, t("connecting status label")), /* @__PURE__ */ React31.createElement("div", {
2519
+ }, t("connecting status label")), /* @__PURE__ */ React34.createElement("div", {
2231
2520
  role: "none",
2232
2521
  className: "grow"
2233
- }), /* @__PURE__ */ React31.createElement(Actions, null, /* @__PURE__ */ React31.createElement(Action, {
2522
+ }), /* @__PURE__ */ React34.createElement(Actions, null, /* @__PURE__ */ React34.createElement(Action, {
2234
2523
  disabled: true,
2235
2524
  classNames: "order-2",
2236
2525
  "data-testid": "next"
2237
- }, t("next label")), /* @__PURE__ */ React31.createElement(Action, {
2526
+ }, t("next label")), /* @__PURE__ */ React34.createElement(Action, {
2238
2527
  disabled: !active,
2239
2528
  onClick: onInvitationCancel,
2240
2529
  "data-testid": "invitation-rescuer-cancel"
@@ -2243,46 +2532,46 @@ var InvitationActions = ({
2243
2532
  };
2244
2533
  var InvitationRescuer = (props) => {
2245
2534
  const { Kind, invitationState, active, send } = props;
2246
- const { t } = useTranslation17("os");
2247
- return /* @__PURE__ */ React31.createElement(React31.Fragment, null, typeof invitationState === "undefined" ? /* @__PURE__ */ React31.createElement(React31.Fragment, null, /* @__PURE__ */ React31.createElement("div", {
2535
+ const { t } = useTranslation20("os");
2536
+ return /* @__PURE__ */ React34.createElement(React34.Fragment, null, typeof invitationState === "undefined" ? /* @__PURE__ */ React34.createElement(React34.Fragment, null, /* @__PURE__ */ React34.createElement("div", {
2248
2537
  role: "none",
2249
2538
  className: "grow flex flex-col justify-center"
2250
- }, /* @__PURE__ */ React31.createElement(StepHeading, {
2539
+ }, /* @__PURE__ */ React34.createElement(StepHeading, {
2251
2540
  className: descriptionText9
2252
- }, "There was a problem joining the space")), /* @__PURE__ */ React31.createElement(Actions, null, /* @__PURE__ */ React31.createElement(Action, {
2541
+ }, "There was a problem joining the space")), /* @__PURE__ */ React34.createElement(Actions, null, /* @__PURE__ */ React34.createElement(Action, {
2253
2542
  disabled: !active,
2254
2543
  "data-testid": "invitation-rescuer-blank-reset",
2255
2544
  onClick: () => send({
2256
2545
  type: `reset${Kind}Invitation`
2257
2546
  })
2258
- }, t("reset label")))) : /* @__PURE__ */ React31.createElement(InvitationActions, props));
2547
+ }, t("reset label")))) : /* @__PURE__ */ React34.createElement(InvitationActions, props));
2259
2548
  };
2260
2549
 
2261
2550
  // packages/sdk/shell/src/panels/JoinPanel/steps/InvitationAuthenticator.tsx
2262
- import React32, { useState as useState6 } from "react";
2263
- import { Input as Input2, useTranslation as useTranslation18 } from "@dxos/react-ui";
2551
+ import React35, { useState as useState7 } from "react";
2552
+ import { Input as Input2, useTranslation as useTranslation21 } from "@dxos/react-ui";
2264
2553
  var pinLength = 6;
2265
2554
  var InvitationAuthenticator = ({ failed, Kind, active, pending, invitationId, onInvitationAuthenticate, onInvitationCancel }) => {
2266
2555
  const disabled = !active || pending;
2267
- const { t } = useTranslation18("os");
2556
+ const { t } = useTranslation21("os");
2268
2557
  const invitationType = Kind.toLowerCase();
2269
- const [authCode, setAuthCode] = useState6("");
2558
+ const [authCode, setAuthCode] = useState7("");
2270
2559
  const onChange = ({ target: { value } }) => {
2271
2560
  setAuthCode(value);
2272
2561
  if (value.length === pinLength) {
2273
2562
  document.querySelector(`[data-autofocus-pinlength="${invitationType}"]`)?.focus();
2274
2563
  }
2275
2564
  };
2276
- return /* @__PURE__ */ React32.createElement(React32.Fragment, null, /* @__PURE__ */ React32.createElement("div", {
2565
+ return /* @__PURE__ */ React35.createElement(React35.Fragment, null, /* @__PURE__ */ React35.createElement("div", {
2277
2566
  role: "none",
2278
2567
  className: "grow flex flex-col justify-center"
2279
- }, invitationId && /* @__PURE__ */ React32.createElement(Emoji, {
2568
+ }, invitationId && /* @__PURE__ */ React35.createElement(Emoji, {
2280
2569
  text: toEmoji(invitationId)
2281
- }), /* @__PURE__ */ React32.createElement(Input2.Root, failed && {
2570
+ }), /* @__PURE__ */ React35.createElement(Input2.Root, failed && {
2282
2571
  validationValence: "error"
2283
- }, /* @__PURE__ */ React32.createElement(Input2.Label, {
2572
+ }, /* @__PURE__ */ React35.createElement(Input2.Label, {
2284
2573
  asChild: true
2285
- }, /* @__PURE__ */ React32.createElement(StepHeading, null, t("auth code input label"))), /* @__PURE__ */ React32.createElement(Input2.PinInput, {
2574
+ }, /* @__PURE__ */ React35.createElement(StepHeading, null, t("auth code input label"))), /* @__PURE__ */ React35.createElement(Input2.PinInput, {
2286
2575
  disabled,
2287
2576
  length: pinLength,
2288
2577
  onChange,
@@ -2293,14 +2582,14 @@ var InvitationAuthenticator = ({ failed, Kind, active, pending, invitationId, on
2293
2582
  "data-prevent-ios-autofocus": true,
2294
2583
  "data-testid": `${invitationType}-auth-code-input`,
2295
2584
  "data-1p-ignore": true
2296
- }), failed && /* @__PURE__ */ React32.createElement(Input2.DescriptionAndValidation, {
2585
+ }), failed && /* @__PURE__ */ React35.createElement(Input2.DescriptionAndValidation, {
2297
2586
  classNames: "text-center"
2298
- }, /* @__PURE__ */ React32.createElement(Input2.Validation, null, t("failed to authenticate message"))))), /* @__PURE__ */ React32.createElement(Actions, null, /* @__PURE__ */ React32.createElement(Action, {
2587
+ }, /* @__PURE__ */ React35.createElement(Input2.Validation, null, t("failed to authenticate message"))))), /* @__PURE__ */ React35.createElement(Actions, null, /* @__PURE__ */ React35.createElement(Action, {
2299
2588
  variant: "ghost",
2300
2589
  disabled,
2301
2590
  onClick: () => onInvitationCancel?.(),
2302
2591
  "data-testid": `${invitationType}-invitation-authenticator-cancel`
2303
- }, t("cancel label")), /* @__PURE__ */ React32.createElement(Action, {
2592
+ }, t("cancel label")), /* @__PURE__ */ React35.createElement(Action, {
2304
2593
  variant: "primary",
2305
2594
  disabled,
2306
2595
  onClick: () => onInvitationAuthenticate?.(authCode),
@@ -2310,21 +2599,21 @@ var InvitationAuthenticator = ({ failed, Kind, active, pending, invitationId, on
2310
2599
  };
2311
2600
 
2312
2601
  // packages/sdk/shell/src/panels/JoinPanel/steps/ResetIdentity.tsx
2313
- import React33, { useState as useState7 } from "react";
2602
+ import React36, { useState as useState8 } from "react";
2314
2603
  import { log as log7 } from "@dxos/log";
2315
2604
  import { useClient as useClient5 } from "@dxos/react-client";
2316
- import { useTranslation as useTranslation19 } from "@dxos/react-ui";
2317
- var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/steps/ResetIdentity.tsx";
2605
+ import { useTranslation as useTranslation22 } from "@dxos/react-ui";
2606
+ var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/steps/ResetIdentity.tsx";
2318
2607
  var ResetIdentity = ({ send, active }) => {
2319
2608
  const client = useClient5();
2320
- const { t } = useTranslation19("os");
2321
- const [validationMessage, setValidationMessage] = useState7("");
2609
+ const { t } = useTranslation22("os");
2610
+ const [validationMessage, setValidationMessage] = useState8("");
2322
2611
  const resetIdentity = () => {
2323
2612
  void client.reset().then(() => send?.({
2324
2613
  type: "resetIdentity"
2325
2614
  }), (error) => {
2326
2615
  log7.catch(error, void 0, {
2327
- F: __dxlog_file7,
2616
+ F: __dxlog_file8,
2328
2617
  L: 32,
2329
2618
  S: void 0,
2330
2619
  C: (f, a) => f(...a)
@@ -2332,29 +2621,29 @@ var ResetIdentity = ({ send, active }) => {
2332
2621
  setValidationMessage(t("failed to reset identity message"));
2333
2622
  });
2334
2623
  };
2335
- return /* @__PURE__ */ React33.createElement(ResetIdentityImpl, {
2624
+ return /* @__PURE__ */ React36.createElement(ResetIdentityImpl, {
2336
2625
  disabled: !active,
2337
2626
  validationMessage,
2338
2627
  onConfirm: () => resetIdentity()
2339
2628
  });
2340
2629
  };
2341
2630
  var ResetIdentityImpl = ({ disabled, validationMessage, onConfirm }) => {
2342
- const { t } = useTranslation19("os");
2631
+ const { t } = useTranslation22("os");
2343
2632
  const confirmationValue = t("confirmation value");
2344
- const [inputValue, setInputValue] = useState7("");
2345
- return /* @__PURE__ */ React33.createElement(React33.Fragment, null, /* @__PURE__ */ React33.createElement("div", {
2633
+ const [inputValue, setInputValue] = useState8("");
2634
+ return /* @__PURE__ */ React36.createElement(React36.Fragment, null, /* @__PURE__ */ React36.createElement("div", {
2346
2635
  role: "none",
2347
2636
  className: "grow flex flex-col justify-center"
2348
- }, /* @__PURE__ */ React33.createElement(Input, {
2637
+ }, /* @__PURE__ */ React36.createElement(Input, {
2349
2638
  validationMessage,
2350
- label: /* @__PURE__ */ React33.createElement(StepHeading, null, t("reset identity input label", {
2639
+ label: /* @__PURE__ */ React36.createElement(StepHeading, null, t("reset identity input label", {
2351
2640
  confirmationValue
2352
2641
  })),
2353
2642
  disabled,
2354
- "data-testid": "identity-input",
2643
+ "data-testid": "reset-identity-input",
2355
2644
  placeholder: confirmationValue,
2356
2645
  onChange: ({ target: { value } }) => setInputValue(value)
2357
- })), /* @__PURE__ */ React33.createElement(Actions, null, /* @__PURE__ */ React33.createElement(Action, {
2646
+ })), /* @__PURE__ */ React36.createElement(Actions, null, /* @__PURE__ */ React36.createElement(Action, {
2358
2647
  // TODO(wittjosiah): Probably make this red?
2359
2648
  variant: "primary",
2360
2649
  disabled: disabled || inputValue !== confirmationValue,
@@ -2367,7 +2656,7 @@ var ResetIdentityImpl = ({ disabled, validationMessage, onConfirm }) => {
2367
2656
  var stepStyles = "pbs-1 pbe-3 pli-3";
2368
2657
 
2369
2658
  // packages/sdk/shell/src/styles/invitationStatusStyles.ts
2370
- import { Invitation as Invitation6 } from "@dxos/react-client/invitations";
2659
+ import { Invitation as Invitation7 } from "@dxos/react-client/invitations";
2371
2660
  var inactiveBgColor = "bg-neutral-100 dark:bg-neutral-600";
2372
2661
  var activeBgColor = "bg-primary-500 dark:bg-primary-400";
2373
2662
  var successBgColor = "bg-success-500 dark:bg-success-400";
@@ -2383,55 +2672,55 @@ var activeStrokeColor = "stroke-primary-400 dark:stroke-primary-150";
2383
2672
  var successStrokeColor = "stroke-success-300 dark:stroke-primary-400";
2384
2673
  var errorStrokeColor = "stroke-error-300 dark:stroke-error-500";
2385
2674
  var cancelledStrokeColor = "stroke-warning-300 dark:stroke-warning-500";
2386
- var resolvedStrokeColor = (status) => status === Invitation6.State.ERROR ? errorStrokeColor : status === Invitation6.State.CANCELLED || status === Invitation6.State.TIMEOUT ? cancelledStrokeColor : successStrokeColor;
2387
- var resolvedBgColor = (status) => status === Invitation6.State.ERROR ? errorBgColor : status === Invitation6.State.CANCELLED || status === Invitation6.State.TIMEOUT ? cancelledBgColor : successBgColor;
2388
- var resolvedTextColor = (status) => status === Invitation6.State.ERROR ? errorTextColor : status === Invitation6.State.CANCELLED || status === Invitation6.State.TIMEOUT ? cancelledTextColor : successTextColor;
2675
+ var resolvedStrokeColor = (status) => status === Invitation7.State.ERROR ? errorStrokeColor : status === Invitation7.State.CANCELLED || status === Invitation7.State.TIMEOUT ? cancelledStrokeColor : successStrokeColor;
2676
+ var resolvedBgColor = (status) => status === Invitation7.State.ERROR ? errorBgColor : status === Invitation7.State.CANCELLED || status === Invitation7.State.TIMEOUT ? cancelledBgColor : successBgColor;
2677
+ var resolvedTextColor = (status) => status === Invitation7.State.ERROR ? errorTextColor : status === Invitation7.State.CANCELLED || status === Invitation7.State.TIMEOUT ? cancelledTextColor : successTextColor;
2389
2678
 
2390
2679
  // packages/sdk/shell/src/panels/JoinPanel/JoinPanel.tsx
2391
- var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/JoinPanel.tsx";
2680
+ var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/JoinPanel.tsx";
2392
2681
  var JoinPanelImpl = (props) => {
2393
2682
  const { titleId, send, activeView, failed, mode, unredeemedCodes, invitationStates, succeededKeys, failReasons, onExit, onHaloDone, onSpaceDone, exitActionParent, doneActionParent, onHaloInvitationCancel, onSpaceInvitationCancel, onHaloInvitationAuthenticate, onSpaceInvitationAuthenticate, IdentityInput: IdentityInputComponent = IdentityInput, ResetIdentity: ResetIdentityComponent = ResetIdentity } = props;
2394
- return /* @__PURE__ */ React34.createElement(DensityProvider3, {
2683
+ return /* @__PURE__ */ React37.createElement(DensityProvider3, {
2395
2684
  density: "fine"
2396
- }, mode !== "halo-only" && /* @__PURE__ */ React34.createElement(JoinHeading, {
2685
+ }, mode !== "halo-only" && /* @__PURE__ */ React37.createElement(JoinHeading, {
2397
2686
  titleId,
2398
2687
  mode,
2399
2688
  onExit,
2400
2689
  exitActionParent
2401
- }), /* @__PURE__ */ React34.createElement(Viewport.Root, {
2690
+ }), /* @__PURE__ */ React37.createElement(Viewport.Root, {
2402
2691
  focusManaged: true,
2403
2692
  activeView
2404
- }, /* @__PURE__ */ React34.createElement(Viewport.Views, null, /* @__PURE__ */ React34.createElement(Viewport.View, {
2693
+ }, /* @__PURE__ */ React37.createElement(Viewport.Views, null, /* @__PURE__ */ React37.createElement(Viewport.View, {
2405
2694
  classNames: stepStyles,
2406
2695
  id: "addition method chooser"
2407
- }, /* @__PURE__ */ React34.createElement(AdditionMethodChooser, {
2696
+ }, /* @__PURE__ */ React37.createElement(AdditionMethodChooser, {
2408
2697
  send,
2409
2698
  active: activeView === "addition method chooser"
2410
- })), /* @__PURE__ */ React34.createElement(Viewport.View, {
2699
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2411
2700
  classNames: stepStyles,
2412
2701
  id: "reset identity confirmation"
2413
- }, /* @__PURE__ */ React34.createElement(ResetIdentityComponent, {
2702
+ }, /* @__PURE__ */ React37.createElement(ResetIdentityComponent, {
2414
2703
  send,
2415
2704
  method: "reset identity",
2416
2705
  active: activeView === "reset identity confirmation"
2417
- })), /* @__PURE__ */ React34.createElement(Viewport.View, {
2706
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2418
2707
  classNames: stepStyles,
2419
2708
  id: "create identity input"
2420
- }, /* @__PURE__ */ React34.createElement(IdentityInputComponent, {
2709
+ }, /* @__PURE__ */ React37.createElement(IdentityInputComponent, {
2421
2710
  send,
2422
2711
  method: "create identity",
2423
2712
  active: activeView === "create identity input"
2424
- })), /* @__PURE__ */ React34.createElement(Viewport.View, {
2713
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2425
2714
  classNames: stepStyles,
2426
2715
  id: "recover identity input"
2427
- }, /* @__PURE__ */ React34.createElement(IdentityInputComponent, {
2716
+ }, /* @__PURE__ */ React37.createElement(IdentityInputComponent, {
2428
2717
  send,
2429
2718
  method: "recover identity",
2430
2719
  active: activeView === "recover identity input"
2431
- })), /* @__PURE__ */ React34.createElement(Viewport.View, {
2720
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2432
2721
  classNames: stepStyles,
2433
2722
  id: "halo invitation input"
2434
- }, /* @__PURE__ */ React34.createElement(InvitationInput, {
2723
+ }, /* @__PURE__ */ React37.createElement(InvitationInput, {
2435
2724
  send,
2436
2725
  Kind: "Halo",
2437
2726
  active: activeView === "halo invitation input",
@@ -2441,20 +2730,20 @@ var JoinPanelImpl = (props) => {
2441
2730
  ...succeededKeys?.Halo && {
2442
2731
  succeededKeys: succeededKeys.Halo
2443
2732
  }
2444
- })), /* @__PURE__ */ React34.createElement(Viewport.View, {
2733
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2445
2734
  classNames: stepStyles,
2446
2735
  id: "halo invitation rescuer"
2447
- }, /* @__PURE__ */ React34.createElement(InvitationRescuer, {
2736
+ }, /* @__PURE__ */ React37.createElement(InvitationRescuer, {
2448
2737
  send,
2449
2738
  Kind: "Halo",
2450
2739
  active: activeView === "halo invitation rescuer",
2451
2740
  invitationState: invitationStates?.Halo,
2452
2741
  onInvitationCancel: onHaloInvitationCancel,
2453
2742
  failReason: failReasons?.Halo
2454
- })), /* @__PURE__ */ React34.createElement(Viewport.View, {
2743
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2455
2744
  classNames: stepStyles,
2456
2745
  id: "halo invitation authenticator"
2457
- }, /* @__PURE__ */ React34.createElement(InvitationAuthenticator, {
2746
+ }, /* @__PURE__ */ React37.createElement(InvitationAuthenticator, {
2458
2747
  send,
2459
2748
  Kind: "Halo",
2460
2749
  active: activeView === "halo invitation authenticator",
@@ -2463,28 +2752,28 @@ var JoinPanelImpl = (props) => {
2463
2752
  ...failed.has("Halo") && {
2464
2753
  failed: true
2465
2754
  }
2466
- })), /* @__PURE__ */ React34.createElement(Viewport.View, {
2755
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2467
2756
  classNames: stepStyles,
2468
2757
  id: "halo invitation accepted"
2469
- }, /* @__PURE__ */ React34.createElement(InvitationAccepted, {
2758
+ }, /* @__PURE__ */ React37.createElement(InvitationAccepted, {
2470
2759
  send,
2471
2760
  Kind: "Halo",
2472
2761
  active: activeView === "halo invitation accepted",
2473
2762
  doneActionParent,
2474
2763
  onDone: onHaloDone
2475
- })), /* @__PURE__ */ React34.createElement(Viewport.View, {
2764
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2476
2765
  classNames: stepStyles,
2477
2766
  id: "identity added"
2478
- }, /* @__PURE__ */ React34.createElement(IdentityAdded, {
2767
+ }, /* @__PURE__ */ React37.createElement(IdentityAdded, {
2479
2768
  send,
2480
2769
  mode,
2481
2770
  active: activeView === "identity added",
2482
2771
  doneActionParent,
2483
2772
  onDone: onHaloDone
2484
- })), /* @__PURE__ */ React34.createElement(Viewport.View, {
2773
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2485
2774
  classNames: stepStyles,
2486
2775
  id: "space invitation input"
2487
- }, /* @__PURE__ */ React34.createElement(InvitationInput, {
2776
+ }, /* @__PURE__ */ React37.createElement(InvitationInput, {
2488
2777
  send,
2489
2778
  Kind: "Space",
2490
2779
  active: activeView === "space invitation input",
@@ -2496,20 +2785,20 @@ var JoinPanelImpl = (props) => {
2496
2785
  },
2497
2786
  onExit,
2498
2787
  exitActionParent
2499
- })), /* @__PURE__ */ React34.createElement(Viewport.View, {
2788
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2500
2789
  classNames: stepStyles,
2501
2790
  id: "space invitation rescuer"
2502
- }, /* @__PURE__ */ React34.createElement(InvitationRescuer, {
2791
+ }, /* @__PURE__ */ React37.createElement(InvitationRescuer, {
2503
2792
  send,
2504
2793
  Kind: "Space",
2505
2794
  active: activeView === "space invitation rescuer",
2506
2795
  invitationState: invitationStates?.Space,
2507
2796
  onInvitationCancel: onSpaceInvitationCancel,
2508
2797
  failReason: failReasons?.Space
2509
- })), /* @__PURE__ */ React34.createElement(Viewport.View, {
2798
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2510
2799
  classNames: stepStyles,
2511
2800
  id: "space invitation authenticator"
2512
- }, /* @__PURE__ */ React34.createElement(InvitationAuthenticator, {
2801
+ }, /* @__PURE__ */ React37.createElement(InvitationAuthenticator, {
2513
2802
  send,
2514
2803
  Kind: "Space",
2515
2804
  active: activeView === "space invitation authenticator",
@@ -2518,10 +2807,10 @@ var JoinPanelImpl = (props) => {
2518
2807
  ...failed.has("Space") && {
2519
2808
  failed: true
2520
2809
  }
2521
- })), /* @__PURE__ */ React34.createElement(Viewport.View, {
2810
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2522
2811
  classNames: stepStyles,
2523
2812
  id: "space invitation accepted"
2524
- }, /* @__PURE__ */ React34.createElement(InvitationAccepted, {
2813
+ }, /* @__PURE__ */ React37.createElement(InvitationAccepted, {
2525
2814
  send,
2526
2815
  Kind: "Space",
2527
2816
  active: activeView === "space invitation accepted",
@@ -2545,12 +2834,11 @@ var JoinPanel = ({ titleId: propsTitleId, mode = "default", initialInvitationCod
2545
2834
  }
2546
2835
  }
2547
2836
  });
2548
- console.log("[joinState]", joinState);
2549
- useEffect4(() => {
2837
+ useEffect5(() => {
2550
2838
  const subscription = joinService.subscribe((state) => {
2551
2839
  log8("[state]", state, {
2552
- F: __dxlog_file8,
2553
- L: 200,
2840
+ F: __dxlog_file9,
2841
+ L: 198,
2554
2842
  S: void 0,
2555
2843
  C: (f, a) => f(...a)
2556
2844
  });
@@ -2559,7 +2847,7 @@ var JoinPanel = ({ titleId: propsTitleId, mode = "default", initialInvitationCod
2559
2847
  }, [
2560
2848
  joinService
2561
2849
  ]);
2562
- useEffect4(() => {
2850
+ useEffect5(() => {
2563
2851
  const stateStack = joinState.configuration[0].id.split(".");
2564
2852
  const innermostState = stateStack[stateStack.length - 1];
2565
2853
  const autoFocusValue = innermostState === "finishingJoining" ? "successSpaceInvitation" : innermostState;
@@ -2740,27 +3028,29 @@ var JoinPanel = ({ titleId: propsTitleId, mode = "default", initialInvitationCod
2740
3028
  }), [
2741
3029
  joinState
2742
3030
  ]);
2743
- const onHaloDone = useCallback6(() => {
3031
+ const onHaloDone = useCallback7(() => {
2744
3032
  propsOnDone?.({
2745
3033
  identityKey: joinState.context.halo.invitation?.identityKey ?? null,
2746
3034
  swarmKey: joinState.context.halo.invitation?.swarmKey ?? null,
2747
- spaceKey: joinState.context.halo.invitation?.spaceKey ?? null
3035
+ spaceKey: joinState.context.halo.invitation?.spaceKey ?? null,
3036
+ target: joinState.context.halo.invitation?.target ?? null
2748
3037
  });
2749
3038
  }, [
2750
3039
  joinState,
2751
3040
  propsOnDone
2752
3041
  ]);
2753
- const onSpaceDone = useCallback6(() => {
3042
+ const onSpaceDone = useCallback7(() => {
2754
3043
  propsOnDone?.({
2755
3044
  identityKey: joinState.context.space.invitation?.identityKey ?? null,
2756
3045
  swarmKey: joinState.context.space.invitation?.swarmKey ?? null,
2757
- spaceKey: joinState.context.space.invitation?.spaceKey ?? null
3046
+ spaceKey: joinState.context.space.invitation?.spaceKey ?? null,
3047
+ target: joinState.context.space.invitation?.target ?? null
2758
3048
  });
2759
3049
  }, [
2760
3050
  joinState,
2761
3051
  propsOnDone
2762
3052
  ]);
2763
- return /* @__PURE__ */ React34.createElement(JoinPanelImpl, {
3053
+ return /* @__PURE__ */ React37.createElement(JoinPanelImpl, {
2764
3054
  titleId,
2765
3055
  mode,
2766
3056
  send: joinSend,
@@ -2799,16 +3089,16 @@ var JoinPanel = ({ titleId: propsTitleId, mode = "default", initialInvitationCod
2799
3089
 
2800
3090
  // packages/sdk/shell/src/panels/SpacePanel/SpacePanel.tsx
2801
3091
  import { Planet } from "@phosphor-icons/react";
2802
- import React36, { useEffect as useEffect5, useMemo as useMemo5 } from "react";
3092
+ import React39, { useEffect as useEffect6, useMemo as useMemo5 } from "react";
2803
3093
  import { log as log10 } from "@dxos/log";
2804
3094
  import { useInvitationStatus as useInvitationStatus3 } from "@dxos/react-client/invitations";
2805
- import { DensityProvider as DensityProvider4, useId as useId8, useTranslation as useTranslation21 } from "@dxos/react-ui";
3095
+ import { DensityProvider as DensityProvider4, useId as useId8, useTranslation as useTranslation24 } from "@dxos/react-ui";
2806
3096
 
2807
3097
  // packages/sdk/shell/src/panels/SpacePanel/spaceMachine.ts
2808
3098
  import { useMachine as useMachine3 } from "@xstate/react";
2809
3099
  import { assign as assign3, createMachine as createMachine3 } from "xstate";
2810
3100
  import { log as log9 } from "@dxos/log";
2811
- var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/SpacePanel/spaceMachine.ts";
3101
+ var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/SpacePanel/spaceMachine.ts";
2812
3102
  var spaceMachine = createMachine3({
2813
3103
  id: "space",
2814
3104
  predictableActionArguments: true,
@@ -2849,7 +3139,7 @@ var spaceMachine = createMachine3({
2849
3139
  event,
2850
3140
  context
2851
3141
  }, {
2852
- F: __dxlog_file9,
3142
+ F: __dxlog_file10,
2853
3143
  L: 53,
2854
3144
  S: void 0,
2855
3145
  C: (f, a) => f(...a)
@@ -2868,21 +3158,21 @@ var useSpaceMachine = (options) => {
2868
3158
 
2869
3159
  // packages/sdk/shell/src/panels/SpacePanel/steps/SpaceManager.tsx
2870
3160
  import { Placeholder as Placeholder2, UserPlus, UsersThree } from "@phosphor-icons/react";
2871
- import React35, { useCallback as useCallback7, useState as useState8 } from "react";
3161
+ import React38, { useCallback as useCallback8, useState as useState9 } from "react";
2872
3162
  import { useConfig } from "@dxos/react-client";
2873
3163
  import { useSpaceInvitations as useSpaceInvitations2 } from "@dxos/react-client/echo";
2874
- import { Invitation as Invitation7, InvitationEncoder as InvitationEncoder3 } from "@dxos/react-client/invitations";
2875
- import { ScrollArea, useTranslation as useTranslation20 } from "@dxos/react-ui";
2876
- import { descriptionText as descriptionText10, mx as mx21 } from "@dxos/react-ui-theme";
3164
+ import { Invitation as Invitation8, InvitationEncoder as InvitationEncoder4 } from "@dxos/react-client/invitations";
3165
+ import { ScrollArea, useTranslation as useTranslation23 } from "@dxos/react-ui";
3166
+ import { descriptionText as descriptionText10, mx as mx22 } from "@dxos/react-ui-theme";
2877
3167
  var activeActionKey = "dxos:react-shell/space-manager/active-action";
2878
3168
  var SpaceManager = (props) => {
2879
- const { space } = props;
2880
- const { t } = useTranslation20("os");
3169
+ const { space, target } = props;
3170
+ const { t } = useTranslation23("os");
2881
3171
  const config = useConfig();
2882
3172
  const invitations = useSpaceInvitations2(space?.key);
2883
- const onInvitationEvent = useCallback7((invitation) => {
2884
- const invitationCode = InvitationEncoder3.encode(invitation);
2885
- if (invitation.state === Invitation7.State.CONNECTING) {
3173
+ const onInvitationEvent = useCallback8((invitation) => {
3174
+ const invitationCode = InvitationEncoder4.encode(invitation);
3175
+ if (invitation.state === Invitation8.State.CONNECTING) {
2886
3176
  console.log(JSON.stringify({
2887
3177
  invitationCode,
2888
3178
  authCode: invitation.authCode
@@ -2894,10 +3184,11 @@ var SpaceManager = (props) => {
2894
3184
  label: t("invite one label"),
2895
3185
  description: t("invite one description"),
2896
3186
  icon: UserPlus,
2897
- onClick: useCallback7(() => {
3187
+ onClick: useCallback8(() => {
2898
3188
  const invitation = space.share?.({
2899
- type: Invitation7.Type.INTERACTIVE,
2900
- authMethod: Invitation7.AuthMethod.SHARED_SECRET
3189
+ type: Invitation8.Type.INTERACTIVE,
3190
+ authMethod: Invitation8.AuthMethod.SHARED_SECRET,
3191
+ target
2901
3192
  });
2902
3193
  if (invitation && config.values.runtime?.app?.env?.DX_ENVIRONMENT !== "production") {
2903
3194
  invitation.subscribe(onInvitationEvent);
@@ -2910,10 +3201,11 @@ var SpaceManager = (props) => {
2910
3201
  label: t("invite many label"),
2911
3202
  description: t("invite many description"),
2912
3203
  icon: UsersThree,
2913
- onClick: useCallback7(() => {
3204
+ onClick: useCallback8(() => {
2914
3205
  const invitation = space.share?.({
2915
- type: Invitation7.Type.MULTIUSE,
2916
- authMethod: Invitation7.AuthMethod.NONE
3206
+ type: Invitation8.Type.MULTIUSE,
3207
+ authMethod: Invitation8.AuthMethod.NONE,
3208
+ target
2917
3209
  });
2918
3210
  if (invitation && config.values.runtime?.app?.env?.DX_ENVIRONMENT !== "production") {
2919
3211
  invitation.subscribe(onInvitationEvent);
@@ -2923,7 +3215,7 @@ var SpaceManager = (props) => {
2923
3215
  ])
2924
3216
  }
2925
3217
  };
2926
- return /* @__PURE__ */ React35.createElement(SpaceManagerImpl, {
3218
+ return /* @__PURE__ */ React38.createElement(SpaceManagerImpl, {
2927
3219
  ...props,
2928
3220
  invitations,
2929
3221
  inviteActions
@@ -2932,7 +3224,7 @@ var SpaceManager = (props) => {
2932
3224
  var headingFragment = "pis-3 pie-1 plb-1 mbe-1 font-medium";
2933
3225
  var SpaceManagerImpl = (props) => {
2934
3226
  const { active, space, createInvitationUrl, send, inviteActions: propsInviteActions, invitations, showInactiveInvitations, SpaceMemberList: SpaceMemberListComponent = SpaceMemberList, InvitationList: InvitationListComponent = InvitationList } = props;
2935
- const { t } = useTranslation20("os");
3227
+ const { t } = useTranslation23("os");
2936
3228
  const inviteActions = propsInviteActions ?? {
2937
3229
  noopInvite: {
2938
3230
  label: t("create space invitation label"),
@@ -2942,34 +3234,34 @@ var SpaceManagerImpl = (props) => {
2942
3234
  }
2943
3235
  }
2944
3236
  };
2945
- const [activeAction, setInternalActiveAction] = useState8(localStorage.getItem(activeActionKey) ?? "inviteOne");
3237
+ const [activeAction, setInternalActiveAction] = useState9(localStorage.getItem(activeActionKey) ?? "inviteOne");
2946
3238
  const setActiveAction = (nextAction) => {
2947
3239
  setInternalActiveAction(nextAction);
2948
3240
  localStorage.setItem(activeActionKey, nextAction);
2949
3241
  };
2950
3242
  const visibleInvitations = showInactiveInvitations ? invitations : invitations?.filter((invitation) => ![
2951
- Invitation7.State.CANCELLED
3243
+ Invitation8.State.CANCELLED
2952
3244
  ].includes(invitation.get().state));
2953
- return /* @__PURE__ */ React35.createElement(React35.Fragment, null, /* @__PURE__ */ React35.createElement(ScrollArea.Root, {
3245
+ return /* @__PURE__ */ React38.createElement(React38.Fragment, null, /* @__PURE__ */ React38.createElement(ScrollArea.Root, {
2954
3246
  classNames: "grow shrink basis-28 -mli-2"
2955
- }, /* @__PURE__ */ React35.createElement(ScrollArea.Viewport, {
3247
+ }, /* @__PURE__ */ React38.createElement(ScrollArea.Viewport, {
2956
3248
  classNames: "is-full pie-2"
2957
- }, !!visibleInvitations?.length && /* @__PURE__ */ React35.createElement(React35.Fragment, null, /* @__PURE__ */ React35.createElement("h3", {
2958
- className: mx21(headingFragment, descriptionText10)
2959
- }, t("invitation list heading")), /* @__PURE__ */ React35.createElement(InvitationListComponent, {
3249
+ }, !!visibleInvitations?.length && /* @__PURE__ */ React38.createElement(React38.Fragment, null, /* @__PURE__ */ React38.createElement("h3", {
3250
+ className: mx22(headingFragment, descriptionText10)
3251
+ }, t("invitation list heading")), /* @__PURE__ */ React38.createElement(InvitationListComponent, {
2960
3252
  className: "mb-2",
2961
3253
  send,
2962
3254
  invitations: visibleInvitations ?? [],
2963
3255
  onClickRemove: (invitation) => invitation.cancel(),
2964
3256
  createInvitationUrl
2965
- }), /* @__PURE__ */ React35.createElement("h3", {
2966
- className: mx21(headingFragment, descriptionText10, "mbs-2")
2967
- }, t("space member list heading"))), /* @__PURE__ */ React35.createElement(SpaceMemberListComponent, {
3257
+ }), /* @__PURE__ */ React38.createElement("h3", {
3258
+ className: mx22(headingFragment, descriptionText10, "mbs-2")
3259
+ }, t("space member list heading"))), /* @__PURE__ */ React38.createElement(SpaceMemberListComponent, {
2968
3260
  spaceKey: space.key,
2969
3261
  includeSelf: true
2970
- })), /* @__PURE__ */ React35.createElement(ScrollArea.Scrollbar, {
3262
+ })), /* @__PURE__ */ React38.createElement(ScrollArea.Scrollbar, {
2971
3263
  orientation: "vertical"
2972
- }, /* @__PURE__ */ React35.createElement(ScrollArea.Thumb, null))), /* @__PURE__ */ React35.createElement(Actions, null, /* @__PURE__ */ React35.createElement(BifurcatedAction, {
3264
+ }, /* @__PURE__ */ React38.createElement(ScrollArea.Thumb, null))), /* @__PURE__ */ React38.createElement(Actions, null, /* @__PURE__ */ React38.createElement(BifurcatedAction, {
2973
3265
  disabled: !active,
2974
3266
  actions: inviteActions,
2975
3267
  activeAction,
@@ -2979,47 +3271,48 @@ var SpaceManagerImpl = (props) => {
2979
3271
  };
2980
3272
 
2981
3273
  // packages/sdk/shell/src/panels/SpacePanel/SpacePanel.tsx
2982
- var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/SpacePanel/SpacePanel.tsx";
3274
+ var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/SpacePanel/SpacePanel.tsx";
2983
3275
  var SpacePanelHeading = ({ titleId, space, onDone }) => {
2984
- const { t } = useTranslation21("os");
3276
+ const { t } = useTranslation24("os");
2985
3277
  const name = space.properties.name;
2986
- return /* @__PURE__ */ React36.createElement(Heading, {
3278
+ return /* @__PURE__ */ React39.createElement(Heading, {
2987
3279
  titleId,
2988
3280
  title: t("space panel heading"),
2989
- corner: /* @__PURE__ */ React36.createElement(CloseButton, {
3281
+ corner: /* @__PURE__ */ React39.createElement(CloseButton, {
2990
3282
  "data-testid": "identity-panel-done",
2991
3283
  onDone
2992
3284
  })
2993
- }, /* @__PURE__ */ React36.createElement("div", {
3285
+ }, /* @__PURE__ */ React39.createElement("div", {
2994
3286
  role: "none",
2995
3287
  className: "flex gap-4 items-center justify-center mlb-4"
2996
- }, /* @__PURE__ */ React36.createElement(Planet, {
3288
+ }, /* @__PURE__ */ React39.createElement(Planet, {
2997
3289
  size: 32
2998
- }), /* @__PURE__ */ React36.createElement("div", {
3290
+ }), /* @__PURE__ */ React39.createElement("div", {
2999
3291
  className: "block text-start font-light text-xl"
3000
3292
  }, name ?? space.key.truncate())));
3001
3293
  };
3002
3294
  var SpacePanelImpl = (props) => {
3003
- const { titleId, activeView, space, SpaceManager: SpaceManagerComponent = SpaceManager, InvitationManager: InvitationManagerComponent = InvitationManager, ...rest } = props;
3004
- return /* @__PURE__ */ React36.createElement(DensityProvider4, {
3295
+ const { titleId, activeView, space, target, SpaceManager: SpaceManagerComponent = SpaceManager, InvitationManager: InvitationManagerComponent = InvitationManager, ...rest } = props;
3296
+ return /* @__PURE__ */ React39.createElement(DensityProvider4, {
3005
3297
  density: "fine"
3006
- }, /* @__PURE__ */ React36.createElement(SpacePanelHeading, {
3298
+ }, /* @__PURE__ */ React39.createElement(SpacePanelHeading, {
3007
3299
  ...rest,
3008
3300
  titleId,
3009
3301
  space
3010
- }), /* @__PURE__ */ React36.createElement(Viewport.Root, {
3302
+ }), /* @__PURE__ */ React39.createElement(Viewport.Root, {
3011
3303
  activeView
3012
- }, /* @__PURE__ */ React36.createElement(Viewport.Views, null, /* @__PURE__ */ React36.createElement(Viewport.View, {
3304
+ }, /* @__PURE__ */ React39.createElement(Viewport.Views, null, /* @__PURE__ */ React39.createElement(Viewport.View, {
3013
3305
  id: "space manager",
3014
3306
  classNames: stepStyles
3015
- }, /* @__PURE__ */ React36.createElement(SpaceManagerComponent, {
3307
+ }, /* @__PURE__ */ React39.createElement(SpaceManagerComponent, {
3016
3308
  active: activeView === "space manager",
3017
3309
  space,
3310
+ target,
3018
3311
  ...rest
3019
- })), /* @__PURE__ */ React36.createElement(Viewport.View, {
3312
+ })), /* @__PURE__ */ React39.createElement(Viewport.View, {
3020
3313
  id: "space invitation manager",
3021
3314
  classNames: stepStyles
3022
- }, /* @__PURE__ */ React36.createElement(InvitationManagerComponent, {
3315
+ }, /* @__PURE__ */ React39.createElement(InvitationManagerComponent, {
3023
3316
  active: activeView === "space invitation manager",
3024
3317
  ...rest,
3025
3318
  invitationUrl: props.invitationUrl
@@ -3027,7 +3320,7 @@ var SpacePanelImpl = (props) => {
3027
3320
  };
3028
3321
  var SpacePanelWithInvitationImpl = ({ invitation, ...props }) => {
3029
3322
  const invitationStatus = useInvitationStatus3(invitation);
3030
- return /* @__PURE__ */ React36.createElement(SpacePanelImpl, {
3323
+ return /* @__PURE__ */ React39.createElement(SpacePanelImpl, {
3031
3324
  ...props,
3032
3325
  ...invitationStatus,
3033
3326
  invitationUrl: props.createInvitationUrl(invitationStatus.invitationCode)
@@ -3040,11 +3333,11 @@ var SpacePanel = ({ titleId: propsTitleId, createInvitationUrl = (code) => code,
3040
3333
  space: props.space
3041
3334
  }
3042
3335
  });
3043
- useEffect5(() => {
3336
+ useEffect6(() => {
3044
3337
  const subscription = spaceService.subscribe((state) => {
3045
3338
  log10("[state]", state, {
3046
- F: __dxlog_file10,
3047
- L: 92,
3339
+ F: __dxlog_file11,
3340
+ L: 94,
3048
3341
  S: void 0,
3049
3342
  C: (f, a) => f(...a)
3050
3343
  });
@@ -3072,62 +3365,65 @@ var SpacePanel = ({ titleId: propsTitleId, createInvitationUrl = (code) => code,
3072
3365
  titleId,
3073
3366
  createInvitationUrl
3074
3367
  };
3075
- return spaceState.context.invitation ? /* @__PURE__ */ React36.createElement(SpacePanelWithInvitationImpl, {
3076
- ...implProps,
3077
- invitation: spaceState.context.invitation
3078
- }) : /* @__PURE__ */ React36.createElement(SpacePanelImpl, implProps);
3368
+ return spaceState.context.invitation ? (
3369
+ // TODO(wittjosiah): Unused? Remove?
3370
+ /* @__PURE__ */ React39.createElement(SpacePanelWithInvitationImpl, {
3371
+ ...implProps,
3372
+ invitation: spaceState.context.invitation
3373
+ })
3374
+ ) : /* @__PURE__ */ React39.createElement(SpacePanelImpl, implProps);
3079
3375
  };
3080
3376
 
3081
3377
  // packages/sdk/shell/src/composites/IdentityDialog/IdentityDialog.tsx
3082
3378
  var IdentityDialog = (props) => {
3083
3379
  const titleId = useId9("spaceDialog__title");
3084
- return /* @__PURE__ */ React37.createElement(Dialog.Root, {
3380
+ return /* @__PURE__ */ React40.createElement(Dialog.Root, {
3085
3381
  defaultOpen: true,
3086
3382
  onOpenChange: (open) => open || props.onDone?.()
3087
- }, /* @__PURE__ */ React37.createElement(Dialog.Portal, null, /* @__PURE__ */ React37.createElement(Dialog.Overlay, null, /* @__PURE__ */ React37.createElement(Dialog.Content, {
3383
+ }, /* @__PURE__ */ React40.createElement(Dialog.Portal, null, /* @__PURE__ */ React40.createElement(Dialog.Overlay, null, /* @__PURE__ */ React40.createElement(Dialog.Content, {
3088
3384
  "aria-labelledby": titleId,
3089
3385
  onOpenAutoFocus: (e) => e.preventDefault()
3090
- }, /* @__PURE__ */ React37.createElement(ClipboardProvider, null, /* @__PURE__ */ React37.createElement(IdentityPanel, {
3386
+ }, /* @__PURE__ */ React40.createElement(ClipboardProvider, null, /* @__PURE__ */ React40.createElement(IdentityPanel, {
3091
3387
  ...props,
3092
3388
  titleId,
3093
- doneActionParent: /* @__PURE__ */ React37.createElement(Dialog.Close, {
3389
+ doneActionParent: /* @__PURE__ */ React40.createElement(Dialog.Close, {
3094
3390
  asChild: true
3095
3391
  })
3096
3392
  }))))));
3097
3393
  };
3098
3394
 
3099
3395
  // packages/sdk/shell/src/composites/JoinDialog/JoinDialog.tsx
3100
- import React38 from "react";
3396
+ import React41 from "react";
3101
3397
  import { AlertDialog, useId as useId10, useVisualViewport } from "@dxos/react-ui";
3102
3398
  var JoinDialog = (joinPanelProps) => {
3103
3399
  const titleId = useId10("joinDialog__title");
3104
3400
  const { height } = useVisualViewport();
3105
- return /* @__PURE__ */ React38.createElement(AlertDialog.Root, {
3401
+ return /* @__PURE__ */ React41.createElement(AlertDialog.Root, {
3106
3402
  defaultOpen: true,
3107
3403
  onOpenChange: (open) => open || (joinPanelProps.onExit ? joinPanelProps.onExit() : joinPanelProps.onDone?.(null))
3108
- }, /* @__PURE__ */ React38.createElement(AlertDialog.Portal, null, /* @__PURE__ */ React38.createElement(AlertDialog.Overlay, {
3404
+ }, /* @__PURE__ */ React41.createElement(AlertDialog.Portal, null, /* @__PURE__ */ React41.createElement(AlertDialog.Overlay, {
3109
3405
  classNames: "backdrop-blur",
3110
3406
  ...height && {
3111
3407
  style: {
3112
3408
  blockSize: `${height}px`
3113
3409
  }
3114
3410
  }
3115
- }, /* @__PURE__ */ React38.createElement(AlertDialog.Content, {
3411
+ }, /* @__PURE__ */ React41.createElement(AlertDialog.Content, {
3116
3412
  "aria-labelledby": titleId
3117
- }, /* @__PURE__ */ React38.createElement(JoinPanel, {
3413
+ }, /* @__PURE__ */ React41.createElement(JoinPanel, {
3118
3414
  ...joinPanelProps,
3119
3415
  titleId,
3120
- exitActionParent: /* @__PURE__ */ React38.createElement(AlertDialog.Cancel, {
3416
+ exitActionParent: /* @__PURE__ */ React41.createElement(AlertDialog.Cancel, {
3121
3417
  asChild: true
3122
3418
  }),
3123
- doneActionParent: /* @__PURE__ */ React38.createElement(AlertDialog.Action, {
3419
+ doneActionParent: /* @__PURE__ */ React41.createElement(AlertDialog.Action, {
3124
3420
  asChild: true
3125
3421
  })
3126
3422
  })))));
3127
3423
  };
3128
3424
 
3129
3425
  // packages/sdk/shell/src/composites/Shell/run-shell.tsx
3130
- import React41, { StrictMode } from "react";
3426
+ import React44, { StrictMode } from "react";
3131
3427
  import { createRoot } from "react-dom/client";
3132
3428
  import { DEFAULT_CLIENT_CHANNEL, DEFAULT_SHELL_CHANNEL } from "@dxos/client-protocol";
3133
3429
  import { ShellRuntimeImpl } from "@dxos/client-services";
@@ -3137,49 +3433,51 @@ import { defaultTx } from "@dxos/react-ui-theme";
3137
3433
  import { createIFramePort } from "@dxos/rpc-tunnel";
3138
3434
 
3139
3435
  // packages/sdk/shell/src/composites/Shell/Shell.tsx
3140
- import React40, { useEffect as useEffect6, useState as useState9 } from "react";
3436
+ import React43, { useEffect as useEffect7, useState as useState10 } from "react";
3141
3437
  import { log as log11 } from "@dxos/log";
3142
- import { ShellDisplay, ShellLayout } from "@dxos/react-client";
3438
+ import { ShellDisplay, ShellLayout, useClient as useClient7 } from "@dxos/react-client";
3143
3439
  import { useSpace as useSpace2 } from "@dxos/react-client/echo";
3144
3440
 
3145
3441
  // packages/sdk/shell/src/composites/SpaceDialog/SpaceDialog.tsx
3146
- import React39 from "react";
3442
+ import React42 from "react";
3147
3443
  import { Dialog as Dialog2, useId as useId11 } from "@dxos/react-ui";
3148
3444
  var SpaceDialog = (spacePanelProps) => {
3149
3445
  const titleId = useId11("spaceDialog__title");
3150
- return /* @__PURE__ */ React39.createElement(Dialog2.Root, {
3446
+ return /* @__PURE__ */ React42.createElement(Dialog2.Root, {
3151
3447
  defaultOpen: true,
3152
3448
  onOpenChange: (open) => open || spacePanelProps.onDone?.()
3153
- }, /* @__PURE__ */ React39.createElement(Dialog2.Portal, null, /* @__PURE__ */ React39.createElement(Dialog2.Overlay, null, /* @__PURE__ */ React39.createElement(Dialog2.Content, {
3449
+ }, /* @__PURE__ */ React42.createElement(Dialog2.Portal, null, /* @__PURE__ */ React42.createElement(Dialog2.Overlay, null, /* @__PURE__ */ React42.createElement(Dialog2.Content, {
3154
3450
  "aria-labelledby": titleId
3155
- }, /* @__PURE__ */ React39.createElement(ClipboardProvider, null, /* @__PURE__ */ React39.createElement(SpacePanel, {
3451
+ }, /* @__PURE__ */ React42.createElement(ClipboardProvider, null, /* @__PURE__ */ React42.createElement(SpacePanel, {
3156
3452
  ...spacePanelProps,
3157
3453
  titleId,
3158
- doneActionParent: /* @__PURE__ */ React39.createElement(Dialog2.Close, {
3454
+ doneActionParent: /* @__PURE__ */ React42.createElement(Dialog2.Close, {
3159
3455
  asChild: true
3160
3456
  })
3161
3457
  }))))));
3162
3458
  };
3163
3459
 
3164
3460
  // packages/sdk/shell/src/composites/Shell/Shell.tsx
3165
- var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/composites/Shell/Shell.tsx";
3461
+ var __dxlog_file12 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/composites/Shell/Shell.tsx";
3166
3462
  var Shell = ({ runtime, origin }) => {
3167
- const [{ layout, invitationCode, spaceKey }, setLayout] = useState9({
3463
+ const [{ layout, invitationCode, spaceKey, target }, setLayout] = useState10({
3168
3464
  layout: runtime.layout,
3169
3465
  invitationCode: runtime.invitationCode,
3170
- spaceKey: runtime.spaceKey
3466
+ spaceKey: runtime.spaceKey,
3467
+ target: runtime.target
3171
3468
  });
3469
+ const client = useClient7();
3172
3470
  const space = useSpace2(spaceKey);
3173
- useEffect6(() => {
3471
+ useEffect7(() => {
3174
3472
  return runtime.layoutUpdate.on((request) => setLayout(request));
3175
3473
  }, [
3176
3474
  runtime
3177
3475
  ]);
3178
- useEffect6(() => {
3476
+ useEffect7(() => {
3179
3477
  if (layout === ShellLayout.SPACE && !space) {
3180
3478
  log11.warn("No space found for shell space invitations.", void 0, {
3181
- F: __dxlog_file11,
3182
- L: 30,
3479
+ F: __dxlog_file12,
3480
+ L: 32,
3183
3481
  S: void 0,
3184
3482
  C: (f, a) => f(...a)
3185
3483
  });
@@ -3200,7 +3498,7 @@ var Shell = ({ runtime, origin }) => {
3200
3498
  ]);
3201
3499
  switch (layout) {
3202
3500
  case ShellLayout.INITIALIZE_IDENTITY:
3203
- return /* @__PURE__ */ React40.createElement(JoinDialog, {
3501
+ return /* @__PURE__ */ React43.createElement(JoinDialog, {
3204
3502
  mode: "halo-only",
3205
3503
  initialInvitationCode: invitationCode,
3206
3504
  onDone: () => {
@@ -3215,8 +3513,18 @@ var Shell = ({ runtime, origin }) => {
3215
3513
  case ShellLayout.IDENTITY:
3216
3514
  case ShellLayout.SHARE_IDENTITY:
3217
3515
  case ShellLayout.EDIT_PROFILE:
3218
- return /* @__PURE__ */ React40.createElement(IdentityDialog, {
3516
+ return /* @__PURE__ */ React43.createElement(IdentityDialog, {
3219
3517
  createInvitationUrl: (invitationCode2) => `${origin}?deviceInvitationCode=${invitationCode2}`,
3518
+ onResetDevice: async () => {
3519
+ await client.reset();
3520
+ await runtime.setAppContext({
3521
+ display: ShellDisplay.NONE,
3522
+ reload: true
3523
+ });
3524
+ },
3525
+ onJoinNewIdentity: () => runtime.setLayout({
3526
+ layout: ShellLayout.INITIALIZE_IDENTITY
3527
+ }),
3220
3528
  onDone: async () => {
3221
3529
  await runtime.setAppContext({
3222
3530
  display: ShellDisplay.NONE
@@ -3227,8 +3535,9 @@ var Shell = ({ runtime, origin }) => {
3227
3535
  }
3228
3536
  });
3229
3537
  case ShellLayout.SPACE:
3230
- return space ? /* @__PURE__ */ React40.createElement(SpaceDialog, {
3538
+ return space ? /* @__PURE__ */ React43.createElement(SpaceDialog, {
3231
3539
  space,
3540
+ target,
3232
3541
  createInvitationUrl: (invitationCode2) => `${origin}?spaceInvitationCode=${invitationCode2}`,
3233
3542
  onDone: async () => {
3234
3543
  await runtime.setAppContext({
@@ -3240,12 +3549,14 @@ var Shell = ({ runtime, origin }) => {
3240
3549
  }
3241
3550
  }) : null;
3242
3551
  case ShellLayout.JOIN_SPACE:
3243
- return /* @__PURE__ */ React40.createElement(JoinDialog, {
3552
+ return /* @__PURE__ */ React43.createElement(JoinDialog, {
3244
3553
  initialInvitationCode: invitationCode,
3245
3554
  onDone: async (result) => {
3555
+ const target2 = result?.target ?? void 0;
3246
3556
  await runtime.setAppContext({
3247
3557
  display: ShellDisplay.NONE,
3248
- spaceKey: result?.spaceKey ?? void 0
3558
+ spaceKey: result?.spaceKey ?? void 0,
3559
+ target: target2
3249
3560
  });
3250
3561
  runtime.setLayout({
3251
3562
  layout: ShellLayout.DEFAULT
@@ -3337,7 +3648,8 @@ var os = {
3337
3648
  "selecting identity heading": "Selecting identity",
3338
3649
  "devices heading": "Devices",
3339
3650
  "identity heading": "Profile settings",
3340
- "choose devices label": "Add device",
3651
+ "choose add device label": "Add device",
3652
+ "choose devices label": "Manage devices",
3341
3653
  "choose profile label": "Edit profile",
3342
3654
  "choose sign out label": "Sign out",
3343
3655
  "empty space members message": "There is nobody in this space yet.",
@@ -3364,7 +3676,12 @@ var os = {
3364
3676
  "confirm label": "Confirm",
3365
3677
  "reset identity input label": "This will clear this device and all associated data. Type {{confirmationValue}} and confirm to continue.",
3366
3678
  "failed to reset identity message": "Failed to reset identity.",
3367
- "confirmation value": "CONFIRM"
3679
+ "confirmation value": "CONFIRM",
3680
+ "sign out chooser title": "DANGER ZONE",
3681
+ "sign out chooser message": "Proceeding with either action below will erase all data on this device.",
3682
+ "join new identity label": "Join a new identity",
3683
+ "reset device label": "Reset device",
3684
+ "reset device confirm message": "Are you sure you want to reset your device? All data will be lost."
3368
3685
  };
3369
3686
 
3370
3687
  // packages/sdk/shell/src/translations/index.ts
@@ -3388,27 +3705,27 @@ var runShell = async (config = new Config()) => {
3388
3705
  runtime.open(),
3389
3706
  client.initialize()
3390
3707
  ]);
3391
- createRoot(document.getElementById("root")).render(/* @__PURE__ */ React41.createElement(StrictMode, null, /* @__PURE__ */ React41.createElement(ThemeProvider, {
3708
+ createRoot(document.getElementById("root")).render(/* @__PURE__ */ React44.createElement(StrictMode, null, /* @__PURE__ */ React44.createElement(ThemeProvider, {
3392
3709
  tx: defaultTx,
3393
3710
  resourceExtensions: [
3394
3711
  osTranslations
3395
3712
  ]
3396
- }, /* @__PURE__ */ React41.createElement(ClientContext.Provider, {
3713
+ }, /* @__PURE__ */ React44.createElement(ClientContext.Provider, {
3397
3714
  value: {
3398
3715
  client,
3399
3716
  status: SystemStatus.ACTIVE
3400
3717
  }
3401
- }, /* @__PURE__ */ React41.createElement(ClipboardProvider, null, /* @__PURE__ */ React41.createElement(Tooltip3.Provider, null, /* @__PURE__ */ React41.createElement(Shell, {
3718
+ }, /* @__PURE__ */ React44.createElement(ClipboardProvider, null, /* @__PURE__ */ React44.createElement(Tooltip3.Provider, null, /* @__PURE__ */ React44.createElement(Shell, {
3402
3719
  runtime,
3403
3720
  origin: location.origin
3404
3721
  })))))));
3405
3722
  };
3406
3723
 
3407
3724
  // packages/sdk/shell/src/composites/Shell/ShellContext.tsx
3408
- import React42, { createContext as createContext2, useCallback as useCallback8, useContext as useContext2, useEffect as useEffect7, useMemo as useMemo6, useState as useState10 } from "react";
3409
- import { ShellDisplay as ShellDisplay2, ShellLayout as ShellLayout3, useClient as useClient7 } from "@dxos/react-client";
3725
+ import React45, { createContext as createContext2, useCallback as useCallback9, useContext as useContext2, useEffect as useEffect8, useMemo as useMemo6, useState as useState11 } from "react";
3726
+ import { ShellDisplay as ShellDisplay2, ShellLayout as ShellLayout3, useClient as useClient8 } from "@dxos/react-client";
3410
3727
  import { useIdentity as useIdentity3 } from "@dxos/react-client/halo";
3411
- import { mx as mx22 } from "@dxos/react-ui-theme";
3728
+ import { mx as mx23 } from "@dxos/react-ui-theme";
3412
3729
 
3413
3730
  // packages/sdk/shell/src/composites/Shell/memory-shell-runtime.ts
3414
3731
  import { Event } from "@dxos/async";
@@ -3444,7 +3761,7 @@ var MemoryShellRuntime = class {
3444
3761
  // packages/sdk/shell/src/composites/Shell/ShellContext.tsx
3445
3762
  var ShellContext = /* @__PURE__ */ createContext2({});
3446
3763
  var useShell = () => {
3447
- const client = useClient7();
3764
+ const client = useClient8();
3448
3765
  const { runtime, setDisplay } = useContext2(ShellContext);
3449
3766
  const setLayout = async (layout, options) => {
3450
3767
  if (runtime) {
@@ -3465,9 +3782,9 @@ var useShell = () => {
3465
3782
  };
3466
3783
  };
3467
3784
  var ShellProvider = ({ space, deviceInvitationCode, spaceInvitationCode, onJoinedSpace, children }) => {
3468
- const client = useClient7();
3785
+ const client = useClient8();
3469
3786
  const identity = useIdentity3();
3470
- const [display, setDisplay] = useState10(!identity || spaceInvitationCode || deviceInvitationCode ? ShellDisplay2.FULLSCREEN : ShellDisplay2.NONE);
3787
+ const [display, setDisplay] = useState11(!identity || spaceInvitationCode || deviceInvitationCode ? ShellDisplay2.FULLSCREEN : ShellDisplay2.NONE);
3471
3788
  const shellRuntime = useMemo6(() => {
3472
3789
  if (client.config.get("runtime.app.env.DX_VAULT") !== "false") {
3473
3790
  return;
@@ -3493,7 +3810,7 @@ var ShellProvider = ({ space, deviceInvitationCode, spaceInvitationCode, onJoine
3493
3810
  spaceInvitationCode,
3494
3811
  deviceInvitationCode
3495
3812
  ]);
3496
- const handleKeyDown = useCallback8((event) => {
3813
+ const handleKeyDown = useCallback9((event) => {
3497
3814
  if (!space || !shellRuntime) {
3498
3815
  return;
3499
3816
  }
@@ -3514,7 +3831,7 @@ var ShellProvider = ({ space, deviceInvitationCode, spaceInvitationCode, onJoine
3514
3831
  space,
3515
3832
  shellRuntime
3516
3833
  ]);
3517
- useEffect7(() => {
3834
+ useEffect8(() => {
3518
3835
  if (!shellRuntime) {
3519
3836
  return;
3520
3837
  }
@@ -3524,7 +3841,7 @@ var ShellProvider = ({ space, deviceInvitationCode, spaceInvitationCode, onJoine
3524
3841
  shellRuntime,
3525
3842
  handleKeyDown
3526
3843
  ]);
3527
- useEffect7(() => {
3844
+ useEffect8(() => {
3528
3845
  if (!shellRuntime) {
3529
3846
  return;
3530
3847
  }
@@ -3537,12 +3854,12 @@ var ShellProvider = ({ space, deviceInvitationCode, spaceInvitationCode, onJoine
3537
3854
  }, [
3538
3855
  shellRuntime
3539
3856
  ]);
3540
- return /* @__PURE__ */ React42.createElement(React42.Fragment, null, shellRuntime && /* @__PURE__ */ React42.createElement("div", {
3541
- className: mx22(display === ShellDisplay2.NONE ? "hidden" : "")
3542
- }, /* @__PURE__ */ React42.createElement(Shell, {
3857
+ return /* @__PURE__ */ React45.createElement(React45.Fragment, null, shellRuntime && /* @__PURE__ */ React45.createElement("div", {
3858
+ className: mx23(display === ShellDisplay2.NONE ? "hidden" : "")
3859
+ }, /* @__PURE__ */ React45.createElement(Shell, {
3543
3860
  runtime: shellRuntime,
3544
3861
  origin: window.location.origin
3545
- })), /* @__PURE__ */ React42.createElement(ShellContext.Provider, {
3862
+ })), /* @__PURE__ */ React45.createElement(ShellContext.Provider, {
3546
3863
  value: {
3547
3864
  runtime: shellRuntime,
3548
3865
  setDisplay