@fusion.dev/helix-headless 0.104.1 → 0.106.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +10386 -3813
- package/dist/accordion/item/accordion-item.d.ts +17 -16
- package/dist/accordion/root/accordion-root.d.ts +13 -17
- package/dist/announcement/root/announcement-root.d.ts +24 -31
- package/dist/app-header/root/app-header-root.d.ts +14 -14
- package/dist/area-chart/root/area-chart-root.d.ts +29 -48
- package/dist/avatar/group/avatar-group.d.ts +6 -8
- package/dist/avatar/root/avatar-root.d.ts +11 -11
- package/dist/badge/root/badge-root.d.ts +14 -15
- package/dist/bar-chart/root/bar-chart-root.d.ts +40 -44
- package/dist/blockquote/root/blockquote-root.d.ts +5 -7
- package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +25 -33
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +12 -11
- package/dist/button/root/button-root.d.ts +16 -17
- package/dist/button-group/root/button-group-root.d.ts +9 -10
- package/dist/callout/root/callout-root.d.ts +10 -15
- package/dist/canvas/edge/canvas-edge.d.ts +21 -21
- package/dist/canvas/node/canvas-node.d.ts +43 -45
- package/dist/canvas/root/canvas-root.d.ts +100 -99
- package/dist/card/root/card-root.d.ts +10 -12
- package/dist/carousel/root/carousel-root.d.ts +32 -33
- package/dist/chat/composer/chat-composer.d.ts +24 -26
- package/dist/chat/message/chat-message.d.ts +30 -33
- package/dist/chat/root/chat-root.d.ts +63 -80
- package/dist/checkbox/root/checkbox-root.d.ts +30 -32
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +25 -25
- package/dist/code/root/code-root.d.ts +6 -10
- package/dist/code-block/root/code-block-root.d.ts +35 -48
- package/dist/color-input/root/color-input-root.d.ts +62 -56
- package/dist/color-input/root/color-input-root.js +3 -0
- package/dist/color-picker/root/color-picker-root.d.ts +61 -49
- package/dist/color-picker/root/color-picker-root.js +4 -0
- package/dist/combobox/root/combobox-root.d.ts +52 -53
- package/dist/command/root/command-root.d.ts +40 -40
- package/dist/command/root/command-root.js +1 -0
- package/dist/copy-button/root/copy-button-root.d.ts +24 -26
- package/dist/data-table/root/data-table-root.d.ts +106 -107
- package/dist/date-input/root/date-input-root.d.ts +54 -53
- package/dist/date-picker/root/date-picker-root.d.ts +25 -21
- package/dist/description-list/item/description-list-item.d.ts +7 -7
- package/dist/description-list/root/description-list-root.d.ts +10 -15
- package/dist/dialog/root/dialog-root.d.ts +22 -19
- package/dist/divider/root/divider-root.d.ts +12 -13
- package/dist/donut-chart/root/donut-chart-root.d.ts +19 -20
- package/dist/drawer/root/drawer-root.d.ts +19 -18
- package/dist/drilldown/item/drilldown-item.d.ts +28 -28
- package/dist/drilldown/root/drilldown-root.d.ts +22 -28
- package/dist/element-events.generated.js +19 -1
- package/dist/empty/root/empty-root.d.ts +16 -19
- package/dist/file-input/root/file-input-root.d.ts +32 -32
- package/dist/filter-input/chip/filter-chip.d.ts +36 -39
- package/dist/filter-input/field/filter-field.d.ts +25 -31
- package/dist/filter-input/menu/filter-menu.d.ts +50 -47
- package/dist/filter-input/operator/filter-operator.d.ts +15 -20
- package/dist/filter-input/root/filter-input-root.d.ts +80 -98
- package/dist/format-date/root/format-date-root.d.ts +19 -27
- package/dist/heatmap/root/heatmap-root.d.ts +40 -41
- package/dist/icon/root/icon-root.d.ts +21 -23
- package/dist/icon-button/root/icon-button-root.d.ts +12 -14
- package/dist/image/root/image-root.d.ts +30 -30
- package/dist/input/root/input-root.d.ts +36 -35
- package/dist/kbd/root/kbd-root.d.ts +13 -15
- package/dist/legend/root/legend-root.d.ts +18 -16
- package/dist/lightbox/item/lightbox-item.d.ts +13 -15
- package/dist/lightbox/root/lightbox-root.d.ts +40 -41
- package/dist/line-chart/root/line-chart-root.d.ts +20 -29
- package/dist/list/item/list-item.d.ts +17 -22
- package/dist/list/root/list-root.d.ts +6 -7
- package/dist/listbox/root/listbox-root.d.ts +42 -41
- package/dist/loader/root/loader-root.d.ts +16 -20
- package/dist/map/area/map-area.d.ts +48 -0
- package/dist/map/area/map-area.js +40 -0
- package/dist/map/buildings/map-buildings.d.ts +45 -0
- package/dist/map/buildings/map-buildings.js +37 -0
- package/dist/map/contours/map-contours.d.ts +61 -0
- package/dist/map/contours/map-contours.js +54 -0
- package/dist/map/index.d.ts +14 -0
- package/dist/map/index.js +10 -0
- package/dist/map/landcover/map-landcover.d.ts +47 -0
- package/dist/map/landcover/map-landcover.js +37 -0
- package/dist/map/marker/map-marker.d.ts +120 -0
- package/dist/map/marker/map-marker.js +109 -0
- package/dist/map/points/map-points.d.ts +139 -0
- package/dist/map/points/map-points.js +161 -0
- package/dist/map/position/map-position.d.ts +70 -0
- package/dist/map/position/map-position.js +89 -0
- package/dist/map/raster/map-raster.d.ts +84 -0
- package/dist/map/raster/map-raster.js +96 -0
- package/dist/map/root/map-root.d.ts +269 -52
- package/dist/map/root/map-root.js +473 -5
- package/dist/map/route/map-route.d.ts +73 -0
- package/dist/map/route/map-route.js +52 -0
- package/dist/map/terrain/map-terrain.d.ts +68 -0
- package/dist/map/terrain/map-terrain.js +58 -0
- package/dist/megamenu/root/megamenu-root.d.ts +27 -25
- package/dist/menu/item/menu-item.d.ts +30 -31
- package/dist/menu/root/menu-root.d.ts +25 -29
- package/dist/meter/root/meter-root.d.ts +22 -21
- package/dist/navigation/root/navigation-root.d.ts +13 -16
- package/dist/notifications/group/notification-group.d.ts +27 -28
- package/dist/notifications/notification/notification.d.ts +35 -42
- package/dist/notifications/root/notifications-root.d.ts +22 -24
- package/dist/number-input/root/number-input-root.d.ts +46 -50
- package/dist/object-inspector/root/object-inspector-root.d.ts +46 -58
- package/dist/option/group/option-group.d.ts +11 -11
- package/dist/option/root/option-root.d.ts +28 -33
- package/dist/outline/root/outline-root.d.ts +18 -17
- package/dist/pagination/root/pagination-root.d.ts +37 -39
- package/dist/pagination/size/pagination-size.d.ts +37 -43
- package/dist/pagination/summary/pagination-summary.d.ts +12 -14
- package/dist/pin-input/root/pin-input-root.d.ts +32 -38
- package/dist/popover/root/popover-root.d.ts +16 -21
- package/dist/progress/root/progress-root.d.ts +16 -14
- package/dist/qr-code/root/qr-code-root.d.ts +22 -25
- package/dist/quote/root/quote-root.d.ts +5 -6
- package/dist/radio/group/radio-group.d.ts +26 -28
- package/dist/radio/root/radio-root.d.ts +24 -28
- package/dist/rating/root/rating-root.d.ts +27 -30
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +43 -55
- package/dist/scroll-area/root/scroll-area-root.d.ts +15 -21
- package/dist/select/root/select-root.d.ts +41 -44
- package/dist/skeleton/root/skeleton-root.d.ts +7 -8
- package/dist/skip-link/root/skip-link-root.d.ts +21 -28
- package/dist/slider/root/slider-root.d.ts +36 -39
- package/dist/sparkline/root/sparkline-root.d.ts +22 -28
- package/dist/speed-dial/item/speed-dial-item.d.ts +21 -21
- package/dist/speed-dial/root/speed-dial-root.d.ts +25 -27
- package/dist/splitter/root/splitter-root.d.ts +37 -41
- package/dist/stat/group/stat-group.d.ts +4 -4
- package/dist/stat/root/stat-root.d.ts +8 -9
- package/dist/steps/root/steps-root.d.ts +11 -14
- package/dist/steps/step/step.d.ts +22 -29
- package/dist/switch/root/switch-root.d.ts +20 -24
- package/dist/table/cell/table-cell.d.ts +18 -8
- package/dist/table/cell/table-cell.js +5 -1
- package/dist/table/column/table-column.d.ts +62 -55
- package/dist/table/root/table-root.d.ts +16 -17
- package/dist/table/row/table-row.d.ts +3 -3
- package/dist/tabs/panel/tab-panel.d.ts +3 -3
- package/dist/tabs/root/tabs-root.d.ts +19 -17
- package/dist/tabs/tab/tab.d.ts +6 -6
- package/dist/tag/root/tag-root.d.ts +11 -12
- package/dist/textarea/root/textarea-root.d.ts +29 -32
- package/dist/time-input/root/time-input-root.d.ts +70 -69
- package/dist/time-picker/root/time-picker-root.d.ts +58 -66
- package/dist/timeline/item/timeline-item.d.ts +18 -24
- package/dist/timeline/root/timeline-root.d.ts +13 -21
- package/dist/toast/item/toast-item.d.ts +21 -22
- package/dist/toast/root/toast-root.d.ts +18 -23
- package/dist/toggle/group/toggle-group.d.ts +23 -25
- package/dist/toggle/root/toggle-root.d.ts +8 -8
- package/dist/toolbar/root/toolbar-root.d.ts +7 -10
- package/dist/tooltip/root/tooltip-root.d.ts +41 -47
- package/dist/tour/root/tour-root.d.ts +24 -26
- package/dist/tour/stop/tour-stop.d.ts +39 -48
- package/dist/tree/item/tree-item.d.ts +23 -25
- package/dist/tree/root/tree-root.d.ts +13 -12
- package/dist/trend/root/trend-root.d.ts +18 -19
- package/dist/video/root/video-root.d.ts +108 -101
- package/dist/video-playlist/item/video-playlist-item.d.ts +23 -28
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +17 -21
- package/dist/video-playlist/root/video-playlist-root.d.ts +21 -25
- package/dist/virtual-list/root/virtual-list-root.d.ts +27 -26
- package/package.json +5 -5
- package/types/jsx.d.ts +14011 -11983
- package/types/svelte.d.ts +10 -0
- package/types/vue.d.ts +2143 -1497
|
@@ -4,13 +4,423 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { customElement, HelixElement, HelixMapPanEvent, HelixMapZoomEvent, hostAria, MixinViewport, } from '@fusion.dev/helix-core';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { customElement, HelixActivateEvent, HelixElement, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, hostAria, KeyboardNavigationController, MixinViewport, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { buildings, cloudRain, dotsNine, leaf, mountains, path, polygon, stack, target, } from '@fusion.dev/helix-icons';
|
|
9
|
+
import { html, nothing } from 'lit';
|
|
10
|
+
import { property, state } from 'lit/decorators.js';
|
|
11
|
+
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
12
|
+
const MAP_TYPES = ['standard', 'hybrid', 'satellite'];
|
|
13
|
+
const iconOf = (layer) => {
|
|
14
|
+
switch (layer?.layerKind) {
|
|
15
|
+
case 'route':
|
|
16
|
+
return path;
|
|
17
|
+
case 'area':
|
|
18
|
+
return polygon;
|
|
19
|
+
case 'points':
|
|
20
|
+
return dotsNine;
|
|
21
|
+
case 'buildings':
|
|
22
|
+
return buildings;
|
|
23
|
+
case 'terrain':
|
|
24
|
+
return mountains;
|
|
25
|
+
case 'contours':
|
|
26
|
+
return target;
|
|
27
|
+
case 'landcover':
|
|
28
|
+
return leaf;
|
|
29
|
+
case 'raster':
|
|
30
|
+
return cloudRain;
|
|
31
|
+
default:
|
|
32
|
+
return stack;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const ROTATE_STEP = 15;
|
|
36
|
+
const TILT_STEP = 10;
|
|
37
|
+
const TILTED = 50;
|
|
10
38
|
let HelixHeadlessMap = class HelixHeadlessMap extends MixinViewport(HelixElement) {
|
|
11
39
|
constructor() {
|
|
12
40
|
super(...arguments);
|
|
41
|
+
this.bearing = 0;
|
|
42
|
+
this.cluster = false;
|
|
43
|
+
this.faceNorthLabel = 'Face north';
|
|
44
|
+
this.hybridLabel = 'Hybrid';
|
|
13
45
|
this.label = '';
|
|
46
|
+
this.layersLabel = 'Map layers';
|
|
47
|
+
this.mapPreviews = {};
|
|
48
|
+
this.mapTypeLabel = 'Map type';
|
|
49
|
+
this.pitch = 0;
|
|
50
|
+
this.rotateLeftLabel = 'Rotate left';
|
|
51
|
+
this.rotateRightLabel = 'Rotate right';
|
|
52
|
+
this.satelliteLabel = 'Satellite';
|
|
53
|
+
this.standardLabel = 'Standard';
|
|
54
|
+
this.tiltLabel = 'Show in 3D';
|
|
55
|
+
this.layersOpen = false;
|
|
56
|
+
this.handleOutside = (event) => {
|
|
57
|
+
if (!event.composedPath().includes(this)) {
|
|
58
|
+
this.layersOpen = false;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
this.handleMenuKeydown = (event) => {
|
|
62
|
+
event.stopPropagation();
|
|
63
|
+
if (event.key === 'Escape' && this.layersOpen) {
|
|
64
|
+
this.layersOpen = false;
|
|
65
|
+
this.renderRoot.querySelector('[part="layers-toggle"]')?.focus();
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
this.handlePartChange = (event) => {
|
|
69
|
+
if (event.detail.kind !== 'place') {
|
|
70
|
+
this.requestUpdate();
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
this.stop = 0;
|
|
74
|
+
this.keys = new KeyboardNavigationController(this, {
|
|
75
|
+
items: () => this.markers.map((marker, at) => ({
|
|
76
|
+
contains: (node) => node !== null && (marker.contains(node) || marker.shadowRoot?.contains(node) === true),
|
|
77
|
+
disabled: marker.gatheredBy !== undefined,
|
|
78
|
+
focusItem: () => {
|
|
79
|
+
this.stop = at;
|
|
80
|
+
marker.focus();
|
|
81
|
+
},
|
|
82
|
+
select: () => { },
|
|
83
|
+
selected: false,
|
|
84
|
+
})),
|
|
85
|
+
origin: 'focus',
|
|
86
|
+
selects: () => false,
|
|
87
|
+
});
|
|
88
|
+
this.handleFocusIn = (event) => {
|
|
89
|
+
const marker = this.markerOf(event);
|
|
90
|
+
const at = marker ? this.markers.indexOf(marker) : -1;
|
|
91
|
+
if (at !== -1) {
|
|
92
|
+
this.stop = at;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
this.handleClick = (event) => {
|
|
96
|
+
const marker = this.markerOf(event);
|
|
97
|
+
if (marker) {
|
|
98
|
+
this.activate(marker);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
this.handleMarkerKeydown = (event) => {
|
|
102
|
+
const marker = this.markerOf(event);
|
|
103
|
+
if (!marker || (event.key !== 'Enter' && event.key !== ' ')) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
event.preventDefault();
|
|
107
|
+
if (event.key === 'Enter' && !event.repeat) {
|
|
108
|
+
this.activate(marker);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
this.handleMarkerKeyup = (event) => {
|
|
112
|
+
const marker = this.markerOf(event);
|
|
113
|
+
if (marker && event.key === ' ') {
|
|
114
|
+
event.preventDefault();
|
|
115
|
+
this.activate(marker);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
this.handleSlotChange = () => {
|
|
119
|
+
this.requestUpdate();
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
get layers() {
|
|
123
|
+
return this.knownChildren.filter((child) => child.isMapLayer === true);
|
|
124
|
+
}
|
|
125
|
+
get imagery() {
|
|
126
|
+
return this.layers.filter((layer) => layer.layerKind === 'raster' && layer.ground === true);
|
|
127
|
+
}
|
|
128
|
+
nameOf(type) {
|
|
129
|
+
return type === 'hybrid'
|
|
130
|
+
? this.hybridLabel
|
|
131
|
+
: type === 'satellite'
|
|
132
|
+
? this.satelliteLabel
|
|
133
|
+
: this.standardLabel;
|
|
134
|
+
}
|
|
135
|
+
showLayers(layers, shown) {
|
|
136
|
+
for (const layer of layers) {
|
|
137
|
+
layer.hidden = !shown;
|
|
138
|
+
}
|
|
139
|
+
this.requestUpdate();
|
|
140
|
+
}
|
|
141
|
+
get layerEntries() {
|
|
142
|
+
const entries = [];
|
|
143
|
+
const groups = new Map();
|
|
144
|
+
const imagery = this.imagery;
|
|
145
|
+
for (const layer of this.layers.filter((one) => !imagery.includes(one))) {
|
|
146
|
+
const had = layer.group ? groups.get(layer.group) : undefined;
|
|
147
|
+
if (had) {
|
|
148
|
+
had.push(layer);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
const entry = [layer];
|
|
152
|
+
entries.push(entry);
|
|
153
|
+
if (layer.group) {
|
|
154
|
+
groups.set(layer.group, entry);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return entries;
|
|
158
|
+
}
|
|
159
|
+
get markers() {
|
|
160
|
+
return this.knownChildren.filter((child) => child.isMapMarker === true);
|
|
161
|
+
}
|
|
162
|
+
markerOf(event) {
|
|
163
|
+
return event
|
|
164
|
+
.composedPath()
|
|
165
|
+
.find((one) => one.isMapMarker === true);
|
|
166
|
+
}
|
|
167
|
+
activate(marker) {
|
|
168
|
+
if (marker.gathered.length > 1) {
|
|
169
|
+
marker.dispatchEvent(new HelixMapClusterEvent({ labels: [...marker.gathered] }));
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
this.dispatchEvent(new HelixActivateEvent({ value: marker.name || marker.label || '' }));
|
|
173
|
+
}
|
|
174
|
+
connectedCallback() {
|
|
175
|
+
super.connectedCallback();
|
|
176
|
+
this.addEventListener(HelixMapPartChangeEvent.eventName, this.handlePartChange);
|
|
177
|
+
this.addEventListener('click', this.handleClick);
|
|
178
|
+
this.addEventListener('focusin', this.handleFocusIn);
|
|
179
|
+
this.addEventListener('keydown', this.handleMarkerKeydown);
|
|
180
|
+
this.addEventListener('keyup', this.handleMarkerKeyup);
|
|
181
|
+
this.hiding = new MutationObserver(() => this.requestUpdate());
|
|
182
|
+
this.hiding.observe(this, { attributeFilter: ['hidden'], attributes: true, subtree: true });
|
|
183
|
+
}
|
|
184
|
+
disconnectedCallback() {
|
|
185
|
+
super.disconnectedCallback();
|
|
186
|
+
this.hiding?.disconnect();
|
|
187
|
+
document.removeEventListener('pointerdown', this.handleOutside);
|
|
188
|
+
this.removeEventListener(HelixMapPartChangeEvent.eventName, this.handlePartChange);
|
|
189
|
+
this.removeEventListener('click', this.handleClick);
|
|
190
|
+
this.removeEventListener('focusin', this.handleFocusIn);
|
|
191
|
+
this.removeEventListener('keydown', this.handleMarkerKeydown);
|
|
192
|
+
this.removeEventListener('keyup', this.handleMarkerKeyup);
|
|
193
|
+
}
|
|
194
|
+
updated(changed) {
|
|
195
|
+
super.updated(changed);
|
|
196
|
+
const photographed = this.mapType !== undefined;
|
|
197
|
+
for (const layer of this.imagery) {
|
|
198
|
+
if (layer.hidden === photographed) {
|
|
199
|
+
layer.hidden = !photographed;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (changed.has('mapType')) {
|
|
203
|
+
this.dispatchEvent(new HelixMapPartChangeEvent({ kind: 'layer' }));
|
|
204
|
+
}
|
|
205
|
+
if (changed.has('layersOpen')) {
|
|
206
|
+
if (this.layersOpen) {
|
|
207
|
+
document.addEventListener('pointerdown', this.handleOutside);
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
document.removeEventListener('pointerdown', this.handleOutside);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
const markers = this.markers;
|
|
214
|
+
const on = markers[Math.min(this.stop, markers.length - 1)];
|
|
215
|
+
const stop = on?.gatheredBy ?? on;
|
|
216
|
+
for (const marker of markers) {
|
|
217
|
+
marker.current = marker === stop;
|
|
218
|
+
}
|
|
219
|
+
if (changed.has('cluster')) {
|
|
220
|
+
this.dispatchEvent(new HelixMapPartChangeEvent({ kind: 'place' }));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
rotate(by) {
|
|
224
|
+
this.dispatchEvent(new HelixMapRotateEvent({ by }));
|
|
225
|
+
}
|
|
226
|
+
faceNorth() {
|
|
227
|
+
this.dispatchEvent(new HelixMapRotateEvent({ to: 0 }));
|
|
228
|
+
}
|
|
229
|
+
tilt(by) {
|
|
230
|
+
this.dispatchEvent(new HelixMapTiltEvent({ by }));
|
|
231
|
+
}
|
|
232
|
+
tiltTo(to) {
|
|
233
|
+
this.dispatchEvent(new HelixMapTiltEvent({ to }));
|
|
234
|
+
}
|
|
235
|
+
renderLayersMenu() {
|
|
236
|
+
const layers = this.layers;
|
|
237
|
+
if (!this.drawsControls('layers') || layers.length === 0) {
|
|
238
|
+
return nothing;
|
|
239
|
+
}
|
|
240
|
+
const entries = this.layerEntries;
|
|
241
|
+
return html `<button
|
|
242
|
+
part="layers-toggle"
|
|
243
|
+
aria-controls="layers-menu"
|
|
244
|
+
aria-expanded=${this.layersOpen ? 'true' : 'false'}
|
|
245
|
+
aria-label=${this.layersLabel}
|
|
246
|
+
type="button"
|
|
247
|
+
@click=${() => {
|
|
248
|
+
this.layersOpen = !this.layersOpen;
|
|
249
|
+
if (this.layersOpen) {
|
|
250
|
+
this.dispatchEvent(new HelixMapPartChangeEvent({ kind: 'menu' }));
|
|
251
|
+
}
|
|
252
|
+
}}
|
|
253
|
+
@keydown=${this.handleMenuKeydown}
|
|
254
|
+
>
|
|
255
|
+
<svg aria-hidden="true" fill="currentColor" height="16" viewBox=${stack.viewBox} width="16">
|
|
256
|
+
${unsafeSVG(stack.content)}
|
|
257
|
+
</svg>
|
|
258
|
+
</button>
|
|
259
|
+
<div
|
|
260
|
+
part="layers-menu"
|
|
261
|
+
id="layers-menu"
|
|
262
|
+
role="group"
|
|
263
|
+
aria-label=${this.layersLabel}
|
|
264
|
+
?hidden=${!this.layersOpen}
|
|
265
|
+
@keydown=${this.handleMenuKeydown}
|
|
266
|
+
>
|
|
267
|
+
${this.imagery.length > 0 ? this.renderMapTypes() : nothing}
|
|
268
|
+
${entries.length > 0
|
|
269
|
+
? html `<div part="layer-choices">
|
|
270
|
+
${entries.map((entry) => {
|
|
271
|
+
const shown = entry.some((layer) => !layer.hidden);
|
|
272
|
+
return html `<button
|
|
273
|
+
part="layer-choice"
|
|
274
|
+
aria-pressed=${shown ? 'true' : 'false'}
|
|
275
|
+
type="button"
|
|
276
|
+
@click=${() => this.showLayers(entry, !shown)}
|
|
277
|
+
>
|
|
278
|
+
<svg part="layer-icon" aria-hidden="true" fill="currentColor" viewBox=${iconOf(entry[0]).viewBox}>
|
|
279
|
+
${unsafeSVG(iconOf(entry[0]).content)}
|
|
280
|
+
</svg>
|
|
281
|
+
<span part="layer-name">${entry[0]?.label ?? ''}</span>
|
|
282
|
+
</button>`;
|
|
283
|
+
})}
|
|
284
|
+
</div>`
|
|
285
|
+
: nothing}
|
|
286
|
+
</div>`;
|
|
287
|
+
}
|
|
288
|
+
renderMapTypes() {
|
|
289
|
+
const chosen = this.mapType ?? 'standard';
|
|
290
|
+
return html `<div part="map-types" role="radiogroup" aria-label=${this.mapTypeLabel}>
|
|
291
|
+
${MAP_TYPES.map((type) => {
|
|
292
|
+
const preview = this.mapPreviews[type];
|
|
293
|
+
return html `<label part="map-type">
|
|
294
|
+
<input
|
|
295
|
+
type="radio"
|
|
296
|
+
name="map-type"
|
|
297
|
+
.checked=${chosen === type}
|
|
298
|
+
@change=${() => {
|
|
299
|
+
this.mapType = type === 'standard' ? undefined : type;
|
|
300
|
+
}}
|
|
301
|
+
/>
|
|
302
|
+
${preview
|
|
303
|
+
? html `<img part="map-type-preview" alt="" src=${preview} />`
|
|
304
|
+
: html `<span part="map-type-preview"></span>`}
|
|
305
|
+
<span part="map-type-name">${this.nameOf(type)}</span>
|
|
306
|
+
</label>`;
|
|
307
|
+
})}
|
|
308
|
+
</div>`;
|
|
309
|
+
}
|
|
310
|
+
renderCompass(pan, rotate) {
|
|
311
|
+
return html `<div part="compass">
|
|
312
|
+
${rotate
|
|
313
|
+
? html `<button part="rotate-left" aria-label=${this.rotateLeftLabel} type="button" @click=${() => this.rotate(-ROTATE_STEP)}>
|
|
314
|
+
↺
|
|
315
|
+
</button>`
|
|
316
|
+
: nothing}
|
|
317
|
+
${pan
|
|
318
|
+
? html `<button part="pan-up" aria-label=${this.panLabel('up')} type="button" @click=${() => this.pan('up')}>
|
|
319
|
+
${this.panGlyph('up')}
|
|
320
|
+
</button>`
|
|
321
|
+
: nothing}
|
|
322
|
+
${rotate
|
|
323
|
+
? html `<button part="rotate-right" aria-label=${this.rotateRightLabel} type="button" @click=${() => this.rotate(ROTATE_STEP)}>
|
|
324
|
+
↻
|
|
325
|
+
</button>`
|
|
326
|
+
: nothing}
|
|
327
|
+
${pan
|
|
328
|
+
? html `<button part="pan-start" aria-label=${this.panLabel('start')} type="button" @click=${() => this.pan('start')}>
|
|
329
|
+
${this.panGlyph('start')}
|
|
330
|
+
</button>`
|
|
331
|
+
: nothing}
|
|
332
|
+
<button part="face-north" aria-label=${this.faceNorthLabel} type="button" style=${`--map-needle-turn: ${-this.bearing}deg`} @click=${() => this.faceNorth()}>
|
|
333
|
+
<svg part="needle" aria-hidden="true" viewBox="0 0 16 16">
|
|
334
|
+
<path data-end="north" d="M8 1.5 10.5 8h-5Z" />
|
|
335
|
+
<path data-end="south" d="M8 14.5 5.5 8h5Z" />
|
|
336
|
+
</svg>
|
|
337
|
+
</button>
|
|
338
|
+
${pan
|
|
339
|
+
? html `<button part="pan-end" aria-label=${this.panLabel('end')} type="button" @click=${() => this.pan('end')}>
|
|
340
|
+
${this.panGlyph('end')}
|
|
341
|
+
</button>`
|
|
342
|
+
: nothing}
|
|
343
|
+
${pan
|
|
344
|
+
? html `<button part="pan-down" aria-label=${this.panLabel('down')} type="button" @click=${() => this.pan('down')}>
|
|
345
|
+
${this.panGlyph('down')}
|
|
346
|
+
</button>`
|
|
347
|
+
: nothing}
|
|
348
|
+
</div>`;
|
|
349
|
+
}
|
|
350
|
+
renderControls() {
|
|
351
|
+
const pan = this.drawsControls('pan');
|
|
352
|
+
const zoom = this.drawsControls('zoom');
|
|
353
|
+
const rotate = this.drawsControls('rotate');
|
|
354
|
+
const tilt = this.drawsControls('tilt');
|
|
355
|
+
const fullscreen = this.drawsControls('fullscreen');
|
|
356
|
+
const menu = this.renderLayersMenu();
|
|
357
|
+
if (!pan && !zoom && !rotate && !tilt && !fullscreen && menu === nothing) {
|
|
358
|
+
return nothing;
|
|
359
|
+
}
|
|
360
|
+
return html `<div part="controls" role="group" aria-label=${this.controlsLabel ?? this.restingControlsLabel}>
|
|
361
|
+
${fullscreen
|
|
362
|
+
? html `<button
|
|
363
|
+
part="fullscreen"
|
|
364
|
+
aria-label=${this.fullscreenLabel}
|
|
365
|
+
aria-pressed=${this.filled ? 'true' : 'false'}
|
|
366
|
+
type="button"
|
|
367
|
+
@click=${this.toggleFullscreen}
|
|
368
|
+
>
|
|
369
|
+
⤢
|
|
370
|
+
</button>`
|
|
371
|
+
: nothing}
|
|
372
|
+
${menu}
|
|
373
|
+
${tilt
|
|
374
|
+
? html `<button
|
|
375
|
+
part="tilt"
|
|
376
|
+
aria-label=${this.tiltLabel}
|
|
377
|
+
aria-pressed=${this.pitch > 0 ? 'true' : 'false'}
|
|
378
|
+
type="button"
|
|
379
|
+
@click=${() => this.tiltTo(this.pitch > 0 ? 0 : TILTED)}
|
|
380
|
+
>
|
|
381
|
+
3D
|
|
382
|
+
</button>`
|
|
383
|
+
: nothing}
|
|
384
|
+
${zoom
|
|
385
|
+
? html `<button part="zoom-in" aria-label=${this.zoomInLabel} type="button" @click=${() => this.zoom(1)}>
|
|
386
|
+
+
|
|
387
|
+
</button>
|
|
388
|
+
<button part="zoom-out" aria-label=${this.zoomOutLabel} type="button" @click=${() => this.zoom(-1)}>
|
|
389
|
+
−
|
|
390
|
+
</button>`
|
|
391
|
+
: nothing}
|
|
392
|
+
${this.drawsCompass ? this.renderCompass(pan, rotate) : nothing}
|
|
393
|
+
</div>`;
|
|
394
|
+
}
|
|
395
|
+
get restingControls() {
|
|
396
|
+
return 'zoom compass fullscreen';
|
|
397
|
+
}
|
|
398
|
+
get drawsCompass() {
|
|
399
|
+
return ['compass', 'pan', 'rotate'].some((group) => this.drawsControls(group));
|
|
400
|
+
}
|
|
401
|
+
get keyShortcuts() {
|
|
402
|
+
const keys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Plus', 'Minus'];
|
|
403
|
+
if (this.drawsCompass) {
|
|
404
|
+
keys.push('Shift+ArrowLeft', 'Shift+ArrowRight');
|
|
405
|
+
}
|
|
406
|
+
if (this.drawsControls('tilt')) {
|
|
407
|
+
keys.push('Shift+ArrowUp', 'Shift+ArrowDown');
|
|
408
|
+
}
|
|
409
|
+
return keys.join(' ');
|
|
410
|
+
}
|
|
411
|
+
handleMoreKeys(event) {
|
|
412
|
+
if (!event.shiftKey) {
|
|
413
|
+
return false;
|
|
414
|
+
}
|
|
415
|
+
if (this.drawsCompass && (event.key === 'ArrowLeft' || event.key === 'ArrowRight')) {
|
|
416
|
+
this.rotate(event.key === 'ArrowLeft' ? -ROTATE_STEP : ROTATE_STEP);
|
|
417
|
+
return true;
|
|
418
|
+
}
|
|
419
|
+
if (this.drawsControls('tilt') && (event.key === 'ArrowUp' || event.key === 'ArrowDown')) {
|
|
420
|
+
this.tilt(event.key === 'ArrowUp' ? TILT_STEP : -TILT_STEP);
|
|
421
|
+
return true;
|
|
422
|
+
}
|
|
423
|
+
return false;
|
|
14
424
|
}
|
|
15
425
|
panEvent(detail) {
|
|
16
426
|
return new HelixMapPanEvent(detail);
|
|
@@ -27,12 +437,21 @@ let HelixHeadlessMap = class HelixHeadlessMap extends MixinViewport(HelixElement
|
|
|
27
437
|
this.toggleState('fullscreen', this.filled);
|
|
28
438
|
this.toggleState('idle', this.resting);
|
|
29
439
|
}
|
|
440
|
+
renderLayers() {
|
|
441
|
+
const layers = this.layers.filter((layer) => !layer.hidden);
|
|
442
|
+
if (layers.length === 0) {
|
|
443
|
+
return nothing;
|
|
444
|
+
}
|
|
445
|
+
return html `<ul part="layers" aria-label=${this.layersLabel}>
|
|
446
|
+
${layers.map((layer) => html `<li part="layer">${layer.label ?? ''}${layer.description ? `, ${layer.description}` : ''}</li>`)}
|
|
447
|
+
</ul>`;
|
|
448
|
+
}
|
|
30
449
|
render() {
|
|
31
450
|
return html `<div
|
|
32
451
|
part="region"
|
|
33
452
|
role="group"
|
|
34
453
|
aria-label=${this.label || 'Map'}
|
|
35
|
-
aria-keyshortcuts
|
|
454
|
+
aria-keyshortcuts=${this.keyShortcuts}
|
|
36
455
|
tabindex="0"
|
|
37
456
|
@focusin=${this.idle.stir}
|
|
38
457
|
@keydown=${this.handleKeydown}
|
|
@@ -43,8 +462,9 @@ let HelixHeadlessMap = class HelixHeadlessMap extends MixinViewport(HelixElement
|
|
|
43
462
|
<slot name="header"></slot>
|
|
44
463
|
</div>
|
|
45
464
|
<div part="viewport">
|
|
46
|
-
<slot></slot>
|
|
465
|
+
<slot @slotchange=${this.handleSlotChange}></slot>
|
|
47
466
|
</div>
|
|
467
|
+
${this.renderLayers()}
|
|
48
468
|
${this.renderControls()}
|
|
49
469
|
<div part="footer">
|
|
50
470
|
<slot name="footer"></slot>
|
|
@@ -55,9 +475,57 @@ let HelixHeadlessMap = class HelixHeadlessMap extends MixinViewport(HelixElement
|
|
|
55
475
|
</div>`;
|
|
56
476
|
}
|
|
57
477
|
};
|
|
478
|
+
__decorate([
|
|
479
|
+
property({ type: Number })
|
|
480
|
+
], HelixHeadlessMap.prototype, "bearing", void 0);
|
|
481
|
+
__decorate([
|
|
482
|
+
property({ type: Boolean })
|
|
483
|
+
], HelixHeadlessMap.prototype, "cluster", void 0);
|
|
484
|
+
__decorate([
|
|
485
|
+
property({ attribute: 'face-north-label' })
|
|
486
|
+
], HelixHeadlessMap.prototype, "faceNorthLabel", void 0);
|
|
487
|
+
__decorate([
|
|
488
|
+
property({ attribute: 'hybrid-label' })
|
|
489
|
+
], HelixHeadlessMap.prototype, "hybridLabel", void 0);
|
|
58
490
|
__decorate([
|
|
59
491
|
property()
|
|
60
492
|
], HelixHeadlessMap.prototype, "label", void 0);
|
|
493
|
+
__decorate([
|
|
494
|
+
property({ attribute: 'layers-label' })
|
|
495
|
+
], HelixHeadlessMap.prototype, "layersLabel", void 0);
|
|
496
|
+
__decorate([
|
|
497
|
+
state()
|
|
498
|
+
], HelixHeadlessMap.prototype, "mapPreviews", void 0);
|
|
499
|
+
__decorate([
|
|
500
|
+
property({ attribute: 'map-type', reflect: true })
|
|
501
|
+
], HelixHeadlessMap.prototype, "mapType", void 0);
|
|
502
|
+
__decorate([
|
|
503
|
+
property({ attribute: 'map-type-label' })
|
|
504
|
+
], HelixHeadlessMap.prototype, "mapTypeLabel", void 0);
|
|
505
|
+
__decorate([
|
|
506
|
+
property({ type: Number })
|
|
507
|
+
], HelixHeadlessMap.prototype, "pitch", void 0);
|
|
508
|
+
__decorate([
|
|
509
|
+
property({ attribute: 'rotate-left-label' })
|
|
510
|
+
], HelixHeadlessMap.prototype, "rotateLeftLabel", void 0);
|
|
511
|
+
__decorate([
|
|
512
|
+
property({ attribute: 'rotate-right-label' })
|
|
513
|
+
], HelixHeadlessMap.prototype, "rotateRightLabel", void 0);
|
|
514
|
+
__decorate([
|
|
515
|
+
property({ attribute: 'satellite-label' })
|
|
516
|
+
], HelixHeadlessMap.prototype, "satelliteLabel", void 0);
|
|
517
|
+
__decorate([
|
|
518
|
+
property({ attribute: 'standard-label' })
|
|
519
|
+
], HelixHeadlessMap.prototype, "standardLabel", void 0);
|
|
520
|
+
__decorate([
|
|
521
|
+
property({ attribute: 'tilt-label' })
|
|
522
|
+
], HelixHeadlessMap.prototype, "tiltLabel", void 0);
|
|
523
|
+
__decorate([
|
|
524
|
+
state()
|
|
525
|
+
], HelixHeadlessMap.prototype, "layersOpen", void 0);
|
|
526
|
+
__decorate([
|
|
527
|
+
state()
|
|
528
|
+
], HelixHeadlessMap.prototype, "stop", void 0);
|
|
61
529
|
HelixHeadlessMap = __decorate([
|
|
62
530
|
customElement('helix-headless-map')
|
|
63
531
|
], HelixHeadlessMap);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { HelixElement } from '@fusion.dev/helix-core';
|
|
2
|
+
import { nothing, type PropertyValues } from 'lit';
|
|
3
|
+
/** A place a line passes through or a shape is drawn around, in degrees. */
|
|
4
|
+
export interface MapPoint {
|
|
5
|
+
lat: number;
|
|
6
|
+
lng: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* `points` as it is written: `lat,lng` pairs separated by spaces, the order a
|
|
10
|
+
* marker's own `lat` and `lng` read in. A pair that is not two numbers is
|
|
11
|
+
* dropped rather than drawn at the origin, **an empty side included**:
|
|
12
|
+
* `Number('')` is 0, so `30.1,` from a record with no longitude was a vertex
|
|
13
|
+
* off West Africa.
|
|
14
|
+
*/
|
|
15
|
+
export declare const pointsOf: (value: string | null) => MapPoint[];
|
|
16
|
+
/** `points` read from its attribute, which is written and never reflected. */
|
|
17
|
+
export declare const pointsConverter: {
|
|
18
|
+
fromAttribute: typeof pointsOf;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* @summary A line on a map, such as a route between stops.
|
|
22
|
+
*
|
|
23
|
+
* @description
|
|
24
|
+
* `connectMap` draws the route as a layer of the map, under its place names,
|
|
25
|
+
* and redraws it when its points, progress, or color change. The frame lists
|
|
26
|
+
* each route by its `label` and `description` for screen readers.
|
|
27
|
+
*
|
|
28
|
+
* @since 0.105.0
|
|
29
|
+
* @status experimental
|
|
30
|
+
* @category media
|
|
31
|
+
* @aliases Map line, Path, Polyline
|
|
32
|
+
* @documentation https://fusion.dev/helix/components/map
|
|
33
|
+
*
|
|
34
|
+
* @event {HelixMapPartChangeEvent} helix-map-part-change - The route's points, progress, name, or color changed. Used by `connectMap`; pages do not need to listen for it.
|
|
35
|
+
*/
|
|
36
|
+
export declare class HelixHeadlessMapRoute extends HelixElement {
|
|
37
|
+
/**
|
|
38
|
+
* More about the route, such as its distance or time. Read after its label
|
|
39
|
+
* in the frame's list.
|
|
40
|
+
*/
|
|
41
|
+
description?: string;
|
|
42
|
+
/**
|
|
43
|
+
* A name this layer shares with other layers, such as a route and its
|
|
44
|
+
* dotted legs. The layers menu shows layers in the same group as one entry,
|
|
45
|
+
* named by the first of them, and its checkbox shows or hides them all.
|
|
46
|
+
*/
|
|
47
|
+
group?: string;
|
|
48
|
+
/** Marks this as a layer for the frame and the connector, whatever its tag. */
|
|
49
|
+
readonly isMapLayer = true;
|
|
50
|
+
/** @internal Which kind of layer, which is how the connector draws it. */
|
|
51
|
+
readonly layerKind: 'area' | 'route';
|
|
52
|
+
/** The route's name, used in the frame's list. */
|
|
53
|
+
label?: string;
|
|
54
|
+
/**
|
|
55
|
+
* The points the line passes through, in order. Write the attribute as
|
|
56
|
+
* `lat,lng` pairs separated by spaces, or set the property to an array of `{
|
|
57
|
+
* lat, lng }`.
|
|
58
|
+
*/
|
|
59
|
+
points?: MapPoint[];
|
|
60
|
+
/**
|
|
61
|
+
* How much of the route has been traveled, from 0 to 1. The traveled part is
|
|
62
|
+
* drawn in a lighter color.
|
|
63
|
+
*/
|
|
64
|
+
progress?: number;
|
|
65
|
+
/** Tells the frame and the connector the line moved, was renamed or was retoned. */
|
|
66
|
+
protected updated(changed: PropertyValues): void;
|
|
67
|
+
protected render(): typeof nothing;
|
|
68
|
+
}
|
|
69
|
+
declare global {
|
|
70
|
+
interface HTMLElementTagNameMap {
|
|
71
|
+
'helix-headless-map-route': HelixHeadlessMapRoute;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { customElement, HelixElement, HelixMapPartChangeEvent } from '@fusion.dev/helix-core';
|
|
8
|
+
import { nothing } from 'lit';
|
|
9
|
+
import { property } from 'lit/decorators.js';
|
|
10
|
+
export const pointsOf = (value) => (value ?? '')
|
|
11
|
+
.trim()
|
|
12
|
+
.split(/\s+/)
|
|
13
|
+
.filter(Boolean)
|
|
14
|
+
.map((pair) => pair.split(','))
|
|
15
|
+
.filter((pair) => pair.length === 2 && pair.every((one) => one.trim() !== ''))
|
|
16
|
+
.map((pair) => pair.map(Number))
|
|
17
|
+
.filter((pair) => pair.every((one) => Number.isFinite(one)))
|
|
18
|
+
.map(([lat, lng]) => ({ lat: lat, lng: lng }));
|
|
19
|
+
export const pointsConverter = { fromAttribute: pointsOf };
|
|
20
|
+
let HelixHeadlessMapRoute = class HelixHeadlessMapRoute extends HelixElement {
|
|
21
|
+
constructor() {
|
|
22
|
+
super(...arguments);
|
|
23
|
+
this.isMapLayer = true;
|
|
24
|
+
this.layerKind = 'route';
|
|
25
|
+
}
|
|
26
|
+
updated(changed) {
|
|
27
|
+
super.updated(changed);
|
|
28
|
+
this.dispatchEvent(new HelixMapPartChangeEvent({ kind: 'layer' }));
|
|
29
|
+
}
|
|
30
|
+
render() {
|
|
31
|
+
return nothing;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
__decorate([
|
|
35
|
+
property()
|
|
36
|
+
], HelixHeadlessMapRoute.prototype, "description", void 0);
|
|
37
|
+
__decorate([
|
|
38
|
+
property()
|
|
39
|
+
], HelixHeadlessMapRoute.prototype, "group", void 0);
|
|
40
|
+
__decorate([
|
|
41
|
+
property()
|
|
42
|
+
], HelixHeadlessMapRoute.prototype, "label", void 0);
|
|
43
|
+
__decorate([
|
|
44
|
+
property({ converter: pointsConverter })
|
|
45
|
+
], HelixHeadlessMapRoute.prototype, "points", void 0);
|
|
46
|
+
__decorate([
|
|
47
|
+
property({ type: Number })
|
|
48
|
+
], HelixHeadlessMapRoute.prototype, "progress", void 0);
|
|
49
|
+
HelixHeadlessMapRoute = __decorate([
|
|
50
|
+
customElement('helix-headless-map-route')
|
|
51
|
+
], HelixHeadlessMapRoute);
|
|
52
|
+
export { HelixHeadlessMapRoute };
|