@dxos/plugin-simple-layout 0.9.0 → 0.9.1-staging.ee54ba693a

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 (109) hide show
  1. package/dist/lib/neutral/capabilities/index.mjs +3 -3
  2. package/dist/lib/neutral/{chunk-7UDV3JDT.mjs → chunk-5DF656PN.mjs} +2 -2
  3. package/dist/lib/neutral/{chunk-FD2CAY4Q.mjs → chunk-LLTNQSEB.mjs} +2 -2
  4. package/dist/lib/neutral/chunk-LLTNQSEB.mjs.map +7 -0
  5. package/dist/lib/neutral/chunk-NTI42Y3O.mjs +8 -0
  6. package/dist/lib/neutral/chunk-T2JFEPBT.mjs +31 -0
  7. package/dist/lib/neutral/chunk-T2JFEPBT.mjs.map +7 -0
  8. package/dist/lib/neutral/{close-WKMURGUB.mjs → close-5ZAMG3N7.mjs} +3 -3
  9. package/dist/lib/neutral/components/index.mjs +19 -20
  10. package/dist/lib/neutral/components/index.mjs.map +3 -3
  11. package/dist/lib/neutral/hooks/index.mjs +8 -8
  12. package/dist/lib/neutral/hooks/index.mjs.map +3 -3
  13. package/dist/lib/neutral/index.mjs +2 -2
  14. package/dist/lib/neutral/meta.json +1 -1
  15. package/dist/lib/neutral/meta.mjs +1 -1
  16. package/dist/lib/neutral/{open-Y4KNROHW.mjs → open-TI35QPEC.mjs} +6 -6
  17. package/dist/lib/neutral/open-TI35QPEC.mjs.map +7 -0
  18. package/dist/lib/neutral/operations/index.mjs +1 -1
  19. package/dist/lib/neutral/plugin.mjs +2 -2
  20. package/dist/lib/neutral/{react-root-VE265VX4.mjs → react-root-JX7QKKR2.mjs} +2 -2
  21. package/dist/lib/neutral/{react-root-VE265VX4.mjs.map → react-root-JX7QKKR2.mjs.map} +3 -3
  22. package/dist/lib/neutral/{react-surface-N3PGKIYV.mjs → react-surface-UBGUUGUS.mjs} +8 -13
  23. package/dist/lib/neutral/react-surface-UBGUUGUS.mjs.map +7 -0
  24. package/dist/lib/neutral/{revert-workspace-ST6NZUNG.mjs → revert-workspace-KI6QHPTX.mjs} +3 -3
  25. package/dist/lib/neutral/{set-6ZRLWPJS.mjs → set-C4HII3NF.mjs} +3 -3
  26. package/dist/lib/neutral/{switch-workspace-PYWPTMFO.mjs → switch-workspace-E664GRHY.mjs} +5 -5
  27. package/dist/lib/neutral/switch-workspace-E664GRHY.mjs.map +7 -0
  28. package/dist/lib/neutral/translations.mjs +1 -2
  29. package/dist/lib/neutral/translations.mjs.map +3 -3
  30. package/dist/lib/neutral/types/index.mjs +1 -1
  31. package/dist/lib/neutral/{update-complementary-HKWF5OXT.mjs → update-complementary-BCWHK4SM.mjs} +3 -3
  32. package/dist/lib/neutral/{update-dialog-P4ASXCE7.mjs → update-dialog-TCKGS26T.mjs} +3 -3
  33. package/dist/lib/neutral/{update-popover-REAKC2GN.mjs → update-popover-NRI2OATE.mjs} +3 -3
  34. package/dist/lib/neutral/{url-handler-DGZ4WISE.mjs → url-handler-BJX33VLR.mjs} +5 -5
  35. package/dist/lib/neutral/url-handler-BJX33VLR.mjs.map +7 -0
  36. package/dist/types/dx.config.d.ts +28 -0
  37. package/dist/types/dx.config.d.ts.map +1 -0
  38. package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -2
  39. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  40. package/dist/types/src/capabilities/index.d.ts +6 -18
  41. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  42. package/dist/types/src/capabilities/react-root.d.ts +1 -5
  43. package/dist/types/src/capabilities/react-root.d.ts.map +1 -1
  44. package/dist/types/src/capabilities/react-surface.d.ts +2 -2
  45. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  46. package/dist/types/src/capabilities/spotlight-dismiss.d.ts +1 -1
  47. package/dist/types/src/capabilities/state.d.ts +1 -11
  48. package/dist/types/src/capabilities/state.d.ts.map +1 -1
  49. package/dist/types/src/capabilities/url-handler.d.ts +1 -1
  50. package/dist/types/src/components/ContentError.stories.d.ts +0 -1
  51. package/dist/types/src/components/ContentError.stories.d.ts.map +1 -1
  52. package/dist/types/src/components/MobileLayout/MobileLayout.d.ts +1 -1
  53. package/dist/types/src/components/MobileLayout/MobileLayout.d.ts.map +1 -1
  54. package/dist/types/src/components/Popover/Popover.d.ts.map +1 -1
  55. package/dist/types/src/components/SimpleLayout/AppBar.stories.d.ts +3 -4
  56. package/dist/types/src/components/SimpleLayout/AppBar.stories.d.ts.map +1 -1
  57. package/dist/types/src/components/SimpleLayout/NavBar.stories.d.ts +0 -1
  58. package/dist/types/src/components/SimpleLayout/NavBar.stories.d.ts.map +1 -1
  59. package/dist/types/src/components/SimpleLayout/SimpleLayout.stories.d.ts +0 -1
  60. package/dist/types/src/components/SimpleLayout/SimpleLayout.stories.d.ts.map +1 -1
  61. package/dist/types/src/hooks/useAppBarProps.d.ts.map +1 -1
  62. package/dist/types/src/meta.d.ts +32 -2
  63. package/dist/types/src/meta.d.ts.map +1 -1
  64. package/dist/types/src/operations/open.d.ts.map +1 -1
  65. package/dist/types/src/operations/switch-workspace.d.ts.map +1 -1
  66. package/dist/types/src/translations.d.ts +0 -1
  67. package/dist/types/src/translations.d.ts.map +1 -1
  68. package/dist/types/src/types/SimpleLayoutCapabilities.d.ts +1 -1
  69. package/dist/types/src/types/SimpleLayoutCapabilities.d.ts.map +1 -1
  70. package/dist/types/tsconfig.tsbuildinfo +1 -1
  71. package/dx.config.ts +20 -0
  72. package/package.json +36 -35
  73. package/src/capabilities/react-root.tsx +1 -1
  74. package/src/capabilities/react-surface.tsx +10 -17
  75. package/src/capabilities/url-handler.ts +4 -4
  76. package/src/components/Home/Home.tsx +5 -5
  77. package/src/components/MobileLayout/MobileLayout.stories.tsx +12 -12
  78. package/src/components/MobileLayout/MobileLayout.tsx +1 -1
  79. package/src/components/NavBranch/NavBranch.tsx +2 -2
  80. package/src/components/Popover/Popover.tsx +7 -5
  81. package/src/components/SimpleLayout/AppBar.stories.tsx +3 -3
  82. package/src/components/SimpleLayout/AppBar.tsx +2 -2
  83. package/src/components/SimpleLayout/SimpleLayout.tsx +6 -6
  84. package/src/hooks/actions.ts +2 -2
  85. package/src/hooks/useAppBarProps.ts +3 -2
  86. package/src/hooks/useCompanions.ts +2 -2
  87. package/src/hooks/useDrawerActions.ts +1 -1
  88. package/src/hooks/useNavbarActions.ts +1 -1
  89. package/src/meta.ts +3 -13
  90. package/src/operations/open.ts +5 -8
  91. package/src/operations/switch-workspace.ts +2 -2
  92. package/src/translations.ts +1 -2
  93. package/src/types/SimpleLayoutCapabilities.ts +2 -2
  94. package/dist/lib/neutral/chunk-FD2CAY4Q.mjs.map +0 -7
  95. package/dist/lib/neutral/chunk-NKAPURKM.mjs +0 -8
  96. package/dist/lib/neutral/chunk-OK5336TS.mjs +0 -22
  97. package/dist/lib/neutral/chunk-OK5336TS.mjs.map +0 -7
  98. package/dist/lib/neutral/open-Y4KNROHW.mjs.map +0 -7
  99. package/dist/lib/neutral/react-surface-N3PGKIYV.mjs.map +0 -7
  100. package/dist/lib/neutral/switch-workspace-PYWPTMFO.mjs.map +0 -7
  101. package/dist/lib/neutral/url-handler-DGZ4WISE.mjs.map +0 -7
  102. /package/dist/lib/neutral/{chunk-7UDV3JDT.mjs.map → chunk-5DF656PN.mjs.map} +0 -0
  103. /package/dist/lib/neutral/{chunk-NKAPURKM.mjs.map → chunk-NTI42Y3O.mjs.map} +0 -0
  104. /package/dist/lib/neutral/{close-WKMURGUB.mjs.map → close-5ZAMG3N7.mjs.map} +0 -0
  105. /package/dist/lib/neutral/{revert-workspace-ST6NZUNG.mjs.map → revert-workspace-KI6QHPTX.mjs.map} +0 -0
  106. /package/dist/lib/neutral/{set-6ZRLWPJS.mjs.map → set-C4HII3NF.mjs.map} +0 -0
  107. /package/dist/lib/neutral/{update-complementary-HKWF5OXT.mjs.map → update-complementary-BCWHK4SM.mjs.map} +0 -0
  108. /package/dist/lib/neutral/{update-dialog-P4ASXCE7.mjs.map → update-dialog-TCKGS26T.mjs.map} +0 -0
  109. /package/dist/lib/neutral/{update-popover-REAKC2GN.mjs.map → update-popover-NRI2OATE.mjs.map} +0 -0
