@dxos/plugin-attention 0.8.4-staging.60fe92afc8 → 0.9.1-main.c7dcc2e112
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.
- package/dist/lib/neutral/AttentionPlugin.mjs +1 -1
- package/dist/lib/neutral/capabilities/index.mjs +1 -1
- package/dist/lib/neutral/{chunk-DPUSNLAH.mjs → chunk-BJDXKPRR.mjs} +7 -4
- package/dist/lib/neutral/chunk-BJDXKPRR.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-DTGSOFCE.mjs → chunk-KYZ6BP6Z.mjs} +5 -5
- package/dist/lib/neutral/chunk-KYZ6BP6Z.mjs.map +7 -0
- package/dist/lib/neutral/chunk-QWYNIPK3.mjs +28 -0
- package/dist/lib/neutral/chunk-QWYNIPK3.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-QSTYRKHK.mjs → chunk-VO5BJP5D.mjs} +2 -2
- package/dist/lib/neutral/index.mjs +2 -2
- package/dist/lib/neutral/meta.json +1 -1
- package/dist/lib/neutral/meta.mjs +1 -1
- package/dist/lib/neutral/operations/index.mjs +1 -1
- package/dist/lib/neutral/plugin.mjs +2 -2
- package/dist/lib/neutral/{react-context-W7BGQDHK.mjs → react-context-G6G3ZRFI.mjs} +6 -6
- package/dist/lib/neutral/react-context-G6G3ZRFI.mjs.map +7 -0
- package/dist/lib/neutral/{select-CI2OLVWT.mjs → select-AR23P2VZ.mjs} +31 -9
- package/dist/lib/neutral/select-AR23P2VZ.mjs.map +7 -0
- package/dist/lib/neutral/testing.mjs +1 -1
- package/dist/lib/neutral/types/index.mjs +1 -1
- package/dist/types/dx.config.d.ts +28 -0
- package/dist/types/dx.config.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +2 -6
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +28 -2
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/operations/select.d.ts.map +1 -1
- package/dist/types/src/stories/SelectionState.stories.d.ts +8 -0
- package/dist/types/src/stories/SelectionState.stories.d.ts.map +1 -0
- package/dist/types/src/types/capabilities.d.ts +2 -2
- package/dist/types/src/types/capabilities.d.ts.map +1 -1
- package/dist/types/src/types/events.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dx.config.ts +19 -0
- package/package.json +19 -10
- package/src/AttentionPlugin.test.ts +1 -1
- package/src/AttentionPlugin.ts +3 -3
- package/src/capabilities/react-context.tsx +4 -4
- package/src/meta.ts +3 -12
- package/src/operations/select.ts +8 -7
- package/src/stories/SelectionState.stories.tsx +188 -0
- package/src/types/capabilities.ts +3 -3
- package/src/types/events.ts +1 -1
- package/src/types/types.ts +1 -1
- package/dist/lib/neutral/chunk-DPUSNLAH.mjs.map +0 -7
- package/dist/lib/neutral/chunk-DTGSOFCE.mjs.map +0 -7
- package/dist/lib/neutral/chunk-GMJVXKMY.mjs +0 -21
- package/dist/lib/neutral/chunk-GMJVXKMY.mjs.map +0 -7
- package/dist/lib/neutral/react-context-W7BGQDHK.mjs.map +0 -7
- package/dist/lib/neutral/select-CI2OLVWT.mjs.map +0 -7
- /package/dist/lib/neutral/{chunk-QSTYRKHK.mjs.map → chunk-VO5BJP5D.mjs.map} +0 -0
package/dx.config.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
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.attention',
|
|
11
|
+
name: 'Attention',
|
|
12
|
+
author: 'DXOS',
|
|
13
|
+
description: trim`
|
|
14
|
+
Track and manage focused attention on objects across your workspace.
|
|
15
|
+
Highlight items requiring action and coordinate team focus on priority work.
|
|
16
|
+
`,
|
|
17
|
+
tags: ['system'],
|
|
18
|
+
},
|
|
19
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/plugin-attention",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1-main.c7dcc2e112",
|
|
4
4
|
"description": "Plugin for attention",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -59,23 +59,32 @@
|
|
|
59
59
|
"types": "dist/types/src/index.d.ts",
|
|
60
60
|
"files": [
|
|
61
61
|
"dist",
|
|
62
|
+
"dx.config.ts",
|
|
62
63
|
"src"
|
|
63
64
|
],
|
|
64
65
|
"dependencies": {
|
|
65
66
|
"effect": "3.21.3",
|
|
66
|
-
"@dxos/
|
|
67
|
-
"@dxos/app-
|
|
68
|
-
"@dxos/
|
|
69
|
-
"@dxos/
|
|
70
|
-
"@dxos/
|
|
71
|
-
"@dxos/
|
|
72
|
-
"@dxos/
|
|
73
|
-
"@dxos/
|
|
67
|
+
"@dxos/compute": "0.9.1-main.c7dcc2e112",
|
|
68
|
+
"@dxos/app-framework": "0.9.1-main.c7dcc2e112",
|
|
69
|
+
"@dxos/app-toolkit": "0.9.1-main.c7dcc2e112",
|
|
70
|
+
"@dxos/keys": "0.9.1-main.c7dcc2e112",
|
|
71
|
+
"@dxos/react-ui-attention": "0.9.1-main.c7dcc2e112",
|
|
72
|
+
"@dxos/plugin-graph": "0.9.1-main.c7dcc2e112",
|
|
73
|
+
"@dxos/util": "0.9.1-main.c7dcc2e112",
|
|
74
|
+
"@dxos/keyboard": "0.9.1-main.c7dcc2e112"
|
|
74
75
|
},
|
|
75
76
|
"devDependencies": {
|
|
76
77
|
"@types/react": "~19.2.7",
|
|
78
|
+
"@types/react-dom": "~19.2.3",
|
|
77
79
|
"react": "~19.2.3",
|
|
78
|
-
"react-dom": "~19.2.3"
|
|
80
|
+
"react-dom": "~19.2.3",
|
|
81
|
+
"vite": "^8.0.16",
|
|
82
|
+
"@dxos/react-ui": "0.9.1-main.c7dcc2e112",
|
|
83
|
+
"@dxos/react-ui-editor": "0.9.1-main.c7dcc2e112",
|
|
84
|
+
"@dxos/react-ui-list": "0.9.1-main.c7dcc2e112",
|
|
85
|
+
"@dxos/storybook-utils": "0.9.1-main.c7dcc2e112",
|
|
86
|
+
"@dxos/ui-theme": "0.9.1-main.c7dcc2e112",
|
|
87
|
+
"@dxos/ui-editor": "0.9.1-main.c7dcc2e112"
|
|
79
88
|
},
|
|
80
89
|
"peerDependencies": {
|
|
81
90
|
"effect": "3.21.3",
|
|
@@ -12,7 +12,7 @@ import { AttentionPlugin } from '#plugin';
|
|
|
12
12
|
|
|
13
13
|
import { meta } from './meta';
|
|
14
14
|
|
|
15
|
-
const moduleId = (name: string) => `${meta.
|
|
15
|
+
const moduleId = (name: string) => `${meta.profile.key}.module.${name}`;
|
|
16
16
|
|
|
17
17
|
describe('AttentionPlugin', () => {
|
|
18
18
|
test('modules activate on the expected events', async ({ expect }) => {
|
package/src/AttentionPlugin.ts
CHANGED
|
@@ -6,7 +6,7 @@ import * as Effect from 'effect/Effect';
|
|
|
6
6
|
|
|
7
7
|
import { ActivationEvent, ActivationEvents, Capabilities, Capability, Plugin } from '@dxos/app-framework';
|
|
8
8
|
import { AppActivationEvents, AppPlugin } from '@dxos/app-toolkit';
|
|
9
|
-
import { AttentionManager,
|
|
9
|
+
import { AttentionManager, ViewStateManager, createDefaultBackends } from '@dxos/react-ui-attention';
|
|
10
10
|
|
|
11
11
|
import { Keyboard, OperationHandler, ReactContext } from '#capabilities';
|
|
12
12
|
import { meta } from '#meta';
|
|
@@ -23,11 +23,11 @@ export const AttentionPlugin = Plugin.define(meta).pipe(
|
|
|
23
23
|
Effect.gen(function* () {
|
|
24
24
|
const registry = yield* Capability.get(Capabilities.AtomRegistry);
|
|
25
25
|
const attention = new AttentionManager(registry);
|
|
26
|
-
const
|
|
26
|
+
const viewState = new ViewStateManager({ registry, backends: createDefaultBackends(registry) });
|
|
27
27
|
setupDevtools(attention);
|
|
28
28
|
return [
|
|
29
29
|
Capability.contributes(AttentionCapabilities.Attention, attention),
|
|
30
|
-
Capability.contributes(AttentionCapabilities.
|
|
30
|
+
Capability.contributes(AttentionCapabilities.ViewState, viewState),
|
|
31
31
|
];
|
|
32
32
|
}),
|
|
33
33
|
}),
|
|
@@ -7,7 +7,7 @@ import React, { type PropsWithChildren } from 'react';
|
|
|
7
7
|
|
|
8
8
|
import { Capabilities, Capability } from '@dxos/app-framework';
|
|
9
9
|
import { useCapability } from '@dxos/app-framework/ui';
|
|
10
|
-
import { RootAttentionProvider,
|
|
10
|
+
import { RootAttentionProvider, ViewStateProvider } from '@dxos/react-ui-attention';
|
|
11
11
|
|
|
12
12
|
import { meta } from '#meta';
|
|
13
13
|
import { AttentionCapabilities } from '#types';
|
|
@@ -15,10 +15,10 @@ import { AttentionCapabilities } from '#types';
|
|
|
15
15
|
export default Capability.makeModule(() =>
|
|
16
16
|
Effect.succeed(
|
|
17
17
|
Capability.contributes(Capabilities.ReactContext, {
|
|
18
|
-
id: meta.
|
|
18
|
+
id: meta.profile.key,
|
|
19
19
|
context: (props: PropsWithChildren) => {
|
|
20
20
|
const attention = useCapability(AttentionCapabilities.Attention);
|
|
21
|
-
const
|
|
21
|
+
const viewState = useCapability(AttentionCapabilities.ViewState);
|
|
22
22
|
|
|
23
23
|
return (
|
|
24
24
|
<RootAttentionProvider
|
|
@@ -30,7 +30,7 @@ export default Capability.makeModule(() =>
|
|
|
30
30
|
// }
|
|
31
31
|
}}
|
|
32
32
|
>
|
|
33
|
-
<
|
|
33
|
+
<ViewStateProvider manager={viewState}>{props.children}</ViewStateProvider>
|
|
34
34
|
</RootAttentionProvider>
|
|
35
35
|
);
|
|
36
36
|
},
|
package/src/meta.ts
CHANGED
|
@@ -3,16 +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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
author: 'DXOS',
|
|
13
|
-
description: trim`
|
|
14
|
-
Track and manage focused attention on objects across your workspace.
|
|
15
|
-
Highlight items requiring action and coordinate team focus on priority work.
|
|
16
|
-
`,
|
|
17
|
-
tags: ['system'],
|
|
18
|
-
});
|
|
7
|
+
import config from '../dx.config';
|
|
8
|
+
|
|
9
|
+
export const meta = Plugin.getMetaFromConfig(config);
|
package/src/operations/select.ts
CHANGED
|
@@ -8,31 +8,32 @@ import * as Match from 'effect/Match';
|
|
|
8
8
|
import { Capability } from '@dxos/app-framework';
|
|
9
9
|
import { LayoutOperation } from '@dxos/app-toolkit';
|
|
10
10
|
import { Operation } from '@dxos/compute';
|
|
11
|
+
import { selectionAspect } from '@dxos/react-ui-attention';
|
|
11
12
|
|
|
12
13
|
import { AttentionCapabilities } from '../types';
|
|
13
14
|
|
|
14
15
|
const handler: Operation.WithHandler<typeof LayoutOperation.Select> = LayoutOperation.Select.pipe(
|
|
15
16
|
Operation.withHandler(
|
|
16
17
|
Effect.fnUntraced(function* (input) {
|
|
17
|
-
const
|
|
18
|
+
const viewState = yield* Capability.get(AttentionCapabilities.ViewState);
|
|
18
19
|
Match.value(input.subject).pipe(
|
|
19
20
|
Match.when({ mode: 'single', id: undefined }, () => {
|
|
20
|
-
|
|
21
|
+
viewState.set(selectionAspect, input.contextId, { mode: 'single' });
|
|
21
22
|
}),
|
|
22
23
|
Match.when({ mode: 'single' }, (s) => {
|
|
23
|
-
|
|
24
|
+
viewState.set(selectionAspect, input.contextId, { mode: 'single', id: s.id });
|
|
24
25
|
}),
|
|
25
26
|
Match.when({ mode: 'multi' }, (s) => {
|
|
26
|
-
|
|
27
|
+
viewState.set(selectionAspect, input.contextId, { mode: 'multi', ids: [...s.ids] });
|
|
27
28
|
}),
|
|
28
29
|
Match.when({ mode: 'range', from: undefined, to: undefined }, () => {
|
|
29
|
-
|
|
30
|
+
viewState.set(selectionAspect, input.contextId, { mode: 'range' });
|
|
30
31
|
}),
|
|
31
32
|
Match.when({ mode: 'range' }, (s) => {
|
|
32
|
-
|
|
33
|
+
viewState.set(selectionAspect, input.contextId, { mode: 'range', from: s.from, to: s.to });
|
|
33
34
|
}),
|
|
34
35
|
Match.when({ mode: 'multi-range' }, (s) => {
|
|
35
|
-
|
|
36
|
+
viewState.set(selectionAspect, input.contextId, { mode: 'multi-range', ranges: [...s.ranges] });
|
|
36
37
|
}),
|
|
37
38
|
Match.exhaustive,
|
|
38
39
|
);
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
+
import React, { useMemo } from 'react';
|
|
7
|
+
|
|
8
|
+
import { useThemeContext } from '@dxos/react-ui';
|
|
9
|
+
import {
|
|
10
|
+
type ViewStateManager,
|
|
11
|
+
defineViewState,
|
|
12
|
+
useSelection,
|
|
13
|
+
useSelectionActions,
|
|
14
|
+
useViewStateManager,
|
|
15
|
+
} from '@dxos/react-ui-attention';
|
|
16
|
+
import { withAttention } from '@dxos/react-ui-attention/testing';
|
|
17
|
+
import { useTextEditor } from '@dxos/react-ui-editor';
|
|
18
|
+
import { OrderedList } from '@dxos/react-ui-list';
|
|
19
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
20
|
+
import {
|
|
21
|
+
EditorSelectionStateSchema,
|
|
22
|
+
type EditorStateStore,
|
|
23
|
+
createBasicExtensions,
|
|
24
|
+
createMarkdownExtensions,
|
|
25
|
+
createThemeExtensions,
|
|
26
|
+
documentId,
|
|
27
|
+
selectionState,
|
|
28
|
+
} from '@dxos/ui-editor';
|
|
29
|
+
import { mx } from '@dxos/ui-theme';
|
|
30
|
+
|
|
31
|
+
//
|
|
32
|
+
// Editor ViewState aspect — local (localStorage) backed, per document id.
|
|
33
|
+
// Mirrors plugin-markdown's editor-view-state.ts but defined inline so
|
|
34
|
+
// plugin-attention does not depend on plugin-markdown.
|
|
35
|
+
//
|
|
36
|
+
|
|
37
|
+
const editorViewStateAspect = defineViewState({
|
|
38
|
+
key: 'story-editor',
|
|
39
|
+
backend: 'local',
|
|
40
|
+
schema: EditorSelectionStateSchema,
|
|
41
|
+
defaultValue: () => ({}),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const makeEditorStore = (manager: ViewStateManager): EditorStateStore => ({
|
|
45
|
+
getState: (id) => manager.get(editorViewStateAspect, id),
|
|
46
|
+
setState: (id, state) => manager.set(editorViewStateAspect, id, state),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
//
|
|
50
|
+
// Sample data.
|
|
51
|
+
//
|
|
52
|
+
|
|
53
|
+
type StoryItem = { id: string; label: string; content: string };
|
|
54
|
+
|
|
55
|
+
const LIST_CONTEXT = 'story-list';
|
|
56
|
+
|
|
57
|
+
const ITEMS: StoryItem[] = [
|
|
58
|
+
{
|
|
59
|
+
id: 'item-alpha',
|
|
60
|
+
label: 'Alpha',
|
|
61
|
+
content: [
|
|
62
|
+
'# Alpha',
|
|
63
|
+
'',
|
|
64
|
+
'This is the **Alpha** document. Scroll down and move the caret, then switch to another item and come back — your position is restored.',
|
|
65
|
+
'',
|
|
66
|
+
Array.from({ length: 30 }, (_, i) => `Line ${i + 1} of Alpha content.`).join('\n'),
|
|
67
|
+
].join('\n'),
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: 'item-bravo',
|
|
71
|
+
label: 'Bravo',
|
|
72
|
+
content: [
|
|
73
|
+
'# Bravo',
|
|
74
|
+
'',
|
|
75
|
+
'This is the **Bravo** document. Each document remembers its own scroll and caret position independently.',
|
|
76
|
+
'',
|
|
77
|
+
Array.from({ length: 30 }, (_, i) => `Line ${i + 1} of Bravo content.`).join('\n'),
|
|
78
|
+
].join('\n'),
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: 'item-charlie',
|
|
82
|
+
label: 'Charlie',
|
|
83
|
+
content: [
|
|
84
|
+
'# Charlie',
|
|
85
|
+
'',
|
|
86
|
+
'This is the **Charlie** document. The selection state is memory-backed (ephemeral); the editor state is local-backed (localStorage).',
|
|
87
|
+
'',
|
|
88
|
+
Array.from({ length: 30 }, (_, i) => `Line ${i + 1} of Charlie content.`).join('\n'),
|
|
89
|
+
].join('\n'),
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
const isItem = (value: unknown): value is StoryItem =>
|
|
94
|
+
typeof value === 'object' && value !== null && 'id' in value && typeof value.id === 'string';
|
|
95
|
+
|
|
96
|
+
//
|
|
97
|
+
// ItemEditor — mounts a CodeMirror editor for the selected item, wired to the
|
|
98
|
+
// local-backed ViewState store so caret/scroll is remembered per document id.
|
|
99
|
+
//
|
|
100
|
+
|
|
101
|
+
type ItemEditorProps = { item: StoryItem; editorStore: EditorStateStore };
|
|
102
|
+
|
|
103
|
+
const ItemEditor = ({ item, editorStore }: ItemEditorProps) => {
|
|
104
|
+
const { themeMode } = useThemeContext();
|
|
105
|
+
|
|
106
|
+
const { parentRef } = useTextEditor(
|
|
107
|
+
() => ({
|
|
108
|
+
id: item.id,
|
|
109
|
+
initialValue: item.content,
|
|
110
|
+
extensions: [
|
|
111
|
+
createBasicExtensions({ placeholder: 'Start typing…', scrollPastEnd: true }),
|
|
112
|
+
createThemeExtensions({ themeMode, syntaxHighlighting: true }),
|
|
113
|
+
createMarkdownExtensions(),
|
|
114
|
+
documentId.of(item.id),
|
|
115
|
+
selectionState(editorStore),
|
|
116
|
+
],
|
|
117
|
+
}),
|
|
118
|
+
[item.id, themeMode, editorStore],
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
return <div ref={parentRef} className='flex-1 overflow-hidden' />;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
//
|
|
125
|
+
// SelectionStateStory — the canonical demo component.
|
|
126
|
+
//
|
|
127
|
+
|
|
128
|
+
const SelectionStateStory = () => {
|
|
129
|
+
const manager = useViewStateManager();
|
|
130
|
+
const editorStore = useMemo(() => makeEditorStore(manager), [manager]);
|
|
131
|
+
|
|
132
|
+
const selectedId = useSelection(LIST_CONTEXT, 'single');
|
|
133
|
+
const { single } = useSelectionActions(LIST_CONTEXT);
|
|
134
|
+
|
|
135
|
+
const selectedItem = ITEMS.find((item) => item.id === selectedId);
|
|
136
|
+
|
|
137
|
+
return (
|
|
138
|
+
<div className='flex h-full overflow-hidden divide-x divide-separator'>
|
|
139
|
+
{/* Left pane: ordered list with selection */}
|
|
140
|
+
<div className='w-56 shrink-0 flex flex-col overflow-hidden'>
|
|
141
|
+
<div className='px-3 py-2 text-sm font-medium text-subdued border-b border-separator'>Items</div>
|
|
142
|
+
<OrderedList.Root<StoryItem> items={ITEMS} isItem={isItem} getId={(item) => item.id}>
|
|
143
|
+
{({ items: resolved }) => (
|
|
144
|
+
<OrderedList.Content>
|
|
145
|
+
{resolved.map((item) => (
|
|
146
|
+
<OrderedList.Item
|
|
147
|
+
key={item.id}
|
|
148
|
+
id={item.id}
|
|
149
|
+
item={item}
|
|
150
|
+
hover
|
|
151
|
+
classNames={mx('px-3 py-2 cursor-pointer', item.id === selectedId && 'bg-hoverSurface font-medium')}
|
|
152
|
+
onClick={() => single(item.id)}
|
|
153
|
+
>
|
|
154
|
+
{item.label}
|
|
155
|
+
</OrderedList.Item>
|
|
156
|
+
))}
|
|
157
|
+
</OrderedList.Content>
|
|
158
|
+
)}
|
|
159
|
+
</OrderedList.Root>
|
|
160
|
+
</div>
|
|
161
|
+
|
|
162
|
+
{/* Right pane: editor for selected item */}
|
|
163
|
+
<div className='flex-1 flex flex-col overflow-hidden'>
|
|
164
|
+
{selectedItem ? (
|
|
165
|
+
<ItemEditor key={selectedItem.id} item={selectedItem} editorStore={editorStore} />
|
|
166
|
+
) : (
|
|
167
|
+
<div className='flex items-center justify-center h-full text-subdued text-sm'>Select an item to edit.</div>
|
|
168
|
+
)}
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
);
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
//
|
|
175
|
+
// Storybook meta.
|
|
176
|
+
//
|
|
177
|
+
|
|
178
|
+
const meta: Meta<typeof SelectionStateStory> = {
|
|
179
|
+
title: 'plugins/plugin-attention/SelectionState',
|
|
180
|
+
component: SelectionStateStory,
|
|
181
|
+
decorators: [withTheme(), withLayout({ layout: 'fullscreen' }), withAttention()],
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
export default meta;
|
|
185
|
+
|
|
186
|
+
type Story = StoryObj<typeof meta>;
|
|
187
|
+
|
|
188
|
+
export const Default: Story = { render: () => <SelectionStateStory /> };
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { Capability } from '@dxos/app-framework';
|
|
6
|
-
import { type AttentionManager, type
|
|
6
|
+
import { type AttentionManager, type ViewStateManager } from '@dxos/react-ui-attention';
|
|
7
7
|
|
|
8
8
|
import { meta } from '#meta';
|
|
9
9
|
|
|
10
10
|
export namespace AttentionCapabilities {
|
|
11
|
-
export const Attention = Capability.make<AttentionManager>(`${meta.
|
|
12
|
-
export const
|
|
11
|
+
export const Attention = Capability.make<AttentionManager>(`${meta.profile.key}.capability.attention`);
|
|
12
|
+
export const ViewState = Capability.make<ViewStateManager>(`${meta.profile.key}.capability.view-state`);
|
|
13
13
|
}
|
package/src/types/events.ts
CHANGED
|
@@ -7,5 +7,5 @@ import { ActivationEvent } from '@dxos/app-framework';
|
|
|
7
7
|
import { meta } from '#meta';
|
|
8
8
|
|
|
9
9
|
export namespace AttentionEvents {
|
|
10
|
-
export const AttentionReady = ActivationEvent.make(`${meta.
|
|
10
|
+
export const AttentionReady = ActivationEvent.make(`${meta.profile.key}.event.attentionReady`);
|
|
11
11
|
}
|
package/src/types/types.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { SelectionSchema } from '@dxos/react-ui-attention';
|
|
|
9
9
|
import { meta } from '#meta';
|
|
10
10
|
|
|
11
11
|
export namespace AttentionAction {
|
|
12
|
-
const ATTENTION_ACTION = `${meta.
|
|
12
|
+
const ATTENTION_ACTION = `${meta.profile.key}.action`;
|
|
13
13
|
|
|
14
14
|
export class Select extends Schema.TaggedClass<Select>()(`${ATTENTION_ACTION}.select`, {
|
|
15
15
|
input: Schema.Struct({
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/AttentionPlugin.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { ActivationEvent, ActivationEvents, Capabilities, Capability, Plugin } from '@dxos/app-framework';\nimport { AppActivationEvents, AppPlugin } from '@dxos/app-toolkit';\nimport { AttentionManager, SelectionManager } from '@dxos/react-ui-attention';\n\nimport { Keyboard, OperationHandler, ReactContext } from '#capabilities';\nimport { meta } from '#meta';\nimport { AttentionEvents } from '#types';\nimport { AttentionCapabilities } from '#types';\n\nexport const AttentionPlugin = Plugin.define(meta).pipe(\n AppPlugin.addOperationHandlerModule({ activate: OperationHandler }),\n Plugin.addModule({\n id: 'attention',\n activatesOn: ActivationEvents.Startup,\n firesAfterActivation: [AttentionEvents.AttentionReady],\n activate: () =>\n Effect.gen(function* () {\n const registry = yield* Capability.get(Capabilities.AtomRegistry);\n const attention = new AttentionManager(registry);\n const selection = new SelectionManager(registry);\n setupDevtools(attention);\n return [\n Capability.contributes(AttentionCapabilities.Attention, attention),\n Capability.contributes(AttentionCapabilities.Selection, selection),\n ];\n }),\n }),\n Plugin.addModule({\n activatesOn: ActivationEvents.Startup,\n activate: ReactContext,\n }),\n Plugin.addModule({\n activatesOn: ActivationEvent.allOf(AppActivationEvents.AppGraphReady, AttentionEvents.AttentionReady),\n activate: Keyboard,\n }),\n Plugin.make,\n);\n\nconst setupDevtools = (attention: AttentionManager) => {\n (globalThis as any).composer ??= {};\n\n (globalThis as any).composer.attention = {\n get manager() {\n return attention;\n },\n get attended() {\n return attention.getCurrent();\n },\n get currentSpace() {\n for (const id of attention.getCurrent()) {\n const segments = id.split('/');\n if (segments.length > 1 && segments[1].length === 33) {\n return segments[1];\n }\n }\n },\n };\n};\n\nexport default AttentionPlugin;\n"],
|
|
5
|
-
"mappings": ";AAIA,YAAYA,YAAY;AAExB,SAASC,iBAAiBC,kBAAkBC,cAAcC,YAAYC,cAAc;AACpF,SAASC,qBAAqBC,iBAAiB;AAC/C,SAASC,kBAAkBC,wBAAwB;AAEnD,SAASC,UAAUC,kBAAkBC,oBAAoB;AACzD,SAASC,YAAY;AACrB,SAASC,uBAAuB;AAChC,SAASC,6BAA6B;AAE/B,IAAMC,kBAAkBX,OAAOY,OAAOJ,IAAAA,EAAMK,KACjDX,UAAUY,0BAA0B;EAAEC,UAAUT;AAAiB,CAAA,GACjEN,OAAOgB,UAAU;EACfC,IAAI;EACJC,aAAarB,iBAAiBsB;EAC9BC,sBAAsB;IAACX,gBAAgBY;;EACvCN,UAAU,MACDO,WAAI,aAAA;AACT,UAAMC,WAAW,OAAOxB,WAAWyB,IAAI1B,aAAa2B,YAAY;AAChE,UAAMC,YAAY,IAAIvB,iBAAiBoB,QAAAA;AACvC,UAAMI,YAAY,IAAIvB,iBAAiBmB,QAAAA;AACvCK,kBAAcF,SAAAA;AACd,WAAO;MACL3B,WAAW8B,YAAYnB,sBAAsBoB,WAAWJ,SAAAA;MACxD3B,WAAW8B,YAAYnB,sBAAsBqB,WAAWJ,SAAAA;;EAE5D,CAAA;AACJ,CAAA,GACA3B,OAAOgB,UAAU;EACfE,aAAarB,iBAAiBsB;EAC9BJ,UAAUR;AACZ,CAAA,GACAP,OAAOgB,UAAU;EACfE,aAAatB,gBAAgBoC,MAAM/B,oBAAoBgC,eAAexB,gBAAgBY,cAAc;EACpGN,UAAUV;AACZ,CAAA,GACAL,OAAOkC,IAAI;AAGb,IAAMN,gBAAgB,CAACF,cAAAA;AACpBS,aAAmBC,aAAa,CAAC;AAEjCD,aAAmBC,SAASV,YAAY;IACvC,IAAIW,UAAU;AACZ,aAAOX;IACT;IACA,IAAIY,WAAW;AACb,aAAOZ,UAAUa,WAAU;IAC7B;IACA,IAAIC,eAAe;AACjB,iBAAWvB,MAAMS,UAAUa,WAAU,GAAI;AACvC,cAAME,WAAWxB,GAAGyB,MAAM,GAAA;AAC1B,YAAID,SAASE,SAAS,KAAKF,SAAS,CAAA,EAAGE,WAAW,IAAI;AACpD,iBAAOF,SAAS,CAAA;QAClB;MACF;IACF;EACF;AACF;AAEA,IAAA,0BAAe9B;",
|
|
6
|
-
"names": ["Effect", "ActivationEvent", "ActivationEvents", "Capabilities", "Capability", "Plugin", "AppActivationEvents", "AppPlugin", "AttentionManager", "SelectionManager", "Keyboard", "OperationHandler", "ReactContext", "meta", "AttentionEvents", "AttentionCapabilities", "AttentionPlugin", "define", "pipe", "addOperationHandlerModule", "activate", "addModule", "id", "activatesOn", "Startup", "firesAfterActivation", "AttentionReady", "gen", "registry", "get", "AtomRegistry", "attention", "selection", "setupDevtools", "contributes", "Attention", "Selection", "allOf", "AppGraphReady", "make", "globalThis", "composer", "manager", "attended", "getCurrent", "currentSpace", "segments", "split", "length"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/types/capabilities.ts", "../../../src/types/events.ts", "../../../src/types/types.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Capability } from '@dxos/app-framework';\nimport { type AttentionManager, type SelectionManager } from '@dxos/react-ui-attention';\n\nimport { meta } from '#meta';\n\nexport namespace AttentionCapabilities {\n export const Attention = Capability.make<AttentionManager>(`${meta.id}.capability.attention`);\n export const Selection = Capability.make<SelectionManager>(`${meta.id}.capability.selection`);\n}\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { ActivationEvent } from '@dxos/app-framework';\n\nimport { meta } from '#meta';\n\nexport namespace AttentionEvents {\n export const AttentionReady = ActivationEvent.make(`${meta.id}.event.attention-ready`);\n}\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\n\nimport { SelectionSchema } from '@dxos/react-ui-attention';\n\nimport { meta } from '#meta';\n\nexport namespace AttentionAction {\n const ATTENTION_ACTION = `${meta.id}.action`;\n\n export class Select extends Schema.TaggedClass<Select>()(`${ATTENTION_ACTION}.select`, {\n input: Schema.Struct({\n contextId: Schema.String,\n selection: SelectionSchema,\n }),\n output: Schema.Void,\n }) {}\n}\n"],
|
|
5
|
-
"mappings": ";AAIA,SAASA,kBAAkB;AAG3B,SAASC,YAAY;UAEJC,wBAAAA;yBACFC,YAAYH,WAAWI,KAAuB,GAAGH,KAAKI,EAAE,uBAAuB;yBAC/EC,YAAYN,WAAWI,KAAuB,GAAGH,KAAKI,EAAE,uBAAuB;AAC9F,GAHiBH,0BAAAA,wBAAAA,CAAAA,EAAAA;;;;ACLjB,SAASK,uBAAuB;AAEhC,SAASC,QAAAA,aAAY;UAEJC,kBAAAA;mBACFC,iBAAiBH,gBAAgBI,KAAK,GAAGH,MAAKI,EAAE,wBAAwB;AACvF,GAFiBH,oBAAAA,kBAAAA,CAAAA,EAAAA;;;;ACJjB,YAAYI,YAAY;AAExB,SAASC,uBAAuB;AAEhC,SAASC,QAAAA,aAAY;UAEJC,kBAAAA;AACf,QAAMC,mBAAmB,GAAGF,MAAKG,EAAE;EAE5B,MAAMC,eAAsBC,mBAAW,EAAW,GAAGH,gBAAAA,WAA2B;IACrFI,OAAcC,cAAO;MACnBC,WAAkBC;MAClBC,WAAWX;IACb,CAAA;IACAY,QAAeC;EACjB,CAAA,EAAA;EAAI;mBANSR,SAAAA;AAOf,GAViBH,oBAAAA,kBAAAA,CAAAA,EAAAA;;",
|
|
6
|
-
"names": ["Capability", "meta", "AttentionCapabilities", "Attention", "make", "id", "Selection", "ActivationEvent", "meta", "AttentionEvents", "AttentionReady", "make", "id", "Schema", "SelectionSchema", "meta", "AttentionAction", "ATTENTION_ACTION", "id", "Select", "TaggedClass", "input", "Struct", "contextId", "String", "selection", "output", "Void"]
|
|
7
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
// src/meta.ts
|
|
2
|
-
import { Plugin } from "@dxos/app-framework";
|
|
3
|
-
import { DXN } from "@dxos/keys";
|
|
4
|
-
import { trim } from "@dxos/util";
|
|
5
|
-
var meta = Plugin.makeMeta({
|
|
6
|
-
key: DXN.make("org.dxos.plugin.attention"),
|
|
7
|
-
name: "Attention",
|
|
8
|
-
author: "DXOS",
|
|
9
|
-
description: trim`
|
|
10
|
-
Track and manage focused attention on objects across your workspace.
|
|
11
|
-
Highlight items requiring action and coordinate team focus on priority work.
|
|
12
|
-
`,
|
|
13
|
-
tags: [
|
|
14
|
-
"system"
|
|
15
|
-
]
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
export {
|
|
19
|
-
meta
|
|
20
|
-
};
|
|
21
|
-
//# sourceMappingURL=chunk-GMJVXKMY.mjs.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/meta.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { Plugin } from '@dxos/app-framework';\nimport { DXN } from '@dxos/keys';\nimport { trim } from '@dxos/util';\n\nexport const meta = Plugin.makeMeta({\n key: DXN.make('org.dxos.plugin.attention'),\n name: 'Attention',\n author: 'DXOS',\n description: trim`\n Track and manage focused attention on objects across your workspace.\n Highlight items requiring action and coordinate team focus on priority work.\n `,\n tags: ['system'],\n});\n"],
|
|
5
|
-
"mappings": ";AAIA,SAASA,cAAc;AACvB,SAASC,WAAW;AACpB,SAASC,YAAY;AAEd,IAAMC,OAAOH,OAAOI,SAAS;EAClCC,KAAKJ,IAAIK,KAAK,2BAAA;EACdC,MAAM;EACNC,QAAQ;EACRC,aAAaP;;;;EAIbQ,MAAM;IAAC;;AACT,CAAA;",
|
|
6
|
-
"names": ["Plugin", "DXN", "trim", "meta", "makeMeta", "key", "make", "name", "author", "description", "tags"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/capabilities/react-context.tsx"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\nimport React, { type PropsWithChildren } from 'react';\n\nimport { Capabilities, Capability } from '@dxos/app-framework';\nimport { useCapability } from '@dxos/app-framework/ui';\nimport { RootAttentionProvider, SelectionProvider } from '@dxos/react-ui-attention';\n\nimport { meta } from '#meta';\nimport { AttentionCapabilities } from '#types';\n\nexport default Capability.makeModule(() =>\n Effect.succeed(\n Capability.contributes(Capabilities.ReactContext, {\n id: meta.id,\n context: (props: PropsWithChildren) => {\n const attention = useCapability(AttentionCapabilities.Attention);\n const selection = useCapability(AttentionCapabilities.Selection);\n\n return (\n <RootAttentionProvider\n attention={attention}\n onChange={(nextAttended) => {\n // TODO(Zan): Workout why this was in deck plugin. It didn't seem to work?\n // if (layout.values.scrollIntoView && nextAttended.has(layout.values.scrollIntoView)) {\n // layout.values.scrollIntoView = undefined;\n // }\n }}\n >\n <SelectionProvider selection={selection}>{props.children}</SelectionProvider>\n </RootAttentionProvider>\n );\n },\n }),\n ),\n);\n"],
|
|
5
|
-
"mappings": ";AAIA,YAAYA,YAAY;AACxB,OAAOC,WAAuC;AAE9C,SAASC,cAAcC,kBAAkB;AACzC,SAASC,qBAAqB;AAC9B,SAASC,uBAAuBC,yBAAyB;AAEzD,SAASC,YAAY;AACrB,SAASC,6BAA6B;AAEtC,IAAA,wBAAeL,WAAWM,WAAW,MAC5BC,eACLP,WAAWQ,YAAYT,aAAaU,cAAc;EAChDC,IAAIN,KAAKM;EACTC,SAAS,CAACC,UAAAA;AACR,UAAMC,YAAYZ,cAAcI,sBAAsBS,SAAS;AAC/D,UAAMC,YAAYd,cAAcI,sBAAsBW,SAAS;AAE/D,WACE,sBAAA,cAACd,uBAAAA;MACCW;MACAI,UAAU,CAACC,iBAAAA;MAKX;OAEA,sBAAA,cAACf,mBAAAA;MAAkBY;OAAuBH,MAAMO,QAAQ,CAAA;EAG9D;AACF,CAAA,CAAA,CAAA;",
|
|
6
|
-
"names": ["Effect", "React", "Capabilities", "Capability", "useCapability", "RootAttentionProvider", "SelectionProvider", "meta", "AttentionCapabilities", "makeModule", "succeed", "contributes", "ReactContext", "id", "context", "props", "attention", "Attention", "selection", "Selection", "onChange", "nextAttended", "children"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/operations/select.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\nimport * as Match from 'effect/Match';\n\nimport { Capability } from '@dxos/app-framework';\nimport { LayoutOperation } from '@dxos/app-toolkit';\nimport { Operation } from '@dxos/compute';\n\nimport { AttentionCapabilities } from '../types';\n\nconst handler: Operation.WithHandler<typeof LayoutOperation.Select> = LayoutOperation.Select.pipe(\n Operation.withHandler(\n Effect.fnUntraced(function* (input) {\n const selection = yield* Capability.get(AttentionCapabilities.Selection);\n Match.value(input.subject).pipe(\n Match.when({ mode: 'single', id: undefined }, () => {\n selection.clearSelection(input.contextId);\n }),\n Match.when({ mode: 'single' }, (s) => {\n selection.updateSingle(input.contextId, s.id!);\n }),\n Match.when({ mode: 'multi' }, (s) => {\n selection.updateMulti(input.contextId, s.ids);\n }),\n Match.when({ mode: 'range', from: undefined, to: undefined }, () => {\n selection.clearSelection(input.contextId);\n }),\n Match.when({ mode: 'range' }, (s) => {\n selection.updateRange(input.contextId, s.from!, s.to!);\n }),\n Match.when({ mode: 'multi-range' }, (s) => {\n selection.updateMultiRange(input.contextId, s.ranges);\n }),\n Match.exhaustive,\n );\n }),\n ),\n);\n\nexport default handler;\n"],
|
|
5
|
-
"mappings": ";;;;;AAIA,YAAYA,YAAY;AACxB,YAAYC,WAAW;AAEvB,SAASC,kBAAkB;AAC3B,SAASC,uBAAuB;AAChC,SAASC,iBAAiB;AAI1B,IAAMC,UAAgEC,gBAAgBC,OAAOC,KAC3FC,UAAUC,YACDC,kBAAW,WAAWC,OAAK;AAChC,QAAMC,YAAY,OAAOC,WAAWC,IAAIC,sBAAsBC,SAAS;AACvEC,EAAMC,YAAMP,MAAMQ,OAAO,EAAEZ,KACnBa,WAAK;IAAEC,MAAM;IAAUC,IAAIC;EAAU,GAAG,MAAA;AAC5CX,cAAUY,eAAeb,MAAMc,SAAS;EAC1C,CAAA,GACML,WAAK;IAAEC,MAAM;EAAS,GAAG,CAACK,MAAAA;AAC9Bd,cAAUe,aAAahB,MAAMc,WAAWC,EAAEJ,EAAE;EAC9C,CAAA,GACMF,WAAK;IAAEC,MAAM;EAAQ,GAAG,CAACK,MAAAA;AAC7Bd,cAAUgB,YAAYjB,MAAMc,WAAWC,EAAEG,GAAG;EAC9C,CAAA,GACMT,WAAK;IAAEC,MAAM;IAASS,MAAMP;IAAWQ,IAAIR;EAAU,GAAG,MAAA;AAC5DX,cAAUY,eAAeb,MAAMc,SAAS;EAC1C,CAAA,GACML,WAAK;IAAEC,MAAM;EAAQ,GAAG,CAACK,MAAAA;AAC7Bd,cAAUoB,YAAYrB,MAAMc,WAAWC,EAAEI,MAAOJ,EAAEK,EAAE;EACtD,CAAA,GACMX,WAAK;IAAEC,MAAM;EAAc,GAAG,CAACK,MAAAA;AACnCd,cAAUqB,iBAAiBtB,MAAMc,WAAWC,EAAEQ,MAAM;EACtD,CAAA,GACMC,gBAAU;AAEpB,CAAA,CAAA,CAAA;AAIJ,IAAA,iBAAe/B;",
|
|
6
|
-
"names": ["Effect", "Match", "Capability", "LayoutOperation", "Operation", "handler", "LayoutOperation", "Select", "pipe", "Operation", "withHandler", "fnUntraced", "input", "selection", "Capability", "get", "AttentionCapabilities", "Selection", "Match", "value", "subject", "when", "mode", "id", "undefined", "clearSelection", "contextId", "s", "updateSingle", "updateMulti", "ids", "from", "to", "updateRange", "updateMultiRange", "ranges", "exhaustive"]
|
|
7
|
-
}
|
|
File without changes
|