@dxos/shell 0.3.11-main.a8d7a97 → 0.3.11-main.afa73e0

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 (96) hide show
  1. package/dist/bundle/shell.mjs +6989 -6763
  2. package/dist/bundle/shell.mjs.map +1 -1
  3. package/dist/bundle/shell.umd.js +64 -64
  4. package/dist/bundle/shell.umd.js.map +1 -1
  5. package/dist/bundle/style.css +1 -1
  6. package/dist/lib/browser/meta.json +1 -1
  7. package/dist/lib/browser/react.mjs +497 -411
  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/SpaceMemberList.js +1 -1
  12. package/dist/types/src/components/IdentityList/SpaceMemberList.js.map +1 -1
  13. package/dist/types/src/components/Panel/Action.d.ts.map +1 -1
  14. package/dist/types/src/components/Panel/Action.js +3 -18
  15. package/dist/types/src/components/Panel/Action.js.map +1 -1
  16. package/dist/types/src/composites/Shell/Shell.d.ts.map +1 -1
  17. package/dist/types/src/composites/Shell/Shell.js +5 -1
  18. package/dist/types/src/composites/Shell/Shell.js.map +1 -1
  19. package/dist/types/src/panels/IdentityPanel/IdentityPanel.d.ts.map +1 -1
  20. package/dist/types/src/panels/IdentityPanel/IdentityPanel.js +11 -7
  21. package/dist/types/src/panels/IdentityPanel/IdentityPanel.js.map +1 -1
  22. package/dist/types/src/panels/IdentityPanel/IdentityPanelProps.d.ts +12 -2
  23. package/dist/types/src/panels/IdentityPanel/IdentityPanelProps.d.ts.map +1 -1
  24. package/dist/types/src/panels/IdentityPanel/identityMachine.d.ts +1 -1
  25. package/dist/types/src/panels/IdentityPanel/identityMachine.d.ts.map +1 -1
  26. package/dist/types/src/panels/IdentityPanel/identityMachine.js +2 -2
  27. package/dist/types/src/panels/IdentityPanel/identityMachine.js.map +1 -1
  28. package/dist/types/src/panels/IdentityPanel/steps/AgentForm.d.ts +3 -0
  29. package/dist/types/src/panels/IdentityPanel/steps/AgentForm.d.ts.map +1 -0
  30. package/dist/types/src/panels/IdentityPanel/steps/AgentForm.js +26 -0
  31. package/dist/types/src/panels/IdentityPanel/steps/AgentForm.js.map +1 -0
  32. package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.d.ts.map +1 -1
  33. package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.js +1 -1
  34. package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.js.map +1 -1
  35. package/dist/types/src/panels/IdentityPanel/steps/SignOutChooser.d.ts +16 -0
  36. package/dist/types/src/panels/IdentityPanel/steps/SignOutChooser.d.ts.map +1 -0
  37. package/dist/types/src/panels/IdentityPanel/steps/SignOutChooser.js +40 -0
  38. package/dist/types/src/panels/IdentityPanel/steps/SignOutChooser.js.map +1 -0
  39. package/dist/types/src/panels/IdentityPanel/steps/index.d.ts +2 -1
  40. package/dist/types/src/panels/IdentityPanel/steps/index.d.ts.map +1 -1
  41. package/dist/types/src/panels/IdentityPanel/steps/index.js +2 -1
  42. package/dist/types/src/panels/IdentityPanel/steps/index.js.map +1 -1
  43. package/dist/types/src/panels/IdentityPanel/useAgentHandlers.d.ts +15 -0
  44. package/dist/types/src/panels/IdentityPanel/useAgentHandlers.d.ts.map +1 -0
  45. package/dist/types/src/panels/IdentityPanel/useAgentHandlers.js +78 -0
  46. package/dist/types/src/panels/IdentityPanel/useAgentHandlers.js.map +1 -0
  47. package/dist/types/src/panels/JoinPanel/joinMachine.d.ts +1 -1
  48. package/dist/types/src/panels/JoinPanel/joinMachine.d.ts.map +1 -1
  49. package/dist/types/src/panels/JoinPanel/joinMachine.js +14 -17
  50. package/dist/types/src/panels/JoinPanel/joinMachine.js.map +1 -1
  51. package/dist/types/src/panels/JoinPanel/steps/AdditionMethodChooser.js +3 -3
  52. package/dist/types/src/panels/JoinPanel/steps/AdditionMethodChooser.js.map +1 -1
  53. package/dist/types/src/panels/JoinPanel/steps/InvitationInput.d.ts.map +1 -1
  54. package/dist/types/src/panels/JoinPanel/steps/InvitationInput.js +13 -6
  55. package/dist/types/src/panels/JoinPanel/steps/InvitationInput.js.map +1 -1
  56. package/dist/types/src/panels/JoinPanel/steps/ResetIdentity.js +1 -1
  57. package/dist/types/src/panels/JoinPanel/steps/ResetIdentity.js.map +1 -1
  58. package/dist/types/src/playwright/invitations-manager.d.ts +1 -0
  59. package/dist/types/src/playwright/invitations-manager.d.ts.map +1 -1
  60. package/dist/types/src/playwright/invitations-manager.js +4 -1
  61. package/dist/types/src/playwright/invitations-manager.js.map +1 -1
  62. package/dist/types/src/playwright/invitations.spec.js +15 -0
  63. package/dist/types/src/playwright/invitations.spec.js.map +1 -1
  64. package/dist/types/src/testing/shell-manager.d.ts +5 -4
  65. package/dist/types/src/testing/shell-manager.d.ts.map +1 -1
  66. package/dist/types/src/testing/shell-manager.js +36 -12
  67. package/dist/types/src/testing/shell-manager.js.map +1 -1
  68. package/dist/types/src/translations/locales/en-US.d.ts +5 -0
  69. package/dist/types/src/translations/locales/en-US.d.ts.map +1 -1
  70. package/dist/types/src/translations/locales/en-US.js +5 -0
  71. package/dist/types/src/translations/locales/en-US.js.map +1 -1
  72. package/package.json +21 -21
  73. package/src/components/IdentityList/SpaceMemberList.tsx +1 -1
  74. package/src/components/Panel/Action.tsx +4 -19
  75. package/src/composites/Shell/Shell.tsx +7 -1
  76. package/src/panels/IdentityPanel/IdentityPanel.tsx +21 -10
  77. package/src/panels/IdentityPanel/IdentityPanelProps.ts +15 -2
  78. package/src/panels/IdentityPanel/identityMachine.ts +3 -3
  79. package/src/panels/IdentityPanel/steps/AgentForm.tsx +61 -0
  80. package/src/panels/IdentityPanel/steps/IdentityActionChooser.tsx +2 -3
  81. package/src/panels/IdentityPanel/steps/SignOutChooser.tsx +84 -0
  82. package/src/panels/IdentityPanel/steps/index.ts +2 -1
  83. package/src/panels/IdentityPanel/useAgentHandlers.ts +88 -0
  84. package/src/panels/JoinPanel/joinMachine.ts +15 -18
  85. package/src/panels/JoinPanel/steps/AdditionMethodChooser.tsx +3 -3
  86. package/src/panels/JoinPanel/steps/InvitationInput.tsx +7 -1
  87. package/src/panels/JoinPanel/steps/ResetIdentity.tsx +1 -1
  88. package/src/playwright/invitations-manager.ts +5 -1
  89. package/src/playwright/invitations.spec.ts +19 -0
  90. package/src/testing/shell-manager.ts +40 -13
  91. package/src/translations/locales/en-US.ts +5 -0
  92. package/dist/types/src/panels/IdentityPanel/steps/AgentPanel.d.ts +0 -19
  93. package/dist/types/src/panels/IdentityPanel/steps/AgentPanel.d.ts.map +0 -1
  94. package/dist/types/src/panels/IdentityPanel/steps/AgentPanel.js +0 -122
  95. package/dist/types/src/panels/IdentityPanel/steps/AgentPanel.js.map +0 -1
  96. package/src/panels/IdentityPanel/steps/AgentPanel.tsx +0 -165
@@ -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 React39 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 React26, { useEffect as useEffect3, 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
- import { useClient as useClient4 } from "@dxos/react-client";
824
- import { useIdentity, useDevices } from "@dxos/react-client/halo";
815
+ import { useClient as useClient3 } from "@dxos/react-client";
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 useTranslation12 } 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";
@@ -871,7 +863,8 @@ var identityMachine = createMachine({
871
863
  actions: "log"
872
864
  }
873
865
  }
874
- }
866
+ },
867
+ signingOut: {}
875
868
  },
