@itwin/saved-views-react 0.6.0 → 0.7.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 (38) hide show
  1. package/README.md +5 -20
  2. package/lib/SavedView.d.ts +20 -12
  3. package/lib/SavedViewTile/SavedViewOptions.js +10 -10
  4. package/lib/SavedViewTile/SavedViewTile.css +8 -1
  5. package/lib/SavedViewTile/SavedViewTile.d.ts +4 -3
  6. package/lib/SavedViewTile/SavedViewTile.js +4 -8
  7. package/lib/SavedViewTile/SavedViewTileContext.d.ts +0 -1
  8. package/lib/SavedViewTile/SavedViewTileContext.js +1 -1
  9. package/lib/SavedViewsClient/ITwinSavedViewsClient.d.ts +20 -22
  10. package/lib/SavedViewsClient/ITwinSavedViewsClient.js +81 -40
  11. package/lib/SavedViewsClient/SavedViewsClient.d.ts +55 -40
  12. package/lib/SavedViewsWidget/SavedViewGroupTile/SavedViewGroupTile.js +2 -3
  13. package/lib/SavedViewsWidget/SavedViewGroupTile/SavedViewGroupTileContext.d.ts +0 -1
  14. package/lib/SavedViewsWidget/SavedViewGroupTile/SavedViewGroupTileContext.js +1 -1
  15. package/lib/SavedViewsWidget/SavedViewsExpandableBlockWidget.d.ts +5 -3
  16. package/lib/SavedViewsWidget/SavedViewsExpandableBlockWidget.js +3 -3
  17. package/lib/SavedViewsWidget/SavedViewsFolderWidget.d.ts +5 -4
  18. package/lib/SavedViewsWidget/SavedViewsFolderWidget.js +7 -7
  19. package/lib/applySavedView.d.ts +33 -31
  20. package/lib/applySavedView.js +58 -23
  21. package/lib/captureSavedViewData.d.ts +12 -16
  22. package/lib/captureSavedViewData.js +76 -62
  23. package/lib/captureSavedViewThumbnail.d.ts +1 -1
  24. package/lib/captureSavedViewThumbnail.js +8 -7
  25. package/lib/createViewState.d.ts +8 -7
  26. package/lib/createViewState.js +16 -24
  27. package/lib/index.d.ts +10 -10
  28. package/lib/index.js +7 -7
  29. package/lib/translation/SavedViewTypes.d.ts +1 -1
  30. package/lib/translation/clipVectorsLegacyExtractor.js +4 -0
  31. package/lib/translation/displayStyleExtractor.js +8 -3
  32. package/lib/translation/extractionUtilities.d.ts +9 -1
  33. package/lib/translation/extractionUtilities.js +16 -0
  34. package/lib/useSavedViews.d.ts +171 -38
  35. package/lib/useSavedViews.js +460 -491
  36. package/lib/utils.d.ts +8 -1
  37. package/lib/utils.js +13 -0
  38. package/package.json +6 -6
@@ -3,23 +3,30 @@ import { extensionHandlers } from "./translation/SavedViewsExtensionHandlers.js"
3
3
  import { extractClipVectorsFromLegacy } from "./translation/clipVectorsLegacyExtractor.js";
4
4
  import { extractDisplayStyle2dFromLegacy, extractDisplayStyle3dFromLegacy, } from "./translation/displayStyleExtractor.js";
5
5
  /**
6
- * Captures current {@link Viewport} state into serializable format. The returned data can later be used to restore
7
- * viewport's view.
6
+ * Captures current {@link Viewport} state into serializable format. The returned
7
+ * data can later be used to restore viewport's view.
8
8
  *
9
9
  * @example
10
10
  * import { captureSavedViewData, captureSavedViewThumbnail } from "@itwin/saved-views-react";
11
11
  *
12
12
  * async function saveViewport(viewport) {
13
13
  * const { viewData, extensions = [] } = await captureSavedViewData({ viewport });
14
- * const myExtensions = captureMyCustomState(viewport);
14
+ * const myExtensions = captureMyCustomViewportState(viewport);
15
15
  * const thumbnail = captureSavedViewThumbnail(viewport);
16
16
  * return { thumbnail, viewData, extensions: extensions.concat(myExtensions) };
17
17
  * }
18
18
  */
