script[setup]: layouts/map (#18440)

This commit is contained in:
Rijk van Zanten
2023-05-03 11:25:46 -04:00
committed by GitHub
parent 3380084975
commit 84f637dc40
4 changed files with 401 additions and 527 deletions

View File

@@ -6,21 +6,18 @@
</transition>
</template>
<script lang="ts" setup>
defineProps<{
itemCount?: number;
showingCount: string;
}>();
</script>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
inheritAttrs: false,
props: {
itemCount: {
type: Number,
default: null,
},
showingCount: {
type: String,
required: true,
},
},
});
</script>

View File

@@ -6,364 +6,343 @@
></div>
</template>
<script lang="ts">
import 'maplibre-gl/dist/maplibre-gl.css';
import maplibre, {
MapboxGeoJSONFeature,
MapLayerMouseEvent,
NavigationControl,
GeolocateControl,
LngLatBoundsLike,
GeoJSONSource,
CameraOptions,
LngLatLike,
AnyLayer,
Map,
AttributionControl,
} from 'maplibre-gl';
<script setup lang="ts">
import MapboxGeocoder from '@mapbox/mapbox-gl-geocoder';
import '@mapbox/mapbox-gl-geocoder/dist/mapbox-gl-geocoder.css';
import { ref, watch, PropType, onMounted, onUnmounted, defineComponent, toRefs, computed, WatchStopHandle } from 'vue';
import maplibre, {
AnyLayer,
AttributionControl,
CameraOptions,
GeoJSONSource,
GeolocateControl,
LngLatBoundsLike,
LngLatLike,
Map,
MapLayerMouseEvent,
MapboxGeoJSONFeature,
NavigationControl,
} from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
import { WatchStopHandle, computed, onMounted, onUnmounted, ref, toRefs, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { ShowSelect } from '@directus/types';
import { useAppStore } from '@/stores/app';
import { useSettingsStore } from '@/stores/settings';
import { BoxSelectControl, ButtonControl } from '@/utils/geometry/controls';
import { getBasemapSources, getStyleFromBasemapSource } from '@/utils/geometry/basemap';
import { BoxSelectControl, ButtonControl } from '@/utils/geometry/controls';
import { ShowSelect } from '@directus/types';
export default defineComponent({
components: {},
props: {
data: {
type: Object as PropType<GeoJSON.FeatureCollection>,
required: true,
},
source: {
type: Object as PropType<GeoJSONSource>,
required: true,
},
layers: {
type: Array as PropType<AnyLayer[]>,
default: () => [],
},
camera: {
type: Object as PropType<CameraOptions & { bbox: any }>,
default: () => ({} as any),
},
bounds: {
type: Array as unknown as PropType<GeoJSON.BBox>,
default: undefined,
},
featureId: {
type: String,
default: undefined,
},
selection: {
type: Array as PropType<Array<string | number>>,
default: () => [],
},
showSelect: {
type: String as PropType<ShowSelect>,
default: 'multiple',
},
},
emits: ['moveend', 'featureclick', 'featureselect', 'fitdata', 'updateitempopup'],
setup(props, { emit }) {
const { t } = useI18n();
const appStore = useAppStore();
const settingsStore = useSettingsStore();
let map: Map;
const hoveredFeature = ref<MapboxGeoJSONFeature>();
const hoveredCluster = ref<boolean>();
const selectMode = ref<boolean>();
const container = ref<HTMLElement>();
const unwatchers = [] as WatchStopHandle[];
const { sidebarOpen, basemap } = toRefs(appStore);
const mapboxKey = settingsStore.settings?.mapbox_key;
const basemaps = getBasemapSources();
const props = withDefaults(
defineProps<{
data: GeoJSON.FeatureCollection;
source: GeoJSONSource;
layers?: AnyLayer[];
camera?: CameraOptions & { bbox: any };
bounds?: GeoJSON.BBox;
featureId?: string;
selection?: (string | number)[];
showSelect?: ShowSelect;
}>(),
{
layers: () => [],
camera: () => ({} as any),
selection: () => [],
showSelect: 'multiple',
}
);
const style = computed(() => {
const source = basemaps.find((source) => source.name === basemap.value) ?? basemaps[0];
return getStyleFromBasemapSource(source);
});
const emit = defineEmits(['moveend', 'featureclick', 'featureselect', 'fitdata', 'updateitempopup']);
const attributionControl = new AttributionControl();
const { t } = useI18n();
const appStore = useAppStore();
const settingsStore = useSettingsStore();
let map: Map;
const hoveredFeature = ref<MapboxGeoJSONFeature>();
const hoveredCluster = ref<boolean>();
const selectMode = ref<boolean>();
const container = ref<HTMLElement>();
const unwatchers = [] as WatchStopHandle[];
const { sidebarOpen, basemap } = toRefs(appStore);
const mapboxKey = settingsStore.settings?.mapbox_key;
const basemaps = getBasemapSources();
const navigationControl = new NavigationControl({
showCompass: false,
});
const geolocateControl = new GeolocateControl();
const fitDataControl = new ButtonControl('mapboxgl-ctrl-fitdata', () => {
emit('fitdata');
});
const boxSelectControl = new BoxSelectControl({
boxElementClass: 'map-selection-box',
selectButtonClass: 'mapboxgl-ctrl-select',
layers: ['__directus_polygons', '__directus_points', '__directus_lines'],
});
let geocoderControl: MapboxGeocoder | undefined;
if (mapboxKey) {
const marker = document.createElement('div');
marker.className = 'mapboxgl-user-location-dot mapboxgl-search-location-dot';
geocoderControl = new MapboxGeocoder({
accessToken: mapboxKey,
collapsed: true,
marker: { element: marker } as any,
flyTo: { speed: 1.4 },
mapboxgl: maplibre as any,
placeholder: t('layouts.map.find_location'),
});
}
onMounted(() => {
setupMap();
});
onUnmounted(() => {
map.remove();
});
return { container, hoveredFeature, hoveredCluster, selectMode };
function setupMap() {
map = new Map({
container: 'map-container',
style: style.value,
dragRotate: false,
attributionControl: false,
...props.camera,
...(mapboxKey ? { accessToken: mapboxKey } : {}),
});
if (geocoderControl) {
map.addControl(geocoderControl as any, 'top-right');
}
map.addControl(attributionControl, 'bottom-left');
map.addControl(navigationControl, 'top-left');
map.addControl(geolocateControl, 'top-left');
map.addControl(fitDataControl, 'top-left');
map.addControl(boxSelectControl, 'top-left');
map.on('load', () => {
watch(() => style.value, updateStyle);
watch(() => props.bounds, fitBounds);
const activeLayers = ['__directus_polygons', '__directus_points', '__directus_lines'];
for (const layer of activeLayers) {
map.on('click', layer, onFeatureClick);
map.on('mousemove', layer, updatePopup);
map.on('mouseleave', layer, updatePopup);
}
map.on('move', updatePopupLocation);
map.on('click', '__directus_clusters', expandCluster);
map.on('mousemove', '__directus_clusters', hoverCluster);
map.on('mouseleave', '__directus_clusters', hoverCluster);
map.on('select.enable', () => (selectMode.value = true));
map.on('select.disable', () => (selectMode.value = false));
map.on('select.end', (event: MapLayerMouseEvent) => {
const ids = event.features?.map((f) => f.id);
emit('featureselect', { ids, replace: !event.alt });
});
map.on('moveend', () => {
emit('moveend', {
center: map.getCenter(),
zoom: map.getZoom(),
bearing: map.getBearing(),
pitch: map.getPitch(),
bbox: map.getBounds().toArray().flat(),
});
});
startWatchers();
});
watch(
() => sidebarOpen.value,
(opened) => {
if (!opened) setTimeout(() => map.resize(), 300);
}
);
setTimeout(() => map.resize(), 300);
}
function fitBounds() {
const bbox = props.data.bbox;
if (map && bbox) {
map.fitBounds(bbox as LngLatBoundsLike, {
padding: 100,
speed: 1.3,
maxZoom: 14,
});
}
}
function updateStyle(style: any) {
unwatchers.forEach((unwatch) => unwatch());
unwatchers.length = 0;
map.setStyle(style, { diff: false });
map.once('styledata', startWatchers);
}
function startWatchers() {
unwatchers.push(
watch(() => props.source, updateSource, { immediate: true }),
watch(() => props.selection, updateSelection, { immediate: true }),
watch(() => props.layers, updateLayers),
watch(() => props.data, updateData)
);
}
function updateData(newData: any) {
const source = map.getSource('__directus');
(source as GeoJSONSource).setData(newData);
updateSelection(props.selection, undefined);
}
function updateSource(newSource: GeoJSONSource) {
const layersId = new Set(map.getStyle().layers?.map(({ id }) => id));
for (const layer of props.layers) {
if (layersId.has(layer.id)) {
map.removeLayer(layer.id);
}
}
if (props.featureId) {
(newSource as any).promoteId = props.featureId;
} else {
(newSource as any).generateId = true;
}
if (map.getStyle().sources?.['__directus']) {
map.removeSource('__directus');
}
map.addSource('__directus', { ...newSource, data: props.data });
map.once('sourcedata', () => {
setTimeout(() => props.layers.forEach((layer) => map.addLayer(layer)));
});
}
function updateLayers(newLayers?: AnyLayer[], previousLayers?: AnyLayer[]) {
const currentMapLayersId = new Set(map.getStyle().layers?.map(({ id }) => id));
previousLayers?.forEach((layer) => {
if (currentMapLayersId.has(layer.id)) map.removeLayer(layer.id);
});
newLayers?.forEach((layer) => {
map.addLayer(layer);
});
}
function updateSelection(newSelection?: (string | number)[], previousSelection?: (string | number)[]) {
previousSelection?.forEach((id) => {
map.setFeatureState({ id, source: '__directus' }, { selected: false });
map.removeFeatureState({ id, source: '__directus' });
});
newSelection?.forEach((id) => {
map.setFeatureState({ id, source: '__directus' }, { selected: true });
});
}
function onFeatureClick(event: MapLayerMouseEvent) {
const feature = event.features?.[0];
const replace = props.showSelect === 'multiple' ? false : !event.originalEvent.altKey;
if (feature && props.featureId) {
if (boxSelectControl.active()) {
emit('featureselect', { ids: [feature.id], replace });
} else {
emit('featureclick', { id: feature.id, replace });
}
}
}
function updatePopup(event: MapLayerMouseEvent) {
const feature = map.queryRenderedFeatures(event.point, {
layers: ['__directus_polygons', '__directus_points', '__directus_lines'],
})[0];
const previousId = hoveredFeature.value?.id;
const featureChanged = previousId !== feature?.id;
if (previousId && featureChanged) {
map.setFeatureState({ id: previousId, source: '__directus' }, { hovered: false });
}
if (feature && feature.properties) {
if (feature.geometry.type === 'Point') {
const { x, y } = map.project(feature.geometry.coordinates as LngLatLike);
const rect = map.getContainer().getBoundingClientRect();
emit('updateitempopup', { position: { x: rect.x + x, y: rect.y + y } });
} else {
const { clientX: x, clientY: y } = event.originalEvent;
emit('updateitempopup', { position: { x, y } });
}
if (featureChanged) {
map.setFeatureState({ id: feature.id, source: '__directus' }, { hovered: true });
hoveredFeature.value = feature;
emit('updateitempopup', { item: feature.id });
}
} else {
if (featureChanged) {
hoveredFeature.value = feature;
emit('updateitempopup', { item: null });
}
}
}
function updatePopupLocation(event: MapLayerMouseEvent) {
if (hoveredFeature.value && event.originalEvent) {
const { x, y } = event.originalEvent;
emit('updateitempopup', { position: { x, y } });
}
}
function expandCluster(event: MapLayerMouseEvent) {
const features = map.queryRenderedFeatures(event.point, {
layers: ['__directus_clusters'],
});
const clusterId = features[0]?.properties?.cluster_id;
const source = map.getSource('__directus') as GeoJSONSource;
source.getClusterExpansionZoom(clusterId, (err: any, zoom: number) => {
if (err) return;
map.flyTo({
center: (features[0].geometry as GeoJSON.Point).coordinates as LngLatLike,
zoom: zoom,
speed: 1.3,
});
});
}
function hoverCluster(event: MapLayerMouseEvent) {
if (event.type == 'mousemove') {
hoveredCluster.value = true;
} else {
hoveredCluster.value = false;
}
}
},
const style = computed(() => {
const source = basemaps.find((source) => source.name === basemap.value) ?? basemaps[0];
return getStyleFromBasemapSource(source);
});
const attributionControl = new AttributionControl();
const navigationControl = new NavigationControl({
showCompass: false,
});
const geolocateControl = new GeolocateControl();
const fitDataControl = new ButtonControl('mapboxgl-ctrl-fitdata', () => {
emit('fitdata');
});
const boxSelectControl = new BoxSelectControl({
boxElementClass: 'map-selection-box',
selectButtonClass: 'mapboxgl-ctrl-select',
layers: ['__directus_polygons', '__directus_points', '__directus_lines'],
});
let geocoderControl: MapboxGeocoder | undefined;
if (mapboxKey) {
const marker = document.createElement('div');
marker.className = 'mapboxgl-user-location-dot mapboxgl-search-location-dot';
geocoderControl = new MapboxGeocoder({
accessToken: mapboxKey,
collapsed: true,
marker: { element: marker } as any,
flyTo: { speed: 1.4 },
mapboxgl: maplibre as any,
placeholder: t('layouts.map.find_location'),
});
}
onMounted(() => {
setupMap();
});
onUnmounted(() => {
map.remove();
});
function setupMap() {
map = new Map({
container: 'map-container',
style: style.value,
dragRotate: false,
attributionControl: false,
...props.camera,
...(mapboxKey ? { accessToken: mapboxKey } : {}),
});
if (geocoderControl) {
map.addControl(geocoderControl as any, 'top-right');
}
map.addControl(attributionControl, 'bottom-left');
map.addControl(navigationControl, 'top-left');
map.addControl(geolocateControl, 'top-left');
map.addControl(fitDataControl, 'top-left');
map.addControl(boxSelectControl, 'top-left');
map.on('load', () => {
watch(() => style.value, updateStyle);
watch(() => props.bounds, fitBounds);
const activeLayers = ['__directus_polygons', '__directus_points', '__directus_lines'];
for (const layer of activeLayers) {
map.on('click', layer, onFeatureClick);
map.on('mousemove', layer, updatePopup);
map.on('mouseleave', layer, updatePopup);
}
map.on('move', updatePopupLocation);
map.on('click', '__directus_clusters', expandCluster);
map.on('mousemove', '__directus_clusters', hoverCluster);
map.on('mouseleave', '__directus_clusters', hoverCluster);
map.on('select.enable', () => (selectMode.value = true));
map.on('select.disable', () => (selectMode.value = false));
map.on('select.end', (event: MapLayerMouseEvent) => {
const ids = event.features?.map((f) => f.id);
emit('featureselect', { ids, replace: !event.alt });
});
map.on('moveend', () => {
emit('moveend', {
center: map.getCenter(),
zoom: map.getZoom(),
bearing: map.getBearing(),
pitch: map.getPitch(),
bbox: map.getBounds().toArray().flat(),
});
});
startWatchers();
});
watch(
() => sidebarOpen.value,
(opened) => {
if (!opened) setTimeout(() => map.resize(), 300);
}
);
setTimeout(() => map.resize(), 300);
}
function fitBounds() {
const bbox = props.data.bbox;
if (map && bbox) {
map.fitBounds(bbox as LngLatBoundsLike, {
padding: 100,
speed: 1.3,
maxZoom: 14,
});
}
}
function updateStyle(style: any) {
unwatchers.forEach((unwatch) => unwatch());
unwatchers.length = 0;
map.setStyle(style, { diff: false });
map.once('styledata', startWatchers);
}
function startWatchers() {
unwatchers.push(
watch(() => props.source, updateSource, { immediate: true }),
watch(() => props.selection, updateSelection, { immediate: true }),
watch(() => props.layers, updateLayers),
watch(() => props.data, updateData)
);
}
function updateData(newData: any) {
const source = map.getSource('__directus');
(source as GeoJSONSource).setData(newData);
updateSelection(props.selection, undefined);
}
function updateSource(newSource: GeoJSONSource) {
const layersId = new Set(map.getStyle().layers?.map(({ id }) => id));
for (const layer of props.layers) {
if (layersId.has(layer.id)) {
map.removeLayer(layer.id);
}
}
if (props.featureId) {
(newSource as any).promoteId = props.featureId;
} else {
(newSource as any).generateId = true;
}
if (map.getStyle().sources?.['__directus']) {
map.removeSource('__directus');
}
map.addSource('__directus', { ...newSource, data: props.data });
map.once('sourcedata', () => {
setTimeout(() => props.layers.forEach((layer) => map.addLayer(layer)));
});
}
function updateLayers(newLayers?: AnyLayer[], previousLayers?: AnyLayer[]) {
const currentMapLayersId = new Set(map.getStyle().layers?.map(({ id }) => id));
previousLayers?.forEach((layer) => {
if (currentMapLayersId.has(layer.id)) map.removeLayer(layer.id);
});
newLayers?.forEach((layer) => {
map.addLayer(layer);
});
}
function updateSelection(newSelection?: (string | number)[], previousSelection?: (string | number)[]) {
previousSelection?.forEach((id) => {
map.setFeatureState({ id, source: '__directus' }, { selected: false });
map.removeFeatureState({ id, source: '__directus' });
});
newSelection?.forEach((id) => {
map.setFeatureState({ id, source: '__directus' }, { selected: true });
});
}
function onFeatureClick(event: MapLayerMouseEvent) {
const feature = event.features?.[0];
const replace = props.showSelect === 'multiple' ? false : !event.originalEvent.altKey;
if (feature && props.featureId) {
if (boxSelectControl.active()) {
emit('featureselect', { ids: [feature.id], replace });
} else {
emit('featureclick', { id: feature.id, replace });
}
}
}
function updatePopup(event: MapLayerMouseEvent) {
const feature = map.queryRenderedFeatures(event.point, {
layers: ['__directus_polygons', '__directus_points', '__directus_lines'],
})[0];
const previousId = hoveredFeature.value?.id;
const featureChanged = previousId !== feature?.id;
if (previousId && featureChanged) {
map.setFeatureState({ id: previousId, source: '__directus' }, { hovered: false });
}
if (feature && feature.properties) {
if (feature.geometry.type === 'Point') {
const { x, y } = map.project(feature.geometry.coordinates as LngLatLike);
const rect = map.getContainer().getBoundingClientRect();
emit('updateitempopup', { position: { x: rect.x + x, y: rect.y + y } });
} else {
const { clientX: x, clientY: y } = event.originalEvent;
emit('updateitempopup', { position: { x, y } });
}
if (featureChanged) {
map.setFeatureState({ id: feature.id, source: '__directus' }, { hovered: true });
hoveredFeature.value = feature;
emit('updateitempopup', { item: feature.id });
}
} else {
if (featureChanged) {
hoveredFeature.value = feature;
emit('updateitempopup', { item: null });
}
}
}
function updatePopupLocation(event: MapLayerMouseEvent) {
if (hoveredFeature.value && event.originalEvent) {
const { x, y } = event.originalEvent;
emit('updateitempopup', { position: { x, y } });
}
}
function expandCluster(event: MapLayerMouseEvent) {
const features = map.queryRenderedFeatures(event.point, {
layers: ['__directus_clusters'],
});
const clusterId = features[0]?.properties?.cluster_id;
const source = map.getSource('__directus') as GeoJSONSource;
source.getClusterExpansionZoom(clusterId, (err: any, zoom: number) => {
if (err) return;
map.flyTo({
center: (features[0].geometry as GeoJSON.Point).coordinates as LngLatLike,
zoom: zoom,
speed: 1.3,
});
});
}
function hoverCluster(event: MapLayerMouseEvent) {
if (event.type == 'mousemove') {
hoveredCluster.value = true;
} else {
hoveredCluster.value = false;
}
}
</script>
<style lang="scss" scoped>

View File

@@ -93,132 +93,57 @@
</template>
<script lang="ts">
import { useI18n } from 'vue-i18n';
import { defineComponent, PropType } from 'vue';
export default {
inheritAttrs: false,
};
</script>
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
import MapComponent from './components/map.vue';
import { useSync } from '@directus/composables';
import { GeometryOptions, Item } from '@directus/types';
export default defineComponent({
components: { MapComponent },
inheritAttrs: false,
props: {
collection: {
type: String,
required: true,
},
selection: {
type: Array as PropType<Item[]>,
default: () => [],
},
loading: {
type: Boolean,
required: true,
},
error: {
type: Object as PropType<any>,
default: null,
},
geojsonError: {
type: String,
default: null,
},
geometryOptions: {
type: Object as PropType<GeometryOptions>,
default: undefined,
},
geojson: {
type: Object as PropType<any>,
required: true,
},
featureId: {
type: String,
default: null,
},
geojsonBounds: {
type: Object as PropType<any>,
default: undefined,
},
directusSource: {
type: Object as PropType<any>,
required: true,
},
directusLayers: {
type: Array as PropType<any[]>,
required: true,
},
handleClick: {
type: Function as PropType<(event: { id: string | number; replace: boolean }) => void>,
required: true,
},
handleSelect: {
type: Function as PropType<(event: { ids: Array<string | number>; replace: boolean }) => void>,
required: true,
},
cameraOptions: {
type: Object as PropType<any>,
default: undefined,
},
resetPresetAndRefresh: {
type: Function as PropType<() => Promise<void>>,
required: true,
},
geojsonLoading: {
type: Boolean,
required: true,
},
itemCount: {
type: Number,
default: null,
},
totalPages: {
type: Number,
required: true,
},
page: {
type: Number,
required: true,
},
toPage: {
type: Function as PropType<(newPage: number) => void>,
required: true,
},
limit: {
type: Number,
required: true,
},
autoLocationFilter: {
type: Boolean,
default: undefined,
},
fitDataBounds: {
type: Function as PropType<() => void>,
required: true,
},
template: {
type: String,
default: () => undefined,
},
itemPopup: {
type: Object as PropType<{ item?: any; position?: { x: number; y: number } }>,
default: () => undefined,
},
updateItemPopup: {
type: Function,
required: true,
},
},
emits: ['update:cameraOptions', 'update:limit'],
setup(props, { emit }) {
const { t, n } = useI18n();
const props = withDefaults(
defineProps<{
collection: string;
geojson: any;
directusSource: any;
directusLayers: any[];
handleClick: (event: { id: string | number; replace: boolean }) => void;
handleSelect: (event: { ids: Array<string | number>; replace: boolean }) => void;
resetPresetAndRefresh: () => Promise<void>;
fitDataBounds: () => void;
updateItemPopup: () => void;
geojsonLoading: boolean;
loading: boolean;
totalPages: number;
page: number;
toPage: (newPage: number) => void;
limit: number;
selection?: Item[];
error?: any;
geojsonError?: string;
geometryOptions?: GeometryOptions;
featureId?: string;
geojsonBounds?: any;
cameraOptions?: any;
itemCount?: number;
autoLocationFilter?: boolean;
template?: string;
itemPopup?: { item?: any; position?: { x: number; y: number } };
}>(),
{
selection: () => [],
}
);
const cameraOptionsWritable = useSync(props, 'cameraOptions', emit);
const limitWritable = useSync(props, 'limit', emit);
const emit = defineEmits(['update:cameraOptions', 'update:limit']);
return { t, n, cameraOptionsWritable, limitWritable };
},
});
const { t, n } = useI18n();
const cameraOptionsWritable = useSync(props, 'cameraOptions', emit);
const limitWritable = useSync(props, 'limit', emit);
</script>
<style lang="scss" scoped>

View File

@@ -37,64 +37,37 @@
</div>
</template>
<script lang="ts">
import { useI18n } from 'vue-i18n';
import { defineComponent, PropType, toRefs } from 'vue';
<script lang="ts" setup>
import { useAppStore } from '@/stores/app';
import { getBasemapSources } from '@/utils/geometry/basemap';
import { GeometryOptions, Item } from '@directus/types';
import { useSync } from '@directus/composables';
import { GeometryOptions, Item } from '@directus/types';
import { toRefs } from 'vue';
import { useI18n } from 'vue-i18n';
export default defineComponent({
inheritAttrs: false,
props: {
collection: {
type: String,
required: true,
},
geometryFields: {
type: Array as PropType<Item[]>,
required: true,
},
geometryField: {
type: String,
default: undefined,
},
geometryOptions: {
type: Object as PropType<GeometryOptions>,
default: undefined,
},
clusterData: {
type: Boolean,
default: undefined,
},
displayTemplate: {
type: String as string | undefined,
default: undefined,
},
},
emits: ['update:geometryField', 'update:autoLocationFilter', 'update:clusterData'],
setup(props, { emit }) {
const { t } = useI18n();
const props = defineProps<{
collection: string;
geometryFields: Item[];
geometryField?: string;
geometryOptions?: GeometryOptions;
clusterData?: boolean;
displayTemplate?: string;
}>();
const appStore = useAppStore();
const emit = defineEmits<{
(e: 'update:geometryField', geometryField: string): void;
(e: 'update:clusterData', clusterData: boolean): void;
(e: 'update:displayTemplate', displayTemplate: string): void;
}>();
const geometryFieldWritable = useSync(props, 'geometryField', emit);
const clusterDataWritable = useSync(props, 'clusterData', emit);
const displayTemplateWritable = useSync(props, 'displayTemplate', emit);
const { t } = useI18n();
const basemaps = getBasemapSources();
const { basemap } = toRefs(appStore);
const appStore = useAppStore();
return {
t,
geometryFieldWritable,
clusterDataWritable,
displayTemplateWritable,
basemaps,
basemap,
};
},
});
const geometryFieldWritable = useSync(props, 'geometryField', emit);
const clusterDataWritable = useSync(props, 'clusterData', emit);
const displayTemplateWritable = useSync(props, 'displayTemplate', emit);
const basemaps = getBasemapSources();
const { basemap } = toRefs(appStore);
</script>