@dxos/react-ui-attention 0.8.4-main.c85a9c8dae → 0.8.4-main.cb12b3f963

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 (70) hide show
  1. package/dist/lib/browser/{chunk-TAZUDNJI.mjs → chunk-XVH365AW.mjs} +136 -174
  2. package/dist/lib/browser/chunk-XVH365AW.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +15 -17
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +1 -2
  7. package/dist/lib/browser/testing/index.mjs.map +2 -2
  8. package/dist/lib/node-esm/{chunk-FT553KKP.mjs → chunk-W73A7WMN.mjs} +136 -173
  9. package/dist/lib/node-esm/chunk-W73A7WMN.mjs.map +7 -0
  10. package/dist/lib/node-esm/index.mjs +15 -17
  11. package/dist/lib/node-esm/index.mjs.map +4 -4
  12. package/dist/lib/node-esm/meta.json +1 -1
  13. package/dist/lib/node-esm/testing/index.mjs +1 -2
  14. package/dist/lib/node-esm/testing/index.mjs.map +2 -2
  15. package/dist/types/src/attention.d.ts +46 -11
  16. package/dist/types/src/attention.d.ts.map +1 -1
  17. package/dist/types/src/components/AttentionGlyph/AttentionGlyph.d.ts.map +1 -0
  18. package/dist/types/src/components/AttentionGlyph/AttentionGlyph.stories.d.ts.map +1 -0
  19. package/dist/types/src/components/AttentionGlyph/index.d.ts +2 -0
  20. package/dist/types/src/components/AttentionGlyph/index.d.ts.map +1 -0
  21. package/dist/types/src/components/AttentionProvider/AttentionProvider.d.ts +34 -0
  22. package/dist/types/src/components/AttentionProvider/AttentionProvider.d.ts.map +1 -0
  23. package/dist/types/src/components/AttentionProvider/AttentionProvider.stories.d.ts.map +1 -0
  24. package/dist/types/src/components/AttentionProvider/index.d.ts +2 -0
  25. package/dist/types/src/components/AttentionProvider/index.d.ts.map +1 -0
  26. package/dist/types/src/components/{SelectionProvider.d.ts → SelectionProvider/SelectionProvider.d.ts} +3 -3
  27. package/dist/types/src/components/SelectionProvider/SelectionProvider.d.ts.map +1 -0
  28. package/dist/types/src/components/SelectionProvider/index.d.ts +2 -0
  29. package/dist/types/src/components/SelectionProvider/index.d.ts.map +1 -0
  30. package/dist/types/src/index.d.ts +0 -1
  31. package/dist/types/src/index.d.ts.map +1 -1
  32. package/dist/types/src/selection.d.ts.map +1 -1
  33. package/dist/types/src/testing/decorators/withAttention.d.ts.map +1 -1
  34. package/dist/types/tsconfig.tsbuildinfo +1 -1
  35. package/package.json +15 -31
  36. package/src/attention.test.ts +179 -23
  37. package/src/attention.ts +136 -54
  38. package/src/components/{AttentionGlyph.tsx → AttentionGlyph/AttentionGlyph.tsx} +1 -1
  39. package/src/components/AttentionGlyph/index.ts +5 -0
  40. package/src/components/{AttentionProvider.stories.tsx → AttentionProvider/AttentionProvider.stories.tsx} +1 -2
  41. package/src/components/{AttentionProvider.tsx → AttentionProvider/AttentionProvider.tsx} +46 -78
  42. package/src/components/AttentionProvider/index.ts +5 -0
  43. package/src/components/{SelectionProvider.tsx → SelectionProvider/SelectionProvider.tsx} +15 -8
  44. package/src/components/SelectionProvider/index.ts +5 -0
  45. package/src/index.ts +0 -1
  46. package/src/selection.ts +10 -8
  47. package/src/testing/decorators/withAttention.ts +1 -0
  48. package/dist/lib/browser/chunk-PAZBZOO2.mjs +0 -7
  49. package/dist/lib/browser/chunk-PAZBZOO2.mjs.map +0 -7
  50. package/dist/lib/browser/chunk-TAZUDNJI.mjs.map +0 -7
  51. package/dist/lib/browser/types.mjs +0 -7
  52. package/dist/lib/browser/types.mjs.map +0 -7
  53. package/dist/lib/node-esm/chunk-FT553KKP.mjs.map +0 -7
  54. package/dist/lib/node-esm/chunk-PMGNPL4M.mjs +0 -9
  55. package/dist/lib/node-esm/chunk-PMGNPL4M.mjs.map +0 -7
  56. package/dist/lib/node-esm/types.mjs +0 -8
  57. package/dist/lib/node-esm/types.mjs.map +0 -7
  58. package/dist/types/src/components/AttentionGlyph.d.ts.map +0 -1
  59. package/dist/types/src/components/AttentionGlyph.stories.d.ts.map +0 -1
  60. package/dist/types/src/components/AttentionProvider.d.ts +0 -39
  61. package/dist/types/src/components/AttentionProvider.d.ts.map +0 -1
  62. package/dist/types/src/components/AttentionProvider.stories.d.ts.map +0 -1
  63. package/dist/types/src/components/SelectionProvider.d.ts.map +0 -1
  64. package/dist/types/src/types.d.ts +0 -10
  65. package/dist/types/src/types.d.ts.map +0 -1
  66. package/src/types.ts +0 -16
  67. /package/dist/types/src/components/{AttentionGlyph.d.ts → AttentionGlyph/AttentionGlyph.d.ts} +0 -0
  68. /package/dist/types/src/components/{AttentionGlyph.stories.d.ts → AttentionGlyph/AttentionGlyph.stories.d.ts} +0 -0
  69. /package/dist/types/src/components/{AttentionProvider.stories.d.ts → AttentionProvider/AttentionProvider.stories.d.ts} +0 -0
  70. /package/src/components/{AttentionGlyph.stories.tsx → AttentionGlyph/AttentionGlyph.stories.tsx} +0 -0
