@deck.gl/widgets 9.3.0-alpha.1 → 9.3.0-alpha.2

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 (89) hide show
  1. package/dist/context-menu-widget.d.ts +7 -5
  2. package/dist/context-menu-widget.d.ts.map +1 -1
  3. package/dist/context-menu-widget.js +2 -1
  4. package/dist/context-menu-widget.js.map +1 -1
  5. package/dist/dist.dev.js +687 -555
  6. package/dist/icon-widget.d.ts +28 -0
  7. package/dist/icon-widget.d.ts.map +1 -0
  8. package/dist/icon-widget.js +35 -0
  9. package/dist/icon-widget.js.map +1 -0
  10. package/dist/index.cjs +468 -309
  11. package/dist/index.cjs.map +4 -4
  12. package/dist/index.d.ts +11 -9
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +7 -7
  15. package/dist/index.js.map +1 -1
  16. package/dist/info-widget.d.ts +1 -0
  17. package/dist/info-widget.d.ts.map +1 -1
  18. package/dist/info-widget.js +6 -0
  19. package/dist/info-widget.js.map +1 -1
  20. package/dist/lib/components/dropdown-menu.d.ts +3 -2
  21. package/dist/lib/components/dropdown-menu.d.ts.map +1 -1
  22. package/dist/lib/components/dropdown-menu.js +12 -8
  23. package/dist/lib/components/dropdown-menu.js.map +1 -1
  24. package/dist/lib/components/icon-button.d.ts +3 -0
  25. package/dist/lib/components/icon-button.d.ts.map +1 -1
  26. package/dist/lib/components/icon-button.js +10 -2
  27. package/dist/lib/components/icon-button.js.map +1 -1
  28. package/dist/lib/components/popover.js +1 -1
  29. package/dist/lib/components/popover.js.map +1 -1
  30. package/dist/lib/data-url.d.ts +5 -0
  31. package/dist/lib/data-url.d.ts.map +1 -0
  32. package/dist/lib/data-url.js +7 -0
  33. package/dist/lib/data-url.js.map +1 -0
  34. package/dist/popup-widget.d.ts +1 -0
  35. package/dist/popup-widget.d.ts.map +1 -1
  36. package/dist/popup-widget.js +6 -0
  37. package/dist/popup-widget.js.map +1 -1
  38. package/dist/selector-widget.d.ts +44 -0
  39. package/dist/selector-widget.d.ts.map +1 -0
  40. package/dist/selector-widget.js +64 -0
  41. package/dist/selector-widget.js.map +1 -0
  42. package/dist/splitter-widget.d.ts +52 -11
  43. package/dist/splitter-widget.d.ts.map +1 -1
  44. package/dist/splitter-widget.js +177 -76
  45. package/dist/splitter-widget.js.map +1 -1
  46. package/dist/stats-widget.d.ts +2 -1
  47. package/dist/stats-widget.d.ts.map +1 -1
  48. package/dist/stats-widget.js +37 -8
  49. package/dist/stats-widget.js.map +1 -1
  50. package/dist/stylesheet.css +50 -13
  51. package/dist/timeline-widget.d.ts.map +1 -1
  52. package/dist/timeline-widget.js +6 -1
  53. package/dist/timeline-widget.js.map +1 -1
  54. package/dist/toggle-widget.d.ts +38 -0
  55. package/dist/toggle-widget.d.ts.map +1 -0
  56. package/dist/toggle-widget.js +47 -0
  57. package/dist/toggle-widget.js.map +1 -0
  58. package/dist.min.js +2 -2
  59. package/package.json +3 -3
  60. package/src/context-menu-widget.tsx +9 -9
  61. package/src/icon-widget.tsx +69 -0
  62. package/src/index.ts +11 -9
  63. package/src/info-widget.tsx +7 -0
  64. package/src/lib/components/dropdown-menu.tsx +22 -15
  65. package/src/lib/components/icon-button.tsx +15 -3
  66. package/src/lib/components/popover.tsx +1 -1
  67. package/src/lib/data-url.ts +5 -0
  68. package/src/popup-widget.tsx +7 -0
  69. package/src/selector-widget.tsx +111 -0
  70. package/src/splitter-widget.tsx +281 -96
  71. package/src/stats-widget.tsx +50 -9
  72. package/src/stylesheet.css +50 -13
  73. package/src/timeline-widget.tsx +8 -1
  74. package/src/toggle-widget.tsx +101 -0
  75. package/dist/fps-widget.d.ts +0 -28
  76. package/dist/fps-widget.d.ts.map +0 -1
  77. package/dist/fps-widget.js +0 -51
  78. package/dist/fps-widget.js.map +0 -1
  79. package/dist/lib/components/icon-menu.d.ts +0 -16
  80. package/dist/lib/components/icon-menu.d.ts.map +0 -1
  81. package/dist/lib/components/icon-menu.js +0 -33
  82. package/dist/lib/components/icon-menu.js.map +0 -1
  83. package/dist/view-selector-widget.d.ts +0 -35
  84. package/dist/view-selector-widget.d.ts.map +0 -1
  85. package/dist/view-selector-widget.js +0 -63
  86. package/dist/view-selector-widget.js.map +0 -1
  87. package/src/fps-widget.tsx +0 -77
  88. package/src/lib/components/icon-menu.tsx +0 -70
  89. package/src/view-selector-widget.tsx +0 -151