package/dx.config.ts ADDED
@@ -0,0 +1,20 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Config2 } from '@dxos/app-framework/config';
6
+ import { trim } from '@dxos/util';
7
+
8
+ export default Config2.make({
9
+ plugin: {
10
+ key: 'org.dxos.plugin.simpleLayout',
11
+ name: 'Simple Layout',
12
+ author: 'DXOS',
13
+ description: trim`
14
+ Minimal layout plugin for simplified UI contexts like popover windows.
15
+ Provides basic content rendering without sidebars or complex navigation.
16
+ `,
17
+ icon: { key: 'ph--layout--regular' },
18
+ tags: ['system'],
19
+ },
20
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/plugin-simple-layout",
3
- "version": "0.9.0",
3
+ "version": "0.9.1-staging.ee54ba693a",
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",
@@ -74,52 +74,53 @@
74
74
  "types": "dist/types/src/index.d.ts",
75
75
  "files": [
76
76
  "dist",
77
+ "dx.config.ts",
77
78
  "src"
78
79
  ],
79
80
  "dependencies": {
80
81
  "@effect-atom/atom-react": "^0.5.0",
81
82
  "@radix-ui/react-context": "1.1.1",
82
83
  "@tauri-apps/plugin-deep-link": "^2.4.9",
83
- "@dxos/async": "0.9.0",
84
- "@dxos/app-framework": "0.9.0",
85
- "@dxos/context": "0.9.0",
86
- "@dxos/compute": "0.9.0",
87
- "@dxos/echo": "0.9.0",
88
- "@dxos/app-toolkit": "0.9.0",
89
- "@dxos/effect": "0.9.0",
90
- "@dxos/plugin-client": "0.9.0",
91
- "@dxos/plugin-graph": "0.9.0",
92
- "@dxos/react-ui-attention": "0.9.0",
93
- "@dxos/react-ui-menu": "0.9.0",
94
- "@dxos/log": "0.9.0",
95
- "@dxos/react-ui-mosaic": "0.9.0",
96
- "@dxos/util": "0.9.0",
97
- "@dxos/react-ui-search": "0.9.0",
98
- "@dxos/keys": "0.9.0"
84
+ "@dxos/app-framework": "0.9.1-staging.ee54ba693a",
85
+ "@dxos/app-toolkit": "0.9.1-staging.ee54ba693a",
86
+ "@dxos/effect": "0.9.1-staging.ee54ba693a",
87
+ "@dxos/context": "0.9.1-staging.ee54ba693a",
88
+ "@dxos/async": "0.9.1-staging.ee54ba693a",
89
+ "@dxos/compute": "0.9.1-staging.ee54ba693a",
90
+ "@dxos/echo": "0.9.1-staging.ee54ba693a",
91
+ "@dxos/keys": "0.9.1-staging.ee54ba693a",
92
+ "@dxos/plugin-client": "0.9.1-staging.ee54ba693a",
93
+ "@dxos/log": "0.9.1-staging.ee54ba693a",
94
+ "@dxos/react-ui-attention": "0.9.1-staging.ee54ba693a",
95
+ "@dxos/plugin-graph": "0.9.1-staging.ee54ba693a",
96
+ "@dxos/react-ui-menu": "0.9.1-staging.ee54ba693a",
97
+ "@dxos/react-ui-search": "0.9.1-staging.ee54ba693a",
98
+ "@dxos/util": "0.9.1-staging.ee54ba693a",
99
+ "@dxos/react-ui-mosaic": "0.9.1-staging.ee54ba693a"
99
100
  },
100
101
  "devDependencies": {
101
- "@types/react": "~19.2.7",
102
+ "@types/react": "~19.2.17",
102
103
  "@types/react-dom": "~19.2.3",
103
- "effect": "3.21.3",
104
- "react": "~19.2.3",
105
- "react-dom": "~19.2.3",
104
+ "effect": "3.21.4",
105
+ "react": "~19.2.7",
106
+ "react-dom": "~19.2.7",
106
107
  "vite": "^8.0.16",
107
- "@dxos/app-graph": "0.9.0",
108
- "@dxos/plugin-preview": "0.9.0",
109
- "@dxos/plugin-search": "0.9.0",
110
- "@dxos/plugin-space": "0.9.0",
111
- "@dxos/plugin-testing": "0.9.0",
112
- "@dxos/react-ui": "0.9.0",
113
- "@dxos/schema": "0.9.0",
114
- "@dxos/storybook-utils": "0.9.0",
115
- "@dxos/ui-theme": "0.9.0"
108
+ "@dxos/app-graph": "0.9.1-staging.ee54ba693a",
109
+ "@dxos/plugin-testing": "0.9.1-staging.ee54ba693a",
110
+ "@dxos/plugin-space": "0.9.1-staging.ee54ba693a",
111
+ "@dxos/react-ui": "0.9.1-staging.ee54ba693a",
112
+ "@dxos/plugin-search": "0.9.1-staging.ee54ba693a",
113
+ "@dxos/schema": "0.9.1-staging.ee54ba693a",
114
+ "@dxos/ui-theme": "0.9.1-staging.ee54ba693a",
115
+ "@dxos/storybook-utils": "0.9.1-staging.ee54ba693a",
116
+ "@dxos/plugin-preview": "0.9.1-staging.ee54ba693a"
116
117
  },
117
118
  "peerDependencies": {
118
- "effect": "3.21.3",
119
- "react": "~19.2.3",
120
- "react-dom": "~19.2.3",
121
- "@dxos/ui-theme": "0.9.0",
122
- "@dxos/react-ui": "0.9.0"
119
+ "effect": "3.21.4",
120
+ "react": "~19.2.7",
121
+ "react-dom": "~19.2.7",
122
+ "@dxos/react-ui": "0.9.1-staging.ee54ba693a",
123
+ "@dxos/ui-theme": "0.9.1-staging.ee54ba693a"
123
124
  },
124
125
  "publishConfig": {
125
126
  "access": "public"
@@ -13,7 +13,7 @@ import { meta } from '#meta';
13
13
  export default Capability.makeModule(() =>
14
14
  Effect.succeed(
15
15
  Capability.contributes(Capabilities.ReactRoot, {
16
- id: meta.id,
16
+ id: meta.profile.key,
17
17
  root: () => {
18
18
  return <SimpleLayout />;
19
19
  },
@@ -7,17 +7,13 @@ import React from 'react';
7
7
 
8
8
  import { Capabilities, Capability } from '@dxos/app-framework';
9
9
  import { Surface } from '@dxos/app-framework/ui';
10
- import { NOT_FOUND_PATH } from '@dxos/app-toolkit';
11
- import { NotFoundArticle } from '@dxos/app-toolkit/ui';
10
+ import { NotFound } from '@dxos/app-toolkit';
11
+ import { AppSurface, NotFoundArticle } from '@dxos/app-toolkit/ui';
12
12
  import { Node } from '@dxos/plugin-graph';
13
+ import { Position } from '@dxos/util';
13
14
 
14
15
  import { Home, NavBranch } from '#components';
15
16
 
16
- type SurfaceData = {
17
- attendableId: string;
18
- properties: Record<string, any>;
19
- };
20
-
21
17
  const ALLOWED_DISPOSITIONS = ['workspace', 'user-account', 'pin-end'];
22
18
 
23
19
  export default Capability.makeModule(() =>
@@ -25,24 +21,21 @@ export default Capability.makeModule(() =>
25
21
  Capability.contributes(Capabilities.ReactSurface, [
26
22
  Surface.create({
27
23
  id: 'home',
28
- role: 'article',
29
- filter: (data): data is SurfaceData => data.attendableId === Node.RootId,
24
+ filter: Surface.makeFilter(AppSurface.Article, (data) => data.attendableId === Node.RootId),
30
25
  component: () => <Home />,
31
26
  }),
32
27
  Surface.create({
33
28
  id: 'notFound',
34
- role: 'article',
35
- filter: (data): data is SurfaceData => data.attendableId === NOT_FOUND_PATH,
29
+ filter: Surface.makeFilter(AppSurface.Article, (data) => data.attendableId === NotFound.NOT_FOUND_PATH),
36
30
  component: () => <NotFoundArticle />,
37
31
  }),
38
32
  Surface.create({
39
33
  id: 'navBranch',
40
- role: 'article',
41
- position: 'last',
42
- filter: (data): data is SurfaceData => {
43
- const props = data.properties as Record<string, any>;
44
- return ALLOWED_DISPOSITIONS.includes(props?.disposition) || props?.role === 'branch';
45
- },
34
+ position: Position.last,
35
+ filter: Surface.makeFilter(
36
+ AppSurface.Article,
37
+ (data) => ALLOWED_DISPOSITIONS.includes(data.properties?.disposition) || data.properties?.role === 'branch',
38
+ ),
46
39
  component: ({ data }) => <NavBranch id={data.attendableId} />,
47
40
  }),
48
41
  ]),
@@ -5,7 +5,7 @@
5
5
  import * as Effect from 'effect/Effect';
6
6
 
7
7
  import { Capabilities, Capability } from '@dxos/app-framework';
8
- import { AppCapabilities, LayoutOperation, fromUrlPath, getWorkspaceFromPath, toUrlPath } from '@dxos/app-toolkit';
8
+ import { AppCapabilities, LayoutOperation, Paths } from '@dxos/app-toolkit';
9
9
  import { EffectEx } from '@dxos/effect';
10
10
  import { log } from '@dxos/log';
11
11
  import { isTauri } from '@dxos/util';
@@ -48,8 +48,8 @@ export default Capability.makeModule(
48
48
  pathname = '/';
49
49
  }
50
50
 
51
- const qualifiedId = fromUrlPath(pathname);
52
- const workspace = getWorkspaceFromPath(qualifiedId);
51
+ const qualifiedId = Paths.fromUrlPath(pathname);
52
+ const workspace = Paths.getWorkspaceFromPath(qualifiedId);
53
53
 
54
54
  void invokePromise(LayoutOperation.SwitchWorkspace, { subject: workspace });
55
55
 
@@ -108,7 +108,7 @@ export default Capability.makeModule(
108
108
  lastWorkspace = workspace;
109
109
  lastActive = active;
110
110
 
111
- const path = active ? toUrlPath(active) : toUrlPath(workspace);
111
+ const path = active ? Paths.toUrlPath(active) : Paths.toUrlPath(workspace);
112
112
  if (window.location.pathname !== path) {
113
113
  history.pushState(null, '', `${path}${window.location.search}`);
114
114
  }
@@ -13,7 +13,7 @@ import { Card } from '@dxos/react-ui';
13
13
  import { Mosaic, type MosaicStackTileComponent } from '@dxos/react-ui-mosaic';
14
14
  import { SearchPanel, useSearchListItem, useSearchListResults } from '@dxos/react-ui-search';
15
15
  import { mx } from '@dxos/ui-theme';
16
- import { byPosition, getHostPlatform, isTauri } from '@dxos/util';
16
+ import { Position, getHostPlatform, isTauri } from '@dxos/util';
17
17
 
18
18
  import { meta } from '#meta';
19
19
 
@@ -25,7 +25,7 @@ export type HomeProps = {};
25
25
  * Home screen.
26
26
  */
27
27
  export const Home = (_: HomeProps) => {
28
- const { t } = useTranslation(meta.id);
28
+ const { t } = useTranslation(meta.profile.key);
29
29
  const userAccountItem = useItemsByDisposition('user-account')[0];
30
30
  const pinnedItems = useItemsByDisposition('pin-end', true);
31
31
  const workspaceItems = useItemsByDisposition('workspace');
@@ -64,7 +64,7 @@ export const Home = (_: HomeProps) => {
64
64
 
65
65
  const WorkspaceTile: MosaicStackTileComponent<Node.Node> = (props) => {
66
66
  const data = props.data;
67
- const { t } = useTranslation(meta.id);
67
+ const { t } = useTranslation(meta.profile.key);
68
68
  const { invokePromise } = useOperationInvoker();
69
69
  const { selectedValue, registerItem, unregisterItem } = useSearchListItem();
70
70
  const name = toLocalizedString(data.properties.label, t);
@@ -104,7 +104,7 @@ const WorkspaceTile: MosaicStackTileComponent<Node.Node> = (props) => {
104
104
  onClick={handleSelect}
105
105
  ref={cardRef}
106
106
  >
107
- <Card.Header density='md'>
107
+ <Card.Header>
108
108
  <Avatar.Root>
109
109
  <Avatar.Content
110
110
  icon={data.properties.icon}
@@ -133,6 +133,6 @@ const useItemsByDisposition = (disposition: string, sort = false) => {
133
133
  const connections = useConnections(graph, Node.RootId, 'child');
134
134
  return useMemo(() => {
135
135
  const filtered = connections.filter((node) => filterItems(node, disposition));
136
- return sort ? filtered.toSorted((a, b) => byPosition(a.properties, b.properties)) : filtered;
136
+ return sort ? filtered.toSorted((a, b) => Position.compare(a.properties, b.properties)) : filtered;
137
137
  }, [connections, disposition, sort]);
138
138
  };
@@ -65,7 +65,7 @@ const StoryPanel = ({ children, label }: PropsWithChildren<{ label: string }>) =
65
65
  </Toolbar.Root>
66
66
  </Panel.Toolbar>
67
67
  <Panel.Content asChild>
68
- <Column.Root gutter='xs' classNames='py-form-chrome'>
68
+ <Column.Root gutter='sm' classNames='py-form-chrome'>
69
69
  <Column.Center>
70
70
  <Flex column>
71
71
  <Input.Root>
@@ -80,33 +80,33 @@ const StoryPanel = ({ children, label }: PropsWithChildren<{ label: string }>) =
80
80
  };
81
81
 
82
82
  const DefaultStory = () => {
83
- const [splitterMode, setSplitterMode] = useState<SplitterMode>('top');
83
+ const [splitterMode, setSplitterMode] = useState<SplitterMode>('start');
84
84
  const [keyboardOpen, setKeyboardOpen] = useState(false);
85
85
 
86
86
  useEffect(() => {
87
- setSplitterMode(splitterMode === 'split' ? 'bottom' : splitterMode);
87
+ setSplitterMode((current) => (current === 'split' ? 'end' : current));
88
88
  }, [keyboardOpen]);
89
89
 
90
90
  return (
91
91
  <WithKeyboard>
92
92
  <MobileLayout.Root onKeyboardOpenChange={setKeyboardOpen}>
93
- <MobileLayout.Panel safe={{ top: true, bottom: splitterMode === 'top' }}>
94
- <Splitter.Root mode={splitterMode} ratio={0.5}>
95
- <Splitter.Panel position='top'>
93
+ <MobileLayout.Panel safe={{ top: true, bottom: splitterMode === 'start' }}>
94
+ <Splitter.Root orientation='vertical' mode={splitterMode} size={24}>
95
+ <Splitter.Panel position='start'>
96
96
  <StoryPanel label='Main'>
97
- {splitterMode === 'top' && (
97
+ {splitterMode === 'start' && (
98
98
  <Toolbar.IconButton icon='ph--plus--regular' label='Open' onClick={() => setSplitterMode('split')} />
99
99
  )}
100
100
  </StoryPanel>
101
101
  </Splitter.Panel>
102
- <Splitter.Panel position='bottom'>
102
+ <Splitter.Panel position='end'>
103
103
  <StoryPanel label='Drawer'>
104
104
  <Toolbar.IconButton
105
- icon={splitterMode === 'bottom' ? 'ph--arrow-down--regular' : 'ph--arrow-up--regular'}
106
- label={splitterMode === 'bottom' ? 'Collapse' : 'Expand'}
107
- onClick={() => setSplitterMode((splitterMode) => (splitterMode === 'split' ? 'bottom' : 'split'))}
105
+ icon={splitterMode === 'end' ? 'ph--arrow-down--regular' : 'ph--arrow-up--regular'}
106
+ label={splitterMode === 'end' ? 'Collapse' : 'Expand'}
107
+ onClick={() => setSplitterMode((splitterMode) => (splitterMode === 'split' ? 'end' : 'split'))}
108
108
  />
109
- <Toolbar.IconButton icon='ph--x--regular' label='Close' onClick={() => setSplitterMode('top')} />
109
+ <Toolbar.IconButton icon='ph--x--regular' label='Close' onClick={() => setSplitterMode('start')} />
110
110
  </StoryPanel>
111
111
  </Splitter.Panel>
112
112
  </Splitter.Root>
@@ -120,7 +120,7 @@ export const MobileLayout = {
120
120
 
121
121
  export { useMobileLayout };
122
122
 
123
- export type { MobileLayoutRootProps, MobileLayoutPanelProps };
123
+ export type { MobileLayoutPanelProps, MobileLayoutRootProps };
124
124
 
125
125
  /**
126
126
  * Prevents iOS (WKWebView) from shifting the layout when the keyboard appears.
@@ -28,7 +28,7 @@ export type NavBranchProps = {
28
28
  * spaces, collection sections, type sections, and schema nodes.
29
29
  */
30
30
  export const NavBranch = ({ id }: NavBranchProps) => {
31
- const { t } = useTranslation(meta.id);
31
+ const { t } = useTranslation(meta.profile.key);
32
32
  const { graph } = useAppGraph();
33
33
 
34
34
  useExpandPath(id);
@@ -66,7 +66,7 @@ export const NavBranch = ({ id }: NavBranchProps) => {
66
66
 
67
67
  const NavBranchTile: MosaicStackTileComponent<Node.Node> = (props) => {
68
68
  const data = props.data;
69
- const { t } = useTranslation(meta.id);
69
+ const { t } = useTranslation(meta.profile.key);
70
70
  const { invokePromise } = useOperationInvoker();
71
71
  const ref = useRef<HTMLDivElement>(null);
72
72
  const { selectedValue, registerItem, unregisterItem } = useSearchListItem();
@@ -55,7 +55,7 @@ export const PopoverRoot = ({ children }: PropsWithChildren) => {
55
55
  };
56
56
 
57
57
  export const PopoverContent = () => {
58
- const { t } = useTranslation(meta.id);
58
+ const { t } = useTranslation(meta.profile.key);
59
59
  const { state, updateState } = useSimpleLayoutState();
60
60
  const { setOpen } = useLayoutPopoverContext('PopoverContent');
61
61
  const handleClose = useCallback(() => {
@@ -102,9 +102,11 @@ export const PopoverContent = () => {
102
102
  onEscapeKeyDown={handleInteractOutside}
103
103
  >
104
104
  <Popover.Viewport>
105
- {state.popoverKind === 'base' && state.popoverContent && 'component' in state.popoverContent && (
106
- <Surface.Surface type={AppSurface.Popover} data={state.popoverContent} limit={1} />
107
- )}
105
+ {(state.popoverKind === 'base' || state.popoverKind === 'rename') &&
106
+ state.popoverContent &&
107
+ 'component' in state.popoverContent && (
108
+ <Surface.Surface type={AppSurface.Popover} data={state.popoverContent} limit={1} />
109
+ )}
108
110
  {state.popoverKind === 'card' && (
109
111
  <Card.Root border={false} classNames='dx-card-popover'>
110
112
  <Card.Header>
@@ -114,7 +116,7 @@ export const PopoverContent = () => {
114
116
  <Card.ActionIconButton action='close' onClick={handleClose} />
115
117
  </Card.Header>
116
118
  {state.popoverContent && 'subject' in state.popoverContent && (
117
- <Surface.Surface type={AppSurface.Card} data={state.popoverContent} limit={1} />
119
+ <Surface.Surface type={AppSurface.CardContent} data={state.popoverContent} limit={1} />
118
120
  )}
119
121
  </Card.Root>
120
122
  )}
@@ -39,11 +39,11 @@ const buildDefaultActions = (): ActionGraphProps => {
39
39
  return result;
40
40
  };
41
41
 
42
- type DefaultStoryProps = Omit<AppBarProps, 'actions'> & {
42
+ type StoryArgs = Omit<AppBarProps, 'actions'> & {
43
43
  actions: ActionGraphProps;
44
44
  };
45
45
 
46
- const DefaultStory = ({ actions: actionsProp, ...props }: DefaultStoryProps) => {
46
+ const DefaultStory = ({ actions: actionsProp, ...props }: StoryArgs) => {
47
47
  const actions = useMemo(() => Atom.make(actionsProp).pipe(Atom.keepAlive), [actionsProp]);
48
48
  return (
49
49
  <MobileLayout.Root>
@@ -71,7 +71,7 @@ const meta = {
71
71
 
72
72
  export default meta;
73
73
 
74
- type Story = StoryObj<DefaultStoryProps>;
74
+ type Story = StoryObj<StoryArgs>;
75
75
 
76
76
  export const Default: Story = {
77
77
  tags: ['test'],
@@ -36,7 +36,7 @@ export type AppBarProps = {
36
36
  */
37
37
  export const AppBar = composable<HTMLDivElement, AppBarProps>(
38
38
  ({ classNames, title, actions, showBackButton, popoverAnchorId, onAction, onBack, ...props }, forwardedRef) => {
39
- const { t } = useTranslation(meta.id);
39
+ const { t } = useTranslation(meta.profile.key);
40
40
  const menuActions = useMenuActions(actions);
41
41
  const actionsValue = useAtomValue(actions);
42
42
  const hasActions = actionsValue.nodes.length > 0;
@@ -73,7 +73,7 @@ export const AppBar = composable<HTMLDivElement, AppBarProps>(
73
73
  <h1 className='text-center truncate font-thin uppercase'>{displayTitle}</h1>
74
74
  {hasActions ? (
75
75
  <AnchorRoot>
76
- <Menu.Root {...menuActions} caller={meta.id} onAction={onAction}>
76
+ <Menu.Root {...menuActions} caller={meta.profile.key} onAction={onAction}>
77
77
  <Menu.Trigger asChild>
78
78
  <IconButton
79
79
  variant='ghost'
@@ -19,14 +19,14 @@ import { Main } from './Main';
19
19
  export const SimpleLayout = () => {
20
20
  const { state } = useSimpleLayoutState();
21
21
  const [keyboardOpen, setKeyboardOpen] = useState(false);
22
- const [splitterMode, setSplitterMode] = useState<SplitterMode>('top');
22
+ const [splitterMode, setSplitterMode] = useState<SplitterMode>('start');
23
23
 
24
24
  const drawerRef = useRef<HTMLDivElement>(null);
25
25
 
26
26
  // Restore Splitter mode when keyboard closes.
27
27
  useLayoutEffect(() => {
28
28
  if (!keyboardOpen) {
29
- setSplitterMode(state.drawerState === 'closed' ? 'top' : state.drawerState === 'open' ? 'split' : 'bottom');
29
+ setSplitterMode(state.drawerState === 'closed' ? 'start' : state.drawerState === 'open' ? 'split' : 'end');
30
30
  }
31
31
  }, [state.drawerState, keyboardOpen]);
32
32
 
@@ -38,12 +38,12 @@ export const SimpleLayout = () => {
38
38
  classNames='dx-container grid relative bg-toolbar-surface'
39
39
  onKeyboardOpenChange={(nextKeyboardOpen) => setKeyboardOpen(nextKeyboardOpen)}
40
40
  >
41
- <MobileLayout.Panel safe={{ top: true, bottom: splitterMode === 'top' }}>
42
- <Splitter.Root mode={splitterMode} ratio={0.55}>
43
- <Splitter.Panel position='top'>
41
+ <MobileLayout.Panel safe={{ top: true, bottom: splitterMode === 'start' }}>
42
+ <Splitter.Root orientation='vertical' mode={splitterMode} size={24}>
43
+ <Splitter.Panel position='start'>
44
44
  <Main />
45
45
  </Splitter.Panel>
46
- <Splitter.Panel position='bottom' ref={drawerRef}>
46
+ <Splitter.Panel position='end' ref={drawerRef}>
47
47
  <Drawer />
48
48
  </Splitter.Panel>
49
49
  </Splitter.Root>
@@ -9,7 +9,7 @@ import { type AppCapabilities } from '@dxos/app-toolkit';
9
9
  import { Node } from '@dxos/plugin-graph';
10
10
  import { getLinkedVariant } from '@dxos/react-ui-attention';
11
11
  import { type ActionGraphProps } from '@dxos/react-ui-menu';
12
- import { byPosition } from '@dxos/util';
12
+ import { Position } from '@dxos/util';
13
13
 
14
14
  import { SimpleLayoutCapabilities } from '#types';
15
15
 
@@ -48,7 +48,7 @@ export const createCompanionActions = (
48
48
  const activeConnections = activeId ? get(graph.connections(activeId, 'child')) : [];
49
49
  const companions = activeConnections
50
50
  .filter((node: Node.Node) => node.type === PLANK_COMPANION_TYPE)
51
- .toSorted((a: Node.Node, b: Node.Node) => byPosition(a.properties, b.properties));
51
+ .toSorted((a: Node.Node, b: Node.Node) => Position.compare(a.properties, b.properties));
52
52
 
53
53
  const nodes: ActionGraphProps['nodes'] = [];
54
54
  const edges: ActionGraphProps['edges'] = [];
@@ -22,7 +22,7 @@ import { SimpleLayoutCapabilities } from '#types';
22
22
  * Derives activeId from state atom. Returns props ready to spread into the AppBar component.
23
23
  */
24
24
  export const useAppBarProps = (): Omit<AppBarProps, 'classNames'> => {
25
- const { t } = useTranslation(meta.id);
25
+ const { t } = useTranslation(meta.profile.key);
26
26
  const stateAtom = useCapability(SimpleLayoutCapabilities.State);
27
27
  const state = useAtomValue(stateAtom);
28
28
  const { graph } = useAppGraph();
@@ -82,7 +82,8 @@ export const useAppBarProps = (): Omit<AppBarProps, 'classNames'> => {
82
82
  }, [graph, invokePromise, state.active, state.history.length]);
83
83
 
84
84
  // Compute popover anchor ID.
85
- const popoverAnchorId = node && state.popoverAnchorId === `${meta.id}:${node.id}` ? state.popoverAnchorId : undefined;
85
+ const popoverAnchorId =
86
+ node && state.popoverAnchorId === `${meta.profile.key}:${node.id}` ? state.popoverAnchorId : undefined;
86
87
 
87
88
  return {
88
89
  title,
@@ -6,7 +6,7 @@ import { useMemo } from 'react';
6
6
 
7
7
  import { useAppGraph } from '@dxos/app-toolkit/ui';
8
8
  import { useConnections } from '@dxos/plugin-graph';
9
- import { byPosition } from '@dxos/util';
9
+ import { Position } from '@dxos/util';
10
10
 
11
11
  import { PLANK_COMPANION_TYPE } from './actions';
12
12
 
@@ -18,5 +18,5 @@ export const useCompanions = (nodeId?: string) => {
18
18
  const { graph } = useAppGraph();
19
19
  const nodes = useConnections(graph, nodeId, 'child');
20
20
  const companions = nodes.filter((node) => node.type === PLANK_COMPANION_TYPE);
21
- return useMemo(() => companions.toSorted((a, b) => byPosition(a.properties, b.properties)), [companions]);
21
+ return useMemo(() => companions.toSorted((a, b) => Position.compare(a.properties, b.properties)), [companions]);
22
22
  };
@@ -30,7 +30,7 @@ export type DrawerActions = {
30
30
  * Builds the drawer actions including companion tabs and toolbar buttons.
31
31
  */
32
32
  export const useDrawerActions = (consumerName: string): DrawerActions => {
33
- const { t } = useTranslation(meta.id);
33
+ const { t } = useTranslation(meta.profile.key);
34
34
  const stateAtom = useCapability(SimpleLayoutCapabilities.State);
35
35
  const { graph } = useAppGraph();
36
36
  const runAction = useActionRunner();
@@ -36,7 +36,7 @@ export type NavbarActions = {
36
36
  * Derives everything from graph connection atoms for proper reactivity.
37
37
  */
38
38
  export const useNavbarActions = (): NavbarActions => {
39
- const { t } = useTranslation(meta.id);
39
+ const { t } = useTranslation(meta.profile.key);
40
40
  const { graph } = useAppGraph();
41
41
  const runAction = useActionRunner();
42
42
  const stateAtom = useCapability(SimpleLayoutCapabilities.State);
package/src/meta.ts CHANGED
@@ -3,17 +3,7 @@
3
3
  //
4
4
 
5
5
  import { Plugin } from '@dxos/app-framework';
6
- import { DXN } from '@dxos/keys';
7
- import { trim } from '@dxos/util';
8
6
 
9
- export const meta = Plugin.makeMeta({
10
- key: DXN.make('org.dxos.plugin.simpleLayout'),
11
- name: 'Simple Layout',
12
- author: 'DXOS',
13
- description: trim`
14
- Minimal layout plugin for simplified UI contexts like popover windows.
15
- Provides basic content rendering without sidebars or complex navigation.
16
- `,
17
- icon: 'ph--layout--regular',
18
- tags: ['system'],
19
- });
7
+ import config from '../dx.config';
8
+
9
+ export const meta = Plugin.getMetaFromConfig(config);
@@ -3,12 +3,7 @@
3
3
  import * as Effect from 'effect/Effect';
4
4
 
5
5
  import { Capability } from '@dxos/app-framework';
6
- import {
7
- AppCapabilities,
8
- LayoutOperation,
9
- createEdgeExistenceChecker,
10
- validateNavigationTarget,
11
- } from '@dxos/app-toolkit';
6
+ import { AppCapabilities, LayoutOperation, NotFound } from '@dxos/app-toolkit';
12
7
  import { Operation } from '@dxos/compute';
13
8
  import { Context } from '@dxos/context';
14
9
  import { Database, EID } from '@dxos/echo';
@@ -47,13 +42,15 @@ const handler: Operation.WithHandler<typeof LayoutOperation.Open> = LayoutOperat
47
42
  }
48
43
  : undefined;
49
44
  const checkRemoteExistence = client
50
- ? createEdgeExistenceChecker((spaceId, body) => client.edge.http.execQuery(new Context(), spaceId, body))
45
+ ? NotFound.createEdgeExistenceChecker((spaceId, body) =>
46
+ client.edge.http.execQuery(new Context(), spaceId, body),
47
+ )
51
48
  : undefined;
52
49
 
53
50
  const validatedId =
54
51
  input.navigation === 'immediate'
55
52
  ? id
56
- : yield* validateNavigationTarget({
53
+ : yield* NotFound.validateNavigationTarget({
57
54
  graph,
58
55
  subjectId: id,
59
56
  pathResolvers,
@@ -2,7 +2,7 @@
2
2
 
3
3
  import * as Effect from 'effect/Effect';
4
4
 
5
- import { isPinnedWorkspace, LayoutOperation } from '@dxos/app-toolkit';
5
+ import { LayoutOperation, Paths } from '@dxos/app-toolkit';
6
6
  import { Operation } from '@dxos/compute';
7
7
 
8
8
  import { layoutStateAccess } from './state-access';
@@ -14,7 +14,7 @@ const handler: Operation.WithHandler<typeof LayoutOperation.SwitchWorkspace> = L
14
14
 
15
15
  updateState((state) => ({
16
16
  ...state,
17
- previousWorkspace: !isPinnedWorkspace(state.workspace) ? state.workspace : state.previousWorkspace,
17
+ previousWorkspace: !Paths.isPinnedWorkspace(state.workspace) ? state.workspace : state.previousWorkspace,
18
18
  workspace: input.subject,
19
19
  active: undefined,
20
20
  history: [],
@@ -11,9 +11,8 @@ export const translations = [
11
11
  ...searchTranslations,
12
12
  {
13
13
  'en-US': {
14
- [meta.id]: {
14
+ [meta.profile.key]: {
15
15
  'plugin.name': 'Simple layout',
16
- 'settings.title': 'Simple layout settings',
17
16
  'workspaces.heading': 'Workspaces',
18
17
  'settings.heading': 'Settings',
19
18
  'back.label': 'Back',
@@ -29,7 +29,7 @@ export type SimpleLayoutState = {
29
29
  popoverVariant?: 'virtual' | 'react';
30
30
  popoverAnchor?: HTMLButtonElement;
31
31
  popoverAnchorId?: string;
32
- popoverKind?: 'base' | 'card';
32
+ popoverKind?: 'base' | 'card' | 'rename';
33
33
  popoverTitle?: Label;
34
34
  popoverContent?: { component: string; props?: any } | { subject: any } | null;
35
35
  drawerState: DrawerState;
@@ -38,4 +38,4 @@ export type SimpleLayoutState = {
38
38
  companionVariant?: string;
39
39
  };
40
40
 
41
- export const State = Capability.make<Atom.Writable<SimpleLayoutState>>(`${meta.id}.state`);
41
+ export const State = Capability.make<Atom.Writable<SimpleLayoutState>>(`${meta.profile.key}.state`);
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/types/SimpleLayoutCapabilities.ts", "../../../src/types/SimpleLayoutEvents.ts"],
4
- "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\n// @import-as-namespace\n\nimport { type Atom } from '@effect-atom/atom-react';\n\nimport { Capability } from '@dxos/app-framework';\nimport { type Label } from '@dxos/react-ui';\n\nimport { meta } from '#meta';\n\nexport type DrawerState = 'closed' | 'open' | 'expanded';\n\nexport type SimpleLayoutState = {\n content?: any;\n previousWorkspace: string;\n workspace: string;\n active?: string;\n dialogOpen: boolean;\n dialogType?: 'default' | 'alert';\n dialogBlockAlign?: 'start' | 'center' | 'end';\n dialogOverlayClasses?: string;\n dialogOverlayStyle?: Record<string, any>;\n dialogContent?: { component: string; props?: any } | null;\n popoverOpen?: boolean;\n popoverSide?: 'top' | 'right' | 'bottom' | 'left';\n popoverVariant?: 'virtual' | 'react';\n popoverAnchor?: HTMLButtonElement;\n popoverAnchorId?: string;\n popoverKind?: 'base' | 'card';\n popoverTitle?: Label;\n popoverContent?: { component: string; props?: any } | { subject: any } | null;\n drawerState: DrawerState;\n history: string[];\n isPopover?: boolean;\n companionVariant?: string;\n};\n\nexport const State = Capability.make<Atom.Writable<SimpleLayoutState>>(`${meta.id}.state`);\n", "//\n// Copyright 2025 DXOS.org\n//\n\n// @import-as-namespace\n\nimport { type ActivationEvent } from '@dxos/app-framework';\nimport { AppActivationEvents } from '@dxos/app-toolkit';\n\nimport * as SimpleLayoutCapabilities from './SimpleLayoutCapabilities';\n\n/** Fired when State capability is ready. */\nexport const StateReady: ActivationEvent.ActivationEvent = AppActivationEvents.createStateEvent(\n SimpleLayoutCapabilities.State.identifier,\n);\n"],
5
- "mappings": ";;;;;AAAA;;;;AAQA,SAASA,kBAAkB;AAG3B,SAASC,YAAY;AA6Bd,IAAMC,QAAQF,WAAWG,KAAuC,GAAGF,KAAKG,EAAE,QAAQ;;;ACxCzF;;;;AAOA,SAASC,2BAA2B;AAK7B,IAAMC,aAA8CC,oBAAoBC,iBACpDC,MAAMC,UAAU;",
6
- "names": ["Capability", "meta", "State", "make", "id", "AppActivationEvents", "StateReady", "AppActivationEvents", "createStateEvent", "State", "identifier"]
7
- }