@dxos/plugin-stack 0.10.0 → 0.11.0

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 (71) hide show
  1. package/dist/lib/StackPlugin.mjs +18 -0
  2. package/dist/lib/StackPlugin.mjs.map +1 -0
  3. package/dist/lib/capabilities.mjs +7 -0
  4. package/dist/lib/capabilities.mjs.map +1 -0
  5. package/dist/lib/chunk-StackArticle.mjs +155 -0
  6. package/dist/lib/chunk-StackArticle.mjs.map +1 -0
  7. package/dist/lib/{neutral/chunk-ZOIZTRMG.mjs → chunk-meta.mjs} +16 -23
  8. package/dist/lib/chunk-meta.mjs.map +1 -0
  9. package/dist/lib/chunk-react-surface.mjs +21 -0
  10. package/dist/lib/chunk-react-surface.mjs.map +1 -0
  11. package/dist/lib/chunk-types.mjs +21 -0
  12. package/dist/lib/chunk-types.mjs.map +1 -0
  13. package/dist/lib/components.mjs +242 -0
  14. package/dist/lib/components.mjs.map +1 -0
  15. package/dist/lib/containers.mjs +7 -0
  16. package/dist/lib/containers.mjs.map +1 -0
  17. package/dist/lib/index.mjs +3 -0
  18. package/dist/lib/meta.mjs +2 -0
  19. package/dist/lib/plugin.mjs +8 -0
  20. package/dist/lib/plugin.mjs.map +1 -0
  21. package/dist/lib/translations.mjs +31 -0
  22. package/dist/lib/translations.mjs.map +1 -0
  23. package/dist/lib/types.mjs +2 -0
  24. package/dist/types/src/capabilities/react-surface.d.ts +1 -1
  25. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  26. package/dist/types/src/components/Stack/Stack.d.ts +11 -4
  27. package/dist/types/src/components/Stack/Stack.d.ts.map +1 -1
  28. package/dist/types/src/components/Stack/StackContext.d.ts +6 -0
  29. package/dist/types/src/components/Stack/StackContext.d.ts.map +1 -0
  30. package/dist/types/src/components/Stack/index.d.ts +1 -0
  31. package/dist/types/src/components/Stack/index.d.ts.map +1 -1
  32. package/dist/types/src/containers/StackArticle/StackArticle.d.ts +4 -1
  33. package/dist/types/src/containers/StackArticle/StackArticle.d.ts.map +1 -1
  34. package/dist/types/src/containers/StackArticle/StackArticle.stories.d.ts.map +1 -1
  35. package/dist/types/tsconfig.tsbuildinfo +1 -1
  36. package/dx.config.ts +1 -0
  37. package/package.json +40 -37
  38. package/src/capabilities/{react-surface.tsx → react-surface.ts} +2 -4
  39. package/src/components/Stack/Stack.tsx +11 -27
  40. package/src/components/Stack/StackContext.ts +23 -0
  41. package/src/components/Stack/index.ts +2 -0
  42. package/src/containers/StackArticle/StackArticle.stories.tsx +14 -11
  43. package/src/containers/StackArticle/StackArticle.tsx +12 -6
  44. package/dist/lib/neutral/StackArticle-DDKRSUE7.mjs +0 -199
  45. package/dist/lib/neutral/StackArticle-DDKRSUE7.mjs.map +0 -7
  46. package/dist/lib/neutral/StackPlugin.mjs +0 -36
  47. package/dist/lib/neutral/StackPlugin.mjs.map +0 -7
  48. package/dist/lib/neutral/capabilities/index.mjs +0 -9
  49. package/dist/lib/neutral/capabilities/index.mjs.map +0 -7
  50. package/dist/lib/neutral/chunk-FDNICBZZ.mjs +0 -18
  51. package/dist/lib/neutral/chunk-FDNICBZZ.mjs.map +0 -7
  52. package/dist/lib/neutral/chunk-J5LGTIGS.mjs +0 -10
  53. package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +0 -7
  54. package/dist/lib/neutral/chunk-ZOIZTRMG.mjs.map +0 -7
  55. package/dist/lib/neutral/components/index.mjs +0 -226
  56. package/dist/lib/neutral/components/index.mjs.map +0 -7
  57. package/dist/lib/neutral/containers/index.mjs +0 -9
  58. package/dist/lib/neutral/containers/index.mjs.map +0 -7
  59. package/dist/lib/neutral/index.mjs +0 -14
  60. package/dist/lib/neutral/index.mjs.map +0 -7
  61. package/dist/lib/neutral/meta.json +0 -1
  62. package/dist/lib/neutral/meta.mjs +0 -10
  63. package/dist/lib/neutral/meta.mjs.map +0 -7
  64. package/dist/lib/neutral/plugin.mjs +0 -12
  65. package/dist/lib/neutral/plugin.mjs.map +0 -7
  66. package/dist/lib/neutral/react-surface-IL4CW7ND.mjs +0 -25
  67. package/dist/lib/neutral/react-surface-IL4CW7ND.mjs.map +0 -7
  68. package/dist/lib/neutral/translations.mjs +0 -39
  69. package/dist/lib/neutral/translations.mjs.map +0 -7
  70. package/dist/lib/neutral/types/index.mjs +0 -8
  71. package/dist/lib/neutral/types/index.mjs.map +0 -7
