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

Stable API (v1)

Allowlist of symbols and protocols we treat as Stable for SemVer on 1.x.

Root and domain barrels use explicit named exports (no public export *). Root src/index.ts imports leaves directly (no internal-barrel). Runtime surface is locked by public-api.spec.ts (root and each domain subpath).

All current root and subpath runtime exports are Stable or Experimental. For Vue/React map-core, Experimental field/UI helpers live on ./fields (not the root). Other packages may list Experimental symbols in *_EXPERIMENTAL_RUNTIME_EXPORTS on a published barrel (may change in a minor). Removing an Experimental export from a published barrel is still a major.

Runtime lock: each entry asserts Object.keys(import * as api from '<entry>') equals its Stable ∪ Experimental allowlist in public-api.spec.ts (type-only exports are erased at runtime and omitted from the lock). Root and subpaths may export first-party types via explicit export type { … } — do not re-export types that already live in third-party packages (geojson, maplibre-gl, …); import those from the original package.

PackageSpec
@hungpvq/map-corelibs/map-core/core/src/public-api.spec.ts (root + subpaths)
@hungpvq/map-datasetlibs/map-core/map-dataset/src/public-api.spec.ts
@hungpvq/map-drawlibs/map-core/map-draw/src/public-api.spec.ts
@hungpvq/vue-map-corelibs/vue/map-core/src/public-api.spec.ts
@hungpvq/vue-map-datasetlibs/vue/map-dataset/src/public-api.spec.ts
@hungpvq/vue-map-drawlibs/vue/map-draw/src/public-api.spec.ts
@hungpvq/vue-map-devtoolslibs/vue/map-devtools/src/public-api.spec.ts
@hungpvq/react-map-corelibs/react/map-core/src/public-api.spec.ts
@hungpvq/react-map-datasetlibs/react/map-dataset/src/public-api.spec.ts
@hungpvq/react-map-drawlibs/react/map-draw/src/public-api.spec.ts
@hungpvq/react-map-devtoolslibs/react/map-devtools/src/public-api.spec.ts
  • Adding a runtime export → named export in the entry barrel + Stable (or Experimental) list in that package’s public-api.spec.ts + this page when documenting the area.
  • Removing a root or subpath runtime export is a major. Adding a new subpath while keeping root is usually a minor.

Canonical imports

Prefer domain subpaths for feature APIs; use the root barrel for platform/runtime symbols (getMap, MapStoreManager, UniversalRegistry, …):

ts
import { getMap, subscribeMapReady } from '@hungpvq/map-core';
import { createMeasurementSession } from '@hungpvq/map-core/measurement';
import { createIdentifySession } from '@hungpvq/map-dataset/identify';
import { createDrawSession } from '@hungpvq/map-draw';

Adapters (@hungpvq/vue-* / @hungpvq/react-*) must not re-export core protocol — import UI from adapters, protocol from core/dataset/draw.

Export removal checklist (do not skip)

Before removing a published runtime export (Stable or Experimental on a barrel):

  1. Classify Stable vs Experimental; confirm it is not a control/menu id, store key, CSS token, or protocol string.
  2. Grep first-party map packages, demos, and docs. Tag: in-use-first-party | docs-only | looks-unused-internal | unknown-external.
  3. SemVer major for any remove from a published barrel (Experimental included).
  4. Update together: barrel index.ts, *_STABLE_* / *_EXPERIMENTAL_* in public-api.spec.ts, this page.
  5. Prefer @deprecated alias for ≥1 minor when unknown-external or docs still reference the symbol.
  6. Forbidden: delete an export only because “no monorepo import” without steps 3–4.

Export inventory (hardening pass)

