@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.
- package/README.md +5 -20
- package/lib/SavedView.d.ts +20 -12
- package/lib/SavedViewTile/SavedViewOptions.js +10 -10
- package/lib/SavedViewTile/SavedViewTile.css +8 -1
- package/lib/SavedViewTile/SavedViewTile.d.ts +4 -3
- package/lib/SavedViewTile/SavedViewTile.js +4 -8
- package/lib/SavedViewTile/SavedViewTileContext.d.ts +0 -1
- package/lib/SavedViewTile/SavedViewTileContext.js +1 -1
- package/lib/SavedViewsClient/ITwinSavedViewsClient.d.ts +20 -22
- package/lib/SavedViewsClient/ITwinSavedViewsClient.js +81 -40
- package/lib/SavedViewsClient/SavedViewsClient.d.ts +55 -40
- package/lib/SavedViewsWidget/SavedViewGroupTile/SavedViewGroupTile.js +2 -3
- package/lib/SavedViewsWidget/SavedViewGroupTile/SavedViewGroupTileContext.d.ts +0 -1
- package/lib/SavedViewsWidget/SavedViewGroupTile/SavedViewGroupTileContext.js +1 -1
- package/lib/SavedViewsWidget/SavedViewsExpandableBlockWidget.d.ts +5 -3
- package/lib/SavedViewsWidget/SavedViewsExpandableBlockWidget.js +3 -3
- package/lib/SavedViewsWidget/SavedViewsFolderWidget.d.ts +5 -4
- package/lib/SavedViewsWidget/SavedViewsFolderWidget.js +7 -7
- package/lib/applySavedView.d.ts +33 -31
- package/lib/applySavedView.js +58 -23
- package/lib/captureSavedViewData.d.ts +12 -16
- package/lib/captureSavedViewData.js +76 -62
- package/lib/captureSavedViewThumbnail.d.ts +1 -1
- package/lib/captureSavedViewThumbnail.js +8 -7
- package/lib/createViewState.d.ts +8 -7
- package/lib/createViewState.js +16 -24
- package/lib/index.d.ts +10 -10
- package/lib/index.js +7 -7
- package/lib/translation/SavedViewTypes.d.ts +1 -1
- package/lib/translation/clipVectorsLegacyExtractor.js +4 -0
- package/lib/translation/displayStyleExtractor.js +8 -3
- package/lib/translation/extractionUtilities.d.ts +9 -1
- package/lib/translation/extractionUtilities.js +16 -0
- package/lib/useSavedViews.d.ts +171 -38
- package/lib/useSavedViews.js +460 -491
- package/lib/utils.d.ts +8 -1
- package/lib/utils.js +13 -0
- package/package.json +6 -6
|
@@ -1,38 +1,39 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { PartialExcept } from "../utils.js";
|
|
1
|
+
import type { SavedViewData, SavedViewGroup, SavedView, SavedViewTag } from "../SavedView.js";
|
|
3
2
|
export interface SavedViewsClient {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
getThumbnailUrl: (args:
|
|
8
|
-
uploadThumbnail: (args:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
3
|
+
getSavedViews: (args: GetSavedViewsArgs) => AsyncIterableIterator<SavedView[]>;
|
|
4
|
+
getGroups: (args: GetGroupsArgs) => Promise<SavedViewGroup[]>;
|
|
5
|
+
getTags: (args: GetTagsArgs) => Promise<SavedViewTag[]>;
|
|
6
|
+
getThumbnailUrl: (args: GetThumbnailUrlArgs) => Promise<string | undefined>;
|
|
7
|
+
uploadThumbnail: (args: UploadThumbnailArgs) => Promise<void>;
|
|
8
|
+
getSavedViewById: (args: GetSavedViewByIdArgs) => Promise<SavedView>;
|
|
9
|
+
getSavedViewDataById: (args: GetSavedViewDataByIdArgs) => Promise<SavedViewData>;
|
|
10
|
+
createSavedView: (args: CreateSavedViewArgs) => Promise<SavedView>;
|
|
11
|
+
updateSavedView: (args: UpdateSavedViewArgs) => Promise<SavedView>;
|
|
12
|
+
deleteSavedView: (args: DeleteSavedViewArgs) => Promise<void>;
|
|
13
|
+
createGroup: (args: CreateGroupArgs) => Promise<SavedViewGroup>;
|
|
14
|
+
updateGroup: (args: UpdateGroupArgs) => Promise<SavedViewGroup>;
|
|
15
|
+
deleteGroup: (args: DeleteGroupArgs) => Promise<void>;
|
|
16
|
+
createTag: (args: CreateTagArgs) => Promise<SavedViewTag>;
|
|
17
|
+
updateTag: (args: UpdateTagArgs) => Promise<SavedViewTag>;
|
|
18
|
+
deleteTag: (args: DeleteTagArgs) => Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export interface GetSavedViewsArgs extends CommonParams {
|
|
21
21
|
iTwinId: string;
|
|
22
22
|
iModelId?: string | undefined;
|
|
23
|
+
groupId?: string | undefined;
|
|
23
24
|
}
|
|
24
|
-
export interface
|
|
25
|
+
export interface GetGroupsArgs extends CommonParams {
|
|
25
26
|
iTwinId: string;
|
|
26
27
|
iModelId?: string | undefined;
|
|
27
28
|
}
|
|
28
|
-
export interface
|
|
29
|
+
export interface GetTagsArgs extends CommonParams {
|
|
29
30
|
iTwinId: string;
|
|
30
31
|
iModelId?: string | undefined;
|
|
31
32
|
}
|
|
32
|
-
export interface
|
|
33
|
+
export interface GetThumbnailUrlArgs extends CommonParams {
|
|
33
34
|
savedViewId: string;
|
|
34
35
|
}
|
|
35
|
-
export interface
|
|
36
|
+
export interface UploadThumbnailArgs extends CommonParams {
|
|
36
37
|
savedViewId: string;
|
|
37
38
|
/**
|
|
38
39
|
* Image data encoded as base64 data URL.
|
|
@@ -42,42 +43,56 @@ export interface UploadThumbnailParams extends CommonParams {
|
|
|
42
43
|
*/
|
|
43
44
|
image: string;
|
|
44
45
|
}
|
|
45
|
-
export interface
|
|
46
|
+
export interface GetSavedViewByIdArgs extends CommonParams {
|
|
46
47
|
savedViewId: string;
|
|
47
48
|
}
|
|
48
|
-
export interface
|
|
49
|
+
export interface GetSavedViewDataByIdArgs extends CommonParams {
|
|
50
|
+
savedViewId: string;
|
|
51
|
+
}
|
|
52
|
+
export interface CreateSavedViewArgs extends CommonParams {
|
|
49
53
|
iTwinId: string;
|
|
50
54
|
iModelId?: string | undefined;
|
|
51
|
-
|
|
55
|
+
displayName: string;
|
|
56
|
+
groupId?: string | undefined;
|
|
57
|
+
tagIds?: string[] | undefined;
|
|
58
|
+
shared?: boolean | undefined;
|
|
59
|
+
savedViewData: SavedViewData;
|
|
52
60
|
}
|
|
53
|
-
export interface
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
export interface UpdateSavedViewArgs extends CommonParams {
|
|
62
|
+
savedViewId: string;
|
|
63
|
+
displayName?: string | undefined;
|
|
64
|
+
groupId?: string | undefined;
|
|
65
|
+
tagIds?: string[] | undefined;
|
|
66
|
+
shared?: boolean | undefined;
|
|
67
|
+
savedViewData?: SavedViewData | undefined;
|
|
57
68
|
}
|
|
58
|
-
export interface
|
|
69
|
+
export interface DeleteSavedViewArgs extends CommonParams {
|
|
59
70
|
savedViewId: string;
|
|
60
71
|
}
|
|
61
|
-
export interface
|
|
72
|
+
export interface CreateGroupArgs extends CommonParams {
|
|
62
73
|
iTwinId: string;
|
|
63
74
|
iModelId?: string | undefined;
|
|
64
|
-
|
|
75
|
+
displayName: string;
|
|
76
|
+
shared?: boolean | undefined;
|
|
65
77
|
}
|
|
66
|
-
export interface
|
|
67
|
-
|
|
78
|
+
export interface UpdateGroupArgs extends CommonParams {
|
|
79
|
+
groupId: string;
|
|
80
|
+
displayName?: string | undefined;
|
|
81
|
+
shared?: boolean | undefined;
|
|
68
82
|
}
|
|
69
|
-
export interface
|
|
83
|
+
export interface DeleteGroupArgs extends CommonParams {
|
|
70
84
|
groupId: string;
|
|
71
85
|
}
|
|
72
|
-
export interface
|
|
86
|
+
export interface CreateTagArgs extends CommonParams {
|
|
73
87
|
iTwinId: string;
|
|
74
88
|
iModelId?: string;
|
|
75
89
|
displayName: string;
|
|
76
90
|
}
|
|
77
|
-
export interface
|
|
78
|
-
|
|
91
|
+
export interface UpdateTagArgs extends CommonParams {
|
|
92
|
+
tagId: string;
|
|
93
|
+
displayName?: string | undefined;
|
|
79
94
|
}
|
|
80
|
-
export interface
|
|
95
|
+
export interface DeleteTagArgs extends CommonParams {
|
|
81
96
|
tagId: string;
|
|
82
97
|
}
|
|
83
98
|
interface CommonParams {
|
|
@@ -23,15 +23,14 @@ export function SavedViewGroupTile(props) {
|
|
|
23
23
|
},
|
|
24
24
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
25
25
|
[]);
|
|
26
|
-
const dispatchOpenGroup = () => props.onOpen(props.group.id);
|
|
27
26
|
const savedViewGroupTileContext = useMemo(() => ({ group: props.group, setEditingName }), [props.group]);
|
|
28
27
|
return (_jsx(SavedViewGroupTileContextProvider, { value: savedViewGroupTileContext, children: _jsx("div", { ref: divRef, children: _jsx(Tile, { className: "svr-folder", variant: "folder", name: _jsx(EditableTileName, { displayName: props.group.displayName, editable: props.editable || editingName, editing: editingName, actions: {
|
|
29
28
|
onStartEditing: () => setEditingName(true),
|
|
30
29
|
onEndEditing: (newName) => {
|
|
31
30
|
setEditingName(false);
|
|
32
31
|
if (newName !== props.group.displayName) {
|
|
33
|
-
props.onRename?.(props.group.
|
|
32
|
+
props.onRename?.(props.group.groupId, newName);
|
|
34
33
|
}
|
|
35
34
|
},
|
|
36
|
-
} }), thumbnail: _jsx(SvgFolder, { className: "iui-thumbnail-icon" }), isActionable: !props.editable && !editingName, moreOptions: (props.options && props.options.length > 0) ? props.options : undefined, onClick:
|
|
35
|
+
} }), thumbnail: _jsx(SvgFolder, { className: "iui-thumbnail-icon" }), isActionable: !props.editable && !editingName, moreOptions: (props.options && props.options.length > 0) ? props.options : undefined, onClick: () => props.onOpen(props.group.groupId), children: _jsxs(Text, { isMuted: true, children: [props.numItems, " items"] }) }) }) }));
|
|
37
36
|
}
|
|
@@ -14,7 +14,7 @@ export const SavedViewGroupTileContextProvider = savedViewGroupTileContext.Provi
|
|
|
14
14
|
export function useSavedViewGroupTileContext() {
|
|
15
15
|
const contextValue = useContext(savedViewGroupTileContext);
|
|
16
16
|
return contextValue ?? {
|
|
17
|
-
group: {
|
|
17
|
+
group: { groupId: "SavedViewGroupTileContext_NoContext", displayName: "" },
|
|
18
18
|
setEditingName: () => { },
|
|
19
19
|
};
|
|
20
20
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { type ReactElement, type ReactNode } from "react";
|
|
2
2
|
import type { SavedView, SavedViewGroup, SavedViewTag } from "../SavedView.js";
|
|
3
|
-
import type {
|
|
3
|
+
import type { SavedViewsActions } from "../useSavedViews.js";
|
|
4
4
|
import "./SavedViewsExpandableBlockWidget.css";
|
|
5
5
|
interface SavedViewsExpandableBlockWidgetProps {
|
|
6
6
|
savedViews: Map<string, SavedView>;
|
|
7
7
|
groups: Map<string, SavedViewGroup>;
|
|
8
8
|
tags: Map<string, SavedViewTag>;
|
|
9
|
-
|
|
9
|
+
thumbnails: Map<string, ReactNode>;
|
|
10
|
+
actions?: Partial<SavedViewsActions> | undefined;
|
|
10
11
|
editable?: boolean | undefined;
|
|
11
12
|
options?: ((savedView: SavedView) => (((close: () => void) => ReactElement[]) | ReactElement[])) | undefined;
|
|
12
13
|
}
|
|
@@ -16,8 +17,9 @@ interface SavedViewsGroupProps {
|
|
|
16
17
|
savedViews: Map<string, SavedView>;
|
|
17
18
|
groups: Map<string, SavedViewGroup>;
|
|
18
19
|
tags: Map<string, SavedViewTag>;
|
|
20
|
+
thumbnails: Map<string, ReactNode>;
|
|
19
21
|
expanded?: boolean | undefined;
|
|
20
|
-
actions?: Partial<
|
|
22
|
+
actions?: Partial<SavedViewsActions> | undefined;
|
|
21
23
|
editable?: boolean | undefined;
|
|
22
24
|
options?: ((savedView: SavedView) => (((close: () => void) => ReactElement[]) | ReactElement[])) | undefined;
|
|
23
25
|
}
|
|
@@ -11,11 +11,11 @@ import { StickyExpandableBlock } from "../StickyExpandableBlock/StickyExpandable
|
|
|
11
11
|
import { TileGrid } from "../TileGrid/TileGrid.js";
|
|
12
12
|
import "./SavedViewsExpandableBlockWidget.css";
|
|
13
13
|
export function SavedViewsExpandableBlockWidget(props) {
|
|
14
|
-
return (_jsxs("div", { className: "svr-saved-views-widget", children: [_jsx(SavedViewsGroup, { group: undefined, savedViews: props.savedViews, actions: props.actions, groups: props.groups, tags: props.tags, editable: props.editable, options: props.options, expanded: true }), [...props.groups.values()].map((group) => _jsx(SavedViewsGroup, { group: group, savedViews: props.savedViews, groups: props.groups, tags: props.tags, actions: props.actions, editable: props.editable, options: props.options }, group.
|
|
14
|
+
return (_jsxs("div", { className: "svr-saved-views-widget", children: [_jsx(SavedViewsGroup, { group: undefined, savedViews: props.savedViews, actions: props.actions, groups: props.groups, tags: props.tags, thumbnails: props.thumbnails, editable: props.editable, options: props.options, expanded: true }), [...props.groups.values()].map((group) => _jsx(SavedViewsGroup, { group: group, savedViews: props.savedViews, groups: props.groups, tags: props.tags, thumbnails: props.thumbnails, actions: props.actions, editable: props.editable, options: props.options }, group.groupId))] }));
|
|
15
15
|
}
|
|
16
16
|
export function SavedViewsGroup(props) {
|
|
17
|
-
const savedViews = [...props.savedViews.values()].filter(({ groupId }) => groupId === props.group?.
|
|
18
|
-
return (_jsx(BorderlessExpandableBlock, { displayName: props.group?.displayName ?? "Ungrouped", numItems: savedViews.length, expanded: props.expanded, shared: props.group?.shared, editable: props.editable, children: _jsx(TileGrid, { gridItems: savedViews, children: (savedView) => (_jsx(SavedViewTile, { savedView: savedView, tags: props.tags, editable: props.editable, onRename: props.actions?.renameSavedView, options: props.options?.(savedView) }, savedView.
|
|
17
|
+
const savedViews = [...props.savedViews.values()].filter(({ groupId }) => groupId === props.group?.groupId);
|
|
18
|
+
return (_jsx(BorderlessExpandableBlock, { displayName: props.group?.displayName ?? "Ungrouped", numItems: savedViews.length, expanded: props.expanded, shared: props.group?.shared, editable: props.editable, children: _jsx(TileGrid, { gridItems: savedViews, children: (savedView) => (_jsx(SavedViewTile, { savedView: savedView, thumbnail: props.thumbnails.get(savedView.savedViewId), tags: props.tags, editable: props.editable, onRename: props.actions?.renameSavedView, options: props.options?.(savedView) }, savedView.savedViewId)) }) }));
|
|
19
19
|
}
|
|
20
20
|
export function BorderlessExpandableBlock(props) {
|
|
21
21
|
const handleEditGroupClick = (closeDropdown) => {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { type ReactElement } from "react";
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
1
|
+
import { type ReactElement, type ReactNode } from "react";
|
|
2
|
+
import type { SavedViewGroup, SavedView, SavedViewTag } from "../SavedView.js";
|
|
3
|
+
import type { SavedViewsActions } from "../useSavedViews.js";
|
|
4
4
|
interface SavedViewsFolderWidgetProps {
|
|
5
5
|
savedViews: Map<string, SavedView>;
|
|
6
6
|
groups: Map<string, SavedViewGroup>;
|
|
7
7
|
tags: Map<string, SavedViewTag>;
|
|
8
|
-
|
|
8
|
+
thumbnails: Map<string, ReactNode>;
|
|
9
|
+
actions?: Partial<SavedViewsActions> | undefined;
|
|
9
10
|
editable?: boolean | undefined;
|
|
10
11
|
options?: ((savedView: SavedView) => (((close: () => void) => ReactElement[]) | ReactElement[])) | undefined;
|
|
11
12
|
onTileClick?: ((selectedViewId: string) => void) | undefined;
|
|
@@ -29,16 +29,16 @@ export function SavedViewsFolderWidget(props) {
|
|
|
29
29
|
const handleGroupOpen = useCallback((activeGroupId) => setState({ activeGroupId, focusedGroupId: undefined }), []);
|
|
30
30
|
const activeGroup = state.activeGroupId !== undefined && props.groups.get(state.activeGroupId);
|
|
31
31
|
if (!activeGroup) {
|
|
32
|
-
return (_jsx(SavedViewsHomeScreen, { groupedSavedViews: groupedSavedViews, groups: props.groups, tags: props.tags, focusedGroupId: state.focusedGroupId, clearFocusedGroup: () => setState(({ activeGroupId }) => ({ activeGroupId, focusedGroupId: undefined })), onGroupOpen: handleGroupOpen, initialScrollTop: storedScrollOffset, storeScrollOffset: setStoredScrollOffset, actions: props.actions, editable: props.editable, savedViewOptions: props.options, onTileClick: props.onTileClick }));
|
|
32
|
+
return (_jsx(SavedViewsHomeScreen, { groupedSavedViews: groupedSavedViews, groups: props.groups, tags: props.tags, thumbnails: props.thumbnails, focusedGroupId: state.focusedGroupId, clearFocusedGroup: () => setState(({ activeGroupId }) => ({ activeGroupId, focusedGroupId: undefined })), onGroupOpen: handleGroupOpen, initialScrollTop: storedScrollOffset, storeScrollOffset: setStoredScrollOffset, actions: props.actions, editable: props.editable, savedViewOptions: props.options, onTileClick: props.onTileClick }));
|
|
33
33
|
}
|
|
34
|
-
return (_jsx(SavedViewsGroupScreen, { activeGroup: activeGroup, groups: props.groups, tags: props.tags, savedViews: groupedSavedViews.get(activeGroup.
|
|
34
|
+
return (_jsx(SavedViewsGroupScreen, { activeGroup: activeGroup, groups: props.groups, tags: props.tags, thumbnails: props.thumbnails, savedViews: groupedSavedViews.get(activeGroup.groupId) ?? [], setActiveGroup: (activeGroupId) => setState({ activeGroupId, focusedGroupId: state.activeGroupId }), actions: props.actions, editable: props.editable, options: props.options, onTileClick: props.onTileClick }, activeGroup.groupId));
|
|
35
35
|
}
|
|
36
36
|
function SavedViewsHomeScreen(props) {
|
|
37
37
|
const ungroupedSavedViews = props.groupedSavedViews.get(undefined) ?? [];
|
|
38
|
-
const groupTiles = useMemo(() => [...props.groups.values()].map((group) => _jsx(SavedViewGroupTile, { group: group, numItems: props.groupedSavedViews.get(group.
|
|
38
|
+
const groupTiles = useMemo(() => [...props.groups.values()].map((group) => _jsx(SavedViewGroupTile, { group: group, numItems: props.groupedSavedViews.get(group.groupId)?.length ?? 0, onOpen: props.onGroupOpen, focused: group.groupId === props.focusedGroupId, initialScrollTop: props.initialScrollTop, editable: props.editable, options: [
|
|
39
39
|
_jsx(SavedViewGroupOptions.Rename, {}, "rename"),
|
|
40
|
-
_jsx(MenuItem, { onClick: () => props.actions?.deleteGroup?.(group.
|
|
41
|
-
], onRename: props.actions?.renameGroup }, group.
|
|
40
|
+
_jsx(MenuItem, { onClick: () => props.actions?.deleteGroup?.(group.groupId), children: "Delete" }, "delete"),
|
|
41
|
+
], onRename: props.actions?.renameGroup }, group.groupId)), [
|
|
42
42
|
props.groups,
|
|
43
43
|
props.groupedSavedViews,
|
|
44
44
|
props.onGroupOpen,
|
|
@@ -47,7 +47,7 @@ function SavedViewsHomeScreen(props) {
|
|
|
47
47
|
props.editable,
|
|
48
48
|
props.actions,
|
|
49
49
|
]);
|
|
50
|
-
return (_jsxs("div", { className: "svr-saved-views-widget", style: { overflow: "auto" }, onScroll: (event) => props.storeScrollOffset(event.target.scrollTop), children: [_jsx(BorderlessExpandableBlock, { displayName: "Saved views", numItems: ungroupedSavedViews.length, expanded: true, children: _jsx(TileGrid, { gridItems: ungroupedSavedViews, children: (savedView) => _jsx(SavedViewTile, { savedView: savedView, tags: props.tags, editable: props.editable, onRename: props.actions?.renameSavedView, options: props.savedViewOptions?.(savedView), onClick: props.onTileClick }, savedView.
|
|
50
|
+
return (_jsxs("div", { className: "svr-saved-views-widget", style: { overflow: "auto" }, onScroll: (event) => props.storeScrollOffset(event.target.scrollTop), children: [_jsx(BorderlessExpandableBlock, { displayName: "Saved views", numItems: ungroupedSavedViews.length, expanded: true, children: _jsx(TileGrid, { gridItems: ungroupedSavedViews, children: (savedView) => _jsx(SavedViewTile, { savedView: savedView, thumbnail: props.thumbnails.get(savedView.savedViewId), tags: props.tags, editable: props.editable, onRename: props.actions?.renameSavedView, options: props.savedViewOptions?.(savedView), onClick: props.onTileClick }, savedView.savedViewId) }) }), _jsx(BorderlessExpandableBlock, { className: "svr-group-grid", displayName: "Groups", numItems: props.groups.size, expanded: true, onExpandToggle: (expanded) => !expanded && props.clearFocusedGroup?.(), editable: props.editable, children: _jsx("div", { className: "svr-tile-grid", children: groupTiles }) })] }));
|
|
51
51
|
}
|
|
52
52
|
function SavedViewsGroupScreen(props) {
|
|
53
53
|
const groups = useMemo(() => [...props.groups.values()], [props.groups]);
|
|
@@ -56,5 +56,5 @@ function SavedViewsGroupScreen(props) {
|
|
|
56
56
|
gap: "var(--iui-size-s)",
|
|
57
57
|
background: "var(--iui-color-background)",
|
|
58
58
|
padding: "var(--iui-size-s)",
|
|
59
|
-
}, children: [_jsx(Button, { styleType: "borderless", startIcon: _jsx(SvgChevronLeft, {}), onClick: () => props.setActiveGroup(undefined), children: "Back" }), _jsxs(Breadcrumbs, { children: [_jsx(IconButton, { styleType: "borderless", onClick: () => props.setActiveGroup(undefined), children: _jsx(SvgHome, {}) }), _jsx(DropdownButton, { styleType: "borderless", menuItems: (close) => groups.map((group) => _jsx(MenuItem, { onClick: () => { close(); props.setActiveGroup(group.
|
|
59
|
+
}, children: [_jsx(Button, { styleType: "borderless", startIcon: _jsx(SvgChevronLeft, {}), onClick: () => props.setActiveGroup(undefined), children: "Back" }), _jsxs(Breadcrumbs, { children: [_jsx(IconButton, { styleType: "borderless", onClick: () => props.setActiveGroup(undefined), children: _jsx(SvgHome, {}) }), _jsx(DropdownButton, { styleType: "borderless", menuItems: (close) => groups.map((group) => _jsx(MenuItem, { onClick: () => { close(); props.setActiveGroup(group.groupId); }, children: group.displayName }, group.groupId)), children: props.activeGroup.displayName })] })] }), _jsx("div", { style: { overflow: "auto" }, children: _jsx(TileGrid, { gridItems: props.savedViews, children: (savedView) => (_jsx(SavedViewTile, { savedView: savedView, thumbnail: props.thumbnails.get(savedView.savedViewId), tags: props.tags, editable: props.editable, options: props.options?.(savedView), onClick: props.onTileClick }, savedView.savedViewId)) }) })] }));
|
|
60
60
|
}
|
package/lib/applySavedView.d.ts
CHANGED
|
@@ -1,67 +1,69 @@
|
|
|
1
|
-
import { ViewState, type IModelConnection, type Viewport } from "@itwin/core-frontend";
|
|
2
|
-
import type {
|
|
1
|
+
import { ViewChangeOptions, ViewPose, ViewState, type IModelConnection, type Viewport } from "@itwin/core-frontend";
|
|
2
|
+
import type { SavedViewData } from "./SavedView.js";
|
|
3
3
|
export interface ApplySavedViewSettings {
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* How to make use of captured {@link ViewState} data. The default behavior is
|
|
6
|
+
* to generate a new `ViewState` object out of {@linkcode SavedViewData.viewData}
|
|
7
|
+
* and apply it to viewport.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
* await applySavedView(iModel, viewport, savedView, { all: "keep", viewState: "apply" });
|
|
11
|
-
*/
|
|
12
|
-
all?: ApplyStrategy | undefined;
|
|
13
|
-
/**
|
|
14
|
-
* How to handle captured {@link ViewState} data. The default behavior is to generate a new `ViewState` object out of
|
|
15
|
-
* {@linkcode SavedView.viewData} and apply it to viewport.
|
|
9
|
+
* You can optionally provide a pre-made `ViewState` instance.
|
|
16
10
|
*
|
|
17
|
-
*
|
|
18
|
-
* {@link createViewState} result.
|
|
11
|
+
* @default "apply"
|
|
19
12
|
*
|
|
20
13
|
* @example
|
|
21
14
|
* import { applySavedView, createViewState } from "@itwin/saved-views-react";
|
|
22
15
|
*
|
|
23
|
-
* const viewState = await createViewState(iModel,
|
|
16
|
+
* const viewState = await createViewState(iModel, savedViewData);
|
|
24
17
|
* await Promise.all([
|
|
25
18
|
* applySavedView(iModel, viewport1, savedView, { viewState }),
|
|
26
19
|
* applySavedView(iModel, viewport2, savedView, { viewState }),
|
|
27
20
|
* ]);
|
|
28
|
-
*
|
|
29
|
-
* @remarks
|
|
30
|
-
* When neither `SavedView.viewData` nor `ViewState` is provided, current {@linkcode Viewport.view} is preserved.
|
|
31
21
|
*/
|
|
32
22
|
viewState?: ApplyStrategy | ViewState | undefined;
|
|
33
23
|
/**
|
|
34
|
-
* How to handle
|
|
35
|
-
*
|
|
24
|
+
* How to handle camera pose in captured data.
|
|
25
|
+
* @default "apply"
|
|
26
|
+
*/
|
|
27
|
+
camera?: ApplyStrategy | ViewPose | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* How to handle element emphasis in captured data.
|
|
30
|
+
* @default "apply"
|
|
31
|
+
*/
|
|
32
|
+
emphasis?: ApplyStrategy | "clear" | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* How to handle captured {@link Viewport.perModelCategoryVisibility} data.
|
|
35
|
+
* @default "apply"
|
|
36
|
+
*/
|
|
37
|
+
perModelCategoryVisibility?: ApplyStrategy | "clear" | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* How to handle visibility of models and categories that exist in iModel but
|
|
40
|
+
* are not captured in Saved View data.
|
|
36
41
|
* @default "hidden"
|
|
37
42
|
*/
|
|
38
43
|
modelAndCategoryVisibilityFallback?: "visible" | "hidden" | undefined;
|
|
39
|
-
/** How to handle captured element emphasis data. In default state emphasis is turned off. */
|
|
40
|
-
emphasis?: ApplyStrategy | undefined;
|
|
41
44
|
/**
|
|
42
|
-
*
|
|
45
|
+
* Options forwarded to {@link Viewport.changeView}.
|
|
46
|
+
* @default undefined
|
|
43
47
|
*/
|
|
44
|
-
|
|
48
|
+
viewChangeOptions?: ViewChangeOptions | undefined;
|
|
45
49
|
}
|
|
46
50
|
/**
|
|
47
51
|
* Controls how viewport state is going to be altered.
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* * `"reset"` – Reset to the default viewport state
|
|
51
|
-
* * `"keep"` – Keep the current viewport state
|
|
52
|
+
* * `"apply"` – Apply captured Saved View state to viewport
|
|
53
|
+
* * `"keep"` – Preserve current viewport state
|
|
52
54
|
*/
|
|
53
|
-
type ApplyStrategy = "apply" | "
|
|
55
|
+
type ApplyStrategy = "apply" | "keep";
|
|
54
56
|
/**
|
|
55
57
|
* Updates {@linkcode viewport} state to match captured Saved View.
|
|
56
58
|
*
|
|
57
59
|
* @example
|
|
58
60
|
* // Optionally, you can create and manage ViewState object yourself to avoid redundant work,
|
|
59
61
|
* // e.g. when applying the same Saved View to multiple viewports
|
|
60
|
-
* const viewState = await createViewState(iModel,
|
|
62
|
+
* const viewState = await createViewState(iModel, savedViewData);
|
|
61
63
|
* await Promise.all([
|
|
62
64
|
* applySavedView(iModel, viewport1, savedView, { viewState }),
|
|
63
65
|
* applySavedView(iModel, viewport2, savedView, { viewState }),
|
|
64
66
|
* ]);
|
|
65
67
|
*/
|
|
66
|
-
export declare function applySavedView(iModel: IModelConnection, viewport: Viewport, savedViewData:
|
|
68
|
+
export declare function applySavedView(iModel: IModelConnection, viewport: Viewport, savedViewData: SavedViewData, settings?: ApplySavedViewSettings | undefined): Promise<void>;
|
|
67
69
|
export {};
|
package/lib/applySavedView.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
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 { ViewState } from "@itwin/core-frontend";
|
|
5
|
+
import { ViewPose, ViewState } from "@itwin/core-frontend";
|
|
6
6
|
import { createViewState } from "./createViewState.js";
|
|
7
7
|
import { extensionHandlers } from "./translation/SavedViewsExtensionHandlers.js";
|
|
8
8
|
/**
|
|
@@ -11,37 +11,72 @@ import { extensionHandlers } from "./translation/SavedViewsExtensionHandlers.js"
|
|
|
11
11
|
* @example
|
|
12
12
|
* // Optionally, you can create and manage ViewState object yourself to avoid redundant work,
|
|
13
13
|
* // e.g. when applying the same Saved View to multiple viewports
|
|
14
|
-
* const viewState = await createViewState(iModel,
|
|
14
|
+
* const viewState = await createViewState(iModel, savedViewData);
|
|
15
15
|
* await Promise.all([
|
|
16
16
|
* applySavedView(iModel, viewport1, savedView, { viewState }),
|
|
17
17
|
* applySavedView(iModel, viewport2, savedView, { viewState }),
|
|
18
18
|
* ]);
|
|
19
19
|
*/
|
|
20
20
|
export async function applySavedView(iModel, viewport, savedViewData, settings = {}) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
if (settings.viewState !== "keep") {
|
|
22
|
+
// We use "hidden" as the default value for modelAndCategoryVisibilityFallback
|
|
23
|
+
// because users expect modelSelector.enabled and categorySelector.enabled to
|
|
24
|
+
// act as exclusive whitelists when modelSelector.disabled or categorySelector.disabled
|
|
25
|
+
// arrays are empty, respectively.
|
|
26
|
+
const { modelAndCategoryVisibilityFallback = "hidden" } = settings;
|
|
27
|
+
const viewState = settings.viewState instanceof ViewState
|
|
28
|
+
? settings.viewState
|
|
29
|
+
: await createViewState(iModel, savedViewData.viewData, { modelAndCategoryVisibilityFallback });
|
|
30
|
+
if (settings.camera instanceof ViewPose) {
|
|
31
|
+
viewState.applyPose(settings.camera);
|
|
25
32
|
}
|
|
26
|
-
else if (
|
|
27
|
-
|
|
28
|
-
const viewState = await createViewState(iModel, savedViewData.viewData, { modelAndCategoryVisibilityFallback });
|
|
29
|
-
viewport.changeView(viewState);
|
|
33
|
+
else if (settings.camera === "keep") {
|
|
34
|
+
viewState.applyPose(viewport.view.savePose());
|
|
30
35
|
}
|
|
36
|
+
viewport.changeView(viewState, settings.viewChangeOptions);
|
|
31
37
|
}
|
|
32
|
-
const extensions =
|
|
33
|
-
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
const extensions = findKnownExtensions(savedViewData.extensions ?? []);
|
|
39
|
+
if (extensions.emphasis) {
|
|
40
|
+
if (settings.emphasis !== "keep") {
|
|
41
|
+
extensionHandlers.emphasizeElements.reset(viewport);
|
|
42
|
+
}
|
|
43
|
+
if (settings.emphasis === "apply") {
|
|
44
|
+
extensionHandlers.emphasizeElements.apply(extensions.emphasis, viewport);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (extensions.perModelCategoryVisibility) {
|
|
48
|
+
if (settings.perModelCategoryVisibility !== "keep") {
|
|
49
|
+
extensionHandlers.perModelCategoryVisibility.reset(viewport);
|
|
43
50
|
}
|
|
51
|
+
if (settings.perModelCategoryVisibility === "apply") {
|
|
52
|
+
extensionHandlers.perModelCategoryVisibility.apply(extensions.perModelCategoryVisibility, viewport);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Finds first occurences of known extensions. */
|
|
57
|
+
function findKnownExtensions(extensions) {
|
|
58
|
+
const result = {
|
|
59
|
+
emphasis: undefined,
|
|
60
|
+
perModelCategoryVisibility: undefined,
|
|
44
61
|
};
|
|
45
|
-
|
|
46
|
-
|
|
62
|
+
for (const extension of extensions) {
|
|
63
|
+
if (result.emphasis === undefined &&
|
|
64
|
+
extension.extensionName === extensionHandlers.emphasizeElements.extensionName) {
|
|
65
|
+
result.emphasis = extension.data;
|
|
66
|
+
if (result.perModelCategoryVisibility) {
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (result.perModelCategoryVisibility === undefined &&
|
|
71
|
+
extension.extensionName === extensionHandlers.perModelCategoryVisibility.extensionName) {
|
|
72
|
+
result.perModelCategoryVisibility = extension.data;
|
|
73
|
+
if (result.emphasis) {
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (result.emphasis && result.perModelCategoryVisibility) {
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return result;
|
|
47
82
|
}
|
|
@@ -1,41 +1,37 @@
|
|
|
1
1
|
import { Id64Array } from "@itwin/core-bentley";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import type { SavedViewExtension } from "./SavedView.js";
|
|
2
|
+
import type { IModelConnection, Viewport } from "@itwin/core-frontend";
|
|
3
|
+
import type { SavedViewData } from "./SavedView.js";
|
|
5
4
|
interface CaptureSavedViewDataArgs {
|
|
6
5
|
/** Viewport to capture. */
|
|
7
6
|
viewport: Viewport;
|
|
8
7
|
/**
|
|
9
|
-
* Whether
|
|
8
|
+
* Whether function will skip capturing element emphasis state.
|
|
10
9
|
* @default false
|
|
11
10
|
*/
|
|
12
11
|
omitEmphasis?: boolean | undefined;
|
|
13
12
|
/**
|
|
14
|
-
* Whether
|
|
13
|
+
* Whether function will skip capturing `viewport.perModelCategoryVisibility` state.
|
|
15
14
|
* @default false
|
|
16
15
|
*/
|
|
17
16
|
omitPerModelCategoryVisibility?: boolean | undefined;
|
|
18
17
|
}
|
|
19
|
-
interface CaptureSavedViewDataResult {
|
|
20
|
-
viewData: ViewData;
|
|
21
|
-
/** Value is `undefined` when no extension data is captured. */
|
|
22
|
-
extensions: SavedViewExtension[] | undefined;
|
|
23
|
-
}
|
|
24
18
|
/**
|
|
25
|
-
* Captures current {@link Viewport} state into serializable format. The returned
|
|
26
|
-
* viewport's view.
|
|
19
|
+
* Captures current {@link Viewport} state into serializable format. The returned
|
|
20
|
+
* data can later be used to restore viewport's view.
|
|
27
21
|
*
|
|
28
22
|
* @example
|
|
29
23
|
* import { captureSavedViewData, captureSavedViewThumbnail } from "@itwin/saved-views-react";
|
|
30
24
|
*
|
|
31
25
|
* async function saveViewport(viewport) {
|
|
32
26
|
* const { viewData, extensions = [] } = await captureSavedViewData({ viewport });
|
|
33
|
-
* const myExtensions =
|
|
27
|
+
* const myExtensions = captureMyCustomViewportState(viewport);
|
|
34
28
|
* const thumbnail = captureSavedViewThumbnail(viewport);
|
|
35
29
|
* return { thumbnail, viewData, extensions: extensions.concat(myExtensions) };
|
|
36
30
|
* }
|
|
37
31
|
*/
|
|
38
|
-
export declare function captureSavedViewData(args: CaptureSavedViewDataArgs): Promise<
|
|
39
|
-
export declare function
|
|
40
|
-
export declare function
|
|
32
|
+
export declare function captureSavedViewData(args: CaptureSavedViewDataArgs): Promise<SavedViewData>;
|
|
33
|
+
export declare function queryMissingModels(iModel: IModelConnection, knownModels: Set<string>): Promise<string[]>;
|
|
34
|
+
export declare function queryAllSpatiallyLocatedModels(iModel: IModelConnection): Promise<string[]>;
|
|
35
|
+
export declare function queryMissingCategories(iModel: IModelConnection, knownCategories: Set<string>): Promise<Id64Array>;
|
|
36
|
+
export declare function queryAllCategories(iModel: IModelConnection): Promise<string[]>;
|
|
41
37
|
export {};
|