package/dx.config.ts CHANGED
@@ -28,5 +28,6 @@ export default Config2.make({
28
28
  source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-stack',
29
29
  icon: { key: 'ph--stack-simple--regular' },
30
30
  spec: 'PLUGIN.mdl',
31
+ tags: ['alpha'],
31
32
  },
32
33
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/plugin-stack",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "DXOS Surface plugin for Stack entities",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -16,55 +16,55 @@
16
16
  "#capabilities": {
17
17
  "source": "./src/capabilities/index.ts",
18
18
  "types": "./dist/types/src/capabilities/index.d.ts",
19
- "default": "./dist/lib/neutral/capabilities/index.mjs"
19
+ "default": "./dist/lib/capabilities.mjs"
20
20
  },
21
21
  "#components": {
22
22
  "source": "./src/components/index.ts",
23
23
  "types": "./dist/types/src/components/index.d.ts",
24
- "default": "./dist/lib/neutral/components/index.mjs"
24
+ "default": "./dist/lib/components.mjs"
25
25
  },
26
26
  "#containers": {
27
27
  "source": "./src/containers/index.ts",
28
28
  "types": "./dist/types/src/containers/index.d.ts",
29
- "default": "./dist/lib/neutral/containers/index.mjs"
29
+ "default": "./dist/lib/containers.mjs"
30
30
  },
31
31
  "#meta": {
32
32
  "source": "./src/meta.ts",
33
33
  "types": "./dist/types/src/meta.d.ts",
34
- "default": "./dist/lib/neutral/meta.mjs"
34
+ "default": "./dist/lib/meta.mjs"
35
35
  },
36
36
  "#plugin": {
37
37
  "source": "./src/StackPlugin.ts",
38
38
  "types": "./dist/types/src/StackPlugin.d.ts",
39
- "default": "./dist/lib/neutral/StackPlugin.mjs"
39
+ "default": "./dist/lib/StackPlugin.mjs"
40
40
  },
41
41
  "#translations": {
42
42
  "source": "./src/translations.ts",
43
43
  "types": "./dist/types/src/translations.d.ts",
44
- "default": "./dist/lib/neutral/translations.mjs"
44
+ "default": "./dist/lib/translations.mjs"
45
45
  },
46
46
  "#types": {
47
47
  "source": "./src/types/index.ts",
48
48
  "types": "./dist/types/src/types/index.d.ts",
49
- "default": "./dist/lib/neutral/types/index.mjs"
49
+ "default": "./dist/lib/types.mjs"
50
50
  }
51
51
  },
52
52
  "exports": {
53
53
  ".": {
54
54
  "source": "./src/index.ts",
55
55
  "types": "./dist/types/src/index.d.ts",
56
- "default": "./dist/lib/neutral/index.mjs"
56
+ "import": "./dist/lib/index.mjs"
57
57
  },
58
58
  "./assets/PLUGIN.mdl": "./PLUGIN.mdl",
59
59
  "./plugin": {
60
60
  "source": "./src/plugin.ts",
61
61
  "types": "./dist/types/src/plugin.d.ts",
62
- "default": "./dist/lib/neutral/plugin.mjs"
62
+ "import": "./dist/lib/plugin.mjs"
63
63
  },
64
64
  "./translations": {
65
65
  "source": "./src/translations.ts",
66
66
  "types": "./dist/types/src/translations.d.ts",
67
- "default": "./dist/lib/neutral/translations.mjs"
67
+ "import": "./dist/lib/translations.mjs"
68
68
  }
69
69
  },
70
70
  "types": "dist/types/src/index.d.ts",
@@ -78,21 +78,23 @@
78
78
  "@effect-atom/atom-react": "^0.5.0",
79
79
  "@radix-ui/react-collapsible": "1.1.3",
80
80
  "effect": "3.21.4",
