@itwin/saved-views-react 0.2.1 → 0.3.1

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 (31) hide show
  1. package/lib/LayeredDropdownMenu/LayeredDropdownMenu.css +11 -1
  2. package/lib/LayeredDropdownMenu/LayeredDropdownMenu.d.ts +3 -1
  3. package/lib/LayeredDropdownMenu/LayeredDropdownMenu.js +2 -2
  4. package/lib/SavedView.d.ts +2 -0
  5. package/lib/SavedViewTile/SavedViewOptions.d.ts +2 -0
  6. package/lib/SavedViewTile/SavedViewOptions.js +4 -4
  7. package/lib/SavedViewTile/SavedViewTile.css +8 -1
  8. package/lib/SavedViewTile/SavedViewTile.d.ts +5 -4
  9. package/lib/SavedViewTile/SavedViewTile.js +12 -14
  10. package/lib/SavedViewsClient/ITwinSavedViewsClient.js +6 -2
  11. package/lib/StickyExpandableBlock/StickyExpandableBlock.js +9 -1
  12. package/lib/api/clients/ISavedViewsClient.d.ts +5 -5
  13. package/lib/api/utilities/SavedViewTypes.d.ts +1 -1
  14. package/lib/api/utilities/translation/SavedViewTranslation.d.ts +19 -15
  15. package/lib/api/utilities/translation/SavedViewTranslation.js +177 -160
  16. package/lib/api/utilities/translation/displayStyleExtractor.js +55 -5
  17. package/lib/api/utilities/translation/viewExtractorSavedViewToLegacySavedView.d.ts +2 -19
  18. package/lib/api/utilities/translation/viewExtractorSavedViewToLegacySavedView.js +82 -133
  19. package/lib/captureSavedViewData.d.ts +4 -1
  20. package/lib/captureSavedViewData.js +12 -10
  21. package/lib/experimental.d.ts +3 -1
  22. package/lib/experimental.js +2 -1
  23. package/lib/useSavedViews.d.ts +2 -2
  24. package/lib/useSavedViews.js +76 -60
  25. package/package.json +3 -3
  26. package/lib/api/clients/IModelQueryClient.d.ts +0 -10
  27. package/lib/api/clients/IModelQueryClient.js +0 -45
  28. package/lib/api/utilities/translation/ModelsAndCategoriesHelper.d.ts +0 -3
  29. package/lib/api/utilities/translation/ModelsAndCategoriesHelper.js +0 -57
  30. package/lib/api/utilities/translation/urlConverter.d.ts +0 -7
  31. package/lib/api/utilities/translation/urlConverter.js +0 -42
@@ -5,6 +5,16 @@
5
5
  @layer itwinui;
6
6
 
7
7
  @layer itwin-svr {
8
+ :has(> .svr-layered-menu-item--forward) {
9
+ display: flex;
10
+ align-items: center;
11
+ gap: var(--iui-size-xs);
12
+ }
13
+
14
+ .svr-layered-menu-item--forward {
15
+ margin-left: var(--iui-size-2xs);
16
+ }
17
+
8
18
  .svr-layered-dropdown--back {
9
19
  display: flex;
10
20
  gap: var(--iui-size-s);
@@ -12,4 +22,4 @@
12
22
  }
13
23
  }
14
24
 
15
- /*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MYXllcmVkRHJvcGRvd25NZW51L0xheWVyZWREcm9wZG93bk1lbnUuY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBIiwiZmlsZSI6IkxheWVyZWREcm9wZG93bk1lbnUuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiogQ29weXJpZ2h0IChjKSBCZW50bGV5IFN5c3RlbXMsIEluY29ycG9yYXRlZC4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiogU2VlIExJQ0VOU0UubWQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSB0ZXJtcyBhbmQgZnVsbCBjb3B5cmlnaHQgbm90aWNlLlxuKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbkBsYXllciBpdHdpbnVpO1xuXG5AbGF5ZXIgaXR3aW4tc3ZyIHtcbiAgLnN2ci1sYXllcmVkLWRyb3Bkb3duLS1iYWNrIHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGdhcDogdmFyKC0taXVpLXNpemUtcyk7XG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgfVxufVxuIl19 */
25
+ /*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9MYXllcmVkRHJvcGRvd25NZW51L0xheWVyZWREcm9wZG93bk1lbnUuY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBIiwiZmlsZSI6IkxheWVyZWREcm9wZG93bk1lbnUuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiogQ29weXJpZ2h0IChjKSBCZW50bGV5IFN5c3RlbXMsIEluY29ycG9yYXRlZC4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiogU2VlIExJQ0VOU0UubWQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSB0ZXJtcyBhbmQgZnVsbCBjb3B5cmlnaHQgbm90aWNlLlxuKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbkBsYXllciBpdHdpbnVpO1xuXG5AbGF5ZXIgaXR3aW4tc3ZyIHtcbiAgOmhhcyg+IC5zdnItbGF5ZXJlZC1tZW51LWl0ZW0tLWZvcndhcmQpIHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgZ2FwOiB2YXIoLS1pdWktc2l6ZS14cyk7XG4gIH1cblxuICAuc3ZyLWxheWVyZWQtbWVudS1pdGVtLS1mb3J3YXJkIHtcbiAgICBtYXJnaW4tbGVmdDogdmFyKC0taXVpLXNpemUtMnhzKTtcbiAgfVxuXG4gIC5zdnItbGF5ZXJlZC1kcm9wZG93bi0tYmFjayB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBnYXA6IHZhcigtLWl1aS1zaXplLXMpO1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIH1cbn1cbiJdfQ== */
@@ -30,7 +30,9 @@ interface LayeredDropdownMenuItemProps {
30
30
  /** Content of the nested menu. */
31
31
  content: ReactNode;
32
32
  /** Menu item icon. */
33
- icon?: ReactNode | undefined;
33
+ icon?: ReactElement | undefined;
34
+ /** Forwarded to the list item wrapper. */
35
+ className?: string | undefined;
34
36
  /** Menu item label. */
35
37
  children: ReactNode;
36
38
  }
