@dxos/plugin-simple-layout 0.8.4-main.2244d791bb → 0.8.4-main.4a85c3132b

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 (66) hide show
  1. package/dist/lib/browser/{chunk-U632CHRU.mjs → chunk-TMZNLVT2.mjs} +130 -127
  2. package/dist/lib/browser/chunk-TMZNLVT2.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +2 -2
  4. package/dist/lib/browser/meta.json +1 -1
  5. package/dist/lib/browser/{react-root-ZQTWLJYR.mjs → react-root-MMB575WY.mjs} +2 -2
  6. package/dist/lib/browser/{react-surface-IOYDLMNR.mjs → react-surface-M6CURANW.mjs} +2 -2
  7. package/dist/lib/node-esm/{chunk-UXFYLQJA.mjs → chunk-FLOYBAHE.mjs} +130 -127
  8. package/dist/lib/node-esm/chunk-FLOYBAHE.mjs.map +7 -0
  9. package/dist/lib/node-esm/index.mjs +2 -2
  10. package/dist/lib/node-esm/meta.json +1 -1
  11. package/dist/lib/node-esm/{react-root-FMAUHDJI.mjs → react-root-ENZKVSY4.mjs} +2 -2
  12. package/dist/lib/node-esm/{react-surface-ZAZRIKZQ.mjs → react-surface-ITVNQYLG.mjs} +2 -2
  13. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts +1 -1
  14. package/dist/types/src/capabilities/react-root/react-root.d.ts +1 -1
  15. package/dist/types/src/capabilities/react-surface/react-surface.d.ts +1 -1
  16. package/dist/types/src/capabilities/spotlight-dismiss/index.d.ts +1 -1
  17. package/dist/types/src/capabilities/spotlight-dismiss/index.d.ts.map +1 -1
  18. package/dist/types/src/capabilities/spotlight-dismiss/spotlight-dismiss.d.ts +1 -1
  19. package/dist/types/src/capabilities/state/index.d.ts +1 -1
  20. package/dist/types/src/capabilities/state/state.d.ts +1 -1
  21. package/dist/types/src/capabilities/url-handler/url-handler.d.ts +1 -1
  22. package/dist/types/src/components/ContentError.stories.d.ts +1 -3
  23. package/dist/types/src/components/ContentError.stories.d.ts.map +1 -1
  24. package/dist/types/src/components/Home/Home.d.ts.map +1 -1
  25. package/dist/types/src/components/MobileLayout/MobileLayout.stories.d.ts.map +1 -1
  26. package/dist/types/src/components/Popover/Popover.d.ts.map +1 -1
  27. package/dist/types/src/components/SimpleLayout/AppBar.d.ts.map +1 -1
  28. package/dist/types/src/components/SimpleLayout/Drawer.d.ts.map +1 -1
  29. package/dist/types/src/components/SimpleLayout/Main.d.ts.map +1 -1
  30. package/dist/types/src/components/SimpleLayout/NavBar.d.ts.map +1 -1
  31. package/dist/types/src/components/Workspace/Workspace.d.ts.map +1 -1
  32. package/dist/types/src/hooks/useAppBarProps.d.ts.map +1 -1
  33. package/dist/types/tsconfig.tsbuildinfo +1 -1
  34. package/package.json +29 -28
  35. package/src/components/ContentError.stories.tsx +7 -6
  36. package/src/components/ContentLoading.stories.tsx +1 -1
  37. package/src/components/ContentLoading.tsx +1 -1
  38. package/src/components/Dialog/Dialog.tsx +3 -3
  39. package/src/components/Home/Home.tsx +25 -20
  40. package/src/components/MobileLayout/MobileLayout.stories.tsx +23 -19
  41. package/src/components/MobileLayout/MobileLayout.tsx +2 -2
  42. package/src/components/Popover/Popover.tsx +14 -4
  43. package/src/components/SimpleLayout/AppBar.stories.tsx +2 -2
  44. package/src/components/SimpleLayout/AppBar.tsx +17 -20
  45. package/src/components/SimpleLayout/Drawer.tsx +12 -9
  46. package/src/components/SimpleLayout/Main.tsx +8 -6
  47. package/src/components/SimpleLayout/NavBar.stories.tsx +8 -8
  48. package/src/components/SimpleLayout/NavBar.tsx +4 -10
  49. package/src/components/SimpleLayout/SimpleLayout.stories.tsx +2 -2
  50. package/src/components/SimpleLayout/SimpleLayout.tsx +1 -1
  51. package/src/components/Workspace/Workspace.tsx +25 -20
  52. package/src/components/hooks.ts +3 -3
  53. package/src/hooks/actions.ts +2 -2
  54. package/src/hooks/useAppBarProps.ts +7 -3
  55. package/src/hooks/useCompanions.ts +1 -1
  56. package/src/hooks/useDrawerActions.ts +2 -2
  57. package/src/hooks/useNavbarActions.ts +5 -5
  58. package/dist/lib/browser/chunk-U632CHRU.mjs.map +0 -7
  59. package/dist/lib/node-esm/chunk-UXFYLQJA.mjs.map +0 -7
  60. package/dist/types/src/components/ContentError.d.ts +0 -5
  61. package/dist/types/src/components/ContentError.d.ts.map +0 -1
  62. package/src/components/ContentError.tsx +0 -23
  63. /package/dist/lib/browser/{react-root-ZQTWLJYR.mjs.map → react-root-MMB575WY.mjs.map} +0 -0
  64. /package/dist/lib/browser/{react-surface-IOYDLMNR.mjs.map → react-surface-M6CURANW.mjs.map} +0 -0
  65. /package/dist/lib/node-esm/{react-root-FMAUHDJI.mjs.map → react-root-ENZKVSY4.mjs.map} +0 -0
  66. /package/dist/lib/node-esm/{react-surface-ZAZRIKZQ.mjs.map → react-surface-ITVNQYLG.mjs.map} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/plugin-simple-layout",