81
- "@dxos/app-framework": "0.10.0",
82
- "@dxos/app-toolkit": "0.10.0",
83
- "@dxos/echo": "0.10.0",
84
- "@dxos/invariant": "0.10.0",
85
- "@dxos/keys": "0.10.0",
86
- "@dxos/operation": "0.10.0",
87
- "@dxos/plugin-client": "0.10.0",
88
- "@dxos/plugin-graph": "0.10.0",
89
- "@dxos/plugin-deck": "0.10.0",
90
- "@dxos/plugin-space": "0.10.0",
91
- "@dxos/react-ui-attention": "0.10.0",
92
- "@dxos/react-ui-menu": "0.10.0",
93
- "@dxos/react-ui-form": "0.10.0",
94
- "@dxos/util": "0.10.0",
95
- "@dxos/react-ui-mosaic": "0.10.0"
81
+ "@dxos/app-framework": "0.11.0",
82
+ "@dxos/app-toolkit": "0.11.0",
83
+ "@dxos/invariant": "0.11.0",
84
+ "@dxos/echo": "0.11.0",
85
+ "@dxos/keys": "0.11.0",
86
+ "@dxos/operation": "0.11.0",
87
+ "@dxos/echo-react": "0.11.0",
88
+ "@dxos/plugin-deck": "0.11.0",
89
+ "@dxos/plugin-graph": "0.11.0",
90
+ "@dxos/plugin-client": "0.11.0",
91
+ "@dxos/react-ui-attention": "0.11.0",
92
+ "@dxos/plugin-space": "0.11.0",
93
+ "@dxos/react-ui-form": "0.11.0",
94
+ "@dxos/react-ui-menu": "0.11.0",
95
+ "@dxos/react-ui-dnd": "0.11.0",
96
+ "@dxos/react-ui-mosaic": "0.11.0",
97
+ "@dxos/util": "0.11.0"
96
98
  },
97
99
  "devDependencies": {
98
100
  "@babel/core": "^7.18.13",
@@ -100,23 +102,24 @@
100
102
  "@types/react-dom": "~19.2.3",
101
103
  "react": "~19.2.7",
102
104
  "react-dom": "~19.2.7",
103
- "vite": "^8.0.16",
104
- "@dxos/plugin-markdown": "0.10.0",
105
- "@dxos/plugin-testing": "0.10.0",
106
- "@dxos/plugin-sketch": "0.10.0",
107
- "@dxos/react-client": "0.10.0",
108
- "@dxos/random": "0.10.0",
109
- "@dxos/storybook-utils": "0.10.0",
110
- "@dxos/ui-theme": "0.10.0",
111
- "@dxos/react-ui": "0.10.0"
105
+ "vite": "^8.1.4",
106
+ "@dxos/plugin-markdown": "0.11.0",
107
+ "@dxos/plugin-testing": "0.11.0",
108
+ "@dxos/plugin-illustrator": "0.11.0",
109
+ "@dxos/plugin-tldraw": "0.11.0",
110
+ "@dxos/random": "0.11.0",
111
+ "@dxos/react-client": "0.11.0",
112
+ "@dxos/react-ui": "0.11.0",
113
+ "@dxos/storybook-utils": "0.11.0",
114
+ "@dxos/ui-theme": "0.11.0"
112
115
  },
113
116
  "peerDependencies": {
114
117
  "@effect-atom/atom-react": "^0.5.0",
115
118
  "effect": "3.21.4",
116
119
  "react": "~19.2.7",
117
120
  "react-dom": "~19.2.7",
118
- "@dxos/react-ui": "0.10.0",
119
- "@dxos/ui-theme": "0.10.0"
121
+ "@dxos/react-ui": "^0.11.0",
122
+ "@dxos/ui-theme": "^0.11.0"
120
123
  },
121
124
  "publishConfig": {
122
125
  "access": "public"
@@ -3,7 +3,6 @@
3
3
  //
4
4
 
5
5
  import * as Effect from 'effect/Effect';
6
- import React from 'react';
7
6
 
8
7
  import { Capabilities, Capability } from '@dxos/app-framework';
9
8
  import { Surface } from '@dxos/app-framework/ui';
@@ -19,9 +18,8 @@ export default Capability.makeModule(() =>
19
18
  Surface.create({
20
19
  id: 'article',
21
20
  filter: AppSurface.object(AppSurface.Article, Collection.Collection),
22
- component: ({ role, data }) => {
23
- return <StackArticle attendableId={data.attendableId} role={role} subject={data.subject} />;
24
- },
21
+ component: StackArticle,
22
+ props: ({ role, data: { subject, attendableId } }) => ({ role, subject, attendableId }),
25
23
  }),
26
24
  ),
27
25
  ),
