@dxos/shell 0.4.10-main.fa5a270 → 0.4.10-main.fd8ea31

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 (223) hide show
  1. package/dist/bundle/index-Cms4wG79.mjs +110 -0
  2. package/dist/bundle/index-Cms4wG79.mjs.map +1 -0
  3. package/dist/bundle/index-DACjPI-n.mjs +96625 -0
  4. package/dist/bundle/index-DACjPI-n.mjs.map +1 -0
  5. package/dist/bundle/shell.mjs +9 -80814
  6. package/dist/bundle/shell.mjs.map +1 -1
  7. package/dist/bundle/shell.umd.js +156 -85
  8. package/dist/bundle/shell.umd.js.map +1 -1
  9. package/dist/bundle/style.css +1 -1
  10. package/dist/lib/browser/meta.json +1 -1
  11. package/dist/lib/browser/react.mjs +1177 -1034
  12. package/dist/lib/browser/react.mjs.map +4 -4
  13. package/dist/lib/browser/testing/index.mjs +10 -9
  14. package/dist/lib/browser/testing/index.mjs.map +3 -3
  15. package/dist/types/src/components/AgentConfig.d.ts +3 -0
  16. package/dist/types/src/components/AgentConfig.d.ts.map +1 -0
  17. package/dist/types/src/components/AgentConfig.js +37 -0
  18. package/dist/types/src/components/AgentConfig.js.map +1 -0
  19. package/dist/types/src/components/DeviceList/DeviceList.d.ts +3 -0
  20. package/dist/types/src/components/DeviceList/DeviceList.d.ts.map +1 -0
  21. package/dist/types/src/components/DeviceList/DeviceList.js +29 -0
  22. package/dist/types/src/components/DeviceList/DeviceList.js.map +1 -0
  23. package/dist/types/src/components/DeviceList/DeviceListItem.d.ts +6 -0
  24. package/dist/types/src/components/DeviceList/DeviceListItem.d.ts.map +1 -0
  25. package/dist/types/src/components/DeviceList/DeviceListItem.js +72 -0
  26. package/dist/types/src/components/DeviceList/DeviceListItem.js.map +1 -0
  27. package/dist/types/src/components/DeviceList/DeviceListProps.d.ts +27 -0
  28. package/dist/types/src/components/DeviceList/DeviceListProps.d.ts.map +1 -0
  29. package/dist/types/src/components/DeviceList/DeviceListProps.js +6 -0
  30. package/dist/types/src/components/DeviceList/DeviceListProps.js.map +1 -0
  31. package/dist/types/src/components/DeviceList/index.d.ts +3 -0
  32. package/dist/types/src/components/DeviceList/index.d.ts.map +1 -0
  33. package/dist/types/src/components/DeviceList/index.js +22 -0
  34. package/dist/types/src/components/DeviceList/index.js.map +1 -0
  35. package/dist/types/src/components/EmojiPicker.d.ts +9 -2
  36. package/dist/types/src/components/EmojiPicker.d.ts.map +1 -1
  37. package/dist/types/src/components/EmojiPicker.js +59 -4
  38. package/dist/types/src/components/EmojiPicker.js.map +1 -1
  39. package/dist/types/src/components/HuePicker.d.ts +9 -2
  40. package/dist/types/src/components/HuePicker.d.ts.map +1 -1
  41. package/dist/types/src/components/HuePicker.js +75 -6
  42. package/dist/types/src/components/HuePicker.js.map +1 -1
  43. package/dist/types/src/components/IdentityList/index.d.ts +0 -1
  44. package/dist/types/src/components/IdentityList/index.d.ts.map +1 -1
  45. package/dist/types/src/components/IdentityList/index.js +0 -1
  46. package/dist/types/src/components/IdentityList/index.js.map +1 -1
  47. package/dist/types/src/components/InvitationList/InvitationListItem.js +5 -5
  48. package/dist/types/src/components/InvitationList/InvitationListItem.js.map +1 -1
  49. package/dist/types/src/components/Panel/Action.d.ts +2 -2
  50. package/dist/types/src/components/Viewport/Viewport.d.ts +1 -1
  51. package/dist/types/src/components/index.d.ts +2 -0
  52. package/dist/types/src/components/index.d.ts.map +1 -1
  53. package/dist/types/src/components/index.js +2 -0
  54. package/dist/types/src/components/index.js.map +1 -1
  55. package/dist/types/src/composites/IdentityDialog/IdentityDialog.js +1 -1
  56. package/dist/types/src/composites/IdentityDialog/IdentityDialog.js.map +1 -1
  57. package/dist/types/src/composites/Shell/Shell.d.ts.map +1 -1
  58. package/dist/types/src/composites/Shell/Shell.js +14 -6
  59. package/dist/types/src/composites/Shell/Shell.js.map +1 -1
  60. package/dist/types/src/composites/StatusDialog/StatusDialog.d.ts +2 -0
  61. package/dist/types/src/composites/StatusDialog/StatusDialog.d.ts.map +1 -0
  62. package/dist/types/src/composites/StatusDialog/StatusDialog.js +22 -0
  63. package/dist/types/src/composites/StatusDialog/StatusDialog.js.map +1 -0
  64. package/dist/types/src/composites/StatusDialog/index.d.ts +2 -0
  65. package/dist/types/src/composites/StatusDialog/index.d.ts.map +1 -0
  66. package/dist/types/src/composites/StatusDialog/index.js +21 -0
  67. package/dist/types/src/composites/StatusDialog/index.js.map +1 -0
  68. package/dist/types/src/panels/IdentityPanel/IdentityPanel.d.ts +1 -1
  69. package/dist/types/src/panels/IdentityPanel/IdentityPanel.d.ts.map +1 -1
  70. package/dist/types/src/panels/IdentityPanel/IdentityPanel.js +89 -42
  71. package/dist/types/src/panels/IdentityPanel/IdentityPanel.js.map +1 -1
  72. package/dist/types/src/panels/IdentityPanel/IdentityPanel.stories.d.ts +0 -3
  73. package/dist/types/src/panels/IdentityPanel/IdentityPanel.stories.d.ts.map +1 -1
  74. package/dist/types/src/panels/IdentityPanel/IdentityPanel.stories.js +1 -43
  75. package/dist/types/src/panels/IdentityPanel/IdentityPanel.stories.js.map +1 -1
  76. package/dist/types/src/panels/IdentityPanel/IdentityPanelProps.d.ts +11 -12
  77. package/dist/types/src/panels/IdentityPanel/IdentityPanelProps.d.ts.map +1 -1
  78. package/dist/types/src/panels/IdentityPanel/identityMachine.d.ts +3 -1
  79. package/dist/types/src/panels/IdentityPanel/identityMachine.d.ts.map +1 -1
  80. package/dist/types/src/panels/IdentityPanel/identityMachine.js +13 -24
  81. package/dist/types/src/panels/IdentityPanel/identityMachine.js.map +1 -1
  82. package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.d.ts +4 -4
  83. package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.d.ts.map +1 -1
  84. package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.js +9 -39
  85. package/dist/types/src/panels/IdentityPanel/steps/IdentityActionChooser.js.map +1 -1
  86. package/dist/types/src/panels/IdentityPanel/steps/ProfileForm.d.ts +1 -1
  87. package/dist/types/src/panels/IdentityPanel/steps/ProfileForm.d.ts.map +1 -1
  88. package/dist/types/src/panels/IdentityPanel/steps/ProfileForm.js +6 -3
  89. package/dist/types/src/panels/IdentityPanel/steps/ProfileForm.js.map +1 -1
  90. package/dist/types/src/panels/IdentityPanel/steps/index.d.ts +0 -3
  91. package/dist/types/src/panels/IdentityPanel/steps/index.d.ts.map +1 -1
  92. package/dist/types/src/panels/IdentityPanel/steps/index.js +0 -3
  93. package/dist/types/src/panels/IdentityPanel/steps/index.js.map +1 -1
  94. package/dist/types/src/panels/IdentityPanel/useAgentHandlers.d.ts.map +1 -1
  95. package/dist/types/src/panels/IdentityPanel/useAgentHandlers.js +5 -1
  96. package/dist/types/src/panels/IdentityPanel/useAgentHandlers.js.map +1 -1
  97. package/dist/types/src/panels/JoinPanel/JoinPanel.d.ts +1 -1
  98. package/dist/types/src/panels/JoinPanel/JoinPanel.d.ts.map +1 -1
  99. package/dist/types/src/panels/JoinPanel/JoinPanel.js +12 -5
  100. package/dist/types/src/panels/JoinPanel/JoinPanel.js.map +1 -1
  101. package/dist/types/src/panels/JoinPanel/JoinPanel.stories.d.ts +1 -1
  102. package/dist/types/src/panels/JoinPanel/JoinPanel.stories.d.ts.map +1 -1
  103. package/dist/types/src/panels/JoinPanel/JoinPanel.stories.js +2 -1
  104. package/dist/types/src/panels/JoinPanel/JoinPanel.stories.js.map +1 -1
  105. package/dist/types/src/panels/JoinPanel/JoinPanelProps.d.ts +8 -3
  106. package/dist/types/src/panels/JoinPanel/JoinPanelProps.d.ts.map +1 -1
  107. package/dist/types/src/panels/JoinPanel/joinMachine.d.ts +3 -2
  108. package/dist/types/src/panels/JoinPanel/joinMachine.d.ts.map +1 -1
  109. package/dist/types/src/panels/JoinPanel/joinMachine.js +7 -0
  110. package/dist/types/src/panels/JoinPanel/joinMachine.js.map +1 -1
  111. package/dist/types/src/panels/JoinPanel/steps/index.d.ts +0 -1
  112. package/dist/types/src/panels/JoinPanel/steps/index.d.ts.map +1 -1
  113. package/dist/types/src/panels/JoinPanel/steps/index.js +0 -1
  114. package/dist/types/src/panels/JoinPanel/steps/index.js.map +1 -1
  115. package/dist/types/src/panels/SpacePanel/steps/SpaceManager.d.ts.map +1 -1
  116. package/dist/types/src/panels/SpacePanel/steps/SpaceManager.js +3 -1
  117. package/dist/types/src/panels/SpacePanel/steps/SpaceManager.js.map +1 -1
  118. package/dist/types/src/panels/StatusPanel/StatusPanel.d.ts +4 -0
  119. package/dist/types/src/panels/StatusPanel/StatusPanel.d.ts.map +1 -0
  120. package/dist/types/src/panels/StatusPanel/StatusPanel.js +19 -0
  121. package/dist/types/src/panels/StatusPanel/StatusPanel.js.map +1 -0
  122. package/dist/types/src/panels/StatusPanel/index.d.ts +2 -0
  123. package/dist/types/src/panels/StatusPanel/index.d.ts.map +1 -0
  124. package/dist/types/src/panels/StatusPanel/index.js +21 -0
  125. package/dist/types/src/panels/StatusPanel/index.js.map +1 -0
  126. package/dist/types/src/panels/index.d.ts +1 -0
  127. package/dist/types/src/panels/index.d.ts.map +1 -1
  128. package/dist/types/src/panels/index.js +1 -0
  129. package/dist/types/src/panels/index.js.map +1 -1
  130. package/dist/types/src/playwright/invitations.spec.js +3 -1
  131. package/dist/types/src/playwright/invitations.spec.js.map +1 -1
  132. package/dist/types/src/steps/ConfirmReset.d.ts +16 -0
  133. package/dist/types/src/steps/ConfirmReset.d.ts.map +1 -0
  134. package/dist/types/src/steps/ConfirmReset.js +71 -0
  135. package/dist/types/src/steps/ConfirmReset.js.map +1 -0
  136. package/dist/types/src/steps/InvitationManager.d.ts +1 -1
  137. package/dist/types/src/steps/InvitationManager.d.ts.map +1 -1
  138. package/dist/types/src/steps/InvitationManager.js +3 -4
  139. package/dist/types/src/steps/InvitationManager.js.map +1 -1
  140. package/dist/types/src/steps/StepProps.d.ts +4 -1
  141. package/dist/types/src/steps/StepProps.d.ts.map +1 -1
  142. package/dist/types/src/steps/index.d.ts +1 -0
  143. package/dist/types/src/steps/index.d.ts.map +1 -1
  144. package/dist/types/src/steps/index.js +1 -0
  145. package/dist/types/src/steps/index.js.map +1 -1
  146. package/dist/types/src/stories/Invitations.e2e-stories.d.ts.map +1 -1
  147. package/dist/types/src/stories/Invitations.e2e-stories.js +5 -2
  148. package/dist/types/src/stories/Invitations.e2e-stories.js.map +1 -1
  149. package/dist/types/src/testing/shell-manager.d.ts.map +1 -1
  150. package/dist/types/src/testing/shell-manager.js +10 -9
  151. package/dist/types/src/testing/shell-manager.js.map +1 -1
  152. package/dist/types/src/translations/locales/en-US.d.ts +16 -3
  153. package/dist/types/src/translations/locales/en-US.d.ts.map +1 -1
  154. package/dist/types/src/translations/locales/en-US.js +20 -7
  155. package/dist/types/src/translations/locales/en-US.js.map +1 -1
  156. package/dist/types/src/types/index.js +1 -0
  157. package/dist/types/src/types/index.js.map +1 -1
  158. package/package.json +22 -21
  159. package/src/components/AgentConfig.tsx +66 -0
  160. package/src/components/DeviceList/DeviceList.tsx +54 -0
  161. package/src/components/DeviceList/DeviceListItem.tsx +120 -0
  162. package/src/components/DeviceList/DeviceListProps.ts +33 -0
  163. package/src/components/DeviceList/index.ts +6 -0
  164. package/src/components/EmojiPicker.tsx +103 -4
  165. package/src/components/HuePicker.tsx +99 -5
  166. package/src/components/IdentityList/index.ts +0 -1
  167. package/src/components/InvitationList/InvitationListItem.tsx +5 -5
  168. package/src/components/index.ts +2 -0
  169. package/src/composites/IdentityDialog/IdentityDialog.tsx +1 -1
  170. package/src/composites/Shell/Shell.tsx +17 -4
  171. package/src/composites/StatusDialog/StatusDialog.tsx +24 -0
  172. package/src/composites/StatusDialog/index.ts +5 -0
  173. package/src/panels/IdentityPanel/IdentityPanel.stories.tsx +0 -63
  174. package/src/panels/IdentityPanel/IdentityPanel.tsx +149 -43
  175. package/src/panels/IdentityPanel/IdentityPanelProps.ts +15 -15
  176. package/src/panels/IdentityPanel/identityMachine.ts +17 -25
  177. package/src/panels/IdentityPanel/steps/IdentityActionChooser.tsx +23 -67
  178. package/src/panels/IdentityPanel/steps/ProfileForm.tsx +18 -5
  179. package/src/panels/IdentityPanel/steps/index.ts +0 -3
  180. package/src/panels/IdentityPanel/useAgentHandlers.ts +5 -1
  181. package/src/panels/JoinPanel/JoinPanel.stories.tsx +3 -2
  182. package/src/panels/JoinPanel/JoinPanel.tsx +21 -5
  183. package/src/panels/JoinPanel/JoinPanelProps.ts +9 -3
  184. package/src/panels/JoinPanel/joinMachine.ts +12 -2
  185. package/src/panels/JoinPanel/steps/index.ts +0 -1
  186. package/src/panels/SpacePanel/steps/SpaceManager.tsx +3 -1
  187. package/src/panels/StatusPanel/StatusPanel.tsx +19 -0
  188. package/src/panels/StatusPanel/index.ts +5 -0
  189. package/src/panels/index.ts +1 -0
  190. package/src/playwright/invitations.spec.ts +3 -1
  191. package/src/steps/ConfirmReset.tsx +112 -0
  192. package/src/steps/InvitationManager.tsx +4 -4
  193. package/src/steps/StepProps.ts +2 -1
  194. package/src/steps/index.ts +1 -0
  195. package/src/stories/Invitations.e2e-stories.tsx +6 -3
  196. package/src/testing/shell-manager.ts +10 -9
  197. package/src/translations/locales/en-US.ts +22 -7
  198. package/src/types/index.ts +2 -0
  199. package/dist/types/src/components/IdentityList/DeviceList.d.ts +0 -7
  200. package/dist/types/src/components/IdentityList/DeviceList.d.ts.map +0 -1
  201. package/dist/types/src/components/IdentityList/DeviceList.js +0 -34
  202. package/dist/types/src/components/IdentityList/DeviceList.js.map +0 -1
  203. package/dist/types/src/panels/IdentityPanel/steps/AgentForm.d.ts +0 -3
  204. package/dist/types/src/panels/IdentityPanel/steps/AgentForm.d.ts.map +0 -1
  205. package/dist/types/src/panels/IdentityPanel/steps/AgentForm.js +0 -26
  206. package/dist/types/src/panels/IdentityPanel/steps/AgentForm.js.map +0 -1
  207. package/dist/types/src/panels/IdentityPanel/steps/DeviceManager.d.ts +0 -10
  208. package/dist/types/src/panels/IdentityPanel/steps/DeviceManager.d.ts.map +0 -1
  209. package/dist/types/src/panels/IdentityPanel/steps/DeviceManager.js +0 -23
  210. package/dist/types/src/panels/IdentityPanel/steps/DeviceManager.js.map +0 -1
  211. package/dist/types/src/panels/IdentityPanel/steps/SignOutChooser.d.ts +0 -16
  212. package/dist/types/src/panels/IdentityPanel/steps/SignOutChooser.d.ts.map +0 -1
  213. package/dist/types/src/panels/IdentityPanel/steps/SignOutChooser.js +0 -40
  214. package/dist/types/src/panels/IdentityPanel/steps/SignOutChooser.js.map +0 -1
  215. package/dist/types/src/panels/JoinPanel/steps/ResetIdentity.d.ts +0 -13
  216. package/dist/types/src/panels/JoinPanel/steps/ResetIdentity.d.ts.map +0 -1
  217. package/dist/types/src/panels/JoinPanel/steps/ResetIdentity.js +0 -66
  218. package/dist/types/src/panels/JoinPanel/steps/ResetIdentity.js.map +0 -1
  219. package/src/components/IdentityList/DeviceList.tsx +0 -49
  220. package/src/panels/IdentityPanel/steps/AgentForm.tsx +0 -61
  221. package/src/panels/IdentityPanel/steps/DeviceManager.tsx +0 -41
  222. package/src/panels/IdentityPanel/steps/SignOutChooser.tsx +0 -84
  223. package/src/panels/JoinPanel/steps/ResetIdentity.tsx +0 -80
