@dxos/react-ui-attention 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.
- package/dist/lib/browser/chunk-4HYAJ4IO.mjs +434 -0
- package/dist/lib/browser/chunk-4HYAJ4IO.mjs.map +7 -0
- package/dist/lib/browser/{chunk-I4VO2RQM.mjs → chunk-I4FDY4AZ.mjs} +92 -111
- package/dist/lib/browser/chunk-I4FDY4AZ.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +36 -15
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +4 -4
- package/dist/lib/browser/testing/index.mjs.map +2 -2
- package/dist/lib/browser/types/index.mjs +19 -5
- package/dist/lib/node-esm/{chunk-ZTUVSH4P.mjs → chunk-DLBZMHST.mjs} +92 -111
- package/dist/lib/node-esm/chunk-DLBZMHST.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-HWN7KJDX.mjs +436 -0
- package/dist/lib/node-esm/chunk-HWN7KJDX.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +36 -15
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +4 -4
- package/dist/lib/node-esm/testing/index.mjs.map +2 -2
- package/dist/lib/node-esm/types/index.mjs +19 -5
- package/dist/types/src/components/AttentionGlyph/AttentionGlyph.d.ts.map +1 -1
- package/dist/types/src/components/AttentionProvider/AttentionProvider.d.ts +1 -1
- package/dist/types/src/components/AttentionProvider/AttentionProvider.d.ts.map +1 -1
- package/dist/types/src/components/ViewStateProvider/ViewStateProvider.d.ts +31 -0
- package/dist/types/src/components/ViewStateProvider/ViewStateProvider.d.ts.map +1 -0
- package/dist/types/src/components/ViewStateProvider/ViewStateProvider.test.d.ts +2 -0
- package/dist/types/src/components/ViewStateProvider/ViewStateProvider.test.d.ts.map +1 -0
- package/dist/types/src/components/ViewStateProvider/index.d.ts +2 -0
- package/dist/types/src/components/ViewStateProvider/index.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/selection.d.ts +10 -40
- package/dist/types/src/selection.d.ts.map +1 -1
- package/dist/types/src/selection.test.d.ts +2 -0
- package/dist/types/src/selection.test.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +1 -0
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/useArticleKeyboardNavigation.d.ts.map +1 -1
- package/dist/types/src/view-state/backends.d.ts +24 -0
- package/dist/types/src/view-state/backends.d.ts.map +1 -0
- package/dist/types/src/view-state/backends.test.d.ts +2 -0
- package/dist/types/src/view-state/backends.test.d.ts.map +1 -0
- package/dist/types/src/view-state/index.d.ts +3 -0
- package/dist/types/src/view-state/index.d.ts.map +1 -0
- package/dist/types/src/view-state/view-state.d.ts +54 -0
- package/dist/types/src/view-state/view-state.d.ts.map +1 -0
- package/dist/types/src/view-state/view-state.test.d.ts +2 -0
- package/dist/types/src/view-state/view-state.test.d.ts.map +1 -0
- package/dist/types/src/vitest-setup.d.ts +2 -0
- package/dist/types/src/vitest-setup.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +22 -20
- package/src/components/AttentionGlyph/AttentionGlyph.tsx +1 -1
- package/src/components/AttentionProvider/AttentionProvider.tsx +3 -3
- package/src/components/ViewStateProvider/ViewStateProvider.test.tsx +45 -0
- package/src/components/ViewStateProvider/ViewStateProvider.tsx +129 -0
- package/src/components/ViewStateProvider/index.ts +5 -0
- package/src/components/index.ts +1 -1
- package/src/index.ts +1 -0
- package/src/selection.test.ts +67 -0
- package/src/selection.ts +39 -169
- package/src/testing/decorators/withAttention.ts +2 -2
- package/src/types/index.ts +1 -0
- package/src/useArticleKeyboardNavigation.ts +5 -4
- package/src/view-state/backends.test.ts +104 -0
- package/src/view-state/backends.ts +145 -0
- package/src/view-state/index.ts +6 -0
- package/src/view-state/view-state.test.ts +54 -0
- package/src/view-state/view-state.ts +91 -0
- package/src/vitest-setup.ts +6 -0
- package/dist/lib/browser/chunk-D2BLVJ6Z.mjs +0 -421
- package/dist/lib/browser/chunk-D2BLVJ6Z.mjs.map +0 -7
- package/dist/lib/browser/chunk-I4VO2RQM.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-6INLBC62.mjs +0 -423
- package/dist/lib/node-esm/chunk-6INLBC62.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-ZTUVSH4P.mjs.map +0 -7
- package/dist/types/src/components/SelectionProvider/SelectionProvider.d.ts +0 -28
- package/dist/types/src/components/SelectionProvider/SelectionProvider.d.ts.map +0 -1
- package/dist/types/src/components/SelectionProvider/index.d.ts +0 -2
- package/dist/types/src/components/SelectionProvider/index.d.ts.map +0 -1
- package/src/components/SelectionProvider/SelectionProvider.tsx +0 -174
- package/src/components/SelectionProvider/index.ts +0 -5
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { RegistryContext } from '@effect-atom/atom-react';
|
|
6
|
-
import { createContext } from '@radix-ui/react-context';
|
|
7
|
-
import * as Match from 'effect/Match';
|
|
8
|
-
import React, { type PropsWithChildren, useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
|
9
|
-
|
|
10
|
-
import { useDefaultValue } from '@dxos/react-hooks';
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
type Selection,
|
|
14
|
-
SelectionManager,
|
|
15
|
-
type SelectionMode,
|
|
16
|
-
type SelectionResult,
|
|
17
|
-
defaultSelection,
|
|
18
|
-
} from '../../selection';
|
|
19
|
-
|
|
20
|
-
const SELECTION_NAME = 'Selection';
|
|
21
|
-
|
|
22
|
-
type SelectionContextValue = {
|
|
23
|
-
selection: SelectionManager;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
// Default value lets consumers like `useSelected` render outside a
|
|
27
|
-
// `SelectionProvider` (e.g. isolated stories) without throwing —
|
|
28
|
-
// `selection` reads as `undefined` and the hook falls back to the
|
|
29
|
-
// per-mode default result. Without this default, Radix `createContext`
|
|
30
|
-
// throws "Selection must be used within Selection" on every consumer.
|
|
31
|
-
const [SelectionContextProvider, useSelectionContext] = createContext<SelectionContextValue>(SELECTION_NAME, {
|
|
32
|
-
selection: undefined as unknown as SelectionManager,
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Manages selection state across the app for multiple contexts.
|
|
37
|
-
*/
|
|
38
|
-
export const SelectionProvider = ({
|
|
39
|
-
children,
|
|
40
|
-
selection: selectionProp,
|
|
41
|
-
}: PropsWithChildren<{ selection?: SelectionManager }>) => {
|
|
42
|
-
const registry = useContext(RegistryContext);
|
|
43
|
-
const selection = useDefaultValue(selectionProp, () => new SelectionManager(registry));
|
|
44
|
-
|
|
45
|
-
return <SelectionContextProvider selection={selection}>{children}</SelectionContextProvider>;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Get the selection contexts.
|
|
50
|
-
*/
|
|
51
|
-
export const useSelectionManager = (): SelectionManager => {
|
|
52
|
-
const { selection } = useSelectionContext(SELECTION_NAME);
|
|
53
|
-
return selection;
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
const getDefaultResult = <T extends SelectionMode>(mode: T): SelectionResult<T> => {
|
|
57
|
-
return Match.type<Selection>().pipe(
|
|
58
|
-
Match.when({ mode: 'single' }, (selection) => selection.id),
|
|
59
|
-
Match.when({ mode: 'multi' }, (selection) => selection.ids),
|
|
60
|
-
Match.when({ mode: 'range' }, (selection) =>
|
|
61
|
-
selection.from && selection.to ? { from: selection.from, to: selection.to } : undefined,
|
|
62
|
-
),
|
|
63
|
-
Match.when({ mode: 'multi-range' }, (selection) => selection.ranges),
|
|
64
|
-
Match.exhaustive,
|
|
65
|
-
)(defaultSelection(mode)) as SelectionResult<T>;
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Get the selected objects for a given context.
|
|
70
|
-
*/
|
|
71
|
-
export const useSelected = <T extends SelectionMode>(
|
|
72
|
-
contextId?: string,
|
|
73
|
-
mode: T = 'multi' as T,
|
|
74
|
-
): SelectionResult<T> => {
|
|
75
|
-
const { selection } = useSelectionContext(SELECTION_NAME);
|
|
76
|
-
const [state, setState] = useState<SelectionResult<T>>(() =>
|
|
77
|
-
contextId && selection ? selection.getSelected(contextId, mode) : getDefaultResult(mode),
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
useEffect(() => {
|
|
81
|
-
if (!contextId || !selection) {
|
|
82
|
-
setState(getDefaultResult(mode));
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Set initial state.
|
|
87
|
-
setState(selection.getSelected(contextId, mode));
|
|
88
|
-
|
|
89
|
-
// Subscribe to changes.
|
|
90
|
-
return selection.subscribe(() => {
|
|
91
|
-
setState(selection.getSelected(contextId, mode));
|
|
92
|
-
});
|
|
93
|
-
}, [selection, contextId, mode]);
|
|
94
|
-
|
|
95
|
-
return state;
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
export type UseSelectionActions = {
|
|
99
|
-
singleSelect: (id: string) => void;
|
|
100
|
-
multiSelect: (ids: string[]) => void;
|
|
101
|
-
rangeSelect: (from: string, to: string) => void;
|
|
102
|
-
toggle: (id: string) => void;
|
|
103
|
-
clear: () => void;
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Provides functions to manage the selection state for multiple contexts.
|
|
108
|
-
*/
|
|
109
|
-
export const useSelectionActions = (contextIds: string[]): UseSelectionActions => {
|
|
110
|
-
const stableContextIds = useMemo(() => contextIds, [JSON.stringify(contextIds)]);
|
|
111
|
-
const { selection } = useSelectionContext(SELECTION_NAME);
|
|
112
|
-
|
|
113
|
-
// No-op when rendered outside a `SelectionProvider` (e.g. an isolated
|
|
114
|
-
// story or a test harness) — `selection` is `undefined` from the
|
|
115
|
-
// context default value. Matches the pre-co-locate behaviour.
|
|
116
|
-
const singleSelect = useCallback(
|
|
117
|
-
(id: string) => {
|
|
118
|
-
if (!selection) {
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
for (const contextId of stableContextIds) {
|
|
122
|
-
selection.updateSingle(contextId, id);
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
[selection, stableContextIds],
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
const multiSelect = useCallback(
|
|
129
|
-
(ids: string[]) => {
|
|
130
|
-
if (!selection) {
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
for (const contextId of stableContextIds) {
|
|
134
|
-
selection.updateMulti(contextId, ids);
|
|
135
|
-
}
|
|
136
|
-
},
|
|
137
|
-
[selection, stableContextIds],
|
|
138
|
-
);
|
|
139
|
-
|
|
140
|
-
const rangeSelect = useCallback(
|
|
141
|
-
(from: string, to: string) => {
|
|
142
|
-
if (!selection) {
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
for (const contextId of stableContextIds) {
|
|
146
|
-
selection.updateRange(contextId, from, to);
|
|
147
|
-
}
|
|
148
|
-
},
|
|
149
|
-
[selection, stableContextIds],
|
|
150
|
-
);
|
|
151
|
-
|
|
152
|
-
const toggle = useCallback(
|
|
153
|
-
(id: string) => {
|
|
154
|
-
if (!selection) {
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
for (const contextId of stableContextIds) {
|
|
158
|
-
selection.toggleSelection(contextId, id);
|
|
159
|
-
}
|
|
160
|
-
},
|
|
161
|
-
[selection, stableContextIds],
|
|
162
|
-
);
|
|
163
|
-
|
|
164
|
-
const clear = useCallback(() => {
|
|
165
|
-
if (!selection) {
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
for (const contextId of stableContextIds) {
|
|
169
|
-
selection.clearSelection(contextId);
|
|
170
|
-
}
|
|
171
|
-
}, [selection, stableContextIds]);
|
|
172
|
-
|
|
173
|
-
return { singleSelect, multiSelect, rangeSelect, toggle, clear };
|
|
174
|
-
};
|