@@ -1,38 +1,30 @@
1
- import {
2
- ATTENDABLE_PATH_SEPARATOR
3
- } from "./chunk-PAZBZOO2.mjs";
4
-
5
1
  // src/attention.ts
6
2
  import { Atom } from "@effect-atom/atom-react";
7
- import { ComplexMap } from "@dxos/util";
8
- var stringKey = (key) => key.join(",");
9
3
  var AttentionManager = class {
10
4
  _registry;
11
- // Each attention path is associated with an attention atom.
12
- // The lookup is not a reactive object to ensure that attention for each path is subscribable independently.
13
- _map = new ComplexMap(stringKey);
5
+ _map = /* @__PURE__ */ new Map();
14
6
  _currentAtom;
15
7
  constructor(_registry, initial = []) {
16
8
  this._registry = _registry;
17
- this._currentAtom = Atom.make([]);
9
+ this._currentAtom = Atom.make([]).pipe(Atom.keepAlive);
18
10
  if (initial.length > 0) {
19
11
  this.update(initial);
20
12
  }
21
13
  }
22
14
  /**
23
- * Atom for the currently attended element path.
15
+ * Atom for the currently attended element IDs.
24
16
  */
25
17
  get current() {
26
18
  return this._currentAtom;
27
19
  }
28
20
  /**
29
- * Gets the currently attended element path.
21
+ * Gets the currently attended element IDs.
30
22
  */
31
23
  getCurrent() {
32
24
  return this._registry.get(this._currentAtom);
33
25
  }
34
26
  /**
35
- * Subscribe to changes in the current attention path.
27
+ * Subscribe to changes in the current attention IDs.
36
28
  */
37
29
  subscribeCurrent(cb) {
38
30
  this._registry.get(this._currentAtom);
@@ -41,30 +33,30 @@ var AttentionManager = class {
41
33
  });
42
34
  }
