@itwin/unified-selection 0.2.0 → 0.4.0

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 (94) hide show
  1. package/CHANGELOG.md +169 -0
  2. package/README.md +34 -14
  3. package/lib/cjs/unified-selection/CachingHiliteSetProvider.d.ts +3 -7
  4. package/lib/cjs/unified-selection/CachingHiliteSetProvider.d.ts.map +1 -1
  5. package/lib/cjs/unified-selection/CachingHiliteSetProvider.js +14 -17
  6. package/lib/cjs/unified-selection/CachingHiliteSetProvider.js.map +1 -1
  7. package/lib/cjs/unified-selection/EnableUnifiedSelectionSyncWithIModel.d.ts +91 -0
  8. package/lib/cjs/unified-selection/EnableUnifiedSelectionSyncWithIModel.d.ts.map +1 -0
  9. package/lib/cjs/unified-selection/EnableUnifiedSelectionSyncWithIModel.js +205 -0
  10. package/lib/cjs/unified-selection/EnableUnifiedSelectionSyncWithIModel.js.map +1 -0
  11. package/lib/cjs/unified-selection/HiliteSetProvider.d.ts +2 -4
  12. package/lib/cjs/unified-selection/HiliteSetProvider.d.ts.map +1 -1
  13. package/lib/cjs/unified-selection/HiliteSetProvider.js +174 -131
  14. package/lib/cjs/unified-selection/HiliteSetProvider.js.map +1 -1
  15. package/lib/cjs/unified-selection/Selectable.d.ts +0 -3
  16. package/lib/cjs/unified-selection/Selectable.d.ts.map +1 -1
  17. package/lib/cjs/unified-selection/Selectable.js +2 -2
  18. package/lib/cjs/unified-selection/Selectable.js.map +1 -1
  19. package/lib/cjs/unified-selection/SelectionChangeEvent.d.ts +5 -3
  20. package/lib/cjs/unified-selection/SelectionChangeEvent.d.ts.map +1 -1
  21. package/lib/cjs/unified-selection/SelectionChangeEvent.js.map +1 -1
  22. package/lib/cjs/unified-selection/SelectionScope.d.ts +2 -2
  23. package/lib/cjs/unified-selection/SelectionScope.d.ts.map +1 -1
  24. package/lib/cjs/unified-selection/SelectionScope.js +87 -54
  25. package/lib/cjs/unified-selection/SelectionScope.js.map +1 -1
  26. package/lib/cjs/unified-selection/SelectionStorage.d.ts +20 -28
  27. package/lib/cjs/unified-selection/SelectionStorage.d.ts.map +1 -1
  28. package/lib/cjs/unified-selection/SelectionStorage.js +21 -18
  29. package/lib/cjs/unified-selection/SelectionStorage.js.map +1 -1
  30. package/lib/cjs/unified-selection/Utils.d.ts +7 -0
  31. package/lib/cjs/unified-selection/Utils.d.ts.map +1 -0
  32. package/lib/cjs/unified-selection/{queries/ECSqlCore.js → Utils.js} +2 -1
  33. package/lib/cjs/unified-selection/Utils.js.map +1 -0
  34. package/lib/cjs/unified-selection/types/IModel.d.ts +84 -0
  35. package/lib/cjs/unified-selection/types/IModel.d.ts.map +1 -0
  36. package/lib/cjs/unified-selection/types/IModel.js +24 -0
  37. package/lib/cjs/unified-selection/types/IModel.js.map +1 -0
  38. package/lib/cjs/unified-selection.d.ts +1 -6
  39. package/lib/cjs/unified-selection.d.ts.map +1 -1
  40. package/lib/cjs/unified-selection.js +3 -7
  41. package/lib/cjs/unified-selection.js.map +1 -1
  42. package/lib/esm/unified-selection/CachingHiliteSetProvider.d.ts +3 -7
  43. package/lib/esm/unified-selection/CachingHiliteSetProvider.d.ts.map +1 -1
  44. package/lib/esm/unified-selection/CachingHiliteSetProvider.js +14 -17
  45. package/lib/esm/unified-selection/CachingHiliteSetProvider.js.map +1 -1
  46. package/lib/esm/unified-selection/EnableUnifiedSelectionSyncWithIModel.d.ts +91 -0
  47. package/lib/esm/unified-selection/EnableUnifiedSelectionSyncWithIModel.d.ts.map +1 -0
  48. package/lib/esm/unified-selection/EnableUnifiedSelectionSyncWithIModel.js +200 -0
  49. package/lib/esm/unified-selection/EnableUnifiedSelectionSyncWithIModel.js.map +1 -0
  50. package/lib/esm/unified-selection/HiliteSetProvider.d.ts +2 -4
  51. package/lib/esm/unified-selection/HiliteSetProvider.d.ts.map +1 -1
  52. package/lib/esm/unified-selection/HiliteSetProvider.js +174 -131
  53. package/lib/esm/unified-selection/HiliteSetProvider.js.map +1 -1
  54. package/lib/esm/unified-selection/Selectable.d.ts +0 -3
  55. package/lib/esm/unified-selection/Selectable.d.ts.map +1 -1
  56. package/lib/esm/unified-selection/Selectable.js.map +1 -1
  57. package/lib/esm/unified-selection/SelectionChangeEvent.d.ts +5 -3
  58. package/lib/esm/unified-selection/SelectionChangeEvent.d.ts.map +1 -1
  59. package/lib/esm/unified-selection/SelectionChangeEvent.js.map +1 -1
  60. package/lib/esm/unified-selection/SelectionScope.d.ts +2 -2
  61. package/lib/esm/unified-selection/SelectionScope.d.ts.map +1 -1
  62. package/lib/esm/unified-selection/SelectionScope.js +84 -51
  63. package/lib/esm/unified-selection/SelectionScope.js.map +1 -1
  64. package/lib/esm/unified-selection/SelectionStorage.d.ts +20 -28
  65. package/lib/esm/unified-selection/SelectionStorage.d.ts.map +1 -1
  66. package/lib/esm/unified-selection/SelectionStorage.js +21 -18
  67. package/lib/esm/unified-selection/SelectionStorage.js.map +1 -1
  68. package/lib/esm/unified-selection/Utils.d.ts +7 -0
  69. package/lib/esm/unified-selection/Utils.d.ts.map +1 -0
  70. package/lib/esm/unified-selection/{queries/ECSqlCore.js → Utils.js} +2 -1
  71. package/lib/esm/unified-selection/Utils.js.map +1 -0
  72. package/lib/esm/unified-selection/types/IModel.d.ts +84 -0
  73. package/lib/esm/unified-selection/types/IModel.d.ts.map +1 -0
  74. package/lib/esm/unified-selection/types/IModel.js +21 -0
  75. package/lib/esm/unified-selection/types/IModel.js.map +1 -0
  76. package/lib/esm/unified-selection.d.ts +1 -6
  77. package/lib/esm/unified-selection.d.ts.map +1 -1
  78. package/lib/esm/unified-selection.js +1 -6
  79. package/lib/esm/unified-selection.js.map +1 -1
  80. package/package.json +23 -16
  81. package/lib/cjs/unified-selection/queries/ECMetadata.d.ts +0 -44
  82. package/lib/cjs/unified-selection/queries/ECMetadata.d.ts.map +0 -1
  83. package/lib/cjs/unified-selection/queries/ECMetadata.js +0 -17
  84. package/lib/cjs/unified-selection/queries/ECMetadata.js.map +0 -1
  85. package/lib/cjs/unified-selection/queries/ECSqlCore.d.ts +0 -69
  86. package/lib/cjs/unified-selection/queries/ECSqlCore.d.ts.map +0 -1
  87. package/lib/cjs/unified-selection/queries/ECSqlCore.js.map +0 -1
  88. package/lib/esm/unified-selection/queries/ECMetadata.d.ts +0 -44
  89. package/lib/esm/unified-selection/queries/ECMetadata.d.ts.map +0 -1
  90. package/lib/esm/unified-selection/queries/ECMetadata.js +0 -13
  91. package/lib/esm/unified-selection/queries/ECMetadata.js.map +0 -1
  92. package/lib/esm/unified-selection/queries/ECSqlCore.d.ts +0 -69
  93. package/lib/esm/unified-selection/queries/ECSqlCore.d.ts.map +0 -1
  94. package/lib/esm/unified-selection/queries/ECSqlCore.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"SelectionChangeEvent.js","sourceRoot":"","sources":["../../../src/unified-selection/SelectionChangeEvent.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAuEhG;;;GAGG;AACH,MAAM,OAAO,wBAAwB;IAC3B,UAAU,GAAsC,EAAE,CAAC;IAE3D;;;;;OAKG;IACI,WAAW,CAAC,QAAyC;QAC1D,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC7C,CAAC;IAED;;;;OAIG;IACI,cAAc,CAAC,QAAyC;QAC7D,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC;IAClE,CAAC;IAED;;;;;OAKG;IACI,UAAU,CAAC,IAAqC,EAAE,OAAyB;QAChF,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IACjE,CAAC;CACF","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Selectables } from \"./Selectable\";\nimport { SelectionStorage } from \"./SelectionStorage\";\n\n/** @packageDocumentation\n * @module UnifiedSelection\n */\n\n/**\n * The type of selection change.\n * @beta\n */\nexport type StorageSelectionChangeType =\n /** Added to selection. */\n | \"add\"\n /** Removed from selection. */\n | \"remove\"\n /** Selection was replaced. */\n | \"replace\"\n /** Selection was cleared. */\n | \"clear\";\n\n/**\n * The event object that is sent when the selection changes.\n *\n * @beta Used in public API as an argument for `StorageSelectionChangesListener`. Not expected to be created / extended by package\n * consumers, may be supplemented with required attributes any time.\n */\nexport interface StorageSelectionChangeEventArgs {\n /** The name of the selection source which caused the selection change. */\n source: string;\n /** Level of the selection. */\n level: number;\n /** The selection change type. */\n changeType: StorageSelectionChangeType;\n /** Selectables affected by this selection change event. */\n selectables: Selectables;\n /** iModel key with which the selection is associated with. */\n iModelKey: string;\n /** The timestamp of when the selection change happened */\n timestamp: Date;\n}\n\n/**\n * An interface for selection change listeners.\n * @beta\n */\nexport declare type StorageSelectionChangesListener = (args: StorageSelectionChangeEventArgs, storage: SelectionStorage) => void;\n\n/**\n * An interface that allows subscribing and unsubscribing listeners that\n * are called when a selection has changed.\n * @beta\n */\nexport interface SelectionChangeEvent {\n /**\n * Registers a Listener to be executed whenever this event is raised\n * @param listener The function to be executed when the event is raised\n * @returns A function that will remove this event listener\n * @beta\n */\n addListener(listener: StorageSelectionChangesListener): () => void;\n /**\n * Un-register a previously registered listener\n * @param listener The listener to be unregistered\n * @beta\n */\n removeListener(listener: StorageSelectionChangesListener): void;\n}\n\n/**\n * An event broadcasted on selection changes.\n * @internal\n */\nexport class SelectionChangeEventImpl implements SelectionChangeEvent {\n private _listeners: StorageSelectionChangesListener[] = [];\n\n /**\n * Registers a Listener to be executed whenever this event is raised\n * @param listener The function to be executed when the event is raised\n * @returns A function that will remove this event listener\n * @beta\n */\n public addListener(listener: StorageSelectionChangesListener): () => void {\n this._listeners.push(listener);\n return () => this.removeListener(listener);\n }\n\n /**\n * Un-register a previously registered listener\n * @param listener The listener to be unregistered\n * @beta\n */\n public removeListener(listener: StorageSelectionChangesListener): void {\n this._listeners = this._listeners.filter((x) => x !== listener);\n }\n\n /**\n * Raises the event by calling each registered listener with the supplied arguments\n * @param args Event arguments\n * @param storage Storage that the selection changed in\n * @beta\n */\n public raiseEvent(args: StorageSelectionChangeEventArgs, storage: SelectionStorage) {\n this._listeners.forEach((listener) => listener(args, storage));\n }\n}\n"]}