19
19
  export async function captureSavedViewData(args) {
20
+ const extensions = [];
21
+ if (!args.omitEmphasis) {
22
+ extensions.push(extensionHandlers.emphasizeElements);
23
+ }
24
+ if (!args.omitPerModelCategoryVisibility) {
25
+ extensions.push(extensionHandlers.perModelCategoryVisibility);
26
+ }
20
27
  return {
21
28
  viewData: await createSavedViewVariant(args.viewport),
22
- extensions: [extensionHandlers.emphasizeElements, extensionHandlers.perModelCategoryVisibility]
29
+ extensions: extensions
23
30
  .map((extension) => ({
24
31
  extensionName: extension.extensionName,
25
32
  data: extension.capture(args.viewport),
@@ -28,11 +35,11 @@ export async function captureSavedViewData(args) {
28
35
  };
29
36
  }
30
37
  async function createSavedViewVariant(viewport) {
31
- const hiddenCategoriesPromise = getMissingCategories(viewport.iModel, new Set(viewport.view.categorySelector.toJSON().categories));
38
+ const hiddenCategoriesPromise = queryMissingCategories(viewport.iModel, new Set(viewport.view.categorySelector.toJSON().categories));
32
39
  if (viewport.view.isSpatialView()) {
33
40
  const [hiddenCategories, hiddenModels] = await Promise.all([
34
41
  hiddenCategoriesPromise,
35
- getMissingModels(viewport.iModel, new Set(viewport.view.modelSelector.toJSON().models)),
42
+ queryMissingModels(viewport.iModel, new Set(viewport.view.modelSelector.toJSON().models)),
36
43
  ]);
37
44
  return createSpatialSavedViewObject(viewport, hiddenCategories, hiddenModels);
38
45
  }
@@ -45,7 +52,8 @@ function createSpatialSavedViewObject(vp, hiddenCategories, hiddenModels) {
45
52
  const viewState = vp.view;
46
53
  const displayStyleProps = viewState.displayStyle.toJSON();
47
54
  // Clear the timePoint if no schedule script is available on the viewState
48
- if (viewState.is3d() && displayStyleProps.jsonProperties?.styles?.timePoint && !viewState.displayStyle.scheduleScript) {
55
+ if (viewState.is3d() && displayStyleProps.jsonProperties?.styles?.timePoint &&
56
+ !viewState.displayStyle.scheduleScript) {
49
57
  displayStyleProps.jsonProperties.styles.timePoint = undefined;
50
58
  }
51
59
  // Omit the schedule script - may cause excessively large JSON.
@@ -54,26 +62,25 @@ function createSpatialSavedViewObject(vp, hiddenCategories, hiddenModels) {
54
62
  }
55
63
  const viewDefinitionProps = viewState.toJSON();
56
64
  return {
57
- itwin3dView: {
58
- origin: toArrayVector3d(viewDefinitionProps.origin),
59
- extents: toArrayVector3d(viewDefinitionProps.extents),
60
- angles: viewDefinitionProps.angles && toYawPitchRoll(viewDefinitionProps.angles),
61
- camera: viewDefinitionProps.cameraOn ? {
62
- lens: toDegrees(viewDefinitionProps.camera.lens) ?? 0,
63
- focusDist: viewDefinitionProps.camera.focusDist,
64
- eye: toArrayVector3d(viewDefinitionProps.camera.eye),
65
- } : undefined,
66
- categories: {
67
- enabled: viewState.categorySelector.toJSON().categories,
68
- disabled: hiddenCategories,
69
- },
70
- models: {
71
- enabled: viewState.modelSelector.toJSON().models,
72
- disabled: hiddenModels,
73
- },
74
- displayStyle: extractDisplayStyle3dFromLegacy(displayStyleProps),
75
- clipVectors: extractClipVectorsFromLegacy(viewDefinitionProps),
65
+ type: "iTwin3d",
66
+ origin: toArrayVector3d(viewDefinitionProps.origin),
67
+ extents: toArrayVector3d(viewDefinitionProps.extents),
68
+ angles: viewDefinitionProps.angles && toYawPitchRoll(viewDefinitionProps.angles),
69
+ camera: viewDefinitionProps.cameraOn ? {
70
+ lens: toDegrees(viewDefinitionProps.camera.lens) ?? 0,
71
+ focusDist: viewDefinitionProps.camera.focusDist,
72
+ eye: toArrayVector3d(viewDefinitionProps.camera.eye),
73
+ } : undefined,
74
+ categories: {
75
+ enabled: viewState.categorySelector.toJSON().categories,
76
+ disabled: hiddenCategories,
77
+ },
78
+ models: {
79
+ enabled: viewState.modelSelector.toJSON().models,
80
+ disabled: hiddenModels,
76
81
  },
82
+ displayStyle: extractDisplayStyle3dFromLegacy(displayStyleProps),
83
+ clipVectors: extractClipVectorsFromLegacy(viewDefinitionProps),
77
84
  };
78
85
  }
79
86
  function toArrayVector3d(xyzProps) {
@@ -93,17 +100,16 @@ function createDrawingSavedViewObject(vp, hiddenCategories) {
93
100
  const viewState = vp.view;
94
101
  const viewDefinitionProps = viewState.toJSON();
95
102
  return {
96
- itwinDrawingView: {
97
- modelExtents: {},
98
- baseModelId: viewDefinitionProps.baseModelId,
99
- origin: toArrayVector2d(viewDefinitionProps.origin),
100
- delta: toArrayVector2d(viewDefinitionProps.delta),
101
- angle: toDegrees(viewDefinitionProps.angle) ?? 0,
102
- displayStyle: extractDisplayStyle2dFromLegacy(viewState.displayStyle.toJSON()),
103
- categories: {
104
- enabled: viewState.categorySelector.toJSON().categories,
105
- disabled: hiddenCategories,
106
- },
103
+ type: "iTwinDrawing",
104
+ modelExtents: {},
105
+ baseModelId: viewDefinitionProps.baseModelId,
106
+ origin: toArrayVector2d(viewDefinitionProps.origin),
107
+ delta: toArrayVector2d(viewDefinitionProps.delta),
108
+ angle: toDegrees(viewDefinitionProps.angle) ?? 0,
109
+ displayStyle: extractDisplayStyle2dFromLegacy(viewState.displayStyle.toJSON()),
110
+ categories: {
111
+ enabled: viewState.categorySelector.toJSON().categories,
112
+ disabled: hiddenCategories,
107
113
  },
108
114
  };
109
115
  }
@@ -111,20 +117,19 @@ function createSheetSavedViewObject(vp, hiddenCategories) {
111
117
  const viewState = vp.view;
112
118
  const viewDefinitionProps = viewState.toJSON();
113
119
  return {
114
- itwinSheetView: {
115
- baseModelId: viewDefinitionProps.baseModelId,
116
- origin: toArrayVector2d(viewDefinitionProps.origin),
117
- delta: toArrayVector2d(viewDefinitionProps.delta),
118
- angle: toDegrees(viewDefinitionProps.angle) ?? 0,
119
- displayStyle: extractDisplayStyle2dFromLegacy(viewState.displayStyle.toJSON()),
120
- categories: {
121
- enabled: viewState.categorySelector.toJSON().categories,
122
- disabled: hiddenCategories,
123
- },
124
- width: viewState.sheetSize.x,
125
- height: viewState.sheetSize.y,
126
- sheetAttachments: viewState.attachmentIds,
120
+ type: "iTwinSheet",
121
+ baseModelId: viewDefinitionProps.baseModelId,
122
+ origin: toArrayVector2d(viewDefinitionProps.origin),
123
+ delta: toArrayVector2d(viewDefinitionProps.delta),
124
+ angle: toDegrees(viewDefinitionProps.angle) ?? 0,
125
+ displayStyle: extractDisplayStyle2dFromLegacy(viewState.displayStyle.toJSON()),
126
+ categories: {
127
+ enabled: viewState.categorySelector.toJSON().categories,
128
+ disabled: hiddenCategories,
127
129
  },
130
+ width: viewState.sheetSize.x,
131
+ height: viewState.sheetSize.y,
132
+ sheetAttachments: viewState.attachmentIds,
128
133
  };
129
134
  }
130
135
  function toArrayVector2d(xyzProps) {
@@ -145,28 +150,37 @@ function toDegrees(angle) {
145
150
  }
146
151
  return undefined;
147
152
  }
148
- export async function getMissingModels(iModel, knownModels) {
149
- const allModels = await getAllModels(iModel);
150
- return allModels.map(({ id }) => id).filter((model) => !knownModels.has(model));
153
+ export async function queryMissingModels(iModel, knownModels) {
154
+ if (iModel.isBlank) {
155
+ return [];
156
+ }
157
+ const allModels = await queryAllSpatiallyLocatedModels(iModel);
158
+ return allModels.filter((modelId) => !knownModels.has(modelId));
151
159
  }
152
- async function getAllModels(iModel) {
153
- // Note: IsNotSpatiallyLocated was introduced in a later version of the BisCore ECSchema. If the iModel has an earlier
154
- // version, the statement will throw because the property does not exist. If the iModel was created from an earlier
155
- // version and later upgraded to a newer version, the property may be NULL for models created prior to the upgrade.
160
+ export async function queryAllSpatiallyLocatedModels(iModel) {
161
+ // BisCore ECSchema gained IsNotSpatiallyLocated property in 2019, almost exactly
162
+ // one year after the initial iTwin.js release. The following query will fail to
163
+ // compile with iModels created in that time frame unless user has performed
164
+ // schema upgrade which assigned NULL value to the property.
156
165
  try {
157
166
  return await executeQuery(iModel, "SELECT ECInstanceId FROM Bis.GeometricModel3D WHERE IsPrivate = false AND IsTemplate = false AND (IsNotSpatiallyLocated IS NULL OR IsNotSpatiallyLocated = false)");
158
167
  }
159
168
  catch {
169
+ // Above query failed, assume we have an old iModel
160
170
  return executeQuery(iModel, "SELECT ECInstanceId FROM Bis.GeometricModel3D WHERE IsPrivate = false AND IsTemplate = false");
161
171
  }
162
172
  }
163
- export async function getMissingCategories(iModel, knownCategories) {
164
- const allCategories = await getAllCategories(iModel);
165
- return allCategories.map(({ id }) => id).filter((category) => !knownCategories.has(category));
173
+ export async function queryMissingCategories(iModel, knownCategories) {
174
+ if (iModel.isBlank) {
175
+ return [];
176
+ }
177
+ const allCategories = await queryAllCategories(iModel);
178
+ return allCategories.filter((categoryId) => !knownCategories.has(categoryId));
166
179
  }
167
- async function getAllCategories(iModel) {
180
+ export async function queryAllCategories(iModel) {
168
181
  return executeQuery(iModel, "SELECT DISTINCT Category.Id AS id FROM BisCore.GeometricElement3d WHERE Category.Id IN (SELECT ECInstanceId FROM BisCore.SpatialCategory)");
169
182
  }
170
183
  async function executeQuery(iModel, query) {
171
- return iModel.createQueryReader(query, undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames }).toArray();
184
+ const result = await iModel.createQueryReader(query, undefined, { rowFormat: QueryRowFormat.UseECSqlPropertyIndexes }).toArray();
185
+ return result.flat();
172
186
  }
@@ -1,7 +1,7 @@
1
1
  import { type Viewport } from "@itwin/core-frontend";
2
2
  /**
3
3
  * Generates Saved View thumbnail based on what is currently displayed on the {@linkcode viewport}.
4
- * @returns base64-encoded URL string
4
+ * @returns base64-encoded URL string, or `undefined` if the thumbnail could not be generated
5
5
  *
6
6
  * @example
7
7
  * const thumbnail = captureSavedViewThumbnail(viewport);
@@ -2,7 +2,7 @@ import { getCenteredViewRect, imageBufferToCanvas } from "@itwin/core-frontend";
2
2
  import { Point2d } from "@itwin/core-geometry";
3
3
  /**
4
4
  * Generates Saved View thumbnail based on what is currently displayed on the {@linkcode viewport}.
5
- * @returns base64-encoded URL string
5
+ * @returns base64-encoded URL string, or `undefined` if the thumbnail could not be generated
6
6
  *
7
7
  * @example
8
8
  * const thumbnail = captureSavedViewThumbnail(viewport);
@@ -18,15 +18,16 @@ export function captureSavedViewThumbnail(viewport, width = 280, height = 200) {
18
18
  }
19
19
  function getThumbnail(vp, width, height) {
20
20
  const size = new Point2d(width, height);
21
- // Passing in vp.target.viewRect instead of vp.viewRect because currently vp.viewRect is not updated correctly in some
22
- // cases when a new dialog is created. The bottom property would be 2px higher than the renderRect in readImageBuffer
23
- // which caused the method to return undefined. vp.target.viewRect allows us to have the correct dimensions when
24
- // creating the thumbnail.
21
+ // Passing in vp.target.viewRect instead of vp.viewRect because currently vp.viewRect
22
+ // is not updated correctly in some cases when a new dialog is created. The bottom
23
+ // property would be 2px higher than the renderRect in readImageBuffer which
24
+ // caused the method to return undefined. vp.target.viewRect allows us to have
25
+ // the correct dimensions when creating the thumbnail.
25
26
  const thumbnail = vp.readImageBuffer({ rect: getCenteredViewRect(vp.target.viewRect), size });
26
27
  if (thumbnail) {
27
28
  return thumbnail;
28
29
  }
29
- // Since using vp.target.viewRect while creating thumbnail returns undefined for some, we switch back to using
30
- // vp.viewRect
30
+ // Since using vp.target.viewRect while creating thumbnail returns undefined
31
+ // for some, we switch back to using vp.viewRect
31
32
  return vp.readImageBuffer({ rect: getCenteredViewRect(vp.viewRect), size });
32
33
  }
@@ -1,26 +1,27 @@
1
1
  import { type IModelConnection, type ViewState } from "@itwin/core-frontend";
2
- import { ViewData } from "@itwin/saved-views-client";
2
+ import type { ViewData } from "./SavedView.js";
3
3
  export interface ViewStateCreateSettings {
4
4
  /**
5
- * Normally {@link createViewState} function invokes and awaits {@linkcode ViewState.load} method before returning.
6
- * You may skip this step if you intend to perform it later.
5
+ * Normally {@link createViewState} function invokes and awaits {@linkcode ViewState.load}
6
+ * method before returning. You may skip this step if you intend to perform it later.
7
7
  * @default false
8
8
  *
9
9
  * @example
10
- * const viewState = await createViewState(iModel, savedView.viewdata, { skipViewStateLoad: true });
10
+ * const viewState = await createViewState(iModel, savedViewData.viewData, { skipViewStateLoad: true });
11
11
  * viewState.categorySelector.addCategories("<additional_category_id>");
12
12
  * await viewState.load();
13
13
  */
14
14
  skipViewStateLoad?: boolean | undefined;
15
15
  /**
16
- * How to handle visibility of models and categories that exist in iModel but are not captured in Saved View data.
16
+ * How to handle visibility of models and categories that exist in iModel but
17
+ * not captured in Saved View data.
17
18
  * @default "hidden"
18
19
  */
19
20
  modelAndCategoryVisibilityFallback?: "visible" | "hidden" | undefined;
20
21
  }
21
22
  /**
22
- * Creates {@link ViewState} object out of Saved View data. It provides a lower-level access to view data for advanced
23
- * use.
23
+ * Creates {@link ViewState} object out of Saved View data. It provides a lower-level
24
+ * access to view data for advanced use.
24
25
  *
25
26
  * @example
26
27
  * const viewState = await createViewState(iModel, savedViewData.viewData);
@@ -2,15 +2,14 @@
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
- import { Camera, IModelReadRpcInterface, } from "@itwin/core-common";
5
+ import { Camera, } from "@itwin/core-common";
6
6
  import { DrawingViewState, SheetViewState, SpatialViewState, } from "@itwin/core-frontend";
7
- import { isViewDataITwin3d, isViewDataITwinDrawing, isViewDataITwinSheet, } from "@itwin/saved-views-client";
8
- import { getMissingCategories, getMissingModels } from "./captureSavedViewData.js";
7
+ import { queryMissingCategories, queryMissingModels } from "./captureSavedViewData.js";
9
8
  import { extractClipVectors } from "./translation/clipVectorsExtractor.js";
10
9
  import { extractDisplayStyle, extractDisplayStyle3d } from "./translation/displayStyleExtractor.js";
11
10
  /**
12
- * Creates {@link ViewState} object out of Saved View data. It provides a lower-level access to view data for advanced
13
- * use.
11
+ * Creates {@link ViewState} object out of Saved View data. It provides a lower-level
12
+ * access to view data for advanced use.
14
13
  *
15
14
  * @example
16
15
  * const viewState = await createViewState(iModel, savedViewData.viewData);
@@ -29,14 +28,14 @@ export async function createViewState(iModel, viewData, settings = {}) {
29
28
  }
30
29
  return viewState;
31
30
  }
32
- async function createViewStateVariant(iModel, savedViewData) {
33
- if (isViewDataITwinDrawing(savedViewData)) {
34
- return createDrawingViewState(iModel, savedViewData.itwinDrawingView);
31
+ async function createViewStateVariant(iModel, viewData) {
32
+ if (viewData.type === "iTwinDrawing") {
33
+ return createDrawingViewState(iModel, viewData);
35
34
  }
36
- if (isViewDataITwinSheet(savedViewData)) {
37
- return createSheetViewState(iModel, savedViewData.itwinSheetView);
35
+ if (viewData.type === "iTwinSheet") {
36
+ return createSheetViewState(iModel, viewData);
38
37
  }
39
- return createSpatialViewState(iModel, savedViewData.itwin3dView);
38
+ return createSpatialViewState(iModel, viewData);
40
39
  }
41
40
  async function createSpatialViewState(iModel, viewData) {
42
41
  const seedViewState = await fetchIModelViewData(iModel, SpatialViewState.classFullName);
@@ -213,10 +212,7 @@ function createEmptyViewState(iModel, viewClassName) {
213
212
  async function getDefaultViewIdFromClassName(iModel, viewClassName) {
214
213
  // Check validity of default view
215
214
  const viewId = await iModel.views.queryDefaultViewId();
216
- const params = {};
217
- params.from = viewClassName;
218
- params.where = "ECInstanceId=" + viewId;
219
- const viewProps = await IModelReadRpcInterface.getClient().queryElementProps(iModel.getRpcProps(), params);
215
+ const viewProps = await iModel.elements.queryProps({ from: viewClassName, where: "ECInstanceId=" + viewId });
220
216
  if (viewProps.length > 0) {
221
217
  return viewId;
222
218
  }
@@ -230,29 +226,25 @@ async function getDefaultViewIdFromClassName(iModel, viewClassName) {
230
226
  function cloneCode({ spec, scope, value }) {
231
227
  return { spec, scope, value };
232
228
  }
233
- async function unhideNewModelsAndCategories(iModel, viewState, savedViewData) {
234
- if (isViewDataITwin3d(savedViewData)) {
229
+ async function unhideNewModelsAndCategories(iModel, viewState, viewData) {
230
+ if (viewData.type === "iTwin3d") {
235
231
  if (!viewState.isSpatialView()) {
236
232
  return;
237
233
  }
238
- const viewData = savedViewData.itwin3dView;
239
234
  if (!viewData.categories?.disabled || !viewData.models?.disabled) {
240
235
  return;
241
236
  }
242
237
  const [visibleCategories, visibleModels] = await Promise.all([
243
- getMissingCategories(iModel, new Set(viewData.categories.disabled)),
244
- getMissingModels(iModel, new Set(viewData.models.disabled)),
238
+ queryMissingCategories(iModel, new Set(viewData.categories.disabled)),
239
+ queryMissingModels(iModel, new Set(viewData.models.disabled)),
245
240
  ]);
246
241
  viewState.categorySelector.addCategories(visibleCategories);
247
242
  viewState.modelSelector.addModels(visibleModels);
248
243
  return;
249
244
  }
250
- const viewData = isViewDataITwinDrawing(savedViewData)
251
- ? savedViewData.itwinDrawingView
252
- : savedViewData.itwinSheetView;
253
245
  if (!viewData.categories?.disabled) {
254
246
  return;
255
247
  }
256
- const visibleCategories = await getMissingCategories(iModel, new Set(viewData.categories.disabled));
248
+ const visibleCategories = await queryMissingCategories(iModel, new Set(viewData.categories.disabled));
257
249
  viewState.categorySelector.addCategories(visibleCategories);
258
250
  }
package/lib/index.d.ts CHANGED
@@ -1,16 +1,16 @@
1
+ export { applySavedView, type ApplySavedViewSettings } from "./applySavedView.js";
2
+ export { captureSavedViewData } from "./captureSavedViewData.js";
3
+ export { captureSavedViewThumbnail } from "./captureSavedViewThumbnail.js";
4
+ export { createViewState, type ViewStateCreateSettings } from "./createViewState.js";
1
5
  export { LayeredDropdownMenu, LayeredMenuItem } from "./LayeredDropdownMenu/LayeredDropdownMenu.js";
2
- export type { SavedView, SavedViewGroup, SavedViewTag } from "./SavedView.js";
6
+ export { defaultLocalization, type LocalizationStrings } from "./localization.js";
7
+ export type { ITwin3dViewData, ITwinDrawingdata, ITwinSheetData, SavedView, SavedViewData, SavedViewGroup, SavedViewTag, ViewData, } from "./SavedView.js";
8
+ export { ITwinSavedViewsClient } from "./SavedViewsClient/ITwinSavedViewsClient.js";
9
+ export type { CreateGroupArgs, CreateSavedViewArgs, CreateTagArgs, DeleteGroupArgs, DeleteSavedViewArgs, DeleteTagArgs, GetGroupsArgs, GetSavedViewByIdArgs, GetSavedViewsArgs, GetTagsArgs, GetThumbnailUrlArgs, SavedViewsClient, UpdateGroupArgs, UpdateSavedViewArgs, UpdateTagArgs, UploadThumbnailArgs, } from "./SavedViewsClient/SavedViewsClient.js";
10
+ export { SavedViewsContextProvider, type SavedViewsContext } from "./SavedViewsContext.js";
3
11
  export { SavedViewOptions } from "./SavedViewTile/SavedViewOptions.js";
4
12
  export { SavedViewTile } from "./SavedViewTile/SavedViewTile.js";
5
13
  export { useSavedViewTileContext, type SavedViewTileContext } from "./SavedViewTile/SavedViewTileContext.js";
6
- export { ITwinSavedViewsClient } from "./SavedViewsClient/ITwinSavedViewsClient.js";
7
- export type { CreateGroupParams, CreateSavedViewParams, CreateTagParams, DeleteGroupParams, DeleteSavedViewParams, DeleteTagParams, GetAllGroupsParams, GetAllSavedViewsParams, GetAllTagsParams, GetSavedViewParams, GetThumbnailUrlParams, SavedViewsClient, UpdateGroupParams, UpdateSavedViewParams, UpdateTagParams, UploadThumbnailParams, } from "./SavedViewsClient/SavedViewsClient.js";
8
- export { SavedViewsContextProvider, type SavedViewsContext } from "./SavedViewsContext.js";
9
14
  export { StickyExpandableBlock } from "./StickyExpandableBlock/StickyExpandableBlock.js";
10
15
  export { TileGrid } from "./TileGrid/TileGrid.js";
11
- export { applySavedView, type ApplySavedViewSettings } from "./applySavedView.js";
12
- export { captureSavedViewData } from "./captureSavedViewData.js";
13
- export { captureSavedViewThumbnail } from "./captureSavedViewThumbnail.js";
14
- export { createViewState, type ViewStateCreateSettings } from "./createViewState.js";
15
- export { defaultLocalization, type LocalizationStrings } from "./localization.js";
16
- export { useSavedViews, type SavedViewActions } from "./useSavedViews.js";
16
+ export { useSavedViews, type SavedViewsActions } from "./useSavedViews.js";
package/lib/index.js CHANGED
@@ -2,17 +2,17 @@
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
+ export { applySavedView } from "./applySavedView.js";
6
+ export { captureSavedViewData } from "./captureSavedViewData.js";
7
+ export { captureSavedViewThumbnail } from "./captureSavedViewThumbnail.js";
8
+ export { createViewState } from "./createViewState.js";
5
9
  export { LayeredDropdownMenu, LayeredMenuItem } from "./LayeredDropdownMenu/LayeredDropdownMenu.js";
10
+ export { defaultLocalization } from "./localization.js";
11
+ export { ITwinSavedViewsClient } from "./SavedViewsClient/ITwinSavedViewsClient.js";
12
+ export { SavedViewsContextProvider } from "./SavedViewsContext.js";
6
13
  export { SavedViewOptions } from "./SavedViewTile/SavedViewOptions.js";
7
14
  export { SavedViewTile } from "./SavedViewTile/SavedViewTile.js";
8
15
  export { useSavedViewTileContext } from "./SavedViewTile/SavedViewTileContext.js";
9
- export { ITwinSavedViewsClient } from "./SavedViewsClient/ITwinSavedViewsClient.js";
10
- export { SavedViewsContextProvider } from "./SavedViewsContext.js";
11
16
  export { StickyExpandableBlock } from "./StickyExpandableBlock/StickyExpandableBlock.js";
12
17
  export { TileGrid } from "./TileGrid/TileGrid.js";
13
- export { applySavedView } from "./applySavedView.js";
14
- export { captureSavedViewData } from "./captureSavedViewData.js";
15
- export { captureSavedViewThumbnail } from "./captureSavedViewThumbnail.js";
16
- export { createViewState } from "./createViewState.js";
17
- export { defaultLocalization } from "./localization.js";
18
18
  export { useSavedViews } from "./useSavedViews.js";
@@ -4,7 +4,6 @@ import type { Range3dProps } from "@itwin/core-geometry";
4
4
  export interface LegacySavedView3d extends LegacySavedViewBase {
5
5
  displayStyleProps: DisplayStyle3dProps;
6
6
  modelSelectorProps: ModelSelectorProps;
7
- modelExtents?: Range3dProps;
8
7
  viewDefinitionProps: SpatialViewDefinitionProps;
9
8
  perModelCategoryVisibility?: PerModelCategoryVisibilityProps[];
10
9
  hiddenModels?: Id64Array;
@@ -20,6 +19,7 @@ export interface LegacySavedView2d extends LegacySavedViewBase {
20
19
  sectionDrawing?: SectionDrawingViewProps;
21
20
  sheetProps?: SheetProps;
22
21
  sheetAttachments?: Id64Array;
22
+ modelExtents?: Range3dProps;
23
23
  }
24
24
  export interface LegacySavedViewBase {
25
25
  id: string;
@@ -6,6 +6,10 @@ export function extractClipVectorsFromLegacy(input) {
6
6
  }
7
7
  const output = {};
8
8
  applyExtraction(viewDetails, output, clipVectorLegacyMappings);
9
+ output.clipVectors = output.clipVectors?.filter((value) => {
10
+ const hasPlanes = "planes" in value;
11
+ return (!hasPlanes || (value.planes && Object.keys(value.planes).length > 0));
12
+ });
9
13
  return output.clipVectors;
10
14
  }
11
15
  const clipPlaneLegacyMappings = [
@@ -1,4 +1,4 @@
1
- import { applyExtraction, extractArray, extractArrayConditionally, extractBoolean, extractColor, extractColorLegacy, extractConditionally, extractNumber, extractNumberOrBool, extractObject, extractPlainTypedMap, extractRGB, extractSimpleArray, extractString, extractStringOrArray, extractStringOrNumber, extractStringOrNumberArray, isAnyColorFormat, simpleTypeOf, } from "./extractionUtilities.js";
1
+ import { applyExtraction, extractArray, extractArrayConditionally, extractBoolean, extractColor, extractColorLegacy, extractConditionally, extractLinePixels, extractNumber, extractNumberOrBool, extractObject, extractPlainTypedMap, extractRGB, extractSimpleArray, extractString, extractStringOrArray, extractStringOrNumber, extractStringOrNumberArray, isAnyColorFormat, simpleTypeOf, } from "./extractionUtilities.js";
2
2
  const viewFlagMappings = [
3
3
  extractNumber("renderMode"),
4
4
  extractBoolean("noConstructions", "noConstruct"),
@@ -111,7 +111,7 @@ export const featureAppearanceMappings = [
111
111
  extractRGB("rgb"),
112
112
  extractNumber("weight"),
113
113
  extractNumber("transparency"),
114
- extractNumber("linePixels"),
114
+ extractLinePixels("linePixels"),
115
115
  extractBoolean("ignoresMaterial"),
116
116
  extractBoolean("nonLocatable"),
117
117
  extractBoolean("emphasized"),
@@ -120,7 +120,7 @@ export const featureAppearanceLegacyMappings = [
120
120
  extractColorLegacy("rgb"),
121
121
  extractNumber("weight"),
122
122
  extractNumber("transparency"),
123
- extractNumber("linePixels"),
123
+ extractLinePixels("linePixels"),
124
124
  extractBoolean("ignoresMaterial"),
125
125
  extractBoolean("nonLocatable"),
126
126
  extractBoolean("emphasized"),
@@ -600,6 +600,11 @@ export const extractDisplayStyle3d = (data) => {
600
600
  styles = data.displayStyleProps.jsonProperties?.styles;
601
601
  applyExtraction(styles, output, displayStyle3dLegacyMapping);
602
602
  }
603
+ const range = output?.thematic?.range;
604
+ if (range && Array.isArray(range) && range.length === 0) {
605
+ // Range is optional, so delete it if it's empty
606
+ output.thematic.range = undefined;
607
+ }
603
608
  if (styles === undefined) {
604
609
  return undefined;
605
610
  }
@@ -38,7 +38,7 @@ export declare const transformRGB: (value: unknown) => Rgba | undefined;
38
38
  * @param transform Transform function of the value to be put in the output
39
39
  * @returns Function that does the extraction
40
40
  */
41
- export declare const createExtractionFunc: (from: string, to: string, typeCheck?: ((value: unknown) => boolean) | undefined, transform?: ((value: unknown) => unknown) | undefined) => (input: any, output: any) => void;
41
+ export declare const createExtractionFunc: (from: string, to: string, typeCheck?: (value: unknown) => boolean, transform?: (value: unknown) => unknown) => (input: any, output: any) => void;
42
42
  /** Type for a extraction function generator */
43
43
  export type ExtractionFunc<InputType, OutputType> = (input: InputType, output: OutputType) => OutputType;
44
44
  /** Type for a function that creates a extraction function */
@@ -51,6 +51,14 @@ export type ExtractionFuncCreator = (from: string, to: string) => ExtractionFunc
51
51
  * @returns Function that extracts a number value and type checks it
52
52
  */
53
53
  export declare const extractNumber: (from: string, to?: string) => ExtractionFunc<void, void>;
54
+ /**
55
+ * Creates a extraction function that will extract a number from the given accessor, transform it into a LinePixels enum, and put it
56
+ * in the given accessor if provided
57
+ * @param from Accessor that will be used on input to access value
58
+ * @param to Accessor that will be used to stored the value in the output object
59
+ * @returns Function that extracts a number value and type checks it
60
+ */
61
+ export declare const extractLinePixels: (from: string, to?: string) => ExtractionFunc<void, void>;
54
62
  /**
55
63
  * Creates a extraction function that will extract a boolean from the given accessor and put it
56
64
  * in the given accessor if provided
@@ -3,6 +3,7 @@
3
3
  * See LICENSE.md in the project root for license terms and full copyright notice.
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  import { ColorDef } from "@itwin/core-common";
6
+ import { LinePixels } from "@itwin/saved-views-client";
6
7
  /**
7
8
  * Returns a function that does a simple typeof check on a value
8
9
  * @param typeOfString String to compare against
@@ -231,6 +232,21 @@ export const createExtractionFunc = (from, to, typeCheck, transform) => {
231
232
  export const extractNumber = (from, to) => {
232
233
  return createExtractionFunc(from, to ?? from, simpleTypeOf("number"));
233
234
  };
235
+ /**
236
+ * Creates a extraction function that will extract a number from the given accessor, transform it into a LinePixels enum, and put it
237
+ * in the given accessor if provided
238
+ * @param from Accessor that will be used on input to access value
239
+ * @param to Accessor that will be used to stored the value in the output object
240
+ * @returns Function that extracts a number value and type checks it
241
+ */
242
+ export const extractLinePixels = (from, to) => {
243
+ return createExtractionFunc(from, to ?? from, simpleTypeOf("number"), (value) => {
244
+ if (typeof value !== "number" ||
245
+ !Object.keys(LinePixels).includes(value.toString()))
246
+ return LinePixels.Invalid;
247
+ return value;
248
+ });
249
+ };
234
250
  /**
235
251
  * Creates a extraction function that will extract a boolean from the given accessor and put it
236
252
  * in the given accessor if provided