@@ -3,11 +3,20 @@
3
3
  //
4
4
  import emojiData from '@emoji-mart/data';
5
5
  import EmojiMart from '@emoji-mart/react';
6
- import { ArrowCounterClockwise, CaretDown } from '@phosphor-icons/react';
6
+ import { ArrowCounterClockwise, CaretDown, ImageSquare } from '@phosphor-icons/react';
7
7
  import { useControllableState } from '@radix-ui/react-use-controllable-state';
8
- import React, { type Dispatch, type SetStateAction, useState } from 'react';
8
+ import React, { type Dispatch, type SetStateAction, useRef, useState } from 'react';
9
9
 
10
- import { Button, Popover, useTranslation, Tooltip, type ButtonProps } from '@dxos/react-ui';
10
+ import {
11
+ Button,
12
+ Popover,
13
+ useTranslation,
14
+ Tooltip,
15
+ type ButtonProps,
16
+ Toolbar,
17
+ useMediaQuery,
18
+ type ThemedClassName,
19
+ } from '@dxos/react-ui';
11
20
  import { getSize } from '@dxos/react-ui-theme';
12
21
 
13
22
  export type EmojiPickerProps = {
@@ -18,9 +27,98 @@ export type EmojiPickerProps = {
18
27
  onClickClear?: ButtonProps['onClick'];
19
28
  };
20
29
 
21
- export const EmojiPicker = ({ disabled, defaultEmoji, emoji, onChangeEmoji, onClickClear }: EmojiPickerProps) => {
30
+ /**
31
+ * A toolbar button for picking an emoji. Use only in `role=toolbar` elements. Unable to unset the value.
32
+ */
33
+ export const EmojiPickerToolbarButton = ({
34
+ disabled,
35
+ defaultEmoji,
36
+ emoji,
37
+ onChangeEmoji,
38
+ classNames,
39
+ }: ThemedClassName<Omit<EmojiPickerProps, 'onClickClear'>>) => {
22
40
  const { t } = useTranslation('os');
23
41
 
42
+ const [_emojiValue, setEmojiValue] = useControllableState<string>({
43
+ prop: emoji,
44
+ onChange: onChangeEmoji,
45
+ defaultProp: defaultEmoji,
46
+ });
47
+
48
+ const [emojiPickerOpen, setEmojiPickerOpen] = useState<boolean>(false);
49
+
50
+ const suppressNextTooltip = useRef<boolean>(false);
51
+ const [triggerTooltipOpen, setTriggerTooltipOpen] = useState(false);
52
+
53
+ return (
54
+ <Tooltip.Root
55
+ open={triggerTooltipOpen}
56
+ onOpenChange={(nextOpen) => {
57
+ if (suppressNextTooltip.current) {
58
+ setTriggerTooltipOpen(false);
59
+ suppressNextTooltip.current = false;
60
+ } else {
61
+ setTriggerTooltipOpen(nextOpen);
62
+ }
63
+ }}
64
+ >
65
+ <Popover.Root
66
+ open={emojiPickerOpen}
67
+ onOpenChange={(nextOpen) => {
68
+ setEmojiPickerOpen(nextOpen);
69
+ suppressNextTooltip.current = true;
70
+ }}
71
+ >
72
+ <Tooltip.Trigger asChild>
73
+ <Popover.Trigger asChild>
74
+ <Toolbar.Button classNames={['gap-2 text-2xl plb-1', classNames]} disabled={disabled}>
75
+ <span className='sr-only'>{t('select emoji label')}</span>
76
+ <ImageSquare className={getSize(5)} />
77
+ </Toolbar.Button>
78
+ </Popover.Trigger>
79
+ </Tooltip.Trigger>
80
+ <Tooltip.Portal>
81
+ <Tooltip.Content side='bottom' classNames='z-50'>
82
+ {t('select emoji label')}
83
+ <Tooltip.Arrow />
84
+ </Tooltip.Content>
85
+ </Tooltip.Portal>
86
+ <Popover.Content
87
+ side='bottom'
88
+ onKeyDownCapture={(event) => {
89
+ if (event.key === 'Escape') {
90
+ event.stopPropagation();
91
+ setEmojiPickerOpen(false);
92
+ suppressNextTooltip.current = true;
93
+ }
94
+ }}
95
+ >
96
+ <EmojiMart
97
+ data={emojiData}
98
+ onEmojiSelect={({ native }: { native?: string }) => {
99
+ if (native) {
100
+ setEmojiValue(native);
101
+ setEmojiPickerOpen(false);
102
+ }
103
+ }}
104
+ autoFocus={true}
105
+ maxFrequentRows={0}
106
+ noCountryFlags={true}
107
+ />
108
+ <Popover.Arrow />
109
+ </Popover.Content>
110
+ </Popover.Root>
111
+ </Tooltip.Root>
112
+ );
113
+ };
114
+
115
+ /**
116
+ * A button for picking an emoji alongside a button for unsetting it.
117
+ */
118
+ export const EmojiPickerBlock = ({ disabled, defaultEmoji, emoji, onChangeEmoji, onClickClear }: EmojiPickerProps) => {
119
+ const { t } = useTranslation('os');
120
+ const [isMd] = useMediaQuery('md', { ssr: false });
121
+
24
122
  const [emojiValue, setEmojiValue] = useControllableState<string>({
25
123
  prop: emoji,
26
124
  onChange: onChangeEmoji,
@@ -41,6 +139,7 @@ export const EmojiPicker = ({ disabled, defaultEmoji, emoji, onChangeEmoji, onCl
41
139
  </Popover.Trigger>
42
140
  <Popover.Content
43
141
  side='right'
142
+ sideOffset={isMd ? 0 : -310}
44
143
  onKeyDownCapture={(event) => {
45
144
  if (event.key === 'Escape') {
46
145
  event.stopPropagation();
@@ -1,12 +1,21 @@
1
1
  //
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
- import { ArrowCounterClockwise, CaretDown, Check } from '@phosphor-icons/react';
4
+ import { ArrowCounterClockwise, CaretDown, Check, Palette } from '@phosphor-icons/react';
5
5
  import { useControllableState } from '@radix-ui/react-use-controllable-state';
6
- import React, { type Dispatch, type SetStateAction } from 'react';
6
+ import React, { type Dispatch, type SetStateAction, useRef, useState } from 'react';
7
7
 
8
- import { Button, useTranslation, Tooltip, DropdownMenu, useThemeContext, type ButtonProps } from '@dxos/react-ui';
9
- import { getSize, hueTokenThemes } from '@dxos/react-ui-theme';
8
+ import {
9
+ Button,
10
+ useTranslation,
11
+ Tooltip,
12
+ DropdownMenu,
13
+ useThemeContext,
14
+ type ButtonProps,
15
+ Toolbar,
16
+ type ThemedClassName,
17
+ } from '@dxos/react-ui';
18
+ import { getSize, hueTokenThemes, mx } from '@dxos/react-ui-theme';
10
19
 
11
20
  const HuePreview = ({ hue }: { hue: string }) => {
12
21
  const { tx } = useThemeContext();
@@ -25,7 +34,92 @@ export type HuePickerProps = {
25
34
  onClickClear?: ButtonProps['onClick'];
26
35
  };
27
36
 
28
- export const HuePicker = ({ disabled, hue, onChangeHue, defaultHue, onClickClear }: HuePickerProps) => {
37
+ /**
38
+ * A toolbar button for picking hue. Use only in `role=toolbar` elements. Unable to unset the value.
39
+ */
40
+ export const HuePickerToolbarButton = ({
41
+ disabled,
42
+ hue,
43
+ onChangeHue,
44
+ classNames,
45
+ defaultHue,
46
+ }: ThemedClassName<Omit<HuePickerProps, 'onClickClear'>>) => {
47
+ const { t } = useTranslation('os');
48
+
49
+ const [hueValue, setHueValue] = useControllableState<string>({
50
+ prop: hue,
51
+ onChange: onChangeHue,
52
+ defaultProp: defaultHue,
53
+ });
54
+
55
+ const [huePickerOpen, setHuePickerOpen] = useState<boolean>(false);
56
+
57
+ const suppressNextTooltip = useRef<boolean>(false);
58
+ const [triggerTooltipOpen, setTriggerTooltipOpen] = useState(false);
59
+
60
+ return (
61
+ <Tooltip.Root
62
+ open={triggerTooltipOpen}
63
+ onOpenChange={(nextOpen) => {
64
+ if (suppressNextTooltip.current) {
65
+ setTriggerTooltipOpen(false);
66
+ suppressNextTooltip.current = false;
67
+ } else {
68
+ setTriggerTooltipOpen(nextOpen);
69
+ }
70
+ }}
71
+ >
72
+ <DropdownMenu.Root
73
+ modal={false}
74
+ open={huePickerOpen}
75
+ onOpenChange={(nextOpen) => {
76
+ setHuePickerOpen(nextOpen);
77
+ suppressNextTooltip.current = true;
78
+ }}
79
+ >
80
+ <Tooltip.Trigger asChild>
81
+ <DropdownMenu.Trigger asChild>
82
+ <Toolbar.Button classNames={mx('gap-2 plb-1', classNames)} disabled={disabled}>
83
+ <span className='sr-only'>{t('select hue label')}</span>
84
+ <Palette className={getSize(5)} />
85
+ </Toolbar.Button>
86
+ </DropdownMenu.Trigger>
87
+ </Tooltip.Trigger>
88
+ <Tooltip.Portal>
89
+ <Tooltip.Content side='bottom' classNames='z-50'>
90
+ {t('select hue label')}
91
+ <Tooltip.Arrow />
92
+ </Tooltip.Content>
93
+ </Tooltip.Portal>
94
+ <DropdownMenu.Content side='bottom'>
95
+ <DropdownMenu.Viewport>
96
+ {Object.keys(hueTokenThemes).map((hue) => {
97
+ return (
98
+ <DropdownMenu.CheckboxItem
99
+ key={hue}
100
+ checked={hue === hueValue}
101
+ onCheckedChange={() => setHueValue(hue)}
102
+ >
103
+ <HuePreview hue={hue} />
104
+ <span className='grow'>{t(`${hue} label`)}</span>
105
+ <DropdownMenu.ItemIndicator>
106
+ <Check />
107
+ </DropdownMenu.ItemIndicator>
108
+ </DropdownMenu.CheckboxItem>
109
+ );
110
+ })}
111
+ </DropdownMenu.Viewport>
112
+ <DropdownMenu.Arrow />
113
+ </DropdownMenu.Content>
114
+ </DropdownMenu.Root>
115
+ </Tooltip.Root>
116
+ );
117
+ };
118
+
119
+ /**
120
+ * A button for picking hue alongside a button for unsetting it.
121
+ */
122
+ export const HuePickerBlock = ({ disabled, hue, onChangeHue, defaultHue, onClickClear }: HuePickerProps) => {
29
123
  const { t } = useTranslation('os');
30
124
 
31
125
  const [hueValue, setHueValue] = useControllableState<string>({
@@ -2,6 +2,5 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- export * from './DeviceList';
6
5
  export * from './IdentityListItem';
7
6
  export * from './SpaceMemberList';
@@ -96,14 +96,14 @@ export const InvitationListItemImpl = ({
96
96
  ...props
97
97
  }: InvitationListItemImplProps) => {
98
98
  const { t } = useTranslation('os');
99
- const { cancel, status: invitationStatus, invitationCode, authCode, type } = propsInvitationStatus;
99
+ const { cancel, status: invitationStatus, invitationCode, authCode, multiUse } = propsInvitationStatus;
100
100
 
101
101
  const isCancellable = !(
102
102
  [Invitation.State.ERROR, Invitation.State.TIMEOUT, Invitation.State.CANCELLED].indexOf(invitationStatus) >= 0
103
103
  );
104
104
 
105
105
  const showShare =
106
- type === Invitation.Type.MULTIUSE ||
106
+ multiUse ||
107
107
  [Invitation.State.INIT, Invitation.State.CONNECTING, Invitation.State.CONNECTED].indexOf(invitationStatus) >= 0;
108
108
 
109
109
  const showAuthCode = invitationStatus === Invitation.State.READY_FOR_AUTHENTICATION;
@@ -147,9 +147,9 @@ export const InvitationListItemImpl = ({
147
147
  classNames={['flex gap-2 pis-3 pie-1 items-center relative', props.classNames]}
148
148
  >
149
149
  <ListItem.Heading classNames='sr-only'>
150
- {t(type === Invitation.Type.MULTIUSE ? 'invite many list item label' : 'invite one list item label')}
150
+ {t(multiUse ? 'invite many list item label' : 'invite one list item label')}
151
151
  </ListItem.Heading>
152
- {type === Invitation.Type.MULTIUSE && (
152
+ {multiUse && (
153
153
  <AvatarStackEffect status={avatarStatus} animation={avatarAnimation} reverseEffects={reverseEffects} />
154
154
  )}
155
155
  <Tooltip.Root>
@@ -162,7 +162,7 @@ export const InvitationListItemImpl = ({
162
162
  </Avatar.Root>
163
163
  <Tooltip.Portal>
164
164
  <Tooltip.Content side='left' classNames='z-[70]'>
165
- {t(type === Invitation.Type.MULTIUSE ? 'invite many qr label' : 'invite one qr label')}
165
+ {t(multiUse ? 'invite many qr label' : 'invite one qr label')}
166
166
  <Tooltip.Arrow />
167
167
  </Tooltip.Content>
168
168
  </Tooltip.Portal>
@@ -2,11 +2,13 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ export * from './AgentConfig';
5
6
  export * from './Clipboard';
6
7
  export * from './CompoundButton';
7
8
  export * from './EmojiPicker';
8
9
  export * from './HuePicker';
9
10
  export * from './IdentityList';
11
+ export * from './DeviceList';
10
12
  export * from './InvitationList';
11
13
  export * from './Panel';
12
14
  export * from './Viewport';
@@ -16,7 +16,7 @@ export interface IdentityDialogProps
16
16
  }
17
17
 
18
18
  export const IdentityDialog = (props: IdentityDialogProps) => {
19
- const titleId = useId('spaceDialog__title');
19
+ const titleId = useId('identityDialog__title', props.title);
20
20
  return (
21
21
  <Dialog.Root defaultOpen onOpenChange={(open) => open || props.onDone?.()}>
22
22
  <Dialog.Portal>
@@ -11,6 +11,7 @@ import { useSpace } from '@dxos/react-client/echo';
11
11
  import { IdentityDialog } from '../IdentityDialog';
12
12
  import { JoinDialog } from '../JoinDialog';
13
13
  import { SpaceDialog } from '../SpaceDialog';
14
+ import { StatusDialog } from '../StatusDialog';
14
15
 
15
16
  export const Shell = ({ runtime, origin }: { runtime: ShellRuntime; origin: string }) => {
16
17
  const [{ layout, invitationCode, spaceKey, target }, setLayout] = useState<LayoutRequest>({
@@ -41,11 +42,18 @@ export const Shell = ({ runtime, origin }: { runtime: ShellRuntime; origin: stri
41
42
  }, [runtime, layout, space]);
42
43
 
43
44
  switch (layout) {
45
+ case ShellLayout.STATUS:
46
+ return <StatusDialog />;
44
47
  case ShellLayout.INITIALIZE_IDENTITY:
48
+ case ShellLayout.INITIALIZE_IDENTITY_FROM_INVITATION:
45
49
  return (
46
50
  <JoinDialog
47
51
  mode='halo-only'
52
+ initialDisposition={
53
+ layout === ShellLayout.INITIALIZE_IDENTITY_FROM_INVITATION ? 'accept-halo-invitation' : 'default'
54
+ }
48
55
  initialInvitationCode={invitationCode}
56
+ onCancelResetStorage={() => runtime.setLayout({ layout: ShellLayout.IDENTITY })}
49
57
  onDone={() => {
50
58
  void runtime.setAppContext({ display: ShellDisplay.NONE });
51
59
  runtime.setLayout({ layout: ShellLayout.DEFAULT });
@@ -53,22 +61,27 @@ export const Shell = ({ runtime, origin }: { runtime: ShellRuntime; origin: stri
53
61
  />
54
62
  );
55
63
 
56
- // TODO(wittjosiah): Jump straight to specific step if SHARE or EDIT are specified.
57
64
  case ShellLayout.IDENTITY:
58
65
  case ShellLayout.SHARE_IDENTITY:
59
66
  case ShellLayout.EDIT_PROFILE:
60
67
  return (
61
68
  <IdentityDialog
62
69
  createInvitationUrl={(invitationCode) => `${origin}?deviceInvitationCode=${invitationCode}`}
63
- onResetDevice={async () => {
70
+ onResetStorage={async () => {
71
+ runtime.setLayout({ layout: ShellLayout.STATUS });
64
72
  await client.reset();
65
- await runtime.setAppContext({ display: ShellDisplay.NONE, reload: true });
73
+ return runtime.setAppContext({ display: ShellDisplay.NONE, reload: true });
74
+ }}
75
+ onJoinNewIdentity={async () => {
76
+ runtime.setLayout({ layout: ShellLayout.STATUS });
77
+ await client.reset();
78
+ return runtime.setLayout({ layout: ShellLayout.INITIALIZE_IDENTITY_FROM_INVITATION });
66
79
  }}
67
- onJoinNewIdentity={() => runtime.setLayout({ layout: ShellLayout.INITIALIZE_IDENTITY })}
68
80
  onDone={async () => {
69
81
  await runtime.setAppContext({ display: ShellDisplay.NONE });
70
82
  runtime.setLayout({ layout: ShellLayout.DEFAULT });
71
83
  }}
84
+ initialDisposition={layout === ShellLayout.SHARE_IDENTITY ? 'manage-device-invitation' : 'default'}
72
85
  />
73
86
  );
74
87
 
@@ -0,0 +1,24 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ import { AlertDialog, useId } from '@dxos/react-ui';
8
+
9
+ import { StatusPanel } from '../../panels';
10
+
11
+ export const StatusDialog = () => {
12
+ const titleId = useId('statusDialog__title');
13
+ return (
14
+ <AlertDialog.Root open>
15
+ <AlertDialog.Portal>
16
+ <AlertDialog.Overlay>
17
+ <AlertDialog.Content aria-labelledby={titleId}>
18
+ <StatusPanel titleId={titleId} />
19
+ </AlertDialog.Content>
20
+ </AlertDialog.Overlay>
21
+ </AlertDialog.Portal>
22
+ </AlertDialog.Root>
23
+ );
24
+ };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ export * from './StatusDialog';
@@ -8,7 +8,6 @@ import React from 'react';
8
8
 
9
9
  import { faker } from '@dxos/random';
10
10
  import { PublicKey } from '@dxos/react-client';
11
- import { Device, DeviceKind } from '@dxos/react-client/halo';
12
11
  import { Invitation } from '@dxos/react-client/invitations';
13
12
  import { withTheme } from '@dxos/storybook-utils';
14
13
 
@@ -53,58 +52,6 @@ export const IdentityActionChooser = () => {
53
52
  );
54
53
  };
55
54
 
56
- export const UpdateProfileForm = () => {
57
- return (
58
- <StorybookDialog inOverlayLayout>
59
- <IdentityPanelImpl
60
- {...noOpProps}
61
- activeView='update profile form'
62
- IdentityActionChooser={IdentityActionChooserImpl}
63
- />
64
- </StorybookDialog>
65
- );
66
- };
67
-
68
- export const DeviceManager = () => {
69
- return (
70
- <StorybookDialog inOverlayLayout>
71
- <IdentityPanelImpl
72
- {...{
73
- ...noOpProps,
74
- // TODO(nf): update
75
- devices: [
76
- {
77
- deviceKey: PublicKey.random(),
78
- kind: DeviceKind.CURRENT,
79
- presence: Device.PresenceState.ONLINE,
80
- },
81
- {
82
- deviceKey: PublicKey.random(),
83
- kind: DeviceKind.TRUSTED,
84
- presence: Device.PresenceState.ONLINE,
85
- },
86
- {
87
- deviceKey: PublicKey.random(),
88
- kind: DeviceKind.TRUSTED,
89
- presence: Device.PresenceState.OFFLINE,
90
- },
91
- ],
92
- }}
93
- activeView='device manager'
94
- IdentityActionChooser={IdentityActionChooserImpl}
95
- />
96
- </StorybookDialog>
97
- );
98
- };
99
-
100
- export const DeviceManagerEmpty = () => {
101
- return (
102
- <StorybookDialog inOverlayLayout>
103
- <IdentityPanelImpl {...noOpProps} activeView='device manager' IdentityActionChooser={IdentityActionChooserImpl} />
104
- </StorybookDialog>
105
- );
106
- };
107
-
108
55
  const DeviceInvitationManagerWithState = (extraProps: InvitationManagerProps) => (
109
56
  <StorybookDialog inOverlayLayout>
110
57
  <IdentityPanelImpl
@@ -156,13 +103,3 @@ export const DeviceInvitationManagerCancelled = () =>
156
103
  DeviceInvitationManagerWithState({
157
104
  status: Invitation.State.CANCELLED,
158
105
  });
159
-
160
- // export const IdentityActionChooser = {
161
- // decorators: [ClientDecorator()],
162
- // args: { activeView: 'identity action chooser' },
163
- // };
164
-
165
- // export const DeviceManager = {
166
- // decorators: [ClientDecorator()],
167
- // args: { activeView: 'device manager' },
168
- // };