876
869
  on: {
877
870
  unchooseAction: {
@@ -903,6 +896,10 @@ var identityMachine = createMachine({
903
896
  target: ".managingProfile",
904
897
  actions: "log"
905
898
  },
899
+ chooseSignOut: {
900
+ target: ".signingOut",
901
+ actions: "log"
902
+ },
906
903
  chooseAgent: {
907
904
  target: ".managingAgent",
908
905
  actions: "log"
@@ -946,18 +943,51 @@ var useIdentityMachine = (client, options) => {
946
943
  });
947
944
  };
948
945
 
949
- // packages/sdk/shell/src/panels/IdentityPanel/steps/DeviceManager.tsx
946
+ // packages/sdk/shell/src/panels/IdentityPanel/steps/AgentForm.tsx
950
947
  import React21 from "react";
951
948
  import { useTranslation as useTranslation7 } from "@dxos/react-ui";
952
- var DeviceManager = ({ devices, active, send }) => {
953
- const { t } = useTranslation7("os");
949
+ var AgentForm = (props) => {
950
+ const { active, onAgentCreate, onAgentDestroy, send, validationMessage, agentStatus, agentActive, agentProviderDisabled } = props;
954
951
  const disabled = !active;
952
+ const { t } = useTranslation7("os");
955
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", {
956
986
  role: "none",
957
987
  className: "grow"
958
- }, /* @__PURE__ */ React21.createElement(DeviceList, {
988
+ }, /* @__PURE__ */ React22.createElement(DeviceList, {
959
989
  devices
960
- })), /* @__PURE__ */ React21.createElement(Actions, null, /* @__PURE__ */ React21.createElement(Action, {
990
+ })), /* @__PURE__ */ React22.createElement(Actions, null, /* @__PURE__ */ React22.createElement(Action, {
961
991
  variant: "ghost",
962
992
  disabled,
963
993
  onClick: () => send?.({
@@ -969,11 +999,11 @@ var DeviceManager = ({ devices, active, send }) => {
969
999
 
970
1000
  // packages/sdk/shell/src/panels/IdentityPanel/steps/IdentityActionChooser.tsx
971
1001
  import { CaretRight, Devices, Plus, Power, UserGear, HardDrive } from "@phosphor-icons/react";
972
- import React22, { useCallback as useCallback4 } from "react";
1002
+ import React23, { useCallback as useCallback4 } from "react";
973
1003
  import { useClient as useClient2 } from "@dxos/react-client";
974
1004
  import { useHaloInvitations } from "@dxos/react-client/halo";
975
1005
  import { Invitation as Invitation3, InvitationEncoder } from "@dxos/react-client/invitations";
976
- import { DensityProvider, useTranslation as useTranslation8 } from "@dxos/react-ui";
1006
+ import { DensityProvider, useTranslation as useTranslation9 } from "@dxos/react-ui";
977
1007
  import { getSize as getSize6 } from "@dxos/react-ui-theme";
978
1008
  var IdentityActionChooser = (props) => {
979
1009
  const { send } = props;
@@ -1003,95 +1033,95 @@ var IdentityActionChooser = (props) => {
1003
1033
  invitation
1004
1034
  });
1005
1035
  };
1006
- return /* @__PURE__ */ React22.createElement(IdentityActionChooserImpl, {
1036
+ return /* @__PURE__ */ React23.createElement(IdentityActionChooserImpl, {
1007
1037
  ...props,
1008
1038
  onCreateInvitationClick: (e) => createInvitation(e)
1009
1039
  });
1010
1040
  };
1011
1041
  var IdentityActionChooserImpl = ({ onCreateInvitationClick, active, send, onDone, doneActionParent }) => {
1012
- const { t } = useTranslation8("os");
1013
- return /* @__PURE__ */ React22.createElement("div", {
1042
+ const { t } = useTranslation9("os");
1043
+ return /* @__PURE__ */ React23.createElement("div", {
1014
1044
  role: "none",
1015
1045
  className: "grow flex flex-col gap-1"
1016
- }, /* @__PURE__ */ React22.createElement(DensityProvider, {
1046
+ }, /* @__PURE__ */ React23.createElement(DensityProvider, {
1017
1047
  density: "coarse"
1018
- }, /* @__PURE__ */ React22.createElement("div", {
1048
+ }, /* @__PURE__ */ React23.createElement("div", {
1019
1049
  className: "grow justify-center flex flex-col gap-1"
1020
- }, /* @__PURE__ */ React22.createElement(Action, {
1050
+ }, /* @__PURE__ */ React23.createElement(Action, {
1021
1051
  "data-testid": "manage-agent",
1022
1052
  onClick: () => send?.({
1023
1053
  type: "chooseAgent"
1024
1054
  }),
1025
1055
  classNames: "plb-4"
1026
- }, /* @__PURE__ */ React22.createElement(HardDrive, {
1056
+ }, /* @__PURE__ */ React23.createElement(HardDrive, {
1027
1057
  className: getSize6(6)
1028
- }), /* @__PURE__ */ React22.createElement("span", {
1058
+ }), /* @__PURE__ */ React23.createElement("span", {
1029
1059
  className: "grow mli-3"
1030
- }, "Manage Agent"), /* @__PURE__ */ React22.createElement(CaretRight, {
1060
+ }, "Manage Agent"), /* @__PURE__ */ React23.createElement(CaretRight, {
1031
1061
  weight: "bold",
1032
1062
  className: getSize6(4)
1033
- })), /* @__PURE__ */ React22.createElement(Action, {
1063
+ })), /* @__PURE__ */ React23.createElement(Action, {
1034
1064
  disabled: !active,
1035
1065
  "data-testid": "devices-panel.create-invitation",
1036
1066
  onClick: onCreateInvitationClick,
1037
1067
  classNames: "plb-4"
1038
- }, /* @__PURE__ */ React22.createElement(Plus, {
1068
+ }, /* @__PURE__ */ React23.createElement(Plus, {
1039
1069
  className: getSize6(6)
1040
- }), /* @__PURE__ */ React22.createElement("span", {
1070
+ }), /* @__PURE__ */ React23.createElement("span", {
1041
1071
  className: "grow mli-3"
1042
- }, t("choose add device label")), /* @__PURE__ */ React22.createElement(CaretRight, {
1072
+ }, t("choose add device label")), /* @__PURE__ */ React23.createElement(CaretRight, {
1043
1073
  weight: "bold",
1044
1074
  className: getSize6(4)
1045
- })), /* @__PURE__ */ React22.createElement(Action, {
1075
+ })), /* @__PURE__ */ React23.createElement(Action, {
1046
1076
  "data-testid": "manage-devices",
1047
1077
  onClick: () => send?.({
1048
1078
  type: "chooseDevices"
1049
1079
  }),
1050
1080
  classNames: "plb-4"
1051
- }, /* @__PURE__ */ React22.createElement(Devices, {
1081
+ }, /* @__PURE__ */ React23.createElement(Devices, {
1052
1082
  className: getSize6(6)
1053
- }), /* @__PURE__ */ React22.createElement("span", {
1083
+ }), /* @__PURE__ */ React23.createElement("span", {
1054
1084
  className: "grow mli-3"
1055
- }, t("choose devices label")), /* @__PURE__ */ React22.createElement(CaretRight, {
1085
+ }, t("choose devices label")), /* @__PURE__ */ React23.createElement(CaretRight, {
1056
1086
  weight: "bold",
1057
1087
  className: getSize6(4)
1058
- })), /* @__PURE__ */ React22.createElement(Action, {
1088
+ })), /* @__PURE__ */ React23.createElement(Action, {
1059
1089
  "data-testid": "manage-profile",
1060
1090
  onClick: () => send?.({
1061
1091
  type: "chooseProfile"
1062
1092
  }),
1063
1093
  classNames: "plb-4"
1064
- }, /* @__PURE__ */ React22.createElement(UserGear, {
1094
+ }, /* @__PURE__ */ React23.createElement(UserGear, {
1065
1095
  className: getSize6(6)
1066
- }), /* @__PURE__ */ React22.createElement("span", {
1096
+ }), /* @__PURE__ */ React23.createElement("span", {
1067
1097
  className: "grow mli-3"
1068
- }, t("choose profile label")), /* @__PURE__ */ React22.createElement(CaretRight, {
1098
+ }, t("choose profile label")), /* @__PURE__ */ React23.createElement(CaretRight, {
1069
1099
  weight: "bold",
1070
1100
  className: getSize6(4)
1071
- })), /* @__PURE__ */ React22.createElement(Action, {
1072
- disabled: true,
1073
- "data-testid": "sign-out",
1074
- onClick: () => {
1075
- },
1101
+ })), /* @__PURE__ */ React23.createElement(Action, {
1102
+ "data-testid": "devices-panel.sign-out",
1103
+ onClick: () => send?.({
1104
+ type: "chooseSignOut"
1105
+ }),
1076
1106
  classNames: "plb-4"
1077
- }, /* @__PURE__ */ React22.createElement(Power, {
1107
+ }, /* @__PURE__ */ React23.createElement(Power, {
1078
1108
  className: getSize6(6)
1079
- }), /* @__PURE__ */ React22.createElement("span", {
1109
+ }), /* @__PURE__ */ React23.createElement("span", {
1080
1110
  className: "grow mli-3"
1081
- }, t("choose sign out label")), /* @__PURE__ */ React22.createElement(CaretRight, {
1111
+ }, t("choose sign out label")), /* @__PURE__ */ React23.createElement(CaretRight, {
1082
1112
  weight: "bold",
1083
1113
  className: getSize6(4)
1084
1114
  })))));
1085
1115
  };
1086
1116
 
1087
1117
  // packages/sdk/shell/src/panels/IdentityPanel/steps/ProfileForm.tsx
1088
- import React23, { useState as useState3 } from "react";
1118
+ import React24, { useState as useState3 } from "react";
1089
1119
  import { log as log2 } from "@dxos/log";
1090
- import { useTranslation as useTranslation9 } from "@dxos/react-ui";
1120
+ import { useTranslation as useTranslation10 } from "@dxos/react-ui";
1091
1121
  var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/IdentityPanel/steps/ProfileForm.tsx";
1092
1122
  var ProfileForm = (props) => {
1093
1123
  const { onUpdateProfile } = props;
1094
- const { t } = useTranslation9("os");
1124
+ const { t } = useTranslation10("os");
1095
1125
  const [validationMessage, setValidationMessage] = useState3("");
1096
1126
  const handleUpdateProfile = async (profile) => {
1097
1127
  await onUpdateProfile?.(profile).catch((error) => {
@@ -1104,7 +1134,7 @@ var ProfileForm = (props) => {
1104
1134
  setValidationMessage(t("failed to update profile message"));
1105
1135
  });
1106
1136
  };
1107
- return /* @__PURE__ */ React23.createElement(ProfileFormImpl, {
1137
+ return /* @__PURE__ */ React24.createElement(ProfileFormImpl, {
1108
1138
  ...props,
1109
1139
  onUpdateProfile: handleUpdateProfile,
1110
1140
  validationMessage
@@ -1113,14 +1143,14 @@ var ProfileForm = (props) => {
1113
1143
  var ProfileFormImpl = (props) => {
1114
1144
  const { active, profile, send, onUpdateProfile, validationMessage } = props;
1115
1145
  const disabled = !active;
1116
- const { t } = useTranslation9("os");
1146
+ const { t } = useTranslation10("os");
1117
1147
  const [inputValue, setInputValue] = useState3(profile?.displayName ?? "");
1118
- return /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement("div", {
1148
+ return /* @__PURE__ */ React24.createElement(React24.Fragment, null, /* @__PURE__ */ React24.createElement("div", {
1119
1149
  role: "none",
1120
1150
  className: "grow flex flex-col justify-center"
1121
- }, /* @__PURE__ */ React23.createElement(Input, {
1151
+ }, /* @__PURE__ */ React24.createElement(Input, {
1122
1152
  validationMessage,
1123
- label: /* @__PURE__ */ React23.createElement(StepHeading, null, t("display name input label")),
1153
+ label: /* @__PURE__ */ React24.createElement(StepHeading, null, t("display name input label")),
1124
1154
  disabled,
1125
1155
  "data-testid": "display-name-input",
1126
1156
  placeholder: t("display name input placeholder"),
@@ -1129,14 +1159,14 @@ var ProfileFormImpl = (props) => {
1129
1159
  onKeyDown: ({ key }) => key === "Enter" && onUpdateProfile?.({
1130
1160
  displayName: inputValue
1131
1161
  })
1132
- })), /* @__PURE__ */ React23.createElement(Actions, null, /* @__PURE__ */ React23.createElement(Action, {
1162
+ })), /* @__PURE__ */ React24.createElement(Actions, null, /* @__PURE__ */ React24.createElement(Action, {
1133
1163
  variant: "ghost",
1134
1164
  disabled,
1135
1165
  onClick: () => send?.({
1136
1166
  type: "unchooseAction"
1137
1167
  }),
1138
1168
  "data-testid": "update-profile-form-back"
1139
- }, t("back label")), /* @__PURE__ */ React23.createElement(Action, {
1169
+ }, t("back label")), /* @__PURE__ */ React24.createElement(Action, {
1140
1170
  variant: "primary",
1141
1171
  disabled,
1142
1172
  onClick: () => onUpdateProfile?.({
@@ -1146,21 +1176,64 @@ var ProfileFormImpl = (props) => {
1146
1176
  }, t("done label"))));
1147
1177
  };
1148
1178
 
1149
- // packages/sdk/shell/src/panels/IdentityPanel/steps/AgentPanel.tsx
1150
- import React24, { useState as useState4, useCallback as useCallback5, useEffect as useEffect2 } from "react";
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";
1151
1229
  import { invariant } from "@dxos/invariant";
1152
- import { useClient as useClient3, useAgentHostingProviderClient } from "@dxos/react-client";
1153
- import { useHaloInvitations as useHaloInvitations2 } from "@dxos/react-client/halo";
1230
+ import { useAgentHostingProviderClient } from "@dxos/react-client";
1154
1231
  import { Invitation as Invitation4, InvitationEncoder as InvitationEncoder2 } from "@dxos/react-client/invitations";
1155
- import { useTranslation as useTranslation10 } from "@dxos/react-ui";
1156
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/IdentityPanel/steps/AgentPanel.tsx";
1157
- var AgentForm = (props) => {
1158
- const { identity } = props;
1232
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/IdentityPanel/useAgentHandlers.ts";
1233
+ var useAgentHandlers = ({ client, invitations, identity }) => {
1159
1234
  const [validationMessage, setValidationMessage] = useState4("");
1160
1235
  const [agentStatus, setAgentStatus] = useState4("");
1161
1236
  const [agentActive, setAgentActive] = useState4(false);
1162
- const client = useClient3();
1163
- const invitations = useHaloInvitations2();
1164
1237
  const agentHostingProviderClient = useAgentHostingProviderClient(client.config);
1165
1238
  useEffect2(() => {
1166
1239
  const fetchAgentStatus = async () => {
@@ -1179,7 +1252,7 @@ var AgentForm = (props) => {
1179
1252
  };
1180
1253
  void fetchAgentStatus();
1181
1254
  }, []);
1182
- const onAgentCreateEvent = useCallback5(async (invitation) => {
1255
+ const handleAgentCreate = useCallback5(async (invitation) => {
1183
1256
  const invitationCode = InvitationEncoder2.encode(invitation);
1184
1257
  if (invitation.state === Invitation4.State.CONNECTING) {
1185
1258
  console.log(JSON.stringify({
@@ -1188,7 +1261,7 @@ var AgentForm = (props) => {
1188
1261
  }));
1189
1262
  invariant(identity, "Identity not found", {
1190
1263
  F: __dxlog_file3,
1191
- L: 65,
1264
+ L: 50,
1192
1265
  S: void 0,
1193
1266
  A: [
1194
1267
  "identity",
@@ -1207,19 +1280,19 @@ var AgentForm = (props) => {
1207
1280
  }
1208
1281
  }
1209
1282
  }, []);
1210
- const handleAgentCreate = async () => {
1283
+ const onAgentCreate = async () => {
1211
1284
  invitations.forEach((invitation2) => invitation2.cancel());
1212
1285
  const invitation = client.halo.share({
1213
1286
  type: Invitation4.Type.MULTIUSE,
1214
1287
  authMethod: Invitation4.AuthMethod.NONE
1215
1288
  });
1216
- invitation.subscribe(onAgentCreateEvent);
1289
+ invitation.subscribe(handleAgentCreate);
1217
1290
  };
1218
- const handleAgentDestroy = async () => {
1291
+ const onAgentDestroy = async () => {
1219
1292
  const identity2 = client.halo.identity.get();
1220
1293
  invariant(identity2, "Identity not found", {
1221
1294
  F: __dxlog_file3,
1222
- L: 91,
1295
+ L: 76,
1223
1296
  S: void 0,
1224
1297
  A: [
1225
1298
  "identity",
@@ -1235,61 +1308,30 @@ var AgentForm = (props) => {
1235
1308
  setValidationMessage(`error destroying agent: ${err.message}`);
1236
1309
  }
1237
1310
  };
1238
- return /* @__PURE__ */ React24.createElement(AgentFormImpl, {
1239
- ...props,
1240
- onAgentCreate: handleAgentCreate,
1241
- onAgentDestroy: handleAgentDestroy,
1311
+ return {
1312
+ onAgentCreate,
1313
+ onAgentDestroy,
1242
1314
  validationMessage,
1243
1315
  agentStatus,
1244
- agentActive,
1245
- agentProviderDisabled: !agentHostingProviderClient
1246
- });
1247
- };
1248
- var AgentFormImpl = (props) => {
1249
- const { active, onAgentCreate, onAgentDestroy, send, validationMessage, agentStatus, agentActive, agentProviderDisabled } = props;
1250
- const disabled = !active;
1251
- const { t } = useTranslation10("os");
1252
- return /* @__PURE__ */ React24.createElement(React24.Fragment, null, /* @__PURE__ */ React24.createElement("div", {
1253
- role: "none",
1254
- className: "grow flex flex-col justify-center"
1255
- }, /* @__PURE__ */ React24.createElement(Input, {
1256
- validationMessage,
1257
- label: /* @__PURE__ */ React24.createElement(StepHeading, null, "Agent Status"),
1258
- disabled,
1259
- "data-testid": "agent-status",
1260
- value: agentStatus
1261
- })), /* @__PURE__ */ React24.createElement(Actions, null, /* @__PURE__ */ React24.createElement(Action, {
1262
- disabled: agentActive || agentProviderDisabled,
1263
- onClick: () => onAgentCreate?.(),
1264
- "data-testid": "create-agent"
1265
- }, "Create Agent"), /* @__PURE__ */ React24.createElement(Action, {
1266
- disabled: !agentActive || agentProviderDisabled,
1267
- onClick: () => onAgentDestroy?.(),
1268
- "data-testid": "destroy-agent"
1269
- }, "Destroy Agent"), /* @__PURE__ */ React24.createElement(Action, {
1270
- disabled,
1271
- onClick: () => send?.({
1272
- type: "unchooseAction"
1273
- }),
1274
- "data-testid": "update-profile-form-back"
1275
- }, t("back label"))));
1316
+ agentActive
1317
+ };
1276
1318
  };
1277
1319
 
1278
1320
  // packages/sdk/shell/src/steps/InvitationManager.tsx
1279
1321
  import { Check as Check3, X as X3 } from "@phosphor-icons/react";
1280
- import React25, { useMemo as useMemo2 } from "react";
1322
+ import React26, { useMemo as useMemo2 } from "react";
1281
1323
  import { QR } from "react-qr-rounded";
1282
1324
  import { Invitation as Invitation5 } from "@dxos/react-client/invitations";
1283
- import { useId as useId4, useTranslation as useTranslation11 } from "@dxos/react-ui";
1284
- import { descriptionText as descriptionText7, getSize as getSize7, mx as mx18 } from "@dxos/react-ui-theme";
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";
1285
1327
  var InvitationManagerView = ({ children, ...props }) => {
1286
- return /* @__PURE__ */ React25.createElement(Viewport.View, {
1328
+ return /* @__PURE__ */ React26.createElement(Viewport.View, {
1287
1329
  ...props,
1288
1330
  classNames: "grow flex flex-col justify-around items-center"
1289
1331
  }, children);
1290
1332
  };
1291
1333
  var InvitationManager = ({ invitationUrl, active, send, status, type, authCode, id }) => {
1292
- const { t } = useTranslation11("os");
1334
+ const { t } = useTranslation12("os");
1293
1335
  const qrLabel = useId4("invitation-manager__qr-code");
1294
1336
  const statusValue = type === Invitation5.Type.MULTIUSE ? 0 : invitationStatusValue.get(status) ?? 0;
1295
1337
  const showAuthCode = statusValue === 3;
@@ -1307,50 +1349,50 @@ var InvitationManager = ({ invitationUrl, active, send, status, type, authCode,
1307
1349
  }, [
1308
1350
  statusValue
1309
1351
  ]);
1310
- return /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement(Viewport.Root, {
1352
+ return /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(Viewport.Root, {
1311
1353
  activeView,
1312
1354
  classNames: "grow plb-1"
1313
- }, /* @__PURE__ */ React25.createElement(Viewport.Views, null, /* @__PURE__ */ React25.createElement(InvitationManagerView, {
1355
+ }, /* @__PURE__ */ React26.createElement(Viewport.Views, null, /* @__PURE__ */ React26.createElement(InvitationManagerView, {
1314
1356
  id: "showing qr",
1315
1357
  emoji: emoji2
1316
- }, /* @__PURE__ */ React25.createElement("p", {
1358
+ }, /* @__PURE__ */ React26.createElement("p", {
1317
1359
  className: "text-sm mlb-1 font-normal text-center"
1318
- }, t(type === Invitation5.Type.MULTIUSE ? "invite many qr label" : "invite one qr label")), /* @__PURE__ */ React25.createElement("div", {
1360
+ }, t(type === Invitation5.Type.MULTIUSE ? "invite many qr label" : "invite one qr label")), /* @__PURE__ */ React26.createElement("div", {
1319
1361
  role: "none",
1320
- className: mx18(descriptionText7, "is-full max-is-[14rem] relative")
1321
- }, /* @__PURE__ */ React25.createElement(QR, {
1362
+ className: mx19(descriptionText7, "is-full max-is-[14rem] relative")
1363
+ }, /* @__PURE__ */ React26.createElement(QR, {
1322
1364
  rounding: 100,
1323
1365
  backgroundColor: "transparent",
1324
1366
  color: "currentColor",
1325
- className: mx18("is-full bs-full p-2", showAuthCode && "invisible"),
1367
+ className: mx19("is-full bs-full p-2", showAuthCode && "invisible"),
1326
1368
  "aria-labelledby": qrLabel,
1327
1369
  errorCorrectionLevel: "Q",
1328
1370
  cutout: true
1329
- }, invitationUrl ?? "never"), /* @__PURE__ */ React25.createElement(Centered, null, /* @__PURE__ */ React25.createElement(Emoji, {
1371
+ }, invitationUrl ?? "never"), /* @__PURE__ */ React26.createElement(Centered, null, /* @__PURE__ */ React26.createElement(Emoji, {
1330
1372
  text: emoji2
1331
- }))), /* @__PURE__ */ React25.createElement("span", {
1373
+ }))), /* @__PURE__ */ React26.createElement("span", {
1332
1374
  id: qrLabel,
1333
1375
  className: "sr-only"
1334
- }, t("qr label")), /* @__PURE__ */ React25.createElement(CopyButton, {
1376
+ }, t("qr label")), /* @__PURE__ */ React26.createElement(CopyButton, {
1335
1377
  variant: "ghost",
1336
1378
  value: invitationUrl ?? "never"
1337
- })), /* @__PURE__ */ React25.createElement(InvitationManagerView, {
1379
+ })), /* @__PURE__ */ React26.createElement(InvitationManagerView, {
1338
1380
  id: "showing auth code"
1339
- }, /* @__PURE__ */ React25.createElement(Label, null, t("auth code message")), /* @__PURE__ */ React25.createElement(AuthCode, {
1381
+ }, /* @__PURE__ */ React26.createElement(Label, null, t("auth code message")), /* @__PURE__ */ React26.createElement(AuthCode, {
1340
1382
  code: authCode,
1341
1383
  large: true,
1342
1384
  classNames: "text-black dark:text-white"
1343
- }), /* @__PURE__ */ React25.createElement(Label, null, "Be sure the other device is showing this symbol:"), emoji2 && /* @__PURE__ */ React25.createElement(Emoji, {
1385
+ }), /* @__PURE__ */ React26.createElement(Label, null, "Be sure the other device is showing this symbol:"), emoji2 && /* @__PURE__ */ React26.createElement(Emoji, {
1344
1386
  text: emoji2
1345
- })), /* @__PURE__ */ React25.createElement(InvitationManagerView, {
1387
+ })), /* @__PURE__ */ React26.createElement(InvitationManagerView, {
1346
1388
  id: "showing final"
1347
- }, statusValue > 0 ? /* @__PURE__ */ React25.createElement(Check3, {
1348
- className: mx18("m-1.5", getSize7(6))
1349
- }) : /* @__PURE__ */ React25.createElement(X3, {
1350
- className: mx18("m-1.5", getSize7(6))
1351
- })))), /* @__PURE__ */ React25.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, {
1352
1394
  classNames: "mbs-4"
1353
- }, /* @__PURE__ */ React25.createElement(Action, {
1395
+ }, /* @__PURE__ */ React26.createElement(Action, {
1354
1396
  disabled: !active,
1355
1397
  onClick: () => send?.({
1356
1398
  type: "deselectInvitation"
@@ -1363,27 +1405,28 @@ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/I
1363
1405
  var viewStyles = "pbs-1 pbe-3 pli-3";
1364
1406
  var IdentityHeading = ({ titleId, title, identity, onDone }) => {
1365
1407
  const fallbackHref = useJdenticonHref3(identity.identityKey.toHex(), 12);
1366
- return /* @__PURE__ */ React26.createElement(Heading, {
1408
+ return /* @__PURE__ */ React27.createElement(Heading, {
1367
1409
  titleId,
1368
1410
  title,
1369
- corner: /* @__PURE__ */ React26.createElement(CloseButton, {
1411
+ corner: /* @__PURE__ */ React27.createElement(CloseButton, {
1370
1412
  onDone
1371
1413
  })
1372
- }, /* @__PURE__ */ React26.createElement(Avatar4.Root, {
1414
+ }, /* @__PURE__ */ React27.createElement(Avatar4.Root, {
1373
1415
  size: 12,
1374
1416
  variant: "circle",
1375
1417
  status: "active"
1376
- }, /* @__PURE__ */ React26.createElement(Avatar4.Frame, {
1418
+ }, /* @__PURE__ */ React27.createElement(Avatar4.Frame, {
1377
1419
  classNames: "block mbs-4 mbe-2 mli-auto chromatic-ignore"
1378
- }, /* @__PURE__ */ React26.createElement(Avatar4.Fallback, {
1420
+ }, /* @__PURE__ */ React27.createElement(Avatar4.Fallback, {
1379
1421
  href: fallbackHref
1380
- })), /* @__PURE__ */ React26.createElement(Avatar4.Label, {
1381
- 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"
1382
1425
  }, identity.profile?.displayName ?? generateName2(identity.identityKey.toHex()))));
1383
1426
  };
1384
1427
  var IdentityPanelImpl = (props) => {
1385
- const { identity, titleId, activeView, onUpdateProfile, IdentityActionChooser: IdentityActionChooserComponent = IdentityActionChooser, InvitationManager: InvitationManagerComponent = InvitationManager, onDone, ...rest } = props;
1386
- const { t } = useTranslation12("os");
1428
+ const { identity, titleId, activeView, onUpdateProfile, onResetDevice, onJoinNewIdentity, IdentityActionChooser: IdentityActionChooserComponent = IdentityActionChooser, InvitationManager: InvitationManagerComponent = InvitationManager, onDone, ...rest } = props;
1429
+ const { t } = useTranslation13("os");
1387
1430
  const title = useMemo3(() => {
1388
1431
  switch (activeView) {
1389
1432
  case "agent manager":
@@ -1397,66 +1440,77 @@ var IdentityPanelImpl = (props) => {
1397
1440
  activeView,
1398
1441
  t
1399
1442
  ]);
1400
- console.log("[IdentityPanelImpl]", {
1401
- activeView
1402
- });
1403
- return /* @__PURE__ */ React26.createElement(DensityProvider2, {
1443
+ return /* @__PURE__ */ React27.createElement(DensityProvider2, {
1404
1444
  density: "fine"
1405
- }, /* @__PURE__ */ React26.createElement(IdentityHeading, {
1445
+ }, /* @__PURE__ */ React27.createElement(IdentityHeading, {
1406
1446
  identity,
1407
1447
  titleId,
1408
1448
  title,
1409
1449
  onDone
1410
- }), /* @__PURE__ */ React26.createElement(Viewport.Root, {
1450
+ }), /* @__PURE__ */ React27.createElement(Viewport.Root, {
1411
1451
  activeView
1412
- }, /* @__PURE__ */ React26.createElement(Viewport.Views, null, /* @__PURE__ */ React26.createElement(Viewport.View, {
1452
+ }, /* @__PURE__ */ React27.createElement(Viewport.Views, null, /* @__PURE__ */ React27.createElement(Viewport.View, {
1413
1453
  id: "identity action chooser",
1414
1454
  classNames: viewStyles
1415
- }, /* @__PURE__ */ React26.createElement(IdentityActionChooserComponent, {
1455
+ }, /* @__PURE__ */ React27.createElement(IdentityActionChooserComponent, {
1416
1456
  active: activeView === "identity action chooser",
1417
1457
  ...rest
1418
- })), /* @__PURE__ */ React26.createElement(Viewport.View, {
1458
+ })), /* @__PURE__ */ React27.createElement(Viewport.View, {
1419
1459
  id: "device invitation manager",
1420
1460
  classNames: viewStyles
1421
- }, /* @__PURE__ */ React26.createElement(InvitationManagerComponent, {
1461
+ }, /* @__PURE__ */ React27.createElement(InvitationManagerComponent, {
1422
1462
  active: activeView === "device invitation manager",
1423
1463
  ...rest,
1424
1464
  invitationUrl: rest.createInvitationUrl(rest.invitationCode)
1425
- })), /* @__PURE__ */ React26.createElement(Viewport.View, {
1465
+ })), /* @__PURE__ */ React27.createElement(Viewport.View, {
1426
1466
  id: "device manager",
1427
1467
  classNames: viewStyles
1428
- }, /* @__PURE__ */ React26.createElement(DeviceManager, {
1468
+ }, /* @__PURE__ */ React27.createElement(DeviceManager, {
1429
1469
  active: activeView === "device manager",
1430
1470
  ...rest
1431
- })), /* @__PURE__ */ React26.createElement(Viewport.View, {
1471
+ })), /* @__PURE__ */ React27.createElement(Viewport.View, {
1432
1472
  classNames: viewStyles,
1433
1473
  id: "update profile form"
1434
- }, /* @__PURE__ */ React26.createElement(ProfileForm, {
1474
+ }, /* @__PURE__ */ React27.createElement(ProfileForm, {
1435
1475
  send: rest.send,
1436
1476
  active: activeView === "update profile form",
1437
1477
  profile: identity.profile,
1438
1478
  onUpdateProfile
1439
- })), /* @__PURE__ */ React26.createElement(Viewport.View, {
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, {
1440
1488
  classNames: viewStyles,
1441
1489
  id: "agent manager"
1442
- }, /* @__PURE__ */ React26.createElement(AgentForm, {
1490
+ }, /* @__PURE__ */ React27.createElement(AgentForm, {
1443
1491
  send: rest.send,
1444
1492
  active: activeView === "agent manager",
1445
- identity
1493
+ ...rest
1446
1494
  })))));
1447
1495
  };
1448
1496
  var IdentityPanelWithInvitationImpl = ({ invitation, ...props }) => {
1449
1497
  const invitationStatus = useInvitationStatus2(invitation);
1450
- return /* @__PURE__ */ React26.createElement(IdentityPanelImpl, {
1498
+ return /* @__PURE__ */ React27.createElement(IdentityPanelImpl, {
1451
1499
  ...props,
1452
1500
  ...invitationStatus
1453
1501
  });
1454
1502
  };
1455
1503
  var IdentityPanel = ({ titleId: propsTitleId, createInvitationUrl = (code) => code, ...props }) => {
1456
1504
  const titleId = useId5("identityPanel__heading", propsTitleId);
1457
- const client = useClient4();
1505
+ const client = useClient3();
1458
1506
  const devices = useDevices();
1459
1507
  const identity = useIdentity();
1508
+ const invitations = useHaloInvitations2();
1509
+ const agentProps = useAgentHandlers({
1510
+ client,
1511
+ identity,
1512
+ invitations
1513
+ });
1460
1514
  if (!identity) {
1461
1515
  console.error("IdentityPanel rendered with no active identity.");
1462
1516
  return null;
@@ -1466,7 +1520,7 @@ var IdentityPanel = ({ titleId: propsTitleId, createInvitationUrl = (code) => co
1466
1520
  const subscription = identityService.subscribe((state) => {
1467
1521
  log3("[state]", state, {
1468
1522
  F: __dxlog_file4,
1469
- L: 126,
1523
+ L: 138,
1470
1524
  S: void 0,
1471
1525
  C: (f, a) => f(...a)
1472
1526
  });
@@ -1492,6 +1546,8 @@ var IdentityPanel = ({ titleId: propsTitleId, createInvitationUrl = (code) => co
1492
1546
  }
1493
1547
  ].some(identityState.matches):
1494
1548
  return "update profile form";
1549
+ case identityState.matches("signingOut"):
1550
+ return "signing out";
1495
1551
  case [
1496
1552
  {
1497
1553
  managingAgent: "idle"
@@ -1507,10 +1563,6 @@ var IdentityPanel = ({ titleId: propsTitleId, createInvitationUrl = (code) => co
1507
1563
  }, [
1508
1564
  identityState
1509
1565
  ]);
1510
- console.log({
1511
- activeView,
1512
- identityState
1513
- });
1514
1566
  const onUpdateProfile = async (profile) => {
1515
1567
  identitySend({
1516
1568
  type: "updateProfile"
@@ -1525,42 +1577,43 @@ var IdentityPanel = ({ titleId: propsTitleId, createInvitationUrl = (code) => co
1525
1577
  send: identitySend,
1526
1578
  titleId,
1527
1579
  createInvitationUrl,
1528
- onUpdateProfile
1580
+ onUpdateProfile,
1581
+ ...agentProps
1529
1582
  };
1530
- return identityState.context.invitation ? /* @__PURE__ */ React26.createElement(IdentityPanelWithInvitationImpl, {
1583
+ return identityState.context.invitation ? /* @__PURE__ */ React27.createElement(IdentityPanelWithInvitationImpl, {
1531
1584
  ...implProps,
1532
1585
  invitation: identityState.context.invitation
1533
- }) : /* @__PURE__ */ React26.createElement(IdentityPanelImpl, implProps);
1586
+ }) : /* @__PURE__ */ React27.createElement(IdentityPanelImpl, implProps);
1534
1587
  };
1535
1588
 
1536
1589
  // packages/sdk/shell/src/panels/JoinPanel/JoinPanel.tsx
1537
- import React36, { useCallback as useCallback7, useEffect as useEffect5, useMemo as useMemo4 } from "react";
1590
+ import React37, { useCallback as useCallback7, useEffect as useEffect5, useMemo as useMemo4 } from "react";
1538
1591
  import { log as log8 } from "@dxos/log";
1539
- import { useClient as useClient7, useMulticastObservable } from "@dxos/react-client";
1592
+ import { useClient as useClient6, useMulticastObservable } from "@dxos/react-client";
1540
1593
  import { useIdentity as useIdentity2 } from "@dxos/react-client/halo";
1541
1594
  import { DensityProvider as DensityProvider3, useId as useId7, useThemeContext as useThemeContext3 } from "@dxos/react-ui";
1542
1595
 
1543
1596
  // packages/sdk/shell/src/panels/JoinPanel/JoinHeading.tsx
1544
1597
  import { X as X4 } from "@phosphor-icons/react";
1545
- import React27, { cloneElement, forwardRef as forwardRef8 } from "react";
1546
- import { Button as Button5, useTranslation as useTranslation13 } from "@dxos/react-ui";
1547
- 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";
1548
1601
  var JoinHeading = /* @__PURE__ */ forwardRef8(({ mode, titleId, onExit, exitActionParent }, forwardedRef) => {
1549
- const { t } = useTranslation13("os");
1550
- const exitButton = /* @__PURE__ */ React27.createElement(Button5, {
1602
+ const { t } = useTranslation14("os");
1603
+ const exitButton = /* @__PURE__ */ React28.createElement(Button5, {
1551
1604
  variant: "ghost",
1552
1605
  ...onExit && {
1553
1606
  onClick: onExit
1554
1607
  },
1555
- 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]"),
1556
1609
  "data-testid": "join-exit"
1557
- }, /* @__PURE__ */ React27.createElement(X4, {
1610
+ }, /* @__PURE__ */ React28.createElement(X4, {
1558
1611
  weight: "bold",
1559
- className: getSize8(4)
1560
- }), /* @__PURE__ */ React27.createElement("span", {
1612
+ className: getSize9(4)
1613
+ }), /* @__PURE__ */ React28.createElement("span", {
1561
1614
  className: "sr-only"
1562
1615
  }, t("exit label")));
1563
- return /* @__PURE__ */ React27.createElement(Heading, {
1616
+ return /* @__PURE__ */ React28.createElement(Heading, {
1564
1617
  ref: forwardedRef,
1565
1618
  titleId,
1566
1619
  title: t(mode === "halo-only" ? "selecting identity heading" : "joining space heading"),
@@ -1578,6 +1631,7 @@ import { useMachine as useMachine2 } from "@xstate/react";
1578
1631
  import { useCallback as useCallback6 } from "react";
1579
1632
  import { assign as assign2, createMachine as createMachine2 } from "xstate";
1580
1633
  import { log as log4 } from "@dxos/log";
1634
+ import { AlreadyJoinedError } from "@dxos/react-client";
1581
1635
  import { Invitation as Invitation6, InvitationEncoder as InvitationEncoder3 } from "@dxos/react-client/invitations";
1582
1636
  var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/joinMachine.ts";
1583
1637
  var getInvitationSubscribable = (Kind, invitation) => {
@@ -1696,12 +1750,28 @@ var getInvitationSubscribable = (Kind, invitation) => {
1696
1750
  }
1697
1751
  }
1698
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
+ }
1699
1769
  log4.error("[invitation errored]", {
1700
1770
  Kind,
1701
1771
  error
1702
1772
  }, {
1703
1773
  F: __dxlog_file5,
1704
- L: 136,
1774
+ L: 142,
1705
1775
  S: void 0,
1706
1776
  C: (f, a) => f(...a)
1707
1777
  });
@@ -2026,7 +2096,7 @@ var joinMachine = createMachine2({
2026
2096
  spaceInvitation: context.space.invitation
2027
2097
  }, {
2028
2098
  F: __dxlog_file5,
2029
- L: 400,
2099
+ L: 406,
2030
2100
  S: void 0,
2031
2101
  C: (f, a) => f(...a)
2032
2102
  });
@@ -2040,7 +2110,7 @@ var defaultCodeFromUrl = (invitationType, text) => {
2040
2110
  } catch (err) {
2041
2111
  log4.catch(err, void 0, {
2042
2112
  F: __dxlog_file5,
2043
- L: 427,
2113
+ L: 433,
2044
2114
  S: void 0,
2045
2115
  C: (f, a) => f(...a)
2046
2116
  });
@@ -2051,7 +2121,8 @@ var useJoinMachine = (client, options) => {
2051
2121
  const redeemHaloInvitationCode = useCallback6(({ halo }) => {
2052
2122
  if (halo.unredeemedCode) {
2053
2123
  try {
2054
- const invitationObservable = client.halo.join(InvitationEncoder3.decode(defaultCodeFromUrl("halo", halo.unredeemedCode)));
2124
+ const invitation = InvitationEncoder3.decode(defaultCodeFromUrl("halo", halo.unredeemedCode));
2125
+ const invitationObservable = client.halo.join(invitation);
2055
2126
  return {
2056
2127
  ...halo,
2057
2128
  invitationObservable,
@@ -2060,7 +2131,7 @@ var useJoinMachine = (client, options) => {
2060
2131
  } catch (err) {
2061
2132
  log4.error("Could not redeem device invitation code", err, {
2062
2133
  F: __dxlog_file5,
2063
- L: 449,
2134
+ L: 454,
2064
2135
  S: void 0,
2065
2136
  C: (f, a) => f(...a)
2066
2137
  });
@@ -2076,23 +2147,16 @@ var useJoinMachine = (client, options) => {
2076
2147
  if (space.unredeemedCode) {
2077
2148
  try {
2078
2149
  const invitation = InvitationEncoder3.decode(defaultCodeFromUrl("space", space.unredeemedCode));
2079
- if (space.succeededKeys?.has(invitation.spaceKey?.toHex() ?? "never")) {
2080
- return {
2081
- ...space,
2082
- invitation
2083
- };
2084
- } else {
2085
- const invitationObservable = client.spaces.join(invitation);
2086
- return {
2087
- ...space,
2088
- invitationObservable,
2089
- invitationSubscribable: getInvitationSubscribable("Space", invitationObservable)
2090
- };
2091
- }
2150
+ const invitationObservable = client.spaces.join(invitation);
2151
+ return {
2152
+ ...space,
2153
+ invitationObservable,
2154
+ invitationSubscribable: getInvitationSubscribable("Space", invitationObservable)
2155
+ };
2092
2156
  } catch (err) {
2093
2157
  log4.error("Could not redeem space invitation code", err, {
2094
2158
  F: __dxlog_file5,
2095
- L: 479,
2159
+ L: 476,
2096
2160
  S: void 0,
2097
2161
  C: (f, a) => f(...a)
2098
2162
  });
@@ -2152,17 +2216,17 @@ var useJoinMachine = (client, options) => {
2152
2216
 
2153
2217
  // packages/sdk/shell/src/panels/JoinPanel/steps/AdditionMethodChooser.tsx
2154
2218
  import { CaretRight as CaretRight2, Plus as Plus2, QrCode, Textbox } from "@phosphor-icons/react";
2155
- import React28 from "react";
2156
- import { useTranslation as useTranslation14 } from "@dxos/react-ui";
2157
- 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";
2158
2222
  var AdditionMethodChooser = (viewStateProps) => {
2159
2223
  const disabled = !viewStateProps.active;
2160
2224
  const { send } = viewStateProps;
2161
- const { t } = useTranslation14("os");
2225
+ const { t } = useTranslation15("os");
2162
2226
  const sharedButtonProps = {
2163
2227
  disabled,
2164
- after: /* @__PURE__ */ React28.createElement(CaretRight2, {
2165
- className: getSize9(4),
2228
+ after: /* @__PURE__ */ React29.createElement(CaretRight2, {
2229
+ className: getSize10(4),
2166
2230
  weight: "bold"
2167
2231
  }),
2168
2232
  slots: {
@@ -2171,77 +2235,77 @@ var AdditionMethodChooser = (viewStateProps) => {
2171
2235
  }
2172
2236
  }
2173
2237
  };
2174
- return /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement(StepHeading, null, t("addition method chooser title")), /* @__PURE__ */ React28.createElement("div", {
2238
+ return /* @__PURE__ */ React29.createElement(React29.Fragment, null, /* @__PURE__ */ React29.createElement(StepHeading, null, t("addition method chooser title")), /* @__PURE__ */ React29.createElement("div", {
2175
2239
  role: "none",
2176
2240
  className: "flex flex-col gap-1 grow"
2177
- }, /* @__PURE__ */ React28.createElement(CompoundButton, {
2241
+ }, /* @__PURE__ */ React29.createElement(CompoundButton, {
2178
2242
  ...sharedButtonProps,
2179
2243
  description: t("create identity description"),
2180
- before: /* @__PURE__ */ React28.createElement(Plus2, {
2181
- className: getSize9(6)
2244
+ before: /* @__PURE__ */ React29.createElement(Plus2, {
2245
+ className: getSize10(6)
2182
2246
  }),
2183
2247
  onClick: () => send({
2184
2248
  type: "createIdentity"
2185
2249
  }),
2186
2250
  "data-autofocus": "choosingAuthMethod",
2187
- "data-testid": "create-identity"
2188
- }, t("create identity label")), /* @__PURE__ */ React28.createElement(CompoundButton, {
2251
+ "data-testid": "identity-chooser.create-identity"
2252
+ }, t("create identity label")), /* @__PURE__ */ React29.createElement(CompoundButton, {
2189
2253
  ...sharedButtonProps,
2190
2254
  description: t("join identity description"),
2191
- before: /* @__PURE__ */ React28.createElement(QrCode, {
2192
- className: getSize9(6)
2255
+ before: /* @__PURE__ */ React29.createElement(QrCode, {
2256
+ className: getSize10(6)
2193
2257
  }),
2194
2258
  onClick: () => send({
2195
2259
  type: "acceptHaloInvitation"
2196
2260
  }),
2197
- "data-testid": "join-identity"
2198
- }, t("join identity label")), /* @__PURE__ */ React28.createElement(CompoundButton, {
2261
+ "data-testid": "identity-chooser.join-identity"
2262
+ }, t("join identity label")), /* @__PURE__ */ React29.createElement(CompoundButton, {
2199
2263
  ...sharedButtonProps,
2200
2264
  // TODO(mykola): Implement recover.
2201
2265
  disabled: true,
2202
2266
  description: t("recover identity description"),
2203
- before: /* @__PURE__ */ React28.createElement(Textbox, {
2204
- className: getSize9(6)
2267
+ before: /* @__PURE__ */ React29.createElement(Textbox, {
2268
+ className: getSize10(6)
2205
2269
  }),
2206
2270
  onClick: () => send({
2207
2271
  type: "recoverIdentity"
2208
2272
  }),
2209
- "data-testid": "recover-identity"
2273
+ "data-testid": "identity-chooser.recover-identity"
2210
2274
  }, t("recover identity label"))));
2211
2275
  };
2212
2276
 
2213
2277
  // packages/sdk/shell/src/panels/JoinPanel/steps/IdentityAdded.tsx
2214
- import React29, { cloneElement as cloneElement2 } from "react";
2278
+ import React30, { cloneElement as cloneElement2 } from "react";
2215
2279
  import { generateName as generateName3 } from "@dxos/display-name";
2216
- import { Avatar as Avatar5, useId as useId6, useJdenticonHref as useJdenticonHref4, useTranslation as useTranslation15 } from "@dxos/react-ui";
2217
- 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";
2218
2282
  var IdentityAdded = (props) => {
2219
2283
  const { mode, addedIdentity, active, send, onDone, doneActionParent } = props;
2220
2284
  const disabled = !active;
2221
- const { t } = useTranslation15("os");
2285
+ const { t } = useTranslation16("os");
2222
2286
  const fallbackValue = addedIdentity?.identityKey.toHex();
2223
2287
  const labelId = useId6("identityListItem__label");
2224
2288
  const jdenticon = useJdenticonHref4(fallbackValue ?? "", 12);
2225
2289
  const displayName = addedIdentity?.profile?.displayName ?? (addedIdentity && generateName3(addedIdentity?.identityKey.toHex()));
2226
- const doneAction = /* @__PURE__ */ React29.createElement(Action, {
2290
+ const doneAction = /* @__PURE__ */ React30.createElement(Action, {
2227
2291
  ...onDone && {
2228
2292
  onClick: () => onDone(null)
2229
2293
  },
2230
2294
  disabled,
2231
2295
  "data-autofocus": "confirmingAddedIdentity",
2232
2296
  "data-testid": "identity-added-done"
2233
- }, /* @__PURE__ */ React29.createElement("span", null, t("done label")));
2234
- return /* @__PURE__ */ React29.createElement(React29.Fragment, null, /* @__PURE__ */ React29.createElement(StepHeading, null, t("identity added label")), /* @__PURE__ */ React29.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", {
2235
2299
  role: "none",
2236
2300
  className: "grow flex flex-col items-center justify-center text-center gap-2"
2237
- }, /* @__PURE__ */ React29.createElement(Avatar5.Root, {
2301
+ }, /* @__PURE__ */ React30.createElement(Avatar5.Root, {
2238
2302
  status: "active",
2239
2303
  labelId
2240
- }, /* @__PURE__ */ React29.createElement(Avatar5.Frame, null, /* @__PURE__ */ React29.createElement(Avatar5.Fallback, {
2304
+ }, /* @__PURE__ */ React30.createElement(Avatar5.Frame, null, /* @__PURE__ */ React30.createElement(Avatar5.Fallback, {
2241
2305
  href: jdenticon
2242
- })), /* @__PURE__ */ React29.createElement(Avatar5.Label, {
2243
- classNames: mx20("text-lg truncate", !addedIdentity?.profile?.displayName && "font-mono")
2244
- }, displayName))), /* @__PURE__ */ React29.createElement(Actions, null, mode === "halo-only" ? doneActionParent ? /* @__PURE__ */ cloneElement2(doneActionParent, {}, doneAction) : doneAction : /* @__PURE__ */ React29.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, {
2245
2309
  variant: "primary",
2246
2310
  disabled: disabled || !addedIdentity,
2247
2311
  onClick: () => addedIdentity && send({
@@ -2253,16 +2317,16 @@ var IdentityAdded = (props) => {
2253
2317
  };
2254
2318
 
2255
2319
  // packages/sdk/shell/src/panels/JoinPanel/steps/IdentityInput.tsx
2256
- import React30, { useState as useState5 } from "react";
2320
+ import React31, { useState as useState5 } from "react";
2257
2321
  import { log as log5 } from "@dxos/log";
2258
- import { useClient as useClient5 } from "@dxos/react-client";
2259
- import { useTranslation as useTranslation16 } from "@dxos/react-ui";
2322
+ import { useClient as useClient4 } from "@dxos/react-client";
2323
+ import { useTranslation as useTranslation17 } from "@dxos/react-ui";
2260
2324
  var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/steps/IdentityInput.tsx";
2261
2325
  var IdentityInput = (props) => {
2262
2326
  const { send, method } = props;
2263
2327
  const isRecover = method === "recover identity";
2264
- const client = useClient5();
2265
- const { t } = useTranslation16("os");
2328
+ const client = useClient4();
2329
+ const { t } = useTranslation17("os");
2266
2330
  const [validationMessage, setValidationMessage] = useState5("");
2267
2331
  const createIdentity = (displayName) => {
2268
2332
  void client.halo.createIdentity({
@@ -2282,7 +2346,7 @@ var IdentityInput = (props) => {
2282
2346
  setValidationMessage(t(isRecover ? "failed to recover identity message" : "failed to create identity message"));
2283
2347
  });
2284
2348
  };
2285
- return /* @__PURE__ */ React30.createElement(IdentityInputImpl, {
2349
+ return /* @__PURE__ */ React31.createElement(IdentityInputImpl, {
2286
2350
  ...props,
2287
2351
  onDisplayNameConfirm: createIdentity,
2288
2352
  validationMessage
@@ -2291,27 +2355,27 @@ var IdentityInput = (props) => {
2291
2355
  var IdentityInputImpl = (props) => {
2292
2356
  const { method, send, active, onDisplayNameConfirm, validationMessage } = props;
2293
2357
  const disabled = !active;
2294
- const { t } = useTranslation16("os");
2358
+ const { t } = useTranslation17("os");
2295
2359
  const [inputValue, setInputValue] = useState5("");
2296
2360
  const isRecover = method === "recover identity";
2297
- return /* @__PURE__ */ React30.createElement(React30.Fragment, null, /* @__PURE__ */ React30.createElement("div", {
2361
+ return /* @__PURE__ */ React31.createElement(React31.Fragment, null, /* @__PURE__ */ React31.createElement("div", {
2298
2362
  role: "none",
2299
2363
  className: "grow flex flex-col justify-center"
2300
- }, /* @__PURE__ */ React30.createElement(Input, {
2364
+ }, /* @__PURE__ */ React31.createElement(Input, {
2301
2365
  validationMessage,
2302
- label: /* @__PURE__ */ React30.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")),
2303
2367
  disabled,
2304
2368
  "data-testid": "identity-input",
2305
2369
  placeholder: isRecover ? "Type your recovery phrase" : "Type a display name",
2306
2370
  onChange: ({ target: { value } }) => setInputValue(value)
2307
- })), /* @__PURE__ */ React30.createElement(Actions, null, /* @__PURE__ */ React30.createElement(Action, {
2371
+ })), /* @__PURE__ */ React31.createElement(Actions, null, /* @__PURE__ */ React31.createElement(Action, {
2308
2372
  variant: "ghost",
2309
2373
  disabled,
2310
2374
  onClick: () => send?.({
2311
2375
  type: "deselectAuthMethod"
2312
2376
  }),
2313
2377
  "data-testid": `${method === "recover identity" ? "recover" : "create"}-identity-input-back`
2314
- }, t("back label")), /* @__PURE__ */ React30.createElement(Action, {
2378
+ }, t("back label")), /* @__PURE__ */ React31.createElement(Action, {
2315
2379
  variant: "primary",
2316
2380
  disabled,
2317
2381
  onClick: () => onDisplayNameConfirm?.(inputValue),
@@ -2320,31 +2384,31 @@ var IdentityInputImpl = (props) => {
2320
2384
  };
2321
2385
 
2322
2386
  // packages/sdk/shell/src/panels/JoinPanel/steps/InvitationAccepted.tsx
2323
- import React31, { cloneElement as cloneElement3 } from "react";
2324
- import { useTranslation as useTranslation17 } from "@dxos/react-ui";
2387
+ import React32, { cloneElement as cloneElement3 } from "react";
2388
+ import { useTranslation as useTranslation18 } from "@dxos/react-ui";
2325
2389
  var InvitationAccepted = (props) => {
2326
2390
  const { active, Kind, doneActionParent, onDone } = props;
2327
2391
  const disabled = !active;
2328
- const { t } = useTranslation17("os");
2329
- const doneAction = /* @__PURE__ */ React31.createElement(Action, {
2392
+ const { t } = useTranslation18("os");
2393
+ const doneAction = /* @__PURE__ */ React32.createElement(Action, {
2330
2394
  variant: "primary",
2331
2395
  onClick: onDone,
2332
2396
  disabled,
2333
2397
  "data-autofocus": `success${Kind}Invitation finishingJoining${Kind}`,
2334
2398
  "data-testid": `${Kind.toLowerCase()}-invitation-accepted-done`
2335
2399
  }, t("done label"));
2336
- return /* @__PURE__ */ React31.createElement(React31.Fragment, null, /* @__PURE__ */ React31.createElement("div", {
2400
+ return /* @__PURE__ */ React32.createElement(React32.Fragment, null, /* @__PURE__ */ React32.createElement("div", {
2337
2401
  role: "none",
2338
2402
  className: "grow flex flex-col justify-center"
2339
- }, /* @__PURE__ */ React31.createElement("p", {
2403
+ }, /* @__PURE__ */ React32.createElement("p", {
2340
2404
  className: "text-center text-sm font-normal"
2341
- }, t("welcome message"))), /* @__PURE__ */ React31.createElement(Actions, null, doneActionParent ? /* @__PURE__ */ cloneElement3(doneActionParent, {}, doneAction) : doneAction));
2405
+ }, t("welcome message"))), /* @__PURE__ */ React32.createElement(Actions, null, doneActionParent ? /* @__PURE__ */ cloneElement3(doneActionParent, {}, doneAction) : doneAction));
2342
2406
  };
2343
2407
 
2344
2408
  // packages/sdk/shell/src/panels/JoinPanel/steps/InvitationInput.tsx
2345
- import React32, { useState as useState6, useEffect as useEffect4, cloneElement as cloneElement4 } from "react";
2409
+ import React33, { useState as useState6, useEffect as useEffect4, cloneElement as cloneElement4 } from "react";
2346
2410
  import { log as log6 } from "@dxos/log";
2347
- import { useTranslation as useTranslation18 } from "@dxos/react-ui";
2411
+ import { useTranslation as useTranslation19 } from "@dxos/react-ui";
2348
2412
  var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/steps/InvitationInput.tsx";
2349
2413
  var invitationCodeFromUrl = (text) => {
2350
2414
  try {
@@ -2364,21 +2428,26 @@ var invitationCodeFromUrl = (text) => {
2364
2428
  var InvitationInput = (props) => {
2365
2429
  const { Kind, active, send, unredeemedCode, onExit, exitActionParent, onDone, doneActionParent, succeededKeys } = props;
2366
2430
  const disabled = !active;
2367
- const { t } = useTranslation18("os");
2431
+ const { t } = useTranslation19("os");
2368
2432
  const [inputValue, setInputValue] = useState6(unredeemedCode ?? "");
2369
2433
  useEffect4(() => {
2370
2434
  unredeemedCode && setInputValue(unredeemedCode ?? "");
2371
2435
  }, [
2372
2436
  unredeemedCode
2373
2437
  ]);
2374
- const handleNext = () => send({
2375
- type: `set${Kind}InvitationCode`,
2376
- code: invitationCodeFromUrl(inputValue),
2377
- ...Kind === "Space" && {
2378
- succeededKeys
2438
+ const handleNext = () => {
2439
+ if (inputValue.trim().length === 0) {
2440
+ return;
2379
2441
  }
2380
- });
2381
- const exitAction = /* @__PURE__ */ React32.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, {
2382
2451
  variant: "ghost",
2383
2452
  disabled,
2384
2453
  ...onExit ? {
@@ -2388,11 +2457,12 @@ var InvitationInput = (props) => {
2388
2457
  },
2389
2458
  "data-testid": "join-exit"
2390
2459
  }, t("cancel label"));
2391
- return /* @__PURE__ */ React32.createElement(React32.Fragment, null, /* @__PURE__ */ React32.createElement("div", {
2460
+ return /* @__PURE__ */ React33.createElement(React33.Fragment, null, /* @__PURE__ */ React33.createElement("div", {
2392
2461
  role: "none",
2393
2462
  className: "grow flex flex-col justify-center"
2394
- }, /* @__PURE__ */ React32.createElement(Input, {
2395
- label: /* @__PURE__ */ React32.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.
2396
2466
  placeholder: "Type an invitation code",
2397
2467
  disabled,
2398
2468
  value: inputValue,
@@ -2400,14 +2470,14 @@ var InvitationInput = (props) => {
2400
2470
  "data-autofocus": `inputting${Kind}InvitationCode`,
2401
2471
  "data-testid": `${Kind.toLowerCase()}-invitation-input`,
2402
2472
  onKeyUp: ({ key }) => key === "Enter" && handleNext()
2403
- })), /* @__PURE__ */ React32.createElement(Actions, null, Kind === "Halo" ? /* @__PURE__ */ React32.createElement(Action, {
2473
+ })), /* @__PURE__ */ React33.createElement(Actions, null, Kind === "Halo" ? /* @__PURE__ */ React33.createElement(Action, {
2404
2474
  variant: "ghost",
2405
2475
  disabled,
2406
2476
  onClick: () => send({
2407
2477
  type: "deselectAuthMethod"
2408
2478
  }),
2409
2479
  "data-testid": `${Kind.toLowerCase()}-invitation-input-back`
2410
- }, t("back label")) : exitActionParent ? /* @__PURE__ */ cloneElement4(exitActionParent, {}, exitAction) : doneActionParent ? /* @__PURE__ */ cloneElement4(doneActionParent, {}, exitAction) : exitAction, /* @__PURE__ */ React32.createElement(Action, {
2480
+ }, t("back label")) : exitActionParent ? /* @__PURE__ */ cloneElement4(exitActionParent, {}, exitAction) : doneActionParent ? /* @__PURE__ */ cloneElement4(doneActionParent, {}, exitAction) : exitAction, /* @__PURE__ */ React33.createElement(Action, {
2411
2481
  variant: "primary",
2412
2482
  disabled,
2413
2483
  onClick: handleNext,
@@ -2416,8 +2486,8 @@ var InvitationInput = (props) => {
2416
2486
  };
2417
2487
 
2418
2488
  // packages/sdk/shell/src/panels/JoinPanel/steps/InvitationRescuer.tsx
2419
- import React33 from "react";
2420
- import { useTranslation as useTranslation19 } from "@dxos/react-ui";
2489
+ import React34 from "react";
2490
+ import { useTranslation as useTranslation20 } from "@dxos/react-ui";
2421
2491
  import { descriptionText as descriptionText9 } from "@dxos/react-ui-theme";
2422
2492
  var InvitationActions = ({
2423
2493
  // `invitationState` does report correct state, but here we evaluate whether `failReason` is a better source of truth
@@ -2429,14 +2499,14 @@ var InvitationActions = ({
2429
2499
  Kind,
2430
2500
  failReason
2431
2501
  }) => {
2432
- const { t } = useTranslation19("os");
2502
+ const { t } = useTranslation20("os");
2433
2503
  if (failReason) {
2434
- return /* @__PURE__ */ React33.createElement(React33.Fragment, null, /* @__PURE__ */ React33.createElement(StepHeading, {
2504
+ return /* @__PURE__ */ React34.createElement(React34.Fragment, null, /* @__PURE__ */ React34.createElement(StepHeading, {
2435
2505
  className: descriptionText9
2436
- }, t(failReason === "timeout" ? "timeout status label" : failReason === "cancelled" ? "cancelled status label" : "error status label")), /* @__PURE__ */ React33.createElement("div", {
2506
+ }, t(failReason === "timeout" ? "timeout status label" : failReason === "cancelled" ? "cancelled status label" : "error status label")), /* @__PURE__ */ React34.createElement("div", {
2437
2507
  role: "none",
2438
2508
  className: "grow"
2439
- }), /* @__PURE__ */ React33.createElement(Actions, null, /* @__PURE__ */ React33.createElement(Action, {
2509
+ }), /* @__PURE__ */ React34.createElement(Actions, null, /* @__PURE__ */ React34.createElement(Action, {
2440
2510
  disabled: !active,
2441
2511
  onClick: () => send({
2442
2512
  type: `reset${Kind}Invitation`
@@ -2444,16 +2514,16 @@ var InvitationActions = ({
2444
2514
  "data-testid": "invitation-rescuer-reset"
2445
2515
  }, t("reset label"))));
2446
2516
  } else {
2447
- return /* @__PURE__ */ React33.createElement(React33.Fragment, null, /* @__PURE__ */ React33.createElement(StepHeading, {
2517
+ return /* @__PURE__ */ React34.createElement(React34.Fragment, null, /* @__PURE__ */ React34.createElement(StepHeading, {
2448
2518
  className: descriptionText9
2449
- }, t("connecting status label")), /* @__PURE__ */ React33.createElement("div", {
2519
+ }, t("connecting status label")), /* @__PURE__ */ React34.createElement("div", {
2450
2520
  role: "none",
2451
2521
  className: "grow"
2452
- }), /* @__PURE__ */ React33.createElement(Actions, null, /* @__PURE__ */ React33.createElement(Action, {
2522
+ }), /* @__PURE__ */ React34.createElement(Actions, null, /* @__PURE__ */ React34.createElement(Action, {
2453
2523
  disabled: true,
2454
2524
  classNames: "order-2",
2455
2525
  "data-testid": "next"
2456
- }, t("next label")), /* @__PURE__ */ React33.createElement(Action, {
2526
+ }, t("next label")), /* @__PURE__ */ React34.createElement(Action, {
2457
2527
  disabled: !active,
2458
2528
  onClick: onInvitationCancel,
2459
2529
  "data-testid": "invitation-rescuer-cancel"
@@ -2462,28 +2532,28 @@ var InvitationActions = ({
2462
2532
  };
2463
2533
  var InvitationRescuer = (props) => {
2464
2534
  const { Kind, invitationState, active, send } = props;
2465
- const { t } = useTranslation19("os");
2466
- return /* @__PURE__ */ React33.createElement(React33.Fragment, null, typeof invitationState === "undefined" ? /* @__PURE__ */ React33.createElement(React33.Fragment, null, /* @__PURE__ */ React33.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", {
2467
2537
  role: "none",
2468
2538
  className: "grow flex flex-col justify-center"
2469
- }, /* @__PURE__ */ React33.createElement(StepHeading, {
2539
+ }, /* @__PURE__ */ React34.createElement(StepHeading, {
2470
2540
  className: descriptionText9
2471
- }, "There was a problem joining the space")), /* @__PURE__ */ React33.createElement(Actions, null, /* @__PURE__ */ React33.createElement(Action, {
2541
+ }, "There was a problem joining the space")), /* @__PURE__ */ React34.createElement(Actions, null, /* @__PURE__ */ React34.createElement(Action, {
2472
2542
  disabled: !active,
2473
2543
  "data-testid": "invitation-rescuer-blank-reset",
2474
2544
  onClick: () => send({
2475
2545
  type: `reset${Kind}Invitation`
2476
2546
  })
2477
- }, t("reset label")))) : /* @__PURE__ */ React33.createElement(InvitationActions, props));
2547
+ }, t("reset label")))) : /* @__PURE__ */ React34.createElement(InvitationActions, props));
2478
2548
  };
2479
2549
 
2480
2550
  // packages/sdk/shell/src/panels/JoinPanel/steps/InvitationAuthenticator.tsx
2481
- import React34, { useState as useState7 } from "react";
2482
- import { Input as Input2, useTranslation as useTranslation20 } from "@dxos/react-ui";
2551
+ import React35, { useState as useState7 } from "react";
2552
+ import { Input as Input2, useTranslation as useTranslation21 } from "@dxos/react-ui";
2483
2553
  var pinLength = 6;
2484
2554
  var InvitationAuthenticator = ({ failed, Kind, active, pending, invitationId, onInvitationAuthenticate, onInvitationCancel }) => {
2485
2555
  const disabled = !active || pending;
2486
- const { t } = useTranslation20("os");
2556
+ const { t } = useTranslation21("os");
2487
2557
  const invitationType = Kind.toLowerCase();
2488
2558
  const [authCode, setAuthCode] = useState7("");
2489
2559
  const onChange = ({ target: { value } }) => {
@@ -2492,16 +2562,16 @@ var InvitationAuthenticator = ({ failed, Kind, active, pending, invitationId, on
2492
2562
  document.querySelector(`[data-autofocus-pinlength="${invitationType}"]`)?.focus();
2493
2563
  }
2494
2564
  };
2495
- return /* @__PURE__ */ React34.createElement(React34.Fragment, null, /* @__PURE__ */ React34.createElement("div", {
2565
+ return /* @__PURE__ */ React35.createElement(React35.Fragment, null, /* @__PURE__ */ React35.createElement("div", {
2496
2566
  role: "none",
2497
2567
  className: "grow flex flex-col justify-center"
2498
- }, invitationId && /* @__PURE__ */ React34.createElement(Emoji, {
2568
+ }, invitationId && /* @__PURE__ */ React35.createElement(Emoji, {
2499
2569
  text: toEmoji(invitationId)
2500
- }), /* @__PURE__ */ React34.createElement(Input2.Root, failed && {
2570
+ }), /* @__PURE__ */ React35.createElement(Input2.Root, failed && {
2501
2571
  validationValence: "error"
2502
- }, /* @__PURE__ */ React34.createElement(Input2.Label, {
2572
+ }, /* @__PURE__ */ React35.createElement(Input2.Label, {
2503
2573
  asChild: true
2504
- }, /* @__PURE__ */ React34.createElement(StepHeading, null, t("auth code input label"))), /* @__PURE__ */ React34.createElement(Input2.PinInput, {
2574
+ }, /* @__PURE__ */ React35.createElement(StepHeading, null, t("auth code input label"))), /* @__PURE__ */ React35.createElement(Input2.PinInput, {
2505
2575
  disabled,
2506
2576
  length: pinLength,
2507
2577
  onChange,
@@ -2512,14 +2582,14 @@ var InvitationAuthenticator = ({ failed, Kind, active, pending, invitationId, on
2512
2582
  "data-prevent-ios-autofocus": true,
2513
2583
  "data-testid": `${invitationType}-auth-code-input`,
2514
2584
  "data-1p-ignore": true
2515
- }), failed && /* @__PURE__ */ React34.createElement(Input2.DescriptionAndValidation, {
2585
+ }), failed && /* @__PURE__ */ React35.createElement(Input2.DescriptionAndValidation, {
2516
2586
  classNames: "text-center"
2517
- }, /* @__PURE__ */ React34.createElement(Input2.Validation, null, t("failed to authenticate message"))))), /* @__PURE__ */ React34.createElement(Actions, null, /* @__PURE__ */ React34.createElement(Action, {
2587
+ }, /* @__PURE__ */ React35.createElement(Input2.Validation, null, t("failed to authenticate message"))))), /* @__PURE__ */ React35.createElement(Actions, null, /* @__PURE__ */ React35.createElement(Action, {
2518
2588
  variant: "ghost",
2519
2589
  disabled,
2520
2590
  onClick: () => onInvitationCancel?.(),
2521
2591
  "data-testid": `${invitationType}-invitation-authenticator-cancel`
2522
- }, t("cancel label")), /* @__PURE__ */ React34.createElement(Action, {
2592
+ }, t("cancel label")), /* @__PURE__ */ React35.createElement(Action, {
2523
2593
  variant: "primary",
2524
2594
  disabled,
2525
2595
  onClick: () => onInvitationAuthenticate?.(authCode),
@@ -2529,14 +2599,14 @@ var InvitationAuthenticator = ({ failed, Kind, active, pending, invitationId, on
2529
2599
  };
2530
2600
 
2531
2601
  // packages/sdk/shell/src/panels/JoinPanel/steps/ResetIdentity.tsx
2532
- import React35, { useState as useState8 } from "react";
2602
+ import React36, { useState as useState8 } from "react";
2533
2603
  import { log as log7 } from "@dxos/log";
2534
- import { useClient as useClient6 } from "@dxos/react-client";
2535
- import { useTranslation as useTranslation21 } from "@dxos/react-ui";
2604
+ import { useClient as useClient5 } from "@dxos/react-client";
2605
+ import { useTranslation as useTranslation22 } from "@dxos/react-ui";
2536
2606
  var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/steps/ResetIdentity.tsx";
2537
2607
  var ResetIdentity = ({ send, active }) => {
2538
- const client = useClient6();
2539
- const { t } = useTranslation21("os");
2608
+ const client = useClient5();
2609
+ const { t } = useTranslation22("os");
2540
2610
  const [validationMessage, setValidationMessage] = useState8("");
2541
2611
  const resetIdentity = () => {
2542
2612
  void client.reset().then(() => send?.({
@@ -2551,29 +2621,29 @@ var ResetIdentity = ({ send, active }) => {
2551
2621
  setValidationMessage(t("failed to reset identity message"));
2552
2622
  });
2553
2623
  };
2554
- return /* @__PURE__ */ React35.createElement(ResetIdentityImpl, {
2624
+ return /* @__PURE__ */ React36.createElement(ResetIdentityImpl, {
2555
2625
  disabled: !active,
2556
2626
  validationMessage,
2557
2627
  onConfirm: () => resetIdentity()
2558
2628
  });
2559
2629
  };
2560
2630
  var ResetIdentityImpl = ({ disabled, validationMessage, onConfirm }) => {
2561
- const { t } = useTranslation21("os");
2631
+ const { t } = useTranslation22("os");
2562
2632
  const confirmationValue = t("confirmation value");
2563
2633
  const [inputValue, setInputValue] = useState8("");
2564
- return /* @__PURE__ */ React35.createElement(React35.Fragment, null, /* @__PURE__ */ React35.createElement("div", {
2634
+ return /* @__PURE__ */ React36.createElement(React36.Fragment, null, /* @__PURE__ */ React36.createElement("div", {
2565
2635
  role: "none",
2566
2636
  className: "grow flex flex-col justify-center"
2567
- }, /* @__PURE__ */ React35.createElement(Input, {
2637
+ }, /* @__PURE__ */ React36.createElement(Input, {
2568
2638
  validationMessage,
2569
- label: /* @__PURE__ */ React35.createElement(StepHeading, null, t("reset identity input label", {
2639
+ label: /* @__PURE__ */ React36.createElement(StepHeading, null, t("reset identity input label", {
2570
2640
  confirmationValue
2571
2641
  })),
2572
2642
  disabled,
2573
- "data-testid": "identity-input",
2643
+ "data-testid": "reset-identity-input",
2574
2644
  placeholder: confirmationValue,
2575
2645
  onChange: ({ target: { value } }) => setInputValue(value)
2576
- })), /* @__PURE__ */ React35.createElement(Actions, null, /* @__PURE__ */ React35.createElement(Action, {
2646
+ })), /* @__PURE__ */ React36.createElement(Actions, null, /* @__PURE__ */ React36.createElement(Action, {
2577
2647
  // TODO(wittjosiah): Probably make this red?
2578
2648
  variant: "primary",
2579
2649
  disabled: disabled || inputValue !== confirmationValue,
@@ -2610,47 +2680,47 @@ var resolvedTextColor = (status) => status === Invitation7.State.ERROR ? errorTe
2610
2680
  var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/JoinPanel/JoinPanel.tsx";
2611
2681
  var JoinPanelImpl = (props) => {
2612
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;
2613
- return /* @__PURE__ */ React36.createElement(DensityProvider3, {
2683
+ return /* @__PURE__ */ React37.createElement(DensityProvider3, {
2614
2684
  density: "fine"
2615
- }, mode !== "halo-only" && /* @__PURE__ */ React36.createElement(JoinHeading, {
2685
+ }, mode !== "halo-only" && /* @__PURE__ */ React37.createElement(JoinHeading, {
2616
2686
  titleId,
2617
2687
  mode,
2618
2688
  onExit,
2619
2689
  exitActionParent
2620
- }), /* @__PURE__ */ React36.createElement(Viewport.Root, {
2690
+ }), /* @__PURE__ */ React37.createElement(Viewport.Root, {
2621
2691
  focusManaged: true,
2622
2692
  activeView
2623
- }, /* @__PURE__ */ React36.createElement(Viewport.Views, null, /* @__PURE__ */ React36.createElement(Viewport.View, {
2693
+ }, /* @__PURE__ */ React37.createElement(Viewport.Views, null, /* @__PURE__ */ React37.createElement(Viewport.View, {
2624
2694
  classNames: stepStyles,
2625
2695
  id: "addition method chooser"
2626
- }, /* @__PURE__ */ React36.createElement(AdditionMethodChooser, {
2696
+ }, /* @__PURE__ */ React37.createElement(AdditionMethodChooser, {
2627
2697
  send,
2628
2698
  active: activeView === "addition method chooser"
2629
- })), /* @__PURE__ */ React36.createElement(Viewport.View, {
2699
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2630
2700
  classNames: stepStyles,
2631
2701
  id: "reset identity confirmation"
2632
- }, /* @__PURE__ */ React36.createElement(ResetIdentityComponent, {
2702
+ }, /* @__PURE__ */ React37.createElement(ResetIdentityComponent, {
2633
2703
  send,
2634
2704
  method: "reset identity",
2635
2705
  active: activeView === "reset identity confirmation"
2636
- })), /* @__PURE__ */ React36.createElement(Viewport.View, {
2706
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2637
2707
  classNames: stepStyles,
2638
2708
  id: "create identity input"
2639
- }, /* @__PURE__ */ React36.createElement(IdentityInputComponent, {
2709
+ }, /* @__PURE__ */ React37.createElement(IdentityInputComponent, {
2640
2710
  send,
2641
2711
  method: "create identity",
2642
2712
  active: activeView === "create identity input"
2643
- })), /* @__PURE__ */ React36.createElement(Viewport.View, {
2713
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2644
2714
  classNames: stepStyles,
2645
2715
  id: "recover identity input"
2646
- }, /* @__PURE__ */ React36.createElement(IdentityInputComponent, {
2716
+ }, /* @__PURE__ */ React37.createElement(IdentityInputComponent, {
2647
2717
  send,
2648
2718
  method: "recover identity",
2649
2719
  active: activeView === "recover identity input"
2650
- })), /* @__PURE__ */ React36.createElement(Viewport.View, {
2720
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2651
2721
  classNames: stepStyles,
2652
2722
  id: "halo invitation input"
2653
- }, /* @__PURE__ */ React36.createElement(InvitationInput, {
2723
+ }, /* @__PURE__ */ React37.createElement(InvitationInput, {
2654
2724
  send,
2655
2725
  Kind: "Halo",
2656
2726
  active: activeView === "halo invitation input",
@@ -2660,20 +2730,20 @@ var JoinPanelImpl = (props) => {
2660
2730
  ...succeededKeys?.Halo && {
2661
2731
  succeededKeys: succeededKeys.Halo
2662
2732
  }
2663
- })), /* @__PURE__ */ React36.createElement(Viewport.View, {
2733
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2664
2734
  classNames: stepStyles,
2665
2735
  id: "halo invitation rescuer"
2666
- }, /* @__PURE__ */ React36.createElement(InvitationRescuer, {
2736
+ }, /* @__PURE__ */ React37.createElement(InvitationRescuer, {
2667
2737
  send,
2668
2738
  Kind: "Halo",
2669
2739
  active: activeView === "halo invitation rescuer",
2670
2740
  invitationState: invitationStates?.Halo,
2671
2741
  onInvitationCancel: onHaloInvitationCancel,
2672
2742
  failReason: failReasons?.Halo
2673
- })), /* @__PURE__ */ React36.createElement(Viewport.View, {
2743
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2674
2744
  classNames: stepStyles,
2675
2745
  id: "halo invitation authenticator"
2676
- }, /* @__PURE__ */ React36.createElement(InvitationAuthenticator, {
2746
+ }, /* @__PURE__ */ React37.createElement(InvitationAuthenticator, {
2677
2747
  send,
2678
2748
  Kind: "Halo",
2679
2749
  active: activeView === "halo invitation authenticator",
@@ -2682,28 +2752,28 @@ var JoinPanelImpl = (props) => {
2682
2752
  ...failed.has("Halo") && {
2683
2753
  failed: true
2684
2754
  }
2685
- })), /* @__PURE__ */ React36.createElement(Viewport.View, {
2755
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2686
2756
  classNames: stepStyles,
2687
2757
  id: "halo invitation accepted"
2688
- }, /* @__PURE__ */ React36.createElement(InvitationAccepted, {
2758
+ }, /* @__PURE__ */ React37.createElement(InvitationAccepted, {
2689
2759
  send,
2690
2760
  Kind: "Halo",
2691
2761
  active: activeView === "halo invitation accepted",
2692
2762
  doneActionParent,
2693
2763
  onDone: onHaloDone
2694
- })), /* @__PURE__ */ React36.createElement(Viewport.View, {
2764
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2695
2765
  classNames: stepStyles,
2696
2766
  id: "identity added"
2697
- }, /* @__PURE__ */ React36.createElement(IdentityAdded, {
2767
+ }, /* @__PURE__ */ React37.createElement(IdentityAdded, {
2698
2768
  send,
2699
2769
  mode,
2700
2770
  active: activeView === "identity added",
2701
2771
  doneActionParent,
2702
2772
  onDone: onHaloDone
2703
- })), /* @__PURE__ */ React36.createElement(Viewport.View, {
2773
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2704
2774
  classNames: stepStyles,
2705
2775
  id: "space invitation input"
2706
- }, /* @__PURE__ */ React36.createElement(InvitationInput, {
2776
+ }, /* @__PURE__ */ React37.createElement(InvitationInput, {
2707
2777
  send,
2708
2778
  Kind: "Space",
2709
2779
  active: activeView === "space invitation input",
@@ -2715,20 +2785,20 @@ var JoinPanelImpl = (props) => {
2715
2785
  },
2716
2786
  onExit,
2717
2787
  exitActionParent
2718
- })), /* @__PURE__ */ React36.createElement(Viewport.View, {
2788
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2719
2789
  classNames: stepStyles,
2720
2790
  id: "space invitation rescuer"
2721
- }, /* @__PURE__ */ React36.createElement(InvitationRescuer, {
2791
+ }, /* @__PURE__ */ React37.createElement(InvitationRescuer, {
2722
2792
  send,
2723
2793
  Kind: "Space",
2724
2794
  active: activeView === "space invitation rescuer",
2725
2795
  invitationState: invitationStates?.Space,
2726
2796
  onInvitationCancel: onSpaceInvitationCancel,
2727
2797
  failReason: failReasons?.Space
2728
- })), /* @__PURE__ */ React36.createElement(Viewport.View, {
2798
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2729
2799
  classNames: stepStyles,
2730
2800
  id: "space invitation authenticator"
2731
- }, /* @__PURE__ */ React36.createElement(InvitationAuthenticator, {
2801
+ }, /* @__PURE__ */ React37.createElement(InvitationAuthenticator, {
2732
2802
  send,
2733
2803
  Kind: "Space",
2734
2804
  active: activeView === "space invitation authenticator",
@@ -2737,10 +2807,10 @@ var JoinPanelImpl = (props) => {
2737
2807
  ...failed.has("Space") && {
2738
2808
  failed: true
2739
2809
  }
2740
- })), /* @__PURE__ */ React36.createElement(Viewport.View, {
2810
+ })), /* @__PURE__ */ React37.createElement(Viewport.View, {
2741
2811
  classNames: stepStyles,
2742
2812
  id: "space invitation accepted"
2743
- }, /* @__PURE__ */ React36.createElement(InvitationAccepted, {
2813
+ }, /* @__PURE__ */ React37.createElement(InvitationAccepted, {
2744
2814
  send,
2745
2815
  Kind: "Space",
2746
2816
  active: activeView === "space invitation accepted",
@@ -2749,7 +2819,7 @@ var JoinPanelImpl = (props) => {
2749
2819
  })))));
2750
2820
  };
2751
2821
  var JoinPanel = ({ titleId: propsTitleId, mode = "default", initialInvitationCode, exitActionParent, onExit, doneActionParent, onDone: propsOnDone }) => {
2752
- const client = useClient7();
2822
+ const client = useClient6();
2753
2823
  const identity = useIdentity2();
2754
2824
  const { hasIosKeyboard } = useThemeContext3();
2755
2825
  const titleId = useId7("joinPanel__heading", propsTitleId);
@@ -2980,7 +3050,7 @@ var JoinPanel = ({ titleId: propsTitleId, mode = "default", initialInvitationCod
2980
3050
  joinState,
2981
3051
  propsOnDone
2982
3052
  ]);
2983
- return /* @__PURE__ */ React36.createElement(JoinPanelImpl, {
3053
+ return /* @__PURE__ */ React37.createElement(JoinPanelImpl, {
2984
3054
  titleId,
2985
3055
  mode,
2986
3056
  send: joinSend,
@@ -3019,10 +3089,10 @@ var JoinPanel = ({ titleId: propsTitleId, mode = "default", initialInvitationCod
3019
3089
 
3020
3090
  // packages/sdk/shell/src/panels/SpacePanel/SpacePanel.tsx
3021
3091
  import { Planet } from "@phosphor-icons/react";
3022
- import React38, { useEffect as useEffect6, useMemo as useMemo5 } from "react";
3092
+ import React39, { useEffect as useEffect6, useMemo as useMemo5 } from "react";
3023
3093
  import { log as log10 } from "@dxos/log";
3024
3094
  import { useInvitationStatus as useInvitationStatus3 } from "@dxos/react-client/invitations";
3025
- import { DensityProvider as DensityProvider4, useId as useId8, useTranslation as useTranslation23 } from "@dxos/react-ui";
3095
+ import { DensityProvider as DensityProvider4, useId as useId8, useTranslation as useTranslation24 } from "@dxos/react-ui";
3026
3096
 
3027
3097
  // packages/sdk/shell/src/panels/SpacePanel/spaceMachine.ts
3028
3098
  import { useMachine as useMachine3 } from "@xstate/react";
@@ -3088,16 +3158,16 @@ var useSpaceMachine = (options) => {
3088
3158
 
3089
3159
  // packages/sdk/shell/src/panels/SpacePanel/steps/SpaceManager.tsx
3090
3160
  import { Placeholder as Placeholder2, UserPlus, UsersThree } from "@phosphor-icons/react";
3091
- import React37, { useCallback as useCallback8, useState as useState9 } from "react";
3161
+ import React38, { useCallback as useCallback8, useState as useState9 } from "react";
3092
3162
  import { useConfig } from "@dxos/react-client";
3093
3163
  import { useSpaceInvitations as useSpaceInvitations2 } from "@dxos/react-client/echo";
3094
3164
  import { Invitation as Invitation8, InvitationEncoder as InvitationEncoder4 } from "@dxos/react-client/invitations";
3095
- import { ScrollArea, useTranslation as useTranslation22 } from "@dxos/react-ui";
3096
- import { descriptionText as descriptionText10, mx as mx21 } from "@dxos/react-ui-theme";
3165
+ import { ScrollArea, useTranslation as useTranslation23 } from "@dxos/react-ui";
3166
+ import { descriptionText as descriptionText10, mx as mx22 } from "@dxos/react-ui-theme";
3097
3167
  var activeActionKey = "dxos:react-shell/space-manager/active-action";
3098
3168
  var SpaceManager = (props) => {
3099
3169
  const { space, target } = props;
3100
- const { t } = useTranslation22("os");
3170
+ const { t } = useTranslation23("os");
3101
3171
  const config = useConfig();
3102
3172
  const invitations = useSpaceInvitations2(space?.key);
3103
3173
  const onInvitationEvent = useCallback8((invitation) => {
@@ -3145,7 +3215,7 @@ var SpaceManager = (props) => {
3145
3215
  ])
3146
3216
  }
3147
3217
  };
3148
- return /* @__PURE__ */ React37.createElement(SpaceManagerImpl, {
3218
+ return /* @__PURE__ */ React38.createElement(SpaceManagerImpl, {
3149
3219
  ...props,
3150
3220
  invitations,
3151
3221
  inviteActions
@@ -3154,7 +3224,7 @@ var SpaceManager = (props) => {
3154
3224
  var headingFragment = "pis-3 pie-1 plb-1 mbe-1 font-medium";
3155
3225
  var SpaceManagerImpl = (props) => {
3156
3226
  const { active, space, createInvitationUrl, send, inviteActions: propsInviteActions, invitations, showInactiveInvitations, SpaceMemberList: SpaceMemberListComponent = SpaceMemberList, InvitationList: InvitationListComponent = InvitationList } = props;
3157
- const { t } = useTranslation22("os");
3227
+ const { t } = useTranslation23("os");
3158
3228
  const inviteActions = propsInviteActions ?? {
3159
3229
  noopInvite: {
3160
3230
  label: t("create space invitation label"),
@@ -3172,26 +3242,26 @@ var SpaceManagerImpl = (props) => {
3172
3242
  const visibleInvitations = showInactiveInvitations ? invitations : invitations?.filter((invitation) => ![
3173
3243
  Invitation8.State.CANCELLED
3174
3244
  ].includes(invitation.get().state));
3175
- return /* @__PURE__ */ React37.createElement(React37.Fragment, null, /* @__PURE__ */ React37.createElement(ScrollArea.Root, {
3245
+ return /* @__PURE__ */ React38.createElement(React38.Fragment, null, /* @__PURE__ */ React38.createElement(ScrollArea.Root, {
3176
3246
  classNames: "grow shrink basis-28 -mli-2"
3177
- }, /* @__PURE__ */ React37.createElement(ScrollArea.Viewport, {
3247
+ }, /* @__PURE__ */ React38.createElement(ScrollArea.Viewport, {
3178
3248
  classNames: "is-full pie-2"
3179
- }, !!visibleInvitations?.length && /* @__PURE__ */ React37.createElement(React37.Fragment, null, /* @__PURE__ */ React37.createElement("h3", {
3180
- className: mx21(headingFragment, descriptionText10)
3181
- }, t("invitation list heading")), /* @__PURE__ */ React37.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, {
3182
3252
  className: "mb-2",
3183
3253
  send,
3184
3254
  invitations: visibleInvitations ?? [],
3185
3255
  onClickRemove: (invitation) => invitation.cancel(),
3186
3256
  createInvitationUrl
3187
- }), /* @__PURE__ */ React37.createElement("h3", {
3188
- className: mx21(headingFragment, descriptionText10, "mbs-2")
3189
- }, t("space member list heading"))), /* @__PURE__ */ React37.createElement(SpaceMemberListComponent, {
3257
+ }), /* @__PURE__ */ React38.createElement("h3", {
3258
+ className: mx22(headingFragment, descriptionText10, "mbs-2")
3259
+ }, t("space member list heading"))), /* @__PURE__ */ React38.createElement(SpaceMemberListComponent, {
3190
3260
  spaceKey: space.key,
3191
3261
  includeSelf: true
3192
- })), /* @__PURE__ */ React37.createElement(ScrollArea.Scrollbar, {
3262
+ })), /* @__PURE__ */ React38.createElement(ScrollArea.Scrollbar, {
3193
3263
  orientation: "vertical"
3194
- }, /* @__PURE__ */ React37.createElement(ScrollArea.Thumb, null))), /* @__PURE__ */ React37.createElement(Actions, null, /* @__PURE__ */ React37.createElement(BifurcatedAction, {
3264
+ }, /* @__PURE__ */ React38.createElement(ScrollArea.Thumb, null))), /* @__PURE__ */ React38.createElement(Actions, null, /* @__PURE__ */ React38.createElement(BifurcatedAction, {
3195
3265
  disabled: !active,
3196
3266
  actions: inviteActions,
3197
3267
  activeAction,
@@ -3203,46 +3273,46 @@ var SpaceManagerImpl = (props) => {
3203
3273
  // packages/sdk/shell/src/panels/SpacePanel/SpacePanel.tsx
3204
3274
  var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/sdk/shell/src/panels/SpacePanel/SpacePanel.tsx";
3205
3275
  var SpacePanelHeading = ({ titleId, space, onDone }) => {
3206
- const { t } = useTranslation23("os");
3276
+ const { t } = useTranslation24("os");
3207
3277
  const name = space.properties.name;
3208
- return /* @__PURE__ */ React38.createElement(Heading, {
3278
+ return /* @__PURE__ */ React39.createElement(Heading, {
3209
3279
  titleId,
3210
3280
  title: t("space panel heading"),
3211
- corner: /* @__PURE__ */ React38.createElement(CloseButton, {
3281
+ corner: /* @__PURE__ */ React39.createElement(CloseButton, {
3212
3282
  "data-testid": "identity-panel-done",
3213
3283
  onDone
3214
3284
  })
3215
- }, /* @__PURE__ */ React38.createElement("div", {
3285
+ }, /* @__PURE__ */ React39.createElement("div", {
3216
3286
  role: "none",
3217
3287
  className: "flex gap-4 items-center justify-center mlb-4"
3218
- }, /* @__PURE__ */ React38.createElement(Planet, {
3288
+ }, /* @__PURE__ */ React39.createElement(Planet, {
3219
3289
  size: 32
3220
- }), /* @__PURE__ */ React38.createElement("div", {
3290
+ }), /* @__PURE__ */ React39.createElement("div", {
3221
3291
  className: "block text-start font-light text-xl"
3222
3292
  }, name ?? space.key.truncate())));
3223
3293
  };
3224
3294
  var SpacePanelImpl = (props) => {
3225
3295
  const { titleId, activeView, space, target, SpaceManager: SpaceManagerComponent = SpaceManager, InvitationManager: InvitationManagerComponent = InvitationManager, ...rest } = props;
3226
- return /* @__PURE__ */ React38.createElement(DensityProvider4, {
3296
+ return /* @__PURE__ */ React39.createElement(DensityProvider4, {
3227
3297
  density: "fine"
3228
- }, /* @__PURE__ */ React38.createElement(SpacePanelHeading, {
3298
+ }, /* @__PURE__ */ React39.createElement(SpacePanelHeading, {
3229
3299
  ...rest,
3230
3300
  titleId,
3231
3301
  space
3232
- }), /* @__PURE__ */ React38.createElement(Viewport.Root, {
3302
+ }), /* @__PURE__ */ React39.createElement(Viewport.Root, {
3233
3303
  activeView
3234
- }, /* @__PURE__ */ React38.createElement(Viewport.Views, null, /* @__PURE__ */ React38.createElement(Viewport.View, {
3304
+ }, /* @__PURE__ */ React39.createElement(Viewport.Views, null, /* @__PURE__ */ React39.createElement(Viewport.View, {
3235
3305
  id: "space manager",
3236
3306
  classNames: stepStyles
3237
- }, /* @__PURE__ */ React38.createElement(SpaceManagerComponent, {
3307
+ }, /* @__PURE__ */ React39.createElement(SpaceManagerComponent, {
3238
3308
  active: activeView === "space manager",
3239
3309
  space,
3240
3310
  target,
3241
3311
  ...rest
3242
- })), /* @__PURE__ */ React38.createElement(Viewport.View, {
3312
+ })), /* @__PURE__ */ React39.createElement(Viewport.View, {
3243
3313
  id: "space invitation manager",
3244
3314
  classNames: stepStyles
3245
- }, /* @__PURE__ */ React38.createElement(InvitationManagerComponent, {
3315
+ }, /* @__PURE__ */ React39.createElement(InvitationManagerComponent, {
3246
3316
  active: activeView === "space invitation manager",
3247
3317
  ...rest,
3248
3318
  invitationUrl: props.invitationUrl
@@ -3250,7 +3320,7 @@ var SpacePanelImpl = (props) => {
3250
3320
  };
3251
3321
  var SpacePanelWithInvitationImpl = ({ invitation, ...props }) => {
3252
3322
  const invitationStatus = useInvitationStatus3(invitation);
3253
- return /* @__PURE__ */ React38.createElement(SpacePanelImpl, {
3323
+ return /* @__PURE__ */ React39.createElement(SpacePanelImpl, {
3254
3324
  ...props,
3255
3325
  ...invitationStatus,
3256
3326
  invitationUrl: props.createInvitationUrl(invitationStatus.invitationCode)
@@ -3297,63 +3367,63 @@ var SpacePanel = ({ titleId: propsTitleId, createInvitationUrl = (code) => code,
3297
3367
  };
3298
3368
  return spaceState.context.invitation ? (
3299
3369
  // TODO(wittjosiah): Unused? Remove?
3300
- /* @__PURE__ */ React38.createElement(SpacePanelWithInvitationImpl, {
3370
+ /* @__PURE__ */ React39.createElement(SpacePanelWithInvitationImpl, {
3301
3371
  ...implProps,
3302
3372
  invitation: spaceState.context.invitation
3303
3373
  })
3304
- ) : /* @__PURE__ */ React38.createElement(SpacePanelImpl, implProps);
3374
+ ) : /* @__PURE__ */ React39.createElement(SpacePanelImpl, implProps);
3305
3375
  };
3306
3376
 
3307
3377
  // packages/sdk/shell/src/composites/IdentityDialog/IdentityDialog.tsx
3308
3378
  var IdentityDialog = (props) => {
3309
3379
  const titleId = useId9("spaceDialog__title");
3310
- return /* @__PURE__ */ React39.createElement(Dialog.Root, {
3380
+ return /* @__PURE__ */ React40.createElement(Dialog.Root, {
3311
3381
  defaultOpen: true,
3312
3382
  onOpenChange: (open) => open || props.onDone?.()
3313
- }, /* @__PURE__ */ React39.createElement(Dialog.Portal, null, /* @__PURE__ */ React39.createElement(Dialog.Overlay, null, /* @__PURE__ */ React39.createElement(Dialog.Content, {
3383
+ }, /* @__PURE__ */ React40.createElement(Dialog.Portal, null, /* @__PURE__ */ React40.createElement(Dialog.Overlay, null, /* @__PURE__ */ React40.createElement(Dialog.Content, {
3314
3384
  "aria-labelledby": titleId,
3315
3385
  onOpenAutoFocus: (e) => e.preventDefault()
3316
- }, /* @__PURE__ */ React39.createElement(ClipboardProvider, null, /* @__PURE__ */ React39.createElement(IdentityPanel, {
3386
+ }, /* @__PURE__ */ React40.createElement(ClipboardProvider, null, /* @__PURE__ */ React40.createElement(IdentityPanel, {
3317
3387
  ...props,
3318
3388
  titleId,
3319
- doneActionParent: /* @__PURE__ */ React39.createElement(Dialog.Close, {
3389
+ doneActionParent: /* @__PURE__ */ React40.createElement(Dialog.Close, {
3320
3390
  asChild: true
3321
3391
  })
3322
3392
  }))))));
3323
3393
  };
3324
3394
 
3325
3395
  // packages/sdk/shell/src/composites/JoinDialog/JoinDialog.tsx
3326
- import React40 from "react";
3396
+ import React41 from "react";
3327
3397
  import { AlertDialog, useId as useId10, useVisualViewport } from "@dxos/react-ui";
3328
3398
  var JoinDialog = (joinPanelProps) => {
3329
3399
  const titleId = useId10("joinDialog__title");
3330
3400
  const { height } = useVisualViewport();
3331
- return /* @__PURE__ */ React40.createElement(AlertDialog.Root, {
3401
+ return /* @__PURE__ */ React41.createElement(AlertDialog.Root, {
3332
3402
  defaultOpen: true,
3333
3403
  onOpenChange: (open) => open || (joinPanelProps.onExit ? joinPanelProps.onExit() : joinPanelProps.onDone?.(null))
3334
- }, /* @__PURE__ */ React40.createElement(AlertDialog.Portal, null, /* @__PURE__ */ React40.createElement(AlertDialog.Overlay, {
3404
+ }, /* @__PURE__ */ React41.createElement(AlertDialog.Portal, null, /* @__PURE__ */ React41.createElement(AlertDialog.Overlay, {
3335
3405
  classNames: "backdrop-blur",
3336
3406
  ...height && {
3337
3407
  style: {
3338
3408
  blockSize: `${height}px`
3339
3409
  }
3340
3410
  }
3341
- }, /* @__PURE__ */ React40.createElement(AlertDialog.Content, {
3411
+ }, /* @__PURE__ */ React41.createElement(AlertDialog.Content, {
3342
3412
  "aria-labelledby": titleId
3343
- }, /* @__PURE__ */ React40.createElement(JoinPanel, {
3413
+ }, /* @__PURE__ */ React41.createElement(JoinPanel, {
3344
3414
  ...joinPanelProps,
3345
3415
  titleId,
3346
- exitActionParent: /* @__PURE__ */ React40.createElement(AlertDialog.Cancel, {
3416
+ exitActionParent: /* @__PURE__ */ React41.createElement(AlertDialog.Cancel, {
3347
3417
  asChild: true
3348
3418
  }),
3349
- doneActionParent: /* @__PURE__ */ React40.createElement(AlertDialog.Action, {
3419
+ doneActionParent: /* @__PURE__ */ React41.createElement(AlertDialog.Action, {
3350
3420
  asChild: true
3351
3421
  })
3352
3422
  })))));
3353
3423
  };
3354
3424
 
3355
3425
  // packages/sdk/shell/src/composites/Shell/run-shell.tsx
3356
- import React43, { StrictMode } from "react";
3426
+ import React44, { StrictMode } from "react";
3357
3427
  import { createRoot } from "react-dom/client";
3358
3428
  import { DEFAULT_CLIENT_CHANNEL, DEFAULT_SHELL_CHANNEL } from "@dxos/client-protocol";
3359
3429
  import { ShellRuntimeImpl } from "@dxos/client-services";
@@ -3363,25 +3433,25 @@ import { defaultTx } from "@dxos/react-ui-theme";
3363
3433
  import { createIFramePort } from "@dxos/rpc-tunnel";
3364
3434
 
3365
3435
  // packages/sdk/shell/src/composites/Shell/Shell.tsx
3366
- import React42, { useEffect as useEffect7, useState as useState10 } from "react";
3436
+ import React43, { useEffect as useEffect7, useState as useState10 } from "react";
3367
3437
  import { log as log11 } from "@dxos/log";
3368
- import { ShellDisplay, ShellLayout } from "@dxos/react-client";
3438
+ import { ShellDisplay, ShellLayout, useClient as useClient7 } from "@dxos/react-client";
3369
3439
  import { useSpace as useSpace2 } from "@dxos/react-client/echo";
3370
3440
 
3371
3441
  // packages/sdk/shell/src/composites/SpaceDialog/SpaceDialog.tsx
3372
- import React41 from "react";
3442
+ import React42 from "react";
3373
3443
  import { Dialog as Dialog2, useId as useId11 } from "@dxos/react-ui";
3374
3444
  var SpaceDialog = (spacePanelProps) => {
3375
3445
  const titleId = useId11("spaceDialog__title");
3376
- return /* @__PURE__ */ React41.createElement(Dialog2.Root, {
3446
+ return /* @__PURE__ */ React42.createElement(Dialog2.Root, {
3377
3447
  defaultOpen: true,
3378
3448
  onOpenChange: (open) => open || spacePanelProps.onDone?.()
3379
- }, /* @__PURE__ */ React41.createElement(Dialog2.Portal, null, /* @__PURE__ */ React41.createElement(Dialog2.Overlay, null, /* @__PURE__ */ React41.createElement(Dialog2.Content, {
3449
+ }, /* @__PURE__ */ React42.createElement(Dialog2.Portal, null, /* @__PURE__ */ React42.createElement(Dialog2.Overlay, null, /* @__PURE__ */ React42.createElement(Dialog2.Content, {
3380
3450
  "aria-labelledby": titleId
3381
- }, /* @__PURE__ */ React41.createElement(ClipboardProvider, null, /* @__PURE__ */ React41.createElement(SpacePanel, {
3451
+ }, /* @__PURE__ */ React42.createElement(ClipboardProvider, null, /* @__PURE__ */ React42.createElement(SpacePanel, {
3382
3452
  ...spacePanelProps,
3383
3453
  titleId,
3384
- doneActionParent: /* @__PURE__ */ React41.createElement(Dialog2.Close, {
3454
+ doneActionParent: /* @__PURE__ */ React42.createElement(Dialog2.Close, {
3385
3455
  asChild: true
3386
3456
  })
3387
3457
  }))))));
@@ -3396,6 +3466,7 @@ var Shell = ({ runtime, origin }) => {
3396
3466
  spaceKey: runtime.spaceKey,
3397
3467
  target: runtime.target
3398
3468
  });
3469
+ const client = useClient7();
3399
3470
  const space = useSpace2(spaceKey);
3400
3471
  useEffect7(() => {
3401
3472
  return runtime.layoutUpdate.on((request) => setLayout(request));
@@ -3406,7 +3477,7 @@ var Shell = ({ runtime, origin }) => {
3406
3477
  if (layout === ShellLayout.SPACE && !space) {
3407
3478
  log11.warn("No space found for shell space invitations.", void 0, {
3408
3479
  F: __dxlog_file12,
3409
- L: 31,
3480
+ L: 32,
3410
3481
  S: void 0,
3411
3482
  C: (f, a) => f(...a)
3412
3483
  });
@@ -3427,7 +3498,7 @@ var Shell = ({ runtime, origin }) => {
3427
3498
  ]);
3428
3499
  switch (layout) {
3429
3500
  case ShellLayout.INITIALIZE_IDENTITY:
3430
- return /* @__PURE__ */ React42.createElement(JoinDialog, {
3501
+ return /* @__PURE__ */ React43.createElement(JoinDialog, {
3431
3502
  mode: "halo-only",
3432
3503
  initialInvitationCode: invitationCode,
3433
3504
  onDone: () => {
@@ -3442,8 +3513,18 @@ var Shell = ({ runtime, origin }) => {
3442
3513
  case ShellLayout.IDENTITY:
3443
3514
  case ShellLayout.SHARE_IDENTITY:
3444
3515
  case ShellLayout.EDIT_PROFILE:
3445
- return /* @__PURE__ */ React42.createElement(IdentityDialog, {
3516
+ return /* @__PURE__ */ React43.createElement(IdentityDialog, {
3446
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
+ }),
3447
3528
  onDone: async () => {
3448
3529
  await runtime.setAppContext({
3449
3530
  display: ShellDisplay.NONE
@@ -3454,7 +3535,7 @@ var Shell = ({ runtime, origin }) => {
3454
3535
  }
3455
3536
  });
3456
3537
  case ShellLayout.SPACE:
3457
- return space ? /* @__PURE__ */ React42.createElement(SpaceDialog, {
3538
+ return space ? /* @__PURE__ */ React43.createElement(SpaceDialog, {
3458
3539
  space,
3459
3540
  target,
3460
3541
  createInvitationUrl: (invitationCode2) => `${origin}?spaceInvitationCode=${invitationCode2}`,
@@ -3468,7 +3549,7 @@ var Shell = ({ runtime, origin }) => {
3468
3549
  }
3469
3550
  }) : null;
3470
3551
  case ShellLayout.JOIN_SPACE:
3471
- return /* @__PURE__ */ React42.createElement(JoinDialog, {
3552
+ return /* @__PURE__ */ React43.createElement(JoinDialog, {
3472
3553
  initialInvitationCode: invitationCode,
3473
3554
  onDone: async (result) => {
3474
3555
  const target2 = result?.target ?? void 0;
@@ -3595,7 +3676,12 @@ var os = {
3595
3676
  "confirm label": "Confirm",
3596
3677
  "reset identity input label": "This will clear this device and all associated data. Type {{confirmationValue}} and confirm to continue.",
3597
3678
  "failed to reset identity message": "Failed to reset identity.",
3598
- "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."
3599
3685
  };
3600
3686
 
3601
3687
  // packages/sdk/shell/src/translations/index.ts
@@ -3619,27 +3705,27 @@ var runShell = async (config = new Config()) => {
3619
3705
  runtime.open(),
3620
3706
  client.initialize()
3621
3707
  ]);
3622
- createRoot(document.getElementById("root")).render(/* @__PURE__ */ React43.createElement(StrictMode, null, /* @__PURE__ */ React43.createElement(ThemeProvider, {
3708
+ createRoot(document.getElementById("root")).render(/* @__PURE__ */ React44.createElement(StrictMode, null, /* @__PURE__ */ React44.createElement(ThemeProvider, {
3623
3709
  tx: defaultTx,
3624
3710
  resourceExtensions: [
3625
3711
  osTranslations
3626
3712
  ]
3627
- }, /* @__PURE__ */ React43.createElement(ClientContext.Provider, {
3713
+ }, /* @__PURE__ */ React44.createElement(ClientContext.Provider, {
3628
3714
  value: {
3629
3715
  client,
3630
3716
  status: SystemStatus.ACTIVE
3631
3717
  }
3632
- }, /* @__PURE__ */ React43.createElement(ClipboardProvider, null, /* @__PURE__ */ React43.createElement(Tooltip3.Provider, null, /* @__PURE__ */ React43.createElement(Shell, {
3718
+ }, /* @__PURE__ */ React44.createElement(ClipboardProvider, null, /* @__PURE__ */ React44.createElement(Tooltip3.Provider, null, /* @__PURE__ */ React44.createElement(Shell, {
3633
3719
  runtime,
3634
3720
  origin: location.origin
3635
3721
  })))))));
3636
3722
  };
3637
3723
 
3638
3724
  // packages/sdk/shell/src/composites/Shell/ShellContext.tsx
3639
- import React44, { createContext as createContext2, useCallback as useCallback9, useContext as useContext2, useEffect as useEffect8, useMemo as useMemo6, useState as useState11 } from "react";
3725
+ import React45, { createContext as createContext2, useCallback as useCallback9, useContext as useContext2, useEffect as useEffect8, useMemo as useMemo6, useState as useState11 } from "react";
3640
3726
  import { ShellDisplay as ShellDisplay2, ShellLayout as ShellLayout3, useClient as useClient8 } from "@dxos/react-client";
3641
3727
  import { useIdentity as useIdentity3 } from "@dxos/react-client/halo";
3642
- import { mx as mx22 } from "@dxos/react-ui-theme";
3728
+ import { mx as mx23 } from "@dxos/react-ui-theme";
3643
3729
 
3644
3730
  // packages/sdk/shell/src/composites/Shell/memory-shell-runtime.ts
3645
3731
  import { Event } from "@dxos/async";
@@ -3768,12 +3854,12 @@ var ShellProvider = ({ space, deviceInvitationCode, spaceInvitationCode, onJoine
3768
3854
  }, [
3769
3855
  shellRuntime
3770
3856
  ]);
3771
- return /* @__PURE__ */ React44.createElement(React44.Fragment, null, shellRuntime && /* @__PURE__ */ React44.createElement("div", {
3772
- className: mx22(display === ShellDisplay2.NONE ? "hidden" : "")
3773
- }, /* @__PURE__ */ React44.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, {
3774
3860
  runtime: shellRuntime,
3775
3861
  origin: window.location.origin
3776
- })), /* @__PURE__ */ React44.createElement(ShellContext.Provider, {
3862
+ })), /* @__PURE__ */ React45.createElement(ShellContext.Provider, {
3777
3863
  value: {
3778
3864
  runtime: shellRuntime,
3779
3865
  setDisplay