43
35
  /**
44
- * All attention paths.
36
+ * All tracked qualified IDs.
45
37
  */
46
38
  keys() {
47
39
  return Array.from(this._map.keys());
48
40
  }
49
41
  /**
50
- * Get the attention state for a given path.
42
+ * Get the attention state for a given qualified ID.
51
43
  */
52
- get(key) {
53
- const atom = this._getAtom(key);
44
+ get(id) {
45
+ const atom = this._getAtom(id);
54
46
  return this._registry.get(atom);
55
47
  }
56
48
  /**
57
- * Subscribe to changes in the attention state for a given path.
49
+ * Subscribe to changes in the attention state for a given qualified ID.
58
50
  */
59
- subscribe(key, cb) {
60
- const atom = this._getAtom(key);
51
+ subscribe(id, cb) {
52
+ const atom = this._getAtom(id);
61
53
  this._registry.get(atom);
62
54
  return this._registry.subscribe(atom, () => {
63
55
  cb(this._registry.get(atom));
64
56
  });
65
57
  }
66
- _getAtom(key) {
67
- const existing = this._map.get(key);
58
+ _getAtom(id) {
59
+ const existing = this._map.get(id);
68
60
  if (existing) {
69
61
  return existing;
70
62
  }
@@ -72,43 +64,70 @@ var AttentionManager = class {
72
64
  hasAttention: false,
73
65
  isAncestor: false,
74
66
  isRelated: false
75
- });
76
- this._map.set(key, newAtom);
67
+ }).pipe(Atom.keepAlive);
68
+ this._map.set(id, newAtom);
77
69
  return newAtom;
78
70
  }
79
71
  /**
80
72
  * Update the currently attended element.
73
+ * Takes the array of qualified IDs collected from the DOM; the first element is the primary attended item.
74
+ * Ancestry is derived from the progressive prefixes of the primary ID.
75
+ * Relatedness is derived from the segment ID: any tracked key whose last `/` segment matches the
76
+ * attended ID's segment ID is marked `isRelated`. Additionally, if the primary ID is a linked segment
77
+ * (starts with `~`), its immediate parent gets `isRelated` alongside `isAncestor`.
81
78
  *
82
79
  * @internal
83
80
  */