3
- "version": "0.8.4-main.2244d791bb",
3
+ "version": "0.8.4-main.4a85c3132b",
4
4
  "description": "Simple layout plugin for minimal UI contexts like popover windows.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -14,9 +14,9 @@
14
14
  "type": "module",
15
15
  "exports": {
16
16
  ".": {
17
+ "source": "./src/index.ts",
17
18
  "browser": "./dist/lib/browser/index.mjs",
18
19
  "node": "./dist/lib/node-esm/index.mjs",
19
- "source": "./src/index.ts",
20
20
  "types": "./dist/types/src/index.d.ts"
21
21
  }
22
22
  },
@@ -31,19 +31,20 @@
31
31
  "@radix-ui/react-context": "1.1.1",
32
32
  "@tauri-apps/plugin-deep-link": "^2.2.0",
33
33
  "@tauri-apps/plugin-haptics": "^2.3.2",
34
- "@dxos/app-framework": "0.8.4-main.2244d791bb",
35
- "@dxos/async": "0.8.4-main.2244d791bb",
36
- "@dxos/app-toolkit": "0.8.4-main.2244d791bb",
37
- "@dxos/log": "0.8.4-main.2244d791bb",
38
- "@dxos/operation": "0.8.4-main.2244d791bb",
39
- "@dxos/plugin-graph": "0.8.4-main.2244d791bb",
40
- "@dxos/react-ui-attention": "0.8.4-main.2244d791bb",
41
- "@dxos/react-ui-menu": "0.8.4-main.2244d791bb",
42
- "@dxos/react-ui-mosaic": "0.8.4-main.2244d791bb",
43
- "@dxos/react-ui-searchlist": "0.8.4-main.2244d791bb",
44
- "@dxos/react-ui-stack": "0.8.4-main.2244d791bb",
45
- "@dxos/schema": "0.8.4-main.2244d791bb",
46
- "@dxos/util": "0.8.4-main.2244d791bb"
34
+ "@dxos/app-framework": "0.8.4-main.4a85c3132b",
35
+ "@dxos/echo": "0.8.4-main.4a85c3132b",
36
+ "@dxos/async": "0.8.4-main.4a85c3132b",
37
+ "@dxos/app-toolkit": "0.8.4-main.4a85c3132b",
38
+ "@dxos/log": "0.8.4-main.4a85c3132b",
39
+ "@dxos/operation": "0.8.4-main.4a85c3132b",
40
+ "@dxos/react-ui-menu": "0.8.4-main.4a85c3132b",
41
+ "@dxos/react-ui-attention": "0.8.4-main.4a85c3132b",
42
+ "@dxos/react-ui-mosaic": "0.8.4-main.4a85c3132b",
43
+ "@dxos/react-ui-searchlist": "0.8.4-main.4a85c3132b",
44
+ "@dxos/react-ui-stack": "0.8.4-main.4a85c3132b",
45
+ "@dxos/schema": "0.8.4-main.4a85c3132b",
46
+ "@dxos/util": "0.8.4-main.4a85c3132b",
47
+ "@dxos/plugin-graph": "0.8.4-main.4a85c3132b"
47
48
  },
