@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,8 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AttentionManager,
|
|
3
|
-
|
|
3
|
+
LocalBackend,
|
|
4
|
+
MemoryBackend,
|
|
4
5
|
SelectionSchema,
|
|
6
|
+
ViewStateManager,
|
|
7
|
+
createDefaultBackends,
|
|
5
8
|
defaultSelection,
|
|
9
|
+
defineViewState,
|
|
6
10
|
expandAttendableId,
|
|
7
11
|
getAttendables,
|
|
8
12
|
getLinkedVariant,
|
|
@@ -10,13 +14,20 @@ import {
|
|
|
10
14
|
getSegmentId,
|
|
11
15
|
getSelectionSet,
|
|
12
16
|
isLinkedSegment,
|
|
13
|
-
linkedSegment
|
|
14
|
-
|
|
17
|
+
linkedSegment,
|
|
18
|
+
resolveSelection,
|
|
19
|
+
selectionAspect,
|
|
20
|
+
toggleSelection
|
|
21
|
+
} from "../chunk-4HYAJ4IO.mjs";
|
|
15
22
|
export {
|
|
16
23
|
AttentionManager,
|
|
17
|
-
|
|
24
|
+
LocalBackend,
|
|
25
|
+
MemoryBackend,
|
|
18
26
|
SelectionSchema,
|
|
27
|
+
ViewStateManager,
|
|
28
|
+
createDefaultBackends,
|
|
19
29
|
defaultSelection,
|
|
30
|
+
defineViewState,
|
|
20
31
|
expandAttendableId,
|
|
21
32
|
getAttendables,
|
|
22
33
|
getLinkedVariant,
|
|
@@ -24,6 +35,9 @@ export {
|
|
|
24
35
|
getSegmentId,
|
|
25
36
|
getSelectionSet,
|
|
26
37
|
isLinkedSegment,
|
|
27
|
-
linkedSegment
|
|
38
|
+
linkedSegment,
|
|
39
|
+
resolveSelection,
|
|
40
|
+
selectionAspect,
|
|
41
|
+
toggleSelection
|
|
28
42
|
};
|
|
29
43
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
AttentionManager,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
getAttendables
|
|
7
|
-
|
|
4
|
+
ViewStateManager,
|
|
5
|
+
createDefaultBackends,
|
|
6
|
+
getAttendables,
|
|
7
|
+
resolveSelection,
|
|
8
|
+
selectionAspect,
|
|
9
|
+
toggleSelection
|
|
10
|
+
} from "./chunk-HWN7KJDX.mjs";
|
|
8
11
|
|
|
9
12
|
// src/components/AttentionProvider/AttentionProvider.tsx
|
|
10
13
|
import { RegistryContext } from "@effect-atom/atom-react";
|
|
@@ -118,127 +121,102 @@ var AttendableContainer = /* @__PURE__ */ forwardRef(({ id, classNames, children
|
|
|
118
121
|
}, children);
|
|
119
122
|
});
|
|
120
123
|
|
|
121
|
-
// src/components/
|
|
124
|
+
// src/components/ViewStateProvider/ViewStateProvider.tsx
|
|
122
125
|
import { RegistryContext as RegistryContext2 } from "@effect-atom/atom-react";
|
|
123
126
|
import { createContext as createContext2 } from "@radix-ui/react-context";
|
|
124
|
-
import
|
|
125
|
-
import
|
|
127
|
+
import React2, { useContext as useContext2, useEffect as useEffect2, useMemo as useMemo2, useState as useState2 } from "react";
|
|
128
|
+
import { invariant } from "@dxos/invariant";
|
|
126
129
|
import { useDefaultValue as useDefaultValue2 } from "@dxos/react-hooks";
|
|
127
|
-
var
|
|
128
|
-
var
|
|
129
|
-
|
|
130
|
+
var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-attention/src/components/ViewStateProvider/ViewStateProvider.tsx";
|
|
131
|
+
var VIEW_STATE_NAME = "ViewState";
|
|
132
|
+
var [ViewStateContextProvider, useViewStateContext] = createContext2(VIEW_STATE_NAME, {
|
|
133
|
+
manager: void 0
|
|
130
134
|
});
|
|
131
|
-
var
|
|
135
|
+
var ViewStateProvider = ({ children, manager: managerProp }) => {
|
|
132
136
|
const registry = useContext2(RegistryContext2);
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
137
|
+
const manager = useDefaultValue2(managerProp, () => new ViewStateManager({
|
|
138
|
+
registry,
|
|
139
|
+
backends: createDefaultBackends(registry)
|
|
140
|
+
}));
|
|
141
|
+
return /* @__PURE__ */ React2.createElement(ViewStateContextProvider, {
|
|
142
|
+
manager
|
|
136
143
|
}, children);
|
|
137
144
|
};
|
|
138
|
-
var
|
|
139
|
-
const {
|
|
140
|
-
|
|
145
|
+
var useViewStateManager = () => {
|
|
146
|
+
const { manager } = useViewStateContext(VIEW_STATE_NAME);
|
|
147
|
+
invariant(manager, "useViewStateManager() requires a ViewStateProvider ancestor.", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 29, S: void 0, A: ["manager", "'useViewStateManager() requires a ViewStateProvider ancestor.'"] });
|
|
148
|
+
return manager;
|
|
141
149
|
};
|
|
142
|
-
var
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}, (selection) => selection.id), Match.when({
|
|
146
|
-
mode: "multi"
|
|
147
|
-
}, (selection) => selection.ids), Match.when({
|
|
148
|
-
mode: "range"
|
|
149
|
-
}, (selection) => selection.from && selection.to ? {
|
|
150
|
-
from: selection.from,
|
|
151
|
-
to: selection.to
|
|
152
|
-
} : void 0), Match.when({
|
|
153
|
-
mode: "multi-range"
|
|
154
|
-
}, (selection) => selection.ranges), Match.exhaustive)(defaultSelection(mode));
|
|
150
|
+
var useViewStateManagerOptional = () => {
|
|
151
|
+
const { manager } = useViewStateContext(VIEW_STATE_NAME);
|
|
152
|
+
return manager;
|
|
155
153
|
};
|
|
156
|
-
var
|
|
157
|
-
const {
|
|
158
|
-
const [
|
|
154
|
+
var useViewState = (aspect, contextId) => {
|
|
155
|
+
const { manager } = useViewStateContext(VIEW_STATE_NAME);
|
|
156
|
+
const [value, setValue] = useState2(() => contextId && manager ? manager.get(aspect, contextId) : aspect.defaultValue());
|
|
159
157
|
useEffect2(() => {
|
|
160
|
-
if (!contextId || !
|
|
161
|
-
|
|
158
|
+
if (!contextId || !manager) {
|
|
159
|
+
setValue(aspect.defaultValue());
|
|
162
160
|
return;
|
|
163
161
|
}
|
|
164
|
-
|
|
165
|
-
return
|
|
166
|
-
setState(selection.getSelected(contextId, mode));
|
|
167
|
-
});
|
|
162
|
+
setValue(manager.get(aspect, contextId));
|
|
163
|
+
return manager.subscribe(aspect, contextId, setValue);
|
|
168
164
|
}, [
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
165
|
+
manager,
|
|
166
|
+
aspect,
|
|
167
|
+
contextId
|
|
172
168
|
]);
|
|
173
|
-
return
|
|
169
|
+
return value;
|
|
174
170
|
};
|
|
175
|
-
var
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
171
|
+
var useViewStateActions = (aspect, contextId) => {
|
|
172
|
+
const { manager } = useViewStateContext(VIEW_STATE_NAME);
|
|
173
|
+
return useMemo2(() => ({
|
|
174
|
+
set: (value) => {
|
|
175
|
+
if (contextId) {
|
|
176
|
+
manager?.set(aspect, contextId, value);
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
update: (fn) => {
|
|
180
|
+
if (contextId) {
|
|
181
|
+
manager?.update(aspect, contextId, fn);
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
clear: () => {
|
|
185
|
+
if (contextId) {
|
|
186
|
+
manager?.set(aspect, contextId, aspect.defaultValue());
|
|
187
|
+
}
|
|
183
188
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
selection,
|
|
189
|
-
stableContextIds
|
|
189
|
+
}), [
|
|
190
|
+
manager,
|
|
191
|
+
aspect,
|
|
192
|
+
contextId
|
|
190
193
|
]);
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
for (const contextId of stableContextIds) {
|
|
218
|
-
selection.toggleSelection(contextId, id);
|
|
219
|
-
}
|
|
220
|
-
}, [
|
|
221
|
-
selection,
|
|
222
|
-
stableContextIds
|
|
223
|
-
]);
|
|
224
|
-
const clear = useCallback2(() => {
|
|
225
|
-
if (!selection) {
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
for (const contextId of stableContextIds) {
|
|
229
|
-
selection.clearSelection(contextId);
|
|
230
|
-
}
|
|
231
|
-
}, [
|
|
232
|
-
selection,
|
|
233
|
-
stableContextIds
|
|
234
|
-
]);
|
|
235
|
-
return {
|
|
236
|
-
singleSelect,
|
|
237
|
-
multiSelect,
|
|
238
|
-
rangeSelect,
|
|
239
|
-
toggle,
|
|
194
|
+
};
|
|
195
|
+
var useSelection = (contextId, mode = "multi") => resolveSelection(useViewState(selectionAspect, contextId), mode);
|
|
196
|
+
var useSelectionActions = (contextId) => {
|
|
197
|
+
const { update, clear } = useViewStateActions(selectionAspect, contextId);
|
|
198
|
+
return useMemo2(() => ({
|
|
199
|
+
single: (id) => update(() => ({
|
|
200
|
+
mode: "single",
|
|
201
|
+
id
|
|
202
|
+
})),
|
|
203
|
+
multi: (ids) => update(() => ({
|
|
204
|
+
mode: "multi",
|
|
205
|
+
ids: [
|
|
206
|
+
...ids
|
|
207
|
+
]
|
|
208
|
+
})),
|
|
209
|
+
range: (from, to) => update(() => ({
|
|
210
|
+
mode: "range",
|
|
211
|
+
from,
|
|
212
|
+
to
|
|
213
|
+
})),
|
|
214
|
+
toggle: (id) => update((prev) => toggleSelection(prev, id)),
|
|
215
|
+
clear
|
|
216
|
+
}), [
|
|
217
|
+
update,
|
|
240
218
|
clear
|
|
241
|
-
|
|
219
|
+
]);
|
|
242
220
|
};
|
|
243
221
|
|
|
244
222
|
export {
|
|
@@ -248,9 +226,12 @@ export {
|
|
|
248
226
|
useAttentionAttributes,
|
|
249
227
|
RootAttentionProvider,
|
|
250
228
|
AttendableContainer,
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
229
|
+
ViewStateProvider,
|
|
230
|
+
useViewStateManager,
|
|
231
|
+
useViewStateManagerOptional,
|
|
232
|
+
useViewState,
|
|
233
|
+
useViewStateActions,
|
|
234
|
+
useSelection,
|
|
254
235
|
useSelectionActions
|
|
255
236
|
};
|
|
256
|
-
//# sourceMappingURL=chunk-
|
|
237
|
+
//# sourceMappingURL=chunk-DLBZMHST.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/components/AttentionProvider/AttentionProvider.tsx", "../../../src/components/ViewStateProvider/ViewStateProvider.tsx"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { RegistryContext } from '@effect-atom/atom-react';\nimport { createContext } from '@radix-ui/react-context';\nimport { Primitive } from '@radix-ui/react-primitive';\nimport { Slot } from '@radix-ui/react-slot';\nimport React, {\n type ComponentPropsWithRef,\n type FocusEvent,\n type PropsWithChildren,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from 'react';\n\nimport { log } from '@dxos/log';\nimport { useDefaultValue } from '@dxos/react-hooks';\nimport { type ThemedClassName } from '@dxos/react-ui';\nimport { mx } from '@dxos/ui-theme';\n\nimport { type Attention, AttentionManager, getAttendables } from '../../attention';\n\nconst ATTENTION_NAME = 'Attention';\nconst ATTENDABLE_ATTRIBUTE = 'data-attendable-id';\nconst ATTENTION_SOURCE_ATTRIBUTE = 'data-w-attention-source';\n\ntype AttentionContextValue = {\n attention: AttentionManager;\n};\n\nconst [AttentionContextProvider, useAttentionContext] = createContext<AttentionContextValue>(ATTENTION_NAME, {\n attention: undefined as unknown as AttentionManager,\n});\n\nconst UNKNOWN_ATTENDABLE = { hasAttention: false, isAncestor: false, isRelated: false } as Attention;\n\n/**\n * Subscribe to the attention state for a qualified graph ID.\n */\n// TODO(burdon): Unify with seleciton and change to contextId?\nconst useAttention = (attendableId?: string): Attention => {\n const { attention } = useAttentionContext(ATTENTION_NAME);\n const [state, setState] = useState<Attention>(UNKNOWN_ATTENDABLE);\n useEffect(() => {\n if (!attendableId || !attention) {\n setState(UNKNOWN_ATTENDABLE);\n return;\n }\n\n const currentState = attention.get(attendableId);\n setState(currentState);\n\n return attention.subscribe(attendableId, (newState) => {\n setState(newState);\n });\n }, [attention, attendableId]);\n\n return state;\n};\n\nconst useAttended = () => {\n const { attention } = useAttentionContext(ATTENTION_NAME);\n const [current, setCurrent] = useState<readonly string[]>([]);\n useEffect(() => {\n if (!attention) {\n return;\n }\n\n setCurrent(attention.getCurrent());\n\n return attention.subscribeCurrent((newCurrent) => {\n setCurrent(newCurrent);\n });\n }, [attention]);\n\n return current;\n};\n\n/**\n * Computes HTML element attributes to apply so the attention system can detect changes.\n */\nconst useAttentionAttributes = (attendableId?: string) => {\n const { hasAttention } = useAttention(attendableId);\n return useMemo(() => {\n const attributes: Record<string, string | undefined> = { [ATTENDABLE_ATTRIBUTE]: attendableId };\n if (hasAttention) {\n attributes[ATTENTION_SOURCE_ATTRIBUTE] = 'true';\n }\n\n return attributes;\n }, [attendableId, hasAttention]);\n};\n\ntype RootAttentionProviderProps = PropsWithChildren<{\n attention?: AttentionManager;\n onChange?: (nextAttended: string[]) => void;\n}>;\n\nconst RootAttentionProvider = ({ children, attention: propsAttention, onChange }: RootAttentionProviderProps) => {\n const registry = useContext(RegistryContext);\n const attention = useDefaultValue(propsAttention, () => new AttentionManager(registry));\n\n const handleFocus = useCallback(\n (event: FocusEvent) => {\n // NOTE(thure): Use the following to debug focus movement across the app:\n log('focus', { related: event.relatedTarget, target: event.target });\n\n const selector = [\n '[data-attendable-id]',\n ...Array.from(document.querySelectorAll('[aria-controls]')).map(\n (el) => `[id=\"${el.getAttribute('aria-controls')}\"]`,\n ),\n ].join(',');\n const prev = attention.getCurrent();\n const next = getAttendables(selector, event.target);\n // TODO(wittjosiah): Not allowing empty state means that the attended item is not strictly guaranteed to be in the DOM.\n // Currently this depends on the deck in order to ensure that when the attended item is removed something else is attended.\n // Only update state if the result is different and not empty.\n if (next.length > 0 && (prev.length !== next.length || !!prev.find((id, index) => next[index] !== id))) {\n attention.update(next);\n onChange?.(next);\n }\n },\n [attention, onChange],\n );\n\n return (\n <AttentionContextProvider attention={attention}>\n <div className='contents' onFocusCapture={handleFocus}>\n {children}\n </div>\n </AttentionContextProvider>\n );\n};\n\nexport type AttendableContainerProps = ThemedClassName<\n ComponentPropsWithRef<'div'> & { id: string; asChild?: boolean }\n>;\n\n/**\n * Note that DeckPlugin and StackPlugin both handle attention on their own,\n * and when rendering content in those cases it is not necessary to also render an `AttendableContainer`.\n * This component is primarily for Storybook stories and other testing scenarios,\n * or the rare cases where an attendable entity is rendered outside of either of those plugins.\n */\nconst AttendableContainer = forwardRef<HTMLDivElement, AttendableContainerProps>(\n ({ id, classNames, children, asChild, ...props }, forwardedRef) => {\n const attentionAttrs = useAttentionAttributes(id);\n const Comp = asChild ? Slot : Primitive.div;\n return (\n <Comp\n role='none'\n {...props}\n {...attentionAttrs}\n className={mx('dx-attention-surface', props.tabIndex === 0 && 'dx-focus-ring-inset-over-all', classNames)}\n ref={forwardedRef}\n >\n {children}\n </Comp>\n );\n },\n);\n\nexport {\n AttendableContainer,\n RootAttentionProvider,\n useAttended,\n useAttention,\n useAttentionAttributes,\n useAttentionContext,\n};\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport { RegistryContext } from '@effect-atom/atom-react';\nimport { createContext } from '@radix-ui/react-context';\nimport React, { type PropsWithChildren, useContext, useEffect, useMemo, useState } from 'react';\n\nimport { invariant } from '@dxos/invariant';\nimport { useDefaultValue } from '@dxos/react-hooks';\n\nimport {\n type SelectionMode,\n type SelectionResult,\n resolveSelection,\n selectionAspect,\n toggleSelection,\n} from '../../selection';\nimport { type AspectDef, ViewStateManager, createDefaultBackends } from '../../view-state';\n\nconst VIEW_STATE_NAME = 'ViewState';\n\ntype ViewStateContextValue = { manager?: ViewStateManager };\n\n// Default value lets consumers render outside a provider (isolated stories/tests) without throwing;\n// `manager` reads as `undefined` and hooks fall back to aspect defaults / no-op actions.\nconst [ViewStateContextProvider, useViewStateContext] = createContext<ViewStateContextValue>(VIEW_STATE_NAME, {\n manager: undefined,\n});\n\n/** Provides the per-context UI state manager. Replaces the former `SelectionProvider`. */\nexport const ViewStateProvider = ({\n children,\n manager: managerProp,\n}: PropsWithChildren<{ manager?: ViewStateManager }>) => {\n const registry = useContext(RegistryContext);\n const manager = useDefaultValue(\n managerProp,\n () => new ViewStateManager({ registry, backends: createDefaultBackends(registry) }),\n );\n return <ViewStateContextProvider manager={manager}>{children}</ViewStateContextProvider>;\n};\n\n/** Access the underlying ViewStateManager from context. Throws when used outside a `ViewStateProvider`. */\nexport const useViewStateManager = (): ViewStateManager => {\n const { manager } = useViewStateContext(VIEW_STATE_NAME);\n invariant(manager, 'useViewStateManager() requires a ViewStateProvider ancestor.');\n return manager;\n};\n\n/** Access the ViewStateManager if a provider is present; `undefined` otherwise (e.g. isolated stories/tests). */\nexport const useViewStateManagerOptional = (): ViewStateManager | undefined => {\n const { manager } = useViewStateContext(VIEW_STATE_NAME);\n return manager;\n};\n\n/** Reactive read of an aspect value for a context; yields the aspect default when unset or unprovided. */\nexport const useViewState = <T,>(aspect: AspectDef<T>, contextId?: string): T => {\n const { manager } = useViewStateContext(VIEW_STATE_NAME);\n const [value, setValue] = useState<T>(() =>\n contextId && manager ? manager.get(aspect, contextId) : aspect.defaultValue(),\n );\n useEffect(() => {\n if (!contextId || !manager) {\n setValue(aspect.defaultValue());\n return;\n }\n setValue(manager.get(aspect, contextId));\n return manager.subscribe(aspect, contextId, setValue);\n }, [manager, aspect, contextId]);\n return value;\n};\n\nexport type UseViewStateActions<T> = {\n set: (value: T) => void;\n update: (fn: (prev: T) => T) => void;\n clear: () => void;\n};\n\nexport const useViewStateActions = <T,>(aspect: AspectDef<T>, contextId?: string): UseViewStateActions<T> => {\n const { manager } = useViewStateContext(VIEW_STATE_NAME);\n return useMemo<UseViewStateActions<T>>(\n () => ({\n set: (value) => {\n if (contextId) {\n manager?.set(aspect, contextId, value);\n }\n },\n update: (fn) => {\n if (contextId) {\n manager?.update(aspect, contextId, fn);\n }\n },\n clear: () => {\n if (contextId) {\n manager?.set(aspect, contextId, aspect.defaultValue());\n }\n },\n }),\n [manager, aspect, contextId],\n );\n};\n\n/** Resolved selection value for `contextId` in the requested `mode` (default `multi`). */\nexport const useSelection = <T extends SelectionMode>(contextId?: string, mode: T = 'multi' as T): SelectionResult<T> =>\n resolveSelection(useViewState(selectionAspect, contextId), mode);\n\nexport type UseSelectionActions = {\n single: (id: string) => void;\n multi: (ids: string[]) => void;\n range: (from: string, to: string) => void;\n toggle: (id: string) => void;\n clear: () => void;\n};\n\n/** Selection mutators for a single context, built on the generic ViewState actions. */\nexport const useSelectionActions = (contextId?: string): UseSelectionActions => {\n const { update, clear } = useViewStateActions(selectionAspect, contextId);\n return useMemo<UseSelectionActions>(\n () => ({\n single: (id) => update(() => ({ mode: 'single', id })),\n multi: (ids) => update(() => ({ mode: 'multi', ids: [...ids] })),\n range: (from, to) => update(() => ({ mode: 'range', from, to })),\n toggle: (id) => update((prev) => toggleSelection(prev, id)),\n clear,\n }),\n [update, clear],\n );\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["RegistryContext", "createContext", "Primitive", "Slot", "React", "forwardRef", "useCallback", "useContext", "useEffect", "useMemo", "useState", "log", "useDefaultValue", "mx", "ATTENTION_NAME", "ATTENTION_SOURCE_ATTRIBUTE", "AttentionContextProvider", "attention", "undefined", "UNKNOWN_ATTENDABLE", "isAncestor", "isRelated", "setState", "useState", "useEffect", "attendableId", "subscribe", "newState", "useAttended", "setCurrent", "newCurrent", "attributes", "ATTENDABLE_ATTRIBUTE", "hasAttention", "useDefaultValue", "propsAttention", "AttentionManager", "registry", "handleFocus", "useCallback", "event", "log", "target", "selector", "join", "prev", "getCurrent", "next", "onChange", "div", "className", "onFocusCapture", "children", "Comp", "role", "attentionAttrs", "ref", "AttendableContainer", "RegistryContext", "createContext", "React", "useContext", "useEffect", "useMemo", "useState", "invariant", "useDefaultValue", "__dxlog_file", "VIEW_STATE_NAME", "createContext", "registry", "backends", "createDefaultBackends", "ViewStateContextProvider", "manager", "children", "defaultValue", "useEffect", "contextId", "setValue", "useMemo", "set", "value", "update", "clear", "aspect", "single", "mode", "id", "ids", "from", "to"]
|
|
7
|
+
}
|