package/dist/index.cjs CHANGED
@@ -21,29 +21,31 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var dist_exports = {};
22
22
  __export(dist_exports, {
23
23
  CompassWidget: () => CompassWidget,
24
+ ContextMenuWidget: () => ContextMenuWidget,
24
25
  DarkGlassTheme: () => DarkGlassTheme,
25
26
  DarkTheme: () => DarkTheme,
26
27
  FullscreenWidget: () => FullscreenWidget,
27
28
  GimbalWidget: () => GimbalWidget,
29
+ IconWidget: () => IconWidget,
30
+ InfoWidget: () => InfoWidget,
28
31
  LightGlassTheme: () => LightGlassTheme,
29
32
  LightTheme: () => LightTheme,
33
+ LoadingWidget: () => LoadingWidget,
30
34
  PopupWidget: () => PopupWidget,
31
35
  ResetViewWidget: () => ResetViewWidget,
32
36
  ScreenshotWidget: () => ScreenshotWidget,
33
37
  ScrollbarWidget: () => ScrollbarWidget,
38
+ SelectorWidget: () => SelectorWidget,
39
+ ThemeWidget: () => ThemeWidget,
40
+ ToggleWidget: () => ToggleWidget,
34
41
  ZoomWidget: () => ZoomWidget,
35
42
  _ButtonGroup: () => ButtonGroup,
36
- _ContextMenuWidget: () => ContextMenuWidget,
37
43
  _CoordinatesGeocoder: () => CoordinatesGeocoder,
38
44
  _CurrentLocationGeocoder: () => CurrentLocationGeocoder,
39
45
  _DropdownMenu: () => DropdownMenu,
40
- _FpsWidget: () => FpsWidget,
41
46
  _GeocoderWidget: () => GeocoderWidget,
42
47
  _GoogleGeocoder: () => GoogleGeocoder,
43
48
  _IconButton: () => IconButton,
44
- _IconMenu: () => IconMenu,
45
- _InfoWidget: () => InfoWidget,
46
- _LoadingWidget: () => LoadingWidget,
47
49
  _MapboxGeocoder: () => MapboxGeocoder,
48
50
  _OpenCageGeocoder: () => OpenCageGeocoder,
49
51
  _RangeInput: () => RangeInput,
@@ -51,9 +53,7 @@ __export(dist_exports, {
51
53
  _SimpleMenu: () => SimpleMenu,
52
54
  _SplitterWidget: () => SplitterWidget,
53
55
  _StatsWidget: () => StatsWidget,
54
- _ThemeWidget: () => ThemeWidget,
55
- _TimelineWidget: () => TimelineWidget,
56
- _ViewSelectorWidget: () => ViewSelectorWidget
56
+ _TimelineWidget: () => TimelineWidget
57
57
  });
58
58
  module.exports = __toCommonJS(dist_exports);
59
59
 
@@ -71,9 +71,26 @@ var ButtonGroup = (props) => {
71
71
 
72
72
  // dist/lib/components/icon-button.js
73
73
  var import_jsx_runtime2 = require("preact/jsx-runtime");
74
+ var import_hooks = require("preact/hooks");
75
+
76
+ // dist/lib/data-url.js
77
+ function getCSSMask(imageUrl) {
78
+ if (!imageUrl)
79
+ return void 0;
80
+ const cssUrl = `url("${imageUrl.replace(/"/g, `'`)}")`;
81
+ return { maskImage: cssUrl, WebkitMaskImage: cssUrl };
82
+ }
83
+
84
+ // dist/lib/components/icon-button.js
74
85
  var IconButton = (props) => {
75
- const { className = "", label, onClick, children } = props;
76
- return (0, import_jsx_runtime2.jsx)("div", { className: "deck-widget-button", children: (0, import_jsx_runtime2.jsx)("button", { className: `deck-widget-icon-button ${className}`, type: "button", onClick, title: label, children: children ? children : (0, import_jsx_runtime2.jsx)("div", { className: "deck-widget-icon" }) }) });
86
+ const { className = "", style, color, icon, label, onClick, children } = props;
87
+ const iconStyle = (0, import_hooks.useMemo)(() => {
88
+ const css = getCSSMask(icon);
89
+ if (!color)
90
+ return css;
91
+ return { ...css, backgroundColor: color };
92
+ }, [color, icon]);
93
+ return (0, import_jsx_runtime2.jsx)("div", { className: "deck-widget-button", style, children: (0, import_jsx_runtime2.jsx)("button", { className: `deck-widget-icon-button ${className}`, type: "button", onClick, title: label, children: children ? children : (0, import_jsx_runtime2.jsx)("div", { className: "deck-widget-icon", style: iconStyle }) }) });
77
94
  };
78
95
 
79
96
  // dist/zoom-widget.js
@@ -448,7 +465,7 @@ var import_preact6 = require("preact");
448
465
 
449
466
  // dist/lib/components/dropdown-menu.js
450
467
  var import_jsx_runtime8 = require("preact/jsx-runtime");
451
- var import_hooks = require("preact/hooks");
468
+ var import_hooks2 = require("preact/hooks");
452
469
  function getMenuItemValue(item) {
453
470
  return typeof item === "string" ? item : item.value;
454
471
  }
@@ -459,25 +476,29 @@ function getMenuItemIcon(item) {
459
476
  return typeof item === "string" ? void 0 : item.icon;
460
477
  }
461
478
  var DropdownMenu = (props) => {
462
- const [isOpen, setIsOpen] = (0, import_hooks.useState)(false);
479
+ const [isOpen, setIsOpen] = (0, import_hooks2.useState)(false);
463
480
  return (0, import_jsx_runtime8.jsx)(SimpleMenu, { ...props, style: { ...props.style, position: "absolute" }, isOpen, onClose: () => setIsOpen(false), trigger: (0, import_jsx_runtime8.jsx)("button", { className: "deck-widget-dropdown-button", onClick: () => setIsOpen(!isOpen), children: (0, import_jsx_runtime8.jsx)("span", { className: `deck-widget-dropdown-icon ${isOpen ? "open" : ""}` }) }) });
464
481
  };
465
482
  var SimpleMenu = (props) => {
466
- const dropdownRef = (0, import_hooks.useRef)(null);
467
- const handleClickOutside = (event) => {
468
- if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
469
- props.onClose();
470
- }
471
- };
472
- (0, import_hooks.useEffect)(() => {
483
+ const dropdownRef = (0, import_hooks2.useRef)(null);
484
+ (0, import_hooks2.useEffect)(() => {
485
+ const handleClickOutside = (event) => {
486
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
487
+ props.onClose();
488
+ }
489
+ };
473
490
  document.addEventListener("mousedown", handleClickOutside);
474
491
  return () => {
475
492
  document.removeEventListener("mousedown", handleClickOutside);
476
493
  };
477
494
  }, []);
478
- const handleSelect = (value) => {
495
+ const handleSelect = (value, item) => {
496
+ var _a, _b;
479
497
  if (value) {
480
- props.onSelect(value);
498
+ if (typeof item === "object") {
499
+ (_a = item.onSelect) == null ? void 0 : _a.call(item);
500
+ }
501
+ (_b = props.onSelect) == null ? void 0 : _b.call(props, value);
481
502
  props.onClose();
482
503
  }
483
504
  };
@@ -487,7 +508,7 @@ var SimpleMenu = (props) => {
487
508
  return (0, import_jsx_runtime8.jsxs)("div", { className: "deck-widget-dropdown-container", ref: dropdownRef, children: [props.trigger, props.isOpen && (0, import_jsx_runtime8.jsx)("ul", { className: "deck-widget-dropdown-menu", style: props.style, children: props.menuItems.map((item, i) => {
488
509
  const value = getMenuItemValue(item);
489
510
  const icon = getMenuItemIcon(item);
490
- return (0, import_jsx_runtime8.jsxs)("li", { className: `deck-widget-dropdown-item ${value ? "" : "disabled"}`, onClick: () => handleSelect(value), children: [icon && (0, import_jsx_runtime8.jsx)("span", { className: "deck-widget-dropdown-item-icon", style: { maskImage: `url("${icon}")`, WebkitMaskImage: `url("${icon}")` } }), getMenuItemLabel(item)] }, i);
511
+ return (0, import_jsx_runtime8.jsxs)("li", { className: `deck-widget-dropdown-item ${value ? "" : "disabled"}`, onClick: () => handleSelect(value, item), children: [icon && (0, import_jsx_runtime8.jsx)("span", { className: "deck-widget-dropdown-item-icon", style: getCSSMask(icon) }), getMenuItemLabel(item)] }, i);
491
512
  }) })] });
492
513
  };
493
514
 
@@ -899,34 +920,146 @@ FullscreenWidget.defaultProps = {
899
920
  // dist/splitter-widget.js
900
921
  var import_jsx_runtime11 = require("preact/jsx-runtime");
901
922
  var import_preact8 = require("preact");
902
- var import_hooks2 = require("preact/hooks");
923
+ var import_hooks3 = require("preact/hooks");
903
924
  var import_core9 = require("@deck.gl/core");
925
+ function parseViewLayout(root) {
926
+ const layoutsById = [];
927
+ const isViewLayout = (v) => "views" in v;
928
+ function createManagedViewLayout(l) {
929
+ const id = layoutsById.length;
930
+ const minSplit = l.minSplit ?? 0.05;
931
+ const maxSplit = l.maxSplit ?? 0.95;
932
+ const split = Math.min(Math.max(l.initialSplit ?? 0.5, minSplit), maxSplit);
933
+ const managed = {
934
+ id,
935
+ orientation: l.orientation,
936
+ views: l.views,
937
+ split,
938
+ editable: l.editable ?? true,
939
+ minSplit,
940
+ maxSplit,
941
+ x: 0,
942
+ y: 0,
943
+ width: 0,
944
+ height: 0
945
+ };
946
+ layoutsById.push(managed);
947
+ managed.views = [
948
+ isViewLayout(l.views[0]) ? createManagedViewLayout(l.views[0]) : l.views[0],
949
+ isViewLayout(l.views[1]) ? createManagedViewLayout(l.views[1]) : l.views[1]
950
+ ];
951
+ return managed;
952
+ }
953
+ createManagedViewLayout(root);
954
+ return layoutsById;
955
+ }
956
+ function evaluateViews(root) {
957
+ const views = [];
958
+ function evaluateViewLayout(l, x, y, width, height) {
959
+ l.x = x;
960
+ l.y = y;
961
+ l.width = width;
962
+ l.height = height;
963
+ const child1X = x;
964
+ const child1Y = y;
965
+ let child1Width = width;
966
+ let child1Height = height;
967
+ let child2X = x;
968
+ let child2Y = y;
969
+ let child2Width = width;
970
+ let child2Height = height;
971
+ if (l.orientation === "horizontal") {
972
+ child1Width = width * l.split;
973
+ child2X = x + child1Width;
974
+ child2Width = width - child1Width;
975
+ } else {
976
+ child1Height = height * l.split;
977
+ child2Y = y + child1Height;
978
+ child2Height = height - child1Height;
979
+ }
980
+ const [view1, view2] = l.views;
981
+ if ("views" in view1) {
982
+ evaluateViewLayout(view1, child1X, child1Y, child1Width, child1Height);
983
+ } else {
984
+ views.push(view1.clone({
985
+ x: `${child1X}%`,
986
+ y: `${child1Y}%`,
987
+ width: `${child1Width}%`,
988
+ height: `${child1Height}%`
989
+ }));
990
+ }
991
+ if ("views" in view2) {
992
+ evaluateViewLayout(view2, child2X, child2Y, child2Width, child2Height);
993
+ } else {
994
+ views.push(view2.clone({
995
+ x: `${child2X}%`,
996
+ y: `${child2Y}%`,
997
+ width: `${child2Width}%`,
998
+ height: `${child2Height}%`
999
+ }));
1000
+ }
1001
+ }
1002
+ evaluateViewLayout(root, 0, 0, 100, 100);
1003
+ return views;
1004
+ }
904
1005
  var SplitterWidget = class extends import_core9.Widget {
905
1006
  constructor(props) {
906
1007
  super(props);
907
1008
  this.className = "deck-widget-splitter";
908
1009
  this.placement = "fill";
1010
+ this.needsUpdate = true;
1011
+ this.viewLayouts = parseViewLayout(this.props.viewLayout);
909
1012
  }
910
1013
  setProps(props) {
1014
+ if (props.viewLayout && !(0, import_core9._deepEqual)(props.viewLayout, this.props.viewLayout, -1)) {
1015
+ this.viewLayouts = parseViewLayout(props.viewLayout);
1016
+ this.views = void 0;
1017
+ }
911
1018
  super.setProps(props);
912
1019
  }
1020
+ onRedraw() {
1021
+ super.updateHTML();
1022
+ }
1023
+ // Usually widgets rerender their DOM elements here
1024
+ // In this case we need the widget UI to synchronize with deck view states
1025
+ // so we update deck props here and rerender DOM in the next onRedraw
1026
+ updateHTML() {
1027
+ if (!this.views) {
1028
+ this.views = evaluateViews(this.viewLayouts[0]);
1029
+ this.props.onChange(this.views.slice());
1030
+ }
1031
+ requestAnimationFrame(() => {
1032
+ this.doUpdate();
1033
+ });
1034
+ }
1035
+ doUpdate() {
1036
+ if (this.deck) {
1037
+ const deckViews = this.deck.props.views;
1038
+ const isManagedExternally = (
1039
+ // is not empty
1040
+ deckViews && // is not set by us
1041
+ deckViews !== this.lastViews
1042
+ );
1043
+ if (!isManagedExternally && this.lastViews !== this.views) {
1044
+ this.lastViews = this.views;
1045
+ this.deck.setProps({ views: this.views });
1046
+ }
1047
+ }
1048
+ }
1049
+ onChange(newSplit, layout) {
1050
+ layout.split = newSplit;
1051
+ this.views = evaluateViews(this.viewLayouts[0]);
1052
+ this.props.onChange(this.views.slice());
1053
+ this.doUpdate();
1054
+ }
913
1055
  onRenderHTML(rootElement) {
914
- rootElement.style.position = "absolute";
915
- rootElement.style.top = "0";
916
- rootElement.style.left = "0";
917
- rootElement.style.width = "100%";
918
- rootElement.style.height = "100%";
919
- rootElement.style.margin = "0px";
920
- (0, import_preact8.render)((0, import_jsx_runtime11.jsx)(Splitter, { orientation: this.props.orientation, initialSplit: this.props.initialSplit, onChange: this.props.onChange, onDragStart: this.props.onDragStart, onDragEnd: this.props.onDragEnd }), rootElement);
1056
+ (0, import_preact8.render)((0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, { children: this.viewLayouts.map((layout) => layout.editable && (0, import_jsx_runtime11.jsx)(Splitter, { ...layout, onChange: (newSplit) => this.onChange(newSplit, layout), onDragStart: () => this.props.onDragStart(), onDragEnd: () => this.props.onDragStart() })) }), rootElement);
921
1057
  }
922
1058
  };
923
1059
  SplitterWidget.defaultProps = {
924
1060
  ...import_core9.Widget.defaultProps,
925
1061
  id: "splitter-widget",
926
- viewId1: "",
927
- viewId2: "",
928
- orientation: "vertical",
929
- initialSplit: 0.5,
1062
+ viewLayout: void 0,
930
1063
  onChange: () => {
931
1064
  },
932
1065
  onDragStart: () => {
@@ -934,162 +1067,62 @@ SplitterWidget.defaultProps = {
934
1067
  onDragEnd: () => {
935
1068
  }
936
1069
  };
937
- function Splitter({ orientation, initialSplit, onChange, onDragStart, onDragEnd }) {
938
- const [split, setSplit] = (0, import_hooks2.useState)(initialSplit);
939
- const dragging = (0, import_hooks2.useRef)(false);
940
- const containerRef = (0, import_hooks2.useRef)(null);
1070
+ function Splitter({ orientation, x, y, width, height, split, minSplit, maxSplit, onChange, onDragStart, onDragEnd }) {
1071
+ const [dragging, setDragging] = (0, import_hooks3.useState)(false);
1072
+ const containerRef = (0, import_hooks3.useRef)(null);
1073
+ (0, import_hooks3.useEffect)(() => {
1074
+ if (!dragging) {
1075
+ return void 0;
1076
+ }
1077
+ const handleDragging = (event) => {
1078
+ if (!containerRef.current)
1079
+ return;
1080
+ const rect = containerRef.current.getBoundingClientRect();
1081
+ let newSplit;
1082
+ if (orientation === "horizontal") {
1083
+ newSplit = (event.clientX - rect.left) / rect.width;
1084
+ } else {
1085
+ newSplit = (event.clientY - rect.top) / rect.height;
1086
+ }
1087
+ newSplit = Math.min(Math.max(newSplit, minSplit), maxSplit);
1088
+ onChange == null ? void 0 : onChange(newSplit);
1089
+ };
1090
+ const handleDragEnd = () => {
1091
+ onDragEnd == null ? void 0 : onDragEnd();
1092
+ setDragging(false);
1093
+ };
1094
+ document.addEventListener("pointermove", handleDragging);
1095
+ document.addEventListener("pointerup", handleDragEnd);
1096
+ document.addEventListener("pointerleave", handleDragEnd);
1097
+ return () => {
1098
+ document.removeEventListener("pointermove", handleDragging);
1099
+ document.removeEventListener("pointerup", handleDragEnd);
1100
+ document.removeEventListener("pointerleave", handleDragEnd);
1101
+ };
1102
+ }, [dragging]);
941
1103
  const handleDragStart = (event) => {
942
- dragging.current = true;
1104
+ setDragging(true);
943
1105
  onDragStart == null ? void 0 : onDragStart();
944
- document.addEventListener("mousemove", handleDragging);
945
- document.addEventListener("mouseup", handleDragEnd);
946
1106
  event.preventDefault();
947
1107
  };
948
- const handleDragging = (event) => {
949
- if (!dragging.current || !containerRef.current)
950
- return;
951
- const rect = containerRef.current.getBoundingClientRect();
952
- let newSplit;
953
- if (orientation === "vertical") {
954
- newSplit = (event.clientX - rect.left) / rect.width;
955
- } else {
956
- newSplit = (event.clientY - rect.top) / rect.height;
957
- }
958
- newSplit = Math.min(Math.max(newSplit, 0.05), 0.95);
959
- setSplit(newSplit);
960
- onChange == null ? void 0 : onChange(newSplit);
961
- };
962
- const handleDragEnd = (event) => {
963
- if (!dragging.current)
964
- return;
965
- dragging.current = false;
966
- onDragEnd == null ? void 0 : onDragEnd();
967
- document.removeEventListener("mousemove", handleDragging);
968
- document.removeEventListener("mouseup", handleDragEnd);
969
- };
970
- const splitterStyle = orientation === "vertical" ? {
971
- position: "absolute",
972
- top: 0,
973
- bottom: 0,
974
- left: `${split * 100}%`,
975
- width: "4px",
976
- cursor: "col-resize",
977
- background: "#ccc",
978
- zIndex: 10,
979
- pointerEvents: "auto",
980
- boxShadow: "inset -1px 0 0 white, inset 1px 0 0 white"
981
- } : {
982
- position: "absolute",
983
- left: 0,
984
- right: 0,
985
- top: `${split * 100}%`,
986
- height: "4px",
987
- cursor: "row-resize",
988
- background: "#ccc",
989
- zIndex: 10,
990
- pointerEvents: "auto",
991
- boxShadow: "inset -1px 0 0 white, inset 1px 0 0 white"
992
- };
1108
+ const splitterStyle = orientation === "horizontal" ? { left: `${split * 100}%` } : { top: `${split * 100}%` };
993
1109
  const containerStyle = {
994
1110
  position: "absolute",
995
- top: 0,
996
- left: 0,
997
- right: 0,
998
- bottom: 0
1111
+ top: `${y}%`,
1112
+ left: `${x}%`,
1113
+ width: `${width}%`,
1114
+ height: `${height}%`
999
1115
  };
1000
- return (0, import_jsx_runtime11.jsx)("div", { ref: containerRef, style: containerStyle, children: (0, import_jsx_runtime11.jsx)("div", { style: splitterStyle, onMouseDown: handleDragStart }) });
1116
+ return (0, import_jsx_runtime11.jsx)("div", { ref: containerRef, style: containerStyle, children: (0, import_jsx_runtime11.jsx)("div", { className: `deck-widget-splitter-handle deck-widget-splitter-handle--${orientation} ${dragging ? "active" : ""}`, style: splitterStyle, onPointerDown: handleDragStart }) });
1001
1117
  }
1002
1118
 
1003
- // dist/view-selector-widget.js
1004
- var import_jsx_runtime13 = require("preact/jsx-runtime");
1005
- var import_preact9 = require("preact");
1006
- var import_core10 = require("@deck.gl/core");
1007
-
1008
- // dist/lib/components/icon-menu.js
1009
- var import_jsx_runtime12 = require("preact/jsx-runtime");
1010
- var import_hooks3 = require("preact/hooks");
1011
- function IconMenu(props) {
1012
- const [menuOpen, setMenuOpen] = (0, import_hooks3.useState)(false);
1013
- const containerRef = (0, import_hooks3.useRef)(null);
1014
- const handleClickOutside = (event) => {
1015
- if (containerRef.current && !containerRef.current.contains(event.target)) {
1016
- setMenuOpen(false);
1017
- }
1018
- };
1019
- (0, import_hooks3.useEffect)(() => {
1020
- document.addEventListener("mousedown", handleClickOutside);
1021
- return () => {
1022
- document.removeEventListener("mousedown", handleClickOutside);
1023
- };
1024
- }, [containerRef]);
1025
- const [selectedItem, setSelectedItem] = (0, import_hooks3.useState)(props.initialItem);
1026
- const handleSelectItem = (item) => {
1027
- setSelectedItem(item);
1028
- setMenuOpen(false);
1029
- props.onItemSelected(item);
1030
- };
1031
- const handleButtonClick = () => setMenuOpen(!menuOpen);
1032
- const selectedMenuItem = props.menuItems.find((item) => item.value === selectedItem);
1033
- const label = props.label || (selectedMenuItem == null ? void 0 : selectedMenuItem.label) || "";
1034
- const icon = props.icon || (selectedMenuItem == null ? void 0 : selectedMenuItem.icon);
1035
- return (0, import_jsx_runtime12.jsxs)("div", { style: { position: "relative", display: "inline-block" }, ref: containerRef, children: [(0, import_jsx_runtime12.jsx)(IconButton, { className: props.className, label, onClick: handleButtonClick, children: icon }), menuOpen && (0, import_jsx_runtime12.jsx)("div", { className: "deck-widget-icon-menu", children: (0, import_jsx_runtime12.jsx)(ButtonGroup, { orientation: "vertical", children: props.menuItems.map((item) => (0, import_jsx_runtime12.jsx)(IconButton, { label: item.label, onClick: () => handleSelectItem(item.value), children: item.icon }, item.value)) }) })] });
1036
- }
1037
-
1038
- // dist/view-selector-widget.js
1039
- var ViewSelectorWidget = class extends import_core10.Widget {
1040
- constructor(props = {}) {
1041
- super(props);
1042
- this.className = "deck-widget-view-selector";
1043
- this.placement = "top-left";
1044
- this.handleSelectMode = (viewMode) => {
1045
- this.viewMode = viewMode;
1046
- this.updateHTML();
1047
- this.props.onViewModeChange(viewMode);
1048
- };
1049
- this.viewMode = this.props.initialViewMode;
1050
- this.setProps(this.props);
1051
- }
1052
- setProps(props) {
1053
- this.placement = props.placement ?? this.placement;
1054
- this.viewId = props.viewId ?? this.viewId;
1055
- super.setProps(props);
1056
- }
1057
- onRenderHTML(rootElement) {
1058
- (0, import_preact9.render)((0, import_jsx_runtime13.jsx)(IconMenu, { className: "deck-widget-view-selector", menuItems: MENU_ITEMS.map((item) => ({
1059
- ...item,
1060
- icon: item.icon()
1061
- })), initialItem: this.props.initialViewMode, onItemSelected: this.handleSelectMode }), rootElement);
1062
- }
1063
- };
1064
- ViewSelectorWidget.defaultProps = {
1065
- ...import_core10.Widget.defaultProps,
1066
- id: "view-selector",
1067
- placement: "top-left",
1068
- viewId: null,
1069
- label: "Split View",
1070
- initialViewMode: "single",
1071
- onViewModeChange: () => {
1072
- }
1073
- };
1074
- var ICON_STYLE = { width: "24px", height: "24px" };
1075
- var ICONS = {
1076
- single: () => (0, import_jsx_runtime13.jsx)("svg", { width: "24", height: "24", style: ICON_STYLE, children: (0, import_jsx_runtime13.jsx)("rect", { x: "4", y: "4", width: "16", height: "16", stroke: "var(--button-icon-hover, rgb(24, 24, 26))", fill: "none", strokeWidth: "2" }) }),
1077
- "split-horizontal": () => (0, import_jsx_runtime13.jsxs)("svg", { width: "24", height: "24", style: ICON_STYLE, children: [(0, import_jsx_runtime13.jsx)("rect", { x: "4", y: "4", width: "16", height: "7", stroke: "var(--button-icon-hover, rgb(24, 24, 26))", fill: "none", strokeWidth: "2" }), (0, import_jsx_runtime13.jsx)("rect", { x: "4", y: "13", width: "16", height: "7", stroke: "var(--button-icon-hover, rgb(24, 24, 26))", fill: "none", strokeWidth: "2" })] }),
1078
- "split-vertical": () => (0, import_jsx_runtime13.jsxs)("svg", { width: "24", height: "24", style: ICON_STYLE, children: [(0, import_jsx_runtime13.jsx)("rect", { x: "4", y: "4", width: "7", height: "16", stroke: "var(--button-icon-hover, rgb(24, 24, 26))", fill: "none", strokeWidth: "2" }), (0, import_jsx_runtime13.jsx)("rect", { x: "13", y: "4", width: "7", height: "16", stroke: "var(--button-icon-hover, rgb(24, 24, 26))", fill: "none", strokeWidth: "2" })] })
1079
- };
1080
- var MENU_ITEMS = [
1081
- { value: "single", icon: ICONS.single, label: "Single View" },
1082
- { value: "split-horizontal", icon: ICONS["split-horizontal"], label: "Split Horizontal" },
1083
- { value: "split-vertical", icon: ICONS["split-vertical"], label: "Split Vertical" }
1084
- ];
1085
-
1086
1119
  // dist/info-widget.js
1087
- var import_jsx_runtime16 = require("preact/jsx-runtime");
1088
- var import_core11 = require("@deck.gl/core");
1089
- var import_preact10 = require("preact");
1120
+ var import_jsx_runtime14 = require("preact/jsx-runtime");
1121
+ var import_core10 = require("@deck.gl/core");
1122
+ var import_preact9 = require("preact");
1090
1123
 
1091
1124
  // dist/lib/components/popover.js
1092
- var import_jsx_runtime14 = require("preact/jsx-runtime");
1125
+ var import_jsx_runtime12 = require("preact/jsx-runtime");
1093
1126
  var import_hooks4 = require("preact/hooks");
1094
1127
  var import_dom = require("@floating-ui/dom");
1095
1128
  var Popover = ({ x, y, placement = "right", offset: pixelOffset = 0, arrow: arrowSize = false, arrowColor = "white", children }) => {
@@ -1128,7 +1161,7 @@ var Popover = ({ x, y, placement = "right", offset: pixelOffset = 0, arrow: arro
1128
1161
  (0, import_hooks4.useMemo)(() => {
1129
1162
  var _a;
1130
1163
  (_a = updaterRef.current) == null ? void 0 : _a.call(updaterRef);
1131
- }, [placement, arrowSize, pixelOffset]);
1164
+ }, [x, y, placement, arrowSize, pixelOffset]);
1132
1165
  (0, import_hooks4.useEffect)(() => {
1133
1166
  if (contentRef.current) {
1134
1167
  contentRef.current.style.visibility = "visible";
@@ -1141,7 +1174,7 @@ var Popover = ({ x, y, placement = "right", offset: pixelOffset = 0, arrow: arro
1141
1174
  cleanup();
1142
1175
  };
1143
1176
  }, []);
1144
- return (0, import_jsx_runtime14.jsx)("div", { style: { position: "absolute", left: x, top: y }, ref: anchorRef, children: (0, import_jsx_runtime14.jsxs)("div", { className: "deck-widget deck-widget-popover", style: { position: "fixed", visibility: "hidden", pointerEvents: "none" }, ref: contentRef, children: [Boolean(arrowSize) && (0, import_jsx_runtime14.jsx)("div", { className: "deck-widget-popover-arrow", style: { position: "absolute" }, ref: arrowRef }), children] }) });
1177
+ return (0, import_jsx_runtime12.jsx)("div", { style: { position: "absolute", left: x, top: y }, ref: anchorRef, children: (0, import_jsx_runtime12.jsxs)("div", { className: "deck-widget deck-widget-popover", style: { position: "fixed", visibility: "hidden", pointerEvents: "none" }, ref: contentRef, children: [Boolean(arrowSize) && (0, import_jsx_runtime12.jsx)("div", { className: "deck-widget-popover-arrow", style: { position: "absolute" }, ref: arrowRef }), children] }) });
1145
1178
  };
1146
1179
  function createArrow(width, height, color, placement) {
1147
1180
  const result = {
@@ -1181,7 +1214,7 @@ function createArrow(width, height, color, placement) {
1181
1214
  }
1182
1215
 
1183
1216
  // dist/lib/components/user-content.js
1184
- var import_jsx_runtime15 = require("preact/jsx-runtime");
1217
+ var import_jsx_runtime13 = require("preact/jsx-runtime");
1185
1218
  var import_hooks5 = require("preact/hooks");
1186
1219
  var UserContent = ({ text, html, element, ...props }) => {
1187
1220
  const containerRef = (0, import_hooks5.useRef)(null);
@@ -1193,11 +1226,11 @@ var UserContent = ({ text, html, element, ...props }) => {
1193
1226
  element == null ? void 0 : element.remove();
1194
1227
  };
1195
1228
  }, [element]);
1196
- return (0, import_jsx_runtime15.jsx)("div", { ref: containerRef, ...props, dangerouslySetInnerHTML: html ? { __html: html } : void 0, children: text });
1229
+ return (0, import_jsx_runtime13.jsx)("div", { ref: containerRef, ...props, dangerouslySetInnerHTML: html ? { __html: html } : void 0, children: text });
1197
1230
  };
1198
1231
 
1199
1232
  // dist/info-widget.js
1200
- var InfoWidget = class extends import_core11.Widget {
1233
+ var InfoWidget = class extends import_core10.Widget {
1201
1234
  constructor(props) {
1202
1235
  super(props);
1203
1236
  this.className = "deck-widget-info";
@@ -1212,6 +1245,11 @@ var InfoWidget = class extends import_core11.Widget {
1212
1245
  onAdd({ deck }) {
1213
1246
  this.deck = deck;
1214
1247
  }
1248
+ onRemove() {
1249
+ if (this.rootElement) {
1250
+ (0, import_preact9.render)(null, this.rootElement);
1251
+ }
1252
+ }
1215
1253
  onViewportChange(viewport) {
1216
1254
  this.viewport = viewport;
1217
1255
  this.updateHTML();
@@ -1248,7 +1286,7 @@ var InfoWidget = class extends import_core11.Widget {
1248
1286
  }
1249
1287
  onRenderHTML(rootElement) {
1250
1288
  if (!this.viewport || this.tooltip === null) {
1251
- (0, import_preact10.render)(null, rootElement);
1289
+ (0, import_preact9.render)(null, rootElement);
1252
1290
  return;
1253
1291
  }
1254
1292
  const style = {
@@ -1256,12 +1294,12 @@ var InfoWidget = class extends import_core11.Widget {
1256
1294
  ...this.tooltip.style
1257
1295
  };
1258
1296
  const [x, y] = this.viewport.project(this.tooltip.position);
1259
- const ui = (0, import_jsx_runtime16.jsx)(Popover, { x, y, placement: this.props.placement, arrow: this.props.arrow, arrowColor: "var(--menu-background, #fff)", offset: this.props.offset, children: (0, import_jsx_runtime16.jsx)(UserContent, { className: `deck-widget-popup-content ${this.tooltip.className} ${this.props.className}`, style, html: this.tooltip.html, text: this.tooltip.text, element: this.tooltip.element }) });
1260
- (0, import_preact10.render)(ui, rootElement);
1297
+ const ui = (0, import_jsx_runtime14.jsx)(Popover, { x, y, placement: this.props.placement, arrow: this.props.arrow, arrowColor: "var(--menu-background, #fff)", offset: this.props.offset, children: (0, import_jsx_runtime14.jsx)(UserContent, { className: `deck-widget-popup-content ${this.tooltip.className} ${this.props.className}`, style, html: this.tooltip.html, text: this.tooltip.text, element: this.tooltip.element }) });
1298
+ (0, import_preact9.render)(ui, rootElement);
1261
1299
  }
1262
1300
  };
1263
1301
  InfoWidget.defaultProps = {
1264
- ...import_core11.Widget.defaultProps,
1302
+ ...import_core10.Widget.defaultProps,
1265
1303
  id: "info",
1266
1304
  viewId: null,
1267
1305
  mode: "hover",
@@ -1272,10 +1310,10 @@ InfoWidget.defaultProps = {
1272
1310
  };
1273
1311
 
1274
1312
  // dist/popup-widget.js
1275
- var import_jsx_runtime17 = require("preact/jsx-runtime");
1276
- var import_core12 = require("@deck.gl/core");
1277
- var import_preact11 = require("preact");
1278
- var PopupWidget = class extends import_core12.Widget {
1313
+ var import_jsx_runtime15 = require("preact/jsx-runtime");
1314
+ var import_core11 = require("@deck.gl/core");
1315
+ var import_preact10 = require("preact");
1316
+ var PopupWidget = class extends import_core11.Widget {
1279
1317
  constructor(props) {
1280
1318
  super(props);
1281
1319
  this.className = "deck-widget-popup";
@@ -1290,6 +1328,11 @@ var PopupWidget = class extends import_core12.Widget {
1290
1328
  onAdd({ deck }) {
1291
1329
  this.deck = deck;
1292
1330
  }
1331
+ onRemove() {
1332
+ if (this.rootElement) {
1333
+ (0, import_preact10.render)(null, this.rootElement);
1334
+ }
1335
+ }
1293
1336
  onViewportChange(viewport) {
1294
1337
  this.viewport = viewport;
1295
1338
  this.updateHTML();
@@ -1309,17 +1352,17 @@ var PopupWidget = class extends import_core12.Widget {
1309
1352
  }
1310
1353
  onRenderHTML(rootElement) {
1311
1354
  if (!this.viewport) {
1312
- (0, import_preact11.render)(null, rootElement);
1355
+ (0, import_preact10.render)(null, rootElement);
1313
1356
  return;
1314
1357
  }
1315
1358
  const { marker, content, style } = this.props;
1316
1359
  const [x, y] = this.viewport.project(this.props.position);
1317
- const ui = (0, import_jsx_runtime17.jsxs)("div", { children: [marker && (0, import_jsx_runtime17.jsx)("div", { style: { position: "absolute", left: x, top: y, pointerEvents: "all", cursor: "pointer" }, children: (0, import_jsx_runtime17.jsx)(UserContent, { ...marker, onClick: () => this._setIsOpen(true) }) }), this.isOpen && (0, import_jsx_runtime17.jsx)(Popover, { x, y, placement: this.props.placement, arrow: this.props.arrow, arrowColor: "var(--menu-background, #fff)", offset: this.props.offset, children: (0, import_jsx_runtime17.jsxs)("div", { className: `deck-widget-popup-content ${this.props.className}`, style, children: [this.props.closeButton && (0, import_jsx_runtime17.jsx)("div", { className: "deck-widget-popup-controls", style: { width: "100%", display: "flex", justifyContent: "end" }, children: (0, import_jsx_runtime17.jsx)(IconButton, { className: "deck-widget-popup-close-button", onClick: () => this._setIsOpen(false) }) }), (0, import_jsx_runtime17.jsx)(UserContent, { ...typeof content === "string" ? { text: content } : content })] }) })] });
1318
- (0, import_preact11.render)(ui, rootElement);
1360
+ const ui = (0, import_jsx_runtime15.jsxs)("div", { children: [marker && (0, import_jsx_runtime15.jsx)("div", { style: { position: "absolute", left: x, top: y, pointerEvents: "all", cursor: "pointer" }, children: (0, import_jsx_runtime15.jsx)(UserContent, { ...marker, onClick: () => this._setIsOpen(true) }) }), this.isOpen && (0, import_jsx_runtime15.jsx)(Popover, { x, y, placement: this.props.placement, arrow: this.props.arrow, arrowColor: "var(--menu-background, #fff)", offset: this.props.offset, children: (0, import_jsx_runtime15.jsxs)("div", { className: `deck-widget-popup-content ${this.props.className}`, style, children: [this.props.closeButton && (0, import_jsx_runtime15.jsx)("div", { className: "deck-widget-popup-controls", style: { width: "100%", display: "flex", justifyContent: "end" }, children: (0, import_jsx_runtime15.jsx)(IconButton, { className: "deck-widget-popup-close-button", onClick: () => this._setIsOpen(false) }) }), (0, import_jsx_runtime15.jsx)(UserContent, { ...typeof content === "string" ? { text: content } : content })] }) })] });
1361
+ (0, import_preact10.render)(ui, rootElement);
1319
1362
  }
1320
1363
  };
1321
1364
  PopupWidget.defaultProps = {
1322
- ...import_core12.Widget.defaultProps,
1365
+ ...import_core11.Widget.defaultProps,
1323
1366
  id: "info",
1324
1367
  viewId: null,
1325
1368
  position: [0, 0],
@@ -1336,10 +1379,10 @@ PopupWidget.defaultProps = {
1336
1379
  };
1337
1380
 
1338
1381
  // dist/context-menu-widget.js
1339
- var import_jsx_runtime18 = require("preact/jsx-runtime");
1340
- var import_core13 = require("@deck.gl/core");
1341
- var import_preact12 = require("preact");
1342
- var ContextMenuWidget = class extends import_core13.Widget {
1382
+ var import_jsx_runtime16 = require("preact/jsx-runtime");
1383
+ var import_core12 = require("@deck.gl/core");
1384
+ var import_preact11 = require("preact");
1385
+ var ContextMenuWidget = class extends import_core12.Widget {
1343
1386
  constructor(props) {
1344
1387
  super(props);
1345
1388
  this.className = "deck-widget-context-menu";
@@ -1352,7 +1395,7 @@ var ContextMenuWidget = class extends import_core13.Widget {
1352
1395
  (_a = deck.getCanvas()) == null ? void 0 : _a.addEventListener("contextmenu", (event) => this.handleContextMenu(event));
1353
1396
  }
1354
1397
  handleContextMenu(srcEvent) {
1355
- var _a;
1398
+ var _a, _b, _c;
1356
1399
  const targetRect = srcEvent.target.getBoundingClientRect();
1357
1400
  const x = srcEvent.clientX - targetRect.x;
1358
1401
  const y = srcEvent.clientY - targetRect.y;
@@ -1365,7 +1408,7 @@ var ContextMenuWidget = class extends import_core13.Widget {
1365
1408
  index: -1,
1366
1409
  pixelRatio: 1
1367
1410
  };
1368
- const menuItems = this.props.getMenuItems(pickInfo, this) || [];
1411
+ const menuItems = ((_c = (_b = this.props).getMenuItems) == null ? void 0 : _c.call(_b, pickInfo, this)) || this.props.menuItems;
1369
1412
  this.menu = menuItems.length > 0 ? {
1370
1413
  items: menuItems,
1371
1414
  pickInfo
@@ -1375,7 +1418,7 @@ var ContextMenuWidget = class extends import_core13.Widget {
1375
1418
  }
1376
1419
  onRenderHTML(rootElement) {
1377
1420
  if (!this.menu) {
1378
- (0, import_preact12.render)(null, rootElement);
1421
+ (0, import_preact11.render)(null, rootElement);
1379
1422
  return;
1380
1423
  }
1381
1424
  const { items, pickInfo } = this.menu;
@@ -1384,8 +1427,8 @@ var ContextMenuWidget = class extends import_core13.Widget {
1384
1427
  position: "static",
1385
1428
  ...this.props.style
1386
1429
  };
1387
- const ui = (0, import_jsx_runtime18.jsx)(Popover, { x: pickInfo.x, y: pickInfo.y, placement: this.props.placement, arrow: this.props.arrow, arrowColor: "var(--menu-background, #fff)", offset: this.props.offset, children: (0, import_jsx_runtime18.jsx)(SimpleMenu, { menuItems: items, onSelect: (value) => this.props.onMenuItemSelected(value, pickInfo), style, isOpen: true, onClose: () => this.hide() }) });
1388
- (0, import_preact12.render)(ui, rootElement);
1430
+ const ui = (0, import_jsx_runtime16.jsx)(Popover, { x: pickInfo.x, y: pickInfo.y, placement: this.props.placement, arrow: this.props.arrow, arrowColor: "var(--menu-background, #fff)", offset: this.props.offset, children: (0, import_jsx_runtime16.jsx)(SimpleMenu, { menuItems: items, onSelect: (value) => this.props.onMenuItemSelected(value, pickInfo), style, isOpen: true, onClose: () => this.hide() }) });
1431
+ (0, import_preact11.render)(ui, rootElement);
1389
1432
  }
1390
1433
  hide() {
1391
1434
  this.menu = null;
@@ -1393,9 +1436,10 @@ var ContextMenuWidget = class extends import_core13.Widget {
1393
1436
  }
1394
1437
  };
1395
1438
  ContextMenuWidget.defaultProps = {
1396
- ...import_core13.Widget.defaultProps,
1439
+ ...import_core12.Widget.defaultProps,
1397
1440
  id: "context",
1398
1441
  viewId: null,
1442
+ menuItems: [],
1399
1443
  getMenuItems: void 0,
1400
1444
  onMenuItemSelected: () => {
1401
1445
  },
@@ -1405,12 +1449,12 @@ ContextMenuWidget.defaultProps = {
1405
1449
  };
1406
1450
 
1407
1451
  // dist/scrollbar-widget.js
1408
- var import_jsx_runtime20 = require("preact/jsx-runtime");
1409
- var import_core14 = require("@deck.gl/core");
1410
- var import_preact13 = require("preact");
1452
+ var import_jsx_runtime18 = require("preact/jsx-runtime");
1453
+ var import_core13 = require("@deck.gl/core");
1454
+ var import_preact12 = require("preact");
1411
1455
 
1412
1456
  // dist/lib/components/range-input.js
1413
- var import_jsx_runtime19 = require("preact/jsx-runtime");
1457
+ var import_jsx_runtime17 = require("preact/jsx-runtime");
1414
1458
  var import_hooks6 = require("preact/hooks");
1415
1459
  var wheelListenerOptions = { passive: false };
1416
1460
  var clamp = (value, min, max) => {
@@ -1660,10 +1704,10 @@ function RangeInput(props) {
1660
1704
  left: `${offsetPct}%`,
1661
1705
  width: `${sizePct}%`
1662
1706
  };
1663
- return (0, import_jsx_runtime19.jsx)("div", { className: "deck-widget-range__decoration", style, children: decoration.element }, `decoration-${index}`);
1707
+ return (0, import_jsx_runtime17.jsx)("div", { className: "deck-widget-range__decoration", style, children: decoration.element }, `decoration-${index}`);
1664
1708
  });
1665
1709
  }, [decorations, range, min, vertical]);
1666
- return (0, import_jsx_runtime19.jsxs)("div", { ref: rootRef, tabIndex: 0, role: "scrollbar", "aria-valuemin": min, "aria-valuemax": min + maxStart, "aria-valuenow": clampedStart, "aria-orientation": orientation, className: `${className} deck-widget-range deck-widget-range--${orientation} ${maxStart === 0 ? "deck-widget-range--disabled" : ""}`, children: [stepButtons && (0, import_jsx_runtime19.jsx)("button", { type: "button", className: "deck-widget-range__button deck-widget-range__button--start", "aria-label": startButtonAriaLabel, disabled: clampedStart <= min, onClick: handleStepNegative, children: (0, import_jsx_runtime19.jsx)("span", { className: "deck-widget-icon" }) }), (0, import_jsx_runtime19.jsxs)("div", { className: "deck-widget-range__track", ref: trackRef, onClick: handleTrackClick, children: [(0, import_jsx_runtime19.jsx)("div", { className: "deck-widget-range__decorations", children: decorationElements }), (0, import_jsx_runtime19.jsx)("div", { className: "deck-widget-range__thumb", "data-scrollbar-thumb": "true", ref: thumbRef, style: vertical ? { height: `${thumbLength * 100}%`, top: `${thumbOffset * 100}%` } : { width: `${thumbLength * 100}%`, left: `${thumbOffset * 100}%` }, onPointerDown: handleThumbPointerDown, onPointerMove: handleThumbPointerMove, onPointerUp: handleThumbPointerUp, onPointerCancel: handleThumbPointerUp })] }), stepButtons && (0, import_jsx_runtime19.jsx)("button", { type: "button", className: "deck-widget-range__button deck-widget-range__button--end", "aria-label": endButtonAriaLabel, disabled: clampedStart >= min + maxStart, onClick: handleStepPositive, children: (0, import_jsx_runtime19.jsx)("span", { className: "deck-widget-icon" }) })] });
1710
+ return (0, import_jsx_runtime17.jsxs)("div", { ref: rootRef, tabIndex: 0, role: "scrollbar", "aria-valuemin": min, "aria-valuemax": min + maxStart, "aria-valuenow": clampedStart, "aria-orientation": orientation, className: `${className} deck-widget-range deck-widget-range--${orientation} ${maxStart === 0 ? "deck-widget-range--disabled" : ""}`, children: [stepButtons && (0, import_jsx_runtime17.jsx)("button", { type: "button", className: "deck-widget-range__button deck-widget-range__button--start", "aria-label": startButtonAriaLabel, disabled: clampedStart <= min, onClick: handleStepNegative, children: (0, import_jsx_runtime17.jsx)("span", { className: "deck-widget-icon" }) }), (0, import_jsx_runtime17.jsxs)("div", { className: "deck-widget-range__track", ref: trackRef, onClick: handleTrackClick, children: [(0, import_jsx_runtime17.jsx)("div", { className: "deck-widget-range__decorations", children: decorationElements }), (0, import_jsx_runtime17.jsx)("div", { className: "deck-widget-range__thumb", "data-scrollbar-thumb": "true", ref: thumbRef, style: vertical ? { height: `${thumbLength * 100}%`, top: `${thumbOffset * 100}%` } : { width: `${thumbLength * 100}%`, left: `${thumbOffset * 100}%` }, onPointerDown: handleThumbPointerDown, onPointerMove: handleThumbPointerMove, onPointerUp: handleThumbPointerUp, onPointerCancel: handleThumbPointerUp })] }), stepButtons && (0, import_jsx_runtime17.jsx)("button", { type: "button", className: "deck-widget-range__button deck-widget-range__button--end", "aria-label": endButtonAriaLabel, disabled: clampedStart >= min + maxStart, onClick: handleStepPositive, children: (0, import_jsx_runtime17.jsx)("span", { className: "deck-widget-icon" }) })] });
1667
1711
  }
1668
1712
 
1669
1713
  // dist/scrollbar-widget.js
@@ -1676,7 +1720,7 @@ var clamp2 = (value, min, max) => {
1676
1720
  }
1677
1721
  return value;
1678
1722
  };
1679
- var ScrollbarWidget = class extends import_core14.Widget {
1723
+ var ScrollbarWidget = class extends import_core13.Widget {
1680
1724
  constructor(props) {
1681
1725
  const resolved = {
1682
1726
  ...ScrollbarWidget.defaultProps,
@@ -1711,12 +1755,12 @@ var ScrollbarWidget = class extends import_core14.Widget {
1711
1755
  const isVertical = this.isVertical();
1712
1756
  const startLabel = this.props.startButtonAriaLabel ?? (isVertical ? "Scroll up" : "Scroll left");
1713
1757
  const endLabel = this.props.endButtonAriaLabel ?? (isVertical ? "Scroll down" : "Scroll right");
1714
- const ui = (0, import_jsx_runtime20.jsx)(RangeInput, { min: 0, max: Math.max(0, this.contentSize), step: this.getEffectiveStep(), pageSize: this.getEffectivePage(), value: [clampedOffset, clampedOffset + this.viewportSize], orientation: this.props.orientation, stepButtons: true, startButtonAriaLabel: startLabel, endButtonAriaLabel: endLabel, eventTarget: wheelTarget, decorations, onChange: this.handleRangeChange });
1715
- (0, import_preact13.render)(ui, element);
1758
+ const ui = (0, import_jsx_runtime18.jsx)(RangeInput, { min: 0, max: Math.max(0, this.contentSize), step: this.getEffectiveStep(), pageSize: this.getEffectivePage(), value: [clampedOffset, clampedOffset + this.viewportSize], orientation: this.props.orientation, stepButtons: true, startButtonAriaLabel: startLabel, endButtonAriaLabel: endLabel, eventTarget: wheelTarget, decorations, onChange: this.handleRangeChange });
1759
+ (0, import_preact12.render)(ui, element);
1716
1760
  }
1717
1761
  onRemove() {
1718
1762
  if (this.rootElement) {
1719
- (0, import_preact13.render)(null, this.rootElement);
1763
+ (0, import_preact12.render)(null, this.rootElement);
1720
1764
  }
1721
1765
  super.onRemove();
1722
1766
  }
@@ -1753,7 +1797,7 @@ var ScrollbarWidget = class extends import_core14.Widget {
1753
1797
  } : void 0;
1754
1798
  return {
1755
1799
  position: [start - contentStart, end - contentStart],
1756
- element: (0, import_jsx_runtime20.jsx)("div", { style: {
1800
+ element: (0, import_jsx_runtime18.jsx)("div", { style: {
1757
1801
  pointerEvents: onClick ? "all" : "none",
1758
1802
  width: "100%",
1759
1803
  height: "100%",
@@ -1816,7 +1860,7 @@ var ScrollbarWidget = class extends import_core14.Widget {
1816
1860
  }
1817
1861
  };
1818
1862
  ScrollbarWidget.defaultProps = {
1819
- ...import_core14.Widget.defaultProps,
1863
+ ...import_core13.Widget.defaultProps,
1820
1864
  contentBounds: null,
1821
1865
  placement: "top-right",
1822
1866
  viewId: null,
@@ -1837,11 +1881,139 @@ function projectBounds(bounds, viewport, isVertical) {
1837
1881
  }, [Infinity, -Infinity]);
1838
1882
  }
1839
1883
 
1840
- // dist/timeline-widget.js
1841
- var import_jsx_runtime21 = require("preact/jsx-runtime");
1842
- var import_core15 = require("@deck.gl/core");
1884
+ // dist/icon-widget.js
1885
+ var import_jsx_runtime19 = require("preact/jsx-runtime");
1886
+ var import_preact13 = require("preact");
1887
+ var import_core14 = require("@deck.gl/core");
1888
+ var IconWidget = class extends import_core14.Widget {
1889
+ constructor(props) {
1890
+ super(props);
1891
+ this.className = "";
1892
+ this.placement = "top-left";
1893
+ this.setProps(this.props);
1894
+ }
1895
+ setProps(props) {
1896
+ this.placement = props.placement ?? this.placement;
1897
+ this.viewId = props.viewId;
1898
+ super.setProps(props);
1899
+ }
1900
+ onRenderHTML(rootElement) {
1901
+ const { className, style, icon, color, label, onClick } = this.props;
1902
+ (0, import_preact13.render)((0, import_jsx_runtime19.jsx)(IconButton, { className, style, color, icon, label, onClick }), rootElement);
1903
+ }
1904
+ };
1905
+ IconWidget.defaultProps = {
1906
+ ...import_core14.Widget.defaultProps,
1907
+ id: "icon",
1908
+ placement: "top-left",
1909
+ viewId: null,
1910
+ icon: "",
1911
+ label: "",
1912
+ color: "",
1913
+ onClick: void 0
1914
+ };
1915
+
1916
+ // dist/toggle-widget.js
1917
+ var import_jsx_runtime20 = require("preact/jsx-runtime");
1843
1918
  var import_preact14 = require("preact");
1844
- var TimelineWidget = class extends import_core15.Widget {
1919
+ var import_core15 = require("@deck.gl/core");
1920
+ var ToggleWidget = class extends import_core15.Widget {
1921
+ constructor(props) {
1922
+ super(props);
1923
+ this.className = "deck-widget-toggle";
1924
+ this.placement = "top-left";
1925
+ this._toggle = () => {
1926
+ var _a, _b;
1927
+ this.checked = !this.checked;
1928
+ (_b = (_a = this.props).onChange) == null ? void 0 : _b.call(_a, this.checked);
1929
+ this.updateHTML();
1930
+ };
1931
+ this.checked = this.props.initialChecked;
1932
+ this.setProps(this.props);
1933
+ }
1934
+ setProps(props) {
1935
+ this.placement = props.placement ?? this.placement;
1936
+ this.viewId = props.viewId;
1937
+ super.setProps(props);
1938
+ }
1939
+ onRenderHTML(rootElement) {
1940
+ const { className, style, icon, label, color, onIcon = icon, onLabel = label, onColor = color } = this.props;
1941
+ const on = this.checked;
1942
+ rootElement.dataset.checked = String(on);
1943
+ (0, import_preact14.render)((0, import_jsx_runtime20.jsx)(IconButton, { className, style, icon: on ? onIcon : icon, label: on ? onLabel : label, color: on ? onColor : color, onClick: this._toggle }), rootElement);
1944
+ }
1945
+ };
1946
+ ToggleWidget.defaultProps = {
1947
+ ...import_core15.Widget.defaultProps,
1948
+ id: "icon",
1949
+ placement: "top-left",
1950
+ viewId: null,
1951
+ initialChecked: false,
1952
+ icon: "",
1953
+ onIcon: void 0,
1954
+ label: "",
1955
+ onLabel: void 0,
1956
+ color: "",
1957
+ onColor: void 0,
1958
+ onChange: void 0
1959
+ };
1960
+
1961
+ // dist/selector-widget.js
1962
+ var import_jsx_runtime21 = require("preact/jsx-runtime");
1963
+ var import_preact15 = require("preact");
1964
+ var import_core16 = require("@deck.gl/core");
1965
+ var SelectorWidget = class extends import_core16.Widget {
1966
+ constructor(props) {
1967
+ super(props);
1968
+ this.className = "deck-widget-selector";
1969
+ this.placement = "top-left";
1970
+ this.isOpen = false;
1971
+ this._toggleMenu = () => {
1972
+ if (this.isOpen) {
1973
+ this.isOpen = false;
1974
+ } else if (this.rootElement) {
1975
+ this.isOpen = {
1976
+ x: this.rootElement.offsetLeft,
1977
+ y: this.rootElement.offsetTop,
1978
+ placement: this.props.placement.includes("right") ? "left-start" : "right-start"
1979
+ };
1980
+ }
1981
+ this.updateHTML();
1982
+ };
1983
+ this._handleSelectMode = (value) => {
1984
+ this.value = value;
1985
+ this.props.onChange(value);
1986
+ this.updateHTML();
1987
+ };
1988
+ this.value = this.props.initialValue;
1989
+ this.setProps(this.props);
1990
+ }
1991
+ setProps(props) {
1992
+ this.placement = props.placement ?? this.placement;
1993
+ this.viewId = props.viewId ?? this.viewId;
1994
+ super.setProps(props);
1995
+ }
1996
+ onRenderHTML(rootElement) {
1997
+ const selectedOption = this.props.options.find((opt) => opt.value === this.value) ?? this.props.options[0];
1998
+ (0, import_preact15.render)((0, import_jsx_runtime21.jsxs)("div", { children: [(0, import_jsx_runtime21.jsx)(IconButton, { icon: selectedOption.icon, label: selectedOption.label, onClick: this._toggleMenu }), this.isOpen && (0, import_jsx_runtime21.jsx)(Popover, { ...this.isOpen, children: (0, import_jsx_runtime21.jsx)(SimpleMenu, { isOpen: true, style: { pointerEvents: "auto", position: "static" }, menuItems: this.props.options, onSelect: this._handleSelectMode, onClose: this._toggleMenu }) })] }), rootElement);
1999
+ }
2000
+ };
2001
+ SelectorWidget.defaultProps = {
2002
+ ...import_core16.Widget.defaultProps,
2003
+ id: "view-selector",
2004
+ placement: "top-left",
2005
+ viewId: null,
2006
+ initialValue: "",
2007
+ options: [],
2008
+ onChange: () => {
2009
+ }
2010
+ };
2011
+
2012
+ // dist/timeline-widget.js
2013
+ var import_jsx_runtime22 = require("preact/jsx-runtime");
2014
+ var import_core17 = require("@deck.gl/core");
2015
+ var import_preact16 = require("preact");
2016
+ var TimelineWidget = class extends import_core17.Widget {
1845
2017
  constructor(props = {}) {
1846
2018
  var _a;
1847
2019
  super(props);
@@ -1867,7 +2039,7 @@ var TimelineWidget = class extends import_core15.Widget {
1867
2039
  this.tick = () => {
1868
2040
  const { timeRange: [min, max], step, loop } = this.props;
1869
2041
  if (step > 0) {
1870
- let next = Math.floor(this.currentTime / step) * step + step;
2042
+ let next = Math.round(this.currentTime / step) * step + step;
1871
2043
  if (next > max) {
1872
2044
  if (this.currentTime < max) {
1873
2045
  next = max;
@@ -1909,15 +2081,20 @@ var TimelineWidget = class extends import_core15.Widget {
1909
2081
  const { timeRange, step, formatLabel } = this.props;
1910
2082
  const currentTime = this.currentTime;
1911
2083
  rootElement.dataset.placement = this.props.placement;
1912
- (0, import_preact14.render)((0, import_jsx_runtime21.jsxs)("div", { className: "deck-widget-button-group", children: [this.playing ? (0, import_jsx_runtime21.jsx)(IconButton, { label: "Pause", className: "deck-widget-timeline-pause", onClick: this.handlePlayPause }) : (0, import_jsx_runtime21.jsx)(IconButton, { label: "Play", className: "deck-widget-timeline-play", onClick: this.handlePlayPause }), (0, import_jsx_runtime21.jsx)(RangeInput, { min: timeRange[0], max: timeRange[1], orientation: "horizontal", step, value: [currentTime, currentTime], onChange: this.handleTimeChange, decorations: [
2084
+ (0, import_preact16.render)((0, import_jsx_runtime22.jsxs)("div", { className: "deck-widget-button-group", children: [this.playing ? (0, import_jsx_runtime22.jsx)(IconButton, { label: "Pause", className: "deck-widget-timeline-pause", onClick: this.handlePlayPause }) : (0, import_jsx_runtime22.jsx)(IconButton, { label: "Play", className: "deck-widget-timeline-play", onClick: this.handlePlayPause }), (0, import_jsx_runtime22.jsx)(RangeInput, { min: timeRange[0], max: timeRange[1], orientation: "horizontal", step, value: [currentTime, currentTime], onChange: this.handleTimeChange, decorations: [
1913
2085
  {
1914
2086
  position: [currentTime, currentTime + step],
1915
- element: (0, import_jsx_runtime21.jsx)("div", { className: "deck-widget-timeline-label deck-widget-timeline-label--current", children: formatLabel(currentTime) })
2087
+ element: (0, import_jsx_runtime22.jsx)("div", { className: "deck-widget-timeline-label deck-widget-timeline-label--current", children: formatLabel(currentTime) })
1916
2088
  }
1917
2089
  ] })] }), rootElement);
1918
2090
  }
1919
2091
  play() {
1920
2092
  this.playing = true;
2093
+ const { timeRange: [min, max] } = this.props;
2094
+ if (this.currentTime >= max) {
2095
+ this.currentTime = min;
2096
+ this.props.onTimeChange(min);
2097
+ }
1921
2098
  this.updateHTML();
1922
2099
  this.tick();
1923
2100
  }
@@ -1931,7 +2108,7 @@ var TimelineWidget = class extends import_core15.Widget {
1931
2108
  }
1932
2109
  };
1933
2110
  TimelineWidget.defaultProps = {
1934
- ...import_core15.Widget.defaultProps,
2111
+ ...import_core17.Widget.defaultProps,
1935
2112
  id: "timeline",
1936
2113
  placement: "bottom-left",
1937
2114
  viewId: null,
@@ -1948,10 +2125,10 @@ TimelineWidget.defaultProps = {
1948
2125
  };
1949
2126
 
1950
2127
  // dist/screenshot-widget.js
1951
- var import_jsx_runtime22 = require("preact/jsx-runtime");
1952
- var import_preact15 = require("preact");
1953
- var import_core16 = require("@deck.gl/core");
1954
- var ScreenshotWidget = class extends import_core16.Widget {
2128
+ var import_jsx_runtime23 = require("preact/jsx-runtime");
2129
+ var import_preact17 = require("preact");
2130
+ var import_core18 = require("@deck.gl/core");
2131
+ var ScreenshotWidget = class extends import_core18.Widget {
1955
2132
  constructor(props = {}) {
1956
2133
  super(props);
1957
2134
  this.className = "deck-widget-screenshot";
@@ -1964,7 +2141,7 @@ var ScreenshotWidget = class extends import_core16.Widget {
1964
2141
  super.setProps(props);
1965
2142
  }
1966
2143
  onRenderHTML(rootElement) {
1967
- (0, import_preact15.render)((0, import_jsx_runtime22.jsx)(IconButton, { className: "deck-widget-camera", label: this.props.label, onClick: this.handleClick.bind(this) }), rootElement);
2144
+ (0, import_preact17.render)((0, import_jsx_runtime23.jsx)(IconButton, { className: "deck-widget-camera", label: this.props.label, onClick: this.handleClick.bind(this) }), rootElement);
1968
2145
  }
1969
2146
  handleClick() {
1970
2147
  if (this.props.onCapture) {
@@ -1991,7 +2168,7 @@ var ScreenshotWidget = class extends import_core16.Widget {
1991
2168
  }
1992
2169
  };
1993
2170
  ScreenshotWidget.defaultProps = {
1994
- ...import_core16.Widget.defaultProps,
2171
+ ...import_core18.Widget.defaultProps,
1995
2172
  id: "screenshot",
1996
2173
  placement: "top-left",
1997
2174
  viewId: null,
@@ -2002,10 +2179,10 @@ ScreenshotWidget.defaultProps = {
2002
2179
  };
2003
2180
 
2004
2181
  // dist/theme-widget.js
2005
- var import_jsx_runtime23 = require("preact/jsx-runtime");
2006
- var import_core17 = require("@deck.gl/core");
2007
- var import_core18 = require("@deck.gl/core");
2008
- var import_preact16 = require("preact");
2182
+ var import_jsx_runtime24 = require("preact/jsx-runtime");
2183
+ var import_core19 = require("@deck.gl/core");
2184
+ var import_core20 = require("@deck.gl/core");
2185
+ var import_preact18 = require("preact");
2009
2186
 
2010
2187
  // dist/themes.js
2011
2188
  var LightTheme = {
@@ -2122,7 +2299,7 @@ var DarkGlassTheme = {
2122
2299
  };
2123
2300
 
2124
2301
  // dist/theme-widget.js
2125
- var ThemeWidget = class extends import_core18.Widget {
2302
+ var ThemeWidget = class extends import_core20.Widget {
2126
2303
  constructor(props = {}) {
2127
2304
  super(props);
2128
2305
  this.className = "deck-widget-theme";
@@ -2139,22 +2316,22 @@ var ThemeWidget = class extends import_core18.Widget {
2139
2316
  super.setProps(props);
2140
2317
  switch (this.themeMode) {
2141
2318
  case "light":
2142
- if (props.lightModeTheme && !(0, import_core17._deepEqual)(props.lightModeTheme, lightModeTheme, 1)) {
2319
+ if (props.lightModeTheme && !(0, import_core19._deepEqual)(props.lightModeTheme, lightModeTheme, 1)) {
2143
2320
  this._setThemeMode("light");
2144
2321
  }
2145
2322
  break;
2146
2323
  case "dark":
2147
- if (props.darkModeTheme && !(0, import_core17._deepEqual)(props.darkModeTheme, darkModeTheme, 1)) {
2324
+ if (props.darkModeTheme && !(0, import_core19._deepEqual)(props.darkModeTheme, darkModeTheme, 1)) {
2148
2325
  this._setThemeMode("dark");
2149
2326
  }
2150
2327
  break;
2151
2328
  default:
2152
- import_core17.log.warn(`Invalid theme mode ${this.themeMode}`)();
2329
+ import_core19.log.warn(`Invalid theme mode ${this.themeMode}`)();
2153
2330
  }
2154
2331
  }
2155
2332
  onRenderHTML(rootElement) {
2156
2333
  const { lightModeLabel, darkModeLabel } = this.props;
2157
- (0, import_preact16.render)((0, import_jsx_runtime23.jsx)(IconButton, { onClick: this._handleClick.bind(this), label: this.themeMode === "dark" ? darkModeLabel : lightModeLabel, className: this.themeMode === "dark" ? "deck-widget-moon" : "deck-widget-sun" }), rootElement);
2334
+ (0, import_preact18.render)((0, import_jsx_runtime24.jsx)(IconButton, { onClick: this._handleClick.bind(this), label: this.themeMode === "dark" ? darkModeLabel : lightModeLabel, className: this.themeMode === "dark" ? "deck-widget-moon" : "deck-widget-sun" }), rootElement);
2158
2335
  }
2159
2336
  onAdd() {
2160
2337
  this._setThemeMode(this.themeMode);
@@ -2169,9 +2346,9 @@ var ThemeWidget = class extends import_core18.Widget {
2169
2346
  const container = (_a = this.rootElement) == null ? void 0 : _a.closest(".deck-widget-container");
2170
2347
  if (container) {
2171
2348
  const themeStyle = themeMode === "dark" ? this.props.darkModeTheme : this.props.lightModeTheme;
2172
- (0, import_core17._applyStyles)(container, themeStyle);
2349
+ (0, import_core19._applyStyles)(container, themeStyle);
2173
2350
  const label = this.themeMode === "dark" ? this.props.darkModeLabel : this.props.lightModeLabel;
2174
- import_core17.log.log(1, `Switched theme to ${label}`, themeStyle)();
2351
+ import_core19.log.log(1, `Switched theme to ${label}`, themeStyle)();
2175
2352
  this.updateHTML();
2176
2353
  }
2177
2354
  }
@@ -2188,7 +2365,7 @@ var ThemeWidget = class extends import_core18.Widget {
2188
2365
  }
2189
2366
  };
2190
2367
  ThemeWidget.defaultProps = {
2191
- ...import_core18.Widget.defaultProps,
2368
+ ...import_core20.Widget.defaultProps,
2192
2369
  id: "theme",
2193
2370
  placement: "top-left",
2194
2371
  viewId: null,
@@ -2200,10 +2377,10 @@ ThemeWidget.defaultProps = {
2200
2377
  };
2201
2378
 
2202
2379
  // dist/loading-widget.js
2203
- var import_jsx_runtime24 = require("preact/jsx-runtime");
2204
- var import_preact17 = require("preact");
2205
- var import_core19 = require("@deck.gl/core");
2206
- var LoadingWidget = class extends import_core19.Widget {
2380
+ var import_jsx_runtime25 = require("preact/jsx-runtime");
2381
+ var import_preact19 = require("preact");
2382
+ var import_core21 = require("@deck.gl/core");
2383
+ var LoadingWidget = class extends import_core21.Widget {
2207
2384
  constructor(props = {}) {
2208
2385
  super(props);
2209
2386
  this.className = "deck-widget-loading";
@@ -2217,9 +2394,9 @@ var LoadingWidget = class extends import_core19.Widget {
2217
2394
  super.setProps(props);
2218
2395
  }
2219
2396
  onRenderHTML(rootElement) {
2220
- (0, import_preact17.render)(
2397
+ (0, import_preact19.render)(
2221
2398
  // TODO(ibgreen) - this should not be a button, but styling is so nested that it is easier to reuse this component.
2222
- this.loading && (0, import_jsx_runtime24.jsx)(IconButton, { className: "deck-widget-spinner", label: this.props.label, onClick: this.handleClick.bind(this) }),
2399
+ this.loading && (0, import_jsx_runtime25.jsx)(IconButton, { className: "deck-widget-spinner", label: this.props.label, onClick: this.handleClick.bind(this) }),
2223
2400
  rootElement
2224
2401
  );
2225
2402
  }
@@ -2235,63 +2412,19 @@ var LoadingWidget = class extends import_core19.Widget {
2235
2412
  }
2236
2413
  };
2237
2414
  LoadingWidget.defaultProps = {
2238
- ...import_core19.Widget.defaultProps,
2415
+ ...import_core21.Widget.defaultProps,
2239
2416
  id: "loading",
2240
2417
  placement: "top-left",
2241
2418
  viewId: null,
2242
2419
  label: "Loading layer data"
2243
2420
  };
2244
2421
 
2245
- // dist/fps-widget.js
2246
- var import_jsx_runtime25 = require("preact/jsx-runtime");
2247
- var import_core20 = require("@deck.gl/core");
2248
- var import_preact18 = require("preact");
2249
- var FpsWidget = class extends import_core20.Widget {
2250
- constructor(props = {}) {
2251
- super(props);
2252
- this.className = "deck-widget-fps";
2253
- this.placement = "top-left";
2254
- this._lastFps = -1;
2255
- this.setProps(this.props);
2256
- }
2257
- setProps(props) {
2258
- this.placement = props.placement ?? this.placement;
2259
- this.viewId = props.viewId ?? this.viewId;
2260
- super.setProps(props);
2261
- }
2262
- onAdd({}) {
2263
- this._lastFps = this._getFps();
2264
- requestAnimationFrame(() => this._animate());
2265
- }
2266
- onRenderHTML(rootElement) {
2267
- const fps = this._getFps();
2268
- (0, import_preact18.render)((0, import_jsx_runtime25.jsx)(IconButton, { children: (0, import_jsx_runtime25.jsxs)("div", { className: "text", children: ["FPS", (0, import_jsx_runtime25.jsx)("br", {}), fps] }) }), rootElement);
2269
- }
2270
- _animate() {
2271
- const fps = this._getFps();
2272
- if (this._lastFps !== fps) {
2273
- this._lastFps = fps;
2274
- this.updateHTML();
2275
- }
2276
- requestAnimationFrame(() => this._animate());
2277
- }
2278
- _getFps() {
2279
- var _a;
2280
- return Math.round(((_a = this.deck) == null ? void 0 : _a.metrics.fps) ?? 0);
2281
- }
2282
- };
2283
- FpsWidget.defaultProps = {
2284
- ...import_core20.Widget.defaultProps,
2285
- id: "fps",
2286
- placement: "top-left",
2287
- viewId: null
2288
- };
2289
-
2290
2422
  // dist/stats-widget.js
2291
2423
  var import_jsx_runtime26 = require("preact/jsx-runtime");
2292
- var import_core21 = require("@deck.gl/core");
2293
- var import_core22 = require("@luma.gl/core");
2294
- var import_preact19 = require("preact");
2424
+ var import_core22 = require("@deck.gl/core");
2425
+ var import_core23 = require("@luma.gl/core");
2426
+ var import_preact20 = require("preact");
2427
+ var import_hooks7 = require("preact/hooks");
2295
2428
  var DEFAULT_COUNT_FORMATTER = (stat) => `${stat.name}: ${stat.count}`;
2296
2429
  function formatTime(time) {
2297
2430
  return time < 1e3 ? `${time.toFixed(2)}ms` : `${(time / 1e3).toFixed(2)}s`;
@@ -2307,7 +2440,7 @@ var DEFAULT_FORMATTERS = {
2307
2440
  fps: (stat) => `${stat.name}: ${Math.round(stat.getHz())}fps`,
2308
2441
  memory: (stat) => `${stat.name}: ${formatMemory(stat.count)}`
2309
2442
  };
2310
- var StatsWidget = class extends import_core21.Widget {
2443
+ var StatsWidget = class extends import_core22.Widget {
2311
2444
  constructor(props = {}) {
2312
2445
  super(props);
2313
2446
  this.className = "deck-widget-stats";
@@ -2318,6 +2451,10 @@ var StatsWidget = class extends import_core21.Widget {
2318
2451
  this.collapsed = !this.collapsed;
2319
2452
  this.updateHTML();
2320
2453
  };
2454
+ this._getFps = () => {
2455
+ var _a;
2456
+ return Math.round(((_a = this.deck) == null ? void 0 : _a.metrics.fps) ?? 0);
2457
+ };
2321
2458
  this._formatters = { ...DEFAULT_FORMATTERS };
2322
2459
  this._resetOnUpdate = { ...this.props.resetOnUpdate };
2323
2460
  this.collapsed = !props.defaultIsExpanded;
@@ -2337,15 +2474,21 @@ var StatsWidget = class extends import_core21.Widget {
2337
2474
  }
2338
2475
  super.setProps(props);
2339
2476
  }
2340
- onAdd() {
2341
- this.updateHTML();
2477
+ onRemove() {
2478
+ if (this.rootElement) {
2479
+ (0, import_preact20.render)(null, this.rootElement);
2480
+ }
2342
2481
  }
2343
2482
  onRenderHTML(rootElement) {
2344
- const stats = this._getStats();
2345
2483
  const collapsed = this.collapsed;
2484
+ if (collapsed) {
2485
+ (0, import_preact20.render)((0, import_jsx_runtime26.jsx)(FpsIcon, { getFps: this._getFps, onClick: this._toggleCollapsed }), rootElement);
2486
+ return;
2487
+ }
2488
+ const stats = this._getStats();
2346
2489
  const title = this.props.title || ("id" in stats ? stats.id : null) || "Stats";
2347
2490
  const items = [];
2348
- if (!collapsed && stats) {
2491
+ if (stats) {
2349
2492
  stats.forEach((stat) => {
2350
2493
  const lines = this._getLines(stat).split("\n");
2351
2494
  if (this._resetOnUpdate && this._resetOnUpdate[stat.name]) {
@@ -2356,12 +2499,14 @@ var StatsWidget = class extends import_core21.Widget {
2356
2499
  });
2357
2500
  });
2358
2501
  }
2359
- (0, import_preact19.render)((0, import_jsx_runtime26.jsxs)("div", { className: "deck-widget-stats-container", style: { cursor: "default" }, children: [(0, import_jsx_runtime26.jsxs)("div", { className: "deck-widget-stats-header", style: { cursor: "pointer", pointerEvents: "auto" }, onClick: this._toggleCollapsed, children: [(0, import_jsx_runtime26.jsx)("b", { children: title }), (0, import_jsx_runtime26.jsx)("button", { className: "deck-widget-dropdown-button", children: (0, import_jsx_runtime26.jsx)("span", { className: `deck-widget-dropdown-icon ${collapsed ? "" : "open"}` }) })] }), !collapsed && (0, import_jsx_runtime26.jsx)("div", { className: "deck-widget-stats-content", children: items })] }), rootElement);
2502
+ (0, import_preact20.render)((0, import_jsx_runtime26.jsxs)("div", { className: "deck-widget-stats-container", style: { cursor: "default" }, children: [(0, import_jsx_runtime26.jsxs)("div", { className: "deck-widget-stats-header", style: { cursor: "pointer", pointerEvents: "auto" }, onClick: this._toggleCollapsed, children: [(0, import_jsx_runtime26.jsx)("b", { children: title }), (0, import_jsx_runtime26.jsx)("button", { className: "deck-widget-dropdown-button", children: (0, import_jsx_runtime26.jsx)("span", { className: "deck-widget-dropdown-icon open" }) })] }), (0, import_jsx_runtime26.jsx)("div", { className: "deck-widget-stats-content", children: items })] }), rootElement);
2360
2503
  }
2361
2504
  onRedraw() {
2362
- const framesPerUpdate = Math.max(1, this.props.framesPerUpdate || 1);
2363
- if (this._counter++ % framesPerUpdate === 0) {
2364
- this.updateHTML();
2505
+ if (!this.collapsed) {
2506
+ const framesPerUpdate = Math.max(1, this.props.framesPerUpdate || 1);
2507
+ if (this._counter++ % framesPerUpdate === 0) {
2508
+ this.updateHTML();
2509
+ }
2365
2510
  }
2366
2511
  }
2367
2512
  _getStats() {
@@ -2371,7 +2516,7 @@ var StatsWidget = class extends import_core21.Widget {
2371
2516
  const metrics = ((_a = this.deck) == null ? void 0 : _a.metrics) ?? {};
2372
2517
  return Object.entries(metrics);
2373
2518
  case "luma":
2374
- return Array.from(import_core22.luma.stats.stats.values())[0];
2519
+ return Array.from(import_core23.luma.stats.stats.values())[0];
2375
2520
  case "device":
2376
2521
  const device = (_b = this.deck) == null ? void 0 : _b.device;
2377
2522
  const stats = device == null ? void 0 : device.statsManager.stats.values();
@@ -2393,7 +2538,7 @@ var StatsWidget = class extends import_core21.Widget {
2393
2538
  }
2394
2539
  };
2395
2540
  StatsWidget.defaultProps = {
2396
- ...import_core21.Widget.defaultProps,
2541
+ ...import_core22.Widget.defaultProps,
2397
2542
  type: "deck",
2398
2543
  placement: "top-left",
2399
2544
  viewId: null,
@@ -2405,4 +2550,18 @@ StatsWidget.defaultProps = {
2405
2550
  resetOnUpdate: {},
2406
2551
  id: "stats"
2407
2552
  };
2553
+ function FpsIcon({ getFps, onClick }) {
2554
+ const [fps, setFps] = (0, import_hooks7.useState)(getFps());
2555
+ (0, import_hooks7.useEffect)(() => {
2556
+ const onUpdate = () => {
2557
+ setFps(getFps());
2558
+ timer = requestAnimationFrame(onUpdate);
2559
+ };
2560
+ let timer = requestAnimationFrame(onUpdate);
2561
+ return () => {
2562
+ cancelAnimationFrame(timer);
2563
+ };
2564
+ }, [getFps]);
2565
+ return (0, import_jsx_runtime26.jsx)(IconButton, { onClick, children: (0, import_jsx_runtime26.jsxs)("div", { className: "text", children: ["FPS", (0, import_jsx_runtime26.jsx)("br", {}), fps] }) });
2566
+ }
2408
2567
  //# sourceMappingURL=index.cjs.map