@@ -6,16 +6,14 @@ import React, {
6
6
  type ComponentPropsWithoutRef,
7
7
  type ForwardedRef,
8
8
  type PropsWithChildren,
9
- createContext,
10
9
  forwardRef,
11
10
  useCallback,
12
- useContext,
13
11
  useMemo,
14
12
  useState,
15
13
  } from 'react';
16
14
 
17
15
  import { Surface } from '@dxos/app-framework/ui';
18
- import { Paths } from '@dxos/app-toolkit';
16
+ import { GraphPath } from '@dxos/app-toolkit';
19
17
  import { AppSurface, AttentionSigilButton } from '@dxos/app-toolkit/ui';
20
18
  import { Obj } from '@dxos/echo';
21
19
  import {
@@ -27,10 +25,13 @@ import {
27
25
  useTranslation,
28
26
  } from '@dxos/react-ui';
29
27
  import { useAttentionAttributes } from '@dxos/react-ui-attention';
30
- import { Mosaic, type MosaicEventHandler, type MosaicTileProps } from '@dxos/react-ui-mosaic';
28
+ import { type DndContainerHandler } from '@dxos/react-ui-dnd';
29
+ import { Mosaic, type MosaicTileProps } from '@dxos/react-ui-mosaic';
31
30
 
32
31
  import { meta } from '#meta';
33
32
 
33
+ import { StackContext, useStack, useStackContext } from './StackContext';
34
+
34
35
  //
35
36
  // Types
36
37
  //
@@ -57,28 +58,15 @@ export type StackContextValue = {
57
58
  onDelete: (id: string) => void;
58
59
  };
59
60
 
60
- type StackContextType = StackContextValue & {
61
+ export type StackContextType = StackContextValue & {
61
62
  /** Container id used to scope Mosaic drag/drop. */
62
63
  id: string;
63
- eventHandler: MosaicEventHandler;
64
+ eventHandler: DndContainerHandler;
64
65
  /** Scroll viewport element; threaded to the Mosaic container for autoscroll. */
65
66
  viewport: HTMLElement | null;
66
67
  setViewport: (element: HTMLElement | null) => void;
67
68
  };
68
69
 
69
- const StackContext = createContext<StackContextType | undefined>(undefined);
70
-
71
- const useStackContext = (consumer: string): StackContextType => {
72
- const context = useContext(StackContext);
73
- if (!context) {
74
- throw new Error(`\`${consumer}\` must be used within \`Stack.Root\`.`);
75
- }
76
- return context;
77
- };
78
-
79
- /** Section-level callbacks consumed by stack sections. */
80
- export const useStack = (): StackContextValue => useStackContext('useStack');
81
-
82
70
  //
83
71
  // Root
84
72
  //
@@ -88,7 +76,7 @@ type StackRootProps = PropsWithChildren<
88
76
  /** Container id used to scope Mosaic drag/drop. */
89
77
  id: string;
90
78
  /** Drag/drop event handler; defaults to a read-only (no-drop) handler. */
91
- eventHandler?: MosaicEventHandler;
79
+ eventHandler?: DndContainerHandler;
92
80
  }
93
81
  >;
94
82
 
@@ -122,11 +110,7 @@ const StackRoot = ({
122
110
  [id, eventHandler, viewport, attendableId, collapsed, onCollapse, onAdd, onMoveUp, onMoveDown, onDelete],
123
111
  );
124
112
 
125
- return (
126
- <StackContext.Provider value={value}>
127
- <Mosaic.Root>{children}</Mosaic.Root>
128
- </StackContext.Provider>
129
- );
113
+ return <StackContext.Provider value={value}>{children}</StackContext.Provider>;
130
114
  };
131
115
 
132
116
  StackRoot.displayName = 'Stack.Root';
@@ -213,7 +197,7 @@ const StackSection = ({ data, ...tileProps }: StackSectionProps) => {
213
197
  const { t } = useTranslation(meta.profile.key);
214
198
  const { attendableId: parentAttendableId, collapsed, onAdd, onMoveUp, onMoveDown, onCollapse, onDelete } = useStack();
215
199
  const [optionsMenuOpen, setOptionsMenuOpen] = useState(false);
216
- const attendableId = Paths.getCollectionObjectPath(parentAttendableId, object.id);
200
+ const attendableId = GraphPath.getCollectionObjectPath(parentAttendableId, object.id);
217
201
  const attentionAttrs = useAttentionAttributes(attendableId);
218
202
  const surfaceData = useMemo(() => ({ attendableId, subject: object }), [object, attendableId]);
219
203
  const isCollapsed = collapsed.has(id);
@@ -222,7 +206,7 @@ const StackSection = ({ data, ...tileProps }: StackSectionProps) => {
222
206
 
223
207
  const rail = (
224
208
  <div className='grid grid-rows-[min-content_1fr]'>
225
- <div className='p-1 bg-toolbar-surface'>
209
+ <div className='p-1 dx-toolbar-surface'>
226
210
  <DropdownMenu.Root open={optionsMenuOpen} onOpenChange={setOptionsMenuOpen}>
227
211
  <DropdownMenu.Trigger asChild>
228
212
  <AttentionSigilButton size='md' attendableId={attendableId}>
@@ -0,0 +1,23 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { createContext, useContext } from 'react';
6
+
7
+ import { type StackContextType, type StackContextValue } from './Stack';
8
+
9
+ // Kept out of `Stack.tsx`: react-refresh only fast-refreshes a module whose exports are all
10
+ // components, so a context and its hook exported beside them force a full page reload on every edit.
11
+
12
+ export const StackContext = createContext<StackContextType | undefined>(undefined);
13
+
14
+ export const useStackContext = (consumer: string): StackContextType => {
15
+ const context = useContext(StackContext);
16
+ if (!context) {
17
+ throw new Error(`\`${consumer}\` must be used within \`Stack.Root\`.`);
18
+ }
19
+ return context;
20
+ };
21
+
22
+ /** Section-level callbacks consumed by stack sections. */
23
+ export const useStack = (): StackContextValue => useStackContext('useStack');
@@ -2,4 +2,6 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
+ export { useStack } from './StackContext';
6
+
5
7
  export * from './Stack';
@@ -11,17 +11,20 @@ import { withPluginManager } from '@dxos/app-framework/testing';
11
11
  import { AppActivationEvents, AppCapabilities } from '@dxos/app-toolkit';
12
12
  import { AppSurface } from '@dxos/app-toolkit/ui';
13
13
  import { Collection, Filter, Ref } from '@dxos/echo';
14
+ import { useQuery } from '@dxos/echo-react';
14
15
  import { ClientPlugin, initializeIdentity } from '@dxos/plugin-client/testing';
16
+ import { Drawing } from '@dxos/plugin-illustrator';
17
+ import { IllustratorPlugin } from '@dxos/plugin-illustrator/plugin';
15
18
  import { Markdown, MarkdownEvents } from '@dxos/plugin-markdown';
16
19
  import { MarkdownPlugin } from '@dxos/plugin-markdown/testing';
17
- import { Sketch } from '@dxos/plugin-sketch';
18
- import { SketchPlugin } from '@dxos/plugin-sketch/plugin';
19
- import { SketchBuilder } from '@dxos/plugin-sketch/testing';
20
20
  import { SpacePlugin } from '@dxos/plugin-space/testing';
21
21
  import { StorybookPlugin, corePlugins } from '@dxos/plugin-testing';
22
+ import { TldrawModel } from '@dxos/plugin-tldraw';
23
+ import { Tldraw } from '@dxos/plugin-tldraw';
24
+ import { TldrawPlugin } from '@dxos/plugin-tldraw/plugin';
22
25
  import { random } from '@dxos/random';
23
26
  import { useClient } from '@dxos/react-client';
24
- import { useQuery } from '@dxos/react-client/echo';
27
+ import { withMosaic } from '@dxos/react-ui-mosaic/testing';
25
28
  import { Loading, withLayout } from '@dxos/react-ui/testing';
26
29
 
27
30
  import { translations } from '#translations';
@@ -29,7 +32,7 @@ import { translations } from '#translations';
29
32
  import { StackArticle, type StackArticleProps } from './StackArticle';
30
33
 
31
34
  // A minimal sketch (tldraw `tldraw.com/2`) snapshot, used as a test image.
32
- const SKETCH_CONTENT = new SketchBuilder()
35
+ const SKETCH_CONTENT = new TldrawModel.RecordBuilder()
33
36
  .rectangle({ id: 'rect', x: 0, y: 0, text: 'DXOS', color: 'blue', fill: 'solid', size: 'l' })
34
37
  .ellipse({ id: 'echo', x: 320, y: 0, text: 'ECHO', color: 'green' })
35
38
  .arrow({ from: 'rect', to: 'echo' })
@@ -51,6 +54,7 @@ const meta: Meta<typeof StackArticle> = {
51
54
  component: StackArticle,
52
55
  render: DefaultStory,
53
56
  decorators: [
57
+ withMosaic(),
54
58
  withLayout({ layout: 'fullscreen' }),
55
59
  withPluginManager({
56
60
  setupEvents: [AppActivationEvents.SetupSettings, MarkdownEvents.SetupExtensions],
@@ -58,7 +62,7 @@ const meta: Meta<typeof StackArticle> = {
58
62
  plugins: [
59
63
  ...corePlugins(),
60
64
  ClientPlugin({
61
- types: [Collection.Collection, Markdown.Document, Sketch.Sketch, Sketch.Canvas],
65
+ types: [Collection.Collection, Markdown.Document, Drawing.Drawing, Drawing.Canvas],
62
66
  onClientInitialized: ({ client }) =>
63
67
  Effect.gen(function* () {
64
68
  const { personalSpace: space } = yield* initializeIdentity(client);
@@ -83,11 +87,9 @@ const meta: Meta<typeof StackArticle> = {
83
87
  const sketches = [
84
88
  Ref.make(
85
89
  space.db.add(
86
- Sketch.make({
90
+ Drawing.make({
87
91
  name: random.lorem.sentence(2),
88
- canvas: {
89
- content: SKETCH_CONTENT,
90
- },
92
+ canvas: Drawing.makeCanvas({ schema: Tldraw.TLDRAW_SCHEMA, content: SKETCH_CONTENT }),
91
93
  }),
92
94
  ),
93
95
  ),
@@ -103,7 +105,8 @@ const meta: Meta<typeof StackArticle> = {
103
105
  }),
104
106
  }),
105
107
  MarkdownPlugin(),
106
- SketchPlugin(),
108
+ IllustratorPlugin(),
109
+ TldrawPlugin(),
107
110
  SpacePlugin({}),
108
111
  StorybookPlugin({}),
109
112
  ],
@@ -3,15 +3,16 @@
3
3
  //
4
4
 
5
5
  import { Atom, useAtomValue } from '@effect-atom/atom-react';
6
- import React, { useCallback, useMemo, useState } from 'react';
6
+ import React, { useCallback, useId, useMemo, useState } from 'react';
7
7
 
8
8
  import { useOperationInvoker } from '@dxos/app-framework/ui';
9
9
  import { type AppSurface } from '@dxos/app-toolkit/ui';
10
10
  import { type Collection, Obj } from '@dxos/echo';
11
11
  import { SpaceOperation } from '@dxos/plugin-space';
12
12
  import { Panel, Toolbar, useTranslation } from '@dxos/react-ui';
13
+ import { type DndContainerHandler } from '@dxos/react-ui-dnd';
13
14
  import { Menu, createMenuAction } from '@dxos/react-ui-menu';
14
- import { Mosaic, type MosaicEventHandler } from '@dxos/react-ui-mosaic';
15
+ import { Mosaic } from '@dxos/react-ui-mosaic';
15
16
  import { arrayMove, isNonNullable } from '@dxos/util';
16
17
 
17
18
  import { Stack, type StackSectionItem } from '#components';
@@ -41,11 +42,14 @@ export const StackArticle = ({ attendableId, subject: collection }: StackArticle
41
42
  [collection],
42
43
  );
43
44
 
45
+ // Per-instance discriminator so the same collection opened in two planks doesn't collide in the Mosaic registry.
46
+ const instanceId = useId();
47
+
44
48
  // Reorder sections in place. Placeholder/tile drop locations are 1-based with half-step placeholders
45
49
  // between tiles, so the floor of the drop location is the destination array index (see Mosaic.Stack).
46
- const eventHandler = useMemo<MosaicEventHandler<StackSectionItem>>(
50
+ const eventHandler = useMemo<DndContainerHandler<StackSectionItem>>(
47
51
  () => ({
48
- id: Obj.getURI(collection),
52
+ id: `${Obj.getURI(collection)}:${instanceId}`,
49
53
  canDrop: ({ source }) =>
50
54
  collection.objects.some((ref) => ref.target != null && Obj.getURI(ref.target) === source.id),
51
55
  onDrop: ({ source, target }) => {
@@ -68,7 +72,7 @@ export const StackArticle = ({ attendableId, subject: collection }: StackArticle
68
72
  });
69
73
  },
70
74
  }),
71
- [collection, findIndex],
75
+ [collection, findIndex, instanceId],
72
76
  );
73
77
 
74
78
  const handleMoveUp = useCallback(
@@ -168,7 +172,7 @@ export const StackArticle = ({ attendableId, subject: collection }: StackArticle
168
172
 
169
173
  return (
170
174
  <Panel.Root>
171
- <Panel.Toolbar classNames='bg-toolbar-surface'>
175
+ <Panel.Toolbar classNames='dx-toolbar-surface'>
172
176
  <Toolbar.Root classNames='dx-document'>
173
177
  <Toolbar.IconButton
174
178
  square
@@ -224,3 +228,5 @@ const createCollectionObjects = Atom.family((collection: Collection.Collection)
224
228
  return snapshot.objects.map((ref) => get(Obj.atomReactive(ref))).filter(isNonNullable);
225
229
  }),
226
230
  );
231
+
232
+ StackArticle.displayName = 'StackArticle';
@@ -1,199 +0,0 @@
1
- import "./chunk-J5LGTIGS.mjs";
2
-
3
- // src/containers/StackArticle/StackArticle.tsx
4
- import { Atom, useAtomValue } from "@effect-atom/atom-react";
5
- import React, { useCallback, useMemo, useState } from "react";
6
- import { useOperationInvoker } from "@dxos/app-framework/ui";
7
- import { Obj } from "@dxos/echo";
8
- import { SpaceOperation } from "@dxos/plugin-space";
9
- import { Panel, Toolbar, useTranslation } from "@dxos/react-ui";
10
- import { Menu, createMenuAction } from "@dxos/react-ui-menu";
11
- import { Mosaic } from "@dxos/react-ui-mosaic";
12
- import { arrayMove, isNonNullable } from "@dxos/util";
13
- import { Stack } from "#components";
14
- import { meta } from "#meta";
15
- var StackArticle = ({ attendableId, subject: collection }) => {
16
- const { invokePromise } = useOperationInvoker();
17
- const { t } = useTranslation(meta.profile.key);
18
- const [collapsedSections, setCollapsedSections] = useState({});
19
- const collectionObjects = useAtomValue(createCollectionObjects(collection));
20
- const items = useMemo(() => collectionObjects.map((object) => ({
21
- id: Obj.getURI(object),
22
- object
23
- })), [
24
- collectionObjects
25
- ]);
26
- const collapsed = useMemo(() => new Set(Object.keys(collapsedSections).filter((id) => collapsedSections[id])), [
27
- collapsedSections
28
- ]);
29
- const findIndex = useCallback((id) => collection.objects.findIndex((ref) => ref.target != null && Obj.getURI(ref.target) === id), [
30
- collection
31
- ]);
32
- const eventHandler = useMemo(() => ({
33
- id: Obj.getURI(collection),
34
- canDrop: ({ source }) => collection.objects.some((ref) => ref.target != null && Obj.getURI(ref.target) === source.id),
35
- onDrop: ({ source, target }) => {
36
- const to = target?.type === "tile" || target?.type === "placeholder" ? target.location : target?.type === "container" ? collection.objects.length : -1;
37
- const insert = typeof to === "number" && to >= 0 ? Math.floor(to) : -1;
38
- if (insert < 0) {
39
- return;
40
- }
41
- Obj.update(collection, (collection2) => {
42
- const from = findIndex(source.id);
43
- if (from !== -1) {
44
- arrayMove(collection2.objects, from, insert);
45
- }
46
- });
47
- }
48
- }), [
49
- collection,
50
- findIndex
51
- ]);
52
- const handleMoveUp = useCallback((id) => {
53
- const index = findIndex(id);
54
- if (index > 0) {
55
- Obj.update(collection, (collection2) => {
56
- const [ref] = collection2.objects.splice(index, 1);
57
- collection2.objects.splice(index - 1, 0, ref);
58
- });
59
- }
60
- }, [
61
- collection,
62
- findIndex
63
- ]);
64
- const handleMoveDown = useCallback((id) => {
65
- const index = findIndex(id);
66
- if (index >= 0 && index < collection.objects.length - 1) {
67
- Obj.update(collection, (collection2) => {
68
- const [ref] = collection2.objects.splice(index, 1);
69
- collection2.objects.splice(index + 1, 0, ref);
70
- });
71
- }
72
- }, [
73
- collection,
74
- findIndex
75
- ]);
76
- const handleDelete = useCallback((id) => {
77
- const index = findIndex(id);
78
- if (index >= 0) {
79
- Obj.update(collection, (collection2) => {
80
- collection2.objects.splice(index, 1);
81
- });
82
- }
83
- }, [
84
- collection,
85
- findIndex
86
- ]);
87
- const handleAdd = useCallback((id) => invokePromise(SpaceOperation.OpenCreateObject, {
88
- target: collection,
89
- navigable: false,
90
- // The created object is appended; move it to immediately after the originating section.
91
- onCreateObject: (object) => {
92
- const from = findIndex(Obj.getURI(object));
93
- const anchor = findIndex(id);
94
- if (from >= 0 && anchor >= 0) {
95
- Obj.update(collection, (collection2) => {
96
- const [ref] = collection2.objects.splice(from, 1);
97
- collection2.objects.splice(anchor < from ? anchor + 1 : anchor, 0, ref);
98
- });
99
- }
100
- }
101
- }), [
102
- collection,
103
- invokePromise,
104
- findIndex
105
- ]);
106
- const handleCollapse = useCallback((id, value) => setCollapsedSections((prev) => ({
107
- ...prev,
108
- [id]: value
109
- })), []);
110
- const handleCollapseAll = useCallback(() => setCollapsedSections(Object.fromEntries(collectionObjects.map((object) => [
111
- Obj.getURI(object),
112
- true
113
- ]))), [
114
- collectionObjects
115
- ]);
116
- const handleExpandAll = useCallback(() => setCollapsedSections({}), []);
117
- const optionsMenu = useMemo(() => [
118
- createMenuAction("collapse-all", handleCollapseAll, {
119
- label: [
120
- "collapse-all.label",
121
- {
122
- ns: meta.profile.key
123
- }
124
- ],
125
- icon: "ph--arrows-in-line-vertical--regular",
126
- testId: "stack.collapse-all"
127
- }),
128
- createMenuAction("expand-all", handleExpandAll, {
129
- label: [
130
- "expand-all.label",
131
- {
132
- ns: meta.profile.key
133
- }
134
- ],
135
- icon: "ph--arrows-out-line-vertical--regular",
136
- testId: "stack.expand-all"
137
- })
138
- ], [
139
- handleCollapseAll,
140
- handleExpandAll
141
- ]);
142
- const handleAddSection = useCallback(() => invokePromise(SpaceOperation.OpenCreateObject, {
143
- target: collection,
144
- navigable: false
145
- }), [
146
- collection,
147
- invokePromise
148
- ]);
149
- return /* @__PURE__ */ React.createElement(Panel.Root, null, /* @__PURE__ */ React.createElement(Panel.Toolbar, {
150
- classNames: "bg-toolbar-surface"
151
- }, /* @__PURE__ */ React.createElement(Toolbar.Root, {
152
- classNames: "dx-document"
153
- }, /* @__PURE__ */ React.createElement(Toolbar.IconButton, {
154
- square: true,
155
- icon: "ph--plus--regular",
156
- iconOnly: true,
157
- label: t("add-section.label"),
158
- "data-testid": "stack.addSection",
159
- onClick: handleAddSection
160
- }), /* @__PURE__ */ React.createElement(Toolbar.Separator, null), /* @__PURE__ */ React.createElement(Menu.Root, null, /* @__PURE__ */ React.createElement(Menu.Trigger, {
161
- asChild: true
162
- }, /* @__PURE__ */ React.createElement(Toolbar.IconButton, {
163
- square: true,
164
- icon: "ph--dots-three-vertical--regular",
165
- iconOnly: true,
166
- label: t("options.label"),
167
- "data-testid": "stack.options"
168
- })), /* @__PURE__ */ React.createElement(Menu.Content, {
169
- items: optionsMenu
170
- })))), /* @__PURE__ */ React.createElement(Panel.Content, null, /* @__PURE__ */ React.createElement(Stack.Root, {
171
- id: Obj.getURI(collection),
172
- attendableId,
173
- collapsed,
174
- eventHandler,
175
- onCollapse: handleCollapse,
176
- onAdd: handleAdd,
177
- onMoveUp: handleMoveUp,
178
- onMoveDown: handleMoveDown,
179
- onDelete: handleDelete
180
- }, /* @__PURE__ */ React.createElement(Stack.Content, {
181
- centered: true,
182
- padding: true,
183
- "data-testid": "main.stack"
184
- }, /* @__PURE__ */ React.createElement(Stack.Viewport, null, /* @__PURE__ */ React.createElement(Mosaic.Stack, {
185
- classNames: "dx-document",
186
- items,
187
- getId,
188
- Tile: Stack.Section
189
- }))))));
190
- };
191
- var getId = (item) => item.id;
192
- var createCollectionObjects = Atom.family((collection) => Atom.make((get) => {
193
- const snapshot = get(Obj.atom(collection));
194
- return snapshot.objects.map((ref) => get(Obj.atomReactive(ref))).filter(isNonNullable);
195
- }));
196
- export {
197
- StackArticle as default
198
- };
199
- //# sourceMappingURL=StackArticle-DDKRSUE7.mjs.map