bruce-cesium 7.0.9 → 7.1.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 (29) hide show
  1. package/dist/bruce-cesium.es5.js +1837 -134
  2. package/dist/bruce-cesium.es5.js.map +1 -1
  3. package/dist/bruce-cesium.umd.js +1831 -131
  4. package/dist/bruce-cesium.umd.js.map +1 -1
  5. package/dist/lib/bruce-cesium.js +3 -1
  6. package/dist/lib/bruce-cesium.js.map +1 -1
  7. package/dist/lib/rendering/visual-register-culler.js +18 -1
  8. package/dist/lib/rendering/visual-register-culler.js.map +1 -1
  9. package/dist/lib/utils/entity-utils.js +52 -2
  10. package/dist/lib/utils/entity-utils.js.map +1 -1
  11. package/dist/lib/widgets/tabs-left-panel/widget-left-panel-tab-bookmarks.js +427 -63
  12. package/dist/lib/widgets/tabs-left-panel/widget-left-panel-tab-bookmarks.js.map +1 -1
  13. package/dist/lib/widgets/tabs-left-panel/widget-left-panel-tab-dashboard.js +507 -0
  14. package/dist/lib/widgets/tabs-left-panel/widget-left-panel-tab-dashboard.js.map +1 -0
  15. package/dist/lib/widgets/tabs-left-panel/widget-left-panel-tab-menu-items.js +704 -0
  16. package/dist/lib/widgets/tabs-left-panel/widget-left-panel-tab-menu-items.js.map +1 -0
  17. package/dist/lib/widgets/widget-bookmarks.js +9 -7
  18. package/dist/lib/widgets/widget-bookmarks.js.map +1 -1
  19. package/dist/lib/widgets/widget-info-view.js +68 -40
  20. package/dist/lib/widgets/widget-info-view.js.map +1 -1
  21. package/dist/lib/widgets/widget-left-panel.js +65 -18
  22. package/dist/lib/widgets/widget-left-panel.js.map +1 -1
  23. package/dist/types/bruce-cesium.d.ts +3 -1
  24. package/dist/types/utils/entity-utils.d.ts +11 -0
  25. package/dist/types/widgets/tabs-left-panel/widget-left-panel-tab-bookmarks.d.ts +14 -0
  26. package/dist/types/widgets/tabs-left-panel/widget-left-panel-tab-dashboard.d.ts +44 -0
  27. package/dist/types/widgets/tabs-left-panel/widget-left-panel-tab-menu-items.d.ts +64 -0
  28. package/dist/types/widgets/widget-left-panel.d.ts +10 -2
  29. package/package.json +1 -2
@@ -1,6 +1,6 @@
1
1
  import * as Cesium from 'cesium';
2
- import { Cartographic, ColorMaterialProperty, Entity, Color, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature, Math as Math$1, Cartesian3, JulianDate, Quaternion, Transforms, HeadingPitchRoll, Matrix4, DistanceDisplayCondition, HeightReference, ColorBlendMode, ShadowMode, ClassificationType, Model, HorizontalOrigin, VerticalOrigin, ConstantPositionProperty, ImageMaterialProperty, PolygonHierarchy, PolylineGraphics, ArcType, CornerType, Cartesian2, SceneTransforms, NearFarScalar, Matrix3, Rectangle, KmlDataSource, GeoJsonDataSource, SceneMode, Cesium3DTileStyle, HeadingPitchRange, Cesium3DTileColorBlendMode, Ion, IonResource, EllipsoidTerrainProvider, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, Cesium3DTileset, OrthographicFrustum, EasingFunction, BoundingSphere, Intersect, CustomDataSource, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, EllipsoidGeodesic, sampleTerrainMostDetailed, defined, GeometryInstance, PolygonPipeline, CesiumInspector, ClockRange, ScreenSpaceEventHandler, ScreenSpaceEventType, Fullscreen, CzmlDataSource } from 'cesium';
3
- import { Cartes, Entity as Entity$1, ENVIRONMENT, Calculator, ClientFile, EntityLod, EntityTag, EntityType, LRUCache, ObjectUtils, Style, Api, Bounds, Color as Color$1, Geometry, Carto, MenuItem, ProjectView, ProjectViewBookmark, Tileset, ZoomControl, BruceEvent, EntityCoords, DataLab, DelayQueue, EntityHistoricData, AccountConcept, RecordChangeFeed, BruceApi, EntityRelation, ProgramKey, EntitySource, ProjectViewLegacyTile, ProjectViewTile, Camera, EntityAttachment, EntityAttachmentType, EntityAttribute, MathUtils, Session, EntityRelationType } from 'bruce-models';
2
+ import { Cartographic, ColorMaterialProperty, Entity, Color, ConstantProperty, CallbackProperty, Primitive, Cesium3DTileFeature, DistanceDisplayCondition, HeightReference, ColorBlendMode, HeadingPitchRoll, Math as Math$1, Transforms, ShadowMode, Cartesian3, ClassificationType, Model, JulianDate, Quaternion, Matrix4, ArcType, CornerType, ConstantPositionProperty, HorizontalOrigin, VerticalOrigin, ImageMaterialProperty, PolygonHierarchy, PolylineGraphics, Cartesian2, SceneTransforms, NearFarScalar, Matrix3, Rectangle, KmlDataSource, GeoJsonDataSource, SceneMode, Cesium3DTileStyle, Cesium3DTileColorBlendMode, HeadingPitchRange, Ion, IonResource, Cesium3DTileset, EllipsoidTerrainProvider, IonImageryProvider, createWorldImagery, createWorldImageryAsync, BingMapsImageryProvider, BingMapsStyle, MapboxImageryProvider, MapboxStyleImageryProvider, ArcGisMapServerImageryProvider, OpenStreetMapImageryProvider, UrlTemplateImageryProvider, GridImageryProvider, GeographicTilingScheme, ImageryLayer, TileMapServiceImageryProvider, CesiumTerrainProvider, BoundingSphere, Intersect, OrthographicFrustum, EasingFunction, ModelGraphics, PolygonGraphics, CorridorGraphics, PointGraphics, BillboardGraphics, EllipseGraphics, PolylineDashMaterialProperty, EllipsoidGeodesic, sampleTerrainMostDetailed, defined, PolygonPipeline, CesiumInspector, ClockRange, GeometryInstance, CustomDataSource, ScreenSpaceEventHandler, ScreenSpaceEventType, Fullscreen, CzmlDataSource } from 'cesium';
3
+ import { Cartes, Entity as Entity$1, ENVIRONMENT, Calculator, ClientFile, EntityLod, EntityTag, EntityType, LRUCache, ObjectUtils, Style, Carto, Geometry, Api, Bounds, Color as Color$1, MenuItem, ProjectView, ProjectViewBookmark, Tileset, ZoomControl, BruceEvent, EntityCoords, DataLab, DelayQueue, EntityHistoricData, AccountConcept, RecordChangeFeed, EntityRelation, BruceApi, ProgramKey, EntitySource, ProjectViewLegacyTile, ProjectViewTile, Camera, Account, AccountLimits, Session, UrlUtils, ProjectViewBookmarkGroup, EntityAttachment, EntityAttachmentType, EntityAttribute, MathUtils, EntityRelationType } from 'bruce-models';
4
4
 
