@itwin/saved-views-react 0.1.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 (77) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +131 -0
  3. package/lib/LayeredDropdownMenu/LayeredDropdownMenu.css +11 -0
  4. package/lib/LayeredDropdownMenu/LayeredDropdownMenu.d.ts +39 -0
  5. package/lib/LayeredDropdownMenu/LayeredDropdownMenu.js +53 -0
  6. package/lib/SavedView.d.ts +18 -0
  7. package/lib/SavedView.js +1 -0
  8. package/lib/SavedViewTile/SavedViewOptions.css +26 -0
  9. package/lib/SavedViewTile/SavedViewOptions.d.ts +139 -0
  10. package/lib/SavedViewTile/SavedViewOptions.js +173 -0
  11. package/lib/SavedViewTile/SavedViewTile.css +89 -0
  12. package/lib/SavedViewTile/SavedViewTile.d.ts +55 -0
  13. package/lib/SavedViewTile/SavedViewTile.js +110 -0
  14. package/lib/SavedViewTile/SavedViewTileContext.d.ts +14 -0
  15. package/lib/SavedViewTile/SavedViewTileContext.js +20 -0
  16. package/lib/SavedViewsClient/ITwinSavedViewsClient.d.ts +30 -0
  17. package/lib/SavedViewsClient/ITwinSavedViewsClient.js +132 -0
  18. package/lib/SavedViewsClient/SavedViewsClient.d.ts +72 -0
  19. package/lib/SavedViewsClient/SavedViewsClient.js +1 -0
  20. package/lib/SavedViewsContext.d.ts +13 -0
  21. package/lib/SavedViewsContext.js +38 -0
  22. package/lib/SavedViewsWidget/SavedViewGroupTile/SavedViewGroupOptions.d.ts +9 -0
  23. package/lib/SavedViewsWidget/SavedViewGroupTile/SavedViewGroupOptions.js +14 -0
  24. package/lib/SavedViewsWidget/SavedViewGroupTile/SavedViewGroupTile.d.ts +14 -0
  25. package/lib/SavedViewsWidget/SavedViewGroupTile/SavedViewGroupTile.js +37 -0
  26. package/lib/SavedViewsWidget/SavedViewGroupTile/SavedViewGroupTileContext.d.ts +14 -0
  27. package/lib/SavedViewsWidget/SavedViewGroupTile/SavedViewGroupTileContext.js +20 -0
  28. package/lib/SavedViewsWidget/SavedViewsExpandableBlockWidget.css +50 -0
  29. package/lib/SavedViewsWidget/SavedViewsExpandableBlockWidget.d.ts +36 -0
  30. package/lib/SavedViewsWidget/SavedViewsExpandableBlockWidget.js +36 -0
  31. package/lib/SavedViewsWidget/SavedViewsFolderWidget.d.ts +14 -0
  32. package/lib/SavedViewsWidget/SavedViewsFolderWidget.js +60 -0
  33. package/lib/StickyExpandableBlock/StickyExpandableBlock.css +20 -0
  34. package/lib/StickyExpandableBlock/StickyExpandableBlock.d.ts +29 -0
  35. package/lib/StickyExpandableBlock/StickyExpandableBlock.js +63 -0
  36. package/lib/TileGrid/TileGrid.css +28 -0
  37. package/lib/TileGrid/TileGrid.d.ts +48 -0
  38. package/lib/TileGrid/TileGrid.js +32 -0
  39. package/lib/api/clients/IModelQueryClient.d.ts +10 -0
  40. package/lib/api/clients/IModelQueryClient.js +45 -0
  41. package/lib/api/clients/ISavedViewsClient.d.ts +9 -0
  42. package/lib/api/clients/ISavedViewsClient.js +16 -0
  43. package/lib/api/utilities/SavedViewTypes.d.ts +48 -0
  44. package/lib/api/utilities/SavedViewTypes.js +1 -0
  45. package/lib/api/utilities/translation/ModelsAndCategoriesHelper.d.ts +3 -0
  46. package/lib/api/utilities/translation/ModelsAndCategoriesHelper.js +57 -0
  47. package/lib/api/utilities/translation/RgbColor.d.ts +29 -0
  48. package/lib/api/utilities/translation/RgbColor.js +1 -0
  49. package/lib/api/utilities/translation/SavedViewTranslation.d.ts +22 -0
  50. package/lib/api/utilities/translation/SavedViewTranslation.js +246 -0
  51. package/lib/api/utilities/translation/SavedViewsExtensionHandlers.d.ts +13 -0
  52. package/lib/api/utilities/translation/SavedViewsExtensionHandlers.js +42 -0
  53. package/lib/api/utilities/translation/clipVectorsExtractor.d.ts +5 -0
  54. package/lib/api/utilities/translation/clipVectorsExtractor.js +56 -0
  55. package/lib/api/utilities/translation/displayStyleExtractor.d.ts +17 -0
  56. package/lib/api/utilities/translation/displayStyleExtractor.js +499 -0
  57. package/lib/api/utilities/translation/extensionExtractor.d.ts +18 -0
  58. package/lib/api/utilities/translation/extensionExtractor.js +79 -0
  59. package/lib/api/utilities/translation/extractionUtilities.d.ts +209 -0
  60. package/lib/api/utilities/translation/extractionUtilities.js +515 -0
  61. package/lib/api/utilities/translation/urlConverter.d.ts +7 -0
  62. package/lib/api/utilities/translation/urlConverter.js +42 -0
  63. package/lib/api/utilities/translation/viewExtractorSavedViewToLegacySavedView.d.ts +35 -0
  64. package/lib/api/utilities/translation/viewExtractorSavedViewToLegacySavedView.js +298 -0
  65. package/lib/experimental.d.ts +4 -0
  66. package/lib/experimental.js +8 -0
  67. package/lib/index.d.ts +12 -0
  68. package/lib/index.js +14 -0
  69. package/lib/localization.d.ts +52 -0
  70. package/lib/localization.js +51 -0
  71. package/lib/ui/viewlist/ModelCategoryOverrideProvider.d.ts +31 -0
  72. package/lib/ui/viewlist/ModelCategoryOverrideProvider.js +88 -0
  73. package/lib/useSavedViews.d.ts +52 -0
  74. package/lib/useSavedViews.js +514 -0
  75. package/lib/utils.d.ts +1 -0
  76. package/lib/utils.js +7 -0
  77. package/package.json +75 -0
