@dxos/react-ui-attention 0.7.5-labs.e27f9b9 → 0.7.5-labs.ea4b4c2

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 (29) hide show
  1. package/dist/lib/browser/{chunk-2TNGSB43.mjs → chunk-KXRLXG2Q.mjs} +108 -2
  2. package/dist/lib/browser/{chunk-2TNGSB43.mjs.map → chunk-KXRLXG2Q.mjs.map} +4 -4
  3. package/dist/lib/browser/index.mjs +11 -3
  4. package/dist/lib/browser/meta.json +1 -1
  5. package/dist/lib/browser/testing/index.mjs +1 -1
  6. package/dist/lib/node/{chunk-BID3HPBP.cjs → chunk-RYXAUIEJ.cjs} +112 -6
  7. package/dist/lib/node/{chunk-BID3HPBP.cjs.map → chunk-RYXAUIEJ.cjs.map} +4 -4
  8. package/dist/lib/node/index.cjs +26 -18
  9. package/dist/lib/node/index.cjs.map +2 -2
  10. package/dist/lib/node/meta.json +1 -1
  11. package/dist/lib/node/testing/index.cjs +2 -2
  12. package/dist/lib/node-esm/{chunk-ARQ2A5DK.mjs → chunk-RUECHK2Y.mjs} +108 -2
  13. package/dist/lib/node-esm/{chunk-ARQ2A5DK.mjs.map → chunk-RUECHK2Y.mjs.map} +4 -4
  14. package/dist/lib/node-esm/index.mjs +11 -3
  15. package/dist/lib/node-esm/meta.json +1 -1
  16. package/dist/lib/node-esm/testing/index.mjs +1 -1
  17. package/dist/types/src/components/SelectionProvider.d.ts +13 -0
  18. package/dist/types/src/components/SelectionProvider.d.ts.map +1 -0
  19. package/dist/types/src/components/index.d.ts +1 -0
  20. package/dist/types/src/components/index.d.ts.map +1 -1
  21. package/dist/types/src/index.d.ts +1 -0
  22. package/dist/types/src/index.d.ts.map +1 -1
  23. package/dist/types/src/selection.d.ts +15 -0
  24. package/dist/types/src/selection.d.ts.map +1 -0
  25. package/package.json +11 -11
  26. package/src/components/SelectionProvider.tsx +67 -0
  27. package/src/components/index.ts +1 -0
  28. package/src/index.ts +1 -0
  29. package/src/selection.ts +59 -0