48
49
  "devDependencies": {
49
50
  "@types/react": "~19.2.7",
@@ -51,24 +52,24 @@
51
52
  "effect": "3.19.16",
52
53
  "react": "~19.2.3",
53
54
  "react-dom": "~19.2.3",
54
- "vite": "7.1.9",
55
- "@dxos/app-graph": "0.8.4-main.2244d791bb",
56
- "@dxos/plugin-preview": "0.8.4-main.2244d791bb",
57
- "@dxos/plugin-client": "0.8.4-main.2244d791bb",
58
- "@dxos/plugin-search": "0.8.4-main.2244d791bb",
59
- "@dxos/plugin-space": "0.8.4-main.2244d791bb",
60
- "@dxos/react-ui": "0.8.4-main.2244d791bb",
61
- "@dxos/plugin-testing": "0.8.4-main.2244d791bb",
62
- "@dxos/storybook-utils": "0.8.4-main.2244d791bb",
63
- "@dxos/schema": "0.8.4-main.2244d791bb",
64
- "@dxos/ui-theme": "0.8.4-main.2244d791bb"
55
+ "vite": "^7.1.11",
56
+ "@dxos/plugin-preview": "0.8.4-main.4a85c3132b",
57
+ "@dxos/plugin-client": "0.8.4-main.4a85c3132b",
58
+ "@dxos/app-graph": "0.8.4-main.4a85c3132b",
59
+ "@dxos/plugin-space": "0.8.4-main.4a85c3132b",
60
+ "@dxos/plugin-search": "0.8.4-main.4a85c3132b",
61
+ "@dxos/react-ui": "0.8.4-main.4a85c3132b",
62
+ "@dxos/schema": "0.8.4-main.4a85c3132b",
63
+ "@dxos/storybook-utils": "0.8.4-main.4a85c3132b",
64
+ "@dxos/plugin-testing": "0.8.4-main.4a85c3132b",
65
+ "@dxos/ui-theme": "0.8.4-main.4a85c3132b"
65
66
  },
66
67
  "peerDependencies": {
67
68
  "effect": "3.19.16",
68
69
  "react": "~19.2.3",
69
70
  "react-dom": "~19.2.3",
70
- "@dxos/react-ui": "0.8.4-main.2244d791bb",
71
- "@dxos/ui-theme": "0.8.4-main.2244d791bb"
71
+ "@dxos/react-ui": "0.8.4-main.4a85c3132b",
72
+ "@dxos/ui-theme": "0.8.4-main.4a85c3132b"
72
73
  },
73
74
  "publishConfig": {
74
75
  "access": "public"
@@ -4,28 +4,29 @@
4
4
 
5
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
6
6
 
7
+ import { ErrorFallback } from '@dxos/react-ui';
7
8
  import { withTheme } from '@dxos/react-ui/testing';
8
9
 
9
10
  import { translations } from '../translations';
10
11
 
11
- import { ContentError } from './ContentError';
12
-
13
12
  const meta = {
14
- title: 'plugins/plugin-simple-layout/ContentError',
15
- component: ContentError,
13
+ title: 'plugins/plugin-simple-layout/components/ErrorFallback',
14
+ component: ErrorFallback,
16
15
  decorators: [withTheme()],
17
16
  parameters: {
18
17
  layout: 'centered',
19
18
  translations,
20
19
  },
21
- } satisfies Meta<typeof ContentError>;
20
+ } satisfies Meta<typeof ErrorFallback>;
22
21
 
23
22
  export default meta;
24
23
 
25
24
  type Story = StoryObj<typeof meta>;
26
25
 
27
26
  export const Default: Story = {
28
- args: {},
27
+ args: {
28
+ error: new Error('An unexpected error occurred'),
29
+ },
29
30
  };
30
31
 
