@itwin/saved-views-react 0.9.7 → 1.0.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.
package/README.md CHANGED
@@ -158,7 +158,7 @@ function OpenSavedView(props) {
158
158
 
159
159
  ## Contributing
160
160
 
161
- We welcome contributions to make this package better. You can submit feature requests or report bugs by creating an [issue](https://github.com/iTwin/saved-views/issues).
161
+ [Contributing](../../README.md#contributing).
162
162
 
163
163
  ---
164
164
 
@@ -1,5 +1,6 @@
1
1
  import { ViewChangeOptions, ViewPose, ViewState, type IModelConnection, type Viewport } from "@itwin/core-frontend";
2
2
  import type { SavedViewData } from "./SavedView.js";
3
+ import { type ApplyVisibilitySettings } from "./createViewState.js";
3
4
  import { type DefaultExtensionHandlersApplyOverrides } from "./translation/SavedViewsExtensionHandlers.js";
4
5
  export interface ApplySavedViewSettings {
5
6
  /**
@@ -37,11 +38,17 @@ export interface ApplySavedViewSettings {
37
38
  */
38
39
  perModelCategoryVisibility?: ApplyStrategy | "clear" | undefined;
39
40
  /**
40
- * How to handle visibility of models and categories that exist in iModel but
41
- * are not captured in Saved View data.
42
- * @default "hidden"
41
+ * How to handle the visibility of models that exist in iModel,
42
+ * including those not captured in Saved View data.
43
+ * @default '{ enabled: "ignore", disabled: "ignore", other: "ignore" }'
43
44
  */
44
- modelAndCategoryVisibilityFallback?: "visible" | "hidden" | undefined;
45
+ models?: ApplyVisibilitySettings | undefined;
46
+ /**
47
+ * How to handle the visibility of categories that exist in iModel,
48
+ * including those not captured in Saved View data.
49
+ * @default '{ enabled: "ignore", disabled: "ignore", other: "ignore" }'
50
+ */
51
+ categories?: ApplyVisibilitySettings | undefined;
45
52
  /**
46
53
  * Options forwarded to {@link Viewport.changeView}.
47
54
  * @default undefined
@@ -61,13 +61,23 @@ function applyCameraOptions(seedViewStateProps, _iModel, viewport, savedViewData
61
61
  return seedViewStateProps;
62
62
  }
63
63
  async function applyViewStateProps(viewStateProps, iModel, viewport, savedViewData, settings) {
64
- // We use "hidden" as the default value for modelAndCategoryVisibilityFallback
65
- // because users expect modelSelector.enabled and categorySelector.enabled to
66
- // act as exclusive whitelists when modelSelector.disabled or categorySelector.disabled
67
- // arrays are empty, respectively.
68
- const { modelAndCategoryVisibilityFallback = "hidden" } = settings;
64
+ // We use {enabled: "ignore", disabled: "ignore", other: "ignore"} as the default values
65
+ // for models and categories because users expect modelSelector.enabled and
66
+ // categorySelector.enabled to act as exclusive whitelists when modelSelector.disabled
67
+ // or categorySelector.disabled arrays are empty, respectively.
68
+ const models = {
69
+ enabled: settings.models?.enabled ?? "ignore",
70
+ disabled: settings.models?.disabled ?? "ignore",
71
+ other: settings.models?.other ?? "ignore",
72
+ };
73
+ const categories = {
74
+ enabled: settings.categories?.enabled ?? "ignore",
75
+ disabled: settings.categories?.disabled ?? "ignore",
76
+ other: settings.categories?.other ?? "ignore",
77
+ };
69
78
  const viewState = await createViewStateFromProps(viewStateProps, iModel, savedViewData.viewData, {
70
- modelAndCategoryVisibilityFallback,
79
+ models,
80
+ categories,
71
81
  });
72
82
  viewport.changeView(viewState, settings.viewChangeOptions);
73
83
  }
@@ -35,8 +35,8 @@ interface CaptureSavedViewDataArgs {
35
35
  * }
36
36
  */
37
37
  export declare function captureSavedViewData(args: CaptureSavedViewDataArgs): Promise<SavedViewData>;
38
- export declare function queryMissingModels(iModel: IModelConnection, knownModels: Set<string>): Promise<string[]>;
38
+ export declare function queryMissingModels(iModel: IModelConnection, knownModels?: Set<string>): Promise<string[]>;
39
39
  export declare function queryAllSpatiallyLocatedModels(iModel: IModelConnection): Promise<string[]>;
40
- export declare function queryMissingCategories(iModel: IModelConnection, knownCategories: Set<string>): Promise<Id64Array>;
40
+ export declare function queryMissingCategories(iModel: IModelConnection, knownCategories?: Set<string>): Promise<Id64Array>;
41
41
  export declare function queryAllCategories(iModel: IModelConnection): Promise<string[]>;
42
42
  export {};
@@ -161,6 +161,9 @@ export async function queryMissingModels(iModel, knownModels) {
161
161
  return [];
162
162
  }
163
163
  const allModels = await queryAllSpatiallyLocatedModels(iModel);
164
+ if (!knownModels || knownModels.size === 0) {
165
+ return allModels;
166
+ }
164
167
  return allModels.filter((modelId) => !knownModels.has(modelId));
165
168
  }
166
169
  export async function queryAllSpatiallyLocatedModels(iModel) {
@@ -181,6 +184,9 @@ export async function queryMissingCategories(iModel, knownCategories) {
181
184
  return [];
182
185
  }
183
186
  const allCategories = await queryAllCategories(iModel);
187
+ if (!knownCategories || knownCategories.size === 0) {
188
+ return allCategories;
189
+ }
184
190
  return allCategories.filter((categoryId) => !knownCategories.has(categoryId));
185
191
  }
186
192
  export async function queryAllCategories(iModel) {
@@ -1,6 +1,26 @@
1
1
  import { type ViewStateProps } from "@itwin/core-common";
2
2
  import { type IModelConnection, type ViewState } from "@itwin/core-frontend";
3
3
  import type { ViewData } from "./SavedView.js";
4
+ /**
5
+ * Settings for how to handle the visibility of elements (models or categories) in iModel.
6
+ * * `enabled` – Enabled is the set of enabled elements (models or categories) that are stored in the saved view. Default is ignore.
7
+ * * `disabled` – Disabled is the set of disabled elements (models or categories) that are stored in the saved view. Default is ignore.
8
+ * * `other` – Other is the set of elements (models or categories) that are not stored in the saved view. Default is ignore.
9
+ *
10
+ * @default '{ enabled: "ignore", disabled: "ignore", other: "ignore" }'
11
+ */
12
+ export interface ApplyVisibilitySettings {
13
+ enabled?: ShowStrategy | undefined;
14
+ disabled?: ShowStrategy | undefined;
15
+ other?: ShowStrategy | undefined;
16
+ }
17
+ /**
18
+ * Controls how models or categories are going to be altered.
19
+ * * `"show"` – Show the elements in this list
20
+ * * `"hide"` – Hide (ie do not show) the elements in this list
21
+ * * `"ignore"` – Preserve current elements that are shown in viewport
22
+ */
23
+ type ShowStrategy = "show" | "hide" | "ignore";
4
24
  export interface ViewStateCreateSettings {
5
25
  /**
6
26
  * Normally {@link createViewState} function invokes and awaits {@linkcode ViewState.load}
@@ -14,11 +34,25 @@ export interface ViewStateCreateSettings {
14
34
  */
15
35
  skipViewStateLoad?: boolean | undefined;
16
36
  /**
17
- * How to handle visibility of models and categories that exist in iModel but
18
- * not captured in Saved View data.
19
- * @default "hidden"
37
+ * How to handle the visibility of models that exist in iModel,
38
+ * including those not captured in Saved View data.
39
+ * Settings for how to handle the visibility of models in iModel.
40
+ * * `enabled` – Enabled is the set of enabled models that are stored in the saved view. Default is ignore.
41
+ * * `disabled` – Disabled is the set of disabled models that are stored in the saved view. Default is ignore.
42
+ * * `other` – Other is the set of models that are not stored in the saved view. Default is ignore.
43
+ * @default '{ enabled: "ignore", disabled: "ignore", other: "ignore" }'
44
+ */
45
+ models?: ApplyVisibilitySettings | undefined;
46
+ /**
47
+ * How to handle the visibility of categories that exist in iModel,
48
+ * including those not captured in Saved View data.
49
+ * Settings for how to handle the visibility of categories in iModel.
50
+ * * `enabled` – Enabled is the set of enabled categories that are stored in the saved view. Default is ignore.
51
+ * * `disabled` – Disabled is the set of disabled categories that are stored in the saved view. Default is ignore.
52
+ * * `other` – Other is the set of categories that are not stored in the saved view. Default is ignore.
53
+ * @default '{ enabled: "ignore", disabled: "ignore", other: "ignore" }'
20
54
  */
21
- modelAndCategoryVisibilityFallback?: "visible" | "hidden" | undefined;
55
+ categories?: ApplyVisibilitySettings | undefined;
22
56
  }
23
57
  /**
24
58
  * Creates {@link ViewStateProps} object out of Saved View data. It provides a lower-level
@@ -60,3 +94,4 @@ export declare function createViewStateFromProps(props: ViewStateProps, iModel:
60
94
  * await applySavedView(iModel, viewport, savedViewData);
61
95
  */
62
96
  export declare function createViewState(iModel: IModelConnection, viewData: ViewData, settings?: ViewStateCreateSettings): Promise<ViewState>;
97
+ export {};
@@ -25,9 +25,8 @@ export async function createViewStateProps(iModel, viewData) {
25
25
  return viewStateProps;
26
26
  }
27
27
  async function applyViewStateOptions(viewState, iModel, viewData, settings = {}) {
28
- if (settings.modelAndCategoryVisibilityFallback === "visible") {
29
- await unhideNewModelsAndCategories(iModel, viewState, viewData);
30
- }
28
+ await applyModelSettings(iModel, viewState, viewData, settings.models);
29
+ await applyCategorySettings(iModel, viewState, viewData, settings.categories);
31
30
  if (!settings.skipViewStateLoad) {
32
31
  await viewState.load();
33
32
  }
@@ -300,27 +299,100 @@ async function getDefaultViewIdFromClassName(iModel, viewClassName) {
300
299
  function cloneCode({ spec, scope, value }) {
301
300
  return { spec, scope, value };
302
301
  }
303
- async function unhideNewModelsAndCategories(iModel, viewState, viewData) {
302
+ /**
303
+ * Apply the model settings to the view state.
304
+ * This function modifies the model selector of the view state based on the provided settings.
305
+ * @param iModel The current IModelConnection.
306
+ * @param viewState The view state to modify.
307
+ * @param viewData The view data containing the lists of enabled and disabled models that will be applied.
308
+ * @param settings The settings for how to handle the visibility of enabled, disabled, and other model lists. Default is 'ignore' for all.
309
+ * @returns A promise that resolves when the model settings have been applied.
310
+ */
311
+ async function applyModelSettings(iModel, viewState, viewData, settings) {
304
312
  if (viewData.type === "iTwin3d") {
305
313
  if (!viewState.isSpatialView()) {
306
314
  return;
307
315
  }
308
- if (!viewData.categories?.disabled || !viewData.models?.disabled) {
316
+ const addModels = [];
317
+ const dropModels = [];
318
+ if (settings?.enabled === "show") {
319
+ addModels.push(...(viewData.models?.enabled ?? []));
320
+ }
321
+ else if (settings?.enabled === "hide") {
322
+ dropModels.push(...(viewData.models?.enabled ?? []));
323
+ }
324
+ if (settings?.disabled === "show") {
325
+ addModels.push(...(viewData.models?.disabled ?? []));
326
+ }
327
+ else if (settings?.disabled === "hide") {
328
+ dropModels.push(...(viewData.models?.disabled ?? []));
329
+ }
330
+ if (settings?.other !== "ignore") {
331
+ const otherModels = await queryMissingModels(iModel, new Set([
332
+ ...(viewData.models?.disabled ?? []),
333
+ ...(viewData.models?.enabled ?? []),
334
+ ]));
335
+ if (settings?.other === "show") {
336
+ addModels.push(...otherModels);
337
+ }
338
+ else if (settings?.other === "hide") {
339
+ dropModels.push(...otherModels);
340
+ }
341
+ }
342
+ if (addModels.length === 0 && dropModels.length === 0) {
309
343
  return;
310
344
  }
311
- const [visibleCategories, visibleModels] = await Promise.all([
312
- queryMissingCategories(iModel, new Set(viewData.categories.disabled)),
313
- queryMissingModels(iModel, new Set(viewData.models.disabled)),
314
- ]);
315
- viewState.categorySelector.addCategories(visibleCategories);
345
+ // Update model selector
316
346
  const modelSelector = viewState.modelSelector.clone();
317
- modelSelector.addModels(visibleModels);
347
+ modelSelector.addModels(addModels);
348
+ modelSelector.dropModels(dropModels);
318
349
  viewState.modelSelector = modelSelector;
319
350
  return;
320
351
  }
321
- if (!viewData.categories?.disabled) {
352
+ }
353
+ /**
354
+ * Apply the category settings to the view state.
355
+ * This function modifies the category selector of the view state based on the provided settings.
356
+ * @param iModel The current IModelConnection.
357
+ * @param viewState The view state to modify.
358
+ * @param viewData The view data containing the lists of enabled and disabled categories that will be applied.
359
+ * @param settings The settings for how to handle the visibility of enabled, disabled, and other category lists. Default is 'ignore' for all.
360
+ * @returns A promise that resolves when the category settings have been applied.
361
+ */
362
+ async function applyCategorySettings(iModel, viewState, viewData, settings) {
363
+ const addCategories = [];
364
+ const dropCategories = [];
365
+ if (settings?.enabled === "show") {
366
+ addCategories.push(...(viewData.categories?.enabled ?? []));
367
+ }
368
+ else if (settings?.enabled === "hide") {
369
+ dropCategories.push(...(viewData.categories?.enabled ?? []));
370
+ }
371
+ if (settings?.disabled === "show") {
372
+ addCategories.push(...(viewData.categories?.disabled ?? []));
373
+ }
374
+ else if (settings?.disabled === "hide") {
375
+ dropCategories.push(...(viewData.categories?.disabled ?? []));
376
+ }
377
+ if (settings?.other !== "ignore") {
378
+ const otherCategories = await queryMissingCategories(iModel, new Set([
379
+ ...(viewData.categories?.disabled ?? []),
380
+ ...(viewData.categories?.enabled ?? []),
381
+ ]));
382
+ if (settings?.other === "show") {
383
+ addCategories.push(...otherCategories);
384
+ }
385
+ else if (settings?.other === "hide") {
386
+ dropCategories.push(...otherCategories);
387
+ }
388
+ }
389
+ if (addCategories.length === 0 && dropCategories.length === 0) {
322
390
  return;
323
391
  }
324
- const visibleCategories = await queryMissingCategories(iModel, new Set(viewData.categories.disabled));
325
- viewState.categorySelector.addCategories(visibleCategories);
392
+ // Update model selector
393
+ const categorySelector = viewState.categorySelector.clone();
394
+ categorySelector.addCategories(addCategories);
395
+ categorySelector.dropCategories(dropCategories);
396
+ viewState.categorySelector = categorySelector;
397
+ return;
326
398
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itwin/saved-views-react",
3
- "version": "0.9.7",
3
+ "version": "1.0.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -68,7 +68,7 @@
68
68
  "@itwin/itwinui-icons-react": "^2.9.0",
69
69
  "@itwin/itwinui-react": "^3.15.0",
70
70
  "fuse.js": "^6.6.2",
71
- "@itwin/saved-views-client": "^0.5.1"
71
+ "@itwin/saved-views-client": "^0.5.2"
72
72
  },
73
73
  "scripts": {
74
74
  "build": "run-p build:*",