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