@@ -4,7 +4,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
4
4
  * See LICENSE.md in the project root for license terms and full copyright notice.
5
5
  *--------------------------------------------------------------------------------------------*/
6
6
  import { SvgChevronLeft, SvgChevronRight } from "@itwin/itwinui-icons-react";
7
- import { DropdownMenu, IconButton, ListItem, MenuDivider, MenuExtraContent } from "@itwin/itwinui-react";
7
+ import { DropdownMenu, IconButton, ListItem, MenuDivider, MenuExtraContent, MenuItem } from "@itwin/itwinui-react";
8
8
  import { createContext, useContext, useMemo, useState } from "react";
9
9
  import "./LayeredDropdownMenu.css";
10
10
  /**
@@ -45,7 +45,7 @@ export function LayeredMenuItem(props) {
45
45
  if (itemIdentifier === activeMenuItem) {
46
46
  return (_jsxs(_Fragment, { children: [_jsx(MenuExtraContent, { children: _jsx("div", { children: _jsx("div", { onClick: () => setActiveMenuItem(undefined), children: _jsxs(IconButton, { styleType: "borderless", iconProps: { className: "svr-layered-dropdown--back" }, children: [_jsx(SvgChevronLeft, {}), props.children] }) }) }) }, "header"), _jsx(MenuDivider, {}, "separator"), _jsx(MenuExtraContent, { children: props.content }, "content")] }));
47
47
  }
48
- return (_jsxs(ListItem, { tabIndex: -1, onClick: () => setActiveMenuItem(itemIdentifier), actionable: true, children: [props.icon && _jsx(ListItem.Icon, { children: props.icon }), _jsx(ListItem.Content, { children: props.children }), _jsx(ListItem.Icon, { children: _jsx(SvgChevronRight, {}) })] }));
48
+ return (_jsxs(MenuItem, { className: props.className, tabIndex: 0, startIcon: props.icon, onClick: () => setActiveMenuItem(itemIdentifier), children: [_jsx(ListItem.Content, { children: props.children }), _jsx(ListItem.Icon, { className: "svr-layered-menu-item--forward", children: _jsx(SvgChevronRight, {}) })] }));
49
49
  }
50
50
  const layeredDropdownMenuContext = createContext({ activeMenuItem: undefined, setActiveMenuItem: () => { } });
51
51
  layeredDropdownMenuContext.displayName = "LayeredDropdownMenuContext";
@@ -3,6 +3,7 @@ export interface SavedView {
3
3
  id: string;
4
4
  displayName: string;
5
5
  groupId?: string | undefined;
6
+ creatorId?: string | undefined;
6
7
  tagIds?: string[] | undefined;
7
8
  shared?: boolean | undefined;
8
9
  thumbnail?: ReactNode | string | undefined;
@@ -14,5 +15,6 @@ export interface SavedViewTag {
14
15
  export interface SavedViewGroup {
15
16
  id: string;
16
17
  displayName: string;
18
+ creatorId?: string | undefined;
17
19
  shared?: boolean | undefined;
18
20
  }
@@ -135,5 +135,7 @@ declare function Delete(props: DeleteProps): ReactElement;
135
135
  interface CommonOptionProps {
136
136
  /** Icon to the left of this menu item. */
137
137
  icon?: ReactElement | undefined;
138
+ /** Forwarded to the wrapping component. */
139
+ className?: string | undefined;
138
140
  }
139
141
  export {};
@@ -107,12 +107,12 @@ function Rename(props) {
107
107
  setEditingName(true);
108
108
  props.onClick?.();
109
109
  };
110
- return (_jsx(MenuItem, { startIcon: props.icon, onClick: handleClick, children: localization.rename }));
110
+ return (_jsx(MenuItem, { className: props.className, startIcon: props.icon, onClick: handleClick, children: localization.rename }));
111
111
  }