@@ -1 +1 @@
1
- {"inputs":{"packages/ui/react-ui-attention/src/attention.ts":{"bytes":16177,"imports":[{"path":"@preact/signals-core","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/live-object","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/ui/react-ui-attention/src/components/AttentionGlyph.tsx":{"bytes":10623,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true}],"format":"esm"},"packages/ui/react-ui-attention/src/components/AttentionProvider.tsx":{"bytes":20134,"imports":[{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"@radix-ui/react-primitive","kind":"import-statement","external":true},{"path":"@radix-ui/react-slot","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-attention/src/attention.ts","kind":"import-statement","original":"../attention"}],"format":"esm"},"packages/ui/react-ui-attention/src/components/index.ts":{"bytes":644,"imports":[{"path":"packages/ui/react-ui-attention/src/components/AttentionGlyph.tsx","kind":"import-statement","original":"./AttentionGlyph"},{"path":"packages/ui/react-ui-attention/src/components/AttentionProvider.tsx","kind":"import-statement","original":"./AttentionProvider"}],"format":"esm"},"packages/ui/react-ui-attention/src/index.ts":{"bytes":597,"imports":[{"path":"packages/ui/react-ui-attention/src/attention.ts","kind":"import-statement","original":"./attention"},{"path":"packages/ui/react-ui-attention/src/components/index.ts","kind":"import-statement","original":"./components"}],"format":"esm"},"packages/ui/react-ui-attention/src/testing/decorators/withAttention.ts":{"bytes":1386,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-attention/src/components/index.ts","kind":"import-statement","original":"../../components"}],"format":"esm"},"packages/ui/react-ui-attention/src/testing/decorators/index.ts":{"bytes":534,"imports":[{"path":"packages/ui/react-ui-attention/src/testing/decorators/withAttention.ts","kind":"import-statement","original":"./withAttention"}],"format":"esm"},"packages/ui/react-ui-attention/src/testing/index.ts":{"bytes":516,"imports":[{"path":"packages/ui/react-ui-attention/src/testing/decorators/index.ts","kind":"import-statement","original":"./decorators"}],"format":"esm"}},"outputs":{"packages/ui/react-ui-attention/dist/lib/node-esm/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":93},"packages/ui/react-ui-attention/dist/lib/node-esm/index.mjs":{"imports":[{"path":"packages/ui/react-ui-attention/dist/lib/node-esm/chunk-ARQ2A5DK.mjs","kind":"import-statement"}],"exports":["ATTENABLE_ATTRIBUTE","ATTENTION_NAME","ATTENTION_SOURCE_ATTRIBUTE","AttendableContainer","AttentionGlyph","AttentionManager","AttentionProvider","AttentionSchema","RootAttentionProvider","Syncing","getAttendables","useAttendableAttributes","useAttended","useAttention","useAttentionContext","useAttentionPath"],"entryPoint":"packages/ui/react-ui-attention/src/index.ts","inputs":{"packages/ui/react-ui-attention/src/index.ts":{"bytesInOutput":0}},"bytes":831},"packages/ui/react-ui-attention/dist/lib/node-esm/testing/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":698},"packages/ui/react-ui-attention/dist/lib/node-esm/testing/index.mjs":{"imports":[{"path":"packages/ui/react-ui-attention/dist/lib/node-esm/chunk-ARQ2A5DK.mjs","kind":"import-statement"},{"path":"react","kind":"import-statement","external":true}],"exports":["withAttention"],"entryPoint":"packages/ui/react-ui-attention/src/testing/index.ts","inputs":{"packages/ui/react-ui-attention/src/testing/decorators/withAttention.ts":{"bytesInOutput":164},"packages/ui/react-ui-attention/src/testing/decorators/index.ts":{"bytesInOutput":0},"packages/ui/react-ui-attention/src/testing/index.ts":{"bytesInOutput":0}},"bytes":459},"packages/ui/react-ui-attention/dist/lib/node-esm/chunk-ARQ2A5DK.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":23358},"packages/ui/react-ui-attention/dist/lib/node-esm/chunk-ARQ2A5DK.mjs":{"imports":[{"path":"@preact/signals-core","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/live-object","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"@radix-ui/react-primitive","kind":"import-statement","external":true},{"path":"@radix-ui/react-slot","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true}],"exports":["ATTENABLE_ATTRIBUTE","ATTENTION_NAME","ATTENTION_SOURCE_ATTRIBUTE","AttendableContainer","AttentionGlyph","AttentionManager","AttentionProvider","AttentionSchema","RootAttentionProvider","Syncing","getAttendables","useAttendableAttributes","useAttended","useAttention","useAttentionContext","useAttentionPath"],"inputs":{"packages/ui/react-ui-attention/src/attention.ts":{"bytesInOutput":3558},"packages/ui/react-ui-attention/src/components/AttentionGlyph.tsx":{"bytesInOutput":3212},"packages/ui/react-ui-attention/src/components/AttentionProvider.tsx":{"bytesInOutput":3282},"packages/ui/react-ui-attention/src/components/index.ts":{"bytesInOutput":0}},"bytes":10720}}}
1
+ {"inputs":{"packages/ui/react-ui-attention/src/attention.ts":{"bytes":16177,"imports":[{"path":"@preact/signals-core","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/live-object","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"format":"esm"},"packages/ui/react-ui-attention/src/components/AttentionGlyph.tsx":{"bytes":10623,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true}],"format":"esm"},"packages/ui/react-ui-attention/src/components/AttentionProvider.tsx":{"bytes":20134,"imports":[{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"@radix-ui/react-primitive","kind":"import-statement","external":true},{"path":"@radix-ui/react-slot","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-attention/src/attention.ts","kind":"import-statement","original":"../attention"}],"format":"esm"},"packages/ui/react-ui-attention/src/selection.ts":{"bytes":5559,"imports":[{"path":"@preact/signals-core","kind":"import-statement","external":true},{"path":"@dxos/live-object","kind":"import-statement","external":true}],"format":"esm"},"packages/ui/react-ui-attention/src/components/SelectionProvider.tsx":{"bytes":6312,"imports":[{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-attention/src/selection.ts","kind":"import-statement","original":"../selection"}],"format":"esm"},"packages/ui/react-ui-attention/src/components/index.ts":{"bytes":757,"imports":[{"path":"packages/ui/react-ui-attention/src/components/AttentionGlyph.tsx","kind":"import-statement","original":"./AttentionGlyph"},{"path":"packages/ui/react-ui-attention/src/components/AttentionProvider.tsx","kind":"import-statement","original":"./AttentionProvider"},{"path":"packages/ui/react-ui-attention/src/components/SelectionProvider.tsx","kind":"import-statement","original":"./SelectionProvider"}],"format":"esm"},"packages/ui/react-ui-attention/src/index.ts":{"bytes":690,"imports":[{"path":"packages/ui/react-ui-attention/src/attention.ts","kind":"import-statement","original":"./attention"},{"path":"packages/ui/react-ui-attention/src/components/index.ts","kind":"import-statement","original":"./components"},{"path":"packages/ui/react-ui-attention/src/selection.ts","kind":"import-statement","original":"./selection"}],"format":"esm"},"packages/ui/react-ui-attention/src/testing/decorators/withAttention.ts":{"bytes":1386,"imports":[{"path":"react","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-attention/src/components/index.ts","kind":"import-statement","original":"../../components"}],"format":"esm"},"packages/ui/react-ui-attention/src/testing/decorators/index.ts":{"bytes":534,"imports":[{"path":"packages/ui/react-ui-attention/src/testing/decorators/withAttention.ts","kind":"import-statement","original":"./withAttention"}],"format":"esm"},"packages/ui/react-ui-attention/src/testing/index.ts":{"bytes":516,"imports":[{"path":"packages/ui/react-ui-attention/src/testing/decorators/index.ts","kind":"import-statement","original":"./decorators"}],"format":"esm"}},"outputs":{"packages/ui/react-ui-attention/dist/lib/node-esm/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":93},"packages/ui/react-ui-attention/dist/lib/node-esm/index.mjs":{"imports":[{"path":"packages/ui/react-ui-attention/dist/lib/node-esm/chunk-RUECHK2Y.mjs","kind":"import-statement"}],"exports":["ATTENABLE_ATTRIBUTE","ATTENTION_NAME","ATTENTION_SOURCE_ATTRIBUTE","AttendableContainer","AttentionGlyph","AttentionManager","AttentionProvider","AttentionSchema","RootAttentionProvider","SelectionManager","SelectionProvider","Syncing","getAttendables","useAttendableAttributes","useAttended","useAttention","useAttentionContext","useAttentionPath","useSelectedItems","useSelectionActions"],"entryPoint":"packages/ui/react-ui-attention/src/index.ts","inputs":{"packages/ui/react-ui-attention/src/index.ts":{"bytesInOutput":0}},"bytes":999},"packages/ui/react-ui-attention/dist/lib/node-esm/testing/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":698},"packages/ui/react-ui-attention/dist/lib/node-esm/testing/index.mjs":{"imports":[{"path":"packages/ui/react-ui-attention/dist/lib/node-esm/chunk-RUECHK2Y.mjs","kind":"import-statement"},{"path":"react","kind":"import-statement","external":true}],"exports":["withAttention"],"entryPoint":"packages/ui/react-ui-attention/src/testing/index.ts","inputs":{"packages/ui/react-ui-attention/src/testing/decorators/withAttention.ts":{"bytesInOutput":164},"packages/ui/react-ui-attention/src/testing/decorators/index.ts":{"bytesInOutput":0},"packages/ui/react-ui-attention/src/testing/index.ts":{"bytesInOutput":0}},"bytes":459},"packages/ui/react-ui-attention/dist/lib/node-esm/chunk-RUECHK2Y.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":29499},"packages/ui/react-ui-attention/dist/lib/node-esm/chunk-RUECHK2Y.mjs":{"imports":[{"path":"@preact/signals-core","kind":"import-statement","external":true},{"path":"@dxos/echo-schema","kind":"import-statement","external":true},{"path":"@dxos/live-object","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"@radix-ui/react-primitive","kind":"import-statement","external":true},{"path":"@radix-ui/react-slot","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"@preact/signals-core","kind":"import-statement","external":true},{"path":"@dxos/live-object","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true}],"exports":["ATTENABLE_ATTRIBUTE","ATTENTION_NAME","ATTENTION_SOURCE_ATTRIBUTE","AttendableContainer","AttentionGlyph","AttentionManager","AttentionProvider","AttentionSchema","RootAttentionProvider","SelectionManager","SelectionProvider","Syncing","getAttendables","useAttendableAttributes","useAttended","useAttention","useAttentionContext","useAttentionPath","useSelectedItems","useSelectionActions"],"inputs":{"packages/ui/react-ui-attention/src/attention.ts":{"bytesInOutput":3558},"packages/ui/react-ui-attention/src/components/AttentionGlyph.tsx":{"bytesInOutput":3212},"packages/ui/react-ui-attention/src/components/AttentionProvider.tsx":{"bytesInOutput":3282},"packages/ui/react-ui-attention/src/selection.ts":{"bytesInOutput":1199},"packages/ui/react-ui-attention/src/components/SelectionProvider.tsx":{"bytesInOutput":1491},"packages/ui/react-ui-attention/src/components/index.ts":{"bytesInOutput":0}},"bytes":13618}}}
@@ -1,7 +1,7 @@
1
1
  import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
2
  import {
3
3
  RootAttentionProvider
4
- } from "../chunk-ARQ2A5DK.mjs";
4
+ } from "../chunk-RUECHK2Y.mjs";
5
5
 
6
6
  // packages/ui/react-ui-attention/src/testing/decorators/withAttention.ts
7
7
  import { createElement } from "react";
@@ -0,0 +1,13 @@
1
+ import { type PropsWithChildren } from 'react';
2
+ import React from 'react';
3
+ import { SelectionManager } from '../selection';
4
+ export declare const SelectionProvider: ({ children, selection: propsSelection, }: PropsWithChildren<{
5
+ selection?: SelectionManager;
6
+ }>) => React.JSX.Element;
7
+ export declare const useSelectedItems: (contextId: string) => Set<string>;
8
+ export declare const useSelectionActions: (contextId?: string) => {
9
+ select: (ids: string[]) => Set<unknown> | undefined;
10
+ toggle: (id: string) => Set<unknown> | undefined;
11
+ clear: () => void;
12
+ };
13
+ //# sourceMappingURL=SelectionProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SelectionProvider.d.ts","sourceRoot":"","sources":["../../../../src/components/SelectionProvider.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAC5D,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAYhD,eAAO,MAAM,iBAAiB,6CAG3B,iBAAiB,CAAC;IAAE,SAAS,CAAC,EAAE,gBAAgB,CAAA;CAAE,CAAC,sBAGrD,CAAC;AAEF,eAAO,MAAM,gBAAgB,cAAe,MAAM,KAAG,GAAG,CAAC,MAAM,CAG9D,CAAC;AAEF,eAAO,MAAM,mBAAmB,eAAgB,MAAM;kBAI5C,MAAM,EAAE;iBAUT,MAAM;;CAiBd,CAAC"}
@@ -1,3 +1,4 @@
1
1
  export * from './AttentionGlyph';
2
2
  export * from './AttentionProvider';
3
+ export * from './SelectionProvider';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/index.ts"],"names":[],"mappings":"AAIA,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/index.ts"],"names":[],"mappings":"AAIA,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC"}
@@ -1,3 +1,4 @@
1
1
  export * from './attention';
2
2
  export * from './components';
3
+ export * from './selection';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { type ReactiveObject } from '@dxos/live-object';
2
+ /**
3
+ * Manages selection state for different contexts.
4
+ * Each context maintains its own list of selected IDs.
5
+ */
6
+ export declare class SelectionManager {
7
+ private readonly _state;
8
+ constructor(initial?: Record<string, Set<string>>);
9
+ get selections(): ReactiveObject<Record<string, Set<string>>>;
10
+ getSelection(contextId: string): Set<string>;
11
+ updateSelection(contextId: string, selectedIds: Set<string> | string[]): void;
12
+ clearSelection(contextId: string): void;
13
+ toggleSelection(contextId: string, id: string): void;
14
+ }
15
+ //# sourceMappingURL=selection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../../src/selection.ts"],"names":[],"mappings":"AAMA,OAAO,EAAU,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEhE;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2E;gBAEtF,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAM;IAQrD,IAAI,UAAU,IAAI,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAE5D;IAED,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;IAS5C,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE;IAMtE,cAAc,CAAC,SAAS,EAAE,MAAM;IAMhC,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;CAU9C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-attention",
3
- "version": "0.7.5-labs.e27f9b9",
3
+ "version": "0.7.5-labs.ea4b4c2",
4
4
  "description": "Signifier components and providers for attention system.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -40,9 +40,9 @@
40
40
  "@radix-ui/react-primitive": "2.0.2",
41
41
  "@radix-ui/react-slot": "1.1.2",
42
42
  "@radix-ui/react-use-controllable-state": "1.1.0",
43
- "@dxos/echo-schema": "0.7.5-labs.e27f9b9",
44
- "@dxos/live-object": "0.7.5-labs.e27f9b9",
45
- "@dxos/util": "0.7.5-labs.e27f9b9"
43
+ "@dxos/live-object": "0.7.5-labs.ea4b4c2",
44
+ "@dxos/echo-schema": "0.7.5-labs.ea4b4c2",
45
+ "@dxos/util": "0.7.5-labs.ea4b4c2"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@phosphor-icons/react": "^2.1.5",
@@ -51,18 +51,18 @@
51
51
  "react": "~18.2.0",
52
52
  "react-dom": "~18.2.0",
53
53
  "vite": "5.4.7",
54
- "@dxos/app-graph": "0.7.5-labs.e27f9b9",
55
- "@dxos/random": "0.7.5-labs.e27f9b9",
56
- "@dxos/react-ui": "0.7.5-labs.e27f9b9",
57
- "@dxos/react-ui-theme": "0.7.5-labs.e27f9b9",
58
- "@dxos/storybook-utils": "0.7.5-labs.e27f9b9"
54
+ "@dxos/app-graph": "0.7.5-labs.ea4b4c2",
55
+ "@dxos/random": "0.7.5-labs.ea4b4c2",
56
+ "@dxos/react-ui": "0.7.5-labs.ea4b4c2",
57
+ "@dxos/react-ui-theme": "0.7.5-labs.ea4b4c2",
58
+ "@dxos/storybook-utils": "0.7.5-labs.ea4b4c2"
59
59
  },
60
60
  "peerDependencies": {
61
61
  "@phosphor-icons/react": "^2.1.5",
62
62
  "react": "~18.2.0",
63
63
  "react-dom": "~18.2.0",
64
- "@dxos/react-ui": "0.7.5-labs.e27f9b9",
65
- "@dxos/react-ui-theme": "0.7.5-labs.e27f9b9"
64
+ "@dxos/react-ui": "0.7.5-labs.ea4b4c2",
65
+ "@dxos/react-ui-theme": "0.7.5-labs.ea4b4c2"
66
66
  },
67
67
  "publishConfig": {
68
68
  "access": "public"
@@ -0,0 +1,67 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { createContext } from '@radix-ui/react-context';
6
+ import { useCallback, type PropsWithChildren } from 'react';
7
+ import React from 'react';
8
+
9
+ import { useDefaultValue } from '@dxos/react-ui';
10
+
11
+ import { SelectionManager } from '../selection';
12
+
13
+ const SELECTION_NAME = 'Selection';
14
+
15
+ type SelectionContextValue = {
16
+ selection: SelectionManager;
17
+ };
18
+
19
+ const [SelectionContextProvider, useSelectionContext] = createContext<SelectionContextValue>(SELECTION_NAME, {
20
+ selection: new SelectionManager(),
21
+ });
22
+
23
+ export const SelectionProvider = ({
24
+ children,
25
+ selection: propsSelection,
26
+ }: PropsWithChildren<{ selection?: SelectionManager }>) => {
27
+ const selection = useDefaultValue(propsSelection, () => new SelectionManager());
28
+ return <SelectionContextProvider selection={selection}>{children}</SelectionContextProvider>;
29
+ };
30
+
31
+ export const useSelectedItems = (contextId: string): Set<string> => {
32
+ const { selection } = useSelectionContext(SELECTION_NAME);
33
+ return selection.getSelection(contextId);
34
+ };
35
+
36
+ export const useSelectionActions = (contextId?: string) => {
37
+ const { selection } = useSelectionContext(SELECTION_NAME);
38
+
39
+ const select = useCallback(
40
+ (ids: string[]) => {
41
+ if (!contextId) {
42
+ return new Set();
43
+ }
44
+ selection.updateSelection(contextId, ids);
45
+ },
46
+ [selection, contextId],
47
+ );
48
+
49
+ const toggle = useCallback(
50
+ (id: string) => {
51
+ if (!contextId) {
52
+ return new Set();
53
+ }
54
+ selection.toggleSelection(contextId, id);
55
+ },
56
+ [selection, contextId],
57
+ );
58
+
59
+ const clear = useCallback(() => {
60
+ if (!contextId) {
61
+ return;
62
+ }
63
+ selection.clearSelection(contextId);
64
+ }, [selection, contextId]);
65
+
66
+ return { select, toggle, clear };
67
+ };
@@ -4,3 +4,4 @@
4
4
 
5
5
  export * from './AttentionGlyph';
6
6
  export * from './AttentionProvider';
7
+ export * from './SelectionProvider';
package/src/index.ts CHANGED
@@ -4,3 +4,4 @@
4
4
 
5
5
  export * from './attention';
6
6
  export * from './components';
7
+ export * from './selection';
@@ -0,0 +1,59 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { untracked } from '@preact/signals-core';
6
+
7
+ import { create, type ReactiveObject } from '@dxos/live-object';
8
+
9
+ /**
10
+ * Manages selection state for different contexts.
11
+ * Each context maintains its own list of selected IDs.
12
+ */
13
+ export class SelectionManager {
14
+ private readonly _state = create<{ selections: Record<string, Set<string>> }>({ selections: {} });
15
+
16
+ constructor(initial: Record<string, Set<string>> = {}) {
17
+ if (Object.keys(initial).length > 0) {
18
+ untracked(() => {
19
+ this._state.selections = initial;
20
+ });
21
+ }
22
+ }
23
+
24
+ get selections(): ReactiveObject<Record<string, Set<string>>> {
25
+ return this._state.selections;
26
+ }
27
+
28
+ getSelection(contextId: string): Set<string> {
29
+ if (!this.selections[contextId]) {
30
+ untracked(() => {
31
+ this._state.selections[contextId] = new Set();
32
+ });
33
+ }
34
+ return this.selections[contextId];
35
+ }
36
+
37
+ updateSelection(contextId: string, selectedIds: Set<string> | string[]) {
38
+ untracked(() => {
39
+ this._state.selections[contextId] = selectedIds instanceof Set ? selectedIds : new Set(selectedIds);
40
+ });
41
+ }
42
+
43
+ clearSelection(contextId: string) {
44
+ untracked(() => {
45
+ this._state.selections[contextId] = new Set();
46
+ });
47
+ }
48
+
49
+ toggleSelection(contextId: string, id: string) {
50
+ untracked(() => {
51
+ const current = this.getSelection(contextId);
52
+ if (current.has(id)) {
53
+ current.delete(id);
54
+ } else {
55
+ current.add(id);
56
+ }
57
+ });
58
+ }
59
+ }