84
- update(nextKey) {
85
- const currentKey = this.getCurrent();
86
- const currentRelatedTo = currentKey[0];
87
- const nextRelatedTo = nextKey[0];
88
- this._getAtom([
89
- nextRelatedTo
90
- ]);
91
- const currentRelatedKeys = this.keys().filter((key) => key[0] === currentRelatedTo);
92
- const nextRelatedKeys = this.keys().filter((key) => key[0] === nextRelatedTo && stringKey(key) !== stringKey(nextKey));
93
- const prevRelatedKeys = currentRelatedKeys.filter((curr) => !nextRelatedKeys.find((next) => stringKey(curr) === stringKey(next)));
94
- const currentAncestorKeys = currentKey.slice(1).map((_, i) => currentKey.slice(i + 1, currentKey.length));
95
- const nextAncestorKeys = nextKey.slice(1).map((_, i) => nextKey.slice(i + 1, nextKey.length));
96
- const prevAncestorKeys = currentAncestorKeys.filter((curr) => !nextAncestorKeys.find((next) => stringKey(curr) === stringKey(next)));
97
- this._registry.set(this._currentAtom, nextKey);
98
- prevRelatedKeys.forEach((key) => this._set(key, {}));
99
- prevAncestorKeys.forEach((key) => this._set(key, {}));
100
- nextRelatedKeys.forEach((key) => this._set(key, {
101
- isRelated: true
102
- }));
103
- nextAncestorKeys.forEach((key) => this._set(key, {
104
- isAncestor: true
105
- }));
106
- this._set(nextKey, {
107
- hasAttention: true
108
- });
81
+ update(nextIds) {
82
+ const primaryId = nextIds[0];
83
+ if (!primaryId) {
84
+ return;
85
+ }
86
+ const currentIds = this.getCurrent();
87
+ const prevPrimaryId = currentIds[0];
88
+ if (prevPrimaryId) {
89
+ const prevPrefixes = expandAttendableId(prevPrimaryId);
90
+ for (const prefix of prevPrefixes) {
91
+ this._set(prefix, {});
92
+ }
93
+ const prevSegmentId = getSegmentId(prevPrimaryId);
94
+ for (const key of this.keys()) {
95
+ if (getSegmentId(key) === prevSegmentId) {
96
+ this._set(key, {});
97
+ }
98
+ }
99
+ }
100
+ this._registry.set(this._currentAtom, nextIds);
101
+ const prefixes = expandAttendableId(primaryId);
102
+ const prefixSet = new Set(prefixes);
103
+ const linkedParent = isLinkedSegment(primaryId) ? getParentId(primaryId) : void 0;
104
+ for (const prefix of prefixes) {
105
+ if (prefix === primaryId) {
106
+ this._set(prefix, {
107
+ hasAttention: true
108
+ });
109
+ } else if (prefix === linkedParent) {
110
+ this._set(prefix, {
111
+ isAncestor: true,
112
+ isRelated: true
113
+ });
114
+ } else {
115
+ this._set(prefix, {
116
+ isAncestor: true
117
+ });
118
+ }
119
+ }
120
+ const segmentId = getSegmentId(primaryId);
121
+ for (const key of this.keys()) {
122
+ if (!prefixSet.has(key) && getSegmentId(key) === segmentId) {
123
+ this._set(key, {
124
+ isRelated: true
125
+ });
126
+ }
127
+ }
109
128
  }
110
- _set(key, attention) {
111
- const atom = this._getAtom(key);
129
+ _set(id, attention) {
130
+ const atom = this._getAtom(id);
112
131
  this._registry.set(atom, {
113
132
  hasAttention: attention.hasAttention ?? false,
114
133
  isAncestor: attention.isAncestor ?? false,
@@ -128,7 +147,7 @@ var getAttendables = (selector, cursor, acc = []) => {
128
147
  return getAttendables(selector, trigger, acc);
129
148
  }
130
149
  } else {
131
- acc.push(...attendableId.split(ATTENDABLE_PATH_SEPARATOR));
150
+ acc.push(attendableId);
132
151
  return !closestAttendable.parentElement ? acc : getAttendables(selector, closestAttendable.parentElement, acc);
133
152
  }
134
153
  }
@@ -136,23 +155,46 @@ var getAttendables = (selector, cursor, acc = []) => {
136
155
  ...new Set(acc)
137
156
  ];
138
157
  };
158
+ var LINKED_PREFIX = "~";
159
+ var expandAttendableId = (qualifiedId) => {
160
+ const segments = qualifiedId.split("/");
161
+ return segments.map((_, index) => segments.slice(0, index + 1).join("/"));
162
+ };
163
+ var isLinkedSegment = (qualifiedId) => {
164
+ const lastSegment = qualifiedId.split("/").pop() ?? "";
165
+ return lastSegment.startsWith(LINKED_PREFIX);
166
+ };
167
+ var linkedSegment = (variant) => `${LINKED_PREFIX}${variant}`;
168
+ var getLinkedVariant = (qualifiedId) => {
169
+ const lastSegment = qualifiedId.split("/").pop() ?? "";
170
+ return lastSegment.startsWith(LINKED_PREFIX) ? lastSegment.slice(LINKED_PREFIX.length) : lastSegment;
171
+ };
172
+ var getParentId = (qualifiedId) => {
173
+ if (!qualifiedId) {
174
+ return void 0;
175
+ }
176
+ const lastSlash = qualifiedId.lastIndexOf("/");
177
+ return lastSlash > 0 ? qualifiedId.slice(0, lastSlash) : void 0;
178
+ };
179
+ var getSegmentId = (qualifiedId) => {
180
+ return qualifiedId.split("/").pop() ?? qualifiedId;
181
+ };
139
182
 
140
- // src/components/AttentionProvider.tsx
183
+ // src/components/AttentionProvider/AttentionProvider.tsx
141
184
  import { RegistryContext } from "@effect-atom/atom-react";
142
185
  import { createContext } from "@radix-ui/react-context";
143
186
  import { Primitive } from "@radix-ui/react-primitive";
144
187
  import { Slot } from "@radix-ui/react-slot";
145
- import React, { forwardRef, useContext, useEffect, useMemo, useState } from "react";
188
+ import React, { forwardRef, useCallback, useContext, useEffect, useMemo, useState } from "react";
146
189
  import { log } from "@dxos/log";
147
190
  import { useDefaultValue } from "@dxos/react-hooks";
148
191
  import { mx } from "@dxos/ui-theme";
149
- var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-attention/src/components/AttentionProvider.tsx";
192
+ var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-attention/src/components/AttentionProvider/AttentionProvider.tsx";
150
193
  var ATTENTION_NAME = "Attention";
151
194
  var ATTENDABLE_ATTRIBUTE = "data-attendable-id";
152
195
  var ATTENTION_SOURCE_ATTRIBUTE = "data-w-attention-source";
153
196
  var [AttentionContextProvider, useAttentionContext] = createContext(ATTENTION_NAME, {
154
- attention: void 0,
155
- path: []
197
+ attention: void 0
156
198
  });
157
199
  var UNKNOWN_ATTENDABLE = {
158
200
  hasAttention: false,
@@ -160,32 +202,21 @@ var UNKNOWN_ATTENDABLE = {
160
202
  isRelated: false
161
203
  };
162
204
  var useAttention = (attendableId) => {
163
- const { attention, path } = useAttentionContext(ATTENTION_NAME);
205
+ const { attention } = useAttentionContext(ATTENTION_NAME);
164
206
  const [state, setState] = useState(UNKNOWN_ATTENDABLE);
165
- const key = useMemo(() => {
166
- if (!attendableId) {
167
- return void 0;
168
- }
169
- return [
170
- ...attendableId.split(ATTENDABLE_PATH_SEPARATOR),
171
- ...path
172
- ];
173
- }, [
174
- attendableId,
175
- path
176
- ]);
177
207
  useEffect(() => {
178
- if (!key || !attention) {
208
+ if (!attendableId || !attention) {
179
209
  setState(UNKNOWN_ATTENDABLE);
180
210
  return;
181
211
  }
182
- setState(attention.get(key));
183
- return attention.subscribe(key, (newState) => {
212
+ const currentState = attention.get(attendableId);
213
+ setState(currentState);
214
+ return attention.subscribe(attendableId, (newState) => {
184
215
  setState(newState);
185
216
  });
186
217
  }, [
187
218
  attention,
188
- key
219
+ attendableId
189
220
  ]);
190
221
  return state;
191
222
  };
@@ -220,23 +251,14 @@ var useAttentionAttributes = (attendableId) => {
220
251
  hasAttention
221
252
  ]);
222
253
  };
223
- var useAttentionPath = () => {
224
- const { path } = useAttentionContext(ATTENTION_NAME);
225
- return path;
226
- };
227
254
  var RootAttentionProvider = ({ children, attention: propsAttention, onChange }) => {
228
255
  const registry = useContext(RegistryContext);
229
256
  const attention = useDefaultValue(propsAttention, () => new AttentionManager(registry));
230
- const handleFocus = (event) => {
257
+ const handleFocus = useCallback((event) => {
231
258
  log("focus", {
232
259
  related: event.relatedTarget,
233
260
  target: event.target
234
- }, {
235
- F: __dxlog_file,
236
- L: 130,
237
- S: void 0,
238
- C: (f, a) => f(...a)
239
- });
261
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 84, S: void 0 });
240
262
  const selector = [
241
263
  "[data-attendable-id]",
242
264
  ...Array.from(document.querySelectorAll("[aria-controls]")).map((el) => `[id="${el.getAttribute("aria-controls")}"]`)
@@ -247,37 +269,25 @@ var RootAttentionProvider = ({ children, attention: propsAttention, onChange })
247
269
  attention.update(next);
248
270
  onChange?.(next);
249
271
  }
250
- };
251
- return /* @__PURE__ */ React.createElement(AttentionContextProvider, {
272
+ }, [
252
273
  attention,
253
- path: []
274
+ onChange
275
+ ]);
276
+ return /* @__PURE__ */ React.createElement(AttentionContextProvider, {
277
+ attention
254
278
  }, /* @__PURE__ */ React.createElement("div", {
255
279
  role: "none",
256
280
  className: "contents",
257
281
  onFocusCapture: handleFocus
258
282
  }, children));
259
283
  };
260
- var AttentionProvider = ({ id, children }) => {
261
- const { attention, path } = useAttentionContext(ATTENTION_NAME);
262
- const nextPath = useMemo(() => [
263
- id,
264
- ...path
265
- ], [
266
- id,
267
- path
268
- ]);
269
- return /* @__PURE__ */ React.createElement(AttentionContextProvider, {
270
- attention,
271
- path: nextPath
272
- }, children);
273
- };
274
284
  var AttendableContainer = /* @__PURE__ */ forwardRef(({ id, classNames, children, asChild, ...props }, forwardedRef) => {
275
285
  const attentionAttrs = useAttentionAttributes(id);
276
286
  const Comp = asChild ? Slot : Primitive.div;
277
287
  return /* @__PURE__ */ React.createElement(Comp, {
278
288
  role: "none",
279
- ...attentionAttrs,
280
289
  ...props,
290
+ ...attentionAttrs,
281
291
  className: mx("dx-attention-surface", props.tabIndex === 0 && "dx-focus-ring-inset-over-all", classNames),
282
292
  ref: forwardedRef
283
293
  }, children);
@@ -381,18 +391,9 @@ var SelectionManager = class {
381
391
  }));
382
392
  return newSelection;
383
393
  }
384
- // TODO(burdon): Disambiguate with getSelection?
385
394
  getSelected(contextId, mode = "multi") {
386
395
  const selection = this.getSelection(contextId, mode);
387
- invariant(selection?.mode === mode, "Selection mode mismatch", {
388
- F: __dxlog_file2,
389
- L: 134,
390
- S: this,
391
- A: [
392
- "selection?.mode === mode",
393
- "'Selection mode mismatch'"
394
- ]
395
- });
396
+ invariant(selection?.mode === mode, "Selection mode mismatch", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 103, S: this, A: ["selection?.mode === mode", "'Selection mode mismatch'"] });
396
397
  return Match.type().pipe(Match.when({
397
398
  mode: "single"
398
399
  }, (s) => s.id), Match.when({
@@ -408,15 +409,7 @@ var SelectionManager = class {
408
409
  }
409
410
  updateSingle(contextId, id) {
410
411
  const selection = this.getSelection(contextId, "single");
411
- invariant(selection?.mode === "single", "Selection mode is not single", {
412
- F: __dxlog_file2,
413
- L: 147,
414
- S: this,
415
- A: [
416
- "selection?.mode === 'single'",
417
- "'Selection mode is not single'"
418
- ]
419
- });
412
+ invariant(selection?.mode === "single", "Selection mode is not single", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 120, S: this, A: ["selection?.mode === 'single'", "'Selection mode is not single'"] });
420
413
  this._registry.update(this._state, (state) => ({
421
414
  selections: {
422
415
  ...state.selections,
@@ -429,15 +422,7 @@ var SelectionManager = class {
429
422
  }
430
423
  updateMulti(contextId, ids) {
431
424
  const selection = this.getSelection(contextId, "multi");
432
- invariant(selection?.mode === "multi", "Selection mode is not multi", {
433
- F: __dxlog_file2,
434
- L: 158,
435
- S: this,
436
- A: [
437
- "selection?.mode === 'multi'",
438
- "'Selection mode is not multi'"
439
- ]
440
- });
425
+ invariant(selection?.mode === "multi", "Selection mode is not multi", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 133, S: this, A: ["selection?.mode === 'multi'", "'Selection mode is not multi'"] });
441
426
  this._registry.update(this._state, (state) => ({
442
427
  selections: {
443
428
  ...state.selections,
@@ -452,15 +437,7 @@ var SelectionManager = class {
452
437
  }
453
438
  updateRange(contextId, from, to) {
454
439
  const selection = this.getSelection(contextId, "range");
455
- invariant(selection?.mode === "range", "Selection mode is not range", {
456
- F: __dxlog_file2,
457
- L: 169,
458
- S: this,
459
- A: [
460
- "selection?.mode === 'range'",
461
- "'Selection mode is not range'"
462
- ]
463
- });
440
+ invariant(selection?.mode === "range", "Selection mode is not range", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 148, S: this, A: ["selection?.mode === 'range'", "'Selection mode is not range'"] });
464
441
  this._registry.update(this._state, (state) => ({
465
442
  selections: {
466
443
  ...state.selections,
@@ -474,15 +451,7 @@ var SelectionManager = class {
474
451
  }
475
452
  updateMultiRange(contextId, ranges) {
476
453
  const selection = this.getSelection(contextId, "multi-range");
477
- invariant(selection?.mode === "multi-range", "Selection mode is not multi-range", {
478
- F: __dxlog_file2,
479
- L: 180,
480
- S: this,
481
- A: [
482
- "selection?.mode === 'multi-range'",
483
- "'Selection mode is not multi-range'"
484
- ]
485
- });
454
+ invariant(selection?.mode === "multi-range", "Selection mode is not multi-range", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 162, S: this, A: ["selection?.mode === 'multi-range'", "'Selection mode is not multi-range'"] });
486
455
  this._registry.update(this._state, (state) => ({
487
456
  selections: {
488
457
  ...state.selections,
@@ -531,15 +500,7 @@ var SelectionManager = class {
531
500
  }
532
501
  toggleSelection(contextId, id) {
533
502
  const selection = this.getSelection(contextId, "multi");
534
- invariant(selection?.mode === "multi", "Selection mode is not multi", {
535
- F: __dxlog_file2,
536
- L: 213,
537
- S: this,
538
- A: [
539
- "selection?.mode === 'multi'",
540
- "'Selection mode is not multi'"
541
- ]
542
- });
503
+ invariant(selection?.mode === "multi", "Selection mode is not multi", { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 211, S: this, A: ["selection?.mode === 'multi'", "'Selection mode is not multi'"] });
543
504
  const newIds = selection.ids.includes(id) ? selection.ids.filter((existingId) => existingId !== id) : [
544
505
  ...selection.ids,
545
506
  id
@@ -556,19 +517,19 @@ var SelectionManager = class {
556
517
  }
557
518
  };
558
519
 
559
- // src/components/SelectionProvider.tsx
520
+ // src/components/SelectionProvider/SelectionProvider.tsx
560
521
  import { RegistryContext as RegistryContext2 } from "@effect-atom/atom-react";
561
522
  import { createContext as createContext2 } from "@radix-ui/react-context";
562
523
  import * as Match2 from "effect/Match";
563
- import React2, { useCallback, useContext as useContext2, useEffect as useEffect2, useMemo as useMemo2, useState as useState2 } from "react";
524
+ import React2, { useCallback as useCallback2, useContext as useContext2, useEffect as useEffect2, useMemo as useMemo2, useState as useState2 } from "react";
564
525
  import { useDefaultValue as useDefaultValue2 } from "@dxos/react-hooks";
565
526
  var SELECTION_NAME = "Selection";
566
527
  var [SelectionContextProvider, useSelectionContext] = createContext2(SELECTION_NAME, {
567
528
  selection: void 0
568
529
  });
569
- var SelectionProvider = ({ children, selection: propsSelection }) => {
530
+ var SelectionProvider = ({ children, selection: selectionProp }) => {
570
531
  const registry = useContext2(RegistryContext2);
571
- const selection = useDefaultValue2(propsSelection, () => new SelectionManager(registry));
532
+ const selection = useDefaultValue2(selectionProp, () => new SelectionManager(registry));
572
533
  return /* @__PURE__ */ React2.createElement(SelectionContextProvider, {
573
534
  selection
574
535
  }, children);
@@ -610,12 +571,12 @@ var useSelected = (contextId, mode = "multi") => {
610
571
  ]);
611
572
  return state;
612
573
  };
613
- var useSelectionActions = (contextIds, mode = "multi") => {
574
+ var useSelectionActions = (contextIds) => {
614
575
  const stableContextIds = useMemo2(() => contextIds, [
615
576
  JSON.stringify(contextIds)
616
577
  ]);
617
578
  const { selection } = useSelectionContext(SELECTION_NAME);
618
- const singleSelect = useCallback((id) => {
579
+ const singleSelect = useCallback2((id) => {
619
580
  if (!selection) {
620
581
  return;
621
582
  }
@@ -626,7 +587,7 @@ var useSelectionActions = (contextIds, mode = "multi") => {
626
587
  selection,
627
588
  stableContextIds
628
589
  ]);
629
- const multiSelect = useCallback((ids) => {
590
+ const multiSelect = useCallback2((ids) => {
630
591
  if (!selection) {
631
592
  return;
632
593
  }
@@ -637,7 +598,7 @@ var useSelectionActions = (contextIds, mode = "multi") => {
637
598
  selection,
638
599
  stableContextIds
639
600
  ]);
640
- const rangeSelect = useCallback((from, to) => {
601
+ const rangeSelect = useCallback2((from, to) => {
641
602
  if (!selection) {
642
603
  return;
643
604
  }
@@ -648,7 +609,7 @@ var useSelectionActions = (contextIds, mode = "multi") => {
648
609
  selection,
649
610
  stableContextIds
650
611
  ]);
651
- const toggle = useCallback((id) => {
612
+ const toggle = useCallback2((id) => {
652
613
  if (!selection) {
653
614
  return;
654
615
  }
@@ -659,7 +620,7 @@ var useSelectionActions = (contextIds, mode = "multi") => {
659
620
  selection,
660
621
  stableContextIds
661
622
  ]);
662
- const clear = useCallback(() => {
623
+ const clear = useCallback2(() => {
663
624
  if (!selection) {
664
625
  return;
665
626
  }
@@ -682,16 +643,17 @@ var useSelectionActions = (contextIds, mode = "multi") => {
682
643
  export {
683
644
  AttentionManager,
684
645
  getAttendables,
685
- ATTENTION_NAME,
686
- ATTENDABLE_ATTRIBUTE,
687
- ATTENTION_SOURCE_ATTRIBUTE,
646
+ expandAttendableId,
647
+ isLinkedSegment,
648
+ linkedSegment,
649
+ getLinkedVariant,
650
+ getParentId,
651
+ getSegmentId,
688
652
  useAttentionContext,
689
653
  useAttention,
690
654
  useAttended,
691
655
  useAttentionAttributes,
692
- useAttentionPath,
693
656
  RootAttentionProvider,
694
- AttentionProvider,
695
657
  AttendableContainer,
696
658
  SelectionSchema,
697
659
  defaultSelection,
@@ -702,4 +664,4 @@ export {
702
664
  useSelected,
703
665
  useSelectionActions
704
666
  };
705
- //# sourceMappingURL=chunk-TAZUDNJI.mjs.map
667
+ //# sourceMappingURL=chunk-XVH365AW.mjs.map