112
112
  function MoveToGroup(props) {
113
113
  const { savedView } = useSavedViewTileContext();
114
114
  const { localization } = useSavedViewsContext();
115
- return (_jsx(LayeredMenuItem, { icon: _jsx(SvgBlank, {}), content: _jsx(MoveToGroupSubmenu, { savedView: savedView, groups: props.groups, moveToGroup: props.moveToGroup, moveToNewGroup: props.moveToNewGroup }, "move"), children: localization.moveToGroupMenu.moveToGroup }));
115
+ return (_jsx(LayeredMenuItem, { className: props.className, icon: _jsx(SvgBlank, {}), content: _jsx(MoveToGroupSubmenu, { savedView: savedView, groups: props.groups, moveToGroup: props.moveToGroup, moveToNewGroup: props.moveToNewGroup }, "move"), children: localization.moveToGroupMenu.moveToGroup }));
116
116
  }
117
117
  function MoveToGroupSubmenu(props) {
118
118
  const { localization: { moveToGroupMenu } } = useSavedViewsContext();
@@ -129,7 +129,7 @@ function MoveToGroupSubmenu(props) {
129
129
  function ManageTags(props) {
130
130
  const { savedView } = useSavedViewTileContext();
131
131
  const { localization } = useSavedViewsContext();
132
- return (_jsx(LayeredMenuItem, { icon: props.icon, content: _jsx(ManageTagsSubmenu, { savedView: savedView, tags: props.tags, addTag: props.addTag, addNewTag: props.addNewTag, removeTag: props.removeTag }, "tags"), children: localization.tagsMenu.tags }));
132
+ return (_jsx(LayeredMenuItem, { className: props.className, icon: props.icon, content: _jsx(ManageTagsSubmenu, { savedView: savedView, tags: props.tags, addTag: props.addTag, addNewTag: props.addNewTag, removeTag: props.removeTag }, "tags"), children: localization.tagsMenu.tags }));
133
133
  }
134
134
  function ManageTagsSubmenu(props) {
135
135
  const { localization } = useSavedViewsContext();
@@ -169,5 +169,5 @@ function SearchableSubmenu(props) {
169
169
  function Delete(props) {
170
170
  const { savedView } = useSavedViewTileContext();
171
171
  const { localization } = useSavedViewsContext();
172
- return (_jsx(MenuItem, { startIcon: props.icon, onClick: () => props.deleteSavedView(savedView.id), children: localization.delete }));
172
+ return (_jsx(MenuItem, { className: props.className, startIcon: props.icon, onClick: () => props.deleteSavedView(savedView.id), children: localization.delete }));
173
173
  }
@@ -16,6 +16,13 @@
16
16
  .svr-tile .svr-tile-name {
17
17
  height: calc(var(--iui-size-l) + 2px);
18
18
  user-select: unset;
19
+ min-width: 0;
20
+ text-wrap: nowrap;
21
+
22
+ > div {
23
+ overflow: hidden;
24
+ text-overflow: ellipsis;
25
+ }
19
26
  }
20
27
 
21
28
  .svr-tile--metadata {
@@ -89,4 +96,4 @@
89
96
  }
90
97
  }
91
98
 
92
- /*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9TYXZlZFZpZXdUaWxlL1NhdmVkVmlld1RpbGUuY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBIiwiZmlsZSI6IlNhdmVkVmlld1RpbGUuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiogQ29weXJpZ2h0IChjKSBCZW50bGV5IFN5c3RlbXMsIEluY29ycG9yYXRlZC4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiogU2VlIExJQ0VOU0UubWQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSB0ZXJtcyBhbmQgZnVsbCBjb3B5cmlnaHQgbm90aWNlLlxuKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbkBsYXllciBpdHdpbnVpO1xuXG5AbGF5ZXIgaXR3aW4tc3ZyIHtcbiAgLnN2ci10aWxlIHtcbiAgICB3aWR0aDogdmFyKC0taXR3aW4tc3ZyLXRpbGUtd2lkdGgsIGNhbGMoOCAqIHZhcigtLWl1aS1zaXplLXhsKSkpO1xuICB9XG5cbiAgLnN2ci10aWxlIC5zdnItdGlsZS10aHVtYm5haWwge1xuICAgIGhlaWdodDogdmFyKC0taXR3aW4tc3ZyLXRodW1ibmFpbC1oZWlnaHQsIGNhbGMoNCAqIHZhcigtLWl1aS1zaXplLXhsKSkpO1xuICB9XG5cbiAgLnN2ci10aWxlIC5zdnItdGlsZS1uYW1lIHtcbiAgICBoZWlnaHQ6IGNhbGModmFyKC0taXVpLXNpemUtbCkgKyAycHgpO1xuICAgIHVzZXItc2VsZWN0OiB1bnNldDtcbiAgfVxuXG4gIC5zdnItdGlsZS0tbWV0YWRhdGEge1xuICAgIGRpc3BsYXk6IGdyaWQ7XG4gICAgZ3JpZDogMWZyIC8gYXV0byBtaW5tYXgoMCwgMWZyKSBhdXRvO1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIH1cblxuICAuc3ZyLXRpbGUtLW1ldGFkYXRhID4gc3ZnIHtcbiAgICBtYXJnaW4tcmlnaHQ6IHZhcigtLWl1aS1zaXplLXhzKTtcbiAgfVxuXG4gIC5zdnItdGlsZS0tdGFnLWNvbnRhaW5lciB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBnYXA6IHZhcigtLWl1aS1zaXplLXMpO1xuICB9XG5cbiAgLnN2ci10aWxlLS10YWcge1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XG4gICAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcbiAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgIG1pbi13aWR0aDogMDtcbiAgfVxuXG4gIC5zdnItdGlsZS0tdGFnLW92ZXJmbG93IHtcbiAgICBtYXJnaW4tbGVmdDogdmFyKC0taXVpLXNpemUtcyk7XG4gIH1cblxuICAuc3ZyLXRpbGUtLW1vcmUtb3B0aW9ucyB7XG4gICAgei1pbmRleDogMjtcbiAgICBncmlkLWFyZWE6IDEgLyAxIC8gLTEgLyAtMTtcbiAgICBwbGFjZS1zZWxmOiBlbmQ7XG4gICAgbWFyZ2luOiAwO1xuICAgIG1hcmdpbi1pbmxpbmUtZW5kOiBjYWxjKC0xKnZhcigtLWl1aS1zaXplLTJ4cykpO1xuICAgIGRpc3BsYXk6IGdyaWQ7XG4gICAgcG9zaXRpb246IGFic29sdXRlO1xuICB9XG5cbiAgLnN2ci10aWxlOm5vdCg6aG92ZXIsIDpmb2N1cy13aXRoaW4pIC5zdnItdGlsZS0tbW9yZS1vcHRpb25zOndoZXJlKDpub3QoLnN2ci12aXNpYmxlKSkge1xuICAgIHZpc2liaWxpdHk6IGhpZGRlbjtcbiAgfVxuXG4gIC5zdnItdGlsZS0taWNvbi1jb250YWluZXIge1xuICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgbWFyZ2luLXRvcDogY2FsYygwLjUgKiB2YXIoLS1pdWktc2l6ZS1zKSk7XG4gICAgbWFyZ2luLWlubGluZTogdmFyKC0taXVpLXNpemUteHMpO1xuICAgIGdhcDogdmFyKC0taXVpLXNpemUtMnhzKTtcbiAgICB6LWluZGV4OiAxO1xuICB9XG5cbiAgLnN2ci10aWxlLS1pY29uIHtcbiAgICBib3JkZXItcmFkaXVzOiA1MCU7XG4gICAgYmFja2dyb3VuZDogcmdiKDAsIDAsIDAsIHZhcigtLWl1aS1vcGFjaXR5LTMpKTtcbiAgICBtaW4td2lkdGg6IHZhcigtLWl1aS1jb21wb25lbnQtaGVpZ2h0LXNtYWxsKTtcbiAgICBtaW4taGVpZ2h0OiB2YXIoLS1pdWktY29tcG9uZW50LWhlaWdodC1zbWFsbCk7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBwbGFjZS1pdGVtczogY2VudGVyO1xuICAgIHBhZGRpbmctaW5saW5lOiB2YXIoLS1pdWktc2l6ZS0yeHMpO1xuICAgIGJvcmRlcjogMXB4IHNvbGlkIHRyYW5zcGFyZW50O1xuICB9XG5cbiAgLnN2ci10aWxlLS1pY29uIHN2ZyB7XG4gICAgZmlsbDogdmFyKC0taXVpLWNvbG9yLXdoaXRlKTtcbiAgfVxuXG4gIC5zdnItdGlsZS0tZWRpdGFibGUtdGl0bGUgPiBzcGFuIHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgZ2FwOiB2YXIoLS1pdWktc2l6ZS1zKTtcbiAgfVxufVxuIl19 */
99
+ /*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9TYXZlZFZpZXdUaWxlL1NhdmVkVmlld1RpbGUuY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBIiwiZmlsZSI6IlNhdmVkVmlld1RpbGUuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiogQ29weXJpZ2h0IChjKSBCZW50bGV5IFN5c3RlbXMsIEluY29ycG9yYXRlZC4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiogU2VlIExJQ0VOU0UubWQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSB0ZXJtcyBhbmQgZnVsbCBjb3B5cmlnaHQgbm90aWNlLlxuKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbkBsYXllciBpdHdpbnVpO1xuXG5AbGF5ZXIgaXR3aW4tc3ZyIHtcbiAgLnN2ci10aWxlIHtcbiAgICB3aWR0aDogdmFyKC0taXR3aW4tc3ZyLXRpbGUtd2lkdGgsIGNhbGMoOCAqIHZhcigtLWl1aS1zaXplLXhsKSkpO1xuICB9XG5cbiAgLnN2ci10aWxlIC5zdnItdGlsZS10aHVtYm5haWwge1xuICAgIGhlaWdodDogdmFyKC0taXR3aW4tc3ZyLXRodW1ibmFpbC1oZWlnaHQsIGNhbGMoNCAqIHZhcigtLWl1aS1zaXplLXhsKSkpO1xuICB9XG5cbiAgLnN2ci10aWxlIC5zdnItdGlsZS1uYW1lIHtcbiAgICBoZWlnaHQ6IGNhbGModmFyKC0taXVpLXNpemUtbCkgKyAycHgpO1xuICAgIHVzZXItc2VsZWN0OiB1bnNldDtcbiAgICBtaW4td2lkdGg6IDA7XG4gICAgdGV4dC13cmFwOiBub3dyYXA7XG5cbiAgICA+IGRpdiB7XG4gICAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgICAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XG4gICAgfVxuICB9XG5cbiAgLnN2ci10aWxlLS1tZXRhZGF0YSB7XG4gICAgZGlzcGxheTogZ3JpZDtcbiAgICBncmlkOiAxZnIgLyBhdXRvIG1pbm1heCgwLCAxZnIpIGF1dG87XG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgfVxuXG4gIC5zdnItdGlsZS0tbWV0YWRhdGEgPiBzdmcge1xuICAgIG1hcmdpbi1yaWdodDogdmFyKC0taXVpLXNpemUteHMpO1xuICB9XG5cbiAgLnN2ci10aWxlLS10YWctY29udGFpbmVyIHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGdhcDogdmFyKC0taXVpLXNpemUtcyk7XG4gIH1cblxuICAuc3ZyLXRpbGUtLXRhZyB7XG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICB0ZXh0LW92ZXJmbG93OiBlbGxpcHNpcztcbiAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xuICAgIG92ZXJmbG93OiBoaWRkZW47XG4gICAgbWluLXdpZHRoOiAwO1xuICB9XG5cbiAgLnN2ci10aWxlLS10YWctb3ZlcmZsb3cge1xuICAgIG1hcmdpbi1sZWZ0OiB2YXIoLS1pdWktc2l6ZS1zKTtcbiAgfVxuXG4gIC5zdnItdGlsZS0tbW9yZS1vcHRpb25zIHtcbiAgICB6LWluZGV4OiAyO1xuICAgIGdyaWQtYXJlYTogMSAvIDEgLyAtMSAvIC0xO1xuICAgIHBsYWNlLXNlbGY6IGVuZDtcbiAgICBtYXJnaW46IDA7XG4gICAgbWFyZ2luLWlubGluZS1lbmQ6IGNhbGMoLTEqdmFyKC0taXVpLXNpemUtMnhzKSk7XG4gICAgZGlzcGxheTogZ3JpZDtcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gIH1cblxuICAuc3ZyLXRpbGU6bm90KDpob3ZlciwgOmZvY3VzLXdpdGhpbikgLnN2ci10aWxlLS1tb3JlLW9wdGlvbnM6d2hlcmUoOm5vdCguc3ZyLXZpc2libGUpKSB7XG4gICAgdmlzaWJpbGl0eTogaGlkZGVuO1xuICB9XG5cbiAgLnN2ci10aWxlLS1pY29uLWNvbnRhaW5lciB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBtYXJnaW4tdG9wOiBjYWxjKDAuNSAqIHZhcigtLWl1aS1zaXplLXMpKTtcbiAgICBtYXJnaW4taW5saW5lOiB2YXIoLS1pdWktc2l6ZS14cyk7XG4gICAgZ2FwOiB2YXIoLS1pdWktc2l6ZS0yeHMpO1xuICAgIHotaW5kZXg6IDE7XG4gIH1cblxuICAuc3ZyLXRpbGUtLWljb24ge1xuICAgIGJvcmRlci1yYWRpdXM6IDUwJTtcbiAgICBiYWNrZ3JvdW5kOiByZ2IoMCwgMCwgMCwgdmFyKC0taXVpLW9wYWNpdHktMykpO1xuICAgIG1pbi13aWR0aDogdmFyKC0taXVpLWNvbXBvbmVudC1oZWlnaHQtc21hbGwpO1xuICAgIG1pbi1oZWlnaHQ6IHZhcigtLWl1aS1jb21wb25lbnQtaGVpZ2h0LXNtYWxsKTtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIHBsYWNlLWl0ZW1zOiBjZW50ZXI7XG4gICAgcGFkZGluZy1pbmxpbmU6IHZhcigtLWl1aS1zaXplLTJ4cyk7XG4gICAgYm9yZGVyOiAxcHggc29saWQgdHJhbnNwYXJlbnQ7XG4gIH1cblxuICAuc3ZyLXRpbGUtLWljb24gc3ZnIHtcbiAgICBmaWxsOiB2YXIoLS1pdWktY29sb3Itd2hpdGUpO1xuICB9XG5cbiAgLnN2ci10aWxlLS1lZGl0YWJsZS10aXRsZSA+IHNwYW4ge1xuICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICBnYXA6IHZhcigtLWl1aS1zaXplLXMpO1xuICB9XG59XG4iXX0= */
@@ -16,13 +16,14 @@ interface SavedViewTileProps {
16
16
  options?: ((close: () => void) => ReactElement[]) | ReactElement[] | undefined;
17
17
  /**
18
18
  * Invoked when user submits a new name for the Saved View.
19
- * @param savedViewId Id of the associated Saved View.
20
- * @param newName User-submitted string for the Saved View title.
19
+ * @param savedViewId Id of the associated Saved View
20
+ * @param newName User-submitted string for the Saved View title. This value is `undefined` when user cancels rename
21
+ * operaton.
21
22
  *
22
23
  * @example
23
24
  * <SavedViewTile savedView={savedView} onRename={handleRename} editable />
24
25
  */
25
- onRename?: ((savedViewId: string, newName: string) => void) | undefined;
26
+ onRename?: ((savedViewId: string, newName: string | undefined) => void) | undefined;
26
27
  /**
27
28
  * Click handler meant for triggering the render of iModel onto the screen with the saved view applied
28
29
  */
@@ -46,7 +47,7 @@ interface EditableTileNameProps {
46
47
  displayName: string;
47
48
  actions: {
48
49
  onStartEditing: () => void;
49
- onEndEditing: (newName: string) => void;
50
+ onEndEditing: (newName: string, commit: boolean) => void;
50
51
  };
51
52
  editing?: boolean | undefined;
52
53
  editable?: boolean | undefined;
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  /*---------------------------------------------------------------------------------------------
3
3
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
4
4
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -59,17 +59,15 @@ export function SavedViewTile(props) {
59
59
  const savedViewTileContext = useMemo(() => ({ savedView: props.savedView, setEditingName }), [props.savedView]);
60
60
  return (_jsx(SavedViewTileContextProvider, { value: savedViewTileContext, children: _jsxs(Tile.Wrapper, { className: `svr-tile ${props.className || ""}`, onClick: () => props.onClick?.(props.savedView.id), children: [!props.editable && _jsx(Tile.Action, {}), _jsx(Tile.Name, { className: "svr-tile-name", children: _jsx(EditableTileName, { displayName: props.savedView.displayName, editing: editingName, actions: {
61
61
  onStartEditing: () => setEditingName(true),
62
- onEndEditing: (newName) => {
62
+ onEndEditing: (newName, commit) => {
63
63
  setEditingName(false);
64
- if (newName !== props.savedView.displayName) {
65
- props.onRename?.(props.savedView.id, newName);
66
- }
64
+ props.onRename?.(props.savedView.id, commit ? newName : undefined);
67
65
  },
68
66
  }, editable: props.editable || editingName }) }), _jsxs(Tile.ThumbnailArea, { className: "svr-tile-thumbnail", children: [typeof props.savedView.thumbnail === "string"
69
67
  ? _jsx(Tile.ThumbnailPicture, { url: props.savedView.thumbnail })
70
68
  : props.savedView.thumbnail
71
69
  ? props.savedView.thumbnail
72
- : _jsx(Tile.ThumbnailPicture, { children: _jsx(SvgImageFrame, {}) }), _jsx(TileIconContainer, { style: { placeSelf: "start" }, icons: props.leftIcons }), _jsx(TileIconContainer, { style: { placeSelf: "start end" }, icons: rightIcons })] }), _jsxs(Tile.ContentArea, { children: [_jsx(Tile.Metadata, { children: metadata }), props.options && props.options.length > 0 &&
70
+ : _jsx(Tile.ThumbnailPicture, { children: _jsx(SvgImageFrame, {}) }), _jsx(TileIconContainer, { style: { placeSelf: "start" }, icons: props.leftIcons }), _jsx(TileIconContainer, { style: { placeSelf: "start end" }, icons: rightIcons })] }), _jsxs(Tile.ContentArea, { children: [_jsx(Tile.Metadata, { children: metadata }), (typeof props.options === "function" || (props.options && props.options.length > 0)) &&
73
71
  _jsx("div", { className: "svr-tile--more-options", onClick: (ev) => ev.stopPropagation(), children: _jsx(LayeredDropdownMenu, { menuItems: props.options, children: _jsx(IconButton, { size: "small", styleType: "borderless", children: _jsx(SvgMore, {}) }) }) })] })] }) }));
74
72
  }
75
73
  function isOverflowing(element) {
@@ -78,26 +76,26 @@ function isOverflowing(element) {
78
76
  export function EditableTileName(props) {
79
77
  const { actions } = props;
80
78
  if (!props.editable) {
81
- return _jsx(_Fragment, { children: props.displayName });
79
+ return _jsx("div", { children: props.displayName });
82
80
  }
83
81
  if (props.editing) {
82
+ const handleEndEditing = (inputValue, commit) => {
83
+ const trimmedValue = trimInputString(inputValue);
84
+ actions.onEndEditing(trimmedValue.length === 0 ? props.displayName : trimmedValue, commit);
85
+ };
84
86
  const handleFocus = (ev) => {
85
87
  ev.target.select();
86
88
  };
87
89
  const handleBlur = (ev) => {
88
- actions.onEndEditing(trimInputString(ev.target.value));
89
- };
90
- const handleEndEditing = (inputValue) => {
91
- actions.onEndEditing(inputValue.length === 0 ? props.displayName : trimInputString(inputValue));
90
+ handleEndEditing(ev.target.value, true);
92
91
  };
93
92
  const handleKeyDown = (ev) => {
94
93
  if (ev.key === "Enter") {
95
- const value = ev.target.value;
96
- handleEndEditing(value);
94
+ handleEndEditing(ev.target.value, true);
97
95
  return;
98
96
  }
99
97
  if (ev.key === "Escape") {
100
- actions.onEndEditing(props.displayName);
98
+ actions.onEndEditing(props.displayName, false);
101
99
  return;
102
100
  }
103
101
  };
@@ -17,8 +17,8 @@ export class ITwinSavedViewsClient {
17
17
  ]);
18
18
  return {
19
19
  savedViews: savedViews.map(savedViewResponseToSavedView),
20
- groups,
21
- tags,
20
+ groups: groups.map(groupResponseToSavedViewGroup),
21
+ tags: tags.map(tagResponseToSavedViewTag),
22
22
  };
23
23
  }
24
24
  async getSingularSavedView(args) {
@@ -91,6 +91,8 @@ export class ITwinSavedViewsClient {
91
91
  return groupResponseToSavedViewGroup(group);
92
92
  }
93
93
  async deleteGroup(args) {
94
+ const savedViews = await this.client.getAllSavedViewsMinimal({ groupId: args.groupId, signal: args.signal });
95
+ await Promise.all(savedViews.savedViews.map(({ id }) => this.client.deleteSavedView({ savedViewId: id, signal: args.signal })));
94
96
  await this.client.deleteGroup({ groupId: args.groupId, signal: args.signal });
95
97
  }
96
98
  async createTag(args) {
@@ -120,6 +122,7 @@ function savedViewResponseToSavedView(response) {
120
122
  displayName: response.displayName,
121
123
  tagIds: response.tags?.map((tag) => tag.id),
122
124
  groupId: response._links.group?.href.split("/").at(-1),
125
+ creatorId: response._links.creator?.href.split("/").at(-1),
123
126
  shared: response.shared,
124
127
  thumbnail: undefined,
125
128
  };
@@ -128,6 +131,7 @@ function groupResponseToSavedViewGroup(response) {
128
131
  return {
129
132
  id: response.id,
130
133
  displayName: response.displayName,
134
+ creatorId: response._links.creator?.href.split("/").at(-1),
131
135
  shared: response.shared,
132
136
  };
133
137
  }
@@ -31,7 +31,15 @@ export function StickyExpandableBlock(props) {
31
31
  };
32
32
  const stickyRef = useRef(null);
33
33
  const stuck = useSticky(stickyRef);
34
- return (_jsxs(ExpandableBlock.Wrapper, { className: props.className, styleType: "borderless", isExpanded: props.isExpanded, onToggle: handleExpandToggle, children: [_jsx("div", { ref: scrollbackRef }), _jsxs(ExpandableBlock.Trigger, { ref: stickyRef, as: "div", className: "svr-expandable-block-header", "data-stuck": stuck, role: "button", children: [_jsx(ExpandableBlock.ExpandIcon, {}), _jsx(ExpandableBlock.LabelArea, { children: _jsx(ExpandableBlock.Title, { className: props.titleClassName, children: props.title }) }), props.endIcon &&
34
+ // We are pretending that expandable block title is a button element for accessibility
35
+ const handleKeyDown = (e) => {
36
+ if (e.target === e.currentTarget && e.key === "Enter" || e.key === " ") {
37
+ handleExpandToggle(!props.isExpanded);
38
+ // We don't want spacebar to cause scroll down
39
+ e.preventDefault();
40
+ }
41
+ };
42
+ return (_jsxs(ExpandableBlock.Wrapper, { className: props.className, styleType: "borderless", isExpanded: props.isExpanded, onToggle: handleExpandToggle, children: [_jsx("div", { ref: scrollbackRef }), _jsxs(ExpandableBlock.Trigger, { ref: stickyRef, className: "svr-expandable-block-header", "data-stuck": stuck, children: [_jsx(ExpandableBlock.ExpandIcon, {}), _jsx(ExpandableBlock.LabelArea, { children: _jsx(ExpandableBlock.Title, { as: "div", className: props.titleClassName, tabIndex: 0, role: "button", onKeyDown: handleKeyDown, children: props.title }) }), props.endIcon &&
35
43
  _jsx(ExpandableBlock.EndIcon, { onClick: handleGroupMenuClick, children: props.endIcon })] }), _jsx(ExpandableBlock.Content, { children: props.children })] }));
36
44
  }
37
45
  function useSticky(ref) {
@@ -1,9 +1,9 @@
1
- import type { LegacySavedView, LegacySavedViewBase } from "../utilities/SavedViewTypes.js";
1
+ import type { LegacySavedView3d, LegacySavedView2d, LegacySavedViewBase } from "../utilities/SavedViewTypes.js";
2
2
  /** Is a 3d saved view */
3
- export declare function isSavedView3d(view: LegacySavedViewBase): view is LegacySavedView;
3
+ export declare function isSavedView3d(view: LegacySavedViewBase): view is LegacySavedView3d;
4
4
  /** Is a 3d spatial saved view */
5
- export declare function isSpatialSavedView(view: LegacySavedViewBase): boolean;
5
+ export declare function isSpatialSavedView(view: LegacySavedViewBase): view is LegacySavedView3d;
6
6
  /** Is a 2d drawing saved view */
7
- export declare function isDrawingSavedView(view: LegacySavedViewBase): boolean;
7
+ export declare function isDrawingSavedView(view: LegacySavedViewBase): view is LegacySavedView2d;
8
8
  /** Is a 2d sheet saved view */
9
- export declare function isSheetSavedView(view: LegacySavedViewBase): boolean;
9
+ export declare function isSheetSavedView(view: LegacySavedViewBase): view is LegacySavedView2d;
@@ -34,7 +34,7 @@ export interface LegacySavedView2d extends LegacySavedViewBase {
34
34
  /**
35
35
  * Format for a saved view setting instance in the service
36
36
  */
37
- export interface LegacySavedView extends LegacySavedViewBase {
37
+ export interface LegacySavedView3d extends LegacySavedViewBase {
38
38
  displayStyleProps: DisplayStyle3dProps;
39
39
  modelSelectorProps: ModelSelectorProps;
40
40
  modelExtents?: Range3dProps;
@@ -1,22 +1,26 @@
1
- import { IModelConnection, ScreenViewport, ViewState } from "@itwin/core-frontend";
1
+ import { SpatialViewState, type IModelConnection, type ViewState, type Viewport } from "@itwin/core-frontend";
2
2
  import { type SavedViewRepresentation } from "@itwin/saved-views-client";
3
- /**
4
- * Converts a saved view response to a saved view response that includes a legacy view.
5
- * @param savedViewResponse A saved view response with or without a legacy view.
6
- * @param iModelConnection The {@link IModelConnection} for the saved view; used to query for additional information.
7
- * @returns A {@link SavedViewRepresentation} that contains legacy saved view data.
8
- */
9
- export declare function translateSavedViewResponseToLegacySavedViewResponse(savedViewResponse: SavedViewRepresentation, iModelConnection: IModelConnection): Promise<SavedViewRepresentation>;
3
+ import type { LegacySavedView3d, LegacySavedViewBase } from "../SavedViewTypes.js";
10
4
  /**
11
5
  * Converts a legacy saved view (response) to an iTwin.js ViewState.
12
- * @param legacySavedViewResponse A saved view response that includes a legacy view.
13
- * @param iModelConnection The {@link IModelConnection} for the saved view; used to query for additional information.
14
- * @returns A {@link ViewState} with the saved view applied.
6
+ * @param legacySavedView a saved view response that includes a legacy view
7
+ * @param iModel the {@linkcode IModelConnection} for the saved view; used to query for additional information
8
+ * @param useHiddenModelsAndCategories when explicitly set to `false`, the returned {@linkcode ViewState} does not have
9
+ * populated category and model selectors
10
+ * @returns a {@linkcode ViewState} with the saved view applied
15
11
  */
16
- export declare function translateLegacySavedViewToITwinJsViewState(legacySavedViewResponse: SavedViewRepresentation, iModelConnection: IModelConnection): Promise<ViewState | undefined>;
12
+ export declare function translateLegacySavedViewToITwinJsViewState(legacySavedView: LegacySavedViewBase, iModel: IModelConnection, useHiddenModelsAndCategories?: boolean): Promise<ViewState | undefined>;
13
+ export declare function augmentWithScheduleScript(iModel: IModelConnection, savedView: LegacySavedView3d, viewState: SpatialViewState): Promise<boolean>;
17
14
  /**
18
15
  * Apply extension data (overrides) onto the supplied viewport. Only works with legacy-formatted extension data.
19
- * @param viewport The {@link ScreenViewport} used to display the saved view and iModel.
20
- * @param legacySavedViewResponse A saved view response that includes a legacy view.
16
+ * @param viewport The {@link Viewport} used to display the saved view and iModel.
17
+ * @param legacySavedView A saved view response that includes a legacy view.
21
18
  */
22
- export declare function applyExtensionsToViewport(viewport: ScreenViewport, legacySavedViewResponse: SavedViewRepresentation | undefined): Promise<void>;
19
+ export declare function applyExtensionsToViewport(viewport: Viewport, legacySavedView: LegacySavedViewBase): Promise<void>;
20
+ /**
21
+ * Creates legacy saved view data from a saved view response.
22
+ * @param savedViewResponse A saved view response with or without a legacy view.
23
+ * @param iModel The {@link IModelConnection} for the saved view; used to query for additional information.
24
+ * @resolves The saved views formatted as a legacy SavedViewBase.
25
+ */
26
+ export declare function translateSavedViewToLegacySavedView(iModel: IModelConnection, savedViewResponse: SavedViewRepresentation): Promise<LegacySavedViewBase>;