Skip to content
Docs version
@hungpvq/vue-map@1.2.0@hungpvq/vue-map-core@1.2.0@hungpvq/vue-map-dataset@1.2.0@hungpvq/vue-map-draw@1.2.0@hungpvq/map-draw@1.2.0@hungpvq/react-map@1.2.0@hungpvq/react-map-core@1.2.0@hungpvq/react-map-dataset@1.2.0@hungpvq/react-map-draw@1.2.0

Map Dataset ​

Library for creating, listing, styling, identifying, and grouping map layers. Vue and React packages share the same core (@hungpvq/map-dataset).

  • Vue: @hungpvq/vue-map-dataset
  • React: @hungpvq/react-map-dataset

Demo: Vue · React · source in apps/vue/demo-map and apps/react/demo-map.

Installation ​

Vue ​

bash
npm install @hungpvq/vue-map-dataset @hungpvq/vue-map-core @hungpvq/map-dataset @hungpvq/map-core

Peer packages you also need (already used by typical map apps):

bash
npm install maplibre-gl @mdi/js @jamescoyle/vue-icon @hungpvq/vue-draggable @hungpvq/shared @hungpvq/shared-store @hungpvq/shared-log

React ​

bash
npm install @hungpvq/react-map-dataset @hungpvq/react-map-core @hungpvq/map-dataset @hungpvq/map-core
bash
npm install maplibre-gl @mdi/js @mdi/react @hungpvq/react-draggable @hungpvq/shared @hungpvq/shared-store @hungpvq/shared-log

Import styles once at the app root. Use the full set — shared cores and framework adapters and draggable. Omitting any line leaves map chrome, list/menus/tables, or panels unstyled.

Vue

ts
import '@hungpvq/map-core/style.css';
import '@hungpvq/map-dataset/style.css';
import '@hungpvq/vue-map-core/style.css';
import '@hungpvq/vue-map-dataset/style.css';
import '@hungpvq/vue-draggable/style.css';

React

ts
import '@hungpvq/map-core/style.css';
import '@hungpvq/map-dataset/style.css';
import '@hungpvq/react-map-core/style.css';
import '@hungpvq/react-map-dataset/style.css';
import '@hungpvq/react-draggable/style.css';

Import paths (breaking major): domain APIs live on subpaths — e.g. createGeoJsonDataset from @hungpvq/map-dataset/geojson, highlight from @hungpvq/map-dataset/highlight, attribute-table from @hungpvq/map-dataset/attribute-table, LIST_VIEW_MENU_* from @hungpvq/map-dataset/menu, LayerSimpleMapboxBuild from @hungpvq/map-dataset/style. Root keeps DatasetService, tree helpers, and shared IDataset types. See Stable API.

Setup ​

Bootstrap once with installMapApp (theme + built-in UI: legend, opacity, toggle show, Add to group, Export, Attribute table, style editor). Without this step those components do not render. Prefer installMapApp over createDatasetRegistryPlugin() alone.

Vue ​

ts
import { createApp } from 'vue';
import { createStoreRegistryPlugin } from '@hungpvq/shared-store';
import { installMapApp } from '@hungpvq/vue-map-dataset';
import App from './App.vue';

const app = createApp(App);
app.use(createStoreRegistryPlugin());
installMapApp(app);
app.mount('#app');

React ​

ts
import { installMapApp } from '@hungpvq/react-map-dataset';

installMapApp();

Features ​

  • Dataset tree: source, layer, list UI, identify, highlight, data management
  • Layer list: show/hide, opacity, delete, drag-and-drop groups
  • Reorder in the list: Move up / Move down
  • Add to group from the layer context menu
  • Custom menus: extra / bottom / prebottom / context menu
  • Menu hidden / disabled from layer data or external state (Pinia, React context)
  • Custom context-menu UI via setComponentMenuKey
  • Identify, style editor, legends
  • Export GeoJSON layers as GeoJSON / KML / CSV / Shapefile
  • Attribute table for GeoJSON feature properties (click a row to zoom / highlight)

Quick start (Vue) ​

vue
<template>
  <Map
    :mapId="mapId"
    @mapLoaded="onMapLoaded"
  >
    <LayerControl
      position="top-left"
      show
    >
      <template #endList="{ mapId }">
        <BaseMapCard :mapId="mapId" />
      </template>
    </LayerControl>
    <IdentifyControl position="top-right" />
    <ComponentManagementControl />
  </Map>
</template>

<script setup lang="ts">
import type { MapSimple } from '@hungpvq/map-core';
import { getUUIDv4 } from '@hungpvq/shared';
import { Map, BaseMapCard } from '@hungpvq/vue-map-core';
import { LayerControl, IdentifyControl, ComponentManagementControl, useMapDataset, useMapHighlight } from '@hungpvq/vue-map-dataset';
import { createRootDataset, createDatasetPartListViewUiComponentBuilder, createMultiMapboxLayerComponent } from '@hungpvq/map-dataset';
import { createDatasetPartGeojsonSourceComponent } from '@hungpvq/map-dataset/geojson';
import { createHighlightPart } from '@hungpvq/map-dataset/highlight';
import { LayerSimpleMapboxBuild } from '@hungpvq/map-dataset/style';
import { onUnmounted, ref } from 'vue';
import '@hungpvq/map-core/style.css';
import '@hungpvq/map-dataset/style.css';
import '@hungpvq/vue-map-core/style.css';
import '@hungpvq/vue-map-dataset/style.css';
import '@hungpvq/vue-draggable/style.css';

const mapId = ref(getUUIDv4());
const hl = useMapHighlight(mapId.value);
const unbind = hl.bindPointer({ click: false, hover: true });
onUnmounted(() => unbind());

function onMapLoaded(map: MapSimple) {
  const { addDataset } = useMapDataset(map.id);

  const dataset = createRootDataset('Sample');
  const list = createDatasetPartListViewUiComponentBuilder('Hanoi').setColor('#ff6b6b').build();
  const source = createDatasetPartGeojsonSourceComponent('source', {
    type: 'FeatureCollection',
    features: [
      {
        type: 'Feature',
        properties: { name: 'Hanoi' },
        geometry: { type: 'Point', coordinates: [105.8342, 21.0285] },
      },
    ],
  });
  const layer = createMultiMapboxLayerComponent('layer', [new LayerSimpleMapboxBuild().setStyleType('point').setColor(list.color).build()]);

  dataset.add(source);
  dataset.add(list);
  dataset.add(layer);
  dataset.add(createHighlightPart());
  addDataset(dataset);
}
</script>

Quick start (React) ​

tsx
import type { MapSimple } from '@hungpvq/map-core';
import { Map, BaseMapCard } from '@hungpvq/react-map-core';
import { LayerControl, IdentifyControl, ComponentManagementControl, useMapDataset, useMapHighlight } from '@hungpvq/react-map-dataset';
import { createRootDataset, createDatasetPartListViewUiComponentBuilder } from '@hungpvq/map-dataset';
import { createHighlightPart } from '@hungpvq/map-dataset/highlight';
import { useEffect } from 'react';
import '@hungpvq/map-core/style.css';
import '@hungpvq/map-dataset/style.css';
import '@hungpvq/react-map-core/style.css';
import '@hungpvq/react-map-dataset/style.css';
import '@hungpvq/react-draggable/style.css';

function Page({ mapId }: { mapId: string }) {
  const hl = useMapHighlight(mapId);
  useEffect(() => {
    const unbind = hl.bindPointer({ click: false, hover: true });
    return unbind;
  }, [hl]);

  function onMapLoaded(map: MapSimple) {
    const { addDataset } = useMapDataset(map.id);
    const dataset = createRootDataset('Sample');
    dataset.add(createDatasetPartListViewUiComponentBuilder('Layer').build());
    dataset.add(createHighlightPart());
    addDataset(dataset);
  }

  return (
    <Map onMapLoaded={onMapLoaded}>
      <LayerControl
        position="top-left"
        show
        endList={({ mapId }) => <BaseMapCard mapId={mapId} />}
      />
      <IdentifyControl position="top-right" />
      <ComponentManagementControl />
    </Map>
  );
}

Shorthand for a full GeoJSON layer: createGeoJsonDataset.

Create-layer parses GIS and reprojects CRS in a Web Worker. Vite / native ESM: zero config. Webpack / CDN / static: configureGisWorker({ url }) + @hungpvq/map-dataset/geojson-worker. This monorepo needs worker.format: 'es' (+ nxViteTsPaths on worker.plugins). Install optional GIS peers when using CreateControl — see CreateControl.

Domain src/extra vs adapter extra ​

LocationRolePublished?
libs/map-core/map-dataset/src/extra/Framework-agnostic helpers (field builders, locales, …) that feed domain entriesNo — not a package export; use @hungpvq/map-dataset / @hungpvq/map-dataset/<domain>
libs/vue|react/map-dataset/src/extra/Framework UI for menu actions / condition context (ToggleShow, DatasetMenuButton, …)Internal only; surfaces via adapter root named exports

Import builders, identify, menu protocol, create-control GIS APIs from @hungpvq/map-dataset/... — never from adapter extra/ barrels. Do not reintroduce adapter builder / model / services re-exports of domain code.

Layer list drag types (LayerListItem, LayerListTreeNode, LayerListGroupTree, ListViewGroupRef, IListViewUI, IGroupListViewUI) are Stable type exports on @hungpvq/map-dataset — see List UI and LayerControl.

Next ​

  • GIS worker — npm app vs Nx monorepo setup so parse + CRS stay off the main thread
  • Create a dataset — tree, source, layer, list UI
  • Components — LayerControl, Identify, Highlight, DatasetControl, props / events
  • Menus — createMenuBuilder, setHidden / setDisabled, custom menu component
  • Events — toggleShow / changeOpacity on list nodes
  • Attribute table — feature properties, click to zoom
  • Export — GeoJSON / KML / CSV / Shapefile