@@ -0,0 +1,89 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+
6
+ .svr-tile {
7
+ width: var(--itwin-svr-tile-width, calc(8 * var(--iui-size-xl)));
8
+ }
9
+
10
+ .svr-tile .svr-tile-thumbnail {
11
+ height: var(--itwin-svr-thumbnail-height, calc(4 * var(--iui-size-xl)));
12
+ }
13
+
14
+ .svr-tile .svr-tile-name {
15
+ height: calc(var(--iui-size-l) + 2px);
16
+ user-select: unset;
17
+ }
18
+
19
+ .svr-tile--metadata {
20
+ display: grid;
21
+ grid: 1fr / auto minmax(0, 1fr) auto;
22
+ align-items: center;
23
+ }
24
+
25
+ .svr-tile--metadata > svg {
26
+ margin-right: var(--iui-size-xs);
27
+ }
28
+
29
+ .svr-tile--tag-container {
30
+ display: flex;
31
+ gap: var(--iui-size-s);
32
+ }
33
+
34
+ .svr-tile--tag {
35
+ align-items: center;
36
+ text-overflow: ellipsis;
37
+ white-space: nowrap;
38
+ overflow: hidden;
39
+ min-width: 0;
40
+ }
41
+
42
+ .svr-tile--tag-overflow {
43
+ margin-left: var(--iui-size-s);
44
+ }
45
+
46
+ .svr-tile--more-options {
47
+ z-index: 2;
48
+ grid-area: 1 / 1 / -1 / -1;
49
+ place-self: end;
50
+ margin: 0;
51
+ margin-inline-end: calc(-1*var(--iui-size-2xs));
52
+ display: grid;
53
+ position: absolute;
54
+ }
55
+
56
+ .svr-tile:not(:hover, :focus-within) .svr-tile--more-options:where(:not(.svr-visible)) {
57
+ visibility: hidden;
58
+ }
59
+
60
+ .svr-tile--icon-container {
61
+ display: flex;
62
+ margin-top: calc(0.5 * var(--iui-size-s));
63
+ margin-inline: var(--iui-size-xs);
64
+ gap: var(--iui-size-2xs);
65
+ z-index: 1;
66
+ }
67
+
68
+ .svr-tile--icon {
69
+ border-radius: 50%;
70
+ background: rgb(0, 0, 0, var(--iui-opacity-3));
71
+ min-width: var(--iui-component-height-small);
72
+ min-height: var(--iui-component-height-small);
73
+ display: flex;
74
+ place-items: center;
75
+ padding-inline: var(--iui-size-2xs);
76
+ border: 1px solid transparent;
77
+ }
78
+
79
+ .svr-tile--icon svg {
80
+ fill: var(--iui-color-white);
81
+ }
82
+
83
+ .svr-tile--editable-title > span {
84
+ display: flex;
85
+ align-items: center;
86
+ gap: var(--iui-size-s);
87
+ }
88
+
89
+ /*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9TYXZlZFZpZXdUaWxlL1NhdmVkVmlld1RpbGUuY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBIiwiZmlsZSI6IlNhdmVkVmlld1RpbGUuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiogQ29weXJpZ2h0IChjKSBCZW50bGV5IFN5c3RlbXMsIEluY29ycG9yYXRlZC4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiogU2VlIExJQ0VOU0UubWQgaW4gdGhlIHByb2plY3Qgcm9vdCBmb3IgbGljZW5zZSB0ZXJtcyBhbmQgZnVsbCBjb3B5cmlnaHQgbm90aWNlLlxuKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cblxuLnN2ci10aWxlIHtcbiAgd2lkdGg6IHZhcigtLWl0d2luLXN2ci10aWxlLXdpZHRoLCBjYWxjKDggKiB2YXIoLS1pdWktc2l6ZS14bCkpKTtcbn1cblxuLnN2ci10aWxlIC5zdnItdGlsZS10aHVtYm5haWwge1xuICBoZWlnaHQ6IHZhcigtLWl0d2luLXN2ci10aHVtYm5haWwtaGVpZ2h0LCBjYWxjKDQgKiB2YXIoLS1pdWktc2l6ZS14bCkpKTtcbn1cblxuLnN2ci10aWxlIC5zdnItdGlsZS1uYW1lIHtcbiAgaGVpZ2h0OiBjYWxjKHZhcigtLWl1aS1zaXplLWwpICsgMnB4KTtcbiAgdXNlci1zZWxlY3Q6IHVuc2V0O1xufVxuXG4uc3ZyLXRpbGUtLW1ldGFkYXRhIHtcbiAgZGlzcGxheTogZ3JpZDtcbiAgZ3JpZDogMWZyIC8gYXV0byBtaW5tYXgoMCwgMWZyKSBhdXRvO1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xufVxuXG4uc3ZyLXRpbGUtLW1ldGFkYXRhID4gc3ZnIHtcbiAgbWFyZ2luLXJpZ2h0OiB2YXIoLS1pdWktc2l6ZS14cyk7XG59XG5cbi5zdnItdGlsZS0tdGFnLWNvbnRhaW5lciB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGdhcDogdmFyKC0taXVpLXNpemUtcyk7XG59XG5cbi5zdnItdGlsZS0tdGFnIHtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XG4gIHdoaXRlLXNwYWNlOiBub3dyYXA7XG4gIG92ZXJmbG93OiBoaWRkZW47XG4gIG1pbi13aWR0aDogMDtcbn1cblxuLnN2ci10aWxlLS10YWctb3ZlcmZsb3cge1xuICBtYXJnaW4tbGVmdDogdmFyKC0taXVpLXNpemUtcyk7XG59XG5cbi5zdnItdGlsZS0tbW9yZS1vcHRpb25zIHtcbiAgei1pbmRleDogMjtcbiAgZ3JpZC1hcmVhOiAxIC8gMSAvIC0xIC8gLTE7XG4gIHBsYWNlLXNlbGY6IGVuZDtcbiAgbWFyZ2luOiAwO1xuICBtYXJnaW4taW5saW5lLWVuZDogY2FsYygtMSp2YXIoLS1pdWktc2l6ZS0yeHMpKTtcbiAgZGlzcGxheTogZ3JpZDtcbiAgcG9zaXRpb246IGFic29sdXRlO1xufVxuXG4uc3ZyLXRpbGU6bm90KDpob3ZlciwgOmZvY3VzLXdpdGhpbikgLnN2ci10aWxlLS1tb3JlLW9wdGlvbnM6d2hlcmUoOm5vdCguc3ZyLXZpc2libGUpKSB7XG4gIHZpc2liaWxpdHk6IGhpZGRlbjtcbn1cblxuLnN2ci10aWxlLS1pY29uLWNvbnRhaW5lciB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIG1hcmdpbi10b3A6IGNhbGMoMC41ICogdmFyKC0taXVpLXNpemUtcykpO1xuICBtYXJnaW4taW5saW5lOiB2YXIoLS1pdWktc2l6ZS14cyk7XG4gIGdhcDogdmFyKC0taXVpLXNpemUtMnhzKTtcbiAgei1pbmRleDogMTtcbn1cblxuLnN2ci10aWxlLS1pY29uIHtcbiAgYm9yZGVyLXJhZGl1czogNTAlO1xuICBiYWNrZ3JvdW5kOiByZ2IoMCwgMCwgMCwgdmFyKC0taXVpLW9wYWNpdHktMykpO1xuICBtaW4td2lkdGg6IHZhcigtLWl1aS1jb21wb25lbnQtaGVpZ2h0LXNtYWxsKTtcbiAgbWluLWhlaWdodDogdmFyKC0taXVpLWNvbXBvbmVudC1oZWlnaHQtc21hbGwpO1xuICBkaXNwbGF5OiBmbGV4O1xuICBwbGFjZS1pdGVtczogY2VudGVyO1xuICBwYWRkaW5nLWlubGluZTogdmFyKC0taXVpLXNpemUtMnhzKTtcbiAgYm9yZGVyOiAxcHggc29saWQgdHJhbnNwYXJlbnQ7XG59XG5cbi5zdnItdGlsZS0taWNvbiBzdmcge1xuICBmaWxsOiB2YXIoLS1pdWktY29sb3Itd2hpdGUpO1xufVxuXG4uc3ZyLXRpbGUtLWVkaXRhYmxlLXRpdGxlID4gc3BhbiB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGdhcDogdmFyKC0taXVpLXNpemUtcyk7XG59XG4iXX0= */
@@ -0,0 +1,55 @@
1
+ import { type ReactElement, type ReactNode } from "react";
2
+ import type { SavedView, SavedViewTag } from "../SavedView.js";
3
+ import "./SavedViewTile.css";
4
+ interface SavedViewTileProps {
5
+ /** A Saved View that is being represented by the tile. */
6
+ savedView: SavedView;
7
+ /** A collection of available Saved View tags. Used for displaying tags on the tile. */
8
+ tags?: Map<string, SavedViewTag> | undefined;
9
+ /** When `true`, the tile becomes non-interactive and tile editing controls are shown. */
10
+ editable?: boolean | undefined;
11
+ /** Overrides icons that are displayed on the top-left of the Saved View thumbnail. */
12
+ leftIcons?: ReactNode[] | undefined;
13
+ /** Overrides icons that are displayed on the top-right of the Saved View thumbnail. */
14
+ rightIcons?: ReactNode[] | undefined;
15
+ /** Items to be added to the tile options menu. */
16
+ options?: ((close: () => void) => ReactElement[]) | ReactElement[] | undefined;
17
+ /**
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.
21
+ *
22
+ * @example
23
+ * <SavedViewTile savedView={savedView} onRename={handleRename} editable />
24
+ */
25
+ onRename?: ((savedViewId: string, newName: string) => void) | undefined;
26
+ /**
27
+ * Click handler meant for triggering the render of iModel onto the screen with the saved view applied
28
+ */
29
+ onClick?: ((selectedViewId: string) => void) | undefined;
30
+ /** Sets `className` of the top-level tile element. */
31
+ className?: string | undefined;
32
+ }
33
+ /**
34
+ * Displays Saved View information within a tile component.
35
+ *
36
+ * @example
37
+ * <SavedViewTile
38
+ * savedView={savedView}
39
+ * tags={savedViewTags}
40
+ * options={[<SavedViewOptions.Rename key="rename" icon={<SvgBlank />} />]}
41
+ * onRename={handleRename}
42
+ * />
43
+ */
44
+ export declare function SavedViewTile(props: SavedViewTileProps): ReactElement;
45
+ interface EditableTileNameProps {
46
+ displayName: string;
47
+ actions: {
48
+ onStartEditing: () => void;
49
+ onEndEditing: (newName: string) => void;
50
+ };
51
+ editing?: boolean | undefined;
52
+ editable?: boolean | undefined;
53
+ }
54
+ export declare function EditableTileName(props: EditableTileNameProps): ReactElement;
55
+ export {};
@@ -0,0 +1,110 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /*---------------------------------------------------------------------------------------------
3
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
4
+ * See LICENSE.md in the project root for license terms and full copyright notice.
5
+ *--------------------------------------------------------------------------------------------*/
6
+ import { SvgEdit, SvgImageFrame, SvgMore, SvgShare, SvgTag } from "@itwin/itwinui-icons-react";
7
+ import { Button, IconButton, Input, Text, Tile } from "@itwin/itwinui-react";
8
+ import { useLayoutEffect, useMemo, useRef, useState, } from "react";
9
+ import { LayeredDropdownMenu } from "../LayeredDropdownMenu/LayeredDropdownMenu.js";
10
+ import { useSavedViewsContext } from "../SavedViewsContext.js";
11
+ import { trimInputString } from "../utils.js";
12
+ import { SavedViewTileContextProvider } from "./SavedViewTileContext.js";
13
+ import "./SavedViewTile.css";
14
+ /**
15
+ * Displays Saved View information within a tile component.
16
+ *
17
+ * @example
18
+ * <SavedViewTile
19
+ * savedView={savedView}
20
+ * tags={savedViewTags}
21
+ * options={[<SavedViewOptions.Rename key="rename" icon={<SvgBlank />} />]}
22
+ * onRename={handleRename}
23
+ * />
24
+ */
25
+ export function SavedViewTile(props) {
26
+ const { localization } = useSavedViewsContext();
27
+ const [editingName, setEditingName] = useState(false);
28
+ const savedViewTags = useMemo(() => {
29
+ const tags = props.tags;
30
+ if (!tags || !props.savedView.tagIds) {
31
+ return [];
32
+ }
33
+ return props.savedView.tagIds.map((id) => tags.get(id)).filter(tag => tag);
34
+ }, [props.savedView.tagIds, props.tags]);
35
+ const [numShownTags, setNumShownTags] = useState(savedViewTags.length);
36
+ const metadataRef = useRef(null);
37
+ const metadata = (_jsxs("div", { className: "svr-tile--metadata", children: [savedViewTags.length > 0 && _jsx(SvgTag, {}), _jsx("div", { ref: metadataRef, className: "svr-tile--tag-container", children: savedViewTags.slice(0, numShownTags).map((tag, i) => (_jsx("div", { className: "svr-tile--tag", style: { flexShrink: i === numShownTags - 1 ? "unset" : 0 }, children: tag.displayName }, tag.id))) }), numShownTags < savedViewTags.length &&
38
+ _jsx(Text, { className: "svr-tile--tag-overflow", variant: "small", children: `+${savedViewTags.length - numShownTags} ${localization.tile.moreTags}` })] }));
39
+ useLayoutEffect(() => { setNumShownTags(savedViewTags.length); }, [savedViewTags]);
40
+ useLayoutEffect(() => {
41
+ const metadataDiv = metadataRef.current;
42
+ if (!metadataDiv || numShownTags <= 1) {
43
+ return;
44
+ }
45
+ // The following check is a workaround for false positive overflow detection in Firefox
46
+ if (!isOverflowing(metadataDiv) && !isOverflowing(metadataDiv.lastChild)) {
47
+ return;
48
+ }
49
+ const metadataRightEdge = metadataDiv.getBoundingClientRect().right;
50
+ for (let i = 1; i < numShownTags; ++i) {
51
+ const child = metadataDiv.children[i];
52
+ if (isOverflowing(child) || child.getBoundingClientRect().right > metadataRightEdge) {
53
+ setNumShownTags(i);
54
+ return;
55
+ }
56
+ }
57
+ }, [numShownTags]);
58
+ const rightIcons = props.rightIcons ?? (props.savedView.shared ? [_jsx(SvgShare, {}, "share")] : []);
59
+ const savedViewTileContext = useMemo(() => ({ savedView: props.savedView, setEditingName }), [props.savedView]);
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
+ onStartEditing: () => setEditingName(true),
62
+ onEndEditing: (newName) => {
63
+ setEditingName(false);
64
+ if (newName !== props.savedView.displayName) {
65
+ props.onRename?.(props.savedView.id, newName);
66
+ }
67
+ },
68
+ }, editable: props.editable || editingName }) }), _jsxs(Tile.ThumbnailArea, { className: "svr-tile-thumbnail", children: [typeof props.savedView.thumbnail === "string"
69
+ ? _jsx(Tile.ThumbnailPicture, { url: props.savedView.thumbnail })
70
+ : props.savedView.thumbnail
71
+ ? 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 &&
73
+ _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
+ }
75
+ function isOverflowing(element) {
76
+ return element.offsetWidth < element.scrollWidth;
77
+ }
78
+ export function EditableTileName(props) {
79
+ const { actions } = props;
80
+ if (!props.editable) {
81
+ return _jsx(_Fragment, { children: props.displayName });
82
+ }
83
+ if (props.editing) {
84
+ const handleFocus = (ev) => {
85
+ ev.target.select();
86
+ };
87
+ 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));
92
+ };
93
+ const handleKeyDown = (ev) => {
94
+ if (ev.key === "Enter") {
95
+ const value = ev.target.value;
96
+ handleEndEditing(value);
97
+ return;
98
+ }
99
+ if (ev.key === "Escape") {
100
+ actions.onEndEditing(props.displayName);
101
+ return;
102
+ }
103
+ };
104
+ return (_jsx(Input, { size: "small", onBlur: handleBlur, onFocus: handleFocus, onKeyDown: handleKeyDown, defaultValue: props.displayName, placeholder: props.displayName, autoFocus: true }));
105
+ }
106
+ return (_jsxs(Button, { className: "svr-tile--editable-title", styleType: "borderless", size: "small", onClick: () => actions.onStartEditing(), children: [props.displayName, _jsx(SvgEdit, {})] }));
107
+ }
108
+ function TileIconContainer(props) {
109
+ return (_jsx("div", { className: "svr-tile--icon-container", style: props.style, children: props.icons?.map((icon) => (_jsx("div", { className: "svr-tile--icon", children: icon }, icon?.key))) }));
110
+ }
@@ -0,0 +1,14 @@
1
+ /// <reference types="react" />
2
+ import type { SavedView } from "../SavedView.js";
3
+ /** Context that's accessable within `<SavedViewTile />` component. */
4
+ export interface SavedViewTileContext {
5
+ savedView: SavedView;
6
+ setEditingName: (value: boolean) => void;
7
+ }
8
+ /** @internal */
9
+ export declare const SavedViewTileContextProvider: import("react").Provider<SavedViewTileContext | undefined>;
10
+ /**
11
+ * Context that's accessable within `<SavedViewTile />` component. You can use this to make custom actions for
12
+ * `SavedViewTile`.
13
+ */
14
+ export declare function useSavedViewTileContext(): SavedViewTileContext;
@@ -0,0 +1,20 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import { createContext, useContext } from "react";
6
+ const savedViewTileContext = createContext(undefined);
7
+ savedViewTileContext.displayName = "SavedViewTileContext";
8
+ /** @internal */
9
+ export const SavedViewTileContextProvider = savedViewTileContext.Provider;
10
+ /**
11
+ * Context that's accessable within `<SavedViewTile />` component. You can use this to make custom actions for
12
+ * `SavedViewTile`.
13
+ */
14
+ export function useSavedViewTileContext() {
15
+ const contextValue = useContext(savedViewTileContext);
16
+ return contextValue ?? {
17
+ savedView: { id: "SavedViewTileContext_NoContext", displayName: "" },
18
+ setEditingName: () => { },
19
+ };
20
+ }
@@ -0,0 +1,30 @@
1
+ import { type SavedViewWithDataRepresentation } from "@itwin/saved-views-client";
2
+ import type { SavedView, SavedViewGroup, SavedViewTag } from "../SavedView.js";
3
+ import type { CreateGroupParams, CreateSavedViewParams, CreateTagParams, DeleteGroupParams, DeleteSavedViewParams, DeleteTagParams, GetSavedViewInfoParams, GetSingularSavedViewParams, GetThumbnailUrlParams, SavedViewInfo, SavedViewsClient, UpdateGroupParams, UpdateSavedViewParams, UpdateTagParams } from "./SavedViewsClient.js";
4
+ interface ITwinSavedViewsClientParams {
5
+ /** @default "https://api.bentley.com/savedviews" */
6
+ getAccessToken: () => Promise<string>;
7
+ /**
8
+ * Authorization token that grants access to iTwin Saved Views API. The token should be valid for `savedviews:read`
9
+ * and `savedviews:modify` OIDC scopes.
10
+ */
11
+ baseUrl?: string | undefined;
12
+ }
13
+ /** */
14
+ export declare class ITwinSavedViewsClient implements SavedViewsClient {
15
+ private client;
16
+ constructor(args: ITwinSavedViewsClientParams);
17
+ getSavedViewInfo(args: GetSavedViewInfoParams): Promise<SavedViewInfo>;
18
+ getSingularSavedView(args: GetSingularSavedViewParams): Promise<SavedViewWithDataRepresentation>;
19
+ getThumbnailUrl(args: GetThumbnailUrlParams): Promise<string | undefined>;
20
+ createSavedView(args: CreateSavedViewParams): Promise<SavedView>;
21
+ updateSavedView(args: UpdateSavedViewParams): Promise<SavedView>;
22
+ deleteSavedView(args: DeleteSavedViewParams): Promise<void>;
23
+ createGroup(args: CreateGroupParams): Promise<SavedViewGroup>;
24
+ updateGroup(args: UpdateGroupParams): Promise<SavedViewGroup>;
25
+ deleteGroup(args: DeleteGroupParams): Promise<void>;
26
+ createTag(args: CreateTagParams): Promise<SavedViewTag>;
27
+ updateTag(args: UpdateTagParams): Promise<SavedViewTag>;
28
+ deleteTag(args: DeleteTagParams): Promise<void>;
29
+ }
30
+ export {};
@@ -0,0 +1,132 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import { ITwinSavedViewsClient as Client, } from "@itwin/saved-views-client";
6
+ /** */
7
+ export class ITwinSavedViewsClient {
8
+ client;
9
+ constructor(args) {
10
+ this.client = new Client(args);
11
+ }
12
+ async getSavedViewInfo(args) {
13
+ const [{ savedViews }, { groups }, { tags }] = await Promise.all([
14
+ this.client.getAllSavedViewsMinimal(args),
15
+ this.client.getAllGroups(args),
16
+ this.client.getAllTags(args),
17
+ ]);
18
+ return {
19
+ savedViews: savedViews.map(savedViewResponseToSavedView),
20
+ groups,
21
+ tags,
22
+ };
23
+ }
24
+ async getSingularSavedView(args) {
25
+ const response = await this.client.getSavedViewRepresentation({
26
+ savedViewId: args.savedViewId,
27
+ signal: args.signal,
28
+ });
29
+ return response.savedView;
30
+ }
31
+ async getThumbnailUrl(args) {
32
+ const response = await this.client.getImage({
33
+ savedViewId: args.savedViewId,
34
+ size: "thumbnail",
35
+ signal: args.signal,
36
+ });
37
+ return response.href;
38
+ }
39
+ async createSavedView(args) {
40
+ const { savedView } = await this.client.createSavedView({
41
+ iTwinId: args.iTwinId,
42
+ iModelId: args.iModelId,
43
+ displayName: args.savedView.displayName,
44
+ tagIds: args.savedView.tagIds,
45
+ groupId: args.savedView.groupId,
46
+ shared: args.savedView.shared,
47
+ savedViewData: args.savedViewData,
48
+ signal: args.signal,
49
+ });
50
+ return savedViewResponseToSavedView(savedView);
51
+ }
52
+ async updateSavedView(args) {
53
+ const { savedView } = await this.client.updateSavedView({
54
+ savedViewId: args.savedView.id,
55
+ displayName: args.savedView.displayName,
56
+ tagIds: args.savedView.tagIds,
57
+ groupId: args.savedView.groupId,
58
+ shared: args.savedView.shared,
59
+ savedViewData: args.savedViewData,
60
+ extensions: args.extensions,
61
+ signal: args.signal,
62
+ });
63
+ return savedViewResponseToSavedView(savedView);
64
+ }
65
+ async deleteSavedView(args) {
66
+ await this.client.deleteSavedView({ savedViewId: args.savedViewId, signal: args.signal });
67
+ }
68
+ async createGroup(args) {
69
+ const { group } = await this.client.createGroup({
70
+ iTwinId: args.iTwinId,
71
+ iModelId: args.iModelId,
72
+ displayName: args.group.displayName,
73
+ signal: args.signal,
74
+ });
75
+ return groupResponseToSavedViewGroup(group);
76
+ }
77
+ async updateGroup(args) {
78
+ const { group } = await this.client.updateGroup({
79
+ groupId: args.group.id,
80
+ displayName: args.group.displayName,
81
+ shared: args.group.shared,
82
+ signal: args.signal,
83
+ });
84
+ return groupResponseToSavedViewGroup(group);
85
+ }
86
+ async deleteGroup(args) {
87
+ await this.client.deleteGroup({ groupId: args.groupId, signal: args.signal });
88
+ }
89
+ async createTag(args) {
90
+ const { tag } = await this.client.createTag({
91
+ iTwinId: args.iTwinId,
92
+ iModelId: args.iModelId,
93
+ displayName: args.displayName,
94
+ signal: args.signal,
95
+ });
96
+ return tagResponseToSavedViewTag(tag);
97
+ }
98
+ async updateTag(args) {
99
+ const { tag } = await this.client.updateTag({
100
+ tagId: args.tag.id,
101
+ displayName: args.tag.displayName,
102
+ signal: args.signal,
103
+ });
104
+ return tagResponseToSavedViewTag(tag);
105
+ }
106
+ async deleteTag(args) {
107
+ await this.client.deleteTag({ tagId: args.tagId, signal: args.signal });
108
+ }
109
+ }
110
+ function savedViewResponseToSavedView(response) {
111
+ return {
112
+ id: response.id,
113
+ displayName: response.displayName,
114
+ tagIds: response.tags?.map((tag) => tag.id),
115
+ groupId: response._links.group?.href.split("/").at(-1),
116
+ shared: response.shared,
117
+ thumbnail: undefined,
118
+ };
119
+ }
120
+ function groupResponseToSavedViewGroup(response) {
121
+ return {
122
+ id: response.id,
123
+ displayName: response.displayName,
124
+ shared: response.shared,
125
+ };
126
+ }
127
+ function tagResponseToSavedViewTag(response) {
128
+ return {
129
+ id: response.id,
130
+ displayName: response.displayName,
131
+ };
132
+ }
@@ -0,0 +1,72 @@
1
+ import type { ExtensionMin, ExtensionSavedViewCreate, SavedViewWithDataRepresentation, ViewData } from "@itwin/saved-views-client";
2
+ import type { SavedView, SavedViewGroup, SavedViewTag } from "../SavedView.js";
3
+ export interface SavedViewInfo {
4
+ savedViews: SavedView[];
5
+ groups: SavedViewGroup[];
6
+ tags: SavedViewTag[];
7
+ }
8
+ export interface SavedViewsClient {
9
+ getSavedViewInfo: (args: GetSavedViewInfoParams) => Promise<SavedViewInfo>;
10
+ getSingularSavedView: (args: GetSingularSavedViewParams) => Promise<SavedViewWithDataRepresentation>;
11
+ getThumbnailUrl: (args: GetThumbnailUrlParams) => Promise<string | undefined>;
12
+ createSavedView: (args: CreateSavedViewParams) => Promise<SavedView>;
13
+ updateSavedView: (args: UpdateSavedViewParams) => Promise<SavedView>;
14
+ deleteSavedView: (args: DeleteSavedViewParams) => Promise<void>;
15
+ createGroup: (args: CreateGroupParams) => Promise<SavedViewGroup>;
16
+ updateGroup: (args: UpdateGroupParams) => Promise<SavedViewGroup>;
17
+ deleteGroup: (args: DeleteGroupParams) => Promise<void>;
18
+ createTag: (args: CreateTagParams) => Promise<SavedViewTag>;
19
+ updateTag: (args: UpdateTagParams) => Promise<SavedViewTag>;
20
+ deleteTag: (args: DeleteTagParams) => Promise<void>;
21
+ }
22
+ export interface GetSavedViewInfoParams extends CommonParams {
23
+ iTwinId: string;
24
+ iModelId?: string | undefined;
25
+ }
26
+ export interface GetSingularSavedViewParams extends CommonParams {
27
+ savedViewId: string;
28
+ }
29
+ export interface GetThumbnailUrlParams extends CommonParams {
30
+ savedViewId: string;
31
+ }
32
+ export interface CreateSavedViewParams extends CommonParams {
33
+ iTwinId: string;
34
+ iModelId?: string | undefined;
35
+ savedView: Pick<SavedView, "displayName" | "tagIds" | "groupId" | "shared">;
36
+ savedViewData: ViewData;
37
+ extensions?: ExtensionSavedViewCreate[] | undefined;
38
+ }
39
+ export interface UpdateSavedViewParams extends CommonParams {
40
+ savedView: Pick<SavedView, "id"> & Partial<SavedView>;
41
+ savedViewData?: ViewData | undefined;
42
+ extensions?: ExtensionMin[] | undefined;
43
+ }
44
+ export interface DeleteSavedViewParams extends CommonParams {
45
+ savedViewId: string;
46
+ }
47
+ export interface CreateGroupParams extends CommonParams {
48
+ iTwinId: string;
49
+ iModelId?: string | undefined;
50
+ group: Pick<SavedViewGroup, "displayName" | "shared">;
51
+ }
52
+ export interface UpdateGroupParams extends CommonParams {
53
+ group: Pick<SavedViewGroup, "id"> & Partial<SavedViewGroup>;
54
+ }
55
+ export interface DeleteGroupParams extends CommonParams {
56
+ groupId: string;
57
+ }
58
+ export interface CreateTagParams extends CommonParams {
59
+ iTwinId: string;
60
+ iModelId?: string;
61
+ displayName: string;
62
+ }
63
+ export interface UpdateTagParams extends CommonParams {
64
+ tag: Pick<SavedViewTag, "id"> & Partial<SavedViewTag>;
65
+ }
66
+ export interface DeleteTagParams extends CommonParams {
67
+ tagId: string;
68
+ }
69
+ interface CommonParams {
70
+ signal?: AbortSignal | undefined;
71
+ }
72
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ import { type PropsWithChildren, type ReactElement } from "react";
2
+ import { defaultLocalization, type LocalizationStrings } from "./localization.js";
3
+ export interface SavedViewsContext {
4
+ localization: typeof defaultLocalization;
5
+ }
6
+ interface SavedViewsContextProviderProps {
7
+ /** Custom strings to be used within `@itwin/saved-views-react` React components. */
8
+ localization?: LocalizationStrings | undefined;
9
+ }
10
+ /** React context for `@itwin/saved-views-react` components. Optional. */
11
+ export declare function SavedViewsContextProvider(props: PropsWithChildren<SavedViewsContextProviderProps>): ReactElement;
12
+ export declare function useSavedViewsContext(): SavedViewsContext;
13
+ export {};
@@ -0,0 +1,38 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /*---------------------------------------------------------------------------------------------
3
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
4
+ * See LICENSE.md in the project root for license terms and full copyright notice.
5
+ *--------------------------------------------------------------------------------------------*/
6
+ import { createContext, useContext, useMemo } from "react";
7
+ import { defaultLocalization } from "./localization.js";
8
+ const savedViewsContext = createContext({ localization: defaultLocalization });
9
+ savedViewsContext.displayName = "SavedViewsContext";
10
+ /** React context for `@itwin/saved-views-react` components. Optional. */
11
+ export function SavedViewsContextProvider(props) {
12
+ const localization = useMemo(() => {
13
+ if (!props.localization) {
14
+ return defaultLocalization;
15
+ }
16
+ const localization = { ...defaultLocalization };
17
+ replaceStringsRecursively(props.localization, localization);
18
+ return localization;
19
+ }, [props.localization]);
20
+ const contextValue = useMemo(() => ({ localization }), [localization]);
21
+ return (_jsx(savedViewsContext.Provider, { value: contextValue, children: props.children }));
22
+ }
23
+ export function useSavedViewsContext() {
24
+ return useContext(savedViewsContext);
25
+ }
26
+ function replaceStringsRecursively(source, destination) {
27
+ for (const key in source) {
28
+ if (!Object.hasOwnProperty.call(destination, key)) {
29
+ return;
30
+ }
31
+ if (typeof source[key] === "string") {
32
+ destination[key] = source[key];
33
+ }
34
+ else {
35
+ replaceStringsRecursively(source[key], destination[key]);
36
+ }
37
+ }
38
+ }
@@ -0,0 +1,9 @@
1
+ import type { ReactElement } from "react";
2
+ export declare const SavedViewGroupOptions: {
3
+ Rename: typeof Rename;
4
+ };
5
+ interface RenameProps {
6
+ icon?: ReactElement | undefined;
7
+ }
8
+ declare function Rename(props: RenameProps): ReactElement;
9
+ export {};
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /*---------------------------------------------------------------------------------------------
3
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
4
+ * See LICENSE.md in the project root for license terms and full copyright notice.
5
+ *--------------------------------------------------------------------------------------------*/
6
+ import { MenuItem } from "@itwin/itwinui-react";
7
+ import { useSavedViewGroupTileContext } from "./SavedViewGroupTileContext.js";
8
+ export const SavedViewGroupOptions = {
9
+ Rename,
10
+ };
11
+ function Rename(props) {
12
+ const { setEditingName } = useSavedViewGroupTileContext();
13
+ return _jsx(MenuItem, { startIcon: props.icon, onClick: () => setEditingName(true), children: "Rename" });
14
+ }
@@ -0,0 +1,14 @@
1
+ import { type ReactElement, type ReactNode } from "react";
2
+ import type { SavedViewGroup } from "../../SavedView.js";
3
+ interface SavedViewGroupTileProps {
4
+ group: SavedViewGroup;
5
+ numItems: number;
6
+ onOpen: (groupId: string) => void;
7
+ focused?: boolean | undefined;
8
+ initialScrollTop: number;
9
+ editable?: boolean | undefined;
10
+ options?: ReactNode[] | undefined;
11
+ onRename?: ((groupId: string, newName: string) => void) | undefined;
12
+ }
13
+ export declare function SavedViewGroupTile(props: SavedViewGroupTileProps): ReactElement;
14
+ export {};