1
+ {"version":3,"file":"SelectionChangeEvent.js","sourceRoot":"","sources":["../../../src/unified-selection/SelectionChangeEvent.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAwEhG;;;GAGG;AACH,MAAM,OAAO,wBAAwB;IAC3B,UAAU,GAAsC,EAAE,CAAC;IAE3D;;;;;OAKG;IACI,WAAW,CAAC,QAAyC;QAC1D,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC7C,CAAC;IAED;;;;OAIG;IACI,cAAc,CAAC,QAAyC;QAC7D,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC;IAClE,CAAC;IAED;;;;;OAKG;IACI,UAAU,CAAC,IAAqC,EAAE,OAAyB;QAChF,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IACjE,CAAC;CACF","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Selectables } from \"./Selectable\";\nimport { SelectionStorage } from \"./SelectionStorage\";\n\n/**\n * The type of selection change.\n * @beta\n */\nexport type StorageSelectionChangeType =\n /** Added to selection. */\n | \"add\"\n /** Removed from selection. */\n | \"remove\"\n /** Selection was replaced. */\n | \"replace\"\n /** Selection was cleared. */\n | \"clear\";\n\n/**\n * The event object that is sent when the selection changes.\n *\n * @beta Used in public API as an argument for `StorageSelectionChangesListener`. Not expected to be created / extended by package\n * consumers, may be supplemented with required attributes any time.\n */\nexport interface StorageSelectionChangeEventArgs {\n /** The name of the selection source which caused the selection change. */\n source: string;\n /** Level of the selection. */\n level: number;\n /** The selection change type. */\n changeType: StorageSelectionChangeType;\n /** Selectables affected by this selection change event. */\n selectables: Selectables;\n /** iModel key with which the selection is associated with. */\n imodelKey: string;\n /**\n * iModel key with which the selection is associated with.\n * @deprecated in 0.2. Use `imodelKey` instead.\n */\n iModelKey: string;\n /** The timestamp of when the selection change happened */\n timestamp: Date;\n}\n\n/**\n * An interface for selection change listeners.\n * @beta\n */\nexport declare type StorageSelectionChangesListener = (args: StorageSelectionChangeEventArgs, storage: SelectionStorage) => void;\n\n/**\n * An interface that allows subscribing and unsubscribing listeners that\n * are called when a selection has changed.\n * @beta\n */\nexport interface SelectionChangeEvent {\n /**\n * Registers a Listener to be executed whenever this event is raised\n * @param listener The function to be executed when the event is raised\n * @returns A function that will remove this event listener\n * @beta\n */\n addListener(listener: StorageSelectionChangesListener): () => void;\n /**\n * Un-register a previously registered listener\n * @param listener The listener to be unregistered\n * @beta\n */\n removeListener(listener: StorageSelectionChangesListener): void;\n}\n\n/**\n * An event broadcasted on selection changes.\n * @internal\n */\nexport class SelectionChangeEventImpl implements SelectionChangeEvent {\n private _listeners: StorageSelectionChangesListener[] = [];\n\n /**\n * Registers a Listener to be executed whenever this event is raised\n * @param listener The function to be executed when the event is raised\n * @returns A function that will remove this event listener\n * @beta\n */\n public addListener(listener: StorageSelectionChangesListener): () => void {\n this._listeners.push(listener);\n return () => this.removeListener(listener);\n }\n\n /**\n * Un-register a previously registered listener\n * @param listener The listener to be unregistered\n * @beta\n */\n public removeListener(listener: StorageSelectionChangesListener): void {\n this._listeners = this._listeners.filter((x) => x !== listener);\n }\n\n /**\n * Raises the event by calling each registered listener with the supplied arguments\n * @param args Event arguments\n * @param storage Storage that the selection changed in\n * @beta\n */\n public raiseEvent(args: StorageSelectionChangeEventArgs, storage: SelectionStorage) {\n this._listeners.forEach((listener) => listener(args, storage));\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { IECSqlQueryExecutor } from "./queries/ECSqlCore";
1
+ import { ECSqlQueryExecutor } from "@itwin/presentation-shared";
2
2
  import { SelectableInstanceKey } from "./Selectable";
3
3
  /**
4
4
  * Available selection scopes.
@@ -27,7 +27,7 @@ export interface ElementSelectionScopeProps {
27
27
  * @internal Not exported through barrel, but used in public API as an argument. May be supplemented with optional attributes any time.
28
28
  */
29
29
  export interface ComputeSelectionProps {
30
- queryExecutor: IECSqlQueryExecutor;
30
+ queryExecutor: ECSqlQueryExecutor;
31
31
  elementIds: string[];
32
32
  scope: ElementSelectionScopeProps | {
33
33
  id: SelectionScope;
@@ -1 +1 @@
1
- {"version":3,"file":"SelectionScope.d.ts","sourceRoot":"","sources":["../../../src/unified-selection/SelectionScope.ts"],"names":[],"mappings":"AAMA,OAAO,EAAgC,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAErD;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,GAAG,YAAY,CAAC;AAE7E;;;GAGG;AACH,MAAM,WAAW,0BAA0B;IACzC,0EAA0E;IAC1E,EAAE,EAAE,SAAS,GAAG,YAAY,CAAC;IAC7B;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,mBAAmB,CAAC;IACnC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,EAAE,0BAA0B,GAAG;QAAE,EAAE,EAAE,cAAc,CAAA;KAAE,GAAG,cAAc,CAAC;CAC7E;AAED;;;;;;GAMG;AACH,wBAAuB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,qBAAqB,CAAC,qBAAqB,CAAC,CAwBlH"}
1
+ {"version":3,"file":"SelectionScope.d.ts","sourceRoot":"","sources":["../../../src/unified-selection/SelectionScope.ts"],"names":[],"mappings":"AAMA,OAAO,EAA+B,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAC7F,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAGrD;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,GAAG,YAAY,CAAC;AAE7E;;;GAGG;AACH,MAAM,WAAW,0BAA0B;IACzC,0EAA0E;IAC1E,EAAE,EAAE,SAAS,GAAG,YAAY,CAAC;IAC7B;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,kBAAkB,CAAC;IAClC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,EAAE,0BAA0B,GAAG;QAAE,EAAE,EAAE,cAAc,CAAA;KAAE,GAAG,cAAc,CAAC;CAC7E;AAED;;;;;;GAMG;AACH,wBAAuB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,qBAAqB,CAAC,qBAAqB,CAAC,CAwBlH"}
@@ -3,7 +3,7 @@
3
3
  * See LICENSE.md in the project root for license terms and full copyright notice.
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  import { Id64 } from "@itwin/core-bentley";
6
- import { formIdBindings } from "./queries/ECSqlCore";
6
+ import { formIdBindings } from "./Utils";
7
7
  /**
8
8
  * Computes selection from given element ID's.
9
9
  * @param queryExecutor iModel query executor.
@@ -36,47 +36,61 @@ export async function* computeSelection(props) {
36
36
  async function* computeElementSelection(queryExecutor, elementIds, ancestorLevel) {
37
37
  const bindings = [];
38
38
  const recurseUntilRoot = ancestorLevel < 0;
39
- const query = `
40
- WITH RECURSIVE
41
- AncestorElements (ECInstanceId, ECClassId, Depth, ParentId) AS (
39
+ const ctes = [
40
+ `
41
+ AncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS (
42
42
  SELECT ECInstanceId, ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, Parent.Id
43
43
  FROM BisCore.Element
44
44
  WHERE ${formIdBindings("ECInstanceId", elementIds, bindings)}
45
45
  UNION ALL
46
- SELECT pe.ECInstanceId, pe.ECClassId, a.Depth - 1, pe.Parent.Id FROM AncestorElements a
47
- JOIN BisCore.Element pe ON pe.ECInstanceId = a.ParentId
46
+ SELECT pe.ECInstanceId, pe.ECClassId, a.Depth - 1, pe.Parent.Id
47
+ FROM AncestorElements a
48
+ JOIN BisCore.Element pe ON pe.ECInstanceId = a.ParentId
48
49
  WHERE ${recurseUntilRoot ? "" : "Depth > 0 AND"} ParentId IS NOT NULL
49
50
  )
50
- SELECT DISTINCT ECInstanceId, ec_classname(ECClassId, 's.c') AS ClassName FROM AncestorElements
51
- WHERE ${recurseUntilRoot ? "" : "Depth = 0 OR"} ParentId IS NULL`;
52
- yield* executeQuery(queryExecutor, query, bindings);
51
+ `,
52
+ ];
53
+ const ecsql = `
54
+ SELECT DISTINCT ECInstanceId, ec_classname(ECClassId, 's.c') AS ClassName
55
+ FROM AncestorElements
56
+ WHERE ${recurseUntilRoot ? "" : "Depth = 0 OR"} ParentId IS NULL
57
+ `;
58
+ yield* executeQuery(queryExecutor, { ctes, ecsql, bindings });
53
59
  }
54
60
  async function* computeCategorySelection(queryExecutor, ids) {
55
61
  const bindings = [];
56
- const query = `
57
- SELECT DISTINCT c.ECInstanceId, ec_classname(c.ECClassId, 's.c') AS ClassName
58
- FROM BisCore.Category c JOIN BisCore.GeometricElement2d ge ON ge.Category.Id = c.ECInstanceId
59
- WHERE ${formIdBindings("ge.ECInstanceId", ids, bindings)}
60
- UNION ALL
61
- SELECT DISTINCT c.ECInstanceId, ec_classname(c.ECClassId, 's.c') AS ClassName
62
- FROM BisCore.Category c JOIN BisCore.GeometricElement3d ge ON ge.Category.Id = c.ECInstanceId
63
- WHERE ${formIdBindings("ge.ECInstanceId", ids, bindings)}`;
64
- yield* executeQuery(queryExecutor, query, bindings);
62
+ const ecsql = [
63
+ `
64
+ SELECT DISTINCT c.ECInstanceId, ec_classname(c.ECClassId, 's.c') AS ClassName
65
+ FROM BisCore.Category c
66
+ JOIN BisCore.GeometricElement2d ge ON ge.Category.Id = c.ECInstanceId
67
+ WHERE ${formIdBindings("ge.ECInstanceId", ids, bindings)}
68
+ `,
69
+ `
70
+ SELECT DISTINCT c.ECInstanceId, ec_classname(c.ECClassId, 's.c') AS ClassName
71
+ FROM BisCore.Category c
72
+ JOIN BisCore.GeometricElement3d ge ON ge.Category.Id = c.ECInstanceId
73
+ WHERE ${formIdBindings("ge.ECInstanceId", ids, bindings)}
74
+ `,
75
+ ].join(" UNION ALL ");
76
+ yield* executeQuery(queryExecutor, { ecsql, bindings });
65
77
  }
66
78
  async function* computeModelSelection(queryExecutor, ids) {
67
79
  const bindings = [];
68
- const query = `
80
+ const ecsql = `
69
81
  SELECT DISTINCT m.ECInstanceId, ec_classname(m.ECClassId, 's.c') AS ClassName
70
- FROM BisCore.Model m JOIN BisCore.Element e ON e.Model.Id = m.ECInstanceId
71
- WHERE ${formIdBindings("e.ECInstanceId", ids, bindings)}`;
72
- yield* executeQuery(queryExecutor, query, bindings);
82
+ FROM BisCore.Model m
83
+ JOIN BisCore.Element e ON e.Model.Id = m.ECInstanceId
84
+ WHERE ${formIdBindings("e.ECInstanceId", ids, bindings)}
85
+ `;
86
+ yield* executeQuery(queryExecutor, { ecsql, bindings });
73
87
  }
74
88
  async function* computeFunctionalElementSelection(queryExecutor, ids, ancestorLevel) {
75
89
  const bindings = [];
76
90
  const recurseUntilRoot = ancestorLevel < 0;
77
- const query = `
78
- WITH RECURSIVE
79
- Elements2dOrNearestFunctionalElements (OriginalECInstanceId, OriginalECClassId, ECInstanceId, ECClassId, ParentId) AS (
91
+ const ctes = [
92
+ `
93
+ Elements2dOrNearestFunctionalElements(OriginalECInstanceId, OriginalECClassId, ECInstanceId, ECClassId, ParentId) AS (
80
94
  SELECT ECInstanceId, ECClassId, ECInstanceId, ECClassId, Parent.Id
81
95
  FROM BisCore.Element
82
96
  WHERE ${formIdBindings("ECInstanceId", ids, bindings)} AND ECClassId IS NOT (BisCore.GeometricElement3d)
@@ -88,67 +102,86 @@ async function* computeFunctionalElementSelection(queryExecutor, ids, ancestorLe
88
102
  COALESCE(dgrfe.TargetECClassId, pe.ECClassId),
89
103
  pe.Parent.Id
90
104
  FROM Elements2dOrNearestFunctionalElements e2onfe
91
- LEFT JOIN BisCore.Element pe ON pe.ECInstanceId = e2onfe.ParentId
92
- LEFT JOIN Functional.DrawingGraphicRepresentsFunctionalElement dgrfe ON dgrfe.SourceECInstanceId = e2onfe.ECInstanceId
105
+ LEFT JOIN BisCore.Element pe ON pe.ECInstanceId = e2onfe.ParentId
106
+ LEFT JOIN Functional.DrawingGraphicRepresentsFunctionalElement dgrfe ON dgrfe.SourceECInstanceId = e2onfe.ECInstanceId
93
107
  WHERE e2onfe.ECClassId IS NOT (Functional.FunctionalElement) AND (e2onfe.ParentId IS NOT NULL OR dgrfe.TargetECInstanceId IS NOT NULL)
94
- ),
95
- Element2dNearestFunctionalElements (OriginalECInstanceId, ECInstanceId, ECClassId) AS (
108
+ )
109
+ `,
110
+ `
111
+ Element2dNearestFunctionalElements(OriginalECInstanceId, ECInstanceId, ECClassId) AS (
96
112
  SELECT OriginalECInstanceId, ECInstanceId, ECClassId
97
113
  FROM Elements2dOrNearestFunctionalElements
98
114
  WHERE ECClassId IS (Functional.FunctionalElement)
99
- ),
100
- Elements2dWithoutFunctionalElement (ECInstanceId, ECClassId) AS (
115
+ )
116
+ `,
117
+ `
118
+ Elements2dWithoutFunctionalElement(ECInstanceId, ECClassId) AS (
101
119
  SELECT e2wfe.OriginalECInstanceId, OriginalECClassId
102
120
  FROM Elements2dOrNearestFunctionalElements e2wfe
103
- LEFT JOIN Element2dNearestFunctionalElements e2nfe ON e2nfe.OriginalECInstanceId = e2wfe.OriginalECInstanceId
121
+ LEFT JOIN Element2dNearestFunctionalElements e2nfe ON e2nfe.OriginalECInstanceId = e2wfe.OriginalECInstanceId
104
122
  WHERE e2wfe.ParentId IS NULL AND e2nfe.ECInstanceId IS NULL
105
- ),
106
- Elements2d (ECInstanceId, ECClassId) AS (
123
+ )
124
+ `,
125
+ `
126
+ Elements2d(ECInstanceId, ECClassId) AS (
107
127
  SELECT ECInstanceId, ECClassId FROM Element2dNearestFunctionalElements
108
128
  UNION
109
129
  SELECT ECInstanceId, ECClassId FROM Elements2dWithoutFunctionalElement
110
- ),
111
- Element2dAncestorElements (ECInstanceId, ECClassId, Depth, ParentId) AS (
130
+ )
131
+ `,
132
+ `
133
+ Element2dAncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS (
112
134
  SELECT e.ECInstanceId, e.ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, e.Parent.Id
113
135
  FROM BisCore.Element e
114
- JOIN Elements2d e2d ON e2d.ECInstanceId = e.ECInstanceId
136
+ JOIN Elements2d e2d ON e2d.ECInstanceId = e.ECInstanceId
115
137
  UNION ALL
116
138
  SELECT pe.ECInstanceId, pe.ECClassId, e2ae.Depth - 1, pe.Parent.Id
117
139
  FROM Element2dAncestorElements e2ae
118
- JOIN BisCore.Element pe ON pe.ECInstanceId = e2ae.ParentId
140
+ JOIN BisCore.Element pe ON pe.ECInstanceId = e2ae.ParentId
119
141
  WHERE ${recurseUntilRoot ? "" : "Depth > 0 AND"} ParentId IS NOT NULL
120
- ),
121
- Element3dAncestorElements (ECInstanceId, ECClassId, Depth, ParentId) AS (
142
+ )
143
+ `,
144
+ `
145
+ Element3dAncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS (
122
146
  SELECT ge.ECInstanceId, ge.ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, ge.Parent.Id
123
147
  FROM BisCore.GeometricElement3d ge
124
148
  WHERE ${formIdBindings("ge.ECInstanceId", ids, bindings)}
125
149
  UNION ALL
126
150
  SELECT pe.ECInstanceId, pe.ECClassId, e3ae.Depth - 1, pe.Parent.Id
127
151
  FROM Element3dAncestorElements e3ae
128
- JOIN BisCore.Element pe ON pe.ECInstanceId = e3ae.ParentId
152
+ JOIN BisCore.Element pe ON pe.ECInstanceId = e3ae.ParentId
129
153
  WHERE ${recurseUntilRoot ? "" : "Depth > 0 AND"} ParentId IS NOT NULL
130
- ),
131
- Element3dAncestorRelatedFunctionalElement (ECInstanceId, ClassName) AS (
154
+ )
155
+ `,
156
+ `
157
+ Element3dAncestorRelatedFunctionalElement(ECInstanceId, ClassName) AS (
132
158
  SELECT
133
159
  COALESCE(peff.TargetECInstanceId, e3ae.ECInstanceId),
134
160
  ec_classname(COALESCE(peff.TargetECClassId, e3ae.ECClassId), 's.c')
135
161
  FROM Element3dAncestorElements e3ae
136
- LEFT JOIN Functional.PhysicalElementFulfillsFunction peff ON peff.SourceECInstanceId = e3ae.ECInstanceId
162
+ LEFT JOIN Functional.PhysicalElementFulfillsFunction peff ON peff.SourceECInstanceId = e3ae.ECInstanceId
137
163
  WHERE ${recurseUntilRoot ? "" : "e3ae.Depth = 0 OR"} e3ae.ParentId IS NULL
138
164
  )
165
+ `,
166
+ ];
167
+ const ecsql = [
168
+ `
139
169
  SELECT DISTINCT ECInstanceId, ec_classname(ECClassId, 's.c') AS ClassName
140
- FROM Element2dAncestorElements
141
- WHERE ${recurseUntilRoot ? "" : "Depth = 0 OR"} ParentId IS NULL
142
- UNION ALL
143
- SELECT DISTINCT ECInstanceId, ClassName FROM Element3dAncestorRelatedFunctionalElement`;
144
- yield* executeQuery(queryExecutor, query, bindings);
170
+ FROM Element2dAncestorElements
171
+ WHERE ${recurseUntilRoot ? "" : "Depth = 0 OR"} ParentId IS NULL
172
+ `,
173
+ `
174
+ SELECT DISTINCT ECInstanceId, ClassName FROM Element3dAncestorRelatedFunctionalElement
175
+ `,
176
+ ].join(" UNION ");
177
+ yield* executeQuery(queryExecutor, { ctes, ecsql, bindings });
145
178
  }
146
179
  function formAncestorLevelBinding(ancestorLevel, bindings) {
147
180
  bindings.push({ type: "int", value: ancestorLevel });
148
181
  return "?";
149
182
  }
150
- async function* executeQuery(queryExecutor, query, bindings) {
151
- const reader = queryExecutor.createQueryReader(query, bindings);
183
+ async function* executeQuery(queryExecutor, query) {
184
+ const reader = queryExecutor.createQueryReader(query);
152
185
  for await (const row of reader) {
153
186
  yield { className: row.ClassName, id: row.ECInstanceId };
154
187
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SelectionScope.js","sourceRoot":"","sources":["../../../src/unified-selection/SelectionScope.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Id64 } from \"@itwin/core-bentley\";\nimport { ECSqlBinding, formIdBindings, IECSqlQueryExecutor } from \"./queries/ECSqlCore\";\nimport { SelectableInstanceKey } from \"./Selectable\";\n\n/**\n * Available selection scopes.\n * @internal Not exported through barrel, but used in public API as an argument. May be supplemented with additional items in the union at any time.\n */\nexport type SelectionScope = \"element\" | \"model\" | \"category\" | \"functional\";\n\n/**\n * Props for computing element selection.\n * @internal Not exported through barrel, but used in public API as an argument. May be supplemented with optional attributes any time.\n */\nexport interface ElementSelectionScopeProps {\n /** Identifies this as either \"element\" or \"functional\" selection scope */\n id: \"element\" | \"functional\";\n /**\n * Specifies how far \"up\" we should walk to find the target element. When not specified or `0`,\n * the target element matches the request element. When set to `1`, the target element matches the direct parent element.\n * When set to `2`, the target element is parent of the parent element and so on. In all situations when this is `> 0`,\n * we're not walking further than the last existing element, for example when `ancestorLevel = 1` (direct parent\n * element is requested), but the request element doesn't have a parent, the request element is returned as the result.\n * A negative value would result in the top-most element to be returned.\n */\n ancestorLevel?: number;\n}\n\n/**\n * Props for `computeSelection`.\n * @internal Not exported through barrel, but used in public API as an argument. May be supplemented with optional attributes any time.\n */\nexport interface ComputeSelectionProps {\n queryExecutor: IECSqlQueryExecutor;\n elementIds: string[];\n scope: ElementSelectionScopeProps | { id: SelectionScope } | SelectionScope;\n}\n\n/**\n * Computes selection from given element ID's.\n * @param queryExecutor iModel query executor.\n * @param elementIds ID's of elements to compute selection for.\n * @param scope Selection scope to compute selection with.\n * @beta\n */\nexport async function* computeSelection(props: ComputeSelectionProps): AsyncIterableIterator<SelectableInstanceKey> {\n const { queryExecutor, elementIds, scope } = props;\n\n if (typeof scope === \"string\") {\n yield* computeSelection({ queryExecutor, elementIds, scope: { id: scope } });\n return;\n }\n\n const nonTransientKeys = elementIds.filter((key) => !Id64.isTransient(key));\n\n switch (scope.id) {\n case \"element\":\n yield* computeElementSelection(queryExecutor, nonTransientKeys, (scope as ElementSelectionScopeProps).ancestorLevel ?? 0);\n return;\n case \"category\":\n yield* computeCategorySelection(queryExecutor, nonTransientKeys);\n return;\n case \"model\":\n yield* computeModelSelection(queryExecutor, nonTransientKeys);\n return;\n case \"functional\":\n yield* computeFunctionalElementSelection(queryExecutor, nonTransientKeys, (scope as ElementSelectionScopeProps).ancestorLevel ?? 0);\n return;\n }\n}\n\nasync function* computeElementSelection(\n queryExecutor: IECSqlQueryExecutor,\n elementIds: string[],\n ancestorLevel: number,\n): AsyncIterableIterator<SelectableInstanceKey> {\n const bindings: ECSqlBinding[] = [];\n const recurseUntilRoot = ancestorLevel < 0;\n const query = `\n WITH RECURSIVE\n AncestorElements (ECInstanceId, ECClassId, Depth, ParentId) AS (\n SELECT ECInstanceId, ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, Parent.Id\n FROM BisCore.Element\n WHERE ${formIdBindings(\"ECInstanceId\", elementIds, bindings)}\n UNION ALL\n SELECT pe.ECInstanceId, pe.ECClassId, a.Depth - 1, pe.Parent.Id FROM AncestorElements a\n JOIN BisCore.Element pe ON pe.ECInstanceId = a.ParentId\n WHERE ${recurseUntilRoot ? \"\" : \"Depth > 0 AND\"} ParentId IS NOT NULL\n )\n SELECT DISTINCT ECInstanceId, ec_classname(ECClassId, 's.c') AS ClassName FROM AncestorElements\n WHERE ${recurseUntilRoot ? \"\" : \"Depth = 0 OR\"} ParentId IS NULL`;\n\n yield* executeQuery(queryExecutor, query, bindings);\n}\n\nasync function* computeCategorySelection(queryExecutor: IECSqlQueryExecutor, ids: string[]): AsyncIterableIterator<SelectableInstanceKey> {\n const bindings: ECSqlBinding[] = [];\n const query = `\n SELECT DISTINCT c.ECInstanceId, ec_classname(c.ECClassId, 's.c') AS ClassName\n FROM BisCore.Category c JOIN BisCore.GeometricElement2d ge ON ge.Category.Id = c.ECInstanceId\n WHERE ${formIdBindings(\"ge.ECInstanceId\", ids, bindings)}\n UNION ALL\n SELECT DISTINCT c.ECInstanceId, ec_classname(c.ECClassId, 's.c') AS ClassName\n FROM BisCore.Category c JOIN BisCore.GeometricElement3d ge ON ge.Category.Id = c.ECInstanceId\n WHERE ${formIdBindings(\"ge.ECInstanceId\", ids, bindings)}`;\n\n yield* executeQuery(queryExecutor, query, bindings);\n}\n\nasync function* computeModelSelection(queryExecutor: IECSqlQueryExecutor, ids: string[]): AsyncIterableIterator<SelectableInstanceKey> {\n const bindings: ECSqlBinding[] = [];\n const query = `\n SELECT DISTINCT m.ECInstanceId, ec_classname(m.ECClassId, 's.c') AS ClassName\n FROM BisCore.Model m JOIN BisCore.Element e ON e.Model.Id = m.ECInstanceId\n WHERE ${formIdBindings(\"e.ECInstanceId\", ids, bindings)}`;\n\n yield* executeQuery(queryExecutor, query, bindings);\n}\n\nasync function* computeFunctionalElementSelection(\n queryExecutor: IECSqlQueryExecutor,\n ids: string[],\n ancestorLevel: number,\n): AsyncIterableIterator<SelectableInstanceKey> {\n const bindings: ECSqlBinding[] = [];\n const recurseUntilRoot = ancestorLevel < 0;\n const query = `\n WITH RECURSIVE\n Elements2dOrNearestFunctionalElements (OriginalECInstanceId, OriginalECClassId, ECInstanceId, ECClassId, ParentId) AS (\n SELECT ECInstanceId, ECClassId, ECInstanceId, ECClassId, Parent.Id\n FROM BisCore.Element\n WHERE ${formIdBindings(\"ECInstanceId\", ids, bindings)} AND ECClassId IS NOT (BisCore.GeometricElement3d)\n UNION ALL\n SELECT\n e2onfe.OriginalECInstanceId,\n e2onfe.OriginalECClassId,\n COALESCE(dgrfe.TargetECInstanceId, pe.ECInstanceId),\n COALESCE(dgrfe.TargetECClassId, pe.ECClassId),\n pe.Parent.Id\n FROM Elements2dOrNearestFunctionalElements e2onfe\n LEFT JOIN BisCore.Element pe ON pe.ECInstanceId = e2onfe.ParentId\n LEFT JOIN Functional.DrawingGraphicRepresentsFunctionalElement dgrfe ON dgrfe.SourceECInstanceId = e2onfe.ECInstanceId\n WHERE e2onfe.ECClassId IS NOT (Functional.FunctionalElement) AND (e2onfe.ParentId IS NOT NULL OR dgrfe.TargetECInstanceId IS NOT NULL)\n ),\n Element2dNearestFunctionalElements (OriginalECInstanceId, ECInstanceId, ECClassId) AS (\n SELECT OriginalECInstanceId, ECInstanceId, ECClassId\n FROM Elements2dOrNearestFunctionalElements\n WHERE ECClassId IS (Functional.FunctionalElement)\n ),\n Elements2dWithoutFunctionalElement (ECInstanceId, ECClassId) AS (\n SELECT e2wfe.OriginalECInstanceId, OriginalECClassId\n FROM Elements2dOrNearestFunctionalElements e2wfe\n LEFT JOIN Element2dNearestFunctionalElements e2nfe ON e2nfe.OriginalECInstanceId = e2wfe.OriginalECInstanceId\n WHERE e2wfe.ParentId IS NULL AND e2nfe.ECInstanceId IS NULL\n ),\n Elements2d (ECInstanceId, ECClassId) AS (\n SELECT ECInstanceId, ECClassId FROM Element2dNearestFunctionalElements\n UNION\n SELECT ECInstanceId, ECClassId FROM Elements2dWithoutFunctionalElement\n ),\n Element2dAncestorElements (ECInstanceId, ECClassId, Depth, ParentId) AS (\n SELECT e.ECInstanceId, e.ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, e.Parent.Id\n FROM BisCore.Element e\n JOIN Elements2d e2d ON e2d.ECInstanceId = e.ECInstanceId\n UNION ALL\n SELECT pe.ECInstanceId, pe.ECClassId, e2ae.Depth - 1, pe.Parent.Id\n FROM Element2dAncestorElements e2ae\n JOIN BisCore.Element pe ON pe.ECInstanceId = e2ae.ParentId\n WHERE ${recurseUntilRoot ? \"\" : \"Depth > 0 AND\"} ParentId IS NOT NULL\n ),\n Element3dAncestorElements (ECInstanceId, ECClassId, Depth, ParentId) AS (\n SELECT ge.ECInstanceId, ge.ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, ge.Parent.Id\n FROM BisCore.GeometricElement3d ge\n WHERE ${formIdBindings(\"ge.ECInstanceId\", ids, bindings)}\n UNION ALL\n SELECT pe.ECInstanceId, pe.ECClassId, e3ae.Depth - 1, pe.Parent.Id\n FROM Element3dAncestorElements e3ae\n JOIN BisCore.Element pe ON pe.ECInstanceId = e3ae.ParentId\n WHERE ${recurseUntilRoot ? \"\" : \"Depth > 0 AND\"} ParentId IS NOT NULL\n ),\n Element3dAncestorRelatedFunctionalElement (ECInstanceId, ClassName) AS (\n SELECT\n COALESCE(peff.TargetECInstanceId, e3ae.ECInstanceId),\n ec_classname(COALESCE(peff.TargetECClassId, e3ae.ECClassId), 's.c')\n FROM Element3dAncestorElements e3ae\n LEFT JOIN Functional.PhysicalElementFulfillsFunction peff ON peff.SourceECInstanceId = e3ae.ECInstanceId\n WHERE ${recurseUntilRoot ? \"\" : \"e3ae.Depth = 0 OR\"} e3ae.ParentId IS NULL\n )\n SELECT DISTINCT ECInstanceId, ec_classname(ECClassId, 's.c') AS ClassName\n FROM Element2dAncestorElements\n WHERE ${recurseUntilRoot ? \"\" : \"Depth = 0 OR\"} ParentId IS NULL\n UNION ALL\n SELECT DISTINCT ECInstanceId, ClassName FROM Element3dAncestorRelatedFunctionalElement`;\n\n yield* executeQuery(queryExecutor, query, bindings);\n}\n\nfunction formAncestorLevelBinding(ancestorLevel: number, bindings: ECSqlBinding[]) {\n bindings.push({ type: \"int\", value: ancestorLevel });\n return \"?\";\n}\n\nasync function* executeQuery(queryExecutor: IECSqlQueryExecutor, query: string, bindings?: ECSqlBinding[]): AsyncIterableIterator<SelectableInstanceKey> {\n const reader = queryExecutor.createQueryReader(query, bindings);\n\n for await (const row of reader) {\n yield { className: row.ClassName, id: row.ECInstanceId };\n }\n}\n"]}
1
+ {"version":3,"file":"SelectionScope.js","sourceRoot":"","sources":["../../../src/unified-selection/SelectionScope.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Id64 } from \"@itwin/core-bentley\";\nimport { ECSqlBinding, ECSqlQueryDef, ECSqlQueryExecutor } from \"@itwin/presentation-shared\";\nimport { SelectableInstanceKey } from \"./Selectable\";\nimport { formIdBindings } from \"./Utils\";\n\n/**\n * Available selection scopes.\n * @internal Not exported through barrel, but used in public API as an argument. May be supplemented with additional items in the union at any time.\n */\nexport type SelectionScope = \"element\" | \"model\" | \"category\" | \"functional\";\n\n/**\n * Props for computing element selection.\n * @internal Not exported through barrel, but used in public API as an argument. May be supplemented with optional attributes any time.\n */\nexport interface ElementSelectionScopeProps {\n /** Identifies this as either \"element\" or \"functional\" selection scope */\n id: \"element\" | \"functional\";\n /**\n * Specifies how far \"up\" we should walk to find the target element. When not specified or `0`,\n * the target element matches the request element. When set to `1`, the target element matches the direct parent element.\n * When set to `2`, the target element is parent of the parent element and so on. In all situations when this is `> 0`,\n * we're not walking further than the last existing element, for example when `ancestorLevel = 1` (direct parent\n * element is requested), but the request element doesn't have a parent, the request element is returned as the result.\n * A negative value would result in the top-most element to be returned.\n */\n ancestorLevel?: number;\n}\n\n/**\n * Props for `computeSelection`.\n * @internal Not exported through barrel, but used in public API as an argument. May be supplemented with optional attributes any time.\n */\nexport interface ComputeSelectionProps {\n queryExecutor: ECSqlQueryExecutor;\n elementIds: string[];\n scope: ElementSelectionScopeProps | { id: SelectionScope } | SelectionScope;\n}\n\n/**\n * Computes selection from given element ID's.\n * @param queryExecutor iModel query executor.\n * @param elementIds ID's of elements to compute selection for.\n * @param scope Selection scope to compute selection with.\n * @beta\n */\nexport async function* computeSelection(props: ComputeSelectionProps): AsyncIterableIterator<SelectableInstanceKey> {\n const { queryExecutor, elementIds, scope } = props;\n\n if (typeof scope === \"string\") {\n yield* computeSelection({ queryExecutor, elementIds, scope: { id: scope } });\n return;\n }\n\n const nonTransientKeys = elementIds.filter((key) => !Id64.isTransient(key));\n\n switch (scope.id) {\n case \"element\":\n yield* computeElementSelection(queryExecutor, nonTransientKeys, (scope as ElementSelectionScopeProps).ancestorLevel ?? 0);\n return;\n case \"category\":\n yield* computeCategorySelection(queryExecutor, nonTransientKeys);\n return;\n case \"model\":\n yield* computeModelSelection(queryExecutor, nonTransientKeys);\n return;\n case \"functional\":\n yield* computeFunctionalElementSelection(queryExecutor, nonTransientKeys, (scope as ElementSelectionScopeProps).ancestorLevel ?? 0);\n return;\n }\n}\n\nasync function* computeElementSelection(\n queryExecutor: ECSqlQueryExecutor,\n elementIds: string[],\n ancestorLevel: number,\n): AsyncIterableIterator<SelectableInstanceKey> {\n const bindings: ECSqlBinding[] = [];\n const recurseUntilRoot = ancestorLevel < 0;\n const ctes = [\n `\n AncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS (\n SELECT ECInstanceId, ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, Parent.Id\n FROM BisCore.Element\n WHERE ${formIdBindings(\"ECInstanceId\", elementIds, bindings)}\n UNION ALL\n SELECT pe.ECInstanceId, pe.ECClassId, a.Depth - 1, pe.Parent.Id\n FROM AncestorElements a\n JOIN BisCore.Element pe ON pe.ECInstanceId = a.ParentId\n WHERE ${recurseUntilRoot ? \"\" : \"Depth > 0 AND\"} ParentId IS NOT NULL\n )\n `,\n ];\n const ecsql = `\n SELECT DISTINCT ECInstanceId, ec_classname(ECClassId, 's.c') AS ClassName\n FROM AncestorElements\n WHERE ${recurseUntilRoot ? \"\" : \"Depth = 0 OR\"} ParentId IS NULL\n `;\n yield* executeQuery(queryExecutor, { ctes, ecsql, bindings });\n}\n\nasync function* computeCategorySelection(queryExecutor: ECSqlQueryExecutor, ids: string[]): AsyncIterableIterator<SelectableInstanceKey> {\n const bindings: ECSqlBinding[] = [];\n const ecsql = [\n `\n SELECT DISTINCT c.ECInstanceId, ec_classname(c.ECClassId, 's.c') AS ClassName\n FROM BisCore.Category c\n JOIN BisCore.GeometricElement2d ge ON ge.Category.Id = c.ECInstanceId\n WHERE ${formIdBindings(\"ge.ECInstanceId\", ids, bindings)}\n `,\n `\n SELECT DISTINCT c.ECInstanceId, ec_classname(c.ECClassId, 's.c') AS ClassName\n FROM BisCore.Category c\n JOIN BisCore.GeometricElement3d ge ON ge.Category.Id = c.ECInstanceId\n WHERE ${formIdBindings(\"ge.ECInstanceId\", ids, bindings)}\n `,\n ].join(\" UNION ALL \");\n yield* executeQuery(queryExecutor, { ecsql, bindings });\n}\n\nasync function* computeModelSelection(queryExecutor: ECSqlQueryExecutor, ids: string[]): AsyncIterableIterator<SelectableInstanceKey> {\n const bindings: ECSqlBinding[] = [];\n const ecsql = `\n SELECT DISTINCT m.ECInstanceId, ec_classname(m.ECClassId, 's.c') AS ClassName\n FROM BisCore.Model m\n JOIN BisCore.Element e ON e.Model.Id = m.ECInstanceId\n WHERE ${formIdBindings(\"e.ECInstanceId\", ids, bindings)}\n `;\n yield* executeQuery(queryExecutor, { ecsql, bindings });\n}\n\nasync function* computeFunctionalElementSelection(\n queryExecutor: ECSqlQueryExecutor,\n ids: string[],\n ancestorLevel: number,\n): AsyncIterableIterator<SelectableInstanceKey> {\n const bindings: ECSqlBinding[] = [];\n const recurseUntilRoot = ancestorLevel < 0;\n const ctes = [\n `\n Elements2dOrNearestFunctionalElements(OriginalECInstanceId, OriginalECClassId, ECInstanceId, ECClassId, ParentId) AS (\n SELECT ECInstanceId, ECClassId, ECInstanceId, ECClassId, Parent.Id\n FROM BisCore.Element\n WHERE ${formIdBindings(\"ECInstanceId\", ids, bindings)} AND ECClassId IS NOT (BisCore.GeometricElement3d)\n UNION ALL\n SELECT\n e2onfe.OriginalECInstanceId,\n e2onfe.OriginalECClassId,\n COALESCE(dgrfe.TargetECInstanceId, pe.ECInstanceId),\n COALESCE(dgrfe.TargetECClassId, pe.ECClassId),\n pe.Parent.Id\n FROM Elements2dOrNearestFunctionalElements e2onfe\n LEFT JOIN BisCore.Element pe ON pe.ECInstanceId = e2onfe.ParentId\n LEFT JOIN Functional.DrawingGraphicRepresentsFunctionalElement dgrfe ON dgrfe.SourceECInstanceId = e2onfe.ECInstanceId\n WHERE e2onfe.ECClassId IS NOT (Functional.FunctionalElement) AND (e2onfe.ParentId IS NOT NULL OR dgrfe.TargetECInstanceId IS NOT NULL)\n )\n `,\n `\n Element2dNearestFunctionalElements(OriginalECInstanceId, ECInstanceId, ECClassId) AS (\n SELECT OriginalECInstanceId, ECInstanceId, ECClassId\n FROM Elements2dOrNearestFunctionalElements\n WHERE ECClassId IS (Functional.FunctionalElement)\n )\n `,\n `\n Elements2dWithoutFunctionalElement(ECInstanceId, ECClassId) AS (\n SELECT e2wfe.OriginalECInstanceId, OriginalECClassId\n FROM Elements2dOrNearestFunctionalElements e2wfe\n LEFT JOIN Element2dNearestFunctionalElements e2nfe ON e2nfe.OriginalECInstanceId = e2wfe.OriginalECInstanceId\n WHERE e2wfe.ParentId IS NULL AND e2nfe.ECInstanceId IS NULL\n )\n `,\n `\n Elements2d(ECInstanceId, ECClassId) AS (\n SELECT ECInstanceId, ECClassId FROM Element2dNearestFunctionalElements\n UNION\n SELECT ECInstanceId, ECClassId FROM Elements2dWithoutFunctionalElement\n )\n `,\n `\n Element2dAncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS (\n SELECT e.ECInstanceId, e.ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, e.Parent.Id\n FROM BisCore.Element e\n JOIN Elements2d e2d ON e2d.ECInstanceId = e.ECInstanceId\n UNION ALL\n SELECT pe.ECInstanceId, pe.ECClassId, e2ae.Depth - 1, pe.Parent.Id\n FROM Element2dAncestorElements e2ae\n JOIN BisCore.Element pe ON pe.ECInstanceId = e2ae.ParentId\n WHERE ${recurseUntilRoot ? \"\" : \"Depth > 0 AND\"} ParentId IS NOT NULL\n )\n `,\n `\n Element3dAncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS (\n SELECT ge.ECInstanceId, ge.ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, ge.Parent.Id\n FROM BisCore.GeometricElement3d ge\n WHERE ${formIdBindings(\"ge.ECInstanceId\", ids, bindings)}\n UNION ALL\n SELECT pe.ECInstanceId, pe.ECClassId, e3ae.Depth - 1, pe.Parent.Id\n FROM Element3dAncestorElements e3ae\n JOIN BisCore.Element pe ON pe.ECInstanceId = e3ae.ParentId\n WHERE ${recurseUntilRoot ? \"\" : \"Depth > 0 AND\"} ParentId IS NOT NULL\n )\n `,\n `\n Element3dAncestorRelatedFunctionalElement(ECInstanceId, ClassName) AS (\n SELECT\n COALESCE(peff.TargetECInstanceId, e3ae.ECInstanceId),\n ec_classname(COALESCE(peff.TargetECClassId, e3ae.ECClassId), 's.c')\n FROM Element3dAncestorElements e3ae\n LEFT JOIN Functional.PhysicalElementFulfillsFunction peff ON peff.SourceECInstanceId = e3ae.ECInstanceId\n WHERE ${recurseUntilRoot ? \"\" : \"e3ae.Depth = 0 OR\"} e3ae.ParentId IS NULL\n )\n `,\n ];\n const ecsql = [\n `\n SELECT DISTINCT ECInstanceId, ec_classname(ECClassId, 's.c') AS ClassName\n FROM Element2dAncestorElements\n WHERE ${recurseUntilRoot ? \"\" : \"Depth = 0 OR\"} ParentId IS NULL\n `,\n `\n SELECT DISTINCT ECInstanceId, ClassName FROM Element3dAncestorRelatedFunctionalElement\n `,\n ].join(\" UNION \");\n yield* executeQuery(queryExecutor, { ctes, ecsql, bindings });\n}\n\nfunction formAncestorLevelBinding(ancestorLevel: number, bindings: ECSqlBinding[]) {\n bindings.push({ type: \"int\", value: ancestorLevel });\n return \"?\";\n}\n\nasync function* executeQuery(queryExecutor: ECSqlQueryExecutor, query: ECSqlQueryDef): AsyncIterableIterator<SelectableInstanceKey> {\n const reader = queryExecutor.createQueryReader(query);\n for await (const row of reader) {\n yield { className: row.ClassName, id: row.ECInstanceId };\n }\n}\n"]}
@@ -1,8 +1,15 @@
1
- /** @packageDocumentation
2
- * @module UnifiedSelection
3
- */
4
1
  import { Selectable, Selectables } from "./Selectable";
5
2
  import { SelectionChangeEvent } from "./SelectionChangeEvent";
3
+ type IModelKeyProp = {
4
+ /** Key of the iModel to get selection levels for. */
5
+ imodelKey: string;
6
+ } | {
7
+ /**
8
+ * Key of the iModel to get selection levels for.
9
+ * @deprecated in 0.2. Use `imodelKey` instead.
10
+ */
11
+ iModelKey: string;
12
+ };
6
13
  /**
7
14
  * Defines return value of `createStorage`.
8
15
  *
@@ -13,21 +20,14 @@ export interface SelectionStorage {
13
20
  /** An event that is raised when selection changes. */
14
21
  selectionChangeEvent: SelectionChangeEvent;
15
22
  /** Get the selection levels currently stored for the specified iModel. */
16
- getSelectionLevels(props: {
17
- /** Key of the iModel to get selection levels for. */
18
- iModelKey: string;
19
- }): number[];
23
+ getSelectionLevels(props: IModelKeyProp): number[];
20
24
  /** Get the selection stored in the storage. */
21
- getSelection(props: {
22
- /** Key of the iModel to get selection for. */
23
- iModelKey: string;
25
+ getSelection(props: IModelKeyProp & {
24
26
  /** Level of the selection. Defaults to `0`. */
25
27
  level?: number;
26
28
  }): Selectables;
27
29
  /** Add keys to the selection. */
28
- addToSelection(props: {
29
- /** Key of the iModel to change selection for. */
30
- iModelKey: string;
30
+ addToSelection(props: IModelKeyProp & {
31
31
  /** Name of the selection source. Generally, this identifies the component that makes the selection change. */
32
32
  source: string;
33
33
  /** The selectables to add to selection. */
@@ -36,9 +36,7 @@ export interface SelectionStorage {
36
36
  level?: number;
37
37
  }): void;
38
38
  /** Remove keys from current selection. */
39
- removeFromSelection(props: {
40
- /** Key of the iModel to change selection for. */
41
- iModelKey: string;
39
+ removeFromSelection(props: IModelKeyProp & {
42
40
  /** Name of the selection source. Generally, this identifies the component that makes the selection change. */
43
41
  source: string;
44
42
  /** The selectables to remove from selection. */
@@ -47,9 +45,7 @@ export interface SelectionStorage {
47
45
  level?: number;
48
46
  }): void;
49
47
  /** Replace current selection. */
50
- replaceSelection(props: {
51
- /** Key of the iModel to change selection for. */
52
- iModelKey: string;
48
+ replaceSelection(props: IModelKeyProp & {
53
49
  /** Name of the selection source. Generally, this identifies the component that makes the selection change. */
54
50
  source: string;
55
51
  /** The selectables to add to selection. */
@@ -58,19 +54,14 @@ export interface SelectionStorage {
58
54
  level?: number;
59
55
  }): void;
60
56
  /** Clear current selection. */
61
- clearSelection(props: {
62
- /** Key of the iModel to change selection for. */
63
- iModelKey: string;
57
+ clearSelection(props: IModelKeyProp & {
64
58
  /** Name of the selection source. Generally, this identifies the component that makes the selection change. */
65
59
  source: string;
66
60
  /** Level of the selection. Defaults to `0`. */
67
61
  level?: number;
68
62
  }): void;
69
63
  /** Clear storage for an iModel. This function should be called when iModel is closed. */
70
- clearStorage(props: {
71
- /** Key of the iModel to change selection for. */
72
- iModelKey: string;
73
- }): void;
64
+ clearStorage(props: IModelKeyProp): void;
74
65
  }
75
66
  /**
76
67
  * Creates a selection storage which stores and allows managing application-level selection.
@@ -78,8 +69,8 @@ export interface SelectionStorage {
78
69
  * **Note:** `clearSelection` should be called upon iModel close to free-up memory:
79
70
  * ```ts
80
71
  * import { IModelConnection } from "@itwin/core-frontend";
81
- * IModelConnection.onClose.addListener((iModel) => {
82
- * storage.clearStorage(iModel.key);
72
+ * IModelConnection.onClose.addListener((imodel) => {
73
+ * storage.clearStorage(imodel.key);
83
74
  * });
84
75
  * ```
85
76
  *
@@ -88,4 +79,5 @@ export interface SelectionStorage {
88
79
  export declare function createStorage(): SelectionStorage;
89
80
  /** @internal */
90
81
  export declare const IMODEL_CLOSE_SELECTION_CLEAR_SOURCE = "Unified selection storage: clear";
82
+ export {};
91
83
  //# sourceMappingURL=SelectionStorage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SelectionStorage.d.ts","sourceRoot":"","sources":["../../../src/unified-selection/SelectionStorage.ts"],"names":[],"mappings":"AAKA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAyF,MAAM,wBAAwB,CAAC;AAErJ;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,sDAAsD;IACtD,oBAAoB,EAAE,oBAAoB,CAAC;IAE3C,0EAA0E;IAC1E,kBAAkB,CAAC,KAAK,EAAE;QACxB,qDAAqD;QACrD,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,MAAM,EAAE,CAAC;IAEb,+CAA+C;IAC/C,YAAY,CAAC,KAAK,EAAE;QAClB,8CAA8C;QAC9C,SAAS,EAAE,MAAM,CAAC;QAClB,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,WAAW,CAAC;IAEhB,iCAAiC;IACjC,cAAc,CAAC,KAAK,EAAE;QACpB,iDAAiD;QACjD,SAAS,EAAE,MAAM,CAAC;QAClB,8GAA8G;QAC9G,MAAM,EAAE,MAAM,CAAC;QACf,2CAA2C;QAC3C,WAAW,EAAE,UAAU,EAAE,CAAC;QAC1B,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,IAAI,CAAC;IAET,0CAA0C;IAC1C,mBAAmB,CAAC,KAAK,EAAE;QACzB,iDAAiD;QACjD,SAAS,EAAE,MAAM,CAAC;QAClB,8GAA8G;QAC9G,MAAM,EAAE,MAAM,CAAC;QACf,gDAAgD;QAChD,WAAW,EAAE,UAAU,EAAE,CAAC;QAC1B,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,IAAI,CAAC;IAET,iCAAiC;IACjC,gBAAgB,CAAC,KAAK,EAAE;QACtB,iDAAiD;QACjD,SAAS,EAAE,MAAM,CAAC;QAClB,8GAA8G;QAC9G,MAAM,EAAE,MAAM,CAAC;QACf,2CAA2C;QAC3C,WAAW,EAAE,UAAU,EAAE,CAAC;QAC1B,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,IAAI,CAAC;IAET,+BAA+B;IAC/B,cAAc,CAAC,KAAK,EAAE;QACpB,iDAAiD;QACjD,SAAS,EAAE,MAAM,CAAC;QAClB,8GAA8G;QAC9G,MAAM,EAAE,MAAM,CAAC;QACf,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,IAAI,CAAC;IAET,yFAAyF;IACzF,YAAY,CAAC,KAAK,EAAE;QAClB,iDAAiD;QACjD,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,IAAI,CAAC;CACV;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,IAAI,gBAAgB,CAEhD;AAED,gBAAgB;AAChB,eAAO,MAAM,mCAAmC,qCAAqC,CAAC"}
1
+ {"version":3,"file":"SelectionStorage.d.ts","sourceRoot":"","sources":["../../../src/unified-selection/SelectionStorage.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAyF,MAAM,wBAAwB,CAAC;AAErJ,KAAK,aAAa,GACd;IACE,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;CACnB,GACD;IACE;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEN;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,sDAAsD;IACtD,oBAAoB,EAAE,oBAAoB,CAAC;IAE3C,0EAA0E;IAC1E,kBAAkB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,EAAE,CAAC;IAEnD,+CAA+C;IAC/C,YAAY,CACV,KAAK,EAAE,aAAa,GAAG;QACrB,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GACA,WAAW,CAAC;IAEf,iCAAiC;IACjC,cAAc,CACZ,KAAK,EAAE,aAAa,GAAG;QACrB,8GAA8G;QAC9G,MAAM,EAAE,MAAM,CAAC;QACf,2CAA2C;QAC3C,WAAW,EAAE,UAAU,EAAE,CAAC;QAC1B,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GACA,IAAI,CAAC;IAER,0CAA0C;IAC1C,mBAAmB,CACjB,KAAK,EAAE,aAAa,GAAG;QACrB,8GAA8G;QAC9G,MAAM,EAAE,MAAM,CAAC;QACf,gDAAgD;QAChD,WAAW,EAAE,UAAU,EAAE,CAAC;QAC1B,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GACA,IAAI,CAAC;IAER,iCAAiC;IACjC,gBAAgB,CACd,KAAK,EAAE,aAAa,GAAG;QACrB,8GAA8G;QAC9G,MAAM,EAAE,MAAM,CAAC;QACf,2CAA2C;QAC3C,WAAW,EAAE,UAAU,EAAE,CAAC;QAC1B,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GACA,IAAI,CAAC;IAER,+BAA+B;IAC/B,cAAc,CACZ,KAAK,EAAE,aAAa,GAAG;QACrB,8GAA8G;QAC9G,MAAM,EAAE,MAAM,CAAC;QACf,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GACA,IAAI,CAAC;IAER,yFAAyF;IACzF,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;CAC1C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,IAAI,gBAAgB,CAEhD;AAED,gBAAgB;AAChB,eAAO,MAAM,mCAAmC,qCAAqC,CAAC"}
@@ -2,9 +2,6 @@
2
2
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
3
  * See LICENSE.md in the project root for license terms and full copyright notice.
4
4
  *--------------------------------------------------------------------------------------------*/
5
- /** @packageDocumentation
6
- * @module UnifiedSelection
7
- */
8
5
  import { Selectables } from "./Selectable";
9
6
  import { SelectionChangeEventImpl } from "./SelectionChangeEvent";
10
7
  /**
@@ -13,8 +10,8 @@ import { SelectionChangeEventImpl } from "./SelectionChangeEvent";
13
10
  * **Note:** `clearSelection` should be called upon iModel close to free-up memory:
14
11
  * ```ts
15
12
  * import { IModelConnection } from "@itwin/core-frontend";
16
- * IModelConnection.onClose.addListener((iModel) => {
17
- * storage.clearStorage(iModel.key);
13
+ * IModelConnection.onClose.addListener((imodel) => {
14
+ * storage.clearStorage(imodel.key);
18
15
  * });
19
16
  * ```
20
17
  *
@@ -31,12 +28,11 @@ class SelectionStorageImpl {
31
28
  constructor() {
32
29
  this.selectionChangeEvent = new SelectionChangeEventImpl();
33
30
  }
34
- getSelectionLevels({ iModelKey }) {
35
- return this.getContainer(iModelKey).getSelectionLevels();
31
+ getSelectionLevels(props) {
32
+ return this.getContainer(getIModelKey(props)).getSelectionLevels();
36
33
  }
37
34
  getSelection(props) {
38
- const { iModelKey, level } = props;
39
- return this.getContainer(iModelKey).getSelection(level ?? 0);
35
+ return this.getContainer(getIModelKey(props)).getSelection(props.level ?? 0);
40
36
  }
41
37
  addToSelection(props) {
42
38
  this.handleChange({ ...props, changeType: "add" });
@@ -50,21 +46,23 @@ class SelectionStorageImpl {
50
46
  clearSelection(props) {
51
47
  this.handleChange({ ...props, changeType: "clear", selectables: [] });
52
48
  }
53
- clearStorage({ iModelKey }) {
54
- this.clearSelection({ source: IMODEL_CLOSE_SELECTION_CLEAR_SOURCE, iModelKey });
55
- this._storage.delete(iModelKey);
49
+ clearStorage(props) {
50
+ const imodelKey = getIModelKey(props);
51
+ this.clearSelection({ source: IMODEL_CLOSE_SELECTION_CLEAR_SOURCE, imodelKey });
52
+ this._storage.delete(imodelKey);
56
53
  }
57
- getContainer(iModelKey) {
58
- let selectionContainer = this._storage.get(iModelKey);
54
+ getContainer(imodelKey) {
55
+ let selectionContainer = this._storage.get(imodelKey);
59
56
  if (!selectionContainer) {
60
57
  selectionContainer = new MultiLevelSelectablesContainer();
61
- this._storage.set(iModelKey, selectionContainer);
58
+ this._storage.set(imodelKey, selectionContainer);
62
59
  }
63
60
  return selectionContainer;
64
61
  }
65
62
  handleChange(props) {
66
- const { iModelKey, source, level: inLevel, changeType, selectables: change } = props;
67
- const container = this.getContainer(iModelKey);
63
+ const { source, level: inLevel, changeType, selectables: change } = props;
64
+ const imodelKey = getIModelKey(props);
65
+ const container = this.getContainer(imodelKey);
68
66
  const level = inLevel ?? 0;
69
67
  const selectables = container.getSelection(level);
70
68
  const selected = Selectables.create(change);
@@ -96,7 +94,8 @@ class SelectionStorageImpl {
96
94
  const event = {
97
95
  source,
98
96
  level,
99
- iModelKey,
97
+ imodelKey,
98
+ iModelKey: imodelKey,
100
99
  changeType,
101
100
  selectables: selected,
102
101
  timestamp: new Date(),
@@ -104,6 +103,10 @@ class SelectionStorageImpl {
104
103
  this.selectionChangeEvent.raiseEvent(event, this);
105
104
  }
106
105
  }
106
+ function getIModelKey(props) {
107
+ // eslint-disable-next-line deprecation/deprecation
108
+ return "imodelKey" in props ? props.imodelKey : props.iModelKey;
109
+ }
107
110
  class MultiLevelSelectablesContainer {
108
111
  _selectablesContainers;
109
112
  constructor() {
@@ -1 +1 @@
1
- {"version":3,"file":"SelectionStorage.js","sourceRoot":"","sources":["../../../src/unified-selection/SelectionStorage.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\n/** @packageDocumentation\n * @module UnifiedSelection\n */\n\nimport { Selectable, Selectables } from \"./Selectable\";\nimport { SelectionChangeEvent, SelectionChangeEventImpl, StorageSelectionChangeEventArgs, StorageSelectionChangeType } from \"./SelectionChangeEvent\";\n\n/**\n * Defines return value of `createStorage`.\n *\n * @beta Used in public API as a return value. Not expected to be created / extended by package\n * consumers, may be supplemented with required attributes any time.\n */\nexport interface SelectionStorage {\n /** An event that is raised when selection changes. */\n selectionChangeEvent: SelectionChangeEvent;\n\n /** Get the selection levels currently stored for the specified iModel. */\n getSelectionLevels(props: {\n /** Key of the iModel to get selection levels for. */\n iModelKey: string;\n }): number[];\n\n /** Get the selection stored in the storage. */\n getSelection(props: {\n /** Key of the iModel to get selection for. */\n iModelKey: string;\n /** Level of the selection. Defaults to `0`. */\n level?: number;\n }): Selectables;\n\n /** Add keys to the selection. */\n addToSelection(props: {\n /** Key of the iModel to change selection for. */\n iModelKey: string;\n /** Name of the selection source. Generally, this identifies the component that makes the selection change. */\n source: string;\n /** The selectables to add to selection. */\n selectables: Selectable[];\n /** Level of the selection. Defaults to `0`. */\n level?: number;\n }): void;\n\n /** Remove keys from current selection. */\n removeFromSelection(props: {\n /** Key of the iModel to change selection for. */\n iModelKey: string;\n /** Name of the selection source. Generally, this identifies the component that makes the selection change. */\n source: string;\n /** The selectables to remove from selection. */\n selectables: Selectable[];\n /** Level of the selection. Defaults to `0`. */\n level?: number;\n }): void;\n\n /** Replace current selection. */\n replaceSelection(props: {\n /** Key of the iModel to change selection for. */\n iModelKey: string;\n /** Name of the selection source. Generally, this identifies the component that makes the selection change. */\n source: string;\n /** The selectables to add to selection. */\n selectables: Selectable[];\n /** Level of the selection. Defaults to `0`. */\n level?: number;\n }): void;\n\n /** Clear current selection. */\n clearSelection(props: {\n /** Key of the iModel to change selection for. */\n iModelKey: string;\n /** Name of the selection source. Generally, this identifies the component that makes the selection change. */\n source: string;\n /** Level of the selection. Defaults to `0`. */\n level?: number;\n }): void;\n\n /** Clear storage for an iModel. This function should be called when iModel is closed. */\n clearStorage(props: {\n /** Key of the iModel to change selection for. */\n iModelKey: string;\n }): void;\n}\n\n/**\n * Creates a selection storage which stores and allows managing application-level selection.\n *\n * **Note:** `clearSelection` should be called upon iModel close to free-up memory:\n * ```ts\n * import { IModelConnection } from \"@itwin/core-frontend\";\n * IModelConnection.onClose.addListener((iModel) => {\n * storage.clearStorage(iModel.key);\n * });\n * ```\n *\n * @beta\n */\nexport function createStorage(): SelectionStorage {\n return new SelectionStorageImpl();\n}\n\n/** @internal */\nexport const IMODEL_CLOSE_SELECTION_CLEAR_SOURCE = \"Unified selection storage: clear\";\n\nclass SelectionStorageImpl implements SelectionStorage {\n private _storage = new Map<string, MultiLevelSelectablesContainer>();\n public selectionChangeEvent: SelectionChangeEventImpl;\n\n constructor() {\n this.selectionChangeEvent = new SelectionChangeEventImpl();\n }\n\n public getSelectionLevels({ iModelKey }: { iModelKey: string }): number[] {\n return this.getContainer(iModelKey).getSelectionLevels();\n }\n\n public getSelection(props: { iModelKey: string; level?: number }): Selectables {\n const { iModelKey, level } = props;\n return this.getContainer(iModelKey).getSelection(level ?? 0);\n }\n\n public addToSelection(props: { source: string; iModelKey: string; selectables: Selectable[]; level?: number }): void {\n this.handleChange({ ...props, changeType: \"add\" });\n }\n\n public removeFromSelection(props: { source: string; iModelKey: string; selectables: Selectable[]; level?: number }): void {\n this.handleChange({ ...props, changeType: \"remove\" });\n }\n\n public replaceSelection(props: { source: string; iModelKey: string; selectables: Selectable[]; level?: number }): void {\n this.handleChange({ ...props, changeType: \"replace\" });\n }\n\n public clearSelection(props: { source: string; iModelKey: string; level?: number }): void {\n this.handleChange({ ...props, changeType: \"clear\", selectables: [] });\n }\n\n public clearStorage({ iModelKey }: { iModelKey: string }): void {\n this.clearSelection({ source: IMODEL_CLOSE_SELECTION_CLEAR_SOURCE, iModelKey });\n this._storage.delete(iModelKey);\n }\n\n private getContainer(iModelKey: string): MultiLevelSelectablesContainer {\n let selectionContainer = this._storage.get(iModelKey);\n if (!selectionContainer) {\n selectionContainer = new MultiLevelSelectablesContainer();\n this._storage.set(iModelKey, selectionContainer);\n }\n return selectionContainer;\n }\n\n private handleChange(props: { source: string; iModelKey: string; level?: number; changeType: StorageSelectionChangeType; selectables: Selectable[] }) {\n const { iModelKey, source, level: inLevel, changeType, selectables: change } = props;\n const container = this.getContainer(iModelKey);\n const level = inLevel ?? 0;\n const selectables = container.getSelection(level);\n const selected = Selectables.create(change);\n switch (changeType) {\n case \"add\":\n if (!Selectables.add(selectables, change)) {\n return;\n }\n break;\n case \"remove\":\n if (!Selectables.remove(selectables, change)) {\n return;\n }\n break;\n case \"replace\":\n if (Selectables.size(selectables) === Selectables.size(selected) && Selectables.hasAll(selectables, change)) {\n return;\n }\n Selectables.clear(selectables);\n Selectables.add(selectables, change);\n break;\n case \"clear\":\n if (!Selectables.clear(selectables)) {\n return;\n }\n break;\n }\n container.clear(level + 1);\n const event: StorageSelectionChangeEventArgs = {\n source,\n level,\n iModelKey,\n changeType,\n selectables: selected,\n timestamp: new Date(),\n };\n this.selectionChangeEvent.raiseEvent(event, this);\n }\n}\n\nclass MultiLevelSelectablesContainer {\n private readonly _selectablesContainers: Map<number, Selectables>;\n\n constructor() {\n this._selectablesContainers = new Map<number, Selectables>();\n }\n\n public getSelection(level: number): Selectables {\n let selectables = this._selectablesContainers.get(level);\n if (!selectables) {\n selectables = Selectables.create([]);\n this._selectablesContainers.set(level, selectables);\n }\n return selectables;\n }\n\n public getSelectionLevels(): number[] {\n const levels = new Array<number>();\n for (const entry of this._selectablesContainers.entries()) {\n if (!Selectables.isEmpty(entry[1])) {\n levels.push(entry[0]);\n }\n }\n return levels.sort();\n }\n\n public clear(level: number) {\n const storedLevels = this._selectablesContainers.keys();\n for (const storedLevel of storedLevels) {\n if (storedLevel >= level) {\n const selectables = this._selectablesContainers.get(storedLevel)!;\n Selectables.clear(selectables);\n }\n }\n }\n}\n"]}
1
+ {"version":3,"file":"SelectionStorage.js","sourceRoot":"","sources":["../../../src/unified-selection/SelectionStorage.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Selectable, Selectables } from \"./Selectable\";\nimport { SelectionChangeEvent, SelectionChangeEventImpl, StorageSelectionChangeEventArgs, StorageSelectionChangeType } from \"./SelectionChangeEvent\";\n\ntype IModelKeyProp =\n | {\n /** Key of the iModel to get selection levels for. */\n imodelKey: string;\n }\n | {\n /**\n * Key of the iModel to get selection levels for.\n * @deprecated in 0.2. Use `imodelKey` instead.\n */\n iModelKey: string;\n };\n\n/**\n * Defines return value of `createStorage`.\n *\n * @beta Used in public API as a return value. Not expected to be created / extended by package\n * consumers, may be supplemented with required attributes any time.\n */\nexport interface SelectionStorage {\n /** An event that is raised when selection changes. */\n selectionChangeEvent: SelectionChangeEvent;\n\n /** Get the selection levels currently stored for the specified iModel. */\n getSelectionLevels(props: IModelKeyProp): number[];\n\n /** Get the selection stored in the storage. */\n getSelection(\n props: IModelKeyProp & {\n /** Level of the selection. Defaults to `0`. */\n level?: number;\n },\n ): Selectables;\n\n /** Add keys to the selection. */\n addToSelection(\n props: IModelKeyProp & {\n /** Name of the selection source. Generally, this identifies the component that makes the selection change. */\n source: string;\n /** The selectables to add to selection. */\n selectables: Selectable[];\n /** Level of the selection. Defaults to `0`. */\n level?: number;\n },\n ): void;\n\n /** Remove keys from current selection. */\n removeFromSelection(\n props: IModelKeyProp & {\n /** Name of the selection source. Generally, this identifies the component that makes the selection change. */\n source: string;\n /** The selectables to remove from selection. */\n selectables: Selectable[];\n /** Level of the selection. Defaults to `0`. */\n level?: number;\n },\n ): void;\n\n /** Replace current selection. */\n replaceSelection(\n props: IModelKeyProp & {\n /** Name of the selection source. Generally, this identifies the component that makes the selection change. */\n source: string;\n /** The selectables to add to selection. */\n selectables: Selectable[];\n /** Level of the selection. Defaults to `0`. */\n level?: number;\n },\n ): void;\n\n /** Clear current selection. */\n clearSelection(\n props: IModelKeyProp & {\n /** Name of the selection source. Generally, this identifies the component that makes the selection change. */\n source: string;\n /** Level of the selection. Defaults to `0`. */\n level?: number;\n },\n ): void;\n\n /** Clear storage for an iModel. This function should be called when iModel is closed. */\n clearStorage(props: IModelKeyProp): void;\n}\n\n/**\n * Creates a selection storage which stores and allows managing application-level selection.\n *\n * **Note:** `clearSelection` should be called upon iModel close to free-up memory:\n * ```ts\n * import { IModelConnection } from \"@itwin/core-frontend\";\n * IModelConnection.onClose.addListener((imodel) => {\n * storage.clearStorage(imodel.key);\n * });\n * ```\n *\n * @beta\n */\nexport function createStorage(): SelectionStorage {\n return new SelectionStorageImpl();\n}\n\n/** @internal */\nexport const IMODEL_CLOSE_SELECTION_CLEAR_SOURCE = \"Unified selection storage: clear\";\n\nclass SelectionStorageImpl implements SelectionStorage {\n private _storage = new Map<string, MultiLevelSelectablesContainer>();\n public selectionChangeEvent: SelectionChangeEventImpl;\n\n constructor() {\n this.selectionChangeEvent = new SelectionChangeEventImpl();\n }\n\n public getSelectionLevels(props: IModelKeyProp): number[] {\n return this.getContainer(getIModelKey(props)).getSelectionLevels();\n }\n\n public getSelection(props: IModelKeyProp & { level?: number }): Selectables {\n return this.getContainer(getIModelKey(props)).getSelection(props.level ?? 0);\n }\n\n public addToSelection(props: IModelKeyProp & { source: string; selectables: Selectable[]; level?: number }): void {\n this.handleChange({ ...props, changeType: \"add\" });\n }\n\n public removeFromSelection(props: IModelKeyProp & { source: string; selectables: Selectable[]; level?: number }): void {\n this.handleChange({ ...props, changeType: \"remove\" });\n }\n\n public replaceSelection(props: IModelKeyProp & { source: string; selectables: Selectable[]; level?: number }): void {\n this.handleChange({ ...props, changeType: \"replace\" });\n }\n\n public clearSelection(props: IModelKeyProp & { source: string; level?: number }): void {\n this.handleChange({ ...props, changeType: \"clear\", selectables: [] });\n }\n\n public clearStorage(props: IModelKeyProp): void {\n const imodelKey = getIModelKey(props);\n this.clearSelection({ source: IMODEL_CLOSE_SELECTION_CLEAR_SOURCE, imodelKey });\n this._storage.delete(imodelKey);\n }\n\n private getContainer(imodelKey: string): MultiLevelSelectablesContainer {\n let selectionContainer = this._storage.get(imodelKey);\n if (!selectionContainer) {\n selectionContainer = new MultiLevelSelectablesContainer();\n this._storage.set(imodelKey, selectionContainer);\n }\n return selectionContainer;\n }\n\n private handleChange(props: IModelKeyProp & { source: string; level?: number; changeType: StorageSelectionChangeType; selectables: Selectable[] }) {\n const { source, level: inLevel, changeType, selectables: change } = props;\n const imodelKey = getIModelKey(props);\n const container = this.getContainer(imodelKey);\n const level = inLevel ?? 0;\n const selectables = container.getSelection(level);\n const selected = Selectables.create(change);\n switch (changeType) {\n case \"add\":\n if (!Selectables.add(selectables, change)) {\n return;\n }\n break;\n case \"remove\":\n if (!Selectables.remove(selectables, change)) {\n return;\n }\n break;\n case \"replace\":\n if (Selectables.size(selectables) === Selectables.size(selected) && Selectables.hasAll(selectables, change)) {\n return;\n }\n Selectables.clear(selectables);\n Selectables.add(selectables, change);\n break;\n case \"clear\":\n if (!Selectables.clear(selectables)) {\n return;\n }\n break;\n }\n container.clear(level + 1);\n const event: StorageSelectionChangeEventArgs = {\n source,\n level,\n imodelKey,\n iModelKey: imodelKey,\n changeType,\n selectables: selected,\n timestamp: new Date(),\n };\n this.selectionChangeEvent.raiseEvent(event, this);\n }\n}\n\nfunction getIModelKey(props: IModelKeyProp): string {\n // eslint-disable-next-line deprecation/deprecation\n return \"imodelKey\" in props ? props.imodelKey : props.iModelKey;\n}\n\nclass MultiLevelSelectablesContainer {\n private readonly _selectablesContainers: Map<number, Selectables>;\n\n constructor() {\n this._selectablesContainers = new Map<number, Selectables>();\n }\n\n public getSelection(level: number): Selectables {\n let selectables = this._selectablesContainers.get(level);\n if (!selectables) {\n selectables = Selectables.create([]);\n this._selectablesContainers.set(level, selectables);\n }\n return selectables;\n }\n\n public getSelectionLevels(): number[] {\n const levels = new Array<number>();\n for (const entry of this._selectablesContainers.entries()) {\n if (!Selectables.isEmpty(entry[1])) {\n levels.push(entry[0]);\n }\n }\n return levels.sort();\n }\n\n public clear(level: number) {\n const storedLevels = this._selectablesContainers.keys();\n for (const storedLevel of storedLevels) {\n if (storedLevel >= level) {\n const selectables = this._selectablesContainers.get(storedLevel)!;\n Selectables.clear(selectables);\n }\n }\n }\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import { ECSqlBinding } from "@itwin/presentation-shared";
2
+ /**
3
+ * Forms ECSql bindings from given ID's.
4
+ * @internal
5
+ */
6
+ export declare function formIdBindings(property: string, ids: string[], bindings: ECSqlBinding[]): string;
7
+ //# sourceMappingURL=Utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Utils.d.ts","sourceRoot":"","sources":["../../../src/unified-selection/Utils.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,MAAM,CAYhG"}
@@ -4,6 +4,7 @@
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  /**
6
6
  * Forms ECSql bindings from given ID's.
7
+ * @internal
7
8
  */
8
9
  export function formIdBindings(property, ids, bindings) {
9
10
  if (ids.length > 1000) {
@@ -16,4 +17,4 @@ export function formIdBindings(property, ids, bindings) {
16
17
  ids.forEach((id) => bindings.push({ type: "id", value: id }));
17
18
  return `${property} IN (${ids.map(() => "?").join(",")})`;
18
19
  }
19
- //# sourceMappingURL=ECSqlCore.js.map
20
+ //# sourceMappingURL=Utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Utils.js","sourceRoot":"","sources":["../../../src/unified-selection/Utils.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAIhG;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,GAAa,EAAE,QAAwB;IACtF,IAAI,GAAG,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;QACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAC7C,OAAO,mBAAmB,QAAQ,GAAG,CAAC;IACxC,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IAC9D,OAAO,GAAG,QAAQ,QAAQ,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AAC5D,CAAC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { ECSqlBinding } from \"@itwin/presentation-shared\";\n\n/**\n * Forms ECSql bindings from given ID's.\n * @internal\n */\nexport function formIdBindings(property: string, ids: string[], bindings: ECSqlBinding[]): string {\n if (ids.length > 1000) {\n bindings.push({ type: \"idset\", value: ids });\n return `InVirtualSet(?, ${property})`;\n }\n\n if (ids.length === 0) {\n return `FALSE`;\n }\n\n ids.forEach((id) => bindings.push({ type: \"id\", value: id }));\n return `${property} IN (${ids.map(() => \"?\").join(\",\")})`;\n}\n"]}