5
5
  /**
6
6
  * Ensures a number is returned from a given value.
@@ -6470,6 +6470,8 @@ function runCullChecker(register) {
6470
6470
  }
6471
6471
  const toRemove = [];
6472
6472
  const toAdd = [];
6473
+ // Entities the register has to re-evaluate, because the culler cannot restore a `show` it did not set.
6474
+ const toRefresh = new Set();
6473
6475
  const isIsolatedAny = register.GetIsIsolatedAny();
6474
6476
  const slice = entityIds.splice(0, CHECK_BATCH);
6475
6477
  for (let i = 0; i < slice.length; i++) {
@@ -6518,6 +6520,12 @@ function runCullChecker(register) {
6518
6520
  (!isIsolatedAny || state.isolated)) {
6519
6521
  toAdd.push(part);
6520
6522
  }
6523
+ else if (part.show === false &&
6524
+ rego.overrideShow != false &&
6525
+ !state.hidden &&
6526
+ (!isIsolatedAny || state.isolated)) {
6527
+ toRefresh.add(entityId);
6528
+ }
6521
6529
  }
6522
6530
  }
6523
6531
  }
@@ -6528,6 +6536,11 @@ function runCullChecker(register) {
6528
6536
  if (toAdd.length > 0) {
6529
6537
  addEntities(viewer, toAdd);
6530
6538
  }
6539
+ if (toRefresh.size > 0) {
6540
+ register.ForceUpdate({
6541
+ entityIds: Array.from(toRefresh)
6542
+ });
6543
+ }
6531
6544
  if (entityIds.length <= 0) {
6532
6545
  clearInterval(checkInterval);
6533
6546
  checkInterval = null;
@@ -6750,7 +6763,11 @@ var VisualRegisterCuller;
6750
6763
  return false;
6751
6764
  }
6752
6765
  if (visual instanceof Entity) {
6753
- return visual[VisualRegisterCuller.VISUAL_CULL_KEY] == true;
6766
+ if (visual[VisualRegisterCuller.VISUAL_CULL_KEY] != true) {
6767
+ return false;
6768
+ }
6769
+ // Invalidated, so the decision above was measured from geometry that no longer describes this.
6770
+ return boundingSphereCache.Get(visual.id) != null;
6754
6771
  }
6755
6772
  return false;
6756
6773
  }
@@ -24005,15 +24022,31 @@ var WidgetLeftPanelTab;
24005
24022
  WidgetLeftPanelTab.ATab = ATab;
24006
24023
  })(WidgetLeftPanelTab || (WidgetLeftPanelTab = {}));
24007
24024
 
24025
+ // Icons are inline so the library stays dependency free.
24026
+ const ICON_FOLDER = `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3 6C3 5.44772 3.44772 5 4 5H9L11 7.5H20C20.5523 7.5 21 7.94772 21 8.5V18C21 18.5523 20.5523 19 20 19H4C3.44772 19 3 18.5523 3 18V6Z" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/></svg>`;
24027
+ const ICON_FOLDER_OPEN = `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3 6C3 5.44772 3.44772 5 4 5H9L11 7.5H20C20.5523 7.5 21 7.94772 21 8.5V10H3V6Z" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/><path d="M3 10H21.5L19.5 18.5C19.4 18.8 19.1 19 18.8 19H4C3.44772 19 3 18.5523 3 18V10Z" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/></svg>`;
24028
+ const OPEN_STATE_STORAGE_PREFIX = "NextspaceBookmarkGroupOpen_";
24029
+ const COMPACT_MODE_STORAGE_KEY = "NextspaceBookmarksCompactMode";
24030
+ // Group id used for the synthetic list of bookmarks that belong to no group.
24031
+ const UNGROUPED_ID = null;
24008
24032
  class WidgetLeftPanelTabBookmarks extends WidgetLeftPanelTab.ATab {
24009
24033
  constructor(params) {
24034
+ var _a, _b;
24010
24035
  super(params);
24011
24036
  this.STYLESHEET_ID = "nextspace-left-panel-tab-bookmarks-stylesheet";
24037
+ this._compact = false;
24038
+ this._compact = this._getStoredCompact();
24012
24039
  this._generateStyles();
24013
24040
  this._generateElement();
24014
24041
  this._widget.Loading.then(() => {
24015
24042
  this._updateBookmarks();
24016
24043
  });
24044
+ // The panel can be opened before a view has rendered, so the list has to rebuild when one arrives.
24045
+ this._viewIdChangeRemoval = (_b = (_a = this._widget) === null || _a === void 0 ? void 0 : _a.OnViewIdChange) === null || _b === void 0 ? void 0 : _b.Subscribe(() => {
24046
+ this._widget.Loading.then(() => {
24047
+ this._updateBookmarks();
24048
+ });
24049
+ });
24017
24050
  // In case another widget messed with the panel width.
24018
24051
  // Probably should just add a SetWidth method to avoid having plugins mess with the container CSS.
24019
24052
  if (this.Container) {
@@ -24021,6 +24054,8 @@ class WidgetLeftPanelTabBookmarks extends WidgetLeftPanelTab.ATab {
24021
24054
  }
24022
24055
  }
24023
24056
  Dispose() {
24057
+ var _a;
24058
+ (_a = this._viewIdChangeRemoval) === null || _a === void 0 ? void 0 : _a.call(this);
24024
24059
  super.Dispose();
24025
24060
  }
24026
24061
  _generateStyles() {
@@ -24030,11 +24065,16 @@ class WidgetLeftPanelTabBookmarks extends WidgetLeftPanelTab.ATab {
24030
24065
  const style = document.createElement("style");
24031
24066
  style.id = this.STYLESHEET_ID;
24032
24067
  style.innerHTML = `
24068
+ .NextspaceLeftPanelTabBookmarks * {
24069
+ box-sizing: border-box;
24070
+ }
24071
+
24033
24072
  .NextspaceLeftPanelTabBookmarks {
24034
24073
  display: flex;
24035
24074
  flex-direction: column;
24036
24075
  flex-grow: 1;
24037
24076
  flex-shrink: 1;
24077
+ font-family: Arial, sans-serif;
24038
24078
  overflow: hidden;
24039
24079
  width: 100%;
24040
24080
  }
@@ -24060,6 +24100,59 @@ class WidgetLeftPanelTabBookmarks extends WidgetLeftPanelTab.ATab {
24060
24100
  margin-bottom: 15px;
24061
24101
  }
24062
24102
 
24103
+ .NextspaceLeftPanelTabBookmarksCompactBar {
24104
+ align-items: center;
24105
+ color: #fff;
24106
+ display: flex;
24107
+ flex-shrink: 0;
24108
+ font-size: 12px;
24109
+ justify-content: flex-end;
24110
+ margin-bottom: 10px;
24111
+ user-select: none;
24112
+ }
24113
+
24114
+ .NextspaceLeftPanelTabBookmarksCompactToggle {
24115
+ align-items: center;
24116
+ cursor: pointer;
24117
+ display: flex;
24118
+ opacity: .7;
24119
+ transition: opacity .3s ease;
24120
+ }
24121
+
24122
+ .NextspaceLeftPanelTabBookmarksCompactToggle:hover {
24123
+ opacity: 1;
24124
+ }
24125
+
24126
+ .NextspaceLeftPanelTabBookmarksCompactToggle >.NextspaceLeftPanelTabBookmarksCompactToggleTrack {
24127
+ background: rgba(255, 255, 255, .2);
24128
+ border-radius: 8px;
24129
+ height: 16px;
24130
+ margin-right: 8px;
24131
+ position: relative;
24132
+ transition: background .3s ease;
24133
+ width: 30px;
24134
+ }
24135
+
24136
+ .NextspaceLeftPanelTabBookmarksCompactToggle >.NextspaceLeftPanelTabBookmarksCompactToggleTrack:after {
24137
+ background: #fff;
24138
+ border-radius: 50%;
24139
+ content: "";
24140
+ height: 12px;
24141
+ left: 2px;
24142
+ position: absolute;
24143
+ top: 2px;
24144
+ transition: left .3s ease;
24145
+ width: 12px;
24146
+ }
24147
+
24148
+ .NextspaceLeftPanelTabBookmarksCompactToggle[is-on="true"] >.NextspaceLeftPanelTabBookmarksCompactToggleTrack {
24149
+ background: #33b1ff;
24150
+ }
24151
+
24152
+ .NextspaceLeftPanelTabBookmarksCompactToggle[is-on="true"] >.NextspaceLeftPanelTabBookmarksCompactToggleTrack:after {
24153
+ left: 16px;
24154
+ }
24155
+
24063
24156
  .NextspaceLeftPanelTabBookmarksList {
24064
24157
  display: flex;
24065
24158
  flex-direction: column;
@@ -24068,30 +24161,110 @@ class WidgetLeftPanelTabBookmarks extends WidgetLeftPanelTab.ATab {
24068
24161
  overflow: auto;
24069
24162
  }
24070
24163
 
24071
- .NextspaceLeftPanelTabBookmarksListItem {
24072
- margin-bottom: 15px;
24164
+ .NextspaceLeftPanelTabBookmarksGroupHeader {
24165
+ align-items: flex-end;
24166
+ border-left: 2px solid rgba(255, 255, 255, .2);
24167
+ color: #fff;
24168
+ cursor: pointer;
24169
+ display: flex;
24170
+ font-size: 12px;
24171
+ font-weight: 300;
24172
+ letter-spacing: .01em;
24173
+ padding-left: 8px;
24174
+ transition: border-left-color .3s ease;
24175
+ user-select: none;
24176
+ }
24177
+
24178
+ .NextspaceLeftPanelTabBookmarksGroupHeader:hover {
24179
+ border-left-color: rgba(255, 255, 255, .5);
24180
+ }
24181
+
24182
+ .NextspaceLeftPanelTabBookmarksGroupHeader[is-opened="false"] {
24183
+ margin-bottom: 10px;
24184
+ }
24185
+
24186
+ .NextspaceLeftPanelTabBookmarksGroupHeader[is-opened="true"] {
24187
+ padding-bottom: 5px;
24188
+ }
24189
+
24190
+ .NextspaceLeftPanelTabBookmarksGroupHeader >.NextspaceLeftPanelTabBookmarksGroupHeaderIcon {
24073
24191
  align-items: center;
24192
+ display: flex;
24193
+ flex-shrink: 0;
24194
+ height: 20px;
24195
+ justify-content: center;
24196
+ margin-right: 8px;
24197
+ width: 20px;
24198
+ }
24199
+
24200
+ .NextspaceLeftPanelTabBookmarksGroupHeader >.NextspaceLeftPanelTabBookmarksGroupHeaderIcon >svg {
24201
+ height: 20px;
24202
+ width: 20px;
24203
+ }
24204
+
24205
+ .NextspaceLeftPanelTabBookmarksGroupHeader >.NextspaceLeftPanelTabBookmarksGroupHeaderName {
24206
+ margin-right: 8px;
24207
+ opacity: .7;
24208
+ overflow: hidden;
24209
+ padding-bottom: 8px;
24210
+ text-overflow: ellipsis;
24211
+ white-space: nowrap;
24212
+ }
24213
+
24214
+ .NextspaceLeftPanelTabBookmarksGroupHeader >.NextspaceLeftPanelTabBookmarksGroupHeaderCount {
24215
+ margin-right: 3px;
24216
+ opacity: .7;
24217
+ padding-bottom: 8px;
24218
+ }
24219
+
24220
+ .NextspaceLeftPanelTabBookmarksGroupBody {
24074
24221
  display: flex;
24075
24222
  flex-direction: column;
24223
+ }
24224
+
24225
+ .NextspaceLeftPanelTabBookmarksGroupBody[is-grouped="true"] {
24226
+ border-left: 2px solid rgba(255, 255, 255, .2);
24227
+ margin-bottom: 12px;
24228
+ padding-left: 8px;
24229
+ }
24230
+
24231
+ .NextspaceLeftPanelTabBookmarksListItem {
24232
+ background: rgba(255, 255, 255, .05);
24233
+ border: 1px solid rgba(255, 255, 255, .1);
24234
+ border-radius: 8px;
24235
+ cursor: pointer;
24236
+ display: flex;
24237
+ flex-direction: column;
24238
+ margin-bottom: 6px;
24239
+ overflow: hidden;
24240
+ padding: 12px;
24241
+ transition: background .3s ease, border-color .3s ease, transform .3s ease;
24076
24242
  width: 100%;
24077
24243
  }
24078
24244
 
24079
- .NextspaceLeftPanelTabBookmarksListItem[is-selected="true"] >.NextspaceLeftPanelTabBookmarksListItemImageBox {
24080
- border: 3px solid #0072c3;
24245
+ .NextspaceLeftPanelTabBookmarksListItem:hover {
24246
+ background: rgba(255, 255, 255, .08);
24247
+ border-color: rgba(255, 255, 255, .2);
24248
+ transform: translateY(-2px);
24249
+ }
24250
+
24251
+ .NextspaceLeftPanelTabBookmarksListItem[is-selected="true"] {
24252
+ background: rgba(51, 177, 255, .1);
24253
+ border-color: #33b1ff;
24081
24254
  }
24082
24255
 
24083
24256
  .NextspaceLeftPanelTabBookmarksListItemImageBox {
24084
- border: 3px solid #0000;
24085
- border-radius: 5px;
24257
+ background-color: rgba(255, 255, 255, .05);
24258
+ border-radius: 6px;
24086
24259
  display: flex;
24087
- height: 132px;
24260
+ flex-shrink: 0;
24261
+ height: 120px;
24088
24262
  margin-bottom: 8px;
24089
24263
  overflow: hidden;
24090
24264
  width: 100%;
24091
24265
  }
24092
24266
 
24093
24267
  .NextspaceLeftPanelTabBookmarksListItemImageBoxImage {
24094
- cursor: pointer;
24095
24268
  display: flex;
24096
24269
  flex-direction: column;
24097
24270
  flex-grow: 1;
@@ -24107,25 +24280,59 @@ class WidgetLeftPanelTabBookmarks extends WidgetLeftPanelTab.ATab {
24107
24280
  width: 100%;
24108
24281
  }
24109
24282
 
24110
- .NextspaceLeftPanelTabBookmarksListItemTitle {
24111
- color: #fff;
24112
- display: flex;
24113
- padding-right: 15px;
24114
- text-align: center;
24115
- width: 100%;
24116
- }
24117
-
24118
24283
  .NextspaceLeftPanelTabBookmarksListItemTitleText {
24284
+ color: #f2f4f8;
24119
24285
  display: block;
24120
- margin-left: 35px;
24121
- margin-right: 20px;
24286
+ font-family: Arial;
24287
+ font-size: 13px;
24288
+ font-weight: 600;
24122
24289
  overflow: hidden;
24123
- text-align: center;
24124
24290
  text-overflow: ellipsis;
24125
24291
  white-space: nowrap;
24126
24292
  width: 100%;
24127
- font-family: Arial;
24293
+ }
24294
+
24295
+ .NextspaceLeftPanelTabBookmarksListItemDescription {
24296
+ color: rgba(255, 255, 255, .7);
24297
+ font-size: 12px;
24298
+ margin-top: 4px;
24299
+ overflow: hidden;
24300
+ width: 100%;
24301
+ }
24302
+
24303
+ .NextspaceLeftPanelTabBookmarks[is-compact="true"] .NextspaceLeftPanelTabBookmarksListItem {
24304
+ align-items: center;
24305
+ flex-direction: row;
24306
+ margin-bottom: 4px;
24307
+ min-height: 54px;
24308
+ padding: 0;
24309
+ transform: none;
24310
+ }
24311
+
24312
+ .NextspaceLeftPanelTabBookmarks[is-compact="true"] .NextspaceLeftPanelTabBookmarksListItemImageBox {
24313
+ border-radius: 8px 0 0 8px;
24314
+ border-right: 1px solid #6a6a6a;
24315
+ height: 60px;
24316
+ margin-bottom: 0;
24317
+ margin-right: 10px;
24318
+ width: 70px;
24319
+ }
24320
+
24321
+ .NextspaceLeftPanelTabBookmarks[is-compact="true"] .NextspaceLeftPanelTabBookmarksListItemTitleText {
24322
+ font-size: 12px;
24323
+ font-weight: 400;
24324
+ padding-right: 10px;
24325
+ text-align: right;
24326
+ }
24327
+
24328
+ .NextspaceLeftPanelTabBookmarks[is-compact="true"] .NextspaceLeftPanelTabBookmarksListItemDescription {
24329
+ display: none;
24330
+ }
24331
+
24332
+ .NextspaceLeftPanelTabBookmarksEmpty {
24333
+ color: #fff;
24128
24334
  font-size: 13px;
24335
+ opacity: .7;
24129
24336
  }
24130
24337
  `;
24131
24338
  document.head.appendChild(style);
@@ -24133,6 +24340,7 @@ class WidgetLeftPanelTabBookmarks extends WidgetLeftPanelTab.ATab {
24133
24340
  _generateElement() {
24134
24341
  const element = document.createElement("div");
24135
24342
  element.className = "NextspaceLeftPanelTabBookmarks";
24343
+ element.setAttribute("is-compact", String(this._compact));
24136
24344
  const title = document.createElement("div");
24137
24345
  title.className = "NextspaceLeftPanelTabBookmarksTitleBar";
24138
24346
  title.textContent = "Bookmarks";
@@ -24140,52 +24348,224 @@ class WidgetLeftPanelTabBookmarks extends WidgetLeftPanelTab.ATab {
24140
24348
  const breaker = document.createElement("div");
24141
24349
  breaker.className = "NextspaceLeftPanelTabBookmarksTitleBreaker";
24142
24350
  element.appendChild(breaker);
24351
+ const compactBar = document.createElement("div");
24352
+ compactBar.className = "NextspaceLeftPanelTabBookmarksCompactBar";
24353
+ const compactToggle = document.createElement("div");
24354
+ compactToggle.className = "NextspaceLeftPanelTabBookmarksCompactToggle";
24355
+ compactToggle.title = "Compact";
24356
+ compactToggle.setAttribute("is-on", String(this._compact));
24357
+ const compactTrack = document.createElement("div");
24358
+ compactTrack.className = "NextspaceLeftPanelTabBookmarksCompactToggleTrack";
24359
+ compactToggle.appendChild(compactTrack);
24360
+ const compactLabel = document.createElement("div");
24361
+ compactLabel.textContent = "Compact";
24362
+ compactToggle.appendChild(compactLabel);
24363
+ compactToggle.onclick = () => {
24364
+ this._setCompact(!this._compact);
24365
+ };
24366
+ compactBar.appendChild(compactToggle);
24367
+ element.appendChild(compactBar);
24368
+ const empty = document.createElement("div");
24369
+ empty.className = "NextspaceLeftPanelTabBookmarksEmpty";
24370
+ empty.textContent = "No bookmarks in this project view.";
24371
+ empty.style.display = "none";
24372
+ element.appendChild(empty);
24143
24373
  const list = document.createElement("div");
24144
24374
  list.className = "NextspaceLeftPanelTabBookmarksList";
24145
24375
  element.appendChild(list);
24146
24376
  this.Container.appendChild(element);
24147
24377
  this._element = element;
24148
24378
  }
24379
+ _getStoredCompact() {
24380
+ try {
24381
+ return window.localStorage.getItem(COMPACT_MODE_STORAGE_KEY) === "true";
24382
+ }
24383
+ catch (e) {
24384
+ // Storage can be unavailable (private mode, blocked cookies). The default layout still works.
24385
+ return false;
24386
+ }
24387
+ }
24388
+ _setCompact(compact) {
24389
+ this._compact = compact;
24390
+ this._element.setAttribute("is-compact", String(compact));
24391
+ const toggle = this._element.querySelector(".NextspaceLeftPanelTabBookmarksCompactToggle");
24392
+ if (toggle) {
24393
+ toggle.setAttribute("is-on", String(compact));
24394
+ }
24395
+ try {
24396
+ window.localStorage.setItem(COMPACT_MODE_STORAGE_KEY, String(compact));
24397
+ }
24398
+ catch (e) {
24399
+ console.warn(e);
24400
+ }
24401
+ }
24402
+ _getGroupOpen(groupId) {
24403
+ try {
24404
+ return window.localStorage.getItem(OPEN_STATE_STORAGE_PREFIX + groupId) === "true";
24405
+ }
24406
+ catch (e) {
24407
+ return false;
24408
+ }
24409
+ }
24410
+ _setGroupOpen(groupId, open) {
24411
+ try {
24412
+ window.localStorage.setItem(OPEN_STATE_STORAGE_PREFIX + groupId, String(open));
24413
+ }
24414
+ catch (e) {
24415
+ console.warn(e);
24416
+ }
24417
+ }
24418
+ /**
24419
+ * Sorts the bookmarks into their groups, ordering both by display order then name.
24420
+ * Bookmarks with no group, or one that no longer exists, land in a trailing ungrouped list.
24421
+ */
24422
+ _buildGroupLists() {
24423
+ var _a, _b;
24424
+ const bookmarks = (_a = this._widget.Bookmarks) !== null && _a !== void 0 ? _a : [];
24425
+ const groups = ((_b = this._widget.BookmarkGroups) !== null && _b !== void 0 ? _b : []).slice().sort((a, b) => {
24426
+ var _a, _b, _c, _d;
24427
+ const orderDiff = ((_a = a.DisplayOrder) !== null && _a !== void 0 ? _a : 0) - ((_b = b.DisplayOrder) !== null && _b !== void 0 ? _b : 0);
24428
+ if (orderDiff !== 0) {
24429
+ return orderDiff;
24430
+ }
24431
+ return ((_c = a.Name) !== null && _c !== void 0 ? _c : "").toLowerCase().localeCompare(((_d = b.Name) !== null && _d !== void 0 ? _d : "").toLowerCase());
24432
+ });
24433
+ const lists = groups.map(group => ({
24434
+ groupId: group.ID,
24435
+ group,
24436
+ bookmarks: []
24437
+ }));
24438
+ const listsById = new Map(lists.map(list => [list.groupId, list]));
24439
+ const ungrouped = {
24440
+ groupId: UNGROUPED_ID,
24441
+ group: null,
24442
+ bookmarks: []
24443
+ };
24444
+ for (const bookmark of bookmarks) {
24445
+ const groupId = bookmark["UI.SlideGroup.ID"];
24446
+ const list = groupId ? listsById.get(groupId) : null;
24447
+ (list !== null && list !== void 0 ? list : ungrouped).bookmarks.push(bookmark);
24448
+ }
24449
+ for (const list of lists) {
24450
+ list.bookmarks.sort(this._compareBookmarks);
24451
+ }
24452
+ ungrouped.bookmarks.sort(this._compareBookmarks);
24453
+ // Ungrouped always trails the named groups.
24454
+ lists.push(ungrouped);
24455
+ return lists;
24456
+ }
24457
+ _compareBookmarks(a, b) {
24458
+ var _a, _b, _c, _d;
24459
+ const orderDiff = ((_a = a.DisplayOrder) !== null && _a !== void 0 ? _a : 0) - ((_b = b.DisplayOrder) !== null && _b !== void 0 ? _b : 0);
24460
+ if (orderDiff !== 0) {
24461
+ return orderDiff;
24462
+ }
24463
+ return ((_c = a.Title) !== null && _c !== void 0 ? _c : "").localeCompare((_d = b.Title) !== null && _d !== void 0 ? _d : "");
24464
+ }
24149
24465
  _updateBookmarks() {
24150
- var _a;
24151
- const bookmarks = this._widget.Bookmarks;
24152
- this._element.style.display = bookmarks.length ? "flex" : "none";
24153
- const api = this._widget._getApiGetters().GetBruceApi();
24466
+ var _a, _b;
24467
+ const bookmarks = (_a = this._widget.Bookmarks) !== null && _a !== void 0 ? _a : [];
24154
24468
  const list = this._element.querySelector(".NextspaceLeftPanelTabBookmarksList");
24469
+ const empty = this._element.querySelector(".NextspaceLeftPanelTabBookmarksEmpty");
24470
+ const compactBar = this._element.querySelector(".NextspaceLeftPanelTabBookmarksCompactBar");
24155
24471
  list.innerHTML = "";
24156
- for (const bookmark of bookmarks) {
24157
- const item = document.createElement("div");
24158
- item.className = "NextspaceLeftPanelTabBookmarksListItem";
24159
- const imageBox = document.createElement("div");
24160
- imageBox.className = "NextspaceLeftPanelTabBookmarksListItemImageBox";
24161
- item.appendChild(imageBox);
24162
- const image = document.createElement("div");
24163
- image.className = "NextspaceLeftPanelTabBookmarksListItemImageBoxImage";
24164
- imageBox.appendChild(image);
24165
- const previewUrl = bookmark["Screenshot.ClientFile.ID"] ? ((_a = bookmark["Screenshot.URL"]) !== null && _a !== void 0 ? _a : ClientFile.GetUrl({
24166
- fileId: bookmark["Screenshot.ClientFile.ID"],
24167
- api,
24168
- viaCdn: true
24169
- })) : "";
24170
- // TODO: Some nice empty image.
24472
+ const hasBookmarks = bookmarks.length > 0;
24473
+ empty.style.display = hasBookmarks ? "none" : "block";
24474
+ compactBar.style.display = hasBookmarks ? "flex" : "none";
24475
+ if (!hasBookmarks) {
24476
+ return;
24477
+ }
24478
+ const api = (_b = this._widget._getApiGetters()) === null || _b === void 0 ? void 0 : _b.GetBruceApi();
24479
+ for (const groupList of this._buildGroupLists()) {
24480
+ if (!groupList.bookmarks.length) {
24481
+ continue;
24482
+ }
24483
+ this._renderGroup(groupList, list, api);
24484
+ }
24485
+ this._updateBookmark();
24486
+ }
24487
+ _renderGroup(groupList, parent, api) {
24488
+ var _a;
24489
+ const isGrouped = groupList.groupId != null;
24490
+ // Ungrouped bookmarks have no header, so they're always visible.
24491
+ const opened = isGrouped ? this._getGroupOpen(groupList.groupId) : true;
24492
+ const body = document.createElement("div");
24493
+ body.className = "NextspaceLeftPanelTabBookmarksGroupBody";
24494
+ body.setAttribute("is-grouped", String(isGrouped));
24495
+ if (isGrouped) {
24496
+ const header = document.createElement("div");
24497
+ header.className = "NextspaceLeftPanelTabBookmarksGroupHeader";
24498
+ header.setAttribute("group-id", String(groupList.groupId));
24499
+ header.setAttribute("is-opened", String(opened));
24500
+ const icon = document.createElement("div");
24501
+ icon.className = "NextspaceLeftPanelTabBookmarksGroupHeaderIcon";
24502
+ icon.innerHTML = opened ? ICON_FOLDER_OPEN : ICON_FOLDER;
24503
+ header.appendChild(icon);
24504
+ const name = document.createElement("div");
24505
+ name.className = "NextspaceLeftPanelTabBookmarksGroupHeaderName";
24506
+ name.textContent = ((_a = groupList.group) === null || _a === void 0 ? void 0 : _a.Name) || "Unnamed Group";
24507
+ header.appendChild(name);
24508
+ const count = document.createElement("div");
24509
+ count.className = "NextspaceLeftPanelTabBookmarksGroupHeaderCount";
24510
+ count.textContent = "(" + groupList.bookmarks.length + ")";
24511
+ header.appendChild(count);
24512
+ header.onclick = () => {
24513
+ this._setGroupOpen(groupList.groupId, !this._getGroupOpen(groupList.groupId));
24514
+ this._updateBookmarks();
24515
+ };
24516
+ parent.appendChild(header);
24517
+ body.style.display = opened ? "flex" : "none";
24518
+ }
24519
+ parent.appendChild(body);
24520
+ if (!opened) {
24521
+ return;
24522
+ }
24523
+ for (const bookmark of groupList.bookmarks) {
24524
+ this._renderBookmark(bookmark, body, api);
24525
+ }
24526
+ }
24527
+ _renderBookmark(bookmark, parent, api) {
24528
+ var _a;
24529
+ const item = document.createElement("div");
24530
+ item.className = "NextspaceLeftPanelTabBookmarksListItem";
24531
+ const imageBox = document.createElement("div");
24532
+ imageBox.className = "NextspaceLeftPanelTabBookmarksListItemImageBox";
24533
+ item.appendChild(imageBox);
24534
+ const image = document.createElement("div");
24535
+ image.className = "NextspaceLeftPanelTabBookmarksListItemImageBoxImage";
24536
+ imageBox.appendChild(image);
24537
+ const previewUrl = bookmark["Screenshot.ClientFile.ID"] ? ((_a = bookmark["Screenshot.URL"]) !== null && _a !== void 0 ? _a : ClientFile.GetUrl({
24538
+ fileId: bookmark["Screenshot.ClientFile.ID"],
24539
+ api,
24540
+ viaCdn: true
24541
+ })) : "";
24542
+ // A bookmark without a screenshot keeps the empty tinted box rather than a broken image.
24543
+ if (previewUrl) {
24171
24544
  const img = document.createElement("img");
24172
24545
  img.src = previewUrl;
24546
+ img.loading = "lazy";
24173
24547
  image.appendChild(img);
24174
- const title = document.createElement("div");
24175
- title.className = "NextspaceLeftPanelTabBookmarksListItemTitle";
24176
- item.appendChild(title);
24177
- const titleText = document.createElement("div");
24178
- titleText.className = "NextspaceLeftPanelTabBookmarksListItemTitleText";
24179
- titleText.textContent = bookmark.Title ? bookmark.Title : "Untitled Bookmark";
24180
- title.appendChild(titleText);
24181
- item.setAttribute("bookmark-id", bookmark.ID);
24182
- item.setAttribute("is-selected", String(bookmark.ID === this._widget.LastEnabledBookmarkId));
24183
- item.onclick = () => {
24184
- this._selectBookmark(bookmark);
24185
- };
24186
- list.appendChild(item);
24187
24548
  }
24188
- this._updateBookmark();
24549
+ const content = document.createElement("div");
24550
+ content.className = "NextspaceLeftPanelTabBookmarksListItemContent";
24551
+ item.appendChild(content);
24552
+ const titleText = document.createElement("div");
24553
+ titleText.className = "NextspaceLeftPanelTabBookmarksListItemTitleText";
24554
+ titleText.textContent = bookmark.Title ? bookmark.Title : "Untitled Bookmark";
24555
+ titleText.title = titleText.textContent;
24556
+ content.appendChild(titleText);
24557
+ if (bookmark.Note) {
24558
+ const description = document.createElement("div");
24559
+ description.className = "NextspaceLeftPanelTabBookmarksListItemDescription";
24560
+ description.textContent = bookmark.Note;
24561
+ content.appendChild(description);
24562
+ }
24563
+ item.setAttribute("bookmark-id", bookmark.ID);
24564
+ item.setAttribute("is-selected", String(bookmark.ID === this._widget.LastEnabledBookmarkId));
24565
+ item.onclick = () => {
24566
+ this._selectBookmark(bookmark);
24567
+ };
24568
+ parent.appendChild(item);
24189
24569
  }
24190
24570
  _selectBookmark(bookmark) {
24191
24571
  this._widget.SelectBookmark(bookmark);
@@ -24201,19 +24581,20 @@ class WidgetLeftPanelTabBookmarks extends WidgetLeftPanelTab.ATab {
24201
24581
  item.setAttribute("is-selected", "false");
24202
24582
  }
24203
24583
  }
24204
- // Scroll the selected bookmark into view.
24584
+ // Scroll the selected bookmark into view. This list is vertical, unlike the bookmark strip widget's.
24205
24585
  const selected = this._element.querySelector(".NextspaceLeftPanelTabBookmarksListItem[is-selected='true']");
24206
24586
  if (selected) {
24207
24587
  const list = this._element.querySelector(".NextspaceLeftPanelTabBookmarksList");
24208
- const scrollLeft = list.scrollLeft;
24209
- const scrollRight = scrollLeft + list.clientWidth;
24210
- const left = selected.offsetLeft;
24211
- const right = left + selected.clientWidth;
24212
- if (left < scrollLeft) {
24213
- list.scrollLeft = left;
24588
+ const scrollTop = list.scrollTop;
24589
+ const scrollBottom = scrollTop + list.clientHeight;
24590
+ // Both share the panel container as their offset parent, so this is the item's offset within the list.
24591
+ const top = selected.offsetTop - list.offsetTop;
24592
+ const bottom = top + selected.clientHeight;
24593
+ if (top < scrollTop) {
24594
+ list.scrollTop = top;
24214
24595
  }
24215
- else if (right > scrollRight) {
24216
- list.scrollLeft = right - list.clientWidth;
24596
+ else if (bottom > scrollBottom) {
24597
+ list.scrollTop = bottom - list.clientHeight;
24217
24598
  }
24218
24599
  }
24219
24600
  }
@@ -24517,6 +24898,1203 @@ class WidgetLeftPanelTabUser extends WidgetLeftPanelTab.ATab {
24517
24898
  }
24518
24899
  }
24519
24900
 
24901
+ /**
24902
+ * Enabled state of a menu item row.
24903
+ * Folders roll up their children, so they can sit between fully on and fully off.
24904
+ */
24905
+ var EMenuItemState;
24906
+ (function (EMenuItemState) {
24907
+ EMenuItemState["Enabled"] = "enabled";
24908
+ EMenuItemState["Disabled"] = "disabled";
24909
+ EMenuItemState["ChildEnabled"] = "child-enabled";
24910
+ })(EMenuItemState || (EMenuItemState = {}));
24911
+ // Icons are inline so the library stays dependency free.
24912
+ const ICON_CHECK = `<svg viewBox="0 0 11 8" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 4L4 7L10 1" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
24913
+ const ICON_PARTIAL_CHECK = `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M8 12H16" stroke="white" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
24914
+ const ICON_CHEV_DOWN = `<svg viewBox="0 0 16 9" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15 1L8 8L1 1" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
24915
+ const ICON_CHEV_RIGHT = `<svg viewBox="0 0 10 17" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1.5 1.5L8.5 8.5L1.5 15.5" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
24916
+ const ICON_FLY_TO = `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M20.5926 2.12617L2.49072 12.5694C1.78383 12.9756 1.87366 13.9597 2.57664 14.2566L6.72815 15.9984L17.9486 6.10975C18.1634 5.91838 18.468 6.21129 18.2844 6.4339L8.87616 17.8964V21.0403C8.87616 21.962 9.98921 22.3252 10.536 21.6574L13.016 18.6385L17.8822 20.6771C18.4367 20.9115 19.0694 20.5639 19.171 19.9663L21.9829 3.09473C22.1157 2.30583 21.2682 1.73563 20.5926 2.12617Z" fill="white"/></svg>`;
24917
+ // Elbow connector drawn instead of a chevron on leaf rows below the root level.
24918
+ const ICON_BRACKET = `<svg viewBox="0 0 11 13" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 1V10C1 11.1046 1.89543 12 3 12H10" stroke="rgb(131, 141, 150)" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
24919
+ // Menu item types backed by a tileset, so a fly-to can fall back to the tileset's bounding sphere.
24920
+ const TILESET_TYPES = [
24921
+ MenuItem.EType.CadTileset,
24922
+ MenuItem.EType.PointCloud,
24923
+ MenuItem.EType.EntityTileset,
24924
+ MenuItem.EType.ArbTileset,
24925
+ MenuItem.EType.IonTileset,
24926
+ MenuItem.EType.Osm,
24927
+ MenuItem.EType.GooglePhotoTileset
24928
+ ];
24929
+ const OPEN_STATE_STORAGE_PREFIX$1 = "NextspaceMenuItemOpen_";
24930
+ const PANEL_WIDTH_STORAGE_KEY = "NextspaceMenuItemsPanelWidth";
24931
+ // Matches the panel's resize range in the full Navigator experience.
24932
+ const PANEL_DEFAULT_WIDTH = 320;
24933
+ const PANEL_MIN_WIDTH = 280;
24934
+ const PANEL_MAX_WIDTH = 700;
24935
+ /**
24936
+ * Left panel tab listing the project view's menu items as a checkbox tree.
24937
+ * Toggling a row renders or removes that layer in the scene.
24938
+ */
24939
+ class WidgetLeftPanelTabMenuItems extends WidgetLeftPanelTab.ATab {
24940
+ constructor(params) {
24941
+ var _a, _b, _c, _d;
24942
+ super(params);
24943
+ this.STYLESHEET_ID = "nextspace-left-panel-tab-menu-items-stylesheet";
24944
+ this._menuItems = [];
24945
+ this._rows = new Map();
24946
+ // Identifies the newest load, so a slow response for an older view can't overwrite a newer one.
24947
+ this._loadToken = 0;
24948
+ // Rows currently mid fly-to, so a double click doesn't stack camera moves.
24949
+ this._flying = new Set();
24950
+ this._disposed = false;
24951
+ this._generateStyles();
24952
+ this._generateElement();
24953
+ this._stateQueue = new DelayQueue(() => {
24954
+ this._updateStates();
24955
+ });
24956
+ this._countQueue = new DelayQueue(() => {
24957
+ this._updateCounts();
24958
+ });
24959
+ this._viewIdChangeRemoval = (_b = (_a = this._widget) === null || _a === void 0 ? void 0 : _a.OnViewIdChange) === null || _b === void 0 ? void 0 : _b.Subscribe(() => {
24960
+ this._loadMenuItems();
24961
+ });
24962
+ const manager = (_c = this._widget) === null || _c === void 0 ? void 0 : _c._getManager();
24963
+ if (manager) {
24964
+ this._menuUpdateRemoval = manager.OnUpdate.Subscribe(() => {
24965
+ this._stateQueue.Call();
24966
+ });
24967
+ this._visualUpdateRemoval = (_d = manager.VisualsRegister) === null || _d === void 0 ? void 0 : _d.OnUpdate.Subscribe(() => {
24968
+ this._countQueue.Call();
24969
+ });
24970
+ }
24971
+ this._loadMenuItems();
24972
+ this._applyPanelWidth(this._getStoredWidth());
24973
+ }
24974
+ Dispose() {
24975
+ var _a, _b, _c, _d, _e;
24976
+ this._disposed = true;
24977
+ this._endResize();
24978
+ // The panel container is shared with the other tabs, so its overrides don't outlive this one.
24979
+ if (this.Container) {
24980
+ this.Container.style.padding = "";
24981
+ }
24982
+ (_a = this._viewIdChangeRemoval) === null || _a === void 0 ? void 0 : _a.call(this);
24983
+ (_b = this._menuUpdateRemoval) === null || _b === void 0 ? void 0 : _b.call(this);
24984
+ (_c = this._visualUpdateRemoval) === null || _c === void 0 ? void 0 : _c.call(this);
24985
+ (_d = this._stateQueue) === null || _d === void 0 ? void 0 : _d.Dispose();
24986
+ (_e = this._countQueue) === null || _e === void 0 ? void 0 : _e.Dispose();
24987
+ this._rows.clear();
24988
+ super.Dispose();
24989
+ }
24990
+ _generateStyles() {
24991
+ if (document.getElementById(this.STYLESHEET_ID)) {
24992
+ return;
24993
+ }
24994
+ const style = document.createElement("style");
24995
+ style.id = this.STYLESHEET_ID;
24996
+ style.innerHTML = `
24997
+ .NextspaceLeftPanelTabMenuItems * {
24998
+ box-sizing: border-box;
24999
+ }
25000
+
25001
+ .NextspaceLeftPanelTabMenuItems {
25002
+ color: #fff;
25003
+ display: flex;
25004
+ flex-direction: column;
25005
+ flex-grow: 1;
25006
+ flex-shrink: 1;
25007
+ font-family: Arial, sans-serif;
25008
+ overflow: hidden;
25009
+ padding: 30px 20px 12px 20px;
25010
+ width: 100%;
25011
+ }
25012
+
25013
+ .NextspaceLeftPanelTabMenuItems >.NextspaceLeftPanelTabMenuItemsTitleBar {
25014
+ align-items: center;
25015
+ color: #fff;
25016
+ display: flex;
25017
+ font-size: 17px;
25018
+ font-weight: 500;
25019
+ justify-content: center;
25020
+ letter-spacing: -.005em;
25021
+ line-height: 20px;
25022
+ margin-bottom: 15px;
25023
+ }
25024
+
25025
+ .NextspaceLeftPanelTabMenuItems >.NextspaceLeftPanelTabMenuItemsTitleBreaker {
25026
+ background-color: #000;
25027
+ flex-shrink: 0;
25028
+ height: 2px;
25029
+ margin-bottom: 15px;
25030
+ }
25031
+
25032
+ .NextspaceLeftPanelTabMenuItems >.NextspaceLeftPanelTabMenuItemsScrollBox {
25033
+ flex-grow: 1;
25034
+ flex-shrink: 1;
25035
+ overflow: auto;
25036
+ padding-right: 10px;
25037
+ }
25038
+
25039
+ .NextspaceLeftPanelTabMenuItems >.NextspaceLeftPanelTabMenuItemsTip {
25040
+ color: #fff;
25041
+ font-size: 13px;
25042
+ opacity: .7;
25043
+ }
25044
+
25045
+ .NextspaceLeftPanelTabMenuItemsResizeHandle {
25046
+ bottom: 0;
25047
+ cursor: col-resize;
25048
+ position: absolute;
25049
+ right: 0;
25050
+ top: 0;
25051
+ width: 8px;
25052
+ z-index: 3;
25053
+ }
25054
+
25055
+ .NextspaceMenuItemRow {
25056
+ border-bottom: 2px solid #121619;
25057
+ width: 100%;
25058
+ }
25059
+
25060
+ .NextspaceMenuItemRow[show-children="true"] {
25061
+ border-bottom: none;
25062
+ }
25063
+
25064
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem {
25065
+ align-items: center;
25066
+ display: flex;
25067
+ height: 40px;
25068
+ user-select: none;
25069
+ }
25070
+
25071
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem >.NextspaceMenuItemRowCheckbox,
25072
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem >.NextspaceMenuItemRowToggle,
25073
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem >.NextspaceMenuItemRowBracket {
25074
+ align-items: center;
25075
+ color: #fff;
25076
+ cursor: pointer;
25077
+ display: flex;
25078
+ flex-shrink: 0;
25079
+ height: 18px;
25080
+ justify-content: center;
25081
+ width: 18px;
25082
+ }
25083
+
25084
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem >.NextspaceMenuItemRowCheckbox >svg,
25085
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem >.NextspaceMenuItemRowToggle >svg,
25086
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem >.NextspaceMenuItemRowBracket >svg {
25087
+ height: 12px;
25088
+ width: 12px;
25089
+ }
25090
+
25091
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem >.NextspaceMenuItemRowCheckbox {
25092
+ border: 1.5px solid #fff;
25093
+ border-radius: 2px;
25094
+ margin-right: 8px;
25095
+ }
25096
+
25097
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem >.NextspaceMenuItemRowToggle {
25098
+ margin-right: 3px;
25099
+ }
25100
+
25101
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem >.NextspaceMenuItemRowTitle {
25102
+ color: #fff;
25103
+ font-size: 14px;
25104
+ margin-right: 8px;
25105
+ overflow: hidden;
25106
+ text-overflow: ellipsis;
25107
+ white-space: nowrap;
25108
+ }
25109
+
25110
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem >.NextspaceMenuItemRowCount {
25111
+ background: rgba(0, 175, 250, .2);
25112
+ border-radius: 11px;
25113
+ color: #18ffff;
25114
+ cursor: pointer;
25115
+ flex-shrink: 0;
25116
+ font-size: 12px;
25117
+ margin-right: 3px;
25118
+ padding: 5px 8px;
25119
+ }
25120
+
25121
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem >.NextspaceMenuItemRowQuickBar {
25122
+ display: flex;
25123
+ flex-shrink: 0;
25124
+ margin-left: auto;
25125
+ }
25126
+
25127
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem >.NextspaceMenuItemRowQuickBar >.NextspaceMenuItemRowQuickBarButton {
25128
+ align-items: center;
25129
+ cursor: pointer;
25130
+ display: flex;
25131
+ height: 20px;
25132
+ justify-content: center;
25133
+ margin-left: 4px;
25134
+ opacity: .7;
25135
+ transition: .3s ease;
25136
+ width: 20px;
25137
+ }
25138
+
25139
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem >.NextspaceMenuItemRowQuickBar >.NextspaceMenuItemRowQuickBarButton:hover {
25140
+ opacity: 1;
25141
+ }
25142
+
25143
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem >.NextspaceMenuItemRowQuickBar >.NextspaceMenuItemRowQuickBarButton[is-disabled="true"] {
25144
+ cursor: default;
25145
+ opacity: .3;
25146
+ }
25147
+
25148
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem >.NextspaceMenuItemRowQuickBar svg {
25149
+ height: 18px;
25150
+ width: 18px;
25151
+ }
25152
+
25153
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem[is-enabled="false"] >.NextspaceMenuItemRowCount,
25154
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem[is-enabled="false"] >.NextspaceMenuItemRowTitle,
25155
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem[is-enabled="false"] >.NextspaceMenuItemRowCheckbox,
25156
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem[is-enabled="false"] >.NextspaceMenuItemRowToggle {
25157
+ opacity: .5;
25158
+ }
25159
+
25160
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowItem[is-enabled="false"] >.NextspaceMenuItemRowQuickBar {
25161
+ opacity: 0;
25162
+ pointer-events: none;
25163
+ }
25164
+
25165
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowDescription {
25166
+ font-size: 12px;
25167
+ margin: 0 0 8px 0;
25168
+ opacity: .7;
25169
+ }
25170
+
25171
+ .NextspaceMenuItemRow >.NextspaceMenuItemRowChildren {
25172
+ border-top: 2px solid #121619;
25173
+ display: flex;
25174
+ flex-direction: column;
25175
+ }
25176
+
25177
+ .NextspaceMenuItemRow[show-children="false"] >.NextspaceMenuItemRowChildren {
25178
+ display: none;
25179
+ }
25180
+ `;
25181
+ document.head.appendChild(style);
25182
+ }
25183
+ _generateElement() {
25184
+ const element = document.createElement("div");
25185
+ element.className = "NextspaceLeftPanelTabMenuItems";
25186
+ const titleBar = document.createElement("div");
25187
+ titleBar.className = "NextspaceLeftPanelTabMenuItemsTitleBar";
25188
+ titleBar.textContent = "Menu";
25189
+ element.appendChild(titleBar);
25190
+ const breaker = document.createElement("div");
25191
+ breaker.className = "NextspaceLeftPanelTabMenuItemsTitleBreaker";
25192
+ element.appendChild(breaker);
25193
+ const tip = document.createElement("div");
25194
+ tip.className = "NextspaceLeftPanelTabMenuItemsTip";
25195
+ tip.textContent = "Loading...";
25196
+ element.appendChild(tip);
25197
+ this._tip = tip;
25198
+ const scrollBox = document.createElement("div");
25199
+ scrollBox.className = "NextspaceLeftPanelTabMenuItemsScrollBox";
25200
+ element.appendChild(scrollBox);
25201
+ this._scrollBox = scrollBox;
25202
+ // Positions against the panel container, which is the nearest positioned ancestor.
25203
+ const resizeHandle = document.createElement("div");
25204
+ resizeHandle.className = "NextspaceLeftPanelTabMenuItemsResizeHandle";
25205
+ resizeHandle.onmousedown = (e) => {
25206
+ this._startResize(e);
25207
+ };
25208
+ element.appendChild(resizeHandle);
25209
+ this.Container.appendChild(element);
25210
+ this._element = element;
25211
+ }
25212
+ _getStoredWidth() {
25213
+ try {
25214
+ const stored = parseInt(window.localStorage.getItem(PANEL_WIDTH_STORAGE_KEY), 10);
25215
+ if (!isNaN(stored)) {
25216
+ return stored;
25217
+ }
25218
+ }
25219
+ catch (e) {
25220
+ // Storage can be unavailable (private mode, blocked cookies). The default width still works.
25221
+ }
25222
+ return PANEL_DEFAULT_WIDTH;
25223
+ }
25224
+ /**
25225
+ * Sizes the shared panel container to this tab's width, clamped to the allowed range.
25226
+ */
25227
+ _applyPanelWidth(width) {
25228
+ const clamped = Math.min(PANEL_MAX_WIDTH, Math.max(PANEL_MIN_WIDTH, width));
25229
+ if (this.Container) {
25230
+ this.Container.style.width = clamped + "px";
25231
+ // Padding lives on this tab's own element instead, so the resize handle can reach the panel edge.
25232
+ this.Container.style.padding = "0";
25233
+ }
25234
+ return clamped;
25235
+ }
25236
+ _startResize(e) {
25237
+ e.preventDefault();
25238
+ const startX = e.clientX;
25239
+ const startWidth = this.Container ? this.Container.offsetWidth : PANEL_DEFAULT_WIDTH;
25240
+ this._onResizeMove = (moveEvent) => {
25241
+ this._applyPanelWidth(startWidth + (moveEvent.clientX - startX));
25242
+ };
25243
+ this._onResizeUp = () => {
25244
+ const finalWidth = this._applyPanelWidth(this.Container ? this.Container.offsetWidth : PANEL_DEFAULT_WIDTH);
25245
+ try {
25246
+ window.localStorage.setItem(PANEL_WIDTH_STORAGE_KEY, String(finalWidth));
25247
+ }
25248
+ catch (err) {
25249
+ console.warn(err);
25250
+ }
25251
+ this._endResize();
25252
+ };
25253
+ window.addEventListener("mousemove", this._onResizeMove);
25254
+ window.addEventListener("mouseup", this._onResizeUp);
25255
+ }
25256
+ _endResize() {
25257
+ if (this._onResizeMove) {
25258
+ window.removeEventListener("mousemove", this._onResizeMove);
25259
+ this._onResizeMove = null;
25260
+ }
25261
+ if (this._onResizeUp) {
25262
+ window.removeEventListener("mouseup", this._onResizeUp);
25263
+ this._onResizeUp = null;
25264
+ }
25265
+ }
25266
+ async _loadMenuItems() {
25267
+ var _a, _b, _c, _d;
25268
+ const viewId = (_a = this._widget) === null || _a === void 0 ? void 0 : _a.ViewId;
25269
+ const token = ++this._loadToken;
25270
+ let menuItems = [];
25271
+ try {
25272
+ if (viewId) {
25273
+ const api = (_b = this._widget._getApiGetters()) === null || _b === void 0 ? void 0 : _b.GetBruceApi();
25274
+ const data = await ProjectView.Get({
25275
+ viewId,
25276
+ api
25277
+ });
25278
+ const settings = (_c = data === null || data === void 0 ? void 0 : data.view) === null || _c === void 0 ? void 0 : _c.Settings;
25279
+ menuItems = (_d = settings === null || settings === void 0 ? void 0 : settings.menuItems) !== null && _d !== void 0 ? _d : [];
25280
+ }
25281
+ }
25282
+ catch (e) {
25283
+ console.error(e);
25284
+ menuItems = [];
25285
+ }
25286
+ if (this._disposed || token !== this._loadToken) {
25287
+ return;
25288
+ }
25289
+ this._menuItems = menuItems;
25290
+ this._renderTree();
25291
+ this._updateStates();
25292
+ this._updateCounts();
25293
+ }
25294
+ _renderTree() {
25295
+ var _a;
25296
+ this._rows.clear();
25297
+ this._scrollBox.innerHTML = "";
25298
+ if (!this._menuItems.length) {
25299
+ // The panel can be opened before any view has rendered, so say so rather than claiming it's empty.
25300
+ this._tip.textContent = ((_a = this._widget) === null || _a === void 0 ? void 0 : _a.ViewId)
25301
+ ? "This project view has no menu items."
25302
+ : "Waiting for a view to load...";
25303
+ this._tip.style.display = "block";
25304
+ return;
25305
+ }
25306
+ this._tip.style.display = "none";
25307
+ for (const item of this._menuItems) {
25308
+ this._renderRow(item, 0, this._scrollBox);
25309
+ }
25310
+ }
25311
+ _renderRow(item, depth, parent) {
25312
+ var _a;
25313
+ if (!(item === null || item === void 0 ? void 0 : item.id)) {
25314
+ return;
25315
+ }
25316
+ const isFolder = !item.Type || item.Type === MenuItem.EType.None;
25317
+ const children = item.hideChildren ? [] : ((_a = item.Children) !== null && _a !== void 0 ? _a : []);
25318
+ const hasChildren = children.length > 0;
25319
+ const row = document.createElement("div");
25320
+ row.className = "NextspaceMenuItemRow";
25321
+ row.setAttribute("menu-item-id", item.id);
25322
+ const itemElement = document.createElement("div");
25323
+ itemElement.className = "NextspaceMenuItemRowItem";
25324
+ itemElement.style.paddingLeft = (depth * 15) + "px";
25325
+ row.appendChild(itemElement);
25326
+ if (hasChildren) {
25327
+ const toggle = document.createElement("div");
25328
+ toggle.className = "NextspaceMenuItemRowToggle";
25329
+ toggle.onclick = () => {
25330
+ this._setOpen(item.id, depth, row.getAttribute("show-children") !== "true", row, toggle);
25331
+ };
25332
+ itemElement.appendChild(toggle);
25333
+ const opened = this._getOpen(item.id, depth);
25334
+ row.setAttribute("show-children", opened ? "true" : "false");
25335
+ toggle.innerHTML = opened ? ICON_CHEV_DOWN : ICON_CHEV_RIGHT;
25336
+ }
25337
+ else if (depth > 0) {
25338
+ const bracket = document.createElement("div");
25339
+ bracket.className = "NextspaceMenuItemRowBracket";
25340
+ bracket.innerHTML = ICON_BRACKET;
25341
+ itemElement.appendChild(bracket);
25342
+ row.setAttribute("show-children", "false");
25343
+ }
25344
+ else {
25345
+ row.setAttribute("show-children", "false");
25346
+ }
25347
+ const checkbox = document.createElement("div");
25348
+ checkbox.className = "NextspaceMenuItemRowCheckbox";
25349
+ checkbox.onclick = () => {
25350
+ this._toggleItem(item);
25351
+ };
25352
+ itemElement.appendChild(checkbox);
25353
+ const title = document.createElement("div");
25354
+ title.className = "NextspaceMenuItemRowTitle";
25355
+ title.textContent = item.Caption || "Unnamed Menu Item";
25356
+ title.title = item.Caption || "Unnamed Menu Item";
25357
+ itemElement.appendChild(title);
25358
+ // Folders have no visuals of their own, so a count would always read zero.
25359
+ let count = null;
25360
+ if (!isFolder) {
25361
+ count = document.createElement("div");
25362
+ count.className = "NextspaceMenuItemRowCount";
25363
+ count.style.display = "none";
25364
+ count.onclick = () => {
25365
+ this._selectItemEntities(item);
25366
+ };
25367
+ itemElement.appendChild(count);
25368
+ }
25369
+ const quickBar = document.createElement("div");
25370
+ quickBar.className = "NextspaceMenuItemRowQuickBar";
25371
+ itemElement.appendChild(quickBar);
25372
+ if (!isFolder) {
25373
+ const flyTo = document.createElement("div");
25374
+ flyTo.className = "NextspaceMenuItemRowQuickBarButton";
25375
+ flyTo.title = "Fly to";
25376
+ flyTo.innerHTML = ICON_FLY_TO;
25377
+ flyTo.onclick = () => {
25378
+ this._flyToItem(item, flyTo);
25379
+ };
25380
+ quickBar.appendChild(flyTo);
25381
+ }
25382
+ if (item.Description) {
25383
+ const description = document.createElement("p");
25384
+ description.className = "NextspaceMenuItemRowDescription";
25385
+ description.style.paddingLeft = (depth * 15) + "px";
25386
+ description.textContent = item.Description;
25387
+ row.appendChild(description);
25388
+ }
25389
+ const childrenElement = document.createElement("div");
25390
+ childrenElement.className = "NextspaceMenuItemRowChildren";
25391
+ row.appendChild(childrenElement);
25392
+ parent.appendChild(row);
25393
+ this._rows.set(item.id, {
25394
+ item,
25395
+ depth,
25396
+ element: row,
25397
+ itemElement,
25398
+ checkboxElement: checkbox,
25399
+ countElement: count,
25400
+ childrenElement
25401
+ });
25402
+ for (const child of children) {
25403
+ this._renderRow(child, depth + 1, childrenElement);
25404
+ }
25405
+ }
25406
+ _getOpen(itemId, depth) {
25407
+ try {
25408
+ return window.localStorage.getItem(OPEN_STATE_STORAGE_PREFIX$1 + itemId + depth) === "true";
25409
+ }
25410
+ catch (e) {
25411
+ // Storage can be unavailable (private mode, blocked cookies). Not worth failing the tree over.
25412
+ return false;
25413
+ }
25414
+ }
25415
+ _setOpen(itemId, depth, open, row, toggle) {
25416
+ row.setAttribute("show-children", open ? "true" : "false");
25417
+ toggle.innerHTML = open ? ICON_CHEV_DOWN : ICON_CHEV_RIGHT;
25418
+ try {
25419
+ window.localStorage.setItem(OPEN_STATE_STORAGE_PREFIX$1 + itemId + depth, open ? "true" : "false");
25420
+ }
25421
+ catch (e) {
25422
+ console.warn(e);
25423
+ }
25424
+ }
25425
+ /**
25426
+ * Resolves each row's state from what the manager currently has rendered.
25427
+ */
25428
+ _updateStates() {
25429
+ var _a;
25430
+ const manager = (_a = this._widget) === null || _a === void 0 ? void 0 : _a._getManager();
25431
+ if (!manager || this._disposed) {
25432
+ return;
25433
+ }
25434
+ const enabledIds = new Set(manager.GetEnabledItemIds());
25435
+ for (const row of Array.from(this._rows.values())) {
25436
+ const state = this._resolveState(row.item, enabledIds);
25437
+ row.itemElement.setAttribute("is-enabled", state === EMenuItemState.Disabled ? "false" : "true");
25438
+ if (state === EMenuItemState.Enabled) {
25439
+ row.checkboxElement.innerHTML = ICON_CHECK;
25440
+ }
25441
+ else if (state === EMenuItemState.ChildEnabled) {
25442
+ row.checkboxElement.innerHTML = ICON_PARTIAL_CHECK;
25443
+ }
25444
+ else {
25445
+ row.checkboxElement.innerHTML = "";
25446
+ }
25447
+ }
25448
+ }
25449
+ /**
25450
+ * Works out a single item's state, rolling up children so a folder can report a partial state.
25451
+ */
25452
+ _resolveState(item, enabledIds) {
25453
+ var _a;
25454
+ const isFolder = !item.Type || item.Type === MenuItem.EType.None;
25455
+ if (!isFolder) {
25456
+ return enabledIds.has(item.id) ? EMenuItemState.Enabled : EMenuItemState.Disabled;
25457
+ }
25458
+ // Folders derive from the leaves below them rather than their own enabled flag.
25459
+ let actionCount = 0;
25460
+ let enabledActionCount = 0;
25461
+ const traverse = (current) => {
25462
+ var _a;
25463
+ const currentIsFolder = !current.Type || current.Type === MenuItem.EType.None;
25464
+ if (!currentIsFolder) {
25465
+ actionCount += 1;
25466
+ if (enabledIds.has(current.id)) {
25467
+ enabledActionCount += 1;
25468
+ }
25469
+ return;
25470
+ }
25471
+ if ((_a = current.Children) === null || _a === void 0 ? void 0 : _a.length) {
25472
+ current.Children.forEach(traverse);
25473
+ }
25474
+ };
25475
+ (_a = item.Children) === null || _a === void 0 ? void 0 : _a.forEach(traverse);
25476
+ if (actionCount <= 0) {
25477
+ return enabledIds.has(item.id) ? EMenuItemState.Enabled : EMenuItemState.Disabled;
25478
+ }
25479
+ if (enabledActionCount <= 0) {
25480
+ return EMenuItemState.Disabled;
25481
+ }
25482
+ return enabledActionCount >= actionCount ? EMenuItemState.Enabled : EMenuItemState.ChildEnabled;
25483
+ }
25484
+ _updateCounts() {
25485
+ var _a, _b;
25486
+ const register = (_b = (_a = this._widget) === null || _a === void 0 ? void 0 : _a._getManager()) === null || _b === void 0 ? void 0 : _b.VisualsRegister;
25487
+ if (!register || this._disposed) {
25488
+ return;
25489
+ }
25490
+ for (const row of Array.from(this._rows.values())) {
25491
+ if (!row.countElement) {
25492
+ continue;
25493
+ }
25494
+ const count = register.GetRegos({
25495
+ menuItemId: row.item.id
25496
+ }).length;
25497
+ row.countElement.style.display = count > 0 ? "block" : "none";
25498
+ row.countElement.textContent = count.toLocaleString();
25499
+ }
25500
+ }
25501
+ _toggleItem(item) {
25502
+ var _a;
25503
+ const manager = (_a = this._widget) === null || _a === void 0 ? void 0 : _a._getManager();
25504
+ if (!manager) {
25505
+ return;
25506
+ }
25507
+ const enabledIds = new Set(manager.GetEnabledItemIds());
25508
+ const state = this._resolveState(item, enabledIds);
25509
+ if (state === EMenuItemState.Enabled) {
25510
+ this._disableItem(item);
25511
+ }
25512
+ else {
25513
+ manager.RenderItem({
25514
+ item
25515
+ });
25516
+ }
25517
+ this._stateQueue.Call(true);
25518
+ }
25519
+ _disableItem(item) {
25520
+ var _a, _b;
25521
+ const manager = (_a = this._widget) === null || _a === void 0 ? void 0 : _a._getManager();
25522
+ if (!manager) {
25523
+ return;
25524
+ }
25525
+ if ((_b = item.Children) === null || _b === void 0 ? void 0 : _b.length) {
25526
+ item.Children.forEach((child) => this._disableItem(child));
25527
+ }
25528
+ manager.RemoveItemById({
25529
+ menuItemId: item.id
25530
+ });
25531
+ }
25532
+ _selectItemEntities(item) {
25533
+ var _a, _b;
25534
+ const register = (_b = (_a = this._widget) === null || _a === void 0 ? void 0 : _a._getManager()) === null || _b === void 0 ? void 0 : _b.VisualsRegister;
25535
+ if (!register) {
25536
+ return;
25537
+ }
25538
+ const entityIds = register.GetRegos({
25539
+ menuItemId: item.id
25540
+ }).map(x => x.entityId);
25541
+ if (!entityIds.length) {
25542
+ return;
25543
+ }
25544
+ register.ClearSelected();
25545
+ register.SetSelected({
25546
+ selected: true,
25547
+ entityIds,
25548
+ menuItemId: item.id
25549
+ });
25550
+ }
25551
+ /**
25552
+ * Flies the camera to a menu item's contents.
25553
+ * Tileset-backed items fall back to the tileset's own bounds when no entity visuals are registered.
25554
+ */
25555
+ async _flyToItem(item, button) {
25556
+ var _a, _b, _c, _d;
25557
+ if (this._flying.has(item.id)) {
25558
+ return;
25559
+ }
25560
+ const manager = (_a = this._widget) === null || _a === void 0 ? void 0 : _a._getManager();
25561
+ const viewer = (_b = this._widget) === null || _b === void 0 ? void 0 : _b._getViewer();
25562
+ if (!manager || !viewer) {
25563
+ return;
25564
+ }
25565
+ this._flying.add(item.id);
25566
+ button.setAttribute("is-disabled", "true");
25567
+ try {
25568
+ const regos = manager.VisualsRegister.GetRegos({
25569
+ menuItemId: item.id
25570
+ }).filter(x => !!(x === null || x === void 0 ? void 0 : x.visual) && !(x.visual instanceof Cesium3DTileFeature));
25571
+ let tileset = null;
25572
+ if (!regos.length && TILESET_TYPES.indexOf(item.Type) >= 0) {
25573
+ const enabled = manager.GetEnabledItem(item.id);
25574
+ tileset = (_d = (_c = enabled === null || enabled === void 0 ? void 0 : enabled.renderManager) === null || _c === void 0 ? void 0 : _c.Tileset) !== null && _d !== void 0 ? _d : null;
25575
+ }
25576
+ const entityIds = regos.map(x => x.entityId);
25577
+ if (!entityIds.length && !tileset) {
25578
+ return;
25579
+ }
25580
+ await EntityUtils.FlyTo({
25581
+ viewer,
25582
+ manager,
25583
+ entityIds: entityIds.length ? entityIds : null,
25584
+ tileset
25585
+ });
25586
+ }
25587
+ catch (e) {
25588
+ console.error(e);
25589
+ }
25590
+ finally {
25591
+ this._flying.delete(item.id);
25592
+ button.setAttribute("is-disabled", "false");
25593
+ }
25594
+ }
25595
+ }
25596
+
25597
+ // Nextspace wordmark, and the "powered by" variant shown once an account or view supplies its own branding.
25598
+ const ICON_NEXTSPACE_LEAF = `<svg width="1000" height="244" viewBox="0 0 1000 244" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M349.751 182.492H335.798L269.898 85.099V182.492H254.432V61.5086H271.411L334.117 155.027V61.5086H349.752V182.492H349.751ZM364.626 138.513C364.626 112.227 381.269 92.6809 405.141 92.6809C429.685 92.6809 442.629 111.385 442.629 135.817V140.872H379.083C379.924 159.408 390.515 171.204 405.813 171.204C417.581 171.204 425.987 164.8 428.676 154.351L441.957 159.07C436.578 174.741 423.296 184.346 405.813 184.346C381.437 184.346 364.626 165.642 364.626 138.512V138.513ZM379.924 129.246H427.331C426.995 116.777 420.27 105.655 404.972 105.655C392.196 105.655 382.613 114.25 379.924 129.246V129.246ZM484.909 147.781L460.701 182.492H444.225L476.335 136.492L446.915 94.3659H464.231L485.413 125.201L506.931 94.3659H523.574L494.155 136.492L526.432 182.492H509.285L484.909 147.781H484.909ZM533.49 68.5854H548.452V94.3659H568.457V107.342H548.452V159.071C548.452 168.338 552.991 170.023 560.724 170.023C564.255 170.023 566.776 169.855 570.307 169.013V181.988C566.44 182.831 562.069 183.334 557.026 183.334C542.064 183.334 533.49 178.28 533.49 161.43V68.5854H533.49ZM588.062 155.194C592.77 165.475 603.529 171.708 614.96 171.708C625.215 171.708 634.293 167.328 634.293 157.723C634.293 148.119 625.888 146.769 611.43 143.737C596.972 140.537 581.842 137.335 581.842 119.304C581.842 103.633 595.46 92.6812 614.12 92.6812C629.923 92.6812 642.867 100.431 648.078 110.88L637.319 119.472C632.78 110.712 624.543 105.151 613.447 105.151C603.36 105.151 596.636 110.205 596.636 118.126C596.636 126.381 604.37 127.898 616.642 130.595C631.772 134.133 649.087 137.165 649.087 156.376C649.087 173.225 633.789 184.347 614.96 184.347C598.99 184.347 583.019 177.437 576.295 163.79L588.062 155.194V155.194ZM678.082 169.687V210.969H662.952V94.3659H678.082V107.172C683.294 98.5782 693.045 92.6809 705.316 92.6809C729.693 92.6809 743.646 113.407 743.646 138.513C743.646 163.451 729.693 184.346 705.316 184.346C693.045 184.346 683.294 178.449 678.082 169.687ZM677.747 141.715C677.747 161.935 690.187 171.035 702.627 171.035C719.102 171.035 728.348 157.386 728.348 138.513C728.348 119.472 719.102 105.992 702.627 105.992C690.187 105.992 677.747 114.924 677.747 135.48V141.715V141.715ZM753.597 158.733C753.597 141.21 767.214 133.965 786.883 129.92L808.233 125.539V121.831C808.233 111.722 802.685 105.993 790.917 105.993C779.822 105.993 773.265 111.215 770.575 120.989L756.286 117.284C760.489 102.96 773.433 92.6816 791.421 92.6816C811.09 92.6816 823.194 102.286 823.194 121.157V164.126C823.194 169.855 826.725 171.708 832.609 170.361V182.492C819.16 184.177 811.426 180.977 809.577 172.55C804.198 179.459 794.447 184.009 782.512 184.009C766.541 184.009 753.596 174.574 753.596 158.734L753.597 158.733ZM808.233 137.334L791.085 141.04C777.636 143.737 768.558 147.444 768.558 158.06C768.558 166.653 774.779 171.707 784.361 171.707C797.306 171.707 808.233 163.79 808.233 152.499V137.334ZM879.593 171.034C891.697 171.034 898.926 163.283 901.447 152.331L914.896 158.565C910.694 173.224 897.917 184.346 879.593 184.346C855.049 184.346 838.069 165.642 838.069 138.512C838.069 111.215 855.049 92.6806 879.593 92.6806C897.917 92.6806 910.357 103.297 914.56 117.956L901.448 124.528C898.926 113.744 891.697 105.824 879.593 105.824C863.959 105.824 853.2 118.293 853.2 138.512C853.2 158.565 863.959 171.034 879.593 171.034L879.593 171.034ZM921.996 138.512C921.996 112.227 938.639 92.6806 962.511 92.6806C987.056 92.6806 1000 111.384 1000 135.817V140.872H936.454C937.294 159.408 947.886 171.204 963.184 171.204C974.951 171.204 983.357 164.8 986.047 154.351L999.328 159.07C993.948 174.741 980.667 184.346 963.184 184.346C938.808 184.346 921.996 165.642 921.996 138.512V138.512ZM937.294 129.245H984.702C984.365 116.776 977.641 105.655 962.343 105.655C949.566 105.655 939.984 114.249 937.294 129.245V129.245ZM200.35 56.2656L109.823 1.82319C105.779 -0.607899 100.756 -0.607562 96.7125 1.82319L6.18535 56.266C2.37013 58.561 0 62.7567 0 67.2163V176.783C0 181.243 2.37013 185.439 6.18535 187.734L51.5924 215.041L51.5948 215.043L96.7125 242.177C98.7343 243.392 101 244 103.268 244C105.535 244 107.801 243.392 109.823 242.177L154.941 215.043L154.943 215.041L200.35 187.733C204.165 185.439 206.535 181.243 206.535 176.783V67.2163C206.535 62.7564 204.165 58.5606 200.35 56.2656H200.35ZM201.171 176.783C201.171 179.365 199.799 181.794 197.59 183.123L156.243 207.989V157.954C156.243 153.494 153.873 149.298 150.057 147.003L109.823 122.806C105.78 120.375 100.757 120.376 96.7132 122.806L56.4782 147.004C52.663 149.298 50.2929 153.494 50.2929 157.954V207.989L8.94576 183.123C6.7369 181.794 5.36457 179.365 5.36457 176.783V67.2163C5.36457 64.6343 6.7369 62.2052 8.94576 60.8768L99.4729 6.43433C100.643 5.73028 101.955 5.37842 103.268 5.37842C104.581 5.37842 105.893 5.73028 107.063 6.43433L197.59 60.8768C199.799 62.2052 201.171 64.6346 201.171 67.2163V176.783ZM142.851 161.822L114.41 178.929C109.192 182.07 105.95 187.81 105.95 193.911V228.852C105.95 229.324 105.703 229.762 105.299 230.005L103.958 230.811C103.533 231.066 103.003 231.066 102.578 230.811L101.237 230.004C100.832 229.761 100.585 229.323 100.585 228.851V193.901C100.582 187.802 97.3398 182.065 92.1218 178.926L63.6845 161.822C63.2805 161.579 63.0334 161.141 63.0334 160.669V158.715C63.0334 158.243 63.2805 157.805 63.6845 157.562L64.6666 156.972C65.0914 156.716 65.6218 156.716 66.0466 156.972L94.3132 173.974C99.8417 177.291 106.705 177.289 112.232 173.968L140.491 156.971C140.916 156.716 141.446 156.716 141.871 156.971L142.851 157.561C143.256 157.804 143.503 158.241 143.503 158.714V160.669C143.503 161.142 143.256 161.579 142.851 161.822H142.851ZM193.144 71.0841C186.359 75.1646 164.709 88.1847 164.708 88.1857C159.487 91.3256 156.243 97.0672 156.243 103.17V139.732C156.243 140.222 155.978 140.672 155.551 140.909C155.124 141.145 154.602 141.131 154.189 140.871C154.184 140.868 154.183 140.871 154.18 140.869C154.071 140.801 153.964 140.73 153.853 140.664L151.53 139.267C151.126 139.024 150.879 138.586 150.879 138.114V103.17C150.879 97.0672 147.635 91.3252 142.414 88.1854C142.412 88.1844 106.331 66.5311 105.95 66.3815V112.285C105.95 112.656 105.797 113.011 105.527 113.265C105.257 113.519 104.894 113.65 104.525 113.627C104.522 113.627 104.522 113.628 104.52 113.628C103.686 113.576 102.851 113.576 102.017 113.628C102.015 113.628 102.013 113.627 102.01 113.627C101.641 113.65 101.278 113.52 101.008 113.266C100.738 113.011 100.585 112.657 100.585 112.286V66.3822C100.204 66.5317 64.1227 88.1854 64.1217 88.186C58.9006 91.3259 55.6571 97.0676 55.6571 103.171V138.114C55.6571 138.587 55.41 139.024 55.006 139.267L52.6824 140.665C52.5725 140.731 52.4652 140.801 52.3565 140.869C52.3532 140.87 52.3522 140.868 52.3471 140.871C51.9337 141.131 51.412 141.146 50.9849 140.909C50.5577 140.673 50.2925 140.222 50.2925 139.733V103.171C50.2925 97.0679 47.049 91.3262 41.8279 88.1864C41.8262 88.1854 20.1762 75.1649 13.3913 71.0847C12.9873 70.8418 12.7402 70.4042 12.7402 69.932V67.9782C12.7402 67.506 12.9873 67.0684 13.3913 66.8255L14.3734 66.2347C14.7982 65.9792 15.3286 65.9792 15.7531 66.2347C22.4373 70.2543 44.0042 83.2244 44.0046 83.2247C49.5341 86.5504 56.4034 86.5524 61.9346 83.2308L96.7125 62.3155C100.756 59.8847 105.779 59.8844 109.823 62.3155L144.599 83.2294C150.131 86.5521 157.001 86.5508 162.531 83.2244C162.531 83.2237 184.1 70.253 190.783 66.234C191.208 65.9786 191.738 65.9786 192.163 66.234L193.144 66.8241C193.548 67.0671 193.795 67.5046 193.795 67.9768V69.932C193.795 70.4042 193.548 70.8418 193.144 71.0847V71.0841Z" fill="white"/> </svg>`;
25599
+ const ICON_NEXTSPACE_POWERED = `<svg width="172" height="25" viewBox="0 0 172 25" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M104.849 18.698H103.419L96.6645 8.71916V18.698H95.0793V6.30211H96.8196L103.247 15.8839V6.30211H104.85V18.698H104.849ZM106.374 14.1919C106.374 11.4987 108.08 9.49599 110.527 9.49599C113.043 9.49599 114.369 11.4124 114.369 13.9157V14.4336H107.856C107.942 16.3328 109.028 17.5414 110.596 17.5414C111.802 17.5414 112.664 16.8852 112.939 15.8147L114.301 16.2982C113.749 17.9038 112.388 18.8879 110.596 18.8879C108.097 18.8879 106.374 16.9715 106.374 14.1918V14.1919ZM107.942 13.2424H112.801C112.767 11.9649 112.078 10.8253 110.51 10.8253C109.2 10.8253 108.218 11.7059 107.942 13.2424ZM118.703 15.1415L116.222 18.698H114.533L117.824 13.9848L114.809 9.66864H116.584L118.755 12.828L120.96 9.66864H122.666L119.651 13.9848L122.959 18.698H121.202L118.703 15.1415ZM123.683 7.02719H125.216V9.66864H127.267V10.9982H125.216V16.2983C125.216 17.2477 125.682 17.4204 126.474 17.4204C126.836 17.4204 127.095 17.4032 127.456 17.3169V18.6463C127.06 18.7327 126.612 18.7842 126.095 18.7842C124.562 18.7842 123.683 18.2664 123.683 16.54V7.02719ZM129.276 15.901C129.759 16.9544 130.862 17.593 132.033 17.593C133.085 17.593 134.015 17.1443 134.015 16.1601C134.015 15.1761 133.154 15.0378 131.672 14.7272C130.19 14.3993 128.639 14.0712 128.639 12.2238C128.639 10.6181 130.035 9.49602 131.947 9.49602C133.567 9.49602 134.894 10.2901 135.428 11.3607L134.325 12.241C133.86 11.3434 133.016 10.7737 131.878 10.7737C130.844 10.7737 130.155 11.2915 130.155 12.1031C130.155 12.9489 130.948 13.1043 132.206 13.3806C133.757 13.7431 135.531 14.0538 135.531 16.0221C135.531 17.7485 133.963 18.888 132.033 18.888C130.396 18.888 128.759 18.18 128.07 16.7818L129.276 15.901ZM138.503 17.386V21.6157H136.953V9.66864H138.503V10.9807C139.038 10.1002 140.037 9.49599 141.295 9.49599C143.794 9.49599 145.224 11.6196 145.224 14.1919C145.224 16.747 143.794 18.8879 141.295 18.8879C140.037 18.8879 139.038 18.2837 138.503 17.386ZM138.469 14.52C138.469 16.5917 139.744 17.5241 141.019 17.5241C142.708 17.5241 143.656 16.1256 143.656 14.1919C143.656 12.241 142.708 10.8598 141.019 10.8598C139.744 10.8598 138.469 11.775 138.469 13.8811V14.52ZM146.244 16.2636C146.244 14.4682 147.639 13.7259 149.656 13.3115L151.844 12.8626V12.4827C151.844 11.4469 151.275 10.8599 150.069 10.8599C148.932 10.8599 148.26 11.395 147.984 12.3964L146.519 12.0168C146.95 10.5492 148.277 9.49607 150.121 9.49607C152.137 9.49607 153.377 10.4801 153.377 12.4136V16.8162C153.377 17.4032 153.739 17.593 154.342 17.455V18.698C152.964 18.8706 152.171 18.5427 151.982 17.6793C151.43 18.3872 150.431 18.8534 149.207 18.8534C147.57 18.8534 146.244 17.8867 146.244 16.2637L146.244 16.2636ZM151.844 14.0711L150.086 14.4508C148.708 14.7272 147.777 15.107 147.777 16.1947C147.777 17.0751 148.415 17.5929 149.397 17.5929C150.724 17.5929 151.844 16.7818 151.844 15.6249V14.0711ZM159.158 17.524C160.399 17.524 161.14 16.7298 161.398 15.6077L162.777 16.2464C162.346 17.7484 161.036 18.8879 159.158 18.8879C156.643 18.8879 154.902 16.9715 154.902 14.1918C154.902 11.395 156.643 9.49596 159.158 9.49596C161.036 9.49596 162.312 10.5837 162.742 12.0857L161.398 12.759C161.14 11.6541 160.399 10.8426 159.158 10.8426C157.556 10.8426 156.453 12.1202 156.453 14.1918C156.453 16.2464 157.556 17.524 159.158 17.524ZM163.505 14.1918C163.505 11.4987 165.21 9.49596 167.657 9.49596C170.173 9.49596 171.5 11.4123 171.5 13.9157V14.4336H164.987C165.073 16.3328 166.158 17.5414 167.726 17.5414C168.932 17.5414 169.794 16.8852 170.07 15.8147L171.431 16.2982C170.88 17.9038 169.518 18.8879 167.726 18.8879C165.228 18.8879 163.505 16.9715 163.505 14.1918ZM165.073 13.2423H169.932C169.897 11.9648 169.208 10.8253 167.64 10.8253C166.331 10.8253 165.348 11.7058 165.073 13.2423ZM89.5359 5.76492L80.2569 0.186802C79.8423 -0.0622847 79.3275 -0.0622502 78.913 0.186802L69.634 5.76496C69.2429 6.0001 69 6.42999 69 6.88692V18.113C69 18.57 69.2429 18.9999 69.634 19.235L74.2882 22.0329L74.2885 22.0331L78.913 24.8132C79.1203 24.9377 79.3525 25 79.585 25C79.8173 25 80.0496 24.9377 80.2569 24.8132L84.8815 22.0331L84.8817 22.0329L89.5359 19.2349C89.9269 18.9999 90.1698 18.57 90.1698 18.113V6.88692C90.1698 6.42996 89.9269 6.00006 89.5359 5.76492ZM89.62 18.113C89.62 18.3776 89.4794 18.6264 89.253 18.7626L85.0149 21.3103V16.1838C85.0149 15.7268 84.772 15.2969 84.3808 15.0618L80.2569 12.5826C79.8425 12.3335 79.3276 12.3336 78.9131 12.5826L74.789 15.0619C74.398 15.2969 74.155 15.7268 74.155 16.1838V21.3103L69.9169 18.7626C69.6905 18.6264 69.5499 18.3776 69.5499 18.113V6.88692C69.5499 6.62237 69.6905 6.37348 69.9169 6.23738L79.196 0.659255C79.3159 0.587119 79.4504 0.551068 79.585 0.551068C79.7196 0.551068 79.854 0.587119 79.974 0.659255L89.253 6.23738C89.4794 6.37348 89.62 6.6224 89.62 6.88692V18.113ZM83.6422 16.5801L80.727 18.3329C80.1922 18.6547 79.8599 19.2428 79.8599 19.8679V23.448C79.8599 23.4963 79.8346 23.5412 79.7931 23.5661L79.6557 23.6487C79.6121 23.6748 79.5578 23.6748 79.5142 23.6487L79.3768 23.566C79.3353 23.5411 79.31 23.4962 79.31 23.4478V19.8669C79.3097 19.242 78.9773 18.6542 78.4425 18.3326L75.5277 16.5801C75.4863 16.5552 75.4609 16.5103 75.4609 16.462V16.2618C75.4609 16.2134 75.4863 16.1685 75.5277 16.1436L75.6283 16.0832C75.6719 16.057 75.7262 16.057 75.7698 16.0832L78.6671 17.8252C79.2338 18.1651 79.9373 18.1649 80.5038 17.8246L83.4003 16.0831C83.4439 16.057 83.4982 16.057 83.5418 16.0831L83.6422 16.1435C83.6837 16.1684 83.7091 16.2132 83.7091 16.2617V16.462C83.7091 16.5105 83.6837 16.5552 83.6422 16.5801ZM88.7973 7.28321C88.1018 7.70129 85.8827 9.03532 85.8826 9.03542C85.3474 9.35713 85.0149 9.94541 85.0149 10.5707V14.3168C85.0149 14.367 84.9877 14.4131 84.944 14.4374C84.9002 14.4616 84.8467 14.4601 84.8044 14.4335C84.8039 14.4332 84.8038 14.4335 84.8034 14.4333C84.7923 14.4263 84.7813 14.4191 84.7699 14.4123L84.5318 14.2692C84.4904 14.2443 84.4651 14.1994 84.4651 14.151V10.5707C84.4651 9.94541 84.1326 9.35709 83.5974 9.03539C83.5972 9.03529 79.8989 6.81671 79.8599 6.80138V11.5046C79.8599 11.5426 79.8442 11.579 79.8165 11.605C79.7888 11.631 79.7516 11.6445 79.7138 11.6421C79.7135 11.6421 79.7135 11.6422 79.7133 11.6422C79.6278 11.6369 79.5422 11.6369 79.4567 11.6422C79.4565 11.6422 79.4563 11.6421 79.456 11.6421C79.4182 11.6445 79.381 11.6311 79.3533 11.6051C79.3256 11.579 79.31 11.5427 79.31 11.5047V6.80146C79.2709 6.81677 75.5726 9.03539 75.5725 9.03545C75.0373 9.35716 74.7049 9.94545 74.7049 10.5708V14.151C74.7049 14.1995 74.6795 14.2443 74.6381 14.2692L74.3999 14.4124C74.3887 14.4192 74.3777 14.4263 74.3665 14.4333C74.3662 14.4334 74.3661 14.4332 74.3656 14.4335C74.3232 14.4601 74.2697 14.4617 74.226 14.4374C74.1822 14.4132 74.155 14.367 74.155 14.3169V10.5708C74.155 9.94548 73.8225 9.35719 73.2874 9.03549C73.2872 9.03539 71.0681 7.70132 70.3726 7.28327C70.3312 7.25838 70.3059 7.21354 70.3059 7.16516V6.96498C70.3059 6.9166 70.3312 6.87176 70.3726 6.84687L70.4733 6.78634C70.5168 6.76016 70.5712 6.76016 70.6147 6.78634C71.2998 7.19819 73.5104 8.52709 73.5105 8.52712C74.0772 8.86787 74.7813 8.86807 75.3483 8.52775L78.913 6.38478C79.3275 6.13573 79.8423 6.1357 80.2569 6.38478L83.8214 8.5276C84.3884 8.86804 85.0926 8.86791 85.6594 8.52709C85.6594 8.52702 87.8703 7.19805 88.5553 6.78627C88.5988 6.7601 88.6531 6.7601 88.6967 6.78627L88.7973 6.84673C88.8387 6.87163 88.864 6.91645 88.864 6.96484V7.16516C88.864 7.21354 88.8387 7.25832 88.7973 7.28321Z" fill="white"/> <path d="M3.168 9.289C4.30467 9.289 5.17733 9.49067 5.786 9.894C6.39467 10.29 6.699 10.9427 6.699 11.852C6.699 12.7687 6.391 13.4323 5.775 13.843C5.159 14.2463 4.279 14.448 3.135 14.448H2.596V17H0.88V9.487C1.254 9.41367 1.65 9.36233 2.068 9.333C2.486 9.30367 2.85267 9.289 3.168 9.289ZM3.278 10.752C3.15333 10.752 3.02867 10.7557 2.904 10.763C2.78667 10.7703 2.684 10.7777 2.596 10.785V12.985H3.135C3.729 12.985 4.17633 12.9043 4.477 12.743C4.77767 12.5817 4.928 12.281 4.928 11.841C4.928 11.6283 4.88767 11.4523 4.807 11.313C4.73367 11.1737 4.62367 11.0637 4.477 10.983C4.33767 10.895 4.16533 10.8363 3.96 10.807C3.75467 10.7703 3.52733 10.752 3.278 10.752ZM13.32 14.096C13.32 14.5507 13.254 14.9687 13.122 15.35C12.99 15.724 12.7993 16.0467 12.55 16.318C12.3006 16.582 12 16.7873 11.648 16.934C11.3033 17.0807 10.9146 17.154 10.482 17.154C10.0566 17.154 9.66797 17.0807 9.31597 16.934C8.9713 16.7873 8.6743 16.582 8.42497 16.318C8.17564 16.0467 7.9813 15.724 7.84197 15.35C7.70264 14.9687 7.63297 14.5507 7.63297 14.096C7.63297 13.6413 7.70264 13.227 7.84197 12.853C7.98864 12.479 8.18664 12.16 8.43597 11.896C8.69264 11.632 8.9933 11.4267 9.33797 11.28C9.68997 11.1333 10.0713 11.06 10.482 11.06C10.9 11.06 11.2813 11.1333 11.626 11.28C11.978 11.4267 12.2786 11.632 12.528 11.896C12.7773 12.16 12.9716 12.479 13.111 12.853C13.2503 13.227 13.32 13.6413 13.32 14.096ZM11.648 14.096C11.648 13.59 11.5453 13.194 11.34 12.908C11.142 12.6147 10.856 12.468 10.482 12.468C10.108 12.468 9.8183 12.6147 9.61297 12.908C9.40764 13.194 9.30497 13.59 9.30497 14.096C9.30497 14.602 9.40764 15.0053 9.61297 15.306C9.8183 15.5993 10.108 15.746 10.482 15.746C10.856 15.746 11.142 15.5993 11.34 15.306C11.5453 15.0053 11.648 14.602 11.648 14.096ZM18.2007 13.678C18.054 14.2353 17.8964 14.789 17.7277 15.339C17.5664 15.889 17.394 16.4427 17.2107 17H15.9347C15.8027 16.692 15.6597 16.3253 15.5057 15.9C15.3517 15.4747 15.1904 15.0127 15.0217 14.514C14.8604 14.008 14.6917 13.4763 14.5157 12.919C14.347 12.3543 14.182 11.786 14.0207 11.214H15.7477C15.8064 11.478 15.8687 11.7677 15.9347 12.083C16.008 12.391 16.0814 12.71 16.1547 13.04C16.2354 13.37 16.316 13.7037 16.3967 14.041C16.4847 14.371 16.5727 14.69 16.6607 14.998C16.756 14.6753 16.8477 14.3453 16.9357 14.008C17.031 13.6707 17.119 13.3407 17.1997 13.018C17.2877 12.688 17.3684 12.3727 17.4417 12.072C17.5224 11.764 17.592 11.478 17.6507 11.214H18.8387C18.8974 11.478 18.9634 11.764 19.0367 12.072C19.11 12.3727 19.187 12.688 19.2677 13.018C19.3484 13.3407 19.4327 13.6707 19.5207 14.008C19.6087 14.3453 19.7004 14.6753 19.7957 14.998C19.8837 14.69 19.9717 14.371 20.0597 14.041C20.1477 13.7037 20.2284 13.37 20.3017 13.04C20.3824 12.71 20.4557 12.391 20.5217 12.083C20.595 11.7677 20.661 11.478 20.7197 11.214H22.4247C22.2634 11.786 22.0947 12.3543 21.9187 12.919C21.75 13.4763 21.5814 14.008 21.4127 14.514C21.2514 15.0127 21.09 15.4747 20.9287 15.9C20.7747 16.3253 20.6317 16.692 20.4997 17H19.2237C19.0404 16.4427 18.8607 15.889 18.6847 15.339C18.5087 14.789 18.3474 14.2353 18.2007 13.678ZM23.1228 14.151C23.1228 13.6377 23.1998 13.1903 23.3538 12.809C23.5151 12.4203 23.7241 12.0977 23.9808 11.841C24.2374 11.5843 24.5308 11.39 24.8608 11.258C25.1981 11.126 25.5428 11.06 25.8948 11.06C26.7161 11.06 27.3651 11.313 27.8418 11.819C28.3184 12.3177 28.5568 13.0547 28.5568 14.03C28.5568 14.1253 28.5531 14.2317 28.5458 14.349C28.5384 14.459 28.5311 14.558 28.5238 14.646H24.8058C24.8424 14.9833 25.0001 15.251 25.2788 15.449C25.5574 15.647 25.9314 15.746 26.4008 15.746C26.7014 15.746 26.9948 15.7203 27.2808 15.669C27.5741 15.6103 27.8124 15.5407 27.9958 15.46L28.2158 16.791C28.1278 16.835 28.0104 16.879 27.8638 16.923C27.7171 16.967 27.5521 17.0037 27.3688 17.033C27.1928 17.0697 27.0021 17.099 26.7968 17.121C26.5914 17.143 26.3861 17.154 26.1808 17.154C25.6601 17.154 25.2054 17.077 24.8168 16.923C24.4354 16.769 24.1164 16.56 23.8598 16.296C23.6104 16.0247 23.4234 15.7057 23.2988 15.339C23.1814 14.9723 23.1228 14.5763 23.1228 14.151ZM26.9728 13.524C26.9654 13.3847 26.9398 13.249 26.8958 13.117C26.8591 12.985 26.7968 12.8677 26.7088 12.765C26.6281 12.6623 26.5218 12.578 26.3898 12.512C26.2651 12.446 26.1074 12.413 25.9168 12.413C25.7334 12.413 25.5758 12.446 25.4438 12.512C25.3118 12.5707 25.2018 12.6513 25.1138 12.754C25.0258 12.8567 24.9561 12.9777 24.9048 13.117C24.8608 13.249 24.8278 13.3847 24.8058 13.524H26.9728ZM33.5286 12.666C33.3819 12.6293 33.2096 12.5927 33.0116 12.556C32.8136 12.512 32.6009 12.49 32.3736 12.49C32.2709 12.49 32.1463 12.501 31.9996 12.523C31.8603 12.5377 31.7539 12.556 31.6806 12.578V17H30.0416V11.522C30.3349 11.4193 30.6796 11.324 31.0756 11.236C31.4789 11.1407 31.9263 11.093 32.4176 11.093C32.5056 11.093 32.6119 11.1003 32.7366 11.115C32.8613 11.1223 32.9859 11.137 33.1106 11.159C33.2353 11.1737 33.3599 11.1957 33.4846 11.225C33.6093 11.247 33.7156 11.2763 33.8036 11.313L33.5286 12.666ZM34.5198 14.151C34.5198 13.6377 34.5968 13.1903 34.7508 12.809C34.9121 12.4203 35.1211 12.0977 35.3778 11.841C35.6345 11.5843 35.9278 11.39 36.2578 11.258C36.5951 11.126 36.9398 11.06 37.2918 11.06C38.1131 11.06 38.7621 11.313 39.2388 11.819C39.7155 12.3177 39.9538 13.0547 39.9538 14.03C39.9538 14.1253 39.9501 14.2317 39.9428 14.349C39.9355 14.459 39.9281 14.558 39.9208 14.646H36.2028C36.2395 14.9833 36.3971 15.251 36.6758 15.449C36.9545 15.647 37.3285 15.746 37.7978 15.746C38.0985 15.746 38.3918 15.7203 38.6778 15.669C38.9711 15.6103 39.2095 15.5407 39.3928 15.46L39.6128 16.791C39.5248 16.835 39.4075 16.879 39.2608 16.923C39.1141 16.967 38.9491 17.0037 38.7658 17.033C38.5898 17.0697 38.3991 17.099 38.1938 17.121C37.9885 17.143 37.7831 17.154 37.5778 17.154C37.0571 17.154 36.6025 17.077 36.2138 16.923C35.8325 16.769 35.5135 16.56 35.2568 16.296C35.0075 16.0247 34.8205 15.7057 34.6958 15.339C34.5785 14.9723 34.5198 14.5763 34.5198 14.151ZM38.3698 13.524C38.3625 13.3847 38.3368 13.249 38.2928 13.117C38.2561 12.985 38.1938 12.8677 38.1058 12.765C38.0251 12.6623 37.9188 12.578 37.7868 12.512C37.6621 12.446 37.5045 12.413 37.3138 12.413C37.1305 12.413 36.9728 12.446 36.8408 12.512C36.7088 12.5707 36.5988 12.6513 36.5108 12.754C36.4228 12.8567 36.3531 12.9777 36.3018 13.117C36.2578 13.249 36.2248 13.3847 36.2028 13.524H38.3698ZM42.8356 14.063C42.8356 14.569 42.9493 14.976 43.1766 15.284C43.404 15.592 43.7413 15.746 44.1886 15.746C44.3353 15.746 44.471 15.7423 44.5956 15.735C44.7203 15.7203 44.823 15.7057 44.9036 15.691V12.71C44.801 12.644 44.6653 12.589 44.4966 12.545C44.3353 12.501 44.1703 12.479 44.0016 12.479C43.2243 12.479 42.8356 13.007 42.8356 14.063ZM46.5426 16.813C46.396 16.857 46.2273 16.901 46.0366 16.945C45.846 16.9817 45.6443 17.0147 45.4316 17.044C45.2263 17.0733 45.0136 17.0953 44.7936 17.11C44.581 17.132 44.3756 17.143 44.1776 17.143C43.701 17.143 43.2756 17.0733 42.9016 16.934C42.5276 16.7947 42.2123 16.5967 41.9556 16.34C41.699 16.076 41.501 15.7607 41.3616 15.394C41.2296 15.02 41.1636 14.602 41.1636 14.14C41.1636 13.6707 41.2223 13.249 41.3396 12.875C41.457 12.4937 41.6256 12.171 41.8456 11.907C42.0656 11.643 42.3333 11.4413 42.6486 11.302C42.9713 11.1627 43.338 11.093 43.7486 11.093C43.976 11.093 44.1776 11.115 44.3536 11.159C44.537 11.203 44.7203 11.2653 44.9036 11.346V8.728L46.5426 8.464V16.813ZM54.8669 14.063C54.8669 13.007 54.4782 12.479 53.7009 12.479C53.5322 12.479 53.3635 12.501 53.1949 12.545C53.0335 12.589 52.9015 12.644 52.7989 12.71V15.691C52.8795 15.7057 52.9822 15.7203 53.1069 15.735C53.2315 15.7423 53.3672 15.746 53.5139 15.746C53.9612 15.746 54.2985 15.592 54.5259 15.284C54.7532 14.976 54.8669 14.569 54.8669 14.063ZM56.5389 14.107C56.5389 14.569 56.4692 14.987 56.3299 15.361C56.1979 15.735 56.0035 16.054 55.7469 16.318C55.4902 16.582 55.1749 16.7873 54.8009 16.934C54.4269 17.0733 54.0015 17.143 53.5249 17.143C53.3269 17.143 53.1179 17.132 52.8979 17.11C52.6852 17.0953 52.4725 17.0733 52.2599 17.044C52.0545 17.0147 51.8565 16.9817 51.6659 16.945C51.4752 16.901 51.3065 16.857 51.1599 16.813V8.728L52.7989 8.464V11.346C52.9822 11.2653 53.1729 11.203 53.3709 11.159C53.5689 11.115 53.7815 11.093 54.0089 11.093C54.4195 11.093 54.7825 11.1663 55.0979 11.313C55.4132 11.4523 55.6772 11.654 55.8899 11.918C56.1025 12.182 56.2639 12.501 56.3739 12.875C56.4839 13.2417 56.5389 13.6523 56.5389 14.107ZM63.0052 11.214C62.6752 12.3287 62.3305 13.3737 61.9712 14.349C61.6118 15.3243 61.2195 16.2703 60.7942 17.187C60.6402 17.517 60.4862 17.7957 60.3322 18.023C60.1782 18.2577 60.0095 18.4483 59.8262 18.595C59.6428 18.749 59.4338 18.859 59.1992 18.925C58.9718 18.9983 58.7042 19.035 58.3962 19.035C58.1395 19.035 57.9012 19.0093 57.6812 18.958C57.4685 18.914 57.2925 18.8627 57.1532 18.804L57.4392 17.495C57.6078 17.5537 57.7582 17.594 57.8902 17.616C58.0222 17.638 58.1615 17.649 58.3082 17.649C58.6015 17.649 58.8252 17.5683 58.9792 17.407C59.1405 17.253 59.2762 17.0367 59.3862 16.758C59.0122 16.0247 58.6382 15.2033 58.2642 14.294C57.8902 13.3773 57.5382 12.3507 57.2082 11.214H58.9462C59.0195 11.5 59.1038 11.8117 59.1992 12.149C59.3018 12.479 59.4082 12.8163 59.5182 13.161C59.6282 13.4983 59.7382 13.8283 59.8482 14.151C59.9655 14.4737 60.0755 14.767 60.1782 15.031C60.2735 14.767 60.3725 14.4737 60.4752 14.151C60.5778 13.8283 60.6768 13.4983 60.7722 13.161C60.8748 12.8163 60.9702 12.479 61.0582 12.149C61.1535 11.8117 61.2378 11.5 61.3112 11.214H63.0052Z" fill="#C1C7CD"/> </svg>`;
25600
+ // The same mark Navigator uses on its Operator tile.
25601
+ const ICON_OPERATOR = `<svg width="32" height="32" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M36 0L6 18V54L36 72L66 54V18L36 0ZM36 58.8L18 48L23.001 45L36 52.8L48.999 45L54 48L36 58.8ZM36 46.8L18 36L23.001 33L36 40.8L48.999 33L54 36L36 46.8ZM36 34.8L18 24L36 13.2L54 24L36 34.8Z" fill="white"/><path opacity="0.85" d="M54 24L36 34.8L18 24L36 13.2L54 24ZM36 52.8L23.001 45L18 48L36 58.8L54 48L48.999 45L36 52.8ZM36 40.8L23.001 33L18 36L36 46.8L54 36L48.999 33L36 40.8Z" fill="black"/></svg>`;
25602
+ const TERMS_URL = "https://www.nextspace.com/legal/terms-of-use";
25603
+ const CONTACT_URL = "https://www.nextspace.com/about/contact?topic=support";
25604
+ const NEXTSPACE_URL = "https://nextspace.com/";
25605
+ class WidgetLeftPanelTabDashboard extends WidgetLeftPanelTab.ATab {
25606
+ constructor(params) {
25607
+ var _a, _b;
25608
+ super(params);
25609
+ this.STYLESHEET_ID = "nextspace-left-panel-tab-dashboard-stylesheet";
25610
+ // Bumped per load so a slow response for an old view or account can't overwrite a newer one.
25611
+ this._loadToken = 0;
25612
+ this._disposed = false;
25613
+ this._viewName = null;
25614
+ this._viewBrandingUrl = null;
25615
+ this._accountBrandingUrl = null;
25616
+ this._accountLinks = [];
25617
+ this._operatorUrl = null;
25618
+ // Null while the account limit check is still in flight.
25619
+ this._operatorAllowed = null;
25620
+ this._operatorError = null;
25621
+ this._apiVersion = null;
25622
+ this._user = null;
25623
+ this._generateStyles();
25624
+ // Sized before the first render so percentage widths inside resolve against the final panel.
25625
+ if (this.Container) {
25626
+ this.Container.style.width = "510px";
25627
+ }
25628
+ this._generateElement();
25629
+ this._load();
25630
+ this._viewIdChangeRemoval = (_b = (_a = this._widget) === null || _a === void 0 ? void 0 : _a.OnViewIdChange) === null || _b === void 0 ? void 0 : _b.Subscribe(() => {
25631
+ this._load();
25632
+ });
25633
+ this._paramsChangeRemoval = ENVIRONMENT.OnParamsChange.Subscribe(() => {
25634
+ this._load();
25635
+ });
25636
+ }
25637
+ Dispose() {
25638
+ var _a, _b;
25639
+ this._disposed = true;
25640
+ (_a = this._viewIdChangeRemoval) === null || _a === void 0 ? void 0 : _a.call(this);
25641
+ (_b = this._paramsChangeRemoval) === null || _b === void 0 ? void 0 : _b.call(this);
25642
+ super.Dispose();
25643
+ }
25644
+ _generateStyles() {
25645
+ if (document.getElementById(this.STYLESHEET_ID)) {
25646
+ return;
25647
+ }
25648
+ const style = document.createElement("style");
25649
+ style.id = this.STYLESHEET_ID;
25650
+ style.innerHTML = `
25651
+ .NextspaceLeftPanelTabDashboard * {
25652
+ box-sizing: border-box;
25653
+ }
25654
+
25655
+ .NextspaceLeftPanelTabDashboard {
25656
+ color: #fff;
25657
+ display: flex;
25658
+ flex-direction: column;
25659
+ flex-grow: 1;
25660
+ flex-shrink: 1;
25661
+ font-family: Arial, sans-serif;
25662
+ font-size: 13px;
25663
+ overflow: auto;
25664
+ width: 100%;
25665
+ }
25666
+
25667
+ .NextspaceLeftPanelTabDashboardTitle {
25668
+ color: #fff;
25669
+ flex-shrink: 0;
25670
+ font-size: 16px;
25671
+ font-weight: 500;
25672
+ margin-bottom: 12px;
25673
+ overflow: hidden;
25674
+ text-overflow: ellipsis;
25675
+ white-space: nowrap;
25676
+ }
25677
+
25678
+ .NextspaceLeftPanelTabDashboardTitle >.NextspaceLeftPanelTabDashboardTitleLabel {
25679
+ color: #00affa;
25680
+ }
25681
+
25682
+ .NextspaceLeftPanelTabDashboardTiles {
25683
+ display: grid;
25684
+ flex-shrink: 0;
25685
+ gap: 20px;
25686
+ grid-template-columns: fit-content(20px) fit-content(20px) 1fr;
25687
+ place-content: center;
25688
+ }
25689
+
25690
+ .NextspaceLeftPanelTabDashboardTile {
25691
+ align-items: center;
25692
+ border: 1px solid rgba(255, 255, 255, .12);
25693
+ border-radius: 6px;
25694
+ color: #fff;
25695
+ cursor: pointer;
25696
+ display: flex;
25697
+ flex-direction: column;
25698
+ font-size: 10px;
25699
+ height: 120px;
25700
+ justify-content: center;
25701
+ min-width: 120px;
25702
+ padding: 0 12px;
25703
+ text-align: center;
25704
+ transition: transform .3s ease, opacity .3s ease;
25705
+ }
25706
+
25707
+ .NextspaceLeftPanelTabDashboardTile:hover {
25708
+ transform: translateY(-4px);
25709
+ }
25710
+
25711
+ .NextspaceLeftPanelTabDashboardTile[is-disabled="true"] {
25712
+ cursor: default;
25713
+ opacity: .4;
25714
+ transform: none;
25715
+ }
25716
+
25717
+ .NextspaceLeftPanelTabDashboardTile >svg {
25718
+ height: 30px;
25719
+ margin-bottom: 10px;
25720
+ width: 30px;
25721
+ }
25722
+
25723
+ /* Carries the auto margin for the whole footer, so it always sits at the bottom. */
25724
+ .NextspaceLeftPanelTabDashboardBrandingImages {
25725
+ align-items: flex-start;
25726
+ display: flex;
25727
+ flex-shrink: 0;
25728
+ flex-wrap: wrap;
25729
+ margin-top: auto;
25730
+ padding-top: 40px;
25731
+ }
25732
+
25733
+ .NextspaceLeftPanelTabDashboardBrandingImages[has-images="true"] {
25734
+ max-height: 198px;
25735
+ overflow: hidden;
25736
+ padding: 24px;
25737
+ }
25738
+
25739
+ /*
25740
+ * The box is clamped as well as the image so a banner can't paint at its intrinsic
25741
+ * size for a frame before the max-width resolves.
25742
+ */
25743
+ .NextspaceLeftPanelTabDashboardBrandingImages >img {
25744
+ height: auto;
25745
+ margin-right: 20px;
25746
+ max-height: 150px;
25747
+ max-width: 80%;
25748
+ min-width: 0;
25749
+ object-fit: contain;
25750
+ overflow: hidden;
25751
+ width: auto;
25752
+ }
25753
+
25754
+ .NextspaceLeftPanelTabDashboardBrandingImages >img:last-of-type {
25755
+ margin-right: 0;
25756
+ }
25757
+
25758
+ .NextspaceLeftPanelTabDashboardCustomLinks {
25759
+ display: flex;
25760
+ flex-shrink: 0;
25761
+ flex-wrap: wrap;
25762
+ margin-left: 24px;
25763
+ }
25764
+
25765
+ .NextspaceLeftPanelTabDashboardBranding {
25766
+ border-top: 2px solid #000;
25767
+ flex-shrink: 0;
25768
+ margin-top: 20px;
25769
+ padding: 24px;
25770
+ }
25771
+
25772
+ .NextspaceLeftPanelTabDashboardBranding >svg {
25773
+ height: max-content;
25774
+ max-width: 220px;
25775
+ }
25776
+
25777
+ .NextspaceLeftPanelTabDashboardLinks {
25778
+ align-items: center;
25779
+ display: flex;
25780
+ flex-wrap: wrap;
25781
+ margin-top: 32px;
25782
+ }
25783
+
25784
+ .NextspaceLeftPanelTabDashboard a {
25785
+ color: #40c4ff;
25786
+ font-size: 11px;
25787
+ letter-spacing: .02em;
25788
+ line-height: 16px;
25789
+ margin-right: 20px;
25790
+ text-decoration: underline;
25791
+ }
25792
+
25793
+ .NextspaceLeftPanelTabDashboardTip {
25794
+ color: #c1c7cd;
25795
+ font-size: 11px;
25796
+ letter-spacing: .02em;
25797
+ line-height: 16px;
25798
+ margin-top: 24px;
25799
+ }
25800
+ `;
25801
+ document.head.appendChild(style);
25802
+ }
25803
+ _generateElement() {
25804
+ if (this._element && this._element.parentElement) {
25805
+ this._element.parentElement.removeChild(this._element);
25806
+ }
25807
+ const element = document.createElement("div");
25808
+ element.className = "NextspaceLeftPanelTabDashboard";
25809
+ element.appendChild(this._buildTitle());
25810
+ element.appendChild(this._buildTiles());
25811
+ element.appendChild(this._buildBrandingImages());
25812
+ element.appendChild(this._buildCustomLinks());
25813
+ element.appendChild(this._buildBranding());
25814
+ this.Container.appendChild(element);
25815
+ this._element = element;
25816
+ }
25817
+ _buildTitle() {
25818
+ var _a, _b;
25819
+ const title = document.createElement("div");
25820
+ title.className = "NextspaceLeftPanelTabDashboardTitle";
25821
+ const label = document.createElement("span");
25822
+ label.className = "NextspaceLeftPanelTabDashboardTitleLabel";
25823
+ label.textContent = (_a = this._viewName) !== null && _a !== void 0 ? _a : (((_b = this._widget) === null || _b === void 0 ? void 0 : _b.ViewId) ? "Unnamed Project View" : "Loading...");
25824
+ title.appendChild(label);
25825
+ const suffix = document.createElement("span");
25826
+ suffix.textContent = ", Dashboard";
25827
+ title.appendChild(suffix);
25828
+ title.title = label.textContent + suffix.textContent;
25829
+ return title;
25830
+ }
25831
+ _buildTiles() {
25832
+ var _a;
25833
+ const tiles = document.createElement("div");
25834
+ tiles.className = "NextspaceLeftPanelTabDashboardTiles";
25835
+ // The other Navigator tiles open panels this library doesn't ship, so Operator is the only one here.
25836
+ const disabled = this._operatorAllowed !== true;
25837
+ const tile = document.createElement("div");
25838
+ tile.className = "NextspaceLeftPanelTabDashboardTile";
25839
+ tile.setAttribute("is-disabled", String(disabled));
25840
+ tile.innerHTML = ICON_OPERATOR;
25841
+ if (disabled) {
25842
+ tile.title = this._operatorAllowed == null ? "Validating..." : ((_a = this._operatorError) !== null && _a !== void 0 ? _a : "You don't have permission to access this option.");
25843
+ }
25844
+ const caption = document.createElement("div");
25845
+ caption.textContent = "Operator";
25846
+ tile.appendChild(caption);
25847
+ tile.onclick = () => {
25848
+ if (this._operatorAllowed !== true || !this._operatorUrl) {
25849
+ return;
25850
+ }
25851
+ window.open(this._operatorUrl, "_blank");
25852
+ };
25853
+ tiles.appendChild(tile);
25854
+ return tiles;
25855
+ }
25856
+ _buildBrandingImages() {
25857
+ const images = document.createElement("div");
25858
+ images.className = "NextspaceLeftPanelTabDashboardBrandingImages";
25859
+ for (const url of [this._accountBrandingUrl, this._viewBrandingUrl]) {
25860
+ if (!url) {
25861
+ continue;
25862
+ }
25863
+ const img = document.createElement("img");
25864
+ img.src = url;
25865
+ img.loading = "lazy";
25866
+ images.appendChild(img);
25867
+ }
25868
+ // Always rendered even when empty, since this element carries the footer's auto margin.
25869
+ images.setAttribute("has-images", String(images.children.length > 0));
25870
+ return images;
25871
+ }
25872
+ _buildCustomLinks() {
25873
+ var _a, _b;
25874
+ const links = document.createElement("div");
25875
+ links.className = "NextspaceLeftPanelTabDashboardCustomLinks";
25876
+ for (const link of (_a = this._accountLinks) !== null && _a !== void 0 ? _a : []) {
25877
+ if (!(link === null || link === void 0 ? void 0 : link.url)) {
25878
+ continue;
25879
+ }
25880
+ const anchor = document.createElement("a");
25881
+ anchor.href = link.url;
25882
+ anchor.target = "_blank";
25883
+ anchor.rel = "noopener noreferrer";
25884
+ anchor.textContent = (_b = link.name) !== null && _b !== void 0 ? _b : link.url;
25885
+ links.appendChild(anchor);
25886
+ }
25887
+ links.style.display = links.children.length ? "flex" : "none";
25888
+ return links;
25889
+ }
25890
+ _buildBranding() {
25891
+ const branding = document.createElement("div");
25892
+ branding.className = "NextspaceLeftPanelTabDashboardBranding";
25893
+ // Once an account or view brands the panel, the Nextspace mark steps back to "powered by".
25894
+ const hasCustomBranding = !!(this._accountBrandingUrl || this._viewBrandingUrl);
25895
+ const logo = document.createElement("div");
25896
+ logo.innerHTML = hasCustomBranding ? ICON_NEXTSPACE_POWERED : ICON_NEXTSPACE_LEAF;
25897
+ logo.style.cursor = "pointer";
25898
+ logo.title = "Nextspace";
25899
+ logo.onclick = () => {
25900
+ window.open(NEXTSPACE_URL, "_blank");
25901
+ };
25902
+ branding.appendChild(logo);
25903
+ const links = document.createElement("div");
25904
+ links.className = "NextspaceLeftPanelTabDashboardLinks";
25905
+ links.appendChild(this._buildLink("Terms of Use", TERMS_URL));
25906
+ links.appendChild(this._buildLink("Help & support", this._getContactUrl()));
25907
+ branding.appendChild(links);
25908
+ const copyright = document.createElement("div");
25909
+ copyright.className = "NextspaceLeftPanelTabDashboardTip";
25910
+ copyright.textContent = `${new Date().getFullYear()} © Nextspace Limited. All rights reserved.`;
25911
+ branding.appendChild(copyright);
25912
+ const versions = document.createElement("div");
25913
+ versions.className = "NextspaceLeftPanelTabDashboardTip";
25914
+ versions.textContent = `Running API ${this._apiVersion || "UNKNOWN"}`;
25915
+ branding.appendChild(versions);
25916
+ return branding;
25917
+ }
25918
+ _buildLink(text, url) {
25919
+ const anchor = document.createElement("a");
25920
+ anchor.href = url;
25921
+ anchor.target = "_blank";
25922
+ anchor.rel = "noopener noreferrer";
25923
+ anchor.textContent = text;
25924
+ return anchor;
25925
+ }
25926
+ /**
25927
+ * Builds the support URL with the signed-in user's details prefilled.
25928
+ */
25929
+ _getContactUrl() {
25930
+ var _a, _b;
25931
+ let url = CONTACT_URL;
25932
+ const user = this._user;
25933
+ if (user) {
25934
+ const names = ((_a = user.FullName) !== null && _a !== void 0 ? _a : "").trim().split(" ").filter(x => !!x);
25935
+ const params = [
25936
+ ["email", user.Email],
25937
+ ["firstname", names.length ? names[0] : null],
25938
+ ["lastname", names.length > 1 ? names[names.length - 1] : null],
25939
+ ["phone", user.Mobile]
25940
+ ];
25941
+ for (const [key, value] of params) {
25942
+ if (value) {
25943
+ url = UrlUtils.AddQueryParam(url, key, value);
25944
+ }
25945
+ }
25946
+ }
25947
+ const accountId = (_b = ENVIRONMENT.PARAMS) === null || _b === void 0 ? void 0 : _b.accountId;
25948
+ if (accountId) {
25949
+ url = UrlUtils.AddQueryParam(url, "accountid", accountId);
25950
+ }
25951
+ return url;
25952
+ }
25953
+ /**
25954
+ * Gathers everything the panel shows.
25955
+ * Each source is caught on its own so one failure doesn't blank the whole panel.
25956
+ */
25957
+ async _load() {
25958
+ var _a, _b, _c;
25959
+ const token = ++this._loadToken;
25960
+ const getters = (_a = this._widget) === null || _a === void 0 ? void 0 : _a._getApiGetters();
25961
+ const accountId = (_b = ENVIRONMENT.PARAMS) === null || _b === void 0 ? void 0 : _b.accountId;
25962
+ const viewId = (_c = this._widget) === null || _c === void 0 ? void 0 : _c.ViewId;
25963
+ await Promise.all([
25964
+ this._loadView(viewId, getters),
25965
+ this._loadAccount(accountId, getters),
25966
+ this._loadOperatorAccess(accountId, getters),
25967
+ this._loadApiVersion(getters),
25968
+ this._loadUser(getters)
25969
+ ]);
25970
+ if (this._disposed || token !== this._loadToken) {
25971
+ return;
25972
+ }
25973
+ this._generateElement();
25974
+ }
25975
+ async _loadView(viewId, getters) {
25976
+ var _a, _b, _c, _d, _e;
25977
+ this._viewName = null;
25978
+ this._viewBrandingUrl = null;
25979
+ if (!viewId) {
25980
+ return;
25981
+ }
25982
+ try {
25983
+ const api = getters === null || getters === void 0 ? void 0 : getters.GetBruceApi();
25984
+ const data = await ProjectView.Get({
25985
+ viewId,
25986
+ api
25987
+ });
25988
+ this._viewName = (_b = (_a = data === null || data === void 0 ? void 0 : data.view) === null || _a === void 0 ? void 0 : _a.Name) !== null && _b !== void 0 ? _b : null;
25989
+ const fileId = (_e = (_d = (_c = data === null || data === void 0 ? void 0 : data.view) === null || _c === void 0 ? void 0 : _c.Settings) === null || _d === void 0 ? void 0 : _d.branding) === null || _e === void 0 ? void 0 : _e.bannerFileId;
25990
+ if (fileId) {
25991
+ this._viewBrandingUrl = ClientFile.GetUrl({
25992
+ fileId,
25993
+ api,
25994
+ viaCdn: true
25995
+ });
25996
+ }
25997
+ }
25998
+ catch (e) {
25999
+ console.error(e);
26000
+ }
26001
+ }
26002
+ async _loadAccount(accountId, getters) {
26003
+ var _a, _b, _c;
26004
+ this._accountBrandingUrl = null;
26005
+ this._accountLinks = [];
26006
+ this._operatorUrl = null;
26007
+ if (!accountId) {
26008
+ return;
26009
+ }
26010
+ try {
26011
+ const { account } = await Account.Get({
26012
+ accountId,
26013
+ appId: Account.EAppId.Navigator,
26014
+ api: getters === null || getters === void 0 ? void 0 : getters.GetGuardianApi()
26015
+ });
26016
+ const operatorBase = (_a = account === null || account === void 0 ? void 0 : account.URL) === null || _a === void 0 ? void 0 : _a.AppOperator;
26017
+ if (operatorBase) {
26018
+ const viewId = (_b = this._widget) === null || _b === void 0 ? void 0 : _b.ViewId;
26019
+ this._operatorUrl = UrlUtils.ConstructUrl({
26020
+ existing: operatorBase,
26021
+ url: viewId ? `projectviews/projectview:${viewId}/` : ""
26022
+ });
26023
+ }
26024
+ const settings = account === null || account === void 0 ? void 0 : account["Application.Settings"];
26025
+ const branding = settings === null || settings === void 0 ? void 0 : settings.branding;
26026
+ if (branding === null || branding === void 0 ? void 0 : branding.dashBannerFileId) {
26027
+ this._accountBrandingUrl = ClientFile.GetUrl({
26028
+ fileId: branding.dashBannerFileId,
26029
+ api: getters === null || getters === void 0 ? void 0 : getters.GetBruceApi(),
26030
+ viaCdn: true
26031
+ });
26032
+ }
26033
+ if ((_c = branding === null || branding === void 0 ? void 0 : branding.links) === null || _c === void 0 ? void 0 : _c.length) {
26034
+ // Bare domains would otherwise resolve against this app's own origin.
26035
+ this._accountLinks = branding.links.map(link => ({
26036
+ name: link.name,
26037
+ url: link.url && !link.url.startsWith("https://") ? `https://${link.url}` : link.url
26038
+ }));
26039
+ }
26040
+ }
26041
+ catch (e) {
26042
+ console.error(e);
26043
+ }
26044
+ }
26045
+ async _loadOperatorAccess(accountId, getters) {
26046
+ var _a;
26047
+ this._operatorAllowed = null;
26048
+ this._operatorError = null;
26049
+ try {
26050
+ const data = await AccountLimits.Assert.GetCanOpenOperator({
26051
+ accountId,
26052
+ api: getters === null || getters === void 0 ? void 0 : getters.GetGuardianApi()
26053
+ });
26054
+ this._operatorAllowed = !!(data === null || data === void 0 ? void 0 : data.allowed);
26055
+ this._operatorError = (_a = data === null || data === void 0 ? void 0 : data.errorText) !== null && _a !== void 0 ? _a : null;
26056
+ }
26057
+ catch (e) {
26058
+ console.error(e);
26059
+ this._operatorAllowed = false;
26060
+ }
26061
+ }
26062
+ /**
26063
+ * Reads the version of the Bruce API instance this account is served by.
26064
+ */
26065
+ async _loadApiVersion(getters) {
26066
+ this._apiVersion = null;
26067
+ try {
26068
+ const api = getters === null || getters === void 0 ? void 0 : getters.GetBruceApi();
26069
+ if (!api) {
26070
+ return;
26071
+ }
26072
+ // The API resolves its own version as part of loading.
26073
+ await api.Loading;
26074
+ this._apiVersion = api.Version;
26075
+ }
26076
+ catch (e) {
26077
+ console.error(e);
26078
+ }
26079
+ }
26080
+ async _loadUser(getters) {
26081
+ var _a, _b, _c;
26082
+ try {
26083
+ const sessionId = (_a = ENVIRONMENT.PARAMS) === null || _a === void 0 ? void 0 : _a.sessionId;
26084
+ const { session } = await Session.Get({
26085
+ api: getters === null || getters === void 0 ? void 0 : getters.GetGuardianApi(),
26086
+ sessionId,
26087
+ accountId: (_b = ENVIRONMENT.PARAMS) === null || _b === void 0 ? void 0 : _b.accountId
26088
+ });
26089
+ this._user = (_c = session === null || session === void 0 ? void 0 : session.User) !== null && _c !== void 0 ? _c : null;
26090
+ }
26091
+ catch (e) {
26092
+ console.error(e);
26093
+ this._user = null;
26094
+ }
26095
+ }
26096
+ }
26097
+
24520
26098
  const VIEWER_LEFT_PANEL_WIDGET_KEY = "_viewerLeftPanelWidget";
24521
26099
  const VIEWER_LEFT_PANEL_CSS_VAR_LEFT = "--nextspace-left-panel-width";
24522
26100
  class WidgetLeftPanel extends Widget.AWidget {
@@ -24529,11 +26107,24 @@ class WidgetLeftPanel extends Widget.AWidget {
24529
26107
  this._viewId = value;
24530
26108
  this._updatePanelStyles();
24531
26109
  this._loading = this.loadBookmarks();
26110
+ // An already-open tab needs to know, as the panel can be opened before a view has rendered.
26111
+ if (this._onViewIdChange) {
26112
+ this._onViewIdChange.Trigger(value);
26113
+ }
26114
+ }
26115
+ }
26116
+ get OnViewIdChange() {
26117
+ if (this._onViewIdChange == null) {
26118
+ this._onViewIdChange = new BruceEvent();
24532
26119
  }
26120
+ return this._onViewIdChange;
24533
26121
  }
24534
26122
  get Bookmarks() {
24535
26123
  return this.bookmarks;
24536
26124
  }
26125
+ get BookmarkGroups() {
26126
+ return this.bookmarkGroups;
26127
+ }
24537
26128
  get LastEnabledBookmarkId() {
24538
26129
  return this._lastEnabledBookmarkId;
24539
26130
  }
@@ -24565,6 +26156,8 @@ class WidgetLeftPanel extends Widget.AWidget {
24565
26156
  // Keeping the bookmark list and loading here at top level.
24566
26157
  // This allows us to share the data between tabs.
24567
26158
  this.bookmarks = [];
26159
+ // Groups the bookmarks above are sorted into, by their "UI.SlideGroup.ID".
26160
+ this.bookmarkGroups = [];
24568
26161
  this._lastEnabledBookmarkId = null;
24569
26162
  // Map of custom tabs added by external devs by calling AddPanelTab.
24570
26163
  // This is a mapping of the provided tab key + content class.
@@ -24589,16 +26182,21 @@ class WidgetLeftPanel extends Widget.AWidget {
24589
26182
  const api = this._apiGetters.GetBruceApi();
24590
26183
  if (!viewId) {
24591
26184
  this.bookmarks = [];
26185
+ this.bookmarkGroups = [];
24592
26186
  return;
24593
26187
  }
24594
- const data = await ProjectViewBookmark.GetList({
24595
- viewId,
24596
- api
24597
- });
26188
+ const [data, groups] = await Promise.all([
26189
+ ProjectViewBookmark.GetList({
26190
+ viewId,
26191
+ api
26192
+ }),
26193
+ this.loadBookmarkGroups(viewId, api)
26194
+ ]);
24598
26195
  if (this._viewId !== viewId) {
24599
26196
  return;
24600
26197
  }
24601
26198
  this.bookmarks = data.bookmarks;
26199
+ this.bookmarkGroups = groups;
24602
26200
  }
24603
26201
  catch (e) {
24604
26202
  console.error(e);
@@ -24606,6 +26204,24 @@ class WidgetLeftPanel extends Widget.AWidget {
24606
26204
  return;
24607
26205
  }
24608
26206
  this.bookmarks = [];
26207
+ this.bookmarkGroups = [];
26208
+ }
26209
+ }
26210
+ /**
26211
+ * Loads the bookmark groups for a view.
26212
+ * A failure here degrades to an ungrouped list rather than losing the bookmarks entirely.
26213
+ */
26214
+ async loadBookmarkGroups(viewId, api) {
26215
+ try {
26216
+ const groups = await ProjectViewBookmarkGroup.GetGroups({
26217
+ viewId,
26218
+ api
26219
+ });
26220
+ return groups !== null && groups !== void 0 ? groups : [];
26221
+ }
26222
+ catch (e) {
26223
+ console.error(e);
26224
+ return [];
24609
26225
  }
24610
26226
  }
24611
26227
  Dispose() {
@@ -24752,14 +26368,21 @@ class WidgetLeftPanel extends Widget.AWidget {
24752
26368
  element.className = "NextspaceLeftPanel";
24753
26369
  this.Container.appendChild(element);
24754
26370
  this._element = element;
24755
- this._addPlaceholderTab("Dashboard", `
26371
+ this._addPanelTab("dashboard", "Dashboard", `
24756
26372
  <svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
24757
26373
  <path fill-rule="evenodd" clip-rule="evenodd" d="M11 9C11 10.1046 10.1046 11 9 11C7.89543 11 7 10.1046 7 9C7 7.89543 7.89543 7 9 7C10.1046 7 11 7.89543 11 9ZM18 9C18 10.1046 17.1046 11 16 11C14.8954 11 14 10.1046 14 9C14 7.89543 14.8954 7 16 7C17.1046 7 18 7.89543 18 9ZM23 11C24.1046 11 25 10.1046 25 9C25 7.89543 24.1046 7 23 7C21.8954 7 21 7.89543 21 9C21 10.1046 21.8954 11 23 11ZM11 16C11 17.1046 10.1046 18 9 18C7.89543 18 7 17.1046 7 16C7 14.8954 7.89543 14 9 14C10.1046 14 11 14.8954 11 16ZM9 25C10.1046 25 11 24.1046 11 23C11 21.8954 10.1046 21 9 21C7.89543 21 7 21.8954 7 23C7 24.1046 7.89543 25 9 25ZM18 16C18 17.1046 17.1046 18 16 18C14.8954 18 14 17.1046 14 16C14 14.8954 14.8954 14 16 14C17.1046 14 18 14.8954 18 16ZM16 25C17.1046 25 18 24.1046 18 23C18 21.8954 17.1046 21 16 21C14.8954 21 14 21.8954 14 23C14 24.1046 14.8954 25 16 25ZM25 16C25 17.1046 24.1046 18 23 18C21.8954 18 21 17.1046 21 16C21 14.8954 21.8954 14 23 14C24.1046 14 25 14.8954 25 16ZM23 25C24.1046 25 25 24.1046 25 23C25 21.8954 24.1046 21 23 21C21.8954 21 21 21.8954 21 23C21 24.1046 21.8954 25 23 25Z" fill="white"></path>
24758
26374
  </svg>
24759
- `);
26375
+ `, "svg");
24760
26376
  const breaker = document.createElement("div");
24761
26377
  breaker.className = "NextspaceLeftPanelBreaker";
24762
26378
  this._element.appendChild(breaker);
26379
+ this._addPanelTab("menu-items", "Menu", `
26380
+ <svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
26381
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M15.5528 5.10557C15.8343 4.96481 16.1657 4.96481 16.4472 5.10557L25.4472 9.60557C25.786 9.77496 26 10.1212 26 10.5C26 10.8788 25.786 11.225 25.4472 11.3944L16.4472 15.8944C16.1657 16.0352 15.8343 16.0352 15.5528 15.8944L6.55279 11.3944C6.214 11.225 6 10.8788 6 10.5C6 10.1212 6.214 9.77496 6.55279 9.60557L15.5528 5.10557Z" fill="white"></path>
26382
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M7.76393 15L6.55279 15.6056C6.214 15.775 6 16.1212 6 16.5C6 16.8788 6.214 17.225 6.55279 17.3944L15.5528 21.8944C15.8343 22.0352 16.1657 22.0352 16.4472 21.8944L25.4472 17.3944C25.786 17.225 26 16.8788 26 16.5C26 16.1212 25.786 15.775 25.4472 15.6056L24.2361 15L16.4472 18.8944C16.1657 19.0352 15.8343 19.0352 15.5528 18.8944L7.76393 15Z" fill="white"></path>
26383
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M7.76393 21L6.55279 21.6056C6.214 21.775 6 22.1212 6 22.5C6 22.8788 6.214 23.225 6.55279 23.3944L15.5528 27.8944C15.8343 28.0352 16.1657 28.0352 16.4472 27.8944L25.4472 23.3944C25.786 23.225 26 22.8788 26 22.5C26 22.1212 25.786 21.775 25.4472 21.6056L24.2361 21L16.4472 24.8944C16.1657 25.0352 15.8343 25.0352 15.5528 24.8944L7.76393 21Z" fill="white"></path>
26384
+ </svg>
26385
+ `, "svg");
24763
26386
  this._addPanelTab("bookmarks", "Bookmarks", `
24764
26387
  <svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
24765
26388
  <path d="M23 25V7H9V25L16 18L23 25Z" fill="white" stroke="white" stroke-linecap="round" stroke-linejoin="round"></path>
@@ -24858,18 +26481,6 @@ class WidgetLeftPanel extends Widget.AWidget {
24858
26481
  this._element.appendChild(tabButton);
24859
26482
  }
24860
26483
  }
24861
- _addPlaceholderTab(title, svgStr) {
24862
- const tabButton = document.createElement("div");
24863
- tabButton.className = "NextspaceLeftPanelButton";
24864
- tabButton.title = title;
24865
- tabButton.style.opacity = "0.5";
24866
- tabButton.style.pointerEvents = "none";
24867
- const buttonBookmarksIcon = document.createElement("div");
24868
- buttonBookmarksIcon.className = "NextspaceLeftPanelButtonIcon";
24869
- buttonBookmarksIcon.innerHTML = svgStr;
24870
- tabButton.appendChild(buttonBookmarksIcon);
24871
- this._element.appendChild(tabButton);
24872
- }
24873
26484
  /**
24874
26485
  * User profile handled separately.
24875
26486
  * This is because for a while it will be just an indicator of logged in user session.
@@ -24999,12 +26610,24 @@ class WidgetLeftPanel extends Widget.AWidget {
24999
26610
  const container = this._element.querySelector(".NextspaceLeftPanelTabContent");
25000
26611
  let tabContent;
25001
26612
  switch (this._enabledPanelTab) {
26613
+ case "dashboard":
26614
+ tabContent = new WidgetLeftPanelTabDashboard({
26615
+ widget: this,
26616
+ container: container
26617
+ });
26618
+ break;
25002
26619
  case "bookmarks":
25003
26620
  tabContent = new WidgetLeftPanelTabBookmarks({
25004
26621
  widget: this,
25005
26622
  container: container
25006
26623
  });
25007
26624
  break;
26625
+ case "menu-items":
26626
+ tabContent = new WidgetLeftPanelTabMenuItems({
26627
+ widget: this,
26628
+ container: container
26629
+ });
26630
+ break;
25008
26631
  case "user":
25009
26632
  tabContent = new WidgetLeftPanelTabUser({
25010
26633
  widget: this,
@@ -27878,29 +29501,31 @@ class WidgetBookmarks extends Widget.AWidget {
27878
29501
  }
27879
29502
 
27880
29503
  .NextspaceBookmarksRowItem {
27881
- background-color: #fff;
29504
+ background-color: rgba(255, 255, 255, .05);
27882
29505
  background-position: 50%;
27883
29506
  background-repeat: no-repeat;
27884
29507
  background-size: cover;
27885
- border-radius: 6px;
29508
+ border: 1px solid rgba(255, 255, 255, .1);
29509
+ border-radius: 8px;
27886
29510
  cursor: pointer;
27887
29511
  margin-right: 8px;
27888
29512
  min-width: 70px;
27889
- outline: 3px solid transparent;
27890
- transition: .3s ease;
29513
+ transition: border-color .3s ease, box-shadow .3s ease, transform .3s ease;
27891
29514
  width: 110px;
27892
29515
  }
27893
-
29516
+
27894
29517
  .NextspaceBookmarksRowItem:last-of-type {
27895
29518
  margin-right: 0;
27896
29519
  }
27897
29520
 
27898
29521
  .NextspaceBookmarksRowItem[is-selected="true"] {
27899
- outline: 3px solid #0072c3;
29522
+ border-color: #33b1ff;
29523
+ box-shadow: 0 0 0 2px rgba(51, 177, 255, .4);
27900
29524
  }
27901
29525
 
27902
29526
  .NextspaceBookmarksRowItem:hover {
27903
- filter: grayscale(.5);
29527
+ border-color: rgba(255, 255, 255, .4);
29528
+ transform: translateY(-2px);
27904
29529
  }
27905
29530
 
27906
29531
  .NextspaceBookmarksToolbar {
@@ -30890,6 +32515,10 @@ class WidgetInfoView extends Widget.AWidget {
30890
32515
  flex-direction: column;
30891
32516
  }
30892
32517
 
32518
+ .NextspaceAttributesGroup + .NextspaceAttributesGroup {
32519
+ margin-top: 4px;
32520
+ }
32521
+
30893
32522
  .NextspaceAttributesGroup[is-opened="false"] .NextspaceAttribute {
30894
32523
  display: none;
30895
32524
  }
@@ -30901,8 +32530,7 @@ class WidgetInfoView extends Widget.AWidget {
30901
32530
  border-radius: 5px;
30902
32531
  cursor: pointer;
30903
32532
  display: flex;
30904
- height: 35px;
30905
- margin-bottom: 3px;
32533
+ min-height: 32px;
30906
32534
  overflow: hidden;
30907
32535
  padding-left: 12px;
30908
32536
  text-overflow: ellipsis;
@@ -30913,6 +32541,11 @@ class WidgetInfoView extends Widget.AWidget {
30913
32541
  font-size: 12px;
30914
32542
  }
30915
32543
 
32544
+ .NextspaceAttributesGroup[is-opened="true"] >.NextspaceAttributesGroupToggle {
32545
+ border-bottom-left-radius: 0;
32546
+ border-bottom-right-radius: 0;
32547
+ }
32548
+
30916
32549
  .NextspaceAttributesGroupToggleIcon {
30917
32550
  align-items: center;
30918
32551
  display: flex;
@@ -30940,51 +32573,79 @@ class WidgetInfoView extends Widget.AWidget {
30940
32573
  }
30941
32574
 
30942
32575
  .NextspaceAttribute {
30943
- align-items: center;
32576
+ align-items: stretch;
30944
32577
  display: flex;
30945
32578
  flex-direction: row;
30946
32579
  flex-grow: 1;
32580
+ min-height: 32px;
30947
32581
  }
30948
32582
 
30949
32583
  .NextspaceAttributeInput {
30950
- align-items: center;
32584
+ align-items: stretch;
30951
32585
  background-color: #121619;
30952
32586
  border: 1px solid #434343;
30953
- border-radius: 5px;
32587
+ border-radius: 0;
30954
32588
  display: flex;
30955
- height: 35px;
30956
- margin-bottom: 3px;
32589
+ flex-grow: 1;
32590
+ min-height: 32px;
32591
+ position: relative;
32592
+ transition: border-color .3s ease, box-shadow .3s ease;
30957
32593
  width: 100%;
30958
32594
  }
30959
32595
 
32596
+ /* Adjacent borders would otherwise double up into a 2px rule. */
32597
+ .NextspaceAttribute + .NextspaceAttribute .NextspaceAttributeInput {
32598
+ border-top: none;
32599
+ }
32600
+
32601
+ .NextspaceAttributesGroup >.NextspaceAttribute:first-child .NextspaceAttributeInput {
32602
+ border-top-left-radius: 5px;
32603
+ border-top-right-radius: 5px;
32604
+ }
32605
+
32606
+ .NextspaceAttributesGroupToggle + .NextspaceAttribute .NextspaceAttributeInput {
32607
+ border-top: none;
32608
+ border-top-left-radius: 0;
32609
+ border-top-right-radius: 0;
32610
+ }
32611
+
32612
+ .NextspaceAttributesGroup >.NextspaceAttribute:last-of-type .NextspaceAttributeInput {
32613
+ border-bottom-left-radius: 5px;
32614
+ border-bottom-right-radius: 5px;
32615
+ }
32616
+
32617
+ /* Rows share borders, so a hovered row has to paint its ring above its neighbours. */
32618
+ .NextspaceAttributeInput:hover {
32619
+ border-color: #33b1ff;
32620
+ box-shadow: 0 0 0 1px #33b1ff;
32621
+ z-index: 1;
32622
+ }
32623
+
30960
32624
  .NextspaceAttributeInputLabel {
30961
32625
  border-right: 1px solid #434343;
30962
- flex-grow: .8;
30963
- flex-shrink: 1;
32626
+ flex: 1 1 50%;
32627
+ line-height: 16px;
30964
32628
  margin-right: 8px;
30965
32629
  overflow: hidden;
30966
- padding-left: 8px;
30967
- text-overflow: ellipsis;
30968
- white-space: nowrap;
30969
- width: 90px;
32630
+ padding: 8px;
32631
+ width: 0;
30970
32632
  font-size: 12px;
30971
32633
  }
30972
32634
 
30973
32635
  .NextspaceAttributeInputValue {
30974
- background-color: transparent;
30975
- border: 1px solid transparent;
30976
32636
  color: #fff;
30977
- flex-grow: 1;
30978
- flex-shrink: 1;
30979
- height: 100%;
30980
- padding-left: 2px;
30981
- text-align: left;
30982
- width: 120px;
30983
- cursor: default;
32637
+ display: flex;
32638
+ flex: 1 1 50%;
32639
+ line-height: 16px;
32640
+ min-height: 30px;
30984
32641
  opacity: .6;
30985
- outline: none;
30986
- padding: .5rem .75rem;
30987
- border-radius: .375rem;
32642
+ overflow: hidden;
32643
+ overflow-wrap: anywhere;
32644
+ padding: 8px 8px 8px 2px;
32645
+ text-align: left;
32646
+ white-space: pre-wrap;
32647
+ width: 0;
32648
+ word-break: break-word;
30988
32649
  font-size: 12px;
30989
32650
  }
30990
32651
 
@@ -31232,24 +32893,14 @@ class WidgetInfoView extends Widget.AWidget {
31232
32893
  groupDiv.appendChild(toggle);
31233
32894
  }
31234
32895
  for (const attr of group.attributes) {
31235
- this._generateAttr(groupDiv, type, entity, attr, group.group.Key != "ROOT");
32896
+ this._generateAttr(groupDiv, type, entity, attr);
31236
32897
  }
31237
32898
  this._summary.appendChild(groupDiv);
31238
32899
  }
31239
- _generateAttr(container, type, entity, path, nested) {
32900
+ _generateAttr(container, type, entity, path) {
31240
32901
  var _a, _b, _c;
31241
32902
  const attrDiv = document.createElement("div");
31242
32903
  attrDiv.className = "NextspaceAttribute";
31243
- if (nested) {
31244
- const nestedIconStr = `
31245
- <svg width="11" height="13" viewBox="0 0 11 13" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 1V10C1 11.1046 1.89543 12 3 12H10" stroke="#4D5358" stroke-linecap="round" stroke-linejoin="round"></path></svg>
31246
- `;
31247
- const nestedIcon = document.createElement("div");
31248
- nestedIcon.style.marginLeft = "12px";
31249
- nestedIcon.style.marginRight = "5px";
31250
- nestedIcon.innerHTML = nestedIconStr;
31251
- attrDiv.appendChild(nestedIcon);
31252
- }
31253
32904
  const typeItem = digTypeItem(path, (_b = (_a = type.DataSchema) === null || _a === void 0 ? void 0 : _a.Structure) !== null && _b !== void 0 ? _b : []);
31254
32905
  const attrType = (_c = typeItem === null || typeItem === void 0 ? void 0 : typeItem.Type) !== null && _c !== void 0 ? _c : EntityAttribute.EType.String;
31255
32906
  const input = document.createElement("div");
@@ -31257,7 +32908,8 @@ class WidgetInfoView extends Widget.AWidget {
31257
32908
  attrDiv.appendChild(input);
31258
32909
  const attrName = document.createElement("div");
31259
32910
  attrName.className = "NextspaceAttributeInputLabel";
31260
- attrName.innerText = typeItem ? typeItem.Name ? typeItem.Name : typeItem.Key : path[path.length - 1];
32911
+ attrName.textContent = typeItem ? typeItem.Name ? typeItem.Name : typeItem.Key : path[path.length - 1];
32912
+ attrName.title = attrName.textContent;
31261
32913
  input.appendChild(attrName);
31262
32914
  const value = Entity$1.GetValue({
31263
32915
  entity,
@@ -31287,9 +32939,10 @@ class WidgetInfoView extends Widget.AWidget {
31287
32939
  valueStr = value ? String(value) : "<No value>";
31288
32940
  }
31289
32941
  }
31290
- const attrValue = document.createElement("input");
32942
+ const attrValue = document.createElement("div");
31291
32943
  attrValue.className = "NextspaceAttributeInputValue";
31292
- attrValue.value = String(valueStr);
32944
+ attrValue.textContent = String(valueStr);
32945
+ attrValue.title = String(valueStr);
31293
32946
  input.appendChild(attrValue);
31294
32947
  container.appendChild(attrDiv);
31295
32948
  return attrDiv;
@@ -34795,6 +36448,54 @@ var EntityUtils;
34795
36448
  });
34796
36449
  }
34797
36450
  EntityUtils.GetPosAsync = GetPosAsync;
36451
+ // Graphics that take a heightReference, and so get a cached terrain offset from Cesium.
36452
+ const GROUND_REFERENCED_GRAPHICS = ["ellipse", "polygon", "corridor", "rectangle", "box", "cylinder", "ellipsoid"];
36453
+ const HEIGHT_REFERENCE_KEYS = ["heightReference", "extrudedHeightReference"];
36454
+ /**
36455
+ * Makes a moved graphic sample the ground again at where it now is.
36456
+ *
36457
+ * Reassigning the height references touches an observed property, so the updater discards the stale offset
36458
+ * and builds a new one against the current position.
36459
+ * @returns whether anything was refreshed.
36460
+ */
36461
+ function RefreshGroundClamping(params) {
36462
+ var _a, _b;
36463
+ const { viewer, visual } = params;
36464
+ if (!viewer || ((_a = viewer.isDestroyed) === null || _a === void 0 ? void 0 : _a.call(viewer)) || !(visual instanceof Entity)) {
36465
+ return false;
36466
+ }
36467
+ const parts = GatherEntity({ entity: visual });
36468
+ let refreshed = false;
36469
+ for (let i = 0; i < parts.length; i++) {
36470
+ const part = parts[i];
36471
+ if (!(part instanceof Entity)) {
36472
+ continue;
36473
+ }
36474
+ for (let j = 0; j < GROUND_REFERENCED_GRAPHICS.length; j++) {
36475
+ const graphic = part[GROUND_REFERENCED_GRAPHICS[j]];
36476
+ if (!graphic) {
36477
+ continue;
36478
+ }
36479
+ for (let k = 0; k < HEIGHT_REFERENCE_KEYS.length; k++) {
36480
+ const key = HEIGHT_REFERENCE_KEYS[k];
36481
+ const current = GetValue$1(viewer, graphic[key]);
36482
+ // Nothing to resample for a graphic that does not follow the ground.
36483
+ if (current == null || current === HeightReference.NONE) {
36484
+ continue;
36485
+ }
36486
+ // A new property instance rather than the same value written back, since an equal value would
36487
+ // be dropped as a no-op and the updater would never hear about it.
36488
+ graphic[key] = new ConstantProperty(current);
36489
+ refreshed = true;
36490
+ }
36491
+ }
36492
+ }
36493
+ if (refreshed) {
36494
+ (_b = viewer.scene) === null || _b === void 0 ? void 0 : _b.requestRender();
36495
+ }
36496
+ return refreshed;
36497
+ }
36498
+ EntityUtils.RefreshGroundClamping = RefreshGroundClamping;
34798
36499
  /**
34799
36500
  * Returns entity and any associated parent/sibling entities as a flat array.
34800
36501
  * @param entity
@@ -34985,7 +36686,9 @@ var EntityUtils;
34985
36686
  viewer: params.viewer,
34986
36687
  createIfMissing: true
34987
36688
  });
34988
- const location = await EntityUtils.GetLocation({
36689
+ // A tileset-only fly-to has no entities to sample from, so there's nothing to resolve here.
36690
+ // The tileset's own bounding sphere is used further down instead.
36691
+ const location = (entityIds === null || entityIds === void 0 ? void 0 : entityIds.length) ? await EntityUtils.GetLocation({
34989
36692
  samples: entityIds.map((id) => ({
34990
36693
  entityId: id,
34991
36694
  entity: entityLookup.get(id),
@@ -34996,7 +36699,7 @@ var EntityUtils;
34996
36699
  visualRegister: manager.VisualsRegister,
34997
36700
  minimumAlt: params.minimumAlt,
34998
36701
  api: manager.Getters.GetBruceApi()
34999
- });
36702
+ }) : null;
35000
36703
  if (params.isCancelled && params.isCancelled()) {
35001
36704
  return;
35002
36705
  }
@@ -40502,7 +42205,7 @@ var StyleUtils;
40502
42205
  StyleUtils.ApplyTypeStyle = ApplyTypeStyle;
40503
42206
  })(StyleUtils || (StyleUtils = {}));
40504
42207
 
40505
- const VERSION = "7.0.9";
42208
+ const VERSION = "7.1.1";
40506
42209
  /**
40507
42210
  * Updates the environment instance used by bruce-cesium to one specified.
40508
42211
  * This can be used to ensure that the instance a parent is referencing is shared between bruce-cesium, bruce-models, and the parent app.
@@ -40519,5 +42222,5 @@ const getENVIRONMENT = () => {
40519
42222
  return ENVIRONMENT;
40520
42223
  };
40521
42224
 
40522
- export { VERSION, setENVIRONMENT, getENVIRONMENT, CesiumAnimatedInOut, CesiumAnimatedProperty, isStyleChanged, isOutlineChanged$1 as isOutlineChanged, StyleEffective, EntityRenderEngine, EntityRenderEngineModel3d, EntityRenderEnginePoint, EntityRenderEnginePolygon, EntityRenderEnginePolyline, MenuItemCreator, MenuItemManager, CesiumParabola, EntityLabel, LiveCursor, SharedGetters, DataSourceStaticKmlManager, DataLabRenderManager, EntitiesIdsRenderManager, EntitiesLoadedRenderManager, EntitiesRenderManager, EntityRenderManager, AssemblyRenderManager, GoogleSearchRenderManager, RelationsRenderManager, RenderManager, TilesetArbRenderManager, TilesetCadRenderManager, TilesetEntitiesRenderManager, TilesetGooglePhotosRenderManager, TilesetOsmRenderManager, TilesetPointcloudRenderManager, TileRenderEngine, createTileset, TilesetRenderEngine, ViewRenderEngine, VisualRegisterCuller, VisualsRegister, XGridsRenderEngine, CesiumEntityStyler, DrawingUtils, EntityUtils, MeasureUtils, StyleUtils, CESIUM_INSPECTOR_KEY, CESIUM_TIMELINE_KEY, CESIUM_TIMELINE_LIVE_KEY, CESIUM_TIMELINE_LIVE_PADDING_KEY, CESIUM_TIMELINE_INTERVAL_KEY, CESIUM_MODEL_SPACE_KEY, DEFAULT_LIVE_PADDING_SECONDS, ViewUtils, CesiumViewMonitor, ViewGroundArea, ViewerEventTracker, ViewerUtils, Draw3dPolygon, Draw3dPolyline, MeasureCreator, Walkthrough, WidgetControlViewBar, WidgetControlViewBarSearch, WidgetLeftPanelTab, WidgetLeftPanelTabBookmarks, Widget, VIEWER_BOOKMARKS_WIDGET_KEY, WidgetBookmarks, WidgetBranding, WidgetCursorBar, WidgetEmbeddedInfoView, WidgetInfoView, VIEWER_LEFT_PANEL_WIDGET_KEY, VIEWER_LEFT_PANEL_CSS_VAR_LEFT, WidgetLeftPanel, WidgetNavCompass$$1 as WidgetNavCompass, VIEWER_VIEW_BAR_WIDGET_KEY, WidgetViewBar };
42225
+ export { VERSION, setENVIRONMENT, getENVIRONMENT, CesiumAnimatedInOut, CesiumAnimatedProperty, isStyleChanged, isOutlineChanged$1 as isOutlineChanged, StyleEffective, EntityRenderEngine, EntityRenderEngineModel3d, EntityRenderEnginePoint, EntityRenderEnginePolygon, EntityRenderEnginePolyline, MenuItemCreator, MenuItemManager, CesiumParabola, EntityLabel, LiveCursor, SharedGetters, DataSourceStaticKmlManager, DataLabRenderManager, EntitiesIdsRenderManager, EntitiesLoadedRenderManager, EntitiesRenderManager, EntityRenderManager, AssemblyRenderManager, GoogleSearchRenderManager, RelationsRenderManager, RenderManager, TilesetArbRenderManager, TilesetCadRenderManager, TilesetEntitiesRenderManager, TilesetGooglePhotosRenderManager, TilesetOsmRenderManager, TilesetPointcloudRenderManager, TileRenderEngine, createTileset, TilesetRenderEngine, ViewRenderEngine, VisualRegisterCuller, VisualsRegister, XGridsRenderEngine, CesiumEntityStyler, DrawingUtils, EntityUtils, MeasureUtils, StyleUtils, CESIUM_INSPECTOR_KEY, CESIUM_TIMELINE_KEY, CESIUM_TIMELINE_LIVE_KEY, CESIUM_TIMELINE_LIVE_PADDING_KEY, CESIUM_TIMELINE_INTERVAL_KEY, CESIUM_MODEL_SPACE_KEY, DEFAULT_LIVE_PADDING_SECONDS, ViewUtils, CesiumViewMonitor, ViewGroundArea, ViewerEventTracker, ViewerUtils, Draw3dPolygon, Draw3dPolyline, MeasureCreator, Walkthrough, WidgetControlViewBar, WidgetControlViewBarSearch, WidgetLeftPanelTab, WidgetLeftPanelTabBookmarks, WidgetLeftPanelTabDashboard, EMenuItemState, WidgetLeftPanelTabMenuItems, Widget, VIEWER_BOOKMARKS_WIDGET_KEY, WidgetBookmarks, WidgetBranding, WidgetCursorBar, WidgetEmbeddedInfoView, WidgetInfoView, VIEWER_LEFT_PANEL_WIDGET_KEY, VIEWER_LEFT_PANEL_CSS_VAR_LEFT, WidgetLeftPanel, WidgetNavCompass$$1 as WidgetNavCompass, VIEWER_VIEW_BAR_WIDGET_KEY, WidgetViewBar };
40523
42226
  //# sourceMappingURL=bruce-cesium.es5.js.map