@deck.gl/widgets 9.3.0-alpha.1 → 9.3.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/context-menu-widget.d.ts +7 -5
- package/dist/context-menu-widget.d.ts.map +1 -1
- package/dist/context-menu-widget.js +2 -1
- package/dist/context-menu-widget.js.map +1 -1
- package/dist/dist.dev.js +687 -555
- package/dist/icon-widget.d.ts +28 -0
- package/dist/icon-widget.d.ts.map +1 -0
- package/dist/icon-widget.js +35 -0
- package/dist/icon-widget.js.map +1 -0
- package/dist/index.cjs +468 -309
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +11 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -7
- package/dist/index.js.map +1 -1
- package/dist/info-widget.d.ts +1 -0
- package/dist/info-widget.d.ts.map +1 -1
- package/dist/info-widget.js +6 -0
- package/dist/info-widget.js.map +1 -1
- package/dist/lib/components/dropdown-menu.d.ts +3 -2
- package/dist/lib/components/dropdown-menu.d.ts.map +1 -1
- package/dist/lib/components/dropdown-menu.js +12 -8
- package/dist/lib/components/dropdown-menu.js.map +1 -1
- package/dist/lib/components/icon-button.d.ts +3 -0
- package/dist/lib/components/icon-button.d.ts.map +1 -1
- package/dist/lib/components/icon-button.js +10 -2
- package/dist/lib/components/icon-button.js.map +1 -1
- package/dist/lib/components/popover.js +1 -1
- package/dist/lib/components/popover.js.map +1 -1
- package/dist/lib/data-url.d.ts +5 -0
- package/dist/lib/data-url.d.ts.map +1 -0
- package/dist/lib/data-url.js +7 -0
- package/dist/lib/data-url.js.map +1 -0
- package/dist/popup-widget.d.ts +1 -0
- package/dist/popup-widget.d.ts.map +1 -1
- package/dist/popup-widget.js +6 -0
- package/dist/popup-widget.js.map +1 -1
- package/dist/selector-widget.d.ts +44 -0
- package/dist/selector-widget.d.ts.map +1 -0
- package/dist/selector-widget.js +64 -0
- package/dist/selector-widget.js.map +1 -0
- package/dist/splitter-widget.d.ts +52 -11
- package/dist/splitter-widget.d.ts.map +1 -1
- package/dist/splitter-widget.js +177 -76
- package/dist/splitter-widget.js.map +1 -1
- package/dist/stats-widget.d.ts +2 -1
- package/dist/stats-widget.d.ts.map +1 -1
- package/dist/stats-widget.js +37 -8
- package/dist/stats-widget.js.map +1 -1
- package/dist/stylesheet.css +50 -13
- package/dist/timeline-widget.d.ts.map +1 -1
- package/dist/timeline-widget.js +6 -1
- package/dist/timeline-widget.js.map +1 -1
- package/dist/toggle-widget.d.ts +38 -0
- package/dist/toggle-widget.d.ts.map +1 -0
- package/dist/toggle-widget.js +47 -0
- package/dist/toggle-widget.js.map +1 -0
- package/dist.min.js +2 -2
- package/package.json +3 -3
- package/src/context-menu-widget.tsx +9 -9
- package/src/icon-widget.tsx +69 -0
- package/src/index.ts +11 -9
- package/src/info-widget.tsx +7 -0
- package/src/lib/components/dropdown-menu.tsx +22 -15
- package/src/lib/components/icon-button.tsx +15 -3
- package/src/lib/components/popover.tsx +1 -1
- package/src/lib/data-url.ts +5 -0
- package/src/popup-widget.tsx +7 -0
- package/src/selector-widget.tsx +111 -0
- package/src/splitter-widget.tsx +281 -96
- package/src/stats-widget.tsx +50 -9
- package/src/stylesheet.css +50 -13
- package/src/timeline-widget.tsx +8 -1
- package/src/toggle-widget.tsx +101 -0
- package/dist/fps-widget.d.ts +0 -28
- package/dist/fps-widget.d.ts.map +0 -1
- package/dist/fps-widget.js +0 -51
- package/dist/fps-widget.js.map +0 -1
- package/dist/lib/components/icon-menu.d.ts +0 -16
- package/dist/lib/components/icon-menu.d.ts.map +0 -1
- package/dist/lib/components/icon-menu.js +0 -33
- package/dist/lib/components/icon-menu.js.map +0 -1
- package/dist/view-selector-widget.d.ts +0 -35
- package/dist/view-selector-widget.d.ts.map +0 -1
- package/dist/view-selector-widget.js +0 -63
- package/dist/view-selector-widget.js.map +0 -1
- package/src/fps-widget.tsx +0 -77
- package/src/lib/components/icon-menu.tsx +0 -70
- package/src/view-selector-widget.tsx +0 -151
|
@@ -6,18 +6,17 @@
|
|
|
6
6
|
import {Widget} from '@deck.gl/core';
|
|
7
7
|
import type {Deck, PickingInfo, WidgetProps} from '@deck.gl/core';
|
|
8
8
|
import {render, type JSX} from 'preact';
|
|
9
|
-
import {SimpleMenu,
|
|
9
|
+
import {SimpleMenu, type MenuItem} from './lib/components/dropdown-menu';
|
|
10
10
|
import {Popover, type PopoverProps} from './lib/components/popover';
|
|
11
11
|
|
|
12
12
|
export type ContextMenuWidgetProps = WidgetProps & {
|
|
13
13
|
/** View to attach to and interact with. Required when using multiple views. */
|
|
14
14
|
viewId?: string | null;
|
|
15
|
-
/**
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
/** Callback with the selected item */
|
|
15
|
+
/** Menu items for the menu. */
|
|
16
|
+
menuItems?: MenuItem[];
|
|
17
|
+
/** Callback to provide menu items for the menu given the picked object. Overrides `menuItems` */
|
|
18
|
+
getMenuItems?: (info: PickingInfo, widget: ContextMenuWidget) => MenuItem[] | null;
|
|
19
|
+
/** Callback when a menu item is selected */
|
|
21
20
|
onMenuItemSelected?: (value: string, pickInfo: PickingInfo | null) => void;
|
|
22
21
|
/** Position menu relative to the anchor.
|
|
23
22
|
* @default 'bottom-start'
|
|
@@ -39,6 +38,7 @@ export class ContextMenuWidget extends Widget<ContextMenuWidgetProps> {
|
|
|
39
38
|
...Widget.defaultProps,
|
|
40
39
|
id: 'context',
|
|
41
40
|
viewId: null,
|
|
41
|
+
menuItems: [],
|
|
42
42
|
getMenuItems: undefined!,
|
|
43
43
|
onMenuItemSelected: () => {},
|
|
44
44
|
placement: 'bottom-start',
|
|
@@ -50,7 +50,7 @@ export class ContextMenuWidget extends Widget<ContextMenuWidgetProps> {
|
|
|
50
50
|
placement = 'fill' as const;
|
|
51
51
|
|
|
52
52
|
menu: {
|
|
53
|
-
items:
|
|
53
|
+
items: MenuItem[];
|
|
54
54
|
pickInfo: PickingInfo;
|
|
55
55
|
} | null = null;
|
|
56
56
|
|
|
@@ -77,7 +77,7 @@ export class ContextMenuWidget extends Widget<ContextMenuWidgetProps> {
|
|
|
77
77
|
index: -1,
|
|
78
78
|
pixelRatio: 1
|
|
79
79
|
};
|
|
80
|
-
const menuItems = this.props.getMenuItems(pickInfo, this) ||
|
|
80
|
+
const menuItems = this.props.getMenuItems?.(pickInfo, this) || this.props.menuItems;
|
|
81
81
|
this.menu =
|
|
82
82
|
menuItems.length > 0
|
|
83
83
|
? {
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// deck.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import type {WidgetPlacement, WidgetProps} from '@deck.gl/core';
|
|
6
|
+
import {render, type JSX} from 'preact';
|
|
7
|
+
import {Widget} from '@deck.gl/core';
|
|
8
|
+
import {IconButton} from './lib/components/icon-button';
|
|
9
|
+
|
|
10
|
+
export type IconWidgetProps = WidgetProps & {
|
|
11
|
+
/** Widget positioning within the view. Default 'bottom-left'. */
|
|
12
|
+
placement?: WidgetPlacement;
|
|
13
|
+
/** View to attach to and interact with. Required when using multiple views. */
|
|
14
|
+
viewId?: string | null;
|
|
15
|
+
/** Data url to display as icon */
|
|
16
|
+
icon: string;
|
|
17
|
+
/** Tooltip label */
|
|
18
|
+
label?: string;
|
|
19
|
+
/** Icon color, a CSS Color string */
|
|
20
|
+
color?: string;
|
|
21
|
+
/** Callback when the widget is clicked */
|
|
22
|
+
onClick?: () => void;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* A generic widget that displays a button with icon or text content.
|
|
27
|
+
*/
|
|
28
|
+
export class IconWidget extends Widget<IconWidgetProps> {
|
|
29
|
+
static defaultProps: Required<IconWidgetProps> = {
|
|
30
|
+
...Widget.defaultProps,
|
|
31
|
+
id: 'icon',
|
|
32
|
+
placement: 'top-left',
|
|
33
|
+
viewId: null,
|
|
34
|
+
icon: '',
|
|
35
|
+
label: '',
|
|
36
|
+
color: '',
|
|
37
|
+
onClick: undefined!
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
className = '';
|
|
41
|
+
placement: WidgetPlacement = 'top-left';
|
|
42
|
+
|
|
43
|
+
constructor(props: IconWidgetProps) {
|
|
44
|
+
super(props);
|
|
45
|
+
this.setProps(this.props);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
setProps(props: Partial<IconWidgetProps>) {
|
|
49
|
+
this.placement = props.placement ?? this.placement;
|
|
50
|
+
this.viewId = props.viewId;
|
|
51
|
+
super.setProps(props);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
onRenderHTML(rootElement: HTMLElement): void {
|
|
55
|
+
const {className, style, icon, color, label, onClick} = this.props;
|
|
56
|
+
|
|
57
|
+
render(
|
|
58
|
+
<IconButton
|
|
59
|
+
className={className}
|
|
60
|
+
style={style as JSX.CSSProperties}
|
|
61
|
+
color={color}
|
|
62
|
+
icon={icon}
|
|
63
|
+
label={label}
|
|
64
|
+
onClick={onClick}
|
|
65
|
+
/>,
|
|
66
|
+
rootElement
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -15,22 +15,23 @@ export {GeocoderWidget as _GeocoderWidget} from './geocoder-widget';
|
|
|
15
15
|
// View widgets
|
|
16
16
|
export {FullscreenWidget} from './fullscreen-widget';
|
|
17
17
|
export {SplitterWidget as _SplitterWidget} from './splitter-widget';
|
|
18
|
-
export {ViewSelectorWidget as _ViewSelectorWidget} from './view-selector-widget';
|
|
19
18
|
|
|
20
19
|
// Information widgets
|
|
21
|
-
export {InfoWidget
|
|
20
|
+
export {InfoWidget} from './info-widget';
|
|
22
21
|
export {PopupWidget} from './popup-widget';
|
|
23
|
-
export {ContextMenuWidget
|
|
22
|
+
export {ContextMenuWidget} from './context-menu-widget';
|
|
24
23
|
export {ScrollbarWidget} from './scrollbar-widget';
|
|
25
24
|
|
|
26
25
|
// Control widgets
|
|
26
|
+
export {IconWidget} from './icon-widget';
|
|
27
|
+
export {ToggleWidget} from './toggle-widget';
|
|
28
|
+
export {SelectorWidget} from './selector-widget';
|
|
27
29
|
export {TimelineWidget as _TimelineWidget} from './timeline-widget';
|
|
28
30
|
|
|
29
31
|
// Utility widgets
|
|
30
32
|
export {ScreenshotWidget} from './screenshot-widget';
|
|
31
|
-
export {ThemeWidget
|
|
32
|
-
export {LoadingWidget
|
|
33
|
-
export {FpsWidget as _FpsWidget} from './fps-widget';
|
|
33
|
+
export {ThemeWidget} from './theme-widget';
|
|
34
|
+
export {LoadingWidget} from './loading-widget';
|
|
34
35
|
export {StatsWidget as _StatsWidget} from './stats-widget';
|
|
35
36
|
|
|
36
37
|
export type {FullscreenWidgetProps} from './fullscreen-widget';
|
|
@@ -40,15 +41,17 @@ export type {ScreenshotWidgetProps} from './screenshot-widget';
|
|
|
40
41
|
export type {ResetViewWidgetProps} from './reset-view-widget';
|
|
41
42
|
export type {GeocoderWidgetProps} from './geocoder-widget';
|
|
42
43
|
export type {LoadingWidgetProps} from './loading-widget';
|
|
43
|
-
export type {
|
|
44
|
+
export type {IconWidgetProps} from './icon-widget';
|
|
45
|
+
export type {ToggleWidgetProps} from './toggle-widget';
|
|
44
46
|
export type {ScaleWidgetProps} from './scale-widget';
|
|
45
47
|
export type {ThemeWidgetProps} from './theme-widget';
|
|
46
48
|
export type {InfoWidgetProps} from './info-widget';
|
|
49
|
+
export type {PopupWidgetProps} from './popup-widget';
|
|
47
50
|
export type {StatsWidgetProps} from './stats-widget';
|
|
48
51
|
export type {ContextMenuWidgetProps} from './context-menu-widget';
|
|
49
52
|
export type {SplitterWidgetProps} from './splitter-widget';
|
|
50
53
|
export type {TimelineWidgetProps} from './timeline-widget';
|
|
51
|
-
export type {
|
|
54
|
+
export type {SelectorWidgetProps} from './selector-widget';
|
|
52
55
|
export type {GimbalWidgetProps} from './gimbal-widget';
|
|
53
56
|
export type {ContentBounds, ScrollbarWidgetProps, ScrollbarDecoration} from './scrollbar-widget';
|
|
54
57
|
|
|
@@ -64,7 +67,6 @@ export {
|
|
|
64
67
|
SimpleMenu as _SimpleMenu,
|
|
65
68
|
type SimpleMenuProps
|
|
66
69
|
} from './lib/components/dropdown-menu';
|
|
67
|
-
export {IconMenu as _IconMenu, type IconMenuProps} from './lib/components/icon-menu';
|
|
68
70
|
export {
|
|
69
71
|
RangeInput as _RangeInput,
|
|
70
72
|
type RangeInputProps,
|
package/src/info-widget.tsx
CHANGED
|
@@ -81,6 +81,13 @@ export class InfoWidget extends Widget<InfoWidgetProps> {
|
|
|
81
81
|
this.deck = deck;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
onRemove() {
|
|
85
|
+
// Invoke clean up of preact hooks
|
|
86
|
+
if (this.rootElement) {
|
|
87
|
+
render(null, this.rootElement);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
84
91
|
onViewportChange(viewport) {
|
|
85
92
|
this.viewport = viewport;
|
|
86
93
|
this.updateHTML();
|
|
@@ -4,12 +4,20 @@
|
|
|
4
4
|
|
|
5
5
|
import {type JSX, type ComponentChild} from 'preact';
|
|
6
6
|
import {useState, useRef, useEffect} from 'preact/hooks';
|
|
7
|
+
import {getCSSMask} from '../data-url';
|
|
7
8
|
|
|
8
|
-
export type MenuItem =
|
|
9
|
+
export type MenuItem =
|
|
10
|
+
| string
|
|
11
|
+
| {
|
|
12
|
+
value?: string;
|
|
13
|
+
label: string;
|
|
14
|
+
icon?: string;
|
|
15
|
+
onSelect?: () => void;
|
|
16
|
+
};
|
|
9
17
|
|
|
10
18
|
export type DropdownMenuProps = {
|
|
11
19
|
menuItems: MenuItem[];
|
|
12
|
-
onSelect
|
|
20
|
+
onSelect?: (value: string) => void;
|
|
13
21
|
style?: Partial<CSSStyleDeclaration>;
|
|
14
22
|
};
|
|
15
23
|
|
|
@@ -52,22 +60,24 @@ export type SimpleMenuProps = DropdownMenuProps & {
|
|
|
52
60
|
export const SimpleMenu = (props: SimpleMenuProps) => {
|
|
53
61
|
const dropdownRef = useRef<HTMLDivElement>(null);
|
|
54
62
|
|
|
55
|
-
const handleClickOutside = (event: MouseEvent) => {
|
|
56
|
-
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
|
|
57
|
-
props.onClose();
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
|
|
61
63
|
useEffect(() => {
|
|
64
|
+
const handleClickOutside = (event: MouseEvent) => {
|
|
65
|
+
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
|
|
66
|
+
props.onClose();
|
|
67
|
+
}
|
|
68
|
+
};
|
|
62
69
|
document.addEventListener('mousedown', handleClickOutside);
|
|
63
70
|
return () => {
|
|
64
71
|
document.removeEventListener('mousedown', handleClickOutside);
|
|
65
72
|
};
|
|
66
73
|
}, []);
|
|
67
74
|
|
|
68
|
-
const handleSelect = (value
|
|
75
|
+
const handleSelect = (value: string | undefined, item: MenuItem) => {
|
|
69
76
|
if (value) {
|
|
70
|
-
|
|
77
|
+
if (typeof item === 'object') {
|
|
78
|
+
item.onSelect?.();
|
|
79
|
+
}
|
|
80
|
+
props.onSelect?.(value);
|
|
71
81
|
props.onClose();
|
|
72
82
|
}
|
|
73
83
|
};
|
|
@@ -89,13 +99,10 @@ export const SimpleMenu = (props: SimpleMenuProps) => {
|
|
|
89
99
|
<li
|
|
90
100
|
className={`deck-widget-dropdown-item ${value ? '' : 'disabled'}`}
|
|
91
101
|
key={i}
|
|
92
|
-
onClick={() => handleSelect(value)}
|
|
102
|
+
onClick={() => handleSelect(value, item)}
|
|
93
103
|
>
|
|
94
104
|
{icon && (
|
|
95
|
-
<span
|
|
96
|
-
className="deck-widget-dropdown-item-icon"
|
|
97
|
-
style={{maskImage: `url("${icon}")`, WebkitMaskImage: `url("${icon}")`}}
|
|
98
|
-
/>
|
|
105
|
+
<span className="deck-widget-dropdown-item-icon" style={getCSSMask(icon)} />
|
|
99
106
|
)}
|
|
100
107
|
{getMenuItemLabel(item)}
|
|
101
108
|
</li>
|
|
@@ -3,26 +3,38 @@
|
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
5
|
import type {ComponentChildren, JSX} from 'preact';
|
|
6
|
+
import {useMemo} from 'preact/hooks';
|
|
7
|
+
import {getCSSMask} from '../data-url';
|
|
6
8
|
|
|
7
9
|
export type IconButtonProps = {
|
|
8
10
|
className?: string;
|
|
11
|
+
icon?: string;
|
|
9
12
|
label?: string;
|
|
13
|
+
color?: string;
|
|
14
|
+
style?: JSX.CSSProperties;
|
|
10
15
|
onClick?: JSX.MouseEventHandler<HTMLButtonElement>;
|
|
11
16
|
children?: ComponentChildren;
|
|
12
17
|
};
|
|
13
18
|
|
|
14
19
|
/** Renders a button component with widget CSS */
|
|
15
20
|
export const IconButton = (props: IconButtonProps) => {
|
|
16
|
-
const {className = '', label, onClick, children} = props;
|
|
21
|
+
const {className = '', style, color, icon, label, onClick, children} = props;
|
|
22
|
+
|
|
23
|
+
const iconStyle = useMemo(() => {
|
|
24
|
+
const css: JSX.CSSProperties | undefined = getCSSMask(icon);
|
|
25
|
+
if (!color) return css;
|
|
26
|
+
return {...css, backgroundColor: color};
|
|
27
|
+
}, [color, icon]);
|
|
28
|
+
|
|
17
29
|
return (
|
|
18
|
-
<div className="deck-widget-button">
|
|
30
|
+
<div className="deck-widget-button" style={style}>
|
|
19
31
|
<button
|
|
20
32
|
className={`deck-widget-icon-button ${className}`}
|
|
21
33
|
type="button"
|
|
22
34
|
onClick={onClick}
|
|
23
35
|
title={label}
|
|
24
36
|
>
|
|
25
|
-
{children ? children : <div className="deck-widget-icon" />}
|
|
37
|
+
{children ? children : <div className="deck-widget-icon" style={iconStyle} />}
|
|
26
38
|
</button>
|
|
27
39
|
</div>
|
|
28
40
|
);
|
package/src/popup-widget.tsx
CHANGED
|
@@ -90,6 +90,13 @@ export class PopupWidget extends Widget<PopupWidgetProps> {
|
|
|
90
90
|
this.deck = deck;
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
onRemove() {
|
|
94
|
+
// Invoke clean up of preact hooks
|
|
95
|
+
if (this.rootElement) {
|
|
96
|
+
render(null, this.rootElement);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
93
100
|
onViewportChange(viewport) {
|
|
94
101
|
this.viewport = viewport;
|
|
95
102
|
this.updateHTML();
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// deck.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import {render} from 'preact';
|
|
6
|
+
import {Widget, type WidgetProps, type WidgetPlacement} from '@deck.gl/core';
|
|
7
|
+
import {SimpleMenu, type MenuItem} from './lib/components/dropdown-menu';
|
|
8
|
+
import {Popover, type PopoverProps} from './lib/components/popover';
|
|
9
|
+
import {IconButton} from './lib/components/icon-button';
|
|
10
|
+
|
|
11
|
+
export type SelectorWidgetOption<ValueT = string> = {
|
|
12
|
+
value: ValueT;
|
|
13
|
+
icon: string;
|
|
14
|
+
label?: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/** Properties for the ViewSelectorWidget */
|
|
18
|
+
export type SelectorWidgetProps<ValueT = string> = WidgetProps & {
|
|
19
|
+
/** Widget positioning within the view. Default 'top-left'. */
|
|
20
|
+
placement?: WidgetPlacement;
|
|
21
|
+
/** View to attach to and interact with. Required when using multiple views. */
|
|
22
|
+
viewId?: string | null;
|
|
23
|
+
options: SelectorWidgetOption<ValueT>[];
|
|
24
|
+
/** The initial value. Default to the first option. */
|
|
25
|
+
initialValue?: ValueT;
|
|
26
|
+
/** Callback invoked when the value changes */
|
|
27
|
+
onChange?: (value: ValueT) => void;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A widget that renders a popup menu for selecting a view mode.
|
|
32
|
+
* It displays a button with the current view mode icon. Clicking the button
|
|
33
|
+
* toggles a popup that shows three icons for:
|
|
34
|
+
* - Single view
|
|
35
|
+
* - Two views, split horizontally
|
|
36
|
+
* - Two views, split vertically
|
|
37
|
+
*/
|
|
38
|
+
export class SelectorWidget<ValueT = string> extends Widget<SelectorWidgetProps<ValueT>> {
|
|
39
|
+
static defaultProps: Required<SelectorWidgetProps> = {
|
|
40
|
+
...Widget.defaultProps,
|
|
41
|
+
id: 'view-selector',
|
|
42
|
+
placement: 'top-left',
|
|
43
|
+
viewId: null,
|
|
44
|
+
initialValue: '',
|
|
45
|
+
options: [],
|
|
46
|
+
onChange: () => {}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
className = 'deck-widget-selector';
|
|
50
|
+
placement: WidgetPlacement = 'top-left';
|
|
51
|
+
value: ValueT;
|
|
52
|
+
isOpen: {x: number; y: number; placement: PopoverProps['placement']} | false = false;
|
|
53
|
+
|
|
54
|
+
constructor(props: SelectorWidgetProps<ValueT>) {
|
|
55
|
+
super(props);
|
|
56
|
+
this.value = this.props.initialValue;
|
|
57
|
+
this.setProps(this.props);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
setProps(props: Partial<SelectorWidgetProps<ValueT>>) {
|
|
61
|
+
this.placement = props.placement ?? this.placement;
|
|
62
|
+
this.viewId = props.viewId ?? this.viewId;
|
|
63
|
+
super.setProps(props);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
onRenderHTML(rootElement: HTMLElement) {
|
|
67
|
+
const selectedOption =
|
|
68
|
+
this.props.options.find(opt => opt.value === this.value) ?? this.props.options[0];
|
|
69
|
+
|
|
70
|
+
render(
|
|
71
|
+
<div>
|
|
72
|
+
<IconButton
|
|
73
|
+
icon={selectedOption.icon}
|
|
74
|
+
label={selectedOption.label}
|
|
75
|
+
onClick={this._toggleMenu}
|
|
76
|
+
/>
|
|
77
|
+
{this.isOpen && (
|
|
78
|
+
<Popover {...this.isOpen}>
|
|
79
|
+
<SimpleMenu
|
|
80
|
+
isOpen
|
|
81
|
+
style={{pointerEvents: 'auto', position: 'static'}}
|
|
82
|
+
menuItems={this.props.options as MenuItem[]}
|
|
83
|
+
onSelect={this._handleSelectMode}
|
|
84
|
+
onClose={this._toggleMenu}
|
|
85
|
+
/>
|
|
86
|
+
</Popover>
|
|
87
|
+
)}
|
|
88
|
+
</div>,
|
|
89
|
+
rootElement
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private _toggleMenu = () => {
|
|
94
|
+
if (this.isOpen) {
|
|
95
|
+
this.isOpen = false;
|
|
96
|
+
} else if (this.rootElement) {
|
|
97
|
+
this.isOpen = {
|
|
98
|
+
x: this.rootElement.offsetLeft,
|
|
99
|
+
y: this.rootElement.offsetTop,
|
|
100
|
+
placement: this.props.placement.includes('right') ? 'left-start' : 'right-start'
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
this.updateHTML();
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
private _handleSelectMode = (value: string) => {
|
|
107
|
+
this.value = value as ValueT;
|
|
108
|
+
this.props.onChange(value as ValueT);
|
|
109
|
+
this.updateHTML();
|
|
110
|
+
};
|
|
111
|
+
}
|