SymbolPackageTagAction
logger (root)@hungpvq/map-drawin-use-first-party (vue/react map-draw stores)Keep Experimental
brightColor, generateInspectStyle, renderPopup, …@hungpvq/map-drawin-use-first-partyKeep (InspectControl)
emptyDraftListSnapshot@hungpvq/map-drawin-use-first-partyKeep (useDrawDrafts)
cycleMapThemeMode@hungpvq/map-core/themein-use-first-party / docsKeep
Inspect GIS helpers (getSourcesFromMap, …)@hungpvq/map-drawunknown-externalKeep (public Inspect extension surface)

Related: SemVer checklist · Minimal starter · Peers and bundle · Map store · Error handling · UniversalRegistry controls · components

MapLibre-first

MapSimple is the Stable MapLibre map type. Platform APIs (getMap, subscribeMapReady, control helpers) take or return that instance — we do not hide MapLibre behind a custom engine facade. Apps may call MapLibre APIs on the instance directly.

Thin-host controls

Dual Vue/React controls share pure orchestration in @hungpvq/map-core (root controls/* or domain subpaths), @hungpvq/map-dataset, or @hungpvq/map-draw. Adapters stay thin hosts (useMap + register/toolbar + SFC/JSX). Prefer subscribeMapReady when waiting for the map with cancel-on-unmount. Do not merge adapter packages or put framework UI into core.

Pure owners to copy (non-exhaustive):

AreaCore helper
Shell controlsroot controls/* (captureHomeView, goHome, navigation / globe / goto / setting / mouse-coordinates / info)
Identify sessioncreateIdentifySession / createIdentifyControlModel (@hungpvq/map-dataset/identify) — session owns runIdentifyMulti + input modes; adapters are thin hosts
MeasurementcreateMeasurementSession / createMeasurementMapView* (./measurement)
Print advancedcreatePrintAdvancedSession (./print)
Toolbar / CRScreateLiveToolbarStrategy (./toolbar), normalizeDisplayEpsgs (./crs)
Draw / inspectcreateDrawSession, draw-control-helpers, InspectController (@hungpvq/map-draw)
MiscGeoLocateSession, createCopyFeedback, theme / fullscreen helpers

Hosts own UI, registry actions, and framework lifecycle only.

Registry architecture

  • Host: UniversalRegistry in @hungpvq/map-core — methods, menu handlers, components, control handles (one resolve path: map-scoped then global). Storage: @hungpvq/shared-store keys map:registry:global / map:registry:maps / map:registry:controls (no class-static Map singletons).
  • Adapters: @hungpvq/vue-map-core / @hungpvq/react-map-core extend that class and only add typed registerComponent / getComponent (Vue also markRaw).
  • Prefer UniversalRegistry / runMapControlAction from @hungpvq/map-core in framework-agnostic code (map-dataset, context menu).

@hungpvq/map-core package entries

EntryRole
.Platform shell: store/getMap/subscribeMapReady, registry, errors, mitt, shared GIS utils, shell locales, host WorkerMonitor, thin-host control helpers (captureHomeView, goHome, navigation/globe/goto/setting/mouse-coordinates/info)
./style.cssShared map CSS
./workerCSS/DOM-free worker helpers
./basemapBasemap adapters, services, INIT_BASEMAPS, BasemapError
./crsCRS catalog, store defaults, CRS_CONTROL_LOCALE, createCoordinateFormatter, normalizeDisplayEpsgs
./devtoolsDevtools store core, BufferingLogAdapter, overlay DOM helpers, installDevtoolsCore (Experimental)
./eventEventManager, event models, bbox ranger, createEventActionSync, groupEventsByMapType / isEventActive
./imageMap image load/store helpers
./legendLegendService, MapLegend, buildLayerLegendElements, paint helpers
./measurementMeasurementService, measure modes, format helpers, resolveMeasurementModeToggle / resolveMeasurementToolbarStatus, createMeasurementSession, createMeasurementMapView / createMeasurementMapViewLayers, draftCoordinatesToFeature / buildMeasurementGeojsonDownload
./menuMap context menu builders / actions
./printPrintService, export helpers (exportMapbox*, printMapToFile, clipCanvasRegion, waitMapIdleAndTiles), createPrintAdvancedSession / DEFAULT_PRINT_ADVANCED_SETTING
./themeTheme bootstrap / resolve / MAP_THEME_*, MAP_THEME_CONTRAST_CLASS, subscribePrefersContrastMore; optional per-map helpers resolveMapThemeElement / applyMapThemeClassToElement / applyMapThemeForMap (document theme remains default)
./toolbarToolbar strategies / store APIs, createLiveToolbarStrategy

Root (.) highlights

Runtime allowlist: MAP_CORE_STABLE_RUNTIME_EXPORTS in public-api.spec.ts (~80 symbols).

AreaStable surface
Map accessgetMapMapSimple | undefined, subscribeMapReady → unsubscribe, registerMapAccessor (+ { hostId }, returns unregister), registerMapReadySubscriber, registerMapStoreCleanup, MAP_PLATFORM_HOST, listMapPlatformHosts, MAP_PLATFORM_REGISTRY_METHOD (reserved UniversalRegistry global keys), MapStoreManager, MAP_STORE_KEY, hasMapInstancemap-store. Theme bootstrap is process-global (one html theme); platform accessors are multi-host.
Thin-host control helpersHome (captureHomeView / goHome), navigation (zoomIn / zoomOut / resetBearing / attachRotateListener / …), globe (toggleGlobeProjection / …), goto / setting / mouse-coordinates / info attach helpers
RegistryUniversalRegistry, runMapControlAction, buildMapControlHandle, MapControlHandle, REGISTRY_* (incl. REGISTRY_GLOBAL_STORE_KEY / REGISTRY_MAPS_STORE_KEY / REGISTRY_CONTROLS_STORE_KEY), filterMapControls (RegistryFn = (...args: unknown[]) => unknown) — backed by @hungpvq/shared-store
Init / errorsMapInitializer, MapError family, errorHandler / MapErrorHandlererror-handling
A11ybindMapKeyboardShortcuts, closeTopOpenMapControl, focusMapLayerSearch, MAP_LAYER_SEARCH_SELECTOR, mapLayerSearchSelector
Shared GISfitBounds (sidebar left/right padding), bboxFromGeojson, isValidBbox, reprojectGeojson, reprojectGeojsonToWgs84, coordinate/DMS helpers (parseCoordinateText, latDMS/lngDMS), color/logHelper, map-info (copyImageDataUrl)
Pointer / touchgetMapPointerProfile, bindMapLongPress
FullscreenrequestElementFullscreen, exitDocumentFullscreen, toggleElementFullscreen, subscribeFullscreenChange, getFullscreenElement, isDocumentFullscreen, isMapRootFullscreen, resolveMapFullscreenTarget
Control layoutresolveControlLayout, ResolvedControlLayout (standalone / toolbar / menu), ControlLayout (standalone / toolbar / button), ButtonInMobile / BUTTON_IN_MOBILE_VALUES (button / toolbar / menu). Map buttonInMobile on viewports ≤640px: button leaves corner controls unchanged; toolbar promotes into one ToolbarControl host except controlLayout="button"; menu fans out by position into corner stacks with outside-in overflow; bottom half budgets menu + same-edge controlLayout="button" chrome (see ToolbarControl). Mount ToolbarControl in the map slot for toolbar and menu.
Button chrome helpersMAP_BUTTON_VARIANTS / MAP_BUTTON_SIZES / MAP_BUTTON_SIZE_PX, resolveMapButtonSizePx, mapButtonVariantClass, mapButtonSizeClass, … (used by Vue/React MapControlButton)
ModuleContainer helpersmoduleCornerHostSelector / moduleDraggableHostSelector (+ id variants), buildModuleBindPosition, moduleBtnContainerClassName, isModuleCornerChromeVisible, queryModuleHostElement (Vue/React ModuleContainer)
Worker hostWorkerMonitor (+ abortTask), connectWorkerMonitor, abortWorkerMonitorTask, createWorkerMonitorAbortMessage, runMonitoredTask, workerHasHistory / anyWorkerHasHistory / countBusyWorkers, … (in-worker: ./worker)
Shell localesMAP_ACTION_*, Home/Goto/Globe/Info/Setting, WORKER_*, REGISTRY_*, LANGUAGE_*, MAP_CORE_LOCALE_EN, MAP_CORE_LOCALE_VI
Lang APIregisterLocale / registerLocaleFlat / setLanguage / loadLocale / MAP_BUILTIN_LANGUAGES / flat helpers (via createMapLocaleApi + root exports)
TypesMapSimple, WithMapPropType, ControlLayout, MapControlHandle, …

Domain APIs (theme, basemap, measurement, …) are not on the root barrel — import from the matching subpath.

Toolbar helpers on @hungpvq/map-core/toolbar: mdiIcon, mdiButtonState, compassIcon, createLiveToolbarStrategy; overflow helpers groupToolbarButtons, splitToolbarOverflow, splitToolbarOverflowKeepGroups (prefer 'start'|'end', toolbarGroupHeightCost), maxVisibleToolbarButtons, maxVisibleButtonsInStackHeight, cornerVerticalMenuBudgetsPx, measureCornerStandaloneReserved, measureCornerMenuUsedPx, elementOuterSize, toolbarAvailableWidth, toolbarGroupHeightCost, toolbarOverflowPanelClassName, planToolbarLayout, TOOLBAR_EDGE_INSET_PX, TOOLBAR_STACK_GAP_PX, BUTTON_GROUP_OVERFLOW_FRACTION, TOOLBAR_CONTROL_LOCALE.

@hungpvq/map-dataset

Breaking major: domain symbols moved off the root onto named subpaths. Root no longer re-exports builders, identify, menu, style, create-control, geo-export, or attribute-table APIs. Full runtime allowlists: public-api.spec.ts (root + each subpath).

EntryStable surface (highlights)
.DatasetService, MAP_DATASET_STORE_KEY (scoped store bag key for adapters), tree/createRootDataset/createGroupDataset, convertListToTree / convertTreeToList / mergeEmptyGroups / createDefaultGroup / isGroupNode, layer-list types (LayerListItem / LayerListTreeNode / LayerListGroupTree / ListViewGroupRef / IListViewUI / IGroupListViewUI), getLayerControlTitleMenuState / registerAddGeojsonHereForMap, generic parts, layer/dataset locales, createDataManagement / isDataManagementView, warnIfDatasetRegistryMissing / resetDatasetRegistryWarnFlag, IDataset (+ shared protocol types). Experimental: upsertDatasetComponent / removeDatasetComponent, logger / loggerIdentify / loggerHighlight
./highlightcreateHighlightPart, getHighlightController / destroyHighlightController / bindHighlightPickDatasets, cascade defaults (DEFAULT_HIGHLIGHT_*); types HighlightPartOptions, HighlightController, IHighlightPart, … (cascade/query/resolve + paint-layer helpers are package-internal)
./attribute-tableATTRIBUTE_TABLE_*, createAttributeTableController / stores (+ optional invalidate), createDatasetPartAttributeTable (columns / ui), createMenuItemAttributeTable, column/sort helpers, resolveAttributeTable*Option, AttributeTableProps / view / toolbar / pager / grid props
./geojsoncreateGeoJsonDataset, createGeojsonHereDataset, geojson source/parse/worker (configureGisWorker, resolveGisWorkerUrl, terminateGeojsonWorker, …), GEOJSON_STYLE_AUTO
./data-managementcreateDataManagement, createLocalStore, createHttpStore, createDataManager, toRecord / toFeature / toFeatureCollection, isDataManagementView
./rastercreateRasterUrlDataset, raster source part, RASTER_XYZ_SAMPLES
./vector-tilecreateDatasetPartVectorTileComponent, VECTOR_SAMPLES
./identifyIDENTIFY_*, createDatasetPartIdentify*, handleMultiIdentify*, runIdentifyMulti / runIdentifyShowFirst (+ layer-filter / result-panel helpers), createIdentifySession / createIdentifyControlModel / scoped-session helpers, scope helpers; types IIdentifyView*, IdentifyFeatureRow, IdentifyMultiResult (canonical result row shape; former IdentifySingleResult / IdentifyResult aliases removed)
./menuLIST_VIEW_MENU_*, createMenu* (list-view / dataset builders), createMapContextMenuBuilder, createLegend / createMultiLegend, handleMenuAction*, menu part builders; MenuItem* / MenuAction / MenuItemProps payload P defaults to unknown (types-only tightening vs former any)
./styleLayerSimpleMapboxBuild, LayerRasterMapboxBuild, *_CONFIG, TABS, CONFIG_TAB_BASE / buildConfigTabs, applyStyleTabValue / applyStyleZoom, STYLE_CONTROL_LOCALE
./create-controlCREATE_CONTROL_*, LAYER_TYPES / LayerHelper / Config*Helper / createLayerFormHelper, assertCreateControlFileSize / formatCreateControlBytes / CREATE_CONTROL_MAX_FILE_BYTES, parseGis* / loadGis* / upload helpers (looksCompleteGis, parseCreateControlUploadedFiles, collectFilesFromDataTransfer, readClipboardGisPaste, …), getCreateControlSamples — GIS format peers (shpjs, papaparse, @tmcw/togeojson, jszip, topojson-client, @xmldom/xmldom) are optional; install when using CreateControl / file parse — peers-and-bundle
./geo-exportGEO_EXPORT_* / GEO_EXPORT_COMPONENT_KEY (SoT; LIST_VIEW_MENU_COMPONENT_KEY.exportGeo* aliases), createGeoExportController, onExport + GeoExportContext (+ AbortSignal), uiMode modal|menu|click, formComponent / loadingComponent, resolveGeoExportUiSlot, resolveExportCollection, active-source bridge, createMenuItemExportGeo, createDatasetPartGeoExport, openGeoExportModalFromAttributeTable / runGeoExportClickFromAttributeTable / runGeoExportFormatFromAttributeTable, resolveGeoExportCrs, downloadBlob / sanitizeExportFilename, getDatasetFeatureCollection / hasGeojsonExportData, ExportGeoComponentAttrs (exportHandler)
./vitemapDatasetGisWorker() — Vite optimizeDeps + maplibre named-export shim for published package consumers
./geojson-workerStatic single-file GIS worker (assets/geojson.worker.js) for Webpack / CDN / static hosts
./style.css / ./assets/*package CSS and static assets

LIST_VIEW_MENU_ID / LIST_VIEW_MENU_COMPONENT_KEY string values remain SemVer-stable (import from @hungpvq/map-dataset/menu).

Map context menu ids, built-in item builders, and types (MAP_CONTEXT_MENU_ID, createMapMenuBuilder, createDefaultMapContextMenuItems, MapContextMenuTarget, …) import from @hungpvq/map-core/menu — not re-exported from @hungpvq/map-dataset/menu.

@hungpvq/vue-map-core / @hungpvq/react-map-core

Root barrels are Stable only (see each public-api.spec.ts). Field / lightweight UI helpers live on ./fields (Experimental; may change in a minor).

Breaking (major): importing former Experimental symbols (Input*, MapCard, MapErrorToast, …) from the package root fails — use @hungpvq/vue-map-core/fields / @hungpvq/react-map-core/fields. Former BaseButton is removed — use Stable root MapControlButton.

Shared root highlights:

AreaStable surface
ShellMap container, @map-loaded / onMapLoaded (and destroy equivalents); optional keyboardShortcuts (default true); mounts MapErrorToast internally from ./fields
HooksuseMap, useMapInstance, useShow, useRegisterMapControl, useUniversalRegistry
Store helperscreateMapScopedStore, destroyMapScopedStore, getStore, addStore (not getMap) — map-store
RegistryFramework UniversalRegistry, RegistryItem
ControlsModuleContainer controls + control ids / action types (registry-controls); both export ActionControl; action UI uses MapControlButton (variant: icon | plain | text | tonal | outlined | filled; size: small | medium | large | number px — see css-variables) / MapCommonButton / MapCopyButton (clipboard + icon feedback; see css-variables)
TypesFirst-party: WithShowProps; prefer WithMapPropType / MapSimple from @hungpvq/map-core

Framework idioms (Stable): Vue makeShowProps / withMapProps; React MapContext* / MapGlobalStoreProvider / ReactMapStoreAdapter / useBreakpoints / …

Package entries: . + ./style.css + ./fields.

@hungpvq/vue-map-core/fields / @hungpvq/react-map-core/fields

SymbolNotes
BaseCollapse, CollapseCollapse panel — canonical BaseCollapse; Collapse alias
InputCheckbox, InputChoose, InputColorPicker, InputCrs, InputFile, InputSelect, InputSlider, InputText, InputTextArea, InputTextareaForm helpers — canonical InputTextArea; InputTextarea alias
MapButtonMap-control chrome (variant / size same as MapControlButton; prefer Stable root MapControlButton in apps)
MapCard, MapIcon, MapImageLightweight map UI primitives
MapErrorToastListens to errorHandler; “Open errors” dispatches hungpvq:map-open-devtools-errors
DragDropFileVue + React /fields (DOM-only drop zone)
ts
import { MapControlButton, MapCopyButton } from '@hungpvq/vue-map-core';
import { InputText } from '@hungpvq/vue-map-core/fields';
// or `@hungpvq/react-map-core` / `.../fields`

MapControlButton: variant + size (small | medium | large | px). Prefer size="small" in dense layer rows; default medium matches draggable header chrome (32px).

MapCopyButton: Stable root copy action — wraps MapControlButton + core createCopyFeedback. On success, icon mdiContentCopymdiCheck and title → copiedTitle for ~1.5s (COPY_FEEDBACK_MS). No toast. Prefer this for every text-copy chrome button (InfoControl rows, LayerDetail cells, measurement CRS values, …).

Prefer canonical names in new code (MapControlButton, MapCopyButton, BaseCollapse, InputTextArea). Authoritative lock: root Stable + *_FIELDS_RUNTIME_EXPORTS in each adapter public-api.spec.ts.

Parity lock: libs/map-core/core/src/dual/parity-catalog.ts + vue-react-parity.spec.ts (shared control ids + shared Stable root + shared /fields Experimental names).

Dataset / draw Experimental allowlists are empty / reserved. @hungpvq/map-core Experimental root: GeoLocateSession (Mapbox-style geolocate engine used by Vue/React GeoLocateControl; may change in a minor); DEVTOOLS_CONTROL + type DevtoolsMode (shared devtools control id / panel mode — re-exported by @hungpvq/*-map-devtools; may change in a minor). @hungpvq/map-core/devtools also exports Experimental formatDevtoolsLogEntryForCopy for LogViewer clipboard formatting.

Adapters do not re-export @hungpvq/map-core protocol (getMap, errorHandler, …). There is no adapter handleError — apps use errorHandler from @hungpvq/map-core.

@hungpvq/vue-map-dataset / @hungpvq/react-map-dataset

AreaStable surface
BootstrapinstallMapApp, createMapAppPlugin (Vue), createDatasetRegistryPlugin()
HooksuseMapDataset, useMapHighlight
UILayerControl, IdentifyControl, IdentifyResultControl, IdentifyShowFirstControl, HighlightPointer, AttributeTable (+ AttributeTableView / toolbar / grid / pager), StyleControl, CreateControl, ComponentManagementControl, DatasetDetail, LayerMenuDefaultHandle, …
Core boundaryBuilders/services/types from @hungpvq/map-dataset (including createLegend / createMultiLegend from @hungpvq/map-dataset/menu)

Menu condition: Vue provideMenuConditionContext / MENU_CONDITION_CONTEXT_KEY; React MenuConditionProvider. React also has imperative getMapDatasetStore / notifyMapDatasetStore.

@hungpvq/map-draw

AreaStable surface
ServiceDrawService
ProtocolDrawingType, DrawingTypeName, MAP_DRAW_EVENT, MapDrawOption, isDraftOption
Engine mountMapDraw, StaticMode, DRAW_MODES, getDrawStyles
Styles / query / idsgetFeatureByMap, getFirstFeatureByMap, getFeatureId, sameFeature
LocalesDRAW_CONTROL_LOCALE, INSPECT_CONTROL_LOCALE
Experimental (@hungpvq/map-draw)createDrawSession (prepareSave / finishCancel / redrawNonDraft, …), draw-control-helpers (handleDrawMapClick, …), logger

Inspect helpers (brightColor, generateInspectStyle, …) remain public; inventory tagged in-use-first-party via InspectControl.

@hungpvq/vue-map-draw / @hungpvq/react-map-draw

AreaStable surface
ShellDrawControl, InspectControl (shared InspectController), useMapDraw, useConfigDrawControl, useMapDrawStore
Control idsmapDrawDraftList, mapInspectControl
Core boundaryProtocol / isDraftOption / locales from @hungpvq/map-draw — adapters do not re-export them

Consumer docs: libs/map-core/map-draw/docs/map/draw/.

@hungpvq/vue-map-devtools / @hungpvq/react-map-devtools

AreaStable surface
Bootstrap (both)installDevtools, uninstallDevtools
PanelDevtools (optional mode: overlay | control; containerId for overlay mobile sheet)
Map controlDevtoolsControl / DEVTOOLS_CONTROL.id (mapDevtools) — popup via DraggableItemPopup
Open helpersopenMapDevtoolsErrors, setDevtoolOpen, toggleDevtoolOpen, …
Store helpers (both)DevtoolLogAdapter, devtoolLogAdapter, devtoolState, getDevtoolState, useDevtoolState, subscribeDevtoolState, toggleDevtoolOpen, setDevtoolActiveTab, clearDevtoolLogs, clearDevtoolErrors
Docsdevtools.md

openMapDevtoolsErrors opens the panel on the Errors tab. MapErrorToast (from @hungpvq/*-map-core/fields) dispatches hungpvq:map-open-devtools-errors; stores listen and call openMapDevtoolsErrors.

Adapters do not re-export @hungpvq/map-core (errorHandler from map-core). See Error handling.

CSS

Documented --map-* tokens and theme classes (map-theme-*) in CSS variables. style.css package entries are stable import paths.

Experimental slot

Vue/React @hungpvq/*-map-core publish field/UI helpers on ./fields (not the root barrel) — see vue/react map-core. They may change in a minor. Root *_EXPERIMENTAL_RUNTIME_EXPORTS for adapters are empty/reserved. Removing an Experimental export from a published barrel (including ./fields) remains a major. @hungpvq/map-core Experimental: GeoLocateSession, DEVTOOLS_CONTROL (+ type DevtoolsMode). Other map packages keep empty/reserved experimental lists.

Enforcing the allowlist

  1. Edit src/index.ts with named exports only (no public export *). Prefer export { X } from './feature/leaf'. Export first-party types with explicit export type { … } — never export type *, and never re-export third-party library types.
  2. Put new implementation symbols in feature modules; only promote to root index.ts + allowlist when intentional.
  3. Update the matching public-api.spec.ts allowlist arrays (runtime symbols only).
  4. Update this page when changing Stable.
  5. Do not hand-edit package CHANGELOG.md unless asked — use release tooling.