31
32
  export const WithError: Story = {
@@ -9,7 +9,7 @@ import { withTheme } from '@dxos/react-ui/testing';
9
9
  import { ContentLoading } from './ContentLoading';
10
10
 
11
11
  const meta = {
12
- title: 'plugins/plugin-simple-layout/ContentLoading',
12
+ title: 'plugins/plugin-simple-layout/components/ContentLoading',
13
13
  component: ContentLoading,
14
14
  decorators: [withTheme()],
15
15
  parameters: {
@@ -6,5 +6,5 @@ import React from 'react';
6
6
 
7
7
  // TODO(burdon): Show skeleton: https://github.com/dxos/dxos/issues/8259
8
8
  export const ContentLoading = () => {
9
- return <div role='none' className='grid place-items-center attention-surface' />;
9
+ return <div role='none' className='grid place-items-center dx-attention-surface' />;
10
10
  };
@@ -6,9 +6,9 @@ import React from 'react';
6
6
 
7
7
  import { Surface } from '@dxos/app-framework/ui';
8
8
  import { AlertDialog, Dialog as NaturalDialog } from '@dxos/react-ui';
9
+ import { ErrorFallback } from '@dxos/react-ui';
9
10
 
10
11
  import { useSimpleLayoutState } from '../../hooks';
11
- import { ContentError } from '../ContentError';
12
12
 
13
13
  export const Dialog = () => {
14
14
  const { state, updateState } = useSimpleLayoutState();
@@ -23,14 +23,14 @@ export const Dialog = () => {
23
23
  onOpenChange={(nextOpen) => updateState((state) => ({ ...state, dialogOpen: nextOpen }))}
24
24
  >
25
25
  {state.dialogBlockAlign === 'end' ? (
26
- <Surface.Surface role='dialog' data={state.dialogContent} limit={1} fallback={ContentError} />
26
+ <Surface.Surface role='dialog' data={state.dialogContent} limit={1} fallback={ErrorFallback} />
27
27
  ) : (
28
28
  <DialogOverlay
29
29
  blockAlign={state.dialogBlockAlign}
30
30
  classNames={state.dialogOverlayClasses}
31
31
  style={state.dialogOverlayStyle}
32
32
  >
33
- <Surface.Surface role='dialog' data={state.dialogContent} limit={1} fallback={ContentError} />
33
+ <Surface.Surface role='dialog' data={state.dialogContent} limit={1} fallback={ErrorFallback} />
34
34
  </DialogOverlay>
35
35
  )}
36
36
  </DialogRoot>
@@ -8,8 +8,9 @@ import { useOperationInvoker } from '@dxos/app-framework/ui';
8
8
  import { LayoutOperation } from '@dxos/app-toolkit';
9
9
  import { useAppGraph } from '@dxos/app-toolkit/ui';
10
10
  import { Node, useConnections } from '@dxos/plugin-graph';
11
- import { Avatar, Icon, Layout, ScrollArea, Toolbar, toLocalizedString, useTranslation } from '@dxos/react-ui';
12
- import { Card, Mosaic, type MosaicStackTileComponent } from '@dxos/react-ui-mosaic';
11
+ import { Avatar, Icon, Panel, ScrollArea, Toolbar, toLocalizedString, useTranslation } from '@dxos/react-ui';
12
+ import { Card } from '@dxos/react-ui';
13
+ import { Mosaic, type MosaicStackTileComponent } from '@dxos/react-ui-mosaic';
13
14
  import { SearchList, useSearchListItem, useSearchListResults } from '@dxos/react-ui-searchlist';
14
15
  import { mx } from '@dxos/ui-theme';
15
16
  import { byPosition } from '@dxos/util';
@@ -40,22 +41,26 @@ export const Home = (_: HomeProps) => {
40
41
  });
41
42
 
42
43
  return (
43
- <Layout.Main toolbar>
44
- <SearchList.Root onSearch={handleSearch}>
45
- <Toolbar.Root>
46
- <SearchList.Input placeholder={t('search placeholder')} autoFocus />
47
- </Toolbar.Root>
48
- <SearchList.Content>
49
- <Mosaic.Container asChild>
50
- <ScrollArea.Root orientation='vertical'>
51
- <ScrollArea.Viewport classNames='p-2'>
52
- <Mosaic.Stack items={results} getId={(node) => node.id} Tile={WorkspaceTile} />
53
- </ScrollArea.Viewport>
54
- </ScrollArea.Root>
55
- </Mosaic.Container>
56
- </SearchList.Content>
57
- </SearchList.Root>
58
- </Layout.Main>
44
+ <SearchList.Root onSearch={handleSearch}>
45
+ <Panel.Root>
46
+ <Panel.Toolbar asChild>
47
+ <Toolbar.Root>
48
+ <SearchList.Input placeholder={t('search placeholder')} autoFocus />
49
+ </Toolbar.Root>
50
+ </Panel.Toolbar>
51
+ <Panel.Content asChild>
52
+ <SearchList.Content>
53
+ <Mosaic.Container asChild>
54
+ <ScrollArea.Root orientation='vertical'>
55
+ <ScrollArea.Viewport classNames='p-2'>
56
+ <Mosaic.Stack items={results} getId={(node) => node.id} Tile={WorkspaceTile} />
57
+ </ScrollArea.Viewport>
58
+ </ScrollArea.Root>
59
+ </Mosaic.Container>
60
+ </SearchList.Content>
61
+ </Panel.Content>
62
+ </Panel.Root>
63
+ </SearchList.Root>
59
64
  );
60
65
  };
61
66
 
@@ -97,7 +102,7 @@ const WorkspaceTile: MosaicStackTileComponent<Node.Node> = (props) => {
97
102
  fullWidth
98
103
  tabIndex={-1} // TODO(burdon): Use Mosaic.Focus.
99
104
  data-selected={isSelected}
100
- classNames={mx('dx-focus-ring', isSelected && 'bg-hoverOverlay')}
105
+ classNames={mx('dx-focus-ring', isSelected && 'bg-hover-overlay')}
101
106
  onClick={handleSelect}
102
107
  ref={cardRef}
103
108
  >
@@ -127,7 +132,7 @@ const filterItems = (node: Node.Node, disposition: string) => {
127
132
  /** Returns root-level items filtered by disposition. */
128
133
  const useItemsByDisposition = (disposition: string, sort = false) => {
129
134
  const { graph } = useAppGraph();
130
- const connections = useConnections(graph, Node.RootId);
135
+ const connections = useConnections(graph, Node.RootId, 'child');
131
136
  const filtered = connections.filter((node) => filterItems(node, disposition));
132
137
  return sort ? filtered.toSorted((a, b) => byPosition(a.properties, b.properties)) : filtered;
133
138
  };
@@ -6,7 +6,7 @@ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
6
  import React, { type PropsWithChildren, useEffect, useState } from 'react';
7
7
 
8
8
  import { addEventListener, combine } from '@dxos/async';
9
- import { Flex, Input, Layout, Splitter, type SplitterMode, Toolbar } from '@dxos/react-ui';
9
+ import { Flex, Input, Panel, Splitter, type SplitterMode, Toolbar } from '@dxos/react-ui';
10
10
  import { withLayout, withTheme } from '@dxos/react-ui/testing';
11
11
 
12
12
  import { MobileLayout, type MobileLayoutRootProps } from './MobileLayout';
@@ -54,20 +54,24 @@ const WithKeyboard = ({ children }: PropsWithChildren) => {
54
54
  return <div className='h-screen relative'>{children}</div>;
55
55
  };
56
56
 
57
- const Panel = ({ children, label }: PropsWithChildren<{ label: string }>) => {
57
+ const StoryPanel = ({ children, label }: PropsWithChildren<{ label: string }>) => {
58
58
  return (
59
- <Layout.Main toolbar>
60
- <Toolbar.Root>
61
- {label}
62
- <Toolbar.Separator variant='gap' />
63
- {children}
64
- </Toolbar.Root>
65
- <Flex column classNames='p-1'>
66
- <Input.Root>
67
- <Input.TextInput />
68
- </Input.Root>
69
- </Flex>
70
- </Layout.Main>
59
+ <Panel.Root>
60
+ <Panel.Toolbar asChild>
61
+ <Toolbar.Root>
62
+ {label}
63
+ <Toolbar.Separator />
64
+ {children}
65
+ </Toolbar.Root>
66
+ </Panel.Toolbar>
67
+ <Panel.Content asChild>
68
+ <Flex column classNames='p-1'>
69
+ <Input.Root>
70
+ <Input.TextInput />
71
+ </Input.Root>
72
+ </Flex>
73
+ </Panel.Content>
74
+ </Panel.Root>
71
75
  );
72
76
  };
73
77
 
@@ -85,21 +89,21 @@ const DefaultStory = () => {
85
89
  <MobileLayout.Panel safe={{ top: true, bottom: splitterMode === 'upper' }}>
86
90
  <Splitter.Root mode={splitterMode} ratio={0.5}>
87
91
  <Splitter.Panel position='upper'>
88
- <Panel label='Main'>
92
+ <StoryPanel label='Main'>
89
93
  {splitterMode === 'upper' && (
90
94
  <Toolbar.IconButton icon='ph--plus--regular' label='Open' onClick={() => setSplitterMode('both')} />
91
95
  )}
92
- </Panel>
96
+ </StoryPanel>
93
97
  </Splitter.Panel>
94
98
  <Splitter.Panel position='lower'>
95
- <Panel label='Drawer'>
99
+ <StoryPanel label='Drawer'>
96
100
  <Toolbar.IconButton
97
101
  icon={splitterMode === 'lower' ? 'ph--arrow-down--regular' : 'ph--arrow-up--regular'}
98
102
  label={splitterMode === 'lower' ? 'Collapse' : 'Expand'}
99
103
  onClick={() => setSplitterMode((splitterMode) => (splitterMode === 'both' ? 'lower' : 'both'))}
100
104
  />
101
105
  <Toolbar.IconButton icon='ph--x--regular' label='Close' onClick={() => setSplitterMode('upper')} />
102
- </Panel>
106
+ </StoryPanel>
103
107
  </Splitter.Panel>
104
108
  </Splitter.Root>
105
109
  </MobileLayout.Panel>
@@ -109,7 +113,7 @@ const DefaultStory = () => {
109
113
  };
110
114
 
111
115
  const meta: Meta<MobileLayoutRootProps> = {
112
- title: 'plugins/plugin-simple-layout/MobileLayout',
116
+ title: 'plugins/plugin-simple-layout/components/MobileLayout',
113
117
  component: MobileLayout.Root,
114
118
  render: DefaultStory,
115
119
  decorators: [withTheme(), withLayout({ layout: 'column', classNames: 'relative' })],
@@ -54,7 +54,7 @@ const MobileLayoutRoot = forwardRef<HTMLDivElement, MobileLayoutRootProps>(
54
54
  {...props}
55
55
  role='none'
56
56
  style={{
57
- transition: `block-size ${transition}ms ease-out`,
57
+ transition: `h-size ${transition}ms ease-out`,
58
58
  blockSize: 'calc(100vh - var(--kb-height, 0px))',
59
59
  }}
60
60
  className={mx('absolute top-0 left-0 right-0 flex flex-col', classNames)}
@@ -95,7 +95,7 @@ const MobileLayoutPanel = forwardRef<HTMLDivElement, MobileLayoutPanelProps>(
95
95
  paddingTop: safe?.top ? 'env(safe-area-inset-top)' : undefined,
96
96
  paddingBottom: safe?.bottom ? `calc((1 - var(--kb-open, 0)) * env(safe-area-inset-bottom))` : undefined,
97
97
  }}
98
- className={mx('relative bs-full flex flex-col overflow-hidden', classNames)}
98
+ className={mx('relative h-full flex flex-col overflow-hidden', classNames)}
99
99
  ref={forwardedRef}
100
100
  >
101
101
  {children}
@@ -6,8 +6,9 @@ import { createContext } from '@radix-ui/react-context';
6
6
  import React, { type PropsWithChildren, useCallback, useEffect, useMemo, useRef, useState } from 'react';
7
7
 
8
8
  import { Surface } from '@dxos/app-framework/ui';
9
+ import { useObjectNavigate } from '@dxos/app-toolkit/ui';
9
10
  import { Popover, type PopoverContentInteractOutsideEvent, toLocalizedString, useTranslation } from '@dxos/react-ui';
10
- import { Card } from '@dxos/react-ui-mosaic';
11
+ import { Card } from '@dxos/react-ui';
11
12
 
12
13
  import { useSimpleLayoutState } from '../../hooks';
13
14
  import { meta } from '../../meta';
@@ -53,10 +54,15 @@ export const PopoverRoot = ({ children }: PropsWithChildren) => {
53
54
  );
54
55
  };
55
56
 
57
+ // Extracts the subject from popover content if it has one, otherwise returns the content as-is.
58
+ const getPopoverSubject = (content: unknown): unknown =>
59
+ content && typeof content === 'object' && 'subject' in content ? (content as { subject: unknown }).subject : content;
60
+
56
61
  export const PopoverContent = () => {
57
62
  const { t } = useTranslation(meta.id);
58
63
  const { state, updateState } = useSimpleLayoutState();
59
64
  const { setOpen } = useLayoutPopoverContext('PopoverContent');
65
+ const handleNavigate = useObjectNavigate(getPopoverSubject(state.popoverContent));
60
66
 
61
67
  const handleClose = useCallback(() => {
62
68
  setOpen(false);
@@ -102,12 +108,16 @@ export const PopoverContent = () => {
102
108
  <Popover.Viewport>
103
109
  {state.popoverKind === 'base' && <Surface.Surface role='popover' data={state.popoverContent} limit={1} />}
104
110
  {state.popoverKind === 'card' && (
105
- <Card.Root border={false} classNames='popover-card-max-width'>
111
+ <Card.Root border={false} classNames='dx-card-popover'>
106
112
  <Card.Toolbar>
107
113
  {/* TODO(wittjosiah): Cleaner way to handle no drag handle in toolbar? */}
108
114
  <span />
109
- {state.popoverTitle ? <Card.Title>{toLocalizedString(state.popoverTitle, t)}</Card.Title> : <span />}
110
- <Card.Close onClick={handleClose} />
115
+ {state.popoverTitle ? (
116
+ <Card.Title onClick={handleNavigate}>{toLocalizedString(state.popoverTitle, t)}</Card.Title>
117
+ ) : (
118
+ <span />
119
+ )}
120
+ <Card.CloseIconButton onClick={handleClose} />
111
121
  </Card.Toolbar>
112
122
  <Surface.Surface role='card--content' data={state.popoverContent} limit={1} />
113
123
  </Card.Root>
@@ -35,7 +35,7 @@ const buildDefaultActions = (): ActionGraphProps => {
35
35
  }),
36
36
  ];
37
37
  result.nodes.push(...actions);
38
- result.edges.push(...actions.map((a) => ({ source: 'root', target: a.id })));
38
+ result.edges.push(...actions.map((a) => ({ source: 'root', target: a.id, relation: 'child' })));
39
39
  return result;
40
40
  };
41
41
 
@@ -53,7 +53,7 @@ const DefaultStory = ({ actions: actionsProp, ...props }: StoryProps) => {
53
53
  };
54
54
 
55
55
  const meta = {
56
- title: 'plugins/plugin-simple-layout/AppBar',
56
+ title: 'plugins/plugin-simple-layout/components/AppBar',
57
57
  render: DefaultStory,
58
58
  decorators: [
59
59
  withTheme(),
@@ -6,13 +6,7 @@ import { type Atom, useAtomValue } from '@effect-atom/atom-react';
6
6
  import React, { Fragment } from 'react';
7
7
 
8
8
  import { IconButton, Popover, type ThemedClassName, Toolbar, useTranslation } from '@dxos/react-ui';
9
- import {
10
- type ActionExecutor,
11
- type ActionGraphProps,
12
- DropdownMenu,
13
- MenuProvider,
14
- useMenuActions,
15
- } from '@dxos/react-ui-menu';
9
+ import { type ActionExecutor, type ActionGraphProps, Menu, useMenuActions } from '@dxos/react-ui-menu';
16
10
  import { mx, osTranslations } from '@dxos/ui-theme';
17
11
 
18
12
  import { meta } from '../../meta';
@@ -62,7 +56,11 @@ export const AppBar = ({
62
56
  return (
63
57
  <Toolbar.Root
64
58
  role='banner'
65
- classNames={mx('grid grid-cols-[var(--rail-size)_1fr_var(--rail-size)] items-center', 'density-fine', classNames)}
59
+ classNames={mx(
60
+ 'grid grid-cols-[var(--dx-rail-size)_1fr_var(--dx-rail-size)] items-center',
61
+ 'dx-density-fine',
62
+ classNames,
63
+ )}
66
64
  >
67
65
  {keyboardOpen ? (
68
66
  <IconButton variant='ghost' icon='ph--x--regular' iconOnly label={t('done label')} />
@@ -74,18 +72,17 @@ export const AppBar = ({
74
72
  <h1 className='text-center truncate font-thin uppercase'>{displayTitle}</h1>
75
73
  {hasActions ? (
76
74
  <AnchorRoot>
77
- <MenuProvider {...menu} onAction={onAction}>
78
- <DropdownMenu.Root caller={meta.id}>
79
- <DropdownMenu.Trigger asChild>
80
- <IconButton
81
- variant='ghost'
82
- icon='ph--dots-three-vertical--regular'
83
- iconOnly
84
- label={t('actions menu label')}
85
- />
86
- </DropdownMenu.Trigger>
87
- </DropdownMenu.Root>
88
- </MenuProvider>
75
+ <Menu.Root {...menu} caller={meta.id} onAction={onAction}>
76
+ <Menu.Trigger asChild>
77
+ <IconButton
78
+ variant='ghost'
79
+ icon='ph--dots-three-vertical--regular'
80
+ iconOnly
81
+ label={t('actions menu label')}
82
+ />
83
+ </Menu.Trigger>
84
+ <Menu.Content />
85
+ </Menu.Root>
89
86
  </AnchorRoot>
90
87
  ) : (
91
88
  <span />
@@ -7,12 +7,11 @@ import React, { useMemo } from 'react';
7
7
  import { Surface } from '@dxos/app-framework/ui';
8
8
  import { useAppGraph } from '@dxos/app-toolkit/ui';
9
9
  import { type Node, useNode } from '@dxos/plugin-graph';
10
- import { Layout } from '@dxos/react-ui';
10
+ import { ErrorFallback, Panel } from '@dxos/react-ui';
11
11
  import { ATTENDABLE_PATH_SEPARATOR } from '@dxos/react-ui-attention';
12
- import { MenuProvider, ToolbarMenu, useMenuActions } from '@dxos/react-ui-menu';
12
+ import { Menu, useMenuActions } from '@dxos/react-ui-menu';
13
13
 
14
14
  import { useCompanions, useDrawerActions, useSimpleLayoutState } from '../../hooks';
15
- import { ContentError } from '../ContentError';
16
15
  import { ContentLoading } from '../ContentLoading';
17
16
 
18
17
  const DRAWER_NAME = 'SimpleLayout.Drawer';
@@ -53,12 +52,16 @@ export const Drawer = () => {
53
52
  const menu = useMenuActions(actions);
54
53
 
55
54
  return (
56
- <Layout.Main toolbar>
57
- <MenuProvider {...menu} onAction={onAction} alwaysActive>
58
- <ToolbarMenu density='coarse' />
59
- </MenuProvider>
60
- <Surface.Surface role='article' data={data} limit={1} fallback={ContentError} placeholder={placeholder} />
61
- </Layout.Main>
55
+ <Panel.Root>
56
+ <Panel.Toolbar>
57
+ <Menu.Root {...menu} alwaysActive onAction={onAction}>
58
+ <Menu.Toolbar density='coarse' />
59
+ </Menu.Root>
60
+ </Panel.Toolbar>
61
+ <Panel.Content asChild>
62
+ <Surface.Surface role='article' data={data} limit={1} fallback={ErrorFallback} placeholder={placeholder} />
63
+ </Panel.Content>
64
+ </Panel.Root>
62
65
  );
63
66
  };
64
67
 
@@ -7,11 +7,11 @@ import React, { useMemo } from 'react';
7
7
  import { Surface } from '@dxos/app-framework/ui';
8
8
  import { useAppGraph } from '@dxos/app-toolkit/ui';
9
9
  import { useNode } from '@dxos/plugin-graph';
10
+ import { ErrorFallback } from '@dxos/react-ui';
10
11
  import { useAttentionAttributes } from '@dxos/react-ui-attention';
11
12
  import { mx } from '@dxos/ui-theme';
12
13
 
13
14
  import { useAppBarProps, useNavbarActions, useSimpleLayoutState } from '../../hooks';
14
- import { ContentError } from '../ContentError';
15
15
  import { ContentLoading } from '../ContentLoading';
16
16
  import { useLoadDescendents } from '../hooks';
17
17
  import { useMobileLayout } from '../MobileLayout/MobileLayout';
@@ -57,23 +57,25 @@ export const Main = () => {
57
57
  <div
58
58
  role='none'
59
59
  className={mx(
60
- 'bs-full grid overflow-hidden bg-toolbarSurface',
61
- showNavBar ? 'grid-rows-[var(--rail-action)_1fr_var(--toolbar-size)]' : 'grid-rows-[var(--rail-action)_1fr]',
60
+ 'h-full grid overflow-hidden bg-toolbar-surface',
61
+ showNavBar
62
+ ? 'grid-rows-[var(--dx-rail-action)_1fr_var(--dx-toolbar-size)]'
63
+ : 'grid-rows-[var(--dx-rail-action)_1fr]',
62
64
  )}
63
65
  {...attentionAttrs}
64
66
  >
65
67
  <AppBar {...appBarProps} />
66
- <article className='bs-full overflow-hidden bg-baseSurface'>
68
+ <article className='h-full overflow-hidden bg-base-surface'>
67
69
  <Surface.Surface
68
70
  key={id}
69
71
  role='article'
70
72
  data={data}
71
73
  limit={1}
72
- fallback={ContentError}
74
+ fallback={ErrorFallback}
73
75
  placeholder={placeholder}
74
76
  />
75
77
  </article>
76
- {showNavBar && <NavBar classNames='border-bs border-subduedSeparator' actions={actions} onAction={onAction} />}
78
+ {showNavBar && <NavBar classNames='border-y border-subdued-separator' actions={actions} onAction={onAction} />}
77
79
  </div>
78
80
  );
79
81
  };
@@ -7,7 +7,7 @@ import { type Meta, type StoryObj } from '@storybook/react-vite';
7
7
  import React, { useMemo } from 'react';
8
8
  import { type Mock, expect, fn, screen, userEvent, within } from 'storybook/test';
9
9
 
10
- import { withTheme } from '@dxos/react-ui/testing';
10
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
11
11
  import { type ActionGraphProps, createGapSeparator, createMenuAction, createMenuItemGroup } from '@dxos/react-ui-menu';
12
12
  import { withRegistry } from '@dxos/storybook-utils';
13
13
 
@@ -39,7 +39,7 @@ const buildCompanionOnlyActions = (): ActionGraphProps => {
39
39
  }),
40
40
  ];
41
41
  result.nodes.push(...companions);
42
- result.edges.push(...companions.map((c) => ({ source: 'root', target: c.id })));
42
+ result.edges.push(...companions.map((c) => ({ source: 'root', target: c.id, relation: 'child' })));
43
43
  return result;
44
44
  };
45
45
 
@@ -81,18 +81,18 @@ const buildDefaultActions = (): ActionGraphProps => {
81
81
  ];
82
82
  result.nodes.push(...companions, ...gapSeparator.nodes, mainMenuGroup, ...menuActions);
83
83
  result.edges.push(
84
- ...companions.map((c) => ({ source: 'root', target: c.id })),
84
+ ...companions.map((c) => ({ source: 'root', target: c.id, relation: 'child' })),
85
85
  ...gapSeparator.edges,
86
- { source: 'root', target: mainMenuGroup.id },
87
- ...menuActions.map((action) => ({ source: MAIN_MENU_GROUP_ID, target: action.id })),
86
+ { source: 'root', target: mainMenuGroup.id, relation: 'child' },
87
+ ...menuActions.map((action) => ({ source: MAIN_MENU_GROUP_ID, target: action.id, relation: 'child' })),
88
88
  );
89
89
  return result;
90
90
  };
91
91
 
92
92
  const meta = {
93
- title: 'plugins/plugin-simple-layout/NavBar',
93
+ title: 'plugins/plugin-simple-layout/components/NavBar',
94
94
  component: NavBar,
95
- decorators: [withTheme(), withRegistry],
95
+ decorators: [withTheme(), withLayout({ layout: 'fullscreen' }), withRegistry],
96
96
  parameters: {
97
97
  layout: 'fullscreen',
98
98
  translations,
@@ -106,7 +106,7 @@ type Story = StoryObj<typeof meta>;
106
106
  const DefaultStory = ({ onAction }: { onAction: (action: { id: string }) => void }) => {
107
107
  const actions = useMemo(() => Atom.make(buildDefaultActions()).pipe(Atom.keepAlive), []);
108
108
 
109
- return <NavBar classNames='border-bs border-separator' actions={actions} onAction={onAction} />;
109
+ return <NavBar classNames='border-y border-separator' actions={actions} onAction={onAction} />;
110
110
  };
111
111
 
112
112
  export const Default: Story = {
@@ -6,13 +6,7 @@ import { type Atom } from '@effect-atom/atom-react';
6
6
  import React from 'react';
7
7
 
8
8
  import { type ThemedClassName } from '@dxos/react-ui';
9
- import {
10
- type ActionExecutor,
11
- type ActionGraphProps,
12
- MenuProvider,
13
- ToolbarMenu,
14
- useMenuActions,
15
- } from '@dxos/react-ui-menu';
9
+ import { type ActionExecutor, type ActionGraphProps, Menu, useMenuActions } from '@dxos/react-ui-menu';
16
10
  import { mx } from '@dxos/ui-theme';
17
11
 
18
12
  const NAVBAR_NAME = 'SimpleLayout.NavBar';
@@ -31,9 +25,9 @@ export const NavBar = ({ classNames, actions, onAction }: NavBarProps) => {
31
25
  const menu = useMenuActions(actions);
32
26
 
33
27
  return (
34
- <MenuProvider {...menu} onAction={onAction} alwaysActive>
35
- <ToolbarMenu density='coarse' classNames={mx(classNames)} />
36
- </MenuProvider>
28
+ <Menu.Root {...menu} alwaysActive onAction={onAction}>
29
+ <Menu.Toolbar density='coarse' classNames={mx(classNames)} />
30
+ </Menu.Root>
37
31
  );
38
32
  };
39
33