Create Control
Dialog to add a GeoJSON / raster / vector dataset from the UI. LayerControl opens this when Create layer is clicked — you usually do not mount it yourself.
GeoJSON / KML / GPX / Shapefile file read, parse, and CRS reproject run in a Web Worker. Configure Vite worker.format: 'es' (and nxViteTsPaths on worker.plugins in this Nx workspace) or large files fall back to the main thread and can freeze the UI. Mount WorkerControl to watch progress and errors.
Optional GIS peers
@hungpvq/map-dataset does not bundle GIS format parsers. Install them in the app when using CreateControl / file import:
npm i shpjs papaparse jszip topojson-client @tmcw/togeojson @xmldom/xmldom| Format | Peer(s) |
|---|---|
| GeoJSON / GeoJSONL / WKT | none (parseGisText sync) |
| CSV | papaparse |
| KML / GPX | @tmcw/togeojson, @xmldom/xmldom |
| TopoJSON | topojson-client |
| ZIP / KMZ | jszip (+ KML peers for KMZ) |
| Shapefile | shpjs |
Programmatic parse: parseGisTextAsync / loadGis*Async from @hungpvq/map-dataset/create-control — see GIS worker.
UX notes
- The dialog keeps a small draft in
sessionStorage(type, name, CRS) vialoadCreateControlDraft/saveCreateControlDraft. - If loaded file CRS differs from selected CRS, UI warns that data will be reprojected.
- Multi-file upload accepts one GIS file, or one shapefile set (
.shp+ sidecars /.zip). - Folder drop: dropping a directory walks entries (
collectFilesFromDataTransfer) and keeps GIS extensions only. - OS paste: on the File tab, paste clipboard files as upload, or paste text to switch to Raw and parse (
readClipboardGisPaste/parseCreateControlPastedText).
Implementation (adapters)
Create / validate / defaults live on core LayerHelper from @hungpvq/map-dataset/create-control. Vue and React adapters only supply framework form UI (geojson upload, raster URL, settings) as leaf modules — there is no adapter helper/ wrapper or config/index barrel.
| Import | |
|---|---|
| Protocol | LayerHelper, LAYER_TYPES, parse/upload helpers from @hungpvq/map-dataset/create-control |
| Vue forms | CreateControl/config/*.vue leaf SFCs |
| React forms | CreateControl/config/CreateConfigForm.tsx (+ createControlComponentKey) |
Props
| Prop | Description | Type | Required | Default Value |
|---|---|---|---|---|
mapId | string | false | -- | |
dragId | string | false | -- | |
btnWidth | number | false | 40 | |
controlOrder | CSS flex order for the standalone button | number | false | 0 |
position | 'top-left', 'top-right', 'bottom-left', 'bottom-right' | false | 'bottom-right' | |
controlLayout | 'standalone' (corner), 'toolbar' (always in toolbar), 'button' (always corner; not auto-promoted on mobile) | 'standalone' | 'toolbar' | 'button' | false | 'standalone' |
controlVisible | boolean | false | true |
Map also accepts buttonInMobile ('button' | 'toolbar' | 'menu', default 'button'). On viewports ≤640px:
'button'— leave corner buttons unchanged'toolbar'— move declared control buttons into a singleToolbarControlhost (exceptcontrolLayout="button"). Mount oneToolbarControlin the map slot'menu'— hide per-control corner buttons; fan out intact clusters bypositioninto corner stacks with outside-in More. Mount oneToolbarControl.
See ToolbarControl.
| Prop | Type | Required | Effect |
|---|---|---|---|
show | boolean | yes | Open the dialog |
Events
| Name | Payload | Framework |
|---|---|---|
update:show | boolean | Vue (v-model:show) |
onShowChange | (show: boolean) => void | React |
Vue
<script setup lang="ts">
import { ref } from 'vue';
import { Map } from '@hungpvq/vue-map-core';
import { CreateControl } from '@hungpvq/vue-map-dataset';
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 open = ref(false);
</script>
<template>
<Map>
<CreateControl v-model:show="open" />
</Map>
</template>React
const [open, setOpen] = useState(false);
<CreateControl show